Files
Paradise/code/modules/admin/verbs/massmodvar.dm
tigercat2000 60e287c019 VV Refactor
Ports /tg/'s VV refactor. Most of this is just cleaning up and making it
easier on the coders, but everyone else benefits too:

 - Mass mod no longer freezes the server (CHECK_TICK <3)
 - Attempting to change any of the step_* values or anything that will
 otherwise disable pixel movement will now prompt you and ask if you are
 sure you want to continue
 - You can actually enter |text| again in a box, rather than being
 forced to always use the multi-line input
 - Cookies! VV saves your search and scroll position for a given UID,
 rather convenient for debugging
 - The refresh button on /clients works finally
 - You can view lists in detail by clicking on them like any other
 reference, and edit them directly that way. This also means there is no
 hard limit on how many variables you can see in a list before it's
 truncated- it will just be hidden until you view the list in VV
 directly.
 - You can shuffle lists and clear duplicate/null entries.
 - Mildly reordered the stuff in the dropdown, inconvenient but
 necessary.
2017-09-14 14:08:38 -07:00

272 lines
7.2 KiB
Plaintext

/client/proc/cmd_mass_modify_object_variables(atom/A, var/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 itms)
if(!check_rights(R_VAREDIT)) return
if(A && A.type)
if(typesof(A.type))
switch(input("Strict object type detection?") as null|anything in list("Strictly this type","This type and subtypes", "Cancel"))
if("Strictly this type")
method = 0
if("This type and subtypes")
method = 1
if("Cancel")
return
if(null)
return
src.massmodify_variables(A, var_name, method)
feedback_add_details("admin_verb","MEV") //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 VVckey_edit)
to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.")
return
if(variable in VVlocked)
if(!check_rights(R_DEBUG))
return
if(variable in VVicon_edit_lock)
if(!check_rights(R_EVENT | R_DEBUG))
return
if(variable in 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(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(dir < 0 && dir < 16)
if(dir & 1)
dir_text += "NORTH"
if(dir & 2)
dir_text += "SOUTH"
if(dir & 4)
dir_text += "EAST"
if(dir & 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_to_dd("### 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 mob_list)
if(typecache[thing.type])
. += thing
CHECK_TICK
else if(ispath(T, /obj/machinery/door))
for(var/obj/machinery/door/thing in airlocks)
if(typecache[thing.type])
. += thing
CHECK_TICK
else if(ispath(T, /obj/machinery))
for(var/obj/machinery/thing in 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 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