From b52f6cc6c038ef0130ac314e53d73c5c8862a4ce Mon Sep 17 00:00:00 2001
From: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
Date: Fri, 19 Sep 2025 11:26:43 -0400
Subject: [PATCH] Converts farm animals to basic mobs (#30244)
* Converts farm animals to basic mobs
* Update paths, removes excess file
* CI
---------
Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
---
.../SpaceRuins/syndie_space_base.dmm | 2 +-
_maps/map_files/shuttles/emergency_jungle.dmm | 4 +-
_maps/map_files/stations/boxstation.dmm | 4 +-
_maps/map_files/stations/cerestation.dmm | 4 +-
_maps/map_files/stations/deltastation.dmm | 6 +-
_maps/map_files/stations/emeraldstation.dmm | 4 +-
_maps/map_files/stations/metastation.dmm | 4 +-
.../spell_targeting/matter_eater_targeting.dm | 4 +-
.../structures/crates_lockers/crittercrate.dm | 12 +-
.../structures/crates_lockers/largecrate.dm | 4 +-
code/modules/events/clogged_disposals.dm | 2 +-
.../mob/living/basic/farm_animals/chicken.dm | 257 ++++++++++
.../mob/living/basic/farm_animals/goat.dm | 131 +++++
.../mob/living/basic/farm_animals/goose.dm | 51 ++
.../mob/living/basic/farm_animals/seal.dm | 56 +++
.../mob/living/basic/farm_animals/turkey.dm | 52 ++
.../mob/living/basic/farm_animals/udders.dm | 27 ++
.../living/carbon/human/species/tajaran.dm | 2 +-
.../mob/living/carbon/human/species/unathi.dm | 2 +-
.../living/carbon/human/species/vulpkanin.dm | 2 +-
.../simple_animal/friendly/farm_animals.dm | 448 ------------------
.../projectile/magic_projectiles.dm | 10 +-
paradise.dme | 7 +-
sound/creatures/bagawk.ogg | Bin 0 -> 7285 bytes
sound/creatures/chick_peep.ogg | Bin 0 -> 2845 bytes
sound/creatures/clucks.ogg | Bin 0 -> 10497 bytes
.../Scripts/30244_basic_farm_animals.txt | 7 +
tools/ci/check_simplemob_additions.py | 11 -
28 files changed, 620 insertions(+), 493 deletions(-)
create mode 100644 code/modules/mob/living/basic/farm_animals/chicken.dm
create mode 100644 code/modules/mob/living/basic/farm_animals/goat.dm
create mode 100644 code/modules/mob/living/basic/farm_animals/goose.dm
create mode 100644 code/modules/mob/living/basic/farm_animals/seal.dm
create mode 100644 code/modules/mob/living/basic/farm_animals/turkey.dm
create mode 100644 code/modules/mob/living/basic/farm_animals/udders.dm
delete mode 100644 code/modules/mob/living/simple_animal/friendly/farm_animals.dm
create mode 100644 sound/creatures/bagawk.ogg
create mode 100644 sound/creatures/chick_peep.ogg
create mode 100644 sound/creatures/clucks.ogg
create mode 100644 tools/UpdatePaths/Scripts/30244_basic_farm_animals.txt
diff --git a/_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm b/_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm
index 5604f99d938..0c2b0495a91 100644
--- a/_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm
+++ b/_maps/map_files/RandomRuins/SpaceRuins/syndie_space_base.dmm
@@ -5173,7 +5173,7 @@
name = "Animal Storage";
req_access = list(150)
},
-/mob/living/simple_animal/chicken{
+/mob/living/basic/chicken{
faction = list("neutral","syndicate")
},
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
diff --git a/_maps/map_files/shuttles/emergency_jungle.dmm b/_maps/map_files/shuttles/emergency_jungle.dmm
index fb69b98dc65..270b77e6165 100644
--- a/_maps/map_files/shuttles/emergency_jungle.dmm
+++ b/_maps/map_files/shuttles/emergency_jungle.dmm
@@ -316,7 +316,7 @@
dir = 1
},
/obj/structure/flora/junglebush,
-/mob/living/simple_animal/hostile/retaliate/goat,
+/mob/living/basic/goat,
/turf/simulated/floor/grass,
/area/shuttle/escape)
"bA" = (
@@ -709,7 +709,7 @@
/obj/machinery/light/small{
dir = 4
},
-/mob/living/simple_animal/hostile/retaliate/goat,
+/mob/living/basic/goat,
/turf/simulated/floor/grass,
/area/shuttle/escape)
"qH" = (
diff --git a/_maps/map_files/stations/boxstation.dmm b/_maps/map_files/stations/boxstation.dmm
index e3de69b4279..94e18d4fe36 100644
--- a/_maps/map_files/stations/boxstation.dmm
+++ b/_maps/map_files/stations/boxstation.dmm
@@ -16557,7 +16557,7 @@
},
/area/station/service/hydroponics)
"bfE" = (
-/mob/living/simple_animal/hostile/retaliate/goat/chef,
+/mob/living/basic/goat/chef,
/turf/simulated/floor/plasteel{
icon_state = "showroomfloor"
},
@@ -45752,7 +45752,7 @@
/area/station/service/hydroponics)
"dnE" = (
/obj/machinery/hydroponics/soil,
-/mob/living/simple_animal/chicken/clucky,
+/mob/living/basic/chicken/clucky,
/turf/simulated/floor/grass,
/area/station/service/hydroponics)
"dnF" = (
diff --git a/_maps/map_files/stations/cerestation.dmm b/_maps/map_files/stations/cerestation.dmm
index 60b26a4ac64..955aa079e59 100644
--- a/_maps/map_files/stations/cerestation.dmm
+++ b/_maps/map_files/stations/cerestation.dmm
@@ -93581,7 +93581,7 @@
},
/area/station/service/clown/secret)
"srW" = (
-/mob/living/simple_animal/hostile/retaliate/goat{
+/mob/living/basic/goat{
name = "Pete"
},
/obj/machinery/hologram/holopad,
@@ -97517,7 +97517,7 @@
/area/station/public/dorms)
"thf" = (
/obj/structure/flora/ausbushes/sunnybush,
-/mob/living/simple_animal/chicken/clucky,
+/mob/living/basic/chicken/clucky,
/turf/simulated/floor/grass,
/area/station/service/hydroponics)
"thi" = (
diff --git a/_maps/map_files/stations/deltastation.dmm b/_maps/map_files/stations/deltastation.dmm
index fae3e814839..de725309142 100644
--- a/_maps/map_files/stations/deltastation.dmm
+++ b/_maps/map_files/stations/deltastation.dmm
@@ -13749,7 +13749,7 @@
/turf/simulated/floor/plasteel/dark,
/area/station/engineering/atmos)
"bdz" = (
-/mob/living/simple_animal/chicken/clucky,
+/mob/living/basic/chicken/clucky,
/turf/simulated/floor/grass,
/area/station/service/kitchen)
"bdA" = (
@@ -46459,7 +46459,7 @@
/area/station/science/research)
"dxA" = (
/obj/structure/flora/ausbushes/fullgrass,
-/mob/living/simple_animal/chick{
+/mob/living/basic/chick{
name = "Sins"
},
/turf/simulated/floor/grass,
@@ -86492,7 +86492,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 4
},
-/mob/living/simple_animal/hostile/retaliate/goat/chef,
+/mob/living/basic/goat/chef,
/obj/item/radio/intercom{
name = "north bump";
pixel_y = 28
diff --git a/_maps/map_files/stations/emeraldstation.dmm b/_maps/map_files/stations/emeraldstation.dmm
index f413f808d90..b35279a717d 100644
--- a/_maps/map_files/stations/emeraldstation.dmm
+++ b/_maps/map_files/stations/emeraldstation.dmm
@@ -72539,7 +72539,7 @@
},
/area/station/security/armory/secure)
"osA" = (
-/mob/living/simple_animal/hostile/retaliate/goat/chef,
+/mob/living/basic/goat/chef,
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 6
},
@@ -106745,7 +106745,7 @@
},
/area/station/security/interrogation)
"vgz" = (
-/mob/living/simple_animal/chicken/clucky,
+/mob/living/basic/chicken/clucky,
/turf/simulated/floor/grass,
/area/station/service/kitchen)
"vgB" = (
diff --git a/_maps/map_files/stations/metastation.dmm b/_maps/map_files/stations/metastation.dmm
index a8e6ae51372..b229ee37c1c 100644
--- a/_maps/map_files/stations/metastation.dmm
+++ b/_maps/map_files/stations/metastation.dmm
@@ -64935,7 +64935,7 @@
},
/area/station/science/rnd)
"oHv" = (
-/mob/living/simple_animal/hostile/retaliate/goat/chef,
+/mob/living/basic/goat/chef,
/obj/machinery/atmospherics/pipe/simple/hidden/supply{
dir = 4
},
@@ -71259,7 +71259,7 @@
/turf/simulated/floor/plating,
/area/station/hallway/primary/fore/east)
"qUq" = (
-/mob/living/simple_animal/chicken/clucky,
+/mob/living/basic/chicken/clucky,
/turf/simulated/floor/grass,
/area/station/service/hydroponics)
"qUX" = (
diff --git a/code/datums/spell_targeting/matter_eater_targeting.dm b/code/datums/spell_targeting/matter_eater_targeting.dm
index a44d3b152b6..bb7efb91d0c 100644
--- a/code/datums/spell_targeting/matter_eater_targeting.dm
+++ b/code/datums/spell_targeting/matter_eater_targeting.dm
@@ -14,8 +14,8 @@
/mob/living/simple_animal/slime,
/mob/living/carbon/alien/larva,
/mob/living/simple_animal/slime,
- /mob/living/simple_animal/chick,
- /mob/living/simple_animal/chicken,
+ /mob/living/basic/chick,
+ /mob/living/basic/chicken,
/mob/living/basic/lizard,
/mob/living/basic/cow,
/mob/living/simple_animal/spiderbot
diff --git a/code/game/objects/structures/crates_lockers/crittercrate.dm b/code/game/objects/structures/crates_lockers/crittercrate.dm
index 04bfe0d1a14..b1a8e7d9e08 100644
--- a/code/game/objects/structures/crates_lockers/crittercrate.dm
+++ b/code/game/objects/structures/crates_lockers/crittercrate.dm
@@ -51,9 +51,9 @@
/mob/living/simple_animal/pet/dog/corgi,
/mob/living/simple_animal/pet/dog/corgi/lisa,
- /mob/living/simple_animal/hostile/retaliate/goat,
- /mob/living/simple_animal/turkey,
- /mob/living/simple_animal/chick,
+ /mob/living/basic/goat,
+ /mob/living/basic/turkey,
+ /mob/living/basic/chick,
/mob/living/simple_animal/pet/cat,
/mob/living/simple_animal/pet/dog/pug,
/mob/living/simple_animal/pet/dog/fox,
@@ -77,15 +77,15 @@
/obj/structure/closet/critter/goat
name = "goat crate"
- content_mob = /mob/living/simple_animal/hostile/retaliate/goat
+ content_mob = /mob/living/basic/goat
/obj/structure/closet/critter/turkey
name = "turkey crate"
- content_mob = /mob/living/simple_animal/turkey
+ content_mob = /mob/living/basic/turkey
/obj/structure/closet/critter/chick
name = "chicken crate"
- content_mob = /mob/living/simple_animal/chick
+ content_mob = /mob/living/basic/chick
/obj/structure/closet/critter/chick/populate_contents()
amount = rand(1, 3)
diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm
index 7633872defb..e0189655921 100644
--- a/code/game/objects/structures/crates_lockers/largecrate.dm
+++ b/code/game/objects/structures/crates_lockers/largecrate.dm
@@ -82,7 +82,7 @@
icon_state = "lisacrate"
/obj/structure/largecrate/goat/break_open()
- new /mob/living/simple_animal/hostile/retaliate/goat(loc)
+ new /mob/living/basic/goat(loc)
/obj/structure/largecrate/chick
name = "chicken crate"
@@ -91,7 +91,7 @@
/obj/structure/largecrate/chick/break_open()
var/num = rand(4, 6)
for(var/i in 1 to num)
- new /mob/living/simple_animal/chick(loc)
+ new /mob/living/basic/chick(loc)
/obj/structure/largecrate/cat
name = "cat crate"
diff --git a/code/modules/events/clogged_disposals.dm b/code/modules/events/clogged_disposals.dm
index b75fcc10f6b..21812e8c5f8 100644
--- a/code/modules/events/clogged_disposals.dm
+++ b/code/modules/events/clogged_disposals.dm
@@ -46,7 +46,7 @@
// Retaliate mobs
/mob/living/basic/clown = 5,
/mob/living/basic/clown/goblin = 5,
- /mob/living/simple_animal/hostile/retaliate/goat = 5,
+ /mob/living/basic/goat = 5,
// Friendly
/mob/living/simple_animal/mouse = 5,
/mob/living/simple_animal/diona = 5,
diff --git a/code/modules/mob/living/basic/farm_animals/chicken.dm b/code/modules/mob/living/basic/farm_animals/chicken.dm
new file mode 100644
index 00000000000..005bfd5f5f8
--- /dev/null
+++ b/code/modules/mob/living/basic/farm_animals/chicken.dm
@@ -0,0 +1,257 @@
+/mob/living/basic/chick
+ name = "chick"
+ desc = "Adorable! They make such a racket though."
+ icon_state = "chick"
+ icon_living = "chick"
+ icon_dead = "chick_dead"
+ icon_gib = "chick_gib"
+ gender = FEMALE
+ mob_biotypes = MOB_ORGANIC | MOB_BEAST
+ speak_emote = list("cheeps")
+ density = FALSE
+ butcher_results = list(/obj/item/food/meat/chicken = 1)
+ response_help_continuous = "pets"
+ response_help_simple = "pet"
+ response_disarm_continuous = "gently pushes aside"
+ response_disarm_simple = "gently push aside"
+ response_harm_continuous = "kicks"
+ response_harm_simple = "kick"
+ attack_verb_continuous = "pecks"
+ attack_verb_simple = "peck"
+ health = 3
+ maxHealth = 3
+ ventcrawler = VENTCRAWLER_ALWAYS
+ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
+ mob_size = MOB_SIZE_TINY
+ holder_type = /obj/item/holder/chicken
+ can_hide = TRUE
+ gold_core_spawnable = FRIENDLY_SPAWN
+ step_type = FOOTSTEP_MOB_CLAW
+ ai_controller = /datum/ai_controller/basic_controller/chicken/chick
+ /// How grown up are we?
+ var/amount_grown = 0
+
+/mob/living/basic/chick/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/wears_collar)
+ scatter_atom()
+ /// Basic mobs need a language otherwise their speech is garbled
+ add_language("Galactic Common")
+ set_default_language(GLOB.all_languages["Galactic Common"])
+
+/mob/living/basic/chick/scatter_atom(x_offset, y_offset)
+ pixel_x = rand(-6, 6) + x_offset
+ pixel_y = rand(0, 10) + y_offset
+
+/mob/living/basic/chick/Life(seconds, times_fired)
+ . = ..()
+ if(.)
+ amount_grown += rand(1,2)
+ if(amount_grown >= 100)
+ var/mob/living/basic/chicken/C = new /mob/living/basic/chicken(loc)
+ if(name != initial(name))
+ C.name = name
+ if(mind)
+ mind.transfer_to(C)
+
+ for(var/atom/movable/AM in contents)
+ AM.forceMove(C)
+
+ qdel(src)
+
+/mob/living/basic/chick/valid_respawn_target_for(mob/user)
+ return TRUE
+
+/mob/living/basic/chick/attack_hand(mob/living/carbon/human/M)
+ if(M.a_intent == INTENT_HELP)
+ get_scooped(M, TRUE)
+ ..()
+
+#define MAX_CHICKENS 50
+GLOBAL_VAR_INIT(chicken_count, 0)
+
+/mob/living/basic/chicken
+ name = "chicken"
+ desc = "Hopefully the eggs are good this season."
+ gender = FEMALE
+ mob_biotypes = MOB_ORGANIC | MOB_BEAST
+ icon_state = "chicken_brown"
+ icon_living = "chicken_brown"
+ icon_dead = "chicken_brown_dead"
+ speak_emote = list("clucks", "croons")
+ density = FALSE
+ butcher_results = list(/obj/item/food/meat/chicken = 2)
+ response_help_continuous = "pets"
+ response_help_simple = "pet"
+ response_disarm_continuous = "gently pushes aside"
+ response_disarm_simple = "gently push aside"
+ response_harm_continuous = "kicks"
+ response_harm_simple = "kick"
+ attack_verb_continuous = "pecks"
+ attack_verb_simple = "peck"
+ friendly_verb_continuous = "headbutts"
+ friendly_verb_simple = "headbutt"
+ health = 15
+ maxHealth = 15
+ ventcrawler = VENTCRAWLER_ALWAYS
+
+ pass_flags = PASSTABLE | PASSMOB
+ mob_size = MOB_SIZE_SMALL
+ holder_type = /obj/item/holder/chicken
+ can_hide = TRUE
+
+ gold_core_spawnable = FRIENDLY_SPAWN
+ step_type = FOOTSTEP_MOB_CLAW
+ ai_controller = /datum/ai_controller/basic_controller/chicken
+
+ /// What type of egg do we lay?
+ var/egg_type = /obj/item/food/egg
+ /// How many eggs do we have left to lay?
+ var/eggsleft = 0
+ /// Are the eggs fertile?
+ var/eggsFertile = TRUE
+ /// What can the chicken eat?
+ var/static/list/edibles = list(
+ /obj/item/food/grown/wheat,
+ )
+ /// What color chicken are we?
+ var/body_color
+ /// Prefix for icon determining colors
+ var/icon_prefix = "chicken"
+ /// What colors can chickens be?
+ var/list/validColors = list("brown", "black", "white")
+ /// What message to play when laying an egg?
+ var/list/layMessage = EGG_LAYING_MESSAGES
+
+/mob/living/basic/chicken/Initialize(mapload)
+ . = ..()
+ if(!body_color)
+ body_color = pick(validColors)
+ icon_state = "[icon_prefix]_[body_color]"
+ icon_living = "[icon_prefix]_[body_color]"
+ icon_dead = "[icon_prefix]_[body_color]_dead"
+ AddElement(/datum/element/wears_collar)
+ AddElement(/datum/element/ai_retaliate)
+ AddElement(/datum/element/pet_bonus, "cluck")
+ // Have all eating components share the same exact list per mob subtype
+ var/static/list/static_food_types
+ if(!static_food_types)
+ static_food_types = edibles.Copy()
+ AddElement(/datum/element/basic_eating, food_types_ = static_food_types)
+ RegisterSignal(src, COMSIG_MOB_PRE_EAT, PROC_REF(on_eat))
+ ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(edibles))
+ scatter_atom()
+ update_appearance(UPDATE_ICON_STATE)
+ GLOB.chicken_count++
+ /// Basic mobs need a language otherwise their speech is garbled
+ add_language("Galactic Common")
+ set_default_language(GLOB.all_languages["Galactic Common"])
+
+/mob/living/basic/chicken/scatter_atom(x_offset, y_offset)
+ pixel_x = rand(-6, 6) + x_offset
+ pixel_y = rand(0, 10) + y_offset
+
+/mob/living/basic/chicken/death(gibbed)
+ // Only execute the below if we successfully died
+ . = ..(gibbed)
+ if(!.)
+ return
+ GLOB.chicken_count--
+
+/mob/living/basic/chicken/proc/on_eat(atom/target, mob/feeder)
+ SIGNAL_HANDLER // COMSIG_MOB_PRE_EAT
+ if(stat == CONSCIOUS && eggsleft < 8)
+ eggsleft += rand(1, 4)
+ else
+ to_chat(feeder, "[src] doesn't seem hungry!")
+ return COMSIG_MOB_CANCEL_EAT
+
+/mob/living/basic/chicken/attack_hand(mob/living/carbon/human/M)
+ if(M.a_intent == INTENT_HELP)
+ get_scooped(M, TRUE)
+ ..()
+
+/mob/living/basic/chicken/Life(seconds, times_fired)
+ . = ..()
+ if((. && prob(3) && eggsleft > 0) && egg_type)
+ visible_message("[src] [pick(layMessage)]")
+ eggsleft--
+ var/obj/item/E = new egg_type(get_turf(src))
+ E.scatter_atom()
+ if(eggsFertile)
+ if(GLOB.chicken_count < MAX_CHICKENS && prob(25))
+ START_PROCESSING(SSobj, E)
+
+/obj/item/food/egg/process()
+ if(isturf(loc))
+ amount_grown += rand(1,2)
+ if(amount_grown >= 100)
+ visible_message("[src] hatches with a quiet cracking sound.")
+ new /mob/living/basic/chick(get_turf(src))
+ STOP_PROCESSING(SSobj, src)
+ qdel(src)
+ else
+ STOP_PROCESSING(SSobj, src)
+
+/mob/living/basic/chicken/valid_respawn_target_for(mob/user)
+ return TRUE
+
+/mob/living/basic/chicken/clucky
+ name = "Commander Clucky"
+ real_name = "Commander Clucky"
+
+/mob/living/basic/chicken/clucky/valid_respawn_target_for(mob/user) // depriving the chef of his animals is not cool
+ return FALSE
+
+/mob/living/basic/chicken/kentucky
+ name = "Kentucky"
+ real_name = "Kentucky"
+
+/mob/living/basic/chicken/kentucky/valid_respawn_target_for(mob/user)
+ return FALSE
+
+/mob/living/basic/chicken/featherbottom
+ name = "Featherbottom"
+ real_name = "Featherbottom"
+
+/mob/living/basic/chicken/featherbottom/valid_respawn_target_for(mob/user)
+ return FALSE
+
+/datum/ai_controller/basic_controller/chicken
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ )
+
+ ai_traits = AI_FLAG_STOP_MOVING_WHEN_PULLED
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee,
+ /datum/ai_planning_subtree/flee_target,
+ /datum/ai_planning_subtree/find_food,
+ /datum/ai_planning_subtree/random_speech/chicken,
+ )
+
+/datum/ai_planning_subtree/random_speech/chicken
+ speech_chance = 15 // really talkative ladies
+ speak = list("Cluck!", "BWAAAAARK BWAK BWAK BWAK!", "Bwaak bwak.")
+ sound = list('sound/creatures/clucks.ogg', 'sound/creatures/bagawk.ogg')
+ emote_hear = list("clucks.", "croons.")
+ emote_see = list("pecks at the ground.", "flaps her wings viciously.")
+
+/datum/ai_controller/basic_controller/chicken/chick
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee,
+ /datum/ai_planning_subtree/flee_target,
+ /datum/ai_planning_subtree/random_speech/chick,
+ )
+
+/datum/ai_planning_subtree/random_speech/chick
+ speech_chance = 15
+ speak = list("Cherp.", "Cherp?", "Chirrup.", "Cheep!")
+ sound = list('sound/creatures/chick_peep.ogg')
+ emote_hear = list("cheeps.")
+ emote_see = list("pecks at the ground", "flaps its tiny wings")
+
+#undef MAX_CHICKENS
diff --git a/code/modules/mob/living/basic/farm_animals/goat.dm b/code/modules/mob/living/basic/farm_animals/goat.dm
new file mode 100644
index 00000000000..39664321e2a
--- /dev/null
+++ b/code/modules/mob/living/basic/farm_animals/goat.dm
@@ -0,0 +1,131 @@
+// goat
+/mob/living/basic/goat
+ name = "goat"
+ desc = "Not known for their pleasant disposition."
+ icon_state = "goat"
+ icon_living = "goat"
+ icon_dead = "goat_dead"
+ see_in_dark = 6
+ butcher_results = list(/obj/item/food/meat = 4)
+
+ speak_emote = list("brays")
+ response_help_continuous = "pets"
+ response_help_simple = "pet"
+ response_disarm_continuous = "gently pushes aside"
+ response_disarm_simple = "gently push aside"
+ response_harm_continuous = "kicks"
+ response_harm_simple = "kick"
+ attack_verb_continuous = "kicks"
+ attack_verb_simple = "kick"
+
+ faction = list("neutral", "jungle")
+ mob_biotypes = MOB_ORGANIC | MOB_BEAST
+ health = 40
+ maxHealth = 40
+ melee_damage_lower = 1
+ melee_damage_upper = 2
+ blood_volume = BLOOD_VOLUME_NORMAL
+ gender = FEMALE
+ step_type = FOOTSTEP_MOB_SHOE
+ ai_controller = /datum/ai_controller/basic_controller/goat
+ /// What can the goat eat?
+ var/static/list/edibles = list(
+ /obj/structure/glowshroom,
+ /obj/structure/spacevine,
+ )
+ /// The goat's udder
+ var/obj/item/udder/cow/udder
+
+/mob/living/basic/goat/Initialize(mapload)
+ . = ..()
+ udder = new()
+ AddElement(/datum/element/wears_collar)
+ AddElement(/datum/element/ai_retaliate)
+ ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(edibles))
+
+ RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_pre_attack))
+ RegisterSignal(src, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(on_move))
+
+/mob/living/basic/goat/Destroy()
+ QDEL_NULL(udder)
+ return ..()
+
+/mob/living/basic/goat/melee_attack(atom/target, list/modifiers, ignore_cooldown)
+ . = ..()
+ if(. && isdiona(target))
+ var/mob/living/carbon/human/H = target
+ var/obj/item/organ/external/NB = pick(H.bodyparts)
+ H.visible_message("[src] takes a big chomp out of [H]!", "[src] takes a big chomp out of your [NB.name]!")
+ NB.droplimb()
+
+/mob/living/basic/goat/proc/on_pre_attack(datum/source, atom/target)
+ SIGNAL_HANDLER // COMSIG_HOSTILE_PRE_ATTACKINGTARGET
+ if(is_type_in_list(target, edibles))
+ eat_plant(list(target))
+ return COMPONENT_HOSTILE_NO_ATTACK
+
+/mob/living/basic/goat/proc/on_move(datum/source, atom/entering_loc)
+ SIGNAL_HANDLER // COMSIG_MOVABLE_PRE_MOVE
+ if(!isturf(entering_loc) || stat == DEAD)
+ return
+
+ var/list/edible_plants = list()
+ for(var/obj/target in entering_loc)
+ if(is_type_in_list(target, edibles))
+ edible_plants += target
+
+ INVOKE_ASYNC(src, PROC_REF(eat_plant), edible_plants)
+
+/mob/living/basic/goat/Life(seconds, times_fired)
+ . = ..()
+ if(stat == CONSCIOUS)
+ udder.generateMilk()
+
+/mob/living/basic/goat/item_interaction(mob/living/user, obj/item/O, list/modifiers)
+ if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
+ udder.milkAnimal(O, user)
+ return ITEM_INTERACT_COMPLETE
+
+/mob/living/basic/goat/proc/eat_plant(list/plants)
+ var/eaten = FALSE
+
+ for(var/atom/target as anything in plants)
+ if(istype(target, /obj/structure/spacevine))
+ var/obj/structure/spacevine/vine = target
+ vine.eat(src)
+ eaten = TRUE
+
+ if(istype(target, /obj/structure/glowshroom))
+ qdel(target)
+ eaten = TRUE
+
+ if(eaten && prob(10))
+ say("Nom") // bon appetit
+ playsound(src, 'sound/items/eatfood.ogg', rand(30, 50), TRUE)
+
+/mob/living/basic/goat/chef
+ name = "Pete"
+ desc = "Pete, the Chef's pet goat from the Caribbean. Not known for their pleasant disposition."
+
+/// Goats are normally content to sorta hang around and crunch any plant in sight, but they will go ape on someone who attacks them.
+/datum/ai_controller/basic_controller/goat
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ )
+ ai_traits = AI_FLAG_STOP_MOVING_WHEN_PULLED
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/capricious_retaliate, // Capricious like Capra, get it?
+ /datum/ai_planning_subtree/target_retaliate,
+ /datum/ai_planning_subtree/find_food,
+ /datum/ai_planning_subtree/basic_melee_attack_subtree,
+ /datum/ai_planning_subtree/random_speech/goat,
+ )
+
+/datum/ai_planning_subtree/random_speech/goat
+ speech_chance = 3
+ emote_hear = list("brays.")
+ emote_see = list("shakes their head.", "stamps a foot.", "glares around.")
+ speak = list("EHEHEHEHEH", "eh?")
diff --git a/code/modules/mob/living/basic/farm_animals/goose.dm b/code/modules/mob/living/basic/farm_animals/goose.dm
new file mode 100644
index 00000000000..e51acaa4a31
--- /dev/null
+++ b/code/modules/mob/living/basic/farm_animals/goose.dm
@@ -0,0 +1,51 @@
+/mob/living/basic/goose
+ name = "goose"
+ desc = "A pretty goose. Would make a nice comforter."
+ icon_state = "goose"
+ icon_living = "goose"
+ icon_dead = "goose_dead"
+ speak_emote = list("quacks")
+ see_in_dark = 6
+ butcher_results = list(/obj/item/food/meat = 6)
+ response_help_continuous = "pets"
+ response_help_simple = "pet"
+ response_disarm_continuous = "gently pushes aside"
+ response_disarm_simple = "gently push aside"
+ response_harm_continuous = "kicks"
+ response_harm_simple = "kick"
+ attack_verb_continuous = "pecks"
+ attack_verb_simple = "peck"
+ health = 50
+ maxHealth = 50
+ mob_biotypes = MOB_ORGANIC | MOB_BEAST
+ gold_core_spawnable = FRIENDLY_SPAWN
+ step_type = FOOTSTEP_MOB_CLAW
+ ai_controller = /datum/ai_controller/basic_controller/goose
+
+/mob/living/basic/goose/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/wears_collar)
+ AddElement(/datum/element/ai_retaliate)
+ /// Basic mobs need a language otherwise their speech is garbled
+ add_language("Galactic Common")
+ set_default_language(GLOB.all_languages["Galactic Common"])
+
+/datum/ai_controller/basic_controller/goose
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ )
+
+ ai_traits = AI_FLAG_STOP_MOVING_WHEN_PULLED
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee,
+ /datum/ai_planning_subtree/flee_target,
+ /datum/ai_planning_subtree/random_speech/goose,
+ )
+
+/datum/ai_planning_subtree/random_speech/goose
+ speech_chance = 2
+ speak = list("quack?", "quack", "QUACK")
+ emote_see = list("flaps it's wings.")
diff --git a/code/modules/mob/living/basic/farm_animals/seal.dm b/code/modules/mob/living/basic/farm_animals/seal.dm
new file mode 100644
index 00000000000..29d6138fd30
--- /dev/null
+++ b/code/modules/mob/living/basic/farm_animals/seal.dm
@@ -0,0 +1,56 @@
+/mob/living/basic/seal
+ name = "seal"
+ desc = "A beautiful white seal."
+ icon_state = "seal"
+ icon_living = "seal"
+ icon_dead = "seal_dead"
+ speak_emote = list("urks")
+ see_in_dark = 6
+ butcher_results = list(/obj/item/food/meat = 6)
+ response_help_continuous = "pets"
+ response_help_simple = "pet"
+ response_disarm_continuous = "gently pushes aside"
+ response_disarm_simple = "gently push aside"
+ response_harm_continuous = "kicks"
+ response_harm_simple = "kick"
+ health = 50
+ maxHealth = 50
+ mob_biotypes = MOB_ORGANIC | MOB_BEAST
+ gold_core_spawnable = FRIENDLY_SPAWN
+ blood_volume = BLOOD_VOLUME_NORMAL
+ ai_controller = /datum/ai_controller/basic_controller/seal
+
+/mob/living/basic/seal/walrus
+ name = "walrus"
+ desc = "A big brown walrus."
+ icon_state = "walrus"
+ icon_living = "walrus"
+ icon_dead = "walrus_dead"
+
+/mob/living/basic/seal/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/wears_collar)
+ AddElement(/datum/element/ai_retaliate)
+ /// Basic mobs need a language otherwise their speech is garbled
+ add_language("Galactic Common")
+ set_default_language(GLOB.all_languages["Galactic Common"])
+
+/datum/ai_controller/basic_controller/seal
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ )
+
+ ai_traits = AI_FLAG_STOP_MOVING_WHEN_PULLED
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee,
+ /datum/ai_planning_subtree/flee_target,
+ /datum/ai_planning_subtree/random_speech/seal,
+ )
+
+/datum/ai_planning_subtree/random_speech/seal
+ speech_chance = 2
+ speak = list("Urk?", "urk.", "URK!")
+ emote_see = list("flops around.")
diff --git a/code/modules/mob/living/basic/farm_animals/turkey.dm b/code/modules/mob/living/basic/farm_animals/turkey.dm
new file mode 100644
index 00000000000..9286d3f4429
--- /dev/null
+++ b/code/modules/mob/living/basic/farm_animals/turkey.dm
@@ -0,0 +1,52 @@
+/mob/living/basic/turkey
+ name = "turkey"
+ desc = "Benjamin Franklin would be proud."
+ icon_state = "turkey"
+ icon_living = "turkey"
+ icon_dead = "turkey_dead"
+ icon_resting = "turkey_rest"
+ speak_emote = list("gobble")
+ see_in_dark = 6
+ butcher_results = list(/obj/item/food/meat = 4)
+ response_help_continuous = "pets"
+ response_help_simple = "pet"
+ response_disarm_continuous = "gently pushes aside"
+ response_disarm_simple = "gently push aside"
+ response_harm_continuous = "kicks"
+ response_harm_simple = "kick"
+ attack_verb_continuous = "pecks"
+ attack_verb_simple = "peck"
+ health = 50
+ maxHealth = 50
+ mob_biotypes = MOB_ORGANIC | MOB_BEAST
+ gold_core_spawnable = FRIENDLY_SPAWN
+ step_type = FOOTSTEP_MOB_CLAW
+ ai_controller = /datum/ai_controller/basic_controller/turkey
+
+/mob/living/basic/turkey/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/wears_collar)
+ AddElement(/datum/element/ai_retaliate)
+ /// Basic mobs need a language otherwise their speech is garbled
+ add_language("Galactic Common")
+ set_default_language(GLOB.all_languages["Galactic Common"])
+
+/datum/ai_controller/basic_controller/turkey
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ )
+
+ ai_traits = AI_FLAG_STOP_MOVING_WHEN_PULLED
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee,
+ /datum/ai_planning_subtree/flee_target,
+ /datum/ai_planning_subtree/random_speech/turkey,
+ )
+
+/datum/ai_planning_subtree/random_speech/turkey
+ speech_chance = 2
+ speak = list("gobble?", "gobble", "GOBBLE")
+ emote_see = list("struts around.")
diff --git a/code/modules/mob/living/basic/farm_animals/udders.dm b/code/modules/mob/living/basic/farm_animals/udders.dm
new file mode 100644
index 00000000000..83e472b2597
--- /dev/null
+++ b/code/modules/mob/living/basic/farm_animals/udders.dm
@@ -0,0 +1,27 @@
+/obj/item/udder
+ name = "udder"
+
+/obj/item/udder/Initialize(mapload)
+ . = ..()
+ create_reagents(50)
+
+/obj/item/udder/proc/generateMilk()
+ if(prob(5))
+ reagents.add_reagent("milk", rand(5, 10))
+
+/obj/item/udder/proc/milkAnimal(obj/O, mob/user)
+ var/obj/item/reagent_containers/glass/G = O
+ if(G.reagents.total_volume >= G.volume)
+ to_chat(user, "[O] is full.")
+ return
+ var/transfered = reagents.trans_to(O, rand(5,10))
+ if(transfered)
+ user.visible_message("[user] milks [src] using \the [O].", "You milk [src] using \the [O].")
+ else
+ to_chat(user, "The udder is dry. Wait a bit longer...")
+
+/obj/item/udder/cow
+
+/obj/item/udder/cow/Initialize(mapload)
+ . = ..()
+ reagents.add_reagent("milk", 20)
diff --git a/code/modules/mob/living/carbon/human/species/tajaran.dm b/code/modules/mob/living/carbon/human/species/tajaran.dm
index 003d4f2131e..7d7f4b980ac 100644
--- a/code/modules/mob/living/carbon/human/species/tajaran.dm
+++ b/code/modules/mob/living/carbon/human/species/tajaran.dm
@@ -44,7 +44,7 @@
unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/
)
- allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/basic/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/hostile/poison/bees)
+ allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/basic/chick, /mob/living/basic/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/hostile/poison/bees)
suicide_messages = list(
"is attempting to bite their tongue off!",
diff --git a/code/modules/mob/living/carbon/human/species/unathi.dm b/code/modules/mob/living/carbon/human/species/unathi.dm
index 04e20ea2042..f96a9b805bc 100644
--- a/code/modules/mob/living/carbon/human/species/unathi.dm
+++ b/code/modules/mob/living/carbon/human/species/unathi.dm
@@ -48,7 +48,7 @@
"eyes" = /obj/item/organ/internal/eyes/unathi //3 darksight.
)
- allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/basic/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken,
+ allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/basic/lizard, /mob/living/basic/chick, /mob/living/basic/chicken,
/mob/living/simple_animal/crab, /mob/living/basic/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/hostile/poison/bees)
suicide_messages = list(
diff --git a/code/modules/mob/living/carbon/human/species/vulpkanin.dm b/code/modules/mob/living/carbon/human/species/vulpkanin.dm
index 5238db6d9e7..55286796834 100644
--- a/code/modules/mob/living/carbon/human/species/vulpkanin.dm
+++ b/code/modules/mob/living/carbon/human/species/vulpkanin.dm
@@ -38,7 +38,7 @@
unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/
)
- allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/basic/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken,
+ allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/basic/lizard, /mob/living/basic/chick, /mob/living/basic/chicken,
/mob/living/simple_animal/crab, /mob/living/basic/butterfly, /mob/living/simple_animal/parrot, /mob/living/simple_animal/hostile/poison/bees)
suicide_messages = list(
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
deleted file mode 100644
index dfc483deced..00000000000
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ /dev/null
@@ -1,448 +0,0 @@
-//goat
-/mob/living/simple_animal/hostile/retaliate/goat
- name = "goat"
- desc = "Not known for their pleasant disposition."
- icon_state = "goat"
- icon_living = "goat"
- icon_dead = "goat_dead"
- speak = list("EHEHEHEHEH","eh?")
- speak_emote = list("brays")
- emote_hear = list("brays")
- emote_see = list("shakes its head", "stamps a foot", "glares around")
- speak_chance = 1
- turns_per_move = 5
- see_in_dark = 6
- butcher_results = list(/obj/item/food/meat = 4)
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- faction = list("neutral", "jungle")
- mob_biotypes = MOB_ORGANIC | MOB_BEAST
- attack_same = TRUE
- attacktext = "kicks"
- attack_sound = 'sound/weapons/punch1.ogg'
- health = 40
- maxHealth = 40
- melee_damage_lower = 1
- melee_damage_upper = 2
- stop_automated_movement_when_pulled = TRUE
- blood_volume = BLOOD_VOLUME_NORMAL
- var/obj/item/udder/cow/udder = null
- gender = FEMALE
- footstep_type = FOOTSTEP_MOB_SHOE
-
-/mob/living/simple_animal/hostile/retaliate/goat/Initialize(mapload)
- . = ..()
- udder = new()
- AddElement(/datum/element/wears_collar)
-
-/mob/living/simple_animal/hostile/retaliate/goat/Destroy()
- QDEL_NULL(udder)
- return ..()
-
-/mob/living/simple_animal/hostile/retaliate/goat/handle_automated_movement()
- . = ..()
- //chance to go crazy and start wacking stuff
- if(!length(enemies) && prob(1))
- Retaliate()
-
- if(length(enemies) && prob(10))
- enemies = list()
- LoseTarget()
- visible_message("[src] calms down.")
-
- eat_plants()
- if(!pulledby)
- for(var/direction in shuffle(GLOB.alldirs))
- var/step = get_step(src, direction)
- if(step)
- if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step)
- Move(step, get_dir(src, step))
-
-/mob/living/simple_animal/hostile/retaliate/goat/Life(seconds, times_fired)
- . = ..()
- if(stat == CONSCIOUS)
- udder.generateMilk()
-
-/mob/living/simple_animal/hostile/retaliate/goat/Retaliate()
- ..()
- visible_message("[src] gets an evil-looking gleam in their eye.")
-
-/mob/living/simple_animal/hostile/retaliate/goat/Move()
- . = ..()
- if(stat == CONSCIOUS)
- eat_plants()
-
-/mob/living/simple_animal/hostile/retaliate/goat/item_interaction(mob/living/user, obj/item/O, list/modifiers)
- if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
- udder.milkAnimal(O, user)
- return ITEM_INTERACT_COMPLETE
-
-/mob/living/simple_animal/hostile/retaliate/goat/proc/eat_plants()
- var/eaten = FALSE
- var/obj/structure/spacevine/SV = locate(/obj/structure/spacevine) in loc
- if(SV)
- SV.eat(src)
- eaten = TRUE
-
- var/obj/structure/glowshroom/GS = locate(/obj/structure/glowshroom) in loc
- if(GS)
- qdel(GS)
- eaten = TRUE
-
- if(eaten && prob(10))
- say("Nom")
-
-/mob/living/simple_animal/hostile/retaliate/goat/AttackingTarget()
- . = ..()
- if(. && isdiona(target))
- var/mob/living/carbon/human/H = target
- var/obj/item/organ/external/NB = pick(H.bodyparts)
- H.visible_message("[src] takes a big chomp out of [H]!", "[src] takes a big chomp out of your [NB.name]!")
- NB.droplimb()
-
-/mob/living/simple_animal/hostile/retaliate/goat/chef
- name = "Pete"
- desc = "Pete, the Chef's pet goat from the Caribbean. Not known for their pleasant disposition."
- unique_pet = TRUE
-
-/mob/living/simple_animal/chick
- name = "chick"
- desc = "Adorable! They make such a racket though."
- icon_state = "chick"
- icon_living = "chick"
- icon_dead = "chick_dead"
- icon_gib = "chick_gib"
- gender = FEMALE
- mob_biotypes = MOB_ORGANIC | MOB_BEAST
- speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
- speak_emote = list("cheeps")
- emote_hear = list("cheeps")
- emote_see = list("pecks at the ground","flaps its tiny wings")
- density = FALSE
- speak_chance = 2
- turns_per_move = 2
- butcher_results = list(/obj/item/food/meat/chicken = 1)
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- attacktext = "kicks"
- health = 3
- maxHealth = 3
- ventcrawler = VENTCRAWLER_ALWAYS
- var/amount_grown = 0
- pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
- mob_size = MOB_SIZE_TINY
- holder_type = /obj/item/holder/chicken
- can_hide = TRUE
- gold_core_spawnable = FRIENDLY_SPAWN
- footstep_type = FOOTSTEP_MOB_CLAW
-
-/mob/living/simple_animal/chick/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/wears_collar)
- scatter_atom()
-
-/mob/living/simple_animal/chick/scatter_atom(x_offset, y_offset)
- pixel_x = rand(-6, 6) + x_offset
- pixel_y = rand(0, 10) + y_offset
-
-/mob/living/simple_animal/chick/Life(seconds, times_fired)
- . =..()
- if(.)
- amount_grown += rand(1,2)
- if(amount_grown >= 100)
- var/mob/living/simple_animal/chicken/C = new /mob/living/simple_animal/chicken(loc)
- if(name != initial(name))
- C.name = name
- if(mind)
- mind.transfer_to(C)
-
- for(var/atom/movable/AM in contents)
- AM.forceMove(C)
-
- qdel(src)
-
-
-/mob/living/simple_animal/chick/npc_safe(mob/user)
- return TRUE
-
-/mob/living/simple_animal/chick/attack_hand(mob/living/carbon/human/M)
- if(M.a_intent == INTENT_HELP)
- get_scooped(M, TRUE)
- ..()
-
-#define MAX_CHICKENS 50
-GLOBAL_VAR_INIT(chicken_count, 0)
-
-/mob/living/simple_animal/chicken
- name = "chicken"
- desc = "Hopefully the eggs are good this season."
- gender = FEMALE
- mob_biotypes = MOB_ORGANIC | MOB_BEAST
- icon_state = "chicken_brown"
- icon_living = "chicken_brown"
- icon_dead = "chicken_brown_dead"
- speak = list("Cluck!","BWAAAAARK BWAK BWAK BWAK!","Bwaak bwak.")
- speak_emote = list("clucks","croons")
- emote_hear = list("clucks")
- emote_see = list("pecks at the ground","flaps its wings viciously")
- density = FALSE
- speak_chance = 2
- turns_per_move = 3
- butcher_results = list(/obj/item/food/meat/chicken = 2)
- var/egg_type = /obj/item/food/egg
- var/food_type = /obj/item/food/grown/wheat
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- attacktext = "kicks"
- health = 15
- maxHealth = 15
- ventcrawler = VENTCRAWLER_ALWAYS
- var/eggsleft = 0
- var/eggsFertile = TRUE
- var/body_color
- var/icon_prefix = "chicken"
- pass_flags = PASSTABLE | PASSMOB
- mob_size = MOB_SIZE_SMALL
- holder_type = /obj/item/holder/chicken
- can_hide = TRUE
- var/list/feedMessages = list("It clucks happily.","It clucks happily.")
- var/list/layMessage = EGG_LAYING_MESSAGES
- var/list/validColors = list("brown","black","white")
- gold_core_spawnable = FRIENDLY_SPAWN
- footstep_type = FOOTSTEP_MOB_CLAW
-
-/mob/living/simple_animal/chicken/Initialize(mapload)
- . = ..()
- if(!body_color)
- body_color = pick(validColors)
- icon_state = "[icon_prefix]_[body_color]"
- icon_living = "[icon_prefix]_[body_color]"
- icon_dead = "[icon_prefix]_[body_color]_dead"
- AddElement(/datum/element/wears_collar)
- scatter_atom()
- update_appearance(UPDATE_ICON_STATE)
- GLOB.chicken_count += 1
-
-/mob/living/simple_animal/chicken/scatter_atom(x_offset, y_offset)
- pixel_x = rand(-6, 6) + x_offset
- pixel_y = rand(0, 10) + y_offset
-
-/mob/living/simple_animal/chicken/death(gibbed)
- // Only execute the below if we successfully died
- . = ..(gibbed)
- if(!.)
- return
- GLOB.chicken_count -= 1
-
-/mob/living/simple_animal/chicken/item_interaction(mob/living/user, obj/item/O, list/modifiers)
- if(istype(O, food_type)) //feedin' dem chickens
- if(stat == CONSCIOUS && eggsleft < 8)
- var/feedmsg = "[user] feeds [O] to [name]! [pick(feedMessages)]"
- user.visible_message(feedmsg)
- user.drop_item()
- qdel(O)
- eggsleft += rand(1, 4)
- //world << eggsleft
- else
- to_chat(user, "[name] doesn't seem hungry!")
-
- return ITEM_INTERACT_COMPLETE
-
-/mob/living/simple_animal/chicken/attack_hand(mob/living/carbon/human/M)
- if(M.a_intent == INTENT_HELP)
- get_scooped(M, TRUE)
- ..()
-
-/mob/living/simple_animal/chicken/Life(seconds, times_fired)
- . = ..()
- if((. && prob(3) && eggsleft > 0) && egg_type)
- visible_message("[src] [pick(layMessage)]")
- eggsleft--
- var/obj/item/E = new egg_type(get_turf(src))
- E.scatter_atom()
- if(eggsFertile)
- if(GLOB.chicken_count < MAX_CHICKENS && prob(25))
- START_PROCESSING(SSobj, E)
-
-/obj/item/food/egg/process()
- if(isturf(loc))
- amount_grown += rand(1,2)
- if(amount_grown >= 100)
- visible_message("[src] hatches with a quiet cracking sound.")
- new /mob/living/simple_animal/chick(get_turf(src))
- STOP_PROCESSING(SSobj, src)
- qdel(src)
- else
- STOP_PROCESSING(SSobj, src)
-
-/mob/living/simple_animal/chicken/npc_safe(mob/user)
- return TRUE
-
-/mob/living/simple_animal/chicken/clucky
- name = "Commander Clucky"
- real_name = "Commander Clucky"
- unique_pet = TRUE
-
-/mob/living/simple_animal/chicken/clucky/npc_safe(mob/user) // depriving the chef of his animals is not cool
- return FALSE
-
-/mob/living/simple_animal/chicken/kentucky
- name = "Kentucky"
- real_name = "Kentucky"
- unique_pet = TRUE
-
-/mob/living/simple_animal/chicken/kentucky/npc_safe(mob/user)
- return FALSE
-
-/mob/living/simple_animal/chicken/featherbottom
- name = "Featherbottom"
- real_name = "Featherbottom"
- unique_pet = TRUE
-
-/mob/living/simple_animal/chicken/featherbottom/npc_safe(mob/user)
- return FALSE
-
-/mob/living/simple_animal/turkey
- name = "turkey"
- desc = "Benjamin Franklin would be proud."
- icon_state = "turkey"
- icon_living = "turkey"
- icon_dead = "turkey_dead"
- icon_resting = "turkey_rest"
- speak = list("gobble?","gobble","GOBBLE")
- speak_emote = list("gobble")
- emote_see = list("struts around")
- speak_chance = 1
- turns_per_move = 5
- see_in_dark = 6
- butcher_results = list(/obj/item/food/meat = 4)
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- attacktext = "pecks"
- health = 50
- maxHealth = 50
- mob_biotypes = MOB_ORGANIC | MOB_BEAST
- gold_core_spawnable = FRIENDLY_SPAWN
- footstep_type = FOOTSTEP_MOB_CLAW
-
-/mob/living/simple_animal/turkey/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/wears_collar)
-
-/mob/living/simple_animal/goose
- name = "goose"
- desc = "A pretty goose. Would make a nice comforter."
- icon_state = "goose"
- icon_living = "goose"
- icon_dead = "goose_dead"
- speak = list("quack?","quack","QUACK")
- speak_emote = list("quacks")
-// emote_hear = list("brays")
- emote_see = list("flaps it's wings")
- speak_chance = 1
- turns_per_move = 5
- see_in_dark = 6
- butcher_results = list(/obj/item/food/meat = 6)
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- attacktext = "kicks"
- health = 50
- maxHealth = 50
- mob_biotypes = MOB_ORGANIC | MOB_BEAST
- gold_core_spawnable = FRIENDLY_SPAWN
- footstep_type = FOOTSTEP_MOB_CLAW
-
-/mob/living/simple_animal/goose/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/wears_collar)
-
-/mob/living/simple_animal/seal
- name = "seal"
- desc = "A beautiful white seal."
- icon_state = "seal"
- icon_living = "seal"
- icon_dead = "seal_dead"
- speak = list("Urk?","urk","URK")
- speak_emote = list("urks")
-// emote_hear = list("brays")
- emote_see = list("flops around")
- speak_chance = 1
- turns_per_move = 5
- see_in_dark = 6
- butcher_results = list(/obj/item/food/meat = 6)
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- attacktext = "kicks"
- health = 50
- maxHealth = 50
- mob_biotypes = MOB_ORGANIC | MOB_BEAST
- gold_core_spawnable = FRIENDLY_SPAWN
- blood_volume = BLOOD_VOLUME_NORMAL
-
-/mob/living/simple_animal/seal/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/wears_collar)
-
-/mob/living/simple_animal/walrus
- name = "walrus"
- desc = "A big brown walrus."
- icon_state = "walrus"
- icon_living = "walrus"
- icon_dead = "walrus_dead"
- speak = list("Urk?","urk","URK")
- speak_emote = list("urks")
-// emote_hear = list("brays")
- emote_see = list("flops around")
- speak_chance = 1
- turns_per_move = 5
- see_in_dark = 6
- butcher_results = list(/obj/item/food/meat = 6)
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "kicks"
- attacktext = "kicks"
- health = 50
- maxHealth = 50
- mob_biotypes = MOB_ORGANIC | MOB_BEAST
- gold_core_spawnable = FRIENDLY_SPAWN
- blood_volume = BLOOD_VOLUME_NORMAL
-
-/mob/living/simple_animal/walrus/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/wears_collar)
-
-/obj/item/udder
- name = "udder"
-
-/obj/item/udder/Initialize(mapload)
- . = ..()
- create_reagents(50)
-
-/obj/item/udder/proc/generateMilk()
- if(prob(5))
- reagents.add_reagent("milk", rand(5, 10))
-
-/obj/item/udder/proc/milkAnimal(obj/O, mob/user)
- var/obj/item/reagent_containers/glass/G = O
- if(G.reagents.total_volume >= G.volume)
- to_chat(user, "[O] is full.")
- return
- var/transfered = reagents.trans_to(O, rand(5,10))
- if(transfered)
- user.visible_message("[user] milks [src] using \the [O].", "You milk [src] using \the [O].")
- else
- to_chat(user, "The udder is dry. Wait a bit longer...")
-
-/obj/item/udder/cow
-
-/obj/item/udder/cow/Initialize(mapload)
- . = ..()
- reagents.add_reagent("milk", 20)
-
-#undef MAX_CHICKENS
diff --git a/code/modules/projectiles/projectile/magic_projectiles.dm b/code/modules/projectiles/projectile/magic_projectiles.dm
index d79d92f1f48..c1c97b46cc4 100644
--- a/code/modules/projectiles/projectile/magic_projectiles.dm
+++ b/code/modules/projectiles/projectile/magic_projectiles.dm
@@ -197,7 +197,7 @@ GLOBAL_LIST_INIT(wabbajack_hostile_animals, list(
"mushroom" = /mob/living/simple_animal/hostile/mushroom,
"statue" = /mob/living/simple_animal/hostile/statue,
"bat" = /mob/living/basic/scarybat,
- "goat" = /mob/living/simple_animal/hostile/retaliate/goat,
+ "goat" = /mob/living/basic/goat,
"kangaroo" = /mob/living/basic/kangaroo,
"tomato" = /mob/living/basic/killertomato,
"gorilla" = /mob/living/basic/gorilla,
@@ -209,14 +209,14 @@ GLOBAL_LIST_INIT(wabbajack_docile_animals, list(
"crab" = /mob/living/simple_animal/crab,
"cat" = /mob/living/simple_animal/pet/cat,
"mouse" = /mob/living/simple_animal/mouse,
- "chicken" = /mob/living/simple_animal/chicken,
+ "chicken" = /mob/living/basic/chicken,
"cow" = /mob/living/basic/cow,
"lizard" = /mob/living/basic/lizard,
"fox" = /mob/living/simple_animal/pet/dog/fox,
- "chick" = /mob/living/simple_animal/chick,
+ "chick" = /mob/living/basic/chick,
"pug" = /mob/living/simple_animal/pet/dog/pug,
- "turkey" = /mob/living/simple_animal/turkey,
- "seal" = /mob/living/simple_animal/seal,
+ "turkey" = /mob/living/basic/turkey,
+ "seal" = /mob/living/basic/seal,
"bunny" = /mob/living/basic/bunny,
"penguin" = /mob/living/basic/pet/penguin/emperor,
))
diff --git a/paradise.dme b/paradise.dme
index 013d2aa35dc..9e95ef103e7 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -2446,6 +2446,12 @@
#include "code\modules\mob\living\basic\basic_emotes.dm"
#include "code\modules\mob\living\basic\basic_mob.dm"
#include "code\modules\mob\living\basic\posessed_object.dm"
+#include "code\modules\mob\living\basic\farm_animals\chicken.dm"
+#include "code\modules\mob\living\basic\farm_animals\goat.dm"
+#include "code\modules\mob\living\basic\farm_animals\goose.dm"
+#include "code\modules\mob\living\basic\farm_animals\seal.dm"
+#include "code\modules\mob\living\basic\farm_animals\turkey.dm"
+#include "code\modules\mob\living\basic\farm_animals\udders.dm"
#include "code\modules\mob\living\basic\farm_animals\cow.dm"
#include "code\modules\mob\living\basic\farm_animals\deer.dm"
#include "code\modules\mob\living\basic\farm_animals\deer_ai.dm"
@@ -2687,7 +2693,6 @@
#include "code\modules\mob\living\simple_animal\friendly\crab.dm"
#include "code\modules\mob\living\simple_animal\friendly\diona_nymph.dm"
#include "code\modules\mob\living\simple_animal\friendly\dog.dm"
-#include "code\modules\mob\living\simple_animal\friendly\farm_animals.dm"
#include "code\modules\mob\living\simple_animal\friendly\fox.dm"
#include "code\modules\mob\living\simple_animal\friendly\friendly_emote.dm"
#include "code\modules\mob\living\simple_animal\friendly\mouse.dm"
diff --git a/sound/creatures/bagawk.ogg b/sound/creatures/bagawk.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..c275c4cbbc9c966059e3bed5db252592255a1265
GIT binary patch
literal 7285
zcmaJ_c|4Tg_rK4~*!ML_)6m#=jY6YFMhIDoh$Q<&kt{>f*w?Hddrg)sm3=86OD2jW
zA-W$1yqkf?s-Bsp5`2*wy<)KpZ}RMb=sU}Q`$T_$<^xLkF)>??a1W9sco`lpeRe&
zk-mFJI%lM#83i_DXAry$mH(f3MQhj@0(mjKV5dv~K;@qzJZKdI1Af4-z_HUwuLe+@
zAfR9%3|Ac>2Zr(gr9am30?HE|3y>@($OftuVD5j6?ykXh*C_n=aZIts@^c6)@W&Dn
z)(XP0PaUhRX<J(Hw^h7TmFN5#$B5nXPZ>4W@4d1hO?%8sM{H;jqVM*N3=!)#2{dQBu?2R78_D$@|Uotf_hYg?=kLZ6Tw&_
zPJ&mmcbO2pfU<5m00B4$}V6==k8o(OW;LHc`
zMuYeQ{W^TFfL_v!bxu(=K4XqV%yEk?kme6Wz&MM+Ng)D`cNDmS0Nh>uIKzQteDCri
zJ>wDJ=L!G7U*_vFXcO0_4R-9H1e4mKSLQ^d*4ip)dn9
zY~EAdWe11{O{TH{Dob9VC?EqooB)LdxWjxJk_W&H24V~%Akk!)MTa8}{{Dwx)0i2i
z8OtCeqsmypBnseDu|YY-e3Ctru@X3*9M@QCF{xlKkUAF_gEto>WkeMRO7t%C#u8Hu
zeh}U9_!JogA!1fXP)`D6xbmsPc=iks`FMCzW=O>TffzE8k8csjWjeS>Bqr&jcy+M+
z;&C8}wLm5gP-bl0sk8mW6q%q!BA>~Aer>8x+sYxeL*NDh8N;}f-KO-BKRn9@bLj6pe++A(g@y(Sc-w54iS578570~50V$6
z!Um$~YygPBF~F*l&nYNc!@m;;8i_7}1thHuXE^tPor)Le7SKKwQ5;B>35qEwiNypJ
zyXUB6XQ`M_U{Dc^VAz9`6lRgZIZFawCg5;I%<#2>sV`PP4fg!ru4)C7_Ed!)em(O#
zoRNUGsdH>jabO>@MnoI`0$Ye6Qw;h2N6@}-RKOIgE;yacXv7FV#}FheQ`hB6UL%9#x;
zp0&ww38K0M6}Z`C%w`w62T^AOsj@-Eu={3W3!V#@^e*E~v2j#V5Y;`W*qz_R^arun
zHK#x(s8}|q0R9Bq_h*=T2c<>Wiw@3ZkCd$(r2k9BjZ5@LAOfC;Fm{JZG<3Gsh&4Ct$DgJ|1NqTcYGjO##f
zaM`ed2qX-CY;ix1OH{uWa2cdVF^LLuxr06j5@WvL;J#dha3)+I0DW)*eeM95APMm5
z8;%6Tu$u?Uu(yR0nRhW%v$6pd>x}7GG(L&Ns1^sK)VmD2(r~>~fp|2YhX$k8TeyU$
z%m$LtJUrCs=;)cy*(E$rQZx&N1s>BPj3FILitY?&StRewellY|lL0*tBy}RuU=jXx
z0dB@@O~^}2kc+SCkKo`Toi}Ulv>o^`$H#=?20^&J1e}m-w>J`!
z<1%fYU^}FtQ&Kvp1M7j8R`^#02sIFqNIcNlKd}VyOQ;>QaP$e|-(lmyA_S7}0zSU}
zmsfnr!IX%Ygyg@nZsnnN*o+K<;J+3;2N@akXUl^!y1}TyaKKw07#ZMn#bH4f9iNX8
z7vH~sznmN`@9(r@{p7W4qS4|%J_pPe-(*9bBU4SGu7+AkIfGFm-a{>
z9zW1&&a&G>8ruEy+ow{D>wCiiXe@7fWq1X>CId^=ypLIe|Q
zhD+IrIcq){8M%8Tr9MR8>_VJ<#)<+&_8N4RIy4&2H~q-PIzhl$>-JW0Px0t_mFMLg
z!OmUDGAe6x(ml~CFA(#_-&?eAKiqv^`IN^UHBswJe1*cfPp0dqG^+UMel{jtyE3~>
z4y>33Q?uhf)!rF^!_6xku04K(Gxf^kw3P^^ik^#FQ<+M)U*Z
zD|Q?H8%T}~!F)8|52K6G23A9s2a)F7-SZ_+s+p87wM=dl`th@l399;j(75h7A0IO^
zx;5T>_q5$WZM?18&lcm>SFZ0w5GbL0{wMlkN7uGu%s0<*R*Kb(X*9l6?pQnb*-SY+
zpBG?-G+mS%+6R4-nEqOl@)WJHaIKeNa#ntxQTjnE)h@c?5+ugwA{5q8v*~Th@BU=I
zJMEzr>y7P~w}soDCJ@#x?teRp1~{R6!oA6ElWY6lV_ZLf*8gT?bYlF#YCuQ)QG?45
zpJ+sxn%3=J08^~13o}TOlB(0Qz3*(hti0y*Jhq=rZ-4XWX!qasOkwW&EU65&v3I3s
zwQBFPa72azr8qc@Qn}0Z>F01-$xK<1F&yyhQ!ULyvq2x
z`I!5|W8$@hx5HmAq7dPR)5H9n${(LetbH4bN?U&SaLDrvoO3~q!d@Ke*sC6IgV5i!OJ@74^%EUz
z6DMsGTsobtk3Ma;&zLQ$MLejw5V$eDT7m%V;P_#j2^){nn`O^j^(|tSI5jXJV6@uy
z^6gxv-K<9hj`1A-`a;@H_IH72^fA{}oE->ZWm<|X-INTwe@9;1Is6e4ph^YEoyxYvrwpo|^+0eyQBdkrON}Q5TH{|f$jYqfYLY_>?_T5ow
zBNN_QXM=F3D(X|eZRpF<9wzWp=vy{mg{APP$*(JFX!UH_MDPWgD*r-@a$$_I=#2x;G<-oQb<~X7^0k
z`!8}1!@lvdK;xN$|LowmxkyP9Ip0KS-F}^J31f_-+gXb!8IRIun^P?xiRk0a52hM3&-k#7iK$ThHdL)|?GuB5SzA`i=*f)^7mURP
z4`N_loUeqk&)PYkWR|O(Z21GWM-L|1Yop9tKE1mWQvhup63W*s1?*^+l*zQ%za$o;_a659_7Zche7fS}haRhvmqAW()7V#n54Bgd#cezu
z$larnjivPZT53t?i^p};6cxAxZyUFc%lERes1pke>QV2K!+kyn8+<2z3yl06@mcb)
zKJ|uOUw>iq3D$@2kB`4di7TAft&c+iZaPF~G84uDbXIzH^vqt}y4Z>uw*pZFpz-Zx
zUO-|@fcJb-ZRMevrsF5O)84fn8B?7(%t2W$6mINPb{gEBx-XZ&jQMeQNXu)3Q}LCs
zmf69Ovk%wg1beb2erG~@UdKz%v)+Gnhfk9OI#w?wFaEKPR-)X{x4gAoUS{VqEb-m%
z{EZ9KD+)I2*Xoum{Qf#83omNpbCPB0TimM@%@^ikz3*lW!y!7-83F|3NrV#A0eMk4
z1i|%M0G`iOtrm+6{0J$r^)oFx`^kt8@If)%rGu#b%V&5gNP*Yf*Q%sgq7_)(*OU_O
zj!eWnpA0otQ5|WlNN11qs*{R6%u2t!jU$~5OBCfiK}(S?m)|t+DDfTgpk1nLx^!7m
z;S7f3^C`gtgu@Fc5He?Z*KnJUeRR5kuVc-{kX2L|(2-dXprfB~01YeXR5N0i9T>BR
zz~I59&3t^g;P&g2ANngL;nT!m&Z7in%CSrkif|nbXgS^ifGRuX;iJupPz9Q=2P+US
zz0i~k*@bcgqSQ?jNy;_mo-$Cn^d{%nS$V;i
z1H=GZh^7cmGVV$UAxA%90T731stIrvU=)*z*+l?E`MUPm=pYm8i+&Ah@n65`UL8ys
zbB&WR{66Z}=4CGeEdtl;)~VGa1+YEpm(j>8XU%h)BJq~XMSB6*p!C8!3vUFxFHS&S
zzlXA01Y-#L%ETA`bI<0v&+mI0GQWE*7d|r&>Y{)?`0^b-Wq{`y6+5TsHhuYQcDUYm
z_&I`x1=cajL!*{u3)8#=e%iB67l~i1ZlIY1vb9f9ue>D-AI7P}erFH0whLUTpWY)q
z@=Hiw*eMytgbtt9=uCj~B8>!SXAnxfz!kK0E_ejf5Bx=qvOQ6|$@wr6)-(Us0?xlO
zR8l5$89O44#9YR_Kk=*G?v+R=}E)Kg@TupY!k(Vrac=->kwYEPii!2hvYYuKJ{~gFJ7)$5DcS
z>PvfJxRgC>HCvtaxpAYnLIymZTk%h_jClZ@3J+<$&EJTEV5y4`eBDLQQsQI*$gffq
zmZSvbE*ogr8?z#(!;+53|nH!mR|}x$J@!(NC+-ro->PCcAv<`Las52)2F>tT%Ck
zhC5$F77!TbuN0@!ta2>N7}Hh}x%$j{v)TXz&?75PG@eWh+)cJTXKVj?^`@~pyaC;}
z2uGSd!V?K+Syw!_{r^O8ku4Kgro_R&2-nk=Xybe&w=gWD@2Yd)HEs9OTQ
z3;R^xV5K(h1N5Q(uzStLt;Y2dS&6D(X8J^1d2q<5rc!kM7xj0u_c$I*6zV2#5qG~XA452=J-~%uc~;$d
zO+H@$P~BbnPaaP_$Co0pcT7{<{pF3PA|TO&at{=9yVu9iYATQV8Lex!rrc`v_o(;!
zYSHrHaJ7+;UPY<&4Js+@FR}<{a`>?4`0FgUi!YfB`iDPn7m$X8cm;(kc@d(as1ur(
zzBjp9ViF%XX`!uX^DkT9e^$s_BP^uyoi|cUsd1mAa|`)e!Z&30%`$$ipOq_07f6<9_CCLCQ{s898x3{Nc%0hpqd)9M#HV^Z%
zGZS84FUV9I(^5KIaJgQN)Wp_%XLCygUeUl2@^pXnVAkqAIic-z{GOl!CP4qiVn@gf
zEs&>3=mPZ5L!N@`ugYs)3$_ML?N8!|C=(`%L3$%2wGy9lXMeFF;DyU^T-7dn_xVBy
zY>gznFQ2@tZb?aBdB0#_2g1JGNKJ2jUZ|XFq&i&mqQr~8;nAJz$DS$&|LjP~P<5;D
z8U5NnkhjqgC=YEJ6xDGYSg)`v;;$@Rc@W0*5(3SYY(R|8?SN;-UtUNq5G-v!_ci`-YkL23Zpf^5D~I-|N5BgS
z>_sB8<42E=dG#mWI^!o^-uf+1XHpc
zSq)uW0IfJfB;3;A!!rtNcXop$rcu6mGO2ula0daTTn3HQ^ehiqvaX4>bx}ukgQL)F
zCzfiJDo_CmeL=l5QunP)3o@8g>mCWWtOYN9GG#ku-@h^XEd5-&z4(#V6)7Nc2*e_d
z8#g{VKgF>F^zg@t=qpFjpFDR>Nyg0$9Wo)jdp>InzNmr$$kQ81dCcw-80Xz^WeGhw
z)P(-Lesw7QerM*8>h6PcvcJ`={BAm88cgJ2S~7rSzVxY)U#0rLLd
zcm7)EPY%bS2BMOjm^Ak}TUp3B>t&IU4VzZk`0RL_kvA9DRshy4{)uwa=?8H4Po1j;`N`B*?tbRsZ;0qx?Zw&^|8q
ztE{^-wW(GzH5V88<1YU2b{o+EV*Lb>y6gQVNL7cko!Fa#P9d-s~A>ZV#ly3
z9F9U|Z(2#}3*0^xq1~WT_*w!SaTWYAQK7|l_f)%^(vio&dM3Tx+^XkP+}u~U2h^_c
zw^%Xs#?9znk#@Jr6J1MJ_|Ff`9%l~KG_`~_uFEXo%~Gq6+zC7d5=0|B%({*G?Un9S
ztE@G9J0DvWVLSanCNuKF^>qJg=4$7SPhY=WI6pgdo;Wtb!@+qOUu`Cl)W-YG`*Mwz
zF2Tjv-8Eq@yv5t~X`N|_8Oh&OD?roBKq}-V>yO5E5vog>k*_iR6ItMGJ@<@L%P2?7
zO9`>uuaya-t}aR`=%@tbOWunJC+nh~<+AtMJ(*gjD!O&|pE3UqQJtEsx;nPcC^oPU
znevJ37|E7Sv3tdA`{@_yW9VL0uN&Dl;gb&?*GI~mA|IQ+P1`e)Vnm|cyPwl!L^9#F
zOJ+I#&OZnR%=e(RV7d9-kSCX_-UAaKv9b$O6&8=i%ca+Qd$VtsCBJBpNB`aYTSM&H
ez{tIOPL_`c*xQUNx-P(b8HNyYHi8204F3;J$=i4U
literal 0
HcmV?d00001
diff --git a/sound/creatures/chick_peep.ogg b/sound/creatures/chick_peep.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..791246171a6886b431187ea960ffe6b661a2f715
GIT binary patch
literal 2845
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
ANdN!<
literal 0
HcmV?d00001
diff --git a/sound/creatures/clucks.ogg b/sound/creatures/clucks.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..e59afd424d814162785b5178bbacdbd2d4968db9
GIT binary patch
literal 10497
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