From 8225d30b9e3ef02fa85e7e20fe15db7a9833ce02 Mon Sep 17 00:00:00 2001 From: Arokha Sieyes Date: Sat, 20 Jan 2018 22:09:21 -0500 Subject: [PATCH] VS: AR Entopics and Soulcatcher projecting (+Worldbender) --- code/__defines/_planes+layers_vr.dm | 2 +- code/__defines/nifsoft.dm | 3 +- code/modules/clothing/glasses/hud_vr.dm | 6 +- .../entopics_vr/alternate_appearance.dm | 151 +++++++++++++ code/modules/entopics_vr/entopics.dm | 94 ++++++-- code/modules/mob/dead/observer/login.dm | 1 + .../mob/living/carbon/human/human_vr.dm | 13 ++ code/modules/mob/login_vr.dm | 6 + code/modules/mob/mob_planes.dm | 2 +- code/modules/mob/mob_planes_vr.dm | 37 +++- code/modules/nifsoft/nif_softshop.dm | 51 ++++- code/modules/nifsoft/software/01_vision.dm | 25 +-- .../nifsoft/software/13_soulcatcher.dm | 203 ++++++++++++++++-- code/modules/nifsoft/software/15_misc.dm | 27 +++ icons/obj/machines/ar_elements.dmi | Bin 7593 -> 11051 bytes vorestation.dme | 3 + 16 files changed, 566 insertions(+), 58 deletions(-) create mode 100644 code/modules/entopics_vr/alternate_appearance.dm create mode 100644 code/modules/mob/living/carbon/human/human_vr.dm create mode 100644 code/modules/mob/login_vr.dm 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 6259e32c4c5f2a6015e47f35738abf60da655ca7..48df8569908410abee40af3680ae7aff063f3791 100644 GIT binary patch literal 11051 zcmcI~2{@G9|My5zBxFmnBvB|8A=@ZCNEu1VmP$z0>@sGgWGibFVkAps-EjuCW zkg;VM#x`TN_l%yN=lMPF@BLrz^Vr!s z#Vc+!C{)cisqbg4*>&=q4$n!uYg0=WcXo&H+^c$spRwLndV00w$>f6KS%yH;eX|zOG^pz8A`{9>e8)ZH`dBSB7eYaKk^Jli1 za3Xw|_goiS6S6MB_?EuL_2XT)UKY)lHY@%it{Wws#$e&)cQZo-J>yr-_Z`tu)zt2M zU+K)~F`pE9m63T*BDFc~Rguu{hv~6$iZz_GpOv3J5WZ9qHqS-jtjH56{^kgQh(L5T zFB*BjT^d6=2=*s!t>(YaxJ2wv5m&$NBXuIe_?_V`=02!5ufuuW#^M~4GR1@a@@Yky zWv-_2qD4!dBbrXtW2bI0ef;u6_qe@Tm8saLk2#d?yvyc|-J1~uk>Z9IJx-n|<-Yt~ zQu+YrWy$5W=8e(zB;~E~_)52#c4G3D-X)g7!7bU@x4yFrvR*S+1{WtAc0ts8ZVrt@ zApWTFnCaI|wlk8CBB0*0;d!0%%%|^=DNO{@sjgMrWw*V{6JL(SvJE=LuzMl(^A=6A zNkf&5PQ<0&avv^9db2~ck7Wp5>ixDb4=8CYUI4qOhq*)MVQr#qSkO**eIkWbp;T*r z+Ei}GBXv}%SqJKJ&CsTrnqaKxz{>Zf&3rTA@{5rv>{Gb%J7gLdhiyvuluozAA)4|y zMXQ0J&1z_v#nO#oLzd-LC7CV8xrL3z2TTezVVqx}F;`wdC5}QMIddN%7DL6~T;`_V zWi{VJrv#{hFApKn(`TviEZtzr^CORpmuMu<(Hn`ONtU&*rjJi@fFaPzZW;{)+HyOa zXgz^6F@Hlr;RUVlqZ4n``V{J?bOj{y?)J;oErBVVf_>&)Mo1)|{-p<#;2x695<=J9 zu9%tmUg;aK93HkxD5FYR`JT&tmU6@WVdcZVn?nVy0|V~*|7_s;PW4ED*;zGNV;@qT zb~^3LYE|>BFZ2B+0;N+BGcX|3M_-GCo8H}jpSq;0w)LK@W@qhvyQfOnOTH)6IVZ1&o|l$+pR1Z-w;iQLk8ila#O3I4-U@x@B^$4Qjbi?QT{b1M{I=@xg@Jsh zTi}iVdON+p8nG_j-Lo4~P~XZQ$$DMyO#^}Sa&@pFi{HQn=9;&%$+d$6i;8;TRz(j% za1lSpGtTO!t>+WPgKyjc+#C-TTo7P6I67g(@FRI0VMRym!juuiF38-Z``?$UyIOZ~ z*VHS2nh@Gb8;n@pGTUIGZLj9vp6nu2H)R!1?0WlrUSS7FLi)TS5P#BJmEFt`7h$Ho zkULEDLtu=39Wh+yE}aoq`v`6a12h6k3&s&E*XE&*J}uj>)i4%$k`WS^XFB4CX#E(H zaph_?te>)o9UpU@A4lKaVFHY{fU%}Dz`ju&h@XXs8%tiw3e+P3ZaM|LH)$bLZ1#7x zSP!o6Yoayb)cVg*djfX*1*}@qR=9Skke33v@T|0eOlO-D8CpbqUnVcX$1MVJ`36I5 zCoEl^+so8)Hz#nK{v?N+P`j`x#PKK3OAEjfYJ!e%7gyZ!^Hpf2S9$Oms@g5Jg3P<* z*X)a&oLfz(;)x?^^Kw_xns=V>x<3SR^VK%TsK)h(8wd1NetbLIaq|}{(tl&9RU_-> zrC|M2#*V|10`fz{37vNK5q87ddVc}^lHGy2mtE~QZeungT$`)WAAHGxS8e@W+_ZFXrF(EW~v{2)IUGJtl9dKcJDzqiBxXGV^mp;ujO*uNje z3mo-RDhema!P$gime^W$Iz)@{^$OcNg?l>9=zF*c z36RaH3#G>AG5(Odf<8;7v(jcs&H)0!*X! zZ!clV%h;RiC*XK)KLG`Vel^}%mU{Bh-qTE6_DAak!5cGuiCho3BBsG``DhhyueLnW zNNtA>%uH6N^7CC`~7g!AT z_~Zrd-a11?D3^clAk02X_dYlAd(vwfKt^u$;Qt~)>dc#rf9fNBU3q#eJ@``p$c+0a z?-=v->YpWzx~m3uM^xRuXm9JXNf_S|H3{H*uR@Pg0JzD%U$Q+_S;sWf7+<` zNWrx{#1vxlkHC#V>%_Oo7$1q6R;q&iNsM%8LZOof;N7l>$9K~GCyLtXY)ak?=w9Mc$ z%dO_PF~U>(?=NlM)1S_{=JDl$T+6Y7#fp#rqT<<(Kahpo?2ykaPOVEK2Tl<{&`r!( z&4gS?>sOrzY8ACQf}2TR4+X%oKTna`(i z#uBNKYIy(w-jcmBQ3E|khm#Fi^`HVZ0~RCya@TIf7az%!=U5^e=ok?gP?$>+be)U%H9*q81H0v$kJy^7Jt-32KhGQ341|7?}Kb=f<8SlYf`zqdn(Q8c@MmTlD z#r33+e#1K5uQXY*OR#c4KKlhCnAf|%S;ao(ig0-$fApUK1X9^p+C1l_-jjvTzG`OO zARZIq^p~Ic6|s$@HxDWARsg2O&a)Ap?~G2ID&?G#b&ItzCeS?RM>>B6{-w24x&o6v zi8)5}@Efd$T61P8`!a2$8WX~dx>h)~W$=S^2jF*mXX#O|#g@(@4to-~b>sBxV06j; zM-*8ao>~w50D*Y%qZs+b073*@ZgzN3ubuX5mWc9=ZbL0D*>g+k4l zUorglp5Ufn9a(A_0pu>yakq1bnwM6reYUo<)EH-tK8Ukfz+#T z2-$e$1u|R1<>L337{Bbhr_vr=3{a~hY@rm#e;X7ek$FpwEWLbo?%qA}bsmv{OL#CB zVB((&_B^*QZv`Wo!{_&LO?6$~3o%qi!*%ZyUpZ8GCVnDeWQN9%a7*W};^w3k|Lo_n zV63nRKZHbLcPx8rO|`&4y%OED6!1o~gE@m3Q|qO!c?c{nH9UQk>OPOuvOrz#oqkI>C)PuBD=+?$#8 zUHD~?e*v*AaMNY4QzN0>T&s_T9rPUj`xHpB>y9f2rZ_lwJ)|Wdsbl`lU*^Q}mpK94 zs_YhGG0-GzR`uAMoBxMF`7bWq{lBafbN_ABWuczk|sC zjRmh*^8Zh{1)cWqm|Iy9zKpmtJHXBlx-OeCk&HE;#AV(g1OF{Rv?6aj`l*yMA;jGy zMW&}|++uTFFOcgjIFPupDT~cD?3nIQM7*a{VYO$h%=*8is|qOUUB6=h-t0RjoAg#% z9ax7vGs9HpW{Z9)a-eT7=}xUz%3U(Zf;6A4ZZS-OdDzx5{k4*+pbG@Db-`!v0my_J zpn>AO6hPL|>;E`e%G%3Wm5Xz z*o3myBgJ{cO|O`^S3Yz1ppiLL3SCVH!uG z3ZFwC&|6gu?sK81I=Mq9yR_Q<@tv8VXk(SCmGa?7j29w{y-rnbcR4YDqtke-zGi`6-hoYvh`)$AWAWqJTUCS<>NDbn>`QP&f@ex^q zv*m|pG*wco^I@q=V363l*48}mF>Silb>}!4rx8|cAu3wu7J#wa8cx5k6O#U?Jlfci zVz?CW6$ne4n?j9P^`Lai(CgYsb0pIevHm?$N>mhuo)36ySt~Y3YmCt^Yc8o+<;zNT znY;&D?CUh-i5hJ}Pu6$EUQfB&{_F>ft^vFZx5&#G#TR}9cUge@-A%N>jck4ckir$6 z@hYL7Y##T5{9{Q}Wo&rw%qrLNwfd_3PU%Fki^lN(7ZQu7@ z&%*0%2^wI+tFaAZD0*EcZ@H{G55&ZnfN5(XKX@2@)yvh;rOWPCgXZ2;Et67$0DU~E z##xh*M5BjwARx0FhXnUc$+-HEKpvNXAz&)RhpYrcJMV};e=gN5L`ac-Tai9l$tvL# zWyKCJFip9+Utiy|l%)T`ooO$X1*s18on>^LB=SwyugRE>rgr93&hIgC>tn-zZ!dos z5$IL)f$s&49tOf$FG6FB5H_id8qpqb)Fum*S1E*?V+1x zql0TuQB|7#w2Y3zYkoQ@^!I;~c6|rCO>N&0W$aIq4w^_vM9<0-@lSqE4z9Jmew)m| zG$MREH+5Q$A-nq;SrVL_5ar71sXg zBq`a<$=fOV$FXSFJ=~))$x>tr_Y0&;<2Dc-`kH@DNOW@94D}G>Q=l?5p$~b;M#h?G z6ENa3npcZD&3fy(bUb*?SDuI6oM?pZjVT=dlj4eLb78mTm#_KTsCbFRg^KJz?(`%aZUw4fY z{ey$ywyS<%xkG7?&*1<_STg>&4?TOI9Cp;Vl>V9UT*Kkr!jqiQ=;{V?I7@e|s-CMg zjM85K%pbeNp4)l1`zhFBI)w+Q2W`j{mwOY|7tXE}wIk=C*adcH8?qyz+gGMb#bGo- zIf#6P=|n|6l%uvDb+Qss$1`46b&~>9GxL413hGkjQcf9n@d$PCHCYShFLrO}k*tX@ zqCgL3^%w?|%Hv)Kh~~j8kONuON5_%`?1Sn;B`^8RxPbzPV(PL|in78@8BGf!HGN)^ z>3AnhmGPm+V2$W|Jrd{IbA_yYcL4x|0In`|T*TD5zxcXCvpoz4{T&WWU8gT-g9-%wEeEuT`2UC;!nG@IcpGIX9JX#l)Ll;0S0nly zTHw!l14qZeYJ*$m){Pd0jeW2ZlInFqKf8Z8EQYI*aT6DO5FAejVKJ!L&$}J@-@bK7 z6jqVw+Kj<@A>P^$wT`05D)(V2S#g)&49Ltj|J1=r=s=@%p}%jQa1tl z;8B@W#1sAn{`OI-3f^%GO7vWt5^Gfmf#cV{!YG0UAE%y(hx6=VYmXMDjHz&sA@Hp- z*J~ZiMqr3q;we^x^?Y>5yUDMG%xWiqn%a3U*N2#4zcUKwj0Ee`SW1$Fll;;q`#qG-Uh!d1ZoUv76b($T= zh&^uS#3`Nq#4MhVE*L{#)rUk4_vk**UD)MDug0TO>~&1_!WkLmLbZ=x zwzRT(u*%MCOs=USb8HKW{A|5`kSD&o-$ot{3^S=F*TQH;n+CV(OXI1QawB^ew+D98 zDJovU8spZ+25nnw(5@XL+XUeQaBABJYQC=&tFW`ThrclTQS0IqC(ON|vNk0olTBmD zJ;;-y9&I%&4)w;4bg)}82+jst>HQI*CqdM2yN{@#y=OW*$Hl@PX`a1H%n-@fGU3t? z1*<`O?yX>wi5hA|EMsj8F8sq;<0pxic67qjU7oRs zVl2EP1&XJyGh|mEa-Kfq-N(AVUjzk5tudT3*{MMJC$X~-Y^-CHI8)w1mBel{E{RaHsV>^?5qS`Gj*BNU`%q_O~l3kO{7lS zD(ySE7xP;RL}FSbP;h*!7ZmEjz=D)`HDl{@6iK)fhnjwa^Ch)PU~FppyDY~Ic~X9} zb<}+UD9|7v?(0^45hP(^ZvC6F85Y@(4f5Xvay5uTXJClCBhouyeuq6d3a)A1zCa2O zHp;wLtgM|~ClwKY?yQ`7<#M*vec!o45gJd!kf>M^9wCuVW5Q$qh&+`1|r)O&V)WKQ|ecFBQaOk%LZ@F+hFGzAM$dHuO==&n zNm$6MN{u9od>nJzk42s*(`1gAMFW16!u30ejw2bLDA*WhS@d#ozZg1_VtJb=IL29; zlgYsAv1AA|<+M;5r38BV{cf<8Hh~G^wWVdvky9fvJ_v28qjIdLe=>GUqd$brCQS2r ztcomUQXWN&I3cf@E+Sbfy-RYIyiQ_T3{~WBUfH`w`T1xV=SA{s4rN-No8veFftVB? zmIq~yom$8L-$N(}=pd)C24s&OY>EVn4MM}(kPb8ehvrQoDN(4wed-s3^R`weZ0U`vi>oX$dJx0Tl@w?d zXybX_jwWkonQye&F+~f3kq6nMT>ugIGYJg+p5M#ED%m^kIG~9Shcy>Q7Ska+j{{&_lu! zhR_CkW&Sz0_A&gqZML&__WyKH&*}(&aip+@?ab3%yHnijwQOBnT~Qs5PcFnewX)H~ zh*GZv1NlL6s15&Vh8bRvbmm2Dr?@89cqd}uNd#l?LrQTZ~L z^3QW{zO#xKD)U>YjsrHKBKXhyb>h!0lG{oI?fGXMj)v|^ zGcfU_YAv}GE$&}yKeIu()vJLjYa04OdLcT^#}a9%29GRWgse%c>!P=Qy3fRJl(rF= z)#GM0Wb_-JUlXrYh!^C)aB%U9!(vM+ajDE@Re2Ty*+--QFThc6{ejvC8@?AkN8L<$ z+EvmW%@VjwQv{e=L@-dD4E^0F^d?)k58EYUvOhmV#jI;a$r0_!&*yI`7r*xgz~eEC z&nQyf@k+6U$#wP0jj`}PVKL0G@Tmv#!_LRhCQr^LVe;+-uElVFRlgmWy@;cIqT@2e z{PdoTwFWJTmIH0apl%E-%p=}hug;@Cn82zx`L2;or^B#=e3S9o3FL}F-4U4{6Igdf z4i2r~oZd$+N#J=`K~B>;5wT@s0;OpkN=p7IDGAM6(Uetg?K1KY_`IZCZB6Q24p+Ez z9l;sI{&kf4sZkIwSw)##1Tomp1iz-DVqHv`lpd#Hy>_^=v7c%S#5BFXuthXHDjK5( zb!v*%8nwUgh>Vjh#kcdd+Ri$-k!`jA2p4O`VV{M0ntRh?Q0CdO98Hh+(AK(tEL!H0 zt4}Wi%{5-X;FAc#$?og*-^q>Jvysjxk*-B@OE@g|T*Z%=blRE{|FMWw+ z_%*eCjq$+Eg{;YT`2WZ-ld{wSwdRm7#>1jr97iz@h-!YLVX`!aRI;5UM@(9Lme?U` zeh3*8^uzoC`Z?JqP^^n=B%152{?eMA(`Miy`t#$pyr&(Ah5 zeeRu^rSN(85PL8k!!)0br!X88AJ&R{aQxXFaqc4ssl&v^>E@*`SFo8wCS_k03bFdt zNAur8w{1wgQmQ_wXcp--uT7| z$q~=h)~8G46EU`FA?DQD&Tk7E3d_vc;B!mgiq6%zl~D$3Uz(5nIIVWxVm*afHYK{4 za`E&+=vN;aLZVWBFf+_4EO*g`)aI(p@d|8#pPDY^I(tI|Up04rJ3$v^TfFkc(YE+T zVVI=8uJPXT#!X@O584cu^n8v?DVV_V<3s5tMt$o`2ZlHN2HNos_jK>dqNE2e`w9dN;$%OjTFOcI zIQ1^g_%d?8lSUmky5=7l5^{Viu|{0^1-`h(syr#e0c@s?R?QYX&BOZUl@Il6*=C?uIXls80L`h_QZqzL>f|4#oqlmW*W0Tp;O4wQdr> z3>>XsUqr&RG_j=(NQcC+YYc}$U=I#HV*0l9+#Coqh(hAzF0KxlRLC<~_#Ew~))#jw z^Cmj8H#@lGtMgX%lXj*Pd)c`u;x1>QUFZX?U9V`uQbbh2E827{Ie(<3i;Ipjo_9Bi zTJ3Pt>CAWr>+J(4{^@qi+Z77ejze!CmK!Ck>4zl}^4}+E>*`_hm1To$y zapHvTnpQNAaMXUL5B+>kwBG)lyN4LJosL8)LCb%{Y)}-GR5vzMLSYg(TF-ozt;5Xh z6Y`HWOJ#C%UdrCmHrV62Q<2#are@2jj6`4|uA{P|%8}I|M!`L``O2f?m~Z?Su@aqK zxrF=eT}uUKab$HNS(HA0?T^|dvP><)dCcL&3L#H;01>x&ekAW1hpI4?T)bm^5aZ^6 zbbmg1bNUwWzlmRIKNhyWP8lO%YHRJZsAexp!FzIJZvJhvtf#?sg?dA9+v2MMs1D3!OkPj zEbh`Puvs$FX7=hhwDn}9cv&p@;l+I{S7PAr8*T4BAhhLn+Q@p;U!2=8OKy!DjCWF( z$_;I^52AgK_2hj;kaOtEJS5)pQ;Dl@WZ7&xQA{Z5pdxT!=BzjwhPto9&n1GSIAW+ z20a*}CVL}~sxk}e&1YQ}mv}euUl|DIxrHGgtT8L6#1Y7{YZ1r>MwtS0d}vYn1>fZDF6&(jroe3iKO*UobSU1Ar&&oRrh+uX?JcDJ4(LF z1T4Wt*h3D~X?fMx2_Q(FPD3D-sE?SgTsuy4rPgv2Nv@p{ynul|yr?(ir~B}%QfiNg zS_Mh$*yF2S>K!(_?uvWXVqYJFzPVbel*1>fCXTnVy%YtXqAzfT9m$MxMNcg<(+Ct> z9#bSlMe$)4$g!2;iNc8s;*rh@w5;7kSbT>t7iXpOprvpqRoYwHJA5BqrvMN0K&WD4 z+Wad&5xt`<++y~#cp?Cu*P#4v0wYevi=)knW~SK0H^eVk literal 7593 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 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"