diff --git a/code/controllers/emergency_shuttle_controller.dm b/code/controllers/emergency_shuttle_controller.dm
index 2955efc7b3b..5fc383c18d3 100644
--- a/code/controllers/emergency_shuttle_controller.dm
+++ b/code/controllers/emergency_shuttle_controller.dm
@@ -149,15 +149,17 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
//returns the time left until the shuttle arrives at it's destination, in seconds
/datum/emergency_shuttle_controller/proc/estimate_arrival_time()
var/eta
- if (isnull(shuttle.last_move_time))
- eta = launch_time + shuttle.move_time*10
- else
+ if (!isnull(shuttle.last_move_time))
+ //if we have a last_move_time than we are in transition and can get an accurate ETA
eta = shuttle.last_move_time + shuttle.move_time*10
+ else
+ //otherwise we need to estimate the arrival time using the scheduled launch time
+ eta = launch_time + shuttle.move_time*10 + shuttle.warmup_time*10
return (eta - world.time)/10
//returns the time left until the shuttle launches, in seconds
/datum/emergency_shuttle_controller/proc/estimate_launch_time()
- return (launch_time - world.time)/10
+ return (launch_time + shuttle.warmup_time*10 - world.time)/10
/datum/emergency_shuttle_controller/proc/has_eta()
return (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
@@ -189,8 +191,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
return 0 //not at station
if (!wait_for_launch)
return 0 //not going anywhere
- if (shuttle.moving_status != SHUTTLE_IDLE)
- return 0 //shuttle is doing stuff
+ if (shuttle.moving_status == SHUTTLE_INTRANSIT)
+ return 0
return 1
/*
diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm
index 98b77823d99..d0b3569fc6b 100644
--- a/code/controllers/shuttle_controller.dm
+++ b/code/controllers/shuttle_controller.dm
@@ -9,7 +9,7 @@ var/global/datum/shuttle_controller/shuttle_controller
/datum/shuttle_controller/proc/process()
//process ferry shuttles
for (var/datum/shuttle/ferry/shuttle in process_shuttles)
- if (shuttle.in_use)
+ if (shuttle.process_state)
shuttle.process()
@@ -291,7 +291,7 @@ var/global/datum/shuttle_controller/shuttle_controller
var/dat = ""
for (var/dock_tag in dock_controller_map + dock_controller_map_station + dock_controller_map_offsite)
dat += "\"[dock_tag]\", "
- world << "/red /b warning: shuttles with docking tags [dat] could not find their controllers!"
+ world << "\red \b warning: shuttles with docking tags [dat] could not find their controllers!"
//makes all shuttles docked to something at round start go into the docked state
for (var/shuttle_tag in shuttles)
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 89a46909569..e8cfce100dc 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -637,6 +637,9 @@ var/global/floorIsLava = 0
Make all items look like guns
Japanese Animes Mode
Egalitarian Station Mode
+ Launch a shuttle
+ Force launch a shuttle
+ Jump a shuttle
Move a shuttle
Break all lights
Fix all lights
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 653a2a8e7f0..df21a2372f1 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1922,21 +1922,111 @@
message_admins("\blue [key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]", 1)
log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]")
+ if("launchshuttle")
+ if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created.
+
+ feedback_inc("admin_secrets_fun_used",1)
+ feedback_add_details("admin_secrets_fun_used","ShL")
+
+ var/list/valid_shuttles = list()
+ for (var/shuttle_tag in shuttle_controller.shuttles)
+ if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry))
+ valid_shuttles += shuttle_tag
+
+ var/shuttle_tag = input("Which shuttle do you want to launch?") as null|anything in valid_shuttles
+
+ if (!shuttle_tag)
+ return
+
+ var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag]
+ if (S.can_launch())
+ S.launch(usr)
+ message_admins("\blue [key_name_admin(usr)] launched the [shuttle_tag] shuttle", 1)
+ log_admin("[key_name(usr)] launched the [shuttle_tag] shuttle")
+ else
+ alert("The [shuttle_tag] shuttle cannot be launched at this time. It's probably busy.")
+
+ if("forcelaunchshuttle")
+ if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created.
+
+ feedback_inc("admin_secrets_fun_used",1)
+ feedback_add_details("admin_secrets_fun_used","ShFL")
+
+ var/list/valid_shuttles = list()
+ for (var/shuttle_tag in shuttle_controller.shuttles)
+ if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry))
+ valid_shuttles += shuttle_tag
+
+ var/shuttle_tag = input("Which shuttle's launch do you want to force?") as null|anything in valid_shuttles
+
+ if (!shuttle_tag)
+ return
+
+ var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag]
+ if (S.can_force())
+ S.force_launch(usr)
+ message_admins("\blue [key_name_admin(usr)] has forced the [shuttle_tag] shuttle launch", 1)
+ log_admin("[key_name(usr)] has forced the [shuttle_tag] shuttle launch")
+ else
+ alert("The [shuttle_tag] shuttle launch cannot be forced at this time. It's busy, or hasn't been launched yet.")
+
+ if("jumpshuttle")
+ if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created.
+
+ feedback_inc("admin_secrets_fun_used",1)
+ feedback_add_details("admin_secrets_fun_used","ShJ")
+
+ var/shuttle_tag = input("Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles
+ if (!shuttle_tag) return
+
+ var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
+
+ var/origin_area = input("Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
+ if (!origin_area) return
+
+ var/destination_area = input("Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
+ if (!destination_area) return
+
+ var/long_jump = alert("Is there a transition area for this jump?","", "Yes", "No")
+ if (long_jump == "Yes")
+ var/transition_area = input("Which area is the transition area? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
+ if (!transition_area) return
+
+ var/move_duration = input("How many seconds will this jump take?") as num
+
+ S.long_jump(origin_area, destination_area, transition_area, move_duration)
+ message_admins("\blue [key_name_admin(usr)] has initiated a jump from [origin_area] to [destination_area] lasting [move_duration] seconds for the [shuttle_tag] shuttle", 1)
+ log_admin("[key_name_admin(usr)] has initiated a jump from [origin_area] to [destination_area] lasting [move_duration] seconds for the [shuttle_tag] shuttle")
+ else
+ S.short_jump(origin_area, destination_area)
+ message_admins("\blue [key_name_admin(usr)] has initiated a jump from [origin_area] to [destination_area] for the [shuttle_tag] shuttle", 1)
+ log_admin("[key_name_admin(usr)] has initiated a jump from [origin_area] to [destination_area] for the [shuttle_tag] shuttle")
+
if("moveshuttle")
if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created.
feedback_inc("admin_secrets_fun_used",1)
- feedback_add_details("admin_secrets_fun_used","ShA")
+ feedback_add_details("admin_secrets_fun_used","ShM")
+
+ var/confirm = alert("This command directly moves a shuttle from one area to another. DO NOT USE THIS UNLESS YOU ARE DEBUGGING A SHUTTLE AND YOU KNOW WHAT YOU ARE DOING.", "Are you sure?", "Ok", "Cancel")
+ if (confirm == "Cancel")
+ return
- var/shuttle_tag = input("Which shuttle do you want to call?") as null|anything in shuttle_controller.shuttles
-
- if(shuttle_tag)
- var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
- if(istype(S) && S.moving_status == 0)
- S.move()
- message_admins("\blue [key_name_admin(usr)] moved the [shuttle_tag] shuttle", 1)
- log_admin("[key_name(usr)] moved the [shuttle_tag] shuttle")
+ var/shuttle_tag = input("Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles
+ if (!shuttle_tag) return
+
+ var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag]
+
+ var/origin_area = input("Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
+ if (!origin_area) return
+
+ var/destination_area = input("Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world
+ if (!destination_area) return
+
+ S.move(origin_area, destination_area)
+ message_admins("\blue [key_name_admin(usr)] moved the [shuttle_tag] shuttle", 1)
+ log_admin("[key_name(usr)] moved the [shuttle_tag] shuttle")
if("togglebombcap")
feedback_inc("admin_secrets_fun_used",1)
diff --git a/code/modules/shuttles/shuttle.dm b/code/modules/shuttles/shuttle.dm
index ebc9fe1c9d3..db215c26b54 100644
--- a/code/modules/shuttles/shuttle.dm
+++ b/code/modules/shuttles/shuttle.dm
@@ -54,7 +54,6 @@
/datum/shuttle/proc/undock()
if (!docking_controller)
return
-
docking_controller.initiate_undocking()
/datum/shuttle/proc/current_dock_target()
@@ -76,6 +75,9 @@
if(origin == destination)
//world << "cancelling move, shuttle will overlap."
return
+
+ if (docking_controller && !docking_controller.undocked())
+ docking_controller.force_undock()
moving_status = SHUTTLE_INTRANSIT
diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm
index d45b66fce55..550c667b10b 100644
--- a/code/modules/shuttles/shuttle_console.dm
+++ b/code/modules/shuttles/shuttle_console.dm
@@ -2,7 +2,6 @@
name = "shuttle control console"
icon = 'icons/obj/computer.dmi'
icon_state = "shuttle"
- req_access = list(access_engine)
circuit = null
var/shuttle_tag // Used to coordinate data in shuttle controller.
diff --git a/code/modules/shuttles/shuttle_ferry.dm b/code/modules/shuttles/shuttle_ferry.dm
index e37ba86e374..e2ea397e01a 100644
--- a/code/modules/shuttles/shuttle_ferry.dm
+++ b/code/modules/shuttles/shuttle_ferry.dm
@@ -3,6 +3,7 @@
#define WAIT_ARRIVE 2
#define WAIT_FINISH 3
+#define DOCK_ATTEMPT_TIMEOUT 450 //how long in ticks we wait before assuming the docking controller is broken or blown up.
/datum/shuttle/ferry
var/location = 0 //0 = at area_station, 1 = at area_offsite
@@ -20,6 +21,8 @@
//TODO: change location to a string and use a mapping for area and dock targets.
var/dock_target_station
var/dock_target_offsite
+
+ var/last_dock_attempt_time = 0
/datum/shuttle/ferry/short_jump(var/area/origin,var/area/destination)
if(isnull(location))
@@ -47,16 +50,16 @@
..(departing, destination, interim, travel_time, direction)
/datum/shuttle/ferry/move(var/area/origin,var/area/destination)
-
- if (docking_controller && !docking_controller.undocked())
- docking_controller.force_undock()
-
..(origin, destination)
if (destination == area_station) location = 0
if (destination == area_offsite) location = 1
//if this is a long_jump retain the location we were last at until we get to the new one
+/datum/shuttle/ferry/dock()
+ ..()
+ last_dock_attempt_time = world.time
+
/datum/shuttle/ferry/proc/get_location_area(location_id = null)
if (isnull(location_id))
location_id = location
@@ -80,11 +83,11 @@
if (WAIT_ARRIVE)
if (moving_status == SHUTTLE_IDLE)
dock()
+ in_use = null //release lock
process_state = WAIT_FINISH
if (WAIT_FINISH)
- if (skip_docking_checks() || docking_controller.docked())
+ if (skip_docking_checks() || docking_controller.docked() || world.time > last_dock_attempt_time + DOCK_ATTEMPT_TIMEOUT)
process_state = IDLE_STATE
- in_use = null //release lock
arrived()
/datum/shuttle/ferry/current_dock_target()
diff --git a/code/modules/shuttles/shuttle_specops.dm b/code/modules/shuttles/shuttle_specops.dm
index 70742a18de7..9bad8d0cb4e 100644
--- a/code/modules/shuttles/shuttle_specops.dm
+++ b/code/modules/shuttles/shuttle_specops.dm
@@ -35,19 +35,22 @@
if(announcer)
announcer.autosay(message, "A.L.I.C.E.", "Response Team")
-/datum/shuttle/ferry/multidock/specops/launch(var/obj/machinery/computer/shuttle_control/user)
+/datum/shuttle/ferry/multidock/specops/launch(var/user)
if (!can_launch())
return
- if(world.time <= reset_time)
- user.visible_message("\blue Central Command will not allow the Special Operations shuttle to launch yet.")
- if (((world.time - reset_time)/10) > 60)
- user.visible_message("\blue [-((world.time - reset_time)/10)/60] minutes remain!")
- else
- user.visible_message("\blue [-(world.time - reset_time)/10] seconds remain!")
- return
+ if (istype(user, /obj/machinery/computer))
+ var/obj/machinery/computer/C = user
+
+ if(world.time <= reset_time)
+ C.visible_message("\blue Central Command will not allow the Special Operations shuttle to launch yet.")
+ if (((world.time - reset_time)/10) > 60)
+ C.visible_message("\blue [-((world.time - reset_time)/10)/60] minutes remain!")
+ else
+ C.visible_message("\blue [-(world.time - reset_time)/10] seconds remain!")
+ return
- user.visible_message("\blue The Special Operations shuttle will depart in [(specops_countdown_time/10)] seconds.")
+ C.visible_message("\blue The Special Operations shuttle will depart in [(specops_countdown_time/10)] seconds.")
if (location) //returning
radio_announce("THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN")
@@ -55,10 +58,6 @@
radio_announce("THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH")
sleep_until_launch()
- if (cancel_countdown)
- radio_announce("ALERT: LAUNCH SEQUENCE ABORTED")
- user.visible_message("\red Launch sequence aborted.")
- return
//launch
radio_announce("ALERT: INITIATING LAUNCH SEQUENCE")
@@ -79,8 +78,17 @@
reset_time = world.time + specops_return_delay //set the timeout
/datum/shuttle/ferry/multidock/specops/cancel_launch()
- ..()
+ if (!can_cancel())
+ return
+
cancel_countdown = 1
+ radio_announce("ALERT: LAUNCH SEQUENCE ABORTED")
+ if (istype(in_use, /obj/machinery/computer))
+ var/obj/machinery/computer/C = in_use
+ C.visible_message("\red Launch sequence aborted.")
+
+ ..()
+
/datum/shuttle/ferry/multidock/specops/can_launch()
@@ -120,6 +128,7 @@
//Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
sleep(5)
+
launch_prep = 0