diff --git a/proto/priest.proto b/proto/priest.proto index a611e0f4c..7bee8ad89 100644 --- a/proto/priest.proto +++ b/proto/priest.proto @@ -60,45 +60,6 @@ message PriestTalents { bool shadowform = 47; } -enum PriestRune { - PriestRuneNone = 0; - - RuneHelmDivineAegis = 431622; - RuneHelmEyeOfTheVoid = 402789; - RuneHelmPainAndSuffering = 413251; - - RuneCloakBindingHeal = 401937; - RuneCloakSoulWarding = 402000; - RuneCloakVampiricTouch = 402668; - - RuneChestSerendipity = 413248; - RuneChestStrengthOfSoul = 415739; - RuneChestTwistedFaith = 425198; - - RuneBracersDespair = 431670; - RuneBracersSurgeOfLight = 431664; - RuneBracersVoidZone = 431681; - - RuneHandsCircleOfHealing = 401946; - RuneHandsMindSear = 413259; - RuneHandsPenance = 402174; - RuneHandsShadowWordDeath = 401955; - - RuneWaistEmpoweredRenew = 425266; - RuneWaistMindSpike = 431655; - RuneWaistRenewedHope = 425280; - - RuneLegsHomunculi = 402799; - RuneLegsPowerWordBarrier = 425207; - RuneLegsPrayerOfMending = 401859; - RuneLegsSharedPain = 401969; - - RuneFeetDispersion = 425294; - RuneFeetPainSuppression = 402004; - RuneFeetSpiritOfTheRedeemer = 425284; - RuneFeetVoidPlague = 425204; -} - message ShadowPriest { message Rotation { } @@ -112,9 +73,8 @@ message ShadowPriest { bool use_shadowfiend = 1; Armor armor = 2; bool use_mind_blast = 4; - bool use_shadow_word_death = 5; - UnitReference power_infusion_target = 6; - double latency = 7 [deprecated = true]; // Latency between actions + UnitReference power_infusion_target = 5; + double latency = 6 [deprecated = true]; // Latency between actions } Options options = 3; } @@ -124,12 +84,8 @@ message HealingPriest { } message Options { - bool use_inner_fire = 3; - bool use_shadowfiend = 1; - UnitReference power_infusion_target = 2; - - // Number of times for rapture to proc each minute, ie when a PWS is fully absorbed. - double raptures_per_minute = 4; + bool use_inner_fire = 2; + UnitReference power_infusion_target = 1; } Options options = 3; } diff --git a/sim/hunter/TestBM.results b/sim/hunter/TestBM.results deleted file mode 100644 index 36900a9d3..000000000 --- a/sim/hunter/TestBM.results +++ /dev/null @@ -1,280 +0,0 @@ -character_stats_results: { - key: "TestBM-Phase2-Lvl40-CharacterStats-Default" - value: { - final_stats: 211.255 - final_stats: 332.695 - final_stats: 359.32325 - final_stats: 163.185 - final_stats: 191.015 - final_stats: 162 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 34.75 - final_stats: 0 - final_stats: 28.53276 - final_stats: 0 - final_stats: 0 - final_stats: 1127.95 - final_stats: 0 - final_stats: 30.08066 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 3272.775 - final_stats: 0 - final_stats: 0 - final_stats: 2503.39 - final_stats: 1281.39 - final_stats: 0 - final_stats: 5 - final_stats: 0 - final_stats: 0 - final_stats: 5 - final_stats: 0 - final_stats: 4380.2325 - final_stats: 13 - final_stats: 56 - final_stats: 30 - final_stats: 30 - final_stats: 30 - final_stats: 263 - final_stats: 0 - final_stats: 35 - final_stats: 0 - } -} -stat_weights_results: { - key: "TestBM-Phase2-Lvl40-StatWeights-Default" - value: { - weights: 0 - weights: 0.50664 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0.13996 - weights: 4.3644 - weights: 3.36833 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0.07897 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Average-Default" - value: { - dps: 653.95169 - tps: 298.34077 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_melee-FullBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 938.88875 - tps: 912.66402 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_melee-FullBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 667.23482 - tps: 313.89596 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_melee-FullBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 701.09983 - tps: 319.47299 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_melee-NoBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 389.83157 - tps: 609.23817 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_melee-NoBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 199.49201 - tps: 112.68143 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_melee-NoBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 214.83784 - tps: 106.45497 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_ranged_bm-FullBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 787.77778 - tps: 681.30603 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_ranged_bm-FullBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 698.66246 - tps: 339.611 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_ranged_bm-FullBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 734.58089 - tps: 336.78729 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_ranged_bm-NoBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 295.57734 - tps: 561.83868 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_ranged_bm-NoBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 251.93539 - tps: 167.86977 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-NightElf-placeholder-Basic-p2_ranged_bm-NoBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 273.04179 - tps: 168.58356 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_melee-FullBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 920.3286 - tps: 894.1469 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_melee-FullBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 652.573 - tps: 298.23343 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_melee-FullBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 685.67111 - tps: 300.57623 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_melee-NoBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 394.08419 - tps: 603.97612 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_melee-NoBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 204.56596 - tps: 113.66426 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_melee-NoBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 222.20253 - tps: 107.48562 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_ranged_bm-FullBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 764.88278 - tps: 717.87402 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_ranged_bm-FullBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 682.45237 - tps: 326.12824 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_ranged_bm-FullBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 718.89282 - tps: 322.33991 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_ranged_bm-NoBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 296.4647 - tps: 559.91976 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_ranged_bm-NoBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 253.84926 - tps: 166.05371 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-Settings-Orc-placeholder-Basic-p2_ranged_bm-NoBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 274.46254 - tps: 167.6218 - } -} -dps_results: { - key: "TestBM-Phase2-Lvl40-SwitchInFrontOfTarget-Default" - value: { - dps: 632.37975 - tps: 278.24115 - } -} diff --git a/sim/hunter/TestMM.results b/sim/hunter/TestMM.results deleted file mode 100644 index 54e9f0763..000000000 --- a/sim/hunter/TestMM.results +++ /dev/null @@ -1,210 +0,0 @@ -character_stats_results: { - key: "TestMM-Phase4-Lvl60-CharacterStats-Default" - value: { - final_stats: 297.275 - final_stats: 507.265 - final_stats: 474.2485 - final_stats: 215.05 - final_stats: 246.675 - final_stats: 162 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 47.25 - final_stats: 3 - final_stats: 28.14833 - final_stats: 0 - final_stats: 0 - final_stats: 1602.54 - final_stats: 3 - final_stats: 34.58731 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 4665.75 - final_stats: 0 - final_stats: 0 - final_stats: 2852.53 - final_stats: 1870.53 - final_stats: 0 - final_stats: 5 - final_stats: 0 - final_stats: 0 - final_stats: 5 - final_stats: 0 - final_stats: 6709.2541 - final_stats: 27 - final_stats: 86 - final_stats: 60 - final_stats: 60 - final_stats: 60 - final_stats: 384 - final_stats: 0 - final_stats: 35 - final_stats: 0 - } -} -stat_weights_results: { - key: "TestMM-Phase4-Lvl60-StatWeights-Default" - value: { - weights: 0 - weights: 0.15354 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0.12138 - weights: 7.19003 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-AllItems-DevilsaurEye-19991" - value: { - dps: 343.41085 - tps: 355.72397 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-AllItems-DevilsaurTooth-19992" - value: { - dps: 338.0538 - tps: 350.37503 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Average-Default" - value: { - dps: 337.33348 - tps: 349.70703 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_ranged-FullBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 419.37663 - tps: 579.42693 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_ranged-FullBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 274.78179 - tps: 282.80397 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_ranged-FullBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 266.84113 - tps: 276.55328 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_ranged-NoBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 174.1017 - tps: 414.45707 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_ranged-NoBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 112.97901 - tps: 124.99678 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_ranged-NoBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 111.38138 - tps: 115.74126 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_ranged-FullBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 449.68521 - tps: 610.1654 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_ranged-FullBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 296.74888 - tps: 304.78254 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_ranged-FullBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 301.1019 - tps: 310.94522 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_ranged-NoBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 173.0927 - tps: 413.95607 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_ranged-NoBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 113.4107 - tps: 125.45386 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_ranged-NoBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 116.07029 - tps: 120.43017 - } -} -dps_results: { - key: "TestMM-Phase4-Lvl60-SwitchInFrontOfTarget-Default" - value: { - dps: 224.48153 - tps: 236.67331 - } -} diff --git a/sim/hunter/TestSV.results b/sim/hunter/TestSV.results deleted file mode 100644 index a77972337..000000000 --- a/sim/hunter/TestSV.results +++ /dev/null @@ -1,210 +0,0 @@ -character_stats_results: { - key: "TestSV-Phase4-Lvl60-CharacterStats-Default" - value: { - final_stats: 297.275 - final_stats: 583.35475 - final_stats: 474.2485 - final_stats: 215.05 - final_stats: 246.675 - final_stats: 162 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 47.25 - final_stats: 3 - final_stats: 28.14833 - final_stats: 0 - final_stats: 0 - final_stats: 1678.62975 - final_stats: 3 - final_stats: 39.0254 - final_stats: 0 - final_stats: 0 - final_stats: 0 - final_stats: 4665.75 - final_stats: 0 - final_stats: 0 - final_stats: 3004.7095 - final_stats: 1922.7095 - final_stats: 0 - final_stats: 5 - final_stats: 0 - final_stats: 0 - final_stats: 5 - final_stats: 0 - final_stats: 6582.6644 - final_stats: 27 - final_stats: 86 - final_stats: 60 - final_stats: 60 - final_stats: 60 - final_stats: 384 - final_stats: 0 - final_stats: 35 - final_stats: 0 - } -} -stat_weights_results: { - key: "TestSV-Phase4-Lvl60-StatWeights-Default" - value: { - weights: 0 - weights: 0.23711 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0.13693 - weights: 7.55342 - weights: 1.10189 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - weights: 0 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-AllItems-DevilsaurEye-19991" - value: { - dps: 466.59017 - tps: 404.77075 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-AllItems-DevilsaurTooth-19992" - value: { - dps: 462.52818 - tps: 399.46188 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Average-Default" - value: { - dps: 460.30515 - tps: 398.87454 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_weave-FullBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 1324.90663 - tps: 1909.48506 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_weave-FullBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 459.93206 - tps: 397.14761 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_weave-FullBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 460.26913 - tps: 394.30809 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_weave-NoBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 758.08202 - tps: 1425.79955 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_weave-NoBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 178.18299 - tps: 169.04959 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Dwarf-placeholder-Weave-p4_weave-NoBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 180.93972 - tps: 162.40202 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_weave-FullBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 1325.62601 - tps: 1934.85365 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_weave-FullBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 455.40794 - tps: 396.73842 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_weave-FullBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 456.19204 - tps: 391.57823 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_weave-NoBuffs-P4-Consumes-LongMultiTarget" - value: { - dps: 754.54603 - tps: 1415.54554 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_weave-NoBuffs-P4-Consumes-LongSingleTarget" - value: { - dps: 176.9543 - tps: 167.04892 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-Settings-Orc-placeholder-Weave-p4_weave-NoBuffs-P4-Consumes-ShortSingleTarget" - value: { - dps: 183.63139 - tps: 160.99185 - } -} -dps_results: { - key: "TestSV-Phase4-Lvl60-SwitchInFrontOfTarget-Default" - value: { - dps: 323.67628 - tps: 281.33173 - } -} diff --git a/sim/priest/devouring_plague.go b/sim/priest/devouring_plague.go index 4f3c5e9f4..dfe3a6373 100644 --- a/sim/priest/devouring_plague.go +++ b/sim/priest/devouring_plague.go @@ -5,7 +5,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const DevouringPlagueRanks = 6 @@ -16,6 +15,7 @@ var DevouringPlagueManaCost = [DevouringPlagueRanks + 1]float64{0, 215, 350, 495 var DevouringPlagueLevel = [DevouringPlagueRanks + 1]int{0, 20, 28, 36, 44, 52, 60} func (priest *Priest) registerDevouringPlagueSpell() { + //TO DO: Implement race requirement priest.DevouringPlague = make([]*core.Spell, DevouringPlagueRanks+1) cdTimer := priest.NewTimer() @@ -29,7 +29,6 @@ func (priest *Priest) registerDevouringPlagueSpell() { } func (priest *Priest) getDevouringPlagueConfig(rank int, cdTimer *core.Timer) core.SpellConfig { - hasDespairRune := priest.HasRune(proto.PriestRune_RuneBracersDespair) var ticks int32 = 8 @@ -80,11 +79,7 @@ func (priest *Priest) getDevouringPlagueConfig(rank int, cdTimer *core.Timer) co dot.Snapshot(target, baseDotDamage, isRollover) }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - if hasDespairRune { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - } else { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - } + dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) }, }, diff --git a/sim/priest/dispersion.go b/sim/priest/dispersion.go deleted file mode 100644 index 53783d086..000000000 --- a/sim/priest/dispersion.go +++ /dev/null @@ -1,63 +0,0 @@ -package priest - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (priest *Priest) registerDispersionSpell() { - if !priest.HasRune(proto.PriestRune_RuneFeetDispersion) { - return - } - - actionId := core.ActionID{SpellID: int32(proto.PriestRune_RuneFeetDispersion)} - - manaMetric := priest.NewManaMetrics(actionId) - - priest.DispersionAura = priest.GetOrRegisterAura(core.Aura{ - Label: "Dispersion", - ActionID: actionId, - Duration: time.Second * 6, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - Period: time.Second, - NumTicks: 6, - OnAction: func(sim *core.Simulation) { - manaGain := priest.MaxMana() * 0.06 - priest.AddMana(sim, manaGain, manaMetric) - }, - }) - }, - }) - - priest.Dispersion = priest.RegisterSpell(core.SpellConfig{ - ActionID: actionId, - Flags: SpellFlagPriest, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: priest.NewTimer(), - Duration: time.Second * 120, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { - priest.DispersionAura.Activate(sim) - priest.WaitUntil(sim, priest.DispersionAura.ExpiresAt()) - }, - }) - - priest.AddMajorCooldown(core.MajorCooldown{ - Spell: priest.Dispersion, - Priority: 1, - Type: core.CooldownTypeMana, - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - return character.CurrentManaPercent() <= 0.01 - }, - }) -} diff --git a/sim/priest/eye_of_the_void.go b/sim/priest/eye_of_the_void.go deleted file mode 100644 index 3830b3427..000000000 --- a/sim/priest/eye_of_the_void.go +++ /dev/null @@ -1,214 +0,0 @@ -package priest - -import ( - "math" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (priest *Priest) registerEyeOfTheVoidCD() { - if !priest.HasRune(proto.PriestRune_RuneHelmEyeOfTheVoid) { - return - } - - actionID := core.ActionID{SpellID: int32(proto.PriestRune_RuneHelmEyeOfTheVoid)} - duration := time.Second * 30 - cooldown := time.Minute * 3 - - // For timeline only - priest.EyeOfTheVoidAura = priest.RegisterAura(core.Aura{ - ActionID: actionID, - Label: "Eye of the Void", - Duration: duration, - }) - - priest.EyeOfTheVoid = priest.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolShadow, - ProcMask: core.ProcMaskEmpty, - Flags: SpellFlagPriest | core.SpellFlagAPL, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: priest.NewTimer(), - Duration: cooldown, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - priest.EyeOfTheVoidPet.EnableWithTimeout(sim, priest.EyeOfTheVoidPet, duration) - priest.EyeOfTheVoidAura.Activate(sim) - }, - }) - - priest.AddMajorCooldown(core.MajorCooldown{ - Spell: priest.EyeOfTheVoid, - Priority: 1, - Type: core.CooldownTypeDPS, - }) -} - -type EyeOfTheVoid struct { - core.Pet - - npcID int32 - Priest *Priest - ShadowBolt *core.Spell -} - -func (priest *Priest) NewEyeOfTheVoid() *EyeOfTheVoid { - baseStats := stats.Stats{} - // Little information about this pet is available so using Warlock Imp stats - switch priest.Level { - case 25: - baseStats = stats.Stats{ - stats.Strength: 47, - stats.Agility: 25, - stats.Stamina: 49, - stats.Intellect: 94, - stats.Spirit: 95, - stats.Mana: 149, - stats.MP5: 0, - stats.MeleeCrit: 3.454 * core.CritRatingPerCritChance, - stats.SpellCrit: 0.9075 * core.CritRatingPerCritChance, - } - case 40: - baseStats = stats.Stats{ - stats.Strength: 70, - stats.Agility: 29, - stats.Stamina: 67, - stats.Intellect: 163, - stats.Spirit: 163, - stats.Mana: 318, - stats.MP5: 0, - stats.MeleeCrit: 3.454 * core.CritRatingPerCritChance, - stats.SpellCrit: 0.9075 * core.CritRatingPerCritChance, - } - case 50: - baseStats = stats.Stats{ - stats.Strength: 101, - stats.Agility: 32, - stats.Stamina: 71, - stats.Intellect: 212, - stats.Spirit: 211, - stats.Mana: 476, - stats.MP5: 0, - stats.MeleeCrit: 3.454 * core.CritRatingPerCritChance, - stats.SpellCrit: 0.9075 * core.CritRatingPerCritChance, - } - case 60: - baseStats = stats.Stats{ - stats.Strength: 101, - stats.Agility: 32, - stats.Stamina: 71, - stats.Intellect: 212, - stats.Spirit: 211, - stats.Mana: 476, - stats.MP5: 0, - stats.MeleeCrit: 3.454 * core.CritRatingPerCritChance, - stats.SpellCrit: 0.9075 * core.CritRatingPerCritChance, - } - } - - eyePet := &EyeOfTheVoid{ - npcID: 202387, - Pet: core.NewPet("Eye of the Void", &priest.Character, baseStats, priest.eyeOfTheVoidStatInheritance(), false, true), - Priest: priest, - } - - eyePet.EnableManaBarWithModifier(0.33) - - // Imp gets 1mp/5 non casting regen per spirit - eyePet.PseudoStats.SpiritRegenMultiplier = 1 - eyePet.PseudoStats.SpiritRegenRateCasting = 0 - eyePet.SpiritManaRegenPerSecond = func() float64 { - // 1mp5 per spirit - return eyePet.GetStat(stats.Spirit) / 5 - } - - // Mage spell crit scaling for imp - eyePet.AddStatDependency(stats.Intellect, stats.SpellCrit, core.CritPerIntAtLevel[proto.Class_ClassMage][int(eyePet.Level)]*core.SpellCritRatingPerCritChance) - - eyePet.ShadowBolt = eyePet.GetOrRegisterSpell(eyePet.newShadowBoltSpellConfig(priest)) - - priest.AddPet(eyePet) - - return eyePet -} - -// TODO: Verify any eye of the void stat inheritance -func (priest *Priest) eyeOfTheVoidStatInheritance() core.PetStatInheritance { - return func(ownerStats stats.Stats) stats.Stats { - ownerHitChance := ownerStats[stats.SpellHit] / core.SpellHitRatingPerHitChance - highestSchoolPower := ownerStats[stats.SpellPower] + ownerStats[stats.SpellDamage] + max(ownerStats[stats.FirePower], ownerStats[stats.ShadowPower]) - - return stats.Stats{ - stats.Stamina: ownerStats[stats.Stamina] * 0.75, - stats.Intellect: ownerStats[stats.Intellect] * 0.3, - stats.Armor: ownerStats[stats.Armor] * 0.35, - stats.AttackPower: highestSchoolPower * 0.565, - stats.MP5: ownerStats[stats.Intellect] * 0.315, - stats.SpellPower: ownerStats[stats.SpellPower] * 0.15, - stats.SpellDamage: ownerStats[stats.SpellDamage] * 0.15, - stats.FirePower: ownerStats[stats.FirePower] * 0.15, - stats.ShadowPower: ownerStats[stats.ShadowPower] * 0.15, - stats.SpellPenetration: ownerStats[stats.SpellPenetration], - stats.MeleeHit: ownerHitChance * core.MeleeHitRatingPerHitChance, - stats.SpellHit: math.Floor(ownerStats[stats.SpellHit] / 12.0 * 17.0), - } - } -} - -// TODO: -func (eyeOfTheVoid *EyeOfTheVoid) newShadowBoltSpellConfig(priest *Priest) core.SpellConfig { - baseDamage := priest.baseRuneAbilityDamage() + 25 - return core.SpellConfig{ - ActionID: core.ActionID{SpellID: 402790}, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - - ManaCost: core.ManaCostOptions{ - // BaseCost: .05, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - CastTime: time.Second * 3, - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - }, - } -} - -func (eyeOfTheVoid *EyeOfTheVoid) Initialize() { -} - -func (eyeOfTheVoid *EyeOfTheVoid) ExecuteCustomRotation(sim *core.Simulation) { - eyeOfTheVoid.ShadowBolt.Cast(sim, nil) -} - -func (eyeOfTheVoid *EyeOfTheVoid) Reset(sim *core.Simulation) { - eyeOfTheVoid.Disable(sim) -} - -func (eyeOfTheVoid *EyeOfTheVoid) OnPetDisable(sim *core.Simulation) { -} - -func (eyeOfTheVoid *EyeOfTheVoid) GetPet() *core.Pet { - return &eyeOfTheVoid.Pet -} diff --git a/sim/priest/healing/healing_priest.go b/sim/priest/healing/healing_priest.go index 68878b47e..2fdb56c24 100644 --- a/sim/priest/healing/healing_priest.go +++ b/sim/priest/healing/healing_priest.go @@ -61,5 +61,4 @@ func (hpriest *HealingPriest) Initialize() { } func (hpriest *HealingPriest) Reset(sim *core.Simulation) { - hpriest.Priest.Reset(sim) } diff --git a/sim/priest/healing/healing_priest_test.go b/sim/priest/healing/healing_priest_test.go index 057ffb50a..c26715049 100644 --- a/sim/priest/healing/healing_priest_test.go +++ b/sim/priest/healing/healing_priest_test.go @@ -83,9 +83,7 @@ var FullConsumes = &proto.Consumes{ var PlayerOptionsDisc = &proto.Player_HealingPriest{ HealingPriest: &proto.HealingPriest{ Options: &proto.HealingPriest_Options{ - UseInnerFire: true, - UseShadowfiend: true, - RapturesPerMinute: 5, + UseInnerFire: true, }, }, } @@ -93,8 +91,7 @@ var PlayerOptionsDisc = &proto.Player_HealingPriest{ var PlayerOptionsHoly = &proto.Player_HealingPriest{ HealingPriest: &proto.HealingPriest{ Options: &proto.HealingPriest_Options{ - UseInnerFire: true, - UseShadowfiend: true, + UseInnerFire: true, }, }, } diff --git a/sim/priest/holy_fire.go b/sim/priest/holy_fire.go index 65691903a..2ba98b4ad 100644 --- a/sim/priest/holy_fire.go +++ b/sim/priest/holy_fire.go @@ -5,7 +5,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const HolyFireRanks = 8 @@ -43,8 +42,6 @@ func (priest *Priest) getHolyFireConfig(rank int) core.SpellConfig { dotCoeff := 0.05 castTime := time.Millisecond * 3500 - hasDespairRune := priest.HasRune(proto.PriestRune_RuneBracersDespair) - return core.SpellConfig{ SpellCode: SpellCode_PriestHolyFire, ActionID: core.ActionID{SpellID: spellId}, @@ -86,11 +83,7 @@ func (priest *Priest) getHolyFireConfig(rank int) core.SpellConfig { }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - if hasDespairRune { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - } else { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - } + dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) }, }, diff --git a/sim/priest/homunculi.go b/sim/priest/homunculi.go deleted file mode 100644 index e86a337ed..000000000 --- a/sim/priest/homunculi.go +++ /dev/null @@ -1,224 +0,0 @@ -package priest - -import ( - "math" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (priest *Priest) registerHomunculiSpell() { - if !priest.HasRune(proto.PriestRune_RuneLegsHomunculi) { - return - } - - actionID := core.ActionID{SpellID: int32(proto.PriestRune_RuneLegsHomunculi)} - duration := time.Minute * 2 - cooldown := time.Minute * 2 - - // For timeline only - priest.HomunculiAura = priest.RegisterAura(core.Aura{ - ActionID: actionID, - Label: "Homunculi", - Duration: duration, - }) - - priest.Homunculi = priest.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolShadow, - ProcMask: core.ProcMaskEmpty, - Flags: SpellFlagPriest | core.SpellFlagAPL, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: priest.NewTimer(), - Duration: cooldown, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - core.Each(priest.HomunculiPets, func(homunculus *Homunculus) { - homunculus.EnableWithTimeout(sim, homunculus, duration) - }) - priest.HomunculiAura.Activate(sim) - }, - }) - - priest.AddMajorCooldown(core.MajorCooldown{ - Spell: priest.Homunculi, - Priority: 1, - Type: core.CooldownTypeDPS, - }) -} - -type Homunculus struct { - core.Pet - - npcID int32 - Priest *Priest - PrimarySpell *core.Spell -} - -func (priest *Priest) NewHomunculus(idx int32, npcID int32) *Homunculus { - // We can't use the legacy pet window for Homunculi so these values are determined from trying to bump damage up to match logs - baseDamageMin := 0.0 - baseDamageMax := 0.0 - baseStats := stats.Stats{ - stats.Strength: 0, - stats.Agility: 0, - stats.Stamina: 0, - stats.Intellect: 0, - stats.Spirit: 0, - stats.AttackPower: 0, - } - - homunculus := &Homunculus{ - npcID: npcID, - Pet: core.NewPet("Homunculi", &priest.Character, baseStats, priest.homunculusStatInheritance(), false, true), - Priest: priest, - } - - homunculus.AddStat(stats.AttackPower, -20) - - homunculus.EnableAutoAttacks(homunculus, core.AutoAttackOptions{ - MainHand: core.Weapon{ - // TODO: Check stats - BaseDamageMin: baseDamageMin, - BaseDamageMax: baseDamageMax, - SwingSpeed: 2, - }, - AutoSwingMelee: true, - }) - - // Homunculus aren't very bright and often sit in front of targets - homunculus.PseudoStats.InFrontOfTarget = true - - // core.ApplyPetConsumeEffects(&homunculus.Character, priest.Consumes) - - priest.AddPet(homunculus) - - return homunculus -} - -// TODO: Verify any homunculus stat inheritance -func (priest *Priest) homunculusStatInheritance() core.PetStatInheritance { - return func(ownerStats stats.Stats) stats.Stats { - // Shadowfiend seems to benefit from the owner's Spell Hit + Shadow Focus hit chance - ownerHitChance := (ownerStats[stats.SpellHit] + 2*float64(priest.Talents.ShadowFocus)) / core.SpellHitRatingPerHitChance - highestSchoolPower := ownerStats[stats.SpellPower] + ownerStats[stats.SpellDamage] + max(ownerStats[stats.HolyPower], ownerStats[stats.ShadowPower]) - - // TODO: Needs more verification - return stats.Stats{ - stats.Stamina: ownerStats[stats.Stamina] * .75, - stats.Intellect: ownerStats[stats.Intellect] * 0.3, - stats.Armor: ownerStats[stats.Armor] * 0.35, - stats.AttackPower: highestSchoolPower * 0.57, - stats.MP5: ownerStats[stats.MP5] * 0.3, - stats.SpellPower: ownerStats[stats.SpellPower] * 0.15, - stats.SpellDamage: ownerStats[stats.SpellDamage] * 0.15, - stats.ShadowPower: ownerStats[stats.ShadowPower] * 0.15, - stats.SpellPenetration: ownerStats[stats.SpellPenetration], - stats.MeleeHit: ownerHitChance * core.MeleeHitRatingPerHitChance, - stats.SpellHit: math.Floor(ownerHitChance / 12.0 * 17.0), - // Shadowfiend seems to most likely use the priest's Spell Crit to scale its melee crit - // In reality the melees are shadow damage and probably use the spell hit table but we can't configure that currently - stats.MeleeCrit: ownerStats[stats.SpellCrit], - stats.SpellCrit: ownerStats[stats.SpellCrit], - } - } -} - -/* func (homunculus *Homunculus) newHomunculusCrippleSpell() core.SpellConfig { - attackSpeedAuras := homunculus.NewEnemyAuraArray(core.HomunculiAttackSpeedAura) - - return core.SpellConfig{ - ActionID: core.ActionID{SpellID: 402808}, - SpellSchool: core.SpellSchoolShadow, - - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoLogs, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: time.Second * 6, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - attackSpeedAuras.Get(target).Activate(sim) - }, - } -} - -func (homunculus *Homunculus) newHomunculusDegradeSpell() core.SpellConfig { - armorAuras := homunculus.NewEnemyAuraArray(core.HomunculiArmorAura) - - return core.SpellConfig{ - ActionID: core.ActionID{SpellID: 402818}, - SpellSchool: core.SpellSchoolShadow, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoLogs, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: time.Second * 15, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - armorAuras.Get(target).Activate(sim) - }, - } -} - -func (homunculus *Homunculus) newHomunculusDemoralizeSpell() core.SpellConfig { - attackPowerAuras := homunculus.NewEnemyAuraArray(core.HomunculiAttackPowerAura) - - return core.SpellConfig{ - ActionID: core.ActionID{SpellID: 402811}, - SpellSchool: core.SpellSchoolShadow, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoLogs, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: time.Second * 15, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - attackPowerAuras.Get(target).Activate(sim) - }, - } -} */ - -func (homunculus *Homunculus) Initialize() { - /* switch homunculus.npcID { - case 202390: - homunculus.PrimarySpell = homunculus.GetOrRegisterSpell(homunculus.newHomunculusCrippleSpell()) - case 202392: - homunculus.PrimarySpell = homunculus.GetOrRegisterSpell(homunculus.newHomunculusDegradeSpell()) - case 202391: - homunculus.PrimarySpell = homunculus.GetOrRegisterSpell(homunculus.newHomunculusDemoralizeSpell()) - } */ -} - -func (homunculus *Homunculus) ExecuteCustomRotation(sim *core.Simulation) { - homunculus.PrimarySpell.Cast(sim, nil) -} - -func (homunculus *Homunculus) Reset(sim *core.Simulation) { - homunculus.Disable(sim) -} - -func (homunculus *Homunculus) OnPetDisable(sim *core.Simulation) { -} - -func (homunculus *Homunculus) GetPet() *core.Pet { - return &homunculus.Pet -} diff --git a/sim/priest/mind_blast.go b/sim/priest/mind_blast.go index e570c9ac2..d703f87ba 100644 --- a/sim/priest/mind_blast.go +++ b/sim/priest/mind_blast.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const MindBlastRanks = 9 @@ -37,8 +36,6 @@ func (priest *Priest) getMindBlastBaseConfig(rank int, cdTimer *core.Timer) core manaCost := MindBlastManaCost[rank] level := MindBlastLevel[rank] - hasMindSpike := priest.HasRune(proto.PriestRune_RuneWaistMindSpike) - return core.SpellConfig{ SpellCode: SpellCode_PriestMindBlast, ActionID: core.ActionID{SpellID: spellId}, @@ -70,38 +67,17 @@ func (priest *Priest) getMindBlastBaseConfig(rank int, cdTimer *core.Timer) core BonusCoefficient: spellCoeff, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - var mindSpikeAura *core.Aura - if hasMindSpike { - mindSpikeAura = priest.MindSpikeAuras.Get(target) - } - - oldBonusCrit := spell.BonusCritRating - oldMultiplier := spell.DamageMultiplier - spell.BonusCritRating += float64(mindSpikeAura.GetStacks()) * 30 * core.CritRatingPerCritChance - spell.DamageMultiplier *= priest.MindBlastModifier - result := spell.CalcDamage(sim, target, sim.Roll(baseDamageLow, baseDamageHigh), spell.OutcomeMagicHitAndCrit) - spell.BonusCritRating = oldBonusCrit - spell.DamageMultiplier = oldMultiplier - if result.Landed() { priest.AddShadowWeavingStack(sim, target) - if mindSpikeAura != nil { - mindSpikeAura.Deactivate(sim) - } } - spell.DealDamage(sim, result) }, ExpectedInitialDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, _ bool) *core.SpellResult { damage := (baseDamageLow + baseDamageHigh) / 2 - - oldMultiplier := spell.DamageMultiplier - spell.DamageMultiplier *= priest.MindBlastModifier result := spell.CalcDamage(sim, target, damage, spell.OutcomeExpectedMagicHitAndCrit) - spell.DamageMultiplier = oldMultiplier return result }, } diff --git a/sim/priest/mind_flay.go b/sim/priest/mind_flay.go index e41d8d610..f80c7545b 100644 --- a/sim/priest/mind_flay.go +++ b/sim/priest/mind_flay.go @@ -5,7 +5,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const MindFlayRanks = 6 @@ -55,8 +54,6 @@ func (priest *Priest) newMindFlaySpellConfig(rank int, tickIdx int32) core.Spell tickLength := time.Second - hasDespairRune := priest.HasRune(proto.PriestRune_RuneBracersDespair) - return core.SpellConfig{ SpellCode: SpellCode_PriestMindFlay, ActionID: core.ActionID{SpellID: spellId}.WithTag(tickIdx), @@ -90,17 +87,10 @@ func (priest *Priest) newMindFlaySpellConfig(rank int, tickIdx int32) core.Spell AffectedByCastSpeed: false, BonusCoefficient: spellCoeff, OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - oldMultiplier := dot.Spell.DamageMultiplier - dot.Spell.DamageMultiplier *= priest.MindFlayModifier dot.Snapshot(target, baseDamage, isRollover) - dot.Spell.DamageMultiplier = oldMultiplier }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - if hasDespairRune { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - } else { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - } + dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) }, }, @@ -115,9 +105,7 @@ func (priest *Priest) newMindFlaySpellConfig(rank int, tickIdx int32) core.Spell ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, _ bool) *core.SpellResult { baseDamage := baseDamage / MindFlayTicks - spell.DamageMultiplier *= priest.MindFlayModifier result := spell.CalcPeriodicDamage(sim, target, baseDamage, spell.OutcomeExpectedMagicAlwaysHit) - spell.DamageMultiplier /= priest.MindFlayModifier return result }, } diff --git a/sim/priest/mind_sear.go b/sim/priest/mind_sear.go deleted file mode 100644 index e5343d3b6..000000000 --- a/sim/priest/mind_sear.go +++ /dev/null @@ -1,116 +0,0 @@ -package priest - -import ( - "fmt" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -const MindSearTicks = 5 - -func (priest *Priest) registerMindSearSpell() { - if !priest.HasRune(proto.PriestRune_RuneHandsMindSear) { - return - } - - priest.MindSear = make([]*core.Spell, MindSearTicks) - priest.MindSearTicks = make([]*core.Spell, MindSearTicks) - - for tickIdx := int32(0); tickIdx < MindSearTicks; tickIdx++ { - priest.MindSear[tickIdx] = priest.RegisterSpell(priest.newMindSearSpellConfig(tickIdx)) - } -} - -func (priest *Priest) newMindSearSpellConfig(tickIdx int32) core.SpellConfig { - spellId := int32(proto.PriestRune_RuneHandsMindSear) - manaCost := .28 - - numTicks := tickIdx - flags := SpellFlagPriest | core.SpellFlagChanneled | core.SpellFlagNoMetrics - if tickIdx == 0 { - numTicks = 5 - flags |= core.SpellFlagAPL - } - tickLength := time.Second - - priest.MindSearTicks[tickIdx] = priest.newMindSearTickSpell(tickIdx) - - return core.SpellConfig{ - ActionID: core.ActionID{SpellID: spellId}.WithTag(tickIdx), - SpellSchool: core.SpellSchoolShadow, - ProcMask: core.ProcMaskSpellDamage, - Flags: flags, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - }, - - Dot: core.DotConfig{ - IsAOE: true, - Aura: core.Aura{ - Label: fmt.Sprintf("MindSear-%d", tickIdx), - }, - NumberOfTicks: numTicks, - TickLength: tickLength, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - priest.MindSearTicks[tickIdx].Cast(sim, aoeTarget) - priest.MindSearTicks[tickIdx].SpellMetrics[target.UnitIndex].Casts -= 1 - } - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - result := spell.CalcOutcome(sim, target, spell.OutcomeMagicHit) - priest.MindSearTicks[tickIdx].SpellMetrics[target.UnitIndex].Casts += 1 - - if result.Landed() { - spell.AOEDot().Apply(sim) - } - spell.DealOutcome(sim, result) - }, - } -} - -func (priest *Priest) newMindSearTickSpell(numTicks int32) *core.Spell { - baseDamageLow := priest.baseRuneAbilityDamage() * .7 - baseDamageHigh := priest.baseRuneAbilityDamage() * .78 - spellCoeff := 0.15 // classic penalty for mf having a slow effect - - return priest.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 413260}.WithTag(numTicks), - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - BonusHitRating: 1, // Not an independent hit once initial lands - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - damage := sim.Roll(baseDamageLow, baseDamageHigh) - - // Apply the base spell's multipliers to pick up on effects that only affect spells with DoTs - spell.DamageMultiplierAdditive += priest.MindSear[numTicks].PeriodicDamageMultiplierAdditive - 1 - result := spell.CalcAndDealDamage(sim, target, damage, spell.OutcomeMagicHitAndCrit) - spell.DamageMultiplierAdditive -= priest.MindSear[numTicks].PeriodicDamageMultiplierAdditive - 1 - - if result.Landed() { - priest.AddShadowWeavingStack(sim, target) - } - }, - }) -} diff --git a/sim/priest/mind_spike.go b/sim/priest/mind_spike.go deleted file mode 100644 index 36401121c..000000000 --- a/sim/priest/mind_spike.go +++ /dev/null @@ -1,85 +0,0 @@ -package priest - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (priest *Priest) registerMindSpikeSpell() { - if !priest.HasRune(proto.PriestRune_RuneWaistMindSpike) { - return - } - - priest.MindSpike = priest.GetOrRegisterSpell(priest.newMindSpikeSpellConfig()) -} - -func (priest *Priest) newMindSpikeSpellConfig() core.SpellConfig { - // 2024-02-22 tuning 10% buff - baseDamageLow := priest.baseRuneAbilityDamage() * 1.11 * 1.1 - baseDamageHigh := priest.baseRuneAbilityDamage() * 1.29 * 1.1 - spellCoeff := .429 - manaCost := .06 - castTime := time.Millisecond * 1500 - - priest.MindSpikeAuras = priest.NewEnemyAuraArray(func(unit *core.Unit, level int32) *core.Aura { - return priest.newMindSpikeAura(unit) - }) - - return core.SpellConfig{ - SpellCode: SpellCode_PriestMindSpike, - ActionID: core.ActionID{SpellID: int32(proto.PriestRune_RuneWaistMindSpike)}, - SpellSchool: core.SpellSchoolShadow | core.SpellSchoolFrost, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagPriest | core.SpellFlagAPL, - // TODO: Verify missile speed - MissileSpeed: 20, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - CastTime: castTime, - GCD: core.GCDDefault, - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ExpectedInitialDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, _ bool) *core.SpellResult { - damage := (baseDamageLow + baseDamageHigh) / 2 - result := spell.CalcDamage(sim, target, damage, spell.OutcomeExpectedMagicHitAndCrit) - return result - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := sim.Roll(baseDamageLow, baseDamageHigh) - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - - spell.WaitTravelTime(sim, func(sim *core.Simulation) { - spell.DealDamage(sim, result) - - if result.Landed() { - priest.AddShadowWeavingStack(sim, target) - priest.MindSpikeAuras.Get(target).Activate(sim) - priest.MindSpikeAuras.Get(target).AddStack(sim) - } - }) - }, - } -} - -func (priest *Priest) newMindSpikeAura(unit *core.Unit) *core.Aura { - return unit.RegisterAura(core.Aura{ - Label: "Mind Spike", - ActionID: core.ActionID{SpellID: int32(proto.PriestRune_RuneWaistMindSpike)}, - Duration: time.Second * 10, - MaxStacks: 3, - }) -} diff --git a/sim/priest/penance.go b/sim/priest/penance.go deleted file mode 100644 index 0a4f24493..000000000 --- a/sim/priest/penance.go +++ /dev/null @@ -1,105 +0,0 @@ -package priest - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (priest *Priest) RegisterPenanceSpell() { - if !priest.HasRune(proto.PriestRune_RuneHandsPenance) { - return - } - priest.Penance = priest.makePenanceSpell(false) - priest.PenanceHeal = priest.makePenanceSpell(true) -} - -// https://www.wowhead.com/classic/spell=402284/penance -// https://www.wowhead.com/classic/news/patch-1-15-build-52124-ptr-datamining-season-of-discovery-runes-336044 -func (priest *Priest) makePenanceSpell(isHeal bool) *core.Spell { - baseDamage := priest.baseRuneAbilityDamage() * 1.28 - baseHealing := priest.baseRuneAbilityHealing() * .85 - spellCoeff := 0.285 - manaCost := .16 - cooldown := time.Second * 12 - - var procMask core.ProcMask - flags := SpellFlagPriest | core.SpellFlagChanneled | core.SpellFlagAPL - if isHeal { - flags |= core.SpellFlagHelpful - procMask = core.ProcMaskSpellHealing - } else { - procMask = core.ProcMaskSpellDamage - } - - return priest.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 402284}, - SpellSchool: core.SpellSchoolHoly, - DefenseType: core.DefenseTypeMagic, - ProcMask: procMask, - Flags: flags, - RequiredLevel: 1, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: priest.NewTimer(), - Duration: cooldown, - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 0, - - Dot: core.Ternary(!isHeal, core.DotConfig{ - Aura: core.Aura{ - Label: "Penance", - }, - NumberOfTicks: 2, - TickLength: time.Second, - AffectedByCastSpeed: true, - BonusCoefficient: spellCoeff, - - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.Spell.CalcAndDealPeriodicDamage(sim, target, baseDamage, dot.OutcomeTick) - }, - }, core.DotConfig{}), - Hot: core.Ternary(isHeal, core.DotConfig{ - Aura: core.Aura{ - Label: "Penance", - }, - NumberOfTicks: 2, - TickLength: time.Second, - AffectedByCastSpeed: true, - BonusCoefficient: spellCoeff, - - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.Spell.CalcAndDealPeriodicHealing(sim, target, baseHealing, dot.Spell.OutcomeHealingCrit) - }, - }, core.DotConfig{}), - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if isHeal { - hot := spell.Hot(target) - hot.Apply(sim) - // Do immediate tick - hot.TickOnce(sim) - } else { - result := spell.CalcOutcome(sim, target, spell.OutcomeMagicHit) - if result.Landed() { - dot := spell.Dot(target) - dot.Apply(sim) - // Do immediate tick - dot.TickOnce(sim) - } - spell.DealOutcome(sim, result) - } - }, - }) -} diff --git a/sim/priest/prayer_of_mending.go b/sim/priest/prayer_of_mending.go deleted file mode 100644 index d8e4e5b5a..000000000 --- a/sim/priest/prayer_of_mending.go +++ /dev/null @@ -1,108 +0,0 @@ -package priest - -// func (priest *Priest) registerPrayerOfMendingSpell() { -// actionID := core.ActionID{SpellID: 48113} - -// pomAuras := make([]*core.Aura, len(priest.Env.AllUnits)) -// for _, unit := range priest.Env.AllUnits { -// if !priest.IsOpponent(unit) { -// pomAuras[unit.UnitIndex] = priest.makePrayerOfMendingAura(unit) -// } -// } - -// maxJumps := 5 - -// var curTarget *core.Unit -// var remainingJumps int -// priest.ProcPrayerOfMending = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { -// baseHealing := 1043 + 0.8057*spell.HealingPower(target) -// priest.PrayerOfMending.CalcAndDealHealing(sim, target, baseHealing, spell.OutcomeHealingCrit) - -// pomAuras[target.UnitIndex].Deactivate(sim) -// curTarget = nil - -// // Bounce to new ally. -// if remainingJumps == 0 { -// return -// } - -// // Find ally with lowest % HP and is not the current mending target. -// var newTarget *core.Unit -// for _, raidUnit := range priest.Env.Raid.AllUnits { -// if raidUnit == target { -// continue -// } - -// if newTarget == nil || (raidUnit.HasHealthBar() && newTarget.HasHealthBar() && raidUnit.CurrentHealthPercent() < newTarget.CurrentHealthPercent()) { -// newTarget = raidUnit -// } -// } - -// if newTarget != nil { -// pomAuras[newTarget.UnitIndex].Activate(sim) -// curTarget = newTarget -// remainingJumps-- -// } -// } - -// priest.PrayerOfMending = priest.RegisterSpell(core.SpellConfig{ -// ActionID: actionID, -// SpellSchool: core.SpellSchoolHoly, -// DefenseType: core.DefenseTypeMagic, -// ProcMask: core.ProcMaskSpellHealing, -// Flags: SpellFlagPriest | core.SpellFlagHelpful | core.SpellFlagAPL, - -// ManaCost: core.ManaCostOptions{ -// BaseCost: 0.15, -// Multiplier: 1, -// }, -// Cast: core.CastConfig{ -// DefaultCast: core.Cast{ -// GCD: core.GCDDefault, -// }, -// CD: core.Cooldown{ -// Timer: priest.NewTimer(), -// Duration: time.Second * 10, -// }, -// }, - -// BonusCritRating: float64(priest.Talents.HolySpecialization) * 1 * core.CritRatingPerCritChance, - -// DamageMultiplier: 1 + .02*float64(priest.Talents.SpiritualHealing), -// ThreatMultiplier: 1, - -// ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { -// if curTarget != nil { -// pomAuras[curTarget.UnitIndex].Deactivate(sim) -// } - -// pomAuras[target.UnitIndex].Activate(sim) -// curTarget = target -// remainingJumps = maxJumps -// }, -// }) -// } - -// func (priest *Priest) makePrayerOfMendingAura(target *core.Unit) *core.Aura { -// autoProc := true - -// return target.RegisterAura(core.Aura{ -// Label: "PrayerOfMending" + strconv.Itoa(int(priest.Index)), -// Duration: time.Second * 30, -// OnGain: func(aura *core.Aura, sim *core.Simulation) { -// if autoProc { -// core.StartDelayedAction(sim, core.DelayedActionOptions{ -// DoAt: sim.CurrentTime + time.Second*5, -// OnAction: func(sim *core.Simulation) { -// priest.ProcPrayerOfMending(sim, aura.Unit, priest.PrayerOfMending) -// }, -// }) -// } -// }, -// OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { -// if !autoProc && result.Damage > 0 { -// priest.ProcPrayerOfMending(sim, aura.Unit, priest.PrayerOfMending) -// } -// }, -// }) -// } diff --git a/sim/priest/priest.go b/sim/priest/priest.go index 9f7d6dba2..23e58570a 100644 --- a/sim/priest/priest.go +++ b/sim/priest/priest.go @@ -1,7 +1,6 @@ package priest import ( - "github.com/wowsims/classic/sim/common/guardians" "github.com/wowsims/classic/sim/core" "github.com/wowsims/classic/sim/core/proto" "github.com/wowsims/classic/sim/core/stats" @@ -23,7 +22,6 @@ const ( SpellCode_PriestHolyFire SpellCode_PriestMindBlast SpellCode_PriestMindFlay - SpellCode_PriestMindSpike SpellCode_PriestShadowWordPain SpellCode_PriestSmite SpellCode_PriestVampiricTouch @@ -33,63 +31,35 @@ type Priest struct { core.Character Talents *proto.PriestTalents - Latency float64 - MindFlayModifier float64 // For Twisted Faith - MindBlastModifier float64 // For Twisted Faith - MindBlastCritChanceModifier float64 + Latency float64 CircleOfHealing *core.Spell DevouringPlague []*core.Spell - Dispersion *core.Spell EmpoweredRenew *core.Spell - EyeOfTheVoid *core.Spell FlashHeal []*core.Spell GreaterHeal []*core.Spell HolyFire []*core.Spell - Homunculi *core.Spell InnerFocus *core.Spell MindBlast []*core.Spell MindFlay [][]*core.Spell // 1 entry for each tick for each rank - MindSear []*core.Spell // 1 entry for each tick - MindSearTicks []*core.Spell // 1 entry for each tick - MindSpike *core.Spell - Penance *core.Spell - PenanceHeal *core.Spell PowerWordShield []*core.Spell PrayerOfHealing []*core.Spell PrayerOfMending *core.Spell Renew []*core.Spell - Shadowfiend *core.Spell Shadowform *core.Spell ShadowWeavingProc *core.Spell - ShadowWordDeath *core.Spell ShadowWordPain []*core.Spell Smite []*core.Spell VampiricEmbrace *core.Spell - VampiricTouch *core.Spell - VoidPlague *core.Spell - VoidZone *core.Spell - - DispersionAura *core.Aura - EyeOfTheVoidAura *core.Aura - HomunculiAura *core.Aura - InnerFocusAura *core.Aura - ShadowfiendAura *core.Aura - ShadowformAura *core.Aura - SpiritTapAura *core.Aura - SurgeOfLightAura *core.Aura - - MindSpikeAuras core.AuraArray + + InnerFocusAura *core.Aura + ShadowformAura *core.Aura + SpiritTapAura *core.Aura + ShadowWeavingAuras core.AuraArray VampiricEmbraceAuras core.AuraArray WeakenedSouls core.AuraArray - EyeOfTheVoidPet *EyeOfTheVoid - HomunculiPets []*Homunculus - ShadowfiendPet *Shadowfiend - - PainAndSufferingDoTSpells []*core.Spell - ProcPrayerOfMending core.ApplySpellResults } @@ -113,7 +83,9 @@ func (priest *Priest) Initialize() { priest.registerMindBlast() priest.registerMindFlay() priest.registerShadowWordPainSpell() - priest.registerDevouringPlagueSpell() + if priest.GetCharacter().Race == proto.Race_RaceUndead { + priest.registerDevouringPlagueSpell() + } priest.RegisterSmiteSpell() priest.registerHolyFire() @@ -128,11 +100,6 @@ func (priest *Priest) RegisterHealingSpells() { // priest.registerRenewSpell() } -func (priest *Priest) Reset(_ *core.Simulation) { - priest.MindFlayModifier = 1 - priest.MindBlastModifier = 1 -} - func New(character *core.Character, talents string) *Priest { priest := &Priest{ Character: *character, @@ -150,36 +117,9 @@ func New(character *core.Character, talents string) *Priest { return 6.25 + priest.GetStat(stats.Spirit)/8 } - priest.ShadowfiendPet = priest.NewShadowfiend() - - if priest.HasRune(proto.PriestRune_RuneHelmEyeOfTheVoid) { - priest.EyeOfTheVoidPet = priest.NewEyeOfTheVoid() - } - - if priest.HasRune(proto.PriestRune_RuneLegsHomunculi) { - priest.HomunculiPets = make([]*Homunculus, 3) - priest.HomunculiPets[0] = priest.NewHomunculus(1, 202390) - priest.HomunculiPets[1] = priest.NewHomunculus(2, 202392) - priest.HomunculiPets[2] = priest.NewHomunculus(3, 202391) - } - - guardians.ConstructGuardians(&priest.Character) - return priest } -func (priest *Priest) HasRune(rune proto.PriestRune) bool { - return false // priest.HasRuneById(int32(rune)) -} - -func (priest *Priest) baseRuneAbilityDamage() float64 { - return 9.456667 + 0.635108*float64(priest.Level) + 0.039063*float64(priest.Level*priest.Level) -} - -func (priest *Priest) baseRuneAbilityHealing() float64 { - return 38.258376 + 0.904195*float64(priest.Level) + 0.161311*float64(priest.Level*priest.Level) -} - // Agent is a generic way to access underlying priest on any of the agents. type PriestAgent interface { GetPriest() *Priest diff --git a/sim/priest/runes.go b/sim/priest/runes.go deleted file mode 100644 index 309935456..000000000 --- a/sim/priest/runes.go +++ /dev/null @@ -1,159 +0,0 @@ -package priest - -import ( - "slices" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (priest *Priest) ApplyRunes() { - // Head - priest.registerEyeOfTheVoidCD() - priest.applyPainAndSuffering() - - // Cloak - priest.registerVampiricTouchSpell() - - // Chest - priest.registerVoidPlagueSpell() - - // Bracers - priest.applySurgeOfLight() - priest.applyDespair() - priest.registerVoidZoneSpell() - - // Hands - priest.registerMindSearSpell() - priest.RegisterPenanceSpell() - priest.registerShadowWordDeathSpell() - - // Belt - priest.registerMindSpikeSpell() - - // Legs - priest.registerHomunculiSpell() - - // Feet - priest.registerDispersionSpell() - - // Skill Books - priest.registerShadowfiendSpell() -} - -func (priest *Priest) applyPainAndSuffering() { - if !priest.HasRune(proto.PriestRune_RuneHelmPainAndSuffering) { - return - } - - priest.PainAndSufferingDoTSpells = []*core.Spell{} - - affectedSpellcodes := []int32{SpellCode_PriestMindBlast, SpellCode_PriestMindFlay, SpellCode_PriestMindSpike} - core.MakePermanent(priest.RegisterAura(core.Aura{ - Label: "Pain and Suffering Trigger", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - priest.PainAndSufferingDoTSpells = append( - priest.PainAndSufferingDoTSpells, - core.FilterSlice( - core.Flatten( - [][]*core.Spell{ - priest.ShadowWordPain, - {priest.VoidPlague, priest.VampiricTouch}, - }, - ), - func(spell *core.Spell) bool { return spell != nil }, - )..., - ) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if slices.Contains(affectedSpellcodes, spell.SpellCode) && result.Landed() { - target := result.Target - - var dotToRollover *core.Dot - dotSpells := core.FilterSlice(priest.PainAndSufferingDoTSpells, func(spell *core.Spell) bool { return spell.Dot(target).IsActive() }) - - if len(dotSpells) > 0 { - dotToRollover = dotSpells[0].Dot(target) - for _, spell := range dotSpells { - dot := spell.Dot(target) - if dot.RemainingDuration(sim) < dotToRollover.RemainingDuration(sim) { - dotToRollover = dot - } - } - - dotToRollover.NumberOfTicks = dotToRollover.OriginalNumberOfTicks - dotToRollover.Rollover(sim) - } - } - }, - })) -} - -func (priest *Priest) applySurgeOfLight() { - if !priest.HasRune(proto.PriestRune_RuneBracersSurgeOfLight) { - return - } - - var affectedSpells []*core.Spell - - priest.SurgeOfLightAura = priest.RegisterAura(core.Aura{ - Label: "Surge of Light Proc", - ActionID: core.ActionID{SpellID: int32(proto.PriestRune_RuneBracersSurgeOfLight)}, - Duration: time.Second * 15, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells = core.FilterSlice( - core.Flatten([][]*core.Spell{priest.Smite, priest.FlashHeal}), - func(spell *core.Spell) bool { return spell != nil }, - ) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedSpells, func(spell *core.Spell) { - spell.CastTimeMultiplier -= 1 - }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedSpells, func(spell *core.Spell) { - spell.CastTimeMultiplier += 1 - }) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - if spell.SpellCode == SpellCode_PriestSmite { - aura.Deactivate(sim) - } - }, - OnHealDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, _ *core.SpellResult) { - if spell.SpellCode == SpellCode_PriestFlashHeal { - aura.Deactivate(sim) - } - }, - }) - - handler := func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskSpellOrSpellProc) && result.Outcome.Matches(core.OutcomeCrit) { - priest.SurgeOfLightAura.Activate(sim) - } - } - - priest.RegisterAura(core.Aura{ - Label: "Surge of Light Trigger", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: handler, - OnHealDealt: handler, - }) -} - -func (priest *Priest) applyDespair() { - if !priest.HasRune(proto.PriestRune_RuneBracersDespair) { - return - } - - priest.OnSpellRegistered(func(spell *core.Spell) { - if spell.Flags.Matches(SpellFlagPriest) && !spell.Flags.Matches(core.SpellFlagHelpful) { - spell.CritDamageBonus += 1 - } - }) -} diff --git a/sim/priest/shadow/TestP1Shadow.results b/sim/priest/shadow/TestP1Shadow.results index b13c4b9e1..0224e34dd 100644 --- a/sim/priest/shadow/TestP1Shadow.results +++ b/sim/priest/shadow/TestP1Shadow.results @@ -1,33 +1,33 @@ character_stats_results: { key: "TestP1Shadow-Phase1-Lvl60-CharacterStats-Default" value: { - final_stats: 175.95 final_stats: 180.55 - final_stats: 476.23225 - final_stats: 372.6 - final_stats: 363.4 - final_stats: 173 - final_stats: 0 - final_stats: 0 - final_stats: 0 + final_stats: 185.15 + final_stats: 462.47825 + final_stats: 319.7 + final_stats: 261.05 + final_stats: 285 final_stats: 0 final_stats: 0 final_stats: 40 - final_stats: 41.25 final_stats: 0 - final_stats: 28.05968 final_stats: 0 + final_stats: 320 + final_stats: 45.25 + final_stats: 1 + final_stats: 29.17096 final_stats: 0 - final_stats: 795.95 + final_stats: 0 + final_stats: 800.55 final_stats: 0 final_stats: 16 final_stats: 0 final_stats: 0 final_stats: 0 - final_stats: 6685 + final_stats: 5891.5 final_stats: 0 final_stats: 0 - final_stats: 1052.1 + final_stats: 879.3 final_stats: 540 final_stats: 0 final_stats: 5 @@ -35,15 +35,15 @@ character_stats_results: { final_stats: 3 final_stats: 5 final_stats: 0 - final_stats: 6279.3225 - final_stats: 35 - final_stats: 68 - final_stats: 68 - final_stats: 68 - final_stats: 78 + final_stats: 6141.7825 + final_stats: 27 + final_stats: 60 + final_stats: 60 + final_stats: 60 + final_stats: 70 final_stats: 384 final_stats: 0 - final_stats: 35 + final_stats: 65 final_stats: 0 } } @@ -53,18 +53,18 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 + weights: 0.35114 weights: 0 - weights: 0 - weights: 0.08882 + weights: 0.29454 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 0.08882 + weights: 0.29454 weights: 0 - weights: 0.45508 - weights: 0.22314 + weights: 5.04909 + weights: 0.47093 weights: 0 weights: 0 weights: 0 @@ -99,98 +99,98 @@ stat_weights_results: { dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Average-Default" value: { - dps: 49.82754 - tps: 49.52526 + dps: 492.68793 + tps: 485.83352 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Dwarf-p0.bis-Basic-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 49.33146 - tps: 82.7582 + dps: 522.09278 + tps: 762.51802 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Dwarf-p0.bis-Basic-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 49.33146 - tps: 49.1282 + dps: 522.09278 + tps: 514.27452 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Dwarf-p0.bis-Basic-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 48.66608 - tps: 48.15904 + dps: 661.35453 + tps: 655.42395 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Dwarf-p0.bis-Basic-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 31.2971 - tps: 30.04522 + dps: 256.91503 + tps: 420.15538 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Dwarf-p0.bis-Basic-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 31.2971 - tps: 30.04522 + dps: 256.91503 + tps: 255.31427 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Dwarf-p0.bis-Basic-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 31.0536 - tps: 29.81145 + dps: 479.19258 + tps: 474.60129 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Undead-p0.bis-Basic-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 49.15098 - tps: 82.58494 + dps: 494.67047 + tps: 732.7942 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Undead-p0.bis-Basic-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 49.15098 - tps: 48.95494 + dps: 494.67047 + tps: 487.77918 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Undead-p0.bis-Basic-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 48.66608 - tps: 48.15904 + dps: 674.0017 + tps: 667.54164 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Undead-p0.bis-Basic-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 31.2971 - tps: 30.04522 + dps: 254.85011 + tps: 418.17306 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Undead-p0.bis-Basic-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 31.2971 - tps: 30.04522 + dps: 254.85011 + tps: 253.33196 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-Settings-Undead-p0.bis-Basic-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 31.0536 - tps: 29.81145 + dps: 488.25164 + tps: 483.29798 } } dps_results: { key: "TestP1Shadow-Phase1-Lvl60-SwitchInFrontOfTarget-Default" value: { - dps: 49.15098 - tps: 48.95494 + dps: 494.67047 + tps: 487.77918 } } diff --git a/sim/priest/shadow/shadow_priest.go b/sim/priest/shadow/shadow_priest.go index edaaffb96..51ecb88db 100644 --- a/sim/priest/shadow/shadow_priest.go +++ b/sim/priest/shadow/shadow_priest.go @@ -56,5 +56,4 @@ func (spriest *ShadowPriest) Initialize() { } func (spriest *ShadowPriest) Reset(sim *core.Simulation) { - spriest.Priest.Reset(sim) } diff --git a/sim/priest/shadow_word_death.go b/sim/priest/shadow_word_death.go deleted file mode 100644 index 38e1fc90e..000000000 --- a/sim/priest/shadow_word_death.go +++ /dev/null @@ -1,61 +0,0 @@ -package priest - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (priest *Priest) registerShadowWordDeathSpell() { - if !priest.HasRune(proto.PriestRune_RuneHandsShadowWordDeath) { - return - } - - // 2024-02-22 In-game value is ~66% base damage after tuning - baseLowDamage := priest.baseRuneAbilityDamage() * 0.66 * 5.32 - baseHighDamage := priest.baseRuneAbilityDamage() * 0.66 * 6.2 - spellCoeff := 0.429 - manaCost := .12 - cooldown := time.Second * 12 - - priest.ShadowWordDeath = priest.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 401955}, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagPriest | core.SpellFlagBinary | core.SpellFlagAPL, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: priest.NewTimer(), - Duration: cooldown, - }, - }, - - BonusCoefficient: spellCoeff, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := sim.Roll(baseLowDamage, baseHighDamage) - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - - if result.Landed() { - priest.AddShadowWeavingStack(sim, target) - } - spell.DealDamage(sim, result) - }, - ExpectedInitialDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, _ bool) *core.SpellResult { - baseDamage := (baseLowDamage + baseHighDamage) / 2 - return spell.CalcDamage(sim, target, baseDamage, spell.OutcomeExpectedMagicHitAndCrit) - }, - }) -} diff --git a/sim/priest/shadow_word_pain.go b/sim/priest/shadow_word_pain.go index e5f96116a..da37e0a72 100644 --- a/sim/priest/shadow_word_pain.go +++ b/sim/priest/shadow_word_pain.go @@ -5,7 +5,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const ShadowWordPainRanks = 8 @@ -16,6 +15,8 @@ var ShadowWordPainSpellCoef = [ShadowWordPainRanks + 1]float64{0, 0.067, 0.104, var ShadowWordPainManaCost = [ShadowWordPainRanks + 1]float64{0, 25, 50, 95, 155, 230, 305, 385, 470} var ShadowWordPainLevel = [ShadowWordPainRanks + 1]int{0, 4, 10, 18, 26, 34, 42, 50, 58} +//To Do: Check rollover code from runes + func (priest *Priest) registerShadowWordPainSpell() { priest.ShadowWordPain = make([]*core.Spell, ShadowWordPainRanks+1) @@ -37,10 +38,6 @@ func (priest *Priest) getShadowWordPainConfig(rank int) core.SpellConfig { manaCost := ShadowWordPainManaCost[rank] level := ShadowWordPainLevel[rank] - results := make([]*core.SpellResult, min(core.TernaryInt32(priest.HasRune(proto.PriestRune_RuneLegsSharedPain), 3, 1), priest.Env.GetNumTargets())) - - hasDespairRune := priest.HasRune(proto.PriestRune_RuneBracersDespair) - return core.SpellConfig{ SpellCode: SpellCode_PriestShadowWordPain, ActionID: core.ActionID{SpellID: spellId}, @@ -67,16 +64,6 @@ func (priest *Priest) getShadowWordPainConfig(rank int) core.SpellConfig { Dot: core.DotConfig{ Aura: core.Aura{ Label: fmt.Sprintf("Shadow Word: Pain (Rank %d)", rank), - OnGain: func(aura *core.Aura, sim *core.Simulation) { - if priest.HasRune(proto.PriestRune_RuneChestTwistedFaith) { - priest.MindBlastModifier = 1.5 - priest.MindFlayModifier = 1.5 - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - priest.MindBlastModifier = 1 - priest.MindFlayModifier = 1 - }, }, NumberOfTicks: ticks + (priest.Talents.ImprovedShadowWordPain), @@ -87,26 +74,18 @@ func (priest *Priest) getShadowWordPainConfig(rank int) core.SpellConfig { dot.Snapshot(target, baseDotDamage, isRollover) }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - if hasDespairRune { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - } else { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - } + dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) }, }, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for idx := range results { - results[idx] = spell.CalcOutcome(sim, target, spell.OutcomeMagicHitNoHitCounter) - target = sim.Environment.NextTargetUnit(target) - } - for _, result := range results { - if result.Landed() { - priest.AddShadowWeavingStack(sim, result.Target) - spell.Dot(result.Target).Apply(sim) - } - spell.DealOutcome(sim, result) + result := spell.CalcOutcome(sim, target, spell.OutcomeMagicHitNoHitCounter) + + if result.Landed() { + priest.AddShadowWeavingStack(sim, result.Target) + spell.Dot(result.Target).Apply(sim) } + spell.DealOutcome(sim, result) }, } } diff --git a/sim/priest/shadowfiend.go b/sim/priest/shadowfiend.go deleted file mode 100644 index 00adb6d38..000000000 --- a/sim/priest/shadowfiend.go +++ /dev/null @@ -1,248 +0,0 @@ -package priest - -import ( - "math" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (priest *Priest) registerShadowfiendSpell() { - actionID := core.ActionID{SpellID: 401977} - duration := time.Second * 15 - cooldown := time.Minute * 5 - - // For timeline only - priest.ShadowfiendAura = priest.RegisterAura(core.Aura{ - ActionID: actionID, - Label: "Shadowfiend", - Duration: duration, - }) - - priest.Shadowfiend = priest.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolShadow, - ProcMask: core.ProcMaskEmpty, - Flags: SpellFlagPriest | core.SpellFlagAPL, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: priest.NewTimer(), - Duration: cooldown, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - priest.ShadowfiendPet.EnableWithTimeout(sim, priest.ShadowfiendPet, duration) - priest.ShadowfiendAura.Activate(sim) - }, - }) - - priest.AddMajorCooldown(core.MajorCooldown{ - Spell: priest.Shadowfiend, - Priority: 1, - Type: core.CooldownTypeMana, - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - return character.CurrentManaPercent() <= 0.01 - }, - }) -} - -type Shadowfiend struct { - core.Pet - - Priest *Priest - Shadowcrawl *core.Spell - ShadowcrawlAura *core.Aura -} - -func (priest *Priest) NewShadowfiend() *Shadowfiend { - baseDamageMin := 0.0 - baseDamageMax := 0.0 - baseStats := stats.Stats{} - // Seems to basically be a reskinned Felhunter so using Felhunter stats - switch priest.Level { - case 25: - baseStats = stats.Stats{ - stats.Strength: 50, - stats.Agility: 40, - stats.Stamina: 87, - stats.Intellect: 35, - stats.Spirit: 61, - stats.Mana: 653, - stats.MP5: 0, - stats.MeleeCrit: 3.2685 * core.CritRatingPerCritChance, - stats.SpellCrit: 3.3355 * core.CritRatingPerCritChance, - } - baseDamageMin = 24 - baseDamageMax = 40 - case 40: - // TODO: All of the stats and stat inheritance needs to be verified - baseStats = stats.Stats{ - stats.Strength: 74, - stats.Agility: 58, - stats.Stamina: 148, - stats.Intellect: 49, - stats.Spirit: 97, - stats.Mana: 653, - stats.MP5: 0, - stats.MeleeCrit: 3.2685 * core.CritRatingPerCritChance, - stats.SpellCrit: 3.3355 * core.CritRatingPerCritChance, - } - baseDamageMin = 24 - baseDamageMax = 40 - case 50: - baseStats = stats.Stats{ - stats.Strength: 107, - stats.Agility: 71, - stats.Stamina: 190, - stats.Intellect: 59, - stats.Spirit: 123, - stats.Mana: 912, - stats.MP5: 0, - stats.MeleeCrit: 3.2685 * core.CritRatingPerCritChance, - stats.SpellCrit: 3.3355 * core.CritRatingPerCritChance, - } - baseDamageMin = 24 - baseDamageMax = 40 - case 60: - baseStats = stats.Stats{ - stats.Strength: 129, - stats.Agility: 85, - stats.Stamina: 234, - stats.Intellect: 70, - stats.Spirit: 150, - stats.Mana: 1066, - stats.MP5: 0, - stats.MeleeCrit: 3.2685 * core.CritRatingPerCritChance, - stats.SpellCrit: 3.3355 * core.CritRatingPerCritChance, - } - baseDamageMin = 70 - baseDamageMax = 97 - } - - shadowfiend := &Shadowfiend{ - Pet: core.NewPet("Shadowfiend", &priest.Character, baseStats, priest.shadowfiendStatInheritance(), false, true), - Priest: priest, - } - - manaMetric := priest.NewManaMetrics(core.ActionID{SpellID: 34433}) - core.MakePermanent(shadowfiend.GetOrRegisterAura(core.Aura{ - Label: "Autoattack mana regen", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - restoreMana := priest.MaxMana() * 0.05 - priest.AddMana(sim, restoreMana, manaMetric) - }, - })) - - shadowfiend.EnableManaBarWithModifier(.77) - - shadowfiend.registerShadowCrawlSpell() - - shadowfiend.PseudoStats.DamageTakenMultiplier *= 0.1 - - shadowfiend.AddStatDependency(stats.Strength, stats.AttackPower, 2) - shadowfiend.AddStat(stats.AttackPower, -20) - - // Warrior crit scaling - shadowfiend.AddStatDependency(stats.Agility, stats.MeleeCrit, core.CritPerAgiAtLevel[proto.Class_ClassWarrior][int(shadowfiend.Level)]*core.CritRatingPerCritChance) - shadowfiend.AddStatDependency(stats.Intellect, stats.SpellCrit, core.CritPerIntAtLevel[proto.Class_ClassWarrior][int(shadowfiend.Level)]*core.SpellCritRatingPerCritChance) - - shadowfiend.EnableAutoAttacks(shadowfiend, core.AutoAttackOptions{ - MainHand: core.Weapon{ - BaseDamageMin: baseDamageMin, - BaseDamageMax: baseDamageMax, - SwingSpeed: 1.5, - AttackPowerPerDPS: 14.0 / 6.0, // Observed 6 times stronger AP scaling then expected - SpellSchool: core.SpellSchoolShadow, - }, - AutoSwingMelee: true, - }) - - priest.AddPet(shadowfiend) - - return shadowfiend -} - -func (priest *Priest) shadowfiendStatInheritance() core.PetStatInheritance { - return func(ownerStats stats.Stats) stats.Stats { - // Shadowfiend seems to benefit from the owner's Spell Hit + Shadow Focus hit chance - ownerHitChance := (ownerStats[stats.SpellHit] + 2*float64(priest.Talents.ShadowFocus)) / core.SpellHitRatingPerHitChance - highestSchoolPower := ownerStats[stats.SpellPower] + ownerStats[stats.SpellDamage] + max(ownerStats[stats.HolyPower], ownerStats[stats.ShadowPower]) - - // TODO: Needs more verification - return stats.Stats{ - stats.Stamina: ownerStats[stats.Stamina] * .75, - stats.Intellect: ownerStats[stats.Intellect] * 0.3, - stats.Armor: ownerStats[stats.Armor] * 0.35, - stats.AttackPower: highestSchoolPower * 0.57, - stats.MP5: ownerStats[stats.MP5] * 0.3, - stats.SpellPower: ownerStats[stats.SpellPower] * 0.15, - stats.SpellDamage: ownerStats[stats.SpellDamage] * 0.15, - stats.ShadowPower: ownerStats[stats.ShadowPower] * 0.15, - stats.SpellPenetration: ownerStats[stats.SpellPenetration], - stats.MeleeHit: ownerHitChance * core.MeleeHitRatingPerHitChance, - stats.SpellHit: math.Floor(ownerHitChance / 12.0 * 17.0), - // Shadowfiend seems to most likely use the priest's Spell Crit to scale its melee crit - // In reality the melees are shadow damage and probably use the spell hit table but we can't configure that currently - stats.MeleeCrit: ownerStats[stats.SpellCrit], - stats.SpellCrit: ownerStats[stats.SpellCrit], - } - } -} - -func (shadowfiend *Shadowfiend) Initialize() { -} - -func (shadowfiend *Shadowfiend) ExecuteCustomRotation(sim *core.Simulation) { - shadowfiend.Shadowcrawl.Cast(sim, shadowfiend.CurrentTarget) -} - -func (shadowfiend *Shadowfiend) Reset(sim *core.Simulation) { - shadowfiend.ShadowcrawlAura.Deactivate(sim) - shadowfiend.Disable(sim) -} - -func (shadowfiend *Shadowfiend) OnPetDisable(sim *core.Simulation) { - shadowfiend.ShadowcrawlAura.Deactivate(sim) -} - -func (shadowfiend *Shadowfiend) GetPet() *core.Pet { - return &shadowfiend.Pet -} - -func (shadowfiend *Shadowfiend) registerShadowCrawlSpell() { - actionID := core.ActionID{SpellID: 401990} - shadowfiend.ShadowcrawlAura = shadowfiend.GetOrRegisterAura(core.Aura{ - Label: "Shadowcrawl", - ActionID: actionID, - Duration: time.Second * 5, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shadowfiend.PseudoStats.DamageDealtMultiplier *= 1.15 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shadowfiend.PseudoStats.DamageDealtMultiplier /= 1.15 - }, - }) - - shadowfiend.Shadowcrawl = shadowfiend.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolShadow, - ProcMask: core.ProcMaskEmpty, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: time.Second * 6, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - shadowfiend.ShadowcrawlAura.Activate(sim) - }, - }) -} diff --git a/sim/priest/talents.go b/sim/priest/talents.go index 6c4d56451..2dd3c9ddd 100644 --- a/sim/priest/talents.go +++ b/sim/priest/talents.go @@ -226,8 +226,6 @@ func (priest *Priest) applyDarkness() { [][]*core.Spell{ priest.MindBlast, priest.DevouringPlague, - priest.MindSearTicks, - {priest.ShadowWordDeath}, }, ), func(spell *core.Spell) bool { return spell != nil }, @@ -237,9 +235,6 @@ func (priest *Priest) applyDarkness() { core.Flatten( [][]*core.Spell{ priest.ShadowWordPain, - {priest.VoidPlague}, - {priest.MindSpike}, - {priest.VoidZone}, }, ), func(spell *core.Spell) bool { return spell != nil }, @@ -329,17 +324,17 @@ func (priest *Priest) registerShadowform() { actionID := core.ActionID{SpellID: 15473} + //To Do: Add physical damage resistance + priest.ShadowformAura = priest.RegisterAura(core.Aura{ Label: "Shadowform", ActionID: actionID, Duration: core.NeverExpires, OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexShadow] *= 1.25 - aura.Unit.PseudoStats.SchoolCostMultiplier[stats.SchoolIndexShadow] -= 50 + aura.Unit.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexShadow] *= 1.15 }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexShadow] /= 1.25 - aura.Unit.PseudoStats.SchoolCostMultiplier[stats.SchoolIndexShadow] += 50 + aura.Unit.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexShadow] /= 1.15 }, OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { if spell.SpellSchool.Matches(core.SpellSchoolHoly) { diff --git a/sim/priest/vampiric_touch.go b/sim/priest/vampiric_touch.go deleted file mode 100644 index aa9e49b29..000000000 --- a/sim/priest/vampiric_touch.go +++ /dev/null @@ -1,103 +0,0 @@ -package priest - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (priest *Priest) registerVampiricTouchSpell() { - if !priest.HasRune(proto.PriestRune_RuneCloakVampiricTouch) { - return - } - - hasDespairRune := priest.HasRune(proto.PriestRune_RuneBracersDespair) - - numTicks := int32(5) - tickLength := time.Second * 3 - baseTickDamage := priest.baseRuneAbilityDamage() * .65 - spellCoef := 0.167 - castTime := time.Millisecond * 1500 - manaCost := 0.16 - - partyPlayers := priest.Env.Raid.GetPlayerParty(&priest.Unit).Players - // https: //www.wowhead.com/classic/spell=402779/vampiric-touch - manaMetrics := priest.NewManaMetrics(core.ActionID{SpellID: 402779}) - manaReturnedMultiplier := 0.05 - - manaGainAura := priest.RegisterAura(core.Aura{ - Label: "Vampiric Touch (Mana)", - Duration: core.NeverExpires, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellSchool.Matches(core.SpellSchoolShadow) { - manaGained := result.Damage * manaReturnedMultiplier - for _, player := range partyPlayers { - player.GetCharacter().AddMana(sim, manaGained, manaMetrics) - } - } - }, - }) - - priest.VampiricTouch = priest.RegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_PriestVampiricTouch, - ActionID: core.ActionID{SpellID: int32(proto.PriestRune_RuneCloakVampiricTouch)}, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagPriest | core.SpellFlagAPL | core.SpellFlagPureDot, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - CastTime: castTime, - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: "VampiricTouch", - OnGain: func(aura *core.Aura, sim *core.Simulation) { - manaGainAura.Activate(sim) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - manaGainAura.Deactivate(sim) - }, - }, - - NumberOfTicks: numTicks, - TickLength: tickLength, - BonusCoefficient: spellCoef, - - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - dot.Snapshot(target, baseTickDamage, isRollover) - if isRollover && priest.VampiricEmbraceAuras != nil { - priest.VampiricEmbraceAuras.Get(target).Activate(sim) - } - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - if hasDespairRune { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - } else { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - } - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - result := spell.CalcOutcome(sim, target, spell.OutcomeMagicHitNoHitCounter) - if result.Landed() { - priest.AddShadowWeavingStack(sim, target) - spell.Dot(target).Apply(sim) - } - spell.DealOutcome(sim, result) - }, - }) -} diff --git a/sim/priest/void_plague.go b/sim/priest/void_plague.go deleted file mode 100644 index fa056bfa0..000000000 --- a/sim/priest/void_plague.go +++ /dev/null @@ -1,82 +0,0 @@ -package priest - -import ( - "strconv" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -// https://www.wowhead.com/classic/spell=425204/void-plague -// https://www.wowhead.com/classic/news/patch-1-15-build-52124-ptr-datamining-season-of-discovery-runes-336044 -func (priest *Priest) registerVoidPlagueSpell() { - if !priest.HasRune(proto.PriestRune_RuneFeetVoidPlague) { - return - } - - hasDespairRune := priest.HasRune(proto.PriestRune_RuneBracersDespair) - - ticks := int32(6) - tickLength := time.Second * 3 - - // 2024-02-22 tuning 10% buff - baseTickDamage := priest.baseRuneAbilityDamage() * 1.17 * 1.1 - spellCoeff := .166 - manaCost := .13 - cooldown := time.Second * 6 - - priest.VoidPlague = priest.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: int32(proto.PriestRune_RuneFeetVoidPlague)}, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagPriest | core.SpellFlagAPL | core.SpellFlagDisease | core.SpellFlagPureDot, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: priest.NewTimer(), - Duration: cooldown, - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: "VoidPlague-" + strconv.Itoa(1), - }, - - NumberOfTicks: ticks, - TickLength: tickLength, - BonusCoefficient: spellCoeff, - - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - dot.Snapshot(target, baseTickDamage, isRollover) - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - if hasDespairRune { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - } else { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - } - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - result := spell.CalcOutcome(sim, target, spell.OutcomeMagicHitNoHitCounter) - if result.Landed() { - priest.AddShadowWeavingStack(sim, target) - spell.Dot(target).Apply(sim) - } - spell.DealOutcome(sim, result) - }, - }) -} diff --git a/sim/priest/void_zone.go b/sim/priest/void_zone.go deleted file mode 100644 index 8f62563a3..000000000 --- a/sim/priest/void_zone.go +++ /dev/null @@ -1,86 +0,0 @@ -package priest - -import ( - "strconv" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (priest *Priest) registerVoidZoneSpell() { - if !priest.HasRune(proto.PriestRune_RuneBracersVoidZone) { - return - } - - ticks := int32(10) - tickLength := time.Second * 1 - - baseTickDamage := priest.baseRuneAbilityDamage() * .51 - spellCoeff := 0.084 - manaCost := .21 - cooldown := time.Second * 30 - - hasDespairRune := priest.HasRune(proto.PriestRune_RuneBracersDespair) - - priest.VoidZone = priest.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: int32(proto.PriestRune_RuneBracersVoidZone)}, - SpellSchool: core.SpellSchoolShadow, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagPriest | core.SpellFlagAPL | core.SpellFlagPureDot, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: priest.NewTimer(), - Duration: cooldown, - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - Dot: core.DotConfig{ - IsAOE: true, - Aura: core.Aura{ - Label: "VoidZone-" + strconv.Itoa(1), - }, - - NumberOfTicks: ticks, - TickLength: tickLength, - BonusCoefficient: spellCoeff, - - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - dot.Snapshot(target, baseTickDamage, isRollover) - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - if hasDespairRune { - dot.CalcAndDealPeriodicSnapshotDamage(sim, aoeTarget, dot.OutcomeSnapshotCrit) - } else { - dot.CalcAndDealPeriodicSnapshotDamage(sim, aoeTarget, dot.OutcomeTick) - } - } - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.AOEDot().Apply(sim) - }, - - ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, useSnapshot bool) *core.SpellResult { - if useSnapshot { - dot := spell.Dot(target) - return dot.CalcSnapshotDamage(sim, target, dot.Spell.OutcomeExpectedMagicAlwaysHit) - } else { - return spell.CalcPeriodicDamage(sim, target, baseTickDamage, spell.OutcomeExpectedMagicAlwaysHit) - } - }, - }) -} diff --git a/ui/healing_priest/inputs.ts b/ui/healing_priest/inputs.ts index ca955a898..0e6525553 100644 --- a/ui/healing_priest/inputs.ts +++ b/ui/healing_priest/inputs.ts @@ -1,10 +1,9 @@ +import * as InputHelpers from '../core/components/input_helpers.js'; import { Player } from '../core/player.js'; import { Spec, UnitReference, UnitReference_Type as UnitType } from '../core/proto/common.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { EventID } from '../core/typed_event.js'; -import * as InputHelpers from '../core/components/input_helpers.js'; - // Configuration for spec-specific UI elements on the settings tab. // These don't need to be in a separate file but it keeps things cleaner. @@ -28,9 +27,4 @@ export const SelfPowerInfusion = InputHelpers.makeSpecOptionsBooleanIconInput({ fieldName: 'useInnerFire', actionId: () => ActionId.fromSpellId(48168), -}); - -export const Shadowfiend = InputHelpers.makeSpecOptionsBooleanIconInput({ - fieldName: 'useShadowfiend', - actionId: () => ActionId.fromSpellId(34433), -}); +}); \ No newline at end of file diff --git a/ui/healing_priest/presets.ts b/ui/healing_priest/presets.ts index 7a91ef93d..42e620676 100644 --- a/ui/healing_priest/presets.ts +++ b/ui/healing_priest/presets.ts @@ -43,8 +43,6 @@ export const HolyTalents = { export const DefaultOptions = Options.create({ useInnerFire: true, - useShadowfiend: true, - rapturesPerMinute: 5, powerInfusionTarget: UnitReference.create(), }); diff --git a/ui/healing_priest/sim.ts b/ui/healing_priest/sim.ts index dad46821e..896a4d320 100644 --- a/ui/healing_priest/sim.ts +++ b/ui/healing_priest/sim.ts @@ -78,7 +78,6 @@ const SPEC_CONFIG = registerSpecConfig(Spec.SpecHealingPriest, { playerIconInputs: [ HealingPriestInputs.SelfPowerInfusion, HealingPriestInputs.InnerFire, - HealingPriestInputs.Shadowfiend, ], // Buff and Debuff inputs to include/exclude, overriding the EP-based defaults. includeBuffDebuffInputs: [ diff --git a/ui/shadow_priest/apls/p1.apl.json b/ui/shadow_priest/apls/p1.apl.json index 479045c3a..416d6fb4b 100644 --- a/ui/shadow_priest/apls/p1.apl.json +++ b/ui/shadow_priest/apls/p1.apl.json @@ -1,8 +1,13 @@ { "type": "TypeAPL", - "prepullActions": [], - "priorityList": [ - {"action":{"autocastOtherCooldowns":{}}}, - {"action":{"castSpell":{"spellId":{"spellId":8103,"rank":3}}}} - ] + "prepullActions": [ + {"action":{"castSpell":{"spellId":{"spellId":15473}}},"doAtValue":{"const":{"val":"-1s"}}} + ], + "priorityList": [ + {"action":{"autocastOtherCooldowns":{}}}, + {"action":{"condition":{"and":{"vals":[{"not":{"val":{"dotIsActive":{"spellId":{"spellId":10894,"rank":8}}}}},{"cmp":{"op":"OpGe","lhs":{"remainingTime":{}},"rhs":{"const":{"val":"10"}}}}]}},"castSpell":{"spellId":{"spellId":10894,"rank":8}}}}, + {"action":{"strictSequence":{"actions":[{"castSpell":{"spellId":{"spellId":14751}}},{"castSpell":{"spellId":{"spellId":19279,"rank":5}}}]}}}, + {"action":{"castSpell":{"spellId":{"spellId":10947,"rank":9}}}}, + {"action":{"castSpell":{"spellId":{"spellId":18807,"rank":6}}}} + ] } \ No newline at end of file diff --git a/ui/shadow_priest/gear_sets/p0.bis.gear.json b/ui/shadow_priest/gear_sets/p0.bis.gear.json index 19141f4df..bb06241c7 100644 --- a/ui/shadow_priest/gear_sets/p0.bis.gear.json +++ b/ui/shadow_priest/gear_sets/p0.bis.gear.json @@ -1,19 +1,19 @@ -{"items": [ - {"id":16693}, - {}, - {"id":16695}, - {}, - {"id":16690}, - {"id":16697}, - {"id":16692}, - {"id":16696}, - {"id":16694}, - {"id":16691}, - {}, - {}, - {}, - {}, - {}, - {}, - {} -]} \ No newline at end of file +{"items": [ + {"id":10504,"randomSuffix":1861,"enchant":1509}, + {"id":18691}, + {"id":14112}, + {"id":13386,"randomSuffix":1851}, + {"id":14136,"enchant":1891}, + {"id":10248,"randomSuffix":1851,"enchant":1883}, + {"id":18407}, + {"id":11662}, + {"id":13170,"enchant":1509}, + {"id":18735,"enchant":851}, + {"id":13001}, + {"id":13001}, + {"id":13968}, + {"id":12930}, + {"id":13349,"enchant":2504}, + {"id":15942,"randomSuffix":1852}, + {"id":13396} + ]} \ No newline at end of file