Harvestable Carpotoxin (#19794)

Adds the ability to obtain small amounts carpotoxin from space carps
without having to kill them! Beakers and buckets work, currently, I do
not believe eyedroppers or syringes can be used to do this.

Friendly space carps are now identified as being tame, and I have also
given them a few new idle emotes for additional cuteness.

You can harvest carpotoxin from hostile space carps, but good luck
trying to do that while they're chomping your fingers...

---------

Signed-off-by: ASmallCuteCat <neofelisnebulosa128@gmail.com>
Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>
Co-authored-by: Matt Atlas <liermattia@gmail.com>
This commit is contained in:
ASmallCuteCat
2024-09-13 10:18:42 +00:00
committed by GitHub
co-authored by Fluffy Matt Atlas
parent 821408a3a3
commit f0602604e7
9 changed files with 120 additions and 30 deletions
@@ -88,7 +88,7 @@
mob_size = 15
canbrush = TRUE
has_udder = TRUE
can_be_milked = TRUE
milk_type = /singleton/reagent/drink/milk/adhomai
meat_type = /obj/item/reagent_containers/food/snacks/meat/adhomai
@@ -102,7 +102,7 @@
icon_living = "fatshouter_m"
icon_dead = "fatshouter_m_dead"
gender = MALE
has_udder = FALSE
can_be_milked = FALSE
/mob/living/simple_animal/hostile/retaliate/rafama
name = "steed of Mata'ke"
@@ -1,5 +1,5 @@
/mob/living/simple_animal/carp
name = "space carp"
name = "tame space carp"
desc = "A domesticated, floating space carp. Careful around the teeth."
icon = 'icons/mob/npc/animal.dmi'
icon_state = "carp"
@@ -9,10 +9,10 @@
icon_gib = "carp_gib"
icon_rest = "carp_rest"
can_nap = TRUE
speak = list("Glub!")
speak = list("Glub!", "Glub?", "Glub.")
speak_emote = list("glubs", "glibs")
emote_hear = list("glubs","glibs")
emote_see = list("floats steadily", "inflates its gills")
emote_see = list("floats steadily", "inflates its gills", "flaps its flippers", "wiggles", "waggles")
speak_chance = 1
turns_per_move = 5
meat_type = /obj/item/reagent_containers/food/snacks/fish/carpmeat
@@ -25,6 +25,11 @@
faction = "carp"
flying = TRUE
can_be_milked = TRUE
udder_size = 3
milk_type = /singleton/reagent/toxin/carpotoxin
milk_regeneration = list(1, 2)
//Space carp aren't affected by atmos.
min_oxy = 0
max_oxy = 0
@@ -138,11 +143,17 @@
gender = FEMALE
emote_see = list("floats steadily", "inflates her gills")
emote_see = list("floats steadily", "inflates her gills", "flaps her flippers", "wiggles", "waggles")
can_nap = TRUE
mob_size = 3.5
// Actually cannot be milked, but this way we get the error message.
can_be_milked = TRUE
udder_size = 2
milk_type = /singleton/reagent/toxin/carpotoxin
milk_regeneration = list(1, 1)
befriend_job = "Chief Engineer"
holder_type = /obj/item/holder/carp/baby
@@ -150,6 +161,10 @@
.=..()
desc = "WHO KILLED GINNY?!"
/mob/living/simple_animal/carp/fluff/ginny/handle_milking(mob/user, obj/item/reagent_containers/container)
//user.visible_message("[SPAN_BOLD("Ginny")] shies away from the [container] and stares at [SPAN_BOLD("[user]")] judgementally.")
user.visible_message("[pick("[SPAN_BOLD("Ginny")] shies away from the [container] and stares at [SPAN_BOLD("[user]")] judgementally.", "[SPAN_BOLD("Ginny")] recoils from [SPAN_BOLD("[user]")] with an indignant glub.", "[SPAN_BOLD("Ginny")] bares her tiny fangs and evades the [container].", "[SPAN_BOLD("Ginny")] stretches a flipper out and pushes the [container] away.")]")
/mob/living/simple_animal/carp/baby
name = "baby space carp"
desc = "Awfully cute! Looks friendly!"
@@ -27,7 +27,7 @@
udder = null
canbrush = TRUE
emote_sounds = list('sound/effects/creatures/goat.ogg')
has_udder = TRUE
can_be_milked = TRUE
hostile_nameable = TRUE
butchering_products = list(/obj/item/stack/material/animalhide = 3)
@@ -99,7 +99,7 @@
mob_size = 20//based on mass of holstein fresian dairy cattle, what the sprite is based on
emote_sounds = list('sound/effects/creatures/cow.ogg')
canbrush = TRUE
has_udder = TRUE
can_be_milked = TRUE
butchering_products = list(/obj/item/stack/material/animalhide = 8)
forbidden_foods = list(/obj/item/reagent_containers/food/snacks/egg)
@@ -25,5 +25,5 @@
mob_size = 15
has_udder = TRUE
can_be_milked = TRUE
milk_type = /singleton/reagent/drink/milk/beetle
@@ -26,7 +26,7 @@
maxHealth = 30
health = 30
has_udder = TRUE
can_be_milked = TRUE
milk_type = /singleton/reagent/drink/milk/schlorrgo
friendly = "bumped"
@@ -235,7 +235,7 @@
maxHealth = 80
health = 80
has_udder = FALSE
can_be_milked = FALSE
organ_names = list("head", "chest", "augmented core", "augmented torso", "robotic centre", "left leg", "right leg")
butchering_products = list(/obj/item/reagent_containers/food/snacks/spreads/lard = 1)
@@ -22,6 +22,11 @@
health = 25
mob_size = 10
can_be_milked = TRUE
udder_size = 3
milk_type = /singleton/reagent/toxin/carpotoxin
milk_regeneration = list(1, 2)
blood_overlay_icon = 'icons/mob/npc/blood_overlay_carp.dmi'
harm_intent_damage = 4
melee_damage_lower = 15
@@ -139,8 +139,16 @@
var/flying = FALSE //if they can fly, which stops them from falling down and allows z-space travel
var/has_udder = FALSE
/// Whether this animal can be milked or not.
var/can_be_milked = FALSE
/// The reagent storage for the animal's milking product.
var/datum/reagents/udder = null
/// The size of the udder's reagent storage.
var/udder_size = 50
/// The minimum and upper floor of the per-tick milk regeneration to feed into rand(). This list should always have both minimum and upper floor.
/// This is also how much milk is taken from the animal at once.
var/list/milk_regeneration = list(5, 10)
/// What the animal's milking product is.
var/milk_type = /singleton/reagent/drink/milk
var/list/butchering_products //if anything else is created when butchering this creature, like bones and leather
@@ -181,8 +189,8 @@
reagents = new/datum/reagents(20, src)
nutrition = max_nutrition
if(has_udder)
udder = new(50)
if(can_be_milked)
udder = new(udder_size)
udder.my_atom = src
if(LAZYLEN(natural_armor))
@@ -311,10 +319,10 @@
if(!atmos_suitable)
apply_damage(unsuitable_atoms_damage, DAMAGE_OXY, used_weapon = "Atmosphere")
if(has_udder)
if(can_be_milked)
if(stat == CONSCIOUS)
if(udder && prob(5))
udder.add_reagent(milk_type, rand(5, 10))
udder.add_reagent(milk_type, rand(milk_regeneration[1], milk_regeneration[2]))
return 1
@@ -577,21 +585,13 @@
qdel(attacking_item)
qdel(src)
if(istype(attacking_item, /obj/item/reagent_containers/glass/rag)) //You can't milk an udder with a rag.
attacked_with_item(attacking_item, user)
return
if(has_udder)
if(can_be_milked)
var/obj/item/reagent_containers/glass/G = attacking_item
if(stat == CONSCIOUS && istype(G) && G.is_open_container())
if(udder.total_volume <= 0)
to_chat(user, SPAN_WARNING("The udder is dry."))
return
if(G.reagents.total_volume >= G.volume)
to_chat(user, SPAN_WARNING("The [attacking_item] is full."))
return
user.visible_message("<b>\The [user]</b> milks \the [src] using \the [attacking_item].")
udder.trans_type_to(G, milk_type, rand(5, 10))
if(istype(G, /obj/item/reagent_containers/glass/rag)) //You can't milk an udder with a rag.
attacked_with_item(attacking_item, user)
return
if(stat == CONSCIOUS && istype(G) && G.is_open_container())
handle_milking(user, G)
if(istype(attacking_item, /obj/item/reagent_containers) || istype(attacking_item, /obj/item/stack/medical) || istype(attacking_item,/obj/item/gripper/))
..()
@@ -1018,6 +1018,16 @@
/mob/living/simple_animal/InStasis()
return in_stasis
/mob/living/simple_animal/proc/handle_milking(mob/user, obj/item/reagent_containers/container)
if(udder.total_volume <= 0)
to_chat(user, SPAN_WARNING("There is nothing left to collect."))
return
if(container.reagents.total_volume >= container.volume)
to_chat(user, SPAN_WARNING("The [container] is full."))
return
user.visible_message("<b>\The [user]</b> milks \the [src] using \the [container].")
udder.trans_type_to(container, milk_type, rand(milk_regeneration[1], milk_regeneration[2]))
#undef BLOOD_NONE
#undef BLOOD_LIGHT
#undef BLOOD_MEDIUM