mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 20:48:56 +01:00
## About The Pull Request Every standing overlay layer that wasn't actually a standing overlay layer is now a "sub-standing layer", denoted with a decimal Total number of standing overlay layers reduced from 39 to 23 Small refactors to mutation overlay/species handling and cult halo. ## Why It's Good For The Game Makes it easier to work with mob overlays. You can see at a glance which layers are applied with standing overlays and which layers are manually handled, and more importantly you can see how the layers sort themselves out by just looking at them. Very convenient. ## Changelog 🆑 Melbert code: Reorganized human layering, report any oddities with sprites, such as mislayered equipment. refactor: Refactored cult halos, report any oddities like them not appearing when they should. refactor: Refactored mutation visuals, they're now affected by height! Report any oddities like them disappearing. refactor: Refactored mutation species handling, report any oddities like lizards with hulk. /🆑 --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
173 lines
6.7 KiB
Plaintext
173 lines
6.7 KiB
Plaintext
/datum/mutation/antenna
|
|
name = "Antenna"
|
|
desc = "The affected person sprouts an antenna. This is known to allow them to access common radio channels passively."
|
|
quality = POSITIVE
|
|
text_gain_indication = span_notice("You feel an antenna sprout from your forehead.")
|
|
text_lose_indication = span_notice("Your antenna shrinks back down.")
|
|
instability = POSITIVE_INSTABILITY_MINOR
|
|
difficulty = 8
|
|
mutation_icon_state = "antenna"
|
|
layer_used = FRONT_MUTATIONS_LAYER
|
|
var/datum/weakref/radio_weakref
|
|
|
|
/obj/item/implant/radio/antenna
|
|
name = "internal antenna organ"
|
|
desc = "The internal organ part of the antenna. Science has not yet given it a good name."
|
|
icon = 'icons/obj/devices/voice.dmi'//maybe make a unique sprite later. not important
|
|
icon_state = "walkietalkie"
|
|
|
|
/obj/item/implant/radio/antenna/Initialize(mapload)
|
|
. = ..()
|
|
radio.name = "internal antenna"
|
|
|
|
/datum/mutation/antenna/on_acquiring(mob/living/carbon/human/owner)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
var/obj/item/implant/radio/antenna/linked_radio = new(owner)
|
|
linked_radio.implant(owner, null, TRUE, TRUE)
|
|
radio_weakref = WEAKREF(linked_radio)
|
|
|
|
/datum/mutation/antenna/on_losing(mob/living/carbon/human/owner)
|
|
if(..())
|
|
return
|
|
var/obj/item/implant/radio/antenna/linked_radio = radio_weakref.resolve()
|
|
if(linked_radio)
|
|
QDEL_NULL(linked_radio)
|
|
|
|
/datum/mutation/mindreader
|
|
name = "Mind Reader"
|
|
desc = "The affected person can look into the recent memories of others."
|
|
quality = POSITIVE
|
|
text_gain_indication = span_notice("You hear distant voices at the corners of your mind.")
|
|
text_lose_indication = span_notice("The distant voices fade.")
|
|
power_path = /datum/action/cooldown/spell/pointed/mindread
|
|
instability = POSITIVE_INSTABILITY_MINOR
|
|
difficulty = 8
|
|
locked = TRUE
|
|
mutation_icon_state = "antenna"
|
|
layer_used = FRONT_MUTATIONS_LAYER
|
|
|
|
/datum/action/cooldown/spell/pointed/mindread
|
|
name = "Mindread"
|
|
desc = "Read the target's mind."
|
|
button_icon_state = "mindread"
|
|
school = SCHOOL_PSYCHIC
|
|
cooldown_time = 5 SECONDS
|
|
spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC
|
|
antimagic_flags = MAGIC_RESISTANCE_MIND
|
|
|
|
ranged_mousepointer = 'icons/effects/mouse_pointers/mindswap_target.dmi'
|
|
|
|
/datum/action/cooldown/spell/pointed/mindread/Grant(mob/grant_to)
|
|
. = ..()
|
|
if (!owner)
|
|
return
|
|
ADD_TRAIT(grant_to, TRAIT_MIND_READER, GENETIC_MUTATION)
|
|
RegisterSignal(grant_to, COMSIG_MOB_EXAMINATE, PROC_REF(on_examining))
|
|
|
|
/datum/action/cooldown/spell/pointed/mindread/Remove(mob/remove_from)
|
|
. = ..()
|
|
REMOVE_TRAIT(remove_from, TRAIT_MIND_READER, GENETIC_MUTATION)
|
|
UnregisterSignal(remove_from, COMSIG_MOB_EXAMINATE)
|
|
|
|
/datum/action/cooldown/spell/pointed/mindread/is_valid_target(atom/cast_on)
|
|
if(!isliving(cast_on))
|
|
return FALSE
|
|
var/mob/living/living_cast_on = cast_on
|
|
if(!living_cast_on.mind)
|
|
to_chat(owner, span_warning("[cast_on] has no mind to read!"))
|
|
return FALSE
|
|
if(living_cast_on.stat == DEAD)
|
|
to_chat(owner, span_warning("[cast_on] is dead!"))
|
|
return FALSE
|
|
if(living_cast_on.mob_biotypes & MOB_ROBOTIC)
|
|
to_chat(owner, span_warning("[cast_on] is robotic, you can't read [cast_on.p_their()] mind!"))
|
|
return FALSE
|
|
|
|
return TRUE
|
|
|
|
/datum/action/cooldown/spell/pointed/mindread/cast(mob/living/cast_on)
|
|
. = ..()
|
|
if(cast_on.can_block_magic(antimagic_flags, charge_cost = 0))
|
|
to_chat(owner, span_warning("As you reach into [cast_on]'s mind, \
|
|
you are stopped by a mental blockage. It seems you've been foiled."))
|
|
return
|
|
|
|
if(cast_on == owner)
|
|
to_chat(owner, span_warning("You plunge into your mind... Yep, it's your mind."))
|
|
return
|
|
|
|
if(cast_on.has_status_effect(/datum/status_effect/heretic_passive/moon))
|
|
to_chat(owner, span_hypnophrase(span_bolddanger("YOU SEEK THE TRUTH? I WILL SHOW YOU EVERYTHING.")))
|
|
if(isliving(owner))
|
|
var/mob/living/reader = owner
|
|
reader.apply_status_effect(/datum/status_effect/moon_converted)
|
|
return
|
|
|
|
if(HAS_TRAIT(cast_on, TRAIT_EVIL))
|
|
to_chat(owner, span_warning("As you reach into [cast_on]'s mind, \
|
|
you feel the overwhelming emptiness within. A truly evil being. \
|
|
[HAS_TRAIT(owner, TRAIT_EVIL) ? "It's nice to find someone who is like-minded." : "What is wrong with this person?"]"))
|
|
|
|
var/list/log_info = list()
|
|
var/list/discovered_info = list("<i>You plunge into [cast_on]'s mind and discover...</i>")
|
|
if(prob(20))
|
|
// chance to alert the read-ee
|
|
to_chat(cast_on, span_danger("You feel something foreign enter your mind."))
|
|
log_info += "Target alerted!"
|
|
|
|
var/list/recent_speech = cast_on.copy_recent_speech(copy_amount = 3, line_chance = 50)
|
|
if(length(recent_speech))
|
|
discovered_info += "...Drifting memories of past conversations:"
|
|
var/list/speech_block = list()
|
|
for(var/spoken_memory in recent_speech)
|
|
speech_block += " \"[spoken_memory]\"..."
|
|
log_info += "Recent speech: \"[spoken_memory]\""
|
|
discovered_info += jointext(speech_block, "<br>")
|
|
|
|
if(iscarbon(cast_on))
|
|
var/mob/living/carbon/carbon_cast_on = cast_on
|
|
discovered_info += "...Intent to <b>[carbon_cast_on.combat_mode ? "harm" : "help"]</b>."
|
|
discovered_info += "...True identity of <b>[carbon_cast_on.mind.name]</b>."
|
|
log_info += "Intent: \"[carbon_cast_on.combat_mode ? "harm" : "help"]\""
|
|
log_info += "Identity: \"[carbon_cast_on.mind.name]\""
|
|
|
|
to_chat(owner, boxed_message(span_notice(jointext(discovered_info, "<br>"))))
|
|
log_combat(owner, cast_on, "mind read (cast intentionally)", null, "info: [english_list(log_info, and_text = ", ")]")
|
|
|
|
/datum/action/cooldown/spell/pointed/mindread/proc/on_examining(mob/examiner, atom/examining)
|
|
SIGNAL_HANDLER
|
|
if(!isliving(examining) || examiner == examining)
|
|
return
|
|
|
|
INVOKE_ASYNC(src, PROC_REF(read_mind), examiner, examining)
|
|
|
|
/datum/action/cooldown/spell/pointed/mindread/proc/read_mind(mob/living/examiner, mob/living/examined)
|
|
if(examined.stat >= UNCONSCIOUS || isnull(examined.mind) || (examined.mob_biotypes & MOB_ROBOTIC))
|
|
return
|
|
|
|
var/antimagic = examined.can_block_magic(antimagic_flags, charge_cost = 0)
|
|
var/read_text = ""
|
|
if(!antimagic)
|
|
read_text = examined.get_typing_text()
|
|
if(!read_text)
|
|
return
|
|
|
|
sleep(0.5 SECONDS) // small pause so it comes after all examine text and effects
|
|
if(QDELETED(examiner))
|
|
return
|
|
if(antimagic)
|
|
to_chat(examiner, boxed_message(span_warning("You attempt to analyze [examined]'s current thoughts, but fail to penetrate [examined.p_their()] mind - It seems you've been foiled.")))
|
|
return
|
|
|
|
var/list/log_info = list()
|
|
if(prob(10))
|
|
to_chat(examined, span_danger("You feel something foreign enter your mind."))
|
|
log_info += "Target alerted!"
|
|
|
|
to_chat(examiner, boxed_message(span_notice("<i>You analyze [examined]'s current thoughts...</i><br> \"[read_text]\"...")))
|
|
log_info += "Current thought: \"[read_text]\""
|
|
|
|
log_combat(examiner, examined, "mind read (triggered on examine)", null, "info: [english_list(log_info, and_text = ", ")]")
|