From f5540621038afcdf5886c279dcab3de6a4e01bc9 Mon Sep 17 00:00:00 2001 From: Verkister Date: Wed, 7 Mar 2018 10:19:06 +0200 Subject: [PATCH 001/109] Couple borg UI fixes. -Fixes missing default module UI icons. -Fixes the UI mudule icons breaking on relog. (oh please who the fuck puts a ..() at the top when the parent proc is nothing but a single return???) --- code/_onclick/hud/robot.dm | 2 +- icons/mob/screen1_robot.dmi | Bin 136736 -> 136942 bytes icons/mob/screen1_robot_minimalist.dmi | Bin 120424 -> 120770 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index daaa52e827..8a6bb736f5 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -276,6 +276,6 @@ var/obj/screen/robot_inventory r.client.screen -= r.robot_modules_background /mob/living/silicon/robot/update_hud() - ..() if(modtype) hands.icon_state = lowertext(modtype) + ..() \ No newline at end of file diff --git a/icons/mob/screen1_robot.dmi b/icons/mob/screen1_robot.dmi index c89dd8a01e90deb45d1df6f5378ed77524e614a5..b991f26d4371d295a348a403f7b394d15d66a243 100644 GIT binary patch delta 14930 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

CtdM+6N{I3u*27foBdb_MJ!XrE%#I2 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 delta 14715 zcmXwAWk40twmu-8k|Nz9-JKGW(j@}Yoq`}SgtT;bcY}1dfHa68NP{3qOT*jT`>wx^ zx@XSp6<@5`=WiuSP6bK~EgWVn9St=8`e!7+43Z2Xw+;$^dhNoi1j*s?=HkO%M6OqV zVj_B(pJZpzp6tp`Y~PGV_oXj%k)OZ`m{4k@9qedjy{%QLWE!)`v}84&DcWVAPw!6H z-esDw*|btPWt|we6P4CTTSvN7y}$}5(GgkyuHZo9VrPp%J*NlHpw5Yi6e|T0`>C(0 z(UyOAdBRM`uhHg~HMhENrBMH7|1a`zP=-KD3|^C#i{jDSIA$kV?fr+(6;3K16y~Kz zVj~Ku-VBO#N0};$4pQ(dtZpWXdX!uxVSpQNZSnH<0);4#=+^G~USIL%TA!l`M{?&XC2o*8En0TUn zQr|=4@2%~N7+|W|uEl7aVLP_Rw)n7e;e5X_*BY_EE}rAf$VkfRuM=2S+QN`Xc~LM^ z&x<6=G_h<&_(MeZ?VyuP*$(_ce$!61_p?0GVhkJ>oyuEjjC(W7^Q^JapTG8vu&*2? z`=EyP@m5k8j1nd!+nZCXK;r=E?i5`ngNP52NZOh3BvkZ@xzCJN~*DV(n z6_uHpnbW_0J$j{-ZUP;H9(4Bh?wiA|*FPKWWjyUwGiQywj}aX^&Iw(2#?3E})>6hS z)W|$~0uV`s-9NXtixj=iR#8!jnl#IVR2b6v?AQPObhMl)QhvYxBX)PDc&73Vf0oBO zs{7xiupZ;pAGM|!qym%G&jh4foKfd=!iSR!hoItWu7{o4&zKD0kF(&8BQ$@WRL(5m{EwTC1F_T9J+73GvFa9nM4-Zo@Fvz9wC9&xBjwCY6 zWPfjN7FcYs4H-70=H`x1NWd3+xP@H7CYek!?D3EA#x%yz8>tJg4P2shU@bMzM<2y5rBrN{$b=TkKG7 zPL9MGnQq5N-VeV#8BkGCS@i0p@t?hEeP8IgEkyWVzLiMnE7%G7#w)6pYKwK~p{>8WR%}Ej|6o^`Gi` z&r^%RND?`3Z;`ODFzTNq&`8$s`+?sC z$cDVUfXz*_cN2zf?yUBUU(|#Z5RvQO@2XdI{L>e5-w*9udy47le)uaAd>G%WeA9%6 zdQmsZw(--ki;j~sb_IIKyt}#3(AFLt&lKKWsAniFEX?C^13^{A4=PklK3NUKo^G^% zW2Q$>N$H0zcIg)mg`?p_CS+zRtExWr_xJA~96Z@dHo_$$dId^I@Z(v@@6Q$u`luKf z1wJ?b5D*Yz5)x>YszAcLFV{k--`P**ND7c*fr=UamdY)&;J#uwaeRD?K_-*{_IMN` zehXJVr=X&O_2+x##xJi!^N0I8yPu7b6%{P>Dj8obvmqZ@b#>ehuZtqDi@$bD&1wjy zR>SWXFN7EvLbS@YaY#v(TwJ&)d@rf6#cykVZxRv{D@aMfPl(;H#L*sCLwAbrYlYwc ze!ATDVW(lWQtiaX$4wyi`!J=X^jGOY5eQDZct* zYLa;y@r>1zkBcW9%l@TSR7f=1J&9~oVdXicA)*R%Sc;DT@lE+_yrUVInI2(oDF2dE zpcR564{;EU!p++D=H}7;%^|nviCJ8HJoH?^i4t4%?5VlAIe zHR^lovHdOerJWti&n8C(YU%(07cQ=@yDMGdpo&3&HFR~q&b$^^1_{9mc@o&uoh9le z;C;zK9vw0e@hsx^bNRR*U##(pUuRqVsClQ9&Zqp1n}Z`pj@(n4c7sgBv=lyPI2uJtkMM)9czW)ol*SVV>c+q7 zZJW#d+YhzIJ@8^T``mzZ^z`&T1qX+7Nc)9QK)yuareCaQq@N#oo^Er3tccxTnkpzN z$~ee7J97?2kv-95py^g*@Ax!k(f8-vr4N(8=EI?3h6=;!_L%8-hM+DB;b0UQ^9iny z+a7Hk!pzK!49{EuBD%EhAF!QR+Au!*#mTl0j^sXPYHD&u==R^e(cd)M;S8YV=jB1t z6w7@f*xXi=lv%#l);PaB_kVB(V?39VmPUwp#$J?@+z?uNjmez80t!?1_Q0U$^Gq>6yC?bEjypC)X{?sn;gi(^J+|ouneI)H}`|Z zf&GR0So2g6IdygQqmLc?D_z<0@esZ9iqD0bre;6chozpS7FRf}jTv}45pry{_(f$yC^5CCylLr0gf-bcD%kS~j)YO^{*wpSm zT%YawPM6ThVY zP2nncKPysB=R1CE88#yTBin%eXkNTP3+d~Lp?c}mVnAKDF(pS~{;S>dQ%DFNKEAY! z3}Vx-kIVq<+5r_n{r&wNS5PuLkY(K>UecKL5_*)8R;N+xg66>4bWrv-M6=(;b9l`l) zz+=^2_d?*?Fi7~6QfSf8(dFgkC6mlSUq7NAR96=V-Tg5#@V(jsOf_9^`C7ZmfGLku z=>6~R3cdRNj4u@FNpvI>6wy;wn;?aG1;N3>f14lM4}95=P9I@JL_`c?p3vXFt)@t2 zMswP?(`+yQ7(Kio?b+Sk-TzS=7!&hUK|vvf(=-@`;M>^P*7rA#TL7(>-p?qrK)N-4 ztEPW5&$iNh*DR@0?sXMjQ|J2{PE?++Fen^t_& zhvOL{$eZ<1%9kC6KxZ7SNjStTSomRVi>LCsK*2 zetzBu@|GgxRu&3tJ02vFfBl+)pFjCAUZonv;oq+RF1O790c7ZVWuD~$t)p6ur3JB! zid_HB_r5(I`r^2f1#aWw;_^yC;Zdi7U~IUzEp&MC%gD$8fvRS8e6jq20+6~1Am8@e zlTpTSYLf?SG9lV<^eWw2DcV1G2aeFoBy*q?lmUJ{Uit(HV-<8p-+}whK;gU=(+s0z zjFx(O+SlaKT{s-*7W!JU;-IQ$8iwQF2=RLH&dISqZzwSbx*2kaM=X3s<1^0)O5 zkZNm@{J)Gr?f1qun~xIW2(yjWSuN%*BuTzCGuNZ1r6xu`R-yv`H#=Z>_%)S=m14^8*B*pSG?<2c4~o6RKtE{ z%a%W9IDG5w-)83Kwe~;xfWv{6tVJXyCTePHpX}F9a6$Lp zCZ?t>*L&pyA2tKA#a4mA>REGoWYBt0>=oL~rKP3Rf{JfAcz1tn9LL1Q`u{wz049i9 zM}}EASI{j|Hot@q{b-DT#c9Djd8+s|1*GOP*QCGiIw3l={9#4ez#xO;t}yxwvmJWXZsVrb(y6c)v6`@P0`hTh^^O3&$p_-hjr>U_EAA|U-6?SIy}Y$*Vg z^8_S{0%2hlf$}1X97HPjSHRU(#?9qxZrO1+)5|T8dN-U!i;rk$ajEfvcdxJ)Q}Kef z{NNdhE?K$;=9zep`2F?Igys~76ebZzQp_H9G)5MdefHO4SG2LQv3}R4;nC60#8ZG{ z;ABI;@Ts#ACzVrUt7MQQ$@0HM-N0Bv}#EQ4v4rC25bbK_jpN+fy;69U! z66+-`G}tDW+<|KA1KdQ!ZGmC?y<*KDnfz%~GuZHSgRKrQ+JfNbec0lgt$(WeEb5Op zfUyA{`~L0_iU$P=*j@7dd!Bdi-W3!S)L2fCx4IvU0C9zihPGY?l~+;o@FYZ%@T=?V zkMPbL^Z`g~-me=CjflX*UGRT`OvGaqQ$m$rxW{hL9P_r#z1Cq_2#2iJWB?6^yfl$_ z(kA`va3vcotOHO$ubkEoTBqfp@h2$h#Lz@+EUax%4RmyLK{RqvM?2yVdiWhP-!xZz zZz@aF1>Zrv2(<#iAt5usiSgO}=w9m!dCqBq@Mpey2W*2LNKqi9G*ne3zz#Y-p5rc* zEW-b)HI+NgpHmWF%xeQJ9vid-cKaAoU@Tec+#_Xa%C#$T7cy#VYxCYIXN&m|3B6}T z#wOp4l_P&Ql_#_0JVch)Uz0@D`r!~VWb3+hQOOXHw6MbgUS6A(OhHCQkRBJ{Y)+}zv@NXRWbCx=pPo}Pv#5O8NG;9@S1 zBV#p7`6Tmi7WH4_b-R2;B_$>E7^HwE1+-2}M;Dut!gzv#gh2!#H%Bp<4VW_&s=hU+ z8ju=*HDF8-h{AL?lYNg+k~Xn993K`Py;DCSX4?A+6$p(wunGyA{PUd6fK3Awm!7UD zD~klobspsI=_v?Y9dg+(^5Dx*2@9u#=Efx^9s$#w*K4P# z{Ep<0*a(p5DZwi`d6Sh+pU0=m${GjjngPs*g@)#ol!U5e3ULC3KXp}QIur%a%^Bc` z6M$&Mh)ziN#Liled@Z*&MY&NQLdqu?Ha30j>-BGQsP@7R89xv+a4OjBi*ruSlN&Ul zny#8BaXrCP#(kPY0*fowJ7O?#if)-Lqvp+pylIhuK+_2lxtCDq?Q|TSqV}@KMx;lF zA%Jul@MK^dfg@f9!i!5tC=2)CD19WsaJH6#-g69K1HKaNE-=vBF;FI@sSIlaxfyR}UoSl+G=WVU%P0%bb)d@7#pGvjae-!$2j1Sg0+AI9vT0z^Ck*-6c9Z{Y3WbR^Ta$i4*=JngU<8x^z^>oEe3-)P)cI|4p*xA zdPAeOQ!TUBT6Ul;ym_0nc`%!L&SUiyC<+>&d(s_RQRU+POcrT z^(m!t$$VoF70n!F@5;!?Af=|Je)O)uTT915wAvNAJ%HUk!H~&WfD}+|_(!ot*&o0L z94}pnJ$l#TnXqMtXBS5Rzkx~!b3yC6`IPE~ztJs|v)@y<8x#+#Kpw9G6yINL zK#v#*7%*7_jSkFg@XHXaTCWR-j~9Pg?S3vMPnpzm06dB9DfN+j0JbJPPYw9_XEyg> z`9iB3v+aD<)*~*0ZhyQQxcQCuLM;#X(9I(kf$!u1^WP{}X` z>w!@T1rQe-_S;F|N85+$n0~-%@;l?1GSz`#%JbMOd=5)rE1P~P0C3eVPfTRiaXDz1 z5C3upMwno##n|~9k3q!@O#40)aRvahyH z-UuyZ8*4rX9@OO4|Iu=_I!e-sdCV8jJ-4YVXKF0PcWE)ihN z9>9uUX`(6Rak(wW&+5%>(?>yZqGDn`&dxwMHe6bM&sS5BN6UHp5=O`*Sbood&fMFU ztC9U0Yh~r+PG>bHxk++si~;N(|c)fx_- zw+?V>Rr`qom_Q8BLs^N5G71W40DD*f@s^Y@PR-I$QTaP>3_j9GE~^hv$e)RM!vQ}= zxJMaQCxcL;)aPppEA|00mcAJTmEL7mI#c{Q;$*xNy|j_hMrQj_4}p1xG#KhO|68;T za+Fj2=)Doi&ylKhcJMQKhypT5sdQ*N;KPSx)(Vpi*E?_inu3f1$O;GyOcnmX_Bdy0 zZ_fZDMHk>jT<^~3>+Ke}ut)_Y4u5r6&lE*+T-hzRCaUGj0{b@%95Wc%0M#%BR8OPB zvck>30~sdV%I`7SBO8mh)dUwCRc(LQ!6a%87|o3|+p1ihYD3=!KO0%L&|k1lV(=TGWx1|&0nd08O=1%A}>9{DG16$jg^D+35mK z9&fF3GJZPkcA{`i-8ABX_Ztmi(I5OORMkq4HjdTslbAKN?ctS&`-MMprTcbh#M0KJbd#g$ zu2mZqaov39G5NXB1Anks{$L6|U_ckQ%!%i(3!Mj+G{Y6DD-BLt%6 zYbF~0e+%PJ;%~~zi+@I3oX>e@EJRGBAy!YOr)C1c>+sDaeqJ+vi5ex^?JC?X{bM3e3P3RpO^63!gvoK zT5RAOY~uNk??c*Vs|@h4Ensu%-pOSfK|ymxIpSGAn8$PXnh!ZGTZW>GIepWq@z%9p z;>+!5D_*!b^{ z6L*93;^20L;#^*Ok%dxUZAg5x+{l)0TyIhGx z9-oPjQUvW(H=6tdO37CVWM(Mgst1GD`awBA6Tbg`n~K6nwUA;NRwr}uv@Sn zD|p^EJl>uA`B@mm!(=E-PN;njcbUPRufTmY2kV7-VNyt#-fAx>TD2gathP0x=5$l2 z{Ox;+i#EVeYfId%S0gQL5@#;pl@jySSSsMf8V^RKU{7pZqZ69!2T=tXHK-y>wLM&N z9`^nVF^~Kc509gNFG^QRWkp|!#S)g-b|B!VVV-4T^n5pjnty%mw~KRXAt1DWT~M>c zq$Hsn3-h6y!c4V3J50jZayqXt)4u18B}Lin-*p-i&7u6TgALUty5E%}*$1 z%KsDD7(s_=Y+c-KL|!dukEJRsq7crCs$#6;fprRDFYY$Iui6?`rOpsy=dY?Ms}!bq z2?O=}ln;W8>~m^@kzi$nlVdr)Pnnh0B2Ur@o)463|6JNQF^QQayHzbr=cn07{b3ma0BylR9AQFo!4&GK+MG7oKhAaM%6>|&=Ni#~9 z=2!?zYp9o%{ug@r0p4Vi#zF0&AnZwjf^1@D?rU=@s$44Xx33jNBUf@5iOjL9aUN?Yq+RWC>eUc^Cc;nEi+V-fJ94ZW{glYk^umg9P$g#|Y#t*Q z=ba|fr;XUi|JJ!7rbPUiIOD5claVLg(1BV^Y)$HFtKrX@6xtC3t_XKpwZCwMdm)7b zV}a1Ob_+D?D1?3Hu=_gB$V>NO6JLw`R*v*Y-0(bE;sXKAHzyTgNv~Fs4n(y&s;@7Z zJNAl7w%})jl8#=JbViiE#wrs#TGzL@Tdep6i(i5Ce8Iq<6f+5hyGo*Fz26ij z6A%|ieS+5U7zM3d5C!HyVnPUJ`m;hd&RFZOl>vE>M7gwCO{_dN!^uebg0wJcLTiFP zdY0q#XZAE^xEqB$WY@ag?1XRx-7zpU31c?#g+nc3Ep2R?rMqfM=%Ozu>s8{tg2Z^! zdbxNPOLNsL$F{o4Z}e*~yROzPio^t8`P{E>6I#QMZ9%ThdT(#xuAzdL-?!XO<`ZuF zY_Vn$?j=kSskYU-N4}=8kVBHoPKKT@GTSG`ZX5RT{l!*ZKq(gTuSb$7;D4L0%!4bYdL{;AKjjy?~f>I!oe9-!Z_H?DAP=($;@h@?R6BPqXP z%zrkJsE~R5urpH4dcXLv{p~8_s-8{f8T2&W?~vDR;Wm8~GE#dV0DD8HR=Y+^%mw%A z#_CDw1qPz=-qe#NeNCx%f}cw7J~3+AKF1|gy=$fyt76=-R&0~K@>%Jc+oY3bD(4N! z>#g4;NM4J*op^Y6<(|mvB7tboS7;Kfm1g=IBKB zv-Ixp(b++kG$f}t3)Vd|CD;<`C_GxYBvo0>S25qVQ+GF;h4DynqlR!bLy%UfXbWD6 zJp4ROK0Q%#`&C?k5b%;ZlnZ%JO+rYYU~d+Nf&1edu0@kSWqRzidRVpilK-&X>h~M3 z<9`*9JiachY|l;KW5zAHq^a8bsiHuzOjPW=z7ncc%5IFHku9bQ4DCKa^4Ri50ZRB zz$z28LRO8v7rA@(c6>a2I#v9^vlrf2&rBeQH7*wUi=*C!|d%o=FZLuP0S)>Nn z#k%+|({B0dr8Q&x%Y`e~{)XK6;}CvZ9wFXIK_7?2sswd>#g%i=lw)s6Hlja=(n9^} z;nbxO?bUZiGw?`*Bt%4xIrHc*2W;h#qfFwhpUEj=h)`60-@M2irQiRgX$@O3-a!_` z6?hY|;?P8+CI8^OHfOY-Y+1xD(%-#W$&q7*R__Ia;bA?VR$8Sslwrl$`KOS<_w$mI zK8mLCsa+$kb7bQ?>vYNY(v)>{q)@WmG%t*-63LfDB5NkB2L@*m1{-*#T7&c1CS&6S zyN-$NxW-J!(IsL+)qrZFwD^afslYSTSu?*$zeO2*I=waUK5R4bYeE|dpL{0v{Tn=Y zuHCi!J%_N1_M;uaOw6Ca@=5)%ZokgVlu7x-*Y=TJNeB`v}5QP($v_@_j zlQw9J!oClu%1I;Ib@Rgyl4aF9DM`TzVhN3_n}T_vUm2g*t}pF#?Kz2oVYfA29ve%w@QplD)93YAHGB^<8%H!FdDFFjzcicQd{6D9LN#D6x8p2pbZ>el z@~dnFH*W8CuI6^icyJ{VMIIu7OF1b_9wE^_mUnj?dAoP6e`S%})GBh?auo7|*5RNo z-iv&H=wzaa^S(-&wpvNPus>lauEe`#>(+97mbGL2x`AOf=61!~*;R|w_ndbo`0%8w zh&%(YYhu0H9Qg*!-G@zB*QyzX{KvHA6*7o#9-4O8pV23bg_xnCM?j1vH7<#NXakoA zU>;^qo@}b0d?TpfxKjK+|IvnhGtwMBJ(3IVUEyTWb+g4N`;A~U8TUnuz=Nk)6XNkl zzd*9@PYYc56Lz%Z;IA;UKTfC~laDB#3ck_wpCZ*e?3e=8fLaUp%CFCXK}5CJBDR~h zG(y}Ezv){nHyRyVkdCs^%3y0dr?m8o<_^}Mu)X+hQY>NFCkXm;U5AItH0PO`Bg}I_ z9*T|8o7sY&j_EJA`|PS#_@2f!!j69EaEW8PsjjJUq_6JCTN`kTCr2Z}6F?xaU->C4 zPKR#1>Tk1u>Yn|=s-O>RwAUY`z_TCHh<3Uh&cgR_uH@+Ru44$g{`3%R7hy0qhHd{P`9+M3oK7`V>Y=58f8dRRNV&z1qGR)pqNB9v07x8WMOs} zb@TbUKh&BRKiAS;|~2RgqLf_vI0KZveZzft_S{jA9bC!pHTpGdD`6lC-E-ja(kQ3{%YQ z-Rfs$9z(l3lj-1F6=8t0s0r@Ah_-NDCK>h^&D7MC*#2cR{BVa#2>nf7P2T#6iW;YP zKVdg$iS1{`OL{hhDbD>xjtdFh;9|n8GdpWAbO$){U>AN}ma!f7N>w_~*M4v>pXJa$ z6wn^MXupeQ2}jHDo3^{xXu>dKvCXjiSk!}cszSv0h|+jo|X zZoPx(JBFMy>bS>W0eO*nztNSJl%bi~Rb3^+TAly+pV@Hua1}W`USkenwDHkw0Rmj|j;N|2O3m&-wS! z91_06aPx;Qwv&TW6WYwgvO5xMLX>XT?0HE%`u^HoQgp+=s`)!?C)<^(ATNkdz#HF% zD?6?@u;KqSJ-6(sA=#}YE`h`IkiKz#JV-lzh$p^_spL<4TWhtw=E?lz5+mh`zyrS{ zpXrJQKhy<@Dwk91Q#>T`k=5#u7K`M4>R;QV_Ut~`l&I<@NB-ogh1tDrpVk0rkU7gg zHW;R%R9{))<(Fta<6V~HeZ3&osiU{%BI6?{)aI^QFTdKPfE9lxVLU?(tO9W;^?#pC zPJL8mMhi8jiDUejuj)i7Ql~$7^}Z@TPGOH158@%fTrgH-jX6>0vdtdf4%Qp?Zs^oM zQ3_S07g^cm7H4GiLu*nBdb4ImC6YcFvhvTo^w|0;jJ&w)n<26+>%I@X@*o-+ zWQ-;HaSzozUsv#zb8;DT2>6~LA#>=zZFj{!uzZ~?ga%JSE&6iq6I;VGj4T>UrWZ%* zd)l@)H+kC)))e+nBOY35YDw9XKcK<$8WmlrU)lIHYzj6zzOctwMdAIPlC57*)viu; z@csoH6~`CH7bJ~k^S%vY>FELLoXC=)aPY)6J@f0?af7@MN&}|w8kD+eUmcUQcB)yQ zc7EiDO#fv|3~BKCz5Z9gVV{hS4o?C(y=@At5SX$Mc1>aMM`F#E4 zMYFkp^P;?U;a=rlY_Z*cZ4`<_^@!Vt8z=jDLaHHMMZ zy~lZ?XoU-DtWlWHv>W&pS-~O~fVOdbg=eKe?ibuKj?%hN9^Z&&dkJT=c;%D3aBF*w zymuj)N!7pC^K_r$4^&1SK=cMWCmm5Z8D=l-Kd5wvkot~QsK3h}rI~;KuW}5^hi9%vRPbwZ*NS}%y z;&=PfBoW7U>cnQ3BM(|BJ6yQ$tvkimjQ(0{$^Lwo8p)bTcNI|$ZV(?tgH)vcH(>pv z-4QWlhT?r^O#A_gQ~0TiVoL?Rf-QA$Bz|F-x!e%f7-lb0@vUqbAJ{|Dj_+z|@Y#Fm zlP2-@R&pDyrg5uP#hQ8_x7!M}m)}+=0%7_V=C*LjG7AuXIG{x_dyh5tb zzUJ$Sf{or|iaA7+Ugiav5w%MrCQPy0B!`l};2V6pE{Z5&WyQ#5E8y@Jv|6|^e1mKL z04?YAJ^F>%kC5nLj8=^JBTP1Yy3C zYC+d_jLvT=+U7kdZGF%7J*I@5tv?4Glm1{ii-zGY9S0A5v>wi|sy6B%gIWEa(hKt{ z*BSV|1~_oWrhRWXnd6=Bi^45cL)2UxTthu;CtqkkZOq2xEY8W!s=3}?}N-=W#*$q|W)K92WbH2wHjslK_tR?zuzQ+QT4!`#pg_0{~RYId-7*0)@^9{lpG{)c~Ngan>FU;}9 z$FBK*ZFCxGC&ZWOr7XRBA{B6V@W7|&hRo|FO-cSnfWQ!)ZousfbuM>eO1JH-1>q~U>h#$MZ8Az+=2MbTF-LYSc zIfQCY$cGKD|Li!{%m^e@UAbVtP!cO7#4cyv$hE-|4REjBaDoq#Wxp$P@0W~v>s{M{ zER$$M8?(r&BFj|$sl;Z;`SVr*k(Zy(vuwvdx%2STQ)M|eFf>x(hU9;o%a<;PTdzuR zJBJ~4^F7XP{;pz5`BklM6T}TcD_C*n&7R2j!7M*oe-_D>XV+aB0nfTiklwc9m&%`V zYwz-MX_EmXm3jm(~0pXOmrLvEJ{Z|FGRoRmSW-K-u-eY3H4 zU4ny3d#)ds5Jfv8_EoiX>X1}vTd9`c-dZtqeX2wI+%h#JJ1Y1c_lSo%H2aW5Dxl;t(iuk~U z``MFeaE1wv2)eUJE18nOEqh;0=VdMGYfCQv%=_+ux{Gp8-0(v>ks9+Ly?lcYrgA1k zp*7?)bd>38yV3RIqO0L3WTD+xM20}Nhr;IkdU+*J!SulY&DX=5D-v3c=LB>7RQ?qu zqS=^n0g~!h9d)#6_f{9Zl>SpWp}s#lV+hWPm2Inrt6vTc`2B$0vm2k6s7;s5m7hy7 zgICa#QwX=&i!ksZH(!v5*JgGgs~3_9%01S2{HK>g4>G?={J?p{_Xc?!yuRV!(>-2_ zn9nuT51kK^IL_|+bMMP!K;Vz!w=`G}f zCmY1uj<_#Jb6~9pLloCYIWOhPdkK6ez|Dl7SAS2{;qf*c!_1c_(rANEsKY5p-|%>W zTNNHaacX14w^ZB;4Sc0}tJ*1|zoScPm2%%p?Du~5QzsmVRoT(uqMQvy*{R3aP6MwW zy|I=kZ%%NtM{Z!?Z$=NQuBdsRXfk0~`JTh)8KUtv=k2C@4v7`*y}xg_H_R|s$AaeE39C`Se>j)Ei|K-JH#Iakd@7~ACs#D_DM#C?vPdwJ(tzkGgILe)T ze0O!h5>1DvbTaF3{nu=-xANjs{ZypMIF9qr7+Oz$ICF&l zmVkVY9Z~*2Y+dQBElsbctFbGUo=g^8TSVsC!jyymyPX{3zdnT@D+`(rT@Ny@4Q)Az zr(iCp_w~fx;PAsAk?I~!E|q$lki|ZYc^L8kuDOQM4vU8uZ@ZR6U6=l8Ak4?XG*;0` zsq6YT`b^=8fZO%^QwTW~<&H^<;-SbEhAFx7SUp-LSj(l)2WBQu31x0)gS3m_GPuv4 zP9pt(7)ng;UW=FFcG54*dt=QJOT68=&eKbi6eaen8)4!K_|qHTxzjnzwM)S!LGBmz zzpD&T85;->S_z#GbT!7crkVpKggB~x=}SN(gR<;8YSDyL9pX98zHD}^lw|k+Elt$x zi$f!=rw6@S71kwB(*{=(g07`bjJ^ixvm@+acaVO;BCAAr)<%9`__aDY@Ov((JPGj2 ztBKv~c!t+|w?b)%fWUL}30A>DCN1!~S@8*ytFyf6np$9g>2auMIl4r%#5u6n%o z@xPnYEX~X~z_Hm(BjlX_q@C@oOO=yD>#J3Nk9X;*k;#9b4Tp=(C1#{>94h^9%;=iI z(XrL!pKwr!g|oAB#2`8vTA5D`-02Wl!zA?q{?DXyEGPJd%*Q^8mr_!?^%lwzgJj?^ z6$IYFpLdGcerMTL-&ACi3UJJN_Y#++mIVxt=cidz#n-T73nG|c^siet%|d_mb8(GG?yy}({7!2pF*;k_3X`>^r=+2eH7-i2zBKXA zRPp0<9DF7-mFc%?(fiNKf|7-vNG@T_=Ppwv#n{i(o_A&)@3iiZ`y9tf-IGc1@)WX5 zw3bRZxQ_H1(JBd;q-+xJTY886i59_iy^sHS>-RE~b&vu7`5BjMy`l;%mu#!I{x(r} z+m)sduWEOn8+hu)FcbADZp(iAwbE<&Va{&*m%3ne?2lW7NfV{||DL~^5We8WVrIng zFX7vK!o<@*zq<=gkJ8$_(tCHL>m}22^8k~Re>(j$a!gooCg(Hv`Sx(B&n+Zllaiq} zpWS~`I&t?r+mzR4(_l`%@0{~R&6OlmN&ev7af{jB z=2Ib&*YpVWCOI$1@1gdf2J?upAs_r}TKpe}U7PUdxU+xWpT)ZnCX{&)uMvO5)^e4m z=+upw_aTdnnQSB7JI@w=i(eg46l^-9L*nz$+e270B`H%YI@ zF0MVF5)djZBTOf!43fwHD36aP_6iY>6miBmR#)5VsA@6cy=;7`b)B{&T+b;*k1{2B zvE48yV^FV^Z!69Bli}u{N3&6q_pRw<1x`PW5U^I%jv^H<@h7c_@YmGTdU?rVcz#dk zkxOJn(sBWF)K2=hu!6ecjN3ncta-21^PD{!p-`yDT(G=+pOBc?`g`G(^_?9pEu(T~$_pS$34=8GT_>e&?gjBEpA>xWA#D{W7we0BczNZa)` zuZ~rgd+$9IZmy`Td>J3FX?8I&G4V6f-5pS0uQ)q5H#0r$KQLgdsi~>TM>jK&t#PB; ziB(io)FJR&RExsCnwr}8CBt+_v(md-2%_S<$aeZP4IQ0&TGW?6?)UE9vz%=3Dyyhy zt$VUU!^TGOQa5;d+OoZ)BReMtKR-WzeRsDLeHQ6bZ*OlaXXj{_PY0peh9O8u$jtbM z2Q1QdlCyioPWRjJY zO;&g!-1Fs&q+1!~-tONCM=}>hMa7?u-prDclI!d1{%_xk1gmqWzka>6d+qJ@nGYj( zgAx)LQ`6GWYm-oO7}HN2?yMk#Lqqr~Dk=@QlOvY%56^VIV5h*ylm>mT*xcC(QOzn; zXFGEys@$e)C^72Aix&>g&RX8yiqXm3-1R#cS8N?((98#}YQ( z-yd`1)-4_-r8D>eIRW06FH<9iXK{v~@b_0NaEI>J);tfVK1DlzD^L@N8;n&fzhQV} z^Ximpp17Tf3BB^ss`Ti@1TP<7aH29P1%-yTHu2S~S1}k1zXN^&!(`Q?f3ScoSn{u5 zzvMkuSu&n2pEYmrq-{FcDcu;<;cRJZBRF;H6nbzTYm?CsY}kGThowdrWMN@p{>g{c z%E}53yR|)nUh>JZDFXuomx99SOrK4%!^1;|5eac|@mqH)VR3G5ZfMA0u~^H84^OeN zv5h}Z;^TNZpg;6J+*Fv*|HoUix!Q${+?&ymA#L=RmDFUtZ{KDUyW0@H^z99=ib|&T zv|*|YnLY9~UG45&j(?Ml6qwQ4M}iHFje`>t&*S6cxqld+cOEB%2Rqbgc)G@MnvKnE zX^4NEA&j&_FHWFkY>f5JojaqA-sit&TztO1?t0_qO{<>xvuIYUtK*-`)7C!@4GFPo z3#D3ITvUaq`D>t>xSr?ARy+LR!3d9l0P$Q`4AKQZ8yg$@=jz0?e)|@u%nV0fR#}<* zr<$5mIZ80ohwkOemk`g*1((ven4VkN+J=1nYUDKa>Gkjm85vni6YkjM@zbX^ErCQ; zQ_W+Q_HNV7c$zvoyh1{x&d$!Hl$7nTV#hXytN6b=quFXaH+UGMRIuv=B^FID(#|6; zJffmehmqlq1eo_xtaNmNpFiuKF4EAKzGrXG3xT2&!_k2~*jjp2;dlH@Y47Kw(Mo%2 zz@v>Z`%G>)oa5u;!oot;J9pRtD`=RQwAr?ULqn}`C&!D+%YhK)8GeV3o?c$rZ{Jd! zJ$u&G)wLPY&N28qtY`Z7Z$vWzpEejSQsZ+VFqrSdxwY@7Z(rw`V}ph;Tf2!f*Cl& zI2-HxuXe$~{d+JOJw^zt{(JoAuV3Z9M;?5Ff@ngYoSYQCeXH^G>G_6+hUxiv;uOQs z)>ifLQ9r=+@aSkQ4Gn^OQmjtS&gG95jAZ2GhNiS2(;(6Et`;q|sp>s?Rahtli&~v* zWJ9`QIN!9w%A&tkRXa}*3knL}T3kF@YkH%;6~^i3Ut4D5Nxpj4Q{VOY_ zVe7Q#9`(Og3`3uqN$tUd2W>GbC*k&)zD&EjyABQxs%mO@^L=SLoGe%ALsGId&)j|Z z@S#k#_wMT0W5t^VaTU~g=`xtpB{z|)SJfXp`TWQI@slUq($e%{)SR7wP>uz{j+KH8 z>-i3zr+Ym-`@p7KVS%F%Uo3WS7&mV5tx?f-Q_p2x=0p!nN# z_@h+9YxCZ%^L7vgkH>ts7q5uksv<2ZDH*MC<3%wWIq}&)I?@nMm_^W~UW{2;S=oSd zGBq=sOE9||04LQM!%1Ch{sN$T@G2doyS(?VX!XNikq<^nxFIY7g^r3%j!RiN zkG)LyY(y%Odiu1QRu8VTy?y%YYsIP;#}&3;79*qh zoPX6lp(y=yD17cnwPHl?&cW#D4M@qhkrC!ASFTijWxUBQb?HjG_)Z72#lWYpOiWC0 z?9C9eu8RZQ+dDfm(=9>aFJ2VST=6vq1Cj`ytW>_R)9Gk^2LgA$_S?0il^QE_Hv<#~dL*=*69jGP0BmX?;s*C;Uu z2M4ZCpXxX`2rVx!mpM8*0DpnFSccuh!)NFYb#@X%85ymx zrSRLUpBgmM_VDnidX%Kf)ja(Ewj=YK@$p*_wbLrN1L}KH22@Utcb z&E4H(?zLz1^z>vZc!h<@rBWzKPMyi>7K{_P6bNkY-&9i!l=}1wkBGPC``Q3+uK*I@AKi@!KU&3Sc20Y(Y5^gUexD*XLdo+SOnz~VDiFav^8mbcP9r`7u zgWqxM8ynfO8M^Gd5kc%V=$8HdeeW>0r@OnQ%JG{6QX_Kqj@m7}S7p<{$+#pXX`$eR zl$MGspX}S*7hn7LFEl@&pAcVb>KJYD2U+bHj%YG^0WQEUpaa?v;(pi-om+ZlK!djz2T@k5 z%NKY5UOX> zK%mJ#S!THF{a4oX+O;c4Own%(507d`Mt@U8*f*s;Lq|(%ChoFw_N3pCd~RtewXd)5 z{_Jycu9vzFzApCm_9#`VuC6vsy9B!rtfOlF_+V?H+;v7BNbWa6{#R#NnVG|Y6ID|-Q&U?zv-BpjK*ev!YzNNZyPJOM9hCW(mzP&5e@>RPF@}(C z^xosSc=5G|Z{&*?+V=K>&axLC%^O0srz$F^7J4-RTsG6^~xfNYl!S8_LfNK#73_4WEF3_3_~js?Cftl=LXN zc6N7L0lEREg~Y{m9zBviS9^&rR#+GjM)^sxC%*2DCJcrPqo=863YDek*Diz`=&8Wy zXsQh4#0zNqkQ5`}<7k7I^w7|d>+#_ec?E?b^;_!MvAgg2r+$6%J))tf5Bm1zvdv(Q zR$)m=C-4agyIvNju?ix93Q%C$zzU$kam96`pZ}hpw;n?B^yEF)xy z$)@-|gl~vkf2Rrr3T1Df?@5i{A;Vxp%fD8CWqJW-vUmq!TYRY**%pq7_U2W9E@ z{TUr;E}zJtXhV&3nrvW&OEiyIAXK0QrR~3RiHcJ8_4U<2DU2Qk4cgX|AR_q)nKw** z;fE zH117mn46#Zggf!RwU!wleD>VAd`2(51U%qur)?pQ)EbU=CnWN*(zW#aJFxItz=4d6 z3?Wg`c5&puV0(9WNcgFpon4im4-hEOBDxo+5zxj}v~4>pBaWWGXWGKJ8OR5RhlwLJ z)n7N{EfJ(R#-@Y-2|heJa!k&I%m*yrfXr0qqCsgFD)5|hq#g{5g7|3Z?~f5Cp(8%T zZuOgV%>vYdJ`V(85*!>nz*z(^3JksM+0Omsw6r-WK{_B-(~;M&2gk-D($mjCjz`$x zQqt0RK~+KlO;+|*kaHUKFD@2FF|DvLJdp$~s>>@YMO5*847GK2_{Q7aDD>eI5I7#E zpj1s$JU~@7H_~r^hGcx%Wp%W?D)_OVpECSH`NLldkQJ>%Lv&NVd+h9cZ%aSv=jtJ= zfB%-lGchnTx4~ak+Vuqj5MIi7`Q?wi@1abF*E}n#ZoVX*t2*@x;NiuY3xPxwOarV7 zu)g)}Z*2lv@WhBEptW(dOd^fpl)t4$89ubk9oe#1FRmM-A$fl>KmszzDw|92Vf;$04 zPz@p#WWk-HYp|OTqf>rIe`8q?*KA|m34e|Y?u3^vU0UDV%;|rr%a@a~?4R?NRZm;- z(LCi{&lw`n-EEVT94O5Nlj7m8x)63nk7)=78TmlX*X;0Zlqw$kUbt|<3Y-F6L&M;d z6jl(X6rf*GHcA%}JWn0FD10^30Wu(21yPo*hpIP=fCdr=0gj5w)B5^nh5#wPlda6m z;4w2Zqe-l#rR527Xnih5W$2a~R9@hKG!dHeuG1LE6IvP?%+se&$CW>nmC=AjRO7uT zmMCuVqWYvh{J{>9hV0ijt)A6~#H`Pvmn*v%39#%H{m~KRPdpn{D^>{i4 z!SVtahcz@Pp;b5Z2b#v2k%ho15;p zbbESxDc`?;|Gh{*^;%p?2{<9{j~f z%&zY=NS+o1JPEMc0zu_KF#+f5IXrsn@Gw)Zc61;RC1PS?ODn4YC@TY`*2nU2Fl*P$r5(-m4fBr1gE32)hFS%rn9(b3VKvk`(A|3pTv>LpNIeEj^V6$&)~-2x!zv`kE)K%_Ob zv|0eJy!ZZfd@nMgWnc(?wD5H%Kk07H0d=07pQ$MW=;KS?LU9!Xd8BuAbxD1%uT3^S zN4+N=9{h#=%r}1VLqk`8)+0};QC-}GsPNH|!4h0SWSqXKqkmhFkFOcR5Mr}+d+FQE z>}()PcEIw0^ln@8+fzIPNgomtQuAa5Em$uB!JsNOU^l;@8V@ik2r~MXU0S>^G8cWG zhLbY}5F-n6z#vgHyF0Sr6{7g`pUis%e}4g#(B@>LHwvJrE_7+!VS=zn#f#|e>Zsk% zd~*Gll@AEPP(;bc`(~Y20-*9XH#Y|c2K+%QwLzT*s|mGubvS*4!ATsclJvN8g%%|) zz@LIr&yrJ60FdIP7!sSAncaF9CC?930R033r33WUa^dUi?-6q=D+XT_V*ea~edkz= zMSZJT*7D<5zh5>T|8;S7cgN2%76s*KI+_X6rn|cvXd|fJEb57tAd)M$Zt2ezQJ;}l zWvl<$gm9uUK}Szd%g7i4np0gYDfivGsA0dN($X%t{LA$8sGmR0#}Ur`p?m{W;%8=Z zPI|9h1ZId5CR8_p;Bp`V;{GBVLPNZ9o9^5jMc>26U_CYW_ftcODXXsT1d-)%^_q?j z3CfhxRS*s^_1+XD0ELD4r2>5T9{lawHv%whSI0k40Fy+Sc=QW2nE|I>BJuITd3k&w z*spLiu(C!#!Vh)IgBEO|5O44YSzJ|Jjrw80OVKhU%h&)FOeXl-uV3tTc9GiBdHR2H zw4OW67eloJSI!NXjCqqEdqhNpJd}=4hsz@4P1X7NL=a?vN(EzuV`F1gHVkBU*jZSz z_WT(T8Qz<>|mQazIbLp7j2&Z-rtXxtt$sB#ue zp)tLForjwnkBaI)gVV=H={0R!p!bx|78Qg?-@S8UV%h*IsCnl2O`tbLI&7X7m81|y z-``zu9O6q?@}fiFcDnldDAYoXNcv$t@Bf3(rGOxodu~{h5=MT#29+9!X6H*@o!I1L zQq<-DYBm3=sfr=M$;rw0X_{lA9Phird zWMtXdsQ~QoFW`fakWe!uq}#ur7f%17hZ6%6?DUMC{=rB0Kl;GPb4p8H-j&Du8wyYm zF?>3!h9F3_sc`-|@(ycBw1ENO0ibfFp8o*v73T|8B+H@aQZXJrIlYdHi@30eh#S~9 z#TWI`eZerE^qix5madw$7;yken$j7c6d$iD%EWvAd=mL;U?Bef;o&TJx+o=x78Ljs zj5okz4v7f%v4*4L*$;F0sOyaSkWbg{Djls>%E)4&z@Wt+_+&X$z~C?>tZjHW@uUze z1}pGkz|9i1_ypYn46uYY@O`gCMNYyHPL>2&?m!+1-M1q0FRhy-V3aG&F++xlp4Qd1vK0gIEFN8!1sh+7y8lr{Krt2l{VVx zN6V}TzzRdH@{zmV(UV`GPYE6_^-KQW%0Iq;pN6EVN>tAJ%)Yd`n)io6S53Fp9JR50 z)>}w)FJBHb7HS7SJ6r`jLoHKW3U>gf>AEl_^2hxGIODNhI|r_#y!-F}00i7+E65I1Hw^sz83otLDKDo5`!iX> z3Lmv_a3_0BC_8d>mGEVWm`l|3e*F0HfUBYP(MM?PMA-b!26$F;bCdjZFpsc_-fduk zI*xWOfVYK#m4GT`RQJ+waJ;zay=yuA?j|$`LtnpUzk^Q^qJBovgA%&19i!zoz(%zH zRsiFCoM>Pu$VbP0{ya0-&?xkOU`|U(nOUD{lQGMIs?RKbH&2-WQ^nT~`D0~cqoHy3 zB3O+}$daBJGulHWl<2-IKr0FU#pC%K78Ws3#(1GKH2zLRMC4^!+H+QEJ1#}VwDAlr z9$K^!Gt1n47FD*#M|Gdc*?s%OLhv&^4*z^9N0S0{dnI@;?0e^R@_j!Rdtsoj!+lHxU{keXBUR zn7o|(z^h=-*q{;f&HF6V^CFW}?1}FCwBh0F`v(VTrx}F5yxS}x*wX9EZ%cD3D(K*o z!s23eNH0LjFsKZcU(+w34LJarC!f9|85h}}Jb41Bp5;ZyCg-FI)(jmTo$=MH_|R2> z9;-FrQkBQ|00I(J96%7I3MIUHg%7HYLIOXF(RXEe*>z?3oDvSZB|~romNaNMe1Go1 zc+w6Lvl1@Q(kPVxufq*~E7ffkOe2l3Q&w=MH!AI@Hj%BZK}adoX@u_ratFP6BZxva zR1?tcS!HFh3VtIXjZk9Htq#6{p(xJIdFs>gpTtBamMtO-99|_M=ssONy$cUr6LJaB z4-8urhb)(m`nR^QO1Qahad46pP9;Aivo20+zOGy_E7(v_ha*%{=|}pvRQ#~`A|h|+ zg3bBp5?F%L<+<-acmQn_*)OB&#tEB}M2NnAq~4m!`nM-=HI;sx=f<~FXFGWW&F|3= zcGi(erHFo?n7Ex!EXUZS%O`xZ-ov?$yOwO|+qaR5HJtABdE)akvj<)$Iw=+cae6FW z`cM9Rv_w8Dm2+o3EJHf?>EeI+%-e@D1@;6_>9#`qql9%63wkO&&oOg*`*AmzxgVYt z?u5Y4WEiCq>^;h0i>Xc3xH4-C++0up83Hz`6vJ1EiQ2gS&!1xp6-o=HhBU}A#_<>B z2z5!=Ie6I$uqP=h7!!Z&4a59k!@mAcxI-VN8Xw&13WEIHPlygUV7Mj1P zQ~Hb;4B+eX&dl@haET@Av@nnTol@kzTR{ocr<216Mk3FlXRCkdJ)vPOzND5QKSb5|Si{$MHgHC~v@%s2PSwIC#&jE@p;?5+6?X z^-=wnc4lvBp!SE)m9!<|L;UJ$YX_O>K}g>EBeqWdzt4q|TP;lTs1MB9_?uxZN}lU1 zGoL?yR@Ko7)8`);9|v#t6by(sJh?kb^1oZq+}phz><4Z4V0DBW!zC-5@K2{zt-ih< zPbeO5q+P=A{~m>(s6CQ^Eg@hgqf9SmN-pyyv4sV%k#1J|G zt$J0|)!g=2;?EkKzj7hIMCiJ$d-=y7!^0rFCxq}Ts;jRr$(d}jX&gw@YV$Om%|s)G zvl}}eA2^WLp8UUT$4vkI+xG{HJR_hDL=gkS#n1nzM)H76JfLWwthDH#3SK`7AH0cE z&*MG0Sl%63kTgGMB_1Ci*H_nEsadB0wHhUcB^_1YcMB<6Q~BR-Cr!aK7>w=0uPHpq zbes8Tc`EpeB_*DXyReBufgi?@%qGQGTUf>NaINJ#wjdNKD#f|YGlQ(hum}@Im!Fa9 zpo{A6PP6p%Yu;Az3+(zq=vYjaQnz;OHp^*^Z>>xi`Z%0MkkE^iv{X_)r2&0(7(#i$ z7GyDYBg*SosmcB1WfmstT(Hj2R%s8j{b%nMtpg=7tPHvCH;veg45P*YXdx#Qym@0V zTyjSQ;m?%(D5+vX{8HDnbvIbri;VdKb6nDKZ5=LU;`4#6)Xl<=ANMq*jcu{Lb15T5 z_c_IEe#{@rZiv+5dgn}ish9Uv&I!K~&6En^Xv5;Z?Ikza6vaYYY zgXj9}vjL+FnVkDOIea~4t0KzYM?&?dY$lYb@ND<=Irsjd8{xI|?9^`W6jbM-$;nf< zZ{LpYV)DJh$1N^4;iWVQx=Ql%7NQ!w>nkgcA)T+`eDp!$s_G?Gr#@G3Xt-4@cMap6 z?EC#wGUFZzr8O24FiX?1^>lVLB(}F}_VjfSX7xVKrJm_wG(WhO(j7`reL-i;dsoi3 zfFlstgFei+p!cl$`0>FR&I!Uir+S4&_uhWI@e?~whfd$VdROI`xD4cL{$QWI}!mszxLvG=5$EYiP|lUuryw|VNlGEV=-u*fl7vU z9W5Ol4>uB>O<1`8v`n*2SkewxlzbwaM<;a4)zhJH>tC&cg@`?8GdP6M+;4Gg(qT6b z=DR|-ynAh4XF4!4lDwq;h30yz1rlSKieRAQs^R#dt7T!Oe20LB-%_~d!VP>j-XfJ| zW4PcA_eV1W&h)M~a^BKS=V8zhl7)pgSIB5)EUsP4|8hf{;rn}h(0}=w>pGC3GH0VM zs~pEy(n)ku{_@Y->s4*FV8h!Jn$k(oH83zKB3zelv=bPuJer)mTZT-rxihL7D)DW9 z>uY)CH#{(;cuzKK?HY#m1|$NO2fuSDKnEth3x$sCvf`m`4J$E;cc-K#vT&+ER5a zLSS-s@iwiDYBnL_ueL?)M~Bs9l}HH8_Q4Ol6xl>z5cZVg!=;%7trKV$7x}ndm>fmp zAU3JGtGFl9j@)lk#k-^Vl)(=H>c9uX+oXZnAx&4o;OV+ys!cMnO@M(Gao#B0XPy^2}&E5Zrp`@=()m_v}h)2C|eN+1UKnK=7Ng|Ge3dc}MqcG3zB|vHnE8jvNPG{WNqkJ9A{uZfP{yhJ|&NrMIk()hT4Z*C#6rX)3Y&x|%R{ zB6}83phg(FJK8mMbwfCvGLuohR!$7`nGSD|;zC2SAL)YdJc|K4k?aZ~?8p87jYkjM zOPuDXrlwpNq#qDS+?&5_cZ@tlM77(RI#iBrlLNG+IIdzeJ&UApg+ap7#+NV0Y=gT@ zouU^Xur44d$g8O6{rLjskDhpOJjQ0eG~zmca%=jRRg2ej(-nuti5IajrxMdXmew7t z($artpMX4!vm6JCvF;a8NMSe%cn*zabH^S=&v>;~r7`f(5ltB86+OqOo+L#2M1bdx z1Y6KNr)A-^3+5}ie@%e(;fSU_SJ7&Rp$mp|JVC!FdcIguwTN2v=4=v(X5VuA9~>MU z8p`%O7cSg>nF7@zdO#qB|)N5cmWai2ShnJ1bAGX3QwOtmii zLjSmh0co|kWo8zZntD1KRp`)~WOKX`ibuP9kEnTYo@MGiZ2!Q_uvUAf?E#a4ja~Tm+bG?Wc3zm0g9$8|LqSn;A}EhViO_fq@=; zCs{qy=d0lEXI~@s9iEZ#@XR z7czondLb&%=nNX~PfJaeu>X3-X}qdiMn32oNSJnXmOz(RiW0h@dG595>Z^OKtgONb z&HY~U{e-luP67SI8wknbH`<>V4CPEe!~W`?Mz1Ox?@aZ(X3rPX)!NNpuWk7S85d!; z8NZbN^?LT~Szh}+&EO`5iCW=+PNtK#kZd9qdazj?oSZaaTE(AshR}`zF^SRPzw5K1 z1%~&R?`;DjnmjK}LHUK#4G@F$AwHe3l&wdL8U_*)#)yj@mz?QWEUSY=&bqj_4z$HZ?kc`y$gICy=roC+J3a{^VHAU4nbeF+#YTI3d*Lw_97^re5pFHl z@!=$5u3>R7tCj~tXRlyNH2UZ?&-ok%)%DEC!DgYhEW`b&fL0mJ^ybhW0^=l%oFlb= zwKhViXJPW|sXI+N1ExHiEte@)xj0~Vdt3KyaWUU&LYP>`67(~Tj!%U$U=5?VCUD_& zCzz*rXcAAqWT6J-$wL>Br%C2|VSYhji&KW6Xgdhac{duid%H~k=FOYVYki)GtlL8#jh;_CNn?K+{g#Y{Zu$T}NqM|Cqpf1F4vTBX}5%3P5 zI5&XfD!%4EeOl9}5S5!m7-|tb9&EV=CAMhP@`XhX;pjv%&ca*mr2#|fbA&#bRF+3I zf@h$BPbS4nIz+&pWL3yu50I_wkZjr(*N7is<&~X+BEQ*(WgqsmD?|Z<$@&KIdR||1V$c z`eidaF@JqyBB%`Ndd#PhA(cH8d7*k4{s5uoc{X zPimM>rgSw#rA7BN1vP!Zx!>T><)L%K?tdchdZn+sno00XuMmge2ry6RF^cuq`<9<^XpFSke?3VV zDWR+zpWdM*lS!X@LL`p8L@_V?GxkiVQqw2PLhqKHLzHbD0SPlm7`T2u*GzB`K3Is) zc6f)Zyb<84Am>tKsXJR<;oLcEDtC0Aut`|UGIC|1)kSnhg|2k!yCv>~vah34w+vMu*1# z&#}f zY!#E2N@=sCf{S#8@oop)EQU^{UgAtr=NkG0A$h%MWCiXT`x^?CE%V+-l~Zro2o&Gw zFsjg=fCt(WT5w)dTYL8J$0-gjeN{&TU3?zw+R99a(v)sjehyDJ{MVR}GqCHkN|Jnl zJbPBB`D+0&|C&ukVqjo)FEQcVFf(Fzb8I#!KVPI~v$9skt@v5#eW%peo7b!5E8jVl zf7Ox+4k(5}_B4lG>4|a?NWTMS(pUjx6IL7D`o;?zO#97V7@$kVl zo@v=1bJj5tD{f9SGb%2VO6agGbi%ju#mg9@kWTl3RRxy1S>>qf)EX`|rlx#knNqel z$gUik^7Ytpj&r=BlKRra^oE$onf=s%j~5Vt_aHzu%fy#jfW*w`PH9qfib101F^{}w zo9n*4*v(lY_R`l>JiR~qsz~Cf`SaWiVVVsF;rYz%7M#kOkURTRH<~65wW|g_G4M)3 zgrNXI)`SZ`+(d--1dRy^Gj;R*q?4m55e`ZrpH%ahKlqpU$H$KFBJH_%?J5Z|UoW|S zH|SE{%s8$!7fXV^<*Ut1XllZIw1o7W+{mYAJHi-C7>Pt@R-la}mp*g9oi`WrKT9s) zBr_=qdGoE}I$K#n^V_BaD#4Q(a-?9uPGzz9%$*)W{;g6ueg9P)*p26D`2UMSwwkUG zbOrW2Sd*Z@YU{tZUiV2Y8>*%fVqFuO;aFB)C5b&DW*7;+lqSDH-*UnH4~c^y_Gav< zk7k%hbj@-kMQzhNPe};_t6eP6LM-ANw$75U+B^(#XP*W!)b z)t}~_w(!;vbU20zu9(*(7ruMf4&8mTAPPiPhiILod^G6*w>&$0|CmzeLUOALnBBlI z;Uxu$I=a!#KS`wPduCrs#Vcck?UM@jimM$(e7aAXNKZ|w65iSz%K!QxC=mI+DILPO z)um!SQ~DxqMY3+al!`pCV8uRAh|@ClOysolhxp*h^EhXrLVEEu5ZpE05^&(*6Z#OD41`U%> zQ(Kpp-Vo)eqgt1(qQf8ztt#ivQ2{ZsEFq?h#vq6(<@lVium~+i=+F6(J_}A2noE|c z1m7+dm_0M8NV^t$96t+$4R1V{ZY`@E2;ph#FuZeIFeen&pkZYG&r1$ zA5`u%4etqtmuTMJ&AB)_eZPLe{kU!)FP=SjWrzBFd@Lzfwy}fhO#gf)Gs_JUXv2@6 zHn{$NQz~y=uyO&WA{2s7=5BDV%Dip&tF^{YL}FuAarUL3N2)$pUb;9}d!uXa0kuo)X*58Hp- z6wP)?0E_o;q||vkzPSH!r+ypW8yF~UsP12d+AaK z@^lOLf?3OYHOb8SU`%}D7q*GOI5`Y&+T!WjbpPJJ85f%_1Du>k!(%uy8A$r}{2dPS zTWj1qCr`dMXwv2v6z~WON0#WzfSf@`As+Xd$4C=#qzG}TW^YthR7Bm!nRVipUHqi) z5n)&?_T%y|U~(x4>DaApYzQ!($oh1^r26r9+aFTwrOPE231xriBHBYNzU@$lWs=Ry z(y?sSU+)mNl@BG`K8J;4*34#*5ZB%JdwwXI6`m^VYpOP>qt6 zyf!sziDKgMr?dSlI19=TBG#oDpi8wiAV+8Le(5lQ{b=~M%Tj{Hubq{k%xDmlFqg@8 zZ7?l0lk^1MXTn4#kSZ33CYvRa{mP>$RvwYO{XDa?kDEOF;sc8-yNo<87=Ne57Zn~2 zCRE*O79n&J($aDB3&?^A{jjco-Br4nU@~1kI=#!83PjUy7So`29>&o*^Ic^yH1pyS z34wp1!}kxUv!iWASyjRL0k(?LR}-U7a@=JLxI0 z_~B-5H)Xyrdk5#bPnN7-0*)uSnucP1?YhX97sK}NdENVw&rVY?LCR+`=&f*hINGb? zVej8qy?GColZ=KT)<}~%hBXUd^*BrZRslt3nwkF4B70okivbu(mxOnm&L})y%=X=W zk7+oeV_iB*`mAe#xf>+jXbGk_OyZ!x>Ix+sJswL+(Mfwm)Wq65Z5s zwW449`j8(iWVzyO@{+#LBc9G>6j?rbm3VywMj7Cx#vma)xyOxu&XwWUddWt=ym0II7Vp;vry=JWiUA3GCqEo-EaT1RwTmlQ%Lgs?Qo~M zAls)8RHb}V!W+j#t(qRQQkVZ(Gw^0NL$nFd_ntgnRCIC%V)J`?RS4TD+ZkartB&$A zKQMqRFjxo;%PWx418>O|#b3T;f(|qKrq2of4eZ;jtjn1T%;X{HjE!;Ov-kF&`Guh~ zb9O(a+nO;UfizP}%l=e}oGYDeR!T3~JYq6&xCin0E zdUfq>1BMH#wYZ*Yb1dhWtMjxIEKtM$Lj8}&$8C&(gsU`&nGJ=XfQlX=LA;{RPBx(( zoSI(Z$DDi3#M#uT7>v7g2YFVbGXpSU(cC(ToJ>2>Kq)JoJ!GOe9T#8%P)QmD-bNk zUN@De=gy*12`KmxShq5=Yo7YTiX3?{qM}K9cIuB{hMlD3 zZet`^;IBKo8DT;VeUF5A(s%C;o&+UPmQ&FtB-`^FyrNd&be1PBLSnYk$P;W&arpf& z7lcG*#zkP_4!pl2FV$bZ11-cQq-i!?UeYDESrOq}k5eY34kFmv)i-^}&Vvb+fQFHg zot3vb0p%N|QIw_sTK3Ed4}nhs$0+(ao}oPmLwLn~I|KJd&_z7)-3+nrQ>3N``}Nr# zK^Z!80xICJ={mXP6F0XVPXDm`c#O=;|j z%JG#V=FMBGbc0thQYSN{c-NFkueF-6HhuEpLJ4SWN@=kYi7j?4P3~73&|KyV zU1UN|U&n<5ps5nqcY>!SomA4YVz9AMGTgbgZPrPf814fEQ%6`!Xi9S9OQX7F=rJpLo^Ot-ZZb(oM=f zT-^pq&(yNk6ZG)$mwTI!4@chJ43Z59_%4~=@VLlqx8PFxnHa+t@7{^_Sc%e{Ou39s z?^u>)Ha9dkD>xiPEg6s{r=;jzvmN^HVVqCeg6kv;gT#6irKIQx2trq=`sE~%rF-~8 zrU#H|bnwa)L@OJ`q41g|DL;lXnov?xH>)5;#mw(cFou~kT;OEpQ1w(|VhIbw344*6 z+U>Dw`w}eWqgdJc#ykO*L&fW1=rd^bT+9Qt^mq8BMbcX4O_FemZL0;&e=PCr2KOk8?~1?osTn6M)NFABC*8kQsK$w(Rzw&|ASG=R zhIjft5r&fSqz>3B#!P4{fO7BfgJdJ6cKwZ&jYBinrHBWSYd2VNLD$}f20uF$26yIc z4j0O?dnehjGkjb44Ho9h6cj`0>FEatv$5sgEAKxNLv`gvjNf9OVQ#32%-m_b(ihbf zcI0J9?mMz0sr{PES6h9l!rZK@^vglj@l4SiBpPvzU*mT@smE1pYLPLQUrTY^IS6B; zd;6A5J5!>QB{@);hev(M`wqN*`#Y@q<#3!Z@7udzJrFRc-?k8+_ey~G`W=51=`a`0 zv2!^DeWQr=NclBw1(8! z7<-6%l|GLu|M0*@X(vSyb9ZPrv^-dD>X++sKcTe!`T$ zl^5_-!Q9vy2!prAyTba4@z7RpR9`nb(xTF@LU(Y9DF6Rl3M_U5hj%l`?;$B!;!OmKCDJZA-G1y(MI36xlPfA{h;P6Ed>>uJe3; zU;jKk$8n$ge!s8xYhBlAufSO;#fjrUt~@m~@lvt#w0Y#@?&aj>ibDBjl)Y|?NmnEY zAKIqK|7DZN7gw+uruoX~RmUHG6(Xs&ftNS~1h%WA{{l-MzO&m@qvS4#oxX4r4OiVg zTkSdT+Q|BM6v&$3V30bnY?NhQtX@{!-_T!8wfeJgm5WQwk#Bc9&Veut{(Ef*xsAba z%OG{`vefh*RTRDPv(8rAS#?k@ZRTsoe#nJN+N?ah9rrt+!F>H z@@LDb&i?s}6jWI9c+(M*AF%JZ8b?{{UHu(HwxNFTERf`MzuU!rpz@)#HBC{L z$H{lPs6EcgW4SW~X>5Ov zQ!lo|B4|99E0nEhq}N*}{!?(s_c_mpG+)Kr@}C{#xtJHuFFSsYGQ=s}{;ur)VkmlZ z;b~LtU+UuZvR4){`Pj`hO^snQQR1kiIsb|$CGP-r?1S-pG6~XH^gk~E2blOz1r{hatnsfWahO-af;XwdCU*; zm>2>H$kiA8<`*t?b#|(XH>ohByr$sgPGild=cD;AaVb$i_mdr)Nu^R+c`^yeZAwcfTb4_se~G9R;y5 zqy4Os^7CfTX3FB?;%`dY4MJmMW2|Cg6#2KJl`RoV7CwIdou8gVR-03`-@eMZOo@H_ z_RX?CMR=m#lRKId*&UE%CBY@3p?U5!S~%OED*Ex+k;r|&O>r-8@2`KGe|&K3$&mIe z+CCXV&O>NL?PpqpF8LlzI;@f_3PJ5%|B5^Mn=LVaEXak_4Ub0 z-o4Y))5Aazg{C?95VViCiHa5(^*efGM8D?4hxwoNp3fsA+a{`P^eil5iw)l9m6YIGyEPuG7nKU&mi-07yTtggOcYD)j&#S8a~bAM-R zQ{;mybkT zk#S{hEss=`!}ddQG2VPnY|pp_qHRhlVk~TBWmQyG_C_vkeSJMXBZI)l$H&mfD7Uhb zq^zv0#!z(imHW=z%?t%3>tOxyC^ZmBmCsMa3p5nfzMZ$J_f&ZJOHS zy*HZ4?(5&LeO`QYcyu&-dbFD&>Oe&Jju00&u&GH-Sy|cg!Goxk6-QjGzRQ2kkh3$P zx2K{f_%kgRCoLA4^8PZezZ$}z)Redqzs6m!GSND*Ngz@z5VU{rfM5P-fn4hPb#^wk z;MelcU%XI;T^|`8#Xw~v=h9qSDT*h5x;r~_U{C!0{iUAn@nk(+<2C!}j?r@1CAi&& z!`#}_gCigykRs#F_jq$E?DJ4@!mS+O@9ENOEECHA4z& zYIb>fCT9OVQmAF8aUlf-g?r`(0?F*Wym&U($M_nz+pmbd+gbUV?>iUCU1YztvC$cJg<8m_n}C9n@+)qJdLqI#ySF;ZbMiXl2z?K$;%aA>OjKCNC?%hl`4V_b)%-Po*VW}t$4bqh^N$|h3VI?U+Ajw$NNl{ zMd8Xm-e5mK$HBp2iJTtpe0;jk_aZ9FW8pLD;qmdvavp5??c29&ejeoBh}d38)M1m5 zpn`gy_~^mjX)V05u`xV48shS!?(0)IIDftuXaByAk4Io%p&Aaj}gc7Aq3%FG-K z=hf@+V>W=Ax3@F%2o2Qm;?~D2=G()r7zzczAANkhNr$-p{1^oHxW>;`NQkNtu~$*S zvbM2tDj?z=h)Yh6fI?xAeuOooa3Sk|`+J#b1oeGij88sWw=6AL(ACh{({n>0IlrNS zE;>58vZ_i6PP5A}In=cO$w4lx&fwsn@A2x}+2!Sk-@oq{ynWlz)rGzOy)2(ppI*{6 z6iH8~H^NsT>05k+-h5d9*2X8hGwbVDBqb$%eSKSphGNqY0D;YCx1P~`|Ngy(?&00L zv<3RSfGY7RDY!T|I2qS{Vvcp;Oba3B&$KdSC@+qNknMGg3%bqC&Cde^U1ul%zD`YP z3^2R8y3#N(gy!e7-@A8jW@{_f4QV-}s;#YESzqrU*O65kU`9E{;Cp;-Mpursb9*Qr zDk*^Vk<0Jjzb61;Mn*<-jf}!(W-P@dB=RaMhywxww*USO*5bOMu8!yOP{H{d4+j@l z9sr|ADnU$43}6WkeALQTUP}w}QWBzH{O!~#r$AcW%xv1yQaSI9xT7Ugw94*w&->G*P%IZSj zbySY`TwxP`yKa;2#YsM|gP&|Kr)`w(YoGz!xJ`pLSuXdZ3Z`hE3 zw17)>?H-nnj?Tl0N(>_-Bj59*Wl{zPf?~w*#a8o4%z><{vvWJ_lb*40#Q1$bLiA24 z1jxc|-6=Oy*Hq`=@LJH~_Lcd`A3tn>G%G)RP=(jv z(?T~k9;)2BHIk+fMJ-t9vDsO5`x%*pgaiO|SX9)N?-drYKzWGF4Zp3Xf5VfL>Y4_~ z;cNuJtCG1nV?tu$*NKVeg@s&L*x0#cWrXMF=S3A25s8W9GS{ycp9S>9Fyays-O|v& z*U;3APfd+HK7JY+9zNGWtkC&)@r%dlp~qE|N>pp?fgc-guf`4lNzKg_(IMH8XnM(! zRNmBU2}C9ZNr;NSzg%<<+af|vM&^EU;Bv1gVDi14*UeiAb*{e~BY|2nU;DF6t{0R) zv$kgY`}Z$e34Hu0b#M7aDN$-6&s_5HM)i=Rg#++3Y`YDVESk9iEInpgG2nQPx*8WW zEq?TvcZ@DdNue=o^dPhTu`ghoV+8VRESKHGl$ppTD_cYOG;6L3Koj^4!7l=a@q zSCXi%iN+_Qd3kx2e*aumR8)rLuXGkSAQu77WK+%l*X;+=!otHZV_{)gjuas3u;4+} z)uQlZl@3Epu&cxU4*KrfnLfXBo25Ma6sjvwTsm2&&Q4CeAV1k;IS^x<+DmQOh?Jf-*?pGk%*J-7trN0iEV+Ns2>mKHs zXVB5nk&uxEBNr#rNL;V2nubPjY%DP)2fR(JF5NvbAe&miEJrjHgw6~++xGT$tIxE* zD)wZRO%DkGYr3S{i2e7htSmHgKi-%KDk$JMJUN-4X$vu_w8Ut>IQK)>Yr0!=8?f=r z+*~lQ&Rhtwe2&LHh`*ZQ3H0j6#gT}KBjUNm#gQ_(&Btr}4D!!XB*M4%_rpGXkbL;? zp{~AuFen2{D7B)Zq8#Btv|q4{2VH$-y!8M$%A{hI*+@@29bcW8kHY98Kl zbmWmgUSUs4N@7t^$Ucy;|6bbSy^c@;sDZv7{_!KKyje1^wC0}6*Z1vldIkF?5d7i8w2T*qoK8jhd`9REaKvn z$jOiCZSWFbDaBUTC`m{Zx#h_sv6OR3w6(RRp8Vzb?K@BS?fZ9qB({FR;{N@tCzME_ zA)o)N&a9rUuG#!p`Mlo&BT_c*?j#{0A%}n~Eb(fN{%#;+(RBrUW|%&ZB7BLLm$zo= ztlo3E5=sJ8&?pvX0&i+kQmA?&*DNsCo7$i1gs*rF3Rxs2eM}5{rZ3KYu9|%$$qqQ? zRlad!=V&>5R4wxF-$ykckPrE_wUlm+JC_0KGcq%0XJ>=Z*i%%53q^`n4y&=*dq#2| zb6DOP3HH=LmNx+h%ZNqn`)R(7kJ}7o$$jqY%QMfOo1gzWI(oxYdoWG>3drpa=Z#B! z95roiN(6+2xwW<4CLeNv5<0uOlyY^4yMfw*>()OZPjjZW?vcK4+;sn z#K6EX{Pk-Pu*}aUKWb5jK@~eYPN>42{c(%=UheEr#hi_qnaIZ@(8Aip{Joy1l5E-*q|Zm>Ll(xO6NdWjEs%v z&(8!an^jRL7L>Y*lHrNr4i*lM!Kcm1Y6mL^2Q-{D9?nHo*4DnU<0B&@t8^OWvbDFL zo2q@_4yr$_1}%?FHJd**`Tb)9>jT8xo_8}!7pSz%^n*3pN&+718yKL;dv4AeZcvdc z(F$JY;X!y>3)B-}?0R?Z-11aai$Np6V1{(a^y!kME)T^DNbN%H^h)b4{AWjt$!I_6 ze=G)^F#P>{I0(Pt=hwKoxf@TAKc7;>A5aa*fJ4IvCmau&^Zk1fIMOztjK482t*yO4 z({R-5-xP!eF+cmCj?oTnGt~8 zk@4enQKqM(Dyzb3iYR?2gUp!xK#=H9^p z7%J-C-rkSCJ8WpK3JSsi89hQ2*tzld;D;O9c%Thg**_hPb}+BQFB%K_0ztJ!i^#gq zpw8D@&aZ&dv-iPlIa*4u0LhA`SWZsP!^xq5aJbmL#lgP57vE!JV`93)kSo+hIE{IE z!4lSJIZhZW>$O4x`w1e0HD0YKF!M>P(lj8T!Th$D=~U!3HFiN z;u$Fd;@92BM^#6M7;*q%a5ZUX4)DA7c4ah$0@Rwc1jso*cz_mWV8ZV)Spuy(Iy>h{ z=qBhctghlIPICLeR^bv7zS(y`i#75lEKH1OzT@+gEvI)a0DB{3BVgv?4P8*N!v4oz zAQa|+9CPOb&XE0aC$UK2|2t*(!eHak8scDM5@g)lUQzroOmr<*56MS0H_Jc#-I)4a z=`WD+Y)3?uWgDgpIu78@3OII}`0>L)^aWhS%*;&4u8#sd>ZrXO6BCoWheyz>SCrcI zf_!}KP}?gnf5T>E`ybHi>+6T}wiF-*9Hpioh|mff|H>7Q!)+_G`bXH5l$5^fWgi@c z%U{2ynsVm=|MjEJ1)Ut+Gc^@<`z_m_A)Pol6~iQl4+goqD;sQX>HQ`;JUl$Hnr{OG zgkWNe-n|QfszB?^&Q6t|4c=EkW;wdKMQCy5^Vc>s$bhw-Uq>ohn5ZrZP~bb!4|hZm zqrnh7#hx@-q>7jUqwZsI_Fl)gI@#Ttf=yT;?BT&We*b1d#}t75RsJWB%|1PjzN{Ko zR1JSU5AgK1MG&+B`j7wsMZmM84<%S@2893yvdGXS;WxE;Qy1Ud>}8jkct3!(r* znUstS)6LCoO1`$B01G0JkDkj!Aj)H)`gA?V!B>-j9UOaSJa61`Ou2biiEebd@dksW;}Z?u{6Gj!p|9!}rknjw`ro0Tx{mlF z*@1Xl!wKo*;^G2NPoF`+@>N;?&Ye3eD=Rs-jYdk-`n}A}&GmG31L2&{)sElq0B3|- zZx*vN--BLX*d(dP8#D}<4aE!s!(>*#ms$m+gaT;~sUo*P*H&BWtADWOd0cG(9WsSr*+G|~u@a44 z@+A-*jyxx`Rz~O;7*xEy#UZ>xMXCg&W5$}AnMm#|6zblcz==X~a`O1Jv=<>b#Cg@# zD;0aBWjni|K{)D(ah$KdVlo4`kCk8XVbN!XG?+|;3mhliB+8pUR=R-bYr zn->7^-rXiR8TS1tLEyvw3oZ2c5I#Qle}Bw@e669#)V@D3A_51XF$B;A9kI5Y?^mGl3Iy%U(m=Y}?c2AktXSLI+qXf{&w-1h5w$0H z`t+$|s*C=?S=oo*%8wq2)VWQ^eE)vu>fQIDT>NR8=bOkxRYxQK4D-cd&pW?^jUaHw z@@IPnr+<7}I);Zy1k4*k?Y_MJ%9PrTZ@Rp zOI9{EXr$Sgs0xws0Ojv=7w5ff3kU-3R|>F%+Oq6*774O{lUq))As0X;z2IbF3B*4E zfMdUQjSyI3U|?X+>N>D5A0MBi>^|gQPBzJ46=uP6wL-oJTNQD)+8%^o&inTX-vgW= zYjedP1JcCb0VghCt$=N4AwTIU(#v!p^LLyDuS394f~-G)_Zw* zwZi!)A|gVkP~w!0r+>eQg^q%TxpSxQmS};-BIrHGr4raZSU!)Xep;XfLbL(}Y~AUi zwirII1s4Q?xC%(1fm;J#zT`9JtF5dJBf}(3I0ZShy~;6=JO^FEaX&wOl2-cwFaSO` zZ9v+p9V%E~lg@u>Vr`Of>7Cb+&!RpHtik~M? zgDg~0PFxS*ID#@qHy9xIu!eLPgp=LMWL@LXQ# zO+<^qt|;moEV_@&K^xwHYY{Qazl3M%=tm|HdDF?CPaw*>W@ctg40th8wW#oT{0%Vc&9b;(X*fkGSDCzo^aUM^qB+)89SI0r zh+rq-Nq>~+92hv#3D6msmPW@Q>l^2+L*_6&HWv2b_tPjQZW10p>+@9|Bu^N&Vi7VH z9v+??%ukT=LE8K=;7kS{M0Gw=UD^s&gKO;Iz@3qip{u8-wD}P=JT``nh7ka&A-R7H z+Jw`<+gZr@6X+2jXxRed+1<;lK%wNt3w%%*`B3R!k_96aSz3QL`R$zU4&^sCW(;9NlaZcKs=}W{e6XRyd8j6$N)sf~HRJsgOIZ5Rjn6 z>*G?62M2GXBX8gpNK|rCMcUaj*cc~c|yAg zo&N`bxh3+`Rcov0?!Kj!Aw?SaUaSM{F}zmw?`0;6Nptu0Ls>L6HK78*UG=9+694Ci z(TxqTPlA<>U)d-qC@iOHoX|nFwl-neW*(x;Q|Y~aN5=DVQg3j9h`p*R4&>{wa6uCj zCMB(qp$z}}6%8`m3Q{>V{oM~ZvfJC+n}OwabaHBgIBI7%`+@MW$J?Aq(Aca^oF5s`IxGJO&AVLBk4NpsC4Q_2GqAO*eW8X6jo4>~Ja z&gsCfqh&lmyb2pB91<-`0|*bE`TOtu_S>4(L5|4*XGlm$0>MCAea*XBSyy+j66%l!4amI;m_cWPxmttUzh9BVE14F6iNOqO&g0=Y$Z%NI{gzS*gp@3A)T-<8{Y&>&CIkM>N~xZ z*+|h_O-J_v@ZZ3%3M>E-ql}6tCs-G>0$dYCDQYUC&kxXv7?Lys#M0c{?ByMwp025h zO5Cs`BPC~K)OLtLhejZj;XaB68UW_8v9VL6J-HyME!w=xLDn`kmBtkipAnppKnA%W z@fE78fl#!NGdRuXfMy+~eF~`woF>PJvZW>adx8OwD?!(j1V8M*$IH(b7Ars=;!J-3 ze#?^zeECgHOkY30`3mHW9|TPVgsN!MqNJqs?d2_o512vkDI}bB)%Z%fA*+HVQ@(eP zt|{5NDn;f^?^f)$hSil7Mc{Af3(YPrh5-ZTS5=Y1*^qH|cAkM(rl#(}@v{2)(E}Yt zEDdHx{rTgH0LthtuR{lY7~*~iN7A^f0?wY+)Yh_ca$*D0q8kcejwK#WC_Yf#oNi%; z)^^;NMKL`-IXOn<+&C&rEJglf=qt>@J^KRJI$eg~@B{R_a8MmsyreGx8PGBbn&Yt$ zB2!Dc{Vt&G0W0{Q#2-SkqQMz~BF2S|smVuoR@dofLZ}bW&h218pf@4_)B~)j%-Hf^ zyu9mMvB9b>D|BD%UnA8YTz(ul`}tkhI>HS6`Sa&wFxVmJurZ4^^yvkmUs#%{6-zle z-#wL87`pKNdj&Ql24l%IIAxuy@>Oj8AzlSi|3?91XlQr$G?uxgb#U+x4J&n|%3>i4 z_wDCU?+Z&ygA%nQhHszsw`FH#xqd$(KK1T!4 zeLCHWhlJONYw-9F_7%!c`-Lk(SaN{Z*t>v~FS23R`Q(~h0SaX|X=4-UH9TuIDYX1= z=oBO6(n6250H>{Mz`>d1LN(I5c;aAjG2dO`Owd0x(aww#5fv5Z!_d|(Mxg-BJ9CIF zw6tE{MJ8muIs^lDu9S&-n{O{BTRggV7kx|4uAG*Gl+WvrCjU+AK2l7cR@gmeRt@mB z#7Fdn5>LmB@l2ei!*F7IaF(df1MPT}JcC*;`uuYK$b+Usq4W_0gNQTEAKus%C|?tb z&%{Gy0f9>k5+8_zTP~Iil-EAqWQ&KkPBQ)ppfgHiHak82U9~99uqEbPTL(jB=p-|2 zMLNALWjoW*B~BL5qe{?Pgv41r>~8J+_XU$BN)$1ZERU^7DinX$jJ#r2Hhl`_y;qlL zbY+%O&k!C6LUc_`crch^L`DjSeX(1?>o8FfJ>Jvt^c3~qT3p2bn_3=Y`5WhdzaTKm z%?7yL>r%0|FT7oUr4bXl9yr8Tuni6$MD4L=ujgU?-!)=jBfNZk-Wg${XC@$id;GZW z_VS`XO4fIK#wv)V8e!W*u7E6~z{fy=d-PHuBbpi?$5AXM_{bH$!;fNuH&$8-*__VL z&4uG3@VeTCT>^hA<^Mi3Ru!v%TSwqWZIJQ*F4?B0qqDs6?NzUB!rq?O;PU^T-Pc6Q z5YOBC#9?cBW23)bf&`X&d#0^J8Gsc7fl#IB{d%=OM&O8rV$3Y2JpOZde%Y%e1%HU2 z40RE7%HR5N{(lb{Cc`=?wo~bF(vTE9^WVby%352dg-+P9d0}i_La#)uD#`J;3x|;Z z-O|qUoKK%j-)>Ije8=kix9#89RvRH0o6XgKc7pso8fzOyA}#qSQR9F1WdqV+1fz$3 z>HM78C%|Bi726W`Q$jNYukmd0ML#DP(&WGN_1&`(2+%}_A6%(^1hV}&p6BOJ0!Bml zPzJabT-1K1H*Q=yJv-B8V}aDu&{dSXg*S;f@eA3}z|rZ>scZ}9?z%p{aypsK|A&IW z7NkWXd6%9*1$PNf`sF}iZJWXc?nbPoIqt@#h6}9!j=Jg97G~ZZ#qFFw2s=u_p2iVW z5+13`Lc1WiRmu8ocFQZXJ(Nq$7yo;=Knwh2muwOe5=N)V&$qjEFyJP)(OfEAFnr_H ze}+mSFBCa3;Zv|Y-)cjCo-T#gS6p~3Q7 zT~r}e`|G{ace`D*yZ7Do(z z(e;9p*-gyU0iGR*p>oQXUAKphpDwx^sn^OaC@-kR#rZbZwI+mr|MQ$du1S52=WpRH zpMFvQ6C$@oh#<%gt{m!-RADD@i9C9E=g#ZU#u~yn+-nldrW3{FzWo=y!u=1dej93Q zUXzHBVg2&6+q=}PHOyj6I(6Jdjl}9U*7eE3-`!N_{r-%M2qPzIZ?H1sZ#M<+6OUi9 zWh7T=3rX4wDfZZds=9mk8&wW}I6e7g(^#|lMYbZhyO@7sxfYY@zAHqo#D2vg5^c9) z#%{8#vR^d{dO~D0ZsnZ*Ryb$vKJDCZf3tghtb+bSZCOXxWn?rO8X9I+R*Lo~Mus#v z7rN}O$M(>Zk|LzHo-jQhZhkw9jhbcnXH!mf75f`j=XU~boh*ifOZG!5y^jwFQjVmh zBT6RUak&e#SLHgJ^*>03L8ZkdYfN3c2H{ZmMf~#9wSHT6j2{{KYjS?+dj z=v|yOo!Tx{ zXdIgM?VD;)#1;Cn0Pk`95WRl=gq1T#{qUXsasPwyZkMY?pDvDHMx+FO3rqg-`mURYcqLR`OfyKOvIYaepLwglIxuBkb%1wC|bDEaX(w8ghE zfoh zYirKspY9=SzO!zMLIVn@xXjG5_fzvB%j;G9mq<7*1$^r#FzKy}6A#DYVjb?P zGVEv1F>Y}x#!UI=knmRh6 zJ-$F(M6hDkd8xbIzUdW;8+*I8;Kr*!uDG+S+ITB#2E!cBQ>!mPd>8X^=CJV}zm>mk zb3a=z6j4+}y=8=P5Z2@`oVVyAdRt*bU?2!0T#!doNv%3eT0dI&gkA;bQYs;$Ng60$ z%k#F_;B1~th5ACTbrdW0j(i+fKM&?t@ivxx&Ia9FD=5&DP6yhZ?C;3FiTB;FT5US# z4iz*LR>chqO6~(`bu2WdhwnNe2h+Z3_oz}EmNOwid99UQRFqsKRVz=Ihw067CreRD ziSpgMlR`=r&dfF(&q+TiAQGMO9NXzX5C$FC!DyoQwvOf)LX52{pWi*guYMKS{0?QV z#WK~;*BPYUe}_ZHiNi)u^2E57%rbU!MQ_tHsI>H|I^?%7WaV``XC9MXg)7zQa47RS zwQ3B5FlE_YJwrpRT;1pYsVC03#Kewb({DQdwJ-#E5-0tf7Gbm{h)Y%2mGcyDeM$7* zu*eYg&@(bNcIZYSW1(PRO4#RRn7m_ubh+ALJuS3OhO?FG{5V*;+Su-7ybvp8ri8>4 zCdnYry!c@Gw(@SM0t&|E7OF_j2L?Kpt?e_(f-o#F+owKMC=oIXFZ z;Gr1VMBhrP78eLa+B?e{rsb{q1Y}FS;RrZ3u*45tUMVN@;A(TR`3vC?_barzw@njd zkfPLY*zHxMCMh~Eevv*$k<^KXB+*|R_6pQs4lL=cfM(;d^-zibvuEM{gDUs#r42R* z!fc0GO8}#jlM~;7c1ezg@WSFEtDqn;yfDleA5ADwhq%aNm|K><$O>2X^hBzqLtARV zsO|6X-?MmB&j9^WF1ptqilK6MF)Gh69zq_aK-Hd&>&>>&`vO&kN0r4d}zah`ejW_JSnS_t7~DkKJLPNT5m0i=j#sp(R&!eL9zbb%c{oLCdFBJBB9;hv#-GiCe2jmDslsU-M z?L<;Tc`(djs=}&3FO_+UA_xi(C<7t1zifSDvp+k?o*e%Iy>AuG1wVu{v=s|OiE`7N z|A{7Ta}zll;0Da7a=WXkJ%1w=WQ2!QM{~2XD$Or14`zyfRnxjsM+O`5q;&2=(4zTj z^z-L&5UV)-8mFlzr9`z~n1tKkqP=X?ej$-m$U285afd0e5UW!C6NXnE!lHE?e%zc$ z+^UX2Lf^paj6s`6=Lip4Q&)GV{r-~`gACWBzl-0tEVbH(La`^$uW1}!`ib3WCLsA& zO$!H36ltW2eje6GhFycqBL$&L#rq-9J;3uIp|?9|F(+uDw{y(cuEhLE*t&K3#v#4$ zfr8z*>?#&R!cP+^vobAYqWrY4nCsDdUE&3k6>{rN8{?|;d=4nY1{wS zV%4I1pK@g*T*xe^oRBN1DzpXL7Spt3JNb1|l6yV%YoYI?A-GcUYAPS9M4zT+%Mr0C zn_s2U1UlyEB!*J&zKX5=s+BpYfUrucx|F8Xeb((^dP_r|o7HtuIjt3KCl}Pr5k=iH)w-N;h4Tt zZFLC+Mr8Zng|J&-|F_htt%fwi&sE3$$J$l;ESm`KSWtf>WHh%g#vk9l!GkI4fN9#W zz1-GeyMkkhGuD2>B&0PVI{l9P;OsJ8GON{%<6z9b)T&(j>f@}QiT&-=YGkSQU2wC6 z?+q2q=mlT@wkybPa6P^xSA_788xPI;efOsG@!$~pmZIVv1MV8}ffaGQV|YQ@jwfyH z7%9ekUW)mdsM}Se)H%Ia%4py`x~<|iY0CU@{dPL2yt(~!`i<%As``n_f)lq5zg(An zox^(k2R1wDbH~`wC`BdxTIs!2DE-;QavICP^FJRK(CBKg{f_?1kehtKUxpO=v^#m- zfp26lO8&I){t5ffNWH~xO&5#&$gUX=)a^$wx#}P0K1lp#byd?@<74h2kVo7tnB6GqiaFaY{saCThH_i z<{cc{(N7KXZcGM4oAh!IL`+~0-PBK)f~TzA!B)`5m0q+VPsYNGQ`rc#!F#>CQZaY* z={b*VhEBV$K#AI(lxV+H@jYB^!0Ux&kYrqnmxT|TdiKG#-va5)7PQ-c&hh~rI0JlNOes);r> zK94t3aEjHy;yn@cWUgaja(ZCIHd8w`Zyg)C?(rH`wwN>NEwtAqmr}|U-sWCaV@M`v z*Y}((kDyr1a6sNm?l$!Te9$27l^-Hx=NWxSU)PNrHx4j^6f2IIw1~`d*@;o99f9Jz{2LbiVKff{BGW(~FZl$aPI2<9|C_76^4A{WQoEw!$h*$*9Y zj{`2u_~uKddUPqhubBtNQqUQrV);{)5f03ZCmU*%kAkwO+k zSmKtT?t;{H7HOCOnen6a2if>UK092AUN77|Jyz*`avJTdWR{p ztYp>NMoy<~yJ!CQRFYVVEF@mYvdd3jYT~rD6?~%uBLSgMGAUiXDj1afe2(6<`E&{K zwf5{fui}&8;W#fqtg3jt??@tMqo9$8R1A(Y@-8G4wT4^+|I~3<-VPvsHaB? zQqr^h>@yEw6Iv(bUQkm}t<{!}VL#;DJ{ClJBawpkY~Gql;szPjWImLC{44?Y#x7W~*zc7O=Rr++scH4g!u6=0x?QnZM$F@*g zuyD`YQad@Hqvvvl^J$TcWU>cLz0ZTut#P8D7VuOO#NPI+l8QUJD0%;0rh`CLJf*z_ zR6n$5;p-^E^<)#LN6WZ)MBhKV@l?mkI3(BoTSMwr`JVNj4~0flaARI`S=Ik1Ze>Mx zl-eG9G|ybTJ>J>7Pvd_$9vY_fV_#H>;_|lTk^<%|aZz?ty0duy>3OP#B4Z2dzzdNA|FXif?%sMr=&X=`|!^lm|v~P^biGivPlSsJv2&3J|2i zL0)vt&He~fwBg546^&2oUgPD7P3B#}8AswY7zT*&n)M&cZNi>gwv>#O%qL^J02o*af3@t`uA6x1sG>z2QQ(Vw=L& zj=Fajjiqy~|oDnuiYd_H3e}ySXV3Z`{bViQ5+Kkk#frMb^eE z*61R2`vwOk8U$Z%yB*In(?{yCzkUA*JAIl46!}3Bi|^KwQLlyS^?9G$h``=Hy{hDC z_g9w*iKTUBqJzVM{dM-I5-B!^#Y%2ND$vP-W;3BQRg|ilyO4j&(eBWypXaTU6n)kb zvS0{SFGn6&hP>O%`m(=1kE84TvUyx#L|2(DFjP5LJxn1T32<~|N5NRC-_^VIBSR_e z+5K5jFJ7z=9247Is_Z~YE}u~J;hDfZ(ph#Bo5iomn6b>w!=5wO(*2$I!Bx7Xxa9JA zR-0k(gY3k_{9TX2aJz=WYcy_6M_m3E<_0zgxtSlKIy%n|ElnRrD2V-TL6|!kZ1JmMMw3BA1QCggj}LOoy5PT06-Ue7tLESE%l&*4DLKW##OO2o)q|S$U%AH; z=L;To_De8s<7Jdb2$LW%icn~?^fW_y`?CrLhDJ0*<`48wTKLY#k)tnG{HWHw_Ux+z z7%65faVsPU4A-Js;fp7PRBLZ}-@RV-9rHSa7${kdL*R6(9N{?C5~_%AO`5Ki3E=Gz z*0OY*MX$q1I1`MNz~KGH!SRl0@fpQxvj0E=^B>b$m+462U+I7{Z(@k;&!ydQgmQLG z=H}+Ml}u?DHrXPdeWtsCy1an-vyL$=_7WE&+j*4pE~_g&mWda;^#-1if|kK9`K-fL z=*u7Hx^TR{_hbK^%z;nKNv6_~xOoff;Up+sB@2seb;_ptqsW=qsHjUhW|5Wo&d;CN zr4DQ2=N@}9dei`IpnR2SSHreN!;rlsUj4$= z2o;>@B#XpW4h5~H_aAd|6d!QB%zZf1x%UP}Fi4hPRY%WPxeV1MF7LJ+93XPA-B*N8yYESCrBC zHxrEok!BL=h&wLYyCrt5oceKy`BKI(rbnfc0 zw;c7j4Vs`l>jUcKev;_1K(i60wY6pS7g_#3e)6lQLp>nvFNarGM!Ax@u>&>3mBD=C zR-V5>XR)4Rr&Ub)KLm`AA7)`B;oUFY?XOv7eC%p28q_OF1&6>mCV*)Cwxtg7c5Nd0 zIW380RlHn7YYzU5MORk{65u`vgA{pK1dq>g6gXb>(y*(gE@QcTmG8F|zF|l@hS-K& zPWti}zVd9P9LKRp({cG+vDN!hD-Qo1vG+%k_O@aI09(YUk=FwIiJ_qcC-KqWE)Rwm zu1j7{sWx>PSI}owYbEj!ubpxDo2VkBSlcm9qG7qTc|AewCQe@j1Id#XN>omzemM$A zdv*iMxM550b*n>&?S;sP)kM4u1klH!4>*ZiTaYyo;W%SfN1}zhpNW z(B^eg)6(Dy;(Z!k#MU=<`On4%fugi1`%d>%%;@-KfwJ<)J(p&)nMj6j{#u4Oy}MW#D2%YH{kv6Dg2DxX_$#Xc*dp-!!apV_{zsrnS!ZX92>M&4`B@MAoWLYJL zW8Qz~*g{iJ;vNm7^>Kq4g0ARZ53Qcca*dq){Ekx5&mX>*?Xr*enEi4L$z|w(RHlRM zY$7++v*9x5uFKQhKl_qLE-Q&gUzjeDzs~sfhS=)>qm+;T-HBXIEggIda8s?@?lJOG zti#wyAt*j3GV>HGa8Qwu(5T&l`aFIrbW$FdpPzs5G<-X#05ly=5PUxa56`Iv^WVBf z(^K&~5#jnh?x5!ap3qA^BFoW=`T5hV&x()ae7f9X%jZH#A?PSKH+p!7Ry4_G0v*BJ zUMYFME2`vj&K_DQ>=^te9YM(0Kef%W;5izZmmFe-`!uaxu!*`6i;CKmN;Z7PuMonkb-QyQZ@9@-;5&7ner@AcV zFh>So%e2J5P%UE?vP}6)6i#+*Yu``%{r4%ytHX(*57UBjXs zp)DVZy+ht2zdX7h@ix)|8TX`}JtoxW?w!CO##+U|h%WKnTV!@pE9LAjxMoGr9XLhV z`k<{XI#Az{eyvNkf)BpxmMOEpa!H%vbw3Om6iiM|!bA!2D>)WXF@ZwNtm#Kb7-Dq6 z^U%71-YGivobxr}bXVmIt$%jG&KOc+)9YvOnZ`Wl5%%!#FoGUbj&6U-;pph7`^D)6 z{T}YFBv}Oe1BGKb4_ff6^{3%;zJ^E48R@(}xXC3h-E+o0J$3|Xw)O=w0iH@Qi+nNM zjc%KEa}5p*WV$%t{?7_O3DBI&2J_78#2l>gzn;46OJYy{zzgCH@`)OSXKT(V_)*8X Md0VAi*)sV50lTd>mH+?% From 09effef4f96bdfb30f16ef2f48ab551cddac709b Mon Sep 17 00:00:00 2001 From: Anewbe Date: Sat, 10 Mar 2018 21:30:01 -0600 Subject: [PATCH 002/109] More projectiles now ignite things --- code/modules/projectiles/projectile.dm | 8 ++++++++ code/modules/projectiles/projectile/animate.dm | 1 + code/modules/projectiles/projectile/beams.dm | 8 ++++++++ code/modules/projectiles/projectile/bullets.dm | 4 ++++ code/modules/projectiles/projectile/change.dm | 2 ++ code/modules/projectiles/projectile/energy.dm | 8 ++++++++ code/modules/projectiles/projectile/force.dm | 2 ++ code/modules/projectiles/projectile/special.dm | 15 +++++++++++++++ 8 files changed, 48 insertions(+) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 7cf68c5d39..c8e4fb0be9 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -49,6 +49,7 @@ //Effects var/incendiary = 0 //1 for ignite on hit, 2 for trail of fire. 3 maybe later for burst of fire around the impact point. - Mech var/flammability = 0 //Amount of fire stacks to add for the above. + var/combustion = TRUE //Does this set off flammable objects on fire/hit? var/stun = 0 var/weaken = 0 var/paralyze = 0 @@ -90,6 +91,10 @@ //called when the projectile stops flying because it collided with something /obj/item/projectile/proc/on_impact(var/atom/A) impact_effect(effect_transform) // generate impact effect + if(damage && damage_type == BURN) + var/turf/T = get_turf(A) + if(T) + T.hotspot_expose(700, 5) return //Checks if the projectile is eligible for embedding. Not that it necessarily will. @@ -132,6 +137,9 @@ if (!istype(targloc) || !istype(curloc)) return 1 + if(combustion) + curloc.hotspot_expose(700, 5) + if(targloc == curloc) //Shooting something in the same turf target.bullet_act(src, target_zone) on_impact(target) diff --git a/code/modules/projectiles/projectile/animate.dm b/code/modules/projectiles/projectile/animate.dm index c09b98a32b..e88e6faa33 100644 --- a/code/modules/projectiles/projectile/animate.dm +++ b/code/modules/projectiles/projectile/animate.dm @@ -8,6 +8,7 @@ light_range = 2 light_power = 0.5 light_color = "#55AAFF" + combustion = FALSE /obj/item/projectile/animate/Bump(var/atom/change) if((istype(change, /obj/item) || istype(change, /obj/structure)) && !is_type_in_list(change, protected_objects)) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 6fee571544..9755f604ab 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -122,6 +122,8 @@ check_armour = "laser" light_color = "#0066FF" + combustion = FALSE + muzzle_type = /obj/effect/projectile/laser_blue/muzzle tracer_type = /obj/effect/projectile/laser_blue/tracer impact_type = /obj/effect/projectile/laser_blue/impact @@ -142,6 +144,8 @@ check_armour = "laser" light_color = "#FF0D00" + combustion = FALSE + /obj/item/projectile/beam/lastertag/red/on_hit(var/atom/target, var/blocked = 0) if(istype(target, /mob/living/carbon/human)) var/mob/living/carbon/human/M = target @@ -157,6 +161,8 @@ check_armour = "laser" light_color = "#00C6FF" + combustion = FALSE + muzzle_type = /obj/effect/projectile/laser_omni/muzzle tracer_type = /obj/effect/projectile/laser_omni/tracer impact_type = /obj/effect/projectile/laser_omni/impact @@ -190,6 +196,8 @@ damage_type = HALLOSS light_color = "#FFFFFF" + combustion = FALSE + muzzle_type = /obj/effect/projectile/stun/muzzle tracer_type = /obj/effect/projectile/stun/tracer impact_type = /obj/effect/projectile/stun/impact diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 02eab7e93a..d47e729898 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -191,6 +191,8 @@ sharp = 0 check_armour = "melee" + combustion = FALSE + /obj/item/projectile/bullet/shotgun/ion/on_hit(var/atom/target, var/blocked = 0) ..() empulse(target, 0, 0, 0, 0) //Only affects what it hits @@ -325,6 +327,8 @@ embed_chance = 0 sharp = 0 + combustion = FALSE + /obj/item/projectile/bullet/pistol/cap/process() loc = null qdel(src) \ No newline at end of file diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index 6f19b29bbb..0beffe46a3 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -6,6 +6,8 @@ nodamage = 1 check_armour = "energy" + combustion = FALSE + /obj/item/projectile/change/on_hit(var/atom/change) wabbajack(change) diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 0cbb96a2e0..d5bae0dc22 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -92,6 +92,7 @@ light_power = 0.5 light_color = "#33CC00" + combustion = FALSE /obj/item/projectile/energy/dart name = "dart" @@ -101,6 +102,7 @@ agony = 120 check_armour = "energy" + combustion = FALSE /obj/item/projectile/energy/bolt name = "bolt" @@ -122,6 +124,8 @@ agony = 10 check_armour = "bio" + combustion = FALSE + /obj/item/projectile/energy/neurotoxin name = "neurotoxic spit" icon_state = "neurotoxin" @@ -130,6 +134,8 @@ agony = 80 check_armour = "bio" + combustion = FALSE + /obj/item/projectile/energy/neurotoxin/toxic //New alien mob projectile to match the player-variant's projectiles. name = "neurotoxic spit" icon_state = "neurotoxin" @@ -149,6 +155,8 @@ light_power = 0.5 light_color = "#33CC00" + combustion = FALSE + /obj/item/projectile/energy/plasmastun name = "plasma pulse" icon_state = "plasma_stun" diff --git a/code/modules/projectiles/projectile/force.dm b/code/modules/projectiles/projectile/force.dm index 71b7d34d04..550aab6113 100644 --- a/code/modules/projectiles/projectile/force.dm +++ b/code/modules/projectiles/projectile/force.dm @@ -5,6 +5,8 @@ damage = 20 check_armour = "energy" + combustion = FALSE + /obj/item/projectile/forcebolt/strong name = "force bolt" diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 4e366bed6d..f7ecddb0eb 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -9,6 +9,9 @@ light_range = 2 light_power = 0.5 light_color = "#55AAFF" + + combustion = FALSE + var/sev1_range = 0 var/sev2_range = 1 var/sev3_range = 1 @@ -56,6 +59,8 @@ light_power = 0.5 light_color = "#55AAFF" + combustion = FALSE + /obj/item/projectile/temp/on_hit(atom/target, blocked = FALSE) ..() if(isliving(target)) @@ -85,6 +90,8 @@ name = "heat beam" target_temperature = 1000 + combustion = TRUE + /obj/item/projectile/meteor name = "meteor" icon = 'icons/obj/meteor.dmi' @@ -127,6 +134,8 @@ light_power = 0.5 light_color = "#33CC00" + combustion = FALSE + /obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0) var/mob/living/M = target if(ishuman(target)) @@ -196,6 +205,8 @@ /obj/item/projectile/beam/mindflayer name = "flayer ray" + combustion = FALSE + /obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0) if(ishuman(target)) var/mob/living/carbon/human/M = target @@ -218,6 +229,8 @@ damage_type = HALLOSS muzzle_type = null + combustion = FALSE + /obj/item/projectile/bola/on_hit(var/atom/target, var/blocked = 0) if(ishuman(target)) var/mob/living/carbon/human/M = target @@ -235,6 +248,8 @@ damage_type = BRUTE muzzle_type = null + combustion = FALSE + /obj/item/projectile/webball/on_hit(var/atom/target, var/blocked = 0) if(isturf(target.loc)) var/obj/effect/spider/stickyweb/W = locate() in get_turf(target) From a8cc2df4ad551df363ab971575cc573d5a7ea21f Mon Sep 17 00:00:00 2001 From: Anewbe Date: Sun, 11 Mar 2018 16:56:17 -0500 Subject: [PATCH 003/109] Ports quickdraw storage items from VIRGO --- .../objects/items/weapons/storage/belt.dm | 3 +- .../items/weapons/storage/quickdraw.dm | 80 ++++++++++++++++++ icons/obj/storage.dmi | Bin 59117 -> 59399 bytes polaris.dme | 1 + 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 code/game/objects/items/weapons/storage/quickdraw.dm diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 23fccf51ac..6889763f20 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -124,7 +124,8 @@ /obj/item/weapon/crowbar, /obj/item/device/flashlight, /obj/item/weapon/cell/device, - /obj/item/weapon/extinguisher/mini + /obj/item/weapon/extinguisher/mini, + /obj/item/weapon/storage/quickdraw/syringe_case ) /obj/item/weapon/storage/belt/medical/emt diff --git a/code/game/objects/items/weapons/storage/quickdraw.dm b/code/game/objects/items/weapons/storage/quickdraw.dm new file mode 100644 index 0000000000..86d7c76ca2 --- /dev/null +++ b/code/game/objects/items/weapons/storage/quickdraw.dm @@ -0,0 +1,80 @@ +// ----------------------------- +// Quickdraw storage +// ----------------------------- +//These items are pouches and cases made to be kept in belts or pockets to quickly draw objects from +//Largely inspired by the vest pouches on Colonial Marines + +/obj/item/weapon/storage/quickdraw + name = "quickdraw" + desc = "This object should not appear" + + //Quickmode + //When set to 0, this storage will operate as a regular storage, and clicking on it while equipped will open it as a storage + //When set to 1, a click while it is equipped will instead move the first item inside it to your hand + var/quickmode = 0 + +/obj/item/weapon/storage/quickdraw/attack_hand(mob/user as mob) + if(src.loc == user) //If they aren't holding us, we do nothing special + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(quickmode) + var/first_item = contents[1] + if(first_item && !H.get_active_hand()) //Do we have anything to give you? + H.put_in_hands(first_item) + return + + if(H.l_store == src && !H.get_active_hand()) //overrides + src.open(user) + return + if(H.r_store == src && !H.get_active_hand()) + src.open(user) + return + ..() //Nothing special happened, go call the other proc + + +/obj/item/weapon/storage/quickdraw/verb/toggle_quickdraw() + set name = "Switch Quickdraw Mode" + set category = "Object" + + quickmode = !quickmode + switch (quickmode) + if(1) + to_chat(usr, "[src] now draws the first object inside.") + if(0) + to_chat(usr, "[src] now opens as a container.") + +/obj/item/weapon/storage/quickdraw/AltClick(mob/user) + ..() + if(src.loc == user) //Are they carrying us? + toggle_quickdraw() + + +// If we start adding more of these, we'll need to make them their own folder. 'til then, this one should be fine. + +// ----------------------------- +// Syringe case +// ----------------------------- + +/obj/item/weapon/storage/quickdraw/syringe_case + name = "syringe case" + desc = "A small case for safely carrying sharps around." + icon_state = "syringe_case" + + w_class = ITEMSIZE_SMALL + max_w_class = ITEMSIZE_TINY + max_storage_space = ITEMSIZE_TINY * 6 //Capable of holding six syringes + + //Can hold syringes and autoinjectors, but also pills if you really wanted. Syringe-shaped objects like pens and cigarettes also fit, but why would you do that? + can_hold = list(/obj/item/weapon/reagent_containers/syringe, /obj/item/weapon/reagent_containers/hypospray/autoinjector, + /obj/item/weapon/reagent_containers/pill, /obj/item/weapon/pen, /obj/item/device/flashlight/pen, /obj/item/clothing/mask/smokable/cigarette) + + quickmode = 1 //Starts in quickdraw mode + //Preloaded for your convenience! + starts_with = list( + /obj/item/weapon/reagent_containers/syringe, + /obj/item/weapon/reagent_containers/syringe, + /obj/item/weapon/reagent_containers/syringe, + /obj/item/weapon/reagent_containers/syringe, + /obj/item/weapon/reagent_containers/syringe, + /obj/item/weapon/reagent_containers/syringe + ) \ No newline at end of file diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 677903284cd0aa2e844055eb480b8c093eb77fbe..91658df513fab3214719e0648098d02ae7d92b68 100644 GIT binary patch delta 17791 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 delta 17498 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 Date: Sun, 11 Mar 2018 18:56:54 -0500 Subject: [PATCH 004/109] Ports ghost pAI alert --- code/modules/mob/dead/observer/observer.dm | 12 ++++++++++++ icons/obj/pda_old.dmi | Bin 20908 -> 21231 bytes 2 files changed, 12 insertions(+) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 13cd4d4c36..f0b4362e0f 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -790,3 +790,15 @@ mob/observer/dead/MayRespawn(var/feedback = 0) /mob/observer/dead/is_deaf() return FALSE + +/mob/observer/dead/verb/paialert() + set category = "Ghost" + set name = "Blank pAI alert" + set desc = "Flash an indicator light on available blank pAI devices for a smidgen of hope." + if(usr.client.prefs.be_special & BE_PAI) + for(var/obj/item/device/paicard/p in world) + var/obj/item/device/paicard/PP = p + if(PP.pai == null) + PP.overlays += "pai-ghostalert" + spawn(54) + PP.overlays.Cut() \ No newline at end of file diff --git a/icons/obj/pda_old.dmi b/icons/obj/pda_old.dmi index fcded39c1e61dd03cc6e8afe7284909e0537b113..d3934be3411242d57de9852330f89f3f051deec8 100644 GIT binary patch literal 21231 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

^DZa4Og(o^< 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 J)ph|F{sD8q2k-y@ literal 20908 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 From d4d2f1d0adcd3fa62935203ba14d385085877cc2 Mon Sep 17 00:00:00 2001 From: Anewbe Date: Sun, 11 Mar 2018 19:41:00 -0500 Subject: [PATCH 005/109] Should speed up ZAS --- code/controllers/subsystems/air.dm | 2 +- code/controllers/subsystems/airflow.dm | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/code/controllers/subsystems/air.dm b/code/controllers/subsystems/air.dm index ed4602f048..ef0173c33a 100644 --- a/code/controllers/subsystems/air.dm +++ b/code/controllers/subsystems/air.dm @@ -9,7 +9,7 @@ SUBSYSTEM_DEF(air) name = "Air" init_order = INIT_ORDER_AIR - priority = 20 + priority = 35 wait = 2 SECONDS // seconds (We probably can speed this up actually) flags = SS_BACKGROUND // TODO - Should this really be background? It might be important. runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME diff --git a/code/controllers/subsystems/airflow.dm b/code/controllers/subsystems/airflow.dm index 9db8138826..c98a02a5ce 100644 --- a/code/controllers/subsystems/airflow.dm +++ b/code/controllers/subsystems/airflow.dm @@ -14,7 +14,7 @@ SUBSYSTEM_DEF(airflow) wait = 2 flags = SS_NO_INIT runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - priority = 15 + priority = 30 var/list/processing = list() var/list/currentrun = list() @@ -47,7 +47,7 @@ SUBSYSTEM_DEF(airflow) continue else if (target.airflow_process_delay) target.airflow_process_delay = 0 - + target.airflow_speed = min(target.airflow_speed, 15) target.airflow_speed -= vsc.airflow_speed_decay if (!target.airflow_skip_speedcheck) @@ -89,7 +89,7 @@ SUBSYSTEM_DEF(airflow) if (MC_TICK_CHECK) return continue - + step_towards(target, target.airflow_dest) var/mob/M = target if (ismob(target) && M.client) @@ -98,7 +98,7 @@ SUBSYSTEM_DEF(airflow) if (MC_TICK_CHECK) return -#undef CLEAR_OBJECT +#undef CLEAR_OBJECT /atom/movable var/tmp/airflow_xo @@ -129,9 +129,9 @@ SUBSYSTEM_DEF(airflow) if (airflow_falloff < 1) airflow_dest = null return FALSE - - airflow_speed = min(max(n * (9 / airflow_falloff), 1), 9) - + + airflow_speed = min(max(n * (9 / airflow_falloff), 1), 9) + airflow_od = 0 if (!density) @@ -154,7 +154,7 @@ SUBSYSTEM_DEF(airflow) /atom/movable/proc/RepelAirflowDest(n) if (!prepare_airflow(n)) return - + airflow_xo = -(airflow_dest.x - src.x) airflow_yo = -(airflow_dest.y - src.y) From e2bade91c843fe0e4114ecd5abdea9240b97689a Mon Sep 17 00:00:00 2001 From: Anewbe Date: Tue, 13 Mar 2018 15:02:49 -0500 Subject: [PATCH 006/109] AFK Kicker should affect ghosts and people in the lobby --- code/controllers/Processes/inactivity.dm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/code/controllers/Processes/inactivity.dm b/code/controllers/Processes/inactivity.dm index 2a6cd44d2c..3b118995bf 100644 --- a/code/controllers/Processes/inactivity.dm +++ b/code/controllers/Processes/inactivity.dm @@ -7,10 +7,10 @@ for(last_object in clients) var/client/C = last_object if(C.is_afk(config.kick_inactive MINUTES)) - if(!istype(C.mob, /mob/observer/dead) && !istype(C.mob, /mob/new_player)) - to_chat(C,"You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.") - var/information + to_chat(C,"You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.") + var/information + if(C.mob) if(ishuman(C.mob)) var/job var/mob/living/carbon/human/H = C.mob @@ -27,10 +27,10 @@ else if(issilicon(C.mob)) information = " while a silicon." - var/adminlinks - adminlinks = " (JMP|CRYO)" + var/adminlinks + adminlinks = " (JMP|CRYO)" - log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob) + log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob) - qdel(C) + qdel(C) SCHECK From e9ad27de9feb89e54f2ce90580e7b4a9bf82bf88 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sat, 24 Feb 2018 15:22:23 -0500 Subject: [PATCH 007/109] POLARIS: Fix oversight in not-late-join jobs without spawnpoints on the map They spawn in space. That's fine, right? --- code/game/jobs/job_controller.dm | 42 +++++++++++++++++--------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index ec98faf2d4..9db29ebd85 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -327,6 +327,27 @@ var/global/datum/controller/occupations/job_master var/datum/job/job = GetJob(rank) var/list/spawn_in_storage = list() + if(!joined_late) + var/obj/S = null + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if(sloc.name != rank) continue + if(locate(/mob/living) in sloc.loc) continue + S = sloc + break + if(!S) + S = locate("start*[rank]") // use old stype + if(istype(S, /obj/effect/landmark/start) && istype(S.loc, /turf)) + H.forceMove(S.loc) + else + var/list/spawn_props = LateSpawn(H.client, rank) + var/turf/T = spawn_props["turf"] + H.forceMove(T) + + // Moving wheelchair if they have one + if(H.buckled && istype(H.buckled, /obj/structure/bed/chair/wheelchair)) + H.buckled.forceMove(H.loc) + H.buckled.set_dir(H.dir) + if(job) //Equip custom gear loadout. @@ -398,25 +419,6 @@ var/global/datum/controller/occupations/job_master H.job = rank - if(!joined_late) - var/obj/S = null - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if(sloc.name != rank) continue - if(locate(/mob/living) in sloc.loc) continue - S = sloc - break - if(!S) - S = locate("start*[rank]") // use old stype - if(istype(S, /obj/effect/landmark/start) && istype(S.loc, /turf)) - H.forceMove(S.loc) - else - LateSpawn(H, rank) - - // Moving wheelchair if they have one - if(H.buckled && istype(H.buckled, /obj/structure/bed/chair/wheelchair)) - H.buckled.forceMove(H.loc) - H.buckled.set_dir(H.dir) - // If they're head, give them the account info for their department if(H.mind && job.head_position) var/remembered_info = "" @@ -612,7 +614,7 @@ var/global/datum/controller/occupations/job_master var/datum/spawnpoint/spawnpos //Spawn them at their preferred one - if(C.prefs.spawnpoint) + if(C && C.prefs.spawnpoint) if(!(C.prefs.spawnpoint in using_map.allowed_spawns)) to_chat(C, "Your chosen spawnpoint ([C.prefs.spawnpoint]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead.") spawnpos = null From e1d31365d3de5b9170c1f59cc9bcee38961e92b9 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sat, 24 Feb 2018 16:57:53 -0500 Subject: [PATCH 008/109] POLARIS: Make cryopods check area first, then range The bug referenced hasn't existed for quite a while. We'll keep the range check as a fallback, though. --- code/game/machinery/cryopod.dm | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 11e9f0f94f..89042fb5e1 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -304,13 +304,18 @@ find_control_computer() /obj/machinery/cryopod/proc/find_control_computer(urgent=0) - //control_computer = locate(/obj/machinery/computer/cryopod) in src.loc.loc // Broken due to http://www.byond.com/forum/?post=2007448 - control_computer = locate(/obj/machinery/computer/cryopod) in range(6,src) + control_computer = null + + var/area/my_area = get_area(src) + control_computer = locate(/obj/machinery/computer/cryopod) in my_area + + if(!control_computer) //Fallback to old method. + control_computer = locate(/obj/machinery/computer/cryopod) in range(6,src) // Don't send messages unless we *need* the computer, and less than five minutes have passed since last time we messaged - if(!control_computer && urgent && last_no_computer_message + 5*60*10 < world.time) - log_admin("Cryopod in [src.loc.loc] could not find control computer!") - message_admins("Cryopod in [src.loc.loc] could not find control computer!") + if(!control_computer && urgent && last_no_computer_message + 5 MINUTES < world.time) + log_admin("Cryopod in [my_area] could not find control computer!") + message_admins("Cryopod in [my_area] could not find control computer!") last_no_computer_message = world.time return control_computer != null From 4686f6fcc4cab6d0d4cfa43617226eb6aec7a83a Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Mon, 26 Feb 2018 00:33:03 -0500 Subject: [PATCH 009/109] POLARIS: Port's /tg/'s current sound.dm, plus pref It's mostly the same, just a little more efficient. I added a 'preferences' var to pass a datum and decide whether or not to play the sound for that client based on some preference. --- code/__defines/atmos.dm | 2 - code/__defines/sound.dm | 56 ++++++++ code/game/area/areas.dm | 13 +- code/game/sound.dm | 223 +++++++++++------------------- code/modules/mob/living/living.dm | 16 ++- code/modules/mob/mob_helpers.dm | 7 + polaris.dme | 1 + 7 files changed, 171 insertions(+), 147 deletions(-) create mode 100644 code/__defines/sound.dm diff --git a/code/__defines/atmos.dm b/code/__defines/atmos.dm index bd9175aab1..13964a6f80 100644 --- a/code/__defines/atmos.dm +++ b/code/__defines/atmos.dm @@ -21,8 +21,6 @@ #define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD * BREATH_PERCENTAGE * 0.16) #define HUMAN_HEAT_CAPACITY 280000 //J/K For 80kg person -#define SOUND_MINIMUM_PRESSURE 10 - #define PRESSURE_DAMAGE_COEFFICIENT 4 // The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE. #define MAX_HIGH_PRESSURE_DAMAGE 4 // This used to be 20... I got this much random rage for some retarded decision by polymorph?! Polymorph now lies in a pool of blood with a katana jammed in his spleen. ~Errorage --PS: The katana did less than 20 damage to him :( #define LOW_PRESSURE_DAMAGE 2 // The amount of damage someone takes when in a low pressure area. (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value). diff --git a/code/__defines/sound.dm b/code/__defines/sound.dm new file mode 100644 index 0000000000..6fae2fadcb --- /dev/null +++ b/code/__defines/sound.dm @@ -0,0 +1,56 @@ +//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on +#define CHANNEL_LOBBYMUSIC 1024 +#define CHANNEL_ADMIN 1023 +#define CHANNEL_VOX 1022 +#define CHANNEL_JUKEBOX 1021 +#define CHANNEL_HEARTBEAT 1020 //sound channel for heartbeats +#define CHANNEL_AMBIENCE_FORCED 1019 +#define CHANNEL_AMBIENCE 1018 +#define CHANNEL_BUZZ 1017 +#define CHANNEL_BICYCLE 1016 + +//THIS SHOULD ALWAYS BE THE LOWEST ONE! +//KEEP IT UPDATED + +#define CHANNEL_HIGHEST_AVAILABLE 1015 + +#define SOUND_MINIMUM_PRESSURE 10 +#define FALLOFF_SOUNDS 0.5 + +//Sound environment defines. Reverb preset for sounds played in an area, see sound datum reference for more. +#define GENERIC 0 +#define PADDED_CELL 1 +#define ROOM 2 +#define BATHROOM 3 +#define LIVINGROOM 4 +#define STONEROOM 5 +#define AUDITORIUM 6 +#define CONCERT_HALL 7 +#define CAVE 8 +#define ARENA 9 +#define HANGAR 10 +#define CARPETED_HALLWAY 11 +#define HALLWAY 12 +#define STONE_CORRIDOR 13 +#define ALLEY 14 +#define FOREST 15 +#define CITY 16 +#define MOUNTAINS 17 +#define QUARRY 18 +#define PLAIN 19 +#define PARKING_LOT 20 +#define SEWER_PIPE 21 +#define UNDERWATER 22 +#define DRUGGED 23 +#define DIZZY 24 +#define PSYCHOTIC 25 + +#define STANDARD_STATION STONEROOM +#define LARGE_ENCLOSED HANGAR +#define SMALL_ENCLOSED BATHROOM +#define TUNNEL_ENCLOSED CAVE +#define LARGE_SOFTFLOOR CARPETED_HALLWAY +#define MEDIUM_SOFTFLOOR LIVINGROOM +#define SMALL_SOFTFLOOR ROOM +#define ASTEROID CAVE +#define SPACE UNDERWATER diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index e9d93b48a3..54a3da3f75 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -248,23 +248,26 @@ var/list/mob/living/forced_ambiance_list = new // If we previously were in an area with force-played ambiance, stop it. if(L in forced_ambiance_list) - L << sound(null, channel = 1) + L << sound(null, channel = CHANNEL_AMBIENCE_FORCED) forced_ambiance_list -= L if(!L.client.ambience_playing) L.client.ambience_playing = 1 - L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2) + L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_AMBIENCE) if(forced_ambience) if(forced_ambience.len) forced_ambiance_list |= L - L << sound(pick(forced_ambience), repeat = 1, wait = 0, volume = 25, channel = 1) + var/sound/chosen_ambiance = pick(forced_ambience) + if(!istype(chosen_ambiance)) + chosen_ambiance = sound(chosen_ambiance, repeat = 1, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE_FORCED) + L << chosen_ambiance else - L << sound(null, channel = 1) + L << sound(null, channel = CHANNEL_AMBIENCE_FORCED) else if(src.ambience.len && prob(35)) if((world.time >= L.client.played + 600)) var/sound = pick(ambience) - L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = 1) + L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE) L.client.played = world.time /area/proc/gravitychange(var/gravitystate = 0, var/area/A) diff --git a/code/game/sound.dm b/code/game/sound.dm index afeeaafcae..2db1e433bd 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -1,107 +1,50 @@ -//Sound environment defines. Reverb preset for sounds played in an area, see sound datum reference for more. -#define GENERIC 0 -#define PADDED_CELL 1 -#define ROOM 2 -#define BATHROOM 3 -#define LIVINGROOM 4 -#define STONEROOM 5 -#define AUDITORIUM 6 -#define CONCERT_HALL 7 -#define CAVE 8 -#define ARENA 9 -#define HANGAR 10 -#define CARPETED_HALLWAY 11 -#define HALLWAY 12 -#define STONE_CORRIDOR 13 -#define ALLEY 14 -#define FOREST 15 -#define CITY 16 -#define MOUNTAINS 17 -#define QUARRY 18 -#define PLAIN 19 -#define PARKING_LOT 20 -#define SEWER_PIPE 21 -#define UNDERWATER 22 -#define DRUGGED 23 -#define DIZZY 24 -#define PSYCHOTIC 25 - -#define STANDARD_STATION STONEROOM -#define LARGE_ENCLOSED HANGAR -#define SMALL_ENCLOSED BATHROOM -#define TUNNEL_ENCLOSED CAVE -#define LARGE_SOFTFLOOR CARPETED_HALLWAY -#define MEDIUM_SOFTFLOOR LIVINGROOM -#define SMALL_SOFTFLOOR ROOM -#define ASTEROID CAVE -#define SPACE UNDERWATER - -var/list/shatter_sound = list('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg') -var/list/explosion_sound = list('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg','sound/effects/Explosion3.ogg','sound/effects/Explosion4.ogg','sound/effects/Explosion5.ogg','sound/effects/Explosion6.ogg') -var/list/spark_sound = list('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks5.ogg','sound/effects/sparks6.ogg','sound/effects/sparks7.ogg') -var/list/rustle_sound = list('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') -var/list/punch_sound = list('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') -var/list/clown_sound = list('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') -var/list/swing_hit_sound = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') -var/list/hiss_sound = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') -var/list/page_sound = list('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg') -var/list/fracture_sound = list('sound/effects/bonebreak1.ogg','sound/effects/bonebreak2.ogg','sound/effects/bonebreak3.ogg','sound/effects/bonebreak4.ogg') -var/list/casing_sound = list ('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg') -var/list/keyboard_sound = list ('sound/effects/keyboard/keyboard1.ogg','sound/effects/keyboard/keyboard2.ogg','sound/effects/keyboard/keyboard3.ogg', 'sound/effects/keyboard/keyboard4.ogg') -var/list/mechstep_sound = list('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') -var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') -var/list/can_sound = list('sound/effects/can_open1.ogg','sound/effects/can_open2.ogg','sound/effects/can_open3.ogg','sound/effects/can_open4.ogg') -var/list/geiger_sound = list('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg') -var/list/geiger_weak_sound = list('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg') - -//var/list/gun_sound = list('sound/weapons/Gunshot.ogg', 'sound/weapons/Gunshot2.ogg','sound/weapons/Gunshot3.ogg','sound/weapons/Gunshot4.ogg') - -/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/is_global, var/frequency) - - soundin = get_sfx(soundin) // same sound for everyone - +/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, is_global, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE, preference = null) if(isarea(source)) - error("[source] is an area and is trying to make the sound: [soundin]") + throw EXCEPTION("playsound(): source is an area") return - frequency = isnull(frequency) ? get_rand_frequency() : frequency // Same frequency for everybody var/turf/turf_source = get_turf(source) + //allocate a channel if necessary now so its the same for everyone + channel = channel || open_sound_channel() + // Looping through the player list has the added bonus of working for mobs inside containers - for (var/P in player_list) + var/sound/S = sound(get_sfx(soundin)) + var/maxdistance = (world.view + extrarange) * 3 + var/list/listeners = player_list + if(!ignore_walls) //these sounds don't carry through walls + listeners = listeners & hearers(maxdistance,turf_source) + for(var/P in listeners) var/mob/M = P if(!M || !M.client) continue + var/turf/T = get_turf(M) + var/distance = get_dist(T, turf_source) - var/distance = get_dist(M, turf_source) - if(distance <= (world.view + extrarange) * 3) - var/turf/T = get_turf(M) - + if(distance <= maxdistance) if(T && T.z == turf_source.z) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, channel, pressure_affected, S) -var/const/FALLOFF_SOUNDS = 0.5 +/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, channel = 0, pressure_affected = TRUE, sound/S, preference) + if(!client || ear_deaf > 0) + return + if(preference && !client.is_preference_enabled(preference)) + return -/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global) - if(!src.client || ear_deaf > 0) return - soundin = get_sfx(soundin) + if(!S) + S = sound(get_sfx(soundin)) - var/sound/S = sound(soundin) S.wait = 0 //No queue - S.channel = 0 //Any channel + S.channel = channel || open_sound_channel() S.volume = vol - S.environment = -1 - if (vary) + + if(vary) if(frequency) S.frequency = frequency else S.frequency = get_rand_frequency() - //sound volume falloff with pressure - var/pressure_factor = 1.0 - if(isturf(turf_source)) - // 3D sounds, the technology is here! var/turf/T = get_turf(src) //sound volume falloff with distance @@ -109,24 +52,32 @@ var/const/FALLOFF_SOUNDS = 0.5 S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff. - var/datum/gas_mixture/hearer_env = T.return_air() - var/datum/gas_mixture/source_env = turf_source.return_air() + //Atmosphere affects sound + var/pressure_factor = 1 + if(pressure_affected) + var/datum/gas_mixture/hearer_env = T.return_air() + var/datum/gas_mixture/source_env = turf_source.return_air() - if (hearer_env && source_env) - var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) + if(hearer_env && source_env) + var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) + if(pressure < ONE_ATMOSPHERE) + pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) + else //space + pressure_factor = 0 - if (pressure < ONE_ATMOSPHERE) - pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) - else //in space - pressure_factor = 0 + if(distance <= 1) + pressure_factor = max(pressure_factor, 0.15) //touching the source of the sound - if (distance <= 1) - pressure_factor = max(pressure_factor, 0.15) //hearing through contact + S.volume *= pressure_factor + //End Atmosphere affecting sound - S.volume *= pressure_factor + //Don't bother with doing anything below. + if(S.volume <= 0) + return //No sound - if (S.volume <= 0) - return //no volume means no sound + //Apply a sound environment. + if(!is_global) + S.environment = get_sound_env(pressure_factor) var/dx = turf_source.x - T.x // Hearing from the right/left S.x = dx @@ -136,58 +87,52 @@ var/const/FALLOFF_SOUNDS = 0.5 S.y = 1 S.falloff = (falloff ? falloff : FALLOFF_SOUNDS) - if(!is_global) - - if(istype(src,/mob/living/)) - var/mob/living/M = src - if (M.hallucination) - S.environment = PSYCHOTIC - else if (M.druggy) - S.environment = DRUGGED - else if (M.drowsyness) - S.environment = DIZZY - else if (M.confused) - S.environment = DIZZY - else if (M.sleeping) - S.environment = UNDERWATER - else if (pressure_factor < 0.5) - S.environment = SPACE - else - var/area/A = get_area(src) - S.environment = A.sound_env - - else if (pressure_factor < 0.5) - S.environment = SPACE - else - var/area/A = get_area(src) - S.environment = A.sound_env - src << S +/proc/sound_to_playing_players(sound, volume = 100, vary) + sound = get_sfx(sound) + for(var/M in player_list) + if(ismob(M) && !isnewplayer(M)) + var/mob/MO = M + MO.playsound_local(get_turf(MO), sound, volume, vary, pressure_affected = FALSE) + +/proc/open_sound_channel() + var/static/next_channel = 1 //loop through the available 1024 - (the ones we reserve) channels and pray that its not still being used + . = ++next_channel + if(next_channel > CHANNEL_HIGHEST_AVAILABLE) + next_channel = 1 + +/mob/proc/stop_sound_channel(chan) + src << sound(null, repeat = 0, wait = 0, channel = chan) + +/proc/get_rand_frequency() + return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs. + /client/proc/playtitlemusic() if(!ticker || !ticker.login_music) return if(is_preference_enabled(/datum/client_preference/play_lobby_music)) src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS -/proc/get_rand_frequency() - return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs. - /proc/get_sfx(soundin) if(istext(soundin)) switch(soundin) - if ("shatter") soundin = pick(shatter_sound) - if ("explosion") soundin = pick(explosion_sound) - if ("sparks") soundin = pick(spark_sound) - if ("rustle") soundin = pick(rustle_sound) - if ("punch") soundin = pick(punch_sound) - if ("clownstep") soundin = pick(clown_sound) - if ("swing_hit") soundin = pick(swing_hit_sound) - if ("hiss") soundin = pick(hiss_sound) - if ("pageturn") soundin = pick(page_sound) - if ("fracture") soundin = pick(fracture_sound) - if ("canopen") soundin = pick(can_sound) - if ("mechstep") soundin = pick(mechstep_sound) - //if ("gunshot") soundin = pick(gun_sound) - if("geiger") soundin = pick(geiger_sound) - if("geiger_weak") soundin = pick(geiger_weak_sound) + if ("shatter") soundin = pick('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg') + if ("explosion") soundin = pick('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg','sound/effects/Explosion3.ogg','sound/effects/Explosion4.ogg','sound/effects/Explosion5.ogg','sound/effects/Explosion6.ogg') + if ("sparks") soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks5.ogg','sound/effects/sparks6.ogg','sound/effects/sparks7.ogg') + if ("rustle") soundin = pick('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') + if ("punch") soundin = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') + if ("clownstep") soundin = pick('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') + if ("swing_hit") soundin = pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg') + if ("hiss") soundin = pick('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') + if ("pageturn") soundin = pick('sound/effects/pageturn1.ogg', 'sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg') + if ("fracture") soundin = pick('sound/effects/bonebreak1.ogg','sound/effects/bonebreak2.ogg','sound/effects/bonebreak3.ogg','sound/effects/bonebreak4.ogg') + if ("canopen") soundin = pick('sound/effects/can_open1.ogg','sound/effects/can_open2.ogg','sound/effects/can_open3.ogg','sound/effects/can_open4.ogg') + if ("mechstep") soundin = pick('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg') + if ("geiger") soundin = pick('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg') + if ("geiger_weak") soundin = pick('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg') return soundin + +//Are these even used? +var/list/casing_sound = list ('sound/weapons/casingfall1.ogg','sound/weapons/casingfall2.ogg','sound/weapons/casingfall3.ogg') +var/list/keyboard_sound = list ('sound/effects/keyboard/keyboard1.ogg','sound/effects/keyboard/keyboard2.ogg','sound/effects/keyboard/keyboard3.ogg', 'sound/effects/keyboard/keyboard4.ogg') +var/list/bodyfall_sound = list('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 772af61eb7..9a7ba9fb0f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1169,6 +1169,20 @@ default behaviour is: item.throw_at(target, throw_range, item.throw_speed, src) +/mob/living/get_sound_env(var/pressure_factor) + if (hallucination) + return PSYCHOTIC + else if (druggy) + return DRUGGED + else if (drowsyness) + return DIZZY + else if (confused) + return DIZZY + else if (sleeping) + return UNDERWATER + else + return ..() + //Add an entry to overlays, assuming it exists /mob/living/proc/apply_hud(cache_index, var/image/I) hud_list[cache_index] = I @@ -1186,4 +1200,4 @@ default behaviour is: return I /mob/living/proc/make_hud_overlays() - return \ No newline at end of file + return diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 9671bcb0c9..6d7d0bdfb3 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -629,6 +629,13 @@ var/global/image/backplane return TRUE +/mob/proc/get_sound_env(var/pressure_factor) + if (pressure_factor < 0.5) + return SPACE + else + var/area/A = get_area(src) + return A.sound_env + /mob/proc/position_hud_item(var/obj/item/item, var/slot) if(!istype(hud_used) || !slot || !LAZYLEN(hud_used.slot_info)) return diff --git a/polaris.dme b/polaris.dme index 08797dc063..9cab1d0078 100644 --- a/polaris.dme +++ b/polaris.dme @@ -44,6 +44,7 @@ #include "code\__defines\process_scheduler.dm" #include "code\__defines\qdel.dm" #include "code\__defines\research.dm" +#include "code\__defines\sound.dm" #include "code\__defines\species_languages.dm" #include "code\__defines\stat_tracking.dm" #include "code\__defines\subsystems.dm" From 73838e0a626532685b2be1da109bdaa6ff392f26 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sat, 10 Mar 2018 15:52:20 -0500 Subject: [PATCH 010/109] POLARIS: Revamp logging to be consistent --- code/_helpers/logging.dm | 98 +++++++++++++------ code/_helpers/mobs.dm | 24 +++-- code/_helpers/time.dm | 5 +- code/_onclick/item_attack.dm | 4 +- code/defines/procs/announce.dm | 2 +- .../gamemodes/changeling/powers/absorb.dm | 4 +- .../changeling/powers/bioelectrogenesis.dm | 4 +- .../changeling/powers/blind_sting.dm | 4 +- .../gamemodes/changeling/powers/cryo_sting.dm | 4 +- .../gamemodes/changeling/powers/deaf_sting.dm | 4 +- .../changeling/powers/death_sting.dm | 4 +- .../changeling/powers/delayed_toxin_sting.dm | 5 +- .../changeling/powers/enfeebling_string.dm | 4 +- .../changeling/powers/extract_dna_sting.dm | 4 +- .../gamemodes/changeling/powers/lsd_sting.dm | 4 +- .../gamemodes/changeling/powers/para_sting.dm | 4 +- .../gamemodes/changeling/powers/shriek.dm | 15 +-- .../changeling/powers/silence_sting.dm | 4 +- .../changeling/powers/transform_sting.dm | 4 +- .../changeling/powers/unfat_sting.dm | 4 +- code/game/gamemodes/cult/ritual.dm | 5 +- code/game/gamemodes/cult/runes.dm | 23 +++-- .../game/machinery/computer/communications.dm | 4 +- .../computer3/computers/communications.dm | 4 +- .../machinery/computer3/computers/prisoner.dm | 2 +- code/game/machinery/doors/airlock.dm | 2 +- .../kitchen/cooking_machines/fryer.dm | 4 +- code/game/machinery/kitchen/gibber.dm | 4 +- code/game/objects/effects/mines.dm | 2 +- code/game/objects/items.dm | 4 +- code/game/objects/items/devices/PDA/PDA.dm | 4 +- code/game/objects/items/devices/aicard.dm | 4 +- .../objects/items/devices/communicator/UI.dm | 2 +- .../items/devices/communicator/messaging.dm | 2 +- code/game/objects/items/devices/defib.dm | 2 +- code/game/objects/items/devices/flash.dm | 4 +- .../objects/items/devices/traitordevices.dm | 6 +- .../objects/items/weapons/cigs_lighters.dm | 2 +- .../objects/items/weapons/dna_injector.dm | 5 +- code/game/objects/items/weapons/explosives.dm | 5 +- .../objects/items/weapons/gift_wrappaper.dm | 5 +- .../items/weapons/grenades/chem_grenade.dm | 4 +- .../objects/items/weapons/grenades/grenade.dm | 2 +- code/game/objects/items/weapons/handcuffs.dm | 11 +-- .../items/weapons/implants/implanter.dm | 2 +- code/game/objects/items/weapons/trays.dm | 4 +- code/game/objects/items/weapons/weaponry.dm | 5 +- code/game/objects/structures/morgue.dm | 4 - .../stool_bed_chair_nest/wheelchair.dm | 4 +- code/game/verbs/ooc.dm | 4 +- code/modules/admin/IsBanned.dm | 6 +- code/modules/admin/admin.dm | 1 - code/modules/admin/admin_attack_log.dm | 3 +- code/modules/admin/verbs/adminsay.dm | 6 +- code/modules/admin/verbs/antag-ooc.dm | 2 +- code/modules/client/client procs.dm | 2 +- code/modules/clothing/rings/rings.dm | 4 +- code/modules/mob/dead/observer/observer.dm | 2 +- code/modules/mob/dead/observer/say.dm | 4 +- code/modules/mob/emote.dm | 5 +- code/modules/mob/language/language.dm | 2 +- code/modules/mob/living/carbon/alien/emote.dm | 2 +- code/modules/mob/living/carbon/brain/emote.dm | 2 +- .../mob/living/carbon/carbon_defense.dm | 9 +- code/modules/mob/living/carbon/human/emote.dm | 2 - code/modules/mob/living/carbon/human/human.dm | 2 +- .../living/carbon/human/human_attackhand.dm | 12 +-- .../mob/living/carbon/human/human_defense.dm | 10 +- .../mob/living/carbon/human/human_powers.dm | 4 +- .../mob/living/carbon/human/stripping.dm | 8 +- code/modules/mob/living/living.dm | 10 +- code/modules/mob/living/living_defense.dm | 8 +- code/modules/mob/living/say.dm | 7 +- code/modules/mob/living/silicon/ai/ai.dm | 2 +- code/modules/mob/living/silicon/say.dm | 8 +- .../simple_animal/borer/borer_captive.dm | 2 +- .../simple_animal/constructs/soulstone.dm | 5 +- .../mob/living/simple_animal/simple_animal.dm | 3 +- code/modules/mob/login.dm | 6 +- code/modules/mob/logout.dm | 2 +- code/modules/mob/mob_grab.dm | 9 +- code/modules/mob/mob_grab_specials.dm | 8 +- code/modules/organs/organ.dm | 4 +- code/modules/paperwork/pen.dm | 15 +-- code/modules/projectiles/gun.dm | 19 ++-- .../projectiles/guns/launcher/syringe_gun.dm | 6 +- code/modules/projectiles/projectile.dm | 13 +-- code/modules/reagents/reagent_containers.dm | 10 +- .../reagents/reagent_containers/borghydro.dm | 2 +- .../reagents/reagent_containers/dropper.dm | 6 +- .../reagent_containers/food/snacks.dm | 5 +- .../reagents/reagent_containers/hypospray.dm | 2 +- .../reagents/reagent_containers/pill.dm | 7 +- .../reagents/reagent_containers/syringes.dm | 10 +- code/modules/recycling/disposal.dm | 9 +- code/modules/vehicles/cargo_train.dm | 2 +- code/modules/vehicles/train.dm | 2 +- .../tools/ano_device_battery.dm | 4 +- 98 files changed, 261 insertions(+), 353 deletions(-) diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm index cd42c84224..5b7974d800 100644 --- a/code/_helpers/logging.dm +++ b/code/_helpers/logging.dm @@ -41,41 +41,71 @@ if (config.log_vote) diary << "\[[time_stamp()]]VOTE: [text][log_end]" -/proc/log_access(text) +/proc/log_access_in(client/new_client) if (config.log_access) - diary << "\[[time_stamp()]]ACCESS: [text][log_end]" + var/message = "[key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version]" + diary << "\[[time_stamp()]]ACCESS IN: [message][log_end]" -/proc/log_say(text) +/proc/log_access_out(mob/last_mob) + if (config.log_access) + var/message = "[key_name(last_mob)] - IP:[last_mob.lastKnownIP] - CID:Logged Out - BYOND Logged Out" + diary << "\[[time_stamp()]]ACCESS OUT: [message][log_end]" + +/proc/log_say(text, mob/speaker) if (config.log_say) - diary << "\[[time_stamp()]]SAY: [text][log_end]" + diary << "\[[time_stamp()]]SAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]" -/proc/log_ooc(text) +/proc/log_ooc(text, client/user) if (config.log_ooc) - diary << "\[[time_stamp()]]OOC: [text][log_end]" + diary << "\[[time_stamp()]]OOC: [user.simple_info_line()]: [html_decode(text)][log_end]" -/proc/log_whisper(text) +/proc/log_aooc(text, client/user) + if (config.log_ooc) + diary << "\[[time_stamp()]]AOOC: [user.simple_info_line()]: [html_decode(text)][log_end]" + +/proc/log_looc(text, client/user) + if (config.log_ooc) + diary << "\[[time_stamp()]]LOOC: [user.simple_info_line()]: [html_decode(text)][log_end]" + +/proc/log_whisper(text, mob/speaker) if (config.log_whisper) - diary << "\[[time_stamp()]]WHISPER: [text][log_end]" + diary << "\[[time_stamp()]]WHISPER: [speaker.simple_info_line()]: [html_decode(text)][log_end]" -/proc/log_emote(text) +/proc/log_emote(text, mob/speaker) if (config.log_emote) - diary << "\[[time_stamp()]]EMOTE: [text][log_end]" + diary << "\[[time_stamp()]]EMOTE: [speaker.simple_info_line()]: [html_decode(text)][log_end]" -/proc/log_attack(text) +/proc/log_attack(attacker, defender, message) if (config.log_attack) - diary << "\[[time_stamp()]]ATTACK: [text][log_end]" //Seperate attack logs? Why? FOR THE GLORY OF SATAN! + diary << "\[[time_stamp()]]ATTACK: [attacker] against [defender]: [message][log_end]" -/proc/log_adminsay(text) +/proc/log_adminsay(text, mob/speaker) if (config.log_adminchat) - diary << "\[[time_stamp()]]ADMINSAY: [text][log_end]" + diary << "\[[time_stamp()]]ADMINSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]" + +/proc/log_modsay(text, mob/speaker) + if (config.log_adminchat) + diary << "\[[time_stamp()]]MODSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]" + +/proc/log_eventsay(text, mob/speaker) + if (config.log_adminchat) + diary << "\[[time_stamp()]]EVENTSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]" + +/proc/log_ghostsay(text, mob/speaker) + if (config.log_say) + diary << "\[[time_stamp()]]DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)][log_end]" + +/proc/log_ghostemote(text, mob/speaker) + if (config.log_emote) + diary << "\[[time_stamp()]]DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)][log_end]" /proc/log_adminwarn(text) if (config.log_adminwarn) - diary << "\[[time_stamp()]]ADMINWARN: [text][log_end]" + diary << "\[[time_stamp()]]ADMINWARN: [html_decode(text)][log_end]" -/proc/log_pda(text) +/proc/log_pda(text, mob/speaker) if (config.log_pda) - diary << "\[[time_stamp()]]PDA: [text][log_end]" + diary << "\[[time_stamp()]]PDA: [speaker.simple_info_line()]: [html_decode(text)][log_end]" /proc/log_to_dd(text) world.log << text //this comes before the config check because it can't possibly runtime @@ -105,12 +135,14 @@ return english_list(comps, nothing_text="0", and_text="|", comma_text="|") //more or less a logging utility -/proc/key_name(var/whom, var/include_link = null, var/include_name = 1, var/highlight_special_characters = 1) +//Always return "Something/(Something)", even if it's an error message. +/proc/key_name(var/whom, var/include_link = null, var/highlight_special_characters = 1) var/mob/M var/client/C var/key - if(!whom) return "*null*" + if(!whom) + return "INVALID/INVALID" if(istype(whom, /client)) C = whom M = C.mob @@ -127,9 +159,11 @@ C = D.current.client else if(istype(whom, /datum)) var/datum/D = whom - return "*invalid:[D.type]*" + return "INVALID/([D.type])" + else if(istext(whom)) + return "AUTOMATED/[whom]" //Just give them the text back else - return "*invalid*" + return "INVALID/INVALID" . = "" @@ -137,7 +171,7 @@ if(include_link && C) . += "" - if(C && C.holder && C.holder.fakekey && !include_name) + if(C && C.holder && C.holder.fakekey) . += "Administrator" else . += key @@ -146,21 +180,19 @@ if(C) . += "" else . += " (DC)" else - . += "*no key*" - - if(include_name && M) - var/name + . += "INVALID" + var/name = "INVALID" + if(M) if(M.real_name) name = M.real_name else if(M.name) name = M.name - if(include_link && is_special_character(M) && highlight_special_characters) - . += "/([name])" //Orange - else - . += "/([name])" + name = "[name]" //Orange + + . += "/([name])" return . @@ -187,3 +219,9 @@ if(!istype(d)) return return d.log_info_line() + +/mob/proc/simple_info_line() + return "[key_name(src)] ([x],[y],[z])" + +/client/proc/simple_info_line() + return "[key_name(src)] ([mob.x],[mob.y],[mob.z])" diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index e97d30c6ad..930767fc55 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -145,13 +145,23 @@ Proc for attack log creation, because really why not 6 is additional information, anything that needs to be added */ -/proc/add_logs(mob/user, mob/target, what_done, var/admin=1, var/object=null, var/addition=null) - if(user && ismob(user)) - user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") - if(target && ismob(target)) - target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") - if(admin) - log_attack("[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(ismob(target) && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition]") +/proc/add_attack_logs(mob/user, mob/target, what_done, var/admin_notify = TRUE) + if(islist(target)) //Multi-victim adding + var/list/targets = target + for(var/mob/M in targets) + add_attack_logs(user,M,what_done,admin_notify) + return + + var/user_str = key_name(user) + var/target_str = key_name(target) + + if(ismob(user)) + user.attack_log += text("\[[time_stamp()]\] Attacked [target_str]: [what_done]") + if(ismob(target)) + target.attack_log += text("\[[time_stamp()]\] Attacked by [user_str]: [what_done]") + log_attack(user_str,target_str,what_done) + if(admin_notify) + msg_admin_attack("[key_name_admin(user)] vs [target_str]: [what_done]") //checks whether this item is a module of the robot it is located in. /proc/is_robot_module(var/obj/item/thing) diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm index 6dad42e128..58348761f8 100644 --- a/code/_helpers/time.dm +++ b/code/_helpers/time.dm @@ -58,8 +58,11 @@ var/next_station_date_change = 1 DAY station_date = num2text((text2num(time2text(timeofday, "YYYY"))+544)) + "-" + time2text(timeofday, "MM-DD") return station_date +//ISO 8601 /proc/time_stamp() - return time2text(station_time_in_ticks, "hh:mm:ss") + var/date_portion = time2text(world.timeofday, "YYYY-MM-DD") + var/time_portion = time2text(world.timeofday, "hh:mm:ss") + return "[date_portion]T[time_portion]" /* Returns 1 if it is the selected month and day */ proc/isDay(var/month, var/day) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 5808fc4498..ae1f81887b 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -84,9 +84,7 @@ avoid code duplication. This includes items that may sometimes act as a standard M.lastattacker = user if(!no_attack_log) - user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" - M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" - msg_admin_attack("[key_name(user)] attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" ) + add_attack_logs(user,M,"attacked with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])") ///////////////////////// user.setClickCooldown(user.get_attack_speed(src)) diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm index 5c44353540..22fa3438ca 100644 --- a/code/defines/procs/announce.dm +++ b/code/defines/procs/announce.dm @@ -111,7 +111,7 @@ datum/announcement/priority/command/Sound(var/message_sound) datum/announcement/proc/Log(message as text, message_title as text) if(log) - log_say("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]") + log_game("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]") message_admins("[key_name_admin(usr)] has made \a [announcement_type].", 1) /proc/GetNameAndAssignmentFromId(var/obj/item/weapon/card/id/I) diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 0af67b22ed..f76fd5ca47 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -53,9 +53,7 @@ src << "We stab [T] with the proboscis." src.visible_message("[src] stabs [T] with the proboscis!") T << "You feel a sharp stabbing pain!" - T.attack_log += text("\[[time_stamp()]\] Was absorbed by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Absorbed [key_name(T)]") - msg_admin_attack("[key_name(T)] was absorbed by [key_name(src)]") + add_attack_logs(src,T,"Absorbed (changeling)") var/obj/item/organ/external/affecting = T.get_organ(src.zone_sel.selecting) if(affecting.take_damage(39,0,1,0,"large organic needle")) T:UpdateDamageIcon() diff --git a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm index 1579252628..3f3c1bd7ad 100644 --- a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm +++ b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm @@ -47,7 +47,7 @@ var/agony = 80 * siemens //Does more than if hit with an electric hand, since grabbing is slower. G.affecting.stun_effect_act(0, agony, BP_TORSO, src) - msg_admin_attack("[key_name(src)] shocked [key_name(G.affecting)] with the [src].") + add_attack_logs(src,G.affecting,"Changeling shocked") if(siemens) visible_message("Arcs of electricity strike [G.affecting]!", @@ -149,7 +149,7 @@ C.electrocute_act(electrocute_amount * siemens,src,1.0,BP_TORSO) C.stun_effect_act(0, agony_amount * siemens, BP_TORSO, src) - msg_admin_attack("[key_name(user)] shocked [key_name(C)] with the [src].") + add_attack_logs(user,C,"Shocked with [src]") if(siemens) visible_message("Arcs of electricity strike [C]!", diff --git a/code/game/gamemodes/changeling/powers/blind_sting.dm b/code/game/gamemodes/changeling/powers/blind_sting.dm index 41b14478b3..347881df9b 100644 --- a/code/game/gamemodes/changeling/powers/blind_sting.dm +++ b/code/game/gamemodes/changeling/powers/blind_sting.dm @@ -15,9 +15,7 @@ var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_blind_sting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was blind stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used blind sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was blind stung by [key_name(src)]") + add_attack_logs(src,T,"Blind sting (changeling)") T << "Your eyes burn horrificly!" T.disabilities |= NEARSIGHTED var/duration = 300 diff --git a/code/game/gamemodes/changeling/powers/cryo_sting.dm b/code/game/gamemodes/changeling/powers/cryo_sting.dm index 4bb92a543e..bc68428d89 100644 --- a/code/game/gamemodes/changeling/powers/cryo_sting.dm +++ b/code/game/gamemodes/changeling/powers/cryo_sting.dm @@ -16,9 +16,7 @@ var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_cryo_sting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was cryo stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used cryo sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was cryo stung by [key_name(src)]") + add_attack_logs(src,T,"Cryo sting (changeling)") var/inject_amount = 10 if(src.mind.changeling.recursive_enhancement) inject_amount = inject_amount * 1.5 diff --git a/code/game/gamemodes/changeling/powers/deaf_sting.dm b/code/game/gamemodes/changeling/powers/deaf_sting.dm index 24c1e5d260..a94ad1744a 100644 --- a/code/game/gamemodes/changeling/powers/deaf_sting.dm +++ b/code/game/gamemodes/changeling/powers/deaf_sting.dm @@ -15,9 +15,7 @@ var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_deaf_sting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was deaf stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used deaf sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was deaf stung by [key_name(src)]") + add_attack_logs(src,T,"Deaf sting (changeling)") var/duration = 300 if(src.mind.changeling.recursive_enhancement) duration = duration + 100 diff --git a/code/game/gamemodes/changeling/powers/death_sting.dm b/code/game/gamemodes/changeling/powers/death_sting.dm index 52412a4282..6dd0cdbf85 100644 --- a/code/game/gamemodes/changeling/powers/death_sting.dm +++ b/code/game/gamemodes/changeling/powers/death_sting.dm @@ -13,9 +13,7 @@ var/mob/living/carbon/T = changeling_sting(40,/mob/proc/changeling_DEATHsting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was death stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used death sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was death stung by [key_name(src)]") + add_attack_logs(src,T,"Death sting (changeling)") T << "You feel a small prick and your chest becomes tight." T.silent = 10 T.Paralyse(10) diff --git a/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm b/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm index a9b323465c..7853a9603e 100644 --- a/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm +++ b/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm @@ -28,10 +28,7 @@ var/mob/living/carbon/T = changeling_sting(20,/mob/proc/changeling_delayed_toxic_sting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was delayed toxic stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used delayed toxic sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was delayed toxic stung by [key_name(src)]") - + add_attack_logs(src,T,"Delayed toxic sting (chagneling)") var/type_to_give = /datum/modifier/delayed_toxin_sting if(src.mind.changeling.recursive_enhancement) type_to_give = /datum/modifier/delayed_toxin_sting/strong diff --git a/code/game/gamemodes/changeling/powers/enfeebling_string.dm b/code/game/gamemodes/changeling/powers/enfeebling_string.dm index b7a6c56957..16303f7c58 100644 --- a/code/game/gamemodes/changeling/powers/enfeebling_string.dm +++ b/code/game/gamemodes/changeling/powers/enfeebling_string.dm @@ -35,9 +35,7 @@ if(ishuman(T)) var/mob/living/carbon/human/H = T - T.attack_log += text("\[[time_stamp()]\] Was enfeebling stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used enfeebling sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was enfeebling stung by [key_name(src)]") + add_attack_logs(src,T,"Enfeebling sting (changeling)") var/type_to_give = /datum/modifier/enfeeble if(src.mind.changeling.recursive_enhancement) diff --git a/code/game/gamemodes/changeling/powers/extract_dna_sting.dm b/code/game/gamemodes/changeling/powers/extract_dna_sting.dm index 6198e409a6..0c5d91d83b 100644 --- a/code/game/gamemodes/changeling/powers/extract_dna_sting.dm +++ b/code/game/gamemodes/changeling/powers/extract_dna_sting.dm @@ -35,9 +35,7 @@ src << "This creature's DNA is ruined beyond useability!" return 0 - T.attack_log += text("\[[time_stamp()]\] Had DNA extracted via sting by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used DNA extraction sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was DNA extraction stung by [key_name(src)]") + add_attack_logs(src,T,"DNA extraction sting (changeling)") var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages) absorbDNA(newDNA) diff --git a/code/game/gamemodes/changeling/powers/lsd_sting.dm b/code/game/gamemodes/changeling/powers/lsd_sting.dm index 9adb4acd09..fabb81327e 100644 --- a/code/game/gamemodes/changeling/powers/lsd_sting.dm +++ b/code/game/gamemodes/changeling/powers/lsd_sting.dm @@ -13,9 +13,7 @@ var/mob/living/carbon/T = changeling_sting(15,/mob/proc/changeling_lsdsting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was hallucination stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used hallucination sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was hallucination stung by [key_name(src)]") + add_attack_logs(src,T,"Hallucination sting (changeling)") spawn(rand(300,600)) if(T) T.hallucination += 400 feedback_add_details("changeling_powers","HS") diff --git a/code/game/gamemodes/changeling/powers/para_sting.dm b/code/game/gamemodes/changeling/powers/para_sting.dm index efe6fe8f79..7a0020bd0f 100644 --- a/code/game/gamemodes/changeling/powers/para_sting.dm +++ b/code/game/gamemodes/changeling/powers/para_sting.dm @@ -12,9 +12,7 @@ var/mob/living/carbon/T = changeling_sting(30,/mob/proc/changeling_paralysis_sting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was paralysis stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used paralysis sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was paralysis stung by [key_name(src)]") + add_attack_logs(src,T,"Paralysis sting (changeling)") T << "Your muscles begin to painfully tighten." T.Weaken(20) feedback_add_details("changeling_powers","PS") diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm index 40e796490f..4989c27f87 100644 --- a/code/game/gamemodes/changeling/powers/shriek.dm +++ b/code/game/gamemodes/changeling/powers/shriek.dm @@ -51,12 +51,8 @@ range = range * 2 to_chat(src, "We are extra loud.") - src.attack_log += text("\[[time_stamp()]\] Used Resonant Shriek.") - message_admins("[key_name(src)] used Resonant Shriek ([src.x],[src.y],[src.z]) (JMP).") - log_game("[key_name(src)] used Resonant Shriek.") - visible_message("[src] appears to shout.") - + var/list/affected = list() for(var/mob/living/M in range(range, src)) if(iscarbon(M)) if(!M.mind || !M.mind.changeling) @@ -67,7 +63,7 @@ M.adjustEarDamage(0,30) M.Confuse(20) M << sound('sound/effects/screech.ogg') - M.attack_log += text("\[[time_stamp()]\] Was affected by [key_name(src)]'s Resonant Shriek.") + affected += M else if(M != src) M << "You hear a familiar screech from nearby. It has no effect on you." @@ -77,7 +73,7 @@ M << sound('sound/weapons/flash.ogg') M << "Auditory input overloaded. Reinitializing..." M.Weaken(rand(5,10)) - M.attack_log += text("\[[time_stamp()]\] Was affected by [key_name(src)]'s Resonant Shriek.") + affected += M for(var/obj/machinery/light/L in range(range, src)) L.on = 1 @@ -85,6 +81,7 @@ changeling.last_shriek = world.time + add_attack_logs(src,affected,"Used resonant shriek") feedback_add_details("changeling_powers","RS") return 1 @@ -133,9 +130,7 @@ visible_message("[src] appears to shout.") - src.attack_log += text("\[[time_stamp()]\] Used Dissonant Shriek.") - message_admins("[key_name(src)] used Dissonant Shriek ([src.x],[src.y],[src.z]) (JMP).") - log_game("[key_name(src)] used Dissonant Shriek.") + add_attack_logs(src,null,"Use dissonant shriek") for(var/obj/machinery/light/L in range(5, src)) L.on = 1 diff --git a/code/game/gamemodes/changeling/powers/silence_sting.dm b/code/game/gamemodes/changeling/powers/silence_sting.dm index 1ab25278a4..334b0c139f 100644 --- a/code/game/gamemodes/changeling/powers/silence_sting.dm +++ b/code/game/gamemodes/changeling/powers/silence_sting.dm @@ -15,9 +15,7 @@ var/mob/living/carbon/T = changeling_sting(10,/mob/proc/changeling_silence_sting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was silence stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used silence sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was silence stung by [key_name(src)]") + add_attack_logs(src,T,"Silence sting (changeling)") var/duration = 30 if(src.mind.changeling.recursive_enhancement) duration = duration + 10 diff --git a/code/game/gamemodes/changeling/powers/transform_sting.dm b/code/game/gamemodes/changeling/powers/transform_sting.dm index 797eec92d2..678e195e22 100644 --- a/code/game/gamemodes/changeling/powers/transform_sting.dm +++ b/code/game/gamemodes/changeling/powers/transform_sting.dm @@ -36,9 +36,7 @@ if((HUSK in T.mutations) || (!ishuman(T) && !issmall(T))) src << "Our sting appears ineffective against its DNA." return 0 - T.attack_log += text("\[[time_stamp()]\] Was transform stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used transform sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was transform stung by [key_name(src)]") + add_attack_logs(src,T,"Transformation sting (changeling)") T.visible_message("[T] transforms!") T.dna = chosen_dna.Clone() T.real_name = chosen_dna.real_name diff --git a/code/game/gamemodes/changeling/powers/unfat_sting.dm b/code/game/gamemodes/changeling/powers/unfat_sting.dm index 4b42f55e30..f2e238746d 100644 --- a/code/game/gamemodes/changeling/powers/unfat_sting.dm +++ b/code/game/gamemodes/changeling/powers/unfat_sting.dm @@ -11,9 +11,7 @@ var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting) if(!T) return 0 - T.attack_log += text("\[[time_stamp()]\] Was unfat stung by [key_name(src)]") - src.attack_log += text("\[[time_stamp()]\] Used unfat sting on [key_name(T)]") - msg_admin_attack("[key_name(T)] was unfat stung by [key_name(src)]") + add_attack_logs(src,T,"Unfat sting (changeling)") T << "you feel a small prick as stomach churns violently and you become to feel skinnier." T.overeatduration = 0 T.nutrition -= 100 diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 8db7a49255..d91e2e1f47 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -292,10 +292,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa"," words[cultwords[V]] = V attack(mob/living/M as mob, mob/living/user as mob) - - M.attack_log += text("\[[time_stamp()]\] Has had the [name] used on them by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used [name] on [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) used [name] on [M.name] ([M.ckey]) (JMP)") + add_attack_logs(user,M,"Hit with [name]") if(istype(M,/mob/observer/dead)) var/mob/observer/dead/D = M diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 0e0ff60791..d7579698d1 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -139,7 +139,7 @@ var/list/sacrificed = list() target.take_overall_damage(0, rand(5, 20)) // You dirty resister cannot handle the damage to your mind. Easily. - even cultists who accept right away should experience some effects // Resist messages go! if(initial_message) //don't do this stuff right away, only if they resist or hesitate. - admin_attack_log(attacker, target, "Used a convert rune", "Was subjected to a convert rune", "used a convert rune on") + add_attack_logs(attacker,target,"Convert rune") switch(target.getFireLoss()) if(0 to 25) target << "Your blood boils as you force yourself to resist the corruption invading every corner of your mind." @@ -247,7 +247,7 @@ var/list/sacrificed = list() if(R.word1==cultwords["travel"] && R.word2==cultwords["blood"] && R.word3==cultwords["self"]) for(var/mob/living/carbon/D in R.loc) if(D.stat!=2) - admin_attack_log(usr, D, "Used a blood drain rune.", "Was victim of a blood drain rune.", "used a blood drain rune on") + add_attack_logs(usr,D,"Blood drain rune") var/bdrain = rand(1,25) D << "You feel weakened." D.take_overall_damage(bdrain, 0) @@ -933,7 +933,7 @@ var/list/sacrificed = list() if(affected.len) usr.say("Sti[pick("'","`")] kaliedir!") usr << "The world becomes quiet as the deafening rune dissipates into fine dust." - admin_attacker_log_many_victims(usr, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on") + add_attack_logs(usr,affected,"Deafen rune") qdel(src) else return fizzle() @@ -952,7 +952,7 @@ var/list/sacrificed = list() if(affected.len) usr.whisper("Sti[pick("'","`")] kaliedir!") usr << "Your talisman turns into gray dust, deafening everyone around." - admin_attacker_log_many_victims(usr, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on") + add_attack_logs(usr, affected, "Deafen rune") for (var/mob/V in orange(1,src)) if(!(iscultist(V))) V.show_message("Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..", 3) @@ -978,7 +978,7 @@ var/list/sacrificed = list() if(affected.len) usr.say("Sti[pick("'","`")] kaliesin!") usr << "The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust." - admin_attacker_log_many_victims(usr, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on") + add_attack_logs(usr, affected, "Blindness rune") qdel(src) else return fizzle() @@ -998,7 +998,7 @@ var/list/sacrificed = list() if(affected.len) usr.whisper("Sti[pick("'","`")] kaliesin!") usr << "Your talisman turns into gray dust, blinding those who not follow the Nar-Sie." - admin_attacker_log_many_victims(usr, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on") + add_attack_logs(usr, affected, "Blindness rune") return @@ -1035,8 +1035,7 @@ var/list/sacrificed = list() if(iscultist(C) && !C.stat) C.say("Dedo ol[pick("'","`")]btoh!") C.take_overall_damage(15, 0) - admin_attacker_log_many_victims(usr, victims, "Used a blood boil rune.", "Was the victim of a blood boil rune.", "used a blood boil rune on") - log_and_message_admins_many(cultists - usr, "assisted activating a blood boil rune.") + add_attack_logs(usr, victims, "Blood boil rune") qdel(src) else return fizzle() @@ -1084,13 +1083,13 @@ var/list/sacrificed = list() C.Weaken(1) C.Stun(1) C.show_message("The rune explodes in a bright flash.", 3) - admin_attack_log(usr, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") + add_attack_logs(usr,C,"Stun rune") else if(issilicon(L)) var/mob/living/silicon/S = L S.Weaken(5) S.show_message("BZZZT... The rune has exploded in a bright flash.", 3) - admin_attack_log(usr, S, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") + add_attack_logs(usr,S,"Stun rune") qdel(src) else ///When invoked as talisman, stun and mute the target mob. usr.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!") @@ -1104,7 +1103,7 @@ var/list/sacrificed = list() if(issilicon(T)) T.Weaken(15) - admin_attack_log(usr, T, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") + add_attack_logs(usr,T,"Stun rune") else if(iscarbon(T)) var/mob/living/carbon/C = T C.flash_eyes() @@ -1112,7 +1111,7 @@ var/list/sacrificed = list() C.silent += 15 C.Weaken(25) C.Stun(25) - admin_attack_log(usr, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on") + add_attack_logs(usr,C,"Stun rune") return /////////////////////////////////////////TWENTY-FIFTH RUNE diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 29196f44d5..c95bd9879c 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -187,7 +187,7 @@ return CentCom_announce(input, usr) usr << "Message transmitted." - log_say("[key_name(usr)] has made an IA [using_map.boss_short] announcement: [input]") + log_game("[key_name(usr)] has made an IA [using_map.boss_short] announcement: [input]") centcomm_message_cooldown = 1 spawn(300)//10 minute cooldown centcomm_message_cooldown = 0 @@ -204,7 +204,7 @@ return Syndicate_announce(input, usr) usr << "Message transmitted." - log_say("[key_name(usr)] has made an illegal announcement: [input]") + log_game("[key_name(usr)] has made an illegal announcement: [input]") centcomm_message_cooldown = 1 spawn(300)//10 minute cooldown centcomm_message_cooldown = 0 diff --git a/code/game/machinery/computer3/computers/communications.dm b/code/game/machinery/computer3/computers/communications.dm index 6f802c54bd..acd66ebde1 100644 --- a/code/game/machinery/computer3/computers/communications.dm +++ b/code/game/machinery/computer3/computers/communications.dm @@ -197,7 +197,7 @@ return CentCom_announce(input, usr) usr << "Message transmitted." - log_say("[key_name(usr)] has made a [using_map.boss_short] announcement: [input]") + log_game("[key_name(usr)] has made a [using_map.boss_short] announcement: [input]") centcomm_message_cooldown = 1 spawn(600)//10 minute cooldown centcomm_message_cooldown = 0 @@ -214,7 +214,7 @@ return Syndicate_announce(input, usr) usr << "Message transmitted." - log_say("[key_name(usr)] has made an illegal announcement: [input]") + log_game("[key_name(usr)] has made an illegal announcement: [input]") centcomm_message_cooldown = 1 spawn(600)//10 minute cooldown centcomm_message_cooldown = 0 diff --git a/code/game/machinery/computer3/computers/prisoner.dm b/code/game/machinery/computer3/computers/prisoner.dm index 7e3ada285d..27943bb353 100644 --- a/code/game/machinery/computer3/computers/prisoner.dm +++ b/code/game/machinery/computer3/computers/prisoner.dm @@ -95,7 +95,7 @@ var/obj/item/weapon/implant/I = locate(href_list["warn"]) if( istype(I) && I.imp_in) var/mob/living/carbon/R = I.imp_in - log_say("PrisonComputer3 message: [key_name(usr)]->[key_name(R)] : [warning]") + log_game("PrisonComputer3 message: [key_name(usr)]->[key_name(R)] : [warning]") R << "You hear a voice in your head saying: '[warning]'" interact() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 7f140b4b7f..3179e7c2d1 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -565,7 +565,7 @@ About the new airlock wires panel: else if(duration) //electrify door for the given duration seconds if(usr) shockedby += text("\[[time_stamp()]\] - [usr](ckey:[usr.ckey])") - usr.attack_log += text("\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]") + add_attack_logs(usr,name,"Electrified a door") else shockedby += text("\[[time_stamp()]\] - EMP)") message = "The door is now electrified [duration == -1 ? "permanently" : "for [duration] second\s"]." diff --git a/code/game/machinery/kitchen/cooking_machines/fryer.dm b/code/game/machinery/kitchen/cooking_machines/fryer.dm index 1fc0e75ef1..7e5cc055e8 100644 --- a/code/game/machinery/kitchen/cooking_machines/fryer.dm +++ b/code/game/machinery/kitchen/cooking_machines/fryer.dm @@ -58,9 +58,7 @@ victim << "Searing hot oil scorches your [E ? E.name : "flesh"]!" if(victim.client) - user.attack_log += text("\[[time_stamp()]\] Has [cook_type] \the [victim] ([victim.ckey]) in \a [src]") - victim.attack_log += text("\[[time_stamp()]\] Has been [cook_type] in \a [src] by [user.name] ([user.ckey])") - msg_admin_attack("[user] ([user.ckey]) [cook_type] \the [victim] ([victim.ckey]) in \a [src]. (JMP)") + add_attack_logs(user,victim,"[cook_type] in [src]") icon_state = off_icon cooking = 0 diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index 9b6b503237..f824053861 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -211,9 +211,7 @@ if(src.occupant.reagents) src.occupant.reagents.trans_to_obj(new_meat, round(occupant.reagents.total_volume/slab_count,1)) - src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed! - user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" - msg_admin_attack("[user.name] ([user.ckey]) gibbed [src.occupant] ([src.occupant.ckey]) (JMP)") + add_attack_logs(user,occupant,"Used [src] to gib") src.occupant.ghostize() diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 47fa55be1a..a1a6623ff1 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -208,7 +208,7 @@ /obj/item/weapon/mine/attack_self(mob/user as mob) // You do not want to move or throw a land mine while priming it... Explosives + Sudden Movement = Bad Times add_fingerprint(user) - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") + msg_admin_attack("[key_name_admin(user)] primed \a [src]") user.visible_message("[user] starts priming \the [src.name].", "You start priming \the [src.name]. Hold still!") if(do_after(user, 10 SECONDS)) playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 484df24866..b646cffa45 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -480,9 +480,7 @@ var/list/global/slot_flags_enumeration = list( visible_message("[U] attempts to stab [M] in the eyes, but misses!") return - user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") //BS12 EDIT ALG + add_attack_logs(user,M,"Attack eyes with [name]") user.setClickCooldown(user.get_attack_speed()) user.do_attack_animation(M) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index dcef269ee9..615c464ea4 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1169,7 +1169,7 @@ var/global/list/obj/item/device/pda/PDAs = list() var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" ([reply ? "Reply" : "Unable to Reply"])" new_info(message_silent, ttone, reception_message) - log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]") + log_pda("(PDA: [sending_unit]) sent \"[message]\" to [name]", usr) new_message = 1 update_icon() @@ -1181,7 +1181,7 @@ var/global/list/obj/item/device/pda/PDAs = list() var/reception_message = "\icon[src] Message from [sender] ([sender_job]), \"[message]\" (Reply) [track]" new_info(message_silent, newstone, reception_message) - log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]") + log_pda("(PDA: [sending_unit]) sent \"[message]\" to [name]",usr) new_message = 1 /obj/item/device/pda/verb/verb_reset_pda() diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index ab893415ac..ebad249bde 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -61,7 +61,7 @@ if (href_list["wipe"]) var/confirm = alert("Are you sure you want to disable this core's power? This cannot be undone once started.", "Confirm Shutdown", "Yes", "No") if(confirm == "Yes" && (CanUseTopic(user, state) == STATUS_INTERACTIVE)) - admin_attack_log(user, carded_ai, "Purged using \the [src.name]", "Was purged with \the [src.name]", "used \the [src.name] to purge") + add_attack_logs(user,carded_ai,"Purged from AI Card") flush = 1 carded_ai.suiciding = 1 carded_ai << "Your power has been disabled!" @@ -110,7 +110,7 @@ new /obj/structure/AIcore/deactivated(get_turf(ai)) ai.carded = 1 - admin_attack_log(user, ai, "Extracted with [src.name]", "Was extracted with [src.name]", "used the [src.name] to extract") + add_attack_logs(user,ai,"Extracted into AI Card") src.name = "[initial(name)] - [ai.name]" ai.loc = src diff --git a/code/game/objects/items/devices/communicator/UI.dm b/code/game/objects/items/devices/communicator/UI.dm index ab5aae9fbf..cbdae90c90 100644 --- a/code/game/objects/items/devices/communicator/UI.dm +++ b/code/game/objects/items/devices/communicator/UI.dm @@ -189,7 +189,7 @@ if(text) exonet.send_message(their_address, "text", text) im_list += list(list("address" = exonet.address, "to_address" = their_address, "im" = text)) - log_pda("[usr] (COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]") + log_pda("(COMM: [src]) sent \"[text]\" to [exonet.get_atom_from_address(their_address)]", usr) for(var/mob/M in player_list) if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat) diff --git a/code/game/objects/items/devices/communicator/messaging.dm b/code/game/objects/items/devices/communicator/messaging.dm index 3419985a71..d600f96a0f 100644 --- a/code/game/objects/items/devices/communicator/messaging.dm +++ b/code/game/objects/items/devices/communicator/messaging.dm @@ -136,7 +136,7 @@ to_chat(src, "You have sent '[text_message]' to [chosen_communicator].") exonet_messages.Add("To [chosen_communicator]:
[text_message]") - log_pda("[usr] (COMM: [src]) sent \"[text_message]\" to [chosen_communicator]") + log_pda("(DCOMM: [src]) sent \"[text_message]\" to [chosen_communicator]", src) for(var/mob/M in player_list) if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat) diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index 4b9ea5137a..af9d697d63 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -475,7 +475,7 @@ if(burn_damage > 15 && H.can_feel_pain()) H.emote("scream") - admin_attack_log(user, H, "Electrocuted using \a [src]", "Was electrocuted with \a [src]", "used \a [src] to electrocute") + add_attack_logs(user,H,"Shocked using [name]") /obj/item/weapon/shockpaddles/proc/make_alive(mob/living/carbon/human/M) //This revives the mob var/deadtime = world.time - M.timeofdeath diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 6027976134..ac62201fc5 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -59,9 +59,7 @@ /obj/item/device/flash/attack(mob/living/M, mob/living/user, var/target_zone) if(!user || !M) return //sanity - M.attack_log += text("\[[time_stamp()]\] Has been flashed (attempt) with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey]) (JMP)") + add_attack_logs(user,M,"Flashed (attempt) with [src]") user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index 126a4871c9..7820d0c4ea 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -35,9 +35,9 @@ effective or pretty fucking useless. user << "The mind batterer has been burnt out!" return - user.attack_log += text("\[[time_stamp()]\] Used [src] to knock down people in the area.") - + var/list/affected = list() for(var/mob/living/carbon/human/M in orange(10, user)) + affected += M spawn() if(prob(50)) @@ -49,6 +49,8 @@ effective or pretty fucking useless. else M << "You feel a sudden, electric jolt travel through your head." + add_attack_logs(user,affected,"Used a [name]") + playsound(src.loc, 'sound/misc/interference.ogg', 50, 1) user << "You trigger [src]." times_used += 1 diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index c39c7e0067..5d60c8485b 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -562,7 +562,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(lit == 1) M.IgniteMob() - msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] and lit them on fire (INTENT: [uppertext(user.a_intent)]) (JMP)") + add_attack_logs(user,M,"Lit on fire with [src]") if(istype(M.wear_mask, /obj/item/clothing/mask/smokable/cigarette) && user.zone_sel.selecting == O_MOUTH && lit) var/obj/item/clothing/mask/smokable/cigarette/cig = M.wear_mask diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index febde75f68..ac0a93941b 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -130,10 +130,7 @@ if((buf.types & DNA2_BUF_SE) && (block ? (GetState() && block == MONKEYBLOCK) : GetState(MONKEYBLOCK))) injected_with_monkey = " (MONKEY)" - M.attack_log += text("\[[time_stamp()]\] Has been injected with [name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [name] to inject [M.name] ([M.ckey])") - log_attack("[user.name] ([user.ckey]) used the [name] to inject [M.name] ([M.ckey])") - message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with \the [src][injected_with_monkey]") + add_attack_logs(user,M,"[injected_with_monkey] used the [name] on") // Apply the DNA shit. inject(M, user) diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 1e1565a2ae..b49a76c5a9 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -55,11 +55,8 @@ loc = null if (ismob(target)) - add_logs(user, target, "planted [name] on") + add_attack_logs(user, target, "planted [name] on with [timer] second fuse") user.visible_message("[user.name] finished planting an explosive on [target.name]!") - message_admins("[key_name(user, user.client)](?) planted [src.name] on [key_name(target)](?) with [timer] second fuse",0,1) - log_game("[key_name(user)] planted [src.name] on [key_name(target)] with [timer] second fuse") - else message_admins("[key_name(user, user.client)](?) planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [timer] second fuse",0,1) log_game("[key_name(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse") diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm index 46543b901b..bef0f8fcd9 100644 --- a/code/game/objects/items/weapons/gift_wrappaper.dm +++ b/code/game/objects/items/weapons/gift_wrappaper.dm @@ -179,10 +179,7 @@ H.loc = present - H.attack_log += text("\[[time_stamp()]\] Has been wrapped with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to wrap [H.name] ([H.ckey])") - msg_admin_attack("[key_name(user)] used [src] to wrap [key_name(H)]") - + add_attack_logs(user,H,"Wrapped with [src]") else user << "You need more paper." else diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 0eaf073cfa..92de17d994 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -43,7 +43,7 @@ if(stage > 1 && !active && clown_check(user)) user << "You prime \the [name]!" - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src]. (JMP)") + msg_admin_attack("[key_name_admin(user)] primed \a [src]") activate() add_fingerprint(user) @@ -136,7 +136,7 @@ icon_state = initial(icon_state) + "_active" if(user) - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") + msg_admin_attack("[key_name_admin(user)] primed \a [src.name]") return diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index b46d987b4c..5854e02cac 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -72,7 +72,7 @@ return if(user) - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") + msg_admin_attack("[key_name_admin(user)] primed \a [src.name]") icon_state = initial(icon_state) + "_active" active = 1 diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 344387f8cd..5ac6545acd 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -82,9 +82,7 @@ if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime return 0 - H.attack_log += text("\[[time_stamp()]\] Has been handcuffed (attempt) by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Attempted to handcuff [H.name] ([H.ckey])") - msg_admin_attack("[key_name(user)] attempted to handcuff [key_name(H)]") + add_attack_logs(user,H,"Handcuffed (attempt)") feedback_add_details("handcuffs","H") user.setClickCooldown(user.get_attack_speed(src)) @@ -129,8 +127,7 @@ var/last_chew = 0 var/s = "[H.name] chews on [T.his] [O.name]!" H.visible_message(s, "You chew on your [O.name]!") - H.attack_log += text("\[[time_stamp()]\] [s] ([H.ckey])") - log_attack("[s] ([H.ckey])") + add_attack_logs(H,H,"chewed own [O.name]") if(O.take_damage(3,0,1,1,"teeth marks")) H:UpdateDamageIcon() @@ -302,9 +299,7 @@ var/last_chew = 0 if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime return 0 - H.attack_log += text("\[[time_stamp()]\] Has been legcuffed (attempt) by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Attempted to legcuff [H.name] ([H.ckey])") - msg_admin_attack("[key_name(user)] attempted to legcuff [key_name(H)]") + add_attack_logs(user,H,"Legcuffed (attempt)") feedback_add_details("legcuffs","H") user.setClickCooldown(user.get_attack_speed(src)) diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index 87a76305c6..8052b19de6 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -54,7 +54,7 @@ if(user && M && (get_turf(M) == T1) && src && src.imp) M.visible_message("[M] has been implanted by [user].") - admin_attack_log(user, M, "Implanted using \the [src.name] ([src.imp.name])", "Implanted with \the [src.name] ([src.imp.name])", "used an implanter, [src.name] ([src.imp.name]), on") + add_attack_logs(user,M,"Implanted with [imp.name] using [name]") if(src.imp.implanted(M)) src.imp.loc = M diff --git a/code/game/objects/items/weapons/trays.dm b/code/game/objects/items/weapons/trays.dm index c2ea991d98..68a2c3a774 100644 --- a/code/game/objects/items/weapons/trays.dm +++ b/code/game/objects/items/weapons/trays.dm @@ -52,9 +52,7 @@ if (istype(location, /turf/simulated)) location.add_blood(H) ///Plik plik, the sound of blood - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (JMP)") + add_attack_logs(user,M,"Hit with [src]") if(prob(15)) M.Weaken(3) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 8938e611c0..b5ae0912e9 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -17,10 +17,7 @@ /obj/item/weapon/nullrod/attack(mob/M as mob, mob/living/user as mob) //Paste from old-code to decult with a null rod. - M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [M.name] ([M.ckey])") - - msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") + add_attack_logs(user,M,"Hit with [src] (nullrod)") user.setClickCooldown(user.get_attack_speed(src)) user.do_attack_animation(M) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index d795d53e3d..732bb1b55d 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -306,10 +306,6 @@ if (C.can_feel_pain()) C.emote("scream") - //Logging for this causes runtimes resulting in the cremator locking up. Commenting it out until that's figured out. - //M.attack_log += "\[[time_stamp()]\] Has been cremated by [user]/[user.ckey]" //No point in this when the mob's about to be deleted - //user.attack_log +="\[[time_stamp()]\] Cremated [M]/[M.ckey]" - //log_attack("\[[time_stamp()]\] [user]/[user.ckey] cremated [M]/[M.ckey]") M.death(1) M.ghostize() qdel(M) diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm index 550b59d112..bb1a62e40b 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm @@ -176,9 +176,7 @@ if(pulling) occupant.visible_message("[pulling] has thrusted \the [name] into \the [A], throwing \the [occupant] out of it!") - pulling.attack_log += "\[[time_stamp()]\] Crashed [occupant.name]'s ([occupant.ckey]) [name] into \a [A]" - occupant.attack_log += "\[[time_stamp()]\] Thrusted into \a [A] by [pulling.name] ([pulling.ckey]) with \the [name]" - msg_admin_attack("[pulling.name] ([pulling.ckey]) has thrusted [occupant.name]'s ([occupant.ckey]) [name] into \a [A] (JMP)") + add_attack_logs(pulling,occupant,"Crashed their [name] into [A]") else occupant.visible_message("[occupant] crashed into \the [A]!") diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index 8fafb555a3..11aa51eb90 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -35,7 +35,7 @@ message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]") return - log_ooc("[mob.name]/[key] : [msg]") + log_ooc(msg, src) if(msg) handle_spam_prevention(MUTE_OOC) @@ -108,7 +108,7 @@ message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]") return - log_ooc("(LOCAL) [mob.name]/[key] : [msg]") + log_looc(msg,src) if(msg) handle_spam_prevention(MUTE_OOC) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 39926e1414..e28c4fd570 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -6,13 +6,13 @@ world/IsBanned(key,address,computer_id) //Guest Checking if(!config.guests_allowed && IsGuestKey(key)) - log_access("Failed Login: [key] - Guests not allowed") + log_adminwarn("Failed Login: [key] - Guests not allowed") message_admins("Failed Login: [key] - Guests not allowed") return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") //check if the IP address is a known TOR node if(config && config.ToRban && ToRban_isbanned(address)) - log_access("Failed Login: [src] - Banned: ToR") + log_adminwarn("Failed Login: [src] - Banned: ToR") message_admins("Failed Login: [src] - Banned: ToR") //ban their computer_id and ckey for posterity AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0) @@ -24,7 +24,7 @@ world/IsBanned(key,address,computer_id) //Ban Checking . = CheckBan( ckey(key), computer_id, address ) if(.) - log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") + log_adminwarn("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") message_admins("Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]") return . diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index a2d8eed8fa..a9075a8430 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -12,7 +12,6 @@ var/global/floorIsLava = 0 C << msg /proc/msg_admin_attack(var/text) //Toggleable Attack Messages - log_attack(text) var/rendered = "ATTACK: [text]" for(var/client/C in admins) if((R_ADMIN|R_MOD) & C.holder.rights) diff --git a/code/modules/admin/admin_attack_log.dm b/code/modules/admin/admin_attack_log.dm index 967a4375da..f04bdf3b61 100644 --- a/code/modules/admin/admin_attack_log.dm +++ b/code/modules/admin/admin_attack_log.dm @@ -16,7 +16,7 @@ proc/log_and_message_admins_many(var/list/mob/users, var/message) log_admin("[english_list(user_keys)] [message]") message_admins("[english_list(user_keys)] [message]") - +/* Old procs proc/admin_attack_log(var/mob/attacker, var/mob/victim, var/attacker_message, var/victim_message, var/admin_message) if(victim) victim.attack_log += text("\[[time_stamp()]\] [key_name(attacker)] - [victim_message]") @@ -42,3 +42,4 @@ proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, amoun "used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred", "was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred", "used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into") +*/ diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index 264e5ad64e..0fdc158227 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -9,7 +9,7 @@ if(!msg) return - log_admin("ADMIN: [key_name(src)] : [msg]") + log_adminsay(msg,src) if(check_rights(R_ADMIN,0)) for(var/client/C in admins) @@ -27,7 +27,7 @@ return msg = sanitize(msg) - log_admin("MOD: [key_name(src)] : [msg]") + log_modsay(msg,src) if (!msg) return @@ -50,7 +50,7 @@ return msg = sanitize(msg) - log_admin("EVENT: [key_name(src)] : [msg]") + log_eventsay(msg,src) if (!msg) return diff --git a/code/modules/admin/verbs/antag-ooc.dm b/code/modules/admin/verbs/antag-ooc.dm index f3a6ffc77c..22689f1718 100644 --- a/code/modules/admin/verbs/antag-ooc.dm +++ b/code/modules/admin/verbs/antag-ooc.dm @@ -39,4 +39,4 @@ if((M.mind && M.mind.special_role && A && A.can_use_aooc) || isobserver(M)) // Antags must have their type be allowed to AOOC to see AOOC. This prevents, say, ERT from seeing AOOC. to_chat(M, "[create_text_tag("aooc", "Antag-OOC:", M.client)] [player_display]: [msg]") - log_ooc("(ANTAG) [key] : [msg]") \ No newline at end of file + log_aooc(msg,src) \ No newline at end of file diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 88352c04eb..95ce3456b6 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -252,7 +252,7 @@ //Panic bunker code if (isnum(player_age) && player_age == 0) //first connection if (config.panic_bunker && !holder && !deadmin_holder) - log_access("Failed Login: [key] - New account attempting to connect during panic bunker") + log_adminwarn("Failed Login: [key] - New account attempting to connect during panic bunker") message_admins("Failed Login: [key] - New account attempting to connect during panic bunker") to_chat(src, "Sorry but the server is currently not accepting connections from never before seen players.") qdel(src) diff --git a/code/modules/clothing/rings/rings.dm b/code/modules/clothing/rings/rings.dm index f8ebd5443e..852ccfdb82 100644 --- a/code/modules/clothing/rings/rings.dm +++ b/code/modules/clothing/rings/rings.dm @@ -37,9 +37,9 @@ if(reagents.total_volume) to_chat(H, "You feel a prick as you slip on \the [src].") if(H.reagents) - var/contained_reagents = reagents.get_reagents() + var/contained = reagents.get_reagents() var/trans = reagents.trans_to_mob(H, 15, CHEM_BLOOD) - admin_inject_log(usr, H, src, contained_reagents, trans) + add_attack_logs(usr, H, "Injected with [name] containing [contained] transferred [trans] units") return //Sleepy Ring diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 143ef9ef7f..71664d957d 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -747,7 +747,7 @@ mob/observer/dead/MayRespawn(var/feedback = 0) return 0 var/msg = sanitize(input(src, "Message:", "Spectral Whisper") as text|null) if(msg) - log_say("SpectralWhisper: [key_name(usr)]->[M.key] : [msg]") + log_say("(SPECWHISP to [key_name(M)]): [msg]", src) M << " You hear a strange, unidentifiable voice in your head... [msg]" src << " You said: '[msg]' to [M]." else diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index 8da03e4de0..c950a84209 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -4,7 +4,7 @@ if (!message) return - log_say("Ghost/[src.key] : [message]") + log_ghostsay(message, src) if (src.client) if(message) @@ -25,7 +25,7 @@ if(act != "me") return - log_emote("Ghost/[src.key] : [message]") + log_ghostemote(message, src) if(src.client) if(message) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 4de1dcf595..eb0137a57d 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -15,14 +15,13 @@ else input = message if(input) + log_emote(message,src) //Log before we add junk message = "[src] [input]" else return if (message) - log_emote("[name]/[key] : [message]") - message = say_emphasis(message) // Hearing gasp and such every five seconds is not good emotes were not global for a reason. @@ -71,7 +70,7 @@ input = say_emphasis(input) if(input) - log_emote("Ghost/[src.key] : [input]") + log_ghostemote(input, src) if(!invisibility) //If the ghost is made visible by admins or cult. And to see if the ghost has toggled its own visibility, as well. -Mech visible_message("[src] [input]") else diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index b9eb226e12..ef8fc37c19 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -99,7 +99,7 @@ return (copytext(message, length(message)) == "!") ? 2 : 1 /datum/language/proc/broadcast(var/mob/living/speaker,var/message,var/speaker_mask) - log_say("[key_name(speaker)] : ([name]) [message]") + log_say("(HIVE) [message]", src) if(!speaker_mask) speaker_mask = speaker.name message = format_message(message, get_spoken_verb(message)) diff --git a/code/modules/mob/living/carbon/alien/emote.dm b/code/modules/mob/living/carbon/alien/emote.dm index 7a70f22cea..175338e5ff 100644 --- a/code/modules/mob/living/carbon/alien/emote.dm +++ b/code/modules/mob/living/carbon/alien/emote.dm @@ -119,7 +119,7 @@ else src << text("Invalid Emote: []", act) if ((message && src.stat == 0)) - log_emote("[name]/[key] : [message]") + log_emote(message, src) if (m_type & 1) for(var/mob/O in viewers(src, null)) O.show_message(message, m_type) diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm index cb07a338c7..22efdc76c6 100644 --- a/code/modules/mob/living/carbon/brain/emote.dm +++ b/code/modules/mob/living/carbon/brain/emote.dm @@ -63,7 +63,7 @@ src << "Unusable emote '[act]'. Say *help for a list." if (message) - log_emote("[name]/[key] : [message]") + log_emote(message, src) for(var/mob/M in dead_mob_list) if (!M.client || istype(M, /mob/new_player)) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 08d0c9384e..18acbda04d 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -101,9 +101,8 @@ G.last_action = world.time flick(G.hud.icon_state, G.hud) - user.attack_log += "\[[time_stamp()]\] Knifed [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" - src.attack_log += "\[[time_stamp()]\] Got knifed by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" - msg_admin_attack("[key_name(user)] knifed [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" ) + add_attack_logs(user,src,"Knifed (throat slit)") + return 1 /mob/living/carbon/proc/shank_attack(obj/item/W, obj/item/weapon/grab/G, mob/user, hit_zone) @@ -119,9 +118,7 @@ if(W.hitsound) playsound(loc, W.hitsound, 50, 1, -1) - user.attack_log += "\[[time_stamp()]\] Shanked [name] ([ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" - src.attack_log += "\[[time_stamp()]\] Got shanked by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" - msg_admin_attack("[key_name(user)] shanked [key_name(src)] with [W.name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(W.damtype)])" ) + add_attack_logs(user,src,"Knifed (shanked)") return 1 diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 2ca171cb87..0a85e9a155 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -728,10 +728,8 @@ src << "Unusable emote '[act]'. Say *help for a list." if (message) - log_emote("[name]/[key] : [message]") custom_emote(m_type,message) - /mob/living/carbon/human/verb/pose() set name = "Set Pose" set desc = "Sets a description which will be shown when someone examines you." diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index bda56bcfbf..fd6e189d11 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -877,7 +877,7 @@ else target.show_message(" You hear a voice that seems to echo around the room: [say]") usr.show_message(" You project your mind into [target.real_name]: [say]") - log_say("[key_name(usr)] sent a telepathic message to [key_name(target)]: [say]") + log_say("(TPATH to [key_name(target)]) [say]",src) for(var/mob/observer/dead/G in world) G.show_message("Telepathic message from [src] to [target]: [say]") diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 2c629b25f9..a2c725b5bd 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -235,9 +235,8 @@ H.visible_message("[attack_message]") playsound(loc, ((miss_type) ? (miss_type == 1 ? attack.miss_sound : 'sound/weapons/thudswoosh.ogg') : attack.attack_sound), 25, 1, -1) - H.attack_log += text("\[[time_stamp()]\] [miss_type ? (miss_type == 1 ? "Missed" : "Blocked") : "[pick(attack.attack_verb)]"] [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] [miss_type ? (miss_type == 1 ? "Was missed by" : "Has blocked") : "Has Been [pick(attack.attack_verb)]"] by [H.name] ([H.ckey])") - msg_admin_attack("[key_name(H)] [miss_type ? (miss_type == 1 ? "has missed" : "was blocked by") : "has [pick(attack.attack_verb)]"] [key_name(src)]") + + add_attack_logs(H,src,"Melee attacked with fists (miss/block)") if(miss_type) return 0 @@ -268,10 +267,8 @@ apply_damage(real_damage, hit_dam_type, hit_zone, armour, soaked, sharp=attack.sharp, edge=attack.edge) if(I_DISARM) - M.attack_log += text("\[[time_stamp()]\] Disarmed [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] Has been disarmed by [M.name] ([M.ckey])") + add_attack_logs(H,src,"Disarmed") - msg_admin_attack("[key_name(M)] disarmed [src.name] ([src.ckey])") M.do_attack_animation(src) if(w_uniform) @@ -333,8 +330,7 @@ if(!damage) return - user.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] was attacked by [user.name] ([user.ckey])") + add_attack_logs(user,src,"Melee attacked with fists (miss/block)",admin_notify = FALSE) //No admin notice since this is usually fighting simple animals src.visible_message("[user] has [attack_message] [src]!") user.do_attack_animation(src) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index e5647682fa..1befd9579b 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -65,7 +65,7 @@ emp_act c_hand = r_hand if(c_hand && (stun_amount || agony_amount > 10)) - msg_admin_attack("[src.name] ([src.ckey]) was disarmed by a stun effect") + msg_admin_attack("[key_name(src)] was disarmed by a stun effect") drop_from_inventory(c_hand) if (affected.robotic >= ORGAN_ROBOT) @@ -403,13 +403,7 @@ emp_act src.visible_message("[src] has been hit in the [hit_area] by [O].") if(ismob(O.thrower)) - var/mob/M = O.thrower - var/client/assailant = M.client - if(assailant) - src.attack_log += text("\[[time_stamp()]\] Has been hit with a [O], thrown by [M.name] ([assailant.ckey])") - M.attack_log += text("\[[time_stamp()]\] Hit [src.name] ([src.ckey]) with a thrown [O]") - if(!istype(src,/mob/living/simple_animal/mouse)) - msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [M.name] ([assailant.ckey]) (JMP)") + add_attack_logs(O.thrower,src,"Hit with thrown [O.name]") //If the armor absorbs all of the damage, skip the rest of the calculations var/soaked = get_armor_soak(affecting, "melee", O.armor_penetration) diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 445d06a802..5c45e80c34 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -74,7 +74,7 @@ src << "Not even a [src.species.name] can speak to the dead." return - log_say("[key_name(src)] communed to [key_name(M)]: [text]") + log_say("(COMMUNE to [key_name(M)]) [text]",src) M << "Like lead slabs crashing into the ocean, alien thoughts drop into your mind: [text]" if(istype(M,/mob/living/carbon/human)) @@ -104,7 +104,7 @@ var/msg = sanitize(input("Message:", "Psychic Whisper") as text|null) if(msg) - log_say("PsychicWhisper: [key_name(src)]->[M.key] : [msg]") + log_say("(PWHISPER to [key_name(M)]) [msg]", src) M << "You hear a strange, alien voice in your head... [msg]" src << "You said: \"[msg]\" to [M]" return diff --git a/code/modules/mob/living/carbon/human/stripping.dm b/code/modules/mob/living/carbon/human/stripping.dm index d67eaf76a9..82ca192181 100644 --- a/code/modules/mob/living/carbon/human/stripping.dm +++ b/code/modules/mob/living/carbon/human/stripping.dm @@ -48,8 +48,7 @@ if(istype(A, /obj/item/clothing/accessory/badge) || istype(A, /obj/item/clothing/accessory/medal)) user.visible_message("\The [user] tears off \the [A] from [src]'s [suit.name]!") - attack_log += "\[[time_stamp()]\] Has had \the [A] removed by [user.name] ([user.ckey])" - user.attack_log += "\[[time_stamp()]\] Attempted to remove [name]'s ([ckey]) [A.name]" + add_attack_logs(user,src,"Stripped [A.name] off [suit.name]") A.on_removed(user) suit.accessories -= A update_inv_w_uniform() @@ -81,7 +80,7 @@ return if(stripping) - admin_attack_log(user, src, "Attempted to remove \a [target_slot]", "Target of an attempt to remove \a [target_slot].", "attempted to remove \a [target_slot] from") + add_attack_logs(user,src,"Removed equipment from slot [target_slot]") unEquip(target_slot) else if(user.unEquip(held)) equip_to_slot_if_possible(held, text2num(slot_to_strip), 0, 1, 1) @@ -108,8 +107,7 @@ if (suit.has_sensor >= 2) user << "\The [src]'s suit sensor controls are locked." return - attack_log += text("\[[time_stamp()]\] Has had their sensors toggled by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Attempted to toggle [name]'s ([ckey]) sensors") + add_attack_logs(user,src,"Adjusted suit sensor level") suit.set_sensors(user) // Remove all splints. diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 772af61eb7..42534318bc 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1136,15 +1136,9 @@ default behaviour is: //limit throw range by relative mob size throw_range = round(M.throw_range * min(src.mob_size/M.mob_size, 1)) - var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors var/turf/end_T = get_turf(target) - if(start_T && end_T) - var/start_T_descriptor = "tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]" - var/end_T_descriptor = "tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]" - - M.attack_log += text("\[[time_stamp()]\] Has been thrown by [usr.name] ([usr.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") - usr.attack_log += text("\[[time_stamp()]\] Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") - msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (JMP)") + if(end_T) + add_attack_logs(src,M,"Thrown via grab to [end_T.x],[end_T.y],[end_T.z]") src.drop_from_inventory(item) if(!item || !isturf(item.loc)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 61ec68550d..3d9140dd46 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -271,10 +271,7 @@ var/mob/M = O.thrower var/client/assailant = M.client if(assailant) - src.attack_log += text("\[[time_stamp()]\] Has been hit with a [O], thrown by [M.name] ([assailant.ckey])") - M.attack_log += text("\[[time_stamp()]\] Hit [src.name] ([src.ckey]) with a thrown [O]") - if(!istype(src,/mob/living/simple_animal/mouse)) - msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [M.name] ([assailant.ckey]) (JMP)") + add_attack_logs(M,src,"Hit by thrown [O.name]") // Begin BS12 momentum-transfer code. var/mass = 1.5 @@ -337,8 +334,7 @@ return adjustBruteLoss(damage) - user.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] was attacked by [user.name] ([user.ckey])") + add_attack_logs(user,src,"Generic attack (probably animal)", admin_notify = FALSE) //Usually due to simple_animal attacks src.visible_message("[user] has [attack_message] [src]!") user.do_attack_animation(src) spawn(1) updatehealth() diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index c9ef8ac7b4..d022ef71b8 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -270,7 +270,7 @@ proc/get_radio_key_from_channel(var/channel) src.custom_emote(1, "[pick(speaking.signlang_verb)].") if (speaking.flags & SIGNLANG) - log_say("[name]/[key] : SIGN: [message]") + log_say("(SIGN) [message]", src) return say_signlang(message, pick(speaking.signlang_verb), speaking) //These will contain the main receivers of the message @@ -345,7 +345,10 @@ proc/get_radio_key_from_channel(var/channel) O.hear_talk(src, message, verb, speaking) //Log the message to file - log_say("[name]/[key][whispering ? " (W)" : ""]: [message]") + if(whispering) + log_whisper(message,src) + else + log_say(message, src) return 1 /mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 0089c79e8c..2bdcf1b912 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -390,7 +390,7 @@ var/list/ai_verbs_default = list( return CentCom_announce(input, usr) usr << "Message transmitted." - log_say("[key_name(usr)] has made an IA [using_map.boss_short] announcement: [input]") + log_game("[key_name(usr)] has made an IA [using_map.boss_short] announcement: [input]") emergency_message_cooldown = 1 spawn(300) emergency_message_cooldown = 0 diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 359ee492f2..ed9f253528 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -2,7 +2,7 @@ return ..((sanitize ? sanitize(message) : message), whispering = whispering) /mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) - log_say("[key_name(src)] : [message]") + log_say(message, src) /mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) ..() @@ -64,7 +64,7 @@ //For holopads only. Usable by AI. /mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking) - log_say("[key_name(src)] : [message]") + log_say("(HPAD) [message]",src) message = trim(message) @@ -112,8 +112,6 @@ /mob/living/silicon/ai/proc/holopad_emote(var/message) //This is called when the AI uses the 'me' verb while using a holopad. - log_emote("[key_name(src)] : [message]") - message = trim(message) if (!message) @@ -141,6 +139,8 @@ if(O) O.see_emote(src, message) + log_emote("(HPAD) [message]", src) + else //This shouldn't occur, but better safe then sorry. src << "No holopad connected." return 0 diff --git a/code/modules/mob/living/simple_animal/borer/borer_captive.dm b/code/modules/mob/living/simple_animal/borer/borer_captive.dm index 2290e6ae6a..c34dca00e8 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_captive.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_captive.dm @@ -15,7 +15,7 @@ message = sanitize(message) if (!message) return - log_say("[key_name(src)] : [message]") + log_say(message,src) if (stat == 2) return say_dead(message) diff --git a/code/modules/mob/living/simple_animal/constructs/soulstone.dm b/code/modules/mob/living/simple_animal/constructs/soulstone.dm index fdd1615259..baf99ec0e4 100644 --- a/code/modules/mob/living/simple_animal/constructs/soulstone.dm +++ b/code/modules/mob/living/simple_animal/constructs/soulstone.dm @@ -27,10 +27,7 @@ user << "This being is corrupted by an alien intelligence and cannot be soul trapped." return..() - M.attack_log += text("\[[time_stamp()]\] Has had their soul captured with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to capture the soul of [M.name] ([M.ckey]) (JMP)") - + add_attack_logs(user,M,"Soulstone'd with [src.name]") transfer_soul("VICTIM", M, user) return diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 2aaa23c282..885b2015bb 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -1248,8 +1248,7 @@ var/mob/living/L = target_mob if(prob(melee_miss_chance)) - src.attack_log += text("\[[time_stamp()]\] attacked [L.name] ([L.ckey])") - L.attack_log += text("\[[time_stamp()]\] was attacked by [src.name] ([src.ckey])") + add_attack_logs(src,L,"Animal-attacked (miss)", admin_notify = FALSE) visible_message("[src] misses [L]!") do_attack_animation(src) return L diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index d67ebe0292..f29a396af6 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -3,7 +3,7 @@ //Multikey checks and logging lastKnownIP = client.address computer_id = client.computer_id - log_access("Login: [key_name(src)] from [lastKnownIP ? lastKnownIP : "localhost"]-[computer_id] || BYOND v[client.byond_version]") + log_access_in(client) if(config.log_access) for(var/mob/M in player_list) if(M == src) continue @@ -18,10 +18,10 @@ if(matches) if(M.client) message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)].", 1) - log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)].") + log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)].") else message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(M)] (no longer logged in). ", 1) - log_access("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).") + log_adminwarn("Notice: [key_name(src)] has the same [matches] as [key_name(M)] (no longer logged in).") /mob/Login() diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index bb01c846ca..2a864b78f4 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -1,7 +1,7 @@ /mob/Logout() nanomanager.user_logout(src) // this is used to clean up (remove) this user's Nano UIs player_list -= src - log_access("Logout: [key_name(src)]") + log_access_out(src) if(admin_datums[src.ckey]) if (ticker && ticker.current_state == GAME_STATE_PLAYING) //Only report this stuff if we are currently playing. var/admins_number = admins.len diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 1602c8cb47..58c530d06c 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -265,9 +265,7 @@ state = GRAB_NECK icon_state = "grabbed+1" assailant.set_dir(get_dir(assailant, affecting)) - affecting.attack_log += "\[[time_stamp()]\] Has had their neck grabbed by [assailant.name] ([assailant.ckey])" - assailant.attack_log += "\[[time_stamp()]\] Grabbed the neck of [affecting.name] ([affecting.ckey])" - msg_admin_attack("[key_name(assailant)] grabbed the neck of [key_name(affecting)]") + add_attack_logs(assailant,affecting,"Neck grabbed") hud.icon_state = "kill" hud.name = "kill" affecting.Stun(10) //10 ticks of ensured grab @@ -277,10 +275,7 @@ state = GRAB_KILL assailant.visible_message("[assailant] has tightened [TU.his] grip on [affecting]'s neck!") - affecting.attack_log += "\[[time_stamp()]\] Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])" - assailant.attack_log += "\[[time_stamp()]\] Strangled (kill intent) [affecting.name] ([affecting.ckey])" - msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") - + add_attack_logs(assailant,affecting,"Strangled") affecting.setClickCooldown(10) affecting.AdjustLosebreath(1) affecting.set_dir(WEST) diff --git a/code/modules/mob/mob_grab_specials.dm b/code/modules/mob/mob_grab_specials.dm index a7b82566f2..a497bd0cc5 100644 --- a/code/modules/mob/mob_grab_specials.dm +++ b/code/modules/mob/mob_grab_specials.dm @@ -82,9 +82,7 @@ attacker << "You cannot locate any eyes on [target]!" return - attacker.attack_log += text("\[[time_stamp()]\] Attacked [target.name]'s eyes using grab ([target.ckey])") - target.attack_log += text("\[[time_stamp()]\] Had eyes attacked by [attacker.name]'s grab ([attacker.ckey])") - msg_admin_attack("[key_name(attacker)] attacked [key_name(target)]'s eyes using a grab action.") + add_attack_logs(attacker,target,"Eye gouge using grab") attack.handle_eye_attack(attacker, target) @@ -111,9 +109,7 @@ target.visible_message("[target] [target.species.get_knockout_message(target)]") playsound(attacker.loc, "swing_hit", 25, 1, -1) - attacker.attack_log += text("\[[time_stamp()]\] Headbutted [target.name] ([target.ckey])") - target.attack_log += text("\[[time_stamp()]\] Headbutted by [attacker.name] ([attacker.ckey])") - msg_admin_attack("[key_name(attacker)] has headbutted [key_name(target)]") + add_attack_logs(attacker,target,"Headbutted using grab") attacker.drop_from_inventory(src) src.loc = null diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index bc11798079..6e67cd768c 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -327,9 +327,7 @@ var/list/organ_cache = list() if(owner && vital) if(user) - user.attack_log += "\[[time_stamp()]\] removed a vital organ ([src]) from [owner.name] ([owner.ckey]) (INTENT: [uppertext(user.a_intent)])" - owner.attack_log += "\[[time_stamp()]\] had a vital organ ([src]) removed by [user.name] ([user.ckey]) (INTENT: [uppertext(user.a_intent)])" - msg_admin_attack("[user.name] ([user.ckey]) removed a vital organ ([src]) from [owner.name] ([owner.ckey]) (INTENT: [uppertext(user.a_intent)]) (JMP)") + add_attack_logs(user,owner,"Removed vital organ [src.name]") owner.death() owner.can_defib = 0 diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 7b310ccaa7..d29dc212ac 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -62,17 +62,6 @@ icon_state = "pen" colour = "white" - -/obj/item/weapon/pen/attack(mob/M as mob, mob/user as mob) - if(!ismob(M)) - return - user << "You stab [M] with the pen." -// M << "You feel a tiny prick!" //That's a whole lot of meta! - M.attack_log += text("\[[time_stamp()]\] Has been stabbed with [name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [name] to stab [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey]) Used the [name] to stab [M.name] ([M.ckey]) (JMP)") - return - /* * Reagent pens */ @@ -95,9 +84,9 @@ if(M.can_inject(user,1)) if(reagents.total_volume) if(M.reagents) - var/contained_reagents = reagents.get_reagents() + var/contained = reagents.get_reagents() var/trans = reagents.trans_to_mob(M, 30, CHEM_BLOOD) - admin_inject_log(user, M, src, contained_reagents, trans) + add_attack_logs(user,M,"Injected with [src.name] containing [contained], trasferred [trans] units") /* * Sleepy Pens diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index b1d2aafe8a..0fc3441238 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -379,10 +379,13 @@ if(one_handed_penalty >= 20) to_chat(user, "You struggle to keep \the [src] pointed at the correct position with just one hand!") - if(reflex) - admin_attack_log(user, target, attacker_message = "fired [src] by reflex.", victim_message = "triggered a reflex shot from [src].", admin_message = "shot [target], who triggered gunfire ([src]) by reflex)") + var/target_for_log + if(ismob(target)) + target_for_log = target else - admin_attack_log(usr, attacker_message="Fired [src]", admin_message="fired a gun ([src]) (MODE: [src.mode_name]) [reflex ? "by reflex" : "manually"].") + target_for_log = "[target.name]" + + add_attack_logs(user,target_for_log,"Fired gun [src.name] ([reflex ? "REFLEX" : "MANUAL"])") //update timing user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) @@ -453,10 +456,14 @@ if(!(target && target.loc)) target = targloc //pointblank = 0 + + var/target_for_log + if(ismob(target)) + target_for_log = target + else + target_for_log = "[target.name]" - log_and_message_admins("Fired [src].") - - //admin_attack_log(usr, attacker_message="Fired [src]", admin_message="fired a gun ([src]) (MODE: [src.mode_name]) [reflex ? "by reflex" : "manually"].") + add_attack_logs("Unmanned",target_for_log,"Fired [src.name]") //update timing next_fire_time = world.time + fire_delay diff --git a/code/modules/projectiles/guns/launcher/syringe_gun.dm b/code/modules/projectiles/guns/launcher/syringe_gun.dm index 6b2c52a304..12a107b642 100644 --- a/code/modules/projectiles/guns/launcher/syringe_gun.dm +++ b/code/modules/projectiles/guns/launcher/syringe_gun.dm @@ -52,9 +52,9 @@ var/mob/living/L = hit_atom //unfortuately we don't know where the dart will actually hit, since that's done by the parent. if(L.can_inject() && syringe.reagents) - var/reagent_log = syringe.reagents.get_reagents() - syringe.reagents.trans_to_mob(L, 15, CHEM_BLOOD) - admin_inject_log(thrower, L, src, reagent_log, 15, violent=1) + var/contained = syringe.reagents.get_reagents() + var/trans = syringe.reagents.trans_to_mob(L, 15, CHEM_BLOOD) + add_attack_logs(thrower,L,"Shot with [src.name] containing [contained], trasferred [trans] units") syringe.break_syringe(iscarbon(hit_atom)? hit_atom : null) syringe.update_icon() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 7cf68c5d39..0600125f8a 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -200,17 +200,8 @@ //admin logs if(!no_attack_log) - if(istype(firer, /mob)) - - var/attacker_message = "shot with \a [src.type]" - var/victim_message = "shot with \a [src.type]" - var/admin_message = "shot (\a [src.type])" - - admin_attack_log(firer, target_mob, attacker_message, victim_message, admin_message) - else - if(target_mob) // Sometimes the target_mob gets gibbed or something. - target_mob.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [target_mob]/[target_mob.ckey] with \a [src]" - msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with \a [src] (JMP)") + if(istype(firer, /mob) && istype(target_mob)) + add_attack_logs(firer,target_mob,"Shot with \a [src.type] projectile") //sometimes bullet_act() will want the projectile to continue flying if (result == PROJECTILE_CONTINUE) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index fc89bab93d..b870a55902 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -62,10 +62,7 @@ return 1 var/contained = reagentlist() - target.attack_log += text("\[[time_stamp()]\] Has been splashed with [name] by [user.name] ([user.ckey]). Reagents: [contained]") - user.attack_log += text("\[[time_stamp()]\] Used the [name] to splash [target.name] ([target.key]). Reagents: [contained]") - msg_admin_attack("[user.name] ([user.ckey]) splashed [target.name] ([target.key]) with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") - + add_attack_logs(user,target,"Splashed with [src.name] containing [contained]") user.visible_message("[target] has been splashed with something by [user]!", "You splash the solution onto [target].") reagents.splash(target, reagents.total_volume) return 1 @@ -126,10 +123,7 @@ other_feed_message_finish(user, target) var/contained = reagentlist() - target.attack_log += text("\[[time_stamp()]\] Has been fed [name] by [user.name] ([user.ckey]). Reagents: [contained]") - user.attack_log += text("\[[time_stamp()]\] Fed [name] by [target.name] ([target.ckey]). Reagents: [contained]") - msg_admin_attack("[key_name(user)] fed [key_name(target)] with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") - + add_attack_logs(user,target,"Fed from [src.name] containing [contained]") reagents.trans_to_mob(target, amount_per_transfer_from_this, CHEM_INGEST) feed_sound(user) return 1 diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 33bea945ec..d5a1f0571a 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -88,7 +88,7 @@ var/t = min(amount_per_transfer_from_this, reagent_volumes[reagent_ids[mode]]) M.reagents.add_reagent(reagent_ids[mode], t) reagent_volumes[reagent_ids[mode]] -= t - admin_inject_log(user, M, src, reagent_ids[mode], t) + add_attack_logs(user, M, "Borg injected with [reagent_ids[mode]]") user << "[t] units injected. [reagent_volumes[reagent_ids[mode]]] units remaining." return diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index f15c2faf3f..ee551696cf 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -62,12 +62,8 @@ user.visible_message("[user] tries to squirt something into [target]'s eyes, but fails!", "You transfer [trans] units of the solution.") return - var/mob/living/M = target var/contained = reagentlist() - M.attack_log += text("\[[time_stamp()]\] Has been squirted with [name] by [user.name] ([user.ckey]). Reagents: [contained]") - user.attack_log += text("\[[time_stamp()]\] Used the [name] to squirt [M.name] ([M.key]). Reagents: [contained]") - msg_admin_attack("[user.name] ([user.ckey]) squirted [M.name] ([M.key]) with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") - + add_attack_logs(user,target,"Used [src.name] containing [contained]") trans += reagents.trans_to_mob(target, min(amount_per_transfer_from_this, reagents.total_volume)/2, CHEM_INGEST) //Half injected, half ingested trans += reagents.trans_to_mob(target, min(amount_per_transfer_from_this, reagents.total_volume), CHEM_BLOOD) //I guess it gets into the bloodstream through the eyes or something diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 4e68857d84..18852a52dc 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -105,9 +105,8 @@ user.setClickCooldown(user.get_attack_speed(src)) if(!do_mob(user, M)) return - M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: [reagentlist(src)]") - user.attack_log += text("\[[time_stamp()]\] Fed [src.name] by [M.name] ([M.ckey]) Reagents: [reagentlist(src)]") - msg_admin_attack("[key_name(user)] fed [key_name(M)] with [src.name] Reagents: [reagentlist(src)] (INTENT: [uppertext(user.a_intent)])") + //Do we really care about this + add_attack_logs(user,M,"Fed with [src.name] containing [reagentlist(src)]", admin_notify = FALSE) user.visible_message("[user] feeds [M] [src].") diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index d59982d256..e38d07dcd2 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -59,7 +59,7 @@ if(M.reagents) var/contained = reagentlist() var/trans = reagents.trans_to_mob(M, amount_per_transfer_from_this, CHEM_BLOOD) - admin_inject_log(user, M, src, contained, trans) + add_attack_logs(user,M,"Injected with [src.name] containing [contained], trasferred [trans] units") to_chat(user, "[trans] units injected. [reagents.total_volume] units remaining in \the [src].") return diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index da834d06c3..40d8acc1ae 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -59,9 +59,7 @@ user.visible_message("[user] forces [M] to swallow \the [src].") var/contained = reagentlist() - M.attack_log += text("\[[time_stamp()]\] Has been fed [name] by [key_name(user)] Reagents: [contained]") - user.attack_log += text("\[[time_stamp()]\] Fed [name] to [key_name(M)] Reagents: [contained]") - msg_admin_attack("[key_name_admin(user)] fed [key_name_admin(M)] with [name] Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (JMP)") + add_attack_logs(user,M,"Fed a pill containing [contained]") if(reagents && reagents.total_volume) reagents.trans_to_mob(M, reagents.total_volume, CHEM_INGEST) @@ -80,8 +78,7 @@ return to_chat(user, "You dissolve \the [src] in [target].") - user.attack_log += text("\[[time_stamp()]\] Spiked \a [target] with a pill. Reagents: [reagentlist()]") - msg_admin_attack("[user.name] ([user.ckey]) spiked \a [target] with a pill. Reagents: [reagentlist()] (INTENT: [uppertext(user.a_intent)]) (JMP)") + add_attack_logs(user,null,"Spiked [target.name] with a pill containing [reagentlist()]") reagents.trans_to(target, reagents.total_volume) for(var/mob/O in viewers(2, user)) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 3a4c8a25e1..fea94f8f96 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -216,7 +216,7 @@ if(trans) to_chat(user, "You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units.") if(ismob(target)) - admin_inject_log(user, target, src, contained, trans) + add_attack_logs(user,target,"Injected with [src.name] containing [contained], trasferred [trans] units") else to_chat(user, "The syringe is empty.") if (reagents.total_volume <= 0 && mode == SYRINGE_INJECT) @@ -275,9 +275,7 @@ user.remove_from_mob(src) qdel(src) - user.attack_log += "\[[time_stamp()]\] Attacked [target.name] ([target.ckey]) with \the [src] (INTENT: HARM)." - target.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: HARM)." - msg_admin_attack("[key_name_admin(user)] attacked [key_name_admin(target)] with [src.name] (INTENT: HARM) (JMP)") + add_attack_logs(user,target,"Syringe harmclick") return @@ -293,10 +291,10 @@ var/syringestab_amount_transferred = rand(0, (reagents.total_volume - 5)) //nerfed by popular demand - var/contained_reagents = reagents.get_reagents() + var/contained = reagents.get_reagents() var/trans = reagents.trans_to_mob(target, syringestab_amount_transferred, CHEM_BLOOD) if(isnull(trans)) trans = 0 - admin_inject_log(user, target, src, contained_reagents, trans, violent=1) + add_attack_logs(user,target,"Stabbed with [src.name] containing [contained], trasferred [trans] units") break_syringe(target, user) /obj/item/weapon/reagent_containers/syringe/proc/break_syringe(mob/living/carbon/target, mob/living/carbon/user) diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 228d4296ed..e9b59dd14f 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -130,9 +130,8 @@ for (var/mob/C in viewers(src)) C.show_message("[GM.name] has been placed in the [src] by [user].", 3) qdel(G) - usr.attack_log += text("\[[time_stamp()]\] Has placed [GM.name] ([GM.ckey]) in disposals.") - GM.attack_log += text("\[[time_stamp()]\] Has been placed in disposals by [usr.name] ([usr.ckey])") - msg_admin_attack("[usr] ([usr.ckey]) placed [GM] ([GM.ckey]) in a disposals unit. (JMP)") + + add_attack_logs(user,GM,"Disposals dunked") return if(isrobot(user)) @@ -185,9 +184,7 @@ msg = "[user.name] stuffs [target.name] into the [src]!" user << "You stuff [target.name] into the [src]!" - user.attack_log += text("\[[time_stamp()]\] Has placed [target.name] ([target.ckey]) in disposals.") - target.attack_log += text("\[[time_stamp()]\] Has been placed in disposals by [user.name] ([user.ckey])") - msg_admin_attack("[user] ([user.ckey]) placed [target] ([target.ckey]) in a disposals unit. (JMP)") + add_attack_logs(user,target,"Disposals dunked") else return if (target.client) diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index e1c643b776..f9c14af3a5 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -164,8 +164,8 @@ var/mob/living/carbon/human/D = load D << "You ran over [H]!" visible_message("\The [src] ran over [H]!") + add_attack_logs(D,H,"Ran over with [src.name]") attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey]), driven by [D.name] ([D.ckey])") - msg_admin_attack("[D.name] ([D.ckey]) ran over [H.name] ([H.ckey]). (JMP)") else attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm index 74ef6075fd..42f97676ad 100644 --- a/code/modules/vehicles/train.dm +++ b/code/modules/vehicles/train.dm @@ -56,7 +56,7 @@ if(istype(load, /mob/living/carbon/human)) var/mob/living/D = load D << "You hit [M]!" - msg_admin_attack("[D.name] ([D.ckey]) hit [M.name] ([M.ckey]) with [src]. (JMP)") + add_attack_logs(D,M,"Ran over with [src.name]") //------------------------------------------- diff --git a/code/modules/xenoarcheaology/tools/ano_device_battery.dm b/code/modules/xenoarcheaology/tools/ano_device_battery.dm index 72a6e39980..a7fdae7553 100644 --- a/code/modules/xenoarcheaology/tools/ano_device_battery.dm +++ b/code/modules/xenoarcheaology/tools/ano_device_battery.dm @@ -209,6 +209,4 @@ M.lastattacker = user if(inserted_battery.battery_effect) - user.attack_log += "\[[time_stamp()]\] Tapped [M.name] ([M.ckey]) with [name] (EFFECT: [inserted_battery.battery_effect.name])" - M.attack_log += "\[[time_stamp()]\] Tapped by [user.name] ([user.ckey]) with [name] (EFFECT: [inserted_battery.battery_effect.name])" - msg_admin_attack("[key_name(user)] tapped [key_name(M)] with [name] (EFFECT: [inserted_battery.battery_effect.name])" ) + add_attack_logs(user,M,"Anobattery tap ([inserted_battery.battery_effect.name])") From 7f93f3cca7c8461057fe328e54b144635c85bd91 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sat, 10 Mar 2018 17:17:16 -0500 Subject: [PATCH 011/109] POLARIS: Moves daily logs into being folders rather than files --- code/_helpers/logging.dm | 6 +++++- code/controllers/subsystems/atoms.dm | 4 +--- code/controllers/subsystems/garbage.dm | 3 +-- code/controllers/subsystems/overlays.dm | 4 +--- code/global.dm | 3 +++ code/modules/admin/verbs/getlogs.dm | 7 ++++++- code/modules/error_handler/error_handler.dm | 8 ++++---- code/world.dm | 10 ++++++---- 8 files changed, 27 insertions(+), 18 deletions(-) diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm index 5b7974d800..622739fe4c 100644 --- a/code/_helpers/logging.dm +++ b/code/_helpers/logging.dm @@ -27,7 +27,7 @@ /proc/log_debug(text) if (config.log_debug) - diary << "\[[time_stamp()]]DEBUG: [text][log_end]" + debug_log << "\[[time_stamp()]]DEBUG: [text][log_end]" for(var/client/C in admins) if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs)) @@ -112,6 +112,10 @@ if(config.log_world_output) diary << "\[[time_stamp()]]DD_OUTPUT: [text][log_end]" +/proc/log_error(text) + world.log << text + error_log << "\[[time_stamp()]]RUNTIME: [text][log_end]" + /proc/log_misc(text) diary << "\[[time_stamp()]]MISC: [text][log_end]" diff --git a/code/controllers/subsystems/atoms.dm b/code/controllers/subsystems/atoms.dm index 6b5669878c..5b09b186bb 100644 --- a/code/controllers/subsystems/atoms.dm +++ b/code/controllers/subsystems/atoms.dm @@ -135,9 +135,7 @@ SUBSYSTEM_DEF(atoms) /datum/controller/subsystem/atoms/Shutdown() var/initlog = InitLog() if(initlog) - //text2file(initlog, "[GLOB.log_directory]/initialize.log") - var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") - text2file(initlog, "data/logs/[date_string]-initialize.log") + text2file(initlog, "[log_path]-initialize.log") #undef BAD_INIT_QDEL_BEFORE #undef BAD_INIT_DIDNT_INIT diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm index eff85a3627..b4d43a8d3f 100644 --- a/code/controllers/subsystems/garbage.dm +++ b/code/controllers/subsystems/garbage.dm @@ -81,8 +81,7 @@ SUBSYSTEM_DEF(garbage) dellog += "\tIgnored force: [I.no_respect_force] times" if (I.no_hint) dellog += "\tNo hint: [I.no_hint] times" - var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") - text2file(dellog.Join(), "data/logs/[date_string]-qdel.log") + text2file(dellog.Join(), "[log_path]-qdel.log") /datum/controller/subsystem/garbage/fire() //the fact that this resets its processing each fire (rather then resume where it left off) is intentional. diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm index 052cb96cba..5c8b3531c9 100644 --- a/code/controllers/subsystems/overlays.dm +++ b/code/controllers/subsystems/overlays.dm @@ -31,9 +31,7 @@ var/global/image/appearance_bro = new() // Temporarily super-global because of B /datum/controller/subsystem/overlays/Shutdown() - //text2file(render_stats(stats), "[GLOB.log_directory]/overlay.log") - var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") - text2file(render_stats(stats), "data/logs/[date_string]-overlay.log") + text2file(render_stats(stats), "[log_path]-overlay.log") /datum/controller/subsystem/overlays/Recover() overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches diff --git a/code/global.dm b/code/global.dm index 58836aac39..1f6124602a 100644 --- a/code/global.dm +++ b/code/global.dm @@ -21,7 +21,10 @@ var/global/list/global_map = null // Noises made when hit while typing. var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF") +var/log_path = "data/logs/" //See world.dm for the full calculated path var/diary = null +var/error_log = null +var/debug_log = null var/href_logfile = null // var/station_name = "Northern Star" // var/const/station_orig = "Northern Star" //station_name can't be const due to event prefix/suffix diff --git a/code/modules/admin/verbs/getlogs.dm b/code/modules/admin/verbs/getlogs.dm index eac11fcac0..3f6e4c9e74 100644 --- a/code/modules/admin/verbs/getlogs.dm +++ b/code/modules/admin/verbs/getlogs.dm @@ -85,7 +85,7 @@ set name = "Show Server Log" set desc = "Shows today's server log." - var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")].log" + var/path = "[log_path].log" if( fexists(path) ) src << run( file(path) ) else @@ -99,7 +99,10 @@ set category = "Admin" set name = "Show Server Attack Log" set desc = "Shows today's server attack log." + + to_chat(usr,"This verb doesn't actually do anything.") + /* var/path = "data/logs/[time2text(world.realtime,"YYYY/MM-Month/DD-Day")] Attack.log" if( fexists(path) ) src << run( file(path) ) @@ -109,3 +112,5 @@ usr << run( file(path) ) feedback_add_details("admin_verb","SSAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! return + */ + \ No newline at end of file diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index de71bfc1ca..db3843a8c9 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -8,7 +8,7 @@ var/total_runtimes_skipped = 0 #ifdef DEBUG /world/Error(var/exception/e, var/datum/e_src) if(!istype(e)) // Something threw an unusual exception - log_to_dd("\[[time_stamp()]] Uncaught exception: [e]") + log_error("\[[time_stamp()]] Uncaught exception: [e]") return ..() if(!error_last_seen) // A runtime is occurring too early in start-up initialization return ..() @@ -39,7 +39,7 @@ var/total_runtimes_skipped = 0 var/skipcount = abs(error_cooldown[erroruid]) - 1 error_cooldown[erroruid] = 0 if(skipcount > 0) - log_to_dd("\[[time_stamp()]] Skipped [skipcount] runtimes in [e.file],[e.line].") + log_error("\[[time_stamp()]] Skipped [skipcount] runtimes in [e.file],[e.line].") error_cache.logError(e, skipCount = skipcount) error_last_seen[erroruid] = world.time error_cooldown[erroruid] = cooldown @@ -95,9 +95,9 @@ var/total_runtimes_skipped = 0 desclines += " (This error will now be silenced for [ERROR_SILENCE_TIME / 600] minutes)" // Now to actually output the error info... - log_to_dd("\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]") + log_error("\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]") for(var/line in desclines) - log_to_dd(line) + log_error(line) if(error_cache) error_cache.logError(e, desclines, e_src = e_src) diff --git a/code/world.dm b/code/world.dm index 7e7dc41c55..75815ea30f 100644 --- a/code/world.dm +++ b/code/world.dm @@ -42,10 +42,12 @@ var/global/datum/global_init/init = new () /world/New() world.log << "Map Loading Complete" //logs - var/date_string = time2text(world.realtime, "YYYY/MM-Month/DD-Day") - href_logfile = file("data/logs/[date_string] hrefs.htm") - diary = file("data/logs/[date_string].log") - diary << "[log_end]\n[log_end]\nStarting up. [time2text(world.timeofday, "hh:mm.ss")][log_end]\n---------------------[log_end]" + log_path += time2text(world.realtime, "YYYY/MM-Month/DD-Day/round-hh-mm-ss") + diary = file("[log_path].log") + href_logfile = file("[log_path]-hrefs.htm") + error_log = file("[log_path]-error.log") + debug_log = file("[log_path]-debug.log") + debug_log << "[log_end]\n[log_end]\nStarting up. [time_stamp()][log_end]\n---------------------[log_end]" changelog_hash = md5('html/changelog.html') //used for telling if the changelog has changed recently if(byond_version < RECOMMENDED_VERSION) From ee53848b4fe6f303151f5f66b0bf457f29a64862 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sat, 10 Mar 2018 20:52:12 -0500 Subject: [PATCH 012/109] POLARIS: Move Topic() log to debug_log --- code/world.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/world.dm b/code/world.dm index 75815ea30f..6fb6a1a01a 100644 --- a/code/world.dm +++ b/code/world.dm @@ -144,7 +144,7 @@ var/world_topic_spam_protect_ip = "0.0.0.0" var/world_topic_spam_protect_time = world.timeofday /world/Topic(T, addr, master, key) - diary << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key][log_end]" + debug_log << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key][log_end]" if (T == "ping") var/x = 1 From 102041b2b614a239f02d028c41cb0f3c17141238 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sun, 11 Mar 2018 21:13:53 -0400 Subject: [PATCH 013/109] POLARIS: Log more engine info --- code/modules/mob/new_player/new_player.dm | 1 + code/modules/power/singularity/emitter.dm | 8 +++++--- code/modules/power/singularity/field_generator.dm | 3 +++ .../particle_accelerator/particle_accelerator.dm | 1 + .../particle_accelerator/particle_control.dm | 7 ++++--- code/modules/power/smes.dm | 3 ++- code/modules/power/supermatter/supermatter.dm | 15 +++++++++++---- code/modules/power/tesla/energy_ball.dm | 3 +++ 8 files changed, 30 insertions(+), 11 deletions(-) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index d941a16c40..abbe5c178a 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -345,6 +345,7 @@ var/mob/living/character = create_character(T) //creates the human and transfers vars and mind character = job_master.EquipRank(character, rank, 1) //equips the human UpdateFactionList(character) + log_game("JOINED [key_name(character)] as \"[rank]\"") // AIs don't need a spawnpoint, they must spawn at an empty core if(character.mind.assigned_role == "AI") diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index f4f6579420..827bd9aefd 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -48,7 +48,7 @@ /obj/machinery/power/emitter/Destroy() message_admins("Emitter deleted at ([x],[y],[z] - JMP)",0,1) - log_game("Emitter deleted at ([x],[y],[z])") + log_game("EMITTER([x],[y],[z]) Destroyed/deleted.") investigate_log("deleted at ([x],[y],[z])","singulo") ..() @@ -72,7 +72,7 @@ src.active = 0 user << "You turn off [src]." message_admins("Emitter turned off by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("Emitter turned off by [user.ckey]([user]) in ([x],[y],[z])") + log_game("EMITTER([x],[y],[z]) OFF by [key_name(user)]") investigate_log("turned off by [user.key]","singulo") else src.active = 1 @@ -80,7 +80,7 @@ src.shot_number = 0 src.fire_delay = get_initial_fire_delay() message_admins("Emitter turned on by [key_name(user, user.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("Emitter turned on by [user.ckey]([user]) in ([x],[y],[z])") + log_game("EMITTER([x],[y],[z]) ON by [key_name(user)]") investigate_log("turned on by [user.key]","singulo") update_icon() else @@ -112,11 +112,13 @@ if(!powered) powered = 1 update_icon() + log_game("EMITTER([x],[y],[z]) Regained power and is ON.") investigate_log("regained power and turned on","singulo") else if(powered) powered = 0 update_icon() + log_game("EMITTER([x],[y],[z]) Lost power and was ON.") investigate_log("lost power and turned off","singulo") return diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index a9251e27ee..dc6fd45163 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -90,6 +90,7 @@ field_generator power level display "You turn on the [src.name].", \ "You hear heavy droning") turn_on() + log_game("FIELDGEN([x],[y],[z]) Activated by [key_name(user)]") investigate_log("activated by [user.key].","singulo") src.add_fingerprint(user) @@ -213,6 +214,7 @@ field_generator power level display for(var/mob/M in viewers(src)) M.show_message("\The [src] shuts down!") turn_off() + log_game("FIELDGEN([x],[y],[z]) Lost power and was ON.") investigate_log("ran out of power and deactivated","singulo") src.power = 0 return 0 @@ -338,4 +340,5 @@ field_generator power level display temp = 0 message_admins("A singulo exists and a containment field has failed.",1) investigate_log("has failed whilst a singulo exists.","singulo") + log_game("FIELDGEN([x],[y],[z]) Containment failed while singulo/tesla exists.") O.last_warning = world.time diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm index 80f90fbacc..a5d2a4ac0a 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm @@ -139,6 +139,7 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin ..() if(master && master.active) master.toggle_power() + log_game("PACCEL([x],[y],[z]) Was moved while active and turned off.") investigate_log("was moved whilst active; it powered down.","singulo") /obj/structure/particle_accelerator/ex_act(severity) diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index 0bc4adabcf..bcdd0d5036 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -119,7 +119,7 @@ strength = strength_upper_limit else message_admins("PA Control Computer increased to [strength] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("PA Control Computer increased to [strength] by [usr.ckey]([usr]) in ([x],[y],[z])") + log_game("PACCEL([x],[y],[z]) [key_name(usr)] increased to [strength]") investigate_log("increased to [strength] by [usr.key]","singulo") strength_change() @@ -130,7 +130,7 @@ strength = 0 else message_admins("PA Control Computer decreased to [strength] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("PA Control Computer decreased to [strength] by [usr.ckey]([usr]) in ([x],[y],[z])") + log_game("PACCEL([x],[y],[z]) [key_name(usr)] decreased to [strength]") investigate_log("decreased to [strength] by [usr.key]","singulo") strength_change() @@ -147,6 +147,7 @@ if(src.active) //a part is missing! if( length(connected_parts) < 6 ) + log_game("PACCEL([x],[y],[z]) Failed due to missing parts.") investigate_log("lost a connected part; It powered down.","singulo") toggle_power() return @@ -209,7 +210,7 @@ active = !active investigate_log("turned [active?"ON":"OFF"] by [usr ? usr.key : "outside forces"]","singulo") message_admins("PA Control Computer turned [active ?"ON":"OFF"] by [key_name(usr, usr.client)](?) in ([x],[y],[z] - JMP)",0,1) - log_game("PA Control Computer turned [active ?"ON":"OFF"] by [usr.ckey]([usr]) in ([x],[y],[z])") + log_game("PACCEL([x],[y],[z]) [key_name(usr)] turned [active?"ON":"OFF"].") if(active) update_use_power(2) for(var/obj/structure/particle_accelerator/part in connected_parts) diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index d1189f25fb..e2b37348a9 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -148,6 +148,7 @@ if(output_used < 0.0001) // either from no charge or set to 0 outputting(0) investigate_log("lost power and turned off","singulo") + log_game("SMES([x],[y],[z]) Power depleted.") else if(output_attempt && output_level > 0) outputting = 1 else @@ -374,7 +375,7 @@ output_level = max(0, min(output_level_max, output_level)) // clamp to range investigate_log("input/output; on":"off"] | Input-mode: [input_attempt?"auto":"off"] by [usr.key]","singulo") - + log_game("SMES([x],[y],[z]) [key_name(usr)] changed settings: I:[input_level]([input_attempt]), O:[output_level]([output_attempt])") return 1 diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 3e33f931b8..fac43cab7d 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -94,7 +94,7 @@ /obj/machinery/power/supermatter/proc/explode() message_admins("Supermatter exploded at ([x],[y],[z] - JMP)",0,1) - log_game("Supermatter exploded at ([x],[y],[z])") + log_game("SUPERMATTER([x],[y],[z]) Exploded. Power:[power], Oxygen:[oxygen], Damage:[damage], Integrity:[get_integrity()]") anchored = 1 grav_pulling = 1 exploded = 1 @@ -146,10 +146,12 @@ alert_msg = null if(alert_msg) global_announcer.autosay(alert_msg, "Supermatter Monitor", "Engineering") + log_game("SUPERMATTER([x],[y],[z]) Emergency engineering announcement. Power:[power], Oxygen:[oxygen], Damage:[damage], Integrity:[get_integrity()]") //Public alerts if((damage > emergency_point) && !public_alert) global_announcer.autosay("WARNING: SUPERMATTER CRYSTAL DELAMINATION IMMINENT!", "Supermatter Monitor") public_alert = 1 + log_game("SUPERMATTER([x],[y],[z]) Emergency PUBLIC announcement. Power:[power], Oxygen:[oxygen], Damage:[damage], Integrity:[get_integrity()]") else if(safe_warned && public_alert) global_announcer.autosay(alert_msg, "Supermatter Monitor") public_alert = 0 @@ -277,12 +279,17 @@ return 0 // This stops people from being able to really power up the supermatter // Then bring it inside to explode instantly upon landing on a valid turf. - + var/added_energy + var/added_damage var/proj_damage = Proj.get_structure_damage() if(istype(Proj, /obj/item/projectile/beam)) - power += proj_damage * config_bullet_energy * CHARGING_FACTOR / POWER_FACTOR + added_energy = proj_damage * config_bullet_energy * CHARGING_FACTOR / POWER_FACTOR + power += added_energy else - damage += proj_damage * config_bullet_energy + added_damage = proj_damage * config_bullet_energy + damage += added_damage + if(added_energy || added_damage) + log_game("SUPERMATTER([x],[y],[z]) Hit by \"[Proj.name]\". +[added_energy] Energy, +[added_damage] Damage.") return 0 /obj/machinery/power/supermatter/attack_robot(mob/user as mob) diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index 3e921d78a9..9e55dde97f 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -93,6 +93,7 @@ /obj/singularity/energy_ball/proc/handle_energy() if (energy <= 0) + log_game("TESLA([x],[y],[z]) Collapsed entirely.") investigate_log("collapsed.", I_SINGULO) qdel(src) return TRUE @@ -287,6 +288,8 @@ else if(closest_mob) var/shock_damage = Clamp(round(power/400), 10, 90) + rand(-5, 5) closest_mob.electrocute_act(shock_damage, source, 1, ran_zone()) + log_game("TESLA([source.x],[source.y],[source.z]) Shocked [key_name(closest_mob)] for [shock_damage]dmg.") + message_admins("Tesla zapped [key_name_admin(closest_mob)]!") if(issilicon(closest_mob)) var/mob/living/silicon/S = closest_mob if(stun_mobs) From 32689067ba15bbd023b3b456bd57fbce7fc6e7c3 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Mon, 12 Mar 2018 11:33:58 -0400 Subject: [PATCH 014/109] POLARIS: Readd include_name param on keyname because it's used for other things --- code/_helpers/logging.dm | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm index 622739fe4c..f9b7a6e3ef 100644 --- a/code/_helpers/logging.dm +++ b/code/_helpers/logging.dm @@ -140,7 +140,7 @@ //more or less a logging utility //Always return "Something/(Something)", even if it's an error message. -/proc/key_name(var/whom, var/include_link = null, var/highlight_special_characters = 1) +/proc/key_name(var/whom, var/include_link = FALSE, var/include_name = TRUE, var/highlight_special_characters = TRUE) var/mob/M var/client/C var/key @@ -186,17 +186,18 @@ else . += "INVALID" - var/name = "INVALID" - if(M) - if(M.real_name) - name = M.real_name - else if(M.name) - name = M.name + if(include_name) + var/name = "INVALID" + if(M) + if(M.real_name) + name = M.real_name + else if(M.name) + name = M.name - if(include_link && is_special_character(M) && highlight_special_characters) - name = "[name]" //Orange - - . += "/([name])" + if(include_link && is_special_character(M) && highlight_special_characters) + name = "[name]" //Orange + + . += "/([name])" return . From 2b767b069fd5463bece3f40fce939fcd21b75324 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Mon, 26 Feb 2018 00:34:31 -0500 Subject: [PATCH 015/109] POLARIS: Hide things from lists in VV Like organs from contents. You can look at the organs and internal_organs list on the same page... don't clutter contents. --- .../admin/view_variables/view_variables.dm | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index e624d2df05..cb110d4e86 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -143,7 +143,12 @@ vtext = "\ref[C] - [C] ([C.type])" else if(islist(value)) var/list/L = value - vtext = "/list ([L.len])" + var/removed = 0 + if(varname == "contents") + var/list/original = value + L = original.Copy() //We'll take a copy to manipulate + removed = D.view_variables_filter_contents(L) + vtext = "/list ([L.len]+[removed]H)" if(!(varname in view_variables_dont_expand) && L.len > 0 && L.len < 100) extra = "