Cargo elevator overhaul (#21430)

## About PR

Implements an animation logic heavily inspired from CM-SS13 elevators.
Elevator hatch and shaft sprites are courtesy of @KingOfThePing!

Currently if something is standing on the hatches when the elevator is
arriving, they'll be sent to CC level, fall, get paralyzed and severely
injured enough to have broken bones/arterial bleeding.

This PR also fixes cargo announcement screens not displaying elevator
ETA.

## Images

<details><summary>Elevator arriving</summary>
<p>



https://github.com/user-attachments/assets/34879994-d10b-4cb6-959e-314ec20411b8

</p>
</details> 

<details><summary>Elevator departing</summary>
<p>


https://github.com/user-attachments/assets/c345fd3b-07eb-4922-9b28-31cf40842da1

</p>
</details> 

<details><summary>Unfortunate victims falling to the pit</summary>
<p>



https://github.com/user-attachments/assets/98feac04-5d65-4383-8abc-363ce51a028a


</p>
</details> 

### Asset Licenses
The following assets that **have not** been created by myself are
included in this PR:

| Path | Original Author | License |
| --- | --- | --- |
| icons/effect/224x192.dmi | KingOfThePing | CC BY-SA 3.0 |
| icons/obj/doors/retractable_railing.dmi | CM-SS13 | CC BY-SA 3.0 |
| sound/machines/industrial_lift_raising.ogg | CM-SS13 | CC BY-SA 3.0 |
| sound/machines/industrial_lift_lowering.ogg | CM-SS13 | CC BY-SA 3.0 |
| sound/machines/warning-buzzer-2.ogg | Unknown -
https://pixabay.com/sound-effects/incorrect-buzzer-sound-147336/ |
Pixabay Licence |
This commit is contained in:
Kano
2025-10-05 17:26:49 +03:00
committed by GitHub
parent 451eb5dcef
commit 2d9d4ce4b6
15 changed files with 1078 additions and 543 deletions
+31 -3
View File
@@ -22,9 +22,8 @@
// Cargo Elevator Plating
/turf/simulated/floor/plating/cargo_elevator
name = "cargo elevator plating"
desc = "The cargo elevator's plating."
mouse_opacity = MOUSE_OPACITY_TRANSPARENT // Obscured by the hatch, shouldn't be examinable by players.
name = "cargo hatch plating"
desc = "The cargo hatch's plating."
// Sanity checks in case someone somehow tries to interact with one of the platings.
/turf/simulated/floor/plating/cargo_elevator/attack_hand(mob/user)
@@ -32,3 +31,32 @@
/turf/simulated/floor/plating/cargo_elevator/attackby(obj/item/attacking_item, mob/user)
to_chat(user, SPAN_NOTICE("You hit \the [src] with \the [attacking_item]. Nothing happens."))
/obj/effect/elevator
name = "\proper elevator shaft"
desc = "There seems to be an awful lot of machinery down below."
icon = 'icons/effects/224x192.dmi'
icon_state = "elevator_shaft"
unacidable = TRUE
layer = TURF_DETAIL_LAYER
appearance_flags = KEEP_TOGETHER
/obj/effect/elevator/ex_act(severity)
return
/obj/effect/elevator/animation_overlay
icon_state = null
layer = TURF_SHADOW_LAYER
blend_mode = BLEND_INSET_OVERLAY
appearance_flags = KEEP_TOGETHER
/obj/effect/elevator/animation_overlay/hatch
name = "elevator hatch"
icon_state = "hatch"
/obj/effect/elevator/animation_overlay/hatch/left
icon_state = "hatch_L"
/obj/effect/elevator/animation_overlay/hatch/right
icon_state = "hatch_R"
+87 -11
View File
@@ -18,6 +18,11 @@
var/maxhealth = 70
var/neighbor_status = 0
/// If the object shouldn't inherit a material, set this to True.
var/non_material_object = FALSE
var/can_wrench = TRUE
var/can_screwdriver = TRUE
can_astar_pass = CANASTARPASS_ALWAYS_PROC
/obj/structure/railing/condition_hints(mob/user, distance, is_adjacent)
@@ -72,19 +77,20 @@
/obj/structure/railing/Initialize()
. = ..()
if(!isnull(material) && !istype(material))
material = SSmaterials.get_material_by_name(material)
if(!istype(material))
return INITIALIZE_HINT_QDEL
if(!non_material_object)
if(!isnull(material) && !istype(material))
material = SSmaterials.get_material_by_name(material)
if(!istype(material))
return INITIALIZE_HINT_QDEL
name = "[material.display_name] [initial(name)]"
desc = "A simple [material.display_name] railing designed to protect against careless trespass."
maxhealth = round(material.integrity / 5)
health = maxhealth
color = material.icon_colour
name = "[material.display_name] [initial(name)]"
desc = "A simple [material.display_name] railing designed to protect against careless trespass."
maxhealth = round(material.integrity / 5)
health = maxhealth
color = material.icon_colour
if(material.products_need_process())
START_PROCESSING(SSprocessing, src)
if(material.products_need_process())
START_PROCESSING(SSprocessing, src)
if(anchored)
update_icon(FALSE)
@@ -246,6 +252,9 @@
// Dismantle
if(attacking_item.iswrench())
if(!can_wrench)
to_chat(user, SPAN_WARNING("This [src] cannot be adjusted."))
return
if(!anchored)
user.visible_message(SPAN_NOTICE("\The [user] starts dismantling \the [src]..."), SPAN_NOTICE("You start dismantling \the [src]..."))
if(attacking_item.use_tool(src, user, 20, volume = 50))
@@ -283,6 +292,9 @@
// Install
if(attacking_item.isscrewdriver())
if(!can_screwdriver)
to_chat(user, SPAN_WARNING("This [src] cannot be adjusted."))
return
if(!density)
to_chat(user, SPAN_NOTICE("You need to wrench \the [src] from back into place first."))
return
@@ -365,3 +377,67 @@
/obj/structure/railing/fence/New(var/newloc, var/material_key = MATERIAL_WOOD)
material = material_key
..(newloc)
/obj/structure/railing/retractable
name = "\improper retractable railing"
icon = 'icons/obj/doors/retractable_railing.dmi'
icon_state = "railing1"
anchored = TRUE
health = 150
maxhealth = 150
non_material_object = TRUE
can_wrench = FALSE
can_screwdriver = FALSE
var/closed_layer = ABOVE_DOOR_LAYER
var/open_layer = OPEN_DOOR_LAYER
var/icon_state_open = "railing0"
var/icon_state_opening = "railingc0"
var/icon_state_closed = "railing1"
var/icon_state_closing = "railingc1"
var/operating
/obj/structure/railing/retractable/Initialize()
. = ..()
if(dir == SOUTH)
closed_layer = ABOVE_HUMAN_LAYER
if(density)//Allows preset-open to work
layer = closed_layer
set_opacity(initial(opacity))
/obj/structure/railing/retractable/update_icon()
if(density)
icon_state = icon_state_closed
else
icon_state = icon_state_open
/obj/structure/railing/retractable/proc/toggle_state()
if(operating)
return
operating = TRUE
flick(density ? icon_state_opening : icon_state_closing, src)
playsound(get_turf(src), 'sound/machines/retractable_railing_openclose.ogg', 20)
if(density)
icon_state = icon_state_open
layer = open_layer
else
icon_state = icon_state_closed
layer = closed_layer
addtimer(CALLBACK(src, PROC_REF(finish_toggling)), 1.2 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT)
return TRUE
/obj/structure/railing/retractable/proc/finish_toggling()
density = !density
operating = FALSE
/obj/structure/railing/retractable/NeighborsCheck()
return
/obj/structure/railing/retractable/flip()
return
/obj/structure/railing/retractable/open
density = FALSE