diff --git a/code/controllers/Processes/inactivity.dm b/code/controllers/Processes/inactivity.dm
index b1029e0391..2a6cd44d2c 100644
--- a/code/controllers/Processes/inactivity.dm
+++ b/code/controllers/Processes/inactivity.dm
@@ -7,8 +7,30 @@
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))
- log_access("AFK: [key_name(C)]")
- C << "You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected."
- del(C) // Don't qdel, cannot override finalize_qdel behaviour for clients.
+ 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
+
+ if(ishuman(C.mob))
+ var/job
+ var/mob/living/carbon/human/H = C.mob
+ var/datum/data/record/R = find_general_record("name", H.real_name)
+ if(R)
+ job = R.fields["real_rank"]
+ if(!job && H.mind)
+ job = H.mind.assigned_role
+ if(!job && H.job)
+ job = H.job
+ if(job)
+ information = " while [job]."
+
+ else if(issilicon(C.mob))
+ information = " while a silicon."
+
+ var/adminlinks
+ adminlinks = " (JMP|CRYO)"
+
+ log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob)
+
+ qdel(C)
SCHECK
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index d3936ca7c0..d254228795 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -346,8 +346,8 @@
// This function can not be undone; do not call this unless you are sure
// Also make sure there is a valid control computer
-/obj/machinery/cryopod/robot/despawn_occupant()
- var/mob/living/silicon/robot/R = occupant
+/obj/machinery/cryopod/robot/despawn_occupant(var/mob/to_despawn)
+ var/mob/living/silicon/robot/R = to_despawn
if(!istype(R)) return ..()
qdel(R.mmi)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 2532554193..721a959c35 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -101,7 +101,8 @@ var/list/admin_verbs_admin = list(
/client/proc/toggle_attack_logs,
/datum/admins/proc/paralyze_mob,
/client/proc/fixatmos,
- /datum/admins/proc/sendFax
+ /datum/admins/proc/sendFax,
+ /client/proc/despawn_player
)
var/list/admin_verbs_ban = list(
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index c2cf55ab00..81c709f6d8 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1864,6 +1864,17 @@
show_player_panel(M)
+ else if(href_list["cryoplayer"])
+ if(!check_rights(R_ADMIN)) return
+
+ var/mob/M = locate(href_list["cryoplayer"])
+ if(!istype(M))
+ to_chat(usr,"Mob doesn't exist!")
+ return
+
+ var/client/C = usr.client
+ C.despawn_player(M)
+
// player info stuff
if(href_list["add_player_info"])
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 961dbdcdfb..9536f830fb 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -935,3 +935,63 @@ Traitors and the like can also be revived with the previous role mostly intact.
usr << "Random events disabled"
message_admins("Admin [key_name_admin(usr)] has disabled random events.", 1)
feedback_add_details("admin_verb","TRE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+/client/proc/despawn_player(var/mob/M in living_mob_list)
+ set name = "Cryo Player"
+ set category = "Admin"
+ set desc = "Removes a player from the round as if they'd cryo'd."
+ set popup_menu = FALSE
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(!M)
+ return
+
+ var/confirm = alert("Are you sure you want to cryo [M]?","Confirmation","No","Yes")
+ if(confirm == "No")
+ return
+
+ var/list/human_cryopods = list()
+ var/list/robot_cryopods = list()
+
+ for(var/obj/machinery/cryopod/CP in machines)
+ if(!CP.control_computer)
+ continue //Broken pod w/o computer, move on.
+
+ var/listname = "[CP.name] ([CP.x],[CP.y],[CP.z])"
+ if(istype(CP,/obj/machinery/cryopod/robot))
+ robot_cryopods[listname] = CP
+ else
+ human_cryopods[listname] = CP
+
+ //Gotta log this up here before they get ghostized and lose their key or anything.
+ log_and_message_admins("[key_name(src)] admin cryo'd [key_name(M)].")
+ feedback_add_details("admin_verb","ACRYO") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+
+ if(ishuman(M))
+ var/obj/machinery/cryopod/CP = human_cryopods[input(usr,"Select a cryopod to use","Cryopod Choice") as null|anything in human_cryopods]
+ if(!CP)
+ return
+ M.ghostize()
+ CP.despawn_occupant(M)
+ return
+
+ else if(issilicon(M))
+ if(isAI(M))
+ var/mob/living/silicon/ai/ai = M
+ empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(ai.loc)
+ global_announcer.autosay("[ai] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
+ ai.clear_client()
+ return
+ else
+ var/obj/machinery/cryopod/robot/CP = robot_cryopods[input(usr,"Select a cryopod to use","Cryopod Choice") as null|anything in robot_cryopods]
+ if(!CP)
+ return
+ M.ghostize()
+ CP.despawn_occupant(M)
+ return
+
+ else if(isliving(M))
+ M.ghostize()
+ qdel(M) //Bye