mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-20 03:26:37 +01:00
View Variables Update (2) (#17946)
* Begin * Begin 2 * move to tsx * fix that UI * fix gib * bunch of fixes * fix this one * Nicer ahelp bot text formatting * clean up all inputs * . * fix MC tab * fix ore spawn * with rare * More filter stuff * Cleaned up world * Fix * ummm * . * fix that * . * Begin * Begin 2 * move to tsx * fix that UI * fix gib * bunch of fixes * fix this one * clean up all inputs * Nicer ahelp bot text formatting * . * fix MC tab * fix ore spawn * with rare * More filter stuff * Cleaned up world * Fix * Added missing props * useContext fix * . --------- Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
@@ -5,27 +5,25 @@
|
||||
if(istype(A))
|
||||
var/turf/T = get_turf(A)
|
||||
if(T)
|
||||
coords = "at [COORD(T)]"
|
||||
jmp_coords = "at [ADMIN_COORDJMP(T)]"
|
||||
var/atom/a_loc = A.loc
|
||||
var/is_turf = isturf(a_loc)
|
||||
coords = "[is_turf ? "at" : "from [a_loc] at"] [AREACOORD(T)]"
|
||||
jmp_coords = "[is_turf ? "at" : "from [a_loc] at"] [ADMIN_VERBOSEJMP(T)]"
|
||||
else
|
||||
jmp_coords = coords = "in nullspace"
|
||||
|
||||
if (tgui_alert(src, "Are you sure you want to delete:\n[D]\n[coords]?", "Confirmation", list("Yes", "No")) == "Yes")
|
||||
if (tgui_alert(usr, "Are you sure you want to delete:\n[D]\n[coords]?", "Confirmation", list("Yes", "No")) == "Yes")
|
||||
log_admin("[key_name(usr)] deleted [D] [coords]")
|
||||
message_admins("[key_name_admin(usr)] deleted [D] [jmp_coords]")
|
||||
//BLACKBOX_LOG_ADMIN_VERB("Delete")
|
||||
feedback_add_details("admin_verb","ADEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/*if(isturf(D)) //Polaris doesn't support baseturfs yet.
|
||||
var/turf/T = D
|
||||
T.ScrapeAway()
|
||||
else*/
|
||||
vv_update_display(D, "deleted", VV_MSG_DELETED)
|
||||
|
||||
// turfs are special snowflakes that'll explode if qdel'd outside ChangeTurf
|
||||
if (isturf(D))
|
||||
SEND_SIGNAL(D, COMSIG_ADMIN_DELETING, src)
|
||||
if(isturf(D))
|
||||
var/turf/T = D
|
||||
//T.ScrapeAway()
|
||||
T.ChangeTurf(world.turf)
|
||||
else
|
||||
vv_update_display(D, "deleted", VV_MSG_DELETED)
|
||||
qdel(D)
|
||||
|
||||
if(!QDELETED(D))
|
||||
vv_update_display(D, "deleted", "")
|
||||
if(!QDELETED(D))
|
||||
vv_update_display(D, "deleted", "")
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/datum/color_matrix_editor
|
||||
var/client/owner
|
||||
var/datum/weakref/target
|
||||
var/atom/movable/screen/map_view/proxy_view
|
||||
var/list/current_color
|
||||
var/closed
|
||||
|
||||
/datum/color_matrix_editor/New(user, atom/_target = null)
|
||||
owner = CLIENT_FROM_VAR(user)
|
||||
if(islist(_target?.color))
|
||||
current_color = _target.color
|
||||
else if(istext(_target?.color))
|
||||
current_color = color_hex2color_matrix(_target.color)
|
||||
else
|
||||
current_color = COLOR_MATRIX_IDENTITY
|
||||
|
||||
var/mutable_appearance/view = image('icons/testing/colortest.dmi', "colors")
|
||||
if(_target)
|
||||
target = WEAKREF(_target)
|
||||
if(!(_target.appearance_flags & PLANE_MASTER))
|
||||
view = image(_target)
|
||||
|
||||
proxy_view = new
|
||||
proxy_view.generate_view("color_matrix_proxy_[REF(src)]")
|
||||
|
||||
proxy_view.appearance = view
|
||||
proxy_view.color = current_color
|
||||
|
||||
/datum/color_matrix_editor/Destroy(force)
|
||||
QDEL_NULL(proxy_view)
|
||||
return ..()
|
||||
|
||||
/datum/color_matrix_editor/tgui_state(mob/user)
|
||||
return ADMIN_STATE(R_VAREDIT)
|
||||
|
||||
/datum/color_matrix_editor/tgui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["mapRef"] = proxy_view.assigned_map
|
||||
|
||||
return data
|
||||
|
||||
/datum/color_matrix_editor/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["currentColor"] = current_color
|
||||
|
||||
return data
|
||||
|
||||
/datum/color_matrix_editor/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ColorMatrixEditor")
|
||||
ui.open()
|
||||
proxy_view.display_to(owner.mob, ui.window)
|
||||
|
||||
/datum/color_matrix_editor/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("transition_color")
|
||||
current_color = params["color"]
|
||||
animate(proxy_view, time = 4, color = current_color)
|
||||
if("confirm")
|
||||
on_confirm()
|
||||
SStgui.close_uis(src)
|
||||
|
||||
/datum/color_matrix_editor/tgui_close(mob/user)
|
||||
. = ..()
|
||||
closed = TRUE
|
||||
|
||||
/datum/color_matrix_editor/proc/on_confirm()
|
||||
var/atom/target_atom = target?.resolve()
|
||||
if(istype(target_atom))
|
||||
target_atom.vv_edit_var("color", current_color)
|
||||
|
||||
/datum/color_matrix_editor/proc/wait()
|
||||
while(!closed)
|
||||
stoplag(1)
|
||||
|
||||
/client/proc/open_color_matrix_editor(atom/in_atom)
|
||||
var/datum/color_matrix_editor/editor = new /datum/color_matrix_editor(src, in_atom)
|
||||
editor.tgui_interact(mob)
|
||||
editor.wait()
|
||||
. = editor.current_color
|
||||
qdel(editor)
|
||||
@@ -0,0 +1,79 @@
|
||||
/// Shows a header name on top when you investigate an appearance/image
|
||||
/image/vv_get_header()
|
||||
. = list()
|
||||
var/icon_name = "<b>[icon || "null"]</b><br/>"
|
||||
. += replacetext(icon_name, "icons/obj", "") // shortens the name. We know the path already.
|
||||
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='byond://?_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
|
||||
|
||||
// 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
|
||||
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
|
||||
// Could make an argument for this but I think they will just confuse people, so yeeet
|
||||
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)
|
||||
@@ -1,77 +1,128 @@
|
||||
#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
|
||||
/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE)
|
||||
var/header
|
||||
if(DA)
|
||||
if (islist(DA))
|
||||
var/list/data_list = DA
|
||||
/// Get displayed variable in VV variable list
|
||||
/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 = data_list[name] //name is really the index until this line
|
||||
if (isnull(value))
|
||||
value = list_owner[name]
|
||||
else
|
||||
value = data_list[name]
|
||||
header = "<li>(<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_EDIT]=1;target=\ref[DA];index=[index]'>E</a>) (<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_CHANGE]=1;target=\ref[DA];index=[index]'>C</a>) (<a href='byond://?_src_=vars;[HrefToken()];[VV_HK_LIST_REMOVE]=1;target=\ref[DA];index=[index]'>-</a>) "
|
||||
name = list_owner[name] //name is really the index until this line
|
||||
. = "<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>(<a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='byond://?_src_=vars;[HrefToken()];datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='byond://?_src_=vars;[HrefToken()];datummass=\ref[DA];varnamemass=[name]'>M</a>) "
|
||||
. = "<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
|
||||
if (isnull(value))
|
||||
item = "[VV_HTML_ENCODE(name)] = <span class='value'>null</span>"
|
||||
var/name_part = VV_HTML_ENCODE(name)
|
||||
if(level > 0 || islist(owner)) //handling keys in assoc lists
|
||||
if(istype(name,/datum))
|
||||
name_part = "<a href='byond://?_src_=vars;[HrefToken()];Vars=[REF(name)]'>[VV_HTML_ENCODE(name)] [REF(name)]</a>"
|
||||
else if(islist(name))
|
||||
var/list/list_value = name
|
||||
name_part = "<a href='byond://?_src_=vars;[HrefToken()];Vars=[REF(name)]'> /list ([length(list_value)]) [REF(name)]</a>"
|
||||
|
||||
else if (istext(value))
|
||||
item = "[VV_HTML_ENCODE(name)] = <span class='value'>\"[VV_HTML_ENCODE(value)]\"</span>"
|
||||
. = "[.][name_part] = "
|
||||
|
||||
else if (isicon(value))
|
||||
var/item = _debug_variable_value(name, value, level, owner, sanitize, display_flags)
|
||||
|
||||
return "[.][item]</li>"
|
||||
|
||||
// This is split into a separate 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)
|
||||
|
||||
. = span_red("DISPLAY_ERROR:") + " ([value] [REF(value)])" // Make sure this line can never runtime
|
||||
|
||||
if(isnull(value))
|
||||
return span_value("null")
|
||||
|
||||
if(istext(value))
|
||||
return span_value("\"[VV_HTML_ENCODE(value)]\"")
|
||||
|
||||
if(isicon(value))
|
||||
#ifdef VARSICON
|
||||
var/icon/I = new/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 = "[VV_HTML_ENCODE(name)] = (<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_value("[value]") + ") <img class=icon src=\"[rname]\">"
|
||||
#else
|
||||
item = "[VV_HTML_ENCODE(name)] = /icon (<span class='value'>[value]</span>)"
|
||||
return "/icon (" + span_value("[value]") + ")"
|
||||
#endif
|
||||
|
||||
else if (isfile(value))
|
||||
item = "[VV_HTML_ENCODE(name)] = <span class='value'>'[value]'</span>"
|
||||
if(isfilter(value))
|
||||
var/datum/filter_value = value
|
||||
return "/filter (" + span_value("[filter_value.type] [REF(filter_value)]") + ")"
|
||||
|
||||
else if (istype(value, /datum))
|
||||
var/datum/D = value
|
||||
if ("[D]" != "[D.type]") //if the thing as a name var, lets use it.
|
||||
item = "<a href='byond://?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] \ref[value]</a> = [D] [D.type]"
|
||||
else
|
||||
item = "<a href='byond://?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] \ref[value]</a> = [D.type]"
|
||||
if(isfile(value))
|
||||
return span_value("'[value]'")
|
||||
|
||||
else if (islist(value))
|
||||
var/list/L = value
|
||||
if(isdatum(value))
|
||||
var/datum/datum_value = value
|
||||
return datum_value.debug_variable_value(name, level, owner, sanitize, display_flags)
|
||||
|
||||
if(islist(value) || (name in GLOB.vv_special_lists)) // Some special lists aren't detectable as a list through istype
|
||||
var/list/list_value = value
|
||||
var/list/items = list()
|
||||
|
||||
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]
|
||||
// This is because some lists either don't 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 = "<a href='byond://?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
|
||||
else
|
||||
item = "<a href='byond://?_src_=vars;[HrefToken()];Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
|
||||
return "<a href='byond://?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a><ul>[items.Join()]</ul>"
|
||||
return "<a href='byond://?_src_=vars;[HrefToken()];[link_vars]'>/list ([list_value.len])</a>"
|
||||
|
||||
else 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 = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(jointext(flags, ", "))]"
|
||||
// if it's a number, is it a bitflag?
|
||||
var/list/valid_bitflags
|
||||
if(!isnum(name))
|
||||
valid_bitflags = get_valid_bitflags(name)
|
||||
|
||||
if(!length(valid_bitflags))
|
||||
return span_value("[VV_HTML_ENCODE(value)]")
|
||||
|
||||
var/list/flags = list()
|
||||
for (var/bit_name in valid_bitflags)
|
||||
if (value & valid_bitflags[bit_name])
|
||||
flags += bit_name
|
||||
if(length(flags))
|
||||
return "[VV_HTML_ENCODE(flags.Join(", "))]"
|
||||
return "NONE"
|
||||
|
||||
/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='byond://?_src_=vars;[HrefToken()];Vars=[REF(src)]'>[src] [type] [REF(src)]</a>"
|
||||
else
|
||||
item = "[VV_HTML_ENCODE(name)] = <span class='value'>[VV_HTML_ENCODE(value)]</span>"
|
||||
return "<a href='byond://?_src_=vars;[HrefToken()];Vars=[REF(src)]'>[type] [REF(src)]</a>"
|
||||
|
||||
return "[header][item]</li>"
|
||||
/datum/weakref/debug_variable_value(name, level, datum/owner, sanitize, display_flags)
|
||||
. = ..()
|
||||
return "[.] <a href='byond://?_src_=vars;[HrefToken()];Vars=[reference]'>(Resolve)</a>"
|
||||
|
||||
/matrix/debug_variable_value(name, level, datum/owner, sanitize, display_flags)
|
||||
return span_value("\
|
||||
<table class='matrixbrak'><tbody><tr><td class='lbrak'> </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'> </td></tr></tbody></table>") //TODO link to modify_transform wrapper for all matrices
|
||||
|
||||
#undef VV_HTML_ENCODE
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/datum/filter_editor
|
||||
var/atom/target
|
||||
|
||||
/datum/filter_editor/New(atom/target)
|
||||
src.target = target
|
||||
|
||||
/datum/filter_editor/tgui_state(mob/user)
|
||||
return ADMIN_STATE(R_VAREDIT)
|
||||
|
||||
/datum/filter_editor/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Filteriffic")
|
||||
ui.open()
|
||||
|
||||
/datum/filter_editor/tgui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["filter_info"] = GLOB.master_filter_info
|
||||
return data
|
||||
|
||||
/datum/filter_editor/tgui_data()
|
||||
var/list/data = list()
|
||||
data["target_name"] = target.name
|
||||
data["target_filter_data"] = target.filter_data
|
||||
return data
|
||||
|
||||
/datum/filter_editor/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("add_filter")
|
||||
var/target_name = params["name"]
|
||||
while(target.filter_data && target.filter_data[target_name])
|
||||
target_name = "[target_name]-dupe"
|
||||
target.add_filter(target_name, params["priority"], list("type" = params["type"]))
|
||||
. = TRUE
|
||||
if("remove_filter")
|
||||
target.remove_filter(params["name"])
|
||||
. = TRUE
|
||||
if("rename_filter")
|
||||
var/list/filter_data = target.filter_data[params["name"]]
|
||||
target.remove_filter(params["name"])
|
||||
target.add_filter(params["new_name"], filter_data["priority"], filter_data)
|
||||
. = TRUE
|
||||
if("edit_filter")
|
||||
target.remove_filter(params["name"])
|
||||
target.add_filter(params["name"], params["priority"], params["new_filter"])
|
||||
. = TRUE
|
||||
if("change_priority")
|
||||
var/new_priority = params["new_priority"]
|
||||
target.change_filter_priority(params["name"], new_priority)
|
||||
. = TRUE
|
||||
if("transition_filter_value")
|
||||
target.transition_filter(params["name"], params["new_data"], 4)
|
||||
. = TRUE
|
||||
if("modify_filter_value")
|
||||
var/list/old_filter_data = target.filter_data[params["name"]]
|
||||
var/list/new_filter_data = old_filter_data.Copy()
|
||||
for(var/entry in params["new_data"])
|
||||
new_filter_data[entry] = params["new_data"][entry]
|
||||
for(var/entry in new_filter_data)
|
||||
if(entry == GLOB.master_filter_info[old_filter_data["type"]]["defaults"][entry])
|
||||
new_filter_data.Remove(entry)
|
||||
target.remove_filter(params["name"])
|
||||
target.add_filter(params["name"], old_filter_data["priority"], new_filter_data)
|
||||
. = TRUE
|
||||
if("modify_color_value")
|
||||
var/new_color = tgui_color_picker(usr, "Pick new filter color", "Filteriffic Colors!")
|
||||
if(new_color)
|
||||
target.transition_filter(params["name"], list("color" = new_color), 4)
|
||||
. = TRUE
|
||||
if("modify_icon_value")
|
||||
var/icon/new_icon = pick_and_customize_icon()
|
||||
if(new_icon)
|
||||
target.filter_data[params["name"]]["icon"] = new_icon
|
||||
target.update_filters()
|
||||
. = TRUE
|
||||
if("mass_apply")
|
||||
if(!check_rights_for(usr.client, R_FUN))
|
||||
to_chat(usr, span_userdanger("Stay in your lane, jannie."))
|
||||
return
|
||||
var/target_path = text2path(params["path"])
|
||||
if(!target_path)
|
||||
return
|
||||
var/filters_to_copy = target.filters
|
||||
var/filter_data_to_copy = target.filter_data
|
||||
var/count = 0
|
||||
for(var/thing in world.contents)
|
||||
if(istype(thing, target_path))
|
||||
var/atom/thing_at = thing
|
||||
thing_at.filters = filters_to_copy
|
||||
thing_at.filter_data = filter_data_to_copy
|
||||
count += 1
|
||||
message_admins("LOCAL CLOWN [usr.ckey] JUST MASS FILTER EDITED [count] WITH PATH OF [params["path"]]!")
|
||||
log_admin("LOCAL CLOWN [usr.ckey] JUST MASS FILTER EDITED [count] WITH PATH OF [params["path"]]!")
|
||||
@@ -1,59 +1,69 @@
|
||||
/client/proc/vv_get_class(var/var_name, var/var_value)
|
||||
/client/proc/vv_get_class(var_name, var_value)
|
||||
if(isnull(var_value))
|
||||
. = VV_NULL
|
||||
|
||||
else if (isnum(var_value))
|
||||
if (var_name in GLOB.bitfields)
|
||||
else if(isnum(var_value))
|
||||
if(length(get_valid_bitflags(var_name)))
|
||||
. = VV_BITFIELD
|
||||
else
|
||||
. = VV_NUM
|
||||
|
||||
else if (istext(var_value))
|
||||
if (findtext(var_value, "\n"))
|
||||
else if(istext(var_value))
|
||||
if(findtext(var_value, "\n"))
|
||||
. = VV_MESSAGE
|
||||
else if(findtext(var_value, GLOB.is_color))
|
||||
. = VV_COLOR
|
||||
else
|
||||
. = VV_TEXT
|
||||
|
||||
else if (isicon(var_value))
|
||||
else if(isicon(var_value))
|
||||
. = VV_ICON
|
||||
|
||||
else if (ismob(var_value))
|
||||
else if(ismob(var_value))
|
||||
. = VV_MOB_REFERENCE
|
||||
|
||||
else if (isloc(var_value))
|
||||
else if(isloc(var_value))
|
||||
. = VV_ATOM_REFERENCE
|
||||
|
||||
else if (istype(var_value, /client))
|
||||
else if(istype(var_value, /client))
|
||||
. = VV_CLIENT
|
||||
|
||||
else if (istype(var_value, /datum))
|
||||
else if(isweakref(var_value))
|
||||
. = VV_WEAKREF
|
||||
|
||||
else if(isdatum(var_value))
|
||||
. = VV_DATUM_REFERENCE
|
||||
|
||||
else if (ispath(var_value))
|
||||
if (ispath(var_value, /atom))
|
||||
else if(ispath(var_value))
|
||||
if(ispath(var_value, /atom))
|
||||
. = VV_ATOM_TYPE
|
||||
else if (ispath(var_value, /datum))
|
||||
else if(ispath(var_value, /datum))
|
||||
. = VV_DATUM_TYPE
|
||||
else
|
||||
. = VV_TYPE
|
||||
|
||||
else if (islist(var_value))
|
||||
. = VV_LIST
|
||||
else if(islist(var_value))
|
||||
if(var_name in GLOB.color_vars)
|
||||
. = VV_COLOR_MATRIX
|
||||
else
|
||||
. = VV_LIST
|
||||
|
||||
else if (isfile(var_value))
|
||||
else if(isfile(var_value))
|
||||
. = VV_FILE
|
||||
else
|
||||
. = VV_NULL
|
||||
|
||||
/client/proc/vv_get_value(class, default_class, current_value, list/restricted_classes, list/extra_classes, list/classes, var_name)
|
||||
. = list("class" = class, "value" = null)
|
||||
if (!class)
|
||||
if (!classes)
|
||||
if(!class)
|
||||
if(!classes)
|
||||
classes = list (
|
||||
VV_NUM,
|
||||
VV_TEXT,
|
||||
VV_MESSAGE,
|
||||
VV_ICON,
|
||||
VV_COLOR,
|
||||
//VV_COLOR_MATRIX,
|
||||
VV_ATOM_REFERENCE,
|
||||
VV_DATUM_REFERENCE,
|
||||
VV_MOB_REFERENCE,
|
||||
@@ -67,147 +77,187 @@
|
||||
VV_NEW_TYPE,
|
||||
VV_NEW_LIST,
|
||||
VV_NULL,
|
||||
VV_RESTORE_DEFAULT
|
||||
VV_INFINITY,
|
||||
VV_RESTORE_DEFAULT,
|
||||
VV_TEXT_LOCATE,
|
||||
VV_PROCCALL_RETVAL,
|
||||
VV_WEAKREF,
|
||||
)
|
||||
|
||||
if(holder && holder.marked_datum && !(VV_MARKED_DATUM in restricted_classes))
|
||||
classes += "[VV_MARKED_DATUM] ([holder.marked_datum.type])"
|
||||
if (restricted_classes)
|
||||
var/markstring
|
||||
if(!(VV_MARKED_DATUM in restricted_classes))
|
||||
markstring = "[VV_MARKED_DATUM] (CURRENT: [(istype(holder) && istype(holder.marked_datum))? holder.marked_datum.type : "NULL"])"
|
||||
classes += markstring
|
||||
|
||||
var/list/tagstrings = new
|
||||
if(!(VV_TAGGED_DATUM in restricted_classes) && holder && LAZYLEN(holder.tagged_datums))
|
||||
var/i = 0
|
||||
for(var/datum/iter_tagged_datum as anything in holder.tagged_datums)
|
||||
i++
|
||||
var/new_tagstring = "[VV_TAGGED_DATUM] #[i]: [iter_tagged_datum.type])"
|
||||
tagstrings[new_tagstring] = iter_tagged_datum
|
||||
classes += new_tagstring
|
||||
|
||||
if(restricted_classes)
|
||||
classes -= restricted_classes
|
||||
|
||||
if (extra_classes)
|
||||
if(extra_classes)
|
||||
classes += extra_classes
|
||||
|
||||
.["class"] = tgui_input_list(src, "What kind of data?", "Variable Type", classes, default_class)
|
||||
if (holder && holder.marked_datum && .["class"] == "[VV_MARKED_DATUM] ([holder.marked_datum.type])")
|
||||
if(holder && holder.marked_datum && .["class"] == markstring)
|
||||
.["class"] = VV_MARKED_DATUM
|
||||
|
||||
if(holder && tagstrings[.["class"]])
|
||||
var/datum/chosen_datum = tagstrings[.["class"]]
|
||||
.["value"] = chosen_datum
|
||||
.["class"] = VV_TAGGED_DATUM
|
||||
|
||||
|
||||
switch(.["class"])
|
||||
if (VV_TEXT)
|
||||
if(VV_TEXT)
|
||||
.["value"] = tgui_input_text(usr, "Enter new text:", "Text", current_value)
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
if (VV_MESSAGE)
|
||||
if(VV_MESSAGE)
|
||||
.["value"] = tgui_input_text(usr, "Enter new text:", "Text", current_value, multiline = TRUE)
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
|
||||
if (VV_NUM)
|
||||
if(VV_NUM)
|
||||
.["value"] = tgui_input_number(usr, "Enter new number:", "Num", current_value, INFINITY, -INFINITY, round_value = FALSE)
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
if (VV_BITFIELD)
|
||||
if(VV_BITFIELD)
|
||||
.["value"] = input_bitfield(usr, "Editing bitfield: [var_name]", var_name, current_value)
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
if (VV_ATOM_TYPE)
|
||||
if(VV_ATOM_TYPE)
|
||||
.["value"] = pick_closest_path(FALSE)
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
if (VV_DATUM_TYPE)
|
||||
if(VV_DATUM_TYPE)
|
||||
.["value"] = pick_closest_path(FALSE, get_fancy_list_of_datum_types())
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
if (VV_TYPE)
|
||||
if(VV_TYPE)
|
||||
var/type = current_value
|
||||
var/error = ""
|
||||
do
|
||||
type = tgui_input_text(usr, "Enter type:[error]", "Type", type)
|
||||
if (!type)
|
||||
if(!type)
|
||||
break
|
||||
type = text2path(type)
|
||||
error = "\nType not found, Please try again"
|
||||
while(!type)
|
||||
if (!type)
|
||||
if(!type)
|
||||
.["class"] = null
|
||||
return
|
||||
.["value"] = type
|
||||
|
||||
|
||||
if (VV_ATOM_REFERENCE)
|
||||
if(VV_ATOM_REFERENCE)
|
||||
var/type = pick_closest_path(FALSE)
|
||||
var/subtypes = vv_subtype_prompt(type)
|
||||
if (subtypes == null)
|
||||
if(subtypes == null)
|
||||
.["class"] = null
|
||||
return
|
||||
var/list/things = vv_reference_list(type, subtypes)
|
||||
var/value = tgui_input_list(usr, "Select reference:", "Reference", things, current_value)
|
||||
if (!value)
|
||||
if(!value)
|
||||
.["class"] = null
|
||||
return
|
||||
.["value"] = things[value]
|
||||
|
||||
if (VV_DATUM_REFERENCE)
|
||||
if(VV_DATUM_REFERENCE)
|
||||
var/type = pick_closest_path(FALSE, get_fancy_list_of_datum_types())
|
||||
var/subtypes = vv_subtype_prompt(type)
|
||||
if (subtypes == null)
|
||||
if(subtypes == null)
|
||||
.["class"] = null
|
||||
return
|
||||
var/list/things = vv_reference_list(type, subtypes)
|
||||
var/value = tgui_input_list(usr, "Select reference:", "Reference", things, current_value)
|
||||
if (!value)
|
||||
if(!value)
|
||||
.["class"] = null
|
||||
return
|
||||
.["value"] = things[value]
|
||||
|
||||
if (VV_MOB_REFERENCE)
|
||||
if(VV_MOB_REFERENCE)
|
||||
var/type = pick_closest_path(FALSE, make_types_fancy(typesof(/mob)))
|
||||
var/subtypes = vv_subtype_prompt(type)
|
||||
if (subtypes == null)
|
||||
if(subtypes == null)
|
||||
.["class"] = null
|
||||
return
|
||||
var/list/things = vv_reference_list(type, subtypes)
|
||||
var/value = tgui_input_list(usr, "Select reference:", "Reference", things, current_value)
|
||||
if (!value)
|
||||
if(!value)
|
||||
.["class"] = null
|
||||
return
|
||||
.["value"] = things[value]
|
||||
|
||||
if(VV_WEAKREF)
|
||||
var/type = pick_closest_path(FALSE, get_fancy_list_of_datum_types())
|
||||
var/subtypes = vv_subtype_prompt(type)
|
||||
if(subtypes == null)
|
||||
.["class"] = null
|
||||
return
|
||||
var/list/things = vv_reference_list(type, subtypes)
|
||||
var/value = tgui_input_list(usr, "Select reference:", "Reference", things, current_value)
|
||||
if(!value)
|
||||
.["class"] = null
|
||||
return
|
||||
.["value"] = WEAKREF(things[value])
|
||||
|
||||
|
||||
if (VV_CLIENT)
|
||||
if(VV_CLIENT)
|
||||
.["value"] = tgui_input_list(usr, "Select reference:", "Reference", GLOB.clients, current_value)
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
|
||||
if (VV_FILE)
|
||||
if(VV_FILE)
|
||||
.["value"] = input(usr, "Pick file:", "File") as null|file
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
|
||||
if (VV_ICON)
|
||||
.["value"] = input(usr, "Pick icon:", "Icon") as null|icon
|
||||
if (.["value"] == null)
|
||||
if(VV_ICON)
|
||||
.["value"] = pick_and_customize_icon(pick_only=TRUE)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
|
||||
if (VV_MARKED_DATUM)
|
||||
if(VV_MARKED_DATUM)
|
||||
.["value"] = holder.marked_datum
|
||||
if (.["value"] == null)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
if(VV_TAGGED_DATUM)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
if (VV_NEW_ATOM)
|
||||
if(VV_PROCCALL_RETVAL)
|
||||
var/list/get_retval = list()
|
||||
callproc_blocking(get_retval)
|
||||
.["value"] = get_retval[1] //should have been set in proccall!
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
if(VV_NEW_ATOM)
|
||||
var/type = pick_closest_path(FALSE)
|
||||
if (!type)
|
||||
if(!type)
|
||||
.["class"] = null
|
||||
return
|
||||
.["type"] = type
|
||||
@@ -215,9 +265,9 @@
|
||||
newguy.datum_flags |= DF_VAR_EDITED
|
||||
.["value"] = newguy
|
||||
|
||||
if (VV_NEW_DATUM)
|
||||
if(VV_NEW_DATUM)
|
||||
var/type = pick_closest_path(FALSE, get_fancy_list_of_datum_types())
|
||||
if (!type)
|
||||
if(!type)
|
||||
.["class"] = null
|
||||
return
|
||||
.["type"] = type
|
||||
@@ -225,17 +275,17 @@
|
||||
newguy.datum_flags |= DF_VAR_EDITED
|
||||
.["value"] = newguy
|
||||
|
||||
if (VV_NEW_TYPE)
|
||||
if(VV_NEW_TYPE)
|
||||
var/type = current_value
|
||||
var/error = ""
|
||||
do
|
||||
type = tgui_input_text(usr, "Enter type:[error]", "Type", type)
|
||||
if (!type)
|
||||
if(!type)
|
||||
break
|
||||
type = text2path(type)
|
||||
error = "\nType not found, Please try again"
|
||||
while(!type)
|
||||
if (!type)
|
||||
if(!type)
|
||||
.["class"] = null
|
||||
return
|
||||
.["type"] = type
|
||||
@@ -244,7 +294,52 @@
|
||||
newguy.datum_flags |= DF_VAR_EDITED
|
||||
.["value"] = newguy
|
||||
|
||||
|
||||
if (VV_NEW_LIST)
|
||||
.["value"] = list()
|
||||
if(VV_NEW_LIST)
|
||||
.["type"] = /list
|
||||
var/list/value = list()
|
||||
|
||||
var/expectation = alert("Would you like to populate the list", "Populate List?", "Yes", "No")
|
||||
if(!expectation || expectation == "No")
|
||||
.["value"] = value
|
||||
return .
|
||||
|
||||
var/list/insert = null
|
||||
while(TRUE)
|
||||
insert = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT))
|
||||
if(!insert["class"])
|
||||
break
|
||||
value += LIST_VALUE_WRAP_LISTS(insert["value"])
|
||||
|
||||
|
||||
.["value"] = value
|
||||
|
||||
if(VV_TEXT_LOCATE)
|
||||
var/datum/D
|
||||
do
|
||||
var/ref = tgui_input_text(usr, "Enter reference:", "Reference")
|
||||
if(!ref)
|
||||
break
|
||||
D = locate(ref)
|
||||
if(!D)
|
||||
tgui_alert(usr,"Invalid ref!")
|
||||
continue
|
||||
if(!D.can_vv_mark())
|
||||
tgui_alert(usr,"Datum can not be marked!")
|
||||
continue
|
||||
while(!D)
|
||||
.["type"] = D.type
|
||||
.["value"] = D
|
||||
|
||||
if(VV_COLOR)
|
||||
.["value"] = tgui_color_picker(src, "Enter new color:", "Color", current_value)
|
||||
if(.["value"] == null)
|
||||
.["class"] = null
|
||||
return
|
||||
|
||||
//if(VV_COLOR_MATRIX)
|
||||
// .["value"] = open_color_matrix_editor()
|
||||
// if(.["value"] == COLOR_MATRIX_IDENTITY) //identity is equivalent to null
|
||||
// .["class"] = null
|
||||
|
||||
if(VV_INFINITY)
|
||||
.["value"] = INFINITY
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
|
||||
// Keep these two together, they *must* be defined on both
|
||||
// If /client ever becomes /datum/client or similar, they can be merged
|
||||
/datum/proc/get_view_variables_header()
|
||||
return span_bold("[src]")
|
||||
|
||||
/atom/get_view_variables_header()
|
||||
return {"
|
||||
<a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[src];varnameedit=name'>"} + span_bold("[src]") + {"</a>
|
||||
<br>
|
||||
"} + span_small("<a href='byond://?_src_=vars;[HrefToken()];rotatedatum=\ref[src];rotatedir=left'><<</a>") + {"
|
||||
"} + span_small("<a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[src];varnameedit=dir'>[dir2text(dir)]</a>") + {"
|
||||
"} + span_small("<a href='byond://?_src_=vars;[HrefToken()];rotatedatum=\ref[src];rotatedir=right'>>></a>") + {"
|
||||
"}
|
||||
|
||||
/mob/living/get_view_variables_header()
|
||||
return {"
|
||||
<a href='byond://?_src_=vars;[HrefToken()];rename=\ref[src]'>"} + span_bold("[src]") + {"</a>
|
||||
"} + span_small("<br><a href='byond://?_src_=vars;[HrefToken()];rotatedatum=\ref[src];rotatedir=left'><<</a> <a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[src];varnameedit=dir'>[dir2text(dir)]</a> <a href='byond://?_src_=vars;[HrefToken()];rotatedatum=\ref[src];rotatedir=right'>>></a>") + {"
|
||||
"} + span_small("<br><a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[src];varnameedit=ckey'>[ckey ? ckey : "No ckey"]</a> / <a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[src];varnameedit=real_name'>[real_name ? real_name : "No real name"]</a>") + {"
|
||||
<br>
|
||||
"} + span_small("BRUTE:<a href='byond://?_src_=vars;[HrefToken()];mobToDamage=\ref[src];adjustDamage=brute'>[getBruteLoss()]</a>") + {"
|
||||
"} + span_small("FIRE:<a href='byond://?_src_=vars;[HrefToken()];mobToDamage=\ref[src];adjustDamage=fire'>[getFireLoss()]</a>") + {"
|
||||
"} + span_small("TOXIN:<a href='byond://?_src_=vars;[HrefToken()];mobToDamage=\ref[src];adjustDamage=toxin'>[getToxLoss()]</a>") + {"
|
||||
"} + span_small("OXY:<a href='byond://?_src_=vars;[HrefToken()];mobToDamage=\ref[src];adjustDamage=oxygen'>[getOxyLoss()]</a>") + {"
|
||||
"} + span_small("CLONE:<a href='byond://?_src_=vars;[HrefToken()];mobToDamage=\ref[src];adjustDamage=clone'>[getCloneLoss()]</a>") + {"
|
||||
"} + span_small("BRAIN:<a href='byond://?_src_=vars;[HrefToken()];mobToDamage=\ref[src];adjustDamage=brain'>[getBrainLoss()]</a>") + {"
|
||||
"}
|
||||
|
||||
//This entire file needs to be removed eventually
|
||||
/datum/proc/get_view_variables_options()
|
||||
return ""
|
||||
|
||||
/mob/get_view_variables_options()
|
||||
return ..() + {"
|
||||
<option value='?_src_=vars;[HrefToken()];mob_player_panel=\ref[src]'>Show player panel</option>
|
||||
<option>---</option>
|
||||
<option value='?_src_=vars;[HrefToken()];give_modifier=\ref[src]'>Give Modifier</option>
|
||||
<option value='?_src_=vars;[HrefToken()];give_wound_internal=\ref[src]'>Give Internal Bleeding</option>
|
||||
<option value='?_src_=vars;[HrefToken()];give_spell=\ref[src]'>Give Spell</option>
|
||||
<option value='?_src_=vars;[HrefToken()];give_disease2=\ref[src]'>Give Disease</option>
|
||||
<option value='?_src_=vars;[HrefToken()];give_disease=\ref[src]'>Give TG-style Disease</option>
|
||||
<option value='?_src_=vars;[HrefToken()];godmode=\ref[src]'>Toggle Godmode</option>
|
||||
<option value='?_src_=vars;[HrefToken()];build_mode=\ref[src]'>Toggle Build Mode</option>
|
||||
|
||||
<option value='?_src_=vars;[HrefToken()];ninja=\ref[src]'>Make Space Ninja</option>
|
||||
<option value='?_src_=vars;[HrefToken()];make_skeleton=\ref[src]'>Make 2spooky</option>
|
||||
|
||||
<option value='?_src_=vars;[HrefToken()];direct_control=\ref[src]'>Assume Direct Control</option>
|
||||
<option value='?_src_=vars;[HrefToken()];give_ai=\ref[src]'>Enable/Modify A.I</option>
|
||||
<option value='?_src_=vars;[HrefToken()];drop_everything=\ref[src]'>Drop Everything</option>
|
||||
|
||||
<option value='?_src_=vars;[HrefToken()];regenerateicons=\ref[src]'>Regenerate Icons</option>
|
||||
<option value='?_src_=vars;[HrefToken()];addlanguage=\ref[src]'>Add Language</option>
|
||||
<option value='?_src_=vars;[HrefToken()];remlanguage=\ref[src]'>Remove Language</option>
|
||||
<option value='?_src_=vars;[HrefToken()];addorgan=\ref[src]'>Add Organ</option>
|
||||
<option value='?_src_=vars;[HrefToken()];remorgan=\ref[src]'>Remove Organ</option>
|
||||
|
||||
<option value='?_src_=vars;[HrefToken()];fix_nano=\ref[src]'>Fix NanoUI</option>
|
||||
|
||||
<option value='?_src_=vars;[HrefToken()];addverb=\ref[src]'>Add Verb</option>
|
||||
<option value='?_src_=vars;[HrefToken()];remverb=\ref[src]'>Remove Verb</option>
|
||||
<option>---</option>
|
||||
<option value='?_src_=vars;[HrefToken()];gib=\ref[src]'>Gib</option>
|
||||
"}
|
||||
|
||||
/mob/living/carbon/human/get_view_variables_options()
|
||||
return ..() + {"
|
||||
<option value='?_src_=vars;[HrefToken()];setspecies=\ref[src]'>Set Species</option>
|
||||
<option value='?_src_=vars;[HrefToken()];makeai=\ref[src]'>Make AI</option>
|
||||
<option value='?_src_=vars;[HrefToken()];makerobot=\ref[src]'>Make cyborg</option>
|
||||
<option value='?_src_=vars;[HrefToken()];makemonkey=\ref[src]'>Make monkey</option>
|
||||
<option value='?_src_=vars;[HrefToken()];makealien=\ref[src]'>Make alien</option>
|
||||
"}
|
||||
|
||||
/obj/get_view_variables_options()
|
||||
return ..() + {"
|
||||
<option value='?_src_=vars;[HrefToken()];delall=\ref[src]'>Delete all of type</option>
|
||||
"}
|
||||
|
||||
/turf/get_view_variables_options()
|
||||
return ..() + {"
|
||||
<option value='?_src_=vars;[HrefToken()];explode=\ref[src]'>Trigger explosion</option>
|
||||
<option value='?_src_=vars;[HrefToken()];emp=\ref[src]'>Trigger EM pulse</option>
|
||||
"}
|
||||
|
||||
/obj/item/pda/get_view_variables_options()
|
||||
return ..() + {"
|
||||
<option value='?_src_=vars;[HrefToken()];fakepdapropconvo=\ref[src]'>Add Fake Prop Conversation</option>
|
||||
"}
|
||||
|
||||
/datum/proc/get_variables()
|
||||
. = vars - VV_hidden()
|
||||
if(!usr || !check_rights(R_ADMIN|R_DEBUG, FALSE))
|
||||
. -= VV_secluded()
|
||||
|
||||
/datum/proc/get_variable_value(varname)
|
||||
return vars[varname]
|
||||
|
||||
/datum/proc/set_variable_value(varname, value)
|
||||
vars[varname] = value
|
||||
|
||||
/datum/proc/get_initial_variable_value(varname)
|
||||
return initial(vars[varname])
|
||||
|
||||
/datum/proc/make_view_variables_variable_entry(var/varname, var/value, var/hide_watch = 0)
|
||||
return {"
|
||||
(<a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[src];varnameedit=[varname]'>E</a>)
|
||||
(<a href='byond://?_src_=vars;[HrefToken()];datumchange=\ref[src];varnamechange=[varname]'>C</a>)
|
||||
(<a href='byond://?_src_=vars;[HrefToken()];datummass=\ref[src];varnamemass=[varname]'>M</a>)
|
||||
[hide_watch ? "" : "(<a href='byond://?_src_=vars;[HrefToken()];datumwatch=\ref[src];varnamewatch=[varname]'>W</a>)"]
|
||||
"}
|
||||
|
||||
// No mass editing of clients
|
||||
/client/make_view_variables_variable_entry(var/varname, var/value, var/hide_watch = 0)
|
||||
return {"
|
||||
(<a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[src];varnameedit=[varname]'>E</a>)
|
||||
(<a href='byond://?_src_=vars;[HrefToken()];datumchange=\ref[src];varnamechange=[varname]'>C</a>)
|
||||
[hide_watch ? "" : "(<a href='byond://?_src_=vars;[HrefToken()];datumwatch=\ref[src];varnamewatch=[varname]'>W</a>)"]
|
||||
"}
|
||||
|
||||
// These methods are all procs and don't use stored lists to avoid VV exploits
|
||||
|
||||
// The following vars cannot be viewed by anyone
|
||||
/datum/proc/VV_hidden()
|
||||
return list()
|
||||
|
||||
// The following vars can only be viewed by R_ADMIN|R_DEBUG
|
||||
/datum/proc/VV_secluded()
|
||||
return list()
|
||||
|
||||
/datum/configuration/VV_secluded()
|
||||
return vars
|
||||
|
||||
// The following vars cannot be edited by anyone
|
||||
/datum/proc/VV_static()
|
||||
return list("parent_type")
|
||||
|
||||
/atom/VV_static()
|
||||
return ..() + list("bound_x", "bound_y", "bound_height", "bound_width", "bounds", "step_x", "step_y", "step_size")
|
||||
|
||||
/client/VV_static()
|
||||
return ..() + list("holder", "prefs")
|
||||
|
||||
/datum/admins/VV_static()
|
||||
return vars
|
||||
|
||||
// The following vars require R_DEBUG to edit
|
||||
/datum/proc/VV_locked()
|
||||
return list("vars", "cuffed")
|
||||
|
||||
/client/VV_locked()
|
||||
return list("vars", "mob")
|
||||
|
||||
/mob/VV_locked()
|
||||
return ..() + list("client")
|
||||
|
||||
// The following vars require R_FUN|R_DEBUG to edit
|
||||
/datum/proc/VV_icon_edit_lock()
|
||||
return list()
|
||||
|
||||
/atom/VV_icon_edit_lock()
|
||||
return ..() + list("icon", "icon_state", "overlays", "underlays")
|
||||
|
||||
// The following vars require R_SPAWN|R_DEBUG to edit
|
||||
/datum/proc/VV_ckey_edit()
|
||||
return list()
|
||||
|
||||
/mob/VV_ckey_edit()
|
||||
return list("key", "ckey")
|
||||
|
||||
/client/VV_ckey_edit()
|
||||
return list("key", "ckey")
|
||||
|
||||
/datum/proc/may_edit_var(var/user, var/var_to_edit) //User must be a CLIENT that is passed to this.
|
||||
if(!user)
|
||||
return FALSE
|
||||
if(ismob(user)) //Failsafe catch in case someone feeds a mob into us.
|
||||
var/mob/living = user
|
||||
user = living.client
|
||||
if(!(var_to_edit in vars))
|
||||
to_chat(user, span_warning("\The [src] does not have a var '[var_to_edit]'"))
|
||||
return FALSE
|
||||
if(var_to_edit in VV_static())
|
||||
return FALSE
|
||||
if((var_to_edit in VV_secluded()) && !check_rights_for(user, R_ADMIN|R_DEBUG))
|
||||
return FALSE
|
||||
if((var_to_edit in VV_locked()) && !check_rights_for(user, R_DEBUG))
|
||||
return FALSE
|
||||
if((var_to_edit in VV_ckey_edit()) && !check_rights_for(user, R_SPAWN|R_DEBUG))
|
||||
return FALSE
|
||||
if((var_to_edit in VV_icon_edit_lock()) && !check_rights_for(user, R_FUN|R_DEBUG))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/proc/forbidden_varedit_object_types()
|
||||
return list(
|
||||
/datum/admins //Admins editing their own admin-power object? Yup, sounds like a good idea.
|
||||
)
|
||||
@@ -0,0 +1,17 @@
|
||||
/client/proc/mark_datum(datum/D)
|
||||
if(!holder)
|
||||
return
|
||||
if(holder.marked_datum)
|
||||
holder.UnregisterSignal(holder.marked_datum, COMSIG_PARENT_QDELETING)
|
||||
vv_update_display(holder.marked_datum, "marked", "")
|
||||
holder.marked_datum = D
|
||||
holder.RegisterSignal(holder.marked_datum, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/datum/admins, handle_marked_del))
|
||||
vv_update_display(D, "marked", VV_MSG_MARKED)
|
||||
|
||||
ADMIN_VERB_ONLY_CONTEXT_MENU(mark_datum, R_HOLDER, "Mark Object", datum/target as mob|obj|turf|area in view())
|
||||
user.mark_datum(target)
|
||||
|
||||
/datum/admins/proc/handle_marked_del(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(marked_datum, COMSIG_PARENT_QDELETING)
|
||||
marked_datum = null
|
||||
@@ -1,29 +1,29 @@
|
||||
/client/proc/cmd_mass_modify_object_variables(atom/A, var_name)
|
||||
set category = "Debug"
|
||||
set name = "Mass Edit Variables"
|
||||
set desc="(target) Edit all instances of a target item's variables"
|
||||
|
||||
var/method = 0 //0 means strict type detection while 1 means this type and all subtypes (IE: /obj/item with this set to 1 will set it to ALL items)
|
||||
/client/proc/cmd_mass_modify_object_variables(datum/target, var_name)
|
||||
if(tgui_alert(src, "Are you sure you'd like to mass-modify every instance of the [var_name] variable? This can break everything if you do not know what you are doing.", "Slow down, chief!", list("Yes", "No"), 60 SECONDS) != "Yes")
|
||||
return
|
||||
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
|
||||
if(A && A.type)
|
||||
method = vv_subtype_prompt(A.type)
|
||||
/// if false get only the strict type, get all subtypes too otherwise
|
||||
var/strict_type = FALSE
|
||||
if(target?.type)
|
||||
strict_type = vv_subtype_prompt(target.type)
|
||||
|
||||
src.massmodify_variables(A, var_name, method)
|
||||
massmodify_variables(target, var_name, strict_type)
|
||||
feedback_add_details("admin_verb","MVV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
//BLACKBOX_LOG_ADMIN_VERB("Mass Edit Variables")
|
||||
|
||||
/client/proc/massmodify_variables(datum/O, var_name = "", method = 0)
|
||||
/client/proc/massmodify_variables(datum/target, var_name = "", strict_type = FALSE)
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
if(!istype(O))
|
||||
if(!istype(target))
|
||||
return
|
||||
|
||||
var/variable = ""
|
||||
if(!var_name)
|
||||
var/list/names = list()
|
||||
for (var/V in O.vars)
|
||||
for (var/V in target.vars)
|
||||
names += V
|
||||
|
||||
names = sortList(names)
|
||||
@@ -32,13 +32,13 @@
|
||||
else
|
||||
variable = var_name
|
||||
|
||||
if(!variable || !O.can_vv_get(variable))
|
||||
if(!variable || !target.can_vv_get(variable))
|
||||
return
|
||||
var/default
|
||||
var/var_value = O.vars[variable]
|
||||
var/var_value = target.vars[variable]
|
||||
|
||||
if(variable in GLOB.VVckey_edit)
|
||||
to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.")
|
||||
to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.", confidential = TRUE)
|
||||
return
|
||||
if(variable in GLOB.VVlocked)
|
||||
if(!check_rights(R_DEBUG))
|
||||
@@ -49,18 +49,18 @@
|
||||
if(variable in GLOB.VVpixelmovement)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
var/prompt = tgui_alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", list("ABORT","Continue","ABORT"))
|
||||
var/prompt = tgui_alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", list("ABORT ", "Continue", " ABORT"))
|
||||
if (prompt != "Continue")
|
||||
return
|
||||
|
||||
default = vv_get_class(variable, var_value)
|
||||
|
||||
if(isnull(default))
|
||||
to_chat(src, "Unable to determine variable type.")
|
||||
to_chat(src, "Unable to determine variable type.", confidential = TRUE)
|
||||
else
|
||||
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
|
||||
to_chat(src, "Variable appears to be " + span_bold("[uppertext(default)]") + ".", confidential = TRUE)
|
||||
|
||||
to_chat(src, "Variable contains: [var_value]")
|
||||
to_chat(src, "Variable contains: [var_value]", confidential = TRUE)
|
||||
|
||||
if(default == VV_NUM)
|
||||
var/dir_text = ""
|
||||
@@ -75,7 +75,7 @@
|
||||
dir_text += "WEST"
|
||||
|
||||
if(dir_text)
|
||||
to_chat(src, "If a direction, direction is: [dir_text]")
|
||||
to_chat(src, "If a direction, direction is: [dir_text]", confidential = TRUE)
|
||||
|
||||
var/value = vv_get_value(default_class = default)
|
||||
var/new_value = value["value"]
|
||||
@@ -90,16 +90,16 @@
|
||||
if (value["type"])
|
||||
class = VV_NEW_TYPE
|
||||
|
||||
var/original_name = "[O]"
|
||||
var/original_name = "[target]"
|
||||
|
||||
var/rejected = 0
|
||||
var/accepted = 0
|
||||
|
||||
switch(class)
|
||||
if(VV_RESTORE_DEFAULT)
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
to_chat(src, "Finding items...", confidential = TRUE)
|
||||
var/list/items = get_all_of_type(target.type, strict_type)
|
||||
to_chat(src, "Changing [items.len] items...", confidential = TRUE)
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
@@ -111,23 +111,21 @@
|
||||
CHECK_TICK
|
||||
|
||||
if(VV_TEXT)
|
||||
var/list/varsvars = vv_parse_text(O, new_value)
|
||||
var/list/varsvars = vv_parse_text(target, new_value)
|
||||
var/pre_processing = new_value
|
||||
var/unique
|
||||
if (varsvars && varsvars.len)
|
||||
unique = tgui_alert(usr, "Process vars unique to each instance, or same for all?", "Variable Association", list("Unique", "Same"))
|
||||
if(!unique)
|
||||
return
|
||||
if (varsvars?.len)
|
||||
unique = tgui_alert(src, "Process vars unique to each instance, or same for all?", "Variable Association", list("Unique", "Same"))
|
||||
if(unique == "Unique")
|
||||
unique = TRUE
|
||||
else
|
||||
unique = FALSE
|
||||
for(var/V in varsvars)
|
||||
new_value = replacetext(new_value,"\[[V]]","[O.vars[V]]")
|
||||
new_value = replacetext(new_value,"\[[V]]","[target.vars[V]]")
|
||||
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
to_chat(src, "Finding items...", confidential = TRUE)
|
||||
var/list/items = get_all_of_type(target.type, strict_type)
|
||||
to_chat(src, "Changing [items.len] items...", confidential = TRUE)
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
@@ -145,7 +143,7 @@
|
||||
|
||||
if (VV_NEW_TYPE)
|
||||
var/many = tgui_alert(src, "Create only one [value["type"]] and assign each or a new one for each thing", "How Many", list("One", "Many", "Cancel"))
|
||||
if (!many || many == "Cancel")
|
||||
if (many == "Cancel")
|
||||
return
|
||||
if (many == "Many")
|
||||
many = TRUE
|
||||
@@ -153,9 +151,9 @@
|
||||
many = FALSE
|
||||
|
||||
var/type = value["type"]
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
to_chat(src, "Finding items...", confidential = TRUE)
|
||||
var/list/items = get_all_of_type(target.type, strict_type)
|
||||
to_chat(src, "Changing [items.len] items...", confidential = TRUE)
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
@@ -171,9 +169,9 @@
|
||||
CHECK_TICK
|
||||
|
||||
else
|
||||
to_chat(src, "Finding items...")
|
||||
var/list/items = get_all_of_type(O.type, method)
|
||||
to_chat(src, "Changing [items.len] items...")
|
||||
to_chat(src, "Finding items...", confidential = TRUE)
|
||||
var/list/items = get_all_of_type(target.type, strict_type)
|
||||
to_chat(src, "Changing [items.len] items...", confidential = TRUE)
|
||||
for(var/thing in items)
|
||||
if (!thing)
|
||||
continue
|
||||
@@ -187,27 +185,27 @@
|
||||
|
||||
var/count = rejected+accepted
|
||||
if (!count)
|
||||
to_chat(src, "No objects found")
|
||||
to_chat(src, "No objects found", confidential = TRUE)
|
||||
return
|
||||
if (!accepted)
|
||||
to_chat(src, "Every object rejected your edit")
|
||||
to_chat(src, "Every object rejected your edit", confidential = TRUE)
|
||||
return
|
||||
if (rejected)
|
||||
to_chat(src, "[rejected] out of [count] objects rejected your edit")
|
||||
to_chat(src, "[rejected] out of [count] objects rejected your edit", confidential = TRUE)
|
||||
|
||||
log_world("### MassVarEdit by [src]: [O.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[O.vars[variable]]")]([list2params(value)])")
|
||||
log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)")
|
||||
message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)")
|
||||
log_world("### MassVarEdit by [src]: [target.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[target.vars[variable]]")]([list2params(value)])")
|
||||
log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [target.vars[variable]] ([accepted] objects modified)")
|
||||
message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [target.vars[variable]] ([accepted] objects modified)")
|
||||
|
||||
|
||||
/proc/get_all_of_type(var/T, subtypes = TRUE)
|
||||
//not using global lists as vv is a debug function and debug functions should rely on as less things as possible.
|
||||
/proc/get_all_of_type(T, subtypes = TRUE)
|
||||
var/list/typecache = list()
|
||||
typecache[T] = 1
|
||||
if (subtypes)
|
||||
typecache = typecacheof(typecache)
|
||||
. = list()
|
||||
if (ispath(T, /mob))
|
||||
for(var/mob/thing in mob_list)
|
||||
for(var/mob/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
@@ -219,7 +217,13 @@
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /obj/machinery))
|
||||
for(var/obj/machinery/thing in GLOB.machines)
|
||||
for(var/obj/machinery/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
else if (ispath(T, /obj/item))
|
||||
for(var/obj/item/thing in world)
|
||||
if (typecache[thing.type])
|
||||
. += thing
|
||||
CHECK_TICK
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
GLOBAL_LIST_INIT(VVlocked, list("vars", "datum_flags", "client", "mob")) //Requires DEBUG
|
||||
GLOBAL_LIST_INIT(VVlocked, list("vars", "datum_flags", "client", "mob")) //Requires DEBUG
|
||||
GLOBAL_PROTECT(VVlocked)
|
||||
GLOBAL_LIST_INIT(VVicon_edit_lock, list("icon", "icon_state", "overlays", "underlays")) //Requires DEBUG or FUN
|
||||
GLOBAL_LIST_INIT(VVicon_edit_lock, list("icon", "icon_state", "overlays", "underlays")) //Requires DEBUG or FUN
|
||||
GLOBAL_PROTECT(VVicon_edit_lock)
|
||||
GLOBAL_LIST_INIT(VVckey_edit, list("key", "ckey")) //Requires DEBUG or SPAWN
|
||||
GLOBAL_LIST_INIT(VVckey_edit, list("key", "ckey")) //Requires DEBUG or SPAWN
|
||||
GLOBAL_PROTECT(VVckey_edit)
|
||||
GLOBAL_LIST_INIT(VVpixelmovement, list("bound_x", "bound_y", "step_x", "step_y", "step_size", "bound_height", "bound_width", "bounds")) //No editing ever.
|
||||
GLOBAL_LIST_INIT(VVpixelmovement, list("bound_x", "bound_y", "step_x", "step_y", "step_size", "bound_height", "bound_width", "bounds")) //No editing ever.
|
||||
GLOBAL_PROTECT(VVpixelmovement)
|
||||
|
||||
/client/proc/vv_parse_text(O, new_var)
|
||||
@@ -17,14 +17,14 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
//FALSE = no subtypes, strict exact type pathing (or the type doesn't have subtypes)
|
||||
//TRUE = Yes subtypes
|
||||
//NULL = User cancelled at the prompt or invalid type given
|
||||
/client/proc/vv_subtype_prompt(var/type)
|
||||
/client/proc/vv_subtype_prompt(type)
|
||||
if (!ispath(type))
|
||||
return
|
||||
var/list/subtypes = subtypesof(type)
|
||||
if (!subtypes || !subtypes.len)
|
||||
return FALSE
|
||||
if (subtypes && subtypes.len)
|
||||
switch(tgui_alert(usr, "Strict object type detection?", "Type detection", list("Strictly this type", "This type and subtypes", "Cancel")))
|
||||
if (subtypes?.len)
|
||||
switch(tgui_alert(usr,"Strict object type detection?", "Type detection", list("Strictly this type","This type and subtypes", "Cancel")))
|
||||
if("Strictly this type")
|
||||
return FALSE
|
||||
if("This type and subtypes")
|
||||
@@ -46,25 +46,25 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
var/things = get_all_of_type(type, subtypes)
|
||||
|
||||
var/i = 0
|
||||
for(var/datum/D as anything in things)
|
||||
for(var/thing in things)
|
||||
var/datum/D = thing
|
||||
i++
|
||||
//try one of 3 methods to shorten the type text:
|
||||
// fancy type,
|
||||
// fancy type with the base type removed from the begaining,
|
||||
// the type with the base type removed from the begaining
|
||||
// fancy type,
|
||||
// fancy type with the base type removed from the begaining,
|
||||
// the type with the base type removed from the begaining
|
||||
var/fancytype = types[D.type]
|
||||
if (findtext(fancytype, types[type]))
|
||||
fancytype = copytext(fancytype, length(types[type])+1)
|
||||
var/shorttype = copytext("[D.type]", length("[type]")+1)
|
||||
if (length(shorttype) > length(fancytype))
|
||||
fancytype = copytext(fancytype, length(types[type]) + 1)
|
||||
var/shorttype = copytext("[D.type]", length("[type]") + 1)
|
||||
if (length_char(shorttype) > length_char(fancytype))
|
||||
shorttype = fancytype
|
||||
if (!length(shorttype))
|
||||
shorttype = "/"
|
||||
|
||||
.["[D]([shorttype])\ref[D]#[i]"] = D
|
||||
.["[D]([shorttype])[REF(D)]#[i]"] = D
|
||||
|
||||
/client/proc/mod_list_add_ass(atom/O) //hehe
|
||||
|
||||
var/list/L = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT))
|
||||
var/class = L["class"]
|
||||
if (!class)
|
||||
@@ -94,15 +94,14 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
if (O)
|
||||
L = L.Copy()
|
||||
|
||||
L += var_value
|
||||
L += list(var_value) //var_value could be a list
|
||||
|
||||
if(IS_VALID_ASSOC_KEY(var_value))
|
||||
switch(tgui_alert(usr, "Would you like to associate a value with the list entry?","List VV",list("Yes","No")))
|
||||
if("Yes")
|
||||
L[var_value] = mod_list_add_ass(O) //hehe
|
||||
switch(tgui_alert(usr,"Would you like to associate a value with the list entry?",,list("Yes","No")))
|
||||
if("Yes")
|
||||
L[var_value] = mod_list_add_ass(O) //hehe
|
||||
if (O)
|
||||
if (O.vv_edit_var(objectvar, L) == FALSE)
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
to_chat(src, "Your edit was rejected by the object.", confidential = TRUE)
|
||||
return
|
||||
log_world("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: ADDED=[var_value]")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: ADDED=[var_value]")
|
||||
@@ -112,27 +111,26 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
if(!istype(L, /list))
|
||||
to_chat(src, "Not a List.")
|
||||
to_chat(src, "Not a List.", confidential = TRUE)
|
||||
return
|
||||
|
||||
if(L.len > 1000)
|
||||
var/confirm = tgui_alert(src, "The list you're trying to edit is very long, continuing may crash the server.", "Long List!", list("Warning", "Continue", "Abort"))
|
||||
var/confirm = tgui_alert(usr, "The list you're trying to edit is very long, continuing may crash the server.", "Warning", list("Continue", "Abort"))
|
||||
if(confirm != "Continue")
|
||||
return
|
||||
|
||||
|
||||
|
||||
var/is_normal_list = IS_NORMAL_LIST(L)
|
||||
var/list/names = list()
|
||||
for (var/i in 1 to L.len)
|
||||
var/key = L[i]
|
||||
var/value
|
||||
if (IS_NORMAL_LIST(L) && !isnum(key))
|
||||
if (is_normal_list && !isnum(key))
|
||||
value = L[key]
|
||||
if (value == null)
|
||||
value = "null"
|
||||
names["#[i] [key] = [value]"] = i
|
||||
if (!index)
|
||||
var/variable = tgui_input_list(usr, "Which var?","Var", names + "(ADD VAR)" + "(CLEAR NULLS)" + "(CLEAR DUPES)" + "(SHUFFLE)")
|
||||
var/variable = tgui_input_list(usr, "Which var?", "Var", names + "(ADD VAR)" + "(CLEAR NULLS)" + "(CLEAR DUPES)" + "(SHUFFLE)")
|
||||
|
||||
if(variable == null)
|
||||
return
|
||||
@@ -143,9 +141,9 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
|
||||
if(variable == "(CLEAR NULLS)")
|
||||
L = L.Copy()
|
||||
listclearnulls(L)
|
||||
list_clear_nulls(L)
|
||||
if (!O.vv_edit_var(objectvar, L))
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
to_chat(src, "Your edit was rejected by the object.", confidential = TRUE)
|
||||
return
|
||||
log_world("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR NULLS")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR NULLS")
|
||||
@@ -155,7 +153,7 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
if(variable == "(CLEAR DUPES)")
|
||||
L = uniqueList(L)
|
||||
if (!O.vv_edit_var(objectvar, L))
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
to_chat(src, "Your edit was rejected by the object.", confidential = TRUE)
|
||||
return
|
||||
log_world("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR DUPES")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR DUPES")
|
||||
@@ -165,7 +163,7 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
if(variable == "(SHUFFLE)")
|
||||
L = shuffle(L)
|
||||
if (!O.vv_edit_var(objectvar, L))
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
to_chat(src, "Your edit was rejected by the object.", confidential = TRUE)
|
||||
return
|
||||
log_world("### ListVarEdit by [src]: [O.type] [objectvar]: SHUFFLE")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: SHUFFLE")
|
||||
@@ -179,32 +177,32 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
if (index == null)
|
||||
return
|
||||
var/assoc = 0
|
||||
if(IS_VALID_ASSOC_KEY(L[index]))
|
||||
var/prompt = tgui_alert(src, "Do you want to edit the key or its assigned value?", "Associated List", list("Key", "Assigned Value", "Cancel"))
|
||||
if (!prompt || prompt == "Cancel")
|
||||
return
|
||||
if (prompt == "Assigned Value")
|
||||
assoc = 1
|
||||
assoc_key = L[index]
|
||||
var/prompt = tgui_alert(usr, "Do you want to edit the key or its assigned value?", "Associated List", list("Key", "Assigned Value", "Cancel"))
|
||||
if (prompt == "Cancel")
|
||||
return
|
||||
if (prompt == "Assigned Value")
|
||||
assoc = 1
|
||||
assoc_key = L[index]
|
||||
var/default
|
||||
var/variable
|
||||
var/old_assoc_value //EXPERIMENTAL - Keep old associated value while modifying key, if any
|
||||
if (assoc)
|
||||
variable = L[assoc_key]
|
||||
else
|
||||
variable = L[index]
|
||||
//EXPERIMENTAL - Keep old associated value while modifying key, if any
|
||||
if(IS_VALID_ASSOC_KEY(variable))
|
||||
var/found = L[variable]
|
||||
if(!isnull(found))
|
||||
old_assoc_value = found
|
||||
//
|
||||
var/old_assoc_value //EXPERIMENTAL - Keep old associated value while modifying key, if any
|
||||
if(is_normal_list)
|
||||
if (assoc)
|
||||
variable = L[assoc_key]
|
||||
else
|
||||
variable = L[index]
|
||||
//EXPERIMENTAL - Keep old associated value while modifying key, if any
|
||||
if(IS_VALID_ASSOC_KEY(variable))
|
||||
var/found = L[variable]
|
||||
if(!isnull(found))
|
||||
old_assoc_value = found
|
||||
//
|
||||
|
||||
default = vv_get_class(objectvar, variable)
|
||||
|
||||
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
|
||||
to_chat(src, "Variable appears to be " + span_bold("[uppertext(default)]") + ".", confidential = TRUE)
|
||||
|
||||
to_chat(src, "Variable contains: [variable]")
|
||||
to_chat(src, "Variable contains: [variable]", confidential = TRUE)
|
||||
|
||||
if(default == VV_NUM)
|
||||
var/dir_text = ""
|
||||
@@ -220,7 +218,7 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
dir_text += "WEST"
|
||||
|
||||
if(dir_text)
|
||||
to_chat(usr, "If a direction, direction is: [dir_text]")
|
||||
to_chat(usr, "If a direction, direction is: [dir_text]", confidential = TRUE)
|
||||
|
||||
var/original_var = variable
|
||||
|
||||
@@ -248,7 +246,7 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
L.Cut(index, index+1)
|
||||
if (O)
|
||||
if (O.vv_edit_var(objectvar, L))
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
to_chat(src, "Your edit was rejected by the object.", confidential = TRUE)
|
||||
return
|
||||
log_world("### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[original_var]")]")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]")
|
||||
@@ -261,15 +259,16 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
new_var = replacetext(new_var,"\[[V]]","[O.vars[V]]")
|
||||
|
||||
|
||||
if(assoc)
|
||||
L[assoc_key] = new_var
|
||||
else
|
||||
L[index] = new_var
|
||||
if(!isnull(old_assoc_value) && IS_VALID_ASSOC_KEY(new_var))
|
||||
L[new_var] = old_assoc_value
|
||||
if(is_normal_list)
|
||||
if(assoc)
|
||||
L[assoc_key] = new_var
|
||||
else
|
||||
L[index] = new_var
|
||||
if(!isnull(old_assoc_value) && IS_VALID_ASSOC_KEY(new_var))
|
||||
L[new_var] = old_assoc_value
|
||||
if (O)
|
||||
if (O.vv_edit_var(objectvar, L) == FALSE)
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
to_chat(src, "Your edit was rejected by the object.", confidential = TRUE)
|
||||
return
|
||||
log_world("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: [original_var]=[new_var]")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]")
|
||||
@@ -297,7 +296,7 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
|
||||
if(param_var_name)
|
||||
if(!(param_var_name in O.vars))
|
||||
to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])")
|
||||
to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])", confidential = TRUE)
|
||||
return
|
||||
variable = param_var_name
|
||||
|
||||
@@ -308,17 +307,10 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
|
||||
names = sortList(names)
|
||||
|
||||
variable = tgui_input_list(usr, "Which var?","Var", names)
|
||||
variable = tgui_input_list(usr, "Which var?", "Var", names)
|
||||
if(!variable)
|
||||
return
|
||||
|
||||
if(variable in GLOB.VVpixelmovement)
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
var/prompt = tgui_alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", list("ABORT","Continue","ABORT"))
|
||||
if (prompt != "Continue")
|
||||
return
|
||||
|
||||
if(!O.can_vv_get(variable))
|
||||
return
|
||||
|
||||
@@ -329,11 +321,11 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
var/default = vv_get_class(variable, var_value)
|
||||
|
||||
if(isnull(default))
|
||||
to_chat(src, "Unable to determine variable type.")
|
||||
to_chat(src, "Unable to determine variable type.", confidential = TRUE)
|
||||
else
|
||||
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
|
||||
to_chat(src, "Variable appears to be " + span_bold("[uppertext(default)]") + ".", confidential = TRUE)
|
||||
|
||||
to_chat(src, "Variable contains: [var_value]")
|
||||
to_chat(src, "Variable contains: [var_value]", confidential = TRUE)
|
||||
|
||||
if(default == VV_NUM)
|
||||
var/dir_text = ""
|
||||
@@ -348,7 +340,7 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
dir_text += "WEST"
|
||||
|
||||
if(dir_text)
|
||||
to_chat(src, "If a direction, direction is: [dir_text]")
|
||||
to_chat(src, "If a direction, direction is: [dir_text]", confidential = TRUE)
|
||||
|
||||
if(autodetect_class && default != VV_NULL)
|
||||
if (default == VV_TEXT)
|
||||
@@ -385,9 +377,10 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
|
||||
|
||||
if (O.vv_edit_var(variable, var_new) == FALSE)
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
to_chat(src, "Your edit was rejected by the object.", confidential = TRUE)
|
||||
return
|
||||
vv_update_display(O, "varedited", VV_MSG_EDITED)
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_VAR_EDIT, args)
|
||||
log_world("### VarEdit by [key_name(src)]: [O.type] [variable]=[var_value] => [var_new]")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [variable] from [html_encode("[var_value]")] to [html_encode("[var_new]")]")
|
||||
var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] from [var_value] to [var_new]"
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
/**
|
||||
* ## nobody wants to learn matrix math!
|
||||
*
|
||||
* More than just a completely true statement, this datum is created as a tgui interface
|
||||
* allowing you to modify each vector until you know what you're doing.
|
||||
* Much like filteriffic, 'nobody wants to learn matrix math' is meant for developers like you and I
|
||||
* to implement interesting matrix transformations without the hassle if needing to know... algebra? Damn, i'm stupid.
|
||||
*/
|
||||
/datum/nobody_wants_to_learn_matrix_math
|
||||
var/atom/target
|
||||
var/matrix/testing_matrix
|
||||
|
||||
/datum/nobody_wants_to_learn_matrix_math/New(atom/target)
|
||||
src.target = target
|
||||
testing_matrix = matrix(target.transform)
|
||||
|
||||
/datum/nobody_wants_to_learn_matrix_math/Destroy(force)
|
||||
QDEL_NULL(testing_matrix)
|
||||
return ..()
|
||||
|
||||
/datum/nobody_wants_to_learn_matrix_math/tgui_state(mob/user)
|
||||
return ADMIN_STATE(R_VAREDIT)
|
||||
|
||||
/datum/nobody_wants_to_learn_matrix_math/tgui_close(mob/user)
|
||||
qdel(src)
|
||||
|
||||
/datum/nobody_wants_to_learn_matrix_math/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "MatrixMathTester")
|
||||
ui.open()
|
||||
|
||||
/datum/nobody_wants_to_learn_matrix_math/tgui_data()
|
||||
var/list/data = list()
|
||||
data["matrix_a"] = testing_matrix.a
|
||||
data["matrix_b"] = testing_matrix.b
|
||||
data["matrix_c"] = testing_matrix.c
|
||||
data["matrix_d"] = testing_matrix.d
|
||||
data["matrix_e"] = testing_matrix.e
|
||||
data["matrix_f"] = testing_matrix.f
|
||||
data["pixelated"] = target.appearance_flags & PIXEL_SCALE
|
||||
return data
|
||||
|
||||
/datum/nobody_wants_to_learn_matrix_math/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("change_var")
|
||||
var/matrix_var_name = params["var_name"]
|
||||
var/matrix_var_value = params["var_value"]
|
||||
if(testing_matrix.vv_edit_var(matrix_var_name, matrix_var_value) == FALSE)
|
||||
to_chat(src, "Your edit was rejected by the object. This is a bug with the matrix tester, not your fault, so report it on GitHub.", confidential = TRUE)
|
||||
return
|
||||
set_transform()
|
||||
if("scale")
|
||||
testing_matrix.Scale(params["x"], params["y"])
|
||||
set_transform()
|
||||
if("translate")
|
||||
testing_matrix.Translate(params["x"], params["y"])
|
||||
set_transform()
|
||||
if("shear")
|
||||
testing_matrix.Shear(params["x"], params["y"])
|
||||
set_transform()
|
||||
if("turn")
|
||||
testing_matrix.Turn(params["angle"])
|
||||
set_transform()
|
||||
if("toggle_pixel")
|
||||
target.appearance_flags ^= PIXEL_SCALE
|
||||
|
||||
/datum/nobody_wants_to_learn_matrix_math/proc/set_transform()
|
||||
animate(target, transform = testing_matrix, time = 0.5 SECONDS)
|
||||
testing_matrix = matrix(target.transform)
|
||||
|
||||
/client/proc/open_matrix_tester(atom/in_atom)
|
||||
if(holder)
|
||||
var/datum/nobody_wants_to_learn_matrix_math/matrix_tester = new(in_atom)
|
||||
matrix_tester.tgui_interact(mob)
|
||||
@@ -0,0 +1,212 @@
|
||||
/datum/particle_editor
|
||||
/// movable whose particles we want to be editing
|
||||
var/atom/movable/target
|
||||
|
||||
/datum/particle_editor/New(atom/target)
|
||||
src.target = target
|
||||
|
||||
/datum/particle_editor/tgui_state(mob/user)
|
||||
return ADMIN_STATE(R_VAREDIT)
|
||||
|
||||
/datum/particle_editor/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ParticleEdit")
|
||||
ui.open()
|
||||
|
||||
/datum/particle_editor/ui_assets(mob/user)
|
||||
. = ..()
|
||||
. += get_asset_datum(/datum/asset/simple/particle_editor)
|
||||
|
||||
///returns ui_data values for the particle editor
|
||||
/particles/proc/return_ui_representation(mob/user)
|
||||
var/data = list()
|
||||
//affect entire set: no generators
|
||||
data["width"] = width //float
|
||||
data["height"] = height //float
|
||||
data["count"] = count //float
|
||||
data["spawning"] = spawning //float
|
||||
data["bound1"] = islist(bound1) ? bound1 : list(bound1,bound1,bound1) //float OR list(x, y, z)
|
||||
data["bound2"] = islist(bound2) ? bound2 : list(bound2,bound2,bound2) //float OR list(x, y, z)
|
||||
data["gravity"] = gravity //list(x, y, z)
|
||||
|
||||
var/list/tgui_grad_list = list()
|
||||
for(var/entry in gradient)
|
||||
if(entry == "space")
|
||||
tgui_grad_list += list(list("[entry]" = gradient[entry])) // package this thing else json encoding breaks
|
||||
continue
|
||||
tgui_grad_list += entry
|
||||
data["gradient"] = tgui_grad_list //gradient array list(number, string, number, string, "loop", "space"=COLORSPACE_RGB)
|
||||
|
||||
data["transform"] = transform //list(a, b, c, d, e, f) OR list(xx,xy,xz, yx,yy,yz, zx,zy,zz) OR list(xx,xy,xz, yx,yy,yz, zx,zy,zz, cx,cy,cz) OR list(xx,xy,xz,xw, yx,yy,yz,yw, zx,zy,zz,zw, wx,wy,wz,ww)
|
||||
|
||||
//applied on spawn
|
||||
if(islist(icon))
|
||||
var/list/icon_data = list()
|
||||
for(var/file in icon)
|
||||
icon_data["[file]"] = icon[file]
|
||||
data["icon"] = icon_data
|
||||
else
|
||||
data["icon"] = "[icon]" //list(icon = weight) OR file reference
|
||||
data["icon_state"] = icon_state // list(icon_state = weight) OR string
|
||||
if(isgenerator(lifespan))
|
||||
data["lifespan"] = return_generator_args(lifespan)
|
||||
else
|
||||
data["lifespan"] = lifespan //float
|
||||
if(isgenerator(fade))
|
||||
data["fade"] = return_generator_args(fade)
|
||||
else
|
||||
data["fade"] = fade //float
|
||||
if(isgenerator(fadein))
|
||||
data["fadein"] = return_generator_args(fadein)
|
||||
else
|
||||
data["fadein"] = fadein //float
|
||||
if(isgenerator(color))
|
||||
data["color"] = return_generator_args(color)
|
||||
else
|
||||
data["color"] = color //float OR string
|
||||
if(isgenerator(color_change))
|
||||
data["color_change"] = return_generator_args(color_change)
|
||||
else
|
||||
data["color_change"] = color_change //float
|
||||
if(isgenerator(position))
|
||||
data["position"] = return_generator_args(position)
|
||||
else
|
||||
data["position"] = position //list(x,y) OR list(x,y,z)
|
||||
if(isgenerator(velocity))
|
||||
data["velocity"] = return_generator_args(velocity)
|
||||
else
|
||||
data["velocity"] = velocity //list(x,y) OR list(x,y,z)
|
||||
if(isgenerator(scale))
|
||||
data["scale"] = return_generator_args(scale)
|
||||
else
|
||||
data["scale"] = scale
|
||||
if(isgenerator(grow))
|
||||
data["grow"] = return_generator_args(grow)
|
||||
else
|
||||
data["grow"] = grow //float OR list(x,y)
|
||||
if(isgenerator(rotation))
|
||||
data["rotation"] = return_generator_args(rotation)
|
||||
else
|
||||
data["rotation"] = rotation
|
||||
if(isgenerator(spin))
|
||||
data["spin"] = return_generator_args(spin)
|
||||
else
|
||||
data["spin"] = spin //float
|
||||
if(isgenerator(friction))
|
||||
data["friction"] = return_generator_args(friction)
|
||||
else
|
||||
data["friction"] = friction //float: 0-1
|
||||
|
||||
//evaluated every tick
|
||||
if(isgenerator(drift))
|
||||
data["drift"] = return_generator_args(drift)
|
||||
else
|
||||
data["drift"] = drift
|
||||
return data
|
||||
|
||||
/datum/particle_editor/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["target_name"] = target.name
|
||||
if(!target.particles)
|
||||
target.particles = new /particles
|
||||
data["particle_data"] = target.particles.return_ui_representation(user)
|
||||
return data
|
||||
|
||||
/datum/particle_editor/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("delete_and_close")
|
||||
ui.close()
|
||||
target.particles = null
|
||||
target = null
|
||||
. = FALSE
|
||||
if("new_type")
|
||||
var/new_type = pick_closest_path(/particles, make_types_fancy(typesof(/particles)))
|
||||
if(!new_type)
|
||||
return FALSE
|
||||
target.particles = new new_type
|
||||
target.particles.datum_flags |= DF_VAR_EDITED
|
||||
. = TRUE
|
||||
if("transform_size")
|
||||
var/list/matrix_size = list("Simple Matrix" = 6, "Complex Matrix" = 12, "Projection Matrix" = 16)
|
||||
var/new_size = matrix_size[params["new_value"]]
|
||||
if(!new_size)
|
||||
return FALSE
|
||||
. = TRUE
|
||||
target.particles.datum_flags |= DF_VAR_EDITED
|
||||
if(!target.particles.transform || length(target.particles.transform) != new_size)
|
||||
switch(new_size)
|
||||
if(6)
|
||||
target.particles.transform = list(1,0,0, 1,0,0) // TRANSFORM_MATRIX_IDENTITY seems wrong for only particles?
|
||||
if(12)
|
||||
target.particles.transform = TRANSFORM_COMPLEX_MATRIX_IDENTITY
|
||||
if(16)
|
||||
target.particles.transform = TRANSFORM_PROJECTION_MATRIX_IDENTITY
|
||||
return
|
||||
if("edit")
|
||||
var/particles/owner = target.particles
|
||||
var/param_var_name = params["var"]
|
||||
if(!(param_var_name in owner.vars))
|
||||
return FALSE
|
||||
var/var_value = params["new_value"]
|
||||
var/var_mod = params["var_mod"]
|
||||
// we can only return arrays from tgui so lets convert it to something usable if needed
|
||||
switch(var_mod)
|
||||
if(P_DATA_GENERATOR)
|
||||
//these MUST be vectors and the others MUST be floats
|
||||
if(var_value[1] in list(GEN_VECTOR, GEN_BOX))
|
||||
if(!islist(var_value[2]))
|
||||
var_value[2] = list(var_value[2],var_value[2],var_value[2])
|
||||
if(!islist(var_value[3]))
|
||||
var_value[3] = list(var_value[3],var_value[3],var_value[3])
|
||||
//this means we just switched off a vector-requiring generator type
|
||||
else if(islist(var_value[2]) && islist(var_value[3]))
|
||||
var_value[2] = var_value[1]
|
||||
var_value[3] = var_value[1]
|
||||
var_value = generator(arglist(var_value))
|
||||
if(P_DATA_ICON_ADD)
|
||||
var_value = pick_and_customize_icon(ui.user, pick_only=TRUE)
|
||||
if(!var_value)
|
||||
return FALSE
|
||||
var/list/new_values = list()
|
||||
new_values += var_value
|
||||
new_values[var_value] = 1
|
||||
if(isicon(owner.icon))
|
||||
new_values[owner.icon] = 1
|
||||
owner.icon = new_values
|
||||
else if(islist(owner.icon))
|
||||
owner.icon[var_value] = 1
|
||||
else
|
||||
owner.icon = new_values
|
||||
target.particles.datum_flags |= DF_VAR_EDITED
|
||||
return TRUE
|
||||
if(P_DATA_ICON_REMOVE)
|
||||
for(var/file in owner.icon)
|
||||
if("[file]" == var_value)
|
||||
owner.icon -= file
|
||||
UNSETEMPTY(owner.icon)
|
||||
target.particles.datum_flags |= DF_VAR_EDITED
|
||||
return TRUE
|
||||
if(P_DATA_ICON_WEIGHT)
|
||||
// [filename, new_weight]
|
||||
var/list/mod_data = var_value
|
||||
for(var/file in owner.icon)
|
||||
if("[file]" == mod_data[1])
|
||||
owner.icon[file] = mod_data[2]
|
||||
target.particles.datum_flags |= DF_VAR_EDITED
|
||||
return TRUE
|
||||
if(P_DATA_GRADIENT)
|
||||
var/list/new_grad_list = list()
|
||||
for(var/entry in var_value)
|
||||
new_grad_list += entry // Unpackage nested lists
|
||||
owner.gradient = new_grad_list
|
||||
target.particles.datum_flags |= DF_VAR_EDITED
|
||||
return TRUE
|
||||
|
||||
owner.vars[param_var_name] = var_value
|
||||
target.particles.datum_flags |= DF_VAR_EDITED
|
||||
return TRUE
|
||||
@@ -0,0 +1,207 @@
|
||||
#ifdef REFERENCE_TRACKING
|
||||
#define REFSEARCH_RECURSE_LIMIT 64
|
||||
|
||||
/datum/proc/find_references(references_to_clear = INFINITY)
|
||||
if(usr?.client)
|
||||
if(tgui_alert(usr,"Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", list("Yes", "No")) != "Yes")
|
||||
return
|
||||
|
||||
src.references_to_clear = references_to_clear
|
||||
//this keeps the garbage collector from failing to collect objects being searched for in here
|
||||
SSgarbage.can_fire = FALSE
|
||||
|
||||
_search_references()
|
||||
//restart the garbage collector
|
||||
SSgarbage.can_fire = TRUE
|
||||
SSgarbage.update_nextfire(reset_time = TRUE)
|
||||
|
||||
/datum/proc/_search_references()
|
||||
log_reftracker("Beginning search for references to a [type], looking for [references_to_clear] refs.")
|
||||
|
||||
var/starting_time = world.time
|
||||
//Time to search the whole game for our ref
|
||||
DoSearchVar(GLOB, "GLOB", starting_time) //globals
|
||||
log_reftracker("Finished searching globals")
|
||||
if(src.references_to_clear == 0)
|
||||
return
|
||||
|
||||
//Yes we do actually need to do this. The searcher refuses to read weird lists
|
||||
//And global.vars is a really weird list
|
||||
var/global_vars = list()
|
||||
for(var/key in global.vars)
|
||||
global_vars[key] = global.vars[key]
|
||||
|
||||
DoSearchVar(global_vars, "Native Global", starting_time)
|
||||
log_reftracker("Finished searching native globals")
|
||||
if(src.references_to_clear == 0)
|
||||
return
|
||||
|
||||
for(var/datum/thing in world) //atoms (don't beleive its lies)
|
||||
DoSearchVar(thing, "World -> [thing.type]", starting_time)
|
||||
if(src.references_to_clear == 0)
|
||||
break
|
||||
log_reftracker("Finished searching atoms")
|
||||
if(src.references_to_clear == 0)
|
||||
return
|
||||
|
||||
for(var/datum/thing) //datums
|
||||
DoSearchVar(thing, "Datums -> [thing.type]", starting_time)
|
||||
if(src.references_to_clear == 0)
|
||||
break
|
||||
log_reftracker("Finished searching datums")
|
||||
if(src.references_to_clear == 0)
|
||||
return
|
||||
|
||||
//Warning, attempting to search clients like this will cause crashes if done on live. Watch yourself
|
||||
#ifndef REFERENCE_DOING_IT_LIVE
|
||||
for(var/client/thing) //clients
|
||||
DoSearchVar(thing, "Clients -> [thing.type]", starting_time)
|
||||
if(src.references_to_clear == 0)
|
||||
break
|
||||
log_reftracker("Finished searching clients")
|
||||
if(src.references_to_clear == 0)
|
||||
return
|
||||
#endif
|
||||
|
||||
log_reftracker("Completed search for references to a [type].")
|
||||
|
||||
/datum/proc/DoSearchVar(potential_container, container_name, search_time, recursion_count, is_special_list)
|
||||
if(recursion_count >= REFSEARCH_RECURSE_LIMIT)
|
||||
log_reftracker("Recursion limit reached. [container_name]")
|
||||
return
|
||||
|
||||
if(references_to_clear == 0)
|
||||
return
|
||||
|
||||
//Check each time you go down a layer. This makes it a bit slow, but it won't effect the rest of the game at all
|
||||
#ifndef FIND_REF_NO_CHECK_TICK
|
||||
CHECK_TICK
|
||||
#endif
|
||||
|
||||
if(isdatum(potential_container))
|
||||
var/datum/datum_container = potential_container
|
||||
if(datum_container.last_find_references == search_time)
|
||||
return
|
||||
|
||||
datum_container.last_find_references = search_time
|
||||
var/list/vars_list = datum_container.vars
|
||||
|
||||
var/is_atom = FALSE
|
||||
var/is_area = FALSE
|
||||
if(isatom(datum_container))
|
||||
is_atom = TRUE
|
||||
if(isarea(datum_container))
|
||||
is_area = TRUE
|
||||
for(var/varname in vars_list)
|
||||
var/variable = vars_list[varname]
|
||||
if(islist(variable))
|
||||
//Fun fact, vis_locs don't count for references
|
||||
if(varname == "vars" || (is_atom && (varname == "vis_locs" || varname == "overlays" || varname == "underlays" || varname == "filters" || varname == "verbs" || (is_area && varname == "contents"))))
|
||||
continue
|
||||
// We do this after the varname check to avoid area contents (reading it incures a world loop's worth of cost)
|
||||
if(!length(variable))
|
||||
continue
|
||||
DoSearchVar(variable,\
|
||||
"[container_name] [datum_container.ref_search_details()] -> [varname] (list)",\
|
||||
search_time,\
|
||||
recursion_count + 1,\
|
||||
/*is_special_list = */ is_atom && (varname == "contents" || varname == "vis_contents" || varname == "locs"))
|
||||
else if(variable == src)
|
||||
#ifdef REFERENCE_TRACKING_DEBUG
|
||||
if(SSgarbage.should_save_refs)
|
||||
if(!found_refs)
|
||||
found_refs = list()
|
||||
found_refs[varname] = TRUE
|
||||
continue //End early, don't want these logging
|
||||
else
|
||||
log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [datum_container.ref_search_details()] [varname] var. [container_name]")
|
||||
#else
|
||||
log_reftracker("Found [type] [text_ref(src)] in [datum_container.type]'s [datum_container.ref_search_details()] [varname] var. [container_name]")
|
||||
#endif
|
||||
references_to_clear -= 1
|
||||
if(references_to_clear == 0)
|
||||
log_reftracker("All references to [type] [text_ref(src)] found, exiting.")
|
||||
return
|
||||
continue
|
||||
|
||||
else if(islist(potential_container))
|
||||
var/list/potential_cache = potential_container
|
||||
for(var/element_in_list in potential_cache)
|
||||
//Check normal sublists
|
||||
if(islist(element_in_list))
|
||||
if(length(element_in_list))
|
||||
DoSearchVar(element_in_list, "[container_name] -> [element_in_list] (list)", search_time, recursion_count + 1)
|
||||
//Check normal entrys
|
||||
else if(element_in_list == src)
|
||||
#ifdef REFERENCE_TRACKING_DEBUG
|
||||
if(SSgarbage.should_save_refs)
|
||||
if(!found_refs)
|
||||
found_refs = list()
|
||||
found_refs[potential_cache] = TRUE
|
||||
continue
|
||||
else
|
||||
log_reftracker("Found [type] [text_ref(src)] in list [container_name].")
|
||||
#else
|
||||
log_reftracker("Found [type] [text_ref(src)] in list [container_name].")
|
||||
#endif
|
||||
|
||||
// This is dumb as hell I'm sorry
|
||||
// I don't want the garbage subsystem to count as a ref for the purposes of this number
|
||||
// If we find all other refs before it I want to early exit, and if we don't I want to keep searching past it
|
||||
var/ignore_ref = FALSE
|
||||
var/list/queues = SSgarbage.queues
|
||||
for(var/list/queue in queues)
|
||||
if(potential_cache in queue)
|
||||
ignore_ref = TRUE
|
||||
break
|
||||
if(ignore_ref)
|
||||
log_reftracker("[container_name] does not count as a ref for our count")
|
||||
else
|
||||
references_to_clear -= 1
|
||||
if(references_to_clear == 0)
|
||||
log_reftracker("All references to [type] [text_ref(src)] found, exiting.")
|
||||
return
|
||||
|
||||
if(!isnum(element_in_list) && !is_special_list)
|
||||
// This exists to catch an error that throws when we access a special list
|
||||
// is_special_list is a hint, it can be wrong
|
||||
try
|
||||
var/assoc_val = potential_cache[element_in_list]
|
||||
//Check assoc sublists
|
||||
if(islist(assoc_val))
|
||||
if(length(assoc_val))
|
||||
DoSearchVar(potential_container[element_in_list], "[container_name]\[[element_in_list]\] -> [assoc_val] (list)", search_time, recursion_count + 1)
|
||||
//Check assoc entry
|
||||
else if(assoc_val == src)
|
||||
#ifdef REFERENCE_TRACKING_DEBUG
|
||||
if(SSgarbage.should_save_refs)
|
||||
if(!found_refs)
|
||||
found_refs = list()
|
||||
found_refs[potential_cache] = TRUE
|
||||
continue
|
||||
else
|
||||
log_reftracker("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]")
|
||||
#else
|
||||
log_reftracker("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]")
|
||||
#endif
|
||||
references_to_clear -= 1
|
||||
if(references_to_clear == 0)
|
||||
log_reftracker("All references to [type] [text_ref(src)] found, exiting.")
|
||||
return
|
||||
catch
|
||||
// So if it goes wrong we kill it
|
||||
is_special_list = TRUE
|
||||
log_reftracker("Curiosity: [container_name] lead to an error when acessing [element_in_list], what is it?")
|
||||
|
||||
#undef REFSEARCH_RECURSE_LIMIT
|
||||
#endif
|
||||
|
||||
// Kept outside the ifdef so overrides are easy to implement
|
||||
|
||||
/// Return info about us for reference searching purposes
|
||||
/// Will be logged as a representation of this datum if it's a part of a search chain
|
||||
/datum/proc/ref_search_details()
|
||||
return text_ref(src)
|
||||
|
||||
/datum/callback/ref_search_details()
|
||||
return "[text_ref(src)] (obj: [object] proc: [delegate] args: [json_encode(arguments)] user: [user?.resolve() || "null"])"
|
||||
@@ -0,0 +1,16 @@
|
||||
/client/proc/tag_datum(datum/target_datum)
|
||||
if(!holder || QDELETED(target_datum))
|
||||
return
|
||||
holder.add_tagged_datum(target_datum)
|
||||
|
||||
/client/proc/toggle_tag_datum(datum/target_datum)
|
||||
if(!holder || !target_datum)
|
||||
return
|
||||
|
||||
if(LAZYFIND(holder.tagged_datums, target_datum))
|
||||
holder.remove_tagged_datum(target_datum)
|
||||
else
|
||||
holder.add_tagged_datum(target_datum)
|
||||
|
||||
ADMIN_VERB_ONLY_CONTEXT_MENU(tag_datum, R_NONE, "Tag Datum", datum/target_datum as mob|obj|turf|area in view())
|
||||
user.tag_datum(target_datum)
|
||||
@@ -1,587 +1,157 @@
|
||||
//DO NOT ADD MORE TO THIS FILE.
|
||||
//Use vv_do_topic()!
|
||||
//Use vv_do_topic() for datums!
|
||||
/client/proc/view_var_Topic(href, href_list, hsrc)
|
||||
if((usr.client != src) || !check_rights(R_HOLDER))
|
||||
if(!check_rights_for(src, R_VAREDIT) || !holder.CheckAdminHref(href, href_list))
|
||||
return
|
||||
var/datum/target = locate(href_list["target"])
|
||||
if(istype(target))
|
||||
target.vv_do_topic(href_list)
|
||||
var/target = GET_VV_TARGET
|
||||
vv_do_basic(target, href_list, href)
|
||||
if(isdatum(target))
|
||||
var/datum/D = target
|
||||
D.vv_do_topic(href_list)
|
||||
else if(islist(target))
|
||||
vv_do_list(target, href_list)
|
||||
|
||||
if(href_list["Vars"])
|
||||
debug_variables(locate(href_list["Vars"]))
|
||||
var/datum/vars_target = locate(href_list["Vars"])
|
||||
if(href_list["special_varname"]) // Some special vars can't be located even if you have their ref, you have to use this instead
|
||||
vars_target = vars_target.vars[href_list["special_varname"]]
|
||||
debug_variables(vars_target)
|
||||
|
||||
//~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records).
|
||||
else if(href_list["rename"])
|
||||
if(!check_rights(R_VAREDIT)) return
|
||||
//~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records).
|
||||
if(href_list["rename"])
|
||||
|
||||
var/mob/M = locate(href_list["rename"])
|
||||
var/mob/M = locate(href_list["rename"]) in mob_list
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob")
|
||||
to_chat(usr, "This can only be used on instances of type /mob", confidential = TRUE)
|
||||
return
|
||||
|
||||
var/new_name = sanitize(tgui_input_text(src,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN), MAX_NAME_LEN)
|
||||
if( !new_name || !M ) return
|
||||
var/new_name = stripped_input(usr,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN)
|
||||
|
||||
// If the new name is something that would be restricted by IC chat filters,
|
||||
// give the admin a warning but allow them to do it anyway if they want.
|
||||
//if(is_ic_filtered(new_name) || is_soft_ic_filtered(new_name) && tgui_alert(usr, "Your selected name contains words restricted by IC chat filters. Confirm this new name?", "IC Chat Filter Conflict", list("Confirm", "Cancel")) == "Cancel")
|
||||
// return
|
||||
|
||||
if( !new_name || !M )
|
||||
return
|
||||
|
||||
message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].")
|
||||
M.fully_replace_character_name(M.real_name,new_name)
|
||||
href_list["datumrefresh"] = href_list["rename"]
|
||||
|
||||
else if(href_list["varnameedit"] && href_list["datumedit"])
|
||||
if(!check_rights(R_VAREDIT)) return
|
||||
|
||||
var/D = locate(href_list["datumedit"])
|
||||
if(!istype(D,/datum) && !istype(D,/client))
|
||||
to_chat(src, "This can only be used on instances of types /client or /datum")
|
||||
return
|
||||
|
||||
modify_variables(D, href_list["varnameedit"], 1)
|
||||
|
||||
else if(href_list["varnamechange"] && href_list["datumchange"])
|
||||
if(!check_rights(R_VAREDIT)) return
|
||||
|
||||
var/D = locate(href_list["datumchange"])
|
||||
if(!istype(D,/datum) && !istype(D,/client))
|
||||
to_chat(src, "This can only be used on instances of types /client or /datum")
|
||||
return
|
||||
|
||||
modify_variables(D, href_list["varnamechange"], 0)
|
||||
|
||||
else if(href_list["varnamemass"] && href_list["datummass"])
|
||||
if(!check_rights(R_VAREDIT)) return
|
||||
|
||||
var/atom/A = locate(href_list["datummass"])
|
||||
if(!istype(A))
|
||||
to_chat(src, "This can only be used on instances of type /atom")
|
||||
return
|
||||
|
||||
cmd_mass_modify_object_variables(A, href_list["varnamemass"])
|
||||
|
||||
else if(href_list["mob_player_panel"])
|
||||
if(!check_rights(0)) return
|
||||
|
||||
var/mob/M = locate(href_list["mob_player_panel"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob")
|
||||
return
|
||||
|
||||
src.holder.show_player_panel(M)
|
||||
href_list["datumrefresh"] = href_list["mob_player_panel"]
|
||||
|
||||
else if(href_list["give_spell"])
|
||||
if(!check_rights(R_ADMIN|R_FUN|R_EVENT)) return
|
||||
|
||||
var/mob/M = locate(href_list["give_spell"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob")
|
||||
return
|
||||
|
||||
src.give_spell(M)
|
||||
href_list["datumrefresh"] = href_list["give_spell"]
|
||||
|
||||
else if(href_list["give_modifier"])
|
||||
if(!check_rights(R_ADMIN|R_FUN|R_DEBUG|R_EVENT))
|
||||
return
|
||||
|
||||
var/mob/living/M = locate(href_list["give_modifier"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob/living")
|
||||
return
|
||||
|
||||
src.admin_give_modifier(M)
|
||||
href_list["datumrefresh"] = href_list["give_modifier"]
|
||||
|
||||
else if(href_list["give_wound_internal"])
|
||||
if(!check_rights(R_ADMIN|R_FUN|R_DEBUG|R_EVENT))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = locate(href_list["give_wound_internal"])
|
||||
if(!istype(H))
|
||||
to_chat(src, span_notice("This can only be used on instances of type /mob/living/carbon/human"))
|
||||
return
|
||||
|
||||
var/severity = tgui_input_number(src, "How much damage should the bleeding internal wound cause? \
|
||||
Bleed timer directly correlates with this. 0 cancels. Input is rounded to nearest integer.",
|
||||
"Wound Severity", 0)
|
||||
if(!severity) return
|
||||
|
||||
var/obj/item/organ/external/chosen_organ = tgui_input_list(src, "Choose an external organ to inflict IB on!", "Organ Choice", H.organs)
|
||||
if(!chosen_organ || !istype(chosen_organ))
|
||||
to_chat(usr, span_notice("The chosen organ is of inappropriate type or no longer exists."))
|
||||
return
|
||||
|
||||
var/datum/wound/internal_bleeding/I = new /datum/wound/internal_bleeding(severity)
|
||||
if(!I || !istype(I))
|
||||
to_chat(src, span_notice("Could not initialize internal wound"))
|
||||
log_debug("[usr] attempted to create an internal bleeding wound on [H]'s [chosen_organ] of [severity] damage \
|
||||
and wound initialization failed")
|
||||
|
||||
chosen_organ.wounds += I
|
||||
chosen_organ.update_wounds()
|
||||
chosen_organ.update_damages()
|
||||
H.bad_external_organs += chosen_organ
|
||||
H.handle_organs()
|
||||
|
||||
if(H.client)
|
||||
H.custom_pain("You feel a throbbing pain inside your [chosen_organ]", severity, force=TRUE)
|
||||
log_and_message_admins("created an Internal Bleeding wound on [H.ckey]'s mob [H] on [chosen_organ] of [severity] damage", usr)
|
||||
|
||||
href_list["datumrefresh"] = href_list["give_wound_internal"]
|
||||
|
||||
else if(href_list["godmode"])
|
||||
if(!check_rights(R_REJUVINATE)) return
|
||||
|
||||
var/mob/M = locate(href_list["godmode"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob")
|
||||
return
|
||||
|
||||
src.cmd_admin_godmode(M)
|
||||
href_list["datumrefresh"] = href_list["godmode"]
|
||||
|
||||
else if(href_list["gib"])
|
||||
if(!check_rights(0)) return
|
||||
|
||||
var/mob/M = locate(href_list["gib"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob")
|
||||
return
|
||||
|
||||
src.cmd_admin_gib(M)
|
||||
|
||||
else if(href_list["build_mode"])
|
||||
if(!check_rights(R_BUILDMODE)) return
|
||||
|
||||
var/mob/M = locate(href_list["build_mode"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob")
|
||||
return
|
||||
|
||||
togglebuildmode(M)
|
||||
href_list["datumrefresh"] = href_list["build_mode"]
|
||||
|
||||
else if(href_list["drop_everything"])
|
||||
if(!check_rights(R_DEBUG|R_ADMIN|R_EVENT)) return
|
||||
|
||||
var/mob/M = locate(href_list["drop_everything"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob")
|
||||
return
|
||||
|
||||
if(usr.client)
|
||||
usr.client.cmd_admin_drop_everything(M)
|
||||
|
||||
else if(href_list["direct_control"])
|
||||
if(!check_rights(0)) return
|
||||
|
||||
var/mob/M = locate(href_list["direct_control"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be used on instances of type /mob")
|
||||
return
|
||||
|
||||
if(usr.client)
|
||||
usr.client.cmd_assume_direct_control(M)
|
||||
|
||||
else if(href_list["give_ai"])
|
||||
if(!check_rights(0)) return
|
||||
|
||||
var/mob/M = locate(href_list["give_ai"])
|
||||
if(!isliving(M))
|
||||
to_chat(src, span_notice("This can only be used on instances of type /mob/living"))
|
||||
return
|
||||
var/mob/living/L = M
|
||||
if(L.client || L.teleop)
|
||||
to_chat(src, span_warning("This cannot be used on player mobs!"))
|
||||
return
|
||||
|
||||
if(L.ai_holder) //Cleaning up the original ai
|
||||
var/ai_holder_old = L.ai_holder
|
||||
L.ai_holder = null
|
||||
qdel(ai_holder_old) //Only way I could make #TESTING - Unable to be GC'd to stop. del() logs show it works.
|
||||
L.ai_holder_type = tgui_input_list(src, "Choose AI holder", "AI Type", typesof(/datum/ai_holder/))
|
||||
L.initialize_ai_holder()
|
||||
L.faction = sanitize(tgui_input_text(src, "Please input AI faction", "AI faction", "neutral"))
|
||||
L.a_intent = tgui_input_list(src, "Please choose AI intent", "AI intent", list(I_HURT, I_HELP))
|
||||
if(tgui_alert(src, "Make mob wake up? This is needed for carbon mobs.", "Wake mob?", list("Yes", "No")) == "Yes")
|
||||
L.AdjustSleeping(-100)
|
||||
|
||||
else if(href_list["make_skeleton"])
|
||||
if(!check_rights(R_FUN)) return
|
||||
|
||||
var/mob/living/carbon/human/H = locate(href_list["make_skeleton"])
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be used on instances of type /mob/living/carbon/human")
|
||||
return
|
||||
|
||||
H.ChangeToSkeleton()
|
||||
href_list["datumrefresh"] = href_list["make_skeleton"]
|
||||
|
||||
else if(href_list["delall"])
|
||||
if(!check_rights(R_DEBUG|R_SERVER))
|
||||
return
|
||||
|
||||
var/obj/O = locate(href_list["delall"])
|
||||
if(!isobj(O))
|
||||
to_chat(src, "This can only be used on instances of type /obj")
|
||||
return
|
||||
|
||||
var/action_type = tgui_alert(src, "Strict type ([O.type]) or type and all subtypes?","Type Selection",list("Strict type","Type and subtypes","Cancel"))
|
||||
if(action_type == "Cancel" || !action_type)
|
||||
return
|
||||
|
||||
if(tgui_alert(src, "Are you really sure you want to delete all objects of type [O.type]?","Delete All?",list("Yes","No")) != "Yes")
|
||||
return
|
||||
|
||||
if(tgui_alert(src, "Second confirmation required. Delete?","REALLY?",list("Yes","No")) != "Yes")
|
||||
return
|
||||
|
||||
var/O_type = O.type
|
||||
switch(action_type)
|
||||
if("Strict type")
|
||||
var/i = 0
|
||||
for(var/obj/Obj in world)
|
||||
if(Obj.type == O_type)
|
||||
i++
|
||||
qdel(Obj)
|
||||
CHECK_TICK
|
||||
if(!i)
|
||||
to_chat(src, "No objects of this type exist")
|
||||
return
|
||||
log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ")
|
||||
message_admins(span_notice("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) "))
|
||||
if("Type and subtypes")
|
||||
var/i = 0
|
||||
for(var/obj/Obj in world)
|
||||
if(istype(Obj,O_type))
|
||||
i++
|
||||
qdel(Obj)
|
||||
CHECK_TICK
|
||||
if(!i)
|
||||
to_chat(src, "No objects of this type exist")
|
||||
return
|
||||
log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ")
|
||||
message_admins(span_notice("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) "))
|
||||
else if(href_list["fakepdapropconvo"])
|
||||
if(!check_rights(R_FUN)) return
|
||||
|
||||
var/obj/item/pda/P = locate(href_list["fakepdapropconvo"])
|
||||
if(!istype(P))
|
||||
to_chat(src, span_warning("This can only be done to instances of type /pda"))
|
||||
return
|
||||
|
||||
P.createPropFakeConversation_admin(usr)
|
||||
vv_update_display(M, "name", new_name)
|
||||
vv_update_display(M, "real_name", M.real_name || "No real name")
|
||||
|
||||
else if(href_list["rotatedatum"])
|
||||
if(!check_rights(0)) return
|
||||
|
||||
var/atom/A = locate(href_list["rotatedatum"])
|
||||
if(!istype(A))
|
||||
to_chat(src, "This can only be done to instances of type /atom")
|
||||
to_chat(usr, "This can only be done to instances of type /atom", confidential = TRUE)
|
||||
return
|
||||
|
||||
switch(href_list["rotatedir"])
|
||||
if("right") A.set_dir(turn(A.dir, -45))
|
||||
if("left") A.set_dir(turn(A.dir, 45))
|
||||
href_list["datumrefresh"] = href_list["rotatedatum"]
|
||||
if("right")
|
||||
A.set_dir(turn(A.dir, -45))
|
||||
if("left")
|
||||
A.set_dir(turn(A.dir, 45))
|
||||
vv_update_display(A, "dir", dir2text(A.dir))
|
||||
|
||||
else if(href_list["makemonkey"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/living/carbon/human/H = locate(href_list["makemonkey"])
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob/living/carbon/human")
|
||||
return
|
||||
|
||||
if(tgui_alert(src, "Confirm mob type change?","Confirm",list("Transform","Cancel")) != "Transform") return
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
holder.Topic(href, list("monkeyone"=href_list["makemonkey"]))
|
||||
|
||||
else if(href_list["makerobot"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/living/carbon/human/H = locate(href_list["makerobot"])
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob/living/carbon/human")
|
||||
return
|
||||
|
||||
if(tgui_alert(src, "Confirm mob type change?","Confirm",list("Transform","Cancel")) != "Transform") return
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
holder.Topic(href, list("makerobot"=href_list["makerobot"]))
|
||||
|
||||
else if(href_list["makealien"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/living/carbon/human/H = locate(href_list["makealien"])
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob/living/carbon/human")
|
||||
return
|
||||
|
||||
if(tgui_alert(src, "Confirm mob type change?","Confirm",list("Transform","Cancel")) != "Transform") return
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
holder.Topic(href, list("makealien"=href_list["makealien"]))
|
||||
|
||||
else if(href_list["makeai"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/living/carbon/human/H = locate(href_list["makeai"])
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob/living/carbon/human")
|
||||
return
|
||||
|
||||
if(tgui_alert(src, "Confirm mob type change?","Confirm",list("Transform","Cancel")) != "Transform") return
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
holder.Topic(href, list("makeai"=href_list["makeai"]))
|
||||
|
||||
else if(href_list["setspecies"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/living/carbon/human/H = locate(href_list["setspecies"])
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob/living/carbon/human")
|
||||
return
|
||||
|
||||
var/new_species = tgui_input_list(src, "Please choose a new species.","Species", GLOB.all_species)
|
||||
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
|
||||
if(H.set_species(new_species))
|
||||
to_chat(src, "Set species of [H] to [H.species].")
|
||||
else
|
||||
to_chat(src, "Failed! Something went wrong.")
|
||||
|
||||
else if(href_list["addlanguage"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/H = locate(href_list["addlanguage"])
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob")
|
||||
return
|
||||
|
||||
var/new_language = tgui_input_list(src, "Please choose a language to add.","Language", GLOB.all_languages)
|
||||
|
||||
if(!new_language)
|
||||
return
|
||||
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
|
||||
if(H.add_language(new_language))
|
||||
to_chat(src, "Added [new_language] to [H].")
|
||||
else
|
||||
to_chat(src, "Mob already knows that language.")
|
||||
|
||||
else if(href_list["remlanguage"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/H = locate(href_list["remlanguage"])
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob")
|
||||
return
|
||||
|
||||
if(!H.languages.len)
|
||||
to_chat(src, "This mob knows no languages.")
|
||||
return
|
||||
|
||||
var/datum/language/rem_language = tgui_input_list(src, "Please choose a language to remove.","Language", H.languages)
|
||||
|
||||
if(!rem_language)
|
||||
return
|
||||
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
|
||||
if(H.remove_language(rem_language.name))
|
||||
to_chat(src, "Removed [rem_language] from [H].")
|
||||
else
|
||||
to_chat(src, "Mob doesn't know that language.")
|
||||
|
||||
else if(href_list["addverb"])
|
||||
if(!check_rights(R_DEBUG)) return
|
||||
|
||||
var/mob/H = locate(href_list["addverb"])
|
||||
|
||||
if(!ismob(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob")
|
||||
return
|
||||
var/list/possibleverbs = list()
|
||||
possibleverbs += "Cancel" // One for the top...
|
||||
possibleverbs += typesof(/mob/proc, /mob/verb)
|
||||
if(isobserver(H))
|
||||
possibleverbs += typesof(/mob/observer/dead/proc,/mob/observer/dead/verb)
|
||||
if(isliving(H))
|
||||
possibleverbs += typesof(/mob/living/proc,/mob/living/verb)
|
||||
if(ishuman(H))
|
||||
possibleverbs += typesof(/mob/living/carbon/proc,/mob/living/carbon/verb,/mob/living/carbon/human/verb,/mob/living/carbon/human/proc)
|
||||
if(isrobot(H))
|
||||
possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/robot/proc,/mob/living/silicon/robot/verb)
|
||||
if(isAI(H))
|
||||
possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/ai/proc,/mob/living/silicon/ai/verb)
|
||||
if(isanimal(H))
|
||||
possibleverbs += typesof(/mob/living/simple_mob/proc)
|
||||
possibleverbs -= H.verbs
|
||||
possibleverbs += "Cancel" // ...And one for the bottom
|
||||
|
||||
var/verb = tgui_input_list(src, "Select a verb!", "Verbs", possibleverbs)
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
if(!verb || verb == "Cancel")
|
||||
return
|
||||
else
|
||||
add_verb(H, verb)
|
||||
|
||||
else if(href_list["remverb"])
|
||||
if(!check_rights(R_DEBUG)) return
|
||||
|
||||
var/mob/H = locate(href_list["remverb"])
|
||||
|
||||
if(!istype(H))
|
||||
to_chat(src, "This can only be done to instances of type /mob")
|
||||
return
|
||||
var/verb = tgui_input_list(src, "Please choose a verb to remove.","Verbs", H.verbs)
|
||||
if(!H)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
if(!verb)
|
||||
return
|
||||
else
|
||||
remove_verb(H, verb)
|
||||
|
||||
else if(href_list["addorgan"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/living/carbon/M = locate(href_list["addorgan"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be done to instances of type /mob/living/carbon")
|
||||
return
|
||||
|
||||
var/new_organ = tgui_input_list(src, "Please choose an organ to add.","Organ", subtypesof(/obj/item/organ))
|
||||
if(!new_organ) return
|
||||
|
||||
if(!M)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
|
||||
if(locate(new_organ) in M.internal_organs)
|
||||
to_chat(src, "Mob already has that organ.")
|
||||
return
|
||||
|
||||
new new_organ(M)
|
||||
|
||||
|
||||
else if(href_list["remorgan"])
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/mob/living/carbon/M = locate(href_list["remorgan"])
|
||||
if(!istype(M))
|
||||
to_chat(src, "This can only be done to instances of type /mob/living/carbon")
|
||||
return
|
||||
|
||||
var/obj/item/organ/rem_organ = tgui_input_list(src, "Please choose an organ to remove.","Organ", M.internal_organs)
|
||||
|
||||
if(!M)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
return
|
||||
|
||||
if(!(locate(rem_organ) in M.internal_organs))
|
||||
to_chat(src, "Mob does not have that organ.")
|
||||
return
|
||||
|
||||
to_chat(src, "Removed [rem_organ] from [M].")
|
||||
rem_organ.removed()
|
||||
qdel(rem_organ)
|
||||
|
||||
else if(href_list["fix_nano"])
|
||||
if(!check_rights(R_DEBUG)) return
|
||||
|
||||
var/mob/H = locate(href_list["fix_nano"])
|
||||
|
||||
if(!istype(H) || !H.client)
|
||||
to_chat(src, "This can only be done on mobs with clients")
|
||||
return
|
||||
|
||||
H.client.send_resources()
|
||||
|
||||
to_chat(src, "Resource files sent")
|
||||
to_chat(H, "Your NanoUI Resource files have been refreshed")
|
||||
|
||||
log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)] ")
|
||||
|
||||
else if(href_list["regenerateicons"])
|
||||
if(!check_rights(0)) return
|
||||
|
||||
var/mob/M = locate(href_list["regenerateicons"])
|
||||
if(!ismob(M))
|
||||
to_chat(src, "This can only be done to instances of type /mob")
|
||||
return
|
||||
M.regenerate_icons()
|
||||
|
||||
else if(href_list["adjustDamage"] && href_list["mobToDamage"])
|
||||
if(!check_rights(R_DEBUG|R_ADMIN|R_FUN|R_EVENT)) return
|
||||
|
||||
var/mob/living/L = locate(href_list["mobToDamage"])
|
||||
if(!istype(L)) return
|
||||
var/mob/living/L = locate(href_list["mobToDamage"]) in mob_list
|
||||
if(!istype(L))
|
||||
return
|
||||
|
||||
var/Text = href_list["adjustDamage"]
|
||||
|
||||
var/amount = tgui_input_number(src, "Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0, min_value=-INFINITY, round_value=FALSE)
|
||||
var/amount = tgui_input_number(src, "Deal how much damage to mob? (Negative values here heal)", "Adjust [Text]loss", 0, min_value=-INFINITY, round_value=FALSE)
|
||||
|
||||
if(!L)
|
||||
to_chat(src, "Mob doesn't exist anymore")
|
||||
if (isnull(amount))
|
||||
return
|
||||
|
||||
if(!L)
|
||||
to_chat(usr, "Mob doesn't exist anymore", confidential = TRUE)
|
||||
return
|
||||
|
||||
var/newamt
|
||||
switch(Text)
|
||||
if("brute") L.adjustBruteLoss(amount)
|
||||
if("fire") L.adjustFireLoss(amount)
|
||||
if("toxin") L.adjustToxLoss(amount)
|
||||
if("oxygen")L.adjustOxyLoss(amount)
|
||||
if("brain") L.adjustBrainLoss(amount)
|
||||
if("clone") L.adjustCloneLoss(amount)
|
||||
if("brute")
|
||||
L.adjustBruteLoss(amount)
|
||||
newamt = L.getBruteLoss()
|
||||
if("fire")
|
||||
L.adjustFireLoss(amount)
|
||||
newamt = L.getFireLoss()
|
||||
if("toxin")
|
||||
L.adjustToxLoss(amount)
|
||||
newamt = L.getToxLoss()
|
||||
if("oxygen")
|
||||
L.adjustOxyLoss(amount)
|
||||
newamt = L.getOxyLoss()
|
||||
if("brain")
|
||||
L.adjustBrainLoss(amount)
|
||||
newamt = L.getBrainLoss()
|
||||
if("clone")
|
||||
L.adjustCloneLoss(amount)
|
||||
newamt = L.getCloneLoss()
|
||||
//if("brain")
|
||||
// L.adjustOrganLoss(ORGAN_SLOT_BRAIN, amount)
|
||||
// newamt = L.get_organ_loss(ORGAN_SLOT_BRAIN)
|
||||
//if("stamina")
|
||||
// L.adjustStaminaLoss(amount, forced = TRUE)
|
||||
// newamt = L.getStaminaLoss()
|
||||
else
|
||||
to_chat(src, "You caused an error. DEBUG: Text:[Text] Mob:[L]")
|
||||
to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]", confidential = TRUE)
|
||||
return
|
||||
|
||||
if(amount != 0)
|
||||
log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L]")
|
||||
message_admins(span_notice("[key_name(usr)] dealt [amount] amount of [Text] damage to [L]"))
|
||||
href_list["datumrefresh"] = href_list["mobToDamage"]
|
||||
else if(href_list["expose"])
|
||||
if(!check_rights(R_ADMIN, FALSE))
|
||||
return
|
||||
var/thing = locate(href_list["expose"])
|
||||
if(!thing) //Do NOT QDELETED check!
|
||||
return
|
||||
var/value = vv_get_value(VV_CLIENT)
|
||||
if (value["class"] != VV_CLIENT)
|
||||
return
|
||||
var/client/C = value["value"]
|
||||
if (!C)
|
||||
return
|
||||
var/prompt = tgui_alert(src, "Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anysrc nor open nested vv windows unless they themselves are an admin)", "Confirm", list("Yes", "No"))
|
||||
if (prompt != "Yes")
|
||||
return
|
||||
if(!thing)
|
||||
to_chat(src, span_warning("The object you tried to expose to [C] no longer exists (GC'd)"))
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='byond://?_src_=vars;[HrefToken(TRUE)];datumrefresh=\ref[thing]'>VV window</a>")
|
||||
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [src]")
|
||||
to_chat(C, "[holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window")
|
||||
C.debug_variables(thing)
|
||||
var/log_msg = "[key_name(usr)] dealt [amount] amount of [Text] damage to [key_name(L)]"
|
||||
message_admins("[key_name(usr)] dealt [amount] amount of [Text] damage to [ADMIN_LOOKUPFLW(L)]")
|
||||
log_admin(log_msg)
|
||||
admin_ticket_log(L, "<font color='blue'>[log_msg]</font>")
|
||||
vv_update_display(L, Text, "[newamt]")
|
||||
|
||||
else if(href_list["item_to_tweak"] && href_list["var_tweak"])
|
||||
|
||||
var/obj/item/editing = locate(href_list["item_to_tweak"])
|
||||
if(!istype(editing) || QDELING(editing))
|
||||
return
|
||||
|
||||
var/existing_val = -1
|
||||
switch(href_list["var_tweak"])
|
||||
if("damtype")
|
||||
existing_val = editing.damtype
|
||||
if("force")
|
||||
existing_val = editing.force
|
||||
//if("wound")
|
||||
// existing_val = editing.wound_bonus
|
||||
//if("bare wound")
|
||||
// existing_val = editing.exposed_wound_bonus
|
||||
else
|
||||
CRASH("Invalid var_tweak passed to item vv set var: [href_list["var_tweak"]]")
|
||||
|
||||
var/new_val
|
||||
if(href_list["var_tweak"] == "damtype")
|
||||
//new_val = tgui_input_list(usr, "Enter the new damage type for [editing]", "Set Damtype", list(BRUTE, BURN, TOX, OXY, STAMINA, BRAIN), existing_val)
|
||||
new_val = tgui_input_list(usr, "Enter the new damage type for [editing]","Set Damtype", list(BRUTE, BURN, TOX, OXY, CLONE, HALLOSS, ELECTROCUTE, BIOACID, SEARING, ELECTROMAG), existing_val)
|
||||
else
|
||||
new_val = tgui_input_number(usr, "Enter the new value for [editing]'s [href_list["var_tweak"]]","Set [href_list["var_tweak"]]", existing_val)
|
||||
if(isnull(new_val) || new_val == existing_val || QDELETED(editing) || !check_rights(R_VAREDIT))
|
||||
return
|
||||
|
||||
switch(href_list["var_tweak"])
|
||||
if("damtype")
|
||||
editing.damtype = new_val
|
||||
if("force")
|
||||
editing.force = new_val
|
||||
//if("wound")
|
||||
// editing.wound_bonus = new_val
|
||||
//if("bare wound")
|
||||
// editing.exposed_wound_bonus = new_val
|
||||
|
||||
message_admins("[key_name(usr)] set [editing]'s [href_list["var_tweak"]] to [new_val] (was [existing_val])")
|
||||
log_admin("[key_name(usr)] set [editing]'s [href_list["var_tweak"]] to [new_val] (was [existing_val])")
|
||||
vv_update_display(editing, href_list["var_tweak"], istext(new_val) ? uppertext(new_val) : new_val)
|
||||
|
||||
//Finally, refresh if something modified the list.
|
||||
if(href_list["datumrefresh"])
|
||||
var/datum/DAT = locate(href_list["datumrefresh"])
|
||||
if(istype(DAT, /datum) || istype(DAT, /client) || islist(DAT))
|
||||
if(isdatum(DAT) || istype(DAT, /client) || islist(DAT))
|
||||
debug_variables(DAT)
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
//Not using datum.vv_do_topic for very basic/low level debug things, incase the datum's vv_do_topic is runtiming/whatnot.
|
||||
/client/proc/vv_do_basic(datum/target, href_list)
|
||||
var/target_var = GET_VV_VAR_TARGET
|
||||
if(check_rights(R_VAREDIT))
|
||||
if(target_var)
|
||||
if(href_list[VV_HK_BASIC_EDIT])
|
||||
if(!modify_variables(target, target_var, 1))
|
||||
return
|
||||
switch(target_var)
|
||||
if("name")
|
||||
vv_update_display(target, "name", "[target]")
|
||||
if("dir")
|
||||
var/atom/A = target
|
||||
if(istype(A))
|
||||
vv_update_display(target, "dir", dir2text(A.dir) || A.dir)
|
||||
if("ckey")
|
||||
var/mob/living/L = target
|
||||
if(istype(L))
|
||||
vv_update_display(target, "ckey", L.ckey || "No ckey")
|
||||
if("real_name")
|
||||
var/mob/living/L = target
|
||||
if(istype(L))
|
||||
vv_update_display(target, "real_name", L.real_name || "No real name")
|
||||
|
||||
if(href_list[VV_HK_BASIC_CHANGE])
|
||||
modify_variables(target, target_var, 0)
|
||||
if(href_list[VV_HK_BASIC_MASSEDIT])
|
||||
cmd_mass_modify_object_variables(target, target_var)
|
||||
if(check_rights(R_ADMIN, FALSE))
|
||||
if(href_list[VV_HK_EXPOSE])
|
||||
var/value = vv_get_value(VV_CLIENT)
|
||||
if (value["class"] != VV_CLIENT)
|
||||
return
|
||||
var/client/C = value["value"]
|
||||
if (!C)
|
||||
return
|
||||
if(!target)
|
||||
to_chat(usr, span_warning("The object you tried to expose to [C] no longer exists (nulled or hard-deled)"), confidential = TRUE)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='byond://?_src_=vars;datumrefresh=[REF(target)]'>VV window</a>")
|
||||
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [target]")
|
||||
to_chat(C, "[holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window", confidential = TRUE)
|
||||
C.debug_variables(target)
|
||||
if(check_rights(R_DEBUG))
|
||||
if(href_list[VV_HK_DELETE])
|
||||
usr.client.admin_delete(target)
|
||||
if (isturf(target)) // show the turf that took its place
|
||||
usr.client.debug_variables(target)
|
||||
return
|
||||
|
||||
if(href_list[VV_HK_MARK])
|
||||
usr.client.mark_datum(target)
|
||||
if(href_list[VV_HK_TAG])
|
||||
usr.client.tag_datum(target)
|
||||
if(href_list[VV_HK_ADDCOMPONENT])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/list/names = list()
|
||||
var/list/componentsubtypes = sortList(subtypesof(/datum/component), GLOBAL_PROC_REF(cmp_typepaths_asc))
|
||||
names += "---Components---"
|
||||
names += componentsubtypes
|
||||
names += "---Elements---"
|
||||
names += sortList(subtypesof(/datum/element), GLOBAL_PROC_REF(cmp_typepaths_asc))
|
||||
|
||||
var/result = tgui_input_list(usr, "Choose a component/element to add", "Add Component", names)
|
||||
if(isnull(result))
|
||||
return
|
||||
if(!usr || result == "---Components---" || result == "---Elements---")
|
||||
return
|
||||
|
||||
if(QDELETED(src))
|
||||
to_chat(usr, "That thing doesn't exist anymore!", confidential = TRUE)
|
||||
return
|
||||
|
||||
var/add_source
|
||||
if(ispath(result, /datum/component))
|
||||
var/datum/component/comp_path = result
|
||||
if(initial(comp_path.dupe_mode) == COMPONENT_DUPE_SOURCES)
|
||||
add_source = tgui_input_text(usr, "Enter a source for the component", "Add Component", "ADMIN-ABUSE")
|
||||
if(isnull(add_source))
|
||||
return
|
||||
|
||||
var/list/lst = get_callproc_args()
|
||||
if(!lst)
|
||||
return
|
||||
|
||||
var/datumname = "error"
|
||||
lst.Insert(1, result)
|
||||
if(result in componentsubtypes)
|
||||
datumname = "component"
|
||||
target._AddComponent(lst, add_source)
|
||||
else
|
||||
datumname = "element"
|
||||
target._AddElement(lst)
|
||||
log_admin("[key_name(usr)] has added [result] [datumname] to [key_name(target)].")
|
||||
message_admins(span_notice("[key_name_admin(usr)] has added [result] [datumname] to [key_name_admin(target)]."))
|
||||
if(href_list[VV_HK_REMOVECOMPONENT] || href_list[VV_HK_MASS_REMOVECOMPONENT])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/mass_remove = href_list[VV_HK_MASS_REMOVECOMPONENT]
|
||||
var/list/components = target._datum_components.Copy()
|
||||
var/list/names = list()
|
||||
names += "---Components---"
|
||||
if(length(components))
|
||||
names += sortList(components, GLOBAL_PROC_REF(cmp_typepaths_asc))
|
||||
names += "---Elements---"
|
||||
// We have to list every element here because there is no way to know what element is on this object without doing some sort of hack.
|
||||
names += sortList(subtypesof(/datum/element), GLOBAL_PROC_REF(cmp_typepaths_asc))
|
||||
var/path = tgui_input_list(usr, "Choose a component/element to remove. All elements listed here may not be on the datum.", "Remove element", names)
|
||||
if(isnull(path))
|
||||
return
|
||||
if(!usr || path == "---Components---" || path == "---Elements---")
|
||||
return
|
||||
if(QDELETED(src))
|
||||
to_chat(usr, "That thing doesn't exist anymore!")
|
||||
return
|
||||
var/list/targets_to_remove_from = list(target)
|
||||
if(mass_remove)
|
||||
var/method = vv_subtype_prompt(target.type)
|
||||
targets_to_remove_from = get_all_of_type(target.type, method)
|
||||
|
||||
if(alert(usr, "Are you sure you want to mass-delete [path] on [target.type]?", "Mass Remove Confirmation", "Yes", "No") == "No")
|
||||
return
|
||||
|
||||
for(var/datum/target_to_remove_from as anything in targets_to_remove_from)
|
||||
if(ispath(path, /datum/element))
|
||||
var/list/lst = get_callproc_args()
|
||||
if(!lst)
|
||||
lst = list()
|
||||
lst.Insert(1, path)
|
||||
target._RemoveElement(lst)
|
||||
else
|
||||
var/list/components_actual = target_to_remove_from.GetComponents(path)
|
||||
for(var/to_delete in components_actual)
|
||||
qdel(to_delete)
|
||||
|
||||
message_admins(span_notice("[key_name_admin(usr)] has [mass_remove? "mass" : ""] removed [path] component from [mass_remove? target.type : key_name_admin(target)]."))
|
||||
//if(href_list[VV_HK_MODIFY_GREYSCALE])
|
||||
// if(!check_rights(NONE))
|
||||
// return
|
||||
// var/datum/greyscale_modify_menu/menu = new(target, usr, SSgreyscale.configurations, unlocked = TRUE)
|
||||
// menu.ui_interact(usr)
|
||||
|
||||
if(href_list[VV_HK_CALLPROC])
|
||||
return SSadmin_verbs.dynamic_invoke_verb(usr, /datum/admin_verb/call_proc_datum, target)
|
||||
@@ -1,44 +1,43 @@
|
||||
//LISTS - CAN NOT DO VV_DO_TOPIC BECAUSE LISTS AREN'T DATUMS :(
|
||||
/client/proc/vv_do_list(list/target, href_list)
|
||||
if(!check_rights(R_VAREDIT))
|
||||
return
|
||||
var/target_index = text2num(href_list["index"])
|
||||
if(target_index)
|
||||
if(href_list[VV_HK_LIST_EDIT])
|
||||
mod_list(target, null, "list", "contents", target_index, autodetect_class = TRUE)
|
||||
if(href_list[VV_HK_LIST_CHANGE])
|
||||
mod_list(target, null, "list", "contents", target_index, autodetect_class = FALSE)
|
||||
if(href_list[VV_HK_LIST_REMOVE])
|
||||
var/variable = target[target_index]
|
||||
var/prompt = tgui_alert(usr, "Do you want to remove item number [target_index] from list?", "Confirm", list("Yes", "No"))
|
||||
if (prompt != "Yes")
|
||||
var/target_index = text2num(GET_VV_VAR_TARGET)
|
||||
if(check_rights(R_VAREDIT))
|
||||
if(target_index)
|
||||
if(href_list[VV_HK_LIST_EDIT])
|
||||
mod_list(target, null, "list", "contents", target_index, autodetect_class = TRUE)
|
||||
if(href_list[VV_HK_LIST_CHANGE])
|
||||
mod_list(target, null, "list", "contents", target_index, autodetect_class = FALSE)
|
||||
if(href_list[VV_HK_LIST_REMOVE])
|
||||
var/variable = target[target_index]
|
||||
var/prompt = tgui_alert(usr,"Do you want to remove item number [target_index] from list?", "Confirm", list("Yes", "No"))
|
||||
if (prompt != "Yes")
|
||||
return
|
||||
target.Cut(target_index, target_index+1)
|
||||
log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]")
|
||||
log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]")
|
||||
if(href_list[VV_HK_LIST_ADD])
|
||||
mod_list_add(target, null, "list", "contents")
|
||||
if(href_list[VV_HK_LIST_ERASE_DUPES])
|
||||
uniqueList_inplace(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES")
|
||||
log_admin("[key_name(src)] modified list's contents: CLEAR DUPES")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES")
|
||||
if(href_list[VV_HK_LIST_ERASE_NULLS])
|
||||
list_clear_nulls(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS")
|
||||
log_admin("[key_name(src)] modified list's contents: CLEAR NULLS")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS")
|
||||
if(href_list[VV_HK_LIST_SET_LENGTH])
|
||||
var/value = vv_get_value(VV_NUM)
|
||||
if (value["class"] != VV_NUM || value["value"] > max(50000, target.len)) //safety - would rather someone not put an extra 0 and erase the server's memory lmao.
|
||||
return
|
||||
target.Cut(target_index, target_index+1)
|
||||
log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]")
|
||||
log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]")
|
||||
if(href_list[VV_HK_LIST_ADD])
|
||||
mod_list_add(target, null, "list", "contents")
|
||||
if(href_list[VV_HK_LIST_ERASE_DUPES])
|
||||
uniqueList_inplace(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES")
|
||||
log_admin("[key_name(src)] modified list's contents: CLEAR DUPES")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES")
|
||||
if(href_list[VV_HK_LIST_ERASE_NULLS])
|
||||
listclearnulls(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS")
|
||||
log_admin("[key_name(src)] modified list's contents: CLEAR NULLS")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS")
|
||||
if(href_list[VV_HK_LIST_SET_LENGTH])
|
||||
var/value = vv_get_value(VV_NUM)
|
||||
if (value["class"] != VV_NUM || value["value"] > max(5000, target.len)) //safety - would rather someone not put an extra 0 and erase the server's memory lmao.
|
||||
return
|
||||
target.len = value["value"]
|
||||
log_world("### ListVarEdit by [src]: /list len: [target.len]")
|
||||
log_admin("[key_name(src)] modified list's len: [target.len]")
|
||||
message_admins("[key_name_admin(src)] modified list's len: [target.len]")
|
||||
if(href_list[VV_HK_LIST_SHUFFLE])
|
||||
shuffle_inplace(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: SHUFFLE")
|
||||
log_admin("[key_name(src)] modified list's contents: SHUFFLE")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE")
|
||||
target.len = value["value"]
|
||||
log_world("### ListVarEdit by [src]: /list len: [target.len]")
|
||||
log_admin("[key_name(src)] modified list's len: [target.len]")
|
||||
message_admins("[key_name_admin(src)] modified list's len: [target.len]")
|
||||
if(href_list[VV_HK_LIST_SHUFFLE])
|
||||
shuffle_inplace(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: SHUFFLE")
|
||||
log_admin("[key_name(src)] modified list's contents: SHUFFLE")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE")
|
||||
|
||||
@@ -5,17 +5,17 @@ ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, (R_DEBUG|R_SERVER|R_ADMIN|R_SPAWN|R
|
||||
user.debug_variables(thing)
|
||||
// This is kept as a separate proc because admins are able to show VV to non-admins
|
||||
|
||||
/client/proc/debug_variables(datum/D in world)
|
||||
/client/proc/debug_variables(datum/thing in world)
|
||||
set category = "Debug.Investigate"
|
||||
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) //The usr vs src abuse in this proc is intentional and must not be changed
|
||||
to_chat(usr, span_danger("You need to be an administrator to access this."))
|
||||
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/dark = usr.client.prefs ? usr.client.prefs.read_preference(/datum/preference/toggle/holder/vv_dark) : TRUE
|
||||
@@ -24,305 +24,306 @@ ADMIN_VERB_AND_CONTEXT_MENU(debug_variables, (R_DEBUG|R_SERVER|R_ADMIN|R_SPAWN|R
|
||||
var/datum/asset/asset_cache_datum = get_asset_datum(/datum/asset/simple/vv)
|
||||
asset_cache_datum.send(usr)
|
||||
|
||||
var/islist = islist(D) || (!isdatum(D) && hascall(D, "Cut")) // Some special lists don't count as lists, but can be detected by if they have list procs
|
||||
if(!islist && !isdatum(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 don't count as lists, but can be detected by if they have list procs
|
||||
if(!islist && !isdatum(thing))
|
||||
return
|
||||
|
||||
//VOREStation Edit Start - the rest of this proc in a spawn
|
||||
spawn(0)
|
||||
var/title = ""
|
||||
var/refid = "\ref[D]"
|
||||
var/icon/sprite
|
||||
var/hash
|
||||
var/title = ""
|
||||
var/refid = REF(thing)
|
||||
var/icon/sprite
|
||||
var/hash
|
||||
|
||||
var/type = islist ? /list : D.type
|
||||
var/no_icon = FALSE
|
||||
var/type = islist ? /list : thing.type
|
||||
var/no_icon = FALSE
|
||||
|
||||
if(isatom(D))
|
||||
var/atom/AT = D
|
||||
if(use_gfi)
|
||||
sprite = getFlatIcon(D)
|
||||
if(!sprite)
|
||||
no_icon = TRUE
|
||||
else if(AT.icon && AT.icon_state)
|
||||
sprite = new /icon(AT.icon, AT.icon_state)
|
||||
else
|
||||
if(isatom(thing))
|
||||
var/atom/AT = thing
|
||||
if(use_gfi)
|
||||
sprite = getFlatIcon(thing)
|
||||
if(!sprite)
|
||||
no_icon = TRUE
|
||||
else if(AT.icon && AT.icon_state)
|
||||
sprite = new /icon(AT.icon, AT.icon_state)
|
||||
else
|
||||
no_icon = TRUE
|
||||
|
||||
else if(isimage(D))
|
||||
// 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 = D
|
||||
var/icon_filename_text = "[image_object.icon]" // "icon(null)" type can exist. textifying filters it.
|
||||
if(icon_filename_text)
|
||||
if(image_object.icon_state)
|
||||
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(icon_exists(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)
|
||||
|
||||
else // it means: icon_state=""
|
||||
if(!dmi_nullstate_checklist[icon_filename_text])
|
||||
dmi_nullstate_checklist[icon_filename_text] = ICON_STATE_CHECKED
|
||||
if(icon_exists(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
|
||||
var/sprite_text
|
||||
if(sprite)
|
||||
hash = md5(sprite)
|
||||
src << browse_rsc(sprite, "vv[hash].png")
|
||||
sprite_text = no_icon ? "\[NO ICON\]" : "<img src='vv[hash].png'></td><td>"
|
||||
|
||||
if(dmi_nullstate_checklist[icon_filename_text] == ICON_STATE_NULL)
|
||||
sprite = icon(image_object.icon, image_object.icon_state)
|
||||
title = "[thing] ([REF(thing)]) = [type]"
|
||||
var/formatted_type = replacetext("[type]", "/", "<wbr>/")
|
||||
|
||||
var/sprite_text
|
||||
if(sprite)
|
||||
hash = md5(sprite)
|
||||
src << browse_rsc(sprite, "vv[hash].png")
|
||||
sprite_text = no_icon ? "\[NO ICON\]" : "<img src='vv[hash].png'></td><td>"
|
||||
var/list/header = islist ? list("<b>/list</b>") : thing.vv_get_header()
|
||||
|
||||
title = "[D] (\ref[D]) = [type]"
|
||||
var/formatted_type = replacetext("[type]", "/", "<wbr>/")
|
||||
var/ref_line = "@[copytext(refid, 2, -1)]" // get rid of the brackets, add a @ prefix for copy pasting in asay
|
||||
|
||||
var/list/header = islist(D)? list(span_bold("/list")) : D.vv_get_header()
|
||||
var/marked_line
|
||||
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 && (thing.datum_flags & DF_VAR_EDITED))
|
||||
varedited_line = VV_MSG_EDITED
|
||||
var/deleted_line
|
||||
if(!islist && thing.gc_destroyed)
|
||||
deleted_line = VV_MSG_DELETED
|
||||
|
||||
var/ref_line = "@[copytext(refid, 2, -1)]" // get rid of the brackets, add a @ prefix for copy pasting in asay
|
||||
var/list/dropdownoptions
|
||||
if (islist)
|
||||
dropdownoptions = list(
|
||||
"---",
|
||||
"Add Item" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_ADD),
|
||||
"Remove Nulls" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_ERASE_NULLS),
|
||||
"Remove Dupes" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_ERASE_DUPES),
|
||||
"Set len" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_SET_LENGTH),
|
||||
"Shuffle" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_SHUFFLE),
|
||||
"Show VV To Player" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_EXPOSE),
|
||||
"---"
|
||||
)
|
||||
for(var/i in 1 to length(dropdownoptions))
|
||||
var/name = dropdownoptions[i]
|
||||
var/link = dropdownoptions[name]
|
||||
dropdownoptions[i] = "<option value[link? "='[link]'":""]>[name]</option>"
|
||||
else
|
||||
dropdownoptions = thing.vv_get_dropdown()
|
||||
|
||||
var/marked_line
|
||||
if(holder && holder.marked_datum && holder.marked_datum == D)
|
||||
marked_line = VV_MSG_MARKED
|
||||
var/varedited_line = ""
|
||||
if(!islist && (D.datum_flags & DF_VAR_EDITED))
|
||||
varedited_line = VV_MSG_EDITED
|
||||
var/deleted_line
|
||||
if(!islist && D.gc_destroyed)
|
||||
deleted_line = VV_MSG_DELETED
|
||||
var/list/names = list()
|
||||
if(!islist)
|
||||
for(var/varname in thing.vars)
|
||||
names += varname
|
||||
|
||||
var/list/dropdownoptions = list()
|
||||
var/autoconvert_dropdown = FALSE
|
||||
if (islist)
|
||||
dropdownoptions = list(
|
||||
"---",
|
||||
"Add Item" = "?_src_=vars;[HrefToken()];[VV_HK_LIST_ADD]=TRUE;target=[refid]",
|
||||
"Remove Nulls" = "?_src_=vars;[HrefToken()];[VV_HK_LIST_ERASE_NULLS]=TRUE;target=[refid]",
|
||||
"Remove Dupes" = "?_src_=vars;[HrefToken()];[VV_HK_LIST_ERASE_DUPES]=TRUE;target=[refid]",
|
||||
"Set len" = "?_src_=vars;[HrefToken()];[VV_HK_LIST_SET_LENGTH]=TRUE;target=[refid]",
|
||||
"Shuffle" = "?_src_=vars;[HrefToken()];[VV_HK_LIST_SHUFFLE]=TRUE;target=[refid]",
|
||||
// "Show VV To Player" = "?_src_=vars;[HrefToken()];[VV_HK_EXPOSE]=TRUE;target=[refid]" // TODO - Not yet implemented for lists
|
||||
)
|
||||
autoconvert_dropdown = TRUE
|
||||
else
|
||||
dropdownoptions = D.vv_get_dropdown()
|
||||
var/list/dropdownoptions_html = list()
|
||||
if(autoconvert_dropdown)
|
||||
for (var/name in dropdownoptions)
|
||||
var/link = dropdownoptions[name]
|
||||
if (link)
|
||||
dropdownoptions_html += "<option value='[link]'>[name]</option>"
|
||||
else
|
||||
dropdownoptions_html += "<option value>[name]</option>"
|
||||
else
|
||||
dropdownoptions_html = dropdownoptions + D.get_view_variables_options()
|
||||
sleep(1 TICKS)
|
||||
|
||||
var/list/names = list()
|
||||
if (!islist)
|
||||
names = D.get_variables()
|
||||
//sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects. //VOREStation edit - commented out, replaced with spawn(0) above
|
||||
var/ui_scale = prefs?.read_preference(/datum/preference/toggle/ui_scale)
|
||||
|
||||
var/ui_scale = prefs?.read_preference(/datum/preference/toggle/ui_scale)
|
||||
var/list/variable_html = list()
|
||||
if(islist)
|
||||
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(list_value) && IS_VALID_ASSOC_KEY(key))
|
||||
value = list_value[key]
|
||||
variable_html += debug_variable(i, value, 0, list_value)
|
||||
else
|
||||
names = sortList(names)
|
||||
for(var/varname in names)
|
||||
if(thing.can_vv_get(varname))
|
||||
variable_html += thing.vv_get_var(varname)
|
||||
|
||||
var/list/variable_html = list()
|
||||
if(islist)
|
||||
var/list/L = D
|
||||
for (var/i in 1 to L.len)
|
||||
var/key = L[i]
|
||||
var/value
|
||||
if(IS_NORMAL_LIST(L) && IS_VALID_ASSOC_KEY(key))
|
||||
value = L[key]
|
||||
variable_html += debug_variable(i, value, 0, D)
|
||||
else
|
||||
names = sortList(names)
|
||||
for (var/V in names)
|
||||
if(D.can_vv_get(V))
|
||||
variable_html += D.vv_get_var(V)
|
||||
|
||||
var/html = {"
|
||||
<!DOCTYPE html>
|
||||
<html class="[dark ? "dark" : ""]">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta charset="utf-8" />
|
||||
<title>[title]</title>
|
||||
<link rel="stylesheet" type="text/css" href="[SSassets.transport.get_asset_url("view_variables.css")]">
|
||||
[!ui_scale && window_scaling ? "<style>body {zoom: [100 / window_scaling]%;}</style>" : ""]
|
||||
</head>
|
||||
<body onload='selectTextField()' onkeydown='return handle_keydown()' onkeyup='handle_keyup()'>
|
||||
<script type="text/javascript">
|
||||
// onload
|
||||
function selectTextField() {
|
||||
var filter_text = document.getElementById('filter');
|
||||
filter_text.focus();
|
||||
filter_text.select();
|
||||
var lastsearch = getCookie("[refid][cookieoffset]search");
|
||||
if (lastsearch) {
|
||||
filter_text.value = lastsearch;
|
||||
updateSearch();
|
||||
}
|
||||
}
|
||||
function getCookie(cname) {
|
||||
var name = cname + "=";
|
||||
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);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// main search functionality
|
||||
var last_filter = "";
|
||||
function updateSearch() {
|
||||
var filter = document.getElementById('filter').value.toLowerCase();
|
||||
var vars_ol = document.getElementById("vars");
|
||||
|
||||
if (filter === last_filter) {
|
||||
// An event triggered an update but nothing has changed.
|
||||
return;
|
||||
} else if (filter.indexOf(last_filter) === 0) {
|
||||
// The new filter starts with the old filter, fast path by removing only.
|
||||
var children = vars_ol.childNodes;
|
||||
for (var i = children.length - 1; i >= 0; --i) {
|
||||
try {
|
||||
var li = children\[i];
|
||||
if (li.innerText.toLowerCase().indexOf(filter) == -1) {
|
||||
vars_ol.removeChild(li);
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
} else {
|
||||
// Remove everything and put back what matches.
|
||||
while (vars_ol.hasChildNodes()) {
|
||||
vars_ol.removeChild(vars_ol.lastChild);
|
||||
}
|
||||
|
||||
for (var i = 0; i < complete_list.length; ++i) {
|
||||
try {
|
||||
var li = complete_list\[i];
|
||||
if (!filter || li.innerText.toLowerCase().indexOf(filter) != -1) {
|
||||
vars_ol.appendChild(li);
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
}
|
||||
|
||||
last_filter = filter;
|
||||
document.cookie="[refid][cookieoffset]search="+encodeURIComponent(filter);
|
||||
|
||||
}
|
||||
|
||||
// onkeydown
|
||||
function handle_keydown() {
|
||||
if(event.keyCode == 116) { //F5 (to refresh properly)
|
||||
document.getElementById("refresh_link").click();
|
||||
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// onkeyup
|
||||
function handle_keyup() {
|
||||
var/html = {"
|
||||
<html class="[dark ? "dark" : ""]">
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
|
||||
<title>[title]</title>
|
||||
<link rel="stylesheet" type="text/css" href="[SSassets.transport.get_asset_url("view_variables.css")]">
|
||||
[!ui_scale && window_scaling ? "<style>body {zoom: [100 / window_scaling]%;}</style>" : ""]
|
||||
</head>
|
||||
<body onload='selectTextField()' onkeydown='return handle_keydown()' onkeyup='handle_keyup()'>
|
||||
<script type="text/javascript">
|
||||
// onload
|
||||
function selectTextField() {
|
||||
var filter_text = document.getElementById('filter');
|
||||
filter_text.focus();
|
||||
filter_text.select();
|
||||
var lastsearch = getCookie("[refid][cookieoffset]search");
|
||||
if (lastsearch) {
|
||||
filter_text.value = lastsearch;
|
||||
updateSearch();
|
||||
}
|
||||
}
|
||||
function getCookie(cname) {
|
||||
var name = cname + "=";
|
||||
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);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// onchange
|
||||
function handle_dropdown(list) {
|
||||
var value = list.options\[list.selectedIndex].value;
|
||||
if (value !== "") {
|
||||
location.href = value;
|
||||
// main search functionality
|
||||
var last_filter = "";
|
||||
function updateSearch() {
|
||||
var filter = document.getElementById('filter').value.toLowerCase();
|
||||
var vars_ol = document.getElementById("vars");
|
||||
|
||||
if (filter === last_filter) {
|
||||
// An event triggered an update but nothing has changed.
|
||||
return;
|
||||
} else if (filter.indexOf(last_filter) === 0) {
|
||||
// The new filter starts with the old filter, fast path by removing only.
|
||||
var children = vars_ol.childNodes;
|
||||
for (var i = children.length - 1; i >= 0; --i) {
|
||||
try {
|
||||
var li = children\[i];
|
||||
if (li.innerText.toLowerCase().indexOf(filter) == -1) {
|
||||
vars_ol.removeChild(li);
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
} else {
|
||||
// Remove everything and put back what matches.
|
||||
while (vars_ol.hasChildNodes()) {
|
||||
vars_ol.removeChild(vars_ol.lastChild);
|
||||
}
|
||||
|
||||
for (var i = 0; i < complete_list.length; ++i) {
|
||||
try {
|
||||
var li = complete_list\[i];
|
||||
if (!filter || li.innerText.toLowerCase().indexOf(filter) != -1) {
|
||||
vars_ol.appendChild(li);
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
list.selectedIndex = 0;
|
||||
document.getElementById('filter').focus();
|
||||
}
|
||||
|
||||
// byjax
|
||||
function replace_span(what) {
|
||||
var idx = what.indexOf(':');
|
||||
document.getElementById(what.substr(0, idx)).innerHTML = what.substr(idx + 1);
|
||||
last_filter = filter;
|
||||
document.cookie="[refid][cookieoffset]search="+encodeURIComponent(filter);
|
||||
|
||||
}
|
||||
|
||||
// onkeydown
|
||||
function handle_keydown() {
|
||||
if(event.keyCode == 116) { //F5 (to refresh properly)
|
||||
document.getElementById("refresh_link").click();
|
||||
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
<div align='center'>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='50%'>
|
||||
<table align='center' width='100%'>
|
||||
<tr>
|
||||
<td>
|
||||
[sprite_text]
|
||||
<div align='center'>
|
||||
[header.Join()]
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</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='varedited'>[varedited_line]</span>
|
||||
<span id='deleted'>[deleted_line]</span>
|
||||
</div>
|
||||
</td>
|
||||
<td width='50%'>
|
||||
<div align='center'>
|
||||
<a id='refresh_link' href='byond://?_src_=vars;
|
||||
datumrefresh=[refid]'>Refresh</a>
|
||||
<form>
|
||||
<select name="file" size="1"
|
||||
onchange="handle_dropdown(this)"
|
||||
onmouseclick="this.focus()">
|
||||
<option value selected>Select option</option>
|
||||
[dropdownoptions_html.Join()]
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<hr>
|
||||
<b>E</b> - Edit, tries to determine the variable type by itself.<br>
|
||||
<b>C</b> - Change, asks you for the var type first.<br>
|
||||
<b>M</b> - Mass modify: changes this variable for all objects of this type.<br>
|
||||
<hr>
|
||||
return true;
|
||||
}
|
||||
|
||||
// onkeyup
|
||||
function handle_keyup() {
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
// onchange
|
||||
function handle_dropdown(list) {
|
||||
var value = list.options\[list.selectedIndex].value;
|
||||
if (value !== "") {
|
||||
location.href = value;
|
||||
}
|
||||
list.selectedIndex = 0;
|
||||
document.getElementById('filter').focus();
|
||||
}
|
||||
|
||||
// byjax
|
||||
function replace_span(what) {
|
||||
var idx = what.indexOf(':');
|
||||
document.getElementById(what.substr(0, idx)).innerHTML = what.substr(idx + 1);
|
||||
}
|
||||
</script>
|
||||
<div align='center'>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='20%'>
|
||||
<td width='50%'>
|
||||
<table align='center' width='100%'>
|
||||
<tr>
|
||||
<td>
|
||||
[sprite_text]
|
||||
<div align='center'>
|
||||
[header.Join()]
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div align='center'>
|
||||
<b>Search:</b>
|
||||
<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>
|
||||
</td>
|
||||
<td width='80%'>
|
||||
<input type='text' id='filter' name='filter_text' value='' style='width:100%;'>
|
||||
<td width='50%'>
|
||||
<div align='center'>
|
||||
<a id='refresh_link' href='byond://?_src_=vars;
|
||||
datumrefresh=[refid];[HrefToken()]'>Refresh</a>
|
||||
<form>
|
||||
<select name="file" size="1"
|
||||
onchange="handle_dropdown(this)"
|
||||
onmouseclick="this.focus()">
|
||||
<option value selected>Select option</option>
|
||||
[dropdownoptions.Join()]
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<ol id='vars'>
|
||||
[variable_html.Join()]
|
||||
</ol>
|
||||
<script type='text/javascript'>
|
||||
var complete_list = \[\];
|
||||
var lis = document.getElementById("vars").children;
|
||||
for(var i = lis.length; i--;) complete_list\[i\] = lis\[i\];
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"}
|
||||
var/size_string = "size=475x650";
|
||||
if(ui_scale && window_scaling)
|
||||
size_string = "size=[475 * window_scaling]x[650 * window_scaling]"
|
||||
</div>
|
||||
<hr>
|
||||
<font size='1'>
|
||||
<b>E</b> - Edit, tries to determine the variable type by itself.<br>
|
||||
<b>C</b> - Change, asks you for the var type first.<br>
|
||||
<b>M</b> - Mass modify: changes this variable for all objects of this type.<br>
|
||||
</font>
|
||||
<hr>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='20%'>
|
||||
<div align='center'>
|
||||
<b>Search:</b>
|
||||
</div>
|
||||
</td>
|
||||
<td width='80%'>
|
||||
<input type='text' id='filter' name='filter_text' value='' style='width:100%;'>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<ol id='vars'>
|
||||
[variable_html.Join()]
|
||||
</ol>
|
||||
<script type='text/javascript'>
|
||||
var complete_list = \[\];
|
||||
var lis = document.getElementById("vars").children;
|
||||
for(var i = lis.length; i--;) complete_list\[i\] = lis\[i\];
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"}
|
||||
|
||||
src << browse(html, "window=variables[refid];[size_string]")
|
||||
var/size_string = "size=475x650";
|
||||
if(ui_scale && window_scaling)
|
||||
size_string = "size=[475 * window_scaling]x[650 * window_scaling]"
|
||||
|
||||
/client/proc/vv_update_display(datum/D, span, content)
|
||||
src << output("[span]:[content]", "variables\ref[D].browser:replace_span")
|
||||
src << browse(html, "window=variables[refid];[size_string]")
|
||||
|
||||
/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
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/proc/readglobal(which)
|
||||
. = global.vars[which]
|
||||
|
||||
/proc/writeglobal(which, newval)
|
||||
global.vars[which] = newval
|
||||
|
||||
/proc/getallglobals()
|
||||
. = list()
|
||||
for(var/some_global in global.vars)
|
||||
. += some_global
|
||||
|
||||
/var/decl/global_vars/global_vars_
|
||||
|
||||
/decl/global_vars
|
||||
var/name = span_bold("Global Variables")
|
||||
|
||||
/decl/global_vars/get_view_variables_options()
|
||||
return "" // Ensuring changes to the base proc never affect us
|
||||
|
||||
/decl/global_vars/get_variables()
|
||||
. = getallglobals() - VV_hidden()
|
||||
if(!usr || !check_rights(R_ADMIN|R_DEBUG, FALSE))
|
||||
. -= VV_secluded()
|
||||
|
||||
/decl/global_vars/get_variable_value(varname)
|
||||
return readglobal(varname)
|
||||
|
||||
/decl/global_vars/set_variable_value(varname, value)
|
||||
writeglobal(varname, value)
|
||||
|
||||
/decl/global_vars/make_view_variables_variable_entry(varname, value)
|
||||
return "(<a href='byond://?_src_=vars;[HrefToken()];datumedit=\ref[src];varnameedit=[varname]'>E</a>) "
|
||||
|
||||
/decl/global_vars/VV_locked()
|
||||
return vars
|
||||
|
||||
/decl/global_vars/VV_hidden()
|
||||
return list(
|
||||
"sqladdress",
|
||||
"sqldb",
|
||||
"sqllogin",
|
||||
"sqlpass",
|
||||
"sqlport",
|
||||
"comms_password",
|
||||
"ban_comms_password",
|
||||
"login_export_addr",
|
||||
"admin_verbs_default",
|
||||
"admin_verbs_admin",
|
||||
"admin_verbs_ban",
|
||||
"admin_verbs_sounds",
|
||||
"admin_verbs_fun",
|
||||
"admin_verbs_spawn",
|
||||
"admin_verbs_server",
|
||||
"admin_verbs_debug",
|
||||
"admin_verbs_paranoid_debug",
|
||||
"admin_verbs_possess",
|
||||
"admin_verbs_permissions",
|
||||
"admin_verbs_rejuv",
|
||||
"admin_verbs_hideable",
|
||||
"admin_verbs_mod",
|
||||
"admin_verbs_event_manager",
|
||||
"adminProcCallCount",
|
||||
"adminProcCaller",
|
||||
"AdminProcCallSpamPrevention",
|
||||
"admins",
|
||||
"admin_datums",
|
||||
"admin_log",
|
||||
"admin_ranks",
|
||||
"admin_state",
|
||||
"alien_whitelist",
|
||||
"GLOB.alldirs",
|
||||
"ahelp_tickets",
|
||||
"adminfaxes",
|
||||
"adminlogs",
|
||||
"GLOB.cardinal",
|
||||
"cardinalz",
|
||||
"IClog"
|
||||
)
|
||||
|
||||
/client/proc/debug_global_variables()
|
||||
set category = "Debug"
|
||||
set name = "View Global Variables"
|
||||
|
||||
if(!global_vars_)
|
||||
global_vars_ = new()
|
||||
debug_variables(global_vars_)
|
||||
Reference in New Issue
Block a user