Ports the VV Refactor by Kevinz.

This commit is contained in:
Ghommie
2020-04-03 19:16:43 +02:00
parent 431722e34d
commit 9d97f1acda
26 changed files with 1740 additions and 2013 deletions
-268
View File
@@ -15,214 +15,6 @@
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Debug Two") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/* 21st Sept 2010
Updated by Skie -- Still not perfect but better!
Stuff you can't do:
Call proc /mob/proc/Dizzy() for some player
Because if you select a player mob as owner it tries to do the proc for
/mob/living/carbon/human/ instead. And that gives a run-time error.
But you can call procs that are of type /mob/living/carbon/human/proc/ for that player.
*/
/client/proc/callproc()
set category = "Debug"
set name = "Advanced ProcCall"
set waitfor = FALSE
if(!check_rights(R_DEBUG))
return
var/datum/target = null
var/targetselected = FALSE
var/returnval = null
if(alert("Proc owned by something?",,"Yes","No") == "Yes")
targetselected = TRUE
var/list/value = vv_get_value(default_class = VV_ATOM_REFERENCE, classes = list(VV_ATOM_REFERENCE, VV_DATUM_REFERENCE, VV_MOB_REFERENCE, VV_CLIENT))
if (!value["class"] || !value["value"])
return
target = value["value"]
var/procpath = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
if(!procpath)
return
//strip away everything but the proc name
var/list/proclist = splittext(procpath, "/")
if (!length(proclist))
return
var/procname = proclist[proclist.len]
var/proctype = ("verb" in proclist) ? "verb" :"proc"
if(targetselected)
if(!hascall(target, procname))
to_chat(usr, "<span class='warning'>Error: callproc(): type [target.type] has no [proctype] named [procpath].</span>")
return
else
procpath = "/[proctype]/[procname]"
if(!text2path(procpath))
to_chat(usr, "<span class='warning'>Error: callproc(): [procpath] does not exist.</span>")
return
var/list/lst = get_callproc_args()
if(!lst)
return
if(targetselected)
if(!target)
to_chat(usr, "<span class='warning'>Error: callproc(): owner of proc no longer exists.</span>")
return
var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
log_admin(msg)
message_admins(msg)
admin_ticket_log(target, msg)
returnval = WrapAdminProcCall(target, procname, lst)
else
var/msg = "[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no argument"]."
log_admin(msg)
message_admins(msg)
returnval = WrapAdminProcCall(GLOBAL_PROC, procpath, lst) //calling globals needs full qualified name (e.g /proc/foo)
. = get_callproc_returnval(returnval, procname)
if(.)
to_chat(usr, .)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Advanced ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
GLOBAL_VAR(AdminProcCaller)
GLOBAL_PROTECT(AdminProcCaller)
GLOBAL_VAR_INIT(AdminProcCallCount, 0)
GLOBAL_PROTECT(AdminProcCallCount)
GLOBAL_VAR(LastAdminCalledTargetRef)
GLOBAL_PROTECT(LastAdminCalledTargetRef)
GLOBAL_VAR(LastAdminCalledTarget)
GLOBAL_PROTECT(LastAdminCalledTarget)
GLOBAL_VAR(LastAdminCalledProc)
GLOBAL_PROTECT(LastAdminCalledProc)
GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
if(target != GLOBAL_PROC && procname == "Del")
to_chat(usr, "<span class='warning'>Calling Del() is not allowed</span>")
return
if(target != GLOBAL_PROC && !target.CanProcCall(procname))
to_chat(usr, "Proccall on [target.type]/proc/[procname] is disallowed!")
return
var/current_caller = GLOB.AdminProcCaller
var/ckey = usr ? usr.client.ckey : GLOB.AdminProcCaller
if(!ckey)
CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]")
if(current_caller && current_caller != ckey)
if(!GLOB.AdminProcCallSpamPrevention[ckey])
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
GLOB.AdminProcCallSpamPrevention[ckey] = TRUE
UNTIL(!GLOB.AdminProcCaller)
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
GLOB.AdminProcCallSpamPrevention -= ckey
else
UNTIL(!GLOB.AdminProcCaller)
GLOB.LastAdminCalledProc = procname
if(target != GLOBAL_PROC)
GLOB.LastAdminCalledTargetRef = "[REF(target)]"
GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
++GLOB.AdminProcCallCount
. = world.WrapAdminProcCall(target, procname, arguments)
if(--GLOB.AdminProcCallCount == 0)
GLOB.AdminProcCaller = null
//adv proc call this, ya nerds
/world/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
if(target == GLOBAL_PROC)
return call(procname)(arglist(arguments))
else if(target != world)
return call(target, procname)(arglist(arguments))
else
log_admin_private("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]")
/proc/IsAdminAdvancedProcCall()
#ifdef TESTING
return FALSE
#else
return usr && usr.client && GLOB.AdminProcCaller == usr.client.ckey
#endif
/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
set category = "Debug"
set name = "Atom ProcCall"
set waitfor = FALSE
if(!check_rights(R_DEBUG))
return
var/procname = input("Proc name, eg: fake_blood","Proc:", null) as text|null
if(!procname)
return
if(!hascall(A,procname))
to_chat(usr, "<span class='warning'>Error: callproc_datum(): type [A.type] has no proc named [procname].</span>")
return
var/list/lst = get_callproc_args()
if(!lst)
return
if(!A || !IsValidSrc(A))
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>")
return
var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]."
log_admin(msg)
message_admins(msg)
admin_ticket_log(A, msg)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Atom ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc
. = get_callproc_returnval(returnval,procname)
if(.)
to_chat(usr, .)
/client/proc/get_callproc_args()
var/argnum = input("Number of arguments","Number:",0) as num|null
if(isnull(argnum))
return
. = list()
var/list/named_args = list()
while(argnum--)
var/named_arg = input("Leave blank for positional argument. Positional arguments will be considered as if they were added first.", "Named argument") as text|null
var/value = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT))
if (!value["class"])
return
if(named_arg)
named_args[named_arg] = value["value"]
else
. += value["value"]
if(LAZYLEN(named_args))
. += named_args
/client/proc/get_callproc_returnval(returnval,procname)
. = ""
if(islist(returnval))
var/list/returnedlist = returnval
. = "<span class='notice'>"
if(returnedlist.len)
var/assoc_check = returnedlist[1]
if(istext(assoc_check) && (returnedlist[assoc_check] != null))
. += "[procname] returned an associative list:"
for(var/key in returnedlist)
. += "\n[key] = [returnedlist[key]]"
else
. += "[procname] returned a list:"
for(var/elem in returnedlist)
. += "\n[elem]"
else
. = "[procname] returned an empty list"
. += "</span>"
else
. = "<span class='notice'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</span>"
/client/proc/Cell()
set category = "Debug"
set name = "Air Status in Location"
@@ -343,66 +135,6 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
else
alert("Invalid mob")
/proc/make_types_fancy(var/list/types)
if (ispath(types))
types = list(types)
. = list()
for(var/type in types)
var/typename = "[type]"
var/static/list/TYPES_SHORTCUTS = list(
/obj/effect/decal/cleanable = "CLEANABLE",
/obj/item/radio/headset = "HEADSET",
/obj/item/clothing/head/helmet/space = "SPESSHELMET",
/obj/item/book/manual = "MANUAL",
/obj/item/reagent_containers/food/drinks = "DRINK", //longest paths comes first
/obj/item/reagent_containers/food = "FOOD",
/obj/item/reagent_containers = "REAGENT_CONTAINERS",
/obj/machinery/atmospherics = "ATMOS_MECH",
/obj/machinery/portable_atmospherics = "PORT_ATMOS",
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack = "MECHA_MISSILE_RACK",
/obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP",
/obj/item/organ = "ORGAN",
/obj/item = "ITEM",
/obj/machinery = "MACHINERY",
/obj/effect = "EFFECT",
/obj = "O",
/datum = "D",
/turf/open = "OPEN",
/turf/closed = "CLOSED",
/turf = "T",
/mob/living/carbon = "CARBON",
/mob/living/simple_animal = "SIMPLE",
/mob/living = "LIVING",
/mob = "M"
)
for (var/tn in TYPES_SHORTCUTS)
if (copytext(typename,1, length("[tn]/")+1)=="[tn]/" /*findtextEx(typename,"[tn]/",1,2)*/ )
typename = TYPES_SHORTCUTS[tn]+copytext(typename,length("[tn]/"))
break
.[typename] = type
/proc/get_fancy_list_of_atom_types()
var/static/list/pre_generated_list
if (!pre_generated_list) //init
pre_generated_list = make_types_fancy(typesof(/atom))
return pre_generated_list
/proc/get_fancy_list_of_datum_types()
var/static/list/pre_generated_list
if (!pre_generated_list) //init
pre_generated_list = make_types_fancy(sortList(typesof(/datum) - typesof(/atom)))
return pre_generated_list
/proc/filter_fancy_list(list/L, filter as text)
var/list/matches = new
for(var/key in L)
var/value = L[key]
if(findtext("[key]", filter) || findtext("[value]", filter))
matches[key] = value
return matches
//TODO: merge the vievars version into this or something maybe mayhaps
/client/proc/cmd_debug_del_all(object as text)
set category = "Debug"
-265
View File
@@ -1,265 +0,0 @@
/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)
if(!check_rights(R_VAREDIT))
return
if(A && A.type)
method = vv_subtype_prompt(A.type)
src.massmodify_variables(A, var_name, method)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Mass Edit Variables") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/massmodify_variables(datum/O, var_name = "", method = 0)
if(!check_rights(R_VAREDIT))
return
if(!istype(O))
return
var/variable = ""
if(!var_name)
var/list/names = list()
for (var/V in O.vars)
names += V
names = sortList(names)
variable = input("Which var?", "Var") as null|anything in names
else
variable = var_name
if(!variable || !O.can_vv_get(variable))
return
var/default
var/var_value = O.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.")
return
if(variable in GLOB.VVlocked)
if(!check_rights(R_DEBUG))
return
if(variable in GLOB.VVicon_edit_lock)
if(!check_rights(R_FUN|R_DEBUG))
return
if(variable in GLOB.VVpixelmovement)
if(!check_rights(R_DEBUG))
return
var/prompt = alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "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.")
else
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
to_chat(src, "Variable contains: [var_value]")
if(default == VV_NUM)
var/dir_text = ""
if(var_value > 0 && var_value < 16)
if(var_value & 1)
dir_text += "NORTH"
if(var_value & 2)
dir_text += "SOUTH"
if(var_value & 4)
dir_text += "EAST"
if(var_value & 8)
dir_text += "WEST"
if(dir_text)
to_chat(src, "If a direction, direction is: [dir_text]")
var/value = vv_get_value(default_class = default)
var/new_value = value["value"]
var/class = value["class"]
if(!class || !new_value == null && class != VV_NULL)
return
if (class == VV_MESSAGE)
class = VV_TEXT
if (value["type"])
class = VV_NEW_TYPE
var/original_name = "[O]"
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...")
for(var/thing in items)
if (!thing)
continue
var/datum/D = thing
if (D.vv_edit_var(variable, initial(D.vars[variable])) != FALSE)
accepted++
else
rejected++
CHECK_TICK
if(VV_TEXT)
var/list/varsvars = vv_parse_text(O, new_value)
var/pre_processing = new_value
var/unique
if (varsvars && varsvars.len)
unique = alert(usr, "Process vars unique to each instance, or same for all?", "Variable Association", "Unique", "Same")
if(unique == "Unique")
unique = TRUE
else
unique = FALSE
for(var/V in varsvars)
new_value = replacetext(new_value,"\[[V]]","[O.vars[V]]")
to_chat(src, "Finding items...")
var/list/items = get_all_of_type(O.type, method)
to_chat(src, "Changing [items.len] items...")
for(var/thing in items)
if (!thing)
continue
var/datum/D = thing
if(unique)
new_value = pre_processing
for(var/V in varsvars)
new_value = replacetext(new_value,"\[[V]]","[D.vars[V]]")
if (D.vv_edit_var(variable, new_value) != FALSE)
accepted++
else
rejected++
CHECK_TICK
if (VV_NEW_TYPE)
var/many = alert(src, "Create only one [value["type"]] and assign each or a new one for each thing", "How Many", "One", "Many", "Cancel")
if (many == "Cancel")
return
if (many == "Many")
many = TRUE
else
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...")
for(var/thing in items)
if (!thing)
continue
var/datum/D = thing
if(many && !new_value)
new_value = new type()
if (D.vv_edit_var(variable, new_value) != FALSE)
accepted++
else
rejected++
new_value = null
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...")
for(var/thing in items)
if (!thing)
continue
var/datum/D = thing
if (D.vv_edit_var(variable, new_value) != FALSE)
accepted++
else
rejected++
CHECK_TICK
var/count = rejected+accepted
if (!count)
to_chat(src, "No objects found")
return
if (!accepted)
to_chat(src, "Every object rejected your edit")
return
if (rejected)
to_chat(src, "[rejected] out of [count] objects rejected your edit")
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)")
/proc/get_all_of_type(var/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 GLOB.mob_list)
if (typecache[thing.type])
. += thing
CHECK_TICK
else if (ispath(T, /obj/machinery/door))
for(var/obj/machinery/door/thing in GLOB.airlocks)
if (typecache[thing.type])
. += thing
CHECK_TICK
else if (ispath(T, /obj/machinery))
for(var/obj/machinery/thing in GLOB.machines)
if (typecache[thing.type])
. += thing
CHECK_TICK
else if (ispath(T, /obj))
for(var/obj/thing in world)
if (typecache[thing.type])
. += thing
CHECK_TICK
else if (ispath(T, /atom/movable))
for(var/atom/movable/thing in world)
if (typecache[thing.type])
. += thing
CHECK_TICK
else if (ispath(T, /turf))
for(var/turf/thing in world)
if (typecache[thing.type])
. += thing
CHECK_TICK
else if (ispath(T, /atom))
for(var/atom/thing in world)
if (typecache[thing.type])
. += thing
CHECK_TICK
else if (ispath(T, /client))
for(var/client/thing in GLOB.clients)
if (typecache[thing.type])
. += thing
CHECK_TICK
else if (ispath(T, /datum))
for(var/datum/thing)
if (typecache[thing.type])
. += thing
CHECK_TICK
else
for(var/datum/thing in world)
if (typecache[thing.type])
. += thing
CHECK_TICK
-644
View File
@@ -1,644 +0,0 @@
GLOBAL_LIST_INIT(VVlocked, list("vars", "datum_flags", "client", "virus", "viruses", "cuffed", "last_eaten", "unlock_content", "force_ending"))
GLOBAL_PROTECT(VVlocked)
GLOBAL_LIST_INIT(VVicon_edit_lock, list("icon", "icon_state", "overlays", "underlays", "resize"))
GLOBAL_PROTECT(VVicon_edit_lock)
GLOBAL_LIST_INIT(VVckey_edit, list("key", "ckey"))
GLOBAL_PROTECT(VVckey_edit)
GLOBAL_LIST_INIT(VVpixelmovement, list("step_x", "step_y", "bound_height", "bound_width", "bound_x", "bound_y"))
GLOBAL_PROTECT(VVpixelmovement)
/client/proc/vv_get_class(var/var_name, var/var_value)
if(isnull(var_value))
. = VV_NULL
else if (isnum(var_value))
if (var_name in GLOB.bitfields)
. = VV_BITFIELD
else
. = VV_NUM
else if (istext(var_value))
if (findtext(var_value, "\n"))
. = VV_MESSAGE
else
. = VV_TEXT
else if (isicon(var_value))
. = VV_ICON
else if (ismob(var_value))
. = VV_MOB_REFERENCE
else if (isloc(var_value))
. = VV_ATOM_REFERENCE
else if (istype(var_value, /client))
. = VV_CLIENT
else if (istype(var_value, /datum))
. = VV_DATUM_REFERENCE
else if (ispath(var_value))
if (ispath(var_value, /atom))
. = VV_ATOM_TYPE
else if (ispath(var_value, /datum))
. = VV_DATUM_TYPE
else
. = VV_TYPE
else if (islist(var_value))
. = VV_LIST
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)
classes = list (
VV_NUM,
VV_TEXT,
VV_MESSAGE,
VV_ICON,
VV_ATOM_REFERENCE,
VV_DATUM_REFERENCE,
VV_MOB_REFERENCE,
VV_CLIENT,
VV_ATOM_TYPE,
VV_DATUM_TYPE,
VV_TYPE,
VV_FILE,
VV_NEW_ATOM,
VV_NEW_DATUM,
VV_NEW_TYPE,
VV_NEW_LIST,
VV_NULL,
VV_RESTORE_DEFAULT
)
if(holder && holder.marked_datum && !(VV_MARKED_DATUM in restricted_classes))
classes += "[VV_MARKED_DATUM] ([holder.marked_datum.type])"
if (restricted_classes)
classes -= restricted_classes
if (extra_classes)
classes += extra_classes
.["class"] = input(src, "What kind of data?", "Variable Type", default_class) as null|anything in classes
if (holder && holder.marked_datum && .["class"] == "[VV_MARKED_DATUM] ([holder.marked_datum.type])")
.["class"] = VV_MARKED_DATUM
switch(.["class"])
if (VV_TEXT)
.["value"] = input("Enter new text:", "Text", current_value) as null|text
if (.["value"] == null)
.["class"] = null
return
if (VV_MESSAGE)
.["value"] = input("Enter new text:", "Text", current_value) as null|message
if (.["value"] == null)
.["class"] = null
return
if (VV_NUM)
.["value"] = input("Enter new number:", "Num", current_value) as null|num
if (.["value"] == null)
.["class"] = null
return
if (VV_BITFIELD)
.["value"] = input_bitfield(usr, "Editing bitfield: [var_name]", var_name, current_value)
if (.["value"] == null)
.["class"] = null
return
if (VV_ATOM_TYPE)
.["value"] = pick_closest_path(FALSE)
if (.["value"] == null)
.["class"] = null
return
if (VV_DATUM_TYPE)
.["value"] = pick_closest_path(FALSE, get_fancy_list_of_datum_types())
if (.["value"] == null)
.["class"] = null
return
if (VV_TYPE)
var/type = current_value
var/error = ""
do
type = input("Enter type:[error]", "Type", type) as null|text
if (!type)
break
type = text2path(type)
error = "\nType not found, Please try again"
while(!type)
if (!type)
.["class"] = null
return
.["value"] = type
if (VV_ATOM_REFERENCE)
var/type = pick_closest_path(FALSE)
var/subtypes = vv_subtype_prompt(type)
if (subtypes == null)
.["class"] = null
return
var/list/things = vv_reference_list(type, subtypes)
var/value = input("Select reference:", "Reference", current_value) as null|anything in things
if (!value)
.["class"] = null
return
.["value"] = things[value]
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)
.["class"] = null
return
var/list/things = vv_reference_list(type, subtypes)
var/value = input("Select reference:", "Reference", current_value) as null|anything in things
if (!value)
.["class"] = null
return
.["value"] = things[value]
if (VV_MOB_REFERENCE)
var/type = pick_closest_path(FALSE, make_types_fancy(typesof(/mob)))
var/subtypes = vv_subtype_prompt(type)
if (subtypes == null)
.["class"] = null
return
var/list/things = vv_reference_list(type, subtypes)
var/value = input("Select reference:", "Reference", current_value) as null|anything in things
if (!value)
.["class"] = null
return
.["value"] = things[value]
if (VV_CLIENT)
.["value"] = input("Select reference:", "Reference", current_value) as null|anything in GLOB.clients
if (.["value"] == null)
.["class"] = null
return
if (VV_FILE)
.["value"] = input("Pick file:", "File") as null|file
if (.["value"] == null)
.["class"] = null
return
if (VV_ICON)
.["value"] = input("Pick icon:", "Icon") as null|icon
if (.["value"] == null)
.["class"] = null
return
if (VV_MARKED_DATUM)
.["value"] = holder.marked_datum
if (.["value"] == null)
.["class"] = null
return
if (VV_NEW_ATOM)
var/type = pick_closest_path(FALSE)
if (!type)
.["class"] = null
return
.["type"] = type
var/atom/newguy = new type()
newguy.datum_flags |= DF_VAR_EDITED
.["value"] = newguy
if (VV_NEW_DATUM)
var/type = pick_closest_path(FALSE, get_fancy_list_of_datum_types())
if (!type)
.["class"] = null
return
.["type"] = type
var/datum/newguy = new type()
newguy.datum_flags |= DF_VAR_EDITED
.["value"] = newguy
if (VV_NEW_TYPE)
var/type = current_value
var/error = ""
do
type = input("Enter type:[error]", "Type", type) as null|text
if (!type)
break
type = text2path(type)
error = "\nType not found, Please try again"
while(!type)
if (!type)
.["class"] = null
return
.["type"] = type
var/datum/newguy = new type()
if(istype(newguy))
newguy.datum_flags |= DF_VAR_EDITED
.["value"] = newguy
if (VV_NEW_LIST)
.["value"] = list()
.["type"] = /list
/client/proc/vv_parse_text(O, new_var)
if(O && findtext(new_var,"\["))
var/process_vars = alert(usr,"\[] detected in string, process as variables?","Process Variables?","Yes","No")
if(process_vars == "Yes")
. = string2listofvars(new_var, O)
//do they want you to include subtypes?
//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)
if (!ispath(type))
return
var/list/subtypes = subtypesof(type)
if (!subtypes || !subtypes.len)
return FALSE
if (subtypes && subtypes.len)
switch(alert("Strict object type detection?", "Type detection", "Strictly this type","This type and subtypes", "Cancel"))
if("Strictly this type")
return FALSE
if("This type and subtypes")
return TRUE
else
return
/client/proc/vv_reference_list(type, subtypes)
. = list()
var/list/types = list(type)
if (subtypes)
types = typesof(type)
var/list/fancytypes = make_types_fancy(types)
for(var/fancytype in fancytypes) //swap the assoication
types[fancytypes[fancytype]] = fancytype
var/things = get_all_of_type(type, subtypes)
var/i = 0
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
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_char(shorttype) > length_char(fancytype))
shorttype = fancytype
if (!length(shorttype))
shorttype = "/"
.["[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)
return
var/var_value = L["value"]
if(class == VV_TEXT || class == VV_MESSAGE)
var/list/varsvars = vv_parse_text(O, var_value)
for(var/V in varsvars)
var_value = replacetext(var_value,"\[[V]]","[O.vars[V]]")
return var_value
/client/proc/mod_list_add(list/L, atom/O, original_name, objectvar)
var/list/LL = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT))
var/class = LL["class"]
if (!class)
return
var/var_value = LL["value"]
if(class == VV_TEXT || class == VV_MESSAGE)
var/list/varsvars = vv_parse_text(O, var_value)
for(var/V in varsvars)
var_value = replacetext(var_value,"\[[V]]","[O.vars[V]]")
if (O)
L = L.Copy()
L += var_value
switch(alert("Would you like to associate a value with the list entry?",,"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.")
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]")
message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: ADDED=[var_value]")
/client/proc/mod_list(list/L, atom/O, original_name, objectvar, index, autodetect_class = FALSE)
if(!check_rights(R_VAREDIT))
return
if(!istype(L, /list))
to_chat(src, "Not a List.")
return
if(L.len > 1000)
var/confirm = alert(src, "The list you're trying to edit is very long, continuing may crash the server.", "Warning", "Continue", "Abort")
if(confirm != "Continue")
return
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))
value = L[key]
if (value == null)
value = "null"
names["#[i] [key] = [value]"] = i
if (!index)
var/variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" + "(CLEAR NULLS)" + "(CLEAR DUPES)" + "(SHUFFLE)"
if(variable == null)
return
if(variable == "(ADD VAR)")
mod_list_add(L, O, original_name, objectvar)
return
if(variable == "(CLEAR NULLS)")
L = L.Copy()
listclearnulls(L)
if (!O.vv_edit_var(objectvar, L))
to_chat(src, "Your edit was rejected by the object.")
return
log_world("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR NULLS")
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR NULLS")
message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: CLEAR NULLS")
return
if(variable == "(CLEAR DUPES)")
L = uniqueList(L)
if (!O.vv_edit_var(objectvar, L))
to_chat(src, "Your edit was rejected by the object.")
return
log_world("### ListVarEdit by [src]: [O.type] [objectvar]: CLEAR DUPES")
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: CLEAR DUPES")
message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: CLEAR DUPES")
return
if(variable == "(SHUFFLE)")
L = shuffle(L)
if (!O.vv_edit_var(objectvar, L))
to_chat(src, "Your edit was rejected by the object.")
return
log_world("### ListVarEdit by [src]: [O.type] [objectvar]: SHUFFLE")
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: SHUFFLE")
message_admins("[key_name_admin(src)] modified [original_name]'s list [objectvar]: SHUFFLE")
return
index = names[variable]
var/assoc_key
if (index == null)
return
var/assoc = 0
var/prompt = alert(src, "Do you want to edit the key or its assigned value?", "Associated List", "Key", "Assigned Value", "Cancel")
if (prompt == "Cancel")
return
if (prompt == "Assigned Value")
assoc = 1
assoc_key = L[index]
var/default
var/variable
if (assoc)
variable = L[assoc_key]
else
variable = L[index]
default = vv_get_class(objectvar, variable)
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
to_chat(src, "Variable contains: [variable]")
if(default == VV_NUM)
var/dir_text = ""
var/tdir = variable
if(tdir > 0 && tdir < 16)
if(tdir & 1)
dir_text += "NORTH"
if(tdir & 2)
dir_text += "SOUTH"
if(tdir & 4)
dir_text += "EAST"
if(tdir & 8)
dir_text += "WEST"
if(dir_text)
to_chat(usr, "If a direction, direction is: [dir_text]")
var/original_var = variable
if (O)
L = L.Copy()
var/class
if(autodetect_class)
if (default == VV_TEXT)
default = VV_MESSAGE
class = default
var/list/LL = vv_get_value(default_class = default, current_value = original_var, restricted_classes = list(VV_RESTORE_DEFAULT), extra_classes = list(VV_LIST, "DELETE FROM LIST"))
class = LL["class"]
if (!class)
return
var/new_var = LL["value"]
if(class == VV_MESSAGE)
class = VV_TEXT
switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet.
if(VV_LIST)
mod_list(variable, O, original_name, objectvar)
if("DELETE FROM LIST")
L.Cut(index, index+1)
if (O)
if (O.vv_edit_var(objectvar, L))
to_chat(src, "Your edit was rejected by the object.")
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]")
message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]")
return
if(VV_TEXT)
var/list/varsvars = vv_parse_text(O, new_var)
for(var/V in varsvars)
new_var = replacetext(new_var,"\[[V]]","[O.vars[V]]")
if(assoc)
L[assoc_key] = new_var
else
L[index] = new_var
if (O)
if (O.vv_edit_var(objectvar, L) == FALSE)
to_chat(src, "Your edit was rejected by the object.")
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]")
message_admins("[key_name_admin(src)] modified [original_name]'s varlist [objectvar]: [original_var]=[new_var]")
/proc/vv_varname_lockcheck(param_var_name)
if(param_var_name in GLOB.VVlocked)
if(!check_rights(R_DEBUG))
return FALSE
if(param_var_name in GLOB.VVckey_edit)
if(!check_rights(R_SPAWN|R_DEBUG))
return FALSE
if(param_var_name in GLOB.VVicon_edit_lock)
if(!check_rights(R_FUN|R_DEBUG))
return FALSE
if(param_var_name in GLOB.VVpixelmovement)
if(!check_rights(R_DEBUG))
return FALSE
var/prompt = alert(usr, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT ", "Continue", " ABORT")
if (prompt != "Continue")
return FALSE
return TRUE
/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0)
if(!check_rights(R_VAREDIT))
return
var/class
var/variable
var/var_value
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])")
return
variable = param_var_name
else
var/list/names = list()
for (var/V in O.vars)
names += V
names = sortList(names)
variable = input("Which var?","Var") as null|anything in names
if(!variable)
return
if(!O.can_vv_get(variable))
return
var_value = O.vars[variable]
if(!vv_varname_lockcheck(variable))
return
if(istype(O, /datum/armor))
var/prompt = alert(src, "Editing this var changes this value on potentially thousands of items that share the same combination of armor values. If you want to edit the armor of just one item, use the \"Modify armor values\" dropdown item", "DANGER", "ABORT ", "Continue", " ABORT")
if (prompt != "Continue")
return
var/default = vv_get_class(variable, var_value)
if(isnull(default))
to_chat(src, "Unable to determine variable type.")
else
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
to_chat(src, "Variable contains: [var_value]")
if(default == VV_NUM)
var/dir_text = ""
if(var_value > 0 && var_value < 16)
if(var_value & 1)
dir_text += "NORTH"
if(var_value & 2)
dir_text += "SOUTH"
if(var_value & 4)
dir_text += "EAST"
if(var_value & 8)
dir_text += "WEST"
if(dir_text)
to_chat(src, "If a direction, direction is: [dir_text]")
if(autodetect_class && default != VV_NULL)
if (default == VV_TEXT)
default = VV_MESSAGE
class = default
var/list/value = vv_get_value(class, default, var_value, extra_classes = list(VV_LIST), var_name = variable)
class = value["class"]
if (!class)
return
var/var_new = value["value"]
if(class == VV_MESSAGE)
class = VV_TEXT
var/original_name = "[O]"
switch(class)
if(VV_LIST)
if(!islist(var_value))
mod_list(list(), O, original_name, variable)
mod_list(var_value, O, original_name, variable)
return
if(VV_RESTORE_DEFAULT)
var_new = initial(O.vars[variable])
if(VV_TEXT)
var/list/varsvars = vv_parse_text(O, var_new)
for(var/V in varsvars)
var_new = replacetext(var_new,"\[[V]]","[O.vars[V]]")
if (O.vv_edit_var(variable, var_new) == FALSE)
to_chat(src, "Your edit was rejected by the object.")
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]"
message_admins(msg)
admin_ticket_log(O, msg)
return TRUE
-25
View File
@@ -594,31 +594,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
admin_delete(A)
/client/proc/admin_delete(datum/D)
var/atom/A = D
var/coords = ""
var/jmp_coords = ""
if(istype(A))
var/turf/T = get_turf(A)
if(T)
coords = "at [COORD(T)]"
jmp_coords = "at [ADMIN_COORDJMP(T)]"
else
jmp_coords = coords = "in nullspace"
if (alert(src, "Are you sure you want to delete:\n[D]\n[coords]?", "Confirmation", "Yes", "No") == "Yes")
log_admin("[key_name(usr)] deleted [D] [coords]")
message_admins("[key_name_admin(usr)] deleted [D] [jmp_coords]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Delete") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
if(isturf(D))
var/turf/T = D
T.ScrapeAway()
else
vv_update_display(D, "deleted", VV_MSG_DELETED)
qdel(D)
if(!QDELETED(D))
vv_update_display(D, "deleted", "")
/client/proc/cmd_admin_list_open_jobs()
set category = "Admin"
set name = "Manage Job Slots"