From bb42c95944ad1ed8723ae5196bbaa403136f74a8 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 4 Jan 2021 14:29:15 -0500 Subject: [PATCH] Skill point gains are displayed in hud. level up message visuals and functionality Handles simultaneous skill point gains in UI. --- .../element/buttons/slot_skilltree.png | Bin 0 -> 2034 bytes assets/voxygen/element/misc_bg/level_down.png | Bin 256 -> 0 bytes assets/voxygen/element/misc_bg/level_up.png | Bin 235 -> 10187 bytes assets/voxygen/i18n/de_DE/_manifest.ron | 4 +- assets/voxygen/i18n/en/common.ron | 1 + assets/voxygen/i18n/en/hud/sct.ron | 3 +- common/src/comp/skills.rs | 7 +- common/src/outcome.rs | 6 + common/sys/src/stats.rs | 16 +- voxygen/src/audio/sfx/mod.rs | 2 +- voxygen/src/hud/img_ids.rs | 2 +- voxygen/src/hud/mod.rs | 138 ++++++++++++++++-- 12 files changed, 154 insertions(+), 25 deletions(-) create mode 100644 assets/voxygen/element/buttons/slot_skilltree.png delete mode 100644 assets/voxygen/element/misc_bg/level_down.png diff --git a/assets/voxygen/element/buttons/slot_skilltree.png b/assets/voxygen/element/buttons/slot_skilltree.png new file mode 100644 index 0000000000000000000000000000000000000000..6da9e2e4cdc42a7a1ba89c096d142b450e11749a GIT binary patch literal 2034 zcmb_d&u`pB6y8b*N~LhC6mc?+kXpg4$KxMskFt%D-LzSW4N*F{D>soDjWt=j;D+?`<{U~Yb|9=02u0^7$-*URRo3`X2+BnSQ z&BM(eKiuWM&{wW$%VP=vu`HN2j)zH3$4z~LOJQ728@e_zDR!IsYUxnh>27H)l}XL5 zW5hAGw1!_dUE3jzw>5$ZHcYr2WHzYnQHyA^pAOzK5z_7U^_eetYwCldNU33rMx*-3 zs;jJTn7;2Dm>7g0ut51iQm`>f@})UKTjo5A(jrocRwA-M?G;TOm`+28(+W1pXK8|j z8Do|jW*wIyO$-IE?9#n#IB_nxA%`-SNs)uCS=puoRj7QR&Va6#A9Dby?RG04r*eto z%0*tR??V`~gq&)f_YP8NY|C8jWn8ZB1I?u}nv}LO$qJSAlp4+tYHLneBcyI>S8hd# zP^0|ni4C&N3fa`lQ$wZ+SC3$deM+3Sut_nVns$|l!h_1xL>Ml+hiyuHYLdrHK{A3B z?5W0r(@&`4rti84 zVw}+Jc4;Tc3zl%%X*YF9PCbeQb&1UzOb8TUFF=87H&9>+f`s&l8#*uyC`dLuiCVG}fXGbY z2LZMab9|1tYfBXHz(c~~mgiW&*%hViA9DTk+8*(x!}; zCEL__sZ}ZT*>rTuX+2Y3X8T72383d_cWPuxm z0y&NuATA)wUc<(q6h=rWee5+rs8dcSsS`xp9`-19DKY0Y^*q#P*nGf}zJ%|;p+A2x z&sH^01asC0;>86s5$RN6#*^Zktet2Pb0tIHDTh_VgO{ph$^`P1K|}m};m*%xGwrlj zdsi;={~kVE`S>XL=SX}j<9o-y{Px#x=BPqR7i>Kmc0$aKnzCTAtV};0W2{%O1z<3P80O?X^11|s#)khJ9{2&B0 zL6Pn?cRpQVJ=wlX%y4(j&oZw>L>kAFz|7R1Z_8%1QVu6z5^_xk&qZE-6AC^NF$+yN(r3t zt@FIj?>WzT{yBTy+kNf2KiB*7{^a7iqYU)ai3#Zmv9Pd+H8oU>u&{1vV8%iCc$il; zg-CJCiNIaM5`~3DM0xYPg_V^}hlPbZ;ACRqX`!nl1x2_DKwtk7a?1Hwpn3x&{Dc1QHGq6AJT{&Ew>VS>I8cR`SV(2Yrd3+n3rXHi$zf22{Ks@@nafARgd zz$ggLgA|3a5qoZzm>tD|EzWQLc086DGVwIcY(WN#84Pwpnp`kJ0d(0 zC`ZKq#g2b2|6`52lrjl zSs*5AAbugtA!;HdB!xMI#dw84n8BZ-x|lqGK|CS|!B)^2HFo@qCBm&`wND4{tgTSI-A$ypp9Zd93 zD=}#LNGD9?KwSP6^@bG;g9w3&+d=Jw;rwt21jcU<7ZK)%z$Hca!9t>vk{Bd=kexjc z0E0@|Bap5TOrAKoLLA_N?rsi1!2f2WjBr69brCR(&xLQY8H0||tKo#ggwF4;`Y?uj z{55iM0{oG5809y)E(?U-1Q`wk{x$9NZ@l;4@%$6k#}SSJ{SU$aQw)W$_w<1v;ff9z zPyauYOYr|j9tH9K&(#0B!2f@w{+C;!ju1BoIHqw50&k2FylF9i21W4yjMpF6{-quL zEsp7NH^YCLE9T8V?HTTdfktAQ?-~ic92OQ!g{F$4iSPWr?QlH5xl!D#rMWW^WIWPI zxO2pyaa%B-IPi9)8vzU5v(L;^q#OV|jmU>sFPRlI-amUDFp=AUHHTf~y+MK}&BO~l z&gNOR_Clm0_$o}c630+_RW{_j-Yzuc&aF~%*BQ%0$5+$ed%tfzm0LBx0D;H{U%fpZ zJqcU>^}Xa!i0+bHgz0t^!^5=XZ_4q3CsJ>9rsBd^OXY+6loQt8UdvtX8cUU4Updg2 zB*m%m4)nb=jep`2$1$K*H0~JeB0~SyP()FTK2D7iwkBHeWEFER^0;*rs#!bOGLAFn zOTjkRKmD)L!Fwm&;Ac+U!Lvw)j0DmHvgovcBlR+ zdtJPi))3dP#W?-^M$22g?3wfS z_vq3SO?~iKdi>D(GNJW84bp z@X!|2%zUH#62mr~t?*A%0!I(OUHAwd3twmfZRn}7Pddy-?|`_gR}nMGydI>(=m6-%I~h{=Xl@O*0dMO7uEt~8ocPPg0@UW zzHoLlL4bwJmqmh6nH$U3x$&lfmUPpYkCYx0g0@}09a*%ud;a{R ztQ=eSjmF4E-iO+RYnls03?PN;2JWH8;V_+gqa`Fjv*0 zT?*JfeyX+H3w1%+pbuktosZ^EOjFmrSL_>XBkz6)LVYgWzcr9pj!GcqHa}N(6lv$^ znZ=pgzOP#pbx7h#auX7e*iG_t^!-s3H&-#4O?Q(mY9SA|c8wt8=@+nsY&ffA2T7F+E8M-cW&0xR z3EHJ4*Qd>o;lqnmi9EN;KY05^jDEFBJFb?bB5N5senuCmAfnQ+4@=^*N}f3fs^81% zvWJ7YCAH1WY+$_+WEc6)M3NNP+^N}|A#ACqxMec0IzDK;v5ewKeUg+1w@~__*L|9J z`)~pmcg%GBvBh<`X5Ebu_g?jqO4>e(a7Rn9C<MP595Lzs64+HmPkC!l6MReAO|zgyVJ}Xb`)_ODUZHfnaqJI-esQsoA>R*9psQv*lu z0qza6T*tgDOfmxarP$bGa(aD60c4k9rDRp%Q8i9Q!Pxo@h8>;wwRpXMW{b^>t$!Xe zpG`-#P6%R#nsx@+WRDRH_P>x$%q@qo%^i3|EX2}2UrTmbWCMyPQJwD9TI&Tb;1?!` ztf$Vxyh_R`-W4zI%!!trL`MJz|FBCxo_l^Zsl|u_3J^ATHkk%6+ipG*pXDjb@x%XC z08X#YBA64qFP|N3&1zMU{gTq89p^$~UEr%qPF8KQYES-0Hc$f}XAXFfAaqfEgWHn3 zg_rb9YpjGmai}2Bsg0FW97l2yd?cCbXiZ@mba-5a>lz&RO4&Iy#;Thp#%XTaRTvzv(yDTQn(rl}KMBj7Wrlv3W)L#Jdo z<@$m`Y#tUU*CZY1EGm&Tgar$>rO7V`8~#LiH#qTgh9yxvk?NQ1#mDv}?2r2u6fBXU2ka}BZCI=P=qO_a9}}59-E%^P(*c0 z>4P#%vacKr@S!Vikke;)X^S;LaYV;=DGzRlm0}UZ(isOR6voVcsZlVL zAPPNR9U`;+F(9ZlkzNduV?R<0(M(E&T`1J{{pe)*?It>hb5=hj8Z+VpXPMI!_RwXbMLEF1m2nY+Id%sn;FPwm#&f) z$ki~y!u1JQHReh~kx5o*bt+@5FqR$l0zcdNb8dCm=j!Wo33B%4dBtbDT@-X)$x-P^ z$8K8mN4aDZ!!=wD$4R;gWAe+91x9AplF5Cvk*dC2<~X1v9@*Q$p0o=D2=cwv=mJQ7 zy8r~MCfSLjntHX!U&gTNgR_Z}>o3-1quh5N{Gai@VHc87&{TAalb(_+OOIgG6GGcr zvemffZTaW$&14LRAeZVkx#Mc>4gD!UxGNorD)}3iXcnC7VhtxMT$ZZ9-h5@VD-aA? z(yGO@=J2Wa1li5P21cG5vFIauWK7kUN5w=n6eZNbF9xs)$+#mbpv93a?@oUus&ukd z?o1v>%o(gw%v<}mX*_DuqGIqZ8=5xQ6z`SNYp`n#s9R~0u^ZdZ zPm|T~hkpY0$h2WGrbC{CnT-od%~sj~nu8mPPSR9o6G^PSNvcr03eYM{ z&VA%^l%Y%IJ1MZ)ZaaezgM_vexR|xZ^d?Zt^o4Ufol_P3j{D&=de-n_fW*8;lgy(? z7G~*dUnZ)ejaz3Xd;{UXop=O?3OE#fT_jaa?8ytwm9STlKg-#+YdxHqgpC>%$YeS9Tdv?2!>j5CdH0CgFD`niu~Jn+F0C-pKQar4=`Tj}S6J89}id}Uab zbH*r_+kJYB%Y3;h?-`0;$&#o>4e@`o5FQ~T8XeQnM`fvmo#N}#5hZgnq^rnH=`ylz zW-7VdQoXlBry*A{Eb&yaUv5UH!EX}h>__*`V%Mwix-bUG0q4XCt{$gQkuKj`=2?6_ z9IP6~&#aN1MKlzt!1Sd2g57Yf*rcL?I6J9lQK)Yd@dWfcRW{|XZMag~6YCA}!Y;BS zs5Y#64eWj$;zA_R5}kPDMl9U`6-~AXHL@fNpt=R8$(9bQSM5Z$K`su9M0XIo^d?Sy zTE^rE#CH)9I^XIP99X%Y;g78pPu{XcmW0=x&_OP#&dN$3B_X>`V@5G?KuyI?UapVd zc@Mv#dFcVRCaVq`(~!6_>C==CimbMo*-}JrHc;L3_{-1{QBF~+swW(poYVkWr84yT zK>`);VQ9n(DJyndq4&Wq5JYJ~%x~mnf!uIa1C!YSL z3~dxRVcja%6gR6j*Izkyzge?yau-(g98aAZOBM7a$F6Xk@W^SMAv0ceD(Nw4x0Apo zQBB04TcAa*A%XrgAt1;?>7ca@>D304{C&vkJthf{bSu<|Dv0iV zX@XVo`@x{Xo>}h zlTdPEn?odjyz7|_kU3mUshZwc(IS3Anp#orP>9148G!)0XV!>O^xG^XDB!<3^x~w# z&(qX^ncL-Z@7dS^CX2=sunq!CWwfZNvD!^de<7t^;CM6@or^Mxo$G0 z@}1eQDuX&h1e2>otrXjXkneuj?FVAlKTmWJse|{7Sw-n5jf0hL4Sh_aH;KV^1}d^N z6XLRKz3!39KM2HPvCbtU5TdGxm@=bCIZ9`LXsNcNl1cXbzJ7@#Lks=}H!-^|^idkF z)X=)thtb$m(SU7j(K~|@#qJy-VMZ0BIN%(`wDv0;xRf@&0EBRmt$^_;Zn)fXxmRY; zFZ^g7wwIF4MN@6;I?jO>9zW-@))Z50?@O3RjG|Ow}7e)iEAR;YGkEk&+rN&;BKo523Bme zTl0M^KC^85BLe_BVkj(4`VaGAA_q|>=8_StPnl(^is0~$y!3bDEMegzxvpC*D&C}AGqCFhD;;W<%lEl2 z5a>k3#r5D#iK;Cb1X{9#2`Olpr6ls-adw@yUJJQ3g|B~Xol#bm<54LElh_!U32oim zm=($}Dg{0K&F1xuj{P<-&IvVVvAn&r8~HFU2wj_Odm{SW-9cjZc4$e}Pvll<5OV?5 zWzCmo69stWCO${*s@&}iyH{#-=0PnVX9}>Z%ZQ6VM5n#P70&`N(+Vxeq z0+sVv^;u)ouy~eF&@uM)1F3bl;6M@L%R;9VP4qD~s~=-#2V6sr zata6ywVfSb$4s6iq7t~r%4vbki?PKvUEbV1-=fVT$ox^n+dI&oNsdG+x-c=Pqbb6K z03BHY+#S`DADFKzGW-uSFVt6koo@GMro3iD2Io_GL;@iNRZ4$j`}mZ70k!_IyM>B!5sLYXUaasiKmW}*>JMmBpqv)he!>65rxs)&zmWF zTfe6Do3u<6r%Z~lMn;j!a#V=aP>2y=?(oU=`(enP>@pJl} z%}FsGbr@XLfW%}=mv);HJ}HwD{alT59XnzcTgpoP;Rs$=9>#OIE(aB0%gh zsS}e>s)4dgPed8wB|C`3QgKV9c!>ieSt&!lEnwT8|Rg{PB`Ny`$-9zt$qh7_sw&Qz|*x=DxLIH z>HZRid})YsgV4p|dp)i7rDIGT$Ki zF7C?XCqtEntG;jUa_;~L27KRd(;COzPr)N?uqNwdC zZL$&F02$sZ_!8HYGxcek{+B(AUvMM-N?fdZg52B*SA_?tKG+45>9?GI##v0Pszk=w zD{t^m_97##y=z3vn((zWHQnA@)MT$=!7T@cVwp+%71`;@iypi2BxlxHuCJAAmjN78 z$S1p%G+%sCu@e#`8NueQh>tM7&TI@ZXWQ$hNu`^yWiv+-s#|KJPiha?r$e8l; zQ8%Gamwqfg7oHF8g4)8tw@QyhXVZvEhBg5&?x~-$`ww#KKP_nMkJ1$(ih>HuwoOuF zMzw)kL-c(YP40QvTn0nRnFmLt>YI{K-V=hXh zM$9_~2fE`DFrsVLe9GlVNbNp&5Gk<>n~3>Th5VihEx2!5x~Gznb1+I>>^K{~5=+;x2IQJqnXHl*>!Xigu{$iBxh_>hi?QP8Bg?RcuJfi9@+Nt)CA^_Poe=G4ieZTLU&8Jq9*J!+ZA z&UZ-HIu=lxf7I1&x0Ld}NBX=v6RcNxYSZmVu+fA+MfhGdb>-XeJXq-!%+ZuJBe4jr zWjAJ7HG_z%#u+|NqDKn_3INga3Pl7*D~ZF1)|`ywJbJcTr$HUFL~V#$ug*AJSJ(ga zHQ|elP&bhos)D94Yw}zaVSVQN-{icM^tk~#?D9BXnRf{%2uIp%fC;D&KZpgRt1!aChPdjbxhT{{=f@`Q z+KQDn&l+UuXUkl{v%tw2FGiCTtD!n1da`@dtM2nFoV^u4M5RX3lqVm-f(GPrPjddqpnhfo8l%UDG!>Er|2^ZxWlg?_9CH1E24wuv;) z8FcBz>eR(J_4N8i)X<>skshmN4aIt%p}Y0TV?YJX4V}B;+PQ-VuRZ&-tsFBmwL)+R zbBmOHMThZ^oN?}V$|Zt`vB{_8{9V`ac2H`pHje(oZqXUqacd=_ferhoZ14-9_zJ*) zet2X&5N3k+Iw9N3l3C69XM&TImDxlb!GsxA5spBB39)Zk!Pl_W&%&6Wb>q}*pmZ{? zNdy05E9KH#jDBu~Oi2o+N=qLjSeh^13~Nfv4%>zu&N8@3TA#YYUT?;i-5QbIG6;WQ z^6m3rh)|n3o9FFX8n^N3#jb{eO}uWHZ9YSe2vXqWH5P^7BhLr>aley@JE3_)sl_@S zSi4dBZTT!*H1Wv|BFEfToS`G#3u#f|eY+PgtFC0WxGK+ONMEDX4ZG@)3}dPSsc5+| z+4;_KHNHmjBwm8PljoyaZUuR8s&m0K{N|x`qvZttGxm z;){_!4+Mz2aC)%G;s-Q#c_2b}8Ijc< zq144=+rNs|ci0u?A=!@R_0H>$`(nc1yH)FO{hTlOWK5l(e%T6GT@VpWusHF^RA_%W zM*3|-$&+a7v3NyJvo?%!owY>-o3IL@^jWd#{|M5W=+K^T!zcrc=6;Fyjl;? zqNAp2j3t$-=75@~W42ZnajHAn>az^z>i!ZWluuR|W+NouagV0Ej@lFnfJ)Oh>=sSd zvh?P&aVv6Ti&-*ei3lje8P8kAs>C?yjFL(%$rxuCc!-EPydEGrl@2qEo(KBoZ_+){ z@xDvy`E%>L@=&m@lU3(wmD(adsO=#5N2<@_N~s++Rlqv0s3-tg1Zm5JwWQ^Z3Q!?} z1J}u{yG;*46EBl#6{`|`V-m6q810CQlGtQ^fmzsf!h?@f)7M*Vql6d(bo|T5-r<`_ zZ1ASb%?DF)m-_bB%-p5)oXa@a-XDe4ElN^zFD9^&)ZenwG;+3$OzYE{1k>xfU)~2XE7qc78lpXZ&f`Hw1LD zi2ucv#>r8zAmT0S?Cewif^Dp#FE-QDNC5Zv;3jkK&>St1oqcTOuW0|dw7E`wc@I(e zgEP^2T?iVgD>1j}95CMW$fEry75K7Jl%b*scY!S0`V9w^&UNc~oCm=a@jK8OOai4v z6@GCy?8}n-ZRt4ZoddAUY`-yT#Kt0msi^rKL(zM@&eOwj(OGv|j$J~Btmp2%0b*8i zV1KYyxoa+nM-8ZtUUX#HROD-<4_`PDhg2aME6aDrObVx!tSt4L*3E2!h^7tIUN;^x zj_1;cR!4l6*sJq+82tM;^onVNAan0_5g>Ttll+v)lTsO;yVBhUVep9tOshKl9tY9ckV*6G7&<+AVHp;i*pyn5ldllKg=BIwgAuGLu*&aVcck^wn- z>FGpo^IFe7G|HV?n*=`$JfD>BU@Z&Co9gSWKFC2_PA@CS8MmMQ;C!k$LvkX~JAa1R z#O2Kq-JXYX_uF18*FAWucQ9Yl;dfRuQoE;T_~XIC+sj%P?9#Y$!m}S|CH)tvKfQh1 z)8RYI57LUHm(q!@cbRh-TDFP9^&X^qAQcD0V#3~D?&t;Km^4TZ`6HF?2KF=Cq7QbF zKDMW+2V?PXvY)am1m>I#9SU*L2+-`$Ib^HvWV?OelU{qgaHTc)>D4=roZ;}w!WFg7 zqB7a3H(MePPh@2prR7-#l2X5&%z>e9D@+~JA42}bxKh+VE<|AedXF|S{&Ms4NmNxig$~K+(XB~prD7$v zz7K&bmmV7-%(Md`dU6I*ENyk9K{jVAhl5v9k*7I`?QIBS{|JaE{{f9AHHGkGwjF7| z>_DENP0FkM@XS*0JG7GK(ZKXnNUWZm0E*k|skv6ihk}!**Y$F51?4Wk=24JeV)n7# zif@?{{0!}vFi*U`(3igyHcfh}uJU74J~Y$$^qX`y`#iL2ouy|)F4OgFf2%+-(04SQ zG0;$9Y7vVrB-bQ|7XNt>wE$_&+`XSCyjDKkR=o$qg2|4V8!`e>?83=?gY|swZ}zHx z%bdAtqnS3e+8=)Dpu&xu*=ltkK^{qJOFD4(XHl%`sC4+S{0_Z(p8K?gCOo&TBh_^p z-be)b(L{0OX0GJZP9~5ScHztCxw7~bcHaROp!O?}ecwH=Wt%ZtB=L9s!OQPW!;_5T zowkX}pRb63g=2D7^3^`eCq$d3RQsy37jx=YvNcP49jy^r3A_ufG;+g(-fu6*x>;VZ z9M2uiTy1Mf_kS+5mvuz`}RZKwOhyHaec|a zDe+pjB9Cx^W2aVcg{2Fgn$JFHwIa-p{Wwo8W<>CegwxWEW|^+|h7ZDR)2446~QY zJ9u-W0;*?tlj@;&n_1GoObUnDu<)YCngwef{2`@QlnPq|JzqoK*FPlkZ)bISuo=-y iTJ84NW;@gUYtrrayUKC}yp}h&+i9xmsZ=RF3jSZpp=aU% literal 235 zcmeAS@N?(olHy`uVBq!ia0vp^Ak4|Z1|%1zR<8$AjKx9jP7LeL$-D$|mU_B4hIn+o zowAYlkb!{f{+0IJF={82d?pyqJRF;)_CT$``KxBZoCPi?OjLBzfP_UoM3 zAGT>~334Cz=!Y9chfY)KIrEOyw|Z!@GH6&|y6bFyqi!Xin|Z`U4jrqa jq*?!urQi8`_O9^KzS%k3HB?Uk9n9eA>gTe~DWM4f9Fbpz diff --git a/assets/voxygen/i18n/de_DE/_manifest.ron b/assets/voxygen/i18n/de_DE/_manifest.ron index 02f81f3753..f351c8a52d 100644 --- a/assets/voxygen/i18n/de_DE/_manifest.ron +++ b/assets/voxygen/i18n/de_DE/_manifest.ron @@ -100,6 +100,7 @@ "common.weapons.bow": "Bogen", "common.weapons.hammer": "Hammer", "common.weapons.sceptre": "Druiden Szepter", + "common.weapons.general": "Kampf", /// End Common section @@ -204,7 +205,8 @@ https://veloren.net/account/. // SCT outputs "hud.sct.experience": "{amount} Erf", - "hud.sct.block": "GEBLOCKT", + "hud.sct.block": "GEBLOCKT", + "hud.rank_up": "Neuer Rang", /// Respawn message "hud.press_key_to_respawn": r#"Drückt {key} um am letzten Lagerfeuer wiederbelebt zu werden."#, diff --git a/assets/voxygen/i18n/en/common.ron b/assets/voxygen/i18n/en/common.ron index 987228462f..0670c3615f 100644 --- a/assets/voxygen/i18n/en/common.ron +++ b/assets/voxygen/i18n/en/common.ron @@ -62,6 +62,7 @@ Is the client up to date?"#, "common.weapons.staff": "Staff", "common.weapons.bow": "Bow", "common.weapons.hammer": "Hammer", + "common.weapons.general": "General Combat", "common.weapons.sceptre": "Healing Sceptre", "common.rand_appearance": "Random appearance and name", }, diff --git a/assets/voxygen/i18n/en/hud/sct.ron b/assets/voxygen/i18n/en/hud/sct.ron index a3a3cfca33..d8ed744fd1 100644 --- a/assets/voxygen/i18n/en/hud/sct.ron +++ b/assets/voxygen/i18n/en/hud/sct.ron @@ -5,7 +5,8 @@ string_map: { // SCT outputs "hud.sct.experience": "{amount} Exp", - "hud.sct.block": "BLOCKED", + "hud.sct.block": "BLOCKED", + "hud.rank_up": "New Rank", }, diff --git a/common/src/comp/skills.rs b/common/src/comp/skills.rs index 0d812662d6..41f32ac140 100644 --- a/common/src/comp/skills.rs +++ b/common/src/comp/skills.rs @@ -544,11 +544,8 @@ impl Skill { /// Returns the cost in skill points of unlocking a particular skill pub fn skill_cost(self, level: Level) -> u16 { - use Skill::*; - match self { - General(GeneralSkill::HealthIncrease) => 1, - _ => level.unwrap_or(1), - } + // TODO: Better balance the costs later + level.unwrap_or(1) } /// Returns the maximum level a skill can reach, returns None if the skill diff --git a/common/src/outcome.rs b/common/src/outcome.rs index d57554bdd3..109ca557c2 100644 --- a/common/src/outcome.rs +++ b/common/src/outcome.rs @@ -33,6 +33,11 @@ pub enum Outcome { uid: Uid, exp: i32, }, + SkillPointGain { + uid: Uid, + skill_tree: comp::skills::SkillGroupType, + total_points: u16, + }, } impl Outcome { @@ -43,6 +48,7 @@ impl Outcome { Outcome::LevelUp { pos } => Some(*pos), Outcome::Beam { pos, .. } => Some(*pos), Outcome::ExpChange { .. } => None, + Outcome::SkillPointGain { .. } => None, } } } diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index b6feb7df45..af5ca5ef5f 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -5,11 +5,13 @@ use common::{ }, event::{EventBus, ServerEvent}, metrics::SysMetrics, + outcome::Outcome, resources::DeltaTime, span, + uid::Uid, }; use hashbrown::HashSet; -use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage}; +use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage}; const ENERGY_REGEN_ACCEL: f32 = 10.0; @@ -26,6 +28,8 @@ impl<'a> System<'a> for Sys { WriteStorage<'a, Stats>, WriteStorage<'a, Health>, WriteStorage<'a, Energy>, + ReadStorage<'a, Uid>, + Write<'a, Vec>, ); fn run( @@ -39,6 +43,8 @@ impl<'a> System<'a> for Sys { mut stats, mut healths, mut energies, + uids, + mut outcomes, ): Self::SystemData, ) { let start_time = std::time::Instant::now(); @@ -53,8 +59,9 @@ impl<'a> System<'a> for Sys { healths.set_event_emission(true); // Update stats - for (entity, mut stats, mut health) in ( + for (entity, uid, mut stats, mut health) in ( &entities, + &uids, &mut stats.restrict_mut(), &mut healths.restrict_mut(), ) @@ -91,6 +98,11 @@ impl<'a> System<'a> for Sys { stat.skill_set .change_experience(skill_group, -(skill_group.skill_point_cost() as i32)); stat.skill_set.add_skill_points(skill_group, 1); + outcomes.push(Outcome::SkillPointGain { + uid: *uid, + skill_tree: skill_group, + total_points: stat.skill_set.get_earned_sp(skill_group), + }); } } } diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index edafdd363e..a93f9afc68 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -358,7 +358,7 @@ impl SfxMgr { audio.play_sfx(file_ref, *pos, None); } }, - Outcome::ExpChange { .. } => {}, + _ => {}, } } diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index fe498767a8..0dc0070fb6 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -69,6 +69,7 @@ image_ids! { diary_exp_frame: "voxygen.element.misc_bg.diary_exp_frame", // Skill Trees + slot_skills: "voxygen.element.buttons.slot_skilltree", swords_crossed: "voxygen.element.icons.swords_crossed", sceptre: "voxygen.element.icons.sceptre", sword: "voxygen.element.icons.sword", @@ -179,7 +180,6 @@ image_ids! { // Skillbar level_up: "voxygen.element.misc_bg.level_up", - level_down:"voxygen.element.misc_bg.level_down", bar_content: "voxygen.element.skillbar.bar_content", skillbar_bg: "voxygen.element.skillbar.bg", skillbar_frame: "voxygen.element.skillbar.frame", diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 4f2e1f56d0..6d17cca5f2 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -56,11 +56,12 @@ use crate::{ GlobalState, }; use client::Client; + use common::{ comp, comp::{ - item::{ItemDesc, Quality}, - skills::Skill, + item::{tool::ToolKind, ItemDesc, Quality}, + skills::{Skill, SkillGroupType}, BuffKind, }, outcome::Outcome, @@ -77,6 +78,7 @@ use conrod_core::{ widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, }; use hashbrown::HashMap; +use inline_tweak::*; use rand::Rng; use specs::{Join, WorldExt}; use std::{ @@ -177,6 +179,13 @@ widget_ids! { // SCT player_scts[], player_sct_bgs[], + player_rank_up, + player_rank_up_txt_number, + player_rank_up_txt_0, + player_rank_up_txt_0_bg, + player_rank_up_txt_1, + player_rank_up_txt_1_bg, + player_rank_up_icon, sct_exp_bgs[], sct_exps[], sct_lvl_bg, @@ -293,6 +302,13 @@ pub struct ExpFloater { pub rand_offset: (f32, f32), } +pub struct SkillPointGain { + pub owner: Uid, + pub skill_tree: SkillGroupType, + pub total_points: u16, + pub timer: f32, +} + pub struct DebugInfo { pub tps: f64, pub frame_time: Duration, @@ -690,6 +706,7 @@ pub struct Hud { events: Vec, crosshair_opacity: f32, exp_floaters: Vec, + skill_point_displays: Vec, } impl Hud { @@ -789,6 +806,7 @@ impl Hud { events: Vec::new(), crosshair_opacity: 0.0, exp_floaters: Vec::new(), + skill_point_displays: Vec::new(), } } @@ -868,8 +886,7 @@ impl Hud { .graphics_for(ui_widgets.window) .color(Some(Color::Rgba(0.0, 0.0, 0.0, 1.0))) .set(self.ids.death_bg, ui_widgets); - } - // Crosshair + } // Crosshair let show_crosshair = (info.is_aiming || info.is_first_person) && !health.is_dead; self.crosshair_opacity = Lerp::lerp( self.crosshair_opacity, @@ -1084,17 +1101,16 @@ impl Hud { ); // Increase font size based on fraction of maximum health // "flashes" by having a larger size in the first 100ms - let font_size_xp = 30 - + ((floater.exp_change as f32 / 300.0).min(1.0) * 50.0) as u32 - + if floater.timer < 0.1 { - FLASH_MAX * (((1.0 - floater.timer / 0.1) * 10.0) as u32) - } else { - 0 - }; - + let font_size_xp = + 30 + ((floater.exp_change as f32 / 300.0).min(1.0) * 50.0) as u32; let y = floater.timer as f64 * number_speed; // Timer sets the widget offset - let fade = ((4.0 - floater.timer as f32) * 0.25) + 0.2; // Timer sets text transparency - + //let fade = ((4.0 - floater.timer as f32) * 0.25) + 0.2; // Timer sets + // text transparency + let fade = if floater.timer < 1.0 { + floater.timer as f32 + } else { + 1.0 + }; Text::new(&format!("{} Exp", floater.exp_change)) .font_size(font_size_xp) .font_id(self.fonts.cyri.conrod_id) @@ -1116,6 +1132,90 @@ impl Hud { floater.timer -= dt.as_secs_f32(); } } + // Skill points + self.skill_point_displays.retain(|d| d.timer > 0_f32); + if let Some(uid) = uids.get(me) { + if let Some(display) = self + .skill_point_displays + .iter_mut() + .find(|d| d.owner == *uid) + { + let fade = if display.timer < 1.0 { + display.timer as f32 + } else { + 1.0 + }; + // Background image + Image::new(self.imgs.level_up) + .w_h(328.0, 126.0) + .mid_top_with_margin_on(ui_widgets.window, tweak!(300.0)) + .graphics_for(ui_widgets.window) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) + .set(self.ids.player_rank_up, ui_widgets); + // Rank Number + let rank = display.total_points; + Text::new(&format!("{}", rank)) + .font_size(tweak!(20)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(1.0, 1.0, 1.0, fade)) + .mid_top_with_margin_on(self.ids.player_rank_up, tweak!(8.0)) + .set(self.ids.player_rank_up_txt_number, ui_widgets); + // Static "New Rank!" text + Text::new(&i18n.get("hud.rank_up")) + .font_size(tweak!(40)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(0.0, 0.0, 0.0, fade)) + .mid_bottom_with_margin_on(self.ids.player_rank_up, tweak!(20.0)) + .set(self.ids.player_rank_up_txt_0_bg, ui_widgets); + Text::new(&i18n.get("hud.rank_up")) + .font_size(tweak!(40)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(1.0, 1.0, 1.0, fade)) + .bottom_left_with_margins_on(self.ids.player_rank_up_txt_0_bg, 2.0, 2.0) + .set(self.ids.player_rank_up_txt_0, ui_widgets); + // Variable skilltree text + let skill = match display.skill_tree { + General => &i18n.get("common.weapons.general"), + Weapon(ToolKind::Hammer) => &i18n.get("common.weapons.hammer"), + Weapon(ToolKind::Axe) => &i18n.get("common.weapons.axe"), + Weapon(ToolKind::Sword) => &i18n.get("common.weapons.sword"), + Weapon(ToolKind::Sceptre) => &i18n.get("common.weapons.sceptre"), + Weapon(ToolKind::Bow) => &i18n.get("common.weapons.bow"), + Weapon(ToolKind::Staff) => &i18n.get("common.weapons.staff"), + _ => "Unknown", + }; + Text::new(skill) + .font_size(tweak!(20)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(0.0, 0.0, 0.0, fade)) + .mid_top_with_margin_on(self.ids.player_rank_up, tweak!(45.0)) + .set(self.ids.player_rank_up_txt_1_bg, ui_widgets); + Text::new(skill) + .font_size(tweak!(20)) + .font_id(self.fonts.cyri.conrod_id) + .color(Color::Rgba(1.0, 1.0, 1.0, fade)) + .bottom_left_with_margins_on(self.ids.player_rank_up_txt_1_bg, 2.0, 2.0) + .set(self.ids.player_rank_up_txt_1, ui_widgets); + // Variable skilltree icon + use crate::hud::SkillGroupType::{General, Weapon}; + Image::new(match display.skill_tree { + General => self.imgs.swords_crossed, + Weapon(ToolKind::Hammer) => self.imgs.hammer, + Weapon(ToolKind::Axe) => self.imgs.axe, + Weapon(ToolKind::Sword) => self.imgs.sword, + Weapon(ToolKind::Sceptre) => self.imgs.sceptre, + Weapon(ToolKind::Bow) => self.imgs.bow, + Weapon(ToolKind::Staff) => self.imgs.staff, + _ => self.imgs.swords_crossed, + }) + .w_h(tweak!(20.0), tweak!(20.0)) + .left_from(self.ids.player_rank_up_txt_1_bg, tweak!(5.0)) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade))) + .set(self.ids.player_rank_up_icon, ui_widgets); + + display.timer -= dt.as_secs_f32(); + } + } } // Pop speech bubbles @@ -2782,6 +2882,16 @@ impl Hud { timer: 4.0, rand_offset: rand::thread_rng().gen::<(f32, f32)>(), }), + Outcome::SkillPointGain { + uid, + skill_tree, + total_points, + } => self.skill_point_displays.push(SkillPointGain { + owner: *uid, + skill_tree: *skill_tree, + total_points: *total_points, + timer: 5.0, + }), _ => {}, } }