diff --git a/code/datums/components/label.dm b/code/datums/components/label.dm new file mode 100644 index 00000000000..26cb99c7e3c --- /dev/null +++ b/code/datums/components/label.dm @@ -0,0 +1,87 @@ +/** + The label component. + + This component is used to manage labels applied by the hand labeler. + + Atoms can only have one instance of this component, and therefore only one label at a time. + This is to avoid having names like "Backpack (label1) (label2) (label3)". This is annoying and abnoxious to read. + + When a player clicks the atom with a hand labeler to apply a label, this component gets applied to it. + If the labeler is off, the component will be removed from it, and the label will be removed from its name. + */ +/datum/component/label + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// The name of the label the player is applying to the parent. + var/label_name + +/datum/component/label/Initialize(_label_name) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + label_name = _label_name + apply_label() + +/datum/component/label/RegisterWithParent() + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackby) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/Examine) + +/datum/component/label/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_PARENT_ATTACKBY, COMSIG_PARENT_EXAMINE)) + +/** + This proc will fire after the parent is hit by a hand labeler which is trying to apply another label. + Since the parent already has a label, it will remove the old one from the parent's name, and apply the new one. +*/ +/datum/component/label/InheritComponent(datum/component/label/new_comp , i_am_original, list/arguments) + remove_label() + if(new_comp) + label_name = new_comp.label_name + else + label_name = arguments[1] + apply_label() + +/** + This proc will trigger when any object is used to attack the parent. + + If the attacking object is not a hand labeler, it will return. + If the attacking object is a hand labeler it will restore the name of the parent to what it was before this component was added to it, and the component will be deleted. + + Arguments: + * source: The parent. + * attacker: The object that is hitting the parent. + * user: The mob who is wielding the attacking object. +*/ +/datum/component/label/proc/OnAttackby(datum/source, obj/item/attacker, mob/user) + // If the attacking object is not a hand labeler or its mode is 1 (has a label ready to apply), return. + // The hand labeler should be off (mode is 0), in order to remove a label. + var/obj/item/hand_labeler/labeler = attacker + if(!istype(labeler) || labeler.mode) + return + + remove_label() + playsound(parent, 'sound/items/poster_ripped.ogg', 20, TRUE) + to_chat(user, "You remove the label from [parent].") + qdel(src) // Remove the component from the object. + +/** + This proc will trigger when someone examines the parent. + It will attach the text found in the body of the proc to the `examine_list` and display it to the player examining the parent. + + Arguments: + * source: The parent. + * user: The mob exmaining the parent. + * examine_list: The current list of text getting passed from the parent's normal examine() proc. +*/ +/datum/component/label/proc/Examine(datum/source, mob/user, list/examine_list) + examine_list += "It has a label with some words written on it. Use a hand labeler to remove it." + +/// Applies a label to the name of the parent in the format of: "parent_name (label)" +/datum/component/label/proc/apply_label() + var/atom/owner = parent + owner.name += " ([label_name])" + +/// Removes the label from the parent's name +/datum/component/label/proc/remove_label() + var/atom/owner = parent + owner.name = replacetext(owner.name, "([label_name])", "") // Remove the label text from the parent's name, wherever it's located. + owner.name = trim(owner.name) // Shave off any white space from the beginning or end of the parent's name. diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm index 732c55e3fbe..14bc959fbb1 100644 --- a/code/datums/outfits/outfit_admin.dm +++ b/code/datums/outfits/outfit_admin.dm @@ -709,7 +709,8 @@ pda = /obj/item/pda backpack_contents = list( /obj/item/storage/box/survival = 1, - /obj/item/hand_labeler = 1 + /obj/item/hand_labeler = 1, + /obj/item/hand_labeler_refill = 1 ) /datum/outfit/admin/sol_trader/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 15c6f3fb2c0..a18a9d74f28 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -1434,6 +1434,8 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY contains = list(/obj/structure/filingcabinet/chestdrawer, /obj/item/camera_film, /obj/item/hand_labeler, + /obj/item/hand_labeler_refill, + /obj/item/hand_labeler_refill, /obj/item/stack/tape_roll, /obj/item/paper_bin, /obj/item/pen, diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index 74bee9867ab..7722dd2b53f 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -1,11 +1,12 @@ /obj/item/hand_labeler name = "hand labeler" + desc = "A combined label printer, applicator, and remover, all in a single portable device. Designed to be easy to operate and use." icon = 'icons/obj/bureaucracy.dmi' icon_state = "labeler0" item_state = "flight" var/label = null var/labels_left = 30 - var/mode = 0 //off or on. + var/mode = 0 /obj/item/hand_labeler/afterattack(atom/A, mob/user, proximity) if(!proximity) @@ -29,7 +30,9 @@ user.visible_message("[user] labels [A] as [label].", \ "You label [A] as [label].") investigate_log("[key_name(user)] labelled [A] as [label].", INVESTIGATE_LABEL) // Investigate goes BEFORE rename so the original name is preserved in the log - A.name = "[A.name] ([label])" + A.AddComponent(/datum/component/label, label) + playsound(A, 'sound/items/handling/component_pickup.ogg', 20, TRUE) + labels_left-- /obj/item/hand_labeler/attack_self(mob/user as mob) mode = !mode @@ -45,3 +48,20 @@ to_chat(user, "You set the text to '[str]'.") else to_chat(user, "You turn off \the [src].") + +/obj/item/hand_labeler/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/hand_labeler_refill)) + to_chat(user, "You insert [I] into [src].") + user.drop_item() + qdel(I) + labels_left = initial(labels_left) //Yes, it's capped at its initial value + else + return ..() + +/obj/item/hand_labeler_refill + name = "hand labeler paper roll" + icon = 'icons/obj/bureaucracy.dmi' + desc = "A roll of paper. Use it on a hand labeler to refill it." + icon_state = "labeler_refill" + item_state = "electropack" + w_class = WEIGHT_CLASS_TINY diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index adf304513c7..3d287a2365a 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/paradise.dme b/paradise.dme index 3ecbfb6b3ee..a913628c28e 100644 --- a/paradise.dme +++ b/paradise.dme @@ -296,6 +296,7 @@ #include "code\datums\components\decal.dm" #include "code\datums\components\ducttape.dm" #include "code\datums\components\jestosterone.dm" +#include "code\datums\components\label.dm" #include "code\datums\components\material_container.dm" #include "code\datums\components\paintable.dm" #include "code\datums\components\spawner.dm" diff --git a/sound/items/handling/component_pickup.ogg b/sound/items/handling/component_pickup.ogg new file mode 100644 index 00000000000..cfaba1dd193 Binary files /dev/null and b/sound/items/handling/component_pickup.ogg differ