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

add TreatAsPeriodic, update warlock 4pT3 #1309

Merged
merged 1 commit into from
Feb 17, 2025
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
11 changes: 6 additions & 5 deletions sim/core/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ const (
SpellFlagNotAProc // Indicates the proc is not treated as a proc (Seal of Command)
SpellFlagSwapped // Indicates that this spell is not useable because it is from a currently swapped item
SpellFlagNoSpellMods // Indicates that no spell mods should be applied to this spell
SpellFlagTreatAsPeriodic // Indicates that the spell deals non-DoT damage but is treated a periodic. Equivalent to the "Treat as Periodic" flag in-game

// Used to let agents categorize their spells.
SpellFlagAgentReserved1
Expand All @@ -216,12 +217,12 @@ const (
type DispelType uint64

const (
DispelType_None DispelType = 0
DispelType_Poison DispelType = 1 << iota
DispelType_Disease
DispelType_Curse
DispelType_None DispelType = 0
DispelType_Poison DispelType = 1 << iota
DispelType_Disease
DispelType_Curse
DispelType_Magic
DispelType_Enrage
DispelType_Enrage
)

/*
Expand Down
129 changes: 61 additions & 68 deletions sim/core/spell_outcome.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,31 +109,23 @@ func (spell *Spell) OutcomeMagicHitAndCritNoHitCounter(sim *Simulation, result *
}
func (spell *Spell) outcomeMagicHitAndCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) {
isPartialResist := result.DidResist()
if spell.MagicHitCheck(sim, attackTable) {
if spell.MagicCritCheck(sim, result.Target) {
didHit := spell.MagicHitCheck(sim, attackTable)
didCrit := didHit && spell.MagicCritCheck(sim, result.Target)

if didHit {
if didCrit {
result.Outcome = OutcomeCrit
result.Damage *= spell.CritMultiplier(attackTable)
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Crits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedCrits++
}
}
} else {
result.Outcome = OutcomeHit
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Hits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedHits++
}
}
}
} else {
result.Outcome = OutcomeMiss
result.Damage = 0
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Misses++
}
}

if countHits {
result.applyMagicOutcome(spell, didHit, didCrit, isPartialResist)
}
}

Expand All @@ -145,24 +137,17 @@ func (spell *Spell) OutcomeMagicCritNoHitCounter(sim *Simulation, result *SpellR
}
func (spell *Spell) outcomeMagicCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) {
isPartialResist := result.DidResist()
didCrit := spell.MagicCritCheck(sim, result.Target)

if spell.MagicCritCheck(sim, result.Target) {
if didCrit {
result.Outcome = OutcomeCrit
result.Damage *= spell.CritMultiplier(attackTable)
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Crits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedCrits++
}
}
} else {
result.Outcome = OutcomeHit
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Hits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedHits++
}
}
}

if countHits {
result.applyMagicOutcome(spell, true, didCrit, isPartialResist)
}
}

Expand All @@ -173,13 +158,8 @@ func (spell *Spell) OutcomeHealingNoHitCounter(_ *Simulation, result *SpellResul
spell.outcomeHealing(nil, result, nil, false)
}
func (spell *Spell) outcomeHealing(_ *Simulation, result *SpellResult, _ *AttackTable, countHits bool) {
isPartialResist := result.DidResist()
result.Outcome = OutcomeHit
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Hits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedHits++
}
result.applyMagicOutcome(spell, true, false, false)
}
}

Expand All @@ -190,34 +170,17 @@ func (spell *Spell) OutcomeHealingCritNoHitCounter(sim *Simulation, result *Spel
spell.outcomeHealingCrit(sim, result, attackTable, false)
}
func (spell *Spell) outcomeHealingCrit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) {
isPartialResist := result.DidResist()
didCrit := spell.HealingCritCheck(sim)

if spell.HealingCritCheck(sim) {
if didCrit {
result.Outcome = OutcomeCrit
result.Damage *= spell.CritMultiplier(attackTable)
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Crits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedCrits++
}
}
} else {
result.Outcome = OutcomeHit
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Hits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedHits++
}
}
}
}

func (spell *Spell) OutcomeTickMagicHit(sim *Simulation, result *SpellResult, attackTable *AttackTable) {
if spell.MagicHitCheck(sim, attackTable) {
result.Outcome = OutcomeHit
} else {
result.Outcome = OutcomeMiss
result.Damage = 0
if countHits {
result.applyMagicOutcome(spell, true, didCrit, false)
}
}

Expand All @@ -228,20 +191,50 @@ func (spell *Spell) OutcomeMagicHitNoHitCounter(sim *Simulation, result *SpellRe
spell.outcomeMagicHit(sim, result, attackTable, false)
}
func (spell *Spell) outcomeMagicHit(sim *Simulation, result *SpellResult, attackTable *AttackTable, countHits bool) {
if spell.MagicHitCheck(sim, attackTable) {
isPartialResist := result.DidResist()
isPartialResist := result.DidResist()
didHit := spell.MagicHitCheck(sim, attackTable)

if didHit {
result.Outcome = OutcomeHit
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Hits++
} else {
result.Outcome = OutcomeMiss
result.Damage = 0
}

if countHits {
result.applyMagicOutcome(spell, didHit, false, isPartialResist)
}
}

func (result *SpellResult) applyMagicOutcome(spell *Spell, didHit bool, didCrit bool, isPartialResist bool) {
if !didHit {
spell.SpellMetrics[result.Target.UnitIndex].Misses++
return
}

if spell.Flags.Matches(SpellFlagTreatAsPeriodic) {
if didCrit {
spell.SpellMetrics[result.Target.UnitIndex].CritTicks++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedHits++
spell.SpellMetrics[result.Target.UnitIndex].ResistedCritTicks++
}
} else {
spell.SpellMetrics[result.Target.UnitIndex].Ticks++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedTicks++
}
}
} else {
result.Outcome = OutcomeMiss
result.Damage = 0
if countHits {
spell.SpellMetrics[result.Target.UnitIndex].Misses++
if didCrit {
spell.SpellMetrics[result.Target.UnitIndex].Crits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedCrits++
}
} else {
spell.SpellMetrics[result.Target.UnitIndex].Hits++
if isPartialResist {
spell.SpellMetrics[result.Target.UnitIndex].ResistedHits++
}
}
}
}
Expand Down Expand Up @@ -691,11 +684,11 @@ func (result *SpellResult) applyAttackTableMissNoDWPenalty(spell *Spell, attackT
func (result *SpellResult) applyAttackTableBlock(spell *Spell, attackTable *AttackTable, roll float64, chance *float64, countHits bool) bool {
*chance += attackTable.BaseBlockChance
if roll < *chance {
isCrit := result.DidCrit()
didCrit := result.DidCrit()
isPartialResist := result.DidResist()
result.Outcome |= OutcomeBlock
if countHits {
if isCrit {
if didCrit {
spell.SpellMetrics[result.Target.UnitIndex].BlockedCrits++
spell.SpellMetrics[result.Target.UnitIndex].Crits--
if isPartialResist {
Expand Down
1 change: 1 addition & 0 deletions sim/core/spell_result.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ func (spell *Spell) CalcAndDealOutcome(sim *Simulation, target *Unit, outcomeApp

// Applies the fully computed spell result to the sim.
func (spell *Spell) dealDamageInternal(sim *Simulation, isPeriodic bool, result *SpellResult) {
isPeriodic = isPeriodic || spell.Flags.Matches(SpellFlagTreatAsPeriodic)
isPartialResist := result.DidResist()

if sim.CurrentTime >= 0 {
Expand Down
83 changes: 48 additions & 35 deletions sim/warlock/item_sets_pve_phase_7.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,38 +49,54 @@ func (warlock *Warlock) applyNaxxramasDamage4PBonus() {
return
}

copiedSpellConfig := []struct {
ClassMask int64
SpellID int32
SpellSchool core.SpellSchool
Flags core.SpellFlag
}{
{
ClassMask: ClassSpellMask_WarlockCorruption,
SpellID: 1219428,
SpellSchool: core.SpellSchoolShadow,
Flags: WarlockFlagAffliction,
},
{
ClassMask: ClassSpellMask_WarlockImmolate,
SpellID: 1219425,
SpellSchool: core.SpellSchoolFire,
Flags: WarlockFlagDestruction,
},
{
ClassMask: ClassSpellMask_WarlockShadowflame,
SpellID: 1219429,
SpellSchool: core.SpellSchoolShadow | core.SpellSchoolFire,
Flags: WarlockFlagAffliction | WarlockFlagDestruction,
},
{
ClassMask: ClassSpellMask_WarlockUnstableAffliction,
SpellID: 1219436,
SpellSchool: core.SpellSchoolShadow,
Flags: WarlockFlagAffliction,
},
}

dotSpellsMap := make(map[int64]*core.Spell)

copiedCorruptionConfig := warlock.getCorruptionConfig(CorruptionRanks)
copiedCorruptionConfig.ActionID.SpellID = 1219428
copiedCorruptionConfig.Dot.Aura.Label = copiedCorruptionConfig.Dot.Aura.Label + "-4pT3"
copiedCorruptionConfig.Flags ^= core.SpellFlagAPL | core.SpellFlagResetAttackSwing
copiedCorruptionConfig.Flags |= core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell
dotSpellsMap[ClassSpellMask_WarlockCorruption] = warlock.RegisterSpell(copiedCorruptionConfig)

copiedImmolateConfig := warlock.getImmolateConfig(ImmolateRanks)
copiedImmolateConfig.ActionID.SpellID = 1219425
copiedImmolateConfig.Dot.Aura.Label = copiedImmolateConfig.Dot.Aura.Label + "-4pT3"
copiedImmolateConfig.Flags ^= core.SpellFlagAPL | core.SpellFlagResetAttackSwing
copiedImmolateConfig.Flags |= core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell
dotSpellsMap[ClassSpellMask_WarlockImmolate] = warlock.RegisterSpell(copiedImmolateConfig)

if warlock.HasRune(proto.WarlockRune_RuneBootsShadowflame) {
copiedShadowflameConfig := warlock.getShadowflameConfig()
copiedShadowflameConfig.ActionID.SpellID = 1219429
copiedShadowflameConfig.Dot.Aura.Label = copiedShadowflameConfig.Dot.Aura.Label + "-4pT3"
copiedShadowflameConfig.Flags ^= core.SpellFlagAPL | core.SpellFlagResetAttackSwing
copiedShadowflameConfig.Flags |= core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell
dotSpellsMap[ClassSpellMask_WarlockShadowflame] = warlock.RegisterSpell(copiedShadowflameConfig)
}
for _, spellConfig := range copiedSpellConfig {
dotSpellsMap[spellConfig.ClassMask] = warlock.RegisterSpell(core.SpellConfig{
ActionID: core.ActionID{SpellID: spellConfig.SpellID},
ClassSpellMask: spellConfig.ClassMask,
SpellSchool: spellConfig.SpellSchool,
DefenseType: core.DefenseTypeMagic,
ProcMask: core.ProcMaskSpellDamage,
Flags: core.SpellFlagTreatAsPeriodic | core.SpellFlagPureDot | core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell | WarlockFlagHaunt | spellConfig.Flags,

DamageMultiplier: 1,
ThreatMultiplier: 1,

if warlock.HasRune(proto.WarlockRune_RuneBracerUnstableAffliction) {
copiedUnstableAfflictionConfig := warlock.getUnstableAfflictionConfig()
copiedUnstableAfflictionConfig.ActionID.SpellID = 1219436
copiedUnstableAfflictionConfig.Dot.Aura.Label = copiedUnstableAfflictionConfig.Dot.Aura.Label + "-4pT3"
copiedUnstableAfflictionConfig.Flags ^= core.SpellFlagAPL | core.SpellFlagResetAttackSwing
copiedUnstableAfflictionConfig.Flags |= core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell
dotSpellsMap[ClassSpellMask_WarlockUnstableAffliction] = warlock.RegisterSpell(copiedUnstableAfflictionConfig)
ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {},
})
}

var affectedDotSpells []*core.Spell
Expand All @@ -101,12 +117,9 @@ func (warlock *Warlock) applyNaxxramasDamage4PBonus() {
if spell.Matches(ClassSpellMask_WarlockAll) && result.DidCrit() {
for _, spell := range affectedDotSpells {
if dot := spell.Dot(result.Target); dot.IsActive() {
copiedDoT := dotSpellsMap[spell.ClassSpellMask].Dot(result.Target)
copiedDoT.SnapshotBaseDamage = dot.SnapshotBaseDamage
copiedDoT.SnapshotAttackerMultiplier = dot.SnapshotAttackerMultiplier
copiedDoT.Apply(sim)
copiedDoT.TickOnce(sim)
copiedDoT.Deactivate(sim)
copiedDoTSpell := dotSpellsMap[spell.ClassSpellMask]
copiedDoTSpell.Cast(sim, result.Target)
copiedDoTSpell.CalcAndDealDamage(sim, result.Target, dot.SnapshotBaseDamage, copiedDoTSpell.OutcomeMagicCrit)
}
}
}
Expand Down
Loading