This commit is contained in:
SandPoot
2024-04-24 20:12:27 -03:00
parent b956e0c40e
commit a1a80c5d4f
4 changed files with 145 additions and 37 deletions

View File

@@ -189,6 +189,12 @@
..()
update_icon()
/obj/machinery/button/vv_edit_var(vname, vval)
. = ..()
if(vname == NAMEOF(src, id))
var/obj/item/assembly/control/controller = device
if(istype(controller))
controller.id = vval
/obj/machinery/button/door
name = "door button"
@@ -285,3 +291,17 @@
icon_state = "button"
result_path = /obj/machinery/button
custom_materials = list(/datum/material/iron = MINERAL_MATERIAL_AMOUNT)
/obj/machinery/button/elevator
name = "elevator button"
desc = "Go back. Go back. Go back. Can you operate the elevator."
icon_state = "launcher"
skin = "launcher"
device_type = /obj/item/assembly/control/elevator
req_access = list()
id = 1
/obj/machinery/button/elevator/examine(mob/user)
. = ..()
. += "<span class='notice'>There's a small inscription on the button...</span>"
. += "<span class='notice'>THIS CALLS THE ELEVATOR! IT DOES NOT OPERATE IT! Interact with the elevator itself to use it!</span>"

View File

@@ -1,3 +1,8 @@
//Booleans in arguments are confusing, so I made them defines.
#define LOCKED 1
#define UNLOCKED 0
///Collect and command
/datum/lift_master
var/list/lift_platforms
@@ -43,18 +48,33 @@
possible_expansions |= lift_platform
possible_expansions -= borderline
///Move all platforms together
/**
* Moves the lift UP or DOWN, this is what users invoke with their hand.
* This is a SAFE proc, ensuring every part of the lift moves SANELY.
* It also locks controls for the (miniscule) duration of the movement, so the elevator cannot be broken by spamming.
* Arguments:
* going - UP or DOWN directions, where the lift should go. Keep in mind by this point checks of whether it should go up or down have already been done.
* user - Whomever made the lift movement.
*/
/datum/lift_master/proc/MoveLift(going, mob/user)
set_controls(LOCKED)
for(var/p in lift_platforms)
var/obj/structure/industrial_lift/lift_platform = p
lift_platform.travel(going)
set_controls(UNLOCKED)
/**
* Moves the lift, this is what users invoke with their hand.
* This is a SAFE proc, ensuring every part of the lift moves SANELY.
* It also locks controls for the (miniscule) duration of the movement, so the elevator cannot be broken by spamming.
*/
/datum/lift_master/proc/MoveLiftHorizontal(going, z)
var/max_x = 1
var/max_y = 1
var/min_x = world.maxx
var/min_y = world.maxy
set_controls(LOCKED)
for(var/p in lift_platforms)
var/obj/structure/industrial_lift/lift_platform = p
max_x = max(max_x, lift_platform.x)
@@ -89,12 +109,14 @@
for(var/y in min_y to max_y)
var/obj/structure/industrial_lift/lift_platform = locate(/obj/structure/industrial_lift, locate(x, y, z))
lift_platform.travel(going)
set_controls(UNLOCKED)
///Check destination turfs
/datum/lift_master/proc/Check_lift_move(check_dir)
for(var/lift_platform in lift_platforms)
for(var/l in lift_platforms)
var/obj/structure/industrial_lift/lift_platform = l
var/turf/T = get_step_multiz(lift_platform, check_dir)
if(!T)
if(!T)//the edges of multi-z maps
return FALSE
if(check_dir == UP && !istype(T, /turf/open/openspace)) // We don't want to go through the ceiling!
return FALSE
@@ -102,6 +124,15 @@
return FALSE
return TRUE
/**
* Sets all lift parts's controls_locked variable. Used to prevent moving mid movement, or cooldowns.
*/
/datum/lift_master/proc/set_controls(state)
for(var/l in lift_platforms)
var/obj/structure/industrial_lift/lift_platform = l
lift_platform.controls_locked = state
GLOBAL_LIST_EMPTY(lifts)
/obj/structure/industrial_lift
name = "lift platform"
desc = "A lightweight lift platform. It moves up and down."
@@ -117,12 +148,18 @@
canSmoothWith = null
obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN
var/id = null //ONLY SET THIS TO ONE OF THE LIFT'S PARTS. THEY'RE CONNECTED! ONLY ONE NEEDS THE SIGNAL!
var/pass_through_floors = FALSE //if true, the elevator works through floors
var/controls_locked = FALSE //if true, the lift cannot be manually moved.
var/list/atom/movable/lift_load //things to move
var/datum/lift_master/lift_master_datum //control from
/obj/structure/industrial_lift/New()
GLOB.lifts.Add(src)
..()
/obj/structure/industrial_lift/Initialize(mapload)
. = ..()
RegisterSignal(src, COMSIG_MOVABLE_CROSSED, PROC_REF(AddItemOnLift))
RegisterSignal(loc, COMSIG_ATOM_CREATED, PROC_REF(AddItemOnLift))//For atoms created on platform
RegisterSignal(src, COMSIG_MOVABLE_UNCROSSED, PROC_REF(RemoveItemFromLift))
@@ -133,7 +170,7 @@
/obj/structure/industrial_lift/Move(atom/newloc, direct)
UnregisterSignal(loc, COMSIG_ATOM_CREATED)
. = ..()
RegisterSignal(newloc, COMSIG_ATOM_CREATED, PROC_REF(AddItemOnLift))//For atoms created on platform
RegisterSignal(loc, COMSIG_ATOM_CREATED, PROC_REF(AddItemOnLift))//For atoms created on platform
/obj/structure/industrial_lift/proc/RemoveItemFromLift(datum/source, atom/movable/AM)
if(!(AM in lift_load))
@@ -162,51 +199,46 @@
destination = get_step_multiz(src, going)
else
destination = going
if(going == DOWN)//make sure this stays pre-item moving, or you'll crush anything on the lift under the lift.
for(var/mob/living/crushed in destination.contents)
to_chat(crushed, span_userdanger("You are crushed by [src]!"))
crushed.gib(FALSE,FALSE,FALSE)//the nicest kind of gibbing, keeping everything intact.
forceMove(destination)
for(var/am in things2move)
var/atom/movable/thing = am
thing.forceMove(destination)
/obj/structure/industrial_lift/proc/use(mob/user, is_ghost=FALSE)
if (is_ghost && !in_range(src, user))
if(is_ghost && !in_range(src, user))
return
var/static/list/tool_list = list(
"Up" = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = NORTH),
"Down" = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = SOUTH)
)
var/turf/can_move_up = lift_master_datum.Check_lift_move(UP)
var/turf/can_move_up_down = lift_master_datum.Check_lift_move(DOWN)
if (!can_move_up && !can_move_up_down)
to_chat(user, "<span class='warning'>[src] doesn't seem to able move anywhere!</span>")
var/list/tool_list = list()
if(lift_master_datum.Check_lift_move(UP))
tool_list["Up"] = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = NORTH)
if(lift_master_datum.Check_lift_move(DOWN))
tool_list["Down"] = image(icon = 'icons/testing/turf_analysis.dmi', icon_state = "red_arrow", dir = SOUTH)
if(!length(tool_list))
to_chat(user, span_warning("[src] doesn't seem to able to move anywhere!"))
add_fingerprint(user)
return
if(controls_locked)
to_chat(user, span_warning("[src] has its controls locked! It must already be trying to do something!"))
add_fingerprint(user)
return
var/result = show_radial_menu(user, src, tool_list, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE)
if (!is_ghost && !in_range(src, user))
if(!is_ghost && !in_range(src, user))
return // nice try
switch(result)
if("Up")
if(can_move_up)
lift_master_datum.MoveLift(UP, user)
show_fluff_message(TRUE, user)
use(user)
else
to_chat(user, "<span class='warning'>[src] doesn't seem to able move up!</span>")
use(user)
lift_master_datum.MoveLift(UP, user)
show_fluff_message(TRUE, user)
use(user)
if("Down")
if(can_move_up_down)
lift_master_datum.MoveLift(DOWN, user)
show_fluff_message(FALSE, user)
use(user)
else
to_chat(user, "<span class='warning'>[src] doesn't seem to able move down!</span>")
use(user)
lift_master_datum.MoveLift(DOWN, user)
show_fluff_message(FALSE, user)
use(user)
if("Cancel")
return
add_fingerprint(user)
/obj/structure/industrial_lift/proc/check_menu(mob/user)
@@ -217,6 +249,14 @@
/obj/structure/industrial_lift/on_attack_hand(mob/user)
return use(user)
//ai probably shouldn't get to use lifts but they sure are great for admins to crush people with
/obj/structure/industrial_lift/attack_ghost(mob/user)
. = ..()
if(.)
return
if(IsAdminGhost(user))
use(user)
/obj/structure/industrial_lift/attack_paw(mob/user)
return use(user)
@@ -229,11 +269,12 @@
/obj/structure/industrial_lift/proc/show_fluff_message(going_up, mob/user)
if(going_up)
user.visible_message("<span class='notice'>[user] move lift up.</span>", "<span class='notice'>Lift move up.</span>")
user.visible_message(span_notice("[user] moves the lift upwards."), span_notice("You move the lift upwards."))
else
user.visible_message("<span class='notice'>[user] move lift down.</span>", "<span class='notice'>Lift move down.</span>")
user.visible_message(span_notice("[user] moves the lift downwards."), span_notice("You move the lift downwards."))
/obj/structure/industrial_lift/Destroy()
GLOB.lifts.Remove(src)
QDEL_NULL(lift_master_datum)
var/list/border_lift_platforms = lift_platform_expansion()
moveToNullspace()

View File

@@ -87,6 +87,12 @@
if(AM)
user.start_pulling(AM)
//reopening ladder radial menu ahead
T = get_turf(user)
var/obj/structure/ladder/ladder_structure = locate() in T
if (ladder_structure && (up && down))
ladder_structure.use(user)
/obj/structure/ladder/proc/use(mob/user, is_ghost=FALSE)
if (!is_ghost && !in_range(src, user))
return

View File

@@ -20,9 +20,9 @@
/obj/item/assembly/control/examine(mob/user)
. = ..()
if(id && show_id)
. += "<span class='notice'>Its channel ID is '[id]'.</span>"
. += span_notice("Its channel ID is '[id]'.")
if(can_change_id)
. += "<span class='notice'>Use in hand to change ID.</span>"
. += span_notice("Use in hand to change ID.")
/obj/item/assembly/control/attack_self(mob/living/user)
. = ..()
@@ -165,3 +165,44 @@
/obj/item/assembly/control/electrochromatic/activate()
on = !on
do_electrochromatic_toggle(on, id)
//how long it spends on each floor when moving somewhere, so it'd take 4 seconds to reach you if it had to travel up 2 floors
#define FLOOR_TRAVEL_TIME 2 SECONDS
/obj/item/assembly/control/elevator
name = "elevator controller"
desc = "A small device used to call elevators to the current floor."
/obj/item/assembly/control/elevator/activate()
if(cooldown)
return
cooldown = TRUE
var/obj/structure/industrial_lift/lift
for(var/l in GLOB.lifts)
var/obj/structure/industrial_lift/possible_lift = l
if(possible_lift.id != id || possible_lift.z == z || possible_lift.controls_locked)
continue
lift = possible_lift
break
if(!lift)
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 2 SECONDS)
return
lift.visible_message(span_notice("[src] clinks and whirrs into automated motion, locking controls."))
lift.lift_master_datum.set_controls(LOCKED)
///The z level to which the elevator should travel
var/targetZ = (abs(loc.z)) //The target Z (where the elevator should move to) is not our z level (we are just some assembly in nullspace) but actually the Z level of whatever we are contained in (e.g. elevator button)
///The amount of z levels between the our and targetZ
var/difference = abs(targetZ - lift.z)
///Direction (up/down) needed to go to reach targetZ
var/direction = lift.z < targetZ ? UP : DOWN
///How long it will/should take us to reach the target Z level
var/travel_duration = FLOOR_TRAVEL_TIME * difference //100 / 2 floors up = 50 seconds on every floor, will always reach destination in the same time
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), travel_duration)
for(var/i in 1 to difference)
sleep(FLOOR_TRAVEL_TIME)//hey this should be alright... right?
if(QDELETED(lift) || QDELETED(src))//elevator control or button gone = don't go up anymore
return
lift.lift_master_datum.MoveLift(direction, null)
lift.visible_message(span_notice("[src] clicks, ready to be manually operated again."))
lift.lift_master_datum.set_controls(UNLOCKED)
#undef FLOOR_TRAVEL_TIME