mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 23:27:34 +01:00
[MIRROR] Refactors slimelink and mansus link to be a component to cut down on hard-dels / code copy+paste [MDB IGNORE] (#11496)
* Refactors slimelink and mansus link to be a component to cut down on hard-dels / code copy+paste (#64836) So this started out as a hard delete fix for the mansus link Then I realized the mansus link was literally copy+pasted exactly the same code And the reason why mansus link was hard-delling was because slime link used to hard-del and those were fixed but those fixes were never copied over So in a fit of rage I refactored the slimelink to be a component, datum/component/mind_linker. Raw Prophets and Stargazers use it. I'm not 100% certain on some of the methods used but it works? It works. * Refactors slimelink and mansus link to be a component to cut down on hard-dels / code copy+paste Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
This commit is contained in:
@@ -695,7 +695,7 @@
|
||||
// Shares cooldowns with other cooldown abilities of the same value, not active if null
|
||||
var/shared_cooldown
|
||||
|
||||
/datum/action/cooldown/New()
|
||||
/datum/action/cooldown/New(Target)
|
||||
..()
|
||||
button.maptext = ""
|
||||
button.maptext_x = 8
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* # Mind Linker
|
||||
*
|
||||
* A component that handles linking multiple player's minds
|
||||
* into one network which allows them to talk directly to one another.
|
||||
* Like telepathy but for multiple people at once!
|
||||
*/
|
||||
/datum/component/mind_linker
|
||||
/// The name of our network, displayed to all users.
|
||||
var/network_name = "Mind Link"
|
||||
/// The color of the network when talking in chat
|
||||
var/chat_color
|
||||
/// The message sent to someone when linked up.
|
||||
var/link_message
|
||||
/// The message sent to someone when unlinked.
|
||||
var/unlink_message
|
||||
/// A list of all signals that will call qdel() on our component if triggered. Optional.
|
||||
var/list/signals_which_destroy_us
|
||||
/// A callback invoked after an unlink is done. Optional.
|
||||
var/datum/callback/post_unlink_callback
|
||||
/// The icon file given to the speech action handed out.
|
||||
var/speech_action_icon = 'icons/mob/actions/actions_slime.dmi'
|
||||
/// The icon state applied to the speech action handed out.
|
||||
var/speech_action_icon_state = "link_speech"
|
||||
/// The icon background for the speech action handed out.
|
||||
var/speech_action_background_icon_state = "bg_alien"
|
||||
/// The master's linking action, which allows them to link people to the network.
|
||||
var/datum/action/linker_action
|
||||
/// The master's speech action. The owner of the link shouldn't lose this as long as the link remains.
|
||||
var/datum/action/innate/linked_speech/master_speech
|
||||
/// An assoc list of [mob/living]s to [datum/action/innate/linked_speech]s. All the mobs that are linked to our network.
|
||||
var/list/mob/living/linked_mobs = list()
|
||||
|
||||
/datum/component/mind_linker/Initialize(
|
||||
network_name = "Mind Link",
|
||||
chat_color = "#008CA2",
|
||||
linker_action_path,
|
||||
link_message,
|
||||
unlink_message,
|
||||
signals_which_destroy_us,
|
||||
datum/callback/post_unlink_callback,
|
||||
speech_action_icon = 'icons/mob/actions/actions_slime.dmi',
|
||||
speech_action_icon_state = "link_speech",
|
||||
speech_action_background_icon_state = "bg_alien",
|
||||
)
|
||||
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
var/mob/living/owner = parent
|
||||
|
||||
src.network_name = network_name
|
||||
src.chat_color = chat_color
|
||||
src.link_message = link_message || "You are now connected to [owner.real_name]'s [network_name]."
|
||||
src.unlink_message = unlink_message || "You are no longer connected to [owner.real_name]'s [network_name]."
|
||||
|
||||
if(islist(signals_which_destroy_us))
|
||||
src.signals_which_destroy_us = signals_which_destroy_us
|
||||
if(post_unlink_callback)
|
||||
src.post_unlink_callback = post_unlink_callback
|
||||
|
||||
src.speech_action_icon = speech_action_icon
|
||||
src.speech_action_icon_state = speech_action_icon_state
|
||||
src.speech_action_background_icon_state = speech_action_background_icon_state
|
||||
|
||||
if(ispath(linker_action_path))
|
||||
linker_action = new linker_action_path(src)
|
||||
linker_action.Grant(owner)
|
||||
else
|
||||
stack_trace("[type] was created without a valid linker_action_path. No one will be able to link to it.")
|
||||
|
||||
master_speech = new(src)
|
||||
master_speech.Grant(owner)
|
||||
|
||||
to_chat(owner, span_boldnotice("You establish a [network_name], allowing you to link minds to communicate telepathically."))
|
||||
|
||||
/datum/component/mind_linker/Destroy(force, silent)
|
||||
for(var/mob/living/remaining_mob as anything in linked_mobs)
|
||||
unlink_mob(remaining_mob)
|
||||
linked_mobs.Cut()
|
||||
QDEL_NULL(linker_action)
|
||||
QDEL_NULL(master_speech)
|
||||
QDEL_NULL(post_unlink_callback)
|
||||
return ..()
|
||||
|
||||
/datum/component/mind_linker/RegisterWithParent()
|
||||
if(signals_which_destroy_us)
|
||||
RegisterSignal(parent, signals_which_destroy_us, .proc/destroy_link)
|
||||
|
||||
/datum/component/mind_linker/UnregisterFromParent()
|
||||
if(signals_which_destroy_us)
|
||||
UnregisterSignal(parent, signals_which_destroy_us)
|
||||
|
||||
/**
|
||||
* Attempts to link [to_link] to our network, giving them a speech action.
|
||||
*
|
||||
* Returns TRUE if successful, FALSE otherwise
|
||||
*/
|
||||
/datum/component/mind_linker/proc/link_mob(mob/living/to_link)
|
||||
if(QDELETED(to_link) || to_link.stat == DEAD)
|
||||
return FALSE
|
||||
if(HAS_TRAIT(to_link, TRAIT_MINDSHIELD)) // Mindshield implant - no dice
|
||||
return FALSE
|
||||
if(to_link.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
return FALSE
|
||||
if(linked_mobs[to_link])
|
||||
return FALSE
|
||||
|
||||
var/mob/living/owner = parent
|
||||
if(to_link == owner)
|
||||
return FALSE
|
||||
|
||||
to_chat(to_link, span_notice(link_message))
|
||||
to_chat(owner, span_notice("You connect [to_link]'s mind to your [network_name]."))
|
||||
|
||||
for(var/mob/living/other_link as anything in linked_mobs)
|
||||
to_chat(other_link, span_notice("You feel a new presence within [owner.real_name]'s [network_name]."))
|
||||
|
||||
var/datum/action/innate/linked_speech/new_link = new(src)
|
||||
new_link.Grant(to_link)
|
||||
|
||||
linked_mobs[to_link] = new_link
|
||||
RegisterSignal(to_link, list(COMSIG_LIVING_DEATH, COMSIG_PARENT_QDELETING, COMSIG_MINDSHIELD_IMPLANTED), .proc/unlink_mob)
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Unlinks [to_unlink] from our network, deleting their speech action
|
||||
* and cleaning up anything involved.
|
||||
*
|
||||
* Also invokes post_unlink_callback, if supplied.
|
||||
*/
|
||||
/datum/component/mind_linker/proc/unlink_mob(mob/living/to_unlink)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!linked_mobs[to_unlink])
|
||||
return
|
||||
|
||||
to_chat(to_unlink, span_warning(unlink_message))
|
||||
post_unlink_callback?.Invoke(to_unlink)
|
||||
|
||||
UnregisterSignal(to_unlink, list(COMSIG_LIVING_DEATH, COMSIG_PARENT_QDELETING, COMSIG_MINDSHIELD_IMPLANTED))
|
||||
|
||||
var/datum/action/innate/linked_speech/old_link = linked_mobs[to_unlink]
|
||||
linked_mobs -= to_unlink
|
||||
qdel(old_link)
|
||||
|
||||
var/mob/living/owner = parent
|
||||
|
||||
to_chat(owner, span_warning("You feel someone disconnect from your [network_name]."))
|
||||
for(var/mob/living/other_link as anything in linked_mobs)
|
||||
to_chat(other_link, span_warning("You feel a pressence disappear from [owner.real_name]'s [network_name]."))
|
||||
|
||||
/**
|
||||
* Signal proc sent from any signals given to us initialize.
|
||||
* Destroys our component and unlinks everyone.
|
||||
*/
|
||||
/datum/component/mind_linker/proc/destroy_link(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(isliving(source))
|
||||
var/mob/living/owner = source
|
||||
to_chat(owner, span_boldwarning("Your [network_name] breaks!"))
|
||||
|
||||
qdel(src)
|
||||
|
||||
/datum/action/innate/linked_speech
|
||||
name = "Mind Link Speech"
|
||||
desc = "Send a psychic message to everyone connected to your Link."
|
||||
button_icon_state = "link_speech"
|
||||
icon_icon = 'icons/mob/actions/actions_slime.dmi'
|
||||
background_icon_state = "bg_alien"
|
||||
|
||||
/datum/action/innate/linked_speech/New(Target)
|
||||
. = ..()
|
||||
if(!istype(Target, /datum/component/mind_linker))
|
||||
stack_trace("[name] ([type]) was instantiated on a non-mind_linker target, this doesn't work.")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
var/datum/component/mind_linker/linker = Target
|
||||
name = "[linker.network_name] Speech"
|
||||
desc = "Send a psychic message to everyone connected to your [linker.network_name]."
|
||||
icon_icon = linker.speech_action_icon
|
||||
button_icon_state = linker.speech_action_icon_state
|
||||
background_icon_state = linker.speech_action_background_icon_state
|
||||
|
||||
/datum/action/innate/linked_speech/IsAvailable()
|
||||
return ..() && (owner.stat != DEAD)
|
||||
|
||||
/datum/action/innate/linked_speech/Activate()
|
||||
|
||||
var/datum/component/mind_linker/linker = target
|
||||
var/mob/living/linker_parent = linker.parent
|
||||
|
||||
var/message = sanitize(tgui_input_text(owner, "Enter a message to transmit.", "[linker.network_name] Telepathy"))
|
||||
if(!message || QDELETED(src) || QDELETED(owner) || owner.stat == DEAD)
|
||||
return
|
||||
|
||||
if(QDELETED(linker))
|
||||
to_chat(owner, span_warning("The link seems to have been severed."))
|
||||
return
|
||||
|
||||
var/formatted_message = "<i><font color=[linker.chat_color]>\[[linker_parent.real_name]'s [linker.network_name]\] <b>[owner]:</b> [message]</font></i>"
|
||||
log_directed_talk(owner, linker_parent, message, LOG_SAY, "mind link ([linker.network_name])")
|
||||
|
||||
var/list/all_who_can_hear = assoc_to_keys(linker.linked_mobs) + linker_parent
|
||||
|
||||
for(var/mob/living/recipient as anything in all_who_can_hear)
|
||||
to_chat(recipient, formatted_message)
|
||||
|
||||
for(var/mob/recipient as anything in GLOB.dead_mob_list)
|
||||
to_chat(recipient, "[FOLLOW_LINK(recipient, owner)] [formatted_message]")
|
||||
@@ -1,71 +1,74 @@
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link
|
||||
name = "Mansus Link"
|
||||
desc = "Piercing through reality, connecting minds. This spell allows you to add people to a Mansus Net, allowing them to communicate with each other from afar."
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "mansus_link"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
invocation = "PI'RC' TH' M'ND"
|
||||
invocation_type = INVOCATION_WHISPER
|
||||
school = SCHOOL_FORBIDDEN
|
||||
charge_max = 300
|
||||
clothes_req = FALSE
|
||||
range = 10
|
||||
// Manse link action for Raw Prophets
|
||||
// Actually an action larping as a spell, because spells don't track what they're attached to.
|
||||
/datum/action/cooldown/manse_link
|
||||
name = "Manse Link"
|
||||
desc = "This spell allows you to pierce through reality and connect minds to one another \
|
||||
via your Mansus Link. All minds connected to your Mansus Link will be able to communicate discreetly across great distances."
|
||||
icon_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
button_icon_state = "mansus_link"
|
||||
background_icon_state = "bg_ecult"
|
||||
cooldown_time = 20 SECONDS
|
||||
text_cooldown = FALSE
|
||||
click_to_activate = TRUE
|
||||
/// The time it takes to link to a mob.
|
||||
var/link_time = 6 SECONDS
|
||||
/// The range of the cast. Expanded beyond normal view range by default, as Raw Prophets have a larger sight range.
|
||||
var/range = 10
|
||||
/// The text the caster is forced tos ay.
|
||||
var/invocation_text = "PI'RC' TH' M'ND"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link/can_target(atom/target, mob/user, silent)
|
||||
if(!isliving(target))
|
||||
/datum/action/cooldown/manse_link/New(Target)
|
||||
. = ..()
|
||||
if(!istype(Target, /datum/component/mind_linker))
|
||||
stack_trace("[name] ([type]) was instantiated on a non-mind_linker target, this doesn't work.")
|
||||
qdel(src)
|
||||
|
||||
/datum/action/cooldown/manse_link/InterceptClickOn(mob/living/caller, params, atom/clicked_on)
|
||||
if(!isliving(clicked_on))
|
||||
return FALSE
|
||||
if(clicked_on == caller)
|
||||
return FALSE
|
||||
if(get_dist(caller, clicked_on) > range)
|
||||
to_chat(caller, span_warning("[clicked_on] is too far to establish a link.")) // Not a balloon alert due being so zoomed out.
|
||||
return FALSE
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/action/cooldown/manse_link/Activate(atom/victim)
|
||||
owner.say("#[invocation_text]", forced = "spell")
|
||||
|
||||
// Short cooldown placed during the channel to prevent spam links.
|
||||
StartCooldown(10 SECONDS)
|
||||
|
||||
// If we link successfuly, we can start the full cooldown duration.
|
||||
if(do_linking(victim))
|
||||
StartCooldown()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link/cast(list/targets, mob/user)
|
||||
var/mob/living/simple_animal/hostile/heretic_summon/raw_prophet/originator = user
|
||||
/**
|
||||
* The actual process of linking [linkee] to our network.
|
||||
*/
|
||||
/datum/action/cooldown/manse_link/proc/do_linking(mob/living/linkee)
|
||||
var/datum/component/mind_linker/linker = target
|
||||
if(linkee.stat == DEAD)
|
||||
to_chat(owner, span_warning("They're dead!"))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/target = targets[1]
|
||||
to_chat(owner, span_notice("You begin linking [linkee]'s mind to yours..."))
|
||||
to_chat(linkee, span_warning("You feel your mind being pulled somewhere... connected... intertwined with the very fabric of reality..."))
|
||||
|
||||
to_chat(originator, span_notice("You begin linking [target]'s mind to yours..."))
|
||||
to_chat(target, span_warning("You feel your mind being pulled... connected... intertwined with the very fabric of reality..."))
|
||||
if(!do_after(originator, 6 SECONDS, target))
|
||||
return
|
||||
if(!originator.link_mob(target))
|
||||
to_chat(originator, span_warning("You can't seem to link [target]'s mind..."))
|
||||
to_chat(target, span_warning("The foreign presence leaves your mind."))
|
||||
return
|
||||
to_chat(originator, span_notice("You connect [target]'s mind to your mansus link!"))
|
||||
if(!do_after(owner, link_time, linkee))
|
||||
to_chat(owner, span_warning("You fail to link to [linkee]'s mind."))
|
||||
to_chat(linkee, span_warning("The foreign presence leaves your mind."))
|
||||
return FALSE
|
||||
|
||||
if(QDELETED(src) || QDELETED(owner) || QDELETED(linkee))
|
||||
return FALSE
|
||||
|
||||
/datum/action/innate/mansus_speech
|
||||
name = "Mansus Link"
|
||||
desc = "Send a psychic message to everyone connected to your Mansus Net."
|
||||
button_icon_state = "link_speech"
|
||||
icon_icon = 'icons/mob/actions/actions_slime.dmi'
|
||||
background_icon_state = "bg_ecult"
|
||||
/// The raw prophet that hosts our link.
|
||||
var/mob/living/simple_animal/hostile/heretic_summon/raw_prophet/originator
|
||||
if(!linker.link_mob(linkee))
|
||||
to_chat(owner, span_warning("You can't seem to link to [linkee]'s mind."))
|
||||
to_chat(linkee, span_warning("The foreign presence leaves your mind."))
|
||||
return FALSE
|
||||
|
||||
/datum/action/innate/mansus_speech/New(originator)
|
||||
. = ..()
|
||||
src.originator = originator
|
||||
|
||||
/datum/action/innate/mansus_speech/Activate()
|
||||
var/mob/living/living_owner = owner
|
||||
if(!originator?.linked_mobs[living_owner])
|
||||
CRASH("Uh oh, a Mansus Link ([type]) got somehow called Activate() [isnull(originator) ? "without an originator Raw Prophet" : "without being in the originator's linked_mobs list"].")
|
||||
|
||||
var/message = sanitize(tgui_input_text(living_owner, "Enter your message", "Telepathy from the Manse"))
|
||||
if(!message)
|
||||
return
|
||||
|
||||
if(QDELETED(living_owner))
|
||||
return
|
||||
|
||||
if(!originator?.linked_mobs[living_owner])
|
||||
to_chat(living_owner, span_warning("The link seems to have been severed..."))
|
||||
Remove(living_owner)
|
||||
return
|
||||
|
||||
var/msg = "<i><font color=#568b00>\[Mansus Link\] <b>[living_owner]:</b> [message]</font></i>"
|
||||
log_directed_talk(living_owner, originator, msg, LOG_SAY, "Mansus Link")
|
||||
to_chat(originator.linked_mobs, msg)
|
||||
|
||||
for(var/dead_mob in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(dead_mob, living_owner)
|
||||
to_chat(dead_mob, "[link] [msg]")
|
||||
return TRUE
|
||||
|
||||
@@ -598,125 +598,28 @@
|
||||
/datum/species/jelly/stargazer
|
||||
name = "Stargazer"
|
||||
id = SPECIES_STARGAZER
|
||||
var/datum/action/innate/project_thought/project_thought
|
||||
var/datum/action/innate/link_minds/link_minds
|
||||
var/datum/action/innate/linked_speech/master_speech
|
||||
var/list/mob/living/linked_mobs = list()
|
||||
var/datum/weakref/slimelink_owner
|
||||
var/current_link_id = 0
|
||||
/// Special "project thought" telepathy action for stargazers.
|
||||
var/datum/action/innate/project_thought/project_action
|
||||
|
||||
/datum/species/jelly/stargazer/on_species_gain(mob/living/carbon/grant_to, datum/species/old_species)
|
||||
. = ..()
|
||||
project_action = new(src)
|
||||
project_action.Grant(grant_to)
|
||||
|
||||
grant_to.AddComponent(/datum/component/mind_linker, \
|
||||
network_name = "Slime Link", \
|
||||
linker_action_path = /datum/action/innate/link_minds, \
|
||||
signals_which_destroy_us = list(COMSIG_SPECIES_LOSS), \
|
||||
)
|
||||
|
||||
//Species datums don't normally implement destroy, but JELLIES SUCK ASS OUT OF A STEEL STRAW
|
||||
/datum/species/jelly/stargazer/Destroy()
|
||||
for(var/mob/living/link_to_clear as anything in linked_mobs)
|
||||
unlink_mob(link_to_clear)
|
||||
linked_mobs.Cut()
|
||||
QDEL_NULL(project_thought)
|
||||
QDEL_NULL(link_minds)
|
||||
QDEL_NULL(master_speech)
|
||||
slimelink_owner = null
|
||||
QDEL_NULL(project_action)
|
||||
return ..()
|
||||
|
||||
/datum/species/jelly/stargazer/on_species_loss(mob/living/carbon/C)
|
||||
..()
|
||||
for(var/mob/living/link_to_clear as anything in linked_mobs)
|
||||
unlink_mob(link_to_clear)
|
||||
if(project_thought)
|
||||
QDEL_NULL(project_thought)
|
||||
if(link_minds)
|
||||
QDEL_NULL(link_minds)
|
||||
if(master_speech)
|
||||
QDEL_NULL(master_speech)
|
||||
slimelink_owner = null
|
||||
|
||||
/datum/species/jelly/stargazer/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
..()
|
||||
for(var/mob/living/link_to_clear as anything in linked_mobs)
|
||||
unlink_mob(link_to_clear)
|
||||
|
||||
/datum/species/jelly/stargazer/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
..()
|
||||
project_thought = new(src)
|
||||
project_thought.Grant(C)
|
||||
link_minds = new(src)
|
||||
link_minds.Grant(C)
|
||||
master_speech = new(src)
|
||||
master_speech.Grant(C)
|
||||
slimelink_owner = WEAKREF(C)
|
||||
|
||||
/**
|
||||
* Adds a living, not mind/psych shielded mob to the linked_mobs list and gives him
|
||||
* the ability to chat with other mobs in the same lists.
|
||||
* Don't call this proc on the owner; stat, mindshield, antimagic checks and superfluous comsigs
|
||||
* will only lead to bugs in that case. He has his own ability.
|
||||
*/
|
||||
/datum/species/jelly/stargazer/proc/link_mob(mob/living/mob_linked)
|
||||
if(QDELETED(mob_linked) || mob_linked.stat == DEAD)
|
||||
return FALSE
|
||||
if(HAS_TRAIT(mob_linked, TRAIT_MINDSHIELD)) //mindshield implant, no dice
|
||||
return FALSE
|
||||
if(mob_linked.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
return FALSE
|
||||
if(mob_linked in linked_mobs)
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/owner = slimelink_owner.resolve()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
to_chat(mob_linked, span_notice("You are now connected to [owner.real_name]'s Slime Link."))
|
||||
var/datum/action/innate/linked_speech/action = new(src)
|
||||
action.Grant(mob_linked)
|
||||
linked_mobs[mob_linked] = action
|
||||
RegisterSignal(mob_linked, list(COMSIG_LIVING_DEATH, COMSIG_PARENT_QDELETING, SIGNAL_ADDTRAIT(TRAIT_MINDSHIELD)), .proc/unlink_mob)
|
||||
return TRUE
|
||||
|
||||
/datum/species/jelly/stargazer/proc/unlink_mob(mob/living/mob_linked)
|
||||
SIGNAL_HANDLER
|
||||
if(!linked_mobs.Find(mob_linked))
|
||||
return
|
||||
UnregisterSignal(mob_linked, list(COMSIG_LIVING_DEATH, COMSIG_PARENT_QDELETING, SIGNAL_ADDTRAIT(TRAIT_MINDSHIELD)))
|
||||
var/datum/action/innate/linked_speech/action = linked_mobs[mob_linked]
|
||||
var/mob/living/carbon/human/owner = slimelink_owner.resolve()
|
||||
if(owner)
|
||||
to_chat(mob_linked, span_notice("You are no longer connected to [owner.real_name]'s Slime Link."))
|
||||
linked_mobs -= mob_linked
|
||||
qdel(action)
|
||||
|
||||
/datum/action/innate/linked_speech
|
||||
name = "Slimelink"
|
||||
desc = "Send a psychic message to everyone connected to your slime link."
|
||||
button_icon_state = "link_speech"
|
||||
icon_icon = 'icons/mob/actions/actions_slime.dmi'
|
||||
background_icon_state = "bg_alien"
|
||||
|
||||
/datum/action/innate/linked_speech/Activate()
|
||||
var/mob/living/carbon/human/human_user = owner
|
||||
if(human_user.stat == DEAD)
|
||||
return
|
||||
|
||||
var/datum/species/jelly/stargazer/master_species = target
|
||||
var/mob/living/carbon/human/star_owner = master_species.slimelink_owner.resolve()
|
||||
|
||||
if(star_owner != human_user && !(human_user in master_species.linked_mobs))
|
||||
to_chat(human_user, span_warning("The link seems to have been severed..."))
|
||||
return
|
||||
|
||||
var/message = sanitize(tgui_input_text(human_user, "Enter a message", "Slime Telepathy"))
|
||||
|
||||
if(!message)
|
||||
return
|
||||
|
||||
if(QDELETED(master_species) || (star_owner != human_user && !(human_user in master_species.linked_mobs)))
|
||||
to_chat(human_user, span_warning("The link seems to have been severed..."))
|
||||
return
|
||||
|
||||
var/msg = "<i><font color=#008CA2>\[[star_owner.real_name]'s Slime Link\] <b>[human_user]:</b> [message]</font></i>"
|
||||
log_directed_talk(human_user, star_owner, msg, LOG_SAY, "slime link")
|
||||
to_chat(star_owner, msg)
|
||||
for(var/mob/living/recipient as anything in master_species.linked_mobs)
|
||||
to_chat(recipient, msg)
|
||||
|
||||
for(var/mob/recipient as anything in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(recipient, human_user)
|
||||
to_chat(recipient, "[link] [msg]")
|
||||
/datum/species/jelly/stargazer/on_species_loss(mob/living/carbon/remove_from)
|
||||
QDEL_NULL(project_action)
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/project_thought
|
||||
name = "Send Thought"
|
||||
@@ -762,26 +665,69 @@
|
||||
button_icon_state = "mindlink"
|
||||
icon_icon = 'icons/mob/actions/actions_slime.dmi'
|
||||
background_icon_state = "bg_alien"
|
||||
/// The species required to use this ability. Typepath.
|
||||
var/req_species = /datum/species/jelly/stargazer
|
||||
/// Whether we're currently linking to someone.
|
||||
var/currently_linking = FALSE
|
||||
|
||||
/datum/action/innate/link_minds/New(Target)
|
||||
. = ..()
|
||||
if(!istype(Target, /datum/component/mind_linker))
|
||||
stack_trace("[name] ([type]) was instantiated on a non-mind_linker target, this doesn't work.")
|
||||
qdel(src)
|
||||
|
||||
/datum/action/innate/link_minds/IsAvailable()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!ishuman(owner) || !is_species(owner, req_species))
|
||||
return FALSE
|
||||
if(currently_linking)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/action/innate/link_minds/Activate()
|
||||
var/mob/living/carbon/human/human_user = owner
|
||||
if(!is_species(human_user, /datum/species/jelly/stargazer))
|
||||
if(!isliving(owner.pulling) || owner.grab_state < GRAB_AGGRESSIVE)
|
||||
to_chat(owner, span_warning("You need to aggressively grab someone to link minds!"))
|
||||
return
|
||||
|
||||
if(!human_user.pulling || !isliving(human_user.pulling) || human_user.grab_state < GRAB_AGGRESSIVE)
|
||||
to_chat(human_user, span_warning("You need to aggressively grab someone to link minds!"))
|
||||
var/mob/living/living_target = owner.pulling
|
||||
if(living_target.stat == DEAD)
|
||||
to_chat(owner, span_warning("They're dead!"))
|
||||
return
|
||||
|
||||
var/mob/living/living_target = human_user.pulling
|
||||
var/datum/species/jelly/stargazer/user_species = human_user.dna.species
|
||||
|
||||
to_chat(human_user, span_notice("You begin linking [living_target]'s mind to yours..."))
|
||||
to_chat(owner, span_notice("You begin linking [living_target]'s mind to yours..."))
|
||||
to_chat(living_target, span_warning("You feel a foreign presence within your mind..."))
|
||||
if(do_after(human_user, 60, target = living_target))
|
||||
if(human_user.pulling != living_target || human_user.grab_state < GRAB_AGGRESSIVE)
|
||||
return
|
||||
if(user_species?.link_mob(living_target))
|
||||
to_chat(human_user, span_notice("You connect [living_target]'s mind to your slime link!"))
|
||||
else
|
||||
to_chat(human_user, span_warning("You can't seem to link [living_target]'s mind..."))
|
||||
to_chat(living_target, span_warning("The foreign presence leaves your mind."))
|
||||
currently_linking = TRUE
|
||||
|
||||
if(!do_after(owner, 6 SECONDS, target = living_target, extra_checks = CALLBACK(src, .proc/while_link_callback, living_target)))
|
||||
to_chat(owner, span_warning("You can't seem to link [living_target]'s mind."))
|
||||
to_chat(living_target, span_warning("The foreign presence leaves your mind."))
|
||||
currently_linking = FALSE
|
||||
return
|
||||
|
||||
currently_linking = FALSE
|
||||
if(QDELETED(src) || QDELETED(owner) || QDELETED(living_target))
|
||||
return
|
||||
|
||||
var/datum/component/mind_linker/linker = target
|
||||
if(!linker.link_mob(living_target))
|
||||
to_chat(owner, span_warning("You can't seem to link [living_target]'s mind."))
|
||||
to_chat(living_target, span_warning("The foreign presence leaves your mind."))
|
||||
|
||||
|
||||
/// Callback ran during the do_after of Activate() to see if we can keep linking with someone.
|
||||
/datum/action/innate/link_minds/proc/while_link_callback(mob/living/linkee)
|
||||
if(!is_species(owner, req_species))
|
||||
return FALSE
|
||||
if(!owner.pulling)
|
||||
return FALSE
|
||||
if(owner.pulling != linkee)
|
||||
return FALSE
|
||||
if(owner.grab_state < GRAB_AGGRESSIVE)
|
||||
return FALSE
|
||||
if(linkee.stat == DEAD)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -61,73 +61,41 @@
|
||||
sight = SEE_MOBS|SEE_OBJS|SEE_TURFS
|
||||
spells_to_add = list(
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/long,
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link,
|
||||
/obj/effect/proc_holder/spell/targeted/telepathy/eldritch,
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/blind/eldritch,
|
||||
)
|
||||
|
||||
/// A assoc list of [mob/living ref] to [datum/action ref] - all the mobs linked to our mansus network.
|
||||
var/list/mob/living/linked_mobs = list()
|
||||
|
||||
/mob/living/simple_animal/hostile/heretic_summon/raw_prophet/Initialize(mapload)
|
||||
. = ..()
|
||||
link_mob(src)
|
||||
var/on_link_message = "You feel something new enter your sphere of mind... \
|
||||
You hear whispers of people far away, screeches of horror and a huming of welcome to [src]'s Mansus Link."
|
||||
|
||||
var/on_unlink_message = "Your mind shatters as [src]'s Mansus Link leaves your mind."
|
||||
|
||||
AddComponent(/datum/component/mind_linker, \
|
||||
network_name = "Mansus Link", \
|
||||
chat_color = "#568b00", \
|
||||
linker_action_path = /datum/action/cooldown/manse_link, \
|
||||
link_message = on_link_message, \
|
||||
unlink_message = on_unlink_message, \
|
||||
post_unlink_callback = CALLBACK(src, .proc/after_unlink), \
|
||||
speech_action_background_icon_state = "bg_ecult", \
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/hostile/heretic_summon/raw_prophet/Login()
|
||||
. = ..()
|
||||
client?.view_size.setTo(10)
|
||||
|
||||
/**
|
||||
* Link [linked_mob] to our mansus link, if possible.
|
||||
* Creates a mansus speech action and grants it to the linked mob,
|
||||
* storing it in our linked_mobs list.
|
||||
/*
|
||||
* Callback for the mind_linker component.
|
||||
* Stuns people who are ejected from the network.
|
||||
*/
|
||||
/mob/living/simple_animal/hostile/heretic_summon/raw_prophet/proc/link_mob(mob/living/mob_linked)
|
||||
if(QDELETED(mob_linked) || mob_linked.stat == DEAD)
|
||||
return FALSE
|
||||
if(HAS_TRAIT(mob_linked, TRAIT_MINDSHIELD)) //mindshield implant, no dice
|
||||
return FALSE
|
||||
if(mob_linked.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
return FALSE
|
||||
if(linked_mobs[mob_linked])
|
||||
return FALSE
|
||||
|
||||
to_chat(mob_linked, span_notice("You feel something new enter your sphere of mind... \
|
||||
You hear whispers of people far away, screeches of horror and a huming of welcome to [src]'s Mansus Link."))
|
||||
|
||||
var/datum/action/innate/mansus_speech/action = new(src)
|
||||
linked_mobs[mob_linked] = action
|
||||
action.Grant(mob_linked)
|
||||
|
||||
RegisterSignal(mob_linked, list(COMSIG_LIVING_DEATH, COMSIG_PARENT_QDELETING, SIGNAL_ADDTRAIT(TRAIT_MINDSHIELD)), .proc/unlink_mob)
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Signal proc that handles removing mobs from our mansus link.
|
||||
*
|
||||
* Remove the [mob_linked] from our list of linked mobs, and delete the associated action.
|
||||
*/
|
||||
/mob/living/simple_animal/hostile/heretic_summon/raw_prophet/proc/unlink_mob(mob/living/mob_linked)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(QDELETED(linked_mobs[mob_linked]))
|
||||
/mob/living/simple_animal/hostile/heretic_summon/raw_prophet/proc/after_unlink(mob/living/unlinked_mob)
|
||||
if(QDELETED(unlinked_mob) || unlinked_mob.stat == DEAD)
|
||||
return
|
||||
UnregisterSignal(mob_linked, list(COMSIG_LIVING_DEATH, COMSIG_PARENT_QDELETING, SIGNAL_ADDTRAIT(TRAIT_MINDSHIELD)))
|
||||
var/datum/action/innate/mansus_speech/action = linked_mobs[mob_linked]
|
||||
action.Remove(mob_linked)
|
||||
qdel(action)
|
||||
|
||||
to_chat(mob_linked, span_notice("Your mind shatters as [src]'s Mansus Link leaves your mind."))
|
||||
INVOKE_ASYNC(mob_linked, /mob.proc/emote, "scream")
|
||||
mob_linked.AdjustParalyzed(0.5 SECONDS) //micro stun
|
||||
|
||||
linked_mobs -= mob_linked
|
||||
|
||||
/mob/living/simple_animal/hostile/heretic_summon/raw_prophet/Destroy()
|
||||
for(var/linked_mob in linked_mobs)
|
||||
unlink_mob(linked_mob)
|
||||
return ..()
|
||||
INVOKE_ASYNC(unlinked_mob, /mob.proc/emote, "scream")
|
||||
unlinked_mob.AdjustParalyzed(0.5 SECONDS) //micro stun
|
||||
|
||||
// What if we took a linked list... But made it a mob?
|
||||
/// The "Terror of the Night" / Armsy, a large worm made of multiple bodyparts that occupies multiple tiles
|
||||
|
||||
@@ -768,6 +768,7 @@
|
||||
#include "code\datums\components\manual_blinking.dm"
|
||||
#include "code\datums\components\manual_breathing.dm"
|
||||
#include "code\datums\components\material_container.dm"
|
||||
#include "code\datums\components\mind_linker.dm"
|
||||
#include "code\datums\components\mirage_border.dm"
|
||||
#include "code\datums\components\mirv.dm"
|
||||
#include "code\datums\components\mood.dm"
|
||||
|
||||
Reference in New Issue
Block a user