diff --git a/_maps/map_files/debug/multiz.dmm b/_maps/map_files/debug/multiz.dmm index 22c88a5afd0..d0e39e1e300 100644 --- a/_maps/map_files/debug/multiz.dmm +++ b/_maps/map_files/debug/multiz.dmm @@ -630,6 +630,9 @@ /obj/machinery/button/elevator/directional/north{ id = "test_vator" }, +/obj/machinery/lift_indicator/directional/north{ + linked_elevator_id = "test_vator" + }, /turf/open/floor/iron, /area/station/commons/storage/primary) "di" = ( @@ -1073,6 +1076,9 @@ /obj/effect/turf_decal/siding/white{ dir = 6 }, +/obj/machinery/lift_indicator/directional/east{ + linked_elevator_id = "test_vator" + }, /turf/open/floor/plating/elevatorshaft, /area/station/commons/storage/primary) "mb" = ( @@ -1659,6 +1665,9 @@ /obj/machinery/button/elevator/directional/north{ id = "test_vator" }, +/obj/machinery/lift_indicator/directional/north{ + linked_elevator_id = "test_vator" + }, /turf/open/openspace, /area/station/engineering/storage) "LM" = ( @@ -1858,6 +1867,9 @@ /obj/machinery/button/elevator/directional/north{ id = "test_vator" }, +/obj/machinery/lift_indicator/directional/north{ + linked_elevator_id = "test_vator" + }, /turf/open/floor/iron, /area/station/hallway/secondary/service) "VG" = ( diff --git a/code/__DEFINES/dcs/signals/signals_lift.dm b/code/__DEFINES/dcs/signals/signals_lift.dm new file mode 100644 index 00000000000..26eef6b9e17 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_lift.dm @@ -0,0 +1,2 @@ +/// Sent from /datum/lift_master when a normal lift starts or stops going up or down. (direction if started or 0 if stopped) +#define COMSIG_LIFT_SET_DIRECTION "lift_set_direction" diff --git a/code/modules/industrial_lift/lift_indicator.dm b/code/modules/industrial_lift/lift_indicator.dm new file mode 100644 index 00000000000..52376457ef6 --- /dev/null +++ b/code/modules/industrial_lift/lift_indicator.dm @@ -0,0 +1,173 @@ + +/** + * A lift indicator aka an elevator hall lantern w/ floor number + */ +/obj/machinery/lift_indicator + name = "lift floor indicator" + desc = "Indicates what floor the lift is on and which way it's going." + icon = 'icons/obj/machines/lift_indicator.dmi' + icon_state = "lift_indo-base" + base_icon_state = "lift_indo-" + max_integrity = 500 + integrity_failure = 0.25 + idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.05 + active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.02 + anchored = TRUE + density = FALSE + + light_range = 1 + light_power = 0.5 + light_color = "#F8E398" + luminosity = 1 + + maptext_x = 17 + maptext_y = 12 + maptext_width = 4 + maptext_height = 8 + + /// What specific_lift_id do we link with? + var/linked_elevator_id + + // = (real lowest floor's z-level) - (what we want to display) + var/lowest_floor_offset = 1 + + /// Weakref to the lift. + var/datum/weakref/lift_ref + /// The lowest floor number. Determined by lift init. + var/lowest_floor_num = 1 + /// Positive for going up, negative going down, 0 for stopped + var/current_lift_direction = 0 + /// The lift's current floor relative to its lowest floor being 1 + var/current_lift_floor = 1 + +/obj/machinery/lift_indicator/Initialize(mapload) + . = ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/lift_indicator/LateInitialize() + . = ..() + + for(var/datum/lift_master/possible_match as anything in GLOB.active_lifts_by_type[BASIC_LIFT_ID]) + if(possible_match.specific_lift_id != linked_elevator_id) + continue + + lift_ref = WEAKREF(possible_match) + RegisterSignal(possible_match, COMSIG_LIFT_SET_DIRECTION, .proc/on_lift_direction) + +/obj/machinery/lift_indicator/examine(mob/user) + . = ..() + + if(!is_operational) + . += span_notice("The display is dark.") + return + + var/dirtext + switch(current_lift_direction) + if(UP) + dirtext = "heading upwards" + if(DOWN) + dirtext = "heading downwards" + else + dirtext = "stopped" + + . += span_notice("The lift is on floor [current_lift_floor], [dirtext].") + +/** + * Update state, and only process if lift is moving. + */ +/obj/machinery/lift_indicator/proc/on_lift_direction(datum/source, direction) + SIGNAL_HANDLER + + var/datum/lift_master/lift = lift_ref?.resolve() + if(!lift) + return + + set_lift_state(direction, current_lift_floor) + update_operating() + +/obj/machinery/lift_indicator/on_set_is_operational() + . = ..() + + update_operating() + +/** + * Update processing state. + * + * Returns whether we are still processing. + */ +/obj/machinery/lift_indicator/proc/update_operating() + // Let process() figure it out to have the logic in one place. + var/should_process = process() != PROCESS_KILL + if(should_process) + begin_processing() + return + end_processing() + +/obj/machinery/lift_indicator/process() + var/datum/lift_master/lift = lift_ref?.resolve() + + // Check for stopped states. + if(!lift || !is_operational) + // Lift missing, or we lost power. + set_lift_state(0, 0, force = !is_operational) + return PROCESS_KILL + + use_power(active_power_usage) + + var/obj/structure/industrial_lift/lift_part = lift.lift_platforms[1] + + if(QDELETED(lift_part)) + set_lift_state(0, 0, force = !is_operational) + return PROCESS_KILL + + // Update + set_lift_state(current_lift_direction, lift.lift_platforms[1].z - lowest_floor_offset) + + // Lift's not moving, we're done; we just had to update the floor number one last time. + if(!current_lift_direction) + return PROCESS_KILL + +/** + * Set the state and update appearance. + * + * Arguments: + * new_direction - new arrow state: UP, DOWN, or 0 + * new_floor - set the floor number, eg. 1, 2, 3 + * force_update - force appearance to update even if state didn't change. + */ +/obj/machinery/lift_indicator/proc/set_lift_state(new_direction, new_floor, force = FALSE) + if(new_direction == current_lift_direction && new_floor == current_lift_floor && !force) + return + + current_lift_direction = new_direction + current_lift_floor = new_floor + update_appearance() + +/obj/machinery/lift_indicator/update_appearance(updates) + . = ..() + + if(!is_operational) + set_light(l_on = FALSE) + maptext = "" + return + + set_light(l_on = TRUE) + maptext = {"