diff --git a/sim/paladin/lay_on_hands.go b/sim/paladin/lay_on_hands.go new file mode 100644 index 0000000000..fb0d532fbc --- /dev/null +++ b/sim/paladin/lay_on_hands.go @@ -0,0 +1,58 @@ +package paladin + +import ( + "slices" + "time" + + "github.com/wowsims/sod/sim/core" +) + +func (paladin *Paladin) registerLayOnHands() { + + minLevels := []int32{50, 30, 10} + idx := slices.IndexFunc(minLevels, func(level int32) bool { + return paladin.Level >= level + }) + + if idx == -1 { + return + } + + spellID := []int32{10310, 2800, 633}[idx] + manaReturn := []float64{550, 250, 0}[idx] + + // Only register the highest available rank of LoH (no benefit to using lower ranks) + actionID := core.ActionID{SpellID: spellID} + layOnHandsManaMetrics := paladin.NewManaMetrics(actionID) + layOnHandsHealthMetrics := paladin.NewHealthMetrics(actionID) + layOnHands := paladin.RegisterSpell(core.SpellConfig{ + ActionID: actionID, + ProcMask: core.ProcMaskSpellHealing, + Flags: core.SpellFlagAPL | core.SpellFlagMCD, + SpellSchool: core.SpellSchoolHoly, + SpellCode: SpellCode_PaladinLayOnHands, + Cast: core.CastConfig{ + DefaultCast: core.Cast{ + GCD: core.GCDDefault, + }, + CD: core.Cooldown{ + Timer: paladin.NewTimer(), + Duration: time.Minute * time.Duration(60-10*paladin.Talents.ImprovedLayOnHands), + }, + }, + ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { + paladin.SpendMana(sim, paladin.CurrentMana(), layOnHandsManaMetrics) + paladin.GainHealth(sim, paladin.MaxHealth(), layOnHandsHealthMetrics) + paladin.AddMana(sim, manaReturn, layOnHandsManaMetrics) + }, + }) + + paladin.AddMajorCooldown(core.MajorCooldown{ + Spell: layOnHands, + Priority: core.CooldownPriorityBloodlust, + Type: core.CooldownTypeSurvival, + ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { + return character.CurrentHealthPercent() < 0.1 // TODO: better default condition + }, + }) +} diff --git a/sim/paladin/paladin.go b/sim/paladin/paladin.go index 4c3087538e..f8d8bd3284 100644 --- a/sim/paladin/paladin.go +++ b/sim/paladin/paladin.go @@ -27,6 +27,7 @@ const ( SpellCode_PaladinAvengersShield SpellCode_PaladinHolyShield SpellCode_PaladinHolyShieldProc + SpellCode_PaladinLayOnHands ) type SealJudgeCode uint8 @@ -141,6 +142,7 @@ func (paladin *Paladin) Initialize() { paladin.registerAuraMastery() paladin.registerHolyShield() paladin.registerShieldOfRighteousness() + paladin.registerLayOnHands() paladin.enableMultiJudge = true // change this to baseline false when P5 launches paladin.lingerDuration = time.Millisecond * 400 diff --git a/sim/paladin/talents.go b/sim/paladin/talents.go index efee0a9c80..4c2e889d45 100644 --- a/sim/paladin/talents.go +++ b/sim/paladin/talents.go @@ -41,6 +41,7 @@ func (paladin *Paladin) ApplyTalents() { paladin.applyRedoubt() paladin.applyReckoning() + paladin.applyImprovedLayOnHands() } func (paladin *Paladin) improvedSoR() float64 { @@ -207,3 +208,29 @@ func (paladin *Paladin) applyVindication() { }, }) } + +func (paladin *Paladin) applyImprovedLayOnHands() { + + if paladin.Talents.ImprovedLayOnHands > 0 { + + armorMultiplier := []float64{1, 1.15, 1.3}[paladin.Talents.ImprovedLayOnHands] + auraID := []int32{0, 20233, 20236}[paladin.Talents.ImprovedLayOnHands] + + paladin.RegisterAura(core.Aura{ + Label: "Lay on Hands", + ActionID: core.ActionID{SpellID: auraID}, + Duration: time.Minute * 2, + OnGain: func(aura *core.Aura, sim *core.Simulation) { + paladin.ApplyDynamicEquipScaling(sim, stats.Armor, armorMultiplier) + }, + OnExpire: func(aura *core.Aura, sim *core.Simulation) { + paladin.RemoveDynamicEquipScaling(sim, stats.Armor, armorMultiplier) + }, + OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { + if spell.SpellCode == SpellCode_PaladinLayOnHands { + aura.Activate(sim) + } + }, + }) + } +}