mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-28 15:47:15 +01:00
## About The Pull Request Medbay, the CMO, the Psychologist, (possibly) the Library, and some maint rooms across all maps now have multiple copies of the SDSM-35 This exists as an in game ability to reference what brain traumas do. No special bells or whistles, not even a search bar - it's a book after all. <img width="819" height="589" alt="image" src="https://github.com/user-attachments/assets/ace867b9-a0f0-4302-99f9-46ed4d6fe377" /> <img width="802" height="546" alt="image" src="https://github.com/user-attachments/assets/c96941d3-8da8-48f7-859b-93953fe01473" /> ## Why It's Good For The Game De-wikification: Rather than needing to pull up the wiki to figure out what the brain trauma is doing, you can refer to the in game book and cross reference the patient's behavior. Medial larp: It's a reference to the DSM-5. If that wasn't obvious. ## Changelog 🆑 Melbert add: You can now find the SDMS-35 in Medbay, the CMO's office, the Psychologist's office, and possibly the Library. Quite simply, it's a reference book for all the brain trauma's you may experience. /🆑
549 lines
20 KiB
Plaintext
549 lines
20 KiB
Plaintext
|
|
#define IMAGINARY_FRIEND_RANGE 9
|
|
#define IMAGINARY_FRIEND_SPEECH_RANGE IMAGINARY_FRIEND_RANGE
|
|
#define IMAGINARY_FRIEND_EXTENDED_SPEECH_RANGE 999
|
|
|
|
/datum/brain_trauma/special/imaginary_friend
|
|
name = "Imaginary Friend"
|
|
desc = "Patient can see and hear an imaginary person."
|
|
scan_desc = "partial schizophrenia"
|
|
symptoms = "Exhibits signs of interacting with an unseen individual, including talking to themselves, \
|
|
responding to unheard stimuli, and displaying behaviors that suggest the presence of a companion. \
|
|
This \"imaginary friend\" may influence the patient's actions and emotional state, \
|
|
leading to social withdrawal, altered perceptions of reality, or atypical activities."
|
|
gain_text = span_notice("You feel in good company, for some reason.")
|
|
lose_text = span_warning("You feel lonely again.")
|
|
var/mob/eye/imaginary_friend/friend
|
|
var/friend_initialized = FALSE
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/on_gain()
|
|
var/mob/living/M = owner
|
|
if(M.stat == DEAD || !M.client)
|
|
return FALSE
|
|
. = ..()
|
|
make_friend()
|
|
get_ghost()
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/on_life(seconds_per_tick)
|
|
if(get_dist(owner, friend) > 9)
|
|
friend.recall()
|
|
if(!friend)
|
|
qdel(src)
|
|
return
|
|
if(!friend.client && friend_initialized)
|
|
addtimer(CALLBACK(src, PROC_REF(reroll_friend)), 1 MINUTES)
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/on_death()
|
|
..()
|
|
qdel(src) //friend goes down with the ship
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/on_lose()
|
|
..()
|
|
QDEL_NULL(friend)
|
|
|
|
//If the friend goes afk, make a brand new friend. Plenty of fish in the sea of imagination.
|
|
/datum/brain_trauma/special/imaginary_friend/proc/reroll_friend()
|
|
if(friend.client) //reconnected
|
|
return
|
|
friend_initialized = FALSE
|
|
QDEL_NULL(friend)
|
|
make_friend()
|
|
get_ghost()
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/proc/make_friend()
|
|
friend = new(get_turf(owner))
|
|
|
|
/// Tries a poll for the imaginary friend
|
|
/datum/brain_trauma/special/imaginary_friend/proc/get_ghost()
|
|
var/mob/chosen_one = SSpolling.poll_ghosts_for_target(
|
|
question = "Do you want to play as [span_danger("[owner.real_name]'s")] [span_notice("imaginary friend")]?",
|
|
check_jobban = ROLE_PAI,
|
|
poll_time = 20 SECONDS,
|
|
checked_target = owner,
|
|
ignore_category = POLL_IGNORE_IMAGINARYFRIEND,
|
|
alert_pic = owner,
|
|
role_name_text = "imaginary friend",
|
|
)
|
|
add_friend(chosen_one)
|
|
|
|
/// Yay more friends!
|
|
/datum/brain_trauma/special/imaginary_friend/proc/add_friend(mob/dead/observer/ghost)
|
|
if(isnull(ghost))
|
|
qdel(src)
|
|
return
|
|
|
|
friend.PossessByPlayer(ghost.ckey)
|
|
friend.attach_to_owner(owner)
|
|
friend.setup_appearance()
|
|
friend_initialized = TRUE
|
|
friend.log_message("became [key_name(owner)]'s split personality.", LOG_GAME)
|
|
message_admins("[ADMIN_LOOKUPFLW(friend)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.")
|
|
|
|
/mob/eye/imaginary_friend
|
|
name = "imaginary friend"
|
|
real_name = "imaginary friend"
|
|
move_on_shuttle = TRUE
|
|
desc = "A wonderful yet fake friend."
|
|
sight = NONE
|
|
mouse_opacity = MOUSE_OPACITY_ICON
|
|
see_invisible = SEE_INVISIBLE_LIVING
|
|
invisibility = INVISIBILITY_MAXIMUM
|
|
has_emotes = TRUE
|
|
var/icon/human_image
|
|
var/image/current_image
|
|
var/hidden = FALSE
|
|
var/move_delay = 0
|
|
var/mob/living/owner
|
|
var/bubble_icon = "default"
|
|
|
|
/// Whether our host and other imaginary friends can hear us only when nearby or practically anywhere.
|
|
var/extended_message_range = TRUE
|
|
|
|
/mob/eye/imaginary_friend/Login()
|
|
. = ..()
|
|
if(!. || !client)
|
|
return FALSE
|
|
if(owner)
|
|
greet()
|
|
Show()
|
|
|
|
/mob/eye/imaginary_friend/proc/greet()
|
|
to_chat(src, span_notice("<b>You are the imaginary friend of [owner]!</b>"))
|
|
to_chat(src, span_notice("You are absolutely loyal to your friend, no matter what."))
|
|
to_chat(src, span_notice("You cannot directly influence the world around you, but you can see what [owner] cannot."))
|
|
|
|
/**
|
|
* Arguments:
|
|
* * imaginary_friend_owner - The living mob that owns the imaginary friend.
|
|
* * appearance_from_prefs - If this is a valid set of prefs, the appearance of the imaginary friend is based on these prefs.
|
|
*/
|
|
/mob/eye/imaginary_friend/Initialize(mapload)
|
|
. = ..()
|
|
var/static/list/grantable_actions = list(
|
|
/datum/action/innate/imaginary_join,
|
|
/datum/action/innate/imaginary_hide,
|
|
)
|
|
grant_actions_by_list(grantable_actions)
|
|
|
|
/// Links this imaginary friend to the provided mob
|
|
/mob/eye/imaginary_friend/proc/attach_to_owner(mob/living/imaginary_friend_owner)
|
|
owner = imaginary_friend_owner
|
|
if(!owner.imaginary_group)
|
|
owner.imaginary_group = list(owner)
|
|
owner.imaginary_group += src
|
|
greet()
|
|
|
|
/// Copies appearance from passed player prefs, or randomises them if none are provided
|
|
/mob/eye/imaginary_friend/proc/setup_appearance(datum/preferences/appearance_from_prefs = null)
|
|
if(appearance_from_prefs)
|
|
INVOKE_ASYNC(src, PROC_REF(setup_friend_from_prefs), appearance_from_prefs)
|
|
else
|
|
INVOKE_ASYNC(src, PROC_REF(setup_friend))
|
|
|
|
/// Randomise friend name and appearance
|
|
/mob/eye/imaginary_friend/proc/setup_friend()
|
|
gender = pick(MALE, FEMALE)
|
|
real_name = generate_random_name_species_based(gender, FALSE, /datum/species/human)
|
|
name = real_name
|
|
human_image = get_flat_human_icon(null, pick(SSjob.joinable_occupations))
|
|
Show()
|
|
|
|
/**
|
|
* Sets up the imaginary friend's name and look using a set of datum preferences.
|
|
*
|
|
* Arguments:
|
|
* * appearance_from_prefs - If this is a valid set of prefs, the appearance of the imaginary friend is based on the currently selected character in them. Otherwise, it's random.
|
|
*/
|
|
/mob/eye/imaginary_friend/proc/setup_friend_from_prefs(datum/preferences/appearance_from_prefs)
|
|
if(!istype(appearance_from_prefs))
|
|
stack_trace("Attempted to create imaginary friend appearance from null prefs. Using random appearance.")
|
|
setup_friend()
|
|
return
|
|
|
|
real_name = appearance_from_prefs.read_preference(/datum/preference/name/real_name)
|
|
name = real_name
|
|
|
|
// Determine what job is marked as 'High' priority.
|
|
var/datum/job/appearance_job
|
|
var/highest_pref = 0
|
|
for(var/job in appearance_from_prefs.job_preferences)
|
|
var/this_pref = appearance_from_prefs.job_preferences[job]
|
|
if(this_pref > highest_pref)
|
|
appearance_job = SSjob.get_job(job)
|
|
highest_pref = this_pref
|
|
|
|
if(!appearance_job)
|
|
appearance_job = SSjob.get_job(JOB_ASSISTANT)
|
|
|
|
if(istype(appearance_job, /datum/job/ai))
|
|
human_image = icon('icons/mob/silicon/ai.dmi', icon_state = resolve_ai_icon(appearance_from_prefs.read_preference(/datum/preference/choiced/ai_core_display)), dir = SOUTH)
|
|
else if(istype(appearance_job, /datum/job/cyborg))
|
|
human_image = icon('icons/mob/silicon/robots.dmi', icon_state = "robot")
|
|
else
|
|
human_image = get_flat_human_icon(null, appearance_job, appearance_from_prefs)
|
|
Show()
|
|
|
|
/// Returns all member clients of the imaginary_group
|
|
/mob/eye/imaginary_friend/proc/group_clients()
|
|
var/group_clients = list()
|
|
for(var/mob/person as anything in owner.imaginary_group)
|
|
if(person.client)
|
|
group_clients += person.client
|
|
return group_clients
|
|
|
|
/mob/eye/imaginary_friend/proc/Show()
|
|
if(!client || !owner) //nobody home
|
|
return
|
|
|
|
var/list/friend_clients = group_clients() - src.client
|
|
//Remove old image from group
|
|
remove_image_from_clients(current_image, friend_clients)
|
|
|
|
//Generate image from the static icon and the current dir
|
|
current_image = image(human_image, src, , MOB_LAYER, dir=src.dir)
|
|
current_image.override = TRUE
|
|
current_image.name = name
|
|
if(hidden)
|
|
current_image.alpha = 150
|
|
|
|
//Add new image to owner and friend
|
|
if(!hidden)
|
|
add_image_to_clients(current_image, friend_clients)
|
|
|
|
src.client.images |= current_image
|
|
|
|
/mob/eye/imaginary_friend/Destroy()
|
|
if(owner?.client)
|
|
owner.client.images.Remove(human_image)
|
|
if(client)
|
|
client.images.Remove(human_image)
|
|
owner.imaginary_group -= src
|
|
return ..()
|
|
|
|
/mob/eye/imaginary_friend/Hear(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, freq_name, freq_color, list/spans, list/message_mods = list(), message_range)
|
|
if (safe_read_pref(client, /datum/preference/toggle/enable_runechat) && (safe_read_pref(client, /datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker)))
|
|
create_chat_message(speaker, message_language, raw_message, spans)
|
|
to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, freq_name, freq_color, spans, message_mods))
|
|
|
|
/mob/eye/imaginary_friend/send_speech(message, range = IMAGINARY_FRIEND_SPEECH_RANGE, obj/source = src, bubble_type = bubble_icon, list/spans = list(), datum/language/message_language = null, list/message_mods = list(), forced = null)
|
|
message = get_message_mods(message, message_mods)
|
|
|
|
if(message_mods[RADIO_EXTENSION] == MODE_ADMIN)
|
|
SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/cmd_admin_say, message)
|
|
return
|
|
|
|
if(message_mods[RADIO_EXTENSION] == MODE_DEADMIN)
|
|
SSadmin_verbs.dynamic_invoke_verb(client, /datum/admin_verb/dsay, message)
|
|
return
|
|
|
|
if(check_emote(message, forced))
|
|
return
|
|
|
|
message = check_for_custom_say_emote(message, message_mods)
|
|
message = capitalize(message)
|
|
|
|
if(message_mods[MODE_SING])
|
|
var/randomnote = pick("♩", "♪", "♫")
|
|
message = "[randomnote] [capitalize(message)] [randomnote]"
|
|
spans |= SPAN_SINGING
|
|
|
|
if(extended_message_range)
|
|
range = IMAGINARY_FRIEND_EXTENDED_SPEECH_RANGE
|
|
|
|
var/eavesdrop_range = 0
|
|
|
|
if(!(message_mods[MODE_CUSTOM_SAY_ERASE_INPUT]))
|
|
if(message_mods[WHISPER_MODE] == MODE_WHISPER)
|
|
spans |= SPAN_ITALICS
|
|
eavesdrop_range = EAVESDROP_EXTRA_RANGE
|
|
range = WHISPER_RANGE
|
|
|
|
log_sayverb_talk(message, message_mods, tag = "imaginary friend", forced_by = forced)
|
|
|
|
var/messagepart = generate_messagepart(message, spans, message_mods)
|
|
var/dead_rendered = "[span_name("[name] (Imaginary friend of [owner])")] [messagepart]"
|
|
|
|
var/language = message_language || owner.get_selected_language()
|
|
Hear(src, language, message, null, null, null, spans, message_mods) // We always hear what we say
|
|
var/group = owner.imaginary_group - src // The people in our group don't, so we have to exclude ourselves not to hear twice
|
|
for(var/mob/person in group)
|
|
person.Hear(src, language, message, null, null, null, spans, message_mods, range)
|
|
|
|
// Speech bubble, but only for those who have runechat off
|
|
var/list/speech_bubble_recipients = list()
|
|
for(var/mob/user as anything in (group + src)) // Add ourselves back in
|
|
if((safe_read_pref(user.client, /datum/preference/toggle/enable_runechat) || (SSlag_switch.measures[DISABLE_RUNECHAT] && !HAS_TRAIT(src, TRAIT_BYPASS_MEASURES))))
|
|
speech_bubble_recipients.Add(user.client)
|
|
|
|
var/image/bubble = image('icons/mob/effects/talk.dmi', src, "[bubble_type][say_test(message)]", FLY_LAYER)
|
|
SET_PLANE_EXPLICIT(bubble, ABOVE_GAME_PLANE, src)
|
|
bubble.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
|
|
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(flick_overlay_global), bubble, speech_bubble_recipients, 3 SECONDS)
|
|
LAZYADD(update_on_z, bubble)
|
|
addtimer(CALLBACK(src, PROC_REF(clear_saypopup), bubble), 3.5 SECONDS)
|
|
|
|
var/turf/center_turf = get_turf(src)
|
|
if(!center_turf)
|
|
return
|
|
|
|
for(var/mob/dead_player in GLOB.dead_mob_list)
|
|
if(dead_player.z != z || get_dist(src, dead_player) > 7)
|
|
if(eavesdrop_range)
|
|
if(!(get_chat_toggles(dead_player.client) & CHAT_GHOSTWHISPER))
|
|
continue
|
|
else if(!(get_chat_toggles(dead_player.client) & CHAT_GHOSTEARS))
|
|
continue
|
|
var/link = FOLLOW_LINK(dead_player, owner)
|
|
to_chat(dead_player, "[link] [dead_rendered]")
|
|
|
|
/mob/eye/imaginary_friend/proc/clear_saypopup(image/say_popup)
|
|
LAZYREMOVE(update_on_z, say_popup)
|
|
|
|
/mob/eye/imaginary_friend/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced, filterproof)
|
|
if(!message)
|
|
return
|
|
say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced, filterproof)
|
|
|
|
/datum/emote/imaginary_friend
|
|
mob_type_allowed_typecache = /mob/eye/imaginary_friend
|
|
|
|
// We have to create our own since we can only show emotes to ourselves and our owner
|
|
/datum/emote/imaginary_friend/run_emote(mob/user, params, type_override, intentional = FALSE)
|
|
user.log_talk(message, LOG_EMOTE)
|
|
if(!can_run_emote(user, FALSE, intentional))
|
|
return FALSE
|
|
|
|
var/msg = select_message_type(user, message, intentional)
|
|
if(params && message_param)
|
|
msg = select_param(user, params)
|
|
|
|
msg = replace_pronoun(user, msg)
|
|
|
|
if(!msg)
|
|
return TRUE
|
|
|
|
var/mob/eye/imaginary_friend/friend = user
|
|
var/dchatmsg = "[span_bold("[friend] (Imaginary friend of [friend.owner])")] [msg]"
|
|
message = "[span_name("[user]")] [msg]"
|
|
|
|
var/user_turf = get_turf(user)
|
|
if (user.client)
|
|
for(var/mob/ghost as anything in GLOB.dead_mob_list)
|
|
if(!ghost.client || isnewplayer(ghost))
|
|
continue
|
|
if(get_chat_toggles(ghost.client) & CHAT_GHOSTSIGHT && !(ghost in viewers(user_turf, null)))
|
|
ghost.show_message("[FOLLOW_LINK(ghost, user)] [dchatmsg]")
|
|
|
|
for(var/mob/person in friend.owner.imaginary_group)
|
|
to_chat(person, message)
|
|
if(safe_read_pref(person.client, /datum/preference/toggle/enable_runechat))
|
|
person.create_chat_message(friend, raw_message = msg, runechat_flags = EMOTE_MESSAGE)
|
|
return TRUE
|
|
|
|
/datum/emote/imaginary_friend/point
|
|
key = "point"
|
|
key_third_person = "points"
|
|
message = "points."
|
|
message_param = "points at %t."
|
|
|
|
/datum/emote/imaginary_friend/point/run_emote(mob/eye/imaginary_friend/friend, params, type_override, intentional)
|
|
message_param = initial(message_param) // reset
|
|
return ..()
|
|
|
|
/datum/emote/imaginary_friend/custom
|
|
key = "me"
|
|
key_third_person = "custom"
|
|
message = null
|
|
|
|
/datum/emote/imaginary_friend/custom/can_run_emote(mob/user, status_check, intentional)
|
|
return ..() && intentional
|
|
|
|
/datum/emote/imaginary_friend/custom/run_emote(mob/user, params, type_override = null, intentional = FALSE)
|
|
if(!can_run_emote(user, TRUE, intentional))
|
|
return FALSE
|
|
if(is_banned_from(user.ckey, "Emote"))
|
|
to_chat(user, span_boldwarning("You cannot send custom emotes (banned)."))
|
|
return FALSE
|
|
else if(QDELETED(user))
|
|
return FALSE
|
|
else if(user.client && user.client.prefs.muted & MUTE_IC)
|
|
to_chat(user, span_boldwarning("You cannot send IC messages (muted)."))
|
|
return FALSE
|
|
else if(!params)
|
|
message = copytext(sanitize(input("Choose an emote to display.") as text|null), 1, MAX_MESSAGE_LEN)
|
|
else
|
|
message = params
|
|
. = ..()
|
|
message = null
|
|
|
|
/datum/emote/imaginary_friend/custom/replace_pronoun(mob/user, message)
|
|
return message
|
|
|
|
// Another snowflake proc, when will they end... should have refactored it differently
|
|
/mob/eye/imaginary_friend/point_at(atom/pointed_atom)
|
|
if(!isturf(loc))
|
|
return
|
|
|
|
if (pointed_atom in src)
|
|
create_point_bubble(pointed_atom)
|
|
return
|
|
|
|
var/turf/tile = get_turf(pointed_atom)
|
|
if (!tile)
|
|
return
|
|
|
|
var/turf/our_tile = get_turf(src)
|
|
var/obj/visual = image('icons/hud/screen_gen.dmi', our_tile, "arrow", FLY_LAYER)
|
|
|
|
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(flick_overlay_global), visual, group_clients(), 2.5 SECONDS)
|
|
animate(visual, pixel_x = (tile.x - our_tile.x) * ICON_SIZE_X + pointed_atom.pixel_x, pixel_y = (tile.y - our_tile.y) * ICON_SIZE_Y + pointed_atom.pixel_y, time = 1.7, easing = SINE_EASING|EASE_OUT)
|
|
|
|
/mob/eye/imaginary_friend/create_thinking_indicator()
|
|
if(active_thinking_indicator || active_typing_indicator || !HAS_TRAIT(src, TRAIT_THINKING_IN_CHARACTER))
|
|
return FALSE
|
|
active_thinking_indicator = image('icons/mob/effects/talk.dmi', src, "[bubble_icon]3", TYPING_LAYER)
|
|
add_image_to_clients(active_thinking_indicator, group_clients())
|
|
|
|
/mob/eye/imaginary_friend/remove_thinking_indicator()
|
|
if(!active_thinking_indicator)
|
|
return FALSE
|
|
remove_image_from_clients(active_thinking_indicator, group_clients())
|
|
active_thinking_indicator = null
|
|
|
|
/mob/eye/imaginary_friend/create_typing_indicator()
|
|
if(active_typing_indicator || active_thinking_indicator || !HAS_TRAIT(src, TRAIT_THINKING_IN_CHARACTER))
|
|
return FALSE
|
|
active_typing_indicator = image('icons/mob/effects/talk.dmi', src, "[bubble_icon]0", TYPING_LAYER)
|
|
add_image_to_clients(active_typing_indicator, group_clients())
|
|
|
|
/mob/eye/imaginary_friend/remove_typing_indicator()
|
|
if(!active_typing_indicator)
|
|
return FALSE
|
|
remove_image_from_clients(active_typing_indicator, group_clients())
|
|
active_typing_indicator = null
|
|
|
|
/mob/eye/imaginary_friend/remove_all_indicators()
|
|
REMOVE_TRAIT(src, TRAIT_THINKING_IN_CHARACTER, CURRENTLY_TYPING_TRAIT)
|
|
remove_thinking_indicator()
|
|
remove_typing_indicator()
|
|
|
|
/mob/eye/imaginary_friend/Move(NewLoc, Dir = 0)
|
|
if(world.time < move_delay)
|
|
return FALSE
|
|
setDir(Dir)
|
|
if(get_dist(src, owner) > 9)
|
|
recall()
|
|
move_delay = world.time + 10
|
|
return FALSE
|
|
abstract_move(NewLoc)
|
|
move_delay = world.time + 1
|
|
|
|
/mob/eye/imaginary_friend/setDir(newdir)
|
|
. = ..()
|
|
Show() // The image does not actually update until Show() gets called
|
|
|
|
/mob/eye/imaginary_friend/proc/recall()
|
|
if(!owner || loc == owner)
|
|
return FALSE
|
|
abstract_move(owner)
|
|
|
|
/datum/action/innate/imaginary_join
|
|
name = "Join"
|
|
desc = "Join your owner, following them from inside their mind."
|
|
button_icon = 'icons/mob/actions/actions_minor_antag.dmi'
|
|
background_icon_state = "bg_revenant"
|
|
overlay_icon_state = "bg_revenant_border"
|
|
button_icon_state = "join"
|
|
|
|
/datum/action/innate/imaginary_join/Activate()
|
|
var/mob/eye/imaginary_friend/I = owner
|
|
I.recall()
|
|
|
|
/datum/action/innate/imaginary_hide
|
|
name = "Hide"
|
|
desc = "Hide yourself from your owner's sight."
|
|
button_icon = 'icons/mob/actions/actions_minor_antag.dmi'
|
|
background_icon_state = "bg_revenant"
|
|
overlay_icon_state = "bg_revenant_border"
|
|
button_icon_state = "hide"
|
|
|
|
/datum/action/innate/imaginary_hide/proc/update_status()
|
|
var/mob/eye/imaginary_friend/I = owner
|
|
if(I.hidden)
|
|
name = "Show"
|
|
desc = "Become visible to your owner."
|
|
button_icon_state = "unhide"
|
|
else
|
|
name = "Hide"
|
|
desc = "Hide yourself from your owner's sight."
|
|
button_icon_state = "hide"
|
|
build_all_button_icons()
|
|
|
|
/datum/action/innate/imaginary_hide/Activate()
|
|
var/mob/eye/imaginary_friend/fake_friend = owner
|
|
fake_friend.hidden = !fake_friend.hidden
|
|
fake_friend.Show()
|
|
build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON)
|
|
|
|
/datum/action/innate/imaginary_hide/update_button_name(atom/movable/screen/movable/action_button/button, force)
|
|
var/mob/eye/imaginary_friend/fake_friend = owner
|
|
if(fake_friend.hidden)
|
|
name = "Show"
|
|
desc = "Become visible to your owner."
|
|
else
|
|
name = "Hide"
|
|
desc = "Hide yourself from your owner's sight."
|
|
return ..()
|
|
|
|
/datum/action/innate/imaginary_hide/apply_button_icon(atom/movable/screen/movable/action_button/current_button, force = FALSE)
|
|
var/mob/eye/imaginary_friend/fake_friend = owner
|
|
if(fake_friend.hidden)
|
|
button_icon_state = "unhide"
|
|
else
|
|
button_icon_state = "hide"
|
|
|
|
return ..()
|
|
|
|
//down here is the trapped mind
|
|
//like imaginary friend but a lot less imagination and more like mind prison//
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/trapped_owner
|
|
name = "Trapped Victim"
|
|
desc = "Patient appears to be targeted by an invisible entity."
|
|
gain_text = ""
|
|
lose_text = ""
|
|
random_gain = FALSE
|
|
known_trauma = FALSE
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/trapped_owner/make_friend()
|
|
friend = new /mob/eye/imaginary_friend/trapped(get_turf(owner), src)
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/trapped_owner/reroll_friend() //no rerolling- it's just the last owner's hell
|
|
if(friend.client) //reconnected
|
|
return
|
|
friend_initialized = FALSE
|
|
QDEL_NULL(friend)
|
|
qdel(src)
|
|
|
|
/datum/brain_trauma/special/imaginary_friend/trapped_owner/get_ghost() //no randoms
|
|
return
|
|
|
|
/mob/eye/imaginary_friend/trapped
|
|
name = "figment of imagination?"
|
|
real_name = "figment of imagination?"
|
|
desc = "The previous host of this body."
|
|
|
|
/mob/eye/imaginary_friend/trapped/greet()
|
|
to_chat(src, span_notice(span_bold("You have managed to hold on as a figment of the new host's imagination!")))
|
|
to_chat(src, span_notice("All hope is lost for you, but at least you may interact with your host. You do not have to be loyal to them."))
|
|
to_chat(src, span_notice("You cannot directly influence the world around you, but you can see what the host cannot."))
|
|
|
|
/mob/eye/imaginary_friend/trapped/setup_friend()
|
|
real_name = "[owner.real_name]?"
|
|
name = real_name
|
|
human_image = icon('icons/mob/simple/lavaland/lavaland_monsters.dmi', icon_state = "curseblob")
|
|
|
|
#undef IMAGINARY_FRIEND_RANGE
|
|
#undef IMAGINARY_FRIEND_SPEECH_RANGE
|
|
#undef IMAGINARY_FRIEND_EXTENDED_SPEECH_RANGE
|