diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index ea134741bec..3dd763ba3da 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -342,6 +342,8 @@
#define COMSIG_MIND_TRANSER_TO "mind_transfer_to"
///called on the mob instead of the mind
#define COMSIG_BODY_TRANSFER_TO "body_transfer_to"
+///called when the mind is initialized (called every time the mob logins)
+#define COMSIG_MIND_INITIALIZE "mind_initialize"
// /mob signals
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 5bde8280239..26d4ba5fa50 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -1786,6 +1786,7 @@
//Initialisation procs
/mob/proc/mind_initialize()
+ SHOULD_CALL_PARENT(TRUE)
if(mind)
mind.key = key
else
@@ -1797,6 +1798,7 @@
if(!mind.name)
mind.name = real_name
mind.current = src
+ SEND_SIGNAL(src, COMSIG_MIND_INITIALIZE)
//HUMAN
/mob/living/carbon/human/mind_initialize()
diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm
index 230aef4f95f..6b481b09daa 100644
--- a/code/datums/outfits/outfit.dm
+++ b/code/datums/outfits/outfit.dm
@@ -50,7 +50,20 @@
/datum/outfit/proc/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
//to be overriden for toggling internals, id binding, access etc
- return
+ SHOULD_CALL_PARENT(TRUE)
+ if(visualsOnly)
+ return
+
+ if(H.mind)
+ on_mind_initialize(H)
+ return
+ RegisterSignal(H, COMSIG_MIND_INITIALIZE, PROC_REF(on_mind_initialize))
+
+// Guaranteed access to mind, will never be called if visualsOnly = TRUE
+/datum/outfit/proc/on_mind_initialize(mob/living/carbon/human/H)
+ SIGNAL_HANDLER // COMSIG_MIND_INITIALIZE
+ SHOULD_CALL_PARENT(TRUE)
+ UnregisterSignal(H, COMSIG_MIND_INITIALIZE) // prevent this call from being called multiple times on a human
/datum/outfit/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE)
pre_equip(H, visualsOnly)
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index 0c8bb8c0d82..217b9658c0a 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -3,21 +3,15 @@
/datum/outfit/admin/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
- if(!visualsOnly && H.mind)
- H.mind.assigned_role = name
- H.job = name
-
-/datum/outfit/admin/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
- . = ..()
-
if(visualsOnly)
return
- if(H.mind)
- H.mind.offstation_role = TRUE
- else
- H.RegisterSignal(H, COMSIG_HUMAN_LOGIN, TYPE_PROC_REF(/mob/living/carbon/human, apply_offstation_roles))
+ H.job = name
+/datum/outfit/admin/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
+ H.mind.assigned_role = name
+ H.mind.offstation_role = TRUE
/proc/apply_to_card(obj/item/card/id/I, mob/living/carbon/human/H, list/access = list(), rank, special_icon)
if(!istype(I) || !istype(H))
@@ -1250,17 +1244,17 @@
if(istype(I))
apply_to_card(I, H, get_all_accesses(), "Ancient One", "data")
- if(H.mind)
- if(!H.mind.has_antag_datum(/datum/antagonist/vampire))
- H.mind.make_vampire(TRUE)
- var/datum/antagonist/vampire/V = H.mind.has_antag_datum(/datum/antagonist/vampire)
- V.bloodusable = 9999
- V.bloodtotal = 9999
- V.add_subclass(SUBCLASS_ANCIENT, FALSE)
- H.dna.SetSEState(GLOB.jumpblock, TRUE)
- singlemutcheck(H, GLOB.jumpblock, MUTCHK_FORCED)
- H.update_mutations()
- H.gene_stability = 100
+/datum/outfit/admin/ancient_vampire/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
+ H.mind.make_vampire()
+ var/datum/antagonist/vampire/V = H.mind.has_antag_datum(/datum/antagonist/vampire)
+ V.bloodusable = 9999
+ V.bloodtotal = 9999
+ V.add_subclass(SUBCLASS_ANCIENT, FALSE)
+ H.dna.SetSEState(GLOB.jumpblock, TRUE)
+ singlemutcheck(H, GLOB.jumpblock, MUTCHK_FORCED)
+ H.update_mutations()
+ H.gene_stability = 100
/datum/outfit/admin/wizard
name = "Blue Wizard"
@@ -1490,10 +1484,6 @@
H.real_name = "Unknown" //Enforcers sacrifice their name to Oblivion for their power
- for(var/spell_path in spell_paths)
- var/S = new spell_path
- H.mind.AddSpell(S)
-
var/obj/item/clothing/suit/hooded/oblivion/robes = H.wear_suit
if(istype(robes))
robes.ToggleHood()
@@ -1502,6 +1492,12 @@
if(istype(I))
apply_to_card(I, H, get_all_accesses(), "Oblivion Enforcer")
+/datum/outfit/admin/enforcer/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
+ for(var/spell_path in spell_paths)
+ var/S = new spell_path
+ H.mind.AddSpell(S)
+
/datum/outfit/admin/viper
name = "Solar Federation Viper Infiltrator"
diff --git a/code/game/dna/mutations/monkey_mutation.dm b/code/game/dna/mutations/monkey_mutation.dm
index 18334b1bd91..d1c4d7f960b 100644
--- a/code/game/dna/mutations/monkey_mutation.dm
+++ b/code/game/dna/mutations/monkey_mutation.dm
@@ -29,18 +29,17 @@
H.set_species(has_primitive_form, keep_missing_bodyparts = TRUE)
new /obj/effect/temp_visual/monkeyify(H.loc)
- sleep(22)
+ addtimer(CALLBACK(src, PROC_REF(finish_monkeyize), H, !has_primitive_form), 2.2 SECONDS)
+/datum/mutation/monkey/proc/finish_monkeyize(mob/living/carbon/human/H, should_gib)
H.invisibility = initial(H.invisibility)
- if(!has_primitive_form) //If the pre-change mob in question has no primitive set, this is going to be messy.
+ if(should_gib) //If the pre-change mob in question has no primitive set, this is going to be messy.
H.gib()
return
REMOVE_TRAITS_IN(H, TRANSFORMING_TRAIT)
to_chat(H, "You are now a [H.dna.species.name].")
- return H
-
/datum/mutation/monkey/deactivate(mob/living/carbon/human/H)
..()
if(!istype(H))
@@ -63,11 +62,13 @@
H.set_species(has_greater_form, keep_missing_bodyparts = TRUE)
new /obj/effect/temp_visual/monkeyify/humanify(H.loc)
- sleep(22)
+ addtimer(CALLBACK(src, PROC_REF(finish_unmonkeyize), H, !has_greater_form), 2.2 SECONDS)
+
+/datum/mutation/monkey/proc/finish_unmonkeyize(mob/living/carbon/human/H, should_gib)
REMOVE_TRAITS_IN(H, TRANSFORMING_TRAIT)
H.invisibility = initial(H.invisibility)
- if(!has_greater_form) //If the pre-change mob in question has no primitive set, this is going to be messy.
+ if(should_gib) //If the pre-change mob in question has no primitive set, this is going to be messy.
H.gib()
return
@@ -76,4 +77,3 @@
to_chat(H, "You are now a [H.dna.species.name].")
- return H
diff --git a/code/game/jobs/job/central.dm b/code/game/jobs/job/central.dm
index 7800f4b68a7..0f49925b52f 100644
--- a/code/game/jobs/job/central.dm
+++ b/code/game/jobs/job/central.dm
@@ -41,10 +41,8 @@
/obj/item/organ/internal/cyberimp/arm/combat/centcom
)
-/datum/outfit/job/ntnavyofficer/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+/datum/outfit/job/ntnavyofficer/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
- if(visualsOnly)
- return
H.mind.offstation_role = TRUE
// CC Officials who lead ERTs, Death Squads, etc.
@@ -97,10 +95,8 @@
/obj/item/organ/internal/cyberimp/arm/combat/centcom
)
-/datum/outfit/job/ntspecops/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+/datum/outfit/job/ntspecops/on_mind_initialize(mob/living/carbon/human/H)
. = ..()
- if(visualsOnly)
- return
H.mind.offstation_role = TRUE
/datum/job/ntspecops/solgovspecops
@@ -121,4 +117,7 @@
if(istype(I))
apply_to_card(I, H, get_centcom_access(name), name, "lifetimeid")
H.sec_hud_set_ID()
+
+/datum/outfit/job/ntspecops/solgovspecops/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
H.mind.offstation_role = TRUE
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 925e8e6f464..7ad8749098b 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -216,6 +216,7 @@
gear_leftovers += G
/datum/outfit/job/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
+ . = ..()
if(visualsOnly)
return
@@ -280,3 +281,16 @@
PDA.ownjob = C.assignment
PDA.ownrank = C.rank
PDA.name = "PDA-[H.real_name] ([PDA.ownjob])"
+
+/datum/outfit/job/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
+ var/obj/item/card/id/id = H.wear_id
+ if(!id)
+ return
+ var/datum/job/J = SSjobs.GetJobType(jobtype)
+ if(!J)
+ J = SSjobs.GetJob(H.job)
+ id.assignment = H.mind.role_alt_title ? H.mind.role_alt_title : J.title
+ if(!H.mind.initial_account)
+ return
+ id.associated_account_number = H.mind.initial_account.account_number
diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm
index 820b12c9a10..c8678be4e11 100644
--- a/code/game/jobs/job/support.dm
+++ b/code/game/jobs/job/support.dm
@@ -202,6 +202,9 @@
singlemutcheck(H, GLOB.soberblock, MUTCHK_FORCED)
H.dna.default_blocks.Add(GLOB.soberblock)
H.check_mutations = 1
+
+/datum/outfit/job/bartender/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
ADD_TRAIT(H.mind, TRAIT_TABLE_LEAP, ROUNDSTART_TRAIT)
ADD_TRAIT(H.mind, TRAIT_SLEIGHT_OF_HAND, ROUNDSTART_TRAIT)
@@ -236,12 +239,10 @@
/obj/item/paper/chef=1,\
/obj/item/book/manual/wiki/chef_recipes=1)
-/datum/outfit/job/chef/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
- ..()
- if(visualsOnly)
- return
+/datum/outfit/job/chef/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
var/datum/martial_art/cqc/under_siege/justacook = new
- justacook.teach(H)
+ justacook.teach(H) // requires mind
ADD_TRAIT(H.mind, TRAIT_TABLE_LEAP, ROUNDSTART_TRAIT)
@@ -419,12 +420,14 @@
if(visualsOnly)
return
- if(H.mind)
- H.mind.AddSpell(new /datum/spell/aoe/conjure/build/mime_wall(null))
- H.mind.AddSpell(new /datum/spell/mime/speak(null))
- H.mind.miming = 1
qdel(H.GetComponent(/datum/component/footstep))
+/datum/outfit/job/mime/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
+ H.mind.AddSpell(new /datum/spell/aoe/conjure/build/mime_wall(null))
+ H.mind.AddSpell(new /datum/spell/mime/speak(null))
+ H.mind.miming = TRUE
+
/datum/job/janitor
title = "Janitor"
flag = JOB_JANITOR
@@ -488,7 +491,7 @@
/datum/outfit/job/librarian/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
..()
- if(!H.mind)
+ if(visualsOnly)
return
for(var/la in GLOB.all_languages)
var/datum/language/new_language = GLOB.all_languages[la]
diff --git a/code/game/jobs/job/support_chaplain.dm b/code/game/jobs/job/support_chaplain.dm
index f97ccfb5422..e0193a6c9be 100644
--- a/code/game/jobs/job/support_chaplain.dm
+++ b/code/game/jobs/job/support_chaplain.dm
@@ -32,11 +32,12 @@
if(visualsOnly)
return
- if(istype(H.mind))
- ADD_TRAIT(H.mind, TRAIT_HOLY, ROUNDSTART_TRAIT)
-
INVOKE_ASYNC(src, PROC_REF(religion_pick), H)
+/datum/outfit/job/chaplain/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
+ ADD_TRAIT(H.mind, TRAIT_HOLY, ROUNDSTART_TRAIT)
+
/datum/outfit/job/chaplain/proc/religion_pick(mob/living/carbon/human/user)
var/obj/item/storage/bible/B = new /obj/item/storage/bible(get_turf(user))
B.customisable = TRUE // Only the initial bible is customisable
diff --git a/code/game/jobs/job/syndicate_jobs.dm b/code/game/jobs/job/syndicate_jobs.dm
index 089a5b26e4b..68a462ccc48 100644
--- a/code/game/jobs/job/syndicate_jobs.dm
+++ b/code/game/jobs/job/syndicate_jobs.dm
@@ -55,8 +55,11 @@
U.implant(H)
U.hidden_uplink.uses = 2500
H.faction += "syndicate"
+
+/datum/outfit/job/syndicateofficer/on_mind_initialize(mob/living/carbon/human/H)
+ . = ..()
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
opshud.join_hud(H.mind.current)
H.mind.offstation_role = TRUE
set_antag_hud(H.mind.current, "hudoperative")
- H.regenerate_icons()
+ INVOKE_ASYNC(H, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons))
diff --git a/code/modules/mob/living/carbon/human/human_mob.dm b/code/modules/mob/living/carbon/human/human_mob.dm
index 2c3d81904c3..eade62cabf0 100644
--- a/code/modules/mob/living/carbon/human/human_mob.dm
+++ b/code/modules/mob/living/carbon/human/human_mob.dm
@@ -1967,7 +1967,3 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
set category = "IC"
update_flavor_text()
-
-/mob/living/carbon/human/proc/apply_offstation_roles(source)
- SIGNAL_HANDLER
- mind.offstation_role = TRUE
diff --git a/code/modules/ruins/syndicate_space_base.dm b/code/modules/ruins/syndicate_space_base.dm
index 67d9fcc50df..3ec2451c0b6 100644
--- a/code/modules/ruins/syndicate_space_base.dm
+++ b/code/modules/ruins/syndicate_space_base.dm
@@ -61,6 +61,7 @@
)
/datum/outfit/spacebase_syndicate/post_equip(mob/living/carbon/human/H)
+ . = ..()
H.faction |= "syndicate"
var/random_name = random_name(pick(MALE,FEMALE), H.dna.species.name)
H.rename_character(H.real_name, random_name)