diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index e1965cf701e..fc58bd0e81d 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -270,4 +270,53 @@ proc/add_logs(mob/target, mob/user, what_done, var/object=null, var/addition=nul
. = 0
break
if(progress)
- qdel(progbar)
\ No newline at end of file
+ qdel(progbar)
+
+/proc/admin_mob_info(mob/M, mob/user = usr)
+ if(!ismob(M))
+ to_chat(user, "This can only be used on instances of type /mob")
+ return
+
+ var/location_description = ""
+ var/special_role_description = ""
+ var/health_description = ""
+ var/gender_description = ""
+ var/turf/T = get_turf(M)
+
+ //Location
+ if(isturf(T))
+ if(isarea(T.loc))
+ location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z] in area [T.loc])"
+ else
+ location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z])"
+
+ //Job + antagonist
+ if(M.mind)
+ special_role_description = "Role: [M.mind.assigned_role]; Antagonist: [M.mind.special_role]; Has been rev: [(M.mind.has_been_rev)?"Yes":"No"]"
+ else
+ special_role_description = "Role: Mind datum missing Antagonist: Mind datum missing; Has been rev: Mind datum missing;"
+
+ //Health
+ if(isliving(M))
+ var/mob/living/L = M
+ var/status
+ switch(M.stat)
+ if(0) status = "Alive"
+ if(1) status = "Unconscious"
+ if(2) status = "Dead"
+ health_description = "Status = [status]"
+ health_description += "
Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()]"
+ else
+ health_description = "This mob type has no health to speak of."
+
+ //Gener
+ switch(M.gender)
+ if(MALE,FEMALE) gender_description = "[M.gender]"
+ else gender_description = "[M.gender]"
+
+ to_chat(user, "Info about [M.name]: ")
+ to_chat(user, "Mob type = [M.type]; Gender = [gender_description] Damage = [health_description]")
+ to_chat(user, "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];")
+ to_chat(user, "Location = [location_description];")
+ to_chat(user, "[special_role_description]")
+ to_chat(user, "(PM) (PP) (VV) (SM) (FLW) (CA)")
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 869ee83ff9c..8927af5f7be 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -25,6 +25,25 @@
return
var/list/modifiers = params2list(params)
+ if(check_rights(R_ADMIN, 0)) // Admin click shortcuts
+ var/mob/M = A
+ if(!istype(M))
+ M = locate() in A
+ if(modifiers["shift"] && modifiers["ctrl"])
+ client.debug_variables(A)
+ return
+ if(modifiers["ctrl"])
+ if(M)
+ client.holder.show_player_panel(M)
+ else
+ to_chat(src, "No mob was found in the atom you clicked on.")
+ return
+ if(modifiers["shift"] && modifiers["middle"])
+ if(M)
+ admin_mob_info(M)
+ else
+ to_chat(src, "No mob was found in the atom you clicked on.")
+ return
if(modifiers["shift"])
ShiftClickOn(A)
return
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index a7fc809aa88..6dacca13d12 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1565,53 +1565,7 @@
else if(href_list["adminmoreinfo"])
var/mob/M = locate(href_list["adminmoreinfo"])
- if(!ismob(M))
- to_chat(usr, "This can only be used on instances of type /mob")
- return
-
- var/location_description = ""
- var/special_role_description = ""
- var/health_description = ""
- var/gender_description = ""
- var/turf/T = get_turf(M)
-
- //Location
- if(isturf(T))
- if(isarea(T.loc))
- location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z] in area [T.loc])"
- else
- location_description = "([M.loc == T ? "at coordinates " : "in [M.loc] at coordinates "] [T.x], [T.y], [T.z])"
-
- //Job + antagonist
- if(M.mind)
- special_role_description = "Role: [M.mind.assigned_role]; Antagonist: [M.mind.special_role]; Has been rev: [(M.mind.has_been_rev)?"Yes":"No"]"
- else
- special_role_description = "Role: Mind datum missing Antagonist: Mind datum missing; Has been rev: Mind datum missing;"
-
- //Health
- if(isliving(M))
- var/mob/living/L = M
- var/status
- switch(M.stat)
- if(0) status = "Alive"
- if(1) status = "Unconscious"
- if(2) status = "Dead"
- health_description = "Status = [status]"
- health_description += "
Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()]"
- else
- health_description = "This mob type has no health to speak of."
-
- //Gener
- switch(M.gender)
- if(MALE,FEMALE) gender_description = "[M.gender]"
- else gender_description = "[M.gender]"
-
- to_chat(src.owner, "Info about [M.name]: ")
- to_chat(src.owner, "Mob type = [M.type]; Gender = [gender_description] Damage = [health_description]")
- to_chat(src.owner, "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];")
- to_chat(src.owner, "Location = [location_description];")
- to_chat(src.owner, "[special_role_description]")
- to_chat(src.owner, "(PM) (PP) (VV) (SM) (FLW) (CA)")
+ admin_mob_info(M)
else if(href_list["adminspawncookie"])
if(!check_rights(R_ADMIN|R_EVENT)) return
diff --git a/interface/interface.dm b/interface/interface.dm
index f144b225160..cf3419cc1a7 100644
--- a/interface/interface.dm
+++ b/interface/interface.dm
@@ -89,6 +89,11 @@ Admin:
\tF7 = Player Panel
\tF8 = Admin PM
\tF9 = Invisimin
+
+Admin ghost:
+\tCtrl+Click = Player Panel
+\tCtrl+Shift+Click = View Variables
+\tShift+Middle Click = Mob Info
"}
mob.hotkey_help()