diff --git a/code/game/machinery/autolathe/autolathe_datums.dm b/code/game/machinery/autolathe/autolathe_datums.dm
index 0d6fae1737d..b2ef06f4e8c 100644
--- a/code/game/machinery/autolathe/autolathe_datums.dm
+++ b/code/game/machinery/autolathe/autolathe_datums.dm
@@ -408,6 +408,11 @@
path = /obj/item/device/destTagger
category = "General"
+/datum/autolathe/recipe/cratescanner
+ name = "crate contents scanner"
+ path = /obj/item/device/cratescanner
+ category = "General"
+
/datum/autolathe/recipe/debugger
name = "debugger"
path = /obj/item/device/debugger
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 8547ce04627..7cd101984e0 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -369,6 +369,15 @@
user.drop_from_inventory(W,loc)
else
user.drop_item()
+ else if(istype(W, /obj/item/device/cratescanner))
+ var/obj/item/device/cratescanner/Cscanner = W
+ if(locked)
+ to_chat(user, SPAN_WARNING("[W] refuses to scan [src]. Unlock it first!"))
+ return
+ if(welded)
+ to_chat(user, SPAN_WARNING("[W] detects that [src] is welded shut, and refuses to scan."))
+ return
+ Cscanner.print_contents(name, contents, src.loc)
else if(istype(W, /obj/item/stack/packageWrap))
return
else if(istype(W, /obj/item/ducttape))
@@ -752,3 +761,32 @@
if(linked_teleporter)
QDEL_NULL(linked_teleporter)
return ..()
+
+/*
+==========================
+ Contents Scanner
+==========================
+*/
+/obj/item/device/cratescanner
+ name = "crate contents scanner"
+ desc = "A handheld device used to scan and print a manifest of a container's contents. Does not work on locked crates, for privacy reasons."
+ icon_state = "cratescanner"
+ matter = list(DEFAULT_WALL_MATERIAL = 250, MATERIAL_GLASS = 140)
+ w_class = ITEMSIZE_SMALL
+ item_state = "electronic"
+ flags = CONDUCT
+ slot_flags = SLOT_BELT
+
+/obj/item/device/cratescanner/proc/print_contents(targetname, targetcontents, targetloc)
+ var/output = list()
+ var/list/outputstring
+ for(var/atom/item in targetcontents)
+ if(item.name in output)
+ output[item.name] = output[item.name] + 1
+ else
+ output[item.name] = 1
+ for(var/entry in output)
+ outputstring += "- [entry]: [output[entry]]x
"
+ var/obj/item/paper/printout = new /obj/item/paper(targetloc)
+ printout.info = "contents of [targetname]
"
+ printout.info += "[outputstring]"
diff --git a/html/changelogs/flaminglily-cheap-and-easy-paperwork.yml b/html/changelogs/flaminglily-cheap-and-easy-paperwork.yml
new file mode 100644
index 00000000000..0d9199529b7
--- /dev/null
+++ b/html/changelogs/flaminglily-cheap-and-easy-paperwork.yml
@@ -0,0 +1,42 @@
+################################
+# 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
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# maptweak
+# spellcheck (typo fixes)
+# experiment
+# balance
+# admin
+# backend
+# security
+# refactor
+#################################
+
+# Your name.
+author: FlamingLily
+
+# 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, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
+# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Added a crate contents scanner, used to quickly and easily generate a paper showing the contents of any scanned (unlocked) crate."
+ - maptweak: "Shifted the table in the warehouse over slightly, and made it bigger."
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 79320e921aa..177374306cd 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/maps/sccv_horizon/sccv_horizon-1_deck_1.dmm b/maps/sccv_horizon/sccv_horizon-1_deck_1.dmm
index 611ba47368f..0189cd6cc7c 100644
--- a/maps/sccv_horizon/sccv_horizon-1_deck_1.dmm
+++ b/maps/sccv_horizon/sccv_horizon-1_deck_1.dmm
@@ -8520,6 +8520,12 @@
/obj/effect/floor_decal/corner/brown{
dir = 6
},
+/obj/structure/table/standard{
+ no_cargo = 1
+ },
+/obj/item/paper_bin,
+/obj/item/pen,
+/obj/item/device/cratescanner,
/turf/simulated/floor/tiled,
/area/operations/storage)
"gGE" = (
@@ -16447,7 +16453,9 @@
/turf/simulated/floor/tiled,
/area/shuttle/intrepid/cargo_bay)
"njB" = (
-/obj/structure/bed/stool/chair/office/dark,
+/obj/structure/bed/stool/chair/office/dark{
+ dir = 4
+ },
/turf/simulated/floor/tiled,
/area/operations/storage)
"njH" = (
@@ -26031,14 +26039,20 @@
},
/area/maintenance/wing/port/deck1)
"vjx" = (
+/obj/structure/cable/green{
+ icon_state = "1-2"
+ },
+/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,
+/obj/machinery/atmospherics/pipe/simple/hidden/supply,
+/obj/effect/floor_decal/corner/brown{
+ dir = 6
+ },
/obj/structure/table/standard{
no_cargo = 1
},
-/obj/item/paper_bin,
-/obj/item/pen,
-/obj/item/stack/packageWrap,
-/obj/item/device/destTagger,
/obj/item/device/hand_labeler,
+/obj/item/device/destTagger,
+/obj/item/stack/packageWrap,
/turf/simulated/floor/tiled,
/area/operations/storage)
"vjI" = (
@@ -41153,7 +41167,7 @@ pme
qAY
sWr
njB
-vjx
+nCV
nCV
duN
jDs
@@ -41355,7 +41369,7 @@ jKF
iXq
cOy
gGg
-gGg
+vjx
fiO
qYc
pfb