mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-21 20:11:04 +01:00
Add crate shelves (#21493)
Ports https://github.com/shiptest-ss13/Shiptest/pull/2374 The warehous has been redesigned to incorporate new shelves that can each carry up to 3 crates. The warehouse now spawns with the crates already on the shelves and the related code has been updated to account for this and still spawn things inside of them. The back room in the warehouse also lost its camera, to give a chance for antags and other shenanigans to occur back there. <img width="595" height="971" alt="image" src="https://github.com/user-attachments/assets/3cf8bd17-e91b-4d32-9ae8-5e461eceee42" /> <img width="282" height="556" alt="image" src="https://github.com/user-attachments/assets/100f02b0-9165-4c35-a24b-f20d9bdda30e" />
This commit is contained in:
@@ -168,8 +168,10 @@
|
||||
|
||||
/obj/structure/closet/proc/can_open()
|
||||
if(welded || locked)
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
if(istype(loc, /obj/structure/crate_shelf))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/structure/closet/proc/can_close()
|
||||
for(var/obj/structure/closet/closet in get_turf(src))
|
||||
@@ -743,6 +745,10 @@
|
||||
return 0
|
||||
|
||||
/obj/structure/closet/proc/mob_breakout(var/mob/living/escapee)
|
||||
if(istype(loc, /obj/structure/crate_shelf))
|
||||
var/obj/structure/crate_shelf/shelf = loc
|
||||
shelf.relay_container_resist_act(escapee, src)
|
||||
return
|
||||
|
||||
//Improved by nanako
|
||||
//Now it actually works, also locker breakout time stacks with locking and welding
|
||||
|
||||
@@ -134,6 +134,9 @@
|
||||
if(!opened && tablestatus == UNDER_TABLE)
|
||||
to_chat(user, SPAN_WARNING("You can't open \the [src] while the lid is obstructed!"))
|
||||
return FALSE
|
||||
if(istype(loc, /obj/structure/crate_shelf))
|
||||
to_chat(user, SPAN_WARNING("You can't open \the [src] while it is on a shelf!"))
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -155,12 +158,30 @@
|
||||
|
||||
//For putting on tables
|
||||
/obj/structure/closet/crate/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
|
||||
if (istype(over, /obj/structure/table))
|
||||
if (istype(over, /obj/structure/table) && !istype(loc, /obj/structure/crate_shelf))
|
||||
put_on_table(over, user)
|
||||
return TRUE
|
||||
else if(istype(over, /obj/structure/crate_shelf) && !istype(loc, /obj/structure/crate_shelf))
|
||||
put_on_shelf(over, user)
|
||||
return TRUE
|
||||
if(istype(loc, /obj/structure/crate_shelf) && isturf(over) && !is_blocked_turf(over))
|
||||
take_off_shelf(loc, user, over)
|
||||
return TRUE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/crate/proc/put_on_shelf(var/obj/structure/crate_shelf/shelf, var/mob/user)
|
||||
shelf.load(src, user)
|
||||
|
||||
/obj/structure/closet/crate/proc/take_off_shelf(var/obj/structure/crate_shelf/shelf, var/mob/user, turf/unload_turf)
|
||||
shelf.unload(src, user, unload_turf)
|
||||
|
||||
/obj/structure/closet/crate/Adjacent(atom/neighbor, atom/target, atom/movable/mover)
|
||||
. = ..()
|
||||
if(istype(loc, /obj/structure/crate_shelf))
|
||||
var/obj/structure/crate_shelf/S = loc
|
||||
return S.Adjacent(neighbor, target, mover)
|
||||
|
||||
/obj/structure/closet/crate/proc/put_on_table(var/obj/structure/table/table, var/mob/user)
|
||||
if (!table || !user || (tablestatus == UNDER_TABLE))
|
||||
return
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/obj/structure/crate_shelf
|
||||
name = "crate shelf"
|
||||
desc = "It's a shelf! For storing crates!"
|
||||
icon = 'icons/obj/structure/crate_shelf.dmi'
|
||||
icon_state = "shelf_base"
|
||||
var/shelf_stack = "shelf_stack"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
layer = BELOW_OBJ_LAYER
|
||||
|
||||
var/capacity = 3 // Default capacity of the shelf
|
||||
var/use_delay = 1 SECONDS // Default interaction delay of the shelf
|
||||
var/list/shelf_contents
|
||||
var/vertical_offset = 10 // Vertical pixel offset of shelving-related things. Set to 10 by default due to this leaving more of the crate on-screen to be clicked.
|
||||
|
||||
var/manipulating = FALSE
|
||||
|
||||
var/obj/item/stack/dismantle_mat = /obj/item/stack/rods
|
||||
build_amt = 10
|
||||
|
||||
// For testing only.
|
||||
/obj/structure/crate_shelf/tall
|
||||
capacity = 12
|
||||
|
||||
/obj/structure/crate_shelf/mechanics_hints()
|
||||
. = list()
|
||||
. += ..()
|
||||
. += "Drag a crate on to the shelf, to put it on it."
|
||||
. += "Drag a crate from the shelf to the ground to remove it."
|
||||
|
||||
/obj/structure/crate_shelf/Initialize(mapload)
|
||||
. = ..()
|
||||
LAZYSETLEN(shelf_contents, capacity)
|
||||
update_icon()
|
||||
return mapload ? INITIALIZE_HINT_LATELOAD : INITIALIZE_HINT_NORMAL
|
||||
|
||||
/obj/structure/crate_shelf/LateInitialize()
|
||||
. = ..()
|
||||
var/next_free
|
||||
for(var/obj/I in loc)
|
||||
if (!istype(I, /obj/structure/closet/crate))
|
||||
continue
|
||||
next_free = LAZYFIND(shelf_contents, null)
|
||||
if(!next_free)
|
||||
continue
|
||||
put_in(I, next_free)
|
||||
|
||||
|
||||
/obj/structure/crate_shelf/update_icon()
|
||||
ClearOverlays()
|
||||
var/stack_layer // This is used to generate the sprite layering of the shelf pieces.
|
||||
var/stack_offset // This is used to generate the vertical offset of the shelf pieces.
|
||||
for(var/i in 1 to (capacity - 1))
|
||||
stack_layer = BELOW_OBJ_LAYER + (0.02 * i) - 0.01 // Make each shelf piece render above the last, but below the crate that should be on it.
|
||||
stack_offset = vertical_offset * i // Make each shelf piece physically above the last.
|
||||
var/image/I = image(icon, icon_state = shelf_stack, layer = stack_layer, pixel_y = stack_offset)
|
||||
AddOverlays(I)
|
||||
|
||||
/obj/structure/crate_shelf/Destroy()
|
||||
LAZYCLEARLIST(shelf_contents)
|
||||
return ..()
|
||||
|
||||
/obj/structure/crate_shelf/attackby(obj/item/attacking_item, mob/user, params)
|
||||
. = ..()
|
||||
if(attacking_item.iswrench())
|
||||
dismantle(attacking_item, user)
|
||||
|
||||
/obj/structure/crate_shelf/dismantle(obj/item/W, mob/user)
|
||||
// if(!LAZYLEN(shelf_contents))
|
||||
var/empty = TRUE
|
||||
for(var/c in shelf_contents)
|
||||
if(c != null)
|
||||
empty = FALSE
|
||||
if(!empty)
|
||||
to_chat(user, SPAN_NOTICE("Remove any crates from \the [src] before dismantling it."))
|
||||
return
|
||||
if(manipulating)
|
||||
return
|
||||
manipulating = TRUE
|
||||
user.visible_message("<b>[user]</b> begins dismantling \the [src].",
|
||||
SPAN_NOTICE("You begin dismantling \the [src]."))
|
||||
if(!W.use_tool(src, user, 2 SECONDS, volume = 50))
|
||||
manipulating = FALSE
|
||||
return
|
||||
user.visible_message("\The [user] dismantles \the [src].",
|
||||
SPAN_NOTICE("You dismantle \the [src]."))
|
||||
new dismantle_mat(src.loc, 10)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/crate_shelf/proc/relay_container_resist_act(mob/living/user, obj/structure/closet/crate)
|
||||
to_chat(user, SPAN_NOTICE("You begin attempting to knock [crate] out of [src]."))
|
||||
visible_message(SPAN_DANGER("\The [crate] begins to shake violently!"), SPAN_DANGER("You hear the sound of metal thrashing around nearby."), intent_message = THUNK_SOUND)
|
||||
crate.shake_animation()
|
||||
|
||||
if(do_after(user, 20 SECONDS, target = crate))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != crate || crate.loc != src)
|
||||
return // If the user is in a strange condition, return early.
|
||||
crate.shake_animation()
|
||||
visible_message(SPAN_WARNING("\The [crate] falls off the [src]!"), SPAN_NOTICE("You hear a thud."), intent_message = THUNK_SOUND)
|
||||
crate.forceMove(loc) // Drop the crate onto the shelf,
|
||||
step_rand(crate, 1) // Then try to push it somewhere.
|
||||
crate.layer = initial(crate.layer) // Reset the crate back to having the default layer, otherwise we might get strange interactions.
|
||||
crate.pixel_y = initial(crate.pixel_y) // Reset the crate back to having no offset, otherwise it will be floating.
|
||||
shelf_contents[shelf_contents.Find(crate)] = null // Remove the reference to the crate from the list.
|
||||
handle_visuals()
|
||||
|
||||
|
||||
/obj/structure/crate_shelf/proc/handle_visuals()
|
||||
vis_contents = contents // It really do be that shrimple.
|
||||
return
|
||||
|
||||
/obj/structure/crate_shelf/proc/load(obj/structure/closet/crate/crate, mob/user)
|
||||
// Check if the shelf has an empty spot, notify the player if not.
|
||||
var/next_free = LAZYFIND(shelf_contents, null)
|
||||
if(!next_free)
|
||||
to_chat(user, SPAN_NOTICE("The shelf is full."))
|
||||
balloon_alert(user, "shelf full!")
|
||||
return FALSE
|
||||
visible_message("\The [user] starts to put \the [crate] on \the [src].")
|
||||
if(do_after(user, use_delay, target = crate))
|
||||
if(shelf_contents[next_free] != null)
|
||||
// Something has been added to the shelf while we were waiting, abort!
|
||||
visible_message("\The [user] stops putting \the [crate] on \the [src].")
|
||||
to_chat(user, SPAN_NOTICE("Something else was added to the shelf first."))
|
||||
return FALSE
|
||||
if(crate.opened) // If the crate is open, try to close it.
|
||||
if(!crate.close())
|
||||
visible_message("\The [user] stops putting \the [crate] on \the [src].")
|
||||
to_chat(user, SPAN_NOTICE("The crate couldn't be closed."))
|
||||
return FALSE // If we fail to close it, don't load it into the shelf.
|
||||
put_in(crate, next_free)
|
||||
visible_message("\The [user] puts \the [crate] on \the [src].")
|
||||
return TRUE
|
||||
visible_message("\The [user] stops putting \the [crate] on \the [src].")
|
||||
return FALSE // If the do_after() is interrupted, return FALSE!
|
||||
|
||||
/obj/structure/crate_shelf/proc/put_in(obj/structure/closet/crate/crate, var/next_free)
|
||||
LAZYSET(shelf_contents, next_free, crate)
|
||||
crate.forceMove(src) // Insert the crate into the shelf.
|
||||
crate.pixel_y = vertical_offset * (next_free - 1) // Adjust the vertical offset of the crate to look like it's on the shelf.
|
||||
crate.layer = BELOW_OBJ_LAYER + 0.02 * (next_free - 1) // Adjust the layer of the crate to look like it's in the shelf.
|
||||
handle_visuals()
|
||||
|
||||
/obj/structure/crate_shelf/proc/unload(obj/structure/closet/crate/crate, mob/user, turf/unload_turf)
|
||||
if(!unload_turf)
|
||||
unload_turf = get_turf(user) // If a turf somehow isn't passed into the proc, put it at the user's feet.
|
||||
if(!unload_turf.Enter(crate)) // If moving the crate from the shelf to the desired turf would bump, don't do it! Thanks Kapu1178 for the help here. - Generic DM
|
||||
to_chat(user, SPAN_NOTICE("There is no room for the crate."))
|
||||
return FALSE
|
||||
visible_message("\The [user] starts unloading \the [crate] from \the [src].")
|
||||
if(do_after(user, use_delay, target = crate))
|
||||
if(!LAZYFIND(shelf_contents, crate))
|
||||
visible_message("\The [user] stops unloading \the [crate] from \the [src].")
|
||||
to_chat(user, SPAN_NOTICE("The crate can't be moved."))
|
||||
return FALSE // If something has happened to the crate while we were waiting, abort!
|
||||
crate.layer = initial(crate.layer) // Reset the crate back to having the default layer, otherwise we might get strange interactions.
|
||||
crate.pixel_y = initial(crate.pixel_y) // Reset the crate back to having no offset, otherwise it will be floating.
|
||||
crate.forceMove(unload_turf)
|
||||
shelf_contents[shelf_contents.Find(crate)] = null // We do this instead of removing it from the list to preserve the order of the shelf.
|
||||
handle_visuals()
|
||||
visible_message("\The [user] unloads \the [crate] from \the [src].")
|
||||
return TRUE
|
||||
visible_message("\The [user] stops unloading \the [crate] from \the [src].")
|
||||
return FALSE // If the do_after() is interrupted, return FALSE!
|
||||
Reference in New Issue
Block a user