diff --git a/code/__defines/MC.dm b/code/__defines/MC.dm
index 26839228206..6acc667f2d9 100644
--- a/code/__defines/MC.dm
+++ b/code/__defines/MC.dm
@@ -19,8 +19,8 @@
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
-#define START_PROCESSING(Processor, Datum) if (!Datum.is_processing) {Datum.is_processing = TRUE;Processor.processing += Datum}
-#define STOP_PROCESSING(Processor, Datum) Datum.is_processing = FALSE;Processor.processing -= Datum
+#define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum}
+#define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum
//! SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier)
diff --git a/code/__defines/_tick.dm b/code/__defines/_tick.dm
index 5ba0eafd0e3..8e3edc066ed 100644
--- a/code/__defines/_tick.dm
+++ b/code/__defines/_tick.dm
@@ -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 )
\ No newline at end of file
+#define CHECK_TICK_HIGH_PRIORITY ( TICK_CHECK_HIGH_PRIORITY? stoplag() : 0 )
+
+#define UNTIL(X) while(!(X)) stoplag()
diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm
index 27b1afcc1c5..b9417d2a866 100644
--- a/code/__defines/flags.dm
+++ b/code/__defines/flags.dm
@@ -1,6 +1,5 @@
-/*
- These defines are specific to the atom/flags_1 bitmask
-*/
+//MARK ALL FLAG CHANGES IN _globals/bitfields.dm!
+//All flags should go in here if possible.
#define ALL (~0) //For convenience.
#define NONE 0
@@ -17,3 +16,4 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
// datum_flags
#define DF_VAR_EDITED (1<<0)
#define DF_ISPROCESSING (1<<1)
+
diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm
new file mode 100644
index 00000000000..ed4a0dd10f7
--- /dev/null
+++ b/code/__defines/is_helpers.dm
@@ -0,0 +1,53 @@
+
+#define isdatum(D) istype(D, /datum)
+#define isweakref(A) istype(A, /weakref)
+
+#define islist(D) istype(D, /list)
+
+//---------------
+#define isatom(D) istype(D, /atom)
+
+//---------------
+//#define isobj(D) istype(D, /obj) //Built in
+
+#define isitem(D) istype(D, /obj/item)
+
+#define isairlock(A) istype(A, /obj/machinery/door/airlock)
+
+#define isorgan(A) istype(A, /obj/item/organ/external)
+
+//---------------
+//#define isarea(D) istype(D, /area) //Built in
+
+//---------------
+//#define ismob(D) istype(D, /mob) //Built in
+#define isliving(A) istype(A, /mob/living)
+
+#define isobserver(A) istype(A, /mob/observer/dead)
+#define isEye(A) istype(A, /mob/observer/eye)
+
+#define isnewplayer(A) istype(A, /mob/new_player)
+
+#define isanimal(A) istype(A, /mob/living/simple_mob)
+#define ismouse(A) istype(A, /mob/living/simple_mob/animal/passive/mouse)
+#define iscorgi(A) istype(A, /mob/living/simple_mob/animal/passive/dog/corgi)
+#define isslime(A) istype(A, /mob/living/simple_mob/slime)
+#define isxeno(A) istype(A, /mob/living/simple_mob/animal/space/alien)
+
+#define iscarbon(A) istype(A, /mob/living/carbon)
+#define isalien(A) istype(A, /mob/living/carbon/alien)
+#define isbrain(A) istype(A, /mob/living/carbon/brain)
+#define ishuman(A) istype(A, /mob/living/carbon/human)
+
+#define issilicon(A) istype(A, /mob/living/silicon)
+#define isAI(A) istype(A, /mob/living/silicon/ai)
+#define isrobot(A) istype(A, /mob/living/silicon/robot)
+#define ispAI(A) istype(A, /mob/living/silicon/pai)
+
+#define isbot(A) istype(A, /mob/living/bot)
+
+#define isvoice(A) istype(A, /mob/living/voice)
+
+//---------------
+//#define isturf(D) istype(D, /turf) //Built in
+#define isopenspace(A) istype(A, /turf/simulated/open)
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index d77b5cf2975..95d4929acb1 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -106,26 +106,15 @@ var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret
#define ATMOS_DEFAULT_VOLUME_MIXER 200 // L.
#define ATMOS_DEFAULT_VOLUME_PIPE 70 // L.
+//wIP - PORT ALL OF THESE TO SUBSYSTEMS AND GET RID OF THE WHOLE LIST PROCESS THING
// Fancy-pants START/STOP_PROCESSING() macros that lets us custom define what the list is.
#define START_PROCESSING_IN_LIST(DATUM, LIST) \
-if (DATUM.is_processing) {\
- if(DATUM.is_processing != #LIST)\
- {\
- crash_with("Failed to start processing. [log_info_line(DATUM)] is already being processed by [DATUM.is_processing] but queue attempt occured on [#LIST]."); \
- }\
-} else {\
- DATUM.is_processing = #LIST;\
+if (!(DATUM.datum_flags & DF_ISPROCESSING)) {\
LIST += DATUM;\
+ DATUM.datum_flags |= DF_ISPROCESSING\
}
-#define STOP_PROCESSING_IN_LIST(DATUM, LIST) \
-if(DATUM.is_processing) {\
- if(LIST.Remove(DATUM)) {\
- DATUM.is_processing = null;\
- } else {\
- crash_with("Failed to stop processing. [log_info_line(DATUM)] is being processed by [is_processing] and not found in SSmachines.[#LIST]"); \
- }\
-}
+#define STOP_PROCESSING_IN_LIST(DATUM, LIST) LIST.Remove(DATUM);DATUM.datum_flags &= ~DF_ISPROCESSING
// Note - I would prefer these be defined machines.dm, but some are used prior in file order. ~Leshana
#define START_MACHINE_PROCESSING(Datum) START_PROCESSING_IN_LIST(Datum, global.processing_machines)
diff --git a/code/__defines/vv.dm b/code/__defines/vv.dm
new file mode 100644
index 00000000000..b7b54b0b57c
--- /dev/null
+++ b/code/__defines/vv.dm
@@ -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 "
Marked Object"
+#define VV_MSG_EDITED "
Var Edited"
+#define VV_MSG_DELETED "
Deleted"
+
+#define VV_NORMAL_LIST_NO_EXPAND_THRESHOLD 50
+#define VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD 150
+
+//Helpers for vv_get_dropdown()
+#define VV_DROPDOWN_OPTION(href_key, name) . += ""
+
+//Helpers for vv_do_topic(list/href_list)
+#define IF_VV_OPTION(href_key) if(href_list[href_key])
+
+// /datum
+#define VV_HK_DELETE "delete"
+#define VV_HK_EXPOSE "expose"
+#define VV_HK_CALLPROC "proc_call"
+#define VV_HK_MARK "mark"
+
+// /atom
+#define VV_HK_ATOM_EXPLODE "turf_explode"
+#define VV_HK_ATOM_EMP "turf_emp"
diff --git a/code/_global_vars/bitfields.dm b/code/_global_vars/bitfields.dm
new file mode 100644
index 00000000000..891c50ce88b
--- /dev/null
+++ b/code/_global_vars/bitfields.dm
@@ -0,0 +1,7 @@
+GLOBAL_LIST_INIT(bitfields, list(
+ "datum_flags" = list(
+ "DF_VAR_EDITED" = DF_VAR_EDITED,
+ "DF_ISPROCESSING" = DF_ISPROCESSING
+ )
+
+))
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index a1e7c8ea590..b29fa91b8b9 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -904,9 +904,9 @@ proc/adjust_brightness(var/color, var/value)
if (!value) return color
var/list/RGB = ReadRGB(color)
- RGB[1] = Clamp(RGB[1]+value,0,255)
- RGB[2] = Clamp(RGB[2]+value,0,255)
- RGB[3] = Clamp(RGB[3]+value,0,255)
+ RGB[1] = CLAMP(RGB[1]+value,0,255)
+ RGB[2] = CLAMP(RGB[2]+value,0,255)
+ RGB[3] = CLAMP(RGB[3]+value,0,255)
return rgb(RGB[1],RGB[2],RGB[3])
proc/sort_atoms_by_layer(var/list/atoms)
diff --git a/code/_helpers/lists.dm b/code/_helpers/lists.dm
index 855aa9c1386..b50db3457c7 100644
--- a/code/_helpers/lists.dm
+++ b/code/_helpers/lists.dm
@@ -27,9 +27,6 @@ proc/listgetindex(var/list/list,index)
return list[index]
return
-proc/islist(list/list)
- return(istype(list))
-
//Return either pick(list) or null if list is not of type /list or is empty
proc/safepick(list/list)
if(!islist(list) || !list.len)
@@ -753,3 +750,9 @@ proc/dd_sortedTextList(list/incoming)
for(var/i = 1 to l.len)
if(islist(.[i]))
.[i] = .(.[i])
+
+//Return a list with no duplicate entries
+/proc/uniqueList(list/L)
+ . = list()
+ for(var/i in L)
+ . |= i
diff --git a/code/_helpers/matrices.dm b/code/_helpers/matrices.dm
index 2e7247543cb..a5ef701c2df 100644
--- a/code/_helpers/matrices.dm
+++ b/code/_helpers/matrices.dm
@@ -50,7 +50,7 @@
/proc/color_rotation(angle)
if(angle == 0)
return color_identity()
- angle = Clamp(angle, -180, 180)
+ angle = CLAMP(angle, -180, 180)
var/cos = cos(angle)
var/sin = sin(angle)
@@ -65,7 +65,7 @@
//Makes everything brighter or darker without regard to existing color or brightness
/proc/color_brightness(power)
- power = Clamp(power, -255, 255)
+ power = CLAMP(power, -255, 255)
power = power/255
return list(1,0,0, 0,1,0, 0,0,1, power,power,power)
@@ -85,7 +85,7 @@
//Exxagerates or removes brightness
/proc/color_contrast(value)
- value = Clamp(value, -100, 100)
+ value = CLAMP(value, -100, 100)
if(value == 0)
return color_identity()
@@ -108,7 +108,7 @@
/proc/color_saturation(value as num)
if(value == 0)
return color_identity()
- value = Clamp(value, -100, 100)
+ value = CLAMP(value, -100, 100)
if(value > 0)
value *= 3
var/x = 1 + value / 100
diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm
index 0316e1d1865..55dad2242f3 100644
--- a/code/_helpers/type2type.dm
+++ b/code/_helpers/type2type.dm
@@ -242,3 +242,34 @@
/proc/isLeap(y)
return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
+
+//Takes a string and a datum
+//The string is well, obviously the string being checked
+//The datum is used as a source for var names, to check validity
+//Otherwise every single word could technically be a variable!
+/proc/string2listofvars(var/t_string, var/datum/var_source)
+ if(!t_string || !var_source)
+ return list()
+
+ . = list()
+
+ var/var_found = findtext(t_string,"\[") //Not the actual variables, just a generic "should we even bother" check
+ if(var_found)
+ //Find var names
+
+ // "A dog said hi [name]!"
+ // splittext() --> list("A dog said hi ","name]!"
+ // jointext() --> "A dog said hi name]!"
+ // splittext() --> list("A","dog","said","hi","name]!")
+
+ t_string = replacetext(t_string,"\[","\[ ")//Necessary to resolve "word[var_name]" scenarios
+ var/list/list_value = splittext(t_string,"\[")
+ var/intermediate_stage = jointext(list_value, null)
+
+ list_value = splittext(intermediate_stage," ")
+ for(var/value in list_value)
+ if(findtext(value,"]"))
+ value = splittext(value,"]") //"name]!" --> list("name","!")
+ for(var/A in value)
+ if(var_source.vars.Find(A))
+ . += A
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index 8bd5a5055c7..31d74dbf082 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -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
diff --git a/code/_macros.dm b/code/_macros.dm
index e6c6e10636d..a4b19b79c2c 100644
--- a/code/_macros.dm
+++ b/code/_macros.dm
@@ -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) ("[text]")
#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
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index fa7b917194d..56a9244347b 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -38,8 +38,10 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
stat("Globals:", statclick.update("Edit"))
-/datum/controller/global_vars/VV_hidden()
- return ..() + gvars_datum_protected_varlist
+/datum/controller/global_vars/vv_edit_var(var_name, var_value)
+ if(gvars_datum_protected_varlist[var_name])
+ return FALSE
+ return ..()
/datum/controller/global_vars/Initialize(var/exclude_these)
gvars_datum_init_order = list()
diff --git a/code/controllers/subsystems/machines.dm b/code/controllers/subsystems/machines.dm
index 4cba70a9814..45251753936 100644
--- a/code/controllers/subsystems/machines.dm
+++ b/code/controllers/subsystems/machines.dm
@@ -109,7 +109,7 @@ SUBSYSTEM_DEF(machines)
else
global.pipe_networks.Remove(PN)
if(!QDELETED(PN))
- PN.is_processing = null
+ DISABLE_BITFIELD(PN.datum_flags, DF_ISPROCESSING)
if(MC_TICK_CHECK)
return
@@ -127,7 +127,7 @@ SUBSYSTEM_DEF(machines)
else
global.processing_machines.Remove(M)
if(!QDELETED(M))
- M.is_processing = null
+ DISABLE_BITFIELD(M.datum_flags, DF_ISPROCESSING)
if(MC_TICK_CHECK)
return
@@ -144,7 +144,7 @@ SUBSYSTEM_DEF(machines)
else
global.powernets.Remove(PN)
if(!QDELETED(PN))
- PN.is_processing = null
+ DISABLE_BITFIELD(PN.datum_flags, DF_ISPROCESSING)
if(MC_TICK_CHECK)
return
@@ -160,7 +160,7 @@ SUBSYSTEM_DEF(machines)
current_run.len--
if(!I.pwr_drain(wait)) // 0 = Process Kill, remove from processing list.
global.processing_power_items.Remove(I)
- I.is_processing = null
+ DISABLE_BITFIELD(I.datum_flags, DF_ISPROCESSING)
if(MC_TICK_CHECK)
return
diff --git a/code/datums/browser.dm b/code/datums/browser.dm
index 577698532e2..ea2f4feec25 100644
--- a/code/datums/browser.dm
+++ b/code/datums/browser.dm
@@ -105,6 +105,10 @@
"}
/datum/browser/proc/open(var/use_onclose = 1)
+ if(isnull(window_id)) //null check because this can potentially nuke goonchat
+ WARNING("Browser [title] tried to open with a null ID")
+ to_chat(user, "The [title] browser you tried to open failed a sanity check! Please report this on github!")
+ return
var/window_size = ""
if (width && height)
window_size = "size=[width]x[height];"
@@ -112,9 +116,6 @@
if (use_onclose)
onclose(user, window_id, ref)
-/datum/browser/proc/close()
- user << browse(null, "window=[window_id]")
-
// This will allow you to show an icon in the browse window
// This is added to mob so that it can be used without a reference to the browser object
// There is probably a better place for this...
@@ -157,12 +158,12 @@
//world << "OnClose [user]: [windowid] : ["on-close=\".windowclose [param]\""]"
-
// the on-close client verb
// called when a browser popup window is closed after registering with proc/onclose()
// if a valid atom reference is supplied, call the atom's Topic() with "close=1"
// otherwise, just reset the client mob's machine var.
//
+
/client/verb/windowclose(var/atomref as text)
set hidden = 1 // hide this verb from the user's panel
set name = ".windowclose" // no autocomplete on cmd line
@@ -182,3 +183,198 @@
//world << "[src] was [src.mob.machine], setting to null"
src.mob.unset_machine()
return
+
+/datum/browser/proc/close()
+ if(!isnull(window_id))//null check because this can potentially nuke goonchat
+ user << browse(null, "window=[window_id]")
+ else
+ WARNING("Browser [title] tried to close with a null ID")
+
+/datum/browser/modal/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000)
+ if (!User)
+ return
+
+ var/output = {"