From 88388a300949ef33d9cae7b097cdfe48bfd23fa7 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:25:57 -0500 Subject: [PATCH 01/83] Delete assets/img/unholy_rune.png --- assets/img/unholy_rune.png | Bin 1840 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 assets/img/unholy_rune.png diff --git a/assets/img/unholy_rune.png b/assets/img/unholy_rune.png deleted file mode 100644 index 99cd7e6c0fadc1dcfe5f5d4e431bdee8f2ee1d0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1840 zcmV-02haG4P)P000;W1^@s654Bdt00004XF*Lt006O% z3;baP0000WV@Og>004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv0RI600RN!9r;`8x21iLmK~zY`O_p7#rezg|ueH|myzlqzy=P|6{+l0nBN{rH zf|YcVQD9^cr6v?~CUzi#ltL$pCy5?(5FHdG5T*Z>d;qXU3V? z|KIn1@B2J!b+EO%kJj16THNbiOTPH8ThIUrMP0!K5ko`S-r8QlA*FOtMEHNzQW?r{ z!!QhsBJxKK?UwhBbJfNNIl8loghD9yKX4xk-~s`-Iw1}?+q+xWMEL!K57(DcMqYiz ztLu9(4_^t7)nw^W75$osE)6oUGu~u(Zi~SRhy$SUZsF<#5GqV(-D&X0N|am0bdV&c zUHz^~T?%nZl=nOJUJ@y_=~Bw+Aq{<4tyW#d)Q8DX7qF7^y$f{TWYJ?YwoFihxqjovxw+!9$6idUbe91c> zUz%Qe(3b6`GV17=GEH)4p-qmf;lP)@4JHKEa{iUyG)NO(X*L&z1C zdXp;iRfDk5-pg%8`th5SHy+T|Uaa(}Q&Hm-W)G#5Zx@wTL=Xckt`@VeYnD4CNuxfJ^9#;sCQMcWW<2Qabwy1&~I1Y_bXnY(c zT*Dxc2yj6~=3V?V9xe(J7LXjxf`wsyy=_SSA9mUKW?Eoz1@(_~Ob^eZN915nayFz% zVrI#*Fi6EqMZ*C_0+mnzOa+oro4~76N+lX{Kk9F}=gGT&lrrs#Q%}K+>IW_p5v<81 zGqNQ#3nEG#pp=Su5Xb>c15rh@kj$v!s0iT9qFg`Cd+Vub@?wEwI79?qDZ4*XogT2qAt_PYEo=LsY?J6PIbq`c5+HD zw9WXRb9sEDAlDk!m`|Z~y1wEfL7PX>0Td1!h(#WuNL!a=F;%_VH0p&sdZ1qiye<%4|+c zpj|=wp(YMu>%SU?;dkQlJxhnqP9`%J<`>T;?2XKLqf);-6@~d@8pIO=-|vE-Nqt%DW7&wVo-Zye1;lTDWljVtISx{40k2P|%lM zpg2_bsD1sD_x8m6WM$*jx$9`oEWWx_*Pb1x(a`2ZPH|3E-%*8$!nR>Z&>OO)N?&V_ zs(}Y5Ppr3vdb+qD_X?#H$}qepUHb0Q{;@MhE*y*1ty3J@TE?dNrJUM}nheYNRn2-{ z1$`&eyqQU4%d^IseKW%vp~}F@+G=v)V-x!OdM#I%Szn{~7b4`*(QM&oH`b5#*H1sp zaXH1pXps=!DU`jQLQU~EPkK&+`g#!0M8rJ{`68B1WwT_E%9vWT;e}xSS$CcX+Zm=-ZncvyRD=Sp7+eyJi__N(Vcm&Y+!C zIt;{|E~R+NES^oud_SJvc}AYU>h;AJr5kVKKBH3SJ*eP6I8qM(@_iStLW$+ z-?I7d$?9Tk<+cwANrI&rc>B}$|Jx?E< zEPrdgyK=I+y@pnGwkF%*)R$(pf2_E_QR=XCU<74%bGKINZxwweEL3ycYz?Qau}|b| zAE;IqB8D)LgIg};W!=l)xnkq0b5~xthH-b8G*=cVL&1j{G0{JdySbNvVcaZ$2f2*c zy)eCeXl?HMg}RQ}&1syUYP*zr@BW&VpO2eyh$ziqkbggBLo0M@6252GB!d&fXYu)VkC({}Hyi=Q=&W;|k?=CE2xI|&D@ zHx`FwtR}>pgKP`<59QdP93WM<*8l(jC3HntbYx+4WjbSWWnpw>05UK#GA%GSEipJ$ zFgQ9iI65*lD=;uRFfesjxby%303~!qSaf7zbY(hiZ)9m^c>ppnGBPbNH!U$ZR4_O? eG&njkH7hVMIxsK<3IIp|0000 Date: Mon, 23 Dec 2024 12:26:23 -0500 Subject: [PATCH 02/83] Delete assets/img/death_rune.png --- assets/img/death_rune.png | Bin 1975 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 assets/img/death_rune.png diff --git a/assets/img/death_rune.png b/assets/img/death_rune.png deleted file mode 100644 index 819ab5b6c57cce8b0163667e3f40fe01c09302a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1975 zcmV;o2T1sdP)P000>X1^@s6#OZ}&00004XF*Lt006O% z3;baP0000WV@Og>004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv0RI600RN!9r;`8x2F^)DK~zY`eU#g)rez&K*YA0r_kF*;XK(k+IA_t)$+Xc1 zCm~BI6G4lT3NO;T5Gu3-MV6$H7!(;sVi^<|Y8NVr;dr4bm?&zfglNv_kmF$-=d|~p z`S$ni_wXEkzb>RMTYti0v1Gh{1yP|Y0f6F^6Ei0`y74H>Gh>$Gl({s=X(zU_cDjZ- zJ6ur|;jJwP_}dwe0dUDHm#}?tJ5V7QjznbO5Q_wyNae#R6u#cK?V+{||7_cC&+Ocq zA&ZhS)H#4(T>>lpXi6_*53NN zE5gCh%+@E@QeSSGZceSNRy2#VDO@viym@+Nb)HI=FkkrS>Dxak6K?WW?Q+Gx3E{@| z!-nV2+rJA3%yn~&*4G!fB7c&=h8S&4XXQ{v9}d3uXGyV(#Y?E`(Smh(p^CwqkbbK>9n!?RT5mbX)D3!>XAS<1QP@_N0kHItKcSJG$3H ziRnTyzXNkCBJ$d36h56TUu!=9V{WdQm#+NQ20L4#BTWk{)5&;M+qH?V$>d15$P`sxhv<2^V?mqeJXlksO;7t{8%dY6sd$%G*AjU zKtBw0xus{7!~j4dp53W`RFlijbfnh(YH;lh(=vUrrTa)?I5(sfdCu47yx0`UxHaJp zO?sWBGN(Nxi=>X)r3hIMfP-Or*O#pHzNuKn{kn zn}~BIi_Q-upXvR;+`9R%ItllsHZ{ZYK-YCgd%FFZbXG^dE>cKj6A=mKakvu1zaS#x zVsdG=R1NgQJ8KSH{r1jx{(5ZTFeN1%C@M;+3fb#rDm1E|f)wC3K`s;Is({~9OGQm3 zwN=#29BP=oapXo{p08%VF<;NVQQ>j;rc~*&<%K2Q-*AM3C%;cnaR4ZwqSu@1TV~}} zQS;#2nrhl2EC(up-OjngA%yKsQ(azpUs=g3F{jO4 z?(1=$+A@>r@o@b9<7<|#TR!zz{?{q55;_<04uZ<88`x>B&Fc_R%@hiX*5I}PzjU~t zG_IcaB0-FAgWgg~T*z@CmmZ~vgZa6>*y5t{6x4lK%Gs)H?N z%bSX1KoN5|{5B6i@~U4EY>!dKvDj*gc|MhhlBlqwBdIqylSOFa+;|4poriQg;svhA z>2(gTmX-8oTuEsdhFd!6Zpu!d64lRmb3RZPkH=%)C`HLb!Daw8^clfEm(ibhl$%wg z5|Qmm)5kNzTT*tG2dvoV%Sw4*d~E#9TI+LSjL-J;`xUz^5bkietA!6LG%`v?QA8Zs z%6%37dn4+{J#t3DF3RX@N%9|C>%SK1A9GG!<%$F|yU00z<)HDNmTo~s@2cvs7<_%N z6CZJcdP|YKIFK1oA{q_3SMZC0`mPb9g@)#ynsBA_{vsz53Z-(iOv+Rzxh*?N$qx>> zKR=Q7CF1Vv6m#|@PF@DZtlX~H7YcT_Q4q72Yr>Na4S}#5U+u$jzIuDGkak4kBoZes zPs_n!5|_KKql+CKEs=ifVEvtaT)nhUT}&GH6v}EL|HZ^!GVIre9XGMP4i`Z#O_V!( zi(6MM(pg8VEuBr5BmKd!a$@C)RMN(-v>)qe>FH6*ya-o_lZU+q0`A2EpDoy;S;0G2 z3bthE3xh>6<-@=ghL9xE>nbfR9o@47{S#r(;hCZIdsmr0($k;O({BaagmJ*K+&}U& zo|-fr9jrf;wA&xaFBGSXAyzSKRSq|G zwcB~2kwC$4>S%04nHY+`t)!@^dhaQwMYY5u&EnhtKJyKZu06V{xSxVUML`s^M8TN0 z9U&6YP*9)AE}^2B8LCDmBcd2A8Ra2^WpRR;E*C8iwPCV!Wc?A|-SjSs!~Qox#i57@ zlW9kob`vt0fsR5#F#v)DyagIY2(AYn1xid2&|=u5D)c}5^Dkf{|Cj#&Tf>4(I-6X3 z0000bbVXQnWMOn=I%9HWVRU5xGB7eSEigANF*sB(I65>rIx#XUFfckWFwwp0rvLx| zC3HntbYx+4WjbwdWNBu305UK#GA%GSEipJ$FgQ9iIXW>iD=;uRFfgFtQX2pO002ov JPDHLkV1l{4s{8-| From e454a53bcd65b9ac0f5a3beba2b489c3b16e4ee0 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:26:38 -0500 Subject: [PATCH 03/83] Delete assets/img/blood_rune.png --- assets/img/blood_rune.png | Bin 1613 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 assets/img/blood_rune.png diff --git a/assets/img/blood_rune.png b/assets/img/blood_rune.png deleted file mode 100644 index 7c563ffa4fcd98121b687bdad28d9630b795b681..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1613 zcmZ{keKgYx7{`BTFP4{-yoc^&UN$yjUBZ;NP2QHg6x$?bR@x1DKU-ef=tacDh*5Nf z6`_{owe+e~LLw=W$|!g2y4&47_ndpqJ?Gx@oagzT=XuWOeE<9A`ulpS!t`JO0I1@< z+=z13l(#+JhB^=lCz`EDHPMf3rHR8s(8WdndjeqwzBfJ8I^ ze5L?^!vz4)W|Rv9cFG^%gWjHQfb6fTx>I)^06=KGn`@xg{fy!Robcc+_n7m|uP0{h zXCIqX(0B=ivRDSXafk;e5v=)_UA+ggegf_OUJcFj+vO(Wt4mBXQ)pz1;-btU;*CI# zKRD;$slc2zyqWLDvK`T zj67$f977>4kT6F8PnLIUJwY6%&UNg0S4~Ck+&7*9sx*7Z^vgZ@5jxT^ZmyjFyNEpO`(IIabst2fFC*vhd8*Xnj^H`)6t7*@^fgi60@tZDWMl$O+c zb;O}Nv+61NtvW^=j4^h9`0+jLdX0#}OVN*lsrwndQe+M4;J2wjWtSxp$7Bpt+R(l) z{g$0!n_67wAb-j}V?o)~*!!}1ajk!z;z-k@O2?2bRrt%4Jf;O3vOZ)O=dt8e^O1H! z7N-9c`Q`M>iAA+vTlzi~po{{DHnb#Nd`4KWxFox_vi7jg_wOYgvi`eMfgq@fYaZg> zaOXiMeZ@|0x3#VIhKWK`SmJhiL^_VmxMERvw-VCAj8mgoHc2EOxP@#4#(7j>zgvQ) z2dy;#EE@#KbKOp%x5M`p+D+5@Y%8n?b3vu~(z2Xu%_>N-u&+5x-{Twe{;hUo!+1SW zlFMgsRf8MJ*}p55^B}KmAD)^Rzy1p*1>aTfFOhGdnFJVrmO$`b>sHP}kcFHWTKA)^ zCy##VdTud%9DluP=b+jpf6MkQCb^<-$*J#qPACb;UzX3c2Cdr` zkqw{;B1OhPmToF(doEgR(3y41DJ}H2aB+IMzkk;Hhos~6*XnKD$DY6S;UHI(5ydv2 z>#uf(V?82pQKG|;lj}?8CX!}n@#+R22C0M6nKKz!r^L8t)RtDd=GY2u2LAS*0dhl) z3$2KlBla`n&v`w#sPn0=mMIQTdhWayYRX)DLAFw5Bdn|^d-~(VWk%6zr|)VJv8l;9i^h<$&2g4hgg)QSk{8M;QOXVE;Cm?t$CN836C@>(;c3lKCeWq03MJ From 560d55a6abe8556518804534a3c19491fdbef0cd Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:26:48 -0500 Subject: [PATCH 04/83] Delete assets/img/frost_rune.png --- assets/img/frost_rune.png | Bin 2133 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 assets/img/frost_rune.png diff --git a/assets/img/frost_rune.png b/assets/img/frost_rune.png deleted file mode 100644 index 4b9884918fa98d3c37f7dca171983684fa2b0a75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2133 zcmV-b2&(sqP)P000^Y1^@s6LVfqm00004XF*Lt006O% z3;baP0000WV@Og>004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv0RI600RN!9r;`8x2W&}1K~zY`U6xynT~!&!f8W|`pWDp2%uLUjdub`1wiGCr za+Qms!4QKY4`2ZC!31868Xrus4+b@nC=dFg#0QD^fYCsLL=g&NfkL=hU>-@?j>D_$A-VO1|&6zW?`6){<|XO#p*c5da2Fq%_^MBGhp1oJZF4 zw_jf=9@saLzGGV9wnBQZb%H;%SnmunsBGr)VRA`^}{_UTkSh)Yu)#cztX7QbM?N&a~%9s z3fGL-X#ZL0nP3ga8eC%#Vk|IlQ)H3??X;quL^QkY;)=H8PCobeKu;bx)AJrY+Ftv1 zBk(IKofbb0&9N+5n`3h5lTC&wqd?3C1Qf~|vT=lKViYkc6NA+lG&)JZaaLMk_+~YT z_GdETLp3kBs2K!@Nz6*Am`^Z}pRS1KuiKo~03=#7Qi|$W3B4SO%ohuGe(St0*?2ss zlxqxuA4~9Nvy-?gMY=Toe9){70x$S=n96?F_x<;hVEA))y!iTjzDU6sirS>+wk=Mi z62@XAY8l)8uorl5Oz$xI{YIAoQW#IGo0dxX`!Go*2g^k*59XtwUyLHIoSlnLhrzq~ zI638-(Y}nbK{=cLWasvUU{869QrM?3o|{0N`@@ubQ3u^w?sN|x>G_9y3p*P6OuNg_ zM7IuY;m3inbV*@MIYK&ZY^G@A{#{FpGpD=5%RZ`1?I5j}GC9`&PTifc z>M5=7*}84}nzDRtJe#_)OD89?wjLtlG;pF(Iv#z|9QT)rt+0#X`$J?DJ z-#&dVS+1{tzUc?MiNb$q;?P<{vtAo~G7Q4s_f7oRsp05Xmrhh3+LqI%WKd&T{+L$o z!ANtP_RYOy-Ia{aJyFi2cB9n|t;F7ZDhkUd`(e0JZ9abdZ0&Hr)6HX~0Yna8x!ZuP zW0($y!)=WqytxxbxBJ0p3zErLrQdZN`Ocx2|M~U>JGQN-w7PvPmwWR4m7_nM*}muhaqxz@~mTyM_|2H{>t$+=t{JvBKTw4I6jzE3#td%#%{nX`$xyx;ey zI^HPP97d|0jHaWEyM5=LrBG?vkrwC6v6HGZxAo)Wetg{<)z$motu-z=dZsp7ZM3V& zAgU6@#~o46Obq=KySisbQh4GpVCc15qO~f-h6+aAfSY*)Ot583Avu3~a`EE1$@XHt z&?`Erg;wA9mOI|+$LpQ)r>#cM>-Pgjrl6we;fbMtC>O`8KzB0eC42f+t3}6HYZBH91u(6lu2CCr(yZC)&OBe;X4&fU$WT zeV`Ee$8OBn56WSHSVcCc@mmpkhyj5F0Y^}xAeDB|YJ{bViJ$d4ov9PO{uQ6LJ8o%m zl5V$4)a`?b|1?paeB1Mag+#QcbBW^{j{w2JA~q&bphHIk3K7S}s-jNoin#GUWyzRP z7+G(SMa;z*+)>}7+4n3q5io$gX}#BdDpQ!MIO)QyFO}U#qCqV)8m>w*>dp?Skct+IS*1#wCuw!3cwqM=kPjg3SZF zK)r6@0HU-c$#24T>#GcWQe%Y$V^rFRnMb1Hy3muwT_0)V57NMOz{S9GSi6q3-^7?5 z80%uKfI1D-*wDxara)O>N?AK;Fl%-gL{T*KK|cf3(B^Z2#5Y#0I-?oJ8Yly0L{@>P zf%8CK!ZHo^M&Jj)Uf>g87T5|r1nja_j9B|iF|lie%TdXT2pw$S7tsP{vS=_;L zr#1FkBaDEbv0=I|0k>^V`*mO(@PPfmL2K=Ez{)0kFDAJc=mS~c6fn{l8v?IxJYd`+ zP*Rp-KpkiSXMlr7xD@yia3Sy^m|p;|ScfL41d9fB49n$!0{#rV0Qee6HuZi6IHW|h z5xSeV!CL%Hp!{C~1VG{@5&2Qr0rlH~&TScqwjxeFW#VprJOC^J!;PJ(`;?_6#vGa&`etXZIy9*IvEpLAoi2&835DT+y?z6|VVI4uqDVHs zGGhOCF2K^J`##u|;2PjEV7G#o(@9J@?4gaJ?~apBj8!6(!yXl{fxhs9?N|ZPDS{-S z?gjMPZEP3-7A$NodH_^`zX1+VF~S-sjBI2v^4Z-vN2FR9flLzd*dq_4ufFmUtUxe? zdT)SVtI_jAh(g4IwblTKf#-m$fS&*v;P1d&M%b9yDpJN!4!uoPHe|>E{{{NU`}c8V zoB{v<03~!qSaf7zbY(hYa%Ew3WdJfTGBPbNH!U$ZR4_O?G&ediH7hVMIxsK_)8v`} z001R)MObuXVRU6WZEs|0W_bWIFfuYNFgGnRI8-n=Iy5&rF*PeNFgh?WdyZTt00000 LNkvXXu0mjfnMeMd From 1df706526ffc5e05e6400c8e9312115701512d7d Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:27:24 -0500 Subject: [PATCH 05/83] Delete sim/paladin/runes.go --- sim/paladin/runes.go | 309 ------------------------------------------- 1 file changed, 309 deletions(-) delete mode 100644 sim/paladin/runes.go diff --git a/sim/paladin/runes.go b/sim/paladin/runes.go deleted file mode 100644 index 0735ed04bb..0000000000 --- a/sim/paladin/runes.go +++ /dev/null @@ -1,309 +0,0 @@ -package paladin - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (paladin *Paladin) ApplyRunes() { - paladin.registerTheArtOfWar() - paladin.registerSheathOfLight() - paladin.registerGuardedByTheLight() - paladin.registerShockAndAwe() - paladin.registerRV() - paladin.registerFanaticism() - - // "RuneHeadWrath" is handled in Exorcism, Holy Shock, Consecration (and Holy Wrath once implemented) - paladin.registerMalleableProtection() - paladin.registerHammerOfTheRighteous() - // "RuneWristImprovedHammerOfWrath" is handled Hammer of Wrath - paladin.applyPurifyingPower() - paladin.registerAegis() - paladin.registerAvengersShield() -} - -func (paladin *Paladin) registerFanaticism() { - if paladin.hasRune(proto.PaladinRune_RuneHeadFanaticism) { - paladin.PseudoStats.SchoolBonusCritChance[stats.SchoolIndexHoly] += 18 - } -} - -func (paladin *Paladin) registerTheArtOfWar() { - if !paladin.hasRune(proto.PaladinRune_RuneFeetTheArtOfWar) { - return - } - - paladin.RegisterAura(core.Aura{ - Label: "The Art of War", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskMelee|core.ProcMaskMeleeDamageProc) || !result.Outcome.Matches(core.OutcomeCrit) { - return - } - //paladin.holyShockCooldown.Reset() - paladin.exorcismCooldown.Set(sim.CurrentTime + max(0, paladin.exorcismCooldown.TimeToReady(sim)-(time.Second*2))) - }, - }) -} - -func (paladin *Paladin) registerSheathOfLight() { - - if !paladin.hasRune(proto.PaladinRune_RuneWaistSheathOfLight) { - return - } - - dep := paladin.NewDynamicStatDependency( - stats.AttackPower, stats.SpellPower, 0.3, - ) - - sheathAura := paladin.RegisterAura(core.Aura{ - Label: "Sheath of Light", - Duration: time.Second * 60, - ActionID: core.ActionID{SpellID: 426159}, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - paladin.EnableDynamicStatDep(sim, dep) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - paladin.DisableDynamicStatDep(sim, dep) - }, - }) - paladin.RegisterAura(core.Aura{ - Label: "Sheath of Light (rune)", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskWhiteHit) { - return - } - sheathAura.Activate(sim) - }, - }) -} - -func (paladin *Paladin) registerShockAndAwe() { - if !paladin.hasRune(proto.PaladinRune_RuneCloakShockAndAwe) { - return - } - - dep := paladin.NewDynamicStatDependency(stats.Intellect, stats.SpellDamage, 2.0) - - shockAndAweAura := paladin.RegisterAura(core.Aura{ - Label: "Shock and Awe", - Duration: time.Second * 60, - ActionID: core.ActionID{SpellID: 462834}, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - paladin.EnableDynamicStatDep(sim, dep) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - paladin.DisableDynamicStatDep(sim, dep) - }, - }) - paladin.RegisterAura(core.Aura{ - Label: "Shock and Awe (rune)", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellCode != SpellCode_PaladinHolyShock { - return - } - shockAndAweAura.Activate(sim) - }, - }) -} - -func (paladin *Paladin) registerGuardedByTheLight() { - if !paladin.hasRune(proto.PaladinRune_RuneFeetGuardedByTheLight) { - return - } - - actionID := core.ActionID{SpellID: 415058} - manaMetrics := paladin.NewManaMetrics(actionID) - var manaPA *core.PendingAction - - guardedAura := paladin.RegisterAura(core.Aura{ - Label: "Guarded by the Light", - Duration: time.Second*15 + 1, - ActionID: actionID, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - manaPA = core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - Period: time.Second * 3, - OnAction: func(sim *core.Simulation) { - paladin.AddMana(sim, 0.05*paladin.MaxMana(), manaMetrics) - }, - }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - manaPA.Cancel(sim) - }, - }) - - paladin.RegisterAura(core.Aura{ - Label: "Guarded by the Light (rune)", - Duration: core.NeverExpires, - ActionID: core.ActionID{SpellID: 415755}, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskWhiteHit) { - return - } - guardedAura.Activate(sim) - }, - }) -} - -func (paladin *Paladin) applyPurifyingPower() { - if !paladin.hasRune(proto.PaladinRune_RuneWristPurifyingPower) { - return - } - - paladin.RegisterAura(core.Aura{ - Label: "Purifying Power", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range paladin.exorcism { - spell.CD.Duration /= 2 - } - - for _, spell := range paladin.holyWrath { - spell.CD.Duration /= 2 - } - }, - }) -} - -func (paladin *Paladin) registerAegis() { - - if !paladin.hasRune(proto.PaladinRune_RuneChestAegis) { - return - } - - // The SBV bonus is additive with Shield Specialization. - paladin.PseudoStats.BlockValueMultiplier += 0.3 - - // Redoubt now has a 10% chance to trigger on any melee or ranged attack against - // you, and always triggers on your melee critical strikes. - paladin.RegisterAura(core.Aura{ - Label: "Redoubt Aegis Trigger", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskMeleeOrRanged) && result.Landed() { - if sim.Proc(0.1, "Aegis Attack") { - paladin.redoubtAura.Activate(sim) - paladin.redoubtAura.SetStacks(sim, 5) - } - } - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskMelee) && result.DidCrit() { - paladin.redoubtAura.Activate(sim) - paladin.redoubtAura.SetStacks(sim, 5) - } - }, - }) - - // Reckoning now also procs on any melee or ranged attack against you with (2% * talent points) chance - procID := core.ActionID{SpellID: 20178} // reckoning proc id - procChance := 0.02 * float64(paladin.Talents.Reckoning) - - core.MakeProcTriggerAura(&paladin.Unit, core.ProcTrigger{ - Name: "Reckoning Aegis Trigger", - Callback: core.CallbackOnSpellHitTaken, - ProcMask: core.ProcMaskMeleeOrRanged, - Outcome: core.OutcomeLanded, - ProcChance: procChance, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - paladin.AutoAttacks.ExtraMHAttack(sim, 1, procID, spell.ActionID) - }, - }) -} - -func (paladin *Paladin) registerMalleableProtection() { - if !paladin.hasRune(proto.PaladinRune_RuneWaistMalleableProtection) { - return - } - // Activating Holy Shield now grants 4 AP for each point of defense above paladin.Level * 5 - defendersResolveAPAura := core.DefendersResolveAttackPower(paladin.GetCharacter()) - handler := func(spell *core.Spell) { - if spell.SpellCode != SpellCode_PaladinHolyShield { - return - } - oldEffects := spell.ApplyEffects - spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - oldEffects(sim, target, spell) - if stacks := int32(paladin.GetStat(stats.Defense)); stacks > 0 { - defendersResolveAPAura.Activate(sim) - if defendersResolveAPAura.GetStacks() != stacks { - defendersResolveAPAura.SetStacks(sim, stacks) - } - } - } - } - paladin.OnSpellRegistered(handler) - - // A prot paladin will only ever cast Divine Protection in conjunction with Malleable Protection, - // so we register only the modified form of the spell when the rune is engraved. - // Although there are two spell ranks, intentional downranking is never done in practice, - // so we only register the highest spell rank available. - if paladin.Level < 10 { - return - } - - isRank1 := paladin.Level < 18 - spellID := core.TernaryInt32(isRank1, 458312, 458371) - manaCost := core.TernaryFloat64(isRank1, 15, 35) - duration := core.TernaryDuration(isRank1, 9, 12) - - actionID := core.ActionID{SpellID: spellID} - - dpAura := paladin.RegisterAura(core.Aura{ - Label: "Divine Protection", - ActionID: actionID, - Duration: time.Second * duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - paladin.PseudoStats.DamageTakenMultiplier *= 0.5 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - paladin.PseudoStats.DamageTakenMultiplier /= 0.5 - }, - }) - - divine_protection := paladin.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagAPL | SpellFlag_Forbearance, - ManaCost: core.ManaCostOptions{ - FlatCost: manaCost, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Minute * 5, - }, - }, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - dpAura.Activate(sim) - }, - }) - - paladin.AddMajorCooldown(core.MajorCooldown{ - Spell: divine_protection, - Priority: core.CooldownPriorityDrums, // Primary defensive cooldown - Type: core.CooldownTypeSurvival, - }) -} From c63fa2eded3d3860d24917e757608254b6c340c7 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:28:12 -0500 Subject: [PATCH 06/83] Update paladin.go --- sim/paladin/paladin.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sim/paladin/paladin.go b/sim/paladin/paladin.go index d3ab5c2441..1a0287aff5 100644 --- a/sim/paladin/paladin.go +++ b/sim/paladin/paladin.go @@ -192,10 +192,6 @@ func NewPaladin(character *core.Character, options *proto.Player, paladinOptions return paladin } -func (paladin *Paladin) hasRune(rune proto.PaladinRune) bool { - return false // paladin.HasRuneById(int32(rune)) -} - func (paladin *Paladin) has2hEquipped() bool { return paladin.MainHand().HandType == proto.HandType_HandTypeTwoHand } @@ -206,7 +202,6 @@ func (paladin *Paladin) ResetPrimarySeal(primarySeal proto.PaladinSeal) { } func (paladin *Paladin) registerStopAttackMacros() { - if paladin.divineStorm != nil && paladin.Options.IsUsingDivineStormStopAttack { paladin.divineStorm.Flags |= core.SpellFlagBatchStopAttackMacro } @@ -289,7 +284,3 @@ func (paladin *Paladin) getLibramSealCostReduction() float64 { } return 0 } - -func (paladin *Paladin) baseRuneAbilityDamage() float64 { - return 9.046514 + 0.676562*float64(paladin.Level) + 0.019349*float64(paladin.Level*paladin.Level) -} From e7e016981d82f9aab72d8fc718f2875f72fab0f1 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:28:33 -0500 Subject: [PATCH 07/83] Delete sim/druid/runes.go --- sim/druid/runes.go | 317 --------------------------------------------- 1 file changed, 317 deletions(-) delete mode 100644 sim/druid/runes.go diff --git a/sim/druid/runes.go b/sim/druid/runes.go deleted file mode 100644 index 8a19cc882b..0000000000 --- a/sim/druid/runes.go +++ /dev/null @@ -1,317 +0,0 @@ -package druid - -import ( - "slices" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (druid *Druid) ApplyRunes() { - // Helm - druid.applyGaleWinds() - druid.applyGore() - - // Cloak - druid.registerStarfallCD() - druid.registerSwipeCatSpell() - - // Chest - druid.applyFuryOfStormRage() - druid.applyWildStrikes() - - // Bracers - druid.applyElunesFires() - - // Hands - druid.applyMangle() - druid.registerSunfireSpell() - - // Belt - druid.applyBerserk() - druid.applyEclipse() - - // Legs - druid.applyStarsurge() - druid.applySavageRoar() - - // Feet - druid.applyDreamstate() - druid.applyKingOfTheJungle() -} - -func (druid *Druid) applyGaleWinds() { - if !druid.HasRune(proto.DruidRune_RuneHelmGaleWinds) { - return - } - - druid.RegisterAura(core.Aura{ - Label: "Gale Winds", - ActionID: core.ActionID{SpellID: int32(proto.DruidRune_RuneHelmGaleWinds)}, - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - }) -} - -func (druid *Druid) applyGore() { - if !druid.HasRune(proto.DruidRune_RuneHelmGore) { - return - } - - druid.RegisterAura(core.Aura{ - Label: "Gore", - ActionID: core.ActionID{SpellID: int32(proto.DruidRune_RuneHelmGore)}, - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - }) -} - -const ( - Gore_BearResetProcChance = .15 - Gore_CatResetProcChance = .15 -) - -// TODO: Bear spells not implemented: MangleBear, Swipe, Maul -func (druid *Druid) rollGoreBearReset(sim *core.Simulation) { - if sim.RandomFloat("Gore (Bear)") < Gore_BearResetProcChance { - druid.MangleBear.CD.Reset() - } -} - -func (druid *Druid) rollGoreCatReset(sim *core.Simulation) { - if sim.RandomFloat("Gore (Cat)") < Gore_CatResetProcChance { - druid.TigersFury.CD.Reset() - } -} - -func (druid *Druid) applyFuryOfStormRage() { - if !druid.HasRune(proto.DruidRune_RuneChestFuryOfStormrage) { - return - } - - druid.FuryOfStormrageAura = druid.RegisterAura(core.Aura{ - Label: "Fury Of Stormrage", - ActionID: core.ActionID{SpellID: int32(proto.DruidRune_RuneChestFuryOfStormrage)}, - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - }) -} - -func (druid *Druid) applyEclipse() { - if !druid.HasRune(proto.DruidRune_RuneBeltEclipse) { - return - } - - solarCritBonus := 30.0 - lunarCastTimeReduction := time.Second * 1 - - var affectedSolarSpells []*DruidSpell - var affectedLunarSpells []*DruidSpell - - // Solar - druid.SolarEclipseProcAura = druid.RegisterAura(core.Aura{ - Label: "Solar Eclipse proc", - Duration: time.Second * 15, - MaxStacks: 4, - ActionID: core.ActionID{SpellID: 408250}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSolarSpells = core.FilterSlice( - core.Flatten([][]*DruidSpell{druid.Wrath, {druid.Starsurge}}), - func(spell *DruidSpell) bool { return spell != nil }, - ) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedSolarSpells, func(spell *DruidSpell) { - spell.BonusCritRating += solarCritBonus - }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedSolarSpells, func(spell *DruidSpell) { - spell.BonusCritRating -= solarCritBonus - }) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode != SpellCode_DruidWrath && spell.SpellCode != SpellCode_DruidStarsurge { - return - } - - aura.RemoveStack(sim) - }, - }) - - // Lunar - druid.LunarEclipseProcAura = druid.RegisterAura(core.Aura{ - Label: "Lunar Eclipse proc", - Duration: time.Second * 15, - MaxStacks: 4, - ActionID: core.ActionID{SpellID: 408255}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedLunarSpells = core.FilterSlice( - core.Flatten([][]*DruidSpell{druid.Starfire}), - func(spell *DruidSpell) bool { return spell != nil }, - ) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedLunarSpells, func(spell *DruidSpell) { - spell.DefaultCast.CastTime -= lunarCastTimeReduction - }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedLunarSpells, func(spell *DruidSpell) { - spell.DefaultCast.CastTime += lunarCastTimeReduction - }) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode != SpellCode_DruidStarfire { - return - } - - aura.RemoveStack(sim) - }, - }) - - druid.EclipseAura = druid.RegisterAura(core.Aura{ - Label: "Eclipse", - Duration: core.NeverExpires, - ActionID: core.ActionID{SpellID: 408248}, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !slices.Contains([]int32{SpellCode_DruidWrath, SpellCode_DruidStarfire, SpellCode_DruidStarsurge}, spell.SpellCode) || !result.Landed() { - return - } - - if spell.SpellCode == SpellCode_DruidWrath || spell.SpellCode == SpellCode_DruidStarsurge { - druid.LunarEclipseProcAura.Activate(sim) - // Solar gives 1 stack of lunar bonus - druid.LunarEclipseProcAura.AddStack(sim) - } - - if spell.SpellCode == SpellCode_DruidStarfire || spell.SpellCode == SpellCode_DruidStarsurge { - druid.SolarEclipseProcAura.Activate(sim) - // Lunar gives 2 staacks of solar bonus - druid.SolarEclipseProcAura.AddStacks(sim, 2) - } - }, - }) - -} - -func (druid *Druid) applyElunesFires() { - if !druid.HasRune(proto.DruidRune_RuneBracersElunesFires) { - return - } - - druid.RegisterAura(core.Aura{ - Label: "Elune's Fires", - ActionID: core.ActionID{SpellID: int32(proto.DruidRune_RuneBracersElunesFires)}, - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(_ *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !result.Landed() { - return - } - - switch spell.SpellCode { - case SpellCode_DruidWrath: - druid.tryElunesFiresSunfireExtension(sim, result.Target) - case SpellCode_DruidStarfire: - druid.tryElunesFiresMoonfireExtension(sim, result.Target) - case SpellCode_DruidStarsurge: // Starsurge now benefits from the effects of Wrath and Starfire - druid.tryElunesFiresSunfireExtension(sim, result.Target) - druid.tryElunesFiresMoonfireExtension(sim, result.Target) - case SpellCode_DruidShred: - druid.tryElunesFiresRipExtension(sim, result.Target) - } - }, - }) -} - -const ( - ElunesFires_BonusMoonfireTime = time.Second * 6 - ElunesFires_BonusSunfireTime = time.Second * 3 - ElunesFires_BonusRipTime = time.Second * 1 -) - -func (druid *Druid) tryElunesFiresMoonfireExtension(sim *core.Simulation, unit *core.Unit) { - for _, spell := range druid.Moonfire { - if dot := spell.Dot(unit); dot.IsActive() { - maxExpiresAt := sim.CurrentTime + dot.Duration - dot.UpdateExpires(sim, min(maxExpiresAt, dot.ExpiresAt()+ElunesFires_BonusMoonfireTime)) - } - } -} - -func (druid *Druid) tryElunesFiresSunfireExtension(sim *core.Simulation, unit *core.Unit) { - if druid.Sunfire == nil { - return - } - if dot := druid.Sunfire.Dot(unit); dot.IsActive() { - maxExpiresAt := sim.CurrentTime + dot.Duration - dot.UpdateExpires(sim, min(maxExpiresAt, dot.ExpiresAt()+ElunesFires_BonusSunfireTime)) - } -} - -func (druid *Druid) tryElunesFiresRipExtension(sim *core.Simulation, unit *core.Unit) { - if dot := druid.Rip.Dot(unit); dot.IsActive() { - maxExpiresAt := sim.CurrentTime + dot.Duration - dot.UpdateExpires(sim, min(maxExpiresAt, dot.ExpiresAt()+ElunesFires_BonusRipTime)) - } -} - -func (druid *Druid) applyMangle() { - //druid.registerMangleBearSpell() - druid.registerMangleCatSpell() -} - -func (druid *Druid) applyWildStrikes() { - if !druid.HasRune(proto.DruidRune_RuneChestWildStrikes) { - return - } - - //druid.WildStrikesBuffAura = core.ApplyWildStrikes(druid.GetCharacter()) -} - -func (druid *Druid) applyKingOfTheJungle() { - if druid.HasRune(proto.DruidRune_RuneFeetKingOfTheJungle) { - druid.registerTigersFurySpellKotJ() - } -} - -func (druid *Druid) applyDreamstate() { - if !druid.HasRune(proto.DruidRune_RuneFeetDreamstate) { - return - } - - - druid.DreamstateManaRegenAura = druid.RegisterAura(core.Aura{ - Label: "Dreamstate Mana Regen", - ActionID: core.ActionID{SpellID: int32(proto.DruidRune_RuneFeetDreamstate)}, - Duration: time.Second * 8, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - druid.PseudoStats.SpiritRegenRateCasting += .5 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - druid.PseudoStats.SpiritRegenRateCasting -= .5 - }, - }) - - core.MakePermanent(druid.RegisterAura(core.Aura{ - Label: "Dreamstate Trigger", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskSpellDamage) && result.DidCrit() || spell.SpellCode == SpellCode_DruidStarsurge { - druid.DreamstateManaRegenAura.Activate(sim) - } - }, - })) -} From d6abbb014c39979d5a94a2ba7d8c1eeec9140557 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:28:50 -0500 Subject: [PATCH 08/83] Update druid.go --- sim/druid/druid.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sim/druid/druid.go b/sim/druid/druid.go index f1f3714153..868a510873 100644 --- a/sim/druid/druid.go +++ b/sim/druid/druid.go @@ -301,14 +301,6 @@ func (ds *DruidSpell) IsEqual(s *core.Spell) bool { return ds.Spell == s } -func (druid *Druid) HasRune(rune proto.DruidRune) bool { - return false // druid.HasRuneById(int32(rune)) -} - -func (druid *Druid) baseRuneAbilityDamage() float64 { - return 9.183105 + 0.616405*float64(druid.Level) + 0.028608*float64(druid.Level*druid.Level) -} - // Agent is a generic way to access underlying druid on any of the agents (for example balance druid.) type DruidAgent interface { GetDruid() *Druid From fa6c335c4ad28bc7ab34bafd42207f9d8c2305f2 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:29:04 -0500 Subject: [PATCH 09/83] Delete sim/hunter/runes.go --- sim/hunter/runes.go | 406 -------------------------------------------- 1 file changed, 406 deletions(-) delete mode 100644 sim/hunter/runes.go diff --git a/sim/hunter/runes.go b/sim/hunter/runes.go deleted file mode 100644 index 2bb0d184af..0000000000 --- a/sim/hunter/runes.go +++ /dev/null @@ -1,406 +0,0 @@ -package hunter - -import ( - "math" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (hunter *Hunter) ApplyRunes() { - if hunter.HasRune(proto.HunterRune_RuneChestLoneWolf) && hunter.pet == nil { - hunter.PseudoStats.DamageDealtMultiplier *= 1.30 - } - - if hunter.HasRune(proto.HunterRune_RuneChestBeastmastery) && hunter.pet != nil { - // https://www.wowhead.com/classic/news/class-tuning-incoming-hunter-shaman-warlock-season-of-discovery-339072?webhook - hunter.pet.PseudoStats.DamageDealtMultiplier *= 1.1 - core.MakePermanent(hunter.RegisterAura(core.Aura{ - Label: "Beastmastery Rune Focus", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - if hunter.pet != nil { - hunter.pet.AddFocusRegenMultiplier(0.50) - } - }, - })) - } - - if hunter.HasRune(proto.HunterRune_RuneBootsDualWieldSpecialization) { - hunter.AutoAttacks.OHConfig().DamageMultiplier *= 1.5 - } - - if hunter.HasRune(proto.HunterRune_RuneHelmCatlikeReflexes) { - hunter.AddStat(stats.Dodge, 20*core.DodgeRatingPerDodgeChance) - if hunter.pet != nil { - hunter.pet.AddStat(stats.Dodge, 9*core.DodgeRatingPerDodgeChance) - } - } - - hunter.applySniperTraining() - hunter.applyCobraStrikes() - hunter.applyExposeWeakness() - // hunter.applyInvigoration() - hunter.applyLockAndLoad() - hunter.applyRaptorFury() - hunter.applyCobraSlayer() - hunter.applyHitAndRun() - hunter.applyMasterMarksman() - hunter.applyImprovedVolley() - hunter.applyTNT() - hunter.applyResourcefulness() -} - -// TODO: 2024-06-13 - Rune seemingly replaced with Wyvern Strike -// func (hunter *Hunter) applyInvigoration() { -// if !hunter.HasRune(proto.HunterRune_RuneBootsInvigoration) || hunter.pet == nil { -// return -// } - -// procSpellId := core.ActionID{SpellID: 437999} -// metrics := hunter.NewManaMetrics(procSpellId) -// procSpell := hunter.RegisterSpell(core.SpellConfig{ -// ActionID: procSpellId, -// SpellSchool: core.SpellSchoolNature, -// ApplyEffects: func(sim *core.Simulation, u *core.Unit, spell *core.Spell) { -// hunter.AddMana(sim, hunter.MaxMana()*0.05, metrics) -// }, -// }) - -// core.MakePermanent(hunter.pet.GetOrRegisterAura(core.Aura{ -// Label: "Invigoration", -// OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { -// if !spell.ProcMask.Matches(core.ProcMaskMeleeSpecial) { -// return -// } - -// if !result.DidCrit() { -// return -// } - -// procSpell.Cast(sim, result.Target) -// }, -// })) -// } - -func (hunter *Hunter) applyMasterMarksman() { - if hunter.HasRune(proto.HunterRune_RuneChestMasterMarksman) { - hunter.AddStat(stats.MeleeCrit, 5*core.CritRatingPerCritChance) - hunter.AddStat(stats.SpellCrit, 5*core.SpellCritRatingPerCritChance) - - hunter.OnSpellRegistered(func(spell *core.Spell) { - if spell.Flags.Matches(SpellFlagShot) { - spell.Cost.Multiplier -= 25 - } - }) - } -} - -func (hunter *Hunter) applyExposeWeakness() { - if !hunter.HasRune(proto.HunterRune_RuneBeltExposeWeakness) { - return - } - - apBonus := hunter.NewDynamicStatDependency(stats.Agility, stats.AttackPower, 0.4) - apRangedBonus := hunter.NewDynamicStatDependency(stats.Agility, stats.RangedAttackPower, 0.4) - - procAura := hunter.GetOrRegisterAura(core.Aura{ - Label: "Expose Weakness Proc", - ActionID: core.ActionID{SpellID: 409507}, - Duration: time.Second * 7, - - OnGain: func(aura *core.Aura, sim *core.Simulation) { - hunter.EnableDynamicStatDep(sim, apBonus) - hunter.EnableDynamicStatDep(sim, apRangedBonus) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - hunter.DisableDynamicStatDep(sim, apBonus) - hunter.DisableDynamicStatDep(sim, apRangedBonus) - }, - }) - - core.MakePermanent(hunter.GetOrRegisterAura(core.Aura{ - Label: "Expose Weakness", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskMeleeOrRanged) { - return - } - - if !result.DidCrit() { - return - } - - procAura.Activate(sim) - }, - })) -} - -func (hunter *Hunter) applySniperTraining() { - if !hunter.HasRune(proto.HunterRune_RuneLegsSniperTraining) { - return - } - - hunter.SniperTrainingAura = hunter.GetOrRegisterAura(core.Aura{ - Label: "Sniper Training", - ActionID: core.ActionID{SpellID: 415399}, - Duration: time.Second * 6, - MaxStacks: 5, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - statDelta := float64(newStacks - oldStacks) - for _, spell := range aura.Unit.Spellbook { - if spell.ProcMask.Matches(core.ProcMaskRangedSpecial) || spell.SpellCode == SpellCode_HunterChimeraSerpent { - spell.BonusCritRating += statDelta * 2 * core.CritRatingPerCritChance - } - - } - }, - }) - - aura := hunter.SniperTrainingAura - uptime := hunter.Options.SniperTrainingUptime - chancePerTick := core.TernaryFloat64(uptime == 1, 1, 1.0-math.Pow(1-uptime, 1)) - - lastMoved := false - aura.Unit.RegisterResetEffect(func(sim *core.Simulation) { - core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - Period: time.Second, - OnAction: func(sim *core.Simulation) { - if sim.Proc(chancePerTick, "FixedAura") { - // Gain stack every second after 2 seconds - if !lastMoved { - aura.Activate(sim) - aura.AddStack(sim) - } else { - lastMoved = false - } - } else { - // Lose stack every second moving - if aura.IsActive() { - aura.RemoveStack(sim) - } - lastMoved = true - } - }, - }) - - core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - Period: 0, - NumTicks: 1, - OnAction: func(sim *core.Simulation) { - if sim.Proc(chancePerTick, "FixedAura") { - aura.Activate(sim) - aura.SetStacks(sim, 5) - } else { - lastMoved = true - } - }, - }) - }) -} - -func (hunter *Hunter) applyCobraStrikes() { - if !hunter.HasRune(proto.HunterRune_RuneChestCobraStrikes) || hunter.pet == nil { - return - } - - hunter.CobraStrikesAura = hunter.pet.GetOrRegisterAura(core.Aura{ - Label: "Cobra Strikes", - ActionID: core.ActionID{SpellID: 425714}, - Duration: time.Second * 30, - MaxStacks: 2, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range aura.Unit.Spellbook { - if spell.ProcMask.Matches(core.ProcMaskMeleeSpecial | core.ProcMaskSpellDamage) { - spell.BonusCritRating += 100 * core.CritRatingPerCritChance - } - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range aura.Unit.Spellbook { - if spell.ProcMask.Matches(core.ProcMaskMeleeSpecial | core.ProcMaskSpellDamage) { - spell.BonusCritRating -= 100 * core.CritRatingPerCritChance - } - } - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskMeleeSpecial | core.ProcMaskSpellDamage) { - aura.RemoveStack(sim) - } - }, - }) - - core.MakePermanent(hunter.RegisterAura(core.Aura{ - Label: "Cobra Strikes Trigger", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.DidCrit() && (spell.Flags.Matches(SpellFlagShot|SpellFlagStrike) || spell.SpellCode == SpellCode_HunterMongooseBite) { - hunter.CobraStrikesAura.Activate(sim) - hunter.CobraStrikesAura.SetStacks(sim, 2) - } - }, - })) -} - -func (hunter *Hunter) applyLockAndLoad() { - if !hunter.HasRune(proto.HunterRune_RuneHelmLockAndLoad) { - return - } - - lockAndLoadMetrics := hunter.Metrics.NewResourceMetrics(core.ActionID{SpellID: 415413}, proto.ResourceType_ResourceTypeMana) - - hunter.LockAndLoadAura = hunter.GetOrRegisterAura(core.Aura{ - Label: "Lock And Load", - ActionID: core.ActionID{SpellID: 415413}, - Duration: time.Second * 20, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.Flags.Matches(SpellFlagShot) { - aura.Deactivate(sim) - hunter.AddMana(sim, spell.CurCast.Cost, lockAndLoadMetrics) - - if spell.CD.Timer != nil { - spell.CD.Reset() - } - } - }, - }) - - core.MakePermanent(hunter.RegisterAura(core.Aura{ - Label: "Lock And Load Trigger", - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.Flags.Matches(SpellFlagTrap) { - hunter.LockAndLoadAura.Activate(sim) - } - }, - })) -} - -const RaptorFuryPerStackDamageMultiplier = 0.15 - -func (hunter *Hunter) raptorFuryDamageMultiplier() float64 { - stacks := hunter.RaptorFuryAura.GetStacks() - if stacks == 0 { - return 1 - } - - return 1 + RaptorFuryPerStackDamageMultiplier*float64(stacks) -} - -func (hunter *Hunter) applyRaptorFury() { - if !hunter.HasRune(proto.HunterRune_RuneBracersRaptorFury) { - return - } - - hunter.RaptorFuryAura = hunter.GetOrRegisterAura(core.Aura{ - Label: "Raptor Fury Buff", - ActionID: core.ActionID{SpellID: int32(proto.HunterRune_RuneBracersRaptorFury)}, - Duration: time.Second * 30, - MaxStacks: 5, - }) -} - -func (hunter *Hunter) applyCobraSlayer() { - if !hunter.HasRune(proto.HunterRune_RuneHandsCobraSlayer) { - return - } - - hunter.RegisterAura(core.Aura{ - Label: "Cobra Slayer", - Duration: core.NeverExpires, - MaxStacks: 20, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskMelee) { - return - } - - if result.DidDodge() { - aura.SetStacks(sim, 1) - hunter.DefensiveState.Activate(sim) - return - } - - if spell.ProcMask.Matches(core.ProcMaskMeleeWhiteHit) && result.Outcome.Matches(core.OutcomeLanded) && sim.Proc((float64(aura.GetStacks())*0.10), "Cobra Slayer") { - aura.SetStacks(sim, 1) - hunter.DefensiveState.Activate(sim) - return - } - - aura.AddStack(sim) - }, - }) -} - -func (hunter *Hunter) applyTNT() { - if !hunter.HasRune(proto.HunterRune_RuneBracersTNT) { - return - } - - hunter.OnSpellRegistered(func(spell *core.Spell) { - if spell.Flags.Matches(SpellFlagTrap) || spell.SpellCode == SpellCode_HunterExplosiveShot { - spell.DamageMultiplier *= 1.10 - } - }) -} - -func (hunter *Hunter) tntDamageFlatBonus() float64 { - if hunter.HasRune(proto.HunterRune_RuneBracersTNT) { - return math.Max(hunter.GetStat(stats.AttackPower), hunter.GetStat(stats.RangedAttackPower)) * 0.25 - } - return 0.0 -} - -func (hunter *Hunter) trapRange() float64 { - if hunter.HasRune(proto.HunterRune_RuneBootsTrapLauncher) { - return 35 - } - return 5 -} - -func (hunter *Hunter) applyResourcefulness() { - if !hunter.HasRune(proto.HunterRune_RuneCloakResourcefulness) { - return - } - - hunter.OnSpellRegistered(func(spell *core.Spell) { - if spell.Flags.Matches(SpellFlagTrap) { - spell.Cost.BaseCost = 0 - spell.CD.Duration = spell.CD.Duration / 100 * 60 - } - }) -} - -func (hunter *Hunter) applyHitAndRun() { - if hunter.HasRune(proto.HunterRune_RuneCloakHitAndRun) { - hunter.HitAndRunAura = hunter.RegisterAura(core.Aura{ - Label: "Hit And Run", - ActionID: core.ActionID{SpellID: 440533}, - Duration: time.Second * 15, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - hunter.Unit.AddMoveSpeedModifier(&aura.ActionID, 1.30) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - hunter.Unit.RemoveMoveSpeedModifier(&aura.ActionID) - }, - }) - } -} - -func (hunter *Hunter) applyImprovedVolley() { - if !hunter.HasRune(proto.HunterRune_RuneCloakImprovedVolley) && hunter.Volley != nil { - return - } - - hunter.RegisterAura(core.Aura{ - Label: "Improved Volley", - ActionID: core.ActionID{SpellID: 440520}, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - // The 3% rAP scaling and manacost reduction is applied inside the volley spell config itself - hunter.Volley.DamageMultiplier *= 2 - }, - }) -} From 577c1e3a14890e700d16488c02385300bfce4638 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:29:42 -0500 Subject: [PATCH 10/83] Update shaman.go --- sim/shaman/shaman.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sim/shaman/shaman.go b/sim/shaman/shaman.go index a6a3b0b47e..04a9253369 100644 --- a/sim/shaman/shaman.go +++ b/sim/shaman/shaman.go @@ -40,10 +40,6 @@ func NewShaman(character *core.Character, talents string) *Shaman { shaman.ApplyFrostbrandImbue(shaman.getImbueProcMask(proto.WeaponImbue_FrostbrandWeapon)) shaman.ApplyWindfuryImbue(shaman.getImbueProcMask(proto.WeaponImbue_WindfuryWeapon)) - if shaman.HasRune(proto.ShamanRune_RuneCloakFeralSpirit) { - shaman.SpiritWolves = shaman.NewSpiritWolves() - } - guardians.ConstructGuardians(&shaman.Character) return shaman @@ -238,14 +234,6 @@ func (shaman *Shaman) RegisterHealingSpells() { shaman.registerChainHealSpell() } -func (shaman *Shaman) HasRune(rune proto.ShamanRune) bool { - return false // shaman.HasRuneById(int32(rune)) -} - -func (shaman *Shaman) baseRuneAbilityDamage() float64 { - return 7.583798 + 0.471881*float64(shaman.Level) + 0.036599*float64(shaman.Level*shaman.Level) -} - func (shaman *Shaman) Reset(_ *core.Simulation) { shaman.ActiveShield = nil shaman.ActiveShieldAura = nil From a7c80e2f6308cb9164d12ad83562f44b856f97c6 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:29:52 -0500 Subject: [PATCH 11/83] Delete sim/shaman/runes.go --- sim/shaman/runes.go | 478 -------------------------------------------- 1 file changed, 478 deletions(-) delete mode 100644 sim/shaman/runes.go diff --git a/sim/shaman/runes.go b/sim/shaman/runes.go deleted file mode 100644 index ac8d7f28f8..0000000000 --- a/sim/shaman/runes.go +++ /dev/null @@ -1,478 +0,0 @@ -package shaman - -import ( - "slices" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (shaman *Shaman) ApplyRunes() { - // Helm - shaman.applyBurn() - shaman.applyMentalDexterity() - - // Cloak - shaman.registerFeralSpiritCD() - - // Chest - shaman.applyDualWieldSpec() - shaman.applyShieldMastery() - shaman.applyTwoHandedMastery() - - // Bracers - shaman.applyStaticShocks() - shaman.registerRollingThunder() - shaman.registerRiptideSpell() - - // Hands - shaman.registerWaterShieldSpell() - shaman.registerLavaBurstSpell() - shaman.applyLavaLash() - shaman.applyMoltenBlast() - - // Waist - shaman.applyFireNova() - shaman.applyMaelstromWeapon() - shaman.applyPowerSurge() - - // Legs - shaman.applyAncestralGuidance() - shaman.applyWayOfEarth() - - // Feet - shaman.applyAncestralAwakening() - shaman.applySpiritOfTheAlpha() -} - -var BurnFlameShockTargetCount = int32(5) -var BurnFlameShockDamageBonus = 1.0 -var BurnFlameShockBonusTicks = int32(2) -var BurnSpellPowerPerLevel = int32(2) - -func (shaman *Shaman) applyBurn() { - if !shaman.HasRune(proto.ShamanRune_RuneHelmBurn) { - return - } - - if shaman.Consumes.MainHandImbue == proto.WeaponImbue_FlametongueWeapon { - shaman.AddStatDependency(stats.Intellect, stats.SpellDamage, 1.50) - } - - shaman.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanFlameShock { - spell.DamageMultiplierAdditive += BurnFlameShockDamageBonus - } - }) - - // Other parts of burn are handled in flame_shock.go -} - -func (shaman *Shaman) applyMentalDexterity() { - if !shaman.HasRune(proto.ShamanRune_RuneHelmMentalDexterity) { - return - } - - intToApStatDep := shaman.NewDynamicStatDependency(stats.Intellect, stats.AttackPower, 1.0) - apToSpStatDep := shaman.NewDynamicStatDependency(stats.AttackPower, stats.SpellDamage, .35) - - procAura := shaman.RegisterAura(core.Aura{ - Label: "Mental Dexterity Proc", - ActionID: core.ActionID{SpellID: int32(proto.ShamanRune_RuneHelmMentalDexterity)}, - Duration: time.Second * 30, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.EnableDynamicStatDep(sim, intToApStatDep) - aura.Unit.EnableDynamicStatDep(sim, apToSpStatDep) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.DisableDynamicStatDep(sim, intToApStatDep) - aura.Unit.DisableDynamicStatDep(sim, apToSpStatDep) - }, - }) - - // Hidden Aura - shaman.RegisterAura(core.Aura{ - Label: "Mental Dexterity", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Landed() && spell == shaman.StormstrikeMH { - procAura.Activate(sim) - } - }, - }) -} - -func (shaman *Shaman) applyDualWieldSpec() { - if !shaman.HasRune(proto.ShamanRune_RuneChestDualWieldSpec) || !shaman.HasMHWeapon() || !shaman.HasOHWeapon() { - return - } - - shaman.AutoAttacks.OHConfig().DamageMultiplier *= 1.5 - - meleeHit := float64(core.MeleeHitRatingPerHitChance * 5) - spellHit := float64(core.SpellHitRatingPerHitChance * 5) - - shaman.AddStat(stats.MeleeHit, meleeHit) - shaman.AddStat(stats.SpellHit, spellHit) - - dwBonusApplied := true - - shaman.RegisterAura(core.Aura{ - Label: "DW Spec Trigger", - ActionID: core.ActionID{SpellID: int32(proto.ShamanRune_RuneChestDualWieldSpec)}, - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - // Perform additional checks for later weapon-swapping - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !result.Landed() || !spell.ProcMask.Matches(core.ProcMaskMeleeMH) { - return - } - - if shaman.HasMHWeapon() && shaman.HasOHWeapon() { - if dwBonusApplied { - return - } else { - shaman.AddStat(stats.MeleeHit, meleeHit) - shaman.AddStat(stats.SpellHit, spellHit) - } - } else { - shaman.AddStat(stats.MeleeHit, -1*meleeHit) - shaman.AddStat(stats.SpellHit, -1*spellHit) - dwBonusApplied = false - } - }, - }) -} - -func (shaman *Shaman) applyShieldMastery() { - if !shaman.HasRune(proto.ShamanRune_RuneChestShieldMastery) { - return - } - - defendersResolveAura := core.DefendersResolveSpellDamage(shaman.GetCharacter()) - - shaman.AddStat(stats.Block, 10) - shaman.PseudoStats.BlockValueMultiplier = 1.15 - - actionId := core.ActionID{SpellID: int32(proto.ShamanRune_RuneChestShieldMastery)} - manaMetrics := shaman.NewManaMetrics(actionId) - procManaReturn := 0.08 - armorPerStack := shaman.Equipment.OffHand().Stats[stats.Armor] * 0.3 - - blockProcAura := shaman.RegisterAura(core.Aura{ - Label: "Shield Mastery Block", - ActionID: core.ActionID{SpellID: 408525}, - Duration: time.Second * 15, - MaxStacks: 5, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - shaman.AddStatDynamic(sim, stats.Armor, armorPerStack*float64(newStacks-oldStacks)) - }, - }) - - affectedSpellcodes := []int32{SpellCode_ShamanEarthShock, SpellCode_ShamanFlameShock, SpellCode_ShamanFrostShock} - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Shield Mastery Trigger", - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.DidBlock() { - shaman.AddMana(sim, shaman.MaxMana()*procManaReturn, manaMetrics) - blockProcAura.Activate(sim) - blockProcAura.AddStack(sim) - } - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Landed() && slices.Contains(affectedSpellcodes, spell.SpellCode) { - if stacks := int32(shaman.GetStat(stats.Defense)); stacks > 0 { - //Aura.Activate takes care of refreshing if the aura is already active - defendersResolveAura.Activate(sim) - if defendersResolveAura.GetStacks() != stacks { - defendersResolveAura.SetStacks(sim, stacks) - } - } - } - }, - })) -} - -func (shaman *Shaman) applyTwoHandedMastery() { - if !shaman.HasRune(proto.ShamanRune_RuneChestTwoHandedMastery) { - return - } - - procSpellId := int32(436365) - - // Two-handed mastery gives +15% AP, +30% attack speed, and +10% spell hit - attackSpeedMultiplier := 1.5 - apMultiplier := 1.15 - spellHitIncrease := core.SpellHitRatingPerHitChance * 10.0 - - statDep := shaman.NewDynamicMultiplyStat(stats.AttackPower, apMultiplier) - procAura := shaman.RegisterAura(core.Aura{ - Label: "Two-Handed Mastery Proc", - ActionID: core.ActionID{SpellID: procSpellId}, - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.MultiplyMeleeSpeed(sim, attackSpeedMultiplier) - shaman.AddStatDynamic(sim, stats.SpellHit, spellHitIncrease) - aura.Unit.EnableDynamicStatDep(sim, statDep) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.MultiplyAttackSpeed(sim, 1/attackSpeedMultiplier) - shaman.AddStatDynamic(sim, stats.SpellHit, -1*spellHitIncrease) - aura.Unit.DisableDynamicStatDep(sim, statDep) - }, - }) - - shaman.RegisterAura(core.Aura{ - Label: "Two-Handed Mastery Trigger", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !result.Landed() || !spell.ProcMask.Matches(core.ProcMaskMeleeMH) { - return - } - - if shaman.MainHand().HandType == proto.HandType_HandTypeTwoHand { - procAura.Activate(sim) - } else { - procAura.Deactivate(sim) - } - }, - }) -} - -func (shaman *Shaman) applyStaticShocks() { - if !shaman.HasRune(proto.ShamanRune_RuneBracersStaticShock) { - return - } - - // DW chance base doubled by using a 2-handed weapon - shaman.staticSHocksProcChance = .06 - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Static Shocks", - OnInit: func(staticShockAura *core.Aura, sim *core.Simulation) { - for _, aura := range shaman.LightningShieldAuras { - if aura == nil { - continue - } - - oldOnGain := aura.OnGain - aura.OnGain = func(aura *core.Aura, sim *core.Simulation) { - oldOnGain(aura, sim) - staticShockAura.Activate(sim) - } - - oldOnExpire := aura.OnExpire - aura.OnExpire = func(aura *core.Aura, sim *core.Simulation) { - oldOnExpire(aura, sim) - staticShockAura.Deactivate(sim) - } - } - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if shaman.ActiveShieldAura == nil || !spell.ProcMask.Matches(core.ProcMaskMelee) || !result.Landed() { - return - } - - staticShockProcChance := core.TernaryFloat64(shaman.MainHand().HandType == proto.HandType_HandTypeTwoHand, shaman.staticSHocksProcChance*2, shaman.staticSHocksProcChance) - if sim.RandomFloat("Static Shock") < staticShockProcChance { - shaman.LightningShieldProcs[shaman.ActiveShield.Rank].Cast(sim, result.Target) - } - }, - })) -} - -func (shaman *Shaman) applyMaelstromWeapon() { - if !shaman.HasRune(proto.ShamanRune_RuneWaistMaelstromWeapon) { - return - } - - // Chance increased by 50% while your main hand weapon is enchanted with Windfury Weapon and by another 50% if wielding a two-handed weapon. - // Base PPM is 10 - ppm := 10.0 - if shaman.GetCharacter().Consumes.MainHandImbue == proto.WeaponImbue_WindfuryWeapon { - ppm += 5 - } - if shaman.MainHand().HandType == proto.HandType_HandTypeTwoHand { - ppm += 5 - } - - var affectedSpells []*core.Spell - shaman.OnSpellRegistered(func(spell *core.Spell) { - if spell.Flags.Matches(SpellFlagMaelstrom) { - affectedSpells = append(affectedSpells, spell) - } - }) - - shaman.MaelstromWeaponAura = shaman.RegisterAura(core.Aura{ - Label: "MaelstromWeapon Proc", - ActionID: core.ActionID{SpellID: 408505}, - Duration: time.Second * 30, - MaxStacks: 5, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks int32, newStacks int32) { - multDiff := 20 * (newStacks - oldStacks) - for _, spell := range affectedSpells { - spell.CastTimeMultiplier -= float64(multDiff) / 100 - spell.Cost.Multiplier -= multDiff - } - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.Flags.Matches(SpellFlagMaelstrom) { - shaman.MaelstromWeaponAura.Deactivate(sim) - } - }, - }) - - ppmm := shaman.AutoAttacks.NewPPMManager(ppm, core.ProcMaskMelee) - shaman.maelstromWeaponPPMM = &ppmm - - // This aura is hidden, just applies stacks of the proc aura. - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Maelstrom Weapon Trigger", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Landed() && spell.ProcMask.Matches(core.ProcMaskMelee|core.ProcMaskMeleeDamageProc) && shaman.maelstromWeaponPPMM.Proc(sim, spell.ProcMask, "Maelstrom Weapon") { - shaman.MaelstromWeaponAura.Activate(sim) - shaman.MaelstromWeaponAura.AddStack(sim) - } - }, - })) -} - -func (shaman *Shaman) applyPowerSurge() { - shaman.powerSurgeProcChance = 0.05 - - // We want to create the power surge damage aura all the time because it's used by the T1 Ele 4P and can be triggered without the rune - var affectedDamageSpells []*core.Spell - shaman.PowerSurgeDamageAura = shaman.RegisterAura(core.Aura{ - Label: "Power Surge Proc (Damage)", - ActionID: core.ActionID{SpellID: 415105}, - Duration: time.Second * 10, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedDamageSpells = core.FilterSlice( - core.Flatten([][]*core.Spell{ - shaman.ChainLightning, - {shaman.LavaBurst}, - }), func(spell *core.Spell) bool { return spell != nil }) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedDamageSpells, func(spell *core.Spell) { - spell.CastTimeMultiplier -= 1 - if spell.CD.Timer != nil { - spell.CD.Reset() - } - }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedDamageSpells, func(spell *core.Spell) { spell.CastTimeMultiplier += 1 }) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanLavaBurst || spell.SpellCode == SpellCode_ShamanChainLightning { - aura.Deactivate(sim) - } - }, - }) - - if !shaman.HasRune(proto.ShamanRune_RuneWaistPowerSurge) { - return - } - - var affectedHealSpells []*core.Spell - shaman.PowerSurgeHealAura = shaman.RegisterAura(core.Aura{ - Label: "Power Surge Proc (Heal)", - ActionID: core.ActionID{SpellID: 468526}, - Duration: time.Second * 10, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedHealSpells = core.FilterSlice(shaman.ChainHeal, func(spell *core.Spell) bool { return spell != nil }) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedHealSpells, func(spell *core.Spell) { spell.CastTimeMultiplier -= 1 }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - core.Each(affectedHealSpells, func(spell *core.Spell) { spell.CastTimeMultiplier += 1 }) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode == SpellCode_ShamanChainHeal { - aura.Deactivate(sim) - } - }, - }) - - statDep := shaman.NewDynamicStatDependency(stats.Intellect, stats.MP5, .15) - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Power Surge", - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.EnableDynamicStatDep(sim, statDep) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.DisableDynamicStatDep(sim, statDep) - }, - })) -} - -func (shaman *Shaman) applyWayOfEarth() { - if !shaman.HasRune(proto.ShamanRune_RuneLegsWayOfEarth) { - return - } - - // Way of Earth only activates if you have Rockbiter Weapon on your mainhand and a shield in your offhand - if shaman.Consumes.MainHandImbue != proto.WeaponImbue_RockbiterWeapon || shaman.OffHand().WeaponType != proto.WeaponType_WeaponTypeShield { - return - } - - healthDep := shaman.NewDynamicMultiplyStat(stats.Health, 1.3) - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Way of Earth", - ActionID: core.ActionID{SpellID: int32(proto.ShamanRune_RuneLegsWayOfEarth)}, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.EnableDynamicStatDep(sim, healthDep) - shaman.PseudoStats.DamageTakenMultiplier *= .9 - shaman.PseudoStats.ReducedCritTakenChance += 6 - shaman.PseudoStats.ThreatMultiplier *= 1.65 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.DisableDynamicStatDep(sim, healthDep) - shaman.PseudoStats.DamageTakenMultiplier /= .9 - shaman.PseudoStats.ReducedCritTakenChance -= 6 - shaman.PseudoStats.ThreatMultiplier /= 1.65 - }, - })) -} - -// https://www.wowhead.com/classic/spell=408696/spirit-of-the-alpha -func (shaman *Shaman) applySpiritOfTheAlpha() { - if !shaman.HasRune(proto.ShamanRune_RuneFeetSpiritOfTheAlpha) { - return - } - - /* shaman.SpiritOfTheAlphaAura = core.SpiritOfTheAlphaAura(&shaman.Unit) - shaman.LoyalBetaAura = shaman.RegisterAura(core.Aura{ - Label: "Loyal Beta", - Duration: core.NeverExpires, - ActionID: core.ActionID{SpellID: 443320}, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - shaman.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] *= 1.05 - shaman.PseudoStats.ThreatMultiplier *= .70 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - shaman.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] /= 1.05 - shaman.PseudoStats.ThreatMultiplier /= .70 - }, - }) - - if !shaman.IsTanking() { - shaman.SpiritOfTheAlphaAura.OnReset = func(aura *core.Aura, sim *core.Simulation) {} - shaman.LoyalBetaAura.OnReset = func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - } - } */ -} From 75d251f4dad6808fb60999cb6c9b3b337f6b478f Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:30:38 -0500 Subject: [PATCH 12/83] Update hunter.go --- sim/hunter/hunter.go | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/sim/hunter/hunter.go b/sim/hunter/hunter.go index 2ff7625f3f..e204bc9aa6 100644 --- a/sim/hunter/hunter.go +++ b/sim/hunter/hunter.go @@ -217,21 +217,11 @@ func (hunter *Hunter) Initialize() { hunter.registerWingClipSpell() hunter.registerVolleySpell() - // Trap Launcher rune also splits the cooldowns between frost traps and fire traps, without the rune all traps share a cd - if hunter.HasRune(proto.HunterRune_RuneBootsTrapLauncher) { - fireTraps := hunter.NewTimer() - frostTraps := hunter.NewTimer() - - hunter.registerExplosiveTrapSpell(fireTraps) - hunter.registerImmolationTrapSpell(fireTraps) - hunter.registerFreezingTrapSpell(frostTraps) - } else { - traps := hunter.NewTimer() - - hunter.registerExplosiveTrapSpell(traps) - hunter.registerImmolationTrapSpell(traps) - hunter.registerFreezingTrapSpell(traps) - } + traps := hunter.NewTimer() + + hunter.registerExplosiveTrapSpell(traps) + hunter.registerImmolationTrapSpell(traps) + hunter.registerFreezingTrapSpell(traps) // hunter.registerKillCommand() hunter.registerRapidFire() @@ -354,14 +344,6 @@ func NewHunter(character *core.Character, options *proto.Player) *Hunter { return hunter } -func (hunter *Hunter) HasRune(rune proto.HunterRune) bool { - return false // hunter.HasRuneById(int32(rune)) -} - -func (hunter *Hunter) baseRuneAbilityDamage() float64 { - return 2.976264 + 0.641066*float64(hunter.Level) + 0.022519*float64(hunter.Level*hunter.Level) -} - func (hunter *Hunter) OnGCDReady(_ *core.Simulation) { } From 096573e2045d2470c1498f93985ba5990fb97443 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:31:06 -0500 Subject: [PATCH 13/83] Update shaman.proto --- proto/shaman.proto | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/proto/shaman.proto b/proto/shaman.proto index 1f5c69bea5..5e96659ea2 100644 --- a/proto/shaman.proto +++ b/proto/shaman.proto @@ -57,47 +57,6 @@ message ShamanTalents { bool mana_tide_totem = 46; } -enum ShamanRune { - RuneNone = 0; - - RuneHelmBurn = 415231; - RuneHelmMentalDexterity = 415140; - RuneHelmTidalWaves = 432042; - - RuneCloakCoherence = 415096; - RuneCloakStormEarthAndFire = 440569; - RuneCloakFeralSpirit = 440580; - - RuneChestDualWieldSpec = 408496; - RuneChestHealingRain = 415236; - RuneChestOverload = 408438; - RuneChestShieldMastery = 408524; - RuneChestTwoHandedMastery = 436364; - - RuneBracersOvercharged = 432140; - RuneBracersRiptide = 408521; - RuneBracersRollingThunder = 432056; - RuneBracersStaticShock = 432134; - - RuneHandsLavaBurst = 408490; - RuneHandsLavaLash = 408507; - RuneHandsMoltenBlast = 425339; - RuneHandsWaterShield = 408510; - - RuneWaistFireNova = 408339; - RuneWaistMaelstromWeapon = 408498; - RuneWaistPowerSurge = 415100; - - RuneLegsAncestralGuidance = 409324; - RuneLegsEarthShield = 408514; - RuneLegsWayOfEarth = 408531; - RuneLegsGreaterGhostWolf = 415813; - - RuneFeetAncestralAwakening = 425858; - RuneFeetDecoyTotem = 425874; - RuneFeetSpiritOfTheAlpha = 408696; -} - enum EarthTotem { NoEarthTotem = 0; StrengthOfEarthTotem = 1; From 439baf3ba205ec73fc401d3f366f90359e8fe84d Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:31:19 -0500 Subject: [PATCH 14/83] Update paladin.proto --- proto/paladin.proto | 45 --------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/proto/paladin.proto b/proto/paladin.proto index 1017a91d63..1325ab8b89 100644 --- a/proto/paladin.proto +++ b/proto/paladin.proto @@ -55,51 +55,6 @@ message PaladinTalents { bool repentance = 44; } -enum PaladinRune { - PaladinRuneNone = 0; - - RuneHeadFanaticism = 429142; - RuneHeadImprovedSanctuary = 429133; - RuneHeadWrath = 429139; - - RuneCloakShieldOfRighteousness = 440658; - RuneCloakVindicator = 440666; - RuneCloakShockAndAwe = 462834; - RuneCloakRighteousVengeance = 440672; - - RuneChestDivineStorm = 407778; - RuneChestAegis = 425589; - RuneChestHallowedGround = 458287; - RuneChestDivineLight = 458856; - - RuneWristHammerOfTheRighteous = 407632; - RuneWristLightsGrace = 428909; - RuneWristPurifyingPower = 429144; - RuneWristImprovedHammerOfWrath = 429152; - - RuneHandsBeaconOfLight = 407613; - RuneHandsHandOfReckoning = 407631; - RuneHandsCrusaderStrike = 407676; - - RuneWaistInfusionOfLight = 426065; - RuneWaistSheathOfLight = 426158; - RuneWaistMalleableProtection = 458318; - - RuneLegsAuraMastery = 407624; - RuneLegsAvengersShield = 407669; - RuneLegsDivineSacrifice = 407804; - RuneLegsInspirationExemplar = 407880; - RuneLegsRebuke = 425609; - - RuneFeetSacredShield = 412019; - RuneFeetGuardedByTheLight = 415059; - RuneFeetTheArtOfWar = 426157; - - RuneUtilitySealOfMartyrdom = 407798; - RuneUtilityExorcist = 415076; - RuneUtilityAvengingWrath = 407788; -} - enum Blessings { BlessingUnknown = 0; BlessingOfKings = 1; From 92eae63aab0707cc1a1100ca2fe587c9bcfe1426 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:31:34 -0500 Subject: [PATCH 15/83] Update druid.proto --- proto/druid.proto | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/proto/druid.proto b/proto/druid.proto index 389b77169b..9f5f46e386 100644 --- a/proto/druid.proto +++ b/proto/druid.proto @@ -60,45 +60,6 @@ message DruidTalents { bool swiftmend = 47; } -enum DruidRune { - DruidRuneNone = 0; - - RuneHelmGaleWinds = 417135; - RuneHelmGore = 417145; - RuneHelmImprovedBarkskin = 431388; - - RuneCloakImprovedSwipe = 439510; - RuneCloakTreeofLife = 439733; - RuneCloakStarfall = 439748; - - RuneChestFuryOfStormrage = 414799; - RuneChestLivingSeed = 414677; - RuneChestSurvivalOfTheFittest = 411115; - RuneChestWildStrikes = 407977; - - RuneBracersEfflorescence = 417149; - RuneBracersElunesFires = 414719; - RuneBracersImpFrenziedRegen = 431389; - - RuneHandsMangle = 407995; - RuneHandsSunfire = 414684; - RuneHandsWildGrowth = 408120; - RuneHandsSkullBash = 410176; - - RuneBeltBerserk = 417141; - RuneBeltEclipse = 408248; - RuneBeltNourish = 408247; - - RuneLegsStarsurge = 417157; - RuneLegsSavageRoar = 407988; - RuneLegsLifebloom = 409824; - RuneLegsLacerate = 414644; - - RuneFeetDreamstate = 408258; - RuneFeetKingOfTheJungle = 417046; - RuneFeetSurvivalInstincts = 408024; -} - message BalanceDruid { message Rotation { } From 545135df46fd08a099c22651ee86e38d169e9271 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:32:16 -0500 Subject: [PATCH 16/83] Update hunter.proto --- proto/hunter.proto | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/proto/hunter.proto b/proto/hunter.proto index a66138c6a4..217f68e5ce 100644 --- a/proto/hunter.proto +++ b/proto/hunter.proto @@ -102,47 +102,6 @@ message HunterPetTalents { int32 silverback = 37; } -enum HunterRune { - HunterRuneNone = 0; - - RuneHelmRapidKilling = 415405; - RuneHelmLockAndLoad = 415413; - RuneHelmCatlikeReflexes = 415428; - - RuneCloakImprovedVolley = 440520; - RuneCloakResourcefulness = 440529; - RuneCloakHitAndRun = 440533; - - RuneChestBeastmastery = 409368; - RuneChestMasterMarksman = 409428; - RuneChestLoneWolf = 415370; - RuneChestCobraStrikes = 425713; - - RuneBracersRaptorFury = 415358; - RuneBracersFocusFire = 428726; - RuneBracersTNT = 428717; - - RuneHandsCobraSlayer = 458393; - RuneHandsChimeraShot = 409433; - RuneHandsExplosiveShot = 409552; - RuneHandsCarve = 425711; - - RuneBeltExposeWeakness = 409504; - RuneBeltMeleeSpecialist = 415352; - RuneBeltSteadyShot = 437123; - - RuneLegsKillShot = 409593; - RuneLegsFlankingStrike = 415320; - RuneLegsSniperTraining = 415399; - RuneLegsSerpentSpread = 425738; - - RuneBootsTrapLauncher = 409541; - RuneBootsDualWieldSpecialization = 409687; - RuneBootsWyvernStrike = 458479; - - RuneUtilityHeartOfTheLion = 409580; -} - message Hunter { message Rotation { enum RotationType { From 0f313165b61f91810b53f27eb1e83e8a1cf6f561 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:32:29 -0500 Subject: [PATCH 17/83] Update mage.proto --- proto/mage.proto | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/proto/mage.proto b/proto/mage.proto index 9a6a3f25ba..3cf35a148b 100644 --- a/proto/mage.proto +++ b/proto/mage.proto @@ -60,46 +60,6 @@ message MageTalents { bool ice_barrier = 49; } -enum MageRune { - MageRuneNone = 0; - - RuneHelmAdvancedWarding = 428738; - RuneHelmDeepFreeze = 428739; - RuneHelmHotStreak = 400624; - RuneHelmTemporalAnomaly = 429305; - - RuneCloakArcaneBarrage = 400610; - RuneCloakOverheat = 400615; - RuneCloakFrozenOrb = 440802; - - RuneChestBurnout = 412286; - RuneChestEnlightenment = 412324; - RuneChestFingersOfFrost = 400647; - RuneChestRegeneration = 401417; - - RuneBracersMoltenArmor = 428741; - RuneBracersDisplacement = 428863; - RuneBracersBalefireBolt = 428878; - RuneBracersRewindTime = 401462; - - RuneHandsArcaneBlast = 400574; - RuneHandsIceLance = 400640; - RuneHandsLivingBomb = 400613; - - RuneBeltFrostfireBolt = 401502; - RuneBeltMissileBarrage = 400588; - RuneBeltSpellfrostBolt = 412532; - - RuneLegsArcaneSurge = 425124; - RuneLegsIceVeins = 425121; - RuneLegsLivingFlame = 401556; - RuneLegsMassRegeneration = 412510; - - RuneFeetBrainFreeze = 400731; - RuneFeetChronoPreservation = 436516; - RuneFeetSpellPower = 412322; -} - message Mage { message Rotation { } From 54161a4b1d0765077b34937c46718404b8051ec5 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:33:07 -0500 Subject: [PATCH 18/83] Update warrior.proto --- proto/warrior.proto | 52 --------------------------------------------- 1 file changed, 52 deletions(-) diff --git a/proto/warrior.proto b/proto/warrior.proto index 1d6b434a16..d21d7c300e 100644 --- a/proto/warrior.proto +++ b/proto/warrior.proto @@ -63,58 +63,6 @@ message WarriorTalents { bool shield_slam = 52; } -enum WarriorRune { - WarriorRuneNone = 0; - - // Helm - RuneEndlessRage = 403218; - RuneTasteForBlood = 426953; - RuneVigilance = 426972; - RuneShieldMastery = 426980; - - // Cloak - RuneSuddenDeath = 440113; - RuneFreshMeat = 440484; - RuneShockwave = 440488; - - // Chest - RuneFlagellation = 402877; - RuneRagingBlow = 402911; - RuneBloodFrenzy = 412507; - RuneWarbringer = 425421; - - // Bracers - RuneRampage = 426940; - RuneSwordAndBoard = 426978; - RuneWreckingCrew = 427065; - - // Hands - RuneVictoryRush = 402927; - RuneDevastate = 403195; - - RuneSingleMindedFury = 413404; - RuneQuickStrike = 429765; - - // Waist - RuneFocusedRage = 29787; - RunePreciseTiming = 402922; - RuneBloodSurge = 413380; - - // Legs - RuneFuriousThunder = 403219; - RuneFrenziedAssault = 425412; - RuneConsumedByRage = 425418; - - // Feet - RuneEnragedRegeneration = 403467; - RuneIntervene = 403472; - RuneRallyingCry = 426491; - RuneGladiatorStance = 412513; - - // Utility - RuneCommandingShout = 403446; -} - enum WarriorShout { WarriorShoutNone = 0; WarriorShoutBattle = 1; From 0df7fd733be9f022b9c43c92e5353facf852af02 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:35:37 -0500 Subject: [PATCH 19/83] Delete sim/druid/berserk.go --- sim/druid/berserk.go | 75 -------------------------------------------- 1 file changed, 75 deletions(-) delete mode 100644 sim/druid/berserk.go diff --git a/sim/druid/berserk.go b/sim/druid/berserk.go deleted file mode 100644 index 8fb387ad26..0000000000 --- a/sim/druid/berserk.go +++ /dev/null @@ -1,75 +0,0 @@ -package druid - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (druid *Druid) applyBerserk() { - if !druid.HasRune(proto.DruidRune_RuneBeltBerserk) { - return - } - - actionId := core.ActionID{SpellID: 417141} - var affectedSpells []*DruidSpell - - druid.BerserkAura = druid.RegisterAura(core.Aura{ - Label: "Berserk", - ActionID: actionId, - Duration: time.Second * 15, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells = core.FilterSlice([]*DruidSpell{ - druid.Rip, - // druid.Claw, // If it would exist - druid.Rake, - druid.TigersFury, - druid.Shred, - // druid.Ravage, // If it would exist - // druid.Pounce, // If it would exist - druid.FerociousBite, - druid.MangleCat, - // druid.Sunfire, // If it would exist - // druid.Skullbash, // If it would exist - druid.SavageRoar, - druid.SwipeCat, - }, func(spell *DruidSpell) bool { return spell != nil }) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range affectedSpells { - if spell.Cost != nil { - spell.Cost.Multiplier -= 50 - } - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range affectedSpells { - if spell.Cost != nil { - spell.Cost.Multiplier += 50 - } - } - }, - }) - - druid.Berserk = druid.RegisterSpell(Cat|Bear, core.SpellConfig{ - ActionID: actionId, - Flags: core.SpellFlagAPL, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: druid.NewTimer(), - Duration: time.Minute * 3, - }, - IgnoreHaste: true, - }, - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - druid.BerserkAura.Activate(sim) - }, - }) - - druid.AddMajorCooldown(core.MajorCooldown{ - Spell: druid.Berserk.Spell, - Type: core.CooldownTypeDPS, - }) -} From 9d2e13d08adc4d0bf5f43465d5c2e70a74db910f Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:37:49 -0500 Subject: [PATCH 20/83] Update forms.go --- sim/druid/forms.go | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/sim/druid/forms.go b/sim/druid/forms.go index 7fd406d125..830d063730 100644 --- a/sim/druid/forms.go +++ b/sim/druid/forms.go @@ -13,8 +13,7 @@ const ( Bear Cat Moonkin - Tree - Any = Humanoid | Bear | Cat | Moonkin | Tree + Any = Humanoid | Bear | Cat | Moonkin ) func (form DruidForm) Matches(other DruidForm) bool { @@ -411,9 +410,6 @@ func (druid *Druid) registerMoonkinFormSpell() { actionID := core.ActionID{SpellID: 24858} - druid.MoonfireDotMultiplier = 1.0 - druid.SunfireDotMultiplier = 1.0 - druid.MoonkinFormAura = druid.RegisterAura(core.Aura{ Label: "Moonkin Form", ActionID: actionID, @@ -423,37 +419,9 @@ func (druid *Druid) registerMoonkinFormSpell() { druid.CancelShapeshift(sim) } druid.form = Moonkin - - druid.AddStatDynamic(sim, stats.SpellDamage, float64(2*druid.Level)) - - druid.MoonfireDotMultiplier *= 2.0 - core.Each(druid.Moonfire, func(spell *DruidSpell) { - if spell != nil { - spell.Spell.Cost.Multiplier -= 50 - } - }) - - if druid.HasRune(proto.DruidRune_RuneHandsSunfire) { - druid.Sunfire.Cost.Multiplier -= 50 - druid.SunfireDotMultiplier *= 2.0 - } }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { druid.form = Humanoid - - druid.AddStatDynamic(sim, stats.SpellDamage, float64(-2*druid.Level)) - - core.Each(druid.Moonfire, func(spell *DruidSpell) { - if spell != nil { - spell.Spell.Cost.Multiplier += 50 - } - }) - druid.MoonfireDotMultiplier /= 2.0 - - if druid.HasRune(proto.DruidRune_RuneHandsSunfire) { - druid.Sunfire.Cost.Multiplier += 50 - druid.SunfireDotMultiplier /= 2.0 - } }, }) From c32dc59e060d629b833d442788fcb09c339fe3c9 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:39:10 -0500 Subject: [PATCH 21/83] Update moonfire.go --- sim/druid/moonfire.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sim/druid/moonfire.go b/sim/druid/moonfire.go index d86f9534a1..46c05107d1 100644 --- a/sim/druid/moonfire.go +++ b/sim/druid/moonfire.go @@ -73,13 +73,9 @@ func (druid *Druid) getMoonfireBaseConfig(rank int) core.SpellConfig { BonusCoefficient: spellDotCoeff, OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { dot.Snapshot(target, baseDotDamage, isRollover) - dot.SnapshotAttackerMultiplier *= druid.MoonfireDotMultiplier - if !druid.form.Matches(Moonkin) { - dot.SnapshotCritChance = 0 - } }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) + dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) }, }, From abcee5d2005ad3ce27fac1fc127644fc6b31968a Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:39:37 -0500 Subject: [PATCH 22/83] Update druid.go --- sim/druid/druid.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/sim/druid/druid.go b/sim/druid/druid.go index 868a510873..e4d9dc98bf 100644 --- a/sim/druid/druid.go +++ b/sim/druid/druid.go @@ -127,10 +127,7 @@ type Druid struct { // Extra data used for various calculations and overrides FerociousBiteExcessEnergyOverride bool // When true, disables the excess energy consumption of Ferocious bite - // Sunfire/Moonfire modifiers applied when in Moonkin form - MoonfireDotMultiplier float64 ShredPositionOverride bool - SunfireDotMultiplier float64 t26pcTreants *T2Treants form DruidForm From ffc2d826f7d63329aa601f89373d5d96892c9d4b Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:39:49 -0500 Subject: [PATCH 23/83] Delete sim/druid/savage_roar.go --- sim/druid/savage_roar.go | 77 ---------------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 sim/druid/savage_roar.go diff --git a/sim/druid/savage_roar.go b/sim/druid/savage_roar.go deleted file mode 100644 index 99ff7ad979..0000000000 --- a/sim/druid/savage_roar.go +++ /dev/null @@ -1,77 +0,0 @@ -package druid - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (druid *Druid) getSavageRoarMultiplier() float64 { - return 1.3 -} - -func (druid *Druid) applySavageRoar() { - if !druid.HasRune(proto.DruidRune_RuneLegsSavageRoar) { - return - } - - actionID := core.ActionID{SpellID: 407988} - - srm := druid.getSavageRoarMultiplier() - - druid.SavageRoarDurationTable = [6]time.Duration{ - 0, - time.Second * (9 + 5), - time.Second * (9 + 10), - time.Second * (9 + 15), - time.Second * (9 + 20), - time.Second * (9 + 25), - } - - druid.SavageRoarAura = druid.RegisterAura(core.Aura{ - Label: "Savage Roar Aura", - ActionID: actionID, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - druid.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] *= srm - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - if druid.InForm(Cat) { - druid.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] /= srm - } - }, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Duration = druid.SavageRoarDurationTable[5] // for pre-pull - }, - }) - - srSpell := druid.RegisterSpell(Cat, core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagAPL, - EnergyCost: core.EnergyCostOptions{ - Cost: 25, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: time.Second, - }, - IgnoreHaste: true, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return druid.ComboPoints() > 0 - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { - druid.SavageRoarAura.Duration = druid.SavageRoarDurationTable[druid.ComboPoints()] - druid.SavageRoarAura.Activate(sim) - druid.SpendComboPoints(sim, spell) - }, - }) - - druid.SavageRoar = srSpell -} - -func (druid *Druid) CurrentSavageRoarCost() float64 { - return druid.SavageRoar.Cost.GetCurrentCost() -} From faf84099acec4253ce0c4cc0de52ab5d4da2b100 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:39:57 -0500 Subject: [PATCH 24/83] Delete sim/druid/mangle.go --- sim/druid/mangle.go | 133 -------------------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 sim/druid/mangle.go diff --git a/sim/druid/mangle.go b/sim/druid/mangle.go deleted file mode 100644 index a2288ccfa1..0000000000 --- a/sim/druid/mangle.go +++ /dev/null @@ -1,133 +0,0 @@ -package druid - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -/* TODO: Bear mangle -func (druid *Druid) registerMangleBearSpell() { - if !druid.Talents.Mangle { - return - } - - mangleAuras := druid.NewEnemyAuraArray(core.MangleAura) - durReduction := (0.5) * float64(druid.Talents.ImprovedMangle) - - druid.MangleBear = druid.RegisterSpell(Bear, core.SpellConfig{ - SpellCode: SpellCode_DruidMangleBear - ActionID: core.ActionID{SpellID: 48564}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: SpellFlagOmen | core.SpellFlagMeleeMetrics | core.SpellFlagIncludeTargetBonusDamage | core.SpellFlagAPL, - - RageCost: core.RageCostOptions{ - Cost: 20 - float64(druid.Talents.Ferocity), - Refund: 0.8, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: druid.NewTimer(), - Duration: time.Duration(float64(time.Second) * (6 - durReduction)), - }, - }, - - DamageMultiplier: (1 + 0.1*float64(druid.Talents.SavageFury)) * 1.15 - ThreatMultiplier: core.TernaryFloat64(druid.HasSetBonus(ItemSetThunderheartHarness, 2), 1.15, 1), - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := 299/1.15 + - spell.Unit.MHWeaponDamage(sim, spell.MeleeAttackPower()) + - spell.BonusWeaponDamage() - - result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - - if result.Landed() { - mangleAuras.Get(target).Activate(sim) - } else { - spell.IssueRefund(sim) - } - - if druid.BerserkAura.IsActive() { - spell.CD.Reset() - } - }, - - RelatedAuras: []core.AuraArray{mangleAuras}, - }) - } -*/ - -func (druid *Druid) registerMangleCatSpell() { - if !druid.HasRune(proto.DruidRune_RuneHandsMangle) { - return - } - - hasGoreRune := druid.HasRune(proto.DruidRune_RuneHelmGore) - - weaponMulti := 2.7 - energyCost := 40 - float64(druid.Talents.Ferocity) - - mangleAuras := druid.NewEnemyAuraArray(core.MangleAura) - druid.MangleCat = druid.RegisterSpell(Cat, core.SpellConfig{ - SpellCode: SpellCode_DruidMangleCat, - ActionID: core.ActionID{SpellID: 409828}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | SpellFlagOmen | SpellFlagBuilder, - - EnergyCost: core.EnergyCostOptions{ - Cost: energyCost, - Refund: 0.8, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: time.Second, - }, - IgnoreHaste: true, - }, - - DamageMultiplier: (1 + 0.1*float64(druid.Talents.SavageFury)) * weaponMulti, - ThreatMultiplier: 1, - BonusCoefficient: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := spell.Unit.MHWeaponDamage(sim, spell.MeleeAttackPower()) - result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - - if result.Landed() { - druid.AddComboPoints(sim, 1, target, spell.ComboPointMetrics()) - mangleAuras.Get(target).Activate(sim) - - if hasGoreRune { - druid.rollGoreCatReset(sim) - } - } else { - spell.IssueRefund(sim) - } - }, - - RelatedAuras: []core.AuraArray{mangleAuras}, - }) -} - -func (druid *Druid) CurrentMangleCatCost() float64 { - return druid.MangleCat.Cost.GetCurrentCost() -} - -func (druid *Druid) IsMangle(spell *core.Spell) bool { - if druid.MangleBear != nil && druid.MangleBear.IsEqual(spell) { - return true - } else if druid.MangleCat != nil && druid.MangleCat.IsEqual(spell) { - return true - } - return false -} From 7cfe5cb4ff1263fabcf0d8e73ec0c86532f132ef Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:40:04 -0500 Subject: [PATCH 25/83] Delete sim/druid/t2_treants.go --- sim/druid/t2_treants.go | 99 ----------------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 sim/druid/t2_treants.go diff --git a/sim/druid/t2_treants.go b/sim/druid/t2_treants.go deleted file mode 100644 index 8e56853020..0000000000 --- a/sim/druid/t2_treants.go +++ /dev/null @@ -1,99 +0,0 @@ -package druid - -import ( - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -// We have limited data on these treants, so numbers are mostly made up. -// A lot of the stats and scaling were copied from Felhunter and Warlock pets with tweaks made to -// adjust to be closer to Testwerk logs. - -type T2Treants struct { - core.Pet - - Druid *Druid - Shadowcrawl *core.Spell - ShadowcrawlAura *core.Aura -} - -func (druid *Druid) NewT2Treants() *T2Treants { - // TODO: Figure out stats - baseDamageMin := 70.0 - baseDamageMax := 97.0 - 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.MeleeHit: 4 * core.MeleeHitRatingPerHitChance, - stats.MeleeCrit: 3.2685 * core.CritRatingPerCritChance, - stats.SpellCrit: 3.3355 * core.CritRatingPerCritChance, - } - - treants := &T2Treants{ - Pet: core.NewPet("Treants", &druid.Character, baseStats, druid.t2TreantsStatInheritance(), false, true), - Druid: druid, - } - - treants.EnableManaBarWithModifier(.77) - - treants.PseudoStats.DamageTakenMultiplier *= 0.1 - - treants.AddStatDependency(stats.Strength, stats.AttackPower, 2) - treants.AddStat(stats.AttackPower, -20) - - // Warrior crit scaling - treants.AddStatDependency(stats.Agility, stats.MeleeCrit, core.CritPerAgiAtLevel[proto.Class_ClassWarrior]*core.CritRatingPerCritChance) - treants.AddStatDependency(stats.Intellect, stats.SpellCrit, core.CritPerIntAtLevel[proto.Class_ClassWarrior]*core.SpellCritRatingPerCritChance) - - treants.EnableAutoAttacks(treants, core.AutoAttackOptions{ - MainHand: core.Weapon{ - BaseDamageMin: baseDamageMin, - BaseDamageMax: baseDamageMax, - SwingSpeed: 0.6667, // 3 Treants attack at 2 second intervals. To avoid creating 3 pets, have the AI swing at 2/3 second intervals - AttackPowerPerDPS: 14.0 / 6.0, - SpellSchool: core.SpellSchoolPhysical, - }, - AutoSwingMelee: true, - }) - - druid.AddPet(treants) - - return treants -} - -func (druid *Druid) t2TreantsStatInheritance() core.PetStatInheritance { - return func(ownerStats stats.Stats) stats.Stats { - 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: ownerStats[stats.AttackPower] * 0.565, - stats.MP5: ownerStats[stats.Intellect] * 0.315, - stats.SpellPower: ownerStats[stats.SpellPower] * 0.15, - stats.SpellDamage: ownerStats[stats.SpellDamage] * 0.15, - } - } -} - -func (treants *T2Treants) Initialize() { -} - -func (treants *T2Treants) ExecuteCustomRotation(sim *core.Simulation) { -} - -func (treants *T2Treants) Reset(sim *core.Simulation) { - treants.Disable(sim) -} - -func (treants *T2Treants) OnPetDisable(sim *core.Simulation) { -} - -func (treants *T2Treants) GetPet() *core.Pet { - return &treants.Pet -} From a8abb5d58f8405305c9ae70c35f9b1788c2b460c Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:40:12 -0500 Subject: [PATCH 26/83] Delete sim/druid/sunfire.go --- sim/druid/sunfire.go | 144 ------------------------------------------- 1 file changed, 144 deletions(-) delete mode 100644 sim/druid/sunfire.go diff --git a/sim/druid/sunfire.go b/sim/druid/sunfire.go deleted file mode 100644 index 237d79cb36..0000000000 --- a/sim/druid/sunfire.go +++ /dev/null @@ -1,144 +0,0 @@ -package druid - -import ( - "fmt" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -const SunfireTicks = int32(4) - -func (druid *Druid) registerSunfireSpell() { - if !druid.HasRune(proto.DruidRune_RuneHandsSunfire) { - return - } - - baseDamageLow := druid.baseRuneAbilityDamage() * 1.3 - baseDamageHigh := druid.baseRuneAbilityDamage() * 1.52 - baseDotDamage := druid.baseRuneAbilityDamage() * 0.65 - - druid.registerSunfireHumanoidSpell(baseDamageLow, baseDamageHigh, baseDotDamage) - druid.registerSunfireCatSpell(baseDamageLow, baseDamageHigh, baseDotDamage) -} - -func (druid *Druid) registerSunfireHumanoidSpell(baseDamageLow float64, baseDamageHigh float64, baseDotDamage float64) { - actionID := core.ActionID{SpellID: int32(proto.DruidRune_RuneHandsSunfire)} - spellCoeff := .15 - dotCoeff := .13 - - config := druid.getSunfireBaseSpellConfig( - actionID, - core.SpellFlagResetAttackSwing, - func(sim *core.Simulation, _ *core.Spell) float64 { - return sim.Roll(baseDamageLow, baseDamageHigh) - }, - func(_ *core.Spell) float64 { - return baseDotDamage - }, - func(_ *core.Simulation, _ *core.Unit, _ *core.Spell) {}, - ) - - config.SpellCode = SpellCode_DruidSunfire - config.ManaCost = core.ManaCostOptions{ - BaseCost: 0.21, - } - config.BonusCoefficient = spellCoeff - config.Dot.BonusCoefficient = dotCoeff - - druid.Sunfire = druid.RegisterSpell(Humanoid|Moonkin, *config) -} - -// TODO: Bear form sunfire -// func (druid *Druid) registerSunfireBearSpell(baseDamageLow float64, baseDamageHigh float64, baseDotDamage float64) {} - -func (druid *Druid) registerSunfireCatSpell(baseDamageLow float64, baseDamageHigh float64, baseDotDamage float64) { - actionID := core.ActionID{SpellID: 414689} - - spellAPCoeff := .12 - dotAPCoeff := .104 - - config := druid.getSunfireBaseSpellConfig( - actionID, - core.SpellFlagNone, - func(sim *core.Simulation, spell *core.Spell) float64 { - // Sunfire (Cat) uses a different scaling formula based on the Druid's AP - return sim.Roll(baseDamageLow, baseDamageHigh) + spellAPCoeff*spell.MeleeAttackPower() - }, - func(spell *core.Spell) float64 { - // Sunfire (Cat) uses a different scaling formula based on the Druid's AP - return baseDotDamage + dotAPCoeff*spell.MeleeAttackPower() - }, - func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - druid.AddComboPoints(sim, 1, target, spell.ComboPointMetrics()) - }, - ) - - config.EnergyCost = core.EnergyCostOptions{ - Cost: 40, - } - - druid.SunfireCat = druid.RegisterSpell(Cat, *config) -} - -func (druid *Druid) getSunfireBaseSpellConfig( - actionID core.ActionID, - additionalFlags core.SpellFlag, - getBaseDamage func(sim *core.Simulation, spell *core.Spell) float64, - getBaseDotDamage func(spell *core.Spell) float64, - // Callback for additional logic after a cast lands like adding a combo point for the Feral spell - onResultLanded func(sim *core.Simulation, target *core.Unit, spell *core.Spell), -) *core.SpellConfig { - return &core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: core.SpellFlagAPL | SpellFlagOmen | additionalFlags, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - }, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: fmt.Sprintf("Sunfire %d", actionID.SpellID), - ActionID: actionID, - }, - NumberOfTicks: SunfireTicks, - TickLength: time.Second * 3, - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - dot.Snapshot(target, getBaseDotDamage(dot.Spell), isRollover) - dot.SnapshotAttackerMultiplier *= druid.SunfireDotMultiplier - if !druid.form.Matches(Moonkin) { - dot.SnapshotCritChance = 0 - } - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := getBaseDamage(sim, spell) - result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - - if result.Landed() { - dot := spell.Dot(target) - dot.Apply(sim) - onResultLanded(sim, target, spell) - } - }, - - ExpectedTickDamage: func(sim *core.Simulation, target *core.Unit, spell *core.Spell, _ bool) *core.SpellResult { - dot := spell.Dot(target) - return dot.CalcSnapshotDamage(sim, target, dot.Spell.OutcomeExpectedMagicAlwaysHit) - }, - } -} From 7c3a6c02968d2d35ab00c230e1dee4e3bb4a978b Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:40:26 -0500 Subject: [PATCH 27/83] Delete sim/druid/starfall.go --- sim/druid/starfall.go | 119 ------------------------------------------ 1 file changed, 119 deletions(-) delete mode 100644 sim/druid/starfall.go diff --git a/sim/druid/starfall.go b/sim/druid/starfall.go deleted file mode 100644 index aed63c344a..0000000000 --- a/sim/druid/starfall.go +++ /dev/null @@ -1,119 +0,0 @@ -package druid - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -// We register two spells to apply two different dot effects and get two entries in Damage/Detailed results -func (druid *Druid) registerStarfallCD() { - if !druid.HasRune(proto.DruidRune_RuneCloakStarfall) { - return - } - - actionID := core.ActionID{SpellID: int32(proto.DruidRune_RuneCloakStarfall)} - - baseDamageLow := druid.baseRuneAbilityDamage() * 0.46 - baseDamageHigh := druid.baseRuneAbilityDamage() * 0.54 - baseDamageSplash := druid.baseRuneAbilityDamage() * 0.08 - spellCoefTick := 0.3 - spellCoefSplash := 0.127 - - numberOfTicks := core.TernaryInt32(druid.Env.GetNumTargets() > 1, 20, 10) - tickLength := time.Second - cooldown := time.Second * 90 - - druid.StarfallSplash = druid.RegisterSpell(Any, core.SpellConfig{ - SpellCode: SpellCode_DruidStarfallSplash, - ActionID: actionID.WithTag(2), - SpellSchool: core.SpellSchoolArcane, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoefSplash, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - // Apply the base spell's multipliers to pick up on effects that only affect spells with DoTs - spell.DamageMultiplierAdditive += druid.Starfall.PeriodicDamageMultiplierAdditive - 1 - - for _, aoeTarget := range sim.Encounter.TargetUnits { - spell.CalcAndDealDamage(sim, aoeTarget, baseDamageSplash, spell.OutcomeMagicHitAndCrit) - } - - spell.DamageMultiplierAdditive -= druid.Starfall.PeriodicDamageMultiplierAdditive - 1 - }, - }) - - druid.StarfallTick = druid.RegisterSpell(Humanoid|Moonkin, core.SpellConfig{ - SpellCode: SpellCode_DruidStarfallTick, - ActionID: actionID.WithTag(1), - SpellSchool: core.SpellSchoolArcane, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, // Shown to proc things in-game - Flags: core.SpellFlagBinary, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoefTick, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := sim.Roll(baseDamageLow, baseDamageHigh) - - // Apply the base spell's multipliers to pick up on effects that only affect spells with DoTs - spell.DamageMultiplierAdditive += druid.Starfall.PeriodicDamageMultiplierAdditive - 1 - spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - spell.DamageMultiplierAdditive -= druid.Starfall.PeriodicDamageMultiplierAdditive - 1 - - druid.StarfallSplash.Cast(sim, target) - }, - }) - - druid.Starfall = druid.RegisterSpell(Humanoid|Moonkin, core.SpellConfig{ - SpellCode: SpellCode_DruidStarfall, - ActionID: actionID, - SpellSchool: core.SpellSchoolArcane, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagAPL | SpellFlagOmen, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.39, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: druid.NewTimer(), - Duration: cooldown, - }, - }, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: "Starfall", - }, - NumberOfTicks: numberOfTicks, - TickLength: tickLength, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - druid.StarfallTick.Cast(sim, target) - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.Dot(target).Apply(sim) - }, - }) - - druid.AddMajorCooldown(core.MajorCooldown{ - Spell: druid.Starfall.Spell, - Type: core.CooldownTypeDPS, - }) -} From 8745a3c4fc1e6dd0ffd565b6cfacc08b72145044 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:40:33 -0500 Subject: [PATCH 28/83] Delete sim/druid/starsurge.go --- sim/druid/starsurge.go | 98 ------------------------------------------ 1 file changed, 98 deletions(-) delete mode 100644 sim/druid/starsurge.go diff --git a/sim/druid/starsurge.go b/sim/druid/starsurge.go deleted file mode 100644 index 84b937a3ed..0000000000 --- a/sim/druid/starsurge.go +++ /dev/null @@ -1,98 +0,0 @@ -package druid - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (druid *Druid) applyStarsurge() { - if !druid.HasRune(proto.DruidRune_RuneLegsStarsurge) { - return - } - - actionID := core.ActionID{SpellID: 417157} - - baseLowDamage := druid.baseRuneAbilityDamage() * 2.48 - baseHighDamage := druid.baseRuneAbilityDamage() * 3.04 - spellCoeff := .429 - - starfireAuraMultiplier := 1 + .80 - starfireAuraDuration := time.Second * 15 - - starfireDamageAura := druid.RegisterAura(core.Aura{ - Label: "Starsurge", - ActionID: actionID, - Duration: starfireAuraDuration, - MaxStacks: 1, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - core.Each(druid.Starfire, func(spell *DruidSpell) { - if spell != nil { - spell.DamageMultiplier *= starfireAuraMultiplier - } - }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - core.Each(druid.Starfire, func(spell *DruidSpell) { - if spell != nil { - spell.DamageMultiplier /= starfireAuraMultiplier - } - }) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode != SpellCode_DruidStarfire { - return - } - - aura.Deactivate(sim) - }, - }) - - druid.Starsurge = druid.RegisterSpell(Humanoid|Moonkin, core.SpellConfig{ - ActionID: actionID, - SpellCode: SpellCode_DruidStarsurge, - SpellSchool: core.SpellSchoolArcane, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagOmen | core.SpellFlagResetAttackSwing | core.SpellFlagBinary | core.SpellFlagAPL, - - MissileSpeed: 24, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.01 * (1 - 0.03*float64(druid.Talents.Moonglow)), - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - CastTime: 0, - }, - CD: core.Cooldown{ - Timer: druid.NewTimer(), - Duration: time.Second * 6, - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := sim.Roll(baseLowDamage, baseHighDamage) - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - - // NG procs when the cast finishes - if result.DidCrit() && druid.NaturesGraceProcAura != nil { - druid.NaturesGraceProcAura.Activate(sim) - druid.NaturesGraceProcAura.SetStacks(sim, druid.NaturesGraceProcAura.MaxStacks) - } - - // Aura applies on cast - starfireDamageAura.Activate(sim) - - spell.WaitTravelTime(sim, func(sim *core.Simulation) { - spell.DealDamage(sim, result) - }) - }, - }) -} From 539a358b2899e64afd19218712050c0e1c45d129 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:44:41 -0500 Subject: [PATCH 29/83] Update druid.go --- sim/druid/druid.go | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/sim/druid/druid.go b/sim/druid/druid.go index e4d9dc98bf..023493ba18 100644 --- a/sim/druid/druid.go +++ b/sim/druid/druid.go @@ -23,19 +23,12 @@ const ( SpellCode_DruidFaerieFireFeral SpellCode_DruidFerociousBite SpellCode_DruidInsectSwarm - SpellCode_DruidMangleCat - SpellCode_DruidMangleBear SpellCode_DruidMoonfire SpellCode_DruidRake SpellCode_DruidRip SpellCode_DruidShred SpellCode_DruidStarfire - SpellCode_DruidStarsurge SpellCode_DruidWrath - SpellCode_DruidStarfall - SpellCode_DruidStarfallTick - SpellCode_DruidStarfallSplash - SpellCode_DruidSunfire ) type Druid struct { @@ -65,31 +58,17 @@ type Druid struct { Hurricane []*DruidSpell Innervate *DruidSpell InsectSwarm []*DruidSpell - Lacerate *DruidSpell Languish *DruidSpell - MangleBear *DruidSpell - MangleCat *DruidSpell - Berserk *DruidSpell Maul *DruidSpell MaulQueueSpell *DruidSpell Moonfire []*DruidSpell Rebirth *DruidSpell Rake *DruidSpell Rip *DruidSpell - SavageRoar *DruidSpell Shred *DruidSpell Starfire []*DruidSpell - Starfall *DruidSpell - StarfallTick *DruidSpell - StarfallSplash *DruidSpell - Starsurge *DruidSpell - Sunfire *DruidSpell - SunfireCat *DruidSpell - SurvivalInstincts *DruidSpell SwipeBear *DruidSpell - SwipeCat *DruidSpell TigersFury *DruidSpell - Typhoon *DruidSpell Wrath []*DruidSpell BearForm *DruidSpell @@ -102,33 +81,18 @@ type Druid struct { CatFormAura *core.Aura ClearcastingAura *core.Aura DemoralizingRoarAuras core.AuraArray - DreamstateManaRegenAura *core.Aura EnrageAura *core.Aura - EclipseAura *core.Aura FaerieFireAuras core.AuraArray - ImprovedFaerieFireAuras core.AuraArray FrenziedRegenerationAura *core.Aura FurorAura *core.Aura - FuryOfStormrageAura *core.Aura InsectSwarmAuras core.AuraArray MaulQueueAura *core.Aura MoonkinFormAura *core.Aura NaturesGraceProcAura *core.Aura PredatoryInstinctsAura *core.Aura - SurvivalInstinctsAura *core.Aura TigersFuryAura *core.Aura - SavageRoarAura *core.Aura - SolarEclipseProcAura *core.Aura - LunarEclipseProcAura *core.Aura - WildStrikesBuffAura *core.Aura BleedCategories core.ExclusiveCategoryArray - SavageRoarDurationTable [6]time.Duration - - // Extra data used for various calculations and overrides - FerociousBiteExcessEnergyOverride bool // When true, disables the excess energy consumption of Ferocious bite - ShredPositionOverride bool - t26pcTreants *T2Treants form DruidForm disabledMCDs []*core.MajorCooldown @@ -215,7 +179,6 @@ func (druid *Druid) RegisterFeralCatSpells() { druid.registerFerociousBiteSpell() // druid.registerMangleBearSpell() // druid.registerMaulSpell() - // druid.registerLacerateSpell() druid.registerRakeSpell() druid.registerRipSpell() druid.registerShredSpell() @@ -233,10 +196,8 @@ func (druid *Druid) RegisterFeralTankSpells() { // druid.registerFrenziedRegenerationCD() // druid.registerMangleBearSpell() // druid.registerMaulSpell() - // druid.registerLacerateSpell() // druid.registerRakeSpell() // druid.registerRipSpell() - // druid.registerSurvivalInstinctsCD() // druid.registerSwipeBearSpell() } @@ -267,7 +228,6 @@ func New(character *core.Character, form DruidForm, selfBuffs SelfBuffs, talents // druid.PseudoStats.MeleeHasteRatingPerHastePercent /= 1.3 guardians.ConstructGuardians(&druid.Character) - druid.t26pcTreants = druid.NewT2Treants() return druid } From c0b8631048347c0a732c00397eb0c232021e8863 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:45:43 -0500 Subject: [PATCH 30/83] Update shred.go --- sim/druid/shred.go | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/sim/druid/shred.go b/sim/druid/shred.go index 9cbf9e302c..eb5fa2f9e0 100644 --- a/sim/druid/shred.go +++ b/sim/druid/shred.go @@ -7,33 +7,20 @@ import ( "github.com/wowsims/classic/sim/core/proto" ) -// See https://www.wowhead.com/classic/spell=436895/s03-tuning-and-overrides-passive-druid -// Modifies Effect #1's Value -24%: -// Modifies Effect #2's Value +76: -const ShredWeaponMultiplierBuff = 0.75 // increases multiplier additively by 75% from 2.25 to 3.0 -const ShredFlatDmgMultiplier = .75 // decreases flat damage modifier multiplicatively by -25% to counteract 3.0/2.25 overall scaling buff - func (druid *Druid) registerShredSpell() { - hasGoreRune := druid.HasRune(proto.DruidRune_RuneHelmGore) - // has6pCunningOfStormrage := druid.HasSetBonus(ItemSetCunningOfStormrage, 6) - damageMultiplier := 2.25 flatDamageBonus := map[int32]float64{ 25: 24, 40: 44, 50: 64, 60: 80, - }[druid.Level] * ShredFlatDmgMultiplier + }[druid.Level] // if druid.Ranged().ID == IdolOfTheDream { // damageMultiplier *= 1.02 // flatDamageBonus *= 1.02 // } - // In-game testing concluded that, unintuitively, Idol of the Drea's 1.02x damage applies to the original 2.25x - // Shred mod, and to the flat damage bonus, but that the .75x SoD buff happens additively after Idol - damageMultiplier += ShredWeaponMultiplierBuff - druid.Shred = druid.RegisterSpell(Cat, core.SpellConfig{ SpellCode: SpellCode_DruidShred, ActionID: core.ActionID{SpellID: map[int32]int32{ @@ -58,7 +45,7 @@ func (druid *Druid) registerShredSpell() { IgnoreHaste: true, }, ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return druid.ShredPositionOverride || !druid.PseudoStats.InFrontOfTarget + return !druid.PseudoStats.InFrontOfTarget }, DamageMultiplier: damageMultiplier, @@ -78,10 +65,6 @@ func (druid *Druid) registerShredSpell() { if result.Landed() { druid.AddComboPoints(sim, 1, target, spell.ComboPointMetrics()) - - if hasGoreRune { - druid.rollGoreCatReset(sim) - } } else { spell.IssueRefund(sim) } From 3758924c614c174c390d101edd5e909c3d9e863a Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:47:18 -0500 Subject: [PATCH 31/83] Update rip.go --- sim/druid/rip.go | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/sim/druid/rip.go b/sim/druid/rip.go index 6c7dac5e82..b09edb6e12 100644 --- a/sim/druid/rip.go +++ b/sim/druid/rip.go @@ -52,18 +52,7 @@ var ripRanks = []RipRankInfo{ }, } -// See https://www.wowhead.com/classic/spell=436895/s03-tuning-and-overrides-passive-druid -// Modifies Buff Duration +4001: -// Modifies Periodic Damage/Healing Done +51%: -// const RipTicks int32 = 6 -const RipTicks int32 = 8 -const RipBaseDamageMultiplier = 1.5 - -// See https://www.wowhead.com/classic/news/development-notes-for-phase-4-ptr-season-of-discovery-new-runes-class-changes-342896 -// - Rake and Rip damage contributions from attack power increased by roughly 50%. -// PTR testing comes out to .0165563 AP scaling per CP -// damageCoefPerCP := 0.01 -const RipDamageCoefPerAPPerCP = 0.015 +const RipTicks int32 = 6 func (druid *Druid) registerRipSpell() { // Add highest available Rip rank for level. @@ -116,7 +105,7 @@ func (druid *Druid) newRipSpellConfig(ripRank RipRankInfo) core.SpellConfig { ap := dot.Spell.MeleeAttackPower() cpScaling := core.TernaryFloat64(cp == 5, 4, cp) - baseDamage := (ripRank.dmgTickBase + ripRank.dmgTickPerCombo*cp + RipDamageCoefPerAPPerCP*ap*cpScaling) + baseDamage := (ripRank.dmgTickBase + ripRank.dmgTickPerCombo*cp dot.Snapshot(target, baseDamage, isRollover) }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { From 9b05a1dd3f9457e41bf0414ec313e007cf3ecae2 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:48:57 -0500 Subject: [PATCH 32/83] Delete sim/druid/_lacerate.go --- sim/druid/_lacerate.go | 106 ----------------------------------------- 1 file changed, 106 deletions(-) delete mode 100644 sim/druid/_lacerate.go diff --git a/sim/druid/_lacerate.go b/sim/druid/_lacerate.go deleted file mode 100644 index 79dc064bcc..0000000000 --- a/sim/druid/_lacerate.go +++ /dev/null @@ -1,106 +0,0 @@ -package druid - -import ( - "time" - - "github.com/wowsims/classic/sim/core" -) - -func (druid *Druid) registerLacerateSpell() { - tickDamage := 320.0 / 5 - initialDamage := 88.0 - if druid.Ranged().ID == 27744 { // Idol of Ursoc - tickDamage += 8 - initialDamage += 8 - } - - initialDamageMul := 1 * - core.TernaryFloat64(druid.HasSetBonus(ItemSetLasherweaveBattlegear, 2), 1.2, 1) * - core.TernaryFloat64(druid.HasSetBonus(ItemSetDreamwalkerBattlegear, 2), 1.05, 1) - - tickDamageMul := 1 * - core.TernaryFloat64(druid.HasSetBonus(ItemSetLasherweaveBattlegear, 2), 1.2, 1) * - core.TernaryFloat64(druid.HasSetBonus(ItemSetMalfurionsBattlegear, 2), 1.05, 1) - - druid.Lacerate = druid.RegisterSpell(Bear, core.SpellConfig{ - ActionID: core.ActionID{SpellID: 48568}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: SpellFlagOmen | core.SpellFlagMeleeMetrics | core.SpellFlagAPL, - - RageCost: core.RageCostOptions{ - Cost: 15 - float64(druid.Talents.ShreddingAttacks), - Refund: 0.8, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, - }, - - DamageMultiplier: initialDamageMul, - ThreatMultiplier: 0.5, - // FlatThreatBonus: 515.5, // Handled below - - Dot: core.DotConfig{ - Aura: druid.applyRendAndTear(core.Aura{ - Label: "Lacerate", - MaxStacks: 5, - Duration: time.Second * 15, - }), - NumberOfTicks: 5, - TickLength: time.Second * 3, - - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - dot.SnapshotBaseDamage = tickDamage + 0.01*dot.Spell.MeleeAttackPower() - dot.SnapshotBaseDamage *= float64(dot.Aura.GetStacks()) - - if !isRollover { - attackTable := dot.Spell.Unit.AttackTables[target.UnitIndex][dot.Spell.CastType] - dot.Spell.DamageMultiplier = tickDamageMul - dot.SnapshotCritChance = dot.Spell.PhysicalCritChance(attackTable) - dot.SnapshotAttackerMultiplier = dot.Spell.AttackerDamageMultiplier(attackTable) - } - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - if druid.Talents.PrimalGore { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - } else { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.Spell.OutcomeAlwaysHit) - } - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := initialDamage + 0.01*spell.MeleeAttackPower() - if druid.BleedCategories.Get(target).AnyActive() { - baseDamage *= 1.3 - } - - // Hack so that FlatThreatBonus only applies to the initial portion. - spell.FlatThreatBonus = 515.5 - spell.DamageMultiplier = initialDamageMul - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - spell.FlatThreatBonus = 0 - - if result.Landed() { - dot := spell.Dot(target) - if dot.IsActive() { - dot.Refresh(sim) - dot.AddStack(sim) - dot.TakeSnapshot(sim, true) - } else { - dot.Apply(sim) - dot.SetStacks(sim, 1) - dot.TakeSnapshot(sim, true) - } - } else { - spell.IssueRefund(sim) - } - - spell.DealDamage(sim, result) - }, - }) -} From b7775c7b4232869ff3331953c50355cf82c16401 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:49:17 -0500 Subject: [PATCH 33/83] Update _item_sets_pve.go --- sim/druid/_item_sets_pve.go | 123 ------------------------------------ 1 file changed, 123 deletions(-) diff --git a/sim/druid/_item_sets_pve.go b/sim/druid/_item_sets_pve.go index 3b4f3b41bc..72515cb535 100644 --- a/sim/druid/_item_sets_pve.go +++ b/sim/druid/_item_sets_pve.go @@ -9,129 +9,6 @@ import ( "github.com/wowsims/classic/sim/core/stats" ) -/////////////////////////////////////////////////////////////////////////// -// SoD Phase 3 Item Sets -/////////////////////////////////////////////////////////////////////////// - -var ItemSetLostWorshippersArmor = core.NewItemSet(core.ItemSet{ - Name: "Lost Worshipper's Armor", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MeleeHit, 1) - c.AddStat(stats.SpellHit, 1) - }, - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_DruidWrath || spell.SpellCode == SpellCode_DruidStarfire { - spell.BonusCritRating += 3 * core.CritRatingPerCritChance - } - }) - }, - }, -}) - -var ItemSetCoagulateBloodguardsLeathers = core.NewItemSet(core.ItemSet{ - Name: "Coagulate Bloodguard's Leathers", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Strength, 10) - }, - 3: func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - - // Power Shredder - procAura := druid.GetOrRegisterAura(core.Aura{ - Label: "Power Shredder Proc", - ActionID: core.ActionID{SpellID: 449925}, - Duration: time.Second * 10, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - druid.CatForm.Cost.Multiplier -= 30 - //druid.BearForm.CostMultiplier -= 0.3 - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - druid.CatForm.Cost.Multiplier += 30 - //druid.BearForm.CostMultiplier += 0.3 - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell == druid.CatForm.Spell /* || spell == druid.BearForm.Spell */ { - aura.Deactivate(sim) - } - }, - }) - - core.MakeProcTriggerAura(&druid.Unit, core.ProcTrigger{ - Name: "Power Shredder", - Callback: core.CallbackOnCastComplete, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellCode == SpellCode_DruidShred { - procAura.Activate(sim) - } - }, - }) - - // Precise Claws should be implemented in the bear form spells when those get added back - // Adds 2% hit while in bear/dire bear forms - }, - }, -}) - -var ItemSetExiledProphetsRaiment = core.NewItemSet(core.ItemSet{ - Name: "Exiled Prophet's Raiment", - Bonuses: map[int32]core.ApplyEffect{ - 2: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.MP5, 4) - }, - 3: func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - // TODO: Not tested because Druid doesn't have healing spells implemented at the moment - if druid.HasRune(proto.DruidRune_RuneFeetDreamstate) { - core.MakeProcTriggerAura(&druid.Unit, core.ProcTrigger{ - Name: "Exiled Dreamer", - Callback: core.CallbackOnHealDealt, - ProcMask: core.ProcMaskSpellHealing, - Outcome: core.OutcomeCrit, - ProcChance: 0.5, - Handler: func(sim *core.Simulation, _ *core.Spell, _ *core.SpellResult) { - druid.DreamstateManaRegenAura.Activate(sim) - }, - }) - } - }, - }, -}) - -var ItemSetEmeraldWatcherVestments = core.NewItemSet(core.ItemSet{ - Name: "Emerald Watcher Vestments", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 10) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.SpellPower, 12) - }, - }, -}) - -var ItemSetEmeraldDreamkeeperGarb = core.NewItemSet(core.ItemSet{ - Name: "Emerald Dreamkeeper Garb", - Bonuses: map[int32]core.ApplyEffect{ - 3: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.Stamina, 10) - }, - 6: func(agent core.Agent) { - c := agent.GetCharacter() - c.AddStat(stats.HealingPower, 22) - }, - }, -}) - /////////////////////////////////////////////////////////////////////////// // SoD Phase 4 Item Sets /////////////////////////////////////////////////////////////////////////// From a3224c0cf72d95be9b2255da6330d5e972d79899 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:52:20 -0500 Subject: [PATCH 34/83] Update rip.go --- sim/druid/rip.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/druid/rip.go b/sim/druid/rip.go index b09edb6e12..b2276202af 100644 --- a/sim/druid/rip.go +++ b/sim/druid/rip.go @@ -105,7 +105,7 @@ func (druid *Druid) newRipSpellConfig(ripRank RipRankInfo) core.SpellConfig { ap := dot.Spell.MeleeAttackPower() cpScaling := core.TernaryFloat64(cp == 5, 4, cp) - baseDamage := (ripRank.dmgTickBase + ripRank.dmgTickPerCombo*cp + baseDamage := ripRank.dmgTickBase + ripRank.dmgTickPerCombo*cp dot.Snapshot(target, baseDamage, isRollover) }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { From 71bf06db6ded1988e9b81f66eee8b58c8042b93f Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:52:31 -0500 Subject: [PATCH 35/83] Delete sim/hunter/carve.go --- sim/hunter/carve.go | 83 --------------------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 sim/hunter/carve.go diff --git a/sim/hunter/carve.go b/sim/hunter/carve.go deleted file mode 100644 index 9d4ea12317..0000000000 --- a/sim/hunter/carve.go +++ /dev/null @@ -1,83 +0,0 @@ -package hunter - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (hunter *Hunter) registerCarveSpell() { - if !hunter.HasRune(proto.HunterRune_RuneHandsCarve) { - return - } - - hunter.CarveMH = hunter.newCarveHitSpell(true) - hunter.CarveOH = hunter.newCarveHitSpell(false) - - hunter.RegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterCarve, - ActionID: core.ActionID{SpellID: 425711}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.04, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: hunter.NewTimer(), - Duration: time.Second * 6, - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return hunter.DistanceFromTarget <= core.MaxMeleeAttackDistance - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - hunter.CarveMH.Cast(sim, aoeTarget) - if hunter.AutoAttacks.IsDualWielding { - hunter.CarveOH.Cast(sim, aoeTarget) - } - } - }, - }) -} - -func (hunter *Hunter) newCarveHitSpell(isMH bool) *core.Spell { - procMask := core.ProcMaskMeleeMHSpecial - damageMultiplier := 0.65 - damageFunc := hunter.MHWeaponDamage - - if !isMH { - procMask = core.ProcMaskMeleeOHSpecial - damageMultiplier = hunter.AutoAttacks.OHConfig().DamageMultiplier * 0.65 - damageFunc = hunter.OHWeaponDamage - } - - return hunter.RegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterCarveHit, - ActionID: core.ActionID{SpellID: 425711}.WithTag(core.TernaryInt32(isMH, 1, 2)), - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: procMask, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagNoOnCastComplete, - - DamageMultiplier: damageMultiplier, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := damageFunc(sim, spell.MeleeAttackPower()) - if target == hunter.CurrentTarget { - baseDamage *= 1.5 - } - spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) - }, - }) -} From 385970a368289f9f652f0ecd91fe33aed52e27fd Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:52:40 -0500 Subject: [PATCH 36/83] Delete sim/hunter/wyvern_strike.go --- sim/hunter/wyvern_strike.go | 94 ------------------------------------- 1 file changed, 94 deletions(-) delete mode 100644 sim/hunter/wyvern_strike.go diff --git a/sim/hunter/wyvern_strike.go b/sim/hunter/wyvern_strike.go deleted file mode 100644 index a316389f1d..0000000000 --- a/sim/hunter/wyvern_strike.go +++ /dev/null @@ -1,94 +0,0 @@ -package hunter - -import ( - "strconv" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (hunter *Hunter) getWyvernStrikeConfig(rank int) core.SpellConfig { - spellId := [4]int32{0, 458436, 458481, 458482}[rank] - manaCost := [4]float64{0, 55, 75, 100}[rank] - level := [4]int{0, 1, 50, 60}[rank] - - // The spell tooltips list 3/4/6 on the respective ranks, but Zirene confirmed it's actually 10%. - bleedCoeff := 0.10 - - spellConfig := core.SpellConfig{ - SpellCode: SpellCode_HunterWyvernStrike, - ActionID: core.ActionID{SpellID: spellId}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | SpellFlagStrike, - Rank: rank, - RequiredLevel: level, - - ManaCost: core.ManaCostOptions{ - FlatCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: hunter.NewTimer(), - Duration: time.Second * 8, - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return hunter.MainHand().HandType == proto.HandType_HandTypeTwoHand && hunter.DistanceFromTarget <= core.MaxMeleeAttackDistance - }, - - CritDamageBonus: hunter.mortalShots(), - DamageMultiplier: 1, - BonusCoefficient: 1, - ThreatMultiplier: 1, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: "WyvernStrike - Bleed" + hunter.Label + strconv.Itoa(rank), - Tag: "WyvernStrike - Bleed", - }, - NumberOfTicks: 8, - TickLength: time.Second * 1, - - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - tickDamage := bleedCoeff * hunter.WyvernStrike.MeleeAttackPower() - dot.Snapshot(target, tickDamage, isRollover) - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - weaponDamage := spell.Unit.MHNormalizedWeaponDamage(sim, spell.MeleeAttackPower()) * 1.40 - result := spell.CalcAndDealDamage(sim, target, weaponDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) - - if result.Landed() { - spell.Dot(target).Apply(sim) - } - }, - } - - return spellConfig -} - -func (hunter *Hunter) registerWyvernStrikeSpell() { - if !hunter.Talents.WyvernSting || !hunter.HasRune(proto.HunterRune_RuneBootsWyvernStrike) { - return - } - - rank := map[int32]int{ - 1: 1, - 50: 2, - 60: 3, - }[hunter.Level] - - config := hunter.getWyvernStrikeConfig(rank) - hunter.WyvernStrike = hunter.GetOrRegisterSpell(config) -} From a10a09b2edbeb38bfc87396a9c9655eb627e41b8 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:52:50 -0500 Subject: [PATCH 37/83] Delete sim/hunter/flanking_strike.go --- sim/hunter/flanking_strike.go | 122 ---------------------------------- 1 file changed, 122 deletions(-) delete mode 100644 sim/hunter/flanking_strike.go diff --git a/sim/hunter/flanking_strike.go b/sim/hunter/flanking_strike.go deleted file mode 100644 index 22deb8c43c..0000000000 --- a/sim/hunter/flanking_strike.go +++ /dev/null @@ -1,122 +0,0 @@ -package hunter - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (hunter *Hunter) registerFlankingStrikeSpell() { - if !hunter.HasRune(proto.HunterRune_RuneLegsFlankingStrike) { - return - } - - hasCatlikeReflexes := hunter.HasRune(proto.HunterRune_RuneHelmCatlikeReflexes) - - cooldownModifier := 1.0 - if hasCatlikeReflexes { - cooldownModifier *= 0.5 - } - var affectedSpells []*core.Spell - - hunter.FlankingStrikeAura = hunter.GetOrRegisterAura(core.Aura{ - Label: "Flanking Strike Buff", - ActionID: core.ActionID{SpellID: 415320}, - MaxStacks: 3, - Duration: time.Second * 10, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells = core.FilterSlice(hunter.Spellbook, func(spell *core.Spell) bool { - return spell.ProcMask.Matches(core.ProcMaskMelee) - }) - }, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - for _, spell := range affectedSpells { - spell.DamageMultiplier *= (1 + 0.08*float64(newStacks)) / (1 + 0.08*float64(oldStacks)) - } - }, - }) - - FlankingStrikeResetCodes := map[int32]bool{ - SpellCode_HunterPetBite: true, SpellCode_HunterPetClaw: true, SpellCode_HunterPetLightningBreath: true, SpellCode_HunterPetLavaBreath: true, SpellCode_HunterPetScorpidPoison: true, - } - - if hunter.pet != nil { - hunter.pet.flankingStrike = hunter.pet.GetOrRegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterPetFlankingStrike, - ActionID: core.ActionID{SpellID: 415320}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics, - - DamageMultiplier: 1, - BonusCoefficient: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := spell.Unit.MHWeaponDamage(sim, spell.MeleeAttackPower()) - - spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) - }, - }) - - hunter.pet.RegisterAura(core.Aura{ - Label: "Flanking Strike Refresh", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if FlankingStrikeResetCodes[spell.SpellCode] { - if sim.RandomFloat("Flanking Strike Refresh") < 0.50 { - hunter.FlankingStrike.CD.Set(sim.CurrentTime) - } - } - }, - }) - } - - hunter.FlankingStrike = hunter.GetOrRegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterFlankingStrike, - ActionID: core.ActionID{SpellID: 415320}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | SpellFlagStrike, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.015, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: hunter.NewTimer(), - Duration: time.Second * time.Duration(30*cooldownModifier), - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return hunter.DistanceFromTarget <= core.MaxMeleeAttackDistance - }, - - CritDamageBonus: hunter.mortalShots(), - DamageMultiplier: 1, - BonusCoefficient: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := spell.Unit.MHWeaponDamage(sim, spell.MeleeAttackPower()) - - spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) - - if hunter.pet != nil { - hunter.pet.flankingStrike.Cast(sim, hunter.pet.CurrentTarget) - } - - hunter.FlankingStrikeAura.Activate(sim) - hunter.FlankingStrikeAura.AddStack(sim) - }, - }) -} From 4cccc816adb44f161ccd26383b51bee2ecd19837 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:52:56 -0500 Subject: [PATCH 38/83] Delete sim/hunter/explosive_shot.go --- sim/hunter/explosive_shot.go | 93 ------------------------------------ 1 file changed, 93 deletions(-) delete mode 100644 sim/hunter/explosive_shot.go diff --git a/sim/hunter/explosive_shot.go b/sim/hunter/explosive_shot.go deleted file mode 100644 index 0fe565d9e7..0000000000 --- a/sim/hunter/explosive_shot.go +++ /dev/null @@ -1,93 +0,0 @@ -package hunter - -import ( - "fmt" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (hunter *Hunter) registerExplosiveShotSpell() { - if !hunter.HasRune(proto.HunterRune_RuneHandsExplosiveShot) { - return - } - - actionID := core.ActionID{SpellID: 409552} - numHits := hunter.Env.GetNumTargets() - - baseLowDamage := hunter.baseRuneAbilityDamage() * 0.36 * 1.15 * 1.5 // 15% Buff from 1/3/2024 - verify with new build and update numbers - baseHighDamage := hunter.baseRuneAbilityDamage() * 0.54 * 1.15 * 1.5 // Second 50% buff from 23/4/2024 - - hunter.ExplosiveShot = hunter.RegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterExplosiveShot, - ActionID: actionID, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeRanged, - ProcMask: core.ProcMaskRangedSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagIgnoreResists | core.SpellFlagAPL | SpellFlagShot, - CastType: proto.CastType_CastTypeRanged, - MissileSpeed: 24, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.035, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: hunter.NewTimer(), - Duration: time.Second * 6, - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return hunter.DistanceFromTarget >= core.MinRangedAttackDistance - }, - - CritDamageBonus: hunter.mortalShots(), - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: fmt.Sprintf("ExplosiveShot-%d", actionID.SpellID), - }, - NumberOfTicks: 2, - TickLength: time.Second * 1, - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - baseDamage := sim.Roll(baseLowDamage, baseHighDamage) + 0.039*dot.Spell.RangedAttackPower(target, false) - dot.Snapshot(target, baseDamage, isRollover) - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeSnapshotCrit) - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := sim.Roll(baseLowDamage, baseHighDamage) + 0.039*spell.RangedAttackPower(target, false) - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeRangedHitAndCrit) - - spell.WaitTravelTime(sim, func(s *core.Simulation) { - spell.DealDamage(sim, result) - - if result.Landed() { - curTarget := target - for hitIndex := int32(0); hitIndex < numHits; hitIndex++ { - if curTarget != target { - baseDamage = sim.Roll(baseLowDamage, baseHighDamage) + 0.039*spell.RangedAttackPower(curTarget, false) - spell.CalcAndDealDamage(sim, curTarget, baseDamage, spell.OutcomeRangedCritOnly) - } - - dot := spell.Dot(curTarget) - dot.Apply(sim) - - curTarget = sim.Environment.NextTargetUnit(curTarget) - } - } - }) - }, - }) -} From 2214426545e92487a13a443cb53be8a103ddf5e4 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:53:04 -0500 Subject: [PATCH 39/83] Delete sim/hunter/explosive_trap.go --- sim/hunter/explosive_trap.go | 104 ----------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 sim/hunter/explosive_trap.go diff --git a/sim/hunter/explosive_trap.go b/sim/hunter/explosive_trap.go deleted file mode 100644 index 09b706f51e..0000000000 --- a/sim/hunter/explosive_trap.go +++ /dev/null @@ -1,104 +0,0 @@ -package hunter - -import ( - "strconv" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -func (hunter *Hunter) getExplosiveTrapConfig(rank int, timer *core.Timer) core.SpellConfig { - spellId := [4]int32{0, 409532, 409534, 409535}[rank] - dotDamage := [4]float64{0, 15, 24, 33}[rank] - minDamage := [4]float64{0, 104, 145, 208}[rank] - maxDamage := [4]float64{0, 135, 193, 265}[rank] - manaCost := [4]float64{0, 275, 395, 520}[rank] - level := [4]int{0, 34, 44, 54}[rank] - - numHits := hunter.Env.GetNumTargets() - - return core.SpellConfig{ - SpellCode: SpellCode_HunterExplosiveTrap, - ActionID: core.ActionID{SpellID: spellId}, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: core.SpellFlagAPL | SpellFlagTrap, - Rank: rank, - RequiredLevel: level, - MissileSpeed: 24, - - ManaCost: core.ManaCostOptions{ - FlatCost: manaCost, - }, - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: timer, - Duration: time.Second * 15, - }, - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, // Hunter GCD is locked at 1.5s - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - Dot: core.DotConfig{ - IsAOE: true, - Aura: core.Aura{ - Label: "ExplosiveTrap" + hunter.Label + strconv.Itoa(rank), - Tag: "ExplosiveTrap", - }, - NumberOfTicks: 10, - TickLength: time.Second * 2, - - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - dot.Snapshot(target, dotDamage, isRollover) - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - // Explosive Trap DoT only does damage if the target does not have an immolation trap ticking on them - if !aoeTarget.HasActiveAuraWithTag("ImmolationTrap") { - dot.CalcAndDealPeriodicSnapshotDamage(sim, aoeTarget, dot.OutcomeTick) - } - } - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if hunter.DistanceFromTarget > hunter.trapRange() { - return - } - - spell.WaitTravelTime(sim, func(s *core.Simulation) { - curTarget := target - // Traps gain no benefit from hit bonuses except for the Trap Mastery talent, since this is a unique interaction this is my workaround - spellHit := spell.Unit.GetStat(stats.SpellHit) + target.PseudoStats.BonusSpellHitRatingTaken - spell.Unit.AddStatDynamic(sim, stats.SpellHit, spellHit*-1) - for hitIndex := int32(0); hitIndex < numHits; hitIndex++ { - baseDamage := sim.Roll(minDamage, maxDamage) - baseDamage += hunter.tntDamageFlatBonus() - baseDamage *= sim.Encounter.AOECapMultiplier() - spell.CalcAndDealDamage(sim, curTarget, baseDamage, spell.OutcomeMagicHitAndCrit) - curTarget = sim.Environment.NextTargetUnit(curTarget) - } - spell.Unit.AddStatDynamic(sim, stats.SpellHit, spellHit) - spell.AOEDot().ApplyOrReset(sim) - }) - }, - } -} - -func (hunter *Hunter) registerExplosiveTrapSpell(timer *core.Timer) { - maxRank := 3 - for i := 1; i <= maxRank; i++ { - config := hunter.getExplosiveTrapConfig(i, timer) - - if config.RequiredLevel <= int(hunter.Level) { - hunter.ExplosiveTrap = hunter.GetOrRegisterSpell(config) - } - } -} From 94e5a9061d64e5e83ae42e1f5162260392304186 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:53:27 -0500 Subject: [PATCH 40/83] Delete sim/hunter/kill_shot.go --- sim/hunter/kill_shot.go | 60 ----------------------------------------- 1 file changed, 60 deletions(-) delete mode 100644 sim/hunter/kill_shot.go diff --git a/sim/hunter/kill_shot.go b/sim/hunter/kill_shot.go deleted file mode 100644 index 0132be6af1..0000000000 --- a/sim/hunter/kill_shot.go +++ /dev/null @@ -1,60 +0,0 @@ -package hunter - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (hunter *Hunter) registerKillShotSpell() { - if !hunter.HasRune(proto.HunterRune_RuneLegsKillShot) { - return - } - - baseDamage := 113 / 100 * hunter.baseRuneAbilityDamage() - - hunter.KillShot = hunter.RegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterKillShot, - ActionID: core.ActionID{SpellID: int32(proto.HunterRune_RuneLegsKillShot)}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeRanged, - ProcMask: core.ProcMaskRangedSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | SpellFlagShot, - CastType: proto.CastType_CastTypeRanged, - MissileSpeed: 24, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.03, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, // Hunter GCD is locked at 1.5s - CD: core.Cooldown{ - Timer: hunter.NewTimer(), - Duration: time.Second * 15, - }, - }, - - CritDamageBonus: hunter.mortalShots(), - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if sim.IsExecutePhase20() { - spell.CD.Reset() - } - - damage := hunter.AutoAttacks.Ranged().CalculateWeaponDamage(sim, spell.RangedAttackPower(target, false)) + hunter.AmmoDamageBonus + baseDamage - result := spell.CalcDamage(sim, target, damage, spell.OutcomeRangedHitAndCrit) - - spell.WaitTravelTime(sim, func(s *core.Simulation) { - spell.DealDamage(sim, result) - }) - }, - }) -} From 7ac2d02d78fc3a5e2d441234a4535fd14489a72c Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:53:45 -0500 Subject: [PATCH 41/83] Delete sim/hunter/chimera_shot.go --- sim/hunter/chimera_shot.go | 70 -------------------------------------- 1 file changed, 70 deletions(-) delete mode 100644 sim/hunter/chimera_shot.go diff --git a/sim/hunter/chimera_shot.go b/sim/hunter/chimera_shot.go deleted file mode 100644 index 3423fa8498..0000000000 --- a/sim/hunter/chimera_shot.go +++ /dev/null @@ -1,70 +0,0 @@ -package hunter - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (hunter *Hunter) registerChimeraShotSpell() { - if !hunter.HasRune(proto.HunterRune_RuneHandsChimeraShot) { - return - } - - ssProcSpell := make([]*core.Spell, 10) - for i := 1; i <= 9; i++ { - ssProcSpell[i] = hunter.chimeraShotSerpentStingSpell(i) - } - - hunter.ChimeraShot = hunter.RegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterChimeraShot, - ActionID: core.ActionID{SpellID: 409433}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeRanged, - ProcMask: core.ProcMaskRangedSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagIgnoreResists | core.SpellFlagAPL | SpellFlagShot, - CastType: proto.CastType_CastTypeRanged, - MissileSpeed: 24, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.06, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, // Hunter GCD is locked at 1.5s - CD: core.Cooldown{ - Timer: hunter.NewTimer(), - Duration: time.Second * 6, - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return hunter.DistanceFromTarget >= core.MinRangedAttackDistance - }, - - CritDamageBonus: hunter.mortalShots(), - - DamageMultiplier: 1.35, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := hunter.AutoAttacks.Ranged().CalculateNormalizedWeaponDamage(sim, spell.RangedAttackPower(target, false)) + - hunter.AmmoDamageBonus - - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeRangedHitAndCrit) - - spell.WaitTravelTime(sim, func(s *core.Simulation) { - spell.DealDamage(sim, result) - - if result.Landed() { - if hunter.SerpentSting.Dot(target).IsActive() { - ssProcSpell[hunter.SerpentSting.Rank].Cast(sim, target) - hunter.SerpentSting.Dot(target).Rollover(sim) - } - } - }) - }, - }) -} From f5f1f3e0a3bc4c6c519ad83f37e39b39f28f4767 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:54:21 -0500 Subject: [PATCH 42/83] Update aspects.go --- sim/hunter/aspects.go | 67 ------------------------------------------- 1 file changed, 67 deletions(-) diff --git a/sim/hunter/aspects.go b/sim/hunter/aspects.go index 04fe22b105..ceddc16ab0 100644 --- a/sim/hunter/aspects.go +++ b/sim/hunter/aspects.go @@ -122,73 +122,6 @@ func (hunter *Hunter) registerAspectOfTheHawkSpell() { hunter.GetOrRegisterSpell(config) } -// Configuration for Aspect of the Falcon spell -func (hunter *Hunter) getAspectOfTheFalconSpellConfig() core.SpellConfig { - var impHawkAura *core.Aura - improvedHawkProcChance := 0.01 * float64(hunter.Talents.ImprovedAspectOfTheHawk) - - maxHawkRank := hunter.getMaxHawkRank() - - if hunter.Talents.ImprovedAspectOfTheHawk > 0 { - impHawkAura = hunter.createImprovedHawkAura( - "Quick Strikes", - core.ActionID{SpellID: 469144}, - true, // Melee - ) - } - - // Get the maximum attack power from Aspect of the Hawk for the given level - maxAttackPower := hunter.getMaxAspectOfTheHawkAttackPower(maxHawkRank) - - actionID := core.ActionID{SpellID: 469145} - aspectOfTheFalconAura := hunter.NewTemporaryStatsAuraWrapped( - "Aspect of the Falcon", - actionID, - stats.Stats{ - stats.RangedAttackPower: maxAttackPower, - stats.AttackPower: maxAttackPower, - }, - core.NeverExpires, - func(aura *core.Aura) { - aura.OnSpellHitDealt = func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskMeleeMHAuto) { - return - } - - if impHawkAura != nil && sim.Proc(improvedHawkProcChance, "Imp Aspect of the Hawk") { - impHawkAura.Activate(sim) - } - } - }) - - aspectOfTheFalconAura.NewExclusiveEffect("Aspect", true, core.ExclusiveEffect{}) - - return core.SpellConfig{ - ActionID: actionID, - Flags: core.SpellFlagAPL, - Rank: 1, // Single rank - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return !aspectOfTheFalconAura.IsActive() - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - aspectOfTheFalconAura.Activate(sim) - }, - } -} - -// Register Aspect of the Falcon spell -func (hunter *Hunter) registerAspectOfTheFalconSpell() { - config := hunter.getAspectOfTheFalconSpellConfig() - hunter.GetOrRegisterSpell(config) -} - func (hunter *Hunter) registerAspectOfTheViperSpell() { actionID := core.ActionID{SpellID: 415423} manaMetrics := hunter.NewManaMetrics(actionID) From c73bb7b436bfd56fb513b46baa436cd7d97a81c9 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:54:51 -0500 Subject: [PATCH 43/83] Delete sim/hunter/steady_shot.go --- sim/hunter/steady_shot.go | 60 --------------------------------------- 1 file changed, 60 deletions(-) delete mode 100644 sim/hunter/steady_shot.go diff --git a/sim/hunter/steady_shot.go b/sim/hunter/steady_shot.go deleted file mode 100644 index 1b62539102..0000000000 --- a/sim/hunter/steady_shot.go +++ /dev/null @@ -1,60 +0,0 @@ -package hunter - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (hunter *Hunter) registerSteadyShotSpell() { - if !hunter.HasRune(proto.HunterRune_RuneBeltSteadyShot) { - return - } - - hunter.SteadyShot = hunter.GetOrRegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterSteadyShot, - ActionID: core.ActionID{SpellID: 437123}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeRanged, - ProcMask: core.ProcMaskRangedSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | SpellFlagShot, - CastType: proto.CastType_CastTypeRanged, - MissileSpeed: 24, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.05, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - CastTime: time.Millisecond * 2000, - }, - ModifyCast: func(_ *core.Simulation, spell *core.Spell, cast *core.Cast) { - cast.CastTime = spell.CastTime() - }, - IgnoreHaste: true, // Hunter GCD is locked at 1.5s - CastTime: func(spell *core.Spell) time.Duration { - return time.Duration(float64(spell.DefaultCast.CastTime) / hunter.RangedSwingSpeed()) - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return hunter.DistanceFromTarget >= core.MinRangedAttackDistance - }, - - CritDamageBonus: hunter.mortalShots(), - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := hunter.AutoAttacks.Ranged().CalculateWeaponDamage(sim, spell.RangedAttackPower(target, false)) + - hunter.AmmoDamageBonus - - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeRangedHitAndCrit) - spell.WaitTravelTime(sim, func(s *core.Simulation) { - spell.DealDamage(sim, result) - }) - }, - }) -} From d6095f5e3e664ba5d3a92af5a03fd6b3e310b9a9 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:56:04 -0500 Subject: [PATCH 44/83] Delete sim/hunter/focus_fire.go --- sim/hunter/focus_fire.go | 90 ---------------------------------------- 1 file changed, 90 deletions(-) delete mode 100644 sim/hunter/focus_fire.go diff --git a/sim/hunter/focus_fire.go b/sim/hunter/focus_fire.go deleted file mode 100644 index 4e7b5d03a9..0000000000 --- a/sim/hunter/focus_fire.go +++ /dev/null @@ -1,90 +0,0 @@ -package hunter - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (hunter *Hunter) registerFocusFireSpell() { - if hunter.pet == nil || !hunter.HasRune(proto.HunterRune_RuneBracersFocusFire) { - return - } - - focusFireMetrics := hunter.pet.NewFocusMetrics(core.ActionID{SpellID: int32(proto.HunterRune_RuneBracersFocusFire)}) - focusFireActionId := core.ActionID{SpellID: int32(proto.HunterRune_RuneBracersFocusFire)} - focusFireFrenzyActionId := core.ActionID{SpellID: 428728} - - // For tracking in timeline - hunterFrenzyAura := hunter.RegisterAura(core.Aura{ - Label: "Focus Fire Frenzy (Hunter)", - ActionID: focusFireFrenzyActionId, - Duration: time.Second * 10, - MaxStacks: 5, - }) - - hunterPetFrenzyAura := hunter.pet.RegisterAura(core.Aura{ - Label: "Focus Fire Frenzy", - ActionID: focusFireFrenzyActionId, - Duration: time.Second * 10, - MaxStacks: 5, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks int32, newStacks int32) { - // revert previous attack speed bonus from stacks and apply new attack speed bonus - aura.Unit.MultiplyMeleeSpeed(sim, 1/(1+(0.06*float64(oldStacks)))) - aura.Unit.MultiplyMeleeSpeed(sim, 1+(0.06*float64(newStacks))) - - // this is just so we can see the frenzy stacks working on the sim timeline - if !hunterFrenzyAura.IsActive() { - hunterFrenzyAura.Activate(sim) - } - hunterFrenzyAura.SetStacks(sim, newStacks) - }, - }) - - hunterFocusFireAura := hunter.RegisterAura(core.Aura{ - Label: "Focus Fire", - ActionID: focusFireActionId, - Duration: time.Second * 20, - MaxStacks: 5, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks, newStacks int32) { - aura.Unit.MultiplyRangedSpeed(sim, 1/(1+(0.03*float64(oldStacks)))) - aura.Unit.MultiplyRangedSpeed(sim, 1+(0.03*float64(newStacks))) - }, - }) - - hunter.pet.RegisterAura(core.Aura{ - Label: "Focus Fire Pet", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskMeleeMHSpecial | core.ProcMaskSpellDamage) { - if !hunterPetFrenzyAura.IsActive() { - hunterPetFrenzyAura.Activate(sim) - } - - hunterPetFrenzyAura.AddStack(sim) - hunterPetFrenzyAura.Refresh(sim) - hunterFrenzyAura.Refresh(sim) - } - }, - }) - - hunter.FocusFire = hunter.RegisterSpell(core.SpellConfig{ - ActionID: focusFireActionId, - Flags: core.SpellFlagAPL, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return hunter.pet.IsEnabled() && (hunterPetFrenzyAura.GetStacks() > 0) - }, - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - frenzyStacks := hunterPetFrenzyAura.GetStacks() - hunter.pet.AddFocus(sim, float64(4*frenzyStacks), focusFireMetrics) - - hunterFocusFireAura.Activate(sim) - hunterFocusFireAura.SetStacks(sim, frenzyStacks) - hunterPetFrenzyAura.SetStacks(sim, 0) - }, - }) -} From ed42b85d3d8c0097a6cebf91ab0c0ebce9c06db0 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:58:42 -0500 Subject: [PATCH 45/83] Update hunter.go --- sim/hunter/hunter.go | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/sim/hunter/hunter.go b/sim/hunter/hunter.go index e204bc9aa6..aa9bf9aa33 100644 --- a/sim/hunter/hunter.go +++ b/sim/hunter/hunter.go @@ -24,17 +24,11 @@ const ( // Shots SpellCode_HunterAimedShot SpellCode_HunterArcaneShot - SpellCode_HunterChimeraShot - SpellCode_HunterExplosiveShot - SpellCode_HunterKillShot SpellCode_HunterMultiShot - SpellCode_HunterSteadyShot // Strikes - SpellCode_HunterFlankingStrike SpellCode_HunterRaptorStrike SpellCode_HunterRaptorStrikeHit - SpellCode_HunterWyvernStrike // Stings SpellCode_HunterSerpentSting @@ -45,15 +39,11 @@ const ( SpellCode_HunterImmolationTrap // Other - SpellCode_HunterCarve - SpellCode_HunterCarveHit SpellCode_HunterMongooseBite SpellCode_HunterWingClip SpellCode_HunterVolley - SpellCode_HunterChimeraSerpent // Pet Spells - SpellCode_HunterPetFlankingStrike SpellCode_HunterPetClaw SpellCode_HunterPetBite SpellCode_HunterPetLightningBreath @@ -99,29 +89,18 @@ type Hunter struct { AimedShot *core.Spell ArcaneShot *core.Spell - ChimeraShot *core.Spell - ExplosiveShot *core.Spell ExplosiveTrap *core.Spell ImmolationTrap *core.Spell FreezingTrap *core.Spell KillCommand *core.Spell - KillShot *core.Spell MultiShot *core.Spell - FocusFire *core.Spell RapidFire *core.Spell RaptorStrike *core.Spell - RaptorStrikeMH *core.Spell - RaptorStrikeOH *core.Spell - FlankingStrike *core.Spell - WyvernStrike *core.Spell MongooseBite *core.Spell ScorpidSting *core.Spell SerpentSting *core.Spell SilencingShot *core.Spell - SteadyShot *core.Spell Volley *core.Spell - CarveMH *core.Spell - CarveOH *core.Spell WingClip *core.Spell Shots []*core.Spell @@ -129,19 +108,9 @@ type Hunter struct { MeleeSpells []*core.Spell LastShot *core.Spell - SerpentStingChimeraShot *core.Spell - - FlankingStrikeAura *core.Aura - RaptorFuryAura *core.Aura - SniperTrainingAura *core.Aura - CobraStrikesAura *core.Aura - HitAndRunAura *core.Aura - // The aura that allows you to cast Mongoose Bite DefensiveState *core.Aura - ImprovedSteadyShotAura *core.Aura - LockAndLoadAura *core.Aura RapidFireAura *core.Aura BestialWrathPetAura *core.Aura } @@ -193,7 +162,6 @@ func (hunter *Hunter) Initialize() { }) hunter.registerAspectOfTheHawkSpell() - hunter.registerAspectOfTheFalconSpell() hunter.registerAspectOfTheViperSpell() multiShotTimer := hunter.NewTimer() @@ -204,16 +172,9 @@ func (hunter *Hunter) Initialize() { hunter.registerArcaneShotSpell(arcaneShotTimer) hunter.registerAimedShotSpell(arcaneShotTimer) hunter.registerMultiShotSpell(multiShotTimer) - hunter.registerExplosiveShotSpell() - hunter.registerChimeraShotSpell() - hunter.registerSteadyShotSpell() - hunter.registerKillShotSpell() hunter.registerRaptorStrikeSpell() - hunter.registerFlankingStrikeSpell() - hunter.registerWyvernStrikeSpell() hunter.registerMongooseBiteSpell() - hunter.registerCarveSpell() hunter.registerWingClipSpell() hunter.registerVolleySpell() @@ -225,7 +186,6 @@ func (hunter *Hunter) Initialize() { // hunter.registerKillCommand() hunter.registerRapidFire() - hunter.registerFocusFireSpell() } func (hunter *Hunter) Reset(sim *core.Simulation) { From 747cbde7aa306dfdd2521d7126ae7b5735b6b278 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:00:03 -0500 Subject: [PATCH 46/83] Update hunter.go --- sim/hunter/hunter.go | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/sim/hunter/hunter.go b/sim/hunter/hunter.go index aa9bf9aa33..957fde5410 100644 --- a/sim/hunter/hunter.go +++ b/sim/hunter/hunter.go @@ -87,21 +87,22 @@ type Hunter struct { curQueueAura *core.Aura curQueuedAutoSpell *core.Spell - AimedShot *core.Spell - ArcaneShot *core.Spell - ExplosiveTrap *core.Spell - ImmolationTrap *core.Spell - FreezingTrap *core.Spell - KillCommand *core.Spell - MultiShot *core.Spell - RapidFire *core.Spell - RaptorStrike *core.Spell - MongooseBite *core.Spell - ScorpidSting *core.Spell - SerpentSting *core.Spell - SilencingShot *core.Spell - Volley *core.Spell - WingClip *core.Spell + AimedShot *core.Spell + ArcaneShot *core.Spell + ExplosiveTrap *core.Spell + ImmolationTrap *core.Spell + FreezingTrap *core.Spell + KillCommand *core.Spell + MultiShot *core.Spell + RapidFire *core.Spell + RaptorStrike *core.Spell + RaptorStrikeHit *core.Spell + MongooseBite *core.Spell + ScorpidSting *core.Spell + SerpentSting *core.Spell + SilencingShot *core.Spell + Volley *core.Spell + WingClip *core.Spell Shots []*core.Spell Strikes []*core.Spell From 67a24e309f5e05ca5cbe21b5f1366212b6cdc494 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:05:13 -0500 Subject: [PATCH 47/83] Update raptor_strike.go --- sim/hunter/raptor_strike.go | 81 ++++++------------------------------- 1 file changed, 12 insertions(+), 69 deletions(-) diff --git a/sim/hunter/raptor_strike.go b/sim/hunter/raptor_strike.go index 6c0baa9552..6f9df311d4 100644 --- a/sim/hunter/raptor_strike.go +++ b/sim/hunter/raptor_strike.go @@ -24,23 +24,18 @@ func (hunter *Hunter) TryRaptorStrike(sim *core.Simulation, mhSwingSpell *core.S } func (hunter *Hunter) getRaptorStrikeConfig(rank int) core.SpellConfig { - hasRaptorFury := hunter.HasRune(proto.HunterRune_RuneBracersRaptorFury) - hasDualWieldSpec := hunter.HasRune(proto.HunterRune_RuneBootsDualWieldSpecialization) - hasMeleeSpecialist := hunter.HasRune(proto.HunterRune_RuneBeltMeleeSpecialist) - - spellID := core.Ternary(hasMeleeSpecialist, RaptorStrikeSpellIdMeleeSpecialist, RaptorStrikeSpellId)[rank] + spellID := RaptorStrikeSpellId[rank] manaCost := RaptorStrikeManaCost[rank] level := RaptorStrikeLevel[rank] - hunter.RaptorStrikeMH = hunter.newRaptorStrikeHitSpell(rank, true) - hunter.RaptorStrikeOH = hunter.newRaptorStrikeHitSpell(rank, false) + hunter.RaptorStrikeHit = hunter.newRaptorStrikeHitSpell(rank) spellConfig := core.SpellConfig{ SpellCode: SpellCode_HunterRaptorStrike, ActionID: core.ActionID{SpellID: spellID}, SpellSchool: core.SpellSchoolPhysical, DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, + ProcMask: core.ProcMaskMeleeMHSpecial | core.ProcMaskMeleeMHAuto, Flags: core.SpellFlagMeleeMetrics | SpellFlagStrike, Rank: rank, RequiredLevel: level, @@ -60,85 +55,37 @@ func (hunter *Hunter) getRaptorStrikeConfig(rank int) core.SpellConfig { }, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - hunter.RaptorStrikeMH.Cast(sim, target) - if hasDualWieldSpec && hunter.AutoAttacks.IsDualWielding { - hunter.RaptorStrikeOH.Cast(sim, target) - } + hunter.RaptorStrikeHit.Cast(sim, target) if hunter.curQueueAura != nil { hunter.curQueueAura.Deactivate(sim) } - - if hasMeleeSpecialist && sim.Proc(0.3, "Raptor Strike Reset") { - spell.CD.Reset() - hunter.MongooseBite.CD.Reset() - } - - if hasRaptorFury { - if !hunter.RaptorFuryAura.IsActive() { - hunter.RaptorFuryAura.Activate(sim) - } - hunter.RaptorFuryAura.AddStack(sim) - } }, } - if hasMeleeSpecialist { - spellConfig.Flags |= core.SpellFlagAPL - spellConfig.Cast.DefaultCast = core.Cast{ - GCD: core.GCDDefault, - } - } else { - spellConfig.ProcMask |= core.ProcMaskMeleeMHAuto - } - return spellConfig } -func (hunter *Hunter) newRaptorStrikeHitSpell(rank int, isMH bool) *core.Spell { - hasMeleeSpecialist := hunter.HasRune(proto.HunterRune_RuneBeltMeleeSpecialist) - hasRaptorFury := hunter.HasRune(proto.HunterRune_RuneBracersRaptorFury) - hasHitAndRun := hunter.HasRune(proto.HunterRune_RuneCloakHitAndRun) - - spellID := core.Ternary(hasMeleeSpecialist, RaptorStrikeSpellIdMeleeSpecialist, RaptorStrikeSpellId)[rank] +func (hunter *Hunter) newRaptorStrikeHitSpell(rank int) *core.Spell { + spellID := RaptorStrikeSpellId[rank] baseDamage := RaptorStrikeBaseDamage[rank] - - procMask := core.ProcMaskMeleeMHSpecial - damageMultiplier := 1.0 - damageFunc := core.Ternary(hasMeleeSpecialist, hunter.MHNormalizedWeaponDamage, hunter.MHWeaponDamage) - - if !isMH { - baseDamage /= 2 - procMask = core.ProcMaskMeleeOHSpecial - damageMultiplier = hunter.AutoAttacks.OHConfig().DamageMultiplier - damageFunc = core.Ternary(hasMeleeSpecialist, hunter.OHNormalizedWeaponDamage, hunter.OHWeaponDamage) - } + damageFunc := hunter.MHWeaponDamage return hunter.RegisterSpell(core.SpellConfig{ SpellCode: SpellCode_HunterRaptorStrikeHit, - ActionID: core.ActionID{SpellID: spellID}.WithTag(core.TernaryInt32(isMH, 1, 2)), + ActionID: core.ActionID{SpellID: spellID}, SpellSchool: core.SpellSchoolPhysical, DefenseType: core.DefenseTypeMelee, - ProcMask: procMask, + ProcMask: core.ProcMaskMeleeMHSpecial, Flags: core.SpellFlagMeleeMetrics | core.SpellFlagNoOnCastComplete, BonusCritRating: float64(hunter.Talents.SavageStrikes) * 10 * core.CritRatingPerCritChance, CritDamageBonus: hunter.mortalShots(), - DamageMultiplier: damageMultiplier, + DamageMultiplier: 1, BonusCoefficient: 1, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if hasHitAndRun { - hunter.HitAndRunAura.Activate(sim) - } - - multiplier := 1.0 - if hasRaptorFury { - multiplier *= hunter.raptorFuryDamageMultiplier() - } - - weaponDamage := damageFunc(sim, spell.MeleeAttackPower()) - damage := multiplier * (weaponDamage + baseDamage) + damage := baseDamage + hunter.MHWeaponDamage(sim, spell.MeleeAttackPower()) spell.CalcAndDealDamage(sim, target, damage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) }, }) @@ -194,11 +141,7 @@ func (hunter *Hunter) registerRaptorStrikeSpell() { 60: 8, }[hunter.Level] - hasMeleeSpecialist := hunter.HasRune(proto.HunterRune_RuneBeltMeleeSpecialist) config := hunter.getRaptorStrikeConfig(rank) hunter.RaptorStrike = hunter.GetOrRegisterSpell(config) - - if !hasMeleeSpecialist { - hunter.makeQueueSpellsAndAura() - } + hunter.makeQueueSpellsAndAura() } From b63169f19abaa77ebf0ea5fd32c88a286994406b Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:05:42 -0500 Subject: [PATCH 48/83] Update action_id.ts --- ui/core/proto_utils/action_id.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/core/proto_utils/action_id.ts b/ui/core/proto_utils/action_id.ts index 3419465e36..735a76a243 100644 --- a/ui/core/proto_utils/action_id.ts +++ b/ui/core/proto_utils/action_id.ts @@ -415,8 +415,7 @@ export class ActionId { else if (this.spellId === 427066) name = `${name} (Wrecking Crew)`; break; case 'Raptor Strike': - if (this.tag === 1) name = `${name} (Main-Hand)`; - else if (this.tag === 2) name = `${name} (Off-Hand)`; + if (this.tag === 1) name = `${name} (Hit)`; else if (this.tag === 3) name = `${name} (Queue)`; break; case 'Thunderfury': From beefaf15d398de52a9128729cd523409c006dc15 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:06:05 -0500 Subject: [PATCH 49/83] Update raptor_strike.go --- sim/hunter/raptor_strike.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/hunter/raptor_strike.go b/sim/hunter/raptor_strike.go index 6f9df311d4..4c8cc4a6a6 100644 --- a/sim/hunter/raptor_strike.go +++ b/sim/hunter/raptor_strike.go @@ -73,7 +73,7 @@ func (hunter *Hunter) newRaptorStrikeHitSpell(rank int) *core.Spell { return hunter.RegisterSpell(core.SpellConfig{ SpellCode: SpellCode_HunterRaptorStrikeHit, - ActionID: core.ActionID{SpellID: spellID}, + ActionID: core.ActionID{SpellID: spellID}.WithTag(1), SpellSchool: core.SpellSchoolPhysical, DefenseType: core.DefenseTypeMelee, ProcMask: core.ProcMaskMeleeMHSpecial, From c72ba4d56f8cba0846a4e609d3f325f8966577a6 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:07:05 -0500 Subject: [PATCH 50/83] Update pet.go --- sim/hunter/pet.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sim/hunter/pet.go b/sim/hunter/pet.go index 2355b755ff..77d35b7301 100644 --- a/sim/hunter/pet.go +++ b/sim/hunter/pet.go @@ -21,8 +21,6 @@ type HunterPet struct { specialAbility *core.Spell focusDump *core.Spell - flankingStrike *core.Spell - uptimePercent float64 hasOwnerCooldown bool } @@ -242,7 +240,7 @@ func (hp *HunterPet) ExecuteCustomRotation(sim *core.Simulation) { if hp.config.CustomRotation != nil { hp.config.CustomRotation(sim, hp, tryCast) } else { - if hp.specialAbility.IsReady(sim) && hp.flankingStrike == nil { + if hp.specialAbility.IsReady(sim) { if !tryCast(hp.specialAbility) && hp.GCD.IsReady(sim) { hp.WaitUntil(sim, sim.CurrentTime+time.Millisecond*500) } From f2c3117ab2f9a8f0243a46d2562d77c7e2e136e9 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:07:39 -0500 Subject: [PATCH 51/83] Update volley.go --- sim/hunter/volley.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sim/hunter/volley.go b/sim/hunter/volley.go index 73cf7ebf06..1caa8ee2e9 100644 --- a/sim/hunter/volley.go +++ b/sim/hunter/volley.go @@ -28,14 +28,8 @@ func (hunter *Hunter) getVolleyConfig(rank int) core.SpellConfig { manaCost := [4]float64{0, 350, 420, 490}[rank] level := [4]int{0, 40, 50, 58}[rank] - hasImprovedVolley := hunter.HasRune(proto.HunterRune_RuneCloakImprovedVolley) - manaCostModifer := 100 - 2*hunter.Talents.Efficiency - if hasImprovedVolley { - manaCostModifer -= 50 - } - return core.SpellConfig{ SpellCode: SpellCode_HunterVolley, ActionID: core.ActionID{SpellID: spellId}, @@ -70,9 +64,6 @@ func (hunter *Hunter) getVolleyConfig(rank int) core.SpellConfig { BonusCoefficient: .056, OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { damage := baseDamage - if hasImprovedVolley { - damage += hunter.GetStat(stats.RangedAttackPower) * 0.03 - } dot.Snapshot(target, damage, isRollover) }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { @@ -87,9 +78,6 @@ func (hunter *Hunter) getVolleyConfig(rank int) core.SpellConfig { ThreatMultiplier: 1, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if hasImprovedVolley { - spell.CD.Reset() - } hunter.Unit.AutoAttacks.DelayRangedUntil(sim, sim.CurrentTime+(time.Second*6)) spell.AOEDot().Apply(sim) }, From dfe7b416675cb675065e90f4b8da1693f9d66dbd Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:08:03 -0500 Subject: [PATCH 52/83] Delete sim/shaman/ancestral_awakening.go --- sim/shaman/ancestral_awakening.go | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 sim/shaman/ancestral_awakening.go diff --git a/sim/shaman/ancestral_awakening.go b/sim/shaman/ancestral_awakening.go deleted file mode 100644 index 28b51520d8..0000000000 --- a/sim/shaman/ancestral_awakening.go +++ /dev/null @@ -1,29 +0,0 @@ -package shaman - -import ( - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -const AncestralAwakeningHealMultiplier = 0.3 - -func (shaman *Shaman) applyAncestralAwakening() { - if !shaman.HasRune(proto.ShamanRune_RuneFeetAncestralAwakening) { - return - } - - shaman.AncestralAwakening = shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: int32(proto.ShamanRune_RuneFeetAncestralAwakening)}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellHealing, - Flags: SpellFlagShaman | core.SpellFlagHelpful | core.SpellFlagAPL, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealHealing(sim, target, shaman.ancestralHealingAmount*(1+shaman.purificationHealingModifier()), spell.OutcomeHealing) - }, - }) -} From 4e0b473a43763f763961a954b60fea4eb7137d65 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:08:11 -0500 Subject: [PATCH 53/83] Delete sim/shaman/earth_shield.go --- sim/shaman/earth_shield.go | 71 -------------------------------------- 1 file changed, 71 deletions(-) delete mode 100644 sim/shaman/earth_shield.go diff --git a/sim/shaman/earth_shield.go b/sim/shaman/earth_shield.go deleted file mode 100644 index 876162375f..0000000000 --- a/sim/shaman/earth_shield.go +++ /dev/null @@ -1,71 +0,0 @@ -package shaman - -// import ( -// "time" - -// "github.com/wowsims/classic/sim/core" -// "github.com/wowsims/classic/sim/core/proto" -// ) - -// func (shaman *Shaman) registerEarthShieldSpell() { -// if !shaman.HasRune(proto.ShamanRune_RuneLegsEarthShield) { -// return -// } - -// actionID := core.ActionID{SpellID: 49284} -// spCoeff := 0.286 - -// icd := core.Cooldown{ -// Timer: shaman.NewTimer(), -// Duration: time.Millisecond * 3500, -// } - -// shaman.EarthShield = shaman.RegisterSpell(core.SpellConfig{ -// ActionID: actionID, -// SpellSchool: core.SpellSchoolNature, -// DefenseType: core.DefenseTypeMagic, -// ProcMask: core.ProcMaskEmpty, -// Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagShaman, - -// Cast: core.CastConfig{ -// DefaultCast: core.Cast{ -// GCD: core.GCDDefault, -// }, -// }, - -// Hot: core.DotConfig{ -// Aura: core.Aura{ -// Label: "Earth Shield", -// ActionID: core.ActionID{SpellID: 379}, -// OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { -// if !result.Landed() { -// return -// } -// if !icd.IsReady(sim) { -// return -// } -// icd.Use(sim) -// shaman.EarthShield.Hot(result.Target).ManualTick(sim) -// }, -// OnExpire: func(aura *core.Aura, sim *core.Simulation) { -// }, -// }, -// NumberOfTicks: 6 + shaman.Talents.ImprovedEarthShield, -// TickLength: time.Minute*10 + 1, // tick length longer than expire time. -// OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, _ bool) { -// dot.SnapshotBaseDamage = 377 + dot.Spell.HealingPower(target)*spCoeff -// dot.SnapshotAttackerMultiplier = dot.Spell.CasterHealingMultiplier() -// }, -// OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { -// dot.CalcAndDealPeriodicSnapshotHealing(sim, target, dot.OutcomeTick) -// }, -// }, - -// DamageMultiplier: 1 -// ThreatMultiplier: 1, - -// ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { -// spell.Hot(target).Apply(sim) -// }, -// }) -// } From d8d0bc38e2db84478ef4accfad164f8c46d85798 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:08:18 -0500 Subject: [PATCH 54/83] Delete sim/shaman/ancestral_guidance.go --- sim/shaman/ancestral_guidance.go | 96 -------------------------------- 1 file changed, 96 deletions(-) delete mode 100644 sim/shaman/ancestral_guidance.go diff --git a/sim/shaman/ancestral_guidance.go b/sim/shaman/ancestral_guidance.go deleted file mode 100644 index 5432041d22..0000000000 --- a/sim/shaman/ancestral_guidance.go +++ /dev/null @@ -1,96 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (shaman *Shaman) applyAncestralGuidance() { - if !shaman.HasRune(proto.ShamanRune_RuneLegsAncestralGuidance) { - return - } - - actionID := core.ActionID{SpellID: int32(proto.ShamanRune_RuneLegsAncestralGuidance)} - duration := time.Second * 10 - cooldown := time.Minute * 1 - - damageConversion := .25 // 25% - healingConversion := 1.0 // 100% - numHealedAllies := int32(3) - - agDamageSpell := shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 409337}, // AG Damage has its own Spell ID - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagShaman | core.SpellFlagIgnoreResists, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - }) - - agHealSpell := shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 409333}, // AG Damage has its own Spell ID - SpellSchool: core.SpellSchoolNature, - ProcMask: core.ProcMaskSpellHealing, - Flags: SpellFlagShaman | core.SpellFlagHelpful, - }) - - agAura := shaman.RegisterAura(core.Aura{ - Label: "Ancestral Guidance", - ActionID: actionID, - Duration: duration, - - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell == agDamageSpell || spell.ProcMask != core.ProcMaskSpellDamage { - return - } - - targets := sim.Environment.Raid.GetFirstNPlayersOrPets(numHealedAllies) - - for hitIndex := int32(0); hitIndex < int32(len(targets)); hitIndex++ { - target := targets[hitIndex] - baseHealing := result.Damage * damageConversion - agHealSpell.CalcAndDealHealing(sim, target, baseHealing, spell.OutcomeHealingCrit) - } - }, - OnHealDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell == agHealSpell || shaman.lastFlameShockTarget == nil { - return - } - - baseDamage := result.Damage * healingConversion - agDamageSpell.CalcAndDealDamage(sim, shaman.lastFlameShockTarget, baseDamage, spell.OutcomeMagicHitAndCrit) - }, - }) - - agCDSpell := shaman.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolNature, - Flags: SpellFlagShaman | core.SpellFlagAPL | core.SpellFlagNoOnCastComplete, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: shaman.NewTimer(), - Duration: cooldown, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - agAura.Activate(sim) - }, - }) - - shaman.AddMajorCooldown(core.MajorCooldown{ - Spell: agCDSpell, - Type: core.CooldownTypeDPS | core.CooldownTypeSurvival, - ShouldActivate: func(sim *core.Simulation, character *core.Character) bool { - return character.CurrentManaPercent() <= 0.2 - }, - }) -} From 40aa481f838711931b537f3d6ab4062ac9305834 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:08:39 -0500 Subject: [PATCH 55/83] Update air_totems.go --- sim/shaman/air_totems.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sim/shaman/air_totems.go b/sim/shaman/air_totems.go index 46755f28a4..3fb5971979 100644 --- a/sim/shaman/air_totems.go +++ b/sim/shaman/air_totems.go @@ -81,13 +81,8 @@ func (shaman *Shaman) newGraceOfAirTotemSpellConfig(rank int) core.SpellConfig { duration := time.Second * 120 multiplier := []float64{1, 1.08, 1.15}[shaman.Talents.EnhancingTotems] - hasFeralSpirit := shaman.HasRune(proto.ShamanRune_RuneCloakFeralSpirit) - graceOfAirTotemAuras := make([]*core.Aura, core.TernaryInt32(hasFeralSpirit, 2, 1)) graceOfAirTotemAuras[0] = core.GraceOfAirTotemAura(&shaman.Unit, multiplier) - if hasFeralSpirit { - graceOfAirTotemAuras[1] = core.GraceOfAirTotemAura(&shaman.SpiritWolves.Unit, multiplier) - } spell := shaman.newTotemSpellConfig(manaCost, spellId) spell.RequiredLevel = level From 2510410ce670ce70ca44d3fb2b8e534f8d59ca1d Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:08:45 -0500 Subject: [PATCH 56/83] Delete sim/shaman/bloodlust.go --- sim/shaman/bloodlust.go | 72 ----------------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 sim/shaman/bloodlust.go diff --git a/sim/shaman/bloodlust.go b/sim/shaman/bloodlust.go deleted file mode 100644 index b2de3685d0..0000000000 --- a/sim/shaman/bloodlust.go +++ /dev/null @@ -1,72 +0,0 @@ -package shaman - -// import ( -// "github.com/wowsims/classic/sim/core" -// ) - -// func (shaman *Shaman) BloodlustActionID() core.ActionID { -// return core.ActionID{ -// SpellID: 2825, -// Tag: shaman.Index, -// } -// } - -// func (shaman *Shaman) registerBloodlustCD() { -// actionID := shaman.BloodlustActionID() - -// blAuras := []*core.Aura{} -// for _, party := range shaman.Env.Raid.Parties { -// for _, partyMember := range party.Players { -// blAuras = append(blAuras, core.BloodlustAura(partyMember.GetCharacter(), actionID.Tag)) -// } -// } - -// shaman.RegisterSpell(core.SpellConfig{ -// ActionID: actionID, -// Flags: core.SpellFlagAPL, - -// ManaCost: core.ManaCostOptions{ -// BaseCost: 0.26, -// Multiplier: 1 - 0.02*float64(shaman.Talents.MentalQuickness), -// }, -// Cast: core.CastConfig{ -// DefaultCast: core.Cast{ -// GCD: core.GCDDefault, -// }, -// CD: core.Cooldown{ -// Timer: shaman.NewTimer(), -// Duration: core.BloodlustCD, -// }, -// }, -// ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { -// // Need to check if any raid member has lust, not just self, because of -// // major CD ordering issues with the shared bloodlust. - -// // If all players in all parties already have sated, don't cast. -// allSated := true -// for _, party := range shaman.Env.Raid.Parties { -// for _, partyMember := range party.Players { -// // If anyone currently has bloodlust, don't cast this. -// if partyMember.GetCharacter().HasActiveAuraWithTag(core.BloodlustAuraTag) { -// return false -// } -// if !partyMember.GetCharacter().HasActiveAura(core.SatedAuraLabel) { -// allSated = false -// } -// } -// } -// return true && !allSated -// }, - -// ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { -// for _, blAura := range blAuras { -// target := blAura.Unit -// // Only activate bloodlust on units without bloodlust and without sated. -// if !target.HasActiveAura(core.SatedAuraLabel) && !target.HasActiveAuraWithTag(core.BloodlustAuraTag) { -// blAura.Activate(sim) -// } - -// } -// }, -// }) -// } From 353489c640744609658f92cb1d004aa1d35c08d5 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:08:53 -0500 Subject: [PATCH 57/83] Delete sim/shaman/fire_nova.go --- sim/shaman/fire_nova.go | 81 ----------------------------------------- 1 file changed, 81 deletions(-) delete mode 100644 sim/shaman/fire_nova.go diff --git a/sim/shaman/fire_nova.go b/sim/shaman/fire_nova.go deleted file mode 100644 index 0562e036b8..0000000000 --- a/sim/shaman/fire_nova.go +++ /dev/null @@ -1,81 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -var FireNovaSpellId = [FireNovaTotemRanks + 1]int32{0, 408341, 408342, 408343, 408427, 408345} -var FireNovaSpellCoeff = [FireNovaTotemRanks + 1]float64{0, .214, .214, .214, .214, .214} - -func (shaman *Shaman) applyFireNova() { - if !shaman.HasRune(proto.ShamanRune_RuneWaistFireNova) { - return - } - - for rank := FireNovaTotemRanks; rank >= 1; rank-- { - config := shaman.newFireNovaSpellConfig(rank) - - if config.RequiredLevel <= int(shaman.Level) { - shaman.FireNova = shaman.RegisterSpell(config) - return - } - } -} - -func (shaman *Shaman) newFireNovaSpellConfig(rank int) core.SpellConfig { - spellId := FireNovaSpellId[rank] - baseDamageLow := FireNovaTotemBaseDamage[rank][0] - baseDamageHigh := FireNovaTotemBaseDamage[rank][1] - spellCoeff := FireNovaTotemSpellCoeff[rank] - cooldown := time.Second * 10 - manaCost := .22 - level := FireNovaTotemLevel[rank] - - spell := core.SpellConfig{ - ActionID: core.ActionID{SpellID: spellId}, - SpellCode: SpellCode_ShamanFireNova, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagShaman | core.SpellFlagAPL, - - RequiredLevel: level, - Rank: rank, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: shaman.NewTimer(), - Duration: cooldown, - }, - }, - - DamageMultiplier: shaman.callOfFlameMultiplier(), - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for _, aoeTarget := range sim.Encounter.TargetUnits { - baseDamage := sim.Roll(baseDamageLow, baseDamageHigh) - result := spell.CalcDamage(sim, aoeTarget, baseDamage, spell.OutcomeMagicCrit) - - spell.DealDamage(sim, result) - } - }, - - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return shaman.ActiveTotems[FireTotem] != nil - }, - } - - return spell -} From a1a29f566eabb57423d6e2eb15ca8b4dd750119b Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:09:00 -0500 Subject: [PATCH 58/83] Delete sim/shaman/feral_spirit.go --- sim/shaman/feral_spirit.go | 54 -------------------------------------- 1 file changed, 54 deletions(-) delete mode 100644 sim/shaman/feral_spirit.go diff --git a/sim/shaman/feral_spirit.go b/sim/shaman/feral_spirit.go deleted file mode 100644 index 573d8036dc..0000000000 --- a/sim/shaman/feral_spirit.go +++ /dev/null @@ -1,54 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (shaman *Shaman) registerFeralSpiritCD() { - if !shaman.HasRune(proto.ShamanRune_RuneCloakFeralSpirit) { - return - } - - actionID := core.ActionID{SpellID: int32(proto.ShamanRune_RuneCloakFeralSpirit)} - - spiritWolvesActiveAura := shaman.RegisterAura(core.Aura{ - Label: "Feral Spirit", - ActionID: actionID, - Duration: time.Second * 45, - }) - - shaman.FeralSpirit = shaman.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: SpellFlagShaman, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.12, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: shaman.NewTimer(), - Duration: time.Minute * 3, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - shaman.SpiritWolves.EnableWithTimeout(sim, shaman.SpiritWolves, time.Second*45) - shaman.SpiritWolves.CancelGCDTimer(sim) - - // Add a dummy aura to show in metrics - spiritWolvesActiveAura.Activate(sim) - }, - }) - - shaman.AddMajorCooldown(core.MajorCooldown{ - Spell: shaman.FeralSpirit, - Type: core.CooldownTypeDPS, - }) -} From ffa21803f4ab31626df44da2762912f39f654263 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:09:10 -0500 Subject: [PATCH 59/83] Delete sim/shaman/lava_burst.go --- sim/shaman/lava_burst.go | 111 --------------------------------------- 1 file changed, 111 deletions(-) delete mode 100644 sim/shaman/lava_burst.go diff --git a/sim/shaman/lava_burst.go b/sim/shaman/lava_burst.go deleted file mode 100644 index 2d3e9e8b99..0000000000 --- a/sim/shaman/lava_burst.go +++ /dev/null @@ -1,111 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (shaman *Shaman) registerLavaBurstSpell() { - if !shaman.HasRune(proto.ShamanRune_RuneHandsLavaBurst) { - return - } - - shaman.LavaBurst = shaman.RegisterSpell(shaman.newLavaBurstSpellConfig(false)) - - if shaman.HasRune(proto.ShamanRune_RuneChestOverload) { - shaman.LavaBurstOverload = shaman.RegisterSpell(shaman.newLavaBurstSpellConfig(true)) - } -} - -func (shaman *Shaman) newLavaBurstSpellConfig(isOverload bool) core.SpellConfig { - hasMaelstromWeaponRune := shaman.HasRune(proto.ShamanRune_RuneWaistMaelstromWeapon) - - baseDamageLow := shaman.baseRuneAbilityDamage() * 4.69 - baseDamageHigh := shaman.baseRuneAbilityDamage() * 6.05 - spellCoeff := .571 - castTime := time.Second * 2 - cooldown := time.Second * 8 - manaCost := .10 - - flags := SpellFlagShaman - if !isOverload { - flags |= core.SpellFlagAPL | SpellFlagMaelstrom - } - - canOverload := !isOverload && shaman.HasRune(proto.ShamanRune_RuneChestOverload) - - spell := core.SpellConfig{ - SpellCode: SpellCode_ShamanLavaBurst, - ActionID: core.ActionID{SpellID: int32(proto.ShamanRune_RuneHandsLavaBurst)}, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: flags, - MissileSpeed: 20, - MetricSplits: 6, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - // Convection does not currently apply to Lava Burst in SoD - // Multiplier: 1 - 0.02*float64(shaman.Talents.Convection), - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - // Lightning Mastery does not currently apply to Lava Burst in SoD - // CastTime: time.Second*2 - time.Millisecond*200*time.Duration(shaman.Talents.LightningMastery), - CastTime: castTime, - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: shaman.NewTimer(), - Duration: cooldown, - }, - ModifyCast: func(sim *core.Simulation, spell *core.Spell, cast *core.Cast) { - castTime := shaman.ApplyCastSpeedForSpell(cast.CastTime, spell) - if hasMaelstromWeaponRune { - stacks := shaman.MaelstromWeaponAura.GetStacks() - spell.SetMetricsSplit(stacks) - - if stacks > 0 { - return - } - } - - shaman.AutoAttacks.StopMeleeUntil(sim, sim.CurrentTime+castTime, false) - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := sim.Roll(baseDamageLow, baseDamageHigh) - - damageMultiplier := 0.0 - if shaman.useLavaBurstCritScaling { - damageMultiplier = shaman.GetStat(stats.SpellCrit) * core.SpellCritRatingPerCritChance / 100 - } - spell.DamageMultiplierAdditive += damageMultiplier - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - spell.DamageMultiplierAdditive -= damageMultiplier - - spell.WaitTravelTime(sim, func(sim *core.Simulation) { - spell.DealDamage(sim, result) - - if canOverload && sim.RandomFloat("LvB Overload") < ShamanOverloadChance { - shaman.LavaBurstOverload.Cast(sim, target) - } - }) - }, - } - - if isOverload { - shaman.applyOverloadModifiers(&spell) - } - - return spell -} From 0cb89e601f925982a1c6a556a476e351d7585ffb Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:10:50 -0500 Subject: [PATCH 60/83] Update talents.go --- sim/druid/talents.go | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/sim/druid/talents.go b/sim/druid/talents.go index 7bf71151a6..72aa9c7e97 100644 --- a/sim/druid/talents.go +++ b/sim/druid/talents.go @@ -280,8 +280,7 @@ func (druid *Druid) applyOmenOfClarity() { return } - // Hotfix 2024-04-13 Starsurge does not consume clearcasting - if spell.Flags.Matches(SpellFlagOmen) && spell.SpellCode != SpellCode_DruidStarsurge && spell.DefaultCast.Cost > 0 { + if spell.Flags.Matches(SpellFlagOmen) && spell.DefaultCast.Cost > 0 { aura.Deactivate(sim) } }, @@ -328,8 +327,6 @@ func (druid *Druid) applyMoonfury() { druid.Wrath, druid.Starfire, druid.Moonfire, - {druid.Starsurge}, - {druid.Sunfire}, }, ), func(spell *DruidSpell) bool { return spell != nil }, @@ -354,25 +351,12 @@ func (druid *Druid) applyImprovedMoonfire() { Label: "Improved moonfire", OnInit: func(aura *core.Aura, sim *core.Simulation) { damageAffectedSpells := core.FilterSlice( - core.Flatten( - [][]*DruidSpell{ - druid.Moonfire, - {druid.Sunfire}, - }, - ), + druid.Moonfire, func(spell *DruidSpell) bool { return spell != nil }, ) critAffectedSpells := core.FilterSlice( - core.Flatten( - [][]*DruidSpell{ - druid.Moonfire, - {druid.Sunfire}, - // Starfall only receives the bonus crit, not damage - {druid.StarfallTick}, - {druid.StarfallSplash}, - }, - ), + druid.Moonfire, func(spell *DruidSpell) bool { return spell != nil }, ) @@ -403,10 +387,6 @@ func (druid *Druid) applyVengeance() { druid.Wrath, druid.Starfire, druid.Moonfire, - {druid.Starsurge}, - {druid.Sunfire}, - {druid.StarfallTick}, - {druid.StarfallSplash}, }, ), func(spell *DruidSpell) bool { return spell != nil }, @@ -435,8 +415,6 @@ func (druid *Druid) applyMoonglow() { druid.Wrath, druid.Starfire, druid.Moonfire, - {druid.Starsurge}, - {druid.Starfall}, }, ), func(spell *DruidSpell) bool { return spell != nil }, From 57eb145874256fd93658a073ca7b259f0675aa1f Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:11:15 -0500 Subject: [PATCH 61/83] Delete sim/shaman/lava_lash.go --- sim/shaman/lava_lash.go | 62 ----------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 sim/shaman/lava_lash.go diff --git a/sim/shaman/lava_lash.go b/sim/shaman/lava_lash.go deleted file mode 100644 index 447a24c711..0000000000 --- a/sim/shaman/lava_lash.go +++ /dev/null @@ -1,62 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -// https://www.wowhead.com/classic/spell=408507/lava-lash -func (shaman *Shaman) applyLavaLash() { - if !shaman.HasRune(proto.ShamanRune_RuneHandsLavaLash) || !shaman.AutoAttacks.IsDualWielding { - return - } - - cooldown := time.Second * 6 - manaCost := .01 - - damageMultiplier := 1.0 - // When off-hand is imbued with flametongue weapon increases damage by 125% - if shaman.GetCharacter().Consumes.OffHandImbue == proto.WeaponImbue_FlametongueWeapon { - damageMultiplier += 1.25 - } - - shaman.LavaLash = shaman.RegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_ShamanLavaLash, - ActionID: core.ActionID{SpellID: int32(proto.ShamanRune_RuneHandsLavaLash)}, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeOHSpecial, - Flags: SpellFlagShaman | core.SpellFlagMeleeMetrics | core.SpellFlagIgnoreResists | core.SpellFlagAPL, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - // Refund: 0.8, -- Not implemented for ManaCostOption - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: shaman.NewTimer(), - Duration: cooldown, - }, - }, - - DamageMultiplier: damageMultiplier * (1 + (.02 * float64(shaman.Talents.WeaponMastery))), - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := (spell.Unit.OHWeaponDamage(sim, spell.MeleeAttackPower())) * - shaman.AutoAttacks.OHConfig().DamageMultiplier - result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - - if !result.Landed() { - spell.IssueRefund(sim) - } - }, - }) -} From 452d8a251c931181bc984492892e91862fe93014 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:13:19 -0500 Subject: [PATCH 62/83] Delete sim/shaman/overload.go --- sim/shaman/overload.go | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 sim/shaman/overload.go diff --git a/sim/shaman/overload.go b/sim/shaman/overload.go deleted file mode 100644 index e82187d5ed..0000000000 --- a/sim/shaman/overload.go +++ /dev/null @@ -1,25 +0,0 @@ -package shaman - -import ( - "github.com/wowsims/classic/sim/core" -) - -// This could be value or bitflag if we ended up needing multiple flags at the same time. -// 1 to 5 are used by MaelstromWeapon Stacks -const CastTagOverload = 6 - -const ShamanOverloadChance = .60 - -func (shaman *Shaman) applyOverloadModifiers(spell *core.SpellConfig) { - spell.ActionID.Tag = int32(CastTagOverload) - spell.Flags |= core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell - spell.Cast.DefaultCast.CastTime = 0 - spell.Cast.DefaultCast.GCD = 0 - spell.Cast.DefaultCast.Cost = 0 - spell.Cast.ModifyCast = nil - spell.ManaCost.BaseCost = 0 - spell.ManaCost.FlatCost = 0 - spell.MetricSplits = 0 - spell.DamageMultiplier *= 0.5 - spell.ThreatMultiplier = 0 -} From 9ce96ebf6b7889cb1fc81a8c2bbe21ed97f6e09f Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:13:59 -0500 Subject: [PATCH 63/83] Update electric_spell.go --- sim/shaman/electric_spell.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sim/shaman/electric_spell.go b/sim/shaman/electric_spell.go index 0e038f8e83..9417601ad4 100644 --- a/sim/shaman/electric_spell.go +++ b/sim/shaman/electric_spell.go @@ -19,20 +19,15 @@ const ( ) // Shared precomputation logic for LB and CL. -func (shaman *Shaman) newElectricSpellConfig(actionID core.ActionID, baseCost float64, baseCastTime time.Duration, isOverload bool) core.SpellConfig { +func (shaman *Shaman) newElectricSpellConfig(actionID core.ActionID, baseCost float64, baseCastTime time.Duration) core.SpellConfig { hasMaelstromWeaponRune := shaman.HasRune(proto.ShamanRune_RuneWaistMaelstromWeapon) - flags := SpellFlagShaman | SpellFlagLightning - if !isOverload { - flags |= core.SpellFlagAPL | SpellFlagMaelstrom - } - spell := core.SpellConfig{ ActionID: actionID, SpellSchool: core.SpellSchoolNature, DefenseType: core.DefenseTypeMagic, ProcMask: core.ProcMaskSpellDamage, - Flags: flags, + Flags: flags := SpellFlagShaman | SpellFlagLightning | core.SpellFlagAPL, MetricSplits: 6, ManaCost: core.ManaCostOptions{ From 5eea4cb5383ca20f86d9049354a536bc96bf010a Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:15:53 -0500 Subject: [PATCH 64/83] Update chain_lightning.go --- sim/shaman/chain_lightning.go | 42 ++++------------------------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/sim/shaman/chain_lightning.go b/sim/shaman/chain_lightning.go index 48c957c127..c345bdd0ca 100644 --- a/sim/shaman/chain_lightning.go +++ b/sim/shaman/chain_lightning.go @@ -17,14 +17,8 @@ var ChainLightningManaCost = [ChainLightningRanks + 1]float64{0, 280, 380, 490, var ChainLightningLevel = [ChainLightningRanks + 1]int{0, 32, 40, 48, 56} func (shaman *Shaman) registerChainLightningSpell() { - overloadRuneEquipped := shaman.HasRune(proto.ShamanRune_RuneChestOverload) - shaman.ChainLightning = make([]*core.Spell, ChainLightningRanks+1) - if overloadRuneEquipped { - shaman.ChainLightningOverload = make([]*core.Spell, ChainLightningRanks+1) - } - cdTimer := shaman.NewTimer() for rank := 1; rank <= ChainLightningRanks; rank++ { @@ -32,20 +26,11 @@ func (shaman *Shaman) registerChainLightningSpell() { if config.RequiredLevel <= int(shaman.Level) { shaman.ChainLightning[rank] = shaman.RegisterSpell(config) - - // TODO: Confirm how CL Overloads work in SoD - if overloadRuneEquipped { - shaman.ChainLightningOverload[rank] = shaman.RegisterSpell(shaman.newChainLightningSpellConfig(rank, cdTimer, true)) - } } } } -func (shaman *Shaman) newChainLightningSpellConfig(rank int, cdTimer *core.Timer, isOverload bool) core.SpellConfig { - hasOverloadRune := shaman.HasRune(proto.ShamanRune_RuneChestOverload) - hasCoherenceRune := shaman.HasRune(proto.ShamanRune_RuneCloakCoherence) - hasStormEarthAndFireRune := shaman.HasRune(proto.ShamanRune_RuneCloakStormEarthAndFire) - +func (shaman *Shaman) newChainLightningSpellConfig(rank int, cdTimer *core.Timer) core.SpellConfig { spellId := ChainLightningSpellId[rank] baseDamageLow := ChainLightningBaseDamage[rank][0] baseDamageHigh := ChainLightningBaseDamage[rank][1] @@ -54,17 +39,10 @@ func (shaman *Shaman) newChainLightningSpellConfig(rank int, cdTimer *core.Timer level := ChainLightningLevel[rank] cooldown := time.Second * 6 - if hasStormEarthAndFireRune { - cooldown /= 2 - } castTime := time.Millisecond * 2500 bounceCoef := .7 // 30% reduction per bounce targetCount := ChainLightningTargetCount - if hasCoherenceRune { - bounceCoef = .8 // 20% reduction per bounce - targetCount += 2 - } canOverload := !isOverload && hasOverloadRune overloadChance := .1667 @@ -73,19 +51,15 @@ func (shaman *Shaman) newChainLightningSpellConfig(rank int, cdTimer *core.Timer core.ActionID{SpellID: spellId}, manaCost, castTime, - isOverload, ) spell.SpellCode = SpellCode_ShamanChainLightning spell.RequiredLevel = level spell.Rank = rank spell.BonusCoefficient = spellCoeff - - if !isOverload { - spell.Cast.CD = core.Cooldown{ - Timer: cdTimer, - Duration: cooldown, - } + spell.Cast.CD = core.Cooldown{ + Timer: cdTimer, + Duration: cooldown, } results := make([]*core.SpellResult, min(targetCount, shaman.Env.GetNumTargets())) @@ -101,18 +75,10 @@ func (shaman *Shaman) newChainLightningSpellConfig(rank int, cdTimer *core.Timer for _, result := range results { spell.DealDamage(sim, result) - - if canOverload && sim.Proc(overloadChance, "CL Overload") { - shaman.ChainLightningOverload[rank].Cast(sim, result.Target) - } } spell.DamageMultiplier = origMult } - if isOverload { - shaman.applyOverloadModifiers(&spell) - } - return spell } From f106e4bcfbcbddeee762c81c976080da04818ec6 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:18:02 -0500 Subject: [PATCH 65/83] Update forms.go --- sim/druid/forms.go | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/sim/druid/forms.go b/sim/druid/forms.go index 830d063730..84b128e747 100644 --- a/sim/druid/forms.go +++ b/sim/druid/forms.go @@ -87,8 +87,6 @@ func (druid *Druid) GetDynamicPredStrikeStats() stats.Stats { func (druid *Druid) registerCatFormSpell() { actionID := core.ActionID{SpellID: 768} - srm := druid.getSavageRoarMultiplier() - statBonus := druid.GetFormShiftStats().Add(stats.Stats{ stats.AttackPower: float64(druid.Level) * 2, }) @@ -137,15 +135,6 @@ func (druid *Druid) registerCatFormSpell() { druid.AutoAttacks.EnableAutoSwing(sim) druid.manageCooldownsEnabled() druid.UpdateManaRegenRates() - - // These buffs stay up, but corresponding changes don't - if druid.SavageRoarAura.IsActive() { - druid.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] *= srm - } - - if druid.PredatoryInstinctsAura != nil { - druid.PredatoryInstinctsAura.Activate(sim) - } } }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { @@ -175,15 +164,6 @@ func (druid *Druid) registerCatFormSpell() { druid.UpdateManaRegenRates() //druid.TigersFuryAura.Deactivate(sim) - - // These buffs stay up, but corresponding changes don't - if druid.SavageRoarAura.IsActive() { - druid.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] /= srm - } - - if druid.PredatoryInstinctsAura != nil { - druid.PredatoryInstinctsAura.Deactivate(sim) - } } }, }) From 636ce12841a2e3f1edf01843770dda3001a826c1 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:19:08 -0500 Subject: [PATCH 66/83] Update hurricane.go --- sim/druid/hurricane.go | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/sim/druid/hurricane.go b/sim/druid/hurricane.go index f0b5509d01..50bd541e26 100644 --- a/sim/druid/hurricane.go +++ b/sim/druid/hurricane.go @@ -22,20 +22,6 @@ func (druid *Druid) registerHurricaneSpell() { {level: 60, spellID: 17402, manaCost: 1495, scaleLevel: 66, damage: 134, scale: 0.3}, } - // assuming Gale Winds is in use, to save creating an unused timer - damageMultiplier := 2.0 - costMultiplier := int32(40) - cd := core.Cooldown{} - - if !druid.HasRune(proto.DruidRune_RuneHelmGaleWinds) { - damageMultiplier = 1.0 - costMultiplier = 100 - cd = core.Cooldown{ - Timer: druid.NewTimer(), - Duration: time.Second * 60, - } - } - for i, rank := range ranks { if druid.Level < rank.level { break @@ -53,16 +39,18 @@ func (druid *Druid) registerHurricaneSpell() { ManaCost: core.ManaCostOptions{ FlatCost: rank.manaCost, - Multiplier: costMultiplier, }, Cast: core.CastConfig{ DefaultCast: core.Cast{ GCD: core.GCDDefault, }, - CD: cd, + CD: core.Cooldown{ + Timer: druid.NewTimer(), + Duration: time.Second * 60, + }, }, - DamageMultiplier: damageMultiplier, + DamageMultiplier: 1, ThreatMultiplier: 1, Dot: core.DotConfig{ From 746933d9fc6583f60620e9135c745716cb14c327 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:19:30 -0500 Subject: [PATCH 67/83] Update innervate.go --- sim/druid/innervate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/druid/innervate.go b/sim/druid/innervate.go index 7b7a6c3003..667c3f1e4d 100644 --- a/sim/druid/innervate.go +++ b/sim/druid/innervate.go @@ -35,7 +35,7 @@ func (druid *Druid) registerInnervateCD() { } }) - druid.Innervate = druid.RegisterSpell(Humanoid|Moonkin|Tree, core.SpellConfig{ + druid.Innervate = druid.RegisterSpell(Humanoid|Moonkin, core.SpellConfig{ ActionID: actionID, ManaCost: core.ManaCostOptions{ From f22c991bc3e47369ecc9e7eb35db3326eb9f723b Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:20:13 -0500 Subject: [PATCH 68/83] Update ferocious_bite.go --- sim/druid/ferocious_bite.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sim/druid/ferocious_bite.go b/sim/druid/ferocious_bite.go index bf90eb4702..40112e6800 100644 --- a/sim/druid/ferocious_bite.go +++ b/sim/druid/ferocious_bite.go @@ -103,11 +103,8 @@ func (druid *Druid) newFerociousBiteSpellConfig(rank FerociousBiteRankInfo) core baseDamage := rank.dmgBase + rank.dmgRange*sim.RandomFloat("Ferocious Bite") + rank.dmgPerCombo*comboPoints + - attackPower*0.03*comboPoints - - if !druid.FerociousBiteExcessEnergyOverride { - baseDamage += rank.dmgPerEnergy * excessEnergy - } + attackPower*0.03*comboPoints + + rank.dmgPerEnergy * excessEnergy result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) From dbef6c736e952f9c33720f94f9f52f69cf9304c3 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:22:15 -0500 Subject: [PATCH 69/83] Update items.go --- sim/druid/items.go | 495 +-------------------------------------------- 1 file changed, 2 insertions(+), 493 deletions(-) diff --git a/sim/druid/items.go b/sim/druid/items.go index ce494ea05e..5a75a0e7b7 100644 --- a/sim/druid/items.go +++ b/sim/druid/items.go @@ -12,161 +12,11 @@ const ( IdolOfFerocity = 22397 IdolOfTheMoon = 23197 IdolOfBrutality = 23198 - // IdolMindExpandingMushroom = 209576 - // Catnip = 213407 - // IdolOfWrath = 216490 - // BloodBarkCrusher = 216499 - // IdolOfTheDream = 220606 - // RitualistsHammer = 221446 - // Glasir = 224281 - // Raelar = 224282 - // IdolOfExsanguinationCat = 228181 - // IdolOfTheSwarm = 228180 - // IdolOfExsanguinationBear = 228182 - // BloodGuardDragonhideGrips = 227180 - // KnightLieutenantsDragonhideGrips = 227183 - // WushoolaysCharmOfNature = 231280 - // PristineEnchantedSouthSeasKelp = 231316 - // IdolOfCelestialFocus = 232390 - // IdolOfFelineFocus = 232391 - // IdolOfUrsinPower = 234468 - // IdolOfFelineFerocity = 234469 - // IdolOfSiderealWrath = 234474 ) func init() { core.AddEffectsToTest = false - /* core.NewItemEffect(BloodBarkCrusher, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - druid.newBloodbarkCleaveItem(BloodBarkCrusher) - }) - - // https://www.wowhead.com/classic/item=227180/blood-guards-dragonhide-grips - // Equip: Reduces the mana cost of your shapeshifts by 150. - core.NewItemEffect(BloodGuardDragonhideGrips, func(agent core.Agent) { - registerDragonHideGripsAura(agent.(DruidAgent).GetDruid()) - }) - - // https://www.wowhead.com/classic/item=224281/glasir - // Equip: Critical effects from heals have a chance to heal 3 nearby allies for 200 to 350, and critical spell hits have a chance to damage 3 nearby enemies for 100 to 175 nature damage. - // (Proc chance: 15%, 15s cooldown) - core.NewItemEffect(Glasir, func(agent core.Agent) { - character := agent.GetCharacter() - - numDamageHits := min(3, character.Env.GetNumTargets()) - numHealHits := min(3, len(character.Env.Raid.AllPlayerUnits)) - damageResults := make([]*core.SpellResult, numDamageHits) - healResults := make([]*core.SpellResult, numHealHits) - - damageSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 452424}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: 0.10, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for idx := range damageResults { - damageResults[idx] = spell.CalcDamage(sim, target, sim.Roll(100, 175), spell.OutcomeMagicHitAndCrit) - target = sim.Environment.NextTargetUnit(target) - } - - for _, result := range damageResults { - spell.DealDamage(sim, result) - } - }, - }) - - healSpell := character.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 453009}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell | core.SpellFlagHelpful, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: 0.10, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for idx := range healResults { - healResults[idx] = spell.CalcHealing(sim, target, sim.Roll(200, 350), spell.OutcomeMagicCrit) - target = sim.Environment.NextTargetUnit(target) - } - - for _, result := range healResults { - spell.DealHealing(sim, result) - } - }, - }) - - core.MakePermanent(character.RegisterAura(core.Aura{ - Label: "Gla'sir Damage Trigger", - OnPeriodicDamageDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskSpellDamage) && result.DidCrit() && sim.Proc(.15, "Gla'sir Damage") { - damageSpell.Cast(sim, result.Target) - } - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskSpellDamage) && result.DidCrit() && sim.Proc(.15, "Gla'sir Damage") { - damageSpell.Cast(sim, result.Target) - } - }, - })) - - core.MakePermanent(character.RegisterAura(core.Aura{ - Label: "Gla'sir Heal Trigger", - OnPeriodicHealDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskSpellDamage) && result.DidCrit() && sim.Proc(.15, "Gla'sir Heal") { - healSpell.Cast(sim, result.Target) - } - }, - OnHealDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.ProcMask.Matches(core.ProcMaskSpellDamage) && result.DidCrit() && sim.Proc(.15, "Gla'sir Heal") { - healSpell.Cast(sim, result.Target) - } - }, - })) - }) - - // https://www.wowhead.com/classic/item=232390/idol-of-celestial-focus - // Equip: Increases the damage done by Starfall by 10%, but decreases its radius by 50%. - core.NewItemEffect(IdolOfCelestialFocus, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - - druid.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_DruidStarfallTick || spell.SpellCode == SpellCode_DruidStarfallSplash { - spell.DamageMultiplier *= 1.10 - } - }) - }) - - // https://www.wowhead.com/classic/item=232391/idol-of-feline-focus - // Equip: Your Ferocious Bite ability no longer converts additional energy into damage, and refunds 30 energy on a Dodge, Miss, or Parry. - core.NewItemEffect(IdolOfFelineFocus, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - druid.FerociousBiteExcessEnergyOverride = true - - actionID := core.ActionID{SpellID: 470270} - - energyMetrics := druid.NewEnergyMetrics(actionID) - - core.MakePermanent(druid.RegisterAura(core.Aura{ - ActionID: actionID, - Label: "Idol of Feline Focus", - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.SpellCode == SpellCode_DruidFerociousBite && result.Outcome.Matches(core.OutcomeDodge|core.OutcomeMiss|core.OutcomeParry) { - druid.AddEnergy(sim, 30, energyMetrics) - } - }, - })) - }) */ - // https://www.wowhead.com/classic/item=22397/idol-of-ferocity // Equip: Reduces the energy cost of Claw and Rake by 3. core.NewItemEffect(IdolOfFerocity, func(agent core.Agent) { @@ -174,7 +24,7 @@ func init() { // TODO: Claw is not implemented druid.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_DruidRake || spell.SpellCode == SpellCode_DruidMangleCat { + if spell.SpellCode == SpellCode_DruidRake { spell.Cost.FlatModifier -= 3 } }) @@ -184,9 +34,8 @@ func init() { // Equip: Increases the damage of your Moonfire spell by up to 33. core.NewItemEffect(IdolOfTheMoon, func(agent core.Agent) { druid := agent.(DruidAgent).GetDruid() - affectedSpellCodes := []int32{SpellCode_DruidMoonfire, SpellCode_DruidSunfire, SpellCode_DruidStarfallSplash, SpellCode_DruidStarfallTick} druid.OnSpellRegistered(func(spell *core.Spell) { - if slices.Contains(affectedSpellCodes, spell.SpellCode) { + if spell.SpellCode == SpellCode_DruidMoonfire { spell.BonusDamage += 33 } }) @@ -198,345 +47,5 @@ func init() { // Implemented in maul.go and swipe.go }) - /* core.NewItemEffect(IdolMindExpandingMushroom, func(agent core.Agent) { - character := agent.GetCharacter() - character.AddStat(stats.Spirit, 5) - }) - - // https://www.wowhead.com/classic/item=228181/idol-of-exsanguination-cat - // Equip: The energy cost of your Rake and Rip spells is reduced by 5. - core.NewItemEffect(IdolOfExsanguinationCat, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - druid.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_DruidRake || spell.SpellCode == SpellCode_DruidRip { - spell.Cost.FlatModifier -= 5 - } - }) - }) - - // https://www.wowhead.com/classic/item=228182/idol-of-exsanguination-bear - // Equip: Your Lacerate ticks energize you for 3 rage. - core.NewItemEffect(IdolOfExsanguinationBear, func(agent core.Agent) { - // TODO: Not yet implemented - }) - - // https://www.wowhead.com/classic/item=234469/idol-of-feline-ferocity - // Increases the damage of Ferocious Bite and Shred by 3%. - core.NewItemEffect(IdolOfFelineFerocity, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - druid.RegisterAura(core.Aura{ - Label: "Improved Wrath/Moonfire", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells := core.FilterSlice( - []*DruidSpell{ - druid.FerociousBite, - druid.Shred, - }, - func(spell *DruidSpell) bool { return spell != nil }, - ) - - for _, spell := range affectedSpells { - spell.DamageMultiplierAdditive += 0.03 - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=234474/idol-of-sidereal-wrath - // Increases the damage of Moonfire and Wrath by 3%. - core.NewItemEffect(IdolOfSiderealWrath, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - druid.RegisterAura(core.Aura{ - Label: "Improved Wrath/Moonfire", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells := core.FilterSlice( - core.Flatten( - [][]*DruidSpell{ - druid.Wrath, - druid.Moonfire, - {druid.Sunfire, druid.Starsurge, druid.StarfallSplash, druid.StarfallTick}, - }, - ), - func(spell *DruidSpell) bool { return spell != nil }, - ) - - for _, spell := range affectedSpells { - spell.DamageMultiplierAdditive += 0.03 - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=228180/idol-of-the-swarm - // Equip: The duration of your Insect Swarm spell is increased by 12 sec. - core.NewItemEffect(IdolOfTheSwarm, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - - bonusDuration := time.Second * 12 - - druid.GetOrRegisterAura(core.Aura{ - Label: "Idol of the Swarm", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range druid.InsectSwarm { - if spell != nil { - for _, dot := range spell.Dots() { - if dot != nil { - dot.NumberOfTicks += 6 - dot.RecomputeAuraDuration() - } - } - } - } - - for _, aura := range druid.InsectSwarmAuras { - if aura != nil && !aura.IsPermanent() { - aura.Duration += bonusDuration - } - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=234468/idol-of-ursin-power - // Increases the damage of Swipe and Mangle by 3%. - core.NewItemEffect(IdolOfUrsinPower, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - druid.RegisterAura(core.Aura{ - Label: "Improved Wrath/Moonfire", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedSpells := core.FilterSlice( - []*DruidSpell{ - druid.SwipeBear, - druid.SwipeCat, - druid.MangleBear, - druid.MangleCat, - }, - func(spell *DruidSpell) bool { return spell != nil }, - ) - - for _, spell := range affectedSpells { - spell.DamageMultiplierAdditive += 0.03 - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=227183/knight-lieutenants-dragonhide-grips - // Equip: Reduces the mana cost of your shapeshifts by 150. - core.NewItemEffect(KnightLieutenantsDragonhideGrips, func(agent core.Agent) { - registerDragonHideGripsAura(agent.(DruidAgent).GetDruid()) - }) - - // https://www.wowhead.com/classic/item=231316/pristine-enchanted-south-seas-kelp - // Increases the critical hit chance of Wrath and Starfire by 2%. - core.NewItemEffect(PristineEnchantedSouthSeasKelp, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - druid.RegisterAura(core.Aura{ - Label: "Improved Wrath/Starfire", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range druid.Wrath { - if spell != nil { - spell.BonusCritRating += 2 * core.SpellCritRatingPerCritChance - } - } - for _, spell := range druid.Starfire { - if spell != nil { - spell.BonusCritRating += 2 * core.SpellCritRatingPerCritChance - } - } - }, - }) - }) - - // https://www.wowhead.com/classic/item=224282/raelar - // Equip: Chance on melee auto attack to steal 140 to 220 life from target enemy. - core.NewItemEffect(Raelar, func(agent core.Agent) { - character := agent.GetCharacter() - actionID := core.ActionID{SpellID: 452430} - healthMetrics := character.NewHealthMetrics(actionID) - - lifesteal := character.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - // TODO: Unsure if this can crit but it we're assuming Gla'sir can - result := spell.CalcAndDealDamage(sim, target, sim.Roll(140, 220), spell.OutcomeMagicHitAndCrit) - character.GainHealth(sim, result.Damage, healthMetrics) - }, - }) - - core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Rae'lar Damage Trigger", - Callback: core.CallbackOnSpellHitDealt, - ProcMask: core.ProcMaskWhiteHit, - PPM: 1.0, - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - lifesteal.Cast(sim, result.Target) - }, - }) - }) - - core.NewItemEffect(RitualistsHammer, func(agent core.Agent) { - druid := agent.(DruidAgent).GetDruid() - druid.newBloodbarkCleaveItem(RitualistsHammer) - }) - - // https://www.wowhead.com/classic/item=231280/wushoolays-charm-of-nature - // Use: Aligns the Druid with nature, increasing the damage done by spells by 10%, improving heal effects by 10%, and increasing the critical strike chance of spells by 10% for 20 sec. - // (2 Min Cooldown) - core.NewItemEffect(WushoolaysCharmOfNature, func(agent core.Agent) { - character := agent.GetCharacter() - actionID := core.ActionID{ItemID: WushoolaysCharmOfNature} - duration := time.Second * 20 - - aura := character.RegisterAura(core.Aura{ - ActionID: actionID, - Label: "Aligned with Nature", - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.SchoolDamageDealtMultiplier.MultiplyMagicSchools(1.10) - // TODO: healing dealt multiplier? - character.AddStatDynamic(sim, stats.SpellCrit, 10*core.SpellCritRatingPerCritChance) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.SchoolDamageDealtMultiplier.MultiplyMagicSchools(1 / 1.10) - // TODO: healing dealt multiplier? - character.AddStatDynamic(sim, stats.SpellCrit, -10*core.SpellCritRatingPerCritChance) - }, - }) - - spell := character.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolNature, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - SharedCD: core.Cooldown{ - Timer: character.GetOffensiveTrinketCD(), - Duration: duration, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - aura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Spell: spell, - Priority: core.CooldownPriorityBloodlust, - Type: core.CooldownTypeDPS, - }) - }) */ - core.AddEffectsToTest = true } - -/* func (druid *Druid) newBloodbarkCleaveItem(itemID int32) { - auraActionID := core.ActionID{SpellID: 436482} - - results := make([]*core.SpellResult, min(3, druid.Env.GetNumTargets())) - - damageSpell := druid.RegisterSpell(Any, core.SpellConfig{ - ActionID: core.ActionID{SpellID: 436481}, - SpellSchool: core.SpellSchoolPhysical | core.SpellSchoolNature, - DefenseType: core.DefenseTypeMelee, // actually has DefenseTypeNone, but is likely using the greatest CritMultiplier available - ProcMask: core.ProcMaskEmpty, - - // TODO: "Causes additional threat" in Tooltip, no clue what the multiplier is. - ThreatMultiplier: 1, - DamageMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for idx := range results { - results[idx] = spell.CalcDamage(sim, target, 5, spell.OutcomeMagicCrit) - target = sim.Environment.NextTargetUnit(target) - } - for _, result := range results { - spell.DealDamage(sim, result) - } - }, - }) - - buffAura := druid.GetOrRegisterAura(core.Aura{ - Label: "Bloodbark Cleave", - ActionID: auraActionID, - Duration: 20 * time.Second, - - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Landed() && spell.ProcMask&core.ProcMaskMelee != 0 { - damageSpell.Cast(sim, result.Target) - return - } - }, - }) - - mainSpell := druid.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{ItemID: itemID}, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: druid.NewTimer(), - Duration: time.Minute * 3, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - buffAura.Activate(sim) - }, - }) - - druid.AddMajorCooldown(core.MajorCooldown{ - Spell: mainSpell, - Priority: core.CooldownPriorityDefault, - Type: core.CooldownTypeDPS, - }) -} - -func registerDragonHideGripsAura(druid *Druid) { - const costReduction int32 = 150 - var affectedForms []*DruidSpell - - druid.RegisterAura(core.Aura{ - Label: "Dragonhide Grips", - ActionID: core.ActionID{SpellID: 459594}, - Duration: core.NeverExpires, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - affectedForms = []*DruidSpell{ - druid.CatForm, - druid.MoonkinForm, - druid.BearForm, - } - }, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range affectedForms { - if spell != nil { - spell.Cost.FlatModifier -= costReduction - } - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - for _, spell := range affectedForms { - if spell != nil { - spell.Cost.FlatModifier += costReduction - } - } - }, - }) -} -*/ From 68e1bc61f77e5e16df0bab3ad9483426ddd57695 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:24:06 -0500 Subject: [PATCH 70/83] Update rip.go --- sim/druid/rip.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sim/druid/rip.go b/sim/druid/rip.go index b2276202af..d35517ac97 100644 --- a/sim/druid/rip.go +++ b/sim/druid/rip.go @@ -101,10 +101,7 @@ func (druid *Druid) newRipSpellConfig(ripRank RipRankInfo) core.SpellConfig { TickLength: time.Second * 2, OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - cp := float64(druid.ComboPoints()) - ap := dot.Spell.MeleeAttackPower() - - cpScaling := core.TernaryFloat64(cp == 5, 4, cp) + cpScaling := core.TernaryFloat64(cp == 5, 4, float64(druid.ComboPoints())) baseDamage := ripRank.dmgTickBase + ripRank.dmgTickPerCombo*cp dot.Snapshot(target, baseDamage, isRollover) }, From d64de8a83e7084c0c078b54e0c426011876abdcd Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:24:37 -0500 Subject: [PATCH 71/83] Update swipe.go --- sim/druid/swipe.go | 50 +--------------------------------------------- 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/sim/druid/swipe.go b/sim/druid/swipe.go index 6050054ee8..bfab3a9588 100644 --- a/sim/druid/swipe.go +++ b/sim/druid/swipe.go @@ -18,8 +18,6 @@ var SwipeLevel = [SwipeRanks + 1]int{0, 16, 24, 34, 44, 54} const SwipeThreatMultiplier = 2.0 func (druid *Druid) registerSwipeBearSpell() { - hasImprovedSwipeRune := druid.HasRune(proto.DruidRune_RuneCloakImprovedSwipe) - rank := map[int32]int{ 25: 2, 40: 3, @@ -32,7 +30,7 @@ func (druid *Druid) registerSwipeBearSpell() { baseDamage := SwipeBaseDamage[rank] rageCost := 20 - float64(druid.Talents.Ferocity) - targetCount := core.TernaryInt32(hasImprovedSwipeRune, 10, 3) + targetCount := 3 numHits := min(targetCount, druid.Env.GetNumTargets()) results := make([]*core.SpellResult, numHits) @@ -77,49 +75,3 @@ func (druid *Druid) registerSwipeBearSpell() { }, }) } - -func (druid *Druid) registerSwipeCatSpell() { - if !druid.HasRune(proto.DruidRune_RuneCloakImprovedSwipe) { - return - } - - weaponMulti := 2.5 - - druid.SwipeCat = druid.RegisterSpell(Cat, core.SpellConfig{ - ActionID: core.ActionID{SpellID: 411128}, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | SpellFlagOmen | SpellFlagBuilder, - - EnergyCost: core.EnergyCostOptions{ - Cost: 50 - float64(druid.Talents.Ferocity), - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: time.Second, - }, - IgnoreHaste: true, - }, - - DamageMultiplier: (1 + 0.1*float64(druid.Talents.SavageFury)) * weaponMulti, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := spell.Unit.MHNormalizedWeaponDamage(sim, spell.MeleeAttackPower()) - aoeTarget := target - for i := 0; i < len(sim.Encounter.TargetUnits); i++ { - result := spell.CalcAndDealDamage(sim, aoeTarget, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - if i == 0 && result.Landed() { - druid.AddComboPoints(sim, 1, target, spell.ComboPointMetrics()) - } - aoeTarget = sim.Environment.NextTargetUnit(aoeTarget) - } - }, - }) -} - -func (druid *Druid) CurrentSwipeCatCost() float64 { - return druid.SwipeCat.Cost.GetCurrentCost() -} From a615222f1e7d97f52041c72f14a152a56aa8bfa2 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:25:10 -0500 Subject: [PATCH 72/83] Update wrath.go --- sim/druid/wrath.go | 1 - 1 file changed, 1 deletion(-) diff --git a/sim/druid/wrath.go b/sim/druid/wrath.go index 4d439674f6..87232d6c82 100644 --- a/sim/druid/wrath.go +++ b/sim/druid/wrath.go @@ -50,7 +50,6 @@ func (druid *Druid) newWrathSpellConfig(rank int) core.SpellConfig { ManaCost: core.ManaCostOptions{ FlatCost: manaCost, - Multiplier: core.TernaryInt32(druid.FuryOfStormrageAura != nil, -1, 100), }, Cast: core.CastConfig{ DefaultCast: core.Cast{ From afaa298886638acf30b47adbf297738c48f90625 Mon Sep 17 00:00:00 2001 From: Kayla Glick <12898988+kayla-glick@users.noreply.github.com> Date: Mon, 23 Dec 2024 13:26:06 -0500 Subject: [PATCH 73/83] Update talents.go --- sim/druid/talents.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sim/druid/talents.go b/sim/druid/talents.go index 72aa9c7e97..447062e5e3 100644 --- a/sim/druid/talents.go +++ b/sim/druid/talents.go @@ -17,8 +17,7 @@ func (druid *Druid) ApplyTalents() { druid.applyMoonglow() druid.applyMoonfury() - // SoD tuning made this all damage, not just physical damage - druid.PseudoStats.DamageDealtMultiplier *= 1 + 0.02*float64(druid.Talents.NaturalWeapons) + druid.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexPhysical] *= 1 + 0.02*float64(druid.Talents.NaturalWeapons) // Feral druid.applyBloodFrenzy() From 61a66a33e65b879fd29096422d576816d1e0d60b Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 13:35:07 -0500 Subject: [PATCH 74/83] fix druid errors --- proto/apl.proto | 3 - sim/druid/druid.go | 4 +- sim/druid/feral/apl_values.go | 25 +-------- sim/druid/feral/rotation.go | 101 +++------------------------------- sim/druid/hurricane.go | 3 +- sim/druid/items.go | 2 - sim/druid/rip.go | 5 +- sim/druid/shred.go | 1 - sim/druid/swipe.go | 6 +- 9 files changed, 14 insertions(+), 136 deletions(-) diff --git a/proto/apl.proto b/proto/apl.proto index 23ad06d021..e26d3f1fa0 100644 --- a/proto/apl.proto +++ b/proto/apl.proto @@ -166,7 +166,6 @@ message APLValue { APLValueTotemRemainingTime totem_remaining_time = 49; // Druid APLValueCatExcessEnergy cat_excess_energy = 52; - APLValueCatNewSavageRoarDuration cat_new_savage_roar_duration = 61; // Warlock APLValueWarlockShouldRecastDrainSoul warlock_should_recast_drain_soul = 59; APLValueWarlockShouldRefreshCorruption warlock_should_refresh_corruption = 60; @@ -518,8 +517,6 @@ message APLValueTotemRemainingTime { } message APLValueCatExcessEnergy { } -message APLValueCatNewSavageRoarDuration { -} message APLValueWarlockShouldRecastDrainSoul { } message APLValueWarlockShouldRefreshCorruption { diff --git a/sim/druid/druid.go b/sim/druid/druid.go index 023493ba18..b58d0e0157 100644 --- a/sim/druid/druid.go +++ b/sim/druid/druid.go @@ -1,8 +1,6 @@ package druid import ( - "time" - "github.com/wowsims/classic/sim/common/guardians" "github.com/wowsims/classic/sim/core" "github.com/wowsims/classic/sim/core/proto" @@ -92,7 +90,7 @@ type Druid struct { PredatoryInstinctsAura *core.Aura TigersFuryAura *core.Aura - BleedCategories core.ExclusiveCategoryArray + BleedCategories core.ExclusiveCategoryArray form DruidForm disabledMCDs []*core.MajorCooldown diff --git a/sim/druid/feral/apl_values.go b/sim/druid/feral/apl_values.go index 17f18eb80b..b639c76d57 100644 --- a/sim/druid/feral/apl_values.go +++ b/sim/druid/feral/apl_values.go @@ -11,8 +11,6 @@ func (cat *FeralDruid) NewAPLValue(rot *core.APLRotation, config *proto.APLValue switch config.Value.(type) { case *proto.APLValue_CatExcessEnergy: return cat.newValueCatExcessEnergy(rot, config.GetCatExcessEnergy()) - case *proto.APLValue_CatNewSavageRoarDuration: - return cat.newValueCatNewSavageRoarDuration(rot, config.GetCatNewSavageRoarDuration()) default: return nil } @@ -72,27 +70,6 @@ func (value *APLValueCatExcessEnergy) String() string { return "Cat Excess Energy()" } -type APLValueCatNewSavageRoarDuration struct { - core.DefaultAPLValueImpl - cat *FeralDruid -} - -func (cat *FeralDruid) newValueCatNewSavageRoarDuration(rot *core.APLRotation, config *proto.APLValueCatNewSavageRoarDuration) core.APLValue { - return &APLValueCatNewSavageRoarDuration{ - cat: cat, - } -} -func (value *APLValueCatNewSavageRoarDuration) Type() proto.APLValueType { - return proto.APLValueType_ValueTypeDuration -} -func (value *APLValueCatNewSavageRoarDuration) GetDuration(sim *core.Simulation) time.Duration { - cat := value.cat - return cat.SavageRoarDurationTable[cat.ComboPoints()] -} -func (value *APLValueCatNewSavageRoarDuration) String() string { - return "New Savage Roar Duration()" -} - func (cat *FeralDruid) NewAPLAction(rot *core.APLRotation, config *proto.APLAction) core.APLActionImpl { switch config.Action.(type) { case *proto.APLAction_CatOptimalRotationAction: @@ -131,7 +108,7 @@ func (action *APLActionCatOptimalRotationAction) Execute(sim *core.Simulation) { // If a melee swing resulted in an Omen or Wild Strikes proc, then schedule the // next player decision based on latency. - if (cat.Talents.OmenOfClarity && cat.ClearcastingAura.RemainingDuration(sim) == cat.ClearcastingAura.Duration) || (cat.WildStrikesBuffAura != nil && cat.WildStrikesBuffAura.RemainingDuration(sim) == cat.WildStrikesBuffAura.Duration) { + if cat.Talents.OmenOfClarity && cat.ClearcastingAura.RemainingDuration(sim) == cat.ClearcastingAura.Duration { // Kick gcd loop, also need to account for any gcd 'left' // otherwise it breaks gcd logic kickTime := max(cat.NextGCDAt(), sim.CurrentTime+cat.latency) diff --git a/sim/druid/feral/rotation.go b/sim/druid/feral/rotation.go index de346af064..b9f0f05d64 100644 --- a/sim/druid/feral/rotation.go +++ b/sim/druid/feral/rotation.go @@ -13,7 +13,6 @@ type FeralDruidRotation struct { MinCombosForRip int32 MaxWaitTime time.Duration MaintainFaerieFire bool - UseSavageRoar bool UseShredTrick bool UseRipTrick bool } @@ -94,34 +93,12 @@ func (cat *FeralDruid) timeToCast(numSpecials int32) time.Duration { return core.DurationFromSeconds(numPowershiftedSpecials*2.0 + numOomSpecials*4.0) } -func (cat *FeralDruid) canRip(sim *core.Simulation, isTrick bool, usingRoar bool) bool { +func (cat *FeralDruid) canRip(sim *core.Simulation, isTrick bool) bool { if cat.Rip.CurDot().IsActive() { return false } - // Allow Rip if conservative napkin math estimate says that we can cast the Rip and then build 5 Combo Points in time before the current Savage Roar expires. - var roarDur time.Duration - - if usingRoar { - roarDur = cat.SavageRoarAura.RemainingDuration(sim) - } else { - roarDur = core.NeverExpires - } fightDur := sim.GetRemainingDuration() - remainingFightTimeAfterRoar := fightDur - roarDur - - // solve "remainingFightTimeAfterRoar = 5*roarCP+9" for roarCP - // add 1 to round up instead of down - roarCp := int32((remainingFightTimeAfterRoar-time.Second*9)/(time.Second*5)) + 1 - minRoarCp := min(roarCp, 5) - - // Actions to generate minRoarCp, plus cast Roar itself. - actionsToCastRoar := minRoarCp + 1 - - // Don't let roar expire. - if cat.timeToCast(actionsToCastRoar) >= roarDur { - return false - } if cat.ComboPoints() == 5 { // 5CP rip is worth it with 4 ticks @@ -137,12 +114,6 @@ func (cat *FeralDruid) canRip(sim *core.Simulation, isTrick bool, usingRoar bool } } - // If we can't get any more combo points before roar expires, then we should rip now. - // If we can generate another CP and then rip without letting roar expire, then wait. - if cat.timeToCast(actionsToCastRoar+1) >= roarDur { - return true - } - // Caller decided that we should "rip trick". if isTrick { return true @@ -153,8 +124,7 @@ func (cat *FeralDruid) canRip(sim *core.Simulation, isTrick bool, usingRoar bool /* func (cat *FeralDruid) canBite(sim *core.Simulation) bool { - return cat.Rip.CurDot().RemainingDuration(sim) >= cat.Rotation.BiteTime && - cat.SavageRoarAura.RemainingDuration(sim) >= cat.Rotation.BiteTime + return cat.Rip.CurDot().RemainingDuration(sim) >= cat.Rotation.BiteTime } func (cat *FeralDruid) berserkExpectedAt(sim *core.Simulation, futureTime time.Duration) bool { @@ -181,35 +151,6 @@ func (cat *FeralDruid) calcBuilderDpe(sim *core.Simulation) (float64, float64) { } */ -func (cat *FeralDruid) clipRoar(sim *core.Simulation) bool { - // If existing Roar already covers us to end of fight, then don't clip it - roarDur := cat.SavageRoarAura.RemainingDuration(sim) - fightDur := sim.GetRemainingDuration() - - if roarDur >= fightDur { - return false - } - - // If a fresh Roar cast now at the current number of Combo Points *would* cover us to end of fight, then clip now for maximum CP efficiency - newRoarDur := cat.SavageRoarDurationTable[cat.ComboPoints()] - - if newRoarDur >= fightDur { - return true - } - - // Roar clips that don't cover us to end of fight should only be done at 5 CP - if cat.ComboPoints() < 5 { - return false - } - - // Calculate the minimum number of Roar casts that will cover us to end of fight if we (a) let the current one expire naturally vs. (b) clip it now. - minRoarsPossible := (fightDur - roarDur) / newRoarDur - projectedRoarCasts := fightDur / newRoarDur - - // Allow a clip at the earliest time that doesn't result in an extra Roar cast - return projectedRoarCasts == minRoarsPossible -} - func (cat *FeralDruid) preRotationCleanup(sim *core.Simulation) bool { // If we previously decided to shift, then execute the shift now once // the input delay is over. @@ -264,7 +205,6 @@ func (cat *FeralDruid) doRotation(sim *core.Simulation) (bool, time.Duration) { nextTick := cat.NextEnergyTickAt() timeToNextTick := nextTick - sim.CurrentTime isClearcast := cat.ClearcastingAura.IsActive() - hasRoar := cat.SavageRoarAura.IsActive() numShiftsToOom := cat.numShiftsRemaining() fightDur := sim.GetRemainingDuration() shredCost := cat.Shred.DefaultCast.Cost @@ -278,14 +218,10 @@ func (cat *FeralDruid) doRotation(sim *core.Simulation) (bool, time.Duration) { var nextAbility *druid.DruidSpell - if rotation.UseSavageRoar && curCp >= 1 && !hasRoar { - nextAbility = cat.SavageRoar - } else if isClearcast { + if isClearcast { nextAbility = cat.Shred - } else if (curCp >= rotation.MinCombosForRip || canRipTrick) && cat.canRip(sim, canRipTrick, rotation.UseSavageRoar) { + } else if (curCp >= rotation.MinCombosForRip || canRipTrick) && cat.canRip(sim, canRipTrick) { nextAbility = cat.Rip - } else if rotation.UseSavageRoar && curCp >= 1 && cat.clipRoar(sim) { - nextAbility = cat.SavageRoar } else if canShredTrick { nextAbility = cat.Shred } else { @@ -293,8 +229,7 @@ func (cat *FeralDruid) doRotation(sim *core.Simulation) (bool, time.Duration) { } // Then determine whether to cast vs. wait vs. shift - waitForWildStrikesProc := (cat.WildStrikesBuffAura != nil) && !cat.WildStrikesBuffAura.IsActive() - poolEnergy := poolMana && ((curCp == 5) || waitForWildStrikesProc) && (nextEnergy < 100) && (nextAbility == rotation.PrimaryBuilder) + poolEnergy := poolMana && curCp == 5 && (nextEnergy < 100) && (nextAbility == rotation.PrimaryBuilder) nextAction := sim.CurrentTime if nextAbility.CanCast(sim, cat.CurrentTarget) && !poolEnergy { @@ -367,7 +302,7 @@ func (cat *FeralDruid) doRotation(sim *core.Simulation) (bool, time.Duration) { mangleNow := !ripNow && cat.MangleCat != nil && (mangleRefreshNow || clipMangle) - biteBeforeRip := (curCp >= rotation.MinCombosForBite) && ripDot.IsActive() && cat.SavageRoarAura.IsActive() && rotation.UseBite && cat.canBite(sim) + biteBeforeRip := (curCp >= rotation.MinCombosForBite) && ripDot.IsActive() && rotation.UseBite && cat.canBite(sim) biteNow := (biteBeforeRip || biteAtEnd) && !isClearcast && curEnergy < 67 // During Berserk, we additionally add an Energy constraint on Bite @@ -416,8 +351,6 @@ func (cat *FeralDruid) doRotation(sim *core.Simulation) (bool, time.Duration) { berserkNow = simTimeRemain < cat.BerserkAura.Duration+(3*time.Second) } - roarNow := curCp >= 1 && (!cat.SavageRoarAura.IsActive() || cat.clipRoar(sim)) - // Faerie Fire on cooldown for Omen procs. Each second of FF delay is // worth ~7 Energy, so it is okay to waste up to 7 Energy to cap when // determining whether to cast it vs. dump Energy first. That puts the @@ -464,10 +397,6 @@ func (cat *FeralDruid) doRotation(sim *core.Simulation) (bool, time.Duration) { mangleCost := core.Ternary(cat.berserkExpectedAt(sim, cat.bleedAura.ExpiresAt()), cat.MangleCat.DefaultCast.Cost*0.5, cat.MangleCat.DefaultCast.Cost) pendingPool.addAction(cat.bleedAura.ExpiresAt(), mangleCost) } - if cat.SavageRoarAura.IsActive() { - roarCost := core.Ternary(cat.berserkExpectedAt(sim, cat.SavageRoarAura.ExpiresAt()), cat.SavageRoar.DefaultCast.Cost*0.5, cat.SavageRoar.DefaultCast.Cost) - pendingPool.addAction(cat.SavageRoarAura.ExpiresAt(), roarCost) - } pendingPool.sort() @@ -637,12 +566,6 @@ func (cat *FeralDruid) doRotation(sim *core.Simulation) (bool, time.Duration) { cat.Berserk.Cast(sim, nil) cat.UpdateMajorCooldowns() return false, 0 - } else if roarNow { - if cat.SavageRoar.CanCast(sim, cat.CurrentTarget) { - cat.SavageRoar.Cast(sim, nil) - return false, 0 - } - timeToNextAction = time.Duration((cat.CurrentSavageRoarCost() - curEnergy) * float64(core.EnergyTickDuration)) } else if ripNow { if cat.Rip.CanCast(sim, cat.CurrentTarget) { cat.Rip.Cast(sim, cat.CurrentTarget) @@ -740,7 +663,6 @@ type FeralDruidRotation struct { BerserkBiteThresh float64 BerserkFfThresh float64 Powerbear bool - MinRoarOffset time.Duration RipLeeway time.Duration MaxFfDelay time.Duration RevitFreq float64 @@ -755,22 +677,13 @@ type FeralDruidRotation struct { */ func (cat *FeralDruid) setupRotation(config *proto.APLActionCatOptimalRotationAction) { - var primaryBuilder *druid.DruidSpell - - if cat.MangleCat != nil { - primaryBuilder = cat.MangleCat - } else { - primaryBuilder = cat.Shred - } - - knowsRoar := cat.SavageRoar != nil + primaryBuilder := cat.Shred cat.Rotation = FeralDruidRotation{ PrimaryBuilder: primaryBuilder, MinCombosForRip: config.MinCombosForRip, MaxWaitTime: core.DurationFromSeconds(float64(config.MaxWaitTime)), MaintainFaerieFire: config.MaintainFaerieFire, - UseSavageRoar: knowsRoar, UseShredTrick: config.UseShredTrick, UseRipTrick: false, } diff --git a/sim/druid/hurricane.go b/sim/druid/hurricane.go index 50bd541e26..665811a80d 100644 --- a/sim/druid/hurricane.go +++ b/sim/druid/hurricane.go @@ -5,7 +5,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) func (druid *Druid) registerHurricaneSpell() { @@ -38,7 +37,7 @@ func (druid *Druid) registerHurricaneSpell() { Rank: i + 1, ManaCost: core.ManaCostOptions{ - FlatCost: rank.manaCost, + FlatCost: rank.manaCost, }, Cast: core.CastConfig{ DefaultCast: core.Cast{ diff --git a/sim/druid/items.go b/sim/druid/items.go index 5a75a0e7b7..a883decab9 100644 --- a/sim/druid/items.go +++ b/sim/druid/items.go @@ -1,8 +1,6 @@ package druid import ( - "slices" - "github.com/wowsims/classic/sim/core" ) diff --git a/sim/druid/rip.go b/sim/druid/rip.go index d35517ac97..54fe1980fc 100644 --- a/sim/druid/rip.go +++ b/sim/druid/rip.go @@ -101,8 +101,9 @@ func (druid *Druid) newRipSpellConfig(ripRank RipRankInfo) core.SpellConfig { TickLength: time.Second * 2, OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - cpScaling := core.TernaryFloat64(cp == 5, 4, float64(druid.ComboPoints())) - baseDamage := ripRank.dmgTickBase + ripRank.dmgTickPerCombo*cp + cp := float64(druid.ComboPoints()) + cpScaling := core.TernaryFloat64(cp == 5, 4, cp) + baseDamage := ripRank.dmgTickBase + ripRank.dmgTickPerCombo*cpScaling dot.Snapshot(target, baseDamage, isRollover) }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { diff --git a/sim/druid/shred.go b/sim/druid/shred.go index eb5fa2f9e0..5344408b31 100644 --- a/sim/druid/shred.go +++ b/sim/druid/shred.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) func (druid *Druid) registerShredSpell() { diff --git a/sim/druid/swipe.go b/sim/druid/swipe.go index bfab3a9588..eb86554bac 100644 --- a/sim/druid/swipe.go +++ b/sim/druid/swipe.go @@ -1,10 +1,7 @@ package druid import ( - "time" - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const SwipeRanks = 5 @@ -30,8 +27,7 @@ func (druid *Druid) registerSwipeBearSpell() { baseDamage := SwipeBaseDamage[rank] rageCost := 20 - float64(druid.Talents.Ferocity) - targetCount := 3 - numHits := min(targetCount, druid.Env.GetNumTargets()) + numHits := min(3, druid.Env.GetNumTargets()) results := make([]*core.SpellResult, numHits) switch druid.Ranged().ID { From fc9c7c093775013cb7a69e14f428e89a0db8ee7c Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 13:39:06 -0500 Subject: [PATCH 75/83] hunter cleanup --- sim/hunter/aimed_shot.go | 3 - sim/hunter/explosive_trap.go | 103 ++++++++++++++++++++++++++++++++++ sim/hunter/immolation_trap.go | 4 +- sim/hunter/mongoose_bite.go | 24 +------- sim/hunter/multi_shot.go | 17 ------ sim/hunter/rapid_fire.go | 11 +--- sim/hunter/raptor_strike.go | 2 - sim/hunter/serpent_sting.go | 33 ----------- sim/hunter/volley.go | 6 +- 9 files changed, 109 insertions(+), 94 deletions(-) create mode 100644 sim/hunter/explosive_trap.go diff --git a/sim/hunter/aimed_shot.go b/sim/hunter/aimed_shot.go index 832c4dd23f..681148f632 100644 --- a/sim/hunter/aimed_shot.go +++ b/sim/hunter/aimed_shot.go @@ -42,9 +42,6 @@ func (hunter *Hunter) getAimedShotConfig(rank int, timer *core.Timer) core.Spell }, IgnoreHaste: true, // Hunter GCD is locked at 1.5s CastTime: func(spell *core.Spell) time.Duration { - if hunter.SniperTrainingAura.GetStacks() >= 2 { - return 0 - } return time.Duration(float64(spell.DefaultCast.CastTime) / hunter.RangedSwingSpeed()) }, }, diff --git a/sim/hunter/explosive_trap.go b/sim/hunter/explosive_trap.go new file mode 100644 index 0000000000..fadb1d2e02 --- /dev/null +++ b/sim/hunter/explosive_trap.go @@ -0,0 +1,103 @@ +package hunter + +import ( + "strconv" + "time" + + "github.com/wowsims/classic/sim/core" + "github.com/wowsims/classic/sim/core/stats" +) + +func (hunter *Hunter) getExplosiveTrapConfig(rank int, timer *core.Timer) core.SpellConfig { + spellId := [4]int32{0, 409532, 409534, 409535}[rank] + dotDamage := [4]float64{0, 15, 24, 33}[rank] + minDamage := [4]float64{0, 104, 145, 208}[rank] + maxDamage := [4]float64{0, 135, 193, 265}[rank] + manaCost := [4]float64{0, 275, 395, 520}[rank] + level := [4]int{0, 34, 44, 54}[rank] + + numHits := hunter.Env.GetNumTargets() + + return core.SpellConfig{ + SpellCode: SpellCode_HunterExplosiveTrap, + ActionID: core.ActionID{SpellID: spellId}, + SpellSchool: core.SpellSchoolFire, + DefenseType: core.DefenseTypeMagic, + ProcMask: core.ProcMaskSpellDamage, + Flags: core.SpellFlagAPL | SpellFlagTrap, + Rank: rank, + RequiredLevel: level, + MissileSpeed: 24, + + ManaCost: core.ManaCostOptions{ + FlatCost: manaCost, + }, + Cast: core.CastConfig{ + CD: core.Cooldown{ + Timer: timer, + Duration: time.Second * 15, + }, + DefaultCast: core.Cast{ + GCD: core.GCDDefault, + }, + IgnoreHaste: true, // Hunter GCD is locked at 1.5s + }, + + DamageMultiplier: 1, + ThreatMultiplier: 1, + + Dot: core.DotConfig{ + IsAOE: true, + Aura: core.Aura{ + Label: "ExplosiveTrap" + hunter.Label + strconv.Itoa(rank), + Tag: "ExplosiveTrap", + }, + NumberOfTicks: 10, + TickLength: time.Second * 2, + + OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { + dot.Snapshot(target, dotDamage, isRollover) + }, + OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { + for _, aoeTarget := range sim.Encounter.TargetUnits { + // Explosive Trap DoT only does damage if the target does not have an immolation trap ticking on them + if !aoeTarget.HasActiveAuraWithTag("ImmolationTrap") { + dot.CalcAndDealPeriodicSnapshotDamage(sim, aoeTarget, dot.OutcomeTick) + } + } + }, + }, + + ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { + if hunter.DistanceFromTarget > 5 { + return + } + + spell.WaitTravelTime(sim, func(s *core.Simulation) { + curTarget := target + // Traps gain no benefit from hit bonuses except for the Trap Mastery talent, since this is a unique interaction this is my workaround + spellHit := spell.Unit.GetStat(stats.SpellHit) + target.PseudoStats.BonusSpellHitRatingTaken + spell.Unit.AddStatDynamic(sim, stats.SpellHit, spellHit*-1) + for hitIndex := int32(0); hitIndex < numHits; hitIndex++ { + baseDamage := sim.Roll(minDamage, maxDamage) + baseDamage *= sim.Encounter.AOECapMultiplier() + spell.CalcAndDealDamage(sim, curTarget, baseDamage, spell.OutcomeMagicHitAndCrit) + curTarget = sim.Environment.NextTargetUnit(curTarget) + } + spell.Unit.AddStatDynamic(sim, stats.SpellHit, spellHit) + spell.AOEDot().ApplyOrReset(sim) + }) + }, + } +} + +func (hunter *Hunter) registerExplosiveTrapSpell(timer *core.Timer) { + maxRank := 3 + for i := 1; i <= maxRank; i++ { + config := hunter.getExplosiveTrapConfig(i, timer) + + if config.RequiredLevel <= int(hunter.Level) { + hunter.ExplosiveTrap = hunter.GetOrRegisterSpell(config) + } + } +} diff --git a/sim/hunter/immolation_trap.go b/sim/hunter/immolation_trap.go index 53031feb8a..2edb88d825 100644 --- a/sim/hunter/immolation_trap.go +++ b/sim/hunter/immolation_trap.go @@ -51,7 +51,7 @@ func (hunter *Hunter) getImmolationTrapConfig(rank int, timer *core.Timer) core. TickLength: time.Millisecond * 1500, OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - tickDamage := (dotDamage + hunter.tntDamageFlatBonus()) / float64(dot.NumberOfTicks) + tickDamage := dotDamage / float64(dot.NumberOfTicks) dot.Snapshot(target, tickDamage, isRollover) }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { @@ -60,7 +60,7 @@ func (hunter *Hunter) getImmolationTrapConfig(rank int, timer *core.Timer) core. }, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if hunter.DistanceFromTarget > hunter.trapRange() { + if hunter.DistanceFromTarget > 5 { return } // Traps gain no benefit from hit bonuses except for the Trap Mastery talent, since this is a unique interaction this is my workaround diff --git a/sim/hunter/mongoose_bite.go b/sim/hunter/mongoose_bite.go index fc39435508..d5630986bb 100644 --- a/sim/hunter/mongoose_bite.go +++ b/sim/hunter/mongoose_bite.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) func (hunter *Hunter) getMongooseBiteConfig(rank int) core.SpellConfig { @@ -13,10 +12,6 @@ func (hunter *Hunter) getMongooseBiteConfig(rank int) core.SpellConfig { manaCost := [5]float64{0, 30, 40, 50, 65}[rank] level := [5]int{0, 16, 30, 44, 58}[rank] - hasCobraSlayer := hunter.HasRune(proto.HunterRune_RuneHandsCobraSlayer) - hasRaptorFury := hunter.HasRune(proto.HunterRune_RuneBracersRaptorFury) - hasMeleeSpecialist := hunter.HasRune(proto.HunterRune_RuneBeltMeleeSpecialist) - spellConfig := core.SpellConfig{ SpellCode: SpellCode_HunterMongooseBite, ActionID: core.ActionID{SpellID: spellId}, @@ -52,24 +47,7 @@ func (hunter *Hunter) getMongooseBiteConfig(rank int) core.SpellConfig { ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { hunter.DefensiveState.Deactivate(sim) - - if hasMeleeSpecialist && sim.Proc(0.3, "Raptor Strike Reset") { - hunter.RaptorStrike.CD.Reset() - spell.CD.Reset() - } - - multiplier := 1.0 - if hasRaptorFury { - multiplier *= hunter.raptorFuryDamageMultiplier() - } - - damage := baseDamage - if hasCobraSlayer { - damage += spell.MeleeAttackPower() * 0.45 - } - damage *= multiplier - - spell.CalcAndDealDamage(sim, target, damage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) + spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) }, } diff --git a/sim/hunter/multi_shot.go b/sim/hunter/multi_shot.go index a3a62a2ae0..eb605c7065 100644 --- a/sim/hunter/multi_shot.go +++ b/sim/hunter/multi_shot.go @@ -16,8 +16,6 @@ func (hunter *Hunter) getMultiShotConfig(rank int, timer *core.Timer) core.Spell numHits := min(3, hunter.Env.GetNumTargets()) results := make([]*core.SpellResult, numHits) - hasSerpentSpread := hunter.HasRune(proto.HunterRune_RuneLegsSerpentSpread) - return core.SpellConfig{ SpellCode: SpellCode_HunterMultiShot, ActionID: core.ActionID{SpellID: spellId}, @@ -77,21 +75,6 @@ func (hunter *Hunter) getMultiShotConfig(rank int, timer *core.Timer) core.Spell for hitIndex := int32(0); hitIndex < numHits; hitIndex++ { spell.DealDamage(sim, results[hitIndex]) - if hasSerpentSpread { - serpentStingAura := hunter.SerpentSting.Dot(curTarget) - serpentStingTicks := serpentStingAura.NumberOfTicks - if serpentStingAura.IsActive() { - // If less then 4 ticks are left then we rollover with a 4 tick duration - serpentStingAura.NumberOfTicks = max(4, serpentStingAura.NumberOfTicks-serpentStingAura.TickCount) - serpentStingAura.Rollover(sim) - } else { - // Else we apply with a 4 tick duration - serpentStingAura.NumberOfTicks = 4 - serpentStingAura.Apply(sim) - } - serpentStingAura.NumberOfTicks = serpentStingTicks - } - curTarget = sim.Environment.NextTargetUnit(curTarget) } }) diff --git a/sim/hunter/rapid_fire.go b/sim/hunter/rapid_fire.go index 164b9e9403..92d71ec25f 100644 --- a/sim/hunter/rapid_fire.go +++ b/sim/hunter/rapid_fire.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) func (hunter *Hunter) registerRapidFire() { @@ -12,10 +11,8 @@ func (hunter *Hunter) registerRapidFire() { return } - hasRapidKilling := hunter.HasRune(proto.HunterRune_RuneHelmRapidKilling) - actionID := core.ActionID{SpellID: 3045} - cooldown := core.TernaryDuration(hasRapidKilling, time.Minute*1, time.Minute*5) + cooldown := time.Minute * 5 hunter.RapidFireAura = hunter.RegisterAura(core.Aura{ Label: "Rapid Fire", @@ -24,15 +21,9 @@ func (hunter *Hunter) registerRapidFire() { OnGain: func(aura *core.Aura, sim *core.Simulation) { aura.Unit.MultiplyRangedSpeed(sim, 1.4) - if hasRapidKilling { - aura.Unit.MultiplyMeleeSpeed(sim, 1.4) - } }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { aura.Unit.MultiplyRangedSpeed(sim, 1/1.4) - if hasRapidKilling { - aura.Unit.MultiplyMeleeSpeed(sim, 1/1.4) - } }, }) diff --git a/sim/hunter/raptor_strike.go b/sim/hunter/raptor_strike.go index 4c8cc4a6a6..8f0a56db91 100644 --- a/sim/hunter/raptor_strike.go +++ b/sim/hunter/raptor_strike.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const RaptorStrikeRanks = 8 @@ -69,7 +68,6 @@ func (hunter *Hunter) getRaptorStrikeConfig(rank int) core.SpellConfig { func (hunter *Hunter) newRaptorStrikeHitSpell(rank int) *core.Spell { spellID := RaptorStrikeSpellId[rank] baseDamage := RaptorStrikeBaseDamage[rank] - damageFunc := hunter.MHWeaponDamage return hunter.RegisterSpell(core.SpellConfig{ SpellCode: SpellCode_HunterRaptorStrikeHit, diff --git a/sim/hunter/serpent_sting.go b/sim/hunter/serpent_sting.go index f2034b34c8..c3a9cf4433 100644 --- a/sim/hunter/serpent_sting.go +++ b/sim/hunter/serpent_sting.go @@ -76,39 +76,6 @@ func (hunter *Hunter) getSerpentStingConfig(rank int) core.SpellConfig { } } -func (hunter *Hunter) chimeraShotSerpentStingSpell(rank int) *core.Spell { - baseDamage := [10]float64{0, 20, 40, 80, 140, 210, 290, 385, 490, 555}[rank] - spellCoeff := [10]float64{0, .4, .625, .925, 1, 1, 1, 1, 1, 1}[rank] - return hunter.RegisterSpell(core.SpellConfig{ - SpellCode: SpellCode_HunterChimeraSerpent, - ActionID: core.ActionID{SpellID: 409493}, - SpellSchool: core.SpellSchoolNature, - CastType: proto.CastType_CastTypeRanged, - DefenseType: core.DefenseTypeRanged, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagPassiveSpell, - MissileSpeed: 24, - - BonusCritRating: 1, - - CritDamageBonus: hunter.mortalShots(), - - DamageMultiplier: 0.48, - DamageMultiplierAdditive: 1 + 0.02*float64(hunter.Talents.ImprovedSerpentSting), - ThreatMultiplier: 1, - BonusCoefficient: spellCoeff, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - // As of phase 5 the only time serpent sting scales with AP is using the Dragonstalker's Pursuit 6P - this AP scaling doesn't benefit from target AP modifiers - damage := baseDamage + (hunter.SerpentStingAPCoeff * spell.RangedAttackPower(target, true)) - result := spell.CalcDamage(sim, target, damage, spell.OutcomeRangedHitAndCrit) - spell.WaitTravelTime(sim, func(s *core.Simulation) { - spell.DealDamage(sim, result) - }) - }, - }) -} - func (hunter *Hunter) registerSerpentStingSpell() { hunter.SerpentStingAPCoeff = 0 diff --git a/sim/hunter/volley.go b/sim/hunter/volley.go index 1caa8ee2e9..23773247e6 100644 --- a/sim/hunter/volley.go +++ b/sim/hunter/volley.go @@ -5,8 +5,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" ) func (hunter *Hunter) registerVolleySpell() { @@ -31,7 +29,7 @@ func (hunter *Hunter) getVolleyConfig(rank int) core.SpellConfig { manaCostModifer := 100 - 2*hunter.Talents.Efficiency return core.SpellConfig{ - SpellCode: SpellCode_HunterVolley, + SpellCode: SpellCode_HunterVolley, ActionID: core.ActionID{SpellID: spellId}, SpellSchool: core.SpellSchoolArcane, ProcMask: core.ProcMaskSpellDamage, @@ -41,7 +39,7 @@ func (hunter *Hunter) getVolleyConfig(rank int) core.SpellConfig { Rank: rank, ManaCost: core.ManaCostOptions{ - FlatCost: manaCost, + FlatCost: manaCost, Multiplier: manaCostModifer, }, Cast: core.CastConfig{ From d7f33bb0aae04b3d359b5281af40a7d431ce99be Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 15:54:16 -0500 Subject: [PATCH 76/83] paladin --- sim/paladin/aura_mastery.go | 56 ------------- sim/paladin/avengers_shield.go | 104 ------------------------- sim/paladin/blessing_of_sanctuary.go | 11 +-- sim/paladin/consecration.go | 13 +--- sim/paladin/crusader_strike.go | 64 --------------- sim/paladin/divine_storm.go | 70 ----------------- sim/paladin/exorcism.go | 20 ++--- sim/paladin/hammer_of_the_righteous.go | 60 -------------- sim/paladin/hammer_of_wrath.go | 11 +-- sim/paladin/holy_shock.go | 48 ++---------- sim/paladin/holy_wrath.go | 11 +-- sim/paladin/judgement.go | 36 +-------- sim/paladin/paladin.go | 103 +++++------------------- sim/paladin/righteous_fury.go | 40 +--------- sim/paladin/righteous_vengeance.go | 74 ------------------ sim/paladin/shield_of_righteousness.go | 50 ------------ sim/paladin/soc.go | 4 +- sim/paladin/som.go | 102 ------------------------ sim/paladin/sor.go | 2 +- 19 files changed, 46 insertions(+), 833 deletions(-) delete mode 100644 sim/paladin/aura_mastery.go delete mode 100644 sim/paladin/avengers_shield.go delete mode 100644 sim/paladin/crusader_strike.go delete mode 100644 sim/paladin/divine_storm.go delete mode 100644 sim/paladin/hammer_of_the_righteous.go delete mode 100644 sim/paladin/righteous_vengeance.go delete mode 100644 sim/paladin/shield_of_righteousness.go delete mode 100644 sim/paladin/som.go diff --git a/sim/paladin/aura_mastery.go b/sim/paladin/aura_mastery.go deleted file mode 100644 index cd8bd9d87c..0000000000 --- a/sim/paladin/aura_mastery.go +++ /dev/null @@ -1,56 +0,0 @@ -package paladin - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (paladin *Paladin) registerAuraMastery() { - - if !paladin.hasRune(proto.PaladinRune_RuneLegsAuraMastery) { - return - } - - cd := core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Minute * 2, - } - - aura := paladin.RegisterAura(core.Aura{ - Label: "Aura Mastery", - ActionID: core.ActionID{SpellID: int32(proto.PaladinRune_RuneLegsAuraMastery)}, - Duration: time.Second * 6, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - if paladin.currentPaladinAura != nil { - if paladin.currentPaladinAura.Label == "Sanctity Aura" { - paladin.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexHoly] *= (1.2 / 1.1) - } - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - if paladin.currentPaladinAura != nil { - if paladin.currentPaladinAura.Label == "Sanctity Aura" { - paladin.PseudoStats.SchoolDamageDealtMultiplier[stats.SchoolIndexHoly] /= (1.2 / 1.1) - } - } - }, - }) - - auraMastery := paladin.RegisterSpell(core.SpellConfig{ - ActionID: aura.ActionID, - Flags: core.SpellFlagNoOnCastComplete, - Cast: core.CastConfig{ - CD: cd, - }, - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - aura.Activate(sim) - }, - }) - paladin.AddMajorCooldown(core.MajorCooldown{ - Spell: auraMastery, - Type: core.CooldownTypeDPS, - }) -} diff --git a/sim/paladin/avengers_shield.go b/sim/paladin/avengers_shield.go deleted file mode 100644 index bf40f417f1..0000000000 --- a/sim/paladin/avengers_shield.go +++ /dev/null @@ -1,104 +0,0 @@ -package paladin - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -// The Arcane Shot of a Hunter, and the Hammer of Wrath and Avenger's Shield talent of a -// Protection-specced Paladin, are resolved as ranged attacks that do non-physical damage. -// They can miss—rather than be "fully resisted"—and they do double damage on a crit. -// The only difference is that if a mob target is higher level than the player attacker, -// or if the target has any resistance to the school of magic used by the attack, the same -// check is made to see if the damage is partially resisted as would happen from a spell. -// https://wowwiki-archive.fandom.com/wiki/Attack_table#Magic-damage_ranged_special_attacks -func (paladin *Paladin) registerAvengersShield() { - if !paladin.hasRune(proto.PaladinRune_RuneLegsAvengersShield) { - return - } - - hasLibramOfAvenging := false // paladin.Ranged().ID == LibramOfAvenging - - // Avenger's Shield hits up to 3 targets. It cannot miss or be resisted. - numTargets := min(3, int(paladin.Env.GetNumTargets())) - - lowDamage := 366 * paladin.baseRuneAbilityDamage() / 100 - highDamage := 448 * paladin.baseRuneAbilityDamage() / 100 - - paladin.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: int32(proto.PaladinRune_RuneLegsAvengersShield)}, - SpellCode: SpellCode_PaladinAvengersShield, - SpellSchool: core.SpellSchoolHoly, - DefenseType: core.DefenseTypeRanged, // Crits as if melee for 200% - ProcMask: core.ProcMaskRangedSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | core.SpellFlagBinary, - MissileSpeed: 35, // Verified from game files using WoW tools. - ManaCost: core.ManaCostOptions{ - BaseCost: 0.26, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Second * 15, - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return paladin.OffHand().WeaponType == proto.WeaponType_WeaponTypeShield - }, - DamageMultiplier: 1, - ThreatMultiplier: 1, - BonusCoefficient: 0.091, // for spell damage; we add the AP bonus manually - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - apBonus := 0.091 * spell.MeleeAttackPower() - baseTravelTime := spell.TravelTime() - - if hasLibramOfAvenging { - // Libram of Avenging causes Avenger's Shield to be single target, but it - // hits the target twice. The second projectile fires after a fixed 1.5s delay. - firstHit := spell.CalcDamage(sim, target, sim.Roll(lowDamage, highDamage)+apBonus, spell.OutcomeRangedHitAndCrit) - spell.WaitTravelTime(sim, func(sim *core.Simulation) { - spell.DealDamage(sim, firstHit) - }) - - secondHit := spell.CalcDamage(sim, target, sim.Roll(lowDamage, highDamage)+apBonus, spell.OutcomeRangedHitAndCrit) - timeToSecondHit := baseTravelTime + time.Millisecond*1500 - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + timeToSecondHit, - OnAction: func(s *core.Simulation) { - spell.DealDamage(sim, secondHit) - }, - }) - - } else { - interTargetTravelTime := int(float64(time.Second) * 3.0 / spell.MissileSpeed) - for i := 0; i < numTargets; i++ { - // Avenger's Shield bounces from target 1 > target 2 > target 3 at MissileSpeed. - // We approximate it by assuming targets are standing ~3 yds apart from each other. - // The damage for each target is therefore scheduled to arrive at: - // T1 = (TravelTime from player; by default 5 yard max melee range) - // T2 = T1 + (3 yd TravelTime) - // T3 = T2 + (3 yd TravelTime) - baseDamage := sim.Roll(lowDamage, highDamage) + apBonus - delay := time.Duration(interTargetTravelTime * i) - nextTarget := target // create new ref for delayed action evaluation - result := spell.CalcDamage(sim, nextTarget, baseDamage, spell.OutcomeRangedHitAndCrit) - - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + baseTravelTime + delay, - OnAction: func(s *core.Simulation) { - spell.DealDamage(sim, result) - - }, - }) - target = sim.NextTargetUnit(target) - } - } - }, - }) -} diff --git a/sim/paladin/blessing_of_sanctuary.go b/sim/paladin/blessing_of_sanctuary.go index 09d02e8ff7..36f9a40fa5 100644 --- a/sim/paladin/blessing_of_sanctuary.go +++ b/sim/paladin/blessing_of_sanctuary.go @@ -23,18 +23,13 @@ func (paladin *Paladin) registerBlessingOfSanctuary() { {minLevel: 60, maxLevel: 60, spellID: 20914, absorb: 24, damage: 35}, } - hasImpSanc := paladin.hasRune(proto.PaladinRune_RuneHeadImprovedSanctuary) - absorbMult := core.TernaryFloat64(hasImpSanc, 2, 1) - bonusDamage := core.TernaryFloat64(hasImpSanc, 0.3, 0.0) - for i, values := range sanctuaryValues { if (values.minLevel <= paladin.Level) && (paladin.Level <= values.maxLevel) { rank := i + 1 actionID := core.ActionID{SpellID: values.spellID} - absorb := values.absorb * absorbMult - damage := values.damage + bonusDamage*paladin.BlockValue() + damage := values.damage sanctuaryProc := paladin.RegisterSpell(core.SpellConfig{ ActionID: actionID, @@ -61,12 +56,12 @@ func (paladin *Paladin) registerBlessingOfSanctuary() { }, OnGain: func(aura *core.Aura, sim *core.Simulation) { for i := range paladin.PseudoStats.BonusDamageTakenBeforeModifiers { - paladin.PseudoStats.BonusDamageTakenBeforeModifiers[i] -= absorb + paladin.PseudoStats.BonusDamageTakenBeforeModifiers[i] -= values.absorb } }, OnExpire: func(aura *core.Aura, sim *core.Simulation) { for i := range paladin.PseudoStats.BonusDamageTakenBeforeModifiers { - paladin.PseudoStats.BonusDamageTakenBeforeModifiers[i] += absorb + paladin.PseudoStats.BonusDamageTakenBeforeModifiers[i] += values.absorb } }, OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { diff --git a/sim/paladin/consecration.go b/sim/paladin/consecration.go index c5d65be58f..ec7c59ecf9 100644 --- a/sim/paladin/consecration.go +++ b/sim/paladin/consecration.go @@ -4,9 +4,6 @@ import ( "strconv" "time" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" - "github.com/wowsims/classic/sim/core" ) @@ -33,8 +30,6 @@ func (paladin *Paladin) registerConsecration() { Duration: time.Second * 8, } - hasWrath := paladin.hasRune(proto.PaladinRune_RuneHeadWrath) - for i, rank := range ranks { rank := rank if paladin.Level < rank.level { @@ -76,18 +71,12 @@ func (paladin *Paladin) registerConsecration() { OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { dot.Snapshot(target, rank.damage, isRollover) - if hasWrath { - dot.Spell.BonusCritRating += paladin.GetStat(stats.MeleeCrit) - dot.SnapshotCritChance = dot.Spell.SpellCritChance(target) - dot.Spell.BonusCritRating -= paladin.GetStat(stats.MeleeCrit) - } }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { // Consecration can miss, showing up as either a resist in logs or a // silent failure (missing damage tick). - outcomeApplier := core.Ternary(hasWrath, dot.OutcomeMagicHitAndSnapshotCrit, dot.Spell.OutcomeMagicHit) for _, aoeTarget := range sim.Encounter.TargetUnits { - dot.CalcAndDealPeriodicSnapshotDamage(sim, aoeTarget, outcomeApplier) + dot.CalcAndDealPeriodicSnapshotDamage(sim, aoeTarget, dot.Spell.OutcomeMagicHit) } }, }, diff --git a/sim/paladin/crusader_strike.go b/sim/paladin/crusader_strike.go deleted file mode 100644 index 801498bc73..0000000000 --- a/sim/paladin/crusader_strike.go +++ /dev/null @@ -1,64 +0,0 @@ -package paladin - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -// Crusader Strike is an ap-normalised instant attack that has a weapon damage % modifier with a 0.75 coefficient. -// It also returns 5% of the paladin's maximum mana when cast, regardless of the ability being negated. -// As of 27/02/24 it deals holy school damage, but otherwise behaves like a melee attack. - -func (paladin *Paladin) registerCrusaderStrike() { - if !paladin.hasRune(proto.PaladinRune_RuneHandsCrusaderStrike) { - return - } - - manaMetrics := paladin.NewManaMetrics(core.ActionID{SpellID: int32(proto.PaladinRune_RuneHandsCrusaderStrike)}) - - crusaderStrikeSpell := paladin.RegisterSpell(core.SpellConfig{ - ActionID: manaMetrics.ActionID, - SpellSchool: core.SpellSchoolHoly, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | SpellFlag_RV | core.SpellFlagIgnoreResists, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, // cs is on phys gcd, which cannot be hasted - CD: core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Second * 6, - }, - }, - - DamageMultiplier: 0.75 * paladin.getWeaponSpecializationModifier(), - ThreatMultiplier: 1, - SpellCode: SpellCode_PaladinCrusaderStrike, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := spell.Unit.MHNormalizedWeaponDamage(sim, spell.MeleeAttackPower()) - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + core.SpellBatchWindow, - OnAction: func(s *core.Simulation) { - spell.DealDamage(sim, result) - }, - }) - - paladin.AddMana(sim, 0.05*paladin.MaxMana(), manaMetrics) - - for _, aura := range target.GetAurasWithTag(core.JudgementAuraTag) { - if aura.IsActive() && aura.Duration < core.NeverExpires { - aura.UpdateExpires(sim, sim.CurrentTime+time.Second*30) - } - } - }, - }) - - paladin.crusaderStrike = crusaderStrikeSpell -} diff --git a/sim/paladin/divine_storm.go b/sim/paladin/divine_storm.go deleted file mode 100644 index 5ee614b7af..0000000000 --- a/sim/paladin/divine_storm.go +++ /dev/null @@ -1,70 +0,0 @@ -package paladin - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -// Divine Storm is a non-ap normalised instant attack that has a weapon damage % modifier with a 1.1 coefficient. -// It does this damage to up to 4 targets in range. -// DS also heals up to 3 party or raid members for 25% of the total damage caused. This has implications for prot -// paladin threat, so we'll implement this as a heal to the casting paladin for now. - -func (paladin *Paladin) registerDivineStorm() { - if !paladin.hasRune(proto.PaladinRune_RuneChestDivineStorm) { - return - } - - results := make([]*core.SpellResult, min(4, paladin.Env.GetNumTargets())) - - healthMetrics := paladin.NewHealthMetrics(core.ActionID{SpellID: int32(proto.PaladinRune_RuneChestDivineStorm)}) - - divineStormSpell := paladin.RegisterSpell(core.SpellConfig{ - ActionID: healthMetrics.ActionID, - SpellSchool: core.SpellSchoolPhysical, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | SpellFlag_RV, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.12, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Second * 10, - }, - }, - - DamageMultiplier: 1.1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - - for idx := range results { - baseDamage := spell.Unit.MHWeaponDamage(sim, spell.MeleeAttackPower()) - results[idx] = spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - target = sim.Environment.NextTargetUnit(target) - } - - for _, result := range results { - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + core.SpellBatchWindow, - OnAction: func(s *core.Simulation) { - spell.DealDamage(sim, result) - paladin.GainHealth(sim, result.Damage*0.25, healthMetrics) - }, - }) - } - - }, - }) - - paladin.divineStorm = divineStormSpell -} diff --git a/sim/paladin/exorcism.go b/sim/paladin/exorcism.go index e33613ee5a..a62b146af6 100644 --- a/sim/paladin/exorcism.go +++ b/sim/paladin/exorcism.go @@ -3,8 +3,6 @@ package paladin import ( "time" - "github.com/wowsims/classic/sim/core/stats" - "github.com/wowsims/classic/sim/core" "github.com/wowsims/classic/sim/core/proto" ) @@ -27,13 +25,6 @@ func (paladin *Paladin) registerExorcism() { {level: 60, spellID: 415073, manaCost: 345, scaleLevel: 60, minDamage: 505, maxDamage: 563, scale: 3.2}, } - hasWrath := paladin.hasRune(proto.PaladinRune_RuneHeadWrath) - - paladin.exorcismCooldown = &core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Second * 15, - } - for i, rank := range ranks { rank := rank if paladin.Level < rank.level { @@ -55,15 +46,17 @@ func (paladin *Paladin) registerExorcism() { SpellCode: SpellCode_PaladinExorcism, ManaCost: core.ManaCostOptions{ - FlatCost: rank.manaCost, - Multiplier: core.TernaryInt32(paladin.hasRune(proto.PaladinRune_RuneFeetTheArtOfWar), 20, 100), + FlatCost: rank.manaCost, }, Cast: core.CastConfig{ DefaultCast: core.Cast{ GCD: core.GCDDefault, }, - CD: *paladin.exorcismCooldown, + CD: core.Cooldown{ + Timer: paladin.NewTimer(), + Duration: time.Second * 15, + }, }, DamageMultiplier: 1, @@ -76,9 +69,6 @@ func (paladin *Paladin) registerExorcism() { if target.MobType == proto.MobType_MobTypeDemon || target.MobType == proto.MobType_MobTypeUndead { bonusCrit += 100 * core.CritRatingPerCritChance } - if hasWrath { - bonusCrit += paladin.GetStat(stats.MeleeCrit) - } spell.BonusCritRating += bonusCrit spell.CalcAndDealDamage(sim, target, sim.Roll(minDamage, maxDamage), spell.OutcomeMagicHitAndCrit) diff --git a/sim/paladin/hammer_of_the_righteous.go b/sim/paladin/hammer_of_the_righteous.go deleted file mode 100644 index b09a41339b..0000000000 --- a/sim/paladin/hammer_of_the_righteous.go +++ /dev/null @@ -1,60 +0,0 @@ -package paladin - -import ( - "slices" - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (paladin *Paladin) registerHammerOfTheRighteous() { - if !paladin.hasRune(proto.PaladinRune_RuneWristHammerOfTheRighteous) { - return - } - - // Phase 4: Hammer of the Righteous damage reduced by 50% but threat increased by 2X. - // https://www.wowhead.com/classic/news/development-notes-for-phase-4-ptr-season-of-discovery-new-runes-class-changes-3428960 - results := make([]*core.SpellResult, min(3, paladin.Env.GetNumTargets())) - - paladin.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: int32(proto.PaladinRune_RuneWristHammerOfTheRighteous)}, - SpellSchool: core.SpellSchoolHoly, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL | core.SpellFlagIgnoreResists, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.06, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: false, - CD: core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Second * 6, - }, - }, - ExtraCastCondition: func(sim *core.Simulation, target *core.Unit) bool { - return slices.Contains([]proto.HandType{proto.HandType_HandTypeMainHand, proto.HandType_HandTypeOneHand}, paladin.MainHand().HandType) - }, - DamageMultiplier: 1, - ThreatMultiplier: 2, // verified with TinyThreat in game - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - weapon := paladin.AutoAttacks.MH() - baseDamage := 3.0 * (weapon.CalculateAverageWeaponDamage(spell.MeleeAttackPower()) / weapon.SwingSpeed) - - for idx := range results { - results[idx] = spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - target = sim.Environment.NextTargetUnit(target) - } - - for _, result := range results { - spell.DealDamage(sim, result) - } - }, - }) -} diff --git a/sim/paladin/hammer_of_wrath.go b/sim/paladin/hammer_of_wrath.go index 5429fdaed2..9ab3f3c245 100644 --- a/sim/paladin/hammer_of_wrath.go +++ b/sim/paladin/hammer_of_wrath.go @@ -26,8 +26,6 @@ func (paladin *Paladin) registerHammerOfWrath() { Duration: time.Second * 6, } - hasImprovedHammerOfWrath := paladin.hasRune(proto.PaladinRune_RuneWristImprovedHammerOfWrath) - for i, rank := range ranks { rank := rank if paladin.Level < rank.level { @@ -52,7 +50,7 @@ func (paladin *Paladin) registerHammerOfWrath() { Cast: core.CastConfig{ DefaultCast: core.Cast{ GCD: time.Second, - CastTime: core.TernaryDuration(hasImprovedHammerOfWrath, 0, time.Second), + CastTime: time.Second, }, IgnoreHaste: true, CD: cd, @@ -69,12 +67,7 @@ func (paladin *Paladin) registerHammerOfWrath() { ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { damage := sim.Roll(rank.minDamage, rank.maxDamage) - result := spell.CalcAndDealDamage(sim, target, damage, spell.OutcomeRangedHitAndCrit) - - // should be based on target.CurrentHealthPercent(), which is not available - if hasImprovedHammerOfWrath && result.Landed() && sim.CurrentTime >= time.Duration(0.9*float64(sim.Duration)) { - cd.Reset() - } + spell.CalcAndDealDamage(sim, target, damage, spell.OutcomeRangedHitAndCrit) }, }) } diff --git a/sim/paladin/holy_shock.go b/sim/paladin/holy_shock.go index 0ec0434db9..e8b27a1b88 100644 --- a/sim/paladin/holy_shock.go +++ b/sim/paladin/holy_shock.go @@ -3,26 +3,10 @@ package paladin import ( "time" - "github.com/wowsims/classic/sim/core/stats" - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) func (paladin *Paladin) registerHolyShock() { - - hasInfusionOfLight := paladin.hasRune(proto.PaladinRune_RuneWaistInfusionOfLight) - - cdTime := time.Second * 30 - if hasInfusionOfLight { - cdTime = time.Second * 6 - } - - paladin.holyShockCooldown = &core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: cdTime, - } - if !paladin.Talents.HolyShock { return } @@ -39,15 +23,6 @@ func (paladin *Paladin) registerHolyShock() { {level: 56, spellID: 20930, manaCost: 325, minDamage: 365, maxDamage: 395}, } - damageMultiplier := core.TernaryFloat64(hasInfusionOfLight, 1.5, 1.0) - - //hasArtOfWar := paladin.hasRune(proto.PaladinRune_RuneFeetTheArtOfWar) - manaCostMultiplier := int32(100) //core.TernaryFloat64(hasArtOfWar, 0.2, 1.0) - - hasWrath := paladin.hasRune(proto.PaladinRune_RuneHeadWrath) - - manaMetrics := paladin.NewManaMetrics(core.ActionID{SpellID: 437063}) // Infusion of Light mana restore - for i, rank := range ranks { rank := rank if paladin.Level < rank.level { @@ -67,35 +42,26 @@ func (paladin *Paladin) registerHolyShock() { SpellCode: SpellCode_PaladinHolyShock, ManaCost: core.ManaCostOptions{ - FlatCost: rank.manaCost, - Multiplier: manaCostMultiplier, + FlatCost: rank.manaCost, }, Cast: core.CastConfig{ DefaultCast: core.Cast{ GCD: core.GCDDefault, }, - CD: *paladin.holyShockCooldown, + CD: core.Cooldown{ + Timer: paladin.NewTimer(), + Duration: time.Second * 30, + }, }, - DamageMultiplier: damageMultiplier, + DamageMultiplier: 1, ThreatMultiplier: 1, BonusCoefficient: 0.429, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { baseDamage := sim.Roll(rank.minDamage, rank.maxDamage) - - bonusCrit := core.TernaryFloat64(hasWrath, paladin.GetStat(stats.MeleeCrit), 0) - spell.BonusCritRating += bonusCrit - result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - spell.BonusCritRating -= bonusCrit - - // If we crit, Infusion of Light refunds base mana cost and reduces next Holy Shock Cooldown by 3 seconds - if hasInfusionOfLight && result.Outcome.Matches(core.OutcomeCrit) { - paladin.AddMana(sim, rank.manaCost, manaMetrics) - paladin.holyShockCooldown.Set(sim.CurrentTime + max(0, paladin.holyShockCooldown.TimeToReady(sim)-(time.Second*3))) - - } + spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) }, }) } diff --git a/sim/paladin/holy_wrath.go b/sim/paladin/holy_wrath.go index 5533f37d9f..b393ede162 100644 --- a/sim/paladin/holy_wrath.go +++ b/sim/paladin/holy_wrath.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" "github.com/wowsims/classic/sim/core" ) @@ -23,9 +22,6 @@ func (paladin *Paladin) registerHolyWrath() { {level: 60, spellID: 10318, manaCost: 805, scaleLevel: 60, minDamage: 490, maxDamage: 576, scale: 1.9}, } - hasPurifyingPower := paladin.hasRune(proto.PaladinRune_RuneWristPurifyingPower) - hasWrath := paladin.hasRune(proto.PaladinRune_RuneHeadWrath) - var results []*core.SpellResult for i, rank := range ranks { @@ -68,12 +64,9 @@ func (paladin *Paladin) registerHolyWrath() { BonusCoefficient: 0.19, ApplyEffects: func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { - bonusCrit := core.TernaryFloat64(hasWrath, paladin.GetStat(stats.MeleeCrit), 0) - spell.BonusCritRating += bonusCrit - results = results[:0] for _, target := range paladin.Env.Encounter.TargetUnits { - if hasPurifyingPower || (target.MobType == proto.MobType_MobTypeDemon || target.MobType == proto.MobType_MobTypeUndead) { + if target.MobType == proto.MobType_MobTypeDemon || target.MobType == proto.MobType_MobTypeUndead { damage := sim.Roll(minDamage, maxDamage) result := spell.CalcDamage(sim, target, damage, spell.OutcomeMagicHitAndCrit) results = append(results, result) @@ -83,8 +76,6 @@ func (paladin *Paladin) registerHolyWrath() { for _, result := range results { spell.DealDamage(sim, result) } - - spell.BonusCritRating -= bonusCrit }, }) diff --git a/sim/paladin/judgement.go b/sim/paladin/judgement.go index d2da4eb27a..987c0f2d3b 100644 --- a/sim/paladin/judgement.go +++ b/sim/paladin/judgement.go @@ -33,45 +33,13 @@ func (paladin *Paladin) registerJudgement() { return paladin.currentSeal.IsActive() }, ApplyEffects: func(sim *core.Simulation, target *core.Unit, _ *core.Spell) { - - // Phase 1-3 - //if paladin.currentJudgement.SpellCode == SpellCode_PaladinJudgementOfCommand { - // spell.CalcAndDealOutcome(sim, target, spell.OutcomeMagicHit) - //} else { - // paladin.currentJudgement.Cast(sim, target) - //} - // paladin.currentSeal.Deactivate(sim) - - // Phase 4 - (Double Judge not tied to T1 6pc bonus) - Judge all Seals (2 possible without 6pc, and with 6pc) - // Random order of Judgements (Server Side - Indeterministic) - - // Phase 5 - (Double Judge now tied to T1 6pc bonus) - Judge all Seals (2 possible with 6pc) - // Otherwise Judge Current Seal, or Previous Seal if two are active - multipleSealsActive := false - if paladin.prevSeal != nil && paladin.prevSeal.IsActive() { - multipleSealsActive = true - } - - if multipleSealsActive { - paladin.castSpecificJudgement(sim, target, paladin.prevJudgement, paladin.prevSeal) - - if paladin.enableMultiJudge { - paladin.castSpecificJudgement(sim, target, paladin.currentJudgement, paladin.currentSeal) - } - } else { - paladin.castSpecificJudgement(sim, target, paladin.currentJudgement, paladin.currentSeal) - } - + paladin.castSpecificJudgement(sim, target, paladin.currentJudgement, paladin.currentSeal) }, }) } // Helper Function For casting Judgement func (paladin *Paladin) castSpecificJudgement(sim *core.Simulation, target *core.Unit, judgementSpell *core.Spell, matchingSeal *core.Aura) { - judgementSpell.Cast(sim, target) - - if paladin.consumeSealsOnJudge { - matchingSeal.Deactivate(sim) - } + matchingSeal.Deactivate(sim) } diff --git a/sim/paladin/paladin.go b/sim/paladin/paladin.go index 1a0287aff5..9b67aa17d4 100644 --- a/sim/paladin/paladin.go +++ b/sim/paladin/paladin.go @@ -1,8 +1,6 @@ package paladin import ( - "time" - "github.com/wowsims/classic/sim/common/guardians" "github.com/wowsims/classic/sim/core" "github.com/wowsims/classic/sim/core/proto" @@ -12,8 +10,7 @@ import ( var TalentTreeSizes = [3]int{14, 15, 15} const ( - SpellFlag_RV = core.SpellFlagAgentReserved1 - SpellFlag_Forbearance = core.SpellFlagAgentReserved2 + SpellFlag_Forbearance = core.SpellFlagAgentReserved1 ) const ( @@ -24,20 +21,17 @@ const ( SpellCode_PaladinHolyWrath SpellCode_PaladinJudgementOfCommand SpellCode_PaladinConsecration - SpellCode_PaladinAvengersShield SpellCode_PaladinHolyShield SpellCode_PaladinHolyShieldProc SpellCode_PaladinLayOnHands SpellCode_PaladinHammerOfWrath - SpellCode_PaladinCrusaderStrike ) type SealJudgeCode uint8 const ( - SealJudgeCodeNone SealJudgeCode = 0 - SealJudgeOfMartyrdomCode SealJudgeCode = 1 << iota - SealJudgeOfRighteousnessCode + SealJudgeCodeNone SealJudgeCode = 0 + SealJudgeOfRighteousnessCode SealJudgeCode = 1 << iota SealJudgeOfCommandCode SealJudgeOfTheCrusaderCode ) @@ -52,42 +46,29 @@ type Paladin struct { primaryPaladinAura proto.PaladinAura currentPaladinAura *core.Aura - currentSeal *core.Aura - prevSeal *core.Aura - allSealAuras [][]*core.Aura - aurasSoM []*core.Aura - aurasSoR []*core.Aura - aurasSoC []*core.Aura - aurasSotC []*core.Aura + currentSeal *core.Aura + allSealAuras [][]*core.Aura + aurasSoR []*core.Aura + aurasSoC []*core.Aura + aurasSotC []*core.Aura + currentJudgement *core.Spell - prevJudgement *core.Spell allJudgeSpells [][]*core.Spell - spellsJoM []*core.Spell spellsJoR []*core.Spell spellsJoC []*core.Spell spellsJotC []*core.Spell // Active abilities and shared cooldowns that are externally manipulated. - holyShockCooldown *core.Cooldown - exorcismCooldown *core.Cooldown - crusaderStrike *core.Spell - divineStorm *core.Spell - exorcism []*core.Spell - judgement *core.Spell - rv *core.Spell - holyShieldAura [3]*core.Aura - holyShieldProc [3]*core.Spell - redoubtAura *core.Aura - holyWrath []*core.Spell + exorcism []*core.Spell + judgement *core.Spell + holyShieldAura [3]*core.Aura + holyShieldProc [3]*core.Spell + redoubtAura *core.Aura + holyWrath []*core.Spell // highest rank seal spell if available sealOfRighteousness *core.Spell sealOfCommand *core.Spell - sealOfMartyrdom *core.Spell - - enableMultiJudge bool - lingerDuration time.Duration - consumeSealsOnJudge bool } // Implemented by each Paladin spec. @@ -117,23 +98,18 @@ func (paladin *Paladin) Initialize() { paladin.registerSealOfRighteousness() paladin.registerSealOfCommand() - paladin.registerSealOfMartyrdom() paladin.registerSealOfTheCrusader() - paladin.allJudgeSpells = append(paladin.allJudgeSpells, paladin.spellsJoM) paladin.allJudgeSpells = append(paladin.allJudgeSpells, paladin.spellsJoR) paladin.allJudgeSpells = append(paladin.allJudgeSpells, paladin.spellsJoC) paladin.allJudgeSpells = append(paladin.allJudgeSpells, paladin.spellsJotC) - paladin.allSealAuras = append(paladin.allSealAuras, paladin.aurasSoM) paladin.allSealAuras = append(paladin.allSealAuras, paladin.aurasSoR) paladin.allSealAuras = append(paladin.allSealAuras, paladin.aurasSoC) paladin.allSealAuras = append(paladin.allSealAuras, paladin.aurasSotC) // Active abilities paladin.registerForbearance() - paladin.registerCrusaderStrike() - paladin.registerDivineStorm() paladin.registerConsecration() paladin.registerHolyShock() paladin.registerExorcism() @@ -141,16 +117,10 @@ func (paladin *Paladin) Initialize() { paladin.registerHammerOfWrath() paladin.registerHolyWrath() paladin.registerAvengingWrath() - paladin.registerAuraMastery() paladin.registerHolyShield() - paladin.registerShieldOfRighteousness() paladin.registerBlessingOfSanctuary() paladin.registerLayOnHands() - paladin.enableMultiJudge = false // Was previously true in Phase 4 but disabled in Phase 5 - paladin.lingerDuration = time.Millisecond * 400 - paladin.consumeSealsOnJudge = true - paladin.registerStopAttackMacros() paladin.ResetCurrentPaladinAura() @@ -202,14 +172,6 @@ func (paladin *Paladin) ResetPrimarySeal(primarySeal proto.PaladinSeal) { } func (paladin *Paladin) registerStopAttackMacros() { - if paladin.divineStorm != nil && paladin.Options.IsUsingDivineStormStopAttack { - paladin.divineStorm.Flags |= core.SpellFlagBatchStopAttackMacro - } - - if paladin.crusaderStrike != nil && paladin.Options.IsUsingCrusaderStrikeStopAttack { - paladin.crusaderStrike.Flags |= core.SpellFlagBatchStopAttackMacro - } - for _, spellsJoX := range paladin.allJudgeSpells { for _, v := range spellsJoX { if v != nil && paladin.Options.IsUsingJudgementStopAttack { @@ -229,8 +191,6 @@ func (paladin *Paladin) ResetCurrentPaladinAura() { func (paladin *Paladin) getPrimarySealSpell(primarySeal proto.PaladinSeal) *core.Spell { // Used in the Cast Primary Seal APLAction to get the max rank spell for the level. switch primarySeal { - case proto.PaladinSeal_Martyrdom: - return paladin.sealOfMartyrdom case proto.PaladinSeal_Command: return paladin.sealOfCommand case proto.PaladinSeal_Righteousness: @@ -241,38 +201,13 @@ func (paladin *Paladin) getPrimarySealSpell(primarySeal proto.PaladinSeal) *core } func (paladin *Paladin) applySeal(newSeal *core.Aura, judgement *core.Spell, sim *core.Simulation) { - isSameSealType := false - if paladin.currentSeal != nil { - if newSeal.Label[:10] == paladin.currentSeal.Label[:10] { - isSameSealType = true - - paladin.currentSeal.Deactivate(sim) - paladin.currentSeal = newSeal - paladin.currentJudgement = judgement - paladin.currentSeal.Activate(sim) - - // Set To nil to avoid issues with multi judging during linger window - if paladin.prevSeal != nil && paladin.prevSeal.IsActive() { - paladin.prevSeal.Deactivate(sim) - } - - paladin.prevSeal = nil - paladin.prevJudgement = nil - } + paladin.currentSeal.Deactivate(sim) } - if !isSameSealType { - if paladin.currentSeal.IsActive() { - paladin.currentSeal.UpdateExpires(sim, sim.CurrentTime+paladin.lingerDuration) // always update, even if it extends duration - } - - paladin.prevSeal = paladin.currentSeal - paladin.currentSeal = newSeal - paladin.prevJudgement = paladin.currentJudgement // Judgment Spell for the previous Seal (doesn't mean it was cast) - paladin.currentJudgement = judgement - paladin.currentSeal.Activate(sim) - } + paladin.currentSeal = newSeal + paladin.currentJudgement = judgement + paladin.currentSeal.Activate(sim) } func (paladin *Paladin) getLibramSealCostReduction() float64 { diff --git a/sim/paladin/righteous_fury.go b/sim/paladin/righteous_fury.go index e3f5bbbe64..1be6718263 100644 --- a/sim/paladin/righteous_fury.go +++ b/sim/paladin/righteous_fury.go @@ -2,57 +2,23 @@ package paladin import ( "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) func (paladin *Paladin) registerRighteousFury() { if !paladin.Options.RighteousFury { return } - horRune := proto.PaladinRune_RuneHandsHandOfReckoning - hasHoR := paladin.hasRune(horRune) + actionID := core.ActionID{SpellID: 25780} - actionID := core.ActionID{SpellID: core.TernaryInt32(hasHoR, int32(horRune), 25780)} - - rfThreatMultiplier := 0.6 + core.TernaryFloat64(hasHoR, 0.2, 0.0) // Improved Righteous Fury is multiplicative. - rfThreatMultiplier *= 1.0 + []float64{0.0, 0.16, 0.33, 0.5}[paladin.Talents.ImprovedRighteousFury] + rfThreatMultiplier := 1.6 * (1 + []float64{0.0, 0.16, 0.33, 0.5}[paladin.Talents.ImprovedRighteousFury]) paladin.OnSpellRegistered(func(spell *core.Spell) { if spell.SpellSchool.Matches(core.SpellSchoolHoly) { - spell.ThreatMultiplier *= 1.0 + rfThreatMultiplier + spell.ThreatMultiplier *= rfThreatMultiplier } }) rfAura := core.MakePermanent(&core.Aura{Label: "Righteous Fury", ActionID: actionID}) - - // Passive effects granted by Hand of Reckoning rune; only active if Righteous Fury is on. - if hasHoR { - - // Damage which takes you below 35% health is reduced by 20% (DR component of WotLK's Ardent Defender) - rfDamageReduction := 0.2 - - handler := func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - incomingDamage := result.Damage - if (paladin.CurrentHealth()-incomingDamage)/paladin.MaxHealth() <= 0.35 { - result.Damage -= (paladin.MaxHealth()*0.35 - (paladin.CurrentHealth() - incomingDamage)) * rfDamageReduction - if sim.Log != nil { - paladin.Log(sim, "Righteous Fury absorbs %d damage", int32(incomingDamage-result.Damage)) - } - } - } - - paladin.AddDynamicDamageTakenModifier(handler) - - // Gives you mana when healed by other friendly targets' spells equal to 25% of the amount healed. - horManaMetrics := paladin.NewManaMetrics(actionID) - - rfAura.OnHealTaken = func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if spell.IsOtherAction(proto.OtherAction_OtherActionHealingModel) { - manaGained := result.Damage * 0.25 - paladin.AddMana(sim, manaGained, horManaMetrics) - } - } - } paladin.RegisterAura(*rfAura) } diff --git a/sim/paladin/righteous_vengeance.go b/sim/paladin/righteous_vengeance.go deleted file mode 100644 index 572bdb1513..0000000000 --- a/sim/paladin/righteous_vengeance.go +++ /dev/null @@ -1,74 +0,0 @@ -package paladin - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -const RVTicks = 4 - -func (paladin *Paladin) registerRV() { - if !paladin.hasRune(proto.PaladinRune_RuneCloakRighteousVengeance) { - return - } - - paladin.RegisterAura(core.Aura{ - Label: "Righteous Vengeance", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - aura.Activate(sim) - }, - OnSpellHitDealt: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - - if spell.Flags.Matches(SpellFlag_RV) && result.DidCrit() { - paladin.procRV(sim, result) - } - }, - }) - - paladin.rv = paladin.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 440675}, - SpellSchool: core.SpellSchoolHoly, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskSpellDamage, - Flags: core.SpellFlagPureDot | core.SpellFlagIgnoreAttackerModifiers | core.SpellFlagNoOnCastComplete, - - // SpellFlagIgnoreTargetModifiers was thought to be used based on wowhead flags - // WCL parses show that this is not the case - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - Cast: core.CastConfig{ - IgnoreHaste: true, - }, - - Dot: core.DotConfig{ - Aura: core.Aura{ - Label: "Righteous Vengeance", - }, - NumberOfTicks: RVTicks, - TickLength: time.Second * 2, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.Dot(target).ApplyOrReset(sim) - }, - }) -} - -func (paladin *Paladin) procRV(sim *core.Simulation, result *core.SpellResult) { - dot := paladin.rv.Dot(result.Target) - - newDamage := result.Damage * 0.5 - outstandingDamage := core.TernaryFloat64(dot.IsActive(), dot.SnapshotBaseDamage*float64(dot.NumberOfTicks-dot.TickCount), 0) - - dot.Snapshot(result.Target, (outstandingDamage+newDamage)/float64(RVTicks), false) - - paladin.rv.Cast(sim, result.Target) -} diff --git a/sim/paladin/shield_of_righteousness.go b/sim/paladin/shield_of_righteousness.go deleted file mode 100644 index 0e773781df..0000000000 --- a/sim/paladin/shield_of_righteousness.go +++ /dev/null @@ -1,50 +0,0 @@ -package paladin - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (paladin *Paladin) registerShieldOfRighteousness() { - if !paladin.hasRune(proto.PaladinRune_RuneCloakShieldOfRighteousness) { - return - } - - // Base damage formula from wowhead tooltip: - // https://www.wowhead.com/classic/spell=440658/shield-of-righteousness - // Testing shows there is an additional 20 base damage included. - damage := (179.0 * paladin.baseRuneAbilityDamage() / 100.0) + 20.0 - - paladin.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: int32(proto.PaladinRune_RuneCloakShieldOfRighteousness)}, - SpellSchool: core.SpellSchoolHoly, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagAPL, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.06, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Second * 6, - }, - }, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - // Shield of Righteousness has a hidden scaling coefficient of 2.2x SBV (derived from testing) - baseDamage := damage + paladin.BlockValue()*2.2 - spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - }, - }) -} diff --git a/sim/paladin/soc.go b/sim/paladin/soc.go index ac319c1606..59f0249305 100644 --- a/sim/paladin/soc.go +++ b/sim/paladin/soc.go @@ -70,7 +70,7 @@ func (paladin *Paladin) registerSealOfCommand() { SpellSchool: core.SpellSchoolHoly, DefenseType: core.DefenseTypeMelee, ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagNoOnCastComplete | SpellFlag_RV, + Flags: core.SpellFlagMeleeMetrics | core.SpellFlagNoOnCastComplete, SpellCode: SpellCode_PaladinJudgementOfCommand, // used in judgement.go @@ -99,7 +99,7 @@ func (paladin *Paladin) registerSealOfCommand() { SpellSchool: core.SpellSchoolHoly, DefenseType: core.DefenseTypeMelee, ProcMask: core.ProcMaskMeleeMHSpecial | core.ProcMaskMeleeProc | core.ProcMaskMeleeDamageProc, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagNotAProc | SpellFlag_RV, // RV Worked on PTR + Flags: core.SpellFlagMeleeMetrics | core.SpellFlagNotAProc, DamageMultiplier: 0.7 * paladin.getWeaponSpecializationModifier(), ThreatMultiplier: 1, diff --git a/sim/paladin/som.go b/sim/paladin/som.go deleted file mode 100644 index e7c025f322..0000000000 --- a/sim/paladin/som.go +++ /dev/null @@ -1,102 +0,0 @@ -package paladin - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -// Seal of Martyrdom is a spell consisting of: -// - A judgement that deals 85% weapon damage that is not normalised. Cannot miss or be dodged/blocked/parried. -// - An on-hit 100% chance proc that deals 50% *normalised* weapon damage. -// Both the on-hit and judgement are subject to weapon specialization talent modifiers as -// they both target melee defense. - -func (paladin *Paladin) registerSealOfMartyrdom() { - manaMetrics := paladin.NewManaMetrics(core.ActionID{SpellID: 407802}) // SoM's mana restore - - judgeSpell := paladin.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 407803}, - SpellSchool: core.SpellSchoolHoly, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagNoOnCastComplete | SpellFlag_RV, - - DamageMultiplier: 0.85 * paladin.getWeaponSpecializationModifier() * paladin.improvedSoR(), - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := spell.Unit.MHWeaponDamage(sim, spell.MeleeAttackPower()) - spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialCritOnly) - }, - }) - - procSpell := paladin.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 407799}, - SpellSchool: core.SpellSchoolHoly, - DefenseType: core.DefenseTypeMelee, - ProcMask: core.ProcMaskMeleeMHSpecial, - Flags: core.SpellFlagMeleeMetrics | core.SpellFlagSuppressWeaponProcs, - RequiredLevel: 1, - - DamageMultiplier: 0.5 * paladin.getWeaponSpecializationModifier() * paladin.improvedSoR(), - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - - baseDamage := spell.Unit.MHNormalizedWeaponDamage(sim, spell.MeleeAttackPower()) - result := spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMeleeSpecialHitAndCrit) - - core.StartDelayedAction(sim, core.DelayedActionOptions{ - DoAt: sim.CurrentTime + core.SpellBatchWindow, - OnAction: func(s *core.Simulation) { - spell.DealDamage(sim, result) - - // damages the paladin for 10% of rawDamage, then adds 133% of that for everyone in the raid - paladin.AddMana(sim, result.RawDamage()*0.1*1.33, manaMetrics) - }, - }) - }, - }) - - aura := paladin.RegisterAura(core.Aura{ - Label: "Seal of Martyrdom" + paladin.Label, - ActionID: core.ActionID{SpellID: int32(proto.PaladinRune_RuneUtilitySealOfMartyrdom)}, - Duration: time.Second * 30, - - OnSpellHitDealt: func(_ *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !result.Landed() { - return - } - - if spell.ProcMask.Matches(core.ProcMaskMeleeWhiteHit) || (spell.ProcMask.Matches(core.ProcMaskMeleeProc) && spell.Flags.Matches(core.SpellFlagNotAProc)) { - procSpell.Cast(sim, result.Target) - } - }, - }) - - paladin.aurasSoM = append(paladin.aurasSoM, aura) - - paladin.sealOfMartyrdom = paladin.RegisterSpell(core.SpellConfig{ - ActionID: aura.ActionID, - SpellSchool: core.SpellSchoolHoly, - Flags: core.SpellFlagAPL, - - ManaCost: core.ManaCostOptions{ - FlatCost: paladin.BaseMana*0.04 - paladin.getLibramSealCostReduction(), - Multiplier: paladin.benediction(), - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - paladin.applySeal(aura, judgeSpell, sim) - }, - }) - - paladin.spellsJoM = append(paladin.spellsJoM, judgeSpell) -} diff --git a/sim/paladin/sor.go b/sim/paladin/sor.go index 6b4183c0a4..22c6caa492 100644 --- a/sim/paladin/sor.go +++ b/sim/paladin/sor.go @@ -75,7 +75,7 @@ func (paladin *Paladin) registerSealOfRighteousness() { SpellSchool: core.SpellSchoolHoly, DefenseType: core.DefenseTypeMagic, ProcMask: core.ProcMaskSpellDamage, - Flags: core.SpellFlagMeleeMetrics | SpellFlag_RV | core.SpellFlagSuppressWeaponProcs | core.SpellFlagSuppressEquipProcs | core.SpellFlagBinary, + Flags: core.SpellFlagMeleeMetrics | core.SpellFlagSuppressWeaponProcs | core.SpellFlagSuppressEquipProcs | core.SpellFlagBinary, DamageMultiplier: 1, ThreatMultiplier: 1, From b687ab3af584628be1e7742c164a9c24ee7029dd Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 15:54:55 -0500 Subject: [PATCH 77/83] paladin items cleanup --- sim/paladin/items.go | 277 ------------------------------------------- 1 file changed, 277 deletions(-) diff --git a/sim/paladin/items.go b/sim/paladin/items.go index 530cc5bd89..7059f1dc2d 100644 --- a/sim/paladin/items.go +++ b/sim/paladin/items.go @@ -12,285 +12,8 @@ const ( SanctifiedOrb = 20512 LibramOfHope = 22401 LibramOfFervor = 23203 - // LibramDiscardedTenetsOfTheSilverHand = 209574 - // LibramOfBenediction = 215435 - // LibramOfDraconicDestruction = 221457 - // LibramOfTheDevoted = 228174 - // LibramOfAvenging = 232421 - // Truthbearer2H = 229749 - // Truthbearer1H = 229806 - // HammerOfTheLightbringer = 230003 - // ScrollsOfBlindingLight = 230272 - // GrileksCharmOfValor = 231285 - // HerosBrand = 231328 - // ZandalarFreethinkersBreastplate = 231329 - // ZandalarFreethinkersBelt = 231330 - // LibramOfWrath = 232420 ) func init() { core.NewSimpleStatOffensiveTrinketEffect(SanctifiedOrb, stats.Stats{stats.MeleeCrit: 3 * core.CritRatingPerCritChance, stats.SpellCrit: 3 * core.CritRatingPerCritChance}, time.Second*25, time.Minute*3) - - /* core.NewItemEffect(LibramDiscardedTenetsOfTheSilverHand, func(agent core.Agent) { - character := agent.GetCharacter() - if character.CurrentTarget.MobType == proto.MobType_MobTypeDemon || character.CurrentTarget.MobType == proto.MobType_MobTypeUndead { - character.PseudoStats.MobTypeAttackPower += 15 - } - }) - - core.NewItemEffect(LibramOfDraconicDestruction, func(agent core.Agent) { - character := agent.GetCharacter() - if character.CurrentTarget.MobType == proto.MobType_MobTypeDragonkin { - character.PseudoStats.MobTypeAttackPower += 36 - } - }) - - core.NewItemEffect(HerosBrand, func(agent core.Agent) { - //Increases critical strike chance of holy shock spell by 2% - paladin := agent.GetCharacter() - paladin.OnSpellRegistered(func(spell *core.Spell) { - if spell.SpellCode == SpellCode_PaladinHolyShock { - spell.BonusCritRating += 2.0 - } - }) - }) - - // https://www.wowhead.com/classic/item=230272/scrolls-of-blinding-light - // Use: Energizes a Paladin with light, increasing melee attack speed by 25% - // and spell casting speed by 33% for 20 sec. (2 Min Cooldown) - core.NewItemEffect(ScrollsOfBlindingLight, func(agent core.Agent) { - character := agent.GetCharacter() - - duration := time.Second * 20 - - aura := character.GetOrRegisterAura(core.Aura{ - Label: "Blinding Light", - ActionID: core.ActionID{SpellID: 467522}, - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.25) - character.MultiplyCastSpeed(1.33) - - // Crusader's zeal proc overwrites scrolls regardless of time left - truthbearerAura := character.GetAuraByID(core.ActionID{SpellID: 465414}) - if truthbearerAura != nil { - truthbearerAura.Deactivate(sim) - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.MultiplyAttackSpeed(sim, 1.0/1.25) - character.MultiplyCastSpeed(1.0 / 1.33) - }, - }) - - spell := character.GetOrRegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{ItemID: ScrollsOfBlindingLight}, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - ProcMask: core.ProcMaskEmpty, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: character.NewTimer(), - Duration: time.Minute * 2, - }, - SharedCD: core.Cooldown{ - Timer: character.GetOffensiveTrinketCD(), - Duration: duration, - }, - }, - - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - aura.Activate(sim) - }, - }) - - character.AddMajorCooldown(core.MajorCooldown{ - Type: core.CooldownTypeDPS, - Priority: core.CooldownPriorityDefault, - Spell: spell, - }) - }) - - core.NewItemEffect(HammerOfTheLightbringer, func(agent core.Agent) { - character := agent.GetCharacter() - vanilla.BlazefuryTriggerAura(character, 465412, core.SpellSchoolHoly, 4) - crusadersZealAura465414(character) - }) - - // https://www.wowhead.com/classic/item=229806/truthbearer - // Chance on hit: Increases damage done by 15 and attack speed by 30% for 8 sec. - // TODO: Proc rate assumed and needs testing - core.NewItemEffect(Truthbearer1H, func(agent core.Agent) { - character := agent.GetCharacter() - crusadersZealAura465414(character) - }) - - // https://www.wowhead.com/classic/item=229749/truthbearer - // Chance on hit: Increases damage done by 15 and attack speed by 30% for 8 sec. - // TODO: Proc rate assumed and needs testing - core.NewItemEffect(Truthbearer2H, func(agent core.Agent) { - character := agent.GetCharacter() - vanilla.BlazefuryTriggerAura(character, 465412, core.SpellSchoolHoly, 4) - crusadersZealAura465414(character) - }) - - core.NewItemEffect(ZandalarFreethinkersBreastplate, func(agent core.Agent) { - character := agent.GetCharacter() - character.PseudoStats.SchoolBonusHitChance[stats.SchoolIndexHoly] += 3 - }) - - core.NewItemEffect(ZandalarFreethinkersBelt, func(agent core.Agent) { - character := agent.GetCharacter() - character.PseudoStats.SchoolBonusHitChance[stats.SchoolIndexHoly] += 2 - }) - - // https://www.wowhead.com/classic/item=231285/grileks-charm-of-valor - // Use: Increases the critical hit chance of Holy spells by 10% for 15 sec. If Shock and Awe is engraved, gain an additional 5%. (1 Min, 30 Sec Cooldown) - core.NewItemEffect(GrileksCharmOfValor, func(agent core.Agent) { - paladin := agent.(PaladinAgent).GetPaladin() - - duration := time.Second * 15 - - aura := paladin.RegisterAura(core.Aura{ - ActionID: core.ActionID{ItemID: GrileksCharmOfValor}, - Label: "Brilliant Light", - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - paladin.PseudoStats.SchoolBonusCritChance[stats.SchoolIndexHoly] += core.TernaryFloat64(paladin.hasRune(proto.PaladinRune_RuneCloakShockAndAwe), 15.0*core.CritRatingPerCritChance, 10.0*core.CritRatingPerCritChance) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - paladin.PseudoStats.SchoolBonusCritChance[stats.SchoolIndexHoly] += core.TernaryFloat64(paladin.hasRune(proto.PaladinRune_RuneCloakShockAndAwe), -15.0*core.CritRatingPerCritChance, -10.0*core.CritRatingPerCritChance) - }, - }) - - spell := paladin.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{ItemID: GrileksCharmOfValor}, - ProcMask: core.ProcMaskEmpty, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagOffensiveEquipment, - - Cast: core.CastConfig{ - CD: core.Cooldown{ - Timer: paladin.NewTimer(), - Duration: time.Second * 90, - }, - SharedCD: core.Cooldown{ - Timer: paladin.GetOffensiveTrinketCD(), - Duration: duration, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - aura.Activate(sim) - }, - }) - - paladin.AddMajorCooldown(core.MajorCooldown{ - Type: core.CooldownTypeDPS, - Spell: spell, - }) - }) - - //https://www.wowhead.com/classic/item=232420/libram-of-wrath - //Equip: Your Holy Shock spell reduces the cast time and mana cost of your next Holy Wrath spell cast within 15 sec by 20%, and increases its damage by 20%. Stacking up to 5 times. - core.NewItemEffect(LibramOfWrath, func(agent core.Agent) { - paladin := agent.(PaladinAgent).GetPaladin() - holyWrathSpells := []*core.Spell{} - - buffAura := paladin.RegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 470246}, - Label: "Libram Of Wrath Buff", - Duration: time.Second * 15, - MaxStacks: 5, - OnInit: func(aura *core.Aura, sim *core.Simulation) { - holyWrathSpells = core.FilterSlice(paladin.holyWrath, func(spell *core.Spell) bool { return spell != nil }) - }, - OnStacksChange: func(aura *core.Aura, sim *core.Simulation, oldStacks int32, newStacks int32) { - core.Each(holyWrathSpells, func(spell *core.Spell) { - spell.CastTimeMultiplier += (0.2 * float64(oldStacks)) - spell.Cost.Multiplier += int32(100.0 * (0.2 * float64(oldStacks))) - spell.DamageMultiplier -= (0.2 * float64(oldStacks)) - - spell.CastTimeMultiplier -= (0.2 * float64(newStacks)) - spell.Cost.Multiplier -= int32(100.0 * (0.2 * float64(newStacks))) - spell.DamageMultiplier += (0.2 * float64(newStacks)) - - }) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode == SpellCode_PaladinHolyWrath { - aura.Deactivate(sim) - } - }, - }) - - paladin.RegisterAura(core.Aura{ - Label: "Libram Of Wrath Trigger", - Duration: core.NeverExpires, - OnReset: func(aura *core.Aura, sim *core.Simulation) { - - aura.Activate(sim) - }, - OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if spell.SpellCode == SpellCode_PaladinHolyShock { - buffAura.Activate(sim) - buffAura.AddStack(sim) - } - }, - }) - }) - - core.NewItemEffect(LibramOfTheDevoted, func(agent core.Agent) { - paladin := agent.(PaladinAgent).GetPaladin() - - actionID := core.ActionID{SpellID: 461309} - devotedMetrics := paladin.NewManaMetrics(actionID) - - core.MakePermanent(paladin.RegisterAura(core.Aura{ - Label: "Libram of the Devoted Trigger", - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.DidBlock() { - amount := paladin.MaxMana() * 0.03 - paladin.AddMana(sim, amount, devotedMetrics) - } - }, - })) - }) */ -} - -// https://www.wowhead.com/classic/spell=465414/crusaders-zeal -// Used by: -// - https://www.wowhead.com/classic/item=229806/truthbearer and -// - https://www.wowhead.com/classic/item=229749/truthbearer -func crusadersZealAura465414(character *core.Character) *core.Aura { - procAura := character.GetOrRegisterAura(core.Aura{ - ActionID: core.ActionID{SpellID: 465414}, - Label: "Crusader's Zeal", - Duration: time.Second * 8, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.BonusPhysicalDamage += 15 - character.MultiplyAttackSpeed(sim, 1.30) - - // Crusader's zeal proc overwrites scrolls regardless of time left - scrollsAura := character.GetAuraByID(core.ActionID{SpellID: 467522}) - if scrollsAura != nil { - scrollsAura.Deactivate(sim) - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - character.PseudoStats.BonusPhysicalDamage -= 15 - character.MultiplyAttackSpeed(sim, 1/1.30) - }, - }) - - return core.MakeProcTriggerAura(&character.Unit, core.ProcTrigger{ - Name: "Truthbearer (Crusader's Zeal)", - Callback: core.CallbackOnSpellHitDealt, - Outcome: core.OutcomeLanded, - ProcMask: core.ProcMaskMelee, - SpellFlagsExclude: core.SpellFlagSuppressWeaponProcs, - PPM: 2.0, // TBD - Handler: func(sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - procAura.Activate(sim) - }, - }) } From 05ebf3dbe082c2105332fb953550f8dfe8f0e2e7 Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 16:16:18 -0500 Subject: [PATCH 78/83] shaman cleanup --- sim/shaman/air_totems.go | 8 +-- sim/shaman/chain_heal.go | 48 ++------------ sim/shaman/chain_lightning.go | 6 +- sim/shaman/earth_shock.go | 6 -- sim/shaman/earth_totems.go | 14 +---- sim/shaman/electric_spell.go | 14 +---- sim/shaman/fire_totems.go | 5 -- sim/shaman/flame_shock.go | 63 ++----------------- sim/shaman/healing_wave.go | 44 +------------ sim/shaman/lesser_healing_wave.go | 30 +-------- sim/shaman/lightning_bolt.go | 22 ------- sim/shaman/lightning_shield.go | 38 ++---------- sim/shaman/molten_blast.go | 68 -------------------- sim/shaman/riptide.go | 72 --------------------- sim/shaman/rolling_thunder.go | 72 --------------------- sim/shaman/shaman.go | 100 ++++++++---------------------- sim/shaman/shamanistic_rage.go | 59 ------------------ sim/shaman/spirit_wolves.go | 85 ------------------------- sim/shaman/stormstrike.go | 40 ++++-------- sim/shaman/talents.go | 8 +-- sim/shaman/water_shield.go | 83 ------------------------- sim/shaman/windfury_weapon.go | 14 ++--- 22 files changed, 72 insertions(+), 827 deletions(-) delete mode 100644 sim/shaman/molten_blast.go delete mode 100644 sim/shaman/riptide.go delete mode 100644 sim/shaman/rolling_thunder.go delete mode 100644 sim/shaman/shamanistic_rage.go delete mode 100644 sim/shaman/spirit_wolves.go delete mode 100644 sim/shaman/water_shield.go diff --git a/sim/shaman/air_totems.go b/sim/shaman/air_totems.go index 3fb5971979..76db84b3bc 100644 --- a/sim/shaman/air_totems.go +++ b/sim/shaman/air_totems.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const WindfuryTotemRanks = 3 @@ -81,8 +80,7 @@ func (shaman *Shaman) newGraceOfAirTotemSpellConfig(rank int) core.SpellConfig { duration := time.Second * 120 multiplier := []float64{1, 1.08, 1.15}[shaman.Talents.EnhancingTotems] - graceOfAirTotemAuras := make([]*core.Aura, core.TernaryInt32(hasFeralSpirit, 2, 1)) - graceOfAirTotemAuras[0] = core.GraceOfAirTotemAura(&shaman.Unit, multiplier) + buffAura := core.GraceOfAirTotemAura(&shaman.Unit, multiplier) spell := shaman.newTotemSpellConfig(manaCost, spellId) spell.RequiredLevel = level @@ -91,9 +89,7 @@ func (shaman *Shaman) newGraceOfAirTotemSpellConfig(rank int) core.SpellConfig { shaman.TotemExpirations[AirTotem] = sim.CurrentTime + duration shaman.ActiveTotems[AirTotem] = spell - for _, aura := range graceOfAirTotemAuras { - aura.Activate(sim) - } + buffAura.Activate(sim) } return spell } diff --git a/sim/shaman/chain_heal.go b/sim/shaman/chain_heal.go index a792f51466..6e79f92c60 100644 --- a/sim/shaman/chain_heal.go +++ b/sim/shaman/chain_heal.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const ChainHealRanks = 3 @@ -18,32 +17,18 @@ var ChainHealManaCost = [ChainHealRanks + 1]float64{0, 260, 315, 405} var ChainHealLevel = [ChainHealRanks + 1]int{0, 40, 46, 54} func (shaman *Shaman) registerChainHealSpell() { - overloadRuneEquipped := shaman.HasRune(proto.ShamanRune_RuneChestOverload) - shaman.ChainHeal = make([]*core.Spell, ChainHealRanks+1) - if overloadRuneEquipped { - shaman.ChainHealOverload = make([]*core.Spell, ChainHealRanks+1) - } - for rank := 1; rank <= ChainHealRanks; rank++ { config := shaman.newChainHealSpellConfig(rank, false) if config.RequiredLevel <= int(shaman.Level) { shaman.ChainHeal[rank] = shaman.RegisterSpell(config) - - if overloadRuneEquipped { - shaman.ChainHealOverload[rank] = shaman.RegisterSpell(shaman.newChainHealSpellConfig(rank, true)) - } } } } func (shaman *Shaman) newChainHealSpellConfig(rank int, isOverload bool) core.SpellConfig { - hasOverloadRune := shaman.HasRune(proto.ShamanRune_RuneChestOverload) - hasCoherenceRune := shaman.HasRune(proto.ShamanRune_RuneCloakCoherence) - hasRiptideRune := shaman.HasRune(proto.ShamanRune_RuneBracersRiptide) - spellId := ChainHealSpellId[rank] baseHealingMultiplier := 1 + shaman.purificationHealingModifier() baseHealingLow := ChainHealBaseHealing[rank][0] * baseHealingMultiplier @@ -53,27 +38,16 @@ func (shaman *Shaman) newChainHealSpellConfig(rank int, isOverload bool) core.Sp manaCost := ChainHealManaCost[rank] level := ChainHealLevel[rank] - flags := core.SpellFlagHelpful | SpellFlagShaman - if !isOverload { - flags |= core.SpellFlagAPL - } - - bounceCoef := .5 // 50% reduction per bounce + bounceCoef := 0.50 // 50% reduction per bounce targetCount := ChainHealTargetCount - if hasCoherenceRune { - bounceCoef = .65 // 35% reduction per bounce - targetCount += 2 - } - - canOverload := !isOverload && hasOverloadRune - spell := core.SpellConfig{ + return core.SpellConfig{ ActionID: core.ActionID{SpellID: spellId}, SpellCode: SpellCode_ShamanChainHeal, DefenseType: core.DefenseTypeMagic, SpellSchool: core.SpellSchoolNature, ProcMask: core.ProcMaskSpellHealing, - Flags: flags, + Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagShaman, RequiredLevel: level, Rank: rank, @@ -100,27 +74,13 @@ func (shaman *Shaman) newChainHealSpellConfig(rank int, isOverload bool) core.Sp // TODO: This bounces to most hurt friendly... for hitIndex := 0; hitIndex < len(targets); hitIndex++ { originalDamageMultiplier := spell.DamageMultiplier - if hasRiptideRune && !isOverload && shaman.Riptide.Hot(curTarget).IsActive() { - spell.DamageMultiplier *= 1.25 - shaman.Riptide.Hot(curTarget).Deactivate(sim) - } spell.CalcAndDealHealing(sim, curTarget, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) spell.DamageMultiplier = originalDamageMultiplier - - if canOverload && sim.RandomFloat("CH Overload") < ShamanOverloadChance { - shaman.ChainHealOverload[rank].Cast(sim, target) - } - spell.DamageMultiplier *= bounceCoef + curTarget = targets[hitIndex] } spell.DamageMultiplier = origMult }, } - - if isOverload { - shaman.applyOverloadModifiers(&spell) - } - - return spell } diff --git a/sim/shaman/chain_lightning.go b/sim/shaman/chain_lightning.go index c345bdd0ca..4b6e4ae81f 100644 --- a/sim/shaman/chain_lightning.go +++ b/sim/shaman/chain_lightning.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const ChainLightningRanks = 4 @@ -22,7 +21,7 @@ func (shaman *Shaman) registerChainLightningSpell() { cdTimer := shaman.NewTimer() for rank := 1; rank <= ChainLightningRanks; rank++ { - config := shaman.newChainLightningSpellConfig(rank, cdTimer, false) + config := shaman.newChainLightningSpellConfig(rank, cdTimer) if config.RequiredLevel <= int(shaman.Level) { shaman.ChainLightning[rank] = shaman.RegisterSpell(config) @@ -44,9 +43,6 @@ func (shaman *Shaman) newChainLightningSpellConfig(rank int, cdTimer *core.Timer bounceCoef := .7 // 30% reduction per bounce targetCount := ChainLightningTargetCount - canOverload := !isOverload && hasOverloadRune - overloadChance := .1667 - spell := shaman.newElectricSpellConfig( core.ActionID{SpellID: spellId}, manaCost, diff --git a/sim/shaman/earth_shock.go b/sim/shaman/earth_shock.go index 1d6a4fee7a..ba3295ad22 100644 --- a/sim/shaman/earth_shock.go +++ b/sim/shaman/earth_shock.go @@ -2,7 +2,6 @@ package shaman import ( "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const EarthShockRanks = 7 @@ -14,11 +13,6 @@ var EarthShockManaCost = [EarthShockRanks + 1]float64{0, 30, 50, 85, 145, 240, 3 var EarthShockLevel = [EarthShockRanks + 1]int{0, 4, 8, 14, 24, 36, 48, 60} func (shaman *Shaman) registerEarthShockSpell(shockTimer *core.Timer) { - // Way of Earth gives earth shock a separate timer - if shaman.HasRune(proto.ShamanRune_RuneLegsWayOfEarth) { - shockTimer = shaman.NewTimer() - } - shaman.EarthShock = make([]*core.Spell, EarthShockRanks+1) for rank := 1; rank <= EarthShockRanks; rank++ { diff --git a/sim/shaman/earth_totems.go b/sim/shaman/earth_totems.go index 4dc02577d8..677aabe7c4 100644 --- a/sim/shaman/earth_totems.go +++ b/sim/shaman/earth_totems.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const StrengthOfEarthTotemRanks = 5 @@ -38,13 +37,7 @@ func (shaman *Shaman) newStrengthOfEarthTotemSpellConfig(rank int) core.SpellCon duration := time.Second * 120 multiplier := []float64{1, 1.08, 1.15}[shaman.Talents.EnhancingTotems] - hasFeralSpirit := shaman.HasRune(proto.ShamanRune_RuneCloakFeralSpirit) - - strengthOfEarthTotemAuras := make([]*core.Aura, core.TernaryInt32(hasFeralSpirit, 2, 1)) - strengthOfEarthTotemAuras[0] = core.StrengthOfEarthTotemAura(&shaman.Unit, multiplier) - if hasFeralSpirit { - strengthOfEarthTotemAuras[1] = core.StrengthOfEarthTotemAura(&shaman.SpiritWolves.Unit, multiplier) - } + buffAura := core.StrengthOfEarthTotemAura(&shaman.Unit, multiplier) spell := shaman.newTotemSpellConfig(manaCost, spellId) spell.RequiredLevel = level @@ -52,9 +45,8 @@ func (shaman *Shaman) newStrengthOfEarthTotemSpellConfig(rank int) core.SpellCon spell.ApplyEffects = func(sim *core.Simulation, _ *core.Unit, spell *core.Spell) { shaman.TotemExpirations[EarthTotem] = sim.CurrentTime + duration shaman.ActiveTotems[EarthTotem] = spell - for _, aura := range strengthOfEarthTotemAuras { - aura.Activate(sim) - } + + buffAura.Activate(sim) } return spell } diff --git a/sim/shaman/electric_spell.go b/sim/shaman/electric_spell.go index 9417601ad4..0739020875 100644 --- a/sim/shaman/electric_spell.go +++ b/sim/shaman/electric_spell.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) // Totem Item IDs @@ -20,14 +19,12 @@ const ( // Shared precomputation logic for LB and CL. func (shaman *Shaman) newElectricSpellConfig(actionID core.ActionID, baseCost float64, baseCastTime time.Duration) core.SpellConfig { - hasMaelstromWeaponRune := shaman.HasRune(proto.ShamanRune_RuneWaistMaelstromWeapon) - spell := core.SpellConfig{ ActionID: actionID, SpellSchool: core.SpellSchoolNature, DefenseType: core.DefenseTypeMagic, ProcMask: core.ProcMaskSpellDamage, - Flags: flags := SpellFlagShaman | SpellFlagLightning | core.SpellFlagAPL, + Flags: SpellFlagShaman | SpellFlagLightning | core.SpellFlagAPL, MetricSplits: 6, ManaCost: core.ManaCostOptions{ @@ -42,15 +39,6 @@ func (shaman *Shaman) newElectricSpellConfig(actionID core.ActionID, baseCost fl }, ModifyCast: func(sim *core.Simulation, spell *core.Spell, cast *core.Cast) { castTime := shaman.ApplyCastSpeedForSpell(cast.CastTime, spell) - if hasMaelstromWeaponRune { - stacks := shaman.MaelstromWeaponAura.GetStacks() - spell.SetMetricsSplit(stacks) - - if stacks > 0 { - return - } - } - shaman.AutoAttacks.StopMeleeUntil(sim, sim.CurrentTime+castTime, false) }, }, diff --git a/sim/shaman/fire_totems.go b/sim/shaman/fire_totems.go index ee49df1ebf..38ce7a47e6 100644 --- a/sim/shaman/fire_totems.go +++ b/sim/shaman/fire_totems.go @@ -5,7 +5,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const SearingTotemRanks = 6 @@ -225,10 +224,6 @@ var FireNovaTotemManaCost = [FireNovaTotemRanks + 1]float64{0, 95, 170, 280, 395 var FireNovaTotemLevel = [FireNovaTotemRanks + 1]int{0, 12, 22, 32, 42, 52} func (shaman *Shaman) registerFireNovaTotemSpell() { - if shaman.HasRune(proto.ShamanRune_RuneWaistFireNova) { - return - } - shaman.FireNovaTotem = make([]*core.Spell, FireNovaTotemRanks+1) for rank := 1; rank <= FireNovaTotemRanks; rank++ { diff --git a/sim/shaman/flame_shock.go b/sim/shaman/flame_shock.go index 67b393f9c2..80cf7213b1 100644 --- a/sim/shaman/flame_shock.go +++ b/sim/shaman/flame_shock.go @@ -1,11 +1,9 @@ package shaman import ( - "fmt" "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const FlameShockRanks = 6 @@ -29,14 +27,7 @@ func (shaman *Shaman) registerFlameShockSpell(shockTimer *core.Timer) { } func (shaman *Shaman) newFlameShockSpell(rank int, shockTimer *core.Timer) core.SpellConfig { - hasBurnRune := shaman.HasRune(proto.ShamanRune_RuneHelmBurn) - hasLavaBurstRune := shaman.HasRune(proto.ShamanRune_RuneHandsLavaBurst) - hasPowerSurgeRune := shaman.HasRune(proto.ShamanRune_RuneWaistPowerSurge) - hasMoltenBlastRune := shaman.HasRune(proto.ShamanRune_RuneHandsMoltenBlast) - hasOverloadRune := shaman.HasRune(proto.ShamanRune_RuneChestOverload) - hasStormEarthAndFireRune := shaman.HasRune(proto.ShamanRune_RuneCloakStormEarthAndFire) - - numTicks := 4 + core.TernaryInt32(hasBurnRune, BurnFlameShockBonusTicks, 0) + numTicks := 4 tickDuration := time.Second * 3 spellId := FlameShockSpellId[rank] @@ -63,69 +54,23 @@ func (shaman *Shaman) newFlameShockSpell(rank int, shockTimer *core.Timer) core. spell.BonusCoefficient = baseSpellCoeff spell.Dot = core.DotConfig{ - Aura: core.Aura{ - Label: fmt.Sprintf("Flame Shock (Rank %d)", rank), - OnGain: func(aura *core.Aura, sim *core.Simulation) { - if hasLavaBurstRune { - shaman.LavaBurst.BonusCritRating += 100 * core.CritRatingPerCritChance - if hasOverloadRune { - shaman.LavaBurstOverload.BonusCritRating += 100 * core.CritRatingPerCritChance - } - } - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - if hasLavaBurstRune { - shaman.LavaBurst.BonusCritRating -= 100 * core.CritRatingPerCritChance - if hasOverloadRune { - shaman.LavaBurstOverload.BonusCritRating -= 100 * core.CritRatingPerCritChance - } - } - }, - }, - NumberOfTicks: int32(numTicks), TickLength: tickDuration, BonusCoefficient: dotSpellCoeff, OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { dot.Snapshot(target, baseDotDamage, isRollover) - if !isRollover && hasStormEarthAndFireRune { - dot.SnapshotAttackerMultiplier *= 1.60 - } }, OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { dot.CalcAndDealPeriodicSnapshotDamage(sim, target, dot.OutcomeTick) - - if hasMoltenBlastRune && sim.Proc(ShamanMoltenBlastResetChance, "Molten Blast Reset") { - shaman.MoltenBlast.CD.Reset() - } - - if hasPowerSurgeRune && sim.Proc(shaman.powerSurgeProcChance, "Power Surge Proc") { - shaman.PowerSurgeDamageAura.Activate(sim) - } }, } - results := make([]*core.SpellResult, min(core.TernaryInt32(hasBurnRune, BurnFlameShockTargetCount, 1), shaman.Env.GetNumTargets())) spell.ApplyEffects = func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for idx := range results { - results[idx] = spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - target = sim.Environment.NextTargetUnit(target) - } - - for _, result := range results { - spell.DealDamage(sim, result) - if result.Landed() { - spell.Dot(result.Target).Apply(sim) - if shaman.HasRune(proto.ShamanRune_RuneLegsAncestralGuidance) { - shaman.lastFlameShockTarget = target - } - - if hasPowerSurgeRune && sim.Proc(shaman.powerSurgeProcChance, "Power Surge Proc") { - shaman.PowerSurgeDamageAura.Activate(sim) - } - } + result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) + if result.Landed() { + spell.Dot(result.Target).Apply(sim) } } diff --git a/sim/shaman/healing_wave.go b/sim/shaman/healing_wave.go index 9363ad662a..8ff3c751c2 100644 --- a/sim/shaman/healing_wave.go +++ b/sim/shaman/healing_wave.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const HealingWaveRanks = 10 @@ -17,23 +16,13 @@ var HealingWaveManaCost = [HealingWaveRanks + 1]float64{0, 25, 45, 80, 155, 200, var HealingWaveLevel = [HealingWaveRanks + 1]int{0, 1, 6, 12, 18, 24, 32, 40, 48, 56, 60} func (shaman *Shaman) registerHealingWaveSpell() { - overloadRuneEquipped := shaman.HasRune(proto.ShamanRune_RuneChestOverload) - shaman.HealingWave = make([]*core.Spell, HealingWaveRanks+1) - if overloadRuneEquipped { - shaman.HealingWaveOverload = make([]*core.Spell, HealingWaveRanks+1) - } - for rank := 1; rank <= HealingWaveRanks; rank++ { config := shaman.newHealingWaveSpellConfig(rank, false) if config.RequiredLevel <= int(shaman.Level) { shaman.HealingWave[rank] = shaman.RegisterSpell(config) - - if overloadRuneEquipped { - shaman.HealingWaveOverload[rank] = shaman.RegisterSpell(shaman.newHealingWaveSpellConfig(rank, true)) - } } } } @@ -48,20 +37,13 @@ func (shaman *Shaman) newHealingWaveSpellConfig(rank int, isOverload bool) core. manaCost := HealingWaveManaCost[rank] level := HealingWaveLevel[rank] - flags := core.SpellFlagHelpful | SpellFlagShaman - if !isOverload { - flags |= core.SpellFlagAPL - } - - canOverload := !isOverload && shaman.HasRune(proto.ShamanRune_RuneChestOverload) - - spell := core.SpellConfig{ + return core.SpellConfig{ ActionID: core.ActionID{SpellID: spellId}, SpellCode: SpellCode_ShamanHealingWave, SpellSchool: core.SpellSchoolNature, DefenseType: core.DefenseTypeMagic, ProcMask: core.ProcMaskSpellHealing, - Flags: flags, + Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagShaman, RequiredLevel: level, Rank: rank, @@ -85,27 +67,7 @@ func (shaman *Shaman) newHealingWaveSpellConfig(rank int, isOverload bool) core. ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { // TODO: Take Healing Way into account 6% stacking up to 3x - result := spell.CalcAndDealHealing(sim, spell.Unit, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) - - if canOverload && sim.RandomFloat("HW Overload") < ShamanOverloadChance { - shaman.HealingWaveOverload[rank].Cast(sim, spell.Unit) - } - - if result.Outcome.Matches(core.OutcomeCrit) { - if shaman.HasRune(proto.ShamanRune_RuneFeetAncestralAwakening) { - shaman.ancestralHealingAmount = result.Damage * AncestralAwakeningHealMultiplier - - // TODO: this should actually target the lowest health target in the raid. - // does it matter in a sim? We currently only simulate tanks taking damage (multiple tanks could be handled here though.) - shaman.AncestralAwakening.Cast(sim, spell.Unit) - } - } + spell.CalcAndDealHealing(sim, spell.Unit, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) }, } - - if isOverload { - shaman.applyOverloadModifiers(&spell) - } - - return spell } diff --git a/sim/shaman/lesser_healing_wave.go b/sim/shaman/lesser_healing_wave.go index 44aa41397b..4158d5df7d 100644 --- a/sim/shaman/lesser_healing_wave.go +++ b/sim/shaman/lesser_healing_wave.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const LesserHealingWaveRanks = 6 @@ -29,8 +28,6 @@ func (shaman *Shaman) registerLesserHealingWaveSpell() { } func (shaman *Shaman) newLesserHealingWaveSpellConfig(rank int) core.SpellConfig { - hasMaelstromWeaponRune := shaman.HasRune(proto.ShamanRune_RuneWaistMaelstromWeapon) - spellId := LesserHealingWaveSpellId[rank] baseHealingMultiplier := 1 + shaman.purificationHealingModifier() baseHealingLow := LesserHealingWaveBaseHealing[rank][0] * baseHealingMultiplier @@ -46,13 +43,13 @@ func (shaman *Shaman) newLesserHealingWaveSpellConfig(rank int) core.SpellConfig baseHealingHigh += 53 } - spell := core.SpellConfig{ + return core.SpellConfig{ ActionID: core.ActionID{SpellID: spellId}, SpellCode: SpellCode_ShamanLesserHealingWave, SpellSchool: core.SpellSchoolNature, DefenseType: core.DefenseTypeMagic, ProcMask: core.ProcMaskSpellHealing, - Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagMaelstrom | SpellFlagShaman, + Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagShaman, MetricSplits: 6, RequiredLevel: level, @@ -69,15 +66,6 @@ func (shaman *Shaman) newLesserHealingWaveSpellConfig(rank int) core.SpellConfig }, ModifyCast: func(sim *core.Simulation, spell *core.Spell, cast *core.Cast) { castTime := shaman.ApplyCastSpeedForSpell(cast.CastTime, spell) - if hasMaelstromWeaponRune { - stacks := shaman.MaelstromWeaponAura.GetStacks() - spell.SetMetricsSplit(stacks) - - if stacks > 0 { - return - } - } - shaman.AutoAttacks.StopMeleeUntil(sim, sim.CurrentTime+castTime, false) }, }, @@ -87,19 +75,7 @@ func (shaman *Shaman) newLesserHealingWaveSpellConfig(rank int) core.SpellConfig BonusCoefficient: spellCoeff, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - result := spell.CalcAndDealHealing(sim, spell.Unit, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) - - if result.Outcome.Matches(core.OutcomeCrit) { - if shaman.HasRune(proto.ShamanRune_RuneFeetAncestralAwakening) { - shaman.ancestralHealingAmount = result.Damage * AncestralAwakeningHealMultiplier - - // TODO: this should actually target the lowest health target in the raid. - // does it matter in a sim? We currently only simulate tanks taking damage (multiple tanks could be handled here though.) - shaman.AncestralAwakening.Cast(sim, spell.Unit) - } - } + spell.CalcAndDealHealing(sim, spell.Unit, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) }, } - - return spell } diff --git a/sim/shaman/lightning_bolt.go b/sim/shaman/lightning_bolt.go index a4f2d90305..ae12014ef8 100644 --- a/sim/shaman/lightning_bolt.go +++ b/sim/shaman/lightning_bolt.go @@ -4,7 +4,6 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const LightningBoltRanks = 10 @@ -17,23 +16,13 @@ var LightningBoltManaCost = [LightningBoltRanks + 1]float64{0, 15, 30, 45, 75, 1 var LightningBoltLevel = [LightningBoltRanks + 1]int{0, 1, 8, 14, 20, 26, 32, 38, 44, 50, 56} func (shaman *Shaman) registerLightningBoltSpell() { - overloadRuneEquipped := shaman.HasRune(proto.ShamanRune_RuneChestOverload) - shaman.LightningBolt = make([]*core.Spell, LightningBoltRanks+1) - if overloadRuneEquipped { - shaman.LightningBoltOverload = make([]*core.Spell, LightningBoltRanks+1) - } - for rank := 1; rank <= LightningBoltRanks; rank++ { config := shaman.newLightningBoltSpellConfig(rank, false) if config.RequiredLevel <= int(shaman.Level) { shaman.LightningBolt[rank] = shaman.RegisterSpell(config) - - if overloadRuneEquipped { - shaman.LightningBoltOverload[rank] = shaman.RegisterSpell(shaman.newLightningBoltSpellConfig(rank, true)) - } } } } @@ -47,13 +36,10 @@ func (shaman *Shaman) newLightningBoltSpellConfig(rank int, isOverload bool) cor manaCost := LightningBoltManaCost[rank] level := LightningBoltLevel[rank] - canOverload := !isOverload && shaman.HasRune(proto.ShamanRune_RuneChestOverload) - spell := shaman.newElectricSpellConfig( core.ActionID{SpellID: spellId}, manaCost, time.Millisecond*time.Duration(castTime), - isOverload, ) spell.SpellCode = SpellCode_ShamanLightningBolt spell.MissileSpeed = 20 @@ -67,16 +53,8 @@ func (shaman *Shaman) newLightningBoltSpellConfig(rank int, isOverload bool) cor spell.WaitTravelTime(sim, func(sim *core.Simulation) { spell.DealDamage(sim, result) - - if canOverload && sim.Proc(ShamanOverloadChance, "LB Overload") { - shaman.LightningBoltOverload[rank].Cast(sim, target) - } }) } - if isOverload { - shaman.applyOverloadModifiers(&spell) - } - return spell } diff --git a/sim/shaman/lightning_shield.go b/sim/shaman/lightning_shield.go index d669fcd4ef..75d50f0f2f 100644 --- a/sim/shaman/lightning_shield.go +++ b/sim/shaman/lightning_shield.go @@ -5,14 +5,12 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) const LightningShieldRanks = 7 var LightningShieldSpellId = [LightningShieldRanks + 1]int32{0, 324, 325, 905, 945, 8134, 10431, 10432} var LightningShieldProcSpellId = [LightningShieldRanks + 1]int32{0, 26364, 26365, 26366, 26367, 26369, 26370, 26363} -var LightningShieldOverchargedProcSpellId = [LightningShieldRanks + 1]int32{0, 432143, 432144, 432145, 432146, 432147, 432148, 432149} var LightningShieldBaseDamage = [LightningShieldRanks + 1]float64{0, 13, 29, 51, 80, 114, 154, 198} var LightningShieldSpellCoef = [LightningShieldRanks + 1]float64{0, .147, .227, .267, .267, .267, .267, .267} var LightningShieldManaCost = [LightningShieldRanks + 1]float64{0, 45, 80, 125, 180, 240, 305} @@ -23,8 +21,6 @@ func (shaman *Shaman) registerLightningShieldSpell() { shaman.LightningShieldProcs = make([]*core.Spell, LightningShieldRanks+1) shaman.LightningShieldAuras = make([]*core.Aura, LightningShieldRanks+1) - shaman.lightningShieldCanCrit = false - for rank := 1; rank <= LightningShieldRanks; rank++ { level := LightningShieldLevel[rank] @@ -35,13 +31,10 @@ func (shaman *Shaman) registerLightningShieldSpell() { } func (shaman *Shaman) registerNewLightningShieldSpell(rank int) { - hasOverchargedRune := shaman.HasRune(proto.ShamanRune_RuneBracersOvercharged) - hasStaticShockRune := shaman.HasRune(proto.ShamanRune_RuneBracersStaticShock) - impLightningShieldBonus := 1 + []float64{0, .05, .10, .15}[shaman.Talents.ImprovedLightningShield] spellId := LightningShieldSpellId[rank] - procSpellId := core.Ternary(hasOverchargedRune, LightningShieldOverchargedProcSpellId, LightningShieldProcSpellId)[rank] + procSpellId := LightningShieldProcSpellId[rank] baseDamage := LightningShieldBaseDamage[rank] * impLightningShieldBonus spellCoeff := LightningShieldSpellCoef[rank] manaCost := LightningShieldManaCost[rank] @@ -49,10 +42,6 @@ func (shaman *Shaman) registerNewLightningShieldSpell(rank int) { baseCharges := int32(3) maxCharges := int32(3) - if hasStaticShockRune { - baseCharges = 9 - maxCharges = 9 - } shaman.LightningShieldProcs[rank] = shaman.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: procSpellId}, @@ -66,19 +55,15 @@ func (shaman *Shaman) registerNewLightningShieldSpell(rank int) { BonusCoefficient: spellCoeff, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - outcome := core.Ternary(shaman.lightningShieldCanCrit, spell.OutcomeMagicCrit, spell.OutcomeAlwaysHit) - spell.CalcAndDealDamage(sim, target, baseDamage, outcome) - - if !hasOverchargedRune { - shaman.ActiveShieldAura.RemoveStack(sim) - } + spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeAlwaysHit) + shaman.ActiveShieldAura.RemoveStack(sim) }, }) // TODO: Does vanilla have an ICD? icd := core.Cooldown{ Timer: shaman.NewTimer(), - Duration: core.Ternary(hasOverchargedRune, time.Second*3, time.Millisecond*3500), + Duration: time.Millisecond * 3500, } shaman.LightningShieldAuras[rank] = shaman.RegisterAura(core.Aura{ @@ -105,19 +90,8 @@ func (shaman *Shaman) registerNewLightningShieldSpell(rank int) { } }, OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if !spell.ProcMask.Matches(core.ProcMaskMelee) || !result.Landed() || !icd.IsReady(sim) { - return - } - icd.Use(sim) - - if hasOverchargedRune { - // Deals damage to all targets within 8 yards and does not lose stacks - for _, aoeTarget := range sim.Encounter.TargetUnits { - if aoeTarget.DistanceFromTarget <= 8 { - shaman.LightningShieldProcs[rank].Cast(sim, aoeTarget) - } - } - } else { + if spell.ProcMask.Matches(core.ProcMaskMelee) && result.Landed() && icd.IsReady(sim) { + icd.Use(sim) shaman.LightningShieldProcs[rank].Cast(sim, spell.Unit) } }, diff --git a/sim/shaman/molten_blast.go b/sim/shaman/molten_blast.go deleted file mode 100644 index 2b8916fd32..0000000000 --- a/sim/shaman/molten_blast.go +++ /dev/null @@ -1,68 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -const ShamanMoltenBlastResetChance = .10 - -func (shaman *Shaman) applyMoltenBlast() { - if !shaman.HasRune(proto.ShamanRune_RuneHandsMoltenBlast) { - return - } - - baseDamageLow := shaman.baseRuneAbilityDamage() * .72 - baseDamageHigh := shaman.baseRuneAbilityDamage() * 1.08 - apCoef := .10 - spCoef := .14 - cooldown := time.Second * 6 - manaCost := .18 - targetCount := int32(10) - - numHits := min(targetCount, shaman.Env.GetNumTargets()) - results := make([]*core.SpellResult, numHits) - - shaman.MoltenBlast = shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: int32(proto.ShamanRune_RuneHandsMoltenBlast)}, - SpellCode: SpellCode_ShamanMoltenBlast, - SpellSchool: core.SpellSchoolFire, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellDamage, - Flags: SpellFlagShaman | core.SpellFlagAPL, - - ManaCost: core.ManaCostOptions{ - BaseCost: manaCost, - }, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: shaman.NewTimer(), - Duration: cooldown, - }, - }, - - BonusCoefficient: spCoef, - DamageMultiplier: 1, - ThreatMultiplier: 2, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - for idx := range results { - // Molten Blast is a magic ability but scales off of Attack Power - baseDamage := sim.Roll(baseDamageLow, baseDamageHigh) + apCoef*spell.MeleeAttackPower() - results[idx] = spell.CalcDamage(sim, target, baseDamage, spell.OutcomeMagicHitAndCrit) - target = sim.Environment.NextTargetUnit(target) - } - - for _, result := range results { - spell.DealDamage(sim, result) - } - }, - }) -} diff --git a/sim/shaman/riptide.go b/sim/shaman/riptide.go deleted file mode 100644 index 53b8beae1c..0000000000 --- a/sim/shaman/riptide.go +++ /dev/null @@ -1,72 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (shaman *Shaman) registerRiptideSpell() { - if !shaman.HasRune(proto.ShamanRune_RuneBracersRiptide) { - return - } - - hasPowerSurgeRune := shaman.HasRune(proto.ShamanRune_RuneWaistPowerSurge) - - baseHealingMultiplier := 1 + shaman.purificationHealingModifier() - baseHealingLow := shaman.baseRuneAbilityDamage() * 1.13 * baseHealingMultiplier - baseHealingHigh := shaman.baseRuneAbilityDamage() * 1.23 * baseHealingMultiplier - baseHotHealing := shaman.baseRuneAbilityDamage() * 1.20 - spellCoeff := 0.215 - hotCoeff := 0.10 - - shaman.Riptide = shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: int32(proto.ShamanRune_RuneBracersRiptide)}, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskSpellHealing, - Flags: core.SpellFlagHelpful | core.SpellFlagAPL | SpellFlagShaman, - - ManaCost: core.ManaCostOptions{ - BaseCost: 0.18, - }, - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - CD: core.Cooldown{ - Timer: shaman.NewTimer(), - Duration: time.Second * 6, - }, - }, - - Hot: core.DotConfig{ - Aura: core.Aura{ - Label: "Riptide", - }, - NumberOfTicks: 5, - TickLength: time.Second * 3, - BonusCoefficient: hotCoeff, - OnSnapshot: func(sim *core.Simulation, target *core.Unit, dot *core.Dot, isRollover bool) { - dot.Snapshot(target, baseHotHealing, isRollover) - }, - OnTick: func(sim *core.Simulation, target *core.Unit, dot *core.Dot) { - dot.CalcAndDealPeriodicSnapshotHealing(sim, target, dot.OutcomeTick) - - if hasPowerSurgeRune && sim.Proc(shaman.powerSurgeProcChance, "Power Surge Proc") { - shaman.PowerSurgeHealAura.Activate(sim) - } - }, - }, - - BonusCoefficient: spellCoeff, - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealHealing(sim, spell.Unit, sim.Roll(baseHealingLow, baseHealingHigh), spell.OutcomeHealingCrit) - spell.Hot(spell.Unit).Apply(sim) - }, - }) -} diff --git a/sim/shaman/rolling_thunder.go b/sim/shaman/rolling_thunder.go deleted file mode 100644 index f15782ff6b..0000000000 --- a/sim/shaman/rolling_thunder.go +++ /dev/null @@ -1,72 +0,0 @@ -package shaman - -import ( - "slices" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" -) - -func (shaman *Shaman) registerRollingThunder() { - if !shaman.HasRune(proto.ShamanRune_RuneBracersRollingThunder) { - return - } - - actionID := core.ActionID{SpellID: 432129} - impLightningShieldBonus := []float64{1, 1.05, 1.10, 1.15}[shaman.Talents.ImprovedLightningShield] - manaMetrics := shaman.NewManaMetrics(actionID) - - procChance := 0.50 - - // Casts handled in lightning_shield.go - shaman.RollingThunder = shaman.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - SpellSchool: core.SpellSchoolNature, - DefenseType: core.DefenseTypeMagic, - ProcMask: core.ProcMaskEmpty, - Flags: SpellFlagShaman | SpellFlagLightning, - - DamageMultiplier: 1, - ThreatMultiplier: 1, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if shaman.ActiveShield == nil || shaman.ActiveShield.SpellCode != SpellCode_ShamanLightningShield { - return - } - - rank := shaman.ActiveShield.Rank - numCharges := float64(shaman.ActiveShieldAura.GetStacks() - 3) - - // TODO: Need a better way to get a spell's base damage directly from a spell - chargeDamage := LightningShieldBaseDamage[rank]*impLightningShieldBonus + LightningShieldSpellCoef[rank]*shaman.LightningShieldProcs[rank].GetBonusDamage() - spell.CalcAndDealDamage(sim, target, chargeDamage*numCharges, spell.OutcomeMagicCrit) - - shaman.AddMana(sim, .02*numCharges*shaman.MaxMana(), manaMetrics) - shaman.ActiveShieldAura.SetStacks(sim, 3) - }, - }) - - affectedSpellCodes := []int32{SpellCode_ShamanLightningBolt, SpellCode_ShamanChainLightning} - - core.MakePermanent(shaman.RegisterAura(core.Aura{ - Label: "Rolling Thunder Trigger", - OnInit: func(aura *core.Aura, sim *core.Simulation) { - for _, aura := range shaman.LightningShieldAuras { - if aura != nil { - aura.MaxStacks = 9 - } - } - }, - OnSpellHitDealt: func(_ *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if shaman.ActiveShield == nil || shaman.ActiveShield.SpellCode != SpellCode_ShamanLightningShield { - return - } - - if spell.SpellCode == SpellCode_ShamanEarthShock && shaman.ActiveShieldAura.GetStacks() > 3 { - shaman.RollingThunder.Cast(sim, result.Target) - } else if slices.Contains(affectedSpellCodes, spell.SpellCode) && sim.Proc(procChance, "Rolling Thunder") { - shaman.ActiveShieldAura.AddStack(sim) - } - }, - })) -} diff --git a/sim/shaman/shaman.go b/sim/shaman/shaman.go index 04a9253369..0b9a1ddeab 100644 --- a/sim/shaman/shaman.go +++ b/sim/shaman/shaman.go @@ -15,7 +15,6 @@ const ( SpellFlagShaman = core.SpellFlagAgentReserved1 SpellFlagTotem = core.SpellFlagAgentReserved2 SpellFlagLightning = core.SpellFlagAgentReserved3 - SpellFlagMaelstrom = core.SpellFlagAgentReserved4 ) func NewShaman(character *core.Character, talents string) *Shaman { @@ -50,9 +49,6 @@ func (shaman *Shaman) getImbueProcMask(imbue proto.WeaponImbue) core.ProcMask { if shaman.HasMHWeapon() && shaman.Consumes.MainHandImbue == imbue { mask |= core.ProcMaskMeleeMH } - if shaman.HasOHWeapon() && shaman.Consumes.OffHandImbue == imbue { - mask |= core.ProcMaskMeleeOH - } return mask } @@ -70,18 +66,14 @@ const ( SpellCode_ShamanChainHeal SpellCode_ShamanChainLightning SpellCode_ShamanEarthShock - SpellCode_ShamanFireNova SpellCode_ShamanFireNovaTotem SpellCode_ShamanFlameShock SpellCode_ShamanFrostShock SpellCode_ShamanHealingWave - SpellCode_ShamanLavaLash SpellCode_ShamanLesserHealingWave SpellCode_ShamanLightningBolt SpellCode_ShamanLightningShield - SpellCode_ShamanLavaBurst SpellCode_ShamanMagmaTotem - SpellCode_ShamanMoltenBlast SpellCode_ShamanSearingTotem SpellCode_ShamanStormstrike ) @@ -93,58 +85,36 @@ type Shaman struct { Talents *proto.ShamanTalents // Spells - AncestralAwakening *core.Spell - ChainHeal []*core.Spell - ChainHealOverload []*core.Spell - ChainLightning []*core.Spell - ChainLightningOverload []*core.Spell - EarthShield *core.Spell - EarthShock []*core.Spell - ElementalMastery *core.Spell - FeralSpirit *core.Spell - FireNova *core.Spell - FireNovaTotem []*core.Spell - FlameShock []*core.Spell - FrostShock []*core.Spell - GraceOfAirTotem []*core.Spell - HealingStreamTotem []*core.Spell - HealingWave []*core.Spell - HealingWaveOverload []*core.Spell - LavaBurst *core.Spell - LavaBurstOverload *core.Spell - LavaLash *core.Spell - LesserHealingWave []*core.Spell - LightningBolt []*core.Spell - LightningBoltOverload []*core.Spell - LightningShield []*core.Spell - LightningShieldProcs []*core.Spell // The damage component of lightning shield is a separate spell - MagmaTotem []*core.Spell - ManaSpringTotem []*core.Spell - MoltenBlast *core.Spell - Riptide *core.Spell - RollingThunder *core.Spell - SearingTotem []*core.Spell - StoneskinTotem []*core.Spell - StormstrikeMH *core.Spell - StormstrikeOH *core.Spell - StrengthOfEarthTotem []*core.Spell - TremorTotem *core.Spell - WaterShield *core.Spell - WaterShieldRestore *core.Spell - WindfuryTotem []*core.Spell - WindfuryWeaponMH *core.Spell - WindfuryWeaponOH *core.Spell - WindwallTotem []*core.Spell + ChainHeal []*core.Spell + ChainLightning []*core.Spell + EarthShield *core.Spell + EarthShock []*core.Spell + ElementalMastery *core.Spell + FireNovaTotem []*core.Spell + FlameShock []*core.Spell + FrostShock []*core.Spell + GraceOfAirTotem []*core.Spell + HealingStreamTotem []*core.Spell + HealingWave []*core.Spell + LesserHealingWave []*core.Spell + LightningBolt []*core.Spell + LightningShield []*core.Spell + LightningShieldProcs []*core.Spell // The damage component of lightning shield is a separate spell + MagmaTotem []*core.Spell + ManaSpringTotem []*core.Spell + SearingTotem []*core.Spell + StoneskinTotem []*core.Spell + StormstrikeMH *core.Spell + StrengthOfEarthTotem []*core.Spell + TremorTotem *core.Spell + WindfuryTotem []*core.Spell + WindfuryWeaponMH *core.Spell + WindfuryWeaponOH *core.Spell + WindwallTotem []*core.Spell // Auras ClearcastingAura *core.Aura LightningShieldAuras []*core.Aura - LoyalBetaAura *core.Aura - MaelstromWeaponAura *core.Aura - PowerSurgeDamageAura *core.Aura - PowerSurgeHealAura *core.Aura - SpiritOfTheAlphaAura *core.Aura - WaterShieldAura *core.Aura // Totems ActiveTotems [4]*core.Spell @@ -158,21 +128,6 @@ type Shaman struct { // Shield ActiveShield *core.Spell // Tracks the Shaman's active shield spell ActiveShieldAura *core.Aura - - // Pets - SpiritWolves *SpiritWolves - - // Other data - ancestralHealingAmount float64 // Used by Ancestral Awakening - bonusFlurrySpeed float64 // Bonus added on top of the normal speed, e.g. Earthfury Impact 6pc - bonusWindfuryWeaponAP float64 - elementalFocusProcChance float64 - lastFlameShockTarget *core.Unit // Used by Ancestral Guidance rune - lightningShieldCanCrit bool - maelstromWeaponPPMM *core.PPMManager - powerSurgeProcChance float64 - staticSHocksProcChance float64 - useLavaBurstCritScaling bool } // Implemented by each Shaman spec. @@ -219,9 +174,6 @@ func (shaman *Shaman) Initialize() { shaman.registerGraceOfAirTotemSpell() shaman.registerWindwallTotemSpell() - // Other Abilities - shaman.registerShamanisticRageCD() - // // This registration must come after all the totems are registered // shaman.registerCallOfTheElements() diff --git a/sim/shaman/shamanistic_rage.go b/sim/shaman/shamanistic_rage.go deleted file mode 100644 index f7a7448b97..0000000000 --- a/sim/shaman/shamanistic_rage.go +++ /dev/null @@ -1,59 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" -) - -func (shaman *Shaman) registerShamanisticRageCD() { - damageTakenMultiplier := .8 - duration := time.Second * 15 - cooldown := time.Minute * 1 - - actionID := core.ActionID{SpellID: 425336} - manaMetrics := shaman.NewManaMetrics(actionID) - srAura := shaman.GetOrRegisterAura(core.Aura{ - Label: "Shamanistic Rage", - ActionID: actionID, - Duration: duration, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.PseudoStats.DamageTakenMultiplier *= damageTakenMultiplier - - // Sham rage mana gain is snapshotted on cast - // TODO: Raid mana regain - var manaPerTick = shaman.GetCharacter().MaxMana() * .05 - - core.StartPeriodicAction(sim, core.PeriodicActionOptions{ - NumTicks: 15, - Period: time.Second * 1, - OnAction: func(sim *core.Simulation) { - shaman.AddMana(sim, manaPerTick, manaMetrics) - }, - }) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.PseudoStats.DamageTakenMultiplier /= damageTakenMultiplier - }, - }) - - srSpell := shaman.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - Flags: SpellFlagShaman | core.SpellFlagNoOnCastComplete, - Cast: core.CastConfig{ - IgnoreHaste: true, - CD: core.Cooldown{ - Timer: shaman.NewTimer(), - Duration: cooldown, - }, - }, - ApplyEffects: func(sim *core.Simulation, _ *core.Unit, _ *core.Spell) { - srAura.Activate(sim) - }, - }) - - shaman.AddMajorCooldown(core.MajorCooldown{ - Spell: srSpell, - Type: core.CooldownTypeMana, - }) -} diff --git a/sim/shaman/spirit_wolves.go b/sim/shaman/spirit_wolves.go deleted file mode 100644 index 685693936d..0000000000 --- a/sim/shaman/spirit_wolves.go +++ /dev/null @@ -1,85 +0,0 @@ -package shaman - -import ( - "math" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/stats" -) - -type SpiritWolves struct { - core.Pet - - shamanOwner *Shaman -} - -var spiritWolfBaseStats = stats.Stats{ - stats.Strength: 136, - stats.Agility: 100, - stats.Stamina: 265, - stats.Intellect: 50, - stats.Spirit: 80, - // Base AP 265 - (136 * 2) - (100 * 0.2) - stats.AttackPower: -27, - - // Add 1.8% because pets aren't affected by that component of crit suppression. - stats.MeleeCrit: (1.1515 + 1.8) * core.CritRatingPerCritChance, -} - -func (shaman *Shaman) NewSpiritWolves() *SpiritWolves { - wolves := &SpiritWolves{ - Pet: core.NewPet("Spirit Wolves", &shaman.Character, spiritWolfBaseStats, shaman.makeStatInheritance(), false, true), - shamanOwner: shaman, - } - - wolves.EnableAutoAttacks(wolves, core.AutoAttackOptions{ - MainHand: core.Weapon{ - BaseDamageMin: 55.5, - BaseDamageMax: 71.5, - SwingSpeed: 1.5 / 2, // Two dogs attack at 1.5s intervals, but for performance we use 1 pet so divide by 2 - }, - AutoSwingMelee: true, - }) - - // Testing found that wolves gained 2 AP per Str, and ~1 AP per 5 Agi - // Tested using different ranks of Strength of Earth and Grace of Air Totems - wolves.AddStatDependency(stats.Strength, stats.AttackPower, 2) - wolves.AddStatDependency(stats.Agility, stats.AttackPower, 0.2) - - // Warrior crit scaling - core.ApplyPetConsumeEffects(&wolves.Character, shaman.Consumes) - - shaman.AddPet(wolves) - - return wolves -} - -func (shaman *Shaman) makeStatInheritance() core.PetStatInheritance { - return func(ownerStats stats.Stats) stats.Stats { - ownerHitChance := ownerStats[stats.MeleeHit] / core.MeleeHitRatingPerHitChance - hitRatingFromOwner := math.Floor(ownerHitChance) * core.MeleeHitRatingPerHitChance - - return stats.Stats{ - stats.Stamina: ownerStats[stats.Stamina] * 0.3, - stats.Armor: ownerStats[stats.Armor] * 0.35, - stats.AttackPower: ownerStats[stats.AttackPower] * 0.31, - stats.MeleeCrit: ownerStats[stats.MeleeCrit], // Logs showed high crit rates consistent with inheriting owner hit but possibly not scaling from Agi - stats.MeleeHit: hitRatingFromOwner, - } - } -} - -func (wolves *SpiritWolves) Initialize() { - // Nothing -} - -func (wolves *SpiritWolves) ExecuteCustomRotation(_ *core.Simulation) { -} - -func (wolves *SpiritWolves) Reset(sim *core.Simulation) { - wolves.Disable(sim) -} - -func (spiritWolf *SpiritWolves) GetPet() *core.Pet { - return &spiritWolf.Pet -} diff --git a/sim/shaman/stormstrike.go b/sim/shaman/stormstrike.go index 61234a5f71..b62ae6ec6a 100644 --- a/sim/shaman/stormstrike.go +++ b/sim/shaman/stormstrike.go @@ -4,21 +4,17 @@ import ( "time" "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" ) +// TODO: All of this needs to be refactored for how it works in Vanilla vs SoD. +// Gives an extra attack instead of a true yellow hit func (shaman *Shaman) registerStormstrikeSpell() { if !shaman.Talents.Stormstrike { return } - hasDualWieldSpecRune := shaman.HasRune(proto.ShamanRune_RuneChestDualWieldSpec) - - shaman.StormstrikeMH = shaman.newStormstrikeHitSpell(true) + shaman.StormstrikeMH = shaman.newStormstrikeHitSpell() shaman.StormstrikeMH.SpellCode = SpellCode_ShamanStormstrike - if hasDualWieldSpecRune { - shaman.StormstrikeOH = shaman.newStormstrikeHitSpell(false) - } shaman.RegisterSpell(core.SpellConfig{ ActionID: core.ActionID{SpellID: 17364}, @@ -41,47 +37,33 @@ func (shaman *Shaman) registerStormstrikeSpell() { }, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - // offhand always swings first - if shaman.AutoAttacks.IsDualWielding && shaman.StormstrikeOH != nil { - shaman.StormstrikeOH.Cast(sim, target) - } shaman.StormstrikeMH.Cast(sim, target) }, }) } // Only the main-hand hit triggers procs / the debuff -func (shaman *Shaman) newStormstrikeHitSpell(isMH bool) *core.Spell { - procMask := core.ProcMaskMeleeMHSpecial - flags := core.SpellFlagMeleeMetrics - damageMultiplier := 1.0 - damageFunc := shaman.MHWeaponDamage - if !isMH { - procMask = core.ProcMaskMeleeOHSpecial - flags |= core.SpellFlagNoOnCastComplete - damageMultiplier = shaman.AutoAttacks.OHConfig().DamageMultiplier - damageFunc = shaman.OHWeaponDamage - } - +func (shaman *Shaman) newStormstrikeHitSpell() *core.Spell { stormStrikeAuras := shaman.NewEnemyAuraArray(func(target *core.Unit) *core.Aura { return core.StormstrikeAura(target) }) return shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 17364}.WithTag(int32(core.Ternary(isMH, 1, 2))), + ActionID: core.ActionID{SpellID: 17364}.WithTag(1), SpellSchool: core.SpellSchoolPhysical, DefenseType: core.DefenseTypeMelee, - ProcMask: procMask, - Flags: flags, + ProcMask: core.ProcMaskMeleeMHSpecial, + Flags: core.SpellFlagMeleeMetrics, - DamageMultiplier: damageMultiplier, + DamageMultiplier: 1, ThreatMultiplier: 1, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - baseDamage := damageFunc(sim, spell.MeleeAttackPower()) + baseDamage := shaman.MHWeaponDamage(sim, spell.MeleeAttackPower()) result := spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) - if isMH && result.Landed() { + if result.Landed() { + // TODO: Stormstrike with 2 stacks instead of unlimited stormStrikeAuras.Get(target).Activate(sim) } }, diff --git a/sim/shaman/talents.go b/sim/shaman/talents.go index e8e29e2336..e9cb436557 100644 --- a/sim/shaman/talents.go +++ b/sim/shaman/talents.go @@ -102,8 +102,6 @@ func (shaman *Shaman) applyElementalFocus() { return } - shaman.elementalFocusProcChance = 0.1 - var affectedSpells []*core.Spell shaman.ClearcastingAura = shaman.RegisterAura(core.Aura{ @@ -148,7 +146,7 @@ func (shaman *Shaman) applyElementalFocus() { core.MakePermanent(shaman.RegisterAura(core.Aura{ Label: "Elemental Focus Trigger", OnCastComplete: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell) { - if shaman.isShamanDamagingSpell(spell) && sim.Proc(shaman.elementalFocusProcChance, "Elemental Focus") { + if shaman.isShamanDamagingSpell(spell) && sim.Proc(0.10, "Elemental Focus") { shaman.ClearcastingAura.Activate(sim) shaman.ClearcastingAura.SetStacks(sim, shaman.ClearcastingAura.MaxStacks) } @@ -394,10 +392,10 @@ func (shaman *Shaman) makeFlurryAura(points int32) *core.Aura { aura.NewExclusiveEffect("Flurry", true, core.ExclusiveEffect{ Priority: attackSpeed, OnGain: func(ee *core.ExclusiveEffect, sim *core.Simulation) { - shaman.MultiplyMeleeSpeed(sim, attackSpeed+shaman.bonusFlurrySpeed) + shaman.MultiplyMeleeSpeed(sim, attackSpeed) }, OnExpire: func(ee *core.ExclusiveEffect, sim *core.Simulation) { - shaman.MultiplyMeleeSpeed(sim, 1/(attackSpeed+shaman.bonusFlurrySpeed)) + shaman.MultiplyMeleeSpeed(sim, 1/(attackSpeed)) }, }) diff --git a/sim/shaman/water_shield.go b/sim/shaman/water_shield.go deleted file mode 100644 index 7bab0642ac..0000000000 --- a/sim/shaman/water_shield.go +++ /dev/null @@ -1,83 +0,0 @@ -package shaman - -import ( - "time" - - "github.com/wowsims/classic/sim/core" - "github.com/wowsims/classic/sim/core/proto" - "github.com/wowsims/classic/sim/core/stats" -) - -func (shaman *Shaman) registerWaterShieldSpell() { - if !shaman.HasRune(proto.ShamanRune_RuneHandsWaterShield) { - return - } - - actionID := core.ActionID{SpellID: int32(proto.ShamanRune_RuneHandsWaterShield)} - - passiveMP5Pct := .01 - onHitManaGainedPct := .04 - - manaMetrics := shaman.NewManaMetrics(actionID) - mp5StatDep := shaman.NewDynamicStatDependency(stats.Mana, stats.MP5, passiveMP5Pct) - - shaman.WaterShieldAura = shaman.RegisterAura(core.Aura{ - Label: "Water Shield", - ActionID: actionID, - Duration: time.Minute * 10, - MaxStacks: 3, - OnGain: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.EnableDynamicStatDep(sim, mp5StatDep) - }, - OnExpire: func(aura *core.Aura, sim *core.Simulation) { - aura.Unit.DisableDynamicStatDep(sim, mp5StatDep) - - if shaman.ActiveShieldAura == aura { - shaman.ActiveShieldAura = nil - shaman.ActiveShield = nil - } - }, - OnSpellHitTaken: func(aura *core.Aura, sim *core.Simulation, spell *core.Spell, result *core.SpellResult) { - if result.Landed() && spell.ProcMask.Matches(core.ProcMaskDirect) { - shaman.WaterShieldRestore.Cast(sim, aura.Unit) - aura.RemoveStack(sim) - - if aura.GetStacks() == 0 { - aura.Deactivate(sim) - } - } - }, - }) - - shaman.WaterShield = shaman.RegisterSpell(core.SpellConfig{ - ActionID: actionID, - ProcMask: core.ProcMaskEmpty, - Flags: SpellFlagShaman | core.SpellFlagAPL, - - Cast: core.CastConfig{ - DefaultCast: core.Cast{ - GCD: core.GCDDefault, - }, - }, - - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - if shaman.ActiveShieldAura != nil { - shaman.ActiveShieldAura.Deactivate(sim) - } - shaman.ActiveShield = spell - shaman.ActiveShieldAura = shaman.WaterShieldAura - shaman.WaterShieldAura.Activate(sim) - shaman.WaterShieldAura.SetStacks(sim, shaman.WaterShieldAura.MaxStacks) - }, - }) - - shaman.WaterShieldRestore = shaman.RegisterSpell(core.SpellConfig{ - ActionID: core.ActionID{SpellID: 408511}, - SpellSchool: core.SpellSchoolNature, - Flags: core.SpellFlagNoOnCastComplete | core.SpellFlagPassiveSpell | core.SpellFlagNoMetrics, - ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - spell.CalcAndDealOutcome(sim, target, spell.OutcomeAlwaysHit) - shaman.AddMana(sim, shaman.MaxMana()*onHitManaGainedPct, manaMetrics) - }, - }) -} diff --git a/sim/shaman/windfury_weapon.go b/sim/shaman/windfury_weapon.go index 112ce3182f..bb54241257 100644 --- a/sim/shaman/windfury_weapon.go +++ b/sim/shaman/windfury_weapon.go @@ -47,7 +47,7 @@ func (shaman *Shaman) newWindfuryImbueSpell(isMH bool) *core.Spell { ThreatMultiplier: 1, ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { - mAP := spell.MeleeAttackPower() + (bonusAP+shaman.bonusWindfuryWeaponAP)*ewMultiplier*ewMultiplier + mAP := spell.MeleeAttackPower() + bonusAP*ewMultiplier*ewMultiplier baseDamage := weaponDamageFunc(sim, mAP) spell.CalcAndDealDamage(sim, target, baseDamage, spell.OutcomeMeleeWeaponSpecialHitAndCrit) }, @@ -84,7 +84,6 @@ func (shaman *Shaman) RegisterWindfuryImbue(procMask core.ProcMask) { } shaman.WindfuryWeaponMH = shaman.newWindfuryImbueSpell(true) - shaman.WindfuryWeaponOH = shaman.newWindfuryImbueSpell(false) aura := shaman.RegisterAura(core.Aura{ Label: "Windfury Imbue", @@ -104,13 +103,10 @@ func (shaman *Shaman) RegisterWindfuryImbue(procMask core.ProcMask) { if sim.RandomFloat("Windfury Imbue") < proc { icd.Use(sim) - if spell.IsMH() { - shaman.WindfuryWeaponMH.Cast(sim, result.Target) - shaman.WindfuryWeaponMH.Cast(sim, result.Target) - } else { - shaman.WindfuryWeaponOH.Cast(sim, result.Target) - shaman.WindfuryWeaponOH.Cast(sim, result.Target) - } + // TODO: Vanilla uses two extra attacks but SoD replaced this with yellow hits + // This needs to be refactored + shaman.WindfuryWeaponMH.Cast(sim, result.Target) + shaman.WindfuryWeaponMH.Cast(sim, result.Target) } }, }) From cf1e85961ea58e7ead5626e39402dfcb47217496 Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 16:25:19 -0500 Subject: [PATCH 79/83] a little bit more cleanup --- sim/priest/circle_of_healing.go | 40 -------- ui/core/proto_utils/action_id.ts | 163 +------------------------------ 2 files changed, 1 insertion(+), 202 deletions(-) delete mode 100644 sim/priest/circle_of_healing.go diff --git a/sim/priest/circle_of_healing.go b/sim/priest/circle_of_healing.go deleted file mode 100644 index fef8cbeb91..0000000000 --- a/sim/priest/circle_of_healing.go +++ /dev/null @@ -1,40 +0,0 @@ -package priest - -// func (priest *Priest) registerCircleOfHealingSpell() { -// targets := priest.Env.Raid.GetFirstNPlayersOrPets(5) - -// priest.CircleOfHealing = priest.RegisterSpell(core.SpellConfig{ -// ActionID: core.ActionID{SpellID: 401946}, -// SpellSchool: core.SpellSchoolHoly, -// DefenseType: core.DefenseTypeMagic, -// ProcMask: core.ProcMaskSpellHealing, -// Flags: SpellFlagPriest | core.SpellFlagHelpful | core.SpellFlagAPL, - -// ManaCost: core.ManaCostOptions{ -// BaseCost: 0.21, -// Multiplier: 1, -// }, -// Cast: core.CastConfig{ -// DefaultCast: core.Cast{ -// GCD: core.GCDDefault, -// }, -// CD: core.Cooldown{ -// Timer: priest.NewTimer(), -// Duration: time.Second * 6, -// }, -// }, - -// BonusCritRating: float64(priest.Talents.HolySpecialization) * 1 * core.CritRatingPerCritChance, - -// DamageMultiplier: 1 + .02*float64(priest.Talents.SpiritualHealing), -// ThreatMultiplier: 1 - []float64{0, .07, .14, .20}[priest.Talents.SilentResolve], - -// ApplyEffects: func(sim *core.Simulation, target *core.Unit, spell *core.Spell) { -// healFromSP := 0.4029 * spell.HealingPower(target) -// for _, aoeTarget := range targets { -// baseHealing := sim.Roll(958, 1058) + healFromSP -// spell.CalcAndDealHealing(sim, aoeTarget, baseHealing, spell.OutcomeHealingCrit) -// } -// }, -// }) -// } diff --git a/ui/core/proto_utils/action_id.ts b/ui/core/proto_utils/action_id.ts index 735a76a243..47ee375c27 100644 --- a/ui/core/proto_utils/action_id.ts +++ b/ui/core/proto_utils/action_id.ts @@ -242,40 +242,11 @@ export class ActionId { const baseName = tooltipData['name']; let name = baseName; switch (baseName) { - case 'Arcane Blast': - if (this.tag === 1) { - name += ' (No Stacks)'; - } else if (this.tag === 2) { - name += ` (1 Stack)`; - } else if (this.tag > 2) { - name += ` (${this.tag - 1} Stacks)`; - } - break; - // Arcane Missiles hits are a separate spell and have to use a tag to differentiate from the cast - case 'Arcane Missiles': - // Balefire Bolt's aura uses the same spell ID as the cast - case 'Balefire Bolt': - break; case 'Berserking': if (this.tag !== 0) name = `${name} (${this.tag * 5}%)`; break; - case 'Explosive Trap': - if (this.tag === 1) { - name += ' (Weaving)'; - } - break; - case 'Hot Streak': - if (this.tag) name = 'Heating Up'; - break; - // DoT then Explode Spells - case 'Living Bomb': - case 'Seed of Corruption': - if (this.tag === 0) name = `${name} (DoT)`; - else if (this.tag === 1) name = `${name} (Explosion)`; - break; // Burn Spells case 'Fireball': - case 'Frostfire Bolt': case 'Pyroblast': case 'Flame Shock': if (this.tag === 1) name = `${name} (DoT)`; @@ -283,16 +254,9 @@ export class ActionId { // Channeled Tick Spells case 'Evocation': case 'Mind Flay': - case 'Mind Sear': if (this.tag > 0) name = `${name} (${this.tag} Tick)`; break; - case 'Shattering Throw': - if (this.tag === playerIndex) { - name += ` (self)`; - } - break; // Combo Point Spenders - case 'Envenom': case 'Eviscerate': case 'Expose Armor': case 'Rupture': @@ -311,7 +275,6 @@ export class ActionId { case 'Instant Poison V': case 'Instant Poison VI': case 'Wound Poison': - case 'Occult Poison': if (this.tag === 1) { name += ' (Shiv)'; } else if (this.tag === 2) { @@ -320,18 +283,7 @@ export class ActionId { name += ' (Tick)'; } break; - case 'Saber Slash': - if (this.tag === 100) { - name += ' (Tick)'; - } - break; // Dual-hit MH/OH spells and weapon imbues - case 'Mutilate': - case 'Stormstrike': - case 'Carve': - case 'Whirlwind': - case 'Slam': - case 'Windfury Weapon': case 'Holy Strength': // Crusader Enchant if (this.tag === 1) { name = `${name} (Main-Hand)`; @@ -339,43 +291,13 @@ export class ActionId { name = `${name} (Off-Hand)`; } break; - // Shaman Overload + Maelstrom Weapon - case 'Lightning Bolt': - case 'Chain Lightning': - case 'Lava Burst': - case 'Healing Wave': - case 'Lesser Healing Wave': - case 'Chain Heal': - if (this.tag === 6) { - name = `${name} OL`; - } else if (this.tag) { - name = `${name} (${this.tag} MSW)`; - } - break; case 'Holy Shield': if (this.tag === 1) { name += ' (Proc)'; } break; - case 'Righteous Vengeance': - if (this.tag === 1) { - name += ' (Application)'; - } else if (this.tag === 2) { - name += ' (DoT)'; - } - break; - case 'Holy Vengeance': - if (this.tag === 1) { - name += ' (Application)'; - } else if (this.tag === 2) { - name += ' (DoT)'; - } - break; // For targetted buffs, tag is the source player's raid index or -1 if none. - case 'Bloodlust': - case 'Ferocious Inspiration': case 'Innervate': - case 'Focus Magic': case 'Mana Tide Totem': case 'Power Infusion': if (this.tag !== -1) { @@ -388,13 +310,6 @@ export class ActionId { name += ' (raid)'; } break; - case 'Darkmoon Card: Crusade': - if (this.tag === 1) { - name += ' (Melee)'; - } else if (this.tag === 2) { - name += ' (Spell)'; - } - break; case 'Battle Shout': if (this.tag === 1) { name += ' (Snapshot)'; @@ -407,13 +322,6 @@ export class ActionId { name += ' (Queue)'; } break; - // There are many different types of enrages. Try to give clarity to users. - case 'Enrage': - if (this.spellId === 13048) name = `${name} (Talent)`; - else if (this.spellId === 14201) name = `${name} (Fresh Meat)`; - else if (this.spellId === 425415) name = `${name} (Consumed by Rage)`; - else if (this.spellId === 427066) name = `${name} (Wrecking Crew)`; - break; case 'Raptor Strike': if (this.tag === 1) name = `${name} (Hit)`; else if (this.tag === 3) name = `${name} (Queue)`; @@ -425,46 +333,6 @@ export class ActionId { name += ' (Bounce)'; } break; - case 'Sunfire': - if (this.spellId === 414689) { - name = `${name} (Cat)`; - } - break; - case 'Mangle': - name = this.spellId === 409828 ? `${name} (Cat)` : `${name} (Bear)`; - break; - case 'Swipe': - name = this.spellId === 411128 ? `${name} (Cat)` : `${name} (Bear)`; - break; - case 'Starfall': - if (this.tag === 1) name = `${name} (Tick)`; - else if (this.tag === 2) name = `${name} (Splash)`; - break; - case 'S03 - Item - T1 - Mage - Damage 4P Bonus': - // Tags correspond to each non-physical spell school - if (this.tag === 2) name = `${name} (Arcane)`; - if (this.tag === 3) name = `${name} (Fire)`; - if (this.tag === 4) name = `${name} (Frost)`; - if (this.tag === 5) name = `${name} (Holy)`; - if (this.tag === 6) name = `${name} (Nature)`; - if (this.tag === 7) name = `${name} (Shadow)`; - break; - // Don't do anything for these but avoid adding "(??)" - case 'S03 - Item - T1 - Shaman - Tank 6P Bonus': - break; - case 'Vampiric Touch': - // Vampiric touch provided to the party - if (this.tag === 1) name = `${name} (External)`; - break; - case 'Totem of Raging Fire': - if (this.tag === 1) name = `${name} (1H)`; - else if (this.tag === 2) name = `${name} (2H)`; - break; - // Warlock T2 6 Piece Needs Heals to trigger for the player - case 'Drain Life': - case 'Death Coil': - if (this.tag === 1) name += ` (Heal)` - break; default: if (this.tag) { name += ' (??)'; @@ -472,23 +340,7 @@ export class ActionId { break; } - let iconOverrideId = this.spellIconOverride; - - // Icon Overrides based on tags - switch (this.spellId) { - // https://www.wowhead.com/classic/spell=457544/s03-item-t1-shaman-tank-6p-bonus - case 457544: { - // Show Stoneskin / Windwall respectively - if (this.tag === 1) iconOverrideId = ActionId.fromSpellId(10408); - else if (this.tag === 2) iconOverrideId = ActionId.fromSpellId(15112); - } - } - - let iconUrl = ActionId.makeIconUrl(tooltipData['icon']); - if (iconOverrideId) { - const overrideTooltipData = await ActionId.getTooltipData(iconOverrideId); - iconUrl = ActionId.makeIconUrl(overrideTooltipData['icon']); - } + const iconUrl = ActionId.makeIconUrl(tooltipData['icon']); return new ActionId(this.itemId, this.spellId, this.otherId, this.tag, baseName, name, iconUrl, this.rank || tooltipData.rank, this.randomSuffixId); } @@ -714,21 +566,8 @@ const spellIDsToShowBuffs = new Set([ 24932, // https://www.wowhead.com/classic/spell=24932/leader-of-the-pack 402808, // https://www.wowhead.com/classic/spell=402808/cripple 425415, // https://www.wowhead.com/classic/spell=425415/enrage - 426969, // https://www.wowhead.com/classic/spell=426969/taste-for-blood - 440114, // https://www.wowhead.com/classic/spell=440114/sudden-death - 446393, // https://www.wowhead.com/classic/spell=446393/decay - 457699, // https://www.wowhead.com/classic/spell=457699/echoes-of-defensive-stance - 457706, // https://www.wowhead.com/classic/spell=457706/echoes-of-battle-stance - 457708, // https://www.wowhead.com/classic/spell=457708/echoes-of-berserker-stance - 457814, // https://www.wowhead.com/classic/spell=457814/defensive-forecast - 457816, // https://www.wowhead.com/classic/spell=457816/battle-forecast - 457817, // https://www.wowhead.com/classic/spell=457817/berserker-forecast - 457819, // https://www.wowhead.com/classic/spell=457819/echoes-of-gladiator-stance - 458403, // https://www.wowhead.com/classic/spell=458403/stalker 461252, // https://www.wowhead.com/classic/spell=461252/shadowflame-fury 461270, // https://www.wowhead.com/classic/spell=461270/magmadars-return - 461615, // https://www.wowhead.com/classic/spell=461615/mark-of-chaos - 456393, // https://www.wowhead.com/classic/spell=456393/stalked 1214279, // https://www.wowhead.com/classic/spell=1214279/spell-blasting ]); From d2390a62d04b688c87571951bd8bb719798f1b4b Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 16:27:18 -0500 Subject: [PATCH 80/83] flag cleanup --- sim/core/apl.go | 4 ---- sim/core/cast.go | 42 +----------------------------------------- sim/core/flags.go | 2 -- sim/core/spell.go | 4 ++-- sim/core/unit.go | 5 ++--- 5 files changed, 5 insertions(+), 52 deletions(-) diff --git a/sim/core/apl.go b/sim/core/apl.go index 72230bb74a..66c5d905d8 100644 --- a/sim/core/apl.go +++ b/sim/core/apl.go @@ -2,7 +2,6 @@ package core import ( "fmt" - "slices" "time" "github.com/wowsims/classic/sim/core/proto" @@ -170,9 +169,6 @@ func (rot *APLRotation) reset(sim *Simulation) { rot.inLoop = false rot.interruptChannelIf = nil rot.allowChannelRecastOnInterrupt = false - rot.allowCastWhileChanneling = slices.ContainsFunc(rot.unit.Spellbook, func(spell *Spell) bool { - return spell.Flags.Matches(SpellFlagCastWhileChanneling) - }) for _, action := range rot.allAPLActions() { action.impl.Reset(sim) } diff --git a/sim/core/cast.go b/sim/core/cast.go index 00f6caf38c..18a6f6d6a0 100644 --- a/sim/core/cast.go +++ b/sim/core/cast.go @@ -194,20 +194,10 @@ func (spell *Spell) makeCastFunc(config CastConfig) CastSuccessFunc { } if hc := spell.Unit.Hardcast; spell.Unit.IsCasting(sim) { - // Attempt to use a queued cast-while-casting spell mid-hard cast - if cwc := spell.Unit.castWhileCastingAction; cwc != nil { - cwc.OnAction(sim) - } - return spell.castFailureHelper(sim, "casting/channeling %v for %s, curTime = %s", hc.ActionID, hc.Expires-sim.CurrentTime, sim.CurrentTime) } - if dot := spell.Unit.ChanneledDot; spell.Unit.IsChanneling(sim) && !spell.Flags.Matches(SpellFlagCastWhileChanneling) { - // Attempt to use a queued cast-while-casting spell mid-hard cast - if cwc := spell.Unit.castWhileCastingAction; cwc != nil { - cwc.OnAction(sim) - } - + if dot := spell.Unit.ChanneledDot; spell.Unit.IsChanneling(sim) { return spell.castFailureHelper(sim, "channeling %v for %s, curTime = %s", dot.ActionID, dot.expires-sim.CurrentTime, sim.CurrentTime) } @@ -233,36 +223,6 @@ func (spell *Spell) makeCastFunc(config CastConfig) CastSuccessFunc { spell.Unit.AutoAttacks.StopMeleeUntil(sim, restartMeleeAt, false) } - // Castable-while-casting spells - if spell.Flags.Matches(SpellFlagCastWhileCasting) { - // Queue cast-while-casting spells to cast 750 ms into the next hard-cast - pa := &PendingAction{ - NextActionAt: sim.CurrentTime + GCDDefault/2, - OnAction: func(sim *Simulation) { - spell.LastCastAt = sim.CurrentTime - - if sim.Log != nil && !spell.Flags.Matches(SpellFlagNoLogs) { - spell.Unit.Log(sim, "Casting %s (Cost = %0.03f, Cast Time = %s, Effective Time = %s)", - spell.ActionID, max(0, spell.CurCast.Cost), spell.CurCast.CastTime, spell.CurCast.EffectiveTime()) - spell.Unit.Log(sim, "Completed cast %s", spell.ActionID) - } - - if spell.Cost != nil { - spell.Cost.SpendCost(sim, spell) - } - - spell.applyEffects(sim, target) - - if !spell.Flags.Matches(SpellFlagNoOnCastComplete) { - spell.Unit.OnCastComplete(sim, spell) - } - }, - } - spell.Unit.castWhileCastingAction = pa - sim.AddPendingAction(pa) - return true - } - // Hardcasts if spell.CurCast.CastTime > 0 { if sim.Log != nil && !spell.Flags.Matches(SpellFlagNoLogs) { diff --git a/sim/core/flags.go b/sim/core/flags.go index 53c0811698..7721831434 100644 --- a/sim/core/flags.go +++ b/sim/core/flags.go @@ -186,8 +186,6 @@ const ( SpellFlagDefensiveEquipment // Indicates this spell a defensive equippable item activation spell SpellFlagResetAttackSwing // Indicates this spell resets the melee swing timer. SpellFlagCastTimeNoGCD // Indicates this spell is off the GCD (e.g. hunter's Auto Shot) - SpellFlagCastWhileCasting // Indicates this spell can be cast while another spell is being cast (e.g. mage's Fire Blast with Overheat rune) - SpellFlagCastWhileChanneling // Indicates this spell can be cast while another spell is being channeled (e.g. spriest's T2.5 4pc set bonus) SpellFlagPureDot // Indicates this spell is a dot with no initial damage component SpellFlagPassiveSpell // Indicates this spell is applied/cast as a result of another spell SpellFlagSuppressWeaponProcs // Indicates this spell cannot proc weapon chance on hits or enchants diff --git a/sim/core/spell.go b/sim/core/spell.go index dc424ab513..2e817e8ed2 100644 --- a/sim/core/spell.go +++ b/sim/core/spell.go @@ -521,7 +521,7 @@ func (spell *Spell) CanCast(sim *Simulation, target *Unit) bool { } // While casting no other action is possible except rare cast-while-casting spells - if spell.Unit.IsCasting(sim) && !spell.Flags.Matches(SpellFlagCastWhileCasting) { + if spell.Unit.IsCasting(sim) { //if sim.Log != nil { // sim.Log("Cant cast because already casting") //} @@ -529,7 +529,7 @@ func (spell *Spell) CanCast(sim *Simulation, target *Unit) bool { } // While channeling no other action is possible except rare cast-while-channeling spells - if spell.Unit.IsChanneling(sim) && !spell.Flags.Matches(SpellFlagCastWhileChanneling) { + if spell.Unit.IsChanneling(sim) { //if sim.Log != nil { // sim.Log("Cant cast because already channeling") //} diff --git a/sim/core/unit.go b/sim/core/unit.go index 1041257e13..ff016e65d2 100644 --- a/sim/core/unit.go +++ b/sim/core/unit.go @@ -140,9 +140,8 @@ type Unit struct { Hardcast Hardcast // GCD-related PendingActions. - gcdAction *PendingAction - hardcastAction *PendingAction - castWhileCastingAction *PendingAction + gcdAction *PendingAction + hardcastAction *PendingAction // Cached mana return values per tick. manaTickWhileCasting float64 From 5c80c1b0d2202a030acf1773281b773fda6f38b8 Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 16:31:37 -0500 Subject: [PATCH 81/83] cleaning up JS errors --- ui/core/components/individual_sim_ui/apl_values.ts | 9 --------- ui/core/components/inputs/warrior_inputs.ts | 3 +-- ui/hunter/inputs.ts | 3 +-- ui/hunter/sim.ts | 3 +-- ui/protection_paladin/inputs.ts | 4 ++-- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/ui/core/components/individual_sim_ui/apl_values.ts b/ui/core/components/individual_sim_ui/apl_values.ts index 77f7e4b6d3..6b933fb648 100644 --- a/ui/core/components/individual_sim_ui/apl_values.ts +++ b/ui/core/components/individual_sim_ui/apl_values.ts @@ -15,7 +15,6 @@ import { APLValueAutoTimeToNext, APLValueAutoTimeToNext_AttackType as AutoAttackType, APLValueCatExcessEnergy, - APLValueCatNewSavageRoarDuration, APLValueChannelClipDelay, APLValueCompare, APLValueCompare_ComparisonOperator as ComparisonOperator, @@ -939,14 +938,6 @@ const valueKindFactories: { [f in NonNullable]: ValueKindConfig, _isPrepull: boolean) => player.spec === Spec.SpecFeralDruid, fields: [], }), - catNewSavageRoarDuration: inputBuilder({ - label: 'New Savage Roar Duration', - submenu: ['Feral Druid'], - shortDescription: 'Returns duration of savage roar based on current combo points', - newValue: APLValueCatNewSavageRoarDuration.create, - includeIf: (player: Player, _isPrepull: boolean) => player.spec === Spec.SpecFeralDruid, - fields: [], - }), warlockShouldRecastDrainSoul: inputBuilder({ label: 'Should Recast Drain Soul', submenu: ['Warlock'], diff --git a/ui/core/components/inputs/warrior_inputs.ts b/ui/core/components/inputs/warrior_inputs.ts index e8182a1d10..3681708bfd 100644 --- a/ui/core/components/inputs/warrior_inputs.ts +++ b/ui/core/components/inputs/warrior_inputs.ts @@ -1,6 +1,5 @@ import * as InputHelpers from '../../components/input_helpers'; -import { ItemSlot } from '../../proto/common'; -import { WarriorRune, WarriorShout, WarriorStance } from '../../proto/warrior'; +import { WarriorShout, WarriorStance } from '../../proto/warrior'; import { ActionId } from '../../proto_utils/action_id'; import { WarriorSpecs } from '../../proto_utils/utils'; import { TypedEvent } from '../../typed_event'; diff --git a/ui/hunter/inputs.ts b/ui/hunter/inputs.ts index 3e20b0baac..34a4edd2c7 100644 --- a/ui/hunter/inputs.ts +++ b/ui/hunter/inputs.ts @@ -1,6 +1,6 @@ import * as InputHelpers from '../core/components/input_helpers.js'; import { Player } from '../core/player.js'; -import { ItemSlot, Spec } from '../core/proto/common.js'; +import { Spec } from '../core/proto/common.js'; import { Hunter_Options_Ammo as Ammo, Hunter_Options_PetAttackSpeed as PetAttackSpeed, @@ -8,7 +8,6 @@ import { Hunter_Options_QuiverBonus as QuiverBonus, Hunter_Rotation_RotationType as RotationType, Hunter_Rotation_StingType as StingType, - HunterRune, } from '../core/proto/hunter.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { makePetTypeInputConfig } from '../core/talents/hunter_pet.js'; diff --git a/ui/hunter/sim.ts b/ui/hunter/sim.ts index c440b5ca6e..52744bbdf5 100644 --- a/ui/hunter/sim.ts +++ b/ui/hunter/sim.ts @@ -4,8 +4,7 @@ import * as OtherInputs from '../core/components/other_inputs.js'; import { Phase } from '../core/constants/other.js'; import { IndividualSimUI, registerSpecConfig } from '../core/individual_sim_ui.js'; import { Player } from '../core/player.js'; -import { ItemSlot, PartyBuffs, PseudoStat, Spec, Stat } from '../core/proto/common.js'; -import { HunterRune } from '../core/proto/hunter.js'; +import { PartyBuffs, PseudoStat, Spec, Stat } from '../core/proto/common.js'; import { Stats } from '../core/proto_utils/stats.js'; import * as HunterInputs from './inputs.js'; import * as Presets from './presets.js'; diff --git a/ui/protection_paladin/inputs.ts b/ui/protection_paladin/inputs.ts index 5857b740de..4c9c2a60e7 100644 --- a/ui/protection_paladin/inputs.ts +++ b/ui/protection_paladin/inputs.ts @@ -1,7 +1,7 @@ import * as InputHelpers from '../core/components/input_helpers.js'; import { Player } from '../core/player.js'; -import { ItemSlot, Spec } from '../core/proto/common.js'; -import { Blessings,PaladinAura, PaladinRune, PaladinSeal } from '../core/proto/paladin.js'; +import { Spec } from '../core/proto/common.js'; +import { Blessings,PaladinAura, PaladinSeal } from '../core/proto/paladin.js'; import { ActionId } from '../core/proto_utils/action_id.js'; import { TypedEvent } from '../core/typed_event.js'; // Configuration for spec-specific UI elements on the settings tab. From 19d68550a8b7a71987e4a4ab77494a28afe11736 Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 16:39:18 -0500 Subject: [PATCH 82/83] fix flame shock, update results --- sim/druid/balance/TestP1Balance.results | 64 +++---- sim/druid/feral/TestP1Feral.results | 160 +++++++++--------- sim/paladin/protection/TestProtection.results | 84 ++++----- sim/paladin/retribution/TestExodin.results | 74 ++++---- .../retribution/TestRetribution.results | 120 +++++++------ sim/shaman/elemental/TestElemental.results | 68 ++++---- .../enhancement/TestEnhancement.results | 106 ++++++------ sim/shaman/flame_shock.go | 5 + sim/shaman/warden/TestWardenShaman.results | 62 +++---- 9 files changed, 373 insertions(+), 370 deletions(-) diff --git a/sim/druid/balance/TestP1Balance.results b/sim/druid/balance/TestP1Balance.results index 87cfb275d3..79b5706545 100644 --- a/sim/druid/balance/TestP1Balance.results +++ b/sim/druid/balance/TestP1Balance.results @@ -53,9 +53,9 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.03725 + weights: 0.02507 weights: 0 - weights: 0.49343 + weights: 0.44857 weights: 0 weights: 0 weights: 0 @@ -63,8 +63,8 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 3.21342 - weights: 2.52661 + weights: 2.16443 + weights: 1.70064 weights: 0 weights: 0 weights: 0 @@ -99,98 +99,98 @@ stat_weights_results: { dps_results: { key: "TestP1Balance-Phase1-Average-Default" value: { - dps: 230.66052 - tps: 244.13791 + dps: 155.39007 + tps: 168.86746 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 229.15741 - tps: 477.4633 + dps: 154.27378 + tps: 402.57966 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 229.15741 - tps: 241.57271 + dps: 154.27378 + tps: 166.68907 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 220.53617 - tps: 229.13647 + dps: 148.49645 + tps: 157.09674 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 154.66373 - tps: 304.76804 + dps: 104.1222 + tps: 254.22651 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 154.66373 - tps: 162.16895 + dps: 104.1222 + tps: 111.62742 } } dps_results: { key: "TestP1Balance-Phase1-Settings-NightElf-p0.bis-Default-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 159.29075 - tps: 174.4745 + dps: 107.26652 + tps: 122.45028 } } dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 227.58749 - tps: 494.61763 + dps: 153.21715 + tps: 420.2473 } } dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 227.58749 - tps: 240.939 + dps: 153.21715 + tps: 166.56866 } } dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 218.9393 - tps: 227.55849 + dps: 147.42161 + tps: 156.0408 } } dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 153.90514 - tps: 296.06075 + dps: 103.61244 + tps: 245.76805 } } dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 153.90514 - tps: 161.01292 + dps: 103.61244 + tps: 110.72022 } } dps_results: { key: "TestP1Balance-Phase1-Settings-Tauren-p0.bis-Default-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 158.80529 - tps: 173.98904 + dps: 106.93939 + tps: 122.12315 } } dps_results: { key: "TestP1Balance-Phase1-SwitchInFrontOfTarget-Default" value: { - dps: 228.48531 - tps: 241.90251 + dps: 153.88456 + tps: 167.30175 } } diff --git a/sim/druid/feral/TestP1Feral.results b/sim/druid/feral/TestP1Feral.results index 46b133dbcb..dbe8e2ba1e 100644 --- a/sim/druid/feral/TestP1Feral.results +++ b/sim/druid/feral/TestP1Feral.results @@ -50,8 +50,8 @@ character_stats_results: { stat_weights_results: { key: "TestP1Feral-Phase1-StatWeights-Default" value: { - weights: 0.48377 - weights: 0.42392 + weights: 0.43169 + weights: 0.38724 weights: 0 weights: 0 weights: 0 @@ -67,9 +67,9 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.17528 + weights: 0.15641 weights: 0 - weights: 4.87826 + weights: 4.45359 weights: 0 weights: 0 weights: 0 @@ -99,266 +99,266 @@ stat_weights_results: { dps_results: { key: "TestP1Feral-Phase1-Average-Default" value: { - dps: 527.06843 - tps: 374.21859 + dps: 477.00991 + tps: 338.67703 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-NoBleed-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 242.04604 - tps: 171.85269 + dps: 197.99744 + tps: 140.57818 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-NoBleed-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 227.1874 - tps: 161.30305 + dps: 184.48959 + tps: 130.98761 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-NoBleed-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 257.3834 - tps: 182.74222 + dps: 208.98448 + tps: 148.37898 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-NoBleed-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 114.77616 - tps: 81.49107 + dps: 97.3878 + tps: 69.14534 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-NoBleed-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 103.70397 - tps: 73.62982 + dps: 87.32218 + tps: 61.99874 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-NoBleed-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 117.10622 - tps: 83.14542 + dps: 98.58337 + tps: 69.99419 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 242.04604 - tps: 171.85269 + dps: 197.99744 + tps: 140.57818 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 227.1874 - tps: 161.30305 + dps: 184.48959 + tps: 130.98761 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 257.3834 - tps: 182.74222 + dps: 208.98448 + tps: 148.37898 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 114.77616 - tps: 81.49107 + dps: 97.3878 + tps: 69.14534 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 103.70397 - tps: 73.62982 + dps: 87.32218 + tps: 61.99874 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Default-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 117.10622 - tps: 83.14542 + dps: 98.58337 + tps: 69.99419 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Flower-Aoe-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 242.04604 - tps: 171.85269 + dps: 197.99744 + tps: 140.57818 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Flower-Aoe-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 227.1874 - tps: 161.30305 + dps: 184.48959 + tps: 130.98761 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Flower-Aoe-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 257.3834 - tps: 182.74222 + dps: 208.98448 + tps: 148.37898 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Flower-Aoe-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 114.77616 - tps: 81.49107 + dps: 97.3878 + tps: 69.14534 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Flower-Aoe-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 103.70397 - tps: 73.62982 + dps: 87.32218 + tps: 61.99874 } } dps_results: { key: "TestP1Feral-Phase1-Settings-NightElf-p0.bis-Flower-Aoe-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 117.10622 - tps: 83.14542 + dps: 98.58337 + tps: 69.99419 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-NoBleed-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 250.90736 - tps: 178.14422 + dps: 204.99849 + tps: 145.54893 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-NoBleed-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 236.09863 - tps: 167.63003 + dps: 191.53601 + tps: 135.99057 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-NoBleed-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 265.92677 - tps: 188.80801 + dps: 215.70963 + tps: 153.15384 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-NoBleed-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 114.58324 - tps: 81.3541 + dps: 97.18705 + tps: 69.0028 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-NoBleed-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 103.51792 - tps: 73.49773 + dps: 87.12767 + tps: 61.86065 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-NoBleed-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 116.80157 - tps: 82.92912 + dps: 98.28617 + tps: 69.78318 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 250.90736 - tps: 178.14422 + dps: 204.99849 + tps: 145.54893 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 236.09863 - tps: 167.63003 + dps: 191.53601 + tps: 135.99057 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 265.92677 - tps: 188.80801 + dps: 215.70963 + tps: 153.15384 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 114.58324 - tps: 81.3541 + dps: 97.18705 + tps: 69.0028 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 103.51792 - tps: 73.49773 + dps: 87.12767 + tps: 61.86065 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Default-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 116.80157 - tps: 82.92912 + dps: 98.28617 + tps: 69.78318 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Flower-Aoe-p1-FullBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 250.90736 - tps: 178.14422 + dps: 204.99849 + tps: 145.54893 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Flower-Aoe-p1-FullBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 236.09863 - tps: 167.63003 + dps: 191.53601 + tps: 135.99057 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Flower-Aoe-p1-FullBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 265.92677 - tps: 188.80801 + dps: 215.70963 + tps: 153.15384 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Flower-Aoe-p1-NoBuffs-P1-Consumes-LongMultiTarget" value: { - dps: 114.58324 - tps: 81.3541 + dps: 97.18705 + tps: 69.0028 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Flower-Aoe-p1-NoBuffs-P1-Consumes-LongSingleTarget" value: { - dps: 103.51792 - tps: 73.49773 + dps: 87.12767 + tps: 61.86065 } } dps_results: { key: "TestP1Feral-Phase1-Settings-Tauren-p0.bis-Flower-Aoe-p1-NoBuffs-P1-Consumes-ShortSingleTarget" value: { - dps: 116.80157 - tps: 82.92912 + dps: 98.28617 + tps: 69.78318 } } dps_results: { key: "TestP1Feral-Phase1-SwitchInFrontOfTarget-Default" value: { - dps: 223.74157 - tps: 158.85651 + dps: 223.47228 + tps: 158.66532 } } diff --git a/sim/paladin/protection/TestProtection.results b/sim/paladin/protection/TestProtection.results index fa4a0d3585..bca57536a9 100644 --- a/sim/paladin/protection/TestProtection.results +++ b/sim/paladin/protection/TestProtection.results @@ -50,35 +50,35 @@ character_stats_results: { stat_weights_results: { key: "TestProtection-Phase4-StatWeights-Default" value: { - weights: 0.42023 - weights: 0.15804 + weights: 0.26263 + weights: 0.15213 weights: 0 + weights: 0.00234 weights: 0 + weights: 0.4582 weights: 0 - weights: 0.10858 weights: 0 weights: 0 + weights: 0.39499 weights: 0 - weights: 0.04691 weights: 0 weights: 0 + weights: 1.78656 + weights: 0.29342 weights: 0 - weights: 1.30564 - weights: 0.07602 weights: 0 + weights: 0.10381 + weights: 2.83515 + weights: 2.44934 + weights: 2.77437 weights: 0 - weights: 0.1661 - weights: 3.4836 - weights: 2.4659 - weights: 2.57742 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 0 - weights: 0.21716 + weights: 0.9164 weights: 0 weights: 0 weights: 0 @@ -99,105 +99,105 @@ stat_weights_results: { dps_results: { key: "TestProtection-Phase4-AllItems-SanctifiedOrb-20512" value: { - dps: 344.94859 - tps: 524.34319 + dps: 392.57184 + tps: 728.03967 } } dps_results: { key: "TestProtection-Phase4-Average-Default" value: { - dps: 345.07417 - tps: 523.77093 + dps: 393.06202 + tps: 727.61732 } } dps_results: { key: "TestProtection-Phase4-Settings-Dwarf-blank-P4 Prot-p4prot-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 53.24158 - tps: 112.73528 + dps: 48.22492 + tps: 140.42146 } } dps_results: { key: "TestProtection-Phase4-Settings-Dwarf-blank-P4 Prot-p4prot-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 33.33373 - tps: 63.67317 + dps: 48.22492 + tps: 116.97388 } } dps_results: { key: "TestProtection-Phase4-Settings-Dwarf-blank-P4 Prot-p4prot-FullBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 108.99482 - tps: 207.90896 + dps: 115.71551 + tps: 279.61014 } } dps_results: { key: "TestProtection-Phase4-Settings-Dwarf-blank-P4 Prot-p4prot-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 21.03145 - tps: 28.98919 + dps: 16.41623 + tps: 39.39894 } } dps_results: { key: "TestProtection-Phase4-Settings-Dwarf-blank-P4 Prot-p4prot-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 9.43678 - tps: 17.39048 + dps: 16.41623 + tps: 39.39894 } } dps_results: { key: "TestProtection-Phase4-Settings-Dwarf-blank-P4 Prot-p4prot-NoBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 36.07527 - tps: 67.49975 + dps: 46.82306 + tps: 112.37534 } } dps_results: { key: "TestProtection-Phase4-Settings-Human-blank-P4 Prot-p4prot-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 53.55332 - tps: 112.5097 + dps: 48.56657 + tps: 141.33978 } } dps_results: { key: "TestProtection-Phase4-Settings-Human-blank-P4 Prot-p4prot-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 33.74149 - tps: 64.52068 + dps: 48.56657 + tps: 117.79878 } } dps_results: { key: "TestProtection-Phase4-Settings-Human-blank-P4 Prot-p4prot-FullBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 108.94013 - tps: 207.80504 + dps: 115.71551 + tps: 279.61014 } } dps_results: { key: "TestProtection-Phase4-Settings-Human-blank-P4 Prot-p4prot-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 21.1268 - tps: 29.07247 + dps: 17.16121 + tps: 41.18689 } } dps_results: { key: "TestProtection-Phase4-Settings-Human-blank-P4 Prot-p4prot-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 9.43007 - tps: 17.37174 + dps: 17.16121 + tps: 41.18689 } } dps_results: { key: "TestProtection-Phase4-Settings-Human-blank-P4 Prot-p4prot-NoBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 36.72963 - tps: 68.71305 + dps: 46.82306 + tps: 112.37534 } } dps_results: { key: "TestProtection-Phase4-SwitchInFrontOfTarget-Default" value: { - dps: 296.73302 - tps: 452.95035 + dps: 351.71045 + tps: 658.41289 } } diff --git a/sim/paladin/retribution/TestExodin.results b/sim/paladin/retribution/TestExodin.results index 70fd5a8c4e..382fb8bc39 100644 --- a/sim/paladin/retribution/TestExodin.results +++ b/sim/paladin/retribution/TestExodin.results @@ -50,12 +50,12 @@ character_stats_results: { stat_weights_results: { key: "TestExodin-Phase5-StatWeights-Default" value: { - weights: 0.45025 - weights: 0.17396 + weights: 0.33175 + weights: 0.18012 weights: 0 weights: 0 weights: 0 - weights: 0.27825 + weights: 0.53169 weights: 0 weights: 0 weights: 0 @@ -63,13 +63,13 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.21085 - weights: 0.09328 + weights: 2.40738 + weights: 0.34737 weights: 0 weights: 0 - weights: 0.16179 - weights: 4.15772 - weights: 3.18201 + weights: 0.11921 + weights: 3.88017 + weights: 2.8226 weights: 0 weights: 0 weights: 0 @@ -99,103 +99,105 @@ stat_weights_results: { dps_results: { key: "TestExodin-Phase5-AllItems-SanctifiedOrb-20512" value: { - dps: 345.69646 - tps: 382.69107 + dps: 480.97798 + tps: 522.8839 } } dps_results: { key: "TestExodin-Phase5-Average-Default" value: { - dps: 343.4384 - tps: 380.47158 + dps: 481.66427 + tps: 523.64138 } } dps_results: { key: "TestExodin-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 23.55242 - tps: 218.06591 + dps: 348.99957 + tps: 557.67306 } } dps_results: { key: "TestExodin-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 9.78378 - tps: 19.50945 + dps: 78.69145 + tps: 89.16446 } } dps_results: { key: "TestExodin-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - tps: 15.18376 + dps: 173.94294 + tps: 191.24086 } } dps_results: { key: "TestExodin-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 14.04078 - tps: 134.89475 + dps: 157.63726 + tps: 323.56962 } } dps_results: { key: "TestExodin-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 2.9307 - tps: 8.9734 + dps: 35.24239 + tps: 43.53901 } } dps_results: { key: "TestExodin-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 2.49444 - tps: 2.49444 + dps: 86.4435 + tps: 101.62726 } } dps_results: { key: "TestExodin-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 22.87194 - tps: 216.9921 + dps: 348.38697 + tps: 557.84713 } } dps_results: { key: "TestExodin-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 9.52454 - tps: 19.23055 + dps: 79.66673 + tps: 90.16924 } } dps_results: { key: "TestExodin-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - tps: 15.18376 + dps: 173.05306 + tps: 190.35099 } } dps_results: { key: "TestExodin-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 13.08502 - tps: 193.83184 + dps: 190.3591 + tps: 371.10593 } } dps_results: { key: "TestExodin-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 2.52678 - tps: 11.56412 + dps: 36.43544 + tps: 45.47278 } } dps_results: { key: "TestExodin-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-exodin-6CF2DR-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 1.12892 - tps: 16.31268 + dps: 84.08524 + tps: 99.26899 } } dps_results: { key: "TestExodin-Phase5-SwitchInFrontOfTarget-Default" value: { - dps: 281.97986 - tps: 316.71265 + dps: 432.35436 + tps: 471.87012 } } diff --git a/sim/paladin/retribution/TestRetribution.results b/sim/paladin/retribution/TestRetribution.results index 9b00a2b6bd..d3cf845c1d 100644 --- a/sim/paladin/retribution/TestRetribution.results +++ b/sim/paladin/retribution/TestRetribution.results @@ -50,12 +50,12 @@ character_stats_results: { stat_weights_results: { key: "TestRetribution-Phase5-StatWeights-Default" value: { - weights: 0.43848 - weights: 0.19149 + weights: 0.34184 + weights: 0.20269 weights: 0 weights: 0 weights: 0 - weights: 0.14789 + weights: 0.14206 weights: 0 weights: 0 weights: 0 @@ -63,13 +63,13 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.93497 - weights: 0.0948 + weights: 0.88388 + weights: 0.06526 weights: 0 weights: 0 - weights: 0.1716 - weights: 3.7574 - weights: 3.24696 + weights: 0.12283 + weights: 1.98199 + weights: 2.96061 weights: 0 weights: 0 weights: 0 @@ -99,189 +99,185 @@ stat_weights_results: { dps_results: { key: "TestRetribution-Phase5-AllItems-SanctifiedOrb-20512" value: { - dps: 353.24282 - tps: 392.05032 + dps: 274.93614 + tps: 303.29598 } } dps_results: { key: "TestRetribution-Phase5-Average-Default" value: { - dps: 351.16556 - tps: 389.76615 + dps: 275.82546 + tps: 304.07937 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 50.47683 - tps: 258.75699 + dps: 51.50917 + tps: 253.00433 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 31.22164 - tps: 41.6504 + dps: 36.27003 + tps: 46.39395 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 38.76171 - tps: 55.64172 + dps: 46.76412 + tps: 63.12788 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 19.00745 - tps: 189.40369 + dps: 22.14 + tps: 197.93187 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 7.75378 - tps: 16.2736 + dps: 15.16236 + tps: 23.95195 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 8.72718 - tps: 23.91094 + dps: 19.30788 + tps: 34.49164 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 16.44032 - tps: 202.10382 + dps: 7.49119 + tps: 189.71302 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 14.49805 - tps: 23.78122 + dps: 6.51412 + tps: 15.62521 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 16.76996 - tps: 32.2733 + tps: 15.18376 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 2.04578 - tps: 138.76393 + dps: 2.43419 + tps: 147.02991 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 1.28285 - tps: 8.11876 + dps: 2.43419 + tps: 9.66397 } } dps_results: { key: "TestRetribution-Phase5-Settings-Dwarf-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 0.48958 - tps: 15.67334 + tps: 15.18376 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 47.19264 - tps: 255.37447 + dps: 51.93984 + tps: 253.82833 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 29.43133 - tps: 39.86501 + dps: 36.97154 + tps: 47.12005 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 38.67912 - tps: 55.55913 + dps: 47.07732 + tps: 63.46566 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 20.6283 - tps: 201.37513 + dps: 22.6547 + tps: 203.40152 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 9.41273 - tps: 18.45007 + dps: 13.94671 + tps: 22.98405 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.5-3.6-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 8.48162 - tps: 23.66537 + dps: 20.11592 + tps: 35.29968 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 16.95611 - tps: 202.71793 + dps: 7.13834 + tps: 189.65517 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 15.01388 - tps: 24.30197 + dps: 6.16127 + tps: 15.28711 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 16.76098 - tps: 32.26433 + tps: 15.18376 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 3.70922 - tps: 170.88796 + dps: 5.67317 + tps: 186.42 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 2.94632 - tps: 11.30525 + dps: 4.95067 + tps: 13.98801 } } dps_results: { key: "TestRetribution-Phase5-Settings-Human-blank-P5 Seal of Martyrdom Ret-p5ret-twist-4DR-3.7-4.0-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 0.48958 - tps: 15.67334 + tps: 15.18376 } } dps_results: { key: "TestRetribution-Phase5-SwitchInFrontOfTarget-Default" value: { - dps: 293.09475 - tps: 328.25252 + dps: 244.51063 + tps: 272.59022 } } diff --git a/sim/shaman/elemental/TestElemental.results b/sim/shaman/elemental/TestElemental.results index b1af02bb04..a788f08895 100644 --- a/sim/shaman/elemental/TestElemental.results +++ b/sim/shaman/elemental/TestElemental.results @@ -53,18 +53,18 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.72152 + weights: 0.28545 weights: 0 - weights: 0.51092 + weights: 0.34779 weights: 0 - weights: 0.09364 + weights: 0.06737 weights: 0 weights: 0 - weights: 0.41728 + weights: 0.28041 weights: 0 weights: 0 - weights: 5.03844 - weights: 2.59396 + weights: 3.68699 + weights: 1.69771 weights: 0 weights: 0 weights: 0 @@ -99,98 +99,98 @@ stat_weights_results: { dps_results: { key: "TestElemental-Phase5-Average-Default" value: { - dps: 419.18307 - tps: 431.25953 + dps: 315.07058 + tps: 305.15394 } } dps_results: { key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 936.03114 - tps: 1063.90326 + dps: 438.54113 + tps: 423.67921 } } dps_results: { key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 382.81453 - tps: 391.18373 + dps: 231.03268 + tps: 213.0393 } } dps_results: { key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 455.77318 - tps: 471.70032 + dps: 411.24888 + tps: 403.27209 } } dps_results: { key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 439.78229 - tps: 670.41777 + dps: 251.27196 + tps: 266.58356 } } dps_results: { key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 193.28771 - tps: 199.2521 + dps: 117.28075 + tps: 106.78686 } } dps_results: { key: "TestElemental-Phase5-Settings-Orc-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 290.74843 - tps: 303.82981 + dps: 211.38078 + tps: 207.61972 } } dps_results: { key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 927.686 - tps: 1063.1965 + dps: 427.65433 + tps: 413.58194 } } dps_results: { key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 378.61527 - tps: 387.4519 + dps: 226.47569 + tps: 208.42126 } } dps_results: { key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-FullBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 468.33804 - tps: 485.29395 + dps: 412.45881 + tps: 405.1777 } } dps_results: { key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-LongMultiTarget" value: { - dps: 407.40739 - tps: 668.29302 + dps: 242.22557 + tps: 264.41278 } } dps_results: { key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-LongSingleTarget" value: { - dps: 194.00563 - tps: 200.3651 + dps: 109.08185 + tps: 98.65562 } } dps_results: { key: "TestElemental-Phase5-Settings-Troll-blank-Adaptive-phase_5-NoBuffs-P5-Consumes-ShortSingleTarget" value: { - dps: 285.69204 - tps: 299.14104 + dps: 204.43526 + tps: 201.00836 } } dps_results: { key: "TestElemental-Phase5-SwitchInFrontOfTarget-Default" value: { - dps: 419.46276 - tps: 431.86281 + dps: 312.30983 + tps: 302.89056 } } diff --git a/sim/shaman/enhancement/TestEnhancement.results b/sim/shaman/enhancement/TestEnhancement.results index 793461f573..e27944c85d 100644 --- a/sim/shaman/enhancement/TestEnhancement.results +++ b/sim/shaman/enhancement/TestEnhancement.results @@ -50,12 +50,12 @@ character_stats_results: { stat_weights_results: { key: "TestEnhancement-Phase5-StatWeights-Default" value: { - weights: 0.31837 - weights: 0.15608 + weights: 0.31856 + weights: 0.20584 weights: 0 weights: 0 weights: 0 - weights: 0.18705 + weights: 0.18501 weights: 0 weights: 0 weights: 0 @@ -67,9 +67,9 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.13842 + weights: 0.1385 weights: 0 - weights: 2.50371 + weights: 2.70552 weights: 0 weights: 0 weights: 0 @@ -99,182 +99,182 @@ stat_weights_results: { dps_results: { key: "TestEnhancement-Phase5-Average-Default" value: { - dps: 364.15052 - tps: 414.58303 + dps: 361.96076 + tps: 407.71357 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Auto-phase_5-FullBuffs-P4-Consumes WF/WF-LongMultiTarget" value: { - dps: 299.03749 - tps: 1030.42407 + dps: 172.63463 + tps: 384.38013 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Auto-phase_5-FullBuffs-P4-Consumes WF/WF-LongSingleTarget" value: { - dps: 185.56504 - tps: 233.65201 + dps: 118.13773 + tps: 116.35787 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Auto-phase_5-FullBuffs-P4-Consumes WF/WF-ShortSingleTarget" value: { dps: 186.17088 - tps: 236.17124 + tps: 217.73365 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Auto-phase_5-NoBuffs-P4-Consumes WF/WF-LongMultiTarget" value: { - dps: 143.74768 - tps: 611.82612 + dps: 78.08604 + tps: 236.3002 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Auto-phase_5-NoBuffs-P4-Consumes WF/WF-LongSingleTarget" value: { - dps: 85.68347 - tps: 107.37283 + dps: 43.3359 + tps: 47.2308 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Auto-phase_5-NoBuffs-P4-Consumes WF/WF-ShortSingleTarget" value: { - dps: 106.25535 - tps: 130.788 + dps: 91.87525 + tps: 106.04602 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Delay OH-phase_5-FullBuffs-P4-Consumes WF/WF-LongMultiTarget" value: { - dps: 299.03749 - tps: 1030.42407 + dps: 172.63463 + tps: 384.38013 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Delay OH-phase_5-FullBuffs-P4-Consumes WF/WF-LongSingleTarget" value: { - dps: 185.56504 - tps: 233.65201 + dps: 118.13773 + tps: 116.35787 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Delay OH-phase_5-FullBuffs-P4-Consumes WF/WF-ShortSingleTarget" value: { dps: 186.17088 - tps: 236.17124 + tps: 217.73365 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Delay OH-phase_5-NoBuffs-P4-Consumes WF/WF-LongMultiTarget" value: { - dps: 143.74768 - tps: 611.82612 + dps: 78.08604 + tps: 236.3002 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Delay OH-phase_5-NoBuffs-P4-Consumes WF/WF-LongSingleTarget" value: { - dps: 85.68347 - tps: 107.37283 + dps: 43.3359 + tps: 47.2308 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Orc-blank-Sync Delay OH-phase_5-NoBuffs-P4-Consumes WF/WF-ShortSingleTarget" value: { - dps: 106.25535 - tps: 130.788 + dps: 91.87525 + tps: 106.04602 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Auto-phase_5-FullBuffs-P4-Consumes WF/WF-LongMultiTarget" value: { - dps: 299.12165 - tps: 1034.54939 + dps: 170.20716 + tps: 382.67426 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Auto-phase_5-FullBuffs-P4-Consumes WF/WF-LongSingleTarget" value: { - dps: 187.95565 - tps: 237.36895 + dps: 116.8431 + tps: 115.54102 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Auto-phase_5-FullBuffs-P4-Consumes WF/WF-ShortSingleTarget" value: { dps: 186.08507 - tps: 233.90514 + tps: 217.06708 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Auto-phase_5-NoBuffs-P4-Consumes WF/WF-LongMultiTarget" value: { - dps: 139.89156 - tps: 599.16195 + dps: 76.32182 + tps: 237.39334 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Auto-phase_5-NoBuffs-P4-Consumes WF/WF-LongSingleTarget" value: { - dps: 84.36506 - tps: 105.44158 + dps: 42.60039 + tps: 46.19213 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Auto-phase_5-NoBuffs-P4-Consumes WF/WF-ShortSingleTarget" value: { - dps: 106.29274 - tps: 131.70691 + dps: 91.86478 + tps: 106.87668 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Delay OH-phase_5-FullBuffs-P4-Consumes WF/WF-LongMultiTarget" value: { - dps: 299.12165 - tps: 1034.54939 + dps: 170.20716 + tps: 382.67426 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Delay OH-phase_5-FullBuffs-P4-Consumes WF/WF-LongSingleTarget" value: { - dps: 187.95565 - tps: 237.36895 + dps: 116.8431 + tps: 115.54102 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Delay OH-phase_5-FullBuffs-P4-Consumes WF/WF-ShortSingleTarget" value: { dps: 186.08507 - tps: 233.90514 + tps: 217.06708 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Delay OH-phase_5-NoBuffs-P4-Consumes WF/WF-LongMultiTarget" value: { - dps: 139.89156 - tps: 599.16195 + dps: 76.32182 + tps: 237.39334 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Delay OH-phase_5-NoBuffs-P4-Consumes WF/WF-LongSingleTarget" value: { - dps: 84.36506 - tps: 105.44158 + dps: 42.60039 + tps: 46.19213 } } dps_results: { key: "TestEnhancement-Phase5-Settings-Troll-blank-Sync Delay OH-phase_5-NoBuffs-P4-Consumes WF/WF-ShortSingleTarget" value: { - dps: 106.29274 - tps: 131.70691 + dps: 91.86478 + tps: 106.87668 } } dps_results: { key: "TestEnhancement-Phase5-SwitchInFrontOfTarget-Default" value: { - dps: 326.2358 - tps: 375.75426 + dps: 323.99607 + tps: 368.7583 } } diff --git a/sim/shaman/flame_shock.go b/sim/shaman/flame_shock.go index 80cf7213b1..6bdd04e30e 100644 --- a/sim/shaman/flame_shock.go +++ b/sim/shaman/flame_shock.go @@ -1,6 +1,7 @@ package shaman import ( + "fmt" "time" "github.com/wowsims/classic/sim/core" @@ -54,6 +55,10 @@ func (shaman *Shaman) newFlameShockSpell(rank int, shockTimer *core.Timer) core. spell.BonusCoefficient = baseSpellCoeff spell.Dot = core.DotConfig{ + Aura: core.Aura{ + Label: fmt.Sprintf("Flame Shock (Rank %d)", rank), + }, + NumberOfTicks: int32(numTicks), TickLength: tickDuration, BonusCoefficient: dotSpellCoeff, diff --git a/sim/shaman/warden/TestWardenShaman.results b/sim/shaman/warden/TestWardenShaman.results index 21e9c49465..83c08de467 100644 --- a/sim/shaman/warden/TestWardenShaman.results +++ b/sim/shaman/warden/TestWardenShaman.results @@ -50,12 +50,12 @@ character_stats_results: { stat_weights_results: { key: "TestWardenShaman-Phase4-StatWeights-Default" value: { - weights: 0.17266 + weights: 0.19577 weights: 0 weights: 0 weights: 0 weights: 0 - weights: 0.28224 + weights: 0.23254 weights: 0 weights: 0 weights: 0 @@ -67,7 +67,7 @@ stat_weights_results: { weights: 0 weights: 0 weights: 0 - weights: 0.07507 + weights: 0.08512 weights: 0 weights: 0 weights: 0 @@ -99,98 +99,98 @@ stat_weights_results: { dps_results: { key: "TestWardenShaman-Phase4-Average-Default" value: { - dps: 302.42866 - tps: 370.93102 + dps: 258.70676 + tps: 271.69814 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Orc-blank-Default-phase_4_enh_tank-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 651.84008 - tps: 928.57389 + dps: 272.32192 + tps: 337.73005 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Orc-blank-Default-phase_4_enh_tank-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 196.11849 - tps: 245.5448 + dps: 110.42692 + tps: 111.28165 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Orc-blank-Default-phase_4_enh_tank-FullBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 241.52465 - tps: 301.3329 + dps: 217.51144 + tps: 245.57233 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Orc-blank-Default-phase_4_enh_tank-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 257.00445 - tps: 589.99815 + dps: 112.0172 + tps: 228.47359 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Orc-blank-Default-phase_4_enh_tank-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 88.86627 - tps: 113.66759 + dps: 40.1898 + tps: 50.57578 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Orc-blank-Default-phase_4_enh_tank-NoBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 145.50903 - tps: 186.12259 + dps: 106.34998 + tps: 122.86867 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Troll-blank-Default-phase_4_enh_tank-FullBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 643.24845 - tps: 917.52123 + dps: 258.67178 + tps: 338.12863 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Troll-blank-Default-phase_4_enh_tank-FullBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 189.83508 - tps: 241.67522 + dps: 105.16448 + tps: 105.39431 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Troll-blank-Default-phase_4_enh_tank-FullBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 253.27836 - tps: 321.41895 + dps: 205.64716 + tps: 235.46158 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Troll-blank-Default-phase_4_enh_tank-NoBuffs-P4-Consumes-LongMultiTarget" value: { - dps: 244.92043 - tps: 588.06147 + dps: 116.31938 + tps: 225.80523 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Troll-blank-Default-phase_4_enh_tank-NoBuffs-P4-Consumes-LongSingleTarget" value: { - dps: 87.22708 - tps: 109.96028 + dps: 38.46577 + tps: 49.08053 } } dps_results: { key: "TestWardenShaman-Phase4-Settings-Troll-blank-Default-phase_4_enh_tank-NoBuffs-P4-Consumes-ShortSingleTarget" value: { - dps: 136.90793 - tps: 176.99728 + dps: 97.27926 + tps: 113.86965 } } dps_results: { key: "TestWardenShaman-Phase4-SwitchInFrontOfTarget-Default" value: { - dps: 280.64126 - tps: 347.17303 + dps: 234.65639 + tps: 247.16943 } } From b2282757104a46d188aa511f94eb12dc2507b4fb Mon Sep 17 00:00:00 2001 From: Kayla Glick Date: Mon, 23 Dec 2024 16:41:56 -0500 Subject: [PATCH 83/83] remove unused overload variables --- sim/shaman/chain_heal.go | 4 ++-- sim/shaman/healing_wave.go | 4 ++-- sim/shaman/lightning_bolt.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sim/shaman/chain_heal.go b/sim/shaman/chain_heal.go index 6e79f92c60..394235fbc0 100644 --- a/sim/shaman/chain_heal.go +++ b/sim/shaman/chain_heal.go @@ -20,7 +20,7 @@ func (shaman *Shaman) registerChainHealSpell() { shaman.ChainHeal = make([]*core.Spell, ChainHealRanks+1) for rank := 1; rank <= ChainHealRanks; rank++ { - config := shaman.newChainHealSpellConfig(rank, false) + config := shaman.newChainHealSpellConfig(rank) if config.RequiredLevel <= int(shaman.Level) { shaman.ChainHeal[rank] = shaman.RegisterSpell(config) @@ -28,7 +28,7 @@ func (shaman *Shaman) registerChainHealSpell() { } } -func (shaman *Shaman) newChainHealSpellConfig(rank int, isOverload bool) core.SpellConfig { +func (shaman *Shaman) newChainHealSpellConfig(rank int) core.SpellConfig { spellId := ChainHealSpellId[rank] baseHealingMultiplier := 1 + shaman.purificationHealingModifier() baseHealingLow := ChainHealBaseHealing[rank][0] * baseHealingMultiplier diff --git a/sim/shaman/healing_wave.go b/sim/shaman/healing_wave.go index 8ff3c751c2..2a633bbb6e 100644 --- a/sim/shaman/healing_wave.go +++ b/sim/shaman/healing_wave.go @@ -19,7 +19,7 @@ func (shaman *Shaman) registerHealingWaveSpell() { shaman.HealingWave = make([]*core.Spell, HealingWaveRanks+1) for rank := 1; rank <= HealingWaveRanks; rank++ { - config := shaman.newHealingWaveSpellConfig(rank, false) + config := shaman.newHealingWaveSpellConfig(rank) if config.RequiredLevel <= int(shaman.Level) { shaman.HealingWave[rank] = shaman.RegisterSpell(config) @@ -27,7 +27,7 @@ func (shaman *Shaman) registerHealingWaveSpell() { } } -func (shaman *Shaman) newHealingWaveSpellConfig(rank int, isOverload bool) core.SpellConfig { +func (shaman *Shaman) newHealingWaveSpellConfig(rank int) core.SpellConfig { spellId := HealingWaveSpellId[rank] baseHealingMultiplier := 1 + shaman.purificationHealingModifier() baseHealingLow := HealingWaveBaseHealing[rank][0] * baseHealingMultiplier diff --git a/sim/shaman/lightning_bolt.go b/sim/shaman/lightning_bolt.go index ae12014ef8..f94708c16c 100644 --- a/sim/shaman/lightning_bolt.go +++ b/sim/shaman/lightning_bolt.go @@ -19,7 +19,7 @@ func (shaman *Shaman) registerLightningBoltSpell() { shaman.LightningBolt = make([]*core.Spell, LightningBoltRanks+1) for rank := 1; rank <= LightningBoltRanks; rank++ { - config := shaman.newLightningBoltSpellConfig(rank, false) + config := shaman.newLightningBoltSpellConfig(rank) if config.RequiredLevel <= int(shaman.Level) { shaman.LightningBolt[rank] = shaman.RegisterSpell(config) @@ -27,7 +27,7 @@ func (shaman *Shaman) registerLightningBoltSpell() { } } -func (shaman *Shaman) newLightningBoltSpellConfig(rank int, isOverload bool) core.SpellConfig { +func (shaman *Shaman) newLightningBoltSpellConfig(rank int) core.SpellConfig { spellId := LightningBoltSpellId[rank] baseDamageLow := LightningBoltBaseDamage[rank][0] baseDamageHigh := LightningBoltBaseDamage[rank][1]