Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update so crit debuffs do not stack for spells #3736

Merged
merged 1 commit into from
Sep 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading