diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm
index 115748a9a82..ec1a3ebbb13 100644
--- a/code/__DEFINES/MC.dm
+++ b/code/__DEFINES/MC.dm
@@ -33,7 +33,7 @@
/// Returns true if the MC is initialized and running.
/// Optional argument init_stage controls what stage the mc must have initialized to count as initialized. Defaults to INITSTAGE_MAX if not specified.
-#define MC_RUNNING(INIT_STAGE...) (Master && Master.processing > 0 && Master.current_runlevel && Master.init_stage_completed == (max(min(INITSTAGE_MAX, ##INIT_STAGE), 1)))
+#define MC_RUNNING(INIT_STAGE...) (Master && Master.processing > 0 && Master.current_runlevel && Master.init_stage_completed >= (max(min(INITSTAGE_MAX, ##INIT_STAGE), 1)))
#define MC_LOOP_RTN_NEWSTAGES 1
#define MC_LOOP_RTN_GRACEFUL_EXIT 2
@@ -83,9 +83,11 @@
#define SS_PAUSING 5 /// in the middle of pausing
// Subsystem init stages
-#define INITSTAGE_EARLY 1 //! Early init stuff that doesn't need to wait for mapload
-#define INITSTAGE_MAIN 2 //! Main init stage
-#define INITSTAGE_MAX 2 //! Highest initstage.
+#define INITSTAGE_FIRST 1
+#define INITSTAGE_EARLY 2 //! Early init stuff that doesn't need to wait for mapload
+#define INITSTAGE_MAIN 3 //! Main init stage
+#define INITSTAGE_LAST 4
+#define INITSTAGE_MAX 4 //! Highest initstage.
#define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\
/datum/controller/subsystem/##X/New(){\
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index 3354f6306d3..3a4956de758 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -125,73 +125,6 @@
/// Successfully initialized, BUT do not announce it to players (generally to hide game mechanics it would otherwise spoil)
#define SS_INIT_NO_MESSAGE 4
-//! ### SS initialization load orders
-// Subsystem init_order, from highest priority to lowest priority
-// Subsystems shutdown in the reverse of the order they initialize in
-// The numbers just define the ordering, they are meaningless otherwise.
-
-#define INIT_ORDER_PROFILER 101
-#define INIT_ORDER_TITLE 100
-#define INIT_ORDER_GARBAGE 99
-#define INIT_ORDER_DBCORE 95
-#define INIT_ORDER_BLACKBOX 94
-#define INIT_ORDER_SERVER_MAINT 93
-#define INIT_ORDER_INPUT 85
-#define INIT_ORDER_ADMIN_VERBS 84 // needs to be pretty high, admins can't do much without it
-#define INIT_ORDER_SOUNDS 83
-#define INIT_ORDER_INSTRUMENTS 82
-#define INIT_ORDER_GREYSCALE 81
-#define INIT_ORDER_VIS 80
-#define INIT_ORDER_SECURITY_LEVEL 79 // We need to load before events so that it has a security level to choose from.
-#define INIT_ORDER_DISCORD 78
-#define INIT_ORDER_ACHIEVEMENTS 77
-#define INIT_ORDER_STATION 74 //This is high priority because it manipulates a lot of the subsystems that will initialize after it.
-#define INIT_ORDER_QUIRKS 73
-#define INIT_ORDER_REAGENTS 72 //HAS to be before mapping and assets - both create objects, which creates reagents, which relies on lists made in this subsystem
-#define INIT_ORDER_EVENTS 70
-#define INIT_ORDER_IDACCESS 66
-#define INIT_ORDER_JOBS 65 // Must init before atoms, to set up properly the dynamic job lists.
-#define INIT_ORDER_AI_MOVEMENT 56 //We need the movement setup
-#define INIT_ORDER_AI_CONTROLLERS 55 //So the controller can get the ref
-#define INIT_ORDER_TICKER 55
-#define INIT_ORDER_TCG 55
-#define INIT_ORDER_MAPPING 50
-#define INIT_ORDER_AI_IDLE_CONTROLLERS 50
-#define INIT_ORDER_EARLY_ASSETS 48
-#define INIT_ORDER_RESEARCH 47
-#define INIT_ORDER_TIMETRACK 46
-#define INIT_ORDER_SPATIAL_GRID 43
-#define INIT_ORDER_ECONOMY 40
-#define INIT_ORDER_OUTPUTS 35
-#define INIT_ORDER_RESTAURANT 34
-#define INIT_ORDER_TTS 33
-#define INIT_ORDER_FLUIDS 32 // Needs to be above atoms, as some atoms may want to start fluids/gases on init
-#define INIT_ORDER_ATOMS 30
-#define INIT_ORDER_LANGUAGE 25
-#define INIT_ORDER_MACHINES 20
-#define INIT_ORDER_SKILLS 15
-#define INIT_ORDER_QUEUELINKS 10
-#define INIT_ORDER_TIMER 1
-#define INIT_ORDER_DEFAULT 0
-#define INIT_ORDER_AIR -1
-#define INIT_ORDER_PERSISTENCE -2
-#define INIT_ORDER_PERSISTENT_PAINTINGS -3 // Assets relies on this
-#define INIT_ORDER_VOTE -4 // Needs to be after persistence so that recent maps are not loaded.
-#define INIT_ORDER_ASSETS -5
-#define INIT_ORDER_ICON_SMOOTHING -6
-#define INIT_ORDER_OVERLAY -7
-#define INIT_ORDER_XKEYSCORE -10
-#define INIT_ORDER_STICKY_BAN -10
-#define INIT_ORDER_LIGHTING -20
-#define INIT_ORDER_SHUTTLE -21
-#define INIT_ORDER_MINOR_MAPPING -40
-#define INIT_ORDER_PATH -50
-#define INIT_ORDER_EXPLOSIONS -69
-#define INIT_ORDER_STATPANELS -97
-#define INIT_ORDER_BAN_CACHE -98
-#define INIT_ORDER_INIT_PROFILER -99 //Near the end, logs the costs of initialize
-#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
-
// Subsystem fire priority, from lowest to highest priority
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_UNPLANNED_NPC 3
diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm
index f333318c94e..ead1b5cbff5 100644
--- a/code/__HELPERS/cmp.dm
+++ b/code/__HELPERS/cmp.dm
@@ -65,7 +65,10 @@
return cmp_numeric_asc(a.get_exp_living(TRUE), b.get_exp_living(TRUE))
/proc/cmp_subsystem_init(datum/controller/subsystem/a, datum/controller/subsystem/b)
- return initial(b.init_order) - initial(a.init_order) //uses initial() so it can be used on types
+ return a.init_order - b.init_order
+
+/proc/cmp_subsystem_init_stage(datum/controller/subsystem/a, datum/controller/subsystem/b)
+ return initial(a.init_stage) - initial(b.init_stage)
/proc/cmp_subsystem_display(datum/controller/subsystem/a, datum/controller/subsystem/b)
return sorttext(b.name, a.name)
diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm
index f796bd5480a..f6457338040 100644
--- a/code/controllers/failsafe.dm
+++ b/code/controllers/failsafe.dm
@@ -152,7 +152,7 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
/proc/recover_all_SS_and_recreate_master()
del(Master)
var/list/subsytem_types = subtypesof(/datum/controller/subsystem)
- sortTim(subsytem_types, GLOBAL_PROC_REF(cmp_subsystem_init))
+ sortTim(subsytem_types, GLOBAL_PROC_REF(cmp_subsystem_init_stage))
for(var/I in subsytem_types)
new I
. = Recreate_MC()
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index 55160ec6504..0c85b980278 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -110,7 +110,7 @@ GLOBAL_REAL(Master, /datum/controller/master)
//Code used for first master on game boot or if existing master got deleted
Master = src
var/list/subsystem_types = subtypesof(/datum/controller/subsystem)
- sortTim(subsystem_types, GLOBAL_PROC_REF(cmp_subsystem_init))
+ sortTim(subsystem_types, GLOBAL_PROC_REF(cmp_subsystem_init_stage))
//Find any abandoned subsystem from the previous master (if there was any)
var/list/existing_subsystems = list()
@@ -333,10 +333,90 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
for (var/i in 1 to INITSTAGE_MAX)
stage_sorted_subsystems[i] = list()
- // Sort subsystems by init_order, so they initialize in the correct order.
- sortTim(subsystems, GLOBAL_PROC_REF(cmp_subsystem_init))
+ var/list/type_to_subsystem = list()
+ for(var/datum/controller/subsystem/subsystem as anything in subsystems)
+ type_to_subsystem[subsystem.type] = subsystem
- for (var/datum/controller/subsystem/subsystem as anything in subsystems)
+ // Allows subsystems to declare other subsystems that must initialize after them.
+ for(var/datum/controller/subsystem/subsystem as anything in subsystems)
+ for(var/dependent_type as anything in subsystem.dependents)
+ if(!ispath(dependent_type, /datum/controller/subsystem))
+ stack_trace("ERROR: MC: subsystem `[subsystem.type]` has an invalid dependent: `[dependent_type]`. Skipping")
+ continue
+ var/datum/controller/subsystem/dependent = type_to_subsystem[dependent_type]
+ dependent.dependencies |= subsystem.type
+ subsystem.dependents = list()
+
+ // Constructs a reverse-dependency graph.
+ for(var/datum/controller/subsystem/subsystem as anything in subsystems)
+ for(var/dependency_type as anything in subsystem.dependencies)
+ if(!ispath(dependency_type, /datum/controller/subsystem))
+ stack_trace("ERROR: MC: subsystem `[subsystem.type]` has an invalid dependency: `[dependency_type]`. Skipping")
+ continue
+ var/datum/controller/subsystem/dependency = type_to_subsystem[dependency_type]
+ // Not a foolproof failsafe, likely to only prevent any immediate issues if this is only triggered once.
+ if(subsystem.init_stage < dependency.init_stage)
+ stack_trace("ERROR: MC: subsystem `[subsystem.type]` has an init_stage before one of its dependencies (Dependency: `[dependency.type]`, [subsystem.init_stage] < [dependency.init_stage])! Setting init_stage to [dependency.init_stage]")
+ subsystem.init_stage = dependency.init_stage
+ dependency.dependents += subsystem
+
+ // Topological sorting algorithm
+ var/list/counts = new(subsystems.len)
+ var/list/unsorted_subsystems = list()
+ var/index = 1
+ for(var/datum/controller/subsystem/subsystem as anything in subsystems)
+ counts[index] = length(subsystem.dependencies)
+ subsystem.ordering_id = index
+ if(counts[index] == 0)
+ unsorted_subsystems += subsystem
+ index += 1
+
+ var/list/sorted_subsystems = list()
+ while(length(unsorted_subsystems) > 0)
+ var/datum/controller/subsystem/sub = unsorted_subsystems[unsorted_subsystems.len]
+ unsorted_subsystems.len--
+ sorted_subsystems += sub
+ for(var/datum/controller/subsystem/dependent as anything in sub.dependents)
+ counts[dependent.ordering_id] -= 1
+ if(counts[dependent.ordering_id] == 0)
+ unsorted_subsystems += dependent
+ // Topological sorting algorithm end
+
+ if(length(subsystems) != length(sorted_subsystems))
+ var/list/circular_dependency = subsystems.Copy() - sorted_subsystems
+ var/list/debug_msg = list()
+ var/list/usr_msg = list()
+ for(var/datum/controller/subsystem/subsystem as anything in circular_dependency)
+ usr_msg += "[subsystem.name]"
+
+ var/list/datum/controller/subsystem/nodes = list(circular_dependency[1])
+ var/list/loop = list()
+ while(length(nodes) > 0)
+ var/datum/controller/subsystem/node = nodes[nodes.len]
+ nodes.len--
+ if(node in loop)
+ loop += node
+ break
+ loop += node
+ for(var/datum/controller/subsystem/connected as anything in node.dependencies)
+ nodes += type_to_subsystem[connected]
+
+ var/loop_position = 0
+ for(var/datum/controller/subsystem/node in loop)
+ if(node == loop[loop.len])
+ break
+ loop_position++
+ if(loop_position != 0)
+ loop.Cut(1, loop_position + 1)
+
+ for(var/datum/controller/subsystem/subsystem as anything in loop)
+ debug_msg += "[subsystem.name]"
+
+ // Can't initialize them if they have circular dependencies, there's no real failsafe here.
+ stack_trace("ERROR: CRITICAL: MC: The following subsystems have circular dependencies: [jointext(debug_msg, " -> ")]")
+ to_chat(world, span_bolddanger("CRITICAL: Failed to initialize [jointext(usr_msg, ", ")]"), MESSAGE_TYPE_DEBUG)
+
+ for (var/datum/controller/subsystem/subsystem as anything in sorted_subsystems)
var/subsystem_init_stage = subsystem.init_stage
if (!isnum(subsystem_init_stage) || subsystem_init_stage < 1 || subsystem_init_stage > INITSTAGE_MAX || round(subsystem_init_stage) != subsystem_init_stage)
stack_trace("ERROR: MC: subsystem `[subsystem.type]` has invalid init_stage: `[subsystem_init_stage]`. Setting to `[INITSTAGE_MAX]`")
@@ -344,12 +424,15 @@ ADMIN_VERB(cmd_controller_view_ui, R_SERVER|R_DEBUG, "Controller Overview", "Vie
stage_sorted_subsystems[subsystem_init_stage] += subsystem
// Sort subsystems by display setting for easy access.
+ var/evaluated_order = 1
sortTim(subsystems, GLOBAL_PROC_REF(cmp_subsystem_display))
var/start_timeofday = REALTIMEOFDAY
for (var/current_init_stage in 1 to INITSTAGE_MAX)
// Initialize subsystems.
for (var/datum/controller/subsystem/subsystem in stage_sorted_subsystems[current_init_stage])
+ subsystem.init_order = evaluated_order
+ evaluated_order++
init_subsystem(subsystem)
CHECK_TICK
diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm
index 4bde26e3c9d..0dbe2af2f8b 100644
--- a/code/controllers/subsystem.dm
+++ b/code/controllers/subsystem.dm
@@ -13,8 +13,20 @@
/// Name of the subsystem - you must change this
name = "fire coderbus"
- /// Order of initialization. Higher numbers are initialized first, lower numbers later. Use or create defines such as [INIT_ORDER_DEFAULT] so we can see the order in one file.
- var/init_order = INIT_ORDER_DEFAULT
+ /// Determines which subsystems this subsystem is dependant on to initialize. Will initialize after all specified subsystems.
+ /// If init_stage is earlier than a dependent subsystem, will throw an error and push the init stage forward to that subsystem.
+ /// Usage: Put the typepaths of the subsystems that need to init before this one in this list.
+ var/list/dependencies = list()
+
+ /// The inverse of the dependencies. Can be set manually, but will also get evaluated at runtime. Turns into a list of instances at runtime.
+ /// Usage: Put the typepaths of the subsystems that need to init after this one in this list.
+ var/list/dependents
+
+ /// ID of the subsystem. Set automatically when the dependency graph is evaluated. Used primarily in determining order.
+ var/ordering_id = 0
+
+ /// Do not modify. Automatically set when the dependency graph is evaluated. Similar to ordering_id, but evaluated after init_stage.
+ var/init_order = 0
/// Time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
var/wait = 20
diff --git a/code/controllers/subsystem/achievements.dm b/code/controllers/subsystem/achievements.dm
index 6a1cc5dd8bd..4633be6f741 100644
--- a/code/controllers/subsystem/achievements.dm
+++ b/code/controllers/subsystem/achievements.dm
@@ -1,7 +1,6 @@
SUBSYSTEM_DEF(achievements)
name = "Achievements"
flags = SS_NO_FIRE
- init_order = INIT_ORDER_ACHIEVEMENTS
var/achievements_enabled = FALSE
///List of achievements
diff --git a/code/controllers/subsystem/admin_verbs.dm b/code/controllers/subsystem/admin_verbs.dm
index 9496b95d998..645a447c485 100644
--- a/code/controllers/subsystem/admin_verbs.dm
+++ b/code/controllers/subsystem/admin_verbs.dm
@@ -3,7 +3,7 @@ GENERAL_PROTECT_DATUM(/datum/controller/subsystem/admin_verbs)
SUBSYSTEM_DEF(admin_verbs)
name = "Admin Verbs"
flags = SS_NO_FIRE
- init_order = INIT_ORDER_ADMIN_VERBS
+ init_stage = INITSTAGE_EARLY
/// A list of all admin verbs indexed by their type.
var/list/datum/admin_verb/admin_verbs_by_type = list()
/// A list of all admin verbs indexed by their visibility flag.
diff --git a/code/controllers/subsystem/ai_controllers.dm b/code/controllers/subsystem/ai_controllers.dm
index 8a5eb43bfc9..c5123f48af6 100644
--- a/code/controllers/subsystem/ai_controllers.dm
+++ b/code/controllers/subsystem/ai_controllers.dm
@@ -3,7 +3,9 @@ SUBSYSTEM_DEF(ai_controllers)
name = "AI Controller Ticker"
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND
priority = FIRE_PRIORITY_NPC
- init_order = INIT_ORDER_AI_CONTROLLERS
+ dependencies = list(
+ /datum/controller/subsystem/movement/ai_movement
+ )
wait = 0.5 SECONDS //Plan every half second if required, not great not terrible.
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
///type of status we are interested in running
diff --git a/code/controllers/subsystem/ai_idle_controllers.dm b/code/controllers/subsystem/ai_idle_controllers.dm
index 367a2c82ffc..a36901ceac6 100644
--- a/code/controllers/subsystem/ai_idle_controllers.dm
+++ b/code/controllers/subsystem/ai_idle_controllers.dm
@@ -2,7 +2,9 @@ AI_CONTROLLER_SUBSYSTEM_DEF(ai_idle_controllers)
name = "AI Idle Controllers"
flags = SS_POST_FIRE_TIMING | SS_BACKGROUND
priority = FIRE_PRIORITY_IDLE_NPC
- init_order = INIT_ORDER_AI_IDLE_CONTROLLERS
+ dependencies = list(
+ /datum/controller/subsystem/ai_controllers
+ )
wait = 5 SECONDS
runlevels = RUNLEVEL_GAME
planning_status = AI_STATUS_IDLE
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index 34e71209f19..a2a73f2b667 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -1,6 +1,9 @@
SUBSYSTEM_DEF(air)
name = "Atmospherics"
- init_order = INIT_ORDER_AIR
+ dependencies = list(
+ /datum/controller/subsystem/mapping,
+ /datum/controller/subsystem/atoms
+ )
priority = FIRE_PRIORITY_AIR
wait = 0.5 SECONDS
flags = SS_BACKGROUND
diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm
index 8336c60c0fa..79d2e312a21 100644
--- a/code/controllers/subsystem/assets.dm
+++ b/code/controllers/subsystem/assets.dm
@@ -1,6 +1,10 @@
SUBSYSTEM_DEF(assets)
name = "Assets"
- init_order = INIT_ORDER_ASSETS
+ dependencies = list(
+ /datum/controller/subsystem/atoms,
+ /datum/controller/subsystem/persistent_paintings,
+ /datum/controller/subsystem/processing/greyscale
+ )
flags = SS_NO_FIRE
var/list/datum/asset_cache_item/cache = list()
var/list/preload = list()
diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm
index 7f26e4d0414..c1b2e86403a 100644
--- a/code/controllers/subsystem/atoms.dm
+++ b/code/controllers/subsystem/atoms.dm
@@ -1,6 +1,11 @@
SUBSYSTEM_DEF(atoms)
name = "Atoms"
- init_order = INIT_ORDER_ATOMS
+ dependencies = list(
+ /datum/controller/subsystem/processing/reagents,
+ /datum/controller/subsystem/fluids,
+ /datum/controller/subsystem/mapping,
+ /datum/controller/subsystem/job
+ )
flags = SS_NO_FIRE
/// A stack of list(source, desired initialized state)
diff --git a/code/controllers/subsystem/ban_cache.dm b/code/controllers/subsystem/ban_cache.dm
index 2d10baecab3..21e1a92a7ed 100644
--- a/code/controllers/subsystem/ban_cache.dm
+++ b/code/controllers/subsystem/ban_cache.dm
@@ -4,7 +4,7 @@ SUBSYSTEM_DEF(ban_cache)
/datum/controller/subsystem/ban_cache
name = "Ban Cache"
- init_order = INIT_ORDER_BAN_CACHE
+ init_stage = INITSTAGE_LAST
flags = SS_NO_FIRE
var/query_started = FALSE
diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm
index 628b192b72c..453eb073e80 100644
--- a/code/controllers/subsystem/blackbox.dm
+++ b/code/controllers/subsystem/blackbox.dm
@@ -2,7 +2,6 @@ SUBSYSTEM_DEF(blackbox)
name = "Blackbox"
wait = 6000
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
- init_order = INIT_ORDER_BLACKBOX
var/list/feedback_list = list() //list of datum/feedback_variable
var/list/first_death = list() //the first death of this round, assoc. vars keep track of different things
diff --git a/code/controllers/subsystem/chat.dm b/code/controllers/subsystem/chat.dm
index f93ab6e09f6..d2303074077 100644
--- a/code/controllers/subsystem/chat.dm
+++ b/code/controllers/subsystem/chat.dm
@@ -8,7 +8,7 @@ SUBSYSTEM_DEF(chat)
flags = SS_TICKER|SS_NO_INIT
wait = 1
priority = FIRE_PRIORITY_CHAT
- init_order = INIT_ORDER_CHAT
+ init_stage = INITSTAGE_LAST
/// Assosciates a ckey with a list of messages to send to them.
var/list/list/datum/chat_payload/client_to_payloads = list()
diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm
index 805fe419c94..c98009ed9d9 100644
--- a/code/controllers/subsystem/dbcore.dm
+++ b/code/controllers/subsystem/dbcore.dm
@@ -2,9 +2,9 @@
SUBSYSTEM_DEF(dbcore)
name = "Database"
flags = SS_TICKER
+ init_stage = INITSTAGE_FIRST
wait = 10 // Not seconds because we're running on SS_TICKER
runlevels = RUNLEVEL_LOBBY|RUNLEVELS_DEFAULT
- init_order = INIT_ORDER_DBCORE
priority = FIRE_PRIORITY_DATABASE
var/schema_mismatch = 0
@@ -49,6 +49,8 @@ SUBSYSTEM_DEF(dbcore)
var/db_daemon_started = FALSE
/datum/controller/subsystem/dbcore/Initialize()
+ Connect()
+
//We send warnings to the admins during subsystem init, as the clients will be New'd and messages
//will queue properly with goonchat
switch(schema_mismatch)
diff --git a/code/controllers/subsystem/discord.dm b/code/controllers/subsystem/discord.dm
index be9f066cf83..802b95b2341 100644
--- a/code/controllers/subsystem/discord.dm
+++ b/code/controllers/subsystem/discord.dm
@@ -31,7 +31,7 @@
SUBSYSTEM_DEF(discord)
name = "Discord"
wait = 3000
- init_order = INIT_ORDER_DISCORD
+ init_stage = INITSTAGE_EARLY
/// People to save to notify file
var/list/notify_members = list()
diff --git a/code/controllers/subsystem/early_assets.dm b/code/controllers/subsystem/early_assets.dm
index 5ce669bec83..d40ea8614d0 100644
--- a/code/controllers/subsystem/early_assets.dm
+++ b/code/controllers/subsystem/early_assets.dm
@@ -5,7 +5,15 @@
/// opened it up early.
SUBSYSTEM_DEF(early_assets)
name = "Early Assets"
- init_order = INIT_ORDER_EARLY_ASSETS
+ dependencies = list(
+ /datum/controller/subsystem/processing/reagents,
+ /datum/controller/subsystem/processing/greyscale
+ )
+ dependents = list(
+ /datum/controller/subsystem/mapping,
+ /datum/controller/subsystem/atoms
+ )
+ init_stage = INITSTAGE_EARLY
flags = SS_NO_FIRE
/datum/controller/subsystem/early_assets/Initialize()
diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm
index 25876fd80c6..4a519d0da34 100644
--- a/code/controllers/subsystem/economy.dm
+++ b/code/controllers/subsystem/economy.dm
@@ -1,7 +1,6 @@
SUBSYSTEM_DEF(economy)
name = "Economy"
wait = 5 MINUTES
- init_order = INIT_ORDER_ECONOMY
runlevels = RUNLEVEL_GAME
///How many paychecks should players start out the round with?
var/roundstart_paychecks = 5
diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm
index 3451ad506c9..e7aaac4159c 100644
--- a/code/controllers/subsystem/events.dm
+++ b/code/controllers/subsystem/events.dm
@@ -1,6 +1,8 @@
SUBSYSTEM_DEF(events)
name = "Events"
- init_order = INIT_ORDER_EVENTS
+ dependencies = list(
+ /datum/controller/subsystem/processing/station
+ )
runlevels = RUNLEVEL_GAME
///list of all datum/round_event_control. Used for selecting events based on weight and occurrences.
var/list/control = list()
diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm
index 36dbba09eae..c51d70a1de2 100644
--- a/code/controllers/subsystem/explosions.dm
+++ b/code/controllers/subsystem/explosions.dm
@@ -7,7 +7,6 @@ GLOBAL_LIST_EMPTY(explosions)
SUBSYSTEM_DEF(explosions)
name = "Explosions"
- init_order = INIT_ORDER_EXPLOSIONS
priority = FIRE_PRIORITY_EXPLOSIONS
wait = 1
flags = SS_TICKER|SS_NO_INIT
diff --git a/code/controllers/subsystem/fluids.dm b/code/controllers/subsystem/fluids.dm
index 2b4ce472956..6b68ae71722 100644
--- a/code/controllers/subsystem/fluids.dm
+++ b/code/controllers/subsystem/fluids.dm
@@ -22,7 +22,6 @@ SUBSYSTEM_DEF(fluids)
wait = 0 // Will be autoset to whatever makes the most sense given the spread and effect waits.
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME
- init_order = INIT_ORDER_FLUIDS
priority = FIRE_PRIORITY_FLUIDS
// Fluid spread processing:
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
index f6b1bc3f860..844f52a860f 100644
--- a/code/controllers/subsystem/garbage.dm
+++ b/code/controllers/subsystem/garbage.dm
@@ -27,8 +27,7 @@ SUBSYSTEM_DEF(garbage)
wait = 2 SECONDS
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
- init_order = INIT_ORDER_GARBAGE
- init_stage = INITSTAGE_EARLY
+ init_stage = INITSTAGE_FIRST
var/list/collection_timeout = list(GC_FILTER_QUEUE, GC_CHECK_QUEUE, GC_DEL_QUEUE) // deciseconds to wait before moving something up in the queue to the next level
diff --git a/code/controllers/subsystem/icon_smooth.dm b/code/controllers/subsystem/icon_smooth.dm
index 9e5e9ffa99d..e157e925a11 100644
--- a/code/controllers/subsystem/icon_smooth.dm
+++ b/code/controllers/subsystem/icon_smooth.dm
@@ -1,6 +1,8 @@
SUBSYSTEM_DEF(icon_smooth)
name = "Icon Smoothing"
- init_order = INIT_ORDER_ICON_SMOOTHING
+ dependencies = list(
+ /datum/controller/subsystem/atoms
+ )
wait = 1
priority = FIRE_PRIORITY_SMOOTHING
flags = SS_TICKER
diff --git a/code/controllers/subsystem/id_access.dm b/code/controllers/subsystem/id_access.dm
index 1a94a13389d..49e12498c8d 100644
--- a/code/controllers/subsystem/id_access.dm
+++ b/code/controllers/subsystem/id_access.dm
@@ -3,7 +3,6 @@
*/
SUBSYSTEM_DEF(id_access)
name = "IDs and Access"
- init_order = INIT_ORDER_IDACCESS
flags = SS_NO_FIRE
/// Dictionary of access flags. Keys are accesses. Values are their associated bitflags.
diff --git a/code/controllers/subsystem/init_profiler.dm b/code/controllers/subsystem/init_profiler.dm
index 063898b6a09..dcb163e596a 100644
--- a/code/controllers/subsystem/init_profiler.dm
+++ b/code/controllers/subsystem/init_profiler.dm
@@ -4,8 +4,7 @@
///Hopefully this makes sorting out what causes problems when easier
SUBSYSTEM_DEF(init_profiler)
name = "Init Profiler"
- init_order = INIT_ORDER_INIT_PROFILER
- init_stage = INITSTAGE_MAX
+ init_stage = INITSTAGE_LAST
flags = SS_NO_FIRE
/datum/controller/subsystem/init_profiler/Initialize()
diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm
index e4e12418a75..a2a43f79a90 100644
--- a/code/controllers/subsystem/input.dm
+++ b/code/controllers/subsystem/input.dm
@@ -1,6 +1,5 @@
VERB_MANAGER_SUBSYSTEM_DEF(input)
name = "Input"
- init_order = INIT_ORDER_INPUT
init_stage = INITSTAGE_EARLY
flags = SS_TICKER
priority = FIRE_PRIORITY_INPUT
diff --git a/code/controllers/subsystem/ipintel.dm b/code/controllers/subsystem/ipintel.dm
index 3ae9cfab0c5..286de507abc 100644
--- a/code/controllers/subsystem/ipintel.dm
+++ b/code/controllers/subsystem/ipintel.dm
@@ -1,6 +1,5 @@
SUBSYSTEM_DEF(ipintel)
name = "XKeyScore"
- init_order = INIT_ORDER_XKEYSCORE
flags = SS_NO_INIT|SS_NO_FIRE
/// The threshold for probability to be considered a VPN and/or bad IP
var/probability_threshold
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index ad264e3d4f0..a1479f7c7a0 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -1,6 +1,8 @@
SUBSYSTEM_DEF(job)
name = "Jobs"
- init_order = INIT_ORDER_JOBS
+ dependencies = list(
+ /datum/controller/subsystem/processing/station
+ )
flags = SS_NO_FIRE
/// List of all jobs.
diff --git a/code/controllers/subsystem/library.dm b/code/controllers/subsystem/library.dm
index bfe77f70f02..fc08e95ba84 100644
--- a/code/controllers/subsystem/library.dm
+++ b/code/controllers/subsystem/library.dm
@@ -1,6 +1,10 @@
/// Manages library data, loading bookselves, etc
SUBSYSTEM_DEF(library)
name = "Library Loading"
+ dependencies = list(
+ /datum/controller/subsystem/atoms,
+ /datum/controller/subsystem/mapping
+ )
flags = SS_NO_FIRE
/// List of bookselves to prefill with books
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index 24d871d2f09..c4fca37ca7b 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -1,7 +1,10 @@
SUBSYSTEM_DEF(lighting)
name = "Lighting"
+ dependencies = list(
+ /datum/controller/subsystem/atoms,
+ /datum/controller/subsystem/mapping
+ )
wait = 2
- init_order = INIT_ORDER_LIGHTING
flags = SS_TICKER
var/static/list/sources_queue = list() // List of lighting sources queued for update.
var/static/list/corners_queue = list() // List of lighting corners queued for update.
diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm
index a9950f1f4d8..0a6cb90d5d4 100644
--- a/code/controllers/subsystem/machines.dm
+++ b/code/controllers/subsystem/machines.dm
@@ -1,6 +1,8 @@
SUBSYSTEM_DEF(machines)
name = "Machines"
- init_order = INIT_ORDER_MACHINES
+ dependencies = list(
+ /datum/controller/subsystem/atoms
+ )
flags = SS_KEEP_TIMING
wait = 2 SECONDS
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index b4184f8a34d..16ff85ead53 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -1,6 +1,10 @@
SUBSYSTEM_DEF(mapping)
name = "Mapping"
- init_order = INIT_ORDER_MAPPING
+ dependencies = list(
+ /datum/controller/subsystem/job,
+ /datum/controller/subsystem/processing/station,
+ /datum/controller/subsystem/processing/reagents
+ )
runlevels = ALL
var/list/nuke_tiles = list()
diff --git a/code/controllers/subsystem/market.dm b/code/controllers/subsystem/market.dm
index 00903cbf654..7a044964ee1 100644
--- a/code/controllers/subsystem/market.dm
+++ b/code/controllers/subsystem/market.dm
@@ -1,7 +1,9 @@
SUBSYSTEM_DEF(market)
name = "Market"
flags = SS_BACKGROUND
- init_order = INIT_ORDER_DEFAULT
+ dependencies = list(
+ /datum/controller/subsystem/atoms
+ )
/// Descriptions for each shipping methods.
var/shipping_method_descriptions = list(
diff --git a/code/controllers/subsystem/minor_mapping.dm b/code/controllers/subsystem/minor_mapping.dm
index 4aed29be350..cdd4d66e695 100644
--- a/code/controllers/subsystem/minor_mapping.dm
+++ b/code/controllers/subsystem/minor_mapping.dm
@@ -3,7 +3,10 @@
SUBSYSTEM_DEF(minor_mapping)
name = "Minor Mapping"
- init_order = INIT_ORDER_MINOR_MAPPING
+ dependencies = list(
+ /datum/controller/subsystem/mapping,
+ /datum/controller/subsystem/atoms,
+ )
flags = SS_NO_FIRE
/datum/controller/subsystem/minor_mapping/Initialize()
diff --git a/code/controllers/subsystem/movement/ai_movement.dm b/code/controllers/subsystem/movement/ai_movement.dm
index db0b987eb31..90333b529d7 100644
--- a/code/controllers/subsystem/movement/ai_movement.dm
+++ b/code/controllers/subsystem/movement/ai_movement.dm
@@ -4,7 +4,6 @@ MOVEMENT_SUBSYSTEM_DEF(ai_movement)
flags = SS_BACKGROUND|SS_TICKER
priority = FIRE_PRIORITY_NPC_MOVEMENT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
- init_order = INIT_ORDER_AI_MOVEMENT
///an assoc list of all ai_movement types. Assoc type to instance
var/list/movement_types
diff --git a/code/controllers/subsystem/ore_generation.dm b/code/controllers/subsystem/ore_generation.dm
index e36dd577794..50560a0b3d4 100644
--- a/code/controllers/subsystem/ore_generation.dm
+++ b/code/controllers/subsystem/ore_generation.dm
@@ -2,7 +2,9 @@
SUBSYSTEM_DEF(ore_generation)
name = "Ore Generation"
wait = 60 SECONDS
- init_order = INIT_ORDER_DEFAULT
+ dependencies = list(
+ /datum/controller/subsystem/atoms
+ )
runlevels = RUNLEVEL_GAME
/// All ore vents that are currently producing boulders.
diff --git a/code/controllers/subsystem/pathfinder.dm b/code/controllers/subsystem/pathfinder.dm
index d95b3bff538..b67260853ba 100644
--- a/code/controllers/subsystem/pathfinder.dm
+++ b/code/controllers/subsystem/pathfinder.dm
@@ -1,7 +1,6 @@
/// Queues and manages JPS pathfinding steps
SUBSYSTEM_DEF(pathfinder)
name = "Pathfinder"
- init_order = INIT_ORDER_PATH
priority = FIRE_PRIORITY_PATHFINDING
wait = 0.5
/// List of pathfind datums we are currently trying to process
diff --git a/code/controllers/subsystem/persistence/_persistence.dm b/code/controllers/subsystem/persistence/_persistence.dm
index 8d9bc483908..2f4f5ff704c 100644
--- a/code/controllers/subsystem/persistence/_persistence.dm
+++ b/code/controllers/subsystem/persistence/_persistence.dm
@@ -3,7 +3,10 @@
SUBSYSTEM_DEF(persistence)
name = "Persistence"
- init_order = INIT_ORDER_PERSISTENCE
+ dependencies = list(
+ /datum/controller/subsystem/mapping,
+ /datum/controller/subsystem/atoms
+ )
flags = SS_NO_FIRE
///instantiated wall engraving components
diff --git a/code/controllers/subsystem/persistent_paintings.dm b/code/controllers/subsystem/persistent_paintings.dm
index b2f0921df6d..845653d0414 100644
--- a/code/controllers/subsystem/persistent_paintings.dm
+++ b/code/controllers/subsystem/persistent_paintings.dm
@@ -93,7 +93,6 @@
SUBSYSTEM_DEF(persistent_paintings)
name = "Persistent Paintings"
- init_order = INIT_ORDER_PERSISTENT_PAINTINGS
flags = SS_NO_FIRE
/// A list of painting frames that this controls
diff --git a/code/controllers/subsystem/processing/ai_behaviors.dm b/code/controllers/subsystem/processing/ai_behaviors.dm
index e92da2474bb..6c53d16e79f 100644
--- a/code/controllers/subsystem/processing/ai_behaviors.dm
+++ b/code/controllers/subsystem/processing/ai_behaviors.dm
@@ -4,7 +4,9 @@ PROCESSING_SUBSYSTEM_DEF(ai_behaviors)
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND
priority = FIRE_PRIORITY_NPC_ACTIONS
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
- init_order = INIT_ORDER_AI_CONTROLLERS
+ dependencies = list(
+ /datum/controller/subsystem/movement/ai_movement
+ )
wait = 1
///List of all ai_behavior singletons, key is the typepath while assigned value is a newly created instance of the typepath. See SetupAIBehaviors()
var/list/ai_behaviors
diff --git a/code/controllers/subsystem/processing/ai_idle_behaviors.dm b/code/controllers/subsystem/processing/ai_idle_behaviors.dm
index 8875d971ad8..53a9465046e 100644
--- a/code/controllers/subsystem/processing/ai_idle_behaviors.dm
+++ b/code/controllers/subsystem/processing/ai_idle_behaviors.dm
@@ -3,7 +3,9 @@ PROCESSING_SUBSYSTEM_DEF(idle_ai_behaviors)
flags = SS_BACKGROUND
wait = 1.5 SECONDS
priority = FIRE_PRIORITY_IDLE_NPC
- init_order = INIT_ORDER_AI_IDLE_CONTROLLERS //must execute only after ai behaviors are initialized
+ dependencies = list(
+ /datum/controller/subsystem/ai_controllers
+ )
///List of all the idle ai behaviors
var/list/idle_behaviors = list()
diff --git a/code/controllers/subsystem/processing/fishing.dm b/code/controllers/subsystem/processing/fishing.dm
index abd31293ac0..8220421effe 100644
--- a/code/controllers/subsystem/processing/fishing.dm
+++ b/code/controllers/subsystem/processing/fishing.dm
@@ -1,6 +1,9 @@
/// subsystem for the fishing minigame processing.
PROCESSING_SUBSYSTEM_DEF(fishing)
name = "Fishing"
+ dependencies = list(
+ /datum/controller/subsystem/atoms
+ )
flags = SS_BACKGROUND
wait = 0.05 SECONDS // If you raise it to 0.1 SECONDS, you better also modify [datum/fish_movement/move_fish()]
///A list of cached fish icons
diff --git a/code/controllers/subsystem/processing/greyscale.dm b/code/controllers/subsystem/processing/greyscale.dm
index 901a3bf930d..fcd7b482847 100644
--- a/code/controllers/subsystem/processing/greyscale.dm
+++ b/code/controllers/subsystem/processing/greyscale.dm
@@ -7,9 +7,8 @@
PROCESSING_SUBSYSTEM_DEF(greyscale)
name = "Greyscale"
flags = SS_BACKGROUND
- init_order = INIT_ORDER_GREYSCALE
wait = 3 SECONDS
-
+ init_stage = INITSTAGE_EARLY
var/list/datum/greyscale_config/configurations = list()
var/list/datum/greyscale_layer/layer_types = list()
#ifdef USE_RUSTG_ICONFORGE_GAGS
diff --git a/code/controllers/subsystem/processing/instruments.dm b/code/controllers/subsystem/processing/instruments.dm
index 1cfbb144e5f..fd486d419eb 100644
--- a/code/controllers/subsystem/processing/instruments.dm
+++ b/code/controllers/subsystem/processing/instruments.dm
@@ -1,7 +1,6 @@
PROCESSING_SUBSYSTEM_DEF(instruments)
name = "Instruments"
wait = 0.5
- init_order = INIT_ORDER_INSTRUMENTS
flags = SS_KEEP_TIMING
priority = FIRE_PRIORITY_INSTRUMENTS
/// List of all instrument data, associative id = datum
diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm
index 43c84864ad9..f3300726029 100644
--- a/code/controllers/subsystem/processing/quirks.dm
+++ b/code/controllers/subsystem/processing/quirks.dm
@@ -47,7 +47,6 @@ GLOBAL_LIST_INIT(quirk_string_blacklist, generate_quirk_string_blacklist())
// - Quirk datums are stored and hold different effects, as well as being a vector for applying trait string
PROCESSING_SUBSYSTEM_DEF(quirks)
name = "Quirks"
- init_order = INIT_ORDER_QUIRKS
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME
wait = 1 SECONDS
diff --git a/code/controllers/subsystem/processing/reagents.dm b/code/controllers/subsystem/processing/reagents.dm
index 503be4384f4..5e64e259db4 100644
--- a/code/controllers/subsystem/processing/reagents.dm
+++ b/code/controllers/subsystem/processing/reagents.dm
@@ -2,11 +2,11 @@
PROCESSING_SUBSYSTEM_DEF(reagents)
name = "Reagents"
- init_order = INIT_ORDER_REAGENTS
priority = FIRE_PRIORITY_REAGENTS
wait = 0.25 SECONDS //You might think that rate_up_lim has to be set to half, but since everything is normalised around seconds_per_tick, it automatically adjusts it to be per second. Magic!
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+ init_stage = INITSTAGE_EARLY
///What time was it when we last ticked
var/previous_world_time = 0
diff --git a/code/controllers/subsystem/processing/station.dm b/code/controllers/subsystem/processing/station.dm
index c58840cfa7a..45a10f3a974 100644
--- a/code/controllers/subsystem/processing/station.dm
+++ b/code/controllers/subsystem/processing/station.dm
@@ -1,6 +1,5 @@
PROCESSING_SUBSYSTEM_DEF(station)
name = "Station"
- init_order = INIT_ORDER_STATION
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME
wait = 5 SECONDS
diff --git a/code/controllers/subsystem/profiler.dm b/code/controllers/subsystem/profiler.dm
index d149bc5e77c..fe733a1ccfa 100644
--- a/code/controllers/subsystem/profiler.dm
+++ b/code/controllers/subsystem/profiler.dm
@@ -1,6 +1,6 @@
SUBSYSTEM_DEF(profiler)
name = "Profiler"
- init_order = INIT_ORDER_PROFILER
+ init_stage = INITSTAGE_FIRST
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
wait = 300 SECONDS
var/fetch_cost = 0
diff --git a/code/controllers/subsystem/queuelinks.dm b/code/controllers/subsystem/queuelinks.dm
index 1f891ee3ea5..20b55622931 100644
--- a/code/controllers/subsystem/queuelinks.dm
+++ b/code/controllers/subsystem/queuelinks.dm
@@ -2,14 +2,10 @@
SUBSYSTEM_DEF(queuelinks)
name = "Queue Links"
- flags = SS_NO_FIRE
- init_order = INIT_ORDER_QUEUELINKS
+ flags = SS_NO_FIRE | SS_NO_INIT
///assoc list of pending queues, id = /datum/queue_link
var/list/queues = list()
-/datum/controller/subsystem/queuelinks/Initialize()
- return SS_INIT_SUCCESS
-
///Creates or adds to a queue with the id supplied, if the queue is now or above the size of the queue, calls MatchedLinks and clears queue.
/// queues with a size of 0 wait never pop until something is added with an actual queue_max
/datum/controller/subsystem/queuelinks/proc/add_to_queue(atom/what, id, queue_max = 0)
diff --git a/code/controllers/subsystem/radioactive_nebula.dm b/code/controllers/subsystem/radioactive_nebula.dm
index 17c0cc9b3da..585514a7f0d 100644
--- a/code/controllers/subsystem/radioactive_nebula.dm
+++ b/code/controllers/subsystem/radioactive_nebula.dm
@@ -4,6 +4,9 @@
/// Controls making objects irradiated when Radioactive Nebula is in effect.
SUBSYSTEM_DEF(radioactive_nebula)
name = "Radioactive Nebula"
+ dependencies = list(
+ /datum/controller/subsystem/processing/station
+ )
flags = SS_BACKGROUND
wait = 30 SECONDS
diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm
index 9979a1a7312..b06b6ff6f85 100644
--- a/code/controllers/subsystem/research.dm
+++ b/code/controllers/subsystem/research.dm
@@ -3,7 +3,9 @@ SUBSYSTEM_DEF(research)
name = "Research"
priority = FIRE_PRIORITY_RESEARCH
wait = 10
- init_order = INIT_ORDER_RESEARCH
+ dependencies = list(
+ /datum/controller/subsystem/processing/station
+ )
//TECHWEB STATIC
var/list/techweb_nodes = list() //associative id = node datum
var/list/techweb_designs = list() //associative id = node datum
diff --git a/code/controllers/subsystem/restaurant.dm b/code/controllers/subsystem/restaurant.dm
index 7a795f72115..034a7610cb6 100644
--- a/code/controllers/subsystem/restaurant.dm
+++ b/code/controllers/subsystem/restaurant.dm
@@ -5,7 +5,6 @@ This subsystem exists to serve as a holder for important info for the restaurant
SUBSYSTEM_DEF(restaurant)
name = "Restaurant"
wait = 20 SECONDS //Roll for new guests but don't do it too fast.
- init_order = INIT_ORDER_RESTAURANT
flags = SS_NO_FIRE
///All venues that exist, assoc list of type - reference
var/list/all_venues = list()
diff --git a/code/controllers/subsystem/security_level.dm b/code/controllers/subsystem/security_level.dm
index cb61af0f3e0..8ad6da2847b 100644
--- a/code/controllers/subsystem/security_level.dm
+++ b/code/controllers/subsystem/security_level.dm
@@ -1,7 +1,6 @@
SUBSYSTEM_DEF(security_level)
name = "Security Level"
can_fire = FALSE // We will control when we fire in this subsystem
- init_order = INIT_ORDER_SECURITY_LEVEL
/// Currently set security level
var/datum/security_level/current_security_level
/// A list of initialised security level datums.
diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm
index f011d01ca67..c4428f297ae 100644
--- a/code/controllers/subsystem/server_maint.dm
+++ b/code/controllers/subsystem/server_maint.dm
@@ -5,7 +5,6 @@ SUBSYSTEM_DEF(server_maint)
wait = 6
flags = SS_POST_FIRE_TIMING
priority = FIRE_PRIORITY_SERVER_MAINT
- init_order = INIT_ORDER_SERVER_MAINT
init_stage = INITSTAGE_EARLY
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun
@@ -34,11 +33,11 @@ SUBSYSTEM_DEF(server_maint)
"dead_mob_list" = GLOB.dead_mob_list,
"keyloop_list" = GLOB.keyloop_list, //A null here will cause new clients to be unable to move. totally unacceptable
)
-
+
var/datum/tgs_version/tgsversion = world.TgsVersion()
if(tgsversion)
SSblackbox.record_feedback("text", "server_tools", 1, tgsversion.raw_parameter)
-
+
return SS_INIT_SUCCESS
/datum/controller/subsystem/server_maint/fire(resumed = FALSE)
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index 060e50e4159..231e0f027e4 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -9,7 +9,11 @@
SUBSYSTEM_DEF(shuttle)
name = "Shuttle"
wait = 1 SECONDS
- init_order = INIT_ORDER_SHUTTLE
+ dependencies = list(
+ /datum/controller/subsystem/mapping,
+ /datum/controller/subsystem/atoms,
+ /datum/controller/subsystem/air
+ )
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_SETUP | RUNLEVEL_GAME
diff --git a/code/controllers/subsystem/skills.dm b/code/controllers/subsystem/skills.dm
index fdf868cf1f7..0ece2ac2aaa 100644
--- a/code/controllers/subsystem/skills.dm
+++ b/code/controllers/subsystem/skills.dm
@@ -5,7 +5,6 @@ This subsystem mostly exists to populate and manage the skill singletons.
SUBSYSTEM_DEF(skills)
name = "Skills"
flags = SS_NO_FIRE
- init_order = INIT_ORDER_SKILLS
///Dictionary of skill.type || skill ref
var/list/all_skills = list()
///List of level names with index corresponding to skill level
diff --git a/code/controllers/subsystem/sounds.dm b/code/controllers/subsystem/sounds.dm
index bcc06e67f63..5f4807d6cca 100644
--- a/code/controllers/subsystem/sounds.dm
+++ b/code/controllers/subsystem/sounds.dm
@@ -3,7 +3,7 @@
SUBSYSTEM_DEF(sounds)
name = "Sounds"
flags = SS_NO_FIRE
- init_order = INIT_ORDER_SOUNDS
+ init_stage = INITSTAGE_EARLY
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
/// Amount of channels to reserve for random usage rather than reservations being allowed to reserve all channels. Also a nice safeguard for when someone screws up.
var/static/random_channels_min = 50
diff --git a/code/controllers/subsystem/spatial_gridmap.dm b/code/controllers/subsystem/spatial_gridmap.dm
index d906de2dc7b..e8c8df0171e 100644
--- a/code/controllers/subsystem/spatial_gridmap.dm
+++ b/code/controllers/subsystem/spatial_gridmap.dm
@@ -79,7 +79,9 @@
*/
SUBSYSTEM_DEF(spatial_grid)
can_fire = FALSE
- init_order = INIT_ORDER_SPATIAL_GRID
+ dependencies = list(
+ /datum/controller/subsystem/mapping
+ )
name = "Spatial Grid"
///list of the spatial_grid_cell datums per z level, arranged in the order of y index then x index
diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm
index d2912cb7fe1..44c5f54aa68 100644
--- a/code/controllers/subsystem/statpanel.dm
+++ b/code/controllers/subsystem/statpanel.dm
@@ -1,8 +1,6 @@
SUBSYSTEM_DEF(statpanels)
name = "Stat Panels"
wait = 4
- init_order = INIT_ORDER_STATPANELS
- init_stage = INITSTAGE_EARLY
priority = FIRE_PRIORITY_STATPANEL
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
flags = SS_NO_INIT
diff --git a/code/controllers/subsystem/stickyban.dm b/code/controllers/subsystem/stickyban.dm
index 757df6a2266..8a955b2fb0d 100644
--- a/code/controllers/subsystem/stickyban.dm
+++ b/code/controllers/subsystem/stickyban.dm
@@ -1,6 +1,5 @@
SUBSYSTEM_DEF(stickyban)
name = "PRISM"
- init_order = INIT_ORDER_STICKY_BAN
flags = SS_NO_FIRE
var/list/cache = list()
diff --git a/code/controllers/subsystem/stock_market.dm b/code/controllers/subsystem/stock_market.dm
index 7d0e0ea9262..1cce5a8c549 100644
--- a/code/controllers/subsystem/stock_market.dm
+++ b/code/controllers/subsystem/stock_market.dm
@@ -2,7 +2,6 @@
SUBSYSTEM_DEF(stock_market)
name = "Stock Market"
wait = 60 SECONDS
- init_order = INIT_ORDER_DEFAULT
runlevels = RUNLEVEL_GAME
/// Associated list of materials and their prices at the given time.
diff --git a/code/controllers/subsystem/tcgsetup.dm b/code/controllers/subsystem/tcgsetup.dm
index e52474adac5..5904c821e79 100644
--- a/code/controllers/subsystem/tcgsetup.dm
+++ b/code/controllers/subsystem/tcgsetup.dm
@@ -1,7 +1,6 @@
SUBSYSTEM_DEF(trading_card_game)
name = "Trading Card Game"
flags = SS_NO_FIRE
- init_order = INIT_ORDER_TCG
/// Base directory for all related string files
var/card_directory = "strings/tcg"
/// List of card files to load
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index e0c153749f2..a957ff9b2e4 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -3,8 +3,6 @@
SUBSYSTEM_DEF(ticker)
name = "Ticker"
- init_order = INIT_ORDER_TICKER
-
priority = FIRE_PRIORITY_TICKER
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME
diff --git a/code/controllers/subsystem/time_track.dm b/code/controllers/subsystem/time_track.dm
index 4c706fdaf6d..57ff27a2737 100644
--- a/code/controllers/subsystem/time_track.dm
+++ b/code/controllers/subsystem/time_track.dm
@@ -1,7 +1,6 @@
SUBSYSTEM_DEF(time_track)
name = "Time Tracking"
wait = 100
- init_order = INIT_ORDER_TIMETRACK
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/time_dilation_current = 0
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index c314fa7d38b..2b2d9393287 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -17,7 +17,6 @@
SUBSYSTEM_DEF(timer)
name = "Timer"
wait = 1 // SS_TICKER subsystem, so wait is in ticks
- init_order = INIT_ORDER_TIMER
priority = FIRE_PRIORITY_TIMER
flags = SS_TICKER|SS_NO_INIT
diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm
index 8df9349ff03..2d526e31353 100644
--- a/code/controllers/subsystem/title.dm
+++ b/code/controllers/subsystem/title.dm
@@ -1,9 +1,7 @@
SUBSYSTEM_DEF(title)
name = "Title Screen"
flags = SS_NO_FIRE
- init_order = INIT_ORDER_TITLE
init_stage = INITSTAGE_EARLY
-
var/file_path
var/icon/icon
var/icon/previous_icon
diff --git a/code/controllers/subsystem/traitor.dm b/code/controllers/subsystem/traitor.dm
index afa15e7606c..599fd91e578 100644
--- a/code/controllers/subsystem/traitor.dm
+++ b/code/controllers/subsystem/traitor.dm
@@ -1,5 +1,9 @@
SUBSYSTEM_DEF(traitor)
name = "Traitor"
+ dependencies = list(
+ /datum/controller/subsystem/mapping,
+ /datum/controller/subsystem/atoms
+ )
flags = SS_KEEP_TIMING
wait = 10 SECONDS
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
diff --git a/code/controllers/subsystem/tts.dm b/code/controllers/subsystem/tts.dm
index 0fccd2eeefa..9d3f7d6b76f 100644
--- a/code/controllers/subsystem/tts.dm
+++ b/code/controllers/subsystem/tts.dm
@@ -2,7 +2,6 @@ SUBSYSTEM_DEF(tts)
name = "Text To Speech"
wait = 0.05 SECONDS
priority = FIRE_PRIORITY_TTS
- init_order = INIT_ORDER_TTS
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME
/// Queued HTTP requests that have yet to be sent. TTS requests are handled as lists rather than datums.
diff --git a/code/controllers/subsystem/unplanned_controllers.dm b/code/controllers/subsystem/unplanned_controllers.dm
index 57b4ed68f16..e33e212c404 100644
--- a/code/controllers/subsystem/unplanned_controllers.dm
+++ b/code/controllers/subsystem/unplanned_controllers.dm
@@ -4,7 +4,9 @@ SUBSYSTEM_DEF(unplanned_controllers)
name = "Unplanned AI Controllers"
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND
priority = FIRE_PRIORITY_UNPLANNED_NPC
- init_order = INIT_ORDER_AI_CONTROLLERS
+ dependencies = list(
+ /datum/controller/subsystem/movement/ai_movement
+ )
wait = 0.25 SECONDS
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
///what ai status are we interested in
diff --git a/code/controllers/subsystem/vis_overlays.dm b/code/controllers/subsystem/vis_overlays.dm
index 1afe1c62100..717455a77bc 100644
--- a/code/controllers/subsystem/vis_overlays.dm
+++ b/code/controllers/subsystem/vis_overlays.dm
@@ -1,16 +1,12 @@
SUBSYSTEM_DEF(vis_overlays)
name = "Vis contents overlays"
wait = 1 MINUTES
+ flags = SS_NO_INIT
priority = FIRE_PRIORITY_VIS
- init_order = INIT_ORDER_VIS
- var/list/vis_overlay_cache
+ var/list/vis_overlay_cache = list()
var/list/currentrun
-/datum/controller/subsystem/vis_overlays/Initialize()
- vis_overlay_cache = list()
- return SS_INIT_SUCCESS
-
/datum/controller/subsystem/vis_overlays/fire(resumed = FALSE)
if(!resumed)
currentrun = vis_overlay_cache.Copy()
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index 84880a47948..5dd3f537bfc 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -5,7 +5,6 @@ SUBSYSTEM_DEF(vote)
name = "Vote"
wait = 1 SECONDS
flags = SS_KEEP_TIMING
- init_order = INIT_ORDER_VOTE
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
/// A list of all generated action buttons
diff --git a/code/controllers/subsystem/wardrobe.dm b/code/controllers/subsystem/wardrobe.dm
index ac435cc9a6d..d52752402ab 100644
--- a/code/controllers/subsystem/wardrobe.dm
+++ b/code/controllers/subsystem/wardrobe.dm
@@ -9,6 +9,10 @@ SUBSYSTEM_DEF(wardrobe)
name = "Wardrobe"
wait = 10 // This is more like a queue then anything else
flags = SS_BACKGROUND
+ dependencies = list(
+ /datum/controller/subsystem/atoms,
+ /datum/controller/subsystem/mapping
+ )
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT // We're going to fill up our cache while players sit in the lobby
/// How much to cache outfit items
/// Multiplier, 2 would mean cache enough items to stock 1 of each preloaded order twice, etc
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index b8496a623eb..516722c8d00 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -2,6 +2,9 @@
SUBSYSTEM_DEF(weather)
name = "Weather"
flags = SS_BACKGROUND
+ dependencies = list(
+ /datum/controller/subsystem/mapping
+ )
wait = 10
runlevels = RUNLEVEL_GAME
var/list/processing = list()
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 98b2c87094e..fa09f840805 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -917,3 +917,41 @@ ADMIN_VERB(queue_tracy, R_DEBUG, "Toggle Tracy Next Round", "Toggle running the
ADMIN_VERB_CUSTOM_EXIST_CHECK(queue_tracy)
return CONFIG_GET(flag/allow_tracy_queue) && fexists(TRACY_DLL_PATH)
#endif
+
+/datum/mc_dependency_ui
+
+/datum/mc_dependency_ui/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "MCDependencyDebug")
+ ui.set_autoupdate(FALSE)
+ ui.open()
+
+/datum/mc_dependency_ui/ui_state(mob/user)
+ return ADMIN_STATE(R_DEBUG)
+
+/datum/mc_dependency_ui/ui_data(mob/user)
+ var/list/data = list()
+
+ var/list/subsystems = Master.subsystems.Copy()
+ sortTim(subsystems, GLOBAL_PROC_REF(cmp_subsystem_init))
+
+ for(var/datum/controller/subsystem/subsystem as anything in subsystems)
+ var/list/sub_data = list()
+ sub_data["name"] = subsystem.name
+ var/list/dependents = list()
+ for(var/datum/controller/subsystem/dependent as anything in subsystem.dependents)
+ dependents += dependent.name
+ sub_data["dependents"] = dependents
+ data += list(sub_data)
+
+ return list(
+ "subsystems" = data
+ )
+
+/datum/mc_dependency_ui/ui_assets(mob/user)
+ return list(get_asset_datum(/datum/asset/simple/plane_background))
+
+ADMIN_VERB(debug_mc_dependencies, R_DEBUG, "Debug MC Dependencies", "Debug MC dependencies.", ADMIN_CATEGORY_DEBUG)
+ var/datum/mc_dependency_ui/data = new /datum/mc_dependency_ui()
+ data.ui_interact(usr)
diff --git a/code/modules/admin/view_variables/debug_variables.dm b/code/modules/admin/view_variables/debug_variables.dm
index 34b34369299..c1c81d711cb 100644
--- a/code/modules/admin/view_variables/debug_variables.dm
+++ b/code/modules/admin/view_variables/debug_variables.dm
@@ -89,7 +89,10 @@
return "/list ([list_value.len])"
// if it's a number, is it a bitflag?
- var/list/valid_bitflags = get_valid_bitflags(name)
+ var/list/valid_bitflags
+ if(!isnum(name))
+ valid_bitflags = get_valid_bitflags(name)
+
if(!length(valid_bitflags))
return "[VV_HTML_ENCODE(value)]"
diff --git a/tgui/packages/tgui/interfaces/MCDependencyDebug.tsx b/tgui/packages/tgui/interfaces/MCDependencyDebug.tsx
new file mode 100644
index 00000000000..52c4b20fc07
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/MCDependencyDebug.tsx
@@ -0,0 +1,295 @@
+import { useLayoutEffect, useMemo, useRef, useState } from 'react';
+import { Box, InfinitePlane, Stack } from 'tgui-core/components';
+import { classes } from 'tgui-core/react';
+
+import { resolveAsset } from '../assets';
+import { useBackend } from '../backend';
+import { Window } from '../layouts';
+import { Connection, Connections, ConnectionStyle } from './common/Connections';
+import { ABSOLUTE_Y_OFFSET } from './IntegratedCircuit/constants';
+
+type Coord = {
+ x: number;
+ y: number;
+};
+
+type SubsystemData = {
+ name: string;
+ dependents: string[];
+};
+
+type Subsystem = {
+ name: string;
+ dependents: Subsystem[];
+};
+
+type DependencyData = {
+ subsystems: SubsystemData[];
+};
+
+function getPosition(el: HTMLElement | null): Coord {
+ let xPos = 0;
+ let yPos = 0;
+
+ while (el !== null) {
+ xPos += el.offsetLeft;
+ yPos += el.offsetTop;
+ el = el.offsetParent as HTMLElement | null;
+ }
+
+ return {
+ x: xPos,
+ y: yPos + ABSOLUTE_Y_OFFSET,
+ };
+}
+
+type GraphNodeProps = {
+ name: string;
+ x: number;
+ y: number;
+ inputRef: (element: HTMLElement) => void;
+ outputRef: (element: HTMLElement) => void;
+};
+
+function GraphNode(props: GraphNodeProps) {
+ const { name, inputRef, outputRef, x, y } = props;
+
+ return (
+
+
+
+
+
+
+
+
+ {name}
+
+
+
+
+
+
+
+
+
+ );
+}
+
+type SubsystemRef = {
+ input?: HTMLElement;
+ output?: HTMLElement;
+};
+
+type ConnectionRef = Record;
+
+type SubsystemCoord = {
+ input: Coord;
+ output: Coord;
+};
+
+type ConnectionData = Record;
+
+type SubsystemLayer = Record;
+
+type SubsystemMap = Record;
+
+function evaluateSubsystemLayer(
+ subsystem: Subsystem,
+ depth: number,
+ data: SubsystemLayer,
+) {
+ data[subsystem.name] = Math.max(depth, data[subsystem.name] || 0);
+ for (let i = 0; i < subsystem.dependents.length; i++) {
+ evaluateSubsystemLayer(subsystem.dependents[i], depth + 1, data);
+ }
+}
+
+export function MCDependencyDebug(props) {
+ const { data } = useBackend();
+ const { subsystems } = data;
+ const connectionDom = useRef({});
+ const [connectionData, setConnectionData] = useState({});
+
+ useLayoutEffect(() => {
+ const doms = connectionDom.current;
+ const newConnectionData: ConnectionData = {};
+ for (let i = 0; i < subsystems.length; i++) {
+ const subsystem = subsystems[i];
+ const domElements = doms[subsystem.name];
+ if (domElements.input === undefined || domElements.output === undefined) {
+ continue;
+ }
+ newConnectionData[subsystem.name] = {
+ input: getPosition(domElements.input),
+ output: getPosition(domElements.output),
+ };
+ }
+ setConnectionData(newConnectionData);
+ }, [subsystems]);
+
+ const subsystemsLayered = useMemo(() => {
+ const namesToSubsystem: SubsystemMap = {};
+ const subsystemsGraph: Subsystem[] = [];
+
+ for (let i = 0; i < subsystems.length; i++) {
+ const subsystem = subsystems[i];
+ const subsystemNode = {
+ name: subsystem.name,
+ dependents: [],
+ };
+ namesToSubsystem[subsystem.name] = subsystemNode;
+ subsystemsGraph.push(subsystemNode);
+ }
+
+ for (let i = 0; i < subsystems.length; i++) {
+ const subsystem = subsystems[i];
+ subsystemsGraph[i].dependents = subsystem.dependents.map(
+ (val) => namesToSubsystem[val],
+ );
+ }
+
+ const subsystemLayer: SubsystemLayer = {};
+ for (let i = 0; i < subsystemsGraph.length; i++) {
+ const subsystem = subsystemsGraph[i];
+ evaluateSubsystemLayer(subsystem, 1, subsystemLayer);
+ }
+ return subsystemLayer;
+ }, [subsystems]);
+
+ const connections: Connection[] = [];
+ for (let i = 0; i < subsystems.length; i++) {
+ const subsystem = subsystems[i];
+ const from = connectionData[subsystem.name];
+ if (from === undefined) {
+ continue;
+ }
+ for (let j = 0; j < subsystem.dependents.length; j++) {
+ const outputSubsystem = subsystem.dependents[j];
+ const target = connectionData[outputSubsystem];
+ if (target === undefined) {
+ continue;
+ }
+
+ connections.push({
+ from: from.output,
+ to: target.input,
+ style: ConnectionStyle.SUBWAY_SHARP,
+ index: i,
+ color: `hsl(${60 + 5 * (i % 30)}, 50%, ${50 + (i % 30)}%)`,
+ });
+ }
+ }
+
+ return (
+
+
+
+
+ First
+
+ {subsystems.map((subsystem, y) => (
+ {
+ if (connectionDom.current[subsystem.name] === undefined) {
+ connectionDom.current[subsystem.name] = {};
+ }
+ connectionDom.current[subsystem.name].input = element;
+ }}
+ outputRef={(element) => {
+ if (connectionDom.current[subsystem.name] === undefined) {
+ connectionDom.current[subsystem.name] = {};
+ }
+ connectionDom.current[subsystem.name].output = element;
+ }}
+ />
+ ))}
+
+ Last
+
+
+
+
+
+ );
+}
diff --git a/tgui/packages/tgui/interfaces/common/Connections.tsx b/tgui/packages/tgui/interfaces/common/Connections.tsx
index 55e6e31895d..068da736082 100644
--- a/tgui/packages/tgui/interfaces/common/Connections.tsx
+++ b/tgui/packages/tgui/interfaces/common/Connections.tsx
@@ -4,9 +4,10 @@ import { CSS_COLORS } from '../../constants';
const SVG_CURVE_INTENSITY = 64;
-enum ConnectionStyle {
+export enum ConnectionStyle {
CURVE = 'curve',
SUBWAY = 'subway',
+ SUBWAY_SHARP = 'subway sharp',
}
export type Position = {
@@ -25,6 +26,8 @@ export type Connection = {
style?: ConnectionStyle;
// Optional: the ref of what element this connection is sourced
ref?: string;
+ // Optional: Used to group some connections together
+ index?: number;
};
export const Connections = (props: {
@@ -78,6 +81,17 @@ export const Connections = (props: {
path += `L ${to.x} ${to.y}`;
break;
}
+ case ConnectionStyle.SUBWAY_SHARP: {
+ let offset = 16;
+ if (val.index !== undefined) {
+ offset = 8 * (val.index % 32) + 32;
+ }
+ const yDiff = Math.abs(to.y - from.y);
+ path += `L ${Math.max(from.x + offset, to.x - offset)} ${from.y}`;
+ path += `L ${Math.max(from.x + offset, to.x - offset)} ${to.y}`;
+ path += `L ${to.x} ${to.y}`;
+ break;
+ }
}
return (
@@ -85,6 +99,7 @@ export const Connections = (props: {
className={classes([
isColorClass(val.color) && `color-stroke-${val.color}`,
])}
+ stroke={(!isColorClass(val.color) && val.color) || undefined}
key={index}
d={path}
fill="transparent"