From 0f57a23830272f6b1bfb5d9939d14c0ae88eb1a9 Mon Sep 17 00:00:00 2001
From: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Date: Mon, 24 Mar 2025 02:50:23 +0530
Subject: [PATCH] Refactor for storage initialization & organization (#89543)
## About The Pull Request
A Huge chunk of changes just comes from moving existing storage code
into new files & seperating `atom_storage` code into its own subtype
under the already existing `storage/subtypes` folder.
With that the changes in this PR can be organized into 3 categories.
**1. Refactors how `/obj/item/storage/PopulateContents()` initializes
storages**
- Fixes #88747 and every other storage item that has a similar variant
of this problem
The problem with `PopulateContents()` is that it allows you to create
atoms directly inside the storage via `new(src)` thus bypassing all the
access restrictions enforced by `/datum/storage/can_insert()` resulting
in storages holding stuff they shouldn't be able to hold.
Now how this proc works has been changed. It must now only return a list
of items(each item in the list can either be a typepath or a solid atom
or a mix of them in any order) that should be inserted into the storage.
Each item is then passed into `can_insert()` to check if it can fit in
the storage.
If your list contains solid atoms they must be first moved
to/Initialized in nullspace so `can_insert()` won't count it as already
inserted. `can_insert()` has now also been refactored to throw stack
traces but explaining exactly why the item could not fit in the storage
thus giving you more debugging details to fix your stuff.
A large majority of changes is refactoring `PopulateContents()` to
return a list instead of simply creating the item in place so simple 1
line changes & with that we have fixed all broken storages(medical
toolbox. electrical toolbox, cruisader armor boxes & many more) that
hold more items they can handle
**2. Organizes initialization of `atom_storage` for storage subtypes.**
All subtypes of `/obj/item/storage` should(not enforced) create their
own `/datum/storage/` subtype under the folder `storage/subtypes` if the
default values are not sufficient. This is the 2nd change done across
all existing storages
Not only does this bring code cleanliness & organization (separating
storage code from item code like how `/datum/wire` code is separated
into its own sub folder) but it also makes storage initialization
slightly faster (because you are not modifying default values after
`atom_storage` is initialized but you are directly setting the default
value in place).
You now cannot & should not modify `atom_storage` values inside
`PopulateContents()`. This will make that proc as pure as possible so
less side effects. Of course this principle is not enforced and you can
still modify the storage value after `Initialize()` but this should not
be encouraged in the future
**3. Adds support for automatic storage computations**
Most people don't understand how `atom_storage` values work. The comment
here clearly states that
https://github.com/tgstation/tgstation/blob/55bbfef0da70d87455ca8d6fd5c95107eb8dbefb/code/game/objects/items/storage/toolbox.dm#L327-L329
Because of that the linked issue occurs not just for medical toolbox but
for a lot of other items as well.
Which is why if you do not know what you doing, `PopulateContents()` now
comes with a new storage parameter i.e. `/datum/storage_config`
This datum allows you to compute storage values that will perfectly fit
with the initial contents of your storage. It allows you to do stuff
like computing `max_slots`, `max_item_weight`, `max_total_weight` etc
based on your storage initial contents so that all the contents can fit
perfectly leaving no space for excess.
## Changelog
:cl:
fix: storages are no longer initialized with items that can't be put
back in after taking them out
refactor: storage initialization has been refactored. Please report bugs
on github
/:cl:
---
code/__DEFINES/storage.dm | 3 +
code/__HELPERS/_lists.dm | 12 +
code/_globalvars/storage_config.dm | 42 +
code/datums/station_traits/neutral_traits.dm | 32 -
code/datums/storage/storage.dm | 142 ++-
code/datums/storage/subtypes/backpack.dm | 18 -
code/datums/storage/subtypes/backpacks.dm | 38 +
code/datums/storage/subtypes/bags.dm | 370 ++++++
code/datums/storage/subtypes/belts.dm | 362 ++++++
code/datums/storage/subtypes/boxes.dm | 328 ++++++
code/datums/storage/subtypes/drone.dm | 26 -
.../subtypes/{duffel_bag.dm => dufflebags.dm} | 26 +-
code/datums/storage/subtypes/holsters.dm | 123 ++
code/datums/storage/subtypes/implant.dm | 15 -
code/datums/storage/subtypes/lockboxes.dm | 32 +
code/datums/storage/subtypes/medkits.dm | 144 +++
code/datums/storage/subtypes/organ_box.dm | 17 -
.../subtypes/{ => others}/bag_of_holding.dm | 0
.../storage/subtypes/{ => others}/cards.dm | 0
.../subtypes/{ => others}/carpskin_bag.dm | 0
.../{ => others}/extract_inventory.dm | 0
.../subtypes/{ => others}/fish_case.dm | 10 +-
code/datums/storage/subtypes/others/misc.dm | 328 ++++++
code/datums/storage/subtypes/others/pod.dm | 50 +
.../storage/subtypes/{ => others}/rped.dm | 7 +-
code/datums/storage/subtypes/pockets.dm | 138 ++-
.../storage/subtypes/portable_chem_mixer.dm | 16 -
code/datums/storage/subtypes/surgery_tray.dm | 29 -
.../datums/storage/subtypes/test_tube_rack.dm | 15 -
code/datums/storage/subtypes/toolboxes.dm | 49 +
code/datums/storage/subtypes/trash.dm | 11 -
code/game/machinery/launch_pad.dm | 6 +-
code/game/objects/items/crayons.dm | 29 +-
code/game/objects/items/devices/spyglasses.dm | 11 +-
.../objects/items/devices/traitordevices.dm | 14 +-
code/game/objects/items/dice.dm | 42 +-
code/game/objects/items/food/moth.dm | 8 +-
code/game/objects/items/mail.dm | 26 +-
code/game/objects/items/pinpointer.dm | 6 +-
code/game/objects/items/religion.dm | 17 +-
code/game/objects/items/storage/backpack.dm | 430 +------
code/game/objects/items/storage/bags.dm | 444 +++----
code/game/objects/items/storage/basket.dm | 9 +-
code/game/objects/items/storage/belt.dm | 629 ++++------
.../objects/items/storage/boxes/_boxes.dm | 9 +-
.../items/storage/boxes/cargo_boxes.dm | 14 +-
.../items/storage/boxes/clothes_boxes.dm | 231 ++--
.../items/storage/boxes/engineering_boxes.dm | 74 +-
.../items/storage/boxes/fishing_boxes.dm | 44 +
.../objects/items/storage/boxes/flat_boxes.dm | 6 +-
.../objects/items/storage/boxes/food_boxes.dm | 414 ++++---
.../items/storage/boxes/implant_boxes.dm | 30 +-
.../objects/items/storage/boxes/job_boxes.dm | 145 ++-
.../items/storage/boxes/medical_boxes.dm | 107 +-
.../items/storage/boxes/science_boxes.dm | 113 +-
.../items/storage/boxes/security_boxes.dm | 123 +-
.../items/storage/boxes/service_boxes.dm | 126 +-
.../items/storage/boxes/trait_boxes.dm | 31 +
.../items/storage/boxes/uplink_kits.dm | 1029 +++++++++++++++++
code/game/objects/items/storage/briefcase.dm | 74 +-
code/game/objects/items/storage/dufflebags.dm | 404 +++++++
code/game/objects/items/storage/fancy.dm | 94 +-
code/game/objects/items/storage/garment.dm | 212 ++--
code/game/objects/items/storage/holsters.dm | 152 +--
code/game/objects/items/storage/lockbox.dm | 112 +-
code/game/objects/items/storage/medkit.dm | 591 ++--------
code/game/objects/items/storage/misc.dm | 120 ++
.../game/objects/items/storage/pillbottles.dm | 274 +++++
code/game/objects/items/storage/sixpack.dm | 28 +-
code/game/objects/items/storage/storage.dm | 156 ++-
code/game/objects/items/storage/toolbox.dm | 700 -----------
.../items/storage/toolboxes/_toolbox.dm | 159 +++
.../items/storage/toolboxes/emergency.dm | 43 +
.../items/storage/toolboxes/fishing.dm | 59 +
.../items/storage/toolboxes/mechanical.dm | 74 ++
.../items/storage/toolboxes/medical.dm | 42 +
.../objects/items/storage/toolboxes/misc.dm | 47 +
.../items/storage/toolboxes/service.dm | 33 +
.../items/storage/toolboxes/weapons.dm | 352 ++++++
.../game/objects/items/storage/uplink_kits.dm | 919 ---------------
code/game/objects/items/storage/wallets.dm | 47 +-
code/game/objects/items/tcg/tcg.dm | 7 +-
code/game/objects/items/teleportation.dm | 6 +-
code/game/objects/items/toys.dm | 7 +-
code/game/objects/structures/janitor.dm | 7 +-
code/modules/admin/verbs/anonymousnames.dm | 53 +-
.../heretic/items/unfathomable_curio.dm | 20 +-
.../traitor/contractor/contractor_items.dm | 10 +-
.../objects/gimmick_disks/_gimmick_disk.dm | 2 +-
.../objects/gimmick_disks/dungeon_disk.dm | 38 +-
.../objects/gimmick_disks/sports_disk.dm | 29 +-
code/modules/bitrunning/objects/loot_box.dm | 11 +-
.../chameleon/generic_chameleon_clothing.dm | 16 +-
code/modules/clothing/head/costume.dm | 18 +
code/modules/clothing/shoes/cowboy.dm | 3 +-
code/modules/detectivework/evidence.dm | 3 +-
code/modules/events/holiday/easter.dm | 22 -
.../events/shuttle_loan/shuttle_loan_items.dm | 8 +-
code/modules/fishing/aquarium/aquarium_kit.dm | 5 +-
code/modules/fishing/fishing_equipment.dm | 163 +--
.../food_and_drinks/machinery/coffeemaker.dm | 5 +-
.../ruins/spaceruin_code/forgottenship.dm | 3 +-
code/modules/mining/money_bag.dm | 37 -
.../mob/living/basic/drone/drone_tools.dm | 22 +-
.../guns/ballistic/bows/bow_quivers.dm | 40 -
.../projectiles/guns/energy/dueling.dm | 28 -
code/modules/research/part_replacer.dm | 73 +-
.../mobile_port/variants/emergency/pods.dm | 82 +-
.../internal/cyberimp/augments_internal.dm | 8 +-
.../vehicles/mecha/mecha_control_console.dm | 11 +-
tgstation.dme | 51 +-
111 files changed, 6790 insertions(+), 5240 deletions(-)
create mode 100644 code/_globalvars/storage_config.dm
delete mode 100644 code/datums/storage/subtypes/backpack.dm
create mode 100644 code/datums/storage/subtypes/backpacks.dm
create mode 100644 code/datums/storage/subtypes/bags.dm
create mode 100644 code/datums/storage/subtypes/belts.dm
create mode 100644 code/datums/storage/subtypes/boxes.dm
delete mode 100644 code/datums/storage/subtypes/drone.dm
rename code/datums/storage/subtypes/{duffel_bag.dm => dufflebags.dm} (76%)
create mode 100644 code/datums/storage/subtypes/holsters.dm
delete mode 100644 code/datums/storage/subtypes/implant.dm
create mode 100644 code/datums/storage/subtypes/lockboxes.dm
create mode 100644 code/datums/storage/subtypes/medkits.dm
delete mode 100644 code/datums/storage/subtypes/organ_box.dm
rename code/datums/storage/subtypes/{ => others}/bag_of_holding.dm (100%)
rename code/datums/storage/subtypes/{ => others}/cards.dm (100%)
rename code/datums/storage/subtypes/{ => others}/carpskin_bag.dm (100%)
rename code/datums/storage/subtypes/{ => others}/extract_inventory.dm (100%)
rename code/datums/storage/subtypes/{ => others}/fish_case.dm (82%)
create mode 100644 code/datums/storage/subtypes/others/misc.dm
create mode 100644 code/datums/storage/subtypes/others/pod.dm
rename code/datums/storage/subtypes/{ => others}/rped.dm (95%)
delete mode 100644 code/datums/storage/subtypes/portable_chem_mixer.dm
delete mode 100644 code/datums/storage/subtypes/surgery_tray.dm
delete mode 100644 code/datums/storage/subtypes/test_tube_rack.dm
create mode 100644 code/datums/storage/subtypes/toolboxes.dm
delete mode 100644 code/datums/storage/subtypes/trash.dm
create mode 100644 code/game/objects/items/storage/boxes/fishing_boxes.dm
create mode 100644 code/game/objects/items/storage/boxes/trait_boxes.dm
create mode 100644 code/game/objects/items/storage/boxes/uplink_kits.dm
create mode 100644 code/game/objects/items/storage/dufflebags.dm
create mode 100644 code/game/objects/items/storage/misc.dm
create mode 100644 code/game/objects/items/storage/pillbottles.dm
delete mode 100644 code/game/objects/items/storage/toolbox.dm
create mode 100644 code/game/objects/items/storage/toolboxes/_toolbox.dm
create mode 100644 code/game/objects/items/storage/toolboxes/emergency.dm
create mode 100644 code/game/objects/items/storage/toolboxes/fishing.dm
create mode 100644 code/game/objects/items/storage/toolboxes/mechanical.dm
create mode 100644 code/game/objects/items/storage/toolboxes/medical.dm
create mode 100644 code/game/objects/items/storage/toolboxes/misc.dm
create mode 100644 code/game/objects/items/storage/toolboxes/service.dm
create mode 100644 code/game/objects/items/storage/toolboxes/weapons.dm
delete mode 100644 code/game/objects/items/storage/uplink_kits.dm
delete mode 100644 code/modules/mining/money_bag.dm
delete mode 100644 code/modules/projectiles/guns/ballistic/bows/bow_quivers.dm
diff --git a/code/__DEFINES/storage.dm b/code/__DEFINES/storage.dm
index a266c86198f..0cd4742fad4 100644
--- a/code/__DEFINES/storage.dm
+++ b/code/__DEFINES/storage.dm
@@ -22,3 +22,6 @@
#define STORAGE_NOT_LOCKED 0
#define STORAGE_SOFT_LOCKED 1
#define STORAGE_FULLY_LOCKED 2
+
+// Throw a stack trace in case of failed insertion into storage
+#define STORAGE_ERROR_INSERT -1
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index 4fbf3b4b968..8b47d6756f5 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -889,6 +889,18 @@
for(var/key in key_list)
. |= LIST_VALUE_WRAP_LISTS(key_list[key])
+/**
+ * Flattens a keyed list(key = some item, value = quantity of item required) into a list of its contents where each
+ * item of the list is duplicated as per the quantity required
+ */
+/proc/flatten_quantified_list(list/key_list)
+ if(!islist(key_list))
+ return null
+ . = list()
+ for(var/key in key_list)
+ for(var/_ in 1 to key_list[key])
+ UNTYPED_LIST_ADD(., key)
+
///Make a normal list an associative one
/proc/make_associative(list/flat_list)
. = list()
diff --git a/code/_globalvars/storage_config.dm b/code/_globalvars/storage_config.dm
new file mode 100644
index 00000000000..a04f2298045
--- /dev/null
+++ b/code/_globalvars/storage_config.dm
@@ -0,0 +1,42 @@
+/// Will be shared across all obj/item/storage as its only a one time use during Initialize()
+GLOBAL_VAR_INIT(initial_storage_config, new /datum/storage_config)
+
+/**
+ * Computes atom_storage values based on the initital contents of the storage.
+ * Use this only when the initial contents are extremly varied such that accurate values
+ * cannot be computed before hand e.g. if the items are randomly generated or you have huge list of stacks & stuff
+ * whose weights cannot be calculated correctly so setting the max_total_storage is not feasible and so on
+ *
+ * Don't use this if you can manually compute the items weights/counts & set max_total_storage or other values
+ * correctly yourself as it can lead to balance implications in game e.g. if your storage initially carries
+ * a large item and you want to set max_specific_storage to that item weight then it will
+ * allow all others items less than or equal to that item weight which may not be ideal.
+ *
+ * In conclusion use this when the initial contents are too complex for mortal comprehension so you make
+ * computing the storage values automatic
+ */
+/datum/storage_config
+ ///Computes the total weight of the storage's initial contents & sets max_total_storage to that value
+ var/compute_max_total_weight = FALSE
+ ///Computes the item that has the highest weight in the storage's initial contents & sets max_specific_storage to that value
+ var/compute_max_item_weight = FALSE
+ ///Computes number of items in the storage's initial contents & sets max_slots to that value
+ var/compute_max_item_count = FALSE
+ ///Sets exception_hold to the storage's initial contents meaning they can be carried without max_specific_storage restrictions
+ var/contents_are_exceptions = FALSE
+ ///Sets the storage's initial contents as the only items(i.e. sets can_hold) that can be carried by the storage
+ var/whitelist_content_types = FALSE
+
+///Resets all values to their defaults
+/datum/storage_config/proc/reset()
+ compute_max_total_weight = FALSE
+ compute_max_item_weight = FALSE
+ compute_max_item_count = FALSE
+ contents_are_exceptions = FALSE
+ whitelist_content_types = FALSE
+
+///Compute max total weight, max item weight & item count
+/datum/storage_config/proc/compute_max_values()
+ compute_max_total_weight = TRUE
+ compute_max_item_weight = TRUE
+ compute_max_item_count = TRUE
diff --git a/code/datums/station_traits/neutral_traits.dm b/code/datums/station_traits/neutral_traits.dm
index 4cb24783684..752c1f153b4 100644
--- a/code/datums/station_traits/neutral_traits.dm
+++ b/code/datums/station_traits/neutral_traits.dm
@@ -492,38 +492,6 @@
if(!spawned.equip_to_slot_if_possible(shirt, ITEM_SLOT_OCLOTHING, indirect_action = TRUE))
shirt.forceMove(boxie)
-/// A box containing a skub, for easier carry because skub is a bulky item.
-/obj/item/storage/box/stickers/skub
- name = "skub fan pack"
- desc = "A vinyl pouch to store your skub and pro-skub shirt in. A label on the back reads: \"Skubtide, Stationwide\"."
- icon_state = "skubpack"
- illustration = "label_skub"
- w_class = WEIGHT_CLASS_SMALL
-
-/obj/item/storage/box/stickers/skub/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 3
- atom_storage.exception_hold = typecacheof(list(/obj/item/skub, /obj/item/clothing/suit/costume/wellworn_shirt/skub))
-
-/obj/item/storage/box/stickers/skub/PopulateContents()
- new /obj/item/skub(src)
- new /obj/item/sticker/skub(src)
- new /obj/item/sticker/skub(src)
-
-/obj/item/storage/box/stickers/anti_skub
- name = "anti-skub stickers pack"
- desc = "The enemy may have been given a skub and a shirt, but I've got more stickers! Plus the pack can hold my anti-skub shirt."
- icon_state = "skubpack"
- illustration = "label_anti_skub"
-
-/obj/item/storage/box/stickers/anti_skub/Initialize(mapload)
- . = ..()
- atom_storage.exception_hold = typecacheof(list(/obj/item/clothing/suit/costume/wellworn_shirt/skub))
-
-/obj/item/storage/box/stickers/anti_skub/PopulateContents()
- for(var/i in 1 to 4)
- new /obj/item/sticker/anti_skub(src)
-
#undef PRO_SKUB
#undef ANTI_SKUB
#undef SKUB_IDFC
diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm
index 42668fb1464..79222e6ad5d 100644
--- a/code/datums/storage/storage.dm
+++ b/code/datums/storage/storage.dm
@@ -35,6 +35,7 @@
/// Do not set directly, use set_holdable
VAR_FINAL/list/obj/item/cant_hold
/// Typecache of items that can always be inserted into this storage, regardless of size.
+ /// Do not set directly, use set_holdable
VAR_FINAL/list/obj/item/exception_hold
/// For use with an exception typecache:
/// The maximum amount of items of the exception type that can be inserted into this storage.
@@ -146,7 +147,6 @@
src.max_total_storage = max_total_storage
/datum/storage/Destroy()
-
for(var/mob/person in is_using)
hide_contents(person)
@@ -287,35 +287,44 @@
/// ~Lemon
GLOBAL_LIST_EMPTY(cached_storage_typecaches)
-/datum/storage/proc/set_holdable(list/can_hold_list, list/cant_hold_list)
- if(!isnull(can_hold_list) && !islist(can_hold_list))
- can_hold_list = list(can_hold_list)
- if(!isnull(cant_hold_list) && !islist(cant_hold_list))
- cant_hold_list = list(cant_hold_list)
-
+/datum/storage/proc/set_holdable(list/can_hold_list, list/cant_hold_list, list/exception_hold_list)
+ can_hold = null
if (!isnull(can_hold_list))
- if(isnull(can_hold_description))
- can_hold_description = generate_hold_desc(can_hold_list)
+ if(!islist(can_hold_list))
+ can_hold_list = list(can_hold_list)
var/unique_key = can_hold_list.Join("-")
if(!GLOB.cached_storage_typecaches[unique_key])
GLOB.cached_storage_typecaches[unique_key] = typecacheof(can_hold_list)
can_hold = GLOB.cached_storage_typecaches[unique_key]
+ cant_hold = null
if (!isnull(cant_hold_list))
+ if(!islist(cant_hold_list))
+ cant_hold_list = list(cant_hold_list)
+
var/unique_key = cant_hold_list.Join("-")
if(!GLOB.cached_storage_typecaches[unique_key])
GLOB.cached_storage_typecaches[unique_key] = typecacheof(cant_hold_list)
cant_hold = GLOB.cached_storage_typecaches[unique_key]
-/// Generates a description, primarily for clothing storage.
-/datum/storage/proc/generate_hold_desc(can_hold_list)
- var/list/desc = list()
+ exception_hold = null
+ if (!isnull(exception_hold_list))
+ if(!islist(exception_hold_list))
+ exception_hold_list = list(exception_hold_list)
- for(var/obj/item/valid_item as anything in can_hold_list)
- desc += "\a [initial(valid_item.name)]"
+ var/unique_key = exception_hold_list.Join("-")
+ if(!GLOB.cached_storage_typecaches[unique_key])
+ GLOB.cached_storage_typecaches[unique_key] = typecacheof(exception_hold_list)
+ exception_hold = GLOB.cached_storage_typecaches[unique_key]
- return "\n\t[span_notice("[desc.Join("\n\t")]")]"
+ can_hold_description = null
+ var/list/holdables = can_hold_list | exception_hold
+ if(length(holdables))
+ var/list/desc = list()
+ for(var/obj/item/valid_item as anything in holdables)
+ desc += "\a [initial(valid_item.name)]"
+ can_hold_description = "\n\t[span_notice("[desc.Join("\n\t")]")]"
/// Updates the action button for toggling collectmode.
/datum/storage/proc/update_actions(atom/source, mob/equipper, slot)
@@ -353,71 +362,114 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
*/
/datum/storage/proc/can_insert(obj/item/to_insert, mob/user, messages = TRUE, force = STORAGE_NOT_LOCKED)
if(QDELETED(to_insert) || !istype(to_insert))
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:deleted/non object type [to_insert.type] was being inserted")
+ return FALSE
+
+ if((to_insert == parent) || (to_insert == real_location))
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:cannot insert storage into itself")
+ return FALSE
+
+ if(locked > force)
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:lock force of [force] cannot bypass lock level [locked]")
+ else if(user)
+ user.balloon_alert(user, "closed!")
return FALSE
//stops you from putting stuff like off-hand thingy inside. Hologram storages can accept only hologram items
if(to_insert.item_flags & ABSTRACT)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:[to_insert.type] is an abstract object")
return FALSE
if(parent.flags_1 & HOLOGRAM_1)
if(!(to_insert.flags_1 & HOLOGRAM_1))
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:[to_insert.type] is real and cannot be stored inside an hologram parent")
return FALSE
else if(to_insert.flags_1 & HOLOGRAM_1)
- return FALSE
-
- if(locked > force)
- if(messages && user)
- user.balloon_alert(user, "closed!")
- return FALSE
-
- if((to_insert == parent) || (to_insert == real_location))
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:[to_insert.type] is a hologram and cannot be stored inside an real parent")
return FALSE
if(to_insert.w_class > max_specific_storage)
if(!is_type_in_typecache(to_insert, exception_hold))
- if(messages && user)
- user.balloon_alert(user, "too big!")
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:[to_insert.type] of weight class [to_insert.w_class] exceeds max_specific_storage of [max_specific_storage] but is not on the exception_hold list")
+ else if(user)
+ user.balloon_alert(user, "too big!")
return FALSE
+
if(exception_max <= get_exception_count())
- if(messages && user)
- user.balloon_alert(user, "no room!")
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:cannot hold any more exceptional objects [get_exception_count()]/[exception_max] like [to_insert.type] that exceeds max_specific_storage of [max_specific_storage]")
+ else if(user)
+ user.balloon_alert(user, "no room!")
return FALSE
if(real_location.contents.len >= max_slots)
- if(messages && user && !silent_for_user)
- user.balloon_alert(user, "no room!")
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]: max slot capacity of [real_location.contents.len]/[max_slots] reached, cannot insert [to_insert.type]")
+ else if(user)
+ user.balloon_alert(user, "no room!")
return FALSE
if(to_insert.w_class + get_total_weight() > max_total_storage)
- if(messages && user && !silent_for_user)
- user.balloon_alert(user, "no room!")
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:Current weight capacity is [get_total_weight()]/[max_total_storage] no more space for [to_insert.type] who's weight is [to_insert.w_class]")
+ else if(user)
+ user.balloon_alert(user, "no room!")
return FALSE
var/can_hold_it = isnull(can_hold) || is_type_in_typecache(to_insert, can_hold) || is_type_in_typecache(to_insert, exception_hold)
var/cant_hold_it = is_type_in_typecache(to_insert, cant_hold)
var/trait_says_no = HAS_TRAIT(to_insert, TRAIT_NO_STORAGE_INSERT)
if(!can_hold_it || cant_hold_it || trait_says_no)
- if(messages && user)
- user.balloon_alert(user, "can't hold!")
- return FALSE
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ if(!can_hold_it)
+ stack_trace("[parent.type]:[to_insert.type] is neither whitelisted nor an exception hold")
+ if(cant_hold_it)
+ stack_trace("[parent.type]:[to_insert.type] has been blacklisted")
+ if(trait_says_no)
+ stack_trace("[parent.type]:[to_insert.type] has TRAIT_NO_STORAGE_INSERT")
+ else if(user)
+ user.balloon_alert(user, "can't hold!")
+ return FALSE
if(HAS_TRAIT(to_insert, TRAIT_NODROP))
- if(messages && user)
- user.balloon_alert(user, "stuck on your hand!")
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:[to_insert.type] has TRAIT_NODROP")
+ else if(user)
+ user.balloon_alert(user, "stuck on your hand!")
return FALSE
- // this is valid if the container our location is being held in is a storage item
- var/datum/storage/bigger_fish = parent.loc.atom_storage
+ // this is valid if the container our location is being held in is a storage item, warddrobe subsystem inits our parent in nullspace so we have to check for that
+ var/datum/storage/bigger_fish = parent.loc?.atom_storage
if(bigger_fish && bigger_fish.max_specific_storage < max_specific_storage)
- if(messages && user)
- user.balloon_alert(user, "[LOWER_TEXT(parent.loc.name)] is in the way!")
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:[LOWER_TEXT(parent.loc.type)] is in the way!")
+ else if(user)
+ user.balloon_alert(user, "[LOWER_TEXT(parent.loc.name)] is in the way!")
return FALSE
if(isitem(parent))
var/obj/item/item_parent = parent
var/datum/storage/smaller_fish = to_insert.atom_storage
if(smaller_fish && !allow_big_nesting && to_insert.w_class >= item_parent.w_class)
- if(messages && user)
- user.balloon_alert(user, "too big!")
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]:[to_insert.type] has an internal storage of weight [to_insert.w_class] that does not allow nested storage inside of parent of weight [item_parent.w_class]")
+ else if(user)
+ user.balloon_alert(user, "too big!")
return FALSE
return TRUE
@@ -457,7 +509,6 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
SEND_SIGNAL(src, COMSIG_STORAGE_STORED_ITEM, to_insert, user, force)
to_insert.forceMove(real_location)
item_insertion_feedback(user, to_insert, override)
- parent.update_appearance()
return TRUE
/// Since items inside storages ignore transparency for QOL reasons, we're tracking when things are dropped onto them instead of our UI elements
@@ -527,10 +578,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
if(animated)
animate_parent()
- if(override)
- return
-
- if(silent)
+ if(override || silent)
return
if(do_rustle && rustle_sound)
diff --git a/code/datums/storage/subtypes/backpack.dm b/code/datums/storage/subtypes/backpack.dm
deleted file mode 100644
index a2a1a13fcd4..00000000000
--- a/code/datums/storage/subtypes/backpack.dm
+++ /dev/null
@@ -1,18 +0,0 @@
-/datum/storage/backpack
- max_total_storage = 21
- max_slots = 21
-
-/datum/storage/backpack/New(
- atom/parent,
- max_slots,
- max_specific_storage,
- max_total_storage,
-)
- . = ..()
- var/static/list/exception_cache = typecacheof(list(/obj/item/fish_tank))
- exception_hold = exception_cache
-
-/datum/storage/backpack/santabag
- max_total_storage = 60
- max_slots = 21
- max_specific_storage = WEIGHT_CLASS_NORMAL
diff --git a/code/datums/storage/subtypes/backpacks.dm b/code/datums/storage/subtypes/backpacks.dm
new file mode 100644
index 00000000000..dbde6f86264
--- /dev/null
+++ b/code/datums/storage/subtypes/backpacks.dm
@@ -0,0 +1,38 @@
+///Regular backpack
+/datum/storage/backpack
+ max_total_storage = 21
+ max_slots = 21
+
+/datum/storage/backpack/New(
+ atom/parent,
+ max_slots,
+ max_specific_storage,
+ max_total_storage,
+)
+ . = ..()
+
+ set_holdable(exception_hold_list = /obj/item/fish_tank)
+
+///Sadle bag
+/datum/storage/backpack/sadle_bag
+ max_total_storage = 26
+
+///Satchel flat
+/datum/storage/backpack/satchel
+ max_total_storage = 15
+ allow_big_nesting = TRUE
+
+/datum/storage/backpack/satchel/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(cant_hold_list = /obj/item/storage/backpack/satchel/flat) //muh recursive backpacks
+
+///Santa backpack
+/datum/storage/backpack/santabag
+ max_total_storage = 60
+ max_slots = 21
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+///Banner pack
+/datum/storage/backpack/bannerpack
+ max_total_storage = 27 //6 more then normal, for the tradeoff of declaring yourself an antag at all times.
diff --git a/code/datums/storage/subtypes/bags.dm b/code/datums/storage/subtypes/bags.dm
new file mode 100644
index 00000000000..90229650652
--- /dev/null
+++ b/code/datums/storage/subtypes/bags.dm
@@ -0,0 +1,370 @@
+///Normal bag
+/datum/storage/bag
+ allow_quick_gather = TRUE
+ allow_quick_empty = TRUE
+ numerical_stacking = TRUE
+
+///Trash bag
+/datum/storage/bag/trash_bag
+ max_slots = 30
+ max_total_storage = 30
+ supports_smart_equip = FALSE
+ max_specific_storage = WEIGHT_CLASS_SMALL
+
+/datum/storage/bag/trash_bag/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(cant_hold_list = /obj/item/disk/nuclear)
+
+/datum/storage/bag/trash_bag/remove_single(mob/removing, obj/item/thing, atom/remove_to_loc, silent)
+ real_location.visible_message(
+ span_notice("[removing] starts fishing around inside [parent]."),
+ span_notice("You start digging around in [parent] to try and pull something out."),
+ )
+ if(!do_after(removing, 1.5 SECONDS, parent))
+ return FALSE
+
+ return ..()
+
+///Bluespace trash bag
+/datum/storage/bag/trash_bag/bluespace
+ max_slots = 60
+ max_total_storage = 60
+
+///Ore bag
+/datum/storage/bag/ore_bag
+ max_total_storage = 50
+ numerical_stacking = TRUE
+ allow_quick_empty = TRUE
+ allow_quick_gather = TRUE
+ silent_for_user = TRUE
+ max_specific_storage = WEIGHT_CLASS_HUGE
+
+/datum/storage/bag/ore_bag/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/stack/ore)
+
+///Bluespace ore bag
+/datum/storage/bag/ore_bag/bluespace
+ max_slots = INFINITY
+ max_specific_storage = INFINITY
+ max_total_storage = INFINITY
+
+///Plant bag
+/datum/storage/bag/plants
+ max_slots = 100
+ max_total_storage = 100
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+/datum/storage/bag/plants/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/food/grown,
+ /obj/item/graft,
+ /obj/item/grown,
+ /obj/item/food/honeycomb,
+ /obj/item/seeds,
+ ))
+
+///Sheet snatcher bag
+/datum/storage/bag/sheet_snatcher
+ max_total_storage = 150
+ allow_quick_empty = TRUE
+ allow_quick_gather = TRUE
+ numerical_stacking = TRUE
+
+/datum/storage/bag/sheet_snatcher/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(
+ can_hold_list = list(
+ /obj/item/stack/sheet
+ ),
+ cant_hold_list = list(
+ /obj/item/stack/sheet/mineral/sandstone,
+ /obj/item/stack/sheet/mineral/wood,
+ ),
+ )
+
+///Sheet snatcher debug bag
+/datum/storage/bag/sheet_snatcher/debug/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/stack)
+
+///Sheet snatcher cyborg bag
+/datum/storage/bag/sheet_snatcher_cyborg
+ max_total_storage = 250
+
+///Book bag
+/datum/storage/bag/books
+ max_slots = 7
+ max_total_storage = 21
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+/datum/storage/bag/books/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/book,
+ /obj/item/spellbook,
+ /obj/item/poster,
+ ))
+
+///Tray bag
+/datum/storage/bag/tray
+ max_slots = 8
+ max_total_storage = 16
+ insert_preposition = "on"
+ max_specific_storage = WEIGHT_CLASS_BULKY //Plates are required bulky to keep them out of backpacks
+
+/datum/storage/bag/tray/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(
+ can_hold_list = list(
+ /obj/item/cigarette,
+ /obj/item/food,
+ /obj/item/kitchen,
+ /obj/item/lighter,
+ /obj/item/organ,
+ /obj/item/plate,
+ /obj/item/reagent_containers/condiment,
+ /obj/item/reagent_containers/cup,
+ /obj/item/rollingpaper,
+ /obj/item/storage/box/gum,
+ /obj/item/storage/box/matches,
+ /obj/item/storage/fancy,
+ /obj/item/trash,
+ ),
+ cant_hold_list = list(
+ /obj/item/plate/oven_tray,
+ /obj/item/reagent_containers/cup/soup_pot,
+ ),
+ ) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Food Containers, Food Trash, Organs, Tobacco Products, Lighters, and Kitchen Tools.
+
+///Chemistry bag
+/datum/storage/bag/chemistry
+ max_slots = 50
+ max_total_storage = 200
+
+/datum/storage/bag/chemistry/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/reagent_containers/chem_pack,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/cup/glass/waterbottle,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/medigel,
+ /obj/item/reagent_containers/applicator,
+ /obj/item/reagent_containers/syringe,
+ ))
+
+///Bio bag
+/datum/storage/bag/bio
+ max_slots = 25
+ max_total_storage = 200
+
+/datum/storage/bag/bio/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/bodypart,
+ /obj/item/food/monkeycube,
+ /obj/item/healthanalyzer,
+ /obj/item/organ,
+ /obj/item/reagent_containers/blood,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/hypospray/medipen,
+ /obj/item/reagent_containers/syringe,
+ ))
+
+///Science bag
+/datum/storage/bag/science
+ max_slots = 25
+ max_total_storage = 200
+
+/datum/storage/bag/science/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/bodypart,
+ /obj/item/food/deadmouse,
+ /obj/item/food/monkeycube,
+ /obj/item/organ,
+ /obj/item/petri_dish,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/slime_extract,
+ /obj/item/swab,
+ ))
+
+///Construction bag
+/datum/storage/bag/construction
+ max_total_storage = 100
+ max_slots = 50
+ max_specific_storage = WEIGHT_CLASS_SMALL
+
+/datum/storage/bag/construction/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/assembly,
+ /obj/item/circuitboard,
+ /obj/item/electronics,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/stack/cable_coil,
+ /obj/item/stack/ore/bluespace_crystal,
+ /obj/item/stock_parts,
+ /obj/item/wallframe/camera,
+ ))
+
+///Harpoon quiver
+/datum/storage/bag/harpoon_quiver
+ max_specific_storage = WEIGHT_CLASS_TINY
+ max_slots = 40
+ max_total_storage = 100
+
+/datum/storage/bag/harpoon_quiver/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/ammo_casing/harpoon)
+
+///New bar quiver
+/datum/storage/bag/rebar_quiver
+ max_specific_storage = WEIGHT_CLASS_TINY
+ max_slots = 10
+ max_total_storage = 15
+
+/datum/storage/bag/rebar_quiver/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/ammo_casing/rebar,
+ /obj/item/ammo_casing/rebar/syndie,
+ /obj/item/ammo_casing/rebar/healium,
+ /obj/item/ammo_casing/rebar/hydrogen,
+ /obj/item/ammo_casing/rebar/zaukerite,
+ /obj/item/ammo_casing/rebar/paperball,
+ ))
+
+///Syndicate rebar quiver
+/datum/storage/bag/rebar_quiver/syndicate
+ max_slots = 20
+ max_total_storage = 20
+
+///Garment bag
+/datum/storage/bag/garment
+ max_slots = 18
+ max_total_storage = 200
+ max_specific_storage = WEIGHT_CLASS_BULKY
+ numerical_stacking = FALSE
+ insert_preposition = "in"
+
+/datum/storage/bag/garment/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/clothing)
+
+
+///Mail storage bag
+/datum/storage/bag/mail
+ max_total_storage = 42
+ max_slots = 21
+ numerical_stacking = FALSE
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+/datum/storage/bag/mail/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/mail,
+ /obj/item/delivery/small,
+ /obj/item/paper
+ ))
+
+///Fishing bag
+/datum/storage/bag/fishing
+ max_total_storage = 24 // Up to 8 normal fish
+ max_slots = 21
+
+/datum/storage/bag/fishing/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdables)
+ . = ..()
+
+ if(!length(holdables))
+ holdables = list(/obj/item/fish)
+
+ set_holdable(/obj/item/fish)
+
+///Carpskin fishing bag
+/datum/storage/bag/fishing/carpskin
+ max_total_storage = 42 // Up to 14 normal fish, but we're assuming that you'll be storing a bunch of gear as well
+
+/datum/storage/bag/fishing/carpskin/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdables)
+ holdables = list(
+ /obj/item/fish,
+ /obj/item/fishing_line,
+ /obj/item/fishing_hook,
+ /obj/item/fishing_lure,
+ /obj/item/fish_analyzer,
+ /obj/item/bait_can,
+ )
+
+ return ..()
+
+///Dutchmen bag
+/datum/storage/bag/dutchmen
+ max_slots = 19
+ max_total_storage = 21
+
+///Money bag
+/datum/storage/bag/money
+ max_slots = 40
+ max_specific_storage = 40
+
+/datum/storage/bag/money/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/coin,
+ /obj/item/stack/spacecash,
+ /obj/item/holochip
+ ))
+
+///Bag of quivers
+/datum/storage/bag/quivers
+ max_specific_storage = WEIGHT_CLASS_TINY
+ max_slots = 40
+ max_total_storage = 100
+ numerical_stacking = TRUE
+
+/datum/storage/bag/quivers/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/ammo_casing/arrow)
+
+///Bag of smaller quivers
+/datum/storage/bag/quivers/lesser
+ max_slots = 10
+
+///Endless quivers
+/datum/storage/bag/quivers/endless
+ max_slots = 1
+
+/datum/storage/bag/quivers/endless/handle_exit(datum/source, obj/item/gone)
+ . = ..()
+
+ var/obj/item/storage/bag/quiver/store = source
+
+ new store.arrow_path(store)
diff --git a/code/datums/storage/subtypes/belts.dm b/code/datums/storage/subtypes/belts.dm
new file mode 100644
index 00000000000..94e7ea24263
--- /dev/null
+++ b/code/datums/storage/subtypes/belts.dm
@@ -0,0 +1,362 @@
+///Utility belt
+/datum/storage/utility_belt
+ max_total_storage = 21
+
+/datum/storage/chief_utility_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(GLOB.tool_items + list(
+ /obj/item/clothing/gloves,
+ /obj/item/radio,
+ /obj/item/melee/sickly_blade/lock,
+ /obj/item/reagent_containers/cup/soda_cans,
+ ))
+
+///Sabre belt
+/datum/storage/sabre_belt
+ max_slots = 1
+ do_rustle = FALSE
+ max_specific_storage = WEIGHT_CLASS_BULKY
+ click_alt_open = FALSE
+
+/datum/storage/sabre_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/melee/sabre)
+
+///Medical belt
+/datum/storage/medical_belt
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+ max_total_storage = 21
+
+/datum/storage/medical_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/bikehorn/rubberducky,
+ /obj/item/blood_filter,
+ /obj/item/bonesetter,
+ /obj/item/cautery,
+ /obj/item/circular_saw,
+ /obj/item/clothing/glasses,
+ /obj/item/clothing/gloves,
+ /obj/item/clothing/neck/stethoscope,
+ /obj/item/clothing/mask/breath,
+ /obj/item/clothing/mask/muzzle,
+ /obj/item/clothing/mask/surgical,
+ /obj/item/clothing/head/utility/surgerycap,
+ /obj/item/construction/plumbing,
+ /obj/item/dnainjector,
+ /obj/item/extinguisher/mini,
+ /obj/item/flashlight/pen,
+ /obj/item/geiger_counter,
+ /obj/item/gun/syringe/syndicate,
+ /obj/item/healthanalyzer,
+ /obj/item/hemostat,
+ /obj/item/holosign_creator/medical,
+ /obj/item/implant,
+ /obj/item/implantcase,
+ /obj/item/implanter,
+ /obj/item/lazarus_injector,
+ /obj/item/lighter,
+ /obj/item/pinpointer/crew,
+ /obj/item/plunger,
+ /obj/item/radio,
+ /obj/item/reagent_containers/blood,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/reagent_containers/medigel,
+ /obj/item/reagent_containers/applicator,
+ /obj/item/reagent_containers/spray,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/retractor,
+ /obj/item/scalpel,
+ /obj/item/shears,
+ /obj/item/stack/medical,
+ /obj/item/stack/sticky_tape, //surgical tape
+ /obj/item/stamp,
+ /obj/item/sensor_device,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/storage/pill_bottle,
+ /obj/item/surgical_drapes, //for true paramedics
+ /obj/item/surgicaldrill,
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/wrench/medical,
+ /obj/item/knife/ritual,
+ /obj/item/flesh_shears,
+ ))
+
+//Security belt
+/datum/storage/security_belt
+ max_slots = 5
+ open_sound = 'sound/items/handling/holster_open.ogg'
+ open_sound_vary = TRUE
+ rustle_sound = null
+
+/datum/storage/security_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/ammo_box,
+ /obj/item/ammo_casing/shotgun,
+ /obj/item/assembly/flash/handheld,
+ /obj/item/clothing/glasses,
+ /obj/item/clothing/gloves,
+ /obj/item/flashlight/seclite,
+ /obj/item/food/donut,
+ /obj/item/grenade,
+ /obj/item/holosign_creator/security,
+ /obj/item/knife/combat,
+ /obj/item/melee/baton,
+ /obj/item/radio,
+ /obj/item/reagent_containers/spray/pepper,
+ /obj/item/restraints/handcuffs,
+ /obj/item/restraints/legcuffs/bola,
+ ))
+
+///Webbing security belt
+/datum/storage/security_belt/webbing
+ max_slots = 6
+
+
+///Mining belt
+/datum/storage/mining_belt
+ max_slots = 6
+ max_total_storage = 20
+
+/datum/storage/mining_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/analyzer,
+ /obj/item/clothing/gloves,
+ /obj/item/crowbar,
+ /obj/item/extinguisher/mini,
+ /obj/item/flashlight,
+ /obj/item/gps,
+ /obj/item/mining_stabilizer,
+ /obj/item/key/lasso,
+ /obj/item/knife,
+ /obj/item/lighter,
+ /obj/item/mining_scanner,
+ /obj/item/multitool,
+ /obj/item/organ/monster_core,
+ /obj/item/pickaxe,
+ /obj/item/radio,
+ /obj/item/reagent_containers/cup/glass,
+ /obj/item/reagent_containers/cup/glass/bottle,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/reagent_containers/applicator/pill,
+ /obj/item/resonator,
+ /obj/item/screwdriver,
+ /obj/item/shovel,
+ /obj/item/stack/cable_coil,
+ /obj/item/stack/marker_beacon,
+ /obj/item/stack/medical,
+ /obj/item/stack/ore,
+ /obj/item/stack/sheet/animalhide,
+ /obj/item/stack/sheet/bone,
+ /obj/item/stack/sheet/sinew,
+ /obj/item/storage/bag/ore,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/storage/pill_bottle,
+ /obj/item/survivalcapsule,
+ /obj/item/t_scanner/adv_mining_scanner,
+ /obj/item/weldingtool,
+ /obj/item/wirecutters,
+ /obj/item/wrench,
+ /obj/item/wormhole_jaunter,
+ /obj/item/skeleton_key,
+ ))
+
+///Mining belt primitive
+/datum/storage/mining_belt/primitive
+ max_slots = 5
+
+///Soulstone belt
+/datum/storage/soulstone_belt
+ max_slots = 6
+
+/datum/storage/soulstone_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/soulstone)
+
+///Champion belt
+/datum/storage/champion_belt
+ max_slots = 1
+
+/datum/storage/champion_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/clothing/mask/luchador)
+
+///Militray belt
+/datum/storage/military_belt
+ max_specific_storage = WEIGHT_CLASS_SMALL
+
+///Military belt snacks
+/datum/storage/military_belt/snacks
+ max_slots = 6
+
+/datum/storage/military_belt/snacks/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/food,
+ /obj/item/reagent_containers/cup/glass,
+ /obj/item/reagent_containers/cup/soda_cans,
+ ))
+
+///Military belt assault
+/datum/storage/military_belt/assault
+ max_slots = 6
+
+///Grenade belt
+/datum/storage/grenade_belt
+ max_slots = 30
+ numerical_stacking = TRUE
+ max_total_storage = 60
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+/datum/storage/grenade_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/food/grown/cherry_bomb,
+ /obj/item/food/grown/firelemon,
+ /obj/item/grenade,
+ /obj/item/grenade/c4,
+ /obj/item/lighter,
+ /obj/item/multitool,
+ /obj/item/reagent_containers/cup/glass/bottle/molotov,
+ /obj/item/screwdriver,
+ ))
+
+///Wand belt
+/datum/storage/wand_belt
+ max_slots = 7
+
+/datum/storage/wand_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/gun/magic/wand)
+
+///Janitor belt
+/datum/storage/janitor_belt
+ max_slots = 6
+
+/datum/storage/janitor_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/access_key,
+ /obj/item/assembly/mousetrap,
+ /obj/item/clothing/gloves,
+ /obj/item/flashlight,
+ /obj/item/forcefield_projector,
+ /obj/item/grenade/chem_grenade,
+ /obj/item/holosign_creator,
+ /obj/item/key/janitor,
+ /obj/item/lightreplacer,
+ /obj/item/melee/flyswatter,
+ /obj/item/paint/paint_remover,
+ /obj/item/plunger,
+ /obj/item/pushbroom,
+ /obj/item/reagent_containers/spray,
+ /obj/item/soap,
+ /obj/item/wirebrush,
+ ))
+
+///Bandolier belt
+/datum/storage/bandolier_belt
+ max_slots = 24
+ max_total_storage = 24
+ allow_quick_gather = TRUE
+ allow_quick_empty = TRUE
+ numerical_stacking = TRUE
+
+/datum/storage/bandolier_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/ammo_casing/strilka310,
+ /obj/item/ammo_casing/shotgun,
+ /obj/item/ammo_casing/c357,
+ /obj/item/ammo_casing/junk,
+ ))
+
+///Fanny pack
+/datum/storage/fanny_pack
+ max_slots = 3
+ max_specific_storage = WEIGHT_CLASS_SMALL
+ silent = TRUE
+
+///Green sabre
+/datum/storage/green_sabre_belt
+ max_slots = 1
+ do_rustle = FALSE
+ max_specific_storage = WEIGHT_CLASS_BULKY
+ click_alt_open = FALSE
+
+/datum/storage/green_sabre_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/melee/parsnip_sabre)
+
+///Plant belt
+/datum/storage/plant_belt
+ max_slots = 6
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+/datum/storage/plant_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/cultivator,
+ /obj/item/geneshears,
+ /obj/item/graft,
+ /obj/item/gun/energy/floragun,
+ /obj/item/hatchet,
+ /obj/item/plant_analyzer,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/spray/pestspray,
+ /obj/item/reagent_containers/spray/plantbgone,
+ /obj/item/secateurs,
+ /obj/item/seeds,
+ /obj/item/shovel/spade,
+ ))
+
+///unfathomable curio belt
+/datum/storage/unfathomable_curio_belt
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+ max_total_storage = 21
+
+/datum/storage/unfathomable_curio_belt/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/ammo_box/strilka310/lionhunter,
+ /obj/item/heretic_labyrinth_handbook,
+ /obj/item/bodypart, // Bodyparts are often used in rituals.
+ /obj/item/clothing/neck/eldritch_amulet,
+ /obj/item/clothing/neck/heretic_focus,
+ /obj/item/codex_cicatrix,
+ /obj/item/eldritch_potion,
+ /obj/item/food/grown/poppy, // Used to regain a Living Heart.
+ /obj/item/food/grown/harebell, // Used to reroll targets
+ /obj/item/melee/rune_carver,
+ /obj/item/melee/sickly_blade,
+ /obj/item/organ, // Organs are also often used in rituals.
+ /obj/item/reagent_containers/cup/beaker/eldritch,
+ /obj/item/stack/sheet/glass, // Glass is often used by moon heretics
+ ))
+
+///Chameleon belt
+/datum/storage/chameleon_belt
+ silent = TRUE
diff --git a/code/datums/storage/subtypes/boxes.dm b/code/datums/storage/subtypes/boxes.dm
new file mode 100644
index 00000000000..606d6f3c6a7
--- /dev/null
+++ b/code/datums/storage/subtypes/boxes.dm
@@ -0,0 +1,328 @@
+///Small box storage
+/datum/storage/box
+ open_sound = 'sound/items/handling/cardboard_box/cardboard_box_open.ogg'
+ rustle_sound = 'sound/items/handling/cardboard_box/cardboard_box_rustle.ogg'
+ max_specific_storage = WEIGHT_CLASS_SMALL
+
+///Flat box
+/datum/storage/box/flat
+ max_slots = 3
+
+///Coffee box
+/datum/storage/box/coffee
+ max_slots = 5
+
+///Ingredient box
+/datum/storage/box/ingredients
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+///Coffee box
+/datum/storage/box/coffee/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/food/grown/coffee)
+
+///Donk pocket box
+/datum/storage/box/donk_pockets/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/food/donkpocket)
+
+///Bubble gum box
+/datum/storage/box/bubble_gum
+ max_slots = 4
+
+/datum/storage/box/bubble_gum/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/food/bubblegum)
+
+///Snappops box
+/datum/storage/box/snappops
+ max_slots = 8
+
+/datum/storage/box/snappops/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/toy/snappop)
+
+///Minor modkits box
+/datum/storage/box/minor_modkits
+ numerical_stacking = TRUE
+
+/datum/storage/box/minor_modkits/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/borg/upgrade/modkit,
+ /obj/item/crusher_trophy
+ ))
+
+///Bandages box
+/datum/storage/box/bandages
+ max_slots = 6
+
+/datum/storage/box/bandages/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/stack/medical/bandage,
+ /obj/item/reagent_containers/applicator/pill,
+ /obj/item/reagent_containers/applicator/patch,
+ ))
+
+///Monkey cubes box
+/datum/storage/box/monkey_cubes/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/food/monkeycube)
+
+///Gorilla cubes box
+/datum/storage/box/gorilla_cubes
+ max_slots = 3
+
+/datum/storage/box/gorilla_cubes/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/food/monkeycube)
+
+///Match box
+/datum/storage/box/matches
+ max_slots = 10
+
+/datum/storage/box/matches/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/match)
+
+///Lights box
+/datum/storage/box/lights
+ max_slots = 21
+ max_total_storage = 21 * WEIGHT_CLASS_NORMAL
+ allow_quick_gather = FALSE //temp workaround to re-enable filling the light replacer with the box
+
+/datum/storage/box/lights/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(/obj/item/light/tube, /obj/item/light/bulb))
+
+///Balloon box
+/datum/storage/box/balloons
+ max_slots = 24
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+ max_total_storage = 24 * WEIGHT_CLASS_NORMAL
+ allow_quick_gather = FALSE
+
+/datum/storage/box/balloons/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/toy/balloon/long)
+
+///Wizard box
+/datum/storage/box/wizard
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+///Syndicate box
+/datum/storage/box/syndicate
+ allow_big_nesting = TRUE
+
+///Syndicate contractor box
+/datum/storage/box/syndicate/contractor
+ max_total_storage = 25
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///Syndicate contractor kit box
+/datum/storage/box/syndicate/contract_kit
+ allow_big_nesting = TRUE
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+///Syndicate contractor loadout box
+/datum/storage/box/syndicate/contractor_loadout
+ max_slots = 12
+ max_total_storage = 27
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///Syndicate conractor loadout
+/datum/storage/box/syndicate/contractor_loadout
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///Stickers box
+/datum/storage/box/stickers
+ max_slots = 8
+
+/datum/storage/box/stickers/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/sticker)
+
+///Holy box
+/datum/storage/box/holy
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+/datum/storage/box/holy/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/clothing)
+
+///Holy Caplin box
+/datum/storage/box/holy/follower
+ max_total_storage = 15
+
+///Hero box
+/datum/storage/box/hero
+ max_slots = 12
+ max_total_storage = 30
+ max_specific_storage = WEIGHT_CLASS_BULKY
+ allow_big_nesting = TRUE
+
+///Floor camo box
+/datum/storage/box/floor_camo
+ allow_big_nesting = TRUE
+
+///Skub box
+/datum/storage/box/stickers/skub
+ max_slots = 3
+
+/datum/storage/box/stickers/skub/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(exception_hold_list = list(
+ /obj/item/skub,
+ /obj/item/clothing/suit/costume/wellworn_shirt/skub,
+ ))
+
+///Anti skub box
+/datum/storage/box/stickers/anti_skub/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(exception_hold_list = /obj/item/clothing/suit/costume/wellworn_shirt/skub)
+
+///SyndiKit box
+/datum/storage/box/syndie_kit
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+///SyndiKit space box
+/datum/storage/box/syndie_kit/space/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/clothing/suit/space/syndicate,
+ /obj/item/clothing/head/helmet/space/syndicate,
+ ))
+
+///SyndiKit chemical box
+/datum/storage/box/syndie_kit/chemical
+ max_slots = 15
+ max_total_storage = 15
+
+///SyndiKit Rebar x bow box
+/datum/storage/box/syndie_kit/rebarxbowsyndie
+ allow_big_nesting = TRUE
+
+///SyndiKit mail counterfeit box
+/datum/storage/box/syndie_kit/mail_counterfeit
+ allow_big_nesting = TRUE
+ max_total_storage = 6 * WEIGHT_CLASS_NORMAL
+
+///SyndiKit cowboy box
+/datum/storage/box/syndie_kit/cowboy
+ max_total_storage = 20
+ allow_big_nesting = TRUE
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///SyniKit induction kit
+/datum/storage/box/syndie_kit/induction_kit
+ allow_big_nesting = TRUE
+
+///SyndiKit centcom costume box
+/datum/storage/box/syndie_kit/centcom_costume
+ max_slots = 8
+ max_total_storage = 24
+ allow_big_nesting = TRUE
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///SyndiKit tuberculosis grenade box
+/datum/storage/box/syndie_kit/tuberculosisgrenade
+ max_slots = 8
+
+///SyndiKit demoman box
+/datum/storage/box/syndie_kit/demoman
+ allow_big_nesting = TRUE
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///SyndiKit Imp death rattle box
+/datum/storage/box/syndie_kit/imp_deathrattle
+ max_slots = 9
+
+///SyndiKit pinata box
+/datum/storage/box/syndie_kit/pinata
+ max_specific_storage = WEIGHT_CLASS_BULKY
+ allow_big_nesting = TRUE
+
+///SyndiKit chaemelon box
+/datum/storage/box/syndie_kit/chaemelon
+ max_slots = 15
+ max_total_storage = 38
+ allow_big_nesting = TRUE
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///SyndiKit throwing weapons box
+/datum/storage/box/syndie_kit/weapons
+ max_slots = 9 // 5 + 2 + 2
+ max_total_storage = 18 // 5*2 + 2*1 + 3*2
+
+/datum/storage/box/syndie_kit/weapons/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/restraints/legcuffs/bola/tactical,
+ /obj/item/paperplane/syndicate,
+ /obj/item/throwing_star,
+ ))
+
+///SyndiKit cutouts box
+/datum/storage/box/syndie_kit/cutouts
+ max_slots = 4
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///Fishing lures box
+/datum/storage/box/fishing_lures/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ set_holdable(list(
+ /obj/item/fishing_lure,
+ /obj/item/paper/lures_instructions
+ )) //can only hold lures
+
+ //adds an extra slot, so we can put back the lures even if we didn't take out the instructions.
+ max_slots = length(typesof(/obj/item/fishing_lure)) + 1
+ max_total_storage = WEIGHT_CLASS_SMALL * (max_slots + 1)
+
+ return ..()
+
+///Stock parts box
+/datum/storage/box/stockparts
+ max_slots = 15
+ max_total_storage = 15 * WEIGHT_CLASS_SMALL
+
+///Tiziran cans box
+/datum/storage/box/tiziran_cans
+ max_slots = 8
+ max_total_storage = 8 * WEIGHT_CLASS_SMALL
+
+///Tiziran meat box
+/datum/storage/box/tiziran_meats
+ max_slots = 10
+ max_total_storage = 10 * WEIGHT_CLASS_SMALL
+
+///Mothic goods box
+/datum/storage/box/mothic_goods
+ max_slots = 12
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+///Mothic cans sauces box
+/datum/storage/box/mothic_cans_sauces
+ max_slots = 8
+ max_total_storage = 8 * WEIGHT_CLASS_SMALL
+
+///Debug box
+/datum/storage/box/debug_tools
+ allow_big_nesting = TRUE
diff --git a/code/datums/storage/subtypes/drone.dm b/code/datums/storage/subtypes/drone.dm
deleted file mode 100644
index 2df8f4c6279..00000000000
--- a/code/datums/storage/subtypes/drone.dm
+++ /dev/null
@@ -1,26 +0,0 @@
-/datum/storage/drone
- max_total_storage = 40
- max_specific_storage = WEIGHT_CLASS_NORMAL
- max_slots = 10
- do_rustle = FALSE
-
-/datum/storage/drone/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
- . = ..()
-
- var/static/list/drone_builtins = list(
- /obj/item/crowbar/drone,
- /obj/item/screwdriver/drone,
- /obj/item/wrench/drone,
- /obj/item/weldingtool/drone,
- /obj/item/wirecutters/drone,
- /obj/item/multitool/drone,
- /obj/item/pipe_dispenser/drone,
- /obj/item/t_scanner/drone,
- /obj/item/analyzer/drone,
- /obj/item/soap/drone,
- )
-
- set_holdable(drone_builtins)
-
-/datum/storage/drone/dump_content_at(atom/dest_object, dump_loc, mob/user)
- return //no dumping of contents allowed
diff --git a/code/datums/storage/subtypes/duffel_bag.dm b/code/datums/storage/subtypes/dufflebags.dm
similarity index 76%
rename from code/datums/storage/subtypes/duffel_bag.dm
rename to code/datums/storage/subtypes/dufflebags.dm
index bb3a236d38b..99e15dc2f25 100644
--- a/code/datums/storage/subtypes/duffel_bag.dm
+++ b/code/datums/storage/subtypes/dufflebags.dm
@@ -1,3 +1,4 @@
+//Regular duffle bag
/datum/storage/duffel
max_total_storage = 30
max_slots = 21
@@ -9,8 +10,8 @@
max_total_storage,
)
. = ..()
- var/static/list/exception_cache = typecacheof(list(/obj/item/fish_tank))
- exception_hold = exception_cache
+
+ set_holdable(exception_hold_list = /obj/item/fish_tank)
// Syndi bags get some FUN extras
// You can fit any 2 bulky objects (assuming they're in the whitelist)
@@ -68,6 +69,7 @@
/obj/item/clothing/suit/utility,
// Storage
/obj/item/storage/bag/money,
+ /obj/item/storage/belt/utility/syndicate,
// Heads!
/obj/item/bodypart/head,
// Fish
@@ -75,9 +77,19 @@
/obj/item/fish_tank,
)
- // We keep the type list and the typecache list separate...
- var/static/list/exception_cache = typecacheof(exception_type_list)
- exception_hold = exception_cache
+ set_holdable(exception_hold_list = exception_type_list)
- //...So we can run this without it generating a line for every subtype.
- can_hold_description = generate_hold_desc(exception_type_list)
+///Syndicate firestarter
+/datum/storage/duffel/syndicate/firestarter
+ allow_big_nesting = TRUE
+
+///Syndicate ammo mech box
+/datum/storage/duffel/syndicate/ammo_mech
+ exception_max = 5
+ allow_big_nesting = TRUE
+
+///Syndicate ammo mauler box
+/datum/storage/duffel/syndicate/ammo_mauler
+ exception_max = 9
+ max_total_storage = 36
+ allow_big_nesting = TRUE
diff --git a/code/datums/storage/subtypes/holsters.dm b/code/datums/storage/subtypes/holsters.dm
new file mode 100644
index 00000000000..35bc54cd898
--- /dev/null
+++ b/code/datums/storage/subtypes/holsters.dm
@@ -0,0 +1,123 @@
+///Regular holster
+/datum/storage/holster
+ max_slots = 1
+ max_total_storage = 16
+ open_sound = 'sound/items/handling/holster_open.ogg'
+ open_sound_vary = TRUE
+
+/datum/storage/holster/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdable_override)
+ . = ..()
+
+ if(!length(holdable_override))
+ holdable_override = list(
+ /obj/item/gun/ballistic/automatic/pistol,
+ /obj/item/gun/ballistic/revolver,
+ /obj/item/gun/energy/e_gun/mini,
+ /obj/item/gun/energy/disabler,
+ /obj/item/gun/energy/dueling,
+ /obj/item/food/grown/banana,
+ /obj/item/gun/energy/laser/thermal,
+ /obj/item/gun/ballistic/rifle/boltaction, //fits if you make it an obrez
+ /obj/item/gun/energy/laser/captain,
+ /obj/item/gun/energy/e_gun/hos,
+ )
+
+ set_holdable(holdable_override)
+
+///Energy holster
+/datum/storage/holster/energy
+ max_slots = 2
+
+/datum/storage/holster/energy/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdable_override)
+ holdable_override = list(
+ /obj/item/gun/energy/e_gun/mini,
+ /obj/item/gun/energy/disabler,
+ /obj/item/gun/energy/dueling,
+ /obj/item/food/grown/banana,
+ /obj/item/gun/energy/laser/thermal,
+ /obj/item/gun/energy/recharge/ebow,
+ /obj/item/gun/energy/laser/captain,
+ /obj/item/gun/energy/e_gun/hos,
+ )
+
+ return ..()
+
+///Detective holster
+/datum/storage/holster/detective
+ max_slots = 3
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+/datum/storage/holster/detective/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdable_override)
+ holdable_override = list(
+ /obj/item/gun/ballistic/automatic/pistol,
+ /obj/item/ammo_box/magazine/m9mm, // Pistol magazines.
+ /obj/item/ammo_box/magazine/m9mm_aps,
+ /obj/item/ammo_box/magazine/m10mm,
+ /obj/item/ammo_box/magazine/m45,
+ /obj/item/ammo_box/magazine/m50,
+ /obj/item/gun/ballistic/revolver,
+ /obj/item/ammo_box/c38, // Revolver speedloaders.
+ /obj/item/ammo_box/a357,
+ /obj/item/ammo_box/strilka310,
+ /obj/item/ammo_box/magazine/toy/pistol,
+ /obj/item/gun/energy/e_gun/mini,
+ /obj/item/gun/energy/disabler,
+ /obj/item/gun/energy/dueling,
+ /obj/item/gun/energy/laser/thermal,
+ /obj/item/gun/energy/laser/captain,
+ /obj/item/gun/energy/e_gun/hos,
+ /obj/item/gun/ballistic/rifle/boltaction, //fits if you make it an obrez
+ )
+
+ return ..()
+
+///Chameleon holster
+/datum/storage/holster/chameleon
+ max_slots = 2
+ silent = TRUE
+
+/datum/storage/holster/chameleon/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdable_override)
+ holdable_override = list(
+ /obj/item/gun/ballistic/automatic/pistol,
+ /obj/item/ammo_box/magazine/m9mm,
+ /obj/item/ammo_box/magazine/m9mm_aps,
+ /obj/item/ammo_box/magazine/m10mm,
+ /obj/item/ammo_box/magazine/m45,
+ /obj/item/ammo_box/magazine/m50,
+ /obj/item/gun/ballistic/revolver,
+ /obj/item/ammo_box/c38,
+ /obj/item/ammo_box/a357,
+ /obj/item/ammo_box/strilka310,
+ /obj/item/ammo_box/magazine/toy/pistol,
+ /obj/item/gun/energy/recharge/ebow,
+ /obj/item/gun/energy/e_gun/mini,
+ /obj/item/gun/energy/disabler,
+ /obj/item/gun/energy/dueling,
+ /obj/item/gun/energy/laser/captain,
+ /obj/item/gun/energy/e_gun/hos,
+ )
+
+ return ..()
+
+///Nukie holster
+/datum/storage/holster/nukie
+ max_slots = 2
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+/datum/storage/holster/nukie/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdable_override)
+ holdable_override = list(
+ /obj/item/gun, // ALL guns.
+ /obj/item/ammo_box/magazine, // ALL magazines.
+ /obj/item/ammo_box/c38, //There isn't a speedloader parent type, so I just put these three here by hand.
+ /obj/item/ammo_box/a357, //I didn't want to just use /obj/item/ammo_box, because then this could hold huge boxes of ammo.
+ /obj/item/ammo_box/strilka310,
+ /obj/item/ammo_casing, // For shotgun shells, rockets, launcher grenades, and a few other things.
+ /obj/item/grenade, // All regular grenades, the big grenade launcher fires these.
+ )
+
+ return ..()
+
+///Nukie cowboy holster
+/datum/storage/holster/nukie/cowboy
+ max_slots = 3
+ max_specific_storage = WEIGHT_CLASS_NORMAL
diff --git a/code/datums/storage/subtypes/implant.dm b/code/datums/storage/subtypes/implant.dm
deleted file mode 100644
index 547e79ba81c..00000000000
--- a/code/datums/storage/subtypes/implant.dm
+++ /dev/null
@@ -1,15 +0,0 @@
-/datum/storage/implant
- max_specific_storage = WEIGHT_CLASS_NORMAL
- max_total_storage = 6
- max_slots = 2
- silent = TRUE
- allow_big_nesting = TRUE
-
-/datum/storage/implant/New(
- atom/parent,
- max_slots,
- max_specific_storage,
- max_total_storage,
-)
- . = ..()
- set_holdable(cant_hold_list = /obj/item/disk/nuclear)
diff --git a/code/datums/storage/subtypes/lockboxes.dm b/code/datums/storage/subtypes/lockboxes.dm
new file mode 100644
index 00000000000..9b6db314e18
--- /dev/null
+++ b/code/datums/storage/subtypes/lockboxes.dm
@@ -0,0 +1,32 @@
+///Regular lockbox
+/datum/storage/lockbox
+ max_total_storage = 14
+ max_slots = 4
+
+///Medal lockbox
+/datum/storage/lockbox/medal
+ max_slots = 10
+ max_total_storage = 20
+ max_specific_storage = WEIGHT_CLASS_SMALL
+
+/datum/storage/lockbox/medal/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/clothing/accessory/medal)
+
+///Bit running lockbox
+/datum/storage/lockbox/bitrunning
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+ max_slots = 1
+ max_total_storage = 3
+ locked = STORAGE_NOT_LOCKED
+
+///Dueling lockbox
+/datum/storage/lockbox/dueling
+ max_specific_storage = WEIGHT_CLASS_SMALL
+ max_slots = 2
+
+/datum/storage/lockbox/dueling/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/gun/energy/dueling)
diff --git a/code/datums/storage/subtypes/medkits.dm b/code/datums/storage/subtypes/medkits.dm
new file mode 100644
index 00000000000..6809d79caa9
--- /dev/null
+++ b/code/datums/storage/subtypes/medkits.dm
@@ -0,0 +1,144 @@
+///Regular medkit
+/datum/storage/medkit
+ open_sound = 'sound/items/handling/medkit/medkit_open.ogg'
+ open_sound_vary = TRUE
+ rustle_sound = 'sound/items/handling/medkit/medkit_rustle.ogg'
+ max_specific_storage = WEIGHT_CLASS_SMALL
+
+ ///List of everything a medkit can hold
+ VAR_FINAL/static/list/obj/item/list_of_everything_medkits_can_hold = list(
+ //surgery tools
+ /obj/item/surgical_drapes,
+ /obj/item/scalpel,
+ /obj/item/circular_saw,
+ /obj/item/bonesetter,
+ /obj/item/surgicaldrill,
+ /obj/item/retractor,
+ /obj/item/cautery,
+ /obj/item/hemostat,
+ /obj/item/blood_filter,
+
+ //special tools
+ /obj/item/healthanalyzer,
+ /obj/item/dnainjector,
+ /obj/item/lazarus_injector,
+ /obj/item/implantcase,
+ /obj/item/implant,
+ /obj/item/implanter,
+
+ //stacks
+ /obj/item/stack/medical,
+ /obj/item/stack/medical/gauze,
+ /obj/item/stack/sticky_tape,
+ /obj/item/stack/medical/suture/medicated,
+ /obj/item/stack/medical/mesh/advanced,
+
+ //containers
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/applicator/pill,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/reagent_containers/medigel,
+ /obj/item/reagent_containers/spray,
+ /obj/item/reagent_containers/applicator/patch/libital,
+ /obj/item/reagent_containers/applicator/patch/aiuri,
+ /obj/item/reagent_containers/applicator/patch/synthflesh,
+ /obj/item/reagent_containers/hypospray/combat/empty,
+ /obj/item/reagent_containers/medigel/sterilizine,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/reagent_containers/blood,
+
+ //storage items
+ /obj/item/storage/box/bandages,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/storage/pill_bottle,
+ /obj/item/storage/box/bandages,
+ /obj/item/storage/box/evilmeds,
+
+ //clothing
+ /obj/item/clothing/mask/surgical,
+ /obj/item/clothing/mask/breath,
+ /obj/item/clothing/mask/breath/medical,
+ /obj/item/clothing/neck/stethoscope,
+ /obj/item/clothing/glasses/hud/health/night/science,
+ /obj/item/clothing/gloves,
+ /obj/item/clothing/mask/muzzle,
+ /obj/item/clothing/glasses,
+
+ //mod suite
+ /obj/item/mod/module/thread_ripper,
+ /obj/item/mod/module/surgical_processor/preloaded,
+ /obj/item/mod/module/defibrillator/combat,
+ /obj/item/mod/module/health_analyzer,
+
+ //misc
+ /obj/item/lighter,
+ /obj/item/sensor_device,
+ /obj/item/radio,
+ /obj/item/bikehorn/rubberducky,
+ /obj/item/shears,
+ /obj/item/geiger_counter,
+ /obj/item/flashlight/pen,
+ /obj/item/extinguisher/mini,
+ /obj/item/stamp,
+ /obj/item/wrench/medical,
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/gun/syringe/syndicate,
+ /obj/item/pinpointer/crew,
+ /obj/item/holosign_creator/medical,
+ /obj/item/healthanalyzer/advanced,
+ /obj/item/autosurgeon/syndicate/emaggedsurgerytoolset,
+ )
+
+/datum/storage/medkit/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdable_override)
+ . = ..()
+
+ if(isnull(holdable_override))
+ holdable_override = list_of_everything_medkits_can_hold
+
+ set_holdable(holdable_override)
+
+///Surgery medkit
+/datum/storage/medkit/surgery
+ max_slots = 12
+ max_total_storage = 24
+ max_specific_storage = WEIGHT_CLASS_NORMAL //holds the same equipment as a medibelt
+
+///Tatical medkit
+/datum/storage/medkit/tatical
+ max_slots = 24
+ max_total_storage = 24
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+///Tatical premium medkit
+/datum/storage/medkit/tatical/premium
+ allow_big_nesting = TRUE // so you can put back the box you took out
+ max_total_storage = 36
+
+///Corrinor medkit
+/datum/storage/medkit/coroner
+ max_slots = 14
+ max_total_storage = 24
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+
+/datum/storage/medkit/coroner/New(atom/parent, max_slots, max_specific_storage, max_total_storage, list/holdable_override)
+
+ holdable_override = list(
+ /obj/item/reagent_containers,
+ /obj/item/bodybag,
+ /obj/item/toy/crayon,
+ /obj/item/pen,
+ /obj/item/paper,
+ /obj/item/surgical_drapes,
+ /obj/item/scalpel,
+ /obj/item/retractor,
+ /obj/item/hemostat,
+ /obj/item/cautery,
+ /obj/item/autopsy_scanner,
+ )
+
+ return ..()
+
+
diff --git a/code/datums/storage/subtypes/organ_box.dm b/code/datums/storage/subtypes/organ_box.dm
deleted file mode 100644
index de1cb5f5071..00000000000
--- a/code/datums/storage/subtypes/organ_box.dm
+++ /dev/null
@@ -1,17 +0,0 @@
-/datum/storage/organ_box
-
-/datum/storage/organ_box/handle_enter(obj/item/storage/organbox/source, obj/item/arrived)
- . = ..()
-
- if(!istype(arrived) || !istype(source) || !source.coolant_to_spend())
- return
-
- arrived.freeze()
-
-/datum/storage/organ_box/handle_exit(datum/source, obj/item/gone)
- . = ..()
-
- if(!istype(gone))
- return
-
- gone.unfreeze()
diff --git a/code/datums/storage/subtypes/bag_of_holding.dm b/code/datums/storage/subtypes/others/bag_of_holding.dm
similarity index 100%
rename from code/datums/storage/subtypes/bag_of_holding.dm
rename to code/datums/storage/subtypes/others/bag_of_holding.dm
diff --git a/code/datums/storage/subtypes/cards.dm b/code/datums/storage/subtypes/others/cards.dm
similarity index 100%
rename from code/datums/storage/subtypes/cards.dm
rename to code/datums/storage/subtypes/others/cards.dm
diff --git a/code/datums/storage/subtypes/carpskin_bag.dm b/code/datums/storage/subtypes/others/carpskin_bag.dm
similarity index 100%
rename from code/datums/storage/subtypes/carpskin_bag.dm
rename to code/datums/storage/subtypes/others/carpskin_bag.dm
diff --git a/code/datums/storage/subtypes/extract_inventory.dm b/code/datums/storage/subtypes/others/extract_inventory.dm
similarity index 100%
rename from code/datums/storage/subtypes/extract_inventory.dm
rename to code/datums/storage/subtypes/others/extract_inventory.dm
diff --git a/code/datums/storage/subtypes/fish_case.dm b/code/datums/storage/subtypes/others/fish_case.dm
similarity index 82%
rename from code/datums/storage/subtypes/fish_case.dm
rename to code/datums/storage/subtypes/others/fish_case.dm
index e38d55e0e1d..4467d42e9ce 100644
--- a/code/datums/storage/subtypes/fish_case.dm
+++ b/code/datums/storage/subtypes/others/fish_case.dm
@@ -6,10 +6,14 @@
/datum/storage/fish_case/can_insert(obj/item/to_insert, mob/user, messages, force)
. = ..()
if(!.)
- return .
+ return
+
if(!HAS_TRAIT(to_insert, TRAIT_AQUARIUM_CONTENT))
- if(messages && user)
- user.balloon_alert(user, "can't hold!")
+ if(messages)
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]: can't hold [to_insert.type] which does not have TRAIT_AQUARIUM_CONTENT")
+ else if(user)
+ user.balloon_alert(user, "can't hold!")
return FALSE
return .
diff --git a/code/datums/storage/subtypes/others/misc.dm b/code/datums/storage/subtypes/others/misc.dm
new file mode 100644
index 00000000000..132b92bc97a
--- /dev/null
+++ b/code/datums/storage/subtypes/others/misc.dm
@@ -0,0 +1,328 @@
+//For storage types that are small enough to fit in this file
+
+///Test tube rack
+/datum/storage/test_tube_rack
+ max_slots = 8
+ screen_max_columns = 4
+ screen_max_rows = 2
+ allow_quick_gather = TRUE
+ allow_quick_empty = TRUE
+
+/datum/storage/test_tube_rack/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/reagent_containers/cup/tube)
+
+///Surgery tray
+/datum/storage/surgery_tray
+ max_total_storage = 30
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+ max_slots = 14
+ animated = FALSE
+
+/datum/storage/surgery_tray/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/autopsy_scanner,
+ /obj/item/blood_filter,
+ /obj/item/bonesetter,
+ /obj/item/cautery,
+ /obj/item/circular_saw,
+ /obj/item/clothing/mask/surgical,
+ /obj/item/hemostat,
+ /obj/item/razor,
+ /obj/item/retractor,
+ /obj/item/scalpel,
+ /obj/item/stack/medical/bone_gel,
+ /obj/item/stack/sticky_tape/surgical,
+ /obj/item/surgical_drapes,
+ /obj/item/surgicaldrill,
+ ))
+
+///Organ box
+/datum/storage/organ_box
+ max_specific_storage = WEIGHT_CLASS_BULKY
+ max_total_storage = 21
+
+/datum/storage/organ_box/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/organ,
+ /obj/item/bodypart,
+ /obj/item/food/icecream,
+ ))
+
+/datum/storage/organ_box/handle_enter(obj/item/storage/organbox/source, obj/item/arrived)
+ . = ..()
+
+ if(!istype(arrived) || !istype(source) || !source.coolant_to_spend())
+ return
+
+ arrived.freeze()
+
+/datum/storage/organ_box/handle_exit(datum/source, obj/item/gone)
+ . = ..()
+
+ if(!istype(gone))
+ return
+
+ gone.unfreeze()
+
+///Portable chem mixer
+/datum/storage/portable_chem_mixer
+ max_total_storage = 200
+ max_slots = 50
+
+/datum/storage/portable_chem_mixer/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/bottle,
+ /obj/item/reagent_containers/cup/tube,
+ /obj/item/reagent_containers/cup/glass/waterbottle,
+ /obj/item/reagent_containers/condiment,
+ ))
+
+///Implant
+/datum/storage/implant
+ max_total_storage = 6
+ max_slots = 2
+ silent = TRUE
+ allow_big_nesting = TRUE
+
+/datum/storage/implant/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(cant_hold_list = /obj/item/disk/nuclear)
+
+///Drone storage
+/datum/storage/drone
+ max_total_storage = 40
+ max_specific_storage = WEIGHT_CLASS_NORMAL
+ max_slots = 10
+ do_rustle = FALSE
+
+/datum/storage/drone/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/crowbar/drone,
+ /obj/item/screwdriver/drone,
+ /obj/item/wrench/drone,
+ /obj/item/weldingtool/drone,
+ /obj/item/wirecutters/drone,
+ /obj/item/multitool/drone,
+ /obj/item/pipe_dispenser/drone,
+ /obj/item/t_scanner/drone,
+ /obj/item/analyzer/drone,
+ /obj/item/soap/drone,
+ ))
+
+/datum/storage/drone/dump_content_at(atom/dest_object, dump_loc, mob/user)
+ return //no dumping of contents allowed
+
+///Basket
+/datum/storage/basket
+ max_total_storage = 21
+
+///Easter basket
+/datum/storage/basket/easter/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/food/egg,
+ /obj/item/food/chocolateegg,
+ /obj/item/food/boiledegg,
+ /obj/item/surprise_egg
+ ))
+
+/datum/storage/basket/easter/handle_enter(datum/source, obj/item/arrived)
+ . = ..()
+
+ countEggs(source)
+
+/datum/storage/basket/easter/proc/countEggs(obj/item/storage/basket/easter/basket)
+ basket.cut_overlays()
+ basket.add_overlay("basket-grass")
+ basket.add_overlay("basket-egg[min(basket.contents.len, 5)]")
+
+/datum/storage/basket/easter/handle_exit(datum/source, obj/item/gone)
+ . = ..()
+
+ countEggs(source)
+
+///Briefcase
+/datum/storage/briefcase
+ max_total_storage = 21
+
+///Sniper brief case
+/datum/storage/briefcase/sniper
+ max_slots = 13
+
+//=======================Fancy storages======================
+///Cigrate boxes
+/datum/storage/cigarette_box
+ display_contents = FALSE
+
+/datum/storage/cigarette_box/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/cigarette,
+ /obj/item/lighter,
+ ))
+
+///Coffee condiment display
+/datum/storage/coffee_condi_display
+ max_slots = 14
+
+/datum/storage/coffee_condi_display/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/reagent_containers/condiment/pack/sugar,
+ /obj/item/reagent_containers/condiment/creamer,
+ /obj/item/reagent_containers/condiment/pack/astrotame,
+ /obj/item/reagent_containers/condiment/chocolate,
+ ))
+
+///Coffee cart rack
+/datum/storage/coffee_cart_rack
+ max_slots = 4
+
+/datum/storage/coffee_cart_rack/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/coffee_cartridge)
+
+//=================================================
+
+///Pill bottle
+/datum/storage/pillbottle
+ allow_quick_gather = TRUE
+ open_sound = 'sound/items/handling/pill_bottle_open.ogg'
+ open_sound_vary = FALSE
+
+/datum/storage/pillbottle/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/reagent_containers/applicator/pill,
+ /obj/item/reagent_containers/applicator/patch,
+ /obj/item/food/bait/natural,
+ ))
+
+
+///Six pack beer
+/datum/storage/sixcan
+ max_specific_storage = WEIGHT_CLASS_SMALL
+ max_total_storage = 12
+ max_slots = 6
+
+/datum/storage/sixcan/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(list(
+ /obj/item/reagent_containers/cup/soda_cans,
+ /obj/item/reagent_containers/cup/glass/bottle/beer,
+ /obj/item/reagent_containers/cup/glass/bottle/ale,
+ /obj/item/reagent_containers/cup/glass/waterbottle,
+ ))
+
+///Wallet storage
+/datum/storage/wallet
+ max_specific_storage = WEIGHT_CLASS_SMALL
+ max_slots = 4
+
+/datum/storage/wallet/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(
+ can_hold_list = list(
+ /obj/item/stack/spacecash,
+ /obj/item/holochip,
+ /obj/item/card,
+ /obj/item/cigarette,
+ /obj/item/clothing/accessory/dogtag,
+ /obj/item/coin,
+ /obj/item/coupon,
+ /obj/item/dice,
+ /obj/item/disk,
+ /obj/item/flashlight/pen,
+ /obj/item/folder/biscuit,
+ /obj/item/food/chococoin,
+ /obj/item/implanter,
+ /obj/item/laser_pointer,
+ /obj/item/lighter,
+ /obj/item/lipstick,
+ /obj/item/match,
+ /obj/item/paper,
+ /obj/item/pen,
+ /obj/item/photo,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/reagent_containers/applicator,
+ /obj/item/screwdriver,
+ /obj/item/seeds,
+ /obj/item/spess_knife,
+ /obj/item/stack/medical,
+ /obj/item/stamp,
+ /obj/item/toy/crayon,
+ ),
+ cant_hold_list = list(
+ /obj/item/screwdriver/power
+ )
+ )
+
+///Crayons storage
+/datum/storage/crayons/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(
+ can_hold_list = /obj/item/toy/crayon,
+ cant_hold_list = list(
+ /obj/item/toy/crayon/spraycan,
+ /obj/item/toy/crayon/mime,
+ /obj/item/toy/crayon/rainbow,
+ ),
+ )
+
+///Dice storage
+/datum/storage/dice
+ allow_quick_gather = TRUE
+
+/datum/storage/dice/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/dice)
+
+///Mail counterfeit
+/datum/storage/mail_counterfeit
+ max_slots = 1
+ allow_big_nesting = TRUE
+
+///Mail counterfeit advanced
+/datum/storage/mail_counterfeit_advanced
+ max_slots = 21
+ max_total_storage = 21
+ allow_big_nesting = TRUE
+
+///Mail counterfeit bluespace
+/datum/storage/mail_counterfeit_bluespace
+ max_total_storage = 35
+ max_slots = 30
+ max_specific_storage = WEIGHT_CLASS_GIGANTIC
+ allow_big_nesting = TRUE
+
+///Card binder
+/datum/storage/card_binder
+ max_total_storage = 120
+ max_slots = 60
+
+/datum/storage/card_binder/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(/obj/item/tcgcard)
diff --git a/code/datums/storage/subtypes/others/pod.dm b/code/datums/storage/subtypes/others/pod.dm
new file mode 100644
index 00000000000..42822348387
--- /dev/null
+++ b/code/datums/storage/subtypes/others/pod.dm
@@ -0,0 +1,50 @@
+/datum/storage/pod
+ max_slots = 14
+ max_total_storage = WEIGHT_CLASS_BULKY * 14
+ allow_big_nesting = TRUE
+ /// If TRUE, we unlock regardless of security level
+ var/always_unlocked = FALSE
+
+/datum/storage/pod/open_storage(mob/to_show)
+ if(isliving(to_show) && SSsecurity_level.get_current_level_as_number() < SEC_LEVEL_RED)
+ to_chat(to_show, span_warning("The storage unit will only unlock during a Red or Delta security alert."))
+ return FALSE
+ return ..()
+
+/datum/storage/pod/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+ // all of these are a type below what actually spawn with
+ // (IE all space suits instead of just the emergency ones)
+ // because an enterprising traitor might be able to hide things,
+ // like their syndicate toolbox or softsuit. may be fun?
+ set_holdable(exception_hold_list = list(
+ /obj/item/clothing/suit/space,
+ /obj/item/pickaxe,
+ /obj/item/storage/toolbox,
+ ))
+
+ RegisterSignal(SSsecurity_level, COMSIG_SECURITY_LEVEL_CHANGED, PROC_REF(update_lock))
+
+/datum/storage/pod/set_parent(atom/new_parent)
+ . = ..()
+ RegisterSignal(parent, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, PROC_REF(pod_launch))
+
+/datum/storage/pod/proc/update_lock(datum/source, new_level)
+ SIGNAL_HANDLER
+ if(always_unlocked)
+ return
+
+ locked = (new_level < SEC_LEVEL_RED) ? STORAGE_FULLY_LOCKED : STORAGE_NOT_LOCKED
+ parent.update_appearance(UPDATE_ICON_STATE)
+ if(locked) // future todo : make `locked` a setter so this behavior can be built in (avoids exploits)
+ close_all()
+
+/datum/storage/pod/proc/pod_launch(datum/source, turf/old_turf)
+ SIGNAL_HANDLER
+ // This check is to ignore the movement of the shuttle from the transit level to the station as it is loaded in.
+ if(old_turf && is_reserved_level(old_turf.z))
+ return
+ // If the pod was launched, the storage will always open.
+ always_unlocked = TRUE
+ locked = STORAGE_NOT_LOCKED
+ parent.update_appearance(UPDATE_ICON_STATE)
diff --git a/code/datums/storage/subtypes/rped.dm b/code/datums/storage/subtypes/others/rped.dm
similarity index 95%
rename from code/datums/storage/subtypes/rped.dm
rename to code/datums/storage/subtypes/others/rped.dm
index a54d52ca359..374ed191a7f 100644
--- a/code/datums/storage/subtypes/rped.dm
+++ b/code/datums/storage/subtypes/others/rped.dm
@@ -43,7 +43,12 @@
/obj/item/circuitboard/computer,
)
- return is_type_in_list(to_insert, exceptions) ? ..() : FALSE
+ if(!is_type_in_list(to_insert, exceptions))
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]: [to_insert.type] is not a valid part")
+ return FALSE
+
+ return ..()
/datum/storage/rped/attempt_insert(obj/item/to_insert, mob/user, override, force, messages)
if(isstack(to_insert))
diff --git a/code/datums/storage/subtypes/pockets.dm b/code/datums/storage/subtypes/pockets.dm
index d7477b9c0ab..57bb0615730 100644
--- a/code/datums/storage/subtypes/pockets.dm
+++ b/code/datums/storage/subtypes/pockets.dm
@@ -1,3 +1,4 @@
+///Regular pockets
/datum/storage/pockets
max_slots = 2
max_specific_storage = WEIGHT_CLASS_SMALL
@@ -17,16 +18,19 @@
else
to_chat(user, span_notice("You discreetly slip [to_insert] into [parent]."))
+///Small pockets
/datum/storage/pockets/small
max_slots = 1
max_specific_storage = WEIGHT_CLASS_SMALL
attack_hand_interact = FALSE
+///Tiny pockets
/datum/storage/pockets/tiny
max_slots = 1
max_specific_storage = WEIGHT_CLASS_TINY
attack_hand_interact = FALSE
+///Fedora pockets
/datum/storage/pockets/small/fedora/New(
atom/parent,
max_slots,
@@ -34,19 +38,21 @@
max_total_storage,
)
. = ..()
- var/static/list/exception_cache = typecacheof(list(
+
+ set_holdable(exception_hold_list = list(
/obj/item/katana,
/obj/item/toy/katana,
/obj/item/nullrod/claymore/katana,
/obj/item/energy_katana,
/obj/item/gun/ballistic/automatic/tommygun,
))
- exception_hold = exception_cache
+///Fedora detective pockets
/datum/storage/pockets/small/fedora/detective
attack_hand_interact = TRUE // so the detectives would discover pockets in their hats
click_alt_open = FALSE
+///Chef hat pocket
/datum/storage/pockets/chefhat
attack_hand_interact = TRUE
max_slots = 1
@@ -59,6 +65,7 @@
max_total_storage,
)
. = ..()
+
set_holdable(list(
/obj/item/clothing/head/mob_holder,
/obj/item/food/deadmouse
@@ -70,8 +77,11 @@
var/obj/item/clothing/head/mob_holder/mausholder = to_insert
if(locate(/mob/living/basic/mouse) in mausholder.contents)
return
+ if(messages == STORAGE_ERROR_INSERT)
+ stack_trace("[parent.type]: no mouse to hold [to_insert]")
return FALSE
+///Shoe pockets
/datum/storage/pockets/shoes
max_slots = 2
attack_hand_interact = FALSE
@@ -85,41 +95,47 @@
max_total_storage,
)
. = ..()
- set_holdable(list(
- /obj/item/knife,
- /obj/item/spess_knife,
- /obj/item/switchblade,
- /obj/item/boxcutter,
- /obj/item/pen,
- /obj/item/scalpel,
- /obj/item/dnainjector,
- /obj/item/reagent_containers/syringe,
- /obj/item/reagent_containers/applicator/pill,
- /obj/item/reagent_containers/hypospray/medipen,
- /obj/item/reagent_containers/dropper,
- /obj/item/implanter,
- /obj/item/screwdriver,
- /obj/item/weldingtool/mini,
- /obj/item/firing_pin,
- /obj/item/suppressor,
- /obj/item/ammo_box/magazine/m9mm,
- /obj/item/ammo_box/magazine/m10mm,
- /obj/item/ammo_box/magazine/m45,
- /obj/item/ammo_box/magazine/toy/pistol,
- /obj/item/ammo_casing,
- /obj/item/lipstick,
- /obj/item/cigarette,
- /obj/item/lighter,
- /obj/item/match,
- /obj/item/holochip,
- /obj/item/toy/crayon,
- /obj/item/reagent_containers/cup/glass/flask),
- list(/obj/item/screwdriver/power,
- /obj/item/ammo_casing/rocket,
- /obj/item/cigarette/pipe,
- /obj/item/toy/crayon/spraycan)
- )
+ set_holdable(
+ can_hold_list = list(
+ /obj/item/knife,
+ /obj/item/spess_knife,
+ /obj/item/switchblade,
+ /obj/item/boxcutter,
+ /obj/item/pen,
+ /obj/item/scalpel,
+ /obj/item/dnainjector,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/reagent_containers/applicator/pill,
+ /obj/item/reagent_containers/hypospray/medipen,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/implanter,
+ /obj/item/screwdriver,
+ /obj/item/weldingtool/mini,
+ /obj/item/firing_pin,
+ /obj/item/suppressor,
+ /obj/item/ammo_box/magazine/m9mm,
+ /obj/item/ammo_box/magazine/m10mm,
+ /obj/item/ammo_box/magazine/m45,
+ /obj/item/ammo_box/magazine/toy/pistol,
+ /obj/item/ammo_casing,
+ /obj/item/lipstick,
+ /obj/item/cigarette,
+ /obj/item/lighter,
+ /obj/item/match,
+ /obj/item/holochip,
+ /obj/item/toy/crayon,
+ /obj/item/reagent_containers/cup/glass/flask,
+ ),
+ cant_hold_list = list(
+ /obj/item/screwdriver/power,
+ /obj/item/ammo_casing/rocket,
+ /obj/item/cigarette/pipe,
+ /obj/item/toy/crayon/spraycan,
+ )
+ )
+
+///Clown shoe pockets
/datum/storage/pockets/shoes/clown/New(
atom/parent,
max_slots,
@@ -127,6 +143,7 @@
max_total_storage,
)
. = ..()
+
set_holdable(
can_hold_list = list(
/obj/item/ammo_box/magazine/m10mm,
@@ -164,6 +181,7 @@
),
)
+///Protector pocket
/datum/storage/pockets/pocketprotector
max_slots = 3
max_specific_storage = WEIGHT_CLASS_TINY
@@ -175,6 +193,7 @@
max_total_storage,
)
. = ..()
+
set_holdable(list( //Same items as a PDA
/obj/item/pen,
/obj/item/toy/crayon,
@@ -183,6 +202,7 @@
/obj/item/lipstick,
))
+///Helmet pockets
/datum/storage/pockets/helmet
max_slots = 2
quickdraw = TRUE
@@ -195,12 +215,15 @@
max_total_storage,
)
. = ..()
- set_holdable(list(/obj/item/reagent_containers/cup/glass/bottle/vodka,
- /obj/item/reagent_containers/cup/glass/bottle/molotov,
- /obj/item/reagent_containers/cup/glass/drinkingglass,
- /obj/item/ammo_box/strilka310))
+ set_holdable(list(
+ /obj/item/reagent_containers/cup/glass/bottle/vodka,
+ /obj/item/reagent_containers/cup/glass/bottle/molotov,,
+ /obj/item/reagent_containers/cup/glass/drinkingglass,,
+ /obj/item/ammo_box/strilka310
+ ))
+///Void cloak pocket
/datum/storage/pockets/void_cloak
quickdraw = TRUE
max_total_storage = 5 // 2 small items + 1 tiny item, or 1 normal item + 1 small item
@@ -213,19 +236,24 @@
max_total_storage,
)
. = ..()
- set_holdable(list(
- /obj/item/ammo_box/strilka310/lionhunter,
- /obj/item/bodypart, // Bodyparts are often used in rituals. They're also often normal sized, so you can only fit one.
- /obj/item/clothing/neck/eldritch_amulet,
- /obj/item/clothing/neck/heretic_focus,
- /obj/item/codex_cicatrix,
- /obj/item/eldritch_potion,
- /obj/item/food/grown/poppy, // Used to regain a Living Heart.
- /obj/item/melee/rune_carver,
- /obj/item/melee/sickly_blade, // Normal sized, so you can only fit one.
- /obj/item/organ, // Organs are also often used in rituals.
- /obj/item/reagent_containers/cup/beaker/eldritch,
- ))
- var/static/list/exception_cache = typecacheof(list(/obj/item/bodypart, /obj/item/melee/sickly_blade))
- exception_hold = exception_cache
+ set_holdable(
+ can_hold_list = list(
+ /obj/item/ammo_box/strilka310/lionhunter,
+ /obj/item/bodypart, // Bodyparts are often used in rituals. They're also often normal sized, so you can only fit one.
+ /obj/item/clothing/neck/eldritch_amulet,
+ /obj/item/clothing/neck/heretic_focus,
+ /obj/item/codex_cicatrix,
+ /obj/item/eldritch_potion,
+ /obj/item/food/grown/poppy, // Used to regain a Living Heart.
+ /obj/item/melee/rune_carver,
+ /obj/item/melee/sickly_blade, // Normal sized, so you can only fit one.
+ /obj/item/organ, // Organs are also often used in rituals.
+ /obj/item/reagent_containers/cup/beaker/eldritch,
+ ),
+ exception_hold_list = list(
+ /obj/item/bodypart,
+ /obj/item/melee/sickly_blade
+ )
+ )
+
diff --git a/code/datums/storage/subtypes/portable_chem_mixer.dm b/code/datums/storage/subtypes/portable_chem_mixer.dm
deleted file mode 100644
index fcf5c6ec412..00000000000
--- a/code/datums/storage/subtypes/portable_chem_mixer.dm
+++ /dev/null
@@ -1,16 +0,0 @@
-/datum/storage/portable_chem_mixer
- max_total_storage = 200
- max_slots = 50
-
-/datum/storage/portable_chem_mixer/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
- . = ..()
-
- var/static/list/obj/item/reagent_containers/containers = list(
- /obj/item/reagent_containers/cup/beaker,
- /obj/item/reagent_containers/cup/bottle,
- /obj/item/reagent_containers/cup/tube,
- /obj/item/reagent_containers/cup/glass/waterbottle,
- /obj/item/reagent_containers/condiment,
- )
-
- set_holdable(containers)
diff --git a/code/datums/storage/subtypes/surgery_tray.dm b/code/datums/storage/subtypes/surgery_tray.dm
deleted file mode 100644
index c4d8780e051..00000000000
--- a/code/datums/storage/subtypes/surgery_tray.dm
+++ /dev/null
@@ -1,29 +0,0 @@
-/datum/storage/surgery_tray
- max_total_storage = 30
- max_specific_storage = WEIGHT_CLASS_NORMAL
- max_slots = 14
- animated = FALSE
-
-/datum/storage/surgery_tray/New(
- atom/parent,
- max_slots,
- max_specific_storage,
- max_total_storage,
-)
- . = ..()
- set_holdable(list(
- /obj/item/autopsy_scanner,
- /obj/item/blood_filter,
- /obj/item/bonesetter,
- /obj/item/cautery,
- /obj/item/circular_saw,
- /obj/item/clothing/mask/surgical,
- /obj/item/hemostat,
- /obj/item/razor,
- /obj/item/retractor,
- /obj/item/scalpel,
- /obj/item/stack/medical/bone_gel,
- /obj/item/stack/sticky_tape/surgical,
- /obj/item/surgical_drapes,
- /obj/item/surgicaldrill,
- ))
diff --git a/code/datums/storage/subtypes/test_tube_rack.dm b/code/datums/storage/subtypes/test_tube_rack.dm
deleted file mode 100644
index aa000cdbafa..00000000000
--- a/code/datums/storage/subtypes/test_tube_rack.dm
+++ /dev/null
@@ -1,15 +0,0 @@
-/datum/storage/test_tube_rack
- max_slots = 8
- screen_max_columns = 4
- screen_max_rows = 2
- allow_quick_gather = TRUE
- allow_quick_empty = TRUE
-
-/datum/storage/test_tube_rack/New(
- atom/parent,
- max_slots,
- max_specific_storage,
- max_total_storage,
-)
- . = ..()
- set_holdable(/obj/item/reagent_containers/cup/tube)
diff --git a/code/datums/storage/subtypes/toolboxes.dm b/code/datums/storage/subtypes/toolboxes.dm
new file mode 100644
index 00000000000..5babe139394
--- /dev/null
+++ b/code/datums/storage/subtypes/toolboxes.dm
@@ -0,0 +1,49 @@
+///Normal toolboxes
+/datum/storage/toolbox
+ open_sound = 'sound/items/handling/toolbox/toolbox_open.ogg'
+ rustle_sound = 'sound/items/handling/toolbox/toolbox_rustle.ogg'
+
+///Electrical toolbox
+/datum/storage/toolbox/electrical
+ max_slots = 8
+ max_total_storage = 15
+
+///Old heirloom toolbox
+/datum/storage/toolbox/old_heirloom
+ max_specific_storage = WEIGHT_CLASS_SMALL
+
+///Syndicate toolbox
+/datum/storage/toolbox/syndicate
+ silent = TRUE
+
+///Artistic toolbox
+/datum/storage/toolbox/artistic
+ max_total_storage = 25
+ max_slots = 11
+
+///Gun storage toolbox
+/datum/storage/toolbox/guncase
+ max_slots = 4
+ max_total_storage = 7 //enough to hold ONE bulky gun and the ammo boxes
+ allow_big_nesting = TRUE
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///Double sword toolbox
+/datum/storage/toolbox/double_sword
+ max_slots = 5
+ max_total_storage = 10 //it'll hold enough
+ max_specific_storage = WEIGHT_CLASS_BULKY
+
+///Fishing toolbox
+/datum/storage/toolbox/fishing/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
+ . = ..()
+
+ set_holdable(exception_hold_list = /obj/item/fishing_rod)
+
+///Small fishing toolbox
+/datum/storage/toolbox/fishing/small
+ max_specific_storage = WEIGHT_CLASS_SMALL
+
+///Ancient bundle toolbox
+/datum/storage/toolbox/ancient_bundle
+ max_slots = 8
diff --git a/code/datums/storage/subtypes/trash.dm b/code/datums/storage/subtypes/trash.dm
deleted file mode 100644
index b4f0e4353e3..00000000000
--- a/code/datums/storage/subtypes/trash.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-/datum/storage/trash
-
-/datum/storage/trash/remove_single(mob/removing, obj/item/thing, atom/remove_to_loc, silent)
- real_location.visible_message(
- span_notice("[removing] starts fishing around inside [parent]."),
- span_notice("You start digging around in [parent] to try and pull something out."),
- )
- if(!do_after(removing, 1.5 SECONDS, parent))
- return FALSE
-
- return ..()
diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm
index 1705a4241fb..b05f0ac1099 100644
--- a/code/game/machinery/launch_pad.dm
+++ b/code/game/machinery/launch_pad.dm
@@ -337,8 +337,10 @@
return ..()
/obj/item/storage/briefcase/launchpad/PopulateContents()
- new /obj/item/pen(src)
- new /obj/item/launchpad_remote(src, pad)
+ return list(
+ /obj/item/pen,
+ new /obj/item/launchpad_remote(null, pad),
+ )
/obj/item/storage/briefcase/launchpad/attack_self(mob/user)
if(!isturf(user.loc)) //no setting up in a locker
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 7396fbb59ca..a2fd4fe6663 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -725,27 +725,18 @@
icon_state = "crayonbox"
w_class = WEIGHT_CLASS_SMALL
custom_materials = list(/datum/material/cardboard = SHEET_MATERIAL_AMOUNT)
-
-/obj/item/storage/crayons/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(
- can_hold_list = /obj/item/toy/crayon,
- cant_hold_list = list(
- /obj/item/toy/crayon/spraycan,
- /obj/item/toy/crayon/mime,
- /obj/item/toy/crayon/rainbow,
- ),
- )
+ storage_type = /datum/storage/crayons
/obj/item/storage/crayons/PopulateContents()
- new /obj/item/toy/crayon/red(src)
- new /obj/item/toy/crayon/orange(src)
- new /obj/item/toy/crayon/yellow(src)
- new /obj/item/toy/crayon/green(src)
- new /obj/item/toy/crayon/blue(src)
- new /obj/item/toy/crayon/purple(src)
- new /obj/item/toy/crayon/black(src)
- update_appearance()
+ return list(
+ new /obj/item/toy/crayon/red,
+ new /obj/item/toy/crayon/orange,
+ new /obj/item/toy/crayon/yellow,
+ new /obj/item/toy/crayon/green,
+ new /obj/item/toy/crayon/blue,
+ new /obj/item/toy/crayon/purple,
+ new /obj/item/toy/crayon/black,
+ )
/obj/item/storage/crayons/update_overlays()
. = ..()
diff --git a/code/game/objects/items/devices/spyglasses.dm b/code/game/objects/items/devices/spyglasses.dm
index 0c91b8b2255..4e16df7f485 100644
--- a/code/game/objects/items/devices/spyglasses.dm
+++ b/code/game/objects/items/devices/spyglasses.dm
@@ -99,8 +99,13 @@ A shrill beep coming from your SpySpeks means that they can't connect to the inc
"}
/obj/item/storage/box/rxglasses/spyglasskit/PopulateContents()
- var/obj/item/clothing/accessory/spy_bug/newbug = new(src)
- var/obj/item/clothing/glasses/sunglasses/spy/newglasses = new(src)
+ var/obj/item/clothing/accessory/spy_bug/newbug = new(null)
+ var/obj/item/clothing/glasses/sunglasses/spy/newglasses = new(null)
newbug.linked_glasses = newglasses
newglasses.linked_bug = newbug
- new /obj/item/paper/fluff/nerddocs(src)
+
+ return list(
+ newbug,
+ newglasses,
+ /obj/item/paper/fluff/nerddocs
+ )
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 2fb6de0c03e..6e9466d732b 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -413,12 +413,14 @@ effective or pretty fucking useless.
desc = "You feel a strange urge to hit this with a wrench."
/obj/item/storage/toolbox/emergency/turret/PopulateContents()
- new /obj/item/screwdriver(src)
- new /obj/item/wrench/combat(src)
- new /obj/item/weldingtool(src)
- new /obj/item/crowbar(src)
- new /obj/item/analyzer(src)
- new /obj/item/wirecutters(src)
+ return list(
+ /obj/item/screwdriver,
+ /obj/item/wrench/combat,
+ /obj/item/weldingtool,
+ /obj/item/crowbar,
+ /obj/item/analyzer,
+ /obj/item/wirecutters,
+ )
/obj/item/storage/toolbox/emergency/turret/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
if(!istype(tool, /obj/item/wrench/combat))
diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm
index e65b4bada08..a9f5f6404fb 100644
--- a/code/game/objects/items/dice.dm
+++ b/code/game/objects/items/dice.dm
@@ -9,20 +9,10 @@
icon = 'icons/obj/toys/dice.dmi'
icon_state = "dicebag"
w_class = WEIGHT_CLASS_SMALL
-
-/obj/item/storage/dice/Initialize(mapload)
- . = ..()
- atom_storage.allow_quick_gather = TRUE
- atom_storage.set_holdable(/obj/item/dice)
+ storage_type = /datum/storage/dice
/obj/item/storage/dice/PopulateContents()
- new /obj/item/dice/d4(src)
- new /obj/item/dice/d6(src)
- new /obj/item/dice/d8(src)
- new /obj/item/dice/d10(src)
- new /obj/item/dice/d12(src)
- new /obj/item/dice/d20(src)
- var/picked = pick(list(
+ var/static/list/obj/item/options = list(
/obj/item/dice/d1,
/obj/item/dice/d2,
/obj/item/dice/fudge,
@@ -31,8 +21,17 @@
/obj/item/dice/eightbd20,
/obj/item/dice/fourdd6,
/obj/item/dice/d100,
- ))
- new picked(src)
+ )
+
+ return list(
+ /obj/item/dice/d4,
+ /obj/item/dice/d6,
+ /obj/item/dice/d8,
+ /obj/item/dice/d10,
+ /obj/item/dice/d12,
+ /obj/item/dice/d20,
+ pick(options),
+ )
/obj/item/storage/dice/suicide_act(mob/living/user)
user.visible_message(span_suicide("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!"))
@@ -41,14 +40,19 @@
/obj/item/storage/dice/hazard
/obj/item/storage/dice/hazard/PopulateContents()
- new /obj/item/dice/d6(src)
- new /obj/item/dice/d6(src)
- new /obj/item/dice/d6(src)
+ var/list/obj/item/dices = list(
+ new /obj/item/dice/d6,
+ new /obj/item/dice/d6,
+ new /obj/item/dice/d6,
+ )
+
for(var/i in 1 to 2)
if(prob(7))
- new /obj/item/dice/d6/ebony(src)
+ dices += /obj/item/dice/d6/ebony
else
- new /obj/item/dice/d6(src)
+ dices += /obj/item/dice/d6
+
+ return dices
///this is a prototype for dice, for a real d6 use "/obj/item/dice/d6"
/obj/item/dice
diff --git a/code/game/objects/items/food/moth.dm b/code/game/objects/items/food/moth.dm
index eeaa02cebc8..d4e6c0398a6 100644
--- a/code/game/objects/items/food/moth.dm
+++ b/code/game/objects/items/food/moth.dm
@@ -916,8 +916,12 @@
return .
/obj/item/storage/box/gum/wake_up/PopulateContents()
- for(var/i in 1 to 4)
- new/obj/item/food/bubblegum/wake_up(src)
+ return list(
+ /obj/item/food/bubblegum/wake_up,
+ /obj/item/food/bubblegum/wake_up,
+ /obj/item/food/bubblegum/wake_up,
+ /obj/item/food/bubblegum/wake_up,
+ )
/obj/item/food/spacers_sidekick
name = "\improper Spacer's Sidekick mints"
diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm
index 90888b062a3..7cad2543ba8 100644
--- a/code/game/objects/items/mail.dm
+++ b/code/game/objects/items/mail.dm
@@ -345,18 +345,7 @@
worn_icon_state = "mailbag"
resistance_flags = FLAMMABLE
custom_premium_price = PAYCHECK_LOWER
-
-/obj/item/storage/bag/mail/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 42
- atom_storage.max_slots = 21
- atom_storage.numerical_stacking = FALSE
- atom_storage.set_holdable(list(
- /obj/item/mail,
- /obj/item/delivery/small,
- /obj/item/paper
- ))
+ storage_type = /datum/storage/bag/mail
/obj/item/paper/fluff/junkmail_redpill
name = "smudged paper"
@@ -495,12 +484,7 @@
w_class = WEIGHT_CLASS_NORMAL
icon = 'icons/obj/antags/syndicate_tools.dmi'
icon_state = "mail_counterfeit_device"
-
-/obj/item/storage/mail_counterfeit_device/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 1
- atom_storage.allow_big_nesting = TRUE
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
+ storage_type = /datum/storage/mail_counterfeit
/obj/item/storage/mail_counterfeit_device/examine_more(mob/user)
. = ..()
@@ -572,19 +556,17 @@
/// Unobtainable item mostly for (b)admin purposes.
/obj/item/storage/mail_counterfeit_device/advanced
name = "GLA-MACRO mail counterfeit device"
+ storage_type = /datum/storage/mail_counterfeit_advanced
/obj/item/storage/mail_counterfeit_device/advanced/Initialize(mapload)
. = ..()
desc += " This model is highly advanced and capable of compressing items, making mail's storage space comparable to standard backpack."
- create_storage(max_slots = 21, max_total_storage = 21)
- atom_storage.allow_big_nesting = TRUE
/// Unobtainable item mostly for (b)admin purposes.
/obj/item/storage/mail_counterfeit_device/bluespace
name = "GLA-ULTRA mail counterfeit device"
+ storage_type = /datum/storage/mail_counterfeit_bluespace
/obj/item/storage/mail_counterfeit_device/bluespace/Initialize(mapload)
. = ..()
desc += " This model is the most advanced and capable of performing crazy bluespace compressions, making mail's storage space comparable to bluespace backpack."
- create_storage(max_specific_storage = WEIGHT_CLASS_GIGANTIC, max_total_storage = 35, max_slots = 30)
- atom_storage.allow_big_nesting = TRUE
diff --git a/code/game/objects/items/pinpointer.dm b/code/game/objects/items/pinpointer.dm
index af7b877bb1d..ace2ef95162 100644
--- a/code/game/objects/items/pinpointer.dm
+++ b/code/game/objects/items/pinpointer.dm
@@ -192,12 +192,14 @@
name = "pinpointer pair box"
/obj/item/storage/box/pinpointer_pairs/PopulateContents()
- var/obj/item/pinpointer/pair/A = new(src)
- var/obj/item/pinpointer/pair/B = new(src)
+ var/obj/item/pinpointer/pair/A = new(null)
+ var/obj/item/pinpointer/pair/B = new(null)
A.other_pair = B
B.other_pair = A
+ return list(A, B)
+
/obj/item/pinpointer/shuttle
name = "bounty shuttle pinpointer"
desc = "A handheld tracking device that locates the bounty hunter shuttle for quick escapes."
diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm
index 4e7430d56a5..c6279f80f61 100644
--- a/code/game/objects/items/religion.dm
+++ b/code/game/objects/items/religion.dm
@@ -257,10 +257,7 @@
name = "\improper Nanotrasen banner backpack"
desc = "It's a backpack with lots of extra room. A banner with Nanotrasen's logo is attached, that can't be removed."
icon_state = "backpack-banner"
-
-/obj/item/storage/backpack/bannerpack/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 27 //6 more then normal, for the tradeoff of declaring yourself an antag at all times.
+ storage_type = /datum/storage/backpack/bannerpack
/obj/item/storage/backpack/bannerpack/red
name = "red banner backpack"
@@ -411,18 +408,6 @@
/obj/item/clothing/shoes/plate/blue
icon_state = "crusader-blue"
-/obj/item/storage/box/itemset/crusader/blue/PopulateContents()
- new /obj/item/clothing/suit/chaplainsuit/armor/crusader/blue(src)
- new /obj/item/clothing/head/helmet/plate/crusader/blue(src)
- new /obj/item/clothing/gloves/plate/blue(src)
- new /obj/item/clothing/shoes/plate/blue(src)
-
-/obj/item/storage/box/itemset/crusader/red/PopulateContents()
- new /obj/item/clothing/suit/chaplainsuit/armor/crusader/red(src)
- new /obj/item/clothing/head/helmet/plate/crusader/red(src)
- new /obj/item/clothing/gloves/plate/red(src)
- new /obj/item/clothing/shoes/plate/red(src)
-
/obj/item/claymore/weak
desc = "This one is rusted."
force = 24
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index f2ed4287c11..c140fc5f831 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -238,13 +238,9 @@
icon = 'icons/obj/storage/ethereal.dmi'
worn_icon = 'icons/mob/clothing/back/ethereal.dmi'
icon_state = "saddlepack"
+ storage_type = /datum/storage/backpack/sadle_bag
-/obj/item/storage/backpack/saddlepack/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 26
-
-// MEAT MEAT MEAT MEAT MEAT
-
+/// MEAT MEAT MEAT MEAT MEAT
/obj/item/storage/backpack/meat
name = "\improper MEAT"
desc = "MEAT MEAT MEAT MEAT MEAT MEAT"
@@ -302,6 +298,7 @@
desc = "A trendy looking satchel."
icon_state = "satchel-norm"
inhand_icon_state = "satchel-norm"
+ storage_type = /datum/storage/backpack/satchel
/obj/item/storage/backpack/satchel/leather
name = "leather satchel"
@@ -310,7 +307,7 @@
inhand_icon_state = "satchel"
/obj/item/storage/backpack/satchel/leather/withwallet/PopulateContents()
- new /obj/item/storage/wallet/random(src)
+ return /obj/item/storage/wallet/random
/obj/item/storage/backpack/satchel/fireproof
resistance_flags = FIRE_PROOF
@@ -389,396 +386,25 @@
inhand_icon_state = "satchel-flat"
w_class = WEIGHT_CLASS_NORMAL //Can fit in backpacks itself.
-/obj/item/storage/backpack/satchel/flat/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, INVISIBILITY_OBSERVER, use_anchor = TRUE)
- atom_storage.max_total_storage = 15
- atom_storage.set_holdable(cant_hold_list = /obj/item/storage/backpack/satchel/flat) //muh recursive backpacks
- ADD_TRAIT(src, TRAIT_CONTRABAND_BLOCKER, INNATE_TRAIT)
+/obj/item/storage/backpack/satchel/flat/PopulateContents(datum/storage_config/config)
+ config.contents_are_exceptions = TRUE
-/obj/item/storage/backpack/satchel/flat/PopulateContents()
- for(var/items in 1 to 4)
+ for(var/_ in 1 to 4)
new /obj/effect/spawner/random/contraband(src)
-/obj/item/storage/backpack/satchel/flat/with_tools/PopulateContents()
- new /obj/item/stack/tile/iron/base(src)
- new /obj/item/crowbar(src)
+ . = list()
+ for(var/obj/item/insert as anything in src)
+ insert.moveToNullspace()
+ . += insert
- ..()
+/obj/item/storage/backpack/satchel/flat/with_tools/PopulateContents()
+ return list(
+ /obj/item/stack/tile/iron/base,
+ /obj/item/crowbar,
+ )
/obj/item/storage/backpack/satchel/flat/empty/PopulateContents()
- return
-
-/obj/item/storage/backpack/duffelbag
- name = "duffel bag"
- desc = "A large duffel bag for holding extra things."
- icon_state = "duffel"
- inhand_icon_state = "duffel"
- actions_types = list(/datum/action/item_action/zipper)
- action_slots = ALL
- storage_type = /datum/storage/duffel
- // How much to slow you down if your bag isn't zipped up
- var/zip_slowdown = 1
- /// If this bag is zipped (contents hidden) up or not
- /// Starts enabled so you're forced to interact with it to "get" it
- var/zipped_up = TRUE
- // How much time it takes to zip up (close) the duffelbag
- var/zip_up_duration = 0.5 SECONDS
- // Audio played during zipup
- var/zip_up_sfx = 'sound/items/zip/zip_up.ogg'
- // How much time it takes to unzip the duffel
- var/unzip_duration = 2.1 SECONDS
- // Audio played during unzip
- var/unzip_sfx = 'sound/items/zip/un_zip.ogg'
-
-/obj/item/storage/backpack/duffelbag/Initialize(mapload)
- . = ..()
- set_zipper(TRUE)
-
-/obj/item/storage/backpack/duffelbag/update_desc(updates)
- . = ..()
- desc = "[initial(desc)]
[zipped_up ? "It's zipped up, preventing you from accessing its contents." : "It's unzipped, and harder to move in."]"
-
-/obj/item/storage/backpack/duffelbag/attack_self(mob/user, modifiers)
- if(loc != user) // God fuck TK
- return ..()
- if(zipped_up)
- return attack_hand(user, modifiers)
- else
- return attack_hand_secondary(user, modifiers)
-
-/obj/item/storage/backpack/duffelbag/attack_self_secondary(mob/user, modifiers)
- attack_self(user, modifiers)
- return ..()
-
-// If we're zipped, click to unzip
-/obj/item/storage/backpack/duffelbag/attack_hand(mob/user, list/modifiers)
- if(loc != user)
- // Hacky, but please don't be cringe yeah?
- atom_storage.silent = TRUE
- . = ..()
- atom_storage.silent = initial(atom_storage.silent)
- return
- if(!zipped_up)
- return ..()
-
- balloon_alert(user, "unzipping...")
- playsound(src, unzip_sfx, 100, FALSE)
- var/datum/callback/can_unzip = CALLBACK(src, PROC_REF(zipper_matches), TRUE)
- if(!do_after(user, unzip_duration, src, extra_checks = can_unzip))
- user.balloon_alert(user, "unzip failed!")
- return
- balloon_alert(user, "unzipped")
- set_zipper(FALSE)
- return TRUE
-
-// Vis versa
-/obj/item/storage/backpack/duffelbag/attack_hand_secondary(mob/user, list/modifiers)
- if(loc != user)
- return ..()
- if(zipped_up)
- return SECONDARY_ATTACK_CALL_NORMAL
-
- balloon_alert(user, "zipping...")
- playsound(src, zip_up_sfx, 100, FALSE)
- var/datum/callback/can_zip = CALLBACK(src, PROC_REF(zipper_matches), FALSE)
- if(!do_after(user, zip_up_duration, src, extra_checks = can_zip))
- user.balloon_alert(user, "zip failed!")
- return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
- balloon_alert(user, "zipped")
- set_zipper(TRUE)
- return SECONDARY_ATTACK_CONTINUE_CHAIN
-
-/// Checks to see if the zipper matches the passed in state
-/// Returns true if so, false otherwise
-/obj/item/storage/backpack/duffelbag/proc/zipper_matches(matching_value)
- return zipped_up == matching_value
-
-/obj/item/storage/backpack/duffelbag/proc/set_zipper(new_zip)
- zipped_up = new_zip
- SEND_SIGNAL(src, COMSIG_DUFFEL_ZIP_CHANGE, new_zip)
- if(zipped_up)
- slowdown = initial(slowdown)
- atom_storage.locked = STORAGE_SOFT_LOCKED
- atom_storage.display_contents = FALSE
- for(var/obj/item/weapon as anything in get_all_contents_type(/obj/item)) //close ui of this and all items inside dufflebag
- weapon.atom_storage?.close_all() //not everything has storage initialized
- else
- slowdown = zip_slowdown
- atom_storage.locked = STORAGE_NOT_LOCKED
- atom_storage.display_contents = TRUE
-
- if(isliving(loc))
- var/mob/living/wearer = loc
- wearer.update_equipment_speed_mods()
- update_appearance()
-
-/obj/item/storage/backpack/duffelbag/cursed
- name = "living duffel bag"
- desc = "A cursed clown duffel bag that hungers for food of any kind. A warning label suggests that it eats food inside. \
- If that food happens to be a horribly ruined mess or the chef scrapped out of the microwave, or poisoned in some way, \
- then it might have negative effects on the bag..."
- icon_state = "duffel-curse"
- inhand_icon_state = "duffel-curse"
- zip_slowdown = 2
- max_integrity = 100
-
-/obj/item/storage/backpack/duffelbag/cursed/Initialize(mapload)
- . = ..()
- AddComponent(/datum/component/curse_of_hunger, add_dropdel = TRUE)
-
-/obj/item/storage/backpack/duffelbag/captain
- name = "captain's duffel bag"
- desc = "A large duffel bag for holding extra captainly goods."
- icon_state = "duffel-captain"
- inhand_icon_state = "duffel-captain"
-
-/obj/item/storage/backpack/duffelbag/med
- name = "medical duffel bag"
- desc = "A large duffel bag for holding extra medical supplies."
- icon_state = "duffel-medical"
- inhand_icon_state = "duffel-med"
-
-/obj/item/storage/backpack/duffelbag/coroner
- name = "coroner duffel bag"
- desc = "A large duffel bag for holding large amounts of organs at once."
- icon_state = "duffel-coroner"
- inhand_icon_state = "duffel-coroner"
-
-/obj/item/storage/backpack/duffelbag/explorer
- name = "explorer duffel bag"
- desc = "A large duffel bag for holding extra exotic treasures."
- icon_state = "duffel-explorer"
- inhand_icon_state = "duffel-explorer"
-
-/obj/item/storage/backpack/duffelbag/hydroponics
- name = "hydroponic's duffel bag"
- desc = "A large duffel bag for holding extra gardening tools."
- icon_state = "duffel-hydroponics"
- inhand_icon_state = "duffel-hydroponics"
-
-/obj/item/storage/backpack/duffelbag/chemistry
- name = "chemistry duffel bag"
- desc = "A large duffel bag for holding extra chemical substances."
- icon_state = "duffel-chemistry"
- inhand_icon_state = "duffel-chemistry"
-
-/obj/item/storage/backpack/duffelbag/genetics
- name = "geneticist's duffel bag"
- desc = "A large duffel bag for holding extra genetic mutations."
- icon_state = "duffel-genetics"
- inhand_icon_state = "duffel-genetics"
-
-/obj/item/storage/backpack/duffelbag/science
- name = "scientist's duffel bag"
- desc = "A large duffel bag for holding extra scientific components."
- icon_state = "duffel-science"
- inhand_icon_state = "duffel-sci"
-
-/obj/item/storage/backpack/duffelbag/virology
- name = "virologist's duffel bag"
- desc = "A large duffel bag for holding extra viral bottles."
- icon_state = "duffel-virology"
- inhand_icon_state = "duffel-virology"
-
-/obj/item/storage/backpack/duffelbag/sec
- name = "security duffel bag"
- desc = "A large duffel bag for holding extra security supplies and ammunition."
- icon_state = "duffel-security"
- inhand_icon_state = "duffel-sec"
-
-/obj/item/storage/backpack/duffelbag/sec/surgery
- name = "surgical duffel bag"
- desc = "A large duffel bag for holding extra supplies - this one has a material inlay with space for various sharp-looking tools."
-
-/obj/item/storage/backpack/duffelbag/sec/surgery/PopulateContents()
- new /obj/item/scalpel(src)
- new /obj/item/hemostat(src)
- new /obj/item/retractor(src)
- new /obj/item/circular_saw(src)
- new /obj/item/bonesetter(src)
- new /obj/item/surgicaldrill(src)
- new /obj/item/cautery(src)
- new /obj/item/surgical_drapes(src)
- new /obj/item/clothing/mask/surgical(src)
- new /obj/item/blood_filter(src)
-
-/obj/item/storage/backpack/duffelbag/engineering
- name = "industrial duffel bag"
- desc = "A large duffel bag for holding extra tools and supplies."
- icon_state = "duffel-engineering"
- inhand_icon_state = "duffel-eng"
- resistance_flags = FIRE_PROOF
-
-/obj/item/storage/backpack/duffelbag/drone
- name = "drone duffel bag"
- desc = "A large duffel bag for holding tools and hats."
- icon_state = "duffel-drone"
- inhand_icon_state = "duffel-drone"
- resistance_flags = FIRE_PROOF
-
-/obj/item/storage/backpack/duffelbag/drone/PopulateContents()
- new /obj/item/screwdriver(src)
- new /obj/item/wrench(src)
- new /obj/item/weldingtool(src)
- new /obj/item/crowbar(src)
- new /obj/item/stack/cable_coil(src)
- new /obj/item/wirecutters(src)
- new /obj/item/multitool(src)
-
-/obj/item/storage/backpack/duffelbag/clown
- name = "clown's duffel bag"
- desc = "A large duffel bag for holding lots of funny gags!"
- icon_state = "duffel-clown"
- inhand_icon_state = "duffel-clown"
-
-/obj/item/storage/backpack/duffelbag/clown/cream_pie/PopulateContents()
- for(var/i in 1 to 10)
- new /obj/item/food/pie/cream(src)
-
-/obj/item/storage/backpack/fireproof
- resistance_flags = FIRE_PROOF
-
-/obj/item/storage/backpack/duffelbag/syndie
- name = "suspicious looking duffel bag"
- desc = "A large duffel bag for holding extra tactical supplies. It contains an oiled plastitanium zipper for maximum speed tactical zipping, and is better balanced on your back than an average duffelbag. Can hold two bulky items!"
- icon_state = "duffel-syndie"
- inhand_icon_state = "duffel-syndieammo"
- storage_type = /datum/storage/duffel/syndicate
- resistance_flags = FIRE_PROOF
- // Less slowdown while unzipped. Still bulky, but it won't halve your movement speed in an active combat situation.
- zip_slowdown = 0.3
- // Faster unzipping. Utilizes the same noise as zipping up to fit the unzip duration.
- unzip_duration = 0.5 SECONDS
- unzip_sfx = 'sound/items/zip/zip_up.ogg'
-
-/obj/item/storage/backpack/duffelbag/syndie/hitman
- desc = "A large duffel bag for holding extra things. There is a Nanotrasen logo on the back."
- icon_state = "duffel-syndieammo"
- inhand_icon_state = "duffel-syndieammo"
-
-/obj/item/storage/backpack/duffelbag/syndie/hitman/PopulateContents()
- new /obj/item/clothing/under/costume/buttondown/slacks/service(src)
- new /obj/item/clothing/neck/tie/red/hitman(src)
- new /obj/item/clothing/accessory/waistcoat(src)
- new /obj/item/clothing/suit/toggle/lawyer/black(src)
- new /obj/item/clothing/shoes/laceup(src)
- new /obj/item/clothing/gloves/color/black(src)
- new /obj/item/clothing/glasses/sunglasses(src)
- new /obj/item/clothing/head/fedora(src)
-
-/obj/item/storage/backpack/duffelbag/syndie/med
- name = "medical duffel bag"
- desc = "A large duffel bag for holding extra tactical medical supplies."
- icon_state = "duffel-syndiemed"
- inhand_icon_state = "duffel-syndiemed"
-
-/obj/item/storage/backpack/duffelbag/syndie/surgery
- name = "surgery duffel bag"
- desc = "A suspicious looking duffel bag for holding surgery tools."
- icon_state = "duffel-syndiemed"
- inhand_icon_state = "duffel-syndiemed"
-
-/obj/item/storage/backpack/duffelbag/syndie/surgery/PopulateContents()
- new /obj/item/scalpel/advanced(src)
- new /obj/item/retractor/advanced(src)
- new /obj/item/cautery/advanced(src)
- new /obj/item/surgical_drapes(src)
- new /obj/item/reagent_containers/medigel/sterilizine(src)
- new /obj/item/bonesetter(src)
- new /obj/item/blood_filter(src)
- new /obj/item/stack/medical/bone_gel(src)
- new /obj/item/stack/sticky_tape/surgical(src)
- new /obj/item/emergency_bed(src)
- new /obj/item/clothing/suit/jacket/straight_jacket(src)
- new /obj/item/clothing/mask/muzzle(src)
- new /obj/item/mmi/syndie(src)
-
-/obj/item/storage/backpack/duffelbag/syndie/ammo
- name = "ammunition duffel bag"
- desc = "A large duffel bag for holding extra weapons ammunition and supplies."
- icon_state = "duffel-syndieammo"
- inhand_icon_state = "duffel-syndieammo"
-
-/obj/item/storage/backpack/duffelbag/syndie/ammo/mech
- desc = "A large duffel bag, packed to the brim with various exosuit ammo."
-
-/obj/item/storage/backpack/duffelbag/syndie/ammo/mech/PopulateContents()
- new /obj/item/mecha_ammo/scattershot(src)
- new /obj/item/mecha_ammo/scattershot(src)
- new /obj/item/mecha_ammo/scattershot(src)
- new /obj/item/mecha_ammo/scattershot(src)
- new /obj/item/storage/belt/utility/syndicate(src)
-
-/obj/item/storage/backpack/duffelbag/syndie/ammo/mauler
- desc = "A large duffel bag, packed to the brim with various exosuit ammo."
-
-/obj/item/storage/backpack/duffelbag/syndie/ammo/mauler/PopulateContents()
- new /obj/item/mecha_ammo/lmg(src)
- new /obj/item/mecha_ammo/lmg(src)
- new /obj/item/mecha_ammo/lmg(src)
- new /obj/item/mecha_ammo/scattershot(src)
- new /obj/item/mecha_ammo/scattershot(src)
- new /obj/item/mecha_ammo/scattershot(src)
- new /obj/item/mecha_ammo/missiles_srm(src)
- new /obj/item/mecha_ammo/missiles_srm(src)
- new /obj/item/mecha_ammo/missiles_srm(src)
-
-/obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle
- desc = "A large duffel bag containing a medical equipment, a Donksoft LMG, a big jumbo box of riot darts, and a magboot MODsuit module."
-
-/obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle/PopulateContents()
- new /obj/item/mod/module/magboot(src)
- new /obj/item/storage/medkit/tactical/premium(src)
- new /obj/item/gun/ballistic/automatic/l6_saw/toy(src)
- new /obj/item/ammo_box/foambox/riot(src)
-
-/obj/item/storage/backpack/duffelbag/syndie/med/bioterrorbundle
- desc = "A large duffel bag containing deadly chemicals, a handheld chem sprayer, Bioterror foam grenade, a Donksoft assault rifle, box of riot grade darts, a dart pistol, and a box of syringes."
-
-/obj/item/storage/backpack/duffelbag/syndie/med/bioterrorbundle/PopulateContents()
- new /obj/item/reagent_containers/spray/chemsprayer/bioterror(src)
- new /obj/item/storage/box/syndie_kit/chemical(src)
- new /obj/item/gun/syringe/syndicate(src)
- new /obj/item/gun/ballistic/automatic/c20r/toy(src)
- new /obj/item/storage/box/syringes(src)
- new /obj/item/ammo_box/foambox/riot(src)
- new /obj/item/grenade/chem_grenade/bioterrorfoam(src)
- if(prob(5))
- new /obj/item/food/pizza/pineapple(src)
-
-/obj/item/storage/backpack/duffelbag/syndie/c4/PopulateContents()
- for(var/i in 1 to 10)
- new /obj/item/grenade/c4(src)
-
-/obj/item/storage/backpack/duffelbag/syndie/x4/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/grenade/c4/x4(src)
-
-/obj/item/storage/backpack/duffelbag/syndie/firestarter
- desc = "A large duffel bag containing a New Russian pyro backpack sprayer, Elite MODsuit, a Stechkin APS pistol, minibomb, ammo, and other equipment."
-
-/obj/item/storage/backpack/duffelbag/syndie/firestarter/PopulateContents()
- new /obj/item/clothing/under/syndicate/soviet(src)
- new /obj/item/mod/control/pre_equipped/elite/flamethrower(src)
- new /obj/item/gun/ballistic/automatic/pistol/aps(src)
- new /obj/item/ammo_box/magazine/m9mm_aps/fire(src)
- new /obj/item/ammo_box/magazine/m9mm_aps/fire(src)
- new /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka(src)
- new /obj/item/reagent_containers/hypospray/medipen/stimulants(src)
- new /obj/item/grenade/syndieminibomb(src)
-
-// For ClownOps.
-/obj/item/storage/backpack/duffelbag/clown/syndie
- storage_type = /datum/storage/duffel/syndicate
-
-/obj/item/storage/backpack/duffelbag/clown/syndie/PopulateContents()
- new /obj/item/modular_computer/pda/clown(src)
- new /obj/item/clothing/under/rank/civilian/clown(src)
- new /obj/item/clothing/shoes/clown_shoes(src)
- new /obj/item/clothing/mask/gas/clown_hat(src)
- new /obj/item/bikehorn(src)
- new /obj/item/implanter/sad_trombone(src)
+ return NONE
/obj/item/storage/backpack/henchmen
name = "wings"
@@ -797,16 +423,18 @@
inhand_icon_state = "duffel-explorer"
/obj/item/storage/backpack/duffelbag/mining_conscript/PopulateContents()
- new /obj/item/clothing/glasses/meson(src)
- new /obj/item/t_scanner/adv_mining_scanner/lesser(src)
- new /obj/item/storage/bag/ore(src)
- new /obj/item/clothing/suit/hooded/explorer(src)
- new /obj/item/encryptionkey/headset_mining(src)
- new /obj/item/clothing/mask/gas/explorer(src)
- new /obj/item/card/id/advanced/mining(src)
- new /obj/item/gun/energy/recharge/kinetic_accelerator(src)
- new /obj/item/knife/combat/survival(src)
- new /obj/item/flashlight/seclite(src)
+ return list(
+ /obj/item/clothing/glasses/meson,
+ /obj/item/t_scanner/adv_mining_scanner/lesser,
+ /obj/item/storage/bag/ore,
+ /obj/item/clothing/suit/hooded/explorer,
+ /obj/item/encryptionkey/headset_mining,
+ /obj/item/clothing/mask/gas/explorer,
+ /obj/item/card/id/advanced/mining,
+ /obj/item/gun/energy/recharge/kinetic_accelerator,
+ /obj/item/knife/combat/survival,
+ /obj/item/flashlight/seclite,
+ )
/*
* Messenger Bag Types
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index 41300362e21..da967fd140e 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -21,12 +21,7 @@
/obj/item/storage/bag
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_BULKY
-
-/obj/item/storage/bag/Initialize(mapload)
- . = ..()
- atom_storage.allow_quick_gather = TRUE
- atom_storage.allow_quick_empty = TRUE
- atom_storage.numerical_stacking = TRUE
+ storage_type = /datum/storage/bag
// -----------------------------
// Trash bag
@@ -40,17 +35,14 @@
worn_icon_state = "trashbag"
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
- storage_type = /datum/storage/trash
+ storage_type = /datum/storage/bag/trash_bag
+
///If true, can be inserted into the janitor cart
var/insertable = TRUE
/obj/item/storage/bag/trash/Initialize(mapload)
. = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.max_total_storage = 30
- atom_storage.max_slots = 30
- atom_storage.set_holdable(cant_hold_list = /obj/item/disk/nuclear)
- atom_storage.supports_smart_equip = FALSE
+
RegisterSignal(atom_storage, COMSIG_STORAGE_DUMP_POST_TRANSFER, PROC_REF(post_insertion))
/// If you dump a trash bag into something, anything that doesn't get inserted will spill out onto your feet
@@ -89,13 +81,18 @@
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
-/obj/item/storage/bag/trash/filled
-
/obj/item/storage/bag/trash/filled/PopulateContents()
- . = ..()
- for(var/i in 1 to rand(1, 7))
+ var/count = rand(1, 7)
+ for(var/_ in 1 to count)
new /obj/effect/spawner/random/trash/garbage(src)
- update_icon_state()
+
+ . = list()
+ for(var/obj/insert as anything in src)
+ if(isitem(insert))
+ insert.moveToNullspace()
+ . += insert
+ else //can't allow stuff like ashes which is /obj/effect subtype as storages don't accept those
+ qdel(insert)
/obj/item/storage/bag/trash/bluespace
name = "trash bag of holding"
@@ -103,11 +100,7 @@
icon_state = "bluetrashbag"
inhand_icon_state = "bluetrashbag"
item_flags = NO_MAT_REDEMPTION
-
-/obj/item/storage/bag/trash/bluespace/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 60
- atom_storage.max_slots = 60
+ storage_type = /datum/storage/bag/trash_bag/bluespace
/obj/item/storage/bag/trash/bluespace/cyborg
insertable = FALSE
@@ -124,22 +117,15 @@
worn_icon_state = "satchel"
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_POCKETS
w_class = WEIGHT_CLASS_NORMAL
+ storage_type = /datum/storage/bag/ore_bag
+
///If this is TRUE, the holder won't receive any messages when they fail to pick up ore through crossing it
var/spam_protection = FALSE
+ /// The mob we are listening for movement
var/mob/listeningTo
///Cooldown on balloon alerts when picking ore
COOLDOWN_DECLARE(ore_bag_balloon_cooldown)
-/obj/item/storage/bag/ore/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_HUGE
- atom_storage.max_total_storage = 50
- atom_storage.numerical_stacking = TRUE
- atom_storage.allow_quick_empty = TRUE
- atom_storage.allow_quick_gather = TRUE
- atom_storage.set_holdable(/obj/item/stack/ore)
- atom_storage.silent_for_user = TRUE
-
/obj/item/storage/bag/ore/equipped(mob/user)
. = ..()
if(listeningTo == user)
@@ -218,36 +204,18 @@
name = "mining satchel of holding"
desc = "A revolution in convenience, this satchel allows for huge amounts of ore storage. It's been outfitted with anti-malfunction safety measures."
icon_state = "satchel_bspace"
-
-/obj/item/storage/bag/ore/holding/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = INFINITY
- atom_storage.max_specific_storage = INFINITY
- atom_storage.max_total_storage = INFINITY
+ storage_type = /datum/storage/bag/ore_bag/bluespace
// -----------------------------
// Plant bag
// -----------------------------
-
/obj/item/storage/bag/plants
name = "plant bag"
icon = 'icons/obj/service/hydroponics/equipment.dmi'
icon_state = "plantbag"
worn_icon_state = "plantbag"
resistance_flags = FLAMMABLE
-
-/obj/item/storage/bag/plants/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 100
- atom_storage.max_slots = 100
- atom_storage.set_holdable(list(
- /obj/item/food/grown,
- /obj/item/graft,
- /obj/item/grown,
- /obj/item/food/honeycomb,
- /obj/item/seeds,
- ))
+ storage_type = /datum/storage/bag/plants
/obj/item/storage/bag/plants/portaseeder
name = "portable seed extractor"
@@ -292,24 +260,7 @@
icon = 'icons/obj/mining.dmi'
icon_state = "sheetsnatcher"
worn_icon_state = "satchel"
-
- var/capacity = 300 //the number of sheets it can carry.
-
-/obj/item/storage/bag/sheetsnatcher/Initialize(mapload)
- . = ..()
- atom_storage.allow_quick_empty = TRUE
- atom_storage.allow_quick_gather = TRUE
- atom_storage.numerical_stacking = TRUE
- atom_storage.set_holdable(
- can_hold_list = list(
- /obj/item/stack/sheet
- ),
- cant_hold_list = list(
- /obj/item/stack/sheet/mineral/sandstone,
- /obj/item/stack/sheet/mineral/wood,
- ),
- )
- atom_storage.max_total_storage = capacity / 2
+ storage_type = /datum/storage/bag/sheet_snatcher
// -----------------------------
// Sheet Snatcher (Cyborg)
@@ -318,7 +269,7 @@
/obj/item/storage/bag/sheetsnatcher/borg
name = "sheet snatcher 9000"
desc = ""
- capacity = 500//Borgs get more because >specialization
+ storage_type = /datum/storage/bag/sheet_snatcher_cyborg
// -----------------------------
@@ -329,55 +280,37 @@
name = "sheet snatcher EXTREME EDITION"
desc = "A Nanotrasen storage system designed which has been given post-market alterations to hold any type of sheet. Comes pre-populated with "
color = "#ff3737" // I'm too lazy to make a unique sprite
- capacity = 5000 // Hopefully enough to fit anything you need
w_class = WEIGHT_CLASS_TINY
+ storage_type = /datum/storage/bag/sheet_snatcher/debug
// Copy-pasted from the former /obj/item/storage/box/material, w/ small additions like rods, cardboard, plastic.
// "Only 20 uranium 'cause of radiation"
-/obj/item/storage/bag/sheetsnatcher/debug/PopulateContents()
- // amount should be null if it should spawn with the type's default amount
- var/static/items_inside = list(
- /obj/item/stack/sheet/iron/fifty = null,
- /obj/item/stack/sheet/glass/fifty = null,
- /obj/item/stack/sheet/rglass/fifty = null,
- /obj/item/stack/sheet/plasmaglass/fifty = null,
- /obj/item/stack/sheet/titaniumglass/fifty = null,
- /obj/item/stack/sheet/plastitaniumglass/fifty = null,
- /obj/item/stack/sheet/plasteel/fifty = null,
- /obj/item/stack/sheet/mineral/titanium/fifty = null,
- /obj/item/stack/sheet/mineral/gold = 50,
- /obj/item/stack/sheet/mineral/silver = 50,
- /obj/item/stack/sheet/mineral/plasma = 50,
- /obj/item/stack/sheet/mineral/uranium = 20,
- /obj/item/stack/sheet/mineral/diamond = 50,
- /obj/item/stack/sheet/bluespace_crystal = 50,
- /obj/item/stack/sheet/mineral/bananium = 50,
- /obj/item/stack/sheet/mineral/wood/fifty = null,
- /obj/item/stack/sheet/plastic/fifty = null,
- /obj/item/stack/sheet/runed_metal/fifty = null,
- /obj/item/stack/rods/fifty = null,
- /obj/item/stack/sheet/mineral/plastitanium = 50,
- /obj/item/stack/sheet/mineral/abductor = 50,
- /obj/item/stack/sheet/cardboard/fifty = null,
- )
- //This needs to be done here and not in Initialize() because the stacks get merged and fall out when their weight updates if this is set after PopulateContents()
- atom_storage.allow_big_nesting = TRUE
- atom_storage.max_slots = 99
- atom_storage.max_specific_storage = WEIGHT_CLASS_GIGANTIC
- atom_storage.max_total_storage = capacity
- for(var/obj/item/stack/stack_type as anything in items_inside)
- var/amt = items_inside[stack_type]
- new stack_type(src, amt, FALSE)
+/obj/item/storage/bag/sheetsnatcher/debug/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
-/obj/item/storage/bag/sheetsnatcher/debug/Initialize(mapload)
- . = ..()
- // Overrides so it can hold all possible sheets
- atom_storage.set_holdable(
- can_hold_list = list(
- /obj/item/stack/sheet,
- /obj/item/stack/sheet/mineral/sandstone,
- /obj/item/stack/sheet/mineral/wood,
- )
+ return list(
+ /obj/item/stack/sheet/iron/fifty,
+ /obj/item/stack/sheet/glass/fifty,
+ /obj/item/stack/sheet/rglass/fifty,
+ /obj/item/stack/sheet/plasmaglass/fifty,
+ /obj/item/stack/sheet/titaniumglass/fifty,
+ /obj/item/stack/sheet/plastitaniumglass/fifty,
+ /obj/item/stack/sheet/plasteel/fifty,
+ /obj/item/stack/sheet/mineral/titanium/fifty,
+ new /obj/item/stack/sheet/mineral/gold(null, 50),
+ new /obj/item/stack/sheet/mineral/silver(null, 50),
+ new /obj/item/stack/sheet/mineral/plasma(null, 50),
+ new /obj/item/stack/sheet/mineral/uranium(null, 20),
+ new /obj/item/stack/sheet/mineral/diamond(null, 50),
+ new /obj/item/stack/sheet/bluespace_crystal(null, 50),
+ new /obj/item/stack/sheet/mineral/bananium(null, 50),
+ /obj/item/stack/sheet/mineral/wood/fifty,
+ /obj/item/stack/sheet/plastic/fifty,
+ /obj/item/stack/sheet/runed_metal/fifty,
+ /obj/item/stack/rods/fifty,
+ new /obj/item/stack/sheet/mineral/plastitanium(null, 50),
+ new /obj/item/stack/sheet/mineral/abductor(null, 50),
+ /obj/item/stack/sheet/cardboard/fifty,
)
// -----------------------------
@@ -391,21 +324,9 @@
icon_state = "bookbag"
worn_icon_state = "bookbag"
resistance_flags = FLAMMABLE
+ storage_type = /datum/storage/bag/books
-/obj/item/storage/bag/books/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 21
- atom_storage.max_slots = 7
- atom_storage.set_holdable(list(
- /obj/item/book,
- /obj/item/spellbook,
- /obj/item/poster,
- ))
-
-/*
- * Trays - Agouri
- */
+/// Trays - Agouri
/obj/item/storage/bag/tray
name = "serving tray"
icon = 'icons/obj/food/containers.dmi'
@@ -420,34 +341,7 @@
slot_flags = ITEM_SLOT_BELT
custom_materials = list(/datum/material/iron=SHEET_MATERIAL_AMOUNT*1.5)
custom_price = PAYCHECK_CREW * 0.6
-
-/obj/item/storage/bag/tray/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY //Plates are required bulky to keep them out of backpacks
- atom_storage.set_holdable(
- can_hold_list = list(
- /obj/item/cigarette,
- /obj/item/food,
- /obj/item/kitchen,
- /obj/item/lighter,
- /obj/item/organ,
- /obj/item/plate,
- /obj/item/reagent_containers/condiment,
- /obj/item/reagent_containers/cup,
- /obj/item/rollingpaper,
- /obj/item/storage/box/gum,
- /obj/item/storage/box/matches,
- /obj/item/storage/fancy,
- /obj/item/trash,
- ),
- cant_hold_list = list(
- /obj/item/plate/oven_tray,
- /obj/item/reagent_containers/cup/soup_pot,
- ),
- ) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Food Containers, Food Trash, Organs, Tobacco Products, Lighters, and Kitchen Tools.
- atom_storage.insert_preposition = "on"
- atom_storage.max_slots = 8
- atom_storage.max_total_storage = 16
+ storage_type = /datum/storage/bag/tray
/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
. = ..()
@@ -503,10 +397,7 @@
icon_state = "foodtray"
desc = "A cheap metal tray to pile today's meal onto."
-/*
- * Chemistry bag
- */
-
+/// Chemistry bag
/obj/item/storage/bag/chemistry
name = "chemistry bag"
icon = 'icons/obj/medical/chemical.dmi'
@@ -514,23 +405,7 @@
worn_icon_state = "chembag"
desc = "A bag for storing pills, patches, and bottles."
resistance_flags = FLAMMABLE
-
-/obj/item/storage/bag/chemistry/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 200
- atom_storage.max_slots = 50
- atom_storage.set_holdable(list(
- /obj/item/reagent_containers/chem_pack,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/cup/glass/waterbottle,
- /obj/item/reagent_containers/cup/beaker,
- /obj/item/reagent_containers/cup/bottle,
- /obj/item/reagent_containers/cup/tube,
- /obj/item/reagent_containers/medigel,
- /obj/item/reagent_containers/applicator,
- /obj/item/reagent_containers/syringe,
- ))
-
+ storage_type = /datum/storage/bag/chemistry
/obj/item/storage/bag/bio
name = "bio bag"
@@ -539,29 +414,9 @@
worn_icon_state = "biobag"
desc = "A bag for the safe transportation and disposal of biowaste and other virulent materials."
resistance_flags = FLAMMABLE
+ storage_type = /datum/storage/bag/bio
-/obj/item/storage/bag/bio/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 200
- atom_storage.max_slots = 25
- atom_storage.set_holdable(list(
- /obj/item/bodypart,
- /obj/item/food/monkeycube,
- /obj/item/healthanalyzer,
- /obj/item/organ,
- /obj/item/reagent_containers/blood,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/cup/beaker,
- /obj/item/reagent_containers/cup/bottle,
- /obj/item/reagent_containers/cup/tube,
- /obj/item/reagent_containers/hypospray/medipen,
- /obj/item/reagent_containers/syringe,
- ))
-
-/*
- * Science bag (mostly for xenobiologists)
- */
-
+/// Science bag (mostly for xenobiologists)
/obj/item/storage/bag/xeno
name = "science bag"
icon = 'icons/obj/medical/chemical.dmi'
@@ -569,30 +424,9 @@
worn_icon_state = "xenobag"
desc = "A bag for the storage and transport of anomalous materials."
resistance_flags = FLAMMABLE
+ storage_type = /datum/storage/bag/science
-/obj/item/storage/bag/xeno/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 200
- atom_storage.max_slots = 25
- atom_storage.set_holdable(list(
- /obj/item/bodypart,
- /obj/item/food/deadmouse,
- /obj/item/food/monkeycube,
- /obj/item/organ,
- /obj/item/petri_dish,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/cup/beaker,
- /obj/item/reagent_containers/cup/bottle,
- /obj/item/reagent_containers/cup/tube,
- /obj/item/reagent_containers/syringe,
- /obj/item/slime_extract,
- /obj/item/swab,
- ))
-
-/*
- * Construction bag (for engineering, holds stock parts and electronics)
- */
-
+///Construction bag (for engineering, holds stock parts and electronics)
/obj/item/storage/bag/construction
name = "construction bag"
icon = 'icons/obj/tools.dmi'
@@ -601,22 +435,8 @@
desc = "A bag for storing small construction components."
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_POCKETS
resistance_flags = FLAMMABLE
+ storage_type = /datum/storage/bag/construction
-/obj/item/storage/bag/construction/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 100
- atom_storage.max_slots = 50
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.set_holdable(list(
- /obj/item/assembly,
- /obj/item/circuitboard,
- /obj/item/electronics,
- /obj/item/reagent_containers/cup/beaker,
- /obj/item/stack/cable_coil,
- /obj/item/stack/ore/bluespace_crystal,
- /obj/item/stock_parts,
- /obj/item/wallframe/camera,
- ))
/obj/item/storage/bag/harpoon_quiver
name = "harpoon quiver"
@@ -625,17 +445,12 @@
icon_state = "quiver"
inhand_icon_state = null
worn_icon_state = "harpoon_quiver"
-
-/obj/item/storage/bag/harpoon_quiver/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_TINY
- atom_storage.max_slots = 40
- atom_storage.max_total_storage = 100
- atom_storage.set_holdable(/obj/item/ammo_casing/harpoon)
+ storage_type = /datum/storage/bag/harpoon_quiver
/obj/item/storage/bag/harpoon_quiver/PopulateContents()
- for(var/i in 1 to 40)
- new /obj/item/ammo_casing/harpoon(src)
+ . = list()
+ for(var/_ in 1 to 40)
+ . += /obj/item/ammo_casing/harpoon
/obj/item/storage/bag/rebar_quiver
name = "rebar quiver"
@@ -646,20 +461,7 @@
desc = "A oxygen tank cut in half, used for holding sharpened rods for the rebar crossbow."
slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_SUITSTORE|ITEM_SLOT_NECK
resistance_flags = FLAMMABLE
-
-/obj/item/storage/bag/rebar_quiver/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_TINY
- atom_storage.max_slots = 10
- atom_storage.max_total_storage = 15
- atom_storage.set_holdable(list(
- /obj/item/ammo_casing/rebar,
- /obj/item/ammo_casing/rebar/syndie,
- /obj/item/ammo_casing/rebar/healium,
- /obj/item/ammo_casing/rebar/hydrogen,
- /obj/item/ammo_casing/rebar/zaukerite,
- /obj/item/ammo_casing/rebar/paperball,
- ))
+ storage_type = /datum/storage/bag/rebar_quiver
/obj/item/storage/bag/rebar_quiver/syndicate
icon_state = "syndie_quiver_0"
@@ -672,16 +474,12 @@
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
actions_types = list(/datum/action/item_action/reload_rebar)
action_slots = ALL
-
-/obj/item/storage/bag/rebar_quiver/syndicate/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 20
- atom_storage.max_total_storage = 20
- update_appearance(UPDATE_OVERLAYS)
+ storage_type = /datum/storage/bag/rebar_quiver/syndicate
/obj/item/storage/bag/rebar_quiver/syndicate/PopulateContents()
- for(var/to_fill in 1 to 20)
- new /obj/item/ammo_casing/rebar/syndie(src)
+ . = list()
+ for(var/_ in 1 to 20)
+ /obj/item/ammo_casing/rebar/syndie
/obj/item/storage/bag/rebar_quiver/syndicate/update_icon_state()
. = ..()
@@ -717,4 +515,112 @@
var/obj/item/ammo_casing/rebar/ammo_to_load = contents[1]
held_crossbow.attackby(ammo_to_load, user)
+
+/obj/item/storage/bag/fishing
+ name = "fishing bag"
+ desc = "A vibrant bag for storing caught fish."
+ icon = 'icons/obj/fishing.dmi'
+ icon_state = "fishing_bag"
+ worn_icon_state = "fishing_bag"
+ resistance_flags = FLAMMABLE
+ custom_price = PAYCHECK_CREW * 3
+ storage_type = /datum/storage/bag/fishing
+
+ ///How much holding this affects fishing difficulty
+ var/fishing_modifier = -2
+
+/obj/item/storage/bag/fishing/Initialize(mapload)
+ . = ..()
+
+ AddComponent(/datum/component/adjust_fishing_difficulty, fishing_modifier, ITEM_SLOT_HANDS)
+
+/obj/item/storage/bag/fishing/carpskin
+ name = "carpskin fishing bag"
+ desc = "A dapper fishing bag made from carpskin. You can store quite a lot of fishing gear in the small pockets formed by larger scales."
+ icon_state = "fishing_bag_carpskin"
+ worn_icon_state = "fishing_bag_carpskin"
+ resistance_flags = ACID_PROOF
+ storage_type = /datum/storage/carpskin_bag
+ fishing_modifier = -4
+ storage_type = /datum/storage/bag/fishing/carpskin
+
+/obj/item/storage/bag/quiver
+ name = "quiver"
+ desc = "Holds arrows for your bow. Good, because while pocketing arrows is possible, it surely can't be pleasant."
+ icon = 'icons/obj/weapons/bows/quivers.dmi'
+ icon_state = "quiver"
+ inhand_icon_state = null
+ worn_icon_state = "harpoon_quiver"
+ storage_type = /datum/storage/bag/quivers
+
+ /// type of arrow the quivel should hold
+ var/arrow_path = /obj/item/ammo_casing/arrow
+
+/obj/item/storage/bag/quiver/lesser
+ storage_type = /datum/storage/bag/quivers/lesser
+
+/obj/item/storage/bag/quiver/full/PopulateContents()
+ . = list()
+ for(var/i in 1 to 10)
+ . += arrow_path
+
+/obj/item/storage/bag/quiver/holy
+ name = "divine quiver"
+ desc = "Holds arrows for your divine bow, where they wait to find their target."
+ icon_state = "holyquiver"
+ inhand_icon_state = "holyquiver"
+ worn_icon_state = "holyquiver"
+ arrow_path = /obj/item/ammo_casing/arrow/holy
+
+/obj/item/storage/bag/quiver/holy/PopulateContents()
+ . = list()
+ for(var/i in 1 to 10)
+ . += arrow_path
+
+/obj/item/storage/bag/quiver/endless
+ name = "endless quiver"
+ desc = "Holds arrows for your bow. A deep digital void is contained within."
+ storage_type = /datum/storage/bag/quivers/endless
+
+/obj/item/storage/bag/quiver/endless/PopulateContents()
+ return arrow_path
+
+/*****************************Money bag********************************/
+
+/obj/item/storage/bag/money
+ name = "money bag"
+ desc = "A bag for storing your profits."
+ icon_state = "moneybag"
+ worn_icon_state = "moneybag"
+ force = 10
+ throwforce = 0
+ resistance_flags = FLAMMABLE
+ max_integrity = 100
+ w_class = WEIGHT_CLASS_BULKY
+ storage_type = /datum/storage/bag/money
+
+/obj/item/storage/bag/money/Initialize(mapload)
+ . = ..()
+ if(prob(20))
+ icon_state = "moneybagalt"
+
+/obj/item/storage/bag/money/vault/PopulateContents()
+ return flatten_quantified_list(list(
+ /obj/item/coin/silver = 2,
+ /obj/item/coin/silver = 2,
+ /obj/item/coin/gold = 2,
+ /obj/item/coin/adamantine = 1,
+ ))
+
+///Used in the dutchmen pirate shuttle.
+/obj/item/storage/bag/money/dutchmen
+ storage_type = /datum/storage/bag/dutchmen
+
+/obj/item/storage/bag/money/dutchmen/PopulateContents()
+ return flatten_quantified_list(list(
+ /obj/item/coin/silver/doubloon = 9,
+ /obj/item/coin/gold/doubloon = 9,
+ /obj/item/coin/adamantine/doubloon = 1,
+ ))
+
#undef ORE_BAG_BALOON_COOLDOWN
diff --git a/code/game/objects/items/storage/basket.dm b/code/game/objects/items/storage/basket.dm
index 6ee98e0f91d..846f9824294 100644
--- a/code/game/objects/items/storage/basket.dm
+++ b/code/game/objects/items/storage/basket.dm
@@ -5,8 +5,9 @@
icon_state = "basket"
w_class = WEIGHT_CLASS_BULKY
resistance_flags = FLAMMABLE
+ storage_type = /datum/storage/basket
-/obj/item/storage/basket/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 21
+//Easter Baskets
+/obj/item/storage/basket/easter
+ name = "Easter Basket"
+ storage_type = /datum/storage/basket/easter
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 3b2546d8af1..01a22bedd07 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -13,7 +13,9 @@
max_integrity = 300
equip_sound = 'sound/items/equip/toolbelt_equip.ogg'
w_class = WEIGHT_CLASS_BULKY
- var/content_overlays = FALSE //If this is true, the belt will gain overlays based on what it's holding
+
+ ///If this is true, the belt will gain overlays based on what it's holding
+ var/content_overlays = FALSE
/obj/item/storage/belt/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] begins belting [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
@@ -41,17 +43,7 @@
custom_premium_price = PAYCHECK_CREW * 2
drop_sound = 'sound/items/handling/toolbelt_drop.ogg'
pickup_sound = 'sound/items/handling/toolbelt_pickup.ogg'
-
-/obj/item/storage/belt/utility/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 21
- atom_storage.set_holdable(GLOB.tool_items + list(
- /obj/item/clothing/gloves,
- /obj/item/radio,
- /obj/item/melee/sickly_blade/lock,
- /obj/item/reagent_containers/cup/soda_cans,
- ))
+ storage_type = /datum/storage/utility_belt
/obj/item/storage/belt/utility/chief
name = "chief engineer's toolbelt"
@@ -64,14 +56,15 @@
preload = TRUE
/obj/item/storage/belt/utility/chief/full/PopulateContents()
- SSwardrobe.provide_type(/obj/item/screwdriver/power, src)
- SSwardrobe.provide_type(/obj/item/crowbar/power, src)
- SSwardrobe.provide_type(/obj/item/weldingtool/experimental, src)
- SSwardrobe.provide_type(/obj/item/multitool, src)
- SSwardrobe.provide_type(/obj/item/stack/cable_coil, src)
- SSwardrobe.provide_type(/obj/item/extinguisher/mini, src)
- SSwardrobe.provide_type(/obj/item/analyzer, src)
- //much roomier now that we've managed to remove two tools
+ return list(
+ SSwardrobe.provide_type(/obj/item/screwdriver/power, null),
+ SSwardrobe.provide_type(/obj/item/crowbar/power, null),
+ SSwardrobe.provide_type(/obj/item/weldingtool/experimental, null),
+ SSwardrobe.provide_type(/obj/item/multitool, null),
+ SSwardrobe.provide_type(/obj/item/stack/cable_coil, null),
+ SSwardrobe.provide_type(/obj/item/extinguisher/mini, null),
+ SSwardrobe.provide_type(/obj/item/analyzer, null),
+ )
/obj/item/storage/belt/utility/chief/full/get_types_to_preload()
var/list/to_preload = list() //Yes this is a pain. Yes this is the point
@@ -85,13 +78,15 @@
return to_preload
/obj/item/storage/belt/utility/full/PopulateContents()
- SSwardrobe.provide_type(/obj/item/screwdriver, src)
- SSwardrobe.provide_type(/obj/item/wrench, src)
- SSwardrobe.provide_type(/obj/item/weldingtool, src)
- SSwardrobe.provide_type(/obj/item/crowbar, src)
- SSwardrobe.provide_type(/obj/item/wirecutters, src)
- SSwardrobe.provide_type(/obj/item/multitool, src)
- SSwardrobe.provide_type(/obj/item/stack/cable_coil, src)
+ return list(
+ SSwardrobe.provide_type(/obj/item/screwdriver, null),
+ SSwardrobe.provide_type(/obj/item/wrench, null),
+ SSwardrobe.provide_type(/obj/item/weldingtool, null),
+ SSwardrobe.provide_type(/obj/item/crowbar, null),
+ SSwardrobe.provide_type(/obj/item/wirecutters, null),
+ SSwardrobe.provide_type(/obj/item/multitool, null),
+ SSwardrobe.provide_type(/obj/item/stack/cable_coil, null),
+ )
/obj/item/storage/belt/utility/full/get_types_to_preload()
var/list/to_preload = list() //Yes this is a pain. Yes this is the point
@@ -108,31 +103,37 @@
preload = FALSE
/obj/item/storage/belt/utility/full/powertools/PopulateContents()
- new /obj/item/screwdriver/power(src)
- new /obj/item/crowbar/power(src)
- new /obj/item/weldingtool/experimental(src)
- new /obj/item/multitool(src)
- new /obj/item/holosign_creator/atmos(src)
- new /obj/item/extinguisher/mini(src)
- new /obj/item/stack/cable_coil(src)
+ return list(
+ /obj/item/screwdriver/power,
+ /obj/item/crowbar/power,
+ /obj/item/weldingtool/experimental,
+ /obj/item/multitool,
+ /obj/item/holosign_creator/atmos,
+ /obj/item/extinguisher/mini,
+ /obj/item/stack/cable_coil,
+ )
/obj/item/storage/belt/utility/full/powertools/rcd/PopulateContents()
- new /obj/item/screwdriver/power(src)
- new /obj/item/crowbar/power(src)
- new /obj/item/weldingtool/experimental(src)
- new /obj/item/multitool(src)
- new /obj/item/construction/rcd/loaded/upgraded(src)
- new /obj/item/extinguisher/mini(src)
- new /obj/item/stack/cable_coil(src)
+ return list(
+ /obj/item/screwdriver/power,
+ /obj/item/crowbar/power,
+ /obj/item/weldingtool/experimental,
+ /obj/item/multitool,
+ /obj/item/construction/rcd/loaded/upgraded,
+ /obj/item/extinguisher/mini,
+ /obj/item/stack/cable_coil,
+ )
/obj/item/storage/belt/utility/full/engi/PopulateContents()
- SSwardrobe.provide_type(/obj/item/screwdriver, src)
- SSwardrobe.provide_type(/obj/item/wrench, src)
- SSwardrobe.provide_type(/obj/item/weldingtool/largetank, src)
- SSwardrobe.provide_type(/obj/item/crowbar, src)
- SSwardrobe.provide_type(/obj/item/wirecutters, src)
- SSwardrobe.provide_type(/obj/item/multitool, src)
- SSwardrobe.provide_type(/obj/item/stack/cable_coil, src)
+ return list(
+ SSwardrobe.provide_type(/obj/item/screwdriver, null),
+ SSwardrobe.provide_type(/obj/item/wrench, null),
+ SSwardrobe.provide_type(/obj/item/weldingtool/largetank, null),
+ SSwardrobe.provide_type(/obj/item/crowbar, null),
+ SSwardrobe.provide_type(/obj/item/wirecutters, null),
+ SSwardrobe.provide_type(/obj/item/multitool, null),
+ SSwardrobe.provide_type(/obj/item/stack/cable_coil, null),
+ )
/obj/item/storage/belt/utility/full/engi/get_types_to_preload()
var/list/to_preload = list() //Yes this is a pain. Yes this is the point
@@ -146,13 +147,15 @@
return to_preload
/obj/item/storage/belt/utility/atmostech/PopulateContents()
- SSwardrobe.provide_type(/obj/item/screwdriver, src)
- SSwardrobe.provide_type(/obj/item/wrench, src)
- SSwardrobe.provide_type(/obj/item/weldingtool, src)
- SSwardrobe.provide_type(/obj/item/crowbar, src)
- SSwardrobe.provide_type(/obj/item/wirecutters, src)
- SSwardrobe.provide_type(/obj/item/t_scanner, src)
- SSwardrobe.provide_type(/obj/item/extinguisher/mini, src)
+ return list(
+ SSwardrobe.provide_type(/obj/item/screwdriver, null),
+ SSwardrobe.provide_type(/obj/item/wrench, null),
+ SSwardrobe.provide_type(/obj/item/weldingtool, null),
+ SSwardrobe.provide_type(/obj/item/crowbar, null),
+ SSwardrobe.provide_type(/obj/item/wirecutters, null),
+ SSwardrobe.provide_type(/obj/item/t_scanner, null),
+ SSwardrobe.provide_type(/obj/item/extinguisher/mini, null),
+ )
/obj/item/storage/belt/utility/atmostech/get_types_to_preload()
var/list/to_preload = list() //Yes this is a pain. Yes this is the point
@@ -166,13 +169,15 @@
return to_preload
/obj/item/storage/belt/utility/full/inducer/PopulateContents()
- SSwardrobe.provide_type(/obj/item/screwdriver, src)
- SSwardrobe.provide_type(/obj/item/wrench, src)
- SSwardrobe.provide_type(/obj/item/weldingtool, src)
- SSwardrobe.provide_type(/obj/item/crowbar/red, src)
- SSwardrobe.provide_type(/obj/item/wirecutters, src)
- SSwardrobe.provide_type(/obj/item/multitool, src)
- SSwardrobe.provide_type(/obj/item/inducer, src)
+ return list(
+ SSwardrobe.provide_type(/obj/item/screwdriver, null),
+ SSwardrobe.provide_type(/obj/item/wrench, null),
+ SSwardrobe.provide_type(/obj/item/weldingtool, null),
+ SSwardrobe.provide_type(/obj/item/crowbar/red, null),
+ SSwardrobe.provide_type(/obj/item/wirecutters, null),
+ SSwardrobe.provide_type(/obj/item/multitool, null),
+ SSwardrobe.provide_type(/obj/item/inducer, null),
+ )
/obj/item/storage/belt/utility/full/inducer/get_types_to_preload()
var/list/to_preload = list() //Yes this is a pain. Yes this is the point
@@ -189,13 +194,15 @@
preload = FALSE
/obj/item/storage/belt/utility/syndicate/PopulateContents()
- new /obj/item/screwdriver/nuke(src)
- new /obj/item/wrench/combat(src)
- new /obj/item/weldingtool/largetank(src)
- new /obj/item/crowbar(src)
- new /obj/item/wirecutters(src)
- new /obj/item/multitool(src)
- new /obj/item/inducer/syndicate(src)
+ return list(
+ /obj/item/screwdriver/nuke,
+ /obj/item/wrench/combat,
+ /obj/item/weldingtool/largetank,
+ /obj/item/crowbar,
+ /obj/item/wirecutters,
+ /obj/item/multitool,
+ /obj/item/inducer/syndicate,
+ )
/obj/item/storage/belt/medical
name = "medical belt"
@@ -205,67 +212,7 @@
worn_icon_state = "medical"
drop_sound = 'sound/items/handling/toolbelt_drop.ogg'
pickup_sound = 'sound/items/handling/toolbelt_pickup.ogg'
-
-/obj/item/storage/belt/medical/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 21
- atom_storage.set_holdable(list(
- /obj/item/bikehorn/rubberducky,
- /obj/item/blood_filter,
- /obj/item/bonesetter,
- /obj/item/cautery,
- /obj/item/circular_saw,
- /obj/item/clothing/glasses,
- /obj/item/clothing/gloves,
- /obj/item/clothing/neck/stethoscope,
- /obj/item/clothing/mask/breath,
- /obj/item/clothing/mask/muzzle,
- /obj/item/clothing/mask/surgical,
- /obj/item/clothing/head/utility/surgerycap,
- /obj/item/construction/plumbing,
- /obj/item/dnainjector,
- /obj/item/extinguisher/mini,
- /obj/item/flashlight/pen,
- /obj/item/geiger_counter,
- /obj/item/gun/syringe/syndicate,
- /obj/item/healthanalyzer,
- /obj/item/hemostat,
- /obj/item/holosign_creator/medical,
- /obj/item/implant,
- /obj/item/implantcase,
- /obj/item/implanter,
- /obj/item/lazarus_injector,
- /obj/item/lighter,
- /obj/item/pinpointer/crew,
- /obj/item/plunger,
- /obj/item/radio,
- /obj/item/reagent_containers/blood,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/cup/beaker,
- /obj/item/reagent_containers/cup/bottle,
- /obj/item/reagent_containers/cup/tube,
- /obj/item/reagent_containers/hypospray,
- /obj/item/reagent_containers/medigel,
- /obj/item/reagent_containers/applicator,
- /obj/item/reagent_containers/spray,
- /obj/item/reagent_containers/syringe,
- /obj/item/retractor,
- /obj/item/scalpel,
- /obj/item/shears,
- /obj/item/stack/medical,
- /obj/item/stack/sticky_tape, //surgical tape
- /obj/item/stamp,
- /obj/item/sensor_device,
- /obj/item/storage/fancy/cigarettes,
- /obj/item/storage/pill_bottle,
- /obj/item/surgical_drapes, //for true paramedics
- /obj/item/surgicaldrill,
- /obj/item/tank/internals/emergency_oxygen,
- /obj/item/wrench/medical,
- /obj/item/knife/ritual,
- /obj/item/flesh_shears,
- ))
+ storage_type = /datum/storage/medical_belt
/obj/item/storage/belt/medical/paramedic
name = "EMT belt"
@@ -275,14 +222,15 @@
preload = TRUE
/obj/item/storage/belt/medical/paramedic/PopulateContents()
- SSwardrobe.provide_type(/obj/item/sensor_device, src)
- SSwardrobe.provide_type(/obj/item/stack/medical/gauze/twelve, src)
- SSwardrobe.provide_type(/obj/item/stack/medical/bone_gel, src)
- SSwardrobe.provide_type(/obj/item/stack/sticky_tape/surgical, src)
- SSwardrobe.provide_type(/obj/item/reagent_containers/syringe, src)
- SSwardrobe.provide_type(/obj/item/reagent_containers/cup/bottle/ammoniated_mercury, src)
- SSwardrobe.provide_type(/obj/item/reagent_containers/cup/bottle/formaldehyde, src)
- update_appearance()
+ return list(
+ SSwardrobe.provide_type(/obj/item/sensor_device, null),
+ SSwardrobe.provide_type(/obj/item/stack/medical/gauze/twelve, null),
+ SSwardrobe.provide_type(/obj/item/stack/medical/bone_gel, null),
+ SSwardrobe.provide_type(/obj/item/stack/sticky_tape/surgical, null),
+ SSwardrobe.provide_type(/obj/item/reagent_containers/syringe, null),
+ SSwardrobe.provide_type(/obj/item/reagent_containers/cup/bottle/ammoniated_mercury, null),
+ SSwardrobe.provide_type(/obj/item/reagent_containers/cup/bottle/formaldehyde, null),
+ )
/obj/item/storage/belt/medical/paramedic/get_types_to_preload()
var/list/to_preload = list() //Yes this is a pain. Yes this is the point
@@ -302,14 +250,15 @@
preload = TRUE
/obj/item/storage/belt/medical/ert/PopulateContents()
- SSwardrobe.provide_type(/obj/item/sensor_device, src)
- SSwardrobe.provide_type(/obj/item/pinpointer/crew, src)
- SSwardrobe.provide_type(/obj/item/scalpel/advanced, src)
- SSwardrobe.provide_type(/obj/item/retractor/advanced, src)
- SSwardrobe.provide_type(/obj/item/stack/medical/bone_gel, src)
- SSwardrobe.provide_type(/obj/item/cautery/advanced, src)
- SSwardrobe.provide_type(/obj/item/surgical_drapes, src)
- update_appearance()
+ return list(
+ SSwardrobe.provide_type(/obj/item/sensor_device, null),
+ SSwardrobe.provide_type(/obj/item/pinpointer/crew, null),
+ SSwardrobe.provide_type(/obj/item/scalpel/advanced, null),
+ SSwardrobe.provide_type(/obj/item/retractor/advanced, null),
+ SSwardrobe.provide_type(/obj/item/stack/medical/bone_gel, null),
+ SSwardrobe.provide_type(/obj/item/cautery/advanced, null),
+ SSwardrobe.provide_type(/obj/item/surgical_drapes, null),
+ )
/obj/item/storage/belt/medical/ert/get_types_to_preload()
var/list/to_preload = list()
@@ -329,39 +278,16 @@
inhand_icon_state = "security"//Could likely use a better one.
worn_icon_state = "security"
content_overlays = TRUE
-
-/obj/item/storage/belt/security/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 5
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.set_holdable(list(
- /obj/item/ammo_box,
- /obj/item/ammo_casing/shotgun,
- /obj/item/assembly/flash/handheld,
- /obj/item/clothing/glasses,
- /obj/item/clothing/gloves,
- /obj/item/flashlight/seclite,
- /obj/item/food/donut,
- /obj/item/grenade,
- /obj/item/holosign_creator/security,
- /obj/item/knife/combat,
- /obj/item/melee/baton,
- /obj/item/radio,
- /obj/item/reagent_containers/spray/pepper,
- /obj/item/restraints/handcuffs,
- /obj/item/restraints/legcuffs/bola,
- ))
- atom_storage.open_sound = 'sound/items/handling/holster_open.ogg'
- atom_storage.open_sound_vary = TRUE
- atom_storage.rustle_sound = null
+ storage_type = /datum/storage/security_belt
/obj/item/storage/belt/security/full/PopulateContents()
- new /obj/item/reagent_containers/spray/pepper(src)
- new /obj/item/restraints/handcuffs(src)
- new /obj/item/grenade/flashbang(src)
- new /obj/item/assembly/flash/handheld(src)
- new /obj/item/melee/baton/security/loaded(src)
- update_appearance()
+ return list(
+ /obj/item/reagent_containers/spray/pepper,
+ /obj/item/restraints/handcuffs,
+ /obj/item/grenade/flashbang,
+ /obj/item/assembly/flash/handheld,
+ /obj/item/melee/baton/security/loaded,
+ )
/obj/item/storage/belt/security/webbing
name = "security webbing"
@@ -371,10 +297,7 @@
worn_icon_state = "securitywebbing"
content_overlays = FALSE
custom_premium_price = PAYCHECK_COMMAND * 3
-
-/obj/item/storage/belt/security/webbing/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 6
+ storage_type = /datum/storage/security_belt/webbing
/obj/item/storage/belt/mining
name = "explorer's webbing"
@@ -383,57 +306,10 @@
inhand_icon_state = "explorer1"
worn_icon_state = "explorer1"
w_class = WEIGHT_CLASS_BULKY
-
-/obj/item/storage/belt/mining/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 6
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 20
- atom_storage.set_holdable(list(
- /obj/item/analyzer,
- /obj/item/clothing/gloves,
- /obj/item/crowbar,
- /obj/item/extinguisher/mini,
- /obj/item/flashlight,
- /obj/item/gps,
- /obj/item/mining_stabilizer,
- /obj/item/key/lasso,
- /obj/item/knife,
- /obj/item/lighter,
- /obj/item/mining_scanner,
- /obj/item/multitool,
- /obj/item/organ/monster_core,
- /obj/item/pickaxe,
- /obj/item/radio,
- /obj/item/reagent_containers/cup/glass,
- /obj/item/reagent_containers/cup/glass/bottle,
- /obj/item/reagent_containers/hypospray,
- /obj/item/reagent_containers/applicator/pill,
- /obj/item/resonator,
- /obj/item/screwdriver,
- /obj/item/shovel,
- /obj/item/stack/cable_coil,
- /obj/item/stack/marker_beacon,
- /obj/item/stack/medical,
- /obj/item/stack/ore,
- /obj/item/stack/sheet/animalhide,
- /obj/item/stack/sheet/bone,
- /obj/item/stack/sheet/sinew,
- /obj/item/storage/bag/ore,
- /obj/item/storage/fancy/cigarettes,
- /obj/item/storage/pill_bottle,
- /obj/item/survivalcapsule,
- /obj/item/t_scanner/adv_mining_scanner,
- /obj/item/weldingtool,
- /obj/item/wirecutters,
- /obj/item/wrench,
- /obj/item/wormhole_jaunter,
- /obj/item/skeleton_key,
- ))
-
+ storage_type = /datum/storage/mining_belt
/obj/item/storage/belt/mining/vendor/PopulateContents()
- new /obj/item/survivalcapsule(src)
+ return /obj/item/survivalcapsule
/obj/item/storage/belt/mining/alt
icon_state = "explorer2"
@@ -441,13 +317,19 @@
worn_icon_state = "explorer2"
/obj/item/storage/belt/mining/healing/PopulateContents()
+ var/list/obj/item/insert = list(
+ /obj/item/reagent_containers/hypospray/medipen/survival/luxury,
+ /obj/item/reagent_containers/hypospray/medipen/survival/luxury,
+ /obj/item/reagent_containers/hypospray/medipen/survival,
+ /obj/item/reagent_containers/hypospray/medipen/survival,
+ )
+
for(var/i in 1 to 2)
- new /obj/item/reagent_containers/hypospray/medipen/survival/luxury(src)
- for(var/i in 1 to 2)
- new /obj/item/reagent_containers/hypospray/medipen/survival(src)
- for(var/i in 1 to 2)
- var/obj/item/organ/monster_core/core = new /obj/item/organ/monster_core/regenerative_core/legion(src)
+ var/obj/item/organ/monster_core/core = new /obj/item/organ/monster_core/regenerative_core/legion(null)
core.preserve()
+ insert += core
+
+ return insert
/obj/item/storage/belt/mining/primitive
name = "hunter's belt"
@@ -455,10 +337,7 @@
icon_state = "ebelt"
inhand_icon_state = "ebelt"
worn_icon_state = "ebelt"
-
-/obj/item/storage/belt/mining/primitive/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 5
+ storage_type = /datum/storage/mining_belt/primitive
/obj/item/storage/belt/soulstone
name = "soul stone belt"
@@ -468,19 +347,17 @@
worn_icon_state = "soulstonebelt"
drop_sound = 'sound/items/handling/toolbelt_drop.ogg'
pickup_sound = 'sound/items/handling/toolbelt_pickup.ogg'
-
-/obj/item/storage/belt/soulstone/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 6
- atom_storage.set_holdable(/obj/item/soulstone)
+ storage_type = /datum/storage/soulstone_belt
/obj/item/storage/belt/soulstone/full/PopulateContents()
- for(var/i in 1 to 6)
- new /obj/item/soulstone/mystic(src)
+ . = list()
+ for(var/_ in 1 to 6)
+ . += /obj/item/soulstone/mystic
/obj/item/storage/belt/soulstone/full/chappy/PopulateContents()
- for(var/i in 1 to 6)
- new /obj/item/soulstone/anybody/chaplain(src)
+ . = list()
+ for(var/_ in 1 to 6)
+ . += /obj/item/soulstone/anybody/chaplain
/obj/item/storage/belt/champion
name = "championship belt"
@@ -488,12 +365,12 @@
icon_state = "championbelt"
inhand_icon_state = "championbelt"
worn_icon_state = "championbelt"
- custom_materials = list(/datum/material/gold=SMALL_MATERIAL_AMOUNT *4)
+ custom_materials = list(/datum/material/gold=SMALL_MATERIAL_AMOUNT * 4)
+ storage_type = /datum/storage/champion_belt
/obj/item/storage/belt/champion/Initialize(mapload)
. = ..()
- atom_storage.max_slots = 1
- atom_storage.set_holdable(/obj/item/clothing/mask/luchador)
+
AddComponent(/datum/component/adjust_fishing_difficulty, -2)
/obj/item/storage/belt/military
@@ -503,57 +380,55 @@
inhand_icon_state = "militarywebbing"
worn_icon_state = "militarywebbing"
resistance_flags = FIRE_PROOF
+ storage_type = /datum/storage/military_belt
-/obj/item/storage/belt/military/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
+/obj/item/storage/belt/military/assault/fisher/PopulateContents()
+ return list(
+ /obj/item/gun/ballistic/automatic/pistol/clandestine/fisher, // 11 TC: 7 (pistol) + 3 (suppressor) + lightbreaker (1 TC, black market meme/util item)
+ /obj/item/ammo_box/magazine/m10mm, // 1 TC
+ /obj/item/ammo_box/magazine/m10mm,
+ /obj/item/card/emag/doorjack, // 3 TC
+ /obj/item/knife/combat, //comparable to the e-dagger, 2 TC
+ )
/obj/item/storage/belt/military/snack
name = "tactical snack rig"
+ storage_type = /datum/storage/military_belt/snacks
/obj/item/storage/belt/military/snack/Initialize(mapload)
. = ..()
var/sponsor = pick("Donk Co.", "Waffle Corp.", "Roffle Co.", "Gorlex Marauders", "Tiger Cooperative")
desc = "A set of snack-tical webbing worn by athletes of the [sponsor] VR sports division."
- atom_storage.max_slots = 6
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.set_holdable(list(
- /obj/item/food,
- /obj/item/reagent_containers/cup/glass,
+
+/obj/item/storage/belt/military/snack/full/PopulateContents()
+ var/obj/item/snack = pick(list(
+ /obj/item/food/candy,
+ /obj/item/food/cheesiehonkers,
+ /obj/item/food/cheesynachos,
+ /obj/item/food/chips,
+ /obj/item/food/cubannachos,
+ /obj/item/food/donkpocket,
+ /obj/item/food/nachos,
+ /obj/item/food/nugget,
+ /obj/item/food/rofflewaffles,
+ /obj/item/food/sosjerky,
+ /obj/item/food/spacetwinkie,
+ /obj/item/food/spaghetti/pastatomato,
+ /obj/item/food/syndicake,
+ /obj/item/reagent_containers/cup/glass/drinkingglass/filled/nuka_cola,
+ /obj/item/reagent_containers/cup/glass/dry_ramen,
+ /obj/item/reagent_containers/cup/soda_cans/cola,
+ /obj/item/reagent_containers/cup/soda_cans/dr_gibb,
+ /obj/item/reagent_containers/cup/soda_cans/lemon_lime,
+ /obj/item/reagent_containers/cup/soda_cans/pwr_game,
+ /obj/item/reagent_containers/cup/soda_cans/space_mountain_wind,
+ /obj/item/reagent_containers/cup/soda_cans/space_up,
+ /obj/item/reagent_containers/cup/soda_cans/starkist,
))
-/obj/item/storage/belt/military/snack/full
-
-/obj/item/storage/belt/military/snack/full/Initialize(mapload)
- . = ..()
- var/amount = 5
- var/rig_snacks
- while(contents.len <= amount)
- rig_snacks = pick(list(
- /obj/item/food/candy,
- /obj/item/food/cheesiehonkers,
- /obj/item/food/cheesynachos,
- /obj/item/food/chips,
- /obj/item/food/cubannachos,
- /obj/item/food/donkpocket,
- /obj/item/food/nachos,
- /obj/item/food/nugget,
- /obj/item/food/rofflewaffles,
- /obj/item/food/sosjerky,
- /obj/item/food/spacetwinkie,
- /obj/item/food/spaghetti/pastatomato,
- /obj/item/food/syndicake,
- /obj/item/reagent_containers/cup/glass/drinkingglass/filled/nuka_cola,
- /obj/item/reagent_containers/cup/glass/dry_ramen,
- /obj/item/reagent_containers/cup/soda_cans/cola,
- /obj/item/reagent_containers/cup/soda_cans/dr_gibb,
- /obj/item/reagent_containers/cup/soda_cans/lemon_lime,
- /obj/item/reagent_containers/cup/soda_cans/pwr_game,
- /obj/item/reagent_containers/cup/soda_cans/space_mountain_wind,
- /obj/item/reagent_containers/cup/soda_cans/space_up,
- /obj/item/reagent_containers/cup/soda_cans/starkist,
- ))
- new rig_snacks(src)
+ . = list()
+ for(var/_ in 1 to 5)
+ . += snack
/obj/item/storage/belt/military/abductor
name = "agent belt"
@@ -565,13 +440,15 @@
content_overlays = TRUE
/obj/item/storage/belt/military/abductor/full/PopulateContents()
- new /obj/item/screwdriver/abductor(src)
- new /obj/item/wrench/abductor(src)
- new /obj/item/weldingtool/abductor(src)
- new /obj/item/crowbar/abductor(src)
- new /obj/item/wirecutters/abductor(src)
- new /obj/item/multitool/abductor(src)
- new /obj/item/stack/cable_coil(src)
+ return list(
+ /obj/item/screwdriver/abductor,
+ /obj/item/wrench/abductor,
+ /obj/item/weldingtool/abductor,
+ /obj/item/crowbar/abductor,
+ /obj/item/wirecutters/abductor,
+ /obj/item/multitool/abductor,
+ /obj/item/stack/cable_coil,
+ )
/obj/item/storage/belt/military/army
name = "army belt"
@@ -586,16 +463,13 @@
icon_state = "assault"
inhand_icon_state = "security"
worn_icon_state = "assault"
-
-/obj/item/storage/belt/military/assault/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 6
+ storage_type = /datum/storage/military_belt/assault
/obj/item/storage/belt/military/assault/full/PopulateContents()
- generate_items_inside(list(
+ return flatten_quantified_list(list(
/obj/item/ammo_box/magazine/wt550m9 = 4,
/obj/item/ammo_box/magazine/wt550m9/wtap = 2,
- ), src)
+ ))
/obj/item/storage/belt/grenade
name = "grenadier belt"
@@ -605,26 +479,10 @@
worn_icon_state = "grenadebeltnew"
drop_sound = 'sound/items/handling/toolbelt_drop.ogg'
pickup_sound = 'sound/items/handling/toolbelt_pickup.ogg'
-
-/obj/item/storage/belt/grenade/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 30
- atom_storage.numerical_stacking = TRUE
- atom_storage.max_total_storage = 60
- atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
- atom_storage.set_holdable(list(
- /obj/item/food/grown/cherry_bomb,
- /obj/item/food/grown/firelemon,
- /obj/item/grenade,
- /obj/item/grenade/c4,
- /obj/item/lighter,
- /obj/item/multitool,
- /obj/item/reagent_containers/cup/glass/bottle/molotov,
- /obj/item/screwdriver,
- ))
+ storage_type = /datum/storage/grenade_belt
/obj/item/storage/belt/grenade/full/PopulateContents()
- generate_items_inside(list(
+ return flatten_quantified_list(list(
/obj/item/grenade/chem_grenade/incendiary = 2,
/obj/item/grenade/empgrenade = 2,
/obj/item/grenade/frag = 10,
@@ -634,7 +492,7 @@
/obj/item/grenade/syndieminibomb = 2,
/obj/item/multitool = 1,
/obj/item/screwdriver = 1,
- ),src)
+ ))
/obj/item/storage/belt/wands
@@ -643,25 +501,26 @@
icon_state = "soulstonebelt"
inhand_icon_state = "soulstonebelt"
worn_icon_state = "soulstonebelt"
-
-/obj/item/storage/belt/wands/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 7
- atom_storage.set_holdable(/obj/item/gun/magic/wand)
+ storage_type = /datum/storage/wand_belt
/obj/item/storage/belt/wands/full/PopulateContents()
- new /obj/item/gun/magic/wand/death(src)
- new /obj/item/gun/magic/wand/resurrection(src)
- new /obj/item/gun/magic/wand/polymorph(src)
- new /obj/item/gun/magic/wand/teleport(src)
- new /obj/item/gun/magic/wand/door(src)
- new /obj/item/gun/magic/wand/fireball(src)
- new /obj/item/gun/magic/wand/shrink(src)
+ var/list/obj/item/insert = list(
+ new /obj/item/gun/magic/wand/death(null),
+ new /obj/item/gun/magic/wand/resurrection(null),
+ new /obj/item/gun/magic/wand/polymorph(null),
+ new /obj/item/gun/magic/wand/teleport(null),
+ new /obj/item/gun/magic/wand/door(null),
+ new /obj/item/gun/magic/wand/fireball(null),
+ new /obj/item/gun/magic/wand/shrink(null),
+ )
- for(var/obj/item/gun/magic/wand/W in contents) //All wands in this pack come in the best possible condition
+ //All wands in this pack come in the best possible condition
+ for(var/obj/item/gun/magic/wand/W in insert)
W.max_charges = initial(W.max_charges)
W.charges = W.max_charges
+ return insert
+
/obj/item/storage/belt/janitor
name = "janibelt"
desc = "A belt used to hold most janitorial supplies."
@@ -670,36 +529,16 @@
worn_icon_state = "janibelt"
drop_sound = 'sound/items/handling/toolbelt_drop.ogg'
pickup_sound = 'sound/items/handling/toolbelt_pickup.ogg'
-
-/obj/item/storage/belt/janitor/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 6
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL // Set to this so the light replacer can fit.
- atom_storage.set_holdable(list(
- /obj/item/access_key,
- /obj/item/assembly/mousetrap,
- /obj/item/clothing/gloves,
- /obj/item/flashlight,
- /obj/item/forcefield_projector,
- /obj/item/grenade/chem_grenade,
- /obj/item/holosign_creator,
- /obj/item/key/janitor,
- /obj/item/lightreplacer,
- /obj/item/melee/flyswatter,
- /obj/item/paint/paint_remover,
- /obj/item/plunger,
- /obj/item/pushbroom,
- /obj/item/reagent_containers/spray,
- /obj/item/soap,
- /obj/item/wirebrush,
- ))
+ storage_type = /datum/storage/janitor_belt
/obj/item/storage/belt/janitor/full/PopulateContents()
- new /obj/item/lightreplacer(src)
- new /obj/item/reagent_containers/spray/cleaner(src)
- new /obj/item/soap/nanotrasen(src)
- new /obj/item/holosign_creator(src)
- new /obj/item/melee/flyswatter(src)
+ return list(
+ /obj/item/lightreplacer,
+ /obj/item/reagent_containers/spray/cleaner,
+ /obj/item/soap/nanotrasen,
+ /obj/item/holosign_creator,
+ /obj/item/melee/flyswatter,
+ )
/obj/item/storage/belt/bandolier
name = "bandolier"
@@ -707,21 +546,7 @@
icon_state = "bandolier"
inhand_icon_state = "bandolier"
worn_icon_state = "bandolier"
-
-/obj/item/storage/belt/bandolier/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 24
- atom_storage.max_total_storage = 24
- atom_storage.numerical_stacking = TRUE
- atom_storage.allow_quick_gather = TRUE
- atom_storage.allow_quick_empty = TRUE
- atom_storage.numerical_stacking = TRUE
- atom_storage.set_holdable(list(
- /obj/item/ammo_casing/strilka310,
- /obj/item/ammo_casing/shotgun,
- /obj/item/ammo_casing/c357,
- /obj/item/ammo_casing/junk,
- ))
+ storage_type = /datum/storage/bandolier_belt
/obj/item/storage/belt/fannypack
name = "fannypack"
@@ -731,12 +556,7 @@
worn_icon_state = "fannypack_leather"
dying_key = DYE_REGISTRY_FANNYPACK
custom_price = PAYCHECK_CREW * 2
-
-/obj/item/storage/belt/fannypack/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 3
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.silent = TRUE
+ storage_type = /datum/storage/fanny_pack
/obj/item/storage/belt/fannypack/black
name = "black fannypack"
@@ -803,17 +623,12 @@
worn_icon_state = "sheath"
w_class = WEIGHT_CLASS_BULKY
interaction_flags_click = parent_type::interaction_flags_click | NEED_DEXTERITY | NEED_HANDS
+ storage_type = /datum/storage/sabre_belt
/obj/item/storage/belt/sabre/Initialize(mapload)
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
- atom_storage.max_slots = 1
- atom_storage.do_rustle = FALSE
- atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
- atom_storage.set_holdable(/obj/item/melee/sabre)
- atom_storage.click_alt_open = FALSE
-
/obj/item/storage/belt/sabre/examine(mob/user)
. = ..()
if(length(contents))
@@ -840,8 +655,7 @@
return ..()
/obj/item/storage/belt/sabre/PopulateContents()
- new /obj/item/melee/sabre(src)
- update_appearance()
+ return /obj/item/melee/sabre
/obj/item/storage/belt/grass_sabre
name = "sabre sheath"
@@ -851,17 +665,12 @@
worn_icon_state = "grass_sheath"
w_class = WEIGHT_CLASS_BULKY
interaction_flags_click = parent_type::interaction_flags_click | NEED_DEXTERITY | NEED_HANDS
+ storage_type = /datum/storage/green_sabre_belt
/obj/item/storage/belt/grass_sabre/Initialize(mapload)
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
- atom_storage.max_slots = 1
- atom_storage.do_rustle = FALSE
- atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
- atom_storage.set_holdable(/obj/item/melee/parsnip_sabre)
- atom_storage.click_alt_open = FALSE
-
/obj/item/storage/belt/grass_sabre/examine(mob/user)
. = ..()
if(length(contents))
@@ -894,24 +703,4 @@
inhand_icon_state = "utility"
worn_icon_state = "plantbelt"
content_overlays = TRUE
-
-/obj/item/storage/belt/plant/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 6
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.set_holdable(list(
- /obj/item/cultivator,
- /obj/item/geneshears,
- /obj/item/graft,
- /obj/item/gun/energy/floragun,
- /obj/item/hatchet,
- /obj/item/plant_analyzer,
- /obj/item/reagent_containers/cup/beaker,
- /obj/item/reagent_containers/cup/bottle,
- /obj/item/reagent_containers/cup/tube,
- /obj/item/reagent_containers/spray/pestspray,
- /obj/item/reagent_containers/spray/plantbgone,
- /obj/item/secateurs,
- /obj/item/seeds,
- /obj/item/shovel/spade,
- ))
+ storage_type = /datum/storage/plant_belt
diff --git a/code/game/objects/items/storage/boxes/_boxes.dm b/code/game/objects/items/storage/boxes/_boxes.dm
index 58e68b4487a..1bc9caa67ae 100644
--- a/code/game/objects/items/storage/boxes/_boxes.dm
+++ b/code/game/objects/items/storage/boxes/_boxes.dm
@@ -10,18 +10,13 @@
resistance_flags = FLAMMABLE
drop_sound = 'sound/items/handling/cardboard_box/cardboardbox_drop.ogg'
pickup_sound = 'sound/items/handling/cardboard_box/cardboardbox_pickup.ogg'
+ storage_type = /datum/storage/box
+
/// What material do we get when we fold this box?
var/foldable_result = /obj/item/stack/sheet/cardboard
/// What drawing will we get on the face of the box?
var/illustration = "writing"
-/obj/item/storage/box/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- update_appearance()
- atom_storage.open_sound = 'sound/items/handling/cardboard_box/cardboard_box_open.ogg'
- atom_storage.rustle_sound = 'sound/items/handling/cardboard_box/cardboard_box_rustle.ogg'
-
/obj/item/storage/box/suicide_act(mob/living/carbon/user)
var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)
if(myhead)
diff --git a/code/game/objects/items/storage/boxes/cargo_boxes.dm b/code/game/objects/items/storage/boxes/cargo_boxes.dm
index ea2fc77ffb1..9f73d8ebe99 100644
--- a/code/game/objects/items/storage/boxes/cargo_boxes.dm
+++ b/code/game/objects/items/storage/boxes/cargo_boxes.dm
@@ -6,10 +6,10 @@
illustration = "shipping"
/obj/item/storage/box/shipping/PopulateContents()
- var/static/items_inside = list(
- /obj/item/dest_tagger=1,
- /obj/item/universal_scanner=1,
- /obj/item/stack/package_wrap/small=2,
- /obj/item/stack/wrapping_paper/small=1,
- )
- generate_items_inside(items_inside,src)
+ return list(
+ /obj/item/dest_tagger,
+ /obj/item/universal_scanner,
+ /obj/item/stack/package_wrap/small,
+ /obj/item/stack/package_wrap/small,
+ /obj/item/stack/wrapping_paper/small
+ )
diff --git a/code/game/objects/items/storage/boxes/clothes_boxes.dm b/code/game/objects/items/storage/boxes/clothes_boxes.dm
index 86cd3931f1e..9c4432825ca 100644
--- a/code/game/objects/items/storage/boxes/clothes_boxes.dm
+++ b/code/game/objects/items/storage/boxes/clothes_boxes.dm
@@ -6,8 +6,9 @@
illustration = "latex"
/obj/item/storage/box/gloves/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/clothing/gloves/latex(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/clothing/gloves/latex
/obj/item/storage/box/masks
name = "box of sterile masks"
@@ -15,8 +16,9 @@
illustration = "sterile"
/obj/item/storage/box/masks/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/clothing/mask/surgical(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/clothing/mask/surgical
/obj/item/storage/box/rxglasses
name = "box of prescription glasses"
@@ -24,37 +26,46 @@
illustration = "glasses"
/obj/item/storage/box/rxglasses/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/clothing/glasses/regular(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/clothing/glasses/regular
/obj/item/storage/box/tape_wizard
name = "Tape Wizard - Episode 23"
desc = "A box containing the costume used by legendary entertainment icon 'Super Tape Wizard'. It got a little stuck on its way out."
-/obj/item/storage/box/tape_wizard/PopulateContents()
- new /obj/item/clothing/head/wizard/tape/fake(src)
- new /obj/item/clothing/suit/wizrobe/tape/fake(src)
- new /obj/item/staff/tape(src)
- new /obj/item/stack/sticky_tape(src)
+/obj/item/storage/box/tape_wizard/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ return list(
+ /obj/item/clothing/head/wizard/tape/fake,
+ /obj/item/clothing/suit/wizrobe/tape/fake,
+ /obj/item/staff/tape,
+ /obj/item/stack/sticky_tape,
+ )
/obj/item/storage/box/fakesyndiesuit
name = "boxed replica space suit and helmet"
desc = "A sleek, sturdy box used to hold toy spacesuits."
icon_state = "syndiebox"
illustration = "syndiesuit"
+ storage_type = /datum/storage/box/syndie_kit
/obj/item/storage/box/fakesyndiesuit/PopulateContents()
- new /obj/item/clothing/head/syndicatefake(src)
- new /obj/item/clothing/suit/syndicatefake(src)
+ return list(
+ /obj/item/clothing/head/syndicatefake,
+ /obj/item/clothing/suit/syndicatefake
+ )
/obj/item/storage/box/syndie_kit/battle_royale
name = "rumble royale broadcast kit"
desc = "Contains everything you need to host the galaxy's greatest show; Rumble Royale."
/obj/item/storage/box/syndie_kit/battle_royale/PopulateContents()
- var/obj/item/royale_implanter/implanter = new(src)
- var/obj/item/royale_remote/remote = new(src)
+ var/obj/item/royale_implanter/implanter = new(null)
+ var/obj/item/royale_remote/remote = new(null)
remote.link_implanter(implanter)
+ return list(implanter, remote)
/obj/item/storage/box/deputy
name = "box of deputy armbands"
@@ -63,161 +74,197 @@
illustration = "depband"
/obj/item/storage/box/deputy/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/clothing/accessory/armband/deputy(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/clothing/accessory/armband/deputy
/obj/item/storage/box/hero
name = "Courageous Tomb Raider - 1940's."
desc = "This legendary figure of still dubious historical accuracy is thought to have been a world-famous archeologist who embarked on countless adventures in far away lands, along with his trademark whip and fedora hat."
+ storage_type = /datum/storage/box/hero
/obj/item/storage/box/hero/PopulateContents()
- new /obj/item/clothing/head/fedora/curator(src)
- new /obj/item/clothing/shoes/workboots/mining(src)
- new /obj/item/clothing/suit/jacket/curator(src)
- new /obj/item/clothing/under/rank/civilian/curator/treasure_hunter(src)
- new /obj/item/melee/curator_whip(src)
+ return list(
+ /obj/item/clothing/head/fedora/curator,
+ /obj/item/clothing/shoes/workboots/mining,
+ /obj/item/clothing/suit/jacket/curator,
+ /obj/item/clothing/under/rank/civilian/curator/treasure_hunter,
+ /obj/item/melee/curator_whip,
+ )
/obj/item/storage/box/hero/astronaut
name = "First Man on the Moon - 1960's."
desc = "One small step for a man, one giant leap for mankind. Relive the beginnings of space exploration with this fully functional set of vintage EVA equipment."
-/obj/item/storage/box/hero/astronaut/PopulateContents()
- new /obj/item/clothing/suit/space/nasavoid(src)
- new /obj/item/clothing/head/helmet/space/nasavoid(src)
- new /obj/item/tank/internals/oxygen(src)
- new /obj/item/gps(src)
+/obj/item/storage/box/hero/astronaut/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ return list(
+ /obj/item/clothing/suit/space/nasavoid,
+ /obj/item/clothing/head/helmet/space/nasavoid,
+ /obj/item/tank/internals/oxygen,
+ /obj/item/gps,
+ )
/obj/item/storage/box/hero/scottish
name = "Braveheart, the Scottish rebel - 1300's."
desc = "Seemingly a legendary figure in the battle for Scottish independence, this historical figure is closely associated with blue facepaint, big swords, strange man skirts, and his ever enduring catchphrase: 'FREEDOM!!'"
/obj/item/storage/box/hero/scottish/PopulateContents()
- new /obj/item/claymore/weak/ceremonial(src)
- new /obj/item/clothing/shoes/sandal(src)
- new /obj/item/clothing/under/costume/kilt(src)
- new /obj/item/toy/crayon/spraycan(src)
+ return list(
+ /obj/item/claymore/weak/ceremonial,
+ /obj/item/clothing/shoes/sandal,
+ /obj/item/clothing/under/costume/kilt,
+ /obj/item/toy/crayon/spraycan,
+ )
/obj/item/storage/box/hero/carphunter
name = "Carp Hunter, Wildlife Expert - 2506."
desc = "Despite his nickname, this wildlife expert was mainly known as a passionate environmentalist and conservationist, often coming in contact with dangerous wildlife to teach about the beauty of nature."
/obj/item/storage/box/hero/carphunter/PopulateContents()
- new /obj/item/clothing/mask/gas/carp(src)
- new /obj/item/clothing/suit/hooded/carp_costume/spaceproof/old(src)
- new /obj/item/knife/hunting(src)
- new /obj/item/storage/box/papersack/meat(src)
+ return list(
+ /obj/item/clothing/mask/gas/carp,
+ /obj/item/clothing/suit/hooded/carp_costume/spaceproof/old,
+ /obj/item/knife/hunting,
+ /obj/item/storage/box/papersack/meat,
+ )
/obj/item/storage/box/hero/mothpioneer
name = "Mothic Fleet Pioneer - 2429."
desc = "Some claim that the fleet engineers are directly responsible for most modern advancements in spacefaring designs. Although the exact details of their past contributions are somewhat fuzzy, their ingenuity remains unmatched and unquestioned to this day."
/obj/item/storage/box/hero/mothpioneer/PopulateContents()
- new /obj/item/clothing/head/mothcap/original(src)
- new /obj/item/clothing/suit/mothcoat/original(src)
- new /obj/item/crowbar(src)
- new /obj/item/flashlight/lantern(src)
- new /obj/item/screwdriver(src)
- new /obj/item/stack/sheet/glass/fifty(src)
- new /obj/item/stack/sheet/iron/fifty(src)
- new /obj/item/wrench(src)
+ return list(
+ /obj/item/clothing/head/mothcap/original,
+ /obj/item/clothing/suit/mothcoat/original,
+ /obj/item/crowbar,
+ /obj/item/flashlight/lantern,
+ /obj/item/screwdriver,
+ /obj/item/stack/sheet/glass/fifty,
+ /obj/item/stack/sheet/iron/fifty,
+ /obj/item/wrench,
+ )
/obj/item/storage/box/hero/etherealwarden
name = "Ethereal Trailwarden - 2450's."
desc = "Many fantastical stories are told of valiant trail wardens, even by offworlders who, thanks to their guidance, avoided an untimely demise while traveling the sometimes treacherous roads of Sprout. In truth their job entails far more walking and fixing roads than slaying dragons, but it is no less important and well respected: keeping the roads and trails safe and well maintained is for many settlements a matter of survival."
/obj/item/storage/box/hero/etherealwarden/PopulateContents()
- new /obj/item/clothing/suit/hooded/ethereal_raincoat/trailwarden(src)
- new /obj/item/clothing/under/ethereal_tunic/trailwarden(src)
- new /obj/item/storage/backpack/saddlepack(src)
+ return list(
+ /obj/item/clothing/suit/hooded/ethereal_raincoat/trailwarden,
+ /obj/item/clothing/under/ethereal_tunic/trailwarden,
+ /obj/item/storage/backpack/saddlepack,
+ )
/obj/item/storage/box/hero/journalist
name = "Assassinated by CIA - 1984." // Literally
desc = "Many courageous individuals risked their lives to report on events the government sought to keep hidden from the public, ensuring that the truth remained buried and unheard. These garments are replicas of the clothing worn by one such 'journalist,' a silent sentinel in the fight for truth."
/obj/item/storage/box/hero/journalist/PopulateContents()
- new /obj/item/clothing/under/costume/buttondown/slacks(src)
- new /obj/item/clothing/suit/toggle/suspenders(src)
- new /obj/item/clothing/neck/tie/red(src)
- new /obj/item/clothing/head/fedora/beige/press(src)
- new /obj/item/clothing/accessory/press_badge(src)
- new /obj/item/clothing/suit/hazardvest/press(src)
- new /obj/item/radio/entertainment/microphone/physical(src)
- new /obj/item/radio/entertainment/speakers/physical(src)
- new /obj/item/clipboard(src)
- new /obj/item/taperecorder(src)
- new /obj/item/camera(src)
- new /obj/item/wallframe/telescreen/entertainment(src)
+ return list(
+ /obj/item/clothing/under/costume/buttondown/slacks,
+ /obj/item/clothing/suit/toggle/suspenders,
+ /obj/item/clothing/neck/tie/red,
+ /obj/item/clothing/head/fedora/beige/press,
+ /obj/item/clothing/accessory/press_badge,
+ /obj/item/clothing/suit/hazardvest/press,
+ /obj/item/radio/entertainment/microphone/physical,
+ /obj/item/radio/entertainment/speakers/physical,
+ /obj/item/clipboard,
+ /obj/item/taperecorder,
+ /obj/item/camera,
+ /obj/item/wallframe/telescreen/entertainment,
+ )
/obj/item/storage/box/holy
name = "Templar Kit"
+ storage_type = /datum/storage/box/holy
/// This item is used to generate a preview image for this set.
/// It could be any item, doesn't even necessarily need to be something in the kit
var/obj/item/typepath_for_preview = /obj/item/clothing/suit/chaplainsuit/armor/templar
/obj/item/storage/box/holy/PopulateContents()
- new /obj/item/clothing/head/helmet/chaplain(src)
- new /obj/item/clothing/suit/chaplainsuit/armor/templar(src)
+ return list(
+ /obj/item/clothing/head/helmet/chaplain,
+ /obj/item/clothing/suit/chaplainsuit/armor/templar,
+ )
/obj/item/storage/box/holy/clock
name = "Forgotten kit"
typepath_for_preview = /obj/item/clothing/suit/chaplainsuit/armor/clock
/obj/item/storage/box/holy/clock/PopulateContents()
- new /obj/item/clothing/head/helmet/chaplain/clock(src)
- new /obj/item/clothing/suit/chaplainsuit/armor/clock(src)
+ return list(
+ /obj/item/clothing/head/helmet/chaplain/clock,
+ /obj/item/clothing/suit/chaplainsuit/armor/clock,
+ )
/obj/item/storage/box/holy/student
name = "Profane Scholar Kit"
typepath_for_preview = /obj/item/clothing/suit/chaplainsuit/armor/studentuni
/obj/item/storage/box/holy/student/PopulateContents()
- new /obj/item/clothing/suit/chaplainsuit/armor/studentuni(src)
- new /obj/item/clothing/head/helmet/chaplain/cage(src)
+ return list(
+ /obj/item/clothing/suit/chaplainsuit/armor/studentuni,
+ /obj/item/clothing/head/helmet/chaplain/cage,
+ )
/obj/item/storage/box/holy/sentinel
name = "Stone Sentinel Kit"
typepath_for_preview = /obj/item/clothing/suit/chaplainsuit/armor/ancient
/obj/item/storage/box/holy/sentinel/PopulateContents()
- new /obj/item/clothing/suit/chaplainsuit/armor/ancient(src)
- new /obj/item/clothing/head/helmet/chaplain/ancient(src)
+ return list(
+ /obj/item/clothing/suit/chaplainsuit/armor/ancient,
+ /obj/item/clothing/head/helmet/chaplain/ancient,
+ )
/obj/item/storage/box/holy/witchhunter
name = "Witchhunter Kit"
typepath_for_preview = /obj/item/clothing/suit/chaplainsuit/armor/witchhunter
/obj/item/storage/box/holy/witchhunter/PopulateContents()
- new /obj/item/clothing/suit/chaplainsuit/armor/witchhunter(src)
- new /obj/item/clothing/head/helmet/chaplain/witchunter_hat(src)
+ return list(
+ /obj/item/clothing/suit/chaplainsuit/armor/witchhunter,
+ /obj/item/clothing/head/helmet/chaplain/witchunter_hat,
+ )
/obj/item/storage/box/holy/adept
name = "Divine Adept Kit"
typepath_for_preview = /obj/item/clothing/suit/chaplainsuit/armor/adept
/obj/item/storage/box/holy/adept/PopulateContents()
- new /obj/item/clothing/suit/chaplainsuit/armor/adept(src)
- new /obj/item/clothing/head/helmet/chaplain/adept(src)
+ return list(
+ /obj/item/clothing/suit/chaplainsuit/armor/adept,
+ /obj/item/clothing/head/helmet/chaplain/adept,
+ )
/obj/item/storage/box/holy/follower
name = "Followers of the Chaplain Kit"
typepath_for_preview = /obj/item/clothing/suit/hooded/chaplain_hoodie/leader
+ storage_type = /datum/storage/box/holy/follower
/obj/item/storage/box/holy/follower/PopulateContents()
- new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
- new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
- new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
- new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
- new /obj/item/clothing/suit/hooded/chaplain_hoodie/leader(src)
+ return list(
+ /obj/item/clothing/suit/hooded/chaplain_hoodie,
+ /obj/item/clothing/suit/hooded/chaplain_hoodie,
+ /obj/item/clothing/suit/hooded/chaplain_hoodie,
+ /obj/item/clothing/suit/hooded/chaplain_hoodie,
+ /obj/item/clothing/suit/hooded/chaplain_hoodie/leader,
+ )
/obj/item/storage/box/holy/divine_archer
name = "Divine Archer Kit"
typepath_for_preview = /obj/item/clothing/suit/hooded/chaplain_hoodie/divine_archer
/obj/item/storage/box/holy/divine_archer/PopulateContents()
- new /obj/item/clothing/under/rank/civilian/chaplain/divine_archer(src)
- new /obj/item/clothing/suit/hooded/chaplain_hoodie/divine_archer(src)
- new /obj/item/clothing/gloves/divine_archer(src)
- new /obj/item/clothing/shoes/divine_archer(src)
+ return list(
+ /obj/item/clothing/under/rank/civilian/chaplain/divine_archer,
+ /obj/item/clothing/suit/hooded/chaplain_hoodie/divine_archer,
+ /obj/item/clothing/gloves/divine_archer,
+ /obj/item/clothing/shoes/divine_archer,
+ )
/obj/item/storage/box/floor_camo
name = "floor tile camo box"
@@ -226,18 +273,26 @@
espionage uniform used by the very best. Providing the best \
flexibility, with our latest Camo-tech threads. Perfect for \
risky-espionage hallway operations. Enjoy our product!"
+ storage_type = /datum/storage/box/floor_camo
-/obj/item/storage/box/floor_camo/PopulateContents()
- new /obj/item/clothing/under/syndicate/floortilecamo(src)
- new /obj/item/clothing/mask/floortilebalaclava(src)
- new /obj/item/clothing/gloves/combat/floortile(src)
- new /obj/item/clothing/shoes/jackboots/floortile(src)
- new /obj/item/storage/backpack/floortile(src)
+/obj/item/storage/box/floor_camo/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ return list(
+ /obj/item/clothing/under/syndicate/floortilecamo,
+ /obj/item/clothing/mask/floortilebalaclava,
+ /obj/item/clothing/gloves/combat/floortile,
+ /obj/item/clothing/shoes/jackboots/floortile,
+ /obj/item/storage/backpack/floortile,
+ )
/obj/item/storage/box/collar_bomb
name = "collar bomb box"
desc = "A small print on the back reads 'For research purposes only. Handle with care. In case of emergency, call the following number:'... the rest is scratched out with a marker..."
-/obj/item/storage/box/collar_bomb/PopulateContents()
- var/obj/item/collar_bomb_button/button = new(src)
- new /obj/item/clothing/neck/collar_bomb(src, button)
+/obj/item/storage/box/collar_bomb/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ var/obj/item/collar_bomb_button/button = new(null)
+
+ return list(button, new /obj/item/clothing/neck/collar_bomb(null, button))
diff --git a/code/game/objects/items/storage/boxes/engineering_boxes.dm b/code/game/objects/items/storage/boxes/engineering_boxes.dm
index 70a64f69da5..a7b4969abcc 100644
--- a/code/game/objects/items/storage/boxes/engineering_boxes.dm
+++ b/code/game/objects/items/storage/boxes/engineering_boxes.dm
@@ -6,8 +6,9 @@
illustration = "grenade"
/obj/item/storage/box/metalfoam/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/grenade/chem_grenade/metalfoam(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/grenade/chem_grenade/metalfoam
/obj/item/storage/box/smart_metal_foam
name = "box of smart metal foam grenades"
@@ -15,39 +16,35 @@
illustration = "grenade"
/obj/item/storage/box/smart_metal_foam/PopulateContents()
- for(var/i in 1 to 7)
- new/obj/item/grenade/chem_grenade/smart_metal_foam(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/grenade/chem_grenade/smart_metal_foam
/obj/item/storage/box/debugtools
name = "box of debug tools"
icon_state = "syndiebox"
+ storage_type = /datum/storage/box/debug_tools
-/obj/item/storage/box/debugtools/Initialize(mapload)
- . = ..()
- atom_storage.allow_big_nesting = TRUE
- atom_storage.max_slots = 99
- atom_storage.max_specific_storage = WEIGHT_CLASS_GIGANTIC
- atom_storage.max_total_storage = 99
+/obj/item/storage/box/debugtools/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
-/obj/item/storage/box/debugtools/PopulateContents()
- var/static/items_inside = list(
- /obj/item/card/emag=1,
- /obj/item/construction/rcd/combat/admin=1,
- /obj/item/disk/tech_disk/debug=1,
- /obj/item/flashlight/emp/debug=1,
- /obj/item/geiger_counter=1,
- /obj/item/healthanalyzer/advanced=1,
- /obj/item/modular_computer/pda/heads/captain=1,
- /obj/item/pipe_dispenser=1,
- /obj/item/stack/spacecash/c1000=50,
- /obj/item/storage/box/beakers/bluespace=1,
- /obj/item/storage/box/beakers/variety=1,
- /obj/item/storage/bag/sheetsnatcher/debug=1,
- /obj/item/uplink/debug=1,
- /obj/item/uplink/nuclear/debug=1,
- /obj/item/clothing/ears/earmuffs/debug = 1,
- )
- generate_items_inside(items_inside,src)
+ return list(
+ /obj/item/card/emag,
+ /obj/item/construction/rcd/combat/admin,
+ /obj/item/disk/tech_disk/debug,
+ /obj/item/flashlight/emp/debug,
+ /obj/item/geiger_counter,
+ /obj/item/healthanalyzer/advanced,
+ /obj/item/modular_computer/pda/heads/captain,
+ /obj/item/pipe_dispenser,
+ /obj/item/storage/box/beakers/bluespace,
+ /obj/item/storage/box/beakers/variety,
+ /obj/item/storage/bag/sheetsnatcher/debug,
+ /obj/item/uplink/debug,
+ /obj/item/uplink/nuclear/debug,
+ /obj/item/clothing/ears/earmuffs/debug,
+ new /obj/item/stack/spacecash/c1000(null, 50),
+ )
/obj/item/storage/box/plastic
name = "plastic box"
@@ -63,9 +60,9 @@
illustration = "emergencytank"
/obj/item/storage/box/emergencytank/PopulateContents()
- ..()
- for(var/i in 1 to 7)
- new /obj/item/tank/internals/emergency_oxygen(src) //in case anyone ever wants to do anything with spawning them, apart from crafting the box
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/tank/internals/emergency_oxygen
/obj/item/storage/box/engitank
name = "extended-capacity emergency oxygen tank box"
@@ -73,9 +70,9 @@
illustration = "extendedtank"
/obj/item/storage/box/engitank/PopulateContents()
- ..()
- for(var/i in 1 to 7)
- new /obj/item/tank/internals/emergency_oxygen/engi(src) //in case anyone ever wants to do anything with spawning them, apart from crafting the box
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/tank/internals/emergency_oxygen/engi
/obj/item/storage/box/stickers/chief_engineer
name = "CE approved sticker pack"
@@ -83,5 +80,8 @@
illustration = "label_ce"
/obj/item/storage/box/stickers/chief_engineer/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/sticker/chief_engineer(src)
+ return list(
+ /obj/item/sticker/chief_engineer,
+ /obj/item/sticker/chief_engineer,
+ /obj/item/sticker/chief_engineer,
+ )
diff --git a/code/game/objects/items/storage/boxes/fishing_boxes.dm b/code/game/objects/items/storage/boxes/fishing_boxes.dm
new file mode 100644
index 00000000000..1501683f3fb
--- /dev/null
+++ b/code/game/objects/items/storage/boxes/fishing_boxes.dm
@@ -0,0 +1,44 @@
+
+/obj/item/storage/box/fishing_hooks
+ name = "fishing hook set"
+ illustration = "fish"
+ custom_price = PAYCHECK_CREW * 2
+
+/obj/item/storage/box/fishing_hooks/PopulateContents()
+ return list(
+ /obj/item/fishing_hook/magnet,
+ /obj/item/fishing_hook/shiny,
+ /obj/item/fishing_hook/weighted,
+ )
+
+/obj/item/storage/box/fishing_hooks/master/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ . = ..()
+ . += /obj/item/fishing_hook/stabilized
+ . += /obj/item/fishing_hook/jaws
+
+/obj/item/storage/box/fishing_lines
+ name = "fishing line set"
+ illustration = "fish"
+ custom_price = PAYCHECK_CREW * 2
+
+/obj/item/storage/box/fishing_lines/PopulateContents()
+ return list(
+ /obj/item/fishing_line/bouncy,
+ /obj/item/fishing_line/reinforced,
+ /obj/item/fishing_line/cloaked,
+ )
+
+/obj/item/storage/box/fishing_lines/master/PopulateContents()
+ . = ..()
+ . += /obj/item/fishing_line/auto_reel
+
+/obj/item/storage/box/fish_debug
+ name = "box full of fish"
+ illustration = "fish"
+
+/obj/item/storage/box/fish_debug/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
+
+ return subtypesof(/obj/item/fish)
diff --git a/code/game/objects/items/storage/boxes/flat_boxes.dm b/code/game/objects/items/storage/boxes/flat_boxes.dm
index b9544c0e548..f1a4a73511f 100644
--- a/code/game/objects/items/storage/boxes/flat_boxes.dm
+++ b/code/game/objects/items/storage/boxes/flat_boxes.dm
@@ -3,11 +3,7 @@
desc = "A cardboard box folded in a manner that is optimal for concealment, rather than for stowing your belongings."
icon_state = "flat"
illustration = null
-
-/obj/item/storage/box/flat/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE, INVISIBILITY_OBSERVER, use_anchor = TRUE, tilt_tile = TRUE)
- atom_storage.max_slots = 3
+ storage_type = /datum/storage/box/flat
/obj/item/storage/box/proc/flatten_box()
if(istype(loc, /obj/item/storage) || type != /obj/item/storage/box || contents.len)
diff --git a/code/game/objects/items/storage/boxes/food_boxes.dm b/code/game/objects/items/storage/boxes/food_boxes.dm
index fd4bef33758..ce2e30033c8 100644
--- a/code/game/objects/items/storage/boxes/food_boxes.dm
+++ b/code/game/objects/items/storage/boxes/food_boxes.dm
@@ -9,12 +9,7 @@
var/donktype = /obj/item/food/donkpocket
/obj/item/storage/box/donkpockets/PopulateContents()
- for(var/i in 1 to 6)
- new donktype(src)
-
-/obj/item/storage/box/donkpockets/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/food/donkpocket)
+ return donktype
/obj/item/storage/box/donkpockets/donkpocketspicy
name = "box of spicy-flavoured donk-pockets"
@@ -146,19 +141,24 @@
desc = "It's slightly moist and smells like a slaughterhouse."
/obj/item/storage/box/papersack/meat/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/food/meat/slab(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/food/meat/slab
/obj/item/storage/box/papersack/wheat
desc = "It's a bit dusty, and smells like a barnyard."
/obj/item/storage/box/papersack/wheat/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/food/grown/wheat(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/food/grown/wheat
/obj/item/storage/box/ingredients //This box is for the randomly chosen version the chef used to spawn with, it shouldn't actually exist.
name = "ingredients box"
illustration = "fruit"
+ storage_type = /datum/storage/box/ingredients
+
+ ///Used in describing the box
var/theme_name
/obj/item/storage/box/ingredients/Initialize(mapload)
@@ -172,154 +172,175 @@
theme_name = "wildcard"
/obj/item/storage/box/ingredients/wildcard/PopulateContents()
+ var/static/list/obj/item/foods = list(
+ /obj/item/food/chocolatebar,
+ /obj/item/food/grown/apple,
+ /obj/item/food/grown/banana,
+ /obj/item/food/grown/cabbage,
+ /obj/item/food/grown/carrot,
+ /obj/item/food/grown/cherries,
+ /obj/item/food/grown/chili,
+ /obj/item/food/grown/corn,
+ /obj/item/food/grown/cucumber,
+ /obj/item/food/grown/mushroom/chanterelle,
+ /obj/item/food/grown/mushroom/plumphelmet,
+ /obj/item/food/grown/potato,
+ /obj/item/food/grown/potato/sweet,
+ /obj/item/food/grown/soybeans,
+ /obj/item/food/grown/tomato,
+ )
+
+ var/list/obj/item/insert = list()
for(var/i in 1 to 7)
- var/random_food = pick(
- /obj/item/food/chocolatebar,
- /obj/item/food/grown/apple,
- /obj/item/food/grown/banana,
- /obj/item/food/grown/cabbage,
- /obj/item/food/grown/carrot,
- /obj/item/food/grown/cherries,
- /obj/item/food/grown/chili,
- /obj/item/food/grown/corn,
- /obj/item/food/grown/cucumber,
- /obj/item/food/grown/mushroom/chanterelle,
- /obj/item/food/grown/mushroom/plumphelmet,
- /obj/item/food/grown/potato,
- /obj/item/food/grown/potato/sweet,
- /obj/item/food/grown/soybeans,
- /obj/item/food/grown/tomato,
- )
- new random_food(src)
+ insert += pick(foods)
+
+ return insert
/obj/item/storage/box/ingredients/fiesta
theme_name = "fiesta"
/obj/item/storage/box/ingredients/fiesta/PopulateContents()
- new /obj/item/food/tortilla(src)
- for(var/i in 1 to 2)
- new /obj/item/food/grown/chili(src)
- new /obj/item/food/grown/corn(src)
- new /obj/item/food/grown/soybeans(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/tortilla = 1,
+ /obj/item/food/grown/chili = 2,
+ /obj/item/food/grown/corn = 2,
+ /obj/item/food/grown/soybeans = 2,
+ ))
/obj/item/storage/box/ingredients/italian
theme_name = "italian"
/obj/item/storage/box/ingredients/italian/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/food/grown/tomato(src)
- new /obj/item/food/meatball(src)
- new /obj/item/reagent_containers/cup/glass/bottle/wine(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/grown/tomato = 3,
+ /obj/item/food/meatball = 3,
+ /obj/item/reagent_containers/cup/glass/bottle/wine = 1,
+ ))
/obj/item/storage/box/ingredients/vegetarian
theme_name = "vegetarian"
/obj/item/storage/box/ingredients/vegetarian/PopulateContents()
- for(var/i in 1 to 2)
- new /obj/item/food/grown/carrot(src)
- new /obj/item/food/grown/apple(src)
- new /obj/item/food/grown/corn(src)
- new /obj/item/food/grown/eggplant(src)
- new /obj/item/food/grown/potato(src)
- new /obj/item/food/grown/tomato(src)
+ return list(
+ /obj/item/food/grown/carrot,
+ /obj/item/food/grown/carrot,
+ /obj/item/food/grown/apple,
+ /obj/item/food/grown/corn,
+ /obj/item/food/grown/eggplant,
+ /obj/item/food/grown/potato,
+ /obj/item/food/grown/tomato,
+ )
/obj/item/storage/box/ingredients/american
theme_name = "american"
/obj/item/storage/box/ingredients/american/PopulateContents()
- for(var/i in 1 to 2)
- new /obj/item/food/grown/corn(src)
- new /obj/item/food/grown/potato(src)
- new /obj/item/food/grown/tomato(src)
- new /obj/item/food/meatball(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/grown/corn = 2,
+ /obj/item/food/grown/potato = 2,
+ /obj/item/food/grown/tomato = 2,
+ /obj/item/food/meatball = 1,
+ ))
/obj/item/storage/box/ingredients/fruity
theme_name = "fruity"
-/obj/item/storage/box/ingredients/fruity/PopulateContents()
- for(var/i in 1 to 2)
- new /obj/item/food/grown/apple(src)
- new /obj/item/food/grown/citrus/orange(src)
- new /obj/item/food/grown/citrus/lemon(src)
- new /obj/item/food/grown/citrus/lime(src)
- new /obj/item/food/grown/watermelon(src)
+/obj/item/storage/box/ingredients/fruity/PopulateContents(datum/storage_config/config)
+ config.compute_max_total_weight = TRUE
+
+ return flatten_quantified_list(list(
+ /obj/item/food/grown/apple = 2,
+ /obj/item/food/grown/citrus/orange = 2,
+ /obj/item/food/grown/citrus/lemon = 1,
+ /obj/item/food/grown/citrus/lime = 1,
+ /obj/item/food/grown/watermelon = 1,
+ ))
/obj/item/storage/box/ingredients/sweets
theme_name = "sweets"
/obj/item/storage/box/ingredients/sweets/PopulateContents()
- for(var/i in 1 to 2)
- new /obj/item/food/grown/cherries(src)
- new /obj/item/food/grown/banana(src)
- new /obj/item/food/chocolatebar(src)
- new /obj/item/food/grown/apple(src)
- new /obj/item/food/grown/cocoapod(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/grown/cherries = 2,
+ /obj/item/food/grown/banana = 2,
+ /obj/item/food/chocolatebar = 1,
+ /obj/item/food/grown/apple = 1,
+ /obj/item/food/grown/cocoapod = 1,
+ ))
/obj/item/storage/box/ingredients/delights
theme_name = "delights"
/obj/item/storage/box/ingredients/delights/PopulateContents()
- for(var/i in 1 to 2)
- new /obj/item/food/grown/bluecherries(src)
- new /obj/item/food/grown/potato/sweet(src)
- new /obj/item/food/grown/berries(src)
- new /obj/item/food/grown/cocoapod(src)
- new /obj/item/food/grown/vanillapod(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/grown/bluecherries = 2,
+ /obj/item/food/grown/potato/sweet = 2,
+ /obj/item/food/grown/berries = 1,
+ /obj/item/food/grown/cocoapod = 1,
+ /obj/item/food/grown/vanillapod = 1,
+ ))
/obj/item/storage/box/ingredients/grains
theme_name = "grains"
/obj/item/storage/box/ingredients/grains/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/food/grown/oat(src)
- new /obj/item/food/grown/cocoapod(src)
- new /obj/item/food/grown/wheat(src)
- new /obj/item/food/honeycomb(src)
- new /obj/item/seeds/poppy(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/grown/oat = 3,
+ /obj/item/food/grown/cocoapod = 1,
+ /obj/item/food/grown/wheat = 1,
+ /obj/item/food/honeycomb = 1,
+ /obj/item/seeds/poppy = 1,
+ ))
/obj/item/storage/box/ingredients/carnivore
theme_name = "carnivore"
/obj/item/storage/box/ingredients/carnivore/PopulateContents()
- new /obj/item/food/meat/slab/bear(src)
- new /obj/item/food/meat/slab/corgi(src)
- new /obj/item/food/meat/slab/penguin(src)
- new /obj/item/food/meat/slab/spider(src)
- new /obj/item/food/meat/slab/xeno(src)
- new /obj/item/food/meatball(src)
- new /obj/item/food/spidereggs(src)
+ return list(
+ /obj/item/food/meat/slab/bear,
+ /obj/item/food/meat/slab/corgi,
+ /obj/item/food/meat/slab/penguin,
+ /obj/item/food/meat/slab/spider,
+ /obj/item/food/meat/slab/xeno,
+ /obj/item/food/meatball,
+ /obj/item/food/spidereggs,
+ )
/obj/item/storage/box/ingredients/exotic
theme_name = "exotic"
/obj/item/storage/box/ingredients/exotic/PopulateContents()
- for(var/i in 1 to 2)
- new /obj/item/food/fishmeat/carp(src)
- new /obj/item/food/grown/cabbage(src)
- new /obj/item/food/grown/soybeans(src)
- new /obj/item/food/grown/chili(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/fishmeat/carp = 2,
+ /obj/item/food/grown/cabbage = 2,
+ /obj/item/food/grown/soybeans = 2,
+ /obj/item/food/grown/chili = 1,
+ ))
/obj/item/storage/box/ingredients/seafood
theme_name = "seafood"
/obj/item/storage/box/ingredients/seafood/PopulateContents()
- for(var/i in 1 to 2)
- new /obj/item/food/fishmeat/armorfish(src)
- new /obj/item/food/fishmeat/carp(src)
- new /obj/item/food/fishmeat/moonfish(src)
- new /obj/item/food/fishmeat/gunner_jellyfish/supply(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/fishmeat/armorfish = 2,
+ /obj/item/food/fishmeat/carp = 2,
+ /obj/item/food/fishmeat/moonfish = 2,
+ /obj/item/food/fishmeat/gunner_jellyfish/supply = 1,
+ ))
/obj/item/storage/box/ingredients/salads
theme_name = "salads"
/obj/item/storage/box/ingredients/salads/PopulateContents()
- new /obj/item/food/grown/cabbage(src)
- new /obj/item/food/grown/carrot(src)
- new /obj/item/food/grown/olive(src)
- new /obj/item/food/grown/onion/red(src)
- new /obj/item/food/grown/onion/red(src)
- new /obj/item/food/grown/tomato(src)
- new /obj/item/reagent_containers/condiment/olive_oil(src)
+ return list(
+ /obj/item/food/grown/cabbage,
+ /obj/item/food/grown/carrot,
+ /obj/item/food/grown/olive,
+ /obj/item/food/grown/onion/red,
+ /obj/item/food/grown/onion/red,
+ /obj/item/food/grown/tomato,
+ /obj/item/reagent_containers/condiment/olive_oil,
+ )
/obj/item/storage/box/ingredients/random
theme_name = "random"
@@ -340,15 +361,12 @@
illustration = null
foldable_result = null
custom_price = PAYCHECK_CREW
-
-/obj/item/storage/box/gum/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/food/bubblegum)
- atom_storage.max_slots = 4
+ storage_type = /datum/storage/box/bubble_gum
/obj/item/storage/box/gum/PopulateContents()
- for(var/i in 1 to 4)
- new/obj/item/food/bubblegum(src)
+ . = list()
+ for(var/_ in 1 to 4)
+ . += /obj/item/food/bubblegum
/obj/item/storage/box/gum/nicotine
name = "nicotine gum packet"
@@ -357,8 +375,9 @@
custom_premium_price = PAYCHECK_CREW * 1.5
/obj/item/storage/box/gum/nicotine/PopulateContents()
- for(var/i in 1 to 4)
- new/obj/item/food/bubblegum/nicotine(src)
+ . = list()
+ for(var/_ in 1 to 4)
+ . += /obj/item/food/bubblegum/nicotine
/obj/item/storage/box/gum/happiness
name = "HP+ gum packet"
@@ -373,8 +392,9 @@
desc += " You can faintly make out the word 'Hemopagopril' was once scribbled on it."
/obj/item/storage/box/gum/happiness/PopulateContents()
- for(var/i in 1 to 4)
- new/obj/item/food/bubblegum/happiness(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/bubblegum/happiness = 4,
+ ))
/obj/item/storage/box/gum/bubblegum
name = "bubblegum gum packet"
@@ -382,8 +402,9 @@
icon_state = "bubblegum_bubblegum"
/obj/item/storage/box/gum/bubblegum/PopulateContents()
- for(var/i in 1 to 4)
- new/obj/item/food/bubblegum/bubblegum(src)
+ return flatten_quantified_list(list(
+ /obj/item/food/bubblegum/bubblegum = 4,
+ ))
/obj/item/storage/box/mothic_rations
name = "Mothic Rations Pack"
@@ -392,16 +413,20 @@
illustration = null
/obj/item/storage/box/mothic_rations/PopulateContents()
+ var/static/list/obj/item/food = list(
+ /obj/item/food/sustenance_bar = 10,
+ /obj/item/food/sustenance_bar/cheese = 5,
+ /obj/item/food/sustenance_bar/mint = 5,
+ /obj/item/food/sustenance_bar/neapolitan = 5,
+ /obj/item/food/sustenance_bar/wonka = 1,
+ )
+
+ var/list/obj/item/insert = list()
for(var/i in 1 to 3)
- var/random_food = pick_weight(list(
- /obj/item/food/sustenance_bar = 10,
- /obj/item/food/sustenance_bar/cheese = 5,
- /obj/item/food/sustenance_bar/mint = 5,
- /obj/item/food/sustenance_bar/neapolitan = 5,
- /obj/item/food/sustenance_bar/wonka = 1,
- ))
- new random_food(src)
- new /obj/item/storage/box/gum/wake_up(src)
+ insert += pick_weight(food)
+ insert += /obj/item/storage/box/gum/wake_up
+
+ return insert
/obj/item/storage/box/tiziran_goods
name = "Tiziran Farm-Fresh Pack"
@@ -410,89 +435,122 @@
illustration = null
/obj/item/storage/box/tiziran_goods/PopulateContents()
- for(var/i in 1 to 12)
- var/random_food = pick_weight(list(
- /obj/item/food/bread/root = 2,
- /obj/item/food/grown/ash_flora/seraka = 2,
- /obj/item/food/grown/korta_nut = 10,
- /obj/item/food/grown/korta_nut/sweet = 2,
- /obj/item/food/liver_pate = 5,
- /obj/item/food/lizard_dumplings = 5,
- /obj/item/food/moonfish_caviar = 5,
- /obj/item/food/root_flatbread = 5,
- /obj/item/food/rootroll = 5,
- /obj/item/food/spaghetti/nizaya = 5,
- ))
- new random_food(src)
+ var/static/list/obj/item/food = list(
+ /obj/item/food/bread/root = 2,
+ /obj/item/food/grown/ash_flora/seraka = 2,
+ /obj/item/food/grown/korta_nut = 10,
+ /obj/item/food/grown/korta_nut/sweet = 2,
+ /obj/item/food/liver_pate = 5,
+ /obj/item/food/lizard_dumplings = 5,
+ /obj/item/food/moonfish_caviar = 5,
+ /obj/item/food/root_flatbread = 5,
+ /obj/item/food/rootroll = 5,
+ /obj/item/food/spaghetti/nizaya = 5,
+ )
+
+ var/list/obj/item/insert = list()
+ for(var/i in 1 to 3)
+ insert += pick_weight(food)
+
+ return insert
/obj/item/storage/box/tiziran_cans
name = "Tiziran Canned Goods Pack"
desc = "A box containing an assortment of canned Tiziran goods- to be eaten as is, or used in cooking."
icon_state = "lizard_package"
illustration = null
+ storage_type = /datum/storage/box/tiziran_cans
/obj/item/storage/box/tiziran_cans/PopulateContents()
+ var/static/list/obj/item/food = list(
+ /obj/item/food/bread/root = 2,
+ /obj/item/food/grown/ash_flora/seraka = 2,
+ /obj/item/food/grown/korta_nut = 10,
+ /obj/item/food/grown/korta_nut/sweet = 2,
+ /obj/item/food/liver_pate = 5,
+ /obj/item/food/lizard_dumplings = 5,
+ /obj/item/food/moonfish_caviar = 5,
+ /obj/item/food/root_flatbread = 5,
+ /obj/item/food/rootroll = 5,
+ /obj/item/food/spaghetti/nizaya = 5,
+ )
+
+ var/list/obj/item/insert = list()
for(var/i in 1 to 8)
- var/random_food = pick_weight(list(
- /obj/item/food/canned/jellyfish = 5,
- /obj/item/food/canned/desert_snails = 5,
- /obj/item/food/canned/larvae = 5,
- ))
- new random_food(src)
+ insert += pick_weight(food)
+
+ return insert
/obj/item/storage/box/tiziran_meats
name = "Tiziran Meatmarket Pack"
desc = "A box containing an assortment of fresh-frozen Tiziran meats and fish- the keys to lizard cooking."
icon_state = "lizard_package"
illustration = null
+ storage_type = /datum/storage/box/tiziran_meats
/obj/item/storage/box/tiziran_meats/PopulateContents()
+ var/static/list/obj/item/food = list(
+ /obj/item/food/fishmeat/armorfish = 5,
+ /obj/item/food/fishmeat/gunner_jellyfish = 5,
+ /obj/item/food/fishmeat/moonfish = 5,
+ /obj/item/food/meat/slab = 5,
+ )
+
+ var/list/obj/item/insert = list()
for(var/i in 1 to 10)
- var/random_food = pick_weight(list(
- /obj/item/food/fishmeat/armorfish = 5,
- /obj/item/food/fishmeat/gunner_jellyfish = 5,
- /obj/item/food/fishmeat/moonfish = 5,
- /obj/item/food/meat/slab = 5,
- ))
- new random_food(src)
+ insert += pick_weight(food)
+
+ return insert
/obj/item/storage/box/mothic_goods
name = "Mothic Farm-Fresh Pack"
desc = "A box containing an assortment of Mothic cooking supplies."
icon_state = "moth_package"
illustration = null
+ storage_type = /datum/storage/box/mothic_goods
-/obj/item/storage/box/mothic_goods/PopulateContents()
+/obj/item/storage/box/mothic_goods/PopulateContents(datum/storage_config/config)
+ config.compute_max_total_weight = TRUE
+
+ var/static/list/obj/item/food = list(
+ /obj/item/food/cheese/cheese_curds = 5,
+ /obj/item/food/cheese/curd_cheese = 5,
+ /obj/item/food/cheese/firm_cheese = 5,
+ /obj/item/food/cheese/mozzarella = 5,
+ /obj/item/food/cheese/wheel = 5,
+ /obj/item/food/grown/toechtauese = 10,
+ /obj/item/reagent_containers/condiment/cornmeal = 5,
+ /obj/item/reagent_containers/condiment/olive_oil = 5,
+ /obj/item/reagent_containers/condiment/yoghurt = 5,
+ )
+
+ var/list/obj/item/insert = list()
for(var/i in 1 to 12)
- var/random_food = pick_weight(list(
- /obj/item/food/cheese/cheese_curds = 5,
- /obj/item/food/cheese/curd_cheese = 5,
- /obj/item/food/cheese/firm_cheese = 5,
- /obj/item/food/cheese/mozzarella = 5,
- /obj/item/food/cheese/wheel = 5,
- /obj/item/food/grown/toechtauese = 10,
- /obj/item/reagent_containers/condiment/cornmeal = 5,
- /obj/item/reagent_containers/condiment/olive_oil = 5,
- /obj/item/reagent_containers/condiment/yoghurt = 5,
- ))
- new random_food(src)
+ insert += pick_weight(food)
+
+ return insert
/obj/item/storage/box/mothic_cans_sauces
name = "Mothic Pantry Pack"
desc = "A box containing an assortment of Mothic canned goods and premade sauces."
icon_state = "moth_package"
illustration = null
+ storage_type = /datum/storage/box/mothic_cans_sauces
/obj/item/storage/box/mothic_cans_sauces/PopulateContents()
+ var/static/list/obj/item/food = list(
+ /obj/item/food/bechamel_sauce = 5,
+ /obj/item/food/canned/pine_nuts = 5,
+ /obj/item/food/canned/tomatoes = 5,
+ /obj/item/food/pesto = 5,
+ /obj/item/food/tomato_sauce = 5,
+ )
+
+ var/list/obj/item/insert = list()
for(var/i in 1 to 8)
- var/random_food = pick_weight(list(
- /obj/item/food/bechamel_sauce = 5,
- /obj/item/food/canned/pine_nuts = 5,
- /obj/item/food/canned/tomatoes = 5,
- /obj/item/food/pesto = 5,
- /obj/item/food/tomato_sauce = 5,
- ))
- new random_food(src)
+ insert += pick_weight(food)
+
+ return insert
/obj/item/storage/box/condimentbottles
name = "box of condiment bottles"
@@ -500,8 +558,9 @@
illustration = "condiment"
/obj/item/storage/box/condimentbottles/PopulateContents()
- for(var/i in 1 to 6)
- new /obj/item/reagent_containers/condiment(src)
+ return flatten_quantified_list(list(
+ /obj/item/reagent_containers/condiment = 6,
+ ))
/obj/item/storage/box/coffeepack
@@ -510,18 +569,21 @@
desc = "A bag containing fresh, dry coffee arabica beans. Ethically sourced and packaged by Waffle Corp."
illustration = null
icon = 'icons/obj/food/containers.dmi'
+ storage_type = /datum/storage/box/coffee
+
+ /// Bean type to initialize the box with
var/beantype = /obj/item/food/grown/coffee
-/obj/item/storage/box/coffeepack/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/food/grown/coffee)
-
/obj/item/storage/box/coffeepack/PopulateContents()
- atom_storage.max_slots = 5
+
+ var/list/obj/item/food = list()
for(var/i in 1 to 5)
- var/obj/item/food/grown/coffee/bean = new beantype(src)
+ var/obj/item/food/grown/coffee/bean = new beantype(null)
ADD_TRAIT(bean, TRAIT_DRIED, ELEMENT_TRAIT(type))
bean.add_atom_colour(COLOR_DRIED_TAN, FIXED_COLOUR_PRIORITY) //give them the tan just like from the drying rack
+ food += bean
+
+ return food
/obj/item/storage/box/coffeepack/robusta
icon_state = "robusta_beans"
diff --git a/code/game/objects/items/storage/boxes/implant_boxes.dm b/code/game/objects/items/storage/boxes/implant_boxes.dm
index 1da12ba3285..13059e80b6d 100644
--- a/code/game/objects/items/storage/boxes/implant_boxes.dm
+++ b/code/game/objects/items/storage/boxes/implant_boxes.dm
@@ -5,13 +5,12 @@
illustration = "implant"
/obj/item/storage/box/trackimp/PopulateContents()
- var/static/items_inside = list(
+ return flatten_quantified_list(list(
/obj/item/implantcase/tracking = 4,
/obj/item/implanter = 1,
/obj/item/implantpad = 1,
/obj/item/locator = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/box/minertracker
name = "boxed tracking implant kit"
@@ -19,14 +18,13 @@
illustration = "implant"
/obj/item/storage/box/minertracker/PopulateContents()
- var/static/items_inside = list(
+ return flatten_quantified_list(list(
/obj/item/implantcase/tracking = 2,
/obj/item/implantcase/beacon = 2,
/obj/item/implanter = 1,
/obj/item/implantpad = 1,
/obj/item/locator = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/box/chemimp
name = "boxed chemical implant kit"
@@ -34,12 +32,11 @@
illustration = "implant"
/obj/item/storage/box/chemimp/PopulateContents()
- var/static/items_inside = list(
+ return flatten_quantified_list(list(
/obj/item/implantcase/chem = 5,
/obj/item/implanter = 1,
/obj/item/implantpad = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/box/exileimp
name = "boxed exile implant kit"
@@ -47,12 +44,11 @@
illustration = "implant"
/obj/item/storage/box/exileimp/PopulateContents()
- var/static/items_inside = list(
+ return flatten_quantified_list(list(
/obj/item/implantcase/exile = 5,
/obj/item/implanter = 1,
/obj/item/implantpad = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/box/beaconimp
name = "boxed beacon implant kit"
@@ -61,12 +57,11 @@
illustration = "implant"
/obj/item/storage/box/beaconimp/PopulateContents()
- var/static/items_inside = list(
+ return flatten_quantified_list(list(
/obj/item/implantcase/beacon = 3,
/obj/item/implanter = 1,
/obj/item/implantpad = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/box/teleport_blocker
name = "boxed bluespace grounding implant kit"
@@ -74,9 +69,8 @@
illustration = "implant"
/obj/item/storage/box/teleport_blocker/PopulateContents()
- var/static/items_inside = list(
+ return flatten_quantified_list(list(
/obj/item/implantcase/teleport_blocker = 2,
/obj/item/implanter = 1,
/obj/item/implantpad = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
diff --git a/code/game/objects/items/storage/boxes/job_boxes.dm b/code/game/objects/items/storage/boxes/job_boxes.dm
index b1bc443d0f5..83c89f0d612 100644
--- a/code/game/objects/items/storage/boxes/job_boxes.dm
+++ b/code/game/objects/items/storage/boxes/job_boxes.dm
@@ -30,29 +30,31 @@
/obj/item/storage/box/survival/PopulateContents()
if(crafted)
- return
+ return NONE
+
+ . = list()
if(!isnull(mask_type))
- new mask_type(src)
+ . += mask_type
if(!isnull(internal_type))
- new internal_type(src)
+ . += internal_type
if(!isnull(medipen_type))
- new medipen_type(src)
+ . += medipen_type
if(give_premium_goods && HAS_TRAIT(SSstation, STATION_TRAIT_PREMIUM_INTERNALS))
- new /obj/item/flashlight/flare(src)
- new /obj/item/radio/off(src)
+ . += /obj/item/flashlight/flare
+ . += /obj/item/radio/off
if(HAS_TRAIT(SSstation, STATION_TRAIT_RADIOACTIVE_NEBULA))
- new /obj/item/storage/pill_bottle/potassiodide(src)
+ . += /obj/item/storage/pill_bottle/potassiodide
if(give_hook && length(SSmapping.levels_by_trait(ZTRAIT_STATION)) > 1)
- new /obj/item/climbing_hook/emergency(src)
+ . += /obj/item/climbing_hook/emergency
/obj/item/storage/box/survival/radio/PopulateContents()
- ..() // we want the survival stuff too.
- new /obj/item/radio/off(src)
+ . = ..() // we want the survival stuff too.
+ . += /obj/item/radio/off
/obj/item/storage/box/survival/proc/wardrobe_removal()
if(!isplasmaman(loc)) //We need to specially fill the box with plasmaman gear, since it's intended for one
@@ -73,9 +75,9 @@
mask_type = /obj/item/clothing/mask/gas/explorer/folded
/obj/item/storage/box/survival/mining/PopulateContents()
- ..()
- new /obj/item/crowbar/red(src)
- new /obj/item/healthanalyzer/simple/miner(src)
+ . = ..()
+ . += /obj/item/crowbar/red
+ . += /obj/item/healthanalyzer/simple/miner
// Engineer survival box
/obj/item/storage/box/survival/engineer
@@ -85,8 +87,8 @@
internal_type = /obj/item/tank/internals/emergency_oxygen/engi
/obj/item/storage/box/survival/engineer/radio/PopulateContents()
- ..() // we want the regular items too.
- new /obj/item/radio/off(src)
+ . = ..() // we want the regular items too.
+ . += /obj/item/radio/off
// Syndie survival box
/obj/item/storage/box/survival/syndie
@@ -96,14 +98,16 @@
illustration = "extendedtank"
mask_type = /obj/item/clothing/mask/gas/syndicate
internal_type = /obj/item/tank/internals/emergency_oxygen/engi
- medipen_type = /obj/item/reagent_containers/hypospray/medipen/atropine
+ medipen_type = /obj/item/reagent_containers/hypospray/medipen/atropine
-/obj/item/storage/box/survival/syndie/PopulateContents()
- ..()
- new /obj/item/crowbar/red(src)
- new /obj/item/screwdriver/red(src)
- new /obj/item/weldingtool/mini(src)
- new /obj/item/paper/fluff/operative(src)
+/obj/item/storage/box/survival/syndie/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_count = TRUE
+
+ . = ..()
+ . += /obj/item/crowbar/red
+ . += /obj/item/screwdriver/red
+ . += /obj/item/weldingtool/mini
+ . += /obj/item/paper/fluff/operative
/obj/item/storage/box/survival/centcom
name = "emergency response survival box"
@@ -113,15 +117,15 @@
/obj/item/storage/box/survival/centcom/PopulateContents()
. = ..()
- new /obj/item/crowbar(src)
+ . += /obj/item/crowbar
// Security survival box
/obj/item/storage/box/survival/security
mask_type = /obj/item/clothing/mask/gas/sechailer
/obj/item/storage/box/survival/security/radio/PopulateContents()
- ..() // we want the regular stuff too
- new /obj/item/radio/off(src)
+ . = ..() // we want the regular stuff too
+ . += /obj/item/radio/off
// Medical survival box
/obj/item/storage/box/survival/medical
@@ -205,9 +209,11 @@
// Special stuff for medical hugboxes.
/obj/item/storage/box/hug/medical/PopulateContents()
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/ointment(src)
- new /obj/item/reagent_containers/hypospray/medipen(src)
+ return list(
+ /obj/item/stack/medical/bruise_pack,
+ /obj/item/stack/medical/ointment,
+ /obj/item/reagent_containers/hypospray/medipen,
+ )
//Clown survival box
/obj/item/storage/box/survival/hug
@@ -222,11 +228,13 @@
/obj/item/storage/box/survival/hug/PopulateContents()
if(!random_funny_internals)
return ..()
+
internal_type = pick(
- /obj/item/tank/internals/emergency_oxygen/engi/clown/n2o,
- /obj/item/tank/internals/emergency_oxygen/engi/clown/bz,
- /obj/item/tank/internals/emergency_oxygen/engi/clown/helium,
- )
+ /obj/item/tank/internals/emergency_oxygen/engi/clown/n2o,
+ /obj/item/tank/internals/emergency_oxygen/engi/clown/bz,
+ /obj/item/tank/internals/emergency_oxygen/engi/clown/helium,
+ )
+
return ..()
//Mime survival box
@@ -252,57 +260,88 @@
for Medical Officers who just take the box for themselves."
/obj/item/storage/box/hug/plushes/PopulateContents()
- for(var/i in 1 to 7)
- var/plush_path = /obj/effect/spawner/random/entertainment/plushie
- new plush_path(src)
+ for(var/_ in 1 to 7)
+ new /obj/effect/spawner/random/entertainment/plushie(src)
+
+ . = list()
+ for(var/obj/item/insert as anything in src)
+ insert.moveToNullspace()
+ . += insert
/obj/item/storage/box/survival/mining/bonus
mask_type = null
internal_type = /obj/item/tank/internals/emergency_oxygen/double
/obj/item/storage/box/survival/mining/bonus/PopulateContents()
- ..()
- new /obj/item/gps/mining(src)
- new /obj/item/t_scanner/adv_mining_scanner(src)
+ . = ..()
+ . += /obj/item/gps/mining
+ . += /obj/item/t_scanner/adv_mining_scanner
/obj/item/storage/box/miner_modkits
name = "miner modkit/trophy box"
desc = "Contains every modkit and trophy in the game."
+ storage_type = /datum/storage/box/minor_modkits
-/obj/item/storage/box/miner_modkits/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(list(/obj/item/borg/upgrade/modkit, /obj/item/crusher_trophy))
- atom_storage.numerical_stacking = TRUE
+/obj/item/storage/box/miner_modkits/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
-/obj/item/storage/box/miner_modkits/PopulateContents()
+ . = list()
for(var/trophy in subtypesof(/obj/item/crusher_trophy))
- new trophy(src)
+ . += trophy
for(var/modkit in subtypesof(/obj/item/borg/upgrade/modkit))
for(var/i in 1 to 10) //minimum cost ucrrently is 20, and 2 pkas, so lets go with that
- new modkit(src)
+ . += modkit
/obj/item/storage/box/skillchips
name = "box of skillchips"
desc = "Contains one copy of every skillchip"
-/obj/item/storage/box/skillchips/PopulateContents()
- var/list/skillchips = subtypesof(/obj/item/skillchip)
+/obj/item/storage/box/skillchips/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
- for(var/skillchip in skillchips)
- new skillchip(src)
+ return subtypesof(/obj/item/skillchip)
/obj/item/storage/box/skillchips/science
name = "box of science job skillchips"
desc = "Contains spares of every science job skillchip."
/obj/item/storage/box/skillchips/science/PopulateContents()
- new/obj/item/skillchip/job/roboticist(src)
- new/obj/item/skillchip/job/roboticist(src)
+ return list(
+ /obj/item/skillchip/job/roboticist,
+ /obj/item/skillchip/job/roboticist,
+ )
/obj/item/storage/box/skillchips/engineering
name = "box of engineering job skillchips"
desc = "Contains spares of every engineering job skillchip."
/obj/item/storage/box/skillchips/engineering/PopulateContents()
- new/obj/item/skillchip/job/engineer(src)
- new/obj/item/skillchip/job/engineer(src)
+ return list(
+ /obj/item/skillchip/job/engineer,
+ /obj/item/skillchip/job/engineer,
+ )
+
+///Chaplin boxes
+/obj/item/storage/box/itemset/crusader/blue/PopulateContents(datum/storage_config/config)
+ config.contents_are_exceptions = TRUE
+ config.compute_max_item_weight = TRUE
+ config.compute_max_total_weight = TRUE
+
+ return list(
+ /obj/item/clothing/suit/chaplainsuit/armor/crusader/blue,
+ /obj/item/clothing/head/helmet/plate/crusader/blue,
+ /obj/item/clothing/gloves/plate/blue,
+ /obj/item/clothing/shoes/plate/blue,
+ )
+
+/obj/item/storage/box/itemset/crusader/red/PopulateContents(datum/storage_config/config)
+ config.contents_are_exceptions = TRUE
+ config.compute_max_item_weight = TRUE
+ config.compute_max_total_weight = TRUE
+
+ return list(
+ /obj/item/clothing/suit/chaplainsuit/armor/crusader/red,
+ /obj/item/clothing/head/helmet/plate/crusader/red,
+ /obj/item/clothing/gloves/plate/red,
+ /obj/item/clothing/shoes/plate/red,
+ )
diff --git a/code/game/objects/items/storage/boxes/medical_boxes.dm b/code/game/objects/items/storage/boxes/medical_boxes.dm
index d83aa337754..717e462a938 100644
--- a/code/game/objects/items/storage/boxes/medical_boxes.dm
+++ b/code/game/objects/items/storage/boxes/medical_boxes.dm
@@ -6,17 +6,20 @@
illustration = "syringe"
/obj/item/storage/box/syringes/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/reagent_containers/syringe(src)
+ . += /obj/item/reagent_containers/syringe
/obj/item/storage/box/syringes/variety
name = "syringe variety box"
/obj/item/storage/box/syringes/variety/PopulateContents()
- new /obj/item/reagent_containers/syringe(src)
- new /obj/item/reagent_containers/syringe/lethal(src)
- new /obj/item/reagent_containers/syringe/piercing(src)
- new /obj/item/reagent_containers/syringe/bluespace(src)
+ return list(
+ /obj/item/reagent_containers/syringe,
+ /obj/item/reagent_containers/syringe/lethal,
+ /obj/item/reagent_containers/syringe/piercing,
+ /obj/item/reagent_containers/syringe/bluespace,
+ )
/obj/item/storage/box/medipens
name = "box of medipens"
@@ -24,45 +27,52 @@
illustration = "epipen"
/obj/item/storage/box/medipens/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/reagent_containers/hypospray/medipen(src)
+ . += /obj/item/reagent_containers/hypospray/medipen
/obj/item/storage/box/medipens/utility
name = "stimpack value kit"
desc = "A box with several stimpack medipens for the economical miner."
illustration = "epipen"
-/obj/item/storage/box/medipens/utility/PopulateContents()
- ..() // includes regular medipens.
+/obj/item/storage/box/medipens/utility/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_count = TRUE
+
+ . = ..() // includes regular medipens.
for(var/i in 1 to 5)
- new /obj/item/reagent_containers/hypospray/medipen/stimpack(src)
+ . += /obj/item/reagent_containers/hypospray/medipen/stimpack
/obj/item/storage/box/beakers
name = "box of beakers"
illustration = "beaker"
/obj/item/storage/box/beakers/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/reagent_containers/cup/beaker( src )
+ . += /obj/item/reagent_containers/cup/beaker
/obj/item/storage/box/beakers/bluespace
name = "box of bluespace beakers"
illustration = "beaker"
/obj/item/storage/box/beakers/bluespace/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/reagent_containers/cup/beaker/bluespace(src)
+ . += /obj/item/reagent_containers/cup/beaker/bluespace
/obj/item/storage/box/beakers/variety
name = "beaker variety box"
/obj/item/storage/box/beakers/variety/PopulateContents()
- new /obj/item/reagent_containers/cup/beaker(src)
- new /obj/item/reagent_containers/cup/beaker/bluespace(src)
- new /obj/item/reagent_containers/cup/beaker/large(src)
- new /obj/item/reagent_containers/cup/beaker/meta(src)
- new /obj/item/reagent_containers/cup/beaker/noreact(src)
- new /obj/item/reagent_containers/cup/beaker/plastic(src)
+ return list(
+ /obj/item/reagent_containers/cup/beaker,
+ /obj/item/reagent_containers/cup/beaker/bluespace,
+ /obj/item/reagent_containers/cup/beaker/large,
+ /obj/item/reagent_containers/cup/beaker/meta,
+ /obj/item/reagent_containers/cup/beaker/noreact,
+ /obj/item/reagent_containers/cup/beaker/plastic,
+ )
/obj/item/storage/box/medigels
name = "box of medical gels"
@@ -70,8 +80,9 @@
illustration = "medgel"
/obj/item/storage/box/medigels/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/reagent_containers/medigel( src )
+ . += /obj/item/reagent_containers/medigel
/obj/item/storage/box/injectors
name = "box of DNA injectors"
@@ -79,11 +90,12 @@
illustration = "dna"
/obj/item/storage/box/injectors/PopulateContents()
- var/static/items_inside = list(
+ var/static/items_inside = flatten_quantified_list(list(
/obj/item/dnainjector/h2m = 3,
/obj/item/dnainjector/m2h = 3,
- )
- generate_items_inside(items_inside,src)
+ ))
+
+ return items_inside
/obj/item/storage/box/bodybags
name = "body bags"
@@ -91,9 +103,9 @@
illustration = "bodybags"
/obj/item/storage/box/bodybags/PopulateContents()
- ..()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/bodybag(src)
+ . += /obj/item/bodybag
/obj/item/storage/box/pillbottles
name = "box of pill bottles"
@@ -101,16 +113,19 @@
illustration = "pillbox"
/obj/item/storage/box/pillbottles/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/storage/pill_bottle(src)
+ . += /obj/item/storage/pill_bottle
-/obj/item/storage/box/plumbing/PopulateContents()
- var/list/items_inside = list(
- /obj/item/stock_parts/water_recycler = 2,
- /obj/item/stack/ducts/fifty = 1,
- /obj/item/stack/sheet/iron/ten = 1,
- )
- generate_items_inside(items_inside, src)
+/obj/item/storage/box/plumbing/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ return list(
+ /obj/item/stock_parts/water_recycler,
+ /obj/item/stock_parts/water_recycler,
+ /obj/item/stack/ducts/fifty,
+ /obj/item/stack/sheet/iron/ten,
+ )
/obj/item/storage/box/evilmeds
name = "box of premium medicine"
@@ -120,15 +135,16 @@
/obj/item/storage/box/evilmeds/PopulateContents()
var/static/list/items_inside = list(
- /obj/item/reagent_containers/cup/beaker/meta/omnizine = 1,
- /obj/item/reagent_containers/cup/beaker/meta/sal_acid = 1,
- /obj/item/reagent_containers/cup/beaker/meta/oxandrolone = 1,
- /obj/item/reagent_containers/cup/beaker/meta/pen_acid = 1,
- /obj/item/reagent_containers/cup/beaker/meta/atropine = 1,
- /obj/item/reagent_containers/cup/beaker/meta/salbutamol = 1,
- /obj/item/reagent_containers/cup/beaker/meta/rezadone = 1,
+ /obj/item/reagent_containers/cup/beaker/meta/omnizine,
+ /obj/item/reagent_containers/cup/beaker/meta/sal_acid,
+ /obj/item/reagent_containers/cup/beaker/meta/oxandrolone,
+ /obj/item/reagent_containers/cup/beaker/meta/pen_acid,
+ /obj/item/reagent_containers/cup/beaker/meta/atropine,
+ /obj/item/reagent_containers/cup/beaker/meta/salbutamol,
+ /obj/item/reagent_containers/cup/beaker/meta/rezadone,
)
- generate_items_inside(items_inside, src)
+
+ return items_inside
/obj/item/storage/box/bandages
name = "box of bandages"
@@ -143,19 +159,12 @@
illustration = null
w_class = WEIGHT_CLASS_SMALL
custom_price = PAYCHECK_CREW * 1.75
-
-/obj/item/storage/box/bandages/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 6
- atom_storage.set_holdable(list(
- /obj/item/stack/medical/bandage,
- /obj/item/reagent_containers/applicator/pill,
- /obj/item/reagent_containers/applicator/patch,
- ))
+ storage_type = /datum/storage/box/bandages
/obj/item/storage/box/bandages/PopulateContents()
+ . = list()
for(var/i in 1 to 5)
- new /obj/item/stack/medical/bandage(src)
+ . += /obj/item/stack/medical/bandage
/obj/item/storage/box/bandages/update_icon_state()
. = ..()
diff --git a/code/game/objects/items/storage/boxes/science_boxes.dm b/code/game/objects/items/storage/boxes/science_boxes.dm
index 27d69a493d1..4d564d5d5bb 100644
--- a/code/game/objects/items/storage/boxes/science_boxes.dm
+++ b/code/game/objects/items/storage/boxes/science_boxes.dm
@@ -6,8 +6,9 @@
illustration = "swab"
/obj/item/storage/box/swab/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/swab(src)
+ . += /obj/item/swab
/obj/item/storage/box/petridish
name = "box of petri dishes"
@@ -15,8 +16,9 @@
illustration = "petridish"
/obj/item/storage/box/petridish/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/petri_dish(src)
+ . += /obj/item/petri_dish
/obj/item/storage/box/plumbing
name = "box of plumbing supplies"
@@ -29,26 +31,25 @@
illustration = "disk_kit"
/obj/item/storage/box/disks/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/disk/data(src)
+ . += /obj/item/disk/data
/obj/item/storage/box/monkeycubes
name = "monkey cube box"
desc = "Drymate brand monkey cubes. Just add water!"
icon_state = "monkeycubebox"
illustration = null
+ custom_price = PAYCHECK_CREW * 2
+ storage_type = /datum/storage/box/monkey_cubes
+
/// Which type of cube are we spawning in this box?
var/cube_type = /obj/item/food/monkeycube
- custom_price = PAYCHECK_CREW * 2
-
-/obj/item/storage/box/monkeycubes/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 7
- atom_storage.set_holdable(/obj/item/food/monkeycube)
/obj/item/storage/box/monkeycubes/PopulateContents()
+ . = list()
for(var/i in 1 to 5)
- new cube_type(src)
+ . += cube_type
/obj/item/storage/box/monkeycubes/syndicate
desc = "Waffle Corp. brand monkey cubes. Just add water and a dash of subterfuge!"
@@ -59,29 +60,30 @@
desc = "Waffle Corp. brand gorilla cubes. Do not taunt."
icon_state = "monkeycubebox"
illustration = null
-
-/obj/item/storage/box/gorillacubes/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 3
- atom_storage.set_holdable(/obj/item/food/monkeycube)
+ storage_type = /datum/storage/box/gorilla_cubes
/obj/item/storage/box/gorillacubes/PopulateContents()
+ . = list()
for(var/i in 1 to 3)
- new /obj/item/food/monkeycube/gorilla(src)
+ . += /obj/item/food/monkeycube/gorilla
+
+/obj/item/storage/box/stockparts
+ storage_type = /datum/storage/box/stockparts
/obj/item/storage/box/stockparts/basic //for ruins where it's a bad idea to give access to an autolathe/protolathe, but still want to make stock parts accessible
name = "box of stock parts"
desc = "Contains a variety of basic stock parts."
/obj/item/storage/box/stockparts/basic/PopulateContents()
- var/static/items_inside = list(
+ var/static/items_inside = flatten_quantified_list(list(
/obj/item/stock_parts/capacitor = 3,
/obj/item/stock_parts/servo = 3,
/obj/item/stock_parts/matter_bin = 3,
/obj/item/stock_parts/micro_laser = 3,
/obj/item/stock_parts/scanning_module = 3,
- )
- generate_items_inside(items_inside,src)
+ ))
+
+ return items_inside
/obj/item/storage/box/stockparts/deluxe
name = "box of deluxe stock parts"
@@ -89,14 +91,15 @@
icon_state = "syndiebox"
/obj/item/storage/box/stockparts/deluxe/PopulateContents()
- var/static/items_inside = list(
+ var/static/items_inside = flatten_quantified_list(list(
/obj/item/stock_parts/capacitor/quadratic = 3,
/obj/item/stock_parts/scanning_module/triphasic = 3,
/obj/item/stock_parts/servo/femto = 3,
/obj/item/stock_parts/micro_laser/quadultra = 3,
/obj/item/stock_parts/matter_bin/bluespace = 3,
- )
- generate_items_inside(items_inside,src)
+ ))
+
+ return items_inside
/obj/item/storage/box/rndboards
name = "\proper the liberator's legacy"
@@ -104,45 +107,43 @@
illustration = "scicircuit"
/obj/item/storage/box/rndboards/PopulateContents()
- new /obj/item/circuitboard/machine/protolathe/offstation(src)
- new /obj/item/circuitboard/machine/destructive_analyzer(src)
- new /obj/item/circuitboard/machine/circuit_imprinter/offstation(src)
- new /obj/item/circuitboard/computer/rdconsole(src)
+ return list(
+ /obj/item/circuitboard/machine/protolathe/offstation,
+ /obj/item/circuitboard/machine/destructive_analyzer,
+ /obj/item/circuitboard/machine/circuit_imprinter/offstation,
+ /obj/item/circuitboard/computer/rdconsole,
+ )
/obj/item/storage/box/stabilized //every single stabilized extract from xenobiology
name = "box of stabilized extracts"
icon_state = "syndiebox"
-/obj/item/storage/box/stabilized/Initialize(mapload)
- . = ..()
- atom_storage.allow_big_nesting = TRUE
- atom_storage.max_slots = 99
- atom_storage.max_specific_storage = WEIGHT_CLASS_GIGANTIC
- atom_storage.max_total_storage = 99
+/obj/item/storage/box/stabilized/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
-/obj/item/storage/box/stabilized/PopulateContents()
var/static/items_inside = list(
- /obj/item/slimecross/stabilized/adamantine=1,
- /obj/item/slimecross/stabilized/black=1,
- /obj/item/slimecross/stabilized/blue=1,
- /obj/item/slimecross/stabilized/bluespace=1,
- /obj/item/slimecross/stabilized/cerulean=1,
- /obj/item/slimecross/stabilized/darkblue=1,
- /obj/item/slimecross/stabilized/darkpurple=1,
- /obj/item/slimecross/stabilized/gold=1,
- /obj/item/slimecross/stabilized/green=1,
- /obj/item/slimecross/stabilized/grey=1,
- /obj/item/slimecross/stabilized/lightpink=1,
- /obj/item/slimecross/stabilized/metal=1,
- /obj/item/slimecross/stabilized/oil=1,
- /obj/item/slimecross/stabilized/orange=1,
- /obj/item/slimecross/stabilized/pink=1,
- /obj/item/slimecross/stabilized/purple=1,
- /obj/item/slimecross/stabilized/pyrite=1,
- /obj/item/slimecross/stabilized/rainbow=1,
- /obj/item/slimecross/stabilized/red=1,
- /obj/item/slimecross/stabilized/sepia=1,
- /obj/item/slimecross/stabilized/silver=1,
- /obj/item/slimecross/stabilized/yellow=1,
+ /obj/item/slimecross/stabilized/adamantine,
+ /obj/item/slimecross/stabilized/black,
+ /obj/item/slimecross/stabilized/blue,
+ /obj/item/slimecross/stabilized/bluespace,
+ /obj/item/slimecross/stabilized/cerulean,
+ /obj/item/slimecross/stabilized/darkblue,
+ /obj/item/slimecross/stabilized/darkpurple,
+ /obj/item/slimecross/stabilized/gold,
+ /obj/item/slimecross/stabilized/green,
+ /obj/item/slimecross/stabilized/grey,
+ /obj/item/slimecross/stabilized/lightpink,
+ /obj/item/slimecross/stabilized/metal,
+ /obj/item/slimecross/stabilized/oil,
+ /obj/item/slimecross/stabilized/orange,
+ /obj/item/slimecross/stabilized/pink,
+ /obj/item/slimecross/stabilized/purple,
+ /obj/item/slimecross/stabilized/pyrite,
+ /obj/item/slimecross/stabilized/rainbow,
+ /obj/item/slimecross/stabilized/red,
+ /obj/item/slimecross/stabilized/sepia,
+ /obj/item/slimecross/stabilized/silver,
+ /obj/item/slimecross/stabilized/yellow,
)
- generate_items_inside(items_inside,src)
+
+ return items_inside
diff --git a/code/game/objects/items/storage/boxes/security_boxes.dm b/code/game/objects/items/storage/boxes/security_boxes.dm
index de18eb76258..035e246aa10 100644
--- a/code/game/objects/items/storage/boxes/security_boxes.dm
+++ b/code/game/objects/items/storage/boxes/security_boxes.dm
@@ -7,8 +7,9 @@
illustration = "flashbang"
/obj/item/storage/box/flashbangs/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/grenade/flashbang(src)
+ . += /obj/item/grenade/flashbang
/obj/item/storage/box/stingbangs
name = "box of stingbangs (WARNING)"
@@ -17,8 +18,9 @@
illustration = "flashbang"
/obj/item/storage/box/stingbangs/PopulateContents()
+ . = list()
for(var/i in 1 to 5)
- new /obj/item/grenade/stingbang(src)
+ . += /obj/item/grenade/stingbang
/obj/item/storage/box/flashes
name = "box of flashbulbs"
@@ -27,8 +29,9 @@
illustration = "flash"
/obj/item/storage/box/flashes/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/assembly/flash/handheld(src)
+ . += /obj/item/assembly/flash/handheld
/obj/item/storage/box/wall_flash
name = "wall-mounted flash kit"
@@ -40,15 +43,19 @@
var/id = rand(1000, 9999)
// FIXME what if this conflicts with an existing one?
- new /obj/item/wallframe/button(src)
- new /obj/item/electronics/airlock(src)
- var/obj/item/assembly/control/flasher/remote = new(src)
+ var/obj/item/assembly/control/flasher/remote = new(null)
remote.id = id
- var/obj/item/wallframe/flasher/frame = new(src)
+ var/obj/item/wallframe/flasher/frame = new(null)
frame.id = id
- new /obj/item/assembly/flash/handheld(src)
- new /obj/item/screwdriver(src)
+ return list(
+ /obj/item/wallframe/button,
+ /obj/item/electronics/airlock,
+ /obj/item/assembly/flash/handheld,
+ /obj/item/screwdriver,
+ remote,
+ frame,
+ )
/obj/item/storage/box/teargas
name = "box of tear gas grenades (WARNING)"
@@ -57,8 +64,9 @@
illustration = "grenade"
/obj/item/storage/box/teargas/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/grenade/chem_grenade/teargas(src)
+ . += /obj/item/grenade/chem_grenade/teargas
/obj/item/storage/box/emps
name = "box of emp grenades"
@@ -66,8 +74,9 @@
illustration = "emp"
/obj/item/storage/box/emps/PopulateContents()
+ . = list()
for(var/i in 1 to 5)
- new /obj/item/grenade/empgrenade(src)
+ . += /obj/item/grenade/empgrenade
/obj/item/storage/box/prisoner
name = "box of prisoner IDs"
@@ -76,14 +85,15 @@
illustration = "id"
/obj/item/storage/box/prisoner/PopulateContents()
- ..()
- new /obj/item/card/id/advanced/prisoner/one(src)
- new /obj/item/card/id/advanced/prisoner/two(src)
- new /obj/item/card/id/advanced/prisoner/three(src)
- new /obj/item/card/id/advanced/prisoner/four(src)
- new /obj/item/card/id/advanced/prisoner/five(src)
- new /obj/item/card/id/advanced/prisoner/six(src)
- new /obj/item/card/id/advanced/prisoner/seven(src)
+ return list(
+ /obj/item/card/id/advanced/prisoner/one,
+ /obj/item/card/id/advanced/prisoner/two,
+ /obj/item/card/id/advanced/prisoner/three,
+ /obj/item/card/id/advanced/prisoner/four,
+ /obj/item/card/id/advanced/prisoner/five,
+ /obj/item/card/id/advanced/prisoner/six,
+ /obj/item/card/id/advanced/prisoner/seven,
+ )
/obj/item/storage/box/seccarts
name = "box of PDA security cartridges"
@@ -92,8 +102,9 @@
illustration = "pda"
/obj/item/storage/box/seccarts/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/computer_disk/security(src)
+ . += /obj/item/computer_disk/security
/obj/item/storage/box/firingpins
name = "box of standard firing pins"
@@ -102,8 +113,9 @@
illustration = "firingpin"
/obj/item/storage/box/firingpins/PopulateContents()
+ . = list()
for(var/i in 1 to 5)
- new /obj/item/firing_pin(src)
+ . += /obj/item/firing_pin
/obj/item/storage/box/firingpins/paywall
name = "box of paywall firing pins"
@@ -111,8 +123,9 @@
illustration = "firingpin"
/obj/item/storage/box/firingpins/paywall/PopulateContents()
+ . = list()
for(var/i in 1 to 5)
- new /obj/item/firing_pin/paywall(src)
+ . += /obj/item/firing_pin/paywall
/obj/item/storage/box/lasertagpins
name = "box of laser tag firing pins"
@@ -120,9 +133,10 @@
illustration = "firingpin"
/obj/item/storage/box/lasertagpins/PopulateContents()
+ . = list()
for(var/i in 1 to 3)
- new /obj/item/firing_pin/tag/red(src)
- new /obj/item/firing_pin/tag/blue(src)
+ . += /obj/item/firing_pin/tag/red
+ . += /obj/item/firing_pin/tag/blue
/obj/item/storage/box/handcuffs
name = "box of spare handcuffs"
@@ -131,8 +145,9 @@
illustration = "handcuff"
/obj/item/storage/box/handcuffs/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/restraints/handcuffs(src)
+ . += /obj/item/restraints/handcuffs
/obj/item/storage/box/zipties
name = "box of spare zipties"
@@ -141,8 +156,9 @@
illustration = "handcuff"
/obj/item/storage/box/zipties/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/restraints/handcuffs/cable/zipties(src)
+ . += /obj/item/restraints/handcuffs/cable/zipties
/obj/item/storage/box/alienhandcuffs
name = "box of spare handcuffs"
@@ -151,8 +167,9 @@
illustration = "handcuff"
/obj/item/storage/box/alienhandcuffs/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/restraints/handcuffs/alien(src)
+ . += /obj/item/restraints/handcuffs/alien
/obj/item/storage/box/rubbershot
name = "box of shotgun shells (Less Lethal - Rubber Shot)"
@@ -161,8 +178,9 @@
illustration = null
/obj/item/storage/box/rubbershot/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/ammo_casing/shotgun/rubbershot(src)
+ . += /obj/item/ammo_casing/shotgun/rubbershot
/obj/item/storage/box/lethalshot
name = "box of shotgun shells (Lethal)"
@@ -171,14 +189,16 @@
illustration = null
/obj/item/storage/box/lethalshot/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/ammo_casing/shotgun/buckshot(src)
+ . += /obj/item/ammo_casing/shotgun/buckshot
/obj/item/storage/box/lethalshot/old
/obj/item/storage/box/lethalshot/old/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/ammo_casing/shotgun/buckshot/old(src)
+ . += /obj/item/ammo_casing/shotgun/buckshot/old
/obj/item/storage/box/slugs
name = "box of shotgun shells (Lethal - Slugs)"
@@ -187,8 +207,9 @@
illustration = null
/obj/item/storage/box/slugs/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/ammo_casing/shotgun(src)
+ . += /obj/item/ammo_casing/shotgun
/obj/item/storage/box/beanbag
name = "box of shotgun shells (Less Lethal - Beanbag)"
@@ -197,8 +218,9 @@
illustration = null
/obj/item/storage/box/beanbag/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/ammo_casing/shotgun/beanbag(src)
+ . += /obj/item/ammo_casing/shotgun/beanbag
/obj/item/storage/box/breacherslug
name = "box of breaching shotgun shells"
@@ -207,8 +229,9 @@
illustration = null
/obj/item/storage/box/breacherslug/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/ammo_casing/shotgun/breacher(src)
+ . += /obj/item/ammo_casing/shotgun/breacher
/obj/item/storage/box/large_dart
name = "box of XL shotgun darts"
@@ -217,16 +240,18 @@
illustration = null
/obj/item/storage/box/large_dart/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/ammo_casing/shotgun/dart/large(src)
+ . += /obj/item/ammo_casing/shotgun/dart/large
/obj/item/storage/box/emptysandbags
name = "box of empty sandbags"
illustration = "sandbag"
/obj/item/storage/box/emptysandbags/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/emptysandbag(src)
+ . += /obj/item/emptysandbag
/obj/item/storage/box/holy_grenades
name = "box of holy hand grenades"
@@ -234,8 +259,9 @@
illustration = "grenade"
/obj/item/storage/box/holy_grenades/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new/obj/item/grenade/chem_grenade/holy(src)
+ . += /obj/item/grenade/chem_grenade/holy
/obj/item/storage/box/fireworks
name = "box of fireworks"
@@ -243,22 +269,25 @@
illustration = "sparkler"
/obj/item/storage/box/fireworks/PopulateContents()
- for(var/i in 1 to 3)
- new/obj/item/sparkler(src)
- new/obj/item/grenade/firecracker(src)
- new /obj/item/toy/snappop(src)
+ return flatten_quantified_list(list(
+ /obj/item/sparkler = 3,
+ /obj/item/grenade/firecracker = 3,
+ /obj/item/toy/snappop = 1,
+ ))
/obj/item/storage/box/fireworks/dangerous
desc = "This box has a small label on it stating that it's from the Gorlex Marauders. Contains an assortment of \"fireworks\"."
/obj/item/storage/box/fireworks/dangerous/PopulateContents()
+ . = list()
for(var/i in 1 to 3)
- new/obj/item/sparkler(src)
- new/obj/item/grenade/firecracker(src)
+ . += /obj/item/sparkler
+ . += /obj/item/grenade/firecracker
+
if(prob(20))
- new /obj/item/grenade/frag(src)
+ . += /obj/item/grenade/frag
else
- new /obj/item/toy/snappop(src)
+ . += /obj/item/toy/snappop
/obj/item/storage/box/firecrackers
name = "box of firecrackers"
@@ -267,8 +296,9 @@
illustration = "firecracker"
/obj/item/storage/box/firecrackers/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new/obj/item/grenade/firecracker(src)
+ . += /obj/item/grenade/firecracker
/obj/item/storage/box/sparklers
name = "box of sparklers"
@@ -276,5 +306,6 @@
illustration = "sparkler"
/obj/item/storage/box/sparklers/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new/obj/item/sparkler(src)
+ . += /obj/item/sparkler
diff --git a/code/game/objects/items/storage/boxes/service_boxes.dm b/code/game/objects/items/storage/boxes/service_boxes.dm
index 6d4aedf4bfc..136dac2c069 100644
--- a/code/game/objects/items/storage/boxes/service_boxes.dm
+++ b/code/game/objects/items/storage/boxes/service_boxes.dm
@@ -7,16 +7,19 @@
illustration = "drinkglass"
/obj/item/storage/box/drinkingglasses/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/reagent_containers/cup/glass/drinkingglass(src)
+ . += /obj/item/reagent_containers/cup/glass/drinkingglass
+
/obj/item/storage/box/cups
name = "box of paper cups"
desc = "It has pictures of paper cups on the front."
illustration = "cup"
/obj/item/storage/box/cups/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/reagent_containers/cup/glass/sillycup(src)
+ . += /obj/item/reagent_containers/cup/glass/sillycup
//Some spare PDAs in a box
/obj/item/storage/box/pdas
@@ -25,8 +28,9 @@
illustration = "pda"
/obj/item/storage/box/pdas/PopulateContents()
+ . = list()
for(var/i in 1 to 4)
- new /obj/item/modular_computer/pda(src)
+ . += /obj/item/modular_computer/pda
/obj/item/storage/box/ids
name = "box of spare IDs"
@@ -34,16 +38,19 @@
illustration = "id"
/obj/item/storage/box/ids/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/card/id/advanced(src)
+ . += /obj/item/card/id/advanced
+
/obj/item/storage/box/silver_ids
name = "box of spare silver IDs"
desc = "Shiny IDs for important people."
illustration = "id"
/obj/item/storage/box/silver_ids/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/card/id/advanced/silver(src)
+ . += /obj/item/card/id/advanced/silver
/obj/item/storage/box/mousetraps
name = "box of Pest-B-Gon mousetraps"
@@ -51,8 +58,9 @@
illustration = "mousetrap"
/obj/item/storage/box/mousetraps/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/assembly/mousetrap(src)
+ . += /obj/item/assembly/mousetrap
/obj/item/storage/box/snappops
name = "snap pop box"
@@ -60,15 +68,12 @@
icon = 'icons/obj/toys/toy.dmi'
icon_state = "spbox"
illustration = ""
-
-/obj/item/storage/box/snappops/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/toy/snappop)
- atom_storage.max_slots = 8
+ storage_type = /datum/storage/box/snappops
/obj/item/storage/box/snappops/PopulateContents()
+ . = list()
for(var/i in 1 to 8)
- new /obj/item/toy/snappop(src)
+ . += /obj/item/toy/snappop
/obj/item/storage/box/matches
name = "matchbox"
@@ -86,16 +91,16 @@
custom_price = PAYCHECK_CREW * 0.4
base_icon_state = "matchbox"
illustration = null
+ storage_type = /datum/storage/box/matches
/obj/item/storage/box/matches/Initialize(mapload)
. = ..()
- atom_storage.max_slots = 10
- atom_storage.set_holdable(/obj/item/match)
AddElement(/datum/element/ignites_matches)
/obj/item/storage/box/matches/PopulateContents()
+ . = list()
for(var/i in 1 to 10)
- new /obj/item/match(src)
+ . += /obj/item/match
/obj/item/storage/box/matches/update_icon_state()
. = ..()
@@ -117,61 +122,62 @@
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
foldable_result = /obj/item/stack/sheet/cardboard //BubbleWrap
illustration = "light"
-
-/obj/item/storage/box/lights/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 21
- atom_storage.set_holdable(list(/obj/item/light/tube, /obj/item/light/bulb))
- atom_storage.max_total_storage = 21
- atom_storage.allow_quick_gather = FALSE //temp workaround to re-enable filling the light replacer with the box
+ storage_type = /datum/storage/box/lights
/obj/item/storage/box/lights/bulbs/PopulateContents()
+ . = list()
for(var/i in 1 to 21)
- new /obj/item/light/bulb(src)
+ . += /obj/item/light/bulb
/obj/item/storage/box/lights/tubes
name = "box of replacement tubes"
illustration = "lighttube"
/obj/item/storage/box/lights/tubes/PopulateContents()
+ . = list()
for(var/i in 1 to 21)
- new /obj/item/light/tube(src)
+ . += /obj/item/light/tube
/obj/item/storage/box/lights/mixed
name = "box of replacement lights"
illustration = "lightmixed"
/obj/item/storage/box/lights/mixed/PopulateContents()
- for(var/i in 1 to 14)
- new /obj/item/light/tube(src)
- for(var/i in 1 to 7)
- new /obj/item/light/bulb(src)
+ return flatten_quantified_list(list(
+ /obj/item/light/tube = 14,
+ /obj/item/light/bulb = 7,
+ ))
/obj/item/storage/box/fountainpens
name = "box of fountain pens"
illustration = "fpen"
/obj/item/storage/box/fountainpens/PopulateContents()
+ . = list()
for(var/i in 1 to 7)
- new /obj/item/pen/fountain(src)
+ . += /obj/item/pen/fountain
/obj/item/storage/box/dishdrive
name = "DIY Dish Drive Kit"
desc = "Contains everything you need to build your own Dish Drive!"
custom_premium_price = PAYCHECK_CREW * 3
-/obj/item/storage/box/dishdrive/PopulateContents()
- var/static/items_inside = list(
- /obj/item/circuitboard/machine/dish_drive = 1,
- /obj/item/screwdriver = 1,
- /obj/item/stack/cable_coil/five = 1,
- /obj/item/stack/sheet/glass = 1,
- /obj/item/stack/sheet/iron/five = 1,
- /obj/item/stock_parts/servo = 1,
- /obj/item/stock_parts/matter_bin = 2,
- /obj/item/wrench = 1,
+/obj/item/storage/box/dishdrive/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_count = TRUE
+
+ var/static/list/obj/item/items_inside = list(
+ /obj/item/circuitboard/machine/dish_drive,
+ /obj/item/screwdriver,
+ /obj/item/stack/cable_coil/five,
+ /obj/item/stack/sheet/glass,
+ /obj/item/stack/sheet/iron/five,
+ /obj/item/stock_parts/servo,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/wrench,
)
- generate_items_inside(items_inside,src)
+
+ return items_inside
/obj/item/storage/box/actionfigure
name = "box of action figures"
@@ -179,9 +185,11 @@
icon_state = "box"
/obj/item/storage/box/actionfigure/PopulateContents()
+ . = list()
+
+ var/static/list/obj/item/toy/figure/types = subtypesof(/obj/item/toy/figure)
for(var/i in 1 to 4)
- var/random_figure = pick(subtypesof(/obj/item/toy/figure))
- new random_figure(src)
+ . += pick(types)
/obj/item/storage/box/tail_pin
name = "pin the tail on the corgi supplies"
@@ -189,33 +197,30 @@
custom_price = PAYCHECK_COMMAND * 1.25
/obj/item/storage/box/tail_pin/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/poster/tail_board(src)
- new /obj/item/tail_pin(src)
+ return flatten_quantified_list(list(
+ /obj/item/poster/tail_board = 3,
+ /obj/item/tail_pin = 3,
+ ))
/obj/item/storage/box/party_poppers
name = "box of party poppers"
desc = "Turn any event into a celebration and ensure the janitor stays busy."
/obj/item/storage/box/party_poppers/PopulateContents()
+ . = list()
for(var/i in 1 to 5)
- new /obj/item/reagent_containers/spray/chemsprayer/party(src)
+ . += /obj/item/reagent_containers/spray/chemsprayer/party
/obj/item/storage/box/balloons
name = "box of long balloons"
desc = "A completely randomized and wacky box of long balloons, harvested straight from balloon farms on the clown planet."
illustration = "balloon"
-
-/obj/item/storage/box/balloons/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 24
- atom_storage.set_holdable(list(/obj/item/toy/balloon/long))
- atom_storage.max_total_storage = 24
- atom_storage.allow_quick_gather = FALSE
+ storage_type = /datum/storage/box/balloons
/obj/item/storage/box/balloons/PopulateContents()
+ . = list()
for(var/i in 1 to 24)
- new /obj/item/toy/balloon/long(src)
+ . += /obj/item/toy/balloon/long
/obj/item/storage/box/stickers
name = "sticker pack"
@@ -224,6 +229,9 @@
icon_state = "stickerpack"
illustration = null
w_class = WEIGHT_CLASS_TINY
+ storage_type = /datum/storage/box/stickers
+
+ ///Laels to pick from for this box illustration
var/static/list/pack_labels = list(
"smile",
"frown",
@@ -235,9 +243,6 @@
/obj/item/storage/box/stickers/Initialize(mapload)
. = ..()
- atom_storage.max_slots = 8
- atom_storage.set_holdable(list(/obj/item/sticker))
- atom_storage.max_specific_storage = WEIGHT_CLASS_TINY
if(isnull(illustration))
illustration = pick(pack_labels)
update_appearance()
@@ -257,9 +262,9 @@
if(isnull(non_contraband))
non_contraband = generate_non_contraband_stickers_list()
+ . = list()
for(var/i in 1 to rand(4, 8))
- var/type = pick(non_contraband)
- new type(src)
+ . += pick(non_contraband)
/obj/item/storage/box/stickers/googly
name = "googly eye sticker pack"
@@ -267,5 +272,6 @@
illustration = "googly-alt"
/obj/item/storage/box/stickers/googly/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/sticker/googly(src)
+ . += /obj/item/sticker/googly
diff --git a/code/game/objects/items/storage/boxes/trait_boxes.dm b/code/game/objects/items/storage/boxes/trait_boxes.dm
new file mode 100644
index 00000000000..7b999932626
--- /dev/null
+++ b/code/game/objects/items/storage/boxes/trait_boxes.dm
@@ -0,0 +1,31 @@
+
+/// A box containing a skub, for easier carry because skub is a bulky item.
+/obj/item/storage/box/stickers/skub
+ name = "skub fan pack"
+ desc = "A vinyl pouch to store your skub and pro-skub shirt in. A label on the back reads: \"Skubtide, Stationwide\"."
+ icon_state = "skubpack"
+ illustration = "label_skub"
+ w_class = WEIGHT_CLASS_SMALL
+ storage_type = /datum/storage/box/stickers/skub
+
+/obj/item/storage/box/stickers/skub/PopulateContents()
+ return list(
+ /obj/item/skub,
+ /obj/item/sticker/skub,
+ /obj/item/sticker/skub
+ )
+
+/obj/item/storage/box/stickers/anti_skub
+ name = "anti-skub stickers pack"
+ desc = "The enemy may have been given a skub and a shirt, but I've got more stickers! Plus the pack can hold my anti-skub shirt."
+ icon_state = "skubpack"
+ illustration = "label_anti_skub"
+ storage_type = /datum/storage/box/stickers/anti_skub
+
+/obj/item/storage/box/stickers/anti_skub/PopulateContents()
+ return list(
+ /obj/item/sticker/anti_skub,
+ /obj/item/sticker/anti_skub,
+ /obj/item/sticker/anti_skub,
+ /obj/item/sticker/anti_skub,
+ )
diff --git a/code/game/objects/items/storage/boxes/uplink_kits.dm b/code/game/objects/items/storage/boxes/uplink_kits.dm
new file mode 100644
index 00000000000..fcc055e2748
--- /dev/null
+++ b/code/game/objects/items/storage/boxes/uplink_kits.dm
@@ -0,0 +1,1029 @@
+#define KIT_RECON "recon"
+#define KIT_BLOODY_SPAI "bloodyspai"
+#define KIT_STEALTHY "stealth"
+#define KIT_SCREWED "screwed"
+#define KIT_SABOTAGE "sabotage"
+#define KIT_GUN "guns"
+#define KIT_MURDER "murder"
+#define KIT_IMPLANTS "implant"
+#define KIT_HACKER "hacker"
+#define KIT_SNIPER "sniper"
+#define KIT_NUKEOPS_METAGAME "metaops"
+#define KIT_LORD_SINGULOTH "lordsingulo"
+#define KIT_REVOLUTIONARY "revolutionary"
+
+#define KIT_JAMES_BOND "bond"
+#define KIT_NINJA "ninja"
+#define KIT_DARK_LORD "darklord"
+#define KIT_WHITE_WHALE_HOLY_GRAIL "white_whale_holy_grail"
+#define KIT_MAD_SCIENTIST "mad_scientist"
+#define KIT_BEES "bee"
+#define KIT_MR_FREEZE "mr_freeze"
+#define KIT_TRAITOR_2006 "ancient"
+#define KIT_DEAD_MONEY "dead_money"
+#define KIT_SAM_FISHER "sam_fisher"
+#define KIT_PROP_HUNT "prop_hunt"
+
+/// last audited december 2022
+/obj/item/storage/box/syndicate
+ storage_type = /datum/storage/box/syndicate
+
+/obj/item/storage/box/syndicate/bundle_a/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
+
+ switch (pick_weight(list(
+ KIT_RECON = 2,
+ KIT_BLOODY_SPAI = 3,
+ KIT_STEALTHY = 2,
+ KIT_SCREWED = 2,
+ KIT_SABOTAGE = 3,
+ KIT_GUN = 2,
+ KIT_MURDER = 2,
+ KIT_IMPLANTS = 1,
+ KIT_HACKER = 3,
+ KIT_SNIPER = 1,
+ KIT_NUKEOPS_METAGAME = 1,
+ KIT_REVOLUTIONARY = 2
+ )))
+ if(KIT_RECON)
+ return list(
+ /obj/item/clothing/glasses/thermal/xray, // ~8 tc?
+ /obj/item/storage/briefcase/launchpad, //6 tc
+ /obj/item/binoculars, // 2 tc?
+ /obj/item/encryptionkey/syndicate, // 2 tc
+ /obj/item/storage/box/syndie_kit/space, //4 tc
+ /obj/item/grenade/frag, // ~2 tc each?
+ /obj/item/grenade/frag,
+ /obj/item/flashlight/emp, // 4 tc
+ )
+
+ if(KIT_BLOODY_SPAI)
+ return list(
+ /obj/item/card/id/advanced/chameleon, // 2 tc
+ /obj/item/clothing/under/chameleon, // 2 tc since it's not the full set
+ /obj/item/clothing/mask/chameleon, // Goes with above
+ /obj/item/clothing/shoes/chameleon/noslip, // 2 tc
+ /obj/item/computer_disk/syndicate/camera_app, // 1 tc
+ /obj/item/multitool/ai_detect, // 1 tc
+ /obj/item/encryptionkey/syndicate, // 2 tc
+ /obj/item/reagent_containers/syringe/mulligan, // 4 tc
+ /obj/item/switchblade, //basically 1 tc as it can be bought from BM kits
+ /obj/item/storage/fancy/cigarettes/cigpack_syndicate , // 2 tc this shit heals
+ /obj/item/flashlight/emp, // 2 tc
+ /obj/item/chameleon, // 7 tc
+ /obj/item/implanter/storage, // 6 tc
+ )
+
+ if(KIT_STEALTHY)
+ return list(
+ /obj/item/gun/energy/recharge/ebow, // 10 tc
+ /obj/item/pen/sleepy, // 4 tc
+ /obj/item/healthanalyzer/rad_laser, // 3 tc
+ /obj/item/chameleon, // 7 tc
+ /obj/item/soap/syndie, // 1 tc
+ /obj/item/clothing/glasses/thermal/syndi, // 4 tc
+ /obj/item/flashlight/emp, // 2 tc
+ /obj/item/jammer, // 5 tc
+ )
+
+ if(KIT_GUN)
+ return list(
+ /obj/item/gun/ballistic/revolver, // 13 tc
+ /obj/item/ammo_box/a357, // 4tc
+ /obj/item/ammo_box/a357,
+ /obj/item/storage/belt/holster/chameleon, // 1 tc
+ /obj/item/card/emag/doorjack, // 3 tc replaced the emag with the doorjack
+ /obj/item/grenade/c4, // 1 tc
+ /obj/item/clothing/gloves/latex/nitrile, // ~1 tc for whole outfit
+ /obj/item/clothing/mask/gas/clown_hat,
+ /obj/item/clothing/under/suit/black_really,
+ /obj/item/clothing/neck/tie/red/hitman,
+ )
+
+ if(KIT_SCREWED)
+ var/obj/item/clothing/suit/space/syndicate/spess_suit = pick(GLOB.syndicate_space_suits_to_helmets)
+
+ return list(
+ /obj/item/sbeacondrop/bomb, // 11 tc
+ /obj/item/grenade/syndieminibomb, // 6 tc
+ /obj/item/sbeacondrop/powersink, // 11 tc
+ spess_suit, // Above allows me to get the helmet from a variable on the object
+ GLOB.syndicate_space_suits_to_helmets[spess_suit], // 4 TC for the space gear
+ /obj/item/encryptionkey/syndicate, // 2 tc
+ )
+
+ if(KIT_MURDER)
+ return list(
+ /obj/item/melee/energy/sword/saber, // 8 tc
+ /obj/item/clothing/glasses/thermal/syndi, // 4 tc
+ /obj/item/card/emag/doorjack, // 3 tc
+ /obj/item/clothing/shoes/chameleon/noslip, // 2 tc
+ /obj/item/encryptionkey/syndicate, // 2 tc
+ /obj/item/grenade/syndieminibomb, // 6 tc
+ )
+
+ if(KIT_IMPLANTS)
+ return list(
+ /obj/item/implanter/freedom, // 5 tc
+ /obj/item/implanter/uplink/precharged, // 10 tc is inside this thing
+ /obj/item/implanter/emp, // 1 tc
+ /obj/item/implanter/explosive, // 2 tc
+ /obj/item/implanter/storage, // 8 tc
+ )
+
+ if(KIT_HACKER) //L-L--LOOK AT YOU, HACKER
+ return list(
+ /obj/item/ai_module/syndicate, // 4 tc
+ /obj/item/card/emag, // 4 tc
+ /obj/item/card/emag/doorjack, // 3 tc
+ /obj/item/encryptionkey/binary, // 5 tc
+ /obj/item/ai_module/toy_ai, // ~6 tc
+ /obj/item/multitool/ai_detect, // 1 tc
+ /obj/item/storage/toolbox/syndicate, // 1 tc
+ /obj/item/computer_disk/syndicate/camera_app, // 1 tc
+ /obj/item/clothing/glasses/thermal/syndi, // 4 tc
+ /obj/item/card/id/advanced/chameleon, // 2 tc
+ )
+
+ if(KIT_LORD_SINGULOTH) //currently disabled, i might return with another anti-engine kit
+ var/obj/item/clothing/suit/space/syndicate/spess_suit = pick(GLOB.syndicate_space_suits_to_helmets)
+
+ . = list(
+ /obj/item/sbeacondrop, // 10 tc
+ spess_suit, // Above allows me to get the helmet from a variable on the object
+ GLOB.syndicate_space_suits_to_helmets[spess_suit], // 4 TC for the space gear
+ /obj/item/card/emag, // 4 tc
+ /obj/item/storage/toolbox/syndicate, // 1 tc
+ /obj/item/card/id/advanced/mining,
+ /obj/item/stack/spacecash/c10000, // this is technically 10 tc but not really
+ )
+
+ if(prob(70))
+ . += /obj/item/toy/spinningtoy //lol
+ else
+ . += /obj/item/toy/spinningtoy/dark_matter //edgy lol
+
+ if(KIT_SABOTAGE)
+ return list(
+ /obj/item/storage/backpack/duffelbag/syndie/sabotage, // 5 tc for 3 c4 and 2 x4
+ /obj/item/computer_disk/syndicate/camera_app, // 1 tc
+ /obj/item/sbeacondrop/powersink, // 11 tc
+ /obj/item/computer_disk/virus/detomatix, // 6 tc
+ /obj/item/storage/toolbox/syndicate, // 1 tc
+ /obj/item/pizzabox/bomb, // 6 tc
+ /obj/item/storage/box/syndie_kit/emp, // 2 tc
+ )
+
+ if(KIT_SNIPER) //This shit is unique so can't really balance it around tc, also no silencer because getting killed without ANY indicator on what killed you sucks
+ return list(
+ /obj/item/gun/ballistic/rifle/sniper_rifle, // 12 tc
+ /obj/item/ammo_box/magazine/sniper_rounds/penetrator, // 5 tc
+ /obj/item/clothing/glasses/thermal/syndi, // 4 tc
+ /obj/item/clothing/gloves/latex/nitrile, // ~ 1 tc for outfit
+ /obj/item/clothing/mask/gas/clown_hat,
+ /obj/item/clothing/under/suit/black_really,
+ /obj/item/clothing/neck/tie/red/hitman,
+ )
+
+ if(KIT_NUKEOPS_METAGAME)
+ return list(
+ /obj/item/mod/control/pre_equipped/nuclear/unrestricted, // 8 tc
+ /obj/item/gun/ballistic/shotgun/bulldog/unrestricted, // 8 tc
+ /obj/item/implanter/explosive, // 2 tc
+ /obj/item/ammo_box/magazine/m12g, // 2 tc
+ /obj/item/ammo_box/magazine/m12g, // 2 tc
+ /obj/item/grenade/c4 , // 1 tc
+ /obj/item/grenade/c4 , // 1 tc
+ /obj/item/card/emag, // 4 tc
+ /obj/item/card/emag/doorjack, // 3 tc
+ )
+
+ if(KIT_REVOLUTIONARY)
+ return list(
+ /obj/item/healthanalyzer/rad_laser, // 3 TC
+ /obj/item/assembly/flash/hypnotic, // 7 TC
+ /obj/item/storage/pill_bottle/lsd, // ~1 TC
+ /obj/item/pen/sleepy, // 4 TC
+ /obj/item/gun/ballistic/revolver/nagant, // 13 TC comparable to 357. revolvers
+ /obj/item/megaphone,
+ /obj/item/bedsheet/rev,
+ /obj/item/clothing/suit/armor/vest/russian_coat,
+ /obj/item/clothing/head/helmet/rus_ushanka,
+ /obj/item/storage/box/syndie_kit/poster_box,
+ )
+
+/obj/item/storage/box/syndicate/bundle_b/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
+
+ switch (pick_weight(list(
+ KIT_JAMES_BOND = 2,
+ KIT_NINJA = 1,
+ KIT_DARK_LORD = 1,
+ KIT_WHITE_WHALE_HOLY_GRAIL = 2,
+ KIT_MAD_SCIENTIST = 2,
+ KIT_BEES = 1,
+ KIT_MR_FREEZE = 2,
+ KIT_DEAD_MONEY = 2,
+ KIT_TRAITOR_2006 = 1,
+ KIT_SAM_FISHER = 1,
+ KIT_PROP_HUNT = 1
+ )))
+ if(KIT_JAMES_BOND)
+ return list(
+ /obj/item/gun/ballistic/automatic/pistol, // 7 tc
+ /obj/item/suppressor, // 3 tc
+ /obj/item/ammo_box/magazine/m9mm, // 1 tc
+ /obj/item/ammo_box/magazine/m9mm,
+ /obj/item/card/id/advanced/chameleon, // 2 tc
+ /obj/item/clothing/under/chameleon, // 1 tc
+ /obj/item/reagent_containers/hypospray/medipen/stimulants, // 5 tc
+ /obj/item/reagent_containers/cup/rag,
+ /obj/item/implanter/freedom, // 5 tc
+ /obj/item/flashlight/emp, // 2 tc
+ /obj/item/grenade/c4/x4, // 1ish tc
+ /obj/item/reagent_containers/applicator/pill/cyanide,
+ /obj/item/toy/cards/deck/syndicate, // 1 tc, for poker
+ )
+
+ if(KIT_NINJA)
+ . = list(
+ /obj/item/katana, // Unique , hard to tell how much tc this is worth. 8 tc?
+ /obj/item/reagent_containers/hypospray/medipen/stimulants, // 5 tc
+ /obj/item/storage/belt/chameleon, // worth some fraction of a tc
+ /obj/item/chameleon, // 7 tc
+ /obj/item/card/id/advanced/chameleon, // 2 tc
+ /obj/item/card/emag/doorjack, // 3 tc
+ /obj/item/book/granter/action/spell/smoke, // ninja smoke bomb. 1 tc
+ /obj/item/clothing/shoes/bhop, // mining item, lets you jump at people, at least 2 tc
+ )
+
+ for(var/i in 1 to 6)
+ . += /obj/item/throwing_star // 1 tc
+
+ if(KIT_DARK_LORD)
+ return list(
+ /obj/item/dualsaber/red, // 16 tc
+ /obj/item/dnainjector/telemut/darkbundle, // ~ 4 tc for tk
+ /obj/item/clothing/suit/hooded/chaplain_hoodie,
+ /obj/item/card/id/advanced/chameleon, // 2 tc
+ /obj/item/clothing/shoes/chameleon/noslip, //2 tc ,because slipping while being a dark lord sucks
+ /obj/item/book/granter/action/spell/summonitem, // ~2 tc
+ /obj/item/book/granter/action/spell/lightningbolt, // 4 tc
+ )
+
+ if(KIT_WHITE_WHALE_HOLY_GRAIL) //Unique items that don't appear anywhere else
+ return list(
+ /obj/item/gun/ballistic/rifle/boltaction/harpoon,
+ /obj/item/storage/bag/harpoon_quiver,
+ /obj/item/clothing/suit/hooded/carp_costume/spaceproof,
+ /obj/item/clothing/mask/gas/carp,
+ /obj/item/grenade/spawnergrenade/spesscarp,
+ /obj/item/toy/plush/carpplushie/dehy_carp, // 1 tc, for use as a personal mount
+ )
+
+ if(KIT_MAD_SCIENTIST)
+ for(var/_ in 1 to 2)
+ new /obj/item/grenade/clusterbuster/random(src) // 10 tc?
+
+ . = list(
+ /obj/item/clothing/suit/toggle/labcoat/mad, // 0 tc
+ /obj/item/clothing/shoes/jackboots, // 0 tc
+ /obj/item/megaphone, // 0 tc
+ /obj/item/grenade/chem_grenade/bioterrorfoam, // 5 tc
+ /obj/item/assembly/signaler, // 0 tc
+ /obj/item/assembly/signaler, // 0 tc
+ /obj/item/assembly/signaler, // 0 tc
+ /obj/item/assembly/signaler, // 0 tc
+ /obj/item/storage/toolbox/syndicate, // 1 tc
+ /obj/item/pen/edagger, // 2 tc
+ /obj/item/gun/energy/wormhole_projector/core_inserted, // 5 tc easily
+ )
+
+ for(var/obj/item/grenade/insert as anything in src)
+ insert.moveToNullspace()
+ . += insert
+
+ if(KIT_BEES)
+ return list(
+ /obj/item/paper/fluff/bee_objectives, // 0 tc (motivation)
+ /obj/item/clothing/suit/hooded/bee_costume, // 0 tc
+ /obj/item/clothing/mask/animal/small/bee, // 0 tc
+ /obj/item/storage/belt/fannypack/yellow, // 0 tc
+ /obj/item/grenade/spawnergrenade/buzzkill, // these are the random super bees this is definitely all of the tc budget for this one
+ /obj/item/grenade/spawnergrenade/buzzkill, // 10 tc per grenade
+ /obj/item/reagent_containers/cup/bottle/beesease, // 10 tc?
+ /obj/item/melee/beesword, //priceless
+ )
+
+ if(KIT_MR_FREEZE)
+ return list(
+ /obj/item/clothing/glasses/cold,
+ /obj/item/clothing/gloves/color/black/security/blu,
+ /obj/item/clothing/mask/chameleon,
+ /obj/item/clothing/suit/hooded/wintercoat,
+ /obj/item/clothing/shoes/winterboots,
+ /obj/item/grenade/gluon, // whole belt is 22 and gluon is weight 4 so lets just go with like 7 total
+ /obj/item/grenade/gluon,
+ /obj/item/grenade/gluon,
+ /obj/item/grenade/gluon,
+ /obj/item/dnainjector/geladikinesis, // both abilities are probably 3 tc total
+ /obj/item/dnainjector/cryokinesis,
+ /obj/item/gun/energy/temperature/freeze, // ~6 tc
+ /obj/item/gun/energy/laser/thermal/cryo, // ~6 tc
+ /obj/item/melee/energy/sword/saber/blue, //see see it
+ )
+
+ if(KIT_TRAITOR_2006) //A kit so old, it's probably older than you. //This bundle is filled with the entire uplink contents traitors had access to in 2006, from OpenSS13. Notably the esword was not a choice but existed in code.
+ return /obj/item/storage/toolbox/emergency/old/ancientbundle //Items fit neatly into a classic toolbox just to remind you what the theme is.
+
+ if(KIT_DEAD_MONEY)
+ . = list(
+ /obj/item/storage/box/syndie_kit/signaler,
+ /obj/item/mod/control/pre_equipped/responsory/inquisitory/syndie, // basically a snowflake yet better elite modsuit, so like, 8 + 5 tc.
+ /obj/item/card/id/advanced/chameleon, // 2 tc
+ /obj/item/clothing/mask/chameleon,
+ /obj/item/melee/baton/telescopic/contractor_baton, // 7 tc
+ /obj/item/jammer, // 5 tc
+ /obj/item/pinpointer/crew, //priceless
+ )
+
+ for(var/i in 1 to 4)
+ . += /obj/item/clothing/neck/collar_bomb // These let you remotely kill people with a signaler, though you have to get them first.
+
+ if(KIT_SAM_FISHER)
+ return list(
+ /obj/item/clothing/under/syndicate/combat,
+ /obj/item/clothing/suit/armor/vest/marine/pmc, //The armor kit is comparable to the infiltrator, 6 TC
+ /obj/item/clothing/head/helmet/marine/pmc,
+ /obj/item/clothing/mask/gas/sechailer,
+ /obj/item/clothing/glasses/night/colorless, // 3~ TC
+ /obj/item/clothing/gloves/krav_maga/combatglovesplus, //5TC
+ /obj/item/clothing/shoes/jackboots,
+ /obj/item/storage/belt/military/assault/fisher, //items in this belt easily costs 18 TC
+ )
+
+ if(KIT_PROP_HUNT)
+ return list(
+ /obj/item/chameleon, // 7 TC
+ /obj/item/card/emag/doorjack, // 3 TC
+ /obj/item/storage/box/syndie_kit/imp_stealth, //8 TC
+ /obj/item/gun/ballistic/automatic/pistol, // 7 TC
+ /obj/item/clothing/glasses/thermal, // 4 TC
+ )
+
+/obj/item/storage/box/syndie_kit
+ name = "box"
+ desc = "A sleek, sturdy box."
+ icon_state = "syndiebox"
+ illustration = "writing_syndie"
+ storage_type = /datum/storage/box/syndie_kit
+
+/obj/item/storage/box/syndie_kit/rebarxbowsyndie
+ name = "Boxed Rebar Crossbow"
+ desc = "A scoped weapon with low armor penetration, but devastating against flesh. Features instruction manual for making specialty ammo."
+ storage_type = /datum/storage/box/syndie_kit/rebarxbowsyndie
+
+/obj/item/storage/box/syndie_kit/rebarxbowsyndie/PopulateContents()
+ return list(
+ /obj/item/book/granter/crafting_recipe/dusting/rebarxbowsyndie_ammo,
+ /obj/item/gun/ballistic/rifle/rebarxbow/syndie,
+ /obj/item/storage/bag/rebar_quiver/syndicate,
+ )
+
+/obj/item/paper/syndicate_forensics_spoofer
+ name = "Forensics Spoofer Guide"
+ default_raw_text = {"
+ Forensics Spoofer Info:
+ The spoofer has two modes: SCAN which scans for fingerprints and fibers, and APPLY which applies the currently chosen fingerprint/fiber to your target.
+ The spoofer can only store 5 fingerprints and 5 fibers, and may not store or report fibers/prints already stored. Additionally, it taps into the stations network to associate scanned fingerprints with names.
+ The spoofer will make the same sounds and sights as a forensics scanner, when silent mode is off.
+ "}
+
+/obj/item/storage/box/syndie_kit/forensics_spoofer
+ name = "forensics spoofing kit"
+
+/obj/item/storage/box/syndie_kit/forensics_spoofer/PopulateContents()
+ return list(
+ /obj/item/forensics_spoofer,
+ /obj/item/paper/syndicate_forensics_spoofer,
+ )
+
+/obj/item/storage/box/syndie_kit/origami_bundle
+ name = "origami kit"
+ desc = "A box full of a number of rather masterfully engineered paper planes and a manual on \"The Art of Origami\"."
+
+/obj/item/storage/box/syndie_kit/origami_bundle/PopulateContents()
+ . = list(/obj/item/book/granter/action/origami)
+ for(var/i in 1 to 5)
+ . += /obj/item/paper
+
+/obj/item/storage/box/syndie_kit/imp_freedom
+ name = "freedom implant box"
+
+/obj/item/storage/box/syndie_kit/imp_freedom/PopulateContents()
+ return /obj/item/implanter/freedom
+
+/obj/item/storage/box/syndie_kit/imp_microbomb
+ name = "microbomb implant box"
+
+/obj/item/storage/box/syndie_kit/imp_microbomb/PopulateContents()
+ return /obj/item/implanter/explosive
+
+/obj/item/storage/box/syndie_kit/imp_macrobomb
+ name = "macrobomb implant box"
+
+/obj/item/storage/box/syndie_kit/imp_macrobomb/PopulateContents()
+ return /obj/item/implanter/explosive_macro
+
+/obj/item/storage/box/syndie_kit/imp_deniability
+ name = "tactical deniability implant box"
+
+/obj/item/storage/box/syndie_kit/imp_deniability/PopulateContents()
+ return /obj/item/implanter/tactical_deniability
+
+/obj/item/storage/box/syndie_kit/imp_uplink
+ name = "uplink implant box"
+
+/obj/item/storage/box/syndie_kit/imp_uplink/PopulateContents()
+ return /obj/item/implanter/uplink
+
+/obj/item/storage/box/syndie_kit/bioterror
+ name = "bioterror syringe box"
+
+/obj/item/storage/box/syndie_kit/bioterror/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/reagent_containers/syringe/bioterror
+
+/obj/item/storage/box/syndie_kit/clownpins
+ name = "ultra hilarious firing pin box"
+
+/obj/item/storage/box/syndie_kit/clownpins/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/firing_pin/clown/ultra
+
+/obj/item/storage/box/syndie_kit/imp_storage
+ name = "storage implant box"
+
+/obj/item/storage/box/syndie_kit/imp_storage/PopulateContents()
+ return /obj/item/implanter/storage
+
+/obj/item/storage/box/syndie_kit/imp_stealth
+ name = "stealth implant box"
+
+/obj/item/storage/box/syndie_kit/imp_stealth/PopulateContents()
+ return /obj/item/implanter/stealth
+
+/obj/item/storage/box/syndie_kit/imp_radio
+ name = "syndicate radio implant box"
+
+/obj/item/storage/box/syndie_kit/imp_radio/PopulateContents()
+ return /obj/item/implanter/radio/syndicate
+
+/obj/item/storage/box/syndie_kit/space
+ name = "boxed space suit and helmet"
+ storage_type = /datum/storage/box/syndie_kit/space
+
+/obj/item/storage/box/syndie_kit/space/PopulateContents()
+ var/obj/item/clothing/suit/space/syndicate/spess_suit = pick(GLOB.syndicate_space_suits_to_helmets)
+
+ return list(
+ spess_suit, // Above allows me to get the helmet from a variable on the object
+ GLOB.syndicate_space_suits_to_helmets[spess_suit], // 4 TC for the space gear
+ )
+
+/obj/item/storage/box/syndie_kit/emp
+ name = "EMP kit"
+
+/obj/item/storage/box/syndie_kit/emp/PopulateContents()
+ . = list()
+
+ for(var/i in 1 to 5)
+ . += /obj/item/grenade/empgrenade
+ . += /obj/item/implanter/emp
+
+/obj/item/storage/box/syndie_kit/smoke
+ name = "smoke kit"
+
+/obj/item/storage/box/syndie_kit/smoke/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/grenade/smokebomb
+
+/obj/item/storage/box/syndie_kit/mail_counterfeit
+ name = "mail counterfeit kit"
+ desc = "A GLA Postal Service branded box. It's emblazoned with the motto: *Nothing stops the mail*."
+ storage_type = /datum/storage/box/syndie_kit/mail_counterfeit
+
+/obj/item/storage/box/syndie_kit/mail_counterfeit/PopulateContents()
+ . = list()
+ for(var/i in 1 to 6)
+ . += /obj/item/storage/mail_counterfeit_device
+
+/obj/item/storage/box/syndie_kit/chemical
+ name = "chemical kit"
+ storage_type = /datum/storage/box/syndie_kit/chemical
+
+/obj/item/storage/box/syndie_kit/chemical/PopulateContents()
+ return list(
+ /obj/item/reagent_containers/cup/bottle/polonium,
+ /obj/item/reagent_containers/cup/bottle/venom,
+ /obj/item/reagent_containers/cup/bottle/fentanyl,
+ /obj/item/reagent_containers/cup/bottle/formaldehyde,
+ /obj/item/reagent_containers/cup/bottle/spewium,
+ /obj/item/reagent_containers/cup/bottle/syndol,
+ /obj/item/reagent_containers/cup/bottle/cyanide,
+ /obj/item/reagent_containers/cup/bottle/histamine,
+ /obj/item/reagent_containers/cup/bottle/initropidril,
+ /obj/item/reagent_containers/cup/bottle/pancuronium,
+ /obj/item/reagent_containers/cup/bottle/sodium_thiopental,
+ /obj/item/reagent_containers/cup/bottle/coniine,
+ /obj/item/reagent_containers/cup/bottle/curare,
+ /obj/item/reagent_containers/cup/bottle/amanitin,
+ /obj/item/reagent_containers/syringe,
+ )
+
+/obj/item/storage/box/syndie_kit/nuke
+ name = "nuke core extraction kit"
+ desc = "A box containing the equipment and instructions for extracting the plutonium cores of most Nanotrasen nuclear explosives."
+
+/obj/item/storage/box/syndie_kit/nuke/PopulateContents()
+ return list(
+ /obj/item/screwdriver/nuke,
+ /obj/item/nuke_core_container,
+ /obj/item/paper/guides/antag/nuke_instructions,
+ )
+/obj/item/storage/box/syndie_kit/supermatter
+ name = "supermatter sliver extraction kit"
+ desc = "A box containing the equipment and instructions for extracting a sliver of supermatter."
+
+/obj/item/storage/box/syndie_kit/supermatter/PopulateContents()
+ return list(
+ /obj/item/scalpel/supermatter,
+ /obj/item/hemostat/supermatter,
+ /obj/item/nuke_core_container/supermatter,
+ /obj/item/paper/guides/antag/supermatter_sliver,
+ )
+
+/obj/item/storage/box/syndie_kit/tuberculosisgrenade
+ name = "virus grenade kit"
+ storage_type = /datum/storage/box/syndie_kit/tuberculosisgrenade
+
+/obj/item/storage/box/syndie_kit/tuberculosisgrenade/PopulateContents()
+ . = list(/obj/item/grenade/chem_grenade/tuberculosis)
+
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/hypospray/medipen/tuberculosiscure
+ . += /obj/item/reagent_containers/syringe
+ . += /obj/item/reagent_containers/cup/bottle/tuberculosiscure
+
+/obj/item/storage/box/syndie_kit/chameleon
+ name = "chameleon kit"
+ storage_type = /datum/storage/box/syndie_kit/chaemelon
+
+/obj/item/storage/box/syndie_kit/chameleon/PopulateContents()
+ return list(
+ /obj/item/clothing/under/chameleon,
+ /obj/item/clothing/suit/chameleon,
+ /obj/item/clothing/gloves/chameleon,
+ /obj/item/clothing/shoes/chameleon,
+ /obj/item/clothing/glasses/chameleon,
+ /obj/item/clothing/head/chameleon,
+ /obj/item/clothing/mask/chameleon,
+ /obj/item/clothing/neck/chameleon,
+ /obj/item/storage/backpack/chameleon,
+ /obj/item/storage/belt/chameleon,
+ /obj/item/radio/headset/chameleon,
+ /obj/item/stamp/chameleon,
+ /obj/item/modular_computer/pda/chameleon,
+ /obj/item/gun/energy/laser/chameleon,
+ /obj/item/chameleon_scanner,
+ )
+
+/obj/item/storage/box/syndie_kit/throwing_weapons
+ storage_type = /datum/storage/box/syndie_kit/weapons
+
+//5*(2*4) = 5*8 = 45, 45 damage if you hit one person with all 5 stars.
+//Not counting the damage it will do while embedded (2*4 = 8, at 15% chance)
+/obj/item/storage/box/syndie_kit/throwing_weapons/PopulateContents()
+ return flatten_quantified_list(list(
+ /obj/item/throwing_star = 5,
+ /obj/item/paperplane/syndicate = 2,
+ /obj/item/restraints/legcuffs/bola/tactical = 2,
+ ))
+
+/obj/item/storage/box/syndie_kit/cutouts
+ storage_type = /datum/storage/box/syndie_kit/cutouts
+
+/obj/item/storage/box/syndie_kit/cutouts/PopulateContents()
+ . = list()
+
+ for(var/i in 1 to 3)
+ . += /obj/item/cardboard_cutout/adaptive
+ . += /obj/item/toy/crayon/rainbow
+
+/obj/item/storage/box/syndie_kit/romerol/PopulateContents()
+ return list(
+ /obj/item/reagent_containers/cup/bottle/romerol,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/reagent_containers/dropper,
+ )
+
+/obj/item/storage/box/syndie_kit/ez_clean/PopulateContents()
+ . = list()
+ for(var/i in 1 to 3)
+ . += /obj/item/grenade/chem_grenade/ez_clean
+
+/obj/item/storage/box/syndie_kit/mulligan/PopulateContents()
+ return list(
+ /obj/item/reagent_containers/syringe/mulligan,
+ /obj/item/fake_identity_kit
+ )
+
+/obj/item/storage/box/hug/reverse_revolver/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+ config.compute_max_total_weight = TRUE
+
+ return /obj/item/gun/ballistic/revolver/reverse
+
+/obj/item/storage/box/syndie_kit/mimery/PopulateContents()
+ return list(
+ /obj/item/book/granter/action/spell/mime/mimery_blockade,
+ /obj/item/book/granter/action/spell/mime/mimery_guns,
+ )
+
+/obj/item/storage/box/syndie_kit/moltobeso/PopulateContents()
+ return list(
+ /obj/item/reagent_containers/cup/bottle/moltobeso,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/reagent_containers/dropper,
+ )
+
+/obj/item/storage/box/syndie_kit/combat_baking/PopulateContents()
+ . = list(/obj/item/food/baguette/combat,)
+
+ for(var/i in 1 to 2)
+ . += /obj/item/food/croissant/throwing
+ . += /obj/item/book/granter/crafting_recipe/combat_baking
+
+/obj/item/storage/box/syndie_kit/centcom_costume
+ storage_type = /datum/storage/box/syndie_kit/centcom_costume
+
+/obj/item/storage/box/syndie_kit/centcom_costume/PopulateContents()
+ return list(
+ /obj/item/clothing/under/rank/centcom/officer,
+ /obj/item/clothing/shoes/sneakers/black,
+ /obj/item/clothing/gloves/color/black,
+ /obj/item/radio/headset/headset_cent/empty,
+ /obj/item/clothing/glasses/sunglasses,
+ /obj/item/storage/backpack/satchel,
+ /obj/item/modular_computer/pda/heads,
+ /obj/item/clipboard,
+ )
+
+/obj/item/storage/box/syndie_kit/chameleon/broken/PopulateContents()
+ return list(
+ /obj/item/clothing/under/chameleon/broken,
+ /obj/item/clothing/suit/chameleon/broken,
+ /obj/item/clothing/gloves/chameleon/broken,
+ /obj/item/clothing/shoes/chameleon/noslip/broken,
+ /obj/item/clothing/glasses/chameleon/broken,
+ /obj/item/clothing/head/chameleon/broken,
+ /obj/item/clothing/mask/chameleon/broken,
+ /obj/item/clothing/neck/chameleon/broken,
+ /obj/item/storage/backpack/chameleon/broken,
+ /obj/item/storage/belt/chameleon/broken,
+ /obj/item/radio/headset/chameleon/broken,
+ /obj/item/stamp/chameleon/broken,
+ /obj/item/modular_computer/pda/chameleon/broken,
+ )
+ // No chameleon laser, they can't randomise for //REASONS//
+
+/obj/item/storage/box/syndie_kit/bee_grenades
+ name = "buzzkill grenade box"
+ desc = "A sleek, sturdy box with a buzzing noise coming from the inside. Uh oh."
+
+/obj/item/storage/box/syndie_kit/bee_grenades/PopulateContents()
+ . = list()
+ for(var/i in 1 to 3)
+ . += /obj/item/grenade/spawnergrenade/buzzkill
+
+/obj/item/storage/box/syndie_kit/manhack_grenades/PopulateContents()
+ . = list()
+ for(var/i in 1 to 3)
+ . += /obj/item/grenade/spawnergrenade/manhacks
+
+/obj/item/storage/box/syndie_kit/sleepytime/PopulateContents()
+ return list(
+ /obj/item/clothing/under/syndicate/bloodred/sleepytime,
+ /obj/item/reagent_containers/cup/glass/mug/coco,
+ /obj/item/toy/plush/carpplushie,
+ /obj/item/bedsheet/syndie,
+ )
+
+/obj/item/storage/box/syndie_kit/demoman
+ storage_type = /datum/storage/box/syndie_kit/demoman
+
+/obj/item/storage/box/syndie_kit/demoman/PopulateContents(datum/storage_config/config)
+
+ . = list(
+ /obj/item/gun/grenadelauncher,
+ /obj/item/storage/belt/grenade/full,
+ )
+
+ if(prob(1))
+ . += /obj/item/clothing/head/hats/hos/shako
+
+/obj/item/storage/box/syndie_kit/core_gear
+ name = "core equipment box"
+ desc = "Contains all the necessary gear for success for any nuclear operative unsure of what is needed for success in the field. Everything here WILL help you."
+
+/obj/item/storage/box/syndie_kit/core_gear/PopulateContents()
+ return list(
+ /obj/item/implanter/freedom ,
+ /obj/item/card/emag/doorjack ,
+ /obj/item/reagent_containers/hypospray/medipen/stimulants ,
+ /obj/item/grenade/c4 ,
+ /obj/item/mod/module/energy_shield,
+ )
+
+/// Surplus Ammo Box
+
+/obj/item/storage/box/syndie_kit/sniper_surplus
+ name = "surplus .50 BMG magazine box"
+ desc = "A shoddy box full of surplus .50 BMG magazines. Not as strong, but good enough to keep lead in the air."
+
+/obj/item/storage/box/syndie_kit/sniper_surplus/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/ammo_box/magazine/sniper_rounds/surplus
+
+/obj/item/storage/box/syndie_kit/shotgun_surplus
+ name = "\improper Donk Co. 'Donk Spike' flechette 12g Bulldog magazine box"
+ desc = "A shoddy box full of Donk Co. 'Donk Spike' flechette 12g. It is debatable whether or not these are actually \
+ better or worse than standard flechette. Donk Co. did genuinely believe in this product being the future of military \
+ ammunition production. The only reason it didn't see wider adoption was a lack of faith in the product. Do you \
+ believe in Donk? Time to put that to the test."
+
+/obj/item/storage/box/syndie_kit/shotgun_surplus/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/ammo_box/magazine/m12g/donk
+
+///Subtype for the sabotage bundle. Contains three C4, two X4 and 6 signalers
+/obj/item/storage/backpack/duffelbag/syndie/sabotage/PopulateContents()
+ return list(
+ /obj/item/grenade/c4,
+ /obj/item/grenade/c4,
+ /obj/item/grenade/c4,
+ /obj/item/grenade/c4/x4,
+ /obj/item/grenade/c4/x4,
+ /obj/item/storage/box/syndie_kit/signaler,
+ )
+
+/obj/item/storage/box/syndie_kit/signaler
+ name = "signaler box"
+ desc = "Contains everything an agent would need to remotely detonate their bombs."
+
+/obj/item/storage/box/syndie_kit/signaler/PopulateContents()
+ . = list()
+ for(var/i in 1 to 6)
+ . += /obj/item/assembly/signaler
+
+/obj/item/storage/box/syndie_kit/imp_deathrattle
+ name = "deathrattle implant box"
+ desc = "Contains eight linked deathrattle implants."
+ storage_type = /datum/storage/box/syndie_kit/imp_deathrattle
+
+/obj/item/storage/box/syndie_kit/imp_deathrattle/PopulateContents()
+ . = list(/obj/item/implanter)
+
+ var/datum/deathrattle_group/group = new
+
+ var/implants = list()
+ for(var/j in 1 to 8)
+ var/obj/item/implantcase/deathrattle/case = new (null)
+ implants += case.imp
+ . += case
+
+ for(var/i in implants)
+ group.register(i)
+ desc += " The implants are registered to the \"[group.name]\" group."
+
+/obj/item/storage/box/stickers/syndie_kit/PopulateContents()
+ var/static/list/types = subtypesof(/obj/item/sticker/syndicate)
+
+ . = list()
+ for(var/i in 1 to 7)
+ . += pick(types)
+
+/obj/item/storage/box/syndie_kit/pinata
+ name = "weapons grade pinata kit"
+ desc = "Contains a weapons grade pinata and 2 belts for carrying its contents."
+ storage_type = /datum/storage/box/syndie_kit/pinata
+
+/obj/item/storage/box/syndie_kit/pinata/PopulateContents()
+ return list(
+ /obj/item/pinata/syndie,
+ /obj/item/storage/belt/grenade,
+ /obj/item/storage/belt/military/snack,
+ )
+
+/obj/item/storage/box/syndie_kit/induction_kit
+ name = "syndicate induction kit"
+ desc = "Contains all you need for introducing your newest comrade to the Syndicate and all its worker's benefits."
+ storage_type = /datum/storage/box/syndie_kit/induction_kit
+
+/obj/item/storage/box/syndie_kit/induction_kit/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_count = TRUE
+ config.compute_max_total_weight = TRUE
+
+ var/obj/item/clothing/suit/space/syndicate/spess_suit = pick(GLOB.syndicate_space_suits_to_helmets)
+ return list(
+ // Basic weaponry, so they have something to use.
+ /obj/item/gun/ballistic/automatic/pistol/clandestine, // 6 TC, but free for nukies
+ /obj/item/ammo_box/magazine/m10mm/hp, // 3 TC, a reward for the teamwork involved
+ /obj/item/ammo_box/magazine/m10mm/ap, // 3 TC, a reward for the teamwork involved
+
+ // The necessary equipment to help secure that disky.
+ /obj/item/radio/headset/syndicate/alt, // 5 TC / Free for nukies
+ /obj/item/modular_computer/pda/nukeops, // ?? TC / Free for nukies
+ /obj/item/card/id/advanced/chameleon, // 2 TC / Free for nukies
+ spess_suit, // 4 TC for the space gear
+ GLOB.syndicate_space_suits_to_helmets[spess_suit],
+ /obj/item/tank/jetpack/oxygen/harness, // They kinda need this to fly to the cruiser.
+
+ // Tacticool gear
+ /obj/item/clothing/shoes/combat,
+ /obj/item/clothing/under/syndicate,
+ /obj/item/clothing/gloves/fingerless,
+ /obj/item/book/manual/nuclear, // Very important
+
+ // The most important part of the kit, the implant that gives them the syndicate faction.
+ /obj/item/implanter/induction_implant,
+ )
+
+ // All in all, 6+3+3+2+5+2+4 = ~25 TC of 'miscellaneous' items.
+ // This is a lot of value for 10 TC, but you have to keep in mind that you NEED someone to get this stuff station-side.
+ // Pretty much all of it is a bad deal for reinforcements or yourself as they already have similar or good-enough alternatives.
+
+/obj/item/implanter/induction_implant
+ name = "implanter (nuclear operative)"
+ desc = "A sterile automatic implant injector. You can see a tiny, somehow legible sticker on the side: 'NOT A BRAINWASH DEVICE'"
+ imp_type = /obj/item/implant/nuclear_operative
+
+/obj/item/implant/nuclear_operative
+ name = "nuclear operative implant"
+ desc = "Registers you as a member of a Syndicate nuclear operative team."
+ implant_color = "r"
+
+/obj/item/implant/nuclear_operative/get_data()
+ return "Implant Specifications:
\
+ Name: Suspicious Implant
\
+ Life: UNKNOWN
\
+ Implant Details:
\
+ Function: Strange implant that seems to resist any attempts at scanning it."
+
+/obj/item/implant/nuclear_operative/implant(mob/living/target, mob/user, silent = FALSE, force = FALSE)
+ . = ..()
+ if(!. || !ishuman(target) || !(target.mind))
+ return FALSE
+ var/mob/living/carbon/human/human_target = target
+
+ if(IS_NUKE_OP(human_target)) // this wont proc due to ..() but i guess its good as a just-in-case?
+ if(human_target == user)
+ to_chat(user, span_userdanger("You're already a nuclear operative, dumbass! The implant disintegrates within you! You feel sick..."))
+ human_target.Stun(10 SECONDS)
+ human_target.reagents.add_reagent(/datum/reagent/toxin, 10)
+ return FALSE
+ else
+ to_chat(user, span_notice("You finish implanting [human_target], but you don't really notice a difference. Huh."))
+ to_chat(human_target, span_userdanger("Nothing seems to really happen, but you start to feel a little ill.."))
+ human_target.reagents.add_reagent(/datum/reagent/toxin, 2)
+ return FALSE
+
+ /// If all the antag datums are 'fake' or none exist, disallow induction! No self-antagging.
+ var/faker
+ for(var/datum/antagonist/antag_datum as anything in human_target.mind.antag_datums)
+ if((antag_datum.antag_flags & FLAG_FAKE_ANTAG))
+ faker = TRUE
+
+ if(faker || isnull(human_target.mind.antag_datums)) // GTFO. Technically not foolproof but making a heartbreaker or a paradox clone a nuke op sounds hilarious
+ to_chat(human_target, span_notice("Huh? Nothing happened? But you're starting to feel a little ill..."))
+ human_target.reagents.add_reagent(/datum/reagent/toxin, 15)
+ return FALSE
+
+ var/datum/antagonist/nukeop/nuke_datum = new()
+ nuke_datum.send_to_spawnpoint = FALSE
+ nuke_datum.nukeop_outfit = null
+ human_target.mind?.add_antag_datum(nuke_datum)
+ human_target.faction |= ROLE_SYNDICATE
+ to_chat(human_target, span_warning("You are now a nuclear operative. Your main objective, if you were an antagonist and willing, is presumably to assist the nuclear operative team and secure the disk."))
+ to_chat(human_target, span_userdanger("This implant does NOT, in any way, brainwash you. If you were a normal crew member beforehand, forcibly implanted or otherwise, you are still one and cannot assist the nuclear operatives."))
+ return TRUE
+
+/obj/item/implant/nuclear_operative/removed(mob/target, silent = FALSE, special = FALSE)
+ . = ..()
+ if(!. || !isliving(target))
+ return FALSE
+ var/mob/living/living_target = target
+ living_target.mind.remove_antag_datum(/datum/antagonist/nukeop)
+ living_target.faction -= ROLE_SYNDICATE
+ to_chat(target, span_notice("You feel a little less nuclear."))
+ to_chat(target, span_userdanger("You're no longer identified as a nuclear operative! You are free to follow any valid goals you wish, even continuing to secure the disk. Just make sure neither any turrets nor operatives kill you on sight."))
+ return TRUE
+
+/obj/item/storage/box/syndie_kit/poster_box
+ name = "syndicate poster pack"
+ desc = "Contains a variety of demotivational posters to ensure minimum productivity for the crew of any Nanotrasen station."
+
+/obj/item/storage/box/syndie_kit/poster_box/PopulateContents()
+ . = list()
+ for(var/i in 1 to 3)
+ . += /obj/item/poster/traitor
+
+/obj/item/storage/box/syndie_kit/cowboy
+ name = "western outlaw pack"
+ desc = "Contains everything you'll need to be the rootin' tootin' cowboy you always wanted. Either play the Lone Ranger or go in with your posse of outlaws."
+ storage_type = /datum/storage/box/syndie_kit/cowboy
+
+/obj/item/storage/box/syndie_kit/cowboy/PopulateContents()
+ //Can spawn with snakes which runtime in null space so we do this
+ var/obj/item/clothing/shoes/cowboy/black/syndicate/shoes = new(src)
+ shoes.moveToNullspace()
+
+ return list(
+ shoes,
+ /obj/item/clothing/head/cowboy/black/syndicate,
+ /obj/item/storage/belt/holster/nukie/cowboy/full,
+ /obj/item/clothing/under/costume/dutch/syndicate,
+ /obj/item/lighter/skull,
+ /obj/item/sbeacondrop/horse,
+ /obj/item/food/grown/apple,
+ )
+
+/obj/item/storage/box/syndicate/contract_kit
+ name = "Contract Kit"
+ desc = "Supplied to Syndicate contractors."
+ icon_state = "syndiebox"
+ illustration = "writing_syndie"
+ storage_type = /datum/storage/box/syndicate/contract_kit
+
+/obj/item/storage/box/syndicate/contract_kit/PopulateContents()
+ return list(
+ /obj/item/modular_computer/pda/syndicate_contract_uplink,
+ /obj/item/storage/box/syndicate/contractor_loadout,
+ /obj/item/melee/baton/telescopic/contractor_baton,
+ // Paper guide is always last.
+ /obj/item/paper/contractor_guide,
+ )
+
+/obj/item/storage/box/syndicate/contractor_loadout
+ name = "Standard Loadout"
+ desc = "Supplied to Syndicate contractors, providing their specialised space suit and chameleon uniform."
+ icon_state = "syndiebox"
+ illustration = "writing_syndie"
+ storage_type = /datum/storage/box/syndicate/contractor_loadout
+
+/obj/item/storage/box/syndicate/contractor_loadout/PopulateContents()
+
+ return list(
+ /obj/item/mod/control/pre_equipped/infiltrator,
+ /obj/item/clothing/head/helmet/space/syndicate/contract,
+ /obj/item/clothing/suit/space/syndicate/contract,
+ /obj/item/clothing/under/chameleon,
+ /obj/item/clothing/mask/chameleon,
+ /obj/item/card/id/advanced/chameleon,
+ /obj/item/clothing/glasses/thermal/syndi,
+ /obj/item/storage/toolbox/syndicate,
+ /obj/item/jammer,
+ /obj/item/storage/fancy/cigarettes/cigpack_syndicate,
+ /obj/item/lighter,
+ )
+
+#undef KIT_RECON
+#undef KIT_BLOODY_SPAI
+#undef KIT_STEALTHY
+#undef KIT_SCREWED
+#undef KIT_SABOTAGE
+#undef KIT_GUN
+#undef KIT_MURDER
+#undef KIT_IMPLANTS
+#undef KIT_HACKER
+#undef KIT_SNIPER
+#undef KIT_NUKEOPS_METAGAME
+#undef KIT_LORD_SINGULOTH
+#undef KIT_REVOLUTIONARY
+
+#undef KIT_JAMES_BOND
+#undef KIT_NINJA
+#undef KIT_DARK_LORD
+#undef KIT_WHITE_WHALE_HOLY_GRAIL
+#undef KIT_MAD_SCIENTIST
+#undef KIT_BEES
+#undef KIT_MR_FREEZE
+#undef KIT_TRAITOR_2006
+#undef KIT_DEAD_MONEY
+#undef KIT_SAM_FISHER
+#undef KIT_PROP_HUNT
diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm
index a0b6e892e05..787eae7cc13 100644
--- a/code/game/objects/items/storage/briefcase.dm
+++ b/code/game/objects/items/storage/briefcase.dm
@@ -16,25 +16,25 @@
attack_verb_simple = list("bash", "batter", "bludgeon", "thrash", "whack")
resistance_flags = FLAMMABLE
max_integrity = 150
- var/folder_path = /obj/item/folder //this is the path of the folder that gets spawned in New()
+ storage_type = /datum/storage/briefcase
-/obj/item/storage/briefcase/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 21
+ ///this is the path of the folder that gets spawned in New()
+ var/folder_path = /obj/item/folder
/obj/item/storage/briefcase/PopulateContents()
- new /obj/item/pen(src)
- var/obj/item/folder/folder = new folder_path(src)
+ . = list(/obj/item/pen)
+
+ var/obj/item/folder/folder = new folder_path(null)
for(var/i in 1 to 6)
new /obj/item/paper(folder)
+ . += folder
/obj/item/storage/briefcase/lawyer
folder_path = /obj/item/folder/blue
/obj/item/storage/briefcase/lawyer/PopulateContents()
- new /obj/item/stamp/law(src)
- ..()
+ . = ..()
+ . += /obj/item/stamp/law
/obj/item/storage/briefcase/suicide_act(mob/living/user)
var/list/papers_found = list()
@@ -63,15 +63,16 @@
/obj/item/storage/briefcase/sniper
desc = "Its label reads \"genuine hardened Captain leather\", but suspiciously has no other tags or branding. Smells like L'Air du Temps."
force = 10
+ storage_type = /datum/storage/briefcase/sniper
/obj/item/storage/briefcase/sniper/PopulateContents()
- ..() // in case you need any paperwork done after your rampage
- new /obj/item/gun/ballistic/rifle/sniper_rifle/syndicate(src)
- new /obj/item/clothing/neck/tie/red/hitman(src)
- new /obj/item/clothing/under/syndicate/sniper(src)
- new /obj/item/ammo_box/magazine/sniper_rounds(src)
- new /obj/item/ammo_box/magazine/sniper_rounds(src)
- new /obj/item/ammo_box/magazine/sniper_rounds/disruptor(src)
+ . = ..() // in case you need any paperwork done after your rampage
+ . += /obj/item/gun/ballistic/rifle/sniper_rifle/syndicate
+ . += /obj/item/clothing/neck/tie/red/hitman
+ . += /obj/item/clothing/under/syndicate/sniper
+ . += /obj/item/ammo_box/magazine/sniper_rounds
+ . += /obj/item/ammo_box/magazine/sniper_rounds
+ . += /obj/item/ammo_box/magazine/sniper_rounds/disruptor
/**
* Secure briefcase
@@ -86,8 +87,7 @@
/obj/item/storage/briefcase/secure/Initialize(mapload)
. = ..()
- atom_storage.max_total_storage = 21
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
+
AddComponent(/datum/component/lockable_storage)
///Syndie variant of Secure Briefcase. Contains space cash, slightly more robust.
@@ -96,26 +96,28 @@
/obj/item/storage/briefcase/secure/syndie/PopulateContents()
. = ..()
- for(var/iterator in 1 to 5)
- new /obj/item/stack/spacecash/c1000(src)
+ for(var/_ in 1 to 5)
+ . += /obj/item/stack/spacecash/c1000
/// A briefcase that contains various sought-after spoils
-/obj/item/storage/briefcase/secure/riches
-
/obj/item/storage/briefcase/secure/riches/PopulateContents()
- new /obj/item/clothing/suit/armor/vest(src)
- new /obj/item/gun/ballistic/automatic/pistol(src)
- new /obj/item/suppressor(src)
- new /obj/item/melee/baton/telescopic(src)
- new /obj/item/clothing/mask/balaclava(src)
- new /obj/item/bodybag(src)
- new /obj/item/soap/nanotrasen(src)
+ return list(
+ /obj/item/clothing/suit/armor/vest,
+ /obj/item/gun/ballistic/automatic/pistol,
+ /obj/item/suppressor,
+ /obj/item/melee/baton/telescopic,
+ /obj/item/clothing/mask/balaclava,
+ /obj/item/bodybag,
+ /obj/item/soap/nanotrasen,
+ )
/obj/item/storage/briefcase/hitchiker/PopulateContents()
- new /obj/item/food/sandwich/peanut_butter_jelly(src)
- new /obj/item/food/sandwich/peanut_butter_jelly(src)
- new /obj/item/reagent_containers/cup/glass/waterbottle/large(src)
- new /obj/item/soap(src)
- new /obj/item/pillow/random(src)
- new /obj/item/tank/internals/emergency_oxygen(src)
- new /obj/item/tank/internals/emergency_oxygen(src)
+ return list(
+ /obj/item/clothing/suit/armor/vest,
+ /obj/item/gun/ballistic/automatic/pistol,
+ /obj/item/suppressor,
+ /obj/item/melee/baton/telescopic,
+ /obj/item/clothing/mask/balaclava,
+ /obj/item/bodybag,
+ /obj/item/soap/nanotrasen,
+ )
diff --git a/code/game/objects/items/storage/dufflebags.dm b/code/game/objects/items/storage/dufflebags.dm
new file mode 100644
index 00000000000..3304c4bbc17
--- /dev/null
+++ b/code/game/objects/items/storage/dufflebags.dm
@@ -0,0 +1,404 @@
+/obj/item/storage/backpack/duffelbag
+ name = "duffel bag"
+ desc = "A large duffel bag for holding extra things."
+ icon_state = "duffel"
+ inhand_icon_state = "duffel"
+ actions_types = list(/datum/action/item_action/zipper)
+ action_slots = ALL
+ storage_type = /datum/storage/duffel
+ // How much to slow you down if your bag isn't zipped up
+ var/zip_slowdown = 1
+ /// If this bag is zipped (contents hidden) up or not
+ /// Starts enabled so you're forced to interact with it to "get" it
+ var/zipped_up = TRUE
+ // How much time it takes to zip up (close) the duffelbag
+ var/zip_up_duration = 0.5 SECONDS
+ // Audio played during zipup
+ var/zip_up_sfx = 'sound/items/zip/zip_up.ogg'
+ // How much time it takes to unzip the duffel
+ var/unzip_duration = 2.1 SECONDS
+ // Audio played during unzip
+ var/unzip_sfx = 'sound/items/zip/un_zip.ogg'
+
+/obj/item/storage/backpack/duffelbag/Initialize(mapload)
+ . = ..()
+ set_zipper(TRUE)
+
+/obj/item/storage/backpack/duffelbag/update_desc(updates)
+ . = ..()
+ desc = "[initial(desc)]
[zipped_up ? "It's zipped up, preventing you from accessing its contents." : "It's unzipped, and harder to move in."]"
+
+/obj/item/storage/backpack/duffelbag/attack_self(mob/user, modifiers)
+ if(loc != user) // God fuck TK
+ return ..()
+ if(zipped_up)
+ return attack_hand(user, modifiers)
+ else
+ return attack_hand_secondary(user, modifiers)
+
+/obj/item/storage/backpack/duffelbag/attack_self_secondary(mob/user, modifiers)
+ attack_self(user, modifiers)
+ return ..()
+
+// If we're zipped, click to unzip
+/obj/item/storage/backpack/duffelbag/attack_hand(mob/user, list/modifiers)
+ if(loc != user)
+ // Hacky, but please don't be cringe yeah?
+ atom_storage.silent = TRUE
+ . = ..()
+ atom_storage.silent = initial(atom_storage.silent)
+ return
+ if(!zipped_up)
+ return ..()
+
+ balloon_alert(user, "unzipping...")
+ playsound(src, unzip_sfx, 100, FALSE)
+ var/datum/callback/can_unzip = CALLBACK(src, PROC_REF(zipper_matches), TRUE)
+ if(!do_after(user, unzip_duration, src, extra_checks = can_unzip))
+ user.balloon_alert(user, "unzip failed!")
+ return
+ balloon_alert(user, "unzipped")
+ set_zipper(FALSE)
+ return TRUE
+
+// Vis versa
+/obj/item/storage/backpack/duffelbag/attack_hand_secondary(mob/user, list/modifiers)
+ if(loc != user)
+ return ..()
+ if(zipped_up)
+ return SECONDARY_ATTACK_CALL_NORMAL
+
+ balloon_alert(user, "zipping...")
+ playsound(src, zip_up_sfx, 100, FALSE)
+ var/datum/callback/can_zip = CALLBACK(src, PROC_REF(zipper_matches), FALSE)
+ if(!do_after(user, zip_up_duration, src, extra_checks = can_zip))
+ user.balloon_alert(user, "zip failed!")
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+ balloon_alert(user, "zipped")
+ set_zipper(TRUE)
+ return SECONDARY_ATTACK_CONTINUE_CHAIN
+
+/// Checks to see if the zipper matches the passed in state
+/// Returns true if so, false otherwise
+/obj/item/storage/backpack/duffelbag/proc/zipper_matches(matching_value)
+ return zipped_up == matching_value
+
+/obj/item/storage/backpack/duffelbag/proc/set_zipper(new_zip)
+ zipped_up = new_zip
+ SEND_SIGNAL(src, COMSIG_DUFFEL_ZIP_CHANGE, new_zip)
+ if(zipped_up)
+ slowdown = initial(slowdown)
+ atom_storage.locked = STORAGE_SOFT_LOCKED
+ atom_storage.display_contents = FALSE
+ for(var/obj/item/weapon as anything in get_all_contents_type(/obj/item)) //close ui of this and all items inside dufflebag
+ weapon.atom_storage?.close_all() //not everything has storage initialized
+ else
+ slowdown = zip_slowdown
+ atom_storage.locked = STORAGE_NOT_LOCKED
+ atom_storage.display_contents = TRUE
+
+ if(isliving(loc))
+ var/mob/living/wearer = loc
+ wearer.update_equipment_speed_mods()
+ update_appearance()
+
+/obj/item/storage/backpack/duffelbag/cursed
+ name = "living duffel bag"
+ desc = "A cursed clown duffel bag that hungers for food of any kind. A warning label suggests that it eats food inside. \
+ If that food happens to be a horribly ruined mess or the chef scrapped out of the microwave, or poisoned in some way, \
+ then it might have negative effects on the bag..."
+ icon_state = "duffel-curse"
+ inhand_icon_state = "duffel-curse"
+ zip_slowdown = 2
+ max_integrity = 100
+
+/obj/item/storage/backpack/duffelbag/cursed/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/curse_of_hunger, add_dropdel = TRUE)
+
+/obj/item/storage/backpack/duffelbag/captain
+ name = "captain's duffel bag"
+ desc = "A large duffel bag for holding extra captainly goods."
+ icon_state = "duffel-captain"
+ inhand_icon_state = "duffel-captain"
+
+/obj/item/storage/backpack/duffelbag/med
+ name = "medical duffel bag"
+ desc = "A large duffel bag for holding extra medical supplies."
+ icon_state = "duffel-medical"
+ inhand_icon_state = "duffel-med"
+
+/obj/item/storage/backpack/duffelbag/coroner
+ name = "coroner duffel bag"
+ desc = "A large duffel bag for holding large amounts of organs at once."
+ icon_state = "duffel-coroner"
+ inhand_icon_state = "duffel-coroner"
+
+/obj/item/storage/backpack/duffelbag/explorer
+ name = "explorer duffel bag"
+ desc = "A large duffel bag for holding extra exotic treasures."
+ icon_state = "duffel-explorer"
+ inhand_icon_state = "duffel-explorer"
+
+/obj/item/storage/backpack/duffelbag/hydroponics
+ name = "hydroponic's duffel bag"
+ desc = "A large duffel bag for holding extra gardening tools."
+ icon_state = "duffel-hydroponics"
+ inhand_icon_state = "duffel-hydroponics"
+
+/obj/item/storage/backpack/duffelbag/chemistry
+ name = "chemistry duffel bag"
+ desc = "A large duffel bag for holding extra chemical substances."
+ icon_state = "duffel-chemistry"
+ inhand_icon_state = "duffel-chemistry"
+
+/obj/item/storage/backpack/duffelbag/genetics
+ name = "geneticist's duffel bag"
+ desc = "A large duffel bag for holding extra genetic mutations."
+ icon_state = "duffel-genetics"
+ inhand_icon_state = "duffel-genetics"
+
+/obj/item/storage/backpack/duffelbag/science
+ name = "scientist's duffel bag"
+ desc = "A large duffel bag for holding extra scientific components."
+ icon_state = "duffel-science"
+ inhand_icon_state = "duffel-sci"
+
+/obj/item/storage/backpack/duffelbag/virology
+ name = "virologist's duffel bag"
+ desc = "A large duffel bag for holding extra viral bottles."
+ icon_state = "duffel-virology"
+ inhand_icon_state = "duffel-virology"
+
+/obj/item/storage/backpack/duffelbag/sec
+ name = "security duffel bag"
+ desc = "A large duffel bag for holding extra security supplies and ammunition."
+ icon_state = "duffel-security"
+ inhand_icon_state = "duffel-sec"
+
+/obj/item/storage/backpack/duffelbag/sec/surgery
+ name = "surgical duffel bag"
+ desc = "A large duffel bag for holding extra supplies - this one has a material inlay with space for various sharp-looking tools."
+
+/obj/item/storage/backpack/duffelbag/sec/surgery/PopulateContents()
+ return list(
+ /obj/item/scalpel,
+ /obj/item/hemostat,
+ /obj/item/retractor,
+ /obj/item/circular_saw,
+ /obj/item/bonesetter,
+ /obj/item/surgicaldrill,
+ /obj/item/cautery,
+ /obj/item/surgical_drapes,
+ /obj/item/clothing/mask/surgical,
+ /obj/item/blood_filter,
+ )
+
+/obj/item/storage/backpack/duffelbag/engineering
+ name = "industrial duffel bag"
+ desc = "A large duffel bag for holding extra tools and supplies."
+ icon_state = "duffel-engineering"
+ inhand_icon_state = "duffel-eng"
+ resistance_flags = FIRE_PROOF
+
+/obj/item/storage/backpack/duffelbag/drone
+ name = "drone duffel bag"
+ desc = "A large duffel bag for holding tools and hats."
+ icon_state = "duffel-drone"
+ inhand_icon_state = "duffel-drone"
+ resistance_flags = FIRE_PROOF
+
+/obj/item/storage/backpack/duffelbag/drone/PopulateContents()
+ return list(
+ /obj/item/screwdriver,
+ /obj/item/wrench,
+ /obj/item/weldingtool,
+ /obj/item/crowbar,
+ /obj/item/stack/cable_coil,
+ /obj/item/wirecutters,
+ /obj/item/multitool,
+ )
+
+/obj/item/storage/backpack/duffelbag/clown
+ name = "clown's duffel bag"
+ desc = "A large duffel bag for holding lots of funny gags!"
+ icon_state = "duffel-clown"
+ inhand_icon_state = "duffel-clown"
+
+/obj/item/storage/backpack/duffelbag/clown/cream_pie/PopulateContents()
+ return list(
+ /obj/item/food/pie/cream,
+ /obj/item/food/pie/cream,
+ /obj/item/food/pie/cream,
+ /obj/item/food/pie/cream,
+ )
+
+/obj/item/storage/backpack/fireproof
+ resistance_flags = FIRE_PROOF
+
+/obj/item/storage/backpack/duffelbag/syndie
+ name = "suspicious looking duffel bag"
+ desc = "A large duffel bag for holding extra tactical supplies. It contains an oiled plastitanium zipper for maximum speed tactical zipping, and is better balanced on your back than an average duffelbag. Can hold two bulky items!"
+ icon_state = "duffel-syndie"
+ inhand_icon_state = "duffel-syndieammo"
+ resistance_flags = FIRE_PROOF
+ // Less slowdown while unzipped. Still bulky, but it won't halve your movement speed in an active combat situation.
+ zip_slowdown = 0.3
+ // Faster unzipping. Utilizes the same noise as zipping up to fit the unzip duration.
+ unzip_duration = 0.5 SECONDS
+ unzip_sfx = 'sound/items/zip/zip_up.ogg'
+ storage_type = /datum/storage/duffel/syndicate
+
+/obj/item/storage/backpack/duffelbag/syndie/hitman
+ desc = "A large duffel bag for holding extra things. There is a Nanotrasen logo on the back."
+ icon_state = "duffel-syndieammo"
+ inhand_icon_state = "duffel-syndieammo"
+
+/obj/item/storage/backpack/duffelbag/syndie/hitman/PopulateContents()
+ return list(
+ /obj/item/clothing/under/costume/buttondown/slacks/service,
+ /obj/item/clothing/neck/tie/red/hitman,
+ /obj/item/clothing/accessory/waistcoat,
+ /obj/item/clothing/suit/toggle/lawyer/black,
+ /obj/item/clothing/shoes/laceup,
+ /obj/item/clothing/gloves/color/black,
+ /obj/item/clothing/glasses/sunglasses,
+ /obj/item/clothing/head/fedora,
+ )
+
+/obj/item/storage/backpack/duffelbag/syndie/med
+ name = "medical duffel bag"
+ desc = "A large duffel bag for holding extra tactical medical supplies."
+ icon_state = "duffel-syndiemed"
+ inhand_icon_state = "duffel-syndiemed"
+
+/obj/item/storage/backpack/duffelbag/syndie/surgery
+ name = "surgery duffel bag"
+ desc = "A suspicious looking duffel bag for holding surgery tools."
+ icon_state = "duffel-syndiemed"
+ inhand_icon_state = "duffel-syndiemed"
+
+/obj/item/storage/backpack/duffelbag/syndie/surgery/PopulateContents()
+ return list(
+ /obj/item/scalpel/advanced,
+ /obj/item/retractor/advanced,
+ /obj/item/cautery/advanced,
+ /obj/item/surgical_drapes,
+ /obj/item/reagent_containers/medigel/sterilizine,
+ /obj/item/bonesetter,
+ /obj/item/blood_filter,
+ /obj/item/stack/medical/bone_gel,
+ /obj/item/stack/sticky_tape/surgical,
+ /obj/item/emergency_bed,
+ /obj/item/clothing/suit/jacket/straight_jacket,
+ /obj/item/clothing/mask/muzzle,
+ /obj/item/mmi/syndie,
+ )
+
+/obj/item/storage/backpack/duffelbag/syndie/ammo
+ name = "ammunition duffel bag"
+ desc = "A large duffel bag for holding extra weapons ammunition and supplies."
+ icon_state = "duffel-syndieammo"
+ inhand_icon_state = "duffel-syndieammo"
+
+/obj/item/storage/backpack/duffelbag/syndie/ammo/mech
+ desc = "A large duffel bag, packed to the brim with various exosuit ammo."
+ storage_type = /datum/storage/duffel/syndicate/ammo_mech
+
+/obj/item/storage/backpack/duffelbag/syndie/ammo/mech/PopulateContents()
+ return list(
+ /obj/item/mecha_ammo/scattershot,
+ /obj/item/mecha_ammo/scattershot,
+ /obj/item/mecha_ammo/scattershot,
+ /obj/item/mecha_ammo/scattershot,
+ /obj/item/storage/belt/utility/syndicate,
+ )
+
+/obj/item/storage/backpack/duffelbag/syndie/ammo/mauler
+ desc = "A large duffel bag, packed to the brim with various exosuit ammo."
+ storage_type = /datum/storage/duffel/syndicate/ammo_mauler
+
+/obj/item/storage/backpack/duffelbag/syndie/ammo/mauler/PopulateContents()
+ return list(
+ /obj/item/mecha_ammo/lmg,
+ /obj/item/mecha_ammo/lmg,
+ /obj/item/mecha_ammo/lmg,
+ /obj/item/mecha_ammo/scattershot,
+ /obj/item/mecha_ammo/scattershot,
+ /obj/item/mecha_ammo/scattershot,
+ /obj/item/mecha_ammo/missiles_srm,
+ /obj/item/mecha_ammo/missiles_srm,
+ /obj/item/mecha_ammo/missiles_srm,
+ )
+
+/obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle
+ desc = "A large duffel bag containing a medical equipment, a Donksoft LMG, a big jumbo box of riot darts, and a magboot MODsuit module."
+
+/obj/item/storage/backpack/duffelbag/syndie/med/medicalbundle/PopulateContents()
+ return list(
+ /obj/item/mod/module/magboot,
+ /obj/item/storage/medkit/tactical/premium,
+ /obj/item/gun/ballistic/automatic/l6_saw/toy,
+ /obj/item/ammo_box/foambox/riot,
+ )
+
+/obj/item/storage/backpack/duffelbag/syndie/med/bioterrorbundle
+ desc = "A large duffel bag containing deadly chemicals, a handheld chem sprayer, Bioterror foam grenade, a Donksoft assault rifle, box of riot grade darts, a dart pistol, and a box of syringes."
+
+/obj/item/storage/backpack/duffelbag/syndie/med/bioterrorbundle/PopulateContents()
+ var/list/obj/item/stuff = list(
+ /obj/item/reagent_containers/spray/chemsprayer/bioterror,
+ /obj/item/storage/box/syndie_kit/chemical,
+ /obj/item/gun/syringe/syndicate,
+ /obj/item/gun/ballistic/automatic/c20r/toy,
+ /obj/item/storage/box/syringes,
+ /obj/item/ammo_box/foambox/riot,
+ /obj/item/grenade/chem_grenade/bioterrorfoam,
+ )
+
+ if(prob(5))
+ stuff += /obj/item/food/pizza/pineapple
+
+ return stuff
+
+/obj/item/storage/backpack/duffelbag/syndie/c4/PopulateContents()
+ . = list()
+ for(var/_ in 1 to 10)
+ . += /obj/item/grenade/c4
+
+/obj/item/storage/backpack/duffelbag/syndie/x4/PopulateContents()
+ . = list()
+ for(var/_ in 1 to 10)
+ . += /obj/item/grenade/c4/x4
+
+/obj/item/storage/backpack/duffelbag/syndie/firestarter
+ desc = "A large duffel bag containing a New Russian pyro backpack sprayer, Elite MODsuit, a Stechkin APS pistol, minibomb, ammo, and other equipment."
+ storage_type = /datum/storage/duffel/syndicate/firestarter
+
+/obj/item/storage/backpack/duffelbag/syndie/firestarter/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ return list(
+ /obj/item/clothing/under/syndicate/soviet,
+ /obj/item/mod/control/pre_equipped/elite/flamethrower,
+ /obj/item/gun/ballistic/automatic/pistol/aps,
+ /obj/item/ammo_box/magazine/m9mm_aps/fire,
+ /obj/item/ammo_box/magazine/m9mm_aps/fire,
+ /obj/item/reagent_containers/cup/glass/bottle/vodka/badminka,
+ /obj/item/reagent_containers/hypospray/medipen/stimulants,
+ /obj/item/grenade/syndieminibomb,
+ )
+
+// For ClownOps.
+/obj/item/storage/backpack/duffelbag/clown/syndie
+ storage_type = /datum/storage/duffel/syndicate
+
+/obj/item/storage/backpack/duffelbag/clown/syndie/PopulateContents()
+ return list(
+ /obj/item/modular_computer/pda/clown,
+ /obj/item/clothing/under/rank/civilian/clown,
+ /obj/item/clothing/shoes/clown_shoes,
+ /obj/item/clothing/mask/gas/clown_hat,
+ /obj/item/bikehorn,
+ /obj/item/implanter/sad_trombone,
+ )
diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm
index e88a0c9ee48..f14fd1fa283 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -30,17 +30,16 @@
/// Whether it supports open and closed state icons.
var/has_open_closed_states = TRUE
-/obj/item/storage/fancy/Initialize(mapload)
- . = ..()
-
- atom_storage.max_slots = spawn_count
-
-/obj/item/storage/fancy/PopulateContents()
+/obj/item/storage/fancy/PopulateContents(datum/storage_config/config)
if(!spawn_type)
return
- for(var/i = 1 to spawn_count)
- var/thing_in_box = pick(spawn_type)
- new thing_in_box(src)
+
+ config.compute_max_values()
+ config.whitelist_content_types = TRUE
+
+ . = list()
+ for(var/i in 1 to spawn_count)
+ . += pick(spawn_type)
/obj/item/storage/fancy/update_icon_state()
icon_state = "[base_icon_state][has_open_closed_states && open_status ? contents.len : null]"
@@ -104,14 +103,6 @@
custom_premium_price = PAYCHECK_COMMAND * 1.75
contents_tag = "donut"
-/obj/item/storage/fancy/donut_box/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/food/donut)
-
-/obj/item/storage/fancy/donut_box/PopulateContents()
- . = ..()
- update_appearance()
-
/obj/item/storage/fancy/donut_box/update_icon_state()
. = ..()
icon_state = "[base_icon_state][open_status ? "_inner" : null]"
@@ -151,10 +142,6 @@
spawn_count = 12
contents_tag = "egg"
-/obj/item/storage/fancy/egg_box/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/food/egg)
-
/*
* Fertile Egg Box
*/
@@ -184,10 +171,6 @@
open_status = FANCY_CONTAINER_ALWAYS_OPEN
contents_tag = "candle"
-/obj/item/storage/fancy/candle_box/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/flashlight/flare/candle)
-
////////////
//CIG PACK//
////////////
@@ -207,6 +190,8 @@
custom_price = PAYCHECK_CREW
age_restricted = TRUE
contents_tag = "cigarette"
+ storage_type = /datum/storage/cigarette_box
+
///for cigarette overlay
var/candy = FALSE
/// Does this cigarette packet come with a coupon attached?
@@ -216,6 +201,12 @@
///Do we not have our own handling for cig overlays?
var/display_cigs = TRUE
+
+/obj/item/storage/fancy/cigarettes/Initialize(mapload)
+ . = ..()
+
+ register_context()
+
/obj/item/storage/fancy/cigarettes/attack_self(mob/user)
if(contents.len != 0 || !spawn_coupon)
return ..()
@@ -230,12 +221,6 @@
desc = "An old cigarette packet with the back torn off, worth less than nothing now."
atom_storage.max_slots = 0
-/obj/item/storage/fancy/cigarettes/Initialize(mapload)
- . = ..()
- atom_storage.display_contents = FALSE
- atom_storage.set_holdable(list(/obj/item/cigarette, /obj/item/lighter))
- register_context()
-
/obj/item/storage/fancy/cigarettes/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
. = ..()
if(interacting_with != user) // you can quickly put a cigarette in your mouth only
@@ -416,10 +401,6 @@
custom_price = PAYCHECK_LOWER
has_open_closed_states = FALSE
-/obj/item/storage/fancy/rollingpapers/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/rollingpaper)
-
/obj/item/storage/fancy/rollingpapers/update_overlays()
. = ..()
if(!contents.len)
@@ -442,10 +423,6 @@
spawn_coupon = FALSE
display_cigs = FALSE
-/obj/item/storage/fancy/cigarettes/cigars/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/cigarette/cigar)
-
/obj/item/storage/fancy/cigarettes/cigars/update_icon_state()
. = ..()
//reset any changes the parent call may have made
@@ -497,11 +474,6 @@
)
spawn_count = 8
-/obj/item/storage/fancy/heart_box/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/food/bonbon)
-
-
/obj/item/storage/fancy/nugget_box
name = "nugget box"
desc = "A cardboard box used for holding chicken nuggies."
@@ -512,10 +484,6 @@
spawn_type = /obj/item/food/nugget
spawn_count = 6
-/obj/item/storage/fancy/nugget_box/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/food/nugget)
-
/*
* Jar of pickles
*/
@@ -534,10 +502,6 @@
open_status = FANCY_CONTAINER_ALWAYS_OPEN
has_open_closed_states = FALSE
-/obj/item/storage/fancy/pickles_jar/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/food/pickle)
-
/obj/item/storage/fancy/pickles_jar/update_icon_state()
. = ..()
if(!contents.len)
@@ -564,16 +528,7 @@
foldable_result = /obj/item/stack/sheet/mineral/wood
open_status = FANCY_CONTAINER_ALWAYS_OPEN
has_open_closed_states = FALSE
-
-/obj/item/storage/fancy/coffee_condi_display/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 14
- atom_storage.set_holdable(list(
- /obj/item/reagent_containers/condiment/pack/sugar,
- /obj/item/reagent_containers/condiment/creamer,
- /obj/item/reagent_containers/condiment/pack/astrotame,
- /obj/item/reagent_containers/condiment/chocolate,
- ))
+ storage_type = /datum/storage/coffee_condi_display
/obj/item/storage/fancy/coffee_condi_display/update_overlays()
. = ..()
@@ -602,12 +557,9 @@
. += "condi_display_chocolate"
/obj/item/storage/fancy/coffee_condi_display/PopulateContents()
- for(var/i in 1 to 4)
- new /obj/item/reagent_containers/condiment/pack/sugar(src)
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/condiment/pack/astrotame(src)
- for(var/i in 1 to 4)
- new /obj/item/reagent_containers/condiment/creamer(src)
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/condiment/chocolate(src)
- update_appearance()
+ return flatten_quantified_list(list(
+ /obj/item/reagent_containers/condiment/pack/sugar = 4,
+ /obj/item/reagent_containers/condiment/pack/astrotame = 3,
+ /obj/item/reagent_containers/condiment/creamer = 4,
+ /obj/item/reagent_containers/condiment/chocolate = 3,
+ ))
diff --git a/code/game/objects/items/storage/garment.dm b/code/game/objects/items/storage/garment.dm
index 65dda7b65ea..5b218f45707 100644
--- a/code/game/objects/items/storage/garment.dm
+++ b/code/game/objects/items/storage/garment.dm
@@ -5,6 +5,7 @@
desc = "A bag for storing extra clothes and shoes."
slot_flags = NONE
resistance_flags = FLAMMABLE
+ storage_type = /datum/storage/bag/garment
/obj/item/storage/bag/garment/captain
name = "captain's garment bag"
@@ -38,120 +39,127 @@
name = "quartermasters's garment bag"
desc = "A bag for storing extra clothes and shoes. This one belongs to the quartermaster."
-/obj/item/storage/bag/garment/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.numerical_stacking = FALSE
- atom_storage.max_total_storage = 200
- atom_storage.max_slots = 15
- atom_storage.insert_preposition = "in"
- atom_storage.set_holdable(/obj/item/clothing)
-
/obj/item/storage/bag/garment/captain/PopulateContents()
- new /obj/item/clothing/under/rank/captain(src)
- new /obj/item/clothing/under/rank/captain/skirt(src)
- new /obj/item/clothing/under/rank/captain/parade(src)
- new /obj/item/clothing/suit/armor/vest/capcarapace(src)
- new /obj/item/clothing/suit/armor/vest/capcarapace/captains_formal(src)
- new /obj/item/clothing/suit/hooded/wintercoat/captain(src)
- new /obj/item/clothing/suit/jacket/capjacket(src)
- new /obj/item/clothing/glasses/sunglasses/gar/giga(src)
- new /obj/item/clothing/gloves/captain(src)
- new /obj/item/clothing/head/costume/crown/fancy(src)
- new /obj/item/clothing/head/hats/caphat(src)
- new /obj/item/clothing/head/hats/caphat/parade(src)
- new /obj/item/clothing/neck/cloak/cap(src)
- new /obj/item/clothing/shoes/laceup(src)
+ return list(
+ /obj/item/clothing/under/rank/captain,
+ /obj/item/clothing/under/rank/captain/skirt,
+ /obj/item/clothing/under/rank/captain/parade,
+ /obj/item/clothing/suit/armor/vest/capcarapace,
+ /obj/item/clothing/suit/armor/vest/capcarapace/captains_formal,
+ /obj/item/clothing/suit/hooded/wintercoat/captain,
+ /obj/item/clothing/suit/jacket/capjacket,
+ /obj/item/clothing/glasses/sunglasses/gar/giga,
+ /obj/item/clothing/gloves/captain,
+ /obj/item/clothing/head/costume/crown/fancy,
+ /obj/item/clothing/head/hats/caphat,
+ /obj/item/clothing/head/hats/caphat/parade,
+ /obj/item/clothing/neck/cloak/cap,
+ /obj/item/clothing/shoes/laceup,
+ )
/obj/item/storage/bag/garment/hop/PopulateContents()
- new /obj/item/clothing/under/rank/civilian/head_of_personnel(src)
- new /obj/item/clothing/under/rank/civilian/head_of_personnel/skirt(src)
- new /obj/item/clothing/suit/armor/vest/hop(src)
- new /obj/item/clothing/suit/hooded/wintercoat/hop(src)
- new /obj/item/clothing/glasses/sunglasses(src)
- new /obj/item/clothing/head/hats/hopcap(src)
- new /obj/item/clothing/neck/cloak/hop(src)
- new /obj/item/clothing/shoes/laceup(src)
+ return list(
+ /obj/item/clothing/under/rank/civilian/head_of_personnel,
+ /obj/item/clothing/under/rank/civilian/head_of_personnel/skirt,
+ /obj/item/clothing/suit/armor/vest/hop,
+ /obj/item/clothing/suit/hooded/wintercoat/hop,
+ /obj/item/clothing/glasses/sunglasses,
+ /obj/item/clothing/head/hats/hopcap,
+ /obj/item/clothing/neck/cloak/hop,
+ /obj/item/clothing/shoes/laceup,
+ )
/obj/item/storage/bag/garment/hos/PopulateContents()
- new /obj/item/clothing/under/rank/security/head_of_security/skirt(src)
- new /obj/item/clothing/under/rank/security/head_of_security/alt(src)
- new /obj/item/clothing/under/rank/security/head_of_security/alt/skirt(src)
- new /obj/item/clothing/under/rank/security/head_of_security/grey(src)
- new /obj/item/clothing/under/rank/security/head_of_security/parade(src)
- new /obj/item/clothing/under/rank/security/head_of_security/parade/female(src)
- new /obj/item/clothing/gloves/tackler/combat(src)
- new /obj/item/clothing/suit/armor/hos(src)
- new /obj/item/clothing/suit/armor/hos/hos_formal(src)
- new /obj/item/clothing/suit/armor/hos/trenchcoat/winter(src)
- new /obj/item/clothing/suit/armor/vest/leather(src)
- new /obj/item/clothing/glasses/hud/security/sunglasses/eyepatch(src)
- new /obj/item/clothing/glasses/hud/security/sunglasses/gars/giga(src)
- new /obj/item/clothing/head/hats/hos/beret(src)
- new /obj/item/clothing/head/hats/hos/cap(src)
- new /obj/item/clothing/mask/gas/sechailer/swat(src)
- new /obj/item/clothing/neck/cloak/hos(src)
+ return list(
+ /obj/item/clothing/under/rank/security/head_of_security/skirt,
+ /obj/item/clothing/under/rank/security/head_of_security/alt,
+ /obj/item/clothing/under/rank/security/head_of_security/alt/skirt,
+ /obj/item/clothing/under/rank/security/head_of_security/grey,
+ /obj/item/clothing/under/rank/security/head_of_security/parade,
+ /obj/item/clothing/under/rank/security/head_of_security/parade/female,
+ /obj/item/clothing/gloves/tackler/combat,
+ /obj/item/clothing/suit/armor/hos,
+ /obj/item/clothing/suit/armor/hos/hos_formal,
+ /obj/item/clothing/suit/armor/hos/trenchcoat/winter,
+ /obj/item/clothing/suit/armor/vest/leather,
+ /obj/item/clothing/glasses/hud/security/sunglasses/eyepatch,
+ /obj/item/clothing/glasses/hud/security/sunglasses/gars/giga,
+ /obj/item/clothing/head/hats/hos/beret,
+ /obj/item/clothing/head/hats/hos/cap,
+ /obj/item/clothing/mask/gas/sechailer/swat,
+ /obj/item/clothing/neck/cloak/hos,
+ )
/obj/item/storage/bag/garment/warden/PopulateContents()
- new /obj/item/clothing/suit/armor/vest/warden(src)
- new /obj/item/clothing/head/hats/warden(src)
- new /obj/item/clothing/head/hats/warden/drill(src)
- new /obj/item/clothing/head/beret/sec/navywarden(src)
- new /obj/item/clothing/suit/armor/vest/warden/alt(src)
- new /obj/item/clothing/under/rank/security/warden/formal(src)
- new /obj/item/clothing/under/rank/security/warden/skirt(src)
- new /obj/item/clothing/gloves/krav_maga/sec(src)
- new /obj/item/clothing/glasses/hud/security/sunglasses(src)
- new /obj/item/clothing/mask/gas/sechailer(src)
+ return list(
+ /obj/item/clothing/suit/armor/vest/warden,
+ /obj/item/clothing/head/hats/warden,
+ /obj/item/clothing/head/hats/warden/drill,
+ /obj/item/clothing/head/beret/sec/navywarden,
+ /obj/item/clothing/suit/armor/vest/warden/alt,
+ /obj/item/clothing/under/rank/security/warden/formal,
+ /obj/item/clothing/under/rank/security/warden/skirt,
+ /obj/item/clothing/gloves/krav_maga/sec,
+ /obj/item/clothing/glasses/hud/security/sunglasses,
+ /obj/item/clothing/mask/gas/sechailer,
+ )
/obj/item/storage/bag/garment/research_director/PopulateContents()
- new /obj/item/clothing/under/rank/rnd/research_director(src)
- new /obj/item/clothing/under/rank/rnd/research_director/skirt(src)
- new /obj/item/clothing/under/rank/rnd/research_director/alt(src)
- new /obj/item/clothing/under/rank/rnd/research_director/alt/skirt(src)
- new /obj/item/clothing/under/rank/rnd/research_director/turtleneck(src)
- new /obj/item/clothing/under/rank/rnd/research_director/turtleneck/skirt(src)
- new /obj/item/clothing/suit/hooded/wintercoat/science/rd(src)
- new /obj/item/clothing/head/beret/science/rd(src)
- new /obj/item/clothing/gloves/color/black(src)
- new /obj/item/clothing/neck/cloak/rd(src)
- new /obj/item/clothing/shoes/jackboots(src)
+ return list(
+ /obj/item/clothing/under/rank/rnd/research_director,
+ /obj/item/clothing/under/rank/rnd/research_director/skirt,
+ /obj/item/clothing/under/rank/rnd/research_director/alt,
+ /obj/item/clothing/under/rank/rnd/research_director/alt/skirt,
+ /obj/item/clothing/under/rank/rnd/research_director/turtleneck,
+ /obj/item/clothing/under/rank/rnd/research_director/turtleneck/skirt,
+ /obj/item/clothing/suit/hooded/wintercoat/science/rd,
+ /obj/item/clothing/head/beret/science/rd,
+ /obj/item/clothing/gloves/color/black,
+ /obj/item/clothing/neck/cloak/rd,
+ /obj/item/clothing/shoes/jackboots,
+ )
/obj/item/storage/bag/garment/chief_medical/PopulateContents()
- new /obj/item/clothing/under/rank/medical/chief_medical_officer(src)
- new /obj/item/clothing/under/rank/medical/chief_medical_officer/skirt(src)
- new /obj/item/clothing/under/rank/medical/chief_medical_officer/scrubs(src)
- new /obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck(src)
- new /obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck/skirt(src)
- new /obj/item/clothing/suit/hooded/wintercoat/medical/cmo(src)
- new /obj/item/clothing/suit/toggle/labcoat/cmo(src)
- new /obj/item/clothing/gloves/latex/nitrile(src)
- new /obj/item/clothing/head/beret/medical/cmo(src)
- new /obj/item/clothing/head/utility/surgerycap/cmo(src)
- new /obj/item/clothing/neck/cloak/cmo(src)
- new /obj/item/clothing/shoes/sneakers/blue (src)
+ return list(
+ /obj/item/clothing/under/rank/medical/chief_medical_officer,
+ /obj/item/clothing/under/rank/medical/chief_medical_officer/skirt,
+ /obj/item/clothing/under/rank/medical/chief_medical_officer/scrubs,
+ /obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck,
+ /obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck/skirt,
+ /obj/item/clothing/suit/hooded/wintercoat/medical/cmo,
+ /obj/item/clothing/suit/toggle/labcoat/cmo,
+ /obj/item/clothing/gloves/latex/nitrile,
+ /obj/item/clothing/head/beret/medical/cmo,
+ /obj/item/clothing/head/utility/surgerycap/cmo,
+ /obj/item/clothing/neck/cloak/cmo,
+ /obj/item/clothing/shoes/sneakers/blue ,
+ )
/obj/item/storage/bag/garment/engineering_chief/PopulateContents()
- new /obj/item/clothing/under/rank/engineering/chief_engineer(src)
- new /obj/item/clothing/under/rank/engineering/chief_engineer/skirt(src)
- new /obj/item/clothing/under/rank/engineering/chief_engineer/turtleneck(src)
- new /obj/item/clothing/under/rank/engineering/chief_engineer/turtleneck/skirt(src)
- new /obj/item/clothing/suit/hooded/wintercoat/engineering/ce(src)
- new /obj/item/clothing/glasses/meson/engine(src)
- new /obj/item/clothing/gloves/chief_engineer(src)
- new /obj/item/clothing/head/utility/hardhat/white(src)
- new /obj/item/clothing/head/utility/hardhat/welding/white(src)
- new /obj/item/clothing/neck/cloak/ce(src)
- new /obj/item/clothing/shoes/sneakers/brown(src)
+ return list(
+ /obj/item/clothing/under/rank/engineering/chief_engineer,
+ /obj/item/clothing/under/rank/engineering/chief_engineer/skirt,
+ /obj/item/clothing/under/rank/engineering/chief_engineer/turtleneck,
+ /obj/item/clothing/under/rank/engineering/chief_engineer/turtleneck/skirt,
+ /obj/item/clothing/suit/hooded/wintercoat/engineering/ce,
+ /obj/item/clothing/glasses/meson/engine,
+ /obj/item/clothing/gloves/chief_engineer,
+ /obj/item/clothing/head/utility/hardhat/white,
+ /obj/item/clothing/head/utility/hardhat/welding/white,
+ /obj/item/clothing/neck/cloak/ce,
+ /obj/item/clothing/shoes/sneakers/brown,
+ )
/obj/item/storage/bag/garment/quartermaster/PopulateContents()
- new /obj/item/clothing/under/rank/cargo/qm(src)
- new /obj/item/clothing/under/rank/cargo/qm/skirt(src)
- new /obj/item/clothing/suit/hooded/wintercoat/cargo/qm(src)
- new /obj/item/clothing/suit/utility/fire/firefighter(src)
- new /obj/item/clothing/gloves/fingerless(src)
- new /obj/item/clothing/suit/jacket/quartermaster(src)
- new /obj/item/clothing/head/soft(src)
- new /obj/item/clothing/mask/gas(src)
- new /obj/item/clothing/neck/cloak/qm(src)
- new /obj/item/clothing/shoes/sneakers/brown(src)
+ return list(
+ /obj/item/clothing/under/rank/cargo/qm,
+ /obj/item/clothing/under/rank/cargo/qm/skirt,
+ /obj/item/clothing/suit/hooded/wintercoat/cargo/qm,
+ /obj/item/clothing/suit/utility/fire/firefighter,
+ /obj/item/clothing/gloves/fingerless,
+ /obj/item/clothing/suit/jacket/quartermaster,
+ /obj/item/clothing/head/soft,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/neck/cloak/qm,
+ /obj/item/clothing/shoes/sneakers/brown,
+ )
diff --git a/code/game/objects/items/storage/holsters.dm b/code/game/objects/items/storage/holsters.dm
index 6de4e83abb7..78c73dc037f 100644
--- a/code/game/objects/items/storage/holsters.dm
+++ b/code/game/objects/items/storage/holsters.dm
@@ -7,6 +7,7 @@
worn_icon_state = "holster"
alternate_worn_layer = UNDER_SUIT_LAYER
w_class = WEIGHT_CLASS_BULKY
+ storage_type = /datum/storage/holster
/obj/item/storage/belt/holster/equipped(mob/user, slot)
. = ..()
@@ -17,105 +18,48 @@
. = ..()
REMOVE_CLOTHING_TRAIT(user, TRAIT_GUNFLIP)
-/obj/item/storage/belt/holster/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 1
- atom_storage.max_total_storage = 16
- atom_storage.set_holdable(list(
- /obj/item/gun/ballistic/automatic/pistol,
- /obj/item/gun/ballistic/revolver,
- /obj/item/gun/energy/e_gun/mini,
- /obj/item/gun/energy/disabler,
- /obj/item/gun/energy/dueling,
- /obj/item/food/grown/banana,
- /obj/item/gun/energy/laser/thermal,
- /obj/item/gun/ballistic/rifle/boltaction, //fits if you make it an obrez
- /obj/item/gun/energy/laser/captain,
- /obj/item/gun/energy/e_gun/hos,
- ))
- atom_storage.open_sound = 'sound/items/handling/holster_open.ogg'
- atom_storage.open_sound_vary = TRUE
-
/obj/item/storage/belt/holster/energy
name = "energy shoulder holsters"
desc = "A rather plain pair of shoulder holsters with a bit of insulated padding inside. Designed to hold energy weaponry."
-
-/obj/item/storage/belt/holster/energy/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 2
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.set_holdable(list(
- /obj/item/gun/energy/e_gun/mini,
- /obj/item/gun/energy/disabler,
- /obj/item/gun/energy/dueling,
- /obj/item/food/grown/banana,
- /obj/item/gun/energy/laser/thermal,
- /obj/item/gun/energy/recharge/ebow,
- /obj/item/gun/energy/laser/captain,
- /obj/item/gun/energy/e_gun/hos,
- ))
+ storage_type = /datum/storage/holster/energy
/obj/item/storage/belt/holster/energy/thermal
name = "thermal shoulder holsters"
desc = "A rather plain pair of shoulder holsters with a bit of insulated padding inside. Meant to hold a twinned pair of thermal pistols, but can fit several kinds of energy handguns as well."
/obj/item/storage/belt/holster/energy/thermal/PopulateContents()
- generate_items_inside(list(
+ return list(
/obj/item/gun/energy/laser/thermal/inferno = 1,
/obj/item/gun/energy/laser/thermal/cryo = 1,
- ),src)
+ )
/obj/item/storage/belt/holster/energy/disabler
desc = "A rather plain pair of shoulder holsters with a bit of insulated padding inside. Designed to hold energy weaponry. A production stamp indicates that it was shipped with a disabler."
/obj/item/storage/belt/holster/energy/disabler/PopulateContents()
- generate_items_inside(list(
- /obj/item/gun/energy/disabler = 1,
- ),src)
+ return /obj/item/gun/energy/disabler
/obj/item/storage/belt/holster/energy/smoothbore
desc = "A rather plain pair of shoulder holsters with a bit of insulated padding inside. Designed to hold energy weaponry. Seems it was meant to fit two smoothbores."
/obj/item/storage/belt/holster/energy/smoothbore/PopulateContents()
- generate_items_inside(list(
- /obj/item/gun/energy/disabler/smoothbore = 2,
- ),src)
+ return list(
+ /obj/item/gun/energy/disabler/smoothbore,
+ /obj/item/gun/energy/disabler/smoothbore
+ )
/obj/item/storage/belt/holster/detective
name = "detective's holster"
desc = "A holster able to carry handguns and some ammo. WARNING: Badasses only."
w_class = WEIGHT_CLASS_BULKY
-
-/obj/item/storage/belt/holster/detective/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 3
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.set_holdable(list(
- /obj/item/gun/ballistic/automatic/pistol,
- /obj/item/ammo_box/magazine/m9mm, // Pistol magazines.
- /obj/item/ammo_box/magazine/m9mm_aps,
- /obj/item/ammo_box/magazine/m10mm,
- /obj/item/ammo_box/magazine/m45,
- /obj/item/ammo_box/magazine/m50,
- /obj/item/gun/ballistic/revolver,
- /obj/item/ammo_box/c38, // Revolver speedloaders.
- /obj/item/ammo_box/a357,
- /obj/item/ammo_box/strilka310,
- /obj/item/ammo_box/magazine/toy/pistol,
- /obj/item/gun/energy/e_gun/mini,
- /obj/item/gun/energy/disabler,
- /obj/item/gun/energy/dueling,
- /obj/item/gun/energy/laser/thermal,
- /obj/item/gun/energy/laser/captain,
- /obj/item/gun/energy/e_gun/hos,
- /obj/item/gun/ballistic/rifle/boltaction, //fits if you make it an obrez
- ))
+ storage_type = /datum/storage/holster/detective
/obj/item/storage/belt/holster/detective/full/PopulateContents()
- generate_items_inside(list(
- /obj/item/ammo_box/c38 = 2,
- /obj/item/gun/ballistic/revolver/c38/detective = 1,
- ), src)
+ return list(
+ /obj/item/ammo_box/c38,
+ /obj/item/ammo_box/c38,
+ /obj/item/gun/ballistic/revolver/c38/detective
+ )
/obj/item/storage/belt/holster/detective/full/ert
name = "marine's holster"
@@ -125,10 +69,11 @@
worn_icon_state = "syndicate_holster"
/obj/item/storage/belt/holster/detective/full/ert/PopulateContents()
- generate_items_inside(list(
- /obj/item/ammo_box/magazine/m45 = 2,
- /obj/item/gun/ballistic/automatic/pistol/m1911 = 1,
- ),src)
+ return list(
+ /obj/item/ammo_box/magazine/m45,
+ /obj/item/ammo_box/magazine/m45,
+ /obj/item/gun/ballistic/automatic/pistol/m1911
+ )
/obj/item/storage/belt/holster/chameleon
name = "syndicate holster"
@@ -139,32 +84,7 @@
w_class = WEIGHT_CLASS_NORMAL
actions_types = list(/datum/action/item_action/chameleon/change/belt)
action_slots = ALL
-
-/obj/item/storage/belt/holster/chameleon/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 2
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.set_holdable(list(
- /obj/item/gun/ballistic/automatic/pistol,
- /obj/item/ammo_box/magazine/m9mm,
- /obj/item/ammo_box/magazine/m9mm_aps,
- /obj/item/ammo_box/magazine/m10mm,
- /obj/item/ammo_box/magazine/m45,
- /obj/item/ammo_box/magazine/m50,
- /obj/item/gun/ballistic/revolver,
- /obj/item/ammo_box/c38,
- /obj/item/ammo_box/a357,
- /obj/item/ammo_box/strilka310,
- /obj/item/ammo_box/magazine/toy/pistol,
- /obj/item/gun/energy/recharge/ebow,
- /obj/item/gun/energy/e_gun/mini,
- /obj/item/gun/energy/disabler,
- /obj/item/gun/energy/dueling,
- /obj/item/gun/energy/laser/captain,
- /obj/item/gun/energy/e_gun/hos,
- ))
-
- atom_storage.silent = TRUE
+ storage_type = /datum/storage/holster/chameleon
/obj/item/storage/belt/holster/nukie
name = "operative holster"
@@ -173,34 +93,18 @@
inhand_icon_state = "syndicate_holster"
worn_icon_state = "syndicate_holster"
w_class = WEIGHT_CLASS_BULKY
-
-/obj/item/storage/belt/holster/nukie/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 2
- atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
- atom_storage.set_holdable(list(
- /obj/item/gun, // ALL guns.
- /obj/item/ammo_box/magazine, // ALL magazines.
- /obj/item/ammo_box/c38, //There isn't a speedloader parent type, so I just put these three here by hand.
- /obj/item/ammo_box/a357, //I didn't want to just use /obj/item/ammo_box, because then this could hold huge boxes of ammo.
- /obj/item/ammo_box/strilka310,
- /obj/item/ammo_casing, // For shotgun shells, rockets, launcher grenades, and a few other things.
- /obj/item/grenade, // All regular grenades, the big grenade launcher fires these.
- ))
+ storage_type = /datum/storage/holster/nukie
/obj/item/storage/belt/holster/nukie/cowboy
desc = "A deep shoulder holster capable of holding almost any form of small firearm and its ammo. This one's specialized for handguns."
-
-/obj/item/storage/belt/holster/nukie/cowboy/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 3
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
+ storage_type = /datum/storage/holster/nukie/cowboy
/obj/item/storage/belt/holster/nukie/cowboy/full/PopulateContents()
- generate_items_inside(list(
- /obj/item/ammo_box/a357 = 2,
- /obj/item/gun/ballistic/revolver/cowboy/nuclear = 1,
- ), src)
+ return list(
+ /obj/item/ammo_box/a357,
+ /obj/item/ammo_box/a357,
+ /obj/item/gun/ballistic/revolver/cowboy/nuclear
+ )
diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm
index 8926e6fd83a..abeafa13b55 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -8,6 +8,8 @@
righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi'
w_class = WEIGHT_CLASS_BULKY
req_access = list(ACCESS_ARMORY)
+ storage_type = /datum/storage/lockbox
+
var/broken = FALSE
var/open = FALSE
var/icon_locked = "lockbox+l"
@@ -17,14 +19,24 @@
/obj/item/storage/lockbox/Initialize(mapload)
. = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 14
- atom_storage.max_slots = 4
+
atom_storage.locked = STORAGE_FULLY_LOCKED
register_context()
+
update_appearance()
+///screentips for lockboxes
+/obj/item/storage/lockbox/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ if(!held_item)
+ return NONE
+ if(src.broken)
+ return NONE
+ if(!held_item.GetID())
+ return NONE
+ context[SCREENTIP_CONTEXT_LMB] = atom_storage.locked ? "Unlock with ID" : "Lock with ID"
+ return CONTEXTUAL_SCREENTIP_SET
+
/obj/item/storage/lockbox/tool_act(mob/living/user, obj/item/tool, list/modifiers)
var/obj/item/card/card = tool.GetID()
if(isnull(card))
@@ -94,9 +106,10 @@
req_access = list(ACCESS_SECURITY)
/obj/item/storage/lockbox/loyalty/PopulateContents()
+ . = list()
for(var/i in 1 to 3)
- new /obj/item/implantcase/mindshield(src)
- new /obj/item/implanter/mindshield(src)
+ . += /obj/item/implantcase/mindshield
+ . += /obj/item/implanter/mindshield
/obj/item/storage/lockbox/clusterbang
name = "lockbox of clusterbangs"
@@ -104,7 +117,7 @@
req_access = list(ACCESS_SECURITY)
/obj/item/storage/lockbox/clusterbang/PopulateContents()
- new /obj/item/grenade/clusterbuster(src)
+ return /obj/item/grenade/clusterbuster
/obj/item/storage/lockbox/medal
name = "medal box"
@@ -119,13 +132,7 @@
icon_closed = "medalbox"
icon_broken = "medalbox+b"
icon_open = "medalboxopen"
-
-/obj/item/storage/lockbox/medal/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.max_slots = 10
- atom_storage.max_total_storage = 20
- atom_storage.set_holdable(/obj/item/clothing/accessory/medal)
+ storage_type = /datum/storage/lockbox/medal
/obj/item/storage/lockbox/medal/examine(mob/user)
. = ..()
@@ -139,15 +146,14 @@
return CLICK_ACTION_SUCCESS
/obj/item/storage/lockbox/medal/PopulateContents()
- new /obj/item/clothing/accessory/medal/gold/captain(src)
- new /obj/item/clothing/accessory/medal/silver/valor(src)
- new /obj/item/clothing/accessory/medal/silver/valor(src)
- new /obj/item/clothing/accessory/medal/silver/security(src)
- new /obj/item/clothing/accessory/medal/bronze_heart(src)
- new /obj/item/clothing/accessory/medal/plasma/nobel_science(src)
- new /obj/item/clothing/accessory/medal/plasma/nobel_science(src)
- for(var/i in 1 to 3)
- new /obj/item/clothing/accessory/medal/conduct(src)
+ return flatten_quantified_list(list(
+ /obj/item/clothing/accessory/medal/gold/captain = 1,
+ /obj/item/clothing/accessory/medal/silver/valor = 2,
+ /obj/item/clothing/accessory/medal/silver/security = 1,
+ /obj/item/clothing/accessory/medal/bronze_heart = 1,
+ /obj/item/clothing/accessory/medal/plasma/nobel_science = 2,
+ /obj/item/clothing/accessory/medal/conduct = 3,
+ ))
/obj/item/storage/lockbox/medal/update_overlays()
. = ..()
@@ -172,9 +178,10 @@
req_access = list(ACCESS_HOP)
/obj/item/storage/lockbox/medal/hop/PopulateContents()
+ . = list()
for(var/i in 1 to 3)
- new /obj/item/clothing/accessory/medal/silver/bureaucracy(src)
- new /obj/item/clothing/accessory/medal/gold/ordom(src)
+ . += /obj/item/clothing/accessory/medal/silver/bureaucracy
+ . += /obj/item/clothing/accessory/medal/gold/ordom
/obj/item/storage/lockbox/medal/sec
name = "security medal box"
@@ -187,14 +194,16 @@
req_access = list(ACCESS_CMO)
/obj/item/storage/lockbox/medal/med/PopulateContents()
- new /obj/item/clothing/accessory/medal/med_medal(src)
- new /obj/item/clothing/accessory/medal/med_medal2(src)
- for(var/i in 1 to 3)
- new /obj/item/clothing/accessory/medal/silver/emergency_services/medical(src)
+ return flatten_quantified_list(list(
+ /obj/item/clothing/accessory/medal/med_medal = 1,
+ /obj/item/clothing/accessory/medal/med_medal2 = 1,
+ /obj/item/clothing/accessory/medal/silver/emergency_services/medical = 3,
+ ))
/obj/item/storage/lockbox/medal/sec/PopulateContents()
+ . = list()
for(var/i in 1 to 3)
- new /obj/item/clothing/accessory/medal/silver/security(src)
+ . += /obj/item/clothing/accessory/medal/silver/security
/obj/item/storage/lockbox/medal/cargo
name = "cargo award box"
@@ -202,7 +211,7 @@
req_access = list(ACCESS_QM)
/obj/item/storage/lockbox/medal/cargo/PopulateContents()
- new /obj/item/clothing/accessory/medal/ribbon/cargo(src)
+ return /obj/item/clothing/accessory/medal/ribbon/cargo
/obj/item/storage/lockbox/medal/service
name = "service award box"
@@ -210,7 +219,7 @@
req_access = list(ACCESS_HOP)
/obj/item/storage/lockbox/medal/service/PopulateContents()
- new /obj/item/clothing/accessory/medal/silver/excellence(src)
+ return /obj/item/clothing/accessory/medal/silver/excellence
/obj/item/storage/lockbox/medal/sci
name = "science medal box"
@@ -218,8 +227,9 @@
req_access = list(ACCESS_RD)
/obj/item/storage/lockbox/medal/sci/PopulateContents()
+ . = list()
for(var/i in 1 to 3)
- new /obj/item/clothing/accessory/medal/plasma/nobel_science(src)
+ . += /obj/item/clothing/accessory/medal/plasma/nobel_science
/obj/item/storage/lockbox/medal/engineering
name = "engineering medal box"
@@ -227,9 +237,10 @@
req_access = list(ACCESS_CE)
/obj/item/storage/lockbox/medal/engineering/PopulateContents()
+ . = list()
for(var/i in 1 to 3)
- new /obj/item/clothing/accessory/medal/silver/emergency_services/engineering(src)
- new /obj/item/clothing/accessory/medal/silver/elder_atmosian(src)
+ . += /obj/item/clothing/accessory/medal/silver/emergency_services/engineering
+ . += /obj/item/clothing/accessory/medal/silver/elder_atmosian
/obj/item/storage/lockbox/order
name = "order lockbox"
@@ -243,6 +254,8 @@
lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi'
w_class = WEIGHT_CLASS_HUGE
+
+ ///The bank account of the mob who purchased this lockbox
var/datum/bank_account/buyer_account
/obj/item/storage/lockbox/order/Initialize(mapload, datum/bank_account/_buyer_account)
@@ -258,13 +271,24 @@
balloon_alert(user, "incorrect bank account!")
return FALSE
-///screentips for lockboxes
-/obj/item/storage/lockbox/add_context(atom/source, list/context, obj/item/held_item, mob/user)
- if(!held_item)
- return NONE
- if(src.broken)
- return NONE
- if(!held_item.GetID())
- return NONE
- context[SCREENTIP_CONTEXT_LMB] = atom_storage.locked ? "Unlock with ID" : "Lock with ID"
- return CONTEXTUAL_SCREENTIP_SET
+//Storage case.
+/obj/item/storage/lockbox/dueling
+ name = "dueling pistol case"
+ desc = "Let's solve this like gentlespacemen."
+ icon_state = "medalbox+l"
+ inhand_icon_state = "syringe_kit"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ w_class = WEIGHT_CLASS_NORMAL
+ req_access = list(ACCESS_CAPTAIN)
+ icon_locked = "medalbox+l"
+ icon_closed = "medalbox"
+ icon_broken = "medalbox+b"
+ base_icon_state = "medalbox"
+ icon_open = "medalboxopen"
+ storage_type = /datum/storage/lockbox/dueling
+
+/obj/item/storage/lockbox/dueling/PopulateContents()
+ var/obj/item/gun/energy/dueling/gun_A = new(null)
+ var/obj/item/gun/energy/dueling/gun_B = new(null)
+ new /datum/duel(gun_A, gun_B)
diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm
index 291df1951bb..f69a53a815e 100644
--- a/code/game/objects/items/storage/medkit.dm
+++ b/code/game/objects/items/storage/medkit.dm
@@ -21,70 +21,12 @@
drop_sound = 'sound/items/handling/medkit/medkit_drop.ogg'
pickup_sound = 'sound/items/handling/medkit/medkit_pick_up.ogg'
sound_vary = TRUE
+ storage_type = /datum/storage/medkit
+
+ ///Does this medkit start out empty
var/empty = FALSE
/// Defines damage type of the medkit. General ones stay null. Used for medibot healing bonuses
var/damagetype_healed
- /// you just type this in holdables list of medkits instead of copypasting bunch of text.
- var/static/list/list_of_everything_medkits_can_hold = list(
- /obj/item/healthanalyzer,
- /obj/item/dnainjector,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/cup/beaker,
- /obj/item/reagent_containers/cup/bottle,
- /obj/item/reagent_containers/cup/tube,
- /obj/item/reagent_containers/applicator,
- /obj/item/reagent_containers/syringe,
- /obj/item/reagent_containers/medigel,
- /obj/item/reagent_containers/spray,
- /obj/item/lighter,
- /obj/item/storage/box/bandages,
- /obj/item/storage/fancy/cigarettes,
- /obj/item/storage/pill_bottle,
- /obj/item/stack/medical,
- /obj/item/flashlight/pen,
- /obj/item/extinguisher/mini,
- /obj/item/reagent_containers/hypospray,
- /obj/item/sensor_device,
- /obj/item/radio,
- /obj/item/clothing/gloves,
- /obj/item/lazarus_injector,
- /obj/item/bikehorn/rubberducky,
- /obj/item/clothing/mask/surgical,
- /obj/item/clothing/mask/breath,
- /obj/item/clothing/mask/breath/medical,
- /obj/item/surgical_drapes,
- /obj/item/scalpel,
- /obj/item/circular_saw,
- /obj/item/bonesetter,
- /obj/item/surgicaldrill,
- /obj/item/retractor,
- /obj/item/cautery,
- /obj/item/hemostat,
- /obj/item/blood_filter,
- /obj/item/shears,
- /obj/item/geiger_counter,
- /obj/item/clothing/neck/stethoscope,
- /obj/item/stamp,
- /obj/item/clothing/glasses,
- /obj/item/wrench/medical,
- /obj/item/clothing/mask/muzzle,
- /obj/item/reagent_containers/blood,
- /obj/item/tank/internals/emergency_oxygen,
- /obj/item/gun/syringe/syndicate,
- /obj/item/implantcase,
- /obj/item/implant,
- /obj/item/implanter,
- /obj/item/pinpointer/crew,
- /obj/item/holosign_creator/medical,
- /obj/item/stack/sticky_tape,
- )
-
-/obj/item/storage/medkit/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.open_sound = 'sound/items/handling/medkit/medkit_open.ogg'
- atom_storage.open_sound_vary = TRUE
- atom_storage.rustle_sound = 'sound/items/handling/medkit/medkit_rustle.ogg'
/obj/item/storage/medkit/regular
icon_state = "medkit"
@@ -97,14 +39,14 @@
/obj/item/storage/medkit/regular/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/stack/medical/gauze = 1,
/obj/item/stack/medical/suture = 2,
/obj/item/stack/medical/mesh = 2,
/obj/item/reagent_containers/hypospray/medipen = 1,
/obj/item/healthanalyzer/simple = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/medkit/emergency
icon_state = "medbriefcase"
@@ -114,34 +56,30 @@
/obj/item/storage/medkit/emergency/PopulateContents()
if(empty)
- return
- var/static/items_inside = list(
- /obj/item/healthanalyzer/simple = 1,
- /obj/item/stack/medical/gauze = 1,
- /obj/item/stack/medical/suture/emergency = 1,
- /obj/item/stack/medical/ointment = 1,
- /obj/item/reagent_containers/hypospray/medipen/ekit = 2,
- /obj/item/storage/pill_bottle/iron = 1,
+ return NONE
+
+ return list(
+ /obj/item/healthanalyzer/simple,
+ /obj/item/stack/medical/gauze,
+ /obj/item/stack/medical/suture/emergency,
+ /obj/item/stack/medical/ointment,
+ /obj/item/reagent_containers/hypospray/medipen/ekit,
+ /obj/item/reagent_containers/hypospray/medipen/ekit,
+ /obj/item/storage/pill_bottle/iron,
)
- generate_items_inside(items_inside,src)
/obj/item/storage/medkit/surgery
name = "surgical medkit"
icon_state = "medkit_surgery"
inhand_icon_state = "medkit-surgical"
desc = "A high capacity aid kit for doctors, full of medical supplies and basic surgical equipment."
-
-/obj/item/storage/medkit/surgery/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL //holds the same equipment as a medibelt
- atom_storage.max_slots = 12
- atom_storage.max_total_storage = 24
- atom_storage.set_holdable(list_of_everything_medkits_can_hold)
+ storage_type = /datum/storage/medkit/surgery
/obj/item/storage/medkit/surgery/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/healthanalyzer = 1,
/obj/item/stack/medical/gauze/twelve = 1,
/obj/item/stack/medical/suture = 2,
@@ -151,8 +89,7 @@
/obj/item/scalpel = 1,
/obj/item/hemostat = 1,
/obj/item/cautery = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/medkit/ancient
icon_state = "oldfirstaid"
@@ -161,11 +98,12 @@
/obj/item/storage/medkit/ancient/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/stack/medical/gauze = 1,
/obj/item/stack/medical/bruise_pack = 3,
- /obj/item/stack/medical/ointment= 3)
- generate_items_inside(items_inside,src)
+ /obj/item/stack/medical/ointment= 3,
+ ))
/obj/item/storage/medkit/ancient/heirloom
desc = "A first aid kit with the ability to heal common types of injuries. You start thinking of the good old days just by looking at it."
@@ -188,12 +126,13 @@
/obj/item/storage/medkit/fire/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/reagent_containers/applicator/patch/aiuri = 3,
/obj/item/reagent_containers/spray/hercuri = 1,
/obj/item/reagent_containers/hypospray/medipen/oxandrolone = 1,
- /obj/item/reagent_containers/hypospray/medipen = 1)
- generate_items_inside(items_inside,src)
+ /obj/item/reagent_containers/hypospray/medipen = 1,
+ ))
/obj/item/storage/medkit/toxin
name = "toxin treatment kit"
@@ -213,14 +152,14 @@
/obj/item/storage/medkit/toxin/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/storage/pill_bottle/multiver/less = 1,
/obj/item/reagent_containers/syringe/syriniver = 3,
/obj/item/storage/pill_bottle/potassiodide = 1,
/obj/item/reagent_containers/hypospray/medipen/penacid = 1,
/obj/item/healthanalyzer/simple/disease = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/medkit/o2
name = "oxygen deprivation treatment kit"
@@ -239,12 +178,13 @@
/obj/item/storage/medkit/o2/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/reagent_containers/syringe/convermol = 3,
/obj/item/reagent_containers/hypospray/medipen/salbutamol = 1,
/obj/item/reagent_containers/hypospray/medipen = 1,
- /obj/item/storage/pill_bottle/iron = 1)
- generate_items_inside(items_inside,src)
+ /obj/item/storage/pill_bottle/iron = 1,
+ ))
/obj/item/storage/medkit/brute
name = "brute trauma treatment kit"
@@ -263,14 +203,14 @@
/obj/item/storage/medkit/brute/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/reagent_containers/applicator/patch/libital = 3,
/obj/item/stack/medical/gauze = 1,
/obj/item/storage/pill_bottle/probital = 1,
/obj/item/reagent_containers/hypospray/medipen/salacid = 1,
/obj/item/healthanalyzer/simple = 1,
- )
- generate_items_inside(items_inside,src)
+ ))
/obj/item/storage/medkit/advanced
name = "advanced first aid kit"
@@ -286,12 +226,13 @@
/obj/item/storage/medkit/advanced/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/reagent_containers/applicator/patch/synthflesh = 3,
/obj/item/reagent_containers/hypospray/medipen/atropine = 2,
/obj/item/stack/medical/gauze = 1,
- /obj/item/storage/pill_bottle/penacid = 1)
- generate_items_inside(items_inside,src)
+ /obj/item/storage/pill_bottle/penacid = 1,
+ ))
/obj/item/storage/medkit/tactical_lite
name = "combat first aid kit"
@@ -305,14 +246,14 @@
/obj/item/storage/medkit/tactical_lite/PopulateContents()
if(empty)
return
- var/static/list/items_inside = list(
+
+ return flatten_quantified_list(list(
/obj/item/healthanalyzer/advanced = 1,
/obj/item/reagent_containers/hypospray/medipen/atropine = 1,
/obj/item/stack/medical/gauze = 1,
/obj/item/stack/medical/suture/medicated = 2,
/obj/item/stack/medical/mesh/advanced = 2,
- )
- generate_items_inside(items_inside, src)
+ ))
/obj/item/storage/medkit/tactical
name = "combat medical kit"
@@ -320,18 +261,13 @@
icon_state = "medkit_tactical"
inhand_icon_state = "medkit-tactical"
damagetype_healed = HEAL_ALL_DAMAGE
-
-/obj/item/storage/medkit/tactical/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_slots = 21
- atom_storage.max_total_storage = 24
- atom_storage.set_holdable(list_of_everything_medkits_can_hold)
+ storage_type = /datum/storage/medkit/tatical
/obj/item/storage/medkit/tactical/PopulateContents()
if(empty)
return
- var/static/list/items_inside = list(
+
+ var/static/list/obj/item/items_inside = flatten_quantified_list(list(
/obj/item/cautery = 1,
/obj/item/scalpel = 1,
/obj/item/healthanalyzer/advanced = 1,
@@ -345,8 +281,9 @@
/obj/item/stack/medical/mesh/advanced = 2,
/obj/item/reagent_containers/applicator/patch/libital = 4,
/obj/item/reagent_containers/applicator/patch/aiuri = 4,
- )
- generate_items_inside(items_inside,src)
+ ))
+
+ return items_inside
/obj/item/storage/medkit/tactical/premium
name = "premium combat medical kit"
@@ -354,19 +291,13 @@
icon_state = "medkit_tactical_premium"
inhand_icon_state = "medkit-tactical-premium"
grind_results = list(/datum/reagent/lead = 10)
-
-/obj/item/storage/medkit/tactical/premium/Initialize(mapload)
- . = ..()
- atom_storage.allow_big_nesting = TRUE // so you can put back the box you took out
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_slots = 21
- atom_storage.max_total_storage = 34
- atom_storage.set_holdable(list_of_everything_medkits_can_hold)
+ storage_type = /datum/storage/medkit/tatical/premium
/obj/item/storage/medkit/tactical/premium/PopulateContents()
if(empty)
- return
- var/static/list/items_inside = list(
+ return NONE
+
+ var/static/list/items_inside = flatten_quantified_list(list(
/obj/item/stack/medical/suture/medicated = 2,
/obj/item/stack/medical/mesh/advanced = 2,
/obj/item/reagent_containers/applicator/patch/libital = 3,
@@ -383,9 +314,9 @@
/obj/item/storage/box/evilmeds = 1,
/obj/item/reagent_containers/medigel/sterilizine = 1,
/obj/item/clothing/glasses/hud/health/night/science = 1,
- )
- generate_items_inside(items_inside,src)
- list_of_everything_medkits_can_hold += items_inside
+ ))
+
+ return items_inside
/obj/item/storage/medkit/coroner
name = "compact coroner's medkit"
@@ -393,37 +324,20 @@
icon = 'icons/obj/storage/medkit.dmi'
icon_state = "compact_coronerkit"
inhand_icon_state = "coronerkit"
-
-/obj/item/storage/medkit/coroner/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_slots = 14
- atom_storage.max_total_storage = 24
- atom_storage.set_holdable(list(
- /obj/item/reagent_containers,
- /obj/item/bodybag,
- /obj/item/toy/crayon,
- /obj/item/pen,
- /obj/item/paper,
- /obj/item/surgical_drapes,
- /obj/item/scalpel,
- /obj/item/retractor,
- /obj/item/hemostat,
- /obj/item/cautery,
- /obj/item/autopsy_scanner,
- ))
+ storage_type = /datum/storage/medkit/coroner
/obj/item/storage/medkit/coroner/PopulateContents()
if(empty)
return
- var/static/items_inside = list(
- /obj/item/reagent_containers/cup/bottle/formaldehyde = 1,
- /obj/item/reagent_containers/medigel/sterilizine = 1,
- /obj/item/reagent_containers/blood = 1,
- /obj/item/bodybag = 2,
- /obj/item/reagent_containers/syringe = 1,
+
+ return list(
+ /obj/item/reagent_containers/cup/bottle/formaldehyde,
+ /obj/item/reagent_containers/medigel/sterilizine,
+ /obj/item/reagent_containers/blood,
+ /obj/item/bodybag,
+ /obj/item/bodybag,
+ /obj/item/reagent_containers/syringe,
)
- generate_items_inside(items_inside,src)
//medibot assembly
/obj/item/storage/medkit/tool_act(mob/living/user, obj/item/tool, list/modifiers)
@@ -446,374 +360,5 @@
/// Gets what skin (icon_state) this medkit uses for a medbot
/obj/item/storage/medkit/proc/get_medbot_skin()
+ // The skin var is nullsafe so returning nothing is A-OK
return "generic"
-
-/*
- * Pill Bottles
- */
-
-/obj/item/storage/pill_bottle
- name = "pill bottle"
- desc = "It's an airtight container for storing medication."
- icon_state = "pill_canister"
- icon = 'icons/obj/medical/chemical.dmi'
- inhand_icon_state = "contsolid"
- worn_icon_state = "nothing"
- lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
- w_class = WEIGHT_CLASS_SMALL
- pickup_sound = 'sound/items/handling/pill_bottle_pickup.ogg'
- drop_sound = 'sound/items/handling/pill_bottle_place.ogg'
-
-/obj/item/storage/pill_bottle/Initialize(mapload)
- . = ..()
- atom_storage.allow_quick_gather = TRUE
- atom_storage.set_holdable(list(
- /obj/item/reagent_containers/applicator/pill,
- /obj/item/reagent_containers/applicator/patch,
- /obj/item/food/bait/natural,
- ))
- atom_storage.open_sound = 'sound/items/handling/pill_bottle_open.ogg'
- atom_storage.open_sound_vary = FALSE
-
-/obj/item/storage/pill_bottle/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] is trying to get the cap off [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
- return TOXLOSS
-
-/obj/item/storage/pill_bottle/multiver
- name = "bottle of multiver pills"
- desc = "Contains pills used to counter toxins."
-
-/obj/item/storage/pill_bottle/multiver/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/applicator/pill/multiver(src)
-
-/obj/item/storage/pill_bottle/multiver/less
-
-/obj/item/storage/pill_bottle/multiver/less/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/applicator/pill/multiver(src)
-
-/obj/item/storage/pill_bottle/epinephrine
- name = "bottle of epinephrine pills"
- desc = "Contains pills used to stabilize patients."
-
-/obj/item/storage/pill_bottle/epinephrine/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/applicator/pill/epinephrine(src)
-
-/obj/item/storage/pill_bottle/mutadone
- name = "bottle of mutadone pills"
- desc = "Contains pills used to treat genetic abnormalities."
-
-/obj/item/storage/pill_bottle/mutadone/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/applicator/pill/mutadone(src)
-
-/obj/item/storage/pill_bottle/potassiodide
- name = "bottle of potassium iodide pills"
- desc = "Contains pills used to reduce radiation damage."
-
-/obj/item/storage/pill_bottle/potassiodide/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/applicator/pill/potassiodide(src)
-
-/obj/item/storage/pill_bottle/probital
- name = "bottle of probital pills"
- desc = "Contains pills used to treat brute damage. The tag in the bottle states 'Eat before ingesting, may cause fatigue'."
-
-/obj/item/storage/pill_bottle/probital/PopulateContents()
- for(var/i in 1 to 4)
- new /obj/item/reagent_containers/applicator/pill/probital(src)
-
-/obj/item/storage/pill_bottle/iron
- name = "bottle of iron pills"
- desc = "Contains pills used to reduce blood loss slowly. The tag in the bottle states 'Only take one each five minutes'."
-
-/obj/item/storage/pill_bottle/iron/PopulateContents()
- for(var/i in 1 to 4)
- new /obj/item/reagent_containers/applicator/pill/iron(src)
-
-/obj/item/storage/pill_bottle/mannitol
- name = "bottle of mannitol pills"
- desc = "Contains pills used to treat brain damage."
-
-/obj/item/storage/pill_bottle/mannitol/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/applicator/pill/mannitol(src)
-
-//Contains 4 pills instead of 7, and 5u pills instead of 50u (50u pills heal 250 brain damage, 5u pills heal 25)
-/obj/item/storage/pill_bottle/mannitol/braintumor
- desc = "Contains diluted pills used to treat brain tumor symptoms. Take one when feeling lightheaded."
-
-/obj/item/storage/pill_bottle/mannitol/braintumor/PopulateContents()
- for(var/i in 1 to 4)
- new /obj/item/reagent_containers/applicator/pill/mannitol/braintumor(src)
-
-/obj/item/storage/pill_bottle/stimulant
- name = "bottle of stimulant pills"
- desc = "Guaranteed to give you that extra burst of energy during a long shift!"
-
-/obj/item/storage/pill_bottle/stimulant/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/stimulant(src)
-
-/obj/item/storage/pill_bottle/sansufentanyl
- name = "bottle of experimental medication"
- desc = "A bottle of pills developed by Interdyne Pharmaceuticals. They're used to treat Hereditary Manifold Sickness."
-
-/obj/item/storage/pill_bottle/sansufentanyl/PopulateContents()
- for(var/i in 1 to 6)
- new /obj/item/reagent_containers/applicator/pill/sansufentanyl(src)
-
-/obj/item/storage/pill_bottle/mining
- name = "bottle of patches"
- desc = "Contains patches used to treat brute and burn damage."
-
-/obj/item/storage/pill_bottle/mining/PopulateContents()
- new /obj/item/reagent_containers/applicator/patch/aiuri(src)
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/applicator/patch/libital(src)
-
-/obj/item/storage/pill_bottle/zoom
- name = "suspicious pill bottle"
- desc = "The label is pretty old and almost unreadable, you recognize some chemical compounds."
-
-/obj/item/storage/pill_bottle/zoom/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/zoom(src)
-
-/obj/item/storage/pill_bottle/happy
- name = "suspicious pill bottle"
- desc = "There is a smiley on the top."
-
-/obj/item/storage/pill_bottle/happy/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/happy(src)
-
-/obj/item/storage/pill_bottle/lsd
- name = "suspicious pill bottle"
- desc = "There is a crude drawing which could be either a mushroom, or a deformed moon."
-
-/obj/item/storage/pill_bottle/lsd/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/lsd(src)
-
-/obj/item/storage/pill_bottle/aranesp
- name = "suspicious pill bottle"
- desc = "The label has 'fuck disablers' hastily scrawled in black marker."
-
-/obj/item/storage/pill_bottle/aranesp/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/aranesp(src)
-
-/obj/item/storage/pill_bottle/psicodine
- name = "bottle of psicodine pills"
- desc = "Contains pills used to treat mental distress and traumas."
-
-/obj/item/storage/pill_bottle/psicodine/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/applicator/pill/psicodine(src)
-
-/obj/item/storage/pill_bottle/penacid
- name = "bottle of pentetic acid pills"
- desc = "Contains pills to expunge radiation and toxins."
-
-/obj/item/storage/pill_bottle/penacid/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/applicator/pill/penacid(src)
-
-
-/obj/item/storage/pill_bottle/neurine
- name = "bottle of neurine pills"
- desc = "Contains pills to treat non-severe mental traumas."
-
-/obj/item/storage/pill_bottle/neurine/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/neurine(src)
-
-/obj/item/storage/pill_bottle/maintenance_pill
- name = "bottle of maintenance pills"
- desc = "An old pill bottle. It smells musty."
-
-/obj/item/storage/pill_bottle/maintenance_pill/Initialize(mapload)
- . = ..()
- var/obj/item/reagent_containers/applicator/pill/P = locate() in src
- name = "bottle of [P.name]s"
-
-/obj/item/storage/pill_bottle/maintenance_pill/PopulateContents()
- for(var/i in 1 to rand(1,7))
- new /obj/item/reagent_containers/applicator/pill/maintenance(src)
-
-/obj/item/storage/pill_bottle/maintenance_pill/full/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/applicator/pill/maintenance(src)
-
-///////////////////////////////////////// Psychologist inventory pillbottles
-/obj/item/storage/pill_bottle/happinesspsych
- name = "happiness pills"
- desc = "Contains pills used as a last resort means to temporarily stabilize depression and anxiety. WARNING: side effects may include slurred speech, drooling, and severe addiction."
-
-/obj/item/storage/pill_bottle/happinesspsych/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/happinesspsych(src)
-
-/obj/item/storage/pill_bottle/lsdpsych
- name = "mindbreaker toxin pills"
- desc = "!FOR THERAPEUTIC USE ONLY! Contains pills used to alleviate the symptoms of Reality Dissociation Syndrome."
-
-/obj/item/storage/pill_bottle/lsdpsych/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/lsdpsych(src)
-
-/obj/item/storage/pill_bottle/paxpsych
- name = "pax pills"
- desc = "Contains pills used to temporarily pacify patients that are deemed a harm to themselves or others."
-
-/obj/item/storage/pill_bottle/paxpsych/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/pill/paxpsych(src)
-
-/obj/item/storage/pill_bottle/naturalbait
- name = "freshness jar"
- desc = "Full of natural fish bait."
-
-/obj/item/storage/pill_bottle/naturalbait/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/food/bait/natural(src)
-
-/obj/item/storage/pill_bottle/ondansetron
- name = "ondansetron patches"
- desc = "A bottle containing patches of ondansetron, a drug used to treat nausea and vomiting. May cause drowsiness."
-
-/obj/item/storage/pill_bottle/ondansetron/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/applicator/patch/ondansetron(src)
-
-/// A box which takes in coolant and uses it to preserve organs and body parts
-/obj/item/storage/organbox
- name = "organ transport box"
- desc = "An advanced box with a cooling mechanism that uses cryostylane or other cold reagents to keep the organs or bodyparts inside preserved."
- icon = 'icons/obj/storage/case.dmi'
- icon_state = "organbox"
- base_icon_state = "organbox"
- lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
- throw_speed = 3
- throw_range = 7
- custom_premium_price = PAYCHECK_CREW * 4
- /// var to prevent it freezing the same things over and over
- var/cooling = FALSE
-
-/obj/item/storage/organbox/Initialize(mapload)
- . = ..()
-
- create_storage(
- storage_type = /datum/storage/organ_box,
- max_specific_storage = WEIGHT_CLASS_BULKY,
- max_total_storage = 21,
- canhold = list(
- /obj/item/organ,
- /obj/item/bodypart,
- /obj/item/food/icecream,
- ),
- )
-
- create_reagents(100, TRANSPARENT)
- START_PROCESSING(SSobj, src)
-
-/obj/item/storage/organbox/process(seconds_per_tick)
- ///if there is enough coolant var
- var/using_coolant = coolant_to_spend()
- if (isnull(using_coolant))
- if (cooling)
- cooling = FALSE
- update_appearance()
- for(var/obj/stored in contents)
- stored.unfreeze()
- return
-
- var/amount_used = 0.05 * seconds_per_tick
- if (using_coolant != /datum/reagent/cryostylane)
- amount_used *= 2
- reagents.remove_reagent(using_coolant, amount_used)
-
- if(cooling)
- return
- cooling = TRUE
- update_appearance()
- for(var/obj/stored in contents)
- stored.freeze()
-
-/// Returns which coolant we are about to use, or null if there isn't any
-/obj/item/storage/organbox/proc/coolant_to_spend()
- if (reagents.get_reagent_amount(/datum/reagent/cryostylane))
- return /datum/reagent/cryostylane
- if (reagents.get_reagent_amount(/datum/reagent/consumable/ice))
- return /datum/reagent/consumable/ice
- return null
-
-/obj/item/storage/organbox/update_icon_state()
- icon_state = "[base_icon_state][cooling ? "-working" : null]"
- return ..()
-
-/obj/item/storage/organbox/tool_act(mob/living/user, obj/item/tool, list/modifiers)
- if(is_reagent_container(tool) && tool.is_open_container())
- var/obj/item/reagent_containers/RC = tool
- var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this, transferred_by = user)
- if(units)
- balloon_alert(user, "[units]u transferred")
- return ITEM_INTERACT_SUCCESS
- return ITEM_INTERACT_BLOCKING
- if(istype(tool, /obj/item/plunger))
- balloon_alert(user, "plunging...")
- if(do_after(user, 1 SECONDS, target = src))
- balloon_alert(user, "plunged")
- reagents.clear_reagents()
- return ITEM_INTERACT_SUCCESS
- return ..()
-
-/obj/item/storage/organbox/suicide_act(mob/living/carbon/user)
- if(HAS_TRAIT(user, TRAIT_RESISTCOLD)) //if they're immune to cold, just do the box suicide
- var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)
- if(myhead)
- user.visible_message(span_suicide("[user] puts [user.p_their()] head into \the [src] and begins closing it! It looks like [user.p_theyre()] trying to commit suicide!"))
- myhead.dismember()
- myhead.forceMove(src) //force your enemies to kill themselves with your head collection box!
- playsound(user, "desecration-01.ogg", 50, TRUE, -1)
- return BRUTELOSS
- user.visible_message(span_suicide("[user] is beating [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
- return BRUTELOSS
- user.visible_message(span_suicide("[user] is putting [user.p_their()] head inside the [src], it looks like [user.p_theyre()] trying to commit suicide!"))
- user.adjust_bodytemperature(-300)
- user.apply_status_effect(/datum/status_effect/freon)
- return FIRELOSS
-
-/// A subtype of organ storage box which starts with a full coolant tank
-/obj/item/storage/organbox/preloaded
-
-/obj/item/storage/organbox/preloaded/Initialize(mapload)
- . = ..()
- reagents.add_reagent(/datum/reagent/cryostylane, reagents.maximum_volume)
-
-/obj/item/storage/test_tube_rack
- name = "test tube rack"
- desc = "A wooden rack for storing test tubes."
- icon_state = "rack"
- base_icon_state = "rack"
- icon = 'icons/obj/medical/chemical.dmi'
- inhand_icon_state = "contsolid"
- lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
- w_class = WEIGHT_CLASS_SMALL
- storage_type = /datum/storage/test_tube_rack
-
-/obj/item/storage/test_tube_rack/update_icon_state()
- icon_state = "[base_icon_state][contents.len > 0 ? contents.len : null]"
- return ..()
-
-/obj/item/storage/test_tube_rack/full/PopulateContents()
- for(var/i in 1 to atom_storage.max_slots)
- new /obj/item/reagent_containers/cup/tube(src)
- update_appearance(UPDATE_ICON_STATE)
-
diff --git a/code/game/objects/items/storage/misc.dm b/code/game/objects/items/storage/misc.dm
new file mode 100644
index 00000000000..e3fc2952c18
--- /dev/null
+++ b/code/game/objects/items/storage/misc.dm
@@ -0,0 +1,120 @@
+
+/// A box which takes in coolant and uses it to preserve organs and body parts
+/obj/item/storage/organbox
+ name = "organ transport box"
+ desc = "An advanced box with a cooling mechanism that uses cryostylane or other cold reagents to keep the organs or bodyparts inside preserved."
+ icon = 'icons/obj/storage/case.dmi'
+ icon_state = "organbox"
+ base_icon_state = "organbox"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ throw_speed = 3
+ throw_range = 7
+ custom_premium_price = PAYCHECK_CREW * 4
+ storage_type = /datum/storage/organ_box
+
+ /// var to prevent it freezing the same things over and over
+ var/cooling = FALSE
+
+/obj/item/storage/organbox/Initialize(mapload)
+ . = ..()
+
+ create_reagents(100, TRANSPARENT)
+
+ START_PROCESSING(SSobj, src)
+
+/obj/item/storage/organbox/process(seconds_per_tick)
+ ///if there is enough coolant var
+ var/using_coolant = coolant_to_spend()
+ if (isnull(using_coolant))
+ if (cooling)
+ cooling = FALSE
+ update_appearance()
+ for(var/obj/stored in contents)
+ stored.unfreeze()
+ return
+
+ var/amount_used = 0.05 * seconds_per_tick
+ if (using_coolant != /datum/reagent/cryostylane)
+ amount_used *= 2
+ reagents.remove_reagent(using_coolant, amount_used)
+
+ if(cooling)
+ return
+ cooling = TRUE
+ update_appearance()
+ for(var/obj/stored in contents)
+ stored.freeze()
+
+/// Returns which coolant we are about to use, or null if there isn't any
+/obj/item/storage/organbox/proc/coolant_to_spend()
+ if (reagents.get_reagent_amount(/datum/reagent/cryostylane))
+ return /datum/reagent/cryostylane
+ if (reagents.get_reagent_amount(/datum/reagent/consumable/ice))
+ return /datum/reagent/consumable/ice
+ return null
+
+/obj/item/storage/organbox/update_icon_state()
+ icon_state = "[base_icon_state][cooling ? "-working" : null]"
+ return ..()
+
+/obj/item/storage/organbox/tool_act(mob/living/user, obj/item/tool, list/modifiers)
+ if(is_reagent_container(tool) && tool.is_open_container())
+ var/obj/item/reagent_containers/RC = tool
+ var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this, transferred_by = user)
+ if(units)
+ balloon_alert(user, "[units]u transferred")
+ return ITEM_INTERACT_SUCCESS
+ return ITEM_INTERACT_BLOCKING
+ if(istype(tool, /obj/item/plunger))
+ balloon_alert(user, "plunging...")
+ if(do_after(user, 1 SECONDS, target = src))
+ balloon_alert(user, "plunged")
+ reagents.clear_reagents()
+ return ITEM_INTERACT_SUCCESS
+ return ..()
+
+/obj/item/storage/organbox/suicide_act(mob/living/carbon/user)
+ if(HAS_TRAIT(user, TRAIT_RESISTCOLD)) //if they're immune to cold, just do the box suicide
+ var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)
+ if(myhead)
+ user.visible_message(span_suicide("[user] puts [user.p_their()] head into \the [src] and begins closing it! It looks like [user.p_theyre()] trying to commit suicide!"))
+ myhead.dismember()
+ myhead.forceMove(src) //force your enemies to kill themselves with your head collection box!
+ playsound(user, "desecration-01.ogg", 50, TRUE, -1)
+ return BRUTELOSS
+ user.visible_message(span_suicide("[user] is beating [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
+ return BRUTELOSS
+ user.visible_message(span_suicide("[user] is putting [user.p_their()] head inside the [src], it looks like [user.p_theyre()] trying to commit suicide!"))
+ user.adjust_bodytemperature(-300)
+ user.apply_status_effect(/datum/status_effect/freon)
+ return FIRELOSS
+
+/// A subtype of organ storage box which starts with a full coolant tank
+/obj/item/storage/organbox/preloaded
+
+/obj/item/storage/organbox/preloaded/Initialize(mapload)
+ . = ..()
+ reagents.add_reagent(/datum/reagent/cryostylane, reagents.maximum_volume)
+
+/obj/item/storage/test_tube_rack
+ name = "test tube rack"
+ desc = "A wooden rack for storing test tubes."
+ icon_state = "rack"
+ base_icon_state = "rack"
+ icon = 'icons/obj/medical/chemical.dmi'
+ inhand_icon_state = "contsolid"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ w_class = WEIGHT_CLASS_SMALL
+ storage_type = /datum/storage/test_tube_rack
+
+/obj/item/storage/test_tube_rack/update_icon_state()
+ icon_state = "[base_icon_state][contents.len > 0 ? contents.len : null]"
+ return ..()
+
+/obj/item/storage/test_tube_rack/full/PopulateContents()
+ . = list()
+ for(var/i in 1 to 8)
+ . += /obj/item/reagent_containers/cup/tube
+
diff --git a/code/game/objects/items/storage/pillbottles.dm b/code/game/objects/items/storage/pillbottles.dm
new file mode 100644
index 00000000000..e1e258437a3
--- /dev/null
+++ b/code/game/objects/items/storage/pillbottles.dm
@@ -0,0 +1,274 @@
+
+/// Pill Bottles
+/obj/item/storage/pill_bottle
+ name = "pill bottle"
+ desc = "It's an airtight container for storing medication."
+ icon_state = "pill_canister"
+ icon = 'icons/obj/medical/chemical.dmi'
+ inhand_icon_state = "contsolid"
+ worn_icon_state = "nothing"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ w_class = WEIGHT_CLASS_SMALL
+ pickup_sound = 'sound/items/handling/pill_bottle_pickup.ogg'
+ drop_sound = 'sound/items/handling/pill_bottle_place.ogg'
+ storage_type = /datum/storage/pillbottle
+
+/obj/item/storage/pill_bottle/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] is trying to get the cap off [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
+ return TOXLOSS
+
+/obj/item/storage/pill_bottle/multiver
+ name = "bottle of multiver pills"
+ desc = "Contains pills used to counter toxins."
+
+/obj/item/storage/pill_bottle/multiver/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/reagent_containers/applicator/pill/multiver
+
+/obj/item/storage/pill_bottle/multiver/less
+
+/obj/item/storage/pill_bottle/multiver/less/PopulateContents()
+ . = list()
+ for(var/i in 1 to 3)
+ . += /obj/item/reagent_containers/applicator/pill/multiver
+
+/obj/item/storage/pill_bottle/epinephrine
+ name = "bottle of epinephrine pills"
+ desc = "Contains pills used to stabilize patients."
+
+/obj/item/storage/pill_bottle/epinephrine/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/reagent_containers/applicator/pill/epinephrine
+
+/obj/item/storage/pill_bottle/mutadone
+ name = "bottle of mutadone pills"
+ desc = "Contains pills used to treat genetic abnormalities."
+
+/obj/item/storage/pill_bottle/mutadone/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/reagent_containers/applicator/pill/mutadone
+
+/obj/item/storage/pill_bottle/potassiodide
+ name = "bottle of potassium iodide pills"
+ desc = "Contains pills used to reduce radiation damage."
+
+/obj/item/storage/pill_bottle/potassiodide/PopulateContents()
+ . = list()
+ for(var/i in 1 to 3)
+ . += /obj/item/reagent_containers/applicator/pill/potassiodide
+
+/obj/item/storage/pill_bottle/probital
+ name = "bottle of probital pills"
+ desc = "Contains pills used to treat brute damage. The tag in the bottle states 'Eat before ingesting, may cause fatigue'."
+
+/obj/item/storage/pill_bottle/probital/PopulateContents()
+ . = list()
+ for(var/i in 1 to 4)
+ . += /obj/item/reagent_containers/applicator/pill/probital
+
+/obj/item/storage/pill_bottle/iron
+ name = "bottle of iron pills"
+ desc = "Contains pills used to reduce blood loss slowly. The tag in the bottle states 'Only take one each five minutes'."
+
+/obj/item/storage/pill_bottle/iron/PopulateContents()
+ . = list()
+ for(var/i in 1 to 4)
+ . += /obj/item/reagent_containers/applicator/pill/iron
+
+/obj/item/storage/pill_bottle/mannitol
+ name = "bottle of mannitol pills"
+ desc = "Contains pills used to treat brain damage."
+
+/obj/item/storage/pill_bottle/mannitol/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/reagent_containers/applicator/pill/mannitol
+
+//Contains 4 pills instead of 7, and 5u pills instead of 50u (50u pills heal 250 brain damage, 5u pills heal 25)
+/obj/item/storage/pill_bottle/mannitol/braintumor
+ desc = "Contains diluted pills used to treat brain tumor symptoms. Take one when feeling lightheaded."
+
+/obj/item/storage/pill_bottle/mannitol/braintumor/PopulateContents()
+ . = list()
+ for(var/i in 1 to 4)
+ . += /obj/item/reagent_containers/applicator/pill/mannitol/braintumor
+
+/obj/item/storage/pill_bottle/stimulant
+ name = "bottle of stimulant pills"
+ desc = "Guaranteed to give you that extra burst of energy during a long shift!"
+
+/obj/item/storage/pill_bottle/stimulant/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/stimulant
+
+/obj/item/storage/pill_bottle/sansufentanyl
+ name = "bottle of experimental medication"
+ desc = "A bottle of pills developed by Interdyne Pharmaceuticals. They're used to treat Hereditary Manifold Sickness."
+
+/obj/item/storage/pill_bottle/sansufentanyl/PopulateContents()
+ . = list()
+ for(var/i in 1 to 6)
+ . += /obj/item/reagent_containers/applicator/pill/sansufentanyl
+
+/obj/item/storage/pill_bottle/mining
+ name = "bottle of patches"
+ desc = "Contains patches used to treat brute and burn damage."
+
+/obj/item/storage/pill_bottle/mining/PopulateContents()
+ return flatten_quantified_list(list(
+ /obj/item/reagent_containers/applicator/patch/aiuri = 1,
+ /obj/item/reagent_containers/applicator/patch/libital = 3,
+ ))
+
+/obj/item/storage/pill_bottle/zoom
+ name = "suspicious pill bottle"
+ desc = "The label is pretty old and almost unreadable, you recognize some chemical compounds."
+
+/obj/item/storage/pill_bottle/zoom/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/zoom
+
+/obj/item/storage/pill_bottle/happy
+ name = "suspicious pill bottle"
+ desc = "There is a smiley on the top."
+
+/obj/item/storage/pill_bottle/happy/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/happy
+
+/obj/item/storage/pill_bottle/lsd
+ name = "suspicious pill bottle"
+ desc = "There is a crude drawing which could be either a mushroom, or a deformed moon."
+
+/obj/item/storage/pill_bottle/lsd/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/lsd
+
+/obj/item/storage/pill_bottle/aranesp
+ name = "suspicious pill bottle"
+ desc = "The label has 'fuck disablers' hastily scrawled in black marker."
+
+/obj/item/storage/pill_bottle/aranesp/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/aranesp
+
+/obj/item/storage/pill_bottle/psicodine
+ name = "bottle of psicodine pills"
+ desc = "Contains pills used to treat mental distress and traumas."
+
+/obj/item/storage/pill_bottle/psicodine/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/reagent_containers/applicator/pill/psicodine
+
+/obj/item/storage/pill_bottle/penacid
+ name = "bottle of pentetic acid pills"
+ desc = "Contains pills to expunge radiation and toxins."
+
+/obj/item/storage/pill_bottle/penacid/PopulateContents()
+ . = list()
+ for(var/i in 1 to 3)
+ . += /obj/item/reagent_containers/applicator/pill/penacid
+
+
+/obj/item/storage/pill_bottle/neurine
+ name = "bottle of neurine pills"
+ desc = "Contains pills to treat non-severe mental traumas."
+
+/obj/item/storage/pill_bottle/neurine/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/neurine
+
+/obj/item/storage/pill_bottle/maintenance_pill
+ name = "bottle of maintenance pills"
+ desc = "An old pill bottle. It smells musty."
+
+/obj/item/storage/pill_bottle/maintenance_applicator/pill/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/applicator/pill/P = locate() in src
+ name = "bottle of [P.name]s"
+
+/obj/item/storage/pill_bottle/maintenance_applicator/pill/PopulateContents()
+ . = list()
+ for(var/i in 1 to rand(1,7))
+ . += /obj/item/reagent_containers/applicator/pill/maintenance
+
+/obj/item/storage/pill_bottle/maintenance_applicator/pill/full/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/reagent_containers/applicator/pill/maintenance
+
+///////////////////////////////////////// Psychologist inventory pillbottles
+/obj/item/storage/pill_bottle/happinesspsych
+ name = "happiness pills"
+ desc = "Contains pills used as a last resort means to temporarily stabilize depression and anxiety. WARNING: side effects may include slurred speech, drooling, and severe addiction."
+
+/obj/item/storage/pill_bottle/happinesspsych/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/happinesspsych
+
+/obj/item/storage/pill_bottle/lsdpsych
+ name = "mindbreaker toxin pills"
+ desc = "!FOR THERAPEUTIC USE ONLY! Contains pills used to alleviate the symptoms of Reality Dissociation Syndrome."
+
+/obj/item/storage/pill_bottle/lsdpsych/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/lsdpsych
+
+/obj/item/storage/pill_bottle/paxpsych
+ name = "pax pills"
+ desc = "Contains pills used to temporarily pacify patients that are deemed a harm to themselves or others."
+
+/obj/item/storage/pill_bottle/paxpsych/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/pill/paxpsych
+
+/obj/item/storage/pill_bottle/naturalbait
+ name = "freshness jar"
+ desc = "Full of natural fish bait."
+
+/obj/item/storage/pill_bottle/naturalbait/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/food/bait/natural
+
+/obj/item/storage/pill_bottle/ondansetron
+ name = "ondansetron patches"
+ desc = "A bottle containing patches of ondansetron, a drug used to treat nausea and vomiting. May cause drowsiness."
+
+/obj/item/storage/pill_bottle/ondansetron/PopulateContents()
+ . = list()
+ for(var/i in 1 to 5)
+ . += /obj/item/reagent_containers/applicator/patch/ondansetron
+
+/obj/item/storage/pill_bottle/maintenance_pill
+ name = "bottle of maintenance pills"
+ desc = "An old pill bottle. It smells musty."
+
+/obj/item/storage/pill_bottle/maintenance_pill/Initialize(mapload)
+ . = ..()
+ var/obj/item/reagent_containers/applicator/pill/P = locate() in src
+ name = "bottle of [P.name]s"
+
+/obj/item/storage/pill_bottle/maintenance_pill/PopulateContents()
+ . = list()
+ for(var/i in 1 to rand(1, 7))
+ . += /obj/item/reagent_containers/applicator/pill/maintenance
+
+/obj/item/storage/pill_bottle/maintenance_pill/full/PopulateContents()
+ . = list()
+ for(var/i in 1 to 7)
+ . += /obj/item/reagent_containers/applicator/pill/maintenance
diff --git a/code/game/objects/items/storage/sixpack.dm b/code/game/objects/items/storage/sixpack.dm
index f1a950f025b..2e53989dba8 100644
--- a/code/game/objects/items/storage/sixpack.dm
+++ b/code/game/objects/items/storage/sixpack.dm
@@ -8,6 +8,12 @@
righthand_file = 'icons/mob/inhands/items/drinks_righthand.dmi'
custom_materials = list(/datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT*1.2)
max_integrity = 500
+ storage_type = /datum/storage/sixcan
+
+/obj/item/storage/cans/Initialize(mapload)
+ . = ..()
+
+ update_appearance()
/obj/item/storage/cans/suicide_act(mob/living/carbon/user)
user.visible_message(span_suicide("[user] begins popping open a final cold one with the boys! It looks like [user.p_theyre()] trying to commit suicide!"))
@@ -17,34 +23,20 @@
icon_state = "[initial(icon_state)][contents.len]"
return ..()
-/obj/item/storage/cans/Initialize(mapload)
- . = ..()
- update_appearance()
-
-/obj/item/storage/cans/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.max_total_storage = 12
- atom_storage.max_slots = 6
- atom_storage.set_holdable(list(
- /obj/item/reagent_containers/cup/soda_cans,
- /obj/item/reagent_containers/cup/glass/bottle/beer,
- /obj/item/reagent_containers/cup/glass/bottle/ale,
- /obj/item/reagent_containers/cup/glass/waterbottle,
- ))
-
/obj/item/storage/cans/sixsoda
name = "soda bottle ring"
desc = "Holds six soda cans. Remember to recycle when you're done!"
/obj/item/storage/cans/sixsoda/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/reagent_containers/cup/soda_cans/cola(src)
+ . += /obj/item/reagent_containers/cup/soda_cans/cola
/obj/item/storage/cans/sixbeer
name = "beer can ring"
desc = "Holds six beers. Remember to recycle when you're done!"
/obj/item/storage/cans/sixbeer/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/reagent_containers/cup/soda_cans/beer(src)
+ . += /obj/item/reagent_containers/cup/soda_cans/beer
diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm
index 06e122780b9..2ca6c3d03a2 100644
--- a/code/game/objects/items/storage/storage.dm
+++ b/code/game/objects/items/storage/storage.dm
@@ -4,7 +4,6 @@
w_class = WEIGHT_CLASS_NORMAL
interaction_flags_click = ALLOW_RESTING|FORBID_TELEKINESIS_REACH
action_slots = ALL
- var/rummage_if_nodrop = TRUE
/// Should we preload the contents of this type?
/// BE CAREFUL, THERE'S SOME REALLY NASTY SHIT IN THIS TYPEPATH
/// SANTA IS EVIL
@@ -12,6 +11,120 @@
/// What storage type to use for this item
var/datum/storage/storage_type = /datum/storage
+/obj/item/storage/Initialize(mapload)
+ . = ..()
+
+ var/datum/storage_config/initial_cofig = GLOB.initial_storage_config
+ initial_cofig.reset()
+ var/list/obj/item/items = PopulateContents(initial_cofig)
+
+ //no hacking our way into the storages loc without going through `can_insert()` first
+ if(contents.len)
+ stack_trace("[contents.len] atoms were found inside storage before they could be inserted correctly")
+ return INITIALIZE_HINT_QDEL
+
+ //Create storage only after retriving the contents. This is done so `atom_storage` values are not modified
+ //manually which is error prone. Either create a storage subtype with your specified values or use
+ //datum/storage_config to compute these values automatically
+ create_storage(storage_type = storage_type)
+
+ //nothing to add
+ if(!items)
+ return
+ if(!islist(items))
+ items = list(items)
+ if(!items.len)
+ return
+
+ //set them to allow all items for now as we compute these values from the contents
+ var/pre_compute = FALSE
+ if(initial_cofig.compute_max_total_weight)
+ atom_storage.max_total_storage = INFINITY
+ pre_compute = TRUE
+ if(initial_cofig.compute_max_item_weight)
+ atom_storage.max_specific_storage = INFINITY
+ pre_compute = TRUE
+ if(initial_cofig.compute_max_item_count)
+ atom_storage.max_slots = items.len
+ pre_compute = TRUE
+ if(initial_cofig.contents_are_exceptions)
+ atom_storage.exception_hold = null
+ if(initial_cofig.whitelist_content_types)
+ atom_storage.can_hold = null
+
+ var/max_total_weight = 0
+ var/max_item_weight = 0
+ var/list/obj/item/type_paths = initial_cofig.contents_are_exceptions || initial_cofig.whitelist_content_types ? list() : null
+ pre_compute |= !isnull(type_paths)
+
+ //we now begin inserting these items the right way
+ for(var/obj/item/insert as anything in items)
+ if(ispath(insert))
+ insert = new insert(null)
+
+ //computing values from contents
+ if(pre_compute)
+ if(initial_cofig.compute_max_total_weight)
+ max_total_weight += insert.w_class
+ if(initial_cofig.compute_max_item_weight)
+ max_item_weight = insert.w_class > max_item_weight ? insert.w_class : max_item_weight
+ if(type_paths)
+ type_paths |= insert.type
+
+ if(!atom_storage.can_insert(insert, messages = STORAGE_ERROR_INSERT))
+ . = INITIALIZE_HINT_QDEL //this thing was shoved inside & destroyed us. Fix your storage caps and try again
+ insert.forceMove(src)
+
+ if(!pre_compute || . == INITIALIZE_HINT_QDEL)
+ return
+
+ //assign computed values
+ if(max_total_weight)
+ atom_storage.max_total_storage = max_total_weight
+ if(max_item_weight)
+ atom_storage.max_specific_storage = max_item_weight
+ if(type_paths)
+ atom_storage.set_holdable(
+ can_hold_list = initial_cofig.whitelist_content_types ? type_paths : atom_storage.can_hold,
+ exception_hold_list = initial_cofig.contents_are_exceptions ? type_paths : atom_storage.exception_hold
+ )
+
+/obj/item/storage/create_storage(
+ max_slots,
+ max_specific_storage,
+ max_total_storage,
+ list/canhold,
+ list/canthold,
+ storage_type,
+)
+ if(!QDELETED(atom_storage))
+ stack_trace("Cannot re initialize storage")
+ return
+
+ // If no type was passed in, default to what we already have
+ storage_type ||= src.storage_type
+ return ..()
+
+/obj/item/storage/atom_deconstruct(disassembled)
+ var/atom/drop_point = drop_location()
+ for(var/obj/important_thing in contents)
+ if(important_thing.resistance_flags & INDESTRUCTIBLE)
+ important_thing.forceMove(drop_point)
+
+/**
+ * Returns a list of items(object typepaths or solid atoms) to be inserted into the storage
+ * If you list contains solid atoms make sure they are created/moved in nullspace i.e. no bypassing storage
+ * restrictions else this storage will self destruct with a stack trace
+ * Arguments
+ *
+ * * datum/storage_config/config - the config used to set storage values based on the contents returned here
+ */
+/obj/item/storage/proc/PopulateContents(datum/storage_config/config)
+ RETURN_TYPE(/list/obj/item)
+ PROTECTED_PROC(TRUE)
+
+ return NONE
+
/obj/item/storage/apply_fantasy_bonuses(bonus)
. = ..()
if(isnull(atom_storage)) // some abstract types of storage (yes i know) don't get a datum
@@ -41,29 +154,6 @@
atom_storage.max_specific_storage = previous_max_storage
return ..()
-/obj/item/storage/Initialize(mapload)
- . = ..()
-
- create_storage(storage_type = storage_type)
-
- PopulateContents()
-
- for (var/obj/item/item in src)
- item.item_flags |= IN_STORAGE
-
-/obj/item/storage/create_storage(
- max_slots,
- max_specific_storage,
- max_total_storage,
- list/canhold,
- list/canthold,
- storage_type,
-)
- // If no type was passed in, default to what we already have
- storage_type ||= src.storage_type
- return ..()
-
-
/obj/item/storage/AllowDrop()
return FALSE
@@ -77,31 +167,17 @@
SSexplosions.low_mov_atom += contents
/obj/item/storage/canStrip(mob/who)
- . = ..()
- if(!. && rummage_if_nodrop)
- return TRUE
+ return TRUE
/obj/item/storage/doStrip(mob/who)
- if(HAS_TRAIT(src, TRAIT_NODROP) && rummage_if_nodrop)
+ if(HAS_TRAIT(src, TRAIT_NODROP))
atom_storage.remove_all()
return TRUE
return ..()
-/obj/item/storage/contents_explosion(severity, target)
-//Cyberboss says: "USE THIS TO FILL IT, NOT INITIALIZE OR NEW"
-
-/obj/item/storage/proc/PopulateContents()
-
/obj/item/storage/proc/emptyStorage()
atom_storage.remove_all()
-/obj/item/storage/Destroy()
- for(var/obj/important_thing in contents)
- if(!(important_thing.resistance_flags & INDESTRUCTIBLE))
- continue
- important_thing.forceMove(drop_location())
- return ..()
-
/// Returns a list of object types to be preloaded by our code
/// I'll say it again, be very careful with this. We only need it for a few things
/// Don't do anything stupid, please
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
deleted file mode 100644
index 010da30b124..00000000000
--- a/code/game/objects/items/storage/toolbox.dm
+++ /dev/null
@@ -1,700 +0,0 @@
-/obj/item/storage/toolbox
- name = "toolbox"
- desc = "Danger. Very robust."
- icon = 'icons/obj/storage/toolbox.dmi'
- icon_state = "toolbox_default"
- inhand_icon_state = "toolbox_default"
- lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
- obj_flags = CONDUCTS_ELECTRICITY
- force = 13
- throwforce = 13
- throw_speed = 2
- throw_range = 7
- demolition_mod = 1.25
- w_class = WEIGHT_CLASS_BULKY
- custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT*5)
- attack_verb_continuous = list("robusts")
- attack_verb_simple = list("robust")
- hitsound = 'sound/items/weapons/smash.ogg'
- drop_sound = 'sound/items/handling/toolbox/toolbox_drop.ogg'
- pickup_sound = 'sound/items/handling/toolbox/toolbox_pickup.ogg'
- material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
- var/latches = "single_latch"
- var/has_latches = TRUE
- wound_bonus = 5
- /// How many interactions are we currently performing
- var/current_interactions = 0
- /// Items we should not interact with when left clicking
- var/static/list/lmb_exception_typecache = typecacheof(list(
- /obj/structure/table,
- /obj/structure/rack,
- /obj/structure/closet,
- /obj/machinery/disposal,
- ))
-
-/obj/item/storage/toolbox/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- if(has_latches)
- if(prob(10))
- latches = "double_latch"
- if(prob(1))
- latches = "triple_latch"
- if(prob(0.1))
- latches = "quad_latch" // like winning the lottery, but worse
- update_appearance()
- atom_storage.open_sound = 'sound/items/handling/toolbox/toolbox_open.ogg'
- atom_storage.rustle_sound = 'sound/items/handling/toolbox/toolbox_rustle.ogg'
- AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound)
-
-/obj/item/storage/toolbox/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
- if (user.combat_mode || !user.has_hand_for_held_index(user.get_inactive_hand_index()))
- return NONE
-
- if (is_type_in_typecache(interacting_with, lmb_exception_typecache) && !LAZYACCESS(modifiers, RIGHT_CLICK))
- return NONE
-
- if (current_interactions)
- var/obj/item/other_tool = user.get_inactive_held_item()
- if (!istype(other_tool)) // what even
- return NONE
- INVOKE_ASYNC(src, PROC_REF(use_tool_on), interacting_with, user, modifiers, other_tool)
- return ITEM_INTERACT_SUCCESS
-
- if (user.get_inactive_held_item())
- user.balloon_alert(user, "hands busy!")
- return ITEM_INTERACT_BLOCKING
-
- var/list/item_radial = list()
- for (var/obj/item/tool in atom_storage.real_location)
- if(is_type_in_list(tool, GLOB.tool_items))
- item_radial[tool] = tool.appearance
-
- if (!length(item_radial))
- return NONE
-
- playsound(user, 'sound/items/handling/toolbox/toolbox_open.ogg', 50)
- var/obj/item/picked_item = show_radial_menu(user, interacting_with, item_radial, require_near = TRUE)
- if (!picked_item)
- return ITEM_INTERACT_BLOCKING
-
- playsound(user, 'sound/items/handling/toolbox/toolbox_rustle.ogg', 50)
- if (!user.put_in_inactive_hand(picked_item))
- return ITEM_INTERACT_BLOCKING
-
- atom_storage.animate_parent()
- if (istype(picked_item, /obj/item/weldingtool))
- var/obj/item/weldingtool/welder = picked_item
- if (!welder.welding)
- welder.attack_self(user)
-
- if (istype(picked_item, /obj/item/spess_knife))
- picked_item.attack_self(user)
-
- INVOKE_ASYNC(src, PROC_REF(use_tool_on), interacting_with, user, modifiers, picked_item)
- return ITEM_INTERACT_SUCCESS
-
-/obj/item/storage/toolbox/proc/use_tool_on(atom/interacting_with, mob/living/user, list/modifiers, obj/item/picked_tool)
- current_interactions += 1
- picked_tool.melee_attack_chain(user, interacting_with, list2params(modifiers))
- current_interactions -= 1
-
- if (QDELETED(picked_tool) || picked_tool.loc != user || !user.CanReach(picked_tool))
- current_interactions = 0
- return
-
- if (current_interactions)
- return
-
- if (istype(picked_tool, /obj/item/weldingtool))
- var/obj/item/weldingtool/welder = picked_tool
- if (welder.welding)
- welder.attack_self(user)
-
- atom_storage.attempt_insert(picked_tool, user)
-
-/obj/item/storage/toolbox/update_overlays()
- . = ..()
- if(has_latches)
- . += latches
-
-/obj/item/storage/toolbox/suicide_act(mob/living/user)
- user.visible_message(span_suicide("[user] robusts [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
- return BRUTELOSS
-
-/obj/item/storage/toolbox/emergency
- name = "emergency toolbox"
- icon_state = "red"
- inhand_icon_state = "toolbox_red"
- material_flags = NONE
- throw_speed = 3 // red ones go faster
-
-/obj/item/storage/toolbox/emergency/PopulateContents()
- new /obj/item/crowbar/red(src)
- new /obj/item/weldingtool/mini(src)
- new /obj/item/extinguisher/mini(src)
- switch(rand(1,3))
- if(1)
- new /obj/item/flashlight(src)
- if(2)
- new /obj/item/flashlight/glowstick(src)
- if(3)
- new /obj/item/flashlight/flare(src)
- new /obj/item/radio/off(src)
-
-/obj/item/storage/toolbox/emergency/old
- name = "rusty red toolbox"
- icon_state = "toolbox_red_old"
- has_latches = FALSE
- material_flags = NONE
-
-/obj/item/storage/toolbox/mechanical
- name = "mechanical toolbox"
- icon_state = "blue"
- inhand_icon_state = "toolbox_blue"
- material_flags = NONE
- /// If FALSE, someone with a ensouled soulstone can sacrifice a spirit to change the sprite of this toolbox.
- var/has_soul = FALSE
-
-/obj/item/storage/toolbox/mechanical/PopulateContents()
- new /obj/item/screwdriver(src)
- new /obj/item/wrench(src)
- new /obj/item/weldingtool(src)
- new /obj/item/crowbar(src)
- new /obj/item/analyzer(src)
- new /obj/item/wirecutters(src)
-
-/obj/item/storage/toolbox/mechanical/old
- name = "rusty blue toolbox"
- icon_state = "toolbox_blue_old"
- has_latches = FALSE
- has_soul = TRUE
-
-/obj/item/storage/toolbox/mechanical/old/heirloom
- name = "toolbox" //this will be named "X family toolbox"
- desc = "It's seen better days."
- force = 5
- w_class = WEIGHT_CLASS_NORMAL
-
-/obj/item/storage/toolbox/mechanical/old/heirloom/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
-
-/obj/item/storage/toolbox/mechanical/old/heirloom/PopulateContents()
- return
-
-// version of below that isn't a traitor item
-/obj/item/storage/toolbox/mechanical/old/cleaner
- name = "old blue toolbox"
- icon_state = "oldtoolboxclean"
- icon_state = "toolbox_blue_old"
-
-/obj/item/storage/toolbox/mechanical/old/clean // the assistant traitor toolbox, damage scales with TC inside
- name = "toolbox"
- desc = "An old, blue toolbox, it looks robust."
- icon_state = "oldtoolboxclean"
- inhand_icon_state = "toolbox_blue"
- has_latches = FALSE
- force = 19
- throwforce = 22
-
-/obj/item/storage/toolbox/mechanical/old/clean/proc/calc_damage()
- var/power = 0
- for (var/obj/item/stack/telecrystal/stored_crystals in get_all_contents())
- power += (stored_crystals.amount / 2)
- force = initial(force) + power
- throwforce = initial(throwforce) + power
-
-/obj/item/storage/toolbox/mechanical/old/clean/attack(mob/target, mob/living/user)
- calc_damage()
- ..()
-
-/obj/item/storage/toolbox/mechanical/old/clean/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
- calc_damage()
- ..()
-
-/obj/item/storage/toolbox/mechanical/old/clean/PopulateContents()
- new /obj/item/screwdriver(src)
- new /obj/item/wrench(src)
- new /obj/item/weldingtool(src)
- new /obj/item/crowbar(src)
- new /obj/item/wirecutters(src)
- new /obj/item/multitool(src)
- new /obj/item/clothing/gloves/color/yellow(src)
-
-/obj/item/storage/toolbox/electrical
- name = "electrical toolbox"
- icon_state = "yellow"
- inhand_icon_state = "toolbox_yellow"
- material_flags = NONE
-
-/obj/item/storage/toolbox/electrical/PopulateContents()
- var/pickedcolor = pick(GLOB.cable_colors)
- new /obj/item/screwdriver(src)
- new /obj/item/wirecutters(src)
- new /obj/item/t_scanner(src)
- new /obj/item/crowbar(src)
- var/obj/item/stack/cable_coil/new_cable_one = new(src, MAXCOIL)
- new_cable_one.set_cable_color(pickedcolor)
- var/obj/item/stack/cable_coil/new_cable_two = new(src, MAXCOIL)
- new_cable_two.set_cable_color(pickedcolor)
- if(prob(5))
- new /obj/item/clothing/gloves/color/yellow(src)
- else
- var/obj/item/stack/cable_coil/new_cable_three = new(src, MAXCOIL)
- new_cable_three.set_cable_color(pickedcolor)
-
-/obj/item/storage/toolbox/syndicate
- name = "suspicious looking toolbox"
- icon_state = "syndicate"
- inhand_icon_state = "toolbox_syndi"
- force = 15
- throwforce = 18
- material_flags = NONE
-
-/obj/item/storage/toolbox/syndicate/Initialize(mapload)
- . = ..()
- atom_storage.silent = TRUE
-
-/obj/item/storage/toolbox/syndicate/PopulateContents()
- new /obj/item/screwdriver/nuke(src)
- new /obj/item/wrench(src)
- new /obj/item/weldingtool/largetank(src)
- new /obj/item/crowbar/red(src)
- new /obj/item/wirecutters(src, "red")
- new /obj/item/multitool(src)
- new /obj/item/clothing/gloves/combat(src)
-
-/obj/item/storage/toolbox/drone
- name = "mechanical toolbox"
- icon_state = "blue"
- inhand_icon_state = "toolbox_blue"
- material_flags = NONE
-
-/obj/item/storage/toolbox/drone/PopulateContents()
- var/pickedcolor = pick("red","yellow","green","blue","pink","orange","cyan","white")
- new /obj/item/screwdriver(src)
- new /obj/item/wrench(src)
- new /obj/item/weldingtool(src)
- new /obj/item/crowbar(src)
- new /obj/item/stack/cable_coil(src,MAXCOIL,pickedcolor)
- new /obj/item/wirecutters(src)
- new /obj/item/multitool(src)
-
-/obj/item/storage/toolbox/artistic
- name = "artistic toolbox"
- desc = "A toolbox painted bright green. Why anyone would store art supplies in a toolbox is beyond you, but it has plenty of extra space."
- icon_state = "green"
- inhand_icon_state = "artistic_toolbox"
- w_class = WEIGHT_CLASS_GIGANTIC //Holds more than a regular toolbox!
- material_flags = NONE
-
-/obj/item/storage/toolbox/artistic/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 20
- atom_storage.max_slots = 11
-
-/obj/item/storage/toolbox/artistic/PopulateContents()
- new /obj/item/storage/crayons(src)
- new /obj/item/crowbar(src)
- new /obj/item/stack/pipe_cleaner_coil/red(src)
- new /obj/item/stack/pipe_cleaner_coil/yellow(src)
- new /obj/item/stack/pipe_cleaner_coil/blue(src)
- new /obj/item/stack/pipe_cleaner_coil/green(src)
- new /obj/item/stack/pipe_cleaner_coil/pink(src)
- new /obj/item/stack/pipe_cleaner_coil/orange(src)
- new /obj/item/stack/pipe_cleaner_coil/cyan(src)
- new /obj/item/stack/pipe_cleaner_coil/white(src)
- new /obj/item/stack/pipe_cleaner_coil/brown(src)
-
-/obj/item/storage/toolbox/medical
- name = "medical toolbox"
- desc = "A toolbox painted soft white and light blue. This is getting ridiculous."
- icon_state = "medical"
- inhand_icon_state = "toolbox_medical"
- attack_verb_continuous = list("treats", "surgeries", "tends", "tends wounds on")
- attack_verb_simple = list("treat", "surgery", "tend", "tend wounds on")
- w_class = WEIGHT_CLASS_BULKY
- material_flags = NONE
- force = 5 // its for healing
- wound_bonus = 25 // wounds are medical right?
- /// Tray we steal the og contents from.
- var/obj/item/surgery_tray/tray_type = /obj/item/surgery_tray
-
-/obj/item/storage/toolbox/medical/Initialize(mapload)
- . = ..()
- // what do any of these numbers fucking mean
- atom_storage.max_total_storage = 20
- atom_storage.max_slots = 11
-
-/obj/item/storage/toolbox/medical/PopulateContents()
- var/atom/fake_tray = new tray_type(get_turf(src)) // not in src lest it fill storage that we need for its tools later
- for(var/atom/movable/thingy in fake_tray)
- thingy.forceMove(src)
- qdel(fake_tray)
-
-/obj/item/storage/toolbox/medical/full
- tray_type = /obj/item/surgery_tray/full
-
-/obj/item/storage/toolbox/medical/coroner
- name = "coroner toolbox"
- desc = "A toolbox painted soft white and dark grey. This is getting beyond ridiculous."
- icon_state = "coroner"
- inhand_icon_state = "toolbox_coroner"
- attack_verb_continuous = list("dissects", "autopsies", "corones")
- attack_verb_simple = list("dissect", "autopsy", "corone")
- w_class = WEIGHT_CLASS_BULKY
- material_flags = NONE
- force = 17 // it's not for healing
- tray_type = /obj/item/surgery_tray/full/morgue
-
-/obj/item/storage/toolbox/medical/coroner/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/bane, mob_biotypes = MOB_UNDEAD, damage_multiplier = 1) //Just in case one of the tennants get uppity
-
-/obj/item/storage/toolbox/ammobox
- name = "ammo canister"
- desc = "A metal canister designed to hold ammunition"
- icon_state = "ammobox"
- inhand_icon_state = "ammobox"
- lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
- has_latches = FALSE
- drop_sound = 'sound/items/handling/ammobox_drop.ogg'
- pickup_sound = 'sound/items/handling/ammobox_pickup.ogg'
- var/ammo_to_spawn
-
-/obj/item/storage/toolbox/ammobox/PopulateContents()
- if(!isnull(ammo_to_spawn))
- for(var/i in 1 to 6)
- new ammo_to_spawn(src)
-
-/obj/item/storage/toolbox/ammobox/strilka310
- name = ".310 Strilka ammo box (Surplus?)"
- desc = "It contains a few clips. Goddamn, this thing smells awful. \
- Has this been sitting in a warehouse for the last several centuries?"
- ammo_to_spawn = /obj/item/ammo_box/strilka310
-
-/obj/item/storage/toolbox/ammobox/strilka310/surplus
- ammo_to_spawn = /obj/item/ammo_box/strilka310/surplus
-
-/obj/item/storage/toolbox/ammobox/wt550m9
- name = "4.6x30mm ammo box"
- ammo_to_spawn = /obj/item/ammo_box/magazine/wt550m9
-
-/obj/item/storage/toolbox/ammobox/wt550m9ap
- name = "4.6x30mm AP ammo box"
- ammo_to_spawn = /obj/item/ammo_box/magazine/wt550m9/wtap
-
-//repairbot assembly
-/obj/item/storage/toolbox/tool_act(mob/living/user, obj/item/tool, list/modifiers)
- if(!istype(tool, /obj/item/assembly/prox_sensor))
- return ..()
- var/static/list/allowed_toolbox = list(
- /obj/item/storage/toolbox/artistic,
- /obj/item/storage/toolbox/electrical,
- /obj/item/storage/toolbox/emergency,
- /obj/item/storage/toolbox/mechanical,
- /obj/item/storage/toolbox/syndicate,
- )
-
- if(!is_type_in_list(src, allowed_toolbox) && (type != /obj/item/storage/toolbox))
- return ITEM_INTERACT_BLOCKING
- if(contents.len >= 1)
- balloon_alert(user, "not empty!")
- return ITEM_INTERACT_BLOCKING
- var/static/list/toolbox_colors = list(
- /obj/item/storage/toolbox = "#445eb3",
- /obj/item/storage/toolbox/emergency = "#445eb3",
- /obj/item/storage/toolbox/electrical = "#b77931",
- /obj/item/storage/toolbox/artistic = "#378752",
- /obj/item/storage/toolbox/syndicate = "#3d3d3d",
- )
- var/obj/item/bot_assembly/repairbot/repair = new
- repair.toolbox = type
- var/new_color = toolbox_colors[type] || "#445eb3"
- repair.set_color(new_color)
- user.put_in_hands(repair)
- repair.update_appearance()
- repair.balloon_alert(user, "sensor added!")
- qdel(tool)
- qdel(src)
- return ITEM_INTERACT_SUCCESS
-
-/obj/item/storage/toolbox/haunted
- name = "old toolbox"
- custom_materials = list(/datum/material/hauntium = SMALL_MATERIAL_AMOUNT*5)
-
-/obj/item/storage/toolbox/guncase
- name = "gun case"
- desc = "A weapon's case. Has a blood-red 'S' stamped on the cover."
- icon = 'icons/obj/storage/case.dmi'
- icon_state = "infiltrator_case"
- lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
- inhand_icon_state = "infiltrator_case"
- has_latches = FALSE
- var/weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol
- var/extra_to_spawn = /obj/item/ammo_box/magazine/m9mm
-
-/obj/item/storage/toolbox/guncase/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
- atom_storage.max_total_storage = 7 //enough to hold ONE bulky gun and the ammo boxes
- atom_storage.max_slots = 4
-
-/obj/item/storage/toolbox/guncase/PopulateContents()
- new weapon_to_spawn (src)
- for(var/i in 1 to 3)
- new extra_to_spawn (src)
-
-/obj/item/storage/toolbox/guncase/traitor
- name = "makarov gun case"
- desc = "A weapon's case. Has a blood-red 'S' stamped on the cover. There seems to be a strange switch along the side inside a plastic flap."
- icon_state = "pistol_case"
- base_icon_state = "pistol_case"
- // What ammo box do we spawn in our case?
- var/ammo_box_to_spawn = /obj/item/ammo_box/c9mm
- // Timer for the bomb in the case.
- var/explosion_timer
- // Whether or not our case is exploding. Used for determining sprite changes.
- var/currently_exploding = FALSE
-
-/obj/item/storage/toolbox/guncase/traitor/Initialize(mapload)
- . = ..()
- register_context()
-
-/obj/item/storage/toolbox/guncase/traitor/examine(mob/user)
- . = ..()
- . += span_notice("Activate the Evidence Disposal Explosive using Alt-Right-Click.")
-
-/obj/item/storage/toolbox/guncase/traitor/add_context(atom/source, list/context, obj/item/held_item, mob/user)
- . = ..()
-
- context[SCREENTIP_CONTEXT_ALT_RMB] = "Activate Evidence Disposal Explosive"
- return CONTEXTUAL_SCREENTIP_SET
-
-/obj/item/storage/toolbox/guncase/traitor/PopulateContents()
- new weapon_to_spawn (src)
- for(var/i in 1 to 2)
- new extra_to_spawn (src)
- new ammo_box_to_spawn(src)
-
-/obj/item/storage/toolbox/guncase/traitor/update_icon_state()
- . = ..()
- if(currently_exploding)
- icon_state = "[base_icon_state]_exploding"
- else
- icon_state = "[base_icon_state]"
-
-/obj/item/storage/toolbox/guncase/traitor/click_alt_secondary(mob/user)
- . = ..()
- if(currently_exploding)
- user.balloon_alert(user, "already exploding!")
- return
-
- var/i_dont_even_think_once_about_blowing_stuff_up = tgui_alert(user, "Would you like to activate the evidence disposal bomb now?", "BYE BYE", list("Yes","No"))
-
- if(i_dont_even_think_once_about_blowing_stuff_up != "Yes" || currently_exploding || QDELETED(user) || QDELETED(src) || user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS|ALLOW_RESTING))
- return
-
- explosion_timer = addtimer(CALLBACK(src, PROC_REF(think_fast_chucklenuts)), 5 SECONDS, (TIMER_UNIQUE|TIMER_OVERRIDE))
- to_chat(user, span_warning("You prime [src]'s evidence disposal bomb!"))
- log_bomber(user, "has activated a", src, "for detonation")
- playsound(src, 'sound/items/weapons/armbomb.ogg', 50, TRUE)
- currently_exploding = TRUE
- update_appearance()
-
-/// proc to handle our detonation
-/obj/item/storage/toolbox/guncase/traitor/proc/think_fast_chucklenuts()
- explosion(src, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 2, explosion_cause = src)
- qdel(src)
-
-/obj/item/storage/toolbox/guncase/traitor/ammunition
- name = "makarov 9mm magazine case"
- weapon_to_spawn = /obj/item/ammo_box/magazine/m9mm
-
-/obj/item/storage/toolbox/guncase/traitor/donksoft
- name = "\improper Donksoft riot pistol gun case"
- weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol/toy/riot/clandestine
- extra_to_spawn = /obj/item/ammo_box/magazine/toy/pistol/riot
- ammo_box_to_spawn = /obj/item/ammo_box/foambox/riot
-
-/obj/item/storage/toolbox/guncase/traitor/ammunition/donksoft
- name = "\improper Donksoft riot pistol magazine case"
- weapon_to_spawn = /obj/item/ammo_box/magazine/toy/pistol/riot
- extra_to_spawn = /obj/item/ammo_box/magazine/toy/pistol/riot
- ammo_box_to_spawn = /obj/item/ammo_box/foambox/riot
-
-/obj/item/storage/toolbox/guncase/bulldog
- name = "bulldog gun case"
- weapon_to_spawn = /obj/item/gun/ballistic/shotgun/bulldog
- extra_to_spawn = /obj/item/ammo_box/magazine/m12g
-
-/obj/item/storage/toolbox/guncase/c20r
- name = "c-20r gun case"
- weapon_to_spawn = /obj/item/gun/ballistic/automatic/c20r
- extra_to_spawn = /obj/item/ammo_box/magazine/smgm45
-
-/obj/item/storage/toolbox/guncase/smartgun
- name = "adielle smartgun case"
- weapon_to_spawn = /obj/item/gun/ballistic/automatic/smartgun
- extra_to_spawn = /obj/item/ammo_box/magazine/smartgun
-
-/obj/item/storage/toolbox/guncase/clandestine
- name = "clandestine gun case"
- weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol/clandestine
- extra_to_spawn = /obj/item/ammo_box/magazine/m10mm
-
-/obj/item/storage/toolbox/guncase/m90gl
- name = "m-90gl gun case"
- weapon_to_spawn = /obj/item/gun/ballistic/automatic/m90
- extra_to_spawn = /obj/item/ammo_box/magazine/m223
-
-/obj/item/storage/toolbox/guncase/m90gl/PopulateContents()
- new weapon_to_spawn (src)
- for(var/i in 1 to 2)
- new extra_to_spawn (src)
- new /obj/item/ammo_box/a40mm/rubber (src)
-
-/obj/item/storage/toolbox/guncase/rocketlauncher
- name = "rocket launcher gun case"
- weapon_to_spawn = /obj/item/gun/ballistic/rocketlauncher
- extra_to_spawn = /obj/item/ammo_box/rocket
-
-/obj/item/storage/toolbox/guncase/rocketlauncher/PopulateContents()
- new weapon_to_spawn (src)
- new extra_to_spawn (src)
-
-/obj/item/storage/toolbox/guncase/revolver
- name = "revolver gun case"
- weapon_to_spawn = /obj/item/gun/ballistic/revolver/badass/nuclear
- extra_to_spawn = /obj/item/ammo_box/a357
-
-/obj/item/storage/toolbox/guncase/sword_and_board
- name = "energy sword and shield weapon case"
- weapon_to_spawn = /obj/item/melee/energy/sword
- extra_to_spawn = /obj/item/shield/energy
-
-/obj/item/storage/toolbox/guncase/sword_and_board/PopulateContents()
- new weapon_to_spawn (src)
- new extra_to_spawn (src)
- new /obj/item/clothing/head/costume/knight (src)
-
-/obj/item/storage/toolbox/guncase/cqc
- name = "\improper CQC equipment case"
- weapon_to_spawn = /obj/item/book/granter/martial/cqc
- extra_to_spawn = /obj/item/storage/box/syndie_kit/imp_stealth
-
-/obj/item/storage/toolbox/guncase/cqc/PopulateContents()
- new weapon_to_spawn (src)
- new extra_to_spawn (src)
- new /obj/item/clothing/head/costume/snakeeater (src)
- new /obj/item/storage/fancy/cigarettes/cigpack_syndicate (src)
-
-/obj/item/clothing/head/costume/snakeeater
- name = "strange bandana"
- desc = "A bandana. It seems to have a little carp embroidered on the inside, as well as the kanji '魚'."
- icon_state = "snake_eater"
- inhand_icon_state = null
- clothing_traits = list(TRAIT_FISH_EATER)
-
-/obj/item/clothing/head/costume/knight
- name = "fake medieval helmet"
- desc = "A classic metal helmet. Though, this one seems to be very obviously fake..."
- icon = 'icons/obj/clothing/head/helmet.dmi'
- worn_icon = 'icons/mob/clothing/head/helmet.dmi'
- icon_state = "knight_green"
- inhand_icon_state = "knight_helmet"
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT
- flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
- dog_fashion = null
-
-/obj/item/storage/toolbox/guncase/doublesword
- name = "double-bladed energy sword weapon case"
- weapon_to_spawn = /obj/item/dualsaber
- extra_to_spawn = /obj/item/soap/syndie
-
-/obj/item/storage/toolbox/guncase/doublesword/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY
- atom_storage.max_total_storage = 10 //it'll hold enough
- atom_storage.max_slots = 5
-
-/obj/item/storage/toolbox/guncase/doublesword/PopulateContents()
- new weapon_to_spawn (src)
- new extra_to_spawn (src)
- new /obj/item/mod/module/noslip (src)
- new /obj/item/reagent_containers/hypospray/medipen/methamphetamine (src)
- new /obj/item/clothing/under/rank/prisoner/nosensor (src)
-
-/obj/item/storage/toolbox/guncase/soviet
- name = "ancient gun case"
- desc = "A weapon's case. Has the symbol of the Third Soviet Union stamped on the side."
- icon_state = "sakhno_case"
- inhand_icon_state = "sakhno_case"
- weapon_to_spawn = /obj/effect/spawner/random/sakhno
- extra_to_spawn = /obj/effect/spawner/random/sakhno/ammo
-
-/obj/item/storage/toolbox/guncase/monkeycase
- name = "monkey gun case"
- desc = "Everything a monkey needs to truly go ape-shit. There's a paw-shaped hand scanner lock on the front of the case."
-
-/obj/item/storage/toolbox/guncase/monkeycase/Initialize(mapload)
- . = ..()
- atom_storage.locked = STORAGE_SOFT_LOCKED
-
-/obj/item/storage/toolbox/guncase/monkeycase/attack_self(mob/user, modifiers)
- if(!monkey_check(user))
- return
- return ..()
-
-/obj/item/storage/toolbox/guncase/monkeycase/attack_self_secondary(mob/user, modifiers)
- attack_self(user, modifiers)
- return
-
-/obj/item/storage/toolbox/guncase/monkeycase/attack_hand(mob/user, list/modifiers)
- if(!monkey_check(user))
- return
- return ..()
-
-/obj/item/storage/toolbox/guncase/monkeycase/proc/monkey_check(mob/user)
- if(atom_storage.locked == STORAGE_NOT_LOCKED)
- return TRUE
-
- if(is_simian(user))
- atom_storage.locked = STORAGE_NOT_LOCKED
- to_chat(user, span_notice("You place your paw on the paw scanner, and hear a soft click as [src] unlocks!"))
- playsound(src, 'sound/items/click.ogg', 25, TRUE)
- return TRUE
- to_chat(user, span_warning("You put your hand on the hand scanner, and it rejects it with an angry chimpanzee screech!"))
- playsound(src, SFX_SCREECH, 75, TRUE)
- return FALSE
-
-/obj/item/storage/toolbox/guncase/monkeycase/PopulateContents()
- switch(rand(1, 3))
- if(1)
- // Uzi with a boxcutter.
- new /obj/item/gun/ballistic/automatic/mini_uzi/chimpgun(src)
- new /obj/item/ammo_box/magazine/uzim9mm(src)
- new /obj/item/ammo_box/magazine/uzim9mm(src)
- new /obj/item/boxcutter/extended(src)
- if(2)
- // Thompson with a boxcutter.
- new /obj/item/gun/ballistic/automatic/tommygun/chimpgun(src)
- new /obj/item/ammo_box/magazine/tommygunm45(src)
- new /obj/item/ammo_box/magazine/tommygunm45(src)
- new /obj/item/boxcutter/extended(src)
- if(3)
- // M1911 with a switchblade and an extra banana bomb.
- new /obj/item/gun/ballistic/automatic/pistol/m1911/chimpgun(src)
- new /obj/item/ammo_box/magazine/m45(src)
- new /obj/item/ammo_box/magazine/m45(src)
- new /obj/item/switchblade/extended(src)
- new /obj/item/food/grown/banana/bunch/monkeybomb(src)
-
- // Banana bomb! Basically a tiny flashbang for monkeys.
- new /obj/item/food/grown/banana/bunch/monkeybomb(src)
- // Somewhere to store it all.
- new /obj/item/storage/backpack/messenger(src)
diff --git a/code/game/objects/items/storage/toolboxes/_toolbox.dm b/code/game/objects/items/storage/toolboxes/_toolbox.dm
new file mode 100644
index 00000000000..22318defc6e
--- /dev/null
+++ b/code/game/objects/items/storage/toolboxes/_toolbox.dm
@@ -0,0 +1,159 @@
+/obj/item/storage/toolbox
+ name = "toolbox"
+ desc = "Danger. Very robust."
+ icon = 'icons/obj/storage/toolbox.dmi'
+ icon_state = "toolbox_default"
+ inhand_icon_state = "toolbox_default"
+ lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
+ obj_flags = CONDUCTS_ELECTRICITY
+ force = 13
+ throwforce = 13
+ throw_speed = 2
+ throw_range = 7
+ demolition_mod = 1.25
+ w_class = WEIGHT_CLASS_BULKY
+ custom_materials = list(/datum/material/iron = SMALL_MATERIAL_AMOUNT*5)
+ attack_verb_continuous = list("robusts")
+ attack_verb_simple = list("robust")
+ hitsound = 'sound/items/weapons/smash.ogg'
+ drop_sound = 'sound/items/handling/toolbox/toolbox_drop.ogg'
+ pickup_sound = 'sound/items/handling/toolbox/toolbox_pickup.ogg'
+ material_flags = MATERIAL_EFFECTS | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
+ storage_type = /datum/storage/toolbox
+
+ var/latches = "single_latch"
+ var/has_latches = TRUE
+ wound_bonus = 5
+ /// How many interactions are we currently performing
+ var/current_interactions = 0
+ /// Items we should not interact with when left clicking
+ var/static/list/lmb_exception_typecache = typecacheof(list(
+ /obj/structure/table,
+ /obj/structure/rack,
+ /obj/structure/closet,
+ /obj/machinery/disposal,
+ ))
+
+/obj/item/storage/toolbox/Initialize(mapload)
+ . = ..()
+ if(has_latches)
+ if(prob(10))
+ latches = "double_latch"
+ if(prob(1))
+ latches = "triple_latch"
+ if(prob(0.1))
+ latches = "quad_latch" // like winning the lottery, but worse
+ update_appearance()
+ AddElement(/datum/element/falling_hazard, damage = force, wound_bonus = wound_bonus, hardhat_safety = TRUE, crushes = FALSE, impact_sound = hitsound)
+
+/obj/item/storage/toolbox/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
+ if (user.combat_mode || !user.has_hand_for_held_index(user.get_inactive_hand_index()))
+ return NONE
+
+ if (is_type_in_typecache(interacting_with, lmb_exception_typecache) && !LAZYACCESS(modifiers, RIGHT_CLICK))
+ return NONE
+
+ if (current_interactions)
+ var/obj/item/other_tool = user.get_inactive_held_item()
+ if (!istype(other_tool)) // what even
+ return NONE
+ INVOKE_ASYNC(src, PROC_REF(use_tool_on), interacting_with, user, modifiers, other_tool)
+ return ITEM_INTERACT_SUCCESS
+
+ if (user.get_inactive_held_item())
+ user.balloon_alert(user, "hands busy!")
+ return ITEM_INTERACT_BLOCKING
+
+ var/list/item_radial = list()
+ for (var/obj/item/tool in atom_storage.real_location)
+ if(is_type_in_list(tool, GLOB.tool_items))
+ item_radial[tool] = tool.appearance
+
+ if (!length(item_radial))
+ return NONE
+
+ playsound(user, 'sound/items/handling/toolbox/toolbox_open.ogg', 50)
+ var/obj/item/picked_item = show_radial_menu(user, interacting_with, item_radial, require_near = TRUE)
+ if (!picked_item)
+ return ITEM_INTERACT_BLOCKING
+
+ playsound(user, 'sound/items/handling/toolbox/toolbox_rustle.ogg', 50)
+ if (!user.put_in_inactive_hand(picked_item))
+ return ITEM_INTERACT_BLOCKING
+
+ atom_storage.animate_parent()
+ if (istype(picked_item, /obj/item/weldingtool))
+ var/obj/item/weldingtool/welder = picked_item
+ if (!welder.welding)
+ welder.attack_self(user)
+
+ if (istype(picked_item, /obj/item/spess_knife))
+ picked_item.attack_self(user)
+
+ INVOKE_ASYNC(src, PROC_REF(use_tool_on), interacting_with, user, modifiers, picked_item)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/item/storage/toolbox/proc/use_tool_on(atom/interacting_with, mob/living/user, list/modifiers, obj/item/picked_tool)
+ current_interactions += 1
+ picked_tool.melee_attack_chain(user, interacting_with, list2params(modifiers))
+ current_interactions -= 1
+
+ if (QDELETED(picked_tool) || picked_tool.loc != user || !user.CanReach(picked_tool))
+ current_interactions = 0
+ return
+
+ if (current_interactions)
+ return
+
+ if (istype(picked_tool, /obj/item/weldingtool))
+ var/obj/item/weldingtool/welder = picked_tool
+ if (welder.welding)
+ welder.attack_self(user)
+
+ atom_storage.attempt_insert(picked_tool, user)
+
+/obj/item/storage/toolbox/update_overlays()
+ . = ..()
+ if(has_latches)
+ . += latches
+
+/obj/item/storage/toolbox/suicide_act(mob/living/user)
+ user.visible_message(span_suicide("[user] robusts [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
+ return BRUTELOSS
+
+//repairbot assembly
+/obj/item/storage/toolbox/tool_act(mob/living/user, obj/item/tool, list/modifiers)
+ if(!istype(tool, /obj/item/assembly/prox_sensor))
+ return ..()
+
+ var/static/list/allowed_toolbox = list(
+ /obj/item/storage/toolbox/artistic,
+ /obj/item/storage/toolbox/electrical,
+ /obj/item/storage/toolbox/emergency,
+ /obj/item/storage/toolbox/mechanical,
+ /obj/item/storage/toolbox/syndicate,
+ )
+
+ if(!is_type_in_list(src, allowed_toolbox) && (type != /obj/item/storage/toolbox))
+ return ITEM_INTERACT_BLOCKING
+ if(contents.len >= 1)
+ balloon_alert(user, "not empty!")
+ return ITEM_INTERACT_BLOCKING
+ var/static/list/toolbox_colors = list(
+ /obj/item/storage/toolbox = "#445eb3",
+ /obj/item/storage/toolbox/emergency = "#445eb3",
+ /obj/item/storage/toolbox/electrical = "#b77931",
+ /obj/item/storage/toolbox/artistic = "#378752",
+ /obj/item/storage/toolbox/syndicate = "#3d3d3d",
+ )
+ var/obj/item/bot_assembly/repairbot/repair = new(src)
+ repair.toolbox = type
+ var/_color = toolbox_colors[type] || "#445eb3"
+ repair.set_color(_color)
+ user.put_in_hands(repair)
+ repair.update_appearance()
+ repair.balloon_alert(user, "sensor added!")
+ qdel(tool)
+ qdel(src)
+ return ITEM_INTERACT_SUCCESS
diff --git a/code/game/objects/items/storage/toolboxes/emergency.dm b/code/game/objects/items/storage/toolboxes/emergency.dm
new file mode 100644
index 00000000000..3b3d59c632c
--- /dev/null
+++ b/code/game/objects/items/storage/toolboxes/emergency.dm
@@ -0,0 +1,43 @@
+/obj/item/storage/toolbox/emergency
+ name = "emergency toolbox"
+ icon_state = "red"
+ inhand_icon_state = "toolbox_red"
+ material_flags = NONE
+ throw_speed = 3 // red ones go faster
+
+/obj/item/storage/toolbox/emergency/PopulateContents()
+ var/obj/item/random_item
+ switch(rand(1,3))
+ if(1)
+ random_item = /obj/item/flashlight
+ if(2)
+ random_item = /obj/item/flashlight/glowstick
+ if(3)
+ random_item = /obj/item/flashlight/flare
+
+ return list(
+ /obj/item/crowbar/red,
+ /obj/item/weldingtool/mini,
+ /obj/item/extinguisher/mini,
+ random_item,
+ /obj/item/radio/off,
+ )
+
+/obj/item/storage/toolbox/emergency/old
+ name = "rusty red toolbox"
+ icon_state = "toolbox_red_old"
+ has_latches = FALSE
+ material_flags = NONE
+ storage_type = /datum/storage/toolbox/ancient_bundle
+
+/obj/item/storage/toolbox/emergency/old/ancientbundle/PopulateContents()
+ return list(
+ /obj/item/card/emag, // 4 tc
+ /obj/item/card/emag/doorjack, //emag used to do both. 3 tc
+ /obj/item/pen/sleepy, // 4 tc
+ /obj/item/reagent_containers/applicator/pill/cyanide,
+ /obj/item/chameleon, //its not the original cloaking device, but it will do. 8 tc
+ /obj/item/gun/ballistic/revolver, // 13 tc old one stays in the old box
+ /obj/item/implanter/freedom, // 5 tc
+ /obj/item/stack/telecrystal, //The failsafe/self destruct isn't an item we can physically include in the kit, but 1 TC is technically enough to buy the equivalent.
+ )
diff --git a/code/game/objects/items/storage/toolboxes/fishing.dm b/code/game/objects/items/storage/toolboxes/fishing.dm
new file mode 100644
index 00000000000..ac8bae404d2
--- /dev/null
+++ b/code/game/objects/items/storage/toolboxes/fishing.dm
@@ -0,0 +1,59 @@
+/obj/item/storage/toolbox/fishing
+ name = "fishing toolbox"
+ desc = "Contains everything you need for your fishing trip."
+ icon_state = "fishing"
+ inhand_icon_state = "artistic_toolbox"
+ material_flags = NONE
+ custom_price = PAYCHECK_CREW * 3
+ storage_type = /datum/storage/toolbox/fishing
+
+ ///How much holding this affects fishing difficulty
+ var/fishing_modifier = -4
+
+/obj/item/storage/toolbox/fishing/Initialize(mapload)
+ . = ..()
+
+ AddComponent(/datum/component/adjust_fishing_difficulty, fishing_modifier, ITEM_SLOT_HANDS)
+
+/obj/item/storage/toolbox/fishing/PopulateContents()
+ return list(
+ /obj/item/bait_can/worm,
+ /obj/item/fishing_rod/unslotted,
+ /obj/item/fishing_hook,
+ /obj/item/fishing_line,
+ /obj/item/paper/paperslip/fishing_tip,
+ )
+
+/obj/item/storage/toolbox/fishing/small
+ name = "compact fishing toolbox"
+ desc = "Contains everything you need for your fishing trip. Except for the bait."
+ w_class = WEIGHT_CLASS_NORMAL
+ force = 5
+ throwforce = 5
+ storage_type = /datum/storage/toolbox/fishing/small
+
+/obj/item/storage/toolbox/fishing/small/PopulateContents()
+ return list(
+ /obj/item/fishing_rod/unslotted,
+ /obj/item/fishing_hook,
+ /obj/item/fishing_line,
+ /obj/item/paper/paperslip/fishing_tip,
+ )
+
+/obj/item/storage/toolbox/fishing/master
+ name = "super fishing toolbox"
+ desc = "Contains (almost) EVERYTHING you need for your fishing trip."
+ icon_state = "gold"
+ inhand_icon_state = "toolbox_gold"
+ fishing_modifier = -10
+
+/obj/item/storage/toolbox/fishing/master/PopulateContents()
+ return list(
+ /obj/item/fishing_rod/telescopic/master,
+ /obj/item/storage/box/fishing_hooks/master,
+ /obj/item/storage/box/fishing_lines/master,
+ /obj/item/bait_can/super_baits,
+ /obj/item/reagent_containers/cup/fish_feed,
+ /obj/item/aquarium_kit,
+ /obj/item/fish_analyzer,
+ )
diff --git a/code/game/objects/items/storage/toolboxes/mechanical.dm b/code/game/objects/items/storage/toolboxes/mechanical.dm
new file mode 100644
index 00000000000..978b56c0613
--- /dev/null
+++ b/code/game/objects/items/storage/toolboxes/mechanical.dm
@@ -0,0 +1,74 @@
+/obj/item/storage/toolbox/mechanical
+ name = "mechanical toolbox"
+ icon_state = "blue"
+ inhand_icon_state = "toolbox_blue"
+ material_flags = NONE
+ /// If FALSE, someone with a ensouled soulstone can sacrifice a spirit to change the sprite of this toolbox.
+ var/has_soul = FALSE
+
+/obj/item/storage/toolbox/mechanical/PopulateContents()
+ return list(
+ /obj/item/screwdriver,
+ /obj/item/wrench,
+ /obj/item/weldingtool,
+ /obj/item/crowbar,
+ /obj/item/analyzer,
+ /obj/item/wirecutters,
+ )
+
+/obj/item/storage/toolbox/mechanical/old
+ name = "rusty blue toolbox"
+ icon_state = "toolbox_blue_old"
+ has_latches = FALSE
+ has_soul = TRUE
+
+/obj/item/storage/toolbox/mechanical/old/heirloom
+ name = "toolbox" //this will be named "X family toolbox"
+ desc = "It's seen better days."
+ force = 5
+ w_class = WEIGHT_CLASS_NORMAL
+ storage_type = /datum/storage/toolbox/old_heirloom
+
+/obj/item/storage/toolbox/mechanical/old/heirloom/PopulateContents()
+ return NONE
+
+// version of below that isn't a traitor item
+/obj/item/storage/toolbox/mechanical/old/cleaner
+ name = "old blue toolbox"
+ icon_state = "oldtoolboxclean"
+ icon_state = "toolbox_blue_old"
+
+/obj/item/storage/toolbox/mechanical/old/clean // the assistant traitor toolbox, damage scales with TC inside
+ name = "toolbox"
+ desc = "An old, blue toolbox, it looks robust."
+ icon_state = "oldtoolboxclean"
+ inhand_icon_state = "toolbox_blue"
+ has_latches = FALSE
+ force = 19
+ throwforce = 22
+
+/obj/item/storage/toolbox/mechanical/old/clean/proc/calc_damage()
+ var/power = 0
+ for (var/obj/item/stack/telecrystal/stored_crystals in get_all_contents())
+ power += (stored_crystals.amount / 2)
+ force = initial(force) + power
+ throwforce = initial(throwforce) + power
+
+/obj/item/storage/toolbox/mechanical/old/clean/attack(mob/target, mob/living/user)
+ calc_damage()
+ ..()
+
+/obj/item/storage/toolbox/mechanical/old/clean/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
+ calc_damage()
+ ..()
+
+/obj/item/storage/toolbox/mechanical/old/clean/PopulateContents()
+ return list(
+ /obj/item/screwdriver,
+ /obj/item/wrench,
+ /obj/item/weldingtool,
+ /obj/item/crowbar,
+ /obj/item/wirecutters,
+ /obj/item/multitool,
+ /obj/item/clothing/gloves/color/yellow,
+ )
diff --git a/code/game/objects/items/storage/toolboxes/medical.dm b/code/game/objects/items/storage/toolboxes/medical.dm
new file mode 100644
index 00000000000..cde39b4f38c
--- /dev/null
+++ b/code/game/objects/items/storage/toolboxes/medical.dm
@@ -0,0 +1,42 @@
+/obj/item/storage/toolbox/medical
+ name = "medical toolbox"
+ desc = "A toolbox painted soft white and light blue. This is getting ridiculous."
+ icon_state = "medical"
+ inhand_icon_state = "toolbox_medical"
+ attack_verb_continuous = list("treats", "surgeries", "tends", "tends wounds on")
+ attack_verb_simple = list("treat", "surgery", "tend", "tend wounds on")
+ w_class = WEIGHT_CLASS_BULKY
+ material_flags = NONE
+ force = 5 // its for healing
+ wound_bonus = 25 // wounds are medical right?
+ /// Tray we steal the og contents from.
+ var/obj/item/surgery_tray/tray_type = /obj/item/surgery_tray
+
+/obj/item/storage/toolbox/medical/PopulateContents(datum/storage_config/config)
+ config.compute_max_values()
+
+ . = list()
+ var/atom/fake_tray = new tray_type(null) // not in src lest it fill storage that we need for its tools later
+ for(var/atom/movable/thingy in fake_tray)
+ thingy.moveToNullspace()
+ . += thingy
+ qdel(fake_tray)
+
+/obj/item/storage/toolbox/medical/full
+ tray_type = /obj/item/surgery_tray/full
+
+/obj/item/storage/toolbox/medical/coroner
+ name = "coroner toolbox"
+ desc = "A toolbox painted soft white and dark grey. This is getting beyond ridiculous."
+ icon_state = "coroner"
+ inhand_icon_state = "toolbox_coroner"
+ attack_verb_continuous = list("dissects", "autopsies", "corones")
+ attack_verb_simple = list("dissect", "autopsy", "corone")
+ w_class = WEIGHT_CLASS_BULKY
+ material_flags = NONE
+ force = 17 // it's not for healing
+ tray_type = /obj/item/surgery_tray/full/morgue
+
+/obj/item/storage/toolbox/medical/coroner/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/bane, mob_biotypes = MOB_UNDEAD, damage_multiplier = 1) //Just in case one of the tennants get uppity
diff --git a/code/game/objects/items/storage/toolboxes/misc.dm b/code/game/objects/items/storage/toolboxes/misc.dm
new file mode 100644
index 00000000000..cb2061955fe
--- /dev/null
+++ b/code/game/objects/items/storage/toolboxes/misc.dm
@@ -0,0 +1,47 @@
+/obj/item/storage/toolbox/drone
+ name = "mechanical toolbox"
+ icon_state = "blue"
+ inhand_icon_state = "toolbox_blue"
+ material_flags = NONE
+
+/obj/item/storage/toolbox/drone/PopulateContents()
+ var/obj/item/stack/cable_coil/cable = new (null, MAXCOIL)
+ cable.set_cable_color(pick(GLOB.cable_colors))
+
+ return list(
+ /obj/item/screwdriver,
+ /obj/item/wrench,
+ /obj/item/weldingtool,
+ /obj/item/crowbar,
+ cable,
+ /obj/item/wirecutters,
+ /obj/item/multitool,
+ )
+
+/obj/item/storage/toolbox/artistic
+ name = "artistic toolbox"
+ desc = "A toolbox painted bright green. Why anyone would store art supplies in a toolbox is beyond you, but it has plenty of extra space."
+ icon_state = "green"
+ inhand_icon_state = "artistic_toolbox"
+ w_class = WEIGHT_CLASS_GIGANTIC //Holds more than a regular toolbox!
+ material_flags = NONE
+ storage_type = /datum/storage/toolbox/artistic
+
+/obj/item/storage/toolbox/artistic/PopulateContents()
+ return list(
+ /obj/item/storage/crayons,
+ /obj/item/crowbar,
+ /obj/item/stack/pipe_cleaner_coil/red,
+ /obj/item/stack/pipe_cleaner_coil/yellow,
+ /obj/item/stack/pipe_cleaner_coil/blue,
+ /obj/item/stack/pipe_cleaner_coil/green,
+ /obj/item/stack/pipe_cleaner_coil/pink,
+ /obj/item/stack/pipe_cleaner_coil/orange,
+ /obj/item/stack/pipe_cleaner_coil/cyan,
+ /obj/item/stack/pipe_cleaner_coil/white,
+ /obj/item/stack/pipe_cleaner_coil/brown,
+ )
+
+/obj/item/storage/toolbox/haunted
+ name = "old toolbox"
+ custom_materials = list(/datum/material/hauntium = SMALL_MATERIAL_AMOUNT*5)
diff --git a/code/game/objects/items/storage/toolboxes/service.dm b/code/game/objects/items/storage/toolboxes/service.dm
new file mode 100644
index 00000000000..cdea077462a
--- /dev/null
+++ b/code/game/objects/items/storage/toolboxes/service.dm
@@ -0,0 +1,33 @@
+/obj/item/storage/toolbox/electrical
+ name = "electrical toolbox"
+ icon_state = "yellow"
+ inhand_icon_state = "toolbox_yellow"
+ material_flags = NONE
+ storage_type = /datum/storage/toolbox/electrical
+
+/obj/item/storage/toolbox/electrical/PopulateContents()
+ var/pickedcolor = pick(GLOB.cable_colors)
+
+ var/obj/item/insert
+ if(prob(5))
+ insert = /obj/item/clothing/gloves/color/yellow
+ else
+ var/obj/item/stack/cable_coil/new_cable_three = new (null, MAXCOIL)
+ new_cable_three.set_cable_color(pickedcolor)
+ insert = new_cable_three
+
+ var/obj/item/stack/cable_coil/new_cable_one = new (null, MAXCOIL)
+ new_cable_one.set_cable_color(pickedcolor)
+ var/obj/item/stack/cable_coil/new_cable_two = new (null, MAXCOIL)
+ new_cable_two.set_cable_color(pickedcolor)
+
+ return list(
+ /obj/item/screwdriver,
+ /obj/item/wirecutters,
+ /obj/item/t_scanner,
+ /obj/item/crowbar,
+ /obj/item/clothing/gloves/color/yellow,
+ new_cable_one,
+ new_cable_two,
+ insert,
+ )
diff --git a/code/game/objects/items/storage/toolboxes/weapons.dm b/code/game/objects/items/storage/toolboxes/weapons.dm
new file mode 100644
index 00000000000..90f545abcb5
--- /dev/null
+++ b/code/game/objects/items/storage/toolboxes/weapons.dm
@@ -0,0 +1,352 @@
+/obj/item/storage/toolbox/maint_kit
+ name = "gun maintenance kit"
+ desc = "It contains some gun maintenance supplies"
+ icon_state = "maint_kit"
+ inhand_icon_state = "ammobox"
+ has_latches = FALSE
+ drop_sound = 'sound/items/handling/ammobox_drop.ogg'
+ pickup_sound = 'sound/items/handling/ammobox_pickup.ogg'
+
+/obj/item/storage/toolbox/maint_kit/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+ config.compute_max_total_weight = TRUE
+
+ return list(
+ /obj/item/gun_maintenance_supplies,
+ /obj/item/gun_maintenance_supplies,
+ /obj/item/gun_maintenance_supplies,
+ )
+
+/obj/item/storage/toolbox/ammobox
+ name = "ammo canister"
+ desc = "A metal canister designed to hold ammunition"
+ icon_state = "ammobox"
+ inhand_icon_state = "ammobox"
+ lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
+ has_latches = FALSE
+ drop_sound = 'sound/items/handling/ammobox_drop.ogg'
+ pickup_sound = 'sound/items/handling/ammobox_pickup.ogg'
+ ///The ammo box to spawn
+ var/obj/item/ammo_box/ammo_to_spawn
+
+/obj/item/storage/toolbox/ammobox/PopulateContents()
+ if(isnull(ammo_to_spawn))
+ return NONE
+
+ . = list()
+ for(var/_ in 1 to 6)
+ . += ammo_to_spawn
+
+/obj/item/storage/toolbox/ammobox/strilka310
+ name = ".310 Strilka ammo box (Surplus?)"
+ desc = "It contains a few clips. Goddamn, this thing smells awful. \
+ Has this been sitting in a warehouse for the last several centuries?"
+ ammo_to_spawn = /obj/item/ammo_box/strilka310
+
+/obj/item/storage/toolbox/ammobox/strilka310/surplus
+ ammo_to_spawn = /obj/item/ammo_box/strilka310/surplus
+
+/obj/item/storage/toolbox/ammobox/wt550m9
+ name = "4.6x30mm ammo box"
+ ammo_to_spawn = /obj/item/ammo_box/magazine/wt550m9
+
+/obj/item/storage/toolbox/ammobox/wt550m9ap
+ name = "4.6x30mm AP ammo box"
+ ammo_to_spawn = /obj/item/ammo_box/magazine/wt550m9/wtap
+
+/obj/item/storage/toolbox/syndicate
+ name = "suspicious looking toolbox"
+ icon_state = "syndicate"
+ inhand_icon_state = "toolbox_syndi"
+ force = 15
+ throwforce = 18
+ material_flags = NONE
+ storage_type = /datum/storage/toolbox/syndicate
+
+/obj/item/storage/toolbox/syndicate/PopulateContents()
+ return list(
+ /obj/item/screwdriver/nuke,
+ /obj/item/wrench,
+ /obj/item/weldingtool/largetank,
+ /obj/item/crowbar/red,
+ new /obj/item/wirecutters(null, "red"),
+ /obj/item/multitool,
+ /obj/item/clothing/gloves/combat,
+ )
+
+/obj/item/storage/toolbox/guncase
+ name = "gun case"
+ desc = "A weapon's case. Has a blood-red 'S' stamped on the cover."
+ icon = 'icons/obj/storage/case.dmi'
+ icon_state = "infiltrator_case"
+ lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
+ inhand_icon_state = "infiltrator_case"
+ has_latches = FALSE
+ storage_type = /datum/storage/toolbox/guncase
+
+ ///Weapon to spawn in this toolbox
+ var/weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol
+ ///Extra item to spawn in this toolbox
+ var/extra_to_spawn = /obj/item/ammo_box/magazine/m9mm
+
+/obj/item/storage/toolbox/guncase/PopulateContents()
+ new weapon_to_spawn(src)
+ for(var/i in 1 to 3)
+ new extra_to_spawn(src)
+
+ . = list()
+ for(var/obj/item/insert as anything in src)
+ insert.moveToNullspace()
+ . += insert
+
+/obj/item/storage/toolbox/guncase/traitor
+ name = "makarov gun case"
+ desc = "A weapon's case. Has a blood-red 'S' stamped on the cover. There seems to be a strange switch along the side inside a plastic flap."
+ icon_state = "pistol_case"
+ base_icon_state = "pistol_case"
+ // What ammo box do we spawn in our case?
+ var/ammo_box_to_spawn = /obj/item/ammo_box/c9mm
+ // Timer for the bomb in the case.
+ var/explosion_timer
+ // Whether or not our case is exploding. Used for determining sprite changes.
+ var/currently_exploding = FALSE
+
+/obj/item/storage/toolbox/guncase/traitor/Initialize(mapload)
+ . = ..()
+ register_context()
+
+/obj/item/storage/toolbox/guncase/traitor/examine(mob/user)
+ . = ..()
+ . += span_notice("Activate the Evidence Disposal Explosive using Alt-Right-Click.")
+
+/obj/item/storage/toolbox/guncase/traitor/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ . = ..()
+
+ context[SCREENTIP_CONTEXT_ALT_RMB] = "Activate Evidence Disposal Explosive"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/obj/item/storage/toolbox/guncase/traitor/PopulateContents()
+ . = list()
+
+ . += weapon_to_spawn
+ for(var/i in 1 to 2)
+ . += extra_to_spawn
+ . += ammo_box_to_spawn
+
+/obj/item/storage/toolbox/guncase/traitor/update_icon_state()
+ . = ..()
+ if(currently_exploding)
+ icon_state = "[base_icon_state]_exploding"
+ else
+ icon_state = "[base_icon_state]"
+
+/obj/item/storage/toolbox/guncase/traitor/click_alt_secondary(mob/user)
+ . = ..()
+ var/i_dont_even_think_once_about_blowing_stuff_up = tgui_alert(user, "Would you like to activate the evidence disposal bomb now?", "BYE BYE", list("Yes","No"))
+ if(i_dont_even_think_once_about_blowing_stuff_up == "No")
+ return
+ explosion_timer = addtimer(CALLBACK(src, PROC_REF(think_fast_chucklenuts)), 5 SECONDS, (TIMER_UNIQUE|TIMER_OVERRIDE))
+ to_chat(user, span_warning("You prime [src]'s evidence disposal bomb!"))
+ log_bomber(user, "has activated a", src, "for detonation")
+ playsound(src, 'sound/items/weapons/armbomb.ogg', 50, TRUE)
+ currently_exploding = TRUE
+ update_appearance()
+
+/// proc to handle our detonation
+/obj/item/storage/toolbox/guncase/traitor/proc/think_fast_chucklenuts()
+ explosion(src, devastation_range = 0, heavy_impact_range = 0, light_impact_range = 2, explosion_cause = src)
+ qdel(src)
+
+/obj/item/storage/toolbox/guncase/traitor/ammunition
+ name = "makarov 9mm magazine case"
+ weapon_to_spawn = /obj/item/ammo_box/magazine/m9mm
+
+/obj/item/storage/toolbox/guncase/traitor/donksoft
+ name = "\improper Donksoft riot pistol gun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol/toy/riot/clandestine
+ extra_to_spawn = /obj/item/ammo_box/magazine/toy/pistol/riot
+ ammo_box_to_spawn = /obj/item/ammo_box/foambox/riot
+
+/obj/item/storage/toolbox/guncase/traitor/ammunition/donksoft
+ name = "\improper Donksoft riot pistol magazine case"
+ weapon_to_spawn = /obj/item/ammo_box/magazine/toy/pistol/riot
+ extra_to_spawn = /obj/item/ammo_box/magazine/toy/pistol/riot
+ ammo_box_to_spawn = /obj/item/ammo_box/foambox/riot
+
+/obj/item/storage/toolbox/guncase/bulldog
+ name = "bulldog gun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/shotgun/bulldog
+ extra_to_spawn = /obj/item/ammo_box/magazine/m12g
+
+/obj/item/storage/toolbox/guncase/c20r
+ name = "c-20r gun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/automatic/c20r
+ extra_to_spawn = /obj/item/ammo_box/magazine/smgm45
+
+/obj/item/storage/toolbox/guncase/smartgun
+ name = "adielle smartgun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/automatic/smartgun
+ extra_to_spawn = /obj/item/ammo_box/magazine/smartgun
+
+/obj/item/storage/toolbox/guncase/clandestine
+ name = "clandestine gun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol/clandestine
+ extra_to_spawn = /obj/item/ammo_box/magazine/m10mm
+
+/obj/item/storage/toolbox/guncase/m90gl
+ name = "m-90gl gun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/automatic/m90
+ extra_to_spawn = /obj/item/ammo_box/magazine/m223
+
+/obj/item/storage/toolbox/guncase/m90gl/PopulateContents()
+ . = list()
+
+ . += weapon_to_spawn
+ for(var/i in 1 to 2)
+ . += extra_to_spawn
+ . += /obj/item/ammo_box/a40mm/rubber
+
+/obj/item/storage/toolbox/guncase/rocketlauncher
+ name = "rocket launcher gun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/rocketlauncher
+ extra_to_spawn = /obj/item/ammo_box/rocket
+
+/obj/item/storage/toolbox/guncase/rocketlauncher/PopulateContents()
+ return list(
+ weapon_to_spawn,
+ extra_to_spawn
+ )
+
+/obj/item/storage/toolbox/guncase/revolver
+ name = "revolver gun case"
+ weapon_to_spawn = /obj/item/gun/ballistic/revolver/badass/nuclear
+ extra_to_spawn = /obj/item/ammo_box/a357
+
+/obj/item/storage/toolbox/guncase/sword_and_board
+ name = "energy sword and shield weapon case"
+ weapon_to_spawn = /obj/item/melee/energy/sword
+ extra_to_spawn = /obj/item/shield/energy
+
+/obj/item/storage/toolbox/guncase/sword_and_board/PopulateContents()
+ return list(
+ weapon_to_spawn,
+ extra_to_spawn,
+ /obj/item/clothing/head/costume/knight,
+ )
+
+/obj/item/storage/toolbox/guncase/cqc
+ name = "\improper CQC equipment case"
+ weapon_to_spawn = /obj/item/book/granter/martial/cqc
+ extra_to_spawn = /obj/item/storage/box/syndie_kit/imp_stealth
+
+/obj/item/storage/toolbox/guncase/cqc/PopulateContents(datum/storage_config/config)
+ config.compute_max_total_weight = TRUE
+
+ return list(
+ weapon_to_spawn,
+ extra_to_spawn,
+ /obj/item/clothing/head/costume/snakeeater,
+ /obj/item/storage/fancy/cigarettes/cigpack_syndicate,
+ )
+
+/obj/item/storage/toolbox/guncase/soviet
+ name = "ancient gun case"
+ desc = "A weapon's case. Has the symbol of the Third Soviet Union stamped on the side."
+ icon_state = "sakhno_case"
+ inhand_icon_state = "sakhno_case"
+ weapon_to_spawn = /obj/effect/spawner/random/sakhno
+ extra_to_spawn = /obj/effect/spawner/random/sakhno/ammo
+
+/obj/item/storage/toolbox/guncase/soviet/PopulateContents(datum/storage_config/config)
+ config.compute_max_total_weight = TRUE
+
+ return ..()
+
+/obj/item/storage/toolbox/guncase/monkeycase
+ name = "monkey gun case"
+ desc = "Everything a monkey needs to truly go ape-shit. There's a paw-shaped hand scanner lock on the front of the case."
+
+/obj/item/storage/toolbox/guncase/monkeycase/Initialize(mapload)
+ . = ..()
+ atom_storage.locked = STORAGE_SOFT_LOCKED
+
+/obj/item/storage/toolbox/guncase/monkeycase/attack_self(mob/user, modifiers)
+ if(!monkey_check(user))
+ return
+ return ..()
+
+/obj/item/storage/toolbox/guncase/monkeycase/attack_self_secondary(mob/user, modifiers)
+ attack_self(user, modifiers)
+ return
+
+/obj/item/storage/toolbox/guncase/monkeycase/attack_hand(mob/user, list/modifiers)
+ if(!monkey_check(user))
+ return
+ return ..()
+
+/obj/item/storage/toolbox/guncase/monkeycase/proc/monkey_check(mob/user)
+ if(atom_storage.locked == STORAGE_NOT_LOCKED)
+ return TRUE
+
+ if(is_simian(user))
+ atom_storage.locked = STORAGE_NOT_LOCKED
+ to_chat(user, span_notice("You place your paw on the paw scanner, and hear a soft click as [src] unlocks!"))
+ playsound(src, 'sound/items/click.ogg', 25, TRUE)
+ return TRUE
+ to_chat(user, span_warning("You put your hand on the hand scanner, and it rejects it with an angry chimpanzee screech!"))
+ playsound(src, SFX_SCREECH, 75, TRUE)
+ return FALSE
+
+/obj/item/storage/toolbox/guncase/monkeycase/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_count = TRUE
+ config.compute_max_total_weight = TRUE
+
+ switch(rand(1, 3))
+ if(1)
+ // Uzi with a boxcutter.
+ . = list(
+ /obj/item/gun/ballistic/automatic/mini_uzi/chimpgun,
+ /obj/item/ammo_box/magazine/uzim9mm,
+ /obj/item/ammo_box/magazine/uzim9mm,
+ /obj/item/boxcutter/extended,
+ )
+ if(2)
+ // Thompson with a boxcutter.
+ . = list(
+ /obj/item/gun/ballistic/automatic/tommygun/chimpgun,
+ /obj/item/ammo_box/magazine/tommygunm45,
+ /obj/item/ammo_box/magazine/tommygunm45,
+ /obj/item/boxcutter/extended,
+ )
+ if(3)
+ // M1911 with a switchblade and an extra banana bomb.
+ . = list(
+ /obj/item/gun/ballistic/automatic/pistol/m1911/chimpgun,
+ /obj/item/ammo_box/magazine/m45,
+ /obj/item/ammo_box/magazine/m45,
+ /obj/item/switchblade/extended,
+ /obj/item/food/grown/banana/bunch/monkeybomb,
+ )
+
+ // Banana bomb! Basically a tiny flashbang for monkeys.
+ . += /obj/item/food/grown/banana/bunch/monkeybomb
+ // Somewhere to store it all.
+ . += /obj/item/storage/backpack/messenger
+
+
+/obj/item/storage/toolbox/guncase/doublesword
+ name = "double-bladed energy sword weapon case"
+ weapon_to_spawn = /obj/item/dualsaber
+ extra_to_spawn = /obj/item/soap/syndie
+ storage_type = /datum/storage/toolbox/double_sword
+
+/obj/item/storage/toolbox/guncase/doublesword/PopulateContents()
+ return list(
+ weapon_to_spawn,
+ extra_to_spawn,
+ /obj/item/mod/module/noslip,
+ /obj/item/reagent_containers/hypospray/medipen/methamphetamine,
+ /obj/item/clothing/under/rank/prisoner/nosensor,
+ )
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
deleted file mode 100644
index f9c00af4206..00000000000
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ /dev/null
@@ -1,919 +0,0 @@
-#define KIT_RECON "recon"
-#define KIT_BLOODY_SPAI "bloodyspai"
-#define KIT_STEALTHY "stealth"
-#define KIT_SCREWED "screwed"
-#define KIT_SABOTAGE "sabotage"
-#define KIT_GUN "guns"
-#define KIT_MURDER "murder"
-#define KIT_IMPLANTS "implant"
-#define KIT_HACKER "hacker"
-#define KIT_SNIPER "sniper"
-#define KIT_NUKEOPS_METAGAME "metaops"
-#define KIT_LORD_SINGULOTH "lordsingulo"
-#define KIT_REVOLUTIONARY "revolutionary"
-
-#define KIT_JAMES_BOND "bond"
-#define KIT_NINJA "ninja"
-#define KIT_DARK_LORD "darklord"
-#define KIT_WHITE_WHALE_HOLY_GRAIL "white_whale_holy_grail"
-#define KIT_MAD_SCIENTIST "mad_scientist"
-#define KIT_BEES "bee"
-#define KIT_MR_FREEZE "mr_freeze"
-#define KIT_TRAITOR_2006 "ancient"
-#define KIT_DEAD_MONEY "dead_money"
-#define KIT_SAM_FISHER "sam_fisher"
-#define KIT_PROP_HUNT "prop_hunt"
-
-/// last audited december 2022
-/obj/item/storage/box/syndicate
-
-/obj/item/storage/box/syndicate/bundle_a/PopulateContents()
- switch (pick_weight(list(
- KIT_RECON = 2,
- KIT_BLOODY_SPAI = 3,
- KIT_STEALTHY = 2,
- KIT_SCREWED = 2,
- KIT_SABOTAGE = 3,
- KIT_GUN = 2,
- KIT_MURDER = 2,
- KIT_IMPLANTS = 1,
- KIT_HACKER = 3,
- KIT_SNIPER = 1,
- KIT_NUKEOPS_METAGAME = 1,
- KIT_REVOLUTIONARY = 2
- )))
- if(KIT_RECON)
- new /obj/item/clothing/glasses/thermal/xray(src) // ~8 tc?
- new /obj/item/storage/briefcase/launchpad(src) //6 tc
- new /obj/item/binoculars(src) // 2 tc?
- new /obj/item/encryptionkey/syndicate(src) // 2 tc
- new /obj/item/storage/box/syndie_kit/space(src) //4 tc
- new /obj/item/grenade/frag(src) // ~2 tc each?
- new /obj/item/grenade/frag(src)
- new /obj/item/flashlight/emp(src) // 4 tc
-
- if(KIT_BLOODY_SPAI)
- new /obj/item/card/id/advanced/chameleon(src) // 2 tc
- new /obj/item/clothing/under/chameleon(src) // 2 tc since it's not the full set
- new /obj/item/clothing/mask/chameleon(src) // Goes with above
- new /obj/item/clothing/shoes/chameleon/noslip(src) // 2 tc
- new /obj/item/computer_disk/syndicate/camera_app(src) // 1 tc
- new /obj/item/multitool/ai_detect(src) // 1 tc
- new /obj/item/encryptionkey/syndicate(src) // 2 tc
- new /obj/item/storage/box/syndie_kit/mulligan(src) // 4 tc
- new /obj/item/switchblade(src) //basically 1 tc as it can be bought from BM kits
- new /obj/item/storage/fancy/cigarettes/cigpack_syndicate (src) // 2 tc this shit heals
- new /obj/item/flashlight/emp(src) // 2 tc
- new /obj/item/chameleon(src) // 7 tc
- new /obj/item/implanter/storage(src) // 6 tc
-
- if(KIT_STEALTHY)
- new /obj/item/gun/energy/recharge/ebow(src) // 10 tc
- new /obj/item/pen/sleepy(src) // 4 tc
- new /obj/item/healthanalyzer/rad_laser(src) // 3 tc
- new /obj/item/chameleon(src) // 7 tc
- new /obj/item/soap/syndie(src) // 1 tc
- new /obj/item/clothing/glasses/thermal/syndi(src) // 4 tc
- new /obj/item/flashlight/emp(src) // 2 tc
- new /obj/item/jammer(src) // 5 tc
-
- if(KIT_GUN)
- new /obj/item/gun/ballistic/revolver(src) // 13 tc
- new /obj/item/ammo_box/a357(src) // 4tc
- new /obj/item/ammo_box/a357(src)
- new /obj/item/storage/belt/holster/chameleon(src) // 1 tc
- new /obj/item/card/emag/doorjack(src) // 3 tc replaced the emag with the doorjack
- new /obj/item/grenade/c4(src) // 1 tc
- new /obj/item/clothing/gloves/latex/nitrile(src) // ~1 tc for whole outfit
- new /obj/item/clothing/mask/gas/clown_hat(src)
- new /obj/item/clothing/under/suit/black_really(src)
- new /obj/item/clothing/neck/tie/red/hitman(src)
-
- if(KIT_SCREWED)
- new /obj/item/sbeacondrop/bomb(src) // 11 tc
- new /obj/item/grenade/syndieminibomb(src) // 6 tc
- new /obj/item/sbeacondrop/powersink(src) // 11 tc
- var/obj/item/clothing/suit/space/syndicate/spess_suit = pick(GLOB.syndicate_space_suits_to_helmets)
- new spess_suit(src) // Above allows me to get the helmet from a variable on the object
- var/obj/item/clothing/head/helmet/space/syndicate/spess_helmet = GLOB.syndicate_space_suits_to_helmets[spess_suit]
- new spess_helmet(src) // 4 TC for the space gear
- new /obj/item/encryptionkey/syndicate(src) // 2 tc
-
- if(KIT_MURDER)
- new /obj/item/melee/energy/sword/saber(src) // 8 tc
- new /obj/item/clothing/glasses/thermal/syndi(src) // 4 tc
- new /obj/item/card/emag/doorjack(src) // 3 tc
- new /obj/item/clothing/shoes/chameleon/noslip(src) // 2 tc
- new /obj/item/encryptionkey/syndicate(src) // 2 tc
- new /obj/item/grenade/syndieminibomb(src) // 6 tc
-
- if(KIT_IMPLANTS)
- new /obj/item/implanter/freedom(src) // 5 tc
- new /obj/item/implanter/uplink/precharged(src) // 10 tc is inside this thing
- new /obj/item/implanter/emp(src) // 1 tc
- new /obj/item/implanter/explosive(src) // 2 tc
- new /obj/item/implanter/storage(src) // 8 tc
-
- if(KIT_HACKER) //L-L--LOOK AT YOU, HACKER
- new /obj/item/ai_module/syndicate(src) // 4 tc
- new /obj/item/card/emag(src) // 4 tc
- new /obj/item/card/emag/doorjack(src) // 3 tc
- new /obj/item/encryptionkey/binary(src) // 5 tc
- new /obj/item/ai_module/toy_ai(src) // ~6 tc
- new /obj/item/multitool/ai_detect(src) // 1 tc
- new /obj/item/storage/toolbox/syndicate(src) // 1 tc
- new /obj/item/computer_disk/syndicate/camera_app(src) // 1 tc
- new /obj/item/clothing/glasses/thermal/syndi(src) // 4 tc
- new /obj/item/card/id/advanced/chameleon(src) // 2 tc
-
- if(KIT_LORD_SINGULOTH) //currently disabled, i might return with another anti-engine kit
- new /obj/item/sbeacondrop(src) // 10 tc
- var/obj/item/clothing/suit/space/syndicate/spess_suit = pick(GLOB.syndicate_space_suits_to_helmets)
- new spess_suit(src) // Above allows me to get the helmet from a variable on the object
- var/obj/item/clothing/head/helmet/space/syndicate/spess_helmet = GLOB.syndicate_space_suits_to_helmets[spess_suit]
- new spess_helmet(src) // 4 TC for the space gear
- new /obj/item/card/emag(src) // 4 tc
- new /obj/item/storage/toolbox/syndicate(src) // 1 tc
- new /obj/item/card/id/advanced/mining(src)
- new /obj/item/stack/spacecash/c10000(src) // this is technically 10 tc but not really
- if(prob(70))
- new /obj/item/toy/spinningtoy(src) //lol
- else
- new /obj/item/toy/spinningtoy/dark_matter(src) //edgy lol
-
- if(KIT_SABOTAGE)
- new /obj/item/storage/backpack/duffelbag/syndie/sabotage(src) // 5 tc for 3 c4 and 2 x4
- new /obj/item/computer_disk/syndicate/camera_app(src) // 1 tc
- new /obj/item/sbeacondrop/powersink(src) // 11 tc
- new /obj/item/computer_disk/virus/detomatix(src) // 6 tc
- new /obj/item/storage/toolbox/syndicate(src) // 1 tc
- new /obj/item/pizzabox/bomb(src) // 6 tc
- new /obj/item/storage/box/syndie_kit/emp(src) // 2 tc
-
- if(KIT_SNIPER) //This shit is unique so can't really balance it around tc, also no silencer because getting killed without ANY indicator on what killed you sucks
- new /obj/item/gun/ballistic/rifle/sniper_rifle(src) // 12 tc
- new /obj/item/ammo_box/magazine/sniper_rounds/penetrator(src) // 5 tc
- new /obj/item/clothing/glasses/thermal/syndi(src) // 4 tc
- new /obj/item/clothing/gloves/latex/nitrile(src) // ~ 1 tc for outfit
- new /obj/item/clothing/mask/gas/clown_hat(src)
- new /obj/item/clothing/under/suit/black_really(src)
- new /obj/item/clothing/neck/tie/red/hitman(src)
-
- if(KIT_NUKEOPS_METAGAME)
- new /obj/item/mod/control/pre_equipped/nuclear/unrestricted(src) // 8 tc
- new /obj/item/gun/ballistic/shotgun/bulldog/unrestricted(src) // 8 tc
- new /obj/item/implanter/explosive(src) // 2 tc
- new /obj/item/ammo_box/magazine/m12g(src) // 2 tc
- new /obj/item/ammo_box/magazine/m12g(src) // 2 tc
- new /obj/item/grenade/c4 (src) // 1 tc
- new /obj/item/grenade/c4 (src) // 1 tc
- new /obj/item/card/emag(src) // 4 tc
- new /obj/item/card/emag/doorjack(src) // 3 tc
-
- if(KIT_REVOLUTIONARY)
- new /obj/item/healthanalyzer/rad_laser(src) // 3 TC
- new /obj/item/assembly/flash/hypnotic(src) // 7 TC
- new /obj/item/storage/pill_bottle/lsd(src) // ~1 TC
- new /obj/item/pen/sleepy(src) // 4 TC
- new /obj/item/gun/ballistic/revolver/nagant(src) // 13 TC comparable to 357. revolvers
- new /obj/item/megaphone(src)
- new /obj/item/bedsheet/rev(src)
- new /obj/item/clothing/suit/armor/vest/russian_coat(src)
- new /obj/item/clothing/head/helmet/rus_ushanka(src)
- new /obj/item/storage/box/syndie_kit/poster_box(src)
-
-/obj/item/storage/box/syndicate/bundle_b/PopulateContents()
- switch (pick_weight(list(
- KIT_JAMES_BOND = 2,
- KIT_NINJA = 1,
- KIT_DARK_LORD = 1,
- KIT_WHITE_WHALE_HOLY_GRAIL = 2,
- KIT_MAD_SCIENTIST = 2,
- KIT_BEES = 1,
- KIT_MR_FREEZE = 2,
- KIT_DEAD_MONEY = 2,
- KIT_TRAITOR_2006 = 1,
- KIT_SAM_FISHER = 1,
- KIT_PROP_HUNT = 1
- )))
- if(KIT_JAMES_BOND)
- new /obj/item/gun/ballistic/automatic/pistol(src) // 7 tc
- new /obj/item/suppressor(src) // 3 tc
- new /obj/item/ammo_box/magazine/m9mm(src) // 1 tc
- new /obj/item/ammo_box/magazine/m9mm(src)
- new /obj/item/card/id/advanced/chameleon(src) // 2 tc
- new /obj/item/clothing/under/chameleon(src) // 1 tc
- new /obj/item/reagent_containers/hypospray/medipen/stimulants(src) // 5 tc
- new /obj/item/reagent_containers/cup/rag(src)
- new /obj/item/implanter/freedom(src) // 5 tc
- new /obj/item/flashlight/emp(src) // 2 tc
- new /obj/item/grenade/c4/x4(src) // 1ish tc
- new /obj/item/reagent_containers/applicator/pill/cyanide(src)
- new /obj/item/toy/cards/deck/syndicate(src) // 1 tc, for poker
-
- if(KIT_NINJA)
- new /obj/item/katana(src) // Unique , hard to tell how much tc this is worth. 8 tc?
- new /obj/item/reagent_containers/hypospray/medipen/stimulants(src) // 5 tc
- for(var/i in 1 to 6)
- new /obj/item/throwing_star(src) // 1 tc
- new /obj/item/storage/belt/chameleon(src) // worth some fraction of a tc
- new /obj/item/chameleon(src) // 7 tc
- new /obj/item/card/id/advanced/chameleon(src) // 2 tc
- new /obj/item/card/emag/doorjack(src) // 3 tc
- new /obj/item/book/granter/action/spell/smoke(src) // ninja smoke bomb. 1 tc
- new /obj/item/clothing/shoes/bhop(src) // mining item, lets you jump at people, at least 2 tc
-
- if(KIT_DARK_LORD)
- new /obj/item/dualsaber/red(src) // 16 tc
- new /obj/item/dnainjector/telemut/darkbundle(src) // ~ 4 tc for tk
- new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
- new /obj/item/card/id/advanced/chameleon(src) // 2 tc
- new /obj/item/clothing/shoes/chameleon/noslip(src) //2 tc ,because slipping while being a dark lord sucks
- new /obj/item/book/granter/action/spell/summonitem(src) // ~2 tc
- new /obj/item/book/granter/action/spell/lightningbolt(src) // 4 tc
-
- if(KIT_WHITE_WHALE_HOLY_GRAIL) //Unique items that don't appear anywhere else
- new /obj/item/gun/ballistic/rifle/boltaction/harpoon(src)
- new /obj/item/storage/bag/harpoon_quiver(src)
- new /obj/item/clothing/suit/hooded/carp_costume/spaceproof(src)
- new /obj/item/clothing/mask/gas/carp(src)
- new /obj/item/grenade/spawnergrenade/spesscarp(src)
- new /obj/item/toy/plush/carpplushie/dehy_carp(src) // 1 tc, for use as a personal mount
-
- if(KIT_MAD_SCIENTIST)
- new /obj/item/clothing/suit/toggle/labcoat/mad(src) // 0 tc
- new /obj/item/clothing/shoes/jackboots(src) // 0 tc
- new /obj/item/megaphone(src) // 0 tc
- new /obj/item/grenade/clusterbuster/random(src) // 10 tc?
- new /obj/item/grenade/clusterbuster/random(src) // 10 tc?
- new /obj/item/grenade/chem_grenade/bioterrorfoam(src) // 5 tc
- new /obj/item/assembly/signaler(src) // 0 tc
- new /obj/item/assembly/signaler(src) // 0 tc
- new /obj/item/assembly/signaler(src) // 0 tc
- new /obj/item/assembly/signaler(src) // 0 tc
- new /obj/item/storage/toolbox/syndicate(src) // 1 tc
- new /obj/item/pen/edagger(src) // 2 tc
- new /obj/item/gun/energy/wormhole_projector/core_inserted(src) // 5 tc easily
-
- if(KIT_BEES)
- new /obj/item/paper/fluff/bee_objectives(src) // 0 tc (motivation)
- new /obj/item/clothing/suit/hooded/bee_costume(src) // 0 tc
- new /obj/item/clothing/mask/animal/small/bee(src) // 0 tc
- new /obj/item/storage/belt/fannypack/yellow(src) // 0 tc
- new /obj/item/grenade/spawnergrenade/buzzkill(src) // these are the random super bees this is definitely all of the tc budget for this one
- new /obj/item/grenade/spawnergrenade/buzzkill(src) // 10 tc per grenade
- new /obj/item/reagent_containers/cup/bottle/beesease(src) // 10 tc?
- new /obj/item/melee/beesword(src) //priceless
-
- if(KIT_MR_FREEZE)
- new /obj/item/clothing/glasses/cold(src)
- new /obj/item/clothing/gloves/color/black/security/blu(src)
- new /obj/item/clothing/mask/chameleon(src)
- new /obj/item/clothing/suit/hooded/wintercoat(src)
- new /obj/item/clothing/shoes/winterboots(src)
- new /obj/item/grenade/gluon(src) // whole belt is 22 and gluon is weight 4 so lets just go with like 7 total
- new /obj/item/grenade/gluon(src)
- new /obj/item/grenade/gluon(src)
- new /obj/item/grenade/gluon(src)
- new /obj/item/dnainjector/geladikinesis(src) // both abilities are probably 3 tc total
- new /obj/item/dnainjector/cryokinesis(src)
- new /obj/item/gun/energy/temperature/freeze(src) // ~6 tc
- new /obj/item/gun/energy/laser/thermal/cryo(src) // ~6 tc
- new /obj/item/melee/energy/sword/saber/blue(src) //see see it fits the theme bc its blue and ice is blue, 8 tc
-
- if(KIT_TRAITOR_2006) //A kit so old, it's probably older than you. //This bundle is filled with the entire uplink contents traitors had access to in 2006, from OpenSS13. Notably the esword was not a choice but existed in code.
- new /obj/item/storage/toolbox/emergency/old/ancientbundle(src) //Items fit neatly into a classic toolbox just to remind you what the theme is.
-
- if(KIT_DEAD_MONEY)
- for(var/i in 1 to 4)
- new /obj/item/clothing/neck/collar_bomb(src) // These let you remotely kill people with a signaler, though you have to get them first.
- new /obj/item/storage/box/syndie_kit/signaler(src)
- new /obj/item/mod/control/pre_equipped/responsory/inquisitory/syndie(src) // basically a snowflake yet better elite modsuit, so like, 8 + 5 tc.
- new /obj/item/card/id/advanced/chameleon(src) // 2 tc
- new /obj/item/clothing/mask/chameleon(src)
- new /obj/item/melee/baton/telescopic/contractor_baton(src) // 7 tc
- new /obj/item/jammer(src) // 5 tc
- new /obj/item/pinpointer/crew(src) //priceless
-
- if(KIT_SAM_FISHER)
- new /obj/item/clothing/under/syndicate/combat(src)
- new /obj/item/clothing/suit/armor/vest/marine/pmc(src) //The armor kit is comparable to the infiltrator, 6 TC
- new /obj/item/clothing/head/helmet/marine/pmc(src)
- new /obj/item/clothing/mask/gas/sechailer(src)
- new /obj/item/clothing/glasses/night/colorless(src) // 3~ TC
- new /obj/item/clothing/gloves/krav_maga/combatglovesplus(src) //5TC
- new /obj/item/clothing/shoes/jackboots(src)
- new /obj/item/storage/belt/military/assault/fisher(src) //items in this belt easily costs 18 TC
-
- if(KIT_PROP_HUNT)
- new /obj/item/chameleon(src) // 7 TC
- new /obj/item/card/emag/doorjack(src) // 3 TC
- new /obj/item/storage/box/syndie_kit/imp_stealth(src) //8 TC
- new /obj/item/gun/ballistic/automatic/pistol(src) // 7 TC
- new /obj/item/clothing/glasses/thermal(src) // 4 TC
-
-/obj/item/storage/toolbox/emergency/old/ancientbundle/ //So the subtype works
-
-/obj/item/storage/toolbox/emergency/old/ancientbundle/PopulateContents()
- new /obj/item/card/emag(src) // 4 tc
- new /obj/item/card/emag/doorjack(src) //emag used to do both. 3 tc
- new /obj/item/pen/sleepy(src) // 4 tc
- new /obj/item/reagent_containers/applicator/pill/cyanide(src)
- new /obj/item/chameleon(src) //its not the original cloaking device, but it will do. 8 tc
- new /obj/item/gun/ballistic/revolver(src) // 13 tc old one stays in the old box
- new /obj/item/implanter/freedom(src) // 5 tc
- new /obj/item/stack/telecrystal(src) //The failsafe/self destruct isn't an item we can physically include in the kit, but 1 TC is technically enough to buy the equivalent.
-
-/obj/item/storage/belt/military/assault/fisher
-
-/obj/item/storage/belt/military/assault/fisher/PopulateContents()
- new /obj/item/gun/ballistic/automatic/pistol/clandestine/fisher(src) // 11 TC: 7 (pistol) + 3 (suppressor) + lightbreaker (1 TC, black market meme/util item)
- new /obj/item/ammo_box/magazine/m10mm(src) // 1 TC
- new /obj/item/ammo_box/magazine/m10mm(src)
- new /obj/item/card/emag/doorjack(src) // 3 TC
- new /obj/item/knife/combat(src) //comparable to the e-dagger, 2 TC
-
-/obj/item/storage/box/syndie_kit
- name = "box"
- desc = "A sleek, sturdy box."
- icon_state = "syndiebox"
- illustration = "writing_syndie"
-
-/obj/item/storage/box/syndie_kit/rebarxbowsyndie
- name = "Boxed Rebar Crossbow"
- desc = "A scoped weapon with low armor penetration, but devastating against flesh. Features instruction manual for making specialty ammo."
-
-/obj/item/storage/box/syndie_kit/rebarxbowsyndie/PopulateContents()
- new /obj/item/book/granter/crafting_recipe/dusting/rebarxbowsyndie_ammo(src)
- new /obj/item/gun/ballistic/rifle/rebarxbow/syndie(src)
- new /obj/item/storage/bag/rebar_quiver/syndicate(src)
-
-/obj/item/paper/syndicate_forensics_spoofer
- name = "Forensics Spoofer Guide"
- default_raw_text = {"
- Forensics Spoofer Info:
- The spoofer has two modes: SCAN which scans for fingerprints and fibers, and APPLY which applies the currently chosen fingerprint/fiber to your target.
- The spoofer can only store 5 fingerprints and 5 fibers, and may not store or report fibers/prints already stored. Additionally, it taps into the stations network to associate scanned fingerprints with names.
- The spoofer will make the same sounds and sights as a forensics scanner, when silent mode is off.
- "}
-
-/obj/item/storage/box/syndie_kit/forensics_spoofer
- name = "forensics spoofing kit"
-
-/obj/item/storage/box/syndie_kit/forensics_spoofer/PopulateContents()
- new /obj/item/forensics_spoofer(src)
- new /obj/item/paper/syndicate_forensics_spoofer(src)
-
-/obj/item/storage/box/syndie_kit/origami_bundle
- name = "origami kit"
- desc = "A box full of a number of rather masterfully engineered paper planes and a manual on \"The Art of Origami\"."
-
-/obj/item/storage/box/syndie_kit/origami_bundle/PopulateContents()
- new /obj/item/book/granter/action/origami(src)
- for(var/i in 1 to 5)
- new /obj/item/paper(src)
-
-/obj/item/storage/box/syndie_kit/imp_freedom
- name = "freedom implant box"
-
-/obj/item/storage/box/syndie_kit/imp_freedom/PopulateContents()
- new /obj/item/implanter/freedom(src)
-
-/obj/item/storage/box/syndie_kit/imp_microbomb
- name = "microbomb implant box"
-
-/obj/item/storage/box/syndie_kit/imp_microbomb/PopulateContents()
- new /obj/item/implanter/explosive(src)
-
-/obj/item/storage/box/syndie_kit/imp_macrobomb
- name = "macrobomb implant box"
-
-/obj/item/storage/box/syndie_kit/imp_macrobomb/PopulateContents()
- new /obj/item/implanter/explosive_macro(src)
-
-/obj/item/storage/box/syndie_kit/imp_deniability
- name = "tactical deniability implant box"
-
-/obj/item/storage/box/syndie_kit/imp_deniability/PopulateContents()
- new /obj/item/implanter/tactical_deniability(src)
-
-/obj/item/storage/box/syndie_kit/imp_uplink
- name = "uplink implant box"
-
-/obj/item/storage/box/syndie_kit/imp_uplink/PopulateContents()
- new /obj/item/implanter/uplink(src)
-
-/obj/item/storage/box/syndie_kit/bioterror
- name = "bioterror syringe box"
-
-/obj/item/storage/box/syndie_kit/bioterror/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/syringe/bioterror(src)
-
-/obj/item/storage/box/syndie_kit/clownpins
- name = "ultra hilarious firing pin box"
-
-/obj/item/storage/box/syndie_kit/clownpins/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/firing_pin/clown/ultra(src)
-
-/obj/item/storage/box/syndie_kit/imp_storage
- name = "storage implant box"
-
-/obj/item/storage/box/syndie_kit/imp_storage/PopulateContents()
- new /obj/item/implanter/storage(src)
-
-/obj/item/storage/box/syndie_kit/imp_stealth
- name = "stealth implant box"
-
-/obj/item/storage/box/syndie_kit/imp_stealth/PopulateContents()
- new /obj/item/implanter/stealth(src)
-
-/obj/item/storage/box/syndie_kit/imp_radio
- name = "syndicate radio implant box"
-
-/obj/item/storage/box/syndie_kit/imp_radio/PopulateContents()
- new /obj/item/implanter/radio/syndicate(src)
-
-/obj/item/storage/box/syndie_kit/space
- name = "boxed space suit and helmet"
-
-/obj/item/storage/box/syndie_kit/space/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.set_holdable(list(/obj/item/clothing/suit/space/syndicate, /obj/item/clothing/head/helmet/space/syndicate))
-
-/obj/item/storage/box/syndie_kit/space/PopulateContents()
- var/obj/item/clothing/suit/space/syndicate/spess_suit = pick(GLOB.syndicate_space_suits_to_helmets)
- new spess_suit(src) // Above allows me to get the helmet from a variable on the object
- var/obj/item/clothing/head/helmet/space/syndicate/spess_helmet = GLOB.syndicate_space_suits_to_helmets[spess_suit]
- new spess_helmet(src) // 4 TC for the space gear
-
-/obj/item/storage/box/syndie_kit/emp
- name = "EMP kit"
-
-/obj/item/storage/box/syndie_kit/emp/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/grenade/empgrenade(src)
- new /obj/item/implanter/emp(src)
-
-/obj/item/storage/box/syndie_kit/smoke
- name = "smoke kit"
-
-/obj/item/storage/box/syndie_kit/smoke/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/grenade/smokebomb(src)
-
-/obj/item/storage/box/syndie_kit/mail_counterfeit
- name = "mail counterfeit kit"
- desc = "A GLA Postal Service branded box. It's emblazoned with the motto: *Nothing stops the mail*."
-
-/obj/item/storage/box/syndie_kit/mail_counterfeit/PopulateContents()
- for(var/i in 1 to 6)
- new /obj/item/storage/mail_counterfeit_device(src)
-
-/obj/item/storage/box/syndie_kit/chemical
- name = "chemical kit"
-
-/obj/item/storage/box/syndie_kit/chemical/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 15
-
-/obj/item/storage/box/syndie_kit/chemical/PopulateContents()
- new /obj/item/reagent_containers/cup/bottle/polonium(src)
- new /obj/item/reagent_containers/cup/bottle/venom(src)
- new /obj/item/reagent_containers/cup/bottle/fentanyl(src)
- new /obj/item/reagent_containers/cup/bottle/formaldehyde(src)
- new /obj/item/reagent_containers/cup/bottle/spewium(src)
- new /obj/item/reagent_containers/cup/bottle/syndol(src)
- new /obj/item/reagent_containers/cup/bottle/cyanide(src)
- new /obj/item/reagent_containers/cup/bottle/histamine(src)
- new /obj/item/reagent_containers/cup/bottle/initropidril(src)
- new /obj/item/reagent_containers/cup/bottle/pancuronium(src)
- new /obj/item/reagent_containers/cup/bottle/sodium_thiopental(src)
- new /obj/item/reagent_containers/cup/bottle/coniine(src)
- new /obj/item/reagent_containers/cup/bottle/curare(src)
- new /obj/item/reagent_containers/cup/bottle/amanitin(src)
- new /obj/item/reagent_containers/syringe(src)
-
-/obj/item/storage/box/syndie_kit/nuke
- name = "nuke core extraction kit"
- desc = "A box containing the equipment and instructions for extracting the plutonium cores of most Nanotrasen nuclear explosives."
-
-/obj/item/storage/box/syndie_kit/nuke/PopulateContents()
- new /obj/item/screwdriver/nuke(src)
- new /obj/item/nuke_core_container(src)
- new /obj/item/paper/guides/antag/nuke_instructions(src)
-
-/obj/item/storage/box/syndie_kit/supermatter
- name = "supermatter sliver extraction kit"
- desc = "A box containing the equipment and instructions for extracting a sliver of supermatter."
-
-/obj/item/storage/box/syndie_kit/supermatter/PopulateContents()
- new /obj/item/scalpel/supermatter(src)
- new /obj/item/hemostat/supermatter(src)
- new /obj/item/nuke_core_container/supermatter(src)
- new /obj/item/paper/guides/antag/supermatter_sliver(src)
-
-/obj/item/storage/box/syndie_kit/tuberculosisgrenade
- name = "virus grenade kit"
-
-/obj/item/storage/box/syndie_kit/tuberculosisgrenade/PopulateContents()
- new /obj/item/grenade/chem_grenade/tuberculosis(src)
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/hypospray/medipen/tuberculosiscure(src)
- new /obj/item/reagent_containers/syringe(src)
- new /obj/item/reagent_containers/cup/bottle/tuberculosiscure(src)
-
-/obj/item/storage/box/syndie_kit/chameleon
- name = "chameleon kit"
-
-/obj/item/storage/box/syndie_kit/chameleon/PopulateContents()
- new /obj/item/clothing/under/chameleon(src)
- new /obj/item/clothing/suit/chameleon(src)
- new /obj/item/clothing/gloves/chameleon(src)
- new /obj/item/clothing/shoes/chameleon(src)
- new /obj/item/clothing/glasses/chameleon(src)
- new /obj/item/clothing/head/chameleon(src)
- new /obj/item/clothing/mask/chameleon(src)
- new /obj/item/clothing/neck/chameleon(src)
- new /obj/item/storage/backpack/chameleon(src)
- new /obj/item/storage/belt/chameleon(src)
- new /obj/item/radio/headset/chameleon(src)
- new /obj/item/stamp/chameleon(src)
- new /obj/item/modular_computer/pda/chameleon(src)
- new /obj/item/gun/energy/laser/chameleon(src)
- new /obj/item/chameleon_scanner(src)
-
-//5*(2*4) = 5*8 = 45, 45 damage if you hit one person with all 5 stars.
-//Not counting the damage it will do while embedded (2*4 = 8, at 15% chance)
-/obj/item/storage/box/syndie_kit/throwing_weapons/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/throwing_star(src)
- for(var/i in 1 to 2)
- new /obj/item/paperplane/syndicate(src)
- new /obj/item/restraints/legcuffs/bola/tactical(src)
- new /obj/item/restraints/legcuffs/bola/tactical(src)
-
-/obj/item/storage/box/syndie_kit/throwing_weapons/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 9 // 5 + 2 + 2
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 18 // 5*2 + 2*1 + 3*2
- atom_storage.set_holdable(list(
- /obj/item/restraints/legcuffs/bola/tactical,
- /obj/item/paperplane/syndicate,
- /obj/item/throwing_star,
- ))
-
-/obj/item/storage/box/syndie_kit/cutouts/PopulateContents()
- for(var/i in 1 to 3)
- new/obj/item/cardboard_cutout/adaptive(src)
- new/obj/item/toy/crayon/rainbow(src)
-
-/obj/item/storage/box/syndie_kit/romerol/PopulateContents()
- new /obj/item/reagent_containers/cup/bottle/romerol(src)
- new /obj/item/reagent_containers/syringe(src)
- new /obj/item/reagent_containers/dropper(src)
-
-/obj/item/storage/box/syndie_kit/ez_clean/PopulateContents()
- for(var/i in 1 to 3)
- new/obj/item/grenade/chem_grenade/ez_clean(src)
-
-/obj/item/storage/box/syndie_kit/mulligan/PopulateContents()
- . = ..()
- new /obj/item/reagent_containers/syringe/mulligan(src)
- new /obj/item/fake_identity_kit(src)
-
-/obj/item/storage/box/hug/reverse_revolver/PopulateContents()
- new /obj/item/gun/ballistic/revolver/reverse(src)
-
-/obj/item/storage/box/syndie_kit/mimery/PopulateContents()
- new /obj/item/book/granter/action/spell/mime/mimery_blockade(src)
- new /obj/item/book/granter/action/spell/mime/mimery_guns(src)
-
-/obj/item/storage/box/syndie_kit/moltobeso/PopulateContents()
- new /obj/item/reagent_containers/cup/bottle/moltobeso(src)
- new /obj/item/reagent_containers/syringe(src)
- new /obj/item/reagent_containers/dropper(src)
-
-/obj/item/storage/box/syndie_kit/combat_baking/PopulateContents()
- new /obj/item/food/baguette/combat(src)
- for(var/i in 1 to 2)
- new /obj/item/food/croissant/throwing(src)
- new /obj/item/book/granter/crafting_recipe/combat_baking(src)
-
-/obj/item/storage/box/syndie_kit/centcom_costume/PopulateContents()
- new /obj/item/clothing/under/rank/centcom/officer(src)
- new /obj/item/clothing/shoes/sneakers/black(src)
- new /obj/item/clothing/gloves/color/black(src)
- new /obj/item/radio/headset/headset_cent/empty(src)
- new /obj/item/clothing/glasses/sunglasses(src)
- new /obj/item/storage/backpack/satchel(src)
- new /obj/item/modular_computer/pda/heads(src)
- new /obj/item/clipboard(src)
-
-/obj/item/storage/box/syndie_kit/chameleon/broken/PopulateContents()
- new /obj/item/clothing/under/chameleon/broken(src)
- new /obj/item/clothing/suit/chameleon/broken(src)
- new /obj/item/clothing/gloves/chameleon/broken(src)
- new /obj/item/clothing/shoes/chameleon/noslip/broken(src)
- new /obj/item/clothing/glasses/chameleon/broken(src)
- new /obj/item/clothing/head/chameleon/broken(src)
- new /obj/item/clothing/mask/chameleon/broken(src)
- new /obj/item/clothing/neck/chameleon/broken(src)
- new /obj/item/storage/backpack/chameleon/broken(src)
- new /obj/item/storage/belt/chameleon/broken(src)
- new /obj/item/radio/headset/chameleon/broken(src)
- new /obj/item/stamp/chameleon/broken(src)
- new /obj/item/modular_computer/pda/chameleon/broken(src)
- // No chameleon laser, they can't randomise for //REASONS//
-
-/obj/item/storage/box/syndie_kit/bee_grenades
- name = "buzzkill grenade box"
- desc = "A sleek, sturdy box with a buzzing noise coming from the inside. Uh oh."
-
-/obj/item/storage/box/syndie_kit/bee_grenades/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/grenade/spawnergrenade/buzzkill(src)
-
-/obj/item/storage/box/syndie_kit/manhack_grenades/PopulateContents()
- for(var/i in 1 to 3)
- new /obj/item/grenade/spawnergrenade/manhacks(src)
-
-/obj/item/storage/box/syndie_kit/sleepytime/PopulateContents()
- new /obj/item/clothing/under/syndicate/bloodred/sleepytime(src)
- new /obj/item/reagent_containers/cup/glass/mug/coco(src)
- new /obj/item/toy/plush/carpplushie(src)
- new /obj/item/bedsheet/syndie(src)
-
-/obj/item/storage/box/syndie_kit/demoman/PopulateContents()
- new /obj/item/gun/grenadelauncher(src)
- new /obj/item/storage/belt/grenade/full(src)
- if(prob(1))
- new /obj/item/clothing/head/hats/hos/shako(src)
-
-/obj/item/storage/box/syndie_kit/core_gear
- name = "core equipment box"
- desc = "Contains all the necessary gear for success for any nuclear operative unsure of what is needed for success in the field. Everything here WILL help you."
-
-/obj/item/storage/box/syndie_kit/core_gear/PopulateContents()
- new /obj/item/implanter/freedom (src)
- new /obj/item/card/emag/doorjack (src)
- new /obj/item/reagent_containers/hypospray/medipen/stimulants (src)
- new /obj/item/grenade/c4 (src)
- new /obj/item/mod/module/energy_shield(src)
-
-/// Surplus Ammo Box
-
-/obj/item/storage/box/syndie_kit/sniper_surplus
- name = "surplus .50 BMG magazine box"
- desc = "A shoddy box full of surplus .50 BMG magazines. Not as strong, but good enough to keep lead in the air."
-
-/obj/item/storage/box/syndie_kit/sniper_surplus/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/ammo_box/magazine/sniper_rounds/surplus(src)
-
-/obj/item/storage/box/syndie_kit/shotgun_surplus
- name = "\improper Donk Co. 'Donk Spike' flechette 12g Bulldog magazine box"
- desc = "A shoddy box full of Donk Co. 'Donk Spike' flechette 12g. It is debatable whether or not these are actually \
- better or worse than standard flechette. Donk Co. did genuinely believe in this product being the future of military \
- ammunition production. The only reason it didn't see wider adoption was a lack of faith in the product. Do you \
- believe in Donk? Time to put that to the test."
-
-/obj/item/storage/box/syndie_kit/shotgun_surplus/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/ammo_box/magazine/m12g/donk(src)
-
-///Subtype for the sabotage bundle. Contains three C4, two X4 and 6 signalers
-/obj/item/storage/backpack/duffelbag/syndie/sabotage
-
-/obj/item/storage/backpack/duffelbag/syndie/sabotage/PopulateContents()
- new /obj/item/grenade/c4(src)
- new /obj/item/grenade/c4(src)
- new /obj/item/grenade/c4(src)
- new /obj/item/grenade/c4/x4(src)
- new /obj/item/grenade/c4/x4(src)
- new /obj/item/storage/box/syndie_kit/signaler(src)
-
-/obj/item/storage/box/syndie_kit/signaler
- name = "signaler box"
- desc = "Contains everything an agent would need to remotely detonate their bombs."
-
-/obj/item/storage/box/syndie_kit/signaler/PopulateContents()
- for(var/i in 1 to 6)
- new /obj/item/assembly/signaler(src)
-
-/obj/item/storage/box/syndie_kit/imp_deathrattle
- name = "deathrattle implant box"
- desc = "Contains eight linked deathrattle implants."
-
-/obj/item/storage/box/syndie_kit/imp_deathrattle/PopulateContents()
- new /obj/item/implanter(src)
-
- var/datum/deathrattle_group/group = new
-
- var/implants = list()
- for(var/j in 1 to 8)
- var/obj/item/implantcase/deathrattle/case = new (src)
- implants += case.imp
-
- for(var/i in implants)
- group.register(i)
- desc += " The implants are registered to the \"[group.name]\" group."
-
-/obj/item/storage/box/stickers/syndie_kit/PopulateContents()
- var/list/types = subtypesof(/obj/item/sticker/syndicate)
-
- for(var/i in 1 to atom_storage.max_slots)
- var/type = pick(types)
- new type(src)
-
-/obj/item/storage/box/syndie_kit/pinata
- name = "weapons grade pinata kit"
- desc = "Contains a weapons grade pinata and 2 belts for carrying its contents."
-
-/obj/item/storage/box/syndie_kit/pinata/PopulateContents()
- new /obj/item/pinata/syndie(src)
- new /obj/item/storage/belt/grenade(src)
- new /obj/item/storage/belt/military/snack(src)
-
-/obj/item/storage/box/syndie_kit/induction_kit
- name = "syndicate induction kit"
- desc = "Contains all you need for introducing your newest comrade to the Syndicate and all its worker's benefits."
-
-/obj/item/storage/box/syndie_kit/induction_kit/PopulateContents()
- // Basic weaponry, so they have something to use.
- new /obj/item/gun/ballistic/automatic/pistol/clandestine(src) // 6 TC, but free for nukies
- new /obj/item/ammo_box/magazine/m10mm/hp(src) // 3 TC, a reward for the teamwork involved
- new /obj/item/ammo_box/magazine/m10mm/ap(src) // 3 TC, a reward for the teamwork involved
- new /obj/item/pen/edagger(src) // 2 TC
- // The necessary equipment to help secure that disky.
- new /obj/item/radio/headset/syndicate/alt(src) // 5 TC / Free for nukies
- new /obj/item/modular_computer/pda/nukeops(src) // ?? TC / Free for nukies
- new /obj/item/card/id/advanced/chameleon(src) // 2 TC / Free for nukies
- var/obj/item/clothing/suit/space/syndicate/spess_suit = pick(GLOB.syndicate_space_suits_to_helmets)
- new spess_suit(src) // Above allows me to get the helmet from a variable on the object
- var/obj/item/clothing/head/helmet/space/syndicate/spess_helmet = GLOB.syndicate_space_suits_to_helmets[spess_suit]
- new spess_helmet(src) // 4 TC for the space gear
- new /obj/item/tank/jetpack/oxygen/harness(src) // They kinda need this to fly to the cruiser.
- // Tacticool gear
- new /obj/item/clothing/shoes/combat(src)
- new /obj/item/clothing/under/syndicate(src)
- new /obj/item/clothing/gloves/fingerless(src)
- new /obj/item/book/manual/nuclear(src) // Very important
- // The most important part of the kit, the implant that gives them the syndicate faction.
- new /obj/item/implanter/induction_implant(src)
- // All in all, 6+3+3+2+5+2+4 = ~25 TC of 'miscellaneous' items.
- // This is a lot of value for 10 TC, but you have to keep in mind that you NEED someone to get this stuff station-side.
- // Pretty much all of it is a bad deal for reinforcements or yourself as they already have similar or good-enough alternatives.
-
-/obj/item/implanter/induction_implant
- name = "implanter (nuclear operative)"
- desc = "A sterile automatic implant injector. You can see a tiny, somehow legible sticker on the side: 'NOT A BRAINWASH DEVICE'"
- imp_type = /obj/item/implant/nuclear_operative
-
-/obj/item/implant/nuclear_operative
- name = "nuclear operative implant"
- desc = "Registers you as a member of a Syndicate nuclear operative team."
- implant_color = "r"
-
-/obj/item/implant/nuclear_operative/get_data()
- return "Implant Specifications:
\
- Name: Suspicious Implant
\
- Life: UNKNOWN
\
- Implant Details:
\
- Function: Strange implant that seems to resist any attempts at scanning it."
-
-/obj/item/implant/nuclear_operative/implant(mob/living/target, mob/user, silent = FALSE, force = FALSE)
- . = ..()
- if(!. || !ishuman(target) || !(target.mind))
- return FALSE
- var/mob/living/carbon/human/human_target = target
-
- if(IS_NUKE_OP(human_target)) // this wont proc due to ..() but i guess its good as a just-in-case?
- if(human_target == user)
- to_chat(user, span_userdanger("You're already a nuclear operative, dumbass! The implant disintegrates within you! You feel sick..."))
- human_target.Stun(10 SECONDS)
- human_target.reagents.add_reagent(/datum/reagent/toxin, 10)
- return FALSE
- else
- to_chat(user, span_notice("You finish implanting [human_target], but you don't really notice a difference. Huh."))
- to_chat(human_target, span_userdanger("Nothing seems to really happen, but you start to feel a little ill.."))
- human_target.reagents.add_reagent(/datum/reagent/toxin, 2)
- return FALSE
-
- /// If all the antag datums are 'fake' or none exist, disallow induction! No self-antagging.
- var/faker
- for(var/datum/antagonist/antag_datum as anything in human_target.mind.antag_datums)
- if((antag_datum.antag_flags & FLAG_FAKE_ANTAG))
- faker = TRUE
-
- if(faker || isnull(human_target.mind.antag_datums)) // GTFO. Technically not foolproof but making a heartbreaker or a paradox clone a nuke op sounds hilarious
- to_chat(human_target, span_notice("Huh? Nothing happened? But you're starting to feel a little ill..."))
- human_target.reagents.add_reagent(/datum/reagent/toxin, 15)
- return FALSE
-
- var/datum/antagonist/nukeop/nuke_datum = new()
- nuke_datum.send_to_spawnpoint = FALSE
- nuke_datum.nukeop_outfit = null
- human_target.mind?.add_antag_datum(nuke_datum)
- human_target.faction |= ROLE_SYNDICATE
- to_chat(human_target, span_warning("You are now a nuclear operative. Your main objective, if you were an antagonist and willing, is presumably to assist the nuclear operative team and secure the disk."))
- to_chat(human_target, span_userdanger("This implant does NOT, in any way, brainwash you. If you were a normal crew member beforehand, forcibly implanted or otherwise, you are still one and cannot assist the nuclear operatives."))
- return TRUE
-
-/obj/item/implant/nuclear_operative/removed(mob/target, silent = FALSE, special = FALSE)
- . = ..()
- if(!. || !isliving(target))
- return FALSE
- var/mob/living/living_target = target
- living_target.mind.remove_antag_datum(/datum/antagonist/nukeop)
- living_target.faction -= ROLE_SYNDICATE
- to_chat(target, span_notice("You feel a little less nuclear."))
- to_chat(target, span_userdanger("You're no longer identified as a nuclear operative! You are free to follow any valid goals you wish, even continuing to secure the disk. Just make sure neither any turrets nor operatives kill you on sight."))
- return TRUE
-
-/obj/item/storage/box/syndie_kit/poster_box
- name = "syndicate poster pack"
- desc = "Contains a variety of demotivational posters to ensure minimum productivity for the crew of any Nanotrasen station."
-
- /// Number of posters this box contains when spawning.
- var/poster_count = 3
-
-/obj/item/storage/box/syndie_kit/poster_box/PopulateContents()
- for(var/i in 1 to poster_count)
- new /obj/item/poster/traitor(src)
-
-/obj/item/storage/box/syndie_kit/cowboy
- name = "western outlaw pack"
- desc = "Contains everything you'll need to be the rootin' tootin' cowboy you always wanted. Either play the Lone Ranger or go in with your posse of outlaws."
-
-/obj/item/storage/box/syndie_kit/cowboy/PopulateContents()
- generate_items_inside(list(
- /obj/item/clothing/shoes/cowboy/black/syndicate= 1,
- /obj/item/clothing/head/cowboy/black/syndicate = 1,
- /obj/item/storage/belt/holster/nukie/cowboy/full = 1,
- /obj/item/clothing/under/costume/dutch/syndicate = 1,
- /obj/item/lighter/skull = 1,
- /obj/item/sbeacondrop/horse = 1,
- /obj/item/food/grown/apple = 1,
- ), src)
-
-/obj/item/storage/box/syndicate/contract_kit
- name = "Contract Kit"
- desc = "Supplied to Syndicate contractors."
- icon_state = "syndiebox"
- illustration = "writing_syndie"
-
-/obj/item/storage/box/syndicate/contract_kit/PopulateContents()
- new /obj/item/modular_computer/pda/syndicate_contract_uplink(src)
- new /obj/item/storage/box/syndicate/contractor_loadout(src)
- new /obj/item/melee/baton/telescopic/contractor_baton(src)
- // Paper guide is always last.
- new /obj/item/paper/contractor_guide(src)
-
-/obj/item/storage/box/syndicate/contractor_loadout
- name = "Standard Loadout"
- desc = "Supplied to Syndicate contractors, providing their specialised space suit and chameleon uniform."
- icon_state = "syndiebox"
- illustration = "writing_syndie"
-
-/obj/item/storage/box/syndicate/contractor_loadout/PopulateContents()
- new /obj/item/mod/control/pre_equipped/infiltrator(src)
- new /obj/item/clothing/head/helmet/space/syndicate/contract(src)
- new /obj/item/clothing/suit/space/syndicate/contract(src)
- new /obj/item/clothing/under/chameleon(src)
- new /obj/item/clothing/mask/chameleon(src)
- new /obj/item/card/id/advanced/chameleon(src)
- new /obj/item/clothing/glasses/thermal/syndi(src)
- new /obj/item/storage/toolbox/syndicate(src)
- new /obj/item/jammer(src)
- new /obj/item/storage/fancy/cigarettes/cigpack_syndicate(src)
- new /obj/item/lighter(src)
-
-#undef KIT_RECON
-#undef KIT_BLOODY_SPAI
-#undef KIT_STEALTHY
-#undef KIT_SCREWED
-#undef KIT_SABOTAGE
-#undef KIT_GUN
-#undef KIT_MURDER
-#undef KIT_IMPLANTS
-#undef KIT_HACKER
-#undef KIT_SNIPER
-#undef KIT_NUKEOPS_METAGAME
-#undef KIT_LORD_SINGULOTH
-#undef KIT_REVOLUTIONARY
-
-#undef KIT_JAMES_BOND
-#undef KIT_NINJA
-#undef KIT_DARK_LORD
-#undef KIT_WHITE_WHALE_HOLY_GRAIL
-#undef KIT_MAD_SCIENTIST
-#undef KIT_BEES
-#undef KIT_MR_FREEZE
-#undef KIT_TRAITOR_2006
-#undef KIT_DEAD_MONEY
-#undef KIT_SAM_FISHER
-#undef KIT_PROP_HUNT
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index d9ee1726b27..c598d3cf7cd 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -5,48 +5,13 @@
w_class = WEIGHT_CLASS_SMALL
resistance_flags = FLAMMABLE
slot_flags = ITEM_SLOT_ID
+ storage_type = /datum/storage/wallet
var/obj/item/card/id/front_id = null
var/list/combined_access
var/cached_flat_icon
var/overlay_icon_state = "wallet_overlay"
-/obj/item/storage/wallet/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.max_slots = 4
- atom_storage.set_holdable(list(
- /obj/item/stack/spacecash,
- /obj/item/holochip,
- /obj/item/card,
- /obj/item/cigarette,
- /obj/item/clothing/accessory/dogtag,
- /obj/item/coin,
- /obj/item/coupon,
- /obj/item/dice,
- /obj/item/disk,
- /obj/item/flashlight/pen,
- /obj/item/folder/biscuit,
- /obj/item/food/chococoin,
- /obj/item/implanter,
- /obj/item/laser_pointer,
- /obj/item/lighter,
- /obj/item/lipstick,
- /obj/item/match,
- /obj/item/paper,
- /obj/item/pen,
- /obj/item/photo,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/syringe,
- /obj/item/reagent_containers/applicator,
- /obj/item/screwdriver,
- /obj/item/seeds,
- /obj/item/spess_knife,
- /obj/item/stack/medical,
- /obj/item/stamp,
- /obj/item/toy/crayon),
- list(/obj/item/screwdriver/power))
-
/obj/item/storage/wallet/Exited(atom/movable/gone, direction)
. = ..()
if(isidcard(gone))
@@ -163,13 +128,19 @@
icon_state = "wallet"
/obj/item/storage/wallet/random/PopulateContents()
- new /obj/item/holochip(src, rand(5, 30))
new /obj/effect/spawner/random/entertainment/wallet_storage(src)
+ new /obj/item/holochip(src, rand(5, 30))
+
+ . = list()
+ for(var/obj/item as anything in src)
+ item.moveToNullspace()
+ . += item
///Used by the toilet fish source.
/obj/item/storage/wallet/money
desc = "It can hold a few small and personal things. This one reeks of toilet water."
/obj/item/storage/wallet/money/PopulateContents()
+ . = list()
for(var/iteration in 1 to pick(3, 4))
- new /obj/item/holochip(src, rand(50, 450))
+ . += new /obj/item/holochip(null, rand(50, 450))
diff --git a/code/game/objects/items/tcg/tcg.dm b/code/game/objects/items/tcg/tcg.dm
index 1f6c334c992..e3de6ddf3d9 100644
--- a/code/game/objects/items/tcg/tcg.dm
+++ b/code/game/objects/items/tcg/tcg.dm
@@ -427,12 +427,7 @@ GLOBAL_LIST_EMPTY(tcgcard_radial_choices)
resistance_flags = FLAMMABLE //burn your enemies' collections, for only you can Collect Them All!
w_class = WEIGHT_CLASS_SMALL
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
-
-/obj/item/storage/card_binder/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(/obj/item/tcgcard)
- atom_storage.max_total_storage = 120
- atom_storage.max_slots = 60
+ storage_type = /datum/storage/card_binder
///Returns a list of cards ids of card_cnt weighted by rarity from the pack's tables that have matching series, with gnt_cnt of the guaranteed table.
/obj/item/cardpack/proc/buildCardListWithRarity(card_cnt, rarity_cnt)
diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm
index 54935e170b6..ae90e9831ae 100644
--- a/code/game/objects/items/teleportation.dm
+++ b/code/game/objects/items/teleportation.dm
@@ -575,8 +575,10 @@
name = "syndicate teleporter kit"
/obj/item/storage/box/syndie_kit/syndicate_teleporter/PopulateContents()
- new /obj/item/syndicate_teleporter(src)
- new /obj/item/paper/syndicate_teleporter(src)
+ return list(
+ /obj/item/syndicate_teleporter,
+ /obj/item/paper/syndicate_teleporter,
+ )
/obj/effect/temp_visual/teleport_abductor/syndi_teleporter
duration = 5
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 2902bd72572..620b1c7d6e7 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1537,9 +1537,12 @@
name = "box of pierced realities"
desc = "A box containing toys resembling pierced realities."
-/obj/item/storage/box/heretic_box/PopulateContents()
+/obj/item/storage/box/heretic_box/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ . = list()
for(var/i in 1 to rand(1,4))
- new /obj/item/toy/reality_pierce(src)
+ . += /obj/item/toy/reality_pierce
/obj/item/toy/foamfinger
name = "foam finger"
diff --git a/code/game/objects/structures/janitor.dm b/code/game/objects/structures/janitor.dm
index a8df82e02b2..a79156a0305 100644
--- a/code/game/objects/structures/janitor.dm
+++ b/code/game/objects/structures/janitor.dm
@@ -200,7 +200,12 @@
if(istype(attacking_item, /obj/item/storage/bag/trash))
if(mybag)
balloon_alert(user, "already has \a [mybag]!")
- else if(user.transferItemToLoc(attacking_item, src))
+ return
+ var/obj/item/storage/bag/trash/bag = attacking_item
+ if(!bag.insertable)
+ balloon_alert(user, "cannot be inserted!")
+ return
+ if(user.transferItemToLoc(attacking_item, src))
balloon_alert(user, "attached [attacking_item]")
return
diff --git a/code/modules/admin/verbs/anonymousnames.dm b/code/modules/admin/verbs/anonymousnames.dm
index 21924288467..1c89082228c 100644
--- a/code/modules/admin/verbs/anonymousnames.dm
+++ b/code/modules/admin/verbs/anonymousnames.dm
@@ -196,51 +196,64 @@ GLOBAL_DATUM(current_anonymous_theme, /datum/anonymous_theme)
/obj/item/storage/box/wizard_kit
name = "Generic Wizard Cosplay Kit"
+ storage_type = /datum/storage/box/wizard
/obj/item/storage/box/wizard_kit/PopulateContents()
- new /obj/item/clothing/head/wizard(src)
- new /obj/item/clothing/suit/wizrobe(src)
- new /obj/item/clothing/shoes/sandal(src)
+ return list(
+ /obj/item/clothing/head/wizard,
+ /obj/item/clothing/suit/wizrobe,
+ /obj/item/clothing/shoes/sandal,
+ )
/obj/item/storage/box/wizard_kit/red
name = "Evocation Wizard Cosplay Kit"
/obj/item/storage/box/wizard_kit/red/PopulateContents()
- new /obj/item/clothing/head/wizard/red(src)
- new /obj/item/clothing/suit/wizrobe/red(src)
- new /obj/item/clothing/shoes/sandal(src)
+ return list(
+ /obj/item/clothing/head/wizard/red,
+ /obj/item/clothing/suit/wizrobe/red,
+ /obj/item/clothing/shoes/sandal,
+ )
/obj/item/storage/box/wizard_kit/yellow
name = "Translocation Wizard Cosplay Kit"
/obj/item/storage/box/wizard_kit/yellow/PopulateContents()
- new /obj/item/clothing/head/wizard/yellow(src)
- new /obj/item/clothing/suit/wizrobe/yellow(src)
- new /obj/item/clothing/shoes/sandal(src)
+ return list(
+ /obj/item/clothing/head/wizard/yellow,
+ /obj/item/clothing/suit/wizrobe/yellow,
+ /obj/item/clothing/shoes/sandal,
+ )
/obj/item/storage/box/wizard_kit/magusred
name = "Conjuration Wizard Cosplay Kit"
-/obj/item/storage/box/wizard_kit/yellow/PopulateContents()
- new /obj/item/clothing/head/wizard/magus(src)
- new /obj/item/clothing/suit/wizrobe/magusred(src)
- new /obj/item/clothing/shoes/sandal(src)
+/obj/item/storage/box/wizard_kit/magusred/PopulateContents()
+ return list(
+ /obj/item/clothing/head/wizard/magus,
+ /obj/item/clothing/suit/wizrobe/magusred,
+ /obj/item/clothing/shoes/sandal,
+ )
/obj/item/storage/box/wizard_kit/magusblue
name = "Transmutation Wizard Cosplay Kit"
-/obj/item/storage/box/wizard_kit/yellow/PopulateContents()
- new /obj/item/clothing/head/wizard/magus(src)
- new /obj/item/clothing/suit/wizrobe/magusblue(src)
- new /obj/item/clothing/shoes/sandal(src)
+/obj/item/storage/box/wizard_kit/magusblue/PopulateContents()
+ return list(
+ /obj/item/clothing/head/wizard/magus,
+ /obj/item/clothing/suit/wizrobe/magusblue,
+ /obj/item/clothing/shoes/sandal,
+ )
/obj/item/storage/box/wizard_kit/black
name = "Necromancy Wizard Cosplay Kit"
/obj/item/storage/box/wizard_kit/black/PopulateContents()
- new /obj/item/clothing/head/wizard/black(src)
- new /obj/item/clothing/suit/wizrobe/black(src)
- new /obj/item/clothing/shoes/sandal(src)
+ return list(
+ /obj/item/clothing/head/wizard/black,
+ /obj/item/clothing/suit/wizrobe/black,
+ /obj/item/clothing/shoes/sandal,
+ )
/datum/anonymous_theme/spider_clan
name = "Spider Clan"
diff --git a/code/modules/antagonists/heretic/items/unfathomable_curio.dm b/code/modules/antagonists/heretic/items/unfathomable_curio.dm
index d5f09a1dc27..466e85de4c5 100644
--- a/code/modules/antagonists/heretic/items/unfathomable_curio.dm
+++ b/code/modules/antagonists/heretic/items/unfathomable_curio.dm
@@ -8,6 +8,8 @@
content_overlays = FALSE
drop_sound = 'sound/items/handling/toolbelt_drop.ogg'
pickup_sound = 'sound/items/handling/toolbelt_pickup.ogg'
+ storage_type = /datum/storage/unfathomable_curio_belt
+
//Vars used for the shield component
var/heretic_shield_icon = "unfathomable_shield"
var/max_charges = 1
@@ -17,24 +19,6 @@
/obj/item/storage/belt/unfathomable_curio/Initialize(mapload)
. = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 21
- atom_storage.set_holdable(list(
- /obj/item/ammo_box/strilka310/lionhunter,
- /obj/item/heretic_labyrinth_handbook,
- /obj/item/bodypart, // Bodyparts are often used in rituals.
- /obj/item/clothing/neck/eldritch_amulet,
- /obj/item/clothing/neck/heretic_focus,
- /obj/item/codex_cicatrix,
- /obj/item/eldritch_potion,
- /obj/item/food/grown/poppy, // Used to regain a Living Heart.
- /obj/item/food/grown/harebell, // Used to reroll targets
- /obj/item/melee/rune_carver,
- /obj/item/melee/sickly_blade,
- /obj/item/organ, // Organs are also often used in rituals.
- /obj/item/reagent_containers/cup/beaker/eldritch,
- /obj/item/stack/sheet/glass, // Glass is often used by moon heretics
- ))
AddComponent(/datum/component/shielded, max_charges = max_charges, recharge_start_delay = recharge_start_delay, charge_increment_delay = charge_increment_delay, \
charge_recovery = charge_recovery, shield_icon = heretic_shield_icon, run_hit_callback = CALLBACK(src, PROC_REF(shield_damaged)))
diff --git a/code/modules/antagonists/traitor/contractor/contractor_items.dm b/code/modules/antagonists/traitor/contractor/contractor_items.dm
index 90c495358f2..12a6eb214c2 100644
--- a/code/modules/antagonists/traitor/contractor/contractor_items.dm
+++ b/code/modules/antagonists/traitor/contractor/contractor_items.dm
@@ -12,9 +12,13 @@
icon_state = "syndiebox"
illustration = "writing_syndie"
-/obj/item/storage/box/contractor/fulton_extraction/PopulateContents()
- new /obj/item/extraction_pack/syndicate(src)
- new /obj/item/fulton_core(src)
+/obj/item/storage/box/contractor/fulton_extraction/PopulateContents(datum/storage_config/config)
+ config.compute_max_item_weight = TRUE
+
+ return list(
+ /obj/item/extraction_pack/syndicate,
+ /obj/item/fulton_core,
+ )
/obj/item/paper/contractor_guide
name = "Contractor Guide"
diff --git a/code/modules/bitrunning/objects/gimmick_disks/_gimmick_disk.dm b/code/modules/bitrunning/objects/gimmick_disks/_gimmick_disk.dm
index 2580d8620c7..a43f07c4688 100644
--- a/code/modules/bitrunning/objects/gimmick_disks/_gimmick_disk.dm
+++ b/code/modules/bitrunning/objects/gimmick_disks/_gimmick_disk.dm
@@ -112,4 +112,4 @@
inhand_icon_state = "sec-case"
/obj/item/storage/briefcase/secure/digital_storage/PopulateContents()
- return
+ return NONE
diff --git a/code/modules/bitrunning/objects/gimmick_disks/dungeon_disk.dm b/code/modules/bitrunning/objects/gimmick_disks/dungeon_disk.dm
index 559c7f022df..8210a77670f 100644
--- a/code/modules/bitrunning/objects/gimmick_disks/dungeon_disk.dm
+++ b/code/modules/bitrunning/objects/gimmick_disks/dungeon_disk.dm
@@ -110,11 +110,13 @@
illustration = "beaker"
/obj/item/storage/box/alchemist_basic_chems/PopulateContents()
+ . = list()
+
for(var/i in 1 to 7)
if(prob(1))
- new /obj/item/reagent_containers/cup/glass/coffee(src)
+ . += /obj/item/reagent_containers/cup/glass/coffee
continue
- new /obj/item/reagent_containers/cup/bottle/alchemist_basic(src)
+ . += /obj/item/reagent_containers/cup/bottle/alchemist_basic
/obj/item/storage/box/alchemist_random_chems
name = "box of potions"
@@ -123,25 +125,28 @@
illustration = "beaker"
/obj/item/storage/box/alchemist_random_chems/PopulateContents()
+ . = list()
+
for(var/i in 1 to 7)
if(prob(1))
- new /obj/item/reagent_containers/cup/glass/coffee(src)
+ . += /obj/item/reagent_containers/cup/glass/coffee
continue
- new /obj/item/reagent_containers/cup/bottle/alchemist_random(src)
+ . += /obj/item/reagent_containers/cup/bottle/alchemist_random
/obj/item/storage/box/alchemist_chemistry_kit
name = "box of alchemy tools"
desc = "Contains everything needed for the up and coming chemistry student to enact hazardous chemical mishaps in the comfort of their own home."
/obj/item/storage/box/alchemist_chemistry_kit/PopulateContents()
- new /obj/item/reagent_containers/cup/mortar(src)
- new /obj/item/pestle(src)
- new /obj/item/lighter/skull(src)
- new /obj/item/ph_booklet(src)
- new /obj/item/thermometer(src)
- new /obj/item/storage/test_tube_rack/full(src)
- new /obj/item/reagent_containers/cup/glass/coffee(src)
-
+ return list(
+ /obj/item/reagent_containers/cup/mortar,
+ /obj/item/pestle,
+ /obj/item/lighter/skull,
+ /obj/item/ph_booklet,
+ /obj/item/thermometer,
+ /obj/item/storage/test_tube_rack/full,
+ /obj/item/reagent_containers/cup/glass/coffee,
+ )
/datum/bitrunning_gimmick/rogue
name = "Rogue"
@@ -173,10 +178,11 @@
name = "fannypack of ULTIMATE DESPAIR"
/obj/item/storage/belt/fannypack/black/rogue/PopulateContents()
- new /obj/item/food/drug/saturnx(src)
- new /obj/item/reagent_containers/cup/blastoff_ampoule(src)
- new /obj/item/reagent_containers/hypospray/medipen/methamphetamine(src)
-
+ return list(
+ /obj/item/food/drug/saturnx,
+ /obj/item/reagent_containers/cup/blastoff_ampoule,
+ /obj/item/reagent_containers/hypospray/medipen/methamphetamine,
+ )
/datum/bitrunning_gimmick/healer
name = "Healer"
diff --git a/code/modules/bitrunning/objects/gimmick_disks/sports_disk.dm b/code/modules/bitrunning/objects/gimmick_disks/sports_disk.dm
index 6be07b53d58..397a4c6aba6 100644
--- a/code/modules/bitrunning/objects/gimmick_disks/sports_disk.dm
+++ b/code/modules/bitrunning/objects/gimmick_disks/sports_disk.dm
@@ -50,13 +50,13 @@
/obj/item/reagent_containers/cup/soda_cans/space_mountain_wind = 50,
/obj/item/reagent_containers/cup/soda_cans/monkey_energy = 30,
/obj/item/reagent_containers/cup/soda_cans/volt_energy = 15,
- /obj/item/reagent_containers/cup/soda_cans/thirteenloko = 5,
+ /obj/item/reagent_containers/cup/soda_cans/thirteenloko = 5,
)
/obj/item/storage/cans/sixenergydrink/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- var/obj/item/chosen_energy_drink = pick_weight(energy_drink_options)
- new chosen_energy_drink(src)
+ . += pick_weight(energy_drink_options)
/datum/bitrunning_gimmick/archer
@@ -70,23 +70,6 @@
/obj/item/ammo_casing/arrow/holy/blazing,
)
-/obj/item/storage/bag/quiver/endless
- name = "endless quiver"
- desc = "Holds arrows for your bow. A deep digital void is contained within."
- max_slots = 1
-
-/obj/item/storage/bag/quiver/endless/Initialize(mapload)
- . = ..()
- RegisterSignal(src, COMSIG_ATOM_EXITED, PROC_REF(handle_removed))
-
-/obj/item/storage/bag/quiver/endless/PopulateContents()
- . = ..()
- new arrow_path(src)
-
-/obj/item/storage/bag/quiver/endless/proc/handle_removed(datum/source, obj/item/gone)
- new arrow_path(src)
-
-
/datum/bitrunning_gimmick/fisher
name = "Fisher"
@@ -125,13 +108,13 @@
/obj/item/reagent_containers/cup/soda_cans/space_mountain_wind = 15,
/obj/item/reagent_containers/cup/soda_cans/monkey_energy = 15,
/obj/item/reagent_containers/cup/soda_cans/volt_energy = 10,
- /obj/item/reagent_containers/cup/soda_cans/thirteenloko = 5,
+ /obj/item/reagent_containers/cup/soda_cans/thirteenloko = 5,
)
/obj/item/storage/cans/sixgamerdrink/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- var/obj/item/chosen_gamer_drink = pick_weight(gamer_drink_options)
- new chosen_gamer_drink(src)
+ . += pick_weight(gamer_drink_options)
/obj/item/modular_computer/laptop/gamer
desc = "A high-end laptop often used for metagaming."
diff --git a/code/modules/bitrunning/objects/loot_box.dm b/code/modules/bitrunning/objects/loot_box.dm
index e142a3e93a4..8575008f0b3 100644
--- a/code/modules/bitrunning/objects/loot_box.dm
+++ b/code/modules/bitrunning/objects/loot_box.dm
@@ -23,6 +23,8 @@
/obj/item/storage/lockbox/bitrunning/decrypted
name = "decrypted curiosity"
desc = "Compiled from the virtual domain. An extra reward of a successful bitrunner."
+ storage_type = /datum/storage/lockbox/bitrunning
+
/// What virtual domain did we come from.
var/datum/lazy_template/virtual_domain/source_domain
@@ -42,13 +44,8 @@
source_domain = completed_domain
. = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_slots = 1
- atom_storage.max_total_storage = 3
- atom_storage.locked = STORAGE_NOT_LOCKED
- icon_state = icon_closed
+
playsound(src, 'sound/effects/magic/blink.ogg', 50, TRUE)
/obj/item/storage/lockbox/bitrunning/decrypted/PopulateContents()
- var/choice = SSbitrunning.pick_secondary_loot(source_domain)
- new choice(src)
+ return SSbitrunning.pick_secondary_loot(source_domain)
diff --git a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
index b2aea379212..83a875332e7 100644
--- a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
+++ b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
@@ -32,8 +32,6 @@ do { \
actions_types = list(/datum/action/item_action/chameleon/change/jumpsuit)
action_slots = ALL
-/obj/item/clothing/under/chameleon/broken
-
/obj/item/clothing/under/chameleon/broken/Initialize(mapload)
. = ..()
BREAK_CHAMELEON_ACTION(src)
@@ -280,12 +278,7 @@ do { \
desc = "Holds tools."
actions_types = list(/datum/action/item_action/chameleon/change/belt)
action_slots = ALL
-
-/obj/item/storage/belt/chameleon/Initialize(mapload)
- . = ..()
- atom_storage.silent = TRUE
-
-/obj/item/storage/belt/chameleon/broken
+ storage_type = /datum/storage/chameleon_belt
/obj/item/storage/belt/chameleon/broken/Initialize(mapload)
. = ..()
@@ -297,7 +290,6 @@ do { \
actions_types = list(/datum/action/item_action/chameleon/change/headset)
action_slots = ALL
-/obj/item/radio/headset/chameleon/broken
/obj/item/radio/headset/chameleon/broken/Initialize(mapload)
. = ..()
@@ -309,8 +301,6 @@ do { \
actions_types = list(/datum/action/item_action/chameleon/change/tablet)
action_slots = ALL
-/obj/item/modular_computer/pda/chameleon/broken
-
/obj/item/modular_computer/pda/chameleon/broken/Initialize(mapload)
. = ..()
BREAK_CHAMELEON_ACTION(src)
@@ -320,8 +310,6 @@ do { \
actions_types = list(/datum/action/item_action/chameleon/change/stamp)
action_slots = ALL
-/obj/item/stamp/chameleon/broken
-
/obj/item/stamp/chameleon/broken/Initialize(mapload)
. = ..()
BREAK_CHAMELEON_ACTION(src)
@@ -341,8 +329,6 @@ do { \
actions_types = list(/datum/action/item_action/chameleon/change/neck)
action_slots = ALL
-/obj/item/clothing/neck/chameleon/broken
-
/obj/item/clothing/neck/chameleon/broken/Initialize(mapload)
. = ..()
BREAK_CHAMELEON_ACTION(src)
diff --git a/code/modules/clothing/head/costume.dm b/code/modules/clothing/head/costume.dm
index a9a70101afb..9bec6127cec 100644
--- a/code/modules/clothing/head/costume.dm
+++ b/code/modules/clothing/head/costume.dm
@@ -208,3 +208,21 @@
desc = "A delicate hairpin normally paired with traditional clothing"
icon_state = "hairpin_fancy"
inhand_icon_state = "hairpin_fancy"
+
+/obj/item/clothing/head/costume/snakeeater
+ name = "strange bandana"
+ desc = "A bandana. It seems to have a little carp embroidered on the inside, as well as the kanji '魚'."
+ icon_state = "snake_eater"
+ inhand_icon_state = null
+ clothing_traits = list(TRAIT_FISH_EATER)
+
+/obj/item/clothing/head/costume/knight
+ name = "fake medieval helmet"
+ desc = "A classic metal helmet. Though, this one seems to be very obviously fake..."
+ icon = 'icons/obj/clothing/head/helmet.dmi'
+ worn_icon = 'icons/mob/clothing/head/helmet.dmi'
+ icon_state = "knight_green"
+ inhand_icon_state = "knight_helmet"
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT
+ flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
+ dog_fashion = null
diff --git a/code/modules/clothing/shoes/cowboy.dm b/code/modules/clothing/shoes/cowboy.dm
index 13f393c72ca..71505b9471d 100644
--- a/code/modules/clothing/shoes/cowboy.dm
+++ b/code/modules/clothing/shoes/cowboy.dm
@@ -18,9 +18,10 @@
/obj/item/clothing/shoes/cowboy/Initialize(mapload)
. = ..()
- create_storage(storage_type = /datum/storage/pockets/shoes)
+
if(prob(2)) //There's a snake in my boot
new /mob/living/basic/snake(src)
+ create_storage(storage_type = /datum/storage/pockets/shoes)
if(has_spurs)
LoadComponent(/datum/component/squeak, spur_sound, 50, falloff_exponent = 20)
AddElement(/datum/element/ignites_matches)
diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm
index 030d2e6c25a..54d8c4b1d9c 100644
--- a/code/modules/detectivework/evidence.dm
+++ b/code/modules/detectivework/evidence.dm
@@ -78,5 +78,6 @@
desc = "A box claiming to contain evidence bags."
/obj/item/storage/box/evidence/PopulateContents()
+ . = list()
for(var/i in 1 to 6)
- new /obj/item/evidencebag(src)
+ . += /obj/item/evidencebag
diff --git a/code/modules/events/holiday/easter.dm b/code/modules/events/holiday/easter.dm
index dad3f31ba89..07536ad297b 100644
--- a/code/modules/events/holiday/easter.dm
+++ b/code/modules/events/holiday/easter.dm
@@ -42,28 +42,6 @@
new /mob/living/basic/rabbit/easter/space(spawn_point.loc)
CHECK_TICK
-
-//Easter Baskets
-/obj/item/storage/basket/easter
- name = "Easter Basket"
-
-/obj/item/storage/basket/easter/Initialize(mapload)
- . = ..()
- atom_storage.set_holdable(list(/obj/item/food/egg, /obj/item/food/chocolateegg, /obj/item/food/boiledegg, /obj/item/surprise_egg))
-
-/obj/item/storage/basket/easter/proc/countEggs()
- cut_overlays()
- add_overlay("basket-grass")
- add_overlay("basket-egg[min(contents.len, 5)]")
-
-/obj/item/storage/basket/easter/Exited(atom/movable/gone, direction)
- . = ..()
- countEggs()
-
-/obj/item/storage/basket/easter/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs)
- . = ..()
- countEggs()
-
//Bunny Suit
/obj/item/clothing/head/costume/bunnyhead
name = "Easter Bunny head"
diff --git a/code/modules/events/shuttle_loan/shuttle_loan_items.dm b/code/modules/events/shuttle_loan/shuttle_loan_items.dm
index 14257a6a80b..824e8f06536 100644
--- a/code/modules/events/shuttle_loan/shuttle_loan_items.dm
+++ b/code/modules/events/shuttle_loan/shuttle_loan_items.dm
@@ -1,8 +1,10 @@
/obj/item/storage/belt/fannypack/yellow/bee_terrorist/PopulateContents()
- new /obj/item/grenade/c4 (src)
- new /obj/item/reagent_containers/applicator/pill/cyanide(src)
- new /obj/item/grenade/chem_grenade/facid(src)
+ return list(
+ /obj/item/grenade/c4,
+ /obj/item/reagent_containers/applicator/pill/cyanide,
+ /obj/item/grenade/chem_grenade/facid,
+ )
/obj/item/paper/fluff/bee_objectives
name = "Objectives of a Bee Liberation Front Operative"
diff --git a/code/modules/fishing/aquarium/aquarium_kit.dm b/code/modules/fishing/aquarium/aquarium_kit.dm
index 71be9a10f56..5768c843e59 100644
--- a/code/modules/fishing/aquarium/aquarium_kit.dm
+++ b/code/modules/fishing/aquarium/aquarium_kit.dm
@@ -39,7 +39,7 @@
if(fish_type)
var/obj/item/fish/spawned_fish = new fish_type(null)
spawned_fish.add_traits(list(TRAIT_NO_FISHING_ACHIEVEMENT, TRAIT_FISH_LOW_PRICE), INNATE_TRAIT)
- spawned_fish.forceMove(src) // trigger storage.handle_entered
+ return spawned_fish
/obj/item/storage/fish_case/proc/get_fish_type()
return
@@ -191,5 +191,4 @@
custom_price = PAYCHECK_LOWER
/obj/item/storage/box/aquarium_props/PopulateContents()
- for(var/prop_type in subtypesof(/obj/item/aquarium_prop))
- new prop_type(src)
+ return subtypesof(/obj/item/aquarium_prop)
diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm
index 47ee0e6c123..04d0c731f63 100644
--- a/code/modules/fishing/fishing_equipment.dm
+++ b/code/modules/fishing/fishing_equipment.dm
@@ -322,106 +322,6 @@
var/mob/living/living_target = target
living_target.apply_status_effect(/datum/status_effect/grouped/hooked/jaws, rod.fishing_line)
-/obj/item/storage/toolbox/fishing
- name = "fishing toolbox"
- desc = "Contains everything you need for your fishing trip."
- icon_state = "fishing"
- inhand_icon_state = "artistic_toolbox"
- material_flags = NONE
- custom_price = PAYCHECK_CREW * 3
- ///How much holding this affects fishing difficulty
- var/fishing_modifier = -4
-
-/obj/item/storage/toolbox/fishing/Initialize(mapload)
- . = ..()
- // Can hold fishing rod despite the size
- var/static/list/exception_cache = typecacheof(list(
- /obj/item/fishing_rod,
- ))
- atom_storage.exception_hold = exception_cache
- AddComponent(/datum/component/adjust_fishing_difficulty, fishing_modifier, ITEM_SLOT_HANDS)
-
-/obj/item/storage/toolbox/fishing/PopulateContents()
- new /obj/item/bait_can/worm(src)
- new /obj/item/fishing_rod/unslotted(src)
- new /obj/item/fishing_hook(src)
- new /obj/item/fishing_line(src)
- new /obj/item/paper/paperslip/fishing_tip(src)
-
-/obj/item/storage/toolbox/fishing/small
- name = "compact fishing toolbox"
- desc = "Contains everything you need for your fishing trip. Except for the bait."
- w_class = WEIGHT_CLASS_NORMAL
- force = 5
- throwforce = 5
-
-/obj/item/storage/toolbox/fishing/small/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL //It can still hold a fishing rod
-
-/obj/item/storage/toolbox/fishing/small/PopulateContents()
- new /obj/item/fishing_rod/unslotted(src)
- new /obj/item/fishing_hook(src)
- new /obj/item/fishing_line(src)
- new /obj/item/paper/paperslip/fishing_tip(src)
-
-/obj/item/storage/toolbox/fishing/master
- name = "super fishing toolbox"
- desc = "Contains (almost) EVERYTHING you need for your fishing trip."
- icon_state = "gold"
- inhand_icon_state = "toolbox_gold"
- fishing_modifier = -10
-
-/obj/item/storage/toolbox/fishing/master/PopulateContents()
- new /obj/item/fishing_rod/telescopic/master(src)
- new /obj/item/storage/box/fishing_hooks/master(src)
- new /obj/item/storage/box/fishing_lines/master(src)
- new /obj/item/bait_can/super_baits(src)
- new /obj/item/reagent_containers/cup/fish_feed(src)
- new /obj/item/aquarium_kit(src)
- new /obj/item/fish_analyzer(src)
-
-/obj/item/storage/box/fishing_hooks
- name = "fishing hook set"
- illustration = "fish"
- custom_price = PAYCHECK_CREW * 2
-
-/obj/item/storage/box/fishing_hooks/PopulateContents()
- new /obj/item/fishing_hook/magnet(src)
- new /obj/item/fishing_hook/shiny(src)
- new /obj/item/fishing_hook/weighted(src)
-
-/obj/item/storage/box/fishing_hooks/master
-
-/obj/item/storage/box/fishing_hooks/master/PopulateContents()
- . = ..()
- new /obj/item/fishing_hook/stabilized(src)
- new /obj/item/fishing_hook/jaws(src)
-
-/obj/item/storage/box/fishing_lines
- name = "fishing line set"
- illustration = "fish"
- custom_price = PAYCHECK_CREW * 2
-
-/obj/item/storage/box/fishing_lines/PopulateContents()
- new /obj/item/fishing_line/bouncy(src)
- new /obj/item/fishing_line/reinforced(src)
- new /obj/item/fishing_line/cloaked(src)
-
-/obj/item/storage/box/fishing_lines/master
-
-/obj/item/storage/box/fishing_lines/master/PopulateContents()
- . = ..()
- new /obj/item/fishing_line/auto_reel(src)
-
-/obj/item/storage/box/fish_debug
- name = "box full of fish"
- illustration = "fish"
-
-/obj/item/storage/box/fish_debug/PopulateContents()
- for(var/fish_type in subtypesof(/obj/item/fish))
- new fish_type(src)
-
///Used to give the average player info about fishing stuff that's unknown to many.
/obj/item/paper/paperslip/fishing_tip
name = "fishing tip"
@@ -438,11 +338,13 @@
illustration = "fish"
/obj/item/storage/box/fish_revival_kit/PopulateContents()
- new /obj/item/lazarus_injector(src)
- new /obj/item/reagent_containers/cup/bottle/fishy_reagent(src)
- new /obj/item/reagent_containers/cup(src) //to splash the reagents on the fish.
- new /obj/item/storage/fish_case(src)
- new /obj/item/storage/fish_case(src)
+ return list(
+ /obj/item/lazarus_injector,
+ /obj/item/reagent_containers/cup/bottle/fishy_reagent,
+ /obj/item/reagent_containers/cup, //to splash the reagents on the fish.
+ /obj/item/storage/fish_case,
+ /obj/item/storage/fish_case,
+ )
/obj/item/storage/box/fishing_lures
name = "fishing lures set"
@@ -451,16 +353,11 @@
foldable_result = null
illustration = "fish"
custom_price = PAYCHECK_CREW * 9
+ storage_type = /datum/storage/box/fishing_lures
/obj/item/storage/box/fishing_lures/PopulateContents()
- new /obj/item/paper/lures_instructions(src)
- var/list/typesof = typesof(/obj/item/fishing_lure)
- for(var/type in typesof)
- new type (src)
- atom_storage.set_holdable(/obj/item/fishing_lure) //can only hold lures
- //adds an extra slot, so we can put back the lures even if we didn't take out the instructions.
- atom_storage.max_slots = length(typesof) + 1
- atom_storage.max_total_storage = WEIGHT_CLASS_SMALL * (atom_storage.max_slots + 1)
+ . = typesof(/obj/item/fishing_lure)
+ . += /obj/item/paper/lures_instructions
/obj/item/paper/lures_instructions
name = "instructions paper"
@@ -580,43 +477,3 @@
#undef MAGNET_HOOK_BONUS_MULTIPLIER
#undef RESCUE_HOOK_FISH_MULTIPLIER
-
-/obj/item/storage/bag/fishing
- name = "fishing bag"
- desc = "A vibrant bag for storing caught fish."
- icon = 'icons/obj/fishing.dmi'
- icon_state = "fishing_bag"
- worn_icon_state = "fishing_bag"
- resistance_flags = FLAMMABLE
- custom_price = PAYCHECK_CREW * 3
- ///How much holding this affects fishing difficulty
- var/fishing_modifier = -2
-
-/obj/item/storage/bag/fishing/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL
- atom_storage.max_total_storage = 24 // Up to 8 normal fish
- atom_storage.max_slots = 21
- atom_storage.set_holdable(/obj/item/fish)
- AddComponent(/datum/component/adjust_fishing_difficulty, fishing_modifier, ITEM_SLOT_HANDS)
-
-/obj/item/storage/bag/fishing/carpskin
- name = "carpskin fishing bag"
- desc = "A dapper fishing bag made from carpskin. You can store quite a lot of fishing gear in the small pockets formed by larger scales."
- icon_state = "fishing_bag_carpskin"
- worn_icon_state = "fishing_bag_carpskin"
- resistance_flags = ACID_PROOF
- storage_type = /datum/storage/carpskin_bag
- fishing_modifier = -4
-
-/obj/item/storage/bag/fishing/carpskin/Initialize(mapload)
- . = ..()
- atom_storage.max_total_storage = 42 // Up to 14 normal fish, but we're assuming that you'll be storing a bunch of gear as well
- atom_storage.set_holdable(list(
- /obj/item/fish,
- /obj/item/fishing_line,
- /obj/item/fishing_hook,
- /obj/item/fishing_lure,
- /obj/item/fish_analyzer,
- /obj/item/bait_can,
- ))
diff --git a/code/modules/food_and_drinks/machinery/coffeemaker.dm b/code/modules/food_and_drinks/machinery/coffeemaker.dm
index 489a548cc56..7bec8fb4029 100644
--- a/code/modules/food_and_drinks/machinery/coffeemaker.dm
+++ b/code/modules/food_and_drinks/machinery/coffeemaker.dm
@@ -492,11 +492,8 @@
open_status = FANCY_CONTAINER_ALWAYS_OPEN
spawn_type = /obj/item/coffee_cartridge
spawn_count = 1
+ storage_type = /datum/storage/coffee_cart_rack
-/obj/item/storage/fancy/coffee_cart_rack/Initialize(mapload)
- . = ..()
- atom_storage.max_slots = 4
- atom_storage.set_holdable(/obj/item/coffee_cartridge)
/*
* impressa coffee maker
diff --git a/code/modules/mapfluff/ruins/spaceruin_code/forgottenship.dm b/code/modules/mapfluff/ruins/spaceruin_code/forgottenship.dm
index bc36823ebc8..5ea1e1d2b7d 100644
--- a/code/modules/mapfluff/ruins/spaceruin_code/forgottenship.dm
+++ b/code/modules/mapfluff/ruins/spaceruin_code/forgottenship.dm
@@ -94,8 +94,9 @@ GLOBAL_VAR_INIT(fscpassword, generate_password())
desc = "A box full of special syndicate firing pins which allow only syndicate operatives to use weapons with those firing pins."
/obj/item/storage/box/firingpins/syndicate/PopulateContents()
+ . = list()
for(var/i in 1 to 5)
- new /obj/item/firing_pin/implant/pindicate(src)
+ . += /obj/item/firing_pin/implant/pindicate
/////////// AI Laws
diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm
deleted file mode 100644
index 3a7687ebebf..00000000000
--- a/code/modules/mining/money_bag.dm
+++ /dev/null
@@ -1,37 +0,0 @@
-/*****************************Money bag********************************/
-
-/obj/item/storage/bag/money
- name = "money bag"
- desc = "A bag for storing your profits."
- icon_state = "moneybag"
- worn_icon_state = "moneybag"
- force = 10
- throwforce = 0
- resistance_flags = FLAMMABLE
- max_integrity = 100
- w_class = WEIGHT_CLASS_BULKY
-
-/obj/item/storage/bag/money/Initialize(mapload)
- . = ..()
- if(prob(20))
- icon_state = "moneybagalt"
- atom_storage.max_slots = 40
- atom_storage.max_specific_storage = 40
- atom_storage.set_holdable(list(/obj/item/coin, /obj/item/stack/spacecash, /obj/item/holochip))
-
-/obj/item/storage/bag/money/vault/PopulateContents()
- new /obj/item/coin/silver(src)
- new /obj/item/coin/silver(src)
- new /obj/item/coin/silver(src)
- new /obj/item/coin/silver(src)
- new /obj/item/coin/gold(src)
- new /obj/item/coin/gold(src)
- new /obj/item/coin/adamantine(src)
-
-///Used in the dutchmen pirate shuttle.
-/obj/item/storage/bag/money/dutchmen/PopulateContents()
- for(var/iteration in 1 to 9)
- new /obj/item/coin/silver/doubloon(src)
- for(var/iteration in 1 to 9)
- new /obj/item/coin/gold/doubloon(src)
- new /obj/item/coin/adamantine/doubloon(src)
diff --git a/code/modules/mob/living/basic/drone/drone_tools.dm b/code/modules/mob/living/basic/drone/drone_tools.dm
index dfb05a8d3a9..5dbcb3f0816 100644
--- a/code/modules/mob/living/basic/drone/drone_tools.dm
+++ b/code/modules/mob/living/basic/drone/drone_tools.dm
@@ -14,20 +14,22 @@
/obj/item/storage/drone_tools/PopulateContents()
var/list/builtintools = list()
- builtintools += new /obj/item/crowbar/drone(src)
- builtintools += new /obj/item/screwdriver/drone(src)
- builtintools += new /obj/item/wrench/drone(src)
- builtintools += new /obj/item/weldingtool/drone(src)
- builtintools += new /obj/item/wirecutters/drone(src)
- builtintools += new /obj/item/multitool/drone(src)
- builtintools += new /obj/item/pipe_dispenser/drone(src)
- builtintools += new /obj/item/t_scanner/drone(src)
- builtintools += new /obj/item/analyzer/drone(src)
- builtintools += new /obj/item/soap/drone(src)
+ builtintools += new /obj/item/crowbar/drone(null)
+ builtintools += new /obj/item/screwdriver/drone(null)
+ builtintools += new /obj/item/wrench/drone(null)
+ builtintools += new /obj/item/weldingtool/drone(null)
+ builtintools += new /obj/item/wirecutters/drone(null)
+ builtintools += new /obj/item/multitool/drone(null)
+ builtintools += new /obj/item/pipe_dispenser/drone(null)
+ builtintools += new /obj/item/t_scanner/drone(null)
+ builtintools += new /obj/item/analyzer/drone(null)
+ builtintools += new /obj/item/soap/drone(null)
for(var/obj/item/tool as anything in builtintools)
tool.AddComponent(/datum/component/holderloving, src)
+ return builtintools
+
/obj/item/crowbar/drone
name = "built-in crowbar"
desc = "A crowbar built into your chassis."
diff --git a/code/modules/projectiles/guns/ballistic/bows/bow_quivers.dm b/code/modules/projectiles/guns/ballistic/bows/bow_quivers.dm
deleted file mode 100644
index a3de2f4b2fe..00000000000
--- a/code/modules/projectiles/guns/ballistic/bows/bow_quivers.dm
+++ /dev/null
@@ -1,40 +0,0 @@
-
-/obj/item/storage/bag/quiver
- name = "quiver"
- desc = "Holds arrows for your bow. Good, because while pocketing arrows is possible, it surely can't be pleasant."
- icon = 'icons/obj/weapons/bows/quivers.dmi'
- icon_state = "quiver"
- inhand_icon_state = null
- worn_icon_state = "harpoon_quiver"
- /// type of arrow the quivel should hold
- var/arrow_path = /obj/item/ammo_casing/arrow
- var/max_slots = 40
-
-/obj/item/storage/bag/quiver/Initialize(mapload)
- . = ..()
- atom_storage.numerical_stacking = TRUE
- atom_storage.max_specific_storage = WEIGHT_CLASS_TINY
- atom_storage.max_slots = max_slots
- atom_storage.max_total_storage = 100
- atom_storage.set_holdable(/obj/item/ammo_casing/arrow)
-
-/obj/item/storage/bag/quiver/lesser
- max_slots = 10
-
-/obj/item/storage/bag/quiver/full/PopulateContents()
- . = ..()
- for(var/i in 1 to 10)
- new arrow_path(src)
-
-/obj/item/storage/bag/quiver/holy
- name = "divine quiver"
- desc = "Holds arrows for your divine bow, where they wait to find their target."
- icon_state = "holyquiver"
- inhand_icon_state = "holyquiver"
- worn_icon_state = "holyquiver"
- arrow_path = /obj/item/ammo_casing/arrow/holy
-
-/obj/item/storage/bag/quiver/holy/PopulateContents()
- . = ..()
- for(var/i in 1 to 10)
- new arrow_path(src)
diff --git a/code/modules/projectiles/guns/energy/dueling.dm b/code/modules/projectiles/guns/energy/dueling.dm
index 95707874e72..c2ec48d1f74 100644
--- a/code/modules/projectiles/guns/energy/dueling.dm
+++ b/code/modules/projectiles/guns/energy/dueling.dm
@@ -352,34 +352,6 @@
B.dismember()
qdel(B)
-//Storage case.
-/obj/item/storage/lockbox/dueling
- name = "dueling pistol case"
- desc = "Let's solve this like gentlespacemen."
- icon_state = "medalbox+l"
- inhand_icon_state = "syringe_kit"
- lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
- w_class = WEIGHT_CLASS_NORMAL
- req_access = list(ACCESS_CAPTAIN)
- icon_locked = "medalbox+l"
- icon_closed = "medalbox"
- icon_broken = "medalbox+b"
- base_icon_state = "medalbox"
- icon_open = "medalboxopen"
-
-/obj/item/storage/lockbox/dueling/Initialize(mapload)
- . = ..()
- atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL
- atom_storage.max_slots = 2
- atom_storage.set_holdable(/obj/item/gun/energy/dueling)
-
-/obj/item/storage/lockbox/dueling/PopulateContents()
- . = ..()
- var/obj/item/gun/energy/dueling/gun_A = new(src)
- var/obj/item/gun/energy/dueling/gun_B = new(src)
- new /datum/duel(gun_A, gun_B)
-
#undef DUEL_IDLE
#undef DUEL_PREPARATION
#undef DUEL_READY
diff --git a/code/modules/research/part_replacer.dm b/code/modules/research/part_replacer.dm
index 53831026444..086db3bc2d3 100644
--- a/code/modules/research/part_replacer.dm
+++ b/code/modules/research/part_replacer.dm
@@ -114,49 +114,54 @@
//RPED with tiered contents
/obj/item/storage/part_replacer/bluespace/tier1/PopulateContents()
- for(var/i in 1 to 10)
- new /obj/item/stock_parts/capacitor(src)
- new /obj/item/stock_parts/scanning_module(src)
- new /obj/item/stock_parts/servo(src)
- new /obj/item/stock_parts/micro_laser(src)
- new /obj/item/stock_parts/matter_bin(src)
- new /obj/item/stock_parts/power_store/cell/high(src)
+ return flatten_quantified_list(list(
+ /obj/item/stock_parts/capacitor = 10,
+ /obj/item/stock_parts/scanning_module = 10,
+ /obj/item/stock_parts/servo = 10,
+ /obj/item/stock_parts/micro_laser = 10,
+ /obj/item/stock_parts/matter_bin = 10,
+ /obj/item/stock_parts/power_store/cell/high = 10,
+ ))
/obj/item/storage/part_replacer/bluespace/tier2/PopulateContents()
- for(var/i in 1 to 10)
- new /obj/item/stock_parts/capacitor/adv(src)
- new /obj/item/stock_parts/scanning_module/adv(src)
- new /obj/item/stock_parts/servo/nano(src)
- new /obj/item/stock_parts/micro_laser/high(src)
- new /obj/item/stock_parts/matter_bin/adv(src)
- new /obj/item/stock_parts/power_store/cell/super(src)
+ return flatten_quantified_list(list(
+ /obj/item/stock_parts/capacitor/adv = 10,
+ /obj/item/stock_parts/scanning_module/adv = 10,
+ /obj/item/stock_parts/servo/nano = 10,
+ /obj/item/stock_parts/micro_laser/high = 10,
+ /obj/item/stock_parts/matter_bin/adv = 10,
+ /obj/item/stock_parts/power_store/cell/super = 10,
+ ))
/obj/item/storage/part_replacer/bluespace/tier3/PopulateContents()
- for(var/i in 1 to 10)
- new /obj/item/stock_parts/capacitor/super(src)
- new /obj/item/stock_parts/scanning_module/phasic(src)
- new /obj/item/stock_parts/servo/pico(src)
- new /obj/item/stock_parts/micro_laser/ultra(src)
- new /obj/item/stock_parts/matter_bin/super(src)
- new /obj/item/stock_parts/power_store/cell/hyper(src)
+ return flatten_quantified_list(list(
+ /obj/item/stock_parts/capacitor/super = 10,
+ /obj/item/stock_parts/scanning_module/phasic = 10,
+ /obj/item/stock_parts/servo/pico = 10,
+ /obj/item/stock_parts/micro_laser/ultra = 10,
+ /obj/item/stock_parts/matter_bin/super = 10,
+ /obj/item/stock_parts/power_store/cell/hyper = 10,
+ ))
/obj/item/storage/part_replacer/bluespace/tier4/PopulateContents()
- for(var/i in 1 to 10)
- new /obj/item/stock_parts/capacitor/quadratic(src)
- new /obj/item/stock_parts/scanning_module/triphasic(src)
- new /obj/item/stock_parts/servo/femto(src)
- new /obj/item/stock_parts/micro_laser/quadultra(src)
- new /obj/item/stock_parts/matter_bin/bluespace(src)
- new /obj/item/stock_parts/power_store/cell/bluespace(src)
+ return flatten_quantified_list(list(
+ /obj/item/stock_parts/capacitor/quadratic = 10,
+ /obj/item/stock_parts/scanning_module/triphasic = 10,
+ /obj/item/stock_parts/servo/femto = 10,
+ /obj/item/stock_parts/micro_laser/quadultra = 10,
+ /obj/item/stock_parts/matter_bin/bluespace = 10,
+ /obj/item/stock_parts/power_store/cell/bluespace = 10,
+ ))
//used in a cargo crate
/obj/item/storage/part_replacer/cargo/PopulateContents()
- for(var/i in 1 to 10)
- new /obj/item/stock_parts/capacitor(src)
- new /obj/item/stock_parts/scanning_module(src)
- new /obj/item/stock_parts/servo(src)
- new /obj/item/stock_parts/micro_laser(src)
- new /obj/item/stock_parts/matter_bin(src)
+ return flatten_quantified_list(list(
+ /obj/item/stock_parts/capacitor = 10,
+ /obj/item/stock_parts/scanning_module = 10,
+ /obj/item/stock_parts/servo = 10,
+ /obj/item/stock_parts/micro_laser = 10,
+ /obj/item/stock_parts/matter_bin = 10,
+ ))
///Cyborg variant
/obj/item/storage/part_replacer/cyborg
diff --git a/code/modules/shuttle/mobile_port/variants/emergency/pods.dm b/code/modules/shuttle/mobile_port/variants/emergency/pods.dm
index 40a4cc16cdb..51aa25c1b43 100644
--- a/code/modules/shuttle/mobile_port/variants/emergency/pods.dm
+++ b/code/modules/shuttle/mobile_port/variants/emergency/pods.dm
@@ -127,57 +127,6 @@
name = "emergency disembarkation tool"
desc = "For extracting yourself from rough landings."
-/datum/storage/pod
- max_slots = 14
- max_total_storage = WEIGHT_CLASS_BULKY * 14
- /// If TRUE, we unlock regardless of security level
- var/always_unlocked = FALSE
-
-/datum/storage/pod/open_storage(mob/to_show)
- if(isliving(to_show) && SSsecurity_level.get_current_level_as_number() < SEC_LEVEL_RED)
- to_chat(to_show, span_warning("The storage unit will only unlock during a Red or Delta security alert."))
- return FALSE
- return ..()
-
-/datum/storage/pod/New(atom/parent, max_slots, max_specific_storage, max_total_storage)
- . = ..()
- // all of these are a type below what actually spawn with
- // (IE all space suits instead of just the emergency ones)
- // because an enterprising traitor might be able to hide things,
- // like their syndicate toolbox or softsuit. may be fun?
- var/static/list/exception_cache = typecacheof(list(
- /obj/item/clothing/suit/space,
- /obj/item/pickaxe,
- /obj/item/storage/toolbox,
- ))
- src.exception_hold = exception_cache
- RegisterSignal(SSsecurity_level, COMSIG_SECURITY_LEVEL_CHANGED, PROC_REF(update_lock))
- update_lock(new_level = SSsecurity_level.get_current_level_as_number())
-
-/datum/storage/pod/set_parent(atom/new_parent)
- . = ..()
- RegisterSignal(parent, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, PROC_REF(pod_launch))
-
-/datum/storage/pod/proc/update_lock(datum/source, new_level)
- SIGNAL_HANDLER
- if(always_unlocked)
- return
-
- locked = (new_level < SEC_LEVEL_RED) ? STORAGE_FULLY_LOCKED : STORAGE_NOT_LOCKED
- parent.update_appearance(UPDATE_ICON_STATE)
- if(locked) // future todo : make `locked` a setter so this behavior can be built in (avoids exploits)
- close_all()
-
-/datum/storage/pod/proc/pod_launch(datum/source, turf/old_turf)
- SIGNAL_HANDLER
- // This check is to ignore the movement of the shuttle from the transit level to the station as it is loaded in.
- if(old_turf && is_reserved_level(old_turf.z))
- return
- // If the pod was launched, the storage will always open.
- always_unlocked = TRUE
- locked = STORAGE_NOT_LOCKED
- parent.update_appearance(UPDATE_ICON_STATE)
-
/obj/item/storage/pod
name = "emergency space suits"
desc = "A wall mounted safe containing space suits. Will only open in emergencies."
@@ -187,6 +136,13 @@
icon_state = "wall_safe_locked"
storage_type = /datum/storage/pod
+/obj/item/storage/pod/Initialize(mapload)
+ . = ..()
+
+ var/datum/storage/pod/storage = atom_storage
+
+ storage.update_lock(new_level = SSsecurity_level.get_current_level_as_number())
+
/obj/item/storage/pod/update_icon_state()
. = ..()
icon_state = "wall_safe[atom_storage?.locked ? "_locked" : ""]"
@@ -194,17 +150,13 @@
MAPPING_DIRECTIONAL_HELPERS(/obj/item/storage/pod, 32)
/obj/item/storage/pod/PopulateContents()
- new /obj/item/clothing/head/helmet/space/orange(src)
- new /obj/item/clothing/head/helmet/space/orange(src)
- new /obj/item/clothing/suit/space/orange(src)
- new /obj/item/clothing/suit/space/orange(src)
- new /obj/item/clothing/mask/gas(src)
- new /obj/item/clothing/mask/gas(src)
- new /obj/item/tank/internals/oxygen/red(src)
- new /obj/item/tank/internals/oxygen/red(src)
- new /obj/item/pickaxe/emergency(src)
- new /obj/item/pickaxe/emergency(src)
- new /obj/item/survivalcapsule(src)
- new /obj/item/storage/toolbox/emergency(src)
- new /obj/item/bodybag/environmental(src)
- new /obj/item/bodybag/environmental(src)
+ return flatten_quantified_list(list(
+ /obj/item/clothing/head/helmet/space/orange = 2,
+ /obj/item/clothing/suit/space/orange = 2,
+ /obj/item/clothing/mask/gas = 2,
+ /obj/item/tank/internals/oxygen/red = 2,
+ /obj/item/pickaxe/emergency = 2,
+ /obj/item/survivalcapsule = 1,
+ /obj/item/storage/toolbox/emergency = 1,
+ /obj/item/bodybag/environmental = 2,
+ ))
diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm
index d604344ba98..7489e64dc94 100644
--- a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm
+++ b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm
@@ -367,6 +367,8 @@
icon_state = "cyber_implants"
/obj/item/storage/box/cyber_implants/PopulateContents()
- new /obj/item/autosurgeon/syndicate/xray_eyes(src)
- new /obj/item/autosurgeon/syndicate/anti_stun(src)
- new /obj/item/autosurgeon/syndicate/reviver(src)
+ return list(
+ /obj/item/autosurgeon/syndicate/xray_eyes,
+ /obj/item/autosurgeon/syndicate/anti_stun,
+ /obj/item/autosurgeon/syndicate/reviver
+ )
diff --git a/code/modules/vehicles/mecha/mecha_control_console.dm b/code/modules/vehicles/mecha/mecha_control_console.dm
index a9dbca0e07d..da67747b842 100644
--- a/code/modules/vehicles/mecha/mecha_control_console.dm
+++ b/code/modules/vehicles/mecha/mecha_control_console.dm
@@ -151,11 +151,6 @@
name = "exosuit tracking beacons"
/obj/item/storage/box/mechabeacons/PopulateContents()
- ..()
- new /obj/item/mecha_parts/mecha_tracking(src)
- new /obj/item/mecha_parts/mecha_tracking(src)
- new /obj/item/mecha_parts/mecha_tracking(src)
- new /obj/item/mecha_parts/mecha_tracking(src)
- new /obj/item/mecha_parts/mecha_tracking(src)
- new /obj/item/mecha_parts/mecha_tracking(src)
- new /obj/item/mecha_parts/mecha_tracking(src)
+ . = list()
+ for(var/_ in 1 to 7)
+ . += /obj/item/mecha_parts/mecha_tracking
diff --git a/tgstation.dme b/tgstation.dme
index 8aacf2a5efa..93986120e2f 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -539,6 +539,7 @@
#include "code\_globalvars\rcd.dm"
#include "code\_globalvars\religion.dm"
#include "code\_globalvars\silo.dm"
+#include "code\_globalvars\storage_config.dm"
#include "code\_globalvars\tgui.dm"
#include "code\_globalvars\time_vars.dm"
#include "code\_globalvars\lists\achievements.dm"
@@ -1967,22 +1968,24 @@
#include "code\datums\status_effects\debuffs\vision\nearsighted.dm"
#include "code\datums\storage\storage.dm"
#include "code\datums\storage\storage_interface.dm"
-#include "code\datums\storage\subtypes\backpack.dm"
-#include "code\datums\storage\subtypes\bag_of_holding.dm"
-#include "code\datums\storage\subtypes\cards.dm"
-#include "code\datums\storage\subtypes\carpskin_bag.dm"
-#include "code\datums\storage\subtypes\drone.dm"
-#include "code\datums\storage\subtypes\duffel_bag.dm"
-#include "code\datums\storage\subtypes\extract_inventory.dm"
-#include "code\datums\storage\subtypes\fish_case.dm"
-#include "code\datums\storage\subtypes\implant.dm"
-#include "code\datums\storage\subtypes\organ_box.dm"
+#include "code\datums\storage\subtypes\backpacks.dm"
+#include "code\datums\storage\subtypes\bags.dm"
+#include "code\datums\storage\subtypes\belts.dm"
+#include "code\datums\storage\subtypes\boxes.dm"
+#include "code\datums\storage\subtypes\dufflebags.dm"
+#include "code\datums\storage\subtypes\holsters.dm"
+#include "code\datums\storage\subtypes\lockboxes.dm"
+#include "code\datums\storage\subtypes\medkits.dm"
#include "code\datums\storage\subtypes\pockets.dm"
-#include "code\datums\storage\subtypes\portable_chem_mixer.dm"
-#include "code\datums\storage\subtypes\rped.dm"
-#include "code\datums\storage\subtypes\surgery_tray.dm"
-#include "code\datums\storage\subtypes\test_tube_rack.dm"
-#include "code\datums\storage\subtypes\trash.dm"
+#include "code\datums\storage\subtypes\toolboxes.dm"
+#include "code\datums\storage\subtypes\others\bag_of_holding.dm"
+#include "code\datums\storage\subtypes\others\cards.dm"
+#include "code\datums\storage\subtypes\others\carpskin_bag.dm"
+#include "code\datums\storage\subtypes\others\extract_inventory.dm"
+#include "code\datums\storage\subtypes\others\fish_case.dm"
+#include "code\datums\storage\subtypes\others\misc.dm"
+#include "code\datums\storage\subtypes\others\pod.dm"
+#include "code\datums\storage\subtypes\others\rped.dm"
#include "code\datums\votes\_vote_datum.dm"
#include "code\datums\votes\custom_vote.dm"
#include "code\datums\votes\map_vote.dm"
@@ -2706,20 +2709,22 @@
#include "code\game\objects\items\storage\basket.dm"
#include "code\game\objects\items\storage\belt.dm"
#include "code\game\objects\items\storage\briefcase.dm"
+#include "code\game\objects\items\storage\dufflebags.dm"
#include "code\game\objects\items\storage\fancy.dm"
#include "code\game\objects\items\storage\garment.dm"
#include "code\game\objects\items\storage\holsters.dm"
#include "code\game\objects\items\storage\lockbox.dm"
#include "code\game\objects\items\storage\medkit.dm"
+#include "code\game\objects\items\storage\misc.dm"
+#include "code\game\objects\items\storage\pillbottles.dm"
#include "code\game\objects\items\storage\sixpack.dm"
#include "code\game\objects\items\storage\storage.dm"
-#include "code\game\objects\items\storage\toolbox.dm"
-#include "code\game\objects\items\storage\uplink_kits.dm"
#include "code\game\objects\items\storage\wallets.dm"
#include "code\game\objects\items\storage\boxes\_boxes.dm"
#include "code\game\objects\items\storage\boxes\cargo_boxes.dm"
#include "code\game\objects\items\storage\boxes\clothes_boxes.dm"
#include "code\game\objects\items\storage\boxes\engineering_boxes.dm"
+#include "code\game\objects\items\storage\boxes\fishing_boxes.dm"
#include "code\game\objects\items\storage\boxes\flat_boxes.dm"
#include "code\game\objects\items\storage\boxes\food_boxes.dm"
#include "code\game\objects\items\storage\boxes\implant_boxes.dm"
@@ -2728,6 +2733,16 @@
#include "code\game\objects\items\storage\boxes\science_boxes.dm"
#include "code\game\objects\items\storage\boxes\security_boxes.dm"
#include "code\game\objects\items\storage\boxes\service_boxes.dm"
+#include "code\game\objects\items\storage\boxes\trait_boxes.dm"
+#include "code\game\objects\items\storage\boxes\uplink_kits.dm"
+#include "code\game\objects\items\storage\toolboxes\_toolbox.dm"
+#include "code\game\objects\items\storage\toolboxes\emergency.dm"
+#include "code\game\objects\items\storage\toolboxes\fishing.dm"
+#include "code\game\objects\items\storage\toolboxes\mechanical.dm"
+#include "code\game\objects\items\storage\toolboxes\medical.dm"
+#include "code\game\objects\items\storage\toolboxes\misc.dm"
+#include "code\game\objects\items\storage\toolboxes\service.dm"
+#include "code\game\objects\items\storage\toolboxes\weapons.dm"
#include "code\game\objects\items\tanks\jetpack.dm"
#include "code\game\objects\items\tanks\tank_types.dm"
#include "code\game\objects\items\tanks\tanks.dm"
@@ -4769,7 +4784,6 @@
#include "code\modules\mining\machine_stacking.dm"
#include "code\modules\mining\machine_unloading.dm"
#include "code\modules\mining\mine_items.dm"
-#include "code\modules\mining\money_bag.dm"
#include "code\modules\mining\ores_coins.dm"
#include "code\modules\mining\satchel_ore_box.dm"
#include "code\modules\mining\shelters.dm"
@@ -5720,7 +5734,6 @@
#include "code\modules\projectiles\guns\ballistic\toy.dm"
#include "code\modules\projectiles\guns\ballistic\bows\_bow.dm"
#include "code\modules\projectiles\guns\ballistic\bows\bow_arrows.dm"
-#include "code\modules\projectiles\guns\ballistic\bows\bow_quivers.dm"
#include "code\modules\projectiles\guns\ballistic\bows\bow_types.dm"
#include "code\modules\projectiles\guns\energy\beam_rifle.dm"
#include "code\modules\projectiles\guns\energy\crank_guns.dm"