diff --git a/baystation12.dme b/baystation12.dme index 91a9b169831..46d7dcc0ca5 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -2071,6 +2071,16 @@ #include "code\modules\telesci\gps.dm" #include "code\modules\telesci\telepad.dm" #include "code\modules\telesci\telesci_computer.dm" +#include "code\modules\turbolift\_Aurora-areas.dm" +#include "code\modules\turbolift\_turbolift.dm" +#include "code\modules\turbolift\turbolift.dm" +#include "code\modules\turbolift\turbolift_areas.dm" +#include "code\modules\turbolift\turbolift_console.dm" +#include "code\modules\turbolift\turbolift_door.dm" +#include "code\modules\turbolift\turbolift_floor.dm" +#include "code\modules\turbolift\turbolift_map.dm" +#include "code\modules\turbolift\turbolift_process.dm" +#include "code\modules\turbolift\turbolift_turfs.dm" #include "code\modules\vehicles\bike.dm" #include "code\modules\vehicles\cargo_train.dm" #include "code\modules\vehicles\train.dm" diff --git a/code/game/machinery/doors/airlock_control.dm b/code/game/machinery/doors/airlock_control.dm index bb4b29b88a6..1eb8bf06d66 100644 --- a/code/game/machinery/doors/airlock_control.dm +++ b/code/game/machinery/doors/airlock_control.dm @@ -305,3 +305,11 @@ obj/machinery/access_button/airlock_interior obj/machinery/access_button/airlock_exterior frequency = 1379 command = "cycle_exterior" + +obj/machinery/door/airlock/proc/command(var/new_command) + cur_command = new_command + + //if there's no power, recieve the signal but just don't do anything. This allows airlocks to continue to work normally once power is restored + if(arePowerSystemsOn()) + spawn() + execute_current_command() \ No newline at end of file diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 9d10a706e23..66ba57f652e 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -568,6 +568,11 @@ var/list/name_to_material hardness = 500 weight = 500 +/material/voxalloy/elevatorium + name = "elevatorium" + display_name = "elevator panelling" + icon_colour = "#666666" + /material/wood name = "wood" stack_type = null diff --git a/code/modules/turbolift/_Aurora-areas.dm b/code/modules/turbolift/_Aurora-areas.dm new file mode 100644 index 00000000000..42441cbc2f5 --- /dev/null +++ b/code/modules/turbolift/_Aurora-areas.dm @@ -0,0 +1,285 @@ +/obj/turbolift_map_holder/aurora + depth = 2 + lift_size_x = 4 + lift_size_y = 4 + clear_objects = 0 + +//Main Lift +/obj/turbolift_map_holder/aurora/civilian + name = "Aurora lift placeholder - Main" + dir = SOUTH + + depth = 3 + lift_size_x = 6 + lift_size_y = 6 + + areas_to_use = list( + /area/turbolift/main_station, + /area/turbolift/main_mid, + /area/turbolift/main_arrivals + ) + +/area/turbolift/main_arrivals + name = "Civilian Lift - Arrivals" + lift_announce_str = "Arriving at Arrivals" + + lift_floor_label = "Arrivals" + lift_floor_name = "Arrivals" + +/area/turbolift/main_station + name = "Civilian Lift - Main" + lift_announce_str = "Arriving at Main floor" + + lift_floor_label = "Main" + lift_floor_name = "Main" + +/area/turbolift/main_mid + name = "Civilian Lift - Mid Level" + lift_announce_str = "Arriving at Unknown" + + lift_floor_label = "Under construction" + lift_floor_name = "Under construction" + +//Security +/obj/turbolift_map_holder/aurora/security + name = "Aurora lift placeholder - Security" + dir = SOUTH + + depth = 2 + + areas_to_use = list( + /area/turbolift/security_maintenance, + /area/turbolift/security_station + ) + +/area/turbolift/security_station + name = "Station - By Security" + lift_announce_str = "Arriving at the station level, by the Security department." + + lift_floor_label = "Security Main" + lift_floor_name = "Security Main" + +/area/turbolift/security_maintenance + name = "Maintenance - Below Security" + lift_announce_str = "Arriving at the maintenance level, below the Security department." + base_turf = /turf/simulated/floor/plating + + lift_floor_label = "Lower Sec" + lift_floor_name = "Lower Sec" + +//Research +/obj/turbolift_map_holder/aurora/research + name = "Aurora lift placeholder - Research" + dir = NORTH + + lift_size_x = 4 + lift_size_y = 4 + depth = 2 + + areas_to_use = list( + /area/turbolift/research_maintenance, + /area/turbolift/research_station + ) + +/area/turbolift/research_station + name = "Station - By Research" + lift_announce_str = "Arriving at the station level, by the R&D department." + + lift_floor_label = "R&D Main" + lift_floor_name = "R&D Main" + +/area/turbolift/research_maintenance + name = "Maintenance - Below Research" + lift_announce_str = "Arriving at the maintenance level, below the R&D department." + base_turf = /turf/simulated/floor/plating + + lift_floor_label = "Lower R&D" + lift_floor_name = "Lower R&D" + +//Engineering +/obj/turbolift_map_holder/aurora/engineering + name = "Aurora lift placeholder - Engineering" + dir = SOUTH + + lift_size_x = 5 + lift_size_y = 4 + depth = 2 + + areas_to_use = list( + /area/turbolift/engineering_maintenance, + /area/turbolift/engineering_station + ) + +/area/turbolift/engineering_station + name = "Station - By Engineering" + lift_announce_str = "Arriving at the station level, by the Engineering department." + + lift_floor_label = "Engineering Main" + lift_floor_name = "Engineering Main" + +/area/turbolift/engineering_maintenance + name = "Maintenance - Below Engineering" + lift_announce_str = "Arriving at the maintenance level, below the Engineering department." + + lift_floor_label = "Lower Engineering" + lift_floor_name = "Lower Engineering" + +//Cargo +/obj/turbolift_map_holder/aurora/cargo + name = "Aurora lift placeholder - Cargo" + dir = EAST + + lift_size_x = 5 + lift_size_y = 5 + depth = 3 + + areas_to_use = list( + /area/turbolift/cargo_station, + /area/turbolift/cargo_mid, + /area/turbolift/cargo_deliverys + ) + +/area/turbolift/cargo_station + name = "Station - By Cargo" + lift_announce_str = "Arriving at the station level, by the Cargo department." + + lift_floor_label = "Cargo Main" + lift_floor_name = "Cargo Main" + +/area/turbolift/cargo_deliverys + name = "Arrivals - Cargo" + lift_announce_str = "Arriving at Cargo department, Deliverys." + + lift_floor_label = "Cargo Arrivals" + lift_floor_name = "Cargo Arrivals" + +/area/turbolift/cargo_mid + name = "Arrivals - Cargo" + lift_announce_str = "Arriving at Unknown." + + lift_floor_label = "Cargo Arrivals" + lift_floor_name = "Cargo Arrivals" + + +//Medical +/obj/turbolift_map_holder/aurora/medical + name = "Aurora lift placeholder - Medical" + dir = WEST + + lift_size_x = 4 + lift_size_y = 4 + depth = 2 + + areas_to_use = list( + /area/turbolift/medical_sub, + /area/turbolift/medical_station + ) + +/area/turbolift/medical_station + name = "Medical Lift - Main" + lift_announce_str = "Arriving at Medical bay" + + lift_floor_label = "Medical Main" + lift_floor_name = "Medical Main" + +/area/turbolift/medical_sub + name = "Medical Lift - Sub" + lift_announce_str = "Arriving at lower Medical" + + lift_floor_label = "Lower Medical" + lift_floor_name = "Lower Medical" + +//AI Access +/obj/turbolift_map_holder/aurora/aiaccess + name = "Aurora lift placeholder - AI Access" + dir = SOUTH + + lift_size_x = 4 + lift_size_y = 4 + depth = 2 + + areas_to_use = list( + /area/turbolift/ai_sub, + /area/turbolift/ai_station + ) + +/area/turbolift/ai_station + name = "AI Access Lift - Main" + lift_announce_str = "Arriving at Main Floor" + + lift_floor_label = "Main" + lift_floor_name = "AI Control Main" + +/area/turbolift/ai_sub + name = "AI Access Lift - Lower" + lift_announce_str = "Arriving at AI control" + + lift_floor_label = "AI Control" + lift_floor_name = "AI Control" + + + +//Vault +/obj/turbolift_map_holder/aurora/vault + name = "Aurora lift placeholder - Vault" + dir = SOUTH + + lift_size_x = 4 + lift_size_y = 4 + depth = 2 + + areas_to_use = list( + /area/turbolift/vault_sub, + /area/turbolift/vault_station + ) + +/area/turbolift/vault_station + name = "Vault Access Lift - Main" + lift_announce_str = "Arriving at Main floor" + + lift_floor_label = "Main" + lift_floor_name = "Vault Main" + + +/area/turbolift/vault_sub + name = "Vault Access Lift - sub" + lift_announce_str = "Arriving at Vault Access" + + lift_floor_label = "Vault Access" + lift_floor_name = "Vault Access" + + +//Command +/obj/turbolift_map_holder/aurora/command + name = "Aurora lift placeholder - Command" + dir = NORTH + + lift_size_x = 4 + lift_size_y = 4 + depth = 3 + + areas_to_use = list( + /area/turbolift/command_sub, + /area/turbolift/command_mid, + /area/turbolift/command_station + ) + +/area/turbolift/command_station + name = "Command Lift - Main" + lift_announce_str = "Arriving at Main floor" + + lift_floor_label = "Main" + lift_floor_name = "Command Main" + +/area/turbolift/command_sub + name = "Command Lift - Sub" + lift_announce_str = "Arriving at Command level" + + lift_floor_label = "Meeting/Escape Pods" + lift_floor_name = "Command Meeting" + +/area/turbolift/command_mid + name = "Command Lift - Mid" + lift_announce_str = "Arriving at Command Unknown" + lift_floor_label = "Command Floor" + lift_floor_name = "Secret Command Floor" diff --git a/code/modules/turbolift/_turbolift.dm b/code/modules/turbolift/_turbolift.dm new file mode 100644 index 00000000000..088bf39c8c4 --- /dev/null +++ b/code/modules/turbolift/_turbolift.dm @@ -0,0 +1,12 @@ +/* + * Turbolifts! Sort of like multishuttles-lite. + * + * How-to: Map /obj/turbolift_map_holder in at the bottom of the shaft, give it a depth + * value equivalent to the number of floors it should span (inclusive of the first), + * and at runtime it will update the map, set areas and create control panels and + * wifi-set doors appropriate to itself. You will save time at init if you map the + * elevator shaft in properly before runtime, but ultimately you're just avoiding a + * bunch of ChangeTurf() calls. + */ + +var/list/turbolifts = list() \ No newline at end of file diff --git a/code/modules/turbolift/turbolift.dm b/code/modules/turbolift/turbolift.dm new file mode 100644 index 00000000000..2ce90867776 --- /dev/null +++ b/code/modules/turbolift/turbolift.dm @@ -0,0 +1,118 @@ +// 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 + +/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") + 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") + return + +/datum/turbolift/proc/do_move() + + 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 + 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 + + sleep(15) + control_panel_interior.visible_message("The elevator announces, \"[origin.lift_announce_str]\"") + sleep(floor_wait_delay) + + 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(AM.simulated) + qdel(AM) + + origin.move_contents_to(destination) + + if((locate(/obj/machinery/power) in destination) || (locate(/obj/structure/cable) in destination)) + makepowernets() + + current_floor = next_floor + control_panel_interior.visible_message("The elevator [moving_upwards ? "rises" : "descends"] smoothly.") + + 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 + turbolift_controller.lift_is_moving(src) + +// TODO: dummy machine ('lift mechanism') in powered area for functionality/blackout checks. +/datum/turbolift/proc/is_functional() + return 1 \ No newline at end of file diff --git a/code/modules/turbolift/turbolift_areas.dm b/code/modules/turbolift/turbolift_areas.dm new file mode 100644 index 00000000000..dbf568aec2e --- /dev/null +++ b/code/modules/turbolift/turbolift_areas.dm @@ -0,0 +1,11 @@ +// Used for creating the exchange areas. +/area/turbolift + name = "Turbolift" + base_turf = /turf/simulated/open + requires_power = 0 + sound_env = SMALL_ENCLOSED + + var/lift_floor_label = null + var/lift_floor_name = null + var/lift_announce_str = "Ding!" + var/arrival_sound = 'sound/machines/ding.ogg' diff --git a/code/modules/turbolift/turbolift_console.dm b/code/modules/turbolift/turbolift_console.dm new file mode 100644 index 00000000000..406b9f1cee2 --- /dev/null +++ b/code/modules/turbolift/turbolift_console.dm @@ -0,0 +1,155 @@ +// Base type, do not use. +/obj/structure/lift + name = "turbolift control component" + icon = 'icons/obj/turbolift.dmi' + anchored = 1 + density = 0 + + var/datum/turbolift/lift + +/obj/structure/lift/set_dir(var/newdir) + . = ..() + pixel_x = 0 + pixel_y = 0 + if(dir & NORTH) + pixel_y = -32 + else if(dir & SOUTH) + pixel_y = 32 + else if(dir & EAST) + pixel_x = -32 + else if(dir & WEST) + pixel_x = 32 + +/obj/structure/lift/proc/pressed(var/mob/user) + if(!istype(user, /mob/living/silicon)) + if(user.a_intent == I_HURT) + user.visible_message("\The [user] hammers on the lift button!") + else + user.visible_message("\The [user] presses the lift button.") + + +/obj/structure/lift/New(var/newloc, var/datum/turbolift/_lift) + lift = _lift + return ..(newloc) + +/obj/structure/lift/attack_ai(var/mob/user) + return attack_hand(user) + +/obj/structure/lift/attack_generic(var/mob/user) + return attack_hand(user) + +/obj/structure/lift/attack_hand(var/mob/user) + return interact(user) + +/obj/structure/lift/interact(var/mob/user) + if(!lift.is_functional()) + return 0 + return 1 +// End base. + +// Button. No HTML interface, just calls the associated lift to its floor. +/obj/structure/lift/button + name = "elevator button" + desc = "A call button for an elevator. Be sure to hit it three hundred times." + icon_state = "button" + var/light_up = FALSE + var/datum/turbolift_floor/floor + +/obj/structure/lift/button/Destroy() + if(floor && floor.ext_panel == src) + floor.ext_panel = null + floor = null + return ..() + +/obj/structure/lift/button/proc/reset() + light_up = FALSE + update_icon() + +/obj/structure/lift/button/interact(var/mob/user) + if(!..()) + return + light_up() + pressed(user) + if(floor == lift.current_floor) + lift.open_doors() + spawn(3) + reset() + return + lift.queue_move_to(floor) + +/obj/structure/lift/button/proc/light_up() + light_up = TRUE + update_icon() + +/obj/structure/lift/button/update_icon() + if(light_up) + icon_state = "button_lit" + else + icon_state = initial(icon_state) + +// End button. + +// Panel. Lists floors (HTML), moves with the elevator, schedules a move to a given floor. +/obj/structure/lift/panel + name = "elevator control panel" + icon_state = "panel" + + +/obj/structure/lift/panel/attack_ghost(var/mob/user) + return interact(user) + +/obj/structure/lift/panel/interact(var/mob/user) + if(!..()) + return + + var/dat = list() + dat += "