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 += "
Lift panel
" + + //the floors list stores levels in order of increasing Z + //therefore, to display upper levels at the top of the menu and + //lower levels at the bottom, we need to go through the list in reverse + for(var/i in lift.floors.len to 1 step -1) + var/datum/turbolift_floor/floor = lift.floors[i] + if(floor) + var/label = floor.label? floor.label : "Level #[i]" + dat += "" + dat += "[label]: [floor.name]
" + + dat += "
" + if(lift.doors_are_open()) + dat += "Close Doors
" + else + dat += "Open Doors
" + dat += "Emergency Stop" + dat += "
" + + var/datum/browser/popup = new(user, "turbolift_panel", "Lift Panel", 230, 260) + popup.set_content(jointext(dat, null)) + popup.open() + return + +/obj/structure/lift/panel/Topic(href, href_list) + . = ..() + if(.) + return + + var/panel_interact + if(href_list["move_to_floor"]) + lift.queue_move_to(locate(href_list["move_to_floor"])) + panel_interact = 1 + if(href_list["open_doors"]) + panel_interact = 1 + lift.open_doors() + if(href_list["close_doors"]) + panel_interact = 1 + lift.close_doors() + if(href_list["emergency_stop"]) + panel_interact = 1 + lift.emergency_stop() + + if(panel_interact) + pressed(usr) + + return 0 + +// End panel. \ No newline at end of file diff --git a/code/modules/turbolift/turbolift_door.dm b/code/modules/turbolift/turbolift_door.dm new file mode 100644 index 00000000000..79bf1d0c51a --- /dev/null +++ b/code/modules/turbolift/turbolift_door.dm @@ -0,0 +1,44 @@ +/obj/machinery/door/airlock/lift + name = "Elevator Door" + desc = "Ding." + req_access = list(access_maint_tunnels) + opacity = 0 + autoclose = 0 + glass = 1 + icon = 'icons/obj/doors/doorlift.dmi' + + var/datum/turbolift/lift + var/datum/turbolift_floor/floor + +/obj/machinery/door/airlock/lift/Destroy() + if(lift) + lift.doors -= src + if(floor) + floor.doors -= src + return ..() + +/obj/machinery/door/airlock/lift/bumpopen(var/mob/user) + return // No accidental sprinting into open elevator shafts. + +/obj/machinery/door/airlock/lift/allowed(mob/M) + return FALSE //only the lift machinery is allowed to operate this door + +/obj/machinery/door/airlock/lift/close(var/forced=0) + for(var/turf/turf in locs) + for(var/mob/living/LM in turf) + if(LM.mob_size <= MOB_TINY) + var/moved = 0 + for(dir in shuffle(cardinal.Copy())) + var/dest = get_step(LM,dir) + if(!(locate(/obj/machinery/door/airlock/lift) in dest)) + if(LM.Move(dest)) + moved = 1 + LM.visible_message("\The [LM] scurries away from the closing doors.") + break + if(!moved) // nowhere to go.... + LM.gib() + else // the mob is too big to just move, so we need to give up what we're doing + audible_message("\The [src]'s motors grind as they quickly reverse direction, unable to safely close.") + cur_command = null // the door will just keep trying otherwise + return 0 + return ..() \ No newline at end of file diff --git a/code/modules/turbolift/turbolift_floor.dm b/code/modules/turbolift/turbolift_floor.dm new file mode 100644 index 00000000000..7761f092843 --- /dev/null +++ b/code/modules/turbolift/turbolift_floor.dm @@ -0,0 +1,33 @@ +// Simple holder for each floor in the lift. +/datum/turbolift_floor + var/area_ref + var/label + var/name + var/announce_str + var/arrival_sound + + var/list/doors = list() + var/obj/structure/lift/button/ext_panel + +/datum/turbolift_floor/proc/set_area_ref(var/ref) + var/area/turbolift/A = locate(ref) + if(!istype(A)) + log_debug("Turbolift floor area was of the wrong type: ref=[ref]") + return + + area_ref = ref + label = A.lift_floor_label + name = A.lift_floor_name ? A.lift_floor_name : A.name + announce_str = A.lift_announce_str + arrival_sound = A.arrival_sound + +//called when a lift has queued this floor as a destination +/datum/turbolift_floor/proc/pending_move(var/datum/turbolift/lift) + if(ext_panel) + ext_panel.light_up() + +//called when a lift arrives at this floor +/datum/turbolift_floor/proc/arrived(var/datum/turbolift/lift) + lift.open_doors(src) + if(ext_panel) + ext_panel.reset() \ No newline at end of file diff --git a/code/modules/turbolift/turbolift_map.dm b/code/modules/turbolift/turbolift_map.dm new file mode 100644 index 00000000000..39554a53a5c --- /dev/null +++ b/code/modules/turbolift/turbolift_map.dm @@ -0,0 +1,234 @@ +// Map object. +/obj/turbolift_map_holder + name = "turbolift map placeholder" + icon = 'icons/obj/turbolift_preview_3x3.dmi' + dir = SOUTH // Direction of the holder determines the placement of the lift control panel and doors. + var/clear_objects = 1 + var/depth = 1 // Number of floors to generate, including the initial floor. + var/lift_size_x = 2 // Number of turfs on each axis to generate in addition to the first + var/lift_size_y = 2 // ie. a 3x3 lift would have a value of 2 in each of these variables. + + // Various turf and door types used when generating the turbolift floors. + var/wall_type = /turf/simulated/wall/elevator + var/floor_type = /turf/simulated/floor/tiled/dark + var/door_type = /obj/machinery/door/airlock/lift + + var/list/areas_to_use = list() + +/obj/turbolift_map_holder/Destroy() + turbolifts -= src + return ..() + +/obj/turbolift_map_holder/New() + turbolifts += src + ..() + +/obj/turbolift_map_holder/initialize() + + // Create our system controller. + var/datum/turbolift/lift = new() + + // Holder values since we're moving this object to null ASAP. + var/ux = x + var/uy = y + var/uz = z + var/udir = dir + forceMove(null) + + // These modifiers are used in relation to the origin + // to place the system control panels and doors. + var/int_panel_x + var/int_panel_y + var/ext_panel_x + var/ext_panel_y + var/door_x1 + var/door_y1 + var/door_x2 + var/door_y2 + var/light_x1 + var/light_x2 + var/light_y1 + var/light_y2 + + var/az = 1 + var/ex = (ux+lift_size_x) + var/ey = (uy+lift_size_y) + var/ez = (uz+(depth-1)) + + switch(dir) + + if(NORTH) + + int_panel_x = ux + Floor(lift_size_x/2) + int_panel_y = uy + 1 + ext_panel_x = ux + ext_panel_y = ey + 2 + + door_x1 = ux + 1 + door_y1 = ey + door_x2 = ex - 1 + door_y2 = ey + 1 + + light_x1 = ux + 1 + light_y1 = uy + 1 + light_x2 = ux + lift_size_x - 1 + light_y2 = uy + 1 + + if(SOUTH) + + int_panel_x = ux + Floor(lift_size_x/2) + int_panel_y = ey - 1 + ext_panel_x = ex + ext_panel_y = uy - 2 + + door_x1 = ux + 1 + door_y1 = uy - 1 + door_x2 = ex - 1 + door_y2 = uy + + light_x1 = ux + 1 + light_y1 = uy + 2 + light_x2 = ux + lift_size_x - 1 + light_y2 = uy + lift_size_y - 1 + + if(EAST) + + int_panel_x = ux+1 + int_panel_y = uy + Floor(lift_size_y/2) + ext_panel_x = ex+2 + ext_panel_y = ey + + door_x1 = ex + door_y1 = uy + 1 + door_x2 = ex + 1 + door_y2 = ey - 1 + + light_x1 = ux + 1 + light_y1 = uy + 1 + light_x2 = ux + 1 + light_y2 = uy + lift_size_x - 1 + + if(WEST) + + int_panel_x = ex-1 + int_panel_y = uy + Floor(lift_size_y/2) + ext_panel_x = ux-2 + ext_panel_y = uy + + door_x1 = ux - 1 + door_y1 = uy + 1 + door_x2 = ux + door_y2 = ey - 1 + + light_x1 = ux + lift_size_x - 1 + light_y1 = uy + 1 + light_x2 = ux + lift_size_x - 1 + light_y2 = uy + lift_size_y - 1 + + // Generate each floor and store it in the controller datum. + if(uz != 1) + for(var/i = 1, i < uz, i++) + lift.floors += null // This silly hack allows lifts to not start on the first zlevel + + for(var/cz = uz;cz<=ez;cz++) + + var/datum/turbolift_floor/cfloor = new() + lift.floors += cfloor + + var/list/floor_turfs = list() + // Update the appropriate turfs. + for(var/tx = ux to ex) + for(var/ty = uy to ey) + + var/turf/checking = locate(tx,ty,cz) + + if(!istype(checking)) + log_debug("[name] cannot find a component turf at [tx],[ty] on floor [cz]. Aborting.") + qdel(src) + return + + // Update path appropriately if needed. + var/swap_to = /turf/simulated/open + if(cz == uz) // Elevator. + if((tx == ux || ty == uy || tx == ex || ty == ey) && !(tx >= door_x1 && tx <= door_x2 && ty >= door_y1 && ty <= door_y2)) + swap_to = wall_type + else + swap_to = floor_type + + if(checking.type != swap_to) + checking.ChangeTurf(swap_to) + // Let's make absolutely sure that we have the right turf. + checking = locate(tx,ty,cz) + + // Clear out contents. + if(clear_objects) + for(var/atom/movable/thing in checking.contents) + if(thing.simulated) + qdel(thing) + + if(tx >= ux && tx <= ex && ty >= uy && ty <= ey) + floor_turfs += checking + + // Place exterior doors. + for(var/tx = door_x1 to door_x2) + for(var/ty = door_y1 to door_y2) + var/turf/checking = locate(tx,ty,cz) + var/internal = 1 + if(!(checking in floor_turfs)) + internal = 0 + if(checking.type != floor_type) + checking.ChangeTurf(floor_type) + checking = locate(tx,ty,cz) + for(var/atom/movable/thing in checking.contents) + if(thing.simulated) + qdel(thing) + if(checking.type == floor_type) // Don't build over empty space on lower levels. + var/obj/machinery/door/airlock/lift/newdoor = new door_type(checking) + if(internal) + lift.doors += newdoor + newdoor.lift = cfloor + else + cfloor.doors += newdoor + newdoor.floor = cfloor + + // Place exterior control panel. + var/turf/placing = locate(ext_panel_x, ext_panel_y, cz) + var/obj/structure/lift/button/panel_ext = new(placing, lift) + panel_ext.floor = cfloor + panel_ext.set_dir(udir) + cfloor.ext_panel = panel_ext + + // Place lights + var/turf/placing1 = locate(light_x1, light_y1, cz) + var/turf/placing2 = locate(light_x2, light_y2, cz) + var/obj/machinery/light/light1 = new(placing1, light) + var/obj/machinery/light/light2 = new(placing2, light) + if(udir == NORTH || udir == SOUTH) + light1.set_dir(WEST) + light2.set_dir(EAST) + else + light1.set_dir(SOUTH) + light2.set_dir(NORTH) + + // Update area. + if(az > areas_to_use.len) + log_debug("Insufficient defined areas in turbolift datum, aborting.") + qdel(src) + return + + var/area_path = areas_to_use[az] + for(var/thing in floor_turfs) + new area_path(thing) + var/area/A = locate(area_path) + cfloor.set_area_ref("\ref[A]") + az++ + + // Place lift panel. + var/turf/T = locate(int_panel_x, int_panel_y, uz) + lift.control_panel_interior = new(T, lift) + lift.control_panel_interior.set_dir(udir) + lift.current_floor = lift.floors[uz] + + lift.open_doors() + + qdel(src) // We're done. diff --git a/code/modules/turbolift/turbolift_process.dm b/code/modules/turbolift/turbolift_process.dm new file mode 100644 index 00000000000..e252b02d1d8 --- /dev/null +++ b/code/modules/turbolift/turbolift_process.dm @@ -0,0 +1,45 @@ +var/datum/controller/process/turbolift/turbolift_controller + +/datum/controller/process/turbolift + var/list/moving_lifts = list() + var/list/processing_lifts = list() + +/datum/controller/process/turbolift/New() + ..() + turbolift_controller = src + +/datum/controller/process/turbolift/setup() + name = "turbolift controller" + schedule_interval = 10 + +/datum/controller/process/turbolift/doWork() + if(!processing_lifts.len) + processing_lifts = moving_lifts.Copy() + + while(processing_lifts.len) + var/liftRef = processing_lifts[processing_lifts.len] + processing_lifts.len-- + + if(!(world.time < moving_lifts[liftRef])) + var/datum/turbolift/lift = locate(liftRef) + if(!lift.busy) + + spawn(0) + lift.busy = 1 + if(!lift.do_move()) + moving_lifts[liftRef] = null + moving_lifts -= liftRef + if(lift.target_floor) + lift.target_floor.ext_panel.reset() + lift.target_floor = null + + else + lift_is_moving(lift) + + lift.busy = 0 + + F_SCHECK + +//Dis is being called all the time, rather use a timer to call it when needed or speed through the lifts? +/datum/controller/process/turbolift/proc/lift_is_moving(var/datum/turbolift/lift) + moving_lifts["\ref[lift]"] = world.time + lift.move_delay diff --git a/code/modules/turbolift/turbolift_turfs.dm b/code/modules/turbolift/turbolift_turfs.dm new file mode 100644 index 00000000000..632160efaa1 --- /dev/null +++ b/code/modules/turbolift/turbolift_turfs.dm @@ -0,0 +1,2 @@ +/turf/simulated/wall/elevator/New(var/newloc) + ..(newloc,"elevatorium") diff --git a/icons/obj/doors/doorlift.dmi b/icons/obj/doors/doorlift.dmi new file mode 100644 index 00000000000..3b037a89568 Binary files /dev/null and b/icons/obj/doors/doorlift.dmi differ diff --git a/icons/obj/turbolift.dmi b/icons/obj/turbolift.dmi new file mode 100644 index 00000000000..cffc8aa140c Binary files /dev/null and b/icons/obj/turbolift.dmi differ diff --git a/icons/obj/turbolift_preview_2x2.dmi b/icons/obj/turbolift_preview_2x2.dmi new file mode 100644 index 00000000000..f0f1ec491e1 Binary files /dev/null and b/icons/obj/turbolift_preview_2x2.dmi differ diff --git a/icons/obj/turbolift_preview_3x3.dmi b/icons/obj/turbolift_preview_3x3.dmi new file mode 100644 index 00000000000..e054a6b9aac Binary files /dev/null and b/icons/obj/turbolift_preview_3x3.dmi differ