Skip to content

Commit

Permalink
warlock: implement infernal
Browse files Browse the repository at this point in the history
  • Loading branch information
Tharre committed Dec 16, 2022
1 parent 886609c commit 7411bc8
Show file tree
Hide file tree
Showing 23 changed files with 403 additions and 189 deletions.
1 change: 1 addition & 0 deletions proto/warlock.proto
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ message Warlock {
bool detonate_seed = 6;
SpecSpell spec_spell = 7;
Type type = 8;
bool use_infernal = 9;
}

Rotation rotation = 1;
Expand Down
2 changes: 1 addition & 1 deletion sim/warlock/chaos_bolt.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (warlock *Warlock) registerChaosBoltSpell() {
},

BonusCritRating: 0 +
warlock.masterDemonologistFireCrit() +
warlock.masterDemonologistFireCrit +
core.TernaryFloat64(warlock.Talents.Devastation, 1, 0)*5*core.CritRatingPerCritChance,
DamageMultiplierAdditive: 1 +
warlock.GrandFirestoneBonus() +
Expand Down
2 changes: 1 addition & 1 deletion sim/warlock/conflagrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (warlock *Warlock) registerConflagrateSpell() {
},

BonusCritRating: 0 +
warlock.masterDemonologistFireCrit() +
warlock.masterDemonologistFireCrit +
core.TernaryFloat64(warlock.Talents.Devastation, 5*core.CritRatingPerCritChance, 0) +
5*float64(warlock.Talents.FireAndBrimstone)*core.CritRatingPerCritChance,
DamageMultiplierAdditive: 1 +
Expand Down
2 changes: 1 addition & 1 deletion sim/warlock/corruption.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (warlock *Warlock) registerCorruptionSpell() {
},

BonusCritRating: 0 +
warlock.masterDemonologistShadowCrit() +
warlock.masterDemonologistShadowCrit +
3*float64(warlock.Talents.Malediction)*core.CritRatingPerCritChance +
core.TernaryFloat64(warlock.HasSetBonus(ItemSetDarkCovensRegalia, 2), 5*core.CritRatingPerCritChance, 0),
DamageMultiplierAdditive: 1 +
Expand Down
4 changes: 1 addition & 3 deletions sim/warlock/demonic_empowerment.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ func (warlock *Warlock) registerDemonicEmpowermentSpell() {
}

if warlock.Options.Summon != proto.Warlock_Options_NoSummon {
warlock.Pet.DemonicEmpowermentAura = warlock.Pet.RegisterAura(
petAura,
)
warlock.Pet.DemonicEmpowermentAura = warlock.Pet.RegisterAura(petAura)
}

warlock.DemonicEmpowerment = warlock.RegisterSpell(core.SpellConfig{
Expand Down
2 changes: 1 addition & 1 deletion sim/warlock/haunt.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (warlock *Warlock) registerHauntSpell() {
},

BonusCritRating: 0 +
warlock.masterDemonologistShadowCrit(),
warlock.masterDemonologistShadowCrit,
DamageMultiplierAdditive: 1 +
warlock.GrandFirestoneBonus() +
0.03*float64(warlock.Talents.ShadowMastery),
Expand Down
2 changes: 1 addition & 1 deletion sim/warlock/immolate.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (warlock *Warlock) registerImmolateSpell() {
},

BonusCritRating: 0 +
warlock.masterDemonologistFireCrit() +
warlock.masterDemonologistFireCrit +
core.TernaryFloat64(warlock.Talents.Devastation, 5*core.CritRatingPerCritChance, 0),
DamageMultiplierAdditive: 1 +
warlock.GrandFirestoneBonus() +
Expand Down
2 changes: 1 addition & 1 deletion sim/warlock/incinerate.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (warlock *Warlock) registerIncinerateSpell() {
},

BonusCritRating: 0 +
warlock.masterDemonologistFireCrit() +
warlock.masterDemonologistFireCrit +
core.TernaryFloat64(warlock.Talents.Devastation, 5*core.CritRatingPerCritChance, 0) +
core.TernaryFloat64(warlock.HasSetBonus(ItemSetDeathbringerGarb, 4), 5*core.CritRatingPerCritChance, 0) +
core.TernaryFloat64(warlock.HasSetBonus(ItemSetDarkCovensRegalia, 2), 5*core.CritRatingPerCritChance, 0),
Expand Down
203 changes: 203 additions & 0 deletions sim/warlock/inferno.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package warlock

import (
"math"
"time"

"github.com/wowsims/wotlk/sim/core"
"github.com/wowsims/wotlk/sim/core/proto"
"github.com/wowsims/wotlk/sim/core/stats"
)

func (warlock *Warlock) registerInfernoSpell() {
if !warlock.Rotation.UseInfernal {
return
}

summonInfernalAura := warlock.RegisterAura(core.Aura{
Label: "Summon Infernal",
ActionID: core.ActionID{SpellID: 1122},
Duration: time.Second * 60,
})

baseCost := 0.8 * warlock.BaseMana
warlock.Inferno = warlock.RegisterSpell(core.SpellConfig{
ActionID: core.ActionID{SpellID: 1122},
SpellSchool: core.SpellSchoolFire,
ProcMask: core.ProcMaskEmpty,
ResourceType: stats.Mana,
BaseCost: baseCost,

Cast: core.CastConfig{
DefaultCast: core.Cast{
CastTime: time.Millisecond * 1500,
Cost: baseCost,
GCD: core.GCDDefault,
},
CD: core.Cooldown{
Timer: warlock.NewTimer(),
Duration: time.Second * time.Duration(600),
},
},

DamageMultiplier: 1,
ThreatMultiplier: 1,
CritMultiplier: warlock.SpellCritMultiplier(1, 0),
ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
// TODO: add fire spell damage
baseDmg := (200 + 1*spell.SpellPower()) * sim.Encounter.AOECapMultiplier()

for _, aoeTarget := range sim.Encounter.Targets {
spell.CalcAndDealDamage(sim, &aoeTarget.Unit, baseDmg, spell.OutcomeMagicHitAndCrit)
}

warlock.Pet.Disable(sim)
warlock.Infernal.EnableWithTimeout(sim, warlock.Infernal, time.Second*60)

// fake aura to show duration
summonInfernalAura.Activate(sim)
},
})

warlock.AddMajorCooldown(core.MajorCooldown{
Spell: warlock.Inferno,
Type: core.CooldownTypeDPS,
ShouldActivate: func(sim *core.Simulation, character *core.Character) bool {
return sim.GetRemainingDuration() <= 61*time.Second
},
})
}

type InfernalPet struct {
core.Pet
owner *Warlock
immolationAura *core.Spell
}

func (warlock *Warlock) NewInfernal() *InfernalPet {
statInheritance :=
func(ownerStats stats.Stats) stats.Stats {
ownerHitChance := math.Floor(ownerStats[stats.SpellHit] / core.SpellHitRatingPerHitChance)

// TODO: account for fire spell damage
return stats.Stats{
stats.Stamina: ownerStats[stats.Stamina] * 0.75,
stats.Intellect: ownerStats[stats.Intellect] * 0.3,
stats.Armor: ownerStats[stats.Armor] * 0.35,
stats.AttackPower: ownerStats[stats.SpellPower] * 0.57,
stats.SpellPower: ownerStats[stats.SpellPower] * 0.15,
stats.SpellPenetration: ownerStats[stats.SpellPenetration],
stats.MeleeHit: ownerHitChance * core.MeleeHitRatingPerHitChance,
stats.SpellHit: ownerHitChance * core.SpellHitRatingPerHitChance,
stats.Expertise: (ownerStats[stats.SpellHit] / core.SpellHitRatingPerHitChance) *
PetExpertiseScale * core.ExpertisePerQuarterPercentReduction,
}
}

infernal := &InfernalPet{
Pet: core.NewPet(
"Infernal",
&warlock.Character,
stats.Stats{
stats.Strength: 331,
stats.Agility: 113,
stats.Stamina: 361,
stats.Intellect: 65,
stats.Spirit: 109,
stats.Mana: 0,
stats.MeleeCrit: 3.192 * core.CritRatingPerCritChance,
},
statInheritance,
false,
false,
),
owner: warlock,
}

infernal.AddStatDependency(stats.Strength, stats.AttackPower, 2)
infernal.AddStat(stats.AttackPower, -20)

// infernal is classified as a warrior class, so we assume it gets the
// same agi crit coefficient
infernal.AddStatDependency(stats.Agility, stats.MeleeCrit, core.CritRatingPerCritChance*1/62.5)

// command doesn't apply to infernal
if warlock.Race == proto.Race_RaceOrc {
infernal.PseudoStats.DamageDealtMultiplier /= 1.05
}

infernal.EnableAutoAttacks(infernal, core.AutoAttackOptions{
MainHand: core.Weapon{
BaseDamageMin: 330,
BaseDamageMax: 494.9,
SwingSpeed: 2,
SwingDuration: time.Second * 2,
CritMultiplier: 2,
},
AutoSwingMelee: true,
})
infernal.AutoAttacks.MHConfig.DamageMultiplier *= 3.2

core.ApplyPetConsumeEffects(&infernal.Character, warlock.Consumes)

warlock.AddPet(infernal)

return infernal
}

func (infernal *InfernalPet) GetPet() *core.Pet {
return &infernal.Pet
}

func (infernal *InfernalPet) Initialize() {
immolationAuraDot := core.NewDot(core.Dot{
Aura: infernal.RegisterAura(core.Aura{
Label: "Immolation",
ActionID: core.ActionID{SpellID: 19483},
}),
NumberOfTicks: 31,
TickLength: time.Second * 2,
AffectedByCastSpeed: false,
OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) {
// TODO: use highest SP amount of all schools
// base formula is 25 + (lvl-50)*0.5 * Warlock_SP*0.2
// note this scales with the warlocks SP, NOT with the pets

// we remove all the spirit based sp since immolation aura doesn't benefit from it, see
// JamminL/wotlk-classic-bugs#329
coef := core.TernaryFloat64(infernal.owner.GlyphOfLifeTapAura.IsActive(), 0.2, 0) +
core.TernaryFloat64(infernal.owner.Options.Armor == proto.Warlock_Options_FelArmor,
0.3*(1+float64(infernal.owner.Talents.DemonicAegis)*0.1), 0)

warlockSP := infernal.owner.Unit.GetStat(stats.SpellPower) - infernal.owner.Unit.GetStat(stats.Spirit)*coef
baseDmg := (40 + warlockSP*0.2) * sim.Encounter.AOECapMultiplier()

for _, aoeTarget := range sim.Encounter.Targets {
dot.Spell.CalcAndDealDamage(sim, &aoeTarget.Unit, baseDmg, dot.Spell.OutcomeMagicHit)
}
},
})

infernal.immolationAura = infernal.RegisterSpell(core.SpellConfig{
ActionID: core.ActionID{SpellID: 20153},
SpellSchool: core.SpellSchoolFire,
ProcMask: core.ProcMaskEmpty,
ResourceType: stats.Mana,

DamageMultiplier: 1,
ThreatMultiplier: 1,

ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) {
immolationAuraDot.Apply(sim)
},
})
immolationAuraDot.Spell = infernal.immolationAura
}

func (infernal *InfernalPet) Reset(sim *core.Simulation) {
}

func (infernal *InfernalPet) OnGCDReady(sim *core.Simulation) {
infernal.immolationAura.Cast(sim, nil)
infernal.DoNothing()
}
1 change: 1 addition & 0 deletions sim/warlock/items.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ var ItemSetGuldansRegalia = core.NewItemSet(core.ItemSet{
Name: "Gul'dan's Regalia",
Bonuses: map[int32]core.ApplyEffect{
2: func(agent core.Agent) {
// TODO: probably doesn't apply to infernal
warlock := agent.(WarlockAgent).GetWarlock()
pet := warlock.Pets[0].GetCharacter()
pet.AddStats(stats.Stats{
Expand Down
Loading

0 comments on commit 7411bc8

Please sign in to comment.