From a7d5e4cdcfc5e5d8f1351ddc25d64041fa55b225 Mon Sep 17 00:00:00 2001 From: Ashe Higgs Date: Sun, 25 Feb 2018 15:50:16 -0500 Subject: [PATCH 1/2] Refactors butchering to a component - item-based butchering effectiveness, speed, and chances (#35744) * Butchering component * auto-butchering based on toolspeed * Gives drills their butchering back * redoes toggles --- code/_onclick/item_attack.dm | 16 +++--- code/datums/components/butchering.dm | 52 +++++++++++++++++++ .../mecha/equipment/tools/mining_tools.dm | 19 ++++++- code/game/objects/items/holy_weapons.dm | 14 ++++- code/game/objects/items/kitchen.dm | 4 ++ code/game/objects/items/melee/misc.dm | 8 +++ code/game/objects/items/melee/transforming.dm | 6 ++- .../game/objects/items/stacks/sheets/glass.dm | 1 + code/game/objects/items/twohanded.dm | 20 ++++++- code/game/objects/items/weaponry.dm | 4 ++ .../changeling/powers/mutations.dm | 1 + code/modules/antagonists/cult/cult_items.dm | 8 +++ .../food_and_drinks/drinks/drinks/bottle.dm | 4 ++ code/modules/hydroponics/hydroitemdefines.dm | 8 +++ .../mining/equipment/kinetic_crusher.dm | 4 ++ code/modules/mining/equipment/mining_tools.dm | 4 ++ .../mining/lavaland/necropolis_chests.dm | 1 + code/modules/mob/living/carbon/carbon.dm | 2 - .../human/species_types/shadowpeople.dm | 6 ++- code/modules/mob/living/living.dm | 13 +---- code/modules/mob/living/living_defines.dm | 5 +- .../simple_animal/hostile/megafauna/drake.dm | 3 +- .../hostile/mining_mobs/goliath.dm | 4 +- .../living/simple_animal/hostile/mushroom.dm | 3 +- code/modules/paperwork/pen.dm | 10 ++++ .../projectiles/guns/energy/special.dm | 4 ++ code/modules/projectiles/guns/magic/staff.dm | 4 ++ code/modules/surgery/tools.dm | 8 +++ tgstation.dme | 1 + 29 files changed, 207 insertions(+), 30 deletions(-) create mode 100644 code/datums/components/butchering.dm diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 3368960da4..1fc40d3007 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -34,14 +34,18 @@ /mob/living/attackby(obj/item/I, mob/living/user, params) user.changeNext_move(CLICK_CD_MELEE) - if(user.a_intent == INTENT_HARM && stat == DEAD && butcher_results) //can we butcher it? - var/sharpness = I.is_sharp() - if(sharpness) + if(user.a_intent == INTENT_HARM && stat == DEAD && (butcher_results || guaranteed_butcher_results)) //can we butcher it? + GET_COMPONENT_FROM(butchering, /datum/component/butchering, I) + if(butchering && butchering.butchering_enabled) to_chat(user, "You begin to butcher [src]...") - playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1) - if(do_mob(user, src, 80/sharpness) && Adjacent(I)) - harvest(user) + playsound(loc, butchering.butcher_sound, 50, TRUE, -1) + if(do_mob(user, src, butchering.speed) && Adjacent(I)) + butchering.Butcher(user, src) return 1 + else if(I.is_sharp() && !butchering) //give sharp objects butchering functionality, for consistency + I.AddComponent(/datum/component/butchering, 80 * I.toolspeed) + attackby(I, user, params) //call the attackby again to refresh and do the butchering check again + return return I.attack(src, user) diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm new file mode 100644 index 0000000000..372fa8e283 --- /dev/null +++ b/code/datums/components/butchering.dm @@ -0,0 +1,52 @@ +/datum/component/butchering + var/speed = 80 //time in deciseconds taken to butcher something + var/effectiveness = 100 //percentage effectiveness; numbers above 100 yield extra drops + var/bonus_modifier = 0 //percentage increase to bonus item chance + var/butcher_sound = 'sound/weapons/slice.ogg' //sound played when butchering + var/butchering_enabled = TRUE + +/datum/component/butchering/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled) + if(_speed) + speed = _speed + if(_effectiveness) + effectiveness = _effectiveness + if(_bonus_modifier) + bonus_modifier = _bonus_modifier + if(_butcher_sound) + butcher_sound = _butcher_sound + if(disabled) + butchering_enabled = FALSE + +/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat) + var/turf/T = meat.drop_location() + var/final_effectiveness = effectiveness - meat.butcher_difficulty + var/bonus_chance = max(0, (final_effectiveness - 100) + bonus_modifier) //so 125 total effectiveness = 25% extra chance + for(var/V in meat.butcher_results) + var/obj/bones = V + var/amount = meat.butcher_results[bones] + for(var/_i in 1 to amount) + if(!prob(final_effectiveness)) + if(butcher) + to_chat(butcher, "You fail to harvest some of the [initial(bones.name)] from [meat].") + else if(prob(bonus_chance)) + if(butcher) + to_chat(butcher, "You harvest some extra [initial(bones.name)] from [meat]!") + for(var/i in 1 to 2) + new bones (T) + else + new bones (T) + meat.butcher_results.Remove(bones) //in case you want to, say, have it drop its results on gib + for(var/V in meat.guaranteed_butcher_results) + var/obj/sinew = V + var/amount = meat.guaranteed_butcher_results[sinew] + for(var/i in 1 to amount) + new sinew (T) + meat.guaranteed_butcher_results.Remove(sinew) + if(butcher) + meat.visible_message("[butcher] butchers [meat].") + ButcherEffects(meat) + meat.harvest(butcher) + meat.gib(FALSE, FALSE, TRUE) + +/datum/component/butchering/proc/ButcherEffects(mob/living/meat) //extra effects called on butchering, override this via subtypes + return diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index 6017515a63..16c0e62795 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -10,6 +10,10 @@ energy_drain = 10 force = 15 +/obj/item/mecha_parts/mecha_equipment/drill/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 50, 100) + /obj/item/mecha_parts/mecha_equipment/drill/action(atom/target) if(!action_checks(target)) return @@ -76,14 +80,25 @@ return 1 return 0 +/obj/item/mecha_parts/mecha_equipment/drill/attach(obj/mecha/M) + ..() + GET_COMPONENT_FROM(butchering, /datum/component/butchering, src) + butchering.butchering_enabled = TRUE + +/obj/item/mecha_parts/mecha_equipment/drill/detach(atom/moveto) + ..() + GET_COMPONENT_FROM(butchering, /datum/component/butchering, src) + butchering.butchering_enabled = FALSE + /obj/item/mecha_parts/mecha_equipment/drill/proc/drill_mob(mob/living/target, mob/user, var/drill_damage=80) target.visible_message("[chassis] drills [target] with [src].", \ "[chassis] drills [target] with [src].") add_logs(user, target, "attacked", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") if(target.stat == DEAD) add_logs(user, target, "gibbed", name) - if(target.butcher_results) - target.harvest(chassis)//Butcher the mob with our drill. + if(target.butcher_results.len || target.guaranteed_butcher_results.len) + GET_COMPONENT_FROM(butchering, /datum/component/butchering, src) + butchering.Butcher(chassis, target) else target.gib() else diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 88e2b40ad6..bf5eb84cdd 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -197,6 +197,10 @@ sharpness = IS_SHARP attack_verb = list("chopped", "sliced", "cut", "reaped") +/obj/item/nullrod/scythe/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 70, 110) //the harvest gives a high bonus chance + /obj/item/nullrod/scythe/vibro icon_state = "hfrequency0" item_state = "hfrequency1" @@ -290,6 +294,10 @@ attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' +/obj/item/nullrod/chainsaw/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 30, 100, 0, hitsound) + /obj/item/nullrod/clown icon = 'icons/obj/wizard.dmi' icon_state = "clownrender" @@ -356,6 +364,10 @@ w_class = WEIGHT_CLASS_HUGE sharpness = IS_SHARP +/obj/item/nullrod/armblade/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 80, 70) + /obj/item/nullrod/armblade/tentacle name = "unholy blessing" icon_state = "tentacle" @@ -414,7 +426,7 @@ /obj/item/nullrod/tribal_knife/Initialize(mapload) . = ..() START_PROCESSING(SSobj, src) - + AddComponent(/datum/component/butchering, 50, 100) /obj/item/nullrod/tribal_knife/Destroy() STOP_PROCESSING(SSobj, src) diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index c626ba44cc..abdca9e77a 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -73,6 +73,10 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) var/bayonet = FALSE //Can this be attached to a gun? +/obj/item/kitchen/knife/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 80 - force, 100, force - 10) //bonus chance increases depending on force + /obj/item/kitchen/knife/attack(mob/living/carbon/M, mob/living/carbon/user) if(user.zone_selected == "eyes") if(user.has_trait(TRAIT_CLUMSY) && prob(50)) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 3fbb5111b7..68cf364c31 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -44,6 +44,10 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") sharpness = IS_SHARP +/obj/item/melee/synthetic_arm_blade/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 60, 80) //very imprecise + /obj/item/melee/sabre name = "officer's sabre" desc = "An elegant weapon, its monomolecular edge is capable of cutting through flesh and bone with ease." @@ -63,6 +67,10 @@ hitsound = 'sound/weapons/rapierhit.ogg' materials = list(MAT_METAL = 1000) +/obj/item/melee/sabre/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 30, 95, 5) //fast and effective, but as a sword, it might damage the results. + /obj/item/melee/sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) if(attack_type == PROJECTILE_ATTACK) final_block_chance = 0 //Don't bring a sword to a gunfight diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm index 86944813ed..d10d02aad7 100644 --- a/code/game/objects/items/melee/transforming.dm +++ b/code/game/objects/items/melee/transforming.dm @@ -1,4 +1,4 @@ -/obj/item/melee/transforming //TODO: make transforming energy weapons a subtype of this +/obj/item/melee/transforming var/active = FALSE var/force_on = 30 //force when active var/faction_bonus_force = 0 //Bonus force dealt against certain factions @@ -21,6 +21,8 @@ else if(attack_verb_off.len) attack_verb = attack_verb_off + if(is_sharp()) + AddComponent(/datum/component/butchering, 50, 100, 0, hitsound, active) /obj/item/melee/transforming/attack_self(mob/living/carbon/user) if(transform_weapon(user)) @@ -59,6 +61,8 @@ attack_verb = attack_verb_off icon_state = initial(icon_state) w_class = initial(w_class) + GET_COMPONENT_FROM(butchering, /datum/component/butchering, src) + butchering.butchering_enabled = active transform_messages(user, supress_message_text) add_fingerprint(user) return TRUE diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 182522cd09..b51eba5b6a 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -251,6 +251,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( /obj/item/shard/Initialize() . = ..() AddComponent(/datum/component/caltrop, force) + AddComponent(/datum/component/butchering, 150, 65) icon_state = pick("large", "medium", "small") switch(icon_state) if("small") diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index 8962e7248d..8ae0508492 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -234,6 +234,10 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) resistance_flags = FIRE_PROOF +/obj/item/twohanded/fireaxe/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 100, 80, hitsound) //axes are not known for being precision butchering tools + /obj/item/twohanded/fireaxe/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "fireaxe[wielded]" return @@ -470,6 +474,10 @@ var/obj/item/grenade/explosive = null var/war_cry = "AAAAARGH!!!" +/obj/item/twohanded/spear/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 100, 70) //decent in a pinch, but pretty bad. + /obj/item/twohanded/spear/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins to sword-swallow \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") if(explosive) @@ -562,6 +570,10 @@ actions_types = list(/datum/action/item_action/startchainsaw) var/on = FALSE +/obj/item/twohanded/required/chainsaw/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 30, 100, 0, 'sound/weapons/chainsawhit.ogg', TRUE) + /obj/item/twohanded/required/chainsaw/suicide_act(mob/living/carbon/user) if(on) user.visible_message("[user] begins to tear [user.p_their()] head off with [src]! It looks like [user.p_theyre()] trying to commit suicide!") @@ -580,8 +592,10 @@ force = on ? force_on : initial(force) throwforce = on ? force_on : initial(force) icon_state = "chainsaw_[on ? "on" : "off"]" + GET_COMPONENT_FROM(butchering, /datum/component/butchering, src) + butchering.butchering_enabled = on - if(hitsound == "swing_hit") + if(on) hitsound = 'sound/weapons/chainsawhit.ogg' else hitsound = "swing_hit" @@ -733,6 +747,10 @@ slot_flags = SLOT_BACK hitsound = 'sound/weapons/bladeslice.ogg' +/obj/item/twohanded/vibro_weapon/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 20, 105) + /obj/item/twohanded/vibro_weapon/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) if(wielded) final_block_chance *= 2 diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index c476611ff9..2d82c3829b 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -66,6 +66,10 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF +/obj/item/claymore/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 40, 105) + /obj/item/claymore/suicide_act(mob/user) user.visible_message("[user] is falling on [src]! It looks like [user.p_theyre()] trying to commit suicide!") return(BRUTELOSS) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index dce13f0aaa..d176de0ccd 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -166,6 +166,7 @@ loc.visible_message("A grotesque blade forms around [loc.name]\'s arm!", "Our arm twists and mutates, transforming it into a deadly blade.", "You hear organic matter ripping and tearing!") if(synthetic) can_drop = TRUE + AddComponent(/datum/component/butchering, 60, 80) /obj/item/melee/arm_blade/afterattack(atom/target, mob/user, proximity) if(!proximity) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 459aaa9f2d..bfbdb2fa94 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -45,6 +45,9 @@ hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "rended") +/obj/item/melee/cultblade/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 40, 100) /obj/item/melee/cultblade/attack(mob/living/target, mob/living/carbon/human/user) if(!iscultist(user)) @@ -112,6 +115,7 @@ set_light(4) jaunt = new(src) linked_action = new(src) + AddComponent(/datum/component/butchering, 50, 80) /obj/item/twohanded/required/cult_bastard/examine(mob/user) if(contents.len) @@ -662,6 +666,10 @@ hitsound = 'sound/weapons/bladeslice.ogg' var/datum/action/innate/cult/spear/spear_act +/obj/item/twohanded/cult_spear/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 100, 90) + /obj/item/twohanded/cult_spear/Destroy() if(spear_act) qdel(spear_act) diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index 407870073d..821b09ae1a 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -129,6 +129,10 @@ var/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken") sharpness = IS_SHARP +/obj/item/broken_bottle/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 200, 55) + /obj/item/reagent_containers/food/drinks/bottle/gin name = "Griffeater gin" desc = "A bottle of high quality gin, produced in the New London Space Station." diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm index 3372b70817..77a69f0475 100644 --- a/code/modules/hydroponics/hydroitemdefines.dm +++ b/code/modules/hydroponics/hydroitemdefines.dm @@ -90,6 +90,10 @@ hitsound = 'sound/weapons/bladeslice.ogg' sharpness = IS_SHARP +/obj/item/hatchet/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 70, 100) + /obj/item/hatchet/suicide_act(mob/user) user.visible_message("[user] is chopping at [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(src, 'sound/weapons/bladeslice.ogg', 50, 1, -1) @@ -113,6 +117,10 @@ hitsound = 'sound/weapons/bladeslice.ogg' var/swiping = FALSE +/obj/item/scythe/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 90, 105) + /obj/item/scythe/suicide_act(mob/user) user.visible_message("[user] is beheading [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!") if(iscarbon(user)) diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 0b02516c0e..2843c22038 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -28,6 +28,10 @@ var/detonation_damage = 50 var/backstab_bonus = 30 +/obj/item/twohanded/required/kinetic_crusher/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 60, 110) //technically it's huge and bulky, but this provides an incentive to use it + /obj/item/twohanded/required/kinetic_crusher/Destroy() QDEL_LIST(trophies) return ..() diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index 581c47b83f..3e241fbc72 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -105,6 +105,10 @@ attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked") sharpness = IS_SHARP +/obj/item/shovel/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 150, 40) //it's sharp, so it works, but barely. + /obj/item/shovel/suicide_act(mob/living/user) user.visible_message("[user] begins digging their own grave! It looks like [user.p_theyre()] trying to commit suicide!") if(use_tool(user, user, 30, volume=50)) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 442a2aa2dc..8ad0c97c6a 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -671,6 +671,7 @@ spirits = list() START_PROCESSING(SSobj, src) GLOB.poi_list |= src + AddComponent(/datum/component/butchering, 150, 90) /obj/item/melee/ghost_sword/Destroy() for(var/mob/dead/observer/G in spirits) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index c38799e9b4..e5feb5c6c1 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -789,8 +789,6 @@ if(organs_amt) to_chat(user, "You retrieve some of [src]\'s internal organs!") - ..() - /mob/living/carbon/ExtinguishMob() for(var/X in get_equipped_items()) var/obj/item/I = X diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index 3d5d2ccbe5..9357855191 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -162,7 +162,7 @@ //Weapon /obj/item/light_eater - name = "light eater" + name = "light eater" //as opposed to heavy eater icon_state = "arm_blade" item_state = "arm_blade" force = 25 @@ -173,6 +173,10 @@ w_class = WEIGHT_CLASS_HUGE sharpness = IS_SHARP +/obj/item/light_eater/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 80, 70) + /obj/item/light_eater/afterattack(atom/movable/AM, mob/user, proximity) if(!proximity) return diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 0a89ad1f11..c78d8b19d7 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -773,17 +773,8 @@ /mob/living/proc/get_permeability_protection() return 0 -/mob/living/proc/harvest(mob/living/user) - if(QDELETED(src)) - return - if(butcher_results) - var/atom/Tsec = drop_location() - for(var/path in butcher_results) - for(var/i = 1; i <= butcher_results[path];i++) - new path(Tsec) - butcher_results.Remove(path) //In case you want to have things like simple_animals drop their butcher results on gib, so it won't double up below. - visible_message("[user] butchers [src].") - gib(0, 0, 1) +/mob/living/proc/harvest(mob/living/user) //used for extra objects etc. in butchering + return /mob/living/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE) if(incapacitated()) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index b56c7ff613..8ba5449b8e 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -65,7 +65,10 @@ var/last_bumped = 0 var/unique_name = 0 //if a mob's name should be appended with an id when created e.g. Mob (666) - var/list/butcher_results = null + var/list/butcher_results = null //these will be yielded from butchering with a probability chance equal to the butcher item's effectiveness + var/list/guaranteed_butcher_results = null //these will always be yielded from butchering + var/butcher_difficulty = 0 //effectiveness prob. is modified negatively by this amount; positive numbers make it more difficult, negative ones make it easier + var/hellbound = 0 //People who've signed infernal contracts are unrevivable. var/list/weather_immunities = list() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 9b8035e790..702c8c8425 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -53,7 +53,8 @@ Difficulty: Medium pixel_x = -16 crusher_loot = list(/obj/structure/closet/crate/necropolis/dragon/crusher) loot = list(/obj/structure/closet/crate/necropolis/dragon) - butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30) + butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30) + guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/ashdrake = 10) var/swooping = NONE var/swoop_cooldown = 0 medal_type = BOSS_MEDAL_DRAKE diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm index e06cce6d3e..979c155249 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm @@ -86,7 +86,8 @@ throw_message = "does nothing to the tough hide of the" pre_attack_icon = "goliath2" crusher_loot = /obj/item/crusher_trophy/goliath_tentacle - butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/goliath = 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2) + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/goliath = 2, /obj/item/stack/sheet/bone = 2) + guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/goliath_hide = 1) loot = list() stat_attack = UNCONSCIOUS robust_searching = 1 @@ -111,6 +112,7 @@ throw_message = "does nothing to the rocky hide of the" loot = list(/obj/item/stack/sheet/animalhide/goliath_hide) //A throwback to the asteroid days butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/goliath = 2, /obj/item/stack/sheet/bone = 2) + guaranteed_butcher_results = list() crusher_drop_mod = 30 wander = FALSE var/list/cached_tentacle_turfs diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index 01d6c427e8..dbaa8ab5fa 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -63,7 +63,7 @@ . = ..() /mob/living/simple_animal/hostile/mushroom/CanAttack(atom/the_target) // Mushroom-specific version of CanAttack to handle stupid attack_same = 2 crap so we don't have to do it for literally every single simple_animal/hostile because this shit never gets spawned - if(!the_target || isturf(the_target) || istype(the_target, /atom/movable/lighting_object)) + if(!the_target || isturf(the_target) || istype(the_target, /atom/movable/lighting_object)) return FALSE if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it @@ -188,4 +188,3 @@ S.reagents.add_reagent("mushroomhallucinogen", powerlevel) S.reagents.add_reagent("omnizine", powerlevel) S.reagents.add_reagent("synaptizine", powerlevel) - qdel(src) diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 118c69b404..f54b1742fe 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -90,6 +90,10 @@ "Command Blue" = "pen-fountain-cb" ) +/obj/item/pen/fountain/captain/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 200, 115) //the pen is mightier than the sword + /obj/item/pen/fountain/captain/reskin_obj(mob/M) ..() if(current_skin) @@ -178,6 +182,10 @@ attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") //these wont show up if the pen is off var/on = FALSE +/obj/item/pen/edagger/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 60, 100, 0, 'sound/weapons/blade1.ogg', TRUE) + /obj/item/pen/edagger/attack_self(mob/living/user) if(on) on = FALSE @@ -199,6 +207,8 @@ throwforce = 35 playsound(user, 'sound/weapons/saberon.ogg', 5, 1) to_chat(user, "[src] is now active.") + GET_COMPONENT_FROM(butchering, /datum/component/butchering, src) + butchering.butchering_enabled = on update_icon() /obj/item/pen/edagger/update_icon() diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 19308c812f..3d9408bcca 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -131,6 +131,10 @@ tool_behaviour = TOOL_WELDER toolspeed = 0.7 //plasmacutters can be used as welders, and are faster than standard welders +/obj/item/gun/energy/plasmacutter/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 25, 105, 0, 'sound/weapons/plasma_cutter.ogg') + /obj/item/gun/energy/plasmacutter/examine(mob/user) ..() if(cell) diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm index 86a2f8d4c1..c268c15272 100644 --- a/code/modules/projectiles/guns/magic/staff.dm +++ b/code/modules/projectiles/guns/magic/staff.dm @@ -86,6 +86,10 @@ sharpness = IS_SHARP max_charges = 4 +/obj/item/gun/magic/staff/spellblade/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 15, 125, 0, hitsound) + /obj/item/gun/magic/staff/spellblade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) if(attack_type == PROJECTILE_ATTACK) final_block_chance = 0 diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 310513326a..997c4e476d 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -112,6 +112,10 @@ hitsound = 'sound/weapons/bladeslice.ogg' sharpness = IS_SHARP_ACCURATE +/obj/item/scalpel/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 80 * toolspeed, 100, 0) + /obj/item/scalpel/augment name = "toolarm scalpel" desc = "Ultra-sharp blade attached directly to your bone for extra-accuracy." @@ -153,6 +157,10 @@ attack_verb = list("attacked", "slashed", "sawed", "cut") sharpness = IS_SHARP +/obj/item/circular_saw/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 40 * toolspeed, 100, 5, 'sound/weapons/circsawhit.ogg') //saws are very accurate and fast at butchering + /obj/item/circular_saw/augment name = "toolarm circular saw" desc = "A small but very fast spinning saw. Edges dulled to prevent accidental cutting inside of the surgeon." diff --git a/tgstation.dme b/tgstation.dme index a49437ef9d..050f1e7213 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -342,6 +342,7 @@ #include "code\datums\brain_damage\split_personality.dm" #include "code\datums\components\_component.dm" #include "code\datums\components\archaeology.dm" +#include "code\datums\components\butchering.dm" #include "code\datums\components\caltrop.dm" #include "code\datums\components\chasm.dm" #include "code\datums\components\cleaning.dm"