diff --git a/code/__HELPERS/trait_helpers.dm b/code/__HELPERS/trait_helpers.dm
index e8e7aaead06..2b67dc76bea 100644
--- a/code/__HELPERS/trait_helpers.dm
+++ b/code/__HELPERS/trait_helpers.dm
@@ -244,6 +244,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_NEVER_MISSES_DISPOSALS "trait_never_misses_disposals" // For janitors landing disposal throws
#define TRAIT_SLEIGHT_OF_HAND "sleight_of_hand"
#define TRAIT_KNOWS_COOKING_RECIPES "knows_cooking_recipes"
+#define TRAIT_XENOBIO_SPAWNED_HUMAN "xenobio_spawned_human" // The mob is from xenobio/cargo/botany that has evolved into their greater form. They do not give vampires usuble blood and cannot be converted by cult.
/// used for dead mobs that are observing, but should not be afforded all the same platitudes as full ghosts.
/// This is a mind trait because ghosts can be frequently deleted and we want to be sure this sticks.
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 8316beacba1..ab2c210265f 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -402,7 +402,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, "You are now able to construct mirror shields inside the daemon forge.")
SSticker.mode.cult_team.mirror_shields_active = TRUE
else
- if(ishuman(offering) && offering.mind?.offstation_role && offering.mind.special_role != SPECIAL_ROLE_ERT) //If you try it on a ghost role, you get nothing
+ if((ishuman(offering) && offering.mind?.offstation_role && offering.mind.special_role != SPECIAL_ROLE_ERT) || HAS_MIND_TRAIT(offering, TRAIT_XENOBIO_SPAWNED_HUMAN)) //If you try it on a ghost role, or an envolved caterpillar/nymph, you get nothing
to_chat(M, "\"This soul is of no use to either of us.\"")
worthless = TRUE
else if(ishuman(offering) || isrobot(offering))
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index 9261b150e9d..98604bf6922 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -116,7 +116,7 @@
to_chat(user, "\"Come now, do not capture your fellow's soul.\"")
return ..()
- if(M.mind.offstation_role && M.mind.special_role != SPECIAL_ROLE_ERT)
+ if((M.mind.offstation_role && M.mind.special_role != SPECIAL_ROLE_ERT) || HAS_MIND_TRAIT(M, TRAIT_XENOBIO_SPAWNED_HUMAN))
to_chat(user, "This being's soul seems worthless. Not even the stone will absorb it.")
return ..()
diff --git a/code/modules/antagonists/vampire/vamp_datum.dm b/code/modules/antagonists/vampire/vamp_datum.dm
index 45625ed3121..e9ba8c78bba 100644
--- a/code/modules/antagonists/vampire/vamp_datum.dm
+++ b/code/modules/antagonists/vampire/vamp_datum.dm
@@ -114,7 +114,7 @@ RESTRICT_TYPE(/datum/antagonist/vampire)
owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + 5))
continue
- if(H.stat != DEAD || H.has_status_effect(STATUS_EFFECT_RECENTLY_SUCCUMBED))
+ if((H.stat != DEAD || H.has_status_effect(STATUS_EFFECT_RECENTLY_SUCCUMBED)) && !HAS_MIND_TRAIT(H, TRAIT_XENOBIO_SPAWNED_HUMAN))
if(H.ckey || H.player_ghosted) //Requires ckey regardless if monkey or humanoid, or the body has been ghosted before it died
blood = min(20, H.blood_volume)
adjust_blood(H, blood * BLOOD_GAINED_MODIFIER)
@@ -130,7 +130,7 @@ RESTRICT_TYPE(/datum/antagonist/vampire)
else
to_chat(owner.current, "You have bled your victim dry!")
break
- if(!H.ckey && !H.player_ghosted)//Only runs if there is no ckey and the body has not being ghosted while alive
+ if((!H.ckey && !H.player_ghosted) || HAS_MIND_TRAIT(H, TRAIT_XENOBIO_SPAWNED_HUMAN)) //Only runs if there is no ckey and the body has not being ghosted while alive, also runs if the victim is an evolved caterpillar or diona nymph.
to_chat(owner.current, "Feeding on [H] reduces your thirst, but you get no usable blood from them.")
owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + 5))
else
diff --git a/code/modules/mob/living/simple_animal/friendly/diona_nymph.dm b/code/modules/mob/living/simple_animal/friendly/diona_nymph.dm
index 1637a02c8ce..77c8b8aeb0a 100644
--- a/code/modules/mob/living/simple_animal/friendly/diona_nymph.dm
+++ b/code/modules/mob/living/simple_animal/friendly/diona_nymph.dm
@@ -205,6 +205,8 @@
adult.real_name = adult.name
adult.ckey = ckey
adult.real_name = adult.dna.species.get_random_name() //I hate this being here of all places but unfortunately dna is based on real_name!
+ // [Nymph -> Diona] is from xenobio (or botany) and does not give vampires usuble blood and cannot be converted by cult.
+ ADD_TRAIT(adult.mind, TRAIT_XENOBIO_SPAWNED_HUMAN, ROUNDSTART_TRAIT)
for(var/obj/item/W in contents)
unEquip(W)
diff --git a/code/modules/mob/living/simple_animal/friendly/nian_caterpillar.dm b/code/modules/mob/living/simple_animal/friendly/nian_caterpillar.dm
index 166b06f23e3..14a22fce199 100644
--- a/code/modules/mob/living/simple_animal/friendly/nian_caterpillar.dm
+++ b/code/modules/mob/living/simple_animal/friendly/nian_caterpillar.dm
@@ -83,6 +83,8 @@
// Mind transfer to new worme.
M.transfer_to(adult)
+ // [Caterpillar -> worme -> nian] is from xenobio (or cargo) and does not give vampires usuble blood and cannot be converted by cult.
+ ADD_TRAIT(adult.mind, TRAIT_XENOBIO_SPAWNED_HUMAN, ROUNDSTART_TRAIT)
// Worme is placed into cacoon.
adult.forceMove(C)