From f6af059a0619a22fa5d1a660a70a97e57e382b65 Mon Sep 17 00:00:00 2001
From: Metis <100518708+sheepishgoat@users.noreply.github.com>
Date: Sat, 2 Nov 2024 03:16:16 -0400
Subject: [PATCH] job titles
---
code/__HELPERS/game.dm | 5 +-
code/controllers/subsystem/job.dm | 5 +-
code/datums/datacore.dm | 10 +-
code/game/machinery/announcement_system.dm | 15 +--
code/modules/client/preferences.dm | 28 ++++-
code/modules/client/preferences_savefile.dm | 9 ++
code/modules/jobs/job_titles.dm | 109 ++++++++++++++++++
code/modules/jobs/job_types/_job.dm | 15 ++-
code/modules/jobs/job_types/captain.dm | 5 +-
.../modules/mob/dead/new_player/new_player.dm | 3 +
tgstation.dme | 1 +
11 files changed, 189 insertions(+), 16 deletions(-)
create mode 100644 code/modules/jobs/job_titles.dm
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index e177fa2860..cb68fe61fd 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -581,8 +581,11 @@
if((character.mind.assigned_role == "Cyborg") || (character.mind.assigned_role == character.mind.special_role))
return
+ var/displayed_rank = rank
+ if(character.client && character.client.prefs && character.client?.prefs?.alt_titles_preferences[rank])
+ displayed_rank = character.client?.prefs?.alt_titles_preferences[rank]
var/obj/machinery/announcement_system/announcer = pick(GLOB.announcement_systems)
- announcer.announce("ARRIVAL", character.real_name, rank, list()) //make the list empty to make it announce it in common
+ announcer.announce("ARRIVAL", character.real_name, displayed_rank, list()) //make the list empty to make it announce it in common
/proc/lavaland_equipment_pressure_check(turf/T)
. = FALSE
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index b8f5c68dee..af28f2edf3 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -464,7 +464,10 @@ SUBSYSTEM_DEF(job)
else
handle_auto_deadmin_roles(M.client, rank)
- to_chat(M, "You are the [rank].")
+ var/display_rank = rank
+ if(M.client && M.client.prefs && M.client?.prefs?.alt_titles_preferences[rank])
+ display_rank = M.client?.prefs?.alt_titles_preferences[rank]
+ to_chat(M, "You are the [display_rank].")
if(job)
to_chat(M, "As the [rank] you answer directly to [job.supervisors]. Special circumstances may change this.")
job.radio_help_message(M)
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index 8195666783..bb0f786fc5 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -138,12 +138,18 @@
var/static/list/show_directions = list(SOUTH, WEST)
if(H.mind && (H.mind.assigned_role != H.mind.special_role))
var/assignment
+ var/displayed_rank
if(H.mind.assigned_role)
assignment = H.mind.assigned_role
else if(H.job)
assignment = H.job
else
assignment = "Unassigned"
+ if(C && C.prefs && C.prefs.alt_titles_preferences[assignment])
+ assignment = C.prefs.alt_titles_preferences[assignment]
+
+ if(assignment)
+ displayed_rank = C.prefs.alt_titles_preferences[assignment]
var/static/record_id_num = 1001
var/id = num2hex(record_id_num++,6)
@@ -166,7 +172,7 @@
var/datum/data/record/G = new()
G.fields["id"] = id
G.fields["name"] = H.real_name
- G.fields["rank"] = assignment
+ G.fields["rank"] = displayed_rank
G.fields["age"] = H.age
G.fields["species"] = H.dna.species.name
G.fields["fingerprint"] = md5(H.dna.uni_identity)
@@ -213,7 +219,7 @@
var/datum/data/record/L = new()
L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others?
L.fields["name"] = H.real_name
- L.fields["rank"] = H.mind.assigned_role
+ L.fields["rank"] = displayed_rank
L.fields["age"] = H.age
if(H.gender == MALE)
G.fields["gender"] = "Male"
diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm
index d06366c021..1919d424ee 100644
--- a/code/game/machinery/announcement_system.dm
+++ b/code/game/machinery/announcement_system.dm
@@ -17,9 +17,9 @@ GLOBAL_LIST_EMPTY(announcement_systems)
circuit = /obj/item/circuitboard/machine/announcement_system
var/obj/item/radio/headset/radio
- var/arrival = "%PERSON has signed up as %RANK"
+ var/arrival = "%PERSON has signed up as %DISP_RANK (%RANK)"
var/arrivalToggle = TRUE
- var/newhead = "%PERSON, %RANK, is the department head."
+ var/newhead = "%PERSON, %DISP_RANK (%RANK), is the department head."
var/newheadToggle = TRUE
var/cryostorage = "%PERSON, %RANK, has been moved into cryogenic storage." // this shouldnt be changed
@@ -70,23 +70,24 @@ GLOBAL_LIST_EMPTY(announcement_systems)
else
return ..()
-/obj/machinery/announcement_system/proc/CompileText(str, user, rank) //replaces user-given variables with actual thingies.
+/obj/machinery/announcement_system/proc/CompileText(str, user, rank, displayed_rank) //replaces user-given variables with actual thingies.
str = replacetext(str, "%PERSON", "[user]")
str = replacetext(str, "%RANK", "[rank]")
+ str = replacetext(str, "%DISP_RANK", "[displayed_rank]")
return str
-/obj/machinery/announcement_system/proc/announce(message_type, user, rank, list/channels)
+/obj/machinery/announcement_system/proc/announce(message_type, user, rank, displayed_rank, list/channels)
if(!is_operational())
return
var/message
if(message_type == "ARRIVAL" && arrivalToggle)
- message = CompileText(arrival, user, rank)
+ message = CompileText(arrival, user, rank, displayed_rank)
else if(message_type == "NEWHEAD" && newheadToggle)
- message = CompileText(newhead, user, rank)
+ message = CompileText(newhead, user, rank, displayed_rank)
else if(message_type == "CRYOSTORAGE")
- message = CompileText(cryostorage, user, rank)
+ message = CompileText(cryostorage, user, rank, displayed_rank)
else if(message_type == "ARRIVALS_BROKEN")
message = "The arrivals shuttle has been damaged. Docking for repairs..."
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index ddf2d71cec..2f1234f46d 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -101,6 +101,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/pda_style = MONO
var/pda_color = "#808000"
var/pda_skin = PDA_SKIN_ALT
+ var/list/alt_titles_preferences = list()
var/uses_glasses_colour = 0
@@ -1449,6 +1450,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
HTML += "
| "
var/rank = job.title
+ var/displayed_rank = rank
+ if(job.alt_titles.len && (rank in alt_titles_preferences))
+ displayed_rank = alt_titles_preferences[rank]
lastJob = job
if(jobban_isbanned(user, rank))
HTML += "[rank] | BANNED |
"
@@ -1470,10 +1474,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if((job_preferences["[SSjob.overflow_role]"] == JP_LOW) && (rank != SSjob.overflow_role) && !jobban_isbanned(user, SSjob.overflow_role))
HTML += "[rank] | "
continue
+ var/rank_title_line = "[displayed_rank]"
if((rank in GLOB.command_positions) || (rank == "AI"))//Bold head jobs
- HTML += "[rank]"
+ rank_title_line = "[rank_title_line]"
+ if(job.alt_titles.len)
+ rank_title_line = "[rank_title_line]"
+
else
- HTML += "[rank]"
+ rank_title_line = "[rank_title_line]" //Make it dark if we're not adding a button for alt titles
+ HTML += rank_title_line
HTML += ""
@@ -1727,6 +1736,21 @@ GLOBAL_LIST_EMPTY(preferences_datums)
SetChoices(user)
if("setJobLevel")
UpdateJobPreference(user, href_list["text"], text2num(href_list["level"]))
+ if("alt_title")
+ var/job_title = href_list["job_title"]
+ var/titles_list = list(job_title)
+ var/datum/job/J = SSjob.GetJob(job_title)
+ for(var/i in J.alt_titles)
+ titles_list += i
+ var/chosen_title
+ chosen_title = input(user, "Choose your job's title:", "Job Preference") as null|anything in titles_list
+ if(chosen_title)
+ if(chosen_title == job_title)
+ if(alt_titles_preferences[job_title])
+ alt_titles_preferences.Remove(job_title)
+ else
+ alt_titles_preferences[job_title] = chosen_title
+ SetChoices(user)
else
SetChoices(user)
return TRUE
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 1f74ca9031..5ff539497d 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -910,6 +910,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(json_from_file)
belly_prefs = json_from_file["belly_prefs"]
+ S["alt_titles_preferences"] >> alt_titles_preferences
//gear loadout
if(istext(S["loadout"]))
loadout_data = safe_json_decode(S["loadout"])
@@ -1098,6 +1099,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
loadout_slot = sanitize_num_clamp(loadout_slot, 1, MAXIMUM_LOADOUT_SAVES, 1, TRUE)
+ alt_titles_preferences = SANITIZE_LIST(alt_titles_preferences)
+ if(SSjob)
+ for(var/datum/job/job in SSjob.occupations)
+ if(alt_titles_preferences[job.title])
+ if(!(alt_titles_preferences[job.title] in job.alt_titles))
+ alt_titles_preferences.Remove(job.title)
+
cit_character_pref_load(S)
return TRUE
@@ -1214,6 +1222,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["feature_butt_color"], features["butt_color"])
WRITE_FILE(S["feature_butt_size"], features["butt_size"])
WRITE_FILE(S["feature_butt_visibility"], features["butt_visibility"])
+ WRITE_FILE(S["alt_titles_preferences"], alt_titles_preferences)
WRITE_FILE(S["feature_ooc_notes"], features["ooc_notes"])
diff --git a/code/modules/jobs/job_titles.dm b/code/modules/jobs/job_titles.dm
new file mode 100644
index 0000000000..9f516940ae
--- /dev/null
+++ b/code/modules/jobs/job_titles.dm
@@ -0,0 +1,109 @@
+//This file also determines the order for the choose your occupation chances screen.
+
+//Engineering
+/datum/job/chief_engineer
+ alt_titles = list("Head Engineer", "Construction Coordinator", "Project Manager", "Power Plant Director")
+
+/datum/job/engineer
+ alt_titles = list("Maintenance Technician", "Engine Technician", "Electrician", "Structural Engineer", "Mechanic", "Station Architect", "Nuclear Plant Operator")
+
+/datum/job/atmos
+ alt_titles = list("Firefighter", "Life Support Specialist", "Disposals Technician")
+
+/datum/job/junior_engineer
+
+//Service
+/datum/job/assistant
+ alt_titles = list("Civilian", "Morale Officer", "Stripper", "Off-Duty", "Escort", "Visitor", "Businessman", "Trader", "Entertainer", "Tourist")
+
+/datum/job/cook
+ alt_titles = list("Cook", "Culinary Artist", "Butcher", "Chef de partie", "Poissonier", "Baker", "Taste Tester")
+
+/datum/job/hydro
+ alt_titles = list("Gardener", "Herbalist", "Botanical Researcher", "Hydroponicist", "Farmer", "Beekeeper", "Vintner")
+
+/datum/job/curator
+ alt_titles = list("Journalist", "Librarian", "Keeper")
+
+/datum/job/chaplain
+ alt_titles = list("Priest", "Priestess", "Prior", "Monk", "Nun", "Counselor")
+
+/datum/job/janitor
+ alt_titles = list("Custodian", "Sanitation Technician", "Maid", "Trash Can", "Disposal Unit")
+
+/datum/job/lawyer
+ alt_titles = list("Human Resources Agent", "Internal Affairs Agent", "Attorney")
+
+/datum/job/clown
+ alt_titles = list("Jester", "Comedian")
+
+/datum/job/mime
+ alt_titles = list("Performer", "Pantomime", "Mimic")
+
+/datum/job/bartender
+ alt_titles = list("Mixologist", "Sommelier", "Bar Owner", "Barmaid", "Expediter")
+
+//Science
+/datum/job/rd
+ alt_titles = list("Research Manager", "Science Administrator")
+
+/datum/job/scientist
+ alt_titles = list("Circuitry Designer", "Xenobiologist", "Xenobotanist", "Xenoarcheologist", "Chemical Researcher", "Researcher", "Pyrotechnician")
+
+/datum/job/roboticist
+ alt_titles = list("Biomechanical Engineer", "Mechatronic Engineer", "Mechanic")
+
+/datum/job/junior_scientist
+
+//Medical
+/datum/job/cmo
+ alt_titles = list("Medical Director", "Medical Administrator")
+
+/datum/job/doctor
+ alt_titles = list("Nurse", "Surgeon", "Physician", "Paramedic", "Trophologist", "Nutritionist")
+
+/datum/job/chemist
+ alt_titles = list("Pharmacist", "Pharmacologist")
+
+/datum/job/virologist
+ alt_titles = list("Microbiologist", "Biochemist", "Pathologist")
+
+/datum/job/geneticist
+ alt_titles = list("Gene Therapist", "Genetics Researcher")
+
+/datum/job/psychologist
+ alt_titles = list("Therapist", "Psychiatrist")
+
+/datum/job/junior_doctor
+
+//Security
+/datum/job/hos
+ alt_titles = list("Chief of Security", "Security Commander", "Sheriff")
+
+/datum/job/warden
+ alt_titles = list("Prison Chief", "Armory Manager", "Prison Administrator", "Brig Superintendent")
+
+/datum/job/officer
+ alt_titles = list("Security Agent", "Probation Officer", "Security Peacekeeper", "Security Guard", "Guardsman", "Security Cadet")
+
+/datum/job/detective
+ alt_titles = list("Forensics Technician", "Private Investigator", "Gumshoe")
+
+/datum/job/junior_officer
+
+//Supply
+/datum/job/qm
+ alt_titles = list("Supply Chief")
+
+/datum/job/cargo_tech
+ alt_titles = list("Mail Man", "Mail Woman", "Mailroom Technician", "Deliveries Officer", "Logistics Technician")
+
+/datum/job/mining
+ alt_titles = list("Exotic Ore Miner", "Fauna Hunter", "Explorer", "Digger") //Just because you're a hunter does not excuse you from rock collecting!!!!!!!!!!!!
+
+//Command
+/datum/job/captain
+ alt_titles = list("Station Director", "Station Commander", "Station Overseer", "Stationmaster", "Commissar")
+
+/datum/job/hop
+ alt_titles = list("Personnel Manager", "Staff Administrator", "Records Administrator")
diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm
index 969a39b560..f9140cfc43 100644
--- a/code/modules/jobs/job_types/_job.dm
+++ b/code/modules/jobs/job_types/_job.dm
@@ -63,6 +63,9 @@
var/list/mind_traits // Traits added to the mind of the mob assigned this job
var/list/blacklisted_quirks //list of quirk typepaths blacklisted.
+ /// What alternate titles does this job currently have?
+ var/list/alt_titles = list()
+
/// Should this job be allowed to be picked for the bureaucratic error event?
var/allow_bureaucratic_error = TRUE
@@ -211,7 +214,7 @@
/datum/job/proc/announce_head(var/mob/living/carbon/human/H, var/channels) //tells the given channel that the given mob is the new department head. See communications.dm for valid channels.
if(H && GLOB.announcement_systems.len)
//timer because these should come after the captain announcement
- SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(_addtimer), CALLBACK(pick(GLOB.announcement_systems), TYPE_PROC_REF(/obj/machinery/announcement_system, announce), "NEWHEAD", H.real_name, H.job, channels), 1))
+ SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(_addtimer), CALLBACK(pick(GLOB.announcement_systems), TYPE_PROC_REF(/obj/machinery/announcement_system, announce), "NEWHEAD", H.real_name, H.job, H.client?.prefs.alt_titles_preferences[H.job], channels), 1))
//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1
/datum/job/proc/player_old_enough(client/C)
@@ -314,7 +317,11 @@
shuffle_inplace(C.access) // Shuffle access list to make NTNet passkeys less predictable
C.registered_name = H.real_name
C.assignment = J.title
- C.update_label()
+ if(preference_source && preference_source.prefs && preference_source.prefs.alt_titles_preferences[J.title])
+ C.update_label(C.registered_name, preference_source.prefs.alt_titles_preferences[J.title])
+ else
+ C.update_label()
+
for(var/A in SSeconomy.bank_accounts)
var/datum/bank_account/B = A
if(B.account_id == H.account_id)
@@ -326,6 +333,10 @@
var/obj/item/pda/PDA = H.get_item_by_slot(pda_slot)
if(istype(PDA))
PDA.owner = H.real_name
+ if(preference_source && preference_source.prefs && preference_source.prefs.alt_titles_preferences[J.title])
+ PDA.ownjob = preference_source.prefs.alt_titles_preferences[J.title]
+ else
+ PDA.ownjob = J.title
PDA.ownjob = J.title
PDA.update_label()
if(preference_source && !PDA.equipped) //PDA's screen color, font style and look depend on client preferences.
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index fe594e4660..e217b3c0d2 100644
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -50,7 +50,10 @@
/datum/job/captain/announce(mob/living/carbon/human/H)
..()
- SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(minor_announce), "Captain [H.nameless ? "" : "[H.real_name] "]on deck!"))
+ var/displayed_rank = H.client?.prefs?.alt_titles_preferences[title]
+ if(!displayed_rank) //Default to Captain
+ displayed_rank = "Captain"
+ SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(minor_announce), "[displayed_rank] [H.nameless ? "" : "[H.real_name] "]on deck!"))
/datum/outfit/job/captain
name = "Captain"
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index b3811b8fef..330d9b36db 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -606,6 +606,9 @@
dept_dat += "[job_datum.title] ([num_positions_current]/[num_positions_total])"
else
dept_dat += "[job_datum.title] ([num_positions_current]/[num_positions_total])"
+ if(client && client.prefs && client?.prefs?.alt_titles_preferences[job_datum.title])
+ dept_dat += " (as [client?.prefs?.alt_titles_preferences[job_datum.title]])"
+
if(!dept_dat.len)
dept_dat += "No positions open."
dat += jointext(dept_dat, "")
diff --git a/tgstation.dme b/tgstation.dme
index 4a116ff9fd..0d49f689c2 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2472,6 +2472,7 @@
#include "code\modules\jobs\access.dm"
#include "code\modules\jobs\job_exp.dm"
#include "code\modules\jobs\job_report.dm"
+#include "code\modules\jobs\job_titles.dm"
#include "code\modules\jobs\jobs.dm"
#include "code\modules\jobs\job_types\_job.dm"
#include "code\modules\jobs\job_types\ai.dm"
|