diff --git a/citadel.dme b/citadel.dme
index d1ddd494c36..cb2a45f0e11 100644
--- a/citadel.dme
+++ b/citadel.dme
@@ -1958,7 +1958,9 @@
#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\bag\trash.dm"
#include "code\game\objects\items\storage\belt\security.dm"
+#include "code\game\objects\items\storage\belt\utility.dm"
#include "code\game\objects\items\storage\medical\firstaid.dm"
#include "code\game\objects\items\storage\medical\hypokit.dm"
#include "code\game\objects\items\storage\medical\pill_bottle.dm"
@@ -2207,12 +2209,18 @@
#include "code\game\objects\systems\storage\storage-filters.dm"
#include "code\game\objects\systems\storage\storage-indirection.dm"
#include "code\game\objects\systems\storage\storage-indirection_holder.dm"
+#include "code\game\objects\systems\storage\storage-insertion_removal.dm"
#include "code\game\objects\systems\storage\storage-limits.dm"
#include "code\game\objects\systems\storage\storage-screen_object.dm"
#include "code\game\objects\systems\storage\storage-ui.dm"
#include "code\game\objects\systems\storage\storage.dm"
+#include "code\game\objects\systems\storage\subtypes\backpack.dm"
+#include "code\game\objects\systems\storage\subtypes\belt.dm"
+#include "code\game\objects\systems\storage\subtypes\hypokit.dm"
+#include "code\game\objects\systems\storage\subtypes\pill_bottle.dm"
#include "code\game\objects\systems\storage\subtypes\stack.dm"
#include "code\game\objects\systems\storage\subtypes\stock_parts.dm"
+#include "code\game\objects\systems\storage\subtypes\trash_bag.dm"
#include "code\game\rendering\client.dm"
#include "code\game\rendering\hud_preferences.dm"
#include "code\game\rendering\hud_style.dm"
diff --git a/code/__DEFINES/inventory/misc.dm b/code/__DEFINES/inventory/misc.dm
index feb1c269b9f..6587f676d2d 100644
--- a/code/__DEFINES/inventory/misc.dm
+++ b/code/__DEFINES/inventory/misc.dm
@@ -6,18 +6,3 @@
// todo: comsig instead?
/// relocated; return false
#define ITEM_RELOCATED_BY_DROPPED -1
-
-//* Item `suit_storage_class` defines *//
-
-#define SUIT_STORAGE_CLASS_HARDWEAR (1<<0)
-#define SUIT_STORAGE_CLASS_SOFTWEAR (1<<1)
-#define SUIT_STORAGE_CLASS_ARMOR (1<<2)
-
-DECLARE_BITFIELD(suit_storage_class, list(
- BITFIELD_NAMED("Hardwear", SUIT_STORAGE_CLASS_HARDWEAR),
- BITFIELD_NAMED("Softwear", SUIT_STORAGE_CLASS_SOFTWEAR),
- BITFIELD_NAMED("Armor", SUIT_STORAGE_CLASS_ARMOR),
-))
-ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class)
-ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class_allow)
-ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class_disallow)
diff --git a/code/__DEFINES/inventory/storage.dm b/code/__DEFINES/inventory/storage.dm
index 3e701885518..4a62f7db31c 100644
--- a/code/__DEFINES/inventory/storage.dm
+++ b/code/__DEFINES/inventory/storage.dm
@@ -1,5 +1,5 @@
//* This file is explicitly licensed under the MIT license. *//
-//* Copyright (c) 2023 Citadel Station developers. *//
+//* Copyright (c) 2025 Citadel Station Developers *//
//* Storage UI defines *//
@@ -68,6 +68,22 @@
/// Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh
#define WEIGHT_CLASS_GIGANTIC 6
+//* Weight Classes - Items *//
+
+// tiny holdout pistols
+// * probably should stop existing ASAP
+#define WEIGHT_CLASS_FOR_HOLDOUT_SIDEARM WEIGHT_CLASS_SMALL
+// big revolvers, magpistols, etc
+#define WEIGHT_CLASS_FOR_SIDEARM WEIGHT_CLASS_NORMAL
+// energy carbines and similar
+#define WEIGHT_CLASS_FOR_SHORT_RIFLE WEIGHT_CLASS_BULKY
+// full sized ARs
+#define WEIGHT_CLASS_FOR_LONG_RIFLE WEIGHT_CLASS_HUGE
+// self-documenting name
+#define WEIGHT_CLASS_FOR_SHOTGUN WEIGHT_CLASS_HUGE
+// LMGs and similar
+#define WEIGHT_CLASS_FOR_LIGHT_MACHINE_GUN WEIGHT_CLASS_HUGE
+
//* Volumetrics - Default Item Volumes *//
#define WEIGHT_VOLUME_TINY 0.5
@@ -109,3 +125,66 @@ GLOBAL_REAL_LIST(w_class_to_volume) = list(
#define ITEM_VOLUME_RIFLE_MAG (WEIGHT_VOLUME_NORMAL / 2)
#define ITEM_VOLUME_AMMO_CASING (WEIGHT_VOLUME_TINY / 2)
+
+#define ITEM_VOLUME_PILL WEIGHT_VOLUME_TINY
+
+//* Item `belt_storage_class` defines *//
+
+/// Doesn't go in a belt
+#define BELT_CLASS_INVALID 1
+/// small grenades, pill bottles, syringes, pistol mags, etc
+#define BELT_CLASS_SMALL 2
+/// rifle mags, welding torches, crowbars, etc
+#define BELT_CLASS_MEDIUM 3
+/// sidearms, rpds, etc
+#define BELT_CLASS_LARGE 4
+
+#define BELT_CLASS_FOR_SMALL_CELL BELT_CLASS_SMALL
+#define BELT_CLASS_FOR_WEAPON_CELL BELT_CLASS_MEDIUM
+#define BELT_CLASS_FOR_MEDIUM_CELL BELT_CLASS_LARGE
+#define BELT_CLASS_FOR_LARGE_CELL BELT_CLASS_INVALID
+
+// TODO: DECLARE_ENUM
+
+GLOBAL_REAL_LIST(belt_class_names) = list(
+ "Invalid",
+ "Small",
+ "Medium",
+ "Large",
+)
+
+//* Item `belt_storage_size` defines *//
+
+/// Default belt size for items
+#define BELT_SIZE_DEFAULT 1
+
+/// Default belt size for ammo casings
+#define BELT_SIZE_FOR_AMMO_CASING 0.25
+/// Default magazine size
+#define BELT_SIZE_FOR_MAGAZINE 1
+
+/// Default flashlight size
+#define BELT_SIZE_FOR_FLASHLIGHT 1
+
+#define BELT_SIZE_FOR_SYRINGE 0.25
+#define BELT_SIZE_FOR_PILL 0.25
+
+#define BELT_SIZE_FOR_SMALL_CELL 1
+#define BELT_SIZE_FOR_WEAPON_CELL 1
+#define BELT_SIZE_FOR_MEDIUM_CELL 1
+#define BELT_SIZE_FOR_LARGE_CELL 1
+
+//* Item `suit_storage_class` defines *//
+
+#define SUIT_STORAGE_CLASS_HARDWEAR (1<<0)
+#define SUIT_STORAGE_CLASS_SOFTWEAR (1<<1)
+#define SUIT_STORAGE_CLASS_ARMOR (1<<2)
+
+DECLARE_BITFIELD(suit_storage_class, list(
+ BITFIELD_NAMED("Hardwear", SUIT_STORAGE_CLASS_HARDWEAR),
+ BITFIELD_NAMED("Softwear", SUIT_STORAGE_CLASS_SOFTWEAR),
+ BITFIELD_NAMED("Armor", SUIT_STORAGE_CLASS_ARMOR),
+))
+ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class)
+ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class_allow)
+ASSIGN_BITFIELD(suit_storage_class, /obj/item, suit_storage_class_disallow)
diff --git a/code/__DEFINES/power/cell.dm b/code/__DEFINES/power/cell.dm
index 5145a517fd4..72d47c39c40 100644
--- a/code/__DEFINES/power/cell.dm
+++ b/code/__DEFINES/power/cell.dm
@@ -49,6 +49,8 @@ ASSIGN_BITFIELD(cell_type, /mob/living/silicon/robot, cell_accept)
cell_datum = ##DATUM_TYPEPATH; \
rendering_system = TRUE; \
indicator_count = 4; \
+ belt_storage_class = BELT_CLASS_FOR_SMALL_CELL; \
+ belt_storage_size = BELT_SIZE_FOR_SMALL_CELL; \
worth_intrinsic = ##DATUM_TYPEPATH::typegen_worth_base_small; \
w_class = ##DATUM_TYPEPATH::typegen_w_class_small; \
weight_volume = ##DATUM_TYPEPATH::typegen_w_volume_small; \
@@ -75,6 +77,8 @@ ASSIGN_BITFIELD(cell_type, /mob/living/silicon/robot, cell_accept)
cell_datum = ##DATUM_TYPEPATH; \
rendering_system = TRUE; \
indicator_count = 4; \
+ belt_storage_class = BELT_CLASS_FOR_MEDIUM_CELL; \
+ belt_storage_size = BELT_SIZE_FOR_MEDIUM_CELL; \
worth_intrinsic = ##DATUM_TYPEPATH::typegen_worth_base_medium; \
w_class = ##DATUM_TYPEPATH::typegen_w_class_medium; \
weight_volume = ##DATUM_TYPEPATH::typegen_w_volume_medium; \
@@ -100,6 +104,8 @@ ASSIGN_BITFIELD(cell_type, /mob/living/silicon/robot, cell_accept)
cell_datum = ##DATUM_TYPEPATH; \
rendering_system = TRUE; \
indicator_count = 4; \
+ belt_storage_class = BELT_CLASS_FOR_LARGE_CELL; \
+ belt_storage_size = BELT_SIZE_FOR_LARGE_CELL; \
worth_intrinsic = ##DATUM_TYPEPATH::typegen_worth_base_large; \
w_class = ##DATUM_TYPEPATH::typegen_w_class_large; \
weight_volume = ##DATUM_TYPEPATH::typegen_w_volume_large; \
@@ -125,6 +131,8 @@ ASSIGN_BITFIELD(cell_type, /mob/living/silicon/robot, cell_accept)
cell_datum = ##DATUM_TYPEPATH; \
rendering_system = TRUE; \
indicator_count = 4; \
+ belt_storage_class = BELT_CLASS_FOR_WEAPON_CELL; \
+ belt_storage_size = BELT_SIZE_FOR_WEAPON_CELL; \
worth_intrinsic = ##DATUM_TYPEPATH::typegen_worth_base_weapon; \
w_class = ##DATUM_TYPEPATH::typegen_w_class_weapon; \
weight_volume = ##DATUM_TYPEPATH::typegen_w_volume_weapon; \
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-heavy_rifle.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-heavy_rifle.dm
index 039adea334e..12e22b18c54 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-heavy_rifle.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-heavy_rifle.dm
@@ -113,6 +113,7 @@
item_renderer = /datum/gun_item_renderer/empty_state
internal_magazine = TRUE
internal_magazine_size = 1
+ w_class = WEIGHT_CLASS_FOR_LONG_RIFLE
/obj/item/gun/projectile/ballistic/nt_expedition/heavy_rifle/semirifle
name = "heavy rifle"
@@ -129,6 +130,7 @@
base_icon_state = "semi"
item_renderer = /datum/gun_item_renderer/empty_state
magazine_restrict = /obj/item/ammo_magazine/nt_expedition/heavy_rifle/stick
+ w_class = WEIGHT_CLASS_FOR_LONG_RIFLE
/obj/item/gun/projectile/ballistic/nt_expedition/heavy_rifle/autorifle
name = "heavy automatic rifle"
@@ -145,6 +147,7 @@
base_icon_state = "auto"
render_magazine_overlay = MAGAZINE_CLASS_GENERIC
magazine_restrict = /obj/item/ammo_magazine/nt_expedition/heavy_rifle/stick
+ w_class = WEIGHT_CLASS_FOR_LONG_RIFLE
/obj/item/gun/projectile/ballistic/nt_expedition/heavy_rifle/lmg
name = "light machine gun"
@@ -153,13 +156,15 @@
The tests of the Mod.2 design quickly turned development towards a
general purpose machine gun (GPMG) version of the Ranger series, the “Hailmaker.”.
Sporting a frame-mounted cryo-stabilized heavy barrel, a feed tray for quickly reloading
- via an assistant gunner, a belt box for 100 rounds of 7.5x54mm, and a gyroscopic assist system,
+ via an assistant gunner, and a gyroscopic assist system,
this weapon is seen in the guard towers of base camps and atop vehicles in addition to
dedicated machine gun teams. The patter this weapon makes as it suppresses any hostile
force makes this weapon's name a logical choice.
"} + "
"
icon_state = "lmg"
- magazine_restrict = /obj/item/ammo_magazine/nt_expedition/heavy_rifle/stick
+ // todo: box mag
+ magazine_restrict = /obj/item/ammo_magazine/nt_expedition/heavy_rifle/stick/drum
+ w_class = WEIGHT_CLASS_FOR_LIGHT_MACHINE_GUN
// todo: rendering; how are we going to render both unloaded and open?
// todo: rendering; maybe expand the render additional to allow for generation of a list?
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-heavy_sidearm.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-heavy_sidearm.dm
index 01bdbdce297..72b5b101b4a 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-heavy_sidearm.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-heavy_sidearm.dm
@@ -127,6 +127,7 @@ GENERATE_DESIGN_FOR_AUTOLATHE(/obj/item/ammo_magazine/nt_expedition/heavy_sidear
base_icon_state = "pistol"
render_magazine_overlay = MAGAZINE_CLASS_GENERIC
magazine_restrict = /obj/item/ammo_magazine/nt_expedition/heavy_sidearm/pistol
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
/obj/item/gun/projectile/ballistic/nt_expedition/heavy_sidearm/revolver
name = "heavy revolver"
@@ -141,6 +142,7 @@ GENERATE_DESIGN_FOR_AUTOLATHE(/obj/item/ammo_magazine/nt_expedition/heavy_sidear
internal_magazine = TRUE
internal_magazine_size = /obj/item/ammo_magazine/nt_expedition/heavy_sidearm/speedloader::ammo_max
icon_state = "revolver"
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
/datum/firemode/nt_expedition_heavy_smg
abstract_type = /datum/firemode/nt_expedition_heavy_smg
@@ -181,6 +183,7 @@ GENERATE_DESIGN_FOR_AUTOLATHE(/obj/item/ammo_magazine/nt_expedition/heavy_sidear
/datum/firemode/nt_expedition_heavy_smg/semi_auto,
/datum/firemode/nt_expedition_heavy_smg/three_burst,
)
+ w_class = WEIGHT_CLASS_FOR_SHORT_RIFLE
GENERATE_DESIGN_FOR_NT_PROTOLATHE(/obj/item/gun/projectile/ballistic/nt_expedition/heavy_sidearm/smg, /nt_expedition/heavy_smg, "nt-expeditionary-heavy_smg")
/obj/item/gun/projectile/ballistic/nt_expedition/heavy_sidearm/smg/no_pin
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-light_rifle.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-light_rifle.dm
index f17f400edae..3360f23064b 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-light_rifle.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-light_rifle.dm
@@ -140,6 +140,7 @@
icon_state = "revolver"
base_icon_state = "revolver"
render_break_overlay = BALLISTIC_RENDER_BREAK_OPEN
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
/obj/item/gun/projectile/ballistic/nt_expedition/light_rifle/semirifle
name = "semi-automatic rifle"
@@ -156,6 +157,7 @@
base_icon_state = "semi"
render_magazine_overlay = MAGAZINE_CLASS_GENERIC
magazine_restrict = /obj/item/ammo_magazine/nt_expedition/light_rifle/stick
+ w_class = WEIGHT_CLASS_FOR_LONG_RIFLE
/obj/item/gun/projectile/ballistic/nt_expedition/light_rifle/autorifle
name = "automatic rifle"
@@ -172,6 +174,7 @@
base_icon_state = "auto"
render_magazine_overlay = MAGAZINE_CLASS_GENERIC
magazine_restrict = /obj/item/ammo_magazine/nt_expedition/light_rifle/stick
+ w_class = WEIGHT_CLASS_FOR_LONG_RIFLE
/obj/item/gun/projectile/ballistic/nt_expedition/light_rifle/pdw
name = "personal defense weapon"
@@ -188,6 +191,7 @@
base_icon_state = "pdw"
render_magazine_overlay = MAGAZINE_CLASS_GENERIC
magazine_restrict = /obj/item/ammo_magazine/nt_expedition/light_rifle/stick
+ w_class = WEIGHT_CLASS_FOR_SHORT_RIFLE
/obj/item/gun/projectile/ballistic/nt_expedition/light_rifle/lmg
name = "squad automatic weapon"
@@ -205,3 +209,4 @@
render_bolt_overlay = BALLISTIC_RENDER_BOLT_CLOSE
render_break_overlay = BALLISTIC_RENDER_BREAK_BOTH
magazine_restrict = /obj/item/ammo_magazine/nt_expedition/light_rifle/stick
+ w_class = WEIGHT_CLASS_FOR_LIGHT_MACHINE_GUN
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-light_sidearm.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-light_sidearm.dm
index fec3e853b0d..83080d19e62 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-light_sidearm.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-light_sidearm.dm
@@ -146,6 +146,7 @@ GENERATE_DESIGN_FOR_AUTOLATHE(/obj/item/ammo_magazine/nt_expedition/light_sidear
base_icon_state = "pistol"
render_magazine_overlay = MAGAZINE_CLASS_GENERIC
magazine_restrict = /obj/item/ammo_magazine/nt_expedition/light_sidearm/pistol
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
//* SMG *//
@@ -187,6 +188,7 @@ GENERATE_DESIGN_FOR_AUTOLATHE(/obj/item/ammo_magazine/nt_expedition/light_sidear
/datum/firemode/nt_expedition_light_smg/semi_auto,
/datum/firemode/nt_expedition_light_smg/two_burst,
)
+ w_class = WEIGHT_CLASS_FOR_SHORT_RIFLE
GENERATE_DESIGN_FOR_NT_PROTOLATHE(/obj/item/gun/projectile/ballistic/nt_expedition/light_sidearm/smg/no_pin, /nt_expedition/light_smg, "nt-expeditionary-light_smg")
/obj/item/gun/projectile/ballistic/nt_expedition/light_sidearm/smg/no_pin
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-shotgun.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-shotgun.dm
index 0122a0b2a5d..29995155278 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-shotgun.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_expedition-shotgun.dm
@@ -41,6 +41,7 @@
"} + "
"
icon_state = "pump"
#warn pump-open
+ w_class = WEIGHT_CLASS_FOR_SHOTGUN
#warn impl
@@ -63,5 +64,6 @@
"} + "
"
icon_state = "semiauto"
#warn semiauto-empty (magout)
+ w_class = WEIGHT_CLASS_FOR_SHOTGUN
#warn impl
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_hydra.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_hydra.dm
index 4b2fdaf179e..d0a1cf6e86b 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_hydra.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_hydra.dm
@@ -30,6 +30,7 @@
}
magazine_restrict = /obj/item/ammo_magazine/microbattery/nt_hydra
origin_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 4, TECH_MAGNETS = 3)
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
/obj/item/gun/projectile/ballistic/microbattery/nt_hydra/sidearm/prototype
name = "prototype cell-loaded revolver"
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_isd.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_isd.dm
index e93c1851bf9..4b14ee95047 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_isd.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_isd.dm
@@ -90,6 +90,7 @@
14,
)
)
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
/obj/item/gun/projectile/energy/nt_isd/sidearm/with_light
attachments = list(
@@ -159,6 +160,7 @@
use_color = TRUE;
use_empty = TRUE;
}
+ w_class = WEIGHT_CLASS_FOR_SHORT_RIFLE
//* Energy Lance *//
@@ -202,6 +204,7 @@
count = 4;
use_empty = TRUE;
}
+ w_class = WEIGHT_CLASS_FOR_LONG_RIFLE
//* Multiphase Sidearm *//
@@ -262,6 +265,7 @@
use_empty = TRUE;
use_single = TRUE;
}
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
//* Projectiles *//
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_protolaser.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_protolaser.dm
index bbef9fc7fc3..0cf40412a2c 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_protolaser.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_protolaser.dm
@@ -77,6 +77,7 @@
/datum/prototype/material/gold::id = 125,
/datum/prototype/material/copper::id = 500,
)
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
GENERATE_DESIGN_FOR_NT_PROTOLATHE(/obj/item/gun/projectile/energy/nt_protolaser/sidearm/no_pin, /nt_protolaser/sidearm, "nt-protolaser-sidearm")
/obj/item/gun/projectile/energy/nt_protolaser/sidearm/no_pin
@@ -133,6 +134,7 @@ GENERATE_DESIGN_FOR_NT_PROTOLATHE(/obj/item/gun/projectile/energy/nt_protolaser/
/datum/prototype/material/gold::id = 250,
/datum/prototype/material/copper::id = 500,
)
+ w_class = WEIGHT_CLASS_FOR_SHORT_RIFLE
GENERATE_DESIGN_FOR_NT_PROTOLATHE(/obj/item/gun/projectile/energy/nt_protolaser/carbine/no_pin, /nt_protolaser/carbine, "nt-protolaser-carbine")
/obj/item/gun/projectile/energy/nt_protolaser/carbine/no_pin
@@ -189,6 +191,7 @@ GENERATE_DESIGN_FOR_NT_PROTOLATHE(/obj/item/gun/projectile/energy/nt_protolaser/
/datum/prototype/material/gold::id = 750,
/datum/prototype/material/copper::id = 500,
)
+ w_class = WEIGHT_CLASS_FOR_LONG_RIFLE
GENERATE_DESIGN_FOR_NT_PROTOLATHE(/obj/item/gun/projectile/energy/nt_protolaser/rifle/no_pin, /nt_protolaser/rifle, "nt-protolaser-rifle")
/obj/item/gun/projectile/energy/nt_protolaser/rifle/no_pin
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_protomag.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_protomag.dm
index f653b603ae9..166ff0dfb13 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_protomag.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_protomag.dm
@@ -79,6 +79,7 @@
/datum/prototype/material/copper::id = 750,
/datum/prototype/material/lead::id = 250,
)
+ w_class = WEIGHT_CLASS_FOR_SIDEARM
legacy_discharged_fire_sound = 'sound/weapons/gunshot/gunshot_pistol.ogg'
@@ -127,6 +128,7 @@ GENERATE_DESIGN_FOR_NT_PROTOLATHE(/obj/item/gun/projectile/ballistic/magnetic/nt
/datum/prototype/material/copper::id = 1200,
/datum/prototype/material/lead::id = 450,
)
+ w_class = WEIGHT_CLASS_FOR_SHORT_RIFLE
legacy_discharged_fire_sound = 'sound/weapons/gunshot/gunshot_strong.ogg'
diff --git a/code/game/content/factions/corporations/nanotrasen/guns/nt_pulse.dm b/code/game/content/factions/corporations/nanotrasen/guns/nt_pulse.dm
index b184e104bb7..efe35ef79b5 100644
--- a/code/game/content/factions/corporations/nanotrasen/guns/nt_pulse.dm
+++ b/code/game/content/factions/corporations/nanotrasen/guns/nt_pulse.dm
@@ -66,6 +66,7 @@
count = 4;
use_empty = TRUE;
}
+ w_class = WEIGHT_CLASS_FOR_SHORT_RIFLE
//* Carbine *//
@@ -113,6 +114,7 @@
count = 4;
use_empty = TRUE;
}
+ w_class = WEIGHT_CLASS_FOR_LONG_RIFLE
//* Projectiles *//
diff --git a/code/game/gamemodes/cult/soulstone.dm b/code/game/gamemodes/cult/soulstone.dm
index 624852e97fd..e920b2843f0 100644
--- a/code/game/gamemodes/cult/soulstone.dm
+++ b/code/game/gamemodes/cult/soulstone.dm
@@ -11,6 +11,7 @@
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_BELT
origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4, TECH_ARCANE = 1)
+ belt_storage_class = BELT_CLASS_SMALL
var/imprinted = "empty"
var/possible_constructs = list("Juggernaut","Wraith","Artificer","Harvester")
diff --git a/code/game/objects/items-interaction.dm b/code/game/objects/items-interaction.dm
index ddf59eb2305..a1d1be8d647 100644
--- a/code/game/objects/items-interaction.dm
+++ b/code/game/objects/items-interaction.dm
@@ -97,7 +97,7 @@
if(isturf(old_loc))
new /obj/effect/temporary_effect/item_pickup_ghost(old_loc, actually_picked_up, user)
user.trigger_aiming(TARGET_CAN_CLICK)
-
+
//* Drag / Drop *//
/obj/item/OnMouseDrop(atom/over, mob/user, proximity, params)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 7efd4574ee5..b395d221849 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -117,18 +117,6 @@
var/obj/item/worn_inside
/// suppress auto inventory hooks in forceMove
var/worn_hook_suppressed = FALSE
- /// Suit storage classes
- var/suit_storage_class = NONE
- /// Suit storage classes to allow
- var/suit_storage_class_allow = NONE
- /// Suit storage classes to disallow
- var/suit_storage_class_disallow = NONE
- /// Suit storage override type-list
- /// * only for adminbus really
- VAR_PRIVATE/list/suit_storage_types_allow_override
- /// Suit storage override type-list
- /// * only for adminbus really
- VAR_PRIVATE/list/suit_storage_types_disallow_override
//* Environmentals *//
/// Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags.
@@ -165,6 +153,30 @@
/// null to default to weight class
var/weight_volume
+ //* Storage - Belts *//
+ /// Belt storage class
+ /// * IT IS NOT SAFE TO MODIFY THIS WITHOUT USING GETTER / SETTER PATTERN
+ /// TODO: getter / setter
+ var/belt_storage_class = BELT_CLASS_INVALID
+ /// Belt storage size
+ /// * IT IS NOT SAFE TO MODIFY THIS WITHOUT USING GETTER / SETTER PATTERN
+ /// TODO: getter / setter
+ var/belt_storage_size = BELT_SIZE_DEFAULT
+
+ //* Storage - Suit Storage *//
+ /// Suit storage classes
+ var/suit_storage_class = NONE
+ /// Suit storage classes to allow
+ var/suit_storage_class_allow = NONE
+ /// Suit storage classes to disallow
+ var/suit_storage_class_disallow = NONE
+ /// Suit storage override type-list
+ /// * only for adminbus really
+ VAR_PRIVATE/list/suit_storage_types_allow_override
+ /// Suit storage override type-list
+ /// * only for adminbus really
+ VAR_PRIVATE/list/suit_storage_types_disallow_override
+
//? unsorted / legacy
/// This saves our blood splatter overlay, which will be processed not to go over the edges of the sprite
var/image/blood_overlay = null
@@ -323,18 +335,8 @@
. += "It looks like it weighs a lot. You probably will have a hard time running with it."
if(40 to INFINITY)
. += "It looks like it weighs a ton. You really won't be doing much running with it."
-
- // if(resistance_flags & INDESTRUCTIBLE)
- // . += "[src] seems extremely robust! It'll probably withstand anything that could happen to it!"
- // else
- // if(resistance_flags & LAVA_PROOF)
- // . += "[src] is made of an extremely heat-resistant material, it'd probably be able to withstand lava!"
- // if(resistance_flags & (ACID_PROOF | UNACIDABLE))
- // . += "[src] looks pretty robust! It'd probably be able to withstand acid!"
- // if(resistance_flags & FREEZE_PROOF)
- // . += "[src] is made of cold-resistant materials."
- // if(resistance_flags & FIRE_PROOF)
- // . += "[src] is made of fire-retardant materials."
+ if(belt_storage_class != BELT_CLASS_INVALID)
+ . += "It looks like it can fit into a belt, and would use [belt_storage_size] [lowertext(global.belt_class_names[belt_storage_class])]-sized loop(s)."
// if(item_flags & (ITEM_CAN_BLOCK | ITEM_CAN_PARRY))
// var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data)
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 57cd6a7e4f1..92e9bbbe742 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -13,6 +13,7 @@ GLOBAL_LIST_EMPTY(PDAs)
slot_flags = SLOT_ID | SLOT_BELT
rad_flags = RAD_BLOCK_CONTENTS
item_flags = ITEM_NO_BLUDGEON
+ belt_storage_class = BELT_CLASS_SMALL
//Main variables
var/pdachoice = 1
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index c1a08b56725..c6bcc166727 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -11,6 +11,7 @@
origin_tech = list(TECH_MAGNET = 2, TECH_COMBAT = 1)
worth_intrinsic = 45
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/times_used = 0 //Number of times it's been used.
var/broken = FALSE //Is the flash burnt out?
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 353e1820b71..e9c72a5f3b1 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -10,6 +10,8 @@
light_wedge = LIGHT_WIDE
worth_intrinsic = 25
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_MEDIUM
+ belt_storage_size = BELT_SIZE_FOR_FLASHLIGHT
var/on = FALSE
/// Luminosity when on
diff --git a/code/game/objects/items/devices/geiger.dm b/code/game/objects/items/devices/geiger.dm
index 7c9eed791be..8f51fee9028 100644
--- a/code/game/objects/items/devices/geiger.dm
+++ b/code/game/objects/items/devices/geiger.dm
@@ -18,6 +18,7 @@
rad_flags = RAD_NO_CONTAMINATE | RAD_BLOCK_CONTENTS
materials_base = list(MAT_STEEL = 200, MAT_GLASS = 100)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/grace = RAD_GRACE_PERIOD
var/datum/looping_sound/geiger/soundloop
diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm
index ff6cd12adc8..0ca516a8981 100644
--- a/code/game/objects/items/devices/gps.dm
+++ b/code/game/objects/items/devices/gps.dm
@@ -28,6 +28,7 @@
materials_base = list(MAT_STEEL = 500)
worth_intrinsic = 40
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/// our GPS tag
var/gps_tag = "GEN0"
diff --git a/code/game/objects/items/devices/holowarrant.dm b/code/game/objects/items/devices/holowarrant.dm
index 4b1afec453b..2c42a2ea46b 100644
--- a/code/game/objects/items/devices/holowarrant.dm
+++ b/code/game/objects/items/devices/holowarrant.dm
@@ -6,6 +6,7 @@
item_state = "flashtool"
item_flags = ITEM_NO_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
throw_force = 5
w_class = WEIGHT_CLASS_SMALL
throw_speed = 4
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index ecaebe45a88..9c8da1281d7 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -5,6 +5,7 @@
icon_state = "megaphone"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/spamcheck = 0
var/emagged = 0
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index 9ed20cccd14..1be3a42f776 100755
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -12,6 +12,7 @@
icon_state = "multitool"
damage_force = 5.0
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_SMALL
throw_force = 5.0
throw_range = 15
throw_speed = 3
diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm
index 0340c914df2..9efc0f03b17 100644
--- a/code/game/objects/items/devices/radio/beacon.dm
+++ b/code/game/objects/items/devices/radio/beacon.dm
@@ -5,6 +5,7 @@
icon_state = "beacon"
item_state = "beacon"
base_icon_state = "beacon"
+ belt_storage_class = BELT_CLASS_SMALL
var/code = "electronic"
var/functioning = TRUE
var/identifier
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 297a669b450..dd5232eee93 100755
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -8,6 +8,7 @@
subspace_transmission = 1
canhear_range = 0 // Can't hear headsets from very far away
slot_flags = SLOT_EARS
+ belt_storage_class = BELT_CLASS_SMALL
var/translate_binary = 0
var/translate_hive = 0
diff --git a/code/game/objects/items/devices/t_scanner.dm b/code/game/objects/items/devices/t_scanner.dm
index 3354b8db3fb..ff7f1cd0006 100644
--- a/code/game/objects/items/devices/t_scanner.dm
+++ b/code/game/objects/items/devices/t_scanner.dm
@@ -11,6 +11,7 @@
materials_base = list(MAT_STEEL = 150)
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/scan_range = 1
diff --git a/code/game/objects/items/devices/tape_recorder/tape_recorder.dm b/code/game/objects/items/devices/tape_recorder/tape_recorder.dm
index ac2f8fa05c4..8638bc6a00a 100644
--- a/code/game/objects/items/devices/tape_recorder/tape_recorder.dm
+++ b/code/game/objects/items/devices/tape_recorder/tape_recorder.dm
@@ -11,6 +11,7 @@
throw_range = 20
materials_base = list(MAT_STEEL = 60, MAT_GLASS = 30)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/// inserted tape
var/obj/item/cassette_tape/tape = /obj/item/cassette_tape/random
diff --git a/code/game/objects/items/devices/whistle.dm b/code/game/objects/items/devices/whistle.dm
index 83e1e8d742c..173d3a67d34 100644
--- a/code/game/objects/items/devices/whistle.dm
+++ b/code/game/objects/items/devices/whistle.dm
@@ -7,6 +7,7 @@
w_class = WEIGHT_CLASS_TINY
slot_flags = SLOT_EARS
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/use_message = "Halt! Security!"
var/spamcheck = 0
diff --git a/code/game/objects/items/grenade/grenade.dm b/code/game/objects/items/grenade/grenade.dm
index 2dcfc41f514..5fcac6c5028 100644
--- a/code/game/objects/items/grenade/grenade.dm
+++ b/code/game/objects/items/grenade/grenade.dm
@@ -15,6 +15,7 @@
throw_range = 20
slot_flags = SLOT_MASK|SLOT_BELT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
// todo: legacy var
var/loadable = TRUE
diff --git a/code/game/objects/items/janitorial/soap.dm b/code/game/objects/items/janitorial/soap.dm
index a15839eb150..3f7bbea54f6 100644
--- a/code/game/objects/items/janitorial/soap.dm
+++ b/code/game/objects/items/janitorial/soap.dm
@@ -9,6 +9,7 @@
atom_flags = NOCONDUCT
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_HOLSTER
+ belt_storage_class = BELT_CLASS_SMALL
throw_force = 0
throw_speed = 4
throw_range = 20
diff --git a/code/game/objects/items/melee/types/transforming/energy/saber.dm b/code/game/objects/items/melee/types/transforming/energy/saber.dm
index 32b983bdf7b..fc71539f6c1 100644
--- a/code/game/objects/items/melee/types/transforming/energy/saber.dm
+++ b/code/game/objects/items/melee/types/transforming/energy/saber.dm
@@ -14,6 +14,7 @@
drop_sound = 'sound/items/drop/sword.ogg'
pickup_sound = 'sound/items/pickup/sword.ogg'
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/can_combine = TRUE
active_damage_force = 30
diff --git a/code/game/objects/items/scanners/atmos.dm b/code/game/objects/items/scanners/atmos.dm
index 6d3ac1822d1..cc2fc488b32 100644
--- a/code/game/objects/items/scanners/atmos.dm
+++ b/code/game/objects/items/scanners/atmos.dm
@@ -12,6 +12,7 @@
materials_base = list(MAT_STEEL = 30, MAT_GLASS = 20)
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/atmos_analyzer/apidean
name = "\improper Apidean analyzer"
diff --git a/code/game/objects/items/scanners/health.dm b/code/game/objects/items/scanners/health.dm
index 894d93b42a0..0ede104741c 100644
--- a/code/game/objects/items/scanners/health.dm
+++ b/code/game/objects/items/scanners/health.dm
@@ -6,6 +6,7 @@
item_state = "healthanalyzer"
slot_flags = SLOT_BELT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
throw_force = 3
w_class = WEIGHT_CLASS_SMALL
throw_speed = 5
diff --git a/code/game/objects/items/scanners/plant.dm b/code/game/objects/items/scanners/plant.dm
index a529a531dcf..570ab99514a 100644
--- a/code/game/objects/items/scanners/plant.dm
+++ b/code/game/objects/items/scanners/plant.dm
@@ -4,6 +4,7 @@
icon_state = "hydro"
item_state = "analyzer"
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/datum/seed/last_seed
var/list/last_reagents
w_class = WEIGHT_CLASS_SMALL
diff --git a/code/game/objects/items/scanners/reagent.dm b/code/game/objects/items/scanners/reagent.dm
index 2cfe06c5c82..23a5ca01029 100644
--- a/code/game/objects/items/scanners/reagent.dm
+++ b/code/game/objects/items/scanners/reagent.dm
@@ -11,6 +11,7 @@
throw_range = 20
materials_base = list(MAT_STEEL = 30, MAT_GLASS = 20)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2)
var/details = 0
diff --git a/code/game/objects/items/scanners/spectrometer.dm b/code/game/objects/items/scanners/spectrometer.dm
index c9f4cf00b59..0d839b8d867 100644
--- a/code/game/objects/items/scanners/spectrometer.dm
+++ b/code/game/objects/items/scanners/spectrometer.dm
@@ -9,6 +9,7 @@
throw_force = 5
throw_speed = 4
throw_range = 20
+ belt_storage_class = BELT_CLASS_SMALL
materials_base = list(MAT_STEEL = 30, MAT_GLASS = 20)
diff --git a/code/game/objects/items/shield/types/transforming/energy.dm b/code/game/objects/items/shield/types/transforming/energy.dm
index c38a6c6b387..b0958b3bdf3 100644
--- a/code/game/objects/items/shield/types/transforming/energy.dm
+++ b/code/game/objects/items/shield/types/transforming/energy.dm
@@ -12,6 +12,7 @@
w_class = WEIGHT_CLASS_TINY
active_weight_class = WEIGHT_CLASS_BULKY
+ belt_storage_class = BELT_CLASS_SMALL
throw_force = 5.0
throw_speed = 1
diff --git a/code/game/objects/items/stacks/marker_beacons.dm b/code/game/objects/items/stacks/marker_beacons.dm
index 6e3302fb292..d8d545a36de 100644
--- a/code/game/objects/items/stacks/marker_beacons.dm
+++ b/code/game/objects/items/stacks/marker_beacons.dm
@@ -28,6 +28,7 @@ var/list/marker_beacon_colors = list(
w_class = WEIGHT_CLASS_SMALL
skip_legacy_icon_update = TRUE
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/picked_color = "random"
/obj/item/stack/marker_beacon/ten
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index e3875489715..d0b45a59743 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -10,6 +10,7 @@
throw_speed = 4
throw_range = 20
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/heal_brute = 0
var/heal_burn = 0
var/apply_sounds
diff --git a/code/game/objects/items/stock_parts/part_replacer.dm b/code/game/objects/items/stock_parts/part_replacer.dm
index 0b8dda13e2f..baa43b5ca47 100644
--- a/code/game/objects/items/stock_parts/part_replacer.dm
+++ b/code/game/objects/items/stock_parts/part_replacer.dm
@@ -16,7 +16,7 @@
max_single_weight_class = WEIGHT_CLASS_NORMAL
max_items = 100
max_combined_volume = 200
- ui_expand_when_needed = TRUE
+ ui_expand_when_needed = 5
materials_base = list(
MAT_STEEL = 8000,
MAT_GLASS = 2500,
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 6929c5717f0..ec39c4df5ee 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -9,15 +9,14 @@
icon_state = "backpack"
w_class = WEIGHT_CLASS_BULKY
slot_flags = SLOT_BACK
- max_single_weight_class = WEIGHT_CLASS_BULKY
weight = ITEM_WEIGHT_STORAGE_BACKPACK
encumbrance = ITEM_ENCUMBRANCE_STORAGE_BACKPACK
- max_combined_volume = STORAGE_VOLUME_BACKPACK
var/flippable = 0
var/side = 0 //0 = right, 1 = left
var/hide_under_tail = 1
drop_sound = 'sound/items/drop/backpack.ogg'
pickup_sound = 'sound/items/pickup/backpack.ogg'
+ storage_datum_path = /datum/object_system/storage/backpack
/*
* Backpack Types
@@ -28,7 +27,6 @@
desc = "A backpack that opens into a localized pocket of Blue Space."
origin_tech = list(TECH_BLUESPACE = 4)
icon_state = "holdingpack"
- max_single_weight_class = WEIGHT_CLASS_BULKY
max_combined_volume = WEIGHT_VOLUME_NORMAL * 14 // 56
/obj/item/storage/backpack/holding/duffle
@@ -153,7 +151,7 @@
flat_encumbrance = ITEM_FLAT_ENCUMBRANCE_DUFFLEBAG
// todo: remove when weight system is used
slowdown = 0.25
- max_combined_volume = STORAGE_VOLUME_DUFFLEBAG
+ storage_datum_path = /datum/object_system/storage/backpack/dufflebag
/obj/item/storage/backpack/dufflebag/syndie
name = "black dufflebag"
@@ -356,10 +354,8 @@
worn_render_flags = WORN_RENDER_SLOT_ONE_FOR_ALL
worn_bodytypes = BODYTYPE_DEFAULT
icon_override = null
- max_single_weight_class = WEIGHT_CLASS_BULKY
weight = ITEM_WEIGHT_STORAGE_BACKPACK
encumbrance = ITEM_ENCUMBRANCE_STORAGE_BACKPACK
- max_combined_volume = STORAGE_VOLUME_BACKPACK
drop_sound = 'sound/items/drop/backpack.ogg'
pickup_sound = 'sound/items/pickup/backpack.ogg'
@@ -596,8 +592,6 @@
item_state = "saddlebag"
icon_state = "saddlebag"
var/icon_base = "saddlebag"
- encumbrance = ITEM_ENCUMBRANCE_STORAGE_DUFFLEBAG
- max_combined_volume = STORAGE_VOLUME_DUFFLEBAG //Saddlebags can hold more, like dufflebags
var/no_message = "You aren't the appropriate taur type to wear this!"
hide_under_tail = -1
@@ -652,7 +646,6 @@
item_state = "taurvest"
icon_state = "taurvest"
icon_base = "taurvest"
- max_combined_volume = STORAGE_VOLUME_BACKPACK
encumbrance = ITEM_ENCUMBRANCE_STORAGE_BACKPACK
/obj/item/storage/backpack/dufflebag/fluff //Black dufflebag without syndie buffs.
diff --git a/code/game/objects/items/storage/bag/trash.dm b/code/game/objects/items/storage/bag/trash.dm
new file mode 100644
index 00000000000..bca467cb394
--- /dev/null
+++ b/code/game/objects/items/storage/bag/trash.dm
@@ -0,0 +1,54 @@
+/obj/item/storage/bag/trash
+ name = "trash bag"
+ desc = "It's the heavy-duty black polymer kind. Time to take out the trash!"
+ icon = 'icons/obj/janitor.dmi'
+ icon_state = "trashbag"
+ item_state_slots = list(SLOT_ID_RIGHT_HAND = "trashbag", SLOT_ID_LEFT_HAND = "trashbag")
+ drop_sound = 'sound/items/drop/wrapper.ogg'
+ pickup_sound = 'sound/items/pickup/wrapper.ogg'
+ w_class = WEIGHT_CLASS_NORMAL
+
+ storage_datum_path = /datum/object_system/storage/trash_bag
+ max_combined_volume = WEIGHT_VOLUME_SMALL * 48
+
+/obj/item/storage/bag/trash/initialize_storage()
+ . = ..()
+ obj_storage.update_icon_on_item_change = TRUE
+
+// TODO: this is fucking broken, fix it.
+/obj/item/storage/bag/trash/update_icon_state()
+ switch(w_class)
+ if(3)
+ icon_state = "[initial(icon_state)]1"
+ if(4)
+ icon_state = "[initial(icon_state)]2"
+ if(5 to INFINITY)
+ icon_state = "[initial(icon_state)]3"
+ else
+ icon_state = "[initial(icon_state)]"
+ return ..()
+
+/obj/item/storage/bag/trash/throw_land(atom/A, datum/thrownthing/TT)
+ . = ..()
+ // let them shuffle the contents so they can grab other stuff with this if they really want
+ obj_storage?.hide()
+ var/list/athena_event_balancing_patch = contents.Copy()
+ shuffle_inplace(athena_event_balancing_patch)
+ contents = athena_event_balancing_patch
+
+/obj/item/storage/bag/trash/bluespace
+ name = "trash bag of holding"
+ w_class = WEIGHT_CLASS_NORMAL
+ max_combined_volume = WEIGHT_VOLUME_SMALL * 48 * 3
+ desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage."
+ icon_state = "bluetrashbag"
+
+/obj/item/storage/bag/trash/plasticbag
+ name = "plastic bag"
+ desc = "It's a very flimsy, very noisy alternative to a bag."
+ icon = 'icons/obj/trash.dmi'
+ icon_state = "plasticbag"
+ drop_sound = 'sound/items/drop/wrapper.ogg'
+ pickup_sound = 'sound/items/pickup/wrapper.ogg'
+ w_class = WEIGHT_CLASS_BULKY
+ max_combined_volume = WEIGHT_VOLUME_NORMAL * 3
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index b9312610c56..c9e5656125f 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -62,71 +62,6 @@
staged = max(staged, contained.get_weight_class())
set_weight_class(staged)
-// -----------------------------
-// Trash bag
-// -----------------------------
-/obj/item/storage/bag/trash
- name = "trash bag"
- desc = "It's the heavy-duty black polymer kind. Time to take out the trash!"
- icon = 'icons/obj/janitor.dmi'
- icon_state = "trashbag"
- item_state_slots = list(SLOT_ID_RIGHT_HAND = "trashbag", SLOT_ID_LEFT_HAND = "trashbag")
- drop_sound = 'sound/items/drop/wrapper.ogg'
- pickup_sound = 'sound/items/pickup/wrapper.ogg'
-
- w_class = WEIGHT_CLASS_SMALL
- max_single_weight_class = WEIGHT_CLASS_NORMAL
- max_combined_volume = WEIGHT_CLASS_SMALL * 21
- insertion_whitelist = list() // any
- insertion_blacklist = list(/obj/item/disk/nuclear)
-
-/obj/item/storage/bag/trash/initialize_storage()
- . = ..()
- obj_storage.update_icon_on_item_change = TRUE
-
-/obj/item/storage/bag/trash/update_icon_state()
- switch(w_class)
- if(3)
- icon_state = "[initial(icon_state)]1"
- if(4)
- icon_state = "[initial(icon_state)]2"
- if(5 to INFINITY)
- icon_state = "[initial(icon_state)]3"
- else
- icon_state = "[initial(icon_state)]"
- return ..()
-
-/obj/item/storage/bag/trash/bluespace
- name = "trash bag of holding"
- max_single_weight_class = WEIGHT_CLASS_HUGE
- max_combined_volume = WEIGHT_CLASS_SMALL * 56
- desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage."
- icon_state = "bluetrashbag"
-
-/obj/item/storage/bag/trash/bluespace/attackby(obj/item/W as obj, mob/user as mob)
- if(istype(W, /obj/item/storage/backpack/holding) || istype(W, /obj/item/storage/bag/trash/bluespace))
- to_chat(user, "The Bluespace interfaces of the two devices conflict and malfunction.")
- qdel(W)
- return 1
- return ..()
-
-// -----------------------------
-// Plastic Bag
-// -----------------------------
-
-/obj/item/storage/bag/plasticbag
- name = "plastic bag"
- desc = "It's a very flimsy, very noisy alternative to a bag."
- icon = 'icons/obj/trash.dmi'
- icon_state = "plasticbag"
- drop_sound = 'sound/items/drop/wrapper.ogg'
- pickup_sound = 'sound/items/pickup/wrapper.ogg'
-
- w_class = WEIGHT_CLASS_BULKY
- max_single_weight_class = WEIGHT_CLASS_SMALL
- insertion_whitelist = list() // any
- insertion_blacklist = list(/obj/item/disk/nuclear)
-
// -----------------------------
// Mining Satchel
// -----------------------------
@@ -147,7 +82,7 @@
max_items = 300
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
storage_datum_path = /datum/object_system/storage/stack
- ui_expand_when_needed = TRUE
+ ui_expand_when_needed = 5
insertion_whitelist = list(/obj/item/stack/ore)
auto_fit_weight_class_to_largest_contained = FALSE
@@ -251,7 +186,7 @@
allow_mass_gather = TRUE
allow_mass_gather_mode_switch = FALSE
auto_fit_weight_class_to_largest_contained = FALSE
- ui_expand_when_needed = TRUE
+ ui_expand_when_needed = 5
// -----------------------------
// Sheet Snatcher (Cyborg)
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index f87287643d1..34d019d14d4 100644
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -3,18 +3,33 @@
desc = "Can hold various things."
icon = 'icons/obj/clothing/belts.dmi'
icon_state = "utility"
- max_items = 7
- max_combined_volume = WEIGHT_VOLUME_NORMAL * 7 //This should ensure belts always have enough room to store whatever.
- max_single_weight_class = WEIGHT_CLASS_NORMAL
- ui_force_slot_mode = TRUE
slot_flags = SLOT_BELT
attack_verb = list("whipped", "lashed", "disciplined")
equip_sound = 'sound/items/toolbelt_equip.ogg'
drop_sound = 'sound/items/drop/toolbelt.ogg'
pickup_sound = 'sound/items/pickup/toolbelt.ogg'
worth_intrinsic = 50
+
+ storage_datum_path = /datum/object_system/storage/belt
+ max_single_weight_class = WEIGHT_CLASS_NORMAL
+
+ var/set_max_combined_belt_small
+ var/set_max_combined_belt_medium
+ var/set_max_combined_belt_large
+
var/show_above_suit = 0
+/obj/item/storage/belt/Initialize(mapload, empty)
+ . = ..()
+ if(istype(obj_storage, /datum/object_system/storage/belt))
+ var/datum/object_system/storage/belt/casted_obj_storage = obj_storage
+ if(set_max_combined_belt_large != null)
+ casted_obj_storage.max_combined_belt_large = set_max_combined_belt_large
+ if(set_max_combined_belt_medium != null)
+ casted_obj_storage.max_combined_belt_medium = set_max_combined_belt_medium
+ if(set_max_combined_belt_small != null)
+ casted_obj_storage.max_combined_belt_small = set_max_combined_belt_small
+
/obj/item/storage/belt/verb/toggle_layer()
set name = "Switch Belt Layer"
set category = VERB_CATEGORY_OBJECT
@@ -45,148 +60,10 @@
var/mob/M = src.loc
M.update_inv_belt()
-/obj/item/storage/belt/utility
- name = "tool-belt" //Carn: utility belt is nicer, but it bamboozles the text parsing.
- desc = "Can hold various tools."
- icon_state = "utility"
- item_state = "utility"
- insertion_whitelist = list(
- ///obj/item/combitool,
- /obj/item/tool/crowbar,
- /obj/item/tool/screwdriver,
- /obj/item/weldingtool,
- /obj/item/tool/wirecutters,
- /obj/item/tool/wrench,
- /obj/item/multitool,
- /obj/item/flashlight,
- // TODO: PLEASE FOR THE LOVE OF GOD REFACTOR FUCKING BELTS ALREADY
- /obj/item/cell/basic/tier_1/weapon,
- /obj/item/cell/basic/tier_2/weapon,
- /obj/item/cell/basic/tier_3/weapon,
- /obj/item/cell/basic/tier_4/weapon,
- /obj/item/cell/basic/tier_5/weapon,
- /obj/item/cell/regen/weapon,
- /obj/item/cell/regen/fractal/weapon,
- /obj/item/cell/infinite/weapon,
- /obj/item/cell/microfission/weapon,
- /obj/item/cell/basic/tier_1/small,
- /obj/item/cell/basic/tier_2/small,
- /obj/item/cell/basic/tier_3/small,
- /obj/item/cell/basic/tier_4/small,
- /obj/item/cell/basic/tier_5/small,
- /obj/item/cell/regen/small,
- /obj/item/cell/regen/fractal/small,
- /obj/item/cell/infinite/small,
- /obj/item/cell/microfission/small,
- /obj/item/stack/cable_coil,
- /obj/item/t_scanner,
- /obj/item/atmos_analyzer,
- /obj/item/clothing/glasses,
- /obj/item/clothing/gloves,
- /obj/item/pda,
- /obj/item/megaphone,
- /obj/item/barrier_tape_roll,
- /obj/item/radio/headset,
- /obj/item/robotanalyzer,
- /obj/item/material/minihoe,
- /obj/item/material/knife/machete/hatchet,
- /obj/item/plant_analyzer,
- /obj/item/extinguisher/mini,
- /obj/item/duct_tape_roll,
- /obj/item/switchtool,
- /obj/item/integrated_electronics/wirer,
- /obj/item/integrated_electronics/debugger,
- )
-
-/obj/item/storage/belt/utility/full
- starts_with = list(
- /obj/item/tool/screwdriver,
- /obj/item/tool/wrench,
- /obj/item/weldingtool,
- /obj/item/tool/crowbar,
- /obj/item/tool/wirecutters,
- /obj/item/stack/cable_coil/random_belt
- )
-
-/obj/item/storage/belt/utility/atmostech
- starts_with = list(
- /obj/item/tool/screwdriver,
- /obj/item/tool/wrench,
- /obj/item/weldingtool,
- /obj/item/tool/crowbar,
- /obj/item/tool/wirecutters,
- )
-
-/obj/item/storage/belt/utility/chief
- name = "chief engineer's toolbelt"
- desc = "Holds tools, looks snazzy."
- icon_state = "utilitybelt_ce"
- item_state = "utility_ce"
-
-/obj/item/storage/belt/utility/chief/full
- starts_with = list(
- /obj/item/tool/screwdriver/power,
- /obj/item/tool/crowbar/power,
- /obj/item/weldingtool/experimental,
- /obj/item/multitool,
- /obj/item/stack/cable_coil/random_belt,
- /obj/item/extinguisher/mini,
- /obj/item/atmos_analyzer/longrange
- )
-
/obj/item/storage/belt/medical
name = "medical belt"
desc = "Can hold various medical equipment."
icon_state = "medical"
- insertion_whitelist = list(
- /obj/item/healthanalyzer,
- /obj/item/dnainjector,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/glass/beaker,
- /obj/item/reagent_containers/glass/bottle,
- /obj/item/reagent_containers/pill,
- /obj/item/reagent_containers/syringe,
- /obj/item/storage/quickdraw/syringe_case,
- /obj/item/flame/lighter/zippo,
- /obj/item/storage/fancy/cigarettes,
- /obj/item/storage/pill_bottle,
- /obj/item/stack/medical,
- /obj/item/radio/headset,
- /obj/item/pda,
- /obj/item/barrier_tape_roll,
- /obj/item/megaphone,
- /obj/item/clothing/mask/surgical,
- /obj/item/clothing/head/surgery,
- /obj/item/clothing/gloves,
- /obj/item/reagent_containers/hypospray,
- /obj/item/hypospray,
- /obj/item/reagent_containers/glass/hypovial,
- /obj/item/clothing/glasses,
- /obj/item/tool/crowbar,
- /obj/item/flashlight,
- // TODO: PLEASE FOR THE LOVE OF GOD REFACTOR FUCKING BELTS ALREADY
- /obj/item/cell/basic/tier_1/weapon,
- /obj/item/cell/basic/tier_2/weapon,
- /obj/item/cell/basic/tier_3/weapon,
- /obj/item/cell/basic/tier_4/weapon,
- /obj/item/cell/basic/tier_5/weapon,
- /obj/item/cell/regen/weapon,
- /obj/item/cell/regen/fractal/weapon,
- /obj/item/cell/infinite/weapon,
- /obj/item/cell/microfission/weapon,
- /obj/item/cell/basic/tier_1/small,
- /obj/item/cell/basic/tier_2/small,
- /obj/item/cell/basic/tier_3/small,
- /obj/item/cell/basic/tier_4/small,
- /obj/item/cell/basic/tier_5/small,
- /obj/item/cell/regen/small,
- /obj/item/cell/regen/fractal/small,
- /obj/item/cell/infinite/small,
- /obj/item/cell/microfission/small,
- /obj/item/extinguisher/mini,
- /obj/item/switchtool/surgery,
- /obj/item/storage/quickdraw/syringe_case
- )
/obj/item/storage/belt/medical/emt
name = "EMT utility belt"
@@ -199,60 +76,6 @@
icon_state = "security"
max_items = 7
max_single_weight_class = WEIGHT_CLASS_NORMAL
- insertion_whitelist = list(
- /obj/item/tape_recorder,
- /obj/item/barrier_tape_roll,
- /obj/item/clothing/glasses,
- /obj/item/flashlight,
- // TODO: PLEASE FOR THE LOVE OF GOD REFACTOR FUCKING BELTS ALREADY
- /obj/item/cell/basic/tier_1/weapon,
- /obj/item/cell/basic/tier_2/weapon,
- /obj/item/cell/basic/tier_3/weapon,
- /obj/item/cell/basic/tier_4/weapon,
- /obj/item/cell/basic/tier_5/weapon,
- /obj/item/cell/regen/weapon,
- /obj/item/cell/regen/fractal/weapon,
- /obj/item/cell/infinite/weapon,
- /obj/item/cell/microfission/weapon,
- /obj/item/cell/basic/tier_1/small,
- /obj/item/cell/basic/tier_2/small,
- /obj/item/cell/basic/tier_3/small,
- /obj/item/cell/basic/tier_4/small,
- /obj/item/cell/basic/tier_5/small,
- /obj/item/cell/regen/small,
- /obj/item/cell/regen/fractal/small,
- /obj/item/cell/infinite/small,
- /obj/item/cell/microfission/small,
- /obj/item/reagent_containers/spray/luminol,
- /obj/item/sample,
- /obj/item/forensics/sample_kit/powder,
- /obj/item/forensics/swab,
- /obj/item/uv_light,
- /obj/item/forensics/sample_kit,
- /obj/item/photo,
- /obj/item/camera_film,
- /obj/item/camera,
- /obj/item/autopsy_scanner,
- /obj/item/mass_spectrometer,
- /obj/item/clothing/accessory/badge,
- /obj/item/reagent_scanner,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/syringe,
- /obj/item/pda,
- /obj/item/hailer,
- /obj/item/megaphone,
- /obj/item/radio/headset,
- /obj/item/clothing/gloves,
- /obj/item/barrier_tape_roll,
- /obj/item/reagent_containers/spray/pepper,
- /obj/item/handcuffs,
- /obj/item/flash,
- /obj/item/flame/lighter,
- /obj/item/reagent_containers/food/snacks/donut/,
- /obj/item/ammo_magazine,
- /obj/item/gun/projectile/ballistic/colt/detective,
- /obj/item/holowarrant
- )
/obj/item/storage/belt/explorer
name = "pathfinder's bandolier"
@@ -261,102 +84,16 @@
max_items = 7
max_combined_volume = WEIGHT_VOLUME_NORMAL * 7
show_above_suit = 1
- insertion_whitelist = list(
- /obj/item/grenade,
- /obj/item/tool/crowbar,
- /obj/item/tool/screwdriver,
- /obj/item/weldingtool,
- /obj/item/tool/wirecutters,
- /obj/item/tool/wrench,
- /obj/item/pickaxe/,
- /obj/item/multitool,
- /obj/item/stack/cable_coil,
- /obj/item/t_scanner,
- /obj/item/atmos_analyzer,
- /obj/item/flashlight,
- // TODO: PLEASE FOR THE LOVE OF GOD REFACTOR FUCKING BELTS ALREADY
- /obj/item/cell/basic/tier_1/weapon,
- /obj/item/cell/basic/tier_2/weapon,
- /obj/item/cell/basic/tier_3/weapon,
- /obj/item/cell/basic/tier_4/weapon,
- /obj/item/cell/basic/tier_5/weapon,
- /obj/item/cell/regen/weapon,
- /obj/item/cell/regen/fractal/weapon,
- /obj/item/cell/infinite/weapon,
- /obj/item/cell/microfission/weapon,
- /obj/item/cell/basic/tier_1/small,
- /obj/item/cell/basic/tier_2/small,
- /obj/item/cell/basic/tier_3/small,
- /obj/item/cell/basic/tier_4/small,
- /obj/item/cell/basic/tier_5/small,
- /obj/item/cell/regen/small,
- /obj/item/cell/regen/fractal/small,
- /obj/item/cell/infinite/small,
- /obj/item/cell/microfission/small,
- /obj/item/material/butterfly,
- /obj/item/material/knife,
- /obj/item/melee/transforming/energy/sword,
- /obj/item/shield/transforming/energy,
- /obj/item/ammo_casing/,
- /obj/item/ammo_magazine/,
- /obj/item/storage/box/beanbags,
- /obj/item/storage/box/shotgunammo,
- /obj/item/storage/box/shotgunshells,
- /obj/item/healthanalyzer,
- /obj/item/robotanalyzer,
- /obj/item/reagent_containers/glass/beaker,
- /obj/item/reagent_containers/glass/bottle,
- /obj/item/reagent_containers/syringe,
- /obj/item/reagent_containers/hypospray,
- /obj/item/hypospray,
- /obj/item/storage/pill_bottle,
- /obj/item/stack/medical,
- /obj/item/stack/marker_beacon,
- /obj/item/flashlight,
- /obj/item/extinguisher/mini,
- /obj/item/storage/quickdraw/syringe_case,
- /obj/item/photo,
- /obj/item/camera_film,
- /obj/item/camera,
- /obj/item/tape_recorder,
- /obj/item/barrier_tape_roll,
- /obj/item/healthanalyzer,
- /obj/item/geiger_counter,
- /obj/item/gps,
- /obj/item/switchtool,
- /obj/item/ano_scanner
- )
/obj/item/storage/belt/soulstone
name = "soul stone belt"
desc = "Designed for ease of access to the shards during a fight, as to not let a single enemy spirit slip away"
icon_state = "soulstone"
max_items = 6
- insertion_whitelist = list(
- /obj/item/soulstone
- )
/obj/item/storage/belt/soulstone/full
starts_with = list(/obj/item/soulstone = 6)
-/obj/item/storage/belt/utility/alien
- name = "alien belt"
- desc = "A belt(?) that can hold things."
- icon = 'icons/obj/abductor.dmi'
- icon_state = "belt"
- item_state = "security"
-
-/obj/item/storage/belt/utility/alien/full
- starts_with = list(
- /obj/item/tool/screwdriver/alien,
- /obj/item/tool/wrench/alien,
- /obj/item/weldingtool/alien,
- /obj/item/tool/crowbar/alien,
- /obj/item/tool/wirecutters/alien,
- /obj/item/multitool/alien,
- /obj/item/stack/cable_coil/alien
- )
-
/obj/item/storage/belt/medical/alien
name = "alien belt"
desc = "A belt(?) that can hold things."
@@ -364,52 +101,6 @@
icon_state = "belt"
item_state = "security"
max_items = 8
- insertion_whitelist = list(
- /obj/item/healthanalyzer,
- /obj/item/dnainjector,
- /obj/item/reagent_containers/dropper,
- /obj/item/reagent_containers/glass/beaker,
- /obj/item/reagent_containers/glass/bottle,
- /obj/item/reagent_containers/pill,
- /obj/item/reagent_containers/syringe,
- /obj/item/flame/lighter/zippo,
- /obj/item/storage/fancy/cigarettes,
- /obj/item/storage/pill_bottle,
- /obj/item/stack/medical,
- /obj/item/radio/headset,
- /obj/item/pda,
- /obj/item/barrier_tape_roll,
- /obj/item/megaphone,
- /obj/item/clothing/mask/surgical,
- /obj/item/clothing/head/surgery,
- /obj/item/clothing/gloves,
- /obj/item/reagent_containers/hypospray,
- /obj/item/hypospray,
- /obj/item/clothing/glasses,
- /obj/item/tool/crowbar,
- /obj/item/flashlight,
- // TODO: PLEASE FOR THE LOVE OF GOD REFACTOR FUCKING BELTS ALREADY
- /obj/item/cell/basic/tier_1/weapon,
- /obj/item/cell/basic/tier_2/weapon,
- /obj/item/cell/basic/tier_3/weapon,
- /obj/item/cell/basic/tier_4/weapon,
- /obj/item/cell/basic/tier_5/weapon,
- /obj/item/cell/regen/weapon,
- /obj/item/cell/regen/fractal/weapon,
- /obj/item/cell/infinite/weapon,
- /obj/item/cell/microfission/weapon,
- /obj/item/cell/basic/tier_1/small,
- /obj/item/cell/basic/tier_2/small,
- /obj/item/cell/basic/tier_3/small,
- /obj/item/cell/basic/tier_4/small,
- /obj/item/cell/basic/tier_5/small,
- /obj/item/cell/regen/small,
- /obj/item/cell/regen/fractal/small,
- /obj/item/cell/infinite/small,
- /obj/item/cell/microfission/small,
- /obj/item/extinguisher/mini,
- /obj/item/surgical
- )
/obj/item/storage/belt/medical/alien
starts_with = list(
@@ -428,22 +119,6 @@
desc = "Proves to the world that you are the strongest!"
icon_state = "champion"
max_items = 1
- insertion_whitelist = list(
- "/obj/item/clothing/mask/luchador"
- )
-
-/obj/item/storage/belt/security/tactical
- name = "combat belt"
- desc = "Can hold security gear like handcuffs and flashes, with more pouches for more storage."
- icon_state = "swat"
- max_items = 9
- max_single_weight_class = WEIGHT_CLASS_NORMAL
- max_combined_volume = WEIGHT_VOLUME_NORMAL * 7
-
-/obj/item/storage/belt/security/tactical/bandolier
- name = "combat belt"
- desc = "Can hold security gear like handcuffs and flashes, with more pouches for more storage."
- icon_state = "bandolier"
/obj/item/storage/belt/spike_bandolier
name = "spike bandolier"
@@ -462,95 +137,12 @@
max_items = 7
max_single_weight_class = WEIGHT_CLASS_NORMAL
worth_intrinsic = 35
- insertion_whitelist = list(
- /obj/item/clothing/glasses,
- /obj/item/flashlight,
- // TODO: PLEASE FOR THE LOVE OF GOD REFACTOR FUCKING BELTS ALREADY
- /obj/item/cell/basic/tier_1/weapon,
- /obj/item/cell/basic/tier_2/weapon,
- /obj/item/cell/basic/tier_3/weapon,
- /obj/item/cell/basic/tier_4/weapon,
- /obj/item/cell/basic/tier_5/weapon,
- /obj/item/cell/regen/weapon,
- /obj/item/cell/regen/fractal/weapon,
- /obj/item/cell/infinite/weapon,
- /obj/item/cell/microfission/weapon,
- /obj/item/cell/basic/tier_1/small,
- /obj/item/cell/basic/tier_2/small,
- /obj/item/cell/basic/tier_3/small,
- /obj/item/cell/basic/tier_4/small,
- /obj/item/cell/basic/tier_5/small,
- /obj/item/cell/regen/small,
- /obj/item/cell/regen/fractal/small,
- /obj/item/cell/infinite/small,
- /obj/item/cell/microfission/small,
- /obj/item/grenade,
- /obj/item/pda,
- /obj/item/radio/headset,
- /obj/item/clothing/gloves,
- /obj/item/clothing/mask/surgical, //sterile mask,
- /obj/item/assembly/mousetrap,
- /obj/item/light/bulb,
- /obj/item/light/tube,
- /obj/item/flame/lighter,
- /obj/item/megaphone,
- /obj/item/barrier_tape_roll,
- /obj/item/reagent_containers/spray,
- /obj/item/soap
- )
/obj/item/storage/belt/archaeology
name = "excavation gear-belt"
desc = "Can hold various excavation gear."
icon_state = "gear"
worth_intrinsic = 65
- insertion_whitelist = list(
- /obj/item/storage/box/samplebags,
- /obj/item/core_sampler,
- /obj/item/beacon_locator,
- /obj/item/radio/beacon,
- /obj/item/gps,
- /obj/item/measuring_tape,
- /obj/item/flashlight,
- // TODO: PLEASE FOR THE LOVE OF GOD REFACTOR FUCKING BELTS ALREADY
- /obj/item/cell/basic/tier_1/weapon,
- /obj/item/cell/basic/tier_2/weapon,
- /obj/item/cell/basic/tier_3/weapon,
- /obj/item/cell/basic/tier_4/weapon,
- /obj/item/cell/basic/tier_5/weapon,
- /obj/item/cell/regen/weapon,
- /obj/item/cell/regen/fractal/weapon,
- /obj/item/cell/infinite/weapon,
- /obj/item/cell/microfission/weapon,
- /obj/item/cell/basic/tier_1/small,
- /obj/item/cell/basic/tier_2/small,
- /obj/item/cell/basic/tier_3/small,
- /obj/item/cell/basic/tier_4/small,
- /obj/item/cell/basic/tier_5/small,
- /obj/item/cell/regen/small,
- /obj/item/cell/regen/fractal/small,
- /obj/item/cell/infinite/small,
- /obj/item/cell/microfission/small,
- /obj/item/pickaxe,
- /obj/item/depth_scanner,
- /obj/item/camera,
- /obj/item/paper,
- /obj/item/photo,
- /obj/item/folder,
- /obj/item/pen,
- /obj/item/folder,
- /obj/item/clipboard,
- /obj/item/anodevice,
- /obj/item/clothing/glasses,
- /obj/item/tool/wrench,
- /obj/item/storage/excavation,
- /obj/item/anobattery,
- /obj/item/ano_scanner,
- /obj/item/pickaxe/hand,
- /obj/item/hand_labeler,
- /obj/item/xenoarch_multi_tool,
- /obj/item/pickaxe/excavationdrill
- )
/obj/item/storage/belt/fannypack
name = "leather fannypack"
@@ -611,13 +203,14 @@
desc = "An ornate sheath designed to hold an officer's blade."
icon_state = "sheath-sabre"
max_items = 1
+ storage_datum_path = /datum/object_system/storage
insertion_whitelist = list(
/obj/item/material/sword/sabre,
/obj/item/melee/baton/stunsword,
- )
+ )
starts_with = list(
/obj/item/material/sword/sabre,
- )
+ )
/obj/item/storage/belt/sheath/initialize_storage()
. = ..()
@@ -644,93 +237,30 @@
name = "dual holster gunbelt"
desc = "Belts like these were popular on old Earth, but were largely supplanted by modular holsters. This gunbelt is too bulky to be comfortably anchored to clothes without support."
icon_state = "dual_holster"
- max_items = 2
- max_single_weight_class = WEIGHT_CLASS_NORMAL
- insertion_whitelist = list(
- /obj/item/gun/projectile/energy/alien,
- /obj/item/gun/projectile/energy/captain,
- /obj/item/gun/projectile/energy/crossbow,
- /obj/item/gun/projectile/energy/decloner,
- /obj/item/gun/projectile/energy/floragun,
- /obj/item/gun/projectile/energy/gun,
- /obj/item/gun/projectile/energy/gun/nuclear,
- /obj/item/gun/projectile/energy/ionrifle/pistol,
- /obj/item/gun/projectile/energy/lasertag,
- /obj/item/gun/projectile/energy/netgun,
- /obj/item/gun/projectile/energy/phasegun/pistol,
- /obj/item/gun/projectile/energy/nt_pulse/carbine,
- /obj/item/gun/projectile/energy/retro,
- /obj/item/gun/projectile/energy/nt_pmd/service_revolver,
- /obj/item/gun/projectile/energy/stunrevolver,
- /obj/item/gun/projectile/energy/taser,
- /obj/item/gun/projectile/energy/toxgun,
- /obj/item/gun/projectile/energy/zip,
- /obj/item/gun/projectile/ballistic/colt,
- /obj/item/gun/projectile/ballistic/contender,
- /obj/item/gun/projectile/ballistic/dartgun,
- /obj/item/gun/projectile/ballistic/deagle,
- /obj/item/gun/projectile/ballistic/derringer,
- /obj/item/gun/projectile/ballistic/gyropistol,
- /obj/item/gun/projectile/ballistic/luger,
- /obj/item/gun/projectile/ballistic/r9,
- /obj/item/gun/projectile/ballistic/revolver,
- /obj/item/gun/projectile/ballistic/sec,
- /obj/item/gun/projectile/ballistic/shotgun/doublebarrel/sawn,
- /obj/item/gun/projectile/ballistic/shotgun/flare,
- /obj/item/gun/projectile/ballistic/silenced,
- /obj/item/gun/projectile/ballistic/p92x,
- /obj/item/gun/projectile/ballistic/pistol,
- /obj/item/gun/projectile/ballistic/pirate
- )
+ set_max_combined_belt_large = 2
/obj/item/storage/belt/quiver
name = "leather quiver"
desc = "A quiver made from the hide of some animal. Used to hold arrows."
icon_state = "quiver"
- max_items = 15
max_single_weight_class = WEIGHT_CLASS_NORMAL
+ set_max_combined_belt_small = 30
insertion_whitelist = list(
- /obj/item/ammo_casing/arrow
- )
+ /obj/item/ammo_casing/arrow,
+ )
/obj/item/storage/belt/quiver/full
name = "leather quiver"
desc = "A quiver made from the hide of some animal. Used to hold arrows."
icon_state = "quiver"
- max_items = 15
- max_single_weight_class = WEIGHT_CLASS_NORMAL
- insertion_whitelist = list(
- /obj/item/ammo_casing/arrow
- )
starts_with = list(
- /obj/item/ammo_casing/arrow = 15
- )
+ /obj/item/ammo_casing/arrow = /obj/item/storage/belt/quiver::set_max_combined_belt_small,
+ )
/obj/item/storage/belt/quiver/full/ash
name = "leather quiver"
desc = "A quiver made from the hide of some animal. Used to hold arrows."
icon_state = "quiver"
- max_items = 15
- max_single_weight_class = WEIGHT_CLASS_NORMAL
- insertion_whitelist = list(
- /obj/item/ammo_casing/arrow
- )
starts_with = list(
- /obj/item/ammo_casing/arrow/bone = 15
- )
-
-/obj/item/storage/belt/utility/crystal
- name = "crystalline tool harness"
- desc = "A segmented belt of strange crystalline material."
- icon_state = "utilitybelt_crystal"
- item_state = "utilitybelt_crystal"
-
-/obj/item/storage/belt/utility/crystal/Initialize()
- new /obj/item/multitool/crystal(src)
- new /obj/item/tool/wrench/crystal(src)
- new /obj/item/tool/crowbar/crystal(src)
- new /obj/item/tool/screwdriver/crystal(src)
- new /obj/item/tool/wirecutters/crystal(src)
- new /obj/item/weldingtool/electric/crystal(src)
- update_icon()
- . = ..()
+ /obj/item/ammo_casing/arrow/bone = /obj/item/storage/belt/quiver::set_max_combined_belt_small,
+ )
diff --git a/code/game/objects/items/storage/belt/security.dm b/code/game/objects/items/storage/belt/security.dm
index 401fa4e3583..27050f75861 100644
--- a/code/game/objects/items/storage/belt/security.dm
+++ b/code/game/objects/items/storage/belt/security.dm
@@ -5,63 +5,26 @@
desc = "Standard issue belt capable of storing many kinds of tactical gear."
icon_state = "security"
max_single_weight_class = WEIGHT_CLASS_NORMAL
- insertion_whitelist = list(
- /obj/item/grenade,
- /obj/item/reagent_containers/spray/pepper,
- /obj/item/handcuffs,
- /obj/item/flash,
- /obj/item/clothing/glasses,
- /obj/item/ammo_casing/a10g,
- /obj/item/ammo_casing/a12g,
- /obj/item/ammo_magazine,
- // TODO: PLEASE FOR THE LOVE OF GOD REFACTOR FUCKING BELTS ALREADY
- /obj/item/cell/basic/tier_1/weapon,
- /obj/item/cell/basic/tier_2/weapon,
- /obj/item/cell/basic/tier_3/weapon,
- /obj/item/cell/basic/tier_4/weapon,
- /obj/item/cell/basic/tier_5/weapon,
- /obj/item/cell/regen/weapon,
- /obj/item/cell/regen/fractal/weapon,
- /obj/item/cell/infinite/weapon,
- /obj/item/cell/microfission/weapon,
- /obj/item/cell/basic/tier_1/small,
- /obj/item/cell/basic/tier_2/small,
- /obj/item/cell/basic/tier_3/small,
- /obj/item/cell/basic/tier_4/small,
- /obj/item/cell/basic/tier_5/small,
- /obj/item/cell/regen/small,
- /obj/item/cell/regen/fractal/small,
- /obj/item/cell/infinite/small,
- /obj/item/cell/microfission/small,
- /obj/item/melee/baton,
- /obj/item/gun/projectile/energy/taser,
- /obj/item/gun/projectile/energy/stunrevolver,
- /obj/item/gun/projectile/energy/gun,
- /obj/item/flame/lighter,
- /obj/item/flashlight,
- /obj/item/tape_recorder,
- /obj/item/barrier_tape_roll,
- /obj/item/pda,
- /obj/item/radio/headset,
- /obj/item/clothing/gloves,
- /obj/item/hailer,
- /obj/item/megaphone,
- /obj/item/melee,
- /obj/item/clothing/accessory/badge,
- /obj/item/gun/projectile/ballistic/sec,
- /obj/item/gun/projectile/ballistic/p92x,
- /obj/item/barrier_tape_roll,
- /obj/item/gun/projectile/ballistic/colt/detective,
- /obj/item/holowarrant,
- /obj/item/gun/projectile/energy/nt_isd/sidearm,
- )
+ set_max_combined_belt_large = /datum/object_system/storage/belt::max_combined_belt_large + 1
+ set_max_combined_belt_medium = /datum/object_system/storage/belt::max_combined_belt_medium
/obj/item/storage/belt/security/nt_isd_preload
starts_with = list(
/obj/item/handcuffs,
/obj/item/flash,
/obj/item/gun/projectile/energy/nt_isd/sidearm/with_light,
- /obj/item/melee/baton,
+ /obj/item/melee/baton/loaded,
/obj/item/cell/basic/tier_2/weapon,
/obj/item/reagent_containers/spray/pepper,
)
+
+/obj/item/storage/belt/security/tactical
+ name = "combat belt"
+ desc = "Can hold security gear like handcuffs and flashes, with more pouches for more storage."
+ icon_state = "swat"
+ set_max_combined_belt_medium = /obj/item/storage/belt/security::set_max_combined_belt_medium + 2
+
+/obj/item/storage/belt/security/tactical/bandolier
+ name = "combat belt"
+ desc = "Can hold security gear like handcuffs and flashes, with more pouches for more storage."
+ icon_state = "bandolier"
diff --git a/code/game/objects/items/storage/belt/utility.dm b/code/game/objects/items/storage/belt/utility.dm
new file mode 100644
index 00000000000..edd8b9a69d6
--- /dev/null
+++ b/code/game/objects/items/storage/belt/utility.dm
@@ -0,0 +1,76 @@
+
+/obj/item/storage/belt/utility
+ name = "tool-belt" //Carn: utility belt is nicer, but it bamboozles the text parsing.
+ desc = "Can hold various tools."
+ icon_state = "utility"
+ item_state = "utility"
+
+/obj/item/storage/belt/utility/full
+ starts_with = list(
+ /obj/item/tool/screwdriver,
+ /obj/item/tool/wrench,
+ /obj/item/weldingtool,
+ /obj/item/tool/crowbar,
+ /obj/item/tool/wirecutters,
+ /obj/item/stack/cable_coil/random_belt
+ )
+
+/obj/item/storage/belt/utility/atmostech
+ starts_with = list(
+ /obj/item/tool/screwdriver,
+ /obj/item/tool/wrench,
+ /obj/item/weldingtool,
+ /obj/item/tool/crowbar,
+ /obj/item/tool/wirecutters,
+ )
+
+/obj/item/storage/belt/utility/chief
+ name = "chief engineer's toolbelt"
+ desc = "Holds tools, looks snazzy."
+ icon_state = "utilitybelt_ce"
+ item_state = "utility_ce"
+
+/obj/item/storage/belt/utility/chief/full
+ starts_with = list(
+ /obj/item/tool/screwdriver/power,
+ /obj/item/tool/crowbar/power,
+ /obj/item/weldingtool/experimental,
+ /obj/item/multitool,
+ /obj/item/stack/cable_coil/random_belt,
+ /obj/item/extinguisher/mini,
+ /obj/item/atmos_analyzer/longrange
+ )
+
+/obj/item/storage/belt/utility/alien
+ name = "alien belt"
+ desc = "A belt(?) that can hold things."
+ icon = 'icons/obj/abductor.dmi'
+ icon_state = "belt"
+ item_state = "security"
+
+/obj/item/storage/belt/utility/alien/full
+ starts_with = list(
+ /obj/item/tool/screwdriver/alien,
+ /obj/item/tool/wrench/alien,
+ /obj/item/weldingtool/alien,
+ /obj/item/tool/crowbar/alien,
+ /obj/item/tool/wirecutters/alien,
+ /obj/item/multitool/alien,
+ /obj/item/stack/cable_coil/alien
+ )
+
+/obj/item/storage/belt/utility/crystal
+ name = "crystalline tool harness"
+ desc = "A segmented belt of strange crystalline material."
+ icon_state = "utilitybelt_crystal"
+ item_state = "utilitybelt_crystal"
+
+/obj/item/storage/belt/utility/crystal/Initialize()
+ new /obj/item/multitool/crystal(src)
+ new /obj/item/tool/wrench/crystal(src)
+ new /obj/item/tool/crowbar/crystal(src)
+ new /obj/item/tool/screwdriver/crystal(src)
+ new /obj/item/tool/wirecutters/crystal(src)
+ new /obj/item/weldingtool/electric/crystal(src)
+ update_icon()
+ . = ..()
diff --git a/code/game/objects/items/storage/medical/hypokit.dm b/code/game/objects/items/storage/medical/hypokit.dm
index 4ca9af08568..1051f93dc81 100644
--- a/code/game/objects/items/storage/medical/hypokit.dm
+++ b/code/game/objects/items/storage/medical/hypokit.dm
@@ -5,6 +5,7 @@
inhand_icon = 'icons/items/storage/firstaid.dmi'
icon_state = "normal"
slot_flags = SLOT_BELT
+ storage_datum_path = /datum/object_system/storage/hypokit
max_combined_volume = STORAGE_VOLUME_BOX
weight_volume = ITEM_VOLUME_BOX
insertion_whitelist = list(
diff --git a/code/game/objects/items/storage/medical/pill_bottle.dm b/code/game/objects/items/storage/medical/pill_bottle.dm
index 16abc9ace2e..e875140af05 100644
--- a/code/game/objects/items/storage/medical/pill_bottle.dm
+++ b/code/game/objects/items/storage/medical/pill_bottle.dm
@@ -7,17 +7,15 @@
pickup_sound = 'sound/items/pickup/pillbottle.ogg'
item_state_slots = list(SLOT_ID_RIGHT_HAND = "contsolid", SLOT_ID_LEFT_HAND = "contsolid")
w_class = WEIGHT_CLASS_SMALL
- insertion_whitelist = list(/obj/item/reagent_containers/pill,/obj/item/dice,/obj/item/paper)
- allow_quick_empty = TRUE
- allow_mass_gather = TRUE
sfx_insert = null
sfx_remove = null
sfx_open = null
- max_combined_volume = WEIGHT_VOLUME_TINY * 14
- max_single_weight_class = WEIGHT_CLASS_TINY
materials_base = list(MAT_PLASTIC = 80)
item_flags = ITEM_CAREFUL_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD | ITEM_EASY_LATHE_DECONSTRUCT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
+ storage_datum_path = /datum/object_system/storage/pill_bottle
+ insertion_whitelist = list(/obj/item/reagent_containers/pill,/obj/item/dice,/obj/item/paper)
var/label_text = ""
var/labeled = 0
diff --git a/code/game/objects/items/storage/misc_legacy/fancy.dm b/code/game/objects/items/storage/misc_legacy/fancy.dm
index e7f388f8987..e47e42e180d 100644
--- a/code/game/objects/items/storage/misc_legacy/fancy.dm
+++ b/code/game/objects/items/storage/misc_legacy/fancy.dm
@@ -239,6 +239,7 @@
icon_state = "cigpacket"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "cigpacket", SLOT_ID_LEFT_HAND = "cigpacket")
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
w_class = WEIGHT_CLASS_TINY
throw_force = 2
slot_flags = SLOT_BELT | SLOT_EARS
diff --git a/code/game/objects/items/storage/quickdraw.dm b/code/game/objects/items/storage/quickdraw.dm
index 3c64736e68c..113144e7a80 100644
--- a/code/game/objects/items/storage/quickdraw.dm
+++ b/code/game/objects/items/storage/quickdraw.dm
@@ -67,6 +67,7 @@
w_class = WEIGHT_CLASS_SMALL
max_single_weight_class = WEIGHT_CLASS_TINY
max_combined_volume = WEIGHT_CLASS_TINY * 6 //Capable of holding six syringes
+ belt_storage_class = BELT_CLASS_SMALL
//Can hold syringes and autoinjectors, but also pills if you really wanted. Syringe-shaped objects like pens and cigarettes also fit, but why would you do that?
insertion_whitelist = list(/obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray/autoinjector,
diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm
index 99871e90fde..9347fde7340 100644
--- a/code/game/objects/items/storage/storage.dm
+++ b/code/game/objects/items/storage/storage.dm
@@ -20,29 +20,32 @@
var/list/insertion_blacklist
var/list/insertion_allow
- var/max_single_weight_class = WEIGHT_CLASS_SMALL
+ var/max_single_weight_class
var/max_combined_weight_class
- var/max_combined_volume = WEIGHT_VOLUME_SMALL * 4
+ var/max_combined_volume
var/max_items
+ var/weight_propagation
+ // always set on base type for :: purposes
var/weight_subtract = 0
+ // always set on base type for :: purposes
var/weight_multiply = 1
- var/allow_mass_gather = FALSE
- var/allow_mass_gather_mode_switch = TRUE
- var/mass_gather_mode = STORAGE_QUICK_GATHER_COLLECT_ALL
+ var/allow_mass_gather
+ var/allow_mass_gather_mode_switch
+ var/mass_gather_mode
- var/allow_quick_empty = TRUE
- var/allow_quick_empty_via_clickdrag = TRUE
- var/allow_quick_empty_via_attack_self = FALSE
+ var/allow_quick_empty
+ var/allow_quick_empty_via_clickdrag
+ var/allow_quick_empty_via_attack_self
var/sfx_open = "rustle"
var/sfx_insert = "rustle"
var/sfx_remove = "rustle"
- var/ui_numerical_mode = FALSE
- var/ui_expand_when_needed = FALSE
- var/ui_force_slot_mode = FALSE
+ var/ui_numerical_mode
+ var/ui_expand_when_needed
+ var/ui_force_slot_mode
//* Initialization *//
@@ -98,26 +101,44 @@
obj_storage.set_insertion_whitelist(insertion_whitelist)
obj_storage.set_insertion_blacklist(insertion_blacklist)
- obj_storage.max_single_weight_class = max_single_weight_class
- obj_storage.max_combined_weight_class = max_combined_weight_class
- obj_storage.max_combined_volume = max_combined_volume
- obj_storage.max_items = max_items
+ if(!isnull(max_single_weight_class))
+ obj_storage.max_single_weight_class = max_single_weight_class
+ if(!isnull(max_combined_weight_class))
+ obj_storage.max_combined_weight_class = max_combined_weight_class
+ if(!isnull(max_combined_volume))
+ obj_storage.max_combined_volume = max_combined_volume
+ if(!isnull(max_items))
+ obj_storage.max_items = max_items
+ if(!isnull(weight_propagation))
+ obj_storage.weight_propagation = weight_propagation
obj_storage.weight_subtract = weight_subtract
obj_storage.weight_multiply = weight_multiply
- obj_storage.allow_mass_gather = allow_mass_gather
- obj_storage.allow_mass_gather_mode_switch = allow_mass_gather_mode_switch
- obj_storage.mass_gather_mode = mass_gather_mode
+ if(!isnull(allow_mass_gather))
+ obj_storage.allow_mass_gather = allow_mass_gather
+ if(!isnull(allow_mass_gather_mode_switch))
+ obj_storage.allow_mass_gather_mode_switch = allow_mass_gather_mode_switch
+ if(!isnull(mass_gather_mode))
+ obj_storage.mass_gather_mode = mass_gather_mode
- obj_storage.allow_quick_empty = allow_quick_empty
- obj_storage.allow_quick_empty_via_clickdrag = allow_quick_empty_via_clickdrag
- obj_storage.allow_quick_empty_via_attack_self = allow_quick_empty_via_attack_self
+ if(!isnull(allow_quick_empty))
+ obj_storage.allow_quick_empty = allow_quick_empty
+ if(!isnull(allow_quick_empty_via_clickdrag))
+ obj_storage.allow_quick_empty_via_clickdrag = allow_quick_empty_via_clickdrag
+ if(!isnull(allow_quick_empty_via_attack_self))
+ obj_storage.allow_quick_empty_via_attack_self = allow_quick_empty_via_attack_self
- obj_storage.sfx_open = sfx_open
- obj_storage.sfx_insert = sfx_insert
- obj_storage.sfx_remove = sfx_remove
+ if(!isnull(sfx_open))
+ obj_storage.sfx_open = sfx_open
+ if(!isnull(sfx_insert))
+ obj_storage.sfx_insert = sfx_insert
+ if(!isnull(sfx_remove))
+ obj_storage.sfx_remove = sfx_remove
- obj_storage.ui_numerical_mode = ui_numerical_mode
- obj_storage.ui_expand_when_needed = ui_expand_when_needed
- obj_storage.ui_force_slot_mode = ui_force_slot_mode
+ if(!isnull(ui_numerical_mode))
+ obj_storage.ui_numerical_mode = ui_numerical_mode
+ if(!isnull(ui_expand_when_needed))
+ obj_storage.ui_expand_when_needed = ui_expand_when_needed
+ if(!isnull(ui_force_slot_mode))
+ obj_storage.ui_force_slot_mode = ui_force_slot_mode
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index b8ae16dde89..13a68469052 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -5,6 +5,8 @@
icon = 'icons/obj/wallet.dmi'
icon_state = "wallet-orange"
w_class = WEIGHT_CLASS_SMALL
+ max_combined_volume = WEIGHT_VOLUME_SMALL * 4
+ max_single_weight_class = WEIGHT_CLASS_SMALL
insertion_whitelist = list(
/obj/item/spacecash,
/obj/item/card,
diff --git a/code/game/objects/items/tools/_tool.dm b/code/game/objects/items/tools/_tool.dm
index 741a7824ff8..56fe8ea0c18 100644
--- a/code/game/objects/items/tools/_tool.dm
+++ b/code/game/objects/items/tools/_tool.dm
@@ -6,6 +6,7 @@
/obj/item/tool
item_flags = ITEM_CAREFUL_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/tool/get_description_info()
. = ..()
diff --git a/code/game/objects/items/tools/switchtool.dm b/code/game/objects/items/tools/switchtool.dm
index 31eefc66502..6f35869395f 100644
--- a/code/game/objects/items/tools/switchtool.dm
+++ b/code/game/objects/items/tools/switchtool.dm
@@ -10,6 +10,7 @@
icon_state = "switchtool"
item_state = "switchtool"
desc = "A multi-deployable, multi-instrument, finely crafted multi-purpose tool. The envy of engineers everywhere."
+ belt_storage_class = BELT_CLASS_SMALL
siemens_coefficient = 1
damage_force = 3
w_class = WEIGHT_CLASS_SMALL
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 0a516a6ec0a..7572fc4b2f3 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -10,6 +10,7 @@
slot_flags = SLOT_BELT
tool_behavior = TOOL_WELDER
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_MEDIUM
//Amount of OUCH when it's thrown
damage_force = 3.0
diff --git a/code/game/objects/items/weapons/autopsy.dm b/code/game/objects/items/weapons/autopsy.dm
index 5a893235ee3..431bc37e8c6 100644
--- a/code/game/objects/items/weapons/autopsy.dm
+++ b/code/game/objects/items/weapons/autopsy.dm
@@ -10,6 +10,7 @@
item_state = "autopsy_scanner"
w_class = WEIGHT_CLASS_SMALL
origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
+ belt_storage_class = BELT_CLASS_SMALL
var/list/datum/autopsy_data_scanner/wdata = list()
var/list/datum/autopsy_data_scanner/chemtraces = list()
var/target_name = null
diff --git a/code/game/objects/items/weapons/barrier_tape.dm b/code/game/objects/items/weapons/barrier_tape.dm
index e6159688fe4..fbc84faa86c 100644
--- a/code/game/objects/items/weapons/barrier_tape.dm
+++ b/code/game/objects/items/weapons/barrier_tape.dm
@@ -5,6 +5,7 @@
icon_state = "tape"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
tool_speed = 3 //You can use it in surgery. It's stupid, but you can.
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index e2cf0589a2e..fe0d8c79f0e 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -587,6 +587,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
w_class = WEIGHT_CLASS_TINY
throw_force = 4
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
slot_flags = SLOT_BELT
attack_verb = list("burnt", "singed")
var/base_state
diff --git a/code/game/objects/items/weapons/duct_tape.dm b/code/game/objects/items/weapons/duct_tape.dm
index 46c5b86f14b..a1b7bc0f29a 100644
--- a/code/game/objects/items/weapons/duct_tape.dm
+++ b/code/game/objects/items/weapons/duct_tape.dm
@@ -5,6 +5,7 @@
icon_state = "taperoll"
damage_force = 0
w_class = WEIGHT_CLASS_TINY
+ belt_storage_class = BELT_CLASS_SMALL
drop_sound = 'sound/items/drop/cardboardbox.ogg'
pickup_sound = 'sound/items/pickup/cardboardbox.ogg'
var/amount = 20
diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm
index 34cfabc9bdb..325dd1e3134 100644
--- a/code/game/objects/items/weapons/extinguisher.dm
+++ b/code/game/objects/items/weapons/extinguisher.dm
@@ -37,6 +37,7 @@
spray_particles = 3
sprite_name = "miniFE"
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_MEDIUM
/obj/item/extinguisher/mini/plasman
name = "emergency phoronoid extinguisher"
diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm
index 760418cd03d..35e5d7c4276 100644
--- a/code/game/objects/items/weapons/handcuffs.dm
+++ b/code/game/objects/items/weapons/handcuffs.dm
@@ -8,6 +8,7 @@
worn_render_flags = WORN_RENDER_SLOT_ONE_FOR_ALL
slot_flags = SLOT_BELT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
throw_force = 5
w_class = WEIGHT_CLASS_SMALL
throw_speed = 2
diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm
index c1296b6fe81..602657a6bae 100644
--- a/code/game/objects/items/weapons/material/knives.dm
+++ b/code/game/objects/items/weapons/material/knives.dm
@@ -8,6 +8,7 @@
attack_verb = list("patted", "tapped")
force_multiplier = 0.1
throw_force_multiplier = 1.5
+ belt_storage_class = BELT_CLASS_SMALL
drop_sound = 'sound/items/drop/knife.ogg'
pickup_sound = 'sound/items/pickup/knife.ogg'
var/active = FALSE
@@ -75,6 +76,7 @@
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
damage_mode = DAMAGE_MODE_SHARP | DAMAGE_MODE_EDGE
material_significance = MATERIAL_SIGNIFICANCE_WEAPON_LIGHT
+ belt_storage_class = BELT_CLASS_MEDIUM
materials_base = list(MAT_STEEL = 12000)
origin_tech = list(TECH_MATERIAL = 1)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
diff --git a/code/game/objects/items/weapons/material/misc.dm b/code/game/objects/items/weapons/material/misc.dm
index ab687b9080d..7a6b97807bf 100644
--- a/code/game/objects/items/weapons/material/misc.dm
+++ b/code/game/objects/items/weapons/material/misc.dm
@@ -22,6 +22,7 @@
material_significance = MATERIAL_SIGNIFICANCE_WEAPON_HEAVY
damage_mode = DAMAGE_MODE_SHARP | DAMAGE_MODE_EDGE
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_MEDIUM
origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1)
attack_verb = list("chopped", "torn", "cut")
material_color = 0
@@ -80,6 +81,7 @@
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("slashed", "sliced", "cut", "clawed")
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/material/minihoe/plasteel
material_parts = /datum/prototype/material/plasteel
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 323e3c69fa3..dc8f9185a5c 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -12,6 +12,7 @@
throw_force = 7
atom_flags = NOCONDUCT
w_class = WEIGHT_CLASS_NORMAL
+ belt_storage_class = BELT_CLASS_LARGE
drop_sound = 'sound/items/drop/metalweapon.ogg'
pickup_sound = 'sound/items/pickup/metalweapon.ogg'
origin_tech = list(TECH_COMBAT = 2)
diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm
index 1ac09e35ee3..62d67f08cca 100644
--- a/code/game/objects/items/weapons/surgery_tools.dm
+++ b/code/game/objects/items/weapons/surgery_tools.dm
@@ -15,6 +15,7 @@
w_class = WEIGHT_CLASS_SMALL
item_flags = ITEM_CAREFUL_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/helpforce = 0 //For help intent things
drop_sound = 'sound/items/drop/weldingtool.ogg'
pickup_sound = 'sound/items/pickup/weldingtool.ogg'
@@ -65,6 +66,7 @@
w_class = WEIGHT_CLASS_NORMAL
origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
attack_verb = list("drilled")
+ belt_storage_class = BELT_CLASS_MEDIUM
/*
* Scalpel
@@ -139,6 +141,7 @@
materials_base = list(MAT_STEEL = 20000, MAT_GLASS = 10000)
attack_verb = list("attacked", "slashed", "sawed", "cut")
damage_mode = DAMAGE_MODE_SHARP | DAMAGE_MODE_EDGE
+ belt_storage_class = BELT_CLASS_MEDIUM
/obj/item/surgical/circular_saw/manager
name = "energetic bone diverter"
diff --git a/code/game/objects/obj.dm b/code/game/objects/obj.dm
index 4f3ced0a35a..ec6442c14e6 100644
--- a/code/game/objects/obj.dm
+++ b/code/game/objects/obj.dm
@@ -747,6 +747,8 @@
// todo: context + construction (tool) examines at some point need a better system
if(obj_rotation_flags & OBJ_ROTATION_ENABLED)
. += SPAN_NOTICE("This entity can be rotated[(obj_rotation_flags & OBJ_ROTATION_NO_ANCHOR_CHECK)? "" : " while unanchored"] via context menu (alt click while adjacent).")
+ if(dist <= 1)
+ obj_storage?.handle_storage_examine(.)
/obj/proc/examine_integrity(mob/user)
. = list()
diff --git a/code/game/objects/systems/storage/storage-insertion_removal.dm b/code/game/objects/systems/storage/storage-insertion_removal.dm
new file mode 100644
index 00000000000..3ed8832ecae
--- /dev/null
+++ b/code/game/objects/systems/storage/storage-insertion_removal.dm
@@ -0,0 +1,224 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * todo: refactor?
+ *
+ * @return TRUE / FALSE; if true, caller should stop clickchain.
+ */
+/datum/object_system/storage/proc/auto_handle_interacted_insertion(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed)
+ if(!actor.performer.is_holding(inserting))
+ // something probably yanked it, don't bother
+ return FALSE
+ if(is_locked(actor.performer))
+ actor.chat_feedback(
+ msg = SPAN_WARNING("[parent] is locked."),
+ target = parent,
+ )
+ return TRUE
+ if(!actor.performer.Reachability(indirection || parent))
+ return TRUE
+ if(!try_insert(inserting, actor, silent, suppressed))
+ return TRUE
+ // sound
+ // todo: put this in interacted_insert()..?
+ if(!suppressed && !isnull(actor))
+ if(sfx_insert)
+ // todo: variable sound
+ playsound(actor.performer, sfx_insert, 50, 1, -5)
+ actor.visible_feedback(
+ target = parent,
+ range = MESSAGE_RANGE_INVENTORY_SOFT,
+ visible = "[actor.performer] puts [inserting] into [parent].",
+ visible_self = "You put [inserting] into [parent]",
+ )
+ return TRUE
+
+/**
+ * Called by inventory procs; skips some checks of interacted insertion.
+ *
+ * todo: refactor?
+ *
+ * @return TRUE on success, FALSE on failure.
+ */
+/datum/object_system/storage/proc/auto_handle_inventory_insertion(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed)
+ if(is_locked(actor.performer))
+ actor.chat_feedback(
+ msg = SPAN_WARNING("[parent] is locked."),
+ target = parent,
+ )
+ return TRUE
+ if(!actor.performer.Reachability(indirection || parent))
+ return TRUE
+ if(!try_insert(inserting, actor, silent, suppressed))
+ return TRUE
+ // sound
+ // todo: put this in interacted_insert()..?
+ if(!suppressed && !isnull(actor))
+ if(sfx_insert)
+ // todo: variable sound
+ playsound(actor.performer, sfx_insert, 50, 1, -5)
+ actor.visible_feedback(
+ target = parent,
+ range = MESSAGE_RANGE_INVENTORY_SOFT,
+ visible = "[actor.performer] puts [inserting] into [parent].",
+ visible_self = "You put [inserting] into [parent]",
+ )
+ return TRUE
+
+/datum/object_system/storage/proc/try_insert(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed, no_update)
+ if(!can_be_inserted(inserting, actor, silent))
+ return FALSE
+ // point of no return
+ if(actor && (inserting.get_worn_mob() == actor.performer && !actor.performer.temporarily_remove_from_inventory(inserting, user = actor.performer)))
+ if(!silent)
+ actor?.chat_feedback(
+ msg = SPAN_WARNING("[inserting] is stuck to your hand / body!"),
+ target = parent,
+ )
+ return FALSE
+ // point of no return (real)
+ return insert(inserting, actor, suppressed, no_update)
+
+/datum/object_system/storage/proc/can_be_inserted(obj/item/inserting, datum/event_args/actor/actor, silent)
+ if(!check_insertion_filters(inserting))
+ if(!silent)
+ actor?.chat_feedback(
+ msg = SPAN_WARNING("[parent] can't hold [inserting]!"),
+ target = parent,
+ )
+ return FALSE
+ var/why_insufficient_space = why_failed_insertion_limits(inserting)
+ if(why_insufficient_space)
+ if(!silent)
+ actor?.chat_feedback(
+ msg = SPAN_WARNING("[parent] can't fit [inserting]! ([why_insufficient_space])"),
+ target = parent,
+ )
+ return FALSE
+ return TRUE
+
+/**
+ * inserts something
+ *
+ * @params
+ * * inserting - thing being inserted
+ * * actor - who's inserting it
+ * * suppressed - suppress sounds
+ * * no_update - do not update uis
+ * * no_move - much more than not moving; basically makes an abstract contents operation without otherwise doing normal logic. use with care.
+ */
+/datum/object_system/storage/proc/insert(obj/item/inserting, datum/event_args/actor/actor, suppressed, no_update, no_move)
+ physically_insert_item(inserting, no_move)
+
+ if(!no_update)
+ if(update_icon_on_item_change)
+ update_icon()
+ refresh()
+
+ return TRUE
+
+/**
+ * handle moving an item in
+ * we can assume this proc will do potentially literally anything with the item, so.
+ *
+ * @return inserted item or null (null doesn't mean insert failed; for example stacks can be merged in)
+ */
+/datum/object_system/storage/proc/physically_insert_item(obj/item/inserting, no_move, from_hook)
+ inserting.item_flags |= ITEM_IN_STORAGE
+ if(!no_move)
+ inserting.forceMove(real_contents_loc())
+ inserting.vis_flags |= VIS_INHERIT_LAYER | VIS_INHERIT_PLANE
+ inserting.reset_pixel_offsets()
+ inserting.on_enter_storage(src)
+ if(weight_propagation)
+ var/inserting_weight = inserting.get_weight()
+ if(inserting_weight)
+ weight_cached += inserting_weight
+ update_containing_weight(inserting_weight)
+ cached_combined_volume += inserting.get_weight_volume()
+ cached_combined_weight_class += inserting.get_weight_class()
+ return inserting
+
+/**
+ * @return TRUE / FALSE
+ */
+/datum/object_system/storage/proc/auto_handle_interacted_removal(obj/item/removing, datum/event_args/actor/actor, silent, suppressed, put_in_hands)
+ if(is_locked(actor.performer))
+ actor.chat_feedback(
+ msg = SPAN_WARNING("[parent] is locked."),
+ target = parent,
+ )
+ return TRUE
+ if(!actor.performer.Reachability(parent))
+ return TRUE
+ if(!try_remove(removing, actor.performer, actor, silent, suppressed))
+ return TRUE
+ if(put_in_hands)
+ actor.performer.put_in_hands_or_drop(removing)
+ else
+ removing.forceMove(actor.performer.drop_location())
+ // todo: put this in interacted_insert()..?
+ if(!suppressed && !isnull(actor))
+ if(sfx_remove)
+ // todo: variable sound
+ playsound(actor.performer, sfx_remove, 50, 1, -5)
+ actor.visible_feedback(
+ target = parent,
+ range = MESSAGE_RANGE_INVENTORY_SOFT,
+ visible = "[actor.performer] takes [removing] out of [parent].",
+ visible_self = "You take [removing] out of [parent]",
+ )
+ return TRUE
+
+/**
+ * try to remove item from self
+ *
+ * @return item removed; not necessarily the item passed in.
+ */
+/datum/object_system/storage/proc/try_remove(obj/item/removing, atom/to_where, datum/event_args/actor/actor, silent, suppressed, no_update)
+ return remove(removing, to_where, actor, suppressed, no_update)
+
+/datum/object_system/storage/proc/can_be_removed(obj/item/removing, atom/to_where, datum/event_args/actor/actor, silent)
+ return TRUE
+
+/**
+ * remove item from self
+ *
+ * @return item removed; not necessarily the item passed in.
+ */
+/datum/object_system/storage/proc/remove(obj/item/removing, atom/to_where, datum/event_args/actor/actor, suppressed, no_update, no_move)
+ . = physically_remove_item(removing, to_where, no_move)
+ if(isnull(.))
+ return
+
+ if(!no_update)
+ if(update_icon_on_item_change)
+ update_icon()
+ refresh()
+
+/**
+ * handle moving an item out
+ * we can assume this proc will do potentially literally anything with the item, so..
+ *
+ * @return moved item
+ */
+/datum/object_system/storage/proc/physically_remove_item(obj/item/removing, atom/to_where, no_move, from_hook)
+ removing.item_flags &= ~ITEM_IN_STORAGE
+ if(!no_move)
+ if(to_where == null)
+ removing.moveToNullspace()
+ else
+ removing.forceMove(to_where)
+ removing.vis_flags = (removing.vis_flags & ~(VIS_INHERIT_LAYER | VIS_INHERIT_LAYER)) | (initial(removing.vis_flags) & (VIS_INHERIT_LAYER | VIS_INHERIT_PLANE))
+ removing.on_exit_storage(src)
+ // we might have set maptext in render_numerical_display
+ removing.maptext = null
+ if(weight_propagation)
+ var/removing_weight = removing.get_weight()
+ if(removing_weight)
+ weight_cached -= removing_weight
+ update_containing_weight(-removing_weight)
+ cached_combined_volume -= removing.get_weight_volume()
+ cached_combined_weight_class -= removing.get_weight_class()
+ return removing
diff --git a/code/game/objects/systems/storage/storage-limits.dm b/code/game/objects/systems/storage/storage-limits.dm
index 798af8ca35d..0407e3249b7 100644
--- a/code/game/objects/systems/storage/storage-limits.dm
+++ b/code/game/objects/systems/storage/storage-limits.dm
@@ -32,3 +32,34 @@
if(candidate.obj_storage && (candidate.w_class >= parent.w_class) && disallow_equal_weight_class_storage_nesting)
return "can't nest storage"
return null
+
+/**
+ * generally a bad idea to call, tbh.
+ *
+ * uses max single weight class
+ * uses combined volume
+ *
+ * can use type whitelist
+ * if type_whitelist is FALSE, this just wipes all type whitelists.
+ */
+/datum/object_system/storage/proc/fit_to_contents(type_whitelist = FALSE, no_shrink = FALSE)
+ var/scanned_max_single_weight_class = WEIGHT_CLASS_TINY
+ var/scanned_max_combined_volume = 0
+
+ if(!no_shrink)
+ max_single_weight_class = scanned_max_single_weight_class
+ max_combined_volume = scanned_max_combined_volume
+
+ var/list/types = list()
+ for(var/obj/item/item in real_contents_loc())
+ if(type_whitelist)
+ types |= item.type
+ scanned_max_single_weight_class = max(max_single_weight_class, item.w_class)
+ scanned_max_combined_volume += item.get_weight_volume()
+
+ max_single_weight_class = max(max_single_weight_class, scanned_max_single_weight_class)
+ max_combined_volume = max(max_combined_volume, scanned_max_combined_volume)
+
+ set_insertion_whitelist(type_whitelist? types : null)
+ set_insertion_blacklist(null)
+ set_insertion_allow(null)
diff --git a/code/game/objects/systems/storage/storage-ui.dm b/code/game/objects/systems/storage/storage-ui.dm
index 0c2c121ab2a..2dbf2b91b4d 100644
--- a/code/game/objects/systems/storage/storage-ui.dm
+++ b/code/game/objects/systems/storage/storage-ui.dm
@@ -1,6 +1,75 @@
//* This file is explicitly licensed under the MIT license. *//
//* Copyright (c) 2024 Citadel Station Developers *//
+//* UI Main *//
+
+/**
+ * @return TRUE if we did something (to interrupt clickchain)
+ */
+/datum/object_system/storage/proc/auto_handle_interacted_open(datum/event_args/actor/actor, force, suppressed)
+ if(!force && is_locked(actor.performer))
+ actor.chat_feedback(
+ msg = SPAN_WARNING("[parent] is locked."),
+ target = parent,
+ )
+ return TRUE
+ if(check_on_found_hooks(actor))
+ return TRUE
+ if(!suppressed && !isnull(actor) && sfx_open)
+ // todo: variable sound
+ playsound(actor.performer, sfx_open, 50, 1, -5)
+ // todo: jiggle animation
+ show(actor.initiator)
+ return TRUE
+
+/datum/object_system/storage/proc/show(mob/viewer)
+ if(viewer.active_storage == src)
+ refresh_ui(viewer)
+ return TRUE
+
+ viewer.active_storage?.hide(viewer)
+ viewer.active_storage = src
+
+ create_ui(viewer)
+
+ parent.object_storage_opened(viewer)
+
+/**
+ * if user not specified, it is 'all'.
+ */
+/datum/object_system/storage/proc/hide(mob/viewer)
+ if(isnull(viewer))
+ for(var/mob/iterating as anything in ui_by_mob)
+ hide(iterating)
+ return
+
+ if(viewer.active_storage != src)
+ stack_trace("viewer didn't have active storage set right, wtf?")
+ else
+ viewer.active_storage = null
+
+ cleanup_ui(viewer)
+
+ parent.object_storage_closed(viewer)
+
+/datum/object_system/storage/proc/refresh(mob/viewer)
+ ui_refresh_queued = FALSE
+ if(isnull(viewer))
+ for(var/mob/iterating as anything in ui_by_mob)
+ refresh_ui(iterating)
+ return
+ refresh_ui(viewer)
+
+
+/datum/object_system/storage/proc/reconsider_mob_viewable(mob/user)
+ if(isnull(user))
+ for(var/mob/viewer as anything in ui_by_mob)
+ reconsider_mob_viewable(viewer)
+ return
+ if(accessible_by_mob(user))
+ return
+ hide(user)
+
//* Helper Datums *//
/**
@@ -89,6 +158,20 @@
/datum/object_system/storage/proc/uses_numerical_ui()
return ui_numerical_mode
+/**
+ * inspired by CM; allows tinting the background if something is nearly full
+ */
+/datum/object_system/storage/proc/get_ui_drawer_tint()
+ return null
+
+/datum/object_system/storage/proc/get_ui_predicted_max_items()
+ // good ol' widescreen predict length of 9 if max isn't set
+ // this is so things don't break when they expect an answer
+ return max_items || 9
+
+/**
+ * * Will not respect random access limits in numerical mode.
+ */
/datum/object_system/storage/proc/create_ui_slot_mode(mob/user)
. = list()
var/atom/movable/screen/storage/closer/closer = new
@@ -100,17 +183,20 @@
var/view_x = decoded_view[1]
// clamp to max items if needed
var/rendering_width = STORAGE_UI_TILES_FOR_SCREEN_VIEW_X(view_x)
- if(max_items)
- rendering_width = min(max_items, rendering_width)
// see if we need to process numerical display
var/list/datum/storage_numerical_display/numerical_rendered = uses_numerical_ui()? render_numerical_display() : null
// process indirection
- var/atom/indirection = real_contents_loc()
+ var/obj/item/accessible = get_accessible_items()
+ // predict max items for slot mode
+ var/predicted_max_items = get_ui_predicted_max_items()
+ if(predicted_max_items)
+ rendering_width = min(predicted_max_items, rendering_width)
// if we have expand when needed, only show 1 more than the actual amount.
if(ui_expand_when_needed)
- rendering_width = min(rendering_width, (isnull(numerical_rendered)? length(indirection.contents) : length(numerical_rendered)) + 1)
+ var/actually_needed = max((isnull(numerical_rendered)? length(accessible) : length(numerical_rendered)) + 1, ui_expand_when_needed)
+ rendering_width = min(rendering_width, actually_needed)
// compute count and rows
- var/item_count = isnull(numerical_rendered)? length(indirection.contents) : length(numerical_rendered)
+ var/item_count = isnull(numerical_rendered)? length(accessible) : length(numerical_rendered)
var/rows_needed = ROUND_UP(item_count / rendering_width) || 1
// prepare iteration
var/current_row = 1
@@ -118,6 +204,7 @@
// render boxes
boxes.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y] to \
LEFT+[STORAGE_UI_START_TILE_X + rendering_width - 1]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y + rows_needed - 1]:[STORAGE_UI_START_PIXEL_Y]"
+ boxes.color = get_ui_drawer_tint()
// render closer
closer.screen_loc = "LEFT+[STORAGE_UI_START_TILE_X + rendering_width]:[STORAGE_UI_START_PIXEL_X],BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y]"
// render items
@@ -138,7 +225,7 @@
if(current_row > STORAGE_UI_MAX_ROWS)
break
else
- for(var/obj/item/item in indirection)
+ for(var/obj/item/item in accessible)
var/atom/movable/screen/storage/item/slot/renderer = new(null, item)
. += renderer
// position
@@ -152,6 +239,10 @@
if(current_row > STORAGE_UI_MAX_ROWS)
break
+/**
+ * Volumetric rendering.
+ * * Doesn't respect random access limits.
+ */
/datum/object_system/storage/proc/create_ui_volumetric_mode(mob/user)
// guard against divide-by-0's
if(!max_combined_volume)
@@ -187,10 +278,13 @@
var/effective_pixel_volume_ratio = VOLUMETRIC_STORAGE_STANDARD_PIXEL_RATIO
// we compute how much pixels we ideally will need to display everything
var/ideal_width_px = effective_pixel_volume_ratio * effective_max_volume
+ // compute what the sane minimum is so small containers don't explode
+ // 'ui_expand_volumetric_minimum_items' is used here to make tiny containers not too small
+ var/sane_minimum = max((VOLUMETRIC_STORAGE_INFLATE_TO_TILES * WORLD_ICON_SIZE), ui_expand_volumetric_minimum_items * VOLUMETRIC_STORAGE_MINIMUM_PIXELS_PER_ITEM)
// if too low,
- if(ideal_width_px < (VOLUMETRIC_STORAGE_INFLATE_TO_TILES * WORLD_ICON_SIZE))
+ if(ideal_width_px < sane_minimum)
// expand our horizons
- effective_pixel_volume_ratio = (VOLUMETRIC_STORAGE_INFLATE_TO_TILES * WORLD_ICON_SIZE) / effective_max_volume
+ effective_pixel_volume_ratio = sane_minimum / effective_max_volume
ideal_width_px = effective_pixel_volume_ratio * effective_max_volume
// -- prepare for iteration --
@@ -211,7 +305,7 @@
// -- iterate --
- for(var/obj/item/item as anything in indirection)
+ for(var/obj/item/item in indirection)
var/item_volume = item.get_weight_volume()
// check safety
if(--safety <= 0)
@@ -286,6 +380,7 @@
BOTTOM+[STORAGE_UI_START_TILE_Y]:[STORAGE_UI_START_PIXEL_Y] to \
LEFT+[STORAGE_UI_START_TILE_X]:[STORAGE_UI_START_PIXEL_X + middle_shift],\
BOTTOM+[STORAGE_UI_START_TILE_Y + current_row - 1]:[STORAGE_UI_START_PIXEL_Y]"
+ p_box.color = get_ui_drawer_tint()
// render closer on bottom
var/atom/movable/screen/storage/closer/closer = new
. += closer
diff --git a/code/game/objects/systems/storage/storage.dm b/code/game/objects/systems/storage/storage.dm
index f9e54023d18..4d79206e718 100644
--- a/code/game/objects/systems/storage/storage.dm
+++ b/code/game/objects/systems/storage/storage.dm
@@ -11,10 +11,16 @@
//* Access *//
/// if set, limit allowable random access to first n items
- var/limited_random_access_stack_amount
+ var/limited_random_access_amount
+ /// if set, limit allowable random access to first n items with this max weight class
+ /// * requires [limited_random_access_amount] to be set
+ var/limited_random_access_total_weight_class = INFINITY
+ /// if set, limit allowable random access to first n items with this max weight volume
+ /// * requires [limited_random_access_amount] to be set
+ var/limited_random_access_total_weight_volume = INFINITY
/// if set, limit allowable random access goes from bottom up, not top down
/// * top down is from end of contents list, bottom up is from start of contents list
- var/limited_random_access_stack_bottom_first = FALSE
+ var/limited_random_access_bottom_first = FALSE
//* Actions *//
@@ -27,7 +33,7 @@
/// use the setter, do not change this manually.
var/weight_propagation = TRUE
/// carry weight in us prior to mitigation
- var/weight_cached = 0
+ var/tmp/weight_cached = 0
/// carry weight mitigation, static. applied after multiplicative
var/weight_subtract = 0
/// carry weight mitigation, multiplicative.
@@ -80,11 +86,11 @@
var/insert_preposition = "in"
/// allow quick empty at all
- var/allow_quick_empty = FALSE
+ var/allow_quick_empty = TRUE
/// allow quick empty via clickdrag
var/allow_quick_empty_via_clickdrag = TRUE
/// allow quick empty via attack self
- var/allow_quick_empty_via_attack_self = TRUE
+ var/allow_quick_empty_via_attack_self = FALSE
/// allow inbound mass transfers
var/allow_inbound_mass_transfer = TRUE
@@ -140,6 +146,8 @@
/// mutex to prevent mass operation spam
var/mass_operation_interaction_mutex = FALSE
+ /// max items dropped per second for mass dumping
+ var/mass_operation_dumping_limit_per_second = INFINITY
//* Redirection *//
@@ -194,8 +202,12 @@
/// ui force slot mode.
var/ui_force_slot_mode = FALSE
/// show minimum number of slots necessary, expand as needed
- /// currently only works for slot mode
- var/ui_expand_when_needed = FALSE
+ /// * currently only works for slot mode
+ /// * this should be set to a number to determine how many minimum slots to show despite this
+ /// setting; the minimum enabled number of '1' just shows a single slot.
+ var/ui_expand_when_needed = 0
+ /// used to hint the number of minimum items to assume we have. useful for pill bottles.
+ var/ui_expand_volumetric_minimum_items
/// ui update queued?
// todo: this is only needed because redirection is halfassed.
var/ui_refresh_queued = FALSE
@@ -222,33 +234,45 @@
//* Access *//
-/**
- * do not mutate returned list
- */
-/datum/object_system/storage/proc/dangerously_accessible_items_immutable(random_access = TRUE)
- var/atom/redirection = real_contents_loc()
- if(random_access)
- if(limited_random_access_stack_amount)
- var/contents_length = length(redirection.contents)
- if(limited_random_access_stack_bottom_first)
- return redirection.contents.Copy(1, min(contents_length + 1, limited_random_access_stack_bottom_first + 1))
- else
- return redirection.contents.Copy(max(1, contents_length - limited_random_access_stack_amount + 1), contents_length + 1)
- return redirection.contents
-
/**
* you may mutate returned list
*/
-/datum/object_system/storage/proc/accessible_items(random_access = TRUE)
+/datum/object_system/storage/proc/get_accessible_items(random_access = TRUE)
var/atom/redirection = real_contents_loc()
- if(random_access)
- if(limited_random_access_stack_amount)
- var/contents_length = length(redirection.contents)
- if(limited_random_access_stack_bottom_first)
- return redirection.contents.Copy(1, min(contents_length + 1, limited_random_access_stack_bottom_first + 1))
+ if(!length(redirection.contents))
+ return list()
+ if(random_access && limited_random_access_amount)
+ var/list/copied_contents = . = list()
+ if(limited_random_access_amount)
+ var/original_contents_length = length(redirection.contents)
+ var/lra_start
+ var/lra_end
+ var/lra_step
+ if(limited_random_access_bottom_first)
+ lra_start = 1
+ lra_end = min(limited_random_access_amount, original_contents_length)
+ lra_step = 1
else
- return redirection.contents.Copy(max(1, contents_length - limited_random_access_stack_amount + 1), contents_length + 1)
- return redirection.contents.Copy()
+ lra_start = original_contents_length
+ lra_end = max(1, original_contents_length - limited_random_access_amount + 1)
+ lra_step = -1
+ var/list/lra_ref = redirection.contents
+ var/lra_twc = 0
+ var/lra_twv = 0
+ for(var/i in lra_start to lra_end step lra_step)
+ var/obj/item/maybe_item = lra_ref[i]
+ // it is valid albeit silly to have non-items in a storage object
+ if(!istype(maybe_item))
+ continue
+ lra_twc += maybe_item.w_class
+ lra_twv += maybe_item.weight_volume
+ if(lra_twc > limited_random_access_total_weight_class)
+ break
+ if(lra_twv > limited_random_access_total_weight_volume)
+ break
+ copied_contents += maybe_item
+ else
+ . = redirection.contents.Copy()
/**
* Recursively return all inventory in this or nested storage (without indirection)
@@ -305,11 +329,20 @@
//* Caches *//
/datum/object_system/storage/proc/rebuild_caches()
+ SHOULD_NOT_SLEEP(TRUE)
+ SHOULD_NOT_OVERRIDE(TRUE)
+
+ var/atom/indirection = real_contents_loc()
+ rebuild_caches_impl(indirection ? indirection.contents : list())
+
+/datum/object_system/storage/proc/rebuild_caches_impl(list/atom/movable/entities)
+ SHOULD_CALL_PARENT(TRUE)
+ SHOULD_NOT_SLEEP(TRUE)
cached_combined_volume = 0
cached_combined_weight_class = 0
var/old_weight = weight_cached
weight_cached = 0
- for(var/obj/item/item in real_contents_loc())
+ for(var/obj/item/item in entities)
cached_combined_volume += item.get_weight_volume()
cached_combined_weight_class += item.get_weight_class()
weight_cached += item.get_weight()
@@ -365,6 +398,11 @@
else
rebuild_caches()
+//* Examine *//
+
+/datum/object_system/storage/proc/handle_storage_examine(list/examine_list)
+ // TODO: proper examine. implement on /stack storage too
+
//* Hooks *//
/**
@@ -433,260 +471,6 @@
return TRUE
return FALSE
-//* Insertion & Removal *//
-
-/**
- * todo: refactor?
- *
- * @return TRUE / FALSE; if true, caller should stop clickchain.
- */
-/datum/object_system/storage/proc/auto_handle_interacted_insertion(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed)
- if(!actor.performer.is_holding(inserting))
- // something probably yanked it, don't bother
- return FALSE
- if(is_locked(actor.performer))
- actor.chat_feedback(
- msg = SPAN_WARNING("[parent] is locked."),
- target = parent,
- )
- return TRUE
- if(!actor.performer.Reachability(indirection || parent))
- return TRUE
- if(!try_insert(inserting, actor, silent, suppressed))
- return TRUE
- // sound
- // todo: put this in interacted_insert()..?
- if(!suppressed && !isnull(actor))
- if(sfx_insert)
- // todo: variable sound
- playsound(actor.performer, sfx_insert, 50, 1, -5)
- actor.visible_feedback(
- target = parent,
- range = MESSAGE_RANGE_INVENTORY_SOFT,
- visible = "[actor.performer] puts [inserting] into [parent].",
- visible_self = "You put [inserting] into [parent]",
- )
- return TRUE
-
-/**
- * Called by inventory procs; skips some checks of interacted insertion.
- *
- * todo: refactor?
- *
- * @return TRUE on success, FALSE on failure.
- */
-/datum/object_system/storage/proc/auto_handle_inventory_insertion(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed)
- if(is_locked(actor.performer))
- actor.chat_feedback(
- msg = SPAN_WARNING("[parent] is locked."),
- target = parent,
- )
- return TRUE
- if(!actor.performer.Reachability(indirection || parent))
- return TRUE
- if(!try_insert(inserting, actor, silent, suppressed))
- return TRUE
- // sound
- // todo: put this in interacted_insert()..?
- if(!suppressed && !isnull(actor))
- if(sfx_insert)
- // todo: variable sound
- playsound(actor.performer, sfx_insert, 50, 1, -5)
- actor.visible_feedback(
- target = parent,
- range = MESSAGE_RANGE_INVENTORY_SOFT,
- visible = "[actor.performer] puts [inserting] into [parent].",
- visible_self = "You put [inserting] into [parent]",
- )
- return TRUE
-
-/datum/object_system/storage/proc/try_insert(obj/item/inserting, datum/event_args/actor/actor, silent, suppressed, no_update)
- if(!can_be_inserted(inserting, actor, silent))
- return FALSE
- // point of no return
- if(actor && (inserting.get_worn_mob() == actor.performer && !actor.performer.temporarily_remove_from_inventory(inserting, user = actor.performer)))
- if(!silent)
- actor?.chat_feedback(
- msg = SPAN_WARNING("[inserting] is stuck to your hand / body!"),
- target = parent,
- )
- return FALSE
- // point of no return (real)
- return insert(inserting, actor, suppressed, no_update)
-
-/datum/object_system/storage/proc/can_be_inserted(obj/item/inserting, datum/event_args/actor/actor, silent)
- if(!check_insertion_filters(inserting))
- if(!silent)
- actor?.chat_feedback(
- msg = SPAN_WARNING("[parent] can't hold [inserting]!"),
- target = parent,
- )
- return FALSE
- var/why_insufficient_space = why_failed_insertion_limits(inserting)
- if(why_insufficient_space)
- if(!silent)
- actor?.chat_feedback(
- msg = SPAN_WARNING("[parent] can't fit [inserting]! ([why_insufficient_space])"),
- target = parent,
- )
- return FALSE
- return TRUE
-
-/**
- * inserts something
- *
- * @params
- * * inserting - thing being inserted
- * * actor - who's inserting it
- * * suppressed - suppress sounds
- * * no_update - do not update uis
- * * no_move - much more than not moving; basically makes an abstract contents operation without otherwise doing normal logic. use with care.
- */
-/datum/object_system/storage/proc/insert(obj/item/inserting, datum/event_args/actor/actor, suppressed, no_update, no_move)
- physically_insert_item(inserting, no_move)
-
- if(!no_update)
- if(update_icon_on_item_change)
- update_icon()
- refresh()
-
- return TRUE
-
-/**
- * handle moving an item in
- *
- * we can assume this proc will do potentially literally anything with the item, so.
- */
-/datum/object_system/storage/proc/physically_insert_item(obj/item/inserting, no_move, from_hook)
- inserting.item_flags |= ITEM_IN_STORAGE
- if(!no_move)
- inserting.forceMove(real_contents_loc())
- inserting.vis_flags |= VIS_INHERIT_LAYER | VIS_INHERIT_PLANE
- inserting.reset_pixel_offsets()
- inserting.on_enter_storage(src)
- if(weight_propagation)
- var/inserting_weight = inserting.get_weight()
- if(inserting_weight)
- weight_cached += inserting_weight
- update_containing_weight(inserting_weight)
- cached_combined_volume += inserting.get_weight_volume()
- cached_combined_weight_class += inserting.get_weight_class()
-
-/**
- * @return TRUE / FALSE
- */
-/datum/object_system/storage/proc/auto_handle_interacted_removal(obj/item/removing, datum/event_args/actor/actor, silent, suppressed, put_in_hands)
- if(is_locked(actor.performer))
- actor.chat_feedback(
- msg = SPAN_WARNING("[parent] is locked."),
- target = parent,
- )
- return TRUE
- if(!actor.performer.Reachability(parent))
- return TRUE
- if(!try_remove(removing, actor.performer, actor, silent, suppressed))
- return TRUE
- if(put_in_hands)
- actor.performer.put_in_hands_or_drop(removing)
- else
- removing.forceMove(actor.performer.drop_location())
- // todo: put this in interacted_insert()..?
- if(!suppressed && !isnull(actor))
- if(sfx_remove)
- // todo: variable sound
- playsound(actor.performer, sfx_remove, 50, 1, -5)
- actor.visible_feedback(
- target = parent,
- range = MESSAGE_RANGE_INVENTORY_SOFT,
- visible = "[actor.performer] takes [removing] out of [parent].",
- visible_self = "You take [removing] out of [parent]",
- )
- return TRUE
-
-/**
- * try to remove item from self
- *
- * @return item removed; not necessarily the item passed in.
- */
-/datum/object_system/storage/proc/try_remove(obj/item/removing, atom/to_where, datum/event_args/actor/actor, silent, suppressed, no_update)
- return remove(removing, to_where, actor, suppressed, no_update)
-
-/datum/object_system/storage/proc/can_be_removed(obj/item/removing, atom/to_where, datum/event_args/actor/actor, silent)
- return TRUE
-
-/**
- * remove item from self
- *
- * @return item removed; not necessarily the item passed in.
- */
-/datum/object_system/storage/proc/remove(obj/item/removing, atom/to_where, datum/event_args/actor/actor, suppressed, no_update, no_move)
- . = physically_remove_item(removing, to_where, no_move)
- if(isnull(.))
- return
-
- if(!no_update)
- if(update_icon_on_item_change)
- update_icon()
- refresh()
-
-/**
- * handle moving an item out
- *
- * we can assume this proc will do potentially literally anything with the item, so..
- */
-/datum/object_system/storage/proc/physically_remove_item(obj/item/removing, atom/to_where, no_move, from_hook)
- removing.item_flags &= ~ITEM_IN_STORAGE
- if(!no_move)
- if(to_where == null)
- removing.moveToNullspace()
- else
- removing.forceMove(to_where)
- removing.vis_flags = (removing.vis_flags & ~(VIS_INHERIT_LAYER | VIS_INHERIT_LAYER)) | (initial(removing.vis_flags) & (VIS_INHERIT_LAYER | VIS_INHERIT_PLANE))
- removing.on_exit_storage(src)
- // we might have set maptext in render_numerical_display
- removing.maptext = null
- if(weight_propagation)
- var/removing_weight = removing.get_weight()
- if(removing_weight)
- weight_cached -= removing_weight
- update_containing_weight(-removing_weight)
- cached_combined_volume -= removing.get_weight_volume()
- cached_combined_weight_class -= removing.get_weight_class()
- return removing
-
-//* Limits *//
-
-/**
- * generally a bad idea to call, tbh.
- *
- * uses max single weight class
- * uses combined volume
- *
- * can use type whitelist
- * if type_whitelist is FALSE, this just wipes all type whitelists.
- */
-/datum/object_system/storage/proc/fit_to_contents(type_whitelist = FALSE, no_shrink = FALSE)
- var/scanned_max_single_weight_class = WEIGHT_CLASS_TINY
- var/scanned_max_combined_volume = 0
-
- if(!no_shrink)
- max_single_weight_class = scanned_max_single_weight_class
- max_combined_volume = scanned_max_combined_volume
-
- var/list/types = list()
- for(var/obj/item/item in real_contents_loc())
- if(type_whitelist)
- types |= item.type
- scanned_max_single_weight_class = max(max_single_weight_class, item.w_class)
- scanned_max_combined_volume += item.get_weight_volume()
-
- max_single_weight_class = max(max_single_weight_class, scanned_max_single_weight_class)
- max_combined_volume = max(max_combined_volume, scanned_max_combined_volume)
-
- set_insertion_whitelist(type_whitelist? types : null)
- set_insertion_blacklist(null)
- set_insertion_allow(null)
-
//* Locking *//
/**
@@ -1041,9 +825,13 @@
var/atom/indirection = real_contents_loc()
var/i = length(things)
. = TRUE
+ // we're driven on 0.5 second ticks; we want to pause after half a MODLPS
+ // might want to adjust this later and use a parameter or something lol
+ var/pause_after = mass_operation_dumping_limit_per_second * 0.5
+ var/transferred = 0
while(i > 0)
// stop if overtaxed
- if(TICK_CHECK)
+ if(TICK_CHECK || (transferred > pause_after))
break
var/obj/item/transferring = things[i]
// make sure they're still there
@@ -1065,6 +853,10 @@
if(removed == transferring)
// but only go down if we got rid of the real item
i--
+ // always count the cycle as transferred,
+ // if you have invalid objects and it gets in the way of MODLPS
+ // then that's on you, stop powergaming.
+ transferred++
things.Cut(i + 1, length(things) + 1)
return . && length(things)
@@ -1083,75 +875,6 @@
for(var/obj/item/I in real_contents_loc())
I.forceMove(where)
-//* UI *//
-
-/**
- * @return TRUE if we did something (to interrupt clickchain)
- */
-/datum/object_system/storage/proc/auto_handle_interacted_open(datum/event_args/actor/actor, force, suppressed)
- if(!force && is_locked(actor.performer))
- actor.chat_feedback(
- msg = SPAN_WARNING("[parent] is locked."),
- target = parent,
- )
- return TRUE
- if(check_on_found_hooks(actor))
- return TRUE
- if(!suppressed && !isnull(actor) && sfx_open)
- // todo: variable sound
- playsound(actor.performer, sfx_open, 50, 1, -5)
- // todo: jiggle animation
- show(actor.initiator)
- return TRUE
-
-/datum/object_system/storage/proc/show(mob/viewer)
- if(viewer.active_storage == src)
- refresh_ui(viewer)
- return TRUE
-
- viewer.active_storage?.hide(viewer)
- viewer.active_storage = src
-
- create_ui(viewer)
-
- parent.object_storage_opened(viewer)
-
-/**
- * if user not specified, it is 'all'.
- */
-/datum/object_system/storage/proc/hide(mob/viewer)
- if(isnull(viewer))
- for(var/mob/iterating as anything in ui_by_mob)
- hide(iterating)
- return
-
- if(viewer.active_storage != src)
- stack_trace("viewer didn't have active storage set right, wtf?")
- else
- viewer.active_storage = null
-
- cleanup_ui(viewer)
-
- parent.object_storage_closed(viewer)
-
-/datum/object_system/storage/proc/refresh(mob/viewer)
- ui_refresh_queued = FALSE
- if(isnull(viewer))
- for(var/mob/iterating as anything in ui_by_mob)
- refresh_ui(iterating)
- return
- refresh_ui(viewer)
-
-
-/datum/object_system/storage/proc/reconsider_mob_viewable(mob/user)
- if(isnull(user))
- for(var/mob/viewer as anything in ui_by_mob)
- reconsider_mob_viewable(viewer)
- return
- if(accessible_by_mob(user))
- return
- hide(user)
-
//? Action
/datum/action/storage_gather_mode
diff --git a/code/game/objects/systems/storage/subtypes/backpack.dm b/code/game/objects/systems/storage/subtypes/backpack.dm
new file mode 100644
index 00000000000..b5850285ee3
--- /dev/null
+++ b/code/game/objects/systems/storage/subtypes/backpack.dm
@@ -0,0 +1,12 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * Default backpack storage.
+ */
+/datum/object_system/storage/backpack
+ max_single_weight_class = WEIGHT_CLASS_BULKY
+ max_combined_volume = STORAGE_VOLUME_BACKPACK
+
+/datum/object_system/storage/backpack/dufflebag
+ max_combined_volume = STORAGE_VOLUME_DUFFLEBAG
diff --git a/code/game/objects/systems/storage/subtypes/belt.dm b/code/game/objects/systems/storage/subtypes/belt.dm
new file mode 100644
index 00000000000..d419603fbe5
--- /dev/null
+++ b/code/game/objects/systems/storage/subtypes/belt.dm
@@ -0,0 +1,174 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * Belt storage
+ *
+ * Uses a list of class-size-limits.
+ */
+/datum/object_system/storage/belt
+ // belts use slot mode for now, pending a new belt UI
+ ui_force_slot_mode = TRUE
+ // belts can be massive so only expand when needed
+ ui_expand_when_needed = 7
+
+ /// max size of small-class belt items
+ var/max_combined_belt_small = 5
+ /// max size of medium-class belt items
+ var/max_combined_belt_medium = 3
+ /// max size of large-class belt items
+ var/max_combined_belt_large = 1
+
+ var/tmp/cached_combined_belt_small_size = 0
+ var/tmp/cached_combined_belt_medium_size = 0
+ var/tmp/cached_combined_belt_large_size = 0
+
+/datum/object_system/storage/belt/get_ui_predicted_max_items()
+ return min(max_items, max_combined_belt_small + max_combined_belt_medium + max_combined_belt_large)
+
+/datum/object_system/storage/belt/uses_volumetric_ui()
+ return FALSE
+
+/datum/object_system/storage/belt/handle_storage_examine(list/examine_list)
+ var/list/used_slots = list(cached_combined_belt_small_size, cached_combined_belt_medium_size, cached_combined_belt_large_size)
+ var/list/max_slots = list(max_combined_belt_small, max_combined_belt_medium, max_combined_belt_large)
+ var/list/rendered_loop_types = list()
+ var/has_overrun
+ for(var/i in 1 to 3)
+ if(used_slots[i] > max_slots[i])
+ has_overrun = TRUE
+ rendered_loop_types += "[used_slots[i] > max_slots[i] ? SPAN_DANGER("[used_slots[i]]") : used_slots[i]]/[max_slots[i]] \
+ [lowertext(global.belt_class_names[i + 1])]"
+ examine_list += SPAN_NOTICE("This is a storage item with belt loops. There are \
+ [english_list(rendered_loop_types)] loops on it.[has_overrun ? SPAN_WARNING(" Some of the larger loops are \
+ currently being filled up by excess items of smaller size.") : ""]")
+
+/**
+ * @return list(small, medium, large, )
+ */
+/datum/object_system/storage/belt/proc/compute_free_slots() as /list
+ var/small = 0
+ var/medium = 0
+ var/large = 0
+
+ // belts are weird
+ // small items can overflow onto medium, medium can overflow onto large
+
+ // the problem arises in that if small is overrunning, you don't know if it's
+ // overrunning into medium or large; this is because storage ui does not yet store, bespoke,
+ // which slot an item is in, so the player has no control over it
+
+ // thus this standard proc is here to enforce a single order of operations
+ // right now, we assume that any items always have dibs on their own slot first,
+ // and overrun 'hops over' if there's not enough.
+
+ small = max_combined_belt_small - cached_combined_belt_small_size
+ medium = max_combined_belt_medium - cached_combined_belt_medium_size
+ large = max_combined_belt_large - cached_combined_belt_large_size
+
+ if(small < 0)
+ if(medium > 0)
+ // overrun as much as we can to medium
+ . = min(medium, -small)
+ small += .
+ medium -= .
+ // overrun rest to large
+ large += small
+ small = 0
+ if(medium < 0)
+ // overrun all medium to large
+ large += medium
+ medium = 0
+
+ return list(small, medium, large)
+
+/datum/object_system/storage/belt/get_ui_drawer_tint()
+ var/list/remaining = compute_free_slots()
+ var/full_classes = 0
+ for(var/i in 1 to 3)
+ if(remaining[i] <= 0)
+ full_classes += 1
+ switch(full_classes)
+ if(0)
+ return null
+ if(1, 2)
+ return "#888800"
+ if(3)
+ return "#aa0000"
+
+/datum/object_system/storage/belt/rebuild_caches_impl(list/atom/movable/entities)
+ ..()
+ cached_combined_belt_small_size = cached_combined_belt_medium_size = cached_combined_belt_large_size = 0
+ for(var/obj/item/item in entities)
+ switch(item.belt_storage_class)
+ if(BELT_CLASS_SMALL)
+ cached_combined_belt_small_size += item.belt_storage_size
+ if(BELT_CLASS_MEDIUM)
+ cached_combined_belt_medium_size += item.belt_storage_size
+ if(BELT_CLASS_LARGE)
+ cached_combined_belt_large_size += item.belt_storage_size
+
+/datum/object_system/storage/belt/can_be_inserted(obj/item/inserting, datum/event_args/actor/actor, silent)
+ if(inserting.belt_storage_class == BELT_CLASS_INVALID)
+ if(!silent)
+ actor?.chat_feedback(
+ SPAN_WARNING("[inserting] can't go in belts."),
+ target = inserting,
+ )
+ return FALSE
+ return ..()
+
+/datum/object_system/storage/belt/proc/room_left_for_belt_class(belt_class, forbid_overrun)
+ if(forbid_overrun)
+ switch(belt_class)
+ if(BELT_CLASS_SMALL)
+ . = 1
+ if(BELT_CLASS_MEDIUM)
+ . = 2
+ if(BELT_CLASS_LARGE)
+ . = 3
+ return . ? compute_free_slots()[.] : 0
+ else
+ var/list/free_slots = compute_free_slots()
+ switch(belt_class)
+ if(BELT_CLASS_SMALL)
+ return free_slots[1] + free_slots[2] + free_slots[3]
+ if(BELT_CLASS_MEDIUM)
+ return free_slots[2] + free_slots[3]
+ if(BELT_CLASS_LARGE)
+ return free_slots[3]
+ return 0
+
+/datum/object_system/storage/belt/why_failed_insertion_limits(obj/item/candidate)
+ if(!room_left_for_belt_class(candidate.belt_storage_class) >= candidate.belt_storage_size)
+ // incase list index out of bounds
+ . = "runtime errored"
+ return "insufficient belt loops of size [lowertext(global.belt_class_names[candidate.belt_storage_class])] or bigger"
+ return ..()
+
+/datum/object_system/storage/belt/check_insertion_limits(obj/item/candidate)
+ return room_left_for_belt_class(candidate.belt_storage_class) >= candidate.belt_storage_size && ..()
+
+/datum/object_system/storage/belt/physically_insert_item(obj/item/inserting, no_move, from_hook)
+ var/obj/item/actually_inserted = . = ..()
+ if(!istype(actually_inserted))
+ return
+ switch(actually_inserted.belt_storage_class)
+ if(BELT_CLASS_SMALL)
+ cached_combined_belt_small_size += actually_inserted.belt_storage_size
+ if(BELT_CLASS_MEDIUM)
+ cached_combined_belt_medium_size += actually_inserted.belt_storage_size
+ if(BELT_CLASS_LARGE)
+ cached_combined_belt_large_size += actually_inserted.belt_storage_size
+
+/datum/object_system/storage/belt/physically_remove_item(obj/item/removing, atom/to_where, no_move, from_hook)
+ var/obj/item/actually_removed = . = ..()
+ if(!istype(actually_removed))
+ return
+ switch(actually_removed.belt_storage_class)
+ if(BELT_CLASS_SMALL)
+ cached_combined_belt_small_size -= actually_removed.belt_storage_size
+ if(BELT_CLASS_MEDIUM)
+ cached_combined_belt_medium_size -= actually_removed.belt_storage_size
+ if(BELT_CLASS_LARGE)
+ cached_combined_belt_large_size -= actually_removed.belt_storage_size
diff --git a/code/game/objects/systems/storage/subtypes/hypokit.dm b/code/game/objects/systems/storage/subtypes/hypokit.dm
new file mode 100644
index 00000000000..e158e60468b
--- /dev/null
+++ b/code/game/objects/systems/storage/subtypes/hypokit.dm
@@ -0,0 +1,5 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/object_system/storage/hypokit
+ ui_expand_volumetric_minimum_items = 14
diff --git a/code/game/objects/systems/storage/subtypes/pill_bottle.dm b/code/game/objects/systems/storage/subtypes/pill_bottle.dm
new file mode 100644
index 00000000000..2eb350bd44a
--- /dev/null
+++ b/code/game/objects/systems/storage/subtypes/pill_bottle.dm
@@ -0,0 +1,10 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/datum/object_system/storage/pill_bottle
+ max_combined_volume = WEIGHT_VOLUME_TINY * 14
+ max_single_weight_class = WEIGHT_CLASS_TINY
+ max_items = 14
+ ui_expand_volumetric_minimum_items = 14
+ allow_quick_empty = TRUE
+ allow_mass_gather = TRUE
diff --git a/code/game/objects/systems/storage/subtypes/stack.dm b/code/game/objects/systems/storage/subtypes/stack.dm
index 8d257a5b7ac..1b6c90328f3 100644
--- a/code/game/objects/systems/storage/subtypes/stack.dm
+++ b/code/game/objects/systems/storage/subtypes/stack.dm
@@ -19,10 +19,10 @@
/datum/object_system/storage/stack/uses_numerical_ui()
return TRUE
-/datum/object_system/storage/stack/rebuild_caches()
- . = ..()
+/datum/object_system/storage/stack/rebuild_caches_impl(list/atom/movable/entities)
+ ..()
cached_combined_stack_amount = 0
- for(var/obj/item/stack/stack in real_contents_loc())
+ for(var/obj/item/stack/stack in entities)
cached_combined_stack_amount += stack.amount
/datum/object_system/storage/stack/why_failed_insertion_limits(obj/item/candidate)
@@ -72,7 +72,7 @@
other.add(stack.amount, TRUE)
// this should delete the stack (?!)
stack.use(stack.amount)
- return TRUE
+ return null
inserting = stack
return ..()
diff --git a/code/game/objects/systems/storage/subtypes/trash_bag.dm b/code/game/objects/systems/storage/subtypes/trash_bag.dm
new file mode 100644
index 00000000000..a94f52bc515
--- /dev/null
+++ b/code/game/objects/systems/storage/subtypes/trash_bag.dm
@@ -0,0 +1,13 @@
+//* This file is explicitly licensed under the MIT license. *//
+//* Copyright (c) 2024 Citadel Station Developers *//
+
+/**
+ * Default trash bag storage.
+ */
+/datum/object_system/storage/trash_bag
+ mass_operation_dumping_limit_per_second = 8
+ max_single_weight_class = WEIGHT_CLASS_NORMAL
+ limited_random_access_amount = 8
+ limited_random_access_total_weight_volume = WEIGHT_VOLUME_NORMAL * 3
+ // needed for LRA to work
+ ui_force_slot_mode = TRUE
diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm
index 6003c01de6f..96db8de112a 100644
--- a/code/modules/assembly/mousetrap.dm
+++ b/code/modules/assembly/mousetrap.dm
@@ -4,6 +4,7 @@
icon_state = "mousetrap"
origin_tech = list(TECH_COMBAT = 1)
materials_base = list(MAT_STEEL = 100)
+ belt_storage_class = BELT_CLASS_SMALL
var/armed = 0
diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm
index ea525ebfcad..737292ac29c 100644
--- a/code/modules/clothing/glasses/_glasses.dm
+++ b/code/modules/clothing/glasses/_glasses.dm
@@ -17,6 +17,7 @@ BLIND // can't see anything
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_EYES
active_slots = list(SLOT_ID_GLASSES)
+ belt_storage_class = BELT_CLASS_SMALL
var/prescription = 0
drop_sound = 'sound/items/drop/accessory.ogg'
pickup_sound = 'sound/items/pickup/accessory.ogg'
diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm
index 2a3767a3e77..fb8c5e86321 100644
--- a/code/modules/clothing/gloves/_gloves.dm
+++ b/code/modules/clothing/gloves/_gloves.dm
@@ -24,6 +24,7 @@
unequip_sound = 'sound/items/drop/gloves.ogg'
pickup_sound = 'sound/items/pickup/gloves.ogg'
material_factoring = 0
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/clothing/gloves/get_fibers()
return "material from a pair of [name]."
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 233e9bec06e..e1b13028c30 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -18,6 +18,7 @@
pickup_sound = 'sound/items/pickup/helm.ogg'
encumbrance = ITEM_ENCUMBRANCE_ARMOR_MEDIUM_HELMET
weight = ITEM_WEIGHT_ARMOR_MEDIUM_HELMET
+ suit_storage_class = SUIT_STORAGE_CLASS_ARMOR
material_factoring = 0.000075
/obj/item/clothing/head/helmet/ntsec
diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm
index 7ab5aa4ad14..3354c7f9ac7 100644
--- a/code/modules/clothing/head/jobs.dm
+++ b/code/modules/clothing/head/jobs.dm
@@ -187,6 +187,7 @@
icon_state = "surgcap_blue"
item_state_slots = list(SLOT_ID_RIGHT_HAND = "beret_blue", SLOT_ID_LEFT_HAND = "beret_blue")
inv_hide_flags = BLOCKHEADHAIR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/clothing/head/surgery/purple
desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs. This one is deep purple."
diff --git a/code/modules/clothing/legacy_accessories/badges.dm b/code/modules/clothing/legacy_accessories/badges.dm
index 41e07fa3bc6..504c060f320 100644
--- a/code/modules/clothing/legacy_accessories/badges.dm
+++ b/code/modules/clothing/legacy_accessories/badges.dm
@@ -10,6 +10,7 @@
icon_state = "badge"
slot_flags = SLOT_BELT | SLOT_TIE
slot = ACCESSORY_SLOT_MEDAL
+ belt_storage_class = BELT_CLASS_SMALL
var/stored_name
var/badge_string = "Corporate Security"
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index 7185c59a354..1fef266e0d7 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -37,6 +37,7 @@
permeability_coefficient = 0.01
armor_type = /datum/armor/mask/surgical
materials_base = list(MAT_PLASTIC = 100, MAT_WOOD = 20)
+ belt_storage_class = BELT_CLASS_SMALL
var/hanging = 0
/obj/item/clothing/mask/surgical/proc/adjust_mask(mob_user)
diff --git a/code/modules/detectivework/tools/sample_kits.dm b/code/modules/detectivework/tools/sample_kits.dm
index 2ead00fe529..c1099729b59 100644
--- a/code/modules/detectivework/tools/sample_kits.dm
+++ b/code/modules/detectivework/tools/sample_kits.dm
@@ -131,6 +131,7 @@
desc = "A magnifying glass and tweezers. Used to lift suit fibers."
icon_state = "m_glass"
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_SMALL
var/evidence_type = "fiber"
var/evidence_path = /obj/item/sample/fibers
diff --git a/code/modules/detectivework/tools/swabs.dm b/code/modules/detectivework/tools/swabs.dm
index 047d7fbad11..82b2bec9550 100644
--- a/code/modules/detectivework/tools/swabs.dm
+++ b/code/modules/detectivework/tools/swabs.dm
@@ -7,6 +7,7 @@
var/used
drop_sound = 'sound/items/drop/glass.ogg'
pickup_sound = 'sound/items/pickup/glass.ogg'
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/forensics/swab/proc/is_used()
return used
diff --git a/code/modules/detectivework/tools/uvlight.dm b/code/modules/detectivework/tools/uvlight.dm
index f97e1ff01ee..1583bffa3ed 100644
--- a/code/modules/detectivework/tools/uvlight.dm
+++ b/code/modules/detectivework/tools/uvlight.dm
@@ -10,6 +10,7 @@
materials_base = list(MAT_STEEL = 150)
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/list/scanned = list()
var/list/stored_alpha = list()
diff --git a/code/modules/examine/descriptions/food.dm b/code/modules/examine/descriptions/food.dm
index f9ee74e42b4..3837f12d02d 100644
--- a/code/modules/examine/descriptions/food.dm
+++ b/code/modules/examine/descriptions/food.dm
@@ -10,9 +10,6 @@
/obj/item/reagent_containers/food/snacks/bagged/chips
description_fluff = "Actual potatos haven't been used in potato chips for centuries. They're mostly a denatured nutrient slurry pressed into a chip-shaped mold and salted. Still tastes the same."
-/obj/item/reagent_containers/food/snacks/donut
- description_fluff = "These donuts claim to be made fresh daily in a boutique bakery in New Reykjavik and delivered to Nanotrasen's hardworking asset protection crew. They're probably synthesized."
-
/obj/item/reagent_containers/food/snacks/donkpocket
description_fluff = "DONKpockets were originally a Nanotrasen product, an attempt to break into the food market controlled by Centauri Provisions. Somehow, Centauri wound up with the rights to the DONK brand, ending Nanotrasen's ambitions. They taste pretty okay."
diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm
index 396ecf06fdb..a35f1c9e5a9 100644
--- a/code/modules/food/food/snacks.dm
+++ b/code/modules/food/food/snacks.dm
@@ -561,10 +561,12 @@
/obj/item/reagent_containers/food/snacks/donut
name = "donut"
desc = "Goes great with Robust Coffee."
+ description_fluff = "These donuts claim to be made fresh daily in a boutique bakery in New Reykjavik and delivered to Nanotrasen's hardworking asset protection crew. They're probably synthesized."
icon_state = "donut1"
filling_color = "#D9C386"
var/overlay_state = "box-donut1"
nutriment_desc = list("sweetness", "donut")
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/reagent_containers/food/snacks/donut/normal
name = "donut"
diff --git a/code/modules/food/glass/bottle.dm b/code/modules/food/glass/bottle.dm
index 0203973446c..ccf65656400 100644
--- a/code/modules/food/glass/bottle.dm
+++ b/code/modules/food/glass/bottle.dm
@@ -9,6 +9,7 @@
item_state = "atoxinbottle"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,25,30,60)
atom_flags = 0
diff --git a/code/modules/genetics/dna_injector.dm b/code/modules/genetics/dna_injector.dm
index 0dabe2cb4c9..554d0b9db15 100644
--- a/code/modules/genetics/dna_injector.dm
+++ b/code/modules/genetics/dna_injector.dm
@@ -4,6 +4,7 @@
desc = "This injects the person with DNA."
icon = 'icons/obj/items.dmi'
icon_state = "dnainjector"
+ belt_storage_class = BELT_CLASS_SMALL
var/block=0
var/datum/dna2/record/buf
var/s_time = 10.0
diff --git a/code/modules/integrated_electronics/tools/debugger.dm b/code/modules/integrated_electronics/tools/debugger.dm
index 5503b8959d1..ec507708ac1 100644
--- a/code/modules/integrated_electronics/tools/debugger.dm
+++ b/code/modules/integrated_electronics/tools/debugger.dm
@@ -5,6 +5,7 @@
icon = 'icons/obj/integrated_electronics/electronic_tools.dmi'
icon_state = "debugger"
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_SMALL
var/data_to_write = null
var/accepting_refs = FALSE
var/copy_values = FALSE
diff --git a/code/modules/integrated_electronics/tools/wirer.dm b/code/modules/integrated_electronics/tools/wirer.dm
index e0b69ca634d..888e6b9e966 100644
--- a/code/modules/integrated_electronics/tools/wirer.dm
+++ b/code/modules/integrated_electronics/tools/wirer.dm
@@ -13,6 +13,7 @@
icon_state = "wirer-wire"
item_state = "wirer"
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_SMALL
var/mode = WIRE
var/datum/weakref/selected_io_weakref
diff --git a/code/modules/materials/definitions/misc/plastic.dm b/code/modules/materials/definitions/misc/plastic.dm
index b223c8bc6cc..e1008d31a38 100644
--- a/code/modules/materials/definitions/misc/plastic.dm
+++ b/code/modules/materials/definitions/misc/plastic.dm
@@ -34,7 +34,7 @@
)
. += create_stack_recipe_datum(
name = "plastic bag",
- product = /obj/item/storage/bag/plasticbag,
+ product = /obj/item/storage/bag/trash/plasticbag,
cost = 3,
)
. += create_stack_recipe_datum(
diff --git a/code/modules/mining/tools/mine_items.dm b/code/modules/mining/tools/mine_items.dm
index 5d8fbd1f6c3..1c951d3a162 100644
--- a/code/modules/mining/tools/mine_items.dm
+++ b/code/modules/mining/tools/mine_items.dm
@@ -24,6 +24,7 @@
materials_base = list(MAT_STEEL = 3750)
worth_intrinsic = 75
suit_storage_class = SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_LARGE
var/digspeed = 40 //moving the delay to an item var so R&D can make improved picks. --NEO
var/sand_dig = FALSE
origin_tech = list(TECH_MATERIAL = 1, TECH_ENGINEERING = 1)
diff --git a/code/modules/mob/living/silicon/robot/analyzer.dm b/code/modules/mob/living/silicon/robot/analyzer.dm
index 31ef9acc564..1379fc03649 100644
--- a/code/modules/mob/living/silicon/robot/analyzer.dm
+++ b/code/modules/mob/living/silicon/robot/analyzer.dm
@@ -15,6 +15,7 @@
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 1, TECH_ENGINEERING = 2)
materials_base = list(MAT_STEEL = 500, MAT_GLASS = 200)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/mode = 1;
/obj/item/robotanalyzer/legacy_mob_melee_hook(mob/target, mob/user, clickchain_flags, list/params, mult, target_zone, intent)
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index 623a3390031..62aaa57e9b1 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -9,6 +9,7 @@
throw_range = 7
slot_flags = SLOT_BELT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/// The stored pen
var/obj/item/pen/pen
diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm
index d7b59cdf517..c8afcd75983 100644
--- a/code/modules/paperwork/folders.dm
+++ b/code/modules/paperwork/folders.dm
@@ -4,6 +4,7 @@
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "folder"
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_SMALL
pressure_resistance = 2
drop_sound = 'sound/items/drop/paper.ogg'
pickup_sound = 'sound/items/pickup/paper.ogg'
diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm
index a9c56da9727..093423ad1b4 100644
--- a/code/modules/paperwork/handlabeler.dm
+++ b/code/modules/paperwork/handlabeler.dm
@@ -5,6 +5,7 @@
icon_state = "labeler0"
item_flags = ITEM_NO_BLUDGEON
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_SMALL
drop_sound = 'sound/items/handling/tape_drop.ogg'
pickup_sound = 'sound/items/handling/tape_pickup.ogg'
worth_intrinsic = 50
diff --git a/code/modules/paperwork/paper/paper.dm b/code/modules/paperwork/paper/paper.dm
index 189bde55f92..86b74194d3d 100644
--- a/code/modules/paperwork/paper/paper.dm
+++ b/code/modules/paperwork/paper/paper.dm
@@ -16,6 +16,7 @@
icon_state = "paper"
item_state = "paper"
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
throw_force = 0
w_class = WEIGHT_CLASS_TINY
throw_range = 1
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index a44fde0ed7d..ad2984b3b19 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -44,6 +44,7 @@
item_state = "pen"
slot_flags = SLOT_BELT | SLOT_EARS
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
throw_force = 0
w_class = WEIGHT_CLASS_TINY
throw_speed = 7
diff --git a/code/modules/photography/camera.dm b/code/modules/photography/camera.dm
index efdd468f182..c680b458293 100644
--- a/code/modules/photography/camera.dm
+++ b/code/modules/photography/camera.dm
@@ -9,6 +9,7 @@
desc = "A polaroid camera. 10 photos left."
item_flags = ITEM_NO_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_BELT
materials_base = list(MAT_STEEL = 2000)
diff --git a/code/modules/photography/film.dm b/code/modules/photography/film.dm
index 1520a85ee5c..18bc42f71d7 100644
--- a/code/modules/photography/film.dm
+++ b/code/modules/photography/film.dm
@@ -6,6 +6,7 @@
icon = 'icons/modules/photography/film.dmi'
icon_state = "film"
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
worn_render_flags = WORN_RENDER_INHAND_ALLOW_DEFAULT
inhand_default_type = INHAND_DEFAULT_ICON_STORAGE
inhand_state = "camera"
diff --git a/code/modules/photography/photo.dm b/code/modules/photography/photo.dm
index b13d9ba43b5..d7c6928ca07 100644
--- a/code/modules/photography/photo.dm
+++ b/code/modules/photography/photo.dm
@@ -38,6 +38,7 @@
w_class = WEIGHT_CLASS_TINY
drop_sound = 'sound/items/drop/paper.ogg'
pickup_sound = 'sound/items/pickup/paper.ogg'
+ belt_storage_class = BELT_CLASS_SMALL
/// scribble on the back
var/scribble
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index a3053ee012f..c1451b02d2d 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -535,6 +535,7 @@ GLOBAL_LIST_INIT(possible_cable_coil_colours, list(
color = COLOR_RED
desc = "A coil of power cable."
throw_force = 10
+ belt_storage_class = BELT_CLASS_SMALL
w_class = WEIGHT_CLASS_SMALL
throw_speed = 2
throw_range = 5
diff --git a/code/modules/power/cells/types/special/slime_core.dm b/code/modules/power/cells/types/special/slime_core.dm
index 099e6a5eef9..df9122ae6cf 100644
--- a/code/modules/power/cells/types/special/slime_core.dm
+++ b/code/modules/power/cells/types/special/slime_core.dm
@@ -72,6 +72,8 @@
self_recharge_amount = POWER_CELL_CAPACITY_SMALL * (5 / 6) / ((4 MINUTES) / (1 SECONDS))
cell_type = CELL_TYPE_SMALL
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_SMALL
+ belt_storage_size = BELT_SIZE_FOR_SMALL_CELL / 2
weight_volume = ITEM_VOLUME_SMALL_CELL / 2
/obj/item/cell/slime_core/fourth
@@ -87,6 +89,8 @@
self_recharge_amount = POWER_CELL_CAPACITY_WEAPON * (5 / 6) / ((4 MINUTES) / (1 SECONDS))
cell_type = CELL_TYPE_WEAPON
w_class = WEIGHT_CLASS_SMALL
+ belt_storage_class = BELT_CLASS_SMALL
+ belt_storage_size = BELT_SIZE_FOR_SMALL_CELL
weight_volume = ITEM_VOLUME_WEAPON_CELL / 2
/obj/item/cell/slime_core/half
@@ -102,6 +106,8 @@
self_recharge_amount = POWER_CELL_CAPACITY_MEDIUM * (5 / 6) / ((4 MINUTES) / (1 SECONDS))
cell_type = CELL_TYPE_MEDIUM
w_class = WEIGHT_CLASS_NORMAL
+ belt_storage_class = BELT_CLASS_MEDIUM
+ belt_storage_size = BELT_SIZE_FOR_MEDIUM_CELL / 2
weight_volume = ITEM_VOLUME_MEDIUM_CELL / 2
/obj/item/cell/slime_core/whole
@@ -117,4 +123,6 @@
self_recharge_amount = POWER_CELL_CAPACITY_LARGE * (5 / 6) / ((4 MINUTES) / (1 SECONDS))
cell_type = CELL_TYPE_LARGE
w_class = WEIGHT_CLASS_NORMAL
+ belt_storage_class = BELT_CLASS_MEDIUM
+ belt_storage_size = BELT_SIZE_FOR_MEDIUM_CELL
weight_volume = ITEM_VOLUME_LARGE_CELL / 2
diff --git a/code/modules/power/lighting/lights.dm b/code/modules/power/lighting/lights.dm
index 7029e40a8dc..d2338cf9ad2 100644
--- a/code/modules/power/lighting/lights.dm
+++ b/code/modules/power/lighting/lights.dm
@@ -41,6 +41,8 @@
base_icon_state = "ltube"
item_state = "c_tube"
materials_base = list(MAT_GLASS = 100)
+ belt_storage_class = BELT_CLASS_SMALL
+
brightness_range = 8
brightness_power = 0.8
brightness_color = LIGHT_COLOR_HALOGEN
@@ -114,6 +116,7 @@
base_icon_state = "lbulb"
item_state = "contvapour"
materials_base = list(MAT_GLASS = 100)
+ belt_storage_class = BELT_CLASS_SMALL
brightness_color = LIGHT_COLOR_TUNGSTEN
brightness_range = 4
diff --git a/code/modules/projectiles/ammunition/ammo_casing.dm b/code/modules/projectiles/ammunition/ammo_casing.dm
index 99ce49d8cd6..d431bbc556a 100644
--- a/code/modules/projectiles/ammunition/ammo_casing.dm
+++ b/code/modules/projectiles/ammunition/ammo_casing.dm
@@ -9,6 +9,8 @@
w_class = WEIGHT_CLASS_TINY
drop_sound = 'sound/items/drop/ring.ogg'
pickup_sound = 'sound/items/pickup/ring.ogg'
+ belt_storage_class = BELT_CLASS_SMALL
+ belt_storage_size = BELT_SIZE_FOR_AMMO_CASING
weight_volume = ITEM_VOLUME_AMMO_CASING
//* Casing *//
diff --git a/code/modules/projectiles/ammunition/ammo_magazine.dm b/code/modules/projectiles/ammunition/ammo_magazine.dm
index 51110064221..de71705a68a 100644
--- a/code/modules/projectiles/ammunition/ammo_magazine.dm
+++ b/code/modules/projectiles/ammunition/ammo_magazine.dm
@@ -11,6 +11,8 @@
item_flags = ITEM_EASY_LATHE_DECONSTRUCT | ITEM_ENCUMBERS_WHILE_HELD
slot_flags = SLOT_BELT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_MEDIUM
+ belt_storage_size = BELT_SIZE_FOR_MAGAZINE
icon = 'icons/system/error_32x32.dmi'
inhand_state = "syringe_kit"
diff --git a/code/modules/projectiles/guns/gun.dm b/code/modules/projectiles/guns/gun.dm
index b413dcf6cf2..22f1e23b2e3 100644
--- a/code/modules/projectiles/guns/gun.dm
+++ b/code/modules/projectiles/guns/gun.dm
@@ -50,6 +50,7 @@
item_state = "gun"
item_flags = ITEM_ENCUMBERS_WHILE_HELD | ITEM_ENCUMBERS_ONLY_HELD
slot_flags = SLOT_BELT|SLOT_HOLSTER
+ belt_storage_class = BELT_CLASS_LARGE
// Fuck it YOLO guns go everywhere now because it's pointless arguing at this point, maybe this'll be re-evaluated later.
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR | SUIT_STORAGE_CLASS_ARMOR
materials_base = list(MAT_STEEL = 2000)
diff --git a/code/modules/reagents/items/hypospray.dm b/code/modules/reagents/items/hypospray.dm
index ceb61f57b05..b91e16b91f5 100644
--- a/code/modules/reagents/items/hypospray.dm
+++ b/code/modules/reagents/items/hypospray.dm
@@ -13,6 +13,7 @@
pickup_sound = 'sound/items/pickup/gun.ogg'
worn_render_flags = NONE
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_MEDIUM
/// loaded vial
var/obj/item/reagent_containers/glass/hypovial/loaded
diff --git a/code/modules/reagents/items/hypovial.dm b/code/modules/reagents/items/hypovial.dm
index 17689b32f04..d7116e166e7 100644
--- a/code/modules/reagents/items/hypovial.dm
+++ b/code/modules/reagents/items/hypovial.dm
@@ -14,6 +14,7 @@
/// how many [state][#] overlays we have for reagents remaining
var/overlay_count = 3
item_flags = ITEM_CAREFUL_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD | ITEM_EASY_LATHE_DECONSTRUCT
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/reagent_containers/glass/hypovial/update_icon(updates)
cut_overlays()
diff --git a/code/modules/reagents/items/spray.dm b/code/modules/reagents/items/spray.dm
index a7bd3ab2d98..e1463a63031 100644
--- a/code/modules/reagents/items/spray.dm
+++ b/code/modules/reagents/items/spray.dm
@@ -14,6 +14,7 @@
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10) //Set to null instead of list, if there is only one.
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_MEDIUM
var/spray_size = 3
var/list/spray_sizes = list(1,3)
volume = 250
@@ -123,6 +124,7 @@
icon_state = "pepperspray"
item_state = "pepperspray"
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
possible_transfer_amounts = null
volume = 40
worth_intrinsic = 85
diff --git a/code/modules/reagents/machinery/chem_master.dm b/code/modules/reagents/machinery/chem_master.dm
index ad50f9ab65c..0ef6f59936e 100644
--- a/code/modules/reagents/machinery/chem_master.dm
+++ b/code/modules/reagents/machinery/chem_master.dm
@@ -235,7 +235,7 @@
data["is_pill_bottle_loaded"] = pill_bottle ? TRUE : FALSE
if(pill_bottle)
data["pill_bottle_current_amount"] = pill_bottle.contents.len
- data["pill_bottle_max_amount"] = pill_bottle.max_combined_volume
+ data["pill_bottle_max_amount"] = pill_bottle.obj_storage?.max_combined_volume / ITEM_VOLUME_PILL
data["is_beaker_loaded"] = beaker ? TRUE : FALSE
data["beaker_current_volume"] = beaker ? round(beaker.reagents.total_volume, 0.01) : null
@@ -402,8 +402,8 @@
var/target_loc = drop_location()
var/drop_threshold = INFINITY
if(pill_bottle)
- if(pill_bottle.max_combined_volume)
- drop_threshold = pill_bottle.max_combined_volume - pill_bottle.contents.len
+ if(pill_bottle.obj_storage)
+ drop_threshold = (pill_bottle.obj_storage.max_combined_volume - pill_bottle.contents.len * ITEM_VOLUME_PILL) / ITEM_VOLUME_PILL
target_loc = pill_bottle
for(var/i in 1 to amount)
if(i-1 < drop_threshold)
diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm
index 8e6e4f59f89..715da6b6697 100644
--- a/code/modules/reagents/reagent_containers/dropper.dm
+++ b/code/modules/reagents/reagent_containers/dropper.dm
@@ -15,6 +15,7 @@
pickup_sound = 'sound/items/pickup/glass.ogg'
integrity_flags = INTEGRITY_ACIDPROOF
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/reagent_containers/dropper/examine(mob/user, dist)
. = ..()
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index 3cd8e9f9908..bafaec17ab8 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -153,6 +153,7 @@
item_state = "beaker"
materials_base = list(MAT_GLASS = 500)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
w_class = WEIGHT_CLASS_TINY
drop_sound = 'sound/items/drop/glass.ogg'
pickup_sound = 'sound/items/pickup/glass.ogg'
@@ -160,7 +161,6 @@
var/rped_rating = 0
item_flags = ITEM_CAREFUL_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD | ITEM_EASY_LATHE_DECONSTRUCT
-
/obj/item/reagent_containers/glass/beaker/Initialize(mapload)
. = ..()
desc += " Can hold up to [volume] units."
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index f263b2e6e48..2dee5385532 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -18,6 +18,7 @@
pickup_sound = 'sound/items/pickup/gun.ogg'
preserve_item = 1
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/filled = 0
var/list/filled_reagents = list()
var/hyposound // What sound do we play on use?
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index e94670401cf..496939f9432 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -12,9 +12,12 @@
pickup_sound = 'sound/items/pickup/food.ogg'
rad_flags = RAD_NO_CONTAMINATE
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
+ belt_storage_size = BELT_SIZE_FOR_PILL
possible_transfer_amounts = null
w_class = WEIGHT_CLASS_TINY
+ weight_volume = ITEM_VOLUME_PILL
slot_flags = SLOT_EARS
volume = 60
diff --git a/code/modules/reagents/reagent_containers/syringe.dm b/code/modules/reagents/reagent_containers/syringe.dm
index 626c26f720d..b4c67403ef6 100644
--- a/code/modules/reagents/reagent_containers/syringe.dm
+++ b/code/modules/reagents/reagent_containers/syringe.dm
@@ -15,6 +15,8 @@
rad_flags = RAD_NO_CONTAMINATE
item_flags = ITEM_NO_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD | ITEM_EASY_LATHE_DECONSTRUCT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR
+ belt_storage_class = BELT_CLASS_SMALL
+ belt_storage_size = BELT_SIZE_FOR_SYRINGE
var/mode = SYRINGE_DRAW
var/image/filling //holds a reference to the current filling overlay
var/visible_name = "a syringe"
diff --git a/code/modules/xenoarcheaology/sampling.dm b/code/modules/xenoarcheaology/sampling.dm
index 8ee7704f6ce..b718d6d536e 100644
--- a/code/modules/xenoarcheaology/sampling.dm
+++ b/code/modules/xenoarcheaology/sampling.dm
@@ -24,6 +24,7 @@
w_class = WEIGHT_CLASS_TINY
worth_intrinsic = 50
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/sampled_turf = ""
var/num_stored_bags = 10
diff --git a/code/modules/xenoarcheaology/tools/ano_device_battery.dm b/code/modules/xenoarcheaology/tools/ano_device_battery.dm
index d4552669cb5..f0dd46df3df 100644
--- a/code/modules/xenoarcheaology/tools/ano_device_battery.dm
+++ b/code/modules/xenoarcheaology/tools/ano_device_battery.dm
@@ -2,6 +2,7 @@
name = "Anomaly power battery"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "anobattery0"
+ belt_storage_class = BELT_CLASS_SMALL
var/datum/artifact_effect/battery_effect
var/capacity = 300
var/stored_charge = 0
@@ -23,6 +24,7 @@
name = "Anomaly power utilizer"
icon = 'icons/obj/xenoarchaeology.dmi'
icon_state = "anodev"
+ belt_storage_class = BELT_CLASS_SMALL
var/activated = 0
var/duration = 0
var/interval = 0
diff --git a/code/modules/xenoarcheaology/tools/tools.dm b/code/modules/xenoarcheaology/tools/tools.dm
index d80e02ebfe6..2e4363e3c08 100644
--- a/code/modules/xenoarcheaology/tools/tools.dm
+++ b/code/modules/xenoarcheaology/tools/tools.dm
@@ -7,6 +7,7 @@
materials_base = list(MAT_STEEL = 100)
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/storage/bag/fossils
name = "Fossil Satchel"
@@ -20,6 +21,7 @@
max_single_weight_class = WEIGHT_CLASS_NORMAL
insertion_whitelist = list(/obj/item/fossil)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/storage/box/samplebags
name = "sample bag box"
@@ -43,6 +45,7 @@
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_BELT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/last_scan_time = 0
var/scan_delay = 25
@@ -105,6 +108,7 @@
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_BELT
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/list/positive_locations = list()
var/datum/depth_scan/current
@@ -238,6 +242,7 @@
origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3)
materials_base = list(MAT_STEEL = 1000, MAT_GLASS = 500)
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/frequency = FREQ_COMMON
var/scan_ticks = 0
var/obj/item/radio/target_radio
@@ -344,6 +349,7 @@
slot_flags = SLOT_BELT
worth_intrinsic = 250
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
var/mode = 1 //Start off scanning. 1 = scanning, 0 = measuring
var/obj/item/ano_scanner/anomaly_scanner = null
var/obj/item/depth_scanner/depth_scanner = null
diff --git a/code/modules/xenoarcheaology/tools/tools_pickaxe.dm b/code/modules/xenoarcheaology/tools/tools_pickaxe.dm
index 479fb7ae31d..b8842f5857b 100644
--- a/code/modules/xenoarcheaology/tools/tools_pickaxe.dm
+++ b/code/modules/xenoarcheaology/tools/tools_pickaxe.dm
@@ -13,6 +13,7 @@
drill_verb = "brushing"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/pickaxe/one_pick
name = "2cm pick"
@@ -27,6 +28,7 @@
drill_verb = "delicately picking"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/pickaxe/two_pick
name = "4cm pick"
@@ -41,6 +43,7 @@
drill_verb = "delicately picking"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/pickaxe/three_pick
name = "6cm pick"
@@ -55,6 +58,7 @@
drill_verb = "delicately picking"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/pickaxe/four_pick
name = "8cm pick"
@@ -69,6 +73,7 @@
drill_verb = "delicately picking"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/pickaxe/five_pick
name = "10cm pick"
@@ -83,6 +88,7 @@
drill_verb = "delicately picking"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/pickaxe/six_pick
name = "12cm pick"
@@ -97,6 +103,7 @@
drill_verb = "delicately picking"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/pickaxe/hand
name = "hand pickaxe"
@@ -111,6 +118,7 @@
drill_verb = "clearing"
w_class = WEIGHT_CLASS_SMALL
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
+ belt_storage_class = BELT_CLASS_SMALL
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pack for holding pickaxes
@@ -123,14 +131,17 @@
item_state = "syringe_kit"
max_items = 7
w_class = WEIGHT_CLASS_SMALL
- insertion_whitelist = list(/obj/item/pickaxe/brush,
- /obj/item/pickaxe/one_pick,
- /obj/item/pickaxe/two_pick,
- /obj/item/pickaxe/three_pick,
- /obj/item/pickaxe/four_pick,
- /obj/item/pickaxe/five_pick,
- /obj/item/pickaxe/six_pick,
- /obj/item/pickaxe/hand)
+ belt_storage_class = BELT_CLASS_SMALL
+ insertion_whitelist = list(
+ /obj/item/pickaxe/brush,
+ /obj/item/pickaxe/one_pick,
+ /obj/item/pickaxe/two_pick,
+ /obj/item/pickaxe/three_pick,
+ /obj/item/pickaxe/four_pick,
+ /obj/item/pickaxe/five_pick,
+ /obj/item/pickaxe/six_pick,
+ /obj/item/pickaxe/hand,
+ )
max_combined_volume = WEIGHT_VOLUME_SMALL * 9
max_single_weight_class = WEIGHT_CLASS_SMALL
allow_mass_gather = TRUE
@@ -159,6 +170,7 @@
w_class = 2
attack_verb = list("drilled")
worth_intrinsic = 250 // this is gonna be very useful/powerful later
+ belt_storage_class = BELT_CLASS_SMALL
/obj/item/pickaxe/excavationdrill/attack_self(mob/user, datum/event_args/actor/actor)
. = ..()