diff --git a/cev_eris.dme b/cev_eris.dme index 7ce2e1a32fe..58c2aa81850 100644 --- a/cev_eris.dme +++ b/cev_eris.dme @@ -406,6 +406,7 @@ #include "code\datums\autolathe\tools.dm" #include "code\datums\changelog\changelog.dm" #include "code\datums\components\_component.dm" +#include "code\datums\components\butchering.dm" #include "code\datums\components\clothing_sanity_protection.dm" #include "code\datums\components\fabric.dm" #include "code\datums\components\jamming.dm" diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index dffaa2ad715..8198ca278ff 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -64,6 +64,8 @@ GLOBAL_VAR_INIT(refid_filter, TYPEID(filter(type="angular_blur"))) #define isgolem(A) istype(A, /mob/living/carbon/superior_animal/golem) +#define isspider(A) istype(A, /mob/living/carbon/superior_animal/giant_spider) + #define isbrain(A) istype(A, /mob/living/carbon/brain) #define ishuman(A) istype(A, /mob/living/carbon/human) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 8c1feb98bf9..33f9e15cece 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -255,3 +255,27 @@ GLOBAL_REAL_VAR(list/voice_type2sound = list( ///Managed global that is a reference to the real global GLOBAL_LIST_INIT(voice_type2sound_ref, voice_type2sound) + +//butchering defines +//defines for base success chance +#define BUTCHER_IMPOSSIBLE 5 +#define BUTCHER_VERY_HARD 10 +#define BUTCHER_HARD 25 +#define BUTCHER_CHALLENGING 35 +#define BUTCHER_DIFFICULT 45 +#define BUTCHER_NORMAL 55 +#define BUTCHER_EASY 65 +#define BUTCHER_VERY_EASY 80 +#define BUTCHER_EFFORTLESS 100//still technically possible to fail with terrible tool + 0 bio, so not 'zero' + +/** + * divisor for BIO effect on butchering + * values of bio above this will improve butchering chances, values below will dmg it + */ +#define BUTCHER_BIO_DIVISOR 25 + +/** + * the base chance of a butchery going wrong and triggering a hazard effect + * increased by 10 each time you fail to extract an item + */ +#define BUTCHERING_HAZARD_CHANCE 5 diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm new file mode 100644 index 00000000000..27e7f682c91 --- /dev/null +++ b/code/datums/components/butchering.dm @@ -0,0 +1,141 @@ +/datum/component/butchering + /// Whether or not this component can be used to butcher currently. Used to temporarily disable an existing butcher component for later + var/butchering_enabled = TRUE + + /// Whether or not this component is compatible with blunt tools. + var/can_be_blunt = FALSE + + // Chance of triggering an additional hazard effect when butchering an animal. + var/hazard_chance = BUTCHERING_HAZARD_CHANCE + +/datum/component/butchering/Initialize( + disabled = FALSE, + can_be_blunt = FALSE, +) + if(disabled) + src.butchering_enabled = FALSE + src.can_be_blunt = can_be_blunt + if(isitem(parent)) + RegisterSignal(parent, COMSIG_IATTACK, PROC_REF(onItemAttack)) + RegisterSignal(parent, COMSIG_APPVAL, PROC_REF(onStatusChange)) + +///checks if we can butcher, and intercepts the attack chain if we successfully do so +/datum/component/butchering/proc/onItemAttack(atom/target, mob/living/user, params) + SIGNAL_HANDLER + var/obj/item/ourparent + if(isitem(parent)) + ourparent = parent + + if(!(user.a_intent == I_HURT))//are we on harm intent? + return + + if(isliving(target)) + var/mob/living/ourmob = target + if(ourmob.stat == DEAD && (ourmob.butcher_results)) //can we butcher it? + if(butchering_enabled && (can_be_blunt || ourparent.sharp)) + INVOKE_ASYNC(src, PROC_REF(startButcher), ourparent, ourmob, user) + return TRUE //ends attack chain, so all we do is butcher + return + +///handles the use tool containing our butchering action. needed since signal_handler procs hate do afters +/datum/component/butchering/proc/startButcher(obj/item/source, mob/living/meat, mob/living/user) + to_chat(user, span_notice("You begin to butcher \the [meat]...")) + var/needed_quality = QUALITY_CUTTING + if(!source.has_quality(QUALITY_CUTTING)) + needed_quality = null + if(source.use_tool(user, meat, WORKTIME_NORMAL, needed_quality, FAILCHANCE_NORMAL, required_stat = STAT_BIO)) + on_butchering(user, meat, source) +/** + * Handles a user butchering a target + * + * Arguments: + * - [butcher][/mob/living]: The mob doing the butchering + * - [meat][/mob/living]: The mob being butchered + * - [source][/obj/item]: The item holding our component, expressly typed + */ +/datum/component/butchering/proc/on_butchering(mob/living/butcher, mob/living/meat, obj/item/source) + //our final items to spawn + var/list/butchered = list() + //did we fail to extract something? + var/mulched + var/turf/dropturf = get_turf(meat) + var/bio = butcher.stats.getStat(STAT_BIO) + //mult to success chance based on tool quality + var/toolpowr = 0.5 + + if(source.has_quality(QUALITY_CUTTING))//otherwise, we're working with something stupid like a glass shard or a beartrap(truly, advanced cutting tool) + toolpowr = round((source.get_tool_quality(QUALITY_CUTTING) / 10)) + + if(!meat.butcher_results) + log_runtime(" [meat.type] was butchered without any possible butcher results.") + meat.gib() + + //for getting the dialogue hinting at relative power + var/msgpowr = toolpowr * (max((bio / BUTCHER_BIO_DIVISOR), 0.25)) + switch(msgpowr) + if(0 to 0.8)//go get an actual knife you gross-ass roundstart vagabond + butcher.visible_message(span_bolddanger("[butcher] can't get anywhere with this tool! Instead, they rip \the [meat] to shreds like an animal!")) + if(0.9 to 3.5) + butcher.visible_message(span_danger("[butcher] messily chops up \the [meat]!")) + if(3.6 to 6) + butcher.visible_message(span_danger("[butcher] carefully butchers \the [meat].")) + if(6.1 to 99) + butcher.visible_message(span_notice("[butcher] precisely dissects \the [meat].")) + + for(var/thing in meat.butcher_results) + //get the assoc list to get our stored info + var/list/resultlist = meat.butcher_results[thing] + //pull out the number of drops + var/number = resultlist[1] + //pull out the base percentage of awarding this result + var/difficulty = resultlist[2] + //takes difficulty and multiplies it by tool and bio stat to get final chance + var/trueprob = clamp((difficulty * toolpowr) * max((bio / BUTCHER_BIO_DIVISOR), 0.25), 1, 100) + for(var/result in 1 to number) + if(prob(trueprob)) + butchered += thing + else + mulched++ + hazard_chance = min(hazard_chance + 10, 100)//chance of complications increases for each item you fail to harvest + + if(mulched) + to_chat(butcher, span_warning("You [LAZYLEN(meat.butcher_results) <= mulched ? "completely destroyed all of" : "lost some of"] the harvest from \the [meat].")) + if(LAZYLEN(butchered)) + for(var/reward in butchered) + var/obj/item/ourdrop = new reward(dropturf) + ourdrop.name = "[meat.name] [ourdrop.name]" + if(istype(ourdrop, /obj/item/reagent_containers/food/snacks)) + var/obj/item/reagent_containers/food/snacks/ourmeat = ourdrop + ourmeat.food_quality = (ourmeat.food_quality * ((bio + 15) / 15) * clamp((toolpowr / 15), 0.25, 4)) + + + //try to invoke a hazard effect on the butcher + if(meat.butchery_hazard && prob(hazard_chance)) + butcher.visible_message(span_danger("While cutting up \the [meat], [butcher]'s hand slips..."), span_danger("While cutting up \the [meat], your hand slips...")) + meat.butchery_fail(butcher) + + //let's finish up. + meat.drop_embedded() + meat.gib() + if(meat.client)//if a player just got hardgibbed, tattle + message_admins("[meat] ([key_name(meat)]) was butchered for meat by [butcher] ([key_name(butcher)]) [ADMIN_JMP(butcher)].") + +///Enables the butchering mechanic. +/datum/component/butchering/proc/enable_butchering(datum/source) + SIGNAL_HANDLER + butchering_enabled = TRUE + +///Disables the butchering mechanic. +/datum/component/butchering/proc/disable_butchering(datum/source) + SIGNAL_HANDLER + butchering_enabled = FALSE + +///signal check to see if our holder is still sharp, for variable butchering items. If not, shut down the component till sharpness comes back. +/datum/component/butchering/proc/onStatusChange(atom/holder) + SIGNAL_HANDLER + if(isitem(holder)) + var/obj/item/itemholder = holder + if(!itemholder.sharp && !can_be_blunt) + disable_butchering() + else if(itemholder.sharp && butchering_enabled == FALSE) + enable_butchering() diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm index 6328690f2d8..ed6c0e3fd7a 100644 --- a/code/game/jobs/job/civilian.dm +++ b/code/game/jobs/job/civilian.dm @@ -21,6 +21,7 @@ wage = WAGE_NONE // Makes his own money department_account_access = TRUE stat_modifiers = list( + STAT_BIO = 20, STAT_ROB = 15, STAT_TGH = 15, STAT_VIG = 15, @@ -59,8 +60,9 @@ wage = WAGE_NONE //They should get paid by the club owner, otherwise you know what to do. department_account_access = TRUE stat_modifiers = list( + STAT_BIO = 25, STAT_ROB = 10, - STAT_TGH = 10, + STAT_TGH = 5, STAT_VIG = 5, ) outfit_type = /decl/hierarchy/outfit/job/service/waiter diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index ede77a8a344..e3c920aaada 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -186,17 +186,17 @@ var/meat_amount = occupant.mob_size / 2 var/meat_type = /obj/item/reagent_containers/food/snacks/meat - if(issuperioranimal(occupant)) - var/mob/living/carbon/superior_animal/S = occupant - meat_type = S.meat_type + if(issuperioranimal(occupant) || isanimal(occupant)) + if(occupant.butcher_results)//nab a meat from the occupant's butcher results. Otherwise use default meat + for(var/possiblemeat in occupant.butcher_results) + if(istype(possiblemeat, /obj/item/reagent_containers/food/snacks/meat)) + meat_type = possiblemeat + break else if(iscarbon(occupant)) var/mob/living/carbon/C = occupant meat_type = C.species.meat_type if(occupant.stats.getPerk(PERK_SURVIVOR)) meat_type = /obj/item/reagent_containers/food/snacks/meat/pork - else if(isanimal(occupant)) - var/mob/living/simple_animal/A = occupant - meat_type = A.meat_type for(var/i in 1 to meat_amount) var/obj/item/reagent_containers/food/snacks/meat/new_meat = new meat_type(src) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 5cb260454cb..1953bbbc933 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -162,6 +162,8 @@ if(chameleon_type) verbs.Add(/obj/item/proc/set_chameleon_appearance) tact_visual = new /obj/effect/effect/melee/alert + if(sharp && !isProjectile(src))//any item with sharpness on spawn gets butchering + AddComponent(/datum/component/butchering, FALSE, FALSE) . = ..() /obj/item/Destroy(force) diff --git a/code/game/objects/items/weapons/tools/mods/_upgrades.dm b/code/game/objects/items/weapons/tools/mods/_upgrades.dm index 6fbf1edb226..e2d6fcd02e7 100644 --- a/code/game/objects/items/weapons/tools/mods/_upgrades.dm +++ b/code/game/objects/items/weapons/tools/mods/_upgrades.dm @@ -300,6 +300,8 @@ T.max_upgrades += tool_upgrades[UPGRADE_MAXUPGRADES] if(tool_upgrades[UPGRADE_SHARP]) T.sharp = tool_upgrades[UPGRADE_SHARP] + if(!T.GetComponent(/datum/component/butchering)) + T.AddComponent(/datum/component/butchering, FALSE, FALSE) if(tool_upgrades[UPGRADE_COLOR]) T.color = tool_upgrades[UPGRADE_COLOR] if(tool_upgrades[UPGRADE_ITEMFLAGPLUS]) diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm index d7e1b7e0e66..2adc05f0243 100644 --- a/code/modules/holodeck/HolodeckObjects.dm +++ b/code/modules/holodeck/HolodeckObjects.dm @@ -487,8 +487,7 @@ icon_dead = "holo4" alpha = 127 icon_gib = null - meat_amount = 0 - meat_type = null + butcher_results = null /mob/living/simple_animal/hostile/carp/holodeck/New() ..() diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index e8b575eea3c..84174cd6108 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -16,9 +16,12 @@ var/potency = -1 -/obj/item/reagent_containers/food/snacks/grown/New(newloc,planttype) +/obj/item/reagent_containers/food/snacks/grown/New(newloc,planttype, quality) ..() + if(quality) + food_quality = quality + if(!dried_type) dried_type = type src.pixel_x = rand(-5, 5) diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm index fff4ce431d1..cf3e0061b5d 100644 --- a/code/modules/hydroponics/seed.dm +++ b/code/modules/hydroponics/seed.dm @@ -748,7 +748,12 @@ if(has_mob_product) product = new has_mob_product(get_turf(user),name) else - product = new /obj/item/reagent_containers/food/snacks/grown(get_turf(user),name) + var/quality + if(user.stats.getStat(STAT_BIO)) + quality = clamp(1 * ((user.stats.getStat(STAT_BIO) + 15) / 15), 0, 10) + else//nuclear farmbot nerf + quality = -5 + product = new /obj/item/reagent_containers/food/snacks/grown(get_turf(user), name, quality) if(get_trait(TRAIT_PRODUCT_COLOUR)) if(!ismob(product)) product.color = get_trait(TRAIT_PRODUCT_COLOUR) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 3f5cde07345..4a51ee7e222 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -457,3 +457,22 @@ to_chat(usr, "Removed [rem_organ] from [src].") rem_organ.removed() qdel(rem_organ) + +/// checks if a location on a mob is protected from skin-contact effects. Returns null if no protection, or the protecting item if protected +/mob/living/carbon/proc/find_skin_protection(var/protection_zone) + var/obj/item/protecting_item + var/list/protection_items + if(!ishuman(src))//if human, check human inventory slots + var/mob/living/carbon/human/ashuman = src + protection_items = list(ashuman.head, ashuman.glasses, ashuman.wear_mask, ashuman.wear_suit, ashuman.w_uniform, ashuman.gloves, ashuman.shoes) + else //otherwise just check for a mask + protection_items = list(src.wear_mask) + + for(var/obj/item/ourcloth in protection_items) + if((ourcloth && ourcloth.body_parts_covered & protection_zone)) + if(!(ourcloth.item_flags & FLEXIBLEMATERIAL) && !(ourcloth.item_flags & AIRTIGHT))//flexible non-airtight items are porous and let liquids/gas through + protecting_item = ourcloth.name + break + return protecting_item + + diff --git a/code/modules/mob/living/carbon/superior_animal/defense.dm b/code/modules/mob/living/carbon/superior_animal/defense.dm index 0bd682f968c..4a0e59aeeea 100644 --- a/code/modules/mob/living/carbon/superior_animal/defense.dm +++ b/code/modules/mob/living/carbon/superior_animal/defense.dm @@ -1,20 +1,3 @@ -/mob/living/carbon/superior_animal/proc/harvest(mob/user) - var/actual_meat_amount = max(1,(meat_amount/2)) - if(meat_type && actual_meat_amount>0 && (stat == DEAD)) - drop_embedded() - for(var/i=0;i item.attack -> mob.resolve_item_attack -> item.apply_hit_effect diff --git a/code/modules/mob/living/carbon/superior_animal/giant_spider/giant_spider.dm b/code/modules/mob/living/carbon/superior_animal/giant_spider/giant_spider.dm index 51b9305ec5a..0a127bffcf6 100644 --- a/code/modules/mob/living/carbon/superior_animal/giant_spider/giant_spider.dm +++ b/code/modules/mob/living/carbon/superior_animal/giant_spider/giant_spider.dm @@ -24,8 +24,7 @@ move_to_delay = 5 turns_per_move = 5 see_in_dark = 10 - meat_type = /obj/item/reagent_containers/food/snacks/meat/spider - meat_amount = 3 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/spider = list(3, BUTCHER_NORMAL)) stop_automated_movement_when_pulled = 0 melee_damage_lower = 12 diff --git a/code/modules/mob/living/carbon/superior_animal/giant_spider/types/hunter.dm b/code/modules/mob/living/carbon/superior_animal/giant_spider/types/hunter.dm index a73dec49078..7645be9088f 100644 --- a/code/modules/mob/living/carbon/superior_animal/giant_spider/types/hunter.dm +++ b/code/modules/mob/living/carbon/superior_animal/giant_spider/types/hunter.dm @@ -10,6 +10,5 @@ melee_damage_upper = 20 poison_per_bite = 8 move_to_delay = 3 - meat_type = /obj/item/reagent_containers/food/snacks/meat/spider/hunter - meat_amount = 4 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/spider/hunter = list(3, BUTCHER_NORMAL)) rarity_value = 75 diff --git a/code/modules/mob/living/carbon/superior_animal/giant_spider/types/nurse.dm b/code/modules/mob/living/carbon/superior_animal/giant_spider/types/nurse.dm index 499dc3d0a8e..782477fff94 100644 --- a/code/modules/mob/living/carbon/superior_animal/giant_spider/types/nurse.dm +++ b/code/modules/mob/living/carbon/superior_animal/giant_spider/types/nurse.dm @@ -16,9 +16,8 @@ poison_per_bite = 3 var/atom/cocoon_target poison_type = "aranecolmin" - meat_type = /obj/item/reagent_containers/food/snacks/meat/spider/nurse + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/spider/nurse = list(3, BUTCHER_NORMAL)) move_to_delay = 4 - meat_amount = 3 rarity_value = 75 var/fed = 0 var/egg_inject_chance = 4 diff --git a/code/modules/mob/living/carbon/superior_animal/golem/golem.dm b/code/modules/mob/living/carbon/superior_animal/golem/golem.dm index 5147003260b..ca820261e7c 100644 --- a/code/modules/mob/living/carbon/superior_animal/golem/golem.dm +++ b/code/modules/mob/living/carbon/superior_animal/golem/golem.dm @@ -40,8 +40,7 @@ speak_chance = 5 see_in_dark = 10 - meat_type = null - meat_amount = 0 + butcher_results = null stop_automated_movement_when_pulled = 0 wander = FALSE viewRange = 8 diff --git a/code/modules/mob/living/carbon/superior_animal/roach/life.dm b/code/modules/mob/living/carbon/superior_animal/roach/life.dm index 9505409d66d..1de59729bba 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/life.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/life.dm @@ -91,12 +91,12 @@ // End message src.visible_message(span_warning("\The [src] finishes eating \the [eat_target], leaving only bones.")) // Get fed - fed += rand(1,tasty.meat_amount) + fed += rand(1,LAZYLEN(tasty.butcher_results)) if (isroach(tasty)) var/mob/living/carbon/superior_animal/roach/cannibalism = tasty fed += cannibalism.fed if(istype(src, /mob/living/carbon/superior_animal/roach/roachling)) - if(tasty.meat_amount >= 6)// ate a fuhrer or kaiser + if(istype(tasty, /mob/living/carbon/superior_animal/roach/kaiser) || istype(tasty, /mob/living/carbon/superior_animal/roach/fuhrer))// ate a fuhrer or kaiser var/mob/living/carbon/superior_animal/roach/roachling/bigboss = src bigboss.big_boss = TRUE clearEatTarget() diff --git a/code/modules/mob/living/carbon/superior_animal/roach/roach.dm b/code/modules/mob/living/carbon/superior_animal/roach/roach.dm index d7eda87832e..5b1bc69c21c 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/roach.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/roach.dm @@ -13,8 +13,7 @@ turns_per_move = 4 turns_since_move = 0 - meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat/kampfer - meat_amount = 2 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/kampfer = list(3, BUTCHER_NORMAL)) maxHealth = 10 health = 10 diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/benzin.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/benzin.dm index 3fe0fccf470..08c436941da 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/benzin.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/benzin.dm @@ -7,8 +7,7 @@ maxHealth = 25 health = 25 melee_damage_upper = 3 - meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat/benzin - meat_amount = 3 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/benzin = list(3, BUTCHER_DIFFICULT)) rarity_value = 15 diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/bluespace.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/bluespace.dm index f52dafbbae4..eca78014883 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/bluespace.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/bluespace.dm @@ -4,7 +4,7 @@ icon_state = "bluespaceroach" maxHealth = 25 health = 25 - meat_type = /obj/item/bluespace_crystal + butcher_results = list(/obj/item/bluespace_crystal = list(4, BUTCHER_CHALLENGING)) melee_damage_lower = 4 melee_damage_upper = 11 armor_divisor = ARMOR_PEN_MAX // Hits through armor @@ -91,3 +91,11 @@ do_teleport(src, T) return FALSE . = ..() + +/mob/living/carbon/superior_animal/roach/bluespace/butchery_fail(mob/living/butcher) + visible_message(span_danger("\the [src] flickers with unearthly light! Space warps horribly!")) + if(loc) + var/blast_radius = view(5, loc) + for(var/mob/living/victim as anything in blast_radius) + var/turf/randtarg = get_random_turf_in_range(src, 8, 1) + go_to_bluespace(get_turf(victim), 5, TRUE, victim, randtarg) diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/fuhrer.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/fuhrer.dm index d0a273d5bb1..29cec865840 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/fuhrer.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/fuhrer.dm @@ -17,9 +17,7 @@ extra_burrow_chance = 100 blattedin_revives_left = 0 //He only lives once, cuz he's huge - meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat/fuhrer - meat_amount = 6 - + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/fuhrer = list(6, BUTCHER_DIFFICULT)) sanity_damage = 1 rarity_value = 90 diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/hunter.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/hunter.dm index e4c7e03b94a..e5130115a24 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/hunter.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/hunter.dm @@ -15,8 +15,8 @@ attacktext = list("slashed", "rended", "diced") - meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat/jager - meat_amount = 3 + + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/jager = list(4, BUTCHER_DIFFICULT)) rarity_value = 11.25 // Armor related variables - jager jacket diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/kaiser.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/kaiser.dm index 97453313386..50d5493d944 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/kaiser.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/kaiser.dm @@ -32,8 +32,8 @@ Has ability of every roach. blattedin_revives_left = 0 - meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat/kaiser - meat_amount = 15 + //big enough to feed a whole clan of vagabonds + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/kaiser = list(14, BUTCHER_DIFFICULT)) sanity_damage = 3 ranged = 1 // RUN, COWARD! diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/nanites.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/nanites.dm index d5b0dcff61f..90fd276c74b 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/nanites.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/nanites.dm @@ -3,8 +3,7 @@ desc = "A deformed mess of a roach that is covered in metallic outcrops and formations. It seems to have a production center on its thorax." icon_state = "naniteroach" - meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat/kraftwerk - meat_amount = 3 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/kraftwerk = list(4, BUTCHER_DIFFICULT)) turns_per_move = 1 maxHealth = 30 health = 30 @@ -72,6 +71,11 @@ overseer?.casualties.Remove(src) overseer = null +/mob/living/carbon/superior_animal/roach/nanite/butchery_fail(mob/living/butcher) + butcher.visible_message(span_danger("[butcher] accidentally connects two wires! \The [src] vomits forth a swarm!"), span_userdanger("You accidentally connects two wires! With a spark, \the [src] vomits forth a swarm!")) + for(var/mob in 1 to rand(2,5)) + mob = new /mob/living/simple_animal/hostile/naniteswarm(get_turf(src), src) + /mob/living/simple_animal/hostile/naniteswarm name = "nanite infested miniroach cluster" desc = "A swarm of disgusting locusts infested with nanomachines." diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/roachling.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/roachling.dm index 32e6bb1c07a..e93d9fc0d49 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/roachling.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/roachling.dm @@ -14,7 +14,7 @@ mob_size = MOB_SMALL * 0.8 // 8 - meat_amount = 1 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/kampfer = list(1, BUTCHER_EASY)) probability_egg_laying = 0 var/amount_grown = 0 diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/support.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/support.dm index a82ef106a47..d08e0db9c50 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/support.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/support.dm @@ -7,8 +7,7 @@ health = 20 melee_damage_lower = 2 melee_damage_upper = 4 - meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat/seuche - meat_amount = 3 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/seuche = list(4, BUTCHER_DIFFICULT)) rarity_value = 11.25 var/datum/reagents/gas_sac //Stores gas. Can't use the default reagents since that is now bloodstream @@ -77,3 +76,9 @@ overseer?.removeHealer(src) // Healer Seuche overseer?.casualties.Remove(src) overseer = null + +/mob/living/carbon/superior_animal/roach/support/butchery_fail(mob/living/butcher) + butcher.visible_message(span_danger("[butcher] accidentally cuts into a sac inside \the [src], causing gas to spill into the air!"), span_userdanger("Your hands slips while cutting the [src]... a foul green smoke sprays outwards!")) + gas_sac.add_reagent("blattedin", 20)//makes sure it has enough gas to actually cast it + gas_attack() + return diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/tank.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/tank.dm index 7a657a1d468..1728a885572 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/tank.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/tank.dm @@ -2,14 +2,14 @@ name = "Panzer Roach" desc = "A monstrous, dog-sized cockroach. This one looks more robust than others." icon_state = "panzer" - meat_amount = 4 turns_per_move = 2 maxHealth = 45 health = 45 move_to_delay = 6 mob_size = MOB_SMALL * 1.5 // 15 density = TRUE - meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat/panzer + //beefy boy + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat/panzer = list(5, BUTCHER_DIFFICULT)) rarity_value = 22.5 attacktext = list("slammed into", "pounded into", "crushed") diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/toxic.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/toxic.dm index 910f00d182f..e223cd009c2 100644 --- a/code/modules/mob/living/carbon/superior_animal/roach/types/toxic.dm +++ b/code/modules/mob/living/carbon/superior_animal/roach/types/toxic.dm @@ -3,7 +3,6 @@ desc = "A hulking beast of green, congealed waste. It has an enlarged salivatory gland for lobbing projectiles." icon_state = "radioactiveroach" - meat_amount = 3 turns_per_move = 1 maxHealth = 40 health = 40 @@ -72,3 +71,9 @@ overseer?.removeRanged(src) // Ranged Gestrahlte overseer?.casualties.Remove(src) overseer = null + +/mob/living/carbon/superior_animal/roach/toxic/butchery_fail(mob/living/butcher) + ..() + for(var/num in rand(2,5)) + var/obj/item/projectile/roach_spit/ourspit = new /obj/item/projectile/roach_spit(src.loc) + ourspit.launch(src.loc, pick(SOUTH, NORTH, WEST, EAST, SOUTHEAST, SOUTHWEST, NORTHEAST, NORTHWEST)) diff --git a/code/modules/mob/living/carbon/superior_animal/stalker/stalker.dm b/code/modules/mob/living/carbon/superior_animal/stalker/stalker.dm index c9fbace5c83..ade29af9a2e 100644 --- a/code/modules/mob/living/carbon/superior_animal/stalker/stalker.dm +++ b/code/modules/mob/living/carbon/superior_animal/stalker/stalker.dm @@ -27,8 +27,7 @@ move_to_delay = 6 turns_per_move = 5 see_in_dark = 10 - meat_type = null - meat_amount = 0 + butcher_results = null stop_automated_movement_when_pulled = 0 melee_damage_lower = 12 diff --git a/code/modules/mob/living/carbon/superior_animal/superior_animal.dm b/code/modules/mob/living/carbon/superior_animal/superior_animal.dm index 5d1e0a3d4d1..9c167bc858f 100644 --- a/code/modules/mob/living/carbon/superior_animal/superior_animal.dm +++ b/code/modules/mob/living/carbon/superior_animal/superior_animal.dm @@ -13,6 +13,9 @@ // AI activation for players is handled in sanity , if it has sanity damage it activates AI. sanity_damage = 0.5 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/roachmeat = list(3, BUTCHER_NORMAL)) + butchery_hazard = TRUE + var/icon_living var/icon_dead var/icon_rest //resting/unconscious animation @@ -55,9 +58,6 @@ var/attack_sound_chance = 33 var/attack_sound_volume = 20 - var/meat_type = /obj/item/reagent_containers/food/snacks/meat/roachmeat - var/meat_amount = 3 - var/melee_damage_lower = 0 var/melee_damage_upper = 10 var/melee_sharp = FALSE //whether mob attacks have sharp property @@ -418,4 +418,37 @@ grabbing = null cheap_update_lying_buckled_and_verb_status_() +//generic gore spray butchering fail, only for superior mobs for now +/mob/living/carbon/superior_animal/butchery_fail(mob/living/butcher) + var/mob/living/carbon/carbonbutcher + if(iscarbon(butcher)) + carbonbutcher = butcher + //no repeat message for mouth if eyes are hit + var/message_sent = FALSE + var/mouth_protection = carbonbutcher.find_skin_protection(FACE) + var/eye_protection = carbonbutcher.find_skin_protection(EYES) + + //get the reagent to poison people with if they fail + var/reagent_id = isroach(src) ? "blattedin" : null + if(isspider(src)) + reagent_id = astype(src, /mob/living/carbon/superior_animal/giant_spider)?.poison_type + + gibs(butcher.loc, null, /obj/effect/gibspawner/generic, fleshcolor, bloodcolor)//splatter_cache + + if(!eye_protection) + butcher.visible_message(span_danger("[butcher] is blinded by a spray of gore from the \the [src]!"), span_userdanger("You are blinded by a spray of gore from \the [src]! [!mouth_protection ? "Some of the muck gets in your mouth!" : null]")) + message_sent = TRUE + butcher.eye_blurry = max(butcher.eye_blurry, 25) + butcher.eye_blind = max(butcher.eye_blind, 10) + if(reagent_id) + butcher.reagents.add_reagent(reagent_id, rand(3, 8)) + + else if(!mouth_protection) + butcher.custom_emote(2, "[pick("coughs!","splutters!", "retches.")]")//yuckers + if(!message_sent) + butcher.visible_message(span_danger("[butcher] is sprayed in the face with gore from the \the [src]!"), span_userdanger("You are sprayed with gore by \the [src]! Some of the muck gets in your mouth!")) + if(reagent_id) + butcher.reagents.add_reagent(reagent_id, rand(5, 10)) + else + butcher.visible_message(span_danger("[butcher] is sprayed by gore from the \the [src]!"), span_danger("You sprayed with gore from \the [src]! Your [mouth_protection ? "mask shields" : "glasses shield"] you from the spray!")) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 44c08bd8a7a..6958ef1324d 100755 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -951,3 +951,7 @@ default behaviour is: exp_list[mind.assigned_role] = minutes return exp_list + +///Negative effect that may be triggered by butchering the mob, especially with low stats +/mob/living/proc/butchery_fail(mob/butcher) + return diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 05bcbe0b008..38753411562 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -110,6 +110,14 @@ var/can_multiz_pb = FALSE var/is_watching = FALSE + /** + * possible drops from this mob when butchering. If set to null, butchery is disabled + * stored like [typepath] = list[number of possible drops, base chance of getting it](which should be expressed as a number) + */ + var/list/butcher_results + ///Whether this animal has a chance for complications when butchered. Set up complications under the butchery_fail() proc + var/butchery_hazard = FALSE + spawn_frequency = 10 bad_type = /mob/living diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index ebcd5cabf5b..41886ac0968 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -9,7 +9,7 @@ speak_chance = 1 turns_per_move = 5 see_in_dark = 6 - meat_type = /obj/item/reagent_containers/food/snacks/meat + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/cat = list(2, BUTCHER_DIFFICULT)) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index cc775134805..88c4bfc843e 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -9,8 +9,7 @@ emote_see = list("shakes its head", "shivers") speak_chance = 1 turns_per_move = 10 - meat_type = /obj/item/reagent_containers/food/snacks/meat/corgi - meat_amount = 3 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/corgi = list(3, BUTCHER_NORMAL)) response_help = "pets" response_disarm = "bops" response_harm = "kicks" diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index 9bce2f28068..0206e476bdf 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -8,7 +8,7 @@ emote_see = list("clacks") speak_chance = 1 turns_per_move = 5 - meat_type = /obj/item/reagent_containers/food/snacks/meat/crab + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/crab = list(2, BUTCHER_EASY)) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "stomps" diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 1dc85a3cd04..6a67185d397 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -8,8 +8,7 @@ speak_chance = 1 turns_per_move = 5 see_in_dark = 6 - meat_type = /obj/item/reagent_containers/food/snacks/meat - meat_amount = 4 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = list(5, BUTCHER_NORMAL)) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" @@ -92,8 +91,7 @@ speak_chance = 1 turns_per_move = 5 see_in_dark = 6 - meat_type = /obj/item/reagent_containers/food/snacks/meat - meat_amount = 6 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = list(6, BUTCHER_NORMAL)) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" @@ -151,8 +149,7 @@ emote_see = list("pecks at the ground","flaps its tiny wings","cheeps") speak_chance = 2 turns_per_move = 2 - meat_type = /obj/item/reagent_containers/food/snacks/meat - meat_amount = 1 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/chicken = list(1, BUTCHER_CHALLENGING)) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" @@ -192,8 +189,7 @@ var/global/chicken_count = 0 emote_see = list("pecks at the ground","flaps its wings viciously") speak_chance = 2 turns_per_move = 3 - meat_type = /obj/item/reagent_containers/food/snacks/meat/chicken - meat_amount = 4 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/chicken = list(4, BUTCHER_NORMAL)) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" diff --git a/code/modules/mob/living/simple_animal/friendly/iriska.dm b/code/modules/mob/living/simple_animal/friendly/iriska.dm index febeb0e1158..fbebee4b168 100644 --- a/code/modules/mob/living/simple_animal/friendly/iriska.dm +++ b/code/modules/mob/living/simple_animal/friendly/iriska.dm @@ -11,8 +11,7 @@ speak_emote = list("purrs.", "meows.") emote_see = list("shakes her head.", "shivers.") speak_chance = 0.75 - meat_amount = 6 - meat_type = /obj/item/reagent_containers/food/snacks/meat + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/cat/iriska = list(6, BUTCHER_EASY)) response_help = "pets" response_disarm = "rubs" response_harm = "makes terrible mistake by kicking" diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 770da6cfdbf..db54eedef8e 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -43,8 +43,7 @@ can_pull_size = ITEM_SIZE_TINY can_pull_mobs = MOB_PULL_NONE - meat_type = /obj/item/reagent_containers/food/snacks/meat - meat_amount = 1 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = list(1, BUTCHER_DIFFICULT)) can_burrow = TRUE diff --git a/code/modules/mob/living/simple_animal/friendly/mushroom.dm b/code/modules/mob/living/simple_animal/friendly/mushroom.dm index c61c8fb7964..f04604a68cc 100644 --- a/code/modules/mob/living/simple_animal/friendly/mushroom.dm +++ b/code/modules/mob/living/simple_animal/friendly/mushroom.dm @@ -7,7 +7,7 @@ turns_per_move = 1 maxHealth = 5 health = 5 - meat_type = /obj/item/reagent_containers/food/snacks/hugemushroomslice + butcher_results = list(/obj/item/reagent_containers/food/snacks/hugemushroomslice = list(2, BUTCHER_NORMAL)) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "whacks" diff --git a/code/modules/mob/living/simple_animal/friendly/tomato.dm b/code/modules/mob/living/simple_animal/friendly/tomato.dm index 303e0dc167f..59895ee49d1 100644 --- a/code/modules/mob/living/simple_animal/friendly/tomato.dm +++ b/code/modules/mob/living/simple_animal/friendly/tomato.dm @@ -8,11 +8,11 @@ turns_per_move = 5 maxHealth = 15 health = 15 - meat_type = /obj/item/reagent_containers/food/snacks/tomatomeat + butcher_results = list(/obj/item/reagent_containers/food/snacks/tomatomeat = list(3, BUTCHER_NORMAL)) response_help = "prods" response_disarm = "pushes aside" response_harm = "smacks" harm_intent_damage = 5 melee_damage_upper = 15 melee_damage_lower = 10 - attacktext = "mauled" \ No newline at end of file + attacktext = "mauled" diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index db0a091bd86..6f2012682bb 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -10,7 +10,7 @@ response_disarm = "shoves" response_harm = "hits" speed = -1 - meat_type = /obj/item/reagent_containers/food/snacks/meat/xenomeat + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/xenomeat = list(3, BUTCHER_DIFFICULT)) maxHealth = 100 health = 100 harm_intent_damage = 5 diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm index 56c941cc284..d090549f0a7 100644 --- a/code/modules/mob/living/simple_animal/hostile/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/bat.dm @@ -7,7 +7,7 @@ bubble_icon = "alien" speak_chance = 0 turns_per_move = 3 - meat_type = /obj/item/reagent_containers/food/snacks/meat + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = list(1, BUTCHER_DIFFICULT)) response_help = "pets the" response_disarm = "gently pushes aside the" response_harm = "hits the" diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 1b2092d0cb2..dbc829df5e6 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -9,7 +9,7 @@ speak_chance = 1 turns_per_move = 5 see_in_dark = 6 - meat_type = /obj/item/reagent_containers/food/snacks/meat/bearmeat + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/bearmeat = list(5, BUTCHER_NORMAL)) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "pokes" diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index 46d095e0674..86acb4938fc 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -5,7 +5,8 @@ icon_gib = "carp_gib" speak_chance = 0 turns_per_move = 5 - meat_type = /obj/item/reagent_containers/food/snacks/meat/carp + + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/carp = list(4, BUTCHER_DIFFICULT)) response_help = "pets the" response_disarm = "gently pushes aside the" response_harm = "hits the" @@ -48,4 +49,4 @@ if(istype(L)) if(prob(15)) L.Weaken(3) - L.visible_message(span_danger("\the [src] knocks down \the [L]!")) \ No newline at end of file + L.visible_message(span_danger("\the [src] knocks down \the [L]!")) diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 85e63fd8faf..53af3b71251 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -8,7 +8,6 @@ icon = 'icons/obj/crate.dmi' icon_state = "crate" - meat_type = /obj/item/reagent_containers/food/snacks/meat/carp response_help = "touches" response_disarm = "pushes" response_harm = "hits" diff --git a/code/modules/mob/living/simple_animal/hostile/pike.dm b/code/modules/mob/living/simple_animal/hostile/pike.dm index 27cb1dff15c..405a1118517 100644 --- a/code/modules/mob/living/simple_animal/hostile/pike.dm +++ b/code/modules/mob/living/simple_animal/hostile/pike.dm @@ -3,8 +3,7 @@ desc = "A bigger, angrier cousin of the space carp." icon = 'icons/mob/spaceshark.dmi' icon_state = "shark" - meat_amount = 10 - turns_per_move = 2 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/carp = list(8, BUTCHER_DIFFICULT)) move_to_delay = 2 speed = 0 mob_size = MOB_LARGE @@ -18,4 +17,4 @@ melee_damage_lower = 20 melee_damage_upper = 25 - break_stuff_probability = 100 \ No newline at end of file + break_stuff_probability = 100 diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index e6c1a473ba7..ee2fcea7bbb 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -7,7 +7,6 @@ icon_gib = "pine_1" speak_chance = 0 turns_per_move = 5 - meat_type = /obj/item/reagent_containers/food/snacks/meat/carp response_help = "brushes" response_disarm = "pushes" response_harm = "hits" @@ -52,4 +51,4 @@ /mob/living/simple_animal/hostile/tree/death() ..(null,"is hacked into pieces!") new /obj/item/stack/material/wood(loc) - qdel(src) \ No newline at end of file + qdel(src) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index dc545fa8ea2..e21530d671e 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -39,7 +39,7 @@ speak_chance = 1//1% (1 in 100) chance every tick; So about once per 150 seconds, assuming an average tick is 1.5s turns_per_move = 5 - meat_type = /obj/item/reagent_containers/food/snacks/cracker/ + butcher_results = list(/obj/item/reagent_containers/food/snacks/cracker = list(1, BUTCHER_VERY_HARD)) response_help = "pets" response_disarm = "gently moves aside" diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 2b660ccac35..99f44a3f788 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -28,8 +28,6 @@ var/turns_per_move = 1 var/turns_since_move = 0 universal_speak = 0 //No, just no. - var/meat_amount = 0 - var/meat_type var/stop_automated_movement = FALSE //Use this to temporarely stop random movement or to if you write special movement code for animals. var/wander = TRUE // Does the mob wander around when idle? var/stop_automated_movement_when_pulled = TRUE //When set to 1 this stops the animal from moving when someone is pulling it. @@ -435,10 +433,6 @@ else if(istype(O, /obj/item/reagent_containers) || istype(O, /obj/item/stack/medical)) ..() - else if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead. - if(QUALITY_CUTTING in O.tool_qualities) - if(O.use_tool(user, src, WORKTIME_NORMAL, QUALITY_CUTTING, FAILCHANCE_NORMAL, required_stat = STAT_BIO)) - harvest(user) else O.attack(src, user, user.targeted_organ) @@ -509,21 +503,6 @@ W.loc = get_turf(src) return 1 -// Harvest an animal's delicious byproducts -/mob/living/simple_animal/proc/harvest(mob/user) - var/actual_meat_amount = max(1,(meat_amount/2)) - if(meat_type && actual_meat_amount>0 && (stat == DEAD)) - for(var/i=0;i CWJ_QUALITY_MEH) + message = "This food helps you relax." + else if(food_tier > CWJ_QUALITY_GROSS) + message = "This food isn't very good, but at least it's edible." + else + message = "You're regretting putting this in your mouth." if(cooked) sanity_gain_per_bite += base_sanity_gain_per_bite * food_tier message += bite_descriptor - if(junk_food || !cooked) + if((junk_food || !cooked) && food_tier > CWJ_QUALITY_GROSS) message += " However, only healthy food will help you rest." return list(sanity_gain_per_bite, span_notice(message)) var/table = FALSE @@ -339,8 +346,8 @@ for(var/i=1 to (slices_num-slices_lost)) var/obj/slice = new slice_path (src.loc) reagents.trans_to_obj(slice, reagents_per_slice) - if(istype(slice_path, /obj/item/reagent_containers/food/snacks)) - slice_path?:food_quality = src.food_quality + if(istype(slice, /obj/item/reagent_containers/food/snacks)) + slice?:food_quality = food_quality qdel(src) return @@ -913,7 +920,7 @@ /obj/item/reagent_containers/food/snacks/rawmeatball/attackby(obj/item/W as obj, mob/user as mob) if(istype(W,/obj/item/material/kitchen/rollingpin)) - new /obj/item/reagent_containers/food/snacks/patty_raw(src) + new /obj/item/reagent_containers/food/snacks/patty_raw(src, food_quality) to_chat(user, "You flatten the raw meatball.") qdel(src) @@ -3562,14 +3569,14 @@ // Dough + rolling pin = flat dough /obj/item/reagent_containers/food/snacks/dough/attackby(obj/item/W as obj, mob/user as mob) if(istype(W,/obj/item/material/kitchen/rollingpin)) - new /obj/item/reagent_containers/food/snacks/sliceable/flatdough(src) + new /obj/item/reagent_containers/food/snacks/sliceable/flatdough(src, food_quality) to_chat(user, "You flatten the dough.") qdel(src) // Dough slice + rolling pin = flat dough slice /obj/item/reagent_containers/food/snacks/doughslice/attackby(obj/item/W as obj, mob/user as mob) if(istype(W,/obj/item/material/kitchen/rollingpin)) - new /obj/item/reagent_containers/food/snacks/flatdoughslice(src) + new /obj/item/reagent_containers/food/snacks/flatdoughslice(src, food_quality) to_chat(user, "You flatten the dough slice.") qdel(src) @@ -3705,8 +3712,8 @@ /obj/item/reagent_containers/food/snacks/rawcutlet/attackby(obj/item/W as obj, mob/user as mob) if(istype(W,/obj/item/material/kitchen/rollingpin)) - new /obj/item/reagent_containers/food/snacks/rawmeatball(src) - new /obj/item/reagent_containers/food/snacks/rawmeatball(src) + new /obj/item/reagent_containers/food/snacks/rawmeatball(src, food_quality) + new /obj/item/reagent_containers/food/snacks/rawmeatball(src, food_quality) to_chat(user, "You ground the sliced meat, and shape it into a ball.") qdel(src) @@ -3747,7 +3754,7 @@ /obj/item/reagent_containers/food/snacks/grown/potato/attackby(obj/item/item, mob/user) //this is obsolete?? if(QUALITY_CUTTING in item.tool_qualities) if(item.use_tool(user, src, WORKTIME_NEAR_INSTANT, QUALITY_CUTTING, FAILCHANCE_ZERO, required_stat = STAT_BIO)) - new /obj/item/reagent_containers/food/snacks/rawsticks(src) + new /obj/item/reagent_containers/food/snacks/rawsticks(src, food_quality) to_chat(user, "You cut the potato.") qdel(src) else diff --git a/code/modules/reagents/reagent_containers/food/snacks/meat.dm b/code/modules/reagents/reagent_containers/food/snacks/meat.dm index e8884360a0d..db101d02be2 100644 --- a/code/modules/reagents/reagent_containers/food/snacks/meat.dm +++ b/code/modules/reagents/reagent_containers/food/snacks/meat.dm @@ -31,6 +31,20 @@ desc = "Tastes like... well, you know." price_tag = 25 +/obj/item/reagent_containers/food/snacks/meat/cat + name = "gato" + desc = "Meat harvested from a small feline creature, tough and stringy but high in protein. Mostly eaten during famine or other times of desperation." + filling_color = "#b84529" + preloaded_reagents = list("protein" = 10) + +/obj/item/reagent_containers/food/snacks/meat/cat/iriska + name = "well-marbled gato" + desc = "Meat harvested from a small feline creature. Unlike most cat meat, this is marbled almost like high-quality pork. It's owner must have been extremely pampered." + filling_color = "#e19e8b" + preloaded_reagents = list("protein" = 6)//mostly fat + slice_path = /obj/item/reagent_containers/food/snacks/rawbacon + slices_num = 4 + /obj/item/reagent_containers/food/snacks/meat/pork name = "porcine meat" desc = "A raw slab of meat from pig or otherwise porcine animal, which you hopefully slaughtered without cruelty." // Always remember to pray Bismillah before, keep it halal. diff --git a/code/modules/sanity/sanity_mob.dm b/code/modules/sanity/sanity_mob.dm index 27f0aa3b46a..c3b7f092359 100644 --- a/code/modules/sanity/sanity_mob.dm +++ b/code/modules/sanity/sanity_mob.dm @@ -414,7 +414,7 @@ GLOBAL_VAR_INIT(GLOBAL_INSIGHT_MOD, 1) changeLevel(snack_sanity_gain) if(snack.cooked && resting && snack.taste_tag.len) for(var/taste in snack.taste_tag) - add_rest(taste, snack_sanity_gain * 50/snack.taste_tag.len) + add_rest(taste, (snack_sanity_gain * 50/snack.taste_tag.len) * snack.food_tier) /datum/sanity/proc/onSmoke(obj/item/clothing/mask/smokable/S) changeLevel(SANITY_GAIN_SMOKE * S.quality_multiplier) diff --git a/code/modules/tips_and_tricks/gameplay.dm b/code/modules/tips_and_tricks/gameplay.dm index e9b6b549a12..e26c118fa1e 100644 --- a/code/modules/tips_and_tricks/gameplay.dm +++ b/code/modules/tips_and_tricks/gameplay.dm @@ -61,3 +61,6 @@ /tipsAndTricks/gameplay/shieldweakness tipText = "You can get around Shields by attacking their wielder from behind." + +/tipsAndTricks/gameplay/foodquality + tipText = "Well-made food will help you rest and recover your sanity more effectively. Crappy food will damage your sanity and contribute less to your desires."