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