From 5f2ecc551366c0145248c4cb147895e3f29f7569 Mon Sep 17 00:00:00 2001 From: Alan Date: Fri, 17 Jul 2026 02:28:54 -0400 Subject: [PATCH] Migrate cosmetics to the new attack chain. (#32228) * Migrate cosmetics to the new attack chain. * Clean up code a bit more. * Fix lipstick cap icon. * Apply suggestions from CRUNCH review Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com> Signed-off-by: Alan * Add fingerprints. --------- Signed-off-by: Alan Co-authored-by: CRUNCH <143041327+CRUNCH-Borg@users.noreply.github.com> --- code/game/objects/items/cosmetics.dm | 283 ++++++++++++++++----------- 1 file changed, 174 insertions(+), 109 deletions(-) diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm index 742604c8967..f35ea226194 100644 --- a/code/game/objects/items/cosmetics.dm +++ b/code/game/objects/items/cosmetics.dm @@ -6,6 +6,7 @@ var/colour = "red" var/open = FALSE var/static/list/lipstick_colors + new_attack_chain = TRUE /obj/item/lipstick/Initialize(mapload) . = ..() @@ -57,44 +58,60 @@ colour = pick(lipstick_colors) name = "[colour] lipstick" -/obj/item/lipstick/attack_self__legacy__attackchain(mob/user) +/obj/item/lipstick/activate_self(mob/user) + if(..()) + return ITEM_INTERACT_COMPLETE cut_overlays() - to_chat(user, SPAN_NOTICE("You twist \the [src] [open ? "closed" : "open"].")) + to_chat(user, SPAN_NOTICE("You twist [src] [open ? "closed" : "open"].")) open = !open - if(open) - var/mutable_appearance/colored = mutable_appearance('icons/obj/items.dmi', "lipstick_uncap_color") - colored.color = lipstick_colors[colour] - icon_state = "lipstick_uncap" - add_overlay(colored) - else + if(!open) icon_state = "lipstick" + return ITEM_INTERACT_COMPLETE + var/mutable_appearance/colored = mutable_appearance('icons/obj/items.dmi', "lipstick_uncap_color") + colored.color = lipstick_colors[colour] + icon_state = "lipstick_uncap" + add_overlay(colored) + add_fingerprint(user) -/obj/item/lipstick/attack__legacy__attackchain(mob/M, mob/user) - if(!open || !istype(M)) - return +/obj/item/lipstick/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!open || !ismob(target)) + return ..() - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.lip_style) // If they already have lipstick on - to_chat(user, SPAN_NOTICE("You need to wipe off the old lipstick first!")) - return - if(H == user) - user.visible_message(SPAN_NOTICE("[user] does [user.p_their()] lips with [src]."), \ - SPAN_NOTICE("You take a moment to apply [src]. Perfect!")) - H.lip_style = "lipstick" - H.lip_color = lipstick_colors[colour] - H.update_body() - else - user.visible_message(SPAN_WARNING("[user] begins to do [H]'s lips with \the [src]."), \ - SPAN_NOTICE("You begin to apply \the [src].")) - if(do_after(user, 20, target = H)) - user.visible_message(SPAN_NOTICE("[user] does [H]'s lips with \the [src]."), \ - SPAN_NOTICE("You apply \the [src].")) - H.lip_style = "lipstick" - H.lip_color = lipstick_colors[colour] - H.update_body() - else - to_chat(user, SPAN_NOTICE("Where are the lips on that?")) + if(!ishuman(target)) + to_chat(user, SPAN_WARNING("Where are the lips on that?")) + return ITEM_INTERACT_COMPLETE + + var/mob/living/carbon/human/human_target = target + if(human_target.lip_style) // If they already have lipstick on... + to_chat(user, SPAN_WARNING("You need to wipe off the old lipstick first!")) + return ITEM_INTERACT_COMPLETE + + if(human_target == user) + user.visible_message( + SPAN_NOTICE("[user] does [user.p_their()] lips with [src]."), + SPAN_NOTICE("You take a moment to apply [src]. Perfect!") + ) + human_target.lip_style = "lipstick" + human_target.lip_color = lipstick_colors[colour] + human_target.update_body() + add_fingerprint(user) + return ITEM_INTERACT_COMPLETE + + user.visible_message( + SPAN_WARNING("[user] begins to do [human_target]'s lips with [src]."), + SPAN_NOTICE("You begin to apply [src].") + ) + if(!do_after(user, 20, target = human_target)) + return ITEM_INTERACT_COMPLETE + user.visible_message( + SPAN_NOTICE("[user] does [human_target]'s lips with [src]."), + SPAN_NOTICE("You apply [src].") + ) + human_target.lip_style = "lipstick" + human_target.lip_color = lipstick_colors[colour] + human_target.update_body() + add_fingerprint(user) + return ITEM_INTERACT_COMPLETE /obj/item/razor name = "electric razor" @@ -103,81 +120,129 @@ flags = CONDUCT w_class = WEIGHT_CLASS_TINY usesound = 'sound/items/welder2.ogg' + new_attack_chain = TRUE -/obj/item/razor/attack__legacy__attackchain(mob/living/carbon/M as mob, mob/user as mob) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/head/C = H.get_organ("head") - if(!istype(C)) - to_chat(user, SPAN_WARNING("There's nothing to cut, [M] [M.p_are()] missing [M.p_their()] head!")) - return ..() - var/datum/robolimb/robohead = GLOB.all_robolimbs[C.model] - if(user.zone_selected == "mouth") - if(!get_location_accessible(H, "mouth")) - to_chat(user, SPAN_WARNING("The mask is in the way.")) - return - if((C.dna.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... - to_chat(user, SPAN_WARNING("You find yourself disappointed at the appalling lack of facial hair.")) - return - if(C.f_style == "Shaved") - to_chat(user, SPAN_NOTICE("Already clean-shaven.")) - return - if(H == user) //shaving yourself - user.visible_message(SPAN_NOTICE("[user] starts to shave [user.p_their()] facial hair with [src]."), \ - SPAN_NOTICE("You take a moment shave your facial hair with \the [src].")) - if(do_after(user, 50 * toolspeed, target = H)) - user.visible_message(SPAN_NOTICE("[user] shaves [user.p_their()] facial hair clean with [src]."), \ - SPAN_NOTICE("You finish shaving with [src]. Fast and clean!")) - C.f_style = "Shaved" - H.update_fhair() - playsound(src.loc, usesound, 20, 1) - else - var/turf/user_loc = user.loc - var/turf/H_loc = H.loc - user.visible_message(SPAN_DANGER("[user] tries to shave [H]'s facial hair with \the [src]."), \ - SPAN_WARNING("You start shaving [H]'s facial hair.")) - if(do_after(user, 50 * toolspeed, target = H)) - if(user_loc == user.loc && H_loc == H.loc) - user.visible_message(SPAN_DANGER("[user] shaves off [H]'s facial hair with \the [src]."), \ - SPAN_NOTICE("You shave [H]'s facial hair clean off.")) - C.f_style = "Shaved" - H.update_fhair() - playsound(src.loc, usesound, 20, 1) - if(user.zone_selected == "head") - if(!get_location_accessible(H, "head")) - to_chat(user, SPAN_WARNING("The headgear is in the way.")) - return - if((C.dna.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... - to_chat(user, SPAN_WARNING("You find yourself disappointed at the appalling lack of hair.")) - return - if(C.h_style == "Bald" || C.h_style == "Balding Hair" || C.h_style == "Skinhead") - to_chat(user, SPAN_NOTICE("There is not enough hair left to shave...")) - return - if(isskrell(M)) - to_chat(user, SPAN_WARNING("Your razor isn't going to cut through tentacles.")) - return - if(H == user) //shaving yourself - user.visible_message(SPAN_WARNING("[user] starts to shave [user.p_their()] head with [src]."), \ - SPAN_WARNING("You start to shave your head with \the [src].")) - if(do_after(user, 50 * toolspeed, target = H)) - user.visible_message(SPAN_NOTICE("[user] shaves [user.p_their()] head with [src]."), \ - SPAN_NOTICE("You finish shaving with \the [src].")) - C.h_style = "Skinhead" - H.update_hair() - playsound(src.loc, usesound, 40, 1) - else - var/turf/user_loc = user.loc - var/turf/H_loc = H.loc - user.visible_message(SPAN_DANGER("[user] tries to shave [H]'s head with \the [src]!"), \ - SPAN_WARNING("You start shaving [H]'s head.")) - if(do_after(user, 50 * toolspeed, target = H)) - if(user_loc == user.loc && H_loc == H.loc) - user.visible_message(SPAN_DANGER("[user] shaves [H]'s head bald with \the [src]!"), \ - SPAN_WARNING("You shave [H]'s head bald.")) - C.h_style = "Skinhead" - H.update_hair() - playsound(src.loc, usesound, 40, 1) - else - ..() +/obj/item/razor/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!ishuman(target)) + return ..() + + if(!(user.zone_selected in list("head", "mouth"))) + return ..() + + var/mob/living/carbon/human/human_target = target + var/obj/item/organ/external/head/human_head = human_target.get_organ("head") + if(!istype(human_head)) + to_chat(user, SPAN_WARNING("There's nothing to cut, [target] [target.p_are()] missing [target.p_their()] head!")) + return ITEM_INTERACT_COMPLETE + + var/datum/robolimb/robohead = GLOB.all_robolimbs[human_head.model] + + if((human_head.dna.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) + // If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'... + to_chat(user, SPAN_WARNING("You find yourself disappointed at the appalling lack of hair.")) + return ITEM_INTERACT_COMPLETE + + if(isskrell(target)) + to_chat(user, SPAN_WARNING("Your razor isn't going to cut through tentacles.")) + return ITEM_INTERACT_COMPLETE + + if(user.zone_selected == "mouth") + shave_face(target, user) + return ITEM_INTERACT_COMPLETE + + shave_head(target, user) + return ITEM_INTERACT_COMPLETE + +/obj/item/razor/proc/shave_head(mob/living/carbon/human/target, mob/living/user) + var/obj/item/organ/external/head/human_head = target.get_organ("head") + if(!get_location_accessible(target, "head")) + to_chat(user, SPAN_WARNING("The headgear is in the way!")) + return FALSE + + if(human_head.h_style == "Bald" || human_head.h_style == "Balding Hair" || human_head.h_style == "Skinhead") + to_chat(user, SPAN_WARNING("There is not enough hair left to shave...")) + return FALSE + + if(target == user) // Shaving yourself. + user.visible_message( + SPAN_NOTICE("[user] starts to shave [user.p_their()] head with [src]."), + SPAN_NOTICE("You start to shave your head with [src].") + ) else - ..() + user.visible_message( + SPAN_DANGER("[user] tries to shave [target]'s head with [src]!"), + SPAN_NOTICE("You start shaving [target]'s head.") + ) + + var/turf/user_loc = user.loc + var/turf/target_loc = target.loc + if(!do_after(user, 50 * toolspeed, target = target)) + return FALSE + if(!(user_loc == user.loc && target_loc == target.loc)) + return FALSE + + if(target == user) + user.visible_message( + SPAN_NOTICE("[user] shaves [user.p_their()] head with [src]."), + SPAN_NOTICE("You finish shaving with [src]."), + SPAN_NOTICE("You hear an electric razor shaving.") + ) + else + user.visible_message( + SPAN_DANGER("[user] shaves [target]'s head bald with [src]!"), + SPAN_NOTICE("You shave [target]'s head bald."), + SPAN_HEAR("You hear an electric razor shaving.") + ) + human_head.h_style = "Skinhead" + target.update_hair() + playsound(src.loc, usesound, 40, 1) + add_fingerprint(user) + return TRUE + +/obj/item/razor/proc/shave_face(mob/living/carbon/human/target, mob/living/user) + var/obj/item/organ/external/head/human_head = target.get_organ("head") + if(!get_location_accessible(target, "mouth")) + to_chat(user, SPAN_WARNING("The mask is in the way!")) + return FALSE + + if(human_head.f_style == "Shaved") + to_chat(user, SPAN_WARNING("Already clean-shaven!")) + return FALSE + + if(target == user) // Shaving yourself. + user.visible_message( + SPAN_NOTICE("[user] starts to shave [user.p_their()] facial hair with [src]."), + SPAN_NOTICE("You take a moment shave your facial hair with [src]."), + SPAN_HEAR("You hear an electric razor shaving.") + ) + else + user.visible_message( + SPAN_DANGER("[user] tries to shave [target]'s facial hair with [src]!"), + SPAN_NOTICE("You start shaving [target]'s facial hair.") + ) + + var/turf/user_loc = user.loc + var/turf/target_loc = target.loc + if(!do_after(user, 50 * toolspeed, target = target)) + return FALSE + if(!(user_loc == user.loc && target_loc == target.loc)) + return FALSE + + if(target == user) + user.visible_message( + SPAN_NOTICE("[user] shaves [user.p_their()] facial hair clean with [src]."), + SPAN_NOTICE("You finish shaving with [src]. Fast and clean!"), + SPAN_HEAR("You hear an electric razor shaving.") + ) + else + user.visible_message( + SPAN_DANGER("[user] shaves off [target]'s facial hair with [src]."), + SPAN_NOTICE("You shave [target]'s facial hair clean off."), + SPAN_HEAR("You hear an electric razor shaving.") + ) + + human_head.f_style = "Shaved" + target.update_fhair() + playsound(src.loc, usesound, 20, 1) + add_fingerprint(user) + return TRUE