Adds a new arcade game - NT Magistrate Simulator (#32111)

* Adds securitysim.dm, haven't yet changed anything from the default recruiter.dm

* Adds the relevant circuit board.

* Stage 1 of rewriting the code

* Renames securitysim.dmm to lawyersim.dmm to match the typepath

* Updates the DME with the new machine

* Reverting a change for testing purposes

* Adds the arcade machine to boxstation with a placeholder sprite for prototype testing

* Finished changing variable names preventing execution

* Adds a UI for the arcade game

* TGUI stuff

* Just a test

* Undoing testing

* Annother test

* Reverting test again

* Removes emagging and changes some wording

* Adds sprites

* Changes the sprite in the .dm to the new sprite.

* Adds random crime generation.

* Fixes the screwed-up RNG stuff

* Adds math and logic for sentencing calculation

* Fixes temporary sentences

* Adds in the "Manner of Arrest" text blurbs.

* Missed a comma.

* Minor grammar fixes

* Corrects a couple issues in the tgui menu.

* Updating branch to match main

* Reverts boxstation, preparing for official mapping

* Maps the arcade into every map

* Adds missing stolls and spawns in arcade remodels

* Making requested changes, part 1

* Prevents duplicate crimes

* Cleans up leftover placeholders

* Fixes apostrophe issues in TGUI

* Adds prevention for same-code crimes

* prettier maybe

* prettier maybe now

* bundle, fuck you tgui

* SPACES SUCK

* DIE, SPACES, DIE!

* Fixes DIRT! DIRT OF ALL THINGS! WHY IS THAT A PROBLEM!

* DIRT! AGAIN!

* Adds variable documentation

---------

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
AurouraPlays
2026-07-01 23:14:35 +00:00
committed by GitHub
co-authored by Burzah
parent 7512a0b4f8
commit 98559dc063
13 changed files with 664 additions and 22 deletions
@@ -0,0 +1,388 @@
#define PROB_CANDIDATE_ERRORS 8.3
#define PROB_MULTIPLE_CRIMES 40
#define PROB_UNIQUE_CANDIDATE 2
#define UNIQUE_MCTIDE 1
#define UNIQUE_CLING 2
#define UNIQUE_CEO_CHILD 3
#define UNIQUE_STEVE 4
// Defines for the game screens
#define LAWYER_STATUS_START 0
#define LAWYER_STATUS_INSTRUCTIONS 1
#define LAWYER_STATUS_NORMAL 2
#define LAWYER_STATUS_GAMEOVER 3
/obj/machinery/computer/arcade/lawyer
name = "\improper NT Magistrate Simulator"
desc = "Make sure Security is applying sentences correctly and restore order aboard the station!"
icon_state = "arcade_lawyer"
icon_screen = "nanotrasen"
light_color = LIGHT_COLOR_WHITE
circuit = /obj/item/circuitboard/arcade/lawyer
/// The name of the criminal
var/criminal_name
/// The species of the criminal, used for name generation
var/datum/species/cand_species
/// The criminal's job
var/criminal_job
/// The crimes the criminal committed
var/crimes_committed
/// The number of crimes, used for crime generation
var/crime_count
/// The sentence applied to the criminal, based on their crimes
var/sentencing
/// The running total for temporary crimes, used to determine sentencing
var/running_total
/// The name of the arresting officer
var/officer_name
/// The species of the arresting officer, used for name generation
var/datum/species/off_species
/// The station the crime took place on
var/station_location
/// The circumstances around the arrest
var/manner_of_arrest
/// Current "turn" of the game
var/curriculums
/// Total number of "turns" to win
var/total_curriculums = 7
/// Which unique candidate is he?
var/unique_candidate
// RNG variable
var/RandNum
/// Loop control variable
var/i
/// The crime about to be added to the full list, used for internal checks & math
var/new_crime
/// Valid stations
var/list/stations = list("NSS Cyberiad", "NSS Cerebron", "NSS Kerberos", "NSS Legaria", "NSS Farragus", "NSS Diagoras")
/// Stations with misspellings, don't support standard crew, or aren't stations at all.
var/list/incorrect_stations = list("Earth", "NAS Trurl", "NMS Inferno", "ISS Lexofficium", "NSS Cerberus",
"Nanotrasen HQ", "NSS Cyberad", "NSS Farragas", "KS13", "NSS Exodus")
/// Valid jobs
var/list/jobs = list("Assistant", "Chef", "Janitor", "Bartender", "Botanist", "Explorer", "Quartermaster",
"Station Engineer", "Atmospheric Technician", "Medical Doctor", "Coroner", "Geneticist", "Chaplain", "Librarian",
"Security Officer", "Detective", "Scientist", "Roboticist", "Shaft Miner", "Cargo Technician", "Internal Affairs Agent",
"Smith", "Mime")
/// Jobs that NT stations dont offer/mispelled
var/list/incorrect_jobs = list("Syndicate Operative", "Syndicate Researcher", "Veterinary", "Brig Physician",
"Pod Pilot", "Cremist", "Cluwne", "Work Safety Inspector", "Musician",
"Chauffeur", "Teacher", "Maid", "Plumber", "Trader", "Hobo", "NT CEO",
"Bridge Assistant", "Assitant", "Janittor", "Medical", "Generticist", "Baton Officer",
"Detecctive", "Sccientist", "Robocticist", "Cargo Tecchhnician", "Internal Afairs Agent",
"Wizard", "Nanotrasen Navy Officer", "Barber", "Ambassador", "Company Shareholder")
/// Valid 'Manner of Arrest' records
var/list/records = list("An investigation led to the suspect's arrest.", "Arresting officer witnessed the crime in progress.",
"Security investigation identified the suspect.", "Suspect matched witness descriptions.",
"Station cameras captured the offense.", "Security officers observed the violation.", "Evidence discovered during search.",
"Suspect detained following security alert.", "Witness testimony established probable cause.",
"Forensic analysis linked suspect to incident.", "Security received credible intelligence.", "Suspect apprehended after attempted evasion.",
"Incident review identified the suspect.", "Biometric records confirmed suspect identity.", "Security personnel responded to disturbance.",
"Unauthorized access triggered investigation.", "Suspect implicated by recovered evidence.", "Security operation resulted in arrest.",
"Suspect found within restricted area.", "Multiple witnesses identified the suspect.", "PDA records supported the investigation.",
"Security officers interrupted the crime.", "Investigation uncovered suspect involvement.", "Security officers executed arrest order.",
"Suspect violated SOP, leading to an arrest pending demotion.", "Evidence recovered from suspect workplace.",
"Security personnel observed prohibited conduct.", "Suspect connected to ongoing investigation.", "Audit logs revealed unauthorized activity.",
"Suspect identified by fibers left at the scene.", "Security officers acted on witness reports.", "Investigation established grounds for detention.",
"Suspect discovered concealing evidence.", "Sensor data implicated the suspect.", "Suspect detained after security interview.",
"Security personnel received an incident report.", "Suspect encountered during targeted search.",
"Suspect identified through surveillance review.", "Evidence supported immediate detention.", "Security investigation corroborated witness accounts.",
"Suspect arrested following Captain authorization.", "Suspect arrested following Head of Security authorization.")
/// Invalid 'Manner of Arrest' records
var/list/incorrect_records = list("Suspect appeared nervous during questioning.", "Suspect was present near the incident.", "Suspect became argumentative with security.",
"Suspect declined to answer questions.", "Suspect appeared to be in a hurry.", "Suspect's explanation seemed unlikely.",
"Suspect was observed loitering.", "Suspect questioned security procedures.",
"Suspect was carrying unusual equipment.", "Suspect appeared evasive when approached.", "Suspect refused to consent to a search.",
"Suspect was observed speaking quietly.", "Suspect changed direction upon seeing security.", "Suspect failed to appear cooperative.",
"Suspect's account differed from officer observations.", "Suspect refused to allow a search on Green",
"Suspect observed criticizing the decisions of their Head.", "Suspect was resistant towards questioning.",
"Suspect arrested following Nanotrasen Representative authorization.", "Suspect demanded a vote to demote the Head of their department.")
/// Species that are hirable in the eyes of NT. Used for name generation
var/list/hirable_species = list(/datum/species/human, /datum/species/unathi, /datum/species/skrell,
/datum/species/tajaran, /datum/species/kidan, /datum/species/drask,
/datum/species/diona, /datum/species/machine, /datum/species/slime,
/datum/species/moth, /datum/species/vox, /datum/species/skulk)
/// Valid minor crimes
var/list/minor_crimes = list("Damage to Station Assets" = 0, "Battery" = 2, "Drug Possession" = 3, "Indecent Exposure" = 5, "Abuse of Equipment" = 6,
"Petty Theft" = 7, "Trespass" = 8)
/// Valid medium crimes
var/list/medium_crimes = list("Workplace Hazard" = 0, "Kidnapping" = 1, "Assault" = 2, "Narcotics Distribution" = 3, "Possession of a Weapon" = 4,
"Rioting" = 5, "Abuse of Confiscated Equipment" = 6, "Robbery" = 7)
/// Valid major crimes
var/list/major_crimes = list("Sabotage" = 0, "Aggravated Assault" = 2, "Possession of a Restricted Weapon/Item" = 4, "Inciting a Riot" = 5,
"Theft" = 7, "Major Trespass" = 8) // Contraband was left off on purpose to avoid more complicated logic
/// Valid exceptional crimes
var/list/exceptional_crimes = list("Grand Sabotage" = 0, "Manslaughter" = 1, "Attempted Murder" = 2, "Grand Theft" = 7, "Enemy of the Corporation" = 9)
/// Valid capital crimes
var/list/capital_crimes = list("Murder" = 2, "Mutiny" = 5)
/// Crimes that are not valid under Space Law
var/list/invalid_crimes = list("Honking", "Cannibalism", "Grand Trespass", "Insulted Me", "Mass Murder", "Capital Theft",
"Impersonation", "Embezzlement", "Vandalism", "Cultist", "Loitering", "Criticizing Command")
/// Is the full record valid?
var/good_candidate = TRUE
/// Why did you lose?
var/reason
/// In which screen are we?
var/game_status = LAWYER_STATUS_START
/// Used to stop players from spamming the buttons
COOLDOWN_DECLARE(spam_cooldown)
/obj/machinery/computer/arcade/lawyer/proc/generate_candidate()
cand_species = pick(hirable_species)
criminal_name = random_name(species = initial(cand_species.name))
off_species = pick(hirable_species)
officer_name = random_name(species = initial(off_species.name))
if(prob(PROB_CANDIDATE_ERRORS)) // Station
station_location = pick(incorrect_stations)
good_candidate = FALSE
else
station_location = pick(stations)
if(prob(PROB_CANDIDATE_ERRORS)) // Criminal's Job
criminal_job = pick(incorrect_jobs)
good_candidate = FALSE
else
criminal_job = pick(jobs)
if(prob(PROB_CANDIDATE_ERRORS)) // Manner of Arrest
manner_of_arrest = pick(incorrect_records)
good_candidate = FALSE
else
manner_of_arrest = pick(records)
if(prob(PROB_CANDIDATE_ERRORS)) // Crimes committed
crimes_committed = pick(invalid_crimes)
good_candidate = FALSE
else
crimes_committed = ""
if(prob(PROB_MULTIPLE_CRIMES)) // 40% chance of having more than one
if(prob(PROB_MULTIPLE_CRIMES)) // 40% chance of having more than two
crime_count = 3
else
crime_count = 2
else
crime_count = 1
running_total = 0
/// Collects the crimes being applied for this record
var/list/list_crimes = list()
for(i=1, i<=crime_count, i++)
if(i!=1)
crimes_committed = addtext(crimes_committed, ", ")
RandNum = rand(1, 10)
switch(RandNum)
if(1, 2, 3)
new_crime = pick(minor_crimes)
if(!(minor_crimes[new_crime] in list_crimes))
crimes_committed = addtext(crimes_committed, new_crime)
list_crimes.Add(minor_crimes[new_crime])
if((running_total != "Execution") && (running_total != "Permanent Imprisonment"))
running_total = running_total + 5
if(4, 5)
new_crime = pick(medium_crimes)
if(!(medium_crimes[new_crime] in list_crimes))
crimes_committed = addtext(crimes_committed, new_crime)
list_crimes.Add(medium_crimes[new_crime])
if((running_total != "Execution") && (running_total != "Permanent Imprisonment"))
running_total = running_total + 10
if(6, 7)
new_crime = pick(major_crimes)
if(!(major_crimes[new_crime] in list_crimes))
crimes_committed = addtext(crimes_committed, new_crime)
list_crimes.Add(major_crimes[new_crime])
if((running_total != "Execution") && (running_total != "Permanent Imprisonment"))
running_total = running_total + 15
if(8, 9)
new_crime = pick(exceptional_crimes)
if(!(exceptional_crimes[new_crime] in list_crimes))
crimes_committed = addtext(crimes_committed, new_crime)
list_crimes.Add(exceptional_crimes[new_crime])
if(running_total != "Execution")
running_total = "Permanent Imprisonment"
if(10)
new_crime = pick(capital_crimes)
if(!(capital_crimes[new_crime] in list_crimes))
crimes_committed = addtext(crimes_committed, new_crime)
list_crimes.Add(capital_crimes[new_crime])
running_total = "Execution"
del(list_crimes)
if(prob(PROB_CANDIDATE_ERRORS)) // Sentencing time
if((running_total == "Execution") || (running_total == "Permanent Imprisonment"))
sentencing = text("[rand(5,55)] Minutes In Brig")
else
RandNum = rand(1,5)
switch(RandNum)
if(1) sentencing = "Permanent Imprisonment"
if(2) sentencing = "Execution"
if(3) sentencing = "Pardoned by Captain"
if(4) sentencing = text("[max(5, running_total - 20)] Minutes In Brig")
if(5) sentencing = text("[running_total + 20] Minutes In Brig")
good_candidate = FALSE
else
if((running_total != "Execution") && (running_total != "Permanent Imprisonment"))
sentencing = text("[running_total] Minutes In Brig")
else
sentencing = running_total
/obj/machinery/computer/arcade/lawyer/proc/unique_candidate()
unique_candidate = pick(UNIQUE_MCTIDE, UNIQUE_CLING, UNIQUE_CEO_CHILD, UNIQUE_STEVE)
switch(unique_candidate)
if(UNIQUE_MCTIDE) // Grey McTide is always evil
criminal_name = "Grey McTide"
criminal_job = "Assistant"
crimes_committed = "Being annoying"
sentencing = "Permanent Imprisonment"
officer_name = "John Ponte"
station_location = "NSS Cyberiad"
manner_of_arrest = "Arrested after hitting an officer with a toolbox and stealing their baton."
if(UNIQUE_CLING) // It's funny!
criminal_name = "Dr. Chang Ling"
criminal_job = "Geneticist"
crimes_committed = "Transforming into other people"
sentencing = "Execution"
officer_name = "Phil Yanst"
station_location = "NSS Diagoras"
manner_of_arrest = "Two identical staff members ran into each other. After some investigation, one was determined to be fake and arrested."
if(UNIQUE_CEO_CHILD) // Hes the son of the CEO, what do you expect?
criminal_name = "Johnny Nanotrasen, Jr."
criminal_job = "Unemployed"
crimes_committed = "Grand Sabotage"
sentencing = "Pardoned by Central Command"
officer_name = "REDACTED"
station_location = "NSS Kerberos"
manner_of_arrest = "Found cutting wires leading to the tesla containment, arrested on the spot."
if(UNIQUE_STEVE) // Impersonating Steve is punishable by death
criminal_name = "'Steve'"
criminal_job = "Central Command Intern"
crimes_committed = "Mutiny, Fraud"
sentencing = "Execution"
officer_name = "Steve"
station_location = "NSS Cerebron"
manner_of_arrest = "Suspect arrested while attempting to order the Captain to give him the contents of the vault."
/obj/machinery/computer/arcade/lawyer/proc/win()
game_status = LAWYER_STATUS_START
atom_say("Congratulations Magistrate, all the criminals have been put away properly thanks to you.")
playsound(loc, 'sound/arcade/recruiter_win.ogg', 20)
if(emagged)
new /obj/item/stamp/chameleon(get_turf(src))
new /obj/item/clothing/accessory/medal/recruiter(get_turf(src))
emagged = FALSE
prizevend(50)
/obj/machinery/computer/arcade/lawyer/ui_state(mob/user)
return GLOB.default_state
/obj/machinery/computer/arcade/lawyer/ui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "LawyerSim", name)
ui.open()
/obj/machinery/computer/arcade/lawyer/ui_data(mob/user)
var/list/data = list(
"gamestatus" = game_status,
"crim_name" = criminal_name,
"crim_job" = criminal_job,
"crimes_list" = crimes_committed,
"total_sent" = sentencing,
"off_name" = officer_name,
"station_loc" = station_location,
"arrest_desc" = manner_of_arrest,
"cand_curriculum" = curriculums,
"total_curriculums" = total_curriculums,
"reason" = reason
)
return data
/obj/machinery/computer/arcade/lawyer/ui_act(action, list/params, datum/tgui/ui)
if(..())
return
var/mob/user = ui.user
add_fingerprint(user)
. = TRUE
if(!COOLDOWN_FINISHED(src, spam_cooldown))
return
COOLDOWN_START(src, spam_cooldown, 0.4 SECONDS)
switch(action)
if("approve")
playsound(user, 'sound/items/handling/standard_stamp.ogg', 50, TRUE)
if(!good_candidate)
game_status = LAWYER_STATUS_GAMEOVER
reason = "You approved an invalid record! Security is abusing their authority and Nanotrasen is firing everyone involved."
playsound(loc, 'sound/misc/compiler-failure.ogg', 3, TRUE)
return
if(curriculums >= total_curriculums)
win()
return
curriculums++
good_candidate = TRUE
if(prob(PROB_UNIQUE_CANDIDATE))
unique_candidate()
else
generate_candidate()
if("deny")
playsound(user, 'sound/items/handling/standard_stamp.ogg', 50, TRUE)
if(good_candidate)
game_status = LAWYER_STATUS_GAMEOVER
reason = "You rejected a valid record. Security complained to Nanotrasen about your performance, and they fired you to save face!"
playsound(loc, 'sound/misc/compiler-failure.ogg', 3, TRUE)
return
if(curriculums >= total_curriculums)
win()
return
curriculums++
good_candidate = TRUE
if(prob(PROB_UNIQUE_CANDIDATE))
unique_candidate()
else
generate_candidate()
if("start_game")
playsound(user, 'sound/effects/pressureplate.ogg', 10, TRUE)
good_candidate = TRUE
game_status = LAWYER_STATUS_NORMAL
curriculums = 1
if(prob(PROB_UNIQUE_CANDIDATE))
unique_candidate()
else
generate_candidate()
if("instructions")
playsound(user, 'sound/effects/pressureplate.ogg', 10, TRUE)
game_status = LAWYER_STATUS_INSTRUCTIONS
if("back_to_menu")
playsound(user, 'sound/effects/pressureplate.ogg', 10, TRUE)
game_status = LAWYER_STATUS_START
/obj/machinery/computer/arcade/lawyer/attack_hand(mob/user)
ui_interact(user)
#undef PROB_CANDIDATE_ERRORS
#undef PROB_MULTIPLE_CRIMES
#undef PROB_UNIQUE_CANDIDATE
#undef UNIQUE_MCTIDE
#undef UNIQUE_CLING
#undef UNIQUE_CEO_CHILD
#undef UNIQUE_STEVE
#undef LAWYER_STATUS_START
#undef LAWYER_STATUS_INSTRUCTIONS
#undef LAWYER_STATUS_NORMAL
#undef LAWYER_STATUS_GAMEOVER
@@ -266,6 +266,12 @@
build_path = /obj/machinery/computer/arcade/recruiter
origin_tech = "programming=1"
/obj/item/circuitboard/arcade/lawyer
board_name = "Nanotrasen Magistrate Simulator"
icon_state = "generic"
build_path = /obj/machinery/computer/arcade/lawyer
origin_tech = "programming=1"
/obj/item/circuitboard/solar_control
board_name = "Solar Control"
icon_state = "engineering"