diff --git a/code/game/dna.dm b/code/game/dna.dm
index 8aa0f241427..00552d48979 100644
--- a/code/game/dna.dm
+++ b/code/game/dna.dm
@@ -1068,7 +1068,7 @@
if (href_list["uimenuset"] && href_list["uimenusubset"]) // This chunk of code updates selected block / sub-block based on click
var/menuset = text2num(href_list["uimenuset"])
var/menusubset = text2num(href_list["uimenusubset"])
- if ((menuset <= 13) && (menuset >= 1))
+ if ((menuset <= 27) && (menuset >= 1))
src.uniblock = menuset
if ((menusubset <= 3) && (menusubset >= 1))
src.subblock = menusubset
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index a79d4714f81..38fd790d922 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -1422,6 +1422,40 @@ var/global/BSACooldown = 0
else
alert("You cannot perform this action. You must be of a higher administrative rank!")
+ if (href_list["adminmoreinfo"])
+ var/mob/M = locate(href_list["adminmoreinfo"])
+ if(!M)
+ usr << "\blue The mob no longer exists."
+ return
+
+ if(src && src.owner)
+ var/location_description = ""
+ var/special_role_description = ""
+ var/health_description = ""
+ var/turf/T = get_turf(M)
+
+ //Location
+ if(T && isturf(T))
+ if(T.loc && isarea(T.loc))
+ location_description = "([T.x], [T.y], [T.z] in area [T.loc])"
+ else
+ location_description = "([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
+ health_description = "Oxy: [M.oxyloss] - Tox: [M.toxloss] - Fire: [M.fireloss] - Brute: [M.bruteloss] - Clone: [M.cloneloss] - Brain: [M.brainloss]"
+
+ src.owner << "Info about [M.name]: "
+ src.owner << "Mob type = [M.type]; Damage = [health_description]"
+ src.owner << "Name = [M.name]; Real_name = [M.real_name]; Original_name = [M.original_name]; Key = [M.key];"
+ src.owner << "Location = [location_description];"
+ src.owner << "[special_role_description]"
+ src.owner << "(PM) (PP) (VV) (SM) (JMP) (CA)"
if (href_list["adminspawncookie"])
var/mob/M = locate(href_list["adminspawncookie"])
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 896c9e81eaf..f5de70b8df3 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -1,3 +1,8 @@
+
+
+//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
+var/list/adminhelp_ignored_words = list("unknown","the","a","an", "monkey", "alien", "as")
+
/client/verb/adminhelp(msg as text)
set category = "Admin"
set name = "Adminhelp"
@@ -10,23 +15,88 @@
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
if (!msg) return
+ var/original_msg = msg
+
+ //The symbol × (fancy multiplication sign) will be used to mark where to put replacements, so the original message must not contain it.
+ msg = dd_replaceText(msg, "×", "")
+ msg = dd_replaceText(msg, "HOLDERREF", "HOLDER-REF") //HOLDERREF is a key word which gets replaced with the admin's holder ref later on, so it mustn't be in the original message
+ msg = dd_replaceText(msg, "ADMINREF", "ADMIN-REF") //ADMINREF is a key word which gets replaced with the admin's client's ref. So it mustn't be in the original message.
+
+ var/list/msglist = dd_text2list(msg, " ")
+
+ var/list/mob/mobs = list()
+
+ for(var/mob/M in world)
+ mobs += M
+
+ var/list/replacement_value = list() //When a word match is found, the word matched will get replaced with an × (fancy multiplication symbol).
+ //This list will contain a list of values which the × will be replaced with in the same order as indexes in this list.
+ //So if this list has the value list("John","Jane") and msg is, at the end, "This is × and he griffed ×" the text to
+ //display will be "This is John and he griffe Jane". The strings in this list are a bit more complex than 'John' and 'Jane' tho.
+
+ //we will try to locate each word of the message in our lists of names and clients
+ //for each mob that we have found
+ //split the mob's info into a list. "John Arnolds" becomes list("John","Arnolds") so we can iterate through this
+ //for each of the name parts IE. "John", "Arnolds", etc. in the current name.
+ for(var/i = 1; i <= msglist.len; i++)
+ var/word = msglist[i]
+ var/original_word = word
+ word = dd_replaceText(word, ".", "")
+ word = dd_replaceText(word, ",", "")
+ word = dd_replaceText(word, "!", "")
+ word = dd_replaceText(word, "?", "") //Strips some common punctuation characters so the actual word can be better compared.
+ word = dd_replaceText(word, ";", "")
+ word = dd_replaceText(word, ":", "")
+ word = dd_replaceText(word, "(", "")
+ word = dd_replaceText(word, ")", "")
+ if(lowertext(word) in adminhelp_ignored_words)
+ continue
+ for(var/mob/M in mobs)
+ var/list/namelist = dd_text2list("[M.name] [M.real_name] [M.original_name] [M.ckey] [M.key]", " ")
+ var/word_is_match = 0 //Used to break from this mob for loop if a match is found
+ for(var/namepart in namelist)
+ if( lowertext(word) == lowertext(namepart) )
+ msglist[i] = "×"
+ var/description_string = "[original_word] (?)"
+ replacement_value += description_string
+ mobs -= M //If a mob is found then remove it from the list of mobs, so we don't get the same mob reported a million times.
+ word_is_match = 1
+ break
+ if(word_is_match)
+ break //Breaks execution of the mob loop, since a match was already found.
+
+ var/j = 1 //index to the next element in the replacement_value list
+ for(var/i = 1; i <= msglist.len; i++)
+ var/word = msglist[i]
+ if(word == "×")
+ msglist[i] = replacement_value[j]
+ j++
+
+ msg = dd_list2text(msglist, " ")
+
if(mob)
var/ref_mob = "\ref[src.mob]"
for (var/client/X)
if (X.holder)
if(X.sound_adminhelp)
X << 'adminhelp.ogg'
- X << "\blue HELP: [key_name(src, X)] (PP) (VV) (SM) (JMP) (CA): [msg]"
+ var/msg_to_send = "\blue HELP: [key_name(src, X)] (?) (PP) (VV) (SM) (JMP) (CA): [msg]"
+ msg_to_send = dd_replaceText(msg_to_send, "HOLDERREF", "\ref[X.holder]")
+ msg_to_send = dd_replaceText(msg_to_send, "ADMINREF", "\ref[X]")
+ X << msg_to_send
else
var/ref_client = "\ref[src]"
for (var/client/X)
if (X.holder)
if(X.sound_adminhelp)
X << 'adminhelp.ogg'
- X << "\blue HELP: [key_name(src, X)] (VV) (CA): [msg]"
+ var/msg_to_send = "\blue HELP: [key_name(src, X)] (VV) (CA): [msg]"
+ msg_to_send = dd_replaceText(msg_to_send, "HOLDERREF", "\ref[X.holder]")
+ msg_to_send = dd_replaceText(msg_to_send, "ADMINREF", "\ref[X]")
+ X << msg_to_send
- src << "PM to-Admins: [msg]"
- log_admin("HELP: [key_name(src)]: [msg]")
+ src << "PM to-Admins: [original_msg]"
+ log_admin("HELP: [key_name(src)]: [original_msg]")
var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "")
msg = sanitize_simple(msg, replacechars)
if(tension_master)
diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi
index 0aed007843d..03310535fc5 100644
Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ