diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index dff12ce03ba..1fbd794856e 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -1370,3 +1370,9 @@ #define COMSIG_MERGER_REMOVING "comsig_merger_removing" /// Called on the merger after finishing a refresh: (list/leaving_members, list/joining_members) #define COMSIG_MERGER_REFRESH_COMPLETE "comsig_merger_refresh_complete" + +// Vacuum signals +/// Called on a bag being attached to a vacuum parent +#define COMSIG_VACUUM_BAG_ATTACH "comsig_vacuum_bag_attach" +/// Called on a bag being detached from a vacuum parent +#define COMSIG_VACUUM_BAG_DETACH "comsig_vacuum_bag_detach" diff --git a/code/datums/components/vacuum.dm b/code/datums/components/vacuum.dm new file mode 100644 index 00000000000..601fdc0d873 --- /dev/null +++ b/code/datums/components/vacuum.dm @@ -0,0 +1,86 @@ +/** + * # Vacuum Component + * + * Adds a vacuum functionality to an atom, requires a trashbag to be linked + * using signals + * + */ +/datum/component/vacuum + /// The linked trash bag to vacuum trash into + var/obj/item/storage/bag/trash/vacuum_bag + +/datum/component/vacuum/Initialize(obj/item/storage/bag/trash/connected_bag = null) + . = ..() + if(!ismovable(parent)) + return COMPONENT_INCOMPATIBLE + if (connected_bag) + attach_bag(null, connected_bag) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/suck) + RegisterSignal(parent, COMSIG_VACUUM_BAG_ATTACH, .proc/attach_bag) + RegisterSignal(parent, COMSIG_VACUUM_BAG_DETACH, .proc/detach_bag) + +/** + * Called when parent moves, deligates vacuuming functionality + * + * Arguments: + * * suckee - The source of the signal + */ +/datum/component/vacuum/proc/suck(datum/suckee) + SIGNAL_HANDLER + + // get tile to suck on + var/atom/movable/AM = suckee + var/turf/tile = AM.loc + if (!isturf(tile)) + return + + // no bag attached, don't bother + if (!vacuum_bag) + return + + // suck the things + INVOKE_ASYNC(src, .proc/suck_items, tile) + +/** + * Sucks up items as possible from a provided turf into the connected trash bag + * + * Arguments: + * * tile - The tile upon which to vacuum up items + */ +/datum/component/vacuum/proc/suck_items(turf/tile) + var/sucked = FALSE + for (var/potential_item in tile) + if (!isitem(potential_item)) + continue + var/obj/item/item = potential_item + if (vacuum_bag?.attackby(item)) + sucked = TRUE // track that we successfully sucked up something + + // if we did indeed suck up something, play a funny noise + if (sucked) + playsound(parent, "rustle", 50, TRUE, -5) + +/** + * Handler for when a new trash bag is attached + * + * Arguments: + * * source - The source of the signal + * * new_bag - The new bag being installed + */ +/datum/component/vacuum/proc/attach_bag(datum/source, obj/item/storage/bag/trash/new_bag) + SIGNAL_HANDLER + + vacuum_bag = new_bag + RegisterSignal(new_bag, COMSIG_PARENT_QDELETING, .proc/detach_bag) + +/** + * Handler for when a trash bag is detached + * + * Arguments: + * * source - The source of the signal + */ +/datum/component/vacuum/proc/detach_bag(datum/source) + SIGNAL_HANDLER + if (vacuum_bag) // null check to avoid runtime on bag being deleted then sending detach as a result from parent + UnregisterSignal(vacuum_bag, COMSIG_PARENT_QDELETING) + vacuum_bag = null diff --git a/code/datums/greyscale/config_types/greyscale_configs.dm b/code/datums/greyscale/config_types/greyscale_configs.dm index 7a70c906729..b182e69ad9c 100644 --- a/code/datums/greyscale/config_types/greyscale_configs.dm +++ b/code/datums/greyscale/config_types/greyscale_configs.dm @@ -357,3 +357,11 @@ name = "Wrapping Paper" icon_file = 'icons/obj/stack_objects.dmi' json_config = 'code/datums/greyscale/json_configs/wrap_paper.json' + +/datum/greyscale_config/janicart_upgrade + name = "Janicart Upgrade" + icon_file = 'icons/obj/janicart_upgrade.dmi' + json_config = 'code/datums/greyscale/json_configs/janicart_upgrade.json' + +/datum/greyscale_config/janicart_upgrade/installed + json_config = 'code/datums/greyscale/json_configs/janicart_upgrade_installed.json' diff --git a/code/datums/greyscale/json_configs/janicart_upgrade.json b/code/datums/greyscale/json_configs/janicart_upgrade.json new file mode 100644 index 00000000000..7269059b3bc --- /dev/null +++ b/code/datums/greyscale/json_configs/janicart_upgrade.json @@ -0,0 +1,28 @@ +{ + "janicart_upgrade": [ + { + "type": "icon_state", + "icon_state": "housing", + "blend_mode": "overlay", + "color_ids": [ 1 ] + }, + { + "type": "icon_state", + "icon_state": "bristles", + "blend_mode": "overlay", + "color_ids": [ 2 ] + }, + { + "type": "icon_state", + "icon_state": "accent", + "blend_mode": "overlay", + "color_ids": [ 3 ] + }, + { + "type": "icon_state", + "icon_state": "light", + "blend_mode": "overlay", + "color_ids": [ 4 ] + } + ] +} diff --git a/code/datums/greyscale/json_configs/janicart_upgrade_installed.json b/code/datums/greyscale/json_configs/janicart_upgrade_installed.json new file mode 100644 index 00000000000..c586c92709c --- /dev/null +++ b/code/datums/greyscale/json_configs/janicart_upgrade_installed.json @@ -0,0 +1,28 @@ +{ + "janicart_upgrade": [ + { + "type": "icon_state", + "icon_state": "cart_housing", + "blend_mode": "overlay", + "color_ids": [ 1 ] + }, + { + "type": "icon_state", + "icon_state": "cart_bristles", + "blend_mode": "overlay", + "color_ids": [ 2 ] + }, + { + "type": "icon_state", + "icon_state": "cart_accent", + "blend_mode": "overlay", + "color_ids": [ 3 ] + }, + { + "type": "icon_state", + "icon_state": "cart_light", + "blend_mode": "overlay", + "color_ids": [ 4 ] + } + ] +} diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index ee94846a0c6..4eea5dcc0af 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -378,13 +378,23 @@ category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_ENGINEERING -/datum/design/buffer +/datum/design/buffer_upgrade name = "Floor Buffer Upgrade" desc = "A floor buffer that can be attached to vehicular janicarts." id = "buffer" build_type = PROTOLATHE | AWAY_LATHE materials = list(/datum/material/iron = 3000, /datum/material/glass = 200) - build_path = /obj/item/janiupgrade + build_path = /obj/item/janicart_upgrade/buffer + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_SERVICE + +/datum/design/vacuum_upgrade + name = "Vacuum Upgrade" + desc = "A vacuum that can be attached to vehicular janicarts." + id = "vacuum" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron = 3000, /datum/material/glass = 200) + build_path = /obj/item/janicart_upgrade/vacuum category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_SERVICE diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index e44c749d033..4e9b6aca9f0 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -1222,6 +1222,7 @@ "beartrap", "blutrash", "buffer", + "vacuum", "holobarrier_jani", "light_replacer", "paint_remover", diff --git a/code/modules/vehicles/pimpin_ride.dm b/code/modules/vehicles/pimpin_ride.dm index c55b3332111..2f8ebebce39 100644 --- a/code/modules/vehicles/pimpin_ride.dm +++ b/code/modules/vehicles/pimpin_ride.dm @@ -1,76 +1,167 @@ -//PIMP-CART +/** + * # Janicart + */ /obj/vehicle/ridden/janicart name = "janicart (pimpin' ride)" desc = "A brave janitor cyborg gave its life to produce such an amazing combination of speed and utility." icon_state = "pussywagon" key_type = /obj/item/key/janitor - var/obj/item/storage/bag/trash/mybag = null - var/floorbuffer = FALSE movedelay = 1 + /// The attached garbage bag, if present + var/obj/item/storage/bag/trash/trash_bag + /// The installed upgrade, if present + var/obj/item/janicart_upgrade/installed_upgrade /obj/vehicle/ridden/janicart/Initialize(mapload) . = ..() update_appearance() AddElement(/datum/element/ridable, /datum/component/riding/vehicle/janicart) - - if(floorbuffer) - AddElement(/datum/element/cleaning) + if (installed_upgrade) + installed_upgrade.install(src) /obj/vehicle/ridden/janicart/Destroy() - if(mybag) - QDEL_NULL(mybag) + if (trash_bag) + QDEL_NULL(trash_bag) + if (installed_upgrade) + QDEL_NULL(installed_upgrade) return ..() -/obj/item/janiupgrade - name = "floor buffer upgrade" - desc = "An upgrade for mobile janicarts." - icon = 'icons/obj/vehicles.dmi' - icon_state = "upgrade" - /obj/vehicle/ridden/janicart/examine(mob/user) . = ..() - if(floorbuffer) - . += "It has been upgraded with a floor buffer." + if (installed_upgrade) + . += "It has been upgraded with [installed_upgrade], which can be removed with a screwdriver." /obj/vehicle/ridden/janicart/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/storage/bag/trash)) - if(mybag) + if(trash_bag) to_chat(user, span_warning("[src] already has a trashbag hooked!")) return if(!user.transferItemToLoc(I, src)) return to_chat(user, span_notice("You hook the trashbag onto [src].")) - mybag = I + trash_bag = I + RegisterSignal(trash_bag, COMSIG_PARENT_QDELETING, .proc/bag_deleted) + SEND_SIGNAL(src, COMSIG_VACUUM_BAG_ATTACH, I) update_appearance() - else if(istype(I, /obj/item/janiupgrade)) - if(floorbuffer) - to_chat(user, span_warning("[src] already has a floor buffer!")) + else if(istype(I, /obj/item/janicart_upgrade)) + if(installed_upgrade) + to_chat(user, span_warning("[src] already has an upgrade installed! Use a screwdriver to remove it.")) return - floorbuffer = TRUE - qdel(I) - to_chat(user, span_notice("You upgrade [src] with the floor buffer.")) - AddElement(/datum/element/cleaning) + var/obj/item/janicart_upgrade/new_upgrade = I + new_upgrade.forceMove(src) + new_upgrade.install(src) + installed_upgrade = new_upgrade + to_chat(user, span_notice("You upgrade [src] with [new_upgrade].")) update_appearance() - else if(mybag) - mybag.attackby(I, user) + else if (istype(I, /obj/item/screwdriver) && installed_upgrade) + installed_upgrade.uninstall(src) + installed_upgrade.forceMove(get_turf(user)) + user.put_in_hands(installed_upgrade) + to_chat(user, span_notice("You remove [installed_upgrade] from [src]")) + installed_upgrade = null + update_appearance() + else if(trash_bag && (!is_key(I) || is_key(inserted_key))) // don't put a key in the trash when we need it + trash_bag.attackby(I, user) else return ..() /obj/vehicle/ridden/janicart/update_overlays() . = ..() - if(mybag) + if(trash_bag) . += "cart_garbage" - if(floorbuffer) - . += "cart_buffer" + if(installed_upgrade) + var/mutable_appearance/overlay = new(SSgreyscale.GetColoredIconByType(installed_upgrade.overlay_greyscale_config, installed_upgrade.greyscale_colors)) + overlay.icon_state = "janicart_upgrade" + . += overlay /obj/vehicle/ridden/janicart/attack_hand(mob/user, list/modifiers) - . = ..() - if(. || !mybag) - return - mybag.forceMove(get_turf(user)) - user.put_in_hands(mybag) - mybag = null + // right click removes bag without unbuckling when possible + . = (LAZYACCESS(modifiers, RIGHT_CLICK) && try_remove_bag(user)) || ..() + if (!.) + try_remove_bag(user) + + +/** + * Called if the attached bag is being qdeleted, ensures appearance is maintained properly + */ +/obj/vehicle/ridden/janicart/proc/bag_deleted(datum/source) + SIGNAL_HANDLER + INVOKE_ASYNC(src, .proc/try_remove_bag) + +/** + * Attempts to remove the attached trash bag, returns true if bag was removed + * + * Arguments: + * * remover - The (optional) mob attempting to remove the bag + */ +/obj/vehicle/ridden/janicart/proc/try_remove_bag(mob/remover = null) + if (!trash_bag) + return FALSE + if (remover) + trash_bag.forceMove(get_turf(remover)) + remover.put_in_hands(trash_bag) + UnregisterSignal(trash_bag, COMSIG_PARENT_QDELETING) + trash_bag = null + SEND_SIGNAL(src, COMSIG_VACUUM_BAG_DETACH) update_appearance() + return TRUE /obj/vehicle/ridden/janicart/upgraded - floorbuffer = TRUE + installed_upgrade = new /obj/item/janicart_upgrade/buffer + +/obj/vehicle/ridden/janicart/upgraded/vacuum + installed_upgrade = new /obj/item/janicart_upgrade/vacuum + +/** + * # Janicart Upgrade + * + * Functional upgrades that can be installed into a janicart. + * + */ +/obj/item/janicart_upgrade + name = "base upgrade" + desc = "An abstract upgrade for mobile janicarts." + icon_state = "janicart_upgrade" + greyscale_config = /datum/greyscale_config/janicart_upgrade + /// The greyscale config for the on-cart installed upgrade overlay + var/overlay_greyscale_config = /datum/greyscale_config/janicart_upgrade/installed + +/** + * Called when upgrade is installed into a janicart + * + * Arguments: + * * installee - The cart the upgrade is being installed into + */ +/obj/item/janicart_upgrade/proc/install(obj/vehicle/ridden/janicart/installee) + return FALSE + +/** + * Called when upgrade is uninstalled from a janicart + * + * Arguments: + * * installee - The cart the upgrade is being removed from + */ +/obj/item/janicart_upgrade/proc/uninstall(obj/vehicle/ridden/janicart/installee) + return FALSE + +/obj/item/janicart_upgrade/buffer + name = "floor buffer upgrade" + desc = "An upgrade for mobile janicarts which adds a floor buffer functionality." + greyscale_colors = "#ffffff#6aa3ff#a2a2a2#d1d15f" + +/obj/item/janicart_upgrade/buffer/install(obj/vehicle/ridden/janicart/installee) + installee._AddElement(list(/datum/element/cleaning)) + +/obj/item/janicart_upgrade/buffer/uninstall(obj/vehicle/ridden/janicart/installee) + installee._RemoveElement(list(/datum/element/cleaning)) + +/obj/item/janicart_upgrade/vacuum + name = "vacuum upgrade" + desc = "An upgrade for mobile janicarts which adds a vacuum functionality." + greyscale_colors = "#ffffff#ffea6a#a2a2a2#d1d15f" + +/obj/item/janicart_upgrade/vacuum/install(obj/vehicle/ridden/janicart/installee) + installee._AddComponent(list(/datum/component/vacuum, installee.trash_bag)) + +/obj/item/janicart_upgrade/vacuum/uninstall(obj/vehicle/ridden/janicart/installee) + qdel(installee.GetComponent(/datum/component/vacuum)) diff --git a/icons/obj/janicart_upgrade.dmi b/icons/obj/janicart_upgrade.dmi new file mode 100644 index 00000000000..18b18790e92 Binary files /dev/null and b/icons/obj/janicart_upgrade.dmi differ diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi index 75553c98fc4..c1ed2b4e3a4 100644 Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ diff --git a/tgstation.dme b/tgstation.dme index d87d7d46df9..c2d2c12db22 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -624,6 +624,7 @@ #include "code\datums\components\udder.dm" #include "code\datums\components\uplink.dm" #include "code\datums\components\usb_port.dm" +#include "code\datums\components\vacuum.dm" #include "code\datums\components\wearertargeting.dm" #include "code\datums\components\wet_floor.dm" #include "code\datums\components\container_item\container_item.dm"