diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 13f774d25d..d3bf0a4e00 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -78455,6 +78455,7 @@
/turf/open/floor/engine,
/area/science/xenobiology)
"dbq" = (
+/mob/living/simple_animal/hostile/retaliate/goose/vomit,
/turf/open/floor/wood{
icon_state = "wood-broken6"
},
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 7e4f54c8b4..3d15f887bd 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -54387,6 +54387,10 @@
},
/turf/open/floor/plating,
/area/maintenance/department/cargo)
+"ggg" = (
+/mob/living/simple_animal/hostile/retaliate/goose/vomit,
+/turf/open/floor/wood,
+/area/maintenance/department/crew_quarters/dorms)
"gih" = (
/obj/machinery/atmospherics/pipe/simple/cyan/visible{
dir = 4
@@ -99275,7 +99279,7 @@ cBk
jhD
cBo
alQ
-alb
+ggg
cBw
noC
aiS
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 5503c6103d..e7562476a8 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -182,6 +182,8 @@
soundin = pick('sound/voice/beepsky/god.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/secureday.ogg', 'sound/voice/beepsky/radio.ogg', 'sound/voice/beepsky/insult.ogg', 'sound/voice/beepsky/creep.ogg')
if("honkbot_e")
soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/effects/reee.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/creep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg')
+ if("goose")
+ soundin = pick('sound/creatures/goose1.ogg', 'sound/creatures/goose2.ogg', 'sound/creatures/goose3.ogg', 'sound/creatures/goose4.ogg')
//START OF CIT CHANGES - adds random vore sounds
if ("struggle_sound")
soundin = pick( 'sound/vore/pred/struggle_01.ogg','sound/vore/pred/struggle_02.ogg','sound/vore/pred/struggle_03.ogg',
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 7110ff4405..f3d50729d1 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -452,16 +452,21 @@
/turf/AllowDrop()
return TRUE
-/turf/proc/add_vomit_floor(mob/living/carbon/M, toxvomit = NONE)
+/turf/proc/add_vomit_floor(mob/living/M, toxvomit = NONE)
+
var/obj/effect/decal/cleanable/vomit/V = new /obj/effect/decal/cleanable/vomit(src, M.get_static_viruses())
- // If the vomit combined, apply toxicity and reagents to the old vomit
+ //if the vomit combined, apply toxicity and reagents to the old vomit
if (QDELETED(V))
V = locate() in src
// Make toxins and blazaam vomit look different
if(toxvomit == VOMIT_PURPLE)
V.icon_state = "vomitpurp_[pick(1,4)]"
- else if(toxvomit == VOMIT_TOXIC)
+ else if (toxvomit == VOMIT_TOXIC)
V.icon_state = "vomittox_[pick(1,4)]"
+ if (iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(C.reagents)
+ clear_reagents_to_vomit_pool(C,V)
/proc/clear_reagents_to_vomit_pool(mob/living/carbon/M, obj/effect/decal/cleanable/vomit/V)
M.reagents.trans_to(V, M.reagents.total_volume / 10)
@@ -474,4 +479,4 @@
//Whatever happens after high temperature fire dies out or thermite reaction works.
//Should return new turf
/turf/proc/Melt()
- return ScrapeAway()
\ No newline at end of file
+ return ScrapeAway()
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 1087f1ebb5..86a9c21f10 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -2230,6 +2230,20 @@
contains = list(/mob/living/simple_animal/hostile/retaliate/goat)
crate_name = "goat crate"
+/datum/supply_pack/critter/goose
+ name = "Goose Crate"
+ desc = "Angry and violent birds. Evil, evil creatures."
+ cost = 2500
+ contains = list(/mob/living/simple_animal/hostile/retaliate/goose)
+ crate_name = "goose crate"
+
+/datum/supply_pack/critter/goose/vomit
+ name = "Vomit Goose Crate"
+ desc = "Angry and violent birds. Evil, evil creatures. This one pukes!"
+ cost = 5000
+ contains = list(/mob/living/simple_animal/hostile/retaliate/goose/vomit/cargo)
+ crate_name = "vomit goose crate"
+
/datum/supply_pack/critter/monkey
name = "Monkey Cube Crate"
desc = "Stop monkeying around! Contains seven monkey cubes. Just add water!"
diff --git a/code/modules/mob/living/simple_animal/hostile/goose.dm b/code/modules/mob/living/simple_animal/hostile/goose.dm
new file mode 100644
index 0000000000..50b8261c79
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/goose.dm
@@ -0,0 +1,173 @@
+#define GOOSE_SATIATED 50
+
+/mob/living/simple_animal/hostile/retaliate/goose
+ name = "goose"
+ desc = "It's loose"
+ icon_state = "goose" // sprites by cogwerks from goonstation, used with permission
+ icon_living = "goose"
+ icon_dead = "goose_dead"
+ mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
+ speak_chance = 0
+ turns_per_move = 5
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 2)
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+ emote_taunt = list("hisses")
+ taunt_chance = 30
+ speed = 0
+ maxHealth = 25
+ health = 25
+ harm_intent_damage = 5
+ melee_damage_lower = 5
+ melee_damage_upper = 5
+ attacktext = "pecks"
+ attack_sound = "goose"
+ speak_emote = list("honks")
+ faction = list("neutral")
+ attack_same = TRUE
+ gold_core_spawnable = HOSTILE_SPAWN
+ var/random_retaliate = TRUE
+ var/icon_vomit_start = "vomit_start"
+ var/icon_vomit = "vomit"
+ var/icon_vomit_end = "vomit_end"
+
+/mob/living/simple_animal/hostile/retaliate/goose/handle_automated_movement()
+ . = ..()
+ if(prob(5) && random_retaliate == TRUE)
+ Retaliate()
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit
+ name = "Birdboat"
+ real_name = "Birdboat"
+ desc = "It's a sick-looking goose, probably ate too much maintenance trash. Best not to move it around too much."
+ gender = MALE
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+ gold_core_spawnable = NO_SPAWN
+ random_retaliate = FALSE
+ var/vomiting = FALSE
+ var/vomitCoefficient = 1
+ var/vomitTimeBonus = 0
+ var/datum/action/cooldown/vomit/goosevomit
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/cargo
+ name = "Sickly Goose"
+ real_name = "Sickly Goose"
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/Initialize()
+ . = ..()
+ goosevomit = new
+ goosevomit.Grant(src)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/Destroy()
+ QDEL_NULL(goosevomit)
+ return ..()
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/examine(user)
+ . = ..()
+ . += "Somehow, it still looks hungry."
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/attacked_by(obj/item/O, mob/user)
+ . = ..()
+ feed(O)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/feed(obj/item/O)
+ var/obj/item/reagent_containers/food/tasty = O
+ if(!istype(O))
+ return
+ if (contents.len > GOOSE_SATIATED)
+ visible_message("[src] looks too full to eat \the [tasty]!")
+ return
+ if (tasty.foodtype & GROSS)
+ visible_message("[src] hungrily gobbles up \the [tasty]!")
+ tasty.forceMove(src)
+ playsound(src,'sound/items/eatfood.ogg', 70, 1)
+ vomitCoefficient += 3
+ vomitTimeBonus += 2
+ else
+ visible_message("[src] refuses to eat \the [tasty].")
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit()
+ var/turf/T = get_turf(src)
+ var/obj/item/reagent_containers/food/consumed = locate() in contents //Barf out a single food item from our guts
+ if (prob(50) && consumed)
+ barf_food(consumed)
+ else
+ playsound(T, 'sound/effects/splat.ogg', 50, 1)
+ T.add_vomit_floor(src)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/barf_food(var/atom/A, var/hard = FALSE)
+ if(!istype(A, /obj/item/reagent_containers/food))
+ return
+ var/turf/currentTurf = get_turf(src)
+ var/obj/item/reagent_containers/food/consumed = A
+ consumed.forceMove(currentTurf)
+ var/destination = get_edge_target_turf(currentTurf, pick(GLOB.alldirs)) //Pick a random direction to toss them in
+ var/throwRange = hard ? rand(2,8) : 1
+ consumed.safe_throw_at(destination, throwRange, 2) //Thow the food at a random tile 1 spot away
+ sleep(2)
+ if (QDELETED(src) || QDELETED(consumed))
+ return
+ currentTurf = get_turf(consumed)
+ currentTurf.add_vomit_floor(src)
+ playsound(currentTurf, 'sound/effects/splat.ogg', 50, 1)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit_prestart(duration)
+ flick("vomit_start",src)
+ addtimer(CALLBACK(src, .proc/vomit_start, duration), 13) //13 is the length of the vomit_start animation in gooseloose.dmi
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit_start(duration)
+ vomiting = TRUE
+ icon_state = "vomit"
+ vomit()
+ addtimer(CALLBACK(src, .proc/vomit_preend), duration)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit_preend()
+ for (var/obj/item/consumed in contents) //Get rid of any food left in the poor thing
+ barf_food(consumed, TRUE)
+ sleep(1)
+ if (QDELETED(src))
+ return
+ vomit_end()
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/proc/vomit_end()
+ flick("vomit_end",src)
+ vomiting = FALSE
+ icon_state = initial(icon_state)
+
+/mob/living/simple_animal/hostile/retaliate/goose/vomit/Moved(oldLoc, dir)
+ . = ..()
+ if(vomiting)
+ vomit() // its supposed to keep vomiting if you move
+ return
+ var/turf/currentTurf = get_turf(src)
+ while (currentTurf == get_turf(src))
+ var/obj/item/reagent_containers/food/tasty = locate() in currentTurf
+ if (tasty)
+ feed(tasty)
+ stoplag(20)
+ if(prob(vomitCoefficient * 0.2))
+ vomit_prestart(vomitTimeBonus + 25)
+ vomitCoefficient = 1
+ vomitTimeBonus = 0
+
+/datum/action/cooldown/vomit
+ name = "Vomit"
+ check_flags = AB_CHECK_CONSCIOUS
+ button_icon_state = "vomit"
+ icon_icon = 'icons/mob/animal.dmi'
+ cooldown_time = 250
+
+/datum/action/cooldown/vomit/Trigger()
+ if(!..())
+ return FALSE
+ if(!istype(owner, /mob/living/simple_animal/hostile/retaliate/goose/vomit))
+ return FALSE
+ var/mob/living/simple_animal/hostile/retaliate/goose/vomit/vomit = owner
+ if(!vomit.vomiting)
+ vomit.vomit_prestart(vomit.vomitTimeBonus + 25)
+ vomit.vomitCoefficient = 1
+ vomit.vomitTimeBonus = 0
+ return TRUE
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index 2a85f8a422..e9343c7ed2 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/sound/creatures/goose1.ogg b/sound/creatures/goose1.ogg
new file mode 100644
index 0000000000..3d605ad622
Binary files /dev/null and b/sound/creatures/goose1.ogg differ
diff --git a/sound/creatures/goose2.ogg b/sound/creatures/goose2.ogg
new file mode 100644
index 0000000000..735faba791
Binary files /dev/null and b/sound/creatures/goose2.ogg differ
diff --git a/sound/creatures/goose3.ogg b/sound/creatures/goose3.ogg
new file mode 100644
index 0000000000..1aeec77369
Binary files /dev/null and b/sound/creatures/goose3.ogg differ
diff --git a/sound/creatures/goose4.ogg b/sound/creatures/goose4.ogg
new file mode 100644
index 0000000000..699f143bd3
Binary files /dev/null and b/sound/creatures/goose4.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index cceeb1f915..9929e4b2df 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2192,6 +2192,7 @@
#include "code\modules\mob\living\simple_animal\hostile\eyeballs.dm"
#include "code\modules\mob\living\simple_animal\hostile\faithless.dm"
#include "code\modules\mob\living\simple_animal\hostile\giant_spider.dm"
+#include "code\modules\mob\living\simple_animal\hostile\goose.dm"
#include "code\modules\mob\living\simple_animal\hostile\headcrab.dm"
#include "code\modules\mob\living\simple_animal\hostile\hivebot.dm"
#include "code\modules\mob\living\simple_animal\hostile\hostile.dm"