From acdbcad0056eec9958bcdb7ff4aa4f117021f01f Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Fri, 19 Jun 2026 14:21:03 -0400 Subject: [PATCH] Xenobiology Cross Skill Interactions (#22643) This PR adds new Cross-Skill Interactions for both Cooking and Xenobiology, the latter of which now provides a new Situational Skill Modifier. Cooking Skill now causes animals butchered by the character to drop additional meat. A pretty simple small interaction that doesn't change much in the grand scheme of things. Xenobiology has gained two new interactions, aimed at making it a skill "potentially useful" for players who think their character might be fighting Space Fauna. The first is that it provides a melee damage modifier (which can offset the penalties from low melee skill), but only when attacking Space Fauna (that aren't player controlled). Normally direct damage modifiers are very hard to balance as a consequence of brainmed, but since this applies exclusively to a PVE interaction, the balance concerns are significantly lessened. Its second new interaction is to situationally modify the amount of butchering products gained from Space Fauna (and only Space Fauna). Particularly in the case of Xenobiology, this helps position the skill in such a way that it provides Opportunity Cost for characters in Cooking, Mining, and Security (to a much lesser extent, given they almost never engage carp in melee). If points spent in Xenobiology helps a miner fight off space fauna, then points spent in Surgery are not points they're spending on being better at fighting carp. Almost all of the skills in general should have care put into making sure that they can provide viable Opportunity Cost against other skills in their same category. Cross-Skill Interactions like this are an incredibly effective method of doing so. --------- Signed-off-by: VMSolidus --- code/__DEFINES/dcs/signals.dm | 3 ++ code/__DEFINES/traits.dm | 5 ++ .../science/xenobiology_skill_component.dm | 30 ++++++++++++ .../skills/service/cooking_skill_component.dm | 19 ++++++++ code/datums/skills/everyday/service.dm | 9 +++- code/datums/skills/occupational/science.dm | 18 +++++--- .../mob/living/simple_animal/hostile/bear.dm | 1 + .../simple_animal/hostile/giant_spider.dm | 1 + .../simple_animal/hostile/phoron_worm.dm | 4 ++ .../simple_animal/hostile/space_fauna.dm | 8 ++++ .../mob/living/simple_animal/simple_animal.dm | 46 +++++++++++-------- .../hellfirejag-cooking-xenobiology-skill.yml | 5 ++ 12 files changed, 121 insertions(+), 28 deletions(-) create mode 100644 html/changelogs/hellfirejag-cooking-xenobiology-skill.yml diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 89a55b62229..5b68f267610 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -141,5 +141,8 @@ /// Signal raised against a character attempting to deliver a speech. #define COMSIG_GET_LEADERSHIP_MODIFIERS "get_leadership_modifiers" +/// Signal raised against a character attempting to butcher a mob, to check for butchering bonuses from skills. +#define COMSIG_GET_BUTCHERING_MODIFIERS "get_butchering_modifiers" + // Crafting Signals #define COMSIG_GET_CRAFTING_MODIFIERS "get_crafting_modifiers" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 803ac7785a3..210500adce1 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -224,3 +224,8 @@ /// Unlinks gliding from movement speed, meaning that there will be a delay between movements rather than a single move movement between tiles #define TRAIT_NO_GLIDE "no_glide" + +// MOB CATEGORY traits used for pattern matching certain subtypes of mobs +#define TRAIT_SOURCE_MOB_CATEGORY "mob_category" +/// All "Space Fauna" EG: Space Carp +#define TRAIT_MC_SPACE_FAUNA "space_fauna" diff --git a/code/datums/components/skills/science/xenobiology_skill_component.dm b/code/datums/components/skills/science/xenobiology_skill_component.dm index 8b667a1c5ea..7057982aec7 100644 --- a/code/datums/components/skills/science/xenobiology_skill_component.dm +++ b/code/datums/components/skills/science/xenobiology_skill_component.dm @@ -1,22 +1,30 @@ /datum/component/skill/xenobiology + /// Bonus surgery success rate, to be applied only when performing surgeries on a creature of a different species. var/success_rate_bonus_per_level = 2.5 /// Bonus surgery speed (as a percent increase) per skill level, to be applied only when performing surgeries on a creature of a different species. var/surgery_speed_mod_per_level = 0.05 + /// +%bonus damage versus Space Fauna (EG: Space Carp, Space Bears, Asteroid Worms, Gnats, Etc.) + var/bonus_damage_per_rank = 0.05 + /datum/component/skill/xenobiology/Initialize(level) . = ..() if (!parent) return RegisterSignal(parent, COMSIG_GET_SURGERY_SUCCESS_MODIFIERS, PROC_REF(handle_surgery_modifiers)) + RegisterSignal(parent, COMSIG_APPLY_HIT_EFFECT, PROC_REF(modify_hit_effect), override = TRUE) + RegisterSignal(parent, COMSIG_GET_BUTCHERING_MODIFIERS, PROC_REF(modify_butchering), override = TRUE) /datum/component/skill/xenobiology/Destroy(force) if (!parent) return ..() UnregisterSignal(parent, COMSIG_GET_SURGERY_SUCCESS_MODIFIERS) + UnregisterSignal(parent, COMSIG_APPLY_HIT_EFFECT) + UnregisterSignal(parent, COMSIG_GET_BUTCHERING_MODIFIERS) return ..() /datum/component/skill/xenobiology/proc/handle_surgery_modifiers(mob/living/user, mob/living/carbon/target, success_rate, duration) @@ -28,3 +36,25 @@ var/effective_skill = skill_level - 1 *success_rate = *success_rate + success_rate_bonus_per_level * effective_skill *duration = *duration * (1 - surgery_speed_mod_per_level * effective_skill) + +/datum/component/skill/xenobiology/proc/modify_hit_effect(owner, mob/living/target, obj/item/weapon, power, hit_zone) + SIGNAL_HANDLER + if (target.ckey || !HAS_TRAIT(target, TRAIT_MC_SPACE_FAUNA)) + return + + if (prob(20)) + // Give the player some feedback that the skill is providing a damage bonus, but no need to spam the chat. + to_chat(owner, SPAN_NOTICE("Your attack exploits a weak spot on [target]")) + + *power = *power * (1 + bonus_damage_per_rank * (skill_level)) + +/datum/component/skill/xenobiology/proc/modify_butchering(owner, mob/living/simple_animal/target, base_meat_amount, butchering_bonus) + SIGNAL_HANDLER + if (!HAS_TRAIT(target, TRAIT_MC_SPACE_FAUNA) || skill_level <= SKILL_LEVEL_UNFAMILIAR) + return + + to_chat(owner, SPAN_NOTICE("Your familiarity with [target] lets you harvest more parts.")) + var/skill_difference = skill_level - SKILL_LEVEL_UNFAMILIAR + *base_meat_amount = *base_meat_amount + skill_difference + if (skill_level >= SKILL_LEVEL_PROFESSIONAL) + *butchering_bonus = *butchering_bonus + skill_difference diff --git a/code/datums/components/skills/service/cooking_skill_component.dm b/code/datums/components/skills/service/cooking_skill_component.dm index bcfc1bde97e..b5bbe18d777 100644 --- a/code/datums/components/skills/service/cooking_skill_component.dm +++ b/code/datums/components/skills/service/cooking_skill_component.dm @@ -1 +1,20 @@ /datum/component/skill/cooking + +/datum/component/skill/cooking/Initialize(level) + . = ..() + RegisterSignal(parent, COMSIG_GET_BUTCHERING_MODIFIERS, PROC_REF(modify_butchering), override = TRUE) + +/datum/component/skill/cooking/Destroy(force) + UnregisterSignal(parent, COMSIG_GET_BUTCHERING_MODIFIERS) + return ..() + +/datum/component/skill/cooking/proc/modify_butchering(owner, mob/living/simple_animal/target, base_meat_amount, butchering_bonus) + SIGNAL_HANDLER + if (skill_level <= SKILL_LEVEL_UNFAMILIAR) + return + + to_chat(owner, SPAN_NOTICE("Your skill with cooking lets you harvest more parts.")) + var/skill_difference = skill_level - SKILL_LEVEL_UNFAMILIAR + *base_meat_amount = *base_meat_amount + skill_difference + if (skill_level >= SKILL_LEVEL_PROFESSIONAL) + *butchering_bonus = *butchering_bonus + skill_difference diff --git a/code/datums/skills/everyday/service.dm b/code/datums/skills/everyday/service.dm index ffde208532d..56962d34c1f 100644 --- a/code/datums/skills/everyday/service.dm +++ b/code/datums/skills/everyday/service.dm @@ -14,11 +14,18 @@ /singleton/skill/cooking name = "Cooking" - description = "Currently unimplemented." + description = "Users of this skill gain bonuses when harvesting parts from animals." maximum_level = SKILL_LEVEL_PROFESSIONAL category = /singleton/skill_category/everyday subcategory = SKILL_SUBCATEGORY_SERVICE component_type = COOKING_SKILL_COMPONENT + skill_level_descriptions = alist( + SKILL_LEVEL_UNFAMILIAR = "You have no modifiers from cooking.", + SKILL_LEVEL_FAMILIAR = "You gain +1 product when butchering any animal", + SKILL_LEVEL_TRAINED = "You gain +2 products when butchering any animal", + SKILL_LEVEL_PROFESSIONAL = "You gain +3 products when butchering any animal" + ) + /singleton/skill/gardening name = "Gardening" diff --git a/code/datums/skills/occupational/science.dm b/code/datums/skills/occupational/science.dm index 90817c256dc..94c66712377 100644 --- a/code/datums/skills/occupational/science.dm +++ b/code/datums/skills/occupational/science.dm @@ -5,7 +5,6 @@ uneducated_skill_cap = SKILL_LEVEL_TRAINED category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_SCIENCE - required = TRUE component_type = RESEARCH_SKILL_COMPONENT /singleton/skill/xenobotany @@ -33,14 +32,19 @@ + "Having this skill at least at the \"Trained\" rank is required to extract cores from slimes. " \ + "Ranks in this skill also provide small situational bonuses when interacting with aliens in general." maximum_level = SKILL_LEVEL_PROFESSIONAL - uneducated_skill_cap = SKILL_LEVEL_TRAINED + uneducated_skill_cap = SKILL_LEVEL_PROFESSIONAL category = /singleton/skill_category/occupational subcategory = SKILL_SUBCATEGORY_SCIENCE component_type = XENOBOTANY_SKILL_COMPONENT - required = TRUE skill_level_descriptions = alist( - SKILL_LEVEL_UNFAMILIAR = "You have no modifiers from this skill.", - SKILL_LEVEL_FAMILIAR = "You have a very small bonus to both success rate and surgery speed when performing surgeries on aliens in general.", - SKILL_LEVEL_TRAINED = "You have a small bonus to both success rate and surgery speed when performing surgeries on aliens in general.", - SKILL_LEVEL_PROFESSIONAL = "You have a moderate bonus to both success rate and surgery speed when performing surgeries on aliens in general." + SKILL_LEVEL_UNFAMILIAR = "You have little to no knowledge of Xenobiology", + SKILL_LEVEL_FAMILIAR = "You have a passing experience with Xenobiology.
" \ + + " - Your melee attacks made against Xenofauna such as Space Carp deal 10% more damage.
" \ + + " - You harvest one additional part when butchering Xenofauna.", + SKILL_LEVEL_TRAINED = "You have a moderate experience with Xenobiology.
" \ + + " - Your melee attacks made against Xenofauna such as Space Carp deal 15% more damage.
" \ + + " - You harvest two additional parts when butchering Xenofauna.", + SKILL_LEVEL_PROFESSIONAL = "You have extensive experience with Xenobiology.
" \ + + " - Your melee attacks made against Xenofauna such as Space Carp deal 20% more damage.
" \ + + " - You harvest three additional parts when butchering Xenofauna.", ) diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 2396d3ce6c8..15841eeb05d 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -86,6 +86,7 @@ . = ..() emote_sounds = quiet_sounds update_bearmode() + ADD_TRAIT(src, TRAIT_MC_SPACE_FAUNA, TRAIT_SOURCE_MOB_CATEGORY) /mob/living/simple_animal/hostile/bear/proc/set_stance(var/input) var/previous = stance diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 31f17feaf23..71133f7e971 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -169,6 +169,7 @@ add_language(LANGUAGE_GREIMORIAN_HIVEMIND) remove_language(LANGUAGE_TCB) default_language = GLOB.all_languages[LANGUAGE_GREIMORIAN] + ADD_TRAIT(src, TRAIT_MC_SPACE_FAUNA, TRAIT_SOURCE_MOB_CATEGORY) /mob/living/simple_animal/hostile/giant_spider/nurse/servant/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/phoron_worm.dm b/code/modules/mob/living/simple_animal/hostile/phoron_worm.dm index 8820fe979ae..b478bd13909 100644 --- a/code/modules/mob/living/simple_animal/hostile/phoron_worm.dm +++ b/code/modules/mob/living/simple_animal/hostile/phoron_worm.dm @@ -46,6 +46,10 @@ var/burrowing = FALSE +/mob/living/simple_animal/hostile/phoron_worm/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_MC_SPACE_FAUNA, TRAIT_SOURCE_MOB_CATEGORY) + /mob/living/simple_animal/hostile/phoron_worm/death() ..(null,"collapses under its own weight!") var/turf/T = get_turf(src) diff --git a/code/modules/mob/living/simple_animal/hostile/space_fauna.dm b/code/modules/mob/living/simple_animal/hostile/space_fauna.dm index a20d846f789..892ee475c84 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_fauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_fauna.dm @@ -59,6 +59,10 @@ smart_melee = FALSE sample_data = list("Cellular structure shows adaptation for survival in vacuum", "Genetic biomarkers identified linked with agressiveness", "Tissue sample contains micro-gas release structures") +/mob/living/simple_animal/hostile/carp/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_MC_SPACE_FAUNA, TRAIT_SOURCE_MOB_CATEGORY) + /mob/living/simple_animal/hostile/carp/update_icon() ..() if(resting || stat == DEAD) @@ -319,3 +323,7 @@ flying = TRUE lighting_alpha = LIGHTING_PLANE_ALPHA_SOMEWHAT_INVISIBLE sample_data = list("Cellular structure shows adaptation for survival in vacuum", "Genetic biomarkers identified linked with agressiveness", "Tissue sample contains micro-gas release structures") + +/mob/living/simple_animal/hostile/gnat/Initialize() + . = ..() + ADD_TRAIT(src, TRAIT_MC_SPACE_FAUNA, TRAIT_SOURCE_MOB_CATEGORY) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index bae3ce58457..b1cb0743ac4 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -195,7 +195,7 @@ var/milk_type = /singleton/reagent/drink/milk /// If anything else is created when butchering this creature, like bones and leather - var/list/butchering_products + var/alist/butchering_products var/psi_pingable = TRUE @@ -900,27 +900,33 @@ return FALSE /// Harvest an animal's delicious byproducts -/mob/living/simple_animal/proc/harvest(var/mob/user) - var/actual_meat_amount = max(1,(meat_amount*0.75)) - if(meat_type && actual_meat_amount>0 && (stat == DEAD)) - for(var/i=0;i\The [user] chops up \the [src]!") - var/obj/effect/decal/cleanable/blood/splatter/S = new /obj/effect/decal/cleanable/blood/splatter(get_turf(src)) - S.basecolor = blood_type - S.update_icon() - qdel(src) - else - user.visible_message("\The [user] butchers \the [src] messily!") - gib() + for (var/i = 0; i < base_meat_amount; i++) + new meat_type(get_turf(src)) + + for (var/path, number in butchering_products) + var/total_product = number + butchering_bonus + for (var/i in 1 to total_product) + new path(get_turf(src)) + + if (issmall(src)) + user.visible_message("\The [user] chops up \the [src]!") + var/obj/effect/decal/cleanable/blood/splatter/S = new /obj/effect/decal/cleanable/blood/splatter(get_turf(src)) + S.basecolor = blood_type + S.update_icon() + qdel(src) + else + user.visible_message("\The [user] butchers \the [src] messily!") + gib() /// For picking up small animals /mob/living/simple_animal/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params) diff --git a/html/changelogs/hellfirejag-cooking-xenobiology-skill.yml b/html/changelogs/hellfirejag-cooking-xenobiology-skill.yml new file mode 100644 index 00000000000..f695eecbc5e --- /dev/null +++ b/html/changelogs/hellfirejag-cooking-xenobiology-skill.yml @@ -0,0 +1,5 @@ +author: Hellfirejag +delete-after: True +changes: + - rscadd: "Cooking Skill now increases the amount of products gained from butchering animals." + - rscadd: "Xenobiology Skill now increases melee damage against Space Fauna (EG: Space Carp, Space Bears, etc). Additionally, it also increases butchering products gained from Space Fauna."