diff --git a/_maps/map_files/stations/boxstation.dmm b/_maps/map_files/stations/boxstation.dmm
index 9164adc8df4..fd4e95b04aa 100644
--- a/_maps/map_files/stations/boxstation.dmm
+++ b/_maps/map_files/stations/boxstation.dmm
@@ -64377,6 +64377,7 @@
"jrt" = (
/obj/structure/rack,
/obj/item/storage/box/monkeycubes/wolpincubes,
+/obj/item/storage/box/monkeycubes/nian_worme_cubes,
/turf/simulated/floor/plating,
/area/station/maintenance/asmaint)
"jrI" = (
@@ -69380,6 +69381,7 @@
layer = 2.9
},
/obj/item/storage/box/monkeycubes/wolpincubes,
+/obj/item/storage/box/monkeycubes/nian_worme_cubes,
/obj/machinery/light,
/obj/item/storage/box/monkeycubes/farwacubes{
pixel_x = -6
@@ -77012,6 +77014,7 @@
/obj/item/storage/box/monkeycubes/stokcubes,
/obj/item/storage/box/monkeycubes/neaeracubes,
/obj/item/storage/box/monkeycubes/wolpincubes,
+/obj/item/storage/box/monkeycubes/nian_worme_cubes,
/obj/item/storage/box/monkeycubes/farwacubes,
/obj/structure/table,
/obj/machinery/atmospherics/pipe/simple/hidden/universal,
diff --git a/_maps/map_files/stations/cerestation.dmm b/_maps/map_files/stations/cerestation.dmm
index c209a8b4c46..fe4e52971ed 100644
--- a/_maps/map_files/stations/cerestation.dmm
+++ b/_maps/map_files/stations/cerestation.dmm
@@ -88216,6 +88216,7 @@
/obj/item/storage/box/monkeycubes/neaeracubes,
/obj/item/storage/box/monkeycubes/stokcubes,
/obj/item/storage/box/monkeycubes/wolpincubes,
+/obj/item/storage/box/monkeycubes/nian_worme_cubes,
/obj/machinery/requests_console{
department = "Genetics";
departmentType = 1;
diff --git a/_maps/map_files/stations/metastation.dmm b/_maps/map_files/stations/metastation.dmm
index c50390ea6ca..88a986c0ede 100644
--- a/_maps/map_files/stations/metastation.dmm
+++ b/_maps/map_files/stations/metastation.dmm
@@ -74699,6 +74699,7 @@
/obj/item/storage/box/monkeycubes/neaeracubes,
/obj/structure/table/glass,
/obj/item/storage/box/monkeycubes/wolpincubes,
+/obj/item/storage/box/monkeycubes/nian_worme_cubes,
/obj/item/storage/box/monkeycubes/farwacubes,
/turf/simulated/floor/grass/no_creep,
/area/station/science/genetics)
diff --git a/code/__DEFINES/mob_defines.dm b/code/__DEFINES/mob_defines.dm
index 5c1d026c3ae..c9725785dcd 100644
--- a/code/__DEFINES/mob_defines.dm
+++ b/code/__DEFINES/mob_defines.dm
@@ -203,6 +203,13 @@
#define INVISIBILITY_ABSTRACT 101
#define UNHEALING_EAR_DAMAGE 100
+/// Nian and Nian Worme cocoon do_after delay, in seconds.
+#define COCOON_WEAVE_DELAY 5 SECONDS
+/// Nian and Nian worme delay after they emerge from their cocoon, in seconds.
+#define COCOON_EMERGE_DELAY 15 SECONDS
+/// Nian and nian worme fly swatter damage multiplier, X + 1 => Total multiplier. (Ex. Value of 9 => 10x dmg)
+#define FLYSWATTER_DAMAGE_MULTIPLIER 9
+
/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
#define EXAMINE_MORE_WINDOW 1 SECONDS
@@ -240,6 +247,7 @@
#define isbot(A) (istype((A), /mob/living/simple_animal/bot))
#define isguardian(A) (istype((A), /mob/living/simple_animal/hostile/guardian))
#define isnymph(A) (istype((A), /mob/living/simple_animal/diona))
+#define iscaterpillar(A) (istype((A), /mob/living/simple_animal/nian_caterpillar))
#define ishostile(A) (istype((A), /mob/living/simple_animal/hostile))
#define isretaliate(A) (istype((A), /mob/living/simple_animal/hostile/retaliate))
#define isterrorspider(A) (istype((A), /mob/living/simple_animal/hostile/poison/terror_spider))
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index 3a8d118ef4a..19ce427d493 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -358,6 +358,12 @@
icon_state = "wolpin_box"
monkey_cube_type = /obj/item/food/snacks/monkeycube/wolpincube
+/obj/item/storage/box/monkeycubes/nian_worme_cubes
+ name = "nian worme cube box"
+ desc = "Nian Trade Guild brand worme cubes. Just add water!"
+ icon_state = "nian_worme_box"
+ monkey_cube_type = /obj/item/food/snacks/monkeycube/nian_wormecube
+
///////////////////
/* Medical Boxes */
///////////////////
diff --git a/code/game/objects/structures/crates_lockers/crittercrate.dm b/code/game/objects/structures/crates_lockers/crittercrate.dm
index f43181be3aa..d11418b046e 100644
--- a/code/game/objects/structures/crates_lockers/crittercrate.dm
+++ b/code/game/objects/structures/crates_lockers/crittercrate.dm
@@ -109,6 +109,10 @@
name = "butterfly crate"
content_mob = /mob/living/simple_animal/butterfly
+/obj/structure/closet/critter/nian_caterpillar
+ name = "nian caterpillar crate"
+ content_mob = /mob/living/simple_animal/nian_caterpillar
+
/obj/structure/closet/critter/deer
name = "deer crate"
content_mob = /mob/living/simple_animal/deer
diff --git a/code/modules/food_and_drinks/food/foods/meat.dm b/code/modules/food_and_drinks/food/foods/meat.dm
index 20e57c7c0ed..348e0afdf36 100644
--- a/code/modules/food_and_drinks/food/foods/meat.dm
+++ b/code/modules/food_and_drinks/food/foods/meat.dm
@@ -391,6 +391,10 @@
name = "wolpin cube"
monkey_type = /datum/species/monkey/vulpkanin
+/obj/item/food/snacks/monkeycube/nian_wormecube
+ name = "nian worme cube"
+ monkey_type = /datum/species/monkey/nian_worme
+
/obj/item/food/snacks/monkeycube/stokcube
name = "stok cube"
monkey_type = /datum/species/monkey/unathi
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index 4f47e4a8863..c79f57df345 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -174,6 +174,10 @@
N.visible_message("[N] nibbles away at [src].", "")
N.adjustHealth(-2)
N.taste(reagents)
+ else if(iscaterpillar(M))
+ var/mob/living/simple_animal/nian_caterpillar/W = M
+ W.taste(reagents)
+ W.consume(src)
/obj/item/food/snacks/sliceable/examine(mob/user)
. = ..()
diff --git a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
index 512d3359c99..7fdbbfbde7e 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm
@@ -73,14 +73,16 @@ GLOBAL_LIST_EMPTY(monkey_recyclers)
cycle_through++
switch(cycle_through)
if(1)
- cube_type = /obj/item/food/snacks/monkeycube/farwacube
+ cube_type = /obj/item/food/snacks/monkeycube/nian_wormecube
if(2)
- cube_type = /obj/item/food/snacks/monkeycube/wolpincube
+ cube_type = /obj/item/food/snacks/monkeycube/farwacube
if(3)
- cube_type = /obj/item/food/snacks/monkeycube/stokcube
+ cube_type = /obj/item/food/snacks/monkeycube/wolpincube
if(4)
- cube_type = /obj/item/food/snacks/monkeycube/neaeracube
+ cube_type = /obj/item/food/snacks/monkeycube/stokcube
if(5)
+ cube_type = /obj/item/food/snacks/monkeycube/neaeracube
+ if(6)
cube_type = /obj/item/food/snacks/monkeycube
cycle_through = 0
to_chat(user, "You change the monkeycube type to [initial(cube_type.name)].")
diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm
index 07f388cc4c1..a879a488e57 100644
--- a/code/modules/mob/living/carbon/human/human_mob.dm
+++ b/code/modules/mob/living/carbon/human/human_mob.dm
@@ -165,6 +165,9 @@
/mob/living/carbon/human/stok/Initialize(mapload)
. = ..(mapload, /datum/species/monkey/unathi)
+/mob/living/carbon/human/nian_worme/Initialize(mapload)
+ . = ..(mapload, /datum/species/monkey/nian_worme)
+
/mob/living/carbon/human/moth/Initialize(mapload)
. = ..(mapload, /datum/species/moth)
if(!body_accessory)
diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm
index 02439084da1..9494070c058 100644
--- a/code/modules/mob/living/carbon/human/species/monkey.dm
+++ b/code/modules/mob/living/carbon/human/species/monkey.dm
@@ -62,7 +62,7 @@
/datum/species/monkey/on_species_gain(mob/living/carbon/human/H)
..()
- H.real_name = "[lowertext(name)] ([rand(100,999)])"
+ H.real_name = get_random_name()
H.name = H.real_name
H.butcher_results = list(/obj/item/food/snacks/meat/monkey = 5)
@@ -85,13 +85,13 @@
tail = "farwatail"
reagent_tag = PROCESS_ORG
has_organ = list(
- "heart" = /obj/item/organ/internal/heart/tajaran,
- "lungs" = /obj/item/organ/internal/lungs/tajaran,
- "liver" = /obj/item/organ/internal/liver/tajaran,
- "kidneys" = /obj/item/organ/internal/kidneys/tajaran,
- "brain" = /obj/item/organ/internal/brain/tajaran,
- "appendix" = /obj/item/organ/internal/appendix,
- "eyes" = /obj/item/organ/internal/eyes/tajaran/farwa //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
+ "heart" = /obj/item/organ/internal/heart/tajaran,
+ "lungs" = /obj/item/organ/internal/lungs/tajaran,
+ "liver" = /obj/item/organ/internal/liver/tajaran,
+ "kidneys" = /obj/item/organ/internal/kidneys/tajaran,
+ "brain" = /obj/item/organ/internal/brain/tajaran,
+ "appendix" = /obj/item/organ/internal/appendix,
+ "eyes" = /obj/item/organ/internal/eyes/tajaran/farwa //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
)
@@ -108,13 +108,13 @@
tail = "wolpintail"
reagent_tag = PROCESS_ORG
has_organ = list(
- "heart" = /obj/item/organ/internal/heart/vulpkanin,
- "lungs" = /obj/item/organ/internal/lungs/vulpkanin,
- "liver" = /obj/item/organ/internal/liver/vulpkanin,
- "kidneys" = /obj/item/organ/internal/kidneys/vulpkanin,
- "brain" = /obj/item/organ/internal/brain/vulpkanin,
- "appendix" = /obj/item/organ/internal/appendix,
- "eyes" = /obj/item/organ/internal/eyes/vulpkanin/wolpin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
+ "heart" = /obj/item/organ/internal/heart/vulpkanin,
+ "lungs" = /obj/item/organ/internal/lungs/vulpkanin,
+ "liver" = /obj/item/organ/internal/liver/vulpkanin,
+ "kidneys" = /obj/item/organ/internal/kidneys/vulpkanin,
+ "brain" = /obj/item/organ/internal/brain/vulpkanin,
+ "appendix" = /obj/item/organ/internal/appendix,
+ "eyes" = /obj/item/organ/internal/eyes/vulpkanin/wolpin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
)
@@ -134,13 +134,13 @@
inherent_traits = list(TRAIT_NOEXAMINE, TRAIT_NOFAT, TRAIT_WATERBREATH)
has_organ = list(
- "heart" = /obj/item/organ/internal/heart/skrell,
- "lungs" = /obj/item/organ/internal/lungs/skrell,
- "liver" = /obj/item/organ/internal/liver/skrell,
- "kidneys" = /obj/item/organ/internal/kidneys/skrell,
- "brain" = /obj/item/organ/internal/brain/skrell,
- "appendix" = /obj/item/organ/internal/appendix,
- "eyes" = /obj/item/organ/internal/eyes/skrell //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
+ "heart" = /obj/item/organ/internal/heart/skrell,
+ "lungs" = /obj/item/organ/internal/lungs/skrell,
+ "liver" = /obj/item/organ/internal/liver/skrell,
+ "kidneys" = /obj/item/organ/internal/kidneys/skrell,
+ "brain" = /obj/item/organ/internal/brain/skrell,
+ "appendix" = /obj/item/organ/internal/appendix,
+ "eyes" = /obj/item/organ/internal/eyes/skrell //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
)
/datum/species/monkey/unathi
@@ -159,11 +159,40 @@
bodyflags = HAS_TAIL | HAS_BODYACC_COLOR
has_organ = list(
- "heart" = /obj/item/organ/internal/heart/unathi,
- "lungs" = /obj/item/organ/internal/lungs/unathi,
- "liver" = /obj/item/organ/internal/liver/unathi,
- "kidneys" = /obj/item/organ/internal/kidneys/unathi,
- "brain" = /obj/item/organ/internal/brain/unathi,
- "appendix" = /obj/item/organ/internal/appendix,
- "eyes" = /obj/item/organ/internal/eyes/unathi
+ "heart" = /obj/item/organ/internal/heart/unathi,
+ "lungs" = /obj/item/organ/internal/lungs/unathi,
+ "liver" = /obj/item/organ/internal/liver/unathi,
+ "kidneys" = /obj/item/organ/internal/kidneys/unathi,
+ "brain" = /obj/item/organ/internal/brain/unathi,
+ "appendix" = /obj/item/organ/internal/appendix,
+ "eyes" = /obj/item/organ/internal/eyes/unathi
)
+
+/datum/species/monkey/nian_worme
+ name = "nian worme"
+ name_plural = "nian worme"
+ icobase = 'icons/mob/human_races/monkeys/r_worme.dmi'
+ tail = ""
+ total_health = 75
+ inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID | MOB_BUG
+ bodyflags = BALD | SHAVED
+ greater_form = /datum/species/moth
+ default_language = "Tkachi"
+ eyes = "blank_eyes"
+ butt_sprite = "nian"
+ reagent_tag = PROCESS_ORG
+ dietflags = DIET_HERB
+ tox_mod = 3 // Die. Terrible creatures. Die.
+
+ has_organ = list(
+ "heart" = /obj/item/organ/internal/heart/nian,
+ "lungs" = /obj/item/organ/internal/lungs/nian,
+ "liver" = /obj/item/organ/internal/liver/nian,
+ "kidneys" = /obj/item/organ/internal/kidneys/nian,
+ "brain" = /obj/item/organ/internal/brain/nian,
+ "eyes" = /obj/item/organ/internal/eyes/nian
+ )
+
+/datum/species/monkey/nian_worme/spec_attacked_by(obj/item/I, mob/living/user, obj/item/organ/external/affecting, intent, mob/living/carbon/human/H)
+ if(istype(I, /obj/item/melee/flyswatter) && I.force)
+ apply_damage(I.force * FLYSWATTER_DAMAGE_MULTIPLIER, I.damtype, affecting, FALSE, H) // making flyswatters do 15x damage to moff
diff --git a/code/modules/mob/living/carbon/human/species/moth.dm b/code/modules/mob/living/carbon/human/species/moth.dm
index a492e31c7d5..b9b298e6cf0 100644
--- a/code/modules/mob/living/carbon/human/species/moth.dm
+++ b/code/modules/mob/living/carbon/human/species/moth.dm
@@ -1,8 +1,5 @@
-#define COCOON_WEAVE_DELAY 5 SECONDS
-#define COCOON_EMERGE_DELAY 15 SECONDS
#define COCOON_HARM_AMOUNT 50
#define COCOON_NUTRITION_AMOUNT -200
-#define FLYSWATTER_DAMAGE_MULTIPLIER 9
/datum/species/moth
name = "Nian"
@@ -51,6 +48,8 @@
"eyes" = /obj/item/organ/internal/eyes/nian
)
+ primitive_form = /datum/species/monkey/nian_worme
+
optional_body_accessory = FALSE
suicide_messages = list(
@@ -75,7 +74,6 @@
H.change_icobase(new_icobase, owner_sensitive) //Update the icobase of all our organs, but make sure we don't mess with frankenstein limbs in doing so.
-
/datum/species/moth/on_species_gain(mob/living/carbon/human/H)
..()
var/datum/action/innate/cocoon/cocoon = new()
@@ -244,8 +242,5 @@
id = "cocooned"
alert_type = null
-#undef COCOON_WEAVE_DELAY
-#undef COCOON_EMERGE_DELAY
#undef COCOON_HARM_AMOUNT
#undef COCOON_NUTRITION_AMOUNT
-#undef FLYSWATTER_DAMAGE_MULTIPLIER
diff --git a/code/modules/mob/living/simple_animal/friendly/nian_caterpillar.dm b/code/modules/mob/living/simple_animal/friendly/nian_caterpillar.dm
new file mode 100644
index 00000000000..be2e565d63d
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/friendly/nian_caterpillar.dm
@@ -0,0 +1,149 @@
+/mob/living/simple_animal/nian_caterpillar
+ name = "nian caterpillar"
+ icon = 'icons/mob/monkey.dmi'
+ icon_state = "mothroach"
+ icon_living = "mothroach"
+ icon_dead = "mothroach_dead"
+ icon_resting = "mothroach_sleep"
+ pass_flags = PASSTABLE | PASSMOB
+ mob_biotypes = MOB_ORGANIC | MOB_BUG
+ mob_size = MOB_SIZE_SMALL
+ ventcrawler = VENTCRAWLER_ALWAYS
+ 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/snacks/meat = 1)
+ minbodytemp = 0
+
+ blood_color = "#b9ae9c"
+
+ maxHealth = 50
+ health = 50
+ speed = 0.75
+ stop_automated_movement = FALSE
+ turns_per_move = 4
+
+ // What they sound like
+ voice_name = "nian caterpillar"
+ speak_emote = list("flutters", "chitters", "chatters")
+ emote_hear = list("flutters", "chitters", "chatters")
+ emote_see = list("flutters", "chitters", "chatters")
+
+ // Special verbs for when someone interacts with a caterpillar
+ response_help = "pets"
+ response_disarm = "shoos"
+ response_harm = "kicks"
+
+ // Xenobiology and cargo are the only ways to get the caterpillar.
+ gold_core_spawnable = FRIENDLY_SPAWN
+
+ melee_damage_lower = 5
+ melee_damage_upper = 8
+ attacktext = "bites"
+ attack_sound = 'sound/weapons/bite.ogg'
+
+ holder_type = /obj/item/holder/nian_caterpillar
+ can_collar = TRUE
+
+ /// Evolution action.
+ var/datum/action/innate/nian_caterpillar_emerge/evolve_action = new()
+ /// The amount of nutrition the nian caterpillar needs to evolve.
+ var/nutrition_need = 500
+
+/mob/living/simple_animal/nian_caterpillar/Initialize()
+ . = ..()
+ real_name = name
+ add_language("Tkachi")
+ evolve_action.Grant(src)
+
+/mob/living/simple_animal/nian_caterpillar/proc/evolve(obj/structure/moth/cocoon/C, datum/mind/M)
+ if(stat != CONSCIOUS)
+ return FALSE
+
+ // A changeling caterpillar shouldn't be restricted from evolving.
+ // A caterpillar needs to consume food-- similar to a dioan nymph --to evolve.
+ if((nutrition < nutrition_need) && !IS_CHANGELING(M))
+ to_chat(src, "You need to binge on food in order to have the energy to evolve...")
+ return
+
+ // Worme is the lesser form of nian. The caterpillar evolves into this lesser form.
+ var/mob/living/carbon/human/nian_worme/adult = new(get_turf(loc))
+
+ if(istype(loc, /obj/item/holder/nian_caterpillar))
+ var/turf/cocoon_turf = get_turf(loc)
+ qdel(loc)
+ forceMove(cocoon_turf)
+
+ for(var/datum/language/L in languages)
+ adult.add_language(L.name)
+ adult.regenerate_icons()
+ adult.name = name
+ adult.real_name = name
+
+ // Mind transfer to new worme.
+ M.transfer_to(adult)
+
+ // Worme is placed into cacoon.
+ adult.forceMove(C)
+ C.preparing_to_emerge = TRUE
+ adult.apply_status_effect(STATUS_EFFECT_COCOONED)
+ adult.KnockOut() // Zzzz
+ adult.create_log(MISC_LOG, "has woven a cocoon")
+
+ // For any random generated names. This is for when a new nian caterpillar is spawned.
+ // [ nian caterpillar (042) ] etc.
+ if(findtext(adult.real_name, "nian caterpillar"))
+ adult.real_name = adult.dna.species.get_random_name()
+ adult.name = adult.real_name
+ for(var/obj/item/W in contents)
+ unEquip(W)
+
+ qdel(src)
+ return TRUE
+
+/mob/living/simple_animal/nian_caterpillar/proc/consume(obj/item/food/snacks/G)
+ if(nutrition >= nutrition_need) // Prevents griefing by overeating food items without evolving.
+ return to_chat(src, "You're too full to consume this! Perhaps it's time to grow bigger...")
+ visible_message("[src] ravenously consumes [G].", "You ravenously devour [G].")
+ playsound(loc, 'sound/items/eatfood.ogg', 30, TRUE, frequency = 1.5)
+ if(G.reagents.get_reagent_amount("nutriment") + G.reagents.get_reagent_amount("plantmatter") < 1)
+ adjust_nutrition(2)
+ else
+ adjust_nutrition((G.reagents.get_reagent_amount("nutriment") + G.reagents.get_reagent_amount("plantmatter")) * 2)
+ qdel(G)
+
+/mob/living/simple_animal/nian_caterpillar/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("[M] playfully boops [src] on the head!", "You playfully boop [src] on the head!")
+ else
+ get_scooped(M)
+
+/mob/living/simple_animal/nian_caterpillar/attacked_by(obj/item/I, mob/living/user, def_zone)
+ if(istype(I, /obj/item/melee/flyswatter) && I.force)
+ gib() // Commit die.
+ else
+ ..()
+
+/datum/action/innate/nian_caterpillar_emerge
+ name = "Evolve"
+ desc = "Weave a cocoon around yourself to evolve into a greater form. The worme."
+ icon_icon = 'icons/effects/effects.dmi'
+ button_icon_state = "cocoon1"
+
+/datum/action/innate/nian_caterpillar_emerge/proc/emerge(obj/structure/moth/cocoon/C)
+ for(var/mob/living/carbon/human/H in C)
+ H.remove_status_effect(STATUS_EFFECT_COCOONED)
+ H.remove_status_effect(STATUS_EFFECT_BURNT_WINGS)
+ C.preparing_to_emerge = FALSE
+ qdel(C)
+
+/datum/action/innate/nian_caterpillar_emerge/Activate()
+ var/mob/living/simple_animal/nian_caterpillar/user = owner
+
+ user.visible_message("[user] begins to hold still and concentrate on weaving a cocoon...", "You begin to focus on weaving a cocoon... (This will take [COCOON_WEAVE_DELAY / 10] seconds, and you must hold still.)")
+ if(do_after(user, COCOON_WEAVE_DELAY, FALSE, user))
+ var/obj/structure/moth/cocoon/C = new(get_turf(user))
+ var/datum/mind/H = user.mind
+ user.evolve(C, H)
+ addtimer(CALLBACK(src, PROC_REF(emerge), C), COCOON_EMERGE_DELAY, TIMER_UNIQUE)
diff --git a/code/modules/mob/mob_holder.dm b/code/modules/mob/mob_holder.dm
index 36ce7a9ed34..e727ab7af83 100644
--- a/code/modules/mob/mob_holder.dm
+++ b/code/modules/mob/mob_holder.dm
@@ -94,6 +94,12 @@
desc = "It's a small maintenance robot."
icon_state = "drone"
+/obj/item/holder/nian_caterpillar
+ name = "nian caterpillar"
+ desc = "It's a tiny little itty bitty critter."
+ icon_state = "mothroach"
+ slot_flags = SLOT_FLAG_HEAD
+
/obj/item/holder/drone/emagged
name = "maintenance drone"
icon_state = "drone-emagged"
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 4225b79bc0e..a36b1092d18 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -267,6 +267,7 @@
var/mob/living/carbon/human/C = owner
var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = target
+ var/obj/machinery/monkey_recycler/recycler = X.connected_recycler
if(GLOB.cameranet.checkTurfVis(remote_eye.loc))
if(LAZYLEN(SSmobs.cubemonkeys) >= GLOB.configuration.general.monkey_cube_cap)
@@ -279,7 +280,20 @@
to_chat(owner, "[X] doesn't have monkeys.")
return
else if(X.monkeys >= 1)
- var/mob/living/carbon/human/monkey/food = new /mob/living/carbon/human/monkey(remote_eye.loc)
+ var/mob/living/carbon/human/monkey/food
+ switch(recycler.cube_type)
+ if(/obj/item/food/snacks/monkeycube) // Regular monkey
+ food = new /mob/living/carbon/human/monkey(remote_eye.loc)
+ if(/obj/item/food/snacks/monkeycube/nian_wormecube) // Worme
+ food = new /mob/living/carbon/human/nian_worme(remote_eye.loc)
+ if(/obj/item/food/snacks/monkeycube/farwacube) // Farwa
+ food = new /mob/living/carbon/human/farwa(remote_eye.loc)
+ if(/obj/item/food/snacks/monkeycube/stokcube) // Stok
+ food = new /mob/living/carbon/human/stok(remote_eye.loc)
+ if(/obj/item/food/snacks/monkeycube/neaeracube) // Neara
+ food = new /mob/living/carbon/human/neara(remote_eye.loc)
+ if(/obj/item/food/snacks/monkeycube/wolpincube) // Wolpin
+ food = new /mob/living/carbon/human/wolpin(remote_eye.loc)
SSmobs.cubemonkeys += food
food.LAssailant = C
X.monkeys --
@@ -471,13 +485,27 @@
var/mob/living/C = user
var/mob/camera/aiEye/remote/xenobio/E = C.remote_control
var/obj/machinery/computer/camera_advanced/xenobio/X = E.origin
+ var/obj/machinery/monkey_recycler/recycler = X.connected_recycler
var/area/turfarea = get_area(T)
if(iswallturf(T))
to_chat(user, "You can't place monkey here.")
return
else if(turfarea.name == E.allowed_area || turfarea.xenobiology_compatible)
if(X.monkeys >= 1)
- var/mob/living/carbon/human/monkey/food = new /mob/living/carbon/human/monkey(T)
+ var/mob/living/carbon/human/monkey/food
+ switch(recycler.cube_type)
+ if(/obj/item/food/snacks/monkeycube) // Regular monkey
+ food = new /mob/living/carbon/human/monkey(T)
+ if(/obj/item/food/snacks/monkeycube/nian_wormecube) // Worme
+ food = new /mob/living/carbon/human/nian_worme(T)
+ if(/obj/item/food/snacks/monkeycube/farwacube) // Farwa
+ food = new /mob/living/carbon/human/farwa(T)
+ if(/obj/item/food/snacks/monkeycube/stokcube) // Stok
+ food = new /mob/living/carbon/human/stok(T)
+ if(/obj/item/food/snacks/monkeycube/neaeracube) // Neara
+ food = new /mob/living/carbon/human/neara(T)
+ if(/obj/item/food/snacks/monkeycube/wolpincube) // Wolpin
+ food = new /mob/living/carbon/human/wolpin(T)
food.LAssailant = C
X.monkeys--
X.monkeys = round(X.monkeys, 0.1)
diff --git a/code/modules/supply/supply_packs/pack_organic.dm b/code/modules/supply/supply_packs/pack_organic.dm
index fbf65d45170..017ad9b3324 100644
--- a/code/modules/supply/supply_packs/pack_organic.dm
+++ b/code/modules/supply/supply_packs/pack_organic.dm
@@ -83,6 +83,13 @@
containername = "monkey crate"
department_restrictions = list(DEPARTMENT_SERVICE, DEPARTMENT_MEDICAL, DEPARTMENT_SCIENCE)
+/datum/supply_packs/organic/nian_worme
+ name = "Nian Worme Crate"
+ contains = list (/obj/item/storage/box/monkeycubes/nian_worme_cubes)
+ cost = 200
+ containername = "nian worme crate"
+ department_restrictions = list(DEPARTMENT_SERVICE, DEPARTMENT_MEDICAL, DEPARTMENT_SCIENCE)
+
/datum/supply_packs/organic/farwa
name = "Farwa Crate"
contains = list (/obj/item/storage/box/monkeycubes/farwacubes)
@@ -210,6 +217,13 @@
containertype = /obj/structure/closet/critter/butterfly
containername = "butterfly crate"
+/datum/supply_packs/organic/nian_caterpillar
+ name = "Nian Caterpillar Crate"
+ cost = 150
+ containertype = /obj/structure/closet/critter/nian_caterpillar
+ contains = list(/obj/item/petcollar)
+ containername = "nian caterpillar crate"
+
/datum/supply_packs/organic/deer
name = "Deer Crate"
cost = 350 //Deer are best.
diff --git a/icons/mob/clothing/head.dmi b/icons/mob/clothing/head.dmi
index 5b9df84c18b..fa1f0f4d077 100644
Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ
diff --git a/icons/mob/human_races/monkeys/r_worme.dmi b/icons/mob/human_races/monkeys/r_worme.dmi
new file mode 100644
index 00000000000..c10aca7613b
Binary files /dev/null and b/icons/mob/human_races/monkeys/r_worme.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 556989be5d2..955ea724379 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index 5350e346160..c30af0033e5 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/mob/monkey.dmi b/icons/mob/monkey.dmi
index d27ef694cd3..6e6a5263f98 100644
Binary files a/icons/mob/monkey.dmi and b/icons/mob/monkey.dmi differ
diff --git a/icons/obj/boxes.dmi b/icons/obj/boxes.dmi
index 30e866ecc84..2ea89ead99b 100644
Binary files a/icons/obj/boxes.dmi and b/icons/obj/boxes.dmi differ
diff --git a/paradise.dme b/paradise.dme
index fb76fc8abf5..748c7a97a49 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -2320,6 +2320,7 @@
#include "code\modules\mob\living\simple_animal\friendly\sloth.dm"
#include "code\modules\mob\living\simple_animal\friendly\snake.dm"
#include "code\modules\mob\living\simple_animal\friendly\spiderbot.dm"
+#include "code\modules\mob\living\simple_animal\friendly\nian_caterpillar.dm"
#include "code\modules\mob\living\simple_animal\hostile\alien_types.dm"
#include "code\modules\mob\living\simple_animal\hostile\angel_statue.dm"
#include "code\modules\mob\living\simple_animal\hostile\bat.dm"