mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com> Co-authored-by: Kashargul <KashL@t-online.de>
226 lines
7.8 KiB
Plaintext
226 lines
7.8 KiB
Plaintext
// Lift master datum. One per turbolift.
|
|
/datum/turbolift
|
|
var/datum/turbolift_floor/target_floor // Where are we going?
|
|
var/datum/turbolift_floor/current_floor // Where is the lift currently?
|
|
var/list/doors = list() // Doors inside the lift structure.
|
|
var/list/queued_floors = list() // Where are we moving to next?
|
|
var/list/floors = list() // All floors in this system.
|
|
var/move_delay = 30 // Time between floor changes.
|
|
var/floor_wait_delay = 85 // Time to wait at floor stops.
|
|
var/obj/structure/lift/panel/control_panel_interior // Lift control panel.
|
|
var/doors_closing = 0 // Whether doors are in the process of closing
|
|
var/list/music = null // Elevator music to set on areas
|
|
var/priority_mode = FALSE // Flag to block buttons from calling the elevator if in priority mode.
|
|
var/fire_mode = FALSE // Flag to indicate firefighter mode is active.
|
|
|
|
var/tmp/moving_upwards
|
|
var/tmp/busy_state // Used for controller processing.
|
|
var/tmp/next_process // world.time process() should next do something
|
|
|
|
/datum/turbolift/proc/emergency_stop()
|
|
cancel_pending_floors()
|
|
target_floor = null
|
|
if(!fire_mode)
|
|
open_doors()
|
|
|
|
// Enter priority mode, blocking all calls for awhile
|
|
/datum/turbolift/proc/priority_mode(var/time = 30 SECONDS)
|
|
priority_mode = TRUE
|
|
cancel_pending_floors()
|
|
update_ext_panel_icons()
|
|
control_panel_interior.audible_message(span_info("This turbolift is responding to a priority call. Please exit the lift when it stops and make way."), runemessage = "BUZZ")
|
|
spawn(time)
|
|
priority_mode = FALSE
|
|
update_ext_panel_icons()
|
|
|
|
/datum/turbolift/proc/update_fire_mode(var/new_fire_mode)
|
|
if(fire_mode == new_fire_mode)
|
|
return
|
|
fire_mode = new_fire_mode
|
|
if(new_fire_mode)
|
|
cancel_pending_floors()
|
|
|
|
// Turn the lights red and kill the music
|
|
for(var/datum/turbolift_floor/F in floors)
|
|
var/area/turbolift/A = locate(F.area_ref)
|
|
if(new_fire_mode)
|
|
if(A.forced_ambience)
|
|
A.forced_ambience.Cut()
|
|
A.fire_alert()
|
|
else
|
|
if(music)
|
|
A.forced_ambience = music.Copy()
|
|
A.fire_reset()
|
|
for(var/mob/living/M in mobs_in_area(A))
|
|
if(M.mind)
|
|
A.play_ambience(M)
|
|
// Disable safeties on the doors during firemode, reset when done
|
|
for(var/obj/machinery/door/airlock/door in F.doors)
|
|
door.safe = new_fire_mode ? FALSE : initial(door.safe)
|
|
|
|
// Disable safeties on the doors during firemode, reset when done
|
|
for(var/obj/machinery/door/airlock/door in doors)
|
|
door.safe = new_fire_mode ? FALSE : initial(door.safe)
|
|
update_ext_panel_icons()
|
|
control_panel_interior.update_icon()
|
|
|
|
// Cancel all pending calls
|
|
/datum/turbolift/proc/cancel_pending_floors()
|
|
for(var/datum/turbolift_floor/floor in queued_floors)
|
|
if(floor.ext_panel)
|
|
floor.ext_panel.reset()
|
|
queued_floors.Cut()
|
|
control_panel_interior.updateDialog()
|
|
|
|
// Update the icons of all exterior panels (after we change modes etc)
|
|
/datum/turbolift/proc/update_ext_panel_icons()
|
|
for(var/datum/turbolift_floor/floor in floors)
|
|
if(floor.ext_panel)
|
|
floor.ext_panel.update_icon()
|
|
|
|
/datum/turbolift/proc/doors_are_open(var/datum/turbolift_floor/use_floor = current_floor)
|
|
for(var/obj/machinery/door/airlock/door in (use_floor ? (doors + use_floor.doors) : doors))
|
|
if(!door.density)
|
|
return 1
|
|
return 0
|
|
|
|
/datum/turbolift/proc/open_doors(var/datum/turbolift_floor/use_floor = current_floor)
|
|
for(var/obj/machinery/door/airlock/door in (use_floor ? (doors + use_floor.doors) : doors))
|
|
//door.command("open")
|
|
spawn(0)
|
|
door.open()
|
|
return
|
|
|
|
/datum/turbolift/proc/close_doors(var/datum/turbolift_floor/use_floor = current_floor)
|
|
for(var/obj/machinery/door/airlock/door in (use_floor ? (doors + use_floor.doors) : doors))
|
|
//door.command("close")
|
|
spawn(0)
|
|
door.close()
|
|
return
|
|
|
|
#define LIFT_MOVING 1 // Lift will try moving.
|
|
#define LIFT_WAITING_A 2 // Waiting 15ds after arrival to announce, then goto LIFT_WAITING_B
|
|
#define LIFT_WAITING_B 3 // Waiting floor_wait_delay after announcement before potentially moving again.
|
|
|
|
/datum/turbolift/process()
|
|
if(world.time < next_process)
|
|
return
|
|
switch(busy_state)
|
|
if(LIFT_MOVING)
|
|
if(!do_move())
|
|
if(target_floor)
|
|
// TODO - This logic copied from old processor. Would be better to have error states.
|
|
target_floor.ext_panel.reset()
|
|
target_floor = null
|
|
return PROCESS_KILL
|
|
else if(!next_process)
|
|
log_debug("Turbolift [src] do_move() returned 1 but next_process = null; busy_state=[busy_state]")
|
|
return PROCESS_KILL
|
|
if(LIFT_WAITING_A)
|
|
var/area/turbolift/origin = locate(current_floor.area_ref)
|
|
control_panel_interior.visible_message(span_infoplain(span_bold("The elevator") + " announces, \"[origin.lift_announce_str]\""))
|
|
next_process = world.time + floor_wait_delay
|
|
busy_state = LIFT_WAITING_B
|
|
if(LIFT_WAITING_B)
|
|
if(queued_floors.len)
|
|
busy_state = LIFT_MOVING
|
|
else
|
|
busy_state = null
|
|
return PROCESS_KILL
|
|
else
|
|
log_debug("Turbolift [src] process() called with unknown busy_state='[busy_state]'")
|
|
return PROCESS_KILL
|
|
|
|
// Called by process when in LIFT_MOVING
|
|
/datum/turbolift/proc/do_move()
|
|
next_process = null
|
|
|
|
var/current_floor_index = floors.Find(current_floor)
|
|
|
|
if(!target_floor)
|
|
if(!queued_floors || !queued_floors.len)
|
|
return 0
|
|
target_floor = queued_floors[1]
|
|
queued_floors -= target_floor
|
|
if(current_floor_index < floors.Find(target_floor))
|
|
moving_upwards = 1
|
|
else
|
|
moving_upwards = 0
|
|
control_panel_interior.updateDialog()
|
|
|
|
if(doors_are_open())
|
|
if(!doors_closing)
|
|
close_doors()
|
|
doors_closing = 1
|
|
next_process = world.time + 1 SECOND // Wait for doors to close
|
|
return 1
|
|
else // We failed to close the doors - probably, someone is blocking them; stop trying to move
|
|
doors_closing = 0
|
|
if(!fire_mode)
|
|
open_doors()
|
|
control_panel_interior.audible_message("\The [current_floor.ext_panel] buzzes loudly.", runemessage = "BUZZ")
|
|
playsound(control_panel_interior, "sound/machines/buzz-two.ogg", 50, 1)
|
|
return 0
|
|
|
|
doors_closing = 0 // The doors weren't open, so they are done closing
|
|
|
|
GLOB.turbo_lift_floors_moved_roundstat++
|
|
|
|
var/area/turbolift/origin = locate(current_floor.area_ref)
|
|
|
|
if(target_floor == current_floor)
|
|
|
|
playsound(control_panel_interior, origin.arrival_sound, 50, 1)
|
|
target_floor.arrived(src)
|
|
target_floor = null
|
|
|
|
next_process = world.time + 15
|
|
busy_state = LIFT_WAITING_A
|
|
return 1
|
|
|
|
// Work out where we're headed.
|
|
var/datum/turbolift_floor/next_floor
|
|
if(moving_upwards)
|
|
next_floor = floors[current_floor_index+1]
|
|
else
|
|
next_floor = floors[current_floor_index-1]
|
|
|
|
var/area/turbolift/destination = locate(next_floor.area_ref)
|
|
|
|
if(!istype(origin) || !istype(destination) || (origin == destination))
|
|
return 0
|
|
|
|
for(var/turf/T in destination)
|
|
for(var/atom/movable/AM in T)
|
|
if(istype(AM, /mob/living) && !(AM.is_incorporeal()))
|
|
var/mob/living/M = AM
|
|
M.gib()
|
|
else if(AM.simulated && !(istype(AM, /mob/observer)) && !(AM.is_incorporeal()))
|
|
qdel(AM)
|
|
|
|
origin.move_contents_to(destination)
|
|
|
|
if((locate(/obj/machinery/power) in destination) || (locate(/obj/structure/cable) in destination))
|
|
SSmachines.makepowernets()
|
|
|
|
current_floor = next_floor
|
|
control_panel_interior.visible_message("The elevator [moving_upwards ? "rises" : "descends"] smoothly.")
|
|
|
|
next_process = world.time + (next_floor.delay_time || move_delay)
|
|
return 1
|
|
|
|
/datum/turbolift/proc/queue_move_to(var/datum/turbolift_floor/floor)
|
|
if(!floor || !(floor in floors) || (floor in queued_floors))
|
|
return // STOP PRESSING THE BUTTON.
|
|
floor.pending_move(src)
|
|
queued_floors |= floor
|
|
busy_state = LIFT_MOVING
|
|
START_PROCESSING(SSprocessing, src)
|
|
|
|
// TODO: dummy machine ('lift mechanism') in powered area for functionality/blackout checks.
|
|
/datum/turbolift/proc/is_functional()
|
|
return 1
|
|
|
|
#undef LIFT_MOVING
|
|
#undef LIFT_WAITING_A
|
|
#undef LIFT_WAITING_B |