From eefb111ebd243ccd896ab35861ebe5b032831d2e Mon Sep 17 00:00:00 2001 From: Matt Haynie Date: Sat, 19 Nov 2016 00:38:01 -0800 Subject: [PATCH] Camera smoothing improvements. --- .vs/CastingEssentials/v14/.suo | Bin 348672 -> 344576 bytes CastingEssentials/Hooking/TemplateFunctions.h | 13 +- CastingEssentials/Misc/DebugOverlay.cpp | 7 + CastingEssentials/Modules/CameraSmooths.cpp | 261 +++++++++++++----- CastingEssentials/Modules/CameraSmooths.h | 33 ++- CastingEssentials/PluginBase/Common.h | 37 ++- CastingEssentials/PluginBase/TFDefinitions.h | 22 +- 7 files changed, 280 insertions(+), 93 deletions(-) diff --git a/.vs/CastingEssentials/v14/.suo b/.vs/CastingEssentials/v14/.suo index a8b3c4bea5fccf19dfbc136c4e4547e0e565ac00..596cfe552763f68357669bdedf61c5a9e9e15bc3 100644 GIT binary patch delta 20300 zcmeHP4OmoF-k)>t85|ICKtM#q5hp}M8j%o9alnuK7Sa491O)Q~0TIkhWyEhqMXt`D zlvOmF%v>XAopN16vU06ewAMaea@Fl^Yu9zHtXJLA_jm4{K{6}bYIon~-FcoL=iYPg zJ@=gd`G22tvF#49Ee|NO^pJF}pHZj#6o)N=8#iy>6tyzo0sJ@c9&i|V^|_3el27^{ ztQq~2PP5NZQ#VXmD2?L2I3(*)IYK%qD_=-UJlq$8q!(UiBnO6gN{`=LIOMfH*+Zi>E{xhVpHoHSjSo6POP?26zH1fIkC+fPO#_ zkO!Oq{sOcI9z&-dNBOQ!m#NFa!J9w;&<7x3DDWp>5nuvl051VsfbGD&!1KWGfxbWu zFdXSKlkhlMi;~T+U(c5D!*g)Bff9;#l#6H2CoQjap0rZ>4E{J zuUAyR_BaRuIslXjLfEl<4aJLkJue57rg0 zL(h8xTY-6i0!CkevLnz9SP%RThzH&QHUR^HY@iHy0T>A+0(g}!7B~n@0`>tX(cW&9 zqk#v21fUvN3!KvFigka(0SBf4_W|jE5AY!H5ReOu0zi)lJO^wBG+8OWdGlqQoW=vcz|FtKaWJsMbweh~UjlCc zJAp=E4{#X>1TFzW>XQM{!6cLlkPiqlpGUb7?e0e@UidW14S={;{Ekh;$y>l+-~-o% z4^fJn>rftb)pbY7(8+};&$;S)qdWr`fh)jdKs4%$^7^KXHbM8}0a4-p>0IYEAqe@zOk%r=<;UOblXcRbd>f2D`zi@TicWOi!35VkV5?a z;Ck*P$}~Wb=J$C14DdGa4)8AUUx2v35#{^9S>U{@PSjsuwDLu^a95U8?o+5-@$pku z`Xuonw5S?K)HLu;I8*A{Md^jII1Z&C__lMON&5i{;$)L@(TZpGF;OxfKxL^*8jRa+GG zjNWOQ!Ok(o78^!pUxpsX*2{`*pjp{HxT7+_rw0{IW+(Mb_$`9Vsc;G#$Lrh;w;Y7` zhR|LHyz@luwV_=k#nhE6=D`ipbxHYR@M+#2)Kl+ixfK%smf9^Hu|2#? zZTP77^xELF(ZL~lrgo!nXsPIEt$BPSv->i$)4YH+vYN>zL#^pkGc!P#bb`HHGxS+0 z)oo`swq03TJ(tQ#xRFN9!q9EuUQT+wwI3l zh7GD6Tyn7GfpoTjv1)oWgRRVt71KoL{@+9M^}5vk;eKM@031cS}ZDP9P4{w zXHh$az2>hpObYbu5gTnu9X}wonpiEnNhK-FuhwttC0TS_G1;EbGofGvpVVHlc{9rN z;we=50r#m*pSY6wpPO-_-^+8K7!&JvByq@y&(7ms9o6+?)>`9L3sb8618Z$h*!&!o zOrn%u%l z9R-dNCRO})oscM@n)#7mpg!7b-6`*^=!Dhp%=?=dB%RkwCg+l5eFPH3S`S$ z*mtuMN{*6^H1JQ{L^YwztOS1Ir#P+!Ii6&U=5CNesVsv>QAj@eIo-szwkV&)4H8B! z15R&$ww&p+aX5#z1h9_&g6?@Z%?HG>038cp@zAb{BQjVJ-8nFlHA2HJXAz7Cql+%O zu3)92gI1?ChSf2<4YLxK5@tXPH$&ZbJyDp+^nVpvgsu%^-IU$aQYk4?4sr&?v5!0z z+Xv;8n+^HToX6rR%~Nl3UJqp+(Eef0us5KuRF@zSp6VO5*Lpp}q*i*x(R(tLkLQ`r z%)xAX3$-;mJVp+#jX8IMk*z25a(Y#>FW7+;7A85v9PBLfd3V@WzjJH4Y|ZPx;B>2< zsz#wd^kD&z7!RgcuU&A4O=K`O-=+v#HB*GT{ghbCb~vk2Svn)@1ZH#EBB0I6FL2^V zr>dS3sQM1G+Zt;+<`sp5c4ho zfd$#ckB+^@qP$l$uTj||dA=M$`vSO+vU!QWztErNxYq+ePM>NT|Kyr8PX}BGS4Fq1 zl39%Jgub8V?c+5+K4<1%e10=>va2PjY#a%q6W zc6HL?v@`XSBc5LKAiwQg)0f`qzw`Y#afRQsL{r$!7Eng~V*a2(6nky7*S&U>hoy08XIC za~aE+ql|gfBvmlX!{Y-Uc2qEK-^&IXL=eylP&t@=NJV=gip9>)_p)xR))aY;(dkIZ z`jpjQX5|gg=O^n_ZS}qU6L0Kco9_J6<4>BC!`|Qa`jCy6)v;Gz%Thzbe?b21^=yEr zI;jSCfAt??q@l{S72TY>>sczRnYFoDTu?c?FBj6QG|o0_8ZtD*nXr$+b7~90+!)4( zgUqTtWkJ{vDc1tKD!ck1ARXbZAAfz7_X)_JFD^!avWpQ0fXKK zQEMkhM9e@KdM9IiI}0fd!-LvsW^ZQhw49=>?9}<$(+cy1yRX}$K;hBkNZHT1_jxv6 zm16G>|HQ~f2+og)Y#d2UavX$oeCv#q2M_RM?J(3PW&bVirAfH9R4`jkp{=WVs58Hg zm9g@|R7%~$4B7+5*04q3OXk?|#AQBZK2v&L8S$F|;bb0{~rW@(9zcaduon~OB zfrfD0Blusv?{;3In28)JWfxRRD;fOI88-@|#E7u)sZBP2b5GR90&#%2(hFrg&>QFj zsFvemEE~bbif7sw$D>l*D1MLNm{RX!sY42y)ru?ga9#+^ch!q#9(5hJL?^}pC4g`g zmbvQ1b3(qH{`=WQ23-R8V27vf9$fALr~|CMGQwNs{9UIzd9nvkeM^r1%n_ri{2%sa zm~u42qW6S_sn;Z;b0<9;irZC52}Au+?amFTALg#_g8ByK+C9gGV^Mo0Tv+&XY!Bmt zZW@8bKy-BNWA?gX2p$s=m^MRKPD95TmZDDF;xv57uCfEi*vrgQXTnWQVR6erI1`=5 zk9wr?E)*Ulzh^IC1}g0@52O4b9%}UI_vcIUn&kxzTVMVk`H>kD1X(-_kqgZiQb`%b zETDA`6!kb{fJ9}gZncs)y}wWiO@tAQq4oJEB8>CeNY+In(?_hcClix3%>4#u;YVOk z$3-T6r&0(>#OFMS_zRB)v8!; z%4l0W821WsbKfgOOc*MW&T`j@Qlz%VpkCy%#<}jV!0{y4vHRXBuJg2J^;2=2;X2Pm zISt6x&I4~g?7A?^Rf>l4R1J1dKC0#dMa?dW%gx932MogCPLPqWw`6zP4bm*;xWT*~ z=@LI+lpb$Mk9U-2I9Z7Fbbs2LEsb}0OCASOB^zV!($a^dd#O5AGE&_`lJ$U}^tdP0 z1xOD&LL|wNB}vq&qqN+)JXBi54&+FCn6Yu*jhMum(WV7o{Pm^7+xl)&J&mff{)#Ec zM9Y6CFL5qeD3vgWN%EqU-tq=|(mY?hSOuQ7`1Jd*LV+H9dju$XO@hEDlHUSjZWOCwl2Dz##k`EUwVa zD(T(_df}E{Xrvb^C3 z(+X$i<z{Zssop+-j)os ztV-@md;7|z2l`6T5EoX%}{9TPJkCNU;vv0gWj&hL}ncHT^pACt^Ro#w3Fx=W9djM$*R7?pkDu4mG)Zab7SQi=4*j`x_=MjfKh@ZKXuzETeTjL zF(A4pXG^j^Mk4Sx;riF45V{w!|MjG!NHBhQ$EiS(_ z2Ca5>zJE;W3_ZJC-cH-!kc>ulegEh8y}#^z?cFo2VshF#1`Ao*EtNLCzbBV<1K$_( zq7Gf7DE(r!JjpRc;$%66PCUC>eu!qSk%=sSlx`{(sTEb-FC8FbqI8;!!zHt`ex#J( zLFF}adwoy5(8sxWv%H*9xmYy(0 z%4U($@S}IGbARO``O~5$Y`KyY6hf&Uau(Tq<)uz`NqS1Y8&!8jGD^)f9GQ=?5CkpL z$mS>8D5;;6NtwmW->V2Q>NGe(sXDUNuuw|dj3B$NjcldUeh|k%D~mKvJn4l2z^!$M zy~$Qq&Azex@()Ho9lkC45ewV9Y3Uq3lq_?2UrJ~X3Z;yY(+Dwp990C%CMt-OOXzY( zIZ!_c3r9noH`hsV2$SwwktfJPTl?lAR-diLYuaM3oqSix#kAifhp>b6$zr~qk|SlW zZ_afBo$DYUW6x9TF0w)gJILWQ(3g)OV+RnAhsbr5**>D`+mDX!y=K9 z@ackV$X41kj^|KNdE#dyqwOx z!#NG>1zVP~fLBmi9HwC0QofZM@52C3KQ7(Lgb_?w9XcFKFU6u8##P|BeX(*NJErw_ z$u8MTx%5#m!i_UJ+8zxmeb8M#L?uz^MS2kTYmtZb(s{Z(np+}Iqm`+0DA{&Fx&C__ zMY`A<=I4WWo<R=9{3rI~i_a71XJlyvFzI2_vjs z(~%H)v=VAJVyYKosvGE&2Kh-!yI;0Y{hQis8EI=DkR~=uUPPv$a5eS^aBq>uq7wzO zhcus&WwyMT7EY9d=u&^#+jA{My$?h^nKqFWaA({7)or%>P6im7*-FOs@_Z^=C3A{L z+mzJ{g4uAH52olpB4uuhl?_y#fUCQQqqmj;augj6kw;KP5{RJ6NSru&J^{>8w^Q;0 zzvR-GD}06EfDk40H$E7-86)4Lv2B?ZqcEp|xMd|WOyM%wtA$9gV0oQ-WXbC(?HVXh zJs1*Os!Fd?_qsPYEL=xrdGZpn-r&K?nMs14V#WEm#){PgA=RCJD^2?@_vCiZAyV}~ z=-@!Oeb2{%_*H30D^!(mgL3wF-WZ5kojuAOiUF#UCNz{iR}S(J{e@MqJs|&?3dYOj zv|yN=Lk+kQ;)xmFM5V(qPL)0%48!9*7-X#;A&(by+)v}KfO|kpGX+fm(LbHeZIm|N zEzsgMBIj#DV_>UwX%^!ur^~Z2@OLK3-Y%Mx_1DZB6c*8tLnxt5wEZC{kIXOm zBC5`kXm5AhU}G!{6c@yOvcIbM4UPs3Zn z3gjv!eXC$35h)%N1A0ubR}d}CmZPA2PmPtv`X=WTJ^WMni-C-)+VKSHI|pqaqE2i1 zMl#N3V$EqhCH99x2MYyJ<7`YqgW6&HY&pg?dAaCs;cT#sivi87ih5k-tH^Lv4nhmv zXiOf@5E2zbWnRn=%m7EgXB8y&a6XI(duoRQ4AftGsa|2!s{EXP6*tCv;LLhM6IZzJccMmijhhg9qA)&B5NT8c^(8&?RaAm zI(~?DM$5nQ)D~%Vx@&amD%^!7f9F0Ohr;U<3jtzTAPY`bhPsh3+vR8!XLAtRMTnb0Uv)Z-EPMO9ncx!#MSACWzT9IL+2ICfO)uUj)lP)v!u zk2yr2pVDtZ_f@9cM3WbTi4JOPy>Ah$l{$=1eK`WJRkEG@MnR}At%P1v^-jZhEba9X zr^1FSbr%GER-w7wV$92w^aO9ZD0=DcZ^a2 zFXXPLW&^6nLb2pTq4FtIZWqJrP3JoDSx_Kzzu-&htX+=5Dl=GwD8UXj01rYXMg-+= zgm?JqI%vj*4RSCZ02P)}=mxh`%y=9G&)kdawwBBX#GOJN+j64x3iw@WGgYg2G}UFn zG=whZ9<-0#oH}DW9)%~Qx+x)aqZ1b{CG`y2{s* zX$lV^I6?l<6&S!2=g9`C2cwsslTVT~3!Oi)5KDiDcEFUm9MQTM7Kn~cr{ebdrwQ-z zpvqGibj<`bXKl~D=xhU27>to>9tTrG0~q>?UGi?QXT~M)QGziBmp>N< z<`fxs)sU{E!JLP(@}~F!{#ZZ6`&kghJeL599^0F4h@n}5SUiR++(&Itu@y(7MUixK z`PTd5&|>okKI+d+U_#Yy4{6WM6q5lvr<#KDU~V?-bNO4uGUea*yW6lbb!1*vQBL+e zh3L%gf7|N9;NI5|th2o2jvs8R=>}Frl#>!XnjfA?fYiv?~5xA*78K1;J8< zwdIFs_k0-Fw+4aNR0d5Lq^W^EigXpS@l(Z#|I)CKE?$97&F=&!{AY>jObd9ps<%2( z%Pz9>M?`GUa3ksHAh@>hsXba{ATEE{#ix0~!7UbEW)LL|gvx;{_9~1$9Gz~IG7_=+ z&llu{P<<@8MCkuJ#&D33GY})yz64PHWLTtOo!DSH8xO^)D%tD35Dp*!hGr5wFtB!S z!b5owE7f&cNBKi|tngA?;R6(-H&uqh*k4XY@Cj{er-D*BmyTTrr=}(2s`Xw?;WrBz z#WsK-`m#5!{u@VNn#f^-{|P};GVcQ2wDc=@h^eEY*kIeAr_7PO0GTCtx<6Yy74@H( z=!eBbWcx~fUQ@we3uEH>8qHPsiNh1*j2MNF|z8|_{D{c+T176ki0 z4*E~!pr0Pet@KvD@D`zymE(IwFnBMWe}ETj?#qS|Jc?Bkn7 z$FPMLN5HdBPmv64J)O!&FI4kuoB?Zmc|7;h;-WEBV&S z95esW>rNK_1D^Uda+siXgP`WGl5Lte`aTkt_Ry9mP>1>s&$&AEV`lEGQIrLfJ@OS#T0>W$`CYLu`9g zq>64$Z7^-f){n00NHL5-b9a9r5$N*Vf3I3-wa;MG4t+(=0 z$UTRNu9TB)E8>K{IK|5{w#mPsQA6Y)EQxpMCU2zUGf;nP88M7PQ+Wi9XphtqSY4;4 zkW@VnQl~PJ;Oc|w10uLu(ew?57o``d8JNE`Q>AC~kPfI2!&^s5dE8H4`K8X|~=o3h}%ea9ZXlhMePYD-c;jNwU{zy+h zip7&CdAXW3RNkRr5OI@GPI($T^=*%j00yUWf6z)zjvrhBhH@{Mg_CIomPA#N&0G$V z-Kq)67t1hR$QW+bE;X)0e;{(VmYPD;7=IFVSj&HTE8(Jq9ukvy4;}d&qOPv_O`OGi zC~FOtO0i4TEE;*WY4Ia?i(Os0?FzEGY^H5J&jr(}W?y8Cm7wJzWL=M$S93F_Z9J7` z`~n?yE#KUz)S~~@VxK{X2!;a{>x&-f#3!1JEZT;ytHFBRd{tEqr_ojX7fm)Jntb-4 z^}bcOOS(dhyq1o)RX@C% zNbsBb5$G~FF&q0bXNqND{>s=5Gu1Jp)x&$=eu4rUYGxfZ#fQWt7TZpME*mpwqnW6 zNV6`0O!Y!HZ=ui+c?>e?8Qpj-E&6X&$GQaptos4Theh;AlD6^%bYc~n`TwGw{i%Eo zk~I}`B%w>ij#AeKigP0n!bN-x3-RfncqJ>L9(h;@to{>E(sYrkuJHYiYX?Q;hhR*R z-|jF6b6lh=#9YtBoKMG@w(cu7PoL1#ub{9J@q9SmD0XvJihUECXwhGxg|H}CLaLs7 z<06E|?F||zpzz3|D@##qU6hPGqsIf!j;_oH#i{am!QN{mmj;&xN@OZtgef%VtyhE zr-l+@Nm*4q|DcMu(eicZFm_9;J6}eT^$HxgTT6E_bmlWyQ1~l$VYY)Q{|mm4j(*Pf zA+k|-z+oE?r~RM9QQ9t6d)ss^QdinFui;-}KU_OPpmw8wa=k4+Tn_*CnO1iJVcjcO zc(Xr-m}I%icWW+j@Kso2*v_>y>;WbgTCFfQRa)W)&e{<5L-kf}?@N5RgiuVZJNqQ6 zv9CWRUWcco?%%3j!27BnVJZ2OIa#m64}1Rad_P^e&JPP`xkl`fJK7W@hLGP)IF(1g zf-CL+6=I0(O)-Rp3=E&XTP#u`y>JyQqI&lK%)UnWmS9J)_#$N)%H_a~O>?{5#fO+= zEkFp2aLik&8tzR#Ux5lgXxNdebF`&Ek55%7qq{Vds;@%ezea%>R6T*0y6!pBUT)JA z&<6c$=IU0bDTe8>HLdxk=d4>FnSSF-TiV%^g-~*y?5{3P$1;7On$L71YQo1DW<6gh zzKr#9*4^ZVtcB|XO6oLOnl1LT1Ue6W#TUp1@nvoXTqd%*$e7_gb+TP^&gLl{=OwIaxuPIoyww&*Q%3KrR&8DUrl>u;ee5`5#nPR zDx1pk?T4{rFlakIX|Ke;jaXy8le0PXu}Lv6RIG34^i1g6D|^2oYu}Cgu4nhsy)E?K z_BNoy?iNylTrd+~uqO0Z2Yw1|(np^9iC-H%2m~r&(3H8ICDM`B`u_jN2J5TG{?#1} ZK};kzQb(k*iQkyN$5d)ig1^4xe*yU#stEu9 delta 20956 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::type)))... }; - // 8192 is the length used internally by CCvar - char buffer[8192]; - vsnprintf_s(buffer, _TRUNCATE, *fmt, vaArgList); + std::string formatted = vstrprintf(*fmt, vaArgList); va_end(vaArgList); + // Escape any '%' with a second % + for (size_t i = 0; i < formatted.size(); i++) + { + if (formatted[i] == '%') + formatted.insert(i++, 1, '%'); + } + // Can't have variable arguments in std::function, overwrite the "format" parameter with // the fully parsed buffer - *parameters[fmtParameter] = &buffer[0]; + *parameters[fmtParameter] = (char*)formatted.c_str(); // Now run all the hooks return HookFunctionsInvoker::Invoke(s_Hook, args...); diff --git a/CastingEssentials/Misc/DebugOverlay.cpp b/CastingEssentials/Misc/DebugOverlay.cpp index 7a1b18d..ddfa9a5 100644 --- a/CastingEssentials/Misc/DebugOverlay.cpp +++ b/CastingEssentials/Misc/DebugOverlay.cpp @@ -44,4 +44,11 @@ void NDebugOverlay::Cross3DOriented(const Vector& position, const QAngle& angles Line(position + right, position - right, r, g, b, noDepthTest, flDuration); Line(position + forward, position - forward, r, g, b, noDepthTest, flDuration); Line(position + up, position - up, r, g, b, noDepthTest, flDuration); +} + +void NDebugOverlay::EntityText(int entityID, int text_offset, const char *text, float duration, int r, int g, int b, int a) +{ + debugoverlay->AddEntityTextOverlay(entityID, text_offset, duration, + (int)clamp(r * 255.f, 0.f, 255.f), (int)clamp(g * 255.f, 0.f, 255.f), (int)clamp(b * 255.f, 0.f, 255.f), + (int)clamp(a * 255.f, 0.f, 255.f), text); } \ No newline at end of file diff --git a/CastingEssentials/Modules/CameraSmooths.cpp b/CastingEssentials/Modules/CameraSmooths.cpp index 58e99db..9f59b1f 100644 --- a/CastingEssentials/Modules/CameraSmooths.cpp +++ b/CastingEssentials/Modules/CameraSmooths.cpp @@ -1,6 +1,9 @@ #include "CameraSmooths.h" #include "PluginBase/HookManager.h" #include "PluginBase/Interfaces.h" +#include "PluginBase/Player.h" +#include "PluginBase/TFDefinitions.h" +#include "Misc/DebugOverlay.h" #include #include @@ -8,6 +11,9 @@ #include #include #include +#include +#include +#include #undef max #include @@ -36,35 +42,44 @@ class CameraSmooths::HLTVCameraOverride : public C_HLTVCamera using C_HLTVCamera::m_vecVelocity; }; -static const std::vector>& GetTestPoints() +static const Vector TEST_POINTS[27] = { - constexpr int resolution = 6; - constexpr float mins = -1; - constexpr float maxs = 1; - - static thread_local std::vector> s_Vectors; - static thread_local bool s_VectorInitialized = false; - - if (!s_VectorInitialized) - { - for (int x = 0; x < resolution; x++) - { - const float xpos = RemapVal(x, 0, resolution - 1, mins, maxs); - for (int y = 0; y < resolution; y++) - { - const float ypos = RemapVal(y, 0, resolution - 1, mins, maxs); - for (int z = 0; z < resolution; z++) - { - const float zpos = RemapVal(y, 0, resolution - 1, mins, maxs); - - s_Vectors.push_back(std::make_shared(xpos, ypos, zpos)); - } - } - } - } - - return s_Vectors; -} + Vector(0, 0, 0), + Vector(0, 0, 0.5), + Vector(0, 0, 1), + + Vector(0, 0.5, 0), + Vector(0, 0.5, 0.5), + Vector(0, 0.5, 1), + + Vector(0, 1, 0), + Vector(0, 1, 0.5), + Vector(0, 1, 1), + + Vector(0.5, 0, 0), + Vector(0.5, 0, 0.5), + Vector(0.5, 0, 1), + + Vector(0.5, 0.5, 0), + Vector(0.5, 0.5, 0.5), + Vector(0.5, 0.5, 1), + + Vector(0.5, 1, 0), + Vector(0.5, 1, 0.5), + Vector(0.5, 1, 1), + + Vector(1, 0, 0), + Vector(1, 0, 0.5), + Vector(1, 0, 1), + + Vector(1, 0.5, 0), + Vector(1, 0.5, 0.5), + Vector(1, 0.5, 1), + + Vector(1, 1, 0), + Vector(1, 1, 0.5), + Vector(1, 1, 1), +}; CameraSmooths::CameraSmooths() { @@ -78,13 +93,23 @@ CameraSmooths::CameraSmooths() smoothLastTime = 0; enabled = new ConVar("ce_camerasmooths_enabled", "0", FCVAR_NONE, "smooth transition between camera positions", [](IConVar *var, const char *pOldValue, float flOldValue) { GetModule()->ToggleEnabled(var, pOldValue, flOldValue); }); - max_angle_difference = new ConVar("ce_camerasmooths_max_angle_difference", "90", FCVAR_NONE, "max angle difference at which smoothing will be performed", true, 0, true, 180); + max_angle = new ConVar("ce_camerasmooths_max_angle", "45", FCVAR_NONE, "max angle difference at which smoothing will be performed", true, 0, true, 180); max_distance = new ConVar("ce_camerasmooths_max_distance", "-1", FCVAR_NONE, "max distance at which smoothing will be performed"); + ce_camerasmooths_min_distance = new ConVar("ce_camerasmooths_min_distance", "128", FCVAR_NONE, "Always smooth if we're closer than this distance."); max_speed = new ConVar("ce_camerasmooths_max_speed", "2000", FCVAR_NONE, "max units per second to move view"); ce_camerasmooths_duration = new ConVar("ce_camerasmooths_duration", "0.5", FCVAR_NONE, "Duration over which to smooth the camera."); ce_camerasmooths_ang_bias = new ConVar("ce_camerasmooths_ang_bias", "0.65", FCVAR_NONE, "biasAmt for angle smoothing. 1 = linear, 0 = sharp snap at halfway", true, 0, true, 1); ce_camerasmooths_pos_bias = new ConVar("ce_camerasmooths_pos_bias", "0.75", FCVAR_NONE, "biasAmt for position smoothing. 1 = linear, 0 = sharp snap at halfway", true, 0, true, 1); + + ce_camerasmooths_check_los = new ConVar("ce_camerasmooths_check_los", "1", FCVAR_NONE, "Make sure we have LOS to the player we're smoothing to."); + + ce_camerasmooths_los_buffer = new ConVar("ce_camerasmooths_los_buffer", "32", FCVAR_NONE, "Additional space to give ourselves so we can sorta see around corners."); + + ce_camerasmooths_debug_los = new ConVar("ce_camerasmooths_debug_los", "0", FCVAR_NONE, "Draw points associated with LOS checking for camera smooths."); + ce_camerasmooths_debug = new ConVar("ce_camerasmooths_debug", "0", FCVAR_NONE, "Prints debugging info about camera smooths to the console."); + + ce_camerasmooths_avoid_scoped_snipers = new ConVar("ce_camerasmooths_avoid_scoped_snipers", "0", FCVAR_NONE, "DHW HACK: Don't smooth to scoped snipers."); } bool CameraSmooths::CheckDependencies() @@ -141,9 +166,93 @@ bool CameraSmooths::CheckDependencies() return ready; } -bool CameraSmooths::TestCollision(const Vector& currentPos, const Vector& targetPos) +void CameraSmooths::UpdateCollisionTests() { - return false; + const auto currentFrame = Interfaces::GetEngineTool()->HostFrameCount(); + if (m_CollisionTestFrame != currentFrame) + { + m_CollisionTests.clear(); + + const Vector viewPos = m_LastFramePos; + + for (Player* player : Player::Iterable()) + { + const auto team = player->GetTeam(); + if (team != TFTeam::Red && team != TFTeam::Blue) + continue; + + if (!player->IsAlive()) + continue; + + IClientEntity* const entity = player->GetEntity(); + if (!entity) + continue; + + CollisionTest newTest; + newTest.m_Entity = entity->GetRefEHandle(); + + const TFClassType playerClass = player->GetClass(); + const Vector eyePos = entity->GetAbsOrigin() + VIEW_OFFSETS[(int)playerClass]; + const Vector buffer(ce_camerasmooths_los_buffer->GetFloat()); + newTest.m_Mins = eyePos - buffer; + newTest.m_Maxs = eyePos + buffer; + + const Vector delta = newTest.m_Maxs - newTest.m_Mins; + + size_t pointsPassed = 0; + for (const auto& testPoint : TEST_POINTS) + { + const Vector worldTestPoint = newTest.m_Mins + delta * testPoint; + + trace_t tr; + UTIL_TraceLine(viewPos, worldTestPoint, MASK_VISIBLE, entity, COLLISION_GROUP_NONE, &tr); + + if (tr.fraction >= 1) + pointsPassed++; + } + + newTest.m_Visibility = (float)pointsPassed / arraysize(TEST_POINTS); + + m_CollisionTests.push_back(newTest); + } + + m_CollisionTestFrame = currentFrame; + } +} + +void CameraSmooths::DrawCollisionTests() +{ + UpdateCollisionTests(); + + for (const CollisionTest& test : m_CollisionTests) + { + C_BaseEntity* entity = test.m_Entity.Get(); + if (!entity) + continue; + + NDebugOverlay::Box(Vector(0, 0, 0), test.m_Mins, test.m_Maxs, + Lerp(test.m_Visibility, 255, 0), + Lerp(test.m_Visibility, 0, 255), + 0, + 64, 0); + + const std::string success = strprintf("Success rate: %1.1f", test.m_Visibility * 100); + NDebugOverlay::Text(entity->GetAbsOrigin(), success.c_str(), false, 0); + } +} + +float CameraSmooths::GetVisibility(int entIndex) +{ + UpdateCollisionTests(); + for (const auto& test : m_CollisionTests) + { + if (test.m_Entity.GetEntryIndex() != entIndex) + continue; + + return test.m_Visibility; + } + + return 0; } bool CameraSmooths::InToolModeOverride() @@ -188,9 +297,50 @@ bool CameraSmooths::SetupEngineViewOverride(Vector &origin, QAngle &angles, floa smoothEndMode = hltvcamera->m_nCameraMode; smoothEndTarget = hltvcamera->m_iTraget1; - Vector targetForward, currentForward; - AngleVectors(angles, &targetForward); - AngleVectors(smoothLastAngles, ¤tForward); + Vector currentForward; + AngleVectors(m_LastFrameAng, ¤tForward); + + const Vector deltaPos = origin - m_LastFramePos; + const float angle = Rad2Deg(std::acosf(currentForward.Dot(deltaPos) / (currentForward.Length() + deltaPos.Length()))); + const float distance = deltaPos.Length(); + + const bool forceSmooth = distance <= ce_camerasmooths_min_distance->GetFloat(); + if (!forceSmooth) + { + if (angle > max_angle->GetFloat()) + { + ConColorMsg(DBGMSG_COLOR, "[%s] Skipping smooth, angle difference was %1.0f degrees.\n\n", GetModuleName(), angle); + smoothInProgress = false; + return false; + } + + ConColorMsg(DBGMSG_COLOR, "[%s] Smooth passed angle test with difference of %1.0f degrees.\n", GetModuleName(), angle); + + const float visibility = GetVisibility(smoothEndTarget); + if (visibility <= 0) + { + ConColorMsg(DBGMSG_COLOR, "[%s] Skipping smooth, no visibility to new target\n\n", GetModuleName()); + smoothInProgress = false; + return false; + } + + ConColorMsg(DBGMSG_COLOR, "[%s] Smooth passed LOS test (%1.0f%% visible)\n", GetModuleName(), visibility * 100); + + if (distance > max_distance->GetFloat()) + { + ConColorMsg(DBGMSG_COLOR, "[%s] Skipping smooth, distance of %1.0f units > %s (1.0f units)\n\n", GetModuleName(), distance, max_distance->GetName(), max_distance->GetFloat()); + smoothInProgress = false; + return false; + } + + ConColorMsg(DBGMSG_COLOR, "[%s] Smooth passed distance test, %1.0f units < %s (%1.0f units)\n", GetModuleName(), distance, max_distance->GetName(), max_distance->GetFloat()); + } + else + { + ConColorMsg(DBGMSG_COLOR, "[%s] Forcing smooth, distance of %1.0f units < %s (%1.0f units)\n", GetModuleName(), distance, ce_camerasmooths_min_distance->GetName(), ce_camerasmooths_min_distance->GetFloat()); + } + + ConColorMsg(DBGMSG_COLOR, "[%s] Launching smooth!\n\n", GetModuleName()); m_SmoothStartAng = m_LastFrameAng; m_SmoothBeginPos = m_SmoothStartPos = m_LastFramePos; @@ -280,42 +430,6 @@ bool CameraSmooths::SetupEngineViewOverride(Vector &origin, QAngle &angles, floa smoothEnding = true; return true; } - -#if 0 - if (moveDistance < moveVector.Length() && moveVector.Length() < max_distance->GetFloat() && angle < max_angle_difference->GetFloat()) - { - float movePercentage = moveDistance / moveVector.Length(); - - moveVector *= movePercentage; - - origin = smoothLastOrigin + moveVector; - - angles.x = smoothLastAngles.x + ((angles.x - smoothLastAngles.x) * movePercentage); - angles.y = smoothLastAngles.y + ((angles.y - smoothLastAngles.y) * movePercentage); - angles.z = smoothLastAngles.z + ((angles.z - smoothLastAngles.z) * movePercentage); - - GetHooks()->GetFunc()(angles); - hltvcamera->m_vCamOrigin = origin; - - smoothEnding = false; - smoothInProgress = true; - } - else - { - if (hltvcamera) - GetHooks()->GetFunc()(OBS_MODE_ROAMING); - - smoothEnding = true; - smoothInProgress = false; - } - - smoothLastAngles = angles; - smoothLastOrigin = origin; - smoothLastTime = Interfaces::GetEngineTool()->HostTime(); - - GetHooks()->SetState(Hooking::HookAction::SUPERCEDE); - return true; -#endif } else if (smoothEnding) { @@ -327,8 +441,8 @@ bool CameraSmooths::SetupEngineViewOverride(Vector &origin, QAngle &angles, floa smoothEndMode = hltvcamera->m_nCameraMode; smoothEndTarget = hltvcamera->m_iTraget1; smoothInProgress = false; - smoothLastAngles = angles; - smoothLastOrigin = origin; + m_LastFrameAng = smoothLastAngles = angles; + m_LastFramePos = smoothLastOrigin = origin; smoothLastTime = Interfaces::GetEngineTool()->HostTime(); return false; @@ -378,5 +492,8 @@ void CameraSmooths::OnTick(bool inGame) m_LastFrameAng = view.angles; } } + + if (ce_camerasmooths_debug_los->GetBool()) + DrawCollisionTests(); } } \ No newline at end of file diff --git a/CastingEssentials/Modules/CameraSmooths.h b/CastingEssentials/Modules/CameraSmooths.h index 1d47664..af3b96d 100644 --- a/CastingEssentials/Modules/CameraSmooths.h +++ b/CastingEssentials/Modules/CameraSmooths.h @@ -3,6 +3,9 @@ #include "PluginBase/Modules.h" #include +#include + +#include class ConVar; class IConVar; @@ -28,8 +31,6 @@ class CameraSmooths : public Module Vector smoothLastOrigin; float smoothLastTime; - bool TestCollision(const Vector& currentPos, const Vector& targetPos); - Vector m_SmoothBeginPos; Vector m_SmoothStartPos; @@ -48,7 +49,8 @@ class CameraSmooths : public Module class HLTVCameraOverride; ConVar *enabled; - ConVar *max_angle_difference; + ConVar *max_angle; + ConVar* ce_camerasmooths_min_distance; ConVar *max_distance; ConVar *max_speed; ConVar* ce_camerasmooths_duration; @@ -56,7 +58,32 @@ class CameraSmooths : public Module ConVar* ce_camerasmooths_pos_bias; ConVar* ce_camerasmooths_ang_bias; + ConVar* ce_camerasmooths_debug; + ConVar* ce_camerasmooths_debug_los; + + ConVar* ce_camerasmooths_check_los; + ConVar* ce_camerasmooths_los_buffer; + + ConVar* ce_camerasmooths_avoid_scoped_snipers; + + struct CollisionTest + { + Vector m_Mins; + Vector m_Maxs; + + CHandle m_Entity; + float m_Visibility; + }; + + int m_CollisionTestFrame; + std::vector m_CollisionTests; + void UpdateCollisionTests(); + void DrawCollisionTests(); + float GetVisibility(int entIndex); + void ToggleEnabled(IConVar *var, const char *pOldValue, float flOldValue); void OnTick(bool inGame) override; + + static constexpr Color DBGMSG_COLOR = Color(255, 205, 68, 255); }; \ No newline at end of file diff --git a/CastingEssentials/PluginBase/Common.h b/CastingEssentials/PluginBase/Common.h index 1994681..2fb0f87 100644 --- a/CastingEssentials/PluginBase/Common.h +++ b/CastingEssentials/PluginBase/Common.h @@ -77,12 +77,12 @@ inline bool IsStringEmpty(const char* s) return !(s[0]); } -inline std::string strprintf(const char* fmt, ...) +inline std::string vstrprintf(const char* fmt, va_list args) { - va_list v; - va_start(v, fmt); - const auto length = vsnprintf(nullptr, 0, fmt, v) + 1; - va_end(v); + va_list args2; + va_copy(args2, args); + + const auto length = vsnprintf(nullptr, 0, fmt, args) + 1; Assert(length > 0); if (length <= 0) @@ -90,14 +90,18 @@ inline std::string strprintf(const char* fmt, ...) std::string retVal; retVal.resize(length); - va_start(v, fmt); - const auto written = vsnprintf(&retVal[0], length, fmt, v); - va_end(v); + const auto written = vsnprintf(&retVal[0], length, fmt, args2); Assert((written + 1) == length); return retVal; } +inline std::string strprintf(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + return vstrprintf(fmt, args); +} inline const char* stristr(const char* const searchThis, const char* const forThis) { @@ -139,11 +143,11 @@ inline float EaseInSlope(float x, float bias = 0.5) inline float smoothstep(float x) { - return x*x*(3.0f - 2.0f * x); + return 3.0f*(x*x) - 2.0f*(x*x*x); } inline float smootherstep(float x) { - return x*x*x*(x*(x * 6.0f - 15.0f) + 10.0f); + return 6.0f*(x*x*x*x*x) - 15.0f*(x*x*x*x) + 10.0f*(x*x*x); } extern CSteamID ParseSteamID(const char* input); @@ -157,4 +161,15 @@ extern bool ParseFloat3(const char* str, float& f1, float& f2, float& f3); extern bool ParseVector(Vector& v, const char* str); extern bool ParseAngle(QAngle& a, const char* str); -extern Vector GetViewOrigin(); \ No newline at end of file +extern Vector GetViewOrigin(); + +template constexpr std::size_t arraysize(T const (&)[N]) noexcept { return N; } + +constexpr float Rad2Deg(float radians) +{ + return radians * float(180.0 / 3.14159265358979323846); +} +constexpr float Deg2Rad(float degrees) +{ + return degrees * float(3.14159265358979323846 / 180); +} \ No newline at end of file diff --git a/CastingEssentials/PluginBase/TFDefinitions.h b/CastingEssentials/PluginBase/TFDefinitions.h index 7be8fc5..8132255 100644 --- a/CastingEssentials/PluginBase/TFDefinitions.h +++ b/CastingEssentials/PluginBase/TFDefinitions.h @@ -10,12 +10,13 @@ #pragma once -#include #include #include #include #include +#include + // taken from SourceMod enum class TFClassType @@ -271,8 +272,8 @@ enum class TFGrenadePipebombType Sticky, }; -#define MAX_COSMETIC_SLOTS 3 -#define MAX_TAUNT_SLOTS 8 +constexpr auto MAX_COSMETIC_SLOTS = 3; +constexpr auto MAX_TAUNT_SLOTS = 8; class TFDefinitions { @@ -281,4 +282,19 @@ class TFDefinitions static const std::array itemSlots; static const std::map normalClassOrdinal; static const std::map> slotKillIcons; +}; + +static const Vector VIEW_OFFSETS[] = +{ + Vector(0, 0, 72), // TF_CLASS_UNDEFINED + + Vector(0, 0, 65), // TF_CLASS_SCOUT, // TF_FIRST_NORMAL_CLASS + Vector(0, 0, 75), // TF_CLASS_SNIPER, + Vector(0, 0, 68), // TF_CLASS_SOLDIER, + Vector(0, 0, 68), // TF_CLASS_DEMOMAN, + Vector(0, 0, 75), // TF_CLASS_MEDIC, + Vector(0, 0, 75), // TF_CLASS_HEAVYWEAPONS, + Vector(0, 0, 68), // TF_CLASS_PYRO, + Vector(0, 0, 75), // TF_CLASS_SPY, + Vector(0, 0, 68), // TF_CLASS_ENGINEER, // TF_LAST_NORMAL_CLASS }; \ No newline at end of file