Ports TGstation view variables + admin proccall guards, and all the baggage that comes with it

This commit is contained in:
Neerti
2019-01-15 22:18:50 -05:00
committed by Novacat
parent 5806e2d712
commit fe0b7373b3
81 changed files with 2289 additions and 1560 deletions

View File

@@ -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)

View File

@@ -3,10 +3,13 @@
#define TICK_LIMIT_MC 70
#define TICK_LIMIT_MC_INIT_DEFAULT 98
#define TICK_CHECK ( TICK_USAGE > GLOB.CURRENT_TICKLIMIT )
#define CHECK_TICK if TICK_CHECK stoplag()
<<<<<<< HEAD
#define TICK_USAGE world.tick_usage
#define TICK_CHECK ( TICK_USAGE > Master.current_ticklimit )
#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 )
#define CHECK_TICK_HIGH_PRIORITY ( TICK_CHECK_HIGH_PRIORITY? stoplag() : 0 )
#define UNTIL(X) while(!(X)) stoplag()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

44
code/__defines/vv.dm Normal file
View File

@@ -0,0 +1,44 @@
#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 "<br><font size='1' color='red'><b>Marked Object</b></font>"
#define VV_MSG_EDITED "<br><font size='1' color='red'><b>Var Edited</b></font>"
#define VV_MSG_DELETED "<br><font size='1' color='red'><b>Deleted</b></font>"
#define VV_NORMAL_LIST_NO_EXPAND_THRESHOLD 50
#define VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD 150
//Helpers for vv_get_dropdown()
#define VV_DROPDOWN_OPTION(href_key, name) . += "<option value='?_src_=vars;[href_key]=TRUE;target=\ref[src]'>[name]</option>"
//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"

View File

@@ -0,0 +1,7 @@
GLOBAL_LIST_INIT(bitfields, list(
"datum_flags" = list(
"DF_VAR_EDITED" = DF_VAR_EDITED,
"DF_ISPROCESSING" = DF_ISPROCESSING
)
))

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1462,5 +1462,96 @@ var/mob/dview/dview_mob = new
/proc/pass()
return
<<<<<<< HEAD
=======
#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

View File

@@ -1,11 +1,8 @@
#define Clamp(x, y, z) (x <= y ? y : (x >= z ? z : x))
#define CLAMP01(x) (Clamp(x, 0, 1))
#define span(class, text) ("<span class='[class]'>[text]</span>")
#define get_turf(A) get_step(A,0)
<<<<<<< HEAD
#define isAI(A) istype(A, /mob/living/silicon/ai)
#define isalien(A) istype(A, /mob/living/carbon/alien)
@@ -52,6 +49,8 @@
#define isweakref(A) istype(A, /weakref)
=======
>>>>>>> b1860f9... Merge pull request #5829 from kevinz000/tg_vv
#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

View File

@@ -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()

View File

@@ -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

View File

@@ -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, "<span class='userdanger'>The [title] browser you tried to open failed a sanity check! Please report this on github!</span>")
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 = {"<center><b>[Message]</b></center><br />
<div style="text-align:center">
<a style="font-size:large;float:[( Button2 ? "left" : "right" )]" href="?src=\ref[src];button=1">[Button1]</a>"}
if (Button2)
output += {"<a style="font-size:large;[( Button3 ? "" : "float:right" )]" href="?src=\ref[src];button=2">[Button2]</a>"}
if (Button3)
output += {"<a style="font-size:large;float:right" href="?src=\ref[src];button=3">[Button3]</a>"}
output += {"</div>"}
..(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 = {"<form><input type="hidden" name="src" value="\ref[src]"><ul class="sparse">"}
if (inputtype == "checkbox" || inputtype == "radio")
for (var/i in values)
var/div_slider = slidecolor
if(!i["allowed_edit"])
div_slider = "locked"
output += {"<li>
<label class="switch">
<input type="[inputtype]" value="1" name="[i["name"]]"[i["checked"] ? " checked" : ""][i["allowed_edit"] ? "" : " onclick='return false' onkeydown='return false'"]>
<div class="slider [div_slider ? "[div_slider]" : ""]"></div>
<span>[i["name"]]</span>
</label>
</li>"}
else
for (var/i in values)
output += {"<li><input id="name="[i["name"]]"" style="width: 50px" type="[type]" name="[i["name"]]" value="[i["value"]]">
<label for="[i["name"]]">[i["name"]]</label></li>"}
output += {"</ul><div style="text-align:center">
<button type="submit" name="button" value="1" style="font-size:large;float:[( Button2 ? "left" : "right" )]">[Button1]</button>"}
if (Button2)
output += {"<button type="submit" name="button" value="2" style="font-size:large;[( Button3 ? "" : "float:right" )]">[Button2]</button>"}
if (Button3)
output += {"<button type="submit" name="button" value="3" style="font-size:large;float:right">[Button3]</button>"}
output += {"</form></div>"}
..(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

View File

@@ -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

View File

@@ -1,21 +1,68 @@
#define VV_MSG_MARKED "<br><font size='1' color='red'><b>Marked Object</b></font>"
#define VV_MSG_EDITED "<br><font size='1' color='red'><b>Var Edited</b></font>"
#define VV_MSG_DELETED "<br><font size='1' color='red'><b>Deleted</b></font>"
/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("proc_call", "Call Proc")
VV_DROPDOWN_OPTION("mark_object", "Mark Object")
VV_DROPDOWN_OPTION("delete", "Delete")
VV_DROPDOWN_OPTION("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 <a href='?_src_=vars;datumrefresh=\ref[src]'>VV window</a>")
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))
. += "<b>[vars["name"]]</b><br>"
/datum/proc/on_reagent_change(changetype)
return

View File

@@ -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

View File

@@ -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 = "<a href='?_src_=vars;datumedit=\ref[src];varnameedit=name'><b>[src]</b></a>"
. += {"
[custom_edit_name]
<br><font size='1'>
<a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=left'><<</a>
<a href='?_src_=vars;datumedit=\ref[src];varnameedit=dir'>[dir2text(dir)]</a>
<a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=right'>>></a>
</font>
"}

View File

@@ -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)

View File

@@ -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()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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."

View File

@@ -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

View File

@@ -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()

View File

@@ -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,8 +215,10 @@ var/list/admin_verbs_debug = list(
/client/proc/show_plant_genes,
/client/proc/enable_debug_verbs,
/client/proc/callproc,
<<<<<<< HEAD
/client/proc/callproc_target,
/client/proc/debug_process, //VOREStation Add,
/client/proc/callproc_datum,
/client/proc/SDQL2_query,
/client/proc/Jump,
/client/proc/debug_rogueminer,
@@ -234,8 +237,10 @@ var/list/admin_verbs_debug = list(
var/list/admin_verbs_paranoid_debug = list(
/client/proc/callproc,
<<<<<<< HEAD
/client/proc/callproc_target,
/client/proc/debug_process, //VOREStation Add,
/client/proc/callproc_datum,
/client/proc/debug_controller
)
@@ -303,8 +308,10 @@ var/list/admin_verbs_hideable = list(
/client/proc/restart_controller,
/client/proc/cmd_admin_list_open_jobs,
/client/proc/callproc,
<<<<<<< HEAD
/client/proc/callproc_target,
/client/proc/debug_process, //VOREStation Add,
/client/proc/callproc_datum,
/client/proc/Debug2,
/client/proc/reload_admins,
/client/proc/kill_air,
@@ -372,7 +379,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,

View File

@@ -1,16 +1,18 @@
/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
var/returnval = null
switch(alert("Proc owned by something?",, "Yes", "No", "Cancel"))
switch(alert("Proc owned by something?",,"Yes","No"))
if("Yes")
<<<<<<< HEAD
targetselected=1
switch(input("Proc owned by...", "Owner", null) as null|anything in list("Obj", "Mob", "Area or Turf", "Client"))
if("Obj")
@@ -25,56 +27,125 @@
return
if(!target)
usr << "Proc call cancelled."
=======
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"])
>>>>>>> b1860f9... Merge pull request #5829 from kevinz000/tg_vv
return
if("Cancel")
return
target = value["value"]
if("No")
; // do nothing
target = null
targetselected = 0
callproc_targetpicked(targetselected, target)
var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
if(!procname)
return
/client/proc/callproc_target(atom/A in world)
set category = "Debug"
set name = "Advanced ProcCall Target"
//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(!check_rights(R_DEBUG)) return
if(config.debugparanoid && !check_rights(R_ADMIN)) return
if(targetselected && !hascall(target,testname))
to_chat(usr, "<font color='red'>Error: callproc(): type [target.type] has no proc named [procname].</font>")
return
else
var/procpath = text2path(procname)
if (!procpath)
to_chat(usr, "<font color='red'>Error: callproc(): proc [procname] does not exist. (Did you forget the /proc/ part?)</font>")
return
var/list/lst = get_callproc_args()
if(!lst)
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(targetselected)
if(!target)
usr << "Your callproc target no longer exists."
return
if(!hascall(target, procname))
usr << "\The [target] has no call [procname]()"
to_chat(usr, "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>")
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)
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"].")
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!
var/list/arguments = list()
var/done = 0
var/current = null
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)
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)
return
/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, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
GLOB.AdminProcCallSpamPrevention[ckey] = TRUE
UNTIL(!GLOB.AdminProcCaller)
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
GLOB.AdminProcCallSpamPrevention -= ckey
else
UNTIL(!GLOB.AdminProcCaller)
GLOB.LastAdminCalledProc = procname
if(target != GLOBAL_PROC)
GLOB.LastAdminCalledTargetRef = "\ref[target]"
GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
++GLOB.AdminProcCallCount
. = world.WrapAdminProcCall(target, procname, arguments)
if(--GLOB.AdminProcCallCount == 0)
GLOB.AdminProcCaller = null
//adv proc call this, ya nerds
/world/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
if(target == GLOBAL_PROC)
return call(procname)(arglist(arguments))
else if(target != world)
return call(target, procname)(arglist(arguments))
else
log_admin("[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
<<<<<<< HEAD
if("finished")
done = 1
@@ -138,15 +209,78 @@
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)()
else
log_admin("[key_name(src)] called [procname]() with [arguments.len ? "the arguments [list2params(arguments)]" : "no arguments"].")
returnval = call(procname)(arglist(arguments))
=======
/client/proc/callproc_datum(datum/A as null|area|mob|obj|turf)
set category = "Debug"
set name = "Atom ProcCall"
set waitfor = 0
usr << "<span class='info'>[procname]() returned: [isnull(returnval) ? "null" : returnval]</span>"
feedback_add_details("admin_verb","APC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
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, "<font color='red'>Error: callproc_datum(): type [A.type] has no proc named [procname].</font>")
return
var/list/lst = get_callproc_args()
if(!lst)
return
if(!A || !IsValidSrc(A))
to_chat(usr, "<span class='warning'>Error: callproc_datum(): owner of proc no longer exists.</span>")
return
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
. = list()
var/list/named_args = list()
while(argnum--)
var/named_arg = input("Leave blank for positional argument. Positional arguments will be considered as if they were added first.", "Named argument") as text|null
var/value = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT))
if (!value["class"])
>>>>>>> b1860f9... Merge pull request #5829 from kevinz000/tg_vv
return
if(named_arg)
named_args[named_arg] = value["value"]
else
. += value["value"]
if(LAZYLEN(named_args))
. += named_args
/client/proc/get_callproc_returnval(returnval,procname)
. = ""
if(islist(returnval))
var/list/returnedlist = returnval
. = "<font color='blue'>"
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"
. += "</font>"
else
. = "<font color='blue'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</font>"

View File

@@ -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 << "<font color='red'>Error: Cannot proceed. They have more or equal rights to us.</font>"
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)

View File

@@ -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

View File

@@ -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 << "<font color='red'>It is forbidden to edit this object's variables.</font>"
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 <b>NUM</b>."
default = "num"
dir = 1
else if(istext(var_value))
usr << "Variable appears to be <b>TEXT</b>."
default = "text"
else if(isloc(var_value))
usr << "Variable appears to be <b>REFERENCE</b>."
default = "reference"
else if(isicon(var_value))
usr << "Variable appears to be <b>ICON</b>."
var_value = "\icon[var_value]"
default = "icon"
else if(istype(var_value,/atom) || istype(var_value,/datum))
usr << "Variable appears to be <b>TYPE</b>."
default = "type"
else if(istype(var_value,/list))
usr << "Variable appears to be <b>LIST</b>."
default = "list"
else if(istype(var_value,/client))
usr << "Variable appears to be <b>CLIENT</b>."
default = "cancel"
else
usr << "Variable appears to be <b>FILE</b>."
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)

View File

@@ -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 <b>NUM</b>."
default = "num"
dir = 1
else if(istext(variable))
usr << "Variable appears to be <b>TEXT</b>."
default = "text"
else if(isloc(variable))
usr << "Variable appears to be <b>REFERENCE</b>."
default = "reference"
else if(isicon(variable))
usr << "Variable appears to be <b>ICON</b>."
variable = "\icon[variable]"
default = "icon"
else if(istype(variable,/atom) || istype(variable,/datum))
usr << "Variable appears to be <b>TYPE</b>."
default = "type"
else if(istype(variable,/list))
usr << "Variable appears to be <b>LIST</b>."
default = "list"
else if(istype(variable,/client))
usr << "Variable appears to be <b>CLIENT</b>."
default = "cancel"
else
usr << "Variable appears to be <b>FILE</b>."
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 << "<span class='danger'>It is forbidden to edit this object's variables.</span>"
return
if(istype(O, /client) && (param_var_name == "ckey" || param_var_name == "key"))
usr << "<span class='danger'>You cannot edit ckeys on client objects.</span>"
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 <b>NUM</b>."
class = "num"
dir = 1
else if(istext(var_value))
usr << "Variable appears to be <b>TEXT</b>."
class = "text"
else if(isloc(var_value))
usr << "Variable appears to be <b>REFERENCE</b>."
class = "reference"
else if(isicon(var_value))
usr << "Variable appears to be <b>ICON</b>."
var_value = "\icon[var_value]"
class = "icon"
else if(istype(var_value,/atom) || istype(var_value,/datum))
usr << "Variable appears to be <b>TYPE</b>."
class = "type"
else if(istype(var_value,/list))
usr << "Variable appears to be <b>LIST</b>."
class = "list"
else if(istype(var_value,/client))
usr << "Variable appears to be <b>CLIENT</b>."
class = "cancel"
else
usr << "Variable appears to be <b>FILE</b>."
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 <b>NUM</b>."
default = "num"
dir = 1
else if(istext(var_value))
usr << "Variable appears to be <b>TEXT</b>."
default = "text"
else if(isloc(var_value))
usr << "Variable appears to be <b>REFERENCE</b>."
default = "reference"
else if(isicon(var_value))
usr << "Variable appears to be <b>ICON</b>."
var_value = "\icon[var_value]"
default = "icon"
else if(istype(var_value,/atom) || istype(var_value,/datum))
usr << "Variable appears to be <b>TYPE</b>."
default = "type"
else if(istype(var_value,/list))
usr << "Variable appears to be <b>LIST</b>."
default = "list"
else if(istype(var_value,/client))
usr << "Variable appears to be <b>CLIENT</b>."
default = "cancel"
else
usr << "Variable appears to be <b>FILE</b>."
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]]")

View File

@@ -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"

View File

@@ -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", "")

View File

@@ -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 = "<li style='backgroundColor:white'>(<a href='?_src_=vars;listedit=\ref[DA];index=[index]'>E</a>) (<a href='?_src_=vars;listchange=\ref[DA];index=[index]'>C</a>) (<a href='?_src_=vars;listremove=\ref[DA];index=[index]'>-</a>) "
else
header = "<li style='backgroundColor:white'>(<a href='?_src_=vars;datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;datummass=\ref[DA];varnamemass=[name]'>M</a>) "
else
header = "<li>"
var/item
if (isnull(value))
item = "[VV_HTML_ENCODE(name)] = <span class='value'>null</span>"
else if (istext(value))
item = "[VV_HTML_ENCODE(name)] = <span class='value'>\"[VV_HTML_ENCODE(value)]\"</span>"
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)] = (<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
#else
item = "[VV_HTML_ENCODE(name)] = /icon (<span class='value'>[value]</span>)"
#endif
else if (isfile(value))
item = "[VV_HTML_ENCODE(name)] = <span class='value'>'[value]'</span>"
else if (istype(value, /datum))
var/datum/D = value
if ("[D]" != "[D.type]") //if the thing as a name var, lets use it.
item = "<a href='?_src_=vars;Vars=\ref[value]'>[VV_HTML_ENCODE(name)] \ref[value]</a> = [D] [D.type]"
else
item = "<a href='?_src_=vars;Vars=\ref[value]'>[VV_HTML_ENCODE(name)] \ref[value]</a> = [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 = "<a href='?_src_=vars;Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
else
item = "<a href='?_src_=vars;Vars=\ref[value]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
else if (name in GLOB.bitfields)
var/list/flags = list()
for (var/i in GLOB.bitfields[name])
if (value & GLOB.bitfields[name][i])
flags += i
item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(jointext(flags, ", "))]"
else
item = "[VV_HTML_ENCODE(name)] = <span class='value'>[VV_HTML_ENCODE(value)]</span>"
return "[header][item]</li>"
#undef VV_HTML_ENCODE

View File

@@ -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

View File

@@ -1,194 +0,0 @@
/datum/proc/get_view_variables_header()
return "<b>[src]</b>"
/atom/get_view_variables_header()
return {"
<a href='?_src_=vars;datumedit=\ref[src];varnameedit=name'><b>[src]</b></a>
<br><font size='1'>
<a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=left'><<</a>
<a href='?_src_=vars;datumedit=\ref[src];varnameedit=dir'>[dir2text(dir)]</a>
<a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=right'>>></a>
</font>
"}
/mob/living/get_view_variables_header()
return {"
<a href='?_src_=vars;rename=\ref[src]'><b>[src]</b></a><font size='1'>
<br><a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=left'><<</a> <a href='?_src_=vars;datumedit=\ref[src];varnameedit=dir'>[dir2text(dir)]</a> <a href='?_src_=vars;rotatedatum=\ref[src];rotatedir=right'>>></a>
<br><a href='?_src_=vars;datumedit=\ref[src];varnameedit=ckey'>[ckey ? ckey : "No ckey"]</a> / <a href='?_src_=vars;datumedit=\ref[src];varnameedit=real_name'>[real_name ? real_name : "No real name"]</a>
<br>
BRUTE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=brute'>[getBruteLoss()]</a>
FIRE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=fire'>[getFireLoss()]</a>
TOXIN:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=toxin'>[getToxLoss()]</a>
OXY:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=oxygen'>[getOxyLoss()]</a>
CLONE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=clone'>[getCloneLoss()]</a>
BRAIN:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=brain'>[getBrainLoss()]</a>
</font>
"}
/datum/proc/get_view_variables_options()
return ""
/mob/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;mob_player_panel=\ref[src]'>Show player panel</option>
<option>---</option>
<option value='?_src_=vars;give_modifier=\ref[src]'>Give Modifier</option>
<option value='?_src_=vars;give_spell=\ref[src]'>Give Spell</option>
<option value='?_src_=vars;give_disease2=\ref[src]'>Give Disease</option>
<option value='?_src_=vars;give_disease=\ref[src]'>Give TG-style Disease</option>
<option value='?_src_=vars;godmode=\ref[src]'>Toggle Godmode</option>
<option value='?_src_=vars;build_mode=\ref[src]'>Toggle Build Mode</option>
<option value='?_src_=vars;ninja=\ref[src]'>Make Space Ninja</option>
<option value='?_src_=vars;make_skeleton=\ref[src]'>Make 2spooky</option>
<option value='?_src_=vars;direct_control=\ref[src]'>Assume Direct Control</option>
<option value='?_src_=vars;drop_everything=\ref[src]'>Drop Everything</option>
<option value='?_src_=vars;regenerateicons=\ref[src]'>Regenerate Icons</option>
<option value='?_src_=vars;addlanguage=\ref[src]'>Add Language</option>
<option value='?_src_=vars;remlanguage=\ref[src]'>Remove Language</option>
<option value='?_src_=vars;addorgan=\ref[src]'>Add Organ</option>
<option value='?_src_=vars;remorgan=\ref[src]'>Remove Organ</option>
<option value='?_src_=vars;fix_nano=\ref[src]'>Fix NanoUI</option>
<option value='?_src_=vars;addverb=\ref[src]'>Add Verb</option>
<option value='?_src_=vars;remverb=\ref[src]'>Remove Verb</option>
<option>---</option>
<option value='?_src_=vars;gib=\ref[src]'>Gib</option>
<option value='?_src_=vars;explode=\ref[src]'>Trigger explosion</option>
<option value='?_src_=vars;emp=\ref[src]'>Trigger EM pulse</option>
"}
/mob/living/carbon/human/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;setspecies=\ref[src]'>Set Species</option>
<option value='?_src_=vars;makeai=\ref[src]'>Make AI</option>
<option value='?_src_=vars;makerobot=\ref[src]'>Make cyborg</option>
<option value='?_src_=vars;makemonkey=\ref[src]'>Make monkey</option>
<option value='?_src_=vars;makealien=\ref[src]'>Make alien</option>
"}
/obj/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;delall=\ref[src]'>Delete all of type</option>
<option value='?_src_=vars;explode=\ref[src]'>Trigger explosion</option>
<option value='?_src_=vars;emp=\ref[src]'>Trigger EM pulse</option>
"}
/turf/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;explode=\ref[src]'>Trigger explosion</option>
<option value='?_src_=vars;emp=\ref[src]'>Trigger EM pulse</option>
"}
/datum/proc/get_variables()
. = vars - VV_hidden()
if(!usr || !check_rights(R_ADMIN|R_DEBUG, FALSE))
. -= VV_secluded()
/datum/proc/get_variable_value(varname)
return vars[varname]
/datum/proc/set_variable_value(varname, value)
vars[varname] = value
/datum/proc/get_initial_variable_value(varname)
return initial(vars[varname])
/datum/proc/make_view_variables_variable_entry(var/varname, var/value, var/hide_watch = 0)
return {"
(<a href='?_src_=vars;datumedit=\ref[src];varnameedit=[varname]'>E</a>)
(<a href='?_src_=vars;datumchange=\ref[src];varnamechange=[varname]'>C</a>)
(<a href='?_src_=vars;datummass=\ref[src];varnamemass=[varname]'>M</a>)
[hide_watch ? "" : "(<a href='?_src_=vars;datumwatch=\ref[src];varnamewatch=[varname]'>W</a>)"]
"}
// No mass editing of clients
/client/make_view_variables_variable_entry(var/varname, var/value, var/hide_watch = 0)
return {"
(<a href='?_src_=vars;datumedit=\ref[src];varnameedit=[varname]'>E</a>)
(<a href='?_src_=vars;datumchange=\ref[src];varnamechange=[varname]'>C</a>)
[hide_watch ? "" : "(<a href='?_src_=vars;datumwatch=\ref[src];varnamewatch=[varname]'>W</a>)"]
"}
// These methods are all procs and don't use stored lists to avoid VV exploits
// The following vars cannot be viewed by anyone
/datum/proc/VV_hidden()
return list()
// The following vars can only be viewed by R_ADMIN|R_DEBUG
/datum/proc/VV_secluded()
return list()
/datum/configuration/VV_secluded()
return vars
// The following vars cannot be edited by anyone
/datum/proc/VV_static()
return list("parent_type")
/atom/VV_static()
return ..() + list("bound_x", "bound_y", "bound_height", "bound_width", "bounds", "step_x", "step_y", "step_size")
/client/VV_static()
return ..() + list("holder", "prefs")
/datum/admins/VV_static()
return vars
// The following vars require R_DEBUG to edit
/datum/proc/VV_locked()
return list("vars", "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, "<span class='warning'>\The [src] does not have a var '[var_to_edit]'</span>")
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
)

View File

@@ -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 ..() + {"
<option value='?_src_=vars;mob_player_panel=\ref[src]'>Show player panel</option>
<option>---</option>
<option value='?_src_=vars;give_modifier=\ref[src]'>Give Modifier</option>
<option value='?_src_=vars;give_spell=\ref[src]'>Give Spell</option>
<option value='?_src_=vars;give_disease2=\ref[src]'>Give Disease</option>
<option value='?_src_=vars;give_disease=\ref[src]'>Give TG-style Disease</option>
<option value='?_src_=vars;godmode=\ref[src]'>Toggle Godmode</option>
<option value='?_src_=vars;build_mode=\ref[src]'>Toggle Build Mode</option>
<option value='?_src_=vars;ninja=\ref[src]'>Make Space Ninja</option>
<option value='?_src_=vars;make_skeleton=\ref[src]'>Make 2spooky</option>
<option value='?_src_=vars;direct_control=\ref[src]'>Assume Direct Control</option>
<option value='?_src_=vars;drop_everything=\ref[src]'>Drop Everything</option>
<option value='?_src_=vars;regenerateicons=\ref[src]'>Regenerate Icons</option>
<option value='?_src_=vars;addlanguage=\ref[src]'>Add Language</option>
<option value='?_src_=vars;remlanguage=\ref[src]'>Remove Language</option>
<option value='?_src_=vars;addorgan=\ref[src]'>Add Organ</option>
<option value='?_src_=vars;remorgan=\ref[src]'>Remove Organ</option>
<option value='?_src_=vars;fix_nano=\ref[src]'>Fix NanoUI</option>
<option value='?_src_=vars;addverb=\ref[src]'>Add Verb</option>
<option value='?_src_=vars;remverb=\ref[src]'>Remove Verb</option>
<option>---</option>
<option value='?_src_=vars;gib=\ref[src]'>Gib</option>
"}
/mob/living/carbon/human/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;setspecies=\ref[src]'>Set Species</option>
<option value='?_src_=vars;makeai=\ref[src]'>Make AI</option>
<option value='?_src_=vars;makerobot=\ref[src]'>Make cyborg</option>
<option value='?_src_=vars;makemonkey=\ref[src]'>Make monkey</option>
<option value='?_src_=vars;makealien=\ref[src]'>Make alien</option>
"}
/obj/get_view_variables_options()
return ..() + {"
<option value='?_src_=vars;delall=\ref[src]'>Delete all of type</option>
"}

View File

@@ -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 <b>[uppertext(default)]</b>.")
to_chat(src, "Variable contains: [var_value]")
if(default == VV_NUM)
var/dir_text = ""
if(var_value > 0 && var_value < 16)
if(var_value & 1)
dir_text += "NORTH"
if(var_value & 2)
dir_text += "SOUTH"
if(var_value & 4)
dir_text += "EAST"
if(var_value & 8)
dir_text += "WEST"
if(dir_text)
to_chat(src, "If a direction, direction is: [dir_text]")
var/value = vv_get_value(default_class = default)
var/new_value = value["value"]
var/class = value["class"]
if(!class || !new_value == null && class != VV_NULL)
return
if (class == VV_MESSAGE)
class = VV_TEXT
if (value["type"])
class = VV_NEW_TYPE
var/original_name = "[O]"
var/rejected = 0
var/accepted = 0
switch(class)
if(VV_RESTORE_DEFAULT)
to_chat(src, "Finding items...")
var/list/items = get_all_of_type(O.type, method)
to_chat(src, "Changing [items.len] items...")
for(var/thing in items)
if (!thing)
continue
var/datum/D = thing
if (D.vv_edit_var(variable, initial(D.vars[variable])) != FALSE)
accepted++
else
rejected++
CHECK_TICK
if(VV_TEXT)
var/list/varsvars = vv_parse_text(O, new_value)
var/pre_processing = new_value
var/unique
if (varsvars && varsvars.len)
unique = alert(usr, "Process vars unique to each instance, or same for all?", "Variable Association", "Unique", "Same")
if(unique == "Unique")
unique = TRUE
else
unique = FALSE
for(var/V in varsvars)
new_value = replacetext(new_value,"\[[V]]","[O.vars[V]]")
to_chat(src, "Finding items...")
var/list/items = get_all_of_type(O.type, method)
to_chat(src, "Changing [items.len] items...")
for(var/thing in items)
if (!thing)
continue
var/datum/D = thing
if(unique)
new_value = pre_processing
for(var/V in varsvars)
new_value = replacetext(new_value,"\[[V]]","[D.vars[V]]")
if (D.vv_edit_var(variable, new_value) != FALSE)
accepted++
else
rejected++
CHECK_TICK
if (VV_NEW_TYPE)
var/many = alert(src, "Create only one [value["type"]] and assign each or a new one for each thing", "How Many", "One", "Many", "Cancel")
if (many == "Cancel")
return
if (many == "Many")
many = TRUE
else
many = FALSE
var/type = value["type"]
to_chat(src, "Finding items...")
var/list/items = get_all_of_type(O.type, method)
to_chat(src, "Changing [items.len] items...")
for(var/thing in items)
if (!thing)
continue
var/datum/D = thing
if(many && !new_value)
new_value = new type()
if (D.vv_edit_var(variable, new_value) != FALSE)
accepted++
else
rejected++
new_value = null
CHECK_TICK
else
to_chat(src, "Finding items...")
var/list/items = get_all_of_type(O.type, method)
to_chat(src, "Changing [items.len] items...")
for(var/thing in items)
if (!thing)
continue
var/datum/D = thing
if (D.vv_edit_var(variable, new_value) != FALSE)
accepted++
else
rejected++
CHECK_TICK
var/count = rejected+accepted
if (!count)
to_chat(src, "No objects found")
return
if (!accepted)
to_chat(src, "Every object rejected your edit")
return
if (rejected)
to_chat(src, "[rejected] out of [count] objects rejected your edit")
log_world("### MassVarEdit by [src]: [O.type] (A/R [accepted]/[rejected]) [variable]=[html_encode("[O.vars[variable]]")]([list2params(value)])")
log_admin("[key_name(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)")
message_admins("[key_name_admin(src)] mass modified [original_name]'s [variable] to [O.vars[variable]] ([accepted] objects modified)")
/proc/get_all_of_type(var/T, subtypes = TRUE)
var/list/typecache = list()
typecache[T] = 1
if (subtypes)
typecache = typecacheof(typecache)
. = list()
if (ispath(T, /mob))
for(var/mob/thing in 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

View File

@@ -0,0 +1,379 @@
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
if (assoc)
variable = L[assoc_key]
else
variable = L[index]
default = vv_get_class(objectvar, variable)
to_chat(src, "Variable appears to be <b>[uppertext(default)]</b>.")
to_chat(src, "Variable contains: [variable]")
if(default == VV_NUM)
var/dir_text = ""
var/tdir = variable
if(tdir > 0 && tdir < 16)
if(tdir & 1)
dir_text += "NORTH"
if(tdir & 2)
dir_text += "SOUTH"
if(tdir & 4)
dir_text += "EAST"
if(tdir & 8)
dir_text += "WEST"
if(dir_text)
to_chat(usr, "If a direction, direction is: [dir_text]")
var/original_var = variable
if (O)
L = L.Copy()
var/class
if(autodetect_class)
if (default == VV_TEXT)
default = VV_MESSAGE
class = default
var/list/LL = vv_get_value(default_class = default, current_value = original_var, restricted_classes = list(VV_RESTORE_DEFAULT), extra_classes = list(VV_LIST, "DELETE FROM LIST"))
class = LL["class"]
if (!class)
return
var/new_var = LL["value"]
if(class == VV_MESSAGE)
class = VV_TEXT
switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet.
if(VV_LIST)
mod_list(variable, O, original_name, objectvar)
if("DELETE FROM LIST")
L.Cut(index, index+1)
if (O)
if (O.vv_edit_var(objectvar, L))
to_chat(src, "Your edit was rejected by the object.")
return
log_world("### ListVarEdit by [src]: [O.type] [objectvar]: REMOVED=[html_encode("[original_var]")]")
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]")
message_admins("[key_name_admin(src)] modified [original_name]'s [objectvar]: REMOVED=[original_var]")
return
if(VV_TEXT)
var/list/varsvars = vv_parse_text(O, new_var)
for(var/V in varsvars)
new_var = replacetext(new_var,"\[[V]]","[O.vars[V]]")
if(assoc)
L[assoc_key] = new_var
else
L[index] = new_var
if (O)
if (O.vv_edit_var(objectvar, L) == FALSE)
to_chat(src, "Your edit was rejected by the object.")
return
log_world("### ListVarEdit by [src]: [(O ? O.type : "/list")] [objectvar]: [original_var]=[new_var]")
log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]")
message_admins("[key_name_admin(src)] modified [original_name]'s varlist [objectvar]: [original_var]=[new_var]")
/proc/vv_varname_lockcheck(param_var_name)
if(param_var_name in GLOB.VVlocked)
if(!check_rights(R_DEBUG))
return FALSE
if(param_var_name in GLOB.VVckey_edit)
if(!check_rights(R_SPAWN|R_DEBUG))
return FALSE
if(param_var_name in GLOB.VVicon_edit_lock)
if(!check_rights(R_FUN|R_DEBUG))
return FALSE
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 <b>[uppertext(default)]</b>.")
to_chat(src, "Variable contains: [var_value]")
if(default == VV_NUM)
var/dir_text = ""
if(var_value > 0 && var_value < 16)
if(var_value & 1)
dir_text += "NORTH"
if(var_value & 2)
dir_text += "SOUTH"
if(var_value & 4)
dir_text += "EAST"
if(var_value & 8)
dir_text += "WEST"
if(dir_text)
to_chat(src, "If a direction, direction is: [dir_text]")
if(autodetect_class && default != VV_NULL)
if (default == VV_TEXT)
default = VV_MESSAGE
class = default
var/list/value = vv_get_value(class, default, var_value, extra_classes = list(VV_LIST), var_name = variable)
class = value["class"]
if (!class)
return
var/var_new = value["value"]
if(class == VV_MESSAGE)
class = VV_TEXT
var/original_name = "[O]"
switch(class)
if(VV_LIST)
if(!islist(var_value))
mod_list(list(), O, original_name, variable)
mod_list(var_value, O, original_name, variable)
return
if(VV_RESTORE_DEFAULT)
var_new = initial(O.vars[variable])
if(VV_TEXT)
var/list/varsvars = vv_parse_text(O, var_new)
for(var/V in varsvars)
var_new = replacetext(var_new,"\[[V]]","[O.vars[V]]")
if (O.vv_edit_var(variable, var_new) == FALSE)
to_chat(src, "Your edit was rejected by the object.")
return
vv_update_display(O, "varedited", VV_MSG_EDITED)
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

View File

@@ -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("<span class='notice'>[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted)</span>")
log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ")
message_admins("<span class='notice'>[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) </span>")
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("<span class='notice'>[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted)</span>")
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("<span class='notice'>[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) </span>")
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("<span class='notice'>[key_name(usr)] dealt [amount] amount of [Text] damage to [L]</span>")
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, "<span class='warning'>The object you tried to expose to [C] no longer exists (GC'd)</span>")
return
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;datumrefresh=\ref[thing]'>VV window</a>")
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [src]")
to_chat(C, "[holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window")
C.debug_variables(thing)
if(href_list["datumrefresh"])
var/datum/DAT = locate(href_list["datumrefresh"])
if(istype(DAT, /datum) || istype(DAT, /client))
debug_variables(DAT)
return

View File

@@ -1,183 +1,337 @@
// 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, "<span class='danger'>You need to be an administrator to access this.</span>")
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]", "/", "<wbr>/")
var/sprite_text
if(sprite)
sprite_text = "<img src='vv[hash].png'></td><td>"
var/list/header = islist(D)? "<b>/list</b>" : 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 += "<option value='[link]'>[name]</option>"
else
dropdownoptions_html += "<option value>[name]</option>"
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 = {"
<html>
<head>
<script src='view_variables.js'></script>
<title>[D] (\ref[D] - [D.type])</title>
<style>
body { font-family: Verdana, sans-serif; font-size: 9pt; }
.value { font-family: "Courier New", monospace; font-size: 8pt; }
</style>
</head>
<body onload='selectTextField(); updateSearch()'; onkeyup='updateSearch()'>
<div align='center'>
<table width='100%'><tr>
<html>
<head>
<title>[title]</title>
<style>
body {
font-family: Verdana, sans-serif;
font-size: 9pt;
}
.value {
font-family: "Courier New", monospace;
font-size: 8pt;
}
</style>
</head>
<body onload='selectTextField()' onkeydown='return handle_keydown()' onkeyup='handle_keyup()'>
<script type="text/javascript">
// onload
function selectTextField() {
var filter_text = document.getElementById('filter');
filter_text.focus();
filter_text.select();
var lastsearch = getCookie("[refid][cookieoffset]search");
if (lastsearch) {
filter_text.value = lastsearch;
updateSearch();
}
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca\[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
}
return "";
}
// main search functionality
var last_filter = "";
function updateSearch() {
var filter = document.getElementById('filter').value.toLowerCase();
var vars_ol = document.getElementById("vars");
if (filter === last_filter) {
// An event triggered an update but nothing has changed.
return;
} else if (filter.indexOf(last_filter) === 0) {
// The new filter starts with the old filter, fast path by removing only.
var children = vars_ol.childNodes;
for (var i = children.length - 1; i >= 0; --i) {
try {
var li = children\[i];
if (li.innerText.toLowerCase().indexOf(filter) == -1) {
vars_ol.removeChild(li);
}
} catch(err) {}
}
} else {
// Remove everything and put back what matches.
while (vars_ol.hasChildNodes()) {
vars_ol.removeChild(vars_ol.lastChild);
}
for (var i = 0; i < complete_list.length; ++i) {
try {
var li = complete_list\[i];
if (!filter || li.innerText.toLowerCase().indexOf(filter) != -1) {
vars_ol.appendChild(li);
}
} catch(err) {}
}
}
last_filter = filter;
document.cookie="[refid][cookieoffset]search="+encodeURIComponent(filter);
var lis_new = vars_ol.getElementsByTagName("li");
for (var j = 0; j < lis_new.length; ++j) {
lis_new\[j].style.backgroundColor = (j == 0) ? "#ffee88" : "white";
}
}
// onkeydown
function handle_keydown() {
if(event.keyCode == 116) { //F5 (to refresh properly)
document.getElementById("refresh_link").click();
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
return false;
}
return true;
}
// onkeyup
function handle_keyup() {
if (event.keyCode == 13) { //Enter / return
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for (var i = 0; i < lis.length; ++i) {
try {
var li = lis\[i];
if (li.style.backgroundColor == "#ffee88") {
alist = lis\[i].getElementsByTagName("a");
if(alist.length > 0) {
location.href=alist\[0].href;
}
}
} catch(err) {}
}
} else if(event.keyCode == 38){ //Up arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for (var i = 0; i < lis.length; ++i) {
try {
var li = lis\[i];
if (li.style.backgroundColor == "#ffee88") {
if (i > 0) {
var li_new = lis\[i-1];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
} catch(err) {}
}
} else if(event.keyCode == 40) { //Down arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for (var i = 0; i < lis.length; ++i) {
try {
var li = lis\[i];
if (li.style.backgroundColor == "#ffee88") {
if ((i+1) < lis.length) {
var li_new = lis\[i+1];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
} catch(err) {}
}
} else {
updateSearch();
}
}
// onchange
function handle_dropdown(list) {
var value = list.options\[list.selectedIndex].value;
if (value !== "") {
location.href = value;
}
list.selectedIndex = 0;
document.getElementById('filter').focus();
}
// byjax
function replace_span(what) {
var idx = what.indexOf(':');
document.getElementById(what.substr(0, idx)).innerHTML = what.substr(idx + 1);
}
</script>
<div align='center'>
<table width='100%'>
<tr>
<td width='50%'>
<table align='center' width='100%'><tr>
[sprite ? "<td><img src='view_vars_sprite.png'></td>" : ""]
<td><div align='center'>[D.get_view_variables_header()]</div></td>
</tr></table>
<table align='center' width='100%'>
<tr>
<td>
[sprite_text]
<div align='center'>
[header.Join()]
</div>
</td>
</tr>
</table>
<div align='center'>
<b><font size='1'>[replacetext("[D.type]", "/", "/<wbr>")]</font></b>
[holder.marked_datum == D ? "<br/><font size='1' color='red'><b>Marked Object</b></font>" : ""]
<b><font size='1'>[formatted_type]</font></b>
<span id='marked'>[marked]</span>
<span id='varedited'>[varedited_line]</span>
<span id='deleted'>[deleted_line]</span>
</div>
</td>
<td width='50%'>
<div align='center'>
<a href='?_src_=vars;datumrefresh=\ref[D]'>Refresh</a>
<a id='refresh_link' href='?_src_=vars;
datumrefresh=[refid]'>Refresh</a>
<form>
<select name='file'
size='1'
onchange='loadPage(this.form.elements\[0\])'
target='_parent._top'
onmouseclick='this.focus()'
style='background-color:#ffffff'>
<option>Select option</option>
<option />
<option value='?_src_=vars;mark_object=\ref[D]'>Mark Object</option>
<option value='?_src_=vars;call_proc=\ref[D]'>Call Proc</option>
[D.get_view_variables_options()]
<select name="file" size="1"
onchange="handle_dropdown(this)"
onmouseclick="this.focus()"
style="background-color:#ffffff">
<option value selected>Select option</option>
[dropdownoptions_html.Join()]
</select>
</form>
</div>
</td>
</tr></table>
</div>
<hr/>
<font size='1'>
<b>E</b> - Edit, tries to determine the variable type by itself.<br/>
<b>C</b> - Change, asks you for the var type first.<br/>
<b>M</b> - Mass modify: changes this variable for all objects of this type.<br/>
</font>
<hr/>
<table width='100%'><tr>
</tr>
</table>
</div>
<hr>
<font size='1'>
<b>E</b> - Edit, tries to determine the variable type by itself.<br>
<b>C</b> - Change, asks you for the var type first.<br>
<b>M</b> - Mass modify: changes this variable for all objects of this type.<br>
</font>
<hr>
<table width='100%'>
<tr>
<td width='20%'>
<div align='center'>
<b>Search:</b>
</div>
</td>
<td width='80%'>
<input type='text'
id='filter'
name='filter_text'
value=''
style='width:100%;' />
<input type='text' id='filter' name='filter_text' value='' style='width:100%;'>
</td>
</tr></table>
<hr/>
<ol id='vars'>
[make_view_variables_var_list(D)]
</ol>
</body>
</html>
"}
</tr>
</table>
<hr>
<ol id='vars'>
[variable_html.Join()]
</ol>
<script type='text/javascript'>
var complete_list = \[\];
var lis = document.getElementById("vars").children;
for(var i = lis.length; i--;) complete_list\[i\] = lis\[i\];
</script>
</body>
</html>
"}
src << browse(html, "window=variables[refid];size=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 = {"
(<a href='?_src_=vars;datumedit=\ref[D];varnameedit=[varname]'>E</a>)
(<a href='?_src_=vars;datumchange=\ref[D];varnamechange=[varname]'>C</a>)
(<a href='?_src_=vars;datummass=\ref[D];varnamemass=[varname]'>M</a>)
"}
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 = "<a href='?_src_=vars;Vars=\ref[DA]'>\ref[DA]</a> - [DA.type]"
else
vtext = "<a href='?_src_=vars;Vars=\ref[DA]'>\ref[DA]</a> - [DA] ([DA.type])"
else if(istype(value, /client))
var/client/C = value
vtext = "<a href='?_src_=vars;Vars=\ref[C]'>\ref[C]</a> - [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 = "<ul>"
var/index = 1
for (var/entry in L)
if(istext(entry))
extra += make_view_variables_var_entry(null, entry, L[entry], level+1)
else
extra += make_view_variables_var_entry(null, index, L[index], level+1)
index++
extra += "</ul>"
else
vtext = "[value]"
return "<li>[ecm][varname] = <span class='value'>[vtext]</span>[extra]</li>"
//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")

View File

@@ -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 ..()

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)
staleness = round( CLAMP(staleness + amt, -50, 200), 0.1)

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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()

View File

@@ -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)

View File

@@ -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]

View File

@@ -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

View File

@@ -227,7 +227,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)
@@ -486,7 +486,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

View File

@@ -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("<span class='danger'>[user] [pick(attack_verb)] [T.himself] in the [affecting.name]!</span>")

View File

@@ -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("<span class='danger'>[user] [pick(attack_verb)] [TU.himself] in the [organ]!</span>")
@@ -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("<span class='danger'>[user] threw [target] a glancing [pick(attack_noun)] to the [organ]!</span>") //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("<span class='danger'>[pick("[user] stomped on", "[user] slammed [TU.his] [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!</span>")

View File

@@ -1330,7 +1330,26 @@ default behaviour is:
/mob/living/proc/dirties_floor() // If we ever decide to add fancy conditionals for making dirty floors (floating, etc), here's the proc.
<<<<<<< HEAD
return makes_dirt
=======
return makes_dirt
/mob/living/proc/needs_to_breathe()
return !isSynthetic()
return !isSynthetic()
/mob/living/vv_get_header()
. = ..()
. += {"
<a href='?_src_=vars;rename=\ref[src]'><b>[src]</b></a><font size='1'>
<br><a href='?_src_=vars;datumedit=\ref[src];varnameedit=ckey'>[ckey ? ckey : "No ckey"]</a> / <a href='?_src_=vars;datumedit=\ref[src];varnameedit=real_name'>[real_name ? real_name : "No real name"]</a>
<br>
BRUTE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=brute'>[getBruteLoss()]</a>
FIRE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=fire'>[getFireLoss()]</a>
TOXIN:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=toxin'>[getToxLoss()]</a>
OXY:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=oxygen'>[getOxyLoss()]</a>
CLONE:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=clone'>[getCloneLoss()]</a>
BRAIN:<a href='?_src_=vars;mobToDamage=\ref[src];adjustDamage=brain'>[getBrainLoss()]</a>
</font>
"}
>>>>>>> b1860f9... Merge pull request #5829 from kevinz000/tg_vv

View File

@@ -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)

View File

@@ -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 ""

View File

@@ -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()

View File

@@ -61,7 +61,7 @@
target << "<span class='danger'>You feel extreme pain!</span>"
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))

View File

@@ -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"])

View File

@@ -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()

View File

@@ -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)

View File

@@ -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"])

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -73,7 +73,7 @@
if(!new_val)
to_chat(usr, "<span class='warning'>That's not a valid number.</span>")
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, "<span class='warning'>That's not a valid number.</span>")
return 1
G.rate = Clamp(new_val, 1, 10)
G.rate = CLAMP(new_val, 1, 10)
updateUsrDialog()
return 1

View File

@@ -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,10 @@
closest_grounding_rod.tesla_act(power, explosive, stun_mobs)
else if(closest_mob)
<<<<<<< HEAD
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)]!")

View File

@@ -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

View File

@@ -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()

View File

@@ -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]"

View File

@@ -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)

View File

@@ -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++

View File

@@ -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"
@@ -1423,8 +1426,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"
@@ -1435,10 +1436,19 @@
#include "code\modules\admin\verbs\striketeam.dm"
#include "code\modules\admin\verbs\ticklag.dm"
#include "code\modules\admin\verbs\tripAI.dm"
<<<<<<< HEAD:vorestation.dme
#include "code\modules\admin\view_variables\helpers.dm"
=======
#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"
>>>>>>> b1860f9... Merge pull request #5829 from kevinz000/tg_vv:polaris.dme
#include "code\modules\admin\view_variables\topic.dm"
#include "code\modules\admin\view_variables\view_variables.dm"
#include "code\modules\ai\_defines.dm"