This commit is contained in:
SandPoot
2024-08-11 04:12:13 -03:00
parent 587f92e900
commit d3a256f1de
9 changed files with 331 additions and 102 deletions

View File

@@ -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 ;

View File

@@ -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.

View File

@@ -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"

View File

@@ -24,6 +24,7 @@
#define VV_PROCCALL_RETVAL "Return Value of Proccall"
#define VV_MSG_MARKED "<br><font size='1' color='red'><b>Marked Object</b></font>"
#define VV_MSG_TAGGED(num) "<br><font size='1' color='red'><b>Tagged Datum #[num]</b></font>"
#define VV_MSG_EDITED "<br><font size='1' color='red'><b>Var Edited</b></font>"
#define VV_MSG_DELETED "<br><font size='1' color='red'><b>Deleted</b></font>"

View File

@@ -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,

View File

@@ -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"
. += "<b>[icon_name]</b><br/>"
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 "<a href='?_src_=vars;[HrefToken()];Vars=[display_ref]'>[display_name] (<span class='value'>[display_value]</span>) [display_ref]</a>"
/// 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 "<li style='backgroundColor:white'>(READ ONLY) [var_name] = [_debug_variable_value(var_name, value, 0, src, sanitize = TRUE, display_flags = NONE)]</li>"
/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)

View File

@@ -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 = "<li style='backgroundColor:white'>([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]
. = "<li style='backgroundColor:white'>([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 = "<li style='backgroundColor:white'>([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)]) "
. = "<li style='backgroundColor:white'>([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 = "<li>"
. = "<li>"
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 = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(name)]'>[VV_HTML_ENCODE(name)] [REF(name)]</a>"
else if(islist(name))
var/list/L = name
name_part = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(name)]'> /list ([length(L)]) [REF(name)]</a>"
var/list/list_value = name
name_part = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(name)]'> /list ([length(list_value)]) [REF(name)]</a>"
if (isnull(value))
item = "[name_part] = <span class='value'>null</span>"
. = "[.][name_part] = "
else if (istext(value))
item = "[name_part] = <span class='value'>\"[VV_HTML_ENCODE(value)]\"</span>"
var/item = _debug_variable_value(name, value, level, owner, sanitize, display_flags)
else if (isicon(value))
return "[.][item]</li>"
// 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)
. = "<font color='red'>DISPLAY_ERROR:</font> ([value] [REF(value)])" // Make sure this line can never runtime
if(isnull(value))
return "<span class='value'>null</span>"
if(istext(value))
return "<span class='value'>\"[VV_HTML_ENCODE(value)]\"</span>"
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] = (<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
var/rname = "tmp[REF(icon_value)][rnd].png"
usr << browse_rsc(icon_value, rname)
return "(<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
#else
item = "[name_part] = /icon (<span class='value'>[value]</span>)"
return "/icon (<span class='value'>[value]</span>)"
#endif
else if (isfile(value))
item = "[name_part] = <span class='value'>'[value]'</span>"
if(isfilter(value))
var/datum/filter_value = value
return "/filter (<span class='value'>[filter_value.type] [REF(filter_value)]</span>)"
else if(istype(value,/matrix)) // Needs to be before datum
var/matrix/M = value
item = {"[name_part] = <span class='value'>
<table class='matrixbrak'><tbody><tr><td class='lbrak'>&nbsp;</td><td>
<table class='matrix'>
<tbody>
<tr><td>[M.a]</td><td>[M.d]</td><td>0</td></tr>
<tr><td>[M.b]</td><td>[M.e]</td><td>0</td></tr>
<tr><td>[M.c]</td><td>[M.f]</td><td>1</td></tr>
</tbody>
</table></td><td class='rbrak'>&nbsp;</td></tr></tbody></table></span>"} //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] = <a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[DV] [DV.type] [REF(value)]</a>"
else
item = "[name_part] = <a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[DV.type] [REF(value)]</a>"
if(isfile(value))
return "<span class='value'>'[value]'</span>"
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] = <a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>/list ([L.len])</a><ul>[items.Join()]</ul>"
else
item = "[name_part] = <a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>/list ([L.len])</a>"
return "<a href='?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a><ul>[items.Join()]</ul>"
else */
return "<a href='?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a>"
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] = <span class='value'>[VV_HTML_ENCODE(value)]</span>"
return "<span class='value'>[VV_HTML_ENCODE(value)]</span>"
return "[header][item]</li>"
/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 "<a href='?_src_=vars;[HrefToken()];Vars=[REF(src)]'>[src] [type] [REF(src)]</a>"
else
return "<a href='?_src_=vars;[HrefToken()];Vars=[REF(src)]'>[type] [REF(src)]</a>"
/datum/weakref/debug_variable_value(name, level, datum/owner, sanitize, display_flags)
. = ..()
return "[.] <a href='?_src_=vars;[HrefToken()];Vars=[reference]'>(Resolve)</a>"
/matrix/debug_variable_value(name, level, datum/owner, sanitize, display_flags)
return {"<span class='value'>
<table class='matrixbrak'><tbody><tr><td class='lbrak'>&nbsp;</td><td>
<table class='matrix'>
<tbody>
<tr><td>[a]</td><td>[d]</td><td>0</td></tr>
<tr><td>[b]</td><td>[e]</td><td>0</td></tr>
<tr><td>[c]</td><td>[f]</td><td>1</td></tr>
</tbody>
</table></td><td class='rbrak'>&nbsp;</td></tr></tbody></table></span>"} //TODO link to modify_transform wrapper for all matrices
#undef VV_HTML_ENCODE

View File

@@ -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, "<span class='danger'>You need to be an administrator to access this.</span>", 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]", "/", "<wbr>/")
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\]" : "<img src='vv[hash].png'></td><td>"
var/list/header = islist(D)? list("<b>/list</b>") : D.vv_get_header()
hash = md5(sprite)
src << browse_rsc(sprite, "vv[hash].png")
sprite_text = no_icon ? "\[NO ICON\]" : "<img src='vv[hash].png'></td><td>"
title = "[thing] ([REF(thing)]) = [type]"
var/formatted_type = replacetext("[type]", "/", "<wbr>/")
var/list/header = islist ? list("<b>/list</b>") : 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] = "<option value[link? "='[link]'":""]>[name]</option>"
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 = {"
<html>
@@ -118,8 +151,8 @@
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca\[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
while (c.charAt(0) == ' ') c = c.substring(1,c.length);
if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
}
return "";
}
@@ -212,7 +245,9 @@
</table>
<div align='center'>
<b><font size='1'>[formatted_type]</font></b>
<br><b><font size='1'>[ref_line]</font></b>
<span id='marked'>[marked_line]</span>
<span id='tagged'>[tagged_line]</span>
<span id='varedited'>[varedited_line]</span>
<span id='deleted'>[deleted_line]</span>
</div>
@@ -267,5 +302,8 @@ datumrefresh=[refid];[HrefToken()]'>Refresh</a>
"}
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

View File

@@ -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"