Adds the parcel cart to operations. (#21288)

This adds a parcel cart to the mail room in operations, which can be
loaded with up to 17 packages. These packages can be any that can be
held in the hand, so not crates but anything smaller effectively yes as
long as it can be wrapped in package wrapper.
When it is loaded with 5 packages, it gives a slowdown to the person
pushing it, and further slowdown at 11 packages.
The cart can have a total of 17 packages at the moment, as that is the
amount of different sprites I have for it.
The code is based on the engineering cart, and also contain a small
bugfix so the engineering cart give back steel when taken apart, as that
is what is used to build it.


https://github.com/user-attachments/assets/b8613c9e-55e1-4f76-926a-60f4acd6269e

### Asset Licenses
The following assets that **have not** been created by myself are
included in this PR:

| Path | Original Author | License |
| --- | --- | --- |
| icons/obj/parcelcart.dmi | Tomixcomics (Aurora Station) | CC-BY |
This commit is contained in:
Casper3667
2025-09-10 19:05:19 +00:00
committed by GitHub
parent e2b00ebe46
commit 9a9e259104
50 changed files with 367 additions and 328 deletions
+141
View File
@@ -0,0 +1,141 @@
ABSTRACT_TYPE(/obj/structure/cart)
name = "cart parent item"
desc = DESC_PARENT
icon_state = "cart"
anchored = FALSE
density = TRUE
climbable = TRUE
build_amt = 15
material = DEFAULT_WALL_MATERIAL
slowdown = 0
var/movesound = 'sound/effects/roll.ogg'
var/driving
var/mob/living/pulling
/obj/structure/cart/mechanics_hints(mob/user, distance, is_adjacent)
. += ..()
. += "\
You can <b>CTRL-Click</b> to start dragging this cart. This object has a special dragging behaviour: when dragged, character's movement \
directs the cart and the character is subsequently pulled by it. \
"
/obj/structure/cart/disassembly_hints(mob/user, distance, is_adjacent)
. += ..()
. += "An empty cart can be taken apart with a <b>wrench</b> or a <b>welder</b>. Or a <b>plasma cutter</b>, if you're that hardcore."
/obj/structure/cart/proc/take_apart(var/mob/user = null, var/obj/I)
if(user)
if(iswelder(I))
var/obj/item/welder = I
welder.play_tool_sound(get_turf(src), 50)
user.visible_message("<b>[user]</b> starts taking apart the [src]...", SPAN_NOTICE("You start disassembling the [src]..."))
if (!do_after(user, 30, do_flags = DO_DEFAULT & ~DO_USER_SAME_HAND))
return
dismantle()
/obj/structure/cart/ex_act(severity)
spill(100 / severity)
..()
/obj/structure/cart/proc/spill(var/chance = 100)
/obj/structure/cart/proc/update_slowdown()
/obj/structure/cart/relaymove(mob/living/user, direction)
. = ..()
if(user.stat || user.stunned || user.weakened || user.paralysis || user.lying || user.restrained())
if(user==pulling)
pulling = null
user.pulledby = null
to_chat(user, SPAN_WARNING("You lost your grip!"))
return
if(user.pulling && (user == pulling))
pulling = null
user.pulledby = null
return
if(pulling && (get_dist(src, pulling) > 1))
pulling = null
user.pulledby = null
if(user==pulling)
return
if(pulling && (get_dir(src.loc, pulling.loc) == direction))
to_chat(user, SPAN_WARNING("You cannot go there."))
return
driving = 1
var/turf/T = null
if(pulling)
T = pulling.loc
if(get_dist(src, pulling) >= 1)
step(pulling, get_dir(pulling.loc, src.loc))
step(src, direction)
set_dir(direction)
if(pulling)
if(pulling.loc == src.loc)
pulling.forceMove(T)
else
spawn(0)
if(get_dist(src, pulling) > 1)
pulling = null
user.pulledby = null
pulling.set_dir(get_dir(pulling, src))
driving = 0
/obj/structure/cart/Move()
. = ..()
if (pulling && (get_dist(src, pulling) > 1))
pulling.pulledby = null
to_chat(pulling, SPAN_WARNING("You lost your grip!"))
pulling = null
if(has_gravity())
playsound(src, movesound, 50, 1)
/obj/structure/cart/CtrlClick(var/mob/user)
if(in_range(src, user))
if(!ishuman(user)) return
if(!pulling)
pulling = user
user.pulledby = src
if(user.pulling)
user.stop_pulling()
user.set_dir(get_dir(user, src))
to_chat(user, SPAN_NOTICE("You grip \the [name]'s handles."))
else
to_chat(user, SPAN_NOTICE("You let go of \the [name]'s handles."))
pulling.pulledby = null
pulling = null
return
/obj/structure/cart/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0))
return TRUE
if(mover?.movement_type & PHASING)
return TRUE
if(istype(mover) && mover.pass_flags & PASSTABLE)
return TRUE
if(istype(mover, /mob/living) && mover == pulling)
return TRUE
else
if(istype(mover, /obj/projectile))
return prob(20)
else
return !density
ABSTRACT_TYPE(/obj/structure/cart/storage)
var/has_items = FALSE
/// Used for displaying and handling radial menu. Collective list of every single item this object contains.
var/list/storage_contents = list()
/obj/structure/cart/storage/proc/handle_storing(var/attacking_item, var/mob/user, var/should_store, var/storage_is_full)
/obj/structure/cart/storage/proc/get_storage_contents_list()
/obj/structure/cart/storage/take_apart(var/mob/user = null, var/obj/I)
if(has_items)
spill()
. = ..()
@@ -1,27 +1,16 @@
/obj/structure/engineeringcart
/obj/structure/cart/storage/engineeringcart
name = "engineering cart"
desc = "A cart for your engineering-related storage needs."
icon = 'icons/obj/engicart.dmi'
icon_state = "cart"
anchored = FALSE
density = TRUE
climbable = TRUE
build_amt = 15
material = DEFAULT_TABLE_REINF_MATERIAL
slowdown = 0
var/has_items = FALSE
var/list/my_glass = list()
var/list/my_metal = list()
var/list/my_plasteel = list()
/// Used for displaying and handling radial menu. Collective list of every single item this object contains.
var/list/storage_contents = list()
var/obj/item/device/lightreplacer/my_lightreplacer = null
var/obj/item/storage/toolbox/mechanical/my_blue_toolbox = null
var/obj/item/storage/toolbox/electrical/my_yellow_toolbox = null
var/obj/item/storage/toolbox/emergency/my_red_toolbox = null
var/driving
var/mob/living/pulling
/// Amount of stacks the cart is capable to store.
var/stack_capacity = 2
@@ -35,19 +24,11 @@
/obj/item/storage/toolbox/emergency
))
/obj/structure/engineeringcart/mechanics_hints(mob/user, distance, is_adjacent)
/obj/structure/cart/storage/engineeringcart/mechanics_hints(mob/user, distance, is_adjacent)
. += ..()
. += "You can use steel, plasteel, glass sheets, toolboxes and light replacers on the cart to store them."
. += "\
You can <b>CTRL-Click</b> to start dragging this cart. This object has a special dragging behaviour: when dragged, character's movement \
directs the cart and the character is subsequently pulled by it. \
"
/obj/structure/engineeringcart/disassembly_hints(mob/user, distance, is_adjacent)
. += ..()
. += "An empty engineering cart can be taken apart with a <b>wrench</b> or a <b>welder</b>. Or a <b>plasma cutter</b>, if you're that hardcore."
/obj/structure/engineeringcart/feedback_hints(mob/user, distance, is_adjacent)
/obj/structure/cart/storage/engineeringcart/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
if(distance <= 1)
if(locate(/obj/item/stack/material) in storage_contents)
@@ -75,7 +56,7 @@
else
. += "[icon2html(src, user)] There is no material in this cart!"
/obj/structure/engineeringcart/proc/get_storage_contents_list()
/obj/structure/cart/storage/engineeringcart/get_storage_contents_list()
storage_contents.Cut()
var/list/lists_to_check = list(
my_glass, my_metal, my_plasteel
@@ -90,7 +71,7 @@
if(O)
storage_contents += O
/obj/structure/engineeringcart/Destroy()
/obj/structure/cart/storage/engineeringcart/Destroy()
QDEL_NULL(my_glass)
QDEL_NULL(my_metal)
QDEL_NULL(my_plasteel)
@@ -100,7 +81,7 @@
QDEL_NULL(my_red_toolbox)
return ..()
/obj/structure/engineeringcart/attackby(obj/item/attacking_item, mob/user)
/obj/structure/cart/storage/engineeringcart/attackby(obj/item/attacking_item, mob/user)
if(is_type_in_typecache(attacking_item, allowed_types))
var/should_store = FALSE
var/storage_is_full = FALSE
@@ -171,28 +152,7 @@
return
..()
// copied from janicart code
/obj/structure/engineeringcart/proc/take_apart(var/mob/user = null, var/obj/I)
if(has_items)
spill()
if(user)
if(iswelder(I))
var/obj/item/welder = I
welder.play_tool_sound(get_turf(src), 50)
user.visible_message("<b>[user]</b> starts taking apart the [src]...", SPAN_NOTICE("You start disassembling the [src]..."))
if (!do_after(user, 30, do_flags = DO_DEFAULT & ~DO_USER_SAME_HAND))
return
dismantle()
/obj/structure/engineeringcart/ex_act(severity)
spill(100 / severity)
..()
/obj/structure/engineeringcart/proc/spill(var/chance = 100)
/obj/structure/cart/storage/engineeringcart/spill(var/chance = 100)
var/turf/dropspot = get_turf(src)
if(LAZYLEN(my_glass) && prob(chance))
var/obj/item/stack/material/glass/G
@@ -243,7 +203,7 @@
update_icon()
/obj/structure/engineeringcart/proc/handle_storing(var/attacking_item, var/mob/user, var/should_store, var/storage_is_full)
/obj/structure/cart/storage/engineeringcart/handle_storing(var/attacking_item, var/mob/user, var/should_store, var/storage_is_full)
if(should_store)
user.drop_from_inventory(attacking_item, src)
get_storage_contents_list()
@@ -254,7 +214,7 @@
else
to_chat(user, SPAN_WARNING("You can't store this here!"))
/obj/structure/engineeringcart/attack_hand(mob/user)
/obj/structure/cart/storage/engineeringcart/attack_hand(mob/user)
if(!isliving(user))
return
@@ -309,7 +269,7 @@
else
to_chat(user, SPAN_WARNING("\The [chosen_item] is not in the cart anymore!"))
/obj/structure/engineeringcart/update_icon()
/obj/structure/cart/storage/engineeringcart/update_icon()
ClearOverlays()
has_items = FALSE
if(my_plasteel.len)
@@ -334,92 +294,9 @@
AddOverlays("cart_redtoolbox")
has_items = TRUE
/obj/structure/cart/storage/engineeringcart/half_filled
/// For future reference, this kind of pulling functions are dependant on a type-check in `mob_movement.dm` line:332
/obj/structure/engineeringcart/relaymove(mob/living/user, direction)
. = ..()
if(user.stat || user.stunned || user.weakened || user.paralysis || user.lying || user.restrained())
if(user==pulling)
pulling = null
user.pulledby = null
to_chat(user, SPAN_WARNING("You lost your grip!"))
return
if(user.pulling && (user == pulling))
pulling = null
user.pulledby = null
return
if(pulling && (get_dist(src, pulling) > 1))
pulling = null
user.pulledby = null
if(user==pulling)
return
if(pulling && (get_dir(src.loc, pulling.loc) == direction))
to_chat(user, SPAN_WARNING("You cannot go there."))
return
driving = 1
var/turf/T = null
if(pulling)
T = pulling.loc
if(get_dist(src, pulling) >= 1)
step(pulling, get_dir(pulling.loc, src.loc))
step(src, direction)
set_dir(direction)
if(pulling)
if(pulling.loc == src.loc)
pulling.forceMove(T)
else
spawn(0)
if(get_dist(src, pulling) > 1)
pulling = null
user.pulledby = null
pulling.set_dir(get_dir(pulling, src))
driving = 0
/obj/structure/engineeringcart/Move()
. = ..()
if (pulling && (get_dist(src, pulling) > 1))
pulling.pulledby = null
to_chat(pulling, SPAN_WARNING("You lost your grip!"))
pulling = null
if(has_gravity())
playsound(src, 'sound/effects/roll.ogg', 50, 1)
/obj/structure/engineeringcart/CtrlClick(var/mob/user)
if(in_range(src, user))
if(!ishuman(user)) return
if(!pulling)
pulling = user
user.pulledby = src
if(user.pulling)
user.stop_pulling()
user.set_dir(get_dir(user, src))
to_chat(user, "You grip \the [name]'s handles.")
else
to_chat(usr, "You let go of \the [name]'s handles.")
pulling.pulledby = null
pulling = null
return
/obj/structure/engineeringcart/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0))
return TRUE
if(mover?.movement_type & PHASING)
return TRUE
if(istype(mover) && mover.pass_flags & PASSTABLE)
return TRUE
if(istype(mover, /mob/living) && mover == pulling)
return TRUE
else
if(istype(mover, /obj/projectile))
return prob(30)
else
return !density
/obj/structure/engineeringcart/half_filled
/obj/structure/engineeringcart/half_filled/Initialize()
/obj/structure/cart/storage/engineeringcart/half_filled/Initialize()
. = ..()
my_blue_toolbox = new /obj/item/storage/toolbox/mechanical(src)
my_yellow_toolbox = new /obj/item/storage/toolbox/electrical(src)
@@ -427,9 +304,9 @@
get_storage_contents_list()
update_icon()
/obj/structure/engineeringcart/full
/obj/structure/cart/storage/engineeringcart/full
/obj/structure/engineeringcart/full/Initialize()
/obj/structure/cart/storage/engineeringcart/full/Initialize()
. = ..()
my_lightreplacer = new /obj/item/device/lightreplacer(src)
my_blue_toolbox = new /obj/item/storage/toolbox/mechanical(src)
@@ -1,14 +1,8 @@
/obj/structure/janitorialcart
/obj/structure/cart/storage/janitorialcart
name = "custodial cart"
desc = "The ultimate in custodial carts. Has space for water, mops, signs, trash bags, and more."
icon = 'icons/obj/janitor.dmi'
icon_state = "cart"
anchored = FALSE
density = TRUE
climbable = TRUE
atom_flags = ATOM_FLAG_OPEN_CONTAINER
build_amt = 15
slowdown = 0
var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
var/obj/item/storage/bag/trash/mybag = null
@@ -17,22 +11,15 @@
var/obj/item/device/lightreplacer/myreplacer = null
var/obj/structure/mopbucket/mybucket = null
var/signs = 0 //maximum capacity hardcoded below
var/has_items = FALSE //This is set true whenever the cart has anything loaded/mounted on it
var/driving
var/mob/living/pulling
/obj/structure/janitorialcart/mechanics_hints(mob/user, distance, is_adjacent)
/obj/structure/cart/storage/janitorialcart/mechanics_hints(mob/user, distance, is_adjacent)
. += ..()
. += "Click and drag a mop bucket onto the cart to mount it."
. += "ALT-Click with a mop to put it away; a normal click will wet it in the bucket."
. += "ALT-Click with a container, such as a bucket, to pour its contents into the mounted bucket. A normal click will toss it into the trash."
. += "You can use a light replacer, spraybottle (of space cleaner) and four wet-floor signs on the cart to store them."
/obj/structure/janitorialcart/disassembly_hints(mob/user, distance, is_adjacent)
. += ..()
. += "An empty custodial cart can be taken apart with a <b>wrench</b> or a <b>welder</b>. Or a <b>plasma cutter</b>, if you're that hardcore."
/obj/structure/janitorialcart/feedback_hints(mob/user, distance, is_adjacent)
/obj/structure/cart/storage/janitorialcart/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
if(distance <= 1)
if (mybucket)
@@ -44,7 +31,7 @@
// Regular Variant
// No trashbag and no light replacer, this is inside the custodian's locker.
/obj/structure/janitorialcart/Initialize()
/obj/structure/cart/storage/janitorialcart/Initialize()
. = ..()
mymop = new /obj/item/mop(src)
myspray = new /obj/item/reagent_containers/spray/cleaner(src)
@@ -58,7 +45,7 @@
// Full Variant
// Has everything.
/obj/structure/janitorialcart/full/Initialize()
/obj/structure/cart/storage/janitorialcart/full/Initialize()
. = ..()
mybag = new /obj/item/storage/bag/trash(src)
mymop = new /obj/item/mop(src)
@@ -74,7 +61,7 @@
// Full with Water Variant
// Has everything as well as water in the mop bucket.
/obj/structure/janitorialcart/full/water/Initialize()
/obj/structure/cart/storage/janitorialcart/full/water/Initialize()
. = ..()
mybag = new /obj/item/storage/bag/trash(src)
mymop = new /obj/item/mop(src)
@@ -89,12 +76,12 @@
update_icon()
/obj/structure/janitorialcart/New()
/obj/structure/cart/storage/janitorialcart/New()
..()
if(is_station_turf(get_turf(src)))
GLOB.janitorial_supplies |= src
/obj/structure/janitorialcart/Destroy()
/obj/structure/cart/storage/janitorialcart/Destroy()
if(src in GLOB.janitorial_supplies)
GLOB.janitorial_supplies -= src
QDEL_NULL(mybag)
@@ -104,10 +91,10 @@
QDEL_NULL(mybucket)
return ..()
/obj/structure/janitorialcart/proc/get_short_status()
/obj/structure/cart/storage/janitorialcart/proc/get_short_status()
return "Contents: [english_list(contents)]"
/obj/structure/janitorialcart/mouse_drop_receive(atom/dropped, mob/user, params)
/obj/structure/cart/storage/janitorialcart/mouse_drop_receive(atom/dropped, mob/user, params)
var/atom/movable/O = dropped
if (istype(O, /obj/structure/mopbucket) && !mybucket)
O.forceMove(src)
@@ -120,7 +107,7 @@
//New Altclick functionality!
//Altclick the cart with a mop to stow the mop away
//Altclick the cart with a reagent container to pour things into the bucket without putting the bottle in trash
/obj/structure/janitorialcart/AltClick()
/obj/structure/cart/storage/janitorialcart/AltClick()
if(!usr || usr.stat || usr.lying || usr.restrained() || !Adjacent(usr)) return
var/obj/I = usr.get_active_hand()
if(istype(I, /obj/item/mop))
@@ -141,7 +128,7 @@
if (LR.store_broken)
return mybag.attackby(I, usr)
/obj/structure/janitorialcart/attackby(obj/item/attacking_item, mob/user)
/obj/structure/cart/storage/janitorialcart/attackby(obj/item/attacking_item, mob/user)
if(istype(attacking_item, /obj/item/mop) || istype(attacking_item, /obj/item/reagent_containers/glass/rag) || istype(attacking_item, /obj/item/soap))
if (mybucket)
if(attacking_item.reagents.total_volume < attacking_item.reagents.maximum_volume)
@@ -205,28 +192,8 @@
return
..()
/obj/structure/janitorialcart/proc/take_apart(var/mob/user = null, var/obj/I)
if(has_items)
spill()
if(user)
if(iswelder(I))
var/obj/item/welder = I
welder.play_tool_sound(get_turf(src), 50)
user.visible_message("<b>[user]</b> starts taking apart the [src]...", SPAN_NOTICE("You start disassembling the [src]..."))
if (!do_after(user, 30, do_flags = DO_DEFAULT & ~DO_USER_SAME_HAND))
return
dismantle()
/obj/structure/janitorialcart/ex_act(severity)
spill(100 / severity)
..()
//This is called if the cart is caught in an explosion, or destroyed by weapon fire
/obj/structure/janitorialcart/proc/spill(var/chance = 100)
/obj/structure/cart/storage/janitorialcart/spill(var/chance = 100)
var/turf/dropspot = get_turf(src)
if (mymop && prob(chance))
mymop.forceMove(dropspot)
@@ -267,11 +234,11 @@
update_icon()
/obj/structure/janitorialcart/attack_hand(mob/user)
/obj/structure/cart/storage/janitorialcart/attack_hand(mob/user)
ui_interact(user)
return
/obj/structure/janitorialcart/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/structure/cart/storage/janitorialcart/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
data["name"] = capitalize(name)
data["bag"] = mybag ? capitalize(mybag.name) : null
@@ -287,7 +254,7 @@
ui.set_initial_data(data)
ui.open()
/obj/structure/janitorialcart/Topic(href, href_list)
/obj/structure/cart/storage/janitorialcart/Topic(href, href_list)
if(!in_range(src, usr))
return
if(!isliving(usr))
@@ -335,7 +302,7 @@
update_icon()
updateUsrDialog()
/obj/structure/janitorialcart/update_icon()
/obj/structure/cart/storage/janitorialcart/update_icon()
ClearOverlays()
has_items = 0
if(mybucket)
@@ -361,83 +328,3 @@
if(signs)
AddOverlays("cart_sign[signs]")
has_items = 1
//Shamelessly copied from wheelchair code
/obj/structure/janitorialcart/relaymove(mob/living/user, direction)
. = ..()
if(user.stat || user.stunned || user.weakened || user.paralysis || user.lying || user.restrained())
if(user==pulling)
pulling = null
user.pulledby = null
to_chat(user, SPAN_WARNING("You lost your grip!"))
return
if(user.pulling && (user == pulling))
pulling = null
user.pulledby = null
return
if(pulling && (get_dist(src, pulling) > 1))
pulling = null
user.pulledby = null
if(user==pulling)
return
if(pulling && (get_dir(src.loc, pulling.loc) == direction))
to_chat(user, SPAN_WARNING("You cannot go there."))
return
driving = 1
var/turf/T = null
if(pulling)
T = pulling.loc
if(get_dist(src, pulling) >= 1)
step(pulling, get_dir(pulling.loc, src.loc))
step(src, direction)
set_dir(direction)
if(pulling)
if(pulling.loc == src.loc)
pulling.forceMove(T)
else
spawn(0)
if(get_dist(src, pulling) > 1)
pulling = null
user.pulledby = null
pulling.set_dir(get_dir(pulling, src))
driving = 0
/obj/structure/janitorialcart/Move()
. = ..()
if (pulling && (get_dist(src, pulling) > 1))
pulling.pulledby = null
to_chat(pulling, SPAN_WARNING("You lost your grip!"))
pulling = null
/obj/structure/janitorialcart/CtrlClick(var/mob/user)
if(in_range(src, user))
if(!ishuman(user)) return
if(!pulling)
pulling = user
user.pulledby = src
if(user.pulling)
user.stop_pulling()
user.set_dir(get_dir(user, src))
to_chat(user, "You grip \the [name]'s handles.")
else
to_chat(usr, "You let go of \the [name]'s handles.")
pulling.pulledby = null
pulling = null
return
/obj/structure/janitorialcart/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0))
return TRUE
if(mover?.movement_type & PHASING)
return TRUE
if(istype(mover) && mover.pass_flags & PASSTABLE)
return TRUE
if(istype(mover, /mob/living) && mover == pulling)
return TRUE
else
if(istype(mover, /obj/projectile))
return prob(30)
else
return !density
@@ -0,0 +1,123 @@
/obj/structure/cart/storage/parcelcart
name = "parcel cart"
desc = "A cart for moving parcels and packages around."
icon = 'icons/obj/parcelcart.dmi'
icon_state = "cart"
var/list/my_parcels = list()
/// Amount of parcels the cart is capable to store.
var/parcel_capacity = 17
var/static/list/allowed_types = typecacheof(list(
/obj/item/smallDelivery
))
/obj/structure/cart/storage/parcelcart/mechanics_hints(mob/user, distance, is_adjacent)
. += ..()
. += "You can use hand held parcels on the cart to store them."
. += "It slows down at 5 packages, and becomes even slower when there is 11 packages or more loaded."
/obj/structure/cart/storage/parcelcart/get_storage_contents_list()
storage_contents.Cut()
var/list/lists_to_check = list(
my_parcels
)
for(var/list/list_to_check in lists_to_check)
if(list_to_check?.len) //null check
storage_contents += list_to_check
var/list/non_sheet_objects = list(my_parcels)
for(var/obj/O in non_sheet_objects)
if(O)
storage_contents += O
/obj/structure/cart/storage/parcelcart/Destroy()
QDEL_NULL(my_parcels)
return ..()
/obj/structure/cart/storage/parcelcart/attackby(obj/item/attacking_item, mob/user)
if(is_type_in_typecache(attacking_item, allowed_types))
var/should_store = FALSE
var/storage_is_full = FALSE
if(my_parcels.len < parcel_capacity)
my_parcels += attacking_item
should_store = TRUE
else
storage_is_full = TRUE
handle_storing(attacking_item, user, should_store, storage_is_full)
return TRUE
else if (!has_items && (attacking_item.iswrench() || attacking_item.iswelder() || istype(attacking_item, /obj/item/gun/energy/plasmacutter)))
take_apart(user, attacking_item)
return
..()
/obj/structure/cart/storage/parcelcart/spill(var/chance = 100)
var/turf/dropspot = get_turf(src)
if(LAZYLEN(my_parcels) && prob(chance))
var/obj/item/smallDelivery/M
for(var/I in my_parcels)
M = I
M.forceMove(dropspot)
M.tumble(1)
my_parcels -= M
my_parcels.Cut()
update_icon()
/obj/structure/cart/storage/parcelcart/handle_storing(var/attacking_item, var/mob/user, var/should_store, var/storage_is_full)
if(should_store)
user.drop_from_inventory(attacking_item, src)
get_storage_contents_list()
update_slowdown()
update_icon()
to_chat(user, SPAN_NOTICE("You put [attacking_item] into [src]."))
else if(storage_is_full)
to_chat(user, SPAN_WARNING("There isn't any space to store [attacking_item] in [src]!"))
else
to_chat(user, SPAN_WARNING("You can't store this here!"))
/obj/structure/cart/storage/parcelcart/update_slowdown()
if(my_parcels.len <= 4)
slowdown = 0
else if(my_parcels.len > 4 && my_parcels.len < 11)
slowdown = 1
else if(my_parcels.len >= 11)
slowdown = 2
/obj/structure/cart/storage/parcelcart/attack_hand(mob/user)
if(!isliving(user))
return
if(LAZYLEN(storage_contents))
for(var/obj/O in storage_contents)
storage_contents[O] = image(O.icon, O.icon_state)
var/obj/item/chosen_item = show_radial_menu(user, src, storage_contents, require_near = TRUE, tooltips = TRUE)
if(isnull(chosen_item))
return
if(chosen_item in storage_contents)
switch(chosen_item.type)
if(/obj/item/smallDelivery)
if(my_parcels.len)
user.put_in_hands(chosen_item)
to_chat(user, SPAN_NOTICE("You take [my_parcels[chosen_item]] from [src]."))
my_parcels -= chosen_item
get_storage_contents_list()
update_slowdown()
update_icon()
else
to_chat(user, SPAN_WARNING("\The [chosen_item] is not in the cart anymore!"))
/obj/structure/cart/storage/parcelcart/update_icon()
ClearOverlays()
has_items = FALSE
if(my_parcels.len)
var/amount_to_show = min(length(my_parcels), parcel_capacity)
AddOverlays("pack_[amount_to_show]")
has_items = TRUE
+2 -2
View File
@@ -44,8 +44,8 @@
/obj/structure/mopbucket/on_reagent_change()
. = ..()
if(istype(loc,/obj/structure/janitorialcart))
var/obj/structure/janitorialcart/cart = loc
if(istype(loc,/obj/structure/cart/storage/janitorialcart))
var/obj/structure/cart/storage/janitorialcart/cart = loc
cart.update_icon()
else
update_icon()