diff --git a/code/__SPLURTCODE/DEFINES/dcs/signals.dm b/code/__SPLURTCODE/DEFINES/dcs/signals.dm index f12c163f71..30320d2b1a 100644 --- a/code/__SPLURTCODE/DEFINES/dcs/signals.dm +++ b/code/__SPLURTCODE/DEFINES/dcs/signals.dm @@ -11,3 +11,6 @@ * Used by signals for determining when genitals have been updated */ #define COMSIG_MOB_UPDATE_GENITALS "mob_genitals_updated" + +///called on [/obj/item] AFTER unequip from base of [mob/proc/doUnEquip]: (force, atom/newloc, no_move, invdrop, silent) +#define COMSIG_ITEM_POST_UNEQUIP "item_post_unequip" diff --git a/code/modules/vending/security.dm b/code/modules/vending/security.dm index 52fbd7dac4..2f05de6034 100644 --- a/code/modules/vending/security.dm +++ b/code/modules/vending/security.dm @@ -14,7 +14,8 @@ /obj/item/storage/box/evidence = 6, /obj/item/flashlight/seclite = 4, /obj/item/restraints/legcuffs/bola/energy = 7, - /obj/item/secbat = 5) + /obj/item/secbat = 5, + /obj/item/bodycam_upgrade = 10) contraband = list(/obj/item/clothing/glasses/sunglasses = 2, /obj/item/storage/fancy/donut_box = 2, /obj/item/storage/belt/sabre/secbelt = 1) diff --git a/modular_splurt/code/modules/clothing/misc/body_camera.dm b/modular_splurt/code/modules/clothing/misc/body_camera.dm new file mode 100644 index 0000000000..4d57911f1a --- /dev/null +++ b/modular_splurt/code/modules/clothing/misc/body_camera.dm @@ -0,0 +1,145 @@ + +/obj/item/clothing/suit/armor/Initialize(mapload) + . = ..() + AddComponent(/datum/component/bodycamera_holder) + +/obj/item/clothing/suit/hooded/wintercoat/security/Initialize(mapload) + . = ..() + AddComponent(/datum/component/bodycamera_holder) + +/obj/item/clothing/suit/security/Initialize(mapload) + . = ..() + AddComponent(/datum/component/bodycamera_holder) + +/** + * The bodycamera + * + * This is the item that gets installed into items that have the bodycamera_holder element + */ +/obj/item/bodycam_upgrade + name = "\improper Body camera" + desc = "An armor vest upgrade, there's an instructions tag if you look a little closer..." + icon = 'modular_splurt/icons/obj/clothing/bodycam.dmi' + icon_state = "bodycamera" + ///The camera itself. + var/obj/machinery/camera/builtin_bodycamera + +/obj/item/bodycam_upgrade/examine_more(mob/user) + . = ..() + . += list(span_notice("Use [src] on any valid vest to quickly install.")) + . += list(span_notice("While equipped, use your ID card on the vest to activate/deactivate the camera.")) + . += list(span_notice("When going off duty, make sure to turn of your camera.")) + +/obj/item/bodycam_upgrade/Destroy() + if(builtin_bodycamera) + turn_off() + return ..() + +/obj/item/bodycam_upgrade/proc/is_on() + if(isnull(builtin_bodycamera)) + return FALSE + return TRUE + +/obj/item/bodycam_upgrade/proc/turn_on(mob/user, obj/item/card/id/id_card) + builtin_bodycamera = new(user) + builtin_bodycamera.internal_light = FALSE + builtin_bodycamera.network = list("ss13") + builtin_bodycamera.c_tag = "-Body Camera: [(id_card.registered_name)] ([id_card.assignment])" + playsound(loc, 'sound/machines/beep.ogg', get_clamped_volume(), TRUE, -1) + if(user) + user.balloon_alert(user, "bodycamera activated") + +/obj/item/bodycam_upgrade/proc/turn_off(mob/user) + if(user) + user.balloon_alert(user, "bodycamera deactivated") + playsound(loc, 'sound/machines/beep.ogg', get_clamped_volume(), TRUE, -1) + QDEL_NULL(builtin_bodycamera) + + +/** + * Bodycamera component + * + * Allows anything to have a body camera inserted into it + */ +/datum/component/bodycamera_holder + ///The installed bodycamera + var/obj/item/bodycam_upgrade/bodycamera_installed + ///The clothing part this needs to be on. This could possibly just be done by checking the clothing's slot + var/clothingtype_required = ITEM_SLOT_OCLOTHING + +/datum/component/bodycamera_holder/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/on_attackby) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE_MORE, .proc/on_examine_more) + +/datum/component/bodycamera_holder/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_PARENT_ATTACKBY) + UnregisterSignal(parent, COMSIG_PARENT_EXAMINE) + QDEL_NULL(bodycamera_installed) + return ..() + +/datum/component/bodycamera_holder/proc/turn_camera_on(mob/living/user, obj/item/card) + RegisterSignal(parent, COMSIG_ITEM_POST_UNEQUIP, PROC_REF(on_unequip)) + bodycamera_installed.turn_on(user, card) + +/datum/component/bodycamera_holder/proc/turn_camera_off(mob/living/user) + UnregisterSignal(parent, COMSIG_ITEM_POST_UNEQUIP) + bodycamera_installed.turn_off(user) + +/// When the camera holder is unequipped +/datum/component/bodycamera_holder/proc/on_unequip(mob/living/source, force, atom/newloc, no_move, invdrop, silent) + SIGNAL_HANDLER + turn_camera_off() + +/// When examining +/datum/component/bodycamera_holder/proc/on_examine_more(atom/source, mob/user, list/examine_list) + SIGNAL_HANDLER + + if(bodycamera_installed) + examine_list += span_notice("It has [bodycamera_installed] installed.") + else + examine_list += span_notice("It has a spot to hook up a body camera onto.") + +/// When items are used on it. Bodycamera/ID card +/datum/component/bodycamera_holder/proc/on_attackby(datum/source, obj/item/item, mob/living/user) + SIGNAL_HANDLER + + if(istype(item, /obj/item/bodycam_upgrade)) + if(bodycamera_installed) + user.balloon_alert(user, "camera already installed!") + playsound(source, 'sound/machines/buzz-two.ogg', item.get_clamped_volume(), TRUE, -1) + else + item.forceMove(source) + bodycamera_installed = item + playsound(source, 'sound/items/drill_use.ogg', item.get_clamped_volume(), TRUE, -1) + return + + if(!bodycamera_installed) + return + + var/obj/item/card/id/card = item.GetID() + if(!card) + return + var/obj/item/clothing/suit_slot = user.get_item_by_slot(clothingtype_required) + if(!istype(suit_slot)) + user.balloon_alert(user, "must be wearing suit!") + return + + //Do we have a camera on or off? + if(bodycamera_installed.is_on()) + turn_camera_off(user) + else + turn_camera_on(user, card) + +/// When a screwdriver is used on it +/datum/component/bodycamera_holder/proc/on_screwdriver_act(atom/source, mob/user, obj/item/tool) + SIGNAL_HANDLER + + if(!bodycamera_installed) + return + if(bodycamera_installed.is_on()) + turn_camera_off(user) + playsound(source, 'sound/items/drill_use.ogg', tool.get_clamped_volume(), TRUE, -1) + bodycamera_installed.forceMove(user.loc) + INVOKE_ASYNC(user, TYPE_PROC_REF(/mob, put_in_hands), bodycamera_installed) + bodycamera_installed = null diff --git a/modular_splurt/icons/obj/clothing/bodycam.dmi b/modular_splurt/icons/obj/clothing/bodycam.dmi new file mode 100644 index 0000000000..4047aca61e Binary files /dev/null and b/modular_splurt/icons/obj/clothing/bodycam.dmi differ diff --git a/modular_splurt/icons/obj/clothing/neck.dmi b/modular_splurt/icons/obj/clothing/neck.dmi index 50d48a91f1..d02b839824 100644 Binary files a/modular_splurt/icons/obj/clothing/neck.dmi and b/modular_splurt/icons/obj/clothing/neck.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 9fb8f23eb6..b2c1200404 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4757,6 +4757,7 @@ #include "modular_splurt\code\modules\clothing\masks\gasmask.dm" #include "modular_splurt\code\modules\clothing\masks\hailer.dm" #include "modular_splurt\code\modules\clothing\masks\miscellaneous.dm" +#include "modular_splurt\code\modules\clothing\misc\body_camera.dm" #include "modular_splurt\code\modules\clothing\neck\_neck.dm" #include "modular_splurt\code\modules\clothing\outfits\ert.dm" #include "modular_splurt\code\modules\clothing\outfits\standard.dm"