From 45a59804439cf9efdb0b0279fe53ca9eedf281e3 Mon Sep 17 00:00:00 2001
From: Jinshee <96621959+Jinshee@users.noreply.github.com>
Date: Wed, 13 May 2026 18:07:32 -0700
Subject: [PATCH] Tele-Port: Ports Telepathy changes from NovaSector (#5531)
## About The Pull Request
This ports changes from
https://github.com/NovaSector/NovaSector/pull/6016 and
https://github.com/NovaSector/NovaSector/pull/6398.
- The quirk no longer automatically applies the Genetics power to the
quirk user. Prior to this PR, communication was mostly anonymized and
only _not_ so when one possessed the gene. This presented a clear
downgrade for individuals who had the genetic variant over the quirk
variant. With this PR, communication through the quirk is not anonymous,
but adding the gene on top of the quirk will allow a user to upgrade it
into being anonymous.
- Every time someone uses the quirk everyone else (in sight) will see
where their attention is sent. This does not add a visual cue besides
the warning in the chat, so it's still somewhat discrete.
- Added a new quirk, Psionic Dampener. This blocks most forms of
telepathic communication.
- Telepathy was made multiline for readability.
## Why It's Good For The Game
Currently, Telepathy as a quirk has a discrepancy where non-synths
receive the mutation Telepathy, while synths receive a different
version. The mechanical differences of these created a problem where,
depending on who was using it, this either did or did not anonymize the
identity of the caster. Additionally, these changes allow the quirk
holder who seeks the genetic variant in-round to properly receive the
benefits of such.
Other changes allow people to opt-out of receiving telepathic messages,
in order to avoid negative interactions from those who abuse it.
Multiline telepathy is a desirable feature for the sake of proof
reading.
## Proof Of Testing
## Changelog
:cl:
add: Added a new quirk Psionic Dampener, affecting telepathy from
quirks, genetics, slimes, xenomorphs, revenants and so on.
balance: Telepathy (Quirk) no longer automatically gives the gene.
qol: The telepathic communication power granted by the quirk or the
genetic power is only anonymous if the caster has the mutation, not the
target.
qol: Telepathy (Quirk) now shows when the user uses the power and on
whom, but not the contents of the message.
qol: Telepathy is now multiline.
/:cl:
---
.../~~bubber_defines/traits/declarations.dm | 3 ++
code/_globalvars/traits/_traits.dm | 1 +
code/_globalvars/traits/admin_tooling.dm | 1 +
.../subsystem/processing/quirks.dm | 1 +
code/datums/components/mind_linker.dm | 8 ++++
.../carbon/human/species_types/jellypeople.dm | 5 ++
.../spell_types/list_target/telepathy.dm | 3 ++
.../quirks/positive_quirks/telepathy.dm | 46 ++++++++++---------
.../code/datums/mutations/antenna.dm | 6 +++
tgstation.dme | 1 +
10 files changed, 54 insertions(+), 21 deletions(-)
create mode 100644 modular_zubbers/master_files/code/datums/mutations/antenna.dm
diff --git a/code/__DEFINES/~~bubber_defines/traits/declarations.dm b/code/__DEFINES/~~bubber_defines/traits/declarations.dm
index c4761904e70..af49f8e55ab 100644
--- a/code/__DEFINES/~~bubber_defines/traits/declarations.dm
+++ b/code/__DEFINES/~~bubber_defines/traits/declarations.dm
@@ -67,3 +67,6 @@
/// Trait that gives your brain traumas more resilance
#define TRAIT_RESILIENT_TRAUMAS "trait_resilient_traumas"
+
+/// Trait used to block telepathy types (Genetics, Xenomorph, Revenant, Slime. Ideally should be all.)
+#define TRAIT_PSIONIC_DAMPENER "psionic_dampener"
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index 0e0a5506a85..b321eef1554 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -893,6 +893,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_PET_OWNER" = TRAIT_PET_OWNER,
"TRAIT_PET_SPACE_TREAT" = TRAIT_PET_SPACE_TREAT,
"TRAIT_PERMIT_HUD" = TRAIT_PERMIT_HUD,
+ "TRAIT_PSIONIC_DAMPENER" = TRAIT_PSIONIC_DAMPENER,
"TRAIT_R_UNIQUEWRECK" = TRAIT_R_UNIQUEWRECK,
"TRAIT_R_UNIQUETIP" = TRAIT_R_UNIQUETIP,
"TRAIT_R_WIDE" = TRAIT_R_WIDE,
diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm
index c288e4ad891..704cca24a6d 100644
--- a/code/_globalvars/traits/admin_tooling.dm
+++ b/code/_globalvars/traits/admin_tooling.dm
@@ -470,6 +470,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_PERSONALSPACE" = TRAIT_PERSONALSPACE,
"TRAIT_QUICKREFLEXES" = TRAIT_QUICKREFLEXES,
"TRAIT_PET_OWNER" = TRAIT_PET_OWNER,
+ "TRAIT_PSIONIC_DAMPENER" = TRAIT_PSIONIC_DAMPENER,
"TRAIT_R_UNIQUEWRECK" = TRAIT_R_UNIQUEWRECK,
"TRAIT_R_UNIQUETIP" = TRAIT_R_UNIQUETIP,
"TRAIT_R_WIDE" = TRAIT_R_WIDE,
diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm
index 8e6f12cd540..63637ad758d 100644
--- a/code/controllers/subsystem/processing/quirks.dm
+++ b/code/controllers/subsystem/processing/quirks.dm
@@ -50,6 +50,7 @@ GLOBAL_LIST_INIT_TYPED(quirk_blacklist, /list/datum/quirk, list(
list(/datum/quirk/equipping/entombed, /datum/quirk/badback),
list(/datum/quirk/unblinking, /datum/quirk/item_quirk/fluoride_stare),
list(/datum/quirk/micro, /datum/quirk/micro/smaller, /datum/quirk/micro/smallest, /datum/quirk/oversized),
+ list(/datum/quirk/psionic_dampener, /datum/quirk/telepathic),
//BUBBER EDIT ADDITION END
))
diff --git a/code/datums/components/mind_linker.dm b/code/datums/components/mind_linker.dm
index 156dc825dd5..6e340424672 100644
--- a/code/datums/components/mind_linker.dm
+++ b/code/datums/components/mind_linker.dm
@@ -90,6 +90,14 @@
/datum/component/mind_linker/proc/link_mob(mob/living/to_link)
if(QDELETED(to_link) || to_link.stat == DEAD)
return FALSE
+ //BUBBER EDIT ADDITION START
+ if(HAS_TRAIT(to_link, TRAIT_MINDSHIELD) && linking_protection) // Mindshield implant - no dice
+ return FALSE
+ if(to_link.can_block_magic(MAGIC_RESISTANCE_MIND, charge_cost = 0) && linking_protection)
+ return FALSE
+ if(HAS_TRAIT(to_link, TRAIT_PSIONIC_DAMPENER) && linking_protection) // Telepathy blocker quirk
+ return FALSE
+ //BUBBER EDIT ADDITION END
if(linked_mobs[to_link])
return FALSE
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 829dd72ba03..a328ae2d15b 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -754,6 +754,11 @@
if(recipient.can_block_magic(MAGIC_RESISTANCE_MIND, charge_cost = 0))
to_chat(telepath, span_warning("As you reach into [recipient]'s mind, you are stopped by a mental blockage. It seems you've been foiled."))
return
+ //BUBBER EDIT ADDITION START - Telepathy Block Quirk
+ if(HAS_TRAIT(recipient, TRAIT_PSIONIC_DAMPENER))
+ to_chat(telepath, span_warning("As you reach into [recipient]'s mind, you are stopped by a mental blockage."))
+ return
+ //BUBBER EDIT ADDITION END
log_directed_talk(telepath, recipient, msg, LOG_SAY, "slime telepathy")
to_chat(recipient, "[span_notice("You hear an alien voice in your head... ")][msg]")
to_chat(telepath, span_notice("You telepathically said: \"[msg]\" to [recipient]"))
diff --git a/code/modules/spells/spell_types/list_target/telepathy.dm b/code/modules/spells/spell_types/list_target/telepathy.dm
index 9f3694c03b4..23ef003c8e1 100644
--- a/code/modules/spells/spell_types/list_target/telepathy.dm
+++ b/code/modules/spells/spell_types/list_target/telepathy.dm
@@ -43,7 +43,10 @@
var/failure_message_for_ghosts = ""
to_chat(owner, "You transmit to [cast_on]: [formatted_message]")
+ /* BUBBER EDIT REMOVAL START
if(!cast_on.can_block_magic(antimagic_flags, charge_cost = 0)) //hear no evil
+ */ //BUBBER EDIT REMOVAL END
+ if(!cast_on.can_block_magic(antimagic_flags, charge_cost = 0) && !(HAS_TRAIT(cast_on, TRAIT_PSIONIC_DAMPENER))) // BUBBER EDIT ADDITION
cast_on.balloon_alert(cast_on, "you hear a voice")
to_chat(cast_on, "You hear a voice in your head... [formatted_message]")
else
diff --git a/modular_zubbers/code/modules/quirks/positive_quirks/telepathy.dm b/modular_zubbers/code/modules/quirks/positive_quirks/telepathy.dm
index 24f0c1e81da..647050c8d5c 100644
--- a/modular_zubbers/code/modules/quirks/positive_quirks/telepathy.dm
+++ b/modular_zubbers/code/modules/quirks/positive_quirks/telepathy.dm
@@ -70,7 +70,7 @@
blocked = TRUE
- message = autopunct_bare(capitalize(tgui_input_text(owner, "What do you wish to whisper to [last_target]?", "[src]", max_length = MAX_MESSAGE_LEN)))
+ message = autopunct_bare(capitalize(tgui_input_text(owner, "What do you wish to whisper to [last_target]?", "[src]", null, max_length = MAX_MESSAGE_LEN, multiline = TRUE)))
if(QDELETED(src) || QDELETED(owner) || QDELETED(last_target) || !can_cast_spell())
blocked = FALSE
return
@@ -79,10 +79,14 @@
blocked = FALSE
return
- . = ..()
+ return ..()
/datum/action/cooldown/spell/pointed/telepathy/cast(mob/living/cast_on)
. = ..()
+ owner.visible_message(
+ span_warning("[owner]'s attention locks onto [cast_on]."),
+ ignored_mobs = owner,
+ )
send_thought(owner, cast_on, message)
/datum/action/cooldown/spell/pointed/telepathy/proc/send_thought(mob/living/caster, mob/living/target, message)
@@ -98,16 +102,16 @@
// flub a runechat chat message, do something with the language later
if(owner.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat))
owner.create_chat_message(owner, owner.get_selected_language(), message, list("italics"))
- if(!target.can_block_magic(antimagic_flags, charge_cost = 0) && target.client) //make sure we've got a client before we bother sending anything
+ if(!target.can_block_magic(antimagic_flags, charge_cost = 0) && target.client && !(HAS_TRAIT(target, TRAIT_PSIONIC_DAMPENER))) //make sure we've got a client before we bother sending anything
//different messaging if the target has the telepathy mutation themselves themselves
- if (ishuman(target))
- var/mob/living/carbon/human/human_target = target
- var/datum/mutation/telepathy/tele_mut = human_target.dna.get_mutation(/datum/mutation/telepathy)
+ if (ishuman(caster))
+ var/mob/living/carbon/human/human_caster = caster
+ var/datum/mutation/telepathy/tele_mut = human_caster.dna.get_mutation(/datum/mutation/telepathy)
if (tele_mut)
- to_chat(target, span_boldnotice("[caster]'s psychic presence resounds in your mind: \"[span_purple(message)]\""))
+ to_chat(target, span_boldnotice("A psychic presence resounds in your mind: \"[span_purple(message)]\""))
else
- to_chat(target, span_boldnotice("A voice echoes in your head: \"[span_purple(message)]\""))
+ to_chat(target, span_boldnotice("[caster]'s voice echoes in your head: \"[span_purple(message)]\""))
if(target.client?.prefs.read_preference(/datum/preference/toggle/enable_runechat))
target.create_chat_message(target, target.get_selected_language(), message, list("italics")) // it appears over them since they hear it in their head
@@ -142,26 +146,16 @@
var/datum/weakref/tele_action_ref
/datum/quirk/telepathic/add(client/client_source)
- if (iscarbon(quirk_holder))
- var/mob/living/carbon/human/human_holder = quirk_holder
- human_holder.dna.add_mutation(/datum/mutation/telepathy, MUTATION_SOURCE_QUIRK)
- else if(issilicon(quirk_holder))
- var/mob/living/silicon/robot_holder = quirk_holder
var/datum/action/cooldown/spell/pointed/telepathy/tele_action = new
- tele_action.Grant(robot_holder)
+ tele_action.Grant(quirk_holder)
tele_action_ref = WEAKREF(tele_action)
/datum/quirk/telepathic/remove()
var/datum/action/cooldown/spell/pointed/telepathy/tele_action = tele_action_ref?.resolve()
- if(isnull(tele_action))
- tele_action_ref = null
- if(iscarbon(quirk_holder))
- var/mob/living/carbon/human/human_holder = quirk_holder
- human_holder.dna.remove_mutation(/datum/mutation/telepathy, MUTATION_SOURCE_QUIRK)
- else if(issilicon(quirk_holder) && !isnull(tele_action))
+ if (!isnull(tele_action))
QDEL_NULL(tele_action)
- tele_action_ref = null
+ tele_action_ref = null
/datum/emote/living/telepathy_reply
key = "treply"
@@ -180,3 +174,13 @@
tele_action.blocked = FALSE
return ..()
+
+/datum/quirk/psionic_dampener
+ name = "Psionic Dampener"
+ desc = "Your mind is abnormally resistant to psionic intrusion. Telepathic communication fail to reach you."
+ gain_text = span_notice("Only your own thoughts echo within your mind; the whispers of others fade into silence.")
+ lose_text = span_purple("The distant hum of foreign thoughts returns, brushing gently against your own.")
+ medical_record_text = "Subject exhibits a persistent dampening of cortical resonance. Neural mapping suggests near-total immunity to telepathic or psionic contact."
+ mob_trait = TRAIT_PSIONIC_DAMPENER
+ value = 0
+ icon = FA_ICON_BELL_SLASH
diff --git a/modular_zubbers/master_files/code/datums/mutations/antenna.dm b/modular_zubbers/master_files/code/datums/mutations/antenna.dm
new file mode 100644
index 00000000000..848d18863b1
--- /dev/null
+++ b/modular_zubbers/master_files/code/datums/mutations/antenna.dm
@@ -0,0 +1,6 @@
+/datum/action/cooldown/spell/pointed/mindread/cast(mob/living/cast_on)
+ if(HAS_TRAIT(cast_on, TRAIT_PSIONIC_DAMPENER))
+ to_chat(owner, span_warning("As you reach into [cast_on]'s mind, \
+ you are stopped by a mental blockage."))
+ return
+ return ..()
diff --git a/tgstation.dme b/tgstation.dme
index 2ba229875d4..4e247920969 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -10105,6 +10105,7 @@
#include "modular_zubbers\master_files\code\controllers\subsystem\id_access.dm"
#include "modular_zubbers\master_files\code\datums\announcers\default_announcer.dm"
#include "modular_zubbers\master_files\code\datums\diseases\chronic_ilness.dm"
+#include "modular_zubbers\master_files\code\datums\mutations\antenna.dm"
#include "modular_zubbers\master_files\code\datums\quirks\positive_quirks\self_aware.dm"
#include "modular_zubbers\master_files\code\datums\quirks\positive_quirks\skittish.dm"
#include "modular_zubbers\master_files\code\datums\traits\slow.dm"