diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index cf913c540ed..4d3b74a4eea 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -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 diff --git a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm index ed1834a5b55..38e1b7f34fe 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm @@ -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() ..() diff --git a/code/game/objects/structures/crates_lockers/closets/walllocker.dm b/code/game/objects/structures/crates_lockers/closets/walllocker.dm index d9fed46e7bb..b6eb16d7d35 100644 --- a/code/game/objects/structures/crates_lockers/closets/walllocker.dm +++ b/code/game/objects/structures/crates_lockers/closets/walllocker.dm @@ -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 diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 92193b26356..06c2c5950e5 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -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" diff --git a/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm b/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm index cb0eabb6505..91357b9d86e 100644 --- a/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm +++ b/code/game/objects/structures/crates_lockers/crates/gear_loadout.dm @@ -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) diff --git a/html/changelogs/fluffyghost-updatefixcratesclosets.yml b/html/changelogs/fluffyghost-updatefixcratesclosets.yml new file mode 100644 index 00000000000..b8f00a2ec43 --- /dev/null +++ b/html/changelogs/fluffyghost-updatefixcratesclosets.yml @@ -0,0 +1,59 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# - (fixes bugs) +# wip +# - (work in progress) +# qol +# - (quality of life) +# soundadd +# - (adds a sound) +# sounddel +# - (removes a sound) +# rscadd +# - (adds a feature) +# rscdel +# - (removes a feature) +# imageadd +# - (adds an image or sprite) +# imagedel +# - (removes an image or sprite) +# spellcheck +# - (fixes spelling or grammar) +# experiment +# - (experimental change) +# balance +# - (balance changes) +# code_imp +# - (misc internal code change) +# refactor +# - (refactors code) +# config +# - (makes a change to the config files) +# admin +# - (makes changes to administrator tools) +# server +# - (miscellaneous changes to server) +################################# + +# Your name. +author: FluffyGhost + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit. +# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Fixed a runtime with crates animation when closing." + - refactor: "Updated closets door animation code, renamed one var to be more clear, some minor DMDoc, moved some procs around."