diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm
index df980539..665ed2b8 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_events.dm
@@ -147,6 +147,25 @@
occurances_max = 2
chaos_min = 1.5
+//////////////////////////////////////////////
+// //
+// MIMICS //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/event/mimics
+ name = "Mimic Infestation"
+ typepath = /datum/round_event/mimic_infestation
+ enemy_roles = list("AI","Security Officer","Head of Security","Captain")
+ required_enemies = list(3,2,2,2,2,1,1,1,0,0)
+ weight = 2
+ cost = 5
+ requirements = list(101,20,15,10,10,10,10,10,10,10)
+ high_population_requirement = 15
+ earliest_start = 30 MINUTES
+ occurances_max = 2
+ chaos_min = 2
+
//////////////////////////////////////////////
// //
// CLOGGED VENTS //
diff --git a/hyperstation/code/mobs/mimic.dm b/hyperstation/code/mobs/mimic.dm
index bc1bb976..082d7d5e 100644
--- a/hyperstation/code/mobs/mimic.dm
+++ b/hyperstation/code/mobs/mimic.dm
@@ -10,7 +10,7 @@
maxHealth = 38
health = 38
turns_per_move = 5
- move_to_delay = 3
+ move_to_delay = 1
speed = 0
see_in_dark = 6
pass_flags = PASSTABLE
@@ -30,22 +30,72 @@
vision_range = 2
aggro_vision_range = 9
wander = TRUE
- minbodytemp = 250 //VERY weak to cold
+ minbodytemp = 250 //weak to cold
maxbodytemp = 1500
pressure_resistance = 600
var/unstealth = FALSE
var/knockdown_people = 1
+ var/static/mimic_blacklisted_transform_items = typecacheof(list(
+ /obj/item/projectile,
+ /obj/item/radio/intercom))
+ var/turns_since_notarget
/mob/living/simple_animal/hostile/hs13mimic/Initialize()
. = ..()
// When initialized, make sure they take the form of something.
unstealth = FALSE
- Mimictransform()
+ trytftorandomobject()
/mob/living/simple_animal/hostile/hs13mimic/attack_hand(mob/living/carbon/human/M)
. = ..()
trigger()
+/mob/living/simple_animal/hostile/hs13mimic/Life()
+ . = ..()
+ turns_since_notarget++
+ if(turns_since_notarget >= 5)
+ turns_since_notarget = 0
+ if(unstealth && (!target || isdead(target)))
+ target = null
+ trytftorandomobject()
+
+/mob/living/simple_animal/hostile/hs13mimic/AttackingTarget()
+ . = ..()
+ if(knockdown_people && . && prob(15) && iscarbon(target))
+ var/mob/living/carbon/C = target
+ C.Knockdown(40)
+ C.visible_message("\The [src] knocks down \the [C]!", \
+ "\The [src] knocks you down!")
+
+/mob/living/simple_animal/hostile/hs13mimic/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
+ trigger()
+ . = ..()
+
+/mob/living/simple_animal/hostile/hs13mimic/FindTarget()
+ . = ..()
+ if(.)
+ trigger()
+ else if(!target && unstealth)
+ trytftorandomobject()
+
+/mob/living/simple_animal/hostile/hs13mimic/death(gibbed)
+ restore()
+ . = ..()
+
+/mob/living/simple_animal/hostile/hs13mimic/med_hud_set_health()
+ if(!unstealth)
+ var/image/holder = hud_list[HEALTH_HUD]
+ holder.icon_state = null
+ return //we hide medical hud while morphed
+ ..()
+
+/mob/living/simple_animal/hostile/hs13mimic/med_hud_set_status()
+ if(!unstealth)
+ var/image/holder = hud_list[STATUS_HUD]
+ holder.icon_state = null
+ return //we hide medical hud while morphed
+ ..()
+
/mob/living/simple_animal/hostile/hs13mimic/proc/Mimictransform() //The list of default things to transform needs to be bigger, consider this in the future.
var/transformitem = rand(1,100)
medhudupdate()
@@ -114,43 +164,6 @@
else
restore()
-/mob/living/simple_animal/hostile/hs13mimic/AttackingTarget()
- . = ..()
- if(knockdown_people && . && prob(15) && iscarbon(target))
- var/mob/living/carbon/C = target
- C.Knockdown(40)
- C.visible_message("\The [src] knocks down \the [C]!", \
- "\The [src] knocks you down!")
-
-/mob/living/simple_animal/hostile/hs13mimic/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
- trigger()
- . = ..()
-
-/mob/living/simple_animal/hostile/hs13mimic/FindTarget()
- . = ..()
- if(.)
- trigger()
- else if(!target && unstealth)
- trytftorandomobject()
-
-/mob/living/simple_animal/hostile/hs13mimic/death(gibbed)
- restore()
- . = ..()
-
-/mob/living/simple_animal/hostile/hs13mimic/med_hud_set_health()
- if(!unstealth)
- var/image/holder = hud_list[HEALTH_HUD]
- holder.icon_state = null
- return //we hide medical hud while morphed
- ..()
-
-/mob/living/simple_animal/hostile/hs13mimic/med_hud_set_status()
- if(!unstealth)
- var/image/holder = hud_list[STATUS_HUD]
- holder.icon_state = null
- return //we hide medical hud while morphed
- ..()
-
/mob/living/simple_animal/hostile/hs13mimic/proc/medhudupdate()
med_hud_set_health()
med_hud_set_status()
@@ -175,7 +188,7 @@
/mob/living/simple_animal/hostile/hs13mimic/proc/triggerOthers(passtarget) //
for(var/mob/living/simple_animal/hostile/hs13mimic/C in oview(5, src.loc))
- if(passtarget && C.target == null)
+ if(passtarget && C.target == null && !(isdead(target)))
C.target = passtarget
C.trigger()
@@ -184,7 +197,8 @@
medhudupdate()
var/list/obj/item/listItems = list()
for(var/obj/item/I in oview(9,src.loc))
- listItems += I
+ if(!(is_type_in_typecache(I, mimic_blacklisted_transform_items)))
+ listItems += I
if(LAZYLEN(listItems))
var/obj/item/changedReference = pick(listItems)
wander = FALSE
@@ -195,3 +209,101 @@
desc = changedReference.desc
else
Mimictransform()
+
+
+//Event control
+
+
+/datum/round_event_control/mimic_infestation
+ name = "Mimic Infestation"
+ typepath = /datum/round_event/mimic_infestation
+ weight = 5
+ max_occurrences = 1
+ min_players = 15
+
+/datum/round_event/mimic_infestation
+ announceWhen = 200
+ var/static/list/mimic_station_areas_blacklist = typecacheof(/area/space,
+ /area/shuttle,
+ /area/mine,
+ /area/holodeck,
+ /area/ruin,
+ /area/hallway,
+ /area/hallway/primary,
+ /area/hallway/secondary,
+ /area/hallway/secondary/entry,
+ /area/engine/supermatter,
+ /area/engine/atmospherics_engine,
+ /area/engine/engineering/reactor_core,
+ /area/engine/engineering/reactor_control,
+ /area/ai_monitored/turret_protected/ai,
+ /area/layenia/cloudlayer,
+ /area/asteroid/nearstation,
+ /area/science/server,
+ /area/science/explab,
+ /area/security/processing)
+ var/spawncount = 1
+ fakeable = FALSE
+
+/datum/round_event/mimic_infestation/setup()
+ announceWhen = rand(announceWhen, announceWhen + 50)
+ spawncount = rand(4, 7)
+
+/datum/round_event/mimic_infestation/announce(fake)
+ priority_announce("Unidentified lifesigns detected aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", 'sound/ai/aliens.ogg')
+
+/datum/round_event/mimic_infestation/start()
+ var/list/area/stationAreas = list()
+ var/list/area/eligible_areas = list()
+ for(var/area/A in world) // Get the areas in the Z level
+ if(A.z == SSmapping.station_start)
+ stationAreas += A
+ for(var/area/place in stationAreas) // first we check if it's a valid area
+ if(place.outdoors)
+ continue
+ if(place.areasize < 16)
+ continue
+ if(is_type_in_typecache(place, mimic_station_areas_blacklist))
+ continue
+ eligible_areas += place
+ for(var/area/place in eligible_areas) // now we check if there are people in that area
+ var/numOfPeople
+ for(var/mob/living/carbon/H in place)
+ numOfPeople++
+ break
+ if(numOfPeople > 0)
+ eligible_areas -= place
+
+ var/validFound = FALSE
+ var/list/turf/validTurfs = list()
+ var/area/pickedArea
+ while(!validFound || !eligible_areas.len)
+ pickedArea = pick_n_take(eligible_areas)
+ var/list/turf/t = get_area_turfs(pickedArea, SSmapping.station_start)
+ for(var/turf/thisTurf in t) // now we check if it's a closed turf, cold turf or occupied turf and yeet it
+ if(isopenturf(thisTurf))
+ var/turf/open/tempGet = thisTurf
+ if(tempGet.air.temperature <= T0C)
+ t -= thisTurf
+ continue
+ if(isclosedturf(thisTurf))
+ t -= thisTurf
+ else
+ for(var/obj/O in thisTurf)
+ if(O.density && !(istype(O, /obj/structure/table)))
+ t -= thisTurf
+ break
+ if(t.len >= spawncount) //Is the number of available turfs equal or bigger than spawncount?
+ validFound = TRUE
+ validTurfs = t
+
+ if(!eligible_areas.len)
+ message_admins("No eligible areas for spawning mimics.")
+ return FALSE
+
+ notify_ghosts("A group of mimics has spawned in [pickedArea]!", source=pickedArea, action=NOTIFY_ATTACK, flashwindow = FALSE)
+ while(spawncount >= 1 && validTurfs.len)
+ var/turf/pickedTurf = pick_n_take(validTurfs)
+ var/spawn_type = /mob/living/simple_animal/hostile/hs13mimic
+ spawn_atom_to_turf(spawn_type, pickedTurf, 1, FALSE)
+ spawncount--