From 23bb467991d514c528c471ef74dcbe7ff61e9835 Mon Sep 17 00:00:00 2001 From: warriorstar-orion Date: Tue, 25 Mar 2025 07:13:37 -0400 Subject: [PATCH] refactor human butchering trait (#28725) * refactor human butchering trait * Update code/datums/elements/butchers_humans.dm Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com> Signed-off-by: warriorstar-orion --------- Signed-off-by: warriorstar-orion Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com> --- code/__HELPERS/trait_helpers.dm | 1 - code/_globalvars/traits.dm | 1 - code/datums/elements/butchers_humans.dm | 54 +++++++++++++++++++ code/game/objects/items.dm | 3 -- code/game/objects/items/weapons/kitchen.dm | 2 +- code/game/objects/items/weapons/twohanded.dm | 2 +- .../food_and_drinks/food/foods/meat.dm | 2 - .../mob/living/carbon/human/human_defense.dm | 17 +----- paradise.dme | 1 + 9 files changed, 58 insertions(+), 25 deletions(-) create mode 100644 code/datums/elements/butchers_humans.dm diff --git a/code/__HELPERS/trait_helpers.dm b/code/__HELPERS/trait_helpers.dm index 819619d9207..ffc14b71a79 100644 --- a/code/__HELPERS/trait_helpers.dm +++ b/code/__HELPERS/trait_helpers.dm @@ -278,7 +278,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_SUPERMATTER_IMMUNE "supermatter_immune" //***** ITEM TRAITS *****// -#define TRAIT_BUTCHERS_HUMANS "butchers_humans" #define TRAIT_CMAGGED "cmagged" /// An item that is being wielded. #define TRAIT_WIELDED "wielded" diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 1485e84fb54..397cda59005 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -132,7 +132,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( /obj/item = list( "TRAIT_SHOW_WIRE_INFO" = TRAIT_SHOW_WIRE_INFO, "TRAIT_SUPERMATTER_IMMUNE" = TRAIT_SUPERMATTER_IMMUNE, - "TRAIT_BUTCHER_HUMANS" = TRAIT_BUTCHERS_HUMANS, "TRAIT_CMAGGED" = TRAIT_CMAGGED, "TRAIT_OBSCURED_WIRES" = TRAIT_OBSCURED_WIRES, "TRAIT_XENO_INTERACTABLE" = TRAIT_XENO_INTERACTABLE, diff --git a/code/datums/elements/butchers_humans.dm b/code/datums/elements/butchers_humans.dm new file mode 100644 index 00000000000..d919fb31425 --- /dev/null +++ b/code/datums/elements/butchers_humans.dm @@ -0,0 +1,54 @@ +/// An element for items that butcher human corpses into meat when attacked on +/// harm intent. +/datum/element/butchers_humans + element_flags = ELEMENT_DETACH_ON_HOST_DESTROY + +/datum/element/butchers_humans/Attach(datum/target) + . = ..() + if(!isitem(target)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(target, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(target, COMSIG_ATTACK, PROC_REF(on_attack)) + +/datum/element/butchers_humans/Detach(datum/source, force) + . = ..() + UnregisterSignal(source, list(COMSIG_PARENT_EXAMINE, COMSIG_ATTACK)) + +/datum/element/butchers_humans/proc/on_examine(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER // COMSIG_PARENT_EXAMINE + examine_list += "Can be used to butcher dead people into meat while on harm intent." + +/datum/element/butchers_humans/proc/on_attack(datum/source, mob/living/victim, mob/living/user, params) + SIGNAL_HANDLER // COMSIG_ATTACK + + if(!ishuman(victim) || !isitem(source)) + return + + var/mob/living/carbon/human/human = victim + var/obj/item/item = source + + if(human.stat == DEAD && user.a_intent == INTENT_HARM) + var/obj/item/food/meat/human/newmeat = new /obj/item/food/meat/human(get_turf(human)) + newmeat.name = human.real_name + newmeat.name + newmeat.reagents.add_reagent("nutriment", (human.nutrition / 15) / 3) + human.reagents.trans_to(newmeat, round((human.reagents.total_volume) / 3, 1)) + human.add_mob_blood(human) + human.meatleft-- + + if(human.meatleft) + to_chat(user, "You hack off a chunk of meat from [human]!") + // fallthrough so we get side-effects like blood splatter and limb + // flyoff from human attacked_by while we still have a corpse around + return + human.send_item_attack_message(item, user) + + // Handle a few tiny things normally done in attack chain + user.do_attack_animation(human) + item.add_fingerprint(user) + if(item.hitsound) + playsound(get_turf(item), item.hitsound, item.get_clamped_volume(), TRUE, extrarange = item.stealthy_audio ? SILENCED_SOUND_EXTRARANGE : -1, falloff_distance = 0) + add_attack_logs(user, human, "Chopped up into meat with [item.name] ([uppertext(user.a_intent)])", human.ckey ? null : ATKLOG_ALMOSTALL) + to_chat(user, "You reduce [human] to a pile of meat!") + qdel(human) + return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 5a45e9a3d87..a875dce2b36 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -299,9 +299,6 @@ GLOBAL_DATUM_INIT(welding_sparks, /mutable_appearance, mutable_appearance('icons . += "Has [length(attached_bits)] bits attached." . += "Bits can be removed with Alt-Click." - if(HAS_TRAIT(src, TRAIT_BUTCHERS_HUMANS)) - . += "Can be used to butcher dead people into meat while on harm intent." - /obj/item/burn() if(!QDELETED(src)) var/turf/T = get_turf(src) diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index 357ac4ca247..60af27cd6ad 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -183,7 +183,7 @@ /obj/item/kitchen/knife/butcher/meatcleaver/Initialize(mapload) . = ..() - ADD_TRAIT(src, TRAIT_BUTCHERS_HUMANS, ROUNDSTART_TRAIT) + AddElement(/datum/element/butchers_humans) /obj/item/kitchen/knife/combat name = "combat knife" diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index e8215cd2c2e..a63bd7a852e 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -521,7 +521,7 @@ /obj/item/butcher_chainsaw/Initialize(mapload) . = ..() - ADD_TRAIT(src, TRAIT_BUTCHERS_HUMANS, ROUNDSTART_TRAIT) + AddElement(/datum/element/butchers_humans) AddComponent(/datum/component/two_handed, \ force_wielded = 40, \ force_unwielded = force, \ diff --git a/code/modules/food_and_drinks/food/foods/meat.dm b/code/modules/food_and_drinks/food/foods/meat.dm index d49ae88550d..95626d4c7d0 100644 --- a/code/modules/food_and_drinks/food/foods/meat.dm +++ b/code/modules/food_and_drinks/food/foods/meat.dm @@ -34,8 +34,6 @@ /obj/item/food/meat/human name = "-meat" - var/subjectname = "" - var/subjectjob = null tastes = list("salty meat" = 1) /obj/item/food/meat/slab/meatproduct diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 8ab535fd81a..128ecc4c037 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -462,24 +462,9 @@ emp_act return ..() /mob/living/carbon/human/attacked_by(obj/item/I, mob/living/user, def_zone) - if(!I || !user) + if(!I || !user || QDELETED(src)) return - if(HAS_TRAIT(I, TRAIT_BUTCHERS_HUMANS) && stat == DEAD && user.a_intent == INTENT_HARM) - var/obj/item/food/meat/human/newmeat = new /obj/item/food/meat/human(get_turf(loc)) - newmeat.name = real_name + newmeat.name - newmeat.subjectname = real_name - newmeat.subjectjob = job - newmeat.reagents.add_reagent("nutriment", (nutrition / 15) / 3) - reagents.trans_to(newmeat, round((reagents.total_volume) / 3, 1)) - add_mob_blood(src) - --meatleft - to_chat(user, "You hack off a chunk of meat from [name]") - if(!meatleft) - add_attack_logs(user, src, "Chopped up into meat") - qdel(src) - return - var/obj/item/organ/external/affecting = get_organ(ran_zone(user.zone_selected)) // if the targeted limb doesn't exist, pick a new one at random so you don't have to swap target zone diff --git a/paradise.dme b/paradise.dme index 514f219cc13..b648f45c506 100644 --- a/paradise.dme +++ b/paradise.dme @@ -563,6 +563,7 @@ #include "code\datums\elements\atmos_requirements.dm" #include "code\datums\elements\body_temperature.dm" #include "code\datums\elements\bombable_turf.dm" +#include "code\datums\elements\butchers_humans.dm" #include "code\datums\elements\connect_loc.dm" #include "code\datums\elements\decal_element.dm" #include "code\datums\elements\earhealing.dm"