The Blood Of Psirens On My Hands I Cant Wash Away (#22740)

SURPRISE! I hope you all had fun during the Psilence event! It was
really fun spending 6 months coding all the infrastructure I required to
make that encounter possible. Encountering an entire new enemy type was
no doubt incredibly exciting to happen during a big canon round. Well as
promised, these critters will start showing up more often now that the
big reveal has occured.

<img width="982" height="981" alt="image"
src="https://github.com/user-attachments/assets/c537afe6-9b97-4913-8572-85650556b871"
/>

<img width="979" height="981" alt="image"
src="https://github.com/user-attachments/assets/1049b564-eb54-45e8-a113-da48f5c4b67b"
/>

This PR adds new rare random events and overmap hazards for Psirens,
allowing the basic varieties of them to appear in normal gameplay. They
can also be summoned by technomancers. More to come later. :)
This commit is contained in:
VMSolidus
2026-07-14 10:39:19 +00:00
committed by GitHub
parent 8c2d57e534
commit b61adb6ea2
6 changed files with 119 additions and 1 deletions
+6
View File
@@ -335,6 +335,9 @@ GLOBAL_LIST_INIT(severity_to_string, alist(EVENT_LEVEL_MUNDANE = "Mundane", EVEN
new /datum/event_meta(EVENT_LEVEL_MODERATE, "APC Damage", /datum/event/apc_damage,
20, list(ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_JANITOR = 20)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Wandering Psirens", /datum/event/wandering_psirens,
10, list(ASSIGNMENT_SECURITY = 15)),
)
// Severity Level, Event Name, Event Type, Base Weight, Role Weight(s), One Shot (TRUE/FALSE), Min Weight, Max Weight. Last two only used if set and non-zero.
@@ -388,6 +391,9 @@ GLOBAL_LIST_INIT(severity_to_string, alist(EVENT_LEVEL_MUNDANE = "Mundane", EVEN
35, list(ASSIGNMENT_ENGINEER = 20), is_one_shot = TRUE,
pop_needed = 12),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Wandering Psiren School", /datum/event/wandering_psirens,
10, list(ASSIGNMENT_SECURITY = 15, ASSIGNMENT_MEDICAL = 5)),
)
#undef ASSIGNMENT_ANY
+75
View File
@@ -0,0 +1,75 @@
/// Wandering Psirens, an event similar enough to Carp Migration that I can reuse much of the code.
/datum/event/wandering_psirens
announceWhen = 50
endWhen = 900
var/list/spawned_psirens = list()
var/list/despawn_turfs = list(
/turf/space,
/turf/simulated/floor/exoplanet/asteroid,
/turf/simulated/open,
/turf/simulated/floor/reinforced/airless // Station roof.
)
/datum/event/wandering_psirens/setup()
announceWhen = rand(40, 60)
endWhen = rand(600, 1200)
despawn_turfs = typecacheof(despawn_turfs)
/datum/event/wandering_psirens/announce()
// Pings every "Psi-sensitive", will trigger feedback on people's mindshields.
for (var/mob/victim in GLOB.player_list)
if (SShallucinations.is_adpi_excluded(victim) || SShallucinations.is_adpi_blocked(victim))
continue
SShallucinations.send_adpi_message(victim, null, FALSE)
/datum/event/wandering_psirens/start()
..()
if(severity == EVENT_LEVEL_MAJOR)
spawn_psirens(length(GLOB.landmarks_list))
else if(severity == EVENT_LEVEL_MODERATE)
spawn_psirens(rand(4, 6)) //12 to 30 psirens
else
spawn_psirens(rand(1, 3), 1, 2) //1 to 6 psirens, alone or in pairs
/datum/event/wandering_psirens/proc/spawn_psirens(num_groups, group_size_min = 3, group_size_max = 5)
set waitfor = FALSE
var/list/spawn_locations = list()
for(var/obj/effect/landmark/C in GLOB.landmarks_list)
if(C.name == "carpspawn") // Reusing the carp landmarks. :)
spawn_locations.Add(C.loc)
spawn_locations = shuffle(spawn_locations)
num_groups = min(num_groups, spawn_locations.len)
var/i = 1
while (i <= num_groups)
var/group_size = rand(group_size_min, group_size_max)
for(var/j = 1, j <= group_size, j++)
if(prob(95))
var/basic_psiren
if (prob(50))
basic_psiren = new /mob/living/simple_animal/hostile/psiren(spawn_locations[i])
else basic_psiren = new /mob/living/simple_animal/hostile/psiren/ranged(spawn_locations[i])
spawned_psirens += WEAKREF(basic_psiren)
else
var/mob/living/simple_animal/hostile/psiren/omen/new_omen = new(spawn_locations[i])
spawned_psirens += WEAKREF(new_omen)
CHECK_TICK
i++
/datum/event/wandering_psirens/end(faked)
..()
for (var/datum/weakref/psiren_weakref in spawned_psirens)
var/mob/living/simple_animal/hostile/psiren/psiren = psiren_weakref.resolve()
if (psiren && prob(50) && is_type_in_typecache(psiren.loc, despawn_turfs))
spawned_psirens -= psiren_weakref
qdel(psiren_weakref)
spawned_psirens?.Cut()
/datum/event/wandering_psirens/overmap
despawn_turfs = list(/turf/space)
+28
View File
@@ -328,6 +328,20 @@
can_be_destroyed = FALSE
tooltip_text = "Unstable gravitic shear effects detected; wide-field artificial gravity should be powered down before transit."
/obj/effect/overmap/event/psiren
name = "psiren shoal"
events = list(/datum/event/wandering_psirens/overmap)
difficulty = EVENT_LEVEL_MODERATE
event_icon_states = list("carp")
movable_event_chance = 30
tooltip_text = "Xenofauna: usually hostile."
/obj/effect/overmap/event/psiren/major
name = "psiren school"
opacity = 1
difficulty = EVENT_LEVEL_MAJOR
movable_event_chance = 15
/obj/effect/overmap/event/MouseEntered(location, control, params)
. = ..()
openToolTip(usr, src, params, tooltip_text)
@@ -402,3 +416,17 @@
radius = 12
hazards = /obj/effect/overmap/event/gravity_anomaly
sectors = list(SECTOR_LEMURIAN_SEA, SECTOR_LEMURIAN_SEA_FAR)
/datum/overmap_event/psiren
name = "psiren shoal"
count = 3
radius = 1
continuous = FALSE
hazards = /obj/effect/overmap/event/psiren
/datum/overmap_event/psiren/major
name = "psiren school"
count = 2
radius = 2
opacity = 1
hazards = /obj/effect/overmap/event/psiren/major