Skip to content

Commit

Permalink
Merge pull request #3256 from wowsims/apl
Browse files Browse the repository at this point in the history
Implement autocast CD action for APL, hunter APL rotation DPS now mat…
  • Loading branch information
jimmyt857 committed Jul 6, 2023
2 parents 47d6395 + 903e2b6 commit f3f012f
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 22 deletions.
4 changes: 4 additions & 0 deletions proto/apl.proto
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ message APLAction {
APLActionStrictSequence strict_sequence = 6;

APLActionCastSpell cast_spell = 3;
APLActionAutocastOtherCooldowns autocast_other_cooldowns = 7;
APLActionWait wait = 4;
}
}
Expand Down Expand Up @@ -87,6 +88,9 @@ message APLActionCastSpell {
ActionID spell_id = 1;
}

message APLActionAutocastOtherCooldowns {
}

message APLActionWait {
APLValue duration = 1;
}
Expand Down
11 changes: 10 additions & 1 deletion sim/core/apl.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ func (unit *Unit) newAPLRotation(config *proto.APLRotation) *APLRotation {

for _, action := range rotation.allAPLActions() {
action.impl.Finalize()

// Remove MCDs that are referenced by APL actions.
character := unit.Env.Raid.GetPlayerFromUnit(unit).GetCharacter()
if castSpellAction, ok := action.impl.(*APLActionCastSpell); ok {
character.removeInitialMajorCooldown(castSpellAction.spell.ActionID)
}
}

return rotation
Expand All @@ -63,8 +69,11 @@ func (rot *APLRotation) reset(sim *Simulation) {
func (apl *APLRotation) DoNextAction(sim *Simulation) {
if apl.strictSequence == nil {
for _, action := range apl.priorityList {
if action.IsAvailable(sim) {
if action.IsReady(sim) {
action.Execute(sim)
if apl.unit.GCD.IsReady(sim) {
apl.unit.WaitUntil(sim, sim.CurrentTime)
}
return
}
}
Expand Down
8 changes: 5 additions & 3 deletions sim/core/apl_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ type APLAction struct {
impl APLActionImpl
}

func (action *APLAction) IsAvailable(sim *Simulation) bool {
return (action.condition == nil || action.condition.GetBool(sim)) && action.impl.IsAvailable(sim)
func (action *APLAction) IsReady(sim *Simulation) bool {
return (action.condition == nil || action.condition.GetBool(sim)) && action.impl.IsReady(sim)
}

func (action *APLAction) Execute(sim *Simulation) {
Expand All @@ -35,7 +35,7 @@ type APLActionImpl interface {
Reset(*Simulation)

// Whether this action is available to be used right now.
IsAvailable(*Simulation) bool
IsReady(*Simulation) bool

// Performs the action.
Execute(*Simulation)
Expand Down Expand Up @@ -66,6 +66,8 @@ func (unit *Unit) newAPLActionImpl(config *proto.APLAction) APLActionImpl {
return unit.newActionStrictSequence(config.GetStrictSequence())
case *proto.APLAction_CastSpell:
return unit.newActionCastSpell(config.GetCastSpell())
case *proto.APLAction_AutocastOtherCooldowns:
return unit.newActionAutocastOtherCooldowns(config.GetAutocastOtherCooldowns())
case *proto.APLAction_Wait:
return unit.newActionWait(config.GetWait())
default:
Expand Down
29 changes: 27 additions & 2 deletions sim/core/apl_actions_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,38 @@ func (unit *Unit) newActionCastSpell(config *proto.APLActionCastSpell) APLAction
func (action *APLActionCastSpell) GetInnerActions() []*APLAction { return nil }
func (action *APLActionCastSpell) Finalize() {}
func (action *APLActionCastSpell) Reset(*Simulation) {}
func (action *APLActionCastSpell) IsAvailable(sim *Simulation) bool {
func (action *APLActionCastSpell) IsReady(sim *Simulation) bool {
return action.spell.CanCast(sim, action.spell.Unit.CurrentTarget)
}
func (action *APLActionCastSpell) Execute(sim *Simulation) {
action.spell.Cast(sim, action.spell.Unit.CurrentTarget)
}

type APLActionAutocastOtherCooldowns struct {
character *Character

nextReadyMCD *MajorCooldown
}

func (unit *Unit) newActionAutocastOtherCooldowns(config *proto.APLActionAutocastOtherCooldowns) APLActionImpl {
return &APLActionAutocastOtherCooldowns{
character: unit.Env.Raid.GetPlayerFromUnit(unit).GetCharacter(),
}
}
func (action *APLActionAutocastOtherCooldowns) GetInnerActions() []*APLAction { return nil }
func (action *APLActionAutocastOtherCooldowns) Finalize() {}
func (action *APLActionAutocastOtherCooldowns) Reset(*Simulation) {
action.nextReadyMCD = nil
}
func (action *APLActionAutocastOtherCooldowns) IsReady(sim *Simulation) bool {
action.nextReadyMCD = action.character.getFirstReadyMCD(sim)
return action.nextReadyMCD != nil
}
func (action *APLActionAutocastOtherCooldowns) Execute(sim *Simulation) {
action.nextReadyMCD.tryActivateHelper(sim, action.character)
action.character.UpdateMajorCooldowns()
}

type APLActionWait struct {
unit *Unit
duration APLValue
Expand All @@ -42,7 +67,7 @@ func (unit *Unit) newActionWait(config *proto.APLActionWait) APLActionImpl {
func (action *APLActionWait) GetInnerActions() []*APLAction { return nil }
func (action *APLActionWait) Finalize() {}
func (action *APLActionWait) Reset(*Simulation) {}
func (action *APLActionWait) IsAvailable(sim *Simulation) bool {
func (action *APLActionWait) IsReady(sim *Simulation) bool {
return action.duration != nil
}
func (action *APLActionWait) Execute(sim *Simulation) {
Expand Down
12 changes: 6 additions & 6 deletions sim/core/apl_actions_sequences.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ func (action *APLActionSequence) Finalize() {}
func (action *APLActionSequence) Reset(*Simulation) {
action.curIdx = 0
}
func (action *APLActionSequence) IsAvailable(sim *Simulation) bool {
return action.curIdx < len(action.actions) && action.actions[action.curIdx].IsAvailable(sim)
func (action *APLActionSequence) IsReady(sim *Simulation) bool {
return action.curIdx < len(action.actions) && action.actions[action.curIdx].IsReady(sim)
}
func (action *APLActionSequence) Execute(sim *Simulation) {
action.actions[action.curIdx].Execute(sim)
Expand Down Expand Up @@ -65,7 +65,7 @@ func (action *APLActionResetSequence) Finalize() {
validationWarning("No sequence with name: %s", action.name)
}
func (action *APLActionResetSequence) Reset(*Simulation) {}
func (action *APLActionResetSequence) IsAvailable(sim *Simulation) bool {
func (action *APLActionResetSequence) IsReady(sim *Simulation) bool {
return true
}
func (action *APLActionResetSequence) Execute(sim *Simulation) {
Expand Down Expand Up @@ -96,17 +96,17 @@ func (action *APLActionStrictSequence) Finalize() {}
func (action *APLActionStrictSequence) Reset(*Simulation) {
action.curIdx = 0
}
func (action *APLActionStrictSequence) IsAvailable(sim *Simulation) bool {
func (action *APLActionStrictSequence) IsReady(sim *Simulation) bool {
for _, subaction := range action.actions {
if !subaction.IsAvailable(sim) {
if !subaction.IsReady(sim) {
return false
}
}
return true
}
func (action *APLActionStrictSequence) Execute(sim *Simulation) {
action.unit.Rotation.strictSequence = action
if !action.actions[action.curIdx].IsAvailable(sim) {
if !action.actions[action.curIdx].IsReady(sim) {
action.curIdx = 0
action.unit.Rotation.strictSequence = nil
return
Expand Down
42 changes: 36 additions & 6 deletions sim/core/major_cooldown.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,7 @@ func (mcd *MajorCooldown) tryActivateInternal(sim *Simulation, character *Charac
return mcd.tryActivateHelper(sim, character)
}

// Activates this MCD, if all the conditions pass.
// Returns whether the MCD was activated.
func (mcd *MajorCooldown) tryActivateHelper(sim *Simulation, character *Character) bool {
func (mcd *MajorCooldown) shouldActivateHelper(sim *Simulation, character *Character) bool {
if mcd.Type.Matches(CooldownTypeSurvival) && character.cooldownConfigs.HpPercentForDefensives != 0 {
if character.CurrentHealthPercent() > character.cooldownConfigs.HpPercentForDefensives {
return false
Expand All @@ -136,12 +134,17 @@ func (mcd *MajorCooldown) tryActivateHelper(sim *Simulation, character *Characte
return false
}

var shouldActivate bool
if mcd.numUsages < len(mcd.timings) {
shouldActivate = sim.CurrentTime >= mcd.timings[mcd.numUsages]
return sim.CurrentTime >= mcd.timings[mcd.numUsages]
} else {
shouldActivate = mcd.ShouldActivate(sim, character)
return mcd.ShouldActivate(sim, character)
}
}

// Activates this MCD, if all the conditions pass.
// Returns whether the MCD was activated.
func (mcd *MajorCooldown) tryActivateHelper(sim *Simulation, character *Character) bool {
shouldActivate := mcd.shouldActivateHelper(sim, character)

if shouldActivate {
if mcd.Spell.Flags.Matches(SpellFlagHelpful) {
Expand Down Expand Up @@ -397,6 +400,16 @@ func (mcdm *majorCooldownManager) GetInitialMajorCooldown(actionID ActionID) Maj
return MajorCooldown{}
}

func (mcdm *majorCooldownManager) removeInitialMajorCooldown(actionID ActionID) {
for i, mcd := range mcdm.initialMajorCooldowns {
if mcd.Spell.SameAction(actionID) {
mcdm.initialMajorCooldowns = append(mcdm.initialMajorCooldowns[:i], mcdm.initialMajorCooldowns[i+1:]...)
mcdm.majorCooldowns = mcdm.majorCooldowns[:len(mcdm.majorCooldowns)-1]
return
}
}
}

func (mcdm *majorCooldownManager) GetMajorCooldown(actionID ActionID) *MajorCooldown {
for _, mcd := range mcdm.majorCooldowns {
if mcd.Spell.SameAction(actionID) {
Expand Down Expand Up @@ -427,6 +440,23 @@ func (mcdm *majorCooldownManager) GetMajorCooldownIDs() []*proto.ActionID {
return ids
}

func (mcdm *majorCooldownManager) getFirstReadyMCD(sim *Simulation) *MajorCooldown {
if sim.CurrentTime < mcdm.minReady {
return nil
}

for _, mcd := range mcdm.majorCooldowns {
if !mcd.IsReady(sim) {
return nil
}
if mcd.shouldActivateHelper(sim, mcdm.character) {
return mcd
}
}

return nil
}

func (mcdm *majorCooldownManager) TryUseCooldowns(sim *Simulation) {
if sim.CurrentTime < mcdm.minReady {
return
Expand Down
3 changes: 2 additions & 1 deletion sim/hunter/rotation.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package hunter

import (
"time"

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

func (hunter *Hunter) OnAutoAttack(sim *core.Simulation, spell *core.Spell) {
Expand Down
15 changes: 15 additions & 0 deletions ui/core/components/individual_sim_ui/apl_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
APLActionSequence,
APLActionResetSequence,
APLActionStrictSequence,
APLActionAutocastOtherCooldowns,
APLActionWait,
APLValue,
} from '../../proto/apl.js';
Expand Down Expand Up @@ -260,8 +261,22 @@ export const actionTypeFactories: Record<NonNullable<APLActionType>, ActionTypeC
actionListFieldConfig('actions'),
],
}),
['autocastOtherCooldowns']: inputBuilder({
label: 'Autocast Other Cooldowns',
submenu: ['Misc'],
shortDescription: 'Auto-casts cooldowns as soon as they are ready.',
fullDescription: `
<ul>
<li>Does not auto-cast cooldowns which are already controlled by other actions in the priority list.</li>
<li>Cooldowns are usually cast immediately upon becoming ready, but there are some basic smart checks in place, e.g. don't use Mana CDs when near full mana.</li>
</ul>
`,
newValue: APLActionAutocastOtherCooldowns.create,
fields: [],
}),
['wait']: inputBuilder({
label: 'Wait',
submenu: ['Misc'],
shortDescription: 'Pauses the GCD for a specified amount of time.',
newValue: APLActionWait.create,
fields: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class APLRotationPicker extends Component {
inlineMenuBar: true,
});

modPlayer.rotationChangeEmitter.on(() => console.log('APL: ' + APLRotation.toJsonString(modPlayer.aplRotation)))
//modPlayer.rotationChangeEmitter.on(() => console.log('APL: ' + APLRotation.toJsonString(modPlayer.aplRotation)))
}
}

Expand Down
1 change: 0 additions & 1 deletion ui/core/components/individual_sim_ui/rotation_tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export class RotationTab extends SimTab {

constructor(parentElem: HTMLElement, simUI: IndividualSimUI<Spec>) {
super(parentElem, simUI, {identifier: 'rotation-tab', title: 'Rotation'});
this.rootElem.classList.add('experimental');
this.simUI = simUI;

this.leftPanel = document.createElement('div');
Expand Down
6 changes: 5 additions & 1 deletion ui/hunter/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,17 @@ export const ROTATION_PRESET_DEFAULT = {
rotation: APLRotation.fromJsonString(`{
"enabled": true,
"priorityList": [
{"action": {"autocastOtherCooldowns": {}}},
{"action": {
"condition": {"not": {"val": {"dotIsActive": {"spellId": { "spellId": 49001 }}}}},
"castSpell": {"spellId": { "spellId": 49001 }}
}},
{"action": {"castSpell": {"spellId": { "spellId": 61006 }}}},
{"action": {"castSpell": {"spellId": { "spellId": 63672 }}}},
{"action": {"castSpell": {"spellId": { "spellId": 60053 }}}},
{"action": {
"condition": {"not": {"val": {"dotIsActive": {"spellId": { "spellId": 60053 }}}}},
"castSpell": {"spellId": { "spellId": 60053 }}
}},
{"action": {"castSpell": {"spellId": { "spellId": 49050 }}}},
{"action": {
"condition": {"not": {"val": {"dotIsActive": {"spellId": { "spellId": 60053 }}}}},
Expand Down

0 comments on commit f3f012f

Please sign in to comment.