diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm
index 0b9a85d9194..e2452ff032b 100644
--- a/code/__DEFINES/MC.dm
+++ b/code/__DEFINES/MC.dm
@@ -80,6 +80,17 @@
}\
/datum/controller/subsystem/timer/##X
+<<<<<<< HEAD
+=======
+#define MOVEMENT_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/movement/##X);\
+/datum/controller/subsystem/movement/##X/New(){\
+ NEW_SS_GLOBAL(SS##X);\
+ PreInit();\
+ ss_id="movement_[#X]";\
+}\
+/datum/controller/subsystem/movement/##X
+
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
#define PROCESSING_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/processing/##X);\
/datum/controller/subsystem/processing/##X/New(){\
NEW_SS_GLOBAL(SS##X);\
diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm
index db856847673..8079a666519 100644
--- a/code/controllers/failsafe.dm
+++ b/code/controllers/failsafe.dm
@@ -92,6 +92,61 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
defcon = 5
sleep(initial(processing_interval))
+<<<<<<< HEAD
+=======
+//Emergency loop used when Master got deleted or the main loop exited while Defcon == 0
+//Loop is driven externally so runtimes only cancel the current recovery attempt
+/datum/controller/failsafe/proc/emergency_loop()
+ //The code in this proc should be kept as simple as possible, anything complicated like to_chat might rely on master existing and runtime
+ //The goal should always be to get a new Master up and running before anything else
+ . = -1
+ switch (defcon) //The lower defcon goes the harder we try to fix the MC
+ if (2 to 3) //Try to normally recreate the MC two times
+ . = Recreate_MC()
+ if (1) //Delete the old MC first so we don't transfer any info, in case that caused any issues
+ del(Master)
+ . = Recreate_MC()
+
+ if (. == 1) //We were able to create a new master
+ to_chat_immediate(world, "Master Controller failure detected. Attempting recovery.\nThings may freeze up for a minute or two (or break entirely).")
+ master_iteration = 0
+ SSticker.Recover() //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, "Failsafe recovered MC while in emergency state [defcon_pretty()]")
+ else
+ log_game("FailSafe: Failsafe in emergency state and was unable to recreate MC while in defcon state [defcon_pretty()].")
+ message_admins("Failsafe in emergency state and master down, trying to recreate MC while in defcon level [defcon_pretty()] failed.")
+
+///Recreate all SSs which will still cause data survive due to Recover(), the new Master will then find and take them from global.vars
+/proc/recover_all_SS_and_recreate_master()
+ del(Master)
+ var/list/subsytem_types = subtypesof(/datum/controller/subsystem)
+ sortTim(subsytem_types, /proc/cmp_subsystem_init)
+ for(var/I in subsytem_types)
+ new I
+ . = Recreate_MC()
+ if (. == 1) //We were able to create a new master
+ SSticker.Recover() //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, "MC successfully recreated after recovering all subsystems!")
+ else
+ message_admins("Failed to create new MC!")
+
+///Delete all existing SS to basically start over
+/proc/delete_all_SS_and_recreate_master()
+ del(Master)
+ for(var/global_var in global.vars)
+ if (istype(global.vars[global_var], /datum/controller/subsystem))
+ del(global.vars[global_var])
+ . = Recreate_MC()
+ if (. == 1) //We were able to create a new master
+ SSticker.Recover() //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, "MC successfully recreated after deleting and recreating all subsystems!")
+ else
+ message_admins("Failed to create new MC!")
+
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
/datum/controller/failsafe/proc/defcon_pretty()
return defcon
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index fea1fd209ef..cd051e24c47 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -20,8 +20,14 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
Initialize()
+<<<<<<< HEAD
/datum/controller/global_vars/Destroy()
//fuck off kevinz
+=======
+/datum/controller/global_vars/Destroy(force)
+ // This is done to prevent an exploit where admins can get around protected vars
+ SHOULD_CALL_PARENT(0)
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
return QDEL_HINT_IWILLGC
/datum/controller/global_vars/stat_entry()
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index f20856bc01c..2f297fba55d 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -84,11 +84,30 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
Recover()
qdel(Master)
else
+<<<<<<< HEAD
var/list/subsytem_types = subtypesof(/datum/controller/subsystem)
sortTim(subsytem_types, /proc/cmp_subsystem_init)
for(var/I in subsytem_types)
_subsystems += new I
Master = src
+=======
+ //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, /proc/cmp_subsystem_init)
+ //Find any abandoned subsystem from the previous master (if there was any)
+ var/list/existing_subsystems = list()
+ for(var/global_var in global.vars)
+ if (istype(global.vars[global_var], /datum/controller/subsystem))
+ existing_subsystems += global.vars[global_var]
+ //Either init a new SS or if an existing one was found use that
+ for(var/I in subsystem_types)
+ var/ss_idx = existing_subsystems.Find(I)
+ if (ss_idx)
+ _subsystems += existing_subsystems[ss_idx]
+ else
+ _subsystems += new I
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
if(!GLOB)
new /datum/controller/global_vars
@@ -192,7 +211,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
// Initialize subsystems.
current_ticklimit = CONFIG_GET(number/tick_limit_mc_init)
for (var/datum/controller/subsystem/SS in subsystems)
+<<<<<<< HEAD
if (SS.flags & SS_NO_INIT)
+=======
+ if (SS.flags & SS_NO_INIT || SS.initialized) //Don't init SSs with the correspondig flag or if they already are initialzized
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
continue
SS.Initialize(REALTIMEOFDAY)
CHECK_TICK
diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm
index 7f57cba7945..f47243f5517 100644
--- a/code/controllers/subsystem.dm
+++ b/code/controllers/subsystem.dm
@@ -222,8 +222,13 @@
//this is so the subsystem doesn't rapid fire to make up missed ticks causing more lag
if (var_value)
next_fire = world.time + wait
+<<<<<<< HEAD
if ("queued_priority") //editing this breaks things.
return 0
+=======
+ if (NAMEOF(src, queued_priority)) //editing this breaks things.
+ return FALSE
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
. = ..()
diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm
index 18b795196bf..9ddd29f2e3d 100644
--- a/code/game/objects/structures/traps.dm
+++ b/code/game/objects/structures/traps.dm
@@ -49,7 +49,11 @@
// Makes the trap visible, and starts the cooldown until it's
// able to be triggered again.
visible_message(flare_message)
+<<<<<<< HEAD
if(sparks)
+=======
+ if(sparks && Master.current_runlevel)
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
spark_system.start()
alpha = 200
last_trigger = world.time
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 1400469d311..d1c16ca227f 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -422,7 +422,11 @@
update()
/obj/machinery/light/proc/broken_sparks(start_only=FALSE)
+<<<<<<< HEAD
if(!QDELETED(src) && status == LIGHT_BROKEN && has_power())
+=======
+ if(!QDELETED(src) && status == LIGHT_BROKEN && has_power() && Master.current_runlevel)
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
if(!start_only)
do_sparks(3, TRUE, src)
var/delay = rand(BROKEN_SPARKS_MIN, BROKEN_SPARKS_MAX)
@@ -754,7 +758,11 @@
if(status == LIGHT_EMPTY || status == LIGHT_BROKEN)
return
+<<<<<<< HEAD
if(!skip_sound_and_sparks)
+=======
+ if(!skip_sound_and_sparks && Master.current_runlevel) //not completly sure disabling this during initialize is needed but then again there are broken lights after initialize
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
if(status == LIGHT_OK || status == LIGHT_BURNED)
playsound(src.loc, 'sound/effects/glasshit.ogg', 75, 1)
if(on)
diff --git a/code/modules/tgchat/to_chat.dm b/code/modules/tgchat/to_chat.dm
index 0bc97d09c66..550285eb8d7 100644
--- a/code/modules/tgchat/to_chat.dm
+++ b/code/modules/tgchat/to_chat.dm
@@ -60,7 +60,11 @@
// FIXME: These flags are now pointless and have no effect
handle_whitespace = TRUE,
trailing_newline = TRUE)
+<<<<<<< HEAD
if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized)
+=======
+ if(isnull(Master) || Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized)
+>>>>>>> bdeb199b49... Revert "Brings our MC up to date with TG (#7285)" (#7597)
to_chat_immediate(target, html, type, text)
return
if(!target || (!html && !text))