diff --git a/code/modules/ai/ai_holder_subtypes/simple_mob_ai.dm b/code/modules/ai/ai_holder_subtypes/simple_mob_ai.dm
index a53906a7a3a..9a173c0ba71 100644
--- a/code/modules/ai/ai_holder_subtypes/simple_mob_ai.dm
+++ b/code/modules/ai/ai_holder_subtypes/simple_mob_ai.dm
@@ -147,6 +147,9 @@
hostile = FALSE
retaliate = TRUE
+/datum/ai_holder/simple_mob/retaliate/chill
+ base_wander_delay = 8
+
// Simple mobs that retaliate and support others in their faction who get attacked.
/datum/ai_holder/simple_mob/retaliate/cooperative
cooperative = TRUE
diff --git a/code/modules/events/gnat_migration.dm b/code/modules/events/gnat_migration.dm
new file mode 100644
index 00000000000..e807f85b3c6
--- /dev/null
+++ b/code/modules/events/gnat_migration.dm
@@ -0,0 +1,102 @@
+/datum/event/gnat_migration
+ startWhen = 0 // Start immediately
+ announceWhen = 45 // Adjusted by setup
+ endWhen = 75 // Adjusted by setup
+ var/gnat_cap = 10
+ var/list/spawned_gnat = list()
+
+/datum/event/gnat_migration/setup()
+ announceWhen = rand(30, 60) // 1 to 2 minutes
+ endWhen += severity * 25
+ gnat_cap = 8 + 4 ** severity // No more than this many at once regardless of waves. (12, 16, ??)
+
+/datum/event/gnat_migration/start()
+ affecting_z -= global.using_map.sealed_levels // Space levels only please!
+ ..()
+
+/datum/event/gnat_migration/announce()
+ var/announcement = ""
+ if(severity == EVENT_LEVEL_MAJOR)
+ announcement = "Massive migration of unknown biological entities has been detected near [location_name()], please stand-by."
+ else
+ announcement = "Unknown biological [spawned_gnat.len == 1 ? "entity has" : "entities have"] been detected near [location_name()], please stand-by."
+ command_announcement.Announce(announcement, "Lifesign Alert")
+
+/datum/event/gnat_migration/tick()
+ if(activeFor % 5 != 0)
+ return // Only process every 10 seconds.
+ if(count_spawned_gnats() < gnat_cap)
+ spawn_fish(rand(3, 3 + severity * 2) - 1, 1, severity + 2)
+
+/datum/event/gnat_migration/proc/spawn_fish(var/num_groups, var/group_size_min, var/group_size_max, var/dir)
+ if(isnull(dir))
+ dir = (victim && prob(80)) ? victim.fore_dir : pick(GLOB.cardinal)
+
+ // Check if any landmarks exist!
+ var/list/spawn_locations = list()
+ for(var/obj/effect/landmark/C in landmarks_list)
+ if(C.name == "gnatspawn" && (C.z in affecting_z))
+ spawn_locations.Add(C.loc)
+ if(spawn_locations.len) // Okay we've got landmarks, lets use those!
+ shuffle_inplace(spawn_locations)
+ num_groups = min(num_groups, spawn_locations.len)
+ for (var/i = 1, i <= num_groups, i++)
+ var/group_size = rand(group_size_min, group_size_max)
+ for (var/j = 0, j < group_size, j++)
+ spawn_one_gnat(spawn_locations[i])
+ return
+
+ // Okay we did *not* have any landmarks, so lets do our best!
+ var/i = 1
+ while (i <= num_groups)
+ var/Z = pick(affecting_z)
+ var/group_size = rand(group_size_min, group_size_max)
+ var/turf/map_center = locate(round(world.maxx/2), round(world.maxy/2), Z)
+ var/turf/group_center = pick_random_edge_turf(dir, Z, TRANSITIONEDGE + 2)
+ var/list/turfs = getcircle(group_center, 2)
+ for (var/j = 0, j < group_size, j++)
+ var/mob/living/simple_mob/animal/M = spawn_one_gnat(turfs[(i % turfs.len) + 1])
+ // Ray trace towards middle of the map to find where they can stop just outside of structure/ship.
+ var/turf/target
+ for(var/turf/T in getline(get_turf(M), map_center))
+ if(!T.is_space())
+ break;
+ target = T
+ if(target)
+ M.ai_holder?.give_destination(target) // Ask gnat to swim towards the middle of the map
+ i++
+
+// Spawn a single gnat at given location.
+/datum/event/gnat_migration/proc/spawn_one_gnat(var/loc)
+ var/mob/living/simple_mob/animal/M = new /mob/living/simple_mob/animal/space/gnat(loc)
+ GLOB.destroyed_event.register(M, src, .proc/on_gnat_destruction)
+ spawned_gnat.Add(M)
+ return M
+
+// Counts living gnat spawned by this event.
+/datum/event/gnat_migration/proc/count_spawned_gnats()
+ . = 0
+ for(var/mob/living/simple_mob/animal/M as anything in spawned_gnat)
+ if(!QDELETED(M) && M.stat != DEAD)
+ . += 1
+
+// If gnat is bomphed, remove it from the list.
+/datum/event/gnat_migration/proc/on_gnat_destruction(var/mob/M)
+ spawned_gnat -= M
+ GLOB.destroyed_event.unregister(M, src, .proc/on_gnat_destruction)
+
+/datum/event/gnat_migration/end()
+ . = ..()
+ // Clean up gnat that died in space for some reason.
+ spawn(0)
+ for(var/mob/living/simple_mob/SM in spawned_gnat)
+ if(SM.stat == DEAD)
+ var/turf/T = get_turf(SM)
+ if(istype(T, /turf/space))
+ if(prob(75))
+ qdel(SM)
+ CHECK_TICK
+
+// Overmap version
+/datum/event/gnat_migration/overmap/announce()
+ return
diff --git a/code/modules/events/ray_migration.dm b/code/modules/events/ray_migration.dm
new file mode 100644
index 00000000000..3df3971a814
--- /dev/null
+++ b/code/modules/events/ray_migration.dm
@@ -0,0 +1,102 @@
+/datum/event/ray_migration
+ startWhen = 0 // Start immediately
+ announceWhen = 45 // Adjusted by setup
+ endWhen = 75 // Adjusted by setup
+ var/ray_cap = 10
+ var/list/spawned_ray = list()
+
+/datum/event/ray_migration/setup()
+ announceWhen = rand(30, 60) // 1 to 2 minutes
+ endWhen += severity * 25
+ ray_cap = 1 + 1 ** severity // No more than this many at once regardless of waves. (2, 3, ?)
+
+/datum/event/ray_migration/start()
+ affecting_z -= global.using_map.sealed_levels // Space levels only please!
+ ..()
+
+/datum/event/ray_migration/announce()
+ var/announcement = ""
+ if(severity == EVENT_LEVEL_MAJOR)
+ announcement = "Massive migration of unknown biological entities has been detected near [location_name()], please stand-by."
+ else
+ announcement = "Unknown biological [spawned_ray.len == 1 ? "entity has" : "entities have"] been detected near [location_name()], please stand-by."
+ command_announcement.Announce(announcement, "Lifesign Alert")
+
+/datum/event/ray_migration/tick()
+ if(activeFor % 5 != 0)
+ return // Only process every 10 seconds.
+ if(count_spawned_rays() < ray_cap)
+ spawn_fish(rand(3, 3 + severity * 2) - 1, 1, severity + 2)
+
+/datum/event/ray_migration/proc/spawn_fish(var/num_groups, var/group_size_min, var/group_size_max, var/dir)
+ if(isnull(dir))
+ dir = (victim && prob(80)) ? victim.fore_dir : pick(GLOB.cardinal)
+
+ // Check if any landmarks exist!
+ var/list/spawn_locations = list()
+ for(var/obj/effect/landmark/C in landmarks_list)
+ if(C.name == "carpspawn" && (C.z in affecting_z))
+ spawn_locations.Add(C.loc)
+ if(spawn_locations.len) // Okay we've got landmarks, lets use those!
+ shuffle_inplace(spawn_locations)
+ num_groups = min(num_groups, spawn_locations.len)
+ for (var/i = 1, i <= num_groups, i++)
+ var/group_size = rand(group_size_min, group_size_max)
+ for (var/j = 0, j < group_size, j++)
+ spawn_one_ray(spawn_locations[i])
+ return
+
+ // Okay we did *not* have any landmarks, so lets do our best!
+ var/i = 1
+ while (i <= num_groups)
+ var/Z = pick(affecting_z)
+ var/group_size = rand(group_size_min, group_size_max)
+ var/turf/map_center = locate(round(world.maxx/2), round(world.maxy/2), Z)
+ var/turf/group_center = pick_random_edge_turf(dir, Z, TRANSITIONEDGE + 2)
+ var/list/turfs = getcircle(group_center, 2)
+ for (var/j = 0, j < group_size, j++)
+ var/mob/living/simple_mob/animal/M = spawn_one_ray(turfs[(i % turfs.len) + 1])
+ // Ray trace towards middle of the map to find where they can stop just outside of structure/ship.
+ var/turf/target
+ for(var/turf/T in getline(get_turf(M), map_center))
+ if(!T.is_space())
+ break;
+ target = T
+ if(target)
+ M.ai_holder?.give_destination(target) // Ask ray to swim towards the middle of the map
+ i++
+
+// Spawn a single ray at given location.
+/datum/event/ray_migration/proc/spawn_one_ray(var/loc)
+ var/mob/living/simple_mob/animal/M = new /mob/living/simple_mob/animal/space/ray(loc)
+ GLOB.destroyed_event.register(M, src, .proc/on_ray_destruction)
+ spawned_ray.Add(M)
+ return M
+
+// Counts living ray spawned by this event.
+/datum/event/ray_migration/proc/count_spawned_rays()
+ . = 0
+ for(var/mob/living/simple_mob/animal/M as anything in spawned_ray)
+ if(!QDELETED(M) && M.stat != DEAD)
+ . += 1
+
+// If ray is bomphed, remove it from the list.
+/datum/event/ray_migration/proc/on_ray_destruction(var/mob/M)
+ spawned_ray -= M
+ GLOB.destroyed_event.unregister(M, src, .proc/on_ray_destruction)
+
+/datum/event/ray_migration/end()
+ . = ..()
+ // Clean up ray that died in space for some reason.
+ spawn(0)
+ for(var/mob/living/simple_mob/SM in spawned_ray)
+ if(SM.stat == DEAD)
+ var/turf/T = get_turf(SM)
+ if(istype(T, /turf/space))
+ if(prob(75))
+ qdel(SM)
+ CHECK_TICK
+
+// Overmap version
+/datum/event/ray_migration/overmap/announce()
+ return
diff --git a/code/modules/events/shark_migration.dm b/code/modules/events/shark_migration.dm
new file mode 100644
index 00000000000..7baed0af9c1
--- /dev/null
+++ b/code/modules/events/shark_migration.dm
@@ -0,0 +1,102 @@
+/datum/event/shark_migration
+ startWhen = 0 // Start immediately
+ announceWhen = 45 // Adjusted by setup
+ endWhen = 75 // Adjusted by setup
+ var/shark_cap = 10
+ var/list/spawned_shark = list()
+
+/datum/event/shark_migration/setup()
+ announceWhen = rand(30, 60) // 1 to 2 minutes
+ endWhen += severity * 25
+ shark_cap = 1 + 1 ** severity // No more than this many at once regardless of waves. (2, 3, ?)
+
+/datum/event/shark_migration/start()
+ affecting_z -= global.using_map.sealed_levels // Space levels only please!
+ ..()
+
+/datum/event/shark_migration/announce()
+ var/announcement = ""
+ if(severity == EVENT_LEVEL_MAJOR)
+ announcement = "Massive migration of unknown biological entities has been detected near [location_name()], please stand-by."
+ else
+ announcement = "Unknown biological [spawned_shark.len == 1 ? "entity has" : "entities have"] been detected near [location_name()], please stand-by."
+ command_announcement.Announce(announcement, "Lifesign Alert")
+
+/datum/event/shark_migration/tick()
+ if(activeFor % 5 != 0)
+ return // Only process every 10 seconds.
+ if(count_spawned_sharks() < shark_cap)
+ spawn_fish(rand(3, 3 + severity * 2) - 1, 1, severity + 2)
+
+/datum/event/shark_migration/proc/spawn_fish(var/num_groups, var/group_size_min, var/group_size_max, var/dir)
+ if(isnull(dir))
+ dir = (victim && prob(80)) ? victim.fore_dir : pick(GLOB.cardinal)
+
+ // Check if any landmarks exist!
+ var/list/spawn_locations = list()
+ for(var/obj/effect/landmark/C in landmarks_list)
+ if(C.name == "carpspawn" && (C.z in affecting_z))
+ spawn_locations.Add(C.loc)
+ if(spawn_locations.len) // Okay we've got landmarks, lets use those!
+ shuffle_inplace(spawn_locations)
+ num_groups = min(num_groups, spawn_locations.len)
+ for (var/i = 1, i <= num_groups, i++)
+ var/group_size = rand(group_size_min, group_size_max)
+ for (var/j = 0, j < group_size, j++)
+ spawn_one_shark(spawn_locations[i])
+ return
+
+ // Okay we did *not* have any landmarks, so lets do our best!
+ var/i = 1
+ while (i <= num_groups)
+ var/Z = pick(affecting_z)
+ var/group_size = rand(group_size_min, group_size_max)
+ var/turf/map_center = locate(round(world.maxx/2), round(world.maxy/2), Z)
+ var/turf/group_center = pick_random_edge_turf(dir, Z, TRANSITIONEDGE + 2)
+ var/list/turfs = getcircle(group_center, 2)
+ for (var/j = 0, j < group_size, j++)
+ var/mob/living/simple_mob/animal/M = spawn_one_shark(turfs[(i % turfs.len) + 1])
+ // Ray trace towards middle of the map to find where they can stop just outside of structure/ship.
+ var/turf/target
+ for(var/turf/T in getline(get_turf(M), map_center))
+ if(!T.is_space())
+ break;
+ target = T
+ if(target)
+ M.ai_holder?.give_destination(target) // Ask shark to swim towards the middle of the map
+ i++
+
+// Spawn a single shark at given location.
+/datum/event/shark_migration/proc/spawn_one_shark(var/loc)
+ var/mob/living/simple_mob/animal/M = new /mob/living/simple_mob/animal/space/shark/event(loc)
+ GLOB.destroyed_event.register(M, src, .proc/on_shark_destruction)
+ spawned_shark.Add(M)
+ return M
+
+// Counts living shark spawned by this event.
+/datum/event/shark_migration/proc/count_spawned_sharks()
+ . = 0
+ for(var/mob/living/simple_mob/animal/M as anything in spawned_shark)
+ if(!QDELETED(M) && M.stat != DEAD)
+ . += 1
+
+// If shark is bomphed, remove it from the list.
+/datum/event/shark_migration/proc/on_shark_destruction(var/mob/M)
+ spawned_shark -= M
+ GLOB.destroyed_event.unregister(M, src, .proc/on_shark_destruction)
+
+/datum/event/shark_migration/end()
+ . = ..()
+ // Clean up shark that died in space for some reason.
+ spawn(0)
+ for(var/mob/living/simple_mob/SM in spawned_shark)
+ if(SM.stat == DEAD)
+ var/turf/T = get_turf(SM)
+ if(istype(T, /turf/space))
+ if(prob(75))
+ qdel(SM)
+ CHECK_TICK
+
+// Overmap version
+/datum/event/shark_migration/overmap/announce()
+ return
diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm
index 8299902b617..0d7f5d906d3 100644
--- a/code/modules/food/food/snacks.dm
+++ b/code/modules/food/food/snacks.dm
@@ -910,6 +910,18 @@
filling_color = "#2c2cff"
color = "#2c2cff"
+/obj/item/weapon/reagent_containers/food/snacks/carpmeat/ray
+ desc = "A fillet of space ray meat."
+ toxin_type = "stoxin"
+
+/obj/item/weapon/reagent_containers/food/snacks/carpmeat/gnat
+ desc = "A paltry sample of space-gnat meat. It looks pretty stringy and unpleasant, honestly."
+ toxin_amount = 1
+
+/obj/item/weapon/reagent_containers/food/snacks/carpmeat/shark
+ desc = "A fillet of space shark meat. It looks rather tough and chewy."
+ toxin_amount = 5
+
/obj/item/weapon/reagent_containers/food/snacks/crab_legs
name = "steamed crab legs"
desc = "Crab legs steamed and buttered to perfection. One day when the boss gets hungry..."
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/gnat.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/gnat.dm
new file mode 100644
index 00000000000..35c77548b19
--- /dev/null
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/gnat.dm
@@ -0,0 +1,57 @@
+// Space carp show up as a random event to wreck hapless people in space or near windows.
+// They generally fit the archetype of 'fast but fragile'.
+// This is compensated by being in groups (usually).
+
+/datum/category_item/catalogue/fauna/gnat
+ name = "Voidborne Fauna - Space Gnat"
+ desc = "Stellar explorers once thought the greatest nuisance was the space carp. \
+
\
+ Regrettably, they were wrong.\
+
\
+ The so-called 'space gnat' is a populous and highly irritating but largely harmless threat \
+ mostly known for how much of a nuisance it poses by flying into various intakes and other \
+ sensitive or delicate starship components. Their small, spherical bodies are very fragile \
+ and possess four stubby wings that serve no apparent purpose, but which the gnats flap furiously \
+ all the same, perhaps in anger at the cruelties of life and the universe.\
+
\
+ Indeed, what kind of god could create such a misbegotten creature? Certainly not a benevolent one."
+ value = CATALOGUER_REWARD_EASY
+
+/mob/living/simple_mob/animal/space/gnat
+ name = "space gnat"
+ desc = "A small, wretched interstellar pest. Whilst little danger by themselves, they can be a problem in large numbers."
+ catalogue_data = list(/datum/category_item/catalogue/fauna/gnat)
+ icon = 'icons/mob/mobs_monsters/animal.dmi'
+ icon_state = "gnat"
+ icon_living = "gnat"
+ icon_dead = "gnat_dead"
+
+ faction = "gnat"
+ maxHealth = 5
+ health = 5
+ movement_cooldown = 0
+ hovering = TRUE
+
+ response_help = "baps the"
+ response_disarm = "gently pushes aside the"
+ response_harm = "hits the"
+
+ melee_damage_lower = 2
+ melee_damage_upper = 3 //they do very little damage but attack fairly fast, like organic viscerators
+ base_attack_cooldown = 10 // Bitey bitey!
+ attack_sharp = TRUE
+ attack_sound = 'sound/weapons/bite.ogg'
+ attacktext = list("nibbled")
+
+ organ_names = /decl/mob_organ_names/fish
+
+ meat_amount = 1
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat/gnat
+
+ ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive/jellyfish
+ mob_bump_flag = 0
+
+ organ_names = /decl/mob_organ_names/space_gnat
+
+/decl/mob_organ_names/space_gnat
+ hit_zones = list("cephalothorax", "stubby winglets", "flailing tail")
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm
new file mode 100644
index 00000000000..18eace68b5c
--- /dev/null
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm
@@ -0,0 +1,78 @@
+// Space carp show up as a random event to wreck hapless people in space or near windows.
+// They generally fit the archetype of 'fast but fragile'.
+// This is compensated by being in groups (usually).
+
+/datum/category_item/catalogue/fauna/ray
+ name = "Voidborne Fauna - Space Ray"
+ desc = "Believed to be a distant relative of the more numerous 'space carp' \
+ the 'space ray' is a somewhat horrifying-looking creature with a maw of sharp fangs \
+ and several vicious-looking bony protrusions.\
+
\
+ In truth, however, they are largely harmless creatures, being content to drift \
+ upon the solar winds. They seem to feed off a mix of interstellar gases, solar radiation, \
+ space dust, and occasionally other detritus. There are no known cases of unprovoked attacks. \
+ More baffling is their ability to fly within gravity fields, as they do not seem to move about \
+ in the same way that carp do, instead seeming to drift on invisible field currents. \
+
\
+ Scientists have found several shared genetic markers between both the 'ray' and 'carp', \
+ but at this time have little direct evidence of any relationship between these species. \
+ There are many competing theories, and few of them can agree on anything but the broadest \
+ strokes. Oh, and that their tissues contain considerable amounts of soporifics. That too. \
+
\
+ What scientists can agree on, however, is that whilst the 'space ray' may look nasty \
+ they're generally little threat. Astroxenobiologists have noted that the two species do \
+ seem to get along quite poorly, and that the rays are quite capable of dispatching their \
+ supposed cousins, even when outnumbered."
+ value = CATALOGUER_REWARD_EASY
+
+/mob/living/simple_mob/animal/space/ray
+ name = "space ray"
+ desc = "A horrifying-looking but ultimately misunderstood creature that poses little actual threat."
+ catalogue_data = list(/datum/category_item/catalogue/fauna/ray)
+ icon = 'icons/mob/mobs_monsters/animal.dmi'
+ icon_state = "ray"
+ icon_living = "ray"
+ icon_dead = "ray_dead"
+ icon_rest = "ray_rest"
+ icon_gib = "ray_gib"
+
+ faction = "ray"
+ maxHealth = 125
+ health = 125
+ movement_cooldown = 0 // Carp go fast
+ hovering = TRUE
+
+ response_help = "strokes the"
+ response_disarm = "gently pushes aside the"
+ response_harm = "hits the"
+
+ melee_damage_lower = 5
+ melee_damage_upper = 10 //minor damage variance, since they should only be fighting carp
+ base_attack_cooldown = 18 // A bit slower than carp
+ attack_sharp = TRUE
+ attack_sound = 'sound/weapons/bite.ogg'
+ attacktext = list("lanced","bitten","impaled","gored")
+
+ organ_names = /decl/mob_organ_names/fish
+
+ meat_amount = 5
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat/ray
+
+ ai_holder_type = /datum/ai_holder/simple_mob/retaliate/chill
+ mob_bump_flag = 0
+
+ say_list_type = /datum/say_list/space_ray
+
+ var/knockdown_chance = 66
+
+/mob/living/simple_mob/animal/space/ray/apply_melee_effects(var/atom/A)
+ if(isliving(A))
+ var/mob/living/L = A
+ if(prob(knockdown_chance))
+ L.Weaken(4)
+ L.visible_message(span("danger", "\The [src] buffets \the [L]!"))
+ src.ai_holder.remove_target()
+ L.visible_message(span("notice", "\The [src] seems to lose interest in \the [L]..."))
+
+/datum/say_list/space_ray
+ emote_see = list("swoops","dives","drifts on a solar current","glides elegantly through the void","briefly tumbles")
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/shark.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/shark.dm
new file mode 100644
index 00000000000..466df2905d8
--- /dev/null
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/shark.dm
@@ -0,0 +1,56 @@
+// Space carp show up as a random event to wreck hapless people in space or near windows.
+// They generally fit the archetype of 'fast but fragile'.
+// This is compensated by being in groups (usually).
+
+/datum/category_item/catalogue/fauna/shark
+ name = "Voidborne Fauna - Space Shark"
+ desc = "The space carp's bigger, highly territorial kin, space sharks are bigger, meaner, \
+ and generally bad news to be around for extended periods. If you see one, hope that it's \
+ the only one around, because if it isn't then that means it's probably a parent with their pups. "
+ value = CATALOGUER_REWARD_HARD
+
+/mob/living/simple_mob/animal/space/shark
+ name = "space shark"
+ desc = "A regal and imposing interstellar creature, and one that poses a serious threat to the ill-prepared."
+ catalogue_data = list(/datum/category_item/catalogue/fauna/shark)
+ icon = 'icons/mob/mobs_monsters/animal.dmi'
+ icon_state = "shark"
+ icon_living = "shark"
+ icon_dead = "shark_dead"
+ icon_rest = "shark_rest"
+
+ faction = "spaceshark"
+ maxHealth = 125
+ health = 125
+ movement_cooldown = 0
+ hovering = TRUE
+
+ response_help = "strokes the"
+ response_disarm = "casually rotates the"
+ response_harm = "hits the"
+
+ melee_damage_lower = 15
+ melee_damage_upper = 30 //don't mess with these critters!
+ base_attack_cooldown = 22 // Quite slow, given their power
+ attack_sharp = TRUE
+ attack_sound = 'sound/weapons/bite.ogg'
+ attacktext = list("lanced","bitten","impaled","gored")
+
+ organ_names = /decl/mob_organ_names/fish
+
+ meat_amount = 10
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat/shark
+
+ ai_holder_type = /datum/ai_holder/simple_mob/melee
+
+ var/knockdown_chance = 10 //slightly reduced their knockdown prob compared to carp given their greater power
+
+/mob/living/simple_mob/animal/space/shark/apply_melee_effects(var/atom/A)
+ if(isliving(A))
+ var/mob/living/L = A
+ if(prob(knockdown_chance))
+ L.Weaken(3)
+ L.visible_message(span("danger", "\The [src] knocks down \the [L]!"))
+
+/mob/living/simple_mob/animal/space/shark/event
+ ai_holder_type = /datum/ai_holder/simple_mob/event
\ No newline at end of file
diff --git a/icons/mob/mobs_monsters/animal.dmi b/icons/mob/mobs_monsters/animal.dmi
new file mode 100644
index 00000000000..38469f718f5
Binary files /dev/null and b/icons/mob/mobs_monsters/animal.dmi differ
diff --git a/maps/groundbase/groundbase_events.dm b/maps/groundbase/groundbase_events.dm
index 265e1faad36..e6d43a25fd9 100644
--- a/maps/groundbase/groundbase_events.dm
+++ b/maps/groundbase/groundbase_events.dm
@@ -41,7 +41,7 @@
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Lore News", /datum/event/lore_news, 400),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 50, list(ASSIGNMENT_JANITOR = 25), 1),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30), 1, min_jobs = list(ASSIGNMENT_ENGINEER = 1)),
- new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Passing Wildlife", /datum/event/roaming_wildlife, 40, list(ASSIGNMENT_SECURITY = 20), min_jobs = list(ASSIGNMENT_SECURITY = 1))
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Passing Wildlife", /datum/event/roaming_wildlife, 40, list(ASSIGNMENT_SECURITY = 20), min_jobs = list(ASSIGNMENT_SECURITY = 1)),
)
add_disabled_events(list(
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Ian Storm", /datum/event/ianstorm, 1, list(), 1),
@@ -49,6 +49,9 @@
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Aurora Caelus", /datum/event/aurora_caelus, 2, list(), 1),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Space Dust", /datum/event/dust, 0, list(ASSIGNMENT_ENGINEER = 20), 0, 0, 50, min_jobs = list(ASSIGNMENT_ENGINEER = 2)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Lost Carp", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Stray Ray", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Stray Shark", /datum/event/shark_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Gnat Mob", /datum/event/gnat_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
))
/datum/event_container/moderate/New()
@@ -67,7 +70,7 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Drone Pod Drop", /datum/event/drone_pod_drop, 40, list(ASSIGNMENT_SCIENTIST = 40), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/morph_spawn, 75, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 100, list(ASSIGNMENT_ANY = 5), 0),
- new /datum/event_meta(EVENT_LEVEL_MODERATE, "Roaming Wildlife", /datum/event/roaming_wildlife, 20, list(ASSIGNMENT_SECURITY = 20, ASSIGNMENT_MEDICAL = 5), min_jobs = list(ASSIGNMENT_SECURITY = 2))
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Roaming Wildlife", /datum/event/roaming_wildlife, 20, list(ASSIGNMENT_SECURITY = 20, ASSIGNMENT_MEDICAL = 5), min_jobs = list(ASSIGNMENT_SECURITY = 2)),
)
add_disabled_events(list(
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 30), 1),
@@ -81,6 +84,9 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 30), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 0, list(ASSIGNMENT_SECURITY = 20), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Jellyfish School", /datum/event/jellyfish_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Stray Rays", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Shark Pack", /datum/event/shark_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gnat Swarm", /datum/event/gnat_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
))
/datum/event_container/major/New()
@@ -89,7 +95,7 @@
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Atmos Leak", /datum/event/atmos_leak, 20, list(ASSIGNMENT_ENGINEER = 25), 1, min_jobs = list(ASSIGNMENT_ENGINEER = 1)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Space Vines", /datum/event/spacevine, 10, list(ASSIGNMENT_ENGINEER = 3, ASSIGNMENT_GARDENER = 3, ASSIGNMENT_SCIENTIST = 3), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ENGINEER = 5, ASSIGNMENT_MEDICAL = 5, ASSIGNMENT_SECURITY = 5, ASSIGNMENT_SCIENTIST = 5), 1),
- new /datum/event_meta(EVENT_LEVEL_MAJOR, "Amassing Wildlife", /datum/event/roaming_wildlife, 0, list(ASSIGNMENT_SECURITY = 10, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3))
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Amassing Wildlife", /datum/event/roaming_wildlife, 0, list(ASSIGNMENT_SECURITY = 10, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
)
add_disabled_events(list(
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Strike", /datum/event/meteor_strike, 10, list(ASSIGNMENT_ENGINEER = 15), 1),
@@ -98,6 +104,9 @@
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Supply Demand", /datum/event/supply_demand, 0, list(ASSIGNMENT_ANY = 5, ASSIGNMENT_SCIENCE = 15, ASSIGNMENT_GARDENER = 10, ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_MEDICAL = 15), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Jellyfish Migration", /datum/event/jellyfish_migration, 5, list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 10, list(ASSIGNMENT_SECURITY = 5), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Stray Rays", /datum/event/ray_migration, 20, list(ASSIGNMENT_SECURITY = 20, ASSIGNMENT_MEDICAL = 5), min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Shark Pack", /datum/event/shark_migration, 20, list(ASSIGNMENT_SECURITY = 20, ASSIGNMENT_MEDICAL = 5), min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Gnat Swarm", /datum/event/gnat_migration, 20, list(ASSIGNMENT_SECURITY = 20, ASSIGNMENT_MEDICAL = 5), min_jobs = list(ASSIGNMENT_SECURITY = 2)),
))
#undef ASSIGNMENT_ANY
diff --git a/maps/stellar_delight/stellar_delight_events.dm b/maps/stellar_delight/stellar_delight_events.dm
index d1a4de83b4f..2f95fb5d12b 100644
--- a/maps/stellar_delight/stellar_delight_events.dm
+++ b/maps/stellar_delight/stellar_delight_events.dm
@@ -37,6 +37,8 @@
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Space Dust", /datum/event/dust, 0, list(ASSIGNMENT_ENGINEER = 20), 0, 0, 50, min_jobs = list(ASSIGNMENT_ENGINEER = 2)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Economic News", /datum/event/economic_event, 300),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Lost Carp", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Stray Ray", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Gnat Cloud", /datum/event/gnat_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Hacker", /datum/event/money_hacker, 0, list(ASSIGNMENT_ANY = 4), 1, 10, 25),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Lotto", /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 1, 5, 15),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Shipping Error", /datum/event/shipping_error , 30, list(ASSIGNMENT_ANY = 2), 0),
@@ -84,6 +86,9 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/morph_spawn, 75, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 100, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Jellyfish School", /datum/event/jellyfish_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 5), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gliding Rays", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 5), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Shark Pack", /datum/event/shark_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gnat Swarm", /datum/event/gnat_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
)
add_disabled_events(list(
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 30), 1),
@@ -102,6 +107,9 @@
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 10, list(ASSIGNMENT_SECURITY = 5), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ENGINEER = 5, ASSIGNMENT_MEDICAL = 5, ASSIGNMENT_SECURITY = 5, ASSIGNMENT_SCIENTIST = 5), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Jellyfish Migration", /datum/event/jellyfish_migration, 5, list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Gliding Rays", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 5), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Shark Pack", /datum/event/shark_migration, 5, list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Gnat Swarm", /datum/event/gnat_migration, 5, list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
)
add_disabled_events(list(
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Strike", /datum/event/meteor_strike, 10, list(ASSIGNMENT_ENGINEER = 15), 1),
diff --git a/maps/tether/tether_events.dm b/maps/tether/tether_events.dm
index b6dc85c1e0d..32971312b18 100644
--- a/maps/tether/tether_events.dm
+++ b/maps/tether/tether_events.dm
@@ -37,6 +37,8 @@
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Space Dust", /datum/event/dust, 0, list(ASSIGNMENT_ENGINEER = 20), 0, 0, 50, min_jobs = list(ASSIGNMENT_ENGINEER = 2)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Economic News", /datum/event/economic_event, 300),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Lost Carp", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Stray Ray", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Gnat Cloud", /datum/event/gnat_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Hacker", /datum/event/money_hacker, 0, list(ASSIGNMENT_ANY = 4), 1, 10, 25),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Lotto", /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 1, 5, 15),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Shipping Error", /datum/event/shipping_error , 30, list(ASSIGNMENT_ANY = 2), 0),
@@ -84,6 +86,9 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/morph_spawn, 75, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 100, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Jellyfish School", /datum/event/jellyfish_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gliding Rays", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 5), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Shark Pack", /datum/event/shark_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gnat Swarm", /datum/event/gnat_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
)
add_disabled_events(list(
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 30), 1),
@@ -102,6 +107,9 @@
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 10, list(ASSIGNMENT_SECURITY = 5), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ENGINEER = 5, ASSIGNMENT_MEDICAL = 5, ASSIGNMENT_SECURITY = 5, ASSIGNMENT_SCIENTIST = 5), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Jellyfish Migration", /datum/event/jellyfish_migration, 5, list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Gliding Rays", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 5), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Shark Pack", /datum/event/shark_migration, 5, list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
+ new /datum/event_meta(EVENT_LEVEL_MAJOR, "Gnat Swarm", /datum/event/gnat_migration, 5, list(ASSIGNMENT_SECURITY = 5, ASSIGNMENT_MEDICAL = 3), 1, min_jobs = list(ASSIGNMENT_SECURITY = 2)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Strike", /datum/event/meteor_strike, 10, list(ASSIGNMENT_ENGINEER = 15), 1),
)
add_disabled_events(list(
diff --git a/vorestation.dme b/vorestation.dme
index fd67cf0453f..de9ffa7c566 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2235,6 +2235,7 @@
#include "code\modules\events\event_container.dm"
#include "code\modules\events\event_dynamic.dm"
#include "code\modules\events\event_manager.dm"
+#include "code\modules\events\gnat_migration.dm"
#include "code\modules\events\gravity.dm"
#include "code\modules\events\grid_check.dm"
#include "code\modules\events\grubinfestation_vr.dm"
@@ -2252,8 +2253,10 @@
#include "code\modules\events\prison_break.dm"
#include "code\modules\events\radiation_storm.dm"
#include "code\modules\events\random_antagonist.dm"
+#include "code\modules\events\ray_migration.dm"
#include "code\modules\events\roaming_wildlife.dm"
#include "code\modules\events\rogue_drones.dm"
+#include "code\modules\events\shark_migration.dm"
#include "code\modules\events\shipping_error.dm"
#include "code\modules\events\solar_storm.dm"
#include "code\modules\events\space_ninja.dm"
@@ -3098,8 +3101,11 @@
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\carp.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\carp_vr.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\gaslamp_vr.dm"
+#include "code\modules\mob\living\simple_mob\subtypes\animal\space\gnat.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\goose.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\goose_vr.dm"
+#include "code\modules\mob\living\simple_mob\subtypes\animal\space\ray.dm"
+#include "code\modules\mob\living\simple_mob\subtypes\animal\space\shark.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\snake_vr.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\space.dm"
#include "code\modules\mob\living\simple_mob\subtypes\animal\space\space_vr.dm"