From 8f8d306f8083f5e8c96a00f29c6d2fda6a221d26 Mon Sep 17 00:00:00 2001
From: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com>
Date: Sun, 4 Aug 2024 04:14:14 -0400
Subject: [PATCH] Fixes cases of players getting sent to lobby, preference
runtimes, & cleans up split personality checks (#10536)
* knitting and knitting and knitting and
* check for clientless on login
* stuff I missed
* fix error
* comments
---
code/datums/brain_damage/imaginary_friend.dm | 9 ++-
code/datums/brain_damage/split_personality.dm | 63 ++++++++++---------
code/modules/antagonists/blob/overmind.dm | 4 +-
.../clock_cult/mobs/clockwork_marauder.dm | 2 +
.../antagonists/clock_cult/mobs/eminence.dm | 2 +
.../devil/true_devil/_true_devil.dm | 4 +-
code/modules/antagonists/revenant/revenant.dm | 4 +-
code/modules/holoparasite/_holoparasite.dm | 2 +
code/modules/mob/dead/dead.dm | 2 +
code/modules/mob/dead/new_player/login.dm | 6 +-
code/modules/mob/dead/observer/login.dm | 4 +-
code/modules/mob/living/carbon/alien/login.dm | 2 +
code/modules/mob/living/login.dm | 5 +-
code/modules/mob/living/silicon/ai/login.dm | 4 +-
code/modules/mob/living/silicon/login.dm | 2 +-
code/modules/mob/living/silicon/pai/pai.dm | 4 +-
.../modules/mob/living/silicon/robot/login.dm | 4 +-
.../mob/living/simple_animal/bot/bot.dm | 2 +
.../mob/living/simple_animal/constructs.dm | 4 +-
.../simple_animal/friendly/drone/_drone.dm | 4 +-
.../friendly/drone/extra_drone_types.dm | 4 +-
.../simple_animal/hostile/giant_spider.dm | 4 +-
code/modules/mob/login.dm | 27 +++++---
23 files changed, 118 insertions(+), 50 deletions(-)
diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm
index 181fbdcf2220e..b1c5d00fffd2d 100644
--- a/code/datums/brain_damage/imaginary_friend.dm
+++ b/code/datums/brain_damage/imaginary_friend.dm
@@ -8,6 +8,11 @@
var/friend_initialized = FALSE
/datum/brain_trauma/special/imaginary_friend/on_gain()
+ var/mob/living/M = owner
+ // dead or clientless mobs dont get the brain trauma
+ if(M.stat == DEAD || !M.client)
+ qdel(src)
+ return
..()
make_friend()
get_ghost()
@@ -78,7 +83,9 @@
var/datum/action/innate/imaginary_hide/hide
/mob/camera/imaginary_friend/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
greet()
Show()
diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm
index 9a7022348f8d4..ba9da36e06630 100644
--- a/code/datums/brain_damage/split_personality.dm
+++ b/code/datums/brain_damage/split_personality.dm
@@ -13,6 +13,11 @@
var/mob/living/split_personality/owner_backseat
/datum/brain_trauma/severe/split_personality/on_gain()
+ var/mob/living/M = owner
+ //Dead and braindead people dont get a second voice
+ if(M.stat == DEAD || !M.client)
+ qdel(src)
+ return
..()
make_backseats()
get_ghost()
@@ -28,9 +33,6 @@
/datum/brain_trauma/severe/split_personality/proc/get_ghost()
set waitfor = FALSE
- if(owner.stat == DEAD || !owner.mind)
- qdel(src)
- return
var/list/mob/dead/observer/candidates = poll_candidates_for_mob("Do you want to play as [owner]'s split personality?", ROLE_SPLIT_PERSONALITY, null, 7.5 SECONDS, stranger_backseat)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
@@ -43,7 +45,7 @@
/datum/brain_trauma/severe/split_personality/on_life()
if(owner.stat == DEAD)
if(current_controller != OWNER)
- switch_personalities()
+ switch_personalities(TRUE)
qdel(src)
else if(prob(3))
switch_personalities()
@@ -51,30 +53,27 @@
/datum/brain_trauma/severe/split_personality/on_lose()
if(current_controller != OWNER) //it would be funny to cure a guy only to be left with the other personality, but it seems too cruel
- switch_personalities()
+ switch_personalities(TRUE)
QDEL_NULL(stranger_backseat)
QDEL_NULL(owner_backseat)
..()
-/datum/brain_trauma/severe/split_personality/Destroy()
- if(stranger_backseat)
- QDEL_NULL(stranger_backseat)
- if(owner_backseat)
- QDEL_NULL(owner_backseat)
- return ..()
-/datum/brain_trauma/severe/split_personality/proc/switch_personalities()
+/datum/brain_trauma/severe/split_personality/proc/switch_personalities(reset_to_owner = FALSE)
if(QDELETED(owner) || owner.stat == DEAD || QDELETED(stranger_backseat) || QDELETED(owner_backseat))
return
var/mob/living/split_personality/current_backseat
- var/mob/living/split_personality/free_backseat
- if(current_controller == OWNER)
- current_backseat = stranger_backseat
- free_backseat = owner_backseat
- else
+ var/mob/living/split_personality/new_backseat
+ if(current_controller == STRANGER || reset_to_owner)
current_backseat = owner_backseat
- free_backseat = stranger_backseat
+ new_backseat = stranger_backseat
+ else
+ current_backseat = stranger_backseat
+ new_backseat = owner_backseat
+
+ if(!current_backseat.client) //Make sure we never switch to a logged off mob.
+ return
log_game("[key_name(current_backseat)] assumed control of [key_name(owner)] due to [src]. (Original owner: [current_controller == OWNER ? owner.key : current_backseat.key])")
to_chat(owner, "You feel your control being taken away... your other personality is in charge now!")
@@ -87,18 +86,21 @@
owner.computer_id = null
owner.lastKnownIP = null
- free_backseat.ckey = owner.ckey
+ new_backseat.ckey = owner.ckey
- free_backseat.name = owner.name
+ new_backseat.name = owner.name
if(owner.mind)
- free_backseat.mind = owner.mind
+ new_backseat.mind = owner.mind
- if(!free_backseat.computer_id)
- free_backseat.computer_id = h2b_id
+ if(!new_backseat.computer_id)
+ new_backseat.computer_id = h2b_id
- if(!free_backseat.lastKnownIP)
- free_backseat.lastKnownIP = h2b_ip
+ if(!new_backseat.lastKnownIP)
+ new_backseat.lastKnownIP = h2b_ip
+
+ if(reset_to_owner && new_backseat.mind)
+ new_backseat.ghostize(FALSE)
//Backseat to body
@@ -149,7 +151,9 @@
..()
/mob/living/split_personality/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
to_chat(src, "As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality.")
to_chat(src, "Do not commit suicide or put the body in a deadly position. Behave like you care about it as much as the owner.")
@@ -207,8 +211,9 @@
return //no random switching
/datum/brain_trauma/severe/split_personality/brainwashing/handle_hearing(datum/source, list/hearing_args)
- if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER])
+ if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER])
return
+
var/message = hearing_args[HEARING_RAW_MESSAGE]
if(findtext(message, codeword))
hearing_args[HEARING_RAW_MESSAGE] = replacetext(message, codeword, "[codeword]")
@@ -225,7 +230,9 @@
var/codeword
/mob/living/split_personality/traitor/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
to_chat(src, "As a brainwashed personality, you cannot do anything yet but observe. However, you may gain control of your body if you hear the special codeword, switching places with the current personality.")
to_chat(src, "Your activation codeword is: [codeword]")
if(objective)
diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm
index 295ca0a6e8fa9..792640428c5af 100644
--- a/code/modules/antagonists/blob/overmind.dm
+++ b/code/modules/antagonists/blob/overmind.dm
@@ -197,7 +197,9 @@ GLOBAL_LIST_EMPTY(blob_nodes)
return ..()
/mob/camera/blob/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
to_chat(src, "You are the overmind!")
blob_help()
update_health_hud()
diff --git a/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm b/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm
index 2e7bfb21164af..a3078affd54aa 100644
--- a/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm
+++ b/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm
@@ -49,6 +49,8 @@ GLOBAL_LIST_EMPTY(clockwork_marauders)
/mob/living/simple_animal/hostile/clockwork_marauder/Login()
. = ..()
+ if(!. || !client)
+ return FALSE
add_servant_of_ratvar(src)
to_chat(src, "You can block up to 4 attacks with your shield, however it requires a welder to be repaired.")
diff --git a/code/modules/antagonists/clock_cult/mobs/eminence.dm b/code/modules/antagonists/clock_cult/mobs/eminence.dm
index 06056a2d9e95f..a197b70acae51 100644
--- a/code/modules/antagonists/clock_cult/mobs/eminence.dm
+++ b/code/modules/antagonists/clock_cult/mobs/eminence.dm
@@ -101,6 +101,8 @@
/mob/living/simple_animal/eminence/Login()
. = ..()
+ if(!. || !client)
+ return FALSE
var/datum/antagonist/servant_of_ratvar/S = add_servant_of_ratvar(src, silent=TRUE)
S.prefix = CLOCKCULT_PREFIX_EMINENCE
to_chat(src, "You are the Eminence!")
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index c519964eda108..23d8640448406 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -58,7 +58,9 @@
real_name = name
/mob/living/carbon/true_devil/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
var/datum/antagonist/devil/devilinfo = mind.has_antag_datum(/datum/antagonist/devil)
devilinfo.greet()
mind.announce_objectives()
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index ec1ab12c6282b..696d00bbe2ee1 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -115,7 +115,9 @@
name = built_name
/mob/living/simple_animal/revenant/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
to_chat(src, "You are a revenant.")
to_chat(src, "Your formerly mundane spirit has been infused with alien energies and empowered into a revenant.")
to_chat(src, "You are not dead, not alive, but somewhere in between. You are capable of limited interaction with both worlds.")
diff --git a/code/modules/holoparasite/_holoparasite.dm b/code/modules/holoparasite/_holoparasite.dm
index 99fdb77fbe344..ab53ae325ae8c 100644
--- a/code/modules/holoparasite/_holoparasite.dm
+++ b/code/modules/holoparasite/_holoparasite.dm
@@ -140,6 +140,8 @@ GLOBAL_LIST_EMPTY_TYPED(holoparasites, /mob/living/simple_animal/hostile/holopar
if(mind && key && key != mind.key) // Ooh, new player!
first_time_show_popup = mind.has_antag_datum(/datum/antagonist/holoparasite)
. = ..()
+ if(!. || !client)
+ return FALSE
if(mind)
mind.name = "[real_name]"
if(QDELETED(summoner?.current))
diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm
index 235b7b8dd3ae0..9067617c458fa 100644
--- a/code/modules/mob/dead/dead.dm
+++ b/code/modules/mob/dead/dead.dm
@@ -102,6 +102,8 @@ INITIALIZE_IMMEDIATE(/mob/dead)
/mob/dead/Login()
. = ..()
+ if(!. || !client)
+ return FALSE
var/turf/T = get_turf(src)
if (isturf(T))
update_z(T.z)
diff --git a/code/modules/mob/dead/new_player/login.dm b/code/modules/mob/dead/new_player/login.dm
index ef150786f64c8..562377de00801 100644
--- a/code/modules/mob/dead/new_player/login.dm
+++ b/code/modules/mob/dead/new_player/login.dm
@@ -1,4 +1,6 @@
/mob/dead/new_player/Login()
+ if(!client)
+ return
if(CONFIG_GET(flag/use_exp_tracking))
client.set_exp_from_db()
if(!client) // client null during sleep
@@ -11,7 +13,9 @@
mind.active = TRUE
mind.set_current(src)
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
var/motd = global.config.motd
if(motd)
diff --git a/code/modules/mob/dead/observer/login.dm b/code/modules/mob/dead/observer/login.dm
index 9bb48f0c46380..b2c114412bfa2 100644
--- a/code/modules/mob/dead/observer/login.dm
+++ b/code/modules/mob/dead/observer/login.dm
@@ -1,5 +1,7 @@
/mob/dead/observer/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
ghost_accs = client.prefs.read_player_preference(/datum/preference/choiced/ghost_accessories)
ghost_others = client.prefs.read_player_preference(/datum/preference/choiced/ghost_others)
diff --git a/code/modules/mob/living/carbon/alien/login.dm b/code/modules/mob/living/carbon/alien/login.dm
index bb6eb084becca..13383568cfe9c 100644
--- a/code/modules/mob/living/carbon/alien/login.dm
+++ b/code/modules/mob/living/carbon/alien/login.dm
@@ -1,3 +1,5 @@
/mob/living/carbon/alien/Login()
. = ..()
+ if(!. || !client)
+ return FALSE
AddInfectionImages()
diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm
index c8f1f02c6bc9b..388d0ba0f5ccf 100644
--- a/code/modules/mob/living/login.dm
+++ b/code/modules/mob/living/login.dm
@@ -1,5 +1,8 @@
/mob/living/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
+
//Mind updates
sync_mind()
mind.show_memory(src, 0)
diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm
index 2909b915bb888..ae8bcc4af66e5 100644
--- a/code/modules/mob/living/silicon/ai/login.dm
+++ b/code/modules/mob/living/silicon/ai/login.dm
@@ -1,5 +1,7 @@
/mob/living/silicon/ai/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
if(stat != DEAD)
if(lacks_power() && apc_override) //Placing this in Login() in case the AI doesn't have this link for whatever reason.
to_chat(usr, "Main power is unavailable, backup power in use. Diagnostics scan complete. Local APC ready for connection.")
diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm
index 541736da1a6a1..9b787a67797b2 100644
--- a/code/modules/mob/living/silicon/login.dm
+++ b/code/modules/mob/living/silicon/login.dm
@@ -4,7 +4,7 @@
var/datum/antagonist/rev/rev = mind.has_antag_datum(/datum/antagonist/rev)
if(rev)
rev.remove_revolutionary(TRUE)
- ..()
+ return ..()
/mob/living/silicon/auto_deadmin_on_login()
if(!client?.holder)
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 776db4f3d618a..a3f4d8aac6c34 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -214,7 +214,9 @@
return TRUE
/mob/living/silicon/pai/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
var/datum/asset/notes_assets = get_asset_datum(/datum/asset/simple/pAI)
mind.assigned_role = JOB_NAME_PAI
notes_assets.send(client)
diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm
index 3856dd40d1564..86c3f731ea99c 100644
--- a/code/modules/mob/living/silicon/robot/login.dm
+++ b/code/modules/mob/living/silicon/robot/login.dm
@@ -1,5 +1,7 @@
/mob/living/silicon/robot/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
regenerate_icons()
show_laws(0)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index feb949acb46fd..f4b33a44b3aed 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -1096,6 +1096,8 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/Login()
. = ..()
+ if(!. || !client)
+ return FALSE
access_card.access |= player_access
diag_hud_set_botmode()
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index f4eabf999266a..b85c5fd56f5ba 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -78,7 +78,9 @@
return ..()
/mob/living/simple_animal/hostile/construct/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
to_chat(src, playstyle_string)
/mob/living/simple_animal/hostile/construct/examine(mob/user)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index bfbc47a96fde7..56faa85c449d3 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -133,7 +133,9 @@
return ..()
/mob/living/simple_animal/drone/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
check_laws()
if(flavortext)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
index eef94e2393bb9..3b84f59d2d989 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
@@ -37,7 +37,9 @@
hidden_uplink.telecrystals = 10
/mob/living/simple_animal/drone/syndrone/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
to_chat(src, "You can kill and eat other drones to increase your health!" )
/mob/living/simple_animal/drone/syndrone/badass
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index 0dbf2e9fc3522..ce8b371221c03 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -95,7 +95,9 @@
return ..()
/mob/living/simple_animal/hostile/poison/giant_spider/Login()
- ..()
+ . = ..()
+ if(!. || !client)
+ return FALSE
SSmove_manager.stop_looping(src) // Just in case the AI's doing anything when we give them the mind
GLOB.spidermobs[src] = TRUE
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index 86e273cc09423..b1438706f2dae 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -21,9 +21,12 @@
* * grant any actions the mob has to the client
* * calls [auto_deadmin_on_login](mob.html#proc/auto_deadmin_on_login)
* * send signal COMSIG_MOB_CLIENT_LOGIN
+ * * client can be deleted mid-execution of this proc, chiefly on parent calls, with lag
* * attaches the ash listener element so clients can hear weather
*/
/mob/Login()
+ if(!client)
+ return FALSE
// set_eye() is important here, because your eye doesn't know if you're using them as your eye
// FALSE when weakref doesn't exist, to prevent using their current eye
client.set_eye(client.eye, client.eye_weakref?.resolve() || FALSE)
@@ -32,28 +35,36 @@
computer_id = client.computer_id
log_access("Mob Login: [key_name(src)] was assigned to a [type]")
world.update_status()
- client.screen = list() //remove hud items just in case
+ client.screen = list() //remove hud items just in case
client.images = list()
if(!hud_used)
- create_mob_hud()
+ create_mob_hud() // creating a hud will add it to the client's screen, which can process a disconnect
+ if(!client)
+ return FALSE
+
if(hud_used)
- hud_used.show_hud(hud_used.hud_version)
+ hud_used.show_hud(hud_used.hud_version) // see above, this can process a disconnect
+ if(!client)
+ return FALSE
hud_used.update_ui_style(ui_style2icon(client.prefs?.read_player_preference(/datum/preference/choiced/ui_style)))
next_move = 1
..()
- if (client && key != client.key)
+ if(!client)
+ return FALSE
+
+ SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
+
+ if (key != client.key)
key = client.key
reset_perspective(loc)
if(loc)
loc.on_log(TRUE)
- SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
-
//readd this mob's HUDs (antag, med, etc)
reload_huds()
@@ -100,10 +111,12 @@
log_message("Client [key_name(src)] has taken ownership of mob [src]([src.type])", LOG_OWNERSHIP)
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
- SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_LOGGED_IN, src)
AddElement(/datum/element/weather_listener, /datum/weather/ash_storm, ZTRAIT_ASHSTORM, GLOB.ash_storm_sounds)
+ SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_LOGGED_IN, src)
+
+ return TRUE
/**
* Checks if the attached client is an admin and may deadmin them