diff --git a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
index fd4de815d3..43432394b7 100644
--- a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
@@ -1,3 +1,6 @@
+#define RAT_VENT_CHANCE 1.75
+GLOBAL_LIST_EMPTY(plague_rats)
+
/mob/living/simple_animal/hostile/plaguerat
name = "plague rat"
desc = "A large decaying rat. It spreads its filth and emits a putrid odor to create more of its kind."
@@ -34,26 +37,69 @@
mob_biotypes = MOB_ORGANIC|MOB_BEAST
var/datum/action/cooldown/scavenge
var/last_spawn_time = 0
+ var/in_vent = FALSE
+ var/min_next_vent = 0
+ var/obj/machinery/atmospherics/components/unary/entry_vent
+ var/obj/machinery/atmospherics/components/unary/exit_vent
/mob/living/simple_animal/hostile/plaguerat/Initialize()
. = ..()
- SSmobs.cheeserats += src
+ GLOB.plague_rats += src
AddComponent(/datum/component/swarming)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
scavenge = new /datum/action/cooldown/scavenge
scavenge.Grant(src)
/mob/living/simple_animal/hostile/plaguerat/Destroy()
- SSmobs.cheeserats -= src
+ GLOB.plague_rats -= src
return ..()
+/mob/living/simple_animal/hostile/plaguerat/Life(seconds, times_fired)
+ . = ..()
+ //Don't try to path to one target for too long. If it takes longer than a certain amount of time, assume it can't be reached and find a new one
+ //Literally only here to prevent farming and that's it.
+ if(!client) //don't do this shit if there's a client, they're capable of ventcrawling manually
+ if(in_vent)
+ target = null
+ if(entry_vent && get_dist(src, entry_vent) <= 1)
+ var/list/vents = list()
+ var/datum/pipeline/entry_vent_parent = entry_vent.parents[1]
+ for(var/obj/machinery/atmospherics/components/unary/temp_vent in entry_vent_parent.other_atmosmch)
+ vents += temp_vent
+ if(!vents.len)
+ entry_vent = null
+ in_vent = FALSE
+ return
+ exit_vent = pick(vents)
+ visible_message("[src] crawls into the ventilation ducts!")
+
+ loc = exit_vent
+ var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
+ addtimer(CALLBACK(src, .proc/exit_vents), travel_time) //come out at exit vent in 2 to 20 seconds
+
+
+ if(world.time > min_next_vent && !entry_vent && !in_vent && prob(RAT_VENT_CHANCE)) //small chance to go into a vent
+ for(var/obj/machinery/atmospherics/components/unary/v in view(7,src))
+ if(!v.welded)
+ entry_vent = v
+ in_vent = TRUE
+ walk_to(src, entry_vent)
+ break
+
/mob/living/simple_animal/hostile/plaguerat/BiologicalLife(seconds, times_fired)
if(!(. = ..()))
return
if(isopenturf(loc))
var/turf/open/T = src.loc
+ var/datum/gas_mixture/stank = new
+ var/miasma_moles = T.air.get_moles(GAS_MIASMA)
+ stank.set_moles(GAS_MIASMA,5)
+ stank.set_temperature(BODYTEMP_NORMAL)
if(T.air)
- T.atmos_spawn_air("miasma=5;TEMP=293.15")
+ if(miasma_moles < 200)
+ T.assume_air(stank)
+ T.air_update_turf()
+
if(prob(40))
scavenge.Trigger()
if(prob(50))
@@ -86,14 +132,30 @@
*/
/mob/living/simple_animal/hostile/plaguerat/proc/be_fruitful()
- var/cap = CONFIG_GET(number/ratcap)
- if(LAZYLEN(SSmobs.cheeserats) >= cap)
+ var/cap = 10
+ if(LAZYLEN(GLOB.plague_rats) >= cap)
visible_message("[src] gnaws into its food, [cap] rats are now on the station!")
return
var/mob/living/newmouse = new /mob/living/simple_animal/hostile/plaguerat(loc)
- SSmobs.cheeserats += newmouse
+ GLOB.plague_rats += newmouse
visible_message("[src] gnaws into its food, attracting another rat!")
+/mob/living/simple_animal/hostile/plaguerat/proc/exit_vents()
+ if(!exit_vent || exit_vent.welded)
+ loc = entry_vent
+ entry_vent = null
+ return
+ loc = exit_vent.loc
+ entry_vent = null
+ exit_vent = null
+ in_vent = FALSE
+ var/area/new_area = get_area(loc)
+ message_admins("[src] came out at [new_area][ADMIN_JMP(loc)]!")
+ if(new_area)
+ new_area.Entered(src)
+ visible_message("[src] climbs out of the ventilation ducts!")
+ min_next_vent = world.time + 900 //90 seconds between ventcrawls
+
/**
*Creates a chance to spawn more trash or gibs to repopulate. Otherwise, spawns a corpse or dirt.
*/
@@ -120,14 +182,8 @@
if(4 to 6)
to_chat(owner, "You find blood and gibs to feed your young!")
new /obj/effect/decal/cleanable/blood/gibs(T)
- new /obj/effect/decal/cleanable/blood/(T)
- if(7 to 18)
- if(locate(/mob/living/carbon/human) in T)
- to_chat(owner, "A corpse is blocking you from digging.")
- return
- else
- to_chat(owner, "A corpse rises from the ground. Best to leave it alone.")
- new /obj/effect/mob_spawn/human/corpse/assistant(T)
- if(19 to 100)
+ if(!locate(/obj/effect/decal/cleanable/blood) in T)
+ new /obj/effect/decal/cleanable/blood/(T)
+ if(7 to 100)
to_chat(owner, "Drat. Nothing.")
StartCooldown()