Janicart NanoUI replacement, misc code improvement (#21522)

This PR updates Janitorial Carts to use radial menus for inventory
management (just like Engineering and Parcel carts). It also expands
mechanics hints and includes some general cleanup.

Removes a NanoUI template for the [TGUI
update](https://github.com/Aurorastation/Aurora.3/pull/21046).
This commit is contained in:
Batrachophreno
2025-12-19 20:21:11 +00:00
committed by GitHub
parent 55045bc606
commit 8ebc0b5213
7 changed files with 326 additions and 326 deletions
+11 -14
View File
@@ -15,19 +15,17 @@ ABSTRACT_TYPE(/obj/structure/cart)
/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. \
"
. += "<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."
. += "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. If it contains anything when disassembled, these contents will spill onto the floor."
/obj/structure/cart/proc/take_apart(var/mob/user = null, var/obj/I)
/obj/structure/cart/proc/take_apart(var/mob/user = null, var/obj/object)
if(user)
if(iswelder(I))
var/obj/item/welder = I
if(iswelder(object))
var/obj/item/welder = object
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]..."))
@@ -64,19 +62,19 @@ ABSTRACT_TYPE(/obj/structure/cart)
return
if(pulling && (get_dir(src.loc, pulling.loc) == direction))
to_chat(user, SPAN_WARNING("You cannot go there."))
return
// return
driving = 1
var/turf/T = null
var/turf/turf = null
if(pulling)
T = pulling.loc
turf = 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)
pulling.forceMove(turf)
else
spawn(0)
if(get_dist(src, pulling) > 1)
@@ -85,7 +83,6 @@ ABSTRACT_TYPE(/obj/structure/cart)
pulling.set_dir(get_dir(pulling, src))
driving = 0
/obj/structure/cart/Move()
. = ..()
if (pulling && (get_dist(src, pulling) > 1))
@@ -136,7 +133,7 @@ ABSTRACT_TYPE(/obj/structure/cart/storage)
/obj/structure/cart/storage/proc/get_storage_contents_list()
/obj/structure/cart/storage/take_apart(var/mob/user = null, var/obj/I)
/obj/structure/cart/storage/take_apart(var/mob/user = null, var/obj/object)
if(has_items)
spill()
. = ..()
+42 -49
View File
@@ -11,7 +11,7 @@
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
/// Amount of stacks the cart is capable to store.
/// Amount of stacks the cart is capable of storing.
var/stack_capacity = 2
var/static/list/allowed_types = typecacheof(list(
@@ -27,6 +27,7 @@
/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."
. += "The cart can contain up to [stack_capacity] stacks of each type of sheet."
/obj/structure/cart/storage/engineeringcart/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
@@ -35,24 +36,24 @@
var/metal_amount
var/plasteel_amount
var/glass_amount
var/obj/item/stack/material/steel/S
var/obj/item/stack/material/plasteel/P
var/obj/item/stack/material/glass/G
var/obj/item/stack/material/steel/stored_steel
var/obj/item/stack/material/plasteel/stored_plasteel
var/obj/item/stack/material/glass/stored_glass
if(LAZYLEN(my_metal))
for(var/I in my_metal) // we already handle the type-check in `atttackby()` so it's safe to assume the lists contain what they're intended to
S = I
metal_amount += S.amount
. += "[icon2html(S, user)] This cart contains <b>[metal_amount] sheet\s</b> of steel!"
for(var/metal in my_metal) // we already handle the type-check in `atttackby()` so it's safe to assume the lists contain what they're intended to
stored_steel = metal
metal_amount += stored_steel.amount
. += "[icon2html(stored_steel, user)] This cart contains <b>[metal_amount] sheet\s</b> of steel!"
if(LAZYLEN(my_plasteel))
for(var/I in my_plasteel)
P = I
plasteel_amount += P.amount
. += "[icon2html(P, user)] This cart contains <b>[plasteel_amount] sheet\s</b> of plasteel!"
for(var/metal in my_plasteel)
stored_plasteel = metal
plasteel_amount += stored_plasteel.amount
. += "[icon2html(stored_plasteel, user)] This cart contains <b>[plasteel_amount] sheet\s</b> of plasteel!"
if(LAZYLEN(my_glass))
for(var/I in my_glass)
G = I
glass_amount += G.amount
. += "[icon2html(G, user)] This cart contains <b>[glass_amount] sheet\s</b> of glass!"
for(var/metal in my_glass)
stored_glass = metal
glass_amount += stored_glass.amount
. += "[icon2html(stored_glass, user)] This cart contains <b>[glass_amount] sheet\s</b> of glass!"
else
. += "[icon2html(src, user)] There is no material in this cart!"
@@ -67,9 +68,11 @@
var/list/non_sheet_objects = list(my_lightreplacer, my_blue_toolbox, my_yellow_toolbox, my_red_toolbox)
for(var/obj/O in non_sheet_objects)
if(O)
storage_contents += O
for(var/obj/non_sheet_object in non_sheet_objects)
if(non_sheet_object)
storage_contents += non_sheet_object
update_icon()
/obj/structure/cart/storage/engineeringcart/Destroy()
QDEL_NULL(my_glass)
@@ -108,9 +111,6 @@
else
storage_is_full = TRUE
handle_storing(attacking_item, user, should_store, storage_is_full)
return TRUE
if(istype(attacking_item, /obj/item/storage/toolbox)) //---- toolboxes
switch(attacking_item.type)
if(/obj/item/storage/toolbox/mechanical)
@@ -134,9 +134,6 @@
else
storage_is_full = TRUE
handle_storing(attacking_item, user, should_store, storage_is_full)
return TRUE
if(istype(attacking_item, /obj/item/device/lightreplacer)) //---- light replacer
if(!my_lightreplacer)
my_lightreplacer = attacking_item
@@ -144,10 +141,10 @@
else
storage_is_full = TRUE
handle_storing(attacking_item, user, should_store, storage_is_full)
return 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)))
else if(!has_items && (attacking_item.iswrench() || attacking_item.iswelder() || istype(attacking_item, /obj/item/gun/energy/plasmacutter)))
take_apart(user, attacking_item)
return
..()
@@ -155,30 +152,30 @@
/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
var/obj/item/stack/material/glass/stored_glass
for(var/I in my_glass)
G = I
G.forceMove(dropspot)
G.tumble(1)
my_glass -= G
stored_glass = I
stored_glass.forceMove(dropspot)
stored_glass.tumble(1)
my_glass -= stored_glass
my_glass.Cut()
if(LAZYLEN(my_metal) && prob(chance))
var/obj/item/stack/material/glass/M
var/obj/item/stack/material/steel/stored_steel
for(var/I in my_metal)
M = I
M.forceMove(dropspot)
M.tumble(1)
my_metal -= M
stored_steel = I
stored_steel.forceMove(dropspot)
stored_steel.tumble(1)
my_metal -= stored_steel
my_metal.Cut()
if(LAZYLEN(my_plasteel) && prob(chance))
var/obj/item/stack/material/glass/P
var/obj/item/stack/material/plasteel/stored_plasteel
for(var/I in my_plasteel)
P = I
P.forceMove(dropspot)
P.tumble(1)
my_plasteel -= P
stored_plasteel = I
stored_plasteel.forceMove(dropspot)
stored_plasteel.tumble(1)
my_plasteel -= stored_plasteel
my_plasteel.Cut()
if(my_lightreplacer && prob(chance))
@@ -207,7 +204,6 @@
if(should_store)
user.drop_from_inventory(attacking_item, src)
get_storage_contents_list()
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]!"))
@@ -219,8 +215,8 @@
return
if(LAZYLEN(storage_contents))
for(var/obj/O in storage_contents)
storage_contents[O] = image(O.icon, O.icon_state)
for(var/obj/object in storage_contents)
storage_contents[object] = image(object.icon, object.icon_state)
var/obj/item/chosen_item = show_radial_menu(user, src, storage_contents, require_near = TRUE, tooltips = TRUE)
@@ -265,7 +261,6 @@
my_red_toolbox = null
get_storage_contents_list()
update_icon()
else
to_chat(user, SPAN_WARNING("\The [chosen_item] is not in the cart anymore!"))
@@ -302,7 +297,6 @@
my_yellow_toolbox = new /obj/item/storage/toolbox/electrical(src)
my_red_toolbox = new /obj/item/storage/toolbox/emergency(src)
get_storage_contents_list()
update_icon()
/obj/structure/cart/storage/engineeringcart/full
@@ -319,4 +313,3 @@
my_plasteel += new /obj/item/stack/material/plasteel/full(src)
my_plasteel += new /obj/item/stack/material/plasteel/full(src)
get_storage_contents_list()
update_icon()
+238 -212
View File
@@ -4,26 +4,37 @@
icon = 'icons/obj/janitor.dmi'
icon_state = "cart"
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
var/obj/item/mop/mymop = null
var/obj/item/reagent_containers/spray/myspray = null
var/obj/item/device/lightreplacer/myreplacer = null
var/obj/structure/mopbucket/mybucket = null
var/signs = 0 //maximum capacity hardcoded below
var/obj/item/storage/bag/trash/my_bag = null
var/obj/item/mop/my_mop = null
var/obj/item/reagent_containers/spray/my_spray = null
var/obj/item/device/lightreplacer/my_lightreplacer = null
var/obj/structure/mopbucket/my_bucket = null
var/signs = 0
var/max_signs = 4
var/static/list/allowed_types = typecacheof(list(
/obj/item/storage/bag/trash,
/obj/item/mop,
/obj/item/reagent_containers/spray,
/obj/item/device/lightreplacer,
/obj/item/clothing/suit/caution
))
/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."
. += "Click and drag a mop bucket (the square kind, not a standard bucket) onto the cart to mount it."
. += "You can use a light replacer, spray bottle, trash bag, and up to [max_signs] wet-floor signs on the cart to store them."
. += "Click the cart with a mop, rag, or soap to wet them from the bucket."
. += "When a trash bag is attached, you can click on the cart with an item to throw it in the trash."
. += "ALT-Click the cart with a mop to store it on the cart."
. += "ALT-Click the cart with a reagent container (such as a bucket, glass, etc.) to pour its contents into the mounted bucket. A normal click will toss it into the trash bag (if able)."
. += "ALT-click the cart with an advanced light replacer to dump any broken lights in the trash."
/obj/structure/cart/storage/janitorialcart/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
if(distance <= 1)
if (mybucket)
var/contains = mybucket.reagents.total_volume
if(my_bucket)
var/contains = my_bucket.reagents.total_volume
. += "[icon2html(src, user)] The bucket contains <b>[contains] unit\s</b> of liquid!"
else
. += "[icon2html(src, user)] There is no bucket mounted on it!"
@@ -33,31 +44,26 @@
// No trashbag and no light replacer, this is inside the custodian's locker.
/obj/structure/cart/storage/janitorialcart/Initialize()
. = ..()
mybucket = new /obj/structure/mopbucket(src)
update_icon()
my_bucket = new /obj/structure/mopbucket(src)
get_storage_contents_list()
// Full Variant
// Has everything.
/obj/structure/cart/storage/janitorialcart/full/Initialize()
. = ..()
mybag = new /obj/item/storage/bag/trash(src)
mymop = new /obj/item/mop(src)
myspray = new /obj/item/reagent_containers/spray/cleaner(src)
myreplacer = new /obj/item/device/lightreplacer(src)
my_bag = new /obj/item/storage/bag/trash(src)
my_mop = new /obj/item/mop(src)
my_spray = new /obj/item/reagent_containers/spray/cleaner(src)
my_lightreplacer = new /obj/item/device/lightreplacer(src)
mybucket = new /obj/structure/mopbucket(src)
for(signs, signs < 4, signs++)
for(signs, signs < max_signs, signs++)
new /obj/item/clothing/suit/caution(src)
update_icon()
// Full with Water Variant
// Has everything as well as water in the mop bucket.
/obj/structure/cart/storage/janitorialcart/full/water/Initialize()
. = ..()
mybucket.reagents.add_reagent(/singleton/reagent/water, mybucket.bucketsize)
update_icon()
my_bucket.reagents.add_reagent(/singleton/reagent/water, my_bucket.bucketsize)
/obj/structure/cart/storage/janitorialcart/New()
..()
@@ -67,60 +73,94 @@
/obj/structure/cart/storage/janitorialcart/Destroy()
if(src in GLOB.janitorial_supplies)
GLOB.janitorial_supplies -= src
QDEL_NULL(mybag)
QDEL_NULL(mymop)
QDEL_NULL(myspray)
QDEL_NULL(myreplacer)
QDEL_NULL(mybucket)
QDEL_NULL(my_bag)
QDEL_NULL(my_mop)
QDEL_NULL(my_spray)
QDEL_NULL(my_lightreplacer)
QDEL_NULL(my_bucket)
return ..()
/obj/structure/cart/storage/janitorialcart/proc/get_short_status()
return "Contents: [english_list(contents)]"
/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)
mybucket = O
to_chat(user, "You mount the [O] on the janicart.")
update_icon()
var/atom/movable/mopbucket = dropped
if(istype(mopbucket, /obj/structure/mopbucket) && !my_bucket && do_after(user, 20))
mopbucket.forceMove(src)
my_bucket = mopbucket
to_chat(user, "You mount the [mopbucket] on the janicart.")
get_storage_contents_list()
else
..()
/obj/structure/cart/storage/janitorialcart/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()
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/janitorialcart/get_storage_contents_list()
storage_contents.Cut()
var/list/objects = list(my_bag, my_mop, my_spray, my_lightreplacer, my_bucket)
for(var/obj/object in objects)
if(object)
storage_contents += object
to_chat(world, "checking for signs")
for(var/obj/item/clothing/suit/caution/wetfloorsign in src)
to_chat(world, "found a sign")
if(wetfloorsign)
storage_contents += wetfloorsign
update_icon()
//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/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))
if(!mymop)
usr.drop_from_inventory(I,src)
mymop = I
update_icon()
updateUsrDialog()
to_chat(usr, SPAN_NOTICE("You put [I] into [src]."))
var/mob/user = usr
if(!user || !istype(user) || user.stat || user.lying || user.restrained() || !Adjacent(user)) return
var/obj/held_item = user.get_active_hand()
var/should_store = FALSE
var/storage_is_full = FALSE
/// If it's a mop, try to store it.
if(istype(held_item, /obj/item/mop))
if(!my_mop)
my_mop = held_item
should_store = TRUE
else
to_chat(usr, SPAN_NOTICE("The cart already has a mop attached"))
return
else if(istype(I, /obj/item/reagent_containers) && mybucket)
var/obj/item/reagent_containers/C = I
C.afterattack(mybucket, usr, 1)
else if(istype (I, /obj/item/device/lightreplacer))
var/obj/item/device/lightreplacer/LR = I
if (LR.store_broken)
return mybag.attackby(I, usr)
storage_is_full = TRUE
handle_storing(held_item, user, should_store, storage_is_full)
return TRUE
/// If its a reagent container, try to dump it in the bucket.
else if(istype(held_item, /obj/item/reagent_containers) && my_bucket)
var/obj/item/reagent_containers/held_container = held_item
held_container.afterattack(my_bucket, user, 1)
/// If its an advanced light replacer, try to dump the broken lights in the trash.
else if(istype(held_item, /obj/item/device/lightreplacer))
var/obj/item/device/lightreplacer/held_lightreplacer = held_item
if(held_lightreplacer.store_broken)
return my_bag.attackby(held_item, 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(my_bucket)
if(attacking_item.reagents.total_volume < attacking_item.reagents.maximum_volume)
if(mybucket.reagents.total_volume < 1)
to_chat(user, SPAN_NOTICE("[mybucket] is empty!"))
if(my_bucket.reagents.total_volume < 1)
to_chat(user, SPAN_NOTICE("[my_bucket] is empty!"))
update_icon()
else
mybucket.reagents.trans_to_obj(attacking_item, 5) //
to_chat(user, SPAN_NOTICE("You wet [attacking_item] in [mybucket]."))
my_bucket.reagents.trans_to_obj(attacking_item, 5) //
to_chat(user, SPAN_NOTICE("You wet [attacking_item] in [my_bucket]."))
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
update_icon()
else
@@ -129,185 +169,171 @@
to_chat(user, SPAN_NOTICE("There is no bucket mounted here to dip [attacking_item] into!"))
return 1
else if(istype(attacking_item, /obj/item/reagent_containers/spray) && !myspray)
user.drop_from_inventory(attacking_item, src)
myspray = attacking_item
update_icon()
updateUsrDialog()
to_chat(user, SPAN_NOTICE("You put [attacking_item] into [src]."))
return 1
if(is_type_in_typecache(attacking_item, allowed_types))
var/should_store = FALSE
var/storage_is_full = FALSE
else if(istype(attacking_item, /obj/item/device/lightreplacer) && !myreplacer)
user.drop_from_inventory(attacking_item, src)
myreplacer = attacking_item
update_icon()
updateUsrDialog()
to_chat(user, SPAN_NOTICE("You put [attacking_item] into [src]."))
return 1
if(istype(attacking_item, /obj/item/device/lightreplacer)) //---- light replacer
if(!my_lightreplacer)
my_lightreplacer = attacking_item
should_store = TRUE
else
storage_is_full = TRUE
else if(istype(attacking_item, /obj/item/storage/bag/trash) && !mybag)
user.drop_from_inventory(attacking_item, src)
mybag = attacking_item
attacking_item.forceMove(src)
update_icon()
updateUsrDialog()
to_chat(user, SPAN_NOTICE("You put [attacking_item] into [src]."))
return 1
else if(istype(attacking_item, /obj/item/storage/bag/trash)) //---- trash bag
if(!my_bag)
my_bag = attacking_item
should_store = TRUE
else
storage_is_full = TRUE
else if(istype(attacking_item, /obj/item/clothing/suit/caution))
if(signs < 4)
user.drop_from_inventory(attacking_item, src)
signs++
update_icon()
updateUsrDialog()
to_chat(user, SPAN_NOTICE("You put [attacking_item] into [src]."))
else
to_chat(user, SPAN_NOTICE("[src] can't hold any more signs."))
return 1
else if(istype(attacking_item, /obj/item/reagent_containers/spray)) //---- spray
if(!my_spray)
my_spray = attacking_item
should_store = TRUE
else
storage_is_full = TRUE
else if(mybag)
return mybag.attackby(attacking_item, user)
//This return will prevent afterattack from executing if the object goes into the trashbag,
//This prevents dumb stuff like splashing the cart with the contents of a container, after putting said container into trash
else if(istype(attacking_item, /obj/item/clothing/suit/caution)) //---- sign(s)
if(signs < max_signs)
should_store = TRUE
signs++
else
storage_is_full = TRUE
else if (!has_items && (attacking_item.iswrench() || attacking_item.iswelder() || istype(attacking_item, /obj/item/gun/energy/plasmacutter)))
handle_storing(attacking_item, user, should_store, storage_is_full)
return
else if(my_bag)
// This return will prevent afterattack from executing if the object goes into the trashbag,
// This prevents dumb stuff like splashing the cart with the contents of a container, after putting said container into trash.
return my_bag.attackby(attacking_item, user)
else if(!has_items && (attacking_item.iswrench() || attacking_item.iswelder() || istype(attacking_item, /obj/item/gun/energy/plasmacutter)))
take_apart(user, attacking_item)
return
..()
//This is called if the cart is caught in an explosion, or destroyed by weapon fire
/obj/structure/cart/storage/janitorialcart/spill(var/chance = 100)
var/turf/dropspot = get_turf(src)
if (mymop && prob(chance))
mymop.forceMove(dropspot)
mymop.tumble(2)
mymop = null
if (myspray && prob(chance))
myspray.forceMove(dropspot)
myspray.tumble(3)
myspray = null
if (myreplacer && prob(chance))
myreplacer.forceMove(dropspot)
myreplacer.tumble(3)
myreplacer = null
if (mybucket && prob(chance*0.5))//bucket is heavier, harder to knock off
mybucket.forceMove(dropspot)
mybucket.tumble(1)
mybucket = null
if (signs)
for (var/obj/item/clothing/suit/caution/Sign in src)
if (prob(min((chance*2),100)))
signs--
Sign.forceMove(dropspot)
Sign.tumble(3)
if (signs < 0)//safety for something that shouldn't happen
signs = 0
update_icon()
return
if (mybag && prob(min((chance*2),100)))//Bag is flimsy
mybag.forceMove(dropspot)
mybag.tumble(1)
mybag.spill()//trashbag spills its contents too
mybag = null
update_icon()
/obj/structure/cart/storage/janitorialcart/attack_hand(mob/user)
ui_interact(user)
return
/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
data["bucket"] = mybucket ? capitalize(mybucket.name) : null
data["mop"] = mymop ? capitalize(mymop.name) : null
data["spray"] = myspray ? capitalize(myspray.name) : null
data["replacer"] = myreplacer ? capitalize(myreplacer.name) : null
data["signs"] = signs ? "[signs] sign\s" : null
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "janitorcart.tmpl", "Janitorial cart", 240, 160)
ui.set_initial_data(data)
ui.open()
/obj/structure/cart/storage/janitorialcart/Topic(href, href_list)
if(!in_range(src, usr))
if(!isliving(user))
return
if(!isliving(usr))
return
var/mob/living/user = usr
if(href_list["take"])
switch(href_list["take"])
if("garbage")
if(mybag)
user.put_in_hands(mybag)
to_chat(user, SPAN_NOTICE("You take [mybag] from [src]."))
mybag = null
if("mop")
if(mymop)
user.put_in_hands(mymop)
to_chat(user, SPAN_NOTICE("You take [mymop] from [src]."))
mymop = null
if("spray")
if(myspray)
user.put_in_hands(myspray)
to_chat(user, SPAN_NOTICE("You take [myspray] from [src]."))
myspray = null
if("replacer")
if(myreplacer)
user.put_in_hands(myreplacer)
to_chat(user, SPAN_NOTICE("You take [myreplacer] from [src]."))
myreplacer = null
if("sign")
if(LAZYLEN(storage_contents))
for(var/obj/object in storage_contents)
storage_contents[object] = image(object.icon, object.icon_state)
var/obj/item/chosen_item = show_radial_menu(user, src, storage_contents, require_near = TRUE, tooltips = TRUE)
if(isnull(chosen_item))
to_chat(world, "is_null")
return
if(chosen_item in storage_contents)
to_chat(world, "chose item [chosen_item], is type [chosen_item.type]")
if(istype(chosen_item, /obj/item/storage/bag/trash) && my_bag)
user.put_in_hands(my_bag)
to_chat(user, SPAN_NOTICE("You take [my_bag] from [src]."))
my_bag = null
if(istype(chosen_item, /obj/item/mop) && my_mop)
user.put_in_hands(my_mop)
to_chat(user, SPAN_NOTICE("You take [my_mop] from [src]."))
my_mop = null
if(istype(chosen_item, /obj/item/reagent_containers/spray) && my_spray)
to_chat(world, "/obj/item/reagent_containers/spray/cleaner")
to_chat(world, "my_spray")
user.put_in_hands(my_spray)
to_chat(user, SPAN_NOTICE("You take [my_spray] from [src]."))
my_spray = null
if(istype(chosen_item, /obj/item/device/lightreplacer) && my_lightreplacer)
user.put_in_hands(my_lightreplacer)
to_chat(user, SPAN_NOTICE("You take [my_lightreplacer] from [src]."))
my_lightreplacer = null
if(istype(chosen_item, /obj/structure/mopbucket) && my_bucket)
my_bucket.forceMove(get_turf(user))
to_chat(user, SPAN_NOTICE("You unmount [my_bucket] from [src]."))
my_bucket.update_icon()
my_bucket = null
if(istype(chosen_item, /obj/item/clothing/suit/caution))
if(signs)
var/obj/item/clothing/suit/caution/Sign = locate() in src
if(Sign)
user.put_in_hands(Sign)
to_chat(user, SPAN_NOTICE("You take \a [Sign] from [src]."))
var/obj/item/clothing/suit/caution/wetfloorsign = locate() in src
if(wetfloorsign)
user.put_in_hands(wetfloorsign)
to_chat(user, SPAN_NOTICE("You take \a [wetfloorsign] from [src]."))
signs--
else
warning("[src] signs ([signs]) didn't match contents")
signs = 0
if("bucket")
if(mybucket)
mybucket.forceMove(get_turf(user))
to_chat(user, SPAN_NOTICE("You unmount [mybucket] from [src]."))
mybucket.update_icon()
mybucket = null
get_storage_contents_list()
else
to_chat(user, SPAN_WARNING("\The [chosen_item] is not in the cart anymore!"))
//This is called if the cart is caught in an explosion, or destroyed by weapon fire
/obj/structure/cart/storage/janitorialcart/spill(var/chance = 100)
var/turf/dropspot = get_turf(src)
if(my_mop && prob(chance))
my_mop.forceMove(dropspot)
my_mop.tumble(2)
my_mop = null
if(my_spray && prob(chance))
my_spray.forceMove(dropspot)
my_spray.tumble(3)
my_spray = null
if(my_lightreplacer && prob(chance))
my_lightreplacer.forceMove(dropspot)
my_lightreplacer.tumble(3)
my_lightreplacer = null
if(my_bucket && prob(chance*0.5))//bucket is heavier, harder to knock off
my_bucket.forceMove(dropspot)
my_bucket.tumble(1)
my_bucket = null
if(signs)
for (var/obj/item/clothing/suit/caution/Sign in src)
if(prob(min((chance*2),100)))
signs--
Sign.forceMove(dropspot)
Sign.tumble(3)
if(signs < 0)//safety for something that shouldn't happen
signs = 0
update_icon()
return
if(my_bag && prob(min((chance*2),100)))//Bag is flimsy
my_bag.forceMove(dropspot)
my_bag.tumble(1)
my_bag.spill()//trashbag spills its contents too
my_bag = null
update_icon()
updateUsrDialog()
/obj/structure/cart/storage/janitorialcart/update_icon()
ClearOverlays()
has_items = 0
if(mybucket)
has_items = FALSE
if(my_bucket)
AddOverlays("cart_bucket")
has_items = 1
if(mybucket.reagents.total_volume > 0)
has_items = TRUE
if(my_bucket.reagents.total_volume > 0)
AddOverlays("cart_water")
if(mybag)
if(my_bag)
AddOverlays("cart_garbage")
has_items = 1
if(mymop)
has_items = TRUE
if(my_mop)
AddOverlays("cart_mop")
has_items = 1
if(myspray)
has_items = TRUE
if(my_spray)
AddOverlays("cart_spray")
has_items = 1
if(myreplacer)
if (istype(myreplacer, /obj/item/device/lightreplacer/advanced))
AddOverlays("cart_adv_lightreplacer")
has_items = TRUE
if(my_lightreplacer)
if(istype(my_lightreplacer, /obj/item/device/lightreplacer/advanced))
AddOverlays("cart_adv_replacer")
else
AddOverlays("cart_replacer")
has_items = 1
has_items = TRUE
if(signs)
AddOverlays("cart_sign[signs]")
has_items = 1
has_items = TRUE
@@ -16,7 +16,7 @@
/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."
. += "It slows down at 5 packages, and slows down more when 11+ packages are loaded."
/obj/structure/cart/storage/parcelcart/get_storage_contents_list()
storage_contents.Cut()
@@ -29,9 +29,11 @@
var/list/non_sheet_objects = list(my_parcels)
for(var/obj/O in non_sheet_objects)
if(O)
storage_contents += O
for(var/obj/non_sheet_object in non_sheet_objects)
if(non_sheet_object)
storage_contents += non_sheet_object
update_icon()
/obj/structure/cart/storage/parcelcart/Destroy()
QDEL_NULL(my_parcels)
@@ -50,7 +52,7 @@
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)))
else if(!has_items && (attacking_item.iswrench() || attacking_item.iswelder() || istype(attacking_item, /obj/item/gun/energy/plasmacutter)))
take_apart(user, attacking_item)
return
..()
@@ -59,12 +61,12 @@
var/turf/dropspot = get_turf(src)
if(LAZYLEN(my_parcels) && prob(chance))
var/obj/item/smallDelivery/M
var/obj/item/smallDelivery/smallDelivery
for(var/I in my_parcels)
M = I
M.forceMove(dropspot)
M.tumble(1)
my_parcels -= M
smallDelivery = I
smallDelivery.forceMove(dropspot)
smallDelivery.tumble(1)
my_parcels -= smallDelivery
my_parcels.Cut()
update_icon()
@@ -73,7 +75,6 @@
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]!"))
@@ -93,8 +94,8 @@
return
if(LAZYLEN(storage_contents))
for(var/obj/O in storage_contents)
storage_contents[O] = image(O.icon, O.icon_state)
for(var/obj/object in storage_contents)
storage_contents[object] = image(object.icon, object.icon_state)
var/obj/item/chosen_item = show_radial_menu(user, src, storage_contents, require_near = TRUE, tooltips = TRUE)
@@ -105,12 +106,11 @@
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]."))
to_chat(user, SPAN_NOTICE("You take \the [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!"))