From 3a5448f7410d20a9a7de820593d0889a388657d2 Mon Sep 17 00:00:00 2001 From: Amunak Date: Wed, 29 Jan 2020 00:48:39 +0100 Subject: [PATCH] Prettifies closet contents list with (now added) countable english_list Contents of closets (as viewed by ghosts) are now less ugly and easier to read. - Adds reusable option to have english_lists count the contents and display them (optionally with icons and specific determiners). - Due to backwards compatibility these options are NOT available for non-countable lists; this was originally planned, but it's not easily possible unless all usage of english_list is revised. - Moves the ghost examine code to proc/examine where it belongs. - Ghosts now also see empty/full messages like characters standing close do. - The contents list for closets now shows number of items (if multiple) and their icons (wherever possible). - The list no longer shows unnecessary determiners ("the" before every single item). - Old usage of english_list still uses the old code. New code could change order of the strings where it matters (in weather reports or camera network assembly code, for example), so it cannot be used. --- code/_helpers/_lists.dm | 65 +++++++++++++++++-- .../structures/crates_lockers/closets.dm | 13 ++-- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/code/_helpers/_lists.dm b/code/_helpers/_lists.dm index 1eb8ac5456..31a09d0bc4 100644 --- a/code/_helpers/_lists.dm +++ b/code/_helpers/_lists.dm @@ -5,17 +5,68 @@ * Sorting */ +// Determiner constants +#define DET_NONE 0x00; +#define DET_DEFINITE 0x01; // the +#define DET_INDEFINITE 0x02; // a, an, some +#define DET_AUTO 0x04; + /* * Misc */ -//Returns a list in plain english as a string -/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) - switch(input.len) +//Returns a list in plain english as a string, optionally counting the elements, displaying icons, etc. (icons, determiners work only with counting) +/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "", output_counts = FALSE, output_icons = TRUE, determiners = DET_NONE) + // non-countable lists MUST use legacy code to maintain compatibility + // with shoddy usage of english_list for code logic + // and because it preserves order of inputs + if (!output_counts) + switch(input.len) + if(0) return nothing_text + if(1) return "[input[1]]" + if(2) return "[input[1]][and_text][input[2]]" + else return "[jointext(input, comma_text, 1, -1)][final_comma_text][and_text][input[input.len]]" + + var/list/counts = list() // counted input items + var/list/items = list() // actual objects for later reference (for icons and formatting) + // count items + for(var/item in input) + var/name = "[item]" // index items by name; usually works fairly well for loose equality + if(name in counts) + counts[name]++ + else + counts[name] = 1 + items.Add(item) + + // assemble the output list + var/list/out = list() + for(var/item in items) + var/name = "[item]" + var/count = counts[name] + var/item_str = "" + if(count > 1) + item_str += "[count]x " + + if(isatom(item)) + // atoms/items/objects can be pretty and whatnot + var/atom/A = item + if(output_icons && isicon(A.icon) && !ismob(A)) // mobs tend to have unusable icons + item_str += "\icon[A] " + switch(determiners) + if(DET_NONE) item_str += A.name + if(DET_DEFINITE) item_str += "\the [A]" + if(DET_INDEFINITE) item_str += "\a [A]" + else item_str += name + else + // non-atoms use plain string conversion + item_str = name + out.Add(item_str) + + switch(out.len) if(0) return nothing_text - if(1) return "[input[1]]" - if(2) return "[input[1]][and_text][input[2]]" - else return "[jointext(input, comma_text, 1, -1)][final_comma_text][and_text][input[input.len]]" + if(1) return "[out[1]]" + if(2) return "[out[1]][and_text][out[2]]" + else return "[jointext(out, comma_text, 1, -1)][final_comma_text][and_text][out[out.len]]" //Returns list element or null. Should prevent "index out of bounds" error. proc/listgetindex(var/list/list,index) @@ -762,4 +813,4 @@ proc/dd_sortedTextList(list/incoming) /proc/popleft(list/L) if(L.len) . = L[1] - L.Cut(1,2) + L.Cut(1,2) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index c3e4f3d7d9..25c8efdc89 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -57,7 +57,7 @@ update_icon() /obj/structure/closet/examine(mob/user) - if(..(user, 1) && !opened) + if(!src.opened && (..(user, 1) || isobserver(user))) var/content_size = 0 for(var/obj/item/I in src.contents) if(!I.anchored) @@ -73,6 +73,9 @@ else to_chat(user, "It is full.") + if(!src.opened && isobserver(user)) + to_chat(user, "It contains: [english_list(contents, output_counts = TRUE)].") + /obj/structure/closet/CanPass(atom/movable/mover, turf/target) if(wall_mounted) return TRUE @@ -359,12 +362,6 @@ if(!src.toggle()) to_chat(usr, "It won't budge!") -/obj/structure/closet/attack_ghost(mob/ghost) - if(ghost.client && ghost.client.inquisitive_ghost) - ghost.examinate(src) - if (!src.opened) - to_chat(ghost, "It contains: [english_list(contents)].") - /obj/structure/closet/verb/verb_toggleopen() set src in oview(1) set category = "Object" @@ -473,4 +470,4 @@ return dump_contents() spawn(1) qdel(src) - return 1 \ No newline at end of file + return 1