diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm
index 8e743d44521..7fa94f8c8ec 100644
--- a/code/__DEFINES/shuttles.dm
+++ b/code/__DEFINES/shuttles.dm
@@ -5,6 +5,7 @@
#define SHUTTLE_CALL "called"
#define SHUTTLE_DOCKED "docked"
#define SHUTTLE_STRANDED "stranded"
+#define SHUTTLE_DISABLED "disabled"
#define SHUTTLE_ESCAPE "escape"
#define SHUTTLE_ENDGAME "endgame: game over"
#define SHUTTLE_RECHARGING "recharging"
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index 41d3b87598a..87354c3bd11 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -26,6 +26,9 @@ SUBSYSTEM_DEF(shuttle)
var/emergencyCallAmount = 0 //how many times the escape shuttle was called
var/emergencyNoEscape
var/emergencyNoRecall = FALSE
+ var/adminEmergencyNoRecall = FALSE
+ var/lastMode = SHUTTLE_IDLE
+ var/lastCallTime = 6000
var/list/hostileEnvironments = list() //Things blocking escape shuttle from leaving
var/list/tradeBlockade = list() //Things blocking cargo from leaving.
var/supplyBlocked = FALSE
@@ -126,7 +129,7 @@ SUBSYSTEM_DEF(shuttle)
break
/datum/controller/subsystem/shuttle/proc/CheckAutoEvac()
- if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted())
+ if(emergencyNoEscape || adminEmergencyNoRecall || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted())
return
var/threshold = CONFIG_GET(number/emergency_shuttle_autocall_threshold)
@@ -153,10 +156,17 @@ SUBSYSTEM_DEF(shuttle)
emergency.request(null, set_coefficient = 0.4)
/datum/controller/subsystem/shuttle/proc/block_recall(lockout_timer)
+ if(adminEmergencyNoRecall)
+ priority_announce("Error!", "Emergency Shuttle Uplink Alert", 'sound/misc/announce_dig.ogg')
+ addtimer(CALLBACK(src, .proc/unblock_recall), lockout_timer)
+ return
emergencyNoRecall = TRUE
addtimer(CALLBACK(src, .proc/unblock_recall), lockout_timer)
/datum/controller/subsystem/shuttle/proc/unblock_recall()
+ if(adminEmergencyNoRecall)
+ priority_announce("Error!", "Emergency Shuttle Uplink Alert", 'sound/misc/announce_dig.ogg')
+ return
emergencyNoRecall = FALSE
/datum/controller/subsystem/shuttle/proc/getShuttle(id)
@@ -193,7 +203,7 @@ SUBSYSTEM_DEF(shuttle)
if(SHUTTLE_ESCAPE)
to_chat(user, "The emergency shuttle is moving away to a safe distance.")
return FALSE
- if(SHUTTLE_STRANDED)
+ if(SHUTTLE_STRANDED, SHUTTLE_DISABLED)
to_chat(user, "The emergency shuttle has been disabled by CentCom.")
return FALSE
@@ -284,7 +294,7 @@ SUBSYSTEM_DEF(shuttle)
return 1
/datum/controller/subsystem/shuttle/proc/canRecall()
- if(!emergency || emergency.mode != SHUTTLE_CALL || emergencyNoRecall || SSticker.mode.name == "meteor")
+ if(!emergency || emergency.mode != SHUTTLE_CALL || adminEmergencyNoRecall || emergencyNoRecall || SSticker.mode.name == "meteor")
return
var/security_num = seclevel2num(get_security_level())
switch(security_num)
@@ -891,4 +901,3 @@ SUBSYSTEM_DEF(shuttle)
message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.")
log_admin("[key_name(usr)] loaded [mdp] with the shuttle manipulator.")
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]")
-
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index df2a1e99538..2b9f67be872 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -158,7 +158,7 @@
replacementmode = pickweight(usable_modes)
switch(SSshuttle.emergency.mode) //Rounds on the verge of ending don't get new antags, they just run out
- if(SHUTTLE_STRANDED, SHUTTLE_ESCAPE)
+ if(SHUTTLE_STRANDED, SHUTTLE_ESCAPE, SHUTTLE_DISABLED)
return TRUE
if(SHUTTLE_CALL)
if(SSshuttle.emergency.timeLeft(1) < initial(SSshuttle.emergencyCallTime)*0.5)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 818c61b7737..a108d21e6ee 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -59,6 +59,8 @@ GLOBAL_PROTECT(admin_verbs_admin)
/client/proc/jumptoturf, /*allows us to jump to a specific turf*/
/client/proc/admin_call_shuttle, /*allows us to call the emergency shuttle*/
/client/proc/admin_cancel_shuttle, /*allows us to cancel the emergency shuttle, sending it back to centcom*/
+ /client/proc/admin_disable_shuttle, /*allows us to disable the emergency shuttle admin-wise so that it cannot be called*/
+ /client/proc/admin_enable_shuttle, /*undoes the above*/
/client/proc/cmd_admin_direct_narrate, /*send text directly to a player with no padding. Useful for narratives and fluff-text*/
/client/proc/cmd_admin_world_narrate, /*sends text to all players with no padding*/
/client/proc/cmd_admin_local_narrate, /*sends text to all mobs within view of atom*/
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index e5bf8ed3739..787003c8892 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -726,7 +726,6 @@ Traitors and the like can also be revived with the previous role mostly intact.
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Change View Range", "[view]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/admin_call_shuttle()
-
set category = "Admin - Events"
set name = "Call Shuttle"
@@ -736,14 +735,18 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_ADMIN))
return
- var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
- if(confirm != "Yes")
- return
+ var/confirm = alert(src, "You sure?", "Confirm", "Yes", "Yes (No Recall)", "No")
+ switch(confirm)
+ if(null, "No")
+ return
+ if("Yes (No Recall)")
+ SSshuttle.adminEmergencyNoRecall = TRUE
+ SSshuttle.emergency.mode = SHUTTLE_IDLE
SSshuttle.emergency.request()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Call Shuttle") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-called the emergency shuttle.")
- message_admins("[key_name_admin(usr)] admin-called the emergency shuttle.")
+ message_admins("[key_name_admin(usr)] admin-called the emergency shuttle[confirm == "Yes (No Recall)" ? " (non-recallable)" : ""].")
return
/client/proc/admin_cancel_shuttle()
@@ -754,6 +757,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes")
return
+ if(SSshuttle.adminEmergencyNoRecall)
+ SSshuttle.adminEmergencyNoRecall = FALSE
+
if(EMERGENCY_AT_LEAST_DOCKED)
return
@@ -764,6 +770,55 @@ Traitors and the like can also be revived with the previous role mostly intact.
return
+/client/proc/admin_disable_shuttle()
+ set category = "Admin - Events"
+ set name = "Disable Shuttle"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(SSshuttle.emergency.mode == SHUTTLE_DISABLED)
+ to_chat(usr, "Error, shuttle is already disabled.")
+ return
+
+ if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes")
+ return
+
+ message_admins("[key_name_admin(usr)] disabled the shuttle.")
+
+ SSshuttle.lastMode = SSshuttle.emergency.mode
+ SSshuttle.lastCallTime = SSshuttle.emergency.timeLeft(1)
+ SSshuttle.adminEmergencyNoRecall = TRUE
+ SSshuttle.emergency.setTimer(0)
+ SSshuttle.emergency.mode = SHUTTLE_DISABLED
+ priority_announce("Warning: Emergency Shuttle uplink failure, shuttle disabled until further notice.", "Emergency Shuttle Uplink Alert", 'sound/misc/announce_dig.ogg')
+
+/client/proc/admin_enable_shuttle()
+ set category = "Admin - Events"
+ set name = "Enable Shuttle"
+
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(SSshuttle.emergency.mode != SHUTTLE_DISABLED)
+ to_chat(usr, "Error, shuttle not disabled.")
+ return
+
+ if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes")
+ return
+
+ message_admins("[key_name_admin(usr)] enabled the emergency shuttle.")
+ SSshuttle.adminEmergencyNoRecall = FALSE
+ SSshuttle.emergencyNoRecall = FALSE
+ if(SSshuttle.lastMode == SHUTTLE_DISABLED) //If everything goes to shit, fix it.
+ SSshuttle.lastMode = SHUTTLE_IDLE
+
+ SSshuttle.emergency.mode = SSshuttle.lastMode
+ if(SSshuttle.lastCallTime < 10 SECONDS && SSshuttle.lastMode != SHUTTLE_IDLE)
+ SSshuttle.lastCallTime = 10 SECONDS //Make sure no insta departures.
+ SSshuttle.emergency.setTimer(SSshuttle.lastCallTime)
+ priority_announce("Warning: Emergency Shuttle uplink reestablished, shuttle enabled.", "Emergency Shuttle Uplink Alert", 'sound/misc/announce_dig.ogg')
+
/client/proc/everyone_random()
set category = "Fun"
set name = "Make Everyone Random"
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index 781675858cc..970a167dc62 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -57,6 +57,8 @@
return
if(!IS_DOCKED) // shuttle computer only has uses when onstation
return
+ if(SSshuttle.emergency.mode == SHUTTLE_DISABLED) // admins have disabled the shuttle.
+ return
var/mob/user = usr
. = FALSE
@@ -243,7 +245,7 @@
else
SSshuttle.emergencyLastCallLoc = null
- priority_announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]", null, 'sound/ai/shuttlecalled.ogg', "Priority")
+ priority_announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ][SSshuttle.adminEmergencyNoRecall ? "\n\nWarning: Shuttle recall subroutines disabled; Recall not possible." : ""]", null, 'sound/ai/shuttlecalled.ogg', "Priority")
/obj/docking_port/mobile/emergency/cancel(area/signalOrigin)
if(mode != SHUTTLE_CALL)
@@ -387,9 +389,10 @@
INVOKE_ASYNC(SSticker, /datum/controller/subsystem/ticker.proc/poll_hearts)
SSmapping.mapvote() //If no map vote has been run yet, start one.
- if(SHUTTLE_STRANDED)
+ if(SHUTTLE_STRANDED, SHUTTLE_DISABLED)
SSshuttle.checkHostileEnvironment()
+
if(SHUTTLE_ESCAPE)
if(sound_played && time_left <= HYPERSPACE_END_TIME)
var/list/areas = list()
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index bbb159fcb0b..c123e4a4e34 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -707,11 +707,13 @@
return "RCH"
if(SHUTTLE_PREARRIVAL)
return "LDN"
+ if(SHUTTLE_DISABLED)
+ return "DIS"
return ""
// returns 5-letter timer string, used by status screens and mob status panel
/obj/docking_port/mobile/proc/getTimerStr()
- if(mode == SHUTTLE_STRANDED)
+ if(mode == SHUTTLE_STRANDED || mode == SHUTTLE_DISABLED)
return "--:--"
var/timeleft = timeLeft()