mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 01:34:01 +00:00
## About The Pull Request This PR does four things: - Shortens and simplifies the medical records template, making it more accessible - Expands Security records flavor into a personnel file that includes exploitables and your character's background, so that you can have Security records without having a criminal history - Creates defaults for medical records, general records, and Security records in the character creator, rather than just the wiki. - Removes exploitables and background records as they've now been integrated into Security records. ## Why It's Good For The Game This PR should make records more accessible for individual players by reducing the amount of work involved, as well as expanding Security records to be more useful. ## Proof Of Testing <img width="656" height="494" alt="image" src="https://github.com/user-attachments/assets/2b5455b2-0e73-4e0a-b9c8-fd278db85040" /> ## Changelog 🆑 ReturnToZender (code) add: All records now have enhanced defaults when making a new character add: Security records have been expanded into personnel records, containing more information on your character del: Exploitables and Background records have been merged into the definition of Security records, which are now Personnel Records. /🆑
242 lines
9.6 KiB
Plaintext
242 lines
9.6 KiB
Plaintext
GLOBAL_DATUM_INIT(manifest, /datum/manifest, new)
|
|
|
|
/** Stores crew records. */
|
|
/datum/manifest
|
|
/// All of the crew records.
|
|
var/list/general = list()
|
|
/// This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
|
|
var/list/locked = list()
|
|
/// Total number of security rapsheet prints. Changes the header.
|
|
var/print_count = 0
|
|
|
|
/// Builds the list of crew records for all crew members.
|
|
/datum/manifest/proc/build()
|
|
// List of mobs we want to mass insert into the manifest table at round start
|
|
var/list/players_to_log = list()
|
|
for(var/mob/dead/new_player/readied_player as anything in GLOB.new_player_list)
|
|
if(readied_player.new_character)
|
|
log_manifest(readied_player.ckey, readied_player.new_character.mind, readied_player.new_character)
|
|
players_to_log[readied_player.ckey] = readied_player.new_character
|
|
if(ishuman(readied_player.new_character))
|
|
inject(readied_player.new_character, null, readied_player.client) // SKYRAT EDIT - RP Records - ORIGINAL: inject(readied_player.new_character)
|
|
CHECK_TICK
|
|
if(length(players_to_log))
|
|
SSblackbox.ReportRoundstartManifest(players_to_log)
|
|
|
|
/// Gets the current manifest.
|
|
/datum/manifest/proc/get_manifest()
|
|
// First we build up the order in which we want the departments to appear in.
|
|
var/list/manifest_out = list()
|
|
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
|
|
manifest_out[department.department_name] = list()
|
|
manifest_out[DEPARTMENT_UNASSIGNED] = list()
|
|
|
|
var/list/departments_by_type = SSjob.joinable_departments_by_type
|
|
for(var/datum/record/crew/target as anything in GLOB.manifest.general)
|
|
var/name = target.name
|
|
var/rank = target.rank // user-visible job
|
|
var/trim = target.trim // internal jobs by trim type
|
|
var/datum/job/job = SSjob.get_job(trim)
|
|
if(!job || !(job.job_flags & JOB_CREW_MANIFEST) || !LAZYLEN(job.departments_list)) // In case an unlawful custom rank is added.
|
|
var/list/misc_list = manifest_out[DEPARTMENT_UNASSIGNED]
|
|
misc_list[++misc_list.len] = list(
|
|
"name" = name,
|
|
"rank" = rank,
|
|
"trim" = trim,
|
|
)
|
|
continue
|
|
for(var/department_type as anything in job.departments_list)
|
|
//Jobs under multiple departments should only be displayed if this is their first department or the command department
|
|
if(job.departments_list[1] != department_type && !(job.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND))
|
|
continue
|
|
var/datum/job_department/department = departments_by_type[department_type]
|
|
if(!department)
|
|
stack_trace("get_manifest() failed to get job department for [department_type] of [job.type]")
|
|
continue
|
|
var/list/entry = list(
|
|
"name" = name,
|
|
"rank" = rank,
|
|
"trim" = trim,
|
|
)
|
|
var/list/department_list = manifest_out[department.department_name]
|
|
if(istype(job, department.department_head))
|
|
department_list.Insert(1, null)
|
|
department_list[1] = entry
|
|
else
|
|
department_list[++department_list.len] = entry
|
|
|
|
// Trim the empty categories.
|
|
for (var/department in manifest_out)
|
|
if(!length(manifest_out[department]))
|
|
manifest_out -= department
|
|
|
|
return manifest_out
|
|
|
|
/// Returns the manifest as an html.
|
|
/datum/manifest/proc/get_html(monochrome = FALSE)
|
|
var/list/manifest = get_manifest()
|
|
var/dat = {"
|
|
<head><style>
|
|
.manifest {border-collapse:collapse;}
|
|
.manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em}
|
|
.manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]}
|
|
.manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] }
|
|
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]}
|
|
</style></head>
|
|
<table class="manifest" width='350px'>
|
|
<tr class='head'><th>Name</th><th>Rank</th></tr>
|
|
"}
|
|
for(var/department in manifest)
|
|
var/list/entries = manifest[department]
|
|
dat += "<tr><th colspan=3>[department]</th></tr>"
|
|
//JUST
|
|
var/even = FALSE
|
|
for(var/entry in entries)
|
|
var/list/entry_list = entry
|
|
dat += "<tr[even ? " class='alt'" : ""]><td>[entry_list["name"]]</td><td>[entry_list["rank"]]</td></tr>"
|
|
even = !even
|
|
|
|
dat += "</table>"
|
|
dat = replacetext(dat, "\n", "")
|
|
dat = replacetext(dat, "\t", "")
|
|
return dat
|
|
|
|
|
|
/// Injects a record into the manifest.
|
|
/datum/manifest/proc/inject(mob/living/carbon/human/person, atom/appearance_proxy, client/person_client) // SKYRAT EDIT - RP Records - ORIGINAL: /datum/manifest/proc/inject(mob/living/carbon/human/person, atom/appearance_proxy)
|
|
set waitfor = FALSE
|
|
if(!(person.mind?.assigned_role.job_flags & JOB_CREW_MANIFEST))
|
|
return
|
|
|
|
// Attempt to get assignment from ID, otherwise default to mind.
|
|
var/obj/item/card/id/id_card = person.get_idcard(hand_first = FALSE)
|
|
var/assignment = id_card?.get_trim_assignment() || person.mind.assigned_role.title
|
|
|
|
var/mutable_appearance/character_appearance = new(appearance_proxy?.appearance || person.appearance)
|
|
var/person_gender = "Other"
|
|
if(person.gender == "male")
|
|
person_gender = "Male"
|
|
if(person.gender == "female")
|
|
person_gender = "Female"
|
|
var/datum/dna/stored/record_dna = new()
|
|
person.dna.copy_dna(record_dna)
|
|
|
|
// SKYRAT EDIT ADDITION BEGIN - ALTERNATIVE_JOB_TITLES
|
|
// The alt job title, if user picked one, or the default
|
|
var/chosen_assignment = id_card?.get_job_title() || assignment //BUBBER EDIT: Intern Job Tags
|
|
// SKYRAT EDIT ADDITION END - ALTERNATIVE_JOB_TITLES
|
|
|
|
var/datum/record/locked/lockfile = new(
|
|
age = person.age,
|
|
chrono_age = person.chrono_age, // SKYRAT EDIT ADDITION - Chronological age
|
|
blood_type = person.get_bloodtype()?.name || "UNKNOWN",
|
|
character_appearance = character_appearance,
|
|
dna_string = record_dna.unique_enzymes,
|
|
fingerprint = md5(record_dna.unique_identity),
|
|
gender = person_gender,
|
|
initial_rank = assignment,
|
|
name = person.real_name,
|
|
rank = chosen_assignment, // SKYRAT EDIT - Alt job titles - ORIGINAL: rank = assignment,
|
|
species = record_dna.species.name,
|
|
trim = assignment,
|
|
// Locked specifics
|
|
locked_dna = record_dna,
|
|
mind_ref = person.mind,
|
|
// BUBBER EDIT ADDITION BEGIN - Records
|
|
exploitable_information = person_client?.prefs.read_preference(/datum/preference/text/security) || "",
|
|
// BUBBER EDIT END
|
|
)
|
|
|
|
new /datum/record/crew(
|
|
age = person.age,
|
|
chrono_age = person.chrono_age, // SKYRAT EDIT ADDITION - Chronological age
|
|
blood_type = person.get_bloodtype()?.name || "UNKNOWN",
|
|
character_appearance = character_appearance,
|
|
dna_string = record_dna.unique_enzymes,
|
|
fingerprint = md5(record_dna.unique_identity),
|
|
gender = person_gender,
|
|
initial_rank = assignment,
|
|
name = person.real_name,
|
|
rank = chosen_assignment, // SKYRAT EDIT - Alt job titles - ORIGINAL: rank = assignment,
|
|
species = record_dna.species.name,
|
|
trim = assignment,
|
|
// Crew specific
|
|
lock_ref = REF(lockfile),
|
|
major_disabilities = person.get_quirk_string(FALSE, CAT_QUIRK_MAJOR_DISABILITY, from_scan = TRUE),
|
|
major_disabilities_desc = person.get_quirk_string(TRUE, CAT_QUIRK_MAJOR_DISABILITY),
|
|
minor_disabilities = person.get_quirk_string(FALSE, CAT_QUIRK_MINOR_DISABILITY, from_scan = TRUE),
|
|
minor_disabilities_desc = person.get_quirk_string(TRUE, CAT_QUIRK_MINOR_DISABILITY),
|
|
quirk_notes = person.get_quirk_string(TRUE, CAT_QUIRK_NOTES),
|
|
// SKYRAT EDIT START - RP Records
|
|
past_general_records = person_client?.prefs.read_preference(/datum/preference/text/general) || "",
|
|
past_medical_records = person_client?.prefs.read_preference(/datum/preference/text/medical) || "",
|
|
past_security_records = person_client?.prefs.read_preference(/datum/preference/text/security) || "",
|
|
// SKYRAT EDIT END
|
|
)
|
|
|
|
/// Edits the rank and trim of the found record.
|
|
/datum/manifest/proc/modify(name, assignment, trim)
|
|
var/datum/record/crew/target = find_record(name)
|
|
if(!target)
|
|
return
|
|
|
|
target.rank = assignment
|
|
target.trim = trim
|
|
|
|
///Removes a record based on its name.
|
|
/datum/manifest/proc/remove(name)
|
|
var/datum/record/crew/target = find_record(name)
|
|
if(!target)
|
|
return
|
|
general -= target
|
|
qdel(target)
|
|
|
|
/**
|
|
* Using the name to find the record, and person in reference to the body, we recreate photos for the manifest (and records).
|
|
* Args:
|
|
* - name - The name of the record we're looking for, which should be the name of the person.
|
|
* - person - The mob we're taking pictures of to update the records.
|
|
* - add_height_chart - If we should add a height chart to the background of the photo.
|
|
*/
|
|
/datum/manifest/proc/change_pictures(name, mob/living/person, add_height_chart = FALSE)
|
|
var/datum/record/crew/target = find_record(name)
|
|
if(!target)
|
|
return FALSE
|
|
|
|
target.character_appearance = new(person.appearance)
|
|
target.recreate_manifest_photos(add_height_chart)
|
|
return TRUE
|
|
|
|
/datum/manifest/ui_state(mob/user)
|
|
return GLOB.always_state
|
|
|
|
/datum/manifest/ui_status(mob/user, datum/ui_state/state)
|
|
return (isnewplayer(user) || isobserver(user) || isAI(user) || ispAI(user) || user.client?.holder) ? UI_INTERACTIVE : UI_CLOSE
|
|
|
|
/datum/manifest/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if (!ui)
|
|
ui = new(user, src, "CrewManifest")
|
|
ui.open()
|
|
|
|
/datum/manifest/ui_data(mob/user)
|
|
var/list/positions = list()
|
|
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
|
|
var/open = 0
|
|
var/list/exceptions = list()
|
|
for(var/datum/job/job as anything in department.department_jobs)
|
|
if(job.total_positions == -1)
|
|
exceptions += job.title
|
|
continue
|
|
var/open_slots = job.total_positions - job.current_positions
|
|
if(open_slots < 1)
|
|
continue
|
|
open += open_slots
|
|
positions[department.department_name] = list("exceptions" = exceptions, "open" = open)
|
|
|
|
return list(
|
|
"manifest" = get_manifest(),
|
|
"positions" = positions
|
|
)
|
|
|