From f715fa769b1a5f7ef2092cc3bd0173eeb5def9d7 Mon Sep 17 00:00:00 2001 From: Killian <49700375+KillianKirilenko@users.noreply.github.com> Date: Fri, 31 Mar 2023 06:37:36 +0100 Subject: [PATCH 1/6] more space creature events --- .../ai/ai_holder_subtypes/simple_mob_ai.dm | 3 + code/modules/events/gnat_migration.dm | 102 ++++++++++++++++++ code/modules/events/ray_migration.dm | 102 ++++++++++++++++++ code/modules/events/shark_migration.dm | 102 ++++++++++++++++++ code/modules/food/food/snacks.dm | 12 +++ .../simple_mob/subtypes/animal/space/gnat.dm | 57 ++++++++++ .../simple_mob/subtypes/animal/space/ray.dm | 67 ++++++++++++ .../simple_mob/subtypes/animal/space/shark.dm | 56 ++++++++++ icons/mob/mobs_monsters/animal.dmi | Bin 0 -> 30948 bytes maps/groundbase/groundbase_events.dm | 3 + .../stellar_delight/stellar_delight_events.dm | 8 ++ maps/tether/tether_events.dm | 8 ++ vorestation.dme | 6 ++ 13 files changed, 526 insertions(+) create mode 100644 code/modules/events/gnat_migration.dm create mode 100644 code/modules/events/ray_migration.dm create mode 100644 code/modules/events/shark_migration.dm create mode 100644 code/modules/mob/living/simple_mob/subtypes/animal/space/gnat.dm create mode 100644 code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm create mode 100644 code/modules/mob/living/simple_mob/subtypes/animal/space/shark.dm create mode 100644 icons/mob/mobs_monsters/animal.dmi 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..18ba1716012 --- /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 = 6 // 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..4e266de79a5 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm @@ -0,0 +1,67 @@ +// 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 = 10 + melee_damage_upper = 15 //minor damage variance, since they should only be fighting carp + base_attack_cooldown = 13 // 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 + +/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..291e318d423 --- /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, " + 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 = 18 // 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 0000000000000000000000000000000000000000..38469f718f5c0896100a217767ab3fa318133b81 GIT binary patch literal 30948 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 Date: Fri, 31 Mar 2023 06:53:36 +0100 Subject: [PATCH 2/6] Update shark.dm --- .../mob/living/simple_mob/subtypes/animal/space/shark.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 291e318d423..f1a1d3007eb 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/space/shark.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/shark.dm @@ -11,7 +11,7 @@ /mob/living/simple_mob/animal/space/shark name = "space shark" - desc = "A regal and imposing interstellar creature, " + 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" From 01fe7dcdf40baefe8eacbfed9f7614be569ce61f Mon Sep 17 00:00:00 2001 From: Killian <49700375+KillianKirilenko@users.noreply.github.com> Date: Fri, 31 Mar 2023 06:58:33 +0100 Subject: [PATCH 3/6] Update groundbase_events.dm --- maps/groundbase/groundbase_events.dm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/maps/groundbase/groundbase_events.dm b/maps/groundbase/groundbase_events.dm index 3904dce9b79..11d1d05d3d3 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)), 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)), ) add_disabled_events(list( @@ -68,8 +68,8 @@ 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, "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_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, "Stray Rays", /datum/event/ray_migration, 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), @@ -91,8 +91,8 @@ 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, "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, "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, "Stray Rays", /datum/event/ray_migration, 20, list(ASSIGNMENT_SECURITY = 20, ASSIGNMENT_MEDICAL = 5), 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), From 77d255faed0e162fd747b61939f9f18bef094716 Mon Sep 17 00:00:00 2001 From: Killian <49700375+KillianKirilenko@users.noreply.github.com> Date: Fri, 31 Mar 2023 18:38:09 +0100 Subject: [PATCH 4/6] Update groundbase_events.dm --- maps/groundbase/groundbase_events.dm | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/maps/groundbase/groundbase_events.dm b/maps/groundbase/groundbase_events.dm index 11d1d05d3d3..e6d43a25fd9 100644 --- a/maps/groundbase/groundbase_events.dm +++ b/maps/groundbase/groundbase_events.dm @@ -42,7 +42,6 @@ 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, "Stray Ray", /datum/event/ray_migration, 0, list(ASSIGNMENT_SECURITY = 10), 1, min_jobs = list(ASSIGNMENT_SECURITY = 3)), ) add_disabled_events(list( new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Ian Storm", /datum/event/ianstorm, 1, list(), 1), @@ -50,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() @@ -69,7 +71,6 @@ 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, "Stray Rays", /datum/event/ray_migration, 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), @@ -83,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() @@ -92,7 +96,6 @@ 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, "Stray Rays", /datum/event/ray_migration, 20, list(ASSIGNMENT_SECURITY = 20, ASSIGNMENT_MEDICAL = 5), 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), @@ -101,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 From 0083237846d49f7e12c73026e95972ba7ba0f067 Mon Sep 17 00:00:00 2001 From: Killian <49700375+KillianKirilenko@users.noreply.github.com> Date: Sun, 2 Apr 2023 18:20:42 +0100 Subject: [PATCH 5/6] tuned attacks made attack speed slower for all three, reduced attack damage for rays, gave rays a 66% chance to knock their enemies prone and made them lose interest in attackers --- .../simple_mob/subtypes/animal/space/gnat.dm | 2 +- .../simple_mob/subtypes/animal/space/ray.dm | 16 +++++++++++++--- .../simple_mob/subtypes/animal/space/shark.dm | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) 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 index 18ba1716012..35c77548b19 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/space/gnat.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/gnat.dm @@ -38,7 +38,7 @@ melee_damage_lower = 2 melee_damage_upper = 3 //they do very little damage but attack fairly fast, like organic viscerators - base_attack_cooldown = 6 // Bitey bitey! + base_attack_cooldown = 10 // Bitey bitey! attack_sharp = TRUE attack_sound = 'sound/weapons/bite.ogg' attacktext = list("nibbled") 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 index 4e266de79a5..fec92cd2e52 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm @@ -46,9 +46,9 @@ response_disarm = "gently pushes aside the" response_harm = "hits the" - melee_damage_lower = 10 - melee_damage_upper = 15 //minor damage variance, since they should only be fighting carp - base_attack_cooldown = 13 // A bit slower than carp + 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") @@ -63,5 +63,15 @@ 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() + /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 index f1a1d3007eb..466df2905d8 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/space/shark.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/shark.dm @@ -31,7 +31,7 @@ melee_damage_lower = 15 melee_damage_upper = 30 //don't mess with these critters! - base_attack_cooldown = 18 // Quite slow, given their power + base_attack_cooldown = 22 // Quite slow, given their power attack_sharp = TRUE attack_sound = 'sound/weapons/bite.ogg' attacktext = list("lanced","bitten","impaled","gored") From 3e6877e92175c9fb68a2d17fcdcecc442c47d965 Mon Sep 17 00:00:00 2001 From: Killian <49700375+KillianKirilenko@users.noreply.github.com> Date: Sun, 2 Apr 2023 18:22:55 +0100 Subject: [PATCH 6/6] Update ray.dm --- code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm | 1 + 1 file changed, 1 insertion(+) 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 index fec92cd2e52..18eace68b5c 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/ray.dm @@ -72,6 +72,7 @@ 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")