From 3df776b082fd5d44ba18a6fdd0ed9ab0cd7218e5 Mon Sep 17 00:00:00 2001 From: Erthilo Date: Sat, 23 Jun 2012 17:36:02 +0100 Subject: [PATCH] TG: - Added a parser to adminhelps. When someone sends an adminhelp it looks through the words for mob names, keys and ckeys. These are then displayed in bold and black with a (?) next to them. Clicking the questionmark will display additional information about the mob. Screenshot: http://www.kamletos.si/Adminhelp%20parser%206.PNG Revision: r3778 Author: baloh.matevz --- code/game/dna.dm | 2 +- code/modules/admin/admin.dm | 34 +++++++++++ code/modules/admin/verbs/adminhelp.dm | 78 ++++++++++++++++++++++++-- icons/mob/mob.dmi | Bin 193213 -> 194561 bytes 4 files changed, 109 insertions(+), 5 deletions(-) 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 0aed007843dfae6b38aa50878fdcd6636f44a431..03310535fc5447e0003d3e03fa2f14165d50009c 100644 GIT binary patch delta 6096 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