diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index c07f783e9e..9669004bca 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -182,3 +182,10 @@ stack_trace("Directional light cone deleted, but not by our component") return QDEL_HINT_LETMELIVE return ..() + +/obj/effect/overlay/closet_door + anchored = TRUE + plane = FLOAT_PLANE + layer = FLOAT_LAYER + vis_flags = VIS_INHERIT_ID + appearance_flags = KEEP_TOGETHER | LONG_GLIDE | PIXEL_SCALE diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index b27ebc27c5..048d089fed 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -26,6 +26,7 @@ closet_appearance = null open_sound = 'sound/items/zip.ogg' close_sound = 'sound/items/zip.ogg' + door_anim_time = 0 //Unsupported var/item_path = /obj/item/bodybag density = FALSE storage_capacity = (MOB_MEDIUM * 2) - 1 diff --git a/code/game/objects/items/poi_items.dm b/code/game/objects/items/poi_items.dm index 2c05f0cfca..8e65ac005b 100644 --- a/code/game/objects/items/poi_items.dm +++ b/code/game/objects/items/poi_items.dm @@ -65,6 +65,7 @@ closet_appearance = null catalogue_data = list(/datum/category_item/catalogue/information/objects/oldreactor) climbable = FALSE + door_anim_time = 0 //Unsupported starts_with = list( /obj/item/weapon/fuel_assembly/deuterium = 6) diff --git a/code/game/objects/structures/crates_lockers/__closets.dm b/code/game/objects/structures/crates_lockers/__closets.dm index fb27ea6977..7a91c6ad8f 100644 --- a/code/game/objects/structures/crates_lockers/__closets.dm +++ b/code/game/objects/structures/crates_lockers/__closets.dm @@ -36,6 +36,19 @@ var/closet_appearance = /decl/closet_appearance // The /decl that defines what decals we end up with, that makes our look unique + /// Currently animating the door transform + var/is_animating_door = FALSE + /// Length of time (ds) to animate the door transform + var/door_anim_time = 2.0 + /// Amount to 'squish' the full width of the door by + var/door_anim_squish = 0.30 + /// Virtual angle at which the door is opened to (136 by default, so not a full 180) + var/door_anim_angle = 136 + /// Offset for the door hinge location from centerline + var/door_hinge = -6.5 + /// Our visual object for the closet door + var/obj/effect/overlay/closet_door/door_obj + /obj/structure/closet/Initialize() ..() return INITIALIZE_HINT_LATELOAD @@ -66,6 +79,10 @@ color = null update_icon() +/obj/structure/closet/Destroy() + . = ..() + qdel_null(door_obj) + /obj/structure/closet/examine(mob/user) . = ..() if(Adjacent(user) || isobserver(user)) @@ -134,7 +151,7 @@ playsound(src, open_sound, 15, 1, -3) if(initial(density)) density = !density - update_icon() + animate_door() return 1 /obj/structure/closet/proc/close() @@ -159,7 +176,7 @@ playsound(src, close_sound, 15, 1, -3) if(initial(density)) density = !density - update_icon() + animate_door(TRUE) return 1 //Cham Projector Exception @@ -214,10 +231,11 @@ /obj/structure/closet/proc/toggle(mob/user as mob) + if(is_animating_door) + return if(!(opened ? close() : open())) to_chat(user, "It won't budge!") return - update_icon() // this should probably use dump_contents() /obj/structure/closet/ex_act(severity) @@ -481,8 +499,45 @@ spawn(1) qdel(src) return 1 -// Just a generic cabinet for mappers to use -/obj/structure/closet/cabinet - name = "cabinet" - icon = 'icons/obj/closets/bases/cabinet.dmi' - closet_appearance = /decl/closet_appearance/cabinet +/obj/structure/closet/proc/animate_door(closing = FALSE) + if(!door_anim_time) + update_icon() + return + if(!door_obj) + door_obj = new + vis_contents |= door_obj + door_obj.icon = icon + door_obj.icon_state = "door_front" + is_animating_door = TRUE + if(!closing) + update_icon() + 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 ? "door_back" : "door_front" + var/door_layer = angle >= 90 ? FLOAT_LAYER : ABOVE_MOB_LAYER + + if(I == 0) + door_obj.transform = M + 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 + animate(transform = M, icon_state = door_state, layer = door_layer, time = world.tick_lag) + addtimer(CALLBACK(src,.proc/end_door_animation,closing),door_anim_time,TIMER_UNIQUE|TIMER_OVERRIDE) + +/obj/structure/closet/proc/end_door_animation(closing = FALSE) + is_animating_door = FALSE + if(closing) + // There's not really harm in leaving it on, but, one less atom to send to clients to render when lockers are closed + vis_contents -= door_obj + update_icon() + +/obj/structure/closet/proc/get_door_transform(angle) + var/matrix/M = matrix() + M.Translate(-door_hinge, 0) + M.Multiply(matrix(cos(angle), 0, 0, -sin(angle) * door_anim_squish, 1, 0)) + M.Translate(door_hinge, 0) + return M diff --git a/code/game/objects/structures/crates_lockers/_closets_appearance_definitions.dm b/code/game/objects/structures/crates_lockers/_closets_appearance_definitions.dm index 9075c87272..eb1ab2d780 100644 --- a/code/game/objects/structures/crates_lockers/_closets_appearance_definitions.dm +++ b/code/game/objects/structures/crates_lockers/_closets_appearance_definitions.dm @@ -33,6 +33,8 @@ var/icon/closed_locked_welded_icon var/icon/closed_unlocked_icon var/icon/closed_unlocked_welded_icon + var/icon/door_front_icon + var/icon/door_back_icon // Create open icon. var/icon/new_icon = new @@ -40,6 +42,10 @@ open_icon.Blend(icon(base_icon, "open"), ICON_OVERLAY) open_icon.Blend(color, BLEND_ADD) open_icon.Blend(icon(base_icon, "interior"), ICON_OVERLAY) + + door_back_icon = icon(base_icon, "door_back") + door_back_icon.Blend(color, BLEND_ADD) + if(decal_icon) for(var/thing in decals) var/icon/this_decal_icon = icon(decal_icon, "[thing]_open") @@ -47,6 +53,8 @@ open_icon.Blend(this_decal_icon, ICON_OVERLAY) // Generate basic closed icons. + door_front_icon = icon(base_icon, "door_front") + door_front_icon.Blend(color, BLEND_ADD) closed_emagged_icon = icon(base_icon, "base") if(can_lock) closed_emagged_icon.Blend(icon(base_icon, "lock"), ICON_OVERLAY) @@ -56,6 +64,10 @@ var/icon/this_decal_icon = icon(decal_icon, thing) this_decal_icon.Blend(decals[thing], BLEND_ADD) closed_emagged_icon.Blend(this_decal_icon, ICON_OVERLAY) + door_front_icon.Blend(this_decal_icon, ICON_OVERLAY) + + door_front_icon.AddAlphaMask(icon(base_icon, "door_front")) // Remove pesky 'more than just door' decals + closed_locked_icon = icon(closed_emagged_icon) closed_unlocked_icon = icon(closed_emagged_icon) @@ -83,13 +95,15 @@ closed_emagged_welded_icon.Blend(sparks, ICON_OVERLAY) // Insert our bevy of icons into the final icon file. - new_icon.Insert(open_icon, "open") - new_icon.Insert(closed_emagged_icon, "closed_emagged") - new_icon.Insert(closed_emagged_welded_icon, "closed_emagged_welded") - new_icon.Insert(closed_locked_icon, "closed_locked") - new_icon.Insert(closed_locked_welded_icon, "closed_locked_welded") - new_icon.Insert(closed_unlocked_icon, "closed_unlocked") - new_icon.Insert(closed_unlocked_welded_icon, "closed_unlocked_welded") + new_icon.Insert(open_icon, "open") + new_icon.Insert(closed_emagged_icon, "closed_emagged") + new_icon.Insert(closed_emagged_welded_icon, "closed_emagged_welded") + new_icon.Insert(closed_locked_icon, "closed_locked") + new_icon.Insert(closed_locked_welded_icon, "closed_locked_welded") + new_icon.Insert(closed_unlocked_icon, "closed_unlocked") + new_icon.Insert(closed_unlocked_welded_icon, "closed_unlocked_welded") + new_icon.Insert(door_front_icon, "door_front") + new_icon.Insert(door_back_icon, "door_back") // Set icon! icon = new_icon diff --git a/code/game/objects/structures/crates_lockers/closets/coffin.dm b/code/game/objects/structures/crates_lockers/closets/coffin.dm index 3865641552..b42bbcb778 100644 --- a/code/game/objects/structures/crates_lockers/closets/coffin.dm +++ b/code/game/objects/structures/crates_lockers/closets/coffin.dm @@ -7,6 +7,7 @@ seal_tool = /obj/item/weapon/tool/screwdriver breakout_sound = 'sound/weapons/tablehit1.ogg' closet_appearance = null // Special icon for us + door_anim_time = 0 //Unsupported /* Graves */ /obj/structure/closet/grave @@ -20,6 +21,7 @@ max_closets = 1 opened = 1 closet_appearance = null // Special icon for us + door_anim_time = 0 //Unsupported /obj/structure/closet/grave/attack_hand(mob/user as mob) if(opened) diff --git a/code/game/objects/structures/crates_lockers/closets/crittercrate.dm b/code/game/objects/structures/crates_lockers/closets/crittercrate.dm index 72a9188d12..0e7763e827 100644 --- a/code/game/objects/structures/crates_lockers/closets/crittercrate.dm +++ b/code/game/objects/structures/crates_lockers/closets/crittercrate.dm @@ -1,4 +1,5 @@ /obj/structure/closet/crate/critter name = "critter crate" desc = "A crate which can sustain life for a while." - closet_appearance = /decl/closet_appearance/large_crate/critter \ No newline at end of file + closet_appearance = /decl/closet_appearance/large_crate/critter + door_anim_time = 0 //Unsupported \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/egg_vr.dm b/code/game/objects/structures/crates_lockers/closets/egg_vr.dm index 19d3f8b452..d024a71582 100644 --- a/code/game/objects/structures/crates_lockers/closets/egg_vr.dm +++ b/code/game/objects/structures/crates_lockers/closets/egg_vr.dm @@ -13,6 +13,7 @@ opened = 0 sealed = 0 //Don't touch this. health = 100 + door_anim_time = 0 //Unsupported /obj/structure/closet/secure_closet/egg/update_icon() if(opened) diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index 6ba78a90a0..2023737b8f 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -1,7 +1,9 @@ /obj/structure/closet/cabinet name = "cabinet" desc = "Old will forever be in fashion." + icon = 'icons/obj/closets/bases/cabinet.dmi' closet_appearance = /decl/closet_appearance/cabinet + door_anim_time = 0 //Unsupported /obj/structure/closet/acloset name = "strange closet" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index bb7b05c7b3..0e05016224 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -312,3 +312,4 @@ GLOBAL_LIST_BOILERPLATE(all_brig_closets, /obj/structure/closet/secure_closet/br //too small to put a man in large = 0 + door_anim_time = 0 // Unsupported diff --git a/code/game/objects/structures/crates_lockers/closets/statue.dm b/code/game/objects/structures/crates_lockers/closets/statue.dm index 9b66918be0..c930b032a1 100644 --- a/code/game/objects/structures/crates_lockers/closets/statue.dm +++ b/code/game/objects/structures/crates_lockers/closets/statue.dm @@ -7,6 +7,7 @@ anchored = TRUE health = 0 //destroying the statue kills the mob within blocks_emissive = EMISSIVE_BLOCK_UNIQUE + door_anim_time = 0 // Why is this a closet?? var/intialTox = 0 //these are here to keep the mob from taking damage from things that logically wouldn't affect a rock var/intialFire = 0 //it's a little sloppy I know but it was this or the GODMODE flag. Lesser of two evils. var/intialBrute = 0 diff --git a/code/game/objects/structures/crates_lockers/closets/walllocker.dm b/code/game/objects/structures/crates_lockers/closets/walllocker.dm index f140e7380f..0bf549f06a 100644 --- a/code/game/objects/structures/crates_lockers/closets/walllocker.dm +++ b/code/game/objects/structures/crates_lockers/closets/walllocker.dm @@ -10,6 +10,7 @@ anchored = TRUE store_mobs = 0 wall_mounted = 1 + door_anim_time = 0 // Unsupported //spawns 2 sets of breathmask, emergency oxy tank and crowbar diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index eec6a8d892..bc178de97e 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -7,6 +7,7 @@ closet_appearance = /decl/closet_appearance/crate climbable = TRUE dir = 4 //Spawn facing 'forward' by default. + door_anim_time = 0 //Unsupported until appropriate sprites are available var/points_per_crate = 5 var/rigged = 0 diff --git a/icons/obj/closets/bases/cabinet.dmi b/icons/obj/closets/bases/cabinet.dmi index 236b164ca6..a8c0261900 100644 Binary files a/icons/obj/closets/bases/cabinet.dmi and b/icons/obj/closets/bases/cabinet.dmi differ diff --git a/icons/obj/closets/bases/cart.dmi b/icons/obj/closets/bases/cart.dmi index 852e539b4d..da1b28500b 100644 Binary files a/icons/obj/closets/bases/cart.dmi and b/icons/obj/closets/bases/cart.dmi differ diff --git a/icons/obj/closets/bases/closet.dmi b/icons/obj/closets/bases/closet.dmi index 551435629e..2753b92b91 100644 Binary files a/icons/obj/closets/bases/closet.dmi and b/icons/obj/closets/bases/closet.dmi differ diff --git a/icons/obj/closets/bases/crate.dmi b/icons/obj/closets/bases/crate.dmi index 83500acb3b..d83ac8da7b 100644 Binary files a/icons/obj/closets/bases/crate.dmi and b/icons/obj/closets/bases/crate.dmi differ diff --git a/icons/obj/closets/bases/large_crate.dmi b/icons/obj/closets/bases/large_crate.dmi index fd3400ed72..a8cb85d5ce 100644 Binary files a/icons/obj/closets/bases/large_crate.dmi and b/icons/obj/closets/bases/large_crate.dmi differ diff --git a/icons/obj/closets/decals/closet.dmi b/icons/obj/closets/decals/closet.dmi index a7bb7591b1..97e24b4f50 100644 Binary files a/icons/obj/closets/decals/closet.dmi and b/icons/obj/closets/decals/closet.dmi differ