Skip to content

Commit

Permalink
Merge pull request #508 from ncberman/hunter_focusFire
Browse files Browse the repository at this point in the history
Implemented Hunter Focus Fire Rune
  • Loading branch information
rosenrusinov authored Mar 31, 2024
2 parents 80ee546 + e2d2ed7 commit a39488e
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 2 deletions.
2 changes: 2 additions & 0 deletions assets/database/db.json
Original file line number Diff line number Diff line change
Expand Up @@ -9901,6 +9901,7 @@
{"id":427717,"name":"Engrave Bracers - Unstable Affliction","icon":"spell_shadow_unstableaffliction_3","class":8,"type":6,"requiresLevel":1},
{"id":427726,"name":"Engrave Bracers - Immolation Aura","icon":"spell_fire_felimmolation","class":8,"type":6,"requiresLevel":1},
{"id":427733,"name":"Engrave Bracers - Summon Felguard","icon":"spell_shadow_summonfelguard","class":8,"type":6,"requiresLevel":1},
{"id":428726,"name":"Engrave Bracers - Focus Fire","icon":"inv_weapon_crossbow_19","class":2,"type":6,"requiresLevel":1},
{"id":428738,"name":"Engrave Helm - Advanced Warding","icon":"spell_arcane_arcaneresilience","class":3,"type":1,"requiresLevel":1},
{"id":428739,"name":"Engrave Helm - Deep Freeze","icon":"ability_mage_deepfreeze","class":3,"type":1,"requiresLevel":1},
{"id":428741,"name":"Engrave Bracers - Molten Armor","icon":"ability_mage_moltenarmor","class":3,"type":6,"requiresLevel":1},
Expand Down Expand Up @@ -13586,6 +13587,7 @@
{"id":426445,"name":"Engrave Belt - Grimoire of Synergy","icon":"inv_misc_desecrated_leatherbelt","requiresLevel":1},
{"id":426452,"name":"Engrave Belt - Shadow and Flame","icon":"inv_misc_desecrated_leatherbelt","requiresLevel":1},
{"id":426467,"name":"Engrave Boots - Shadowflame","icon":"inv_misc_desecrated_leatherboots","requiresLevel":1},
{"id":428728,"name":"Frenzy","icon":"ability_ghoulfrenzy","requiresLevel":1},
{"id":429304,"name":"Engrave Helm - Deep Freeze","icon":"inv_misc_desecrated_leatherhelm","requiresLevel":1},
{"id":429306,"name":"Engrave Helm - Temporal Anomaly","icon":"inv_misc_desecrated_leatherhelm","requiresLevel":1},
{"id":429308,"name":"Engrave Bracers - Molten Armor","icon":"inv_misc_desecrated_clothbracer","requiresLevel":1},
Expand Down
1 change: 1 addition & 0 deletions proto/hunter.proto
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ enum HunterRune {

RuneHelmLockAndLoad = 415413;

RuneBracersFocusFire = 428726;
RuneBracersRaptorFury = 415358;
}

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

import (
"time"

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

func (hunter *Hunter) registerFocusFireSpell() {
if hunter.pet == nil || !hunter.HasRune(proto.HunterRune_RuneBracersFocusFire) {
return
}

focusFireMetrics := hunter.pet.NewFocusMetrics(core.ActionID{SpellID: int32(proto.HunterRune_RuneBracersFocusFire)})
focusFireActionId := core.ActionID{SpellID: int32(proto.HunterRune_RuneBracersFocusFire)}
focusFireFrenzyActionId := core.ActionID{SpellID: 428728}

// For tracking in timeline
hunterFrenzyAura := hunter.RegisterAura(core.Aura{
Label: "Focus Fire Frenzy (Hunter)",
ActionID: focusFireFrenzyActionId,
Duration: time.Second * 10,
MaxStacks: 5,
})

hunterPetFrenzyAura := hunter.pet.RegisterAura(core.Aura{
Label: "Focus Fire Frenzy",
ActionID: focusFireFrenzyActionId,
Duration: time.Second * 10,
MaxStacks: 5,
OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks int32, newStacks int32) {
// revert previous attack speed bonus from stacks and apply new attack speed bonus
aura.Unit.MultiplyMeleeSpeed(sim, 1/(1+(0.06*float64(oldStacks))))
aura.Unit.MultiplyMeleeSpeed(sim, 1+(0.06*float64(newStacks)))

// this is just so we can see the frenzy stacks working on the sim timeline
if !hunterFrenzyAura.IsActive() { hunterFrenzyAura.Activate(sim) }
hunterFrenzyAura.SetStacks(sim, newStacks)
},
})

hunterFocusFireAura := hunter.RegisterAura(core.Aura{
Label: "Focus Fire",
ActionID: focusFireActionId,
Duration: time.Second * 20,
MaxStacks: 5,
OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) {
aura.Unit.MultiplyRangedSpeed(sim, 1/(1+(0.03*float64(oldStacks))))
aura.Unit.MultiplyRangedSpeed(sim, 1+(0.03*float64(newStacks)))
},
})

hunter.pet.RegisterAura(core.Aura{
Label: "Focus Fire Pet",
Duration: core.NeverExpires,
OnReset: func(aura *core.Aura, sim *core.Simulation) {
aura.Activate(sim)
},
OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) {
if spell.ProcMask.Matches(core.ProcMaskMeleeMHAuto) {
if !hunterPetFrenzyAura.IsActive() {
hunterPetFrenzyAura.Activate(sim)
}

hunterPetFrenzyAura.AddStack(sim)
hunterPetFrenzyAura.Refresh(sim)
hunterFrenzyAura.Refresh(sim)
}
},
})

hunter.FocusFire = hunter.RegisterSpell(core.SpellConfig{
ActionID: focusFireActionId,

ManaCost: core.ManaCostOptions{
FlatCost: 0, // TODO: Update when mana cost is known
},
Cast: core.CastConfig{
DefaultCast: core.Cast{
GCD: core.GCDDefault,
},
CD: core.Cooldown{
Timer: hunter.NewTimer(),
Duration: time.Second * 15, // TODO: Update when cooldown is known (Currently using the cooldown value from Cataclysm)
},
},
ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool {
return hunter.pet.IsEnabled() && (hunterPetFrenzyAura.GetStacks() > 0)
},
ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) {
frenzyStacks := hunterPetFrenzyAura.GetStacks()
hunter.pet.AddFocus(sim, float64(4 * frenzyStacks), focusFireMetrics)

hunterFocusFireAura.Activate(sim)
hunterFocusFireAura.SetStacks(sim, frenzyStacks)
hunterPetFrenzyAura.SetStacks(sim, 0)
},
})
}
2 changes: 2 additions & 0 deletions sim/hunter/hunter.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type Hunter struct {
KillCommand *core.Spell
KillShot *core.Spell
MultiShot *core.Spell
FocusFire *core.Spell
RapidFire *core.Spell
RaptorStrike *core.Spell
FlankingStrike *core.Spell
Expand Down Expand Up @@ -127,6 +128,7 @@ func (hunter *Hunter) Initialize() {

hunter.registerKillCommand()
hunter.registerRapidFire()
hunter.registerFocusFireSpell()
}

func (hunter *Hunter) Reset(sim *core.Simulation) {
Expand Down
2 changes: 1 addition & 1 deletion sim/hunter/runes.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func (hunter *Hunter) applyLockAndLoad() {
OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) {
if spell.ProcMask.Matches(core.ProcMaskRangedSpecial) && spell.Flags.Matches(core.SpellFlagMeleeMetrics) {
aura.Deactivate(sim)
hunter.AddMana(sim, spell.DefaultCast.Cost, lockAndLoadMetrics)
hunter.AddMana(sim, spell.CurCast.Cost, lockAndLoadMetrics)
spell.CD.Reset()
}
},
Expand Down
1 change: 0 additions & 1 deletion tools/database/rune_overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ var UnimplementedRuneOverrides = []int32{
// Hunter
415428, // Catlike Reflexes
415405, // Rapid Killing
428726, // Focus Fire
428717, // T.N.T.

// Paladin
Expand Down

0 comments on commit a39488e

Please sign in to comment.