From 281c72fbccb71625b3e3cb39e7296b9978dbd902 Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Wed, 5 May 2021 02:43:05 +0100 Subject: [PATCH] Who & Adminwho improvements (#15855) * Who & Adminwho improvements * Mochi tweaks * Sabre tweaks --- code/__HELPERS/text.dm | 19 ++++ code/_globalvars/lists/misc.dm | 3 + code/controllers/configuration.dm | 31 +++++++ code/game/verbs/who.dm | 149 ++++++++++++++++++++---------- code/game/world.dm | 1 + code/modules/admin/topic.dm | 2 + config/example/rank_colours.txt | 11 +++ 7 files changed, 168 insertions(+), 48 deletions(-) create mode 100644 config/example/rank_colours.txt diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index c72149c7a20..68acde69228 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -652,3 +652,22 @@ // return the split html object to the caller return s + +/** + * Proc to generate a "rank colour" from a client + * + * This takes the client and looks at various factors in order, such as patreon status, staff rank, and more + * Arguments: + * * C - The client were looking up + */ +/proc/client2rankcolour(client/C) + // First check if end user is an admin + if(C.holder) + if(C.holder.rank in GLOB.rank_colour_map) + // Return their rank colour if they are in here + return GLOB.rank_colour_map[C.holder.rank] + + // If they arent an admin, see if they are a patreon. Just accept any level + if(C.donator_level) + return "#e67e22" // Patreon orange + return null diff --git a/code/_globalvars/lists/misc.dm b/code/_globalvars/lists/misc.dm index ebdf2017900..b5fd84ef6d6 100644 --- a/code/_globalvars/lists/misc.dm +++ b/code/_globalvars/lists/misc.dm @@ -54,4 +54,7 @@ GLOBAL_LIST_INIT(cooking_recipes, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = GLOBAL_LIST_INIT(cooking_ingredients, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list())) GLOBAL_LIST_INIT(cooking_reagents, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list())) +/// Associative list of admin rank to colour. Set in config/rank_colours.txt +GLOBAL_LIST_EMPTY(rank_colour_map) + #define EGG_LAYING_MESSAGES list("lays an egg.", "squats down and croons.", "begins making a huge racket.", "begins clucking raucously.") diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index aa43133d111..3b39682efbf 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -925,3 +925,34 @@ runnable_modes[M] = probabilities[M.config_tag] // to_chat(world, "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]") return runnable_modes + +/datum/configuration/proc/load_rank_colour_map() + var/list/lines = file2list("config/rank_colours.txt") + + for(var/line in lines) + // Skip newlines + if(!length(line)) + continue + // Skip comments + if(line[1] == "#") + continue + + //Split the line at every " - " + var/list/split_holder = splittext(line, " - ") + if(!length(split_holder)) + continue + + // Rank is before the " - " + var/rank = split_holder[1] + if(!rank) + continue + + // Color is after the " - " + var/colour = "" + if(length(split_holder) >= 2) + colour = split_holder[2] + + if(rank && colour) + GLOB.rank_colour_map[rank] = colour + else + stack_trace("Invalid colour for rank '[rank]' in config/rank_colours.txt") diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm index 4a0429dd576..449ff234157 100644 --- a/code/game/verbs/who.dm +++ b/code/game/verbs/who.dm @@ -1,63 +1,98 @@ - /client/verb/who() set name = "Who" set category = "OOC" - var/msg = "Current Players:\n" + var/list/lines = list() + var/list/temp = list() + for(var/client/C in GLOB.clients) + if(C.holder && C.holder.big_brother) // BB doesn't show up at all + continue + + if(C.holder && C.holder.fakekey) + temp += C.holder.fakekey + else + temp += C.key + + temp = sortList(temp) // Sort it. We dont do this above because fake keys would be out of order, which would be a giveaway + + var/list/output_players = list() + + // Now go over it again to apply colours. + for(var/p in temp) + var/client/C = GLOB.directory[ckey(p)] + if(!C) + // This should NEVER happen, but better to be safe + continue + // Get the colour + var/colour = client2rankcolour(C) + var/out = "[p]" + if(C.holder) + out = "[out]" + if(colour) + out = "[out]" + + output_players += out + + lines += "Current Players ([length(output_players)]): " + lines += output_players.Join(", ") // Turn players into a comma separated list + + if(check_rights(R_ADMIN, FALSE)) + lines += "Click here for detailed (old) who." + + var/msg = lines.Join("\n") + + to_chat(src, msg) + +// Advanced version of `who` to show player age, antag status and more. Lags the chat when loading, so its in its own proc +/client/proc/who_advanced() + if(!check_rights(R_ADMIN)) + return var/list/Lines = list() - if(check_rights(R_ADMIN,0)) - for(var/client/C in GLOB.clients) - if(C.holder && C.holder.big_brother && !check_rights(R_PERMISSIONS, 0)) // need PERMISSIONS to see BB - continue + for(var/client/C in GLOB.clients) + if(C.holder && C.holder.big_brother && !check_rights(R_PERMISSIONS, FALSE)) // need PERMISSIONS to see BB + continue - var/entry = "\t[C.key]" - if(C.holder && C.holder.fakekey) - entry += " (as [C.holder.fakekey])" - entry += " - Playing as [C.mob.real_name]" - switch(C.mob.stat) - if(UNCONSCIOUS) - entry += " - Unconscious" - if(DEAD) - if(isobserver(C.mob)) - var/mob/dead/observer/O = C.mob - if(O.started_as_observer) - entry += " - Observing" - else - entry += " - DEAD" - else if(isnewplayer(C.mob)) - entry += " - New Player" + var/entry = "\t[C.key]" + if(C.holder && C.holder.fakekey) + entry += " (as [C.holder.fakekey])" + entry += " - Playing as [C.mob.real_name]" + switch(C.mob.stat) + if(UNCONSCIOUS) + entry += " - Unconscious" + if(DEAD) + if(isobserver(C.mob)) + var/mob/dead/observer/O = C.mob + if(O.started_as_observer) + entry += " - Observing" else entry += " - DEAD" + else if(isnewplayer(C.mob)) + entry += " - New Player" + else + entry += " - DEAD" - var/age - if(isnum(C.player_age)) - age = C.player_age - else - age = 0 + var/age + if(isnum(C.player_age)) + age = C.player_age + else + age = 0 - if(age <= 1) - age = "[age]" - else if(age < 10) - age = "[age]" + if(age <= 1) + age = "[age]" + else if(age < 10) + age = "[age]" - entry += " - [age]" + entry += " - [age]" - if(is_special_character(C.mob)) - entry += " - Antagonist" - entry += " ([ADMIN_QUE(C.mob,"?")])" - Lines += entry - else - for(var/client/C in GLOB.clients) - if(C.holder && C.holder.big_brother) // BB doesn't show up at all - continue + if(is_special_character(C.mob)) + entry += " - Antagonist" + entry += " ([ADMIN_QUE(C.mob, "?")])" + Lines += entry - if(C.holder && C.holder.fakekey) - Lines += C.holder.fakekey - else - Lines += C.key + var/msg = "" for(var/line in sortList(Lines)) msg += "[line]\n" @@ -83,7 +118,12 @@ if(C.holder.big_brother && !check_rights(R_PERMISSIONS, 0)) // normal admins can't see BB continue - msg += "\t[C] is a [C.holder.rank]" + // Their rank may not have a defined colour, only set colour if so + var/rank_colour = client2rankcolour(C) + if(rank_colour) + msg += "[C] is a [C.holder.rank]" + else + msg += "[C] is a [C.holder.rank]" if(C.holder.fakekey) msg += " (as [C.holder.fakekey])" @@ -102,7 +142,12 @@ num_admins_online++ else if(check_rights(R_MENTOR|R_MOD, 0, C.mob)) - modmsg += "\t[C] is a [C.holder.rank]" + // Their rank may not have a defined colour, only set colour if so + var/rank_colour = client2rankcolour(C) + if(rank_colour) + modmsg += "[C] is a [C.holder.rank]" + else + modmsg += "[C] is a [C.holder.rank]" if(isobserver(C.mob)) modmsg += " - Observing" @@ -120,10 +165,18 @@ if(check_rights(R_ADMIN, 0, C.mob)) if(!C.holder.fakekey) - msg += "\t[C] is a [C.holder.rank]\n" + var/rank_colour = client2rankcolour(C) + if(rank_colour) + msg += "[C] is a [C.holder.rank]" + else + msg += "[C] is a [C.holder.rank]" num_admins_online++ else if(check_rights(R_MOD|R_MENTOR, 0, C.mob) && !check_rights(R_ADMIN, 0, C.mob)) - modmsg += "\t[C] is a [C.holder.rank]\n" + var/rank_colour = client2rankcolour(C) + if(rank_colour) + modmsg += "[C] is a [C.holder.rank]" + else + modmsg += "[C] is a [C.holder.rank]" num_mods_online++ var/noadmins_info = "\nIf no admins or mentors are online, make a ticket anyways. Adminhelps and mentorhelps will be relayed to discord, and staff will still be informed." diff --git a/code/game/world.dm b/code/game/world.dm index 5ba97917661..b3abac365e8 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -190,6 +190,7 @@ GLOBAL_LIST_EMPTY(world_topic_handlers) config.load("config/game_options.txt","game_options") config.loadsql("config/dbconfig.txt") config.loadoverflowwhitelist("config/ofwhitelist.txt") + config.load_rank_colour_map() // apply some settings from config.. /world/proc/update_status() diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 26fa05cebfb..db9a440c11d 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -3556,6 +3556,8 @@ var/datum/browser/popup = new(usr, "view_karma", "Karma stats for [target_ckey]", 600, 300) popup.set_content(dat) popup.open(FALSE) + else if(href_list["who_advanced"]) + usr.client.who_advanced() /client/proc/create_eventmob_for(mob/living/carbon/human/H, killthem = 0) if(!check_rights(R_EVENT)) diff --git a/config/example/rank_colours.txt b/config/example/rank_colours.txt new file mode 100644 index 00000000000..b35641c39f4 --- /dev/null +++ b/config/example/rank_colours.txt @@ -0,0 +1,11 @@ +# Use this file to denote colours for ingame admin ranks, using the following format +# Rankname - #12A5F4 +# Colours dont have to be in hex, since this colour string is thrown into the style -aa +Head of Staff - #e74c3c +Maintainer - #992d22 +Server Dev - #1abc9c +Community Manager - #e91e63 +Game Admin - #238afa +Trial Admin - #7fb6fc +PR Reviewer - #c27c0e +Mentor - #f1c40f