diff --git a/assets/database/db.json b/assets/database/db.json index a3553e66d2..89c7f15e81 100644 --- a/assets/database/db.json +++ b/assets/database/db.json @@ -10671,8 +10671,8 @@ {"effectId":929,"itemId":16217,"spellId":20069,"name":"Enchant Shield - Greater Stamina","type":13,"enchantType":2,"stats":[0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, {"effectId":930,"spellId":13947,"name":"Enchant Gloves - Riding Skill","type":7,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":2}, {"effectId":931,"spellId":13948,"name":"Enchant Gloves - Minor Haste","type":7,"stats":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"quality":1}, -{"effectId":943,"spellId":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":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":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}, @@ -15489,6 +15489,7 @@ {"id":453696,"name":"Engrave Ring - Fire Specialization","icon":"inv_jewelry_ring_31","requiresLevel":1}, {"id":453697,"name":"Engrave Ring - Frost Specialization","icon":"inv_jewelry_ring_31","requiresLevel":1}, {"id":457437,"name":"Vanish","icon":"ability_vanish","requiresLevel":1,"hasBuff":true}, +{"id":457544,"name":"S03 - Item - T1 - Shaman - Tank 6P Bonus","icon":"ability_ghoulfrenzy","requiresLevel":1}, {"id":458436,"name":"Wyvern Strike","icon":"inv_spear_02","requiresLevel":1,"hasBuff":true}, {"id":458481,"name":"Wyvern Strike","icon":"inv_spear_02","requiresLevel":1,"hasBuff":true}, {"id":458482,"name":"Wyvern Strike","icon":"inv_spear_02","requiresLevel":1,"hasBuff":true}, diff --git a/assets/db_inputs/wowhead_spell_tooltips.csv b/assets/db_inputs/wowhead_spell_tooltips.csv index d2c425aa49..59568edee8 100644 --- a/assets/db_inputs/wowhead_spell_tooltips.csv +++ b/assets/db_inputs/wowhead_spell_tooltips.csv @@ -21581,6 +21581,7 @@ 453696,{"name":"Engrave Ring - Fire Specialization","icon":"inv_jewelry_ring_31","tooltip":"
Engrave Ring - Fire Specialization
3 sec cast
Requires level 1
Requires Ring
","tooltip2":"","buff":"","quality":-1,"spells":{},"buffspells":{},"completion_category":7} 453697,{"name":"Engrave Ring - Frost Specialization","icon":"inv_jewelry_ring_31","tooltip":"
Engrave Ring - Frost Specialization
3 sec cast
Requires level 1
Requires Ring
","tooltip2":"","buff":"","quality":-1,"spells":{},"buffspells":{},"completion_category":7} 457437,{"name":"Vanish","icon":"ability_vanish","tooltip":"
Vanish
Instant5 min cooldown
Requires Rogue
Requires level 1
Reagents:
Reduces all Magic damage taken by 50% for 10 sec.
","tooltip2":"","buff":"
Vanish
Magic damage taken reduced by 50%.
10 seconds remaining
","quality":-1,"spells":{},"buffspells":{},"completion_category":0} +457544,{"name":"S03 - Item - T1 - Shaman - Tank 6P Bonus","icon":"ability_ghoulfrenzy","tooltip":"
S03 - Item - T1 - Shaman - Tank 6P Bonus
Requires Shaman
Requires level 1
Your Stoneskin Totem also reduces Physical damage taken by 5% and your Windwall Totem also reduces Magical damage taken by 5%.
","tooltip2":"","buff":"","quality":-1,"spells":{},"buffspells":{},"completion_category":-25} 458436,{"name":"Wyvern Strike","icon":"inv_spear_02","tooltip":"
Wyvern Strike
55 ManaMelee Range
Instant8 sec cooldown
Requires Hunter
Requires level 1
Requires Melee Weapon
A vicious strike that deals 100% weapon damage and causes the target to Bleed for (3 / 100 * 8 * Attack power) Physical damage over 8 sec.
","tooltip2":"","buff":"
Wyvern Strike
3 Bleed damage every 1 seconds.
8 seconds remaining
","quality":-1,"spells":{},"buffspells":{},"completion_category":0} 458481,{"name":"Wyvern Strike","icon":"inv_spear_02","tooltip":"
Wyvern Strike
75 ManaMelee Range
Instant8 sec cooldown
Requires Hunter
Requires level 1
Requires Melee Weapon
A vicious strike that deals 100% weapon damage and causes the target to Bleed for (4 / 100 * 8 * Attack power) Physical damage over 8 sec.
","tooltip2":"","buff":"
Wyvern Strike
4 Bleed damage every 1 seconds.
8 seconds remaining
","quality":-1,"spells":{},"buffspells":{},"completion_category":0} 458482,{"name":"Wyvern Strike","icon":"inv_spear_02","tooltip":"
Wyvern Strike
100 ManaMelee Range
Instant8 sec cooldown
Requires Hunter
Requires level 1
Requires Melee Weapon
A vicious strike that deals 100% weapon damage and causes the target to Bleed for (6 / 100 * 8 * Attack power) Physical damage over 8 sec.
","tooltip2":"","buff":"
Wyvern Strike
6 Bleed damage every 1 seconds.
8 seconds remaining
","quality":-1,"spells":{},"buffspells":{},"completion_category":0} diff --git a/sim/common/sod/item_effects.go b/sim/common/sod/item_effects.go index f628f74644..c8e3bf4cd5 100644 --- a/sim/common/sod/item_effects.go +++ b/sim/common/sod/item_effects.go @@ -53,3 +53,56 @@ func RegisterFiftyPercentHasteBuffCD(character *core.Character, actionID core.Ac Type: core.CooldownTypeDPS, }) } + +func StormhammerChainLightningProcAura(agent core.Agent) { + character := agent.GetCharacter() + + maxHits := int(min(3, character.Env.GetNumTargets())) + procSpell := character.RegisterSpell(core.SpellConfig{ + ActionID: core.ActionID{SpellID: 463946}, + SpellSchool: core.SpellSchoolNature, + DefenseType: core.DefenseTypeMagic, + ProcMask: core.ProcMaskEmpty, + Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, + BonusCoefficient: 0.1, + DamageMultiplier: 1, + ThreatMultiplier: 1, + ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { + for numHits := 0; numHits < maxHits; numHits++ { + spell.CalcAndDealDamage(sim, target, sim.Roll(105, 145), spell.OutcomeMagicHitAndCrit) + target = character.Env.NextTargetUnit(target) + } + }, + }) + + core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ + Name: "Chain Lightning (Skyrider's Masterwork Stormhammer Melee)", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: core.ProcMaskMelee, + SpellFlagsExclude: core.SpellFlagSuppressWeaponProcs, + PPM: 4, // Someone in the armemnts Discord tested it out to 4 PPM + Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { + procSpell.Cast(sim, result.Target) + }, + }) + + icd := core.Cooldown{ + Timer: character.NewTimer(), + Duration: time.Millisecond * 100, + } + core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ + Name: "Chain Lightning (Skyrider's Masterwork Stormhammer Spell)", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: core.ProcMaskSpellDamage, + ProcChance: .1, + Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { + if !icd.IsReady(sim) { + return + } + procSpell.Cast(sim, result.Target) + icd.Use(sim) + }, + }) +} diff --git a/sim/common/sod/item_effects/phase_4.go b/sim/common/sod/item_effects/phase_4.go index be7c3d90a0..15f5b980db 100644 --- a/sim/common/sod/item_effects/phase_4.go +++ b/sim/common/sod/item_effects/phase_4.go @@ -4,6 +4,7 @@ import ( "time" "github.com/wowsims/sod/sim/common/itemhelpers" + "github.com/wowsims/sod/sim/common/sod" "github.com/wowsims/sod/sim/core" "github.com/wowsims/sod/sim/core/proto" "github.com/wowsims/sod/sim/core/stats" @@ -41,58 +42,7 @@ func init() { // https://www.wowhead.com/classic/item=227886/skyriders-masterwork-stormhammer // Chance on hit: Blasts up to 3 targets for 105 to 145 Nature damage. // Estimated based on data from WoW Armaments Discord - core.NewItemEffect(SkyridersMasterworkStormhammer, func(agent core.Agent) { - character := agent.GetCharacter() - - maxHits := int(min(3, character.Env.GetNumTargets())) - procSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 463946}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - BonusCoefficient: 0.1, - DamageMultiplier: 1, - ThreatMultiplier: 1, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for numHits := 0; numHits < maxHits; numHits++ { - spell.CalcAndDealDamage(sim, target, sim.Roll(105, 145), spell.OutcomeMagicHitAndCrit) - target = character.Env.NextTargetUnit(target) - } - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Chain Lightning (Skyrider's Masterwork Stormhammer Melee)", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee, - SpellFlagsExclude: core.SpellFlagSuppressWeaponProcs, - PPM: 4, // Someone in the armemnts Discord tested it out to 4 PPM - Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { - procSpell.Cast(sim, result.Target) - }, - }) - - icd := core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Millisecond * 100, - } - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Chain Lightning (Skyrider's Masterwork Stormhammer Spell)", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskSpellDamage, - ProcChance: .1, - Handler: func(sim *core.Simulation, _ *core.Spell, result *core.SpellResult) { - if !icd.IsReady(sim) { - return - } - procSpell.Cast(sim, result.Target) - icd.Use(sim) - }, - }) - }) + core.NewItemEffect(SkyridersMasterworkStormhammer, sod.StormhammerChainLightningProcAura) // https://www.wowhead.com/classic/item=228486/treants-bane // Equip: +75 Attack Power when fighting Elementals. diff --git a/sim/common/sod/item_effects/phase_6.go b/sim/common/sod/item_effects/phase_6.go index 602e9a9610..69986faf37 100644 --- a/sim/common/sod/item_effects/phase_6.go +++ b/sim/common/sod/item_effects/phase_6.go @@ -3,11 +3,26 @@ package item_effects import ( "time" + "github.com/wowsims/sod/sim/common/sod" + "github.com/wowsims/sod/sim/common/vanilla" "github.com/wowsims/sod/sim/core" "github.com/wowsims/sod/sim/core/stats" ) const ( + LeggingsOfImmersion = 233505 + RingOfSwarmingThought = 233507 + RobesOfTheBattleguard = 233575 + + // Obsidian Weapons + ObsidianChampion = 233490 + ObsidianReaver = 233491 + ObsidianDestroyer = 233796 + ObsidianStormhammer = 233797 + ObsidianSageblade = 233798 + ObsidianDefender = 233801 + ObsidianHeartseeker = 234428 + // Brood of Nozdormu Reputations Rings SignetRingBronzeDominatorR5 = 234034 SignetRingBronzeDominatorR4 = 234030 @@ -49,10 +64,109 @@ const ( func init() { core.AddEffectsToTest = false + /////////////////////////////////////////////////////////////////////////// + // Weapons + /////////////////////////////////////////////////////////////////////////// + + // https://www.wowhead.com/classic/item=233490/obsidian-champion + // Chance on hit: Heal self for 270 to 450 and Increases Strength by 120 for 30 sec. + // Chance on hit: Increases damage done by 20 and attack speed by 5% for 15 sec. + // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. + // Deals extra damage to Silithid creatures in Silithus on almost every hit. + // (2.1s cooldown) + core.NewItemEffect(ObsidianChampion, func(agent core.Agent) { + character := agent.GetCharacter() + vanilla.StrengthOfTheChampionAura(character) + vanilla.EnrageAura446327(character) + ObsidianEdgedAura(ObsidianChampion, agent) + }) + + // https://www.wowhead.com/classic/item=233801/obsidian-defender + // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. + // Deals extra damage to Silithid creatures in Silithus on almost every hit. + // (2.1s cooldown) + core.NewItemEffect(ObsidianDefender, func(agent core.Agent) { + ObsidianEdgedAura(ObsidianDefender, agent) + }) + + // https://www.wowhead.com/classic/item=233796/obsidian-destroyer + // Chance on hit: Stuns target for 3 sec. + // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. + // Deals extra damage to Silithid creatures in Silithus on almost every hit. + // (2.1s cooldown) + core.NewItemEffect(ObsidianDestroyer, func(agent core.Agent) { + ObsidianEdgedAura(ObsidianDestroyer, agent) + }) + + // https://www.wowhead.com/classic/item=234428/obsidian-heartseeker + // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. + // Deals extra damage to Silithid creatures in Silithus on almost every hit. + // (2.1s cooldown) + core.NewItemEffect(ObsidianHeartseeker, func(agent core.Agent) { + ObsidianEdgedAura(ObsidianHeartseeker, agent) + }) + + // https://www.wowhead.com/classic/item=233491/obsidian-reaver + // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. + // Deals extra damage to Silithid creatures in Silithus on almost every hit. + // (2.1s cooldown) + core.NewItemEffect(ObsidianReaver, func(agent core.Agent) { + ObsidianEdgedAura(ObsidianReaver, agent) + }) + + // https://www.wowhead.com/classic/item=233798/obsidian-sageblade + // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. + // Deals extra damage to Silithid creatures in Silithus on almost every hit. + // (2.1s cooldown) + core.NewItemEffect(ObsidianSageblade, func(agent core.Agent) { + ObsidianEdgedAura(ObsidianSageblade, agent) + }) + + // https://www.wowhead.com/classic/item=233797/obsidian-stormhammer + // Chance on hit: Blasts up to 3 targets for 105 to 145 Nature damage. + // Equip: Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. + // Deals extra damage to Silithid creatures in Silithus on almost every hit. + // (2.1s cooldown) + core.NewItemEffect(ObsidianStormhammer, func(agent core.Agent) { + sod.StormhammerChainLightningProcAura(agent) + ObsidianEdgedAura(ObsidianStormhammer, agent) + }) + /////////////////////////////////////////////////////////////////////////// // Rings /////////////////////////////////////////////////////////////////////////// + // https://www.wowhead.com/classic/item=233507/ring-of-swarming-thought + // Your damaging non-periodic spells increase your spell damage by 15 for 15 sec. + // If the target is player controlled, gain 100 spell penetration for 15 sec instead. + // (15s cooldown) + core.NewItemEffect(RingOfSwarmingThought, func(agent core.Agent) { + character := agent.GetCharacter() + buffAura := character.RegisterAura(core.Aura{ + ActionID: core.ActionID{SpellID: 474148}, + Label: "Swarming Thoughts", + Duration: time.Second * 15, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + character.AddStatDynamic(sim, stats.SpellDamage, 15) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + character.AddStatDynamic(sim, stats.SpellDamage, -15) + }, + }) + + core.MakeProcTriggerAura(&agent.GetCharacter().Unit, core.ProcTrigger{ + Name: "Swarming Thoughts Trigger", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: core.ProcMaskSpellDamage, + ProcChance: 1.00, + ICD: time.Second * 15, + Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + buffAura.Activate(sim) + }, + }) + }) + // https://www.wowhead.com/classic/item=234198/signet-ring-of-the-bronze-dragonflight core.NewItemEffect(SignetRingBronzeConquerorR5, TimeswornStrikeAura) core.NewItemEffect(SignetRingBronzeConquerorR4, TimeswornStrikeAura) @@ -102,9 +216,128 @@ func init() { core.NewItemEffect(SignetRingBronzeSubjugatorR2, TimewornDecayAura) core.NewItemEffect(SignetRingBronzeSubjugatorR1, TimewornDecayAura) + /////////////////////////////////////////////////////////////////////////// + // Other + /////////////////////////////////////////////////////////////////////////// + + // https://www.wowhead.com/classic/item=233505/leggings-of-immersion + // Your damaging non-periodic Nature spell critical strikes have a chance to grant you 40 increased spell damage for 10 sec. + // (Proc chance: 50%, 5s cooldown) + core.NewItemEffect(LeggingsOfImmersion, func(agent core.Agent) { + character := agent.GetCharacter() + buffAura := character.RegisterAura(core.Aura{ + ActionID: core.ActionID{SpellID: 474126}, + Label: "Immersed", + Duration: time.Second * 10, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + character.AddStatDynamic(sim, stats.SpellDamage, 40) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + character.AddStatDynamic(sim, stats.SpellDamage, -40) + }, + }) + + icd := core.Cooldown{ + Timer: character.NewTimer(), + Duration: time.Second * 5, + } + + core.MakeProcTriggerAura(&agent.GetCharacter().Unit, core.ProcTrigger{ + Name: "Immersed Trigger", + Callback: core.CallbackOnSpellHitDealt, + ProcMask: core.ProcMaskSpellDamage, + Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + if spell.SpellSchool.Matches(core.SpellSchoolNature) && result.DidCrit() && icd.IsReady(sim) && sim.Proc(0.50, "Immersed Proc") { + buffAura.Activate(sim) + icd.Use(sim) + } + }, + }) + }) + + // https://www.wowhead.com/classic/item=233575/robes-of-the-battleguard + // Your damaging non-periodic spells increase your spell damage by 20 for 15 sec. + // If the target is player controlled, gain 120 spell penetration for 15 sec instead. + // (15s cooldown) + core.NewItemEffect(RobesOfTheBattleguard, func(agent core.Agent) { + character := agent.GetCharacter() + buffAura := character.RegisterAura(core.Aura{ + ActionID: core.ActionID{SpellID: 1213241}, + Label: "Resolve of the Battleguard", + Duration: time.Second * 15, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + character.AddStatDynamic(sim, stats.SpellDamage, 20) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + character.AddStatDynamic(sim, stats.SpellDamage, -20) + }, + }) + + core.MakeProcTriggerAura(&agent.GetCharacter().Unit, core.ProcTrigger{ + Name: "Resolve of the Battleguard Trigger", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: core.ProcMaskSpellDamage, + ProcChance: 1.00, + ICD: time.Second * 15, + Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + buffAura.Activate(sim) + }, + }) + }) + core.AddEffectsToTest = true } +// https://www.wowhead.com/classic/spell=1214125/obsidian-edged +// Chance on direct spell damage or melee attack to deal 325 to 500 Fire damage to your target. +// Deals extra damage to Silithid creatures in Silithus on almost every hit. +// (2.1s cooldown) +func ObsidianEdgedAura(itemID int32, agent core.Agent) { + character := agent.GetCharacter() + + damageSpell := character.GetOrRegisterSpell(core.SpellConfig{ + ActionID: core.ActionID{SpellID: 1213941}, + SpellSchool: core.SpellSchoolFire, + DefenseType: core.DefenseTypeMagic, + ProcMask: core.ProcMaskSpellProc | core.ProcMaskSpellDamageProc, + Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, + + DamageMultiplier: 1, + ThreatMultiplier: 1, + + ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { + spell.CalcAndDealDamage(sim, target, sim.Roll(325, 500), spell.OutcomeMagicHitAndCrit) + }, + }) + + meleeProcMask := character.GetProcMaskForItem(itemID) + + core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ + Name: "Obsidian Edged Proc Melee", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: meleeProcMask, + PPM: 1.0, // TODO: Determine PPM + ICD: time.Millisecond * 2100, + Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + damageSpell.Cast(sim, result.Target) + }, + }) + + core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ + Name: "Obsidian Edged Proc Melee", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: core.ProcMaskSpellDamage, + ProcChance: 1.0, // Wowhead and Wago show 100% but this seems unlikely due to the tooltip. We'll see + ICD: time.Millisecond * 2100, + Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + damageSpell.Cast(sim, result.Target) + }, + }) +} + // https://www.wowhead.com/classic/spell=1214155/timeworn-decay // Increases the damage dealt by all of your damage over time spells by 2% per piece of Timeworn armor equipped. func TimewornDecayAura(agent core.Agent) { @@ -113,11 +346,11 @@ func TimewornDecayAura(agent core.Agent) { return } - multiplier := 1 + 0.02*float64(character.PseudoStats.TimewornBonus) + multiplier := 0.02 * float64(character.PseudoStats.TimewornBonus) character.OnSpellRegistered(func(spell *core.Spell) { if spell.SpellCode != 0 && len(spell.Dots()) > 0 { - spell.PeriodicDamageMultiplier *= multiplier + spell.PeriodicDamageMultiplierAdditive += multiplier } }) } diff --git a/sim/common/vanilla/item_effects.go b/sim/common/vanilla/item_effects.go index de45bd7a2c..2478ee6db4 100644 --- a/sim/common/vanilla/item_effects.go +++ b/sim/common/vanilla/item_effects.go @@ -139,6 +139,7 @@ const ( DarkmoonCardBlueDragon = 234177 // 19288 DarkmoonCardMaelstrom = 234178 // 19289 Earthstrike = 234462 + WrathOfCenarius = 234463 // 21190 KalimdorsRevengeVoidTouched = 234981 NeretzekBloodDrinkerVoidTouched = 234987 ManslayerOfTheQirajiVoidTouched = 234990 @@ -156,7 +157,7 @@ func init() { // https://www.wowhead.com/classic/spell=16916/strength-of-the-champion // Chance on hit: Heal self for 270 to 450 and Increases Strength by 120 for 30 sec. // TODO: Proc rate assumed and needs testing - itemhelpers.CreateWeaponProcAura(ArcaniteChampion, "Arcanite Champion", 1.0, strengthOfTheChampionAura) + itemhelpers.CreateWeaponProcAura(ArcaniteChampion, "Arcanite Champion", 1.0, StrengthOfTheChampionAura) // https://www.wowhead.com/classic/item=227997/barovian-family-sword // Chance on hit: Deals 30 Shadow damage every 3 sec for 15 sec. All damage done is then transferred to the caster. @@ -425,7 +426,7 @@ func init() { // https://www.wowhead.com/classic/item=220569/blistering-ragehammer // Chance on hit: Increases damage done by 20 and attack speed by 5% for 15 sec. // TODO: Proc rate assumed and needs testing - itemhelpers.CreateWeaponProcAura(BlisteringRagehammer, "Blistering Ragehammer", 1.0, enrageAura446327) + itemhelpers.CreateWeaponProcAura(BlisteringRagehammer, "Blistering Ragehammer", 1.0, EnrageAura446327) itemhelpers.CreateWeaponCoHProcDamage(BloodletterScalpel, "Bloodletter Scalpel", 1.0, 18081, core.SpellSchoolPhysical, 60, 10, 0, core.DefenseTypeMelee) @@ -1442,9 +1443,9 @@ func init() { core.NewItemEffect(RefinedArcaniteChampion, func(agent core.Agent) { character := agent.GetCharacter() - strengthAura := strengthOfTheChampionAura(character) + strengthAura := StrengthOfTheChampionAura(character) procMask := character.GetProcMaskForItem(RefinedArcaniteChampion) - enrageAura := enrageAura446327(character) + enrageAura := EnrageAura446327(character) core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ Name: "Refined Arcanite Champion (Strength)", @@ -3002,6 +3003,35 @@ func init() { }) }) + // https://www.wowhead.com/classic/item=234463/wrath-of-cenarius + // Gives a chance when your harmful spells land to increase the damage of your spells and effects by 193 for 10 sec. + // (Proc chance: 5%) + core.NewItemEffect(WrathOfCenarius, func(agent core.Agent) { + character := agent.GetCharacter() + buffAura := character.RegisterAura(core.Aura{ + ActionID: core.ActionID{SpellID: 1214279}, + Label: "Spell Blasting", + Duration: time.Second * 10, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + character.AddStatDynamic(sim, stats.SpellDamage, 193) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + character.AddStatDynamic(sim, stats.SpellDamage, -193) + }, + }) + + core.MakeProcTriggerAura(&agent.GetCharacter().Unit, core.ProcTrigger{ + Name: "Spell Blasting Trigger", + Callback: core.CallbackOnSpellHitDealt, + Outcome: core.OutcomeLanded, + ProcMask: core.ProcMaskSpellDamage, + ProcChance: 0.05, + Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { + buffAura.Activate(sim) + }, + }) + }) + core.AddEffectsToTest = true } @@ -3009,7 +3039,7 @@ func init() { // Used by: // - https://www.wowhead.com/classic/item=220569/blistering-ragehammer and // - https://www.wowhead.com/classic/item=228125/refined-arcanite-champion -func enrageAura446327(character *core.Character) *core.Aura { +func EnrageAura446327(character *core.Character) *core.Aura { return character.GetOrRegisterAura(core.Aura{ ActionID: core.ActionID{SpellID: 446327}, Label: "Enrage (446327)", @@ -3229,7 +3259,7 @@ func gutgoreRipperEffect(character *core.Character) *core.Spell { // }) // } -func strengthOfTheChampionAura(character *core.Character) *core.Aura { +func StrengthOfTheChampionAura(character *core.Character) *core.Aura { actionID := core.ActionID{SpellID: 16916} healthMetrics := character.NewHealthMetrics(actionID) return character.GetOrRegisterAura(core.Aura{ diff --git a/sim/core/apl.go b/sim/core/apl.go index 820c11d1f3..ade870fccf 100644 --- a/sim/core/apl.go +++ b/sim/core/apl.go @@ -2,6 +2,7 @@ package core import ( "fmt" + "slices" "time" "github.com/wowsims/sod/sim/core/proto" @@ -22,6 +23,8 @@ type APLRotation struct { // If true, can recast channel when interrupted. allowChannelRecastOnInterrupt bool + // Checking for cast-while-channeling spells to allow the APL to not evaluate during channels unless absolutely necessary + allowCastWhileChanneling bool // Used inside of actions/value to determine whether they will occur during the prepull or regular rotation. parsingPrepull bool @@ -167,6 +170,9 @@ func (rot *APLRotation) reset(sim *Simulation) { rot.inLoop = false rot.interruptChannelIf = nil rot.allowChannelRecastOnInterrupt = false + rot.allowCastWhileChanneling = slices.ContainsFunc(rot.unit.Spellbook, func(spell *Spell) bool { + return spell.Flags.Matches(SpellFlagCastWhileChanneling) + }) for _, action := range rot.allAPLActions() { action.impl.Reset(sim) } @@ -184,7 +190,7 @@ func (apl *APLRotation) DoNextAction(sim *Simulation) { return } - if apl.unit.IsChanneling(sim) { + if apl.unit.IsChanneling(sim) && !apl.allowCastWhileChanneling { return } diff --git a/sim/core/cast.go b/sim/core/cast.go index ee3a0cfe40..00f6caf38c 100644 --- a/sim/core/cast.go +++ b/sim/core/cast.go @@ -202,6 +202,15 @@ func (spell *Spell) makeCastFunc(config CastConfig) CastSuccessFunc { return spell.castFailureHelper(sim, "casting/channeling %v for %s, curTime = %s", hc.ActionID, hc.Expires-sim.CurrentTime, sim.CurrentTime) } + if dot := spell.Unit.ChanneledDot; spell.Unit.IsChanneling(sim) && !spell.Flags.Matches(SpellFlagCastWhileChanneling) { + // Attempt to use a queued cast-while-casting spell mid-hard cast + if cwc := spell.Unit.castWhileCastingAction; cwc != nil { + cwc.OnAction(sim) + } + + return spell.castFailureHelper(sim, "channeling %v for %s, curTime = %s", dot.ActionID, dot.expires-sim.CurrentTime, sim.CurrentTime) + } + if effectiveTime := spell.CurCast.EffectiveTime(); effectiveTime != 0 { if spell.Flags.Matches(SpellFlagCastTimeNoGCD) { effectiveTime = max(effectiveTime, spell.Unit.GCD.TimeToReady(sim)) diff --git a/sim/core/flags.go b/sim/core/flags.go index 9e623d016d..53c0811698 100644 --- a/sim/core/flags.go +++ b/sim/core/flags.go @@ -187,6 +187,7 @@ const ( SpellFlagResetAttackSwing // Indicates this spell resets the melee swing timer. SpellFlagCastTimeNoGCD // Indicates this spell is off the GCD (e.g. hunter's Auto Shot) SpellFlagCastWhileCasting // Indicates this spell can be cast while another spell is being cast (e.g. mage's Fire Blast with Overheat rune) + SpellFlagCastWhileChanneling // Indicates this spell can be cast while another spell is being channeled (e.g. spriest's T2.5 4pc set bonus) SpellFlagPureDot // Indicates this spell is a dot with no initial damage component SpellFlagPassiveSpell // Indicates this spell is applied/cast as a result of another spell SpellFlagSuppressWeaponProcs // Indicates this spell cannot proc weapon chance on hits or enchants diff --git a/sim/core/spell.go b/sim/core/spell.go index ede07c28c4..f6a0e93fb7 100644 --- a/sim/core/spell.go +++ b/sim/core/spell.go @@ -41,11 +41,11 @@ type SpellConfig struct { CritDamageBonus float64 - BaseDamageMultiplierAdditive float64 // Applies an additive multiplier to spell base damage - DamageMultiplier float64 // Applies a multiplicative multiplier to full spell damage - DamageMultiplierAdditive float64 // Applies an additive multiplier to full spell damage - ImpactDamageMultiplier float64 // Applies a multiplicative multiplier to full non-periodic spell damage - PeriodicDamageMultiplier float64 // Applies a multiplicative multiplier to full spell periodic damage + BaseDamageMultiplierAdditive float64 // Applies an additive multiplier to spell base damage + DamageMultiplier float64 // Applies a multiplicative multiplier to full spell damage + DamageMultiplierAdditive float64 // Applies an additive multiplier to full spell damage + ImpactDamageMultiplierAdditive float64 // Applies an additive multiplier to full non-periodic spell damage + PeriodicDamageMultiplierAdditive float64 // Applies an additive multiplier to full spell periodic damage BonusDamage float64 // Bonus scaling power e.g. Idol of the Moon "Increases the damage of X spell by N" https://www.wowhead.com/classic/item=23197/idol-of-the-moon BonusCoefficient float64 // EffectBonusCoefficient in SpellEffect client DB table, "SP mod" on Wowhead (not necessarily shown there even if > 0) @@ -139,11 +139,11 @@ type Spell struct { BonusCritRating float64 CastTimeMultiplier float64 - BaseDamageMultiplierAdditive float64 // Applies an additive multiplier to spell base damage - DamageMultiplier float64 // Applies a multiplicative multiplier to full spell damage - DamageMultiplierAdditive float64 // Applies an additive multiplier to full spell damage - ImpactDamageMultiplier float64 // Applies a multiplicative multiplier to full non-periodic spell damage - PeriodicDamageMultiplier float64 // Applies a multiplicative multiplier to full spell periodic damage + BaseDamageMultiplierAdditive float64 // Applies an additive multiplier to spell base damage + DamageMultiplier float64 // Applies a multiplicative multiplier to full spell damage + DamageMultiplierAdditive float64 // Applies an additive multiplier to full spell damage + ImpactDamageMultiplierAdditive float64 // Applies an additive multiplier to full non-periodic spell damage + PeriodicDamageMultiplierAdditive float64 // Applies an additive multiplier to full spell periodic damage BonusDamage float64 // Bonus scaling power e.g. Idol of the Moon "Increases the damage of X spell by N" https://www.wowhead.com/classic/item=23197/idol-of-the-moon BonusCoefficient float64 // EffectBonusCoefficient in SpellEffect client DB table, "SP mod" on Wowhead (not necessarily shown there even if > 0) @@ -199,11 +199,11 @@ func (unit *Unit) RegisterSpell(config SpellConfig) *Spell { } else if config.DamageMultiplierAdditive != 0 && config.DamageMultiplier == 0 { config.DamageMultiplier = 1 } - if config.ImpactDamageMultiplier == 0 { - config.ImpactDamageMultiplier = 1 + if config.ImpactDamageMultiplierAdditive == 0 { + config.ImpactDamageMultiplierAdditive = 1 } - if config.PeriodicDamageMultiplier == 0 { - config.PeriodicDamageMultiplier = 1 + if config.PeriodicDamageMultiplierAdditive == 0 { + config.PeriodicDamageMultiplierAdditive = 1 } // Default CastSlot to mainhand @@ -265,11 +265,11 @@ func (unit *Unit) RegisterSpell(config SpellConfig) *Spell { CritDamageBonus: 1 + config.CritDamageBonus, - BaseDamageMultiplierAdditive: config.BaseDamageMultiplierAdditive, - DamageMultiplier: config.DamageMultiplier, - DamageMultiplierAdditive: config.DamageMultiplierAdditive, - ImpactDamageMultiplier: config.ImpactDamageMultiplier, - PeriodicDamageMultiplier: config.PeriodicDamageMultiplier, + BaseDamageMultiplierAdditive: config.BaseDamageMultiplierAdditive, + DamageMultiplier: config.DamageMultiplier, + DamageMultiplierAdditive: config.DamageMultiplierAdditive, + ImpactDamageMultiplierAdditive: config.ImpactDamageMultiplierAdditive, + PeriodicDamageMultiplierAdditive: config.PeriodicDamageMultiplierAdditive, BonusCoefficient: config.BonusCoefficient, @@ -520,10 +520,18 @@ func (spell *Spell) CanCast(sim *Simulation, target *Unit) bool { return false } - // While casting or channeling, no other action is possible except rare cast-while-casting spells + // While casting no other action is possible except rare cast-while-casting spells if spell.Unit.IsCasting(sim) && !spell.Flags.Matches(SpellFlagCastWhileCasting) { //if sim.Log != nil { - // sim.Log("Cant cast because already casting/channeling") + // sim.Log("Cant cast because already casting") + //} + return false + } + + // While channeling no other action is possible except rare cast-while-channeling spells + if spell.Unit.IsChanneling(sim) && !spell.Flags.Matches(SpellFlagCastWhileChanneling) { + //if sim.Log != nil { + // sim.Log("Cant cast because already channeling") //} return false } diff --git a/sim/core/spell_result.go b/sim/core/spell_result.go index 2ae581dbd9..85ef0c45c1 100644 --- a/sim/core/spell_result.go +++ b/sim/core/spell_result.go @@ -333,7 +333,7 @@ func (spell *Spell) calcDamageInternal(sim *Simulation, target *Unit, baseDamage return result } func (spell *Spell) CalcDamage(sim *Simulation, target *Unit, baseDamage float64, outcomeApplier OutcomeApplier) *SpellResult { - attackerMultiplier := spell.AttackerDamageMultiplier(spell.Unit.AttackTables[target.UnitIndex][spell.CastType]) * spell.ImpactDamageMultiplier + attackerMultiplier := spell.AttackerDamageMultiplier(spell.Unit.AttackTables[target.UnitIndex][spell.CastType]) * spell.ImpactDamageMultiplierAdditive baseDamage *= spell.BaseDamageMultiplierAdditive @@ -346,7 +346,7 @@ func (spell *Spell) CalcDamage(sim *Simulation, target *Unit, baseDamage float64 func (spell *Spell) CalcPeriodicDamage(sim *Simulation, target *Unit, baseDamage float64, outcomeApplier OutcomeApplier) *SpellResult { baseDamage *= spell.BaseDamageMultiplierAdditive - attackerMultiplier := spell.AttackerDamageMultiplier(spell.Unit.AttackTables[target.UnitIndex][spell.CastType]) * spell.PeriodicDamageMultiplier + attackerMultiplier := spell.AttackerDamageMultiplier(spell.Unit.AttackTables[target.UnitIndex][spell.CastType]) * spell.PeriodicDamageMultiplierAdditive dot := spell.DotOrAOEDot(target) attackerMultiplier *= dot.DamageMultiplier @@ -372,7 +372,7 @@ func (dot *Dot) Snapshot(target *Unit, baseDamage float64, isRollover bool) { if dot.Spell.Flags.Matches(SpellFlagHelpful) { dot.SnapshotAttackerMultiplier = dot.Spell.CasterHealingMultiplier() } else { - dot.SnapshotAttackerMultiplier = dot.Spell.AttackerDamageMultiplier(attackTable) * dot.Spell.PeriodicDamageMultiplier + dot.SnapshotAttackerMultiplier = dot.Spell.AttackerDamageMultiplier(attackTable) * dot.Spell.PeriodicDamageMultiplierAdditive } dot.SnapshotAttackerMultiplier *= dot.DamageMultiplier diff --git a/sim/core/unit.go b/sim/core/unit.go index cc209ec850..dc4ac3d9d9 100644 --- a/sim/core/unit.go +++ b/sim/core/unit.go @@ -1,6 +1,7 @@ package core import ( + "math" "time" "github.com/wowsims/sod/sim/core/proto" @@ -26,7 +27,6 @@ const ( type DynamicDamageTakenModifier func(sim *Simulation, spell *Spell, result *SpellResult) - // Unit is an abstraction of a Character/Boss/Pet/etc, containing functionality // shared by all of them. type Unit struct { @@ -351,7 +351,7 @@ func (unit *Unit) ApplyCastSpeed(dur time.Duration) time.Duration { return time.Duration(float64(dur) * unit.CastSpeed) } func (unit *Unit) ApplyCastSpeedForSpell(dur time.Duration, spell *Spell) time.Duration { - return time.Duration(float64(dur) * unit.CastSpeed * spell.CastTimeMultiplier) + return time.Duration(float64(dur) * unit.CastSpeed * math.Max(spell.CastTimeMultiplier, 0)) } func (unit *Unit) SwingSpeed() float64 { diff --git a/sim/hunter/item_sets_pve.go b/sim/hunter/item_sets_pve.go index c1a8f543b0..4d64026450 100644 --- a/sim/hunter/item_sets_pve.go +++ b/sim/hunter/item_sets_pve.go @@ -416,7 +416,7 @@ var StrikersProwess = core.NewItemSet(core.ItemSet{ hunter.RegisterAura(core.Aura{ Label: "Striker's Prowess 2P", OnInit: func(aura *core.Aura, sim *core.Simulation) { - hunter.WyvernStrike.PeriodicDamageMultiplier *= 1.50 + hunter.WyvernStrike.PeriodicDamageMultiplierAdditive += 0.50 }, }) }, @@ -427,11 +427,11 @@ var StrikersProwess = core.NewItemSet(core.ItemSet{ Label: "Striker's Prowess 4P", OnInit: func(aura *core.Aura, sim *core.Simulation) { for _, spell := range hunter.Strikes { - spell.ImpactDamageMultiplier *= 1.10 + spell.ImpactDamageMultiplierAdditive += 0.10 } - hunter.RaptorStrikeMH.ImpactDamageMultiplier *= 1.10 - hunter.RaptorStrikeOH.ImpactDamageMultiplier *= 1.10 - hunter.MongooseBite.ImpactDamageMultiplier *= 1.10 + hunter.RaptorStrikeMH.ImpactDamageMultiplierAdditive += 0.10 + hunter.RaptorStrikeOH.ImpactDamageMultiplierAdditive += 0.10 + hunter.MongooseBite.ImpactDamageMultiplierAdditive += 0.10 }, }) }, diff --git a/sim/hunter/wyvern_strike.go b/sim/hunter/wyvern_strike.go index 7a3e0d998e..9882424819 100644 --- a/sim/hunter/wyvern_strike.go +++ b/sim/hunter/wyvern_strike.go @@ -43,12 +43,10 @@ func (hunter *Hunter) getWyvernStrikeConfig(rank int) core.SpellConfig { return hunter.MainHand().HandType == proto.HandType_HandTypeTwoHand && hunter.DistanceFromTarget <= core.MaxMeleeAttackDistance }, - CritDamageBonus: hunter.mortalShots(), - DamageMultiplier: 1, - PeriodicDamageMultiplier: 1, - ImpactDamageMultiplier: 1, - BonusCoefficient: 1, - ThreatMultiplier: 1, + CritDamageBonus: hunter.mortalShots(), + DamageMultiplier: 1, + BonusCoefficient: 1, + ThreatMultiplier: 1, Dot: core.DotConfig{ Aura: core.Aura{ diff --git a/sim/mage/TestArcane.results b/sim/mage/TestArcane.results index 28211f394f..dd98689086 100644 --- a/sim/mage/TestArcane.results +++ b/sim/mage/TestArcane.results @@ -298,18 +298,18 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.60335 + weights: 0.77344 weights: 0 - weights: 1.21855 - weights: 1.09181 - weights: 0.12674 + weights: 1.21905 + weights: 1.0925 + weights: 0.12655 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 14.21506 + weights: 14.42223 weights: 0 weights: 0 weights: 0 @@ -393,8 +393,8 @@ stat_weights_results: { dps_results: { key: "TestArcane-Phase1-Lvl25-Average-Default" value: { - dps: 179.25803 - tps: 110.74567 + dps: 179.25832 + tps: 110.74584 } } dps_results: { @@ -491,8 +491,8 @@ dps_results: { dps_results: { key: "TestArcane-Phase2-Lvl40-Average-Default" value: { - dps: 441.12825 - tps: 276.23124 + dps: 441.12813 + tps: 276.23119 } } dps_results: { @@ -617,8 +617,8 @@ dps_results: { dps_results: { key: "TestArcane-Phase4-Lvl60-AllItems-IronweaveBattlesuit" value: { - dps: 590.19959 - tps: 614.93977 + dps: 588.24351 + tps: 612.9821 } } dps_results: { @@ -645,15 +645,15 @@ dps_results: { dps_results: { key: "TestArcane-Phase4-Lvl60-AllItems-Sorcerer'sRegalia" value: { - dps: 738.75817 - tps: 774.45243 + dps: 738.64832 + tps: 774.10139 } } dps_results: { key: "TestArcane-Phase4-Lvl60-Average-Default" value: { - dps: 2060.85374 - tps: 2084.05392 + dps: 2060.69217 + tps: 2083.8894 } } dps_results: { @@ -680,15 +680,15 @@ dps_results: { dps_results: { key: "TestArcane-Phase4-Lvl60-Settings-Gnome-p4_arcane-Arcane-p4_arcane-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 979.70597 - tps: 1224.03219 + dps: 980.25939 + tps: 1224.39883 } } dps_results: { key: "TestArcane-Phase4-Lvl60-Settings-Gnome-p4_arcane-Arcane-p4_arcane-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 979.70597 - tps: 991.92228 + dps: 980.25939 + tps: 992.46636 } } dps_results: { @@ -701,15 +701,15 @@ dps_results: { dps_results: { key: "TestArcane-Phase4-Lvl60-Settings-Troll-p4_arcane-Arcane-p4_arcane-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 2088.39044 - tps: 2495.90754 + dps: 2087.93997 + tps: 2495.35874 } } dps_results: { key: "TestArcane-Phase4-Lvl60-Settings-Troll-p4_arcane-Arcane-p4_arcane-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 2088.39044 - tps: 2108.76629 + dps: 2087.93997 + tps: 2108.31091 } } dps_results: { @@ -722,15 +722,15 @@ dps_results: { dps_results: { key: "TestArcane-Phase4-Lvl60-Settings-Troll-p4_arcane-Arcane-p4_arcane-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 974.94648 - tps: 1223.65239 + dps: 977.35726 + tps: 1225.98831 } } dps_results: { key: "TestArcane-Phase4-Lvl60-Settings-Troll-p4_arcane-Arcane-p4_arcane-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 974.94648 - tps: 987.38177 + dps: 977.35726 + tps: 989.78881 } } dps_results: { diff --git a/sim/mage/TestFire.results b/sim/mage/TestFire.results index 9b24e5f8d1..e8b20d1841 100644 --- a/sim/mage/TestFire.results +++ b/sim/mage/TestFire.results @@ -396,18 +396,18 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 3.40147 + weights: 3.88065 weights: 0 - weights: 1.98432 + weights: 1.98343 weights: 0 - weights: 1.98432 + weights: 1.98343 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 21.26948 + weights: 20.73157 weights: 0 weights: 0 weights: 0 @@ -445,18 +445,18 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.64024 + weights: 1.57419 weights: 0 - weights: 2.39253 + weights: 2.39184 weights: 0 - weights: 2.39253 + weights: 2.39184 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 33.06184 + weights: 32.94408 weights: 0 weights: 0 weights: 0 @@ -785,8 +785,8 @@ dps_results: { dps_results: { key: "TestFire-Phase4-Lvl60-AllItems-BloodGuard'sDreadweave" value: { - dps: 1978.13588 - tps: 1295.26232 + dps: 1979.93022 + tps: 1296.67588 } } dps_results: { @@ -799,29 +799,29 @@ dps_results: { dps_results: { key: "TestFire-Phase4-Lvl60-AllItems-EmeraldEnchantedVestments" value: { - dps: 1930.02845 - tps: 1266.50107 + dps: 1926.03341 + tps: 1263.40556 } } dps_results: { key: "TestFire-Phase4-Lvl60-AllItems-EmeraldWovenGarb" value: { - dps: 1768.03779 - tps: 1158.05177 + dps: 1773.55975 + tps: 1161.61662 } } dps_results: { key: "TestFire-Phase4-Lvl60-AllItems-IronweaveBattlesuit" value: { - dps: 676.42349 - tps: 648.61787 + dps: 676.47795 + tps: 648.65813 } } dps_results: { key: "TestFire-Phase4-Lvl60-AllItems-Knight-Lieutenant'sDreadweave" value: { - dps: 1978.13588 - tps: 1295.26232 + dps: 1979.93022 + tps: 1296.67588 } } dps_results: { @@ -834,36 +834,36 @@ dps_results: { dps_results: { key: "TestFire-Phase4-Lvl60-AllItems-MalevolentProphet'sVestments" value: { - dps: 2170.06198 - tps: 1425.62099 + dps: 2171.61474 + tps: 1426.2924 } } dps_results: { key: "TestFire-Phase4-Lvl60-AllItems-Sorcerer'sRegalia" value: { - dps: 841.63931 - tps: 804.92407 + dps: 840.48361 + tps: 803.82597 } } dps_results: { key: "TestFire-Phase4-Lvl60-Average-Default" value: { - dps: 3001.35682 - tps: 1972.31589 + dps: 3001.06827 + tps: 1972.1994 } } dps_results: { key: "TestFire-Phase4-Lvl60-Settings-Gnome-p4_fire-Fire-p4_fire-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 3047.60889 - tps: 2549.63272 + dps: 3049.44649 + tps: 2551.33966 } } dps_results: { key: "TestFire-Phase4-Lvl60-Settings-Gnome-p4_fire-Fire-p4_fire-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 3047.60889 - tps: 1998.57808 + dps: 3049.44649 + tps: 2000.13505 } } dps_results: { @@ -876,15 +876,15 @@ dps_results: { dps_results: { key: "TestFire-Phase4-Lvl60-Settings-Gnome-p4_fire-Fire-p4_fire-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 834.74694 - tps: 884.25808 + dps: 833.70959 + tps: 883.54911 } } dps_results: { key: "TestFire-Phase4-Lvl60-Settings-Gnome-p4_fire-Fire-p4_fire-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 834.74694 - tps: 543.80302 + dps: 833.70959 + tps: 543.33188 } } dps_results: { @@ -897,15 +897,15 @@ dps_results: { dps_results: { key: "TestFire-Phase4-Lvl60-Settings-Troll-p4_fire-Fire-p4_fire-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 3011.23011 - tps: 2525.06781 + dps: 3010.72438 + tps: 2523.30419 } } dps_results: { key: "TestFire-Phase4-Lvl60-Settings-Troll-p4_fire-Fire-p4_fire-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 3011.23011 - tps: 1980.07046 + dps: 3010.72438 + tps: 1978.56779 } } dps_results: { @@ -918,15 +918,15 @@ dps_results: { dps_results: { key: "TestFire-Phase4-Lvl60-Settings-Troll-p4_fire-Fire-p4_fire-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 763.26259 - tps: 830.3161 + dps: 766.805 + tps: 832.60461 } } dps_results: { key: "TestFire-Phase4-Lvl60-Settings-Troll-p4_fire-Fire-p4_fire-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 763.26259 - tps: 495.25131 + dps: 766.805 + tps: 497.28403 } } dps_results: { @@ -939,92 +939,92 @@ dps_results: { dps_results: { key: "TestFire-Phase4-Lvl60-SwitchInFrontOfTarget-Default" value: { - dps: 3022.39287 - tps: 1987.29295 + dps: 3020.37964 + tps: 1985.52329 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-BloodGuard'sDreadweave" value: { - dps: 2295.68875 - tps: 1509.21895 + dps: 2300.16515 + tps: 1511.97246 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-BloodGuard'sSatin" value: { - dps: 2085.42728 - tps: 1372.47773 + dps: 2085.39482 + tps: 1372.4467 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-EmeraldEnchantedVestments" value: { - dps: 2264.64873 - tps: 1489.62535 + dps: 2263.54399 + tps: 1489.15936 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-EmeraldWovenGarb" value: { - dps: 2060.57681 - tps: 1354.97988 + dps: 2056.98677 + tps: 1352.70999 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-IronweaveBattlesuit" value: { - dps: 986.6752 - tps: 720.19692 + dps: 985.7509 + tps: 719.5436 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-Knight-Lieutenant'sDreadweave" value: { - dps: 2295.68875 - tps: 1509.21895 + dps: 2300.16515 + tps: 1511.97246 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-KnightLieutenant'sSatin" value: { - dps: 2085.42728 - tps: 1372.47773 + dps: 2085.39482 + tps: 1372.4467 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-MalevolentProphet'sVestments" value: { - dps: 2778.70289 - tps: 1647.40547 + dps: 2779.53508 + tps: 1647.86049 } } dps_results: { key: "TestFire-Phase5-Lvl60-AllItems-Sorcerer'sRegalia" value: { - dps: 1206.5568 - tps: 882.73657 + dps: 1206.2969 + tps: 882.52242 } } dps_results: { key: "TestFire-Phase5-Lvl60-Average-Default" value: { - dps: 3703.34736 - tps: 2134.47055 + dps: 3702.73784 + tps: 2134.09335 } } dps_results: { key: "TestFire-Phase5-Lvl60-Settings-Gnome-p5_fire-Fire-p5_fire-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 16389.24084 - tps: 9703.17079 + dps: 16407.93282 + tps: 9714.39566 } } dps_results: { key: "TestFire-Phase5-Lvl60-Settings-Gnome-p5_fire-Fire-p5_fire-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 3702.12666 - tps: 2138.63682 + dps: 3699.90474 + tps: 2137.41771 } } dps_results: { @@ -1044,8 +1044,8 @@ dps_results: { dps_results: { key: "TestFire-Phase5-Lvl60-Settings-Gnome-p5_fire-Fire-p5_fire-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 1007.04839 - tps: 594.24594 + dps: 1008.57945 + tps: 595.03911 } } dps_results: { @@ -1065,8 +1065,8 @@ dps_results: { dps_results: { key: "TestFire-Phase5-Lvl60-Settings-Troll-p5_fire-Fire-p5_fire-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 3672.47039 - tps: 2122.22097 + dps: 3667.32848 + tps: 2119.907 } } dps_results: { @@ -1086,8 +1086,8 @@ dps_results: { dps_results: { key: "TestFire-Phase5-Lvl60-Settings-Troll-p5_fire-Fire-p5_fire-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 981.78903 - tps: 578.48686 + dps: 983.97355 + tps: 579.78841 } } dps_results: { @@ -1100,7 +1100,7 @@ dps_results: { dps_results: { key: "TestFire-Phase5-Lvl60-SwitchInFrontOfTarget-Default" value: { - dps: 3750.62217 - tps: 2163.14984 + dps: 3748.08077 + tps: 2161.39735 } } diff --git a/sim/mage/TestFrost.results b/sim/mage/TestFrost.results index 6df71964fb..39733b25fa 100644 --- a/sim/mage/TestFrost.results +++ b/sim/mage/TestFrost.results @@ -200,18 +200,18 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 1.71163 + weights: 1.7582 weights: 0 - weights: 2.08143 + weights: 2.08213 weights: 0 - weights: 1.85627 - weights: 0.22516 + weights: 1.85709 + weights: 0.22504 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 25.91885 + weights: 25.31337 weights: 0 weights: 0 weights: 0 @@ -400,29 +400,29 @@ dps_results: { dps_results: { key: "TestFrost-Phase4-Lvl60-AllItems-BloodGuard'sSatin" value: { - dps: 1569.19276 - tps: 1289.56962 + dps: 1565.66976 + tps: 1286.52727 } } dps_results: { key: "TestFrost-Phase4-Lvl60-AllItems-EmeraldEnchantedVestments" value: { - dps: 1724.7375 - tps: 1417.97999 + dps: 1727.57314 + tps: 1420.32606 } } dps_results: { key: "TestFrost-Phase4-Lvl60-AllItems-EmeraldWovenGarb" value: { - dps: 1563.2498 - tps: 1284.01585 + dps: 1566.4225 + tps: 1286.4318 } } dps_results: { key: "TestFrost-Phase4-Lvl60-AllItems-IronweaveBattlesuit" value: { - dps: 747.63715 - tps: 597.91515 + dps: 746.80376 + tps: 597.00412 } } dps_results: { @@ -435,43 +435,43 @@ dps_results: { dps_results: { key: "TestFrost-Phase4-Lvl60-AllItems-KnightLieutenant'sSatin" value: { - dps: 1569.19276 - tps: 1289.56962 + dps: 1565.66976 + tps: 1286.52727 } } dps_results: { key: "TestFrost-Phase4-Lvl60-AllItems-MalevolentProphet'sVestments" value: { - dps: 1777.5382 - tps: 1463.52391 + dps: 1776.88764 + tps: 1462.86416 } } dps_results: { key: "TestFrost-Phase4-Lvl60-AllItems-Sorcerer'sRegalia" value: { - dps: 866.54435 - tps: 692.26737 + dps: 866.74455 + tps: 692.16307 } } dps_results: { key: "TestFrost-Phase4-Lvl60-Average-Default" value: { - dps: 2904.05673 - tps: 2385.14044 + dps: 2904.26763 + tps: 2385.18404 } } dps_results: { key: "TestFrost-Phase4-Lvl60-Settings-Gnome-p4_frost-Frost-p4_frost-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 2905.00949 - tps: 2889.65672 + dps: 2903.65503 + tps: 2888.59189 } } dps_results: { key: "TestFrost-Phase4-Lvl60-Settings-Gnome-p4_frost-Frost-p4_frost-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 2905.00949 - tps: 2385.63608 + dps: 2903.65503 + tps: 2384.5322 } } dps_results: { @@ -484,15 +484,15 @@ dps_results: { dps_results: { key: "TestFrost-Phase4-Lvl60-Settings-Gnome-p4_frost-Frost-p4_frost-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 929.97946 - tps: 1084.66451 + dps: 928.46555 + tps: 1082.58398 } } dps_results: { key: "TestFrost-Phase4-Lvl60-Settings-Gnome-p4_frost-Frost-p4_frost-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 929.97946 - tps: 760.20234 + dps: 928.46555 + tps: 758.50608 } } dps_results: { @@ -505,15 +505,15 @@ dps_results: { dps_results: { key: "TestFrost-Phase4-Lvl60-Settings-Troll-p4_frost-Frost-p4_frost-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 2884.10464 - tps: 2868.42827 + dps: 2885.46222 + tps: 2869.31363 } } dps_results: { key: "TestFrost-Phase4-Lvl60-Settings-Troll-p4_frost-Frost-p4_frost-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 2884.10464 - tps: 2369.72321 + dps: 2885.46222 + tps: 2370.55491 } } dps_results: { @@ -526,15 +526,15 @@ dps_results: { dps_results: { key: "TestFrost-Phase4-Lvl60-Settings-Troll-p4_frost-Frost-p4_frost-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 918.84482 - tps: 1074.96964 + dps: 918.89321 + tps: 1075.01044 } } dps_results: { key: "TestFrost-Phase4-Lvl60-Settings-Troll-p4_frost-Frost-p4_frost-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 918.84482 - tps: 750.79334 + dps: 918.89321 + tps: 750.83413 } } dps_results: { @@ -547,8 +547,8 @@ dps_results: { dps_results: { key: "TestFrost-Phase4-Lvl60-SwitchInFrontOfTarget-Default" value: { - dps: 2885.37143 - tps: 2369.78885 + dps: 2886.48871 + tps: 2370.42606 } } dps_results: { @@ -582,8 +582,8 @@ dps_results: { dps_results: { key: "TestFrost-Phase5-Lvl60-AllItems-IronweaveBattlesuit" value: { - dps: 1037.78195 - tps: 647.97953 + dps: 1037.8484 + tps: 648.02604 } } dps_results: { diff --git a/sim/priest/devouring_plague.go b/sim/priest/devouring_plague.go index e1cf318f3d..45d241f10d 100644 --- a/sim/priest/devouring_plague.go +++ b/sim/priest/devouring_plague.go @@ -16,10 +16,6 @@ var DevouringPlagueManaCost = [DevouringPlagueRanks + 1]float64{0, 215, 350, 495 var DevouringPlagueLevel = [DevouringPlagueRanks + 1]int{0, 20, 28, 36, 44, 52, 60} func (priest *Priest) registerDevouringPlagueSpell() { - if priest.Race != proto.Race_RaceUndead { - return - } - priest.DevouringPlague = make([]*core.Spell, DevouringPlagueRanks+1) cdTimer := priest.NewTimer() @@ -45,6 +41,7 @@ func (priest *Priest) getDevouringPlagueConfig(rank int, cdTimer *core.Timer) co spellCoeff := 0.063 return core.SpellConfig{ + SpellCode: SpellCode_PriestDevouringPlague, ActionID: core.ActionID{SpellID: spellId}, SpellSchool: core.SpellSchoolShadow, DefenseType: core.DefenseTypeMagic, diff --git a/sim/priest/item_sets_pve.go b/sim/priest/item_sets_pve.go index 5c39acf7e6..84255f5483 100644 --- a/sim/priest/item_sets_pve.go +++ b/sim/priest/item_sets_pve.go @@ -359,3 +359,95 @@ var ItemSetConfessorsRaiment = core.NewItemSet(core.ItemSet{ }, }, }) + +/////////////////////////////////////////////////////////////////////////// +// SoD Phase 6 Item Sets +/////////////////////////////////////////////////////////////////////////// + +var ItemSetTwilightOfTheOracle = core.NewItemSet(core.ItemSet{ + Name: "Twilight of the Oracle", + Bonuses: map[int32]core.ApplyEffect{ + // Your Mind Flay no longer loses duration from taking damage and launches a free Mind Spike at the target on cast. + 2: func(agent core.Agent) { + priest := agent.(PriestAgent).GetPriest() + if !priest.Talents.MindFlay || !priest.HasRune(proto.PriestRune_RuneWaistMindSpike) { + return + } + + priest.RegisterAura(core.Aura{ + Label: "S03 - Item - TAQ - Priest - Shadow 2P Bonus", + OnInit: func(aura *core.Aura, sim *core.Simulation) { + for _, spells := range priest.MindFlay { + for _, spell := range spells { + if spell == nil { + continue + } + + spell.PushbackReduction += 1 + + oldApplyEffects := spell.ApplyEffects + spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { + priest.MindSpike.DefaultCast.GCD = 0 + priest.MindSpike.CastTimeMultiplier -= 1 + priest.MindSpike.Cost.Multiplier -= 100 + priest.MindSpike.Cast(sim, target) + priest.MindSpike.DefaultCast.GCD = core.GCDDefault + priest.MindSpike.CastTimeMultiplier += 1 + priest.MindSpike.Cost.Multiplier += 100 + + oldApplyEffects(sim, target, spell) + } + } + } + }, + }) + }, + // Your Mind Spike is now instant, deals 30% more damage, and can be cast while channeling another spell. + 4: func(agent core.Agent) { + priest := agent.(PriestAgent).GetPriest() + if !priest.HasRune(proto.PriestRune_RuneWaistMindSpike) { + return + } + + priest.RegisterAura(core.Aura{ + Label: "S03 - Item - TAQ - Priest - Shadow 4P Bonus", + OnInit: func(aura *core.Aura, sim *core.Simulation) { + priest.MindSpike.CastTimeMultiplier -= 1 + priest.MindSpike.DamageMultiplier *= 1.30 + priest.MindSpike.Flags |= core.SpellFlagCastWhileChanneling + }, + }) + }, + }, +}) + +var ItemSetDawnOfTheOracle = core.NewItemSet(core.ItemSet{ + Name: "Dawn of the Oracle", + Bonuses: map[int32]core.ApplyEffect{ + // Your Prayer of Mending gains 2 additional charges. + 2: func(agent core.Agent) { + }, + // Your Circle of Healing now heals the most injured member of the target party for 100% more. + 4: func(agent core.Agent) { + }, + }, +}) + +var ItemSetFineryOfInfiniteWisdom = core.NewItemSet(core.ItemSet{ + Name: "Finery of Infinite Wisdom", + Bonuses: map[int32]core.ApplyEffect{ + // Your Pain and Suffering rune can now refresh the duration of Devouring Plague. + 3: func(agent core.Agent) { + priest := agent.(PriestAgent).GetPriest() + priest.RegisterAura(core.Aura{ + Label: "S03 - Item - RAQ - Priest - Shadow 3P Bonus", + OnInit: func(aura *core.Aura, sim *core.Simulation) { + priest.PainAndSufferingDoTSpells = append( + priest.PainAndSufferingDoTSpells, + core.FilterSlice(priest.DevouringPlague, func(spell *core.Spell) bool { return spell != nil })..., + ) + }, + }) + }, + }, +}) diff --git a/sim/priest/priest.go b/sim/priest/priest.go index d725eefe43..6b40d0f417 100644 --- a/sim/priest/priest.go +++ b/sim/priest/priest.go @@ -15,6 +15,8 @@ const ( const ( SpellCode_PriestNone int32 = iota + + SpellCode_PriestDevouringPlague SpellCode_PriestFlashHeal SpellCode_PriestGreaterHeal SpellCode_PriestHeal @@ -86,6 +88,8 @@ type Priest struct { HomunculiPets []*Homunculus ShadowfiendPet *Shadowfiend + PainAndSufferingDoTSpells []*core.Spell + ProcPrayerOfMending core.ApplySpellResults } diff --git a/sim/priest/runes.go b/sim/priest/runes.go index b02398b284..ca29558eb4 100644 --- a/sim/priest/runes.go +++ b/sim/priest/runes.go @@ -47,24 +47,31 @@ func (priest *Priest) applyPainAndSuffering() { return } + priest.PainAndSufferingDoTSpells = []*core.Spell{} + affectedSpellcodes := []int32{SpellCode_PriestMindBlast, SpellCode_PriestMindFlay, SpellCode_PriestMindSpike} - priest.RegisterAura(core.Aura{ - Label: "Pain and Suffering Trigger", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) + core.MakePermanent(priest.RegisterAura(core.Aura{ + Label: "Pain and Suffering Trigger", + OnInit: func(aura *core.Aura, sim *core.Simulation) { + priest.PainAndSufferingDoTSpells = append( + priest.PainAndSufferingDoTSpells, + core.FilterSlice( + core.Flatten( + [][]*core.Spell{ + priest.ShadowWordPain, + {priest.VoidPlague, priest.VampiricTouch}, + }, + ), + func(spell *core.Spell) bool { return spell != nil }, + )..., + ) }, OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { if slices.Contains(affectedSpellcodes, spell.SpellCode) && result.Landed() { target := result.Target var dotToRollover *core.Dot - dotSpells := core.FilterSlice( - core.Flatten([][]*core.Spell{priest.ShadowWordPain, {priest.VoidPlague, priest.VampiricTouch}}), - func(spell *core.Spell) bool { - return spell != nil && spell.Dot(target).IsActive() - }, - ) + dotSpells := core.FilterSlice(priest.PainAndSufferingDoTSpells, func(spell *core.Spell) bool { return spell.Dot(target).IsActive() }) if len(dotSpells) > 0 { dotToRollover = dotSpells[0].Dot(target) @@ -80,7 +87,7 @@ func (priest *Priest) applyPainAndSuffering() { } } }, - }) + })) } func (priest *Priest) applySurgeOfLight() { diff --git a/sim/priest/shadow/TestShadow.results b/sim/priest/shadow/TestShadow.results index 6528c2fe1f..5fbea51744 100644 --- a/sim/priest/shadow/TestShadow.results +++ b/sim/priest/shadow/TestShadow.results @@ -298,18 +298,18 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.01233 + weights: -0.08102 weights: 0 - weights: 0.80115 + weights: 0.80098 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 0.80115 + weights: 0.80098 weights: 0 weights: 0 - weights: 1.78676 + weights: 1.91708 weights: 0 weights: 0 weights: 0 @@ -347,18 +347,18 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.34297 + weights: 0.01477 weights: 0 - weights: 1.11123 + weights: 1.1089 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 1.11123 + weights: 1.1089 weights: 0 weights: 0 - weights: 8.2918 + weights: 8.25052 weights: 0 weights: 0 weights: 0 @@ -596,226 +596,226 @@ dps_results: { dps_results: { key: "TestShadow-Phase2-Lvl40-AllItems-VestmentsoftheVirtuous" value: { - dps: 172.92058 - tps: 147.5328 + dps: 179.51888 + tps: 153.3209 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Average-Default" value: { - dps: 616.36966 - tps: 491.91368 + dps: 619.22943 + tps: 494.2898 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-NightElf-phase_2-Basic-phase_2-FullBuffs-P2-Consumes-LongMultiTarget" value: { - dps: 614.07089 - tps: 777.97399 + dps: 617.81812 + tps: 781.11954 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-NightElf-phase_2-Basic-phase_2-FullBuffs-P2-Consumes-LongSingleTarget" value: { - dps: 614.07089 - tps: 489.91091 + dps: 617.81812 + tps: 492.95196 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-NightElf-phase_2-Basic-phase_2-FullBuffs-P2-Consumes-ShortSingleTarget" value: { - dps: 588.09828 - tps: 476.17304 + dps: 596.38381 + tps: 483.13289 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-NightElf-phase_2-Basic-phase_2-NoBuffs-P2-Consumes-LongMultiTarget" value: { - dps: 418.40522 - tps: 536.81367 + dps: 410.86677 + tps: 530.85775 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-NightElf-phase_2-Basic-phase_2-NoBuffs-P2-Consumes-LongSingleTarget" value: { - dps: 418.40522 - tps: 332.12354 + dps: 410.86677 + tps: 326.16762 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-NightElf-phase_2-Basic-phase_2-NoBuffs-P2-Consumes-ShortSingleTarget" value: { - dps: 457.29279 - tps: 369.58089 + dps: 462.63504 + tps: 373.1684 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-Troll-phase_2-Basic-phase_2-FullBuffs-P2-Consumes-LongMultiTarget" value: { - dps: 615.76983 - tps: 776.9357 + dps: 618.19708 + tps: 779.07194 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-Troll-phase_2-Basic-phase_2-FullBuffs-P2-Consumes-LongSingleTarget" value: { - dps: 615.76983 - tps: 490.95531 + dps: 618.19708 + tps: 493.43326 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-Troll-phase_2-Basic-phase_2-FullBuffs-P2-Consumes-ShortSingleTarget" value: { - dps: 586.93871 - tps: 475.20992 + dps: 596.09863 + tps: 482.91058 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-Troll-phase_2-Basic-phase_2-NoBuffs-P2-Consumes-LongMultiTarget" value: { - dps: 412.32511 - tps: 529.29259 + dps: 405.24011 + tps: 523.33977 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-Troll-phase_2-Basic-phase_2-NoBuffs-P2-Consumes-LongSingleTarget" value: { - dps: 412.32511 - tps: 327.01546 + dps: 405.24011 + tps: 321.06264 } } dps_results: { key: "TestShadow-Phase2-Lvl40-Settings-Troll-phase_2-Basic-phase_2-NoBuffs-P2-Consumes-ShortSingleTarget" value: { - dps: 456.71813 - tps: 369.12507 + dps: 465.35137 + tps: 372.09172 } } dps_results: { key: "TestShadow-Phase2-Lvl40-SwitchInFrontOfTarget-Default" value: { - dps: 618.26167 - tps: 493.04169 + dps: 620.47341 + tps: 495.36289 } } dps_results: { key: "TestShadow-Phase3-Lvl50-AllItems-VestmentsoftheVirtuous" value: { - dps: 298.82108 - tps: 238.56474 - hps: 4.65023 + dps: 309.34995 + tps: 247.48837 + hps: 4.80734 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Average-Default" value: { - dps: 1281.42357 - tps: 1029.17891 - hps: 11.8172 + dps: 1284.94113 + tps: 1032.27919 + hps: 11.79392 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-NightElf-phase_3-Basic-phase_3-FullBuffs-P3-Consumes-LongMultiTarget" value: { - dps: 1726.37267 - tps: 1766.56997 - hps: 11.345 + dps: 1709.16108 + tps: 1751.46946 + hps: 11.29946 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-NightElf-phase_3-Basic-phase_3-FullBuffs-P3-Consumes-LongSingleTarget" value: { - dps: 1277.43542 - tps: 1025.29728 - hps: 12.18977 + dps: 1281.62125 + tps: 1029.93207 + hps: 12.01216 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-NightElf-phase_3-Basic-phase_3-FullBuffs-P3-Consumes-ShortSingleTarget" value: { - dps: 1300.70233 - tps: 980.414 - hps: 13.25709 + dps: 1308.60668 + tps: 988.70125 + hps: 12.90415 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-NightElf-phase_3-Basic-phase_3-NoBuffs-P3-Consumes-LongMultiTarget" value: { - dps: 846.70858 - tps: 920.27959 - hps: 6.611 + dps: 823.5955 + tps: 901.22838 + hps: 6.32183 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-NightElf-phase_3-Basic-phase_3-NoBuffs-P3-Consumes-LongSingleTarget" value: { - dps: 722.48049 - tps: 573.28679 - hps: 7.98433 + dps: 710.01705 + tps: 561.89001 + hps: 7.79217 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-NightElf-phase_3-Basic-phase_3-NoBuffs-P3-Consumes-ShortSingleTarget" value: { - dps: 873.56163 - tps: 663.44907 - hps: 10.59667 + dps: 880.36099 + tps: 669.52208 + hps: 10.31042 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-Troll-phase_3-Basic-phase_3-FullBuffs-P3-Consumes-LongMultiTarget" value: { - dps: 1704.92405 - tps: 1744.54468 - hps: 10.98296 + dps: 1685.60598 + tps: 1727.14566 + hps: 11.01256 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-Troll-phase_3-Basic-phase_3-FullBuffs-P3-Consumes-LongSingleTarget" value: { - dps: 1268.61862 - tps: 1019.35976 - hps: 12.01216 + dps: 1279.50141 + tps: 1028.12809 + hps: 12.09869 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-Troll-phase_3-Basic-phase_3-FullBuffs-P3-Consumes-ShortSingleTarget" value: { - dps: 1302.96122 - tps: 983.21613 + dps: 1308.61731 + tps: 989.74416 hps: 12.88138 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-Troll-phase_3-Basic-phase_3-NoBuffs-P3-Consumes-LongMultiTarget" value: { - dps: 832.86134 - tps: 906.45084 - hps: 6.382 + dps: 810.4076 + tps: 887.63244 + hps: 6.27608 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-Troll-phase_3-Basic-phase_3-NoBuffs-P3-Consumes-LongSingleTarget" value: { - dps: 707.95608 - tps: 559.99959 - hps: 7.84917 + dps: 695.48135 + tps: 550.05906 + hps: 7.63758 } } dps_results: { key: "TestShadow-Phase3-Lvl50-Settings-Troll-phase_3-Basic-phase_3-NoBuffs-P3-Consumes-ShortSingleTarget" value: { - dps: 870.66677 - tps: 661.06158 + dps: 879.80179 + tps: 668.77736 hps: 10.31042 } } dps_results: { key: "TestShadow-Phase3-Lvl50-SwitchInFrontOfTarget-Default" value: { - dps: 1272.78351 - tps: 1022.84238 - hps: 12.05315 + dps: 1284.99015 + tps: 1032.77466 + hps: 12.14651 } } dps_results: { diff --git a/sim/shaman/lava_burst.go b/sim/shaman/lava_burst.go index 7626c9d26f..e123e80f34 100644 --- a/sim/shaman/lava_burst.go +++ b/sim/shaman/lava_burst.go @@ -84,13 +84,14 @@ func (shaman *Shaman) newLavaBurstSpellConfig(isOverload bool) core.SpellConfig ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { baseDamage := sim.Roll(baseDamageLow, baseDamageHigh) - damageMultiplier := 1.0 + + damageMultiplier := 0.0 if shaman.useLavaBurstCritScaling { - damageMultiplier *= 1 + shaman.GetStat(stats.SpellCrit)*core.SpellCritRatingPerCritChance/100 + damageMultiplier = shaman.GetStat(stats.SpellCrit) * core.SpellCritRatingPerCritChance / 100 } - spell.DamageMultiplier *= damageMultiplier + spell.DamageMultiplierAdditive += damageMultiplier result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - spell.DamageMultiplier /= damageMultiplier + spell.DamageMultiplierAdditive -= damageMultiplier spell.WaitTravelTime(sim, func(sim *core.Simulation) { spell.DealDamage(sim, result) diff --git a/sim/warlock/dps/TestAffliction.results b/sim/warlock/dps/TestAffliction.results index 02bd90912f..c105652495 100644 --- a/sim/warlock/dps/TestAffliction.results +++ b/sim/warlock/dps/TestAffliction.results @@ -249,9 +249,9 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 2.91832 + weights: 2.96543 weights: 0 - weights: 2.00004 + weights: 1.96256 weights: 0 weights: 0 weights: 0 @@ -259,8 +259,8 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 10.97814 - weights: 21.42464 + weights: 10.55878 + weights: 21.34366 weights: 0 weights: 0 weights: 0 @@ -367,9 +367,9 @@ dps_results: { dps_results: { key: "TestAffliction-Phase3-Lvl50-AllItems-DeathmistRaiment" value: { - dps: 364.72877 - tps: 241.74446 - hps: 160.59939 + dps: 364.69077 + tps: 241.70868 + hps: 160.33128 } } dps_results: { @@ -439,136 +439,136 @@ dps_results: { dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-BloodGuard'sDreadweave" value: { - dps: 844.45204 - tps: 649.16932 + dps: 837.80611 + tps: 642.34162 hps: 261.53768 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-DeathmistRaiment" value: { - dps: 646.7303 - tps: 454.10724 + dps: 645.14768 + tps: 452.49557 hps: 270.79764 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-EmeraldEnchantedVestments" value: { - dps: 844.75629 - tps: 650.26559 + dps: 839.98702 + tps: 645.17724 hps: 261.61803 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-InfernalPactEssence-216509" value: { - dps: 3052.17511 - tps: 2874.92106 - hps: 647.60484 + dps: 3048.2967 + tps: 2871.07193 + hps: 647.62383 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-IronweaveBattlesuit" value: { - dps: 630.33445 - tps: 447.38723 + dps: 628.53701 + tps: 445.18315 hps: 271.7413 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-Kezan'sUnstoppableTaint-231346" value: { - dps: 3129.46577 - tps: 2955.60414 - hps: 645.47369 + dps: 3124.2962 + tps: 2950.35553 + hps: 645.48312 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-Knight-Lieutenant'sDreadweave" value: { - dps: 844.45204 - tps: 649.16932 + dps: 837.80611 + tps: 642.34162 hps: 261.53768 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-MalevolentProphet'sVestments" value: { - dps: 1347.92236 - tps: 1140.52584 + dps: 1342.43588 + tps: 1134.95787 hps: 322.22865 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-AllItems-NightmareProphet'sGarb" value: { - dps: 1325.88624 - tps: 1116.75884 + dps: 1321.50648 + tps: 1111.90605 hps: 320.86936 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-Average-Default" value: { - dps: 3155.67156 - tps: 2980.12974 - hps: 642.47865 + dps: 3151.82255 + tps: 2976.0768 + hps: 642.47761 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-Settings-Orc-affliction-Affliction Warlock-affliction-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 3136.72974 - tps: 4371.12245 - hps: 652.95692 + dps: 3134.63852 + tps: 4368.77991 + hps: 652.92846 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-Settings-Orc-affliction-Affliction Warlock-affliction-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 3136.72974 - tps: 2962.40302 - hps: 652.95692 + dps: 3134.63852 + tps: 2960.34073 + hps: 652.92846 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-Settings-Orc-affliction-Affliction Warlock-affliction-FullBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 2962.64007 - tps: 2757.31274 + dps: 2943.01379 + tps: 2737.32798 hps: 579.79383 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-Settings-Orc-affliction-Affliction Warlock-affliction-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 1484.36206 - tps: 2910.83103 + dps: 1483.41865 + tps: 2905.92662 hps: 356.33254 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-Settings-Orc-affliction-Affliction Warlock-affliction-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 1484.36206 - tps: 1428.13863 + dps: 1483.41865 + tps: 1427.04827 hps: 356.33254 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-Settings-Orc-affliction-Affliction Warlock-affliction-NoBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 1437.11824 - tps: 1354.86812 + dps: 1429.99839 + tps: 1344.64608 hps: 318.51428 } } dps_results: { key: "TestAffliction-Phase4-Lvl60-SwitchInFrontOfTarget-Default" value: { - dps: 3154.87031 - tps: 2980.95864 - hps: 650.50758 + dps: 3151.80551 + tps: 2977.38602 + hps: 650.58947 } } diff --git a/sim/warlock/dps/TestDestruction.results b/sim/warlock/dps/TestDestruction.results index 2720631857..72422d3c32 100644 --- a/sim/warlock/dps/TestDestruction.results +++ b/sim/warlock/dps/TestDestruction.results @@ -393,8 +393,8 @@ stat_weights_results: { dps_results: { key: "TestDestruction-Phase1-Lvl25-AllItems-DeathmistRaiment" value: { - dps: 87.00926 - tps: 45.91668 + dps: 86.87702 + tps: 42.40319 } } dps_results: { diff --git a/sim/warlock/tank/TestAffliction.results b/sim/warlock/tank/TestAffliction.results index 09186b8a75..12c07c197b 100644 --- a/sim/warlock/tank/TestAffliction.results +++ b/sim/warlock/tank/TestAffliction.results @@ -197,9 +197,9 @@ stat_weights_results: { dps_results: { key: "TestAffliction-Phase1-Lvl25-AllItems-DeathmistRaiment" value: { - dps: 127.09166 - tps: 103.96621 - hps: 58.1983 + dps: 120.06911 + tps: 96.16488 + hps: 58.11955 } } dps_results: { diff --git a/sim/warlock/tank/TestDemonology.results b/sim/warlock/tank/TestDemonology.results index 577b3fb86c..2e0782408a 100644 --- a/sim/warlock/tank/TestDemonology.results +++ b/sim/warlock/tank/TestDemonology.results @@ -197,9 +197,9 @@ stat_weights_results: { dps_results: { key: "TestDemonology-Phase2-Lvl40-AllItems-DeathmistRaiment" value: { - dps: 129.6623 - tps: 144.73308 - hps: 107.23702 + dps: 107.53626 + tps: 115.28647 + hps: 106.55339 } } dps_results: { @@ -269,25 +269,25 @@ dps_results: { dps_results: { key: "TestDemonology-Phase4-Lvl60-AllItems-BloodGuard'sDreadweave" value: { - dps: 1179.29768 - tps: 433.61142 - hps: 232.83312 + dps: 1147.38615 + tps: 416.74601 + hps: 228.25902 } } dps_results: { key: "TestDemonology-Phase4-Lvl60-AllItems-DeathmistRaiment" value: { - dps: 110.24914 - tps: 121.33879 + dps: 109.79237 + tps: 120.77467 hps: 4.3855 } } dps_results: { key: "TestDemonology-Phase4-Lvl60-AllItems-EmeraldEnchantedVestments" value: { - dps: 1166.37178 - tps: 430.1719 - hps: 232.49417 + dps: 1150.20075 + tps: 414.38849 + hps: 227.46431 } } dps_results: { @@ -301,8 +301,8 @@ dps_results: { dps_results: { key: "TestDemonology-Phase4-Lvl60-AllItems-IronweaveBattlesuit" value: { - dps: 108.20422 - tps: 119.17866 + dps: 107.76671 + tps: 118.65756 hps: 4.1892 } } @@ -317,25 +317,25 @@ dps_results: { dps_results: { key: "TestDemonology-Phase4-Lvl60-AllItems-Knight-Lieutenant'sDreadweave" value: { - dps: 1179.29768 - tps: 433.61142 - hps: 232.83312 + dps: 1147.38615 + tps: 416.74601 + hps: 228.25902 } } dps_results: { key: "TestDemonology-Phase4-Lvl60-AllItems-MalevolentProphet'sVestments" value: { - dps: 1253.43066 - tps: 1376.93708 - hps: 220.31534 + dps: 1250.81307 + tps: 1353.1845 + hps: 217.82529 } } dps_results: { key: "TestDemonology-Phase4-Lvl60-AllItems-NightmareProphet'sGarb" value: { - dps: 1245.71217 - tps: 1389.78133 - hps: 219.05612 + dps: 1223.38191 + tps: 1337.13652 + hps: 217.87458 } } dps_results: { diff --git a/sim/warlock/tank/TestDestruction.results b/sim/warlock/tank/TestDestruction.results index 90890c74b1..31b25b4578 100644 --- a/sim/warlock/tank/TestDestruction.results +++ b/sim/warlock/tank/TestDestruction.results @@ -393,8 +393,8 @@ stat_weights_results: { dps_results: { key: "TestDestruction-Phase1-Lvl25-AllItems-DeathmistRaiment" value: { - dps: 105.62966 - tps: 68.98748 + dps: 92.67207 + tps: 49.71363 } } dps_results: { @@ -456,8 +456,8 @@ dps_results: { dps_results: { key: "TestDestruction-Phase2-Lvl40-AllItems-DeathmistRaiment" value: { - dps: 143.55913 - tps: 90.73104 + dps: 119.82255 + tps: 58.34481 } } dps_results: { @@ -519,9 +519,9 @@ dps_results: { dps_results: { key: "TestDestruction-Phase3-Lvl50-AllItems-DeathmistRaiment" value: { - dps: 344.34488 - tps: 228.52974 - hps: 162.73233 + dps: 321.19075 + tps: 199.75076 + hps: 161.55267 } } dps_results: { diff --git a/ui/core/proto_utils/action_id.ts b/ui/core/proto_utils/action_id.ts index 883078e927..3419465e36 100644 --- a/ui/core/proto_utils/action_id.ts +++ b/ui/core/proto_utils/action_id.ts @@ -730,6 +730,7 @@ const spellIDsToShowBuffs = new Set([ 461270, // https://www.wowhead.com/classic/spell=461270/magmadars-return 461615, // https://www.wowhead.com/classic/spell=461615/mark-of-chaos 456393, // https://www.wowhead.com/classic/spell=456393/stalked + 1214279, // https://www.wowhead.com/classic/spell=1214279/spell-blasting ]); export const defaultTargetIcon = 'https://wow.zamimg.com/images/wow/icons/large/spell_shadow_metamorphosis.jpg';