diff --git a/sim/core/attack.go b/sim/core/attack.go index aa601b5b16..4827d143eb 100644 --- a/sim/core/attack.go +++ b/sim/core/attack.go @@ -275,7 +275,7 @@ func (wa *WeaponAttack) swing(sim *Simulation) time.Duration { wa.swingAt = sim.CurrentTime + wa.curSwingDuration attackSpell.Cast(sim, wa.unit.CurrentTarget) - if !sim.Options.Interactive { + if !sim.Options.Interactive && wa.unit.Rotation != nil { wa.unit.Rotation.DoNextAction(sim) } diff --git a/sim/deathknight/dps/TestBlood.results b/sim/deathknight/dps/TestBlood.results index 5102649157..a4f19e677b 100644 --- a/sim/deathknight/dps/TestBlood.results +++ b/sim/deathknight/dps/TestBlood.results @@ -287,8 +287,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-EphemeralSnowflake-50260" value: { - dps: 10467.28296 - tps: 5296.53902 + dps: 10443.90447 + tps: 5277.80696 } } dps_results: { @@ -666,8 +666,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 10350.69235 - tps: 5235.5789 + dps: 10383.49361 + tps: 5254.72979 } } dps_results: { @@ -778,8 +778,8 @@ dps_results: { dps_results: { key: "TestBlood-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 10317.50284 - tps: 5211.82802 + dps: 10379.62764 + tps: 5242.10503 } } dps_results: { diff --git a/sim/deathknight/dps/TestUnholy.results b/sim/deathknight/dps/TestUnholy.results index e31fee5d05..b00336dda8 100644 --- a/sim/deathknight/dps/TestUnholy.results +++ b/sim/deathknight/dps/TestUnholy.results @@ -46,984 +46,984 @@ character_stats_results: { dps_results: { key: "TestUnholy-AllItems-Althor'sAbacus-50359" value: { - dps: 9680.47429 - tps: 5704.45855 + dps: 9710.58503 + tps: 5711.54761 hps: 63.52617 } } dps_results: { key: "TestUnholy-AllItems-Althor'sAbacus-50366" value: { - dps: 9680.47429 - tps: 5704.45855 + dps: 9710.58503 + tps: 5711.54761 hps: 66.3402 } } dps_results: { key: "TestUnholy-AllItems-AustereEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-Bandit'sInsignia-40371" value: { - dps: 9893.9745 - tps: 5859.94867 + dps: 9924.17016 + tps: 5866.99266 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-BaubleofTrueBlood-50354" value: { - dps: 9680.48618 - tps: 5704.5175 + dps: 9710.59693 + tps: 5711.60656 hps: 134.78881 } } dps_results: { key: "TestUnholy-AllItems-BaubleofTrueBlood-50726" value: { - dps: 9680.48618 - tps: 5704.5175 + dps: 9710.59693 + tps: 5711.60656 hps: 134.78881 } } dps_results: { key: "TestUnholy-AllItems-BeamingEarthsiegeDiamond" value: { - dps: 10240.42421 - tps: 5900.33685 + dps: 10270.83734 + tps: 5906.78165 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Beast-tamer'sShoulders-30892" value: { - dps: 9561.27606 - tps: 5428.86625 + dps: 9590.63003 + tps: 5434.59411 hps: 40.4349 } } dps_results: { key: "TestUnholy-AllItems-BlessedBattlegearofUndeadSlaying" value: { - dps: 7500.6957 - tps: 4266.20781 + dps: 7528.9716 + tps: 4272.7715 hps: 34.38394 } } dps_results: { key: "TestUnholy-AllItems-BlessedGarboftheUndeadSlayer" value: { - dps: 7390.28759 - tps: 4234.65809 + dps: 7417.57124 + tps: 4240.52367 hps: 32.96775 } } dps_results: { key: "TestUnholy-AllItems-BlessedRegaliaofUndeadCleansing" value: { - dps: 7173.57707 - tps: 4090.382 + dps: 7201.24066 + tps: 4096.56066 hps: 32.72866 } } dps_results: { key: "TestUnholy-AllItems-BracingEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5762.92136 + dps: 10248.30721 + tps: 5769.21867 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Bryntroll,theBoneArbiter-50415" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Bryntroll,theBoneArbiter-50709" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ChaoticSkyflareDiamond" value: { - dps: 10353.5962 - tps: 5995.41414 + dps: 10384.12635 + tps: 6001.95118 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorpseTongueCoin-50349" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorpseTongueCoin-50352" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-CorrodedSkeletonKey-50356" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 110.32034 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Berserker!-42989" value: { - dps: 9811.44494 - tps: 5817.02786 + dps: 9841.85262 + tps: 5824.32161 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Death-42990" value: { - dps: 9873.64594 - tps: 5864.21871 + dps: 9904.01516 + tps: 5871.41583 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkmoonCard:Greatness-44255" value: { - dps: 9986.29823 - tps: 5844.5239 + dps: 10016.40898 + tps: 5851.61296 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DarkrunedBattlegear" value: { - dps: 8313.25385 - tps: 4722.11602 + dps: 8342.40652 + tps: 4728.74456 hps: 38.90837 } } dps_results: { key: "TestUnholy-AllItems-DarkrunedPlate" value: { - dps: 7427.64393 - tps: 4189.2183 + dps: 7455.04498 + tps: 4195.27998 hps: 40.98666 } } dps_results: { key: "TestUnholy-AllItems-DeadlyGladiator'sSigilofStrife-42620" value: { - dps: 10398.41427 - tps: 6019.99796 + dps: 10428.94056 + tps: 6026.53603 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DeathKnight'sAnguish-38212" value: { - dps: 9784.41797 - tps: 5793.32415 + dps: 9814.76517 + tps: 5800.54798 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Deathbringer'sWill-50362" value: { - dps: 10212.23545 - tps: 6011.7831 + dps: 10244.26393 + tps: 6019.38836 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Deathbringer'sWill-50363" value: { - dps: 10304.74071 - tps: 6126.35152 + dps: 10336.93352 + tps: 6134.04278 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Defender'sCode-40257" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DestructiveSkyflareDiamond" value: { - dps: 10245.17112 - tps: 5903.63941 + dps: 10275.66073 + tps: 5910.13257 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DislodgedForeignObject-50348" value: { - dps: 10027.7374 - tps: 5913.21833 + dps: 10058.86423 + tps: 5920.2823 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-DislodgedForeignObject-50353" value: { - dps: 10015.90074 - tps: 5863.92416 + dps: 10045.90755 + tps: 5870.04449 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EffulgentSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-EmberSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EnigmaticSkyflareDiamond" value: { - dps: 10240.42421 - tps: 5900.33685 + dps: 10270.83734 + tps: 5906.78165 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EnigmaticStarflareDiamond" value: { - dps: 10238.88528 - tps: 5898.8624 + dps: 10269.30196 + tps: 5905.31005 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EphemeralSnowflake-50260" value: { - dps: 9957.51073 - tps: 5686.58021 + dps: 9960.43305 + tps: 5713.77531 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EssenceofGossamer-37220" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 44.16848 } } dps_results: { key: "TestUnholy-AllItems-EternalEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ExtractofNecromanticPower-40373" value: { - dps: 9854.14952 - tps: 5848.27771 + dps: 9884.46426 + tps: 5855.45523 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-EyeoftheBroodmother-45308" value: { - dps: 9799.48063 - tps: 5805.4028 + dps: 9829.83582 + tps: 5812.66149 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Figurine-SapphireOwl-42413" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForethoughtTalisman-40258" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForgeEmber-37660" value: { - dps: 9778.71591 - tps: 5788.07856 + dps: 9809.03194 + tps: 5795.31409 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForlornSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ForlornStarflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuriousGladiator'sSigilofStrife-42621" value: { - dps: 10408.71405 - tps: 6026.07503 + dps: 10439.24034 + tps: 6032.61311 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuryoftheFiveFlights-40431" value: { - dps: 9905.69267 - tps: 5871.20429 + dps: 9935.80342 + tps: 5878.29335 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-FuturesightRune-38763" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GlowingTwilightScale-54573" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GlowingTwilightScale-54589" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-GnomishLightningGenerator-41121" value: { - dps: 9832.05026 - tps: 5830.41915 + dps: 9862.40069 + tps: 5837.60588 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-HatefulGladiator'sSigilofStrife-42619" value: { - dps: 10376.42406 - tps: 6005.85502 + dps: 10406.95035 + tps: 6012.39309 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-IllustrationoftheDragonSoul-40432" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ImpassiveSkyflareDiamond" value: { - dps: 10240.42421 - tps: 5900.33685 + dps: 10270.83734 + tps: 5906.78165 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ImpassiveStarflareDiamond" value: { - dps: 10238.88528 - tps: 5898.8624 + dps: 10269.30196 + tps: 5905.31005 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-IncisorFragment-37723" value: { - dps: 9858.84411 - tps: 5841.99589 + dps: 9889.84971 + tps: 5849.80123 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-InsightfulEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-InvigoratingEarthsiegeDiamond" value: { - dps: 10250.43861 - tps: 5903.12227 + dps: 10280.82071 + tps: 5909.54809 hps: 58.71565 } } dps_results: { key: "TestUnholy-AllItems-LastWord-50179" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-LastWord-50708" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Lavanthor'sTalisman-37872" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-MajesticDragonFigurine-40430" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-MeteoriteWhetstone-37390" value: { - dps: 10002.66676 - tps: 5837.61294 + dps: 10032.0625 + tps: 5843.61227 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-NevermeltingIceCrystal-50259" value: { - dps: 9829.70588 - tps: 5834.98049 + dps: 9859.78621 + tps: 5842.11561 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-OfferingofSacrifice-37638" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PersistentEarthshatterDiamond" value: { - dps: 10244.24556 - tps: 5898.81936 + dps: 10274.62766 + tps: 5905.24519 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PersistentEarthsiegeDiamond" value: { - dps: 10250.43861 - tps: 5903.12227 + dps: 10280.82071 + tps: 5909.54809 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedScarab-21685" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedTwilightScale-54571" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PetrifiedTwilightScale-54591" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-PowerfulEarthshatterDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.60516 } } dps_results: { key: "TestUnholy-AllItems-PowerfulEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.71551 } } dps_results: { key: "TestUnholy-AllItems-PurifiedShardoftheGods" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ReignoftheDead-47316" value: { - dps: 9754.94571 - tps: 5763.56884 + dps: 9785.06353 + tps: 5770.6385 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ReignoftheDead-47477" value: { - dps: 9762.03411 - tps: 5769.56958 + dps: 9792.15193 + tps: 5776.63924 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RelentlessEarthsiegeDiamond" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RelentlessGladiator'sSigilofStrife-42622" value: { - dps: 10420.73045 - tps: 6033.16496 + dps: 10451.25674 + tps: 6039.70303 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RevitalizingSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-RuneofRepulsion-40372" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SavageGladiator'sSigilofStrife-42618" value: { - dps: 10373.08345 - tps: 6004.01625 + dps: 10403.60974 + tps: 6010.55432 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ScourgeborneBattlegear" value: { - dps: 8000.74515 - tps: 4559.84406 + dps: 8029.52875 + tps: 4566.12376 hps: 36.48062 } } dps_results: { key: "TestUnholy-AllItems-ScourgebornePlate" value: { - dps: 7338.02073 - tps: 4115.32448 + dps: 7364.82744 + tps: 4120.861 hps: 38.04394 } } dps_results: { key: "TestUnholy-AllItems-Scourgelord'sBattlegear" value: { - dps: 9330.42072 - tps: 5515.28971 + dps: 9358.46371 + tps: 5521.64302 hps: 44.60989 } } dps_results: { key: "TestUnholy-AllItems-Scourgelord'sPlate" value: { - dps: 8192.96648 - tps: 4636.93277 + dps: 8219.42444 + tps: 4642.08454 hps: 48.06758 } } dps_results: { key: "TestUnholy-AllItems-SealofthePantheon-36993" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Shadowmourne-49623" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-ShinyShardoftheGods" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofDeflection-45144" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofHauntedDreams-40715" value: { - dps: 10376.62308 - tps: 6015.42194 + dps: 10407.04323 + tps: 6021.87725 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigilofInsolence-47672" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheBoneGryphon-50462" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheHangedMan-50459" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SigiloftheUnfalteringKnight-40714" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Sindragosa'sFlawlessFang-50361" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 46.32034 } } dps_results: { key: "TestUnholy-AllItems-SliverofPureIce-50339" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SliverofPureIce-50346" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SoulPreserver-37111" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SouloftheDead-40382" value: { - dps: 9802.43285 - tps: 5808.86704 + dps: 9832.82416 + tps: 5816.15563 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SparkofLife-37657" value: { - dps: 9832.06089 - tps: 5797.8349 + dps: 9862.05029 + tps: 5804.30139 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SphereofRedDragon'sBlood-37166" value: { - dps: 9800.6582 - tps: 5811.52763 + dps: 9913.75663 + tps: 5850.97982 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-StormshroudArmor" value: { - dps: 7067.22499 - tps: 4050.80338 + dps: 7095.52999 + tps: 4057.87955 hps: 30.7975 } } dps_results: { key: "TestUnholy-AllItems-SwiftSkyflareDiamond" value: { - dps: 10250.43861 - tps: 5903.12227 + dps: 10280.82071 + tps: 5909.54809 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SwiftStarflareDiamond" value: { - dps: 10244.24556 - tps: 5898.81936 + dps: 10274.62766 + tps: 5905.24519 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-SwiftWindfireDiamond" value: { - dps: 10233.40773 - tps: 5891.28927 + dps: 10263.78983 + tps: 5897.7151 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TalismanofTrollDivinity-37734" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TearsoftheVanquished-47215" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-Thassarian'sBattlegear" value: { - dps: 8590.35604 - tps: 4952.61627 + dps: 8618.51653 + tps: 4958.8001 hps: 38.68766 } } dps_results: { key: "TestUnholy-AllItems-Thassarian'sPlate" value: { - dps: 7458.635 - tps: 4188.82468 + dps: 7486.10663 + tps: 4194.90667 hps: 40.30616 } } dps_results: { key: "TestUnholy-AllItems-TheGeneral'sHeart-45507" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TheTwinBladesofAzzinoth" value: { - dps: 8979.88721 - tps: 5025.14863 + dps: 9010.98248 + tps: 5032.12724 hps: 40.74757 } } dps_results: { key: "TestUnholy-AllItems-ThunderingSkyflareDiamond" value: { - dps: 10275.22899 - tps: 5912.27746 + dps: 10305.50604 + tps: 5918.26645 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TinyAbominationinaJar-50351" value: { - dps: 9924.59603 - tps: 5907.08552 + dps: 9954.00729 + tps: 5913.58867 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TinyAbominationinaJar-50706" value: { - dps: 9890.45908 - tps: 5873.52857 + dps: 9920.42339 + tps: 5880.41645 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TirelessSkyflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TirelessStarflareDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TomeofArcanePhenomena-36972" value: { - dps: 9826.9966 - tps: 5751.9898 + dps: 9840.77218 + tps: 5774.12915 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TrenchantEarthshatterDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-TrenchantEarthsiegeDiamond" value: { - dps: 10217.92511 - tps: 5880.532 + dps: 10248.30721 + tps: 5886.95782 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-UndeadSlayer'sBlessedArmor" value: { - dps: 7395.21167 - tps: 4250.00861 + dps: 7423.03446 + tps: 4256.35867 hps: 33.68504 } } dps_results: { key: "TestUnholy-AllItems-Val'anyr,HammerofAncientKings-46017" value: { - dps: 9602.82536 - tps: 5420.6152 + dps: 9633.49282 + tps: 5427.26413 hps: 42.81036 } } dps_results: { key: "TestUnholy-AllItems-WingedTalisman-37844" value: { - dps: 9680.49504 - tps: 5704.45555 + dps: 9710.60578 + tps: 5711.54461 hps: 42.12697 } } dps_results: { key: "TestUnholy-AllItems-WrathfulGladiator'sSigilofStrife-51417" value: { - dps: 10434.46349 - tps: 6041.26773 + dps: 10464.98978 + tps: 6047.8058 hps: 42.12697 } } dps_results: { key: "TestUnholy-Average-Default" value: { - dps: 10279.57916 - tps: 5964.26539 + dps: 10310.79563 + tps: 5971.29709 hps: 42.14164 } } @@ -1174,152 +1174,152 @@ dps_results: { dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-LongMultiTarget" value: { - dps: 14275.55112 - tps: 9275.62941 + dps: 14312.2404 + tps: 9287.052 hps: 42.12697 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-LongSingleTarget" value: { - dps: 10346.91539 - tps: 5989.61257 + dps: 10377.44167 + tps: 5996.15064 hps: 42.12697 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-FullBuffs-ShortSingleTarget" value: { - dps: 15451.74278 - tps: 7165.07213 + dps: 15559.83451 + tps: 7162.15963 hps: 210.63484 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-LongMultiTarget" value: { - dps: 6761.4395 - tps: 4575.413 + dps: 6783.40918 + tps: 4583.6299 hps: 27.7272 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-LongSingleTarget" value: { - dps: 5085.97636 - tps: 3172.95627 + dps: 5103.61606 + tps: 3177.62391 hps: 27.7272 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_2h_ss-NoBuffs-ShortSingleTarget" value: { - dps: 6701.62049 - tps: 3491.63258 + dps: 6757.40436 + tps: 3489.08968 hps: 138.636 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-LongMultiTarget" value: { - dps: 59321.04606 - tps: 61361.65332 + dps: 59452.42669 + tps: 61476.73056 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-LongSingleTarget" value: { - dps: 11318.78456 - tps: 7472.9393 + dps: 11354.57131 + tps: 7485.7125 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-FullBuffs-ShortSingleTarget" value: { - dps: 16412.5451 - tps: 8686.56163 + dps: 16535.42503 + tps: 8698.33633 hps: 337.01574 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-LongMultiTarget" value: { - dps: 35117.90018 - tps: 37478.75367 + dps: 35212.15599 + tps: 37565.37369 hps: 155.82686 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-LongSingleTarget" value: { - dps: 5750.84606 - tps: 4175.86894 + dps: 5772.20815 + tps: 4185.27192 hps: 155.27232 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-uh_dnd_aoe-NoBuffs-ShortSingleTarget" value: { - dps: 7280.02322 - tps: 4471.44132 + dps: 7347.6605 + tps: 4481.15645 hps: 221.8176 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-LongMultiTarget" value: { - dps: 36238.79517 - tps: 43195.85148 + dps: 36324.85779 + tps: 43276.25499 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-LongSingleTarget" value: { - dps: 11434.83628 - tps: 7578.90963 + dps: 11470.17283 + tps: 7591.32914 hps: 236.33229 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-FullBuffs-ShortSingleTarget" value: { - dps: 16487.2343 - tps: 8798.61633 + dps: 16608.09173 + tps: 8808.92846 hps: 339.12209 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-LongMultiTarget" value: { - dps: 18696.93865 - tps: 22871.51167 + dps: 18749.83496 + tps: 22923.25478 hps: 155.82686 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-LongSingleTarget" value: { - dps: 5876.43297 - tps: 4281.49641 + dps: 5897.73441 + tps: 4290.70565 hps: 155.27232 } } dps_results: { key: "TestUnholy-Settings-Orc-p3_uh_dw-Basic-unholy_dw_ss-NoBuffs-ShortSingleTarget" value: { - dps: 7351.97253 - tps: 4548.398 + dps: 7417.6708 + tps: 4556.06307 hps: 221.8176 } } dps_results: { key: "TestUnholy-SwitchInFrontOfTarget-Default" value: { - dps: 9815.01951 - tps: 5629.20041 + dps: 9845.43373 + tps: 5635.64895 hps: 42.12697 } } diff --git a/sim/druid/balance/balance.go b/sim/druid/balance/balance.go index f5206e3878..d0cea4e797 100644 --- a/sim/druid/balance/balance.go +++ b/sim/druid/balance/balance.go @@ -32,9 +32,8 @@ func NewBalanceDruid(character *core.Character, options *proto.Player) *BalanceD selfBuffs := druid.SelfBuffs{} moonkin := &BalanceDruid{ - Druid: druid.New(character, druid.Moonkin, selfBuffs, options.TalentsString), - Options: balanceOptions.Options, - Rotation: balanceOptions.Rotation, + Druid: druid.New(character, druid.Moonkin, selfBuffs, options.TalentsString), + Options: balanceOptions.Options, } moonkin.SelfBuffs.InnervateTarget = &proto.UnitReference{} @@ -42,7 +41,6 @@ func NewBalanceDruid(character *core.Character, options *proto.Player) *BalanceD moonkin.SelfBuffs.InnervateTarget = balanceOptions.Options.InnervateTarget } - moonkin.EnableResumeAfterManaWait(moonkin.tryUseGCD) wotlk.ConstructValkyrPets(&moonkin.Character) return moonkin } @@ -55,19 +53,7 @@ type BalanceOnUseTrinket struct { type BalanceDruid struct { *druid.Druid - Options *proto.BalanceDruid_Options - Rotation *proto.BalanceDruid_Rotation - CooldownsAvailable []*core.MajorCooldown - LastCast *druid.DruidSpell - - // CDS - hyperSpeedMCD *core.MajorCooldown - potionSpeedMCD *core.MajorCooldown - potionWildMagicMCD *core.MajorCooldown - powerInfusion *core.MajorCooldown - onUseTrinket1 BalanceOnUseTrinket - onUseTrinket2 BalanceOnUseTrinket - potionUsed bool + Options *proto.BalanceDruid_Options } func (moonkin *BalanceDruid) GetDruid() *druid.Druid { @@ -78,70 +64,14 @@ func (moonkin *BalanceDruid) Initialize() { moonkin.Druid.Initialize() moonkin.RegisterBalanceSpells() - moonkin.Env.RegisterPreFinalizeEffect(func() { - if moonkin.OwlkinFrenzyAura != nil && moonkin.Options.OkfUptime > 0 { + if moonkin.OwlkinFrenzyAura != nil && moonkin.Options.OkfUptime > 0 { + moonkin.Env.RegisterPreFinalizeEffect(func() { core.ApplyFixedUptimeAura(moonkin.OwlkinFrenzyAura, float64(moonkin.Options.OkfUptime), time.Second*5, 0) - } - }) + }) + } } func (moonkin *BalanceDruid) Reset(sim *core.Simulation) { moonkin.Druid.Reset(sim) moonkin.RebirthTiming = moonkin.Env.BaseDuration.Seconds() * sim.RandomFloat("Rebirth Timing") - - if moonkin.Rotation.Type == proto.BalanceDruid_Rotation_Default { - moonkin.Rotation.MfUsage = proto.BalanceDruid_Rotation_BeforeLunar - moonkin.Rotation.IsUsage = proto.BalanceDruid_Rotation_OptimizeIs - moonkin.Rotation.WrathUsage = proto.BalanceDruid_Rotation_RegularWrath - moonkin.Rotation.UseBattleRes = false - moonkin.Rotation.UseStarfire = true - moonkin.Rotation.UseTyphoon = false - moonkin.Rotation.UseHurricane = false - moonkin.Rotation.UseSmartCooldowns = true - moonkin.Rotation.MaintainFaerieFire = true - moonkin.Rotation.PlayerLatency = 200 - } - - if moonkin.Rotation.UseSmartCooldowns { - moonkin.potionUsed = false - consumes := moonkin.Consumes - - if consumes.DefaultPotion == proto.Potions_PotionOfSpeed { - moonkin.potionSpeedMCD = moonkin.getBalanceMajorCooldown(core.ActionID{ItemID: 40211}) - } - if consumes.DefaultPotion == proto.Potions_PotionOfWildMagic { - moonkin.potionWildMagicMCD = moonkin.getBalanceMajorCooldown(core.ActionID{ItemID: 40212}) - } - if moonkin.HasProfession(proto.Profession_Engineering) { - moonkin.hyperSpeedMCD = moonkin.getBalanceMajorCooldown(core.ActionID{SpellID: 54758}) - } - moonkin.powerInfusion = moonkin.getBalanceMajorCooldown(core.ActionID{SpellID: 10060}) - moonkin.onUseTrinket1 = BalanceOnUseTrinket{ - Cooldown: moonkin.getBalanceMajorCooldown(core.ActionID{ItemID: moonkin.Trinket1().ID}), - Stat: getOnUseTrinketStat(moonkin.Trinket1().ID), - } - moonkin.onUseTrinket2 = BalanceOnUseTrinket{ - Cooldown: moonkin.getBalanceMajorCooldown(core.ActionID{ItemID: moonkin.Trinket2().ID}), - Stat: getOnUseTrinketStat(moonkin.Trinket2().ID), - } - } -} - -// Takes out a Cooldown from the generic MajorCooldownManager and adds it to a custom Slice of Cooldowns -func (moonkin *BalanceDruid) getBalanceMajorCooldown(actionID core.ActionID) *core.MajorCooldown { - if majorCd := moonkin.Character.GetMajorCooldownIgnoreTag(actionID); majorCd != nil { - majorCd.Disable() - return majorCd - } - return nil -} - -func getOnUseTrinketStat(itemId int32) stats.Stat { - if itemId == 45466 || itemId == 48722 || itemId == 47726 || itemId == 47946 || itemId == 36972 { - return stats.SpellHaste - } - if itemId == 50259 { - return stats.SpellCrit - } - return stats.SpellPower } diff --git a/sim/druid/balance/rotation.go b/sim/druid/balance/rotation.go deleted file mode 100644 index e0a633aad4..0000000000 --- a/sim/druid/balance/rotation.go +++ /dev/null @@ -1,256 +0,0 @@ -package balance - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" - "github.com/wowsims/wotlk/sim/core/proto" - "github.com/wowsims/wotlk/sim/core/stats" - "github.com/wowsims/wotlk/sim/druid" -) - -func (moonkin *BalanceDruid) OnGCDReady(sim *core.Simulation) { - moonkin.tryUseGCD(sim) -} - -func (moonkin *BalanceDruid) tryUseGCD(sim *core.Simulation) { - spell, target := moonkin.rotation(sim) - if success := spell.Cast(sim, target); !success { - moonkin.WaitForMana(sim, spell.CurCast.Cost) - } - moonkin.LastCast = spell -} - -func (moonkin *BalanceDruid) rotation(sim *core.Simulation) (*druid.DruidSpell, *core.Unit) { - moonkin.CurrentTarget = sim.Environment.GetTargetUnit(0) - rotation := moonkin.Rotation - target := moonkin.CurrentTarget - - if rotation.MaintainFaerieFire && moonkin.ShouldFaerieFire(sim, moonkin.CurrentTarget) { - return moonkin.FaerieFire, target - } - - if sim.GetRemainingDuration() < 15*time.Second { - moonkin.castMajorCooldown(moonkin.hyperSpeedMCD, sim, target) - moonkin.castMajorCooldown(moonkin.potionSpeedMCD, sim, target) - moonkin.castMajorCooldown(moonkin.potionWildMagicMCD, sim, target) - moonkin.useTrinkets(stats.SpellHaste, sim, target) - moonkin.useTrinkets(stats.SpellPower, sim, target) - moonkin.useTrinkets(stats.SpellCrit, sim, target) - } - - if rotation.SnapshotMf { - flareProc := moonkin.GetAura("Flare of the Heavens Proc") - pleaProc := moonkin.GetAura("Pandora's Plea Proc") - wildMagicProc := moonkin.GetAura("Potion of Wild Magic") - shouldCheckForSnapshot := flareProc.IsActive() || pleaProc.IsActive() || (wildMagicProc.IsActive() && sim.CurrentTime > 60*time.Second) - if shouldCheckForSnapshot { - if moonkin.shouldSnapshotMf(sim, flareProc) || moonkin.shouldSnapshotMf(sim, wildMagicProc) || moonkin.shouldSnapshotMf(sim, pleaProc) { - return moonkin.Moonfire, target - } - } - } - - var lunarUptime time.Duration - shouldRefreshMf := moonkin.Moonfire.CurDot().RemainingDuration(sim) <= 0 - hasLunarFury := core.Ternary(moonkin.Ranged().ID == 47670, true, false) - lunarIsActive := moonkin.LunarEclipseProcAura.IsActive() - maximizeMf := !(rotation.MfUsage == proto.BalanceDruid_Rotation_NoMf) && !(rotation.MfUsage == proto.BalanceDruid_Rotation_BeforeLunar) && !(rotation.SnapshotMf) - - if moonkin.LunarEclipseProcAura != nil { - lunarUptime = moonkin.LunarEclipseProcAura.RemainingDuration(sim) - } - if moonkin.MoonkinT84PCAura.IsActive() && moonkin.MoonkinT84PCAura.RemainingDuration(sim) < moonkin.SpellGCD() { - return moonkin.Starfire, target - } else if rotation.UseBattleRes && sim.GetRemainingDuration().Seconds() < moonkin.RebirthTiming && moonkin.Rebirth.IsReady(sim) { - return moonkin.Rebirth, target - } else if maximizeMf && shouldRefreshMf && hasLunarFury { - return moonkin.Moonfire, target - } else if moonkin.Talents.ForceOfNature && moonkin.ForceOfNature.IsReady(sim) && !lunarIsActive { - moonkin.useTrinkets(stats.SpellPower, sim, target) - return moonkin.ForceOfNature, target - } else if moonkin.Starfall.IsReady(sim) && !lunarIsActive { - moonkin.useTrinkets(stats.SpellPower, sim, target) - return moonkin.Starfall, target - } else if moonkin.Typhoon.IsReady(sim) && rotation.UseTyphoon { - return moonkin.Typhoon, target - } else if rotation.UseHurricane { - return moonkin.Hurricane, target - } - - shouldHoldIs := core.Ternary(moonkin.MoonkinT84PCAura == nil, lunarIsActive, lunarIsActive && moonkin.HasActiveAura("Bloodlust-"+core.BloodlustActionID.WithTag(-1).String())) - - // Max IS uptime - if rotation.IsUsage == proto.BalanceDruid_Rotation_OptimizeIs && !shouldHoldIs { - if moonkin.InsectSwarm.CurDot().RemainingDuration(sim) <= 0 { - return moonkin.InsectSwarm, target - } - } else if rotation.IsUsage == proto.BalanceDruid_Rotation_MultidotIs { - for range sim.Encounter.Targets { - if moonkin.InsectSwarm.CurDot().RemainingDuration(sim) <= 0 { - return moonkin.InsectSwarm, moonkin.CurrentTarget - } - moonkin.CurrentTarget = sim.Environment.NextTargetUnit(moonkin.CurrentTarget) - } - } - - // Max MF uptime - if rotation.MfUsage == proto.BalanceDruid_Rotation_MaximizeMf && shouldRefreshMf { - return moonkin.Moonfire, target - } else if rotation.MfUsage == proto.BalanceDruid_Rotation_MultidotMf { - for range sim.Encounter.Targets { - if moonkin.Moonfire.CurDot().RemainingDuration(sim) <= 0 { - return moonkin.Moonfire, moonkin.CurrentTarget - } - moonkin.CurrentTarget = sim.Environment.NextTargetUnit(moonkin.CurrentTarget) - } - } - - // Player "brain" latency - playerLatency := time.Duration(max(rotation.PlayerLatency, 0)) * time.Millisecond - lunarICD := moonkin.LunarICD.Timer.TimeToReady(sim) - solarICD := moonkin.SolarICD.Timer.TimeToReady(sim) - canExtendMf := rotation.MfExtension == proto.BalanceDruid_Rotation_ExtendAlways || rotation.MfExtension == proto.BalanceDruid_Rotation_ExtendOutsideSolar - - if moonkin.Talents.Eclipse > 0 { - solarUptime := moonkin.SolarEclipseProcAura.ExpiresAt() - sim.CurrentTime - solarIsActive := moonkin.SolarEclipseProcAura.IsActive() - - //"Dispelling" eclipse effects before casting if needed - if float64(lunarUptime-moonkin.Starfire.CurCast.CastTime) <= 0 { - moonkin.LunarEclipseProcAura.Deactivate(sim) - lunarIsActive = false - } - if float64(solarUptime-moonkin.Wrath.CurCast.CastTime) <= 0 { - moonkin.SolarEclipseProcAura.Deactivate(sim) - solarIsActive = false - } - // Player latency adjustments - if lunarIsActive { - lunarIsActive = lunarUptime < (moonkin.LunarEclipseProcAura.Duration - playerLatency) - } - if solarIsActive { - solarIsActive = solarUptime < (moonkin.SolarEclipseProcAura.Duration - playerLatency) - solarICD = 0 - } - - // Eclipse - if solarIsActive || lunarIsActive { - if lunarIsActive { - if canExtendMf && moonkin.ExtendingMoonfireStacks == 0 { - if extendTarget := moonkin.tryExtendMoonfire(sim); extendTarget != nil { - return moonkin.Moonfire, extendTarget - } - } - if (rotation.UseSmartCooldowns && lunarUptime > 10*time.Second) || sim.GetRemainingDuration() < 15*time.Second { - moonkin.castMajorCooldown(moonkin.hyperSpeedMCD, sim, target) - moonkin.castMajorCooldown(moonkin.potionSpeedMCD, sim, target) - moonkin.useTrinkets(stats.SpellHaste, sim, target) - if !moonkin.HasActiveAura("Bloodlust-" + core.BloodlustActionID.WithTag(-1).String()) { - moonkin.castMajorCooldown(moonkin.powerInfusion, sim, target) - } - } - return moonkin.Starfire, target - } else if solarIsActive { - if moonkin.MoonkinT84PCAura.IsActive() { - if moonkin.MoonkinT84PCAura.RemainingDuration(sim) < solarUptime { - return moonkin.Starfire, target - } - } - if canExtendMf && moonkin.ExtendingMoonfireStacks == 0 { - if extendTarget := moonkin.tryExtendMoonfire(sim); extendTarget != nil { - return moonkin.Moonfire, extendTarget - } - } - if (rotation.UseSmartCooldowns && solarUptime > 10*time.Second) || sim.GetRemainingDuration() < 15*time.Second { - moonkin.castMajorCooldown(moonkin.potionWildMagicMCD, sim, target) - moonkin.useTrinkets(stats.SpellCrit, sim, target) - } - if rotation.WrathUsage == proto.BalanceDruid_Rotation_RegularWrath { - return moonkin.Wrath, target - } - } - } - if rotation.MfUsage == proto.BalanceDruid_Rotation_BeforeLunar && lunarICD < 2*time.Second && shouldRefreshMf { - return moonkin.Moonfire, target - } - shouldRefreshIs := moonkin.InsectSwarm.CurDot().RemainingDuration(sim) <= 0 - if rotation.IsUsage == proto.BalanceDruid_Rotation_BeforeSolar && solarICD < 2*time.Second && shouldRefreshIs { - return moonkin.InsectSwarm, target - } - } - - fishingForLunar := lunarICD <= solarICD - if rotation.EclipsePrio == proto.BalanceDruid_Rotation_Solar { - fishingForLunar = lunarICD < solarICD - } - - if canExtendMf && moonkin.ExtendingMoonfireStacks == 0 { - if extendTarget := moonkin.tryExtendMoonfire(sim); extendTarget != nil { - return moonkin.Moonfire, extendTarget - } - } - - // Non-Eclipse - eclipseShuffle := rotation.EclipseShuffling && lunarICD == 0 && solarICD == 0 - if eclipseShuffle && moonkin.LastCast == moonkin.Wrath && rotation.UseStarfire { - return moonkin.Starfire, target - } - if (fishingForLunar || eclipseShuffle) && rotation.WrathUsage != proto.BalanceDruid_Rotation_NoWrath { - return moonkin.Wrath, target - } else { - return moonkin.Starfire, target - } -} - -func (moonkin *BalanceDruid) castMajorCooldown(mcd *core.MajorCooldown, sim *core.Simulation, target *core.Unit) { - if mcd != nil && mcd.Spell.IsReady(sim) { - isOffensivePotion := mcd.Spell.SameAction(core.ActionID{ItemID: 40211}) || mcd.Spell.SameAction(core.ActionID{ItemID: 40212}) - willUseOffensivePotion := isOffensivePotion && !moonkin.potionUsed - - // Use Potion if we can - if isOffensivePotion && moonkin.potionUsed { - return - } - mcd.Spell.Cast(sim, target) - - if willUseOffensivePotion { - moonkin.potionUsed = true - } - moonkin.UpdateMajorCooldowns() - } -} - -func (moonkin *BalanceDruid) useTrinkets(stat stats.Stat, sim *core.Simulation, target *core.Unit) { - if moonkin.onUseTrinket1.Stat == stat { - moonkin.castMajorCooldown(moonkin.onUseTrinket1.Cooldown, sim, target) - } - if moonkin.onUseTrinket2.Stat == stat { - moonkin.castMajorCooldown(moonkin.onUseTrinket2.Cooldown, sim, target) - } -} - -func (moonkin *BalanceDruid) tryExtendMoonfire(sim *core.Simulation) *core.Unit { - if len(sim.Encounter.Targets) < 2 { - return nil - } - minTarget := moonkin.CurrentTarget - minTimer := moonkin.Moonfire.CurDot().RemainingDuration(sim) - for range sim.Encounter.Targets { - if moonkin.Moonfire.CurDot().RemainingDuration(sim) < minTimer { - minTarget = moonkin.CurrentTarget - minTimer = moonkin.Moonfire.CurDot().RemainingDuration(sim) - } - moonkin.CurrentTarget = sim.Environment.NextTargetUnit(moonkin.CurrentTarget) - } - return minTarget -} - -func (moonkin *BalanceDruid) shouldSnapshotMf(sim *core.Simulation, aura *core.Aura) bool { - if aura.IsActive() && aura.RemainingDuration(sim) < moonkin.Moonfire.CurDot().RemainingDuration(sim) { - if moonkin.Moonfire.CurDot().SnapshotBaseDamage < (200 + 0.13*moonkin.Moonfire.CurDot().Spell.SpellPower()) { - return true - } - } - return false -} diff --git a/sim/druid/berserk.go b/sim/druid/berserk.go index 9c189f8c2c..cd58cb4966 100644 --- a/sim/druid/berserk.go +++ b/sim/druid/berserk.go @@ -62,10 +62,8 @@ func (druid *Druid) registerBerserkCD() { }, }) - if druid.IsUsingAPL { - druid.AddMajorCooldown(core.MajorCooldown{ - Spell: druid.Berserk.Spell, - Type: core.CooldownTypeDPS, - }) - } + druid.AddMajorCooldown(core.MajorCooldown{ + Spell: druid.Berserk.Spell, + Type: core.CooldownTypeDPS, + }) } diff --git a/sim/druid/druid.go b/sim/druid/druid.go index c27551ed99..5bd1c29bf1 100644 --- a/sim/druid/druid.go +++ b/sim/druid/druid.go @@ -23,7 +23,6 @@ type Druid struct { StartingForm DruidForm RebirthUsed bool - MaulRageThreshold float64 RebirthTiming float64 BleedsActive int AssumeBleedActive bool @@ -226,7 +225,7 @@ func (druid *Druid) RegisterFeralCatSpells() { druid.registerFerociousBiteSpell() druid.registerMangleBearSpell() druid.registerMangleCatSpell() - druid.registerMaulSpell(0) + druid.registerMaulSpell() druid.registerLacerateSpell() druid.registerRakeSpell() druid.registerRipSpell() @@ -237,7 +236,7 @@ func (druid *Druid) RegisterFeralCatSpells() { druid.registerTigersFurySpell() } -func (druid *Druid) RegisterFeralTankSpells(maulRageThreshold float64) { +func (druid *Druid) RegisterFeralTankSpells() { druid.registerBarkskinCD() druid.registerBerserkCD() druid.registerBearFormSpell() @@ -245,7 +244,7 @@ func (druid *Druid) RegisterFeralTankSpells(maulRageThreshold float64) { druid.registerEnrageSpell() druid.registerFrenziedRegenerationCD() druid.registerMangleBearSpell() - druid.registerMaulSpell(maulRageThreshold) + druid.registerMaulSpell() druid.registerLacerateSpell() druid.registerRakeSpell() druid.registerRipSpell() diff --git a/sim/druid/feral/feral.go b/sim/druid/feral/feral.go index 13e085a5e8..1608d06272 100644 --- a/sim/druid/feral/feral.go +++ b/sim/druid/feral/feral.go @@ -45,9 +45,9 @@ func NewFeralDruid(character *core.Character, options *proto.Player) *FeralDruid cat.PrePopBerserk = feralOptions.Rotation.PrePopBerserk cat.setupRotation(feralOptions.Rotation) - cat.EnableEnergyBar(100.0, cat.OnEnergyGain) + cat.EnableEnergyBar(100.0) - cat.EnableRageBar(core.RageBarOptions{RageMultiplier: 1, MHSwingSpeed: 2.5}, func(sim *core.Simulation) {}) + cat.EnableRageBar(core.RageBarOptions{RageMultiplier: 1, MHSwingSpeed: 2.5}) cat.EnableAutoAttacks(cat, core.AutoAttackOptions{ // Base paw weapon. @@ -96,22 +96,6 @@ func (cat *FeralDruid) MissChance() float64 { func (cat *FeralDruid) Initialize() { cat.Druid.Initialize() cat.RegisterFeralCatSpells() - - if cat.IsUsingAPL { - return - } - - if cat.prepopOoc && cat.Talents.OmenOfClarity { - cat.RegisterPrepullAction(-time.Second, func(sim *core.Simulation) { - cat.ProcOoc(sim) - }) - } - - if cat.PrePopBerserk && cat.Talents.Berserk { - cat.RegisterPrepullAction(-time.Second, func(sim *core.Simulation) { - cat.Berserk.Cast(sim, nil) - }) - } } func (cat *FeralDruid) Reset(sim *core.Simulation) { diff --git a/sim/druid/feral/rotation.go b/sim/druid/feral/rotation.go index 5fa1b6a1df..4694a15739 100644 --- a/sim/druid/feral/rotation.go +++ b/sim/druid/feral/rotation.go @@ -9,30 +9,11 @@ import ( "github.com/wowsims/wotlk/sim/druid" ) -func (cat *FeralDruid) OnEnergyGain(sim *core.Simulation) { - if cat.IsUsingAPL && !cat.usingHardcodedAPL { - return - } - - if sim.CurrentTime < 0 { - return - } - - cat.TryUseCooldowns(sim) - if cat.InForm(druid.Cat) && !cat.readyToShift { - cat.doTigersFury(sim) - } -} - func (cat *FeralDruid) OnGCDReady(sim *core.Simulation) { - if cat.IsUsingAPL && !cat.usingHardcodedAPL { + if !cat.usingHardcodedAPL { return } - if !cat.IsUsingAPL { - cat.TryUseCooldowns(sim) - } - if !cat.GCD.IsReady(sim) { return } @@ -56,33 +37,12 @@ func (cat *FeralDruid) OnGCDReady(sim *core.Simulation) { // Replace gcd event with our own if we casted a spell if !cat.GCD.IsReady(sim) { nextGcd := cat.NextGCDAt() - cat.DoNothing() cat.CancelGCDTimer(sim) cat.NextRotationAction(sim, nextGcd) } } -func (cat *FeralDruid) OnAutoAttack(sim *core.Simulation, _ *core.Spell) { - if cat.IsUsingAPL { - return - } - - if cat.InForm(druid.Humanoid) { - panic("auto attack out of form?") - } - - // If the swing resulted in an Omen proc, then schedule the - // next player decision based on latency. - - if cat.Talents.OmenOfClarity && cat.ClearcastingAura.RemainingDuration(sim) == cat.ClearcastingAura.Duration { - // Kick gcd loop, also need to account for any gcd 'left' - // otherwise it breaks gcd logic - kickTime := max(cat.NextGCDAt(), sim.CurrentTime+cat.latency) - cat.NextRotationAction(sim, kickTime) - } -} - func (cat *FeralDruid) NextRotationAction(sim *core.Simulation, kickAt time.Duration) { if cat.rotationAction != nil { cat.rotationAction.Cancel(sim) @@ -97,62 +57,8 @@ func (cat *FeralDruid) NextRotationAction(sim *core.Simulation, kickAt time.Dura sim.AddPendingAction(cat.rotationAction) } -// Ported from https://github.com/NerdEgghead/WOTLK_cat_sim - func (cat *FeralDruid) checkReplaceMaul(sim *core.Simulation, mhSwingSpell *core.Spell) *core.Spell { - if cat.IsUsingAPL { - return mhSwingSpell - } - - // If we have enough time and Energy leeway to stay in - // Dire Bear Form once the GCD expires, then only Maul if we - // will be left with enough Rage to cast Mangle or Lacerate - // on that global. - - ripDot := cat.Rip.CurDot() - - furorCap := min(20.0*float64(cat.Talents.Furor), 85.0) - ripRefreshPending := ripDot.IsActive() && (ripDot.RemainingDuration(sim) < sim.GetRemainingDuration()-time.Second*10) - gcdTimeToRdy := cat.GCD.TimeToReady(sim) - energyLeeway := furorCap - 15.0 - float64((gcdTimeToRdy+cat.latency)/core.EnergyTickDuration) - shiftNext := cat.CurrentEnergy() > energyLeeway - - if ripRefreshPending { - shiftNext = shiftNext || (ripDot.RemainingDuration(sim) < (gcdTimeToRdy + time.Second*3)) - } - - lacerateNext := false - emergencyLacerateNext := false - mangleNext := false - - lacerateDot := cat.Lacerate.CurDot() - if cat.Rotation.BearweaveType == proto.FeralDruid_Rotation_Lacerate { - lacerateLeeway := cat.Rotation.LacerateTime + gcdTimeToRdy - lacerateNext = !lacerateDot.IsActive() || (lacerateDot.GetStacks() < 5) || (lacerateDot.RemainingDuration(sim) <= lacerateLeeway) - emergencyLeeway := gcdTimeToRdy + (3 * time.Second) + (2 * cat.latency) - emergencyLacerateNext = lacerateDot.IsActive() && (lacerateDot.RemainingDuration(sim) <= emergencyLeeway) - mangleNext = cat.MangleBear != nil && !lacerateNext && (!cat.bleedAura.IsActive() || (cat.bleedAura.RemainingDuration(sim) < gcdTimeToRdy+time.Second*3) || (sim.CurrentTime-cat.lastShift < time.Duration(1500*time.Millisecond))) - } else { - mangleNext = cat.MangleBear != nil && cat.MangleBear.TimeToReady(sim) < gcdTimeToRdy - lacerateNext = lacerateDot.IsActive() && (lacerateDot.GetStacks() < 5 || lacerateDot.RemainingDuration(sim) < gcdTimeToRdy+(time.Second*4)) - } - - maulRageThresh := 10.0 - if emergencyLacerateNext { - maulRageThresh += cat.Lacerate.DefaultCast.Cost - } else if shiftNext { - maulRageThresh = 10.0 - } else if mangleNext { - maulRageThresh += cat.MangleBear.DefaultCast.Cost - } else if lacerateNext { - maulRageThresh += cat.Lacerate.DefaultCast.Cost - } - - if cat.CurrentRage() >= maulRageThresh { - return cat.Maul.Spell - } else { - return mhSwingSpell - } + return mhSwingSpell } func (cat *FeralDruid) shiftBearCat(sim *core.Simulation, powershift bool) bool { diff --git a/sim/druid/hurricane.go b/sim/druid/hurricane.go index 7ccedd3433..b13106b6d1 100644 --- a/sim/druid/hurricane.go +++ b/sim/druid/hurricane.go @@ -37,8 +37,7 @@ func (druid *Druid) registerHurricaneSpell() { }, Cast: core.CastConfig{ DefaultCast: core.Cast{ - GCD: core.GCDDefault, - ChannelTime: time.Second * 10, + GCD: core.GCDDefault, }, }, Dot: core.DotConfig{ diff --git a/sim/druid/maul.go b/sim/druid/maul.go index 600d2399e4..cf82c24d2b 100644 --- a/sim/druid/maul.go +++ b/sim/druid/maul.go @@ -5,7 +5,7 @@ import ( "github.com/wowsims/wotlk/sim/core/proto" ) -func (druid *Druid) registerMaulSpell(rageThreshold float64) { +func (druid *Druid) registerMaulSpell() { flatBaseDamage := 578.0 if druid.Ranged().ID == 23198 { // Idol of Brutality flatBaseDamage += 50 @@ -87,11 +87,6 @@ func (druid *Druid) registerMaulSpell(rageThreshold float64) { druid.MaulQueueAura.Activate(sim) }, }) - - druid.MaulRageThreshold = max(druid.Maul.DefaultCast.Cost, rageThreshold) - if druid.IsUsingAPL { - druid.MaulRageThreshold = 0 - } } func (druid *Druid) QueueMaul(sim *core.Simulation) { @@ -106,11 +101,6 @@ func (druid *Druid) MaulReplaceMH(sim *core.Simulation, mhSwingSpell *core.Spell return mhSwingSpell } - if druid.CurrentRage() < druid.MaulRageThreshold { - druid.MaulQueueAura.Deactivate(sim) - return mhSwingSpell - } - if !druid.Maul.Spell.CanCast(sim, druid.CurrentTarget) { druid.MaulQueueAura.Deactivate(sim) return mhSwingSpell @@ -118,7 +108,3 @@ func (druid *Druid) MaulReplaceMH(sim *core.Simulation, mhSwingSpell *core.Spell return druid.Maul.Spell } - -func (druid *Druid) ShouldQueueMaul(_ *core.Simulation) bool { - return druid.CurrentRage() >= druid.MaulRageThreshold -} diff --git a/sim/druid/talents.go b/sim/druid/talents.go index b3d944c3c7..3a63ceadc1 100644 --- a/sim/druid/talents.go +++ b/sim/druid/talents.go @@ -399,7 +399,7 @@ func (druid *Druid) applyOmenOfClarity() { // https://github.com/JamminL/wotlk-classic-bugs/issues/66#issuecomment-1182017571 if druid.HurricaneTickSpell.IsEqual(spell) { - curCastTickSpeed := spell.CurCast.ChannelTime.Seconds() / 10 + curCastTickSpeed := spell.CurDot().TickPeriod().Seconds() / 10 hurricaneCoeff := 1.0 - (7.0 / 9.0) spellCoeff := hurricaneCoeff * curCastTickSpeed chanceToProc := ((1.5 / 60) * 3.5) * spellCoeff diff --git a/sim/druid/tank/rotation.go b/sim/druid/tank/rotation.go deleted file mode 100644 index f1c75829b8..0000000000 --- a/sim/druid/tank/rotation.go +++ /dev/null @@ -1,88 +0,0 @@ -package tank - -import ( - "time" - - "github.com/wowsims/wotlk/sim/core" -) - -func (bear *FeralTankDruid) OnGCDReady(sim *core.Simulation) { - bear.doRotation(sim) -} - -func (bear *FeralTankDruid) OnAutoAttack(sim *core.Simulation, _ *core.Spell) { - bear.tryQueueMaul(sim) -} - -func (bear *FeralTankDruid) doRotation(sim *core.Simulation) { - if bear.GCD.IsReady(sim) { - if bear.shouldSaveLacerateStacks(sim) && bear.Lacerate.CanCast(sim, bear.CurrentTarget) { - bear.Lacerate.Cast(sim, bear.CurrentTarget) - } else if bear.shouldDemoRoar(sim) { - bear.DemoralizingRoar.Cast(sim, bear.CurrentTarget) - } else if bear.Berserk.IsReady(sim) { - bear.Berserk.Cast(sim, nil) - } else if bear.MangleBear.CanCast(sim, bear.CurrentTarget) { - bear.MangleBear.Cast(sim, bear.CurrentTarget) - } else if bear.shouldFaerieFire(sim) { - bear.FaerieFire.Cast(sim, bear.CurrentTarget) - } else if bear.shouldLacerate(sim) { - bear.Lacerate.Cast(sim, bear.CurrentTarget) - } else if bear.shouldSwipe(sim) { - bear.SwipeBear.Cast(sim, bear.CurrentTarget) - } - } - - if bear.GCD.IsReady(sim) { - nextAction := bear.FaerieFire.ReadyAt() - - if bear.MangleBear == nil { - bear.WaitUntil(sim, nextAction) - } else if !bear.MangleBear.IsReady(sim) { - nextAction = max(nextAction, sim.CurrentTime) - nextMangle := bear.MangleBear.ReadyAt() - - if nextMangle < nextAction+time.Second { - nextAction = nextMangle - } - - if nextAction > sim.CurrentTime { - bear.WaitUntil(sim, nextAction) - } - } - } - - bear.tryQueueMaul(sim) - bear.DoNothing() // means we intionally have no other action if all else fails. -} - -func (bear *FeralTankDruid) shouldSaveLacerateStacks(sim *core.Simulation) bool { - lacerateDot := bear.Lacerate.CurDot() - return lacerateDot.GetStacks() == 5 && - lacerateDot.RemainingDuration(sim) <= time.Millisecond*1500 -} - -func (bear *FeralTankDruid) shouldSwipe(sim *core.Simulation) bool { - return bear.SwipeBear.CanCast(sim, bear.CurrentTarget) && - ((bear.MangleBear == nil) || (bear.MangleBear.ReadyAt() >= sim.CurrentTime+core.GCDDefault)) && - bear.CurrentRage()-bear.SwipeBear.DefaultCast.Cost >= bear.MaulRageThreshold -} - -func (bear *FeralTankDruid) tryQueueMaul(sim *core.Simulation) { - if bear.ShouldQueueMaul(sim) { - bear.QueueMaul(sim) - } -} - -func (bear *FeralTankDruid) shouldDemoRoar(sim *core.Simulation) bool { - return bear.ShouldDemoralizingRoar(sim, false, bear.Rotation.MaintainDemoralizingRoar) -} - -func (bear *FeralTankDruid) shouldFaerieFire(sim *core.Simulation) bool { - return bear.FaerieFire.IsReady(sim) && ((bear.MangleBear == nil) || (bear.MangleBear.ReadyAt() >= sim.CurrentTime+time.Second)) -} - -func (bear *FeralTankDruid) shouldLacerate(sim *core.Simulation) bool { - lacerateDot := bear.Lacerate.CurDot() - return bear.Lacerate.CanCast(sim, bear.CurrentTarget) && ((bear.MangleBear == nil) || (bear.MangleBear.ReadyAt() >= sim.CurrentTime+core.GCDDefault)) && ((lacerateDot.GetStacks() < 5) || (lacerateDot.RemainingDuration(sim) <= time.Duration(bear.Rotation.LacerateTime*float64(time.Second)))) -} diff --git a/sim/druid/tank/tank.go b/sim/druid/tank/tank.go index cd8e1f895a..21fab7ceeb 100644 --- a/sim/druid/tank/tank.go +++ b/sim/druid/tank/tank.go @@ -28,9 +28,8 @@ func NewFeralTankDruid(character *core.Character, options *proto.Player) *FeralT selfBuffs := druid.SelfBuffs{} bear := &FeralTankDruid{ - Druid: druid.New(character, druid.Bear, selfBuffs, options.TalentsString), - Rotation: tankOptions.Rotation, - Options: tankOptions.Options, + Druid: druid.New(character, druid.Bear, selfBuffs, options.TalentsString), + Options: tankOptions.Options, } bear.SelfBuffs.InnervateTarget = &proto.UnitReference{} @@ -64,8 +63,7 @@ func NewFeralTankDruid(character *core.Character, options *proto.Player) *FeralT type FeralTankDruid struct { *druid.Druid - Rotation *proto.FeralTankDruid_Rotation - Options *proto.FeralTankDruid_Options + Options *proto.FeralTankDruid_Options } func (bear *FeralTankDruid) GetDruid() *druid.Druid { @@ -74,7 +72,7 @@ func (bear *FeralTankDruid) GetDruid() *druid.Druid { func (bear *FeralTankDruid) Initialize() { bear.Druid.Initialize() - bear.RegisterFeralTankSpells(float64(bear.Rotation.MaulRageThreshold)) + bear.RegisterFeralTankSpells() } func (bear *FeralTankDruid) Reset(sim *core.Simulation) {