mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-28 11:11:52 +00:00
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.
272 lines
7.2 KiB
Plaintext
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 |