Skip to content

Commit

Permalink
Variable Door Delay + Timer Based Animations (tgstation#84631)
Browse files Browse the repository at this point in the history
## About The Pull Request

### Variable Door Delay

Door opening/closing delay times are currently static, but many doors do
not have animations that FIT the actual timings.

It would be better if subtypes cound declare how long each animation
takes, and how long it takes for opening to say, become passable and
such.

Let's do that.

### Timer Based Animations

Currently all doors use flick() to do their animations. This is fine
right NOW, but fucks with walleniong because we have to split most
things into segments to make layering work.

So rather then flick let's use client timers and update_icon_state to
achive our effects, alongside a proc that lets us do other effects (like
sound) on playing an animation

## Why It's Good For The Game

Door behavior and visuals better match up, wallening compatability
upstreaming.

## Changelog
:cl:
add: Most door animations now better line up with when they are/are not
passable.
/:cl:

---------

Co-authored-by: MrMelbert <[email protected]>
  • Loading branch information
LemonInTheDark and MrMelbert authored Jul 8, 2024
1 parent 274c54f commit 9bc534f
Show file tree
Hide file tree
Showing 22 changed files with 323 additions and 78 deletions.
18 changes: 18 additions & 0 deletions code/__DEFINES/door.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Door animation defines
#define DOOR_OPENING_ANIMATION "opening"
#define DOOR_CLOSING_ANIMATION "closing"
#define DOOR_DENY_ANIMATION "deny"

// Door animation STEP defines
// These are used to mark points in the animtion when things in game should change
#define DOOR_OPENING_PASSABLE "opening_passable"
#define DOOR_OPENING_FINISHED "opening_finished"
#define DOOR_CLOSING_UNPASSABLE "closing_unpassable"
#define DOOR_CLOSING_FINISHED "closing_finished"

#define AIRLOCK_OPENING_TRANSPARENT "airlock_opening_transparent"
#define AIRLOCK_OPENING_PASSABLE "airlock_opening_passable"
#define AIRLOCK_OPENING_FINISHED "airlock_opening_finished"
#define AIRLOCK_CLOSING_OPAQUE "airlock_closing_opaque"
#define AIRLOCK_CLOSING_UNPASSABLE "airlock_closing_unpassable"
#define AIRLOCK_CLOSING_FINISHED "airlock_closing_finished"
2 changes: 1 addition & 1 deletion code/datums/wires/airlock.dm
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
A.update_appearance()
if(WIRE_IDSCAN) // Pulse to disable emergency access and flash the red lights.
if(A.hasPower() && A.density)
A.do_animate("deny")
A.run_animation(DOOR_DENY_ANIMATION)
if(A.emergency)
A.emergency = FALSE
A.update_appearance()
Expand Down
48 changes: 38 additions & 10 deletions code/game/machinery/doors/airlock.dm
Original file line number Diff line number Diff line change
Expand Up @@ -591,13 +591,13 @@
floorlight.pixel_y = 0
. += floorlight

/obj/machinery/door/airlock/do_animate(animation)
/obj/machinery/door/airlock/run_animation(animation)
switch(animation)
if("opening")
if(DOOR_OPENING_ANIMATION)
update_icon(ALL, AIRLOCK_OPENING)
if("closing")
if(DOOR_OPENING_ANIMATION)
update_icon(ALL, AIRLOCK_CLOSING)
if("deny")
if(DOOR_DENY_ANIMATION)
if(!machine_stat)
update_icon(ALL, AIRLOCK_DENY)
playsound(src,doorDeni,50,FALSE,3)
Expand All @@ -607,6 +607,28 @@
if(airlock_state == AIRLOCK_DENY)
update_icon(ALL, AIRLOCK_CLOSED)

/obj/machinery/door/airlock/animation_length(animation)
switch(animation)
if(DOOR_OPENING_ANIMATION)
return 0.6 SECONDS
if(DOOR_CLOSING_ANIMATION)
return 0.6 SECONDS

/obj/machinery/door/airlock/animation_segment_delay(animation)
switch(animation)
if(AIRLOCK_OPENING_TRANSPARENT)
return 0.1 SECONDS
if(AIRLOCK_OPENING_PASSABLE)
return 0.5 SECONDS
if(AIRLOCK_OPENING_FINISHED)
return 0.6 SECONDS
if(AIRLOCK_CLOSING_UNPASSABLE)
return 0.2 SECONDS
if(AIRLOCK_CLOSING_OPAQUE)
return 0.5 SECONDS
if(AIRLOCK_CLOSING_FINISHED)
return 0.6 SECONDS

/obj/machinery/door/airlock/examine(mob/user)
. = ..()
if(closeOtherId)
Expand Down Expand Up @@ -1234,18 +1256,21 @@
SEND_SIGNAL(src, COMSIG_AIRLOCK_OPEN, forced)
operating = TRUE
update_icon(ALL, AIRLOCK_OPENING, TRUE)
sleep(0.1 SECONDS)
var/transparent_delay = animation_segment_delay(AIRLOCK_OPENING_TRANSPARENT)
sleep(transparent_delay)
set_opacity(0)
if(multi_tile)
filler.set_opacity(FALSE)
update_freelook_sight()
sleep(0.4 SECONDS)
var/passable_delay = animation_segment_delay(AIRLOCK_OPENING_PASSABLE) - transparent_delay
sleep(passable_delay)
set_density(FALSE)
if(multi_tile)
filler.set_density(FALSE)
flags_1 &= ~PREVENT_CLICK_UNDER_1
air_update_turf(TRUE, FALSE)
sleep(0.1 SECONDS)
var/open_delay = animation_segment_delay(AIRLOCK_OPENING_FINISHED) - transparent_delay - passable_delay
sleep(open_delay)
layer = OPEN_DOOR_LAYER
update_icon(ALL, AIRLOCK_OPEN, TRUE)
operating = FALSE
Expand Down Expand Up @@ -1314,22 +1339,25 @@
filler.density = TRUE
flags_1 |= PREVENT_CLICK_UNDER_1
air_update_turf(TRUE, TRUE)
sleep(0.1 SECONDS)
var/unpassable_delay = animation_segment_delay(AIRLOCK_CLOSING_UNPASSABLE)
sleep(unpassable_delay)
if(!air_tight)
set_density(TRUE)
if(multi_tile)
filler.density = TRUE
flags_1 |= PREVENT_CLICK_UNDER_1
air_update_turf(TRUE, TRUE)
sleep(0.4 SECONDS)
var/opaque_delay = animation_segment_delay(AIRLOCK_CLOSING_OPAQUE) - unpassable_delay
sleep(opaque_delay)
if(dangerous_close)
crush()
if(visible && !glass)
set_opacity(TRUE)
if(multi_tile)
filler.set_opacity(TRUE)
update_freelook_sight()
sleep(0.1 SECONDS)
var/close_delay = animation_segment_delay(AIRLOCK_CLOSING_FINISHED) - unpassable_delay - opaque_delay
sleep(close_delay)
update_icon(ALL, AIRLOCK_CLOSED, 1)
operating = FALSE
delayed_close_requested = FALSE
Expand Down
113 changes: 91 additions & 22 deletions code/game/machinery/doors/door.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
name = "door"
desc = "It opens and closes."
icon = 'icons/obj/doors/doorint.dmi'
icon_state = "door1"
icon_state = "door_closed"
base_icon_state = "door"
opacity = TRUE
density = TRUE
Expand All @@ -24,6 +24,8 @@
idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.1
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.2

/// The animation we're currently playing, if any
var/animation
var/visible = TRUE
var/operating = FALSE
var/glass = FALSE
Expand Down Expand Up @@ -252,7 +254,7 @@
if(requiresID() && check_access(I))
open()
else
do_animate("deny")
run_animation(DOOR_DENY_ANIMATION)
return

/obj/machinery/door/Move()
Expand Down Expand Up @@ -282,7 +284,7 @@
else if(requiresID() && allowed(user))
open()
else
do_animate("deny")
run_animation(DOOR_DENY_ANIMATION)

/obj/machinery/door/attack_hand(mob/user, list/modifiers)
. = ..()
Expand Down Expand Up @@ -310,7 +312,7 @@
close()
return TRUE
if(density)
do_animate("deny")
run_animation(DOOR_DENY_ANIMATION)

/obj/machinery/door/allowed(mob/M)
if(emergency)
Expand Down Expand Up @@ -405,24 +407,67 @@
INVOKE_ASYNC(src, PROC_REF(open))

/obj/machinery/door/update_icon_state()
icon_state = "[base_icon_state][density]"
return ..()

/obj/machinery/door/proc/do_animate(animation)
. = ..()
switch(animation)
if("opening")
if(DOOR_OPENING_ANIMATION)
if(panel_open)
flick("o_doorc0", src)
icon_state = "o_door_opening"
else
flick("doorc0", src)
if("closing")
icon_state = "door_opening"
if(DOOR_CLOSING_ANIMATION)
if(panel_open)
flick("o_doorc1", src)
icon_state = "o_door_closing"
else
flick("doorc1", src)
if("deny")
icon_state = "door_closing"
if(DOOR_DENY_ANIMATION)
if(!machine_stat)
flick("door_deny", src)
icon_state = "door_deny"
else
icon_state = "[base_icon_state]_[density ? "closed" : "open"]"

/obj/machinery/door/update_overlays()
. = ..()
if(panel_open)
. += mutable_appearance(icon, "panel_open")

/// Returns the delay to use for the passed in animation
/// We'll do our cleanup once the delay runs out
/obj/machinery/door/proc/animation_length(animation)
switch(animation)
if(DOOR_OPENING_ANIMATION)
return 0.6 SECONDS
if(DOOR_CLOSING_ANIMATION)
return 0.6 SECONDS
if(DOOR_DENY_ANIMATION)
return 0.3 SECONDS

/// Returns the time required to hit particular points in an animation
/// Used to manage delays for opening/closing and such
/obj/machinery/door/proc/animation_segment_delay(animation)
switch(animation)
if(DOOR_OPENING_PASSABLE)
return 0.5 SECONDS
if(DOOR_OPENING_FINISHED)
return 0.6 SECONDS
if(DOOR_CLOSING_UNPASSABLE)
return 0.2 SECONDS
if(DOOR_CLOSING_FINISHED)
return 0.6 SECONDS

/// Override this to do misc tasks on animation start
/obj/machinery/door/proc/animation_effects(animation)
return

/// Used to start a new animation
/// Accepts the animation to start as an arg
/obj/machinery/door/proc/run_animation(animation)
set_animation(animation)
addtimer(CALLBACK(src, PROC_REF(set_animation), null), animation_length(animation), TIMER_UNIQUE|TIMER_OVERRIDE)

// React to our animation changing
/obj/machinery/door/proc/set_animation(animation)
src.animation = animation
update_appearance()

/// Public proc that simply handles opening the door. Returns TRUE if the door was opened, FALSE otherwise.
/// Use argument "forced" in conjunction with try_to_force_door_open if you want/need additional checks depending on how sorely you need the door opened.
Expand All @@ -433,12 +478,14 @@
return FALSE
operating = TRUE
use_energy(active_power_usage)
do_animate("opening")
run_animation(DOOR_OPENING_ANIMATION)
set_opacity(0)
SLEEP_NOT_DEL(0.5 SECONDS)
var/passable_delay = animation_segment_delay(DOOR_OPENING_PASSABLE)
SLEEP_NOT_DEL(passable_delay)
set_density(FALSE)
flags_1 &= ~PREVENT_CLICK_UNDER_1
SLEEP_NOT_DEL(0.5 SECONDS)
var/open_delay = animation_segment_delay(DOOR_OPENING_FINISHED) - passable_delay
SLEEP_NOT_DEL(open_delay)
layer = initial(layer)
update_appearance()
set_opacity(0)
Expand Down Expand Up @@ -470,12 +517,14 @@

operating = TRUE

do_animate("closing")
run_animation(DOOR_CLOSING_ANIMATION)
layer = closingLayer
SLEEP_NOT_DEL(0.5 SECONDS)
var/unpassable_delay = animation_segment_delay(DOOR_CLOSING_UNPASSABLE)
SLEEP_NOT_DEL(unpassable_delay)
set_density(TRUE)
flags_1 |= PREVENT_CLICK_UNDER_1
SLEEP_NOT_DEL(0.5 SECONDS)
var/close_delay = animation_segment_delay(DOOR_CLOSING_FINISHED) - unpassable_delay
SLEEP_NOT_DEL(close_delay)
update_appearance()
if(visible && !glass)
set_opacity(1)
Expand Down Expand Up @@ -556,6 +605,26 @@
/obj/machinery/door/get_dumping_location()
return null

/obj/machinery/door/morgue/animation_length(animation)
switch(animation)
if(DOOR_OPENING_ANIMATION)
return 1.5 SECONDS
if(DOOR_CLOSING_ANIMATION)
return 1.5 SECONDS
if(DOOR_DENY_ANIMATION)
return 0.1 SECONDS

/obj/machinery/door/morgue/animation_segment_delay(animation)
switch(animation)
if(DOOR_OPENING_PASSABLE)
return 1.4 SECONDS
if(DOOR_OPENING_FINISHED)
return 1.5 SECONDS
if(DOOR_CLOSING_UNPASSABLE)
return 0.2 SECONDS
if(DOOR_CLOSING_FINISHED)
return 1.5 SECONDS

/obj/machinery/door/proc/lock()
return

Expand Down
37 changes: 29 additions & 8 deletions code/game/machinery/doors/firedoor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -609,16 +609,37 @@
if(active)
addtimer(CALLBACK(src, PROC_REF(correct_state)), 2 SECONDS, TIMER_UNIQUE)

/obj/machinery/door/firedoor/do_animate(animation)
switch(animation)
if("opening")
flick("[base_icon_state]_opening", src)
if("closing")
flick("[base_icon_state]_closing", src)

/obj/machinery/door/firedoor/update_icon_state()
. = ..()
icon_state = "[base_icon_state]_[density ? "closed" : "open"]"
switch(animation)
if(DOOR_OPENING_ANIMATION)
icon_state = "[base_icon_state]_opening"
if(DOOR_CLOSING_ANIMATION)
icon_state = "[base_icon_state]_closing"
if(DOOR_DENY_ANIMATION)
icon_state = "[base_icon_state]_deny"
else
icon_state = "[base_icon_state]_[density ? "closed" : "open"]"

/obj/machinery/door/firedoor/animation_length(animation)
switch(animation)
if(DOOR_OPENING_ANIMATION)
return 1.2 SECONDS
if(DOOR_CLOSING_ANIMATION)
return 1.2 SECONDS
if(DOOR_DENY_ANIMATION)
return 0.3 SECONDS

/obj/machinery/door/firedoor/animation_segment_delay(animation)
switch(animation)
if(DOOR_OPENING_PASSABLE)
return 1.0 SECONDS
if(DOOR_OPENING_FINISHED)
return 1.2 SECONDS
if(DOOR_CLOSING_UNPASSABLE)
return 0.2 SECONDS
if(DOOR_CLOSING_FINISHED)
return 1.2 SECONDS

/obj/machinery/door/firedoor/update_overlays()
. = ..()
Expand Down
Loading

0 comments on commit 9bc534f

Please sign in to comment.