diff --git a/code/controllers/configuration/entries/server.dm b/code/controllers/configuration/entries/server.dm
index 1acf8a11ca..ee40df573c 100644
--- a/code/controllers/configuration/entries/server.dm
+++ b/code/controllers/configuration/entries/server.dm
@@ -88,3 +88,6 @@
/datum/config_entry/number/rounds_until_hard_restart
config_entry_value = -1
min_val = 0
+
+/datum/config_entry/string/force_gamemode
+ config_entry_value = null
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index d2a4882f82..6f1fe6d8d0 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -71,6 +71,9 @@ SUBSYSTEM_DEF(ticker)
var/station_integrity = 100 // stored at roundend for use in some antag goals
var/emergency_reason
+ /// If the gamemode fails to be run too many times, we swap to a preset gamemode, this should give admins time to set their preferred one
+ var/emergency_swap = 0
+
/datum/controller/subsystem/ticker/Initialize(timeofday)
load_mode()
@@ -179,7 +182,11 @@ SUBSYSTEM_DEF(ticker)
timeLeft = 0
if(!modevoted)
- send_gamemode_vote()
+ var/forcemode = CONFIG_GET(string/force_gamemode)
+ if(forcemode)
+ force_gamemode(forcemode)
+ if(!forcemode || (GLOB.master_mode == "dynamic" && CONFIG_GET(flag/dynamic_voting)))
+ send_gamemode_vote()
//countdown
if(timeLeft < 0)
return
@@ -227,13 +234,15 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/proc/setup()
to_chat(world, "Starting game...")
var/init_start = world.timeofday
- GLOB.master_mode = "dynamic"
+ if(emergency_swap >= 10)
+ force_gamemode("extended") // If everything fails extended does not have hard requirements for starting, could be changed if needed.
mode = config.pick_mode(GLOB.master_mode)
if(!mode.can_start())
to_chat(world, "Unable to start [mode.name]. Not enough players, [mode.required_players] players and [mode.required_enemies] eligible antagonists needed. Reverting to pre-game lobby.")
qdel(mode)
mode = null
SSjob.ResetOccupations()
+ emergency_swap++
return 0
CHECK_TICK
@@ -252,6 +261,7 @@ SUBSYSTEM_DEF(ticker)
QDEL_NULL(mode)
to_chat(world, "Error setting up [GLOB.master_mode]. Reverting to pre-game lobby.")
SSjob.ResetOccupations()
+ emergency_swap++
return 0
else
message_admins("DEBUG: Bypassing prestart checks...")
@@ -305,6 +315,19 @@ SUBSYSTEM_DEF(ticker)
return TRUE
+/datum/controller/subsystem/ticker/proc/force_gamemode(gamemode)
+ if(gamemode)
+ if(!modevoted)
+ modevoted = TRUE
+ if(gamemode in config.modes)
+ GLOB.master_mode = gamemode
+ SSticker.save_mode(gamemode)
+ message_admins("The gamemode has been set to [gamemode].")
+ else
+ GLOB.master_mode = "extended"
+ SSticker.save_mode("extended")
+ message_admins("force_gamemode proc received an invalid gamemode, defaulting to extended.")
+
/datum/controller/subsystem/ticker/proc/PostSetup()
set waitfor = FALSE
mode.post_setup()
@@ -618,7 +641,7 @@ SUBSYSTEM_DEF(ticker)
/datum/controller/subsystem/ticker/proc/load_mode()
var/mode = trim(file2text("data/mode.txt"))
if(mode)
- GLOB.master_mode = "dynamic"
+ GLOB.master_mode = mode
else
GLOB.master_mode = GLOB.dynamic_forced_extended
log_game("Saved mode is '[GLOB.master_mode]'")
diff --git a/config/entries/server.txt b/config/entries/server.txt
index 0ffd5b21a3..2b905810cd 100644
--- a/config/entries/server.txt
+++ b/config/entries/server.txt
@@ -66,3 +66,9 @@ DISABLE_HIGH_POP_MC_MODE_AMOUNT 60
## Uncomment to set the number of /world/Reboot()s before the DreamDaemon restarts itself. 0 means restart every round. Requires tgstation server tools.
#ROUNDS_UNTIL_HARD_RESTART 10
+
+## Force Gamemode ##
+## Disallows roundstart gamemode voting if not null or uncommented
+## Just input the gamemode lowercase in there, the thing will take a simple string for it
+## Invalid gamemodes will default extended, have fun.
+#FORCE_GAMEMODE