diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 9fd3794520..66b4bd5e73 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -99,15 +99,17 @@
evolve()
return
for(var/obj/item/trash/garbage in range(1, src))
- if(prob(2))
- qdel(garbage)
- evolve_plague()
- return
+ if(is_station_level(z))
+ if(prob(2))
+ qdel(garbage)
+ evolve_plague()
+ return
for(var/obj/effect/decal/cleanable/blood/gibs/leftovers in range(1, src))
- if(prob(2))
- qdel(leftovers)
- evolve_plague()
- return
+ if(is_station_level(z))
+ if(prob(2))
+ qdel(leftovers)
+ evolve_plague()
+ return
/**
*Checks the mouse cap, if it's above the cap, doesn't spawn a mouse. If below, spawns a mouse and adds it to cheeserats.
@@ -202,4 +204,5 @@ GLOBAL_VAR(tom_existed)
/mob/living/simple_animal/mouse/handle_environment(datum/gas_mixture/environment)
. = ..()
- miasma()
+ if(is_station_level(z))
+ miasma()
diff --git a/code/modules/mob/living/simple_animal/hostile/plaguerat.dm b/code/modules/mob/living/simple_animal/hostile/plaguerat.dm
index 331dc1eb75..2b92894317 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."
@@ -11,8 +14,8 @@
gender = NEUTER
speak_chance = 1
turns_per_move = 5
- maxHealth = 15
- health = 15
+ maxHealth = 100
+ health = 100
see_in_dark = 6
obj_damage = 10
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
@@ -22,8 +25,8 @@
response_disarm_simple = "skoff at"
response_harm_continuous = "slashes"
response_harm_simple = "slash"
- melee_damage_lower = 5
- melee_damage_upper = 7
+ melee_damage_lower = 6
+ melee_damage_upper = 8
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
attack_sound = 'sound/weapons/punch1.ogg'
@@ -34,27 +37,69 @@
mob_biotypes = MOB_ORGANIC|MOB_BEAST
var/datum/action/cooldown/scavenge
var/last_spawn_time = 0
- ///Number assigned to rats and mice, checked when determining infighting.
+ 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))
@@ -66,9 +111,10 @@
playsound(src, 'sound/effects/sparks2.ogg', 100, TRUE)
C.deconstruct()
for(var/obj/O in range(1,src))
- if(istype(O, /obj/item/trash) || istype(O, /obj/effect/decal/cleanable/blood/gibs))
+ if((world.time - last_spawn_time) > 10 SECONDS && istype(O, /obj/item/trash) || istype(O, /obj/effect/decal/cleanable/blood/gibs))
qdel(O)
be_fruitful()
+ last_spawn_time = world.time
/mob/living/simple_animal/hostile/plaguerat/CanAttack(atom/the_target)
if(istype(the_target,/mob/living/simple_animal))
@@ -86,14 +132,29 @@
*/
/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
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.
*/
@@ -116,16 +177,12 @@
if(1 to 3)
var/pickedtrash = pick(GLOB.ratking_trash)
to_chat(owner, "Excellent, you find more trash to spread your filth!")
- new /obj/effect/decal/cleanable/dirt(T)
new pickedtrash(T)
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)
- 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.")
- new /obj/effect/decal/cleanable/dirt(T)
StartCooldown()