Files
Bubberstation/code/datums/components/ghost_direct_control.dm
SkyratBot 227264f146 [MIRROR] Removes Orbit Polling Component, SSpolling improvement (#26769)
* Removes Orbit Polling Component, SSpolling improvement

* a

* Update effects.dmi

* Update tgstation.dme

* Revert "Update tgstation.dme"

This reverts commit d4fdaf0abbfaacddb0cc0d175dad4e410fe57e44.

---------

Co-authored-by: 13spacemen <46101244+13spacemen@users.noreply.github.com>
Co-authored-by: Pinta <68373373+softcerv@users.noreply.github.com>
2024-03-26 11:20:47 -04:00

155 lines
5.8 KiB
Plaintext

/**
* Component which lets ghosts click on a mob to take control of it
*/
/datum/component/ghost_direct_control
/// Message to display upon successful possession
var/assumed_control_message
/// Type of ban you can get to prevent you from accepting this role
var/ban_type
/// Any extra checks which need to run before we take over
var/datum/callback/extra_control_checks
/// Callback run after someone successfully takes over the body
var/datum/callback/after_assumed_control
/// If we're currently awaiting the results of a ghost poll
var/awaiting_ghosts = FALSE
/datum/component/ghost_direct_control/Initialize(
ban_type = ROLE_SENTIENCE,
role_name = null,
poll_question = null,
poll_candidates = TRUE,
poll_announce_chosen = TRUE,
poll_length = 10 SECONDS,
poll_chat_border_icon = null,
poll_ignore_key = POLL_IGNORE_SENTIENCE_POTION,
assumed_control_message = null,
datum/callback/extra_control_checks,
datum/callback/after_assumed_control,
)
. = ..()
if (!isliving(parent))
return COMPONENT_INCOMPATIBLE
src.ban_type = ban_type
src.assumed_control_message = assumed_control_message || "You are [parent]!"
src.extra_control_checks = extra_control_checks
src.after_assumed_control = after_assumed_control
var/mob/mob_parent = parent
LAZYADD(GLOB.joinable_mobs[format_text("[initial(mob_parent.name)]")], mob_parent)
if (poll_candidates)
INVOKE_ASYNC(src, PROC_REF(request_ghost_control), poll_question, role_name || "[parent]", poll_length, poll_ignore_key, poll_announce_chosen, poll_chat_border_icon)
/datum/component/ghost_direct_control/RegisterWithParent()
. = ..()
RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, PROC_REF(on_ghost_clicked))
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examined))
RegisterSignal(parent, COMSIG_MOB_LOGIN, PROC_REF(on_login))
/datum/component/ghost_direct_control/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_EXAMINE, COMSIG_MOB_LOGIN))
return ..()
/datum/component/ghost_direct_control/Destroy(force)
extra_control_checks = null
after_assumed_control = null
var/mob/mob_parent = parent
var/list/spawners = GLOB.joinable_mobs[format_text("[initial(mob_parent.name)]")]
LAZYREMOVE(spawners, mob_parent)
if(!LAZYLEN(spawners))
GLOB.joinable_mobs -= format_text("[initial(mob_parent.name)]")
return ..()
/// Inform ghosts that they can possess this
/datum/component/ghost_direct_control/proc/on_examined(datum/source, mob/user, list/examine_text)
SIGNAL_HANDLER
if (!isobserver(user))
return
var/mob/living/our_mob = parent
if (our_mob.stat == DEAD || our_mob.key || awaiting_ghosts)
return
examine_text += span_boldnotice("You could take control of this mob by clicking on it.")
/// Send out a request for a brain
/datum/component/ghost_direct_control/proc/request_ghost_control(poll_question, role_name, poll_length, poll_ignore_key, poll_announce_chosen, poll_chat_border_icon)
if(!(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER))
return
awaiting_ghosts = TRUE
var/mob/chosen_one = SSpolling.poll_ghosts_for_target(
question = poll_question,
check_jobban = ban_type,
role = ban_type,
poll_time = poll_length,
checked_target = parent,
ignore_category = poll_ignore_key,
alert_pic = parent,
role_name_text = role_name,
chat_text_border_icon = poll_chat_border_icon,
announce_chosen = poll_announce_chosen,
)
awaiting_ghosts = FALSE
if(isnull(chosen_one))
return
assume_direct_control(chosen_one)
/// A ghost clicked on us, they want to get in this body
/datum/component/ghost_direct_control/proc/on_ghost_clicked(mob/our_mob, mob/dead/observer/hopeful_ghost)
SIGNAL_HANDLER
if (our_mob.key)
qdel(src)
return
if (!hopeful_ghost.client)
return
if (!(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER))
to_chat(hopeful_ghost, span_warning("Ghost roles have been temporarily disabled!"))
return
if (awaiting_ghosts)
to_chat(hopeful_ghost, span_warning("Ghost candidate selection currently in progress!"))
return COMPONENT_CANCEL_ATTACK_CHAIN
if (!SSticker.HasRoundStarted())
to_chat(hopeful_ghost, span_warning("You cannot assume control of this until after the round has started!"))
return COMPONENT_CANCEL_ATTACK_CHAIN
INVOKE_ASYNC(src, PROC_REF(attempt_possession), our_mob, hopeful_ghost)
return COMPONENT_CANCEL_ATTACK_CHAIN
/// We got far enough to establish that this mob is a valid target, let's try to posssess it
/datum/component/ghost_direct_control/proc/attempt_possession(mob/our_mob, mob/dead/observer/hopeful_ghost)
var/ghost_asked = tgui_alert(usr, "Become [our_mob]?", "Are you sure?", list("Yes", "No"))
if (ghost_asked != "Yes" || QDELETED(our_mob))
return
assume_direct_control(hopeful_ghost)
/// Grant possession of our mob, component is now no longer required
/datum/component/ghost_direct_control/proc/assume_direct_control(mob/harbinger)
if (QDELETED(src))
to_chat(harbinger, span_warning("Offer to possess creature has expired!"))
return
if (is_banned_from(harbinger.ckey, list(ban_type)))
to_chat(harbinger, span_warning("You are banned from playing as this role!"))
return
if (!(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER))
to_chat(harbinger, span_warning("Ghost roles have been temporarily disabled!"))
return
var/mob/living/new_body = parent
if (new_body.stat == DEAD)
to_chat(harbinger, span_warning("This body has passed away, it is of no use!"))
return
if (new_body.key)
to_chat(harbinger, span_warning("[parent] has already become sapient!"))
qdel(src)
return
if (extra_control_checks && !extra_control_checks.Invoke(harbinger))
return
harbinger.log_message("took control of [new_body].", LOG_GAME)
new_body.key = harbinger.key
to_chat(new_body, span_boldnotice(assumed_control_message))
after_assumed_control?.Invoke(harbinger)
qdel(src)
/// When someone else assumes control via some other means, get rid of our component
/datum/component/ghost_direct_control/proc/on_login()
SIGNAL_HANDLER
qdel(src)