Skip to content

Commit

Permalink
update so crit debuffs do not stack for spells (#3736)
Browse files Browse the repository at this point in the history
  • Loading branch information
lime-green committed Sep 23, 2023
1 parent 412e22b commit 61465a9
Show file tree
Hide file tree
Showing 42 changed files with 6,806 additions and 6,826 deletions.
2 changes: 1 addition & 1 deletion sim/common/wotlk/nibelung.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func getSmiteConfig(valkyr *ValkyrPet, spellId int32, damageMin float64, damageM
ThreatMultiplier: 1,
ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
baseDamage := sim.Roll(damageMin, damageMax)
result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeCritFixedChance(0.05))
result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicCrit)
spell.DealDamage(sim, result)
valkyr.GainHealth(sim, valkyr.MaxHealth()*0.25, valkyr.healthMetrics)
},
Expand Down
67 changes: 46 additions & 21 deletions sim/core/debuffs.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,19 @@ func spellDamageEffect(aura *Aura, multiplier float64) *ExclusiveEffect {
})
}

func spellCritBonusEffect(aura *Aura, percent float64) *ExclusiveEffect {
bonusSpellCrit := percent * CritRatingPerCritChance
return aura.NewExclusiveEffect(SpellCritEffectCategory, true, ExclusiveEffect{
Priority: bonusSpellCrit,
OnGain: func(ee *ExclusiveEffect, sim *Simulation) {
ee.Aura.Unit.PseudoStats.BonusSpellCritRatingTaken += bonusSpellCrit
},
OnExpire: func(ee *ExclusiveEffect, sim *Simulation) {
ee.Aura.Unit.PseudoStats.BonusSpellCritRatingTaken -= bonusSpellCrit
},
})
}

func BloodFrenzyAura(target *Unit, points int32) *Aura {
return bloodFrenzySavageCombatAura(target, "Blood Frenzy", ActionID{SpellID: 29859}, points)
}
Expand Down Expand Up @@ -511,16 +524,7 @@ func majorSpellCritDebuffAura(target *Unit, label string, actionID ActionID, per
Duration: time.Second * 30,
})

bonusSpellCrit := percent * CritRatingPerCritChance
aura.NewExclusiveEffect(SpellCritEffectCategory, true, ExclusiveEffect{
Priority: percent,
OnGain: func(ee *ExclusiveEffect, sim *Simulation) {
ee.Aura.Unit.PseudoStats.BonusSpellCritRatingTaken += bonusSpellCrit
},
OnExpire: func(ee *ExclusiveEffect, sim *Simulation) {
ee.Aura.Unit.PseudoStats.BonusSpellCritRatingTaken -= bonusSpellCrit
},
})
spellCritBonusEffect(aura, percent)
return aura
}

Expand Down Expand Up @@ -924,35 +928,56 @@ func increasedMissEffect(aura *Aura, increasedMissChance float64) *ExclusiveEffe
}

func TotemOfWrathDebuff(target *Unit) *Aura {
return minorCritDebuffAura(target, "Totem of Wrath Debuff", ActionID{SpellID: 30708}, time.Minute*5, 3*CritRatingPerCritChance)
return minorCritDebuffAura(target, "Totem of Wrath Debuff", ActionID{SpellID: 30708}, time.Minute*5, 3)
}

func MasterPoisonerDebuff(target *Unit, points int32) *Aura {
return minorCritDebuffAura(target, "Master Poisoner", ActionID{SpellID: 58410}, time.Second*20, float64(points)*CritRatingPerCritChance)
return minorCritDebuffAura(target, "Master Poisoner", ActionID{SpellID: 58410}, time.Second*20, float64(points))
}

func HeartOfTheCrusaderDebuff(target *Unit, points int32) *Aura {
return minorCritDebuffAura(target, "Heart of the Crusader", ActionID{SpellID: 20337}, time.Second*20, float64(points)*CritRatingPerCritChance)
return minorCritDebuffAura(target, "Heart of the Crusader", ActionID{SpellID: 20337}, time.Second*20, float64(points))
}

func minorCritDebuffAura(target *Unit, label string, actionID ActionID, duration time.Duration, critBonus float64) *Aura {
aura := target.GetOrRegisterAura(Aura{
func minorCritDebuffAura(target *Unit, label string, actionID ActionID, duration time.Duration, percent float64) *Aura {
meleeAura := target.GetOrRegisterAura(Aura{
Label: label + "-Melee",
ActionID: actionID,
Duration: duration,
})
spellAura := target.GetOrRegisterAura(Aura{
Label: label + "-Spell",
ActionID: actionID,
Duration: duration,
})
meleeEE := meleeCritBonusEffect(meleeAura, percent)
spellEE := spellCritBonusEffect(spellAura, percent)

compoundAura := target.GetOrRegisterAura(Aura{
Label: label,
ActionID: actionID,
Duration: duration,
OnGain: func(aura *Aura, sim *Simulation) {
meleeEE.Activate(sim)
spellEE.Activate(sim)
},
OnExpire: func(aura *Aura, sim *Simulation) {
meleeEE.Deactivate(sim)
spellEE.Deactivate(sim)
},
})
critBonusEffect(aura, critBonus)
return aura
return compoundAura
}

func critBonusEffect(aura *Aura, critBonus float64) *ExclusiveEffect {
return aura.NewExclusiveEffect("CritBonus", false, ExclusiveEffect{
func meleeCritBonusEffect(aura *Aura, percent float64) *ExclusiveEffect {
critBonus := percent * CritRatingPerCritChance
return aura.NewExclusiveEffect("MeleeCritBonus", false, ExclusiveEffect{
Priority: critBonus,
OnGain: func(ee *ExclusiveEffect, sim *Simulation) {
ee.Aura.Unit.PseudoStats.BonusCritRatingTaken += critBonus
ee.Aura.Unit.PseudoStats.BonusMeleeCritRatingTaken += critBonus
},
OnExpire: func(ee *ExclusiveEffect, sim *Simulation) {
ee.Aura.Unit.PseudoStats.BonusCritRatingTaken -= critBonus
ee.Aura.Unit.PseudoStats.BonusMeleeCritRatingTaken -= critBonus
},
})
}
Expand Down
42 changes: 0 additions & 42 deletions sim/core/spell_outcome.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,44 +126,6 @@ func (spell *Spell) OutcomeHealingCrit(sim *Simulation, result *SpellResult, att
}
}

func (spell *Spell) OutcomeCritFixedChance(critChance float64) OutcomeApplier {
return func(sim *Simulation, result *SpellResult, attackTable *AttackTable) {
if spell.CritMultiplier == 0 {
panic("Spell " + spell.ActionID.String() + " missing CritMultiplier")
}
if spell.fixedCritCheck(sim, critChance) {
result.Outcome = OutcomeCrit
result.Damage *= spell.CritMultiplier
spell.SpellMetrics[result.Target.UnitIndex].Crits++
} else {
result.Outcome = OutcomeHit
spell.SpellMetrics[result.Target.UnitIndex].Hits++
}
}
}

func (spell *Spell) OutcomeMagicCritFixedChance(critChance float64) OutcomeApplier {
return func(sim *Simulation, result *SpellResult, attackTable *AttackTable) {
if spell.CritMultiplier == 0 {
panic("Spell " + spell.ActionID.String() + " missing CritMultiplier")
}
if spell.MagicHitCheck(sim, attackTable) {
if spell.fixedCritCheck(sim, critChance) {
result.Outcome = OutcomeCrit
result.Damage *= spell.CritMultiplier
spell.SpellMetrics[result.Target.UnitIndex].Crits++
} else {
result.Outcome = OutcomeHit
spell.SpellMetrics[result.Target.UnitIndex].Hits++
}
} else {
result.Outcome = OutcomeMiss
result.Damage = 0
spell.SpellMetrics[result.Target.UnitIndex].Misses++
}
}
}

func (spell *Spell) OutcomeTickMagicHit(sim *Simulation, result *SpellResult, attackTable *AttackTable) {
if spell.MagicHitCheck(sim, attackTable) {
result.Outcome = OutcomeHit
Expand Down Expand Up @@ -410,10 +372,6 @@ func (spell *Spell) OutcomeEnemyMeleeWhite(sim *Simulation, result *SpellResult,
}
}

func (spell *Spell) fixedCritCheck(sim *Simulation, critChance float64) bool {
return sim.RandomFloat("Fixed Crit Roll") < critChance
}

func (result *SpellResult) applyAttackTableMiss(spell *Spell, attackTable *AttackTable, roll float64, chance *float64) bool {
missChance := attackTable.BaseMissChance - spell.PhysicalHitChance(attackTable)
if spell.Unit.AutoAttacks.IsDualWielding && !spell.Unit.PseudoStats.DisableDWMissPenalty {
Expand Down
3 changes: 1 addition & 2 deletions sim/core/spell_result.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (spell *Spell) PhysicalHitChance(attackTable *AttackTable) float64 {
func (spell *Spell) PhysicalCritChance(attackTable *AttackTable) float64 {
critRating := spell.Unit.stats[stats.MeleeCrit] +
spell.BonusCritRating +
attackTable.Defender.PseudoStats.BonusCritRatingTaken
attackTable.Defender.PseudoStats.BonusMeleeCritRatingTaken
return critRating/(CritRatingPerCritChance*100) - attackTable.CritSuppression
}
func (spell *Spell) PhysicalCritCheck(sim *Simulation, attackTable *AttackTable) bool {
Expand Down Expand Up @@ -131,7 +131,6 @@ func (spell *Spell) MagicHitCheck(sim *Simulation, attackTable *AttackTable) boo
func (spell *Spell) spellCritRating(target *Unit) float64 {
return spell.Unit.stats[stats.SpellCrit] +
spell.BonusCritRating +
target.PseudoStats.BonusCritRatingTaken +
target.PseudoStats.BonusSpellCritRatingTaken
}
func (spell *Spell) SpellCritChance(target *Unit) float64 {
Expand Down
4 changes: 2 additions & 2 deletions sim/core/stats/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,8 @@ type PseudoStats struct {
ReducedCritTakenChance float64 // Reduces chance to be crit.

BonusRangedAttackPowerTaken float64 // Hunters mark
BonusSpellCritRatingTaken float64 // Imp Shadow Bolt / Imp Scorch / Winter's Chill debuff
BonusCritRatingTaken float64 // Totem of Wrath / Master Poisoner / Heart of the Crusader
BonusSpellCritRatingTaken float64 // Imp Shadow Bolt / Imp Scorch / Winter's Chill debuff + Totem of Wrath / Master Poisoner / Heart of the Crusader
BonusMeleeCritRatingTaken float64 // Totem of Wrath / Master Poisoner / Heart of the Crusader
BonusMeleeHitRatingTaken float64 // Formerly Imp FF and SW Radiance;
BonusSpellHitRatingTaken float64 // Imp FF

Expand Down
Loading

0 comments on commit 61465a9

Please sign in to comment.