mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-29 10:31:34 +00:00
## About The Pull Request Revived my old PR https://github.com/tgstation/tgstation/pull/68901 Replaces the annoying tgui alert popup "Do you want to be X? | Yes | No | Never for this round" that is hard to read and steals window focus, with a nice clean alert in the top right that counts down. If it's the same event/mob they stack with 2x, 3x, etc. It also shows how many candidates/ghosts are signed up. The poll alerts have screentips too, they countdown and show if you're signed up, how many people are signed up, if you chose "never for this round" (which is cancelable) ## Why It's Good For The Game  Way easier to see what role is available, you get a nice pic of the role and get it's name in big text, you can cancel "never for this round", and you can cancel signing up for a role before the timer is up ## Changelog 🆑 refactor: Ghost roles now offer ghosts a clickable poll button. Ghosts can select a role, deselect it, alt-click it for "Never For This Round", can cancel "Never", can see the countdown, and can see how many other people are signed up for the role poll. /🆑
323 lines
13 KiB
Plaintext
323 lines
13 KiB
Plaintext
#define OWNER 0
|
|
#define STRANGER 1
|
|
|
|
/datum/brain_trauma/severe/split_personality
|
|
name = "Split Personality"
|
|
desc = "Patient's brain is split into two personalities, which randomly switch control of the body."
|
|
scan_desc = "complete lobe separation"
|
|
gain_text = span_warning("You feel like your mind was split in two.")
|
|
lose_text = span_notice("You feel alone again.")
|
|
var/current_controller = OWNER
|
|
var/initialized = FALSE //to prevent personalities deleting themselves while we wait for ghosts
|
|
var/mob/living/split_personality/stranger_backseat //there's two so they can swap without overwriting
|
|
var/mob/living/split_personality/owner_backseat
|
|
///The role to display when polling ghost
|
|
var/poll_role = "split personality"
|
|
|
|
/datum/brain_trauma/severe/split_personality/on_gain()
|
|
var/mob/living/M = owner
|
|
if(M.stat == DEAD || !M.client) //No use assigning people to a corpse or braindead
|
|
qdel(src)
|
|
return
|
|
..()
|
|
make_backseats()
|
|
get_ghost()
|
|
|
|
/datum/brain_trauma/severe/split_personality/proc/make_backseats()
|
|
stranger_backseat = new(owner, src)
|
|
var/datum/action/personality_commune/stranger_spell = new(src)
|
|
stranger_spell.Grant(stranger_backseat)
|
|
|
|
owner_backseat = new(owner, src)
|
|
var/datum/action/personality_commune/owner_spell = new(src)
|
|
owner_spell.Grant(owner_backseat)
|
|
|
|
/// Attempts to get a ghost to play the personality
|
|
/datum/brain_trauma/severe/split_personality/proc/get_ghost()
|
|
var/datum/callback/to_call = CALLBACK(src, PROC_REF(schism))
|
|
owner.AddComponent(/datum/component/orbit_poll, \
|
|
ignore_key = POLL_IGNORE_SPLITPERSONALITY, \
|
|
job_bans = ROLE_PAI, \
|
|
title = "[owner.real_name]'s [poll_role]", \
|
|
to_call = to_call, \
|
|
)
|
|
|
|
/// Ghost poll has concluded
|
|
/datum/brain_trauma/severe/split_personality/proc/schism(mob/dead/observer/ghost)
|
|
if(isnull(ghost))
|
|
qdel(src)
|
|
return
|
|
|
|
stranger_backseat.key = ghost.key
|
|
stranger_backseat.log_message("became [key_name(owner)]'s split personality.", LOG_GAME)
|
|
message_admins("[ADMIN_LOOKUPFLW(stranger_backseat)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.")
|
|
|
|
|
|
/datum/brain_trauma/severe/split_personality/on_life(seconds_per_tick, times_fired)
|
|
if(owner.stat == DEAD)
|
|
if(current_controller != OWNER)
|
|
switch_personalities(TRUE)
|
|
qdel(src)
|
|
else if(SPT_PROB(1.5, seconds_per_tick))
|
|
switch_personalities()
|
|
..()
|
|
|
|
/datum/brain_trauma/severe/split_personality/on_lose()
|
|
if(current_controller != OWNER) //it would be funny to cure a guy only to be left with the other personality, but it seems too cruel
|
|
switch_personalities(TRUE)
|
|
QDEL_NULL(stranger_backseat)
|
|
QDEL_NULL(owner_backseat)
|
|
..()
|
|
|
|
|
|
/datum/brain_trauma/severe/split_personality/proc/switch_personalities(reset_to_owner = FALSE)
|
|
if(QDELETED(owner) || QDELETED(stranger_backseat) || QDELETED(owner_backseat))
|
|
return
|
|
|
|
var/mob/living/split_personality/current_backseat
|
|
var/mob/living/split_personality/new_backseat
|
|
if(current_controller == STRANGER || reset_to_owner)
|
|
current_backseat = owner_backseat
|
|
new_backseat = stranger_backseat
|
|
else
|
|
current_backseat = stranger_backseat
|
|
new_backseat = owner_backseat
|
|
|
|
if(!current_backseat.client) //Make sure we never switch to a logged off mob.
|
|
return
|
|
|
|
current_backseat.log_message("assumed control of [key_name(owner)] due to [src]. (Original owner: [current_controller == OWNER ? owner.key : current_backseat.key])", LOG_GAME)
|
|
to_chat(owner, span_userdanger("You feel your control being taken away... your other personality is in charge now!"))
|
|
to_chat(current_backseat, span_userdanger("You manage to take control of your body!"))
|
|
|
|
//Body to backseat
|
|
|
|
var/h2b_id = owner.computer_id
|
|
var/h2b_ip= owner.lastKnownIP
|
|
owner.computer_id = null
|
|
owner.lastKnownIP = null
|
|
|
|
new_backseat.ckey = owner.ckey
|
|
|
|
new_backseat.name = owner.name
|
|
|
|
if(owner.mind)
|
|
new_backseat.mind = owner.mind
|
|
|
|
if(!new_backseat.computer_id)
|
|
new_backseat.computer_id = h2b_id
|
|
|
|
if(!new_backseat.lastKnownIP)
|
|
new_backseat.lastKnownIP = h2b_ip
|
|
|
|
if(reset_to_owner && new_backseat.mind)
|
|
new_backseat.ghostize(FALSE)
|
|
|
|
//Backseat to body
|
|
|
|
var/s2h_id = current_backseat.computer_id
|
|
var/s2h_ip= current_backseat.lastKnownIP
|
|
current_backseat.computer_id = null
|
|
current_backseat.lastKnownIP = null
|
|
|
|
owner.ckey = current_backseat.ckey
|
|
owner.mind = current_backseat.mind
|
|
|
|
if(!owner.computer_id)
|
|
owner.computer_id = s2h_id
|
|
|
|
if(!owner.lastKnownIP)
|
|
owner.lastKnownIP = s2h_ip
|
|
|
|
current_controller = !current_controller
|
|
|
|
|
|
/mob/living/split_personality
|
|
name = "split personality"
|
|
real_name = "unknown conscience"
|
|
var/mob/living/carbon/body
|
|
var/datum/brain_trauma/severe/split_personality/trauma
|
|
|
|
/mob/living/split_personality/Initialize(mapload, _trauma)
|
|
if(iscarbon(loc))
|
|
body = loc
|
|
name = body.real_name
|
|
real_name = body.real_name
|
|
trauma = _trauma
|
|
return ..()
|
|
|
|
/mob/living/split_personality/Life(seconds_per_tick = SSMOBS_DT, times_fired)
|
|
if(QDELETED(body))
|
|
qdel(src) //in case trauma deletion doesn't already do it
|
|
|
|
if((body.stat == DEAD && trauma.owner_backseat == src))
|
|
trauma.switch_personalities()
|
|
qdel(trauma)
|
|
|
|
//if one of the two ghosts, the other one stays permanently
|
|
if(!body.client && trauma.initialized)
|
|
trauma.switch_personalities()
|
|
qdel(trauma)
|
|
|
|
..()
|
|
|
|
/mob/living/split_personality/Login()
|
|
. = ..()
|
|
if(!. || !client)
|
|
return FALSE
|
|
to_chat(src, span_notice("As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality."))
|
|
to_chat(src, span_warning("<b>Do not commit suicide or put the body in a deadly position. Behave like you care about it as much as the owner.</b>"))
|
|
|
|
/mob/living/split_personality/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
|
|
to_chat(src, span_warning("You cannot speak, your other self is controlling your body!"))
|
|
return FALSE
|
|
|
|
/mob/living/split_personality/emote(act, m_type = null, message = null, intentional = FALSE, force_silence = FALSE)
|
|
return FALSE
|
|
|
|
///////////////BRAINWASHING////////////////////
|
|
|
|
/datum/brain_trauma/severe/split_personality/brainwashing
|
|
name = "Split Personality"
|
|
desc = "Patient's brain is split into two personalities, which randomly switch control of the body."
|
|
scan_desc = "complete lobe separation"
|
|
gain_text = ""
|
|
lose_text = span_notice("You are free of your brainwashing.")
|
|
can_gain = FALSE
|
|
var/codeword
|
|
var/objective
|
|
|
|
/datum/brain_trauma/severe/split_personality/brainwashing/New(obj/item/organ/internal/brain/B, _permanent, _codeword, _objective)
|
|
..()
|
|
if(_codeword)
|
|
codeword = _codeword
|
|
else
|
|
codeword = pick(strings("ion_laws.json", "ionabstract")\
|
|
| strings("ion_laws.json", "ionobjects")\
|
|
| strings("ion_laws.json", "ionadjectives")\
|
|
| strings("ion_laws.json", "ionthreats")\
|
|
| strings("ion_laws.json", "ionfood")\
|
|
| strings("ion_laws.json", "iondrinks"))
|
|
|
|
/datum/brain_trauma/severe/split_personality/brainwashing/on_gain()
|
|
..()
|
|
var/mob/living/split_personality/traitor/traitor_backseat = stranger_backseat
|
|
traitor_backseat.codeword = codeword
|
|
traitor_backseat.objective = objective
|
|
|
|
/datum/brain_trauma/severe/split_personality/brainwashing/make_backseats()
|
|
stranger_backseat = new /mob/living/split_personality/traitor(owner, src, codeword, objective)
|
|
owner_backseat = new(owner, src)
|
|
|
|
/datum/brain_trauma/severe/split_personality/brainwashing/get_ghost()
|
|
set waitfor = FALSE
|
|
var/list/mob/dead/observer/candidates = SSpolling.poll_ghost_candidates_for_mob("Do you want to play as [owner.real_name]'s brainwashed mind?", poll_time = 7.5 SECONDS, target_mob = stranger_backseat, pic_source = owner, role_name_text = "brainwashed mind")
|
|
if(LAZYLEN(candidates))
|
|
var/mob/dead/observer/C = pick(candidates)
|
|
stranger_backseat.key = C.key
|
|
else
|
|
qdel(src)
|
|
|
|
/datum/brain_trauma/severe/split_personality/brainwashing/on_life(seconds_per_tick, times_fired)
|
|
return //no random switching
|
|
|
|
/datum/brain_trauma/severe/split_personality/brainwashing/handle_hearing(datum/source, list/hearing_args)
|
|
if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER] || !owner.has_language(hearing_args[HEARING_LANGUAGE]))
|
|
return
|
|
|
|
var/message = hearing_args[HEARING_RAW_MESSAGE]
|
|
if(findtext(message, codeword))
|
|
hearing_args[HEARING_RAW_MESSAGE] = replacetext(message, codeword, span_warning("[codeword]"))
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/brain_trauma/severe/split_personality, switch_personalities)), 10)
|
|
|
|
/datum/brain_trauma/severe/split_personality/brainwashing/handle_speech(datum/source, list/speech_args)
|
|
if(findtext(speech_args[SPEECH_MESSAGE], codeword))
|
|
speech_args[SPEECH_MESSAGE] = "" //oh hey did you want to tell people about the secret word to bring you back?
|
|
|
|
/mob/living/split_personality/traitor
|
|
name = "split personality"
|
|
real_name = "unknown conscience"
|
|
var/objective
|
|
var/codeword
|
|
|
|
/mob/living/split_personality/traitor/Login()
|
|
. = ..()
|
|
if(!. || !client)
|
|
return FALSE
|
|
to_chat(src, span_notice("As a brainwashed personality, you cannot do anything yet but observe. However, you may gain control of your body if you hear the special codeword, switching places with the current personality."))
|
|
to_chat(src, span_notice("Your activation codeword is: <b>[codeword]</b>"))
|
|
if(objective)
|
|
to_chat(src, span_notice("Your master left you an objective: <b>[objective]</b>. Follow it at all costs when in control."))
|
|
|
|
/datum/brain_trauma/severe/split_personality/blackout
|
|
name = "Alcohol-Induced CNS Impairment"
|
|
desc = "Patient's CNS has been temporarily impaired by imbibed alcohol, blocking memory formation, and causing reduced cognition and stupefaction."
|
|
scan_desc = "alcohol-induced CNS impairment"
|
|
gain_text = span_warning("Crap, that was one drink too many. You black out...")
|
|
lose_text = "You wake up very, very confused and hungover. All you can remember is drinking a lot of alcohol... what happened?"
|
|
poll_role = "blacked out drunkard"
|
|
random_gain = FALSE
|
|
/// Duration of effect, tracked in seconds, not deciseconds. qdels when reaching 0.
|
|
var/duration_in_seconds = 180
|
|
|
|
/datum/brain_trauma/severe/split_personality/blackout/on_gain()
|
|
. = ..()
|
|
RegisterSignal(owner, COMSIG_ATOM_SPLASHED, PROC_REF(on_splashed))
|
|
notify_ghosts(
|
|
"[owner] is blacking out!",
|
|
source = owner,
|
|
header = "Bro I'm not even drunk right now",
|
|
notify_flags = NOTIFY_CATEGORY_NOFLASH,
|
|
)
|
|
|
|
/datum/brain_trauma/severe/split_personality/blackout/on_lose()
|
|
. = ..()
|
|
owner.add_mood_event("hang_over", /datum/mood_event/hang_over)
|
|
UnregisterSignal(owner, COMSIG_ATOM_SPLASHED)
|
|
|
|
/datum/brain_trauma/severe/split_personality/blackout/proc/on_splashed()
|
|
SIGNAL_HANDLER
|
|
if(prob(20))//we don't want every single splash to wake them up now do we
|
|
qdel(src)
|
|
|
|
/datum/brain_trauma/severe/split_personality/blackout/on_life(seconds_per_tick, times_fired)
|
|
if(current_controller == OWNER && stranger_backseat)//we should only start transitioning after the other personality has entered
|
|
owner.overlay_fullscreen("fade_to_black", /atom/movable/screen/fullscreen/blind)
|
|
owner.clear_fullscreen("fade_to_black", animated = 4 SECONDS)
|
|
switch_personalities()
|
|
if(owner.stat == DEAD)
|
|
if(current_controller != OWNER)
|
|
switch_personalities(TRUE)
|
|
qdel(src)
|
|
return
|
|
if(duration_in_seconds <= 0)
|
|
qdel(src)
|
|
return
|
|
else if(duration_in_seconds <= 60 && !(duration_in_seconds % 20))
|
|
to_chat(owner, span_warning("You have [duration_in_seconds] seconds left before sobering up!"))
|
|
if(prob(10) && !HAS_TRAIT(owner, TRAIT_DISCOORDINATED_TOOL_USER))
|
|
ADD_TRAIT(owner, TRAIT_DISCOORDINATED_TOOL_USER, TRAUMA_TRAIT)
|
|
owner.balloon_alert(owner, "dexterity reduced temporarily!")
|
|
//We then send a callback to automatically re-add the trait
|
|
addtimer(TRAIT_CALLBACK_REMOVE(owner, TRAIT_DISCOORDINATED_TOOL_USER, TRAUMA_TRAIT), 10 SECONDS)
|
|
addtimer(CALLBACK(owner, TYPE_PROC_REF(/atom, balloon_alert), owner, "dexterity regained!"), 10 SECONDS)
|
|
if(prob(15))
|
|
playsound(owner,'sound/effects/sf_hiccup_male_01.ogg', 50)
|
|
owner.emote("hiccup")
|
|
owner.adjustStaminaLoss(-5) //too drunk to feel anything
|
|
duration_in_seconds -= seconds_per_tick
|
|
|
|
/mob/living/split_personality/blackout
|
|
name = "blacked-out drunkard"
|
|
real_name = "drunken consciousness"
|
|
|
|
/mob/living/split_personality/blackout/Login()
|
|
. = ..()
|
|
if(!. || !client)
|
|
return FALSE
|
|
to_chat(src, span_notice("You're the incredibly inebriated leftovers of your host's consciousness! Make sure to act the part and leave a trail of confusion and chaos in your wake."))
|
|
to_chat(src, span_boldwarning("Do not commit suicide or put the body in danger, you have a minor liscense to grief just like a clown, do not kill anyone or create a situation leading to the body being in danger or in harm ways. While you're drunk, you're not suicidal."))
|
|
|
|
#undef OWNER
|
|
#undef STRANGER
|