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--