/* Note from Carnie:
The way datum/mind stuff works has been changed a lot.
Minds now represent IC characters rather than following a client around constantly.
Guidelines for using minds properly:
- Never mind.transfer_to(ghost). The var/current and var/original of a mind must always be of type mob/living!
ghost.mind is however used as a reference to the ghost's corpse
- When creating a new mob for an existing IC character (e.g. cloning a dead guy or borging a brain of a human)
the existing mind of the old mob should be transfered to the new mob like so:
mind.transfer_to(new_mob)
- You must not assign key= or ckey= after transfer_to() since the transfer_to transfers the client for you.
By setting key or ckey explicitly after transferring the mind with transfer_to you will cause bugs like DCing
the player.
- IMPORTANT NOTE 2, if you want a player to become a ghost, use mob.ghostize() It does all the hard work for you.
- When creating a new mob which will be a new IC character (e.g. putting a shade in a construct or randomly selecting
a ghost to become a xeno during an event). Simply assign the key or ckey like you've always done.
new_mob.key = key
The Login proc will handle making a new mind for that mobtype (including setting up stuff like mind.name). Simple!
However if you want that mind to have any special properties like being a traitor etc you will have to do that
yourself.
*/
/datum/mind
var/key
var/name //replaces mob/var/original_name
var/mob/living/current
var/active = 0
var/memory
var/assigned_role
var/special_role
var/list/restricted_roles = list()
var/list/datum/objective/objectives = list()
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
var/linglink
var/datum/martial_art/martial_art
var/static/default_martial_art = new/datum/martial_art
var/miming = 0 // Mime's vow of silence
var/list/antag_datums
var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state
var/datum/atom_hud/antag/antag_hud = null //this mind's antag HUD
var/damnation_type = 0
var/datum/mind/soulOwner //who owns the soul. Under normal circumstances, this will point to src
var/hasSoul = TRUE // If false, renders the character unable to sell their soul.
var/isholy = FALSE //is this person a chaplain or admin role allowed to use bibles
var/mob/living/enslaved_to //If this mind's master is another mob (i.e. adamantine golems)
var/datum/language_holder/language_holder
var/unconvertable = FALSE
var/late_joiner = FALSE
var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator
/datum/mind/New(var/key)
src.key = key
soulOwner = src
martial_art = default_martial_art
/datum/mind/Destroy()
SSticker.minds -= src
if(islist(antag_datums))
for(var/i in antag_datums)
var/datum/antagonist/antag_datum = i
if(antag_datum.delete_on_mind_deletion)
qdel(i)
antag_datums = null
return ..()
/datum/mind/proc/get_language_holder()
if(!language_holder)
var/datum/language_holder/L = current.get_language_holder(shadow=FALSE)
language_holder = L.copy(src)
return language_holder
/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0)
if(current) // remove ourself from our old body's mind variable
current.mind = null
SStgui.on_transfer(current, new_character)
if(!language_holder)
var/datum/language_holder/mob_holder = new_character.get_language_holder(shadow = FALSE)
language_holder = mob_holder.copy(src)
if(key)
if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours
new_character.ghostize(1) //we'll need to ghostize so that key isn't mobless.
else
key = new_character.key
if(new_character.mind) //disassociate any mind currently in our new body's mind variable
new_character.mind.current = null
var/datum/atom_hud/antag/hud_to_transfer = antag_hud//we need this because leave_hud() will clear this list
var/mob/living/old_current = current
if(current)
current.transfer_observers_to(new_character) //transfer anyone observing the old character to the new one
current = new_character //associate ourself with our new body
new_character.mind = src //and associate our new body with ourself
for(var/a in antag_datums) //Makes sure all antag datums effects are applied in the new body
var/datum/antagonist/A = a
A.on_body_transfer(old_current, current)
if(iscarbon(new_character))
var/mob/living/carbon/C = new_character
C.last_mind = src
transfer_antag_huds(hud_to_transfer) //inherit the antag HUD
transfer_actions(new_character)
transfer_martial_arts(new_character)
if(active || force_key_move)
new_character.key = key //now transfer the key to link the client to our new body
//CIT CHANGE - makes arousal update when transfering bodies
if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs.
var/mob/living/L = new_character
if(L.client && L.client.prefs)
L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting...
L.update_arousal_hud() //Removes the old icon
/datum/mind/proc/store_memory(new_text)
memory += "[new_text]
"
/datum/mind/proc/wipe_memory()
memory = null
// Datum antag mind procs
/datum/mind/proc/add_antag_datum(datum_type_or_instance, team)
if(!datum_type_or_instance)
return
var/datum/antagonist/A
if(!ispath(datum_type_or_instance))
A = datum_type_or_instance
if(!istype(A))
return
else
A = new datum_type_or_instance()
//Choose snowflake variation if antagonist handles it
var/datum/antagonist/S = A.specialization(src)
if(S && S != A)
qdel(A)
A = S
if(!A.can_be_owned(src))
qdel(A)
return
A.owner = src
LAZYADD(antag_datums, A)
A.create_team(team)
var/datum/team/antag_team = A.get_team()
if(antag_team)
antag_team.add_member(src)
A.on_gain()
return A
/datum/mind/proc/remove_antag_datum(datum_type)
if(!datum_type)
return
var/datum/antagonist/A = has_antag_datum(datum_type)
if(A)
A.on_removal()
return TRUE
/datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us.
for(var/a in antag_datums)
var/datum/antagonist/A = a
A.on_removal()
/datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE)
if(!datum_type)
return
. = FALSE
for(var/a in antag_datums)
var/datum/antagonist/A = a
if(check_subtypes && istype(A, datum_type))
return A
else if(A.type == datum_type)
return A
/*
Removes antag type's references from a mind.
objectives, uplinks, powers etc are all handled.
*/
/datum/mind/proc/remove_changeling()
var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling)
if(C)
remove_antag_datum(/datum/antagonist/changeling)
special_role = null
/datum/mind/proc/remove_traitor()
remove_antag_datum(/datum/antagonist/traitor)
/datum/mind/proc/remove_brother()
if(src in SSticker.mode.brothers)
remove_antag_datum(/datum/antagonist/brother)
SSticker.mode.update_brother_icons_removed(src)
/datum/mind/proc/remove_nukeop()
var/datum/antagonist/nukeop/nuke = has_antag_datum(/datum/antagonist/nukeop,TRUE)
if(nuke)
remove_antag_datum(nuke.type)
special_role = null
/datum/mind/proc/remove_wizard()
remove_antag_datum(/datum/antagonist/wizard)
special_role = null
/datum/mind/proc/remove_cultist()
if(src in SSticker.mode.cult)
SSticker.mode.remove_cultist(src, 0, 0)
special_role = null
remove_antag_equip()
/datum/mind/proc/remove_rev()
var/datum/antagonist/rev/rev = has_antag_datum(/datum/antagonist/rev)
if(rev)
remove_antag_datum(rev.type)
special_role = null
/datum/mind/proc/remove_antag_equip()
var/list/Mob_Contents = current.get_contents()
for(var/obj/item/I in Mob_Contents)
var/datum/component/uplink/O = I.GetComponent(/datum/component/uplink)
//Todo make this reset signal
if(O)
O.unlock_code = null
/datum/mind/proc/remove_all_antag() //For the Lazy amongst us.
remove_changeling()
remove_traitor()
remove_nukeop()
remove_wizard()
remove_cultist()
remove_rev()
SSticker.mode.update_cult_icons_removed(src)
/datum/mind/proc/equip_traitor(employer = "The Syndicate", silent = FALSE, datum/antagonist/uplink_owner)
if(!current)
return
var/mob/living/carbon/human/traitor_mob = current
if (!istype(traitor_mob))
return
var/list/all_contents = traitor_mob.GetAllContents()
var/obj/item/pda/PDA = locate() in all_contents
var/obj/item/radio/R = locate() in all_contents
var/obj/item/pen/P
if (PDA) // Prioritize PDA pen, otherwise the pocket protector pens will be chosen, which causes numerous ahelps about missing uplink
P = locate() in PDA
if (!P) // If we couldn't find a pen in the PDA, or we didn't even have a PDA, do it the old way
P = locate() in all_contents
if(!P) // I do not have a pen.
var/obj/item/pen/inowhaveapen
if(istype(traitor_mob.back,/obj/item/storage)) //ok buddy you better have a backpack!
inowhaveapen = new /obj/item/pen(traitor_mob.back)
else
inowhaveapen = new /obj/item/pen(traitor_mob.loc)
traitor_mob.put_in_hands(inowhaveapen) // I hope you don't have arms and your traitor pen gets stolen for all this trouble you've caused.
P = inowhaveapen
var/obj/item/uplink_loc
if(traitor_mob.client && traitor_mob.client.prefs)
switch(traitor_mob.client.prefs.uplink_spawn_loc)
if(UPLINK_PDA)
uplink_loc = PDA
if(!uplink_loc)
uplink_loc = R
if(!uplink_loc)
uplink_loc = P
if(UPLINK_RADIO)
uplink_loc = R
if(!uplink_loc)
uplink_loc = PDA
if(!uplink_loc)
uplink_loc = P
if(UPLINK_PEN)
uplink_loc = P
if(!uplink_loc)
uplink_loc = PDA
if(!uplink_loc)
uplink_loc = R
if (!uplink_loc)
if(!silent)
to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
. = 0
else
. = uplink_loc
var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
if(!U)
CRASH("Uplink creation failed.")
U.setup_unlock_code()
if(!silent)
if(uplink_loc == R)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.")
else if(uplink_loc == PDA)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.")
else if(uplink_loc == P)
to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.")
if(uplink_owner)
uplink_owner.antag_memory += U.unlock_note + "
"
else
traitor_mob.mind.store_memory(U.unlock_note)
//Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does.
/datum/mind/proc/enslave_mind_to_creator(mob/living/creator)
if(iscultist(creator))
SSticker.mode.add_cultist(src)
else if(is_revolutionary(creator))
var/datum/antagonist/rev/converter = creator.mind.has_antag_datum(/datum/antagonist/rev,TRUE)
converter.add_revolutionary(src,FALSE)
else if(is_servant_of_ratvar(creator))
add_servant_of_ratvar(current)
else if(is_nuclear_operative(creator))
var/datum/antagonist/nukeop/converter = creator.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE)
var/datum/antagonist/nukeop/N = new()
N.send_to_spawnpoint = FALSE
N.nukeop_outfit = null
add_antag_datum(N,converter.nuke_team)
enslaved_to = creator
current.faction |= creator.faction
creator.faction |= current.faction
if(creator.mind.special_role)
message_admins("[ADMIN_LOOKUPFLW(current)] has been created by [ADMIN_LOOKUPFLW(creator)], an antagonist.")
to_chat(current, "Despite your creators current allegiances, your true master remains [creator.real_name]. If their loyalties change, so do yours. This will never change unless your creator's body is destroyed.")
/datum/mind/proc/show_memory(mob/recipient, window=1)
if(!recipient)
recipient = current
var/output = "[current.real_name]'s Memories:
"
output += memory
for(var/datum/antagonist/A in antag_datums)
output += A.antag_memory
if(objectives.len)
output += "Objectives:"
var/obj_count = 1
for(var/datum/objective/objective in objectives)
output += "
Objective #[obj_count++]: [objective.explanation_text]"
var/list/datum/mind/other_owners = objective.get_owners() - src
if(other_owners.len)
output += "
"
for(var/datum/mind/M in other_owners)
output += "- Conspirator: [M.name]
"
output += "
"
if(window)
recipient << browse(output,"window=memory")
else if(objectives.len || memory)
to_chat(recipient, "[output]")
/datum/mind/Topic(href, href_list)
if(!check_rights(R_ADMIN))
return
var/self_antagging = usr == current
if(href_list["add_antag"])
add_antag_wrapper(text2path(href_list["add_antag"]),usr)
if(href_list["remove_antag"])
var/datum/antagonist/A = locate(href_list["remove_antag"]) in antag_datums
if(!istype(A))
to_chat(usr,"Invalid antagonist ref to be removed.")
return
A.admin_remove(usr)
if (href_list["role_edit"])
var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in get_all_jobs()
if (!new_role)
return
assigned_role = new_role
else if (href_list["memory_edit"])
var/new_memo = copytext(sanitize(input("Write new memory", "Memory", memory) as null|message),1,MAX_MESSAGE_LEN)
if (isnull(new_memo))
return
memory = new_memo
else if (href_list["obj_edit"] || href_list["obj_add"])
var/datum/objective/objective
var/objective_pos
var/def_value
var/datum/antagonist/target_antag
if (href_list["obj_edit"])
objective = locate(href_list["obj_edit"])
if (!objective)
return
for(var/datum/antagonist/A in antag_datums)
if(objective in A.objectives)
target_antag = A
objective_pos = A.objectives.Find(objective)
break
if(!target_antag) //Shouldn't happen anymore
stack_trace("objective without antagonist found")
objective_pos = objectives.Find(objective)
//Text strings are easy to manipulate. Revised for simplicity.
var/temp_obj_type = "[objective.type]"//Convert path into a text string.
def_value = copytext(temp_obj_type, 19)//Convert last part of path into an objective keyword.
if(!def_value)//If it's a custom objective, it will be an empty string.
def_value = "custom"
else
//We're adding this objective
if(href_list["target_antag"])
var/datum/antagonist/X = locate(href_list["target_antag"]) in antag_datums
if(X)
target_antag = X
if(!target_antag)
switch(antag_datums.len)
if(0)
target_antag = add_antag_datum(/datum/antagonist/custom)
if(1)
target_antag = antag_datums[1]
else
var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", def_value) as null|anything in antag_datums + "(new custom antag)"
if (QDELETED(target))
return
else if(target == "(new custom antag)")
target_antag = add_antag_datum(/datum/antagonist/custom)
else
target_antag = target
var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom")
if (!new_obj_type)
return
var/datum/objective/new_objective = null
switch (new_obj_type)
if ("assassinate","protect","debrain","maroon")
var/list/possible_targets = list("Free objective")
for(var/datum/mind/possible_target in SSticker.minds)
if ((possible_target != src) && ishuman(possible_target.current))
possible_targets += possible_target.current
var/mob/def_target = null
var/list/objective_list = typecacheof(list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain, /datum/objective/maroon))
if (is_type_in_typecache(objective, objective_list) && objective.target)
def_target = objective.target.current
var/mob/new_target = input("Select target:", "Objective target", def_target) as null|anything in possible_targets
if (!new_target)
return
var/objective_path = text2path("/datum/objective/[new_obj_type]")
if (new_target == "Free objective")
new_objective = new objective_path
new_objective.owner = src
new_objective.target = null
new_objective.explanation_text = "Free objective"
else
new_objective = new objective_path
new_objective.owner = src
new_objective.target = new_target.mind
//Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops.
new_objective.update_explanation_text()
if ("destroy")
var/list/possible_targets = active_ais(1)
if(possible_targets.len)
var/mob/new_target = input("Select target:", "Objective target") as null|anything in possible_targets
new_objective = new /datum/objective/destroy
new_objective.target = new_target.mind
new_objective.owner = src
new_objective.update_explanation_text()
else
to_chat(usr, "No active AIs with minds")
if ("prevent")
new_objective = new /datum/objective/block
new_objective.owner = src
if ("hijack")
new_objective = new /datum/objective/hijack
new_objective.owner = src
if ("escape")
new_objective = new /datum/objective/escape
new_objective.owner = src
if ("survive")
new_objective = new /datum/objective/survive
new_objective.owner = src
if("martyr")
new_objective = new /datum/objective/martyr
new_objective.owner = src
if ("nuclear")
new_objective = new /datum/objective/nuclear
new_objective.owner = src
if ("steal")
if (!istype(objective, /datum/objective/steal))
new_objective = new /datum/objective/steal
new_objective.owner = src
else
new_objective = objective
var/datum/objective/steal/steal = new_objective
if (!steal.select_target())
return
if("download","capture","absorb")
var/def_num
if(objective&&objective.type==text2path("/datum/objective/[new_obj_type]"))
def_num = objective.target_amount
var/target_number = input("Input target number:", "Objective", def_num) as num | null
if (isnull(target_number))//Ordinarily, you wouldn't need isnull. In this case, the value may already exist.
return
switch(new_obj_type)
if("download")
new_objective = new /datum/objective/download
new_objective.explanation_text = "Download [target_number] research node\s."
if("capture")
new_objective = new /datum/objective/capture
new_objective.explanation_text = "Capture [target_number] lifeforms with an energy net. Live, rare specimens are worth more."
if("absorb")
new_objective = new /datum/objective/absorb
new_objective.explanation_text = "Absorb [target_number] compatible genomes."
new_objective.owner = src
new_objective.target_amount = target_number
if ("custom")
var/expl = stripped_input(usr, "Custom objective:", "Objective", objective ? objective.explanation_text : "")
if (!expl)
return
new_objective = new /datum/objective
new_objective.owner = src
new_objective.explanation_text = expl
if (!new_objective)
return
if (objective)
if(target_antag)
target_antag.objectives -= objective
objectives -= objective
target_antag.objectives.Insert(objective_pos, new_objective)
message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]")
log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]")
else
if(target_antag)
target_antag.objectives += new_objective
objectives += new_objective
message_admins("[key_name_admin(usr)] added a new objective for [current]: [new_objective.explanation_text]")
log_admin("[key_name(usr)] added a new objective for [current]: [new_objective.explanation_text]")
else if (href_list["obj_delete"])
var/datum/objective/objective = locate(href_list["obj_delete"])
if(!istype(objective))
return
for(var/datum/antagonist/A in antag_datums)
if(objective in A.objectives)
A.objectives -= objective
break
objectives -= objective
message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]")
log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]")
else if(href_list["obj_completed"])
var/datum/objective/objective = locate(href_list["obj_completed"])
if(!istype(objective))
return
objective.completed = !objective.completed
log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]")
else if (href_list["silicon"])
switch(href_list["silicon"])
if("unemag")
var/mob/living/silicon/robot/R = current
if (istype(R))
R.SetEmagged(0)
message_admins("[key_name_admin(usr)] has unemag'ed [R].")
log_admin("[key_name(usr)] has unemag'ed [R].")
if("unemagcyborgs")
if(isAI(current))
var/mob/living/silicon/ai/ai = current
for (var/mob/living/silicon/robot/R in ai.connected_robots)
R.SetEmagged(0)
message_admins("[key_name_admin(usr)] has unemag'ed [ai]'s Cyborgs.")
log_admin("[key_name(usr)] has unemag'ed [ai]'s Cyborgs.")
else if (href_list["common"])
switch(href_list["common"])
if("undress")
for(var/obj/item/W in current)
current.dropItemToGround(W, TRUE) //The 1 forces all items to drop, since this is an admin undress.
if("takeuplink")
take_uplink()
memory = null//Remove any memory they may have had.
log_admin("[key_name(usr)] removed [current]'s uplink.")
if("crystals")
if(check_rights(R_FUN, 0))
var/datum/component/uplink/U = find_syndicate_uplink()
if(U)
var/crystals = input("Amount of telecrystals for [key]","Syndicate uplink", U.telecrystals) as null | num
if(!isnull(crystals))
U.telecrystals = crystals
message_admins("[key_name_admin(usr)] changed [current]'s telecrystal count to [crystals].")
log_admin("[key_name(usr)] changed [current]'s telecrystal count to [crystals].")
if("uplink")
if(!equip_traitor())
to_chat(usr, "Equipping a syndicate failed!")
log_admin("[key_name(usr)] tried and failed to give [current] an uplink.")
else
log_admin("[key_name(usr)] gave [current] an uplink.")
else if (href_list["obj_announce"])
announce_objectives()
//Something in here might have changed your mob
if(self_antagging && (!usr || !usr.client) && current.client)
usr = current
traitor_panel()
/datum/mind/proc/announce_objectives()
var/obj_count = 1
to_chat(current, "Your current objectives:")
for(var/objective in objectives)
var/datum/objective/O = objective
to_chat(current, "Objective #[obj_count]: [O.explanation_text]")
obj_count++
/datum/mind/proc/find_syndicate_uplink()
var/list/L = current.GetAllContents()
for (var/i in L)
var/atom/movable/I = i
. = I.GetComponent(/datum/component/uplink)
if(.)
break
/datum/mind/proc/take_uplink()
qdel(find_syndicate_uplink())
/datum/mind/proc/make_Traitor()
if(!(has_antag_datum(/datum/antagonist/traitor)))
add_antag_datum(/datum/antagonist/traitor)
/datum/mind/proc/make_Changeling()
var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling)
if(!C)
C = add_antag_datum(/datum/antagonist/changeling)
special_role = ROLE_CHANGELING
return C
/datum/mind/proc/make_Wizard()
if(!has_antag_datum(/datum/antagonist/wizard))
special_role = ROLE_WIZARD
assigned_role = ROLE_WIZARD
add_antag_datum(/datum/antagonist/wizard)
/datum/mind/proc/make_Cultist()
if(!has_antag_datum(/datum/antagonist/cult,TRUE))
SSticker.mode.add_cultist(src,FALSE,equip=TRUE)
special_role = ROLE_CULTIST
to_chat(current, "You catch a glimpse of the Realm of Nar'Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar'Sie.")
to_chat(current, "Assist your new brethren in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.")
/datum/mind/proc/make_Rev()
var/datum/antagonist/rev/head/head = new()
head.give_flash = TRUE
head.give_hud = TRUE
add_antag_datum(head)
special_role = ROLE_REV_HEAD
/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S)
spell_list += S
S.action.Grant(current)
/datum/mind/proc/owns_soul()
return soulOwner == src
//To remove a specific spell from a mind
/datum/mind/proc/RemoveSpell(obj/effect/proc_holder/spell/spell)
if(!spell)
return
for(var/X in spell_list)
var/obj/effect/proc_holder/spell/S = X
if(istype(S, spell))
spell_list -= S
qdel(S)
/datum/mind/proc/RemoveAllSpells()
for(var/obj/effect/proc_holder/S in spell_list)
RemoveSpell(S)
/datum/mind/proc/transfer_martial_arts(mob/living/new_character)
if(!ishuman(new_character))
return
if(martial_art)
if(martial_art.base) //Is the martial art temporary?
martial_art.remove(new_character)
else
martial_art.teach(new_character)
/datum/mind/proc/transfer_actions(mob/living/new_character)
if(current && current.actions)
for(var/datum/action/A in current.actions)
A.Grant(new_character)
transfer_mindbound_actions(new_character)
/datum/mind/proc/transfer_mindbound_actions(mob/living/new_character)
for(var/X in spell_list)
var/obj/effect/proc_holder/spell/S = X
S.action.Grant(new_character)
var/datum/antagonist/changeling/changeling = new_character.mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling &&(ishuman(new_character) || ismonkey(new_character)))
for(var/P in changeling.purchasedpowers)
var/obj/effect/proc_holder/changeling/I = P
I.action.Grant(new_character)
/datum/mind/proc/disrupt_spells(delay, list/exceptions = New())
for(var/X in spell_list)
var/obj/effect/proc_holder/spell/S = X
for(var/type in exceptions)
if(istype(S, type))
continue
S.charge_counter = delay
S.updateButtonIcon()
INVOKE_ASYNC(S, /obj/effect/proc_holder/spell.proc/start_recharge)
/datum/mind/proc/get_ghost(even_if_they_cant_reenter)
for(var/mob/dead/observer/G in GLOB.dead_mob_list)
if(G.mind == src)
if(G.can_reenter_corpse || even_if_they_cant_reenter)
return G
break
/datum/mind/proc/grab_ghost(force)
var/mob/dead/observer/G = get_ghost(even_if_they_cant_reenter = force)
. = G
if(G)
G.reenter_corpse()
/datum/mind/proc/has_objective(objective_type)
for(var/datum/antagonist/A in antag_datums)
for(var/O in A.objectives)
if(istype(O,objective_type))
return TRUE
/mob/proc/sync_mind()
mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist)
mind.active = 1 //indicates that the mind is currently synced with a client
/mob/dead/new_player/sync_mind()
return
/mob/dead/observer/sync_mind()
return
//Initialisation procs
/mob/proc/mind_initialize()
if(mind)
mind.key = key
else
mind = new /datum/mind(key)
SSticker.minds += mind
if(!mind.name)
mind.name = real_name
mind.current = src
/mob/living/carbon/mind_initialize()
..()
last_mind = mind
//HUMAN
/mob/living/carbon/human/mind_initialize()
..()
if(!mind.assigned_role)
mind.assigned_role = "Unassigned" //default
//AI
/mob/living/silicon/ai/mind_initialize()
..()
mind.assigned_role = "AI"
//BORG
/mob/living/silicon/robot/mind_initialize()
..()
mind.assigned_role = "Cyborg"
//PAI
/mob/living/silicon/pai/mind_initialize()
..()
mind.assigned_role = ROLE_PAI
mind.special_role = ""