From 853f108c89aa005e2ed1a391a54ed8fd0cb40736 Mon Sep 17 00:00:00 2001
From: Contrabang <91113370+Contrabang@users.noreply.github.com>
Date: Mon, 22 Apr 2024 20:50:48 -0400
Subject: [PATCH] [SERIOUS] Improves admin tooling for radiation (#24968)
* lets clean some radiation
* changes
* lgtm
---
code/__DEFINES/dcs/signals.dm | 3 +
code/controllers/subsystem/SSradiation.dm | 2 +
code/datums/components/radioactive.dm | 27 ++++++---
code/defines/procs/admin_keyname_procs.dm | 4 ++
code/modules/admin/verbs/debug.dm | 21 +++++++
code/modules/admin/verbs/toggledebugverbs.dm | 1 +
.../buildmode/submodes/antirad_mode.dm | 55 ++++++++++++++++++
icons/misc/buildmode.dmi | Bin 1823 -> 1907 bytes
paradise.dme | 1 +
9 files changed, 107 insertions(+), 7 deletions(-)
create mode 100644 code/modules/buildmode/submodes/antirad_mode.dm
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 585f6c5365f..f10dc5d3334 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -1058,3 +1058,6 @@
// Sent when a mob spawner is attacked directly or via projectile.
#define COMSIG_SPAWNER_SET_TARGET "spawner_set_target"
+
+/// Used by admin-tooling to remove radiation
+#define COMSIG_ADMIN_DECONTAMINATE "admin_decontaminate"
diff --git a/code/controllers/subsystem/SSradiation.dm b/code/controllers/subsystem/SSradiation.dm
index 540e56ce19a..c30f40a1363 100644
--- a/code/controllers/subsystem/SSradiation.dm
+++ b/code/controllers/subsystem/SSradiation.dm
@@ -13,6 +13,8 @@ PROCESSING_SUBSYSTEM_DEF(radiation)
var/rad_cache_update_interval = 5 SECONDS
var/list/turf_rad_cache = list()
var/list/prev_rad_cache = list()
+ /// Lazy list of all radioactive components
+ var/list/all_radiations
/datum/controller/subsystem/processing/radiation/proc/warn(datum/component/radioactive/contamination)
diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm
index 97d0591c4eb..ba240898e34 100644
--- a/code/datums/components/radioactive.dm
+++ b/code/datums/components/radioactive.dm
@@ -13,17 +13,17 @@
var/can_contaminate
/datum/component/radioactive/Initialize(_strength = 0, _source, _half_life = RAD_HALF_LIFE, _can_contaminate = TRUE)
+ if(!istype(parent, /atom))
+ return COMPONENT_INCOMPATIBLE
strength = _strength
source = _source
hl3_release_date = _half_life
can_contaminate = _can_contaminate
- if(istype(parent, /atom))
- RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(rad_examine))
- if(isitem(parent))
- RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(rad_attack))
- RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(rad_attack))
- else
- return COMPONENT_INCOMPATIBLE
+ RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(rad_examine))
+ RegisterSignal(parent, COMSIG_ADMIN_DECONTAMINATE, PROC_REF(admin_decontaminate))
+ if(isitem(parent))
+ RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(rad_attack))
+ RegisterSignal(parent, COMSIG_ITEM_ATTACK_OBJ, PROC_REF(rad_attack))
if(strength > RAD_MINIMUM_CONTAMINATION)
SSradiation.warn(src)
//Let's make er glow
@@ -31,10 +31,12 @@
var/atom/movable/master = parent
master.add_filter("rad_glow", 2, list("type" = "outline", "color" = "#39ff1430", "size" = 2))
addtimer(CALLBACK(src, PROC_REF(glow_loop), master), rand(1, 19)) //Things should look uneven
+ LAZYADD(SSradiation.all_radiations, src)
START_PROCESSING(SSradiation, src)
/datum/component/radioactive/Destroy()
STOP_PROCESSING(SSradiation, src)
+ LAZYREMOVE(SSradiation.all_radiations, src)
var/atom/movable/master = parent
master.remove_filter("rad_glow")
return ..()
@@ -99,6 +101,17 @@
return
strength -= strength / hl3_release_date
+/datum/component/radioactive/proc/admin_decontaminate()
+ SIGNAL_HANDLER
+ . = TRUE
+ if(ismob(parent))
+ var/mob/M = parent
+ M.radiation = 0
+ if(ismob(source))
+ var/mob/M = source
+ M.radiation = 0
+ qdel(src)
+
#undef RAD_AMOUNT_LOW
#undef RAD_AMOUNT_MEDIUM
#undef RAD_AMOUNT_HIGH
diff --git a/code/defines/procs/admin_keyname_procs.dm b/code/defines/procs/admin_keyname_procs.dm
index 255b89dd7f8..166540f7b13 100644
--- a/code/defines/procs/admin_keyname_procs.dm
+++ b/code/defines/procs/admin_keyname_procs.dm
@@ -90,3 +90,7 @@
/proc/log_and_message_admins(message)
log_admin("[key_name(usr)] " + message)
message_admins("[key_name_admin(usr)] " + message)
+
+/proc/log_and_message_admins_no_usr(message)
+ log_admin(message)
+ message_admins(message)
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 6e3753a705c..47529556d96 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -989,3 +989,24 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
vis.set_content(ui_dat.Join(""))
vis.open(FALSE)
+
+/client/proc/cmd_clean_radiation()
+ set name = "Remove All Radiation"
+ set desc = "Remove all radiation in the world."
+ set category = "Debug"
+
+ if(!check_rights(R_DEBUG))
+ return
+
+ if(alert(src, "Are you sure you want to remove all radiation in the world? This may lag the server. Alternatively, use the radiation cleaning buildmode.", "Lag warning", "Yes, I'm sure", "No, I want to live") != "Yes, I'm sure")
+ return
+
+ log_and_message_admins("is decontaminating the world of all radiation. (This may be laggy!)")
+
+ var/counter = 0
+ for(var/datum/component/radioactive/rad as anything in SSradiation.all_radiations)
+ rad.admin_decontaminate()
+ counter++
+ CHECK_TICK
+
+ log_and_message_admins_no_usr("The world has been decontaminated of [counter] radiation components.")
diff --git a/code/modules/admin/verbs/toggledebugverbs.dm b/code/modules/admin/verbs/toggledebugverbs.dm
index 74d8358640c..120a69b924b 100644
--- a/code/modules/admin/verbs/toggledebugverbs.dm
+++ b/code/modules/admin/verbs/toggledebugverbs.dm
@@ -16,6 +16,7 @@ GLOBAL_LIST_INIT(admin_verbs_show_debug_verbs, list(
/client/proc/forceEvent,
/client/proc/admin_redo_space_transitions,
/client/proc/make_turf_space_map,
+ /client/proc/cmd_clean_radiation,
))
// Would be nice to make this a permanent admin pref so we don't need to click it each time
diff --git a/code/modules/buildmode/submodes/antirad_mode.dm b/code/modules/buildmode/submodes/antirad_mode.dm
new file mode 100644
index 00000000000..1ddd9964bb0
--- /dev/null
+++ b/code/modules/buildmode/submodes/antirad_mode.dm
@@ -0,0 +1,55 @@
+/datum/buildmode_mode/clean_radiation
+ key = "rad"
+
+/datum/buildmode_mode/clean_radiation/show_help(mob/user)
+ var/list/messages = list(
+ "***********************************************************",
+ "Left Mouse Button on obj/turf/mob = Remove radiation of selected target.",
+ "Ctrl-Left Mouse Button on screen = Remove all radiation in your sight.",
+ "Right Mouse Button on obj/turf/mob = Deep clean: Remove radiation of all recursive contents of turf.",
+ "Ctrl-Right Mouse Button on screen = Deep clean: Remove radiation of all recursive contents in your sight.",
+ "***********************************************************"
+ )
+ to_chat(user, messages.Join("
"))
+
+/datum/buildmode_mode/clean_radiation/handle_click(mob/user, params, atom/target)
+ var/list/pa = params2list(params)
+ var/deep_clean = pa.Find("right")
+ var/clean_screen = pa.Find("ctrl")
+
+ if(!clean_screen)
+ if(!deep_clean)
+ if(SEND_SIGNAL(target, COMSIG_ADMIN_DECONTAMINATE))
+ to_chat(user, "Decontaminated [target].")
+ log_admin("Build Mode: [key_name(user)] decontaminated radiation at ([target.x],[target.y],[target.z])")
+ return
+
+ var/counter = 0
+ var/turf/T = get_turf(target)
+ counter += SEND_SIGNAL(T, COMSIG_ADMIN_DECONTAMINATE)
+ for(var/atom/movable/cleanable in T)
+ counter += SEND_SIGNAL(cleanable, COMSIG_ADMIN_DECONTAMINATE)
+ CHECK_TICK
+
+ if(isliving(cleanable))
+ var/mob/living/L = cleanable
+ for(var/atom/movable/cleanable2 in L.get_contents())
+ counter += SEND_SIGNAL(cleanable2, COMSIG_ADMIN_DECONTAMINATE)
+ CHECK_TICK
+ to_chat(user, "Decontaminated [counter] atom\s.")
+ log_admin("Build Mode: [key_name(user)] deep-clean decontaminated radiation at ([target.x],[target.y],[target.z])")
+ return
+
+ var/counter = 0
+ for(var/turf/T in range(user.client.view, user))
+ counter += SEND_SIGNAL(T, COMSIG_ADMIN_DECONTAMINATE)
+ for(var/atom/movable/cleanable in T)
+ counter += SEND_SIGNAL(cleanable, COMSIG_ADMIN_DECONTAMINATE)
+ CHECK_TICK
+ if(deep_clean && isliving(cleanable))
+ var/mob/living/L = cleanable
+ for(var/atom/movable/cleanable2 in L.get_contents())
+ counter += SEND_SIGNAL(cleanable2, COMSIG_ADMIN_DECONTAMINATE)
+ CHECK_TICK
+ to_chat(user, "Decontaminated [counter] atom\s.")
+ log_admin("Build Mode: [key_name(user)] [deep_clean ? "deep-clean " : ""]decontaminated their screen of radiation at ([target.x],[target.y],[target.z])")
diff --git a/icons/misc/buildmode.dmi b/icons/misc/buildmode.dmi
index 0520a9ef005cfae042b0dfbd9ba686e3b57795b3..663d4546caf3283ae775209cd1b29df950182a85 100644
GIT binary patch
literal 1907
zcmV-(2aNcMP)
zCLii?CdI{r!)E>h*@LY9QL7HhvBq;G8~Yt<(3Wkau*_wfMFxTLK}ygS6glcaV${@{
ztWy|`=jR}$gYt?+zdG-af!E8qeD$+vI`jx#Rs4}$$l3(lQgKVbGiH~72dFS5Zgd<{
zva-+7agv9J))zTeyVLgbv)^nKDEfWfmp}jj1`tU^K~!jg?V3xHhJIB
z<@H-~yr0&~>n$(%dOxj~*H5cBet$o$m)9?UZTs=hpYMv+w*7vlHGpNkyndEf{Nr8G
z0PXiv4Q5>xkah%{IB*0d?MGC7Kh>IrMLkNO%n1TMcU30{d<@12bU5EmA}~RzIRrYM
zZ>JEbD9tP`)5D;|ZiKhI-zC^J4_0;$$TG1u&YB=m7GL3nyq3J5_
z#2~o?&Undth{owz{S~a^Z1X$azCZmRe%1$9>x1a$$MiAtYni>|ett+7GPjobOYY}K
zbUcCvUc2~-<_v|_K+eJwNIyTK4+M@buD;Gw82WZUWrD=d59lL-3y_ALz&RrK#}R1%
zOiuj#fIbjVcnE=gQXufpgW5qG>h;Ev&;=VjX~2Q&bFQ*sER
zNB|q2;lBJVO8tCa<7`rF9VEdXgOqT|{d`}e(mb`qtctTJjnR_(`Mxd_)Lh7t`}w{u
z66hq8DK+pb60B=F;)X5~2p589J6=qKJqE(h_cacmCQ?EWouJDB`qH7&PyKvf7xO?8
z!0I5t>;$Qw@9V-^loPn1VJb_4-Ou-RmtZyM>motw=Ld9;05Ak%7NvfEK$i%rdddC#
zh%OLR^^*Jf5#5f#fgttsLpmG-UCE_f(e(707<|?TJ@Y%=zMuU-uVBgF|A6(umsEc<
z`v;fxXxFi!RrIdmd4X-bJ(Dv(f1$$#L4g%s)%&C+_wyHsAk+`x^Q_HIkhtLs{h@#W
zqMq2;4l+UF=dZ+s5wJ=~>Irk1!1-nXGTi>2g9i}LaBc>BS7A=Zz!?9DVioFr6ip;1
zNc=qAQ}@bw0)J0&f?0Qt^QNBAy+{ZMfePv1qqOg5m-B#FRD1^GX#Ejp2@wcF=i^`%
z1l%wWRpwz-DzIP9H(qb6b`_u2H`n-9JSEdj7$W&+?FTqP*PNbD4<(3_|3
zJo_T;?x5a%&yj%cIy%lUYtXi7Im=|FPg5xDFL0%gc2XIr#NaSuE&ycjB5@sN-7nxP
zeQoKU+AWzy_1=X00N^J?ufmEN&E^C+Aj92;(ax?R_bhuAqRLbUf(^~E`v*pMTOlI|
z&M$b`0s-K-F0Q7W#NrO9jNt6*d0d<9=F@r4>@*L~jyTf{KnUWACiCDX0fhP?#?W8j
z#C~!^2LMD6c|m(?_5Fhr`tMl7{TsWG1n`WjC~Ni=pY_3v`rx#E&wuc={s!xVFCCqo
z|5+albz9KaS^DeZ^Pr`v`>yCAt1k6}ip~(oysEw9rO8t0`u;$su^?*fH(T;q*6zO{
z1)#v7yBsA5&a_(buoaX9dOJe^TS5T#NI<4T%NPKR#~>pxmGf0=Prny~O%PbR<6w*D
zKamH(&b$16$b;=p9@q{6r9jI~_hZr~pa~@E0fMocu8!CZ)=ea=DEutqnO`Moz;3?(-<(C5J$h^{!c4{@D-h62L11vRl}5c+_DtY+rMd+92yz0_
zfa#tQY=Z>(2x!E#K#7=uQu{0es!Gjef-(^nZdbeStr6_A3RHbR`6dD9g&tpR&l23y
z{|8s`Ss(Pw?{xd#J>l-rMZA51UXX5Ipy%&zU!a$Xw=dAk#QOyN3k1~rEv<$R5b&=|
z#J=g{1pF%#y1ZZf1Oa+W^hU+*`%?t6^ZOBFK#$ycv*?fqid+voMv#n{I=h=U5z`1(
zZ$+mOP{H$o2+(-aP7@?Cfafw<8Q-p$l?S{O*`j-Xg24D&4l~!HuRs73V?Yy#HYdN*
tTJ$i%hj$e{e}DS|)2-ud^E=zV{|Ava6)_@kq^tk{002ovPDHLkV1jZ?q_zM6
literal 1823
zcmV+)2jKXLP)005u_0{{R3dEt5<0000XP)t-s1u_!`
zArAvp9R)iU3tc4uP#FM77iP==1u_!_C=LZO6J4Slw*UYD0d!JMQvg8b*k%9#0N;94
zSad{Xb7OL8aCB*JZU6vyoSl=w3c@fDM9;}r1igz@4_>^8MS8HmAZfFj#iU!4*y7(?
z^&p5XrnenCY^PKp~E
zHQ`L5^POIEc5>3f^G?1fOA3wwP59u+0ItE*eIzqPbzejwJ(i=KQZ=$FL5(tl!ro?s
z#-JUwqnuXOXQ=+0^LiWkyprnse-ZBu9mt_6eppUuOayMQx)|xlRl6;e$#Lk78DL6T2&h%fMPJb<1)^DYkZ@yEo<74@9O3C{aPKryzlDe_33w;k3WBVM-5)<_W4Ewq8GiqeyHE!*LT#2TDQ+@jc#2H
zvJQl{I_Mp3dB?2V=d}hAp7b7}aVH4n+|?Wq#u&~KLOS0+MCg(-&k#a6-#gdORCi-&k$>$8!qGgG)ybVCJeY@a_~!`a_0JHNn1X$Tkk&zYy<49l
zOo&je*d|V_ON47&Z(Lllxr)hZFvO?d;Ts@|O#s!tdSeH{}j-1qdqU`3ubOOM;R
z4}bWSKP>)kPIsAuNiVIxo6;MZk}_>+{oRaiR~uRiFzTiCcQd*p4D=gxcSYbx+7oG9nXde>c`!qfAHM1!#Xap%LkqCuc=m2(`Z(YZ`4M
zrLHC{G1UHUtVw|keKqRUC~JQ=*4u>DJkxx{~v|@*X27p}Ic!h5C@#?a%
z+Ju_s_&1m+UZER(o-kD0@GlTStRY&TC&WY)Ye=KN03m`8RhkT1ta?tzu+d{e=i)0O
zAzd8kCysKXEk8m}TNQae@P~7P*NLAXJg5nW1k7qmO(B|iq+J3NuDR+BV#LvevQP04
za0x3DO4RKxVJKlJ21^K00<=rmXNsl5MnCZ#AxOw|xF_VOg>*{00Ddu4nL<&ZX_rPV
zJVfJgCx-ne;tN!}0M9>=cTV6rCW$DH^8Q{gya4GHB~t<a()QV8o&KC`-Py00??Q~vM{(dQui>Z{&|
zKfG<{Mkk!rpTQsg-01(JKQyJcm8uxscDkG?pJGG9Qst|9S+NfjH2Db6e69ZoS#RS(gi3sn)Pcl3gY*%`3H
zqN%lXicoifW1ofxy2KE1K8Avb-j@4x5bu9pt|=6uwIY-osu%0BwfcJvknh#Tc}Y{y
zo|%Udv;2-G-K&jvYsHuyxvvdEn>*!9i0O!<&YOblz8Kb*dAdcYx*l%L7fka|JJ{qW
z4+w)DExGFlgx*F!xlc$#j5&8rPly!ck~x~t(aj2;teG%%j#95n6Skw;60$~0r`-F(
zHKt4I?JL4|RGEkqyoxCr<8lmT4g%(w=y^EG6d@)fp8AI}2iLNi=y^EG6d83i`TI7Q
z`h&$|zHovdl|>^nIHINQhN8j=#%rDVP5!J=VW+6%)WG{h`#o4}W;YAKtcew=d8h
zw?ATc!PXC+^oRWg@A|>+f_MF3cfq?mr=GA|Jw}?h*4%rt*9fU0L9HW`S7^s2#OxAM
zL-XMKHlF)9-j}N9dHItXvPGCWS386lTS