Persistent clients and body recovery (#29974)

* Persistent clients and body recovery

* Update code/_globalvars/lists/mob_lists.dm

Co-authored-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>

---------

Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>
Co-authored-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
This commit is contained in:
Charlie Nolan
2025-08-19 13:42:43 +00:00
committed by GitHub
co-authored by PollardTheDragon
parent e43a88de5b
commit 1d068fe25c
25 changed files with 128 additions and 93 deletions
@@ -803,17 +803,19 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return TRUE
/mob/dead/observer/proc/incarnate_ghost()
/mob/dead/observer/proc/incarnate_ghost(datum/mind/from_mind = null)
if(!client)
return
var/mob/living/carbon/human/new_char = new(get_turf(src))
client.prefs.active_character.copy_to(new_char)
if(mind)
mind.active = TRUE
mind.transfer_to(new_char)
var/mob/new_char
if(from_mind)
new_char = json_to_object(from_mind.destroyed_body_json, get_turf(src))
from_mind.transfer_to(new_char)
else
new_char.key = key
new_char = new /mob/living/carbon/human(get_turf(src))
client.prefs.active_character.copy_to(new_char)
if(!new_char.ckey)
new_char.ckey = ckey
return new_char
+1 -1
View File
@@ -57,7 +57,7 @@
S.be_replaced()
QDEL_NULL(middleClickOverride)
if(mind?.current == src)
mind.current = null
mind.unbind()
UnregisterSignal(src, COMSIG_ATOM_PREHIT)
return ..()
@@ -1626,7 +1626,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
custom_name = borgname
real_name = name
mind = new
mind.current = src
mind.bind_to(src)
mind.set_original_mob(src)
mind.assigned_role = SPECIAL_ROLE_ERT
mind.special_role = SPECIAL_ROLE_ERT
@@ -126,7 +126,7 @@
return FALSE
layer = MOB_LAYER
if(client)
client.time_died_as_mouse = world.time
client.persistent.time_died_as_mouse = world.time
/*
* Mouse types
+4 -7
View File
@@ -965,9 +965,6 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
/mob/proc/is_mechanical()
return mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI")
/mob/proc/is_ready()
return client && !!mind
/mob/proc/is_in_brig()
if(!loc || !loc.loc)
return 0
@@ -1107,8 +1104,8 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
* Returns true if the player successfully becomes a mouse
*/
/mob/proc/become_mouse()
var/timedifference = world.time - client.time_died_as_mouse
if(client.time_died_as_mouse && timedifference <= GLOB.mouse_respawn_time * 600)
var/timedifference = world.time - client.persistent.time_died_as_mouse
if(client.persistent.time_died_as_mouse && timedifference <= GLOB.mouse_respawn_time * 600)
var/timedifference_text = time2text(GLOB.mouse_respawn_time * 600 - timedifference,"mm:ss")
to_chat(src, "<span class='warning'>You may only spawn again as a mouse more than [GLOB.mouse_respawn_time] minutes after your death. You have [timedifference_text] left.</span>")
return FALSE
@@ -1519,10 +1516,10 @@ GLOBAL_LIST_INIT(holy_areas, typecacheof(list(
// Pretend we've always succeeded when we might not have.
// This should prevent people from using it to suss anything out about mobs' states
if(!client || !target.mind)
if(!client || !target.client)
return
target.mind.kudos_received_from |= ckey
target.client.persistent.kudos_received_from |= ckey
/mob/living/simple_animal/relaymove(mob/living/user, direction)
if(user.incapacitated())
+7 -6
View File
@@ -19,7 +19,8 @@
/mob/new_player/Destroy()
if(mind)
mind.current = null // We best null their mind as well, otherwise /every/ single new player is going to explode the server a little more going in/out of the round
// Minds really shouldn't bind to new players, but just in case...
mind.unbind()
return ..()
/mob/new_player/proc/new_player_panel()
@@ -62,11 +63,11 @@
var/list/antags = client.prefs.be_special
if(length(antags))
if(!client.skip_antag)
if(!client.persistent.skip_antag)
output += "<p><a href='byond://?src=[UID()];skip_antag=1'>Global Antag Candidacy</A>"
else
output += "<p><a href='byond://?src=[UID()];skip_antag=2'>Global Antag Candidacy</A>"
output += "<br /><small>You are <b>[client.skip_antag ? "ineligible" : "eligible"]</b> for all antag roles.</small></p>"
output += "<br /><small>You are <b>[client.persistent.skip_antag ? "ineligible" : "eligible"]</b> for all antag roles.</small></p>"
if(SSticker.current_state == GAME_STATE_STARTUP)
output += "<p>Observe (Please wait...)</p>"
@@ -143,7 +144,7 @@
new_player_panel_proc()
if(href_list["skip_antag"])
client.skip_antag = !client.skip_antag
client.persistent.skip_antag = !client.persistent.skip_antag
new_player_panel_proc()
if(href_list["refresh"])
@@ -613,8 +614,8 @@
if(!client || !client.prefs) ..()
return client.prefs.active_character.gender
/mob/new_player/is_ready()
return ready && ..()
/mob/new_player/proc/is_ready()
return ready && client
// No hearing announcements
/mob/new_player/can_hear()
@@ -3,11 +3,6 @@
if(GLOB.join_motd)
to_chat(src, "<div class='motd'>[GLOB.join_motd]</div>")
if(!mind)
mind = new /datum/mind(key)
mind.active = TRUE
mind.current = src
if(length(GLOB.newplayer_start))
loc = pick(GLOB.newplayer_start)
else