mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-12 11:13:16 +00:00
-Fixes several instances of runtime spam caused by lack of sanity checks in nifsoft procs. -Fixes a runtime spam caused by 512>513 transition having renamed a fake ao filter argument. -This also fixes the fake ao.
587 lines
18 KiB
Plaintext
587 lines
18 KiB
Plaintext
//These two also have NIF FLAG representations. These are the local setting representations.
|
|
#define NIF_SC_CATCHING_ME 0x1
|
|
#define NIF_SC_CATCHING_OTHERS 0x2
|
|
//These are purely local setings flags, without global representation.
|
|
#define NIF_SC_ALLOW_EARS 0x4
|
|
#define NIF_SC_ALLOW_EYES 0x8
|
|
#define NIF_SC_BACKUPS 0x10
|
|
#define NIF_SC_PROJECTING 0x20
|
|
|
|
///////////
|
|
// Soulcatcher - Like a posibrain, sorta!
|
|
/datum/nifsoft/soulcatcher
|
|
name = "Soulcatcher"
|
|
desc = "A mind storage and processing system capable of capturing and supporting human-level minds in a small VR space."
|
|
list_pos = NIF_SOULCATCHER
|
|
cost = 100 //If I wanna trap people's minds and lood them, then by god I'll do so.
|
|
wear = 1
|
|
p_drain = 0.01
|
|
|
|
var/setting_flags = (NIF_SC_CATCHING_OTHERS|NIF_SC_ALLOW_EARS|NIF_SC_ALLOW_EYES|NIF_SC_BACKUPS|NIF_SC_PROJECTING)
|
|
var/list/brainmobs = list()
|
|
var/inside_flavor = "A small completely white room with a couch, and a window to what seems to be the outside world. A small sign in the corner says 'Configure Me'."
|
|
|
|
New()
|
|
..()
|
|
load_settings()
|
|
|
|
Destroy()
|
|
QDEL_LIST_NULL(brainmobs)
|
|
return ..()
|
|
|
|
activate()
|
|
if((. = ..()))
|
|
show_settings(nif.human)
|
|
spawn(0)
|
|
deactivate()
|
|
|
|
deactivate()
|
|
if((. = ..()))
|
|
return TRUE
|
|
|
|
stat_text()
|
|
return "Change Settings ([brainmobs.len] minds)"
|
|
|
|
install()
|
|
if((. = ..()))
|
|
nif.set_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER) //Required on install, because other_flags aren't sufficient for our complicated settings.
|
|
nif.human.verbs |= /mob/living/carbon/human/proc/nsay
|
|
nif.human.verbs |= /mob/living/carbon/human/proc/nme
|
|
|
|
uninstall()
|
|
QDEL_LIST_NULL(brainmobs)
|
|
if((. = ..()) && nif && nif.human) //Sometimes NIFs are deleted outside of a human
|
|
nif.human.verbs -= /mob/living/carbon/human/proc/nsay
|
|
nif.human.verbs -= /mob/living/carbon/human/proc/nme
|
|
|
|
proc/save_settings()
|
|
if(!nif)
|
|
return
|
|
nif.save_data["[list_pos]"] = inside_flavor
|
|
return TRUE
|
|
|
|
proc/load_settings()
|
|
if(!nif)
|
|
return
|
|
var/load = nif.save_data["[list_pos]"]
|
|
if(load)
|
|
inside_flavor = load
|
|
return TRUE
|
|
|
|
proc/notify_into(var/message)
|
|
var/sound = nif.good_sound
|
|
|
|
to_chat(nif.human,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>Soulcatcher</b> displays, \"<span class='notice'>[message]</span>\"")
|
|
nif.human << sound
|
|
|
|
for(var/brainmob in brainmobs)
|
|
var/mob/living/carbon/brain/caught_soul/CS = brainmob
|
|
to_chat(CS,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>Soulcatcher</b> displays, \"<span class='notice'>[message]</span>\"")
|
|
brainmob << sound
|
|
|
|
proc/say_into(var/message, var/mob/living/sender, var/mob/eyeobj)
|
|
var/sender_name = eyeobj ? eyeobj.name : sender.name
|
|
|
|
//AR Projecting
|
|
if(eyeobj)
|
|
sender.eyeobj.visible_message("<b>[sender_name]</b> says, \"[message]\"")
|
|
|
|
//Not AR Projecting
|
|
else
|
|
to_chat(nif.human,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>[sender_name]</b> speaks, \"[message]\"")
|
|
for(var/brainmob in brainmobs)
|
|
var/mob/living/carbon/brain/caught_soul/CS = brainmob
|
|
to_chat(CS,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>[sender_name]</b> speaks, \"[message]\"")
|
|
|
|
log_nsay(message,nif.human.real_name,sender)
|
|
|
|
proc/emote_into(var/message, var/mob/living/sender, var/mob/eyeobj)
|
|
var/sender_name = eyeobj ? eyeobj.name : sender.name
|
|
|
|
//AR Projecting
|
|
if(eyeobj)
|
|
sender.eyeobj.visible_message("[sender_name] [message]")
|
|
|
|
//Not AR Projecting
|
|
else
|
|
to_chat(nif.human,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>[sender_name]</b> [message]")
|
|
for(var/brainmob in brainmobs)
|
|
var/mob/living/carbon/brain/caught_soul/CS = brainmob
|
|
to_chat(CS,"<b>\[\icon[nif.big_icon]NIF\]</b> <b>[sender_name]</b> [message]")
|
|
|
|
log_nme(message,nif.human.real_name,sender)
|
|
|
|
proc/show_settings(var/mob/living/carbon/human/H)
|
|
set waitfor = FALSE
|
|
var/settings_list = list(
|
|
"Catching You \[[setting_flags & NIF_SC_CATCHING_ME ? "Enabled" : "Disabled"]\]" = NIF_SC_CATCHING_ME,
|
|
"Catching Prey \[[setting_flags & NIF_SC_CATCHING_OTHERS ? "Enabled" : "Disabled"]\]" = NIF_SC_CATCHING_OTHERS,
|
|
"Ext. Hearing \[[setting_flags & NIF_SC_ALLOW_EARS ? "Enabled" : "Disabled"]\]" = NIF_SC_ALLOW_EARS,
|
|
"Ext. Vision \[[setting_flags & NIF_SC_ALLOW_EYES ? "Enabled" : "Disabled"]\]" = NIF_SC_ALLOW_EYES,
|
|
"Mind Backups \[[setting_flags & NIF_SC_BACKUPS ? "Enabled" : "Disabled"]\]" = NIF_SC_BACKUPS,
|
|
"AR Projecting \[[setting_flags & NIF_SC_PROJECTING ? "Enabled" : "Disabled"]\]" = NIF_SC_PROJECTING,
|
|
"Design Inside",
|
|
"Erase Contents")
|
|
var/choice = input(nif.human,"Select a setting to modify:","Soulcatcher NIFSoft") as null|anything in settings_list
|
|
if(choice in settings_list)
|
|
switch(choice)
|
|
|
|
if("Design Inside")
|
|
var/new_flavor = input(nif.human, "Type what the prey sees after being 'caught'. This will be \
|
|
printed after an intro ending with: \"Around you, you see...\" to the prey. If you already \
|
|
have prey, this will be printed to them after \"Your surroundings change to...\". Limit 2048 char.", \
|
|
"VR Environment", html_decode(inside_flavor)) as message
|
|
new_flavor = sanitize(new_flavor, MAX_MESSAGE_LEN*2)
|
|
inside_flavor = new_flavor
|
|
nif.notify("Updating VR environment...")
|
|
for(var/brain in brainmobs)
|
|
var/mob/living/carbon/brain/caught_soul/CS = brain
|
|
to_chat(CS,"<span class='notice'>Your surroundings change to...</span>\n[inside_flavor]")
|
|
save_settings()
|
|
return TRUE
|
|
|
|
if("Erase Contents")
|
|
var/mob/living/carbon/brain/caught_soul/brainpick = input(nif.human,"Select a mind to delete:","Erase Mind") as null|anything in brainmobs
|
|
|
|
var/warning = alert(nif.human,"Are you SURE you want to erase \"[brainpick]\"?","Erase Mind","CANCEL","DELETE","CANCEL")
|
|
if(warning == "DELETE")
|
|
brainmobs -= brainpick
|
|
qdel(brainpick)
|
|
return TRUE
|
|
|
|
//Must just be a flag without special handling then.
|
|
else
|
|
var/flag = settings_list[choice]
|
|
return toggle_setting(flag)
|
|
|
|
proc/toggle_setting(var/flag)
|
|
setting_flags ^= flag
|
|
|
|
var/notify_message
|
|
//Special treatment
|
|
switch(flag)
|
|
if(NIF_SC_BACKUPS)
|
|
if(setting_flags & NIF_SC_BACKUPS)
|
|
notify_message = "Mind backup system enabled."
|
|
else
|
|
notify_message = "Mind backup system disabled."
|
|
|
|
if(NIF_SC_CATCHING_ME)
|
|
if(setting_flags & NIF_SC_CATCHING_ME)
|
|
nif.set_flag(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)
|
|
else
|
|
nif.clear_flag(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)
|
|
if(NIF_SC_CATCHING_OTHERS)
|
|
if(setting_flags & NIF_SC_CATCHING_OTHERS)
|
|
nif.set_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER)
|
|
else
|
|
nif.clear_flag(NIF_O_SCOTHERS,NIF_FLAGS_OTHER)
|
|
if(NIF_SC_ALLOW_EARS)
|
|
if(setting_flags & NIF_SC_ALLOW_EARS)
|
|
for(var/brain in brainmobs)
|
|
var/mob/living/carbon/brain/caught_soul/brainmob = brain
|
|
brainmob.ext_deaf = FALSE
|
|
notify_message = "External audio input enabled."
|
|
else
|
|
for(var/brain in brainmobs)
|
|
var/mob/living/carbon/brain/caught_soul/brainmob = brain
|
|
brainmob.ext_deaf = TRUE
|
|
notify_message = "External audio input disabled."
|
|
if(NIF_SC_ALLOW_EYES)
|
|
if(setting_flags & NIF_SC_ALLOW_EYES)
|
|
for(var/brain in brainmobs)
|
|
var/mob/living/carbon/brain/caught_soul/brainmob = brain
|
|
brainmob.ext_blind = FALSE
|
|
notify_message = "External video input enabled."
|
|
else
|
|
for(var/brain in brainmobs)
|
|
var/mob/living/carbon/brain/caught_soul/brainmob = brain
|
|
brainmob.ext_blind = TRUE
|
|
notify_message = "External video input disabled."
|
|
|
|
if(notify_message)
|
|
notify_into(notify_message)
|
|
|
|
return TRUE
|
|
|
|
//Complex version for catching in-round characters
|
|
proc/catch_mob(var/mob/M)
|
|
if(!M.mind) return
|
|
|
|
//Create a new brain mob
|
|
var/mob/living/carbon/brain/caught_soul/brainmob = new(nif)
|
|
brainmob.nif = nif
|
|
brainmob.soulcatcher = src
|
|
brainmob.container = src
|
|
brainmob.stat = 0
|
|
brainmob.silent = FALSE
|
|
dead_mob_list -= brainmob
|
|
brainmob.add_language(LANGUAGE_GALCOM)
|
|
brainmobs |= brainmob
|
|
|
|
//Put the mind and player into the mob
|
|
M.mind.transfer_to(brainmob)
|
|
brainmob.name = brainmob.mind.name
|
|
brainmob.real_name = brainmob.mind.name
|
|
|
|
//If we caught our owner, special settings.
|
|
if(M == nif.human)
|
|
brainmob.ext_deaf = FALSE
|
|
brainmob.ext_blind = FALSE
|
|
brainmob.parent_mob = TRUE
|
|
|
|
//If they have these values, apply them
|
|
if(ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
brainmob.dna = H.dna
|
|
brainmob.ooc_notes = H.ooc_notes
|
|
brainmob.timeofhostdeath = H.timeofdeath
|
|
SStranscore.m_backup(brainmob.mind,0) //It does ONE, so medical will hear about it.
|
|
|
|
//Else maybe they're a joining ghost
|
|
else if(isobserver(M))
|
|
brainmob.transient = TRUE
|
|
qdel(M) //Bye ghost
|
|
|
|
//Give them a flavortext message
|
|
var/message = "<span class='notice'>Your vision fades in a haze of static, before returning.</span>\n\
|
|
Around you, you see...\n\
|
|
[inside_flavor]"
|
|
|
|
to_chat(brainmob,message)
|
|
|
|
//Reminder on how this works to host
|
|
if(brainmobs.len == 1) //Only spam this on the first one
|
|
to_chat(nif.human,"<span class='notice'>Your occupant's messages/actions can only be seen by you, and you can \
|
|
send messages that only they can hear/see by using the NSay and NMe verbs (or the *nsay and *nme emotes).</span>")
|
|
|
|
//Announce to host and other minds
|
|
notify_into("New mind loaded: [brainmob.name]")
|
|
return TRUE
|
|
|
|
////////////////
|
|
//The caught mob
|
|
/mob/living/carbon/brain/caught_soul
|
|
name = "recorded mind"
|
|
desc = "A mind recorded and being played on digital hardware."
|
|
use_me = 1
|
|
var/ext_deaf = FALSE //Forbidden from 'ear' access on host
|
|
var/ext_blind = FALSE //Forbidden from 'eye' access on host
|
|
var/parent_mob = FALSE //If we've captured our owner
|
|
var/transient = FALSE //Someone who ghosted into the NIF
|
|
var/client_missing = 0 //How long the client has been missing
|
|
universal_understand = TRUE
|
|
|
|
var/obj/item/device/nif/nif
|
|
var/datum/nifsoft/soulcatcher/soulcatcher
|
|
var/identifying_gender
|
|
|
|
/mob/living/carbon/brain/caught_soul/Login()
|
|
..()
|
|
plane_holder.set_vis(VIS_AUGMENTED, TRUE)
|
|
identifying_gender = client.prefs.identifying_gender
|
|
|
|
/mob/living/carbon/brain/caught_soul/Destroy()
|
|
if(soulcatcher)
|
|
soulcatcher.notify_into("Mind unloaded: [name]")
|
|
soulcatcher.brainmobs -= src
|
|
soulcatcher = null
|
|
if(eyeobj)
|
|
reenter_soulcatcher()
|
|
eyeobj = null //This SHOULD be null already, reenter_soulcatcher destroys and nulls it, but safety first.
|
|
container = null
|
|
nif = null
|
|
return ..()
|
|
|
|
/mob/living/carbon/brain/caught_soul/Life()
|
|
if(!mind || !key)
|
|
qdel(src)
|
|
return
|
|
|
|
. = ..()
|
|
|
|
if(!parent_mob && !transient &&(life_tick % 150 == 0) && soulcatcher.setting_flags & NIF_SC_BACKUPS)
|
|
SStranscore.m_backup(mind,0) //Passed 0 means "Don't touch the nif fields on the mind record"
|
|
|
|
life_tick++
|
|
|
|
if(!client)
|
|
if(++client_missing == 300)
|
|
qdel(src)
|
|
return
|
|
else
|
|
client_missing = 0
|
|
|
|
if(parent_mob) return
|
|
|
|
//If they're blinded
|
|
if(ext_blind)
|
|
eye_blind = 5
|
|
client.screen.Remove(global_hud.whitense)
|
|
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
|
|
else
|
|
eye_blind = 0
|
|
clear_fullscreens()
|
|
client.screen.Add(global_hud.whitense)
|
|
|
|
//If they're deaf
|
|
if(ext_deaf)
|
|
ear_deaf = 5
|
|
else
|
|
ear_deaf = 0
|
|
|
|
/mob/living/carbon/brain/caught_soul/hear_say()
|
|
if(ext_deaf || !client)
|
|
return FALSE
|
|
..()
|
|
|
|
/mob/living/carbon/brain/caught_soul/show_message()
|
|
if(ext_blind || !client)
|
|
return FALSE
|
|
..()
|
|
|
|
/mob/living/carbon/brain/caught_soul/me_verb_subtle()
|
|
set hidden = TRUE
|
|
|
|
return FALSE
|
|
|
|
/mob/living/carbon/brain/caught_soul/whisper()
|
|
set hidden = TRUE
|
|
|
|
return FALSE
|
|
|
|
/mob/living/carbon/brain/caught_soul/face_atom(var/atom/A)
|
|
if(eyeobj)
|
|
return eyeobj.face_atom(A)
|
|
else
|
|
return ..(A)
|
|
|
|
/mob/living/carbon/brain/caught_soul/set_dir(var/direction)
|
|
if(eyeobj)
|
|
return eyeobj.set_dir(direction)
|
|
else
|
|
return ..(direction)
|
|
|
|
/mob/living/carbon/brain/caught_soul/say(var/message)
|
|
if(silent) return FALSE
|
|
soulcatcher.say_into(message,src,eyeobj)
|
|
|
|
/mob/living/carbon/brain/caught_soul/emote(var/act,var/m_type=1,var/message = null)
|
|
if(silent) return FALSE
|
|
if (act == "me")
|
|
if(silent)
|
|
return
|
|
if (src.client)
|
|
if (client.prefs.muted & MUTE_IC)
|
|
to_chat(src, "<span class='warning'>You cannot send IC messages (muted).</span>")
|
|
return
|
|
if (stat)
|
|
return
|
|
if(!(message))
|
|
return
|
|
return custom_emote(m_type, message)
|
|
else
|
|
return FALSE
|
|
|
|
/mob/living/carbon/brain/caught_soul/custom_emote(var/m_type, var/message)
|
|
if(silent) return FALSE
|
|
soulcatcher.emote_into(message,src,eyeobj)
|
|
|
|
/mob/living/carbon/brain/caught_soul/resist()
|
|
set name = "Resist"
|
|
set category = "IC"
|
|
|
|
to_chat(src,"<span class='warning'>There's no way out! You're stuck in VR.</span>")
|
|
|
|
///////////////////
|
|
//A projected AR soul thing
|
|
/mob/observer/eye/ar_soul
|
|
plane = PLANE_AUGMENTED
|
|
icon = 'icons/obj/machines/ar_elements.dmi'
|
|
icon_state = "beacon"
|
|
var/mob/living/carbon/human/parent_human
|
|
|
|
/mob/observer/eye/ar_soul/New(var/mob/brainmob, var/human)
|
|
ASSERT(brainmob && brainmob.client)
|
|
..()
|
|
|
|
owner = brainmob //Set eyeobj's owner
|
|
parent_human = human //E-z reference to human
|
|
sight |= SEE_SELF //Always see yourself
|
|
|
|
name = "[brainmob.name] (AR)" //Set the name
|
|
real_name = brainmob.real_name //And the OTHER name
|
|
|
|
forceMove(get_turf(parent_human))
|
|
GLOB.moved_event.register(parent_human, src, /mob/observer/eye/ar_soul/proc/human_moved)
|
|
|
|
//Time to play dressup
|
|
if(brainmob.client.prefs)
|
|
var/mob/living/carbon/human/dummy/dummy = new ()
|
|
brainmob.client.prefs.dress_preview_mob(dummy)
|
|
sleep(1 SECOND) //Strange bug in preview code? Without this, certain things won't show up. Yay race conditions?
|
|
dummy.regenerate_icons()
|
|
|
|
var/icon/new_icon = getHologramIcon(getCompoundIcon(dummy))
|
|
qdel(dummy)
|
|
icon = new_icon
|
|
|
|
/mob/observer/eye/ar_soul/Destroy()
|
|
if(parent_human) //It's POSSIBLE they've been deleted before the NIF somehow
|
|
GLOB.moved_event.unregister(parent_human, src)
|
|
parent_human = null
|
|
return ..()
|
|
|
|
/mob/observer/eye/ar_soul/EyeMove(n, direct)
|
|
var/initial = initial(sprint)
|
|
var/max_sprint = 50
|
|
|
|
if(cooldown && cooldown < world.timeofday)
|
|
sprint = initial
|
|
|
|
for(var/i = 0; i < max(sprint, initial); i += 20)
|
|
var/turf/stepn = get_turf(get_step(src, direct))
|
|
if(stepn)
|
|
set_dir(direct)
|
|
if(can_see(parent_human, stepn))
|
|
forceMove(stepn)
|
|
|
|
cooldown = world.timeofday + 5
|
|
if(acceleration)
|
|
sprint = min(sprint + 0.5, max_sprint)
|
|
else
|
|
sprint = initial
|
|
return 1
|
|
|
|
/mob/observer/eye/ar_soul/proc/human_moved()
|
|
if(!can_see(parent_human,src))
|
|
forceMove(get_turf(parent_human))
|
|
|
|
///////////////////
|
|
//The catching hook
|
|
/hook/death/proc/nif_soulcatcher(var/mob/living/carbon/human/H)
|
|
if(!istype(H) || !H.mind) return TRUE //Hooks must return TRUE
|
|
|
|
if(isbelly(H.loc)) //Died in someone
|
|
var/obj/belly/B = H.loc
|
|
var/mob/living/carbon/human/HP = B.owner
|
|
if(istype(HP) && HP.nif && HP.nif.flag_check(NIF_O_SCOTHERS,NIF_FLAGS_OTHER))
|
|
var/datum/nifsoft/soulcatcher/SC = HP.nif.imp_check(NIF_SOULCATCHER)
|
|
SC.catch_mob(H)
|
|
else if(H.nif && H.nif.flag_check(NIF_O_SCMYSELF,NIF_FLAGS_OTHER)) //They are caught in their own NIF
|
|
var/datum/nifsoft/soulcatcher/SC = H.nif.imp_check(NIF_SOULCATCHER)
|
|
SC.catch_mob(H)
|
|
|
|
return TRUE
|
|
|
|
///////////////////
|
|
//Verbs for humans
|
|
/mob/living/carbon/human/proc/nsay(message as text|null)
|
|
set name = "NSay"
|
|
set desc = "Speak into your NIF's Soulcatcher."
|
|
set category = "IC"
|
|
|
|
if(!nif)
|
|
to_chat(src,"<span class='warning'>You can't use NSay without a NIF.</span>")
|
|
return
|
|
var/datum/nifsoft/soulcatcher/SC = nif.imp_check(NIF_SOULCATCHER)
|
|
if(!SC)
|
|
to_chat(src,"<span class='warning'>You need the Soulcatcher software to use NSay.</span>")
|
|
return
|
|
if(!SC.brainmobs.len)
|
|
to_chat(src,"<span class='warning'>You need a loaded mind to use NSay.</span>")
|
|
return
|
|
if(!message)
|
|
message = input("Type a message to say.","Speak into Soulcatcher") as text|null
|
|
if(message)
|
|
var/sane_message = sanitize(message)
|
|
SC.say_into(sane_message,src)
|
|
|
|
/mob/living/carbon/human/proc/nme(message as text|null)
|
|
set name = "NMe"
|
|
set desc = "Emote into your NIF's Soulcatcher."
|
|
set category = "IC"
|
|
|
|
if(!nif)
|
|
to_chat(src,"<span class='warning'>You can't use NMe without a NIF.</span>")
|
|
return
|
|
var/datum/nifsoft/soulcatcher/SC = nif.imp_check(NIF_SOULCATCHER)
|
|
if(!SC)
|
|
to_chat(src,"<span class='warning'>You need the Soulcatcher software to use NMe.</span>")
|
|
return
|
|
if(!SC.brainmobs.len)
|
|
to_chat(src,"<span class='warning'>You need a loaded mind to use NMe.</span>")
|
|
return
|
|
|
|
if(!message)
|
|
message = input("Type an action to perform.","Emote into Soulcatcher") as text|null
|
|
if(message)
|
|
var/sane_message = sanitize(message)
|
|
SC.emote_into(sane_message,src)
|
|
|
|
///////////////////
|
|
//Verbs for soulbrains
|
|
/mob/living/carbon/brain/caught_soul/verb/ar_project()
|
|
set name = "AR Project"
|
|
set desc = "Project your form into Augmented Reality for those around your predator with the appearance of your loaded character."
|
|
set category = "Soulcatcher"
|
|
|
|
if(eyeobj)
|
|
to_chat(src,"<span class='warning'>You're already projecting in AR!</span>")
|
|
return
|
|
|
|
if(!(soulcatcher.setting_flags & NIF_SC_PROJECTING))
|
|
to_chat(src,"<span class='warning'>Projecting from this NIF has been disabled!</span>")
|
|
return
|
|
|
|
if(!client || !client.prefs)
|
|
return //Um...
|
|
|
|
eyeobj = new/mob/observer/eye/ar_soul(src,nif.human)
|
|
soulcatcher.notify_into("[src] now AR projecting.")
|
|
|
|
/mob/living/carbon/brain/caught_soul/verb/jump_to_owner()
|
|
set name = "Jump to Owner"
|
|
set desc = "Jump your projection back to the owner of the soulcatcher you're inside."
|
|
set category = "Soulcatcher"
|
|
|
|
if(!eyeobj)
|
|
to_chat(src,"<span class='warning'>You're not projecting into AR!</span>")
|
|
return
|
|
|
|
eyeobj.forceMove(get_turf(nif))
|
|
|
|
/mob/living/carbon/brain/caught_soul/verb/reenter_soulcatcher()
|
|
set name = "Re-enter Soulcatcher"
|
|
set desc = "Leave AR projection and drop back into the soulcatcher."
|
|
set category = "Soulcatcher"
|
|
|
|
if(!eyeobj)
|
|
to_chat(src,"<span class='warning'>You're not projecting into AR!</span>")
|
|
return
|
|
|
|
QDEL_NULL(eyeobj)
|
|
soulcatcher.notify_into("[src] ended AR projection.")
|
|
|
|
/mob/living/carbon/brain/caught_soul/verb/nsay(message as text|null)
|
|
set name = "NSay"
|
|
set desc = "Speak into the NIF's Soulcatcher (circumventing AR speaking)."
|
|
set category = "Soulcatcher"
|
|
|
|
if(!message)
|
|
message = input("Type a message to say.","Speak into Soulcatcher") as text|null
|
|
if(message)
|
|
var/sane_message = sanitize(message)
|
|
soulcatcher.say_into(sane_message,src,null)
|
|
|
|
/mob/living/carbon/brain/caught_soul/verb/nme(message as text|null)
|
|
set name = "NMe"
|
|
set desc = "Emote into the NIF's Soulcatcher (circumventing AR speaking)."
|
|
set category = "Soulcatcher"
|
|
|
|
if(!message)
|
|
message = input("Type an action to perform.","Emote into Soulcatcher") as text|null
|
|
if(message)
|
|
var/sane_message = sanitize(message)
|
|
soulcatcher.emote_into(sane_message,src,null)
|