Skip to content

Commit

Permalink
Merge branch 'master' into vigo/more-min-max
Browse files Browse the repository at this point in the history
# Conflicts:
#	sim/core/cast.go
#	sim/priest/mind_flay.go
#	sim/priest/shadow/experimental_rotation.go
  • Loading branch information
vigo2 committed Oct 4, 2023
2 parents 907d922 + 2f42f20 commit 1499b53
Show file tree
Hide file tree
Showing 43 changed files with 3,121 additions and 3,374 deletions.
87 changes: 87 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"json.schemas": [
{
"fileMatch": [
"*.apl.json"
],
"url": "./jsonschema/APLRotation.json"
}
],
"Lua.diagnostics.globals": [
"FONT_COLOR_CODE_CLOSE",
"SELECTED_CHAT_FRAME",
"DEFAULT_CHAT_FRAME",
"InterfaceOptions_AddCategory",
"NORMAL_FONT_COLOR",
"GameFontNormal",
"GameFontHighlight",
"ACCEPT",
"CANCEL",
"GameFontHighlightLarge",
"GameFontHighlightSmall",
"SlashCmdList",
"hash_SlashCmdList",
"NORMAL_FONT_COLOR_CODE",
"CLOSE",
"PanelTemplates_TabResize",
"PanelTemplates_SetDisabledTabState",
"PanelTemplates_SelectTab",
"PanelTemplates_DeselectTab",
"SetDesaturation",
"ColorPickerFrame",
"OpacitySliderFrame",
"ChatFontNormal",
"OKAY",
"NOT_BOUND",
"NUM_BAG_SLOTS",
"NUM_BANKBAGSLOTS",
"InterfaceOptionsFrame_OpenToCategory",
"BANK_CONTAINER",
"CreateFrame",
"geterrorhandler",
"IsLoggedIn",
"PlaySound",
"GetRealmName",
"UnitName",
"UnitClass",
"UnitRace",
"UnitFactionGroup",
"GetCurrentRegion",
"GetLocale",
"C_Container",
"GetTalentInfo",
"UnitFullName",
"GetPlayerInfoByGUID",
"UnitLevel",
"tInvert",
"GetItemInfo",
"IsEquippableItem",
"UnitGUID",
"GetSpellInfo",
"GetInventorySlotInfo",
"GetInventoryItemLink",
"max",
"min",
"ceil",
"BackdropTemplateMixin",
"floor",
"GetCursorInfo",
"ClearCursor",
"hooksecurefunc",
"GetMacroInfo",
"IsShiftKeyDown",
"IsControlKeyDown",
"IsAltKeyDown",
"issecurevariable",
"GetTime",
"C_Timer",
"format",
"gsub",
"strfind",
"strsub",
"strchar",
"strbyte",
"tinsert",
"UIParent"
]
}
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ FROM golang:1.21

WORKDIR /wotlk
COPY . .
COPY gitconfig /etc/gitconfig

RUN apt-get update
RUN apt-get install -y protobuf-compiler
Expand Down
2 changes: 2 additions & 0 deletions gitconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[safe]
directory = *
2 changes: 1 addition & 1 deletion proto/apl.proto
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ message APLActionChannelSpell {
UnitReference target = 2;

APLValue interrupt_if = 3;
APLValue max_ticks = 4;
bool allow_recast = 5;
}

message APLActionMultidot {
Expand Down
15 changes: 6 additions & 9 deletions sim/core/apl.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ type APLRotation struct {
// Will be nil when there is no active channel.
interruptChannelIf APLValue

// Max ticks for the current channel, or 0 for no maximum.
channelMaxTicks int32
// If true, can recast channel when interrupted.
allowChannelRecastOnInterrupt bool

// Used inside of actions/value to determine whether they will occur during the prepull or regular rotation.
parsingPrepull bool
Expand Down Expand Up @@ -153,7 +153,7 @@ func (rot *APLRotation) reset(sim *Simulation) {
rot.controllingAction = nil
rot.inLoop = false
rot.interruptChannelIf = nil
rot.channelMaxTicks = 0
rot.allowChannelRecastOnInterrupt = false
for _, action := range rot.allAPLActions() {
action.impl.Reset(sim)
}
Expand Down Expand Up @@ -218,10 +218,6 @@ func (apl *APLRotation) shouldInterruptChannel(sim *Simulation) bool {
return false
}

if apl.channelMaxTicks != 0 && channeledDot.TickCount >= apl.channelMaxTicks {
return true
}

if apl.interruptChannelIf == nil || !apl.interruptChannelIf.GetBool(sim) {
// Continue the channel.
return false
Expand All @@ -232,9 +228,10 @@ func (apl *APLRotation) shouldInterruptChannel(sim *Simulation) bool {
if nextAction == nil {
return false
}

if channelAction, ok := nextAction.impl.(*APLActionChannelSpell); ok && channelAction.spell == channeledDot.Spell {
// Newly selected action is channeling the same spell, so continue the channel.
return false
// Newly selected action is channeling the same spell, so continue the channel unless recast is allowed.
return apl.allowChannelRecastOnInterrupt
}

return true
Expand Down
13 changes: 4 additions & 9 deletions sim/core/apl_actions_casting.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package core

import (
"fmt"

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

Expand Down Expand Up @@ -40,7 +41,7 @@ type APLActionChannelSpell struct {
spell *Spell
target UnitReference
interruptIf APLValue
maxTicks APLValue
allowRecast bool
}

func (rot *APLRotation) newActionChannelSpell(config *proto.APLActionChannelSpell) APLActionImpl {
Expand All @@ -52,8 +53,6 @@ func (rot *APLRotation) newActionChannelSpell(config *proto.APLActionChannelSpel
})
}

maxTicks := rot.coerceTo(rot.newAPLValue(config.MaxTicks), proto.APLValueType_ValueTypeInt)

spell := rot.GetAPLSpell(config.SpellId)
if spell == nil {
return nil
Expand All @@ -71,20 +70,16 @@ func (rot *APLRotation) newActionChannelSpell(config *proto.APLActionChannelSpel
spell: spell,
target: target,
interruptIf: interruptIf,
maxTicks: maxTicks,
allowRecast: config.AllowRecast,
}
}
func (action *APLActionChannelSpell) IsReady(sim *Simulation) bool {
return action.spell.CanCast(sim, action.target.Get())
}
func (action *APLActionChannelSpell) Execute(sim *Simulation) {
maxTicks := int32(0)
if action.maxTicks != nil {
maxTicks = action.maxTicks.GetInt(sim)
}
action.spell.Cast(sim, action.target.Get())
action.spell.Unit.Rotation.interruptChannelIf = action.interruptIf
action.spell.Unit.Rotation.channelMaxTicks = maxTicks
action.spell.Unit.Rotation.allowChannelRecastOnInterrupt = action.allowRecast
}
func (action *APLActionChannelSpell) String() string {
return fmt.Sprintf("Channel Spell(%s, interruptIf=%s)", action.spell.ActionID, action.interruptIf)
Expand Down
5 changes: 5 additions & 0 deletions sim/core/attack.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,11 @@ func (aa *AutoAttacks) TrySwingMH(sim *Simulation, target *Unit) {
return
}

if aa.unit.IsUsingAPL {
// Need to check APL here to allow last-moment HS queue casts.
aa.unit.Rotation.DoNextAction(sim)
}

attackSpell := aa.MaybeReplaceMHSwing(sim, aa.MHAuto)

attackSpell.Cast(sim, target)
Expand Down
2 changes: 1 addition & 1 deletion sim/core/buffs.go
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ func registerPowerInfusionCD(agent Agent, numPowerInfusions int32) {

ShouldActivate: func(sim *Simulation, character *Character) bool {
// Haste portion doesn't stack with Bloodlust, so prefer to wait.
return !character.HasActiveAuraWithTag(BloodlustAuraTag)
return !character.HasActiveAura("Bloodlust-" + BloodlustActionID.WithTag(-1).String())
},
AddAura: func(sim *Simulation, character *Character) { piAura.Activate(sim) },
},
Expand Down
6 changes: 1 addition & 5 deletions sim/core/cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ type Cast struct {

// Additional GCD delay after the cast completes.
ChannelTime time.Duration

// Additional GCD delay after the cast ends. Never affected by cast speed.
// This is typically used for latency.
AfterCastDelay time.Duration
}

func (cast *Cast) EffectiveTime() time.Duration {
Expand All @@ -60,7 +56,7 @@ func (cast *Cast) EffectiveTime() time.Duration {
// TODO: isn't this wrong for spells like shadowfury, that have a reduced GCD?
gcd = max(GCDMin, gcd)
}
fullCastTime := cast.CastTime + cast.ChannelTime + cast.AfterCastDelay
fullCastTime := cast.CastTime + cast.ChannelTime
return max(gcd, fullCastTime)
}

Expand Down
2 changes: 1 addition & 1 deletion sim/core/dot.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func newDot(config Dot) *Dot {
dot.Spell.Unit.ChanneledDot = nil
if dot.Spell.Unit.IsUsingAPL {
dot.Spell.Unit.Rotation.interruptChannelIf = nil
dot.Spell.Unit.Rotation.channelMaxTicks = 0
dot.Spell.Unit.Rotation.allowChannelRecastOnInterrupt = false
}
}
})
Expand Down
29 changes: 19 additions & 10 deletions sim/core/spell.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ type SpellConfig struct {
ApplyEffects ApplySpellResults

// Optional field. Calculates expected average damage.
ExpectedDamage ExpectedDamageCalculator
ExpectedInitialDamage ExpectedDamageCalculator
ExpectedTickDamage ExpectedDamageCalculator

Dot DotConfig
Hot DotConfig
Expand Down Expand Up @@ -98,7 +99,8 @@ type Spell struct {
ApplyEffects ApplySpellResults

// Optional field. Calculates expected average damage.
expectedDamageInternal ExpectedDamageCalculator
expectedInitialDamageInternal ExpectedDamageCalculator
expectedTickDamageInternal ExpectedDamageCalculator

// The current or most recent cast data.
CurCast Cast
Expand Down Expand Up @@ -163,7 +165,6 @@ func (unit *Unit) RegisterSpell(config SpellConfig) *Spell {

if unit.IsUsingAPL {
config.Cast.DefaultCast.ChannelTime = 0
config.Cast.DefaultCast.AfterCastDelay = 0
}

if (config.DamageMultiplier != 0 || config.ThreatMultiplier != 0) && config.ProcMask == ProcMaskUnknown {
Expand Down Expand Up @@ -197,7 +198,8 @@ func (unit *Unit) RegisterSpell(config SpellConfig) *Spell {

ApplyEffects: config.ApplyEffects,

expectedDamageInternal: config.ExpectedDamage,
expectedInitialDamageInternal: config.ExpectedInitialDamage,
expectedTickDamageInternal: config.ExpectedTickDamage,

BonusHitRating: config.BonusHitRating,
BonusCritRating: config.BonusCritRating,
Expand Down Expand Up @@ -535,21 +537,28 @@ func (spell *Spell) ApplyAOEThreat(threatAmount float64) {
spell.ApplyAOEThreatIgnoreMultipliers(threatAmount * spell.Unit.PseudoStats.ThreatMultiplier)
}

func (spell *Spell) expectedDamageHelper(sim *Simulation, target *Unit, useSnapshot bool) float64 {
result := spell.expectedDamageInternal(sim, target, spell, useSnapshot)
func (spell *Spell) finalizeExpectedDamage(result *SpellResult) {
if !spell.SpellSchool.Matches(SpellSchoolPhysical) {
result.Damage /= result.ResistanceMultiplier
result.Damage *= AverageMagicPartialResistMultiplier
result.ResistanceMultiplier = AverageMagicPartialResistMultiplier
}
result.inUse = false
}
func (spell *Spell) ExpectedInitialDamage(sim *Simulation, target *Unit) float64 {
result := spell.expectedInitialDamageInternal(sim, target, spell, false)
spell.finalizeExpectedDamage(result)
return result.Damage
}
func (spell *Spell) ExpectedDamage(sim *Simulation, target *Unit) float64 {
return spell.expectedDamageHelper(sim, target, false)
func (spell *Spell) ExpectedTickDamage(sim *Simulation, target *Unit) float64 {
result := spell.expectedTickDamageInternal(sim, target, spell, false)
spell.finalizeExpectedDamage(result)
return result.Damage
}
func (spell *Spell) ExpectedDamageFromCurrentSnapshot(sim *Simulation, target *Unit) float64 {
return spell.expectedDamageHelper(sim, target, true)
func (spell *Spell) ExpectedTickDamageFromCurrentSnapshot(sim *Simulation, target *Unit) float64 {
result := spell.expectedTickDamageInternal(sim, target, spell, true)
spell.finalizeExpectedDamage(result)
return result.Damage
}

// Time until either the cast is finished or GCD is ready again, whichever is longer
Expand Down
Loading

0 comments on commit 1499b53

Please sign in to comment.