Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aurorastation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1482,6 +1482,7 @@
#include "code\game\objects\structures\carts\parcelcart.dm"
#include "code\game\objects\structures\crates_lockers\closets.dm"
#include "code\game\objects\structures\crates_lockers\crates.dm"
#include "code\game\objects\structures\crates_lockers\crateshelf.dm"
#include "code\game\objects\structures\crates_lockers\largecrate.dm"
#include "code\game\objects\structures\crates_lockers\closets\crittercrate.dm"
#include "code\game\objects\structures\crates_lockers\closets\fitness.dm"
Expand Down
3 changes: 2 additions & 1 deletion code/game/objects/items/stacks/rods.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ GLOBAL_LIST_INIT_TYPED(rod_recipes, /datum/stack_recipe, list(
new /datum/stack_recipe("floor-mounted catwalk", /obj/structure/lattice/catwalk/indoor, 4, time = 10, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("grate, dark", /obj/structure/lattice/catwalk/indoor/grate, 1, time = 10, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("grate, light", /obj/structure/lattice/catwalk/indoor/grate/light, 1, time = 10, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("table frame", /obj/structure/table, 2, time = 10, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("table frame", /obj/structure/table, 2, time = 10, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("crate shelf", /obj/structure/crate_shelf, req_amount = 10, time = 10, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("mine track", /obj/structure/track, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE),
new /datum/stack_recipe("cane", /obj/item/cane, 1, time = 6),
new /datum/stack_recipe("crowbar", /obj/item/crowbar, 1, time = 6),
Expand Down
10 changes: 8 additions & 2 deletions code/game/objects/structures/crates_lockers/closets.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand Down
23 changes: 22 additions & 1 deletion code/game/objects/structures/crates_lockers/crates.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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 ..()

Expand All @@ -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
Expand Down
164 changes: 164 additions & 0 deletions code/game/objects/structures/crates_lockers/crateshelf.dm
Original file line number Diff line number Diff line change
@@ -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!
5 changes: 5 additions & 0 deletions code/modules/cargo/randomstock.dm
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ GLOBAL_LIST_EMPTY(random_stock_large)
var/obj/structure/table/B = A
if(!B.no_cargo)
tables |= B
else if(istype(A, /obj/structure/crate_shelf))
var/obj/structure/crate_shelf/shelf = A
for(var/obj/I in shelf.shelf_contents)
if (istype(I, /obj/structure/closet/crate))
containers |= I

/datum/cargospawner/proc/start()
if (!SSatlas.current_map.warehouse_basearea || !length(warehouseturfs))
Expand Down
7 changes: 7 additions & 0 deletions html/changelogs/TheGreatestOfShelves.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
author: TheGreyWolf

delete-after: True

changes:
- rscadd: "Added crate shelves."
- rscadd: "Remapped the warehouse to fit the crate shelves."
Binary file added icons/obj/structure/crate_shelf.dmi
Binary file not shown.
Loading
Loading