diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm
index c683f55c59..49ff1c8d49 100644
--- a/code/controllers/configuration/config_entry.dm
+++ b/code/controllers/configuration/config_entry.dm
@@ -1,6 +1,9 @@
-#define LIST_MODE_NUM 0
-#define LIST_MODE_TEXT 1
-#define LIST_MODE_FLAG 2
+#define VALUE_MODE_NUM 0
+#define VALUE_MODE_TEXT 1
+#define VALUE_MODE_FLAG 2
+
+#define KEY_MODE_TEXT 0
+#define KEY_MODE_TYPE 1
/datum/config_entry
var/name //read-only, this is determined by the last portion of the derived entry type
@@ -15,6 +18,8 @@
var/protection = NONE
var/abstract_type = /datum/config_entry //do not instantiate if type matches this
+ var/vv_VAS = TRUE //Force validate and set on VV. VAS proccall guard will run regardless.
+
var/dupes_allowed = FALSE
/datum/config_entry/New()
@@ -37,20 +42,23 @@
. &= !(protection & CONFIG_ENTRY_HIDDEN)
/datum/config_entry/vv_edit_var(var_name, var_value)
- var/static/list/banned_edits = list(NAMEOF(src, name), NAMEOF(src, default), NAMEOF(src, resident_file), NAMEOF(src, protection), NAMEOF(src, abstract_type), NAMEOF(src, modified), NAMEOF(src, dupes_allowed))
+ var/static/list/banned_edits = list(NAMEOF(src, name), NAMEOF(src, vv_VAS), NAMEOF(src, default), NAMEOF(src, resident_file), NAMEOF(src, protection), NAMEOF(src, abstract_type), NAMEOF(src, modified), NAMEOF(src, dupes_allowed))
if(var_name == NAMEOF(src, config_entry_value))
if(protection & CONFIG_ENTRY_LOCKED)
return FALSE
- . = ValidateAndSet("[var_value]")
- if(.)
- datum_flags |= DF_VAR_EDITED
- return
+ if(vv_VAS)
+ . = ValidateAndSet("[var_value]")
+ if(.)
+ datum_flags |= DF_VAR_EDITED
+ return
+ else
+ return ..()
if(var_name in banned_edits)
return FALSE
return ..()
/datum/config_entry/proc/VASProcCallGuard(str_val)
- . = !(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "ValidateAndSet" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
+ . = !((protection & CONFIG_ENTRY_LOCKED) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "ValidateAndSet" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
if(!.)
log_admin_private("Config set of [type] to [str_val] attempted by [key_name(usr)]")
@@ -58,32 +66,6 @@
VASProcCallGuard(str_val)
CRASH("Invalid config entry type!")
-/datum/config_entry/proc/ValidateKeyedList(str_val, list_mode, splitter)
- str_val = trim(str_val)
- var/key_pos = findtext(str_val, splitter)
- var/key_name = null
- var/key_value = null
-
- if(key_pos || list_mode == LIST_MODE_FLAG)
- key_name = lowertext(copytext(str_val, 1, key_pos))
- key_value = copytext(str_val, key_pos + 1)
- var/temp
- var/continue_check
- switch(list_mode)
- if(LIST_MODE_FLAG)
- temp = TRUE
- continue_check = TRUE
- if(LIST_MODE_NUM)
- temp = text2num(key_value)
- continue_check = !isnull(temp)
- if(LIST_MODE_TEXT)
- temp = key_value
- continue_check = temp
- if(continue_check && ValidateListEntry(key_name, temp))
- config_entry_value[key_name] = temp
- return TRUE
- return FALSE
-
/datum/config_entry/proc/ValidateListEntry(key_name, key_value)
return TRUE
@@ -156,44 +138,59 @@
config_entry_value = new_list
return TRUE
-/datum/config_entry/keyed_flag_list
- abstract_type = /datum/config_entry/keyed_flag_list
- config_entry_value = list()
- dupes_allowed = TRUE
-
-/datum/config_entry/keyed_flag_list/ValidateAndSet(str_val)
- if(!VASProcCallGuard(str_val))
- return FALSE
- return ValidateKeyedList(str_val, LIST_MODE_FLAG, " ")
-
-/datum/config_entry/keyed_number_list
- abstract_type = /datum/config_entry/keyed_number_list
+/datum/config_entry/keyed_list
+ abstract_type = /datum/config_entry/keyed_list
config_entry_value = list()
dupes_allowed = TRUE
+ vv_VAS = FALSE //VAS will not allow things like deleting from lists, it'll just bug horribly.
+ var/key_mode
+ var/value_mode
var/splitter = " "
-/datum/config_entry/keyed_number_list/vv_edit_var(var_name, var_value)
- return var_name != "splitter" && ..()
+/datum/config_entry/keyed_list/New()
+ . = ..()
+ if(isnull(key_mode) || isnull(value_mode))
+ CRASH("Keyed list of type [type] created with null key or value mode!")
-/datum/config_entry/keyed_number_list/ValidateAndSet(str_val)
+/datum/config_entry/keyed_list/ValidateAndSet(str_val)
if(!VASProcCallGuard(str_val))
return FALSE
- return ValidateKeyedList(str_val, LIST_MODE_NUM, splitter)
-/datum/config_entry/keyed_string_list
- abstract_type = /datum/config_entry/keyed_string_list
- config_entry_value = list()
- dupes_allowed = TRUE
- var/splitter = " "
+ str_val = trim(str_val)
+ var/key_pos = findtext(str_val, splitter)
+ var/key_name = null
+ var/key_value = null
-/datum/config_entry/keyed_string_list/vv_edit_var(var_name, var_value)
+ if(key_pos || value_mode == VALUE_MODE_FLAG)
+ key_name = lowertext(copytext(str_val, 1, key_pos))
+ key_value = copytext(str_val, key_pos + 1)
+ var/new_key
+ var/new_value
+ var/continue_check_value
+ var/continue_check_key
+ switch(key_mode)
+ if(KEY_MODE_TEXT)
+ new_key = key_name
+ continue_check_key = new_key
+ if(KEY_MODE_TYPE)
+ new_key = key_name
+ if(!ispath(new_key))
+ new_key = text2path(new_key)
+ continue_check_key = ispath(new_key)
+ switch(value_mode)
+ if(VALUE_MODE_FLAG)
+ new_value = TRUE
+ continue_check_value = TRUE
+ if(VALUE_MODE_NUM)
+ new_value = text2num(key_value)
+ continue_check_value = !isnull(new_value)
+ if(VALUE_MODE_TEXT)
+ new_value = key_value
+ continue_check_value = new_value
+ if(continue_check_value && continue_check_key && ValidateListEntry(new_key, new_value))
+ config_entry_value[new_key] = new_value
+ return TRUE
+ return FALSE
+
+/datum/config_entry/keyed_list/vv_edit_var(var_name, var_value)
return var_name != "splitter" && ..()
-
-/datum/config_entry/keyed_string_list/ValidateAndSet(str_val)
- if(!VASProcCallGuard(str_val))
- return FALSE
- return ValidateKeyedList(str_val, LIST_MODE_TEXT, splitter)
-
-#undef LIST_MODE_NUM
-#undef LIST_MODE_TEXT
-#undef LIST_MODE_FLAG
diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm
index 5c22fc320f..0232081c1a 100644
--- a/code/controllers/configuration/configuration.dm
+++ b/code/controllers/configuration/configuration.dm
@@ -20,7 +20,19 @@
var/motd
-/datum/controller/configuration/proc/Load()
+/datum/controller/configuration/proc/admin_reload()
+ if(IsAdminAdvancedProcCall())
+ return
+ log_admin("[key_name_admin(usr)] has forcefully reloaded the configuration from disk.")
+ message_admins("[key_name_admin(usr)] has forcefully reloaded the configuration from disk.")
+ full_wipe()
+ Load(world.params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
+
+/datum/controller/configuration/proc/Load(_directory)
+ if(IsAdminAdvancedProcCall()) //If admin proccall is detected down the line it will horribly break everything.
+ return
+ if(_directory)
+ directory = _directory
if(entries)
CRASH("[THIS_PROC_TYPE_WEIRD] called more than once!")
InitEntries()
@@ -36,12 +48,18 @@
loadmaplist(CONFIG_MAPS_FILE)
LoadMOTD()
-/datum/controller/configuration/Destroy()
+/datum/controller/configuration/proc/full_wipe()
+ if(IsAdminAdvancedProcCall())
+ return
entries_by_type.Cut()
QDEL_LIST_ASSOC_VAL(entries)
+ entries = null
QDEL_LIST_ASSOC_VAL(maplist)
+ maplist = null
QDEL_NULL(defaultmap)
+/datum/controller/configuration/Destroy()
+ full_wipe()
config = null
return ..()
@@ -84,9 +102,10 @@
var/list/lines = world.file2list("[directory]/[filename]")
var/list/_entries = entries
for(var/L in lines)
+ L = trim(L)
if(!L)
continue
-
+
var/firstchar = copytext(L, 1, 2)
if(firstchar == "#")
continue
@@ -107,7 +126,7 @@
if(!entry)
continue
-
+
if(entry == "$include")
if(!value)
log_config("Warning: Invalid $include directive: [value]")
@@ -115,7 +134,7 @@
LoadEntries(value, stack)
++.
continue
-
+
var/datum/config_entry/E = _entries[entry]
if(!E)
log_config("Unknown setting in configuration: '[entry]'")
@@ -137,19 +156,19 @@
E = new_ver
else
warning("[new_ver.type] is deprecated but gave no proper return for DeprecationUpdate()")
-
+
var/validated = E.ValidateAndSet(value)
if(!validated)
log_config("Failed to validate setting \"[value]\" for [entry]")
- else
+ else
if(E.modified && !E.dupes_allowed)
log_config("Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.")
E.resident_file = filename
-
+
if(validated)
E.modified = TRUE
-
+
++.
/datum/controller/configuration/can_vv_get(var_name)
@@ -165,9 +184,6 @@
stat("[name]:", statclick)
/datum/controller/configuration/proc/Get(entry_type)
- if(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
- log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
- return
var/datum/config_entry/E = entry_type
var/entry_is_abstract = initial(E.abstract_type) == entry_type
if(entry_is_abstract)
@@ -175,12 +191,12 @@
E = entries_by_type[entry_type]
if(!E)
CRASH("Missing config entry for [entry_type]!")
+ if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
+ log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
+ return
return E.config_entry_value
/datum/controller/configuration/proc/Set(entry_type, new_val)
- if(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Set" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
- log_admin_private("Config rewrite of [entry_type] to [new_val] attempted by [key_name(usr)]")
- return
var/datum/config_entry/E = entry_type
var/entry_is_abstract = initial(E.abstract_type) == entry_type
if(entry_is_abstract)
@@ -188,6 +204,9 @@
E = entries_by_type[entry_type]
if(!E)
CRASH("Missing config entry for [entry_type]!")
+ if((E.protection & CONFIG_ENTRY_LOCKED) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Set" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
+ log_admin_private("Config rewrite of [entry_type] to [new_val] attempted by [key_name(usr)]")
+ return
return E.ValidateAndSet("[new_val]")
/datum/controller/configuration/proc/LoadModes()
@@ -197,7 +216,7 @@
mode_reports = list()
mode_false_report_weight = list()
votable_modes = list()
- var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability)
+ var/list/probabilities = Get(/datum/config_entry/keyed_list/probability)
for(var/T in gamemode_cache)
// I wish I didn't have to instance the game modes in order to look up
// their information, but it is the only way (at least that I know of).
@@ -293,9 +312,9 @@
/datum/controller/configuration/proc/get_runnable_modes()
var/list/datum/game_mode/runnable_modes = new
- var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability)
- var/list/min_pop = Get(/datum/config_entry/keyed_number_list/min_pop)
- var/list/max_pop = Get(/datum/config_entry/keyed_number_list/max_pop)
+ var/list/probabilities = Get(/datum/config_entry/keyed_list/probability)
+ var/list/min_pop = Get(/datum/config_entry/keyed_list/min_pop)
+ var/list/max_pop = Get(/datum/config_entry/keyed_list/max_pop)
var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust)
for(var/T in gamemode_cache)
var/datum/game_mode/M = new T()
@@ -323,9 +342,9 @@
/datum/controller/configuration/proc/get_runnable_midround_modes(crew)
var/list/datum/game_mode/runnable_modes = new
- var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability)
- var/list/min_pop = Get(/datum/config_entry/keyed_number_list/min_pop)
- var/list/max_pop = Get(/datum/config_entry/keyed_number_list/max_pop)
+ var/list/probabilities = Get(/datum/config_entry/keyed_list/probability)
+ var/list/min_pop = Get(/datum/config_entry/keyed_list/min_pop)
+ var/list/max_pop = Get(/datum/config_entry/keyed_list/max_pop)
for(var/T in (gamemode_cache - SSticker.mode.type))
var/datum/game_mode/M = new T()
if(!(M.config_tag in modes))
diff --git a/code/controllers/configuration/entries/comms.dm b/code/controllers/configuration/entries/comms.dm
index 576e73faaa..a1de1c962e 100644
--- a/code/controllers/configuration/entries/comms.dm
+++ b/code/controllers/configuration/entries/comms.dm
@@ -4,10 +4,12 @@
/datum/config_entry/string/comms_key/ValidateAndSet(str_val)
return str_val != "default_pwd" && length(str_val) > 6 && ..()
-/datum/config_entry/keyed_string_list/cross_server
+/datum/config_entry/keyed_list/cross_server
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_TEXT
protection = CONFIG_ENTRY_LOCKED
-/datum/config_entry/keyed_string_list/cross_server/ValidateAndSet(str_val)
+/datum/config_entry/keyed_list/cross_server/ValidateAndSet(str_val)
. = ..()
if(.)
var/list/newv = list()
@@ -15,7 +17,7 @@
newv[replacetext(I, "+", " ")] = config_entry_value[I]
config_entry_value = newv
-/datum/config_entry/keyed_string_list/cross_server/ValidateListEntry(key_name, key_value)
+/datum/config_entry/keyed_list/cross_server/ValidateListEntry(key_name, key_value)
return key_value != "byond:\\address:port" && ..()
/datum/config_entry/string/cross_comms_name
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index 88ce13db92..9a1457e0e1 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -1,31 +1,43 @@
/datum/config_entry/number_list/repeated_mode_adjust
-/datum/config_entry/keyed_number_list/probability
+/datum/config_entry/keyed_list/probability
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
-/datum/config_entry/keyed_number_list/probability/ValidateListEntry(key_name)
+/datum/config_entry/keyed_list/probability/ValidateListEntry(key_name)
return key_name in config.modes
-/datum/config_entry/keyed_number_list/max_pop
+/datum/config_entry/keyed_list/max_pop
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
-/datum/config_entry/keyed_number_list/max_pop/ValidateListEntry(key_name)
+/datum/config_entry/keyed_list/max_pop/ValidateListEntry(key_name)
return key_name in config.modes
-/datum/config_entry/keyed_number_list/min_pop
+/datum/config_entry/keyed_list/min_pop
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
-/datum/config_entry/keyed_number_list/min_pop/ValidateListEntry(key_name, key_value)
+/datum/config_entry/keyed_list/min_pop/ValidateListEntry(key_name, key_value)
return key_name in config.modes
-/datum/config_entry/keyed_flag_list/continuous // which roundtypes continue if all antagonists die
+/datum/config_entry/keyed_list/continuous // which roundtypes continue if all antagonists die
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
-/datum/config_entry/keyed_flag_list/continuous/ValidateListEntry(key_name, key_value)
+/datum/config_entry/keyed_list/continuous/ValidateListEntry(key_name, key_value)
return key_name in config.modes
-/datum/config_entry/keyed_flag_list/midround_antag // which roundtypes use the midround antagonist system
+/datum/config_entry/keyed_list/midround_antag // which roundtypes use the midround antagonist system
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
-/datum/config_entry/keyed_flag_list/midround_antag/ValidateListEntry(key_name, key_value)
+/datum/config_entry/keyed_list/midround_antag/ValidateListEntry(key_name, key_value)
return key_name in config.modes
-/datum/config_entry/keyed_string_list/policy
+/datum/config_entry/keyed_list/policy
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_TEXT
/datum/config_entry/number/damage_multiplier
config_entry_value = 1
@@ -124,7 +136,9 @@
/datum/config_entry/flag/show_game_type_odds //if set this allows players to see the odds of each roundtype on the get revision screen
-/datum/config_entry/keyed_flag_list/roundstart_races //races you can play as from the get go.
+/datum/config_entry/keyed_list/roundstart_races //races you can play as from the get go.
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game
@@ -174,28 +188,67 @@
/datum/config_entry/flag/emojis
-/datum/config_entry/number/run_delay //Used for modifying movement speed for mobs.
- var/static/value_cache = 0
+/datum/config_entry/keyed_list/multiplicative_movespeed
+ key_mode = KEY_MODE_TYPE
+ value_mode = VALUE_MODE_NUM
+ config_entry_value = list( //DEFAULTS
+ /mob/living/simple_animal = 1,
+ /mob/living/silicon/pai = 1,
+ /mob/living/carbon/alien/humanoid/hunter = -1,
+ /mob/living/carbon/alien/humanoid/royal/praetorian = 1,
+ /mob/living/carbon/alien/humanoid/royal/queen = 3
+ )
-/datum/config_entry/number/run_delay/ValidateAndSet()
+/datum/config_entry/keyed_list/multiplicative_movespeed/ValidateAndSet()
. = ..()
if(.)
- value_cache = config_entry_value
+ update_config_movespeed_type_lookup(TRUE)
-/datum/config_entry/number/walk_delay
- var/static/value_cache = 0
+/datum/config_entry/keyed_list/multiplicative_movespeed/vv_edit_var(var_name, var_value)
+ . = ..()
+ if(. && (var_name == NAMEOF(src, config_entry_value)))
+ update_config_movespeed_type_lookup(TRUE)
-/datum/config_entry/number/walk_delay/ValidateAndSet()
+/datum/config_entry/number/movedelay //Used for modifying movement speed for mobs.
+ abstract_type = /datum/config_entry/number/movedelay
+
+/datum/config_entry/number/movedelay/ValidateAndSet()
. = ..()
if(.)
- value_cache = config_entry_value
+ update_mob_config_movespeeds()
-/datum/config_entry/number/human_delay //Mob specific modifiers. NOTE: These will affect different mob types in different ways
-/datum/config_entry/number/robot_delay
-/datum/config_entry/number/monkey_delay
-/datum/config_entry/number/alien_delay
-/datum/config_entry/number/slime_delay
-/datum/config_entry/number/animal_delay
+/datum/config_entry/number/movedelay/vv_edit_var(var_name, var_value)
+ . = ..()
+ if(. && (var_name == NAMEOF(src, config_entry_value)))
+ update_mob_config_movespeeds()
+
+/datum/config_entry/number/movedelay/run_delay
+
+/datum/config_entry/number/movedelay/walk_delay
+
+/////////////////////////////////////////////////Outdated move delay
+/datum/config_entry/number/outdated_movedelay
+ deprecated_by = /datum/config_entry/keyed_list/multiplicative_movespeed
+ abstract_type = /datum/config_entry/number/outdated_movedelay
+
+ var/movedelay_type
+
+/datum/config_entry/number/outdated_movedelay/DeprecationUpdate(value)
+ return "[movedelay_type] [value]"
+
+/datum/config_entry/number/outdated_movedelay/human_delay
+ movedelay_type = /mob/living/carbon/human
+/datum/config_entry/number/outdated_movedelay/robot_delay
+ movedelay_type = /mob/living/silicon/robot
+/datum/config_entry/number/outdated_movedelay/monkey_delay
+ movedelay_type = /mob/living/carbon/monkey
+/datum/config_entry/number/outdated_movedelay/alien_delay
+ movedelay_type = /mob/living/carbon/alien
+/datum/config_entry/number/outdated_movedelay/slime_delay
+ movedelay_type = /mob/living/simple_animal/slime
+/datum/config_entry/number/outdated_movedelay/animal_delay
+ movedelay_type = /mob/living/simple_animal
+/////////////////////////////////////////////////
/datum/config_entry/flag/roundstart_away //Will random away mission be loaded.
@@ -219,9 +272,13 @@
config_entry_value = 12
min_val = 0
-/datum/config_entry/keyed_flag_list/random_laws
+/datum/config_entry/keyed_list/random_laws
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_FLAG
-/datum/config_entry/keyed_number_list/law_weight
+/datum/config_entry/keyed_list/law_weight
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
splitter = ","
/datum/config_entry/number/overflow_cap
@@ -286,25 +343,10 @@
/datum/config_entry/flag/shift_time_realtime
-/datum/config_entry/keyed_number_list/antag_rep
+/datum/config_entry/keyed_list/antag_rep
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
/datum/config_entry/number/monkeycap
config_entry_value = 64
min_val = 0
-
-//Cit changes - Adds config options for crew objectives and miscreants
-/datum/config_entry/flag/allow_crew_objectives
-
-/datum/config_entry/flag/allow_miscreants
-
-/datum/config_entry/flag/allow_extended_miscreants
-
-
-/datum/config_entry/flag/nightshift_enabled
-
-/datum/config_entry/number/nightshift_start
- config_entry_value = 20
-
-/datum/config_entry/number/nightshift_finish
- config_entry_value = 6
-//End of Cit changes
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index f05a42e72c..21b0acd040 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -49,6 +49,8 @@
/datum/config_entry/flag/log_pda // log pda messages
+/datum/config_entry/flag/log_telecomms // log telecomms messages
+
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
@@ -324,8 +326,6 @@
/datum/config_entry/flag/allow_map_voting
-/datum/config_entry/flag/generate_minimaps
-
/datum/config_entry/number/client_warn_version
config_entry_value = null
min_val = 500
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index 4791f21c13..4683e93a46 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -30,11 +30,6 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
stat("Globals:", statclick.update("Edit"))
-/datum/controller/global_vars/can_vv_get(var_name)
- if(gvars_datum_protected_varlist[var_name])
- return FALSE
- return ..()
-
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
if(gvars_datum_protected_varlist[var_name])
return FALSE
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index 464a5d305f..c2fb6d6d5c 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -71,7 +71,7 @@ SUBSYSTEM_DEF(air)
setup_atmos_machinery()
setup_pipenets()
gas_reactions = init_gas_reactions()
- ..()
+ return ..()
/datum/controller/subsystem/air/fire(resumed = 0)
@@ -300,9 +300,12 @@ SUBSYSTEM_DEF(air)
var/list/active_turfs = src.active_turfs
var/times_fired = ++src.times_fired
+ // Clear active turfs - faster than removing every single turf in the world
+ // one-by-one, and Initalize_Atmos only ever adds `src` back in.
+ active_turfs.Cut()
+
for(var/thing in turfs_to_init)
var/turf/T = thing
- active_turfs -= T
if (T.blocks_air)
continue
T.Initalize_Atmos(times_fired)
diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm
index 464991e0cf..ebd8d3801f 100644
--- a/code/controllers/subsystem/atoms.dm
+++ b/code/controllers/subsystem/atoms.dm
@@ -11,7 +11,6 @@ SUBSYSTEM_DEF(atoms)
var/old_initialized
var/list/late_loaders
- var/list/created_atoms
var/list/BadInitializeCalls = list()
@@ -33,13 +32,11 @@ SUBSYSTEM_DEF(atoms)
var/count
var/list/mapload_arg = list(TRUE)
if(atoms)
- created_atoms = list()
count = atoms.len
for(var/I in atoms)
var/atom/A = I
if(!(A.flags_1 & INITIALIZED_1))
- if(InitAtom(I, mapload_arg))
- atoms -= I
+ InitAtom(I, mapload_arg)
CHECK_TICK
else
count = 0
@@ -61,10 +58,6 @@ SUBSYSTEM_DEF(atoms)
testing("Late initialized [late_loaders.len] atoms")
late_loaders.Cut()
- if(atoms)
- . = created_atoms + atoms
- created_atoms = null
-
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
var/the_type = A.type
if(QDELING(A))
diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm
index 446ee721ed..72dfed6af0 100644
--- a/code/controllers/subsystem/blackbox.dm
+++ b/code/controllers/subsystem/blackbox.dm
@@ -11,6 +11,7 @@ SUBSYSTEM_DEF(blackbox)
var/sealed = FALSE //time to stop tracking stats?
var/list/versions = list("antagonists" = 3,
"admin_secrets_fun_used" = 2,
+ "explosion" = 2,
"time_dilation_current" = 3,
"science_techweb_unlock" = 2,
"round_end_stats" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
@@ -67,8 +68,8 @@ SUBSYSTEM_DEF(blackbox)
return FALSE
return ..()
-/datum/controller/subsystem/blackbox/Shutdown()
- sealed = FALSE
+//Recorded on subsystem shutdown
+/datum/controller/subsystem/blackbox/proc/FinalFeedback()
record_feedback("tally", "ahelp_stats", GLOB.ahelp_tickets.active_tickets.len, "unresolved")
for (var/obj/machinery/telecomms/message_server/MS in GLOB.telecomms_list)
if (MS.pda_msgs.len)
@@ -76,6 +77,14 @@ SUBSYSTEM_DEF(blackbox)
if (MS.rc_msgs.len)
record_feedback("tally", "radio_usage", MS.rc_msgs.len, "request console")
+ for(var/player_key in GLOB.player_details)
+ var/datum/player_details/PD = GLOB.player_details[player_key]
+ record_feedback("tally", "client_byond_version", 1, PD.byond_version)
+
+/datum/controller/subsystem/blackbox/Shutdown()
+ sealed = FALSE
+ FinalFeedback()
+
if (!SSdbcore.Connect())
return
@@ -321,5 +330,6 @@ Versioning
suicide = sanitizeSQL(suicide)
map = sanitizeSQL(map)
var/datum/DBQuery/query_report_death = SSdbcore.NewQuery("INSERT INTO [format_table_name("death")] (pod, x_coord, y_coord, z_coord, mapname, server_ip, server_port, round_id, tod, job, special, name, byondkey, laname, lakey, bruteloss, fireloss, brainloss, oxyloss, toxloss, cloneloss, staminaloss, last_words, suicide) VALUES ('[sqlpod]', '[x_coord]', '[y_coord]', '[z_coord]', '[map]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', [GLOB.round_id], '[SQLtime()]', '[sqljob]', '[sqlspecial]', '[sqlname]', '[sqlkey]', '[laname]', '[lakey]', [sqlbrute], [sqlfire], [sqlbrain], [sqloxy], [sqltox], [sqlclone], [sqlstamina], '[last_words]', [suicide])")
- query_report_death.Execute()
- qdel(query_report_death)
+ if(query_report_death)
+ query_report_death.Execute(async = TRUE)
+ qdel(query_report_death)
diff --git a/code/controllers/subsystem/communications.dm b/code/controllers/subsystem/communications.dm
index 5a791e28ef..718357b8bb 100644
--- a/code/controllers/subsystem/communications.dm
+++ b/code/controllers/subsystem/communications.dm
@@ -25,7 +25,7 @@ SUBSYSTEM_DEF(communications)
else
priority_announce(html_decode(user.treat_message(input)), null, 'sound/misc/announce.ogg', "Captain")
nonsilicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN
- log_talk(user,"[key_name(user)] has made a priority announcement: [input]",LOGSAY)
+ user.log_talk(input, LOG_SAY, tag="priority announcement")
message_admins("[ADMIN_LOOKUPFLW(user)] has made a priority announcement.")
/datum/controller/subsystem/communications/proc/send_message(datum/comm_message/sending,print = TRUE,unique = FALSE)
diff --git a/code/controllers/subsystem/disease.dm b/code/controllers/subsystem/disease.dm
index 48676bc51e..9be1d8d90c 100644
--- a/code/controllers/subsystem/disease.dm
+++ b/code/controllers/subsystem/disease.dm
@@ -17,7 +17,7 @@ SUBSYSTEM_DEF(disease)
for(var/common_disease_type in all_common_diseases)
var/datum/disease/prototype = new common_disease_type()
archive_diseases[prototype.GetDiseaseID()] = prototype
- ..()
+ return ..()
/datum/controller/subsystem/disease/stat_entry(msg)
..("P:[active_diseases.len]")
diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm
index ffc934c061..abc46cba25 100644
--- a/code/controllers/subsystem/events.dm
+++ b/code/controllers/subsystem/events.dm
@@ -22,7 +22,7 @@ SUBSYSTEM_DEF(events)
control += E //add it to the list of all events (controls)
reschedule()
getHoliday()
- ..()
+ return ..()
/datum/controller/subsystem/events/fire(resumed = 0)
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
index 15a668b038..eec9f63a12 100644
--- a/code/controllers/subsystem/garbage.dm
+++ b/code/controllers/subsystem/garbage.dm
@@ -85,41 +85,21 @@ SUBSYSTEM_DEF(garbage)
/datum/controller/subsystem/garbage/fire()
//the fact that this resets its processing each fire (rather then resume where it left off) is intentional.
- var/queue = GC_QUEUE_PREQUEUE
+ var/queue = GC_QUEUE_CHECK
while (state == SS_RUNNING)
switch (queue)
- if (GC_QUEUE_PREQUEUE)
- HandlePreQueue()
- queue = GC_QUEUE_PREQUEUE+1
if (GC_QUEUE_CHECK)
HandleQueue(GC_QUEUE_CHECK)
queue = GC_QUEUE_CHECK+1
if (GC_QUEUE_HARDDELETE)
HandleQueue(GC_QUEUE_HARDDELETE)
+ if (state == SS_PAUSED) //make us wait again before the next run.
+ state = SS_RUNNING
break
- if (state == SS_PAUSED) //make us wait again before the next run.
- state = SS_RUNNING
+
-//If you see this proc high on the profile, what you are really seeing is the garbage collection/soft delete overhead in byond.
-//Don't attempt to optimize, not worth the effort.
-/datum/controller/subsystem/garbage/proc/HandlePreQueue()
- var/list/tobequeued = queues[GC_QUEUE_PREQUEUE]
- var/static/count = 0
- if (count)
- var/c = count
- count = 0 //so if we runtime on the Cut, we don't try again.
- tobequeued.Cut(1,c+1)
-
- for (var/ref in tobequeued)
- count++
- Queue(ref, GC_QUEUE_PREQUEUE+1)
- if (MC_TICK_CHECK)
- break
- if (count)
- tobequeued.Cut(1,count+1)
- count = 0
/datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK)
if (level == GC_QUEUE_CHECK)
@@ -141,7 +121,7 @@ SUBSYSTEM_DEF(garbage)
if (!refID)
count++
if (MC_TICK_CHECK)
- break
+ return
continue
var/GCd_at_time = queue[refID]
@@ -160,7 +140,7 @@ SUBSYSTEM_DEF(garbage)
reference_find_on_fail -= refID //It's deleted we don't care anymore.
#endif
if (MC_TICK_CHECK)
- break
+ return
continue
// Something's still referring to the qdel'd object.
@@ -183,27 +163,20 @@ SUBSYSTEM_DEF(garbage)
if (GC_QUEUE_HARDDELETE)
HardDelete(D)
if (MC_TICK_CHECK)
- break
+ return
continue
Queue(D, level+1)
if (MC_TICK_CHECK)
- break
+ return
if (count)
queue.Cut(1,count+1)
count = 0
-/datum/controller/subsystem/garbage/proc/PreQueue(datum/D)
- if (D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
- queues[GC_QUEUE_PREQUEUE] += D
- D.gc_destroyed = GC_QUEUED_FOR_QUEUING
-
/datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_CHECK)
if (isnull(D))
return
- if (D.gc_destroyed == GC_QUEUED_FOR_HARD_DEL)
- level = GC_QUEUE_HARDDELETE
if (level > GC_QUEUE_COUNT)
HardDelete(D)
return
@@ -249,11 +222,6 @@ SUBSYSTEM_DEF(garbage)
message_admins("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete).")
postpone(time)
-/datum/controller/subsystem/garbage/proc/HardQueue(datum/D)
- if (D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
- queues[GC_QUEUE_PREQUEUE] += D
- D.gc_destroyed = GC_QUEUED_FOR_HARD_DEL
-
/datum/controller/subsystem/garbage/Recover()
if (istype(SSgarbage.queues))
for (var/i in 1 to SSgarbage.queues.len)
@@ -308,7 +276,7 @@ SUBSYSTEM_DEF(garbage)
return
switch(hint)
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
- SSgarbage.PreQueue(D)
+ SSgarbage.Queue(D)
if (QDEL_HINT_IWILLGC)
D.gc_destroyed = world.time
return
@@ -328,18 +296,18 @@ SUBSYSTEM_DEF(garbage)
#endif
I.no_respect_force++
- SSgarbage.PreQueue(D)
- if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate()
- SSgarbage.HardQueue(D)
+ SSgarbage.Queue(D)
+ if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete
+ SSgarbage.Queue(D, GC_QUEUE_HARDDELETE)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
SSgarbage.HardDelete(D)
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
- SSgarbage.PreQueue(D)
+ SSgarbage.Queue(D)
#ifdef TESTING
D.find_references()
#endif
if (QDEL_HINT_IFFAIL_FINDREFERENCE)
- SSgarbage.PreQueue(D)
+ SSgarbage.Queue(D)
#ifdef TESTING
SSgarbage.reference_find_on_fail[REF(D)] = TRUE
#endif
@@ -349,7 +317,7 @@ SUBSYSTEM_DEF(garbage)
testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
#endif
I.no_hint++
- SSgarbage.PreQueue(D)
+ SSgarbage.Queue(D)
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
diff --git a/code/controllers/subsystem/icon_smooth.dm b/code/controllers/subsystem/icon_smooth.dm
index 1c8d94826d..6f4040299a 100644
--- a/code/controllers/subsystem/icon_smooth.dm
+++ b/code/controllers/subsystem/icon_smooth.dm
@@ -39,4 +39,4 @@ SUBSYSTEM_DEF(icon_smooth)
smooth_icon(A)
CHECK_TICK
- ..()
+ return ..()
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index 5897889510..0ae378e07f 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -21,7 +21,7 @@ SUBSYSTEM_DEF(job)
LoadJobs()
generate_selectable_species()
set_overflow_role(CONFIG_GET(string/overflow_job))
- ..()
+ return ..()
/datum/controller/subsystem/job/proc/set_overflow_role(new_overflow_role)
var/datum/job/new_overflow = GetJob(new_overflow_role)
@@ -583,7 +583,7 @@ SUBSYSTEM_DEF(job)
return
//pick an open spot on arrivals and dump em
- var/list/arrivals_turfs = shuffle(get_area_turfs(/area/shuttle/arrival))
+ var/list/arrivals_turfs = shuffle(GLOB.areas_by_type[/area/shuttle/arrival]))
if(arrivals_turfs.len)
for(var/turf/T in arrivals_turfs)
if(!is_blocked_turf(T, TRUE))
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index 6c5721531d..12b467b624 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -22,10 +22,10 @@ SUBSYSTEM_DEF(lighting)
create_all_lighting_objects()
initialized = TRUE
-
+
fire(FALSE, TRUE)
- ..()
+ return ..()
/datum/controller/subsystem/lighting/fire(resumed, init_tick_checks)
MC_SPLIT_TICK_INIT(3)
diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm
index 6d5d64fe6c..c4b09d1b87 100644
--- a/code/controllers/subsystem/machines.dm
+++ b/code/controllers/subsystem/machines.dm
@@ -9,7 +9,7 @@ SUBSYSTEM_DEF(machines)
/datum/controller/subsystem/machines/Initialize()
makepowernets()
fire()
- ..()
+ return ..()
/datum/controller/subsystem/machines/proc/makepowernets()
for(var/datum/powernet/PN in powernets)
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index 89a8df1091..3a25d889e0 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -33,7 +33,6 @@ SUBSYSTEM_DEF(mapping)
var/list/z_list
var/datum/space_level/transit
var/datum/space_level/empty_space
- var/dmm_suite/loader
/datum/controller/subsystem/mapping/PreInit()
if(!config)
@@ -54,7 +53,6 @@ SUBSYSTEM_DEF(mapping)
if(!config || config.defaulted)
to_chat(world, "Unable to load next or default map config, defaulting to Box Station")
config = old_config
- loader = new
loadWorld()
repopulate_sorted_areas()
process_teleport_locs() //Sets up the wizard teleport locations
@@ -94,9 +92,8 @@ SUBSYSTEM_DEF(mapping)
// Set up Z-level transitions.
setup_map_transitions()
generate_station_area_list()
- QDEL_NULL(loader)
initialize_reserved_level()
- ..()
+ return ..()
/* Nuke threats, for making the blue tiles on the station go RED
Used by the AI doomsday and the self destruct nuke.
@@ -170,6 +167,7 @@ SUBSYSTEM_DEF(mapping)
#define INIT_ANNOUNCE(X) to_chat(world, "[X]"); log_world(X)
/datum/controller/subsystem/mapping/proc/LoadGroup(list/errorList, name, path, files, list/traits, list/default_traits, silent = FALSE)
+ . = list()
var/start_time = REALTIMEOFDAY
if (!islist(files)) // handle single-level maps
@@ -177,10 +175,15 @@ SUBSYSTEM_DEF(mapping)
// check that the total z count of all maps matches the list of traits
var/total_z = 0
+ var/list/parsed_maps = list()
for (var/file in files)
var/full_path = "_maps/[path]/[file]"
- var/bounds = loader.load_map(file(full_path), 1, 1, 1, cropMap=FALSE, measureOnly=TRUE)
- files[file] = total_z // save the start Z of this file
+ var/datum/parsed_map/pm = new(file(full_path))
+ var/bounds = pm?.bounds
+ if (!bounds)
+ errorList |= full_path
+ continue
+ parsed_maps[pm] = total_z // save the start Z of this file
total_z += bounds[MAP_MAXZ] - bounds[MAP_MINZ] + 1
if (!length(traits)) // null or empty - default
@@ -201,12 +204,13 @@ SUBSYSTEM_DEF(mapping)
++i
// load the maps
- for (var/file in files)
- var/full_path = "_maps/[path]/[file]"
- if(!loader.load_map(file(full_path), 0, 0, start_z + files[file], no_changeturf = TRUE))
- errorList |= full_path
+ for (var/P in parsed_maps)
+ var/datum/parsed_map/pm = P
+ if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE))
+ errorList |= pm.original_path
if(!silent)
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
+ return parsed_maps
/datum/controller/subsystem/mapping/proc/loadWorld()
//if any of these fail, something has gone horribly, HORRIBLY, wrong
@@ -456,7 +460,13 @@ GLOBAL_LIST_EMPTY(the_station_areas)
for(var/i in levels_by_trait(ZTRAIT_RESERVED))
var/turf/A = get_turf(locate(SHUTTLE_TRANSIT_BORDER,SHUTTLE_TRANSIT_BORDER,i))
var/turf/B = get_turf(locate(world.maxx - SHUTTLE_TRANSIT_BORDER,world.maxy - SHUTTLE_TRANSIT_BORDER,i))
- reserve_turfs(block(A, B))
+ var/block = block(A, B)
+ for(var/t in block)
+ // No need to empty() these, because it's world init and they're
+ // already /turf/open/space/basic.
+ var/turf/T = t
+ T.flags_1 |= UNUSED_RESERVATION_TURF_1
+ unused_turfs["[i]"] = block
clearing_reserved_turfs = FALSE
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
diff --git a/code/controllers/subsystem/medals.dm b/code/controllers/subsystem/medals.dm
index 8b69726af1..21ab27492b 100644
--- a/code/controllers/subsystem/medals.dm
+++ b/code/controllers/subsystem/medals.dm
@@ -6,7 +6,7 @@ SUBSYSTEM_DEF(medals)
/datum/controller/subsystem/medals/Initialize(timeofday)
if(CONFIG_GET(string/medal_hub_address) && CONFIG_GET(string/medal_hub_password))
hub_enabled = TRUE
- ..()
+ return ..()
/datum/controller/subsystem/medals/proc/UnlockMedal(medal, client/player)
set waitfor = FALSE
@@ -84,4 +84,4 @@ SUBSYSTEM_DEF(medals)
/datum/controller/subsystem/medals/proc/ClearScore(client/player)
if(isnull(world.SetScores(player.ckey, "", CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))))
log_game("MEDAL ERROR: Could not contact hub to clear scores for [player.key]!")
- message_admins("Error! Failed to contact hub to clear scores for [player.key]!")
\ No newline at end of file
+ message_admins("Error! Failed to contact hub to clear scores for [player.key]!")
diff --git a/code/controllers/subsystem/mobs.dm b/code/controllers/subsystem/mobs.dm
index 428819f897..56cdf2fa03 100644
--- a/code/controllers/subsystem/mobs.dm
+++ b/code/controllers/subsystem/mobs.dm
@@ -6,6 +6,7 @@ SUBSYSTEM_DEF(mobs)
var/list/currentrun = list()
var/static/list/clients_by_zlevel[][]
+ var/static/list/dead_players_by_zlevel[][] = list(list()) // Needs to support zlevel 1 here, MaxZChanged only happens when z2 is created and new_players can login before that.
var/static/list/cubemonkeys = list()
/datum/controller/subsystem/mobs/stat_entry()
@@ -14,9 +15,12 @@ SUBSYSTEM_DEF(mobs)
/datum/controller/subsystem/mobs/proc/MaxZChanged()
if (!islist(clients_by_zlevel))
clients_by_zlevel = new /list(world.maxz,0)
+ dead_players_by_zlevel = new /list(world.maxz,0)
while (clients_by_zlevel.len < world.maxz)
clients_by_zlevel.len++
clients_by_zlevel[clients_by_zlevel.len] = list()
+ dead_players_by_zlevel.len++
+ dead_players_by_zlevel[dead_players_by_zlevel.len] = list()
/datum/controller/subsystem/mobs/fire(resumed = 0)
var/seconds = wait * 0.1
diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm
index 1a7bd43fd2..20eb2af001 100644
--- a/code/controllers/subsystem/overlays.dm
+++ b/code/controllers/subsystem/overlays.dm
@@ -19,7 +19,7 @@ SUBSYSTEM_DEF(overlays)
/datum/controller/subsystem/overlays/Initialize()
initialized = TRUE
fire(mc_check = FALSE)
- ..()
+ return ..()
/datum/controller/subsystem/overlays/stat_entry()
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index b844a1fc1a..978eedb62f 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -28,7 +28,7 @@ SUBSYSTEM_DEF(persistence)
LoadPhotoPersistence()
if(CONFIG_GET(flag/use_antag_rep))
LoadAntagReputation()
- ..()
+ return ..()
/datum/controller/subsystem/persistence/proc/LoadSatchels()
var/placed_satchel = 0
@@ -207,6 +207,16 @@ SUBSYSTEM_DEF(persistence)
if(CONFIG_GET(flag/use_antag_rep))
CollectAntagReputation()
+/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
+ var/album_path = file("data/photo_albums.json")
+ if(fexists(album_path))
+ return json_decode(file2text(album_path))
+
+/datum/controller/subsystem/persistence/proc/GetPhotoFrames()
+ var/frame_path = file("data/photo_frames.json")
+ if(fexists(frame_path))
+ return json_decode(file2text(frame_path))
+
/datum/controller/subsystem/persistence/proc/LoadPhotoPersistence()
var/album_path = file("data/photo_albums.json")
var/frame_path = file("data/photo_frames.json")
diff --git a/code/controllers/subsystem/processing/circuit.dm b/code/controllers/subsystem/processing/circuit.dm
index dad71a005a..1ae5bad23c 100644
--- a/code/controllers/subsystem/processing/circuit.dm
+++ b/code/controllers/subsystem/processing/circuit.dm
@@ -50,6 +50,11 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
/obj/item/electronic_assembly/simple,
/obj/item/electronic_assembly/hook,
/obj/item/electronic_assembly/pda,
+ /obj/item/electronic_assembly/small/default,
+ /obj/item/electronic_assembly/small/cylinder,
+ /obj/item/electronic_assembly/small/scanner,
+ /obj/item/electronic_assembly/small/hook,
+ /obj/item/electronic_assembly/small/box,
/obj/item/electronic_assembly/medium/default,
/obj/item/electronic_assembly/medium/box,
/obj/item/electronic_assembly/medium/clam,
@@ -68,6 +73,7 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
/obj/item/electronic_assembly/drone/medbot,
/obj/item/electronic_assembly/drone/genbot,
/obj/item/electronic_assembly/drone/android,
+ /obj/item/electronic_assembly/wallmount/tiny,
/obj/item/electronic_assembly/wallmount/light,
/obj/item/electronic_assembly/wallmount,
/obj/item/electronic_assembly/wallmount/heavy
@@ -83,3 +89,4 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
/obj/item/card/data/full_color,
/obj/item/card/data/disk
)
+
diff --git a/code/controllers/subsystem/processing/obj.dm b/code/controllers/subsystem/processing/obj.dm
index 68f6f16cea..26021fb267 100644
--- a/code/controllers/subsystem/processing/obj.dm
+++ b/code/controllers/subsystem/processing/obj.dm
@@ -1,29 +1,5 @@
-SUBSYSTEM_DEF(obj)
+PROCESSING_SUBSYSTEM_DEF(obj)
name = "Objects"
priority = FIRE_PRIORITY_OBJ
flags = SS_NO_INIT
-
- var/list/processing = list()
- var/list/currentrun = list()
-
-/datum/controller/subsystem/obj/stat_entry()
- ..("P:[processing.len]")
-
-/datum/controller/subsystem/obj/fire(resumed = 0)
- if (!resumed)
- src.currentrun = processing.Copy()
- //cache for sanic speed (lists are references anyways)
- var/list/currentrun = src.currentrun
-
- while(currentrun.len)
- var/datum/thing = currentrun[currentrun.len]
- currentrun.len--
- if(thing)
- thing.process(wait)
- else
- SSobj.processing -= thing
- if (MC_TICK_CHECK)
- return
-
-/datum/controller/subsystem/obj/Recover()
- processing = SSobj.processing
+ wait = 20
diff --git a/code/controllers/subsystem/processing/processing.dm b/code/controllers/subsystem/processing/processing.dm
index ef2a0f72e6..c5d6dfa126 100644
--- a/code/controllers/subsystem/processing/processing.dm
+++ b/code/controllers/subsystem/processing/processing.dm
@@ -22,12 +22,14 @@ SUBSYSTEM_DEF(processing)
while(current_run.len)
var/datum/thing = current_run[current_run.len]
current_run.len--
- if(QDELETED(thing) || thing.process(wait) == PROCESS_KILL)
+ if(QDELETED(thing))
processing -= thing
+ else if(thing.process(wait) == PROCESS_KILL)
+ // fully stop so that a future START_PROCESSING will work
+ STOP_PROCESSING(src, thing)
if (MC_TICK_CHECK)
return
/datum/proc/process()
set waitfor = 0
- STOP_PROCESSING(SSobj, src)
- return 0
+ return PROCESS_KILL
diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm
index cec8b2832b..a6c86a3576 100644
--- a/code/controllers/subsystem/processing/quirks.dm
+++ b/code/controllers/subsystem/processing/quirks.dm
@@ -15,7 +15,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
/datum/controller/subsystem/processing/quirks/Initialize(timeofday)
if(!quirks.len)
SetupQuirks()
- ..()
+ return ..()
/datum/controller/subsystem/processing/quirks/proc/SetupQuirks()
for(var/V in subtypesof(/datum/quirk))
diff --git a/code/controllers/subsystem/processing/traits.dm b/code/controllers/subsystem/processing/traits.dm
deleted file mode 100644
index 8e31260d94..0000000000
--- a/code/controllers/subsystem/processing/traits.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-//Used to process and handle roundstart trait datums
-//Trait datums are separate from trait strings:
-// - Trait strings are used for faster checking in code
-// - Trait datums are stored and hold different effects, as well as being a vector for applying trait string
-PROCESSING_SUBSYSTEM_DEF(traits)
- name = "Traits"
- init_order = INIT_ORDER_TRAITS
- flags = SS_BACKGROUND
- wait = 10
- runlevels = RUNLEVEL_GAME
-
- var/list/traits = list() //Assoc. list of all roundstart trait datum types; "name" = /path/
- var/list/trait_points = list() //Assoc. list of trait names and their "point cost"; positive numbers are good traits, and negative ones are bad
- var/list/trait_objects = list() //A list of all trait objects in the game, since some may process
-
-/datum/controller/subsystem/processing/traits/Initialize(timeofday)
- if(!traits.len)
- SetupTraits()
- ..()
-
-/datum/controller/subsystem/processing/traits/proc/SetupTraits()
- for(var/V in subtypesof(/datum/trait))
- var/datum/trait/T = V
- traits[initial(T.name)] = T
- trait_points[initial(T.name)] = initial(T.value)
-
-/datum/controller/subsystem/processing/traits/proc/AssignTraits(mob/living/user, client/cli, spawn_effects)
- GenerateTraits(cli)
- if(user && cli && cli.prefs.character_traits)
- for(var/V in cli.prefs.character_traits)
- user.add_trait_datum(V, spawn_effects)
-
-/datum/controller/subsystem/processing/traits/proc/GenerateTraits(client/user)
- if(user && user.prefs && user.prefs.character_traits)
- if(user.prefs.character_traits.len)
- return
- user.prefs.character_traits = user.prefs.all_traits
diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm
index d60c8336fa..56f933724d 100644
--- a/code/controllers/subsystem/research.dm
+++ b/code/controllers/subsystem/research.dm
@@ -17,9 +17,9 @@ SUBSYSTEM_DEF(research)
var/list/techweb_boost_items = list() //associative double-layer path = list(id = list(point_type = point_discount))
var/list/techweb_nodes_hidden = list() //Nodes that should be hidden by default.
var/list/techweb_point_items = list( //path = list(point type = value)
- /obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 2500),
+ /obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 2500),
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 5000), // Cit three more anomalys anomalys
- /obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 7500),
+ /obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 7500),
/obj/item/assembly/signaler/anomaly = list(TECHWEB_POINT_TYPE_GENERIC = 10000),
/obj/item/slime_extract/grey = list(TECHWEB_POINT_TYPE_GENERIC = 500), // Adds in slime core deconing
/obj/item/slime_extract/metal = list(TECHWEB_POINT_TYPE_GENERIC = 750),
@@ -40,14 +40,18 @@ SUBSYSTEM_DEF(research)
/obj/item/slime_extract/adamantine =list (TECHWEB_POINT_TYPE_GENERIC = 1500),
/obj/item/slime_extract/oil = list(TECHWEB_POINT_TYPE_GENERIC = 1500),
/obj/item/slime_extract/lightpink = list(TECHWEB_POINT_TYPE_GENERIC = 1500),
- /obj/item/slime_extract/rainbow = list(TECHWEB_POINT_TYPE_GENERIC = 2500) // End of Cit changes
- )
+ /obj/item/slime_extract/rainbow = list(TECHWEB_POINT_TYPE_GENERIC = 2500) // End of Cit changes
var/list/errored_datums = list()
var/list/point_types = list() //typecache style type = TRUE list
//----------------------------------------------
- var/list/single_server_income = list(TECHWEB_POINT_TYPE_GENERIC = 25) //citadel edit - techwebs nerf
+ var/list/single_server_income = list(TECHWEB_POINT_TYPE_GENERIC = 25) //citadel edit - techwebs nerf
var/multiserver_calculation = FALSE
- var/last_income = 0
+ var/last_income
+ //^^^^^^^^ ALL OF THESE ARE PER SECOND! ^^^^^^^^
+
+ //Aiming for 1.5 hours to max R&D
+ //[88nodes * 5000points/node] / [1.5hr * 90min/hr * 60s/min]
+ //Around 450000 points max???
/datum/controller/subsystem/research/Initialize()
point_types = TECHWEB_POINT_TYPE_LIST_ASSOCIATIVE_NAMES
@@ -59,9 +63,6 @@ SUBSYSTEM_DEF(research)
return ..()
/datum/controller/subsystem/research/fire()
- handle_research_income()
-
-/datum/controller/subsystem/research/proc/handle_research_income()
var/list/bitcoins = list()
if(multiserver_calculation)
var/eff = calculate_server_coefficient()
@@ -75,11 +76,12 @@ SUBSYSTEM_DEF(research)
if(miner.working)
bitcoins = single_server_income.Copy()
break //Just need one to work.
- var/income_time_difference = world.time - last_income
- science_tech.last_bitcoins = bitcoins // Doesn't take tick drift into account
- for(var/i in bitcoins)
- bitcoins[i] *= income_time_difference / 10
- science_tech.add_point_list(bitcoins)
+ if (!isnull(last_income))
+ var/income_time_difference = world.time - last_income
+ science_tech.last_bitcoins = bitcoins // Doesn't take tick drift into account
+ for(var/i in bitcoins)
+ bitcoins[i] *= income_time_difference / 10
+ science_tech.add_point_list(bitcoins)
last_income = world.time
/datum/controller/subsystem/research/proc/calculate_server_coefficient() //Diminishing returns.
diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm
index dd45f9146f..7abb873b9c 100644
--- a/code/controllers/subsystem/server_maint.dm
+++ b/code/controllers/subsystem/server_maint.dm
@@ -12,7 +12,7 @@ SUBSYSTEM_DEF(server_maint)
/datum/controller/subsystem/server_maint/Initialize(timeofday)
if (CONFIG_GET(flag/hub))
world.update_hub_visibility(TRUE)
- ..()
+ return ..()
/datum/controller/subsystem/server_maint/fire(resumed = FALSE)
if(!resumed)
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index dcce2c0462..32d87425ff 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -53,7 +53,7 @@ SUBSYSTEM_DEF(shuttle)
var/lockdown = FALSE //disallow transit after nuke goes off
- var/auto_call = 72000 //CIT CHANGE - time before in deciseconds in which the shuttle is auto called. Default is 2½ hours plus 15 for the shuttle. So total is 3.
+ var/auto_call = 72000 //CIT CHANGE - time before in deciseconds in which the shuttle is auto called. Default is 2ish hours plus 15 for the shuttle. So total is 3.
/datum/controller/subsystem/shuttle/Initialize(timeofday)
ordernum = rand(1, 9000)
@@ -74,7 +74,7 @@ SUBSYSTEM_DEF(shuttle)
WARNING("No /obj/docking_port/mobile/emergency/backup placed on the map!")
if(!supply)
WARNING("No /obj/docking_port/mobile/supply placed on the map!")
- ..()
+ return ..()
/datum/controller/subsystem/shuttle/proc/initial_load()
if(!istype(manipulator))
@@ -220,6 +220,14 @@ SUBSYSTEM_DEF(shuttle)
else
emergency.request(null, signal_origin, html_decode(emergency_reason), 0)
+ var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
+
+ if(!frequency)
+ return
+
+ var/datum/signal/status_signal = new(list("command" = "update")) // Start processing shuttle-mode displays to display the timer
+ frequency.post_signal(src, status_signal)
+
var/area/A = get_area(user)
log_game("[key_name(user)] has called the shuttle.")
diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm
index e03299f57f..b10d0af8c5 100644
--- a/code/controllers/subsystem/tgui.dm
+++ b/code/controllers/subsystem/tgui.dm
@@ -11,7 +11,7 @@ SUBSYSTEM_DEF(tgui)
var/basehtml // The HTML base used for all UIs.
/datum/controller/subsystem/tgui/PreInit()
- basehtml = file2text("tgui/tgui.html")
+ basehtml = file2text('tgui/tgui.html')
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index 2b9c0f3653..de58c1a0d7 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -126,6 +126,7 @@ SUBSYSTEM_DEF(throwing)
//done throwing, either because it hit something or it finished moving
if(!thrownthing)
return
+ thrownthing.throwing = null
if (!hit)
for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on.
var/atom/A = thing
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 408f8bf96b..30c78d6321 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -67,12 +67,6 @@ SUBSYSTEM_DEF(ticker)
var/end_state = "undefined"
var/modevoted = FALSE //Have we sent a vote for the gamemode?
- var/tumpedbuckets = FALSE //Have we tumped over buckets?
-
- //Crew Objective/Miscreant stuff
- var/list/crewobjlist = list()
- var/list/crewobjjobs = list()
- var/list/miscreantobjlist = list()
/datum/controller/subsystem/ticker/Initialize(timeofday)
load_mode()
@@ -129,26 +123,19 @@ SUBSYSTEM_DEF(ticker)
login_music = pick(music)
else
login_music = "[global.config.directory]/title_music/sounds/[pick(music)]"
-/*
- crewobjlist = typesof(/datum/objective/crew)
- miscreantobjlist = (typesof(/datum/objective/miscreant) - /datum/objective/miscreant)
- for(var/hoorayhackyshit in crewobjlist) //taken from old Hippie's "job2obj" proc with adjustments.
- var/datum/objective/crew/obj = hoorayhackyshit //dm is not a sane language in any way, shape, or form.
- var/list/availableto = splittext(initial(obj.jobs),",")
- for(var/job in availableto)
- crewobjjobs["[job]"] += list(obj) */
+
if(!GLOB.syndicate_code_phrase)
GLOB.syndicate_code_phrase = generate_code_phrase()
if(!GLOB.syndicate_code_response)
GLOB.syndicate_code_response = generate_code_phrase()
- ..()
start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10)
if(CONFIG_GET(flag/randomize_shift_time))
gametime_offset = rand(0, 23) HOURS
else if(CONFIG_GET(flag/shift_time_realtime))
gametime_offset = world.timeofday
+ return ..()
/datum/controller/subsystem/ticker/fire()
switch(current_state)
@@ -166,10 +153,6 @@ SUBSYSTEM_DEF(ticker)
fire()
if(GAME_STATE_PREGAME)
//lobby stats for statpanels
- if(!tumpedbuckets)
- SStimer.tump_buckets()
- if(!modevoted)
- send_gamemode_vote()
if(isnull(timeLeft))
timeLeft = max(0,start_at - world.time)
totalPlayers = 0
@@ -182,6 +165,8 @@ SUBSYSTEM_DEF(ticker)
if(start_immediately)
timeLeft = 0
+ if(!modevoted)
+ send_gamemode_vote()
//countdown
if(timeLeft < 0)
return
@@ -326,13 +311,6 @@ SUBSYSTEM_DEF(ticker)
GLOB.start_state = new /datum/station_state()
GLOB.start_state.count()
-/* //assign crew objectives and generate miscreants
- if(CONFIG_GET(flag/allow_extended_miscreants) && GLOB.master_mode == "extended")
- GLOB.miscreants_allowed = TRUE
- if(CONFIG_GET(flag/allow_miscreants) && GLOB.master_mode != "extended")
- GLOB.miscreants_allowed = TRUE
- generate_crew_objectives() */
-
var/list/adm = get_admin_counts()
var/list/allmins = adm["present"]
send2irc("Server", "Round [GLOB.round_id ? "#[GLOB.round_id]:" : "of"] [hide_mode ? "secret":"[mode.name]"] has started[allmins.len ? ".":" with no active admins online!"]")
@@ -662,6 +640,7 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/Shutdown()
gather_newscaster() //called here so we ensure the log is created even upon admin reboot
save_admin_data()
+ update_everything_flag_in_db()
if(!round_end_sound)
round_end_sound = pick(\
'sound/roundend/newroundsexy.ogg',
@@ -670,7 +649,8 @@ SUBSYSTEM_DEF(ticker)
'sound/roundend/leavingtg.ogg',
'sound/roundend/its_only_game.ogg',
'sound/roundend/yeehaw.ogg',
- 'sound/roundend/disappointed.ogg'\
+ 'sound/roundend/disappointed.ogg',
+ 'sound/roundend/gondolabridge.ogg'\
)
SEND_SOUND(world, sound(round_end_sound))
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index fb975c8a79..4b347b2a39 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -71,6 +71,7 @@ SUBSYSTEM_DEF(timer)
for(var/I in second_queue)
log_world(get_timer_debug_string(I))
+ var/cut_start_index = 1
var/next_clienttime_timer_index = 0
var/len = length(clienttime_timers)
@@ -90,11 +91,17 @@ SUBSYSTEM_DEF(timer)
ctime_timer.spent = REALTIMEOFDAY
callBack.InvokeAsync()
- qdel(ctime_timer)
+
+ if(ctime_timer.flags & TIMER_LOOP)
+ ctime_timer.spent = 0
+ clienttime_timers.Insert(ctime_timer, 1)
+ cut_start_index++
+ else
+ qdel(ctime_timer)
if (next_clienttime_timer_index)
- clienttime_timers.Cut(1,next_clienttime_timer_index+1)
+ clienttime_timers.Cut(cut_start_index,next_clienttime_timer_index+1)
if (MC_TICK_CHECK)
return
@@ -197,8 +204,22 @@ SUBSYSTEM_DEF(timer)
bucket_count -= length(spent)
- for (var/spent_timer in spent)
- qdel(spent_timer)
+ for (var/i in spent)
+ var/datum/timedevent/qtimer = i
+ if(QDELETED(qtimer))
+ bucket_count++
+ continue
+ if(!(qtimer.flags & TIMER_LOOP))
+ qdel(qtimer)
+ else
+ bucket_count++
+ qtimer.spent = 0
+ qtimer.bucketEject()
+ if(qtimer.flags & TIMER_CLIENT_TIME)
+ qtimer.timeToRun = REALTIMEOFDAY + qtimer.wait
+ else
+ qtimer.timeToRun = world.time + qtimer.wait
+ qtimer.bucketJoin()
spent.len = 0
@@ -294,6 +315,7 @@ SUBSYSTEM_DEF(timer)
var/id
var/datum/callback/callBack
var/timeToRun
+ var/wait
var/hash
var/list/flags
var/spent = 0 //time we ran the timer.
@@ -302,14 +324,19 @@ SUBSYSTEM_DEF(timer)
var/datum/timedevent/next
var/datum/timedevent/prev
-/datum/timedevent/New(datum/callback/callBack, timeToRun, flags, hash)
+/datum/timedevent/New(datum/callback/callBack, wait, flags, hash)
var/static/nextid = 1
id = TIMER_ID_NULL
src.callBack = callBack
- src.timeToRun = timeToRun
+ src.wait = wait
src.flags = flags
src.hash = hash
+ if (flags & TIMER_CLIENT_TIME)
+ timeToRun = REALTIMEOFDAY + wait
+ else
+ timeToRun = world.time + wait
+
if (flags & TIMER_UNIQUE)
SStimer.hashes[hash] = src
@@ -321,7 +348,7 @@ SUBSYSTEM_DEF(timer)
nextid++
SStimer.timer_id_dict[id] = src
- name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
+ name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
if ((timeToRun < world.time || timeToRun < SStimer.head_offset) && !(flags & TIMER_CLIENT_TIME))
CRASH("Invalid timer state: Timer created that would require a backtrack to run (addtimer would never let this happen): [SStimer.get_timer_debug_string(src)]")
@@ -329,60 +356,7 @@ SUBSYSTEM_DEF(timer)
if (callBack.object != GLOBAL_PROC && !QDESTROYING(callBack.object))
LAZYADD(callBack.object.active_timers, src)
-
- var/list/L
-
- if (flags & TIMER_CLIENT_TIME)
- L = SStimer.clienttime_timers
- else if (timeToRun >= TIMER_MAX)
- L = SStimer.second_queue
-
-
- if (L)
- //binary search sorted insert
- var/cttl = length(L)
- if(cttl)
- var/left = 1
- var/right = cttl
- var/mid = (left+right) >> 1 //rounded divide by two for hedgehogs
-
- var/datum/timedevent/item
- while (left < right)
- item = L[mid]
- if (item.timeToRun <= timeToRun)
- left = mid+1
- else
- right = mid
- mid = (left+right) >> 1
-
- item = L[mid]
- mid = item.timeToRun > timeToRun ? mid : mid+1
- L.Insert(mid, src)
-
- else
- L += src
- return
-
- //get the list of buckets
- var/list/bucket_list = SStimer.bucket_list
-
- //calculate our place in the bucket list
- var/bucket_pos = BUCKET_POS(src)
-
- //get the bucket for our tick
- var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
- SStimer.bucket_count++
- //empty bucket, we will just add ourselves
- if (!bucket_head)
- bucket_list[bucket_pos] = src
- return
- //other wise, lets do a simplified linked list add.
- if (!bucket_head.prev)
- bucket_head.prev = bucket_head
- next = bucket_head
- prev = bucket_head.prev
- next.prev = src
- prev.next = src
+ bucketJoin()
/datum/timedevent/Destroy()
..()
@@ -406,31 +380,7 @@ SUBSYSTEM_DEF(timer)
if (!spent)
spent = world.time
- var/bucketpos = BUCKET_POS(src)
- var/datum/timedevent/buckethead
- var/list/bucket_list = SStimer.bucket_list
- if (bucketpos > 0)
- buckethead = bucket_list[bucketpos]
-
- if (buckethead == src)
- bucket_list[bucketpos] = next
- SStimer.bucket_count--
- else if (timeToRun < TIMER_MAX || next || prev)
- SStimer.bucket_count--
- else
- var/l = length(SStimer.second_queue)
- SStimer.second_queue -= src
- if (l == length(SStimer.second_queue))
- SStimer.bucket_count--
-
- if (prev == next && next)
- next.prev = null
- prev.next = null
- else
- if (prev)
- prev.next = next
- if (next)
- next.prev = prev
+ bucketEject()
else
if (prev && prev.next == src)
prev.next = next
@@ -440,6 +390,64 @@ SUBSYSTEM_DEF(timer)
prev = null
return QDEL_HINT_IWILLGC
+/datum/timedevent/proc/bucketEject()
+ var/bucketpos = BUCKET_POS(src)
+ var/list/bucket_list = SStimer.bucket_list
+ var/list/second_queue = SStimer.second_queue
+ var/datum/timedevent/buckethead
+ if(bucketpos > 0)
+ buckethead = bucket_list[bucketpos]
+ if(buckethead == src)
+ bucket_list[bucketpos] = next
+ SStimer.bucket_count--
+ else if(timeToRun < TIMER_MAX || next || prev)
+ SStimer.bucket_count--
+ else
+ var/l = length(second_queue)
+ second_queue -= src
+ if(l == length(second_queue))
+ SStimer.bucket_count--
+ if(prev != next)
+ prev.next = next
+ next.prev = prev
+ else
+ prev?.next = null
+ next?.prev = null
+ prev = next = null
+
+/datum/timedevent/proc/bucketJoin()
+ var/list/L
+
+ if (flags & TIMER_CLIENT_TIME)
+ L = SStimer.clienttime_timers
+ else if (timeToRun >= TIMER_MAX)
+ L = SStimer.second_queue
+
+ if(L)
+ BINARY_INSERT(src, L, datum/timedevent, timeToRun)
+ return
+
+ //get the list of buckets
+ var/list/bucket_list = SStimer.bucket_list
+
+ //calculate our place in the bucket list
+ var/bucket_pos = BUCKET_POS(src)
+
+ //get the bucket for our tick
+ var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
+ SStimer.bucket_count++
+ //empty bucket, we will just add ourselves
+ if (!bucket_head)
+ bucket_list[bucket_pos] = src
+ return
+ //other wise, lets do a simplified linked list add.
+ if (!bucket_head.prev)
+ bucket_head.prev = bucket_head
+ next = bucket_head
+ prev = bucket_head.prev
+ next.prev = src
+ prev.next = src
+
/datum/timedevent/proc/getcallingtype()
. = "ERROR"
if (callBack.object == GLOBAL_PROC)
@@ -488,12 +496,7 @@ SUBSYSTEM_DEF(timer)
else if(flags & TIMER_OVERRIDE)
stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE")
-
- var/timeToRun = world.time + wait
- if (flags & TIMER_CLIENT_TIME)
- timeToRun = REALTIMEOFDAY + wait
-
- var/datum/timedevent/timer = new(callback, timeToRun, flags, hash)
+ var/datum/timedevent/timer = new(callback, wait, flags, hash)
return timer.id
/proc/deltimer(id)
@@ -512,9 +515,6 @@ SUBSYSTEM_DEF(timer)
return TRUE
return FALSE
-/datum/controller/subsystem/timer/proc/tump_buckets()
- reset_buckets()
- SSticker.tumpedbuckets = TRUE
#undef BUCKET_LEN
#undef BUCKET_POS
diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm
index fb92fc37ab..39f2eaf08b 100644
--- a/code/controllers/subsystem/traumas.dm
+++ b/code/controllers/subsystem/traumas.dm
@@ -14,7 +14,7 @@ SUBSYSTEM_DEF(traumas)
//phobia types is to pull from randomly for brain traumas, e.g. conspiracies is for special assignment only
phobia_types = list("spiders", "space", "security", "clowns", "greytide", "lizards",
"skeletons", "snakes", "robots", "doctors", "authority", "the supernatural",
- "aliens", "strangers", "birds", "falling")
+ "aliens", "strangers", "birds", "falling", "anime")
phobia_words = list("spiders" = strings(PHOBIA_FILE, "spiders"),
"space" = strings(PHOBIA_FILE, "space"),
@@ -32,7 +32,8 @@ SUBSYSTEM_DEF(traumas)
"strangers" = strings(PHOBIA_FILE, "strangers"),
"conspiracies" = strings(PHOBIA_FILE, "conspiracies"),
"birds" = strings(PHOBIA_FILE, "birds"),
- "falling" = strings(PHOBIA_FILE, "falling")
+ "falling" = strings(PHOBIA_FILE, "falling"),
+ "anime" = strings(PHOBIA_FILE, "anime")
)
phobia_mobs = list("spiders" = typecacheof(list(/mob/living/simple_animal/hostile/poison/giant_spider)),
@@ -50,7 +51,8 @@ SUBSYSTEM_DEF(traumas)
"conspiracies" = typecacheof(list(/mob/living/simple_animal/bot/secbot, /mob/living/simple_animal/bot/ed209, /mob/living/simple_animal/drone,
/mob/living/simple_animal/pet/penguin)),
"birds" = typecacheof(list(/mob/living/simple_animal/parrot, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken,
- /mob/living/simple_animal/pet/penguin))
+ /mob/living/simple_animal/pet/penguin)),
+ "anime" = typecacheof(list(/mob/living/simple_animal/hostile/guardian))
)
phobia_objs = list("snakes" = typecacheof(list(/obj/item/rod_of_asclepius)),
@@ -135,9 +137,14 @@ SUBSYSTEM_DEF(traumas)
/obj/item/clothing/suit/chickensuit, /obj/item/clothing/head/chicken,
/obj/item/clothing/suit/toggle/owlwings, /obj/item/clothing/under/owl, /obj/item/clothing/mask/gas/owl_mask,
/obj/item/clothing/under/griffin, /obj/item/clothing/shoes/griffin, /obj/item/clothing/head/griffin,
- /obj/item/clothing/head/helmet/space/freedom, /obj/item/clothing/suit/space/freedom))
- )
-
+ /obj/item/clothing/head/helmet/space/freedom, /obj/item/clothing/suit/space/freedom)),
+
+ "anime" = typecacheof(list(/obj/item/clothing/under/schoolgirl, /obj/item/katana, /obj/item/reagent_containers/food/snacks/sashimi, /obj/item/reagent_containers/food/snacks/chawanmushi,
+ /obj/item/reagent_containers/food/drinks/bottle/sake, /obj/item/throwing_star, /obj/item/clothing/head/kitty/genuine, /obj/item/clothing/suit/space/space_ninja,
+ /obj/item/clothing/mask/gas/space_ninja, /obj/item/clothing/shoes/space_ninja, /obj/item/clothing/gloves/space_ninja, /obj/item/twohanded/vibro_weapon,
+ /obj/item/nullrod/scythe/vibro, /obj/item/energy_katana, /obj/item/toy/katana, /obj/item/nullrod/claymore/katana, /obj/structure/window/paperframe, /obj/structure/mineral_door/paperframe))
+ )
+
phobia_turfs = list("space" = typecacheof(list(/turf/open/space, /turf/open/floor/holofloor/space, /turf/open/floor/fakespace)),
"the supernatural" = typecacheof(list(/turf/open/floor/clockwork, /turf/closed/wall/clockwork,
/turf/open/floor/plasteel/cult, /turf/closed/wall/mineral/cult)),
@@ -146,14 +153,15 @@ SUBSYSTEM_DEF(traumas)
"falling" = typecacheof(list(/turf/open/chasm, /turf/open/floor/fakepit))
)
- phobia_species = list("lizards" = typecacheof(list(/datum/species/lizard)),
+ phobia_species = list("lizards" = typecacheof(list(/datum/species/lizard)),
"skeletons" = typecacheof(list(/datum/species/skeleton, /datum/species/plasmaman)),
"conspiracies" = typecacheof(list(/datum/species/abductor, /datum/species/lizard, /datum/species/synth)),
- "robots" = typecacheof(list(/datum/species/android)),
+ "robots" = typecacheof(list(/datum/species/android)),
"the supernatural" = typecacheof(list(/datum/species/golem/clockwork, /datum/species/golem/runic)),
"aliens" = typecacheof(list(/datum/species/abductor, /datum/species/jelly, /datum/species/pod,
- /datum/species/shadow))
- )
+ /datum/species/shadow)),
+ "anime" = typecacheof(list(/datum/species/human/felinid))
+ )
return ..()
diff --git a/code/controllers/subsystem/vis_overlays.dm b/code/controllers/subsystem/vis_overlays.dm
new file mode 100644
index 0000000000..435414a899
--- /dev/null
+++ b/code/controllers/subsystem/vis_overlays.dm
@@ -0,0 +1,75 @@
+SUBSYSTEM_DEF(vis_overlays)
+ name = "Vis contents overlays"
+ wait = 1 MINUTES
+ priority = FIRE_PRIORITY_VIS
+ init_order = INIT_ORDER_VIS
+
+ var/list/vis_overlay_cache
+ var/list/currentrun
+ var/datum/callback/rotate_cb
+
+/datum/controller/subsystem/vis_overlays/Initialize()
+ vis_overlay_cache = list()
+ rotate_cb = CALLBACK(src, .proc/rotate_vis_overlay)
+ return ..()
+
+/datum/controller/subsystem/vis_overlays/fire(resumed = FALSE)
+ if(!resumed)
+ currentrun = vis_overlay_cache.Copy()
+ var/list/current_run = currentrun
+
+ while(current_run.len)
+ var/key = current_run[current_run.len]
+ var/obj/effect/overlay/vis/overlay = current_run[key]
+ current_run.len--
+ if(!overlay.unused && !length(overlay.vis_locs))
+ overlay.unused = world.time
+ else if(overlay.unused && overlay.unused + overlay.cache_expiration < world.time)
+ vis_overlay_cache -= key
+ qdel(overlay)
+ if(MC_TICK_CHECK)
+ return
+
+//the "thing" var can be anything with vis_contents which includes images
+/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha=255)
+ . = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]"
+ var/obj/effect/overlay/vis/overlay = vis_overlay_cache[.]
+ if(!overlay)
+ overlay = new
+ overlay.icon = icon
+ overlay.icon_state = iconstate
+ overlay.layer = layer
+ overlay.plane = plane
+ overlay.dir = dir
+ overlay.alpha = alpha
+ vis_overlay_cache[.] = overlay
+ else
+ overlay.unused = 0
+ thing.vis_contents += overlay
+
+ if(!isatom(thing)) // Automatic rotation is not supported on non atoms
+ return
+
+ if(!thing.managed_vis_overlays)
+ thing.managed_vis_overlays = list(overlay)
+ RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, rotate_cb)
+ else
+ thing.managed_vis_overlays += overlay
+
+/datum/controller/subsystem/vis_overlays/proc/remove_vis_overlay(atom/movable/thing, list/overlays)
+ thing.vis_contents -= overlays
+ if(!isatom(thing))
+ return
+ thing.managed_vis_overlays -= overlays
+ if(!length(thing.managed_vis_overlays))
+ thing.managed_vis_overlays = null
+ UnregisterSignal(thing, COMSIG_ATOM_DIR_CHANGE)
+
+/datum/controller/subsystem/vis_overlays/proc/rotate_vis_overlay(atom/thing, old_dir, new_dir)
+ var/rotation = dir2angle(old_dir) - dir2angle(new_dir)
+ var/list/overlays_to_remove = list()
+ for(var/i in thing.managed_vis_overlays)
+ var/obj/effect/overlay/vis/overlay = i
+ add_vis_overlay(thing, overlay.icon, overlay.icon_state, overlay.layer, overlay.plane, turn(overlay.dir, rotation))
+ overlays_to_remove += overlay
+ remove_vis_overlay(thing, overlays_to_remove)
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index 0d5a68f027..2391b4c839 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -45,7 +45,7 @@ SUBSYSTEM_DEF(weather)
for(var/z in SSmapping.levels_by_trait(target_trait))
LAZYINITLIST(eligible_zlevels["[z]"])
eligible_zlevels["[z]"][W] = probability
- ..()
+ return ..()
/datum/controller/subsystem/weather/proc/run_weather(datum/weather/weather_datum_type, z_levels)
if (istext(weather_datum_type))