From b21bd0c42d2159c15c26b47436ceb613214236c0 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Sun, 16 Aug 2015 14:07:11 -0400 Subject: [PATCH 01/16] Ports fix for #10660 from vg Courtesy of PJB3005 --- code/modules/lighting/__lighting_docs.dm | 2 +- code/modules/lighting/light_source.dm | 39 ++++++++++++++++++++++++ code/modules/lighting/lighting_turf.dm | 4 +++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/code/modules/lighting/__lighting_docs.dm b/code/modules/lighting/__lighting_docs.dm index 6ad0e32cdb..5ac5897eb5 100644 --- a/code/modules/lighting/__lighting_docs.dm +++ b/code/modules/lighting/__lighting_docs.dm @@ -51,7 +51,7 @@ turf: (lighting_turf.dm) - proc/lighting_clear_overlays(): - Delete (manual GC) all light overlays on this turf, used when changing turf to space - proc/lighting_build_overlays(): - - Create lighting overlays for this turf + - Create lighting overlays for this turf. Called by ChangeTurf in case the turf is being changed to use dynamic lighting. atom/movable/lighting_overlay: (lighting_overlay.dm) diff --git a/code/modules/lighting/light_source.dm b/code/modules/lighting/light_source.dm index 73a65f064f..2acddb4d29 100644 --- a/code/modules/lighting/light_source.dm +++ b/code/modules/lighting/light_source.dm @@ -246,6 +246,45 @@ effect_turf.Cut(idx, idx + 1) effect_str.Cut(idx, idx + 1) +//Whoop yet not another copy pasta because speed ~~~~BYOND. +//Calculates and applies lighting for a single turf. This is intended for when a turf switches to +//using dynamic lighting when it was not doing so previously (when constructing a floor on space, for example). +//Assumes the turf is visible and such. +//For the love of god don't call this proc when it's not needed! Lighting artifacts WILL happen! +/datum/light_source/proc/calc_turf(var/turf/T) + var/idx = effect_turf.Find(T) + if(!idx) + return //WHY. + + if(T.lighting_overlay) + #if LIGHTING_FALLOFF == 1 // circular + . = (T.lighting_overlay.x - source_turf.x)**2 + (T.lighting_overlay.y - source_turf.y)**2 + LIGHTING_HEIGHT + #if LIGHTING_LAMBERTIAN == 1 + . = CLAMP01((1 - CLAMP01(sqrt(.) / light_range)) * (1 / (sqrt(. + 1)))) + #else + . = 1 - CLAMP01(sqrt(.) / light_range) + #endif + + #elif LIGHTING_FALLOFF == 2 // square + . = abs(T.lighting_overlay.x - source_turf.x) + abs(T.lighting_overlay.y - source_turf.y) + LIGHTING_HEIGHT + #if LIGHTING_LAMBERTIAN == 1 + . = CLAMP01((1 - CLAMP01(. / light_range)) * (1 / (sqrt(.)**2 + ))) + #else + . = 1 - CLAMP01(. / light_range) + #endif + #endif + . *= light_power + + . = round(., LIGHTING_ROUND_VALUE) + + effect_str[idx] = . + + T.lighting_overlay.update_lumcount( + lum_r * ., + lum_g * ., + lum_b * . + ) + #undef LUM_FALLOFF #undef LUM_DISTANCE #undef LUM_ATTENUATION diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index e261931c41..f8f0a5ab10 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -17,6 +17,10 @@ var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, src) lighting_overlay = O + //Make the light sources recalculate us so the lighting overlay updates immediately + for(var/datum/light_source/L in affecting_lights) + L.calc_turf(src) + /turf/Entered(atom/movable/obj) . = ..() if(obj && obj.opacity) From 917f6f025036fc5f3793b2a95cdef17b3a96ef27 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Mon, 17 Aug 2015 05:45:34 +0100 Subject: [PATCH 02/16] Add Medical Equipment access to Chemists --- code/game/jobs/job/medical.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 0e79223b18..8de924339d 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -107,7 +107,7 @@ supervisors = "the chief medical officer" selection_color = "#ffeef0" access = list(access_medical, access_medical_equip, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics) - minimal_access = list(access_medical, access_chemistry) + minimal_access = list(access_medical, access_medical_equip, access_chemistry) alt_titles = list("Pharmacist") From edebf946d8c59bb82e912ff51a627222c81b09ce Mon Sep 17 00:00:00 2001 From: PsiOmegaDelta Date: Mon, 17 Aug 2015 10:16:39 +0200 Subject: [PATCH 03/16] Harm icon state consistency. All icon states relating to the I_HARM intent now all use the same naming convention. --- code/_onclick/hud/monkey.dm | 10 +++++----- code/_onclick/hud/robot.dm | 2 +- code/setup.dm | 2 +- icons/mob/screen1_Midnight.dmi | Bin 141941 -> 141939 bytes icons/mob/screen1_Orange.dmi | Bin 140369 -> 140367 bytes icons/mob/screen1_White.dmi | Bin 128151 -> 128149 bytes icons/mob/screen1_old.dmi | Bin 114081 -> 114079 bytes 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm index 7314e8692d..a7564246ac 100644 --- a/code/_onclick/hud/monkey.dm +++ b/code/_onclick/hud/monkey.dm @@ -10,7 +10,7 @@ using.name = "act_intent" using.set_dir(SOUTHWEST) using.icon = ui_style - using.icon_state = (mymob.a_intent == I_HURT ? I_HURT : mymob.a_intent) + using.icon_state = mymob.a_intent using.screen_loc = ui_acti using.layer = 20 src.adding += using @@ -23,7 +23,7 @@ ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height()) using = new /obj/screen( src ) - using.name = "help" + using.name = I_HELP using.icon = ico using.screen_loc = ui_acti using.layer = 21 @@ -34,7 +34,7 @@ ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height()) using = new /obj/screen( src ) - using.name = "disarm" + using.name = I_DISARM using.icon = ico using.screen_loc = ui_acti using.layer = 21 @@ -45,7 +45,7 @@ ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2) using = new /obj/screen( src ) - using.name = "grab" + using.name = I_GRAB using.icon = ico using.screen_loc = ui_acti using.layer = 21 @@ -56,7 +56,7 @@ ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2) using = new /obj/screen( src ) - using.name = "harm" + using.name = I_HURT using.icon = ico using.screen_loc = ui_acti using.layer = 21 diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index e5e05aa718..7441ac5609 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -57,7 +57,7 @@ var/obj/screen/robot_inventory using.name = "act_intent" using.set_dir(SOUTHWEST) using.icon = 'icons/mob/screen1_robot.dmi' - using.icon_state = (mymob.a_intent == I_HURT ? I_HURT : mymob.a_intent) + using.icon_state = mymob.a_intent using.screen_loc = ui_acti using.layer = 20 src.adding += using diff --git a/code/setup.dm b/code/setup.dm index 07a53f51f1..635214c490 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -852,7 +852,7 @@ var/list/be_special_flags = list( #define I_HELP "help" #define I_DISARM "disarm" #define I_GRAB "grab" -#define I_HURT "hurt" +#define I_HURT "harm" /* These are used Bump() code for living mobs, in the mob_bump_flag, mob_swap_flags, and mob_push_flags vars to determine whom can bump/swap with whom. diff --git a/icons/mob/screen1_Midnight.dmi b/icons/mob/screen1_Midnight.dmi index 1952b1ea199dfe64c793a6722f6c4dac0d995437..7316c3dcac153efd08f03f391e5f4679a5c9ca95 100644 GIT binary patch delta 789 zcmV+w1M2+s)Clv`2#_Ry-+EM7bVOxyV{&P5bZKvH004NLrI*2S;xG(`&&gAG+vA2^ z5}@scOQ)Tk9@XN0DuZyBL!={rVf+Q<#}E@6^QPM3^$UXFNfj(C2KzThY? z2inds1hef7Lo8*5rH7ycvQVtO+mvp(970k7x`UQoYZdx7QwTB!u}zmF^Q5^F(h4DMc2@l zCTJtld$&1H&E5+v-wRt-q=|=(w(65iT3Sq(Mus{{B{$Y^}Vc#WR3`3LPgFG6cpkL3$ce8f)+~ zTD2FZ^M1#Fh^=Ovz{|w~6qlpx`vCr=Ne|jCov$L(N00o$NB3#)d##Nb!bW;ke*(&i ztcZz3&r;;vlMj~8+u71%gOYxo7k4b~hMshl^y>*NrOJ1!RV3w#+s|S;=sRgsMOGC3 zHf5a-vH5iT&5bX()O(p3(^tjVIAL71X4KI}nzgonE4ny3YdM_l&}-Dr(z0C!x+ zbY>h;I(3gIotCYK5IW9d`;BDG??-gttN(2se}{n^Xp3O6lnl)}psbd7V40oqK(iX; zn-?6r|D1&~0DUxsrZv&WXr5k+$Cn53@cfki2R^JJ|CK-iJOBV707*naRCt{1y?K}$ T)tN4XAOnXW0|B=n0|HeiUEzjc delta 789 zcmV+w1M2+q)Cl#|2#_Ry;d)e9bVOxyV{&P5bZKvH004NLrI*2S;xG(`&*Uk*?Qz2{ z3DEY!rPIz%58YQ_Oe}~8$Ii-1fqnWt(9+OiB)XFe%zTz*S^6bktNX`aPruc}^HcT$ z7;W%srY1i|*x!4h=?``-t^dII#? zjl^UjCd<=gnGFm$y;Cza&8P3nmKK3`V`&i*E}S!*@TF%sYWt8@|(FCXA$-B?x zbd(o)k@ph3K0-Ivwi-H99Khk6$lu=Vz>x=dGOjdLseV zfcO05K(!ztRxZ3iWU*KW0aa^k1ijDk*=KB&*jl0H#WR9~ih?8-I!3`UK_d?tOEut> zSM7!C5O;!q*jm8}P%jo>q#R%0ui$r{M6iAtuu4oHJ@T6z-KW9NwRP?iHqop46Hs2} zWlAJ^mJ;V4f3S4g&Xyk=jK+0Q-if#ye$q7>*JEBv4R)(lBIU~4&tiJfchsiJye#`| z$_E=$^Xce6H$LN1?`7s(Ulmj1gbUSLP)8f>*4D3o_~PiimvFu#v}A+lW#fSIrFlU4 z%s8NY>K;%&En9>bJIQ1FjTFr92lT>M|JyqG4i|1boD90P|O0|B=j0|Hkk1?z>q diff --git a/icons/mob/screen1_Orange.dmi b/icons/mob/screen1_Orange.dmi index 772a62386c974caddea41d8b36582948e34fe7f6..c5824e67908f88a99b09fedf8c6938832f8237c0 100644 GIT binary patch delta 796 zcmV+%1LOSB$OzBK2#_QJT9G9;0!b*5ULb$Kd1Z}Qh}pMEFj}b`OR*5sI2e_nmL+a~ zJW2$y5H~l$C|Aylg?I=?g_AXSu@KP#NM%;F4T&j(;EdFh0~uW=BQ_bIC*xq0gO(ey z5c6<;W`e}(oIeSRE|dd0#6mgf39rxTLOJM(vt!tn?wEmzp0k zL$uAvVH}Jctdz+=@O_E3|fEOh#Hj#6^LN_^SMx$j`vYXC-(ao~}ryar&@ zA_pF6%3{e-^itb5@U&;8Wl*JbHKU!-wBU2)IkuKg(uKx@h72udEu{C1FcIoT_x2>+ z3@#mQEmv5Ao73t@b?e-Qu?c^Q5vr4E3UnUZakScY;8%`%l_{*t=;iyuN4I+UUMa1I zusx-{+g65g822Txj-{Tsrze&^lL*&z$CgW1MezfRyQA+SxpdW(E(W=4m&+bu#`hn~ z!JzM`Y{y|7cgwc1%J*FjCZC-6f=iu80Ij=8wy#IiHmew?%_k>ywWmaJC}gJ0k~FuH zy5exIHHO3GkXfw^-O=qY0jvju$LHTaNXWG46e?@zJh?~dT(n1NksqwGf;w0phSO(! zkJ9J2ao~NEJp&jrgNbAmj2+5qTy`w8f7#KjHs;+6j@^IOK;nT8jc9pp#q+Nx@$~u< a{09_@T^s&`FqDId1BZzN0k??*0>~gND2sjo delta 798 zcmV+(1L6G7$OzHM2#_QJT#+R=0zoQ~ULbz}ow7zO#O&K77_C(9OR*5sI2e_nmZjhR zI4?bjg}Av1M!7;K7UCfo6)0Z zA?D%y%mj(mIe!usT_^-P#6ltTgxBYEp%8lF>=?G|4Lv&>VnuA%n}MNtyQb&&cFljA z-`h2j0a@xT`3Kt${ayGfy>M%C!2i19HV4OlhcQPO%t>ciP(Q#=q@!s zWQJ&)k;6C`A*__iKje2qXMjRWSN2eoqbzj#b&gVU!AgAD%DL}g*=YbqkwI{trkn;~ z)FK4uY0CPNq3ETyZ{TRpO3R>1i8Z60(6r!lsacEdwOE&Gl_6bcWk-DDvBRi+#P)v$t6}(x)|ixE|)#RjPE~| zgF)X>*^a|F?v`z1mFv42Og=gB1(!OH09tpGY+sM2ZB{W(n@djWYEMMtP{>S~C24LY zb;aSZHHO3GkXfw^-O=qY0jvju$LHTaNXWDvl~>l#d2)}^xoD5lB0pGV1$D4I45!cd z9;MH3gWz0~Jp&jt;}gj!7(0~Jxa?SF|FWZ5ZOpqDEz;N5f7U?afDVmld2Yq?uP5>J c`V#yHAnsi@BSmclgNFl$hXVn(hXVr0AdjSd6aWAK diff --git a/icons/mob/screen1_White.dmi b/icons/mob/screen1_White.dmi index 4b0a1a4a0739087dae12073af866bf1466fbdb49..0c852e859ea0fa92efb4590381d4be636088eb1c 100644 GIT binary patch delta 788 zcmV+v1MB>k=?9hR2aqIx^LkWRbVOxyV{&P5bZKvH004NLrI*2Sqc9AH&+ru9_PAs> zkfiM;mrgr7J+!aDIG}(h#%5*HkbU|+q)kYRk=+iLWaj&2Vf~WLHM@WO^Yp?Vo}c1Z zKqItbYqtC~kE6XPZOztfk;PFBqN?rjkFneWTeGXHI4T7iwq|L69Bq*|aQuA>CB& z%egn1dXw2WnZ;2Fk{{Tbt&-JQwiO6;8e4(jNMS0lBbPy7-5==Hb$BY5G7ZX_>ueiT=t;TFc>@HCru&gp?udmY()WmSipq4k9_;d+{OCc$}UdktN4nn%#MEH}t7qa@;NGMlG?cDuCdx%N~b`FI^$0 zZ$9r?_{42H=MYQdNNU|)^1QG)f)U0BifoN~pX;rEWA;)y6(}oFJ4-MkDL`3pp2vt1p#~|^(&YFfvI&6KV{i5e4@`r@aa|?d*6v}8{Hmm zOwjuR$FS`YA?4b0xf7}iP++H2nBt#SkQ;E0#u15yrj^c5?lit;k1r4G;rS{454KKQ S40H4X#WI5;1Ggdr0d?{1j)g7& delta 790 zcmV+x1L^#g=?9nT2aqIx^?FoTbVOxyV{&P5bZKvH004NLrI*ce+At8u&-PQO$+4!z z29jL3WRmIRki3FN*bCAiOYTYz(5LT#1WaOirDS}8ncsi4+Am4h?Edl3(+hieeo9{f ztu&e~+5FcuO?I+&f-TvsND~2aBi!+ib=(14va72!sU=#rWOKhUe2{ULI3XZEyNXZCbh z1#smAZS2T}+M@$=~pc0 zW_gxp{epm|4JaFbXj(eY4w{zEvV*3jbL^mLJsIvLVV2Dvf-d8g>JSekwn4sHK^@A`1K|z)Ns|atuMJk7N!ufTgrl{z z9Gl-;sZ{;W(-I3G?uKh=2w`wm z(|CHgWX$t&%yVjU?3BVhJ?XNKy%4+~d&v4+8rYtrLMc3NCf~P%eEQ4yKYZ+}{ z(}FLR=h&*9q#J?<4Fy`xw~*d5!bE609h@D8l~y|1TB)!BH>cH+>)yFH#vv$1s7~fN z&~1I&6zODnpOm9E7gNvSM)L8VLMX?Y`8mH-S5;s=)&I z;>KrO8eG=39v0cqETwI+WMrGqj{0g~aHwRVOih|wNxkH7t~Z9ml~83^tqeU)?S^&M z#s2>B&o2@(JvxQT8oEyIP`VcFP+H`BtE`~*mM_EU9N(dI{&o($?>RrJb|lN&cbai? z+@Tl#yL(^9-{BKK2MuPD(J;0sYjD}J%=u+Yv&NWrFF1DpSp%5|lV1ZD2$AtjK;)mq N3WI(Fw|)ZwBf9=AeFOji delta 785 zcmV+s1Md8v`v#%=29P8HQIRDz0=g2BTp@p;Q`U%unEjYUqm?RsBNk$sMxzE)-T2Lm z^U{M@h^wn;R4R00A?~74g|Y=F79!aLxh$4_M`Fr&KqK{JPbTNdgiWTW$ut_3pyiub zhk3Ly~Zz_4Av(Yv!DR>XGwc3~*quIc@~UGsnT z_jXMyrR%kx$Og3EZ4GF@+fIkD?OZsXZz67`6N!_Bpxae+KwS?XggXC9@>r;gNL@GrQo6M0zw#^ z)ijXi;6S8SP0HK0|QIc^2v$w5!Zk)g`oH z!6n*`1mSP5=sunwWYR3qGfNW5L3%!{`PF zP+(J8`0VH~&X{Ag7HLX4N!K(%86!pF zIj9!L&p`6o87t{|E2o~lWv2lc%>co9nsOR|(K8U7rzz_jhN5e2U%}CyHI_j&5?e;w z*R1I%3U)KR)rnev4!9`CrYOHsi^B&o2@(y+`GhHFTZap>!?Up|r^NR#`#qEnkMyIle>b{Ou5&>p4HFb|lN&cbai? z+@Tl#yL(^9-{BKK2aV4pqhV}O*5I;bne)q*W{olLUi3&`GyhownFEtu0~ZLP>r7iR PVWhu Date: Mon, 17 Aug 2015 10:31:29 +0100 Subject: [PATCH 04/16] Remove Sabess's custom item from code, it's been replaced with an entry in the new system. --- .../clothing/under/accessories/lockets.dm | 14 +++++++------- icons/obj/clothing/ties.dmi | Bin 11017 -> 9967 bytes 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/modules/clothing/under/accessories/lockets.dm b/code/modules/clothing/under/accessories/lockets.dm index d5fa21c0aa..2aaa6750e5 100644 --- a/code/modules/clothing/under/accessories/lockets.dm +++ b/code/modules/clothing/under/accessories/lockets.dm @@ -10,14 +10,14 @@ var/open var/obj/item/held //Item inside locket. -/obj/item/clothing/accessory/locket/heart - name = "heart-shaped locket" - desc = " A silver, heart-shaped locket. It flips open to reveal two pictures, one of a young red-headed woman and one of a brunette of similar age. Small writing is etched onto the back, reading 'M+L'. Some may regard it as cheesy." - icon_state = "heartlocket" - /obj/item/clothing/accessory/locket/attack_self(mob/user as mob) if(!base_icon) base_icon = icon_state + + if(!("[base_icon]_open" in icon_states(icon))) + user << "\The [src] doesn't seem to open." + return + open = !open user << "You flip \the [src] [open?"open":"closed"]." if(open) @@ -36,11 +36,11 @@ if(istype(O,/obj/item/weapon/paper) || istype(O, /obj/item/weapon/photo)) if(held) - usr << "[src] already has something inside it." + usr << "\The [src] already has something inside it." else usr << "You slip [O] into [src]." user.drop_item() O.loc = src src.held = O return - ..() \ No newline at end of file + ..() diff --git a/icons/obj/clothing/ties.dmi b/icons/obj/clothing/ties.dmi index 357c32e5e5884289d3f583dea9164d3439934122..7ea52eaf5d8f99f4351be54fd961d82e2fa63f20 100644 GIT binary patch literal 9967 zcmb7KRa6|owjEr9ORx|;1cv~@-2%bgCAhmYXmEG8;1*zT83;~rmjrhh++pBN?)`W_ z@8|Ve)zz!Jy1I_kIlFdsq_U#S8+1~1008htPF7MCR`TV!Wy4bf48!gtWWf2&Wz(ZT$%EbaS< z#oA72%7gB8|M*OMckbMM&3jPWrJLYdfXLDbey84utS1OM_fU-;+VER`*LDy*^=qP^ zM7}52#%=?XgLf-~qLFhboqD)E?7JLuAHFUVsr8E`+WG zHMDs?JVt31U%tYZpw*c5tGA>cnP%h|YZqH+@t!g6Q4hOGnTfk-IP~fx_kkAl{!Wz- zb@bDb*yn!B1&*XAw!YiVal7cXRm`~BOITlc|tO>xCoCGA~uiZd1H= z^$O)UQn)P|LIK>thF&@=kU#+7JwQ%UOx-I7lI!cGe$#d)Vrwz3z?uF>ArKMudp0V% z_IZRVouNlfx&gN~s%eS2R<+FCA<T<*|@GwrUENhX6joD|2&4t>W3QcV}nd@@Yz#G&3cl@ z*;;I*T&XF^F$OyaiM#?_#vZV$*c`%A0nEiW%gr-+fQ5=n6cbT@O_F})W zlWfemLiqCg35!I5V^tR-HVbCSpWaeot#hf9ru(#m;)r^lDbXVsn+pS@w^pmXB&2;@ zqWx?Mo!uPxK?xG~KYB7EjngE&S-_(Ny_UFrhy~KX1HxXbqW@M6u(o3Y&BbnpZmrmoFCmSlH5vEOdAbT6~%o>3zWkDbwMuzI5rHJXMg%P*vl${ zG7-G*(ch#H8_9n@1-guNd7ddoL%px|B8z3>Zw0jejpDnBu{JVJ8*8;9TJ);8mH~Ib znKQEkMq4B6fRK0GCIl|s>3x{JHat;fmjSusr5T#`Kb7R@x0pbJY6M0Hp0($P95r%Y zpmznQ>>%kBaq7W^TQ7*fX)11rU03;k6-&yWz&HpXtqitdl^3`aAsQ#0+}fS@>6#o z-M6r69^Kl6YULUzJwK^a2e7{-$mVrKHvZf0Zpw}uLuB(F?q}Bxa^W#}%8_j5%Aa9N z`@v&8V7pp`{i46B9)eDvcVFc3hpyv{q#25f_I~YRe(hb;(2&&@g%Jdz;_EjP)~#e@ zo+g1Cq`T-COG_m2akzoGva(XU;Tsy4<;1tEz44H!o|x;37N_4Uq6LzUFZEmY9h4YIQ~tr^Rppg6hoE-%()|M(x1 z@CX#iV|>X+NU9X;FslPJ%OuO?NH$fZHtyc>g2GXZ6>G@=jCM3zs?uH>xGv|h?cK@CyCk~aI7H&q;}*df6zKHYIu4l$Mo9kdN>KFysC=B z_Lnkt{{kiLK9qD1NO!Vw^_jD$3Qzde9Pnn{EwTKit|&^3FtD3~eFn4O66Q3~LDUb8 zlftWI{5ZfdzD!pv$MvX?pTIH;`R>71_O_kH$AuZgyCOfQTzJUBl2h~Z`r=U%kR9ImSA`PrYQ zD_-a}1JS>@>*#r4U;q{r%~N735!6c_0}er4maN7C?M= zEnDUj-rU>(Qc_ah?mdgQ&0+3Q(%Smj#6p(gqKo5WZ#xhDcveCKP23K@wCQXh{c6~_m4Gj`I)hdiASUW+ zs94&l3B%=+3Rh5j?veKxrg74z$U(Tdpo-~;m&1O7K)KPFTiKtu8Sv~QR%1_MS`R)8q7>_S_C=m(_F_=|?$Ps|d^HqeSp}i6fn= zJF*1~y$76Ryj)(tZ05W-yVI`ks7Cb14bH{YjdQ6e}LFX!NGwQU|5$vTc%_?l$x4K0uuH+gSH;` zQ~y9&fP2qlZ_((cEO46ickoYhYgvQp*u*IOduBxMh9uF|zEM)f?uZ6)&96%Fx0wY8 zU1457;M?w29V19u7L?gNDK)c0b4uonJ5~vwdM8j{=*Ql~b-@>a zKm-TJ&r(uSpL0h!Z}90A4z5UJrLC>43xEE^QLbdEh}al`GNm4^A!Z^NfH#F!kM*;= zf^F|FBOnZPfej6ua`{Ne{PdZw^nG+4p7M{(>{A?v4J|M&rYu1eQp{bs@~@R0jn+<5W9|`2i?uhgK{&1=F?(P z_osCY#BFa>e+6NoTlg#Vo;2=E_z?rLXM+bSzeQB*mt@WTB^~5qO~A+pFRLagmr$=0JV z;_sak40m+|d3XY+revFWA6(Lqs{V@8zAfo6$D0@ER#?gpfyw=?o=S&8Qo=x16D4UN zDnc3u*PIX%8T}%Aq0w4#uRN5krp%%b05yrkaRSl_Ib%(F)lhUaXW2rubY6^GIMvL4C3}Ll4 zy?A{jDLh4mFzhSets51U2@x$zj6Tqa?NYtb@t);t0ip%PvD0b2W~P}*tgd%>*0o+u z2w2Q?n{AS&r1imyjGe5x=7p~tkKSW$*Pv`Xydjm3s3n`LI->49c(u#t$S3KmB4Q!UzY0!RkZcttckIXSaid=Jm5XGS*=8 z1(!np7X}n#Q>stRJ!4g-D4-H0M1WNLTHc;h#)5LhcVir7&c3k|JC;kzlcOztcG<|k ziUb)aPE+KVE<8B0?HKCzD4!XwSMGSjF7mObmkX9Av-dWNbe45@>ik=hCtSq@={zFD zC)81Z&_e{oj){vcu92JW1G1ivmXmoU&CO|9S)`(oW6{KH3)E-Fb>NASWQI%*GvsNj zls4CWm&a@CxOYNXZp2pYCnBykED%e0geVbnxIpUQdOXp6xm|xV`5e?4T0p9#H~{q6 z`4KtrNP9Ww#4c@j505Cgi-LmY=v9dpF)%HjP_ObWAWKA*(|KB-!F+Ka?+x0^Q@*3p z%EJw9_>1oNE;O9QjX! zh13!8FI;u1p~fK80#9auu^2Pzr|>>dxVR*oP7>-6Da^xCnWMw7{klQ1SXKU;0DR&> zA5+s1!ude%53ZnnUmaht^GGQD^bMl@;Amg-mgKdlo=g zSQsoO-JUEbH&2@spTM#OEa|%(Oi{61GWh(3P3ukg13|PrlCE7JTrUgb2*CBhK!RC) z0$DnRaKuf@TW)S~He}y8DY64q>u1q=$GJJwE-oSh0xN{CAAN66;G~5w1xRm`CjdTM zRiegr+_L#_*VG4#MC{rCA9W5;xK9~*%wW!YLJiEroXZ5vO0LQ(^$_Pc$51FPcksKD{!y%Y?&`6MTD)~*8R>1hW3-#7^drwFjCYyMLtQb`8Xju#`#7V7XNQr{56 z;Fla%;S|?_Z?TSx4r67XNK-(rwu{c8G9^huie-rKYYDIE@%Fy!5R+EiWA&JbkY5L& zb=cancW}A`NxAXWZ!91$7s)fG77B^~INNjfpt8RF6Ct$>-_pb7IGR+fR={@ZZY04C zd8zH$puX-hM|(r(*Zc#p4^%C`q~)zx9?YIaL-tW})>A90gpTize%fSCCv#SJhbrvJ zpO*>rX^>-yb~}4`cHM~O#DLBxh#sT5SPb$!O9h0CF<#Iuzt!Uu6#C>~_$gZEUHjzJ z*+#|9asP8>^1&ratM`aqo-SDNPvAf=YVA@9RkL$s7AtXjIWxX&>_9- z-X6Qq{CC|3Kd6Ig1ehe96JxiicliJwI@GI$%<|d^OxqDP^EwG+^P_+wT&pwm z^7*a-j@v|s7jNz`T7D<8sv)>k*2ZS1kL|recfG)i>TlHn0_k8T`sFf}Z`m<26GJRa z>z!YZUgP;$6pN^{-%Wol^rt2o`I43rD>G3na8fMfmlt_EB4_X?@eN_o+_v%MC$eV^ zrwiWH1KUP9FPDZ*yn~YnWh2UO3;B&sIU3~C6ivoW+QZE{!`LHkVZT0khG(A0oucqJ zG>WGvx+v>^D}Jv4#6#N~DJthL}grlpJLMQi?a8MAm6GM*Dr= zffRuFSFb2kk=ESM_1Tul>i|n~*kj3gi3KrOW&Gi06;QLrj?~6kn9!5zST;{q+9880 z^C2e(>UBL)w@+#4%Va{My<4&GDeqGslLDJwN|-x4*?GPyK0Ad^{e{Jr#4uR@WL#t> z9o150sa-cRRfpT@`p{vjqR8icDYZn4!pawJd}4xek!a+cPD|uoq)Cf7^M}Pr19jaO|XL|Hy_2(0!OF^D?gedXA^~KL1sMkOLop8Tpi3W-+b-U(5!xBGA zXgL32MUmzc=`j)({0*CdA>H)yU`+OrTF~XOkK%>3sE(IgWpT{%X&3<7Ao~7j$ix{> z{J|Mg?=L(pCjawYd=84JR;!tI?8b~Xcgf&t-v}23FgE;qD~g${+bKo#bCg8$MiR?C zY0>bjmeaIj4d^zsew2N_$ZeKe5mQBrq@Y0g`E5IA9FQsok!pi={vYjE_-sw_kA{$!W<4)cTkNyBTZ5X6)sR z?^GYo-Q-Yz2tMI|B~_#N!rNzeCq8~bL1ga#K6|H!mCp)oA(^G)0JCK~@v8hxMcw3`0?ZYp5|bPLFxzwrT}vVg#Bp=cC>@@4nHGgx0CCC;2CdUC!iovL zjf55j`xpUQzS28Ue|Z6q>8TqrR!5k!?D;Jf zTRsnB27kq3fTvPua{ld)KS-4e+qMEJ?}Zl`-yBUHb;q0j=1KL!YoSyvtkv;r>U2gf(z@&6=oK5lwIlnCa1oykjkc?E)xec;#!Se@_Wfuz@dHj7sF z%Gb6Z;zJ87d8IXg>T^N0lDGjs{X;lTN^s}v0fE2&ydngq8PlvOGpSGyCn;!u_)GDQ z4<$Qge5e~7=XEZ>3yVJEFBKWc5{OA*GzngJ?_x({|4c&^7&+oK*h%^S zV9x$au)Pg#Sr5>go12S()xL8JP!19yRYMY1{PKzl+(kp*8boDHO=%dh^?`|riy_@W zG=sz#$Hvz7sgsR~DS1r6$;1TR7^k-DR=1+GR2oymf-`^vi5)Srs5=vlm0ST1GelAa zIGVy}=FUfNO-lz?tT8xw8q9WpmpFd0j^X}Gs+2&{8jQrl+H7%Fo{r5VP2U!bGcNW^{=;)97F@R!K z>i(GyOX=r^@;BETAl`^f+h)gP8w8>1`?qAQLvLP|lJ=sBzX_0oj z%(ufY#p`->0U*nGK56y|S$+h&)#k4&V4z4iHf1S{NKz7h2(3^nyW9+?blDlkjd2MG z44Jk9?uYc76BqcWu83k!)>aez8(W@%4x_{Kz*G%^dGKJn(k00>A{@mt&P}%z)72Wizgnr zn!7j;=#zM3J_rzsBT0=rk;50l{986j@)POq_2H~!u}Ua=$B+y{(^^$`?Q*xhdhvOf zDQvl1t>30PmdObKjci(z91aMi1U=n9dP+e@q}`x{@51C zAZ&XJ2@=#^%Dd)EHY9UBBHOO!x)M)+%VQ`Ke9ORU0ek3k5nD% zX@&@;#$8)rB2BN)C@cycclk#`lE#|$=c|*1S03V=z!e_0z z6h6Ok@YhZ$OAhiQ|MgFcuQN0n(6Go?>k#>g!tdn1F5Sr7A1~3p`h>wZcl#qkM#c}a ztM70BZx$bynKd5(K#KkMFTj5o{cRia9$IKhdV2f~T@0fIGHf&8f0_QqHwn~aJaz}X z9FE(Av3vR@&fhcPRNp6FVQV^EE)R?W`gUqNG_iiS-3)czuE<+R-^Xy(BA&mzwmEAn zdY!BD7_Hv>tmK@*8bzJh5l;$vGT1J@R8AfvU_a-5&2~7{>h^%twI0`|{(|kxXFGFI z@Ly(UBZ@L51Ip{F&Kkj9F7?d@q6lCw0VWpef9>FfV-x zc;dBh57Ve>_AliUD~(5p!GMzta7}(Ye6g((mVkv@p15w|dcC^u^!WkOf@O2&_|#hz zN{t!@@8ZAFy*d}(zQE2V;JXWW z5{D-1_j$gjiuS9UPM3SIeV+-DdK?IhisxUl1Qty)M9&^}R_yI$8pPg=t3KN<$5`_! zGPB~DbCv%6ob<{zOQJ=xajJnI?*1G{OxlF`)5?eU3S7^0XhlK^y-{3WD*7xGSO(zN zOSNz6tS@ntmgUAs8PA}%QOqN`=7RNtwo#guZ0SMwzy@!DEX#;s2L$Qc0q2$&8v2X* zfNSm{uZQszR5sTO0wUM$0heZV?JoY(Q~3-?4x~qcus3Pr1@_0)-+bd|)C#K9oAD-* zxSFMWr^&POiWvyHB(cwLrdVy+4jTk5>38s4sFK5Inh7PcEL1_RB!Nlgxg5bpCZbK0 zlEx}C*}@E3dTThpE>kxe@Vl>w9M{xu4>A%9q)$bAChbMEC5t~kX3R49l>iB?Xd!^_ z=|~>qMow*fsOj)>@d*0#v~#I&U_%wwFM{l4IHwQO2W&djhPwI6h=-<-6(hP6xRv|h z{_h&_mnPe53-0<1E=pul)(h6N>i7s(2Y&~@gX%!Rs=Y-ZfougjsLWm!%&FvDu_+|+ zm{*X0(g7cs?|1#xTww3{&<+usppExgsgT=mzPabS1~sHh6rs=papP+)>KG)9^ zqTP2t{!hf~R@b#0ZT)Yzh;$=AkZBqt$(d7e7P9zCns# zqHnk@{EzHwYvkng9kQpCAd^ap^(65{woM>v7KyG8XCg?GA18H`zn zu0eybfWf4DU--EvfT8cVe2+1hcOn+>y;`kfu>Wh@ScMQT5U!2jtqt4hL}F*g`%A_? z^@gLE@L^W06vJ5mFE)ExCoI0HdbY&Fq81ea`cLaw7DV`ffcri=Sojg%-5z-O3RC;1 zzBax9K|WxqWuUXW+Os9xeA~Et5G&@`N9Cw~fsVuHZG1HVji|fN?86XSDL^^`b|?E4 a+t?O8okWM~59~)afSi<~WUaVy@c#f=zm=l^ literal 11017 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 Date: Mon, 17 Aug 2015 10:54:51 +0100 Subject: [PATCH 05/16] fix #10692 --- code/modules/virus2/disease2.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/virus2/disease2.dm b/code/modules/virus2/disease2.dm index 1edfec1280..81a57dd300 100644 --- a/code/modules/virus2/disease2.dm +++ b/code/modules/virus2/disease2.dm @@ -46,7 +46,7 @@ for (var/specie in all_species) var/datum/species/S = all_species[specie] if(!S.virus_immune) - meat += S.name + meat += S if(meat.len) var/num = rand(1,meat.len) for(var/i=0,i Date: Mon, 17 Aug 2015 11:34:26 +0100 Subject: [PATCH 06/16] adds admin logs to cryostorage --- code/game/machinery/cryopod.dm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 337d57df8d..f2bb806153 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -22,6 +22,7 @@ //Used for logging people entering cryosleep and important items they are carrying. var/list/frozen_crew = list() var/list/frozen_items = list() + var/list/_admin_logs = list() // _ so it shows first in VV var/storage_type = "crewmembers" var/storage_name = "Cryogenic Oversight Control" @@ -389,15 +390,18 @@ //TODO: Check objectives/mode, update new targets if this mob is the target, spawn new antags? - //This should guarantee that ghosts don't spawn. - occupant.ckey = null //Make an announcement and log the person entering storage. control_computer.frozen_crew += "[occupant.real_name], [occupant.mind.role_alt_title] - [worldtime2text()]" + control_computer._admin_logs += "[key_name(occupant)] ([occupant.mind.role_alt_title]) at [worldtime2text()]" + log_and_message_admins("[key_name(occupant)] ([occupant.mind.role_alt_title]) entered cryostorage.") announce.autosay("[occupant.real_name], [occupant.mind.role_alt_title], [on_store_message]", "[on_store_name]") visible_message("\The [initial(name)] hums and hisses as it moves [occupant.real_name] into storage.", 3) + //This should guarantee that ghosts don't spawn. + occupant.ckey = null + // Delete the mob. qdel(occupant) set_occupant(null) From 7bdbb7273165a63a62a78b7835c7c9589117deb1 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Mon, 17 Aug 2015 11:51:05 +0100 Subject: [PATCH 07/16] Change all misc research doors and windoors to require one of access_tox or access_robotics, rather than only access_tox or access_research --- maps/exodus-1.dmm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/maps/exodus-1.dmm b/maps/exodus-1.dmm index bcca05b583..3cd7fa5768 100644 --- a/maps/exodus-1.dmm +++ b/maps/exodus-1.dmm @@ -5254,8 +5254,8 @@ "bXb" = (/obj/machinery/air_sensor{frequency = 1430; id_tag = "toxins_mixing_exterior"; output = 63},/turf/simulated/floor/engine/vacuum,/area/rnd/mixing) "bXc" = (/obj/structure/table/standard,/obj/machinery/computer/med_data/laptop,/obj/machinery/atmospherics/unary/vent_pump/on{dir = 4},/turf/simulated/floor{dir = 10; icon_state = "whitered"},/area/medical/patient_b) "bXd" = (/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume{dir = 2; frequency = 1379; id = "tox_airlock_pump"},/obj/machinery/air_sensor{frequency = 1430; id_tag = "toxins_mixing_interior"; output = 63; pixel_x = -8; pixel_y = -18},/turf/simulated/floor/engine,/area/rnd/mixing) -"bXe" = (/obj/machinery/door/window/southright{dir = 1; name = "Test Chamber"; req_access = list(47)},/obj/machinery/door/window/southright{name = "Test Chamber"; req_access = list(47)},/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "misclab"; name = "Test Chamber Blast Doors"; opacity = 0},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) -"bXf" = (/obj/machinery/door/window/southleft{dir = 1; name = "Test Chamber"; req_access = list(47)},/obj/machinery/door/window/southleft{name = "Test Chamber"; req_access = list(47)},/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "misclab"; name = "Test Chamber Blast Doors"; opacity = 0},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) +"bXe" = (/obj/machinery/door/window/southright{dir = 1; name = "Test Chamber"; req_one_access = list(7, 29)},/obj/machinery/door/window/southright{name = "Test Chamber"; req_one_access = list(7, 29)},/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "misclab"; name = "Test Chamber Blast Doors"; opacity = 0},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) +"bXf" = (/obj/machinery/door/window/southleft{dir = 1; name = "Test Chamber"; req_one_access = list(7, 29)},/obj/machinery/door/window/southleft{name = "Test Chamber"; req_one_access = list(7, 29)},/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "misclab"; name = "Test Chamber Blast Doors"; opacity = 0},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) "bXg" = (/turf/simulated/floor{dir = 4; icon_state = "warnwhite"},/area/rnd/mixing) "bXh" = (/obj/machinery/computer/general_air_control{frequency = 1430; name = "Mixing Chamber Monitor"; sensors = list("toxins_mixing_exterior" = "Mixing Chamber - Exterior", "toxins_mixing_interior" = "Mixing Chamber - Interior")},/turf/simulated/floor{dir = 4; icon_state = "warning"},/area/rnd/mixing) "bXi" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 6},/turf/simulated/wall/r_wall,/area/rnd/mixing) @@ -5382,7 +5382,7 @@ "bZz" = (/obj/machinery/door/firedoor,/obj/machinery/door/airlock/maintenance{name = "Medbay Patient Wing Maintenance Access"; req_access = list(5)},/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/plating,/area/medical/patient_wing) "bZA" = (/turf/simulated/wall,/area/medical/patient_c) "bZB" = (/obj/machinery/button/remote/blast_door{id = "misclab"; name = "Test Chamber Blast Doors"; pixel_x = 6; pixel_y = 30; req_access = list(47)},/obj/item/weapon/stool/padded,/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) -"bZC" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "hazard door east"},/obj/machinery/door/airlock/research{name = "Miscellaneous Reseach Room"; req_access = list(7)},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) +"bZC" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "hazard door east"},/obj/machinery/door/airlock/research{name = "Miscellaneous Reseach Room"; req_one_access = list(7, 29)},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) "bZD" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plating,/area/maintenance/research_port) "bZE" = (/obj/machinery/light,/obj/machinery/atmospherics/portables_connector{dir = 1},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) "bZF" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/plating,/area/maintenance/research_port) @@ -5441,7 +5441,7 @@ "caG" = (/obj/structure/table/woodentable,/obj/item/device/flashlight/lamp/green,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/wood,/area/medical/psych) "caH" = (/obj/structure/table/woodentable,/obj/machinery/computer/med_data/laptop,/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 8},/turf/simulated/floor/wood,/area/medical/psych) "caI" = (/turf/simulated/wall,/area/medical/psych) -"caJ" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "hazard door east"},/obj/machinery/door/airlock/research{name = "Miscellaneous Reseach Room"; req_access = list(7)},/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) +"caJ" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "hazard door east"},/obj/machinery/door/airlock/research{name = "Miscellaneous Reseach Room"; req_one_access = list(7, 29)},/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) "caK" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 5},/turf/simulated/floor{icon_state = "dark"},/area/medical/biostorage) "caL" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/camera/network/research{c_tag = "Research Division South"; dir = 1},/turf/simulated/floor{icon_state = "white"},/area/rnd/research) "caM" = (/obj/machinery/atmospherics/pipe/simple/heat_exchanging{dir = 5},/turf/simulated/floor/engine/vacuum,/area/rnd/mixing) @@ -5531,7 +5531,7 @@ "ccs" = (/obj/machinery/power/smes/buildable{charge = 0; RCon_tag = "Substation - Research"},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/obj/structure/cable/green{d2 = 4; icon_state = "0-4"},/turf/simulated/floor/plating,/area/maintenance/substation/research) "cct" = (/obj/structure/table/standard,/obj/item/weapon/storage/box/lights/mixed,/obj/item/device/flashlight,/obj/item/device/flashlight,/obj/machinery/light_switch{dir = 2; name = "light switch "; pixel_x = 0; pixel_y = 22},/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/turf/simulated/floor{icon_state = "dark"},/area/medical/biostorage) "ccu" = (/obj/structure/table/standard,/obj/machinery/computer/med_data/laptop,/obj/machinery/atmospherics/unary/vent_pump/on{dir = 4},/turf/simulated/floor{dir = 9; icon_state = "whitered"},/area/medical/patient_c) -"ccv" = (/obj/machinery/door/airlock/maintenance{name = "Miscellaneous Reseach Maintenance"; req_access = list(7)},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/firedoor,/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/substation/research) +"ccv" = (/obj/machinery/door/airlock/maintenance{name = "Miscellaneous Reseach Maintenance"; req_one_access = list(7, 29)},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/door/firedoor,/obj/structure/disposalpipe/segment,/turf/simulated/floor/plating,/area/maintenance/substation/research) "ccw" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/machinery/atmospherics/pipe/simple/visible/universal{dir = 4},/turf/simulated/floor/plating,/area/maintenance/research_starboard) "ccx" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/pipe/simple/hidden/cyan{dir = 9; icon_state = "intact"; tag = "icon-intact-f (NORTHWEST)"},/turf/simulated/floor/plating,/area/maintenance/research_starboard) "ccy" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/turf/simulated/floor/plating,/area/maintenance/research_starboard) @@ -7381,7 +7381,7 @@ "cLW" = (/obj/structure/grille,/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "SupermatterPort"; layer = 2.7; name = "Reactor Blast Door"; opacity = 0},/obj/structure/window/phoronreinforced,/obj/structure/window/phoronreinforced{tag = "icon-phoronrwindow (EAST)"; icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced{tag = "icon-phoronrwindow (WEST)"; icon_state = "phoronrwindow"; dir = 8},/turf/simulated/floor/plating,/area/engineering/engine_room) "cLX" = (/obj/machinery/door/blast/regular{density = 0; icon_state = "pdoor0"; id = "SupermatterPort"; layer = 2.7; name = "Reactor Blast Door"; opacity = 0},/obj/structure/grille,/obj/structure/window/phoronreinforced,/obj/structure/window/phoronreinforced{tag = "icon-phoronrwindow (EAST)"; icon_state = "phoronrwindow"; dir = 4},/obj/structure/window/phoronreinforced{tag = "icon-phoronrwindow (WEST)"; icon_state = "phoronrwindow"; dir = 8},/turf/simulated/floor/plating,/area/engineering/engine_room) "cLY" = (/obj/structure/grille,/obj/structure/window/reinforced/polarized{dir = 8},/obj/structure/window/reinforced/polarized{dir = 4},/turf/simulated/floor/plating,/area/quartermaster/qm) - + (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa From 439b976272855491060025b129eab49d67229a8c Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Mon, 17 Aug 2015 22:41:19 +0200 Subject: [PATCH 08/16] Admin level doors are now always of the secure variant. Players keep finding ways to surprise. --- code/game/machinery/doors/airlock.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index d604cefff5..000c374598 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1022,6 +1022,9 @@ About the new airlock wires panel: name = "[istext(assembly.glass) ? "[assembly.glass] airlock" : assembly.base_name]" //wires + var/turf/T = get_turf(newloc) + if(T && (T.z in config.admin_levels)) + secured_wires = 1 if (secured_wires) wires = new/datum/wires/airlock/secure(src) else From ef8e3a94a0a9b6fd64cbb1e8b7f29e31507c0cea Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 17 Aug 2015 21:00:22 -0400 Subject: [PATCH 09/16] Fixes antag datum not respecting restricted_jobs depending on config Fixes #10657 --- code/game/antagonist/antagonist_helpers.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm index a578c1bf4f..056fbd1865 100644 --- a/code/game/antagonist/antagonist_helpers.dm +++ b/code/game/antagonist/antagonist_helpers.dm @@ -2,9 +2,9 @@ if(player.current && jobban_isbanned(player.current, bantype)) return 0 if(!ignore_role) - if(player.assigned_role in protected_jobs) + if(player.assigned_role in restricted_jobs) return 0 - if(config.protect_roles_from_antagonist && (player.assigned_role in restricted_jobs)) + if(config.protect_roles_from_antagonist && (player.assigned_role in protected_jobs)) return 0 return 1 From e1f4551693834d7a1a11d0ba981b01d8fda6490f Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 17 Aug 2015 21:04:23 -0400 Subject: [PATCH 10/16] Fixes revs being unspawnable The player has not been spawned yet how can they possibly be a /mob/living/carbon/human? Also fixes spawning revs via traitor panel. --- code/game/antagonist/station/revolutionary.dm | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/code/game/antagonist/station/revolutionary.dm b/code/game/antagonist/station/revolutionary.dm index 59d12b50ad..06819c96ce 100644 --- a/code/game/antagonist/station/revolutionary.dm +++ b/code/game/antagonist/station/revolutionary.dm @@ -135,10 +135,10 @@ datum/antagonist/revolutionary/finalize(var/datum/mind/target) world << text // This is a total redefine because headrevs are greeted differently to subrevs. -/datum/antagonist/revolutionary/add_antagonist(var/datum/mind/player) +/datum/antagonist/revolutionary/add_antagonist(var/datum/mind/player, var/ignore_role) if((player in current_antagonists) || (player in head_revolutionaries)) return 0 - if(!can_become_antag(player)) + if(!can_become_antag(player, ignore_role)) return 0 current_antagonists |= player player.current << "You are a Revolutionary!" @@ -168,11 +168,6 @@ datum/antagonist/revolutionary/finalize(var/datum/mind/target) if(show_message) player.current.visible_message("[player.current] looks like they just remembered their real allegiance!") -/datum/antagonist/revolutionary/can_become_antag(var/datum/mind/player) - return ..() && istype(player) && \ - istype(player.current, /mob/living/carbon/human) && \ - !(player.assigned_role in command_positions) - // Used by RP-rev. /mob/living/carbon/human/proc/convert_to_rev(mob/M as mob in oview(src)) set name = "Convert Bourgeoise" From dadc6e4b7749ce191de99737ca74fd72359ef9fb Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 17 Aug 2015 21:10:24 -0400 Subject: [PATCH 11/16] Adds logging for admin spawning antags --- code/__HELPERS/logging.dm | 6 ++++++ code/datums/mind.dm | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/code/__HELPERS/logging.dm b/code/__HELPERS/logging.dm index d5d0f58685..23119c69ad 100644 --- a/code/__HELPERS/logging.dm +++ b/code/__HELPERS/logging.dm @@ -109,6 +109,12 @@ M = whom C = M.client key = M.key + else if(istype(whom, /datum/mind)) + var/datum/mind/D = whom + key = D.key + M = D.current + if(D.current) + C = D.current.client else if(istype(whom, /datum)) var/datum/D = whom return "*invalid:[D.type]*" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index b8260825c9..99c467825c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -143,7 +143,11 @@ if(href_list["add_antagonist"]) var/datum/antagonist/antag = all_antag_types[href_list["add_antagonist"]] - if(antag) antag.add_antagonist(src, 1, 1, 0, 1, 1) // Ignore equipment and role type for this. + if(antag) + if(antag.add_antagonist(src, 1, 1, 0, 1, 1)) // Ignore equipment and role type for this. + log_admin("[key_name_admin(usr)] made [key_name(src)] into a [antag.role_text].") + else + usr << "[src] could not be made into a [antag.role_text]!" else if(href_list["remove_antagonist"]) var/datum/antagonist/antag = all_antag_types[href_list["remove_antagonist"]] From e84f6932195e23c240bfc57ecf0d60f6c0530aa8 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 17 Aug 2015 21:11:57 -0400 Subject: [PATCH 12/16] Fixes certain antag roles from being unspawnable Fixes antag roles without certain flags from being unspawnable at round start. Also adds more debug messages and feedback --- code/game/antagonist/antagonist.dm | 19 ++++++++++++------- code/game/gamemodes/game_mode.dm | 24 ++++++++++-------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 059a883aad..0bde5791c7 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -59,20 +59,23 @@ /datum/antagonist/proc/get_candidates(var/ghosts_only) candidates = list() // Clear. - candidates = ticker.mode.get_players_for_role(role_type, id) + // Prune restricted status. Broke it up for readability. // Note that this is done before jobs are handed out. - for(var/datum/mind/player in candidates) + for(var/datum/mind/player in ticker.mode.get_players_for_role(role_type, id)) if(ghosts_only && !istype(player.current, /mob/dead)) - candidates -= player + log_debug("[key_name(player)] is not eligible to become a [role_text]: Only ghosts may join as this role!" else if(player.special_role) - candidates -= player + log_debug("[key_name(player)] is not eligible to become a [role_text]: They already have a special role ([player.special_role])!" else if (player in pending_antagonists) - candidates -= player + log_debug("[key_name(player)] is not eligible to become a [role_text]: They have already been selected for this role!" else if(!can_become_antag(player)) - candidates -= player + log_debug("[key_name(player)] is not eligible to become a [role_text]: They are blacklisted for this role!" else if(player_is_antag(player)) - candidates -= player + log_debug("[key_name(player)] is not eligible to become a [role_text]: They are already an antagonist!" + else + candidates += player + return candidates /datum/antagonist/proc/attempt_random_spawn() @@ -108,6 +111,7 @@ return 0 //Grab candidates randomly until we have enough. + candidates = shuffle(candidates) while(candidates.len && pending_antagonists.len < cur_max) var/datum/mind/player = pick(candidates) candidates -= player @@ -118,6 +122,7 @@ /datum/antagonist/proc/draft_antagonist(var/datum/mind/player) //Check if the player can join in this antag role, or if the player has already been given an antag role. if(!can_become_antag(player) || player.special_role) + log_debug("[player.key] was selected for [role_text] by lottery, but is not allowed to be that role.") return 0 pending_antagonists |= player diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 961d3e067b..8c0254829a 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -511,32 +511,26 @@ var/global/list/additional_antag_types = list() if(!antag_template) return candidates - var/roletext // Assemble a list of active players without jobbans. for(var/mob/new_player/player in player_list) if( player.client && player.ready ) - if(!(jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, antag_template.bantype))) - players += player - - // Shuffle the players list so that it becomes ping-independent. - players = shuffle(players) + players += player // Get a list of all the people who want to be the antagonist for this round for(var/mob/new_player/player in players) if(!role || (player.client.prefs.be_special & role)) - log_debug("[player.key] had [roletext] enabled, so we are drafting them.") + log_debug("[player.key] had [antag_id] enabled, so we are drafting them.") candidates += player.mind players -= player // If we don't have enough antags, draft people who voted for the round. if(candidates.len < required_enemies) - for(var/key in round_voters) - for(var/mob/new_player/player in players) - if(player.ckey == key) - log_debug("[player.key] voted for this round, so we are drafting them.") - candidates += player.mind - players -= player - break + for(var/mob/new_player/player in players) + if(player.ckey in round_voters) + log_debug("[player.key] voted for this round, so we are drafting them.") + candidates += player.mind + players -= player + break return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than required_enemies // required_enemies if the number of people with that role set to yes is less than recomended_enemies, @@ -569,12 +563,14 @@ var/global/list/additional_antag_types = list() if(antag) antag_templates |= antag + /* if(antag_templates && antag_templates.len) for(var/datum/antagonist/antag in antag_templates) if(antag.flags & (ANTAG_OVERRIDE_JOB|ANTAG_RANDSPAWN)) continue antag_templates -= antag world << "[antag.role_text_plural] are invalid for additional roundtype antags!" + */ newscaster_announcements = pick(newscaster_standard_feeds) From 3ea5bfb1318b19d5eca8ef0db9883c779fa5b3b2 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 17 Aug 2015 21:12:40 -0400 Subject: [PATCH 13/16] Makes error message print to admins instead of world --- code/game/antagonist/antagonist_create.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/antagonist/antagonist_create.dm b/code/game/antagonist/antagonist_create.dm index 026b1a556c..7d92468721 100644 --- a/code/game/antagonist/antagonist_create.dm +++ b/code/game/antagonist/antagonist_create.dm @@ -86,7 +86,7 @@ code_owner.store_memory("Nuclear Bomb Code: [code]", 0, 0) code_owner.current << "The nuclear authorization code is: [code]" else - world << "Could not spawn nuclear bomb. Contact a developer." + message_admins("Could not spawn nuclear bomb. Contact a developer.") return spawned_nuke = code From f0c8db3d0fc3c4b604c4a4f94e6e2a6e2232127a Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Tue, 18 Aug 2015 02:16:50 +0100 Subject: [PATCH 14/16] Adds settable rank to IRC messages, changes it so non-admins can see who on IRC is messaging them, and adds the name of the original sender to reply PMs --- code/modules/admin/verbs/adminpm.dm | 21 +++++++++++---------- code/modules/client/client procs.dm | 2 +- code/world.dm | 8 ++++++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 26cae206e9..ca2fd11f9c 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -118,30 +118,31 @@ if(X.key != key && X.key != C.key && (X.holder.rights & R_ADMIN|R_MOD|R_MENTOR)) X << "" + create_text_tag("pm_other", "PM:", X) + " [key_name(src, X, 0)] to [key_name(C, X, 0)]: [msg]" -/client/proc/cmd_admin_irc_pm() +/client/proc/cmd_admin_irc_pm(sender) if(prefs.muted & MUTE_ADMINHELP) src << "Error: Private-Message: You are unable to use PM-s (muted)." return - var/msg = input(src,"Message:", "Private message to admins on IRC / 400 character limit") as text|null + var/msg = input(src,"Message:", "Reply private message to [sender] on IRC / 400 character limit") as text|null if(!msg) return sanitize(msg) - if(length(msg) > 400) // TODO: if message length is over 400, divide it up into seperate messages, the message length restriction is based on IRC limitations. Probably easier to do this on the bots ends. - src << "\red Your message was not sent because it was more then 400 characters find your message below for ease of copy/pasting" - src << "\blue [msg]" - return + // Handled on Bot32's end, unsure about other bots +// if(length(msg) > 400) // TODO: if message length is over 400, divide it up into seperate messages, the message length restriction is based on IRC limitations. Probably easier to do this on the bots ends. +// src << "Your message was not sent because it was more then 400 characters find your message below for ease of copy/pasting" +// src << "\blue [msg]" +// return - send2adminirc("PlayerPM from [key_name(src)]: [html_decode(msg)]") + send2adminirc("PlayerPM to [sender] from [key_name(src)]: [html_decode(msg)]") - src << "" + create_text_tag("pm_out_alt", "", src) + " to Admin IRC: [msg]" + src << "" + create_text_tag("pm_out_alt", "", src) + " to IRC-[sender]: [msg]" - log_admin("PM: [key_name(src)]->IRC: [msg]") + log_admin("PM: [key_name(src)]->IRC-[sender]: [msg]") for(var/client/X in admins) if(X == src) continue if(X.holder.rights & R_ADMIN|R_MOD) - X << "" + create_text_tag("pm_other", "PM:", X) + " [key_name(src, X, 0)] to Admin IRC: [msg]" + X << "" + create_text_tag("pm_other", "PM:", X) + " [key_name(src, X, 0)] to IRC-[sender]: [msg]" diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index f9c67496a8..ecbd78b14d 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -52,7 +52,7 @@ if(mute_irc) usr << "" return - cmd_admin_irc_pm() + cmd_admin_irc_pm(href_list["irc_msg"]) return diff --git a/code/world.dm b/code/world.dm index 2b8b0f07f3..34b9107699 100644 --- a/code/world.dm +++ b/code/world.dm @@ -183,8 +183,12 @@ var/world_topic_spam_protect_time = world.timeofday if(!C) return "No client with that name on server" - var/message = "IRC-Admin PM from [C.holder ? "IRC-" + input["sender"] : "Administrator"]: [input["msg"]]" - var/amessage = "IRC-Admin PM from IRC-[input["sender"]] to [key_name(C)] : [input["msg"]]" + var/rank = input["rank"] + if(!rank) + rank = "Admin" + + var/message = "IRC-[rank] PM from IRC-[input["sender"]]: [input["msg"]]" + var/amessage = "IRC-[rank] PM from IRC-[input["sender"]] to [key_name(C)] : [input["msg"]]" C.received_irc_pm = world.time C.irc_admin = input["sender"] From 87da0d4eb52ee07ead92f0a9f04367f9b490340a Mon Sep 17 00:00:00 2001 From: mwerezak Date: Mon, 17 Aug 2015 21:24:59 -0400 Subject: [PATCH 15/16] Fixes missing ), "spam" class --- code/game/antagonist/antagonist.dm | 10 +++++----- code/game/antagonist/antagonist_create.dm | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 0bde5791c7..6e98ce6c35 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -64,15 +64,15 @@ // Note that this is done before jobs are handed out. for(var/datum/mind/player in ticker.mode.get_players_for_role(role_type, id)) if(ghosts_only && !istype(player.current, /mob/dead)) - log_debug("[key_name(player)] is not eligible to become a [role_text]: Only ghosts may join as this role!" + log_debug("[key_name(player)] is not eligible to become a [role_text]: Only ghosts may join as this role!") else if(player.special_role) - log_debug("[key_name(player)] is not eligible to become a [role_text]: They already have a special role ([player.special_role])!" + log_debug("[key_name(player)] is not eligible to become a [role_text]: They already have a special role ([player.special_role])!") else if (player in pending_antagonists) - log_debug("[key_name(player)] is not eligible to become a [role_text]: They have already been selected for this role!" + log_debug("[key_name(player)] is not eligible to become a [role_text]: They have already been selected for this role!") else if(!can_become_antag(player)) - log_debug("[key_name(player)] is not eligible to become a [role_text]: They are blacklisted for this role!" + log_debug("[key_name(player)] is not eligible to become a [role_text]: They are blacklisted for this role!") else if(player_is_antag(player)) - log_debug("[key_name(player)] is not eligible to become a [role_text]: They are already an antagonist!" + log_debug("[key_name(player)] is not eligible to become a [role_text]: They are already an antagonist!") else candidates += player diff --git a/code/game/antagonist/antagonist_create.dm b/code/game/antagonist/antagonist_create.dm index 7d92468721..416a774541 100644 --- a/code/game/antagonist/antagonist_create.dm +++ b/code/game/antagonist/antagonist_create.dm @@ -86,7 +86,7 @@ code_owner.store_memory("Nuclear Bomb Code: [code]", 0, 0) code_owner.current << "The nuclear authorization code is: [code]" else - message_admins("Could not spawn nuclear bomb. Contact a developer.") + message_admins("Could not spawn nuclear bomb. Contact a developer.") return spawned_nuke = code From a8969916576cb53c5beaa29b60cbfbdefe877d40 Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Tue, 18 Aug 2015 11:55:43 -0700 Subject: [PATCH 16/16] Even comments need matching spans for Travis to pass. --- code/modules/admin/verbs/adminpm.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index ca2fd11f9c..61050526d5 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -133,7 +133,7 @@ // Handled on Bot32's end, unsure about other bots // if(length(msg) > 400) // TODO: if message length is over 400, divide it up into seperate messages, the message length restriction is based on IRC limitations. Probably easier to do this on the bots ends. // src << "Your message was not sent because it was more then 400 characters find your message below for ease of copy/pasting" -// src << "\blue [msg]" +// src << "[msg]" // return send2adminirc("PlayerPM to [sender] from [key_name(src)]: [html_decode(msg)]")