controllers sync
This commit is contained in:
@@ -53,8 +53,9 @@
|
||||
. = !(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "ValidateAndSet" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
|
||||
if(!.)
|
||||
log_admin_private("Config set of [type] to [str_val] attempted by [key_name(usr)]")
|
||||
|
||||
|
||||
/datum/config_entry/proc/ValidateAndSet(str_val)
|
||||
VASProcCallGuard(str_val)
|
||||
CRASH("Invalid config entry type!")
|
||||
|
||||
/datum/config_entry/proc/ValidateKeyedList(str_val, list_mode, splitter)
|
||||
@@ -78,12 +79,12 @@
|
||||
if(LIST_MODE_TEXT)
|
||||
temp = key_value
|
||||
continue_check = temp
|
||||
if(continue_check && ValidateKeyName(key_name))
|
||||
if(continue_check && ValidateListEntry(key_name, temp))
|
||||
value[key_name] = temp
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/config_entry/proc/ValidateKeyName(key_name)
|
||||
/datum/config_entry/proc/ValidateListEntry(key_name, key_value)
|
||||
return TRUE
|
||||
|
||||
/datum/config_entry/string
|
||||
@@ -95,6 +96,8 @@
|
||||
return var_name != "auto_trim" && ..()
|
||||
|
||||
/datum/config_entry/string/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
value = auto_trim ? trim(str_val) : str_val
|
||||
return TRUE
|
||||
|
||||
@@ -106,6 +109,8 @@
|
||||
var/min_val = -INFINITY
|
||||
|
||||
/datum/config_entry/number/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
var/temp = text2num(trim(str_val))
|
||||
if(!isnull(temp))
|
||||
value = CLAMP(integer ? round(temp) : temp, min_val, max_val)
|
||||
@@ -123,6 +128,8 @@
|
||||
abstract_type = /datum/config_entry/flag
|
||||
|
||||
/datum/config_entry/flag/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
value = text2num(trim(str_val)) != 0
|
||||
return TRUE
|
||||
|
||||
@@ -131,6 +138,8 @@
|
||||
value = list()
|
||||
|
||||
/datum/config_entry/number_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
str_val = trim(str_val)
|
||||
var/list/new_list = list()
|
||||
var/list/values = splittext(str_val," ")
|
||||
@@ -150,6 +159,8 @@
|
||||
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
|
||||
@@ -162,6 +173,8 @@
|
||||
return var_name != "splitter" && ..()
|
||||
|
||||
/datum/config_entry/keyed_number_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
return ValidateKeyedList(str_val, LIST_MODE_NUM, splitter)
|
||||
|
||||
/datum/config_entry/keyed_string_list
|
||||
@@ -174,6 +187,8 @@
|
||||
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
|
||||
|
||||
@@ -97,19 +97,13 @@ GLOBAL_PROTECT(config_dir)
|
||||
|
||||
if(!entry)
|
||||
continue
|
||||
if(entry == "$include")
|
||||
if(!value)
|
||||
log_config("Warning: Invalid $include directive: [value]")
|
||||
else
|
||||
LoadEntries(value, stack)
|
||||
++.
|
||||
continue
|
||||
|
||||
if(entry == "$include")
|
||||
if(!value)
|
||||
log_config("Warning: Invalid $include directive: [value]")
|
||||
else
|
||||
LoadEntries(value, stack)
|
||||
++.
|
||||
continue
|
||||
|
||||
var/datum/config_entry/E = _entries[entry]
|
||||
|
||||
@@ -2,13 +2,21 @@
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
|
||||
/datum/config_entry/string/comms_key/ValidateAndSet(str_val)
|
||||
return str_val != "default_pwd" && length(str_val) > 6 && ..()
|
||||
return str_val != "default_pwd" && length(str_val) > 6 && ..()
|
||||
|
||||
/datum/config_entry/keyed_string_list/cross_server
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/datum/config_entry/string/cross_server_address/ValidateAndSet(str_val)
|
||||
return str_val != "byond:\\address:port" && ..()
|
||||
/datum/config_entry/keyed_string_list/cross_server/ValidateAndSet(str_val)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/list/newv = list()
|
||||
for(var/I in value)
|
||||
newv[replacetext(I, "+", " ")] = value[I]
|
||||
value = newv
|
||||
|
||||
/datum/config_entry/keyed_string_list/cross_server/ValidateListEntry(key_name, key_value)
|
||||
return key_value != "byond:\\address:port" && ..()
|
||||
|
||||
/datum/config_entry/string/cross_comms_name
|
||||
|
||||
@@ -17,4 +25,4 @@ GLOBAL_VAR_INIT(medals_enabled, TRUE) //will be auto set to false if the game fa
|
||||
/datum/config_entry/string/medal_hub_address
|
||||
|
||||
/datum/config_entry/string/medal_hub_password
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
@@ -2,27 +2,27 @@
|
||||
|
||||
/datum/config_entry/keyed_number_list/probability
|
||||
|
||||
/datum/config_entry/keyed_number_list/probability/ValidateKeyName(key_name)
|
||||
/datum/config_entry/keyed_number_list/probability/ValidateListEntry(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
/datum/config_entry/keyed_number_list/max_pop
|
||||
|
||||
/datum/config_entry/keyed_number_list/max_pop/ValidateKeyName(key_name)
|
||||
/datum/config_entry/keyed_number_list/max_pop/ValidateListEntry(key_name)
|
||||
return key_name in config.modes
|
||||
|
||||
/datum/config_entry/keyed_number_list/min_pop
|
||||
|
||||
/datum/config_entry/keyed_number_list/min_pop/ValidateKeyName(key_name)
|
||||
/datum/config_entry/keyed_number_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_flag_list/continuous/ValidateKeyName(key_name)
|
||||
/datum/config_entry/keyed_flag_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_flag_list/midround_antag/ValidateKeyName(key_name)
|
||||
/datum/config_entry/keyed_flag_list/midround_antag/ValidateListEntry(key_name, key_value)
|
||||
return key_name in config.modes
|
||||
|
||||
/datum/config_entry/keyed_string_list/policy
|
||||
|
||||
@@ -394,4 +394,4 @@ SUBSYSTEM_DEF(air)
|
||||
#undef SSAIR_EXCITEDGROUPS
|
||||
#undef SSAIR_HIGHPRESSURE
|
||||
#undef SSAIR_HOTSPOT
|
||||
#undef SSAIR_SUPERCONDUCTIVITY
|
||||
#undef SSAIR_SUPERCONDUCTIVITY
|
||||
|
||||
@@ -8,11 +8,10 @@ SUBSYSTEM_DEF(blackbox)
|
||||
var/list/feedback = list() //list of datum/feedback_variable
|
||||
var/triggertime = 0
|
||||
var/sealed = FALSE //time to stop tracking stats?
|
||||
var/list/research_levels = list() //list of highest tech levels attained that isn't lost lost by destruction of RD computers
|
||||
var/list/versions = list("time_dilation_current" = 2,
|
||||
"science_techweb_unlock" = 2,
|
||||
"antagonists" = 3) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
|
||||
|
||||
var/list/versions = list("antagonists" = 3,
|
||||
"admin_secrets_fun_used" = 2,
|
||||
"time_dilation_current" = 3,
|
||||
"science_techweb_unlock" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
|
||||
|
||||
/datum/controller/subsystem/blackbox/Initialize()
|
||||
triggertime = world.time
|
||||
@@ -59,13 +58,11 @@ SUBSYSTEM_DEF(blackbox)
|
||||
/datum/controller/subsystem/blackbox/Shutdown()
|
||||
sealed = FALSE
|
||||
record_feedback("tally", "ahelp_stats", GLOB.ahelp_tickets.active_tickets.len, "unresolved")
|
||||
for (var/obj/machinery/message_server/MS in GLOB.message_servers)
|
||||
for (var/obj/machinery/telecomms/message_server/MS in GLOB.telecomms_list)
|
||||
if (MS.pda_msgs.len)
|
||||
record_feedback("tally", "radio_usage", MS.pda_msgs.len, "PDA")
|
||||
if (MS.rc_msgs.len)
|
||||
record_feedback("tally", "radio_usage", MS.rc_msgs.len, "request console")
|
||||
if(research_levels.len)
|
||||
SSblackbox.record_feedback("associative", "high_research_level", 1, research_levels)
|
||||
|
||||
if (!SSdbcore.Connect())
|
||||
return
|
||||
@@ -92,39 +89,35 @@ SUBSYSTEM_DEF(blackbox)
|
||||
sealed = TRUE
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/blackbox/proc/log_research(tech, level)
|
||||
if(!(tech in research_levels) || research_levels[tech] < level)
|
||||
research_levels[tech] = level
|
||||
|
||||
/datum/controller/subsystem/blackbox/proc/LogBroadcast(freq)
|
||||
if(sealed)
|
||||
return
|
||||
switch(freq)
|
||||
if(1459)
|
||||
if(FREQ_COMMON)
|
||||
record_feedback("tally", "radio_usage", 1, "common")
|
||||
if(GLOB.SCI_FREQ)
|
||||
if(FREQ_SCIENCE)
|
||||
record_feedback("tally", "radio_usage", 1, "science")
|
||||
if(GLOB.COMM_FREQ)
|
||||
if(FREQ_COMMAND)
|
||||
record_feedback("tally", "radio_usage", 1, "command")
|
||||
if(GLOB.MED_FREQ)
|
||||
if(FREQ_MEDICAL)
|
||||
record_feedback("tally", "radio_usage", 1, "medical")
|
||||
if(GLOB.ENG_FREQ)
|
||||
if(FREQ_ENGINEERING)
|
||||
record_feedback("tally", "radio_usage", 1, "engineering")
|
||||
if(GLOB.SEC_FREQ)
|
||||
if(FREQ_SECURITY)
|
||||
record_feedback("tally", "radio_usage", 1, "security")
|
||||
if(GLOB.SYND_FREQ)
|
||||
if(FREQ_SYNDICATE)
|
||||
record_feedback("tally", "radio_usage", 1, "syndicate")
|
||||
if(GLOB.SERV_FREQ)
|
||||
if(FREQ_SERVICE)
|
||||
record_feedback("tally", "radio_usage", 1, "service")
|
||||
if(GLOB.SUPP_FREQ)
|
||||
if(FREQ_SUPPLY)
|
||||
record_feedback("tally", "radio_usage", 1, "supply")
|
||||
if(GLOB.CENTCOM_FREQ)
|
||||
if(FREQ_CENTCOM)
|
||||
record_feedback("tally", "radio_usage", 1, "centcom")
|
||||
if(GLOB.AIPRIV_FREQ)
|
||||
if(FREQ_AI_PRIVATE)
|
||||
record_feedback("tally", "radio_usage", 1, "ai private")
|
||||
if(GLOB.REDTEAM_FREQ)
|
||||
if(FREQ_CTF_RED)
|
||||
record_feedback("tally", "radio_usage", 1, "CTF red team")
|
||||
if(GLOB.BLUETEAM_FREQ)
|
||||
if(FREQ_CTF_BLUE)
|
||||
record_feedback("tally", "radio_usage", 1, "CTF blue team")
|
||||
else
|
||||
record_feedback("tally", "radio_usage", 1, "other")
|
||||
@@ -194,7 +187,7 @@ Versioning
|
||||
"gun_fired" = 2)
|
||||
*/
|
||||
/datum/controller/subsystem/blackbox/proc/record_feedback(key_type, key, increment, data, overwrite)
|
||||
if(sealed || !key_type || !istext(key) || !isnum(increment || !data))
|
||||
if(sealed || !key_type || !istext(key) || !isnum(increment) || !data)
|
||||
return
|
||||
var/datum/feedback_variable/FV = find_feedback_datum(key, key_type)
|
||||
switch(key_type)
|
||||
|
||||
@@ -41,4 +41,3 @@ SUBSYSTEM_DEF(idlenpcpool)
|
||||
SA.consider_wakeup()
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
|
||||
@@ -1,10 +1,101 @@
|
||||
SUBSYSTEM_DEF(input)
|
||||
name = "Input"
|
||||
wait = 1 //SS_TICKER means this runs every tick
|
||||
flags = SS_TICKER | SS_NO_INIT
|
||||
init_order = INIT_ORDER_INPUT
|
||||
flags = SS_TICKER
|
||||
priority = FIRE_PRIORITY_INPUT
|
||||
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
|
||||
|
||||
var/list/macro_sets
|
||||
|
||||
/datum/controller/subsystem/input/Initialize()
|
||||
setup_default_macro_sets()
|
||||
|
||||
initialized = TRUE
|
||||
|
||||
refresh_client_macro_sets()
|
||||
|
||||
return ..()
|
||||
|
||||
// This is for when macro sets are eventualy datumized
|
||||
/datum/controller/subsystem/input/proc/setup_default_macro_sets()
|
||||
var/list/static/default_macro_sets
|
||||
|
||||
if(default_macro_sets)
|
||||
macro_sets = default_macro_sets
|
||||
return
|
||||
|
||||
default_macro_sets = list(
|
||||
"default" = list(
|
||||
"Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=[COLOR_INPUT_DISABLED]:input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"O" = "ooc",
|
||||
"T" = "say",
|
||||
"M" = "me",
|
||||
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
),
|
||||
"old_default" = list(
|
||||
"Tab" = "\".winset \\\"mainwindow.macro=old_hotkeys map.focus=true input.background-color=[COLOR_INPUT_DISABLED]\\\"\"",
|
||||
"Ctrl+T" = "say",
|
||||
"Ctrl+O" = "ooc",
|
||||
),
|
||||
"old_hotkeys" = list(
|
||||
"Tab" = "\".winset \\\"mainwindow.macro=old_default input.focus=true input.background-color=[COLOR_INPUT_ENABLED]\\\"\"",
|
||||
"O" = "ooc",
|
||||
"T" = "say",
|
||||
"M" = "me",
|
||||
"Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
|
||||
"Any" = "\"KeyDown \[\[*\]\]\"",
|
||||
"Any+UP" = "\"KeyUp \[\[*\]\]\"",
|
||||
),
|
||||
)
|
||||
|
||||
// Because i'm lazy and don't want to type all these out twice
|
||||
var/list/old_default = default_macro_sets["old_default"]
|
||||
|
||||
var/list/static/oldmode_keys = list(
|
||||
"North", "East", "South", "West",
|
||||
"Northeast", "Southeast", "Northwest", "Southwest",
|
||||
"Insert", "Delete", "Ctrl", "Alt",
|
||||
"F1", "F2", "F5", "F6", "F7", "F8", "F12",
|
||||
)
|
||||
|
||||
for(var/i in 1 to oldmode_keys.len)
|
||||
var/key = oldmode_keys[i]
|
||||
old_default[key] = "\"KeyDown [key]\""
|
||||
old_default["[key]+UP"] = "\"KeyUp [key]\""
|
||||
|
||||
var/list/static/oldmode_ctrl_override_keys = list(
|
||||
"W" = "W", "A" = "A", "S" = "S", "D" = "D", // movement
|
||||
"1" = "1", "2" = "2", "3" = "3", "4" = "4", // intent
|
||||
"B" = "B", // resist
|
||||
"E" = "E", // quick equip
|
||||
"F" = "F", // intent left
|
||||
"G" = "G", // intent right
|
||||
"H" = "H", // stop pulling
|
||||
"Q" = "Q", // drop
|
||||
"R" = "R", // throw
|
||||
"X" = "X", // switch hands
|
||||
"Y" = "Y", // activate item
|
||||
"Z" = "Z", // activate item
|
||||
)
|
||||
|
||||
for(var/i in 1 to oldmode_ctrl_override_keys.len)
|
||||
var/key = oldmode_ctrl_override_keys[i]
|
||||
var/override = oldmode_ctrl_override_keys[key]
|
||||
old_default["Ctrl+[key]"] = "\"KeyDown [override]\""
|
||||
old_default["Ctrl+[key]+UP"] = "\"KeyUp [override]\""
|
||||
|
||||
macro_sets = default_macro_sets
|
||||
|
||||
// Badmins just wanna have fun ♪
|
||||
/datum/controller/subsystem/input/proc/refresh_client_macro_sets()
|
||||
var/list/clients = GLOB.clients
|
||||
for(var/i in 1 to clients.len)
|
||||
var/client/user = clients[i]
|
||||
user.set_macros()
|
||||
|
||||
/datum/controller/subsystem/input/fire()
|
||||
var/list/clients = GLOB.clients // Let's sing the list cache song
|
||||
for(var/i in 1 to clients.len)
|
||||
|
||||
@@ -107,9 +107,6 @@ SUBSYSTEM_DEF(job)
|
||||
if(player.mind && job.title in player.mind.restricted_roles)
|
||||
Debug("FOC incompatible with antagonist role, Player: [player]")
|
||||
continue
|
||||
if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
Debug("FOC non-human failed, Player: [player]")
|
||||
continue
|
||||
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
|
||||
Debug("FOC pass, Player: [player], Level:[level]")
|
||||
candidates += player
|
||||
@@ -144,11 +141,6 @@ SUBSYSTEM_DEF(job)
|
||||
Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]")
|
||||
continue
|
||||
|
||||
if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
Debug("GRJ non-human failed, Player: [player]")
|
||||
continue
|
||||
|
||||
|
||||
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
|
||||
Debug("GRJ Random job given, Player: [player], Job: [job]")
|
||||
if(AssignRole(player, job.title))
|
||||
@@ -319,10 +311,6 @@ SUBSYSTEM_DEF(job)
|
||||
Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
|
||||
Debug("DO non-human failed, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
// If the player wants that job on this level, then try give it to him.
|
||||
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
|
||||
|
||||
@@ -424,7 +412,8 @@ SUBSYSTEM_DEF(job)
|
||||
|
||||
if(job && H)
|
||||
job.after_spawn(H, M)
|
||||
handle_roundstart_items(H, M.ckey, H.mind.assigned_role, H.mind.special_role)
|
||||
handle_roundstart_items(H, M.ckey, H.mind.assigned_role, H.mind.special_role) //CIT CHANGE - makes donators spawn with their items
|
||||
|
||||
return H
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ SUBSYSTEM_DEF(lighting)
|
||||
|
||||
create_all_lighting_objects()
|
||||
initialized = TRUE
|
||||
|
||||
|
||||
fire(FALSE, TRUE)
|
||||
|
||||
..()
|
||||
|
||||
@@ -62,4 +62,4 @@ SUBSYSTEM_DEF(machines)
|
||||
if (istype(SSmachines.processing))
|
||||
processing = SSmachines.processing
|
||||
if (istype(SSmachines.powernets))
|
||||
powernets = SSmachines.powernets
|
||||
powernets = SSmachines.powernets
|
||||
|
||||
@@ -135,12 +135,12 @@ SUBSYSTEM_DEF(npcpool)
|
||||
|
||||
if(facCount == 1 && helpProb)
|
||||
helpProb = 100
|
||||
|
||||
|
||||
if(prob(helpProb) && candidate.takeDelegate(check,FALSE))
|
||||
--canBeUsed.len
|
||||
candidate.eye_color = "yellow"
|
||||
candidate.update_icons()
|
||||
|
||||
|
||||
if(!currentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary
|
||||
return
|
||||
|
||||
|
||||
@@ -40,3 +40,5 @@ SUBSYSTEM_DEF(orbit)
|
||||
O.Check(targetloc)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -250,4 +250,4 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = saved_modes
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
@@ -14,35 +14,22 @@ SUBSYSTEM_DEF(radio)
|
||||
/datum/controller/subsystem/radio/proc/add_object(obj/device, new_frequency as num, filter = null as text|null)
|
||||
var/f_text = num2text(new_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(!frequency)
|
||||
frequency = new
|
||||
frequency.frequency = new_frequency
|
||||
frequencies[f_text] = frequency
|
||||
|
||||
frequencies[f_text] = frequency = new(new_frequency)
|
||||
frequency.add_listener(device, filter)
|
||||
return frequency
|
||||
|
||||
/datum/controller/subsystem/radio/proc/remove_object(obj/device, old_frequency)
|
||||
var/f_text = num2text(old_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(frequency)
|
||||
frequency.remove_listener(device)
|
||||
|
||||
if(frequency.devices.len == 0)
|
||||
qdel(frequency)
|
||||
frequencies -= f_text
|
||||
|
||||
// let's don't delete frequencies in case a non-listener keeps a reference
|
||||
return 1
|
||||
|
||||
/datum/controller/subsystem/radio/proc/return_frequency(new_frequency as num)
|
||||
var/f_text = num2text(new_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(!frequency)
|
||||
frequency = new
|
||||
frequency.frequency = new_frequency
|
||||
frequencies[f_text] = frequency
|
||||
|
||||
frequencies[f_text] = frequency = new(new_frequency)
|
||||
return frequency
|
||||
|
||||
@@ -54,6 +54,7 @@ SUBSYSTEM_DEF(research)
|
||||
bitcoins = single_server_income
|
||||
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
|
||||
bitcoins *= income_time_difference / 10
|
||||
science_tech.research_points += bitcoins
|
||||
last_income = world.time
|
||||
|
||||
@@ -54,7 +54,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
var/lockdown = FALSE //disallow transit after nuke goes off
|
||||
|
||||
var/auto_call = 99000 //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 = 99000 //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.
|
||||
|
||||
/datum/controller/subsystem/shuttle/Initialize(timeofday)
|
||||
if(!arrivals)
|
||||
@@ -158,7 +158,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
break
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/CheckAutoEvac()
|
||||
if(emergencyNoEscape || emergencyNoRecall || !emergency)
|
||||
if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted())
|
||||
return
|
||||
|
||||
var/threshold = CONFIG_GET(number/emergency_shuttle_autocall_threshold)
|
||||
@@ -261,7 +261,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
if(!admiral_message)
|
||||
admiral_message = pick(GLOB.admiral_messages)
|
||||
var/intercepttext = "<font size = 3><b>NanoTrasen Update</b>: Request For Shuttle.</font><hr>\
|
||||
var/intercepttext = "<font size = 3><b>Nanotrasen Update</b>: Request For Shuttle.</font><hr>\
|
||||
To whom it may concern:<br><br>\
|
||||
We have taken note of the situation upon [station_name()] and have come to the \
|
||||
conclusion that it does not warrant the abandonment of the station.<br>\
|
||||
@@ -385,7 +385,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
emergency.setTimer(emergencyDockTime)
|
||||
priority_announce("Hostile environment resolved. \
|
||||
You have 3 minutes to board the Emergency Shuttle.",
|
||||
null, 'sound/AI/shuttledock.ogg', "Priority")
|
||||
null, 'sound/ai/shuttledock.ogg', "Priority")
|
||||
|
||||
//try to move/request to dockHome if possible, otherwise dockAway. Mainly used for admin buttons
|
||||
/datum/controller/subsystem/shuttle/proc/toggleShuttle(shuttleId, dockHome, dockAway, timed)
|
||||
@@ -429,7 +429,8 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(!(M in transit_requesters))
|
||||
transit_requesters += M
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/autoEnd()
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/autoEnd() //CIT CHANGE - allows shift to end after 3 hours has passed.
|
||||
if(world.time > auto_call && EMERGENCY_IDLE_OR_RECALLED) //3 hours
|
||||
SSshuttle.emergency.request(null, 1.5)
|
||||
priority_announce("The shift has come to an end and the shuttle called.")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// The Squeak
|
||||
// because this is about placement of mice mobs, and nothing to do with
|
||||
// mice - the computer peripheral
|
||||
// mice - the computer peripheral
|
||||
|
||||
SUBSYSTEM_DEF(squeak)
|
||||
name = "Squeak"
|
||||
|
||||
@@ -27,6 +27,6 @@ SUBSYSTEM_DEF(stickyban)
|
||||
ban["existing_user_matches_this_round"] = list()
|
||||
ban["admin_matches_this_round"] = list()
|
||||
cache[ckey] = ban
|
||||
|
||||
|
||||
for (var/bannedckey in cache)
|
||||
world.SetConfig("ban", bannedckey, list2stickyban(cache[bannedckey]))
|
||||
|
||||
@@ -631,6 +631,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
world.Reboot()
|
||||
|
||||
/datum/controller/subsystem/ticker/Shutdown()
|
||||
gather_newscaster() //called here so we ensure the log is created even upon admin reboot
|
||||
if(!round_end_sound)
|
||||
round_end_sound = pick(\
|
||||
'sound/roundend/newroundsexy.ogg',
|
||||
|
||||
@@ -35,4 +35,4 @@ SUBSYSTEM_DEF(time_track)
|
||||
last_tick_realtime = current_realtime
|
||||
last_tick_byond_time = current_byondtime
|
||||
last_tick_tickcount = current_tickcount
|
||||
SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[time_dilation_current]" = "[SQLtime()]"))
|
||||
SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[SQLtime()]" = list("current" = "[time_dilation_current]", "avg_fast" = "[time_dilation_avg_fast]", "avg" = "[time_dilation_avg]", "avg_slow" = "[time_dilation_avg_slow]")))
|
||||
|
||||
+200
-101
@@ -1,5 +1,6 @@
|
||||
#define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth)
|
||||
#define BUCKET_POS(timer) (round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) + 1)
|
||||
#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN) + 1)
|
||||
#define TIMER_MAX (world.time + TICKS2DS(min(BUCKET_LEN-(SStimer.practical_offset-DS2TICKS(world.time - SStimer.head_offset))-1, BUCKET_LEN-1)))
|
||||
#define TIMER_ID_MAX (2**24) //max float with integer precision
|
||||
|
||||
SUBSYSTEM_DEF(timer)
|
||||
@@ -9,11 +10,11 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
flags = SS_TICKER|SS_NO_INIT
|
||||
|
||||
var/list/datum/timedevent/processing = list()
|
||||
var/list/datum/timedevent/second_queue = list() //awe, yes, you've had first queue, but what about second queue?
|
||||
var/list/hashes = list()
|
||||
|
||||
var/head_offset = 0 //world.time of the first entry in the the bucket.
|
||||
var/practical_offset = 0 //index of the first non-empty item in the bucket.
|
||||
var/practical_offset = 1 //index of the first non-empty item in the bucket.
|
||||
var/bucket_resolution = 0 //world.tick_lag the bucket was designed for
|
||||
var/bucket_count = 0 //how many timers are in the buckets
|
||||
|
||||
@@ -27,13 +28,19 @@ SUBSYSTEM_DEF(timer)
|
||||
var/static/last_invoke_warning = 0
|
||||
var/static/bucket_auto_reset = TRUE
|
||||
|
||||
/datum/controller/subsystem/timer/PreInit()
|
||||
bucket_list.len = BUCKET_LEN
|
||||
head_offset = world.time
|
||||
bucket_resolution = world.tick_lag
|
||||
|
||||
/datum/controller/subsystem/timer/stat_entry(msg)
|
||||
..("B:[bucket_count] P:[length(processing)] H:[length(hashes)] C:[length(clienttime_timers)]")
|
||||
..("B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)]")
|
||||
|
||||
/datum/controller/subsystem/timer/fire(resumed = FALSE)
|
||||
var/lit = last_invoke_tick
|
||||
var/last_check = world.time - TIMER_NO_INVOKE_WARNING
|
||||
var/list/bucket_list = src.bucket_list
|
||||
|
||||
if(!bucket_count)
|
||||
last_invoke_tick = world.time
|
||||
|
||||
@@ -60,50 +67,62 @@ SUBSYSTEM_DEF(timer)
|
||||
bucket_node = bucket_node.next
|
||||
anti_loop_check--
|
||||
while(bucket_node && bucket_node != bucket_head && anti_loop_check)
|
||||
log_world("Active timers in the processing queue:")
|
||||
for(var/I in processing)
|
||||
log_world("Active timers in the second_queue queue:")
|
||||
for(var/I in second_queue)
|
||||
log_world(get_timer_debug_string(I))
|
||||
|
||||
while(length(clienttime_timers))
|
||||
var/datum/timedevent/ctime_timer = clienttime_timers[clienttime_timers.len]
|
||||
if (ctime_timer.timeToRun <= REALTIMEOFDAY)
|
||||
--clienttime_timers.len
|
||||
var/datum/callback/callBack = ctime_timer.callBack
|
||||
ctime_timer.spent = REALTIMEOFDAY
|
||||
callBack.InvokeAsync()
|
||||
qdel(ctime_timer)
|
||||
else
|
||||
break //None of the rest are ready to run
|
||||
var/next_clienttime_timer_index = 0
|
||||
var/len = length(clienttime_timers)
|
||||
|
||||
for (next_clienttime_timer_index in 1 to len)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
next_clienttime_timer_index--
|
||||
break
|
||||
var/datum/timedevent/ctime_timer = clienttime_timers[next_clienttime_timer_index]
|
||||
if (ctime_timer.timeToRun > REALTIMEOFDAY)
|
||||
next_clienttime_timer_index--
|
||||
break
|
||||
|
||||
var/datum/callback/callBack = ctime_timer.callBack
|
||||
if (!callBack)
|
||||
clienttime_timers.Cut(next_clienttime_timer_index,next_clienttime_timer_index+1)
|
||||
CRASH("Invalid timer: [get_timer_debug_string(ctime_timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset], REALTIMEOFDAY: [REALTIMEOFDAY]")
|
||||
|
||||
ctime_timer.spent = REALTIMEOFDAY
|
||||
callBack.InvokeAsync()
|
||||
qdel(ctime_timer)
|
||||
|
||||
|
||||
if (next_clienttime_timer_index)
|
||||
clienttime_timers.Cut(1,next_clienttime_timer_index+1)
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
var/static/list/spent = list()
|
||||
var/static/datum/timedevent/timer
|
||||
var/static/datum/timedevent/head
|
||||
if (practical_offset > BUCKET_LEN)
|
||||
head_offset += TICKS2DS(BUCKET_LEN)
|
||||
practical_offset = 1
|
||||
resumed = FALSE
|
||||
|
||||
if (practical_offset > BUCKET_LEN || (!resumed && length(bucket_list) != BUCKET_LEN || world.tick_lag != bucket_resolution))
|
||||
shift_buckets()
|
||||
if ((length(bucket_list) != BUCKET_LEN) || (world.tick_lag != bucket_resolution))
|
||||
reset_buckets()
|
||||
bucket_list = src.bucket_list
|
||||
resumed = FALSE
|
||||
|
||||
|
||||
if (!resumed)
|
||||
timer = null
|
||||
head = null
|
||||
|
||||
while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time && !MC_TICK_CHECK)
|
||||
while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time)
|
||||
var/datum/timedevent/head = bucket_list[practical_offset]
|
||||
if (!timer || !head || timer == head)
|
||||
head = bucket_list[practical_offset]
|
||||
if (!head)
|
||||
practical_offset++
|
||||
if (MC_TICK_CHECK)
|
||||
break
|
||||
continue
|
||||
timer = head
|
||||
do
|
||||
while (timer)
|
||||
var/datum/callback/callBack = timer.callBack
|
||||
if (!callBack)
|
||||
qdel(timer)
|
||||
bucket_resolution = null //force bucket recreation
|
||||
CRASH("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
|
||||
|
||||
@@ -113,15 +132,68 @@ SUBSYSTEM_DEF(timer)
|
||||
callBack.InvokeAsync()
|
||||
last_invoke_tick = world.time
|
||||
|
||||
timer = timer.next
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
while (timer && timer != head)
|
||||
timer = null
|
||||
|
||||
timer = timer.next
|
||||
if (timer == head)
|
||||
break
|
||||
|
||||
|
||||
bucket_list[practical_offset++] = null
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
//we freed up a bucket, lets see if anything in second_queue needs to be shifted to that bucket.
|
||||
var/i = 0
|
||||
var/L = length(second_queue)
|
||||
for (i in 1 to L)
|
||||
timer = second_queue[i]
|
||||
if (timer.timeToRun >= TIMER_MAX)
|
||||
i--
|
||||
break
|
||||
|
||||
if (timer.timeToRun < head_offset)
|
||||
bucket_resolution = null //force bucket recreation
|
||||
CRASH("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
|
||||
|
||||
if (timer.callBack && !timer.spent)
|
||||
timer.callBack.InvokeAsync()
|
||||
spent += timer
|
||||
bucket_count++
|
||||
else if(!QDELETED(timer))
|
||||
qdel(timer)
|
||||
continue
|
||||
|
||||
if (timer.timeToRun < head_offset + TICKS2DS(practical_offset))
|
||||
bucket_resolution = null //force bucket recreation
|
||||
CRASH("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
|
||||
if (timer.callBack && !timer.spent)
|
||||
timer.callBack.InvokeAsync()
|
||||
spent += timer
|
||||
bucket_count++
|
||||
else if(!QDELETED(timer))
|
||||
qdel(timer)
|
||||
continue
|
||||
|
||||
bucket_count++
|
||||
var/bucket_pos = max(1, BUCKET_POS(timer))
|
||||
|
||||
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
|
||||
if (!bucket_head)
|
||||
bucket_list[bucket_pos] = timer
|
||||
timer.next = null
|
||||
timer.prev = null
|
||||
continue
|
||||
|
||||
if (!bucket_head.prev)
|
||||
bucket_head.prev = bucket_head
|
||||
timer.next = bucket_head
|
||||
timer.prev = bucket_head.prev
|
||||
timer.next.prev = timer
|
||||
timer.prev.next = timer
|
||||
if (i)
|
||||
second_queue.Cut(1, i+1)
|
||||
|
||||
timer = null
|
||||
|
||||
bucket_count -= length(spent)
|
||||
|
||||
@@ -141,7 +213,7 @@ SUBSYSTEM_DEF(timer)
|
||||
if(!TE.callBack)
|
||||
. += ", NO CALLBACK"
|
||||
|
||||
/datum/controller/subsystem/timer/proc/shift_buckets()
|
||||
/datum/controller/subsystem/timer/proc/reset_buckets()
|
||||
var/list/bucket_list = src.bucket_list
|
||||
var/list/alltimers = list()
|
||||
//collect the timers currently in the bucket
|
||||
@@ -162,7 +234,7 @@ SUBSYSTEM_DEF(timer)
|
||||
head_offset = world.time
|
||||
bucket_resolution = world.tick_lag
|
||||
|
||||
alltimers += processing
|
||||
alltimers += second_queue
|
||||
if (!length(alltimers))
|
||||
return
|
||||
|
||||
@@ -173,22 +245,26 @@ SUBSYSTEM_DEF(timer)
|
||||
if (head.timeToRun < head_offset)
|
||||
head_offset = head.timeToRun
|
||||
|
||||
var/list/timers_to_remove = list()
|
||||
|
||||
for (var/thing in alltimers)
|
||||
var/datum/timedevent/timer = thing
|
||||
var/new_bucket_count
|
||||
var/i = 1
|
||||
for (i in 1 to length(alltimers))
|
||||
var/datum/timedevent/timer = alltimers[1]
|
||||
if (!timer)
|
||||
timers_to_remove += timer
|
||||
continue
|
||||
|
||||
var/bucket_pos = BUCKET_POS(timer)
|
||||
if (bucket_pos > BUCKET_LEN)
|
||||
if (timer.timeToRun >= TIMER_MAX)
|
||||
i--
|
||||
break
|
||||
|
||||
timers_to_remove += timer //remove it from the big list once we are done
|
||||
|
||||
if (!timer.callBack || timer.spent)
|
||||
WARNING("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
|
||||
if (timer.callBack)
|
||||
qdel(timer)
|
||||
continue
|
||||
bucket_count++
|
||||
|
||||
new_bucket_count++
|
||||
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
|
||||
if (!bucket_head)
|
||||
bucket_list[bucket_pos] = timer
|
||||
@@ -202,12 +278,14 @@ SUBSYSTEM_DEF(timer)
|
||||
timer.prev = bucket_head.prev
|
||||
timer.next.prev = timer
|
||||
timer.prev.next = timer
|
||||
|
||||
processing = (alltimers - timers_to_remove)
|
||||
if (i)
|
||||
alltimers.Cut(1, i+1)
|
||||
second_queue = alltimers
|
||||
bucket_count = new_bucket_count
|
||||
|
||||
|
||||
/datum/controller/subsystem/timer/Recover()
|
||||
processing |= SStimer.processing
|
||||
second_queue |= SStimer.second_queue
|
||||
hashes |= SStimer.hashes
|
||||
timer_id_dict |= SStimer.timer_id_dict
|
||||
bucket_list |= SStimer.bucket_list
|
||||
@@ -224,8 +302,6 @@ SUBSYSTEM_DEF(timer)
|
||||
var/datum/timedevent/next
|
||||
var/datum/timedevent/prev
|
||||
|
||||
var/static/nextid = 1
|
||||
|
||||
/datum/timedevent/New(datum/callback/callBack, timeToRun, flags, hash)
|
||||
id = TIMER_ID_NULL
|
||||
src.callBack = callBack
|
||||
@@ -235,56 +311,65 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
if (flags & TIMER_UNIQUE)
|
||||
SStimer.hashes[hash] = src
|
||||
|
||||
if (flags & TIMER_STOPPABLE)
|
||||
do
|
||||
if (nextid >= TIMER_ID_MAX)
|
||||
nextid = 1
|
||||
id = nextid++
|
||||
while(SStimer.timer_id_dict["timerid" + num2text(id, 8)])
|
||||
SStimer.timer_id_dict["timerid" + num2text(id, 8)] = src
|
||||
id = GUID()
|
||||
SStimer.timer_id_dict[id] = src
|
||||
|
||||
name = "Timer: " + num2text(id, 8) + ", 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")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
|
||||
|
||||
if (spent)
|
||||
CRASH("HOLY JESUS. WHAT IS THAT? WHAT THE FUCK IS THAT?")
|
||||
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)]")
|
||||
|
||||
if (callBack.object != GLOBAL_PROC)
|
||||
LAZYADD(callBack.object.active_timers, src)
|
||||
|
||||
|
||||
var/list/L
|
||||
|
||||
if (flags & TIMER_CLIENT_TIME)
|
||||
//sorted insert
|
||||
var/list/ctts = SStimer.clienttime_timers
|
||||
var/cttl = length(ctts)
|
||||
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/datum/timedevent/Last = ctts[cttl]
|
||||
if(Last.timeToRun >= timeToRun)
|
||||
ctts += src
|
||||
else
|
||||
for(var/i in cttl to 1 step -1)
|
||||
var/datum/timedevent/E = ctts[i]
|
||||
if(E.timeToRun <= timeToRun)
|
||||
ctts.Insert(i, src)
|
||||
break
|
||||
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
|
||||
ctts += src
|
||||
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)
|
||||
//we are too far aways from needing to run to be in the bucket list, shift_buckets() will handle us.
|
||||
if (bucket_pos > length(bucket_list))
|
||||
SStimer.processing += src
|
||||
return
|
||||
|
||||
//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
|
||||
if (bucket_pos < SStimer.practical_offset)
|
||||
SStimer.practical_offset = bucket_pos
|
||||
return
|
||||
//other wise, lets do a simplified linked list add.
|
||||
if (!bucket_head.prev)
|
||||
@@ -296,10 +381,9 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
/datum/timedevent/Destroy()
|
||||
..()
|
||||
if (flags & TIMER_UNIQUE)
|
||||
if (flags & TIMER_UNIQUE && hash)
|
||||
SStimer.hashes -= hash
|
||||
|
||||
|
||||
if (callBack && callBack.object && callBack.object != GLOBAL_PROC && callBack.object.active_timers)
|
||||
callBack.object.active_timers -= src
|
||||
UNSETEMPTY(callBack.object.active_timers)
|
||||
@@ -307,13 +391,33 @@ SUBSYSTEM_DEF(timer)
|
||||
callBack = null
|
||||
|
||||
if (flags & TIMER_STOPPABLE)
|
||||
SStimer.timer_id_dict -= "timerid" + num2text(id, 8)
|
||||
SStimer.timer_id_dict -= id
|
||||
|
||||
if (flags & TIMER_CLIENT_TIME)
|
||||
SStimer.clienttime_timers -= src
|
||||
if (!spent)
|
||||
spent = world.time
|
||||
SStimer.clienttime_timers -= src
|
||||
return QDEL_HINT_IWILLGC
|
||||
|
||||
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
|
||||
@@ -322,19 +426,6 @@ SUBSYSTEM_DEF(timer)
|
||||
prev.next = next
|
||||
if (next)
|
||||
next.prev = prev
|
||||
|
||||
var/bucketpos = BUCKET_POS(src)
|
||||
var/datum/timedevent/buckethead
|
||||
var/list/bucket_list = SStimer.bucket_list
|
||||
|
||||
if (bucketpos > 0 && bucketpos <= length(bucket_list))
|
||||
buckethead = bucket_list[bucketpos]
|
||||
SStimer.bucket_count--
|
||||
else
|
||||
SStimer.processing -= src
|
||||
|
||||
if (buckethead == src)
|
||||
bucket_list[bucketpos] = next
|
||||
else
|
||||
if (prev && prev.next == src)
|
||||
prev.next = next
|
||||
@@ -351,9 +442,16 @@ SUBSYSTEM_DEF(timer)
|
||||
else
|
||||
. = "[callBack.object.type]"
|
||||
|
||||
/proc/addtimer(datum/callback/callback, wait, flags)
|
||||
/proc/addtimer(datum/callback/callback, wait = 0, flags = 0)
|
||||
if (!callback)
|
||||
return
|
||||
CRASH("addtimer called without a callback")
|
||||
|
||||
if (wait < 0)
|
||||
stack_trace("Addtimer called with a negitive wait. Converting to 0")
|
||||
|
||||
//alot of things add short timers on themselves in their destroy, we ignore those cases
|
||||
if (wait >= 1 && callback && callback.object && callback.object != GLOBAL_PROC && QDELETED(callback.object))
|
||||
stack_trace("Add timer called with a callback assigned to a qdeleted object")
|
||||
|
||||
wait = max(wait, 0)
|
||||
|
||||
@@ -374,11 +472,10 @@ SUBSYSTEM_DEF(timer)
|
||||
var/datum/timedevent/hash_timer = SStimer.hashes[hash]
|
||||
if(hash_timer)
|
||||
if (hash_timer.spent) //it's pending deletion, pretend it doesn't exist.
|
||||
hash_timer.hash = null
|
||||
SStimer.hashes -= hash
|
||||
hash_timer.hash = null //but keep it from accidentally deleting us
|
||||
else
|
||||
|
||||
if (flags & TIMER_OVERRIDE)
|
||||
hash_timer.hash = null //no need having it delete it's hash if we are going to replace it
|
||||
qdel(hash_timer)
|
||||
else
|
||||
if (hash_timer.flags & TIMER_STOPPABLE)
|
||||
@@ -403,7 +500,7 @@ SUBSYSTEM_DEF(timer)
|
||||
qdel(id)
|
||||
return TRUE
|
||||
//id is string
|
||||
var/datum/timedevent/timer = SStimer.timer_id_dict["timerid[id]"]
|
||||
var/datum/timedevent/timer = SStimer.timer_id_dict[id]
|
||||
if (timer && !timer.spent)
|
||||
qdel(timer)
|
||||
return TRUE
|
||||
@@ -412,3 +509,5 @@ SUBSYSTEM_DEF(timer)
|
||||
|
||||
#undef BUCKET_LEN
|
||||
#undef BUCKET_POS
|
||||
#undef TIMER_MAX
|
||||
#undef TIMER_ID_MAX
|
||||
@@ -36,7 +36,7 @@ SUBSYSTEM_DEF(title)
|
||||
break
|
||||
|
||||
file_path = "config/title_screens/images/[pick(title_screens)]"
|
||||
|
||||
|
||||
icon = new(fcopy_rsc(file_path))
|
||||
|
||||
if(splash_turf)
|
||||
|
||||
Reference in New Issue
Block a user