Skip to content

Commit

Permalink
Merge pull request #3273 from wowsims/apl
Browse files Browse the repository at this point in the history
Implement prepull actions for APL
  • Loading branch information
jimmyt857 authored Jul 9, 2023
2 parents e3d0d09 + eefc425 commit 4bcc966
Show file tree
Hide file tree
Showing 18 changed files with 602 additions and 311 deletions.
1 change: 1 addition & 0 deletions proto/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ message SpellStats {
bool is_castable = 2; // Whether this spell may be cast by the APL logic.
bool is_major_cooldown = 3; // Whether this spell is a major cooldown.
bool has_dot = 4; // Whether this spell applies a DoT effect.
bool prepull_only = 5; // Whether this spell may only be cast during prepull.
}
message APLActionStats {
repeated string warnings = 1;
Expand Down
11 changes: 6 additions & 5 deletions proto/apl.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ message APLRotation {
repeated APLListItem priority_list = 2;
}

message APLPrepullAction {
APLAction action = 1;
string do_at = 2; // Should be a negative value. Uses the same syntax as APLValueConst.
bool hide = 3; // Causes this item to be ignored.
}

message APLListItem {
bool hide = 1; // Causes this item to be ignored.
string notes = 2; // Comments for the reader.
Expand Down Expand Up @@ -76,11 +82,6 @@ message APLValue {
}
}

message APLPrepullAction {
APLAction action = 1;
Duration do_at = 2; // Should be a negative value.
}

///////////////////////////////////////////////////////////////////////////
// ACTIONS
///////////////////////////////////////////////////////////////////////////
Expand Down
1 change: 1 addition & 0 deletions proto/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ enum OtherAction {
OtherActionFrostRuneGain = 14; // Indicates healing received from healing model.
OtherActionUnholyRuneGain = 15; // Indicates healing received from healing model.
OtherActionDeathRuneGain = 16; // Indicates healing received from healing model.
OtherActionPotion = 17; // Used by APL to generically refer to either the prepull or combat potion.
}

message ActionID {
Expand Down
68 changes: 64 additions & 4 deletions sim/core/apl.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ import (
)

type APLRotation struct {
unit *Unit
priorityList []*APLAction
unit *Unit
prepullActions []*APLAction
priorityList []*APLAction

// Current strict sequence
strictSequence *APLActionStrictSequence

// Used inside of actions/value to determine whether they will occur during the prepull or regular rotation.
parsingPrepull bool

// Validation warnings that occur during proto parsing.
// We return these back to the user for display in the UI.
curWarnings []string
Expand All @@ -36,6 +40,33 @@ func (unit *Unit) newAPLRotation(config *proto.APLRotation) *APLRotation {
unit: unit,
}

// Parse prepull actions
rotation.parsingPrepull = true
for _, prepullItem := range config.PrepullActions {
if !prepullItem.Hide {
doAt := time.Duration(1)
if durVal, err := time.ParseDuration(prepullItem.DoAt); err == nil {
doAt = durVal
}
if doAt > 0 {
rotation.validationWarning("Invalid time for 'Do At', ignoring this Prepull Action")
} else {
action := rotation.newAPLAction(prepullItem.Action)
if action != nil {
rotation.prepullActions = append(rotation.prepullActions, action)
unit.RegisterPrepullAction(doAt, func(sim *Simulation) {
action.Execute(sim)
})
}
}
}

rotation.prepullWarnings = append(rotation.prepullWarnings, rotation.curWarnings)
rotation.curWarnings = nil
}
rotation.parsingPrepull = false

// Parse priority list
var configIdxs []int
for i, aplItem := range config.PriorityList {
if !aplItem.Hide {
Expand All @@ -50,19 +81,43 @@ func (unit *Unit) newAPLRotation(config *proto.APLRotation) *APLRotation {
rotation.curWarnings = nil
}

// Finalize
for _, action := range rotation.prepullActions {
action.impl.Finalize(rotation)
rotation.curWarnings = nil
}
for i, action := range rotation.priorityList {
action.impl.Finalize(rotation)

rotation.priorityListWarnings[configIdxs[i]] = append(rotation.priorityListWarnings[configIdxs[i]], rotation.curWarnings...)
rotation.curWarnings = nil
}

// Remove MCDs that are referenced by APL actions.
character := unit.Env.Raid.GetPlayerFromUnit(unit).GetCharacter()
// Remove MCDs that are referenced by APL actions, so that the Autocast Other Cooldowns
// action does not include them.
character := unit.Env.Raid.GetPlayerFromUnit(unit).GetCharacter()
for _, action := range rotation.allAPLActions() {
if castSpellAction, ok := action.impl.(*APLActionCastSpell); ok {
character.removeInitialMajorCooldown(castSpellAction.spell.ActionID)
}
}

// If user has a Prepull potion set but does not use it in their APL settings, we enable it here.
prepotSpell := rotation.aplGetSpell(ActionID{OtherID: proto.OtherAction_OtherActionPotion}.ToProto())
if prepotSpell != nil {
found := false
for _, prepullAction := range rotation.allPrepullActions() {
if castSpellAction, ok := prepullAction.impl.(*APLActionCastSpell); ok && castSpellAction.spell == prepotSpell {
found = true
}
}
if !found {
unit.RegisterPrepullAction(-1*time.Second, func(sim *Simulation) {
prepotSpell.Cast(sim, nil)
})
}
}

return rotation
}
func (rot *APLRotation) getStats() *proto.APLStats {
Expand All @@ -77,6 +132,11 @@ func (rot *APLRotation) allAPLActions() []*APLAction {
return Flatten(MapSlice(rot.priorityList, func(action *APLAction) []*APLAction { return action.GetAllActions() }))
}

// Returns all action objects from the prepull as an unstructured list. Used for easily finding specific actions.
func (rot *APLRotation) allPrepullActions() []*APLAction {
return Flatten(MapSlice(rot.prepullActions, func(action *APLAction) []*APLAction { return action.GetAllActions() }))
}

func (rot *APLRotation) reset(sim *Simulation) {
rot.strictSequence = nil
for _, action := range rot.allAPLActions() {
Expand Down
26 changes: 24 additions & 2 deletions sim/core/apl_values_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,31 @@ import (
)

func (rot *APLRotation) aplGetSpell(spellId *proto.ActionID) *Spell {
spell := rot.unit.GetSpell(ProtoToActionID(spellId))
actionID := ProtoToActionID(spellId)
var spell *Spell

if actionID.IsOtherAction(proto.OtherAction_OtherActionPotion) {
if rot.parsingPrepull {
for _, s := range rot.unit.Spellbook {
if s.Flags.Matches(SpellFlagPrepullPotion) {
spell = s
break
}
}
} else {
for _, s := range rot.unit.Spellbook {
if s.Flags.Matches(SpellFlagCombatPotion) {
spell = s
break
}
}
}
} else {
spell = rot.unit.GetSpell(actionID)
}

if spell == nil {
rot.validationWarning("%s does not know spell %s", rot.unit.Label, ProtoToActionID(spellId))
rot.validationWarning("%s does not know spell %s", rot.unit.Label, actionID)
}
return spell
}
Expand Down
1 change: 1 addition & 0 deletions sim/core/character.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ func (character *Character) FillPlayerStats(playerStats *proto.PlayerStats) {
IsCastable: spell.Flags.Matches(SpellFlagAPL),
IsMajorCooldown: spell.Flags.Matches(SpellFlagMCD),
HasDot: spell.dots != nil,
PrepullOnly: spell.Flags.Matches(SpellFlagPrepullOnly),
}
})

Expand Down
42 changes: 32 additions & 10 deletions sim/core/consumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,19 +456,22 @@ func registerPotionCD(agent Agent, consumes *proto.Consumes) {

startingMCD := makePotionActivation(startingPotion, character, potionCD)
if startingMCD.Spell != nil {
character.RegisterPrepullAction(-1*time.Second, func(sim *Simulation) {
startingMCD.Spell.Cast(sim, nil)
if startingPotion == proto.Potions_IndestructiblePotion {
potionCD.Set(sim.CurrentTime + 2*time.Minute)
} else {
potionCD.Set(sim.CurrentTime + time.Minute)
}
character.UpdateMajorCooldowns()
})
startingMCD.Spell.Flags |= SpellFlagPrepullPotion
if !character.IsUsingAPL {
character.RegisterPrepullAction(-1*time.Second, func(sim *Simulation) {
startingMCD.Spell.Cast(sim, nil)
})
}
}

defaultMCD := makePotionActivation(defaultPotion, character, potionCD)
var defaultMCD MajorCooldown
if defaultPotion == startingPotion {
defaultMCD = startingMCD
} else {
defaultMCD = makePotionActivation(defaultPotion, character, potionCD)
}
if defaultMCD.Spell != nil {
defaultMCD.Spell.Flags |= SpellFlagCombatPotion
character.AddMajorCooldown(defaultMCD)
}
}
Expand All @@ -484,6 +487,25 @@ func (character *Character) HasAlchStone() bool {
}

func makePotionActivation(potionType proto.Potions, character *Character, potionCD *Timer) MajorCooldown {
mcd := makePotionActivationInternal(potionType, character, potionCD)
if mcd.Spell != nil {
oldApplyEffects := mcd.Spell.ApplyEffects
mcd.Spell.ApplyEffects = func(sim *Simulation, target *Unit, spell *Spell) {
oldApplyEffects(sim, target, spell)
if sim.CurrentTime < 0 {
if potionType == proto.Potions_IndestructiblePotion {
potionCD.Set(sim.CurrentTime + 2*time.Minute)
} else {
potionCD.Set(sim.CurrentTime + time.Minute)
}
character.UpdateMajorCooldowns()
}
}
}
return mcd
}

func makePotionActivationInternal(potionType proto.Potions, character *Character, potionCD *Timer) MajorCooldown {
alchStoneEquipped := character.HasAlchStone()
hasEngi := character.HasProfession(proto.Profession_Engineering)

Expand Down
3 changes: 3 additions & 0 deletions sim/core/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ const (
SpellFlagAPL // Indicates this spell can be used from an APL rotation.
SpellFlagMCD // Indicates this spell is a MajorCooldown.
SpellFlagNoOnDamageDealt // Disables OnSpellHitDealt and OnPeriodicDamageDealt aura callbacks for this spell.
SpellFlagPrepullOnly // Indicates this spell should only be used during prepull. Not enforced, just a signal for the APL UI.
SpellFlagPrepullPotion // Indicates this spell is the prepull potion.
SpellFlagCombatPotion // Indicates this spell is the combat potion.

// Used to let agents categorize their spells.
SpellFlagAgentReserved1
Expand Down
Loading

0 comments on commit 4bcc966

Please sign in to comment.