diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 81a0cf3d028..03959a3265b 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -5717,6 +5717,10 @@ }, /turf/open/floor/plasteel/dark, /area/security/courtroom) +"amu" = ( +/mob/living/simple_animal/hostile/retaliate/goose/vomit, +/turf/open/floor/wood, +/area/maintenance/port/aft) "amv" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/door/airlock/external{ @@ -72265,7 +72269,7 @@ bCq bPS aad bPS -bPS +amu bCq cbk bLv diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 27531838ff7..5bb87dbc52a 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -96331,6 +96331,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/abandoned_gambling_den) "dvV" = ( +/mob/living/simple_animal/hostile/retaliate/goose/vomit, /turf/open/floor/wood{ icon_state = "wood-broken7" }, diff --git a/_maps/map_files/Donutstation/Donutstation.dmm b/_maps/map_files/Donutstation/Donutstation.dmm index 19fb34449b1..71cb4986016 100644 --- a/_maps/map_files/Donutstation/Donutstation.dmm +++ b/_maps/map_files/Donutstation/Donutstation.dmm @@ -5,6 +5,13 @@ "aab" = ( /turf/closed/wall, /area/space/nearstation) +"aac" = ( +/obj/effect/decal/cleanable/dirt, +/mob/living/simple_animal/hostile/retaliate/goose/vomit, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/maintenance/department/crew_quarters/bar) "aad" = ( /turf/closed/wall/r_wall, /area/engine/engineering) @@ -75563,7 +75570,7 @@ kIi bXA bVM bVU -bSy +aac bSy bWC aRr diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index a2f581c4218..9d9ffd16b82 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -9939,6 +9939,10 @@ /obj/structure/cable, /turf/open/floor/plating, /area/maintenance/starboard) +"auR" = ( +/mob/living/simple_animal/hostile/retaliate/goose/vomit, +/turf/open/floor/wood, +/area/maintenance/port/aft) "auU" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -92469,7 +92473,7 @@ ckP ckS ckP ckP -ckP +auR cjt crh ckN diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 7803dbac70b..ed803e219ea 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -56011,6 +56011,10 @@ icon_state = "panelscorched" }, /area/maintenance/department/science) +"tSN" = ( +/mob/living/simple_animal/hostile/retaliate/goose/vomit, +/turf/open/floor/wood, +/area/maintenance/department/crew_quarters/dorms) "tSU" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible/layer1, /obj/effect/turf_decal/stripes/line{ @@ -94879,7 +94883,7 @@ cBk jhD cBo alQ -alb +tSN cBw alb aiS diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 22c1ab84e3e..f83d44977d6 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -536,9 +536,11 @@ /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 if(!V) @@ -546,10 +548,12 @@ // 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(M.reagents) - clear_reagents_to_vomit_pool(M,V) + 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, transfered_by = M) diff --git a/code/modules/mob/living/simple_animal/hostile/goose.dm b/code/modules/mob/living/simple_animal/hostile/goose.dm index a0a2073a790..19e9c7c8b30 100644 --- a/code/modules/mob/living/simple_animal/hostile/goose.dm +++ b/code/modules/mob/living/simple_animal/hostile/goose.dm @@ -1,7 +1,9 @@ +#define GOOSE_SATIATED 50 + /mob/living/simple_animal/hostile/retaliate/goose name = "goose" desc = "It's loose" - icon_state = "goose" + 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) @@ -10,7 +12,7 @@ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 2) response_help = "pets" response_disarm = "gently pushes aside" - response_harm = "hits" + response_harm = "kicks" emote_taunt = list("hisses") taunt_chance = 30 speed = 0 @@ -25,33 +27,143 @@ faction = list("neutral") attack_same = TRUE gold_core_spawnable = HOSTILE_SPAWN - var/icon_resting = "goose_sit" - - -/mob/living/simple_animal/hostile/retaliate/goose/toggle_ai(togglestatus) - . = ..() - if(!key) - if(AIStatus != AI_ON) - set_resting(TRUE) - else - set_resting(FALSE) - -/mob/living/simple_animal/hostile/retaliate/goose/update_resting() - . = ..() - if(resting) - wander = FALSE - else - wander = TRUE - update_icon() + 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)) + if(prob(5) && random_retaliate == TRUE) Retaliate() -/mob/living/simple_animal/hostile/retaliate/goose/proc/update_icon() - if(stat != DEAD) - icon_state = resting ? icon_resting : icon_living - else - icon_state = icon_dead +/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/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(2) + 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 0fa693a7c52..e551678e5a2 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ