diff --git a/code/__DEFINES/security.dm b/code/__DEFINES/security.dm
index 3e741d82aaf..a385d843398 100644
--- a/code/__DEFINES/security.dm
+++ b/code/__DEFINES/security.dm
@@ -54,3 +54,21 @@
/// if any categories list has this entry, it will be hidden
#define DETSCAN_BLOCK "DETSCAN_BLOCK"
+
+/// Wanted statuses
+#define WANTED_ARREST "Arrest"
+#define WANTED_DISCHARGED "Discharged"
+#define WANTED_NONE "None"
+#define WANTED_PAROLE "Parole"
+#define WANTED_PRISONER "Incarcerated"
+#define WANTED_SUSPECT "Suspected"
+
+/// List of available wanted statuses
+#define WANTED_STATUSES(...) list(\
+ WANTED_NONE, \
+ WANTED_SUSPECT, \
+ WANTED_ARREST, \
+ WANTED_PRISONER, \
+ WANTED_PAROLE, \
+ WANTED_DISCHARGED, \
+)
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index 074ade9e5af..4a4bc828cf8 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -594,12 +594,11 @@
inserted_list[key] = temp[key]
///for sorting clients or mobs by ckey
-/proc/sort_key(list/ckey_list, order=1)
+/proc/sort_key(list/ckey_list, order = 1)
return sortTim(ckey_list, order >= 0 ? GLOBAL_PROC_REF(cmp_ckey_asc) : GLOBAL_PROC_REF(cmp_ckey_dsc))
///Specifically for record datums in a list.
-/proc/sort_record(list/record_list, field = "name", order = 1)
- GLOB.cmp_field = field
+/proc/sort_record(list/record_list, order = 1)
return sortTim(record_list, order >= 0 ? GLOBAL_PROC_REF(cmp_records_asc) : GLOBAL_PROC_REF(cmp_records_dsc))
///sort any value in a list
@@ -639,11 +638,27 @@
i++
return i
-/// Returns datum/data/record
-/proc/find_record(field, value, list/inserted_list)
- for(var/datum/data/record/record_to_check in inserted_list)
- if(record_to_check.fields[field] == value)
- return record_to_check
+/**
+ * Returns the first record in the list that matches the name
+ *
+ * If locked_only is TRUE, locked records will be checked
+ *
+ * If locked_only is FALSE, crew records will be checked
+ *
+ * If no record is found, returns null
+ */
+/proc/find_record(value, locked_only = FALSE)
+ if(locked_only)
+ for(var/datum/record/locked/target in GLOB.manifest.locked)
+ if(target.name != value)
+ continue
+ return target
+ return null
+
+ for(var/datum/record/crew/target in GLOB.manifest.general)
+ if(target.name != value)
+ continue
+ return target
return null
diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm
index 467f60e8195..e7af8e0dcd7 100644
--- a/code/__HELPERS/cmp.dm
+++ b/code/__HELPERS/cmp.dm
@@ -16,12 +16,11 @@
/proc/cmp_name_dsc(atom/a, atom/b)
return sorttext(a.name, b.name)
-GLOBAL_VAR_INIT(cmp_field, "name")
-/proc/cmp_records_asc(datum/data/record/a, datum/data/record/b)
- return sorttext(b.fields[GLOB.cmp_field], a.fields[GLOB.cmp_field])
+/proc/cmp_records_asc(datum/record/a, datum/record/b)
+ return sorttext(b.name, a.name)
-/proc/cmp_records_dsc(datum/data/record/a, datum/data/record/b)
- return sorttext(a.fields[GLOB.cmp_field], b.fields[GLOB.cmp_field])
+/proc/cmp_records_dsc(datum/record/a, datum/record/b)
+ return sorttext(a.name, b.name)
// Datum cmp with vars is always slower than a specialist cmp proc, use your judgement.
/proc/cmp_datum_numeric_asc(datum/a, datum/b, variable)
diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm
index 82d9ea1ffab..15a659f1bc7 100644
--- a/code/__HELPERS/names.dm
+++ b/code/__HELPERS/names.dm
@@ -178,8 +178,8 @@ GLOBAL_DATUM(syndicate_code_response_regex, /regex)
var/locations = strings(LOCATIONS_FILE, "locations")
var/list/names = list()
- for(var/datum/data/record/t in GLOB.data_core.general)//Picks from crew manifest.
- names += t.fields["name"]
+ for(var/datum/record/crew/target in GLOB.manifest.general)//Picks from crew manifest.
+ names += target.name
var/maxwords = words//Extra var to check for duplicates.
diff --git a/code/__HELPERS/records.dm b/code/__HELPERS/records.dm
index b3dba849d3c..288ef5284d2 100644
--- a/code/__HELPERS/records.dm
+++ b/code/__HELPERS/records.dm
@@ -1,6 +1,6 @@
-/proc/overwrite_field_if_available(datum/data/record/base, datum/data/record/other, field_name)
- if(other.fields[field_name])
- base.fields[field_name] = other.fields[field_name]
+/proc/overwrite_field_if_available(datum/record/base, datum/record/other, field_name)
+ if(other[field_name])
+ base[field_name] = other[field_name]
diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm
index 1cb4fd688f1..1c6b4b90bc6 100644
--- a/code/_globalvars/lists/mobs.dm
+++ b/code/_globalvars/lists/mobs.dm
@@ -110,9 +110,8 @@ GLOBAL_LIST_INIT(construct_radial_images, list(
/proc/get_crewmember_minds()
var/list/minds = list()
- for(var/data in GLOB.data_core.locked)
- var/datum/data/record/record = data
- var/datum/mind/mind = record.fields["mindref"]
+ for(var/datum/record/locked/target in GLOB.manifest.locked)
+ var/datum/mind/mind = target.mind_ref
if(mind)
minds += mind
return minds
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index e5af18e359b..dc94b509552 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -267,7 +267,7 @@ SUBSYSTEM_DEF(ticker)
collect_minds()
equip_characters()
- GLOB.data_core.manifest()
+ GLOB.manifest.build()
transfer_characters() //transfer keys to the new mobs
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
deleted file mode 100644
index bdd60690328..00000000000
--- a/code/datums/datacore.dm
+++ /dev/null
@@ -1,421 +0,0 @@
-GLOBAL_DATUM_INIT(data_core, /datum/datacore, new)
-
-//TODO: someone please get rid of this shit
-/datum/datacore
- var/list/medical = list()
- var/medicalPrintCount = 0
- var/list/general = list()
- var/list/security = list()
- var/securityPrintCount = 0
- var/securityCrimeCounter = 0
- ///This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
- var/list/locked = list()
-
-/datum/data
- var/name = "data"
-
-/datum/data/record
- name = "record"
- var/list/fields = list()
-
-/datum/data/record/Destroy()
- GLOB.data_core.medical -= src
- GLOB.data_core.security -= src
- GLOB.data_core.general -= src
- GLOB.data_core.locked -= src
- . = ..()
-
-/// A helper proc to get the front photo of a character from the record.
-/// Handles calling `get_photo()`, read its documentation for more information.
-/datum/data/record/proc/get_front_photo()
- return get_photo("photo_front", SOUTH)
-
-/// A helper proc to get the side photo of a character from the record.
-/// Handles calling `get_photo()`, read its documentation for more information.
-/datum/data/record/proc/get_side_photo()
- return get_photo("photo_side", WEST)
-
-/**
- * You shouldn't be calling this directly, use `get_front_photo()` or `get_side_photo()`
- * instead.
- *
- * This is the proc that handles either fetching (if it was already generated before) or
- * generating (if it wasn't) the specified photo from the specified record. This is only
- * intended to be used by records that used to try to access `fields["photo_front"]` or
- * `fields["photo_side"]`, and will return an empty icon if there isn't any of the necessary
- * fields.
- *
- * Arguments:
- * * field_name - The name of the key in the `fields` list, of the record itself.
- * * orientation - The direction in which you want the character appearance to be rotated
- * in the outputed photo.
- *
- * Returns an empty `/icon` if there was no `character_appearance` entry in the `fields` list,
- * returns the generated/cached photo otherwise.
- */
-/datum/data/record/proc/get_photo(field_name, orientation)
- if(fields[field_name])
- return fields[field_name]
-
- if(!fields["character_appearance"])
- return new /icon()
-
- var/mutable_appearance/character_appearance = fields["character_appearance"]
- character_appearance.setDir(orientation)
-
- var/icon/picture_image = getFlatIcon(character_appearance)
-
- var/datum/picture/picture = new
- picture.picture_name = "[fields["name"]]"
- picture.picture_desc = "This is [fields["name"]]."
- picture.picture_image = picture_image
-
- var/obj/item/photo/photo = new(null, picture)
- fields[field_name] = photo
- return photo
-
-/datum/data/crime
- name = "crime"
- var/crimeName = ""
- var/crimeDetails = ""
- var/author = ""
- var/time = ""
- var/fine = 0
- var/paid = 0
- var/dataId = 0
-
-/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "", fine = 0)
- var/datum/data/crime/c = new /datum/data/crime
- c.crimeName = cname
- c.crimeDetails = cdetails
- c.author = author
- c.time = time
- c.fine = fine
- c.paid = 0
- c.dataId = ++securityCrimeCounter
- return c
-
-/datum/datacore/proc/addCitation(id = "", datum/data/crime/crime)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["citation"]
- crimes |= crime
- return
-
-/datum/datacore/proc/removeCitation(id, cDataId)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["citation"]
- for(var/datum/data/crime/crime in crimes)
- if(crime.dataId == text2num(cDataId))
- crimes -= crime
- return
-
-/datum/datacore/proc/payCitation(id, cDataId, amount)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["citation"]
- for(var/datum/data/crime/crime in crimes)
- if(crime.dataId == text2num(cDataId))
- crime.paid = crime.paid + amount
- var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_SEC)
- D.adjust_money(amount)
- return
-
-/**
- * Adds crime to security record.
- *
- * Is used to add single crime to someone's security record.
- * Arguments:
- * * id - record id.
- * * datum/data/crime/crime - premade array containing every variable, usually created by createCrimeEntry.
- */
-/datum/datacore/proc/addCrime(id = "", datum/data/crime/crime)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["crim"]
- crimes |= crime
- return
-
-/**
- * Deletes crime from security record.
- *
- * Is used to delete single crime to someone's security record.
- * Arguments:
- * * id - record id.
- * * cDataId - id of already existing crime.
- */
-/datum/datacore/proc/removeCrime(id, cDataId)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["crim"]
- for(var/datum/data/crime/crime in crimes)
- if(crime.dataId == text2num(cDataId))
- crimes -= crime
- return
-
-/**
- * Adds details to a crime.
- *
- * Is used to add or replace details to already existing crime.
- * Arguments:
- * * id - record id.
- * * cDataId - id of already existing crime.
- * * details - data you want to add.
- */
-/datum/datacore/proc/addCrimeDetails(id, cDataId, details)
- for(var/datum/data/record/R in security)
- if(R.fields["id"] == id)
- var/list/crimes = R.fields["crim"]
- for(var/datum/data/crime/crime in crimes)
- if(crime.dataId == text2num(cDataId))
- crime.crimeDetails = details
- return
-
-/datum/datacore/proc/manifest()
- for(var/i in GLOB.new_player_list)
- var/mob/dead/new_player/N = i
- if(N.new_character)
- log_manifest(N.ckey,N.new_character.mind,N.new_character)
- if(ishuman(N.new_character))
- manifest_inject(N.new_character, N.client) // SKYRAT EDIT - Alt-titles - ORIGINAL: manifest_inject(N.new_character)
- CHECK_TICK
-
-/datum/datacore/proc/manifest_modify(name, assignment, trim)
- var/datum/data/record/foundrecord = find_record("name", name, GLOB.data_core.general)
- if(foundrecord)
- foundrecord.fields["rank"] = assignment
- foundrecord.fields["trim"] = trim
-
-
-/datum/datacore/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/data/record/record as anything in GLOB.data_core.general)
- var/name = record.fields["name"]
- var/rank = record.fields["rank"] // user-visible job
- var/trim = record.fields["trim"] // internal jobs by trim type
- var/datum/job/job = SSjob.GetJob(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, // SKYRAT CHANGE ADDITION - ALTERNATIVE_JOB_TITLES
- )
- continue
- for(var/department_type as anything in job.departments_list)
- 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, // SKYRAT CHANGE ADDITION - ALTERNATIVE_JOB_TITLES
- )
- 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
-
-/datum/datacore/proc/get_manifest_html(monochrome = FALSE)
- var/list/manifest = get_manifest()
- var/dat = {"
-
-
- Name Rank
- "}
- for(var/department in manifest)
- var/list/entries = manifest[department]
- dat += "[department] "
- //JUST
- var/even = FALSE
- for(var/entry in entries)
- var/list/entry_list = entry
- dat += "[entry_list["name"]] [entry_list["rank"] == entry_list["trim"] ? entry_list["rank"] : "[entry_list["rank"]] ([entry_list["trim"]])"] " // SKYRAT CHANGE EDIT - ALTERNATIVE_JOB_TITLES - Original: dat += "[entry_list["name"]] [entry_list["rank"]] "
- even = !even
-
- dat += "
"
- dat = replacetext(dat, "\n", "")
- dat = replacetext(dat, "\t", "")
- return dat
-
-
-/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/human_client) // SKYRAT EDIT - Alt-titles - ORIGINAL: /datum/datacore/proc/manifest_inject(mob/living/carbon/human/H)
- set waitfor = FALSE
- var/static/list/show_directions = list(SOUTH, WEST)
- if(H.mind?.assigned_role.job_flags & JOB_CREW_MANIFEST)
- var/assignment = H.mind.assigned_role.title
- // SKYRAT EDIT ADDITION BEGIN - ALTERNATIVE_JOB_TITLES
- // The alt job title, if user picked one, or the default
- var/chosen_assignment = human_client?.prefs.alt_job_titles[assignment] || assignment
- // SKYRAT EDIT ADDITION END - ALTERNATIVE_JOB_TITLES
-
- var/static/record_id_num = 1001
- var/id = num2hex(record_id_num++,6)
- var/mutable_appearance/character_appearance = new(H.appearance)
-
- //These records should ~really~ be merged or something
- //General Record
- var/datum/data/record/G = new()
- G.fields["id"] = id
- G.fields["name"] = H.real_name
- G.fields["rank"] = chosen_assignment // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: G.fields["rank"] = assignment
- G.fields["trim"] = assignment
- G.fields["initial_rank"] = assignment
- G.fields["age"] = H.age
- G.fields["species"] = H.dna.species.name
- G.fields["fingerprint"] = md5(H.dna.unique_identity)
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- G.fields["gender"] = H.gender
- if(H.gender == "male")
- G.fields["gender"] = "Male"
- else if(H.gender == "female")
- G.fields["gender"] = "Female"
- else
- G.fields["gender"] = "Other"
- G.fields["character_appearance"] = character_appearance
- // SKYRAT ADDITION START - RP RECORDS
- G.fields["past_records"] = human_client?.prefs?.read_preference(/datum/preference/text/general) || ""
- G.fields["background_records"] = human_client?.prefs?.read_preference(/datum/preference/text/background) || ""
- G.fields["exploitable_records"] = human_client?.prefs?.read_preference(/datum/preference/text/exploitable) || ""
- // SKYRAT ADDITION END
- general += G
-
- //Medical Record
- var/datum/data/record/M = new()
- M.fields["id"] = id
- M.fields["name"] = H.real_name
- M.fields["blood_type"] = H.dna.blood_type
- M.fields["b_dna"] = H.dna.unique_enzymes
- M.fields["mi_dis"] = H.get_quirk_string(!medical, CAT_QUIRK_MINOR_DISABILITY)
- M.fields["mi_dis_d"] = H.get_quirk_string(medical, CAT_QUIRK_MINOR_DISABILITY)
- M.fields["ma_dis"] = H.get_quirk_string(!medical, CAT_QUIRK_MAJOR_DISABILITY)
- M.fields["ma_dis_d"] = H.get_quirk_string(medical, CAT_QUIRK_MAJOR_DISABILITY)
- M.fields["cdi"] = "None"
- M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
- M.fields["notes"] = H.get_quirk_string(!medical, CAT_QUIRK_NOTES)
- M.fields["notes_d"] = H.get_quirk_string(medical, CAT_QUIRK_NOTES)
- // SKYRAT EDIT ADD - RP RECORDS
- M.fields["past_records"] = human_client?.prefs?.read_preference(/datum/preference/text/medical) || ""
- // SKYRAT EDIT END
- medical += M
-
- //Security Record
- var/datum/data/record/S = new()
- S.fields["id"] = id
- S.fields["name"] = H.real_name
- S.fields["criminal"] = "None"
- S.fields["citation"] = list()
- S.fields["crim"] = list()
- S.fields["notes"] = "No notes."
- // SKYRAT EDIT ADD - RP RECORDS
- S.fields["past_records"] = human_client?.prefs?.read_preference(/datum/preference/text/security) || ""
- // SKYRAT EDIT END
- security += S
-
- //Locked Record
- var/datum/data/record/L = new()
- L.fields["id"] = md5("[H.real_name][assignment]") //surely this should just be id, like the others?
- L.fields["name"] = H.real_name
- L.fields["rank"] = chosen_assignment // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: L.fields["rank"] = assignment
- L.fields["trim"] = assignment
- G.fields["initial_rank"] = assignment
- L.fields["age"] = H.age
- L.fields["gender"] = H.gender
- if(H.gender == "male")
- G.fields["gender"] = "Male"
- else if(H.gender == "female")
- G.fields["gender"] = "Female"
- else
- G.fields["gender"] = "Other"
- L.fields["blood_type"] = H.dna.blood_type
- L.fields["b_dna"] = H.dna.unique_enzymes
- L.fields["identity"] = H.dna.unique_identity
- L.fields["species"] = H.dna.species.type
- L.fields["features"] = H.dna.features
- L.fields["character_appearance"] = character_appearance
- L.fields["mindref"] = H.mind
- locked += L
- return
-
-//Todo: Add citations to the prinout - you get them from sec record's "citation" field, same as "crim" (which is frankly a terrible fucking field name)
-///Standardized printed records. SPRs. Like SATs but for bad guys who probably didn't actually finish school. Input the records and out comes a paper.
-/proc/print_security_record(datum/data/record/general_data, datum/data/record/security, atom/location)
- if(!istype(general_data) && !istype(security))
- stack_trace("called without any datacores! this may or may not be intentional!")
- if(!isatom(location)) //can't drop the paper if we didn't get passed an atom.
- CRASH("NO VALID LOCATION PASSED.")
-
- GLOB.data_core.securityPrintCount++ //just alters the name of the paper.
- var/obj/item/paper/printed_paper = new(location)
- var/final_paper_text = "Security Record - (SR-[GLOB.data_core.securityPrintCount]) "
- if((istype(general_data, /datum/data/record) && GLOB.data_core.general.Find(general_data)))
- final_paper_text += text("Name: [] ID: [] \nGender: [] \nAge: [] ", general_data.fields["name"], general_data.fields["id"], general_data.fields["gender"], general_data.fields["age"])
- final_paper_text += "\nSpecies: [general_data.fields["species"]] "
- final_paper_text += text("\nFingerprint: [] \nPhysical Status: [] \nMental Status: [] ", general_data.fields["fingerprint"], general_data.fields["p_stat"], general_data.fields["m_stat"])
- //SKYRAT EDIT ADD - RP RECORDS
- if(!(general_data.fields["past_records"] == ""))
- final_paper_text += "\nGeneral Records:\n[general_data.fields["past_records"]]\n"
- //SKYRAT EDIT ADD END
- else
- final_paper_text += "General Record Lost! "
- if((istype(security, /datum/data/record) && GLOB.data_core.security.Find(security)))
- //final_paper_text += text(" \nSecurity Data \nCriminal Status: []", security.fields["criminal"]) // ORIGINAL
- //SKYRAT EDIT ADDITION START - RP RECORDS
- final_paper_text += text(" \nSecurity Data \n")
- if(!(security.fields["past_records"] == ""))
- final_paper_text += "\nSecurity Records:\n[security.fields["past_records"]]\n"
- final_paper_text += text("Criminal Status: []", security.fields["criminal"])
- //SKYRAT EDIT END
-
- final_paper_text += " \n \nCrimes: \n"
- final_paper_text +={"
-
-Crime
-Details
-Author
-Time Added
- "}
- for(var/datum/data/crime/c in security.fields["crim"])
- final_paper_text += "[c.crimeName] "
- final_paper_text += "[c.crimeDetails] "
- final_paper_text += "[c.author] "
- final_paper_text += "[c.time] "
- final_paper_text += " "
- final_paper_text += "
"
-
- final_paper_text += text(" \nImportant Notes: \n\t[] \n \nComments/Log ", security.fields["notes"])
- var/counter = 1
- while(security.fields[text("com_[]", counter)])
- final_paper_text += text("[] ", security.fields[text("com_[]", counter)])
- counter++
- printed_paper.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, general_data.fields["name"])
- else //if no security record
- final_paper_text += "Security Record Lost! "
- printed_paper.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, "Record Lost")
- final_paper_text += ""
- printed_paper.add_raw_text(final_paper_text)
- printed_paper.update_appearance() //make sure we make the paper look like it has writing on it.
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 0d9f670836f..098eb083abf 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -561,7 +561,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
return dna
-/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, list/default_mutation_genes, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/mutations, force_transfer_mutations)
+/// Sets the DNA of the mob to the given DNA.
+/mob/living/carbon/human/proc/hardset_dna(unique_identity, list/mutation_index, list/default_mutation_genes, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/mutations, force_transfer_mutations)
//Do not use force_transfer_mutations for stuff like cloners without some precautions, otherwise some conditional mutations could break (timers, drill hat etc)
if(newfeatures)
dna.features = newfeatures
@@ -579,9 +580,9 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
if(newblood_type)
dna.blood_type = newblood_type
- if(ui)
- dna.unique_identity = ui
- updateappearance(icon_update=0)
+ if(unique_identity)
+ dna.unique_identity = unique_identity
+ updateappearance(icon_update = 0)
if(LAZYLEN(mutation_index))
dna.mutation_index = mutation_index.Copy()
@@ -591,7 +592,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
dna.default_mutation_genes = mutation_index.Copy()
domutcheck()
- if(mrace || newfeatures || ui)
+ if(mrace || newfeatures || unique_identity)
update_body(is_creating = TRUE)
update_mutations_overlay()
diff --git a/code/datums/id_trim/_id_trim.dm b/code/datums/id_trim/_id_trim.dm
index 06c2bec74ec..7000e2d6b1d 100644
--- a/code/datums/id_trim/_id_trim.dm
+++ b/code/datums/id_trim/_id_trim.dm
@@ -16,8 +16,6 @@
var/intern_alt_name = null
/// The icon_state associated with this trim, as it will show on the security HUD.
var/sechud_icon_state = SECHUD_UNKNOWN
- /// Icons to be displayed in the orbit ui. Source: FontAwesome v6 Free Edition.
- var/orbit_icon
/// Accesses that this trim unlocks on a card it is imprinted on. These accesses never take wildcard slots and can be added and removed at will.
var/list/access = list()
diff --git a/code/datums/id_trim/jobs.dm b/code/datums/id_trim/jobs.dm
index 86290c69ec6..18a32214b5c 100644
--- a/code/datums/id_trim/jobs.dm
+++ b/code/datums/id_trim/jobs.dm
@@ -79,7 +79,6 @@
/datum/id_trim/job/assistant
assignment = "Assistant"
trim_state = "trim_assistant"
- orbit_icon = "toolbox"
sechud_icon_state = SECHUD_ASSISTANT
minimal_access = list()
extra_access = list(
@@ -106,7 +105,6 @@
/datum/id_trim/job/atmospheric_technician
assignment = "Atmospheric Technician"
trim_state = "trim_atmospherictechnician"
- orbit_icon = "fan"
department_color = COLOR_ENGINEERING_ORANGE
subdepartment_color = COLOR_ENGINEERING_ORANGE
sechud_icon_state = SECHUD_ATMOSPHERIC_TECHNICIAN
@@ -136,7 +134,6 @@
/datum/id_trim/job/bartender
assignment = "Bartender"
trim_state = "trim_bartender"
- orbit_icon = "cocktail"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SERVICE_LIME
sechud_icon_state = SECHUD_BARTENDER
@@ -161,7 +158,6 @@
/datum/id_trim/job/botanist
assignment = "Botanist"
trim_state = "trim_botanist"
- orbit_icon = "seedling"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SERVICE_LIME
sechud_icon_state = SECHUD_BOTANIST
@@ -186,7 +182,6 @@
assignment = "Captain"
intern_alt_name = "Captain-in-Training"
trim_state = "trim_captain"
- orbit_icon = "crown"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_COMMAND_BLUE
department_state = "departmenthead"
@@ -209,7 +204,6 @@
/datum/id_trim/job/cargo_technician
assignment = "Cargo Technician"
trim_state = "trim_cargotechnician"
- orbit_icon = "box"
department_color = COLOR_CARGO_BROWN
subdepartment_color = COLOR_CARGO_BROWN
sechud_icon_state = SECHUD_CARGO_TECHNICIAN
@@ -234,7 +228,6 @@
/datum/id_trim/job/chaplain
assignment = "Chaplain"
trim_state = "trim_chaplain"
- orbit_icon = "cross"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SERVICE_LIME
sechud_icon_state = SECHUD_CHAPLAIN
@@ -256,7 +249,6 @@
/datum/id_trim/job/chemist
assignment = "Chemist"
trim_state = "trim_chemist"
- orbit_icon = "prescription-bottle"
department_color = COLOR_MEDICAL_BLUE
subdepartment_color = COLOR_MEDICAL_BLUE
sechud_icon_state = SECHUD_CHEMIST
@@ -283,7 +275,6 @@
assignment = "Chief Engineer"
intern_alt_name = "Chief Engineer-in-Training"
trim_state = "trim_stationengineer"
- orbit_icon = "user-astronaut"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_ENGINEERING_ORANGE
department_state = "departmenthead"
@@ -325,7 +316,6 @@
assignment = "Chief Medical Officer"
intern_alt_name = "Chief Medical Officer-in-Training"
trim_state = "trim_medicaldoctor"
- orbit_icon = "user-md"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_MEDICAL_BLUE
department_state = "departmenthead"
@@ -363,7 +353,6 @@
/datum/id_trim/job/clown
assignment = "Clown"
trim_state = "trim_clown"
- orbit_icon = "face-grin-tears"
department_color = COLOR_MAGENTA
subdepartment_color = COLOR_MAGENTA
sechud_icon_state = SECHUD_CLOWN
@@ -382,7 +371,6 @@
/datum/id_trim/job/cook
assignment = "Cook"
trim_state = "trim_cook"
- orbit_icon = "utensils"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SERVICE_LIME
sechud_icon_state = SECHUD_COOK
@@ -410,7 +398,6 @@
/datum/id_trim/job/curator
assignment = "Curator"
trim_state = "trim_curator"
- orbit_icon = "book"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SERVICE_LIME
sechud_icon_state = SECHUD_CURATOR
@@ -431,7 +418,6 @@
/datum/id_trim/job/detective
assignment = "Detective"
trim_state = "trim_detective"
- orbit_icon = "user-secret"
department_color = COLOR_SECURITY_RED
subdepartment_color = COLOR_SECURITY_RED
sechud_icon_state = SECHUD_DETECTIVE
@@ -469,7 +455,6 @@
/datum/id_trim/job/geneticist
assignment = "Geneticist"
trim_state = "trim_geneticist"
- orbit_icon = "dna"
department_color = COLOR_SCIENCE_PINK
subdepartment_color = COLOR_SCIENCE_PINK
sechud_icon_state = SECHUD_GENETICIST
@@ -497,7 +482,6 @@
assignment = "Head of Personnel"
intern_alt_name = "Head of Personnel-in-Training"
trim_state = "trim_headofpersonnel"
- orbit_icon = "dog"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_SERVICE_LIME
department_state = "departmenthead"
@@ -549,7 +533,6 @@
assignment = "Head of Security"
intern_alt_name = "Head of Security-in-Training"
trim_state = "trim_securityofficer"
- orbit_icon = "user-shield"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_SECURITY_RED
department_state = "departmenthead"
@@ -606,7 +589,6 @@
/datum/id_trim/job/janitor
assignment = "Janitor"
trim_state = "trim_janitor"
- orbit_icon = "broom"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SERVICE_LIME
sechud_icon_state = SECHUD_JANITOR
@@ -627,7 +609,6 @@
/datum/id_trim/job/lawyer
assignment = "Lawyer"
trim_state = "trim_lawyer"
- orbit_icon = "gavel"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SECURITY_RED
sechud_icon_state = SECHUD_LAWYER
@@ -648,7 +629,6 @@
/datum/id_trim/job/medical_doctor
assignment = "Medical Doctor"
trim_state = "trim_medicaldoctor"
- orbit_icon = "staff-snake"
department_color = COLOR_MEDICAL_BLUE
subdepartment_color = COLOR_MEDICAL_BLUE
sechud_icon_state = SECHUD_MEDICAL_DOCTOR
@@ -674,7 +654,6 @@
/datum/id_trim/job/mime
assignment = "Mime"
trim_state = "trim_mime"
- orbit_icon = "comment-slash"
department_color = COLOR_SILVER
subdepartment_color = COLOR_WHITE
sechud_icon_state = SECHUD_MIME
@@ -693,7 +672,6 @@
/datum/id_trim/job/paramedic
assignment = "Paramedic"
trim_state = "trim_paramedic"
- orbit_icon = "truck-medical"
department_color = COLOR_MEDICAL_BLUE
subdepartment_color = COLOR_MEDICAL_BLUE
sechud_icon_state = SECHUD_PARAMEDIC
@@ -724,7 +702,6 @@
/datum/id_trim/job/prisoner
assignment = "Prisoner"
trim_state = "trim_warden"
- orbit_icon = "lock"
department_color = COLOR_PRISONER_BLACK
subdepartment_color = COLOR_PRISONER_ORANGE
sechud_icon_state = SECHUD_PRISONER
@@ -767,7 +744,6 @@
/datum/id_trim/job/psychologist
assignment = "Psychologist"
trim_state = "trim_psychologist"
- orbit_icon = "brain"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_MEDICAL_BLUE
sechud_icon_state = SECHUD_PSYCHOLOGIST
@@ -788,7 +764,6 @@
/datum/id_trim/job/quartermaster
assignment = "Quartermaster"
trim_state = "trim_quartermaster"
- orbit_icon = "sack-dollar"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_CARGO_BROWN
department_state = "departmenthead"
@@ -824,7 +799,6 @@
assignment = "Research Director"
intern_alt_name = "Research Director-in-Training"
trim_state = "trim_scientist"
- orbit_icon = "user-graduate"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_SCIENCE_PINK
department_state = "departmenthead"
@@ -872,7 +846,6 @@
/datum/id_trim/job/roboticist
assignment = "Roboticist"
trim_state = "trim_roboticist"
- orbit_icon = "battery-half"
department_color = COLOR_SCIENCE_PINK
subdepartment_color = COLOR_SCIENCE_PINK
sechud_icon_state = SECHUD_ROBOTICIST
@@ -900,7 +873,6 @@
/datum/id_trim/job/scientist
assignment = "Scientist"
trim_state = "trim_scientist"
- orbit_icon = "flask"
department_color = COLOR_SCIENCE_PINK
subdepartment_color = COLOR_SCIENCE_PINK
sechud_icon_state = SECHUD_SCIENTIST
@@ -929,7 +901,6 @@
/datum/id_trim/job/security_officer
assignment = "Security Officer"
trim_state = "trim_securityofficer"
- orbit_icon = "shield-halved"
department_color = COLOR_SECURITY_RED
subdepartment_color = COLOR_SECURITY_RED
sechud_icon_state = SECHUD_SECURITY_OFFICER
@@ -1050,7 +1021,6 @@
/datum/id_trim/job/shaft_miner
assignment = "Shaft Miner"
trim_state = "trim_shaftminer"
- orbit_icon = "digging"
department_color = COLOR_CARGO_BROWN
subdepartment_color = COLOR_SCIENCE_PINK
sechud_icon_state = SECHUD_SHAFT_MINER
@@ -1087,7 +1057,6 @@
/datum/id_trim/job/station_engineer
assignment = "Station Engineer"
trim_state = "trim_stationengineer"
- orbit_icon = "gears"
department_color = COLOR_ENGINEERING_ORANGE
subdepartment_color = COLOR_ENGINEERING_ORANGE
sechud_icon_state = SECHUD_STATION_ENGINEER
@@ -1117,7 +1086,6 @@
/datum/id_trim/job/virologist
assignment = "Virologist"
trim_state = "trim_virologist"
- orbit_icon = "virus"
department_color = COLOR_MEDICAL_BLUE
subdepartment_color = COLOR_MEDICAL_BLUE
sechud_icon_state = SECHUD_VIROLOGIST
@@ -1142,7 +1110,6 @@
/datum/id_trim/job/warden
assignment = "Warden"
trim_state = "trim_warden"
- orbit_icon = "handcuffs"
department_color = COLOR_SECURITY_RED
subdepartment_color = COLOR_SECURITY_RED
sechud_icon_state = SECHUD_WARDEN
diff --git a/code/datums/records/crime.dm b/code/datums/records/crime.dm
new file mode 100644
index 00000000000..27daf0646f6
--- /dev/null
+++ b/code/datums/records/crime.dm
@@ -0,0 +1,60 @@
+/**
+ * Crime data. Used to store information about crimes.
+ */
+/datum/crime
+ /// Name of the crime
+ var/name
+ /// Details about the crime
+ var/details
+ /// Player that wrote the crime
+ var/author
+ /// Time of the crime
+ var/time
+
+/datum/crime/New(name = "Crime", details = "No details provided.", author = "Anonymous")
+ src.author = author
+ src.details = details
+ src.name = name
+ src.time = station_time_timestamp()
+
+/datum/crime/citation
+ /// Fine for the crime
+ var/fine
+ /// Amount of money paid for the crime
+ var/paid
+
+/datum/crime/citation/New(name = "Citation", details = "No details provided.", author = "Anonymous", fine = 0)
+ . = ..()
+ src.fine = fine
+ src.paid = 0
+
+/// Pays off a fine and attempts to fix any weird values.
+/datum/crime/citation/proc/pay_fine(amount)
+ paid += amount
+ if(paid > fine)
+ paid = fine
+
+ fine -= amount
+ if(fine < 0)
+ fine = 0
+
+ return TRUE
+
+/// Sends a citation alert message to the target's PDA.
+/datum/crime/citation/proc/alert_owner(mob/sender, atom/source, target_name, message)
+ for(var/obj/item/modular_computer/tablet in GLOB.TabletMessengers)
+ if(tablet.saved_identification != target_name)
+ continue
+
+ var/datum/signal/subspace/messaging/tablet_msg/signal = new(source, list(
+ name = "Security Citation",
+ job = "Citation Server",
+ message = message,
+ targets = list(tablet),
+ automated = TRUE
+ ))
+ signal.send_to_receivers()
+ sender.log_message("(PDA: Citation Server) sent \"[message]\" to [signal.format_target()]", LOG_PDA)
+ break
+
+ return TRUE
diff --git a/code/datums/records/data.dm b/code/datums/records/data.dm
new file mode 100644
index 00000000000..2b63dd4e796
--- /dev/null
+++ b/code/datums/records/data.dm
@@ -0,0 +1,4 @@
+/// Currently used for experiments, vending products.
+/datum/data
+ /// Given name for the item.
+ var/name
diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm
new file mode 100644
index 00000000000..20fd5ef1ec0
--- /dev/null
+++ b/code/datums/records/manifest.dm
@@ -0,0 +1,171 @@
+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()
+ for(var/i in GLOB.new_player_list)
+ var/mob/dead/new_player/readied_player = i
+ if(readied_player.new_character)
+ log_manifest(readied_player.ckey,readied_player.new_character.mind,readied_player.new_character)
+ if(ishuman(readied_player.new_character))
+ inject(readied_player.new_character, readied_player.client) // SKYRAT EDIT - RP Records - ORIGINAL: inject(readied_player.new_character)
+ CHECK_TICK
+
+/// 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.GetJob(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, // SKYRAT EDIT ADDITION - Alt Titles
+ )
+ continue
+ for(var/department_type as anything in job.departments_list)
+ 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, // SKYRAT EDIT ADDITION - Alt Titles
+ )
+ 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 = {"
+
+
+ Name Rank
+ "}
+ for(var/department in manifest)
+ var/list/entries = manifest[department]
+ dat += "[department] "
+ //JUST
+ var/even = FALSE
+ for(var/entry in entries)
+ var/list/entry_list = entry
+ dat += "[entry_list["name"]] [entry_list["rank"]] "
+ even = !even
+
+ dat += "
"
+ 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, client/person_client) // SKYRAT EDIT - RP Records - ORIGINAL: /datum/manifest/proc/inject(mob/living/carbon/human/person)
+ set waitfor = FALSE
+ if(!(person.mind?.assigned_role.job_flags & JOB_CREW_MANIFEST))
+ return
+
+ var/assignment = person.mind.assigned_role.title
+ var/mutable_appearance/character_appearance = new(person.appearance)
+ var/person_gender = "Other"
+ if(person.gender == "male")
+ person_gender = "Male"
+ if(person.gender == "female")
+ person_gender = "Female"
+
+ // SKYRAT EDIT ADDITION BEGIN - ALTERNATIVE_JOB_TITLES
+ // The alt job title, if user picked one, or the default
+ var/chosen_assignment = person_client?.prefs.alt_job_titles[assignment] || assignment
+ // SKYRAT EDIT ADDITION END - ALTERNATIVE_JOB_TITLES
+
+ var/datum/record/locked/lockfile = new(
+ age = person.age,
+ blood_type = person.dna.blood_type,
+ character_appearance = character_appearance,
+ dna_string = person.dna.unique_enzymes,
+ fingerprint = md5(person.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 = person.dna.species.name,
+ trim = assignment,
+ // Locked specifics
+ dna_ref = person.dna,
+ mind_ref = person.mind,
+ )
+
+ new /datum/record/crew(
+ age = person.age,
+ blood_type = person.dna.blood_type,
+ character_appearance = character_appearance,
+ dna_string = person.dna.unique_enzymes,
+ fingerprint = md5(person.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 = person.dna.species.name,
+ trim = assignment,
+ // Crew specific
+ lock_ref = REF(lockfile),
+ major_disabilities = person.get_quirk_string(FALSE, CAT_QUIRK_MAJOR_DISABILITY),
+ major_disabilities_desc = person.get_quirk_string(TRUE, CAT_QUIRK_MAJOR_DISABILITY),
+ minor_disabilities = person.get_quirk_string(FALSE, CAT_QUIRK_MINOR_DISABILITY),
+ 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
+ background_information = person_client?.prefs.read_preference(/datum/preference/text/background) || "",
+ exploitable_information = person_client?.prefs.read_preference(/datum/preference/text/exploitable) || "",
+ 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
+ )
+
+ return
+
+/// 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
diff --git a/code/datums/records/medical_note.dm b/code/datums/records/medical_note.dm
new file mode 100644
index 00000000000..a1843394c2a
--- /dev/null
+++ b/code/datums/records/medical_note.dm
@@ -0,0 +1,15 @@
+/**
+ * Player-written medical note.
+ */
+/datum/medical_note
+ /// Player that wrote the note
+ var/author
+ /// Details of the note
+ var/content
+ /// Station timestamp
+ var/time
+
+/datum/medical_note/New(author = "Anonymous", content = "No details provided.")
+ src.author = author
+ src.content = content
+ src.time = station_time_timestamp()
diff --git a/code/datums/records/record.dm b/code/datums/records/record.dm
new file mode 100644
index 00000000000..69c0682e6b2
--- /dev/null
+++ b/code/datums/records/record.dm
@@ -0,0 +1,280 @@
+/**
+ * Record datum. Used for crew records and admin locked records.
+ */
+/datum/record
+ /// Age of the character
+ var/age
+ /// Their blood type
+ var/blood_type
+ /// Character appearance
+ var/mutable_appearance/character_appearance
+ /// DNA string
+ var/dna_string
+ /// Fingerprint string (md5)
+ var/fingerprint
+ /// The character's gender
+ var/gender
+ /// The character's initial rank at roundstart
+ var/initial_rank
+ /// The character's name
+ var/name = "Unknown"
+ /// The character's rank
+ var/rank
+ /// The character's species
+ var/species
+ /// The character's ID trim
+ var/trim
+
+/datum/record/New(
+ age = 18,
+ blood_type = "?",
+ character_appearance,
+ dna_string = "Unknown",
+ fingerprint = "?????",
+ gender = "Other",
+ initial_rank = "Unassigned",
+ name = "Unknown",
+ rank = "Unassigned",
+ species = "Human",
+ trim = "Unassigned",
+)
+ src.age = age
+ src.blood_type = blood_type
+ src.character_appearance = character_appearance
+ src.dna_string = dna_string
+ src.fingerprint = fingerprint
+ src.gender = gender
+ src.initial_rank = rank
+ src.name = name
+ src.rank = rank
+ src.species = species
+ src.trim = trim
+
+/**
+ * Crew record datum
+ */
+/datum/record/crew
+ /// List of citations
+ var/list/citations = list()
+ /// List of crimes
+ var/list/crimes = list()
+ /// Unique ID generated that is used to fetch lock record
+ var/lock_ref
+ /// Names of major disabilities
+ var/major_disabilities
+ /// Fancy description of major disabilities
+ var/major_disabilities_desc
+ /// List of medical notes
+ var/list/medical_notes = list()
+ /// Names of minor disabilities
+ var/minor_disabilities
+ /// Fancy description of minor disabilities
+ var/minor_disabilities_desc
+ /// Positive and neutral quirk strings
+ var/quirk_notes
+ /// Security note
+ var/security_note
+ /// Current arrest status
+ var/wanted_status = WANTED_NONE
+
+/datum/record/crew/New(
+ age = 18,
+ blood_type = "?",
+ character_appearance,
+ dna_string = "Unknown",
+ fingerprint = "?????",
+ gender = "Other",
+ initial_rank = "Unassigned",
+ name = "Unknown",
+ rank = "Unassigned",
+ species = "Human",
+ trim = "Unassigned",
+ /// Crew specific
+ lock_ref,
+ major_disabilities = "None",
+ major_disabilities_desc = "No disabilities have been diagnosed at the moment.",
+ minor_disabilities = "None",
+ minor_disabilities_desc = "No disabilities have been diagnosed at the moment.",
+ quirk_notes,
+ // SKYRAT EDIT START - RP Records
+ background_information = "",
+ exploitable_information = "",
+ past_general_records = "",
+ past_medical_records = "",
+ past_security_records = "",
+ // SKYRAT EDIT END
+)
+ . = ..()
+ src.lock_ref = lock_ref
+ src.major_disabilities = major_disabilities
+ src.major_disabilities_desc = major_disabilities_desc
+ src.minor_disabilities = minor_disabilities
+ src.minor_disabilities_desc = minor_disabilities_desc
+ src.quirk_notes = quirk_notes
+ // SKYRAT EDIT START - RP Records
+ src.background_information = background_information
+ src.exploitable_information = exploitable_information
+ src.past_general_records = past_general_records
+ src.past_medical_records = past_medical_records
+ src.past_security_records = past_security_records
+ // SKYRAT EDIT END
+
+ GLOB.manifest.general += src
+
+/datum/record/crew/Destroy()
+ GLOB.manifest.general -= src
+ return ..()
+
+/**
+ * Admin locked record
+ */
+/datum/record/locked
+ /// Mob's dna
+ var/datum/dna/dna_ref
+ /// Mind datum
+ var/datum/mind/mind_ref
+
+/datum/record/locked/New(
+ age = 18,
+ blood_type = "?",
+ character_appearance,
+ dna_string = "Unknown",
+ fingerprint = "?????",
+ gender = "Other",
+ initial_rank = "Unassigned",
+ name = "Unknown",
+ rank = "Unassigned",
+ species = "Human",
+ trim = "Unassigned",
+ /// Locked specific
+ datum/dna/dna_ref,
+ datum/mind/mind_ref,
+)
+ . = ..()
+ src.dna_ref = dna_ref
+ src.mind_ref = mind_ref
+
+ GLOB.manifest.locked += src
+
+/datum/record/locked/Destroy()
+ GLOB.manifest.locked -= src
+ return ..()
+
+/// A helper proc to get the front photo of a character from the record.
+/// Handles calling `get_photo()`, read its documentation for more information.
+/datum/record/crew/proc/get_front_photo()
+ return get_photo("photo_front", SOUTH)
+
+/// A helper proc to get the side photo of a character from the record.
+/// Handles calling `get_photo()`, read its documentation for more information.
+/datum/record/crew/proc/get_side_photo()
+ return get_photo("photo_side", WEST)
+
+/**
+ * You shouldn't be calling this directly, use `get_front_photo()` or `get_side_photo()`
+ * instead.
+ *
+ * This is the proc that handles either fetching (if it was already generated before) or
+ * generating (if it wasn't) the specified photo from the specified record. This is only
+ * intended to be used by records that used to try to access `fields["photo_front"]` or
+ * `fields["photo_side"]`, and will return an empty icon if there isn't any of the necessary
+ * fields.
+ *
+ * Arguments:
+ * * field_name - The name of the key in the `fields` list, of the record itself.
+ * * orientation - The direction in which you want the character appearance to be rotated
+ * in the outputed photo.
+ *
+ * Returns an empty `/icon` if there was no `character_appearance` entry in the `fields` list,
+ * returns the generated/cached photo otherwise.
+ */
+/datum/record/crew/proc/get_photo(field_name, orientation)
+ if(!field_name)
+ return
+
+ if(!character_appearance)
+ return new /icon()
+
+ var/mutable_appearance/appearance = character_appearance
+ appearance.setDir(orientation)
+
+ var/icon/picture_image = getFlatIcon(appearance)
+
+ var/datum/picture/picture = new
+ picture.picture_name = name
+ picture.picture_desc = "This is [name]."
+ picture.picture_image = picture_image
+
+ var/obj/item/photo/photo = new(null, picture)
+ field_name = photo
+ return photo
+
+/// Returns a paper printout of the current record's crime data.
+/datum/record/crew/proc/get_rapsheet(alias, header = "Rapsheet", description = "No further details.")
+ var/print_count = ++GLOB.manifest.print_count
+ var/obj/item/paper/printed_paper = new
+ var/final_paper_text = text("SR-[print_count]: [header] ")
+
+ final_paper_text += text("Name: [] Gender: [] Age: [] ", name, gender, age)
+ if(alias != name)
+ final_paper_text += text("Alias: [] ", alias)
+
+ final_paper_text += text("Species: [] Fingerprint: [] Wanted Status: [] ", species, fingerprint, wanted_status)
+
+ //SKYRAT EDIT ADD - RP RECORDS
+ if(past_general_records != "")
+ final_paper_text += "\nGeneral Records:\n[past_general_records]\n"
+ //SKYRAT EDIT ADD END
+
+ final_paper_text += text("Security Data ")
+
+ //SKYRAT EDIT ADDITION START - RP RECORDS
+ if(past_security_records != "")
+ final_paper_text += " Security Records: [past_security_records] "
+ //SKYRAT EDIT END
+
+ final_paper_text += "Crimes: "
+ final_paper_text += {"
+
+ Crime
+ Details
+ Author
+ Time Added
+ "}
+ for(var/datum/crime/crime in crimes)
+ final_paper_text += "[crime.name] "
+ final_paper_text += "[crime.details] "
+ final_paper_text += "[crime.author] "
+ final_paper_text += "[crime.time] "
+ final_paper_text += " "
+ final_paper_text += "
"
+
+ final_paper_text += "Citations: "
+ final_paper_text += {"
+
+ Citation
+ Details
+ Author
+ Time Added
+ Fine
+ "}
+ for(var/datum/crime/citation/warrant in citations)
+ final_paper_text += "[warrant.name] "
+ final_paper_text += "[warrant.details] "
+ final_paper_text += "[warrant.author] "
+ final_paper_text += "[warrant.time] "
+ final_paper_text += "[warrant.fine] "
+ final_paper_text += " "
+ final_paper_text += "
"
+
+ final_paper_text += text("Important Notes: ")
+ if(security_note)
+ final_paper_text += text("- [security_note] ")
+ if(description)
+ final_paper_text += text("- [description] ")
+
+ printed_paper.name = text("SR-[] '[]'", print_count, name)
+ printed_paper.add_raw_text(final_paper_text)
+ printed_paper.update_appearance()
+
+ return printed_paper
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 27cd5175cfe..36157cd76b2 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -309,32 +309,30 @@ Security HUDs! Basic mode shows only the job.
/mob/living/carbon/human/proc/sec_hud_set_security_status()
var/image/holder = hud_list[WANTED_HUD]
- var/icon/I = icon(icon, icon_state, dir)
- holder.pixel_y = I.Height() - world.icon_size
- var/perpname = get_face_name(get_id_name(""))
- if(perpname && GLOB.data_core)
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
- if(R)
- var/has_criminal_entry = TRUE
- switch(R.fields["criminal"])
- if("*Arrest*")
- holder.icon_state = "hudwanted"
- if("Incarcerated")
- holder.icon_state = "hudincarcerated"
- if("Suspected")
- holder.icon_state = "hudsuspected"
- if("Paroled")
- holder.icon_state = "hudparolled"
- if("Discharged")
- holder.icon_state = "huddischarged"
- else
- has_criminal_entry = FALSE
- if(has_criminal_entry)
- set_hud_image_active(WANTED_HUD)
- return
+ var/icon/sec_icon = icon(icon, icon_state, dir)
+ holder.pixel_y = sec_icon.Height() - world.icon_size
+ var/perp_name = get_face_name(get_id_name(""))
- holder.icon_state = null
- set_hud_image_inactive(WANTED_HUD)
+ if(!perp_name || !GLOB.manifest)
+ holder.icon_state = null
+ set_hud_image_inactive(WANTED_HUD)
+ return
+
+ var/datum/record/crew/target = find_record(perp_name)
+ if(!target || target.wanted_status == WANTED_NONE)
+ return
+
+ switch(target.wanted_status)
+ if(WANTED_ARREST)
+ holder.icon_state = "hudwanted"
+ if(WANTED_PRISONER)
+ holder.icon_state = "hudincarcerated"
+ if(WANTED_SUSPECT)
+ holder.icon_state = "hudsuspected"
+ if(WANTED_PAROLE)
+ holder.icon_state = "hudparolled"
+ if(WANTED_DISCHARGED)
+ holder.icon_state = "huddischarged"
/***********************************************
Diagnostic HUDs!
diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm
index 339126c0c47..54ecff1a79a 100644
--- a/code/game/machinery/computer/_computer.dm
+++ b/code/game/machinery/computer/_computer.dm
@@ -19,6 +19,8 @@
var/time_to_unscrew = 2 SECONDS
/// Are we authenticated to use this? Used by things like comms console, security and medical data, and apc controller.
var/authenticated = FALSE
+ /// The character preview view for the UI.
+ var/atom/movable/screen/map_view/char_preview/character_preview_view
/datum/armor/machinery_computer
fire = 40
@@ -148,3 +150,154 @@
SHOULD_CALL_PARENT(TRUE)
. = ..()
update_use_power(IDLE_POWER_USE)
+
+/obj/machinery/computer/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ var/datum/record/crew/target
+ if(params["crew_ref"])
+ target = locate(params["crew_ref"]) in GLOB.manifest.general
+
+ switch(action)
+ if("edit_field")
+ target = locate(params["ref"]) in GLOB.manifest.general
+ var/field = params["field"]
+ if(!field || !target?.vars[field])
+ return FALSE
+
+ var/value = trim(params["value"], MAX_BROADCAST_LEN)
+ target.vars[field] = value || "Unknown"
+
+ return TRUE
+
+ if("expunge_record")
+ if(!target)
+ return FALSE
+
+ expunge_record_info(target)
+ balloon_alert(usr, "record expunged")
+ playsound(src, 'sound/machines/terminal_eject.ogg', 70, TRUE)
+
+ return TRUE
+
+ if("login")
+ authenticated = secure_login(usr)
+ return TRUE
+
+ if("logout")
+ balloon_alert(usr, "logged out")
+ playsound(src, 'sound/machines/terminal_off.ogg', 70, TRUE)
+ authenticated = FALSE
+
+ return TRUE
+
+ if("purge_records")
+ ui.close()
+ balloon_alert(usr, "purging records")
+ playsound(src, 'sound/machines/terminal_alert.ogg', 70, TRUE)
+
+ if(do_after(usr, 5 SECONDS))
+ for(var/datum/record/crew/entry in GLOB.manifest.general)
+ expunge_record_info(entry)
+
+ balloon_alert(usr, "records purged")
+ playsound(src, 'sound/machines/terminal_off.ogg', 70, TRUE)
+
+ return TRUE
+
+ if("view_record")
+ if(!target)
+ return FALSE
+
+ playsound(src, "sound/machines/terminal_button0[rand(1, 8)].ogg", 50, TRUE)
+ update_preview(usr, params["assigned_view"], target)
+ return TRUE
+
+ return FALSE
+
+/// Creates a character preview view for the UI.
+/obj/machinery/computer/proc/create_character_preview_view(mob/user)
+ var/assigned_view = "preview_[user.ckey]_[REF(src)]_records"
+ if(user.client?.screen_maps[assigned_view])
+ return
+
+ var/atom/movable/screen/map_view/char_preview/new_view = new(null, src)
+ new_view.generate_view(assigned_view)
+ new_view.display_to(user)
+
+/// Takes a record and updates the character preview view to match it.
+/obj/machinery/computer/proc/update_preview(mob/user, assigned_view, datum/record/crew/target)
+ var/mutable_appearance/preview = new(target.character_appearance)
+ preview.underlays += mutable_appearance('icons/effects/effects.dmi', "static_base", alpha = 20)
+ preview.add_overlay(mutable_appearance(generate_icon_alpha_mask('icons/effects/effects.dmi', "scanline"), alpha = 20))
+
+ var/atom/movable/screen/map_view/char_preview/old_view = user.client?.screen_maps[assigned_view]?[1]
+ if(!old_view)
+ return
+
+ old_view.appearance = preview.appearance
+
+/// Expunges info from a record.
+/obj/machinery/computer/proc/expunge_record_info(datum/record/crew/target)
+ return
+
+/// Detects whether a user can use buttons on the machine
+/obj/machinery/computer/proc/has_auth(mob/user)
+ if(!isliving(user))
+ return FALSE
+ var/mob/living/player = user
+
+ if(issilicon(player)) // Silicons don't need to authenticate
+ return TRUE
+
+ var/obj/item/card/auth = player.get_idcard(TRUE)
+ if(!auth)
+ return FALSE
+ var/list/access = auth.GetAccess()
+ if(!check_access_list(access))
+ return FALSE
+
+ return TRUE
+
+/// Inserts a new record into GLOB.manifest.general. Requires a photo to be taken.
+/obj/machinery/computer/proc/insert_new_record(mob/user, obj/item/photo/mugshot)
+ if(!mugshot || !is_operational || !user.canUseTopic(src, be_close = !issilicon(user)))
+ return FALSE
+
+ if(!authenticated && !has_auth(user))
+ balloon_alert(user, "access denied")
+ playsound(src, 'sound/machines/terminal_error.ogg', 70, TRUE)
+ return FALSE
+
+ var/trimmed = copytext(mugshot.name, 9, MAX_NAME_LEN) // Remove "photo - "
+ var/name = tgui_input_text(user, "Enter the name of the new record.", "New Record", trimmed, MAX_NAME_LEN)
+ if(!name || !is_operational || !user.canUseTopic(src, be_close = !issilicon(user)) || !mugshot || QDELETED(mugshot) || QDELETED(src))
+ return FALSE
+
+ new /datum/record/crew(name = name, character_appearance = mugshot.picture.picture_image)
+
+ balloon_alert(user, "record created")
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 70, TRUE)
+
+ qdel(mugshot)
+
+ return TRUE
+
+/// Secure login
+/obj/machinery/computer/proc/secure_login(mob/user)
+ if(!user.canUseTopic(src, be_close = !issilicon(user)) || !is_operational)
+ return FALSE
+
+ if(!has_auth(user))
+ balloon_alert(user, "access denied")
+ playsound(src, 'sound/machines/terminal_error.ogg', 70, TRUE)
+ return FALSE
+
+ balloon_alert(user, "logged in")
+ playsound(src, 'sound/machines/terminal_on.ogg', 70, TRUE)
+
+ return TRUE
+
+
diff --git a/code/game/machinery/computer/arcade/orion.dm b/code/game/machinery/computer/arcade/orion.dm
index 4669254622c..05123a4c11b 100644
--- a/code/game/machinery/computer/arcade/orion.dm
+++ b/code/game/machinery/computer/arcade/orion.dm
@@ -139,12 +139,6 @@ GLOBAL_LIST_INIT(orion_events, generate_orion_events())
gamer.client.give_award(/datum/award/achievement/misc/gamer, gamer) // PSYCH REPORT NOTE: patient kept rambling about how they did it for an "achievement", recommend continued holding for observation
gamer.mind?.adjust_experience(/datum/skill/gaming, 50) // cheevos make u better
- if(!isnull(GLOB.data_core.general))
- for(var/datum/data/record/insanity_records in GLOB.data_core.general)
- if(insanity_records.fields["name"] == gamer.name)
- insanity_records.fields["m_stat"] = "*Unstable*"
- return
-
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/user, datum/tgui/ui)
. = ..()
ui = SStgui.try_update_ui(user, src, ui)
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 2a297ef7ff4..cef5baff9f0 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -1,6 +1,4 @@
-
-
-/obj/machinery/computer/med_data//TODO:SANITY
+/obj/machinery/computer/med_data
name = "medical records console"
desc = "This can be used to check medical records."
icon_screen = "medcomp"
@@ -8,619 +6,11 @@
req_one_access = list(ACCESS_MEDICAL, ACCESS_DETECTIVE, ACCESS_GENETICS)
circuit = /obj/item/circuitboard/computer/med_data
light_color = LIGHT_COLOR_BLUE
- var/rank = null
- var/screen = null
- var/datum/data/record/active1
- var/datum/data/record/active2
- var/temp = null
- var/printing = null
- //Sorting Variables
- var/sortBy = "name"
- var/order = 1 // -1 = Descending - 1 = Ascending
-
/obj/machinery/computer/med_data/syndie
icon_keyboard = "syndie_key"
req_one_access = list(ACCESS_SYNDICATE)
-/obj/machinery/computer/med_data/ui_interact(mob/user)
- . = ..()
- /* - SKYRAT EDIT REMOVAL - AESTHETICS
- if(isliving(user))
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- */
- var/dat
- if(temp)
- dat = text("[temp] Clear Screen ")
- else
- if(authenticated)
- switch(screen)
- if(1)
- dat += {"
-Search Records
-List Records
-
-Virus Database
-Medbot Tracking
-
-Record Maintenance
-{Log Out}
-"}
- if(2)
- dat += {"
-
-
-
-
-Name
-ID
-Fingerprints (F) | DNA UE (D)
-Blood Type
-Physical Status
-Mental Status
- "}
-
-
- if(!isnull(GLOB.data_core.general))
- for(var/datum/data/record/R in sort_record(GLOB.data_core.general, sortBy, order))
- var/blood_type = ""
- var/b_dna = ""
- for(var/datum/data/record/E in GLOB.data_core.medical)
- if((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
- blood_type = E.fields["blood_type"]
- b_dna = E.fields["b_dna"]
- var/background
-
- if(R.fields["m_stat"] == "*Insane*" || R.fields["p_stat"] == "*Deceased*")
- background = "'background-color:#990000;'"
- else if(R.fields["p_stat"] == "*Unconscious*" || R.fields["m_stat"] == "*Unstable*")
- background = "'background-color:#CD6500;'"
- else if(R.fields["p_stat"] == "Physically Unfit" || R.fields["m_stat"] == "*Watch*")
- background = "'background-color:#3BB9FF;'"
- else
- background = "'background-color:#4F7529;'"
-
- dat += text("[] ", background, R.fields["id"], R.fields["name"])
- dat += text("[] ", R.fields["id"])
- dat += text("F: []D: [] ", R.fields["fingerprint"], b_dna)
- dat += text("[] ", blood_type)
- dat += text("[] ", R.fields["p_stat"])
- dat += text("[] ", R.fields["m_stat"])
- dat += "
"
- dat += "Back "
- if(3)
- dat += "Records Maintenance \nBackup To Disk \nUpload From Disk \nDelete All Records \n \nBack "
- if(4)
-
- dat += ""
- if(5)
- dat += "Virus Database "
- for(var/Dt in typesof(/datum/disease/))
- var/datum/disease/Dis = new Dt(0)
- if(istype(Dis, /datum/disease/advance))
- continue // TODO (tm): Add advance diseases to the virus database which no one uses.
- if(!Dis.desc)
- continue
- dat += "[Dis.name] "
- dat += "Back "
- if(6)
- dat += "Medical Robot Monitor "
- dat += "Back "
- dat += "Medical Robots: "
- var/bdat = null
- for(var/mob/living/simple_animal/bot/medbot/M in GLOB.alive_mob_list)
- if(M.z != z)
- continue //only find medibots on the same z-level as the computer
- var/turf/bl = get_turf(M)
- if(bl) //if it can't find a turf for the medibot, then it probably shouldn't be showing up
- bdat += "[M.name] - \[[bl.x],[bl.y]\] - [M.bot_mode_flags & BOT_MODE_ON ? "Online" : "Offline"] "
- if(!bdat)
- dat += "None detected "
- else
- dat += " [bdat]"
-
- else
- else
- dat += "{Log In} "
- var/datum/browser/popup = new(user, "med_rec", "Medical Records Console", 600, 400)
- popup.set_content(dat)
- popup.open()
-
-/obj/machinery/computer/med_data/Topic(href, href_list)
- . = ..()
- if(.)
- return .
- if(!(active1 in GLOB.data_core.general))
- active1 = null
- if(!(active2 in GLOB.data_core.medical))
- active2 = null
-
- if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || isAdminGhostAI(usr))
- usr.set_machine(src)
- if(href_list["temp"])
- temp = null
- else if(href_list["logout"])
- authenticated = null
- screen = null
- active1 = null
- active2 = null
- playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
- else if(href_list["choice"])
- //SKYRAT EDIT ADD - RP RECORDS
- if(href_list["choice"] == "View Past Medical")
- if(istype(active2, /datum/data/record))
- temp = "Medical Records: "
- temp += ""
- temp += "[active2.fields["past_records"]] "
- temp += " "
-
- if(href_list["choice"] == "View Past General")
- if(istype(active1, /datum/data/record))
- temp = "General Records: "
- temp += ""
- temp += "[active1.fields["past_records"]] "
- temp += " "
- //SKYRAT EDIT END
- // SORTING!
- if(href_list["choice"] == "Sorting")
- // Reverse the order if clicked twice
- if(sortBy == href_list["sort"])
- if(order == 1)
- order = -1
- else
- order = 1
- else
- // New sorting order!
- sortBy = href_list["sort"]
- order = initial(order)
- else if(href_list["login"])
- var/obj/item/card/id/I
- if(isliving(usr))
- var/mob/living/L = usr
- I = L.get_idcard(TRUE)
- if(issilicon(usr))
- active1 = null
- active2 = null
- authenticated = 1
- rank = "AI"
- screen = 1
- else if(isAdminGhostAI(usr))
- active1 = null
- active2 = null
- authenticated = 1
- rank = "Central Command"
- screen = 1
- else if(istype(I) && check_access(I))
- active1 = null
- active2 = null
- authenticated = I.registered_name
- rank = I.assignment
- screen = 1
- else
- to_chat(usr, span_danger("Unauthorized access."))
- playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
- if(authenticated)
- if(href_list["screen"])
- screen = text2num(href_list["screen"])
- if(screen < 1)
- screen = 1
-
- active1 = null
- active2 = null
-
- else if(href_list["vir"])
- var/type = text2path(href_list["vir"] || "")
- if(!ispath(type, /datum/disease))
- return
-
- var/datum/disease/disease = new type(0)
- var/applicable_mob_names = ""
- for(var/mob/viable_mob as anything in disease.viable_mobtypes)
- applicable_mob_names += " [initial(viable_mob.name)];"
- temp = {"Name: [disease.name]
-Number of stages: [disease.max_stages]
-Spread: [disease.spread_text] Transmission
-Possible Cure: [(disease.cure_text || "none")]
-Affected Lifeforms: [applicable_mob_names]
-
-Notes: [disease.desc]
-
-Severity: [disease.severity]"}
-
- else if(href_list["del_all"])
- temp = "Are you sure you wish to delete all records? \n\tYes \n\tNo "
-
- else if(href_list["del_all2"])
- usr.investigate_log("has deleted all medical records.", INVESTIGATE_RECORDS)
- GLOB.data_core.medical.Cut()
- temp = "All records deleted."
-
- else if(href_list["field"])
- var/a1 = active1
- var/a2 = active2
- switch(href_list["field"])
- if("fingerprint")
- if(active1)
- var/t1 = stripped_input("Please input fingerprint hash:", "Med. records", active1.fields["fingerprint"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, a1))
- return
- active1.fields["fingerprint"] = t1
- if("gender")
- if(active1)
- if(active1.fields["gender"] == "Male")
- active1.fields["gender"] = "Female"
- else if(active1.fields["gender"] == "Female")
- active1.fields["gender"] = "Other"
- else
- active1.fields["gender"] = "Male"
- if("age")
- if(active1)
- var/t1 = input("Please input age:", "Med. records", active1.fields["age"], null) as num
- if(!canUseMedicalRecordsConsole(usr, t1, a1))
- return
- active1.fields["age"] = t1
- if("species")
- if(active1)
- var/t1 = stripped_input("Please input species name", "Med. records", active1.fields["species"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, a1))
- return
- active1.fields["species"] = t1
- if("mi_dis")
- if(active2)
- var/t1 = stripped_input("Please input minor disabilities list:", "Med. records", active2.fields["mi_dis"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["mi_dis"] = t1
- if("mi_dis_d")
- if(active2)
- var/t1 = stripped_input("Please summarize minor dis.:", "Med. records", active2.fields["mi_dis_d"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["mi_dis_d"] = t1
- if("ma_dis")
- if(active2)
- var/t1 = stripped_input("Please input major disabilities list:", "Med. records", active2.fields["ma_dis"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["ma_dis"] = t1
- if("ma_dis_d")
- if(active2)
- var/t1 = stripped_input("Please summarize major dis.:", "Med. records", active2.fields["ma_dis_d"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["ma_dis_d"] = t1
- if("alg")
- if(active2)
- var/t1 = stripped_input("Please state allergies:", "Med. records", active2.fields["alg"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["alg"] = t1
- if("alg_d")
- if(active2)
- var/t1 = stripped_input("Please summarize allergies:", "Med. records", active2.fields["alg_d"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["alg_d"] = t1
- if("cdi")
- if(active2)
- var/t1 = stripped_input("Please state diseases:", "Med. records", active2.fields["cdi"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["cdi"] = t1
- if("cdi_d")
- if(active2)
- var/t1 = stripped_input("Please summarize diseases:", "Med. records", active2.fields["cdi_d"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["cdi_d"] = t1
- if("notes")
- if(active2)
- var/t1 = stripped_input("Please summarize notes:", "Med. records", active2.fields["notes"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["notes"] = t1
- if("p_stat")
- if(active1)
- temp = "Physical Condition: \n\t*Deceased* \n\t*Unconscious* \n\tActive \n\tPhysically Unfit "
- if("m_stat")
- if(active1)
- temp = "Mental Condition: \n\t*Insane* \n\t*Unstable* \n\t*Watch* \n\tStable "
- if("blood_type")
- if(active2)
- temp = "Blood Type: \n\tA- A+ \n\tB- B+ \n\tAB- AB+ \n\tO- O+ "
- if("b_dna")
- if(active2)
- var/t1 = stripped_input("Please input DNA hash:", "Med. records", active2.fields["b_dna"], null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["b_dna"] = t1
- if("show_photo_front")
- if(active1)
- var/front_photo = active1.get_front_photo()
- if(istype(front_photo, /obj/item/photo))
- var/obj/item/photo/photo = front_photo
- photo.show(usr)
- if("show_photo_side")
- if(active1)
- var/side_photo = active1.get_side_photo()
- if(istype(side_photo, /obj/item/photo))
- var/obj/item/photo/photo = side_photo
- photo.show(usr)
- else
-
- else if(href_list["p_stat"])
- if(active1)
- switch(href_list["p_stat"])
- if("deceased")
- active1.fields["p_stat"] = "*Deceased*"
- if("unconscious")
- active1.fields["p_stat"] = "*Unconscious*"
- if("active")
- active1.fields["p_stat"] = "Active"
- if("unfit")
- active1.fields["p_stat"] = "Physically Unfit"
-
- else if(href_list["m_stat"])
- if(active1)
- switch(href_list["m_stat"])
- if("insane")
- active1.fields["m_stat"] = "*Insane*"
- if("unstable")
- active1.fields["m_stat"] = "*Unstable*"
- if("watch")
- active1.fields["m_stat"] = "*Watch*"
- if("stable")
- active1.fields["m_stat"] = "Stable"
-
-
- else if(href_list["blood_type"])
- if(active2)
- switch(href_list["blood_type"])
- if("an")
- active2.fields["blood_type"] = "A-"
- if("bn")
- active2.fields["blood_type"] = "B-"
- if("abn")
- active2.fields["blood_type"] = "AB-"
- if("on")
- active2.fields["blood_type"] = "O-"
- if("ap")
- active2.fields["blood_type"] = "A+"
- if("bp")
- active2.fields["blood_type"] = "B+"
- if("abp")
- active2.fields["blood_type"] = "AB+"
- if("op")
- active2.fields["blood_type"] = "O+"
-
-
- else if(href_list["del_r"])
- if(active2)
- temp = "Are you sure you wish to delete the record (Medical Portion Only)? \n\tYes \n\tNo "
-
- else if(href_list["del_r2"])
- usr.investigate_log("has deleted the medical records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
- if(active2)
- qdel(active2)
- active2 = null
-
- else if(href_list["d_rec"])
- active1 = find_record("id", href_list["d_rec"], GLOB.data_core.general)
- if(active1)
- active2 = find_record("id", href_list["d_rec"], GLOB.data_core.medical)
- if(!active2)
- active1 = null
- screen = 4
-
- else if(href_list["new"])
- if((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) )))
- var/datum/data/record/R = new /datum/data/record()
- R.fields["name"] = active1.fields["name"]
- R.fields["id"] = active1.fields["id"]
- R.name = text("Medical Record #[]", R.fields["id"])
- R.fields["blood_type"] = "Unknown"
- R.fields["b_dna"] = "Unknown"
- R.fields["mi_dis"] = "None"
- R.fields["mi_dis_d"] = "No minor disabilities have been diagnosed."
- R.fields["ma_dis"] = "None"
- R.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
- R.fields["alg"] = "None"
- R.fields["alg_d"] = "No allergies have been detected in this patient."
- R.fields["cdi"] = "None"
- R.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
- R.fields["notes"] = "No notes."
- GLOB.data_core.medical += R
- active2 = R
- screen = 4
-
- else if(href_list["add_c"])
- if(!(active2 in GLOB.data_core.medical))
- return
- var/a2 = active2
- var/t1 = stripped_multiline_input("Add Comment:", "Med. records", null, null)
- if(!canUseMedicalRecordsConsole(usr, t1, null, a2))
- return
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], [] []", authenticated, rank, station_time_timestamp(), time2text(world.realtime, "MMM DD"), CURRENT_STATION_YEAR, t1)
-
- else if(href_list["del_c"])
- if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
- active2.fields[text("com_[]", href_list["del_c"])] = "Deleted "
-
- else if(href_list["search"])
- var/t1 = stripped_input(usr, "Search String: (Name, DNA, or ID)", "Med. records")
- if(!canUseMedicalRecordsConsole(usr, t1))
- return
- active1 = null
- active2 = null
- t1 = lowertext(t1)
- for(var/datum/data/record/R in GLOB.data_core.medical)
- if((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"])))
- active2 = R
- else
- //Foreach continue //goto(3229)
- if(!( active2 ))
- temp = text("Could not locate record [].", sanitize(t1))
- else
- for(var/datum/data/record/E in GLOB.data_core.general)
- if((E.fields["name"] == active2.fields["name"] || E.fields["id"] == active2.fields["id"]))
- active1 = E
- else
- //Foreach continue //goto(3334)
- screen = 4
-
- else if(href_list["print_p"])
- if(!( printing ))
- printing = 1
- GLOB.data_core.medicalPrintCount++
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, TRUE)
- sleep(3 SECONDS)
- var/obj/item/paper/printed_paper = new /obj/item/paper(loc)
- var/final_paper_text = "Medical Record - (MR-[GLOB.data_core.medicalPrintCount]) "
- if(active1 in GLOB.data_core.general)
- final_paper_text += text("Name: [] ID: [] \nGender: [] \nAge: [] ", active1.fields["name"], active1.fields["id"], active1.fields["gender"], active1.fields["age"])
- final_paper_text += "\nSpecies: [active1.fields["species"]] "
- final_paper_text += text("\nFingerprint: [] \nPhysical Status: [] \nMental Status: [] ", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"])
- //SKYRAT EDIT ADD - RP RECORDS
- if(!(active1.fields["past_records"] == ""))
- final_paper_text += "\nGeneral Records:\n[active1.fields["past_records"]]\n"
- //SKYRAT EDIT ADD END
- else
- final_paper_text += "General Record Lost! "
- if(active2 in GLOB.data_core.medical)
- // final_paper_text += text(" \nMedical Data \nBlood Type: [] \nDNA: [] \n \nMinor Disabilities: [] \nDetails: [] \n \nMajor Disabilities: [] \nDetails: [] \n \nAllergies: [] \nDetails: [] \n \nCurrent Diseases: [] (per disease info placed in log/comment section) \nDetails: [] \n \nImportant Notes: \n\t[] \n \nComments/Log ", active2.fields["blood_type"], active2.fields["b_dna"], active2.fields["mi_dis"], active2.fields["mi_dis_d"], active2.fields["ma_dis"], active2.fields["ma_dis_d"], active2.fields["alg"], active2.fields["alg_d"], active2.fields["cdi"], active2.fields["cdi_d"], active2.fields["notes"]) // SKYRAT EDIT ORIGINAL - WHAT THE FUCK IS THIS CODE WHY IS THIS SO UNREADABLE KILL ME
- //SKYRAT EDIT START - THANK YOU TO AZARAK FOR DOING ALL THE WORK HENK
- final_paper_text += " \nMedical Data "
- if(!(active2.fields["past_records"] == ""))
- final_paper_text += "\nMedical Records:\n[active2.fields["past_records"]] \n"
- final_paper_text += " \nBlood Type: [active2.fields["blood_type"]]"
- final_paper_text += " \nDNA: [active2.fields["b_dna"]]"
- final_paper_text += " \n"
- final_paper_text += " \nMinor Disabilities: [active2.fields["mi_dis"]]"
- final_paper_text += " \nDetails: [active2.fields["mi_dis_d"]]"
- final_paper_text += " \n"
- final_paper_text += " \nMajor Disabilities: [active2.fields["ma_dis"]]"
- final_paper_text += " \nDetails: [active2.fields["ma_dis_d"]]"
- final_paper_text += " \n"
- final_paper_text += " \nAllergies: [active2.fields["alg"]]"
- final_paper_text += " \nDetails: [active2.fields["alg_d"]]"
- final_paper_text += " \n"
- final_paper_text += " \nCurrent Diseases: [active2.fields["cdi"]] (per disease info placed in log/comment section)"
- final_paper_text += " \nDetails: [active2.fields["cdi_d"]]"
- final_paper_text += " \n"
- final_paper_text += " \nImportant Notes:"
- final_paper_text += " \n\t[active2.fields["notes"]]"
- final_paper_text += " \n"
- //SKYRAT EDIT END
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- final_paper_text += text("[] ", active2.fields[text("com_[]", counter)])
- counter++
- printed_paper.name = text("MR-[] '[]'", GLOB.data_core.medicalPrintCount, active1.fields["name"])
- else
- final_paper_text += "Medical Record Lost! "
- printed_paper.name = text("MR-[] '[]'", GLOB.data_core.medicalPrintCount, "Record Lost")
- final_paper_text += ""
- printed_paper.add_raw_text(final_paper_text)
- printed_paper.update_appearance()
- printing = null
-
- add_fingerprint(usr)
- updateUsrDialog()
- return
-
-/obj/machinery/computer/med_data/emp_act(severity)
- . = ..()
- if(!(machine_stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF))
- for(var/datum/data/record/R in GLOB.data_core.medical)
- if(prob(10/severity))
- switch(rand(1,6))
- if(1)
- if(prob(10))
- R.fields["name"] = random_unique_lizard_name(R.fields["gender"],1)
- else
- R.fields["name"] = random_unique_name(R.fields["gender"],1)
- if(2)
- R.fields["gender"] = pick("Male", "Female", "Other")
- if(3)
- R.fields["age"] = rand(AGE_MIN, AGE_MAX)
- if(4)
- R.fields["blood_type"] = random_blood_type()
- if(5)
- R.fields["p_stat"] = pick("*Unconscious*", "Active", "Physically Unfit")
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
-/obj/machinery/computer/med_data/proc/canUseMedicalRecordsConsole(mob/user, message = 1, record1, record2)
- if(user && message && authenticated)
- if(user.canUseTopic(src, !issilicon(user)))
- if(!record1 || record1 == active1)
- if(!record2 || record2 == active2)
- return TRUE
- return FALSE
-
/obj/machinery/computer/med_data/laptop
name = "medical laptop"
desc = "A cheap Nanotrasen medical laptop, it functions as a medical records computer. It's bolted to the table."
@@ -628,3 +18,129 @@
icon_screen = "medlaptop"
icon_keyboard = "laptop_key"
pass_flags = PASSTABLE
+
+/obj/machinery/computer/med_data/attacked_by(obj/item/attacking_item, mob/living/user)
+ . = ..()
+ if(!istype(attacking_item, /obj/item/photo))
+ return
+ insert_new_record(user, attacking_item)
+
+/obj/machinery/computer/med_data/ui_interact(mob/user, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+ ui = SStgui.try_update_ui(user, src, ui)
+ if (!ui)
+ create_character_preview_view(user)
+ ui = new(user, src, "MedicalRecords")
+ ui.set_autoupdate(FALSE)
+ ui.open()
+
+/obj/machinery/computer/med_data/ui_data(mob/user)
+ var/list/data = list()
+
+ var/has_access = authenticated && isliving(user)
+ data["authenticated"] = authenticated
+ if(!has_access)
+ return data
+
+ data["assigned_view"] = "preview_[user.ckey]_[REF(src)]_records"
+
+ var/list/records = list()
+ for(var/datum/record/crew/target in GLOB.manifest.general)
+ var/list/notes = list()
+ for(var/datum/medical_note/note in target.medical_notes)
+ notes += list(list(
+ author = note.author,
+ content = note.content,
+ note_ref = REF(note),
+ time = note.time,
+ ))
+
+ records += list(list(
+ age = target.age,
+ blood_type = target.blood_type,
+ crew_ref = REF(target),
+ dna = target.dna_string,
+ gender = target.gender,
+ major_disabilities = target.major_disabilities_desc,
+ minor_disabilities = target.minor_disabilities_desc,
+ name = target.name,
+ notes = notes,
+ quirk_notes = target.quirk_notes,
+ rank = target.rank,
+ species = target.species,
+ // SKYRAT EDIT ADDITION START - Expanded records!
+ past_medical_records = target.past_medical_records,
+ past_general_records = target.past_general_records,
+ // SKYRAT EDIT END
+ ))
+
+ data["records"] = records
+
+ return data
+
+/obj/machinery/computer/med_data/ui_static_data(mob/user)
+ var/list/data = list()
+ data["min_age"] = AGE_MIN
+ data["max_age"] = AGE_MAX
+ return data
+
+/obj/machinery/computer/med_data/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ var/datum/record/crew/target
+ if(params["crew_ref"])
+ target = locate(params["crew_ref"]) in GLOB.manifest.general
+ if(!target)
+ return FALSE
+
+ switch(action)
+ if("add_note")
+ if(!params["content"])
+ return FALSE
+ var/content = trim(params["content"], MAX_MESSAGE_LEN)
+
+ var/datum/medical_note/new_note = new(usr.name, content)
+ while(length(target.medical_notes) > 2)
+ target.medical_notes.Cut(1, 2)
+
+ target.medical_notes += new_note
+
+ return TRUE
+
+ if("delete_note")
+ var/datum/medical_note/old_note = locate(params["note_ref"]) in target.medical_notes
+ if(!old_note)
+ return FALSE
+
+ target.medical_notes -= old_note
+ qdel(old_note)
+
+ return TRUE
+
+ return FALSE
+
+/// Deletes medical information from a record.
+/obj/machinery/computer/med_data/expunge_record_info(datum/record/crew/target)
+ if(!target)
+ return FALSE
+
+ target.age = 18
+ target.blood_type = pick(list("A+", "A-", "B+", "B-", "O+", "O-", "AB+", "AB-"))
+ target.dna_string = "Unknown"
+ target.gender = "Unknown"
+ target.major_disabilities = ""
+ target.major_disabilities_desc = ""
+ target.medical_notes.Cut()
+ target.minor_disabilities = ""
+ target.minor_disabilities_desc = ""
+ target.name = "Unknown"
+ target.quirk_notes = ""
+ target.rank = "Unknown"
+ target.species = "Unknown"
+ target.trim = "Unknown"
+
+ return TRUE
diff --git a/code/game/machinery/computer/prisoner/gulag_teleporter.dm b/code/game/machinery/computer/prisoner/gulag_teleporter.dm
index acdb74f9442..45124eefeee 100644
--- a/code/game/machinery/computer/prisoner/gulag_teleporter.dm
+++ b/code/game/machinery/computer/prisoner/gulag_teleporter.dm
@@ -12,7 +12,7 @@
var/obj/machinery/gulag_teleporter/teleporter = null
var/obj/structure/gulag_beacon/beacon = null
var/mob/living/carbon/human/prisoner = null
- var/datum/data/record/temporary_record = null
+ var/datum/record/crew/temporary_record = null
/obj/machinery/computer/prisoner/gulag_teleporter_computer/Initialize(mapload)
@@ -37,12 +37,11 @@
prisoner_list["name"] = prisoner.real_name
if(contained_id)
can_teleport = TRUE
- if(!isnull(GLOB.data_core.general))
- for(var/r in GLOB.data_core.security)
- var/datum/data/record/R = r
- if(R.fields["name"] == prisoner_list["name"])
- temporary_record = R
- prisoner_list["crimstat"] = temporary_record.fields["criminal"]
+ if(!isnull(GLOB.manifest.general))
+ for(var/datum/record/crew/record as anything in GLOB.manifest.general)
+ if(record.name == prisoner_list["name"])
+ temporary_record = record
+ prisoner_list["crimstat"] = temporary_record.wanted_status
data["prisoner"] = prisoner_list
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 9da287841a2..fe05cf2b806 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -1,3 +1,8 @@
+#define COMP_SECURITY_ARREST_AMOUNT_TO_FLAG 10
+#define PRINTOUT_MISSING "Missing"
+#define PRINTOUT_RAPSHEET "Rapsheet"
+#define PRINTOUT_WANTED "Wanted"
+
/obj/machinery/computer/secure_data//TODO:SANITY
name = "security records console"
desc = "Used to view and edit personnel's security records."
@@ -6,18 +11,24 @@
req_one_access = list(ACCESS_SECURITY, ACCESS_HOP)
circuit = /obj/item/circuitboard/computer/secure_data
light_color = COLOR_SOFT_RED
- var/rank = null
- var/screen = null
- var/datum/data/record/active1 = null
- var/datum/data/record/active2 = null
- var/temp = null
- var/printing = null
- var/can_change_id = 0
- var/list/Perp
- var/tempname = null
- //Sorting Variables
- var/sortBy = "name"
- var/order = 1 // -1 = Descending - 1 = Ascending
+ /// The current state of the printer
+ var/printing = FALSE
+
+/obj/machinery/computer/secure_data/syndie
+ icon_keyboard = "syndie_key"
+ req_one_access = list(ACCESS_SYNDICATE)
+
+/obj/machinery/computer/secure_data/laptop
+ name = "security laptop"
+ desc = "A cheap Nanotrasen security laptop, it functions as a security records console. It's bolted to the table."
+ icon_state = "laptop"
+ icon_screen = "seclaptop"
+ icon_keyboard = "laptop_key"
+ pass_flags = PASSTABLE
+
+/obj/machinery/computer/secure_data/laptop/syndie
+ desc = "A cheap, jailbroken security laptop. It functions as a security records console. It's bolted to the table."
+ req_one_access = list(ACCESS_SYNDICATE)
/obj/machinery/computer/secure_data/Initialize(mapload, obj/item/circuitboard/C)
. = ..()
@@ -26,14 +37,285 @@
/obj/item/circuit_component/arrest_console_arrest,
))
-#define COMP_STATE_ARREST "*Arrest*"
-#define COMP_STATE_PRISONER "Incarcerated"
-#define COMP_STATE_SUSPECTED "Suspected"
-#define COMP_STATE_PAROL "Paroled"
-#define COMP_STATE_DISCHARGED "Discharged"
-#define COMP_STATE_NONE "None"
-#define COMP_SECURITY_ARREST_AMOUNT_TO_FLAG 10
+/obj/machinery/computer/secure_data/emp_act(severity)
+ . = ..()
+ if(machine_stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_SELF)
+ return
+
+ for(var/datum/record/crew/target in GLOB.manifest.general)
+ if(prob(10/severity))
+ switch(rand(1,5))
+ if(1)
+ if(prob(10))
+ target.name = "[pick(lizard_name(MALE),lizard_name(FEMALE))]"
+ else
+ target.name = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]"
+ if(2)
+ target.gender = pick("Male", "Female", "Other")
+ if(3)
+ target.age = rand(5, 85)
+ if(4)
+ target.wanted_status = pick(WANTED_STATUSES())
+ if(5)
+ target.species = pick(get_selectable_species())
+ continue
+
+ else if(prob(1))
+ qdel(target)
+ continue
+
+/obj/machinery/computer/secure_data/attacked_by(obj/item/attacking_item, mob/living/user)
+ . = ..()
+ if(!istype(attacking_item, /obj/item/photo))
+ return
+ insert_new_record(user, attacking_item)
+
+/obj/machinery/computer/secure_data/ui_interact(mob/user, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ character_preview_view = create_character_preview_view(user)
+ ui = new(user, src, "SecurityRecords")
+ ui.set_autoupdate(FALSE)
+ ui.open()
+
+/obj/machinery/computer/secure_data/ui_data(mob/user)
+ var/list/data = list()
+
+ var/has_access = authenticated && isliving(user)
+ data["authenticated"] = has_access
+ if(!has_access)
+ return data
+
+ data["assigned_view"] = "preview_[user.ckey]_[REF(src)]_records"
+ data["available_statuses"] = WANTED_STATUSES()
+
+ var/list/records = list()
+ for(var/datum/record/crew/target in GLOB.manifest.general)
+ var/list/citations = list()
+ for(var/datum/crime/citation/warrant in target.citations)
+ citations += list(list(
+ author = warrant.author,
+ crime_ref = REF(warrant),
+ details = warrant.details,
+ fine = warrant.fine,
+ name = warrant.name,
+ paid = warrant.paid,
+ time = warrant.time,
+ ))
+
+ var/list/crimes = list()
+ for(var/datum/crime/crime in target.crimes)
+ crimes += list(list(
+ author = crime.author,
+ crime_ref = REF(crime),
+ details = crime.details,
+ name = crime.name,
+ time = crime.time,
+ ))
+
+ records += list(list(
+ age = target.age,
+ citations = citations,
+ crew_ref = REF(target),
+ crimes = crimes,
+ fingerprint = target.fingerprint,
+ gender = target.gender,
+ name = target.name,
+ note = target.security_note,
+ rank = target.rank,
+ species = target.species,
+ wanted_status = target.wanted_status,
+ // SKYRAT EDIT ADDITION - RP Records
+ past_general_records = target.past_general_records,
+ past_security_records = target.past_security_records,
+ // SKYRAT EDIT END
+ ))
+
+ data["records"] = records
+
+ return data
+
+/obj/machinery/computer/secure_data/ui_static_data(mob/user)
+ var/list/data = list()
+ data["min_age"] = AGE_MIN
+ data["max_age"] = AGE_MAX
+ return data
+
+/obj/machinery/computer/secure_data/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return
+
+ var/datum/record/crew/target
+ if(params["crew_ref"])
+ target = locate(params["crew_ref"]) in GLOB.manifest.general
+ if(!target)
+ return FALSE
+
+ switch(action)
+ if("add_crime")
+ add_crime(usr, target, params)
+ return TRUE
+
+ if("delete_crime")
+ delete_crime(target, params)
+ return TRUE
+
+ if("print_record")
+ print_record(usr, target, params)
+ return TRUE
+
+ if("set_note")
+ var/note = params["note"]
+ target.security_note = trim(note, MAX_MESSAGE_LEN)
+ return TRUE
+
+ if("set_wanted")
+ var/wanted_status = params["status"]
+ if(!wanted_status || !(wanted_status in WANTED_STATUSES()))
+ return FALSE
+
+ investigate_log("[target.name] has been set from [target.wanted_status] to [wanted_status] by [key_name(usr)].", INVESTIGATE_RECORDS)
+ target.wanted_status = wanted_status
+
+ return TRUE
+
+ return FALSE
+
+/// Handles adding a crime to a particular record.
+/obj/machinery/computer/secure_data/proc/add_crime(mob/user, datum/record/crew/target, list/params)
+ var/input_name = trim(params["name"], 24)
+ if(!input_name)
+ to_chat(usr, span_warning("You must enter a name for the crime."))
+ playsound(src, 'sound/machines/terminal_error.ogg', 100, TRUE)
+ return FALSE
+
+ var/max = CONFIG_GET(number/maxfine)
+ if(params["fine"] > max)
+ to_chat(usr, span_warning("The maximum fine is [max] credits."))
+ playsound(src, 'sound/machines/terminal_error.ogg', 100, TRUE)
+ return FALSE
+
+ var/input_details
+ if(params["details"])
+ input_details = trim(params["details"], MAX_MESSAGE_LEN)
+
+ if(params["fine"] == 0)
+ var/datum/crime/new_crime = new(name = input_name, details = input_details, author = usr)
+ target.crimes += new_crime
+ investigate_log("New Crime: [input_name] | Added to [target.name] by [key_name(user)]. Their previous status was [target.wanted_status]", INVESTIGATE_RECORDS)
+ target.wanted_status = WANTED_ARREST
+ return TRUE
+
+ var/datum/crime/citation/new_citation = new(name = input_name, details = input_details, author = usr, fine = params["fine"])
+
+ target.citations += new_citation
+ new_citation.alert_owner(user, src, target.name, "You have been issued a [params["fine"]]cr citation for [input_name]. Fines are payable at Security.")
+ investigate_log("New Citation: [input_name] Fine: [params["fine"]] | Added to [target.name] by [key_name(user)]", INVESTIGATE_RECORDS)
+ SSblackbox.ReportCitation(REF(new_citation), user.ckey, user.real_name, target.name, input_name, params["fine"])
+
+ return TRUE
+
+/// Deletes a crime or citation from the chosen record.
+/obj/machinery/computer/secure_data/proc/delete_crime(datum/record/crew/target, list/params)
+ var/datum/crime/incident = locate(params["crime_ref"]) in target.crimes
+ if(incident)
+ target.crimes -= incident
+ qdel(incident)
+ return TRUE
+
+ var/datum/crime/citation/warrant = locate(params["crime_ref"]) in target.citations
+ if(warrant)
+ target.citations -= warrant
+ qdel(warrant)
+ return TRUE
+
+ return FALSE
+
+/// Deletes security information from a record.
+/obj/machinery/computer/secure_data/expunge_record_info(datum/record/crew/target)
+ target.age = 18
+ target.citations.Cut()
+ target.crimes.Cut()
+ target.fingerprint = "Unknown"
+ target.gender = "Unknown"
+ target.name = "Unknown"
+ target.rank = "Unknown"
+ target.security_note = "None"
+ target.species = "Unknown"
+ target.trim = "Unknown"
+ target.wanted_status = WANTED_NONE
+
+ return TRUE
+
+/// Finishes printing, resets the printer.
+/obj/machinery/computer/secure_data/proc/print_finish(obj/item/printable)
+ printing = FALSE
+ playsound(src, 'sound/machines/terminal_eject.ogg', 100, TRUE)
+ printable.forceMove(loc)
+
+ return TRUE
+
+/// Handles printing records via UI. Takes the params from UI_act.
+/obj/machinery/computer/secure_data/proc/print_record(mob/user, datum/record/crew/target, list/params)
+ if(printing)
+ balloon_alert(usr, "printer busy")
+ playsound(src, 'sound/machines/terminal_error.ogg', 100, TRUE)
+ return FALSE
+
+ printing = TRUE
+ balloon_alert(user, "printing")
+ playsound(src, 'sound/machines/printer.ogg', 100, TRUE)
+
+ var/obj/item/printable
+ var/input_alias = trim(params["alias"], MAX_NAME_LEN) || target.name
+ var/input_description = trim(params["desc"], MAX_BROADCAST_LEN) || "No further details."
+ var/input_header = trim(params["head"], 8) || capitalize(params["type"])
+
+ switch(params["type"])
+ if("missing")
+ var/obj/item/photo/mugshot = target.get_front_photo()
+ var/obj/item/poster/wanted/missing/missing_poster = new(null, mugshot.picture.picture_image, input_alias, input_description, input_header)
+
+ printable = missing_poster
+
+ if("wanted")
+ var/list/crimes = target.crimes
+ if(!length(crimes))
+ balloon_alert(user, "no crimes")
+ return FALSE
+
+ input_description += "\n\nWANTED FOR: "
+ for(var/datum/crime/incident in crimes)
+ input_description += "\n [incident.name]\n"
+ input_description += "Details: [incident.details]\n"
+
+ var/obj/item/photo/mugshot = target.get_front_photo()
+ var/obj/item/poster/wanted/wanted_poster = new(null, mugshot.picture.picture_image, input_alias, input_description, input_header)
+
+ printable = wanted_poster
+
+ if("rapsheet")
+ var/list/crimes = target.crimes
+ if(!length(crimes))
+ balloon_alert(user, "no crimes")
+ return FALSE
+
+ var/obj/item/paper/rapsheet = target.get_rapsheet(input_alias, input_header, input_description)
+ printable = rapsheet
+
+ addtimer(CALLBACK(src, PROC_REF(print_finish), printable), 2 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE)
+
+ return TRUE
+
+
+/**
+ * Security circuit component
+ */
/obj/item/circuit_component/arrest_console_data
display_name = "Security Records Data"
desc = "Outputs the security records data, where it can then be filtered with a Select Query component"
@@ -73,35 +355,30 @@
"fingerprint",
))
-
/obj/item/circuit_component/arrest_console_data/input_received(datum/port/input/port)
if(!attached_console || !attached_console.authenticated)
on_fail.set_output(COMPONENT_SIGNAL)
return
- if(isnull(GLOB.data_core.general))
+ if(isnull(GLOB.manifest.general))
on_fail.set_output(COMPONENT_SIGNAL)
return
var/list/new_table = list()
- for(var/datum/data/record/player_record as anything in GLOB.data_core.general)
+ for(var/datum/record/crew/player_record as anything in GLOB.manifest.general)
var/list/entry = list()
- var/datum/data/record/player_security_record = find_record("id", player_record.fields["id"], GLOB.data_core.security)
- if(player_security_record)
- entry["arrest_status"] = player_security_record.fields["criminal"]
- entry["security_record"] = player_security_record
- entry["name"] = player_record.fields["name"]
- entry["id"] = player_record.fields["id"]
- entry["rank"] = player_record.fields["rank"]
- entry["gender"] = player_record.fields["gender"]
- entry["age"] = player_record.fields["age"]
- entry["species"] = player_record.fields["species"]
- entry["fingerprint"] = player_record.fields["fingerprint"]
+ entry["age"] = player_record.age
+ entry["arrest_status"] = player_record.wanted_status
+ entry["fingerprint"] = player_record.fingerprint
+ entry["gender"] = player_record.gender
+ entry["name"] = player_record.name
+ entry["rank"] = player_record.rank
+ entry["record"] = REF(player_record)
+ entry["species"] = player_record.species
new_table += list(entry)
records.set_output(new_table)
-
/obj/item/circuit_component/arrest_console_arrest
display_name = "Security Records Set Status"
desc = "Receives a table to use to set people's arrest status. Table should be from the security records data component. If New Status port isn't set, the status will be decided by the options."
@@ -131,15 +408,10 @@
return ..()
/obj/item/circuit_component/arrest_console_arrest/populate_options()
- var/static/list/component_options = list(
- COMP_STATE_ARREST,
- COMP_STATE_PRISONER,
- COMP_STATE_SUSPECTED,
- COMP_STATE_PAROL,
- COMP_STATE_DISCHARGED,
- COMP_STATE_NONE,
- )
- new_status = add_option_port("Arrest Options", component_options)
+ if(!attached_console)
+ return
+ var/list/available_statuses = WANTED_STATUSES()
+ new_status = add_option_port("Arrest Options", available_statuses)
/obj/item/circuit_component/arrest_console_arrest/populate_ports()
targets = add_input_port("Targets", PORT_TYPE_TABLE)
@@ -162,14 +434,14 @@
var/successful_set = 0
var/list/names_of_entries = list()
for(var/list/target in target_table)
- var/datum/data/record/sec_record = target["security_record"]
+ var/datum/record/crew/sec_record = target["security_record"]
if(!sec_record)
continue
- if(sec_record.fields["criminal"] != status_to_set)
+ if(sec_record.wanted_status != status_to_set)
successful_set++
names_of_entries += target["name"]
- sec_record.fields["criminal"] = status_to_set
+ sec_record.wanted_status = status_to_set
if(successful_set > 0)
@@ -179,870 +451,7 @@
for(var/mob/living/carbon/human/human as anything in GLOB.human_list)
human.sec_hud_set_security_status()
-#undef COMP_STATE_ARREST
-#undef COMP_STATE_PRISONER
-#undef COMP_STATE_SUSPECTED
-#undef COMP_STATE_PAROL
-#undef COMP_STATE_DISCHARGED
-#undef COMP_STATE_NONE
#undef COMP_SECURITY_ARREST_AMOUNT_TO_FLAG
-
-/obj/machinery/computer/secure_data/syndie
- icon_keyboard = "syndie_key"
- req_one_access = list(ACCESS_SYNDICATE)
-
-/obj/machinery/computer/secure_data/laptop
- name = "security laptop"
- desc = "A cheap Nanotrasen security laptop, it functions as a security records console. It's bolted to the table."
- icon_state = "laptop"
- icon_screen = "seclaptop"
- icon_keyboard = "laptop_key"
- pass_flags = PASSTABLE
-
-/obj/machinery/computer/secure_data/laptop/syndie
- desc = "A cheap, jailbroken security laptop. It functions as a security records console. It's bolted to the table."
- req_one_access = list(ACCESS_SYNDICATE)
-
-//Someone needs to break down the dat += into chunks instead of long ass lines.
-/obj/machinery/computer/secure_data/ui_interact(mob/user)
- . = ..()
- /* SKYRAT EDIT REMOVAL - AESTHETICS
- if(isliving(user))
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
- */
- if(src.z > 6)
- to_chat(user, "[span_boldannounce("Unable to establish a connection")]: \black You're too far away from the station!")
- return
- var/dat
-
- if(temp)
- dat = "[temp] Clear Screen "
- else
- dat = ""
- if(authenticated)
- switch(screen)
- if(1)
-
- //body tag start + onload and onkeypress (onkeyup) javascript event calls
- dat += ""
- //search bar javascript
- dat += {"
-
-
-
-
-
-
-
- "}
- dat += {"
-"}
- dat += "New Record "
- //search bar
- dat += {"
-
- "}
- dat += {"
-
-
-
-
-
-
-Name
-ID
-Rank
-Fingerprints
-Criminal Status
- "}
- if(!isnull(GLOB.data_core.general))
- for(var/datum/data/record/R in sort_record(GLOB.data_core.general, sortBy, order))
- var/crimstat = ""
- for(var/datum/data/record/E in GLOB.data_core.security)
- if((E.fields["name"] == R.fields["name"]) && (E.fields["id"] == R.fields["id"]))
- crimstat = E.fields["criminal"]
- var/background
- switch(crimstat)
- if("*Arrest*")
- background = "'background-color:#990000;'"
- if("Incarcerated")
- background = "'background-color:#CD6500;'"
- if("Suspected")
- background = "'background-color:#CD6500;'"
- if("Paroled")
- background = "'background-color:#CD6500;'"
- if("Discharged")
- background = "'background-color:#006699;'"
- if("None")
- background = "'background-color:#4F7529;'"
- if("")
- background = "''" //"'background-color:#FFFFFF;'"
- crimstat = "No Record."
- dat += ""
- dat += text("[] ", R.fields["name"], R.fields["id"], R.fields["rank"], R.fields["fingerprint"], R.fields["name"])
- dat += text("[] ", R.fields["id"])
- dat += text("[] ", R.fields["rank"])
- dat += text("[] ", R.fields["fingerprint"])
- dat += text("[] ", crimstat)
- dat += {"
-
-
- "}
- dat += "Record Maintenance "
- dat += "{Log Out} "
- if(2)
- dat += "Records Maintenance "
- dat += "Delete All Records Back "
- if(3)
- dat += "Security Record "
- if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1))
- var/front_photo = active1.get_front_photo()
- if(istype(front_photo, /obj/item/photo))
- var/obj/item/photo/photo_front = front_photo
- user << browse_rsc(photo_front.picture.picture_image, "photo_front")
- var/side_photo = active1.get_side_photo()
- if(istype(side_photo, /obj/item/photo))
- var/obj/item/photo/photo_side = side_photo
- user << browse_rsc(photo_side.picture.picture_image, "photo_side")
- dat += {""} // SKYRAT EDIT - TEXT AMENDED, "GENERAL RECORDS" - RP RECORDS
- else
- dat += " General Record Lost! "
- if((istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2)))
- dat += "Security Data "
- dat += " Security Records: View " //SKYRAT EDIT ADD - RP RECORDS
- dat += " Criminal Status: [active2.fields["criminal"]] "
- dat += " Citations: Add New "
-
- dat +={"
-
- Crime
- Fine
- Author
- Time Added
- Amount Due
- Del
- "}
- for(var/datum/data/crime/c in active2.fields["citation"])
- var/owed = c.fine - c.paid
- dat += {"[c.crimeName]
- [c.fine] cr [c.author]
- [c.time] "}
- if(owed > 0)
- dat += "[owed] cr \[Pay\] "
- else
- dat += "All Paid Off "
- dat += {"
- \[X\]
-
- "}
- dat += "
"
-
- dat += " Crimes: Add New "
-
-
- dat +={"
-
- Crime
- Details
- Author
- Time Added
- Del
- "}
- for(var/datum/data/crime/c in active2.fields["crim"])
- dat += "[c.crimeName] "
- if(!c.crimeDetails)
- dat += "\[+\] "
- else
- dat += "[c.crimeDetails] "
- dat += "[c.author] "
- dat += "[c.time] "
- dat += "\[X\] "
- dat += " "
- dat += "
"
-
- dat += " \nImportant Notes: \n\t [active2.fields["notes"]] "
- dat += "Comments/Log "
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- dat += (active2.fields[text("com_[]", counter)] + " ")
- if(active2.fields[text("com_[]", counter)] != "Deleted ")
- dat += text("Delete Entry ", counter)
- counter++
- dat += "Add Entry "
- dat += "Delete Record (Security Only) "
- else
- dat += "Security Record Lost! "
- dat += "New Security Record "
- dat += "Delete Record (ALL) Print Record Print Wanted Poster Print Missing Persons Poster Back "
- dat += "{Log Out} "
- else
- else
- dat += "{Log In} "
- var/datum/browser/popup = new(user, "secure_rec", "Security Records Console", 600, 400)
- popup.set_content(dat)
- popup.open()
- return
-
-/*Revised /N
-I can't be bothered to look more of the actual code outside of switch but that probably needs revising too.
-What a mess.*/
-/obj/machinery/computer/secure_data/Topic(href, href_list)
- . = ..()
- if(.)
- return .
- if(!( GLOB.data_core.general.Find(active1) ))
- active1 = null
- if(!( GLOB.data_core.security.Find(active2) ))
- active2 = null
- if(!authenticated && href_list["choice"] != "Log In") // logging in is the only action you can do if not logged in
- return
- if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || isAdminGhostAI(usr))
- usr.set_machine(src)
- switch(href_list["choice"])
- //SKYRAT EDIT ADD - RP RECORDS
- if("View Past Security")
- if(istype(active2, /datum/data/record))
- temp = "Security Records: "
- temp += ""
- temp += "[active2.fields["past_records"]] "
- temp += " "
-
- if("View Past General")
- if(istype(active1, /datum/data/record))
- temp = "General Records: "
- temp += ""
- temp += "[active1.fields["past_records"]] "
- temp += " "
- //SKYRAT EDIT ADD END
-// SORTING!
- if("Sorting")
- // Reverse the order if clicked twice
- if(sortBy == href_list["sort"])
- if(order == 1)
- order = -1
- else
- order = 1
- else
- // New sorting order!
- sortBy = href_list["sort"]
- order = initial(order)
-//BASIC FUNCTIONS
- if("Clear Screen")
- temp = null
-
- if("Return")
- screen = 1
- active1 = null
- active2 = null
-
- if("Log Out")
- authenticated = null
- screen = null
- active1 = null
- active2 = null
- playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
-
- if("Log In")
- var/obj/item/card/id/I
- if(isliving(usr))
- var/mob/living/L = usr
- I = L.get_idcard(TRUE)
- if(issilicon(usr))
- active1 = null
- active2 = null
- authenticated = usr.name
- rank = "AI"
- screen = 1
- else if(isAdminGhostAI(usr))
- active1 = null
- active2 = null
- authenticated = usr.client.holder.admin_signature
- rank = "Central Command"
- screen = 1
- else if(I && check_access(I))
- active1 = null
- active2 = null
- authenticated = (I.registered_name ? I.registered_name : "Unknown")
- rank = I.assignment
- screen = 1
- else
- to_chat(usr, span_danger("Unauthorized Access."))
- playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
-
-//RECORD FUNCTIONS
- if("Record Maintenance")
- screen = 2
- active1 = null
- active2 = null
-
- if("Browse Record")
- var/datum/data/record/R = locate(href_list["d_rec"]) in GLOB.data_core.general
- if(!R)
- temp = "Record Not Found!"
- else
- active1 = active2 = R
- for(var/datum/data/record/E in GLOB.data_core.security)
- if((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- active2 = E
- screen = 3
-
- if("Pay")
- for(var/datum/data/crime/p in active2.fields["citation"])
- if(p.dataId == text2num(href_list["cdataid"]))
- var/obj/item/holochip/C = usr.is_holding_item_of_type(/obj/item/holochip)
- if(C && istype(C))
- var/pay = C.get_item_credit_value()
- if(!pay)
- to_chat(usr, span_warning("[C] doesn't seem to be worth anything!"))
- else
- var/diff = p.fine - p.paid
- GLOB.data_core.payCitation(active2.fields["id"], text2num(href_list["cdataid"]), pay)
- to_chat(usr, span_notice("You have paid [pay] credit\s towards your fine."))
- if (pay == diff || pay > diff || pay >= diff)
- investigate_log("Citation Paid off: [p.crimeName] Fine: [p.fine] | Paid off by [key_name(usr)]", INVESTIGATE_RECORDS)
- to_chat(usr, span_notice("The fine has been paid in full."))
- SSblackbox.ReportCitation(text2num(href_list["cdataid"]),"","","","", 0, pay)
- qdel(C)
- playsound(src, SFX_TERMINAL_TYPE, 25, FALSE)
- else
- to_chat(usr, span_warning("Fines can only be paid with holochips!"))
-
- if("Print Record")
- if(!( printing ))
- printing = TRUE
- playsound(src, 'sound/items/poster_being_created.ogg', 100, TRUE)
- sleep(3 SECONDS)
- print_security_record(active1, active2, loc)
- printing = FALSE
- if("Print Poster")
- if(!( printing ))
- var/wanted_name = tgui_input_text(usr, "Enter an alias for the criminal", "Print Wanted Poster", active1.fields["name"])
- if(wanted_name)
- var/default_description = "A poster declaring [wanted_name] to be a dangerous individual, wanted by Nanotrasen. Report any sightings to security immediately."
- var/list/crimes = active2.fields["crim"]
- if(length(crimes))
- default_description += "\n[wanted_name] is wanted for the following crimes:\n"
- for(var/datum/data/crime/c in active2.fields["crim"])
- default_description += "\n[c.crimeName]\n"
- default_description += "[c.crimeDetails]\n"
-
- var/headerText = tgui_input_text(usr, "Enter a poster heading", "Print Wanted Poster", "WANTED", 7)
-
- var/info = tgui_input_text(usr, "Input a description for the poster", "Print Wanted Poster", default_description)
- if(info)
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, TRUE)
- printing = 1
- sleep(3 SECONDS)
- if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))//make sure the record still exists.
- var/obj/item/photo/photo = active1.get_front_photo()
- new /obj/item/poster/wanted(loc, photo.picture.picture_image, wanted_name, info, headerText)
- printing = 0
- if("Print Missing")
- if(!( printing ))
- var/missing_name = tgui_input_text(usr, "Enter an alias for the missing person", "Print Missing Persons Poster", active1.fields["name"])
- if(missing_name)
- var/default_description = "A poster declaring [missing_name] to be a missing individual, missed by Nanotrasen. Report any sightings to security immediately."
-
- var/headerText = tgui_input_text(usr, "Enter a poster heading", "Print Missing Persons Poster", "MISSING", 7)
-
- var/info = tgui_input_text(usr, "Input a description for the poster", "Print Missing Persons Poster", default_description)
- if(info)
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, TRUE)
- printing = 1
- sleep(3 SECONDS)
- if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))//make sure the record still exists.
- var/obj/item/photo/photo = active1.get_front_photo()
- new /obj/item/poster/wanted/missing(loc, photo.picture.picture_image, missing_name, info, headerText)
- printing = 0
-
-//RECORD DELETE
- if("Delete All Records")
- temp = ""
- temp += "Are you sure you wish to delete all Security records? "
- temp += "Yes "
- temp += "No "
-
- if("Purge All Records")
- investigate_log("[key_name(usr)] has purged all the security records.", INVESTIGATE_RECORDS)
- for(var/datum/data/record/R in GLOB.data_core.security)
- qdel(R)
- GLOB.data_core.security.Cut()
- temp = "All Security records deleted."
-
- if("Add Entry")
- if(!( istype(active2, /datum/data/record) ))
- return
- var/a2 = active2
- var/t1 = tgui_input_text(usr, "Add a comment", "Security Records")
- if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], [] []", src.authenticated, src.rank, station_time_timestamp(), time2text(world.realtime, "MMM DD"), CURRENT_STATION_YEAR, t1)
-
- if("Delete Record (ALL)")
- if(active1)
- temp = "Are you sure you wish to delete the record (ALL)? "
- temp += "Yes "
- temp += "No "
-
- if("Delete Record (Security)")
- if(active2)
- temp = "Are you sure you wish to delete the record (Security Portion Only)? "
- temp += "Yes "
- temp += "No "
-
- if("Delete Entry")
- if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
- active2.fields[text("com_[]", href_list["del_c"])] = "Deleted "
-//RECORD CREATE
- if("New Record (Security)")
- if((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) )))
- var/datum/data/record/R = new /datum/data/record()
- R.fields["name"] = active1.fields["name"]
- R.fields["id"] = active1.fields["id"]
- R.name = text("Security Record #[]", R.fields["id"])
- R.fields["criminal"] = "None"
- R.fields["crim"] = list()
- R.fields["notes"] = "No notes."
- GLOB.data_core.security += R
- active2 = R
- screen = 3
-
- if("New Record (General)")
- //General Record
- var/datum/data/record/G = new /datum/data/record()
- G.fields["name"] = "New Record"
- G.fields["id"] = "[num2hex(rand(1, 1.6777215E7), 6)]"
- G.fields["rank"] = "Unassigned"
- G.fields["trim"] = "Unassigned"
- G.fields["initial_rank"] = "Unassigned"
- G.fields["gender"] = "Male"
- G.fields["age"] = "Unknown"
- G.fields["species"] = "Human"
- G.fields["photo_front"] = new /icon()
- G.fields["photo_side"] = new /icon()
- G.fields["fingerprint"] = "?????"
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- GLOB.data_core.general += G
- active1 = G
-
- //Security Record
- var/datum/data/record/R = new /datum/data/record()
- R.fields["name"] = active1.fields["name"]
- R.fields["id"] = active1.fields["id"]
- R.name = text("Security Record #[]", R.fields["id"])
- R.fields["criminal"] = "None"
- R.fields["crim"] = list()
- R.fields["notes"] = "No notes."
- GLOB.data_core.security += R
- active2 = R
-
- //Medical Record
- var/datum/data/record/M = new /datum/data/record()
- M.fields["id"] = active1.fields["id"]
- M.fields["name"] = active1.fields["name"]
- M.fields["blood_type"] = "?"
- M.fields["b_dna"] = "?????"
- M.fields["mi_dis"] = "None"
- M.fields["mi_dis_d"] = "No minor disabilities have been declared."
- M.fields["ma_dis"] = "None"
- M.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
- M.fields["alg"] = "None"
- M.fields["alg_d"] = "No allergies have been detected in this patient."
- M.fields["cdi"] = "None"
- M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
- M.fields["notes"] = "No notes."
- GLOB.data_core.medical += M
-
-
-
-//FIELD FUNCTIONS
- if("Edit Field")
- var/a1 = active1
- var/a2 = active2
-
- switch(href_list["field"])
- if("name")
- if(istype(active1, /datum/data/record) || istype(active2, /datum/data/record))
- var/t1 = tgui_input_text(usr, "Input a name", "Security Records", active1.fields["name"])
- if(!canUseSecurityRecordsConsole(usr, t1, a1))
- return
- if(istype(active1, /datum/data/record))
- active1.fields["name"] = t1
- if(istype(active2, /datum/data/record))
- active2.fields["name"] = t1
- if("id")
- if(istype(active2, /datum/data/record) || istype(active1, /datum/data/record))
- var/t1 = tgui_input_text(usr, "Input an id", "Security Records", active1.fields["id"])
- if(!canUseSecurityRecordsConsole(usr, t1, a1))
- return
- if(istype(active1, /datum/data/record))
- active1.fields["id"] = t1
- if(istype(active2, /datum/data/record))
- active2.fields["id"] = t1
- if("fingerprint")
- if(istype(active1, /datum/data/record))
- var/t1 = tgui_input_text(usr, "Input a fingerprint hash", "Security Records", active1.fields["fingerprint"])
- if(!canUseSecurityRecordsConsole(usr, t1, a1))
- return
- active1.fields["fingerprint"] = t1
- if("gender")
- if(istype(active1, /datum/data/record))
- if(active1.fields["gender"] == "Male")
- active1.fields["gender"] = "Female"
- else if(active1.fields["gender"] == "Female")
- active1.fields["gender"] = "Other"
- else
- active1.fields["gender"] = "Male"
- if("age")
- if(istype(active1, /datum/data/record))
- var/t1 = tgui_input_number(usr, "Input age", "Security records", active1.fields["age"], AGE_MAX, AGE_MIN)
- if (!t1)
- return
- if(!canUseSecurityRecordsConsole(usr, "age", a1))
- return
- active1.fields["age"] = t1
- if("species")
- if(istype(active1, /datum/data/record))
- var/t1 = tgui_input_list(usr, "Select a species", "Species Selection", get_selectable_species())
- if(isnull(t1))
- return
- if(!canUseSecurityRecordsConsole(usr, t1, a1))
- return
- active1.fields["species"] = t1
- if("show_photo_front")
- if(active1)
- var/front_photo = active1.get_front_photo()
- if(istype(front_photo, /obj/item/photo))
- var/obj/item/photo/photo = front_photo
- photo.show(usr)
- if("upd_photo_front")
- var/obj/item/photo/photo = get_photo(usr)
- if(photo)
- qdel(active1.fields["photo_front"])
- //Lets center it to a 32x32.
- var/icon/I = photo.picture.picture_image
- var/w = I.Width()
- var/h = I.Height()
- var/dw = w - 32
- var/dh = w - 32
- I.Crop(dw/2, dh/2, w - dw/2, h - dh/2)
- active1.fields["photo_front"] = photo
- if("print_photo_front")
- if(active1)
- var/front_photo = active1.get_front_photo()
- if(istype(front_photo, /obj/item/photo))
- var/obj/item/photo/photo_front = front_photo
- print_photo(photo_front.picture.picture_image, active1.fields["name"])
- if("show_photo_side")
- if(active1)
- var/side_photo = active1.get_side_photo()
- if(istype(side_photo, /obj/item/photo))
- var/obj/item/photo/photo = side_photo
- photo.show(usr)
- if("upd_photo_side")
- var/obj/item/photo/photo = get_photo(usr)
- if(photo)
- qdel(active1.fields["photo_side"])
- //Lets center it to a 32x32.
- var/icon/I = photo.picture.picture_image
- var/w = I.Width()
- var/h = I.Height()
- var/dw = w - 32
- var/dh = w - 32
- I.Crop(dw/2, dh/2, w - dw/2, h - dh/2)
- active1.fields["photo_side"] = photo
- if("print_photo_side")
- if(active1)
- var/side_photo = active1.get_side_photo()
- if(istype(side_photo, /obj/item/photo))
- var/obj/item/photo/photo_side = side_photo
- print_photo(photo_side.picture.picture_image, active1.fields["name"])
- if("crim_add")
- if(istype(active1, /datum/data/record))
- var/t1 = tgui_input_text(usr, "Input crime names", "Security Records")
- var/t2 = tgui_input_text(usr, "Input crime details", "Security Records")
- if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, station_time_timestamp())
- GLOB.data_core.addCrime(active1.fields["id"], crime)
- investigate_log("New Crime: [t1] : [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
- if("crim_delete")
- if(istype(active1, /datum/data/record))
- if(href_list["cdataid"])
- if(!canUseSecurityRecordsConsole(usr, "delete", null, a2))
- return
- GLOB.data_core.removeCrime(active1.fields["id"],href_list["cdataid"])
- if("add_details")
- if(istype(active1, /datum/data/record))
- if(href_list["cdataid"])
- var/t1 = tgui_input_text(usr, "Input crime details", "Security Records")
- if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- GLOB.data_core.addCrimeDetails(active1.fields["id"], href_list["cdataid"], t1)
- investigate_log("New Crime details: [t1] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
- if("citation_add")
- if(istype(active1, /datum/data/record))
- var/maxFine = CONFIG_GET(number/maxfine)
-
- var/t1 = tgui_input_text(usr, "Input citation crime", "Security Records")
- if(!t1)
- return
- var/fine = tgui_input_number(usr, "Input citation fine", "Security Records", 50, maxFine)
- if (!fine || QDELETED(usr) || QDELETED(src) || !canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- var/datum/data/crime/crime = GLOB.data_core.createCrimeEntry(t1, "", authenticated, station_time_timestamp(), fine)
- for (var/obj/item/modular_computer/tablet as anything in GLOB.TabletMessengers)
- if(tablet.saved_identification == active1.fields["name"])
- var/message = "You have been fined [fine] credits for '[t1]'. Fines may be paid at security."
- var/datum/signal/subspace/messaging/tablet_msg/signal = new(src, list(
- "name" = "Security Citation",
- "job" = "Citation Server",
- "message" = message,
- "targets" = list(tablet),
- "automated" = TRUE
- ))
- signal.send_to_receivers()
- usr.log_message("(PDA: Citation Server) sent \"[message]\" to [signal.format_target()]", LOG_PDA)
- GLOB.data_core.addCitation(active1.fields["id"], crime)
- investigate_log("New Citation: [t1] Fine: [fine] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
- SSblackbox.ReportCitation(crime.dataId, usr.ckey, usr.real_name, active1.fields["name"], t1, fine)
- if("citation_delete")
- if(istype(active1, /datum/data/record))
- if(href_list["cdataid"])
- if(!canUseSecurityRecordsConsole(usr, "delete", null, a2))
- return
- GLOB.data_core.removeCitation(active1.fields["id"], href_list["cdataid"])
- if("notes")
- if(istype(active2, /datum/data/record))
- var/t1 = tgui_input_text(usr, "Please summarize notes", "Security Records", active2.fields["notes"])
- if(!canUseSecurityRecordsConsole(usr, t1, null, a2))
- return
- active2.fields["notes"] = t1
- if("criminal")
- if(istype(active2, /datum/data/record))
- temp = "Criminal Status: "
- temp += ""
- if("rank")
- var/list/L = list(
- JOB_CAPTAIN,
- JOB_HEAD_OF_PERSONNEL,
- JOB_AI,
- JOB_CENTCOM,
- )
- //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N
- if((istype(active1, /datum/data/record) && L.Find(rank)))
- temp = "Rank: "
- temp += ""
- var/list/station_job_templates = SSid_access.station_job_templates
- for(var/path in station_job_templates)
- var/rank = station_job_templates[path]
- temp += "[rank] "
- temp += " "
- else
- tgui_alert(usr, "You do not have the required rank to do this!")
-//TEMPORARY MENU FUNCTIONS
- else//To properly clear as per clear screen.
- temp=null
- switch(href_list["choice"])
- if("Change Rank")
- if(active1)
- var/text = strip_html(href_list["rank"])
- var/path = text2path(text)
- if(ispath(path))
- var/rank = SSid_access.station_job_templates[path]
- if(rank)
- active1.fields["rank"] = rank
- active1.fields["trim"] = active1.fields["rank"]
- else
- message_admins("Warning: possible href exploit by [key_name(usr)] - attempted to set change a crew member rank to an invalid path: [path]")
- log_game("Warning: possible href exploit by [key_name(usr)] - attempted to set change a crew member rank to an invalid path: [path]")
- usr.log_message("possibly trying to href exploit - attempted to set change a crew member rank to an invalid path: [path]", LOG_ADMIN, log_globally = FALSE)
- else if(!isnull(text))
- message_admins("Warning: possible href exploit by [key_name(usr)] - attempted to set change a crew member rank to an invalid value: [text]")
- log_game("Warning: possible href exploit by [key_name(usr)] - attempted to set change a crew member rank to an invalid value: [text]")
- usr.log_message("possibly trying to href exploit - attempted to set change a crew member rank to an invalid value: [text]", LOG_ADMIN, log_globally = FALSE)
-
- if("Change Criminal Status")
- if(active2)
- var/old_field = active2.fields["criminal"]
- switch(href_list["criminal2"])
- if("none")
- active2.fields["criminal"] = "None"
- if("arrest")
- active2.fields["criminal"] = "*Arrest*"
- if("incarcerated")
- active2.fields["criminal"] = "Incarcerated"
- if("suspected")
- active2.fields["criminal"] = "Suspected"
- if("paroled")
- active2.fields["criminal"] = "Paroled"
- if("released")
- active2.fields["criminal"] = "Discharged"
- investigate_log("[active1.fields["name"]] has been set from [old_field] to [active2.fields["criminal"]] by [key_name(usr)].", INVESTIGATE_RECORDS)
- for(var/i in GLOB.human_list)
- var/mob/living/carbon/human/H = i
- H.sec_hud_set_security_status()
- if("Delete Record (Security) Execute")
- usr.investigate_log("has deleted the security records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
- if(active2)
- qdel(active2)
- active2 = null
-
- if("Delete Record (ALL) Execute")
- if(active1)
- usr.investigate_log("has deleted all records for [active1.fields["name"]].", INVESTIGATE_RECORDS)
- for(var/datum/data/record/R in GLOB.data_core.medical)
- if((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
- qdel(R)
- break
- qdel(active1)
- active1 = null
-
- if(active2)
- qdel(active2)
- active2 = null
- else
- temp = "This function does not appear to be working at the moment. Our apologies."
-
- add_fingerprint(usr)
- updateUsrDialog()
- return
-
-/obj/machinery/computer/secure_data/proc/get_photo(mob/user)
- var/obj/item/photo/P = null
- if(issilicon(user))
- var/mob/living/silicon/tempAI = user
- var/datum/picture/selection = tempAI.GetPhoto(user)
- if(selection)
- P = new(null, selection)
- else if(istype(user.get_active_held_item(), /obj/item/photo))
- P = user.get_active_held_item()
- return P
-
-/obj/machinery/computer/secure_data/proc/print_photo(icon/temp, person_name)
- if (printing)
- return
- printing = TRUE
- sleep(2 SECONDS)
- var/obj/item/photo/P = new/obj/item/photo(drop_location())
- var/datum/picture/toEmbed = new(name = person_name, desc = "The photo on file for [person_name].", image = temp)
- P.set_picture(toEmbed, TRUE, TRUE)
- P.pixel_x = rand(-10, 10)
- P.pixel_y = rand(-10, 10)
- printing = FALSE
-
-/obj/machinery/computer/secure_data/emp_act(severity)
- . = ..()
-
- if(machine_stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_SELF)
- return
-
- for(var/datum/data/record/R in GLOB.data_core.security)
- if(prob(10/severity))
- switch(rand(1,8))
- if(1)
- if(prob(10))
- R.fields["name"] = "[pick(lizard_name(MALE),lizard_name(FEMALE))]"
- else
- R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]"
- if(2)
- R.fields["gender"] = pick("Male", "Female", "Other")
- if(3)
- R.fields["age"] = rand(5, 85)
- if(4)
- R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Suspected", "Paroled", "Discharged")
- if(5)
- R.fields["p_stat"] = pick("*Unconscious*", "Active", "Physically Unfit")
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- if(7)
- R.fields["species"] = pick(get_selectable_species())
- if(8)
- var/datum/data/record/G = pick(GLOB.data_core.general)
- R.fields["photo_front"] = G.fields["photo_front"]
- R.fields["photo_side"] = G.fields["photo_side"]
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
-/obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2)
- if(user && authenticated)
- if(user.canUseTopic(src, !issilicon(user)))
- if(!trim(message1))
- return FALSE
- if(!record1 || record1 == active1)
- if(!record2 || record2 == active2)
- return TRUE
- return FALSE
+#undef PRINTOUT_MISSING
+#undef PRINTOUT_RAPSHEET
+#undef PRINTOUT_WANTED
diff --git a/code/game/machinery/computer/warrant.dm b/code/game/machinery/computer/warrant.dm
index 52f06860752..dca46c5b634 100644
--- a/code/game/machinery/computer/warrant.dm
+++ b/code/game/machinery/computer/warrant.dm
@@ -1,137 +1,178 @@
-/obj/machinery/computer/warrant//TODO:SANITY
+/obj/machinery/computer/warrant
name = "security warrant console"
- desc = "Used to view crewmember security records"
+ desc = "Used to view outstanding warrants."
icon_screen = "security"
icon_keyboard = "security_key"
circuit = /obj/item/circuitboard/computer/warrant
light_color = COLOR_SOFT_RED
- var/screen = null
- var/datum/data/record/current = null
+ /// The state of the printer
+ var/printing = FALSE
-/obj/machinery/computer/warrant/ui_interact(mob/user)
+/obj/machinery/computer/warrant/ui_interact(mob/user, datum/tgui/ui)
. = ..()
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "WarrantConsole", name)
+ ui.set_autoupdate(FALSE)
+ ui.open()
- var/list/dat = list("Logged in as: ")
- if(authenticated)
- dat += {"[authenticated] "}
- if(current)
- var/background
- var/notice = ""
- switch(current.fields["criminal"])
- if("*Arrest*")
- background = "background-color:#990000;"
- notice = " **REPORT TO THE BRIG**"
- if("Incarcerated")
- background = "background-color:#CD6500;"
- if("Suspected")
- background = "background-color:#CD6500;"
- if("Paroled")
- background = "background-color:#CD6500;"
- if("Discharged")
- background = "background-color:#006699;"
- if("None")
- background = "background-color:#4F7529;"
- if("")
- background = "''" //"'background-color:#FFFFFF;'"
- dat += "Warrant Data "
- dat += {"
- Name: [current.fields["name"]]
- ID: [current.fields["id"]]
-
"}
- dat += {"Criminal Status:
-
- [current.fields["criminal"]][notice]
-
"}
+/obj/machinery/computer/warrant/ui_data(mob/user)
+ var/list/data = list()
- dat += " Citations:"
+ var/list/records = list()
- dat +={"
-
- Crime
- Fine
- Author
- Time Added
- Amount Due
- Make Payment
- "}
- for(var/datum/data/crime/c in current.fields["citation"])
- var/owed = c.fine - c.paid
- dat += {"[c.crimeName]
- [c.fine] cr
- [c.author]
- [c.time] "}
- if(owed > 0)
- dat += {"[owed] cr
- \[Pay\] "}
- else
- dat += "All Paid Off "
- dat += " "
- dat += "
"
+ for(var/datum/record/crew/target in GLOB.manifest.general)
+ if(!length(target.citations))
+ continue
- dat += " Crimes:"
- dat +={"
-
- Crime
- Details
- Author
- Time Added
- "}
- for(var/datum/data/crime/c in current.fields["crim"])
- dat += {"[c.crimeName]
- [c.crimeDetails]
- [c.author]
- [c.time]
- "}
- dat += "
"
- else
- dat += {"** No security record found for this ID ** "}
- else
- dat += {"------------ "}
+ var/list/citations = list()
- var/datum/browser/popup = new(user, "warrant", "Security Warrant Console", 600, 400)
- popup.set_content(dat.Join())
- popup.open()
+ for(var/datum/crime/citation/warrant as anything in target.citations)
+ var/list/entry = list(list(
+ author = warrant.author,
+ details = warrant.details,
+ fine = warrant.fine,
+ fine_name = warrant.name,
+ fine_ref = REF(warrant),
+ paid = warrant.paid,
+ time = warrant.time,
+ ))
-/obj/machinery/computer/warrant/Topic(href, href_list)
- if(..())
- return
- var/mob/M = usr
- switch(href_list["choice"])
- if("Login")
- if(isliving(M))
- var/mob/living/L = M
- var/obj/item/card/id/scan = L.get_idcard(TRUE)
- if (!scan)
- say("You do not have a registered ID!")
- return
- authenticated = scan.registered_name
- if(authenticated)
- current = find_record("name", authenticated, GLOB.data_core.security)
- playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
- if("Logout")
- current = null
- authenticated = null
- playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
+ citations += entry
- if("Pay")
- for(var/datum/data/crime/p in current.fields["citation"])
- if(p.dataId == text2num(href_list["cdataid"]))
- var/obj/item/holochip/C = M.is_holding_item_of_type(/obj/item/holochip)
- if(C && istype(C))
- var/pay = C.get_item_credit_value()
- if(!pay)
- to_chat(M, span_warning("[C] doesn't seem to be worth anything!"))
- else
- var/diff = p.fine - p.paid
- GLOB.data_core.payCitation(current.fields["id"], text2num(href_list["cdataid"]), pay)
- to_chat(M, span_notice("You have paid [pay] credit\s towards your fine."))
- if (pay == diff || pay > diff || pay >= diff)
- investigate_log("Citation Paid off: [p.crimeName] Fine: [p.fine] | Paid off by [key_name(usr)]", INVESTIGATE_RECORDS)
- to_chat(M, span_notice("The fine has been paid in full."))
- SSblackbox.ReportCitation(text2num(href_list["cdataid"]),"","","","", 0, pay)
- qdel(C)
- playsound(src, SFX_TERMINAL_TYPE, 25, FALSE)
- else
- to_chat(M, span_warning("Fines can only be paid with holochips!"))
- updateUsrDialog()
- add_fingerprint(M)
+ var/list/record = list(list(
+ citations = citations,
+ crew_name = target.name,
+ crew_ref = REF(target),
+ notes = target.security_note,
+ rank = target.rank,
+ ))
+
+ records += record
+ data["records"] = records
+
+ return data
+
+/obj/machinery/computer/warrant/ui_act(action, list/params, datum/tgui/ui)
+ . = ..()
+ if(.)
+ return FALSE
+
+ switch(action)
+ if("pay")
+ pay_fine(usr, params)
+ return TRUE
+
+ if("print")
+ ui.close()
+ print_bounty(usr, params)
+ return TRUE
+
+ if("refresh")
+ return TRUE
+
+ return FALSE
+
+/// Pays towards a listed fine.
+/obj/machinery/computer/warrant/proc/pay_fine(mob/user, list/params)
+ var/datum/record/crew/target = locate(params["crew_ref"]) in GLOB.manifest.general
+ if(!target)
+ return FALSE
+
+ var/datum/crime/citation/warrant = locate(params["fine_ref"]) in target.citations
+ if(!warrant)
+ return FALSE
+
+ if(!isliving(user) || issilicon(user))
+ to_chat(user, span_warning("ACCESS DENIED"))
+ playsound(src, 'sound/machines/terminal_error.ogg', 100, TRUE)
+ return FALSE
+
+ var/mob/living/player = user
+ var/obj/item/card/id/auth = player.get_idcard(TRUE)
+ if(!auth)
+ to_chat(user, span_warning("ACCESS DENIED: No ID card detected."))
+ playsound(src, 'sound/machines/terminal_error.ogg', 100, TRUE)
+ return FALSE
+
+ var/datum/bank_account/account = auth.registered_account
+ if(!account?.account_holder || account.account_holder == "Unassigned")
+ to_chat(user, span_warning("ACCESS DENIED: No account linked to ID."))
+ playsound(src, 'sound/machines/terminal_error.ogg', 100, TRUE)
+ return FALSE
+
+ var/amount = params["amount"]
+ if(!amount || !isnum(amount) || amount > warrant.fine || !account.adjust_money(-amount, "Paid fine for [target.name]"))
+ to_chat(user, span_warning("ACCESS DENIED: Invalid amount."))
+ playsound(src, 'sound/machines/terminal_error.ogg', 100, TRUE)
+ return FALSE
+
+ account.bank_card_talk("You have paid [amount]cr towards [target.name]'s fine of [warrant.fine]cr.")
+ log_econ("[amount]cr was transferred from [user]'s transaction to [target.name]'s [warrant.fine]cr fine")
+ SSblackbox.record_feedback("amount", "credits_transferred", amount)
+ warrant.pay_fine(amount)
+
+ if(amount >= 100 && target?.name != user)
+ var/list/titles = list(
+ "An anonymous benefactor",
+ "A generous citizen",
+ "A kind soul",
+ "A good samaritan",
+ "A friendly face",
+ "A helpful stranger",
+ )
+ warrant.alert_owner(user, src, target.name, "[pick(titles)] has paid [amount]cr towards your fine.")
+
+ var/datum/bank_account/sec_account = SSeconomy.get_dep_account(ACCOUNT_SEC)
+ sec_account.adjust_money(amount)
+
+ if(warrant.fine != 0 || target.name == user)
+ return TRUE
+
+ warrant.alert_owner(user, src, target.name, "One of your outstanding warrants has been completely paid.")
+ return TRUE
+
+/// Finishes printing, resets the printer.
+/obj/machinery/computer/warrant/proc/print_finish(obj/item/paper/bounty)
+ printing = FALSE
+ playsound(src, 'sound/machines/terminal_eject.ogg', 100, TRUE)
+ bounty.forceMove(loc)
+
+ return TRUE
+
+/// Prints a bounty for a listed fine.
+/obj/machinery/computer/warrant/proc/print_bounty(mob/user, list/params)
+ if(printing)
+ balloon_alert(user, "printer busy")
+ playsound(src, 'sound/machines/terminal_error.ogg', 100, TRUE)
+ return FALSE
+
+ var/datum/record/crew/target = locate(params["crew_ref"]) in GLOB.manifest.general
+ if(!target)
+ return FALSE
+
+ var/datum/crime/citation/warrant = locate(params["fine_ref"]) in target.citations
+ if(!warrant?.fine)
+ return FALSE
+
+ var/bounty_text = "Bounty for [target.name] "
+ bounty_text += "Wanted for [warrant.name] "
+ bounty_text += "Details: [warrant.details] "
+ bounty_text += "Issued to: [usr] "
+ bounty_text += "Issued on: [warrant.time] "
+ bounty_text += "Comments: [!target.security_note ? "None." : target.security_note] "
+ bounty_text += "FINE: [warrant.fine] credits "
+
+ printing = TRUE
+ balloon_alert(user, "printing")
+ playsound(src, 'sound/machines/printer.ogg', 100, TRUE)
+
+ var/obj/item/paper/bounty = new(null)
+ bounty.name = "Bounty for [target.name]"
+ bounty.desc = "A [warrant.fine]cr bounty for [target.name]."
+ bounty.add_raw_text(bounty_text)
+ bounty.update_icon()
+
+ addtimer(CALLBACK(src, PROC_REF(print_finish), bounty), 2 SECONDS)
+
+ return TRUE
diff --git a/code/game/machinery/gulag_teleporter.dm b/code/game/machinery/gulag_teleporter.dm
index e0d48dee344..1d3eaba6358 100644
--- a/code/game/machinery/gulag_teleporter.dm
+++ b/code/game/machinery/gulag_teleporter.dm
@@ -144,7 +144,7 @@ The console is located at computer/gulag_teleporter.dm
else
W.forceMove(src)
-/obj/machinery/gulag_teleporter/proc/handle_prisoner(obj/item/id, datum/data/record/R)
+/obj/machinery/gulag_teleporter/proc/handle_prisoner(obj/item/id, datum/record/crew/target)
if(!ishuman(occupant))
return
strip_occupant()
@@ -158,8 +158,8 @@ The console is located at computer/gulag_teleporter.dm
prisoner.equip_to_appropriate_slot(new shoes_type, qdel_on_fail = TRUE)
if(id)
prisoner.equip_to_appropriate_slot(id, qdel_on_fail = TRUE)
- if(R)
- R.fields["criminal"] = "Incarcerated"
+ if(target)
+ target.wanted_status = WANTED_PRISONER
use_power(active_power_usage)
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 4d3d78cca3a..b1d87fa5ada 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -569,8 +569,8 @@ DEFINE_BITFIELD(turret_flags, list(
if(turret_flags & TURRET_FLAG_SHOOT_CRIMINALS) //if the turret can check the records, check if they are set to *Arrest* on records
var/perpname = perp.get_face_name(perp.get_id_name())
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
- if(!R || (R.fields["criminal"] == "*Arrest*"))
+ var/datum/record/crew/target = find_record(perpname)
+ if(!target || (target.wanted_status == WANTED_ARREST))
threatcount += 4
if((turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED) && (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)))
diff --git a/code/game/machinery/scan_gate.dm b/code/game/machinery/scan_gate.dm
index d6dc3b3299c..271c4b31c8b 100644
--- a/code/game/machinery/scan_gate.dm
+++ b/code/game/machinery/scan_gate.dm
@@ -140,8 +140,8 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/perpname = H.get_face_name(H.get_id_name())
- var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
- if(!R || (R.fields["criminal"] == "*Arrest*"))
+ var/datum/record/crew/target = find_record(perpname)
+ if(!target || (target.wanted_status == WANTED_ARREST))
beep = TRUE
if(SCANGATE_MINDSHIELD)
if(HAS_TRAIT(M, TRAIT_MINDSHIELD))
diff --git a/code/game/say.dm b/code/game/say.dm
index c8a319eb63c..1828e5fdc9a 100644
--- a/code/game/say.dm
+++ b/code/game/say.dm
@@ -248,9 +248,9 @@ INITIALIZE_IMMEDIATE(/atom/movable/virtualspeaker)
if(ishuman(M))
// Humans use their job as seen on the crew manifest. This is so the AI
// can know their job even if they don't carry an ID.
- var/datum/data/record/findjob = find_record("name", name, GLOB.data_core.general)
- if(findjob)
- job = findjob.fields["rank"]
+ var/datum/record/crew/found_record = find_record(name)
+ if(found_record)
+ job = found_record.rank
else
job = "Unknown"
else if(iscarbon(M)) // Carbon nonhuman
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 02dd5f9651e..5bba5081210 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -979,7 +979,7 @@ GLOBAL_PROTECT(admin_verbs_poll)
// Finally, ensure the minds are tracked and in the manifest.
SSticker.minds += character.mind
if(ishuman(character))
- GLOB.data_core.manifest_inject(character)
+ GLOB.manifest.inject(character)
number_made++
CHECK_TICK
diff --git a/code/modules/admin/verbs/admingame.dm b/code/modules/admin/verbs/admingame.dm
index 87734493a7c..8e8ae1f00cd 100644
--- a/code/modules/admin/verbs/admingame.dm
+++ b/code/modules/admin/verbs/admingame.dm
@@ -209,19 +209,16 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/mob/living/carbon/human/new_character = new//The mob being spawned.
SSjob.SendToLateJoin(new_character)
- var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character.
+ var/datum/record/locked/record_found //Referenced to later to either randomize or not randomize the character.
if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something
- /*Try and locate a record for the person being respawned through GLOB.data_core.
- This isn't an exact science but it does the trick more often than not.*/
- var/id = md5("[G_found.real_name][G_found.mind.assigned_role.title]")
-
- record_found = find_record("id", id, GLOB.data_core.locked)
+ record_found = find_record(G_found.name, locked_only = TRUE)
if(record_found)//If they have a record we can determine a few things.
- new_character.real_name = record_found.fields["name"]
- new_character.gender = record_found.fields["gender"]
- new_character.age = record_found.fields["age"]
- new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], null, record_found.fields["name"], record_found.fields["blood_type"], new record_found.fields["species"], record_found.fields["features"])
+ new_character.real_name = record_found.name
+ new_character.gender = record_found.gender
+ new_character.age = record_found.age
+ var/datum/dna/found_dna = record_found.dna_ref
+ new_character.hardset_dna(found_dna.unique_identity, record_found.dna_string, null, record_found.name, record_found.blood_type, new record_found.species, found_dna.features)
else
new_character.randomize_human_appearance()
new_character.dna.update_dna_identity()
@@ -285,7 +282,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!record_found && (new_character.mind.assigned_role.job_flags & JOB_CREW_MEMBER))
//Power to the user!
if(tgui_alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,list("No","Yes")) == "Yes")
- GLOB.data_core.manifest_inject(new_character, src) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: GLOB.data_core.manifest_inject(new_character)
+ GLOB.manifest.inject(new_character, src) // SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES - Original: GLOB.manifest.inject(new_character)
if(tgui_alert(new_character,"Would you like an active AI to announce this character?",,list("No","Yes")) == "Yes")
announce_arrival(new_character, new_character.mind.assigned_role.title)
diff --git a/code/modules/admin/verbs/list_exposer.dm b/code/modules/admin/verbs/list_exposer.dm
index b4cd1f42e76..851bd901c1e 100644
--- a/code/modules/admin/verbs/list_exposer.dm
+++ b/code/modules/admin/verbs/list_exposer.dm
@@ -53,8 +53,8 @@
return
var/data = "Showing Crew Manifest. "
data += "Name Position "
- for(var/datum/data/record/entry in GLOB.data_core.general)
- data += "[entry.fields["name"]] [entry.fields["rank"]][entry.fields["rank"] != entry.fields["trim"] ? " ([entry.fields["trim"]])" : ""] "
+ for(var/datum/record/crew/entry in GLOB.manifest.general)
+ data += "[entry.name] [entry.rank][entry.rank != entry.trim ? " ([entry.trim])" : ""] "
data += "
"
usr << browse(data, "window=manifest;size=440x410")
diff --git a/code/modules/antagonists/ninja/ninjaDrainAct.dm b/code/modules/antagonists/ninja/ninjaDrainAct.dm
index 8e82921d99d..14422f2dd09 100644
--- a/code/modules/antagonists/ninja/ninjaDrainAct.dm
+++ b/code/modules/antagonists/ninja/ninjaDrainAct.dm
@@ -156,9 +156,8 @@
/obj/machinery/computer/secure_data/proc/ninjadrain_charge(mob/living/carbon/human/ninja, obj/item/mod/module/hacker/hacking_module)
if(!do_after(ninja, 20 SECONDS, src, extra_checks = CALLBACK(src, PROC_REF(can_hack), ninja)))
return
- for(var/datum/data/record/rec in sort_record(GLOB.data_core.general, sortBy, order))
- for(var/datum/data/record/security_record in GLOB.data_core.security)
- security_record.fields["criminal"] = "*Arrest*"
+ for(var/datum/record/crew/target in GLOB.manifest.general)
+ target.wanted_status = WANTED_ARREST
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
if(!ninja_antag)
return
diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm
index 6a178aca738..b8f59894174 100644
--- a/code/modules/detectivework/scanner.dm
+++ b/code/modules/detectivework/scanner.dm
@@ -55,7 +55,7 @@
// Create our paper
var/obj/item/paper/report_paper = new(get_turf(src))
- //This could be a global count like sec and med record printouts. See GLOB.data_core.medicalPrintCount AKA datacore.dm
+ //This could be a global count like sec and med record printouts. See GLOB.manifest.generalPrintCount AKA datacore.dm
var/frNum = ++forensicPrintCount
report_paper.name = text("FR-[] 'Forensic Record'", frNum)
diff --git a/code/modules/jobs/job_types/prisoner.dm b/code/modules/jobs/job_types/prisoner.dm
index e0cd88171c1..d02a0b0b4b1 100644
--- a/code/modules/jobs/job_types/prisoner.dm
+++ b/code/modules/jobs/job_types/prisoner.dm
@@ -41,9 +41,9 @@
crime_name = pick(assoc_to_keys(GLOB.prisoner_crimes))
var/datum/prisoner_crime/crime = GLOB.prisoner_crimes[crime_name]
- var/datum/data/record/target_record = find_record("name", crewmember.real_name, GLOB.data_core.security)
- var/datum/data/crime/past_crime = GLOB.data_core.createCrimeEntry(crime.name, crime.desc, "Central Command", "Indefinite.")
- GLOB.data_core.addCrime(target_record.fields["id"], past_crime)
+ var/datum/record/crew/target_record = find_record(crewmember.real_name)
+ var/datum/crime/past_crime = new(crime.name, crime.desc, "Central Command", "Indefinite.")
+ target_record.crimes += past_crime
to_chat(crewmember, span_warning("You are imprisoned for \"[crime_name]\"."))
/datum/outfit/job/prisoner
diff --git a/code/modules/mob/dead/crew_manifest.dm b/code/modules/mob/dead/crew_manifest.dm
index 08ff61de1a6..6a2c84622a2 100644
--- a/code/modules/mob/dead/crew_manifest.dm
+++ b/code/modules/mob/dead/crew_manifest.dm
@@ -33,6 +33,6 @@
positions[department.department_name] = list("exceptions" = exceptions, "open" = open)
return list(
- "manifest" = GLOB.data_core.get_manifest(),
+ "manifest" = GLOB.manifest.get_manifest(),
"positions" = positions
)
diff --git a/code/modules/mob/dead/new_player/latejoin_menu.dm b/code/modules/mob/dead/new_player/latejoin_menu.dm
index b74e9c5c390..4c8245e69d1 100644
--- a/code/modules/mob/dead/new_player/latejoin_menu.dm
+++ b/code/modules/mob/dead/new_player/latejoin_menu.dm
@@ -101,13 +101,9 @@ GLOBAL_DATUM_INIT(latejoin_menu, /datum/latejoin_menu, new)
departments[department.department_name] = department_data
for(var/datum/job/job_datum as anything in department.department_jobs)
- var/datum/outfit/outfit = job_datum.outfit
- var/datum/id_trim/trim = initial(outfit.id_trim)
-
var/list/job_data = list(
"command" = !!(job_datum.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND),
"description" = job_datum.description,
- "icon" = initial(trim.orbit_icon),
)
department_jobs[job_datum.title] = job_data
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index fe2c90fd4e3..1db1d09ea41 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -226,7 +226,7 @@
if(humanc) //These procs all expect humans
// BEGIN SKYRAT EDIT CHANGE - ALTERNATIVE_JOB_TITLES
var/chosen_rank = humanc.client?.prefs.alt_job_titles[rank] || rank
- GLOB.data_core.manifest_inject(humanc, humanc.client)
+ GLOB.manifest.inject(humanc, humanc.client)
if(SSshuttle.arrivals)
SSshuttle.arrivals.QueueAnnounce(humanc, chosen_rank)
else
diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm
index 93495de2038..0e9334b896f 100644
--- a/code/modules/mob/dead/observer/orbit.dm
+++ b/code/modules/mob/dead/observer/orbit.dm
@@ -97,8 +97,6 @@ GLOBAL_DATUM_INIT(orbit_menu, /datum/orbit_menu, new)
else
var/obj/item/card/id/id_card = player.get_idcard(hand_first = FALSE)
serialized["job"] = id_card?.get_trim_assignment()
- var/datum/id_trim/trim = id_card?.trim
- serialized["job_icon"] = trim?.orbit_icon
for(var/datum/antagonist/antag_datum as anything in mind.antag_datums)
if (antag_datum.show_to_ghosts)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 3f0b1ddb512..37214035911 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -411,10 +411,9 @@
var/perpname = get_face_name(get_id_name(""))
if(perpname && (HAS_TRAIT(user, TRAIT_SECURITY_HUD) || HAS_TRAIT(user, TRAIT_MEDICAL_HUD)))
- var/datum/data/record/target_record = find_record("name", perpname, GLOB.data_core.general)
- var/datum/data/record/record_cache = target_record //SKYRAT EDIT ADDITION - RECORDS
+ var/datum/record/crew/target_record = find_record(perpname)
if(target_record)
- . += "Rank: [target_record.fields["rank"]]\n\[Front photo\] \[Side photo\] "
+ . += "Rank: [target_record.rank]\n\[Front photo\] \[Side photo\] "
if(HAS_TRAIT(user, TRAIT_MEDICAL_HUD))
var/cyberimp_detect
for(var/obj/item/organ/internal/cyberimp/CI in internal_organs)
@@ -423,41 +422,34 @@
if(cyberimp_detect)
. += "Detected cybernetic modifications: "
. += "[cyberimp_detect] "
-
- if(target_record)
- var/health_r = target_record.fields["p_stat"]
- . += "\[[health_r]\] "
- health_r = target_record.fields["m_stat"]
- . += "\[[health_r]\] "
- target_record = find_record("name", perpname, GLOB.data_core.medical)
+ target_record = find_record(perpname)
if(target_record)
. += "\[Medical evaluation\] "
. += "\[See quirks\] "
//SKYRAT EDIT ADDITION BEGIN - EXAMINE RECORDS
- if(target_record && length(target_record.fields["past_records"]) > RECORDS_INVISIBLE_THRESHOLD)
+ if(target_record && length(target_record.past_medical_records) > RECORDS_INVISIBLE_THRESHOLD)
. += "\[View medical records\] "
//SKYRAT EDIT END
if(HAS_TRAIT(user, TRAIT_SECURITY_HUD))
if(!user.stat && user != src)
//|| !user.canmove || user.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
- var/criminal = "None"
+ var/wanted_status = WANTED_NONE
- target_record = find_record("name", perpname, GLOB.data_core.security)
+ target_record = find_record(perpname)
if(target_record)
- criminal = target_record.fields["criminal"]
+ wanted_status = target_record.wanted_status
- . += "Criminal status: \[[criminal]\] "
+ . += "Criminal status: \[[wanted_status]\] "
. += jointext(list("Security record: \[View\] ",
"\[Add citation\] ",
"\[Add crime\] ",
- "\[View comment log\] ",
- "\[Add comment\] "), "")
+ "\[Add note\] "), "")
// SKYRAT EDIT ADDITION BEGIN - EXAMINE RECORDS
- if(target_record && length(target_record.fields["past_records"]) > RECORDS_INVISIBLE_THRESHOLD)
- . += "Security record: \[View security records\] "
+ if(target_record && length(target_record.past_security_records) > RECORDS_INVISIBLE_THRESHOLD)
+ . += "Past security records: \[View past security records\] "
- if (record_cache && length(record_cache.fields["past_records"]) > RECORDS_INVISIBLE_THRESHOLD)
+ if (target_record && length(target_record.past_general_records) > RECORDS_INVISIBLE_THRESHOLD)
. += "\[View general records\] "
//SKYRAT EDIT ADDITION END
else if(isobserver(user))
@@ -465,10 +457,10 @@
//SKYRAT EDIT ADDITION BEGIN - EXAMINE RECORDS
if(isobserver(user) || user.mind?.can_see_exploitables || user.mind?.has_exploitables_override)
- var/datum/data/record/target_records = find_record("name", perpname, GLOB.data_core.general)
+ var/datum/record/crew/target_records = find_record(perpname)
if(target_records)
- var/background_text = target_records.fields["background_records"]
- var/exploitable_text = target_records.fields["exploitable_records"]
+ var/background_text = target_records.background_information
+ var/exploitable_text = target_records.exploitable_information
if((length(background_text) > RECORDS_INVISIBLE_THRESHOLD))
. += "\[View background info\] "
if((length(exploitable_text) > RECORDS_INVISIBLE_THRESHOLD) && ((exploitable_text) != EXPLOITABLE_DEFAULT_TEXT))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index ed1acb01077..379e958dbab 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -107,24 +107,17 @@
if((text2num(href_list["examine_time"]) + 1 MINUTES) < world.time)
to_chat(human_user, "[span_notice("It's too late to use this now!")]")
return
- //SKYRAT EDIT ADDITION BEGIN - EXAMINE RECORDS
- //var/datum/data/record/target_record = find_record("name", perpname, GLOB.data_core.general) // SKYRAT EDIT CHANGE ORIGINAL
- var/datum/data/record/general_record = find_record("name", perpname, GLOB.data_core.general)
- var/datum/data/record/med_record = find_record("name", perpname, GLOB.data_core.medical)
- var/datum/data/record/sec_record = find_record("name", perpname, GLOB.data_core.security)
- //SKYRAT EDIT ADDITION END - EXAMINE RECORDS
+ var/datum/record/crew/target_record = find_record(perpname)
if(href_list["photo_front"] || href_list["photo_side"])
- if(!general_record) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- return
if(!human_user.canUseHUD())
return
if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD) && !HAS_TRAIT(human_user, TRAIT_MEDICAL_HUD))
return
var/obj/item/photo/photo_from_record = null
if(href_list["photo_front"])
- photo_from_record = general_record.get_front_photo() // SKYRAT EDIT - Examine Records - ORIGINAL: photo_from_record = target_record.get_front_photo()
+ photo_from_record = target_record.get_front_photo()
else if(href_list["photo_side"])
- photo_from_record = general_record.get_side_photo() // SKYRAT EDIT - Examine Records - ORIGINAL: photo_from_record = target_record.get_side_photo()
+ photo_from_record = target_record.get_side_photo()
if(photo_from_record)
photo_from_record.show(human_user)
return
@@ -181,28 +174,6 @@
if(!(ACCESS_MEDICAL in access))
to_chat(human_user, span_warning("ERROR: Invalid access"))
return
- if(href_list["p_stat"])
- var/health_status = input(human_user, "Specify a new physical status for this person.", "Medical HUD", general_record.fields["p_stat"]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel")
- if(!general_record) // SKYRAT EDIT CHANGE
- return
- if(!human_user.canUseHUD())
- return
- if(!HAS_TRAIT(human_user, TRAIT_MEDICAL_HUD))
- return
- if(health_status && health_status != "Cancel")
- general_record.fields["p_stat"] = health_status // SKYRAT EDIT CHANGE
- return
- if(href_list["m_stat"])
- var/health_status = input(human_user, "Specify a new mental status for this person.", "Medical HUD", general_record.fields["m_stat"]) in list("Stable", "*Watch*", "*Unstable*", "*Insane*", "Cancel")
- if(!general_record) // SKYRAT EDIT CHANGE
- return
- if(!human_user.canUseHUD())
- return
- if(!HAS_TRAIT(human_user, TRAIT_MEDICAL_HUD))
- return
- if(health_status && health_status != "Cancel")
- general_record.fields["m_stat"] = health_status //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- return
if(href_list["quirk"])
var/quirkstring = get_quirk_string(TRUE, CAT_QUIRK_ALL)
if(quirkstring)
@@ -211,9 +182,9 @@
to_chat(usr, "No physiological traits found. ")
//SKYRAT EDIT ADDITION BEGIN - EXAMINE RECORDS
if(href_list["medrecords"])
- to_chat(usr, "Medical Record: [med_record.fields["past_records"]]")
+ to_chat(usr, "Medical Record: [target_record.past_medical_records]")
if(href_list["genrecords"])
- to_chat(usr, "General Record: [general_record.fields["past_records"]]")
+ to_chat(usr, "General Record: [target_record.past_general_records]")
//SKYRAT EDIT END
return //Medical HUD ends here.
@@ -240,25 +211,17 @@
if(!perpname)
to_chat(human_user, span_warning("ERROR: Can not identify target."))
return
- /* ORIGINAL
- target_record = find_record("name", perpname, GLOB.data_core.security)
+ target_record = find_record(perpname)
if(!target_record)
- */
- if(!sec_record) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
to_chat(usr, span_warning("ERROR: Unable to locate data core entry for target."))
return
if(href_list["status"])
- var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", sec_record.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Suspected", "Paroled", "Discharged", "Cancel") //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- if(setcriminal != "Cancel")
- if(!sec_record) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- return
- if(!human_user.canUseHUD())
- return
- if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
- return
- investigate_log("has been set from [sec_record.fields["criminal"]] to [setcriminal] by [key_name(human_user)].", INVESTIGATE_RECORDS) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- sec_record.fields["criminal"] = setcriminal //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- sec_hud_set_security_status()
+ var/setcriminal = tgui_input_list(human_user, "Specify a new criminal status for this person.", "Security HUD", WANTED_STATUSES(), target_record.wanted_status)
+ if(!setcriminal || !target_record || !human_user.canUseHUD() || !HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
+ return
+ investigate_log("has been set from [target_record.wanted_status] to [setcriminal] by [key_name(human_user)].", INVESTIGATE_RECORDS)
+ target_record.wanted_status = setcriminal
+ sec_hud_set_security_status()
return
if(href_list["view"])
@@ -266,16 +229,17 @@
return
if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
return
- to_chat(usr, "Name: [sec_record.fields["name"]] Criminal Status: [sec_record.fields["criminal"]]") //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- for(var/datum/data/crime/c in sec_record.fields["crim"]) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- to_chat(usr, "Crime: [c.crimeName]")
- if (c.crimeDetails)
- to_chat(human_user, "Details: [c.crimeDetails]")
- else
- to_chat(human_user, "Details: \[Add details] ")
- to_chat(human_user, "Added by [c.author] at [c.time]")
+ to_chat(human_user, "Name: [target_record.name]")
+ to_chat(human_user, "Criminal Status: [target_record.wanted_status]")
+ to_chat(human_user, "Rapsheet: ")
+ for(var/datum/crime/crime in target_record.crimes)
+ to_chat(human_user, "Crime: [crime.name]")
+ to_chat(human_user, "Details: [crime.details]")
+ to_chat(human_user, "Added by [crime.author] at [crime.time]")
to_chat(human_user, "----------")
- to_chat(human_user, "Notes: [sec_record.fields["notes"]]") //SKYRAT EDIT CHANGE - EXAMINE RECORDS
+ to_chat(human_user, "Citations: [length(target_record.citations)]")
+ to_chat(human_user, "Note: [target_record.security_note || "None."]")
+
return
//SKYRAT EDIT ADDITION BEGIN - EXAMINE RECORDS
@@ -284,115 +248,65 @@
return
if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
return
- to_chat(usr, "General Record: [general_record.fields["past_records"]]")
+ to_chat(human_user, "General Record: [target_record.past_general_records]")
if(href_list["secrecords"])
if(!human_user.canUseHUD())
return
if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
return
- to_chat(usr, "Security Record: [sec_record.fields["past_records"]]")
+ to_chat(human_user, "Security Record: [target_record.past_security_records]")
//SKYRAT EDIT END
if(href_list["add_citation"])
- var/maxFine = CONFIG_GET(number/maxfine)
- var/t1 = tgui_input_text(human_user, "Citation crime", "Security HUD")
- var/fine = tgui_input_number(human_user, "Citation fine", "Security HUD", 50, maxFine, 5)
- if(!fine)
- return
- //if(!target_record || !t1 || !allowed_access) // ORIGINAL
- if(!sec_record || !t1 || !allowed_access) // SKYRAT EDIT CHANGE - EXAMINE RECORDS
- return
- if(!human_user.canUseHUD())
- return
- if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
+ var/max_fine = CONFIG_GET(number/maxfine)
+ var/citation_name = tgui_input_text(human_user, "Citation crime", "Security HUD")
+ var/fine = tgui_input_number(human_user, "Citation fine", "Security HUD", 50, max_fine, 5)
+ if(!fine || !target_record || !citation_name || !allowed_access || !isnum(fine) || fine > max_fine || fine <= 0 || !human_user.canUseHUD() || !HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
return
- var/datum/data/crime/crime = GLOB.data_core.createCrimeEntry(t1, "", allowed_access, station_time_timestamp(), fine)
- for (var/obj/item/modular_computer/tablet in GLOB.TabletMessengers)
- if(tablet.saved_identification == sec_record.fields["name"]) // SKYRAT EDIT CHANGE
- var/message = "You have been fined [fine] credits for '[t1]'. Fines may be paid at security."
- var/datum/signal/subspace/messaging/tablet_msg/signal = new(src, list(
- "name" = "Security Citation",
- "job" = "Citation Server",
- "message" = message,
- "targets" = list(tablet),
- "automated" = TRUE
- ))
- signal.send_to_receivers()
- human_user.log_message("(PDA: Citation Server) sent \"[message]\" to [signal.format_target()]", LOG_PDA)
- GLOB.data_core.addCitation(sec_record.fields["id"], crime) // SKYRAT EDIT CHANGE - RECORDS
- investigate_log("New Citation: [t1] Fine: [fine] | Added to [sec_record.fields["name"]] by [key_name(human_user)]", INVESTIGATE_RECORDS) // SKYRAT EDIT CHANGE - RECORDS
- SSblackbox.ReportCitation(crime.dataId, human_user.ckey, human_user.real_name, sec_record.fields["name"], t1, fine) // SKYRAT EDIT CHANGE - RECORDS
+ var/datum/crime/citation/new_citation = new(name = citation_name, author = allowed_access, fine = fine)
+
+ target_record.citations += new_citation
+ new_citation.alert_owner(target_record.name, "You have been fined [fine] credits for '[citation_name]'. Fines may be paid at security.")
+ investigate_log("New Citation: [citation_name] Fine: [fine] | Added to [target_record.name] by [key_name(human_user)]", INVESTIGATE_RECORDS)
+ SSblackbox.ReportCitation(REF(new_citation), human_user.ckey, human_user.real_name, target_record.name, citation_name, fine)
+
return
if(href_list["add_crime"])
- var/t1 = tgui_input_text(human_user, "Crime name", "Security HUD")
- if(!sec_record || !t1 || !allowed_access) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
+ var/crime_name = tgui_input_text(human_user, "Crime name", "Security HUD")
+ if(!target_record || !crime_name || !allowed_access || !human_user.canUseHUD() || !HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
return
- if(!human_user.canUseHUD())
- return
- if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
- return
- var/crime = GLOB.data_core.createCrimeEntry(t1, null, allowed_access, station_time_timestamp())
- GLOB.data_core.addCrime(sec_record.fields["id"], crime) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- investigate_log("New Crime: [t1] | Added to [sec_record.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- to_chat(usr, span_notice("Successfully added a crime."))
+
+ var/datum/crime/new_crime = new(name = crime_name, author = allowed_access)
+
+ target_record.crimes += new_crime
+ investigate_log("New Crime: [crime_name] | Added to [target_record.name] by [key_name(human_user)]", INVESTIGATE_RECORDS)
+ to_chat(human_user, span_notice("Successfully added a crime."))
+
return
- if(href_list["add_details"])
- var/t1 = tgui_input_text(usr, "Crime details", "Security Records", multiline = TRUE)
- if(!sec_record || !t1 || !allowed_access) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
+ if(href_list["add_note"])
+ var/new_note = tgui_input_text(human_user, "Security note", "Security Records", multiline = TRUE)
+ if(!target_record || !new_note || !allowed_access || !human_user.canUseHUD() || !HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
return
- if(!human_user.canUseHUD())
- return
- if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
- return
- if(href_list["cdataid"])
- GLOB.data_core.addCrimeDetails(sec_record.fields["id"], href_list["cdataid"], t1) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- investigate_log("New Crime details: [t1] | Added to [sec_record.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- to_chat(human_user, span_notice("Successfully added details."))
- return
- if(href_list["view_comment"])
- if(!human_user.canUseHUD())
- return
- if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
- return
- to_chat(human_user, "Comments/Log: ")
- var/counter = 1
- while(sec_record.fields[text("com_[]", counter)]) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- to_chat(human_user, sec_record.fields[text("com_[]", counter)]) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- to_chat(human_user, "----------")
- counter++
- return
+ target_record.security_note = new_note
- if(href_list["add_comment"])
- var/t1 = tgui_input_text(human_user, "Add a comment", "Security Records", multiline = TRUE)
- if (!sec_record || !t1 || !allowed_access) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- return
- if(!human_user.canUseHUD())
- return
- if(!HAS_TRAIT(human_user, TRAIT_SECURITY_HUD))
- return
- var/counter = 1
- while(sec_record.fields[text("com_[]", counter)]) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- counter++
- sec_record.fields[text("com_[]", counter)] = text("Made by [] on [] [], [] []", allowed_access, station_time_timestamp(), time2text(world.realtime, "MMM DD"), CURRENT_STATION_YEAR, t1) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- to_chat(human_user, span_notice("Successfully added comment."))
return
//SKYRAT EDIT ADDITION BEGIN - VIEW RECORDS
if(href_list["bgrecords"])
if(isobserver(usr) || usr.mind.can_see_exploitables || usr.mind.has_exploitables_override)
var/examined_name = get_face_name(get_id_name(""))
- var/datum/data/record/target_general_records = find_record("name", examined_name, GLOB.data_core.general)
- to_chat(usr, "Background information: [target_general_records.fields["background_records"]]")
+ var/datum/record/crew/target_record = find_record(examined_name)
+ to_chat(usr, "Background information: [target_record.background_information]")
if(href_list["exprecords"])
if(isobserver(usr) || usr.mind.can_see_exploitables || usr.mind.has_exploitables_override)
var/examined_name = get_face_name(get_id_name("")) //Named as such because this is the name we see when we examine
- var/datum/data/record/target_general_records = find_record("name", examined_name, GLOB.data_core.general)
- to_chat(usr, "Exploitable information: [target_general_records.fields["exploitable_records"]]")
+ var/datum/record/crew/target_record = find_record(examined_name)
+ to_chat(usr, "Exploitable information: [target_record.exploitable_information]")
//SKYRAT EDIT END
..() //end of this massive fucking chain. TODO: make the hud chain not spooky. - Yeah, great job doing that.
@@ -474,17 +388,16 @@
//Check for arrest warrant
if(judgement_criteria & JUDGE_RECORDCHECK)
var/perpname = get_face_name(get_id_name())
- var/datum/data/record/sec_record = find_record("name", perpname, GLOB.data_core.security) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
-
- if(sec_record?.fields["criminal"]) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- switch(sec_record.fields["criminal"]) //SKYRAT EDIT CHANGE - EXAMINE RECORDS
- if("*Arrest*")
+ var/datum/record/crew/record = find_record(perpname)
+ if(record?.wanted_status)
+ switch(record.wanted_status)
+ if(WANTED_ARREST)
threatcount += 5
- if("Incarcerated")
+ if(WANTED_PRISONER)
threatcount += 2
- if("Suspected")
+ if(WANTED_SUSPECT)
threatcount += 2
- if("Paroled")
+ if(WANTED_PAROLE)
threatcount += 2
//Check for dresscode violations
@@ -744,11 +657,14 @@
return TRUE
//SKYRAT ERP UPDATE ADDITION END
-/mob/living/carbon/human/replace_records_name(oldname,newname) // Only humans have records right now, move this up if changed.
- for(var/list/L in list(GLOB.data_core.general,GLOB.data_core.medical,GLOB.data_core.security,GLOB.data_core.locked))
- var/datum/data/record/general_record = find_record("name", oldname, L)
- if(general_record)
- general_record.fields["name"] = newname
+/mob/living/carbon/human/replace_records_name(oldname, newname) // Only humans have records right now, move this up if changed.
+ var/datum/record/crew/crew_record = find_record(oldname)
+ var/datum/record/locked/locked_record = find_record(oldname, locked_only = TRUE)
+
+ if(crew_record)
+ crew_record.name = newname
+ if(locked_record)
+ locked_record.name = newname
/mob/living/carbon/human/update_health_hud()
if(!client || !hud_used)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index a5f3bfc21ef..d7ac65f12ee 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -661,8 +661,8 @@
if("Station Member")
var/list/personnel_list = list()
- for(var/datum/data/record/record_datum in GLOB.data_core.locked)//Look in data core locked.
- personnel_list["[record_datum.fields["name"]]: [record_datum.fields["rank"]]"] = record_datum.fields["character_appearance"]//Pull names, rank, and image.
+ for(var/datum/record/crew/record in GLOB.manifest.locked)//Look in data core locked.
+ personnel_list["[record.name]: [record.rank]"] = record.character_appearance//Pull names, rank, and image.
if(!length(personnel_list))
tgui_alert(usr,"No suitable records found. Aborting.")
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index df83b4396a0..9c64a3fa893 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1069,7 +1069,7 @@
/**
* Fully update the name of a mob
*
- * This will update a mob's name, real_name, mind.name, GLOB.data_core records, pda, id and traitor text
+ * This will update a mob's name, real_name, mind.name, GLOB.manifest records, pda, id and traitor text
*
* Calling this proc without an oldname will only update the mob and skip updating the pda, id and records ~Carn
*/
@@ -1112,7 +1112,7 @@
return TRUE
-///Updates GLOB.data_core records with new name , see mob/living/carbon/human
+///Updates GLOB.manifest records with new name , see mob/living/carbon/human
/mob/proc/replace_records_name(oldname,newname)
return
diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm
index fb21969726c..769865bce01 100644
--- a/code/modules/modular_computers/file_system/programs/card.dm
+++ b/code/modules/modular_computers/file_system/programs/card.dm
@@ -133,7 +133,7 @@
// Eject the ID being modified.
if("PRG_ejectmodid")
if(inserted_auth_card)
- GLOB.data_core.manifest_modify(inserted_auth_card.registered_name, inserted_auth_card.assignment, inserted_auth_card.get_trim_assignment())
+ GLOB.manifest.modify(inserted_auth_card.registered_name, inserted_auth_card.assignment, inserted_auth_card.get_trim_assignment())
return computer.RemoveID(usr)
else
var/obj/item/I = user.get_active_held_item()
diff --git a/code/modules/modular_computers/file_system/programs/crewmanifest.dm b/code/modules/modular_computers/file_system/programs/crewmanifest.dm
index 63c09d33d5d..345bee97d90 100644
--- a/code/modules/modular_computers/file_system/programs/crewmanifest.dm
+++ b/code/modules/modular_computers/file_system/programs/crewmanifest.dm
@@ -13,7 +13,7 @@
/datum/computer_file/program/crew_manifest/ui_static_data(mob/user)
var/list/data = get_header_data()
- data["manifest"] = GLOB.data_core.get_manifest()
+ data["manifest"] = GLOB.manifest.get_manifest()
return data
/datum/computer_file/program/crew_manifest/ui_act(action, params, datum/tgui/ui)
@@ -26,7 +26,7 @@
if(computer) //This option should never be called if there is no printer
var/contents = {"Crew Manifest
- [GLOB.data_core ? GLOB.data_core.get_manifest_html(0) : ""]
+ [GLOB.manifest ? GLOB.manifest.get_html(0) : ""]
"}
if(!computer.print_text(contents,text("crew manifest ([])", station_time_timestamp())))
to_chat(usr, span_notice("Printer is out of paper."))
diff --git a/code/modules/modular_computers/file_system/programs/records.dm b/code/modules/modular_computers/file_system/programs/records.dm
index e0329103814..15da0d8f61b 100644
--- a/code/modules/modular_computers/file_system/programs/records.dm
+++ b/code/modules/modular_computers/file_system/programs/records.dm
@@ -35,32 +35,27 @@
switch(mode)
if("security")
- for(var/datum/data/record/person in GLOB.data_core.general)
- var/datum/data/record/security_person = find_record("id", person.fields["id"], GLOB.data_core.security)
+ for(var/datum/record/crew/person in GLOB.manifest.general)
var/list/current_record = list()
- if(security_person)
- current_record["wanted"] = security_person.fields["criminal"]
-
- current_record["id"] = person.fields["id"]
- current_record["name"] = person.fields["name"]
- current_record["rank"] = person.fields["rank"]
- current_record["gender"] = person.fields["gender"]
- current_record["age"] = person.fields["age"]
- current_record["species"] = person.fields["species"]
- current_record["fingerprint"] = person.fields["fingerprint"]
+ current_record["age"] = person.age
+ current_record["fingerprint"] = person.fingerprint
+ current_record["gender"] = person.gender
+ current_record["name"] = person.name
+ current_record["rank"] = person.rank
+ current_record["species"] = person.species
+ current_record["wanted"] = person.wanted_status
all_records += list(current_record)
if("medical")
- for(var/datum/data/record/person in GLOB.data_core.medical)
+ for(var/datum/record/crew/person in GLOB.manifest.general)
var/list/current_record = list()
- current_record["name"] = person.fields["name"]
- current_record["bloodtype"] = person.fields["blood_type"]
- current_record["mi_dis"] = person.fields["mi_dis"]
- current_record["ma_dis"] = person.fields["ma_dis"]
- current_record["notes"] = person.fields["notes"]
- current_record["cnotes"] = person.fields["notes_d"]
+ current_record["bloodtype"] = person.blood_type
+ current_record["ma_dis"] = person.major_disabilities_desc
+ current_record["minor_disabilities"] = person.minor_disabilities_desc
+ current_record["name"] = person.name
+ current_record["notes"] = person.medical_notes
all_records += list(current_record)
diff --git a/code/modules/modular_computers/file_system/programs/robocontrol.dm b/code/modules/modular_computers/file_system/programs/robocontrol.dm
index 80bba20cfd1..fe053b7cc25 100644
--- a/code/modules/modular_computers/file_system/programs/robocontrol.dm
+++ b/code/modules/modular_computers/file_system/programs/robocontrol.dm
@@ -121,7 +121,7 @@
if(!computer || !computer.computer_id_slot)
return
if(id_card)
- GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment, id_card.get_trim_assignment())
+ GLOB.manifest.modify(id_card.registered_name, id_card.assignment, id_card.get_trim_assignment())
computer.RemoveID(usr)
else
playsound(get_turf(ui_host()) , 'sound/machines/buzz-sigh.ogg', 25, FALSE)
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index 52327092e03..0c49a6b1cad 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -124,14 +124,13 @@
var/virgin = TRUE
/obj/structure/filingcabinet/security/proc/populate()
- if(virgin)
- for(var/datum/data/record/G in GLOB.data_core.general)
- var/datum/data/record/S = find_record("name", G.fields["name"], GLOB.data_core.security)
- if(!S)
- continue
- print_security_record(G, S, src)
- virgin = FALSE //tabbing here is correct- it's possible for people to try and use it
- //before the records have been generated, so we do this inside the loop.
+ if(!virgin)
+ return
+ for(var/datum/record/crew/target in GLOB.manifest.general)
+ var/obj/item/paper/rapsheet = target.get_rapsheet()
+ rapsheet.forceMove(src)
+ virgin = FALSE //tabbing here is correct- it's possible for people to try and use it
+ //before the records have been generated, so we do this inside the loop.
/obj/structure/filingcabinet/security/attack_hand(mob/user, list/modifiers)
populate()
@@ -149,24 +148,18 @@
var/virgin = TRUE
/obj/structure/filingcabinet/medical/proc/populate()
- if(virgin)
- for(var/datum/data/record/G in GLOB.data_core.general)
- var/datum/data/record/M = find_record("name", G.fields["name"], GLOB.data_core.medical)
- if(!M)
- continue
- var/obj/item/paper/med_record_paper = new /obj/item/paper(src)
- var/med_record_text = "Medical Record "
- med_record_text += "Name: [G.fields["name"]] ID: [G.fields["id"]] \nGender: [G.fields["gender"]] \nAge: [G.fields["age"]] \nFingerprint: [G.fields["fingerprint"]] \nPhysical Status: [G.fields["p_stat"]] \nMental Status: [G.fields["m_stat"]] "
- med_record_text += " \nMedical Data \nBlood Type: [M.fields["blood_type"]] \nDNA: [M.fields["b_dna"]] \n \nMinor Disabilities: [M.fields["mi_dis"]] \nDetails: [M.fields["mi_dis_d"]] \n \nMajor Disabilities: [M.fields["ma_dis"]] \nDetails: [M.fields["ma_dis_d"]] \n \nAllergies: [M.fields["alg"]] \nDetails: [M.fields["alg_d"]] \n \nCurrent Diseases: [M.fields["cdi"]] (per disease info placed in log/comment section) \nDetails: [M.fields["cdi_d"]] \n \nImportant Notes: \n\t[M.fields["notes"]] \n \nComments/Log "
- var/counter = 1
- while(M.fields["com_[counter]"])
- med_record_text += "[M.fields["com_[counter]"]] "
- counter++
- med_record_text += ""
- med_record_paper.add_raw_text(med_record_text)
- med_record_paper.name = "paper - '[G.fields["name"]]'"
- med_record_paper.update_appearance()
- virgin = FALSE //tabbing here is correct- it's possible for people to try and use it
+ if(!virgin)
+ return
+ for(var/datum/record/crew/record in GLOB.manifest.general)
+ var/obj/item/paper/med_record_paper = new /obj/item/paper(src)
+ var/med_record_text = "Medical Record "
+ med_record_text += "Name: [record.name] Rank: [record.rank] \nGender: [record.gender] \nAge: [record.age] "
+ med_record_text += " \nMedical Data \nBlood Type: [record.blood_type] \nDNA: [record.dna_string] \n \nMinor Disabilities: [record.minor_disabilities] \nDetails: [record.minor_disabilities_desc] \n \nMajor Disabilities: [record.major_disabilities] \nDetails: [record.major_disabilities_desc] \n \nImportant Notes: \n\t[record.medical_notes] \n \nComments/Log "
+ med_record_text += ""
+ med_record_paper.add_raw_text(med_record_text)
+ med_record_paper.name = "paper - '[record.name]'"
+ med_record_paper.update_appearance()
+ virgin = FALSE //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
//ATTACK HAND IGNORING PARENT RETURN VALUE
@@ -199,14 +192,10 @@ GLOBAL_LIST_EMPTY(employmentCabinets)
/obj/structure/filingcabinet/employment/proc/fillCurrent()
//This proc fills the cabinet with the current crew.
- for(var/record in GLOB.data_core.locked)
- var/datum/data/record/G = record
- if(!G)
- continue
- var/datum/mind/M = G.fields["mindref"]
- if(M && ishuman(M.current))
- addFile(M.current)
-
+ for(var/datum/record/locked/target in GLOB.manifest.locked)
+ var/datum/mind/mind_ref = target.mind_ref
+ if(mind_ref && ishuman(mind_ref.current))
+ addFile(mind_ref.current)
/obj/structure/filingcabinet/employment/proc/addFile(mob/living/carbon/human/employee)
new /obj/item/paper/employment_contract(src, employee.mind.name)
diff --git a/modular_skyrat/master_files/code/datums/id_trim/jobs.dm b/modular_skyrat/master_files/code/datums/id_trim/jobs.dm
index 85e2783de40..049d619b0e0 100644
--- a/modular_skyrat/master_files/code/datums/id_trim/jobs.dm
+++ b/modular_skyrat/master_files/code/datums/id_trim/jobs.dm
@@ -52,13 +52,12 @@
trim_state = "trim_blueshield"
department_color = COLOR_COMMAND_BLUE
subdepartment_color = COLOR_CENTCOM_BLUE // Not the other way around. I think.
- orbit_icon = "shield-dog"
sechud_icon_state = SECHUD_BLUESHIELD
extra_access = list(ACCESS_SECURITY, ACCESS_BRIG, ACCESS_COURT, ACCESS_CARGO, ACCESS_GATEWAY) // Someone needs to come back and order these alphabetically, this is a nightmare
minimal_access = list(
ACCESS_DETECTIVE, ACCESS_BRIG_ENTRANCE, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_ENGINEERING, ACCESS_MAINT_TUNNELS, ACCESS_RESEARCH,
ACCESS_RC_ANNOUNCE, ACCESS_COMMAND, ACCESS_WEAPONS,
- )
+ )
minimal_wildcard_access = list(ACCESS_CAPTAIN)
template_access = list(ACCESS_CAPTAIN, ACCESS_CHANGE_IDS)
@@ -67,7 +66,6 @@
trim_state = "trim_centcom"
department_color = COLOR_GREEN
subdepartment_color = COLOR_GREEN
- orbit_icon = "clipboard-check"
sechud_icon_state = SECHUD_NT_CONSULTANT
extra_access = list()
minimal_access = list(ACCESS_SECURITY, ACCESS_BRIG_ENTRANCE, ACCESS_COURT, ACCESS_WEAPONS,
@@ -84,7 +82,6 @@
assignment = "Security Medic"
trim_icon = 'modular_skyrat/master_files/icons/obj/card.dmi'
trim_state = "trim_securitymedic"
- orbit_icon = "heart-pulse"
department_color = COLOR_ASSEMBLY_BLACK
subdepartment_color = COLOR_ASSEMBLY_BLACK
sechud_icon_state = SECHUD_SECURITY_MEDIC
@@ -103,7 +100,6 @@
assignment = "Corrections Officer"
trim_icon = 'modular_skyrat/master_files/icons/obj/card.dmi'
trim_state = "trim_corrections_officer"
- orbit_icon = "hands-bound"
department_color = COLOR_ASSEMBLY_BLACK
subdepartment_color = COLOR_ASSEMBLY_BLACK
sechud_icon_state = SECHUD_CORRECTIONS_OFFICER
@@ -119,7 +115,6 @@
trim_state = "trim_barber"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SERVICE_LIME
- orbit_icon = "scissors"
sechud_icon_state = SECHUD_BARBER
extra_access = list()
minimal_access = list(ACCESS_THEATRE, ACCESS_MAINT_TUNNELS, ACCESS_BARBER, ACCESS_SERVICE)
diff --git a/modular_skyrat/master_files/code/datums/records/record.dm b/modular_skyrat/master_files/code/datums/records/record.dm
new file mode 100644
index 00000000000..2b4897d86a5
--- /dev/null
+++ b/modular_skyrat/master_files/code/datums/records/record.dm
@@ -0,0 +1,11 @@
+/datum/record/crew
+ /// Contains their background information.
+ var/background_information
+ /// Contains their exploitable information.
+ var/exploitable_information
+ /// Contains their own custom past general records.
+ var/past_general_records
+ /// Contains their own custom past medical records.
+ var/past_medical_records
+ /// Contains their own custom past security records.
+ var/past_security_records
diff --git a/modular_skyrat/modules/contractor/code/datums/contract.dm b/modular_skyrat/modules/contractor/code/datums/contract.dm
index 155aee20caf..f86843c85ae 100644
--- a/modular_skyrat/modules/contractor/code/datums/contract.dm
+++ b/modular_skyrat/modules/contractor/code/datums/contract.dm
@@ -30,12 +30,12 @@
/datum/syndicate_contract/proc/generate(blacklist)
contract.find_target(null, blacklist)
- var/datum/data/record/record
+ var/datum/record/crew/record
if (contract.target)
- record = find_record("name", contract.target.name, GLOB.data_core.general)
+ record = find_record(contract.target.name)
if (record)
- target_rank = record.fields["rank"]
+ target_rank = record.rank
else
target_rank = "Unknown"
diff --git a/modular_skyrat/modules/contractor/code/datums/contractor_hub.dm b/modular_skyrat/modules/contractor/code/datums/contractor_hub.dm
index c7853d969a1..130cd3d2a4b 100644
--- a/modular_skyrat/modules/contractor/code/datums/contractor_hub.dm
+++ b/modular_skyrat/modules/contractor/code/datums/contractor_hub.dm
@@ -45,8 +45,8 @@
)
//What the fuck
- if(length(to_generate) > length(GLOB.data_core.locked))
- to_generate.Cut(1, length(GLOB.data_core.locked))
+ if(length(to_generate) > length(GLOB.manifest.locked))
+ to_generate.Cut(1, length(GLOB.manifest.locked))
var/total = 0
var/lowest_paying_sum = 0
diff --git a/modular_skyrat/modules/cryosleep/code/cryopod.dm b/modular_skyrat/modules/cryosleep/code/cryopod.dm
index fb9f22d5405..da05a5740bb 100644
--- a/modular_skyrat/modules/cryosleep/code/cryopod.dm
+++ b/modular_skyrat/modules/cryosleep/code/cryopod.dm
@@ -165,6 +165,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/cryopod, 32)
/// What was the ckey of the client that entered the cryopod?
var/stored_ckey = null
+ /// The name of the mob that entered the cryopod.
+ var/stored_name = null
+ /// The rank (job title) of the mob that entered the cryopod, if it was a human. "N/A" by default.
+ var/stored_rank = "N/A"
+
/obj/machinery/cryopod/quiet
quiet = TRUE
@@ -210,6 +215,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/cryopod, 32)
if(mob_occupant && mob_occupant.stat != DEAD)
to_chat(occupant, span_notice("You feel cool air surround you. You go numb as your senses turn inward. "))
stored_ckey = mob_occupant.ckey
+ stored_name = mob_occupant.name
+
+ if(mob_occupant.mind)
+ stored_rank = mob_occupant.mind.assigned_role.title
COOLDOWN_START(src, despawn_world_time, time_till_despawn)
@@ -219,6 +228,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/cryopod, 32)
name = initial(name)
tucked = FALSE
stored_ckey = null
+ stored_name = null
+ stored_rank = "N/A"
/obj/machinery/cryopod/container_resist_act(mob/living/user)
visible_message(span_notice("[occupant] emerges from [src]!"),
@@ -305,55 +316,46 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/cryopod, 32)
return TRUE
return FALSE
-// This function can not be undone; do not call this unless you are sure
+/// This function can not be undone; do not call this unless you are sure.
+/// Handles despawning the player.
/obj/machinery/cryopod/proc/despawn_occupant()
var/mob/living/mob_occupant = occupant
- var/list/crew_member = list()
if(ishuman(occupant))
var/mob/living/carbon/human/human = occupant
human.save_individual_persistence()
- crew_member["name"] = mob_occupant.real_name
+ SSjob.FreeRole(stored_rank)
if(mob_occupant.mind)
- // Handle job slot/tater cleanup.
- var/job = mob_occupant.mind.assigned_role.title
- crew_member["job"] = job
- SSjob.FreeRole(job)
+ // Handle tater cleanup.
if(LAZYLEN(mob_occupant.mind.objectives))
mob_occupant.mind.objectives.Cut()
mob_occupant.mind.special_role = null
if(mob_occupant.mind.holy_role == HOLY_ROLE_HIGHPRIEST)
reset_religion() // Reset religion to its default state so the new chaplain becomes high priest and can change the sect, armor, weapon type, etc
- else
- crew_member["job"] = "N/A"
// Delete them from datacore and ghost records.
var/announce_rank = null
- for(var/datum/data/record/record as anything in GLOB.ghost_records)
- if(record.fields["name"] == mob_occupant.real_name)
- announce_rank = record.fields["rank"]
- GLOB.ghost_records.Remove(record)
- qdel(record)
+ for(var/list/record in GLOB.ghost_records)
+ if(record["name"] == stored_name)
+ announce_rank = record["rank"]
+ GLOB.ghost_records.Remove(list(record))
+ break
- for(var/datum/data/record/medical_record as anything in GLOB.data_core.medical)
- if(medical_record.fields["name"] == mob_occupant.real_name)
- qdel(medical_record)
- for(var/datum/data/record/security_record as anything in GLOB.data_core.security)
- if(security_record.fields["name"] == mob_occupant.real_name)
- qdel(security_record)
- for(var/datum/data/record/general_record as anything in GLOB.data_core.general)
- if(general_record.fields["name"] == mob_occupant.real_name)
- announce_rank = general_record.fields["rank"]
- qdel(general_record)
+ if(!announce_rank) // No need to loop over all of those if we already found it beforehand.
+ for(var/datum/record/crew/possible_target_record as anything in GLOB.manifest.general)
+ if(possible_target_record.name == stored_name && (stored_rank == "N/A" || possible_target_record.trim == stored_rank))
+ announce_rank = possible_target_record.rank
+ qdel(possible_target_record)
+ break
var/obj/machinery/computer/cryopod/control_computer = control_computer_weakref?.resolve()
if(!control_computer)
control_computer_weakref = null
else
- control_computer.frozen_crew += list(crew_member)
+ control_computer.frozen_crew += list(list("name" = stored_name, "job" = stored_rank))
// Make an announcement and log the person entering storage. If set to quiet, does not make an announcement.
if(!quiet)
@@ -540,16 +542,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/cryopod/prison, 18)
/// For figuring out where the local cryopod computer is. Must be set for cryo computer announcements.
var/area/computer_area
-/obj/effect/mob_spawn/ghost_role/special(mob/living/spawned_mob, mob/mob_possessor)
- . = ..()
+/obj/effect/mob_spawn/ghost_role/create(mob/mob_possessor, newname)
+ var/mob/living/spawned_mob = ..()
var/obj/machinery/computer/cryopod/control_computer = find_control_computer()
- var/datum/data/record/record = new
- record.fields["name"] = spawned_mob.real_name
- record.fields["rank"] = name
- GLOB.ghost_records.Add(record)
+ GLOB.ghost_records.Add(list(list("name" = spawned_mob.real_name, "rank" = name)))
if(control_computer)
control_computer.announce("CRYO_JOIN", spawned_mob.real_name, name)
+ return spawned_mob
+
/obj/effect/mob_spawn/ghost_role/proc/find_control_computer()
if(!computer_area)
return
diff --git a/modular_skyrat/modules/goofsec/code/department_guards.dm b/modular_skyrat/modules/goofsec/code/department_guards.dm
index 0faf95b58cf..833e929f938 100644
--- a/modular_skyrat/modules/goofsec/code/department_guards.dm
+++ b/modular_skyrat/modules/goofsec/code/department_guards.dm
@@ -214,7 +214,6 @@
trim_state = "trim_calhoun"
department_color = COLOR_SCIENCE_PINK
subdepartment_color = COLOR_SCIENCE_PINK
- orbit_icon = "shield-heart"
sechud_icon_state = SECHUD_SCIENCE_GUARD
extra_access = list(
ACCESS_AUX_BASE,
@@ -319,7 +318,6 @@
trim_state = "trim_orderly"
department_color = COLOR_MEDICAL_BLUE
subdepartment_color = COLOR_MEDICAL_BLUE
- orbit_icon = "shield-heart"
sechud_icon_state = SECHUD_ORDERLY
extra_access = list(
ACCESS_BRIG_ENTRANCE,
@@ -417,7 +415,6 @@
trim_state = "trim_engiguard"
department_color = COLOR_ENGINEERING_ORANGE
subdepartment_color = COLOR_ENGINEERING_ORANGE
- orbit_icon = "shield-heart"
sechud_icon_state = SECHUD_ENGINEERING_GUARD
extra_access = list(
ACCESS_ATMOSPHERICS,
@@ -521,7 +518,6 @@
trim_state = "trim_customs"
department_color = COLOR_CARGO_BROWN
subdepartment_color = COLOR_CARGO_BROWN
- orbit_icon = "shield-heart"
sechud_icon_state = SECHUD_CUSTOMS_AGENT
extra_access = list(
ACCESS_BRIG_ENTRANCE,
@@ -617,7 +613,6 @@
assignment = "Bouncer"
trim_icon = 'modular_skyrat/master_files/icons/obj/card.dmi'
trim_state = "trim_bouncer"
- orbit_icon = "shield-heart"
department_color = COLOR_SERVICE_LIME
subdepartment_color = COLOR_SERVICE_LIME // Personally speaking I'd have one of these with sec colors but I'm being authentic
sechud_icon_state = SECHUD_BOUNCER
diff --git a/modular_skyrat/modules/records_on_examine/code/record_manifest.dm b/modular_skyrat/modules/records_on_examine/code/record_manifest.dm
index 2ad6d7ea030..a0e7af41628 100644
--- a/modular_skyrat/modules/records_on_examine/code/record_manifest.dm
+++ b/modular_skyrat/modules/records_on_examine/code/record_manifest.dm
@@ -1,47 +1,60 @@
+/// A datum that's mainly used to get exploitables for antagonists.
/datum/record_manifest
-/datum/datacore/proc/get_exploitable_manifest()
+/// Proc that returns a list of all the exploitables there is currently.
+/datum/manifest/proc/get_exploitable_manifest()
var/list/exp_manifest_out = list()
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
exp_manifest_out[department.department_name] = list()
+
exp_manifest_out[DEPARTMENT_UNASSIGNED] = list()
var/list/departments_by_type = SSjob.joinable_departments_by_type
- for(var/datum/data/record/general_record in GLOB.data_core.general)
- var/exploitables = general_record.fields["exploitable_records"]
+
+ for(var/datum/record/crew/crew_record in GLOB.manifest.general)
+ var/exploitables = crew_record.exploitable_information
+
var/exploitables_empty = ((length(exploitables) < 1) || ((exploitables) == EXPLOITABLE_DEFAULT_TEXT))
+
if (exploitables_empty)
continue
- var/name = general_record.fields["name"]
- var/rank = general_record.fields["rank"]
-// var/truerank = general_record.fields["truerank"]
+
+ var/name = crew_record.name
+ var/rank = crew_record.rank
+// var/truerank = crew_record.truerank
var/datum/job/job = SSjob.GetJob(rank)
+
if(!job || !(job.job_flags & JOB_CREW_MANIFEST) || !LAZYLEN(job.departments_list) && (!exploitables_empty)) // In case an unlawful custom rank is added.
var/list/exp_misc_list = exp_manifest_out[DEPARTMENT_UNASSIGNED]
exp_misc_list[++exp_misc_list.len] = list(
"name" = name,
"rank" = rank,
// "truerank" = truerank,
- "exploitable_records" = exploitables,
- )
+ "exploitable_information" = exploitables,
+ )
continue
+
for(var/department_type as anything in job.departments_list)
var/datum/job_department/department = departments_by_type[department_type]
+
if(!department)
stack_trace("get_exploitable_manifest() failed to get job department for [department_type] of [job.type]")
continue
+
var/list/exp_entry = list(
"name" = name,
"rank" = rank,
// "truerank" = truerank,
- "exploitable_records" = exploitables,
- )
+ "exploitable_information" = exploitables,
+ )
+
var/list/exp_department_list = exp_manifest_out[department.department_name]
+
if(istype(job, department.department_head))
exp_department_list.Insert(1, null)
exp_department_list[1] = exp_entry
else
- exp_department_list[++exp_department_list.len] = exp_entry
+ exp_department_list[length(exp_department_list) + 1] = exp_entry
// Trim the empty categories.
for (var/department in exp_manifest_out)
@@ -50,6 +63,7 @@
return exp_manifest_out
+
/datum/record_manifest/ui_state(mob/user)
return GLOB.always_state
@@ -66,26 +80,32 @@
. = ..()
if(.)
return
+
if(action == "show_exploitables")
var/exploitable_id = params["exploitable_id"]
- var/datum/data/record/general_record = find_record("name", exploitable_id, GLOB.data_core.general)
- to_chat(usr, "Exploitable information: [general_record.fields["exploitable_records"]]")
+ var/datum/record/crew/target_record = find_record(exploitable_id)
+ to_chat(usr, "Exploitable information: [target_record.exploitable_information]")
+
else if(action == "show_background")
var/background_id = params["background_id"]
- var/datum/data/record/general_record = find_record("name", background_id, GLOB.data_core.general)
- to_chat(usr, "Background information: [general_record.fields["background_records"]]")
+ var/datum/record/crew/target_record = find_record(background_id)
+ to_chat(usr, "Background information: [target_record.background_information]")
+
/datum/record_manifest/ui_data(mob/user)
var/list/positions = list()
+
for(var/datum/job_department/department as anything in SSjob.joinable_departments)
var/list/exceptions = list()
+
for(var/datum/job/job as anything in department.department_jobs)
if(job.total_positions == -1)
exceptions += job.title
continue
+
positions[department.department_name] = list("exceptions" = exceptions)
return list(
- "manifest" = GLOB.data_core.get_exploitable_manifest(),
+ "manifest" = GLOB.manifest.get_exploitable_manifest(),
"positions" = positions
)
diff --git a/tgstation.dme b/tgstation.dme
index ef50598f2f3..6789ca9eed2 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -715,7 +715,6 @@
#include "code\datums\callback.dm"
#include "code\datums\chatmessage.dm"
#include "code\datums\dash_weapon.dm"
-#include "code\datums\datacore.dm"
#include "code\datums\datum.dm"
#include "code\datums\datumvars.dm"
#include "code\datums\dna.dm"
@@ -1389,6 +1388,11 @@
#include "code\datums\quirks\negative_quirks.dm"
#include "code\datums\quirks\neutral_quirks.dm"
#include "code\datums\quirks\positive_quirks.dm"
+#include "code\datums\records\crime.dm"
+#include "code\datums\records\data.dm"
+#include "code\datums\records\manifest.dm"
+#include "code\datums\records\medical_note.dm"
+#include "code\datums\records\record.dm"
#include "code\datums\ruins\icemoon.dm"
#include "code\datums\ruins\lavaland.dm"
#include "code\datums\ruins\space.dm"
@@ -5163,6 +5167,7 @@
#include "modular_skyrat\master_files\code\datums\quirks\_quirk.dm"
#include "modular_skyrat\master_files\code\datums\quirks\negative.dm"
#include "modular_skyrat\master_files\code\datums\quirks\neutral.dm"
+#include "modular_skyrat\master_files\code\datums\records\record.dm"
#include "modular_skyrat\master_files\code\datums\storage\storage.dm"
#include "modular_skyrat\master_files\code\datums\storage\subtypes\pockets.dm"
#include "modular_skyrat\master_files\code\datums\traits\good.dm"
diff --git a/tgui/packages/tgui/interfaces/JobSelection.tsx b/tgui/packages/tgui/interfaces/JobSelection.tsx
index aad103253bd..47289fa62b8 100644
--- a/tgui/packages/tgui/interfaces/JobSelection.tsx
+++ b/tgui/packages/tgui/interfaces/JobSelection.tsx
@@ -12,7 +12,6 @@ type Job = {
command: BooleanLike;
open_slots: number;
used_slots: number;
- icon: string;
prioritized: BooleanLike;
description: string;
};
@@ -43,7 +42,7 @@ export const JobEntry: SFC<{
const jobName = data.jobName;
const job = data.job;
const department = data.department;
- const jobIcon = job.icon || JOB2ICON[jobName] || null;
+ const jobIcon = JOB2ICON[jobName] || null;
return (
{
+ const foundRecord = getMedicalRecord(context);
+ if (!foundRecord) return <> >;
+
+ const { act } = useBackend(context);
+ const { crew_ref } = foundRecord;
+
+ const [selectedNote, setSelectedNote] = useLocalState<
+ MedicalNote | undefined
+ >(context, 'selectedNote', undefined);
+
+ const [writing, setWriting] = useLocalState(context, 'note', false);
+
+ const addNote = (event, value: string) => {
+ act('add_note', {
+ crew_ref: crew_ref,
+ content: value,
+ });
+ setWriting(false);
+ };
+
+ const deleteNote = () => {
+ if (!selectedNote) return;
+ act('delete_note', {
+ crew_ref: crew_ref,
+ note_ref: selectedNote.note_ref,
+ });
+ setSelectedNote(undefined);
+ };
+
+ return (
+ } fill scrollable title="Notes">
+ {writing && (
+