diff --git a/code/__defines/_planes+layers_vr.dm b/code/__defines/_planes+layers_vr.dm index 30238bc6b0..744f299224 100644 --- a/code/__defines/_planes+layers_vr.dm +++ b/code/__defines/_planes+layers_vr.dm @@ -6,4 +6,4 @@ #define PLANE_AUGMENTED 40 //Augmented-reality plane -#define ABOVE_WINDOW_LAYER 3.25 //Above full tile windows so wall items are clickable \ No newline at end of file +#define ABOVE_WINDOW_LAYER 3.25 //Above full tile windows so wall items are clickable diff --git a/code/__defines/nifsoft.dm b/code/__defines/nifsoft.dm index 2772aadede..dc03b2b411 100644 --- a/code/__defines/nifsoft.dm +++ b/code/__defines/nifsoft.dm @@ -38,9 +38,10 @@ #define NIF_COMPLIANCE 31 #define NIF_SIZECHANGE 32 #define NIF_SOULCATCHER 33 +#define NIF_WORLDBEND 34 // Must be equal to the highest number above -#define TOTAL_NIF_SOFTWARE 33 +#define TOTAL_NIF_SOFTWARE 34 ////////////////////// // NIF flag list hints diff --git a/code/modules/clothing/glasses/hud_vr.dm b/code/modules/clothing/glasses/hud_vr.dm index ec91efe9b4..c2b198bc70 100644 --- a/code/modules/clothing/glasses/hud_vr.dm +++ b/code/modules/clothing/glasses/hud_vr.dm @@ -9,7 +9,7 @@ var/datum/nano_module/arscreen var/arscreen_path var/flash_prot = 0 //0 for none, 1 for flash weapon protection, 2 for welder protection - enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR) + enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_AUGMENTED) plane_slots = list(slot_glasses) /obj/item/clothing/glasses/omnihud/New() @@ -72,7 +72,7 @@ mode = "med" action_button_name = "AR Console (Crew Monitor)" arscreen_path = /datum/nano_module/crew_monitor - enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_STATUS_R,VIS_CH_BACKUP) + enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_STATUS_R,VIS_CH_BACKUP,VIS_AUGMENTED) ar_interact(var/mob/living/carbon/human/user) if(arscreen) @@ -87,7 +87,7 @@ flash_protection = FLASH_PROTECTION_MAJOR action_button_name = "AR Console (Security Alerts)" arscreen_path = /datum/nano_module/alarm_monitor/security - enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_WANTED) + enables_planes = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_WANTED,VIS_AUGMENTED) ar_interact(var/mob/living/carbon/human/user) if(arscreen) diff --git a/code/modules/entopics_vr/alternate_appearance.dm b/code/modules/entopics_vr/alternate_appearance.dm new file mode 100644 index 0000000000..4fd7d31ed0 --- /dev/null +++ b/code/modules/entopics_vr/alternate_appearance.dm @@ -0,0 +1,151 @@ +/* + Alternate Appearances! By RemieRichards + A framework for replacing an atom (and it's overlays) with an override = 1 image, that's less shit! + Example uses: + * hallucinating all mobs looking like skeletons + * people wearing cardborg suits appearing as Standard Cyborgs to the other Silicons + * !!use your imagination!! + +*/ + +//This datum is built on-the-fly by some of the procs below +//no need to instantiate it +/datum/alternate_appearance + var/key = "" + var/image/img + var/list/viewers = list() + var/atom/owner = null + + +/* + Displays the alternate_appearance + displayTo - a list of MOBS to show this appearance to +*/ +/datum/alternate_appearance/proc/display_to(list/displayTo) + if(!displayTo || !displayTo.len) + return + for(var/m in displayTo) + var/mob/M = m + if(!M.viewing_alternate_appearances) + M.viewing_alternate_appearances = list() + viewers |= M + M.viewing_alternate_appearances |= src + if(M.client) + M.client.images |= img + +/* + Hides the alternate_appearance + hideFrom - optional list of MOBS to hide it from the list's mobs specifically +*/ +/datum/alternate_appearance/proc/hide(list/hideFrom) + var/list/hiding = viewers + if(hideFrom) + hiding = hideFrom + + for(var/m in hiding) + var/mob/M = m + if(M.client) + M.client.images -= img + if(M.viewing_alternate_appearances && M.viewing_alternate_appearances.len) + M.viewing_alternate_appearances -= src + viewers -= M + + +/* + Removes the alternate_appearance from its owner's alternate_appearances list, hiding it also +*/ +/datum/alternate_appearance/proc/remove() + hide() + if(owner && owner.alternate_appearances) + owner.alternate_appearances -= key + + +/datum/alternate_appearance/Destroy() + remove() + return ..() + + + +/atom + var/list/alternate_appearances //the alternate appearances we own + var/list/viewing_alternate_appearances //the alternate appearances we're viewing, stored here to reestablish them after Logout()s + //these lists are built as necessary, so atoms aren't all lugging around empty lists + +/* + Builds an alternate_appearance datum for the supplied args, optionally displaying it straight away + key - the key to the assoc list of key = /datum/alternate_appearances + img - the image file to be the "alternate appearance" + WORKS BEST IF: + * it has override = 1 set + * the image's loc is the atom that will use the appearance (otherwise... it's not exactly an alt appearance of this atom is it?) + displayTo - optional list of MOBS to display to immediately + + Example: + var/image/I = image(icon = 'disguise.dmi', icon_state = "disguise", loc = src) + I.override = 1 + add_alt_appearance("super_secret_disguise", I, players) + +*/ +/atom/proc/add_alt_appearance(key, img, list/displayTo = list()) + if(!key || !img) + return + if(!alternate_appearances) + alternate_appearances = list() + + var/datum/alternate_appearance/AA = new() + AA.img = img + AA.key = key + AA.owner = src + + if(alternate_appearances[key]) + qdel(alternate_appearances[key]) + alternate_appearances[key] = AA + if(displayTo && displayTo.len) + display_alt_appearance(key, displayTo) + + +////////////// +// WRAPPERS // +////////////// + +/* + Removes an alternate_appearance from src's alternate_appearances list + Wrapper for: alternate_appearance/remove() + key - the key to the assoc list of key = /datum/alternate_appearance +*/ +/atom/proc/remove_alt_appearance(key) + if(alternate_appearances) + if(alternate_appearances[key]) + qdel(alternate_appearances[key]) + + +/* + Displays an alternate appearance from src's alternate_appearances list + Wrapper for: alternate_appearance/display_to() + key - the key to the assoc list of key = /datum/alternate_appearance + displayTo - a list of MOBS to show this appearance to +*/ +/atom/proc/display_alt_appearance(key, list/displayTo) + if(!alternate_appearances || !key) + return + var/datum/alternate_appearance/AA = alternate_appearances[key] + if(!AA || !AA.img) + return + AA.display_to(displayTo) + + +/* + Hides an alternate appearance from src's alternate_appearances list + Wrapper for: alternate_appearance/hide() + key - the key to the assoc list of key = /datum/alternate_appearance + hideFrom - optional list of MOBS to hide it from the list's mobs specifically +*/ +/atom/proc/hide_alt_appearance(key, list/hideFrom) + if(!alternate_appearances || !key) + return + var/datum/alternate_appearance/AA = alternate_appearances[key] + if(!AA) + return + AA.hide(hideFrom) + + diff --git a/code/modules/entopics_vr/entopics.dm b/code/modules/entopics_vr/entopics.dm index 931728e321..1e146e0c05 100644 --- a/code/modules/entopics_vr/entopics.dm +++ b/code/modules/entopics_vr/entopics.dm @@ -1,28 +1,65 @@ //Augmented reality objects and their associated systems for attaching to things var/global/list/entopic_images = list() +var/global/list/entopic_users = list() + +var/global/list/alt_farmanimals = list() /datum/entopic - var/icon = null - var/icon_state = null - var/plane = PLANE_AUGMENTED - var/layer = OBJ_LAYER + var/name + var/suffix + var/icon + var/icon_state + var/plane + var/layer + var/holder + var/alpha = 200 //Holo-ish + var/override = FALSE var/image/my_image var/registered = FALSE // Less expensive to make it a finite state than to use |= on entopic_images or anything like that. -/datum/entopic/New(var/atom/aholder, var/icon/aicon, var/aicon_state, var/aplane, var/alayer) +/datum/entopic/New(var/atom/aholder, var/icon/aicon, var/aicon_state, var/aalpha, var/aplane, var/alayer, var/aoverride, var/aname, var/asuffix) ASSERT(aholder && (isicon(aicon) || isicon(icon))) //Everything we need to set in the initializer var/image/tempimage = image(icon = aicon || icon, loc = aholder, icon_state = aicon_state || icon_state) - //And everything we don't - tempimage.plane = plane = aplane || plane - tempimage.layer = layer = alayer || layer + //And everything we don't (order of prescidence: directly passed, datum-specified, then natural byond) + if(aplane) + tempimage.plane = plane = aplane + else if(plane) + tempimage.plane = plane + if(alayer) + tempimage.layer = layer = alayer + else if(layer) + tempimage.layer = layer + + if(aalpha) + tempimage.alpha = alpha = aalpha + else if(alpha) + tempimage.alpha = alpha + + if(aoverride) + tempimage.override = override = aoverride + else if(override) + tempimage.override = override + + if(aname) + tempimage.name = name = aname + else if(name) + tempimage.name = name + + if(asuffix) + tempimage.suffix = suffix = asuffix + else if(suffix) + tempimage.suffix = suffix + + //Save these for later + holder = aholder if(aicon) icon = aicon - if(aicon_state) + if(icon_state) icon_state = aicon_state my_image = tempimage @@ -38,16 +75,23 @@ var/global/list/entopic_images = list() if(registered || !my_image) return - entopic_images += my_image - world << my_image // *noises of disgust* registered = TRUE + entopic_images += my_image + for(var/m in entopic_users) + var/mob/M = m + if(M.client) + M.client.images += my_image /datum/entopic/proc/unregister_entopic() if(!registered || !my_image) return - entopic_images -= my_image registered = FALSE + entopic_images -= my_image + for(var/m in entopic_users) + var/mob/M = m + if(M.client) + M.client.images -= my_image /datum/entopic/proc/show() if(!my_image) @@ -55,6 +99,8 @@ var/global/list/entopic_images = list() my_image.mouse_opacity = 1 my_image.invisibility = 0 + my_image.alpha = alpha + my_image.override = override /datum/entopic/proc/hide() if(!my_image) @@ -62,3 +108,27 @@ var/global/list/entopic_images = list() my_image.mouse_opacity = 0 my_image.invisibility = 101 + my_image.alpha = 0 + my_image.override = FALSE + +////////////////////////////////////// +// Debug helper stuff +/obj/item/entopic_debug + name = "Entopic Debugger" + desc = "You shouldn't see this..." + icon = 'icons/obj/machines/ar_elements.dmi' + icon_state = "proj0" + + var/datum/entopic/ent_debug + +/obj/item/entopic_debug/New() + ..() + ent_debug = new(aholder = src, aicon = icon, aicon_state = "holo_Jin") + +/proc/entopic_icon_helper(var/atom/A,var/holo = TRUE) + ASSERT(A) + + var/icon/CI = getCompoundIcon(A) + var/icon/HI = getHologramIcon(CI) + + usr << ftp(holo ? HI : CI,"[A.name].dmi") diff --git a/code/modules/mob/dead/observer/login.dm b/code/modules/mob/dead/observer/login.dm index d3d65faa31..121a7643ea 100644 --- a/code/modules/mob/dead/observer/login.dm +++ b/code/modules/mob/dead/observer/login.dm @@ -4,4 +4,5 @@ plane_holder.set_vis(VIS_GHOSTS, ghostvision) plane_holder.set_vis(VIS_FULLBRIGHT, !seedarkness) plane_holder.set_vis(VIS_AI_EYE, TRUE) + plane_holder.set_vis(VIS_AUGMENTED, TRUE) //VOREStation Add - GHOST VISION IS AUGMENTED plane = PLANE_GHOSTS diff --git a/code/modules/mob/living/carbon/human/human_vr.dm b/code/modules/mob/living/carbon/human/human_vr.dm new file mode 100644 index 0000000000..f12836ad3d --- /dev/null +++ b/code/modules/mob/living/carbon/human/human_vr.dm @@ -0,0 +1,13 @@ +//Crazy alternate human stuff +/mob/living/carbon/human/New() + . = ..() + + var/animal = pick("cow","chicken_brown", "chicken_black", "chicken_white", "chick", "mouse_brown", "mouse_gray", "mouse_white", "lizard", "cat2", "goose", "penguin") + var/image/img = image('icons/mob/animal.dmi', src, animal) + img.override = TRUE + add_alt_appearance("animals", img, displayTo = alt_farmanimals) + +/mob/living/carbon/human/Destroy() + alt_farmanimals -= src + + . = ..() diff --git a/code/modules/mob/login_vr.dm b/code/modules/mob/login_vr.dm new file mode 100644 index 0000000000..a9ce4bd51d --- /dev/null +++ b/code/modules/mob/login_vr.dm @@ -0,0 +1,6 @@ +/mob/Login() + . = ..() + + if(viewing_alternate_appearances && viewing_alternate_appearances.len) + for(var/datum/alternate_appearance/AA in viewing_alternate_appearances) + AA.display_to(list(src)) diff --git a/code/modules/mob/mob_planes.dm b/code/modules/mob/mob_planes.dm index 437d70914b..a9b36bc6d3 100644 --- a/code/modules/mob/mob_planes.dm +++ b/code/modules/mob/mob_planes.dm @@ -37,7 +37,7 @@ /datum/plane_holder/Destroy() my_mob = null - plane_masters.Cut() //Goodbye my children, be free + qdel_null_list(plane_masters) //Goodbye my children, be free //VOREStation Edit - Need to qdel these now return ..() /datum/plane_holder/proc/set_vis(var/which = null, var/state = FALSE) diff --git a/code/modules/mob/mob_planes_vr.dm b/code/modules/mob/mob_planes_vr.dm index 55dba8e0a4..7883c9ccfb 100644 --- a/code/modules/mob/mob_planes_vr.dm +++ b/code/modules/mob/mob_planes_vr.dm @@ -5,4 +5,39 @@ plane_masters[VIS_CH_BACKUP] = new /obj/screen/plane_master{plane = PLANE_CH_BACKUP} //Backup implant status plane_masters[VIS_CH_VANTAG] = new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags - plane_masters[VIS_AUGMENTED] = new /obj/screen/plane_master{plane = PLANE_AUGMENTED} //Augmented reality \ No newline at end of file + plane_masters[VIS_AUGMENTED] = new /obj/screen/plane_master/augmented(my_mob) //Augmented reality + +///////////////// +//AR planemaster does some special image handling +/obj/screen/plane_master/augmented + plane = PLANE_AUGMENTED + var/state = FALSE //Saves cost with the lists + var/mob/my_mob + +/obj/screen/plane_master/augmented/New(var/mob/M) + ..() + my_mob = M + logged_in_event.register(my_mob,src,/obj/screen/plane_master/augmented/proc/apply) + +/obj/screen/plane_master/augmented/Destroy() + logged_in_event.unregister(my_mob,src) + my_mob = null + return ..() + +/obj/screen/plane_master/augmented/set_visibility(var/want = FALSE) + . = ..() + state = want + apply() + +/obj/screen/plane_master/augmented/proc/apply() + if(!my_mob.client) + return + + if(state) + entopic_users |= my_mob + if(my_mob.client) + my_mob.client.images |= entopic_images + else + entopic_users -= my_mob + if(my_mob.client) + my_mob.client.images -= entopic_images diff --git a/code/modules/nifsoft/nif_softshop.dm b/code/modules/nifsoft/nif_softshop.dm index e58ab917cf..1ac271036d 100644 --- a/code/modules/nifsoft/nif_softshop.dm +++ b/code/modules/nifsoft/nif_softshop.dm @@ -3,15 +3,50 @@ name = "NIFSoft Shop" desc = "For all your mindware and mindware accessories." product_ads = "Let us get into your head!;Looking for an upgrade?;Surpass Humanity!;Why be normal when you can be SUPERnormal?;Jack in with NIFSoft!" - icon_state = "nifsoft" - icon_vend = "nifsoft-purchase" - icon_deny = "nifsoft-problem" + + icon = 'icons/obj/machines/ar_elements.dmi' + icon_state = "proj" + icon_vend = "beacon_yes" + icon_deny = "beacon_no" + products = list() contraband = list() premium = list() var/global/list/starting_legal_nifsoft var/global/list/starting_illegal_nifsoft + density = 0 + opacity = 0 + var/datum/entopic/entopic + +/obj/machinery/vending/nifsoft_shop/initialize() + . = ..() + entopic = new(aholder = src, aicon = icon, aicon_state = "beacon") + +/obj/machinery/vending/nifsoft_shop/Destroy() + qdel_null(entopic) + return ..() + +/obj/machinery/vending/nifsoft_shop/power_change() + ..() + if(stat & BROKEN) + icon_state = "[initial(icon_state)]-broken" + entopic.hide() + else + if(!(stat & NOPOWER)) + icon_state = initial(icon_state) + entopic.show() + else + spawn(rand(0, 15)) + icon_state = "[initial(icon_state)]-off" + entopic.hide() + +/obj/machinery/vending/nifsoft_shop/malfunction() + stat |= BROKEN + icon_state = "[initial(icon_state)]-broken" + entopic.hide() + return + // Special Treatment! /obj/machinery/vending/nifsoft_shop/build_inventory() //Firsties @@ -62,7 +97,7 @@ var/mob/living/carbon/human/H = user if(!H.nif || !H.nif.stat == NIF_WORKING) to_chat(H,"[src] seems unable to connect to your NIF...") - flick(icon_deny,src) + flick(icon_deny,entopic.my_image) return FALSE return ..() @@ -90,7 +125,7 @@ if((href_list["vend"]) && (vend_ready) && (!currently_vending)) if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH usr << "Access denied." //Unless emagged of course - flick(icon_deny,src) + flick(icon_deny,entopic.my_image) return var/key = text2num(href_list["vend"]) @@ -107,7 +142,7 @@ var/list/usr_access = usr.GetAccess() if(!has_access(soft_access, list(), usr_access) && !emagged) usr << "You aren't authorized to buy [initial(path.name)]." - flick(icon_deny,src) + flick(icon_deny,entopic.my_image) return if(R.price <= 0) @@ -138,7 +173,7 @@ var/mob/living/carbon/human/H = user if((!allowed(usr)) && !emagged && scan_id && istype(H)) //For SECURE VENDING MACHINES YEAH usr << "Purchase not allowed." //Unless emagged of course - flick(icon_deny,src) + flick(icon_deny,entopic.my_image) return vend_ready = 0 //One thing at a time!! status_message = "Installing..." @@ -171,7 +206,7 @@ spawn(vend_delay) R.amount-- new R.item_path(H.nif) - flick(icon_vend,src) + flick(icon_vend,entopic.my_image) if(has_logs) do_logging(R, user, 1) diff --git a/code/modules/nifsoft/software/01_vision.dm b/code/modules/nifsoft/software/01_vision.dm index 5368636a7c..2ce33c1c88 100644 --- a/code/modules/nifsoft/software/01_vision.dm +++ b/code/modules/nifsoft/software/01_vision.dm @@ -5,8 +5,8 @@ desc = "Provides a general identification and health status overlay on your vision with no frills." list_pos = NIF_CIVILIAN_AR cost = 500 - a_drain = 0.05 - planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR) + a_drain = 0.01 + planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_AUGMENTED) vision_flags = (NIF_V_AR_CIVILIAN) incompatible_with = list(NIF_MEDICAL_AR,NIF_SECURITY_AR,NIF_ENGINE_AR,NIF_SCIENCE_AR,NIF_OMNI_AR) @@ -16,8 +16,8 @@ list_pos = NIF_MEDICAL_AR cost = 750 access = access_medical - a_drain = 0.05 - planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_STATUS_R,VIS_CH_BACKUP) + a_drain = 0.01 + planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_STATUS_R,VIS_CH_BACKUP,VIS_AUGMENTED) vision_flags = (NIF_V_AR_MEDICAL) incompatible_with = list(NIF_CIVILIAN_AR,NIF_SECURITY_AR,NIF_ENGINE_AR,NIF_SCIENCE_AR,NIF_OMNI_AR) @@ -27,8 +27,8 @@ list_pos = NIF_SECURITY_AR cost = 750 access = access_security - a_drain = 0.05 - planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_WANTED) + a_drain = 0.01 + planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_WANTED,VIS_AUGMENTED) vision_flags = (NIF_V_AR_SECURITY) incompatible_with = list(NIF_CIVILIAN_AR,NIF_MEDICAL_AR,NIF_ENGINE_AR,NIF_SCIENCE_AR,NIF_OMNI_AR) @@ -38,8 +38,8 @@ list_pos = NIF_ENGINE_AR cost = 750 access = access_engine - a_drain = 0.05 - planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR) + a_drain = 0.01 + planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_AUGMENTED) vision_flags = (NIF_V_AR_ENGINE) incompatible_with = list(NIF_CIVILIAN_AR,NIF_MEDICAL_AR,NIF_SECURITY_AR,NIF_SCIENCE_AR,NIF_OMNI_AR) @@ -49,8 +49,8 @@ list_pos = NIF_SCIENCE_AR cost = 750 access = access_research - a_drain = 0.05 - planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR) + a_drain = 0.01 + planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_AUGMENTED) vision_flags = (NIF_V_AR_SCIENCE) incompatible_with = list(NIF_CIVILIAN_AR,NIF_MEDICAL_AR,NIF_SECURITY_AR,NIF_ENGINE_AR,NIF_OMNI_AR) @@ -60,10 +60,11 @@ list_pos = NIF_OMNI_AR cost = 750 access = access_captain - a_drain = 0.05 - planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_STATUS_R,VIS_CH_BACKUP,VIS_CH_WANTED) + a_drain = 0.01 + planes_enabled = list(VIS_CH_ID,VIS_CH_HEALTH_VR,VIS_CH_STATUS_R,VIS_CH_BACKUP,VIS_CH_WANTED,VIS_AUGMENTED) vision_flags = (NIF_V_AR_OMNI) incompatible_with = list(NIF_CIVILIAN_AR,NIF_MEDICAL_AR,NIF_SECURITY_AR,NIF_ENGINE_AR,NIF_SCIENCE_AR) + ////////////// // Misc Vision /datum/nifsoft/corrective diff --git a/code/modules/nifsoft/software/13_soulcatcher.dm b/code/modules/nifsoft/software/13_soulcatcher.dm index 7dbf0f9d5f..e8d14ab902 100644 --- a/code/modules/nifsoft/software/13_soulcatcher.dm +++ b/code/modules/nifsoft/software/13_soulcatcher.dm @@ -5,6 +5,7 @@ #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! @@ -15,9 +16,8 @@ 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 - other_flags = (NIF_O_SCOTHERS) // Default on when installed, clear when uninstalled - var/setting_flags = (NIF_SC_CATCHING_OTHERS|NIF_SC_ALLOW_EARS|NIF_SC_ALLOW_EYES|NIF_SC_BACKUPS) + 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'." @@ -44,6 +44,7 @@ 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 @@ -73,23 +74,36 @@ to_chat(CS,"\[\icon[nif.big_icon]NIF\] Soulcatcher displays, \"[message]\"") brainmob << sound - proc/say_into(var/message, var/mob/living/sender) - var/sender_name = sender.name + proc/say_into(var/message, var/mob/living/sender, var/mob/eyeobj) + var/sender_name = eyeobj ? eyeobj.name : sender.name log_nsay("[sender_name]/[sender.key] : [message]",nif.human) - to_chat(nif.human,"\[\icon[nif.big_icon]NIF\] [sender_name] speaks, \"[message]\"") - for(var/brainmob in brainmobs) - var/mob/living/carbon/brain/caught_soul/CS = brainmob - to_chat(CS,"\[\icon[nif.big_icon]NIF\] [sender_name] speaks, \"[message]\"") + //AR Projecting + if(eyeobj) + sender.eyeobj.visible_message("[sender_name] says, \"[message]\"") - proc/emote_into(var/message, var/mob/living/sender) - var/sender_name = sender.name + //Not AR Projecting + else + log_nsay("[sender_name]/[sender.key] : [message]",nif.human) + to_chat(nif.human,"\[\icon[nif.big_icon]NIF\] [sender_name] speaks, \"[message]\"") + for(var/brainmob in brainmobs) + var/mob/living/carbon/brain/caught_soul/CS = brainmob + to_chat(CS,"\[\icon[nif.big_icon]NIF\] [sender_name] speaks, \"[message]\"") + + proc/emote_into(var/message, var/mob/living/sender, var/mob/eyeobj) + var/sender_name = eyeobj ? eyeobj.name : sender.name log_nme("[sender_name]/[sender.key] : [message]",nif.human) - to_chat(nif.human,"\[\icon[nif.big_icon]NIF\] [sender_name] [message]") - for(var/brainmob in brainmobs) - var/mob/living/carbon/brain/caught_soul/CS = brainmob - to_chat(CS,"\[\icon[nif.big_icon]NIF\] [sender_name] [message]") + //AR Projecting + if(eyeobj) + sender.eyeobj.visible_message("[sender_name] [message]") + + //Not AR Projecting + else + to_chat(nif.human,"\[\icon[nif.big_icon]NIF\] [sender_name] [message]") + for(var/brainmob in brainmobs) + var/mob/living/carbon/brain/caught_soul/CS = brainmob + to_chat(CS,"\[\icon[nif.big_icon]NIF\] [sender_name] [message]") proc/show_settings(var/mob/living/carbon/human/H) set waitfor = FALSE @@ -99,6 +113,7 @@ "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 @@ -252,6 +267,10 @@ var/obj/item/device/nif/nif var/datum/nifsoft/soulcatcher/soulcatcher +/mob/living/carbon/brain/caught_soul/Login() + ..() + plane_holder.set_vis(VIS_AUGMENTED, TRUE) + /mob/living/carbon/brain/caught_soul/Destroy() if(soulcatcher) soulcatcher.notify_into("Mind unloaded: [name]") @@ -259,6 +278,9 @@ soulcatcher = null if(nif) nif = null + if(eyeobj) + reenter_soulcatcher() + qdel_null(eyeobj) container = null return ..() @@ -274,13 +296,15 @@ life_tick++ - if(!client && ++client_missing == 300) - qdel(src) + 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 @@ -317,10 +341,22 @@ 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(parent_mob) return ..() if(silent) return FALSE - soulcatcher.say_into(message,src) + soulcatcher.say_into(message,src,eyeobj) /mob/living/carbon/brain/caught_soul/emote(var/act,var/m_type=1,var/message = null) if(parent_mob) return ..() @@ -342,7 +378,7 @@ /mob/living/carbon/brain/caught_soul/custom_emote(var/m_type, var/message) if(silent) return FALSE - soulcatcher.emote_into(message,src) + soulcatcher.emote_into(message,src,eyeobj) /mob/living/carbon/brain/caught_soul/resist() set name = "Resist" @@ -350,6 +386,69 @@ to_chat(src,"There's no way out! You're stuck in VR.") +/////////////////// +//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)) + 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() + parent_human = null + moved_event.unregister(parent_human, src) + 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) @@ -364,7 +463,6 @@ var/datum/nifsoft/soulcatcher/SC = H.nif.imp_check(NIF_SOULCATCHER) SC.catch_mob(H) - return TRUE /////////////////// @@ -411,3 +509,70 @@ 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,"You're already projecting in AR!") + return + + if(!(soulcatcher.setting_flags & NIF_SC_PROJECTING)) + to_chat(src,"Projecting from this NIF has been disabled!") + 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,"You're not projecting into AR!") + 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,"You're not projecting into AR!") + return + + moved_event.unregister(nif.human, eyeobj) + qdel(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) diff --git a/code/modules/nifsoft/software/15_misc.dm b/code/modules/nifsoft/software/15_misc.dm index e62e303235..9c8d6d7f0e 100644 --- a/code/modules/nifsoft/software/15_misc.dm +++ b/code/modules/nifsoft/software/15_misc.dm @@ -148,3 +148,30 @@ stat_text() return "Change Size" + +/datum/nifsoft/worldbend + name = "World Bender" + desc = "Alters your perception of various objects in the world. Only has one setting for now: displaying all your crewmates as farm animals." + list_pos = NIF_WORLDBEND + cost = 200 + a_drain = 0.01 + + activate() + if((. = ..())) + var/list/justme = list(nif.human) + for(var/human in human_mob_list) + if(human == nif.human) + continue + var/mob/living/carbon/human/H = human + H.display_alt_appearance("animals", justme) + alt_farmanimals += nif.human + + deactivate() + if((. = ..())) + var/list/justme = list(nif.human) + for(var/human in human_mob_list) + if(human == nif.human) + continue + var/mob/living/carbon/human/H = human + H.hide_alt_appearance("animals", justme) + alt_farmanimals -= nif.human diff --git a/icons/obj/machines/ar_elements.dmi b/icons/obj/machines/ar_elements.dmi index 6259e32c4c..48df856990 100644 Binary files a/icons/obj/machines/ar_elements.dmi and b/icons/obj/machines/ar_elements.dmi differ diff --git a/vorestation.dme b/vorestation.dme index 88a0cbf137..d787515f9a 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1575,6 +1575,7 @@ #include "code\modules\economy\price_list.dm" #include "code\modules\economy\retail_scanner.dm" #include "code\modules\economy\TradeDestinations.dm" +#include "code\modules\entopics_vr\alternate_appearance.dm" #include "code\modules\entopics_vr\entopics.dm" #include "code\modules\error_handler\_defines.dm" #include "code\modules\error_handler\error_handler.dm" @@ -1800,6 +1801,7 @@ #include "code\modules\mob\holder.dm" #include "code\modules\mob\inventory.dm" #include "code\modules\mob\login.dm" +#include "code\modules\mob\login_vr.dm" #include "code\modules\mob\logout.dm" #include "code\modules\mob\mob.dm" #include "code\modules\mob\mob_defines.dm" @@ -1927,6 +1929,7 @@ #include "code\modules\mob\living\carbon\human\human_powers.dm" #include "code\modules\mob\living\carbon\human\human_species.dm" #include "code\modules\mob\living\carbon\human\human_species_vr.dm" +#include "code\modules\mob\living\carbon\human\human_vr.dm" #include "code\modules\mob\living\carbon\human\inventory.dm" #include "code\modules\mob\living\carbon\human\life.dm" #include "code\modules\mob\living\carbon\human\life_vr.dm"