virtual reality component improvements, fixes and documentation.
This commit is contained in:
@@ -36,8 +36,10 @@
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
// /datum signals
|
||||
#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component)
|
||||
#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component)
|
||||
#define COMSIG_COMPONENT_ADDED "component_added" //sent to the new datum parent when a component is added to them: (/datum/component)
|
||||
#define COMSIG_COMPONENT_REMOVING "component_removing" //sent to the datum parent before a component is removed from them because of RemoveComponent: (/datum/component)
|
||||
#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent" //sent to the component itself when unregistered from a parent
|
||||
#define COMSIG_COMPONENT_REGISTER_PARENT "component_register_parent" //sent to the component itself when registered to a parent
|
||||
#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation
|
||||
#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called
|
||||
|
||||
@@ -140,7 +142,7 @@
|
||||
#define HEARING_RAW_MESSAGE 4
|
||||
/* #define HEARING_RADIO_FREQ 5
|
||||
#define HEARING_SPANS 6
|
||||
#define HEARING_MESSAGE_MODE 7
|
||||
#define HEARING_MESSAGE_MODE 7
|
||||
#define HEARING_SOURCE 8*/
|
||||
#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)
|
||||
#define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination)
|
||||
@@ -152,7 +154,8 @@
|
||||
#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A)
|
||||
#define COMPONENT_ALLOW_EXAMINE 1
|
||||
#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
|
||||
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize(): (can_reenter_corpse)
|
||||
#define COMPONENT_BLOCK_DEATH_BROADCAST 1 //stops the death from being broadcasted in deathchat.
|
||||
#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize(): (can_reenter_corpse, special, penalize)
|
||||
#define COMPONENT_BLOCK_GHOSTING 1
|
||||
#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
|
||||
#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
// If you want/expect to be moving the component around between parents, use this to register on the parent for signals
|
||||
/datum/component/proc/RegisterWithParent()
|
||||
return
|
||||
SEND_SIGNAL(src, COMSIG_COMPONENT_REGISTER_PARENT) //CITADEL EDIT
|
||||
|
||||
/datum/component/proc/Initialize(...)
|
||||
return
|
||||
@@ -85,7 +85,7 @@
|
||||
UnregisterFromParent()
|
||||
|
||||
/datum/component/proc/UnregisterFromParent()
|
||||
return
|
||||
SEND_SIGNAL(src, COMSIG_COMPONENT_UNREGISTER_PARENT) //CITADEL EDIT
|
||||
|
||||
/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE)
|
||||
if(QDELETED(src) || QDELETED(target))
|
||||
|
||||
@@ -19,12 +19,14 @@
|
||||
src.damage_multiplier = damage_multiplier
|
||||
|
||||
/datum/component/bane/RegisterWithParent()
|
||||
. = ..()
|
||||
if(speciestype)
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/speciesCheck)
|
||||
else
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/mobCheck)
|
||||
|
||||
/datum/component/bane/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK)
|
||||
|
||||
/datum/component/bane/proc/speciesCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
RegisterSignal(parent, bounce, .proc/bounce_up)
|
||||
|
||||
/datum/component/bouncy/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, bounce_signals, .proc/bounce_up)
|
||||
|
||||
/datum/component/bouncy/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, bounce_signals)
|
||||
|
||||
/datum/component/bouncy/proc/bounce_up(datum/source)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
apply()
|
||||
|
||||
/datum/component/decal/RegisterWithParent()
|
||||
. = ..()
|
||||
if(first_dir)
|
||||
RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_react)
|
||||
if(cleanable)
|
||||
@@ -25,6 +26,7 @@
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
|
||||
/datum/component/decal/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE))
|
||||
|
||||
/datum/component/decal/Destroy()
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
return ..()
|
||||
|
||||
/datum/component/fantasy/RegisterWithParent()
|
||||
. = ..()
|
||||
var/obj/item/master = parent
|
||||
originalName = master.name
|
||||
modify()
|
||||
|
||||
/datum/component/fantasy/UnregisterFromParent()
|
||||
. = ..()
|
||||
unmodify()
|
||||
|
||||
/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
src.fire_stacks = fire_stacks
|
||||
|
||||
/datum/component/igniter/RegisterWithParent()
|
||||
. = ..()
|
||||
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
else if(isitem(parent))
|
||||
@@ -17,6 +18,7 @@
|
||||
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
|
||||
|
||||
/datum/component/igniter/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/igniter/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
src.throw_anchored = throw_anchored
|
||||
|
||||
/datum/component/knockback/RegisterWithParent()
|
||||
. = ..()
|
||||
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
else if(isitem(parent))
|
||||
@@ -18,6 +19,7 @@
|
||||
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
|
||||
|
||||
/datum/component/knockback/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/knockback/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
src.flat_heal = flat_heal
|
||||
|
||||
/datum/component/lifesteal/RegisterWithParent()
|
||||
. = ..()
|
||||
if(isgun(parent))
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
else if(isitem(parent))
|
||||
@@ -18,6 +19,7 @@
|
||||
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
|
||||
|
||||
/datum/component/lifesteal/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/lifesteal/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
cloud_sync()
|
||||
|
||||
/datum/component/nanites/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_HAS_NANITES, .proc/confirm_nanites)
|
||||
RegisterSignal(parent, COMSIG_NANITE_UI_DATA, .proc/nanite_ui_data)
|
||||
RegisterSignal(parent, COMSIG_NANITE_GET_PROGRAMS, .proc/get_programs)
|
||||
@@ -57,6 +58,7 @@
|
||||
RegisterSignal(parent, COMSIG_NANITE_SIGNAL, .proc/receive_signal)
|
||||
|
||||
/datum/component/nanites/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_HAS_NANITES,
|
||||
COMSIG_NANITE_UI_DATA,
|
||||
COMSIG_NANITE_GET_PROGRAMS,
|
||||
|
||||
@@ -20,12 +20,14 @@
|
||||
begin_orbit(orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
|
||||
|
||||
/datum/component/orbiter/RegisterWithParent()
|
||||
. = ..()
|
||||
var/atom/target = parent
|
||||
while(ismovableatom(target))
|
||||
RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/move_react)
|
||||
target = target.loc
|
||||
|
||||
/datum/component/orbiter/UnregisterFromParent()
|
||||
. = ..()
|
||||
var/atom/target = parent
|
||||
while(ismovableatom(target))
|
||||
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
@@ -13,10 +13,12 @@
|
||||
src.override_projectile_range = override_projectile_range
|
||||
|
||||
/datum/component/shrapnel/RegisterWithParent()
|
||||
. = ..()
|
||||
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
|
||||
/datum/component/shrapnel/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/shrapnel/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
src.faction = faction
|
||||
|
||||
/datum/component/summoning/RegisterWithParent()
|
||||
. = ..()
|
||||
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
else if(isitem(parent))
|
||||
@@ -32,6 +33,7 @@
|
||||
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
|
||||
|
||||
/datum/component/summoning/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/summoning/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
src.allowed_slot = allowed_slot
|
||||
|
||||
/datum/component/tactical/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/modify)
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/unmodify)
|
||||
|
||||
/datum/component/tactical/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
|
||||
unmodify()
|
||||
|
||||
|
||||
@@ -1,128 +1,204 @@
|
||||
/**
|
||||
* The virtual reality turned component.
|
||||
* Originally created to overcome issues of mob polymorphing locking the player inside virtual reality
|
||||
* and allow for a more "realistic" virtual reality in a virtual reality experience.
|
||||
* (I was there when VR sleepers were first tested on /tg/station, it was whacky.)
|
||||
* In short, a barebone not so hardcoded VR framework.
|
||||
* If you plan to add more devices that make use of this component, remember to isolate their specific code outta here where possible.
|
||||
*/
|
||||
/datum/component/virtual_reality
|
||||
can_transfer = TRUE
|
||||
var/datum/mind/mastermind // where is my mind t. pixies
|
||||
//the player's mind (not the parent's), should something happen to them or to their mob.
|
||||
var/datum/mind/mastermind
|
||||
//the current mob's mind, which we need to keep track for mind transfer.
|
||||
var/datum/mind/current_mind
|
||||
var/obj/machinery/vr_sleeper/vr_sleeper
|
||||
//the action datum used by the mob to quit the vr session.
|
||||
var/datum/action/quit_vr/quit_action
|
||||
//This one's name should be self explainatory, currently used for emags.
|
||||
var/you_die_in_the_game_you_die_for_real = FALSE
|
||||
var/datum/component/virtual_reality/inception //The component works on a very fragile link betwixt mind, ckey and death.
|
||||
//Used to allow people to play recursively playing vr while playing vr without many issues.
|
||||
var/datum/component/virtual_reality/inception
|
||||
//Used to stop the component from executing certain functions that'd cause us some issues otherwise.
|
||||
//FALSE if there is a connected player, otherwise TRUE.
|
||||
var/session_paused = TRUE
|
||||
//Used to stop unwarranted behaviour from happening in cases where the master mind transference is unsupported. Set on Initialize().
|
||||
var/allow_mastermind_transfer = FALSE
|
||||
|
||||
/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
|
||||
/datum/component/virtual_reality/Initialize(yolo = FALSE, _allow_mastermind_transfer = FALSE)
|
||||
var/mob/vr_M = parent
|
||||
mastermind = M.mind
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over)
|
||||
RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/switch_player)
|
||||
RegisterSignal(mastermind, COMSIG_MIND_TRANSFER, .proc/switch_player)
|
||||
if(!istype(vr_M) || !vr_M.mind)
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
you_die_in_the_game_you_die_for_real = yolo
|
||||
quit_action = new()
|
||||
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)
|
||||
vr_M.ckey = M.ckey
|
||||
var/datum/component/virtual_reality/clusterfk = M.GetComponent(/datum/component/virtual_reality)
|
||||
if(clusterfk && !clusterfk.inception)
|
||||
clusterfk.inception = src
|
||||
SStgui.close_user_uis(M, src)
|
||||
allow_mastermind_transfer = _allow_mastermind_transfer
|
||||
quit_action = new
|
||||
|
||||
/datum/component/virtual_reality/Destroy()
|
||||
QDEL_NULL(quit_action)
|
||||
return ..()
|
||||
|
||||
/datum/component/virtual_reality/RegisterWithParent()
|
||||
. = ..()
|
||||
var/mob/M = parent
|
||||
current_mind = M.mind
|
||||
if(!quit_action)
|
||||
quit_action = new
|
||||
quit_action.Grant(M)
|
||||
RegisterSignal(quit_action, COMSIG_ACTION_TRIGGER, .proc/revert_to_reality)
|
||||
RegisterSignal(quit_action, COMSIG_ACTION_TRIGGER, .proc/action_trigger)
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over)
|
||||
RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/be_a_quitter)
|
||||
RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/pass_me_the_remote)
|
||||
RegisterSignal(current_mind, COMSIG_MIND_TRANSFER, .proc/pass_me_the_remote)
|
||||
mastermind.current.audiovisual_redirect = M
|
||||
if(vr_sleeper)
|
||||
vr_sleeper.vr_mob = M
|
||||
if(mastermind)
|
||||
mastermind.current.audiovisual_redirect = M
|
||||
|
||||
/datum/component/virtual_reality/UnregisterFromParent()
|
||||
quit_action.Remove(parent)
|
||||
. = ..()
|
||||
if(quit_action)
|
||||
quit_action.Remove(parent)
|
||||
UnregisterSignal(quit_action, COMSIG_ACTION_TRIGGER)
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE))
|
||||
UnregisterSignal(current_mind, COMSIG_MIND_TRANSFER)
|
||||
UnregisterSignal(quit_action, COMSIG_ACTION_TRIGGER)
|
||||
current_mind = null
|
||||
mastermind.current.audiovisual_redirect = null
|
||||
if(mastermind)
|
||||
mastermind.current.audiovisual_redirect = null
|
||||
|
||||
/**
|
||||
* Called when attempting to connect a mob to a virtual reality mob.
|
||||
* This will return FALSE if the mob is without player or dead.
|
||||
*/
|
||||
/datum/component/virtual_reality/proc/connect(mob/M)
|
||||
if(!M.mind || M.stat == DEAD)
|
||||
return FALSE
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over)
|
||||
mastermind = M.mind
|
||||
RegisterSignal(mastermind, COMSIG_MIND_TRANSFER, .proc/switch_player)
|
||||
var/datum/component/virtual_reality/clusterfk = M.GetComponent(/datum/component/virtual_reality)
|
||||
if(clusterfk)
|
||||
clusterfk.inception = src
|
||||
var/mob/vr_M = parent
|
||||
SStgui.close_user_uis(M, src)
|
||||
M.transfer_ckey(vr_M, FALSE)
|
||||
session_paused = FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Called when the mastermind mind is transferred to another mob.
|
||||
* This is pretty much going to simply quit the session until machineries support polymorphed occupants etcetera.
|
||||
*/
|
||||
/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 et similar... Or did something fuck up?
|
||||
revert_to_reality()
|
||||
if(!allow_mastermind_transfer)
|
||||
quit()
|
||||
return
|
||||
old_mob.audiovisual_redirect = null
|
||||
new_mob.audiovisual_redirect = parent
|
||||
|
||||
/datum/component/virtual_reality/proc/action_trigger(datum/signal_source, datum/action/source)
|
||||
if(source != quit_action)
|
||||
return COMPONENT_ACTION_BLOCK_TRIGGER
|
||||
revert_to_reality(signal_source)
|
||||
|
||||
/**
|
||||
* VR sleeper emag_act() hook.
|
||||
*/
|
||||
/datum/component/virtual_reality/proc/you_only_live_once()
|
||||
if(you_die_in_the_game_you_die_for_real || vr_sleeper?.only_current_user_can_interact)
|
||||
if(you_die_in_the_game_you_die_for_real)
|
||||
return FALSE
|
||||
you_die_in_the_game_you_die_for_real = TRUE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Takes care of moving the component from a mob to another when their mind or ckey is transferred.
|
||||
* The very reason this component even exists (else one would be stuck playing as a monky if monkyified)
|
||||
* Should the new mob happen to be one of the virtual realities ultimately associated the player
|
||||
* a 180° turn will be done and quit the session instead.
|
||||
*/
|
||||
/datum/component/virtual_reality/proc/pass_me_the_remote(datum/source, mob/new_mob)
|
||||
if(new_mob == mastermind.current)
|
||||
revert_to_reality(source)
|
||||
return TRUE
|
||||
if(mastermind && new_mob == mastermind.current)
|
||||
quit()
|
||||
return
|
||||
var/datum/component/virtual_reality/VR = new_mob.GetComponent(/datum/component/virtual_reality)
|
||||
if(VR.inception)
|
||||
var/datum/component/virtual_reality/VR2 = VR.inception
|
||||
var/emergency_quit = FALSE
|
||||
while(VR2)
|
||||
if(VR2 == src)
|
||||
emergency_quit = TRUE
|
||||
break
|
||||
VR2 = VR2.inception
|
||||
if(emergency_quit)
|
||||
VR.inception.quit() //this will make the ckey revert back to the new mob.
|
||||
return
|
||||
new_mob.TakeComponent(src)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Required for the component to be transferable from mob to mob.
|
||||
*/
|
||||
/datum/component/virtual_reality/PostTransfer()
|
||||
if(!ismob(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
/**
|
||||
*The following procs simply acts as hooks for quit(), since components do not use callbacks anymore
|
||||
*/
|
||||
/datum/component/virtual_reality/proc/action_trigger(datum/signal_source, datum/action/source)
|
||||
quit()
|
||||
return COMPONENT_ACTION_BLOCK_TRIGGER
|
||||
|
||||
/datum/component/virtual_reality/proc/revert_to_reality(datum/source)
|
||||
quit_it()
|
||||
quit()
|
||||
|
||||
/datum/component/virtual_reality/proc/game_over(datum/source)
|
||||
quit_it(TRUE, TRUE)
|
||||
quit(you_die_in_the_game_you_die_for_real, TRUE)
|
||||
return COMPONENT_BLOCK_DEATH_BROADCAST
|
||||
|
||||
/datum/component/virtual_reality/proc/be_a_quitter(datum/source, can_reenter_corpse)
|
||||
quit_it()
|
||||
return COMPONENT_BLOCK_GHOSTING
|
||||
/datum/component/virtual_reality/proc/be_a_quitter(datum/source, can_reenter_corpse, special = FALSE, penalize = FALSE)
|
||||
if(!special)
|
||||
quit()
|
||||
return COMPONENT_BLOCK_GHOSTING
|
||||
|
||||
/datum/component/virtual_reality/proc/virtual_reality_in_a_virtual_reality(mob/player, killme = FALSE, datum/component/virtual_reality/yo_dawg)
|
||||
/datum/component/virtual_reality/proc/machine_destroyed(datum/source)
|
||||
quit(cleanup = TRUE)
|
||||
|
||||
/**
|
||||
* Takes care of deleting itself, moving the player back to the mastermind's current and queueing the parent for deletion.
|
||||
* It supports nested virtual realities by recursively calling vr_in_a_vr(), which in turns calls quit(),
|
||||
* up to the deepest level, where the ckey will be transferred back to our mastermind's mob instead.
|
||||
* The above operation is skipped when session_paused is TRUE (ergo no player in control of the current mob).
|
||||
* vars:
|
||||
* * deathcheck is used to kill the master, you want this FALSE unless for stuff that doesn't involve emagging.
|
||||
* * cleanup is used to queue the parent for the next vr_clean_master's run, where they'll be deleted should they be dead.
|
||||
* * mob/override is used for the recursive virtual reality explained above and shouldn't be used outside of vr_in_a_vr().
|
||||
*/
|
||||
/datum/component/virtual_reality/proc/quit(deathcheck = FALSE, cleanup = FALSE, mob/override)
|
||||
var/mob/M = parent
|
||||
quit_it(FALSE, killme, player, yo_dawg)
|
||||
yo_dawg.inception = null
|
||||
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 = override ? override : mastermind.current
|
||||
if(!mastermind)
|
||||
to_chat(M, "<span class='warning'>You feel a dreadful sensation, something terrible happened. You try to wake up, but you find yourself unable to...</span>")
|
||||
else
|
||||
var/key_transfer = FALSE
|
||||
if(!session_paused)
|
||||
var/mob/dreamer = override || mastermind?.current
|
||||
if(!dreamer) //This should NEVER happen.
|
||||
stack_trace("virtual reality component quit() called without a mob to transfer the parent key to.")
|
||||
to_chat(M, "<span class='warning'>You feel a dreadful sensation, something terrible happened. You try to wake up, but you find yourself unable to...</span>")
|
||||
qdel(src)
|
||||
return
|
||||
if(inception?.parent)
|
||||
inception.virtual_reality_in_a_virtual_reality(dreamer, cleanup, src)
|
||||
else
|
||||
key_transfer = TRUE
|
||||
if(key_transfer)
|
||||
inception.vr_in_a_vr(dreamer, deathcheck, cleanup, src)
|
||||
else if(M.ckey)
|
||||
M.transfer_ckey(dreamer, FALSE)
|
||||
dreamer.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
dreamer.audiovisual_redirect = null
|
||||
if(deathcheck && you_die_in_the_game_you_die_for_real)
|
||||
to_chat(mastermind, "<span class='warning'>You feel everything fading away...</span>")
|
||||
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(vr_sleeper)
|
||||
vr_sleeper.vr_mob = null
|
||||
vr_sleeper = null
|
||||
qdel(src)
|
||||
if(deathcheck)
|
||||
to_chat(dreamer, "<span class='warning'>You feel everything fading away...</span>")
|
||||
dreamer.death(FALSE)
|
||||
dreamer.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
dreamer.audiovisual_redirect = null
|
||||
if(cleanup)
|
||||
var/obj/effect/vr_clean_master/cleanbot = locate() in get_area(M)
|
||||
if(cleanbot)
|
||||
LAZYOR(cleanbot.corpse_party, M)
|
||||
qdel(src)
|
||||
else if(mastermind)
|
||||
UnregisterSignal(mastermind.current, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING))
|
||||
UnregisterSignal(mastermind, COMSIG_MIND_TRANSFER)
|
||||
mastermind = null
|
||||
session_paused = TRUE
|
||||
|
||||
/datum/component/virtual_reality/Destroy()
|
||||
var/datum/action/quit_vr/delet_me = quit_action
|
||||
. = ..()
|
||||
qdel(delet_me)
|
||||
/**
|
||||
* Used for recursive virtual realities shenanigeans and should be called only through the above proc.
|
||||
*/
|
||||
/datum/component/virtual_reality/proc/vr_in_a_vr(mob/player, deathcheck = FALSE, cleanup = FALSE, datum/component/virtual_reality/yo_dawg)
|
||||
var/mob/M = parent
|
||||
quit(deathcheck, cleanup, player, yo_dawg)
|
||||
yo_dawg.inception = null
|
||||
if(deathcheck && cleanup)
|
||||
M.death(FALSE)
|
||||
|
||||
@@ -34,10 +34,12 @@
|
||||
last_process = world.time
|
||||
|
||||
/datum/component/wet_floor/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_TURF_IS_WET, .proc/is_wet)
|
||||
RegisterSignal(parent, COMSIG_TURF_MAKE_DRY, .proc/dry)
|
||||
|
||||
/datum/component/wet_floor/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_TURF_IS_WET, COMSIG_TURF_MAKE_DRY))
|
||||
|
||||
/datum/component/wet_floor/Destroy()
|
||||
|
||||
@@ -181,8 +181,9 @@ Class Procs:
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.update_canmove()
|
||||
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
|
||||
occupant = null
|
||||
if(occupant)
|
||||
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/proc/can_be_occupant(atom/movable/am)
|
||||
return occupant_typecache ? is_type_in_typecache(am, occupant_typecache) : isliving(am)
|
||||
|
||||
@@ -40,5 +40,5 @@
|
||||
|
||||
/datum/action/quit_vr/Trigger() //this merely a trigger for /datum/component/virtual_reality
|
||||
. = ..()
|
||||
if(!.)
|
||||
if(.) //The component was not there to block the trigger.
|
||||
Remove(owner)
|
||||
|
||||
@@ -52,18 +52,16 @@
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
only_current_user_can_interact = TRUE
|
||||
|
||||
/obj/machinery/vr_sleeper/hugbox/emag_act(mob/user)
|
||||
return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
|
||||
|
||||
/obj/machinery/vr_sleeper/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(!(obj_flags & EMAGGED))
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
you_die_in_the_game_you_die_for_real = TRUE
|
||||
sparks.start()
|
||||
addtimer(CALLBACK(src, .proc/emagNotify), 150)
|
||||
return TRUE
|
||||
if(!only_current_user_can_interact)
|
||||
obj_flags |= EMAGGED
|
||||
you_die_in_the_game_you_die_for_real = TRUE
|
||||
sparks.start()
|
||||
addtimer(CALLBACK(src, .proc/emagNotify), 150)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/vr_sleeper/update_icon()
|
||||
icon_state = "[initial(icon_state)][state_open ? "-open" : ""]"
|
||||
@@ -76,7 +74,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/vr_sleeper/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
if(user.lying || !iscarbon(target) || !Adjacent(target) || user.canUseTopic(src, BE_CLOSE, TRUE, NO_TK))
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
@@ -91,22 +89,19 @@
|
||||
return
|
||||
switch(action)
|
||||
if("vr_connect")
|
||||
var/mob/living/carbon/human/human_occupant = occupant
|
||||
if(human_occupant && human_occupant.mind && usr == occupant)
|
||||
|
||||
to_chat(occupant, "<span class='warning'>Transferring to virtual reality...</span>")
|
||||
if(vr_mob && (!istype(vr_mob) || !vr_mob.InCritical()) && !vr_mob.GetComponent(/datum/component/virtual_reality))
|
||||
vr_mob.AddComponent(/datum/component/virtual_reality, human_occupant, src, you_die_in_the_game_you_die_for_real)
|
||||
to_chat(vr_mob, "<span class='notice'>Transfer successful! You are now playing as [vr_mob] in VR!</span>")
|
||||
else
|
||||
var/mob/M = occupant
|
||||
if(M?.mind && M == usr)
|
||||
to_chat(M, "<span class='warning'>Transferring to virtual reality...</span>")
|
||||
var/datum/component/virtual_reality/VR
|
||||
if(vr_mob)
|
||||
VR = vr_mob.GetComponent(/datum/component/virtual_reality)
|
||||
if(!(VR?.connect(M)))
|
||||
if(allow_creating_vr_mobs)
|
||||
to_chat(occupant, "<span class='warning'>Virtual avatar not found, attempting to create one...</span>")
|
||||
var/obj/effect/landmark/vr_spawn/V = get_vr_spawnpoint()
|
||||
var/turf/T = get_turf(V)
|
||||
if(T)
|
||||
SStgui.close_user_uis(occupant, src)
|
||||
new_player(occupant, T, V.vr_outfit)
|
||||
to_chat(vr_mob, "<span class='notice'>Transfer successful! You are now playing as [vr_mob] in VR!</span>")
|
||||
else
|
||||
to_chat(occupant, "<span class='warning'>Virtual world misconfigured, aborting transfer</span>")
|
||||
else
|
||||
@@ -157,17 +152,29 @@
|
||||
for(var/obj/effect/landmark/vr_spawn/V in GLOB.landmarks_list)
|
||||
GLOB.vr_spawnpoints[V.vr_category] = V
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/new_player(mob/living/carbon/human/H, location, datum/outfit/outfit, transfer = TRUE)
|
||||
if(!H)
|
||||
/obj/machinery/vr_sleeper/proc/new_player(mob/M, location, datum/outfit/outfit, transfer = TRUE)
|
||||
if(!M)
|
||||
return
|
||||
cleanup_vr_mob()
|
||||
vr_mob = new virtual_mob_type(location)
|
||||
if(vr_mob.build_virtual_character(H, outfit))
|
||||
var/mob/living/carbon/human/vr_H = vr_mob
|
||||
vr_H.updateappearance(TRUE, TRUE, TRUE)
|
||||
if(!transfer || !H.mind)
|
||||
return
|
||||
vr_mob.AddComponent(/datum/component/virtual_reality, H, src, you_die_in_the_game_you_die_for_real)
|
||||
if(vr_mob.build_virtual_character(M, outfit) && iscarbon(vr_mob))
|
||||
var/mob/living/carbon/C = vr_mob
|
||||
C.updateappearance(TRUE, TRUE, TRUE)
|
||||
var/datum/component/virtual_reality/VR = vr_mob.AddComponent(/datum/component/virtual_reality, you_die_in_the_game_you_die_for_real)
|
||||
if(VR.connect(M))
|
||||
RegisterSignal(VR, COMSIG_COMPONENT_UNREGISTER_PARENT, .proc/unset_vr_mob)
|
||||
RegisterSignal(VR, COMSIG_COMPONENT_REGISTER_PARENT, .proc/set_vr_mob)
|
||||
if(!only_current_user_can_interact)
|
||||
VR.RegisterSignal(src, COMSIG_ATOM_EMAG_ACT, /datum/component/virtual_reality.proc/you_only_live_once)
|
||||
VR.RegisterSignal(src, COMSIG_MACHINE_EJECT_OCCUPANT, /datum/component/virtual_reality.proc/revert_to_reality)
|
||||
VR.RegisterSignal(src, COMSIG_PARENT_QDELETING, /datum/component/virtual_reality.proc/machine_destroyed)
|
||||
to_chat(vr_mob, "<span class='notice'>Transfer successful! You are now playing as [vr_mob] in VR!</span>")
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/unset_vr_mob(datum/component/virtual_reality/VR)
|
||||
vr_mob = null
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/set_vr_mob(datum/component/virtual_reality/VR)
|
||||
vr_mob = VR.parent
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/cleanup_vr_mob()
|
||||
if(vr_mob)
|
||||
@@ -222,6 +229,7 @@
|
||||
qdel(C)
|
||||
for (var/A in corpse_party)
|
||||
var/mob/M = A
|
||||
if(get_area(M) == vr_area && M.stat == DEAD)
|
||||
if(M && M.stat == DEAD && get_area(M) == vr_area)
|
||||
qdel(M)
|
||||
corpse_party -= M
|
||||
addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
|
||||
|
||||
@@ -265,7 +265,7 @@ Works together with spawning an observer, noted above.
|
||||
|
||||
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE)
|
||||
penalize = suiciding || penalize // suicide squad.
|
||||
if(!key || cmptext(copytext(key,1,2),"@") || (!special && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse) & COMPONENT_BLOCK_GHOSTING))
|
||||
if(!key || cmptext(copytext(key,1,2),"@") || (SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize) & 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.
|
||||
|
||||
@@ -62,12 +62,8 @@
|
||||
unset_machine()
|
||||
timeofdeath = world.time
|
||||
tod = STATION_TIME_TIMESTAMP("hh:mm:ss")
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/obj/item/I in contents)
|
||||
I.on_mob_death(src, gibbed)
|
||||
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf))
|
||||
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[get_area_name(T)]</b>.</span>"
|
||||
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
|
||||
if(mind)
|
||||
mind.store_memory("Time of death: [tod]", 0)
|
||||
GLOB.alive_mob_list -= src
|
||||
@@ -89,7 +85,12 @@
|
||||
addtimer(CALLBACK(src, .proc/med_hud_set_status), (DEFIB_TIME_LIMIT * 10) + 1)
|
||||
stop_pulling()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
|
||||
var/signal = SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf) && !(signal & COMPONENT_BLOCK_DEATH_BROADCAST))
|
||||
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[get_area_name(T)]</b>.</span>"
|
||||
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
|
||||
|
||||
if (client)
|
||||
client.move_delay = initial(client.move_delay)
|
||||
|
||||
Reference in New Issue
Block a user