diff --git a/code/__defines/MC.dm b/code/__defines/MC.dm index 2683922820..6acc667f2d 100644 --- a/code/__defines/MC.dm +++ b/code/__defines/MC.dm @@ -19,8 +19,8 @@ #define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;} -#define START_PROCESSING(Processor, Datum) if (!Datum.is_processing) {Datum.is_processing = TRUE;Processor.processing += Datum} -#define STOP_PROCESSING(Processor, Datum) Datum.is_processing = FALSE;Processor.processing -= Datum +#define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum} +#define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum //! SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier) diff --git a/code/__defines/_tick.dm b/code/__defines/_tick.dm index 5ba0eafd0e..54ac7d398d 100644 --- a/code/__defines/_tick.dm +++ b/code/__defines/_tick.dm @@ -1,3 +1,4 @@ + #define TICK_LIMIT_RUNNING 80 #define TICK_LIMIT_TO_RUN 70 #define TICK_LIMIT_MC 70 @@ -9,4 +10,6 @@ #define CHECK_TICK ( TICK_CHECK ? stoplag() : 0 ) #define TICK_CHECK_HIGH_PRIORITY ( TICK_USAGE > 95 ) -#define CHECK_TICK_HIGH_PRIORITY ( TICK_CHECK_HIGH_PRIORITY? stoplag() : 0 ) \ No newline at end of file +#define CHECK_TICK_HIGH_PRIORITY ( TICK_CHECK_HIGH_PRIORITY? stoplag() : 0 ) + +#define UNTIL(X) while(!(X)) stoplag() \ No newline at end of file diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm index 27b1afcc1c..b9417d2a86 100644 --- a/code/__defines/flags.dm +++ b/code/__defines/flags.dm @@ -1,6 +1,5 @@ -/* - These defines are specific to the atom/flags_1 bitmask -*/ +//MARK ALL FLAG CHANGES IN _globals/bitfields.dm! +//All flags should go in here if possible. #define ALL (~0) //For convenience. #define NONE 0 @@ -17,3 +16,4 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 // datum_flags #define DF_VAR_EDITED (1<<0) #define DF_ISPROCESSING (1<<1) + diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm new file mode 100644 index 0000000000..ed4a0dd10f --- /dev/null +++ b/code/__defines/is_helpers.dm @@ -0,0 +1,53 @@ + +#define isdatum(D) istype(D, /datum) +#define isweakref(A) istype(A, /weakref) + +#define islist(D) istype(D, /list) + +//--------------- +#define isatom(D) istype(D, /atom) + +//--------------- +//#define isobj(D) istype(D, /obj) //Built in + +#define isitem(D) istype(D, /obj/item) + +#define isairlock(A) istype(A, /obj/machinery/door/airlock) + +#define isorgan(A) istype(A, /obj/item/organ/external) + +//--------------- +//#define isarea(D) istype(D, /area) //Built in + +//--------------- +//#define ismob(D) istype(D, /mob) //Built in +#define isliving(A) istype(A, /mob/living) + +#define isobserver(A) istype(A, /mob/observer/dead) +#define isEye(A) istype(A, /mob/observer/eye) + +#define isnewplayer(A) istype(A, /mob/new_player) + +#define isanimal(A) istype(A, /mob/living/simple_mob) +#define ismouse(A) istype(A, /mob/living/simple_mob/animal/passive/mouse) +#define iscorgi(A) istype(A, /mob/living/simple_mob/animal/passive/dog/corgi) +#define isslime(A) istype(A, /mob/living/simple_mob/slime) +#define isxeno(A) istype(A, /mob/living/simple_mob/animal/space/alien) + +#define iscarbon(A) istype(A, /mob/living/carbon) +#define isalien(A) istype(A, /mob/living/carbon/alien) +#define isbrain(A) istype(A, /mob/living/carbon/brain) +#define ishuman(A) istype(A, /mob/living/carbon/human) + +#define issilicon(A) istype(A, /mob/living/silicon) +#define isAI(A) istype(A, /mob/living/silicon/ai) +#define isrobot(A) istype(A, /mob/living/silicon/robot) +#define ispAI(A) istype(A, /mob/living/silicon/pai) + +#define isbot(A) istype(A, /mob/living/bot) + +#define isvoice(A) istype(A, /mob/living/voice) + +//--------------- +//#define isturf(D) istype(D, /turf) //Built in +#define isopenspace(A) istype(A, /turf/simulated/open) diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm index d77b5cf297..95d4929acb 100644 --- a/code/__defines/machinery.dm +++ b/code/__defines/machinery.dm @@ -106,26 +106,15 @@ var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret #define ATMOS_DEFAULT_VOLUME_MIXER 200 // L. #define ATMOS_DEFAULT_VOLUME_PIPE 70 // L. +//wIP - PORT ALL OF THESE TO SUBSYSTEMS AND GET RID OF THE WHOLE LIST PROCESS THING // Fancy-pants START/STOP_PROCESSING() macros that lets us custom define what the list is. #define START_PROCESSING_IN_LIST(DATUM, LIST) \ -if (DATUM.is_processing) {\ - if(DATUM.is_processing != #LIST)\ - {\ - crash_with("Failed to start processing. [log_info_line(DATUM)] is already being processed by [DATUM.is_processing] but queue attempt occured on [#LIST]."); \ - }\ -} else {\ - DATUM.is_processing = #LIST;\ +if (!(DATUM.datum_flags & DF_ISPROCESSING)) {\ LIST += DATUM;\ + DATUM.datum_flags |= DF_ISPROCESSING\ } -#define STOP_PROCESSING_IN_LIST(DATUM, LIST) \ -if(DATUM.is_processing) {\ - if(LIST.Remove(DATUM)) {\ - DATUM.is_processing = null;\ - } else {\ - crash_with("Failed to stop processing. [log_info_line(DATUM)] is being processed by [is_processing] and not found in SSmachines.[#LIST]"); \ - }\ -} +#define STOP_PROCESSING_IN_LIST(DATUM, LIST) LIST.Remove(DATUM);DATUM.datum_flags &= ~DF_ISPROCESSING // Note - I would prefer these be defined machines.dm, but some are used prior in file order. ~Leshana #define START_MACHINE_PROCESSING(Datum) START_PROCESSING_IN_LIST(Datum, global.processing_machines) diff --git a/code/__defines/vv.dm b/code/__defines/vv.dm new file mode 100644 index 0000000000..97e3a02e0d --- /dev/null +++ b/code/__defines/vv.dm @@ -0,0 +1,46 @@ +#define VV_NUM "Number" +#define VV_TEXT "Text" +#define VV_MESSAGE "Mutiline Text" +#define VV_ICON "Icon" +#define VV_ATOM_REFERENCE "Atom Reference" +#define VV_DATUM_REFERENCE "Datum Reference" +#define VV_MOB_REFERENCE "Mob Reference" +#define VV_CLIENT "Client" +#define VV_ATOM_TYPE "Atom Typepath" +#define VV_DATUM_TYPE "Datum Typepath" +#define VV_TYPE "Custom Typepath" +#define VV_FILE "File" +#define VV_LIST "List" +#define VV_NEW_ATOM "New Atom" +#define VV_NEW_DATUM "New Datum" +#define VV_NEW_TYPE "New Custom Typepath" +#define VV_NEW_LIST "New List" +#define VV_NULL "NULL" +#define VV_RESTORE_DEFAULT "Restore to Default" +#define VV_MARKED_DATUM "Marked Datum" +#define VV_BITFIELD "Bitfield" + +#define VV_MSG_MARKED "
Marked Object" +#define VV_MSG_EDITED "
Var Edited" +#define VV_MSG_DELETED "
Deleted" + +#define VV_NORMAL_LIST_NO_EXPAND_THRESHOLD 50 +#define VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD 150 + +#define IS_VALID_ASSOC_KEY(V) (istext(V) || isdatum(V) || islist(V)) + +//Helpers for vv_get_dropdown() +#define VV_DROPDOWN_OPTION(href_key, name) . += "" + +//Helpers for vv_do_topic(list/href_list) +#define IF_VV_OPTION(href_key) if(href_list[href_key]) + +// /datum +#define VV_HK_DELETE "delete" +#define VV_HK_EXPOSE "expose" +#define VV_HK_CALLPROC "proc_call" +#define VV_HK_MARK "mark" + +// /atom +#define VV_HK_ATOM_EXPLODE "turf_explode" +#define VV_HK_ATOM_EMP "turf_emp" diff --git a/code/_global_vars/bitfields.dm b/code/_global_vars/bitfields.dm new file mode 100644 index 0000000000..891c50ce88 --- /dev/null +++ b/code/_global_vars/bitfields.dm @@ -0,0 +1,7 @@ +GLOBAL_LIST_INIT(bitfields, list( + "datum_flags" = list( + "DF_VAR_EDITED" = DF_VAR_EDITED, + "DF_ISPROCESSING" = DF_ISPROCESSING + ) + +)) diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index a1e7c8ea59..b29fa91b8b 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -904,9 +904,9 @@ proc/adjust_brightness(var/color, var/value) if (!value) return color var/list/RGB = ReadRGB(color) - RGB[1] = Clamp(RGB[1]+value,0,255) - RGB[2] = Clamp(RGB[2]+value,0,255) - RGB[3] = Clamp(RGB[3]+value,0,255) + RGB[1] = CLAMP(RGB[1]+value,0,255) + RGB[2] = CLAMP(RGB[2]+value,0,255) + RGB[3] = CLAMP(RGB[3]+value,0,255) return rgb(RGB[1],RGB[2],RGB[3]) proc/sort_atoms_by_layer(var/list/atoms) diff --git a/code/_helpers/lists.dm b/code/_helpers/lists.dm index 855aa9c138..b50db3457c 100644 --- a/code/_helpers/lists.dm +++ b/code/_helpers/lists.dm @@ -27,9 +27,6 @@ proc/listgetindex(var/list/list,index) return list[index] return -proc/islist(list/list) - return(istype(list)) - //Return either pick(list) or null if list is not of type /list or is empty proc/safepick(list/list) if(!islist(list) || !list.len) @@ -753,3 +750,9 @@ proc/dd_sortedTextList(list/incoming) for(var/i = 1 to l.len) if(islist(.[i])) .[i] = .(.[i]) + +//Return a list with no duplicate entries +/proc/uniqueList(list/L) + . = list() + for(var/i in L) + . |= i diff --git a/code/_helpers/matrices.dm b/code/_helpers/matrices.dm index 2e7247543c..a5ef701c2d 100644 --- a/code/_helpers/matrices.dm +++ b/code/_helpers/matrices.dm @@ -50,7 +50,7 @@ /proc/color_rotation(angle) if(angle == 0) return color_identity() - angle = Clamp(angle, -180, 180) + angle = CLAMP(angle, -180, 180) var/cos = cos(angle) var/sin = sin(angle) @@ -65,7 +65,7 @@ //Makes everything brighter or darker without regard to existing color or brightness /proc/color_brightness(power) - power = Clamp(power, -255, 255) + power = CLAMP(power, -255, 255) power = power/255 return list(1,0,0, 0,1,0, 0,0,1, power,power,power) @@ -85,7 +85,7 @@ //Exxagerates or removes brightness /proc/color_contrast(value) - value = Clamp(value, -100, 100) + value = CLAMP(value, -100, 100) if(value == 0) return color_identity() @@ -108,7 +108,7 @@ /proc/color_saturation(value as num) if(value == 0) return color_identity() - value = Clamp(value, -100, 100) + value = CLAMP(value, -100, 100) if(value > 0) value *= 3 var/x = 1 + value / 100 diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm index 0316e1d186..55dad2242f 100644 --- a/code/_helpers/type2type.dm +++ b/code/_helpers/type2type.dm @@ -242,3 +242,34 @@ /proc/isLeap(y) return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0)) + +//Takes a string and a datum +//The string is well, obviously the string being checked +//The datum is used as a source for var names, to check validity +//Otherwise every single word could technically be a variable! +/proc/string2listofvars(var/t_string, var/datum/var_source) + if(!t_string || !var_source) + return list() + + . = list() + + var/var_found = findtext(t_string,"\[") //Not the actual variables, just a generic "should we even bother" check + if(var_found) + //Find var names + + // "A dog said hi [name]!" + // splittext() --> list("A dog said hi ","name]!" + // jointext() --> "A dog said hi name]!" + // splittext() --> list("A","dog","said","hi","name]!") + + t_string = replacetext(t_string,"\[","\[ ")//Necessary to resolve "word[var_name]" scenarios + var/list/list_value = splittext(t_string,"\[") + var/intermediate_stage = jointext(list_value, null) + + list_value = splittext(intermediate_stage," ") + for(var/value in list_value) + if(findtext(value,"]")) + value = splittext(value,"]") //"name]!" --> list("name","!") + for(var/A in value) + if(var_source.vars.Find(A)) + . += A diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 8bd5a5055c..eccf77399a 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -1464,3 +1464,92 @@ var/mob/dview/dview_mob = new return #define NAMEOF(datum, X) (#X || ##datum.##X) + +/proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types()) + if (value == FALSE) //nothing should be calling us with a number, so this is safe + value = input("Enter type to find (blank for all, cancel to cancel)", "Search for type") as null|text + if (isnull(value)) + return + value = trim(value) + if(!isnull(value) && value != "") + matches = filter_fancy_list(matches, value) + + if(matches.len==0) + return + + var/chosen + if(matches.len==1) + chosen = matches[1] + else + chosen = input("Select a type", "Pick Type", matches[1]) as null|anything in matches + if(!chosen) + return + chosen = matches[chosen] + return chosen + +/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 + +/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/device/radio/headset = "HEADSET", + /obj/item/clothing/head/helmet/space = "SPESSHELMET", + /obj/item/weapon/book/manual = "MANUAL", + /obj/item/weapon/reagent_containers/food/drinks = "DRINK", + /obj/item/weapon/reagent_containers/food = "FOOD", + /obj/item/weapon/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/simulated/wall = "S-WALL", + /turf/simulated/floor = "S-FLOOR", + /turf/simulated = "SIMULATED", + /turf/unsimulated/wall = "US-WALL", + /turf/unsimulated/floor = "US-FLOOR", + /turf/unsimulated = "UNSIMULATED", + /turf = "T", + /mob/living/carbon = "CARBON", + /mob/living/simple_mob = "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/IsValidSrc(datum/D) + if(istype(D)) + return !QDELETED(D) + return FALSE diff --git a/code/_macros.dm b/code/_macros.dm index e6c6e10636..0af691a90c 100644 --- a/code/_macros.dm +++ b/code/_macros.dm @@ -1,57 +1,7 @@ -#define Clamp(x, y, z) (x <= y ? y : (x >= z ? z : x)) - -#define CLAMP01(x) (Clamp(x, 0, 1)) - #define span(class, text) ("[text]") #define get_turf(A) get_step(A,0) -#define isAI(A) istype(A, /mob/living/silicon/ai) - -#define isalien(A) istype(A, /mob/living/carbon/alien) - -#define isanimal(A) istype(A, /mob/living/simple_mob) - -#define isairlock(A) istype(A, /obj/machinery/door/airlock) - -#define isbrain(A) istype(A, /mob/living/carbon/brain) - -#define iscarbon(A) istype(A, /mob/living/carbon) - -#define iscorgi(A) istype(A, /mob/living/simple_mob/animal/passive/dog/corgi) - -#define isEye(A) istype(A, /mob/observer/eye) - -#define ishuman(A) istype(A, /mob/living/carbon/human) - -#define isliving(A) istype(A, /mob/living) - -#define ismouse(A) istype(A, /mob/living/simple_mob/animal/passive/mouse) - -#define isnewplayer(A) istype(A, /mob/new_player) - -#define isobserver(A) istype(A, /mob/observer/dead) - -#define isorgan(A) istype(A, /obj/item/organ/external) - -#define ispAI(A) istype(A, /mob/living/silicon/pai) - -#define isrobot(A) istype(A, /mob/living/silicon/robot) - -#define issilicon(A) istype(A, /mob/living/silicon) - -#define isvoice(A) istype(A, /mob/living/voice) - -#define isslime(A) istype(A, /mob/living/simple_mob/slime) - -#define isbot(A) istype(A, /mob/living/bot) - -#define isxeno(A) istype(A, /mob/living/simple_mob/animal/space/alien) - -#define isopenspace(A) istype(A, /turf/simulated/open) - -#define isweakref(A) istype(A, /weakref) - #define RANDOM_BLOOD_TYPE pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+") #define to_chat(target, message) target << message diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm index fa7b917194..56a9244347 100644 --- a/code/controllers/globals.dm +++ b/code/controllers/globals.dm @@ -38,8 +38,10 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars) stat("Globals:", statclick.update("Edit")) -/datum/controller/global_vars/VV_hidden() - return ..() + gvars_datum_protected_varlist +/datum/controller/global_vars/vv_edit_var(var_name, var_value) + if(gvars_datum_protected_varlist[var_name]) + return FALSE + return ..() /datum/controller/global_vars/Initialize(var/exclude_these) gvars_datum_init_order = list() diff --git a/code/controllers/subsystems/machines.dm b/code/controllers/subsystems/machines.dm index 4cba70a981..4525175393 100644 --- a/code/controllers/subsystems/machines.dm +++ b/code/controllers/subsystems/machines.dm @@ -109,7 +109,7 @@ SUBSYSTEM_DEF(machines) else global.pipe_networks.Remove(PN) if(!QDELETED(PN)) - PN.is_processing = null + DISABLE_BITFIELD(PN.datum_flags, DF_ISPROCESSING) if(MC_TICK_CHECK) return @@ -127,7 +127,7 @@ SUBSYSTEM_DEF(machines) else global.processing_machines.Remove(M) if(!QDELETED(M)) - M.is_processing = null + DISABLE_BITFIELD(M.datum_flags, DF_ISPROCESSING) if(MC_TICK_CHECK) return @@ -144,7 +144,7 @@ SUBSYSTEM_DEF(machines) else global.powernets.Remove(PN) if(!QDELETED(PN)) - PN.is_processing = null + DISABLE_BITFIELD(PN.datum_flags, DF_ISPROCESSING) if(MC_TICK_CHECK) return @@ -160,7 +160,7 @@ SUBSYSTEM_DEF(machines) current_run.len-- if(!I.pwr_drain(wait)) // 0 = Process Kill, remove from processing list. global.processing_power_items.Remove(I) - I.is_processing = null + DISABLE_BITFIELD(I.datum_flags, DF_ISPROCESSING) if(MC_TICK_CHECK) return diff --git a/code/datums/browser.dm b/code/datums/browser.dm index 577698532e..ea2f4feec2 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -105,6 +105,10 @@ "} /datum/browser/proc/open(var/use_onclose = 1) + if(isnull(window_id)) //null check because this can potentially nuke goonchat + WARNING("Browser [title] tried to open with a null ID") + to_chat(user, "The [title] browser you tried to open failed a sanity check! Please report this on github!") + return var/window_size = "" if (width && height) window_size = "size=[width]x[height];" @@ -112,9 +116,6 @@ if (use_onclose) onclose(user, window_id, ref) -/datum/browser/proc/close() - user << browse(null, "window=[window_id]") - // This will allow you to show an icon in the browse window // This is added to mob so that it can be used without a reference to the browser object // There is probably a better place for this... @@ -157,12 +158,12 @@ //world << "OnClose [user]: [windowid] : ["on-close=\".windowclose [param]\""]" - // the on-close client verb // called when a browser popup window is closed after registering with proc/onclose() // if a valid atom reference is supplied, call the atom's Topic() with "close=1" // otherwise, just reset the client mob's machine var. // + /client/verb/windowclose(var/atomref as text) set hidden = 1 // hide this verb from the user's panel set name = ".windowclose" // no autocomplete on cmd line @@ -182,3 +183,198 @@ //world << "[src] was [src.mob.machine], setting to null" src.mob.unset_machine() return + +/datum/browser/proc/close() + if(!isnull(window_id))//null check because this can potentially nuke goonchat + user << browse(null, "window=[window_id]") + else + WARNING("Browser [title] tried to close with a null ID") + +/datum/browser/modal/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000) + if (!User) + return + + var/output = {"
[Message]

+
+ [Button1]"} + + if (Button2) + output += {"[Button2]"} + + if (Button3) + output += {"[Button3]"} + + output += {"
"} + + ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, 350, 150, src, StealFocus, Timeout) + set_content(output) + +/datum/browser/modal/alert/Topic(href,href_list) + if (href_list["close"] || !user || !user.client) + opentime = 0 + return + if (href_list["button"]) + var/button = text2num(href_list["button"]) + if (button <= 3 && button >= 1) + selectedbutton = button + opentime = 0 + close() + +//designed as a drop in replacement for alert(); functions the same. (outside of needing User specified) +/proc/tgalert(var/mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) + if (!User) + User = usr + switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)) + if (1) + return Button1 + if (2) + return Button2 + if (3) + return Button3 + +//Same shit, but it returns the button number, could at some point support unlimited button amounts. +/proc/askuser(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) + if (!istype(User)) + if (istype(User, /client/)) + var/client/C = User + User = C.mob + else + return + var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout) + A.open() + A.wait() + if (A.selectedbutton) + return A.selectedbutton + +/datum/browser/modal + var/opentime = 0 + var/timeout + var/selectedbutton = 0 + var/stealfocus + +/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, StealFocus = 1, Timeout = 6000) + ..() + stealfocus = StealFocus + if (!StealFocus) + window_options += "focus=false;" + timeout = Timeout + + +/datum/browser/modal/close() + .=..() + opentime = 0 + +/datum/browser/modal/open() + set waitfor = 0 + opentime = world.time + + if (stealfocus) + . = ..(use_onclose = 1) + else + var/focusedwindow = winget(user, null, "focus") + . = ..(use_onclose = 1) + + //waits for the window to show up client side before attempting to un-focus it + //winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping + for (var/i in 1 to 10) + if (user && winexists(user, window_id)) + if (focusedwindow) + winset(user, focusedwindow, "focus=true") + else + winset(user, "mapwindow", "focus=true") + break + if (timeout) + addtimer(CALLBACK(src, .proc/close), timeout) + +/datum/browser/modal/proc/wait() + while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time)) + stoplag(1) + +/datum/browser/modal/listpicker + var/valueslist = list() + +/datum/browser/modal/listpicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/values,inputtype="checkbox", width, height, slidecolor) + if (!User) + return + + var/output = {"
+ "} + + if (Button2) + output += {""} + + if (Button3) + output += {""} + + output += {"
"} + ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout) + set_content(output) + +/datum/browser/modal/listpicker/Topic(href,href_list) + if (href_list["close"] || !user || !user.client) + opentime = 0 + return + if (href_list["button"]) + var/button = text2num(href_list["button"]) + if (button <= 3 && button >= 1) + selectedbutton = button + for (var/item in href_list) + switch(item) + if ("close", "button", "src") + continue + else + valueslist[item] = href_list[item] + opentime = 0 + close() + +/proc/presentpicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor) + if (!istype(User)) + if (istype(User, /client/)) + var/client/C = User + User = C.mob + else + return + var/datum/browser/modal/listpicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, values, inputtype, width, height, slidecolor) + A.open() + A.wait() + if (A.selectedbutton) + return list("button" = A.selectedbutton, "values" = A.valueslist) + +/proc/input_bitfield(var/mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null) + if (!User || !(bitfield in GLOB.bitfields)) + return + var/list/pickerlist = list() + for (var/i in GLOB.bitfields[bitfield]) + var/can_edit = 1 + if(!isnull(allowed_edit_list) && !(allowed_edit_list & GLOB.bitfields[bitfield][i])) + can_edit = 0 + if (current_value & GLOB.bitfields[bitfield][i]) + pickerlist += list(list("checked" = 1, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit)) + else + pickerlist += list(list("checked" = 0, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit)) + var/list/result = presentpicker(User, "", title, Button1="Save", Button2 = "Cancel", Timeout=FALSE, values = pickerlist, width = nwidth, height = nheight, slidecolor = nslidecolor) + if (islist(result)) + if (result["button"] == 2) // If the user pressed the cancel button + return + . = 0 + for (var/flag in result["values"]) + . |= GLOB.bitfields[bitfield][flag] + else + return diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 36d430a0ed..833a442e30 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -7,7 +7,7 @@ var/gc_destroyed //Time when this object was destroyed. var/list/active_timers //for SStimer var/weakref/weakref // Holder of weakref instance pointing to this datum - var/is_processing //If is processing, may or may not have the name of the list it's in. + var/datum_flags = NONE #ifdef TESTING var/tmp/running_find_references diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 1938b0d913..aa28473fa3 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1,21 +1,68 @@ -#define VV_MSG_MARKED "
Marked Object" -#define VV_MSG_EDITED "
Var Edited" -#define VV_MSG_DELETED "
Deleted" - /datum/proc/CanProcCall(procname) return TRUE /datum/proc/can_vv_get(var_name) - //Pending refactor of vv_hidden - //return TRUE - - return !(var_name in VV_hidden()) + return TRUE /datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited - //Pending refactor of vv_static - //if(var_name == NAMEOF(src, vars)) - // return FALSE - if(var_name in VV_static()) + if(var_name == NAMEOF(src, vars) || var_name == NAMEOF(src, parent_type)) return FALSE vars[var_name] = var_value + datum_flags |= DF_VAR_EDITED return TRUE + +/datum/proc/vv_get_var(var_name) + switch(var_name) + if ("vars") + return debug_variable(var_name, list(), 0, src) + return debug_variable(var_name, vars[var_name], 0, src) + +//please call . = ..() first and append to the result, that way parent items are always at the top and child items are further down +//add separaters by doing . += "---" +/datum/proc/vv_get_dropdown() + . = 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_DELETE, "Delete") + VV_DROPDOWN_OPTION(VV_HK_EXPOSE, "Show VV To Player") + +//This proc is only called if everything topic-wise is verified. The only verifications that should happen here is things like permission checks! +//href_list is a reference, modifying it in these procs WILL change the rest of the proc in topic.dm of admin/view_variables! +/datum/proc/vv_do_topic(list/href_list) + if(!usr || !usr.client.holder) + return //This is VV, not to be called by anything else. + IF_VV_OPTION(VV_HK_EXPOSE) + if(!check_rights(R_ADMIN, FALSE)) + return + var/value = usr.client.vv_get_value(VV_CLIENT) + if (value["class"] != VV_CLIENT) + return + var/client/C = value["value"] + if (!C) + return + var/prompt = alert("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", "Yes", "No") + if (prompt != "Yes" || !usr.client) + return + message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a VV window") + log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [src]") + to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window") + C.debug_variables(src) + IF_VV_OPTION(VV_HK_DELETE) + if(!check_rights(R_DEBUG)) + return + usr.client.admin_delete(src) + if (isturf(src)) // show the turf that took its place + usr.client.debug_variables(src) + IF_VV_OPTION(VV_HK_MARK) + usr.client.mark_datum(src) + IF_VV_OPTION(VV_HK_CALLPROC) + usr.client.callproc_datum(src) + +/datum/proc/vv_get_header() + . = list() + if(("name" in vars) && !isatom(src)) + . += "[vars["name"]]
" + +/datum/proc/on_reagent_change(changetype) + return diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm index bf38ab7a1c..581dc012f8 100644 --- a/code/datums/progressbar.dm +++ b/code/datums/progressbar.dm @@ -39,7 +39,7 @@ shown = 0 client = user.client - progress = Clamp(progress, 0, goal) + progress = CLAMP(progress, 0, goal) bar.icon_state = "prog_bar_[round(((progress / goal) * 100), 5)]" if (!shown && user.is_preference_enabled(/datum/client_preference/show_progress_bar)) user.client.images += bar diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 4d71c4af27..29af4ba677 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -97,9 +97,6 @@ return 0 return -1 -/atom/proc/on_reagent_change() - return - /atom/proc/Bumped(AM as mob|obj) return @@ -534,3 +531,35 @@ /atom/proc/get_nametag_desc(mob/user) return "" //Desc itself is often too long to use + +/atom/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION(VV_HK_ATOM_EXPLODE, "Explosion") + VV_DROPDOWN_OPTION(VV_HK_ATOM_EMP, "Emp Pulse") + +/atom/vv_do_topic(list/href_list) + . = ..() + IF_VV_OPTION(VV_HK_ATOM_EXPLODE) + if(!check_rights(R_DEBUG|R_FUN)) + return + usr.client.cmd_admin_explosion(src) + href_list["datumrefresh"] = "\ref[src]" + IF_VV_OPTION(VV_HK_ATOM_EMP) + if(!check_rights(R_DEBUG|R_FUN)) + return + usr.client.cmd_admin_emp(src) + href_list["datumrefresh"] = "\ref[src]" + +/atom/vv_get_header() + . = ..() + var/custom_edit_name + if(!isliving(src)) + custom_edit_name = "[src]" + . += {" + [custom_edit_name] +
+ << + [dir2text(dir)] + >> + + "} diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index f19a74f3c4..b06a1db623 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -42,6 +42,11 @@ pulledby = null QDEL_NULL(riding_datum) //VOREStation Add +/atom/movable/vv_edit_var(var_name, var_value) + if(GLOB.VVpixelmovement[var_name]) //Pixel movement is not yet implemented, changing this will break everything irreversibly. + return FALSE + return ..() + /atom/movable/Bump(var/atom/A, yes) if(src.throwing) src.throw_impact(A) diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index f249d7a8e7..b2d9be7c35 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -136,7 +136,7 @@ . = 1 if (href_list["volume_adj"]) var/diff = text2num(href_list["volume_adj"]) - volume_rate = Clamp(volume_rate+diff, minrate, maxrate) + volume_rate = CLAMP(volume_rate+diff, minrate, maxrate) . = 1 update_icon() diff --git a/code/game/machinery/bomb_tester_vr.dm b/code/game/machinery/bomb_tester_vr.dm index 66d71f923d..224885d9ca 100644 --- a/code/game/machinery/bomb_tester_vr.dm +++ b/code/game/machinery/bomb_tester_vr.dm @@ -201,7 +201,7 @@ if(href_list["set_can_pressure"]) var/change = text2num(href_list["set_can_pressure"]) - sim_canister_output = Clamp(sim_canister_output+change, ONE_ATMOSPHERE/10, ONE_ATMOSPHERE*10) + sim_canister_output = CLAMP(sim_canister_output+change, ONE_ATMOSPHERE/10, ONE_ATMOSPHERE*10) if(href_list["start_sim"]) start_simulating() diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 9132cf4b12..bd1d9cbd12 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -40,7 +40,7 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa if(dist <= round(max_range + world.view - 2, 1)) M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound else if(dist <= far_dist) - var/far_volume = Clamp(far_dist, 30, 50) // Volume is based on explosion size and dist + var/far_volume = CLAMP(far_dist, 30, 50) // Volume is based on explosion size and dist far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5) diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index 7f0b8b6dac..26fb1b69aa 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -503,7 +503,7 @@ var/obj/item/organ/internal/brain/brain = H.internal_organs_by_name[O_BRAIN] if(!brain) return //no brain - var/brain_damage = Clamp((deadtime - DEFIB_TIME_LOSS)/(DEFIB_TIME_LIMIT - DEFIB_TIME_LOSS)*brain.max_damage, H.getBrainLoss(), brain.max_damage) + var/brain_damage = CLAMP((deadtime - DEFIB_TIME_LOSS)/(DEFIB_TIME_LIMIT - DEFIB_TIME_LOSS)*brain.max_damage, H.getBrainLoss(), brain.max_damage) H.setBrainLoss(brain_damage) /obj/item/weapon/shockpaddles/proc/make_announcement(var/message, var/msg_class) diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 5290ac7479..86e3badc6f 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -37,7 +37,7 @@ /obj/item/weapon/plastique/attack_self(mob/user as mob) var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num if(user.get_active_hand() == src) - newtime = Clamp(newtime, 10, 60000) + newtime = CLAMP(newtime, 10, 60000) timer = newtime user << "Timer set for [timer] seconds." diff --git a/code/game/objects/items/weapons/implants/implant_vr.dm b/code/game/objects/items/weapons/implants/implant_vr.dm index 006c4884e1..bf67f83953 100644 --- a/code/game/objects/items/weapons/implants/implant_vr.dm +++ b/code/game/objects/items/weapons/implants/implant_vr.dm @@ -105,9 +105,9 @@ if(size_mult.Find(msg)) var/resizing_value = text2num(size_mult.match) if(findtext(msg, "centimeter")) //Because metric system rules - H.resize(Clamp(resizing_value/170 , 0.25, 2)) //170 cm is average crewmember, I think + H.resize(CLAMP(resizing_value/170 , 0.25, 2)) //170 cm is average crewmember, I think else - H.resize(Clamp(resizing_value , 0.25, 2)) + H.resize(CLAMP(resizing_value , 0.25, 2)) diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 79197e7a7b..f5ff602fa4 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -503,7 +503,7 @@ var/list/global/tank_gauge_cache = list() var/release_ratio = 0.002 if(tank_pressure) - release_ratio = Clamp(0.002, sqrt(max(tank_pressure-env_pressure,0)/tank_pressure),1) + release_ratio = CLAMP(0.002, sqrt(max(tank_pressure-env_pressure,0)/tank_pressure),1) var/datum/gas_mixture/leaked_gas = air_contents.remove_ratio(release_ratio) //dynamic air release based on ambient pressure diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 8c2d8e70fd..a24f2868da 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -54,7 +54,7 @@ color = girder_material.icon_colour if(girder_material.products_need_process()) //Am I radioactive or some other? Process me! START_PROCESSING(SSobj, src) - else if(is_processing) //If I happened to be radioactive or s.o. previously, and am not now, stop processing. + else if(datum_flags & DF_ISPROCESSING) //If I happened to be radioactive or s.o. previously, and am not now, stop processing. STOP_PROCESSING(SSobj, src) /obj/structure/girder/get_material() diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index f3e820e5cd..c57b0ff80a 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -6,6 +6,7 @@ var/list/admin_verbs_default = list( /client/proc/hide_verbs, //hides all our adminverbs, /client/proc/hide_most_verbs, //hides all our hideable adminverbs, /client/proc/debug_variables, //allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify, + /client/proc/mark_datum_mapview, /client/proc/cmd_check_new_players, //allows us to see every new player // /client/proc/check_antagonists, //shows all antags, // /client/proc/cmd_mod_say, @@ -214,7 +215,7 @@ var/list/admin_verbs_debug = list( /client/proc/show_plant_genes, /client/proc/enable_debug_verbs, /client/proc/callproc, - /client/proc/callproc_target, + /client/proc/callproc_datum, /client/proc/debug_process, //VOREStation Add, /client/proc/SDQL2_query, /client/proc/Jump, @@ -234,7 +235,7 @@ var/list/admin_verbs_debug = list( var/list/admin_verbs_paranoid_debug = list( /client/proc/callproc, - /client/proc/callproc_target, + /client/proc/callproc_datum, /client/proc/debug_process, //VOREStation Add, /client/proc/debug_controller ) @@ -303,7 +304,7 @@ var/list/admin_verbs_hideable = list( /client/proc/restart_controller, /client/proc/cmd_admin_list_open_jobs, /client/proc/callproc, - /client/proc/callproc_target, + /client/proc/callproc_datum, /client/proc/debug_process, //VOREStation Add, /client/proc/Debug2, /client/proc/reload_admins, @@ -372,7 +373,7 @@ var/list/admin_verbs_event_manager = list( /proc/possess, /proc/release, /client/proc/callproc, - /client/proc/callproc_target, + /client/proc/callproc_datum, /client/proc/debug_controller, /client/proc/show_gm_status, /datum/admins/proc/change_weather, diff --git a/code/modules/admin/callproc/callproc.dm b/code/modules/admin/callproc/callproc.dm index df7937d2c5..4b0b70a05d 100644 --- a/code/modules/admin/callproc/callproc.dm +++ b/code/modules/admin/callproc/callproc.dm @@ -1,152 +1,210 @@ - /client/proc/callproc() set category = "Debug" set name = "Advanced ProcCall" + set waitfor = 0 - if(!check_rights(R_DEBUG)) return - if(config.debugparanoid && !check_rights(R_ADMIN)) return + if(!check_rights(R_DEBUG)) + return - var/target = null + var/datum/target = null var/targetselected = 0 - - switch(alert("Proc owned by something?",, "Yes", "No", "Cancel")) - if("Yes") - targetselected=1 - switch(input("Proc owned by...", "Owner", null) as null|anything in list("Obj", "Mob", "Area or Turf", "Client")) - if("Obj") - target = input("Select target:", "Target") as null|obj in world - if("Mob") - target = input("Select target:", "Target", usr) as null|mob in world - if("Area or Turf") - target = input("Select target:", "Target", get_turf(usr)) as null|area|turf in world - if("Client") - target = input("Select target:", "Target", usr.client) as null|anything in GLOB.clients - else - return - if(!target) - usr << "Proc call cancelled." - return - if("Cancel") - return - if("No") - ; // do nothing - - callproc_targetpicked(targetselected, target) - -/client/proc/callproc_target(atom/A in world) - set category = "Debug" - set name = "Advanced ProcCall Target" - - if(!check_rights(R_DEBUG)) return - if(config.debugparanoid && !check_rights(R_ADMIN)) return - - callproc_targetpicked(1, A) - -/client/proc/callproc_targetpicked(hastarget, datum/target) - - // this needs checking again here because VV's 'Call Proc' option directly calls this proc with the target datum - if(!check_rights(R_DEBUG)) return - if(config.debugparanoid && !check_rights(R_ADMIN)) return - var/returnval = null - var/procname = input("Proc name", "Proc") as null|text - if(!procname) return - - if(hastarget) - if(!target) - usr << "Your callproc target no longer exists." - return - if(!hascall(target, procname)) - usr << "\The [target] has no call [procname]()" - return - - var/list/arguments = list() - var/done = 0 - var/current = null - - while(!done) - if(hastarget && !target) - usr << "Your callproc target no longer exists." - return - switch(input("Type of [arguments.len+1]\th variable", "argument [arguments.len+1]") as null|anything in list( - "finished", "null", "text", "num", "type", "obj reference", "mob reference", - "area/turf reference", "icon", "file", "client", "mob's area", "marked datum")) - if(null) + switch(alert("Proc owned by something?",,"Yes","No")) + if("Yes") + targetselected = 1 + 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"] + if("No") + target = null + targetselected = 0 - if("finished") - done = 1 + var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null + if(!procname) + return - if("null") - current = null + //hascall() doesn't support proc paths (eg: /proc/gib(), it only supports "gib") + var/testname = procname + if(targetselected) + //Find one of the 3 possible ways they could have written /proc/PROCNAME + if(findtext(procname, "/proc/")) + testname = replacetext(procname, "/proc/", "") + else if(findtext(procname, "/proc")) + testname = replacetext(procname, "/proc", "") + else if(findtext(procname, "proc/")) + testname = replacetext(procname, "proc/", "") + //Clear out any parenthesis if they're a dummy + testname = replacetext(testname, "()", "") - if("text") - current = input("Enter text for [arguments.len+1]\th argument") as null|text - if(isnull(current)) return - - if("num") - current = input("Enter number for [arguments.len+1]\th argument") as null|num - if(isnull(current)) return - - if("type") - current = input("Select type for [arguments.len+1]\th argument") as null|anything in typesof(/obj, /mob, /area, /turf) - if(isnull(current)) return - - if("obj reference") - current = input("Select object for [arguments.len+1]\th argument") as null|obj in world - if(isnull(current)) return - - if("mob reference") - current = input("Select mob for [arguments.len+1]\th argument") as null|mob in world - if(isnull(current)) return - - if("area/turf reference") - current = input("Select area/turf for [arguments.len+1]\th argument") as null|area|turf in world - if(isnull(current)) return - - if("icon") - current = input("Provide icon for [arguments.len+1]\th argument") as null|icon - if(isnull(current)) return - - if("client") - current = input("Select client for [arguments.len+1]\th argument") as null|anything in GLOB.clients - if(isnull(current)) return - - if("mob's area") - var/mob/M = input("Select mob to take area for [arguments.len+1]\th argument") as null|mob in world - if(!M) return - current = get_area(M) - if(!current) - switch(alert("\The [M] appears to not have an area; do you want to pass null instead?",, "Yes", "Cancel")) - if("Yes") - ; // do nothing - if("Cancel") - return - - if("marked datum") - current = holder.marked_datum - if(!current) - switch(alert("You do not currently have a marked datum; do you want to pass null instead?",, "Yes", "Cancel")) - if("Yes") - ; // do nothing - if("Cancel") - return - if(!done) - arguments += current - - if(hastarget) - if(!target) - usr << "Your callproc target no longer exists." - return - log_admin("[key_name(src)] called [target]'s [procname]() with [arguments.len ? "the arguments [list2params(arguments)]" : "no arguments"].") - if(arguments.len) - returnval = call(target, procname)(arglist(arguments)) - else - returnval = call(target, procname)() + if(targetselected && !hascall(target,testname)) + to_chat(usr, "Error: callproc(): type [target.type] has no proc named [procname].") + return else - log_admin("[key_name(src)] called [procname]() with [arguments.len ? "the arguments [list2params(arguments)]" : "no arguments"].") - returnval = call(procname)(arglist(arguments)) + var/procpath = text2path(procname) + if (!procpath) + to_chat(usr, "Error: callproc(): proc [procname] does not exist. (Did you forget the /proc/ part?)") + return + var/list/lst = get_callproc_args() + if(!lst) + return - usr << "[procname]() returned: [isnull(returnval) ? "null" : returnval]" + if(targetselected) + if(!target) + to_chat(usr, "Error: callproc(): owner of proc no longer exists.") + return + var/msg = "[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]." + log_admin(msg) + //message_admins(msg) //Proccall announce removed. + admin_ticket_log(target, msg) + returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc + else + //this currently has no hascall protection. wasn't able to get it working. + log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") + //message_admins("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") //Proccall announce removed. + returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc + . = get_callproc_returnval(returnval, procname) + if(.) + to_chat(usr, .) feedback_add_details("admin_verb","APC") //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 && procname == "Del") + to_chat(usr, "Calling Del() is not allowed") + 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, "Another set of admin called procs are still running, your proc will be run after theirs finish.") + GLOB.AdminProcCallSpamPrevention[ckey] = TRUE + UNTIL(!GLOB.AdminProcCaller) + to_chat(usr, "Running your proc") + 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("[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 = 0 + + 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, "Error: callproc_datum(): type [A.type] has no proc named [procname].") + return + var/list/lst = get_callproc_args() + if(!lst) + return + + if(!A || !IsValidSrc(A)) + to_chat(usr, "Error: callproc_datum(): owner of proc no longer exists.") + return + log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].") + var/msg = "[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]." + message_admins(msg) + admin_ticket_log(A, msg) + feedback_add_details("admin_verb","TPC") //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 null //Cancel + + . = list() + //var/list/named_args = list() //Named arguments are removed, due to them making proccalling take too long. + while(argnum--) + /* //Named arguments are removed, due to them making proccalling take too long. + 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 + if(isnull(named_arg)) + return null //Cancel + */ + var/value = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT)) + if (!value["class"]) + return null //Cancel + /* + if(named_arg) + named_args[named_arg] = value["value"] + else + . += value["value"] + if(LAZYLEN(named_args)) + . += named_args + */ + . += value["value"] + +/client/proc/get_callproc_returnval(returnval,procname) + . = "" + if(islist(returnval)) + var/list/returnedlist = returnval + . = "" + 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" + . += "" + + else + . = "[procname] returned: [!isnull(returnval) ? returnval : "null"]" diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 2d74b43433..114808d3d3 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -47,6 +47,12 @@ var/list/admin_datums = list() owner.deadmin_holder = null owner.add_admin_verbs() +/datum/admins/vv_edit_var(var_name, var_value) + if(var_name == NAMEOF(src, rights) || var_name == NAMEOF(src, owner) || var_name == NAMEOF(src, rank)) + return FALSE + return ..() + +//TODO: Proccall guard, when all try/catch are removed and WrapAdminProccall is ported. /* checks if usr is an admin with at least ONE of the flags in rights_required. (Note, they don't need all the flags) @@ -95,7 +101,18 @@ NOTE: It checks usr by default. Supply the "user" argument if you wish to check usr << "Error: Cannot proceed. They have more or equal rights to us." return 0 +/client/proc/mark_datum(datum/D) + if(!holder) + return + if(holder.marked_datum) + vv_update_display(holder.marked_datum, "marked", "") + holder.marked_datum = D + vv_update_display(D, "marked", VV_MSG_MARKED) +/client/proc/mark_datum_mapview(datum/D as mob|obj|turf|area in view(view)) + set category = "Debug" + set name = "Mark Object" + mark_datum(D) /client/proc/deadmin() if(holder) diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index 571d709f6e..58f568cfa7 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -747,8 +747,8 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null new_args[++new_args.len] = SDQL_expression(source, arg) if(object == GLOB) // Global proc. procname = "/proc/[procname]" - return call(procname)(arglist(new_args)) - return call(object, procname)(arglist(new_args)) + return superuser? (call(procname)(new_args)) : (WrapAdminProcCall(GLOBAL_PROC, procname, new_args)) + return superuser? (call(object, procname)(new_args)) : (WrapAdminProcCall(object, procname, new_args)) /datum/SDQL2_query/proc/SDQL_function_async(datum/object, procname, list/arguments, source) set waitfor = FALSE diff --git a/code/modules/admin/verbs/massmodvar.dm b/code/modules/admin/verbs/massmodvar.dm deleted file mode 100644 index 09178d650e..0000000000 --- a/code/modules/admin/verbs/massmodvar.dm +++ /dev/null @@ -1,375 +0,0 @@ -/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(var/atom/O, var/var_name = "", var/method = 0) - if(!check_rights(R_VAREDIT)) return - - var/list/locked = list("vars", "key", "ckey", "client") - - for(var/p in forbidden_varedit_object_types) - if( istype(O,p) ) - usr << "It is forbidden to edit this object's variables." - return - - var/list/names = list() - for (var/V in O.vars) - names += V - - names = sortList(names) - - var/variable = "" - - if(!var_name) - variable = input("Which var?","Var") as null|anything in names - else - variable = var_name - - if(!variable) return - var/default - var/var_value = O.vars[variable] - var/dir - - if(variable == "holder" || (variable in locked)) - if(!check_rights(R_DEBUG)) return - - if(isnull(var_value)) - usr << "Unable to determine variable type." - - else if(isnum(var_value)) - usr << "Variable appears to be NUM." - default = "num" - dir = 1 - - else if(istext(var_value)) - usr << "Variable appears to be TEXT." - default = "text" - - else if(isloc(var_value)) - usr << "Variable appears to be REFERENCE." - default = "reference" - - else if(isicon(var_value)) - usr << "Variable appears to be ICON." - var_value = "\icon[var_value]" - default = "icon" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) - usr << "Variable appears to be TYPE." - default = "type" - - else if(istype(var_value,/list)) - usr << "Variable appears to be LIST." - default = "list" - - else if(istype(var_value,/client)) - usr << "Variable appears to be CLIENT." - default = "cancel" - - else - usr << "Variable appears to be FILE." - default = "file" - - usr << "Variable contains: [var_value]" - if(dir) - switch(var_value) - if(1) - dir = "NORTH" - if(2) - dir = "SOUTH" - if(4) - dir = "EAST" - if(8) - dir = "WEST" - if(5) - dir = "NORTHEAST" - if(6) - dir = "SOUTHEAST" - if(9) - dir = "NORTHWEST" - if(10) - dir = "SOUTHWEST" - else - dir = null - if(dir) - usr << "If a direction, direction is: [dir]" - - var/class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","icon","file","edit referenced object","restore to default") - - if(!class) - return - - var/original_name - - if (!istype(O, /atom)) - original_name = "\ref[O] ([O])" - else - original_name = O:name - - switch(class) - - if("restore to default") - O.vars[variable] = initial(O.vars[variable]) - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - if("edit referenced object") - return .(O.vars[variable]) - - if("text") - var/new_value = input("Enter new text:","Text",O.vars[variable]) as text|null//todo: sanitize ??? - if(new_value == null) return - O.vars[variable] = new_value - - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - if("num") - var/new_value = input("Enter new number:","Num",\ - O.vars[variable]) as num|null - if(new_value == null) return - - if(variable=="light_range") - O.set_light(new_value) - else - O.vars[variable] = new_value - - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - if(variable=="light_range") - M.set_light(new_value) - else - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - if(variable=="light_range") - A.set_light(new_value) - else - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - if(variable=="light_range") - A.set_light(new_value) - else - A.vars[variable] = O.vars[variable] - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - if(variable=="light_range") - M.set_light(new_value) - else - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - if(variable=="light_range") - A.set_light(new_value) - else - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - if(variable=="light_range") - A.set_light(new_value) - else - A.vars[variable] = O.vars[variable] - - if("type") - var/new_value - new_value = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf) - if(new_value == null) return - O.vars[variable] = new_value - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - if("file") - var/new_value = input("Pick file:","File",O.vars[variable]) as null|file - if(new_value == null) return - O.vars[variable] = new_value - - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O.type, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O.type, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O.type, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O.type, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - if("icon") - var/new_value = input("Pick icon:","Icon",O.vars[variable]) as null|icon - if(new_value == null) return - O.vars[variable] = new_value - if(method) - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if ( istype(M , O.type) ) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if ( istype(A , O.type) ) - A.vars[variable] = O.vars[variable] - - else - if(istype(O, /mob)) - for(var/mob/M in mob_list) - if (M.type == O.type) - M.vars[variable] = O.vars[variable] - - else if(istype(O, /obj)) - for(var/obj/A in world) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - else if(istype(O, /turf)) - for(var/turf/A in turfs) - if (A.type == O.type) - A.vars[variable] = O.vars[variable] - - log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]") - message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]]", 1) diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm deleted file mode 100644 index ecd26e9b56..0000000000 --- a/code/modules/admin/verbs/modifyvariables.dm +++ /dev/null @@ -1,591 +0,0 @@ -var/list/forbidden_varedit_object_types = list( - /datum/admins, //Admins editing their own admin-power object? Yup, sounds like a good idea, - /obj/machinery/blackbox_recorder, //Prevents people messing with feedback gathering, - /datum/feedback_variable //Prevents people messing with feedback gathering, - ) - -var/list/VVlocked = list("vars", "client", "virus", "viruses", "cuffed", "last_eaten", "unlock_content", "bound_x", "bound_y", "step_x", "step_y", "force_ending", "queued_priority") -var/list/VVicon_edit_lock = list("icon", "icon_state", "overlays", "underlays") -var/list/VVckey_edit = list("key", "ckey") - -/* -/client/proc/cmd_modify_object_variables(obj/O as obj|mob|turf|area in world) - set category = "Debug" - set name = "Edit Variables" - set desc="(target) Edit a target item's variables" - src.modify_variables(O) - feedback_add_details("admin_verb","EDITV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -*/ - -/client/proc/cmd_modify_ticker_variables() - set category = "Debug" - set name = "Edit Ticker Variables" - - if (ticker == null) - src << "Game hasn't started yet." - else - src.modify_variables(ticker) - feedback_add_details("admin_verb","ETV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -/client/proc/mod_list_add_ass() //haha - - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") - - if(!class) - return - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - var/var_value = null - - switch(class) - - if("text") - var_value = input("Enter new text:","Text") as null|text - - if("num") - var_value = input("Enter new number:","Num") as null|num - - if("type") - var_value = input("Enter type:","Type") as null|anything in typesof(/obj,/mob,/area,/turf) - - if("reference") - var_value = input("Select reference:","Reference") as null|mob|obj|turf|area in world - - if("mob reference") - var_value = input("Select reference:","Reference") as null|mob in world - - if("file") - var_value = input("Pick file:","File") as null|file - - if("icon") - var_value = input("Pick icon:","Icon") as null|icon - - if("marked datum") - var_value = holder.marked_datum - - if(!var_value) return - - return var_value - - -/client/proc/mod_list_add(var/list/L, atom/O, original_name, objectvar) - - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type") as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") - - if(!class) - return - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - var/var_value = null - - switch(class) - - if("text") - var_value = input("Enter new text:","Text") as text - - if("num") - var_value = input("Enter new number:","Num") as num - - if("type") - var_value = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - - if("reference") - var_value = input("Select reference:","Reference") as mob|obj|turf|area in world - - if("mob reference") - var_value = input("Select reference:","Reference") as mob in world - - if("file") - var_value = input("Pick file:","File") as file - - if("icon") - var_value = input("Pick icon:","Icon") as icon - - if("marked datum") - var_value = holder.marked_datum - - if(!var_value) return - - switch(alert("Would you like to associate a var with the list entry?",,"Yes","No")) - if("Yes") - L += var_value - L[var_value] = mod_list_add_ass() //haha - if("No") - L += var_value - world.log << "### ListVarEdit by [src]: [O.type] [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(var/list/L, atom/O, original_name, objectvar) - if(!check_rights(R_VAREDIT)) return - if(!istype(L,/list)) src << "Not a List." - - 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/assoc = 0 - if(L.len > 0) - var/a = L[1] - if(istext(a) && L[a] != null) - assoc = 1 //This is pretty weak test but i can't think of anything else - usr << "List appears to be associative." - - var/list/names = null - if(!assoc) - names = sortList(L) - - var/variable - var/assoc_key - if(assoc) - variable = input("Which var?","Var") as null|anything in L + "(ADD VAR)" - else - variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" - - if(variable == "(ADD VAR)") - mod_list_add(L, O, original_name, objectvar) - return - - if(assoc) - assoc_key = variable - variable = L[assoc_key] - - if(!assoc && !variable || assoc && !assoc_key) - return - - var/default - - var/dir - - if(variable in VVlocked) - if(!check_rights(R_DEBUG)) return - if(variable in VVckey_edit) - if(!check_rights(R_SPAWN|R_DEBUG)) return - if(variable in VVicon_edit_lock) - if(!check_rights(R_FUN|R_DEBUG)) return - - if(isnull(variable)) - usr << "Unable to determine variable type." - - else if(isnum(variable)) - usr << "Variable appears to be NUM." - default = "num" - dir = 1 - - else if(istext(variable)) - usr << "Variable appears to be TEXT." - default = "text" - - else if(isloc(variable)) - usr << "Variable appears to be REFERENCE." - default = "reference" - - else if(isicon(variable)) - usr << "Variable appears to be ICON." - variable = "\icon[variable]" - default = "icon" - - else if(istype(variable,/atom) || istype(variable,/datum)) - usr << "Variable appears to be TYPE." - default = "type" - - else if(istype(variable,/list)) - usr << "Variable appears to be LIST." - default = "list" - - else if(istype(variable,/client)) - usr << "Variable appears to be CLIENT." - default = "cancel" - - else - usr << "Variable appears to be FILE." - default = "file" - - usr << "Variable contains: [variable]" - if(dir) - switch(variable) - if(1) - dir = "NORTH" - if(2) - dir = "SOUTH" - if(4) - dir = "EAST" - if(8) - dir = "WEST" - if(5) - dir = "NORTHEAST" - if(6) - dir = "SOUTHEAST" - if(9) - dir = "NORTHWEST" - if(10) - dir = "SOUTHWEST" - else - dir = null - - if(dir) - usr << "If a direction, direction is: [dir]" - - var/class = "text" - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])", "DELETE FROM LIST") - else - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default", "DELETE FROM LIST") - - if(!class) - return - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - var/original_var - if(assoc) - original_var = L[assoc_key] - else - original_var = L[L.Find(variable)] - - var/new_var - switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet. - - if("list") - mod_list(variable, O, original_name, objectvar) - - if("restore to default") - new_var = initial(variable) - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("edit referenced object") - modify_variables(variable) - - if("DELETE FROM LIST") - world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[variable]")]" - log_admin("[key_name(src)] modified [original_name]'s [objectvar]: REMOVED=[variable]") - message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: REMOVED=[variable]") - L -= variable - return - - if("text") - new_var = input("Enter new text:","Text") as text - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("num") - new_var = input("Enter new number:","Num") as num - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("type") - new_var = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("reference") - new_var = input("Select reference:","Reference") as mob|obj|turf|area in world - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("mob reference") - new_var = input("Select reference:","Reference") as mob in world - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("file") - new_var = input("Pick file:","File") as file - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("icon") - new_var = input("Pick icon:","Icon") as icon - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - if("marked datum") - new_var = holder.marked_datum - if(assoc) - L[assoc_key] = new_var - else - L[L.Find(variable)] = new_var - - world.log << "### ListVarEdit by [src]: [O.type] [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]") - -/client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0) - if(!check_rights(R_VAREDIT)) return - - for(var/p in forbidden_varedit_object_types) - if( istype(O,p) ) - usr << "It is forbidden to edit this object's variables." - return - - if(istype(O, /client) && (param_var_name == "ckey" || param_var_name == "key")) - usr << "You cannot edit ckeys on client objects." - return - - var/class - var/variable - var/var_value - - if(param_var_name) - if(!param_var_name in O.vars) - src << "A variable with this name ([param_var_name]) doesn't exist in this atom ([O])" - return - - if(param_var_name in VVlocked) - if(!check_rights(R_DEBUG)) return - if(param_var_name in VVckey_edit) - if(!check_rights(R_SPAWN|R_DEBUG)) return - if(param_var_name in VVicon_edit_lock) - if(!check_rights(R_FUN|R_DEBUG)) return - - variable = param_var_name - - var_value = O.vars[variable] - - if(autodetect_class) - if(isnull(var_value)) - usr << "Unable to determine variable type." - class = null - autodetect_class = null - else if(isnum(var_value)) - usr << "Variable appears to be NUM." - class = "num" - dir = 1 - - else if(istext(var_value)) - usr << "Variable appears to be TEXT." - class = "text" - - else if(isloc(var_value)) - usr << "Variable appears to be REFERENCE." - class = "reference" - - else if(isicon(var_value)) - usr << "Variable appears to be ICON." - var_value = "\icon[var_value]" - class = "icon" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) - usr << "Variable appears to be TYPE." - class = "type" - - else if(istype(var_value,/list)) - usr << "Variable appears to be LIST." - class = "list" - - else if(istype(var_value,/client)) - usr << "Variable appears to be CLIENT." - class = "cancel" - - else - usr << "Variable appears to be FILE." - class = "file" - - 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 - var_value = O.vars[variable] - - if(variable in VVlocked) - if(!check_rights(R_DEBUG)) return - if(variable in VVckey_edit) - if(!check_rights(R_SPAWN|R_DEBUG)) return - if(variable in VVicon_edit_lock) - if(!check_rights(R_FUN|R_DEBUG)) return - - if(!autodetect_class) - - var/dir - var/default - if(isnull(var_value)) - usr << "Unable to determine variable type." - - else if(isnum(var_value)) - usr << "Variable appears to be NUM." - default = "num" - dir = 1 - - else if(istext(var_value)) - usr << "Variable appears to be TEXT." - default = "text" - - else if(isloc(var_value)) - usr << "Variable appears to be REFERENCE." - default = "reference" - - else if(isicon(var_value)) - usr << "Variable appears to be ICON." - var_value = "\icon[var_value]" - default = "icon" - - else if(istype(var_value,/atom) || istype(var_value,/datum)) - usr << "Variable appears to be TYPE." - default = "type" - - else if(istype(var_value,/list)) - usr << "Variable appears to be LIST." - default = "list" - - else if(istype(var_value,/client)) - usr << "Variable appears to be CLIENT." - default = "cancel" - - else - usr << "Variable appears to be FILE." - default = "file" - - usr << "Variable contains: [var_value]" - if(dir) - switch(var_value) - if(1) - dir = "NORTH" - if(2) - dir = "SOUTH" - if(4) - dir = "EAST" - if(8) - dir = "WEST" - if(5) - dir = "NORTHEAST" - if(6) - dir = "SOUTHEAST" - if(9) - dir = "NORTHWEST" - if(10) - dir = "SOUTHWEST" - else - dir = null - if(dir) - usr << "If a direction, direction is: [dir]" - - if(src.holder && src.holder.marked_datum) - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default","marked datum ([holder.marked_datum.type])") - else - class = input("What kind of variable?","Variable Type",default) as null|anything in list("text", - "num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default") - - if(!class) - return - - var/original_name - - if (!istype(O, /atom)) - original_name = "\ref[O] ([O])" - else - original_name = O:name - - if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") - class = "marked datum" - - switch(class) - - if("list") - mod_list(O.vars[variable], O, original_name, variable) - return - - if("restore to default") - O.vars[variable] = initial(O.vars[variable]) - - if("edit referenced object") - return .(O.vars[variable]) - - if("text") - var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|text - if(var_new==null) return - O.vars[variable] = var_new - - if("num") - if(variable=="light_range") - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new == null) return - O.set_light(var_new) - else if(variable=="stat") - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new == null) return - if((O.vars[variable] == 2) && (var_new < 2))//Bringing the dead back to life - dead_mob_list -= O - living_mob_list += O - if((O.vars[variable] < 2) && (var_new == 2))//Kill he - living_mob_list -= O - dead_mob_list += O - O.vars[variable] = var_new - else - var/var_new = input("Enter new number:","Num",O.vars[variable]) as null|num - if(var_new==null) return - O.vars[variable] = var_new - - if("type") - var/var_new = input("Enter type:","Type",O.vars[variable]) as null|anything in typesof(/obj,/mob,/area,/turf) - if(var_new==null) return - O.vars[variable] = var_new - - if("reference") - var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob|obj|turf|area in world - if(var_new==null) return - O.vars[variable] = var_new - - if("mob reference") - var/var_new = input("Select reference:","Reference",O.vars[variable]) as null|mob in world - if(var_new==null) return - O.vars[variable] = var_new - - if("file") - var/var_new = input("Pick file:","File",O.vars[variable]) as null|file - if(var_new==null) return - O.vars[variable] = var_new - - if("icon") - var/var_new = input("Pick icon:","Icon",O.vars[variable]) as null|icon - if(var_new==null) return - O.vars[variable] = var_new - - if("marked datum") - O.vars[variable] = holder.marked_datum - - world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]" - log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]") - message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]") diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index bbb618e7c8..7d0b7ee259 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -603,12 +603,7 @@ Traitors and the like can also be revived with the previous role mostly intact. if (!holder) src << "Only administrators may use this command." return - - if (alert(src, "Are you sure you want to delete:\n[O]\nat ([O.x], [O.y], [O.z])?", "Confirmation", "Yes", "No") == "Yes") - log_admin("[key_name(usr)] deleted [O] at ([O.x],[O.y],[O.z])") - message_admins("[key_name_admin(usr)] deleted [O] at ([O.x],[O.y],[O.z])", 1) - feedback_add_details("admin_verb","DEL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - qdel(O) + admin_delete(O) /client/proc/cmd_admin_list_open_jobs() set category = "Admin" diff --git a/code/modules/admin/view_variables/admin_delete.dm b/code/modules/admin/view_variables/admin_delete.dm new file mode 100644 index 0000000000..53a54786a9 --- /dev/null +++ b/code/modules/admin/view_variables/admin_delete.dm @@ -0,0 +1,24 @@ +/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]") + 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) + qdel(D) + if(!QDELETED(D)) + vv_update_display(D, "deleted", "") diff --git a/code/modules/admin/view_variables/debug_variables.dm b/code/modules/admin/view_variables/debug_variables.dm new file mode 100644 index 0000000000..bcf097f813 --- /dev/null +++ b/code/modules/admin/view_variables/debug_variables.dm @@ -0,0 +1,76 @@ +#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/index = name + if (value) + name = DA[name] //name is really the index until this line + else + value = DA[name] + header = "
  • (E) (C) (-) " + else + header = "
  • (E) (C) (M) " + else + header = "
  • " + + var/item + if (isnull(value)) + item = "[VV_HTML_ENCODE(name)] = null" + + else if (istext(value)) + item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\"" + + else if (isicon(value)) + #ifdef VARSICON + var/icon/I = new/icon(value) + var/rnd = rand(1,10000) + var/rname = "tmp\ref[I][rnd].png" + usr << browse_rsc(I, rname) + item = "[VV_HTML_ENCODE(name)] = ([value]) " + #else + item = "[VV_HTML_ENCODE(name)] = /icon ([value])" + #endif + + else if (isfile(value)) + item = "[VV_HTML_ENCODE(name)] = '[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 = "[VV_HTML_ENCODE(name)] \ref[value] = [D] [D.type]" + else + item = "[VV_HTML_ENCODE(name)] \ref[value] = [D.type]" + + else if (islist(value)) + var/list/L = 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] + 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 "" + val = key + key = i + + items += debug_variable(key, val, level + 1, sanitize = sanitize) + + item = "[VV_HTML_ENCODE(name)] = /list ([L.len])" + else + item = "[VV_HTML_ENCODE(name)] = /list ([L.len])" + + 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, ", "))]" + else + item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]" + + return "[header][item]
  • " + +#undef VV_HTML_ENCODE diff --git a/code/modules/admin/view_variables/get_variables.dm b/code/modules/admin/view_variables/get_variables.dm new file mode 100644 index 0000000000..eb2d1bf4db --- /dev/null +++ b/code/modules/admin/view_variables/get_variables.dm @@ -0,0 +1,250 @@ +/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 diff --git a/code/modules/admin/view_variables/helpers.dm b/code/modules/admin/view_variables/helpers.dm deleted file mode 100644 index 2776458e06..0000000000 --- a/code/modules/admin/view_variables/helpers.dm +++ /dev/null @@ -1,194 +0,0 @@ - -/datum/proc/get_view_variables_header() - return "[src]" - -/atom/get_view_variables_header() - return {" - [src] -
    - << - [dir2text(dir)] - >> - - "} - -/mob/living/get_view_variables_header() - return {" - [src] -
    << [dir2text(dir)] >> -
    [ckey ? ckey : "No ckey"] / [real_name ? real_name : "No real name"] -
    - BRUTE:[getBruteLoss()] - FIRE:[getFireLoss()] - TOXIN:[getToxLoss()] - OXY:[getOxyLoss()] - CLONE:[getCloneLoss()] - BRAIN:[getBrainLoss()] -
    - "} - -/datum/proc/get_view_variables_options() - return "" - -/mob/get_view_variables_options() - return ..() + {" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "} - -/mob/living/carbon/human/get_view_variables_options() - return ..() + {" - - - - - - "} - -/obj/get_view_variables_options() - return ..() + {" - - - - "} - -/turf/get_view_variables_options() - return ..() + {" - - - "} - -/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 {" - (E) - (C) - (M) - [hide_watch ? "" : "(W)"] - "} - -// No mass editing of clients -/client/make_view_variables_variable_entry(var/varname, var/value, var/hide_watch = 0) - return {" - (E) - (C) - [hide_watch ? "" : "(W)"] - "} - -// 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", "virus", "viruses", "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) - if(!user) - return FALSE - if(!(var_to_edit in vars)) - to_chat(user, "\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(R_ADMIN|R_DEBUG, FALSE, C = user)) - return FALSE - if((var_to_edit in VV_locked()) && !check_rights(R_DEBUG, C = user)) - return FALSE - if((var_to_edit in VV_ckey_edit()) && !check_rights(R_SPAWN|R_DEBUG, C = user)) - return FALSE - if((var_to_edit in VV_icon_edit_lock()) && !check_rights(R_FUN|R_DEBUG, C = user)) - 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., - /obj/machinery/blackbox_recorder, //Prevents people messing with feedback gathering, - /datum/feedback_variable //Prevents people messing with feedback gathering - ) \ No newline at end of file diff --git a/code/modules/admin/view_variables/helpers_deprecated.dm b/code/modules/admin/view_variables/helpers_deprecated.dm new file mode 100644 index 0000000000..1a7e44d4a5 --- /dev/null +++ b/code/modules/admin/view_variables/helpers_deprecated.dm @@ -0,0 +1,48 @@ +//This entire file needs to be removed eventually +/datum/proc/get_view_variables_options() + return "" + +/mob/get_view_variables_options() + return ..() + {" + + + + + + + + + + + + + + + + + + + + + + + + + + + + "} + +/mob/living/carbon/human/get_view_variables_options() + return ..() + {" + + + + + + "} + +/obj/get_view_variables_options() + return ..() + {" + + "} diff --git a/code/modules/admin/view_variables/mass_edit_variables.dm b/code/modules/admin/view_variables/mass_edit_variables.dm new file mode 100644 index 0000000000..7374759e8c --- /dev/null +++ b/code/modules/admin/view_variables/mass_edit_variables.dm @@ -0,0 +1,265 @@ +/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) + feedback_add_details("admin_verb","MVV") //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 [uppertext(default)].") + + 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 mob_list) + if (typecache[thing.type]) + . += thing + CHECK_TICK + + else if (ispath(T, /obj/machinery/door)) + for(var/obj/machinery/door/thing in world) + 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 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 diff --git a/code/modules/admin/view_variables/modify_variables.dm b/code/modules/admin/view_variables/modify_variables.dm new file mode 100644 index 0000000000..b964339aa9 --- /dev/null +++ b/code/modules/admin/view_variables/modify_variables.dm @@ -0,0 +1,387 @@ +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_PROTECT(VVicon_edit_lock) +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_PROTECT(VVpixelmovement) + +/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, lentext(types[type])+1) + var/shorttype = copytext("[D.type]", lentext("[type]")+1) + if (lentext(shorttype) > lentext(fancytype)) + shorttype = fancytype + if (!lentext(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 + 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 + var/found = L[variable] + if(!isnull(found)) + old_assoc_value = found + // + + default = vv_get_class(objectvar, variable) + + to_chat(src, "Variable appears to be [uppertext(default)].") + + 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(!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.") + 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 + 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 + + 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 [uppertext(default)].") + + 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) + 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 diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm index 16550f6712..35cff902d8 100644 --- a/code/modules/admin/view_variables/topic.dm +++ b/code/modules/admin/view_variables/topic.dm @@ -1,8 +1,12 @@ - +//DO NOT ADD MORE TO THIS FILE. +//Use vv_do_topic()! /client/proc/view_var_Topic(href, href_list, hsrc) - //This should all be moved over to datum/admins/Topic() or something ~Carn - if( (usr.client != src) || !src.holder ) + if((usr.client != src) || !src.holder) return + var/datum/target = locate(href_list["target"]) + if(target) + target.vv_do_topic(href_list) + if(href_list["Vars"]) debug_variables(locate(href_list["Vars"])) @@ -163,11 +167,12 @@ href_list["datumrefresh"] = href_list["make_skeleton"] else if(href_list["delall"]) - if(!check_rights(R_DEBUG|R_SERVER)) return + if(!check_rights(R_DEBUG|R_SERVER)) + return var/obj/O = locate(href_list["delall"]) if(!isobj(O)) - usr << "This can only be used on instances of type /obj" + to_chat(usr, "This can only be used on instances of type /obj") return var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel") @@ -188,55 +193,24 @@ if(Obj.type == O_type) i++ qdel(Obj) + CHECK_TICK if(!i) - usr << "No objects of this type exist" + to_chat(usr, "No objects of this type exist") return - log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)") - message_admins("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)") + log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") + message_admins("[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) - usr << "No objects of this type exist" + to_chat(usr, "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("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)") - - else if(href_list["explode"]) - if(!check_rights(R_DEBUG|R_FUN)) return - - var/atom/A = locate(href_list["explode"]) - if(!isobj(A) && !ismob(A) && !isturf(A)) - usr << "This can only be done to instances of type /obj, /mob and /turf" - return - - src.cmd_admin_explosion(A) - href_list["datumrefresh"] = href_list["explode"] - - else if(href_list["emp"]) - if(!check_rights(R_DEBUG|R_FUN)) return - - var/atom/A = locate(href_list["emp"]) - if(!isobj(A) && !ismob(A) && !isturf(A)) - usr << "This can only be done to instances of type /obj, /mob and /turf" - return - - src.cmd_admin_emp(A) - href_list["datumrefresh"] = href_list["emp"] - - else if(href_list["mark_object"]) - if(!check_rights(0)) return - - var/datum/D = locate(href_list["mark_object"]) - if(!istype(D)) - usr << "This can only be done to instances of type /datum" - return - - src.holder.marked_datum = D - href_list["datumrefresh"] = href_list["mark_object"] + log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") + message_admins("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") else if(href_list["rotatedatum"]) if(!check_rights(0)) return @@ -519,15 +493,31 @@ log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L]") message_admins("[key_name(usr)] dealt [amount] amount of [Text] damage to [L]") href_list["datumrefresh"] = href_list["mobToDamage"] - - else if(href_list["call_proc"]) - var/datum/D = locate(href_list["call_proc"]) - if(istype(D) || istype(D, /client)) // can call on clients too, not just datums - callproc_targetpicked(1, D) + 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 = alert("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", "Yes", "No") + if (prompt != "Yes") + return + if(!thing) + to_chat(usr, "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 VV window") + 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) if(href_list["datumrefresh"]) var/datum/DAT = locate(href_list["datumrefresh"]) if(istype(DAT, /datum) || istype(DAT, /client)) debug_variables(DAT) - return diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index cb110d4e86..efa6f424f1 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -1,183 +1,284 @@ - -// Variables to not even show in the list. -// step_* and bound_* are here because they literally break the game and do nothing else. -// parent_type is here because it's pointless to show in VV. -/var/list/view_variables_hide_vars = list("bound_x", "bound_y", "bound_height", "bound_width", "bounds", "parent_type", "step_x", "step_y", "step_size") -// Variables not to expand the lists of. Vars is pointless to expand, and overlays/underlays cannot be expanded. -/var/list/view_variables_dont_expand = list("overlays", "underlays", "vars") - /client/proc/debug_variables(datum/D in world) set category = "Debug" set name = "View Variables" + //set src in world + var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round. - if(!check_rights(0)) + if(!usr.client || !usr.client.holder) //The usr vs src abuse in this proc is intentional and must not be changed + to_chat(usr, "You need to be an administrator to access this.") return if(!D) return - var/icon/sprite - if(istype(D, /atom)) - var/atom/A = D - if(A.icon && A.icon_state) - sprite = icon(A.icon, A.icon_state) - usr << browse_rsc(sprite, "view_vars_sprite.png") + var/islist = islist(D) + if (!islist && !istype(D)) + return - usr << browse_rsc('code/js/view_variables.js', "view_variables.js") + var/title = "" + var/refid = "\ref[D]" + var/icon/sprite + var/hash + + var/type = /list + if (!islist) + type = D.type + + if(istype(D, /atom)) + var/atom/AT = D + if(AT.icon && AT.icon_state) + sprite = new /icon(AT.icon, AT.icon_state) + hash = md5(AT.icon) + hash = md5(hash + AT.icon_state) + src << browse_rsc(sprite, "vv[hash].png") + + title = "[D] (\ref[D]) = [type]" + var/formatted_type = replacetext("[type]", "/", "/") + + var/sprite_text + if(sprite) + sprite_text = "" + var/list/header = islist(D)? list("/list") : D.vv_get_header() + + var/marked + if(holder && holder.marked_datum && holder.marked_datum == D) + marked = 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/dropdownoptions = list() + var/autoconvert_dropdown = FALSE + if (islist) + dropdownoptions = list( + "---", + "Add Item" = "?_src_=vars;listadd=[refid]", + "Remove Nulls" = "?_src_=vars;listnulls=[refid]", + "Remove Dupes" = "?_src_=vars;listdupes=[refid]", + "Set len" = "?_src_=vars;listlen=[refid]", + "Shuffle" = "?_src_=vars;listshuffle=[refid]", + "Show VV To Player" = "?_src_=vars;expose=[refid]" + ) + 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 += "" + else + dropdownoptions_html += "" + else + dropdownoptions_html = dropdownoptions + D.get_view_variables_options() + + var/list/names = list() + if (!islist) + for (var/V in D.vars) + names += V + sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects. + + 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) && !isnum(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 = {" - - - - [D] (\ref[D] - [D.type]) - - - -
    - + + + [title] + + + + +
    +
    + -
    - - [sprite ? "" : ""] - -
    [D.get_view_variables_header()]
    + + + + +
    + [sprite_text] +
    + [header.Join()] +
    +
    - [replacetext("[D.type]", "/", "/")] - [holder.marked_datum == D ? "
    Marked Object" : ""] + [formatted_type] + [marked] + [varedited_line] + [deleted_line]
    - Refresh + Refresh
    - + + [dropdownoptions_html.Join()]
    -
    -
    - - E - Edit, tries to determine the variable type by itself.
    - C - Change, asks you for the var type first.
    - M - Mass modify: changes this variable for all objects of this type.
    -
    -
    - + +
    + +
    + + E - Edit, tries to determine the variable type by itself.
    + C - Change, asks you for the var type first.
    + M - Mass modify: changes this variable for all objects of this type.
    +
    +
    + + -
    Search:
    - +
    -
    -
      - [make_view_variables_var_list(D)] -
    - - - "} + + +
    +
      + [variable_html.Join()] +
    + + + +"} + src << browse(html, "window=variables[refid];size=475x650") - usr << browse(html, "window=variables\ref[D];size=475x650") - - -/proc/make_view_variables_var_list(datum/D) - . = "" - var/list/variables = list() - for(var/x in D.vars) - if(x in view_variables_hide_vars) - continue - variables += x - variables = sortList(variables) - for(var/x in variables) - . += make_view_variables_var_entry(D, x, D.vars[x]) - -/proc/make_view_variables_var_entry(datum/D, varname, value, level=0) - var/ecm = null - var/vtext = null - var/extra = null - - if(D) - ecm = {" - (E) - (C) - (M) - "} - - if(isnull(value)) - vtext = "null" - else if(istext(value)) - vtext = "\"[value]\"" - else if(isicon(value)) - vtext = "[value]" - else if(isfile(value)) - vtext = "'[value]'" - else if(istype(value, /datum)) - var/datum/DA = value - if("[DA]" == "[DA.type]" || !"[DA]") - vtext = "\ref[DA] - [DA.type]" - else - vtext = "\ref[DA] - [DA] ([DA.type])" - else if(istype(value, /client)) - var/client/C = value - vtext = "\ref[C] - [C] ([C.type])" - else if(islist(value)) - var/list/L = value - var/removed = 0 - if(varname == "contents") - var/list/original = value - L = original.Copy() //We'll take a copy to manipulate - removed = D.view_variables_filter_contents(L) - vtext = "/list ([L.len]+[removed]H)" - if(!(varname in view_variables_dont_expand) && L.len > 0 && L.len < 100) - extra = "" - else - vtext = "[value]" - - return "
  • [ecm][varname] = [vtext][extra]
  • " - -//Allows us to mask out some contents when it's not necessary to show them -//For example, organs on humans, as the organs are stored in other lists which will also be present -//So there's really no need to list them twice. -/datum/proc/view_variables_filter_contents(list/L) - return 0 //Return how many items you removed. - -/mob/living/carbon/human/view_variables_filter_contents(list/L) - . = ..() - L -= ability_master - .++ - -/mob/living/carbon/human/view_variables_filter_contents(list/L) - . = ..() - var/len_before = L.len - L -= organs - L -= internal_organs - . += len_before - L.len +/client/proc/vv_update_display(datum/D, span, content) + src << output("[span]:[content]", "variables\ref[D].browser:replace_span") diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 95455bba3f..a4123ea47e 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -401,3 +401,8 @@ client/verb/character_setup() . = R.group[1] else CRASH("Age check regex failed for [src.ckey]") + +/client/vv_edit_var(var_name, var_value) + if(var_name == NAMEOF(src, holder)) + return FALSE + return ..() diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index c6184c41a0..cda61be1b3 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -182,7 +182,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if(isnull(last_descriptors[entry])) pref.body_descriptors[entry] = descriptor.default_value // Species datums have initial default value. else - pref.body_descriptors[entry] = Clamp(last_descriptors[entry], 1, LAZYLEN(descriptor.standalone_value_descriptors)) + pref.body_descriptors[entry] = CLAMP(last_descriptors[entry], 1, LAZYLEN(descriptor.standalone_value_descriptors)) return diff --git a/code/modules/client/preference_setup/global/05_media.dm b/code/modules/client/preference_setup/global/05_media.dm index 3551735bb9..7ae263d9ea 100644 --- a/code/modules/client/preference_setup/global/05_media.dm +++ b/code/modules/client/preference_setup/global/05_media.dm @@ -15,7 +15,7 @@ S["media_player"] << pref.media_player /datum/category_item/player_setup_item/player_global/media/sanitize_preferences() - pref.media_volume = isnum(pref.media_volume) ? Clamp(pref.media_volume, 0, 1) : initial(pref.media_volume) + pref.media_volume = isnum(pref.media_volume) ? CLAMP(pref.media_volume, 0, 1) : initial(pref.media_volume) pref.media_player = sanitize_inlist(pref.media_player, list(0, 1, 2), initial(pref.media_player)) /datum/category_item/player_setup_item/player_global/media/content(var/mob/user) @@ -35,7 +35,7 @@ if(CanUseTopic(user)) var/value = input("Choose your Jukebox volume (0-100%)", "Jukebox volume", round(pref.media_volume * 100)) if(isnum(value)) - value = Clamp(value, 0, 100) + value = CLAMP(value, 0, 100) pref.media_volume = value/100.0 if(user.client && user.client.media) user.client.media.update_volume(pref.media_volume) diff --git a/code/modules/economy/Accounts_DB.dm b/code/modules/economy/Accounts_DB.dm index 507a516981..2d6676adec 100644 --- a/code/modules/economy/Accounts_DB.dm +++ b/code/modules/economy/Accounts_DB.dm @@ -143,7 +143,7 @@ var/account_name = href_list["holder_name"] var/starting_funds = max(text2num(href_list["starting_funds"]), 0) - starting_funds = Clamp(starting_funds, 0, station_account.money) // Not authorized to put the station in debt. + starting_funds = CLAMP(starting_funds, 0, station_account.money) // Not authorized to put the station in debt. starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap. create_account(account_name, starting_funds, src) diff --git a/code/modules/economy/cash.dm b/code/modules/economy/cash.dm index 8bf5c63cc7..8c67e5394c 100644 --- a/code/modules/economy/cash.dm +++ b/code/modules/economy/cash.dm @@ -78,7 +78,7 @@ /obj/item/weapon/spacecash/attack_self() var/amount = input(usr, "How many Thalers do you want to take? (0 to [src.worth])", "Take Money", 20) as num - amount = round(Clamp(amount, 0, src.worth)) + amount = round(CLAMP(amount, 0, src.worth)) if(!amount) return diff --git a/code/modules/economy/cash_register.dm b/code/modules/economy/cash_register.dm index 9ef7a3f871..f3402f892e 100644 --- a/code/modules/economy/cash_register.dm +++ b/code/modules/economy/cash_register.dm @@ -128,7 +128,7 @@ if("set_amount") var/item_name = locate(href_list["item"]) var/n_amount = round(input("Enter amount", "New amount") as num) - n_amount = Clamp(n_amount, 0, 20) + n_amount = CLAMP(n_amount, 0, 20) if (!item_list[item_name] || !Adjacent(usr)) return transaction_amount += (n_amount - item_list[item_name]) * price_list[item_name] if(!n_amount) diff --git a/code/modules/economy/retail_scanner.dm b/code/modules/economy/retail_scanner.dm index af1d87177a..55a7fd0866 100644 --- a/code/modules/economy/retail_scanner.dm +++ b/code/modules/economy/retail_scanner.dm @@ -120,7 +120,7 @@ if("set_amount") var/item_name = locate(href_list["item"]) var/n_amount = round(input("Enter amount", "New amount") as num) - n_amount = Clamp(n_amount, 0, 20) + n_amount = CLAMP(n_amount, 0, 20) if (!item_list[item_name] || !Adjacent(usr)) return transaction_amount += (n_amount - item_list[item_name]) * price_list[item_name] if(!n_amount) diff --git a/code/modules/food/food/sandwich.dm b/code/modules/food/food/sandwich.dm index 5662b7d3ff..f4d9ac5fd0 100644 --- a/code/modules/food/food/sandwich.dm +++ b/code/modules/food/food/sandwich.dm @@ -71,7 +71,7 @@ name = lowertext("[fullname] sandwich") if(length(name) > 80) name = "[pick(list("absurd","colossal","enormous","ridiculous"))] sandwich" - w_class = n_ceil(Clamp((ingredients.len/2),2,4)) + w_class = n_ceil(CLAMP((ingredients.len/2),2,4)) /obj/item/weapon/reagent_containers/food/snacks/csandwich/Destroy() for(var/obj/item/O in ingredients) diff --git a/code/modules/gamemaster/helpers.dm b/code/modules/gamemaster/helpers.dm index 80fc133931..da05cb1b20 100644 --- a/code/modules/gamemaster/helpers.dm +++ b/code/modules/gamemaster/helpers.dm @@ -1,9 +1,9 @@ // Tell the game master that something dangerous happened, e.g. someone dying. /datum/game_master/proc/adjust_danger(var/amt) amt = amt * danger_modifier - danger = round( Clamp(danger + amt, 0, 1000), 0.1) + danger = round( CLAMP(danger + amt, 0, 1000), 0.1) // Tell the game master that something interesting happened. /datum/game_master/proc/adjust_staleness(var/amt) amt = amt * staleness_modifier - staleness = round( Clamp(staleness + amt, -50, 200), 0.1) \ No newline at end of file + staleness = round( CLAMP(staleness + amt, -50, 200), 0.1) \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/data_transfer.dm b/code/modules/integrated_electronics/subtypes/data_transfer.dm index e490ccd27a..052d3acb76 100644 --- a/code/modules/integrated_electronics/subtypes/data_transfer.dm +++ b/code/modules/integrated_electronics/subtypes/data_transfer.dm @@ -125,7 +125,7 @@ /obj/item/integrated_circuit/transfer/pulsedemultiplexer/do_work() var/output_index = get_pin_data(IC_INPUT, 1) - if(output_index == Clamp(output_index, 1, number_of_outputs)) + if(output_index == CLAMP(output_index, 1, number_of_outputs)) activate_pin(round(output_index + 1 ,1)) /obj/item/integrated_circuit/transfer/pulsedemultiplexer/medium diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index 08f4975e5c..9c54a6e377 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -296,7 +296,7 @@ /obj/item/integrated_circuit/input/advanced_locator/on_data_written() var/rad = get_pin_data(IC_INPUT, 2) if(isnum(rad)) - rad = Clamp(rad, 0, 7) + rad = CLAMP(rad, 0, 7) radius = rad /obj/item/integrated_circuit/input/advanced_locator/do_work() diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm index 4f029dce6e..bbfcb25f94 100644 --- a/code/modules/integrated_electronics/subtypes/output.dm +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -103,7 +103,7 @@ var/brightness = get_pin_data(IC_INPUT, 2) if(new_color && isnum(brightness)) - brightness = Clamp(brightness, 0, 6) + brightness = CLAMP(brightness, 0, 6) light_rgb = new_color light_brightness = brightness diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index e8ca2ae134..ca834b3a09 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -83,7 +83,7 @@ else direc = 1 if(isnum(new_amount)) - new_amount = Clamp(new_amount, 0, volume) + new_amount = CLAMP(new_amount, 0, volume) transfer_amount = new_amount @@ -132,7 +132,7 @@ if(!TS.Adjacent(TT)) activate_pin(3) return - var/tramount = Clamp(min(transfer_amount, reagents.maximum_volume - reagents.total_volume), 0, reagents.maximum_volume) + var/tramount = CLAMP(min(transfer_amount, reagents.maximum_volume - reagents.total_volume), 0, reagents.maximum_volume) if(ismob(target))//Blood! if(istype(target, /mob/living/carbon)) var/mob/living/carbon/T = target @@ -207,7 +207,7 @@ else direc = 1 if(isnum(new_amount)) - new_amount = Clamp(new_amount, 0, 50) + new_amount = CLAMP(new_amount, 0, 50) transfer_amount = new_amount /obj/item/integrated_circuit/reagent/pump/do_work() @@ -329,7 +329,7 @@ else direc = 1 if(isnum(new_amount)) - new_amount = Clamp(new_amount, 0, 50) + new_amount = CLAMP(new_amount, 0, 50) transfer_amount = new_amount /obj/item/integrated_circuit/reagent/filter/do_work() diff --git a/code/modules/media/mediamanager.dm b/code/modules/media/mediamanager.dm index 83da1250a7..c1cd4897ca 100644 --- a/code/modules/media/mediamanager.dm +++ b/code/modules/media/mediamanager.dm @@ -149,7 +149,7 @@ if (url != targetURL || abs(targetStartTime - start_time) > 1 || abs(targetVolume - source_volume) > 0.1 /* 10% */) url = targetURL start_time = targetStartTime - source_volume = Clamp(targetVolume, 0, 1) + source_volume = CLAMP(targetVolume, 0, 1) send_update() /datum/media_manager/proc/stop_music() diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index f03cc9ef75..3f76672610 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -273,7 +273,7 @@ else if(ores_processing[metal] == PROCESS_COMPRESS && O.compresses_to) //Compressing. - var/can_make = Clamp(ores_stored[metal],0,sheets_per_tick-sheets) + var/can_make = CLAMP(ores_stored[metal],0,sheets_per_tick-sheets) if(can_make%2>0) can_make-- var/material/M = get_material_by_name(O.compresses_to) @@ -288,7 +288,7 @@ else if(ores_processing[metal] == PROCESS_SMELT && O.smelts_to) //Smelting. - var/can_make = Clamp(ores_stored[metal],0,sheets_per_tick-sheets) + var/can_make = CLAMP(ores_stored[metal],0,sheets_per_tick-sheets) var/material/M = get_material_by_name(O.smelts_to) if(!istype(M) || !can_make || ores_stored[metal] < 1) diff --git a/code/modules/mob/living/carbon/human/descriptors/_descriptors.dm b/code/modules/mob/living/carbon/human/descriptors/_descriptors.dm index 79e876a985..815914f40c 100644 --- a/code/modules/mob/living/carbon/human/descriptors/_descriptors.dm +++ b/code/modules/mob/living/carbon/human/descriptors/_descriptors.dm @@ -99,10 +99,10 @@ /datum/mob_descriptor/proc/get_comparative_value_string_smaller(var/value, var/datum/gender/my_gender, var/datum/gender/other_gender) var/maxval = LAZYLEN(comparative_value_descriptors_smaller) - value = Clamp(CEILING(value * maxval, 1), 1, maxval) + value = CLAMP(CEILING(value * maxval, 1), 1, maxval) return comparative_value_descriptors_smaller[value] /datum/mob_descriptor/proc/get_comparative_value_string_larger(var/value, var/datum/gender/my_gender, var/datum/gender/other_gender) var/maxval = LAZYLEN(comparative_value_descriptors_larger) - value = Clamp(CEILING(value * maxval, 1), 1, maxval) + value = CLAMP(CEILING(value * maxval, 1), 1, maxval) return comparative_value_descriptors_larger[value] diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 304e74c96c..187ebd4e1e 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -138,19 +138,19 @@ var/turf_move_cost = T.movement_cost if(istype(T, /turf/simulated/floor/water)) if(species.water_movement) - turf_move_cost = Clamp(HUMAN_LOWEST_SLOWDOWN, turf_move_cost + species.water_movement, 15) + turf_move_cost = CLAMP(HUMAN_LOWEST_SLOWDOWN, turf_move_cost + species.water_movement, 15) if(shoes) var/obj/item/clothing/shoes/feet = shoes if(feet.water_speed) - turf_move_cost = Clamp(HUMAN_LOWEST_SLOWDOWN, turf_move_cost + feet.water_speed, 15) + turf_move_cost = CLAMP(HUMAN_LOWEST_SLOWDOWN, turf_move_cost + feet.water_speed, 15) . += turf_move_cost if(istype(T, /turf/simulated/floor/outdoors/snow)) if(species.snow_movement) - turf_move_cost = Clamp(HUMAN_LOWEST_SLOWDOWN, turf_move_cost + species.snow_movement, 15) + turf_move_cost = CLAMP(HUMAN_LOWEST_SLOWDOWN, turf_move_cost + species.snow_movement, 15) if(shoes) var/obj/item/clothing/shoes/feet = shoes if(feet.water_speed) - turf_move_cost = Clamp(HUMAN_LOWEST_SLOWDOWN, turf_move_cost + feet.snow_speed, 15) + turf_move_cost = CLAMP(HUMAN_LOWEST_SLOWDOWN, turf_move_cost + feet.snow_speed, 15) . += turf_move_cost #undef HUMAN_LOWEST_SLOWDOWN diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 41cdc18034..f3d86e9f76 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -257,7 +257,7 @@ if(gene.is_active(src)) gene.OnMobLife(src) - radiation = Clamp(radiation,0,250) + radiation = CLAMP(radiation,0,250) if(!radiation) if(species.appearance_flags & RADIATION_GLOWS) @@ -516,7 +516,7 @@ if(toxins_pp > safe_toxins_max) var/ratio = (poison/safe_toxins_max) * 10 if(reagents) - reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) + reagents.add_reagent("toxin", CLAMP(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) breath.adjust_gas(poison_type, -poison/6, update = 0) //update after phoron_alert = max(phoron_alert, 1) else diff --git a/code/modules/mob/living/carbon/human/species/species_attack.dm b/code/modules/mob/living/carbon/human/species/species_attack.dm index 2654715f74..9e6a07d168 100644 --- a/code/modules/mob/living/carbon/human/species/species_attack.dm +++ b/code/modules/mob/living/carbon/human/species/species_attack.dm @@ -27,7 +27,7 @@ var/datum/gender/T = gender_datums[user.get_visible_gender()] var/datum/gender/TT = gender_datums[target.get_visible_gender()] if(!skill) skill = 1 - attack_damage = Clamp(attack_damage, 1, 5) + attack_damage = CLAMP(attack_damage, 1, 5) if(target == user) user.visible_message("[user] [pick(attack_verb)] [T.himself] in the [affecting.name]!") diff --git a/code/modules/mob/living/carbon/human/species/species_attack_vr.dm b/code/modules/mob/living/carbon/human/species/species_attack_vr.dm index f7e1e43e31..658a453afc 100644 --- a/code/modules/mob/living/carbon/human/species/species_attack_vr.dm +++ b/code/modules/mob/living/carbon/human/species/species_attack_vr.dm @@ -9,7 +9,7 @@ /datum/unarmed_attack/bite/sharp/numbing/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage) var/obj/item/organ/external/affecting = target.get_organ(zone) - attack_damage = Clamp(attack_damage, 1, 5) + attack_damage = CLAMP(attack_damage, 1, 5) if(target == user) user.visible_message("[user] [pick(attack_verb)] \himself in the [affecting.name]!") return 0 //No venom for you. diff --git a/code/modules/mob/living/carbon/human/species/station/alraune.dm b/code/modules/mob/living/carbon/human/species/station/alraune.dm index 2dcd3a0433..55e6215fc7 100644 --- a/code/modules/mob/living/carbon/human/species/station/alraune.dm +++ b/code/modules/mob/living/carbon/human/species/station/alraune.dm @@ -207,7 +207,7 @@ var/co2buff = 0 if(inhaling) - co2buff = (Clamp(inhale_pp, 0, minimum_breath_pressure))/minimum_breath_pressure //returns a value between 0 and 1. + co2buff = (CLAMP(inhale_pp, 0, minimum_breath_pressure))/minimum_breath_pressure //returns a value between 0 and 1. var/light_amount = fullysealed ? H.getlightlevel() : H.getlightlevel()/5 // if they're covered, they're not going to get much light on them. @@ -222,7 +222,7 @@ if(toxins_pp > safe_toxins_max) var/ratio = (poison/safe_toxins_max) * 10 if(H.reagents) - H.reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) + H.reagents.add_reagent("toxin", CLAMP(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) breath.adjust_gas(poison_type, -poison/6, update = 0) //update after H.phoron_alert = max(H.phoron_alert, 1) else diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm index 6ec4ce2954..f3526983ef 100644 --- a/code/modules/mob/living/carbon/human/unarmed_attack.dm +++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm @@ -139,7 +139,7 @@ var/global/list/sparring_attack_cache = list() var/datum/gender/TU = gender_datums[user.get_visible_gender()] var/datum/gender/TT = gender_datums[target.get_visible_gender()] - attack_damage = Clamp(attack_damage, 1, 5) // We expect damage input of 1 to 5 for this proc. But we leave this check juuust in case. + attack_damage = CLAMP(attack_damage, 1, 5) // We expect damage input of 1 to 5 for this proc. But we leave this check juuust in case. if(target == user) user.visible_message("[user] [pick(attack_verb)] [TU.himself] in the [organ]!") @@ -213,7 +213,7 @@ var/global/list/sparring_attack_cache = list() var/datum/gender/TT = gender_datums[target.get_visible_gender()] var/organ = affecting.name - attack_damage = Clamp(attack_damage, 1, 5) + attack_damage = CLAMP(attack_damage, 1, 5) switch(attack_damage) if(1 to 2) user.visible_message("[user] threw [target] a glancing [pick(attack_noun)] to the [organ]!") //it's not that they're kicking lightly, it's that the kick didn't quite connect @@ -259,7 +259,7 @@ var/global/list/sparring_attack_cache = list() var/obj/item/clothing/shoes = user.shoes var/datum/gender/TU = gender_datums[user.get_visible_gender()] - attack_damage = Clamp(attack_damage, 1, 5) + attack_damage = CLAMP(attack_damage, 1, 5) switch(attack_damage) if(1 to 4) user.visible_message("[pick("[user] stomped on", "[user] slammed [TU.his] [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 6a91f7aa23..75a291632c 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1333,4 +1333,19 @@ default behaviour is: return makes_dirt /mob/living/proc/needs_to_breathe() - return !isSynthetic() \ No newline at end of file + return !isSynthetic() + +/mob/living/vv_get_header() + . = ..() + . += {" + [src] +
    [ckey ? ckey : "No ckey"] / [real_name ? real_name : "No real name"] +
    + BRUTE:[getBruteLoss()] + FIRE:[getFireLoss()] + TOXIN:[getToxLoss()] + OXY:[getOxyLoss()] + CLONE:[getCloneLoss()] + BRAIN:[getBrainLoss()] +
    + "} diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 87145b46fc..b3ee75349c 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -365,7 +365,7 @@ return /mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person - fire_stacks = Clamp(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS) + fire_stacks = CLAMP(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS) /mob/living/proc/handle_fire() if(fire_stacks < 0) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 48c741c140..63cb5c0ffe 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -900,10 +900,10 @@ return /mob/proc/AdjustLosebreath(amount) - losebreath = Clamp(0, losebreath + amount, 25) + losebreath = CLAMP(0, losebreath + amount, 25) /mob/proc/SetLosebreath(amount) - losebreath = Clamp(0, amount, 25) + losebreath = CLAMP(0, amount, 25) /mob/proc/get_species() return "" diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 0bf523a48e..b335faf1d3 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -382,7 +382,7 @@ //It's easier to break out of a grab by a smaller mob break_strength += max(size_difference(affecting, assailant), 0) - var/break_chance = break_chance_table[Clamp(break_strength, 1, break_chance_table.len)] + var/break_chance = break_chance_table[CLAMP(break_strength, 1, break_chance_table.len)] if(prob(break_chance)) if(state == GRAB_KILL) reset_kill_state() diff --git a/code/modules/mob/mob_grab_specials.dm b/code/modules/mob/mob_grab_specials.dm index a497bd0cc5..a3e4c14660 100644 --- a/code/modules/mob/mob_grab_specials.dm +++ b/code/modules/mob/mob_grab_specials.dm @@ -61,7 +61,7 @@ target << "You feel extreme pain!" var/max_halloss = round(target.species.total_health * 0.8) //up to 80% of passing out - affecting.adjustHalLoss(Clamp(0, max_halloss - affecting.halloss, 30)) + affecting.adjustHalLoss(CLAMP(0, max_halloss - affecting.halloss, 30)) /obj/item/weapon/grab/proc/attack_eye(mob/living/carbon/human/target, mob/living/carbon/human/attacker) if(!istype(attacker)) diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm index 0b56c7b32a..ae8473c8ce 100644 --- a/code/modules/nano/modules/law_manager.dm +++ b/code/modules/nano/modules/law_manager.dm @@ -94,7 +94,7 @@ if(href_list["change_supplied_law_position"]) var/new_position = input(usr, "Enter new supplied law position between 1 and [MAX_SUPPLIED_LAW_NUMBER], inclusive. Inherent laws at the same index as a supplied law will not be stated.", "Law Position", supplied_law_position) as num|null if(isnum(new_position) && can_still_topic()) - supplied_law_position = Clamp(new_position, 1, MAX_SUPPLIED_LAW_NUMBER) + supplied_law_position = CLAMP(new_position, 1, MAX_SUPPLIED_LAW_NUMBER) return 1 if(href_list["edit_law"]) diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 0c496b39be..2309876e94 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -97,7 +97,7 @@ var/list/organ_cache = list() owner.can_defib = 0 /obj/item/organ/proc/adjust_germ_level(var/amount) // Unless you're setting germ level directly to 0, use this proc instead - germ_level = Clamp(germ_level + amount, 0, INFECTION_LEVEL_MAX) + germ_level = CLAMP(germ_level + amount, 0, INFECTION_LEVEL_MAX) /obj/item/organ/process() diff --git a/code/modules/overmap/ships/computers/engine_control.dm b/code/modules/overmap/ships/computers/engine_control.dm index 85ac9cf993..4316762671 100644 --- a/code/modules/overmap/ships/computers/engine_control.dm +++ b/code/modules/overmap/ships/computers/engine_control.dm @@ -70,13 +70,13 @@ if(href_list["set_limit"]) var/datum/ship_engine/E = locate(href_list["engine"]) var/newlim = input("Input new thrust limit (0..100)", "Thrust limit", E.get_thrust_limit()) as num - var/limit = Clamp(newlim/100, 0, 1) + var/limit = CLAMP(newlim/100, 0, 1) if(E) E.set_thrust_limit(limit) if(href_list["limit"]) var/datum/ship_engine/E = locate(href_list["engine"]) - var/limit = Clamp(E.get_thrust_limit() + text2num(href_list["limit"]), 0, 1) + var/limit = CLAMP(E.get_thrust_limit() + text2num(href_list["limit"]), 0, 1) if(E) E.set_thrust_limit(limit) diff --git a/code/modules/overmap/ships/computers/helm.dm b/code/modules/overmap/ships/computers/helm.dm index 58048bac5f..e31560f9e3 100644 --- a/code/modules/overmap/ships/computers/helm.dm +++ b/code/modules/overmap/ships/computers/helm.dm @@ -130,9 +130,9 @@ R.fields["y"] = linked.y if("new") var/newx = input("Input new entry x coordinate", "Coordinate input", linked.x) as num - R.fields["x"] = Clamp(newx, 1, world.maxx) + R.fields["x"] = CLAMP(newx, 1, world.maxx) var/newy = input("Input new entry y coordinate", "Coordinate input", linked.y) as num - R.fields["y"] = Clamp(newy, 1, world.maxy) + R.fields["y"] = CLAMP(newy, 1, world.maxy) known_sectors += R if (href_list["remove"]) @@ -142,12 +142,12 @@ if (href_list["setx"]) var/newx = input("Input new destiniation x coordinate", "Coordinate input", dx) as num|null if (newx) - dx = Clamp(newx, 1, world.maxx) + dx = CLAMP(newx, 1, world.maxx) if (href_list["sety"]) var/newy = input("Input new destiniation y coordinate", "Coordinate input", dy) as num|null if (newy) - dy = Clamp(newy, 1, world.maxy) + dy = CLAMP(newy, 1, world.maxy) if (href_list["x"] && href_list["y"]) dx = text2num(href_list["x"]) diff --git a/code/modules/overmap/ships/ship.dm b/code/modules/overmap/ships/ship.dm index b7849db860..0abd450a69 100644 --- a/code/modules/overmap/ships/ship.dm +++ b/code/modules/overmap/ships/ship.dm @@ -53,8 +53,8 @@ return res /obj/effect/map/ship/proc/adjust_speed(n_x, n_y) - speed[1] = Clamp(speed[1] + n_x, -default_delay, default_delay) - speed[2] = Clamp(speed[2] + n_y, -default_delay, default_delay) + speed[1] = CLAMP(speed[1] + n_x, -default_delay, default_delay) + speed[2] = CLAMP(speed[2] + n_y, -default_delay, default_delay) if(is_still()) toggle_move_stars(map_z) else diff --git a/code/modules/power/fusion/core/_core.dm b/code/modules/power/fusion/core/_core.dm index b66941c915..99b0346e62 100644 --- a/code/modules/power/fusion/core/_core.dm +++ b/code/modules/power/fusion/core/_core.dm @@ -94,7 +94,7 @@ var/list/fusion_cores = list() . = owned_field.bullet_act(Proj) /obj/machinery/power/fusion_core/proc/set_strength(var/value) - value = Clamp(value, MIN_FIELD_STR, MAX_FIELD_STR) + value = CLAMP(value, MIN_FIELD_STR, MAX_FIELD_STR) field_strength = value active_power_usage = 5 * value if(owned_field) diff --git a/code/modules/power/fusion/core/core_control.dm b/code/modules/power/fusion/core/core_control.dm index 0dca71a4d1..dc5e16c87e 100644 --- a/code/modules/power/fusion/core/core_control.dm +++ b/code/modules/power/fusion/core/core_control.dm @@ -140,7 +140,7 @@ return if(href_list["access_device"]) - var/idx = Clamp(text2num(href_list["toggle_active"]), 1, connected_devices.len) + var/idx = CLAMP(text2num(href_list["toggle_active"]), 1, connected_devices.len) cur_viewed_device = connected_devices[idx] updateUsrDialog() return 1 diff --git a/code/modules/power/fusion/gyrotron/gyrotron_control.dm b/code/modules/power/fusion/gyrotron/gyrotron_control.dm index 958e03f06f..4f5abdbd3b 100644 --- a/code/modules/power/fusion/gyrotron/gyrotron_control.dm +++ b/code/modules/power/fusion/gyrotron/gyrotron_control.dm @@ -73,7 +73,7 @@ if(!new_val) to_chat(usr, "That's not a valid number.") return 1 - G.mega_energy = Clamp(new_val, 1, 50) + G.mega_energy = CLAMP(new_val, 1, 50) G.active_power_usage = G.mega_energy * 1500 updateUsrDialog() return 1 @@ -83,7 +83,7 @@ if(!new_val) to_chat(usr, "That's not a valid number.") return 1 - G.rate = Clamp(new_val, 1, 10) + G.rate = CLAMP(new_val, 1, 10) updateUsrDialog() return 1 diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index e557bfce5a..8c404e05c0 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -65,7 +65,7 @@ set_dir(tesla_zap(src, 7, TESLA_DEFAULT_POWER, TRUE)) for (var/ball in orbiting_balls) - var/range = rand(1, Clamp(orbiting_balls.len, 3, 7)) + var/range = rand(1, CLAMP(orbiting_balls.len, 3, 7)) tesla_zap(ball, range, TESLA_MINI_POWER/7*range, TRUE) else energy = 0 // ensure we dont have miniballs of miniballs @@ -288,7 +288,7 @@ closest_grounding_rod.tesla_act(power, explosive, stun_mobs) else if(closest_mob) - var/shock_damage = Clamp(round(power/400), 10, 90) + rand(-5, 5) + var/shock_damage = CLAMP(round(power/400), 10, 90) + rand(-5, 5) closest_mob.electrocute_act(shock_damage, source, 1 - closest_mob.get_shock_protection(), ran_zone()) log_game("TESLA([source.x],[source.y],[source.z]) Shocked [key_name(closest_mob)] for [shock_damage]dmg.") message_admins("Tesla zapped [key_name_admin(closest_mob)]!") diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 65c5d4c783..b2635b8fab 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -177,21 +177,21 @@ if(href_list["amount"]) var/id = href_list["add"] - var/amount = Clamp((text2num(href_list["amount"])), 0, 200) + var/amount = CLAMP((text2num(href_list["amount"])), 0, 200) R.trans_id_to(src, id, amount) else if (href_list["addcustom"]) var/id = href_list["addcustom"] useramount = input("Select the amount to transfer.", 30, useramount) as num - useramount = Clamp(useramount, 0, 200) + useramount = CLAMP(useramount, 0, 200) src.Topic(null, list("amount" = "[useramount]", "add" = "[id]")) else if (href_list["remove"]) if(href_list["amount"]) var/id = href_list["remove"] - var/amount = Clamp((text2num(href_list["amount"])), 0, 200) + var/amount = CLAMP((text2num(href_list["amount"])), 0, 200) if(mode) reagents.trans_id_to(beaker, id, amount) else @@ -202,7 +202,7 @@ var/id = href_list["removecustom"] useramount = input("Select the amount to transfer.", 30, useramount) as num - useramount = Clamp(useramount, 0, 200) + useramount = CLAMP(useramount, 0, 200) src.Topic(null, list("amount" = "[useramount]", "remove" = "[id]")) else if (href_list["toggle"]) @@ -224,7 +224,7 @@ count = input("Select the number of pills to make.", "Max [max_pill_count]", pillamount) as null|num if(!count) //Covers 0 and cancel return - count = Clamp(count, 1, max_pill_count) + count = CLAMP(count, 1, max_pill_count) if(reagents.total_volume/count < 1) //Sanity checking. return diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm index 19afc0f564..75fb5fff2a 100644 --- a/code/modules/research/message_server.dm +++ b/code/modules/research/message_server.dm @@ -169,6 +169,11 @@ var/global/list/obj/machinery/message_server/message_servers = list() var/value var/details +/datum/feedback_variable/vv_edit_var(var_name, var_value) + if(var_name == NAMEOF(src, variable) || var_name == NAMEOF(src, value) || var_name == NAMEOF(src, details)) + return FALSE + return ..() + /datum/feedback_variable/New(var/param_variable,var/param_value = 0) variable = param_variable value = param_value @@ -319,6 +324,15 @@ var/obj/machinery/blackbox_recorder/blackbox feedback_set_details("round_end","[time2text(world.realtime)]") //This one MUST be the last one that gets set. +/obj/machinery/blackbox_recorder/vv_edit_var(var_name, var_value) + var/static/list/blocked_vars //hacky as fuck kill me + if(!blocked_vars) + var/obj/machinery/M = new + var/list/parent_vars = M.vars.Copy() + blocked_vars = vars.Copy() - parent_vars + if(var_name in blocked_vars) + return FALSE + return ..() //This proc is only to be called at round end. /obj/machinery/blackbox_recorder/proc/save_all_data_to_sql() diff --git a/code/modules/telesci/telesci_computer.dm b/code/modules/telesci/telesci_computer.dm index 43784ef42a..277463bddc 100644 --- a/code/modules/telesci/telesci_computer.dm +++ b/code/modules/telesci/telesci_computer.dm @@ -173,7 +173,7 @@ return if(telepad) - var/trueDistance = Clamp(distance + distance_off, 1, get_max_allowed_distance()) + var/trueDistance = CLAMP(distance + distance_off, 1, get_max_allowed_distance()) var/trueRotation = rotation + rotation_off var/datum/projectile_data/proj_data = simple_projectile_trajectory(telepad.x, telepad.y, trueRotation, trueDistance) @@ -283,7 +283,7 @@ updateDialog() /obj/machinery/computer/telescience/proc/teleport(mob/user) - distance = Clamp(distance, 0, get_max_allowed_distance()) + distance = CLAMP(distance, 0, get_max_allowed_distance()) if(rotation == null || distance == null || z_co == null) temp_msg = "ERROR!
    Set a distance, rotation and sector." return @@ -320,14 +320,14 @@ var/new_rot = input("Please input desired bearing in degrees.", name, rotation) as num if(..()) // Check after we input a value, as they could've moved after they entered something return - rotation = Clamp(new_rot, -900, 900) + rotation = CLAMP(new_rot, -900, 900) rotation = round(rotation, 0.01) if(href_list["setdistance"]) var/new_pow = input("Please input desired distance in meters.", name, rotation) as num if(..()) // Check after we input a value, as they could've moved after they entered something return - distance = Clamp(new_pow, 1, get_max_allowed_distance()) + distance = CLAMP(new_pow, 1, get_max_allowed_distance()) distance = FLOOR(distance, 1) if(href_list["setz"]) diff --git a/code/modules/virus2/admin.dm b/code/modules/virus2/admin.dm index dc10bc85f9..e2821db1a9 100644 --- a/code/modules/virus2/admin.dm +++ b/code/modules/virus2/admin.dm @@ -15,7 +15,7 @@ return 1 -/datum/disease2/disease/get_view_variables_header() +/datum/disease2/disease/vv_get_header() . = list() for(var/datum/disease2/effectholder/E in effects) . += "[E.stage]: [E.effect.name]" diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 772d008dd0..26c03300a2 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -71,12 +71,12 @@ // // Hide vore organs in contents // -/mob/living/view_variables_filter_contents(list/L) - . = ..() - var/len_before = L.len - L -= vore_organs - . += len_before - L.len - +///mob/living/view_variables_filter_contents(list/L) +// . = ..() +// var/len_before = L.len +// L -= vore_organs +// . += len_before - L.len +// // // Handle being clicked, perhaps with something to devour // diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index 679fe389de..336b86b5a4 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -654,14 +654,14 @@ var/new_damage = input(user, "Choose the amount of burn damage prey will take per tick. Ranges from 0 to 6.", "Set Belly Burn Damage.", selected.digest_burn) as num|null if(new_damage == null) return - var/new_new_damage = Clamp(new_damage, 0, 6) + var/new_new_damage = CLAMP(new_damage, 0, 6) selected.digest_burn = new_new_damage if(href_list["b_brute_dmg"]) var/new_damage = input(user, "Choose the amount of brute damage prey will take per tick. Ranges from 0 to 6", "Set Belly Brute Damage.", selected.digest_brute) as num|null if(new_damage == null) return - var/new_new_damage = Clamp(new_damage, 0, 6) + var/new_new_damage = CLAMP(new_damage, 0, 6) selected.digest_brute = new_new_damage if(href_list["b_escapable"]) diff --git a/code/modules/xenoarcheaology/tools/tools.dm b/code/modules/xenoarcheaology/tools/tools.dm index 00eb61b79b..c5eb9b35ac 100644 --- a/code/modules/xenoarcheaology/tools/tools.dm +++ b/code/modules/xenoarcheaology/tools/tools.dm @@ -254,7 +254,7 @@ if(prob(scan_ticks * 10)) spawn(0) set background = 1 - if(is_processing) + if(datum_flags & DF_ISPROCESSING) //scan radios in the world to try and find one var/cur_dist = 999 for(var/obj/item/device/radio/beacon/R in all_beacons) diff --git a/code/world.dm b/code/world.dm index ccd0bc26d0..d9643ea2f2 100644 --- a/code/world.dm +++ b/code/world.dm @@ -299,7 +299,7 @@ var/world_topic_spam_protect_time = world.timeofday info["hasbeenrev"] = M.mind ? M.mind.has_been_rev : "No mind" info["stat"] = M.stat info["type"] = M.type - if(isliving(M)) + if(istype(M, /mob/living)) var/mob/living/L = M info["damage"] = list2params(list( oxy = L.getOxyLoss(), @@ -669,7 +669,7 @@ proc/establish_old_db_connection() // Things to do when a new z-level was just made. /world/proc/max_z_changed() - if(!islist(GLOB.players_by_zlevel)) + if(!istype(GLOB.players_by_zlevel, /list)) GLOB.players_by_zlevel = new /list(world.maxz, 0) while(GLOB.players_by_zlevel.len < world.maxz) GLOB.players_by_zlevel.len++ diff --git a/vorestation.dme b/vorestation.dme index 8ef0fc1910..520d84a4d0 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -44,6 +44,7 @@ #include "code\__defines\holomap.dm" #include "code\__defines\integrated_circuits.dm" #include "code\__defines\inventory_sizes.dm" +#include "code\__defines\is_helpers.dm" #include "code\__defines\items_clothing.dm" #include "code\__defines\lighting.dm" #include "code\__defines\machinery.dm" @@ -74,6 +75,7 @@ #include "code\__defines\typeids.dm" #include "code\__defines\unit_tests.dm" #include "code\__defines\vote.dm" +#include "code\__defines\vv.dm" #include "code\__defines\xenoarcheaology.dm" #include "code\__defines\ZAS.dm" #include "code\_compatibility\509\_JSON.dm" @@ -81,6 +83,7 @@ #include "code\_compatibility\509\JSON Writer.dm" #include "code\_compatibility\509\text.dm" #include "code\_compatibility\509\type2type.dm" +#include "code\_global_vars\bitfields.dm" #include "code\_global_vars\misc.dm" #include "code\_global_vars\mobs.dm" #include "code\_global_vars\sensitive.dm" @@ -1424,8 +1427,6 @@ #include "code\modules\admin\verbs\lightning_strike.dm" #include "code\modules\admin\verbs\map_template_loadverb.dm" #include "code\modules\admin\verbs\mapping.dm" -#include "code\modules\admin\verbs\massmodvar.dm" -#include "code\modules\admin\verbs\modifyvariables.dm" #include "code\modules\admin\verbs\panicbunker.dm" #include "code\modules\admin\verbs\playsound.dm" #include "code\modules\admin\verbs\possess.dm" @@ -1439,7 +1440,12 @@ #include "code\modules\admin\verbs\SDQL2\SDQL_2.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2_wrappers.dm" -#include "code\modules\admin\view_variables\helpers.dm" +#include "code\modules\admin\view_variables\admin_delete.dm" +#include "code\modules\admin\view_variables\debug_variables.dm" +#include "code\modules\admin\view_variables\get_variables.dm" +#include "code\modules\admin\view_variables\helpers_deprecated.dm" +#include "code\modules\admin\view_variables\mass_edit_variables.dm" +#include "code\modules\admin\view_variables\modify_variables.dm" #include "code\modules\admin\view_variables\topic.dm" #include "code\modules\admin\view_variables\view_variables.dm" #include "code\modules\ai\_defines.dm"