From 3d11ab73f801a9e8a77eaa3a8551eb0201b3aef1 Mon Sep 17 00:00:00 2001 From: ppi13 Date: Thu, 22 Oct 2020 05:38:32 +0200 Subject: [PATCH 1/8] Sets correct sprite for the white east facing beanie --- icons/mob/species/vox/head.dmi | Bin 40958 -> 41018 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/mob/species/vox/head.dmi b/icons/mob/species/vox/head.dmi index d73146e4e7d0b7a70baf07884769d8b0f13c6760..223dd0337c44e0470c4cdc1ab48000a68058cbc3 100644 GIT binary patch delta 19731 zcmc$`cT`l{_9nWEtYjtUprELLqDTf21O-INNX{xb$6_N{GN=SWq5_hNjKo4vvIGf* z6hS~TMUg{6QEzk3x&6BP-SI~EukRa=Kd9P!?XZ|@hHuXKEl!a{4Xs4wz1m>?J&H@l zmZ}tVJUXPIE)~nKbm<4Ri;Qa`&s*k<``s(aHdoVZ4jT27<+(z}SjZQZtWEl@;fXSg znCKlFuVUAQ_RG8nKk%}k`gHgDW0_6gdK4|P8r2E==XEup7j$^#Ga7Lim z9?{82?{UKizmk%oF)X5_sP+;FJP3`LMe}#wbe@*6xwG^mJ;FJjLtk!3UrQ^vL7T=@ z+L&pv3Dwf;nd9-a3p@8?) ze5X6=G(-GkJ5B){NU$3iNOLDL}S>jtgxX(E*D2jM@Bbfpv^5H$Ea0OumqIYacgK)dTM!I1tGa1;>b<$VQ< z838vl&S^{TC@U%LYJUYD{OBN1CPhXT+OV`nLO%@l`%6Le(9hFe(Z4>gb^s5Ql$1WQ z5VJsM6D_ICp(CZJoB!oO@ZaCct9MsnghOrdI=yMHo^XZXkedB%n;r&wF0Q!9NQ!EE zG}GlzpIqvVuZW0rHey@saS{e5GsCfWr>`j9zdzIh_YaMT$TLCLc6mt=PxrpPs;y+H zNc8BD+EY{0xZGSm9X-9dym&dShJMiN*bnwG_tdQ6bYM2s)=xwaCGRZ%d9Wp)n5Hu> zXy39f{=&q3fqk+4kQBk9+T;=`?BQ1hT6Py>!0?WO-i=LpG-v*Sr6*idjBxyHC`W@% zs=6ZQzJ-woW!b%^QZoMchfUT1KeCWUv2r>D=|`tO89>S>twaQD$1Pd(XMmDzQFOM- zEY`qfKHLj)AkWt5mfdTEdbi7#{@;jzp7TAMKgeg6XL$x+nRjPgp8IMhO98Olv?8&5 zW4U(>{o4BFoi+PD5EXg(TFQ9e>enjn>{-$058#H{3tobJd^?AXtsNqD(OrRG6>bM9 zX0JE0Ikc!u?aqv7j0gv#i8E_-9K7dYfoJom!pgZf%8OssqvhRRB4#8@?la`uNcZ6``*L(1P*Cy+ zMGd@Vd^_8%l0{OU{(61shCl})TeRXI%lGy3*KUgPQgP-rm@l_7@Hmk)nEKLst&h_WN)>2kb$mu76W2GEA1ILZ zGcwNyRo%+IQ+TvEvn@p?&=ei_w3}<5dt6Gf)#^mdwbhWy{FyoB(<=27WjZnerTSP< z2gy3_Z|?jia0Xm-k$A8BBpfj(dk0rpXz{g2aa_ZBLfJ=A6i{H8FpnPV?|Lh3zd6hK zasW27n{N_o#ze)Sh$RPv`t|aJL|k~+J3e_02{2KteO$1q?~f$wLEiChPJzUcX|&G) ztu&v=HCjM)Glh7H<|K$I_z&I;xpT)ffbgAZpzC@XSfw-x|1lN0&hk1z)NzVmS}C_A zo9f8$2ndokLtgYX^c}CUO*!>1BVyJIXli?FSa>Wj9l={i1^dkz1UO0u;Mxj+Amk|q zk?P-WjPx^vv?l?1jd;fMz^uT!F-x;zp4UQVkcIaA(|tR2@YK-6?ENj9DAZ?jvuA!c zQj0(-4V%6Fx`vjICdZ>+l1=kI6+PBAY{r+CiQp}&n;*{q9QSn6@``lkCVuQ`FyObWN3)S{aD0 zGRbn+oCFwU9K9l~AC8jqzrn*x1=z-<=7<93~rvc7ZVimbbEwlMVE5Iv*kJQw(cFULoW)BZ2}U>A7AM0fNc{R2Y_KW?G9Qjc00pTLCfPW%uOBBc#yR!B)TZk`s#KiPpf(c2D#zLq z87WM28bG(^Vs%KgD=ID{dgFuH{n=ihM_OU;`5c-0U!Hk{tGDVplHRE~?0~w#&_mnN z_W6f0UF;!|SF1EVWdXp=`vu`+16rtzShOsCNj-zHZ+b&X$vO@aaJCl&6yjSl3L9r` zf5p@wX3u>sSEj5(fE~xW6i$e+dq&kkSE_SrNv=!>75^wRYJ%ybl1Gp*-s?h2-F_;+ zvMMmL39vsKipX;3Dce`LF!;5EMoMTRmMUSxh$Tl@sv+ue*Qc_|Lv(;c9O$O5MI-f=$j?aKi{1(`YfxRf=O~eO3-6(nB<1wXT zt{Mj68*8Mw_L|!EZJumWUdfA0k~CSwqIXC}Mh9*2tKlMrAI9GNDv-}x9~j@4;<^AS zNJ{{A>^447Y|Vdcyiu1@T4)B(w}$bQxfIUEEbj4a_!K{ZH2~#EYxf7GWS-j3i`nYYu^}ggt*Pht?21t7w_9u*b&QGg z8wBX-NlmMWSw4!D|KObL1>OX;caiEdsH59@NN&gAuR%gR} zS~0K~=&b5ZGEwM=?>qSaI{JS+Ncm!wcB5hIK_Y*!Yo!1S>CmSug%_?A7Aa52pS}>Q zy7v-%UpMWi=7F8&JOgm8uZT5R-w>12LFWk|RZ)y)JpewvrFAG^+rG=uQcwrNQj zwmAOq(8nPV`y#;oOPig1M;7VovD5SVf@{Lm7v}|KV=^)_9)QV_k^R`*OqfxvL)!C` zg20BoPx_|5%IcXitn(eQ?V;x`(lIbFY=SMp!NK34BT=VGiL*gO({_~2+SwcFxw&bN z2E-IjM%Mh3;6PCEGR1>9HqYt6I4+Zr-@ncAUM?=8(0BJ~Hhz`Z3uU?drhAc*UGm}) z?L!~An+9!LV`lBX29x&qmp8Ojd#q@=&d1)(RZ9_G9xG*+^4@^ff#MGcLCeCzD?IQT z=NZ#)9UW~8ZnJ%9ViLaFmmX)y#m39wC@7hQbs9EqodB(e?S!^PH3B7&@a9dPwRp!W zj(X2h$JjV#ZqD*;N(%oarSv~E=g!^J(P03xA;1chzZ?}}2l_H)jQ|B}>yM|$qoboh z(CX?-2p;hZ2|XgfLH=uF(z3E9*0#2*b#LChNqqmlsD!+D?RZrs5d70f{bjG#CVzK( zzkxJY6ZskEcny_yn|+wc4_|S|cTr2bL)oTu$FSV|l|FZGa$42E@hvEgK;Q;s4>HX5 z(m7hgX*h(UkVeFRHrl3%Stax{UK96Q#$+{`tN_=IYSoS1!0yYbH?7Ei{`~2J-$Tv! ziXguY<*B?Q;VoWczhTm#^R2TpueO%y+_`g+v9aGF{YZTKHZ&uHV`OB6Fd*rTKM@eepliOf716z{lAQvY?&&<4}D}VPc3PCrve8(JQag@id#57}H91sS) zB9cH(QDI>kIBxeIl+ZZUFEH({43p2!&O+E)sHbr>>z2*=q@<*`V=2=CI~uOL%TGO4 zev%#?9ZC4_Uk|5Z4c3%9BAIINY!8AF|8|iGopN#>`Xa$WVzPpS&{DyLlOzCF@_Sdi2WyP_VS*vjnZI zV1P(jaodSt3LpRc)fkSWCjC;#BKsiCDWtHtb#n5ADXeD_w~+I?6$=hCfxb4cM8!zD zacOCt3F9l*f$Sza3E$d_dNSh|-3c$9;F>EdD|4B}i~LP+{HrZ!Q2~IKlh9c^pruW$ zwUjeY7$=jtMFw!G2eJn-$$;4UmvYJAR>>3AHu3x$4DNPQ;ruEz*_v6ea45!N=JSlO z--?CUYaXoK$9MBZGA(WDMKhcFT}0=5&!GoVcHCw$rMrswx;7vIn zxkMs_m0Nv&hxU+Lup$(AQ8o0#T92#IVb5mXEK$AR8p$3$6426GY}gwn6ommnA3t8Q zwz2V*HPuGVbR8N*v=|hXR_(;AJ~RoBiD6V#{Xz`3C<@YjVMW%VZqOkK8jzpF-Wgx? zB@D5$3}34puTHySby$Qc`5`3`6#@h~paGH(-S^zwG(U-1Y>&)ChRQ2hFBqJx;^?2> z3C8;#EEYPB`p5CYQBDEkE3{TdTJ!G@PVMYhBWEdC$1ZBiUE$gp+yWhnn+tr@Z5MCK zg6p5pn|Ex^Kcu|3rv4!;aS!&}XY61(aYUbRUcnHqulx?ZtzF;wM0Z6oeUL&&w?UJ{ zVdlsg>Ay{7#_c>4&HjLP)ZR08ZDoIl-ojCRhK!QwI^DZ>?;_*k#!?uWnD}nr*7-$c z@celpYP+ZBk-KfH@TC;9K*=~x>F~Zj^$buB&IZ}Yc)h#eJ_a3Ok7#BRPp?Otjmdi~ z(}mJq5fW1L@sY6o@jh$@zu}#ay6YzO;mr0Ys$Ya8B+z{^7Iv8YGF19X(tR=V-8FsO z6r=}v4w>;=y=JEuyc$j3CMV}MG_dLF>MoCb)>hN|9-9&StK!JQ8vZ71eB9t0*wJCx zHiaInL+mT2BsEYivz3L#md)ZEXaO05UYOk4ybv}XzjD`VH&s5bq@?8GZ09Pjg~jfV zl-GJ8c^jAPhT=>M{3dR3kAf{Z*i79hhY&}l{-bo|Xs60z$Ksm9Www9V6>;;};93v2DX)+eB z!S`BE(sitDofI6Gd}MuCJ=Z*#CTuLa^G6QeW@ZX&X=^*)3bnE2Y8R8`8fs?-I9UB% z`XW5#mz-nyt!U@Q=4R1F2ORBO`%h zk@q#qt5MU;ZZd2B&@%7xJg2g-O)P-L+reo8r`ZB~W6g{n+3=;AlYWeMpufGA!b_CA z6T_|P6B^pdA=)6O6Kn1QxA^+KmwFUun8y)XAt&B5p&K9ro0ISZGxp7FZcjsq`Pn-I6IqXWNa)q zKc7qld2%Z_B*elNt_h(v1!&^X(a>jY!M+Sh?T?>6t)T4|dfwH3QcF1xB8Hwdczo6m zN|$uchh}lHr?>a1iAgLCr&P7aou-m!H9g|HQrI+*Wgef|8}MWDwnq;}5#h|h!4dQJ z?HU~;Qz*| ziQtgdJx49rIvMbXbKqWtR(AG{U4(6M=_7IgvH8xC{kK>`S~p9}pBlp;@r&WKT&z2F zJ`Vn%^y=u%?rvGvKkd}2dpkOR60zbuM;)0y(mSI!>zD|B=(n^{ojzm7qImiozEDSX zqbs-Ea?76&@v#HfO{<>(_gvmF&Tk1;hu|-2%JB9{9XdmoxM?oUpP4Zm>LO&7zl#cg zBDn@|T=fMz8r0l(W4KoJ(5jS*Gb`vN@U>tjohCw#iict|@65S>Z{fc;?tO{V5nb!) zZ+s*+5tF(PkN?=>qN_6-KD2=fOS`8#t~Hx`-aPh4b*e1!XoZzZ9h#Js^!ZGSY+GBK z%VHm^w!Od5_3KLLTE{bI41vRO2XSZ#{qU1*VU&)@qaV)St|6L!mc$MZf>;J7rre^U z^Nfs)kx@~Kj*d6ZQ&Jk03$)aDEG}9iu-y{;DIY$RmXsCjkXC;CreqD*j^a$`?igH4 zCaEr?QmAdxvTiwMC5vZ!wXCH8be%kBc2Hgbte;TIU|egw<&u+$+~zJnbphdsVWaXF2d-tx^g%N>W?gF#iEj5Le*&=*PUd?nJW*S6 zmD!U2WPBa=J7bC$qyXB9BOc7U0CCXK&Qi2p7JSTJ<-LS!ZUPGIOkLQVZ9jwLkZOiP zaE1TcHA-2(-B!pQ4i)Q*WJr1TjNmjX9Dd!JJ#y+>3`c|qE-4;OR*flD(yn&yc1q0bnf5%EpB|!>O~TEgC<%+TP1V&52w^;9oE_X5s#_GW#eSs>LOB+* zXiC1UGJEy(*|R8R_o;)dogW=fhfQ?2zu|U=H9>S7XR$oWf$AKT8XO+a5S&&izaC?e z&b__8A?>r}n28!n@pS6r18nD5sgWa8=x>8Y5$mmo-GW);kJQwj8W}}HaDgI+Gpo3$ z2!aZU0KaN`rN z?LG^W8YC{4#{wmY$Rl?K;7-e_uJ^RUqjy)yF?4U@D z!ZaWj_aD8FUNuPoT-vGcMz+9@=fapx2hFH51GXQ!{^_D;L4db<$1AM9p9u*Hdk~7r zf#3>FM7wPrI;=fsF;60<40-BD&%h808PTOnmv|&4S>;bQLE_WHPI!uOrSylfBX<}gU zM|vmx!X9_VL~it^#)&y<@mApJyDf%azvcE)OjD0&no?4JFo_k!dNyuO9>OPZrH4~Q zJEsbMzP}tmder3y$SH9xX{^aJy(kDyIJ)dR&m{6tZD^zaIPz=WW2-ApEU_sOS;*|a z>&bpHV(bB<0`eb!5F(>u3Hlz*jFvk+wAxxNMhJa?H$0j0UHWjA;~qls-?FFn5RU~# z&Jx+X(>{5l&h}c^v-HTl%4^<7xLgz?0D!G&Vs_=YSrda)uZxi9aot}xY&zNQosGq`B?O$jJ9|xzy$W_!drd zm)=BT+Oz;~=0Yrm?f5Fzo|uJglRaqZLc#bN3XMnps+cTWdOU4D>y1P%7X(hXIXaXr+7zYPSF49ug+jn%BEEjD62m50-h}$ zqA{$d%@Q0}dvN6qfmY4HE3Aqxbm8n_e9e8c6eH9nGM?})Xt?PM$ z`934(0BJ4u0i;xdxp{d|DlzM6=H%qmN)rcFA}_kSx|;Ty2s1-V^^PmlM&#?)uei$h z@81WNVUMmGlq-Du_RVK>U|>L>t4$|1x(Hu#wVL>zP&KF}736W5oVa-H?sRmukU9Rj zr|t0<6}%s4bXIG|PDLNh=f0G;kNUGYWLc2MPG+JTH9PWVU-&qqY0rS250er*-mG>$HgbU6mJY50ZkD~SebYBs}>EK1(+&0?Ok3VTuxGr zV!w=wOPt)7)I+=u!|PQQ+h-IM!2p|u4KrPIdBwH-$8sw>E%lUq^fSImK+p@M{{X_( zkWjgQENRDAVfpK6O!YCi!Mn$ND$_t9s>d67oKGsb={RvaF*UVtroX?x1Gl$!qn<4L zP9+*eIiRgT(|Owo)CxY%sxgK81uqXbpVChA3kq$mMcj2g)~@GBvjCMKnxFcNnNM`XUNiUcbFci*_;_ zIMi-j?qGLjfa2rMGp^;pfKvB|56{Wrmign5bC5k*cKoGoZJ9S`>_2c`9S~Y;&$Kvr zI%Cm&IB-yL1Ni+5aHiGud=Iw$t#=+3@yH*uF1Od1liF3HKg2n)co>GZI1uWDW2&=s zxE`FHofB(rP9|^QHe0){>?v2|(F{dnp|GSN23c8;QP^gW_o&h;ZVxHz}xqa z5xg|k!Pse745W%Ayr=od#*|O2s;TQnS8X>=s-+Dd(S)pf(XNkqB@><4V26Du<*`Xh5@jcTqx4qIhvC;L0t z^eX+1jhYD$^!W+*@DIfs%M%D{)hxYu7^Wrl7^fXy^C&n9G|Mp z6&hovJ9by->eYJ>AHGIcR@uD@i9pYaTytUoPBPEcZ#}>qpurk@ef_+Ti8D{y|Cast zFRAreN0)0hM&%h58Yc40g@SfofcD_h!kVkuGaSR zlhV>ZlAFjcC?LLiX3WBo80Xp30zc!v$$|Iq^A~`>?NwF>3IC&XIS{`opw}E1k}FKB0sB|9`ya|1Upr_8Ra%$R+sipR4rI zAW|N=`<0xVV!#F}X;qajU~d1IsDY>%nptuthWHLY7|~2T)c-u)&#j~_K9J8FlQ@lF z`qk{WLI}NY$PM)iOPF~!@r6b6&LSM3xBSAEcfGM`GZbE~{1Y;7H*=@A&py}tN-KA$ za7j>*Uq;5*Ob=ohK!ugdy-QBkjm$^AyGtvX-6%2A3MuUZJ&UsSO($2|RfZBd!iHg(^N!x{ilOGIe)%-&0qo z+TPiLbEWF^3=DWfX`FnfXNfh`H1;EiY26Vn+ONv*awn>oRmfCMmmm1d8EV6wEVbr} z?tJz0trXMWR$Bk`uL}hZ<@kx=+FFyr36DDCINQfv!TEB}UZyOV>g55)!HmF@^XB9< z98hI8H&9wyn*GeXF6EpgrKOz%B)m5=(E6iLmiEWp7lOyomycQE+uq@dr-Ao9*%}9~ z>p6qaI*!g;?guW?N)ppkV$2JlIY8PLlxGd^NrFy%^si$>_wG&Nkpa2SyO7BI_SaYTN6$Ylz;a?CbPshGph_lP>yf64 z_%XvJ;0*AboGi(soWY}o6a%R0a(T)8^WN;KU8%;wgfe!2uP&YmcG0wQk&WXe{0qTw ztt*kAk2mL(qa1?xS#t0%co6?v|F6azA7RVt%Kt7H{8tz6zaBmRWBtGDA3w`4yVXOm z6ml80tu^zYh|uxBkmr&j8)4MF)_?Do{lfFJ;EAj-4Qf5eD~bb=%`PWX__v)i7Ipr6 zmfjL?_lEja@E5}NVsEW`4LRrUH;Y|9R~Oq)6dphwk#{K@KaRnWv~UG`qTeJWB$5J$ z!qlo2=FO$kr>`an5OmEO;&!Vywp{-L;Z)>6S8Ih;=i7*^iusP&;}|Nq;mlhGhp9^C zhup#`YP;*dE`pFY?%L=%kpGH~a^0%wPb$I)mu6O(82|DtL2V-*JL;r z_ptlK>X?EYPq}9vbap24LbUQ6gq?#6%dSsrvhIXo46z|umlo4Ox_!^h6rBjsflX2c zT62Jiscn7VYeEV|Dhecri5Ay^*#}60fgqR*rK}z(?X}L*5yu_@nc*Q7neFl41|l5k zm|H|XAf@MUK>1z2pmwgO%xVvzC-ux@5L1gF{>188;=$_(7Jp`A);<1pB!PJJapNI1io;zzemV0%^0LZ7*q3x-$Rk05FO_K-?UNZKgtre~ zHPDIwvH!is>%>d-q;Xo$nV^6LHKa%%Zp3j&@?E%aVHfRb(V1iqJj+|cPF%^I@ECMH zd*>^Zp!@Ng3zLKrn>xG5mF1in)985@39T>qhp!dD4e%ch+y5`-#{&M%v-{sj0RO$s zU;p@t*1WFn;-MeKn4_km;sYk&cjIlI@3ZAKU!+5*8clZ7Kf|%=58E8`s)BgU+Gnqv zd;THcWgNt`xu?mtuKCNY!AG+4%m2Gf@#(LK(c`SA_8bJv8ScI1_YdwZyb~v%Mc8{b ze<&CczrT99DxlE}KF&cCF%t{fX7z(rsE?|xm}+-Olua%QJi4FS?!-(Cc-*}%4g1YA zB6DsGjp1Wduxqar12_P1@yawS3XQSkn5+w{KL5(!t)ve9-GRGT6BxhHDy4z>-t%`} z_BSN0fUoMfzVIOd%%22E>@U3~253?m--hxSf=>dzv^ao|>nm{&0#5A@PrMJb15cp| zGD&kzi7r=Cz<)u|ljVi{iav$?(ABP$u3;q7v6=~NvQ|iXb(Jn4T!dS;(4%d>_>t~8 z$01II$5W`H(Avn#Y}%F3PGofRV=LiMjPt_j(&w63c|aCm4M}*EWt(CSK9-dGAzbmX z<*7Y8C`Xv8sof&49<(`G6+u3}*J6tpEckt9gAoDL0kR~JA8TvCJoJ0AI+i=O+TBS^ z1c+Txo%Fx2vLdIoRWLShFkJ z2hlnBPs2}WrB8e}nackP`jCBA9aJs)6=VZ(Nw}1L?a|R?Zm#^?+kj&&HQ-iUG}-dZ zLXEgrSC&xPx`f2J-gK9@j~lhO1nJQgWGVaSJLBs|BcmNd+U4I`?Y%b`cXm9TuUTfW zw!gD_t?}^9Y|v)sr`EV@rIO^DrL+g~xnt1-pnWrLmt?5GzcBE)>-D1(+^ohb0(M3+ z$zA+khK}HWl1%zP0>J+zj_SXx|DRi#EIo-Kgg0`V7JoX>=Kf0z^z9pawyNfi_0_@V zIie|s{co0ezxb?X)?#_|CJst||KqwQfvdxGo(3-_8U+N%V-2k>AOl3$LpxO(Y*iPB8l8=w|R4ES$ zIhu}(i$+0%B8m57QxnIXJ46aMs?j#8{&-~@^jz(VcXVXra|&KM2J4U?OrcOCPU*o* zw7?)*vCJFlvlbN>^D5nVX;11P&Td?$SYmYi-fRydlqEy8lXVY|_Uzu(i%Wl*12=d> zhdU-4Lumnag)OKmQwbmS+J~4|TAv{Qa*yHV>*y^4+{i|LfPU!`TRK79#la zXmQH(mD+RPtVn+1cQ%-tg=1lW2MueeSVhF%f{4sP@Cux5t)SzCW5sb~>|ovIQP#{_ zohHLOV&K*Qrqe23{yGt392e++VnP2*hM}9290oMh(R#1l+w)6FNr3?nFJ~}cgXNK$ ziIbRu?X?@8_afPJbd?vnt^xpO@EMsvH@mi0&(K73VL_RK#)+7>nn%ZoJ#J#+S+zZ? z|E=HU%a;qw$`o~V>rJcj^NW<@R}QXrX?nlo5s+dz3cC~en#SqrMes%q!6*goXh!}> zY}KH96@!F|PGlxbuJ;@+>dHbDqkcO)ZjbNsWzxI{v2D>JEs@6?jkMU7}h0D|#b$%%Vl>2PW1&zXhV$|`e??Lo_g~jqv4LQJ5E5zZr)*|m;G_otov!*5( z)$_^#a|{hXY6rW{gxB6U9la}Fyk}!qtXAWkTm7qEAr#_N3gzw3$&XGr%%q7s?j1*X zH=}m$tjFskUMo9vvKdcYrv83&pW zKPW{PYiiQL8&HJHUVmrK`IL*dsfRRUGvGo!#X$&SxYa@3NT2jl8wx&+0?1jWDgOK&iu<43PJ-w#`~~aH7@Qwep1HUi>DnfC#0(-}}Me6|I$*yxs43 zWCYDHhVW-S<2;D5YMV98sxtdS+YgcWO-R_%U%b!|yV=nyw$m?}dj)CS-6)F9@Xl1XUw^TiG3$-1==R9b!{rYYK`7} z9VvWa+tO!VJwD^zQ~L8U%=7G9w>h5fxRS+0F7wUW=YuLXhg+U_#&+gJP=fgHy#;pv zAx!i?Q62wnk_7%g;S>^n6CVEj$DWaNaUBxk3jYru#9z+{<9n3s7%v#`nzzEKH^Lbl zU@9+TtMK2wR7ag<@_`&kU3a;%_En!ds2=@QU$%G*AH5=`bb+MOyj|BGb*0qN20kFz z%(&)ctt$_5fYhB?^N6Ba5e`DM|4BMy>)5z6J^uuSlKzJW9_m!*cXnVvm}A55jKZfE z+Pva3FG)=V)0=osIQm+o3yne3Wm%2$M9=xCmRvp?8rWg4`@p?rLr%0pe?jWkkF7kUrGE4>fYU07C`{#hY zd9%0hwzIuPe-3-ON(Lu7L1QnbAlw#r$_E?VVK1B8i4CpZbId$<j{e_F0-*;Kt`jCn( zsdD!jq^h=9gP@bU3%5d3q0KONUY~PB=#Q-+laHo#y%mQ;@Z$Z5(+2j&8!dys$K-roirC zC*kRmE6>e`-G}n4GBm(=QtC$$NC083K&Fn&snLZulSB#Y-F;imh56?LP8%t|?I61$ zhsD$cOk$sSe{CK*QtYDi!cvZCthH}tVn~lKfvz@@$0g}en@iC}_DJByy78OTAo#@C z2GK}F@N%dU6vobTxc!p*4$^l!&e|Jh=YK;yYwWP4YC&BR@Cnm=$6IpcICNjpiUq`n zUHN(v@(R(KBcd&HimTnM=!@A(iO2YEK4op|u(5kV4sSo~eNrxx6S1-fC#8X>&26E; zy0CZ~+Zbek!@%a}TcKM=W+HS01Y0C!(yDK`TygN{^KSbO!=sh^=ZP2Kkmx1MGg!su z5p-7YY&jnm;>ff;S;r4vjV!Dj9|s<=`rn-QBN?ExEh(PEksqN70$jK5oNkL)Rdtw+ zk*}I9$A|>mjvZX;G&?1ASpVL)b+-(xD=B_?!tKe0Y7awfrHEPC#v)5-N62ZdfSXk< zf|93h;yvThY4gs;&W0%igy@5#nG#k}w*ze&V~trC37QGaKCEcfmn>dpwpo4jy1@&L z8*!s!%X_*%lzht&?{wmkcAH%n6-qj9>4K!aTUbMVvr+Z8OXB58t6K+DT)tqNf7BKAcUGIx-i=RTu`sCJW zJ@sT3kPzd);fxuuciFg`ED`HDZbQIQCMJq>uAB;}Q zv9vDdzHtZ9n7QaTl3#AiaYeYhx#-sUd_#x{?hb|tF4dxyyB`V`&0QQ6=zQ%pbpi5> zs{M|2(e{sR*XrcglDoE?l>;9Q{HufJL;YXbk_Y8q|M?0$)6bvehn6@hizYa<(6z~O zw%WVPL-!H>Cx@<=?}&WFl}?=;EUlsmzg~ma-a=K|)d3UV6jSf-87PrRe1BBt29gli zyhth1lpP>#U;=i;;80U{>_?gwO;u$%K<8%D#?Fr~dQdZ~IJ1&~r+~s%@_?w*uz*?z z*c*C|@8#qjh^@akSx_BOgAL4eCah?e>9?Gw*RBt(X|mky!{W{;`hU3hsf++nbX*`o zzwS1r_+{92Vd2NS8V`q@!K}nrlat0aA?BWNz(q=P*(xz%a4JbKTUT~H?e;@sR<5#{ z)1oGh_Gy2tpc%N))A+6D10xP2$=?nDcO4}oXgfW1m;x8en$)`9L#@6yzu*+SN>Q^% zDT#@&^dI>SC#7ZbRvlCo_9##ozaL4@4*(*~yB9Kj=FVL=X&8BH$|P)jh3Uq#P=9PQ zGxUIvB08^==Dl3hF=5b|Ai9No7oJV<-@m%m3nz>@6X2T*hu=?B-i{J17oz8oUK?J; z+}lT7_*%nP4v;`_Yw*3%cJoOx0-L08KcA2 zmeGIFa>B80tqz6o@5KaGwI$qifd$#o3Mr0fK76Azk@_4^c&@{)!=w)bY@M#@TnOG* ze}Ad=l$X`UZuPzjXuTvFgU?deUhCbgF}D>|@)`?9l?YZP&|L^76_d6YA!H5`CmO<3 z`#q+r7dX65YNeAueF&>+U@PXnp zoa6oW^OM?B1A{`5=(xBJi2e3%BxTlq?%V6gxUo#~0ht|;%F@c}jP}Svtd&ian6Z)s z!{QHSR7_2|xcruR0R@OMJq;4zmw6oqK0eHS*>?p{NOzQmAlOqSFl4yW7=?+KRKb7~9z3#1qi>g^iFK zH((^fk=?&-O6-m8^bJ|_r@W-c5dNTADreiz4yE}DFnO$*?m2Ilp-HTK{Ob-;F-nx- z-Om@9WYS21E<~xadV&}0Lgm8`>ZRatvb(`1dgIH%s4@Ik7Q&Gd@L3-HR zoeD7!9T;v1$-N_>p*X7A z`Yd0L6ca-5wf2-KR?&i;&{R>23(x`&tjX0+_5nO0U8DN(B!I`pB&%J21`L3>{Evaf ztf)8WR#hijD^XG+v1<#GXo2>!lBHh}X>0P{3np{W;;w#eR~5dyvzsEbx8IF%g?5GS z=M-Kq0!aX4f?nB50jy3vmFLX7&fkiLDbVI_>wL7{r%J7MvkPMiTgTR6)In)z~KHdLxNsLg(|t8tBX zn$cQ~jymlfP&c;idV(wO_V}(@N=Pj_?KNPHCk-yud(BVJq-=|9bTJz8~3B ztIb=Paa6lhEKk6RA+g9b&K3Ye`XwiUzdbQcq}5+Q<3jqPz%s0>5R#ifiOc&yHpTEK zR-2WpmI16?G57lVOrxTsmGAR{D&hQM_k-vZWwyKc{WfnxXWO+kWk0Py6J>o6`&Di9 zj=`-2){xYw2_pe@x&pG(KD+V+Ufw4;?J2Tv1YUv>KX}u0PXZZM&eT zsD93bdW*`+P5iO)W`N}{Hy9AjG&!%k7H~k?<7_s5l~2m!ep0W0?Tu@epoB50U^<+w z`XM&B=_Q5@%{**JaY3HGJ{&nm6ar$RL*dCebC0b;mPy@&khprIoFCD#4r5m0Mrlvf@ehcXhU&p-$HqcvXp!@ zfK(Q=n}(X*LEwaT{Gaq;-?rW8X_0U)r~xc2{^RsgfaEc>Tl)7slqIv`W<8xB6xJHX zZy$#kEPOxwyI*zsLhrA>ac=TF*rD-XMseVO_TM>#8B786L*Jjjof7tv;1Dl9E^iB~ z-eA@e@o=p`W0J?}Bspl1fv%XwEQ%xi?p2f#Sh-{LtDQXEbl84IX4Yw84LMwK4=k>;??=CzY;)DTWfu12(i7OYKxhVng zim*(9h%~&L`W8LFR--p22DAWQYx6aq%?-a5O52q><-2T`zC zq&x}({jt-{kM1X!&e#%%J~8D63n}Fk+2fl14;rTI^h7!a&jC1=afhCE6tcq+f_A9n ztw;B}=7tBNHl{A@p#>k?8a)F|2n$XJ*m1jlgBUgkZ*~HjW-1TFV#U8K6G6oHnYVk2 zN%nUE9?0_nJh}H}j7cSN+y0=~4IbjHpV!vHO8D&omts))4=vCK(pqpk_-TCej3ou2 z|BAtTyP6u{Inc>WN)u%beDHxiSL98dE(x6>0rxX&tyk{4J5QxM3yv^|!q^el$i`H~ z0xpH9gDcY7uhRK2xXLrhSpOxL$C)zcfyk9{`lF?4d9nu2wbDzW-J3gDeAY^@FtcFU|iU5AjaF4YQfTokbovcLZH zLhxi;iuFATv2b217Sg_RA2W0G#}ai)8>!5WQufDEzH`VGT@UTXb!=9Y5!^oQHF~Rk zYx}*h41PX_cR0E|$JoO#p9s5+d-xlRn@{VGX*fZ$fkHg-arH(OdY61@Tp7J+_+mC*oH%BgX&k)4k#n9VZI z33^fh)sDnKy6MFm)PF4n$LgLe;Mfc^KcvOO0PftDh;(z6%SBCr@`L->5%~k^DSJ1A{G~u6CuE z8j4i%h5P>q^6Z;h-FH6==ofpF8=HGFqS+}SSaH3(M%rA=iTdazN?^+(jToOH3+;Us zo@H^0s-Ewmzo@=;ub%|3_R;FmBnu?#Gm$r?H&PR9)JU@z{chKDhBF_aQaB;uHelnu zkL#uFWatu1r$K|ACiGzz%iDQzbglGi!U~#e&=!P*OkyMs&U(&#+0vhF#0K8>Bzw?L zLf!c6cz9TXxNd2u9U!{9<{@`x@>FaAz9ySQe!DBA^N!smtmWtGPA(iD;MqIlPkwu$ z*MA|P_IrlNliOaPT5KiyyJ`GyUd;csySv4mw+gJtsTVtETygf>kDU%*llGkBW(bqq zH{H?aC{KdVj@XjfcceF-TO9ZOsp^+wCwtu|#^>Gp*3Y@U`^#(Vhtn_0?s@mSI*~ER z-ZDGuZ`&^q-j&BbK0dy;?wsI)kK3zz>={6PZvGVA$nw?c2mb8ih;Q4_!S|8lzaFo{ z1E%og6b0?~=E3#$PczGYFuiJSSf5b1?>E!ae_xATQl=Mdf1v!f&#Gn9<);;ix4cx7 zKO9_k{m8o&&K+-Lma*#_U%%^-_gc8QD4=W^)8X#l+MM%1At7V`srh`u#}|)ZyY}1d z_2FflcksAJD96MnzodQ#3jRyUJz(3ha>d;nyWgIv10L10J9bS|y_l8FTX{2{%?sZ- zl{`K(g(q%R)@g?{o}@Ik_?I_+oJ>ml7&-sop}g(gTUPkJ*jc$avsOmhKJt&|Hra+> zHx(Fu<=m0~?B%oe{ms*79&OG$%_O=*>apaBs7-g*@+H*G-*Ku-V%^z_r>nT*Caw8? zWYbe68HcdDJu|p?TYG>hAmMZUoRyqg4o_ARsg zN)LKZ`ugPCy}1P(=GrT&_c8yS+`atfmV|_RnI4aO`k&8cc$MCAWe(fazbm-x-8Rj8 zerCo^DQ*cZrV}{~t7~GKpIQE1()8+q>dC6jwJe6lrXu?obZdaeaXtL;|J%CpGsMxLa#=x-ukLQ^KtC) zA6~83E93Y#mflY~|98v$`wgL2mCN_Mo0ZtUW%UJb_kjD!NABD#^VrSRU&8X$*6qyP z-1aS>C&pZzao+LFhreqjfl^kJpz74i>m~lOy$NezWcaiABIC1g7Y2qzCLRU_AD~DJ zrvXEQ0V8m)w%P#(hC?h83=T6Gm>D>P6DU+0Q delta 19670 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 Z${+mr)ks;)Zvq1lc)I$ztaD0e0s!5|d4&J~ From b4d7d6c98e3d14d9a5bec23128d841113028b805 Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Thu, 22 Oct 2020 16:07:48 +0100 Subject: [PATCH 2/8] Fixes TGUI login exploit (#14695) --- code/modules/tgui/plugins/login.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/tgui/plugins/login.dm b/code/modules/tgui/plugins/login.dm index ae0ac9c028e..044ab46fad7 100644 --- a/code/modules/tgui/plugins/login.dm +++ b/code/modules/tgui/plugins/login.dm @@ -130,6 +130,9 @@ GLOBAL_LIST(tgui_logins) state.name = state.id.registered_name state.rank = state.id.assignment state.access = state.id.access + else + to_chat(usr, "Access Denied") + return else if(login_type == LOGIN_TYPE_AI && isAI(usr)) state.name = usr.name state.rank = "AI" From 1dfd637c80db396ee35fe459370be93b61c2d313 Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Thu, 22 Oct 2020 22:16:11 +0100 Subject: [PATCH 3/8] [TGUI] Accounts Uplink Terminal (#14697) * TGUI Accounts Uplink Terminal * Mochi tweaks --- code/modules/economy/Accounts.dm | 5 +- code/modules/economy/Accounts_DB.dm | 365 +++++++++--------- nano/templates/accounts_terminal.tmpl | 146 ------- .../tgui/interfaces/AccountsUplinkTerminal.js | 288 ++++++++++++++ tgui/packages/tgui/public/tgui.bundle.css | 2 +- tgui/packages/tgui/public/tgui.bundle.js | 6 +- .../interfaces/AccountsUplinkTerminal.scss | 20 + tgui/packages/tgui/styles/main.scss | 1 + 8 files changed, 491 insertions(+), 342 deletions(-) delete mode 100644 nano/templates/accounts_terminal.tmpl create mode 100644 tgui/packages/tgui/interfaces/AccountsUplinkTerminal.js create mode 100644 tgui/packages/tgui/styles/interfaces/AccountsUplinkTerminal.scss diff --git a/code/modules/economy/Accounts.dm b/code/modules/economy/Accounts.dm index 0a2b500a0d3..19e2bcafe0b 100644 --- a/code/modules/economy/Accounts.dm +++ b/code/modules/economy/Accounts.dm @@ -87,8 +87,9 @@ GLOBAL_LIST_EMPTY(all_money_accounts) R.name = "Account information: [M.owner_name]" var/overseer = "Unknown" - if(source_db.held_card) - overseer = source_db.held_card.registered_name + var/datum/tgui_login/L = source_db.tgui_login_get() + if(L.id) + overseer = L.id.registered_name R.info = {"Account details (confidential)


Account holder: [M.owner_name]
Account number: [M.account_number]
diff --git a/code/modules/economy/Accounts_DB.dm b/code/modules/economy/Accounts_DB.dm index aafc91cb849..dccab690af3 100644 --- a/code/modules/economy/Accounts_DB.dm +++ b/code/modules/economy/Accounts_DB.dm @@ -1,22 +1,30 @@ GLOBAL_VAR(current_date_string) +#define AUT_ACCLST 1 +#define AUT_ACCINF 2 +#define AUT_ACCNEW 3 + /obj/machinery/computer/account_database name = "Accounts Uplink Terminal" desc = "Access transaction logs, account data and all kinds of other financial records." icon_screen = "accounts" - density = 1 req_one_access = list(ACCESS_HOP, ACCESS_CAPTAIN, ACCESS_CENT_COMMANDER) + light_color = LIGHT_COLOR_GREEN var/receipt_num var/machine_id = "" - var/obj/item/card/id/held_card var/datum/money_account/detailed_account_view - var/creating_new_account = 0 - var/activated = 1 + var/activated = TRUE var/const/fund_cap = 1000000 - - light_color = LIGHT_COLOR_GREEN + /// Current UI page + var/current_page = AUT_ACCLST + /// Next time a print can be made + var/next_print = 0 /obj/machinery/computer/account_database/New() + // Why the fuck are these not in a subsystem? They are global variables for fucks sake + // If someone ever makes a map without one of these consoles, the entire eco AND date system breaks + // This upsets me a lot + // AA Todo: SSeconomy if(!GLOB.station_account) create_station_account() @@ -33,230 +41,207 @@ GLOBAL_VAR(current_date_string) machine_id = "[station_name()] Acc. DB #[GLOB.num_financial_terminals++]" ..() -/obj/machinery/computer/account_database/proc/get_access_level(var/mob/user) - if(user.can_admin_interact()) - return 2 - if(!held_card) - return 0 - if(ACCESS_CENT_COMMANDER in held_card.access) - return 2 - else if((ACCESS_HOP in held_card.access) || (ACCESS_CAPTAIN in held_card.access)) - return 1 - /obj/machinery/computer/account_database/proc/accounting_letterhead(report_name) + var/datum/tgui_login/L = tgui_login_get() return {"

[report_name]

[station_name()] Accounting Report
+ Generated By: [L?.id?.registered_name ? L.id.registered_name : "Unknown"], [L?.id?.assignment ? L.id.assignment : "Unknown"]

- Generated By: [held_card.registered_name], [held_card.assignment]
"} /obj/machinery/computer/account_database/attackby(obj/O, mob/user, params) - if(!istype(O, /obj/item/card/id)) - return ..() + if(tgui_login_attackby(O, user)) + return + return ..() - if(!held_card) - user.drop_item() - O.loc = src - held_card = O +/obj/machinery/computer/account_database/attack_hand(mob/user) + tgui_interact(user) - SSnanoui.update_uis(src) - - attack_hand(user) - -/obj/machinery/computer/account_database/attack_hand(mob/user as mob) - ui_interact(user) - -/obj/machinery/computer/account_database/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/account_database/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "accounts_terminal.tmpl", src.name, 400, 640) + ui = new(user, src, ui_key, "AccountsUplinkTerminal", name, 800, 600, master_ui, state) ui.open() -/obj/machinery/computer/account_database/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) - var/data[0] +/obj/machinery/computer/account_database/tgui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) + var/list/data = list() + data["currentPage"] = current_page + data["is_printing"] = (next_print > world.time) + tgui_login_data(data, user) + if(data["loginState"]["logged_in"]) + switch(current_page) + if(AUT_ACCLST) + var/list/accounts = list() + for(var/i in 1 to length(GLOB.all_money_accounts)) + var/datum/money_account/D = GLOB.all_money_accounts[i] + accounts.Add(list(list( + "account_number" = D.account_number, + "owner_name" = D.owner_name, + "suspended" = D.suspended ? "SUSPENDED" : "Active", + "account_index" = i))) - data["src"] = UID() - data["id_inserted"] = !!held_card - data["id_card"] = held_card ? text("[held_card.registered_name], [held_card.assignment]") : "-----" - data["access_level"] = get_access_level(user) - data["machine_id"] = machine_id - data["creating_new_account"] = creating_new_account - data["detailed_account_view"] = !!detailed_account_view - data["station_account_number"] = GLOB.station_account.account_number - data["transactions"] = null - data["accounts"] = null + data["accounts"] = accounts - if(detailed_account_view) - data["account_number"] = detailed_account_view.account_number - data["owner_name"] = detailed_account_view.owner_name - data["money"] = detailed_account_view.money - data["suspended"] = detailed_account_view.suspended + if(AUT_ACCINF) + data["account_number"] = detailed_account_view.account_number + data["owner_name"] = detailed_account_view.owner_name + data["money"] = detailed_account_view.money + data["suspended"] = detailed_account_view.suspended - var/list/trx[0] - for(var/datum/transaction/T in detailed_account_view.transaction_log) - trx.Add(list(list(\ - "date" = T.date, \ - "time" = T.time, \ - "target_name" = T.target_name, \ - "purpose" = T.purpose, \ - "amount" = T.amount, \ - "source_terminal" = T.source_terminal))) - - if(trx.len > 0) - data["transactions"] = trx - - var/list/accounts[0] - for(var/i=1, i<=GLOB.all_money_accounts.len, i++) - var/datum/money_account/D = GLOB.all_money_accounts[i] - accounts.Add(list(list(\ - "account_number"=D.account_number,\ - "owner_name"=D.owner_name,\ - "suspended"=D.suspended ? "SUSPENDED" : "",\ - "account_index"=i))) - - if(accounts.len > 0) - data["accounts"] = accounts + var/list/transactions = list() + for(var/datum/transaction/T in detailed_account_view.transaction_log) + transactions.Add(list(list( + "date" = T.date, + "time" = T.time, + "target_name" = T.target_name, + "purpose" = T.purpose, + "amount" = T.amount, + "source_terminal" = T.source_terminal))) + data["transactions"] = transactions return data -/obj/machinery/computer/account_database/Topic(href, href_list) + +/obj/machinery/computer/account_database/tgui_act(action, list/params) if(..()) - return 1 + return - if(href_list["insert_card"]) - if(held_card) - held_card.forceMove(loc) + . = TRUE - if(ishuman(usr) && !usr.get_active_hand()) - usr.put_in_hands(held_card) - held_card = null + if(tgui_login_act(action, params)) + return - else - var/obj/item/I = usr.get_active_hand() - if(istype(I, /obj/item/card/id)) - var/obj/item/card/id/C = I - usr.drop_item() - C.forceMove(src) - held_card = C + if(!tgui_login_get().logged_in) + return - if(!get_access_level(usr)) - return 1 + switch(action) + if("view_account_detail") + var/index = text2num(params["index"]) + if(index && index > 0 && index <= length(GLOB.all_money_accounts)) + detailed_account_view = GLOB.all_money_accounts[index] + current_page = AUT_ACCINF - var/datum/nanoui/ui = SSnanoui.get_open_ui(usr, src, "main") + if("back") + detailed_account_view = null + current_page = AUT_ACCLST - if(href_list["choice"]) - switch(href_list["choice"]) - if("create_account") - creating_new_account = 1 + if("toggle_suspension") + if(detailed_account_view) + detailed_account_view.suspended = !detailed_account_view.suspended - if("toggle_suspension") - if(detailed_account_view) - detailed_account_view.suspended = !detailed_account_view.suspended + if("create_new_account") + current_page = AUT_ACCNEW - if("finalise_create_account") - var/account_name = href_list["holder_name"] - var/starting_funds = max(text2num(href_list["starting_funds"]), 0) + if("finalise_create_account") + var/account_name = params["holder_name"] + var/starting_funds = max(text2num(params["starting_funds"]), 0) + if(!account_name || !starting_funds) + return - starting_funds = clamp(starting_funds, 0, GLOB.station_account.money) // Not authorized to put the station in debt. - starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap. + starting_funds = clamp(starting_funds, 0, GLOB.station_account.money) // Not authorized to put the station in debt. + starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap. - var/datum/money_account/M = create_account(account_name, starting_funds, src) - if(starting_funds > 0) - GLOB.station_account.charge(starting_funds, null, "New account activation", - "", "New account activation", M.owner_name) + var/datum/money_account/M = create_account(account_name, starting_funds, src) + if(starting_funds > 0) + GLOB.station_account.charge(starting_funds, null, "New account activation", "", "New account activation", M.owner_name) - creating_new_account = 0 - ui.close() + current_page = AUT_ACCLST - creating_new_account = 0 - if("view_account_detail") - var/index = text2num(href_list["account_index"]) - if(index && index <= GLOB.all_money_accounts.len) - detailed_account_view = GLOB.all_money_accounts[index] + if("print_records") + // Anti spam measures + if(next_print > world.time) + to_chat(usr, "The printer is busy spooling. It will be ready in [(next_print - world.time) / 10] seconds.") + return + var/text + playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1) + var/obj/item/paper/P = new(loc) + P.name = "financial account list" + text = {" + [accounting_letterhead("Financial Account List")] - if("view_accounts_list") - detailed_account_view = null - creating_new_account = 0 + + + + + + + + + + + "} - if("print") - var/text - playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1) - var/obj/item/paper/P = new(loc) - if(detailed_account_view) - P.name = "account #[detailed_account_view.account_number] details" - var/title = "Account #[detailed_account_view.account_number] Details" - text = {" - [accounting_letterhead(title)] - Holder: [detailed_account_view.owner_name]
- Balance: $[detailed_account_view.money]
- Status: [detailed_account_view.suspended ? "Suspended" : "Active"]
- Transactions: ([detailed_account_view.transaction_log.len])
-
Account NumberHolderBalanceStatus
- - - - - - - - - - - "} + for(var/i in 1 to length(GLOB.all_money_accounts)) + var/datum/money_account/D = GLOB.all_money_accounts[i] + text += {" + + + + + + + "} - for(var/datum/transaction/T in detailed_account_view.transaction_log) - text += {" - - - - - - - - "} + text += {" + +
TimestampTargetReasonValueTerminal
#[D.account_number][D.owner_name]$[D.money][D.suspended ? "Suspended" : "Active"]
[T.date] [T.time][T.target_name][T.purpose][T.amount][T.source_terminal]
+ "} - text += {" - - - "} + P.info = text + visible_message("[src] prints out a report.") + next_print = world.time + 30 SECONDS - else - P.name = "financial account list" - text = {" - [accounting_letterhead("Financial Account List")] + if("print_account_details") + // Anti spam measures + if(next_print > world.time) + to_chat(usr, "The printer is busy spooling. It will be ready in [(next_print - world.time) / 10] seconds.") + return + var/text + playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1) + var/obj/item/paper/P = new(loc) + P.name = "account #[detailed_account_view.account_number] details" + var/title = "Account #[detailed_account_view.account_number] Details" + text = {" + [accounting_letterhead(title)] + Holder: [detailed_account_view.owner_name]
+ Balance: $[detailed_account_view.money]
+ Status: [detailed_account_view.suspended ? "Suspended" : "Active"]
+ Transactions: ([detailed_account_view.transaction_log.len])
+ + + + + + + + + + + + "} -
TimestampTargetReasonValueTerminal
- - - - - - - - - + for(var/datum/transaction/T in detailed_account_view.transaction_log) + text += {" + + + + + + + "} - for(var/i=1, i<=GLOB.all_money_accounts.len, i++) - var/datum/money_account/D = GLOB.all_money_accounts[i] - text += {" - - - - - - - "} + text += {" + +
Account NumberHolderBalanceStatus
[T.date] [T.time][T.target_name][T.purpose][T.amount][T.source_terminal]
#[D.account_number][D.owner_name]$[D.money][D.suspended ? "Suspended" : "Active"]
+ "} - text += {" - - - "} + P.info = text + visible_message("[src] prints out a report.") + next_print = world.time + 30 SECONDS - P.info = text - visible_message("[src] prints out a report.") - - return 1 +#undef AUT_ACCLST +#undef AUT_ACCINF +#undef AUT_ACCNEW diff --git a/nano/templates/accounts_terminal.tmpl b/nano/templates/accounts_terminal.tmpl deleted file mode 100644 index de738cd2940..00000000000 --- a/nano/templates/accounts_terminal.tmpl +++ /dev/null @@ -1,146 +0,0 @@ -
-
- Machine: -
-
- {{:data.machine_id}} -
-
-
-
- ID: -
-
- {{:helper.link(data.id_card, 'eject', {'insert_card' : 1}, null, data.id_inserted ? 'fixedLeftWidest' : 'fixedLeft')}} -
-
- -{{if data.access_level > 0}} -
-

Menu

-
- {{:helper.link('Home', 'home', {'choice' : 'view_accounts_list'}, !data.creating_new_account && !data.detailed_account_view ? 'disabled' : null, 'fixedLeft')}} - {{:helper.link('New Account', 'gear', {'choice' : 'create_account'}, data.creating_new_account ? 'disabled' : null, 'fixedLeft')}} - {{:helper.link('Print', 'print', {'choice' : 'print'}, data.creating_new_account ? 'disabled' : null, 'fixedLeft')}} - - {{if data.creating_new_account}} -
-

Create Account

-
- -
- - -
-
- Account Holder: -
-
- -
-
-
-
- Initial Deposit: -
-
- -
-
-
- -
-
- {{else data.detailed_account_view}} -
-

Account Details

-
- -
-
- Account Number: -
-
- #{{:data.account_number}} -
-
- -
-
- Holder: -
-
- {{:data.owner_name}} -
-
- -
-
- Balance: -
-
- ${{:helper.formatNumber(data.money)}} -
-
- -
-
- Status: -
-
- - {{:data.suspended ? "Suspended" : "Active"}} - -
-
-
- {{:helper.link(data.suspended ? "Unsuspend" : "Suspend", 'gear', {'choice' : 'toggle_suspension'})}} -
- -
- {{if data.transactions}} - - - - - - - - - - - - {{for data.transactions}} - - - - - - - - {{/for}} - -
TimestampTargetReasonValueTerminal
{{:value.date}} {{:value.time}}{{:value.target_name}}{{:value.purpose}}{{:value.amount}}{{:value.source_terminal}}
- {{else}} - This account has no financial transactions on record for today. - {{/if}} -
- {{else}} -
-

Nanotrasen Accounts

-
- {{if data.accounts}} - - {{for data.accounts}} - - - - - - {{/for}} -
{{:helper.link('#' + value.account_number, '', {'choice' : 'view_account_detail', 'account_index' : value.account_index})}}{{:value.owner_name}}{{:value.suspended}}
- {{else}} - There are no accounts available. - {{/if}} - {{/if}} -{{/if}} diff --git a/tgui/packages/tgui/interfaces/AccountsUplinkTerminal.js b/tgui/packages/tgui/interfaces/AccountsUplinkTerminal.js new file mode 100644 index 00000000000..b6d073574bd --- /dev/null +++ b/tgui/packages/tgui/interfaces/AccountsUplinkTerminal.js @@ -0,0 +1,288 @@ +import { createSearch, decodeHtmlEntities } from 'common/string'; +import { Fragment } from 'inferno'; +import { useBackend, useLocalState } from "../backend"; +import { Box, Button, Flex, Icon, Input, LabeledList, NumberInput, Section, Table, Tabs } from '../components'; +import { FlexItem } from '../components/Flex'; +import { Window } from "../layouts"; +import { ComplexModal, modalOpen } from './common/ComplexModal'; +import { LoginInfo } from './common/LoginInfo'; +import { LoginScreen } from './common/LoginScreen'; +import { TemporaryNotice } from './common/TemporaryNotice'; + +export const AccountsUplinkTerminal = (properties, context) => { + const { act, data } = useBackend(context); + const { + loginState, + currentPage, + } = data; + + let body; + if (!loginState.logged_in) { + return ( + + + + + + ); + } else { + if (currentPage === 1) { + body = ; + } else if (currentPage === 2) { + body = ; + } else if (currentPage === 3) { + body = ; + } + } + + return ( + + + + {body} + + + ); +}; + +const AccountsRecordList = (properties, context) => { + const { act, data } = useBackend(context); + const { + accounts, + } = data; + const [searchText, setSearchText] = useLocalState(context, "searchText", ""); + const [sortId, _setSortId] = useLocalState(context, "sortId", "owner_name"); + const [sortOrder, _setSortOrder] = useLocalState(context, "sortOrder", true); + return ( + + + +
+ + + Account Holder + Account Number + Account Status + + {accounts + .filter(createSearch(searchText, account => { + return account.owner_name + "|" + + account.account_number + "|" + + account.suspended; + })) + .sort((a, b) => { + const i = sortOrder ? 1 : -1; + return a[sortId].localeCompare(b[sortId]) * i; + }) + .map(account => ( + act('view_account_detail', { index: account.account_index }) + }> + {account.owner_name} + #{account.account_number} + {account.suspended} + + ))} +
+
+
+
+ ); +}; + +const SortButton = (properties, context) => { + const [sortId, setSortId] = useLocalState(context, "sortId", "name"); + const [sortOrder, setSortOrder] = useLocalState(context, "sortOrder", true); + const { + id, + children, + } = properties; + return ( + + + + ); +}; + +const AccountsActions = (properties, context) => { + const { act, data } = useBackend(context); + const { + is_printing, + } = data; + const [searchText, setSearchText] = useLocalState(context, "searchText", ""); + return ( + + +