Files
Polaris/code/modules/turbolift/turbolift.dm
Leshana 43fc65d529 Remove turbolift_controller proccess, just use SSprocessing instead.
- Design based on BayStation: Refactor turbolift.do_move() to remove all sleep()'s, instead have wait_state to keep track of where it was.
- Add in process() proc to do appropriate action based on wait_state.
- Register/deregister with SSprocessing instead of turbolift_controller
2020-03-25 14:33:47 -04:00

166 lines
5.6 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/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()
queued_floors.Cut()
target_floor = null
open_doors()
/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("<b>The elevator</b> 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
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
open_doors()
control_panel_interior.audible_message("\The [current_floor.ext_panel] buzzes loudly.")
playsound(control_panel_interior.loc, "sound/machines/buzz-two.ogg", 50, 1)
return 0
doors_closing = 0 // The doors weren't open, so they are done closing
var/area/turbolift/origin = locate(current_floor.area_ref)
if(target_floor == current_floor)
playsound(control_panel_interior.loc, 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))
var/mob/living/M = AM
M.gib()
else if(istype(AM, /mob/zshadow))
AM.Destroy() //prevent deleting shadow without deleting shadow's shadows
else if(AM.simulated && !(istype(AM, /mob/observer)))
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