mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-14 03:32:00 +00:00
299 lines
10 KiB
Plaintext
299 lines
10 KiB
Plaintext
/**
|
|
* Essentially temporary body with a twist - the virtual domain variant uses damage connections,
|
|
* listens for vdom relevant signals.
|
|
*/
|
|
/datum/component/avatar_connection
|
|
/// The person in the netpod
|
|
var/datum/weakref/old_body_ref
|
|
/// The mind of the person in the netpod
|
|
var/datum/weakref/old_mind_ref
|
|
/// The server connected to the netpod
|
|
var/datum/weakref/server_ref
|
|
/// The netpod the avatar is in
|
|
var/datum/weakref/netpod_ref
|
|
|
|
/datum/component/avatar_connection/Initialize(
|
|
datum/mind/old_mind,
|
|
mob/living/old_body,
|
|
obj/machinery/quantum_server/server,
|
|
obj/machinery/netpod/pod,
|
|
help_text,
|
|
)
|
|
|
|
if(!isliving(parent) || !isliving(old_body) || !old_mind || !server.is_operational || !pod.is_operational)
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
var/mob/living/avatar = parent
|
|
|
|
netpod_ref = WEAKREF(pod)
|
|
old_body_ref = WEAKREF(old_body)
|
|
old_mind_ref = WEAKREF(old_mind)
|
|
pod.avatar_ref = WEAKREF(avatar)
|
|
server_ref = WEAKREF(server)
|
|
server.avatar_connection_refs.Add(WEAKREF(src))
|
|
|
|
avatar.key = old_body.key
|
|
ADD_TRAIT(avatar, TRAIT_NO_MINDSWAP, REF(src)) // do not remove this one
|
|
ADD_TRAIT(old_body, TRAIT_MIND_TEMPORARILY_GONE, REF(src))
|
|
|
|
/**
|
|
* Things that will disconnect forcefully:
|
|
* - Server shutdown / broken
|
|
* - Netpod power loss / broken
|
|
* - Pilot dies/ is moved / falls unconscious
|
|
*/
|
|
RegisterSignals(old_body, list(COMSIG_LIVING_DEATH, COMSIG_MOVABLE_MOVED, COMSIG_LIVING_STATUS_UNCONSCIOUS), PROC_REF(on_sever_connection))
|
|
RegisterSignal(pod, COMSIG_BITRUNNER_CROWBAR_ALERT, PROC_REF(on_netpod_crowbar))
|
|
RegisterSignal(pod, COMSIG_BITRUNNER_NETPOD_INTEGRITY, PROC_REF(on_netpod_damaged))
|
|
RegisterSignal(pod, COMSIG_BITRUNNER_NETPOD_SEVER, PROC_REF(on_sever_connection))
|
|
RegisterSignal(server, COMSIG_BITRUNNER_DOMAIN_COMPLETE, PROC_REF(on_domain_completed))
|
|
RegisterSignal(server, COMSIG_BITRUNNER_QSRV_SEVER, PROC_REF(on_sever_connection))
|
|
RegisterSignal(server, COMSIG_BITRUNNER_SHUTDOWN_ALERT, PROC_REF(on_shutting_down))
|
|
RegisterSignal(server, COMSIG_BITRUNNER_THREAT_CREATED, PROC_REF(on_threat_created))
|
|
RegisterSignal(server, COMSIG_BITRUNNER_STATION_SPAWN, PROC_REF(on_station_spawn))
|
|
#ifndef UNIT_TESTS
|
|
RegisterSignal(avatar.mind, COMSIG_MIND_TRANSFERRED, PROC_REF(on_mind_transfer))
|
|
#endif
|
|
|
|
if(!locate(/datum/action/avatar_domain_info) in avatar.actions)
|
|
var/datum/avatar_help_text/help_datum = new(help_text)
|
|
var/datum/action/avatar_domain_info/action = new(help_datum)
|
|
action.Grant(avatar)
|
|
|
|
//var/client/our_client = avatar.client // BUBBER EDIT
|
|
var/alias = null // BUBBER EDIT - removes random aliases - original: var/alias = our_client?.prefs?.read_preference(/datum/preference/name/hacker_alias) || pick(GLOB.hacker_aliases)
|
|
|
|
|
|
if(alias && avatar.real_name != alias)
|
|
avatar.fully_replace_character_name(avatar.real_name, alias)
|
|
|
|
for(var/skill_type in old_mind.known_skills)
|
|
avatar.mind.set_experience(skill_type, old_mind.get_skill_exp(skill_type), silent = TRUE)
|
|
|
|
avatar.playsound_local(avatar, 'sound/effects/magic/blink.ogg', 25, TRUE)
|
|
avatar.set_static_vision(2 SECONDS)
|
|
avatar.set_temp_blindness(1 SECONDS) // I'm in
|
|
|
|
|
|
/datum/component/avatar_connection/PostTransfer()
|
|
var/obj/machinery/netpod/pod = netpod_ref?.resolve()
|
|
if(isnull(pod))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
if(!isliving(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
pod.avatar_ref = WEAKREF(parent)
|
|
|
|
|
|
/datum/component/avatar_connection/RegisterWithParent()
|
|
ADD_TRAIT(parent, TRAIT_TEMPORARY_BODY, REF(src))
|
|
/**
|
|
* Things that cause safe disconnection:
|
|
* - Click the alert
|
|
* - Mailed in a cache
|
|
* - Click / Stand on the ladder
|
|
*/
|
|
RegisterSignals(parent, list(COMSIG_BITRUNNER_ALERT_SEVER, COMSIG_BITRUNNER_CACHE_SEVER, COMSIG_BITRUNNER_LADDER_SEVER), PROC_REF(on_safe_disconnect))
|
|
RegisterSignal(parent, COMSIG_LIVING_PILL_CONSUMED, PROC_REF(disconnect_if_red_pill))
|
|
RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(on_sever_connection))
|
|
RegisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(on_linked_damage))
|
|
|
|
|
|
/datum/component/avatar_connection/UnregisterFromParent()
|
|
REMOVE_TRAIT(parent, TRAIT_TEMPORARY_BODY, REF(src))
|
|
UnregisterSignal(parent, list(
|
|
COMSIG_BITRUNNER_ALERT_SEVER,
|
|
COMSIG_BITRUNNER_CACHE_SEVER,
|
|
COMSIG_BITRUNNER_LADDER_SEVER,
|
|
COMSIG_LIVING_DEATH,
|
|
COMSIG_LIVING_PILL_CONSUMED,
|
|
COMSIG_MOB_APPLY_DAMAGE,
|
|
))
|
|
|
|
|
|
/// Disconnects the avatar and returns the mind to the old_body.
|
|
/datum/component/avatar_connection/proc/full_avatar_disconnect(cause_damage = FALSE, datum/source)
|
|
#ifndef UNIT_TESTS
|
|
return_to_old_body()
|
|
#endif
|
|
|
|
var/obj/machinery/netpod/hosting_netpod = netpod_ref?.resolve()
|
|
if(isnull(hosting_netpod) && istype(source, /obj/machinery/netpod))
|
|
hosting_netpod = source
|
|
|
|
hosting_netpod?.disconnect_occupant(cause_damage)
|
|
|
|
var/obj/machinery/quantum_server/server = server_ref?.resolve()
|
|
server?.avatar_connection_refs.Remove(WEAKREF(src))
|
|
|
|
qdel(src)
|
|
|
|
|
|
/// Triggers whenever the server gets a loot crate pushed to goal area
|
|
/datum/component/avatar_connection/proc/on_domain_completed(datum/source, atom/entered)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/avatar = parent
|
|
avatar.playsound_local(avatar, 'sound/machines/terminal/terminal_success.ogg', 50, vary = TRUE)
|
|
avatar.throw_alert(
|
|
ALERT_BITRUNNER_COMPLETED,
|
|
/atom/movable/screen/alert/bitrunning/qserver_domain_complete,
|
|
new_master = entered,
|
|
)
|
|
|
|
|
|
/// Transfers damage from the avatar to the old_body
|
|
/datum/component/avatar_connection/proc/on_linked_damage(datum/source, damage, damage_type, def_zone, blocked, ...)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/carbon/old_body = old_body_ref?.resolve()
|
|
if(isnull(old_body) || damage_type == STAMINA || damage_type == OXYLOSS)
|
|
return
|
|
|
|
if(damage >= (old_body.health + (ishuman(old_body) ? HUMAN_MAXHEALTH : MAX_LIVING_HEALTH))) // SKYRAT EDIT CHANGE - ORIGINAL: if(damage >= (old_body.health + MAX_LIVING_HEALTH))
|
|
full_avatar_disconnect(cause_damage = TRUE)
|
|
return
|
|
|
|
if(damage > 30 && prob(30))
|
|
INVOKE_ASYNC(old_body, TYPE_PROC_REF(/mob/living, emote), "scream")
|
|
|
|
old_body.apply_damage(damage, damage_type, def_zone, blocked, wound_bonus = CANT_WOUND)
|
|
|
|
if(old_body.stat > SOFT_CRIT) // KO!
|
|
full_avatar_disconnect(cause_damage = TRUE)
|
|
|
|
|
|
/// Handles minds being swapped around in subsequent avatars
|
|
/datum/component/avatar_connection/proc/on_mind_transfer(datum/mind/source, mob/living/previous_body)
|
|
SIGNAL_HANDLER
|
|
|
|
var/datum/action/avatar_domain_info/action = locate() in previous_body.actions
|
|
if(action)
|
|
action.Grant(source.current)
|
|
|
|
source.current.TakeComponent(src)
|
|
|
|
|
|
/// Triggers when someone starts prying open our netpod
|
|
/datum/component/avatar_connection/proc/on_netpod_crowbar(datum/source, mob/living/intruder)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/avatar = parent
|
|
avatar.playsound_local(avatar, 'sound/machines/terminal/terminal_alert.ogg', 50, vary = TRUE)
|
|
var/atom/movable/screen/alert/bitrunning/alert = avatar.throw_alert(
|
|
ALERT_BITRUNNER_CROWBAR,
|
|
/atom/movable/screen/alert/bitrunning,
|
|
new_master = intruder,
|
|
)
|
|
alert.name = "Netpod Breached"
|
|
alert.desc = "Someone is prying open the netpod. Find an exit."
|
|
|
|
|
|
/// Triggers when the netpod is taking damage and is under 50%
|
|
/datum/component/avatar_connection/proc/on_netpod_damaged(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/avatar = parent
|
|
var/atom/movable/screen/alert/bitrunning/alert = avatar.throw_alert(
|
|
ALERT_BITRUNNER_INTEGRITY,
|
|
/atom/movable/screen/alert/bitrunning,
|
|
new_master = source,
|
|
)
|
|
alert.name = "Integrity Compromised"
|
|
alert.desc = "The netpod is damaged. Find an exit."
|
|
|
|
|
|
//if your bitrunning avatar somehow manages to acquire and consume a red pill, they will be ejected from the Matrix
|
|
/datum/component/avatar_connection/proc/disconnect_if_red_pill(datum/source, obj/item/reagent_containers/pill/pill, mob/feeder)
|
|
SIGNAL_HANDLER
|
|
if(pill.icon_state == "pill4")
|
|
full_avatar_disconnect()
|
|
|
|
|
|
/// Triggers when a safe disconnect is called
|
|
/datum/component/avatar_connection/proc/on_safe_disconnect(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
full_avatar_disconnect()
|
|
|
|
|
|
/// Received message to sever connection
|
|
/datum/component/avatar_connection/proc/on_sever_connection(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
full_avatar_disconnect(cause_damage = TRUE, source = source)
|
|
|
|
|
|
/// Triggers when the server is shutting down
|
|
/datum/component/avatar_connection/proc/on_shutting_down(datum/source, mob/living/hackerman)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/avatar = parent
|
|
avatar.playsound_local(avatar, 'sound/machines/terminal/terminal_alert.ogg', 50, vary = TRUE)
|
|
var/atom/movable/screen/alert/bitrunning/alert = avatar.throw_alert(
|
|
ALERT_BITRUNNER_SHUTDOWN,
|
|
/atom/movable/screen/alert/bitrunning,
|
|
new_master = hackerman,
|
|
)
|
|
alert.name = "Domain Rebooting"
|
|
alert.desc = "The domain is rebooting. Find an exit."
|
|
|
|
|
|
/// Triggers whenever an antag steps onto an exit turf and the server is emagged
|
|
/datum/component/avatar_connection/proc/on_station_spawn(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/avatar = parent
|
|
avatar.playsound_local(avatar, 'sound/machines/terminal/terminal_alert.ogg', 50, vary = TRUE)
|
|
var/atom/movable/screen/alert/bitrunning/alert = avatar.throw_alert(
|
|
ALERT_BITRUNNER_BREACH,
|
|
/atom/movable/screen/alert/bitrunning,
|
|
new_master = source,
|
|
)
|
|
alert.name = "Security Breach"
|
|
alert.desc = "A hostile entity is breaching the safehouse. Find an exit."
|
|
|
|
|
|
/// Server has spawned a ghost role threat
|
|
/datum/component/avatar_connection/proc/on_threat_created(datum/source)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/avatar = parent
|
|
var/atom/movable/screen/alert/bitrunning/alert = avatar.throw_alert(
|
|
ALERT_BITRUNNER_THREAT,
|
|
/atom/movable/screen/alert/bitrunning,
|
|
new_master = source,
|
|
)
|
|
alert.name = "Threat Detected"
|
|
alert.desc = "Data stream abnormalities present."
|
|
|
|
|
|
/// Returns the mind to the old body
|
|
/datum/component/avatar_connection/proc/return_to_old_body()
|
|
var/datum/mind/old_mind = old_mind_ref?.resolve()
|
|
var/mob/living/old_body = old_body_ref?.resolve()
|
|
var/mob/living/avatar = parent
|
|
|
|
var/mob/dead/observer/ghost = avatar.ghostize()
|
|
if(isnull(ghost))
|
|
ghost = avatar.get_ghost()
|
|
|
|
if(isnull(ghost))
|
|
CRASH("[src] belonging to [parent] was completely unable to find a ghost to put back into a body!")
|
|
|
|
if(isnull(old_mind) || isnull(old_body))
|
|
return
|
|
|
|
for(var/skill_type in avatar.mind.known_skills)
|
|
old_mind.set_experience(skill_type, avatar.mind.get_skill_exp(skill_type), silent = TRUE)
|
|
avatar.mind.set_experience(skill_type, 0, silent = TRUE)
|
|
|
|
ghost.mind = old_mind
|
|
if(old_body.stat != DEAD)
|
|
old_mind.transfer_to(old_body, force_key_move = TRUE)
|
|
else
|
|
old_mind.set_current(old_body)
|
|
|
|
REMOVE_TRAIT(old_body, TRAIT_MIND_TEMPORARILY_GONE, REF(src))
|