From d9d4a88a0b82d24ac5d1eede82680194591d77c9 Mon Sep 17 00:00:00 2001 From: Ghommie Date: Tue, 18 Jun 2019 21:59:05 +0200 Subject: [PATCH] *Dramatic low-pitch scenic sound plays in* --- code/__DEFINES/components.dm | 2 +- code/datums/components/virtual_reality.dm | 94 ++++++++++++------- code/datums/mind.dm | 5 +- code/modules/VR/vr_sleeper.dm | 10 +- code/modules/mob/dead/observer/observer.dm | 10 +- code/modules/mob/death.dm | 2 + .../living/simple_animal/guardian/guardian.dm | 2 +- code/modules/mob/mob.dm | 4 +- code/modules/mob/mob_defines.dm | 2 + code/modules/mob/mob_helpers.dm | 2 +- .../spells/spell_types/mind_transfer.dm | 2 +- 11 files changed, 83 insertions(+), 52 deletions(-) diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index fe88832e8d..3841a086e9 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -120,7 +120,7 @@ #define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source) // /mind signals -#define COMSIG_MIND_TRANSFER "mind_transfer" //from base of mind/transfer_to(): (new_character) +#define COMSIG_MIND_TRANSFER "mind_transfer" //from base of mind/transfer_to(): (new_character, old_character) // /mob signals #define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed) diff --git a/code/datums/components/virtual_reality.dm b/code/datums/components/virtual_reality.dm index 0bc1f9d8ec..8421f18dbb 100644 --- a/code/datums/components/virtual_reality.dm +++ b/code/datums/components/virtual_reality.dm @@ -1,36 +1,54 @@ /datum/component/virtual_reality - dupe_mode = COMPONENT_DUPE_UNIQUE - var/datum/mind/real_mind // where is my mind t. pixies + dupe_mode = COMPONENT_DUPE_ALLOWED //mindswap memes, shouldn't stack up otherwise. + var/datum/mind/mastermind // where is my mind t. pixies var/datum/mind/current_mind var/obj/machinery/vr_sleeper/vr_sleeper var/datum/action/quit_vr/quit_action var/you_die_in_the_game_you_die_for_real = FALSE -/datum/component/virtual_reality/Initialize(datum/mind/mastermind, obj/machinery/vr_sleeper/gaming_pod, yolo = FALSE, new_char = TRUE) - if(!ismob(parent)) +/datum/component/virtual_reality/Initialize(mob/M, obj/machinery/vr_sleeper/gaming_pod, yolo = FALSE, new_char = TRUE) + if(!ismob(parent) || !istype(M)) return COMPONENT_INCOMPATIBLE - + var/mob/vr_M + mastermind = M.mind + RegisterSignal(mastermind, COMSIG_MIND_TRANSFER, .proc/switch_player) + RegisterSignal(mastermind, COMSIG_MOB_KEY_CHANGE, .proc/switch_player) you_die_in_the_game_you_die_for_real = yolo quit_action = new() - quit_action.Grant(parent) + RegisterSignal(quit_action, COMSIG_ACTION_TRIGGER, .proc/revert_to_reality) if(gaming_pod) vr_sleeper = gaming_pod RegisterSignal(vr_sleeper, COMSIG_ATOM_EMAG_ACT, .proc/you_only_live_once) - RegisterSignal(vr_sleeper, COMSIG_MACHINE_EJECT_OCCUPANT, .proc/revert_to_reality) + RegisterSignal(vr_sleeper, COMSIG_MACHINE_EJECT_OCCUPANT, .proc/virtual_reality_in_a_virtual_reality) + vr_M.ckey = M.ckey + SStgui.close_user_uis(M, src) /datum/component/virtual_reality/RegisterWithParent() var/mob/M = parent current_mind = M.mind - RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/game_over) - RegisterSignal(parent, COMSIG_MOB_KEY_CHANGE, .proc/pass_me_the_remote) - RegisterSignal(current_mind, COMSIG_MIND_TRANSFER, .proc/pass_me_the_remote) - RegisterSignal(parent, COMSIG_MOB_GHOSTIZE, .proc/be_a_quitter) - RegisterSignal(quit_action, COMSIG_ACTION_TRIGGER, .proc/revert_to_reality) + quit_action.Grant(M) + RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over) + RegisterSignal(M, list(COMSIG_MOB_KEY_CHANGE, COMSIG_MIND_TRANSFER), .proc/pass_me_the_remote) + RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/be_a_quitter) + mastermind.current.audiovisual_redirect = M /datum/component/virtual_reality/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE)) + quit_action.Remove(parent) + UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE)) UnregisterSignal(quit_action, COMSIG_ACTION_TRIGGER) UnregisterSignal(current_mind, COMSIG_MIND_TRANSFER) + current_mind = null + mastermind.current.audiovisual_redirect = null + +/datum/component/virtual_reality/proc/switch_player(datum/source, mob/new_mob, mob/old_mob) + if(vr_sleeper || !new_mob.mind) + // Machineries currently don't deal up with the occupant being polymorphed or the such. Or the admin dared to use outdated transformation procs. + virtual_reality_in_a_virtual_reality(FALSE, new_mob) + return + old_mob.audiovisual_redirect = null + old_mob.inception = null + new_mob.audiovisual_redirect = parent + new_mob.inception = src /datum/component/virtual_reality/proc/action_trigger(datum/signal_source, datum/action/source) if(source != quit_action) @@ -44,7 +62,7 @@ return TRUE /datum/component/virtual_reality/proc/pass_me_the_remote(datum/source, mob/new_mob) - if(new_mob == real_mind.current) + if(new_mob == mastermind.current) revert_to_reality(source) new_mob.TakeComponent(src) return TRUE @@ -54,35 +72,47 @@ return COMPONENT_INCOMPATIBLE /datum/component/virtual_reality/proc/revert_to_reality(datum/source) - quit_it(FALSE) + quit_it() /datum/component/virtual_reality/proc/game_over(datum/source) - quit_it(TRUE) + quit_it(TRUE, TRUE) -/datum/component/virtual_reality/proc/be_a_quitter(datum/source) - quit_it(FALSE) +/datum/component/virtual_reality/proc/be_a_quitter(datum/source, can_reenter_corpse) + quit_it() return COMPONENT_BLOCK_GHOSTING -/datum/component/virtual_reality/proc/quit_it(deathcheck = FALSE) +/datum/component/virtual_reality/proc/virtual_reality_in_a_virtual_reality(killme = FALSE, mob_override) var/mob/M = parent - if(!real_mind) - to_chat(M, "You feel as if something terrible happened, you try to wake up from this dream... but you can't...") + if(!QDELETED(M.inception) && M.inception.parent) + M.inception.virtual_reality_in_a_virtual_reality() + quit_it(FALSE, killme, mob_override) + if(killme) + M.death(FALSE) + +/datum/component/virtual_reality/proc/quit_it(deathcheck = FALSE, cleanup = FALSE, mob_override) + var/mob/M = parent + var/mob/dreamer = mob_override ? mob_override : mastermind.current + if(!mastermind) + to_chat(M, "You feel like something terrible happened. You try to wake up from this dream, but you can't...") else - real_mind.current.audiovisual_redirect = null - real_mind.current.ckey = M.ckey - real_mind.current.stop_sound_channel(CHANNEL_HEARTBEAT) + dreamer.ckey = M.ckey + dreamer.stop_sound_channel(CHANNEL_HEARTBEAT) + dreamer.inception = null + dreamer.audiovisual_redirect = null if(deathcheck) + if(you_die_in_the_game_you_die_for_real) + to_chat(mastermind, "You feel everything fading away...") + dreamer.death(FALSE) + if(cleanup) var/obj/effect/vr_clean_master/cleanbot = locate() in get_area(M) if(cleanbot) LAZYADD(cleanbot.corpse_party, M) - if(you_die_in_the_game_you_die_for_real) - to_chat(real_mind, "You feel everything fading away...") - real_mind.current.death(0) - if(vr_sleeper) - vr_sleeper.vr_mob = null - vr_sleeper = null + if(vr_sleeper) + vr_sleeper.vr_mob = null + vr_sleeper = null qdel(src) /datum/component/virtual_reality/Destroy() - QDEL_NULL(quit_action) - return ..() \ No newline at end of file + var/datum/action/quit_vr/delet_me = quit_action + . = ..() + qdel(delet_me) \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 2844a59d61..07414a3362 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -87,6 +87,7 @@ return language_holder /datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0) + var/old_character = current if(current) // remove ourself from our old body's mind variable current.mind = null SStgui.on_transfer(current, new_character) @@ -97,7 +98,7 @@ if(key) if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours - new_character.ghostize(1) //we'll need to ghostize so that key isn't mobless. + new_character.ghostize(TRUE, TRUE) //we'll need to ghostize so that key isn't mobless. else key = new_character.key @@ -121,7 +122,7 @@ transfer_martial_arts(new_character) if(active || force_key_move) new_character.key = key //now transfer the key to link the client to our new body - SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character) + SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character) //CIT CHANGE - makes arousal update when transfering bodies if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs. diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm index afc8de6e21..86816ba3cb 100644 --- a/code/modules/VR/vr_sleeper.dm +++ b/code/modules/VR/vr_sleeper.dm @@ -93,10 +93,7 @@ if(human_occupant && human_occupant.mind && usr == occupant) to_chat(occupant, "Transferring to virtual reality...") if(vr_mob && vr_mob.stat == CONSCIOUS && !vr_mob.GetComponent(/datum/component/virtual_reality)) - SStgui.close_user_uis(occupant, src) - vr_mob.AddComponent(/datum/component/virtual_reality, human_occupant.mind, src, you_die_in_the_game_you_die_for_real) - human_occupant.audiovisual_redirect = vr_mob - vr_mob.ckey = human_occupant.ckey + vr_mob.AddComponent(/datum/component/virtual_reality, human_occupant, src, you_die_in_the_game_you_die_for_real) to_chat(vr_mob, "Transfer successful! You are now playing as [vr_mob] in VR!") else if(allow_creating_vr_mobs) @@ -164,10 +161,7 @@ vr_H.updateappearance(TRUE, TRUE, TRUE) if(!transfer || !H.mind) return - vr_mob.AddComponent(/datum/component/virtual_reality, H.mind, src, you_die_in_the_game_you_die_for_real) - SStgui.close_user_uis(H, src) - H.audiovisual_redirect = vr_mob - vr_mob.ckey = H.ckey + vr_mob.AddComponent(/datum/component/virtual_reality, H, src, you_die_in_the_game_you_die_for_real) /obj/machinery/vr_sleeper/proc/cleanup_vr_mob() if(vr_mob) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index a018acb165..e074631640 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -260,9 +260,9 @@ Transfer_mind is there to check if mob is being deleted/not going to have a body Works together with spawning an observer, noted above. */ -/mob/proc/ghostize(can_reenter_corpse = TRUE, send_the_signal = TRUE) - if(!key || cmptext(copytext(key,1,2),"@") || (send_the_signal && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse) & COMPONENT_BLOCK_GHOSTING)) - return //mob has no key, is an aghost or some component hijack. +/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE) + if(!key || cmptext(copytext(key,1,2),"@") || (!special && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special) & COMPONENT_BLOCK_GHOSTING)) + return //mob has no key, is an aghost or some component hijacked. stop_sound_channel(CHANNEL_HEARTBEAT) //Stop heartbeat sounds because You Are A Ghost Now var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc. SStgui.on_transfer(src, ghost) // Transfer NanoUIs. @@ -280,7 +280,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set name = "Ghost" set desc = "Relinquish your life and enter the land of the dead." - if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, (stat == DEAD) ? TRUE : FALSE) & COMPONENT_BLOCK_GHOSTING) + if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, (stat == DEAD) ? TRUE : FALSE, FALSE) & COMPONENT_BLOCK_GHOSTING) return // CITADEL EDIT @@ -309,7 +309,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set name = "Ghost" set desc = "Relinquish your life and enter the land of the dead." - if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, FALSE) & COMPONENT_BLOCK_GHOSTING) + if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, FALSE, FALSE) & COMPONENT_BLOCK_GHOSTING) return var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body") diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 8c335a9e8c..f10d4baa20 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -11,4 +11,6 @@ /mob/proc/death(gibbed) SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed) + if(!QDELETED(inception) && inception.parent) + inception.virtual_reality_in_a_virtual_reality(TRUE) return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 8a5d06392f..7ce2a11314 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -426,7 +426,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians to_chat(G, "Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.") to_chat(src, "Your [G.real_name] has been successfully reset.") message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(G)])") - G.ghostize(FALSE, FALSE) + G.ghostize(FALSE) G.setthemename(G.namedatum.theme) //give it a new color, to show it's a new person C.transfer_key(G) G.reset = 1 diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 113f8a54c8..d1f83e69de 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -12,6 +12,8 @@ var/mob/dead/observe = M observe.reset_perspective(null) qdel(hud_used) + if(!QDELETED(inception) && inception.parent) + inception.virtual_reality_in_a_virtual_reality(TRUE) for(var/cc in client_colours) qdel(cc) client_colours = null @@ -438,7 +440,7 @@ /mob/proc/transfer_key(mob/new_mob, send_signal = TRUE) if(send_signal) - SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob) + SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src) new_mob.key = key /mob/verb/cancel_camera() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index a0126f5fdd..c016fac8b0 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -112,3 +112,5 @@ var/registered_z var/mob/audiovisual_redirect //Mob to redirect messages, speech, and sounds to + + var/datum/component/virtual_reality/inception \ No newline at end of file diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 80a65f56c6..8b26660cbb 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -429,7 +429,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp var/mob/dead/observer/C = pick(candidates) to_chat(M, "Your mob has been taken over by a ghost!") message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(M)])") - M.ghostize(FALSE, FALSE) + M.ghostize(FALSE, TRUE) C.transfer_key(M, FALSE) return TRUE else diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm index 021f57e873..a5e6ed202a 100644 --- a/code/modules/spells/spell_types/mind_transfer.dm +++ b/code/modules/spells/spell_types/mind_transfer.dm @@ -70,7 +70,7 @@ Also, you never added distance checking after target is selected. I've went ahea var/mob/living/caster = user//The wizard/whomever doing the body transferring. //MIND TRANSFER BEGIN - var/mob/dead/observer/ghost = victim.ghostize(FALSE, FALSE) + var/mob/dead/observer/ghost = victim.ghostize(FALSE, TRUE) caster.mind.transfer_to(victim) ghost.mind.transfer_to(caster)