mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-22 20:43:10 +01:00
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:
@@ -107,14 +107,11 @@
|
||||
if(on)
|
||||
vis_contents += spin_effect
|
||||
|
||||
|
||||
/obj/machinery/rotating_alarm/proc/set_on()
|
||||
vis_contents += spin_effect
|
||||
set_light(2, 0.5, alarm_light_color)
|
||||
on = TRUE
|
||||
|
||||
|
||||
/obj/machinery/rotating_alarm/proc/set_off()
|
||||
vis_contents -= spin_effect
|
||||
set_light(0)
|
||||
on = FALSE
|
||||
/obj/machinery/rotating_alarm/proc/toggle_state()
|
||||
if(on)
|
||||
vis_contents -= spin_effect
|
||||
set_light(0)
|
||||
else
|
||||
vis_contents += spin_effect
|
||||
set_light(2, 0.5, alarm_light_color)
|
||||
on = !on
|
||||
|
||||
@@ -119,24 +119,7 @@
|
||||
AddOverlays(emissive_appearance(icon, "outline", src, alpha = src.alpha))
|
||||
return 1
|
||||
if(STATUS_DISPLAY_MESSAGE) //custom messages
|
||||
var/line1_metric
|
||||
var/line2_metric
|
||||
var/line_pair
|
||||
var/datum/font/display_font = new STATUS_DISPLAY_FONT_DATUM()
|
||||
line1_metric = display_font.get_metrics(message1)
|
||||
line2_metric = display_font.get_metrics(message2)
|
||||
line_pair = (line1_metric > line2_metric ? line1_metric : line2_metric)
|
||||
var/overlay = update_message(message1_overlay, LINE1_Y, message1, LINE1_X, line_pair)
|
||||
if(overlay)
|
||||
message1_overlay = overlay
|
||||
overlay = update_message(message2_overlay, LINE2_Y, message2, LINE2_X, line_pair)
|
||||
if(overlay)
|
||||
message2_overlay = overlay
|
||||
if(message1 == "" && message2 == "")
|
||||
return 1
|
||||
else
|
||||
AddOverlays(emissive_appearance(icon, "outline", src, alpha = src.alpha))
|
||||
return 1
|
||||
arrange_displayed_texts(message1, message2)
|
||||
if(STATUS_DISPLAY_ALERT)
|
||||
set_picture(picture_state)
|
||||
return 1
|
||||
@@ -144,26 +127,29 @@
|
||||
message1 = "-Time-"
|
||||
message2 = worldtime2text()
|
||||
set_messages(message1, message2)
|
||||
var/line1_metric
|
||||
var/line2_metric
|
||||
var/line_pair
|
||||
var/datum/font/display_font = new STATUS_DISPLAY_FONT_DATUM()
|
||||
line1_metric = display_font.get_metrics(message1)
|
||||
line2_metric = display_font.get_metrics(message2)
|
||||
line_pair = (line1_metric > line2_metric ? line1_metric : line2_metric)
|
||||
var/overlay = update_message(message1_overlay, LINE1_Y, message1, LINE1_X, line_pair)
|
||||
if(overlay)
|
||||
message1_overlay = overlay
|
||||
overlay = update_message(message2_overlay, LINE2_Y, message2, LINE2_X, line_pair)
|
||||
if(overlay)
|
||||
message2_overlay = overlay
|
||||
if(message1 == "" && message2 == "")
|
||||
return 1
|
||||
else
|
||||
AddOverlays(emissive_appearance(icon, "outline", src, alpha = src.alpha))
|
||||
return 1
|
||||
arrange_displayed_texts(message1, message2)
|
||||
return 0
|
||||
|
||||
/obj/machinery/status_display/proc/arrange_displayed_texts(message1, message2)
|
||||
var/line1_metric
|
||||
var/line2_metric
|
||||
var/line_pair
|
||||
var/datum/font/display_font = new STATUS_DISPLAY_FONT_DATUM()
|
||||
line1_metric = display_font.get_metrics(message1)
|
||||
line2_metric = display_font.get_metrics(message2)
|
||||
line_pair = (line1_metric > line2_metric ? line1_metric : line2_metric)
|
||||
var/overlay = update_message(message1_overlay, LINE1_Y, message1, LINE1_X, line_pair)
|
||||
if(overlay)
|
||||
message1_overlay = overlay
|
||||
overlay = update_message(message2_overlay, LINE2_Y, message2, LINE2_X, line_pair)
|
||||
if(overlay)
|
||||
message2_overlay = overlay
|
||||
if(message1 == "" && message2 == "")
|
||||
return 1
|
||||
else
|
||||
AddOverlays(emissive_appearance(icon, "outline", src, alpha = src.alpha))
|
||||
return 1
|
||||
|
||||
/obj/machinery/status_display/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
|
||||
. = ..()
|
||||
if(mode != STATUS_DISPLAY_BLANK && mode != STATUS_DISPLAY_ALERT)
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
message2 = "ETA"
|
||||
else
|
||||
if(shuttle.at_station())
|
||||
message2 = "Docked"
|
||||
message2 = "Elevator Arrived"
|
||||
else
|
||||
message1 = ""
|
||||
set_messages(message1, message2)
|
||||
return 1
|
||||
arrange_displayed_texts(message1, message2)
|
||||
return 0
|
||||
|
||||
/obj/machinery/status_display/supply_display/receive_signal(datum/signal/signal)
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -351,6 +351,7 @@
|
||||
icon_state = "stairs_railing"
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
layer = ABOVE_ABOVE_HUMAN_LAYER
|
||||
|
||||
/obj/structure/stairs_railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
|
||||
@@ -1,12 +1,84 @@
|
||||
/// Used for placing '/obj/effect/elevator' to the northern corners of the shaft.
|
||||
#define SHAFT_WIDTH 6
|
||||
/// Used for locating center of the shaft.
|
||||
#define SHAFT_CENTER_OFFSET 3
|
||||
#define ELEVATOR_DEPARTING_X 224
|
||||
#define ELEVATOR_DEPARTING_Y -96
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply
|
||||
category = /datum/shuttle/autodock/ferry/supply
|
||||
var/away_location = 1 //the location to hide at while pretending to be in-transit
|
||||
/// The location to hide at while pretending to be in-transit.
|
||||
var/away_location = 1
|
||||
var/late_chance = 80
|
||||
var/max_late_time = 300
|
||||
|
||||
/// A list for step_triggers, used for toggling fall functionality. Making the elevator shaft tiles safe to stand or not depening on where the elevator is.
|
||||
var/list/step_trigger_group = list()
|
||||
|
||||
/// Elevator effects for each northern corners of the shaft. This way the entire elevator won't disappear if there's an opaque obstacle in the sight line of original turf.
|
||||
/// Later on hardcoded to have their icons positioned on top of each other.
|
||||
/// These contain elevator shaft sprite. '/obj/effect/elevator/animation_overlay/elevator_animation' is used as a masked layer onto this.
|
||||
var/obj/effect/elevator/NW
|
||||
var/obj/effect/elevator/NE
|
||||
|
||||
/// This effect will contain an image, copy of the turfs at CC supply shuttle zone. Added onto the elevator shaft effect as an off-centered overlay.
|
||||
var/obj/effect/elevator/animation_overlay/elevator_animation
|
||||
|
||||
/// Hatch layers. Works similar to 'elevator_animation'.
|
||||
var/obj/effect/elevator/animation_overlay/hatch/left/hatch_left
|
||||
var/obj/effect/elevator/animation_overlay/hatch/right/hatch_right
|
||||
|
||||
/// Locations caches for Horizon elevator bay.
|
||||
var/target_dest_x
|
||||
var/target_dest_y
|
||||
var/target_dest_z
|
||||
|
||||
/// Area cache of Horizon elevator bay.
|
||||
var/area/horizon_elevator_area
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply/New(var/_name, var/obj/effect/shuttle_landmark/start_waypoint)
|
||||
..(_name, start_waypoint)
|
||||
SScargo.shuttle = src
|
||||
addtimer(CALLBACK(src, PROC_REF(prepare_elevator)), 1 MINUTE) // pseudo initialize. We give mapload some time before initializing rest of the properties
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply/proc/prepare_elevator()
|
||||
var/obj/dest_helper = locate(/obj/effect/landmark/destination_helper/cargo_elevator)
|
||||
target_dest_x = dest_helper.x
|
||||
target_dest_y = dest_helper.y
|
||||
target_dest_z = dest_helper.z
|
||||
horizon_elevator_area = get_area(dest_helper)
|
||||
|
||||
var/center_dest_x = target_dest_x + SHAFT_CENTER_OFFSET
|
||||
var/group_number
|
||||
for(var/obj/effect/step_trigger/cargo_elevator/ST in horizon_elevator_area) // sorts step triggers by their distance to the shaft center
|
||||
group_number = "distance_[abs(ST.x - center_dest_x)]"
|
||||
LAZYADDASSOCLIST(step_trigger_group, group_number, ST)
|
||||
|
||||
elevator_animation = new /obj/effect/elevator/animation_overlay()
|
||||
elevator_animation.pixel_x = ELEVATOR_DEPARTING_X // 7 tiles
|
||||
elevator_animation.pixel_y = ELEVATOR_DEPARTING_Y // 3 tiles
|
||||
|
||||
hatch_left = new /obj/effect/elevator/animation_overlay/hatch/left()
|
||||
hatch_right = new /obj/effect/elevator/animation_overlay/hatch/right()
|
||||
|
||||
// North-West corner
|
||||
NW = new /obj/effect/elevator(get_turf(src))
|
||||
NW.pixel_y = -192 // 6 tiles
|
||||
NW.vis_contents += elevator_animation
|
||||
NW.vis_contents += hatch_left
|
||||
NW.vis_contents += hatch_right
|
||||
|
||||
// North-East corner
|
||||
NE = new /obj/effect/elevator(get_turf(src))
|
||||
NE.pixel_x = -192
|
||||
NE.pixel_y = -192
|
||||
NE.vis_contents += elevator_animation
|
||||
NE.vis_contents += hatch_left
|
||||
NE.vis_contents += hatch_right
|
||||
|
||||
// We position the shaft beforehand
|
||||
NW.forceMove(locate(target_dest_x, target_dest_y, target_dest_z))
|
||||
NE.forceMove(locate(target_dest_x + SHAFT_WIDTH, target_dest_y, target_dest_z))
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply/short_jump(var/area/destination)
|
||||
if(moving_status != SHUTTLE_IDLE)
|
||||
@@ -26,9 +98,13 @@
|
||||
moving_status = SHUTTLE_IDLE
|
||||
return
|
||||
|
||||
if (!at_station()) //at centcom
|
||||
if (!at_station()) //at centcom
|
||||
if(!SScargo.buy()) //Check if the shuttle can be sent
|
||||
moving_status = SHUTTLE_IDLE //Dont move the shuttle
|
||||
return
|
||||
|
||||
flip_rotating_alarms() // elevator is coming up, prepare the lights
|
||||
playsound(locate(target_dest_x + SHAFT_CENTER_OFFSET, target_dest_y - SHAFT_CENTER_OFFSET, target_dest_z), 'sound/machines/warning-buzzer-2.ogg', 60, FALSE)
|
||||
|
||||
//We pretend it's a long_jump by making the shuttle stay at centcom for the "in-transit" period.
|
||||
var/obj/effect/shuttle_landmark/away_waypoint = get_location_waypoint(away_location)
|
||||
@@ -37,6 +113,7 @@
|
||||
//If we are at the away_landmark then we are just pretending to move, otherwise actually do the move
|
||||
if (next_location == away_waypoint)
|
||||
attempt_move(away_waypoint)
|
||||
play_elevator_animation(TRUE) // returning to CC, play the animation after elevator physically leaves
|
||||
|
||||
//wait ETA here.
|
||||
arrive_time = world.time + SScargo.movetime
|
||||
@@ -48,6 +125,7 @@
|
||||
if (prob(late_chance))
|
||||
sleep(rand(0,max_late_time))
|
||||
|
||||
play_elevator_animation() // coming from CC, play the animation before elevator physically arrives, delay the process
|
||||
attempt_move(destination)
|
||||
|
||||
moving_status = SHUTTLE_IDLE
|
||||
@@ -75,3 +153,162 @@
|
||||
/datum/shuttle/autodock/ferry/supply/proc/eta_minutes()
|
||||
var/ticksleft = arrive_time - world.time
|
||||
return round(ticksleft/600,1)
|
||||
|
||||
/**************************
|
||||
Elevator Animations
|
||||
***************************/
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply/proc/play_elevator_animation(returning_to_CC = FALSE)
|
||||
// Positioning the shafts
|
||||
NW.forceMove(locate(target_dest_x, target_dest_y, target_dest_z))
|
||||
NE.forceMove(locate(target_dest_x + SHAFT_WIDTH, target_dest_y, target_dest_z))
|
||||
|
||||
for(var/area/A in shuttle_area) // an image copy of the elevator platform is prepared here
|
||||
for(var/turf/T in A)
|
||||
elevator_animation.vis_contents += T
|
||||
|
||||
if(!returning_to_CC)
|
||||
handle_arrival_sequence() // coming to Horizon
|
||||
else
|
||||
handle_departure_sequence() // leaving the Horizon
|
||||
|
||||
elevator_animation.vis_contents.Cut() // animation is done, we can get rid of the elevator platform image
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply/proc/handle_arrival_sequence()
|
||||
var/obj/effect/step_trigger/cargo_elevator/trigger
|
||||
|
||||
playsound(locate(target_dest_x + SHAFT_CENTER_OFFSET, target_dest_y - SHAFT_CENTER_OFFSET, target_dest_z), 'sound/machines/industrial_lift_raising.ogg', 100, FALSE)
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(handle_step_triggers))
|
||||
animate(hatch_left, pixel_x = -112, time = 5 SECONDS)
|
||||
animate(hatch_right, pixel_x = 112, time = 5 SECONDS)
|
||||
sleep(4 SECONDS)
|
||||
|
||||
animate(elevator_animation, pixel_x = 0, pixel_y = 0, time = 4 SECONDS)
|
||||
sleep(4.2 SECONDS)
|
||||
|
||||
for(var/group_key in step_trigger_group)
|
||||
for(trigger in step_trigger_group[group_key])
|
||||
trigger.safe_to_walk = TRUE
|
||||
|
||||
// We move the shafts away to avoid layering issues with turfs
|
||||
NW.moveToNullspace()
|
||||
NE.moveToNullspace()
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(flip_rotating_alarms)), 4 SECONDS)
|
||||
addtimer(CALLBACK(src, PROC_REF(toggle_railings)), 2 SECONDS)
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply/proc/handle_departure_sequence()
|
||||
flip_rotating_alarms()
|
||||
toggle_railings()
|
||||
sleep(2 SECONDS)
|
||||
|
||||
// checking for standers is redundant here, since the elevator won't leave if a forbidden type is standing
|
||||
// we also want to avoid sending people to CC level in a case where we don't immediately retrieve them back after doing so
|
||||
playsound(locate(target_dest_x + SHAFT_CENTER_OFFSET, target_dest_y - SHAFT_CENTER_OFFSET, target_dest_z), 'sound/machines/industrial_lift_lowering.ogg', 100, FALSE)
|
||||
animate(elevator_animation, pixel_x = ELEVATOR_DEPARTING_X, pixel_y = ELEVATOR_DEPARTING_Y, time = 4 SECONDS)
|
||||
sleep(4.2 SECONDS)
|
||||
|
||||
animate(hatch_left, pixel_x = 0, time = 5 SECONDS)
|
||||
animate(hatch_right, pixel_x = 0, time = 5 SECONDS)
|
||||
addtimer(CALLBACK(src, PROC_REF(flip_rotating_alarms)), 9 SECOND)
|
||||
|
||||
/// This attempts to sync up with hatch animation, by activating groups of step triggers in delayed order.
|
||||
/datum/shuttle/autodock/ferry/supply/proc/handle_step_triggers()
|
||||
var/obj/effect/step_trigger/cargo_elevator/trigger
|
||||
var/group_key
|
||||
for(var/i in 0 to 3)
|
||||
group_key = "distance_[i]"
|
||||
for(trigger in step_trigger_group[group_key]) // checking for the things standing on top of the hatch, then we send them to falling
|
||||
for(var/atom/movable/AM in get_turf(trigger))
|
||||
if(istype(AM, /obj/effect)) // avoid picking up step_triggers
|
||||
continue
|
||||
trigger.handle_falling(AM)
|
||||
trigger.safe_to_walk = FALSE
|
||||
|
||||
sleep(1 SECOND)
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply/proc/flip_rotating_alarms()
|
||||
for(var/obj/machinery/rotating_alarm/RA in horizon_elevator_area)
|
||||
RA.toggle_state()
|
||||
|
||||
/datum/shuttle/autodock/ferry/supply/proc/toggle_railings()
|
||||
for(var/obj/structure/railing/retractable/R in horizon_elevator_area)
|
||||
R.toggle_state()
|
||||
|
||||
/obj/effect/landmark/destination_helper/cargo_elevator
|
||||
name = "cargo elevator destination helper"
|
||||
|
||||
/obj/effect/step_trigger/cargo_elevator
|
||||
name = "cargo elevator shaft"
|
||||
icon = 'icons/effects/map_effects.dmi'
|
||||
simulated = FALSE // this prevents the effects getting transported along with the elevator
|
||||
|
||||
/// List of turfs within the 'area/supply/dock'. Shared between all instances.
|
||||
var/static/list/possible_turfs_to_land_on = list()
|
||||
|
||||
/// Boolean, determines whether the movables should fall or not.
|
||||
var/safe_to_walk = TRUE
|
||||
|
||||
/obj/effect/step_trigger/cargo_elevator/Initialize()
|
||||
. = ..()
|
||||
if(!possible_turfs_to_land_on.len)
|
||||
possible_turfs_to_land_on = get_area_turfs(/area/supply/dock)
|
||||
|
||||
/obj/effect/step_trigger/cargo_elevator/Destroy()
|
||||
LAZYNULL(possible_turfs_to_land_on)
|
||||
return ..()
|
||||
|
||||
/obj/effect/step_trigger/cargo_elevator/Trigger(atom/movable/AM)
|
||||
if(safe_to_walk)
|
||||
return
|
||||
INVOKE_ASYNC(src, PROC_REF(handle_falling), AM)
|
||||
|
||||
/obj/effect/step_trigger/cargo_elevator/proc/handle_falling(atom/movable/AM)
|
||||
|
||||
if(!isliving(AM) && !isobj(AM)) // only mobs and objects
|
||||
return
|
||||
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(L.CanAvoidGravity())
|
||||
return
|
||||
L.apply_effect(2, WEAKEN)
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(animate_falling), AM) // this needs to run asynchronously, otherwise will cause issues
|
||||
|
||||
/obj/effect/step_trigger/cargo_elevator/proc/animate_falling(atom/movable/AM)
|
||||
sleep(0.1 SECOND) // allowing some time for mobs to get weaken effect applied
|
||||
var/oldalpha = AM.alpha
|
||||
var/oldcolor = AM.color
|
||||
var/old_pixel_y = AM.pixel_y
|
||||
animate(AM, transform = matrix() - matrix(), alpha = 0, color = rgb(0, 0, 0), time = 1 SECOND)
|
||||
|
||||
for(var/i in 1 to 5)
|
||||
//Make sure the item is still there after our sleep
|
||||
if(!AM || QDELETED(AM))
|
||||
return
|
||||
AM.pixel_y--
|
||||
sleep(0.2 SECONDS)
|
||||
|
||||
//Make sure the item is still there after our sleep
|
||||
if(!AM || QDELETED(AM))
|
||||
return
|
||||
|
||||
AM.visible_message(SPAN_WARNING("[AM] falls into [src]!"), SPAN_DANGER("You stumble and stare into \the [src] as you fall. It will be a long ride..."))
|
||||
AM.forceMove(pick(possible_turfs_to_land_on))
|
||||
|
||||
AM.alpha = oldalpha
|
||||
AM.color = oldcolor
|
||||
AM.transform = matrix()
|
||||
AM.pixel_y = old_pixel_y
|
||||
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
L.adjustBruteLoss(rand(30,50))
|
||||
L.dir = pick(GLOB.cardinals)
|
||||
|
||||
#undef SHAFT_WIDTH
|
||||
#undef SHAFT_CENTER_OFFSET
|
||||
#undef ELEVATOR_DEPARTING_X
|
||||
#undef ELEVATOR_DEPARTING_Y
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
author: Kano, KingOfThePing
|
||||
|
||||
delete-after: True
|
||||
|
||||
changes:
|
||||
- rscadd: "Added an elevator animation logic for cargo elevator, heavily inspired from CM."
|
||||
- rscadd: "Added hatch and shaft sprites for cargo elevator, made by KingOfThePing!"
|
||||
- rscadd: "Ported some sounds and sprites from CM."
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
+680
-478
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user