Skip to content

Commit

Permalink
Merge pull request #2691 from wowsims/cleanups
Browse files Browse the repository at this point in the history
Move focus logic to core
  • Loading branch information
jimmyt857 committed Feb 20, 2023
2 parents 06c70cf + ea96daf commit 55d2ec1
Show file tree
Hide file tree
Showing 9 changed files with 465 additions and 479 deletions.
138 changes: 138 additions & 0 deletions sim/core/focus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package core

import (
"time"

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

// Time between focus ticks.
const MaxFocus = 100.0
const tickDuration = time.Second * 1
const BaseFocusPerTick = 5.0

// OnFocusGain is called any time focus is increased.
type OnFocusGain func(sim *Simulation)

type focusBar struct {
unit *Unit

focusPerTick float64

currentFocus float64

onFocusGain OnFocusGain
tickAction *PendingAction
}

func (unit *Unit) EnableFocusBar(regenMultiplier float64, onFocusGain OnFocusGain) {
unit.focusBar = focusBar{
unit: unit,
focusPerTick: BaseFocusPerTick * regenMultiplier,
onFocusGain: onFocusGain,
}
}

func (unit *Unit) HasFocusBar() bool {
return unit.focusBar.unit != nil
}

func (fb *focusBar) CurrentFocus() float64 {
return fb.currentFocus
}

func (fb *focusBar) AddFocus(sim *Simulation, amount float64, actionID ActionID) {
if amount < 0 {
panic("Trying to add negative focus!")
}

newFocus := MinFloat(fb.currentFocus+amount, MaxFocus)

if sim.Log != nil {
fb.unit.Log(sim, "Gained %0.3f focus from %s (%0.3f --> %0.3f).", amount, actionID, fb.currentFocus, newFocus)
}

fb.currentFocus = newFocus

if fb.onFocusGain != nil {
fb.onFocusGain(sim)
}
}

func (fb *focusBar) SpendFocus(sim *Simulation, amount float64, metrics *ResourceMetrics) {
if amount < 0 {
panic("Trying to spend negative focus!")
}

newFocus := fb.currentFocus - amount
metrics.AddEvent(-amount, -amount)

if sim.Log != nil {
fb.unit.Log(sim, "Spent %0.3f focus from %s (%0.3f --> %0.3f).", amount, metrics.ActionID, fb.currentFocus, newFocus)
}

fb.currentFocus = newFocus
}

func (fb *focusBar) reset(sim *Simulation) {
if fb.unit == nil {
return
}

fb.currentFocus = MaxFocus

pa := &PendingAction{
Priority: ActionPriorityRegen,
NextActionAt: tickDuration,
}
pa.OnAction = func(sim *Simulation) {
fb.AddFocus(sim, fb.focusPerTick, ActionID{OtherID: proto.OtherAction_OtherActionFocusRegen})

pa.NextActionAt = sim.CurrentTime + tickDuration
sim.AddPendingAction(pa)
}
fb.tickAction = pa
sim.AddPendingAction(pa)
}

func (fb *focusBar) Cancel(sim *Simulation) {
if fb.tickAction != nil {
fb.tickAction.Cancel(sim)
fb.tickAction = nil
}
}

type FocusCostOptions struct {
Cost float64
}
type FocusCost struct {
Refund float64
ResourceMetrics *ResourceMetrics
}

func newFocusCost(spell *Spell, options FocusCostOptions) *FocusCost {
spell.DefaultCast.Cost = options.Cost

return &FocusCost{
ResourceMetrics: spell.Unit.NewFocusMetrics(spell.ActionID),
}
}

func (fc *FocusCost) MeetsRequirement(spell *Spell) bool {
spell.CurCast.Cost = MaxFloat(0, spell.CurCast.Cost*spell.Unit.PseudoStats.CostMultiplier)
return spell.Unit.CurrentFocus() >= spell.CurCast.Cost
}
func (fc *FocusCost) LogCostFailure(sim *Simulation, spell *Spell) {
spell.Unit.Log(sim,
"Failed casting %s, not enough focus. (Current Focus = %0.03f, Focus Cost = %0.03f)",
spell.ActionID, spell.Unit.CurrentFocus(), spell.CurCast.Cost)
}
func (fc *FocusCost) SpendCost(sim *Simulation, spell *Spell) {
spell.Unit.SpendFocus(sim, spell.CurCast.Cost, fc.ResourceMetrics)
}
func (fc *FocusCost) IssueRefund(sim *Simulation, spell *Spell) {
}

func (spell *Spell) FocusMetrics() *ResourceMetrics {
return spell.Cost.(*FocusCost).ResourceMetrics
}
1 change: 1 addition & 0 deletions sim/core/pet.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func (pet *Pet) Disable(sim *Simulation) {
}

pet.CancelGCDTimer(sim)
pet.focusBar.Cancel(sim)
pet.AutoAttacks.CancelAutoSwing(sim)
pet.enabled = false
pet.DoNothing() // mark it is as doing nothing now.
Expand Down
3 changes: 3 additions & 0 deletions sim/core/spell.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type SpellConfig struct {
EnergyCost EnergyCostOptions
RageCost RageCostOptions
RuneCost RuneCostOptions
FocusCost FocusCostOptions

Cast CastConfig
ExtraCastCondition CanCastCondition
Expand Down Expand Up @@ -218,6 +219,8 @@ func (unit *Unit) RegisterSpell(config SpellConfig) *Spell {
spell.Cost = newRageCost(spell, config.RageCost)
} else if config.RuneCost.BloodRuneCost != 0 || config.RuneCost.FrostRuneCost != 0 || config.RuneCost.UnholyRuneCost != 0 || config.RuneCost.RunicPowerCost != 0 || config.RuneCost.RunicPowerGain != 0 {
spell.Cost = newRuneCost(spell, config.RuneCost)
} else if config.FocusCost.Cost != 0 {
spell.Cost = newFocusCost(spell, config.FocusCost)
}

spell.createDots(config.Dot, false)
Expand Down
2 changes: 2 additions & 0 deletions sim/core/unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ type Unit struct {
manaBar
rageBar
energyBar
focusBar
RunicPowerBar

// All spells that can be cast by this unit.
Expand Down Expand Up @@ -434,6 +435,7 @@ func (unit *Unit) reset(sim *Simulation, agent Agent) {
}

unit.manaBar.reset()
unit.focusBar.reset(sim)
unit.healthBar.reset(sim)
unit.UpdateManaRegenRates()

Expand Down
99 changes: 0 additions & 99 deletions sim/hunter/focus.go

This file was deleted.

4 changes: 2 additions & 2 deletions sim/hunter/kill_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ func (hunter *Hunter) registerKillCommandCD() {
MaxStacks: 3,
OnGain: func(aura *core.Aura, sim *core.Simulation) {
hunter.pet.focusDump.BonusCritRating += bonusPetSpecialCrit
if !hunter.pet.specialAbility.IsEmpty() {
if hunter.pet.specialAbility != nil {
hunter.pet.specialAbility.BonusCritRating += bonusPetSpecialCrit
}
},
OnExpire: func(aura *core.Aura, sim *core.Simulation) {
hunter.pet.focusDump.BonusCritRating -= bonusPetSpecialCrit
if !hunter.pet.specialAbility.IsEmpty() {
if hunter.pet.specialAbility != nil {
hunter.pet.specialAbility.BonusCritRating -= bonusPetSpecialCrit
}
},
Expand Down
30 changes: 11 additions & 19 deletions sim/hunter/pet.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

type HunterPet struct {
core.Pet
focusBar

config PetConfig

Expand All @@ -17,8 +16,8 @@ type HunterPet struct {
CobraStrikesAura *core.Aura
KillCommandAura *core.Aura

specialAbility PetAbility
focusDump PetAbility
specialAbility *core.Spell
focusDump *core.Spell

uptimePercent float64
hasOwnerCooldown bool
Expand Down Expand Up @@ -86,25 +85,18 @@ func (hp *HunterPet) Talents() *proto.HunterPetTalents {
}

func (hp *HunterPet) Initialize() {
//if hp.hunterOwner.Options.PetSingleAbility {
// hp.specialAbility = hp.NewPetAbility(hp.config.FocusDump, true)
// hp.config.RandomSelection = false
//} else {
hp.specialAbility = hp.NewPetAbility(hp.config.SpecialAbility, true)
hp.focusDump = hp.NewPetAbility(hp.config.FocusDump, false)
//}
}

func (hp *HunterPet) Reset(sim *core.Simulation) {
hp.focusBar.reset(sim)
hp.uptimePercent = core.MinFloat(1, core.MaxFloat(0, hp.hunterOwner.Options.PetUptime))
}

func (hp *HunterPet) OnGCDReady(sim *core.Simulation) {
percentRemaining := sim.GetRemainingDurationPercent()
if percentRemaining < 1.0-hp.uptimePercent { // once fight is % completed, disable pet.
hp.Disable(sim)
hp.focusBar.Cancel(sim)
return
}

Expand All @@ -118,35 +110,35 @@ func (hp *HunterPet) OnGCDReady(sim *core.Simulation) {
target := hp.CurrentTarget
if hp.config.RandomSelection {
if sim.RandomFloat("Hunter Pet Ability") < 0.5 {
if !hp.specialAbility.TryCast(sim, target, hp) {
if !hp.focusDump.TryCast(sim, target, hp) {
if !hp.specialAbility.CanCast(sim, target) || !hp.specialAbility.Cast(sim, target) {
if !hp.focusDump.Cast(sim, target) {
hp.DoNothing()
}
}
} else {
if !hp.focusDump.TryCast(sim, target, hp) {
if !hp.specialAbility.TryCast(sim, target, hp) {
if !hp.focusDump.Cast(sim, target) {
if !hp.specialAbility.CanCast(sim, target) || !hp.specialAbility.Cast(sim, target) {
hp.DoNothing()
}
}
}
return
}

if hp.specialAbility.TryCast(sim, target, hp) {
if !hp.specialAbility.CanCast(sim, target) || hp.specialAbility.Cast(sim, target) {
// For abilities that don't use the GCD.
if hp.GCD.IsReady(sim) {
if hp.focusDump.Type != Unknown {
if !hp.focusDump.TryCast(sim, target, hp) {
if hp.focusDump != nil {
if !hp.focusDump.Cast(sim, target) {
hp.DoNothing()
}
} else {
hp.DoNothing()
}
}
} else {
if hp.focusDump.Type != Unknown {
if !hp.focusDump.TryCast(sim, target, hp) {
if hp.focusDump != nil {
if !hp.focusDump.Cast(sim, target) {
hp.DoNothing()
}
} else {
Expand Down
Loading

0 comments on commit 55d2ec1

Please sign in to comment.