Storyteller Narration Filters (#21767)

This PR adds a feature requested of me by @Fyniiy , adding optional
Filters to the Narrate panel that allow Storytellers to narrate only to
people that meet a set condition. The conditions themselves were
specifically requested to be "Psi Narrates" and "Synth Narrates", with
optional variations on Synth narrates that include people with cranial
implants. While I was touching these files, I've also fixed the improper
message sanitization bug with admin messages in general.

<img width="926" height="536" alt="image"
src="https://github.com/user-attachments/assets/08dcfd2a-5399-48b0-a13d-2bfd3a2c88f0"
/>

Here's a breakdown of the filter options.

1. **Skrell-like Psi-sensitives**: Anyone with a Psi-sensitivity score
of "At least 1". This will include Skrell, anyone with a Psi-receiver,
and people with the High Psi-sensitivity trait. It will exclude people
who are blocked from receiving telepathy for any reason, such as having
a mindshield, mindblanker, or having the psi-suppression power active.
Skrell with the Low Psi-sensitivity trait are counted as "Human-like
Psi-sensitives", and so won't be caught by this filter.
2. **Human-like Psi-sensitives**: Anyone who isn't blocked from
receiving telepathy, and also has a Psi-sensitivity score of "At least
0". This will basically catch "Most people who aren't a Vaurca,
Synthetic, or Diona". It will ignore Humanoids with the Low
Psi-sensitivity trait.
3. **Silicons**: Basically all of the possible robots/IPCs.
4. **Silicons + Implants**: It's fairly common practice during Hivebot
related events for Storytellers to also include characters with brain
implants. This filter automates that by including said brain implant
owners in the "Are you a synthetic?" check.
5. **Hivenet**: Pretty simple, people with the Vaurca language. This
would be Vaurca, plus anyone with the hivenet implants.
This commit is contained in:
VMSolidus
2026-02-02 15:40:30 +00:00
committed by GitHub
parent d0f44e1a14
commit cc0a809b4c
7 changed files with 130 additions and 4 deletions
@@ -8,6 +8,7 @@
var/list/data = list()
data["narrate_styles"] = list("danger", "notice", "warning", "alien", "cult")
data["narrate_locations"] = list("View", "Range", "Z-Level", "Global")
data["narrate_filters"] = list("None", "Skrell-like Psi-sensitives", "Human-like Psi-sensitives", "Silicons", "Silicons + Implants", "Hivenet")
return data
/datum/tgui_module/narrate_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
@@ -63,5 +64,65 @@
if("Global")
mobs_to_message = GLOB.player_list.Copy()
// Skip the switch if no filter was selected.
if (params["narrate_filter"] == "None")
for(var/mob/actor in mobs_to_message)
to_chat(actor, "<font size=[narrate_size]><span class='[narrate_style]'>[narrate_text]</span></font>")
return
// Create a copy of the message receivers. We have to iterate the copy of the list in order to safely remove entries from the list of message receivers.
// Otherwise we'll get memory exceptions.
var/list/filtered_list = mobs_to_message.Copy()
var/narrate_filter = params["narrate_filter"]
switch(narrate_filter)
if ("Skrell-like Psi-sensitives")
for(var/mob/filteree in filtered_list)
// This will check for anyone who is capable of receiving and interpreting telepathic messages.
// It will include Skrell who don't have a mindshield or the Low Psi-sensitivity trait.
// It will also include characters who have Psi-receivers, the High Psi-sensitivity trait, or are under the effects of Psycho-nootropic drugs.
if (IS_TELEPATHY_BLOCKED(filteree, PSI_RANK_SENSITIVE))
mobs_to_message.Remove(filteree)
continue
if ("Human-like Psi-sensitives")
for(var/mob/filteree in filtered_list)
// This will check for anyone who has a Zona Bovina capable of hearing psionics at all.
if (IS_TELEPATHY_BLOCKED(filteree, 0))
mobs_to_message.Remove(filteree)
continue
if ("Silicons")
for(var/mob/filteree in filtered_list)
// List will include Borgs, Robots, Shipbounds, pAIs, and IPCs.
if(issilicon(filteree) || isipc(filteree) || ispAI(filteree))
continue
// Remove anyone not made of silicon.
mobs_to_message.Remove(filteree)
if ("Silicons + Implants")
for(var/mob/filteree in filtered_list)
// List will include Borgs, Robots, Shipbounds, pAIs, and IPCs.
if(issilicon(filteree) || isipc(filteree) || ispAI(filteree))
continue
if (!ishuman(filteree))
// The mob in question can't have a brain at all, filter it early.
mobs_to_message.Remove(filteree)
continue
var/mob/living/carbon/human/brain_haver = filteree
// Check for silicon brain implants.
var/obj/item/organ/internal/brain = brain_haver.internal_organs_by_name[BP_BRAIN]
if (brain && ((brain.status & ORGAN_ASSISTED) || (brain.status & ORGAN_ROBOT)))
continue
// Remove anyone not made of silicon or doesn't have a cranial implant.
mobs_to_message.Remove(filteree)
if ("Hivenet")
for(var/mob/filteree in filtered_list)
// Filter anyone who doesn't have the Vaurca language at all.
if (!(GLOB.all_languages[LANGUAGE_VAURCA] in filteree.languages))
mobs_to_message.Remove(filteree)
continue
for(var/mob/actor in mobs_to_message)
to_chat(actor, "<font size=[narrate_size]><span class='[narrate_style]'>[narrate_text]</span></font>")