Skip to content

Commit

Permalink
implement Righteous Fury + Hand of Reckoning
Browse files Browse the repository at this point in the history
  • Loading branch information
wsphillips committed Sep 15, 2024
1 parent e66efed commit 09a3e29
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 13 deletions.
25 changes: 12 additions & 13 deletions sim/core/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,12 @@ func (character *Character) applyHealingModel(healingModel *proto.HealingModel)

healthMetrics := character.NewHealthMetrics(ActionID{OtherID: proto.OtherAction_OtherActionHealingModel})

// Dummy spell for healing callback
healingModelSpell := character.RegisterSpell(SpellConfig{
ActionID: ActionID{OtherID: proto.OtherAction_OtherActionHealingModel},
})

character.RegisterResetEffect(func(sim *Simulation) {
// Hack since we don't have OnHealingReceived aura handlers yet.
//ardentDefenderAura := character.GetAura("Ardent Defender")
willOfTheNecropolisAura := character.GetAura("Will of The Necropolis")

// Initialize randomized cadence model
timeToNextHeal := DurationFromSeconds(0.0)
Expand All @@ -171,18 +173,15 @@ func (character *Character) applyHealingModel(healingModel *proto.HealingModel)
pa.OnAction = func(sim *Simulation) {
// Use modeled HPS to scale heal per tick based on random cadence
healPerTick = healingModel.Hps * (float64(timeToNextHeal) / float64(time.Second))

totalHeal := healPerTick * character.PseudoStats.HealingTakenMultiplier
// Execute the heal
character.GainHealth(sim, healPerTick*character.PseudoStats.HealingTakenMultiplier, healthMetrics)
character.GainHealth(sim, totalHeal, healthMetrics)

// Might use this again in the future to track "absorb" metrics but currently disabled
//if ardentDefenderAura != nil && character.CurrentHealthPercent() >= 0.35 {
// ardentDefenderAura.Deactivate(sim)
//}

if willOfTheNecropolisAura != nil && character.CurrentHealthPercent() > 0.35 {
willOfTheNecropolisAura.Deactivate(sim)
}
// Callback that can be used by tank specs
result := healingModelSpell.NewResult(&character.Unit)
result.Damage = totalHeal
character.OnHealTaken(sim, healingModelSpell, result)
healingModelSpell.DisposeResult(result)

// Random roll for time to next heal. In the case where CadenceVariation exceeds CadenceSeconds, then
// CadenceSeconds is treated as the median, with two separate uniform distributions to the left and right
Expand Down
1 change: 1 addition & 0 deletions sim/paladin/paladin.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func (paladin *Paladin) AddPartyBuffs(_ *proto.PartyBuffs) {
}

func (paladin *Paladin) Initialize() {
paladin.registerRighteousFury()
// Judgement and Seals
paladin.registerJudgement()

Expand Down
71 changes: 71 additions & 0 deletions sim/paladin/righteous_fury.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package paladin

import (
"github.com/wowsims/sod/sim/core"
"github.com/wowsims/sod/sim/core/proto"
)

func (paladin *Paladin) registerRighteousFury() {
if !paladin.Options.RighteousFury {
return
}
horRune := proto.PaladinRune_RuneHandsHandOfReckoning
hasHoR := paladin.hasRune(horRune)
actionID := core.ActionID{SpellID: core.TernaryInt32(hasHoR, int32(horRune), 25780)}

rfThreatMultiplier := 0.6 + core.TernaryFloat64(hasHoR, 0.2, 0.0)
// Improved Righteous Fury is multiplicative.
rfThreatMultiplier *= 1.0 + []float64{0.0, 0.16, 0.33, 0.5}[paladin.Talents.ImprovedRighteousFury]

paladin.OnSpellRegistered(func(spell *core.Spell) {
if spell.SpellSchool.Matches(core.SpellSchoolHoly) {
spell.ThreatMultiplier *= 1.0 + rfThreatMultiplier
}
})

if !hasHoR { // This is just a visual/UI indicator when we don't have HoR rune.
paladin.RegisterAura(core.Aura{
Label: "Righetous Fury",
ActionID: actionID,
Duration: core.NeverExpires, // 30 minutes without HoR rune, but no need to model
OnReset: func(aura *core.Aura, sim *core.Simulation) {
aura.Activate(sim)
},
})
} else {
// Passive effects granted by Hand of Reckoning rune.

// Damage which takes you below 35% health is reduced by 20% (DR component of WotLK's Ardent Defender)
rfDamageReduction := 0.2

handler := func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) {
incomingDamage := result.Damage
if (paladin.CurrentHealth()-incomingDamage)/paladin.MaxHealth() <= 0.35 {
result.Damage -= (paladin.MaxHealth()*0.35 - (paladin.CurrentHealth() - incomingDamage)) * rfDamageReduction
if sim.Log != nil {
paladin.Log(sim, "Righteous Fury absorbs %d damage", int32(incomingDamage-result.Damage))
}
}
}

paladin.AddDynamicDamageTakenModifier(handler)

// Gives you mana when healed by other friendly targets' spells equal to 25% of the amount healed.
horManaMetrics := paladin.NewManaMetrics(actionID)

paladin.RegisterAura(core.Aura{
Label: "Righteous Fury",
ActionID: core.ActionID{SpellID: 407627},
Duration: core.NeverExpires,
OnReset: func(aura *core.Aura, sim *core.Simulation) {
aura.Activate(sim)
},
OnHealTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) {
if spell.IsOtherAction(proto.OtherAction_OtherActionHealingModel) {
manaGained := result.Damage * 0.25
paladin.AddMana(sim, manaGained, horManaMetrics)
}
},
})
} // else
}

0 comments on commit 09a3e29

Please sign in to comment.