From b76bfc4351d2aa16dcd03701bc634f7fb9b469b7 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Sat, 23 Sep 2023 21:38:03 -0700 Subject: [PATCH] Fix several small bugs related to channel / spriest --- sim/core/apl_values_operators.go | 10 ++++++++ sim/core/dot.go | 4 +++- sim/priest/healing/TestDisc.results | 36 ++++++++++++++--------------- sim/priest/mind_flay.go | 5 ++-- sim/priest/priest.go | 6 +++-- sim/priest/shadow_word_pain.go | 6 +++++ sim/priest/talents.go | 3 +++ ui/core/player.ts | 11 ++++++--- ui/shadow_priest/presets.ts | 28 ++++++++++++++++------ ui/shadow_priest/sim.ts | 2 +- 10 files changed, 77 insertions(+), 34 deletions(-) diff --git a/sim/core/apl_values_operators.go b/sim/core/apl_values_operators.go index a98d8d2e96..b10c13eb7b 100644 --- a/sim/core/apl_values_operators.go +++ b/sim/core/apl_values_operators.go @@ -27,6 +27,16 @@ func (rot *APLRotation) newValueConst(config *proto.APLValueConst) APLValue { boolVal: config.Val != "", } + if strings.ToLower(config.Val) == "true" { + result.boolVal = true + result.valType = proto.APLValueType_ValueTypeBool + return result + } else if strings.ToLower(config.Val) == "false" { + result.boolVal = false + result.valType = proto.APLValueType_ValueTypeBool + return result + } + if durVal, err := time.ParseDuration(config.Val); err == nil { result.durationVal = durVal result.valType = proto.APLValueType_ValueTypeDuration diff --git a/sim/core/dot.go b/sim/core/dot.go index b3972392fc..0c3a3d4e02 100644 --- a/sim/core/dot.go +++ b/sim/core/dot.go @@ -194,7 +194,9 @@ func (dot *Dot) TickOnce(sim *Simulation) { if dot.isChanneled && dot.Spell.Unit.IsUsingAPL { // Note: even if the clip delay is 0ms, need a WaitUntil so that APL is called after the channel aura fully fades. if dot.MaxTicksRemaining() == 0 { - dot.Spell.Unit.WaitUntil(sim, sim.CurrentTime+dot.Spell.Unit.ChannelClipDelay) + if dot.Spell.Unit.GCD.IsReady(sim) { + dot.Spell.Unit.WaitUntil(sim, sim.CurrentTime+dot.Spell.Unit.ChannelClipDelay) + } } else if dot.Spell.Unit.Rotation.shouldInterruptChannel(sim) { dot.Cancel(sim) dot.Spell.Unit.WaitUntil(sim, sim.CurrentTime+dot.Spell.Unit.ChannelClipDelay) diff --git a/sim/priest/healing/TestDisc.results b/sim/priest/healing/TestDisc.results index 4cc94714df..46a55ef872 100644 --- a/sim/priest/healing/TestDisc.results +++ b/sim/priest/healing/TestDisc.results @@ -147,8 +147,8 @@ dps_results: { dps_results: { key: "TestDisc-AllItems-BlessedRegaliaofUndeadCleansing" value: { - tps: 16.32773 - hps: 3210.59379 + tps: 16.32466 + hps: 3210.02224 } } dps_results: { @@ -189,15 +189,15 @@ dps_results: { dps_results: { key: "TestDisc-AllItems-CrimsonAcolyte'sRaiment" value: { - tps: 15.23724 - hps: 3617.95922 + tps: 15.30562 + hps: 3620.60223 } } dps_results: { key: "TestDisc-AllItems-CrimsonAcolyte'sRegalia" value: { - tps: 16.02513 - hps: 3708.05555 + tps: 16.02929 + hps: 3686.08594 } } dps_results: { @@ -266,15 +266,15 @@ dps_results: { dps_results: { key: "TestDisc-AllItems-DislodgedForeignObject-50348" value: { - tps: 17.0725 + tps: 17.0619 hps: 3621.43778 } } dps_results: { key: "TestDisc-AllItems-DislodgedForeignObject-50353" value: { - tps: 17.17594 - hps: 3638.27588 + tps: 16.94699 + hps: 3639.64227 } } dps_results: { @@ -308,7 +308,7 @@ dps_results: { dps_results: { key: "TestDisc-AllItems-EphemeralSnowflake-50260" value: { - tps: 18.41134 + tps: 18.4095 hps: 3603.63774 } } @@ -386,7 +386,7 @@ dps_results: { key: "TestDisc-AllItems-GarbofFaith" value: { tps: 14.52615 - hps: 3418.32699 + hps: 3418.75382 } } dps_results: { @@ -644,15 +644,15 @@ dps_results: { dps_results: { key: "TestDisc-AllItems-SanctificationGarb" value: { - tps: 14.78178 - hps: 3535.22675 + tps: 14.79011 + hps: 3530.40997 } } dps_results: { key: "TestDisc-AllItems-SanctificationRegalia" value: { - tps: 14.64321 - hps: 3507.59616 + tps: 14.63905 + hps: 3509.97468 } } dps_results: { @@ -840,15 +840,15 @@ dps_results: { dps_results: { key: "TestDisc-AllItems-Zabra'sRaiment" value: { - tps: 14.84923 - hps: 3708.98145 + tps: 14.86221 + hps: 3732.2729 } } dps_results: { key: "TestDisc-AllItems-Zabra'sRegalia" value: { tps: 15.08364 - hps: 3426.15129 + hps: 3426.83291 } } dps_results: { diff --git a/sim/priest/mind_flay.go b/sim/priest/mind_flay.go index 09de613e93..d498721702 100644 --- a/sim/priest/mind_flay.go +++ b/sim/priest/mind_flay.go @@ -57,8 +57,10 @@ func (priest *Priest) newMindFlaySpell(numTicksIdx int32) *core.Spell { if wait > gcd && priest.Latency > 0 { base := priest.Latency * 0.67 variation := base + sim.RandomFloat("spriest latency")*base // should vary from 0.66 - 1.33 of given latency - variation = core.MaxFloat(variation, 10) // no player can go under XXXms response time cast.AfterCastDelay += time.Duration(variation) * time.Millisecond + if sim.Log != nil { + priest.Log(sim, "Latency: %0.02f, AfterCastDelay: %s", priest.Latency, cast.AfterCastDelay) + } } }, }, @@ -151,6 +153,5 @@ func (priest *Priest) AverageMindFlayLatencyDelay(numTicks int, gcd time.Duratio base := priest.Latency * 0.25 variation := base + 0.5*base - variation = core.MaxFloat(variation, 10) return time.Duration(variation) * time.Millisecond } diff --git a/sim/priest/priest.go b/sim/priest/priest.go index e4b3e014e3..80f7cb92b2 100644 --- a/sim/priest/priest.go +++ b/sim/priest/priest.go @@ -42,7 +42,9 @@ type Priest struct { ShadowWordPain *core.Spell MindBlast *core.Spell MindFlay []*core.Spell + MindFlayAPL *core.Spell MindSear []*core.Spell + MindSearAPL *core.Spell Penance *core.Spell PenanceHeal *core.Spell PowerWordShield *core.Spell @@ -133,8 +135,8 @@ func (priest *Priest) Initialize() { priest.registerPowerInfusionCD() if priest.IsUsingAPL { - priest.newMindFlaySpell(0) - priest.newMindSearSpell(0) + priest.MindFlayAPL = priest.newMindFlaySpell(0) + priest.MindSearAPL = priest.newMindSearSpell(0) } priest.MindFlay = []*core.Spell{ diff --git a/sim/priest/shadow_word_pain.go b/sim/priest/shadow_word_pain.go index 1bd376b118..4c998cb81f 100644 --- a/sim/priest/shadow_word_pain.go +++ b/sim/priest/shadow_word_pain.go @@ -49,6 +49,9 @@ func (priest *Priest) registerShadowWordPainSpell() { Label: "ShadowWordPain", OnGain: func(_ *core.Aura, _ *core.Simulation) { priest.MindBlast.DamageMultiplier *= twistedFaithMultiplier + if priest.MindFlayAPL != nil { + priest.MindFlayAPL.DamageMultiplier *= mindFlayMod + } for _, spell := range priest.MindFlay { if spell != nil { spell.DamageMultiplier *= mindFlayMod @@ -57,6 +60,9 @@ func (priest *Priest) registerShadowWordPainSpell() { }, OnExpire: func(_ *core.Aura, _ *core.Simulation) { priest.MindBlast.DamageMultiplier /= twistedFaithMultiplier + if priest.MindFlayAPL != nil { + priest.MindFlayAPL.DamageMultiplier /= mindFlayMod + } for _, spell := range priest.MindFlay { if spell != nil { spell.DamageMultiplier /= mindFlayMod diff --git a/sim/priest/talents.go b/sim/priest/talents.go index b0d55fc864..e72b3d4cfd 100644 --- a/sim/priest/talents.go +++ b/sim/priest/talents.go @@ -397,6 +397,9 @@ func (priest *Priest) applyMisery() { priest.VampiricTouch.RelatedAuras = append(priest.VampiricTouch.RelatedAuras, miseryAuras) } if priest.MindFlay[1] != nil { + if priest.IsUsingAPL { + priest.MindFlayAPL.RelatedAuras = append(priest.MindFlayAPL.RelatedAuras, miseryAuras) + } priest.MindFlay[1].RelatedAuras = append(priest.MindFlay[1].RelatedAuras, miseryAuras) priest.MindFlay[2].RelatedAuras = append(priest.MindFlay[2].RelatedAuras, miseryAuras) priest.MindFlay[3].RelatedAuras = append(priest.MindFlay[3].RelatedAuras, miseryAuras) diff --git a/ui/core/player.ts b/ui/core/player.ts index 4826006c62..e2fd163f7e 100644 --- a/ui/core/player.ts +++ b/ui/core/player.ts @@ -1225,6 +1225,7 @@ export class Player { toProto(forExport?: boolean, forSimming?: boolean): PlayerProto { const aplIsLaunched = aplLaunchStatuses[this.spec] == LaunchStatus.Launched; const gear = this.getGear(); + const aplRotation = forSimming ? this.getResolvedAplRotation() : this.aplRotation; return withSpecProto( this.spec, PlayerProto.create({ @@ -1235,10 +1236,12 @@ export class Player { consumes: this.getConsumes(), bonusStats: this.getBonusStats().toProto(), buffs: this.getBuffs(), - cooldowns: aplIsLaunched ? Cooldowns.create({ hpPercentForDefensives: this.getCooldowns().hpPercentForDefensives }) : this.getCooldowns(), + cooldowns: (aplIsLaunched || (forSimming && aplRotation.type == APLRotationType.TypeAPL)) + ? Cooldowns.create({ hpPercentForDefensives: this.getCooldowns().hpPercentForDefensives }) + : this.getCooldowns(), talentsString: this.getTalentsString(), glyphs: this.getGlyphs(), - rotation: forSimming ? this.getResolvedAplRotation() : this.aplRotation, + rotation: aplRotation, profession1: this.getProfession1(), profession2: this.getProfession2(), reactionTimeMs: this.getReactionTime(), @@ -1248,7 +1251,9 @@ export class Player { healingModel: this.getHealingModel(), database: forExport ? SimDatabase.create() : this.toDatabase(), }), - aplIsLaunched ? this.specTypeFunctions.rotationCreate() : this.getRotation(), + (aplIsLaunched || (forSimming && aplRotation.type == APLRotationType.TypeAPL)) + ? this.specTypeFunctions.rotationCreate() + : this.getRotation(), this.getSpecOptions()); } diff --git a/ui/shadow_priest/presets.ts b/ui/shadow_priest/presets.ts index 56b82d4066..6298543d48 100644 --- a/ui/shadow_priest/presets.ts +++ b/ui/shadow_priest/presets.ts @@ -3,9 +3,7 @@ import { EquipmentSpec } from '../core/proto/common.js'; import { Flask } from '../core/proto/common.js'; import { Food } from '../core/proto/common.js'; import { Glyphs } from '../core/proto/common.js'; -import { ItemSpec } from '../core/proto/common.js'; import { Potions } from '../core/proto/common.js'; -import { Faction } from '../core/proto/common.js'; import { RaidBuffs } from '../core/proto/common.js'; import { IndividualBuffs } from '../core/proto/common.js'; import { Debuffs } from '../core/proto/common.js'; @@ -191,14 +189,30 @@ export const P3_PRESET = { ] }`), }; -export const ROTATION_PRESET_BASIC_APL = { - name: 'Basic APL', +export const ROTATION_PRESET_DEFAULT = { + name: 'Default', rotation: SavedRotation.create({ - specRotationOptionsJson: Rotation.toJsonString(DefaultRotation), + specRotationOptionsJson: Rotation.toJsonString(Rotation.create()), rotation: APLRotation.fromJsonString(`{ "type": "TypeAPL", + "prepullActions": [ + {"action":{"castSpell":{"spellId":{"otherId":"OtherActionPotion"}}},"doAtValue":{"const":{"val":"-1s"}}}, + {"action":{"castSpell":{"spellId":{"spellId":48160}}},"doAtValue":{"const":{"val":"-0.97s"}}} + ], "priorityList": [ + {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"0s"}}}},"castSpell":{"spellId":{"spellId":34433}}}}, + {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"currentTime":{}},"rhs":{"const":{"val":"1s"}}}},"autocastOtherCooldowns":{}}}, + {"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"currentTime":{}},"rhs":{"const":{"val":"61s"}}}},"castSpell":{"spellId":{"otherId":"OtherActionPotion"}}}}, + {"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"2s"}}}},"castSpell":{"spellId":{"spellId":48300}}}}, + {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":48125}}}}},{"or":{"vals":[{"and":{"vals":[{"cmp":{"op":"OpEq","lhs":{"const":{"val":"5"}},"rhs":{"auraNumStacks":{"auraId":{"spellId":15258}}}}},{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"75s"}}}}]}},{"and":{"vals":[{"cmp":{"op":"OpLe","lhs":{"const":{"val":"3"}},"rhs":{"auraNumStacks":{"auraId":{"spellId":15258}}}}},{"cmp":{"op":"OpLt","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"75s"}}}}]}}]}}]}},"castSpell":{"spellId":{"spellId":48125}}}}, + {"action":{"condition":{"cmp":{"op":"OpLe","lhs":{"dotRemainingTime":{"spellId":{"spellId":48160}}},"rhs":{"spellCastTime":{"spellId":{"spellId":48160}}}}},"castSpell":{"spellId":{"spellId":48160}}}}, + {"action":{"condition":{"not":{"val":{"dotIsActive":{"spellId":{"spellId":48300}}}}},"castSpell":{"spellId":{"spellId":48300}}}}, + {"hide":true,"action":{"condition":{"and":{"vals":[{"cmp":{"op":"OpGe","lhs":{"spellCastTime":{"spellId":{"spellId":48127}}},"rhs":{"const":{"val":"750ms"}}}},{"cmp":{"op":"OpLe","lhs":{"auraRemainingTime":{"auraId":{"spellId":57669}}},"rhs":{"const":{"val":"5s"}}}}]}},"castSpell":{"spellId":{"spellId":48127}}}}, + {"hide":true,"action":{"condition":{"cmp":{"op":"OpGe","lhs":{"spellCastTime":{"spellId":{"spellId":48127}}},"rhs":{"const":{"val":"750ms"}}}},"castSpell":{"spellId":{"spellId":48127}}}}, + {"action":{"condition":{"cmp":{"op":"OpEq","lhs":{"auraNumStacks":{"auraId":{"spellId":15258}}},"rhs":{"const":{"val":"5"}}}},"strictSequence":{"actions":[{"castSpell":{"spellId":{"spellId":14751}}},{"castSpell":{"spellId":{"spellId":48156}}}]}}}, + {"action":{"channelSpell":{"spellId":{"spellId":48156},"interruptIf":{"const":{"val":"true"}}}}}, + {"action":{"castSpell":{"spellId":{"spellId":47585}}}} ] - }`), + }`), }), - }; \ No newline at end of file +}; \ No newline at end of file diff --git a/ui/shadow_priest/sim.ts b/ui/shadow_priest/sim.ts index 24db349ee7..9b5f4b5e0d 100644 --- a/ui/shadow_priest/sim.ts +++ b/ui/shadow_priest/sim.ts @@ -140,7 +140,7 @@ export class ShadowPriestSimUI extends IndividualSimUI { Presets.StandardTalents, ], rotations: [ - Presets.ROTATION_PRESET_BASIC_APL, + Presets.ROTATION_PRESET_DEFAULT, ], // Preset gear configurations that the user can quickly select. gear: [