diff --git a/baystation12.dme b/baystation12.dme
index a89b58dd1c34d..a84d26578807d 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1584,6 +1584,8 @@
#include "code\modules\client\preference_setup\loadout\lists\xenowear.dm"
#include "code\modules\client\preference_setup\occupation\occupation.dm"
#include "code\modules\client\preference_setup\occupation\skill_selection.dm"
+#include "code\modules\client\preference_setup\psionics\01_basic.dm"
+#include "code\modules\client\preference_setup\psionics\02_abilities.dm"
#include "code\modules\clothing\_clothing.dm"
#include "code\modules\clothing\_clothing_flags.dm"
#include "code\modules\clothing\buttons.dm"
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 09ef39dbb7262..7f78a425db410 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -49,7 +49,7 @@
var/list/species_branch_rank_cache_ = list()
var/list/psi_faculties // Starting psi faculties, if any.
var/psi_latency_chance = 0 // Chance of an additional psi latency, if any.
- var/give_psionic_implant_on_join = TRUE // If psionic, will be implanted for control.
+ var/give_psionic_implant_on_join = FALSE // If psionic, will be implanted for control.
var/use_species_whitelist // If set, restricts the job to players with the given species whitelist. This does NOT restrict characters joining as the job to the species itself.
@@ -57,6 +57,8 @@
var/faction = MOB_FACTION_CREW
+ var/global/psi_allowed_species = list(/datum/species/human,/datum/species/human/vatgrown,/datum/species/human/tritonian,/datum/species/human/gravworlder,/datum/species/human/spacer)
+
/datum/job/New()
if(prob(100-availablity_chance)) //Close positions, blah blah.
@@ -71,6 +73,41 @@
/datum/job/dd_SortValue()
return title
+/datum/job/proc/give_psi(mob/living/carbon/human/H)
+ if(!(all_species[H.client.prefs.species].type in psi_allowed_species))
+ return
+
+ if(psi_latency_chance && prob(psi_latency_chance))
+ H.set_psi_rank(pick(PSI_COERCION, PSI_REDACTION, PSI_ENERGISTICS, PSI_PSYCHOKINESIS, PSI_CONSCIOUSNESS, PSI_MANIFESTATION, PSI_METAKINESIS), 1, defer_update = TRUE)
+
+ var/list/psi_abilities_by_name = H.client.prefs.psi_abilities
+
+ LAZYINITLIST(psi_faculties)
+ for(var/faculty_name in psi_abilities_by_name)
+ var/faculty_id = SSpsi.faculties_by_name[faculty_name].id
+ psi_faculties |= list("[faculty_id]" = psi_abilities_by_name[faculty_name])
+
+ for(var/psi in psi_faculties)
+ H.set_psi_rank(psi, psi_faculties[psi], take_larger = TRUE, defer_update = TRUE)
+
+ H.psi.update()
+
+ give_psionic_implant_on_join ||= (H.client.prefs.psi_openness && H.client.prefs.psi_status < 4)
+
+ if(!give_psionic_implant_on_join)
+ return
+
+ var/obj/item/implant/psi_control/imp = new
+ imp.implanted(H)
+ imp.forceMove(H)
+ imp.imp_in = H
+ imp.implanted = TRUE
+ var/obj/item/organ/external/affected = H.get_organ(BP_HEAD)
+ if(affected)
+ affected.implants += imp
+ imp.part = affected
+ to_chat(H, SPAN_DANGER("As a registered psionic, you are fitted with a psi-dampening control implant. Using psi-power while the implant is active will result in neural shocks and your violation being reported."))
+
/datum/job/proc/equip(mob/living/carbon/human/H, alt_title, datum/mil_branch/branch, datum/mil_rank/grade)
if (required_language)
@@ -81,24 +118,7 @@
H.add_language(LANGUAGE_SPACER)
H.set_default_language(all_languages[LANGUAGE_SPACER])
- if(psi_latency_chance && prob(psi_latency_chance))
- H.set_psi_rank(pick(PSI_COERCION, PSI_REDACTION, PSI_ENERGISTICS, PSI_PSYCHOKINESIS), 1, defer_update = TRUE)
- if(islist(psi_faculties))
- for(var/psi in psi_faculties)
- H.set_psi_rank(psi, psi_faculties[psi], take_larger = TRUE, defer_update = TRUE)
- if(H.psi)
- H.psi.update()
- if(give_psionic_implant_on_join)
- var/obj/item/implant/psi_control/imp = new
- imp.implanted(H)
- imp.forceMove(H)
- imp.imp_in = H
- imp.implanted = TRUE
- var/obj/item/organ/external/affected = H.get_organ(BP_HEAD)
- if(affected)
- affected.implants += imp
- imp.part = affected
- to_chat(H, SPAN_DANGER("As a registered psionic, you are fitted with a psi-dampening control implant. Using psi-power while the implant is active will result in neural shocks and your violation being reported."))
+ give_psi(H)
var/singleton/hierarchy/outfit/outfit = get_outfit(H, alt_title, branch, grade)
if(outfit) . = outfit.equip(H, title, alt_title)
diff --git a/code/game/objects/items/passport.dm b/code/game/objects/items/passport.dm
index 4c4395b94c983..f93ff57f2d698 100644
--- a/code/game/objects/items/passport.dm
+++ b/code/game/objects/items/passport.dm
@@ -21,6 +21,12 @@
fingerprint = "N/A"
info = "\icon[src] [src]:\nName: [H.real_name]\nSpecies: [H.get_species()]\nPronouns: [H.pronouns]\nAge: [H.age]\nPlace of Birth: [pob]\nFingerprint: [fingerprint]"
+ var/psi
+ if(H.client?.prefs?.psi_threat_level && H.client.prefs.psi_openness)
+ psi = "Psionics status: [GLOB.psi_status2text[H.client.prefs.psi_status]]\n"
+ psi += "Psionics threat level: [H.client.prefs.psi_threat_level]\n"
+ info = "\icon[src] [src]:\nName: [H.real_name]\nSpecies: [H.get_species()]\nGender: [gender2text(H.gender)]\nAge: [H.age]\n[psi]Place of Birth: [pob]\nFingerprint: [fingerprint]"
+
/obj/item/passport/attack_self(mob/user as mob)
user.visible_message(
SPAN_ITALIC("[user] opens and checks [src]."),
diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm
index 2862b1f50a63c..b52e9b4d40e9b 100644
--- a/code/game/objects/items/weapons/cards_ids.dm
+++ b/code/game/objects/items/weapons/cards_ids.dm
@@ -221,6 +221,9 @@ var/global/const/NO_EMAG_ACT = -50
var/detail_color
var/extra_details
+ var/psi_status
+ var/psi_level
+
/obj/item/card/id/Initialize()
.=..()
if(job_access_type)
@@ -268,7 +271,7 @@ var/global/const/NO_EMAG_ACT = -50
if(front && side)
send_rsc(user, front, "front.png")
send_rsc(user, side, "side.png")
- var/datum/browser/popup = new(user, "idcard", name, 600, 250)
+ var/datum/browser/popup = new(user, "idcard", name, 600, 350)
popup.set_content(dat())
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
@@ -293,7 +296,7 @@ var/global/const/NO_EMAG_ACT = -50
id_card.formal_name_prefix = initial(id_card.formal_name_prefix)
id_card.formal_name_suffix = initial(id_card.formal_name_suffix)
- if(client && client.prefs)
+ if(client?.prefs)
for(var/culturetag in client.prefs.cultural_info)
var/singleton/cultural_info/culture = SSculture.get_culture(client.prefs.cultural_info[culturetag])
if(culture)
@@ -314,6 +317,10 @@ var/global/const/NO_EMAG_ACT = -50
id_card.dna_hash = dna.unique_enzymes
id_card.fingerprint_hash= md5(dna.uni_identity)
+ if(client?.prefs?.psi_threat_level && client.prefs.psi_openness)
+ id_card.psi_level = client.prefs.psi_threat_level
+ id_card.psi_status = GLOB.psi_status2text[client.prefs.psi_status]
+
/mob/living/carbon/human/set_id_info(obj/item/card/id/id_card)
..()
id_card.age = age
@@ -327,25 +334,39 @@ var/global/const/NO_EMAG_ACT = -50
for(var/add_access in category.add_accesses)
id_card.access.Add(add_access)
+/obj/item/card/id/proc/extra_dat()
+ . = list()
+ if(psi_status)
+ . += "Psionics status: [psi_status]
"
+ . += "Psionics threat level: [psi_level]
"
+
/obj/item/card/id/proc/dat()
var/list/dat = list("
")
- dat += text("Name: [] ", "[formal_name_prefix][registered_name][formal_name_suffix]") - dat += text("Pronouns: [] \n", sex) - dat += text("Age: [] \n", age) + dat += text("Name: [] ", "[formal_name_prefix][registered_name][formal_name_suffix]") + dat += text("Pronouns: [] \n", sex) + dat += text("Age: [] \n", age) + + dat += jointext(extra_dat(), null) + dat += " " if(GLOB.using_map.flags & MAP_HAS_BRANCH) dat += text("Branch: [] \n", military_branch ? military_branch.name : "\[UNSET\]") if(GLOB.using_map.flags & MAP_HAS_RANK) dat += text("Rank: [] \n", military_rank ? military_rank.name : "\[UNSET\]") + dat += " " dat += text("Assignment: [] \n", assignment) dat += text("Fingerprint: [] \n", fingerprint_hash) dat += text("Blood Type: [] \n", blood_type) dat += text("DNA Hash: [] \n", dna_hash) if(front && side) - dat +=" | Photo: | "
+ dat += "Photo: " + dat += "" + dat += "" + dat += " | "
dat += "
[faculty]: | "
+
+ for(var/level_index in 1 to GLOB.psi_level2cost.len)
+ var/level_name = GLOB.psi_level2cost[level_index]
+
+ if(pref.psi_abilities[faculty] == level_index)
+ . += "[level_name] | "
+ else if(can_select_level(faculty, level_index))
+ . += "" + else + . += " | [level_name] | "
+
+ . += "
---|
")
+/obj/item/card/id/extra_dat()
+ . = ..()
if(ipc_gen)
- dat += text("Registration: [] \n", ipc_gen) - ..() + . += "Registration: [ipc_gen] " /singleton/cultural_info/faction/ipc economic_power = 0.1 |