Fixed a runtime with crates animation when closing, update some procs (#19688)

Fixed a runtime with crates animation when closing.
Updated closets door animation code, renamed one var to be more clear,
some minor DMDoc, moved some procs around.
This commit is contained in:
Fluffy
2024-07-27 10:09:40 +00:00
committed by GitHub
parent e6d0e12d94
commit e55adbaf7d
6 changed files with 149 additions and 61 deletions
@@ -58,6 +58,7 @@
var/double_doors = FALSE
/// The overlay for the closet's door
var/obj/effect/overlay/closet_door/door_obj
var/obj/effect/overlay/closet_door/door_obj_alt
var/is_animating_door = FALSE
@@ -66,15 +67,26 @@
var/door_underlay = FALSE
/// Multiplier on proc/get_door_transform. basically, how far you want this to swing out. value of 1 means the length of the door is unchanged (and will swing out of the tile), 0 means it will just slide back and forth.
var/door_anim_squish = 0.12
var/door_anim_angle = 147
/// For closets, x away from the centre of the closet. typically good to add a 0.5 so it's centered on the edge of the closet.
var/door_hinge = -6.5
/// The maximum angle the door will be drawn at
var/door_anim_angle = 140
/// X position of the closet door hinge, relative to the center of the sprite
var/door_hinge_x = -6.5
/// For closets with two doors. why a seperate var? because some closets may be weirdly shaped or something.
var/door_hinge_alt = 6.5
/// Set to 0 to make the door not animate at all
var/door_anim_time = 2.5
/obj/structure/closet/Initialize(mapload, var/no_fill)
. = ..()
update_icon()
if(!no_fill)
fill()
if(secure)
verbs += /obj/structure/closet/proc/verb_togglelock
return mapload ? INITIALIZE_HINT_LATELOAD : INITIALIZE_HINT_NORMAL
/obj/structure/closet/LateInitialize()
if(opened) // if closed, any item at the crate's loc is put in the contents
return
@@ -92,17 +104,16 @@
if(content_size > storage_capacity-5)
storage_capacity = content_size + 5
/obj/structure/closet/Initialize(mapload, var/no_fill)
/obj/structure/closet/Destroy()
QDEL_NULL(linked_teleporter)
QDEL_NULL(door_obj)
QDEL_NULL(door_obj_alt)
. = ..()
update_icon()
if(!no_fill)
fill()
if(secure)
verbs += /obj/structure/closet/proc/verb_togglelock
return mapload ? INITIALIZE_HINT_LATELOAD : INITIALIZE_HINT_NORMAL
/// Fill lockers with this.
/obj/structure/closet/proc/fill()
return
/obj/structure/closet/proc/content_info(mob/user, content_size)
if(!content_size)
@@ -491,9 +502,15 @@
// helper procs for callbacks
/obj/structure/closet/proc/is_closed()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
. = !opened
/obj/structure/closet/proc/is_open()
SHOULD_NOT_SLEEP(TRUE)
SHOULD_BE_PURE(TRUE)
. = opened
/obj/structure/closet/MouseDrop_T(atom/dropping, mob/user)
@@ -600,33 +617,43 @@
/obj/structure/closet/proc/animate_door(var/closing = FALSE)
if(!door_anim_time)
return
if(!door_obj) door_obj = new
vis_contents |= door_obj
if(!door_obj)
door_obj = new
var/default_door_icon = "[icon_door || icon_state]_door"
vis_contents += door_obj
door_obj.icon = icon
door_obj.icon_state = "[icon_door || icon_state]_door"
door_obj.icon_state = default_door_icon
is_animating_door = TRUE
var/num_steps = door_anim_time / world.tick_lag
for(var/I in 0 to num_steps)
var/angle = door_anim_angle * (closing ? 1 - (I/num_steps) : (I/num_steps))
var/matrix/M = get_door_transform(angle)
var/door_state = angle >= 90 ? "[icon_door_override ? icon_door : icon_state]_back" : "[icon_door || icon_state]_door"
var/door_layer = angle >= 90 ? FLOAT_LAYER : ABOVE_HUMAN_LAYER
if(I == 0)
door_obj.transform = M
for(var/step in 0 to num_steps)
var/angle = door_anim_angle * (closing ? 1 - (step/num_steps) : (step/num_steps))
var/matrix/door_transform = get_door_transform(angle)
var/door_state
var/door_layer
if (angle >= 90)
door_state = "[icon_state]_back"
door_layer = FLOAT_LAYER
else
door_state = default_door_icon
door_layer = ABOVE_HUMAN_LAYER
if(step == 0)
door_obj.transform = door_transform
door_obj.icon_state = door_state
door_obj.layer = door_layer
else if(I == 1)
animate(door_obj, transform = M, icon_state = door_state, layer = door_layer, time = world.tick_lag, flags = ANIMATION_END_NOW)
else if(step == 1)
animate(door_obj, transform = door_transform, icon_state = door_state, layer = door_layer, time = world.tick_lag, flags = ANIMATION_END_NOW)
else
animate(transform = M, icon_state = door_state, layer = door_layer, time = world.tick_lag)
addtimer(CALLBACK(src, PROC_REF(end_door_animation)),door_anim_time,TIMER_UNIQUE|TIMER_OVERRIDE)
animate(transform = door_transform, icon_state = door_state, layer = door_layer, time = world.tick_lag)
addtimer(CALLBACK(src, PROC_REF(end_door_animation)), door_anim_time, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_CLIENT_TIME)
/obj/structure/closet/proc/end_door_animation()
is_animating_door = FALSE // comment this out and the line below to manually tweak the animation end state by fiddling with the door_anim vars to match the open door icon
remove_vis_contents(door_obj)
is_animating_door = FALSE
vis_contents -= door_obj
update_icon()
UpdateOverlays(src)
/obj/structure/closet/proc/animate_door_alt(var/closing = FALSE)
if(!door_anim_time)
@@ -659,13 +686,12 @@
update_icon()
UpdateOverlays(src)
/obj/structure/closet/proc/get_door_transform(angle, var/inverse_hinge = FALSE)
var/matrix/M = matrix()
var/matrix_door_hinge = inverse_hinge ? door_hinge_alt : door_hinge
M.Translate(-matrix_door_hinge, 0)
M.Multiply(matrix(cos(angle), 0, 0, ((matrix_door_hinge >= 0) ? sin(angle) : -sin(angle)) * door_anim_squish, 1, 0)) // this matrix door hinge >= 0 check is for door hinges on the right, so they swing out instead of upwards
M.Translate(matrix_door_hinge, 0)
return M
/obj/structure/closet/proc/get_door_transform(angle)
var/matrix/door_matrix = matrix()
door_matrix.Translate(-door_hinge_x, 0)
door_matrix.Multiply(matrix(cos(angle), 0, 0, -sin(angle) * door_anim_squish, 1, 0))
door_matrix.Translate(door_hinge_x, 0)
return door_matrix
/obj/structure/closet/hear_talk(mob/M as mob, text, verb, datum/language/speaking)
for (var/atom/A in src)
@@ -776,11 +802,6 @@
new /obj/item/stack/material/steel(get_turf(src))
qdel(src)
/obj/structure/closet/Destroy()
if(linked_teleporter)
QDEL_NULL(linked_teleporter)
return ..()
/obj/structure/closet/stair_act()
if(opened || !can_open())
return
@@ -9,7 +9,7 @@
door_underlay = TRUE
door_anim_squish = 0.12
door_anim_angle = 119
door_hinge = -9.5
door_hinge_x = -9.5
/obj/structure/closet/secure_closet/guncabinet/Initialize()
..()
@@ -8,7 +8,7 @@
icon_state = "walllocker" //...man, how OLD is this $#!?
door_anim_angle = 132
door_anim_squish = 0.38
door_hinge = -7
door_hinge_x = -7
door_anim_time = 2.7
store_mobs = FALSE
density = FALSE
@@ -19,7 +19,7 @@
door_anim_squish = 0.30
door_anim_time = 3
door_anim_angle = 140
door_hinge = 3.5
door_hinge_x = 3.5
pass_flags_self = PASSSTRUCTURE | LETPASSTHROW
var/tablestatus = 0
@@ -42,18 +42,25 @@
if(!door_obj) door_obj = new
if(animation_math == null) //checks if there is already a list for animation_math if not creates one to avoid runtimes
animation_math = new/list()
if(!door_anim_time == 0 && !animation_math["[door_anim_time]-[door_anim_angle]-[azimuth_angle_2]-[radius_2]-[door_hinge]"])
if(!door_anim_time == 0 && !animation_math["[door_anim_time]-[door_anim_angle]-[azimuth_angle_2]-[radius_2]-[door_hinge_x]"])
animation_list()
vis_contents |= door_obj
door_obj.icon = icon
door_obj.icon_state = "[icon_door || icon_state]_door"
is_animating_door = TRUE
var/num_steps = door_anim_time / world.tick_lag
var/list/animation_math_list = animation_math["[door_anim_time]-[door_anim_angle]-[azimuth_angle_2]-[radius_2]-[door_hinge]"]
var/num_steps = round(door_anim_time / world.tick_lag)
var/list/animation_math_list = animation_math["[door_anim_time]-[door_anim_angle]-[azimuth_angle_2]-[radius_2]-[door_hinge_x]"]
for(var/I in 0 to num_steps)
var/door_state = I == (closing ? num_steps : 0) ? "[icon_door || icon_state]_door" : animation_math_list[closing ? 2 * num_steps - I : num_steps + I] <= 0 ? "[icon_door_override ? icon_door : icon_state]_back" : "[icon_door || icon_state]_door"
var/door_layer = I == (closing ? num_steps : 0) ? ABOVE_HUMAN_LAYER : animation_math_list[closing ? 2 * num_steps - I : num_steps + I] <= 0 ? FLOAT_LAYER : ABOVE_HUMAN_LAYER
var/matrix/M = get_door_transform(I == (closing ? num_steps : 0) ? 0 : animation_math_list[closing ? num_steps - I : I], I == (closing ? num_steps : 0) ? 1 : animation_math_list[closing ? 2 * num_steps - I : num_steps + I])
var/crateanim_1 = 0
var/crateanim_2 = 1
if(!(I == (closing ? num_steps : 0)))
crateanim_1 = animation_math_list[closing ? num_steps - I : I]
crateanim_2 = animation_math_list[closing ? 2 * num_steps - I : num_steps + I]
var/matrix/M = get_door_transform(crateanim_1, crateanim_2)
if(I == 0)
door_obj.transform = M
door_obj.icon_state = door_state
@@ -62,13 +69,14 @@
animate(door_obj, transform = M, icon_state = door_state, layer = door_layer, time = world.tick_lag, flags = ANIMATION_END_NOW)
else
animate(transform = M, icon_state = door_state, layer = door_layer, time = world.tick_lag)
addtimer(CALLBACK(src, PROC_REF(end_door_animation)),door_anim_time,TIMER_UNIQUE|TIMER_OVERRIDE)
addtimer(CALLBACK(src, PROC_REF(end_door_animation)), door_anim_time, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_CLIENT_TIME)
/obj/structure/closet/crate/get_door_transform(crateanim_1, crateanim_2)
var/matrix/M = matrix()
M.Translate(0, -door_hinge)
M.Translate(0, -door_hinge_x)
M.Multiply(matrix(1, crateanim_1, 0, 0, crateanim_2, 0))
M.Translate(0, door_hinge)
M.Translate(0, door_hinge_x)
return M
/obj/structure/closet/crate/proc/animation_list() //pre calculates a list of values for the crate animation cause byond not like math
@@ -81,7 +89,7 @@
var/radius_cr = angle_1 >= 90 ? radius_2 : 1
new_animation_math_sublist[I] = -sin(polar_angle) * sin(azimuth_angle) * radius_cr
new_animation_math_sublist[num_steps_1 + I] = cos(azimuth_angle) * sin(polar_angle) * radius_cr
animation_math["[door_anim_time]-[door_anim_angle]-[azimuth_angle_2]-[radius_2]-[door_hinge]"] = new_animation_math_sublist
animation_math["[door_anim_time]-[door_anim_angle]-[azimuth_angle_2]-[radius_2]-[door_hinge_x]"] = new_animation_math_sublist
/*
==========================
@@ -220,7 +228,7 @@
door_anim_angle = 140
azimuth_angle_2 = 180
door_anim_time = 5
door_hinge = 5
door_hinge_x = 5
/obj/structure/closet/crate/internals
name = "internals crate"
@@ -231,13 +239,13 @@
name = "trash cart"
desc = "A heavy, metal trashcart with wheels."
icon_state = "trashcart"
door_hinge = 2.5
door_hinge_x = 2.5
/obj/structure/closet/crate/miningcart
desc = "A mining cart. This one doesn't work on rails, but has to be dragged."
name = "mining cart"
icon_state = "miningcart"
door_hinge = 2.5
door_hinge_x = 2.5
/obj/structure/closet/crate/miningcart/ore/fill()
var/i_max = rand(3, 6)
@@ -332,7 +340,7 @@
name = "freezer"
desc = "A freezer."
icon_state = "freezer"
door_hinge = 4.5
door_hinge_x = 4.5
var/target_temp = T0C - 40
var/cooling_power = 40
@@ -385,13 +393,13 @@
name = "drop crate"
desc = "A large, sturdy crate meant for airdrops."
icon_state = "drop_crate"
door_hinge = 0.5
door_hinge_x = 0.5
/obj/structure/closet/crate/drop/grey
name = "drop crate"
desc = "A large, sturdy crate meant for airdrops."
icon_state = "drop_crate-grey"
door_hinge = 0.5
door_hinge_x = 0.5
/obj/structure/closet/crate/tool
name = "tool crate"
@@ -11,31 +11,31 @@
desc = "A sturdy crate with Hephaestus Industries branding."
name = "hephaestus drop crate"
icon_state = "heph_crate"
door_hinge = 0.5
door_hinge_x = 0.5
/obj/structure/closet/crate/gear_loadout/zenghu
desc = "A sturdy crate with Zeng-Hu Pharmaceuticals branding."
name = "zeng-hu drop crate"
icon_state = "zenghu_crate"
door_hinge = 0.5
door_hinge_x = 0.5
/obj/structure/closet/crate/gear_loadout/nanotrasen
desc = "A sturdy crate with NanoTrasen Corporation branding."
name = "nanotrasen drop crate"
icon_state = "nanotrasen_crate"
door_hinge = 0.5
door_hinge_x = 0.5
/obj/structure/closet/crate/gear_loadout/einstein
desc = "A sturdy crate with Einstein Engines branding."
name = "einstein drop crate"
icon_state = "einstein_crate"
door_hinge = 0.5
door_hinge_x = 0.5
/obj/structure/closet/crate/gear_loadout/zavodskoi
desc = "A sturdy crate with Zavodskoi Interstellar branding."
name = "zavodskoi interstellar drop crate"
icon_state = "necro_crate"
door_hinge = 0.5
door_hinge_x = 0.5
/obj/structure/closet/crate/secure/gear_loadout/coalition/fill()
new /obj/item/rig/gunslinger/equipped(src)