mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-29 09:16:43 +01:00
Belts & Trashbags (#7443)
requires #6644 Entirely replaces how (most) belts perform insertion checks. This pretty much allows belts to hold most things. Armor vests are next. Trashbags will also use the systems we use on main. Closes #7256 and #7435 --------- Co-authored-by: silicons <silicons@silicons.dev>
This commit is contained in:
@@ -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)
|
||||
|
||||
+26
-24
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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, "<span class='warning'>The Bluespace interfaces of the two devices conflict and malfunction.</span>")
|
||||
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)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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 += "<b>[used_slots[i] > max_slots[i] ? SPAN_DANGER("[used_slots[i]]") : used_slots[i]]/[max_slots[i]]</b> \
|
||||
[lowertext(global.belt_class_names[i + 1])]"
|
||||
examine_list += SPAN_NOTICE("This is a storage item with <b>belt loops</b>. 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user