diff --git a/code/__DEFINES/industrial_lift.dm b/code/__DEFINES/industrial_lift.dm
index 2b4401da5e2..05225385128 100644
--- a/code/__DEFINES/industrial_lift.dm
+++ b/code/__DEFINES/industrial_lift.dm
@@ -22,8 +22,6 @@
// Defines for update_lift_doors
#define OPEN_DOORS "open"
#define CLOSE_DOORS "close"
-#define LOCK_DOORS "lock"
-#define UNLOCK_DOORS "unlock"
// Defines for the state of tram destination signs
#define DESTINATION_WEST_ACTIVE "west_active"
diff --git a/code/modules/industrial_lift/tram/tram_doors.dm b/code/modules/industrial_lift/tram/tram_doors.dm
new file mode 100644
index 00000000000..cf1171725fe
--- /dev/null
+++ b/code/modules/industrial_lift/tram/tram_doors.dm
@@ -0,0 +1,131 @@
+/obj/machinery/door/window/tram
+ name = "tram door"
+ desc = "Probably won't crush you if you try to rush them as they close. But we know you live on that danger, try and beat the tram!"
+ icon = 'icons/obj/doors/tramdoor.dmi'
+ req_access = list("tcomms")
+ var/associated_lift = MAIN_STATION_TRAM
+ var/datum/weakref/tram_ref
+ /// Are the doors in a malfunctioning state (dangerous)
+ var/malfunctioning = FALSE
+
+/obj/machinery/door/window/tram/left
+ icon_state = "left"
+ base_state = "left"
+
+/obj/machinery/door/window/tram/left/directional/south
+ plane = WALL_PLANE_UPPER
+
+/obj/machinery/door/window/tram/right
+ icon_state = "right"
+ base_state = "right"
+
+/obj/machinery/door/window/tram/hilbert
+ icon = 'icons/obj/lavaland/survival_pod.dmi'
+ associated_lift = HILBERT_TRAM
+ icon_state = "windoor"
+ base_state = "windoor"
+
+/obj/machinery/door/window/tram/emag_act(mob/living/user)
+ if(obj_flags & EMAGGED)
+ return
+ balloon_alert(user, "disabled motion sensors")
+ obj_flags |= EMAGGED
+
+/// Random event called by code\modules\events\tram_malfunction.dm
+/// Makes the doors malfunction
+/obj/machinery/door/window/tram/proc/start_malfunction()
+ if(obj_flags & EMAGGED)
+ return
+
+ malfunctioning = TRUE
+ process()
+
+/// Random event called by code\modules\events\tram_malfunction.dm
+/// Returns doors to their original status
+/obj/machinery/door/window/tram/proc/end_malfunction()
+ if(obj_flags & EMAGGED)
+ return
+
+ malfunctioning = FALSE
+ process()
+
+/obj/machinery/door/window/tram/proc/cycle_doors(command, forced=FALSE)
+ if(command == "open" && icon_state == "[base_state]open")
+ if(!forced && !hasPower())
+ return FALSE
+ return TRUE
+ if(command == "close" && icon_state == base_state)
+ return TRUE
+ switch(command)
+ if("open")
+ playsound(src, 'sound/machines/tramopen.ogg', 100, TRUE)
+ do_animate("opening")
+ icon_state ="[base_state]open"
+ sleep(7 DECISECONDS)
+ set_density(FALSE)
+ air_update_turf(TRUE, FALSE)
+ if("close")
+ if((obj_flags & EMAGGED) || malfunctioning)
+ flick("[base_state]spark", src)
+ playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
+ sleep(6 DECISECONDS)
+ playsound(src, 'sound/machines/tramclose.ogg', 100, TRUE)
+ do_animate("closing")
+ icon_state = base_state
+ sleep(19 DECISECONDS)
+ if((obj_flags & EMAGGED) || malfunctioning)
+ if(malfunctioning && prob(85))
+ return
+ for(var/i in 1 to 3)
+ for(var/mob/living/crushee in get_turf(src))
+ crush()
+ sleep(2 DECISECONDS)
+ air_update_turf(TRUE, TRUE)
+ operating = FALSE
+ set_density(TRUE)
+
+ update_freelook_sight()
+ return TRUE
+
+/obj/machinery/door/window/tram/right/directional/south
+ plane = WALL_PLANE_UPPER
+
+/obj/machinery/door/window/tram/proc/find_tram()
+ for(var/datum/lift_master/lift as anything in GLOB.active_lifts_by_type[TRAM_LIFT_ID])
+ if(lift.specific_lift_id == associated_lift)
+ tram_ref = WEAKREF(lift)
+
+/obj/machinery/door/window/tram/Initialize(mapload, set_dir, unres_sides)
+ . = ..()
+ RemoveElement(/datum/element/atmos_sensitive, mapload)
+ INVOKE_ASYNC(src, PROC_REF(open))
+ GLOB.tram_doors += src
+ find_tram()
+
+/obj/machinery/door/window/tram/Destroy()
+ GLOB.tram_doors -= src
+ return ..()
+
+/obj/machinery/door/window/tram/examine(mob/user)
+ . = ..()
+ . += span_notice("It has labels indicating that it has an emergency mechanism to open using just your hands in the event of an emergency.")
+
+/obj/machinery/door/window/tram/try_safety_unlock(mob/user)
+ if(!hasPower() && density)
+ balloon_alert(user, "pulling emergency exit...")
+ if(do_after(user, 7 SECONDS, target = src))
+ try_to_crowbar(null, user, TRUE)
+ return TRUE
+
+/obj/machinery/door/window/tram/bumpopen(mob/user)
+ if(operating || !density)
+ return
+ var/datum/lift_master/tram/tram_part = tram_ref?.resolve()
+ add_fingerprint(user)
+ if(tram_part.travel_distance < XING_DEFAULT_TRAM_LENGTH || tram_part.travel_distance > tram_part.travel_trip_length - XING_DEFAULT_TRAM_LENGTH)
+ return // we're already animating, don't reset that
+ cycle_doors(OPEN_DOORS, TRUE) //making a daring exit midtravel? make sure the doors don't go in the wrong state on arrival.
+ return
+
+MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/door/window/tram/left, 0)
+MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/door/window/tram/right, 0)
diff --git a/code/modules/industrial_lift/tram/tram_lift_master.dm b/code/modules/industrial_lift/tram/tram_lift_master.dm
index a2d88283f4c..84f48c659ea 100644
--- a/code/modules/industrial_lift/tram/tram_lift_master.dm
+++ b/code/modules/industrial_lift/tram/tram_lift_master.dm
@@ -6,6 +6,8 @@
var/travel_direction = NONE
///if we're travelling, how far do we have to go
var/travel_distance = 0
+ ///how far in total we'll be travelling
+ var/travel_trip_length = 0
///multiplier on how much damage/force the tram imparts on things it hits
var/collision_lethality = 1
@@ -116,6 +118,7 @@
travel_direction = get_dir(idle_platform, destination_platform)
travel_distance = get_dist(idle_platform, destination_platform)
+ travel_trip_length = travel_distance
idle_platform = destination_platform
set_travelling(TRUE)
set_controls(LIFT_PLATFORM_LOCKED)
@@ -127,7 +130,6 @@
/datum/lift_master/tram/proc/dispatch_tram(obj/effect/landmark/tram/destination_platform)
SEND_SIGNAL(src, COMSIG_TRAM_TRAVEL, idle_platform, destination_platform)
- update_tram_doors(UNLOCK_DOORS)
for(var/obj/structure/industrial_lift/tram/tram_part as anything in lift_platforms) //only thing everyone needs to know is the new location.
if(tram_part.travelling) //wee woo wee woo there was a double action queued. damn multi tile structs
@@ -142,7 +144,6 @@
/datum/lift_master/tram/process(delta_time)
if(!travel_distance)
- update_tram_doors(LOCK_DOORS)
update_tram_doors(OPEN_DOORS)
addtimer(CALLBACK(src, PROC_REF(unlock_controls)), 2 SECONDS)
return PROCESS_KILL
@@ -210,12 +211,6 @@
/datum/lift_master/tram/proc/set_door_state(tram_door, action)
switch(action)
- if(LOCK_DOORS)
- INVOKE_ASYNC(tram_door, TYPE_PROC_REF(/obj/machinery/door/window/tram, lock))
-
- if(UNLOCK_DOORS)
- INVOKE_ASYNC(tram_door, TYPE_PROC_REF(/obj/machinery/door/window/tram, unlock))
-
if(OPEN_DOORS)
INVOKE_ASYNC(tram_door, TYPE_PROC_REF(/obj/machinery/door/window/tram, cycle_doors), action)
diff --git a/code/modules/industrial_lift/tram/tram_machinery.dm b/code/modules/industrial_lift/tram/tram_machinery.dm
index 37ad1ce5198..6d0294e1a00 100644
--- a/code/modules/industrial_lift/tram/tram_machinery.dm
+++ b/code/modules/industrial_lift/tram/tram_machinery.dm
@@ -718,135 +718,6 @@ GLOBAL_LIST_EMPTY(tram_doors)
if(!(machine_stat & (NOPOWER|BROKEN)) && !panel_open)
. += emissive_appearance(icon, light_mask, src, alpha = alpha)
-/obj/machinery/door/window/tram
- name = "tram door"
- desc = "Probably won't crush you if you try to rush them as they close. But we know you live on that danger, try and beat the tram!"
- icon = 'icons/obj/doors/tramdoor.dmi'
- var/associated_lift = MAIN_STATION_TRAM
- var/datum/weakref/tram_ref
- /// Directions the tram door can be forced open in an emergency
- var/space_dir = null
- var/malfunctioning = FALSE
-
-/obj/machinery/door/window/tram/left
- icon_state = "left"
- base_state = "left"
-
-/obj/machinery/door/window/tram/left/directional/south
- plane = WALL_PLANE_UPPER
-
-/obj/machinery/door/window/tram/right
- icon_state = "right"
- base_state = "right"
-
-/obj/machinery/door/window/tram/hilbert
- icon = 'icons/obj/lavaland/survival_pod.dmi'
- associated_lift = HILBERT_TRAM
- icon_state = "windoor"
- base_state = "windoor"
-
-/obj/machinery/door/window/tram/emag_act(mob/living/user)
- if(obj_flags & EMAGGED)
- return
- balloon_alert(user, "disabled motion sensors")
- obj_flags |= EMAGGED
-
-/obj/machinery/door/window/tram/proc/start_malfunction()
- if(obj_flags & EMAGGED)
- return
-
- malfunctioning = TRUE
- process()
-
-/obj/machinery/door/window/tram/proc/end_malfunction()
- if(obj_flags & EMAGGED)
- return
-
- malfunctioning = FALSE
- process()
-
-/obj/machinery/door/window/tram/proc/cycle_doors(command, forced=FALSE)
- if(command == "open" && icon_state == "[base_state]open")
- if(!forced)
- if(!hasPower())
- return 0
- return 1
- if(command == "close" && icon_state == base_state)
- return 1
- playsound(src, 'sound/machines/windowdoor.ogg', 100, TRUE)
- switch(command)
- if("open")
- do_animate("opening")
- icon_state ="[base_state]open"
- sleep(7 DECISECONDS)
- set_density(FALSE)
- air_update_turf(TRUE, FALSE)
- if("close")
- if(obj_flags & EMAGGED | malfunctioning)
- flick("[base_state]spark", src)
- playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
- sleep(6 DECISECONDS)
- do_animate("closing")
- icon_state = base_state
- sleep(19 DECISECONDS)
- if(obj_flags & EMAGGED | malfunctioning)
- if(malfunctioning && prob(85))
- return
- for(var/i=1 to 3)
- for(var/mob/living/crushee in get_turf(src))
- crush()
- sleep(2 DECISECONDS)
- air_update_turf(TRUE, TRUE)
- operating = FALSE
- set_density(TRUE)
-
- update_freelook_sight()
- return 1
-
-//When the tram is in station, the doors are locked to engineering and command only.
-/obj/machinery/door/window/tram/lock()
- req_access = list("engineering")
-
-/obj/machinery/door/window/tram/unlock()
- req_access = null
-
-/obj/machinery/door/window/tram/right/directional/south
- plane = WALL_PLANE_UPPER
-
-/obj/machinery/door/window/tram/proc/find_tram()
- for(var/datum/lift_master/lift as anything in GLOB.active_lifts_by_type[TRAM_LIFT_ID])
- if(lift.specific_lift_id == associated_lift)
- tram_ref = WEAKREF(lift)
-
-/obj/machinery/door/window/tram/Initialize(mapload, set_dir, unres_sides)
- . = ..()
- RemoveElement(/datum/element/atmos_sensitive, mapload)
- INVOKE_ASYNC(src, PROC_REF(open))
- GLOB.tram_doors += src
- find_tram()
-
-/obj/machinery/door/window/tram/Destroy()
- GLOB.tram_doors -= src
- return ..()
-
-/obj/machinery/door/window/tram/examine(mob/user)
- . = ..()
- . += span_notice("It has labels indicating that it has an emergency mechanism to open from the inside using just your hands in the event of an emergency.")
-
-/obj/machinery/door/window/tram/try_safety_unlock(mob/user)
- if(!hasPower() && density)
- to_chat(user, span_notice("You begin pulling the tram emergency exit handle..."))
- if(do_after(user, 15 SECONDS, target = src))
- try_to_crowbar(null, user, TRUE)
- return TRUE
-
-/obj/machinery/door/window/tram/open_and_close()
- var/datum/lift_master/tram/tram_part = tram_ref?.resolve()
- if(!open())
- return
- if(tram_part.travelling) //making a daring exit midtravel? make sure the doors don't go in the wrong state on arrival.
- return PROCESS_KILL
-
/obj/machinery/button/tram
name = "tram request"
desc = "A button for calling the tram. It has a speakerbox in it with some internals."
@@ -870,8 +741,6 @@ GLOBAL_LIST_EMPTY(tram_doors)
. += span_notice("There's a small inscription on the button...")
. += span_notice("THIS CALLS THE TRAM! IT DOES NOT OPERATE IT! The console on the tram tells it where to go!")
-MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/door/window/tram/left, 0)
-MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/door/window/tram/right, 0)
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/tram_controls, 0)
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/destination_sign/indicator, 32)
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/button/tram, 32)
diff --git a/sound/machines/tramclose.ogg b/sound/machines/tramclose.ogg
new file mode 100644
index 00000000000..d6777a6aab1
Binary files /dev/null and b/sound/machines/tramclose.ogg differ
diff --git a/sound/machines/tramopen.ogg b/sound/machines/tramopen.ogg
new file mode 100644
index 00000000000..2138286418b
Binary files /dev/null and b/sound/machines/tramopen.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index 9113d223e24..7b7160f2251 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -3576,6 +3576,7 @@
#include "code\modules\industrial_lift\industrial_lift.dm"
#include "code\modules\industrial_lift\lift_indicator.dm"
#include "code\modules\industrial_lift\lift_master.dm"
+#include "code\modules\industrial_lift\tram\tram_doors.dm"
#include "code\modules\industrial_lift\tram\tram_floors.dm"
#include "code\modules\industrial_lift\tram\tram_landmark.dm"
#include "code\modules\industrial_lift\tram\tram_lift_master.dm"