From d3a256f1de5671accecea20b6249f35de7d91825 Mon Sep 17 00:00:00 2001 From: SandPoot Date: Sun, 11 Aug 2024 04:12:13 -0300 Subject: [PATCH] push --- code/__DEFINES/_helpers.dm | 38 +++++ code/__DEFINES/is_helpers.dm | 13 ++ code/__DEFINES/misc.dm | 6 - code/__DEFINES/vv.dm | 1 + code/_globalvars/bitfields.dm | 13 ++ .../debug_variable_appearance.dm | 101 ++++++++++++ .../admin/view_variables/debug_variables.dm | 145 +++++++++++------- .../admin/view_variables/view_variables.dm | 114 +++++++++----- tgstation.dme | 2 + 9 files changed, 331 insertions(+), 102 deletions(-) create mode 100644 code/__DEFINES/_helpers.dm create mode 100644 code/modules/admin/view_variables/debug_variable_appearance.dm diff --git a/code/__DEFINES/_helpers.dm b/code/__DEFINES/_helpers.dm new file mode 100644 index 0000000000..384f6c064e --- /dev/null +++ b/code/__DEFINES/_helpers.dm @@ -0,0 +1,38 @@ +// Stuff that is relatively "core" and is used in other defines/helpers + +//Returns the hex value of a decimal number +//len == length of returned string +// #define num2hex(X, len) num2text(X, len, 16) -- NOT YET + +//Returns an integer given a hex input, supports negative values "-ff" +//skips preceding invalid characters +// #define hex2num(X) text2num(X, 16) -- NO + +/// Stringifies whatever you put into it. +#define STRINGIFY(argument) #argument + +/// subtypesof(), typesof() without the parent path +#define subtypesof(typepath) ( typesof(typepath) - typepath ) + +/// Until a condition is true, sleep +#define UNTIL(X) while(!(X)) stoplag() + +/// Sleep if we haven't been deleted +/// Otherwise, return +#define SLEEP_NOT_DEL(time) \ + if(QDELETED(src)) { \ + return; \ + } \ + sleep(time); + +/// Takes a datum as input, returns its ref string +#define text_ref(datum) ref(datum) + +// Refs contain a type id within their string that can be used to identify byond types. +// Custom types that we define don't get a unique id, but this is useful for identifying +// types that don't normally have a way to run istype() on them. +#define TYPEID(thing) copytext(REF(thing), 4, 6) + +/// A null statement to guard against EmptyBlock lint without necessitating the use of pass() +/// Used to avoid proc-call overhead. But use sparingly. Probably pointless in most places. +#define EMPTY_BLOCK_GUARD ; diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 640079e9b8..fb8ebd3d08 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -7,8 +7,21 @@ #define isatom(A) (isloc(A)) +#define isdatum(thing) (istype(thing, /datum)) + #define isweakref(D) (istype(D, /datum/weakref)) +#define isimage(thing) (istype(thing, /image)) + +GLOBAL_VAR_INIT(magic_appearance_detecting_image, new /image) // appearances are awful to detect safely, but this seems to be the best way ~ninjanomnom +#define isappearance(thing) (!isimage(thing) && !ispath(thing) && istype(GLOB.magic_appearance_detecting_image, thing)) + +// The filters list has the same ref type id as a filter, but isnt one and also isnt a list, so we have to check if the thing has Cut() instead +GLOBAL_VAR_INIT(refid_filter, TYPEID(filter(type="angular_blur"))) +#define isfilter(thing) (!hascall(thing, "Cut") && TYPEID(thing) == GLOB.refid_filter) + +#define isgenerator(A) (istype(A, /generator)) + //Turfs //#define isturf(A) (istype(A, /turf)) This is actually a byond built-in. Added here for completeness sake. diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index edd9149fa3..0b051af156 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -211,10 +211,6 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) #define POLLTYPE_IRV "IRV" - -//subtypesof(), typesof() without the parent path -#define subtypesof(typepath) ( typesof(typepath) - typepath ) - //Gets the turf this atom inhabits #define get_turf(A) (get_step(A, 0)) @@ -550,8 +546,6 @@ GLOBAL_LIST_INIT(pda_reskins, list( #define NIGHTSHIFT_AREA_DEPARTMENT_HALLS 3 //interior hallways, etc #define NIGHTSHIFT_AREA_NONE 4 //default/highest. -#define UNTIL(X) while(!(X)) stoplag() - //Scavenging element defines for special loot "events". #define SCAVENGING_FOUND_NOTHING "found_nothing" diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index 86a3bd4c31..198265b041 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -24,6 +24,7 @@ #define VV_PROCCALL_RETVAL "Return Value of Proccall" #define VV_MSG_MARKED "
Marked Object" +#define VV_MSG_TAGGED(num) "
Tagged Datum #[num]" #define VV_MSG_EDITED "
Var Edited" #define VV_MSG_DELETED "
Deleted" diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index e4ac2fe140..381ddc7d4a 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -471,6 +471,19 @@ DEFINE_BITFIELD(vis_flags, list( "VIS_UNDERLAY" = VIS_UNDERLAY, )) +// I am so sorry. Required because vis_flags is both undefinable and unreadable on mutable_appearance +// But we need to display them anyway. See /mutable_appearance/appearance_mirror +DEFINE_BITFIELD(_vis_flags, list( + "VIS_HIDE" = VIS_HIDE, + "VIS_INHERIT_DIR" = VIS_INHERIT_DIR, + "VIS_INHERIT_ICON" = VIS_INHERIT_ICON, + "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE, + "VIS_INHERIT_ID" = VIS_INHERIT_ID, + "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER, + "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE, + "VIS_UNDERLAY" = VIS_UNDERLAY, +)) + DEFINE_BITFIELD(visor_flags, list( "ALLOWINTERNALS" = ALLOWINTERNALS, "BLOCK_GAS_SMOKE_EFFECT" = BLOCK_GAS_SMOKE_EFFECT, diff --git a/code/modules/admin/view_variables/debug_variable_appearance.dm b/code/modules/admin/view_variables/debug_variable_appearance.dm new file mode 100644 index 0000000000..3ceaf2a50b --- /dev/null +++ b/code/modules/admin/view_variables/debug_variable_appearance.dm @@ -0,0 +1,101 @@ +/// Shows a header name on top when you investigate an appearance/image +/image/vv_get_header() + . = list() + var/icon_name = icon ? copytext("[icon]", findlasttext("[icon]", "/") + 1) : "null" + . += "[icon_name]
" + if(icon) + . += icon_state ? "\"[icon_state]\"" : "(icon_state = null)" + +/// Makes nice short vv names for images +/image/debug_variable_value(name, level, datum/owner, sanitize, display_flags) + var/display_name = "[type]" + if("[src]" != "[type]") // If we have a name var, let's use it. + display_name = "[src] [type]" + + var/display_value + var/list/icon_file_name = splittext("[icon]", "/") + if(length(icon_file_name)) + display_value = icon_file_name[length(icon_file_name)] + else + display_value = "null" + + if(icon_state) + display_value = "[display_value]:[icon_state]" + + var/display_ref = get_vv_link_ref() + return "[display_name] ([display_value]) [display_ref]" + +/// Returns the ref string to use when displaying this image in the vv menu of something else +/image/proc/get_vv_link_ref() + return REF(src) + +// It is endlessly annoying to display /appearance directly for stupid byond reasons, so we copy everything we care about into a holder datum +// That we can override procs on and store other vars on and such. +/mutable_appearance/appearance_mirror + // So people can see where it came from + var/appearance_ref + // vis flags can't be displayed by mutable appearances cause it don't make sense as overlays, but appearances do carry them + // can't use the name either for byond reasons + var/_vis_flags + +// all alone at the end of the universe +GLOBAL_DATUM_INIT(pluto, /atom/movable, new /atom/movable(null)) + +// arg is actually an appearance, typed as mutable_appearance as closest mirror +/mutable_appearance/appearance_mirror/New(mutable_appearance/appearance_father) + . = ..() // /mutable_appearance/New() copies over all the appearance vars MAs care about by default + // We copy over our appearance onto an atom. This is done so we can read vars carried by but not accessible on appearances + GLOB.pluto.appearance = appearance_father + _vis_flags = GLOB.pluto.vis_flags + appearance_ref = REF(appearance_father) + +// This means if the appearance loses refs before a click it's gone, but that's consistent to other datums so it's fine +// Need to ref the APPEARANCE because we just free on our own, which sorta fucks this operation up you know? +/mutable_appearance/appearance_mirror/get_vv_link_ref() + return appearance_ref + +/mutable_appearance/appearance_mirror/can_vv_get(var_name) + var/static/datum/beloved = new() + if(beloved.vars.Find(var_name)) // If datums have it, get out + return FALSE + // If it is one of the two args on /image, yeet (I am sorry) + if(var_name == NAMEOF(src, realized_overlays)) + return FALSE + if(var_name == NAMEOF(src, realized_underlays)) + return FALSE + // Filtering out the stuff I know we don't care about + if(var_name == NAMEOF(src, x)) + return FALSE + if(var_name == NAMEOF(src, y)) + return FALSE + if(var_name == NAMEOF(src, z)) + return FALSE + // Could make an argument for these but I think they will just confuse people, so yeeet +#ifndef SPACEMAN_DMM // Spaceman doesn't believe in contents on appearances, sorry lads + if(var_name == NAMEOF(src, contents)) + return FALSE +#endif + if(var_name == NAMEOF(src, loc)) + return FALSE + if(var_name == NAMEOF(src, vis_contents)) + return FALSE + return ..() + +/mutable_appearance/appearance_mirror/vv_get_var(var_name) + // No editing for you + var/value = vars[var_name] + return "
  • (READ ONLY) [var_name] = [_debug_variable_value(var_name, value, 0, src, sanitize = TRUE, display_flags = NONE)]
  • " + +/mutable_appearance/appearance_mirror/vv_get_dropdown() + SHOULD_CALL_PARENT(FALSE) + + . = list() + VV_DROPDOWN_OPTION("", "---") + VV_DROPDOWN_OPTION(VV_HK_CALLPROC, "Call Proc") + VV_DROPDOWN_OPTION(VV_HK_MARK, "Mark Object") + VV_DROPDOWN_OPTION(VV_HK_TAG, "Tag Datum") + VV_DROPDOWN_OPTION(VV_HK_DELETE, "Delete") + VV_DROPDOWN_OPTION(VV_HK_EXPOSE, "Show VV To Player") + +/proc/get_vv_appearance(mutable_appearance/appearance) // actually appearance yadeeyada + return new /mutable_appearance/appearance_mirror(appearance) diff --git a/code/modules/admin/view_variables/debug_variables.dm b/code/modules/admin/view_variables/debug_variables.dm index a7c191de58..ddb372551a 100644 --- a/code/modules/admin/view_variables/debug_variables.dm +++ b/code/modules/admin/view_variables/debug_variables.dm @@ -1,96 +1,125 @@ #define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) /// Get displayed variable in VV variable list -/proc/debug_variable(name, value, level, datum/D, sanitize = TRUE) //if D is a list, name will be index, and value will be assoc value. - var/header - if(D) - if(islist(D)) +/proc/debug_variable(name, value, level, datum/owner, sanitize = TRUE, display_flags = NONE) //if D is a list, name will be index, and value will be assoc value. + if(owner) + if(islist(owner)) + var/list/list_owner = owner var/index = name if (value) - name = D[name] //name is really the index until this line + name = list_owner[name] //name is really the index until this line else - value = D[name] - header = "
  • ([VV_HREF_TARGET_1V(D, VV_HK_LIST_EDIT, "E", index)]) ([VV_HREF_TARGET_1V(D, VV_HK_LIST_CHANGE, "C", index)]) ([VV_HREF_TARGET_1V(D, VV_HK_LIST_REMOVE, "-", index)]) " + value = list_owner[name] + . = "
  • ([VV_HREF_TARGET_1V(owner, VV_HK_LIST_EDIT, "E", index)]) ([VV_HREF_TARGET_1V(owner, VV_HK_LIST_CHANGE, "C", index)]) ([VV_HREF_TARGET_1V(owner, VV_HK_LIST_REMOVE, "-", index)]) " else - header = "
  • ([VV_HREF_TARGET_1V(D, VV_HK_BASIC_EDIT, "E", name)]) ([VV_HREF_TARGET_1V(D, VV_HK_BASIC_CHANGE, "C", name)]) ([VV_HREF_TARGET_1V(D, VV_HK_BASIC_MASSEDIT, "M", name)]) " + . = "
  • ([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_EDIT, "E", name)]) ([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_CHANGE, "C", name)]) ([VV_HREF_TARGET_1V(owner, VV_HK_BASIC_MASSEDIT, "M", name)]) " else - header = "
  • " + . = "
  • " - var/item var/name_part = VV_HTML_ENCODE(name) - if(level > 0 || islist(D)) //handling keys in assoc lists + if(level > 0 || islist(owner)) //handling keys in assoc lists if(istype(name,/datum)) name_part = "[VV_HTML_ENCODE(name)] [REF(name)]" else if(islist(name)) - var/list/L = name - name_part = " /list ([length(L)]) [REF(name)]" + var/list/list_value = name + name_part = " /list ([length(list_value)]) [REF(name)]" - if (isnull(value)) - item = "[name_part] = null" + . = "[.][name_part] = " - else if (istext(value)) - item = "[name_part] = \"[VV_HTML_ENCODE(value)]\"" + var/item = _debug_variable_value(name, value, level, owner, sanitize, display_flags) - else if (isicon(value)) + return "[.][item]
  • " + +// This is split into a seperate proc mostly to make errors that happen not break things too much +/proc/_debug_variable_value(name, value, level, datum/owner, sanitize, display_flags) + if(isappearance(value)) + value = get_vv_appearance(value) + + . = "DISPLAY_ERROR: ([value] [REF(value)])" // Make sure this line can never runtime + + if(isnull(value)) + return "null" + + if(istext(value)) + return "\"[VV_HTML_ENCODE(value)]\"" + + if(isicon(value)) #ifdef VARSICON - var/icon/I = icon(value) + var/icon/icon_value = icon(value) var/rnd = rand(1,10000) - var/rname = "tmp[REF(I)][rnd].png" - usr << browse_rsc(I, rname) - item = "[name_part] = ([value]) " + var/rname = "tmp[REF(icon_value)][rnd].png" + usr << browse_rsc(icon_value, rname) + return "([value]) " #else - item = "[name_part] = /icon ([value])" + return "/icon ([value])" #endif - else if (isfile(value)) - item = "[name_part] = '[value]'" + if(isfilter(value)) + var/datum/filter_value = value + return "/filter ([filter_value.type] [REF(filter_value)])" - else if(istype(value,/matrix)) // Needs to be before datum - var/matrix/M = value - item = {"[name_part] = -
      - - - - - - -
    [M.a][M.d]0
    [M.b][M.e]0
    [M.c][M.f]1
     
    "} //TODO link to modify_transform wrapper for all matrices - else if (istype(value, /datum)) - var/datum/DV = value - if ("[DV]" != "[DV.type]") //if the thing as a name var, lets use it. - item = "[name_part] = [DV] [DV.type] [REF(value)]" - else - item = "[name_part] = [DV.type] [REF(value)]" + if(isfile(value)) + return "'[value]'" - else if (islist(value)) - var/list/L = value - var/list/items = list() + if(isdatum(value)) + var/datum/datum_value = value + return datum_value.debug_variable_value(name, level, owner, sanitize, display_flags) - if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? VV_NORMAL_LIST_NO_EXPAND_THRESHOLD : VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD))) - for (var/i in 1 to L.len) - var/key = L[i] + if(islist(value)) // || (name in GLOB.vv_special_lists)) // Some special lists arent detectable as a list through istype + var/list/list_value = value +// var/list/items = list() + + // This is becuse some lists either dont count as lists or a locate on their ref will return null + var/link_vars = "Vars=[REF(value)]" +// if(name in GLOB.vv_special_lists) +// link_vars = "Vars=[REF(owner)];special_varname=[name]" + +/* if (!(display_flags & VV_ALWAYS_CONTRACT_LIST) && list_value.len > 0 && list_value.len <= (IS_NORMAL_LIST(list_value) ? VV_NORMAL_LIST_NO_EXPAND_THRESHOLD : VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD)) + for (var/i in 1 to list_value.len) + var/key = list_value[i] var/val - if (IS_NORMAL_LIST(L) && !isnum(key)) - val = L[key] - if (isnull(val)) // we still want to display non-null false values, such as 0 or "" + if (IS_NORMAL_LIST(list_value) && !isnum(key)) + val = list_value[key] + if (isnull(val)) // we still want to display non-null false values, such as 0 or "" val = key key = i items += debug_variable(key, val, level + 1, sanitize = sanitize) - item = "[name_part] = /list ([L.len])" - else - item = "[name_part] = /list ([L.len])" + return "/list ([list_value.len])" + else */ + return "/list ([list_value.len])" - else if (name in GLOB.bitfields) + if(name in GLOB.bitfields) var/list/flags = list() for (var/i in GLOB.bitfields[name]) if (value & GLOB.bitfields[name][i]) flags += i - item = "[name_part] = [VV_HTML_ENCODE(jointext(flags, ", "))]" + if(length(flags)) + return "[VV_HTML_ENCODE(jointext(flags, ", "))]" + else + return "NONE" else - item = "[name_part] = [VV_HTML_ENCODE(value)]" + return "[VV_HTML_ENCODE(value)]" - return "[header][item]" +/datum/proc/debug_variable_value(name, level, datum/owner, sanitize, display_flags) + if("[src]" != "[type]") // If we have a name var, let's use it. + return "[src] [type] [REF(src)]" + else + return "[type] [REF(src)]" + +/datum/weakref/debug_variable_value(name, level, datum/owner, sanitize, display_flags) + . = ..() + return "[.] (Resolve)" + +/matrix/debug_variable_value(name, level, datum/owner, sanitize, display_flags) + return {" +
      + + + + + + +
    [a][d]0
    [b][e]0
    [c][f]1
     
    "} //TODO link to modify_transform wrapper for all matrices #undef VV_HTML_ENCODE diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index a7faea2553..0ddec6f147 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -1,55 +1,87 @@ -/client/proc/debug_variables(datum/D in world) +#define ICON_STATE_CHECKED 1 /// this dmi is checked. We don't check this one anymore. +#define ICON_STATE_NULL 2 /// this dmi has null-named icon_state, allowing it to show a sprite on vv editor. + +/client/proc/debug_variables(datum/thing in world) set category = "Debug" set name = "View Variables" //set src in world var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round. - if(!usr.client || !usr.client.holder) //This is usr because admins can call the proc on other clients, even if they're not admins, to show them VVs. - to_chat(usr, "You need to be an administrator to access this.", confidential = TRUE) + if(!usr.client || !usr.client.holder) //This is usr because admins can call the proc on other clients, even if they're not admins, to show them VVs. + to_chat(usr, span_danger("You need to be an administrator to access this."), confidential = TRUE) return - if(!D) + if(!thing) return var/datum/asset/asset_cache_datum = get_asset_datum(/datum/asset/simple/vv) asset_cache_datum.send(usr) - var/islist = islist(D) - if(!islist && !istype(D)) + if(isappearance(thing)) + thing = get_vv_appearance(thing) // this is /mutable_appearance/our_bs_subtype + var/islist = islist(thing) || (!isdatum(thing) && hascall(thing, "Cut")) // Some special lists dont count as lists, but can be detected by if they have list procs + if(!islist && !isdatum(thing)) return var/title = "" - var/refid = REF(D) + var/refid = REF(thing) var/icon/sprite var/hash - var/type = islist? /list : D.type + var/type = islist ? /list : thing.type var/no_icon = FALSE - if(istype(D, /atom)) - sprite = getFlatIcon(D) - if(sprite) - hash = md5(sprite) - src << browse_rsc(sprite, "vv[hash].png") - else + if(isatom(thing)) + sprite = getFlatIcon(thing) + if(!sprite) no_icon = TRUE - title = "[D] ([REF(D)]) = [type]" - var/formatted_type = replacetext("[type]", "/", "/") + else if(isimage(thing)) + // icon_state=null shows first image even if dmi has no icon_state for null name. + // This list remembers which dmi has null icon_state, to determine if icon_state=null should display a sprite + // (NOTE: icon_state="" is correct, but saying null is obvious) + var/static/list/dmi_nullstate_checklist = list() + var/image/image_object = thing + var/icon_filename_text = "[image_object.icon]" // "icon(null)" type can exist. textifying filters it. + if(icon_filename_text) + if(image_object.icon_state) + sprite = icon(image_object.icon, image_object.icon_state) + + else // it means: icon_state="" + if(!dmi_nullstate_checklist[icon_filename_text]) + dmi_nullstate_checklist[icon_filename_text] = ICON_STATE_CHECKED + if("" in icon_states(image_object.icon)) + // this dmi has nullstate. We'll allow "icon_state=null" to show image. + dmi_nullstate_checklist[icon_filename_text] = ICON_STATE_NULL + + if(dmi_nullstate_checklist[icon_filename_text] == ICON_STATE_NULL) + sprite = icon(image_object.icon, image_object.icon_state) var/sprite_text if(sprite) - sprite_text = no_icon? "\[NO ICON\]" : "" - var/list/header = islist(D)? list("/list") : D.vv_get_header() + hash = md5(sprite) + src << browse_rsc(sprite, "vv[hash].png") + sprite_text = no_icon ? "\[NO ICON\]" : "" + + title = "[thing] ([REF(thing)]) = [type]" + var/formatted_type = replacetext("[type]", "/", "/") + + var/list/header = islist ? list("/list") : thing.vv_get_header() + + var/ref_line = "@[copytext(refid, 2, -1)]" // get rid of the brackets, add a @ prefix for copy pasting in asay var/marked_line - if(holder && holder.marked_datum && holder.marked_datum == D) + if(holder && holder.marked_datum && holder.marked_datum == thing) marked_line = VV_MSG_MARKED + var/tagged_line + if(holder && LAZYFIND(holder.tagged_datums, thing)) + var/tag_index = LAZYFIND(holder.tagged_datums, thing) + tagged_line = VV_MSG_TAGGED(tag_index) var/varedited_line - if(!islist && (D.datum_flags & DF_VAR_EDITED)) + if(!islist && (thing.datum_flags & DF_VAR_EDITED)) varedited_line = VV_MSG_EDITED var/deleted_line - if(!islist && D.gc_destroyed) + if(!islist && thing.gc_destroyed) deleted_line = VV_MSG_DELETED var/list/dropdownoptions @@ -70,28 +102,29 @@ var/link = dropdownoptions[name] dropdownoptions[i] = "" else - dropdownoptions = D.vv_get_dropdown() + dropdownoptions = thing.vv_get_dropdown() var/list/names = list() if(!islist) - for(var/V in D.vars) - names += V - sleep(1) + for(var/varname in thing.vars) + names += varname + + sleep(1 TICKS) var/list/variable_html = list() if(islist) - var/list/L = D - for(var/i in 1 to L.len) - var/key = L[i] + var/list/list_value = thing + for(var/i in 1 to list_value.len) + var/key = list_value[i] var/value - if(IS_NORMAL_LIST(L) && IS_VALID_ASSOC_KEY(key)) - value = L[key] - variable_html += debug_variable(i, value, 0, L) + if(IS_NORMAL_LIST(list_value) && IS_VALID_ASSOC_KEY(key)) + value = list_value[key] + variable_html += debug_variable(i, value, 0, list_value) else names = sort_list(names) - for(var/V in names) - if(D.can_vv_get(V)) - variable_html += D.vv_get_var(V) + for(var/varname in names) + if(thing.can_vv_get(varname)) + variable_html += thing.vv_get_var(varname) var/html = {" @@ -118,8 +151,8 @@ var ca = document.cookie.split(';'); for(var i=0; i
    [formatted_type] +
    [ref_line] [marked_line] + [tagged_line] [varedited_line] [deleted_line]
    @@ -267,5 +302,8 @@ datumrefresh=[refid];[HrefToken()]'>Refresh "} src << browse(html, "window=variables[refid];size=475x650") -/client/proc/vv_update_display(datum/D, span, content) - src << output("[span]:[content]", "variables[REF(D)].browser:replace_span") +/client/proc/vv_update_display(datum/thing, span, content) + src << output("[span]:[content]", "variables[REF(thing)].browser:replace_span") + +#undef ICON_STATE_CHECKED +#undef ICON_STATE_NULL diff --git a/tgstation.dme b/tgstation.dme index 8333203c05..640bc99969 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -21,6 +21,7 @@ #include "code\world.dm" #include "code\__DEFINES\_click.dm" #include "code\__DEFINES\_globals.dm" +#include "code\__DEFINES\_helpers.dm" #include "code\__DEFINES\_protect.dm" #include "code\__DEFINES\_tick.dm" #include "code\__DEFINES\access.dm" @@ -1558,6 +1559,7 @@ #include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2_wrappers.dm" #include "code\modules\admin\view_variables\admin_delete.dm" +#include "code\modules\admin\view_variables\debug_variable_appearance.dm" #include "code\modules\admin\view_variables\debug_variables.dm" #include "code\modules\admin\view_variables\filterrific.dm" #include "code\modules\admin\view_variables\get_variables.dm"