Adds more extensive config settings for human authority (#86886)

## About The Pull Request
Before there were two settings for human authority:
`ENFORCE_HUMAN_AUTHORITY` and `ENFORCE_HUMAN_AUTHORITY_ON_EVERYONE`
The first, if enabled, would not let non-humans be heads of staff unless
they had a specific var on their job set to TRUE.
The second, if enabled, would simply ignore that var and reject the
non-human anyways.

This PR replaces both of those settings with a single one,
`HUMAN_AUTHORITY`. You can set it to one of four settings:
* "OFF": human authority will be turned OFF. Non-Humans will be able to
be heads of staff.
* "HUMAN WHITELIST": human authority will be turned OFF, HOWEVER; if a
job has its new `human_authority` variable set to
`JOB_AUTHORITY_HUMANS_ONLY`, then whoever picks that job will be forced
to be human.
* "NON-HUMAN WHITELIST": human authority will be turned ON. However, if
a job has its `human_authority` variable set to
`JOB_AUTHORITY_NON_HUMANS_ALLOWED`, a non-human can become that job.
This is what we have now, it works the same as if
`ENFORCE_HUMAN_AUTHORITY` were turned on. This is also what I've set as
the default value.
* "ENFORCED" human authority will be turned ON. Non-Humans will never be
able to be heads of staff. This is what
`ENFORCE_HUMAN_AUTHORITY_ON_EVERYONE` used to do.

You can also now set the `human_authority` variable through
`jobconfig.toml`!

## Why It's Good For The Game

Allows more configuration options for downstreams, and lets keyholders
and headmins have more options over how to set up human authority.

## Changelog
🆑
config: Both human authority settings were combined into a singular one,
allowing for more flexibility
/🆑

---------

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
# Conflicts:
#	config/game_options.txt
#	config/jobconfig.toml
This commit is contained in:
Ilán Mori
2024-10-06 14:48:39 -03:00
committed by Majkl-J
parent dc9bfc883a
commit 9facb9914a
24 changed files with 148 additions and 39 deletions

View File

@@ -28,3 +28,9 @@
#define RESPAWN_FLAG_FREE 1
/// Can respawn, but not as the same character
#define RESPAWN_FLAG_NEW_CHARACTER 2
// Human authority defines
#define HUMAN_AUTHORITY_DISABLED "DISABLED"
#define HUMAN_AUTHORITY_HUMAN_WHITELIST "HUMAN_WHITELIST"
#define HUMAN_AUTHORITY_NON_HUMAN_WHITELIST "NON_HUMAN_WHITELIST"
#define HUMAN_AUTHORITY_ENFORCED "ENFORCED"

View File

@@ -12,6 +12,11 @@
/// Used when the `get_job_unavailable_error_message` proc can't make sense of a given code.
#define GENERIC_JOB_UNAVAILABLE_ERROR "Error: Unknown job availability."
// Human authority settings
// If you want to add another setting, make sure to also add it to the if chain in /datum/job_config_type/human_authority/validate_value()
#define JOB_AUTHORITY_HUMANS_ONLY "HUMANS_ONLY"
#define JOB_AUTHORITY_NON_HUMANS_ALLOWED "NON_HUMANS_ALLOWED"
#define DEFAULT_RELIGION "Christianity"
#define DEFAULT_DEITY "Space Jesus"
#define DEFAULT_BIBLE "Default Bible Name"
@@ -25,6 +30,7 @@
#define JOB_CONFIG_REQUIRED_CHARACTER_AGE "Required Character Age"
#define JOB_CONFIG_SPAWN_POSITIONS "Spawn Positions"
#define JOB_CONFIG_TOTAL_POSITIONS "Total Positions"
#define JOB_CONFIG_HUMAN_AUTHORITY "Human Authority Whitelist Setting"
/**
* =======================

View File

@@ -107,9 +107,22 @@
/datum/config_entry/flag/protect_assistant_from_antagonist //If assistants can be traitor/cult/other
/datum/config_entry/flag/enforce_human_authority //If non-human species are barred from joining as a head of staff
/datum/config_entry/string/human_authority //Controls how to enforce human authority
default = "HUMAN_WHITELIST"
/datum/config_entry/flag/enforce_human_authority_on_everyone //If non-human species are barred from joining as a head of staff, including jobs flagged as allowed for non-humans, ie. Quartermaster.
/////////////////////////////////////////////////Outdated human authority settings
/datum/config_entry/flag/enforce_human_authority
deprecated_by = /datum/config_entry/string/human_authority
/datum/config_entry/flag/enforce_human_authority/DeprecationUpdate(value)
return value ? HUMAN_AUTHORITY_NON_HUMAN_WHITELIST : HUMAN_AUTHORITY_DISABLED
/datum/config_entry/flag/enforce_human_authority_on_everyone
deprecated_by = /datum/config_entry/string/human_authority
/datum/config_entry/flag/enforce_human_authority_on_everyone/DeprecationUpdate(value)
return value ? HUMAN_AUTHORITY_ENFORCED : HUMAN_AUTHORITY_DISABLED
/////////////////////////////////////////////////
/datum/config_entry/flag/allow_latejoin_antagonists // If late-joining players can be traitor/changeling

View File

@@ -133,6 +133,11 @@
var/list/working_list = list()
for(var/config_datum_key in job_config_datum_singletons)
var/datum/job_config_type/config_datum = job_config_datum_singletons[config_datum_key]
// Dont make the entry if it doesn't apply to this job
if(!config_datum.validate_entry(occupation))
continue
var/config_read_value = job_config[job_key][config_datum_key]
if(!config_datum.validate_value(config_read_value))
working_list += list(
@@ -155,6 +160,11 @@
var/returnable_list = list()
for(var/config_datum_key in job_config_datum_singletons)
var/datum/job_config_type/config_datum = job_config_datum_singletons[config_datum_key]
// Dont make the entry if it doesn't apply to this job
if(!config_datum.validate_entry(new_occupation))
continue
// Remember, every time we write the TOML from scratch, we want to have it commented out by default.
// This is to ensure that the server operator knows that they are overriding codebase defaults when they remove the comment.
// Having comments mean that we allow server operators to defer to codebase standards when they deem acceptable. They must uncomment to override the codebase default.
@@ -171,6 +181,11 @@
var/list/datums_to_read = job_config_datum_singletons - list(JOB_CONFIG_TOTAL_POSITIONS, JOB_CONFIG_SPAWN_POSITIONS)
for(var/config_datum_key in datums_to_read)
var/datum/job_config_type/config_datum = job_config_datum_singletons[config_datum_key]
// Dont make the entry if it doesn't apply to this job
if(!config_datum.validate_entry(new_occupation))
continue
returnable_list += list(
"# [config_datum_key]" = config_datum.get_current_value(new_occupation),
)

View File

@@ -73,10 +73,11 @@ SUBSYSTEM_DEF(job)
/// This is just the message we prepen and put into all of the config files to ensure documentation. We use this in more than one place, so let's put it in the SS to make life a bit easier.
var/config_documentation = "## This is the configuration file for the job system.\n## This will only be enabled when the config flag LOAD_JOBS_FROM_TXT is enabled.\n\
## We use a system of keys here that directly correlate to the job, just to ensure they don't desync if we choose to change the name of a job.\n## You are able to change (as of now) five different variables in this file.\n\
## We use a system of keys here that directly correlate to the job, just to ensure they don't desync if we choose to change the name of a job.\n## You are able to change (as of now) five (six if the job is a command head) different variables in this file.\n\
## Total Positions are how many job slots you get in a shift, Spawn Positions are how many you get that load in at spawn. If you set this to -1, it is unrestricted.\n## Playtime Requirements is in minutes, and the job will unlock when a player reaches that amount of time.\n\
## However, that can be superseded by Required Account Age, which is a time in days that you need to have had an account on the server for.\n\
## Also there is a required character age in years. It prevents player from joining as this job, if their character's age as is lower than required. Setting it to 0 means it is turned off for this job.\n\n\
## Also there is a required character age in years. It prevents player from joining as this job, if their character's age as is lower than required. Setting it to 0 means it is turned off for this job.\n\
## Lastly there's Human Authority Whitelist Setting. You can set it to either \"HUMANS_ONLY\" or \"NON_HUMANS_ALLOWED\". Check the \"Human Authority\" setting on the game_options file to know which you should choose. Note that this entry only appears on jobs that are marked as heads of staff.\n\n\
## As time goes on, more config options may be added to this file.\n\
## You can use the admin verb 'Generate Job Configuration' in-game to auto-regenerate this config as a downloadable file without having to manually edit this file if we add more jobs or more things you can edit here.\n\
## It will always respect prior-existing values in the config, but will appropriately add more fields when they generate.\n## It's strongly advised you create your own version of this file rather than use the one provisioned on the codebase.\n\n\

View File

@@ -87,6 +87,6 @@
msg += "<br><b>Current Informational Settings:</b>"
msg += "Protect Authority Roles From Traitor: [CONFIG_GET(flag/protect_roles_from_antagonist)]"
msg += "Protect Assistant Role From Traitor: [CONFIG_GET(flag/protect_assistant_from_antagonist)]"
msg += "Enforce Human Authority: [CONFIG_GET(flag/enforce_human_authority)]"
msg += "Enforce Human Authority: [CONFIG_GET(string/human_authority)]"
msg += "Allow Latejoin Antagonists: [CONFIG_GET(flag/allow_latejoin_antagonists)]"
to_chat(src, span_infoplain(msg.Join("<br>")))

View File

@@ -33,6 +33,12 @@
stack_trace("Attempted to validate value for the default job config! You're doing something wrong!!")
return FALSE
/// Check if the config entry should be made for a specific job
/// By default returns TRUE, meaning that by default every job will have the config entry created by the datum
/// An example of what this could be used for is: A value that only appears if the job is a head of staff
/datum/job_config_type/proc/validate_entry(datum/job/occupation)
return TRUE
/// This is the proc that we actually invoke to set the config-based values for each job. Is also intended to handle all in-depth logic checks pertient to the job datum itself.
/// Return TRUE if the value was set successfully (or if expected behavior did indeed occur), FALSE if it was not.
/datum/job_config_type/proc/set_current_value(datum/job/occupation, value)

View File

@@ -0,0 +1,17 @@
/// Whether if the job should whitelist humans, whitelist nonhumans, or neither
/datum/job_config_type/human_authority
name = JOB_CONFIG_HUMAN_AUTHORITY
datum_var_name = "human_authority"
/datum/job_config_type/human_authority/validate_value(value)
if(value == JOB_AUTHORITY_HUMANS_ONLY)
return TRUE
if(value == JOB_AUTHORITY_NON_HUMANS_ALLOWED)
return TRUE
return FALSE
/datum/job_config_type/human_authority/validate_entry(datum/job/occupation)
return occupation.job_flags & JOB_HEAD_OF_STAFF

View File

@@ -77,6 +77,8 @@
else
ertemplate = new /datum/ert/centcom_official
var/human_authority_setting = CONFIG_GET(string/human_authority)
var/list/settings = list(
"preview_callback" = CALLBACK(src, PROC_REF(makeERTPreviewIcon)),
"mainsettings" = list(
@@ -84,7 +86,7 @@
"teamsize" = list("desc" = "Team Size", "type" = "number", "value" = ertemplate.teamsize),
"mission" = list("desc" = "Mission", "type" = "string", "value" = ertemplate.mission),
"polldesc" = list("desc" = "Ghost poll description", "type" = "string", "value" = ertemplate.polldesc),
"enforce_human" = list("desc" = "Enforce human authority", "type" = "boolean", "value" = "[(CONFIG_GET(flag/enforce_human_authority) ? "Yes" : "No")]"),
"enforce_human" = list("desc" = "Enforce human authority", "type" = "boolean", "value" = "[(human_authority_setting == HUMAN_AUTHORITY_ENFORCED ? "Yes" : "No")]"),
"open_armory" = list("desc" = "Open armory doors", "type" = "boolean", "value" = "[(ertemplate.opendoors ? "Yes" : "No")]"),
"leader_experience" = list("desc" = "Pick an experienced leader", "type" = "boolean", "value" = "[(ertemplate.leader_experience ? "Yes" : "No")]"),
"random_names" = list("desc" = "Randomize names", "type" = "boolean", "value" = "[(ertemplate.random_names ? "Yes" : "No")]"),

View File

@@ -125,8 +125,7 @@
/// Alternate titles to register as pointing to this job.
var/list/alternate_titles
/// Does this job ignore human authority?
var/ignore_human_authority = FALSE
var/human_authority = JOB_AUTHORITY_NON_HUMANS_ALLOWED
/// String key to track any variables we want to tie to this job in config, so we can avoid using the job title. We CAPITALIZE it in order to ensure it's unique and resistant to trivial formatting changes.
/// You'll probably break someone's config if you change this, so it's best to not to.
@@ -571,11 +570,28 @@
if(!player_client)
return // Disconnected while checking for the appearance ban.
var/require_human = CONFIG_GET(flag/enforce_human_authority) && (job.job_flags & JOB_HEAD_OF_STAFF)
if(require_human)
var/all_authority_require_human = CONFIG_GET(flag/enforce_human_authority_on_everyone)
if(!all_authority_require_human && job.ignore_human_authority)
require_human = FALSE
var/human_authority_setting = CONFIG_GET(string/human_authority)
var/require_human = FALSE
// If the job in question is a head of staff,
// check the config to see if we should force the player onto a human character or not
if(job.job_flags & JOB_HEAD_OF_STAFF)
switch(human_authority_setting)
// If non-humans are the norm and jobs must be forced to be only for humans
// then we only force the player to be a human if the job exclusively allows humans
if(HUMAN_AUTHORITY_HUMAN_WHITELIST)
require_human = job.human_authority == JOB_AUTHORITY_HUMANS_ONLY
// If humans are the norm and jobs must be allowed to be played by non-humans
// then we only force the player to be a human if the job doesn't allow for non-humans to play it
if(HUMAN_AUTHORITY_NON_HUMAN_WHITELIST)
require_human = job.human_authority != JOB_AUTHORITY_NON_HUMANS_ALLOWED
// If humans are the norm and there is no chance that a non-human can be a head of staff
// always return true, since there is no chance that a non-human can be a head of staff.
if(HUMAN_AUTHORITY_ENFORCED)
require_human = TRUE
src.job = job.title

View File

@@ -46,6 +46,8 @@
job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS
rpg_title = "Star Duke"
human_authority = JOB_AUTHORITY_HUMANS_ONLY
voice_of_god_power = 1.4 //Command staff has authority

View File

@@ -46,6 +46,8 @@
rpg_title = "Head Crystallomancer"
job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS
human_authority = JOB_AUTHORITY_HUMANS_ONLY
voice_of_god_power = 1.4 //Command staff has authority

View File

@@ -43,6 +43,8 @@
rpg_title = "High Cleric"
job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS
human_authority = JOB_AUTHORITY_HUMANS_ONLY
voice_of_god_power = 1.4 //Command staff has authority

View File

@@ -41,6 +41,9 @@
family_heirlooms = list(/obj/item/reagent_containers/cup/glass/trophy/silver_cup)
rpg_title = "Guild Questgiver"
job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS
human_authority = JOB_AUTHORITY_HUMANS_ONLY
voice_of_god_power = 1.4 //Command staff has authority

View File

@@ -37,6 +37,8 @@
rpg_title = "Guard Leader"
job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS
human_authority = JOB_AUTHORITY_HUMANS_ONLY
voice_of_god_power = 1.4 //Command staff has authority

View File

@@ -36,7 +36,7 @@
rpg_title = "Steward"
job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS
voice_of_god_power = 1.4 //Command staff has authority
ignore_human_authority = TRUE
human_authority = JOB_AUTHORITY_NON_HUMANS_ALLOWED
/datum/outfit/job/quartermaster
name = "Quartermaster"

View File

@@ -44,6 +44,8 @@
rpg_title = "Archmagister"
job_flags = STATION_JOB_FLAGS | HEAD_OF_STAFF_JOB_FLAGS
human_authority = JOB_AUTHORITY_HUMANS_ONLY
voice_of_god_power = 1.4 //Command staff has authority

View File

@@ -33,7 +33,7 @@
rpg_title = "Royal Guard"
allow_bureaucratic_error = FALSE
job_flags = STATION_JOB_FLAGS | STATION_TRAIT_JOB_FLAGS
ignore_human_authority = TRUE
human_authority = JOB_AUTHORITY_NON_HUMANS_ALLOWED
/datum/job/bridge_assistant/after_spawn(mob/living/spawned, client/player_client)
. = ..()

View File

@@ -40,7 +40,7 @@
random_spawns_possible = FALSE
allow_bureaucratic_error = FALSE
job_flags = STATION_JOB_FLAGS | STATION_TRAIT_JOB_FLAGS
ignore_human_authority = TRUE //we can safely assume NT doesn't care what species AIs are made of, much less if they can't even afford an AI.
human_authority = JOB_AUTHORITY_NON_HUMANS_ALLOWED //we can safely assume NT doesn't care what species AIs are made of, much less if they can't even afford an AI.
/datum/job/human_ai/get_roundstart_spawn_point()
return get_latejoin_spawn_point()

View File

@@ -130,7 +130,9 @@
to humans. As a human, silicons are required to both protect and obey you.",
))
if(CONFIG_GET(flag/enforce_human_authority))
var/human_authority_setting = CONFIG_GET(string/human_authority)
if(human_authority_setting == HUMAN_AUTHORITY_NON_HUMAN_WHITELIST || human_authority_setting == HUMAN_AUTHORITY_ENFORCED)
to_add += list(list(
SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK,
SPECIES_PERK_ICON = "bullhorn",

View File

@@ -241,6 +241,8 @@ REQUEST_INTERNET_ALLOWED youtube\.com\/watch?v=,youtu\.be\/,soundcloud\.com\/,ba
## Jobs have specific "keys" tied to their in-game datums, those should sync up otherwise it will fail to load.
## Setting Total/Spawn Positions to -1 will open unlimited join slots for it.
## Playtime Requirements is in minutes, Required Account Age is in days.
## Human Authority Whitelist Setting can either be 0 or 1.
## Make sure to read the start of the file to get a more in-depth explanation of what each entry does!
#LOAD_JOBS_FROM_TXT
## Uncomment this to forbid admins from possessing the singularity.

View File

@@ -122,11 +122,12 @@ PROTECT_ROLES_FROM_ANTAGONIST
## Uncomment to prohibit assistants from becoming most antagonists.
#PROTECT_ASSISTANT_FROM_ANTAGONIST
## If non-human species are barred from joining as a head of staff
#ENFORCE_HUMAN_AUTHORITY
## If non-human species are barred from joining as a head of staff, including jobs flagged as allowed for non-humans, ie. Quartermaster.
#ENFORCE_HUMAN_AUTHORITY_ON_EVERYONE
## How human authority should be distributed. Can be set to four options (Make sure that what you type is exact!):
## "DISABLED"/Comment out/Put any invalid value: non-human races can be heads of staff and "human only" settings on jobs will be fully ignored.
## "HUMAN_WHITELIST": all heads-of-staff jobs will be able to be played by non-humans, unless that job incorporates the "human only" flag (Which can be configured via a variable or the job config txt).
## "NON_HUMAN_WHITELIST": non-humans will not be able to play as heads of staff, unless that job incorporates the "allow non-humans" flag (Which can be configured via a variable or the job config txt).
## "ENFORCED": non-humans cannot be heads of staff, only humans can. the "allow non-humans" setting will be ignored.
HUMAN_AUTHORITY HUMAN_WHITELIST
## If late-joining players have a chance to become a traitor/changeling
ALLOW_LATEJOIN_ANTAGONISTS

View File

@@ -1,11 +1,12 @@
## This is the configuration file for the job system.
## This will only be enabled when the config flag LOAD_JOBS_FROM_TXT is enabled.
## We use a system of keys here that directly correlate to the job, just to ensure they don't desync if we choose to change the name of a job.
## You are able to change (as of now) five different variables in this file.
## You are able to change (as of now) five (six if the job is a command head) different variables in this file.
## Total Positions are how many job slots you get in a shift, Spawn Positions are how many you get that load in at spawn. If you set this to -1, it is unrestricted.
## Playtime Requirements is in minutes, and the job will unlock when a player reaches that amount of time.
## However, that can be superseded by Required Account Age, which is a time in days that you need to have had an account on the server for.
## Also there is a required character age in years. It prevents player from joining as this job, if their character's age as is lower than required. Setting it to 0 means it is turned off for this job.
## Lastly there's Human Authority Whitelist Setting. You can set it to either "HUMANS_ONLY" or "NON_HUMANS_ALLOWED". Check the "Human Authority" setting on the game_options file to know which you should choose. Note that this entry only appears on jobs that are marked as heads of staff.
## As time goes on, more config options may be added to this file.
## You can use the admin verb 'Generate Job Configuration' in-game to auto-regenerate this config as a downloadable file without having to manually edit this file if we add more jobs or more things you can edit here.
@@ -82,8 +83,9 @@
"Total Positions" = 2
[CAPTAIN]
"Playtime Requirements" = 2400
"Required Account Age" = 14
"# Human Authority Whitelist Setting" = "HUMANS_ONLY"
"# Playtime Requirements" = 180
"# Required Account Age" = 14
"# Required Character Age" = 0
"Spawn Positions" = 1
"Total Positions" = 1
@@ -110,15 +112,17 @@
"Total Positions" = 2
[CHIEF_ENGINEER]
"Playtime Requirements" = 2400
"Required Account Age" = 7
"# Human Authority Whitelist Setting" = "HUMANS_ONLY"
"# Playtime Requirements" = 180
"# Required Account Age" = 7
"# Required Character Age" = 0
"Spawn Positions" = 1
"Total Positions" = 1
[CHIEF_MEDICAL_OFFICER]
"Playtime Requirements" = 2400
"Required Account Age" = 7
"# Human Authority Whitelist Setting" = "HUMANS_ONLY"
"# Playtime Requirements" = 180
"# Required Account Age" = 7
"# Required Character Age" = 0
"Spawn Positions" = 1
"Total Positions" = 1
@@ -169,8 +173,8 @@
"Playtime Requirements" = 120
"Required Account Age" = 21
"# Required Character Age" = 0
"Spawn Positions" = 3
"Total Positions" = 3
"# Spawn Positions" = 3
"# Total Positions" = 0
[DETECTIVE]
"Playtime Requirements" = 300
@@ -194,15 +198,17 @@
"Total Positions" = 2
[HEAD_OF_PERSONNEL]
"Playtime Requirements" = 2400
"Required Account Age" = 10
"# Human Authority Whitelist Setting" = "HUMANS_ONLY"
"# Playtime Requirements" = 180
"# Required Account Age" = 10
"# Required Character Age" = 0
"Spawn Positions" = 1
"Total Positions" = 1
[HEAD_OF_SECURITY]
"Playtime Requirements" = 2400
"Required Account Age" = 14
"# Human Authority Whitelist Setting" = "HUMANS_ONLY"
"# Playtime Requirements" = 300
"# Required Account Age" = 14
"# Required Character Age" = 0
"Spawn Positions" = 1
"Total Positions" = 1
@@ -271,15 +277,17 @@
"Total Positions" = 1
[QUARTERMASTER]
"Playtime Requirements" = 2400
"Required Account Age" = 7
"# Human Authority Whitelist Setting" = "NON_HUMANS_ALLOWED"
"# Playtime Requirements" = 0
"# Required Account Age" = 7
"# Required Character Age" = 0
"Spawn Positions" = 1
"Total Positions" = 1
[RESEARCH_DIRECTOR]
"Playtime Requirements" = 2400
"Required Account Age" = 7
"# Human Authority Whitelist Setting" = "HUMANS_ONLY"
"# Playtime Requirements" = 180
"# Required Account Age" = 7
"# Required Character Age" = 0
"Spawn Positions" = 1
"Total Positions" = 1

View File

@@ -1744,6 +1744,7 @@
#include "code\datums\id_trim\syndicate.dm"
#include "code\datums\job_configs\_job_configs.dm"
#include "code\datums\job_configs\default_positions.dm"
#include "code\datums\job_configs\human_authority.dm"
#include "code\datums\job_configs\playtime_requirements.dm"
#include "code\datums\job_configs\required_account_age.dm"
#include "code\datums\job_configs\required_character_age.dm"