From ac96197d7f8cddc2f0deacb00aba3f0c94e995ab Mon Sep 17 00:00:00 2001 From: Darlantan Date: Wed, 24 May 2023 08:42:09 -0400 Subject: [PATCH] VR code tweaks, mob TF, ghost joining, qdel to VR escapees --- code/_helpers/global_lists_ch.dm | 47 ++- code/_onclick/hud/_defines.dm | 7 +- code/_onclick/hud/ghost.dm | 24 +- .../machinery/virtual_reality/vr_console.dm | 3 +- .../human/species/virtual_reality/avatar.dm | 5 + code/modules/mob/living/life.dm | 2 + code/modules/mob/living/living_ch.dm | 2 - .../machinery/virtual_reality/vr_console.dm | 328 ++++++++++++++++++ .../modules/mob/dead/observer/observer.dm | 63 ++++ .../code/modules/mob/living/living.dm | 96 +++++ modular_chomp/icons/mob/screen_ghost.dmi | Bin 0 -> 30852 bytes vorestation.dme | 3 +- 12 files changed, 570 insertions(+), 10 deletions(-) delete mode 100644 code/modules/mob/living/living_ch.dm create mode 100644 modular_chomp/code/game/machinery/virtual_reality/vr_console.dm create mode 100644 modular_chomp/icons/mob/screen_ghost.dmi diff --git a/code/_helpers/global_lists_ch.dm b/code/_helpers/global_lists_ch.dm index 5bd21c42dd..89048a1169 100644 --- a/code/_helpers/global_lists_ch.dm +++ b/code/_helpers/global_lists_ch.dm @@ -36,4 +36,49 @@ var/global/list/item_digestion_blacklist = list( /obj/item/device/perfect_tele_beacon, /obj/item/organ/internal/brain/slime, /obj/item/device/mmi/digital/posibrain, - /obj/item/weapon/rig/protean) \ No newline at end of file + /obj/item/weapon/rig/protean) + +// Options for transforming into a different mob in virtual reality. +var/global/list/vr_mob_tf_options = list( + "Borg" = /mob/living/silicon/robot, + "Cortical borer" = /mob/living/simple_mob/animal/borer/non_antag, + "Hyena" = /mob/living/simple_mob/animal/hyena, + "Giant spider" = /mob/living/simple_mob/animal/giant_spider/thermic, + "Armadillo" = /mob/living/simple_mob/animal/passive/armadillo, + "Parrot" = /mob/living/simple_mob/animal/passive/bird/parrot, + "Cat" = /mob/living/simple_mob/animal/passive/cat, + "Corgi" = /mob/living/simple_mob/animal/passive/dog/corgi, + "Fox" = /mob/living/simple_mob/animal/passive/fox, + "Racoon" = /mob/living/simple_mob/animal/passive/raccoon_ch, + "Shantak" = /mob/living/simple_mob/animal/sif/shantak, + "Goose" = /mob/living/simple_mob/animal/space/goose, + "Space shark" = /mob/living/simple_mob/animal/space/shark, + "Synx" = /mob/living/simple_mob/animal/synx, + "Dire wolf" = /mob/living/simple_mob/animal/wolf/direwolf, + "Construct Artificer" = /mob/living/simple_mob/construct/artificer, + "Tech golem" = /mob/living/simple_mob/mechanical/technomancer_golem, + "Metroid" = /mob/living/simple_mob/metroid/juvenile/baby, + "Otie" = /mob/living/simple_mob/otie/cotie/chubby, + "Shadekin" = /mob/living/simple_mob/shadekin, + "Slime" = /mob/living/simple_mob/slime/xenobio/metal, + "Corrupt hound" = /mob/living/simple_mob/vore/aggressive/corrupthound, + "Deathclaw" = /mob/living/simple_mob/vore/aggressive/deathclaw/den, + "Mimic" = /mob/living/simple_mob/vore/aggressive/mimic/floor/plating, + "Giant rat" = /mob/living/simple_mob/vore/aggressive/rat, + "Catslug" = /mob/living/simple_mob/vore/alienanimals/catslug, + "Dust jumper" = /mob/living/simple_mob/vore/alienanimals/dustjumper, + "Space ghost" = /mob/living/simple_mob/vore/alienanimals/spooky_ghost, + "Teppi" = /mob/living/simple_mob/vore/alienanimals/teppi, + "Bee" = /mob/living/simple_mob/vore/bee, + //"Dragon" = /mob/living/simple_mob/vore/bigdragon/friendly, //Currently adds 12 bellies to the user when transformed into. Do not uncomment without fixing this. + "Riftwalker" = /mob/living/simple_mob/vore/demon/wendigo, + "Horse" = /mob/living/simple_mob/vore/horse/big, + "Morph" = /mob/living/simple_mob/vore/hostile/morph, + "Leopardmander" = /mob/living/simple_mob/vore/leopardmander, + "Rabbit" = /mob/living/simple_mob/vore/rabbit, + "Red panda" = /mob/living/simple_mob/vore/redpanda, + "Sect drone" = /mob/living/simple_mob/vore/sect_drone, + "Armalis vox" = /mob/living/simple_mob/vox/armalis, + "Xeno hunter" = /mob/living/simple_mob/xeno_ch/hunter, + "Xeno queen" = /mob/living/simple_mob/xeno_ch/queen/maid, + "Xeno sentinel" = /mob/living/simple_mob/xeno_ch/sentinel) diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index f1a7f22248..d1c17f532f 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -160,7 +160,10 @@ #define ui_genetic_master "EAST-1:16,NORTH-3:16" // Ghost ones -#define ui_ghost_returntomenu "SOUTH:6,CENTER-3:24" +// CHOMPedit +#define ui_ghost_returntomenu "SOUTH:6,CENTER-4:24" +// CHOMPedit +#define ui_ghost_vr "SOUTH: 6,CENTER-3:24" #define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24" #define ui_ghost_orbit "SOUTH:6,CENTER-1:24" #define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24" @@ -195,4 +198,4 @@ #define ui_mech_deco1_f "WEST+2:-7, SOUTH+8" #define ui_mech_deco2_f "WEST+2:-7, SOUTH+9" -#define ui_smallquad "EAST-4:22,SOUTH:5" \ No newline at end of file +#define ui_smallquad "EAST-4:22,SOUTH:5" diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm index 5120348488..399f736fdd 100644 --- a/code/_onclick/hud/ghost.dm +++ b/code/_onclick/hud/ghost.dm @@ -91,12 +91,25 @@ var/mob/observer/dead/G = usr G.zMove(DOWN) +// CHOMPedit start +/obj/screen/ghost/vr + name = "Enter VR" + desc = "Enter virtual reality." + icon = 'modular_chomp/icons/mob/screen_ghost.dmi' + icon_state = "entervr" + +/obj/screen/ghost/vr/Click() + ..() + var/mob/observer/dead/G = usr + G.fake_enter_vr() +// CHOMPedit end + /mob/observer/dead/create_mob_hud(datum/hud/HUD, apply_to_client = TRUE) ..() var/list/adding = list() HUD.adding = adding - + var/obj/screen/using using = new /obj/screen/ghost/returntomenu() using.screen_loc = ui_ghost_returntomenu @@ -138,6 +151,13 @@ using.hud = src adding += using + //CHOMPedit start + using = new /obj/screen/ghost/vr() + using.screen_loc = ui_ghost_vr + using.hud = src + adding += using + //CHOMPedit end + /* using = new /obj/screen/language_menu using.icon = ui_style @@ -173,4 +193,4 @@ if (istype(O) && O.observetarget) return . = ..() -*/ \ No newline at end of file +*/ diff --git a/code/game/machinery/virtual_reality/vr_console.dm b/code/game/machinery/virtual_reality/vr_console.dm index b66bc2dff8..6cf461dd0c 100644 --- a/code/game/machinery/virtual_reality/vr_console.dm +++ b/code/game/machinery/virtual_reality/vr_console.dm @@ -1,3 +1,5 @@ +//CHOMPedit: This file has been disabled and moved to the modular_chomp folder. Check that one if you're bug-fixing! + /obj/machinery/vr_sleeper name = "virtual reality sleeper" desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality." @@ -262,4 +264,3 @@ else occupant.enter_vr(avatar) - diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm index 0054bbb623..2326de811b 100644 --- a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm +++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm @@ -91,6 +91,11 @@ if(!vr_holder) return + if(tfed_into_mob_check()) //CHOMPedit start: make sure we're not TFed and revert if we are before checking for a mind. + var/mob/living/M = loc + if(istype(M)) // Sanity check, though shouldn't be needed since this is already checked by the proc. + M.revert_mob_tf() // CHOMPedit end + if(!mind) return diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index eb7462967e..86a9afb81e 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -74,6 +74,8 @@ handle_tf_holder() //VOREStation Addition + handle_vr_derez() // CHOMPedit + /mob/living/proc/handle_breathing() return diff --git a/code/modules/mob/living/living_ch.dm b/code/modules/mob/living/living_ch.dm deleted file mode 100644 index 5307dfedd0..0000000000 --- a/code/modules/mob/living/living_ch.dm +++ /dev/null @@ -1,2 +0,0 @@ -/mob/living/proc/handle_vorefootstep(m_intent, turf/T) - return FALSE \ No newline at end of file diff --git a/modular_chomp/code/game/machinery/virtual_reality/vr_console.dm b/modular_chomp/code/game/machinery/virtual_reality/vr_console.dm new file mode 100644 index 0000000000..592903efd7 --- /dev/null +++ b/modular_chomp/code/game/machinery/virtual_reality/vr_console.dm @@ -0,0 +1,328 @@ +/obj/machinery/vr_sleeper + name = "virtual reality sleeper" + desc = "A fancy bed with built-in sensory I/O ports and connectors to interface users' minds with their bodies in virtual reality." + icon = 'icons/obj/Cryogenic2.dmi' + icon_state = "body_scanner_0" + + var/base_state = "body_scanner_" + + density = TRUE + anchored = TRUE + circuit = /obj/item/weapon/circuitboard/vr_sleeper + var/mob/living/carbon/human/occupant = null + var/mob/living/carbon/human/avatar = null + var/datum/mind/vr_mind = null + var/datum/effect/effect/system/smoke_spread/bad/smoke + + var/eject_dead = TRUE + + var/mirror_first_occupant = TRUE // Do we force the newly produced body to look like the occupant? + + use_power = USE_POWER_IDLE + idle_power_usage = 15 + active_power_usage = 200 + light_color = "#FF0000" + //var/global/list/vr_mob_tf_options // Global var located in global_list_ch.dm + + +/obj/machinery/vr_sleeper/Initialize() + . = ..() + default_apply_parts() + +/obj/machinery/vr_sleeper/Initialize() + . = ..() + smoke = new + update_icon() + +/obj/machinery/vr_sleeper/Destroy() + . = ..() + go_out() + +/obj/machinery/vr_sleeper/process() + if(stat & (NOPOWER|BROKEN)) + if(occupant) + go_out() + visible_message("\The [src] emits a low droning sound, before the pod door clicks open.") + return + else if(eject_dead && occupant && occupant.stat == DEAD) // If someone dies somehow while inside, spit them out. + visible_message("\The [src] sounds an alarm, swinging its hatch open.") + go_out() + +/obj/machinery/vr_sleeper/update_icon() + icon_state = "[base_state][occupant ? "1" : "0"]" + +// CHOMPedit +/obj/machinery/vr_sleeper/examine(mob/user) + . = ..() + if(occupant) + . += "[occupant] is inside." + +/obj/machinery/vr_sleeper/Topic(href, href_list) + if(..()) + return 1 + + if(usr == occupant) + to_chat(usr, "You can't reach the controls from the inside.") + return + + add_fingerprint(usr) + + if(href_list["eject"]) + go_out() + + return 1 + +/obj/machinery/vr_sleeper/attackby(var/obj/item/I, var/mob/user) + add_fingerprint(user) + + if(occupant && (istype(I, /obj/item/device/healthanalyzer) || istype(I, /obj/item/device/robotanalyzer))) + I.attack(occupant, user) + return + + if(default_deconstruction_screwdriver(user, I)) + return + else if(default_deconstruction_crowbar(user, I)) + if(occupant && avatar) + avatar.exit_vr() + avatar = null + go_out() + return + + +/obj/machinery/vr_sleeper/MouseDrop_T(var/mob/target, var/mob/user) + if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user)|| !isliving(target)) + return + go_in(target, user) + + + +/obj/machinery/vr_sleeper/relaymove(var/mob/user) + ..() + if(user.incapacitated()) + return + go_out() + + + +/obj/machinery/vr_sleeper/emp_act(var/severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + if(occupant) + // This will eject the user from VR + // ### Fry the brain? Yes. Maybe. + if(prob(15 / ( severity / 4 )) && occupant.species.has_organ[O_BRAIN] && occupant.internal_organs_by_name[O_BRAIN]) + var/obj/item/organ/O = occupant.internal_organs_by_name[O_BRAIN] + O.take_damage(severity * 2) + visible_message("\The [src]'s internal lighting flashes rapidly, before the hatch swings open with a cloud of smoke.") + smoke.set_up(severity, 0, src) + smoke.start("#202020") + go_out() + + ..(severity) + +/obj/machinery/vr_sleeper/verb/eject() + set src in view(1) + set category = "Object" + set name = "Eject VR Capsule" + + if(usr.incapacitated()) + return + + var/forced = FALSE + + if(stat & (BROKEN|NOPOWER) || occupant && occupant.stat == DEAD) + forced = TRUE + + go_out(forced) + add_fingerprint(usr) + +/obj/machinery/vr_sleeper/verb/climb_in() + set src in oview(1) + set category = "Object" + set name = "Enter VR Capsule" + + if(usr.incapacitated()) + return + go_in(usr, usr) + add_fingerprint(usr) + +/obj/machinery/vr_sleeper/relaymove(mob/user as mob) + if(user.incapacitated()) + return 0 //maybe they should be able to get out with cuffs, but whatever + go_out() + +/obj/machinery/vr_sleeper/proc/go_in(var/mob/M, var/mob/user) + if(!M) + return + if(stat & (BROKEN|NOPOWER)) + return + if(!ishuman(M)) + to_chat(user, "\The [src] rejects [M] with a sharp beep.") + if(occupant) + to_chat(user, "\The [src] is already occupied.") + return + + if(M == user) + visible_message("\The [user] starts climbing into \the [src].") + else + visible_message("\The [user] starts putting [M] into \the [src].") + + if(do_after(user, 20)) + if(occupant) + to_chat(user, "\The [src] is already occupied.") + return + M.stop_pulling() + if(M.client) + M.client.perspective = EYE_PERSPECTIVE + M.client.eye = src + M.loc = src + update_use_power(USE_POWER_ACTIVE) + occupant = M + + update_icon() + + enter_vr() + return + +/obj/machinery/vr_sleeper/proc/go_out(var/forced = TRUE) + if(!occupant) + return + + if(!forced && avatar && tgui_alert(avatar, "Someone wants to remove you from virtual reality. Do you want to leave?", "Leave VR?", list("Yes", "No")) == "No") + return + + if(avatar) + avatar.exit_vr() + avatar = null + + if(occupant.client) + occupant.client.eye = occupant.client.mob + occupant.client.perspective = MOB_PERSPECTIVE + occupant.loc = src.loc + occupant = null + for(var/atom/movable/A in src) // In case an object was dropped inside or something + if(A == circuit) + continue + if(A in component_parts) + continue + A.loc = src.loc + update_use_power(USE_POWER_IDLE) + update_icon() + +/obj/machinery/vr_sleeper/proc/enter_vr() + + // No mob to transfer a mind from + if(!occupant) + return + + // No mind to transfer + if(!occupant.mind) + return + + // Mob doesn't have an active consciousness to send/receive from + if(occupant.stat == DEAD) + return + + avatar = occupant.vr_link + // If they've already enterred VR, and are reconnecting, prompt if they want a new body + if(avatar && tgui_alert(occupant, "You already have a [avatar.stat == DEAD ? "" : "deceased "]Virtual Reality avatar. Would you like to use it?", "New avatar", list("Yes", "No")) == "No") + // Delink the mob + occupant.vr_link = null + avatar = null + + if(!avatar) + // Get the desired spawn location to put the body + var/S = null + var/list/vr_landmarks = list() + for(var/obj/effect/landmark/virtual_reality/sloc in landmarks_list) + vr_landmarks += sloc.name + + S = tgui_input_list(occupant, "Please select a location to spawn your avatar at:", "Spawn location", vr_landmarks) + if(!S) + return 0 + + //CHOMPedit: mob TF masquerading as mob spawning because that's somehow less spaghetti + var/tf = null + if(tgui_alert(occupant, "Would you like to play as a different creature?", "Join as a mob?", list("Yes", "No")) == "Yes") + var/k = tgui_input_list(occupant, "Please select a creature:", "Mob list", vr_mob_tf_options) + if(!k) + return 0 + tf = vr_mob_tf_options[k] + + for(var/obj/effect/landmark/virtual_reality/i in landmarks_list) + if(i.name == S) + S = i + break + + avatar = new(S, "Virtual Reality Avatar") + //CHOMPedit start: rewriting this to spawn a copy of the user and allow mob TF. + // I know this is a modular file now but perhaps keeping old comments will help with documentation. + if(mirror_first_occupant && occupant.client && occupant.client.prefs) + occupant.client.prefs.copy_to(avatar) + + avatar.forceMove(get_turf(S)) // Put the mob on the landmark, instead of inside it + occupant.enter_vr(avatar) + avatar.regenerate_icons() + avatar.update_transform() + avatar.species.equip_survival_gear(avatar) + avatar.verbs += /mob/living/carbon/human/proc/exit_vr + avatar.verbs += /mob/living/carbon/human/proc/vr_transform_into_mob + avatar.verbs |= /mob/living/proc/set_size // Introducing NeosVR + avatar.virtual_reality_mob = TRUE + + // Prompt for username after they've enterred the body. + var/newname = sanitize(tgui_input_text(avatar, "You are entering virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change", null, MAX_NAME_LEN), MAX_NAME_LEN) + if(newname) + avatar.real_name = newname + avatar.name = newname + + if(tf) + var/mob/living/new_form = avatar.transform_into_mob(tf, TRUE) // No need to check prefs when the occupant already chose to transform. + if(isliving(new_form)) // Make sure the mob spawned properly. + new_form.verbs += /mob/living/proc/vr_revert_mob_tf + new_form.virtual_reality_mob = TRUE + + else + // If TFed, revert TF. Easier than coding mind transfer stuff for edge cases. + if(avatar.tfed_into_mob_check()) + var/mob/living/M = loc + if(istype(M)) // Sanity check, though shouldn't be needed since this is already checked by the proc. + M.revert_mob_tf() + occupant.enter_vr(avatar) + +// I am not making a new file just for vr-specific mob procs. +/mob/living/carbon/human/proc/vr_transform_into_mob() + set name = "Transform Into Creature" + set category = "Abilities" + set desc = "Become a different creature" + + var/tf = null + var/k = tgui_input_list(usr, "Please select a creature:", "Mob list", vr_mob_tf_options) + if(!k) + return 0 + tf = vr_mob_tf_options[k] + + var/mob/living/new_form = transform_into_mob(tf, TRUE, TRUE) + if(isliving(new_form)) // Sanity check + new_form.verbs += /mob/living/proc/vr_revert_mob_tf + new_form.virtual_reality_mob = TRUE + +/mob/living/proc/vr_revert_mob_tf() + set name = "Revert Transformation" + set category = "Abilities" + + revert_mob_tf() + +// Exiting VR but for ghosts +/mob/living/carbon/human/proc/fake_exit_vr() + set name = "Log Out Of Virtual Reality" + set category = "Abilities" + + if(tgui_alert(usr, "Would you like to log out of virtual reality?", "Log out?", list("Yes", "No")) == "Yes") + release_vore_contents(TRUE) + for(var/obj/item/I in src) + drop_from_inventory(I) + qdel(src) +//CHOMPedit end diff --git a/modular_chomp/code/modules/mob/dead/observer/observer.dm b/modular_chomp/code/modules/mob/dead/observer/observer.dm index 5c9b519416..57f06022f2 100644 --- a/modular_chomp/code/modules/mob/dead/observer/observer.dm +++ b/modular_chomp/code/modules/mob/dead/observer/observer.dm @@ -6,3 +6,66 @@ if(body_backup) qdel(body_backup) ..() + +// Persistence vars not included as we probably don't want losing limbs in the game mean losing limbs in real life. Definitely can't backfire. +/mob/observer/dead/verb/fake_enter_vr() + set name = "Join virtual reality" + set category = "Ghost" + set desc = "Log into NanoTrasen's local virtual reality server." + + var/time_till_respawn = time_till_respawn() + if(time_till_respawn == -1) // Special case, never allowed to respawn + to_chat(usr, "Respawning is not allowed!") + return + if(time_till_respawn) // Nonzero time to respawn + to_chat(usr, "You can't do that yet! You died too recently. You need to wait another [round(time_till_respawn/10/60, 0.1)] minutes.") + return + + var/datum/data/record/record_found + record_found = find_general_record("name", client.prefs.real_name) + // Found their record, they were spawned previously. Remind them corpses cannot play games. + if(record_found) + var/answer = tgui_alert(src,"You seem to have previously joined this round. If you are currently dead, you should not enter VR as this character. Would you still like to proceed?","Previously spawned",list("Yes","No")) + if(answer != "Yes") + return + + var/S = null + var/list/vr_landmarks = list() + for(var/obj/effect/landmark/virtual_reality/sloc in landmarks_list) + vr_landmarks += sloc.name + + S = tgui_input_list(usr, "Please select a location to spawn your avatar at:", "Spawn location", vr_landmarks) + if(!S) + return 0 + for(var/obj/effect/landmark/virtual_reality/i in landmarks_list) + if(i.name == S) + S = i + break + + var/mob/living/carbon/human/avatar = new(get_turf(S), "Virtual Reality Avatar") + if(!avatar) + to_chat(src, "Something went wrong and spawning failed.") + return + + //Write the appearance and whatnot out to the character + var/client/C = client + C.prefs.copy_to(avatar) // Unfortunately the cascade of procs this calls will add the body to the transcore body DB. Don't see a simple way to prevent that. + avatar.key = key + for(var/lang in C.prefs.alternate_languages) + var/datum/language/chosen_language = GLOB.all_languages[lang] + if(chosen_language) + if(is_lang_whitelisted(usr,chosen_language) || (avatar.species && (chosen_language.name in avatar.species.secondary_langs))) + avatar.add_language(lang) + + avatar.regenerate_icons() + avatar.update_transform() + avatar.species.equip_survival_gear(avatar) + avatar.verbs += /mob/living/carbon/human/proc/fake_exit_vr + avatar.verbs += /mob/living/carbon/human/proc/vr_transform_into_mob + avatar.verbs |= /mob/living/proc/set_size // Introducing NeosVR + avatar.virtual_reality_mob = TRUE + log_and_message_admins("[key_name_admin(avatar)] joined virtual reality from the ghost menu.") + + var/newname = sanitize(tgui_input_text(avatar, "You are entering virtual reality. Your username is currently [src.name]. Would you like to change it to something else?", "Name change", null, MAX_NAME_LEN), MAX_NAME_LEN) + if(newname) + avatar.real_name = newname diff --git a/modular_chomp/code/modules/mob/living/living.dm b/modular_chomp/code/modules/mob/living/living.dm index 3a45d96a4f..76c36f6309 100644 --- a/modular_chomp/code/modules/mob/living/living.dm +++ b/modular_chomp/code/modules/mob/living/living.dm @@ -10,6 +10,7 @@ var/pain_emote_3p = null var/species_sounds = "None" // By default, we have nothing. var/death_sound_override = null + var/virtual_reality_mob = FALSE // gross boolean for keeping VR mobs in VR /* // Not sure if needed, screams aren't a carbon thing rn. var/scream_sound = null var/female_scream_sound = null @@ -44,3 +45,98 @@ Maybe later, gotta figure out a way to click yourself when in a locker etc. ..() verbs |= /mob/living/proc/click_self */ + +/mob/living/proc/handle_vorefootstep(m_intent, turf/T) // Moved from living_ch.dm + return FALSE + +// Gross proc which is called on Life() to check for escaped VR mobs. Tried to do this with Exited() on area/vr but ended up being too heavy. +/mob/living/proc/handle_vr_derez() + if(virtual_reality_mob && !istype(get_area(src), /area/vr)) + log_debug("[src] escaped virtual reality") + visible_message("[src] blinks out of existence.") + for(var/obj/belly/B in vore_organs) // Assume anybody inside an escaped VR mob is also an escaped VR mob. + for(var/mob/living/L in B) + log_debug("[L] was inside an escaped VR mob and has been deleted.") + qdel(L) + qdel(src) // Would like to convert escaped players into AR holograms in the future to encourage exploit finding. + +// TRANSFORMATION PROCS + +// Used to check if THIS MOB has been transformed into a different mob, as only the NEW mob uses tf_mob_holder. +// Necessary in niche cases where a proc interacts with the old body and needs to know it's been transformed (such as transforming into a mob then dying in virtual reality). +// Use this if you cannot use the tf_mob_holder var. Returns TRUE if transformed, FALSE if not. +/mob/living/proc/tfed_into_mob_check() + if(loc && isliving(loc)) + var/mob/living/M = loc + if(istype(M) && M.tf_mob_holder && (M.tf_mob_holder == src)) + return TRUE + else + return FALSE + else + return FALSE + +// For some reason upstream made a general revert proc but not a general transform proc, so here it is. +// Requires a /mob/living type path for transformation. Returns the new mob on success, null in all other cases. +// Just handles mob TF right now, but maybe we'll want to do something similar for items in the future. +/mob/living/proc/transform_into_mob(mob/living/new_form, pref_override = FALSE, revert = FALSE) + if(!src.mind) + return + if(!src.allow_spontaneous_tf && !pref_override) + return + if(src.tf_mob_holder) //If we're already transformed + if(revert) + revert_mob_tf() + return + else + return + else + if(src.stat == DEAD) + return + if(!ispath(new_form, /mob/living)) + return + var/mob/living/new_mob = new new_form(get_turf(src)) + new_mob.faction = src.faction + + if(new_mob && isliving(new_mob)) + for(var/obj/belly/B as anything in new_mob.vore_organs) + new_mob.vore_organs -= B + qdel(B) + new_mob.vore_organs = list() + new_mob.name = src.name + new_mob.real_name = src.real_name + for(var/lang in src.languages) + new_mob.languages |= lang + src.copy_vore_prefs_to_mob(new_mob) + new_mob.vore_selected = src.vore_selected + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(ishuman(new_mob)) + var/mob/living/carbon/human/N = new_mob + N.gender = H.gender + N.identifying_gender = H.identifying_gender + else + new_mob.gender = H.gender + else + new_mob.gender = src.gender + if(ishuman(new_mob)) + var/mob/living/carbon/human/N = new_mob + N.identifying_gender = src.gender + + for(var/obj/belly/B as anything in src.vore_organs) + B.loc = new_mob + B.forceMove(new_mob) + B.owner = new_mob + src.vore_organs -= B + new_mob.vore_organs += B + + new_mob.ckey = src.ckey + if(src.ai_holder && new_mob.ai_holder) + var/datum/ai_holder/old_AI = src.ai_holder + old_AI.set_stance(STANCE_SLEEP) + var/datum/ai_holder/new_AI = new_mob.ai_holder + new_AI.hostile = old_AI.hostile + new_AI.retaliate = old_AI.retaliate + src.loc = new_mob + src.forceMove(new_mob) + new_mob.tf_mob_holder = src + return new_mob diff --git a/modular_chomp/icons/mob/screen_ghost.dmi b/modular_chomp/icons/mob/screen_ghost.dmi new file mode 100644 index 0000000000000000000000000000000000000000..31eb23dcde94ee116394494eb2c3db615bcd8a01 GIT binary patch literal 30852 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
#ZTlB-^Iw5HcNq|nCVw7!oT;TXJ? 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