[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:
SkyratBot
2022-02-14 06:10:49 +00:00
committed by GitHub
co-authored by MrMelbert
parent ae8b335c0f
commit aef7cc4ab2
6 changed files with 377 additions and 246 deletions
+1 -1
View File
@@ -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
+213
View File
@@ -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
+1
View File
@@ -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"