diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index d14a4ab29b..5fc789549a 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -729,3 +729,12 @@ /obj/item/weapon/storage/AllowDrop() return TRUE + +//Useful for spilling the contents of containers all over the floor +/obj/item/weapon/storage/proc/spill(var/dist = 2, var/turf/T = null) + if (!istype(T))//If its not on the floor this might cause issues + T = get_turf(src) + + for (var/obj/O in contents) + remove_from_storage(O, T) + O.tumble(2) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 1d58533771..3764ae6258 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -203,3 +203,14 @@ /obj/proc/container_resist(var/mob/living) return + +//To be called from things that spill objects on the floor. +//Makes an object move around randomly for a couple of tiles +/obj/proc/tumble(var/dist = 2) + set waitfor = FALSE + if (dist >= 1) + dist += rand(0,1) + for(var/i = 1, i <= dist, i++) + if(src) + step(src, pick(NORTH,SOUTH,EAST,WEST)) + sleep(rand(2,4)) diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index b7807711e3..e6e58954a4 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -7,95 +7,147 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) icon_state = "cart" anchored = 0 density = 1 - climbable = 1 flags = OPENCONTAINER + climbable = TRUE //copypaste sorry var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite var/obj/item/weapon/storage/bag/trash/mybag = null var/obj/item/weapon/mop/mymop = null var/obj/item/weapon/reagent_containers/spray/myspray = null var/obj/item/device/lightreplacer/myreplacer = null + var/obj/structure/mopbucket/mybucket = null + var/has_items = FALSE + var/dismantled = TRUE var/signs = 0 //maximum capacity hardcoded below -/obj/structure/janitorialcart/New() - create_reagents(300) - ..() +/obj/structure/janitorialcart/Destroy() + QDEL_NULL(mybag) + QDEL_NULL(mymop) + QDEL_NULL(myspray) + QDEL_NULL(myreplacer) + QDEL_NULL(mybucket) + return ..() /obj/structure/janitorialcart/examine(mob/user) - . = ..() - if(Adjacent(user)) - . += "It contains [reagents.total_volume] unit\s of liquid!" + if(..(user, 1)) + if (mybucket) + var/contains = mybucket.reagents.total_volume + to_chat(user, "\icon[src] The bucket contains [contains] unit\s of liquid!") + else + to_chat(user, "\icon[src] There is no bucket mounted on it!") + +/obj/structure/janitorialcart/MouseDrop_T(atom/movable/O as mob|obj, mob/living/user as mob) + if (istype(O, /obj/structure/mopbucket) && !mybucket) + O.forceMove(src) + mybucket = O + to_chat(user, "You mount the [O] on the janicart.") + update_icon() + else + ..() /obj/structure/janitorialcart/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/storage/bag/trash) && !mybag) - user.drop_item() - mybag = I - I.loc = src - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") - - else if(istype(I, /obj/item/weapon/mop)) - if(I.reagents.total_volume < I.reagents.maximum_volume) //if it's not completely soaked we assume they want to wet it, otherwise store it - if(reagents.total_volume < 1) - to_chat(user, "[src] is out of water!") + if(istype(I, /obj/item/weapon/mop) || istype(I, /obj/item/weapon/reagent_containers/glass/rag) || istype(I, /obj/item/weapon/soap)) + if (mybucket) + if(I.reagents.total_volume < I.reagents.maximum_volume) + if(mybucket.reagents.total_volume < 1) + to_chat(user, "[mybucket] is empty!") + else + mybucket.reagents.trans_to_obj(I, 5) // + to_chat(user, "You wet [I] in [mybucket].") + playsound(loc, 'sound/effects/slosh.ogg', 25, 1) else - reagents.trans_to_obj(I, 5) // - to_chat(user, "You wet [I] in [src].") - playsound(loc, 'sound/effects/slosh.ogg', 25, 1) - return - if(!mymop) - user.drop_item() - mymop = I - I.loc = src - update_icon() - updateUsrDialog() - to_chat(user, "You put [I] into [src].") + to_chat(user, "[I] can't absorb anymore liquid!") + else + to_chat(user, "There is no bucket mounted here to dip [I] into!") + return 1 + + else if (istype(I, /obj/item/weapon/reagent_containers/glass/bucket) && mybucket) + I.afterattack(mybucket, usr, 1) + update_icon() + return 1 else if(istype(I, /obj/item/weapon/reagent_containers/spray) && !myspray) - user.drop_item() + user.unEquip(I, 0, src) myspray = I - I.loc = src update_icon() updateUsrDialog() to_chat(user, "You put [I] into [src].") + return 1 else if(istype(I, /obj/item/device/lightreplacer) && !myreplacer) - user.drop_item() + user.unEquip(I, 0, src) myreplacer = I - I.loc = src update_icon() updateUsrDialog() to_chat(user, "You put [I] into [src].") + return 1 + + else if(istype(I, /obj/item/weapon/storage/bag/trash) && !mybag) + user.unEquip(I, 0, src) + mybag = I + update_icon() + updateUsrDialog() + to_chat(user, "You put [I] into [src].") + return 1 else if(istype(I, /obj/item/weapon/caution)) if(signs < 4) - user.drop_item() - I.loc = src + user.unEquip(I, 0, src) signs++ update_icon() updateUsrDialog() to_chat(user, "You put [I] into [src].") else to_chat(user, "[src] can't hold any more signs.") - - else if(istype(I, /obj/item/weapon/reagent_containers/glass)) - return // So we do not put them in the trash bag as we mean to fill the mop bucket + return 1 else if(mybag) - mybag.attackby(I, user) + return mybag.attackby(I, 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 (!has_items) + if (I.is_wrench()) + if (do_after(user, 5 SECONDS, src)) + dismantle(user) + return + ..() + + +//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(mob/living/user) + if(user.incapacitated() || !Adjacent(user)) return + var/obj/I = usr.get_active_hand() + if(istype(I, /obj/item/weapon/mop)) + if(!mymop) + usr.drop_from_inventory(I,src) + mymop = I + update_icon() + updateUsrDialog() + to_chat(usr, "You put [I] into [src].") + update_icon() + else + to_chat(usr, "The cart already has a mop attached") + return + else if(istype(I, /obj/item/weapon/reagent_containers) && mybucket) + var/obj/item/weapon/reagent_containers/C = I + C.afterattack(mybucket, usr, 1) + update_icon() /obj/structure/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/janitorialcart/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = TRUE) 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 @@ -107,6 +159,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) ui.set_initial_data(data) ui.open() + /obj/structure/janitorialcart/Topic(href, href_list) if(!in_range(src, usr)) return @@ -146,13 +199,24 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) else warning("[src] signs ([signs]) didn't match contents") signs = 0 + if("bucket") + if(mybucket) + mybucket.forceMove(get_turf(user)) + to_chat(user, "You unmount [mybucket] from [src].") + mybucket = null update_icon() updateUsrDialog() + /obj/structure/janitorialcart/update_icon() - overlays = null + overlays.Cut() + + if(mybucket) + overlays += "cart_bucket" + if(mybucket.reagents.total_volume >= 1) + overlays += "water_cart" if(mybag) overlays += "cart_garbage" if(mymop) @@ -165,6 +229,73 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) overlays += "cart_sign[signs]" + + + + +//This is called if the cart is caught in an explosion, or destroyed by weapon fire +/obj/structure/janitorialcart/proc/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/weapon/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/janitorialcart/proc/dismantle(var/mob/user = null) + if (!dismantled) + if (has_items) + spill() + + new /obj/item/stack/material/steel(src.loc, 10) + new /obj/item/stack/material/plastic(src.loc, 10) + new /obj/item/stack/rods(src.loc, 20) + dismantled = 1 + qdel(src) + + +/obj/structure/janitorialcart/ex_act(severity) + spill(100 / severity) + ..() + + + + //old style retardo-cart /obj/structure/bed/chair/janicart name = "janicart" diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi index 2a08fc2a8d..349c8a4030 100644 Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ diff --git a/nano/templates/janitorcart.tmpl b/nano/templates/janitorcart.tmpl index 916b92bc72..3b8ee07680 100644 --- a/nano/templates/janitorcart.tmpl +++ b/nano/templates/janitorcart.tmpl @@ -27,4 +27,9 @@ {{:helper.link(data.signs, '', { 'take' : 'sign' })}} {{/if}} + {{if data.bucket}} +
+ {{:helper.link(data.bucket, '', { 'take' : 'bucket' })}} +
+ {{/if}} \ No newline at end of file