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 <evilexecutive@gmail.com>
This commit is contained in:
VMSolidus
2026-06-19 14:21:03 -04:00
committed by GitHub
parent 662fecfc79
commit acdbcad005
12 changed files with 121 additions and 28 deletions
@@ -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
@@ -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()
. = ..()
@@ -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)
@@ -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)
@@ -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<actual_meat_amount;i++)
new meat_type(get_turf(src))
/mob/living/simple_animal/proc/harvest(mob/user)
if (!meat_type || (stat != DEAD))
return
if(butchering_products)
for(var/path in butchering_products)
var/number = butchering_products[path]
for(var/i in 1 to number)
new path(get_turf(src))
var/base_meat_amount = meat_amount - rand(0, 2)
var/butchering_bonus = 0
SEND_SIGNAL(user, COMSIG_GET_BUTCHERING_MODIFIERS, src, &base_meat_amount, &butchering_bonus)
if (base_meat_amount <= 0)
return
if(issmall(src))
user.visible_message("<b>\The [user]</b> 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("<b>\The [user]</b> 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("<b>\The [user]</b> 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("<b>\The [user]</b> 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)