Adds Isopods (#31842)

* Adds Isopods

* Fix

* Moved some values

* Om nom nom

* Pickups

* Linters

* Adjusted name
This commit is contained in:
PollardTheDragon
2026-04-14 03:16:49 +00:00
committed by GitHub
parent 3d934ba704
commit fb29bc6f4f
16 changed files with 202 additions and 2 deletions
+1
View File
@@ -52,6 +52,7 @@
/mob/living/basic/diona_nymph = 5,
/mob/living/basic/crab = 5,
/mob/living/basic/mouse = 5,
/mob/living/basic/isopod/small = 5,
/mob/living/simple_animal/pet/dog/corgi = 5,
/mob/living/simple_animal/hostile/retaliate/carp/koi = 5
)
+7 -1
View File
@@ -1,6 +1,7 @@
#define VERM_MICE 0
#define VERM_LIZARDS 1
#define VERM_SPIDERS 2
#define VERM_ISOPODS 3
/datum/event/infestation
name = "Vermin Infestation"
@@ -53,7 +54,7 @@
/datum/event/infestation/proc/spawn_on_turfs(list/turfs)
var/list/spawn_types = list()
var/max_number
vermin = rand(0, 2)
vermin = rand(0, 3)
switch(vermin)
if(VERM_MICE)
spawn_types = list(/mob/living/basic/mouse/gray, /mob/living/basic/mouse/brown, /mob/living/basic/mouse/white)
@@ -67,6 +68,10 @@
spawn_types = list(/mob/living/basic/spiderling)
max_number = 3
vermstring = "spiders"
if(VERM_ISOPODS)
spawn_types = list(/mob/living/basic/isopod/small)
max_number = 2
vermstring = "isopods"
var/amount_to_spawn = rand(2, max_number)
while(length(turfs) && amount_to_spawn > 0)
var/turf/simulated/floor/T = pick_n_take(turfs)
@@ -95,3 +100,4 @@
#undef VERM_MICE
#undef VERM_LIZARDS
#undef VERM_SPIDERS
#undef VERM_ISOPODS
@@ -0,0 +1,153 @@
/mob/living/basic/isopod
name = "ahuitz"
desc = "A large isopod from Kelune that is usually kept as a ranch animal."
icon_state = "ahuitz"
icon_living = "ahuitz"
icon_dead = "ahuitz_dead"
pass_flags = PASSTABLE | PASSMOB
mob_biotypes = MOB_ORGANIC | MOB_BUG
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
butcher_results = list(/obj/item/food/meat = 1)
minimum_survivable_temperature = 0
maxHealth = 75
health = 75
speed = 2
// What they sound like
voice_name = "ahuitz"
speak_emote = list("chitters", "chatters", "clicks", "clacks")
// Special verbs for when someone interacts with a caterpillar
response_help_continuous = "pets"
response_help_simple = "pet"
response_disarm_continuous = "shoos"
response_disarm_simple = "shoo"
response_harm_continuous = "kicks"
response_harm_simple = "kicks"
// Xenobiology and cargo are the only ways to get the caterpillar.
gold_core_spawnable = FRIENDLY_SPAWN
melee_attack_cooldown_min = 1.5 SECONDS
melee_attack_cooldown_max = 2.5 SECONDS
melee_damage_lower = 5
melee_damage_upper = 10
attack_verb_continuous = "bites"
attack_verb_simple = "bite"
attack_sound = 'sound/weapons/bite.ogg'
ai_controller = /datum/ai_controller/basic_controller/isopod
/// List of stuff that we want to eat
var/static/list/edibles = list(
/obj/item/food,
)
/// Max the bug can eat
var/max_nutrition = 700
/mob/living/basic/isopod/Initialize(mapload)
. = ..()
real_name = name
AddElement(/datum/element/wears_collar)
AddElement(/datum/element/ai_retaliate)
AddElement(/datum/element/basic_eating, heal_amt_ = 2, food_types_ = edibles)
ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(edibles))
RegisterSignal(src, COMSIG_MOB_PRE_EAT, PROC_REF(check_full))
RegisterSignal(src, COMSIG_MOB_ATE, PROC_REF(consume))
/mob/living/basic/isopod/examine_more(mob/user)
. = ..()
. += "Ahuitz are a species incredibly similar to earth isopods - being crustaceans that are commonly found in Kelunes oceans. Well suited for cold environments and requiring little \
food these creatures are often kept as pets or for aquatic ranching. They have a long history of being pseudo selectively bred. With those intended to be pets often being bred for \
bright colors or smaller sizes. They are commonly served in a stew alongside whatever could be foraged, farmed, fished or hunted for. The Ahuitz have little meat relative to their weight \
but are very easy to fish up due to their slow speed and inquisitive nature."
/mob/living/basic/isopod/proc/check_full(datum/source, obj/item/potential_food)
SIGNAL_HANDLER // COMSIG_MOB_PRE_EAT
if(nutrition >= max_nutrition) // Prevents griefing by overeating food items without evolving.
to_chat(src, SPAN_WARNING("You're too full to consume this!"))
return COMSIG_MOB_TERMINATE_EAT
/mob/living/basic/isopod/proc/consume(datum/source, obj/item/potential_food)
SIGNAL_HANDLER // COMSIG_MOB_ATE
var/food_reagents = potential_food.reagents.get_reagent_amount("nutriment") + potential_food.reagents.get_reagent_amount("plantmatter") + potential_food.reagents.get_reagent_amount("protein") + potential_food.reagents.get_reagent_amount("vitamin")
if(food_reagents < 1)
adjust_nutrition(2)
else
adjust_nutrition(food_reagents * 2)
butcher_results = list(/obj/item/food/meat = (MODULUS(nutrition, 100)))
/mob/living/basic/isopod/small
name = "deverka"
desc = "A small isopod from Kelune that is usually kept as a pet."
icon_state = "deverka"
icon_living = "deverka"
icon_dead = "deverka_dead"
maxHealth = 30
health = 30
melee_damage_lower = 1
melee_damage_upper = 5
mob_size = MOB_SIZE_SMALL
ventcrawler = VENTCRAWLER_ALWAYS
holder_type = /obj/item/holder/isopod_smol
ai_controller = /datum/ai_controller/basic_controller/isopod/small
max_nutrition = 400
/mob/living/basic/isopod/small/attack_hand(mob/living/carbon/human/M)
// Let people pick the little buggers up.
if(M.a_intent != INTENT_HELP)
return ..()
if(isrobot(M))
M.visible_message(SPAN_NOTICE("[M] playfully boops [src]!"), SPAN_NOTICE("You playfully boop [src]!"))
else
get_scooped(M)
/mob/living/basic/isopod/small/consume(datum/source, obj/item/potential_food)
var/food_reagents = potential_food.reagents.get_reagent_amount("nutriment") + potential_food.reagents.get_reagent_amount("plantmatter") + potential_food.reagents.get_reagent_amount("protein") + potential_food.reagents.get_reagent_amount("vitamin")
if(food_reagents < 1)
adjust_nutrition(2)
else
adjust_nutrition(food_reagents * 2)
/datum/ai_controller/basic_controller/isopod
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
BB_EAT_FOOD_COOLDOWN = 1 MINUTES, // Isopod wants to eat, but not too fast.
BB_SEARCH_RANGE = 3,
)
ai_traits = AI_FLAG_STOP_MOVING_WHEN_PULLED | AI_FLAG_PAUSE_DURING_DO_AFTER
ai_movement = /datum/ai_movement/basic_avoidance
idle_behavior = /datum/idle_behavior/idle_random_walk
planning_subtrees = list(
/datum/ai_planning_subtree/random_speech/isopod,
/datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee,
/datum/ai_planning_subtree/flee_target,
/datum/ai_planning_subtree/find_food/isopod,
)
/datum/ai_controller/basic_controller/isopod/small
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
BB_EAT_FOOD_COOLDOWN = 4 MINUTES, // Smol isopod wants to eat, but not fast at all.
BB_SEARCH_RANGE = 3,
)
/datum/ai_planning_subtree/find_food/isopod
/datum/ai_planning_subtree/find_food/isopod/select_behaviors(datum/ai_controller/controller, seconds_per_tick)
var/mob/living/basic/isopod/pod = controller.pawn
if(pod.nutrition >= pod.max_nutrition)
// Put eating on cooldown so it doesn't keep trying to eat.
var/food_cooldown = controller.blackboard[BB_EAT_FOOD_COOLDOWN] || EAT_FOOD_COOLDOWN
controller.set_blackboard_key(BB_NEXT_FOOD_EAT, world.time + food_cooldown)
return SUBTREE_RETURN_FINISH_PLANNING
return ..()
/datum/ai_planning_subtree/random_speech/isopod
speech_chance = 2
sound = list('sound/creatures/chitter.ogg', 'sound/effects/kidanclack.ogg', 'sound/effects/kidanclack2.ogg')
emote_hear = list("clicks.", "chitters.", "chatters.", "clacks.")
emote_see = list("clicks.", "chitters.", "chatters.", "clacks.")
@@ -43,7 +43,7 @@
"lantern" = /obj/item/organ/internal/lantern
)
allowed_consumed_mobs = list(/mob/living/basic/diona_nymph)
allowed_consumed_mobs = list(/mob/living/basic/diona_nymph, /mob/living/basic/isopod/small)
suicide_messages = list(
"is attempting to bite their antenna off!",
@@ -51,6 +51,7 @@
/mob/living/basic/butterfly,
/mob/living/simple_animal/parrot,
/mob/living/basic/bee,
/mob/living/basic/isopod/small,
)
suicide_messages = list(
@@ -57,6 +57,7 @@
/mob/living/basic/butterfly,
/mob/living/simple_animal/parrot,
/mob/living/basic/bee,
/mob/living/basic/isopod/small,
)
suicide_messages = list(
@@ -47,6 +47,7 @@
/mob/living/basic/butterfly,
/mob/living/simple_animal/parrot,
/mob/living/basic/bee,
/mob/living/basic/isopod/small,
)
suicide_messages = list(
@@ -1160,6 +1160,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
"Cockroach",
"Nian Caterpillar",
"Slime",
"Isopod",
"Mecha-Cat",
"Mecha-Fairy",
"Mecha-Fox",
@@ -1228,6 +1229,8 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
holo_icon = getHologramIcon(icon('icons/mob/monkey.dmi', "mothroach"), FALSE, hologram_color)
if("Slime")
holo_icon = getHologramIcon(icon('icons/mob/slimes.dmi', "grey baby slime"), FALSE, hologram_color)
if("Isopod")
holo_icon = getHologramIcon(icon('icons/mob/animal.dmi', "ahuitz"), FALSE, hologram_color)
if("Mecha-Cat")
holo_icon = getHologramIcon(icon('icons/mob/pai.dmi', "cat"), FALSE, hologram_color)
if("Mecha-Fairy")
+7
View File
@@ -100,6 +100,13 @@
icon_state = "mothroach"
slot_flags = ITEM_SLOT_HEAD
/obj/item/holder/isopod_smol
name = "deverka"
desc = "A tiny isopod that wriggles and chitters!"
icon_state = "deverka"
w_class = WEIGHT_CLASS_SMALL
slot_flags = null
/obj/item/holder/drone/emagged
icon_state = "drone-emagged"
@@ -243,6 +243,15 @@
containertype = /obj/structure/closet/critter/pig
containername = "pig crate"
/datum/supply_packs/organic/isopod
name = "Ahuitz Crate"
cost = 100
contains_special = list(
"Ahuitz"
)
containertype = /obj/structure/closet/critter/cow
containername = "ahuitz crate"
/datum/supply_packs/organic/goat
name = "Goat Crate"
cost = 100
@@ -291,6 +300,15 @@
/obj/item/toy/cattoy)
containername = "cat crate"
/datum/supply_packs/organic/isopod_smol
name = "Deverka Crate"
cost = 300
contains_special = list(
"Deverka"
)
containertype = /obj/structure/closet/critter/isopod_smol
containername = "deverka crate"
/datum/supply_packs/organic/pug
name = "Pug Crate"
cost = 300