diff --git a/code/__DEFINES/configuration.dm b/code/__DEFINES/configuration.dm new file mode 100644 index 00000000000..c78dfb28ab2 --- /dev/null +++ b/code/__DEFINES/configuration.dm @@ -0,0 +1,10 @@ +//config files +#define CONFIG_DEF(X) /datum/config_entry/##X { resident_file = CURRENT_RESIDENT_FILE }; /datum/config_entry/##X +#define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X) +#define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y) + +#define CONFIG_MAPS_FILE "maps.txt" + +//flags +#define CONFIG_ENTRY_LOCKED 1 //can't edit +#define CONFIG_ENTRY_HIDDEN 2 //can't see value diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 8f3a0163b93..91508ded321 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -26,74 +26,74 @@ /proc/log_admin(text) GLOB.admin_log.Add(text) - if (config.log_admin) + if (CONFIG_GET(flag/log_admin)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ADMIN: [text]") //Items using this proc are stripped from public logs - use with caution /proc/log_admin_private(text) GLOB.admin_log.Add(text) - if (config.log_admin) + if (CONFIG_GET(flag/log_admin)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ADMINPRIVATE: [text]") /proc/log_adminsay(text) - if (config.log_adminchat) + if (CONFIG_GET(flag/log_adminchat)) log_admin_private("ASAY: [text]") /proc/log_dsay(text) - if (config.log_adminchat) + if (CONFIG_GET(flag/log_adminchat)) log_admin("DSAY: [text]") /proc/log_game(text) - if (config.log_game) + if (CONFIG_GET(flag/log_game)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]GAME: [text]") /proc/log_vote(text) - if (config.log_vote) + if (CONFIG_GET(flag/log_vote)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]VOTE: [text]") /proc/log_access(text) - if (config.log_access) + if (CONFIG_GET(flag/log_access)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]ACCESS: [text]") /proc/log_say(text) - if (config.log_say) + if (CONFIG_GET(flag/log_say)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]SAY: [text]") /proc/log_prayer(text) - if (config.log_prayer) + if (CONFIG_GET(flag/log_prayer)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]PRAY: [text]") /proc/log_law(text) - if (config.log_law) + if (CONFIG_GET(flag/log_law)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]LAW: [text]") /proc/log_ooc(text) - if (config.log_ooc) + if (CONFIG_GET(flag/log_ooc)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]OOC: [text]") /proc/log_whisper(text) - if (config.log_whisper) + if (CONFIG_GET(flag/log_whisper)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]WHISPER: [text]") /proc/log_emote(text) - if (config.log_emote) + if (CONFIG_GET(flag/log_emote)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]EMOTE: [text]") /proc/log_attack(text) - if (config.log_attack) + if (CONFIG_GET(flag/log_attack)) WRITE_FILE(GLOB.world_attack_log, "\[[time_stamp()]]ATTACK: [text]") /proc/log_pda(text) - if (config.log_pda) + if (CONFIG_GET(flag/log_pda)) WRITE_FILE(GLOB.world_pda_log, "\[[time_stamp()]]PDA: [text]") /proc/log_comment(text) - if (config.log_pda) + if (CONFIG_GET(flag/log_pda)) //reusing the PDA option because I really don't think news comments are worth a config option WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]COMMENT: [text]") /proc/log_chat(text) - if (config.log_pda) + if (CONFIG_GET(flag/log_pda)) WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]CHAT: [text]") /proc/log_qdel(text) @@ -102,6 +102,10 @@ /proc/log_sql(text) WRITE_FILE(GLOB.sql_error_log, "\[[time_stamp()]]SQL: [text]") +/proc/log_config(text) + WRITE_FILE(GLOB.config_error_log, text) + SEND_TEXT(world.log, text) + //This replaces world.log so it displays both in DD and the file /proc/log_world(text) WRITE_FILE(GLOB.world_runtime_log, text) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index c040e264e6e..e38a6826f97 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -314,10 +314,11 @@ // Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer. -/proc/get_candidates(be_special_type, afk_bracket = config.inactivity_period, jobbanType) +/proc/get_candidates(be_special_type, afk_bracket = CONFIG_GET(number/inactivity_period), jobbanType) var/list/candidates = list() // Keep looping until we find a non-afk candidate within the time bracket (we limit the bracket to 10 minutes (6000)) - while(!candidates.len && afk_bracket < config.afk_period) + var/afk_period = CONFIG_GET(number/afk_period) + while(!candidates.len && afk_bracket < afk_period) for(var/mob/dead/observer/G in GLOB.player_list) if(G.client != null) if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 5b5f7206373..7e140457207 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -34,9 +34,7 @@ //Species for(var/spath in subtypesof(/datum/species)) var/datum/species/S = new spath() - if(S.roundstart) - GLOB.roundstart_species[S.id] = S.type - GLOB.species_list[S.id] = S.type + GLOB.species_list[S.id] = spath //Surgeries for(var/path in subtypesof(/datum/surgery)) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index d43073127f6..56829a29d0d 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -133,7 +133,6 @@ GLOBAL_LIST_INIT(skin_tones, list( )) GLOBAL_LIST_EMPTY(species_list) -GLOBAL_LIST_EMPTY(roundstart_species) /proc/age2agedescription(age) switch(age) diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 58b8fbaa0f0..bfcfd23f505 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -57,8 +57,9 @@ GLOBAL_VAR(command_name) /proc/station_name() if(!GLOB.station_name) var/newname - if(config && config.station_name) - newname = config.station_name + var/config_station_name = CONFIG_GET(string/stationname) + if(config_station_name) + newname = config_station_name else newname = new_station_name() @@ -69,8 +70,9 @@ GLOBAL_VAR(command_name) /proc/set_station_name(newname) GLOB.station_name = newname - if(config && config.server_name) - world.name = "[config.server_name][config.server_name==GLOB.station_name ? "" : ": [GLOB.station_name]"]" + var/config_server_name = CONFIG_GET(string/servername) + if(config_server_name) + world.name = "[config_server_name][config_server_name == GLOB.station_name ? "" : ": [GLOB.station_name]"]" else world.name = GLOB.station_name diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 53691d122e5..b4f5b2500a4 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -19,7 +19,7 @@ return copytext(sqltext, 2, lentext(sqltext));//Quote() adds quotes around input, we already do that /proc/format_table_name(table as text) - return global.sqlfdbktableprefix + table + return CONFIG_GET(string/feedback_tableprefix) + table /* * Text sanitization @@ -469,7 +469,7 @@ GLOBAL_LIST_INIT(binary, list("0","1")) //in the json file and have it be reflected in the in game item/mob it came from. //(That's what things like savefiles are for) Note that this list is not shuffled. /proc/twitterize(list/proposed, filename, cullshort = 1, storemax = 1000) - if(!islist(proposed) || !filename || !config.log_twitter) + if(!islist(proposed) || !filename || !CONFIG_GET(flag/log_twitter)) return //Regular expressions are, as usual, absolute magic diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index a534eba9662..26c1a609614 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -554,3 +554,24 @@ else return /datum return text2path(copytext(string_type, 1, last_slash)) + +//returns a string the last bit of a type, without the preceeding '/' +/proc/type2top(the_type) + //handle the builtins manually + if(!ispath(the_type)) + return + switch(the_type) + if(/datum) + return "datum" + if(/atom) + return "atom" + if(/obj) + return "obj" + if(/mob) + return "mob" + if(/area) + return "area" + if(/turf) + return "turf" + else //regex everything else (works for /proc too) + return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", "")) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index c2398982c21..905babe8488 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1266,7 +1266,7 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types()) #define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); } #define QDEL_LIST_IN(L, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/______qdel_list_wrapper, L), time, TIMER_STOPPABLE) #define QDEL_LIST_ASSOC(L) if(L) { for(var/I in L) { qdel(L[I]); qdel(I); } L.Cut(); } -#define QDEL_LIST_ASSOC_VAL(L) if(L) { for(var/I in L) qel(L[I]); L.Cut(); } +#define QDEL_LIST_ASSOC_VAL(L) if(L) { for(var/I in L) qdel(L[I]); L.Cut(); } /proc/______qdel_list_wrapper(list/L) //the underscores are to encourage people not to use this directly. QDEL_LIST(L) diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index 83bf3cfb5ad..391744e34c6 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -1,4 +1,4 @@ -GLOBAL_REAL(config, /datum/configuration) +GLOBAL_REAL(config, /datum/controller/configuration) GLOBAL_DATUM_INIT(revdata, /datum/getrev, new) @@ -11,9 +11,7 @@ GLOBAL_VAR_INIT(hub_visibility, FALSE) GLOBAL_VAR_INIT(ooc_allowed, TRUE) // used with admin verbs to disable ooc - not a config option apparently GLOBAL_VAR_INIT(dooc_allowed, TRUE) -GLOBAL_VAR_INIT(abandon_allowed, TRUE) GLOBAL_VAR_INIT(enter_allowed, TRUE) -GLOBAL_VAR_INIT(guests_allowed, TRUE) GLOBAL_VAR_INIT(shuttle_frozen, FALSE) GLOBAL_VAR_INIT(shuttle_left, FALSE) GLOBAL_VAR_INIT(tinted_weldhelh, TRUE) @@ -25,10 +23,16 @@ GLOBAL_VAR_INIT(Debug, FALSE) // global debug switch GLOBAL_VAR_INIT(Debug2, FALSE) //This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage +//Protecting these because the proper way to edit them is with the config/secrets GLOBAL_VAR_INIT(MAX_EX_DEVESTATION_RANGE, 3) +GLOBAL_PROTECT(MAX_EX_DEVESTATION_RANGE) GLOBAL_VAR_INIT(MAX_EX_HEAVY_RANGE, 7) +GLOBAL_PROTECT(MAX_EX_HEAVY_RANGE) GLOBAL_VAR_INIT(MAX_EX_LIGHT_RANGE, 14) +GLOBAL_PROTECT(MAX_EX_LIGHT_RANGE) GLOBAL_VAR_INIT(MAX_EX_FLASH_RANGE, 14) +GLOBAL_PROTECT(MAX_EX_FLASH_RANGE) GLOBAL_VAR_INIT(MAX_EX_FLAME_RANGE, 14) +GLOBAL_PROTECT(MAX_EX_FLAME_RANGE) GLOBAL_VAR_INIT(DYN_EX_SCALE, 0.5) diff --git a/code/_globalvars/sensitive.dm b/code/_globalvars/sensitive.dm deleted file mode 100644 index e1a02621acb..00000000000 --- a/code/_globalvars/sensitive.dm +++ /dev/null @@ -1,16 +0,0 @@ -//Server API key -GLOBAL_REAL_VAR(comms_key) = "default_pwd" -GLOBAL_REAL_VAR(comms_allowed) = FALSE //By default, the server does not allow messages to be sent to it, unless the key is strong enough (this is to prevent misconfigured servers from becoming vulnerable) - -GLOBAL_REAL_VAR(medal_hub) -GLOBAL_REAL_VAR(medal_pass) = " " -GLOBAL_REAL_VAR(medals_enabled) = TRUE //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls. - -// MySQL configuration - -GLOBAL_REAL_VAR(sqladdress) = "localhost" -GLOBAL_REAL_VAR(sqlport) = "3306" -GLOBAL_REAL_VAR(sqlfdbkdb) = "test" -GLOBAL_REAL_VAR(sqlfdbklogin) = "root" -GLOBAL_REAL_VAR(sqlfdbkpass) = "" -GLOBAL_REAL_VAR(sqlfdbktableprefix) = "" diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm deleted file mode 100644 index 56e1c9fa520..00000000000 --- a/code/controllers/configuration.dm +++ /dev/null @@ -1,1016 +0,0 @@ -//Configuraton defines //TODO: Move all yes/no switches into bitflags - -//Used by jobs_have_maint_access -#define ASSISTANTS_HAVE_MAINT_ACCESS 1 -#define SECURITY_HAS_MAINT_ACCESS 2 -#define EVERYONE_HAS_MAINT_ACCESS 4 - -GLOBAL_VAR_INIT(config_dir, "config/") -GLOBAL_PROTECT(config_dir) - -/datum/configuration/can_vv_get(var_name) - var/static/list/banned_gets = list("autoadmin", "autoadmin_rank") - if (var_name in banned_gets) - return FALSE - return ..() - -/datum/configuration/vv_edit_var(var_name, var_value) - var/static/list/banned_edits = list("cross_address", "cross_allowed", "autoadmin", "autoadmin_rank", "invoke_youtubedl") - if(var_name in banned_edits) - return FALSE - return ..() - -/datum/configuration - var/name = "Configuration" // datum name - - var/autoadmin = 0 - var/autoadmin_rank = "Game Admin" - - var/server_name = null // server name (the name of the game window) - var/server_sql_name = null // short form server name used for the DB - var/station_name = null // station name (the name of the station in-game) - var/lobby_countdown = 120 // In between round countdown. - var/round_end_countdown = 25 // Post round murder death kill countdown - var/hub = 0 - - var/log_ooc = 0 // log OOC channel - var/log_access = 0 // log login/logout - var/log_say = 0 // log client say - var/log_admin = 0 // log admin actions - var/log_game = 0 // log game events - var/log_vote = 0 // log voting - var/log_whisper = 0 // log client whisper - var/log_prayer = 0 // log prayers - var/log_law = 0 // log lawchanges - var/log_emote = 0 // log emotes - var/log_attack = 0 // log attack messages - var/log_adminchat = 0 // log admin chat messages - var/log_pda = 0 // log pda messages - var/log_twitter = 0 // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases. - var/log_world_topic = 0 // log all world.Topic() calls - var/sql_enabled = 0 // for sql switching - var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour - var/allow_vote_restart = 0 // allow votes to restart - var/allow_vote_mode = 0 // allow votes to change mode - var/vote_delay = 6000 // minimum time between voting sessions (deciseconds, 10 minute default) - var/vote_period = 600 // length of voting period (deciseconds, default 1 minute) - var/vote_no_default = 0 // vote does not default to nochange/norestart (tbi) - var/vote_no_dead = 0 // dead people can't vote (tbi) - var/del_new_on_log = 1 // del's new players if they log before they spawn in - var/allow_Metadata = 0 // Metadata is supported. - var/popup_admin_pm = 0 //adminPMs to non-admins show in a pop-up 'reply' window when set to 1. - var/fps = 20 - var/allow_holidays = 0 //toggles whether holiday-specific content should be used - var/tick_limit_mc_init = TICK_LIMIT_MC_INIT_DEFAULT //SSinitialization throttling - - var/hostedby = null - var/respawn = 1 - var/guest_jobban = 1 - var/usewhitelist = 0 - var/inactivity_period = 3000 //time in ds until a player is considered inactive - var/afk_period = 6000 //time in ds until a player is considered afk and kickable - var/kick_inactive = FALSE //force disconnect for inactive players - var/load_jobs_from_txt = 0 - var/automute_on = 0 //enables automuting/spam prevention - var/minimal_access_threshold = 0 //If the number of players is larger than this threshold, minimal access will be turned on. - var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access. - var/jobs_have_maint_access = 0 //Who gets maint access? See defines above. - var/sec_start_brig = 0 //makes sec start in brig or dept sec posts - - var/server - var/banappeals - var/wikiurl = "http://www.tgstation13.org/wiki" // Default wiki link. - var/forumurl = "http://tgstation13.org/phpBB/index.php" //default forums - var/rulesurl = "http://www.tgstation13.org/wiki/Rules" // default rules - var/githuburl = "https://www.github.com/tgstation/-tg-station" //default github - var/githubrepoid - - var/forbid_singulo_possession = 0 - var/useircbot = 0 - - var/check_randomizer = 0 - - var/panic_server_name - var/panic_address //Reconnect a player this linked server if this server isn't accepting new players - - var/invoke_youtubedl - - //IP Intel vars - var/ipintel_email - var/ipintel_rating_bad = 1 - var/ipintel_save_good = 12 - var/ipintel_save_bad = 1 - var/ipintel_domain = "check.getipintel.net" - - var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt - var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt - var/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database - var/use_account_age_for_jobs = 0 //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected. - var/see_own_notes = 0 //Can players see their own admin notes (read-only)? Config option in config.txt - var/note_fresh_days - var/note_stale_days - - var/use_exp_tracking = FALSE - var/use_exp_restrictions_heads = FALSE - var/use_exp_restrictions_heads_hours = 0 - var/use_exp_restrictions_heads_department = FALSE - var/use_exp_restrictions_other = FALSE - var/use_exp_restrictions_admin_bypass = FALSE - - //Population cap vars - var/soft_popcap = 0 - var/hard_popcap = 0 - var/extreme_popcap = 0 - var/soft_popcap_message = "Be warned that the server is currently serving a high number of users, consider using alternative game servers." - var/hard_popcap_message = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers." - var/extreme_popcap_message = "The server is currently serving a high number of users, find alternative servers." - - //game_options.txt configs - var/force_random_names = 0 - var/list/mode_names = list() - var/list/mode_reports = list() - var/list/mode_false_report_weight = list() - var/list/modes = list() // allowed modes - var/list/votable_modes = list() // votable modes - var/list/probabilities = list() // relative probability of each mode - var/list/min_pop = list() // overrides for acceptible player counts in a mode - var/list/max_pop = list() - var/list/repeated_mode_adjust = list() // weight adjustments for recent modes - - var/humans_need_surnames = 0 - var/allow_ai = 0 // allow ai job - var/forbid_secborg = 0 // disallow secborg module to be chosen. - var/forbid_peaceborg = 0 - var/panic_bunker = 0 // prevents new people it hasn't seen before from connecting - var/notify_new_player_age = 0 // how long do we notify admins of a new player - var/notify_new_player_account_age = 0 // how long do we notify admins of a new byond account - var/irc_first_connection_alert = 0 // do we notify the irc channel when somebody is connecting for the first time? - - var/traitor_scaling_coeff = 6 //how much does the amount of players get divided by to determine traitors - var/brother_scaling_coeff = 25 //how many players per brother team - var/changeling_scaling_coeff = 6 //how much does the amount of players get divided by to determine changelings - var/security_scaling_coeff = 8 //how much does the amount of players get divided by to determine open security officer positions - var/abductor_scaling_coeff = 15 //how many players per abductor team - - var/traitor_objectives_amount = 2 - var/brother_objectives_amount = 2 - var/protect_roles_from_antagonist = 0 //If security and such can be traitor/cult/other - var/protect_assistant_from_antagonist = 0 //If assistants can be traitor/cult/other - var/enforce_human_authority = 0 //If non-human species are barred from joining as a head of staff - var/allow_latejoin_antagonists = 0 // If late-joining players can be traitor/changeling - var/list/continuous = list() // which roundtypes continue if all antagonists die - var/list/midround_antag = list() // which roundtypes use the midround antagonist system - var/midround_antag_time_check = 60 // How late (in minutes) you want the midround antag system to stay on, setting this to 0 will disable the system - var/midround_antag_life_check = 0.7 // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist - var/shuttle_refuel_delay = 12000 - var/show_game_type_odds = 0 //if set this allows players to see the odds of each roundtype on the get revision screen - var/mutant_races = 0 //players can choose their mutant race before joining the game - var/list/roundstart_races = list() //races you can play as from the get go. If left undefined the game's roundstart var for species is used - var/mutant_humans = 0 //players can pick mutant bodyparts for humans before joining the game - - var/no_summon_guns //No - var/no_summon_magic //Fun - var/no_summon_events //Allowed - - var/intercept = 1 //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes. - var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced." - var/alert_desc_blue_upto = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted." - var/alert_desc_blue_downto = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed." - var/alert_desc_red_upto = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised." - var/alert_desc_red_downto = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised." - var/alert_desc_delta = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill." - - var/revival_pod_plants = FALSE - var/revival_cloning = FALSE - var/revival_brain_life = -1 - - var/rename_cyborg = 0 - var/ooc_during_round = 0 - var/emojis = 0 - - //Used for modifying movement speed for mobs. - //Unversal modifiers - var/run_speed = 0 - var/walk_speed = 0 - - //Mob specific modifiers. NOTE: These will affect different mob types in different ways - var/human_delay = 0 - var/robot_delay = 0 - var/monkey_delay = 0 - var/alien_delay = 0 - var/slime_delay = 0 - var/animal_delay = 0 - - var/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour. - var/ghost_interaction = 0 - - var/silent_ai = 0 - var/silent_borg = 0 - - var/damage_multiplier = 1 //Modifier for damage to all mobs. Impacts healing as well. - - var/allowwebclient = 0 - var/webclientmembersonly = 0 - - var/sandbox_autoclose = FALSE // close the sandbox panel after spawning an item, potentially reducing griff - - var/default_laws = 0 //Controls what laws the AI spawns with. - var/silicon_max_law_amount = 12 - var/list/lawids = list() - - var/list/law_weights = list() - - var/assistant_cap = -1 - - var/starlight = 0 - var/generate_minimaps = 0 - var/grey_assistants = 0 - - var/id_console_jobslot_delay = 30 - - var/lavaland_budget = 60 - var/space_budget = 16 - - var/aggressive_changelog = 0 - - var/reactionary_explosions = 0 //If we use reactionary explosions, explosions that react to walls and doors - - var/autoconvert_notes = 0 //if all connecting player's notes should attempt to be converted to the database - - var/announce_admin_logout = 0 - var/announce_admin_login = 0 - - var/list/datum/map_config/maplist = list() - var/datum/map_config/defaultmap = null - var/maprotation = 1 - var/maprotatechancedelta = 0.75 - var/allow_map_voting = TRUE - - // Enables random events mid-round when set to 1 - var/allow_random_events = 0 - - // Multipliers for random events minimal starting time and minimal players amounts - var/events_min_time_mul = 1 - var/events_min_players_mul = 1 - - // The object used for the clickable stat() button. - var/obj/effect/statclick/statclick - - var/client_warn_version = 0 - var/client_warn_message = "Your version of byond may have issues or be blocked from accessing this server in the future." - var/client_error_version = 0 - var/client_error_message = "Your version of byond is too old, may have issues, and is blocked from accessing this server." - - var/cross_name = "Other server" - var/cross_address = "byond://" - var/cross_allowed = FALSE - var/showircname = 0 - - var/list/gamemode_cache = null - - var/minutetopiclimit - var/secondtopiclimit - - var/error_cooldown = 600 // The "cooldown" time for each occurrence of a unique error - var/error_limit = 50 // How many occurrences before the next will silence them - var/error_silence_time = 6000 // How long a unique error will be silenced for - var/error_msg_delay = 50 // How long to wait between messaging admins about occurrences of a unique error - - var/arrivals_shuttle_dock_window = 55 //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station - var/arrivals_shuttle_require_undocked = FALSE //Require the arrivals shuttle to be undocked before latejoiners can join - var/arrivals_shuttle_require_safe_latejoin = FALSE //Require the arrivals shuttle to be operational in order for latejoiners to join - - var/mice_roundstart = 10 // how many wire chewing rodents spawn at roundstart. - - var/irc_announce_new_game = FALSE - - var/list/policies = list() - - var/debug_admin_hrefs = FALSE //turns off admin href token protection for debugging purposes - -/datum/configuration/New() - gamemode_cache = typecacheof(/datum/game_mode,TRUE) - for(var/T in gamemode_cache) - // I wish I didn't have to instance the game modes in order to look up - // their information, but it is the only way (at least that I know of). - var/datum/game_mode/M = new T() - - if(M.config_tag) - if(!(M.config_tag in modes)) // ensure each mode is added only once - WRITE_FILE(GLOB.config_error_log, "Adding game mode [M.name] ([M.config_tag]) to configuration.") - modes += M.config_tag - mode_names[M.config_tag] = M.name - probabilities[M.config_tag] = M.probability - mode_reports[M.config_tag] = M.generate_report() - mode_false_report_weight[M.config_tag] = M.false_report_weight - if(M.votable) - votable_modes += M.config_tag - qdel(M) - votable_modes += "secret" - - Reload() - -/datum/configuration/proc/Reload() - load("config.txt") - load("comms.txt", "comms") - load("game_options.txt","game_options") - load("policies.txt", "policies") - loadsql("dbconfig.txt") - if (maprotation) - loadmaplist("maps.txt") - - // apply some settings from config.. - GLOB.abandon_allowed = respawn - -/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist - filename = "[GLOB.config_dir][filename]" - var/list/Lines = world.file2list(filename) - for(var/t in Lines) - if(!t) - continue - - t = trim(t) - if(length(t) == 0) - continue - else if(copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/name = null - var/value = null - - if(pos) - name = lowertext(copytext(t, 1, pos)) - value = copytext(t, pos + 1) - else - name = lowertext(t) - - if(!name) - continue - - if(type == "config") - switch(name) - if("hub") - hub = 1 - if("admin_legacy_system") - admin_legacy_system = 1 - if("ban_legacy_system") - ban_legacy_system = 1 - if("use_age_restriction_for_jobs") - use_age_restriction_for_jobs = 1 - if("use_account_age_for_jobs") - use_account_age_for_jobs = 1 - if("use_exp_tracking") - use_exp_tracking = TRUE - if("use_exp_restrictions_heads") - use_exp_restrictions_heads = TRUE - if("use_exp_restrictions_heads_hours") - use_exp_restrictions_heads_hours = text2num(value) - if("use_exp_restrictions_heads_department") - use_exp_restrictions_heads_department = TRUE - if("use_exp_restrictions_other") - use_exp_restrictions_other = TRUE - if("use_exp_restrictions_admin_bypass") - use_exp_restrictions_admin_bypass = TRUE - if("lobby_countdown") - lobby_countdown = text2num(value) - if("round_end_countdown") - round_end_countdown = text2num(value) - if("log_ooc") - log_ooc = 1 - if("log_access") - log_access = 1 - if("log_say") - log_say = 1 - if("log_admin") - log_admin = 1 - if("log_prayer") - log_prayer = 1 - if("log_law") - log_law = 1 - if("log_game") - log_game = 1 - if("log_vote") - log_vote = 1 - if("log_whisper") - log_whisper = 1 - if("log_attack") - log_attack = 1 - if("log_emote") - log_emote = 1 - if("log_adminchat") - log_adminchat = 1 - if("log_pda") - log_pda = 1 - if("log_twitter") - log_twitter = 1 - if("log_world_topic") - log_world_topic = 1 - if("allow_admin_ooccolor") - allow_admin_ooccolor = 1 - if("allow_vote_restart") - allow_vote_restart = 1 - if("allow_vote_mode") - allow_vote_mode = 1 - if("no_dead_vote") - vote_no_dead = 1 - if("default_no_vote") - vote_no_default = 1 - if("vote_delay") - vote_delay = text2num(value) - if("vote_period") - vote_period = text2num(value) - if("norespawn") - respawn = 0 - if("servername") - server_name = value - if("serversqlname") - server_sql_name = value - if("stationname") - station_name = value - if("hostedby") - hostedby = value - if("server") - server = value - if("banappeals") - banappeals = value - if("wikiurl") - wikiurl = value - if("forumurl") - forumurl = value - if("rulesurl") - rulesurl = value - if("githuburl") - githuburl = value - if("githubrepoid") - githubrepoid = value - if("guest_jobban") - guest_jobban = 1 - if("guest_ban") - GLOB.guests_allowed = 0 - if("usewhitelist") - usewhitelist = TRUE - if("allow_metadata") - allow_Metadata = 1 - if("id_console_jobslot_delay") - id_console_jobslot_delay = text2num(value) - if("inactivity_period") - inactivity_period = text2num(value) * 10 //documented as seconds in config.txt - if("afk_period") - afk_period = text2num(value) * 10 // ^^^ - if("kick_inactive") - kick_inactive = TRUE - if("load_jobs_from_txt") - load_jobs_from_txt = 1 - if("forbid_singulo_possession") - forbid_singulo_possession = 1 - if("popup_admin_pm") - popup_admin_pm = 1 - if("allow_holidays") - allow_holidays = 1 - if("useircbot") //tgs2 support - useircbot = 1 - if("ticklag") - var/ticklag = text2num(value) - if(ticklag > 0) - fps = 10 / ticklag - if("tick_limit_mc_init") - tick_limit_mc_init = text2num(value) - if("fps") - fps = text2num(value) - if("automute_on") - automute_on = 1 - if("panic_server_name") - if (value != "\[Put the name here\]") - panic_server_name = value - if("panic_server_address") - if(value != "byond://address:port") - panic_address = value - if("invoke_youtubedl") - invoke_youtubedl = value - if("show_irc_name") - showircname = 1 - if("see_own_notes") - see_own_notes = 1 - if("note_fresh_days") - note_fresh_days = text2num(value) - if("note_stale_days") - note_stale_days = text2num(value) - if("soft_popcap") - soft_popcap = text2num(value) - if("hard_popcap") - hard_popcap = text2num(value) - if("extreme_popcap") - extreme_popcap = text2num(value) - if("soft_popcap_message") - soft_popcap_message = value - if("hard_popcap_message") - hard_popcap_message = value - if("extreme_popcap_message") - extreme_popcap_message = value - if("panic_bunker") - panic_bunker = 1 - if("notify_new_player_age") - notify_new_player_age = text2num(value) - if("notify_new_player_account_age") - notify_new_player_account_age = text2num(value) - if("irc_first_connection_alert") - irc_first_connection_alert = 1 - if("check_randomizer") - check_randomizer = 1 - if("ipintel_email") - if (value != "ch@nge.me") - ipintel_email = value - if("ipintel_rating_bad") - ipintel_rating_bad = text2num(value) - if("ipintel_domain") - ipintel_domain = value - if("ipintel_save_good") - ipintel_save_good = text2num(value) - if("ipintel_save_bad") - ipintel_save_bad = text2num(value) - if("aggressive_changelog") - aggressive_changelog = 1 - if("autoconvert_notes") - autoconvert_notes = 1 - if("allow_webclient") - allowwebclient = 1 - if("webclient_only_byond_members") - webclientmembersonly = 1 - if("announce_admin_logout") - announce_admin_logout = 1 - if("announce_admin_login") - announce_admin_login = 1 - if("maprotation") - maprotation = 1 - if("allow_map_voting") - allow_map_voting = text2num(value) - if("maprotationchancedelta") - maprotatechancedelta = text2num(value) - if("autoadmin") - autoadmin = 1 - if(value) - autoadmin_rank = ckeyEx(value) - if("generate_minimaps") - generate_minimaps = 1 - if("client_warn_version") - client_warn_version = text2num(value) - if("client_warn_message") - client_warn_message = value - if("client_error_version") - client_error_version = text2num(value) - if("client_error_message") - client_error_message = value - if("minute_topic_limit") - minutetopiclimit = text2num(value) - if("second_topic_limit") - secondtopiclimit = text2num(value) - if("error_cooldown") - error_cooldown = text2num(value) - if("error_limit") - error_limit = text2num(value) - if("error_silence_time") - error_silence_time = text2num(value) - if("error_msg_delay") - error_msg_delay = text2num(value) - if("irc_announce_new_game") - irc_announce_new_game = TRUE - if("debug_admin_hrefs") - debug_admin_hrefs = TRUE - else -#if DM_VERSION > 511 -#error Replace the line below with WRITE_FILE(GLOB.config_error_log, "Unknown setting in configuration: '[name]'") -#endif - HandleCommsConfig(name, value) //TODO: Deprecate this eventually - else if(type == "comms") - HandleCommsConfig(name, value) - else if(type == "game_options") - switch(name) - if("damage_multiplier") - damage_multiplier = text2num(value) - if("revival_pod_plants") - revival_pod_plants = TRUE - if("revival_cloning") - revival_cloning = TRUE - if("revival_brain_life") - revival_brain_life = text2num(value) - if("rename_cyborg") - rename_cyborg = 1 - if("ooc_during_round") - ooc_during_round = 1 - if("emojis") - emojis = 1 - if("run_delay") - run_speed = text2num(value) - if("walk_delay") - walk_speed = text2num(value) - if("human_delay") - human_delay = text2num(value) - if("robot_delay") - robot_delay = text2num(value) - if("monkey_delay") - monkey_delay = text2num(value) - if("alien_delay") - alien_delay = text2num(value) - if("slime_delay") - slime_delay = text2num(value) - if("animal_delay") - animal_delay = text2num(value) - if("alert_red_upto") - alert_desc_red_upto = value - if("alert_red_downto") - alert_desc_red_downto = value - if("alert_blue_downto") - alert_desc_blue_downto = value - if("alert_blue_upto") - alert_desc_blue_upto = value - if("alert_green") - alert_desc_green = value - if("alert_delta") - alert_desc_delta = value - if("no_intercept_report") - intercept = 0 - if("assistants_have_maint_access") - jobs_have_maint_access |= ASSISTANTS_HAVE_MAINT_ACCESS - if("security_has_maint_access") - jobs_have_maint_access |= SECURITY_HAS_MAINT_ACCESS - if("everyone_has_maint_access") - jobs_have_maint_access |= EVERYONE_HAS_MAINT_ACCESS - if("sec_start_brig") - sec_start_brig = 1 - if("gateway_delay") - gateway_delay = text2num(value) - if("continuous") - var/mode_name = lowertext(value) - if(mode_name in modes) - continuous[mode_name] = 1 - else - WRITE_FILE(GLOB.config_error_log, "Unknown continuous configuration definition: [mode_name].") - if("midround_antag") - var/mode_name = lowertext(value) - if(mode_name in modes) - midround_antag[mode_name] = 1 - else - WRITE_FILE(GLOB.config_error_log, "Unknown midround antagonist configuration definition: [mode_name].") - if("midround_antag_time_check") - midround_antag_time_check = text2num(value) - if("midround_antag_life_check") - midround_antag_life_check = text2num(value) - if("min_pop") - var/pop_pos = findtext(value, " ") - var/mode_name = null - var/mode_value = null - - if(pop_pos) - mode_name = lowertext(copytext(value, 1, pop_pos)) - mode_value = copytext(value, pop_pos + 1) - if(mode_name in modes) - min_pop[mode_name] = text2num(mode_value) - else - WRITE_FILE(GLOB.config_error_log, "Unknown minimum population configuration definition: [mode_name].") - else - WRITE_FILE(GLOB.config_error_log, "Incorrect minimum population configuration definition: [mode_name] [mode_value].") - if("max_pop") - var/pop_pos = findtext(value, " ") - var/mode_name = null - var/mode_value = null - - if(pop_pos) - mode_name = lowertext(copytext(value, 1, pop_pos)) - mode_value = copytext(value, pop_pos + 1) - if(mode_name in modes) - max_pop[mode_name] = text2num(mode_value) - else - WRITE_FILE(GLOB.config_error_log, "Unknown maximum population configuration definition: [mode_name].") - else - WRITE_FILE(GLOB.config_error_log, "Incorrect maximum population configuration definition: [mode_name] [mode_value].") - if("shuttle_refuel_delay") - shuttle_refuel_delay = text2num(value) - if("show_game_type_odds") - show_game_type_odds = 1 - if("ghost_interaction") - ghost_interaction = 1 - if("traitor_scaling_coeff") - traitor_scaling_coeff = text2num(value) - if("brother_scaling_coeff") - brother_scaling_coeff = text2num(value) - if("changeling_scaling_coeff") - changeling_scaling_coeff = text2num(value) - if("security_scaling_coeff") - security_scaling_coeff = text2num(value) - if("abductor_scaling_coeff") - abductor_scaling_coeff = text2num(value) - if("traitor_objectives_amount") - traitor_objectives_amount = text2num(value) - if("brother_objectives_amount") - brother_objectives_amount = text2num(value) - if("probability") - var/prob_pos = findtext(value, " ") - var/prob_name = null - var/prob_value = null - - if(prob_pos) - prob_name = lowertext(copytext(value, 1, prob_pos)) - prob_value = copytext(value, prob_pos + 1) - if(prob_name in modes) - probabilities[prob_name] = text2num(prob_value) - else - WRITE_FILE(GLOB.config_error_log, "Unknown game mode probability configuration definition: [prob_name].") - else - WRITE_FILE(GLOB.config_error_log, "Incorrect probability configuration definition: [prob_name] [prob_value].") - if("repeated_mode_adjust") - if(value) - repeated_mode_adjust.Cut() - var/values = splittext(value," ") - for(var/v in values) - repeated_mode_adjust += text2num(v) - else - WRITE_FILE(GLOB.config_error_log, "Incorrect round weight adjustment configuration definition for [value].") - if("protect_roles_from_antagonist") - protect_roles_from_antagonist = 1 - if("protect_assistant_from_antagonist") - protect_assistant_from_antagonist = 1 - if("enforce_human_authority") - enforce_human_authority = 1 - if("allow_latejoin_antagonists") - allow_latejoin_antagonists = 1 - if("allow_random_events") - allow_random_events = 1 - - if("events_min_time_mul") - events_min_time_mul = text2num(value) - if("events_min_players_mul") - events_min_players_mul = text2num(value) - - if("minimal_access_threshold") - minimal_access_threshold = text2num(value) - if("jobs_have_minimal_access") - jobs_have_minimal_access = 1 - if("humans_need_surnames") - humans_need_surnames = 1 - if("force_random_names") - force_random_names = 1 - if("allow_ai") - allow_ai = 1 - if("disable_secborg") - forbid_secborg = 1 - if("disable_peaceborg") - forbid_peaceborg = 1 - if("silent_ai") - silent_ai = 1 - if("silent_borg") - silent_borg = 1 - if("sandbox_autoclose") - sandbox_autoclose = 1 - if("default_laws") - default_laws = text2num(value) - if("random_laws") - var/law_id = lowertext(value) - lawids += law_id - if("law_weight") - // Value is in the form "LAWID,NUMBER" - var/list/L = splittext(value, ",") - if(L.len != 2) - WRITE_FILE(GLOB.config_error_log, "Invalid LAW_WEIGHT: " + t) - continue - var/lawid = L[1] - var/weight = text2num(L[2]) - law_weights[lawid] = weight - - if("silicon_max_law_amount") - silicon_max_law_amount = text2num(value) - if("join_with_mutant_race") - mutant_races = 1 - if("roundstart_races") - var/race_id = lowertext(value) - for(var/species_id in GLOB.species_list) - if(species_id == race_id) - roundstart_races += GLOB.species_list[species_id] - GLOB.roundstart_species[species_id] = GLOB.species_list[species_id] - if("join_with_mutant_humans") - mutant_humans = 1 - if("assistant_cap") - assistant_cap = text2num(value) - if("starlight") - starlight = 1 - if("grey_assistants") - grey_assistants = 1 - if("lavaland_budget") - lavaland_budget = text2num(value) - if("space_budget") - space_budget = text2num(value) - if("no_summon_guns") - no_summon_guns = 1 - if("no_summon_magic") - no_summon_magic = 1 - if("no_summon_events") - no_summon_events = 1 - if("reactionary_explosions") - reactionary_explosions = 1 - if("bombcap") - var/BombCap = text2num(value) - if (!BombCap) - continue - if (BombCap < 4) - BombCap = 4 - - GLOB.MAX_EX_DEVESTATION_RANGE = round(BombCap/4) - GLOB.MAX_EX_HEAVY_RANGE = round(BombCap/2) - GLOB.MAX_EX_LIGHT_RANGE = BombCap - GLOB.MAX_EX_FLASH_RANGE = BombCap - GLOB.MAX_EX_FLAME_RANGE = BombCap - if("arrivals_shuttle_dock_window") - arrivals_shuttle_dock_window = max(PARALLAX_LOOP_TIME, text2num(value)) - if("arrivals_shuttle_require_undocked") - arrivals_shuttle_require_undocked = TRUE - if("arrivals_shuttle_require_safe_latejoin") - arrivals_shuttle_require_safe_latejoin = TRUE - if("mice_roundstart") - mice_roundstart = text2num(value) - else - WRITE_FILE(GLOB.config_error_log, "Unknown setting in configuration: '[name]'") - else if(type == "policies") - policies[name] = value - - fps = round(fps) - if(fps <= 0) - fps = initial(fps) - -/datum/configuration/proc/HandleCommsConfig(name, value) - switch(name) - if("comms_key") - global.comms_key = value - if(value != "default_pwd" && length(value) > 6) //It's the default value or less than 6 characters long, warn badmins - global.comms_allowed = TRUE - if("cross_server_address") - cross_address = value - if(value != "byond:\\address:port") - cross_allowed = TRUE - if("cross_comms_name") - cross_name = value - if("medal_hub_address") - global.medal_hub = value - if("medal_hub_password") - global.medal_pass = value - else - WRITE_FILE(GLOB.config_error_log, "Unknown setting in configuration: '[name]'") - -/datum/configuration/proc/loadmaplist(filename) - filename = "[GLOB.config_dir][filename]" - var/list/Lines = world.file2list(filename) - - var/datum/map_config/currentmap = null - for(var/t in Lines) - if(!t) - continue - - t = trim(t) - if(length(t) == 0) - continue - else if(copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/command = null - var/data = null - - if(pos) - command = lowertext(copytext(t, 1, pos)) - data = copytext(t, pos + 1) - else - command = lowertext(t) - - if(!command) - continue - - if (!currentmap && command != "map") - continue - - switch (command) - if ("map") - currentmap = new ("_maps/[data].json") - if(currentmap.defaulted) - log_world("Failed to load map config for [data]!") - if ("minplayers","minplayer") - currentmap.config_min_users = text2num(data) - if ("maxplayers","maxplayer") - currentmap.config_max_users = text2num(data) - if ("weight","voteweight") - currentmap.voteweight = text2num(data) - if ("default","defaultmap") - defaultmap = currentmap - if ("endmap") - maplist[currentmap.map_name] = currentmap - currentmap = null - if ("disabled") - currentmap = null - else - WRITE_FILE(GLOB.config_error_log, "Unknown command in map vote config: '[command]'") - - -/datum/configuration/proc/loadsql(filename) - filename = "[GLOB.config_dir][filename]" - var/list/Lines = world.file2list(filename) - for(var/t in Lines) - if(!t) - continue - - t = trim(t) - if(length(t) == 0) - continue - else if(copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/name = null - var/value = null - - if(pos) - name = lowertext(copytext(t, 1, pos)) - value = copytext(t, pos + 1) - else - name = lowertext(t) - - if(!name) - continue - - switch(name) - if("sql_enabled") - sql_enabled = 1 - if("address") - global.sqladdress = value - if("port") - global.sqlport = value - if("feedback_database") - global.sqlfdbkdb = value - if("feedback_login") - global.sqlfdbklogin = value - if("feedback_password") - global.sqlfdbkpass = value - if("feedback_tableprefix") - global.sqlfdbktableprefix = value - else - WRITE_FILE(GLOB.config_error_log, "Unknown setting in configuration: '[name]'") - -/datum/configuration/proc/pick_mode(mode_name) - // I wish I didn't have to instance the game modes in order to look up - // their information, but it is the only way (at least that I know of). - // ^ This guy didn't try hard enough - for(var/T in gamemode_cache) - var/datum/game_mode/M = T - var/ct = initial(M.config_tag) - if(ct && ct == mode_name) - return new T - return new /datum/game_mode/extended() - -/datum/configuration/proc/get_runnable_modes() - var/list/datum/game_mode/runnable_modes = new - for(var/T in gamemode_cache) - var/datum/game_mode/M = new T() - if(!(M.config_tag in modes)) - qdel(M) - continue - if(probabilities[M.config_tag]<=0) - qdel(M) - continue - if(min_pop[M.config_tag]) - M.required_players = min_pop[M.config_tag] - if(max_pop[M.config_tag]) - M.maximum_players = max_pop[M.config_tag] - if(M.can_start()) - var/final_weight = probabilities[M.config_tag] - if(SSpersistence.saved_modes.len == 3 && repeated_mode_adjust.len == 3) - var/recent_round = min(SSpersistence.saved_modes.Find(M.config_tag),3) - var/adjustment = 0 - while(recent_round) - adjustment += repeated_mode_adjust[recent_round] - recent_round = SSpersistence.saved_modes.Find(M.config_tag,recent_round+1,0) - final_weight *= ((100-adjustment)/100) - runnable_modes[M] = final_weight - return runnable_modes - -/datum/configuration/proc/get_runnable_midround_modes(crew) - var/list/datum/game_mode/runnable_modes = new - for(var/T in (gamemode_cache - SSticker.mode.type)) - var/datum/game_mode/M = new T() - if(!(M.config_tag in modes)) - qdel(M) - continue - if(probabilities[M.config_tag]<=0) - qdel(M) - continue - if(min_pop[M.config_tag]) - M.required_players = min_pop[M.config_tag] - if(max_pop[M.config_tag]) - M.maximum_players = max_pop[M.config_tag] - if(M.required_players <= crew) - if(M.maximum_players >= 0 && M.maximum_players < crew) - continue - runnable_modes[M] = probabilities[M.config_tag] - return runnable_modes - -/datum/configuration/proc/stat_entry() - if(!statclick) - statclick = new/obj/effect/statclick/debug(null, "Edit", src) - - stat("[name]:", statclick) diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm new file mode 100644 index 00000000000..5358073dbea --- /dev/null +++ b/code/controllers/configuration/config_entry.dm @@ -0,0 +1,178 @@ +#undef CURRENT_RESIDENT_FILE + +#define LIST_MODE_NUM 0 +#define LIST_MODE_TEXT 1 +#define LIST_MODE_FLAG 2 + +/datum/config_entry + var/name //read-only, this is determined by the last portion of the derived entry type + var/value + var/default //read-only, just set value directly + + var/resident_file //the file which this belongs to, must be set + var/modified = FALSE //set to TRUE if the default has been overridden by a config entry + + var/protection = NONE + var/abstract_type = /datum/config_entry //do not instantiate if type matches this + + var/dupes_allowed = FALSE + +/datum/config_entry/New() + if(!resident_file) + CRASH("Config entry [type] has no resident_file set") + if(type == abstract_type) + CRASH("Abstract config entry [type] instatiated!") + name = lowertext(type2top(type)) + if(islist(value)) + var/list/L = value + default = L.Copy() + else + default = value + +/datum/config_entry/Destroy() + config.RemoveEntry(src) + return ..() + +/datum/config_entry/can_vv_get(var_name) + . = ..() + if(var_name == "value" || var_name == "default") + . &= !(protection & CONFIG_ENTRY_HIDDEN) + +/datum/config_entry/vv_edit_var(var_name, var_value) + var/static/list/banned_edits = list("name", "default", "resident_file", "protection", "abstract_type", "modified", "dupes_allowed") + if(var_name == "value") + if(protection & CONFIG_ENTRY_LOCKED) + return FALSE + . = ValidateAndSet("[var_value]") + if(.) + var_edited = TRUE + return + if(var_name in banned_edits) + return FALSE + return ..() + +/datum/config_entry/proc/ValidateAndSet(str_val) + CRASH("Invalid config entry type!") + +/datum/config_entry/proc/ValidateKeyedList(str_val, list_mode, splitter) + str_val = trim(str_val) + var/key_pos = findtext(str_val, splitter) + var/key_name = null + var/key_value = null + + if(key_pos || list_mode == LIST_MODE_FLAG) + key_name = lowertext(copytext(str_val, 1, key_pos)) + key_value = copytext(str_val, key_pos + 1) + var/temp + var/continue_check + switch(list_mode) + if(LIST_MODE_FLAG) + temp = TRUE + continue_check = TRUE + if(LIST_MODE_NUM) + temp = text2num(key_value) + continue_check = !isnull(temp) + if(LIST_MODE_TEXT) + temp = key_value + continue_check = temp + if(continue_check && ValidateKeyName(key_name)) + value[key_name] = temp + return TRUE + return FALSE + +/datum/config_entry/proc/ValidateKeyName(key_name) + return TRUE + +/datum/config_entry/string + value = "" + abstract_type = /datum/config_entry/string + var/auto_trim = TRUE + +/datum/config_entry/string/vv_edit_var(var_name, var_value) + return var_name != "auto_trim" && ..() + +/datum/config_entry/string/ValidateAndSet(str_val) + value = auto_trim ? trim(str_val) : str_val + return TRUE + +/datum/config_entry/number + value = 0 + abstract_type = /datum/config_entry/number + var/integer = TRUE + var/max_val = INFINITY + var/min_val = -INFINITY + +/datum/config_entry/number/ValidateAndSet(str_val) + var/temp = text2num(trim(str_val)) + if(!isnull(temp)) + value = Clamp(integer ? round(temp) : temp, min_val, max_val) + if(value != temp && !var_edited) + log_config("Changing [name] from [temp] to [value]!") + return TRUE + return FALSE + +/datum/config_entry/number/vv_edit_var(var_name, var_value) + var/static/list/banned_edits = list("max_val", "min_val", "integer") + return !(var_name in banned_edits) && ..() + +/datum/config_entry/flag + value = FALSE + abstract_type = /datum/config_entry/flag + +/datum/config_entry/flag/ValidateAndSet(str_val) + value = text2num(trim(str_val)) != 0 + return TRUE + +/datum/config_entry/number_list + abstract_type = /datum/config_entry/number_list + value = list() + +/datum/config_entry/number_list/ValidateAndSet(str_val) + str_val = trim(str_val) + var/list/new_list = list() + var/list/values = splittext(str_val," ") + for(var/I in values) + var/temp = text2num(I) + if(isnull(temp)) + return FALSE + new_list += temp + if(!new_list.len) + return FALSE + value = new_list + return TRUE + +/datum/config_entry/keyed_flag_list + abstract_type = /datum/config_entry/keyed_flag_list + value = list() + dupes_allowed = TRUE + +/datum/config_entry/keyed_flag_list/ValidateAndSet(str_val) + return ValidateKeyedList(str_val, LIST_MODE_FLAG, " ") + +/datum/config_entry/keyed_number_list + abstract_type = /datum/config_entry/keyed_number_list + value = list() + dupes_allowed = TRUE + var/splitter = " " + +/datum/config_entry/keyed_number_list/vv_edit_var(var_name, var_value) + return var_name != "splitter" && ..() + +/datum/config_entry/keyed_number_list/ValidateAndSet(str_val) + return ValidateKeyedList(str_val, LIST_MODE_NUM, splitter) + +/datum/config_entry/keyed_string_list + abstract_type = /datum/config_entry/keyed_string_list + value = list() + dupes_allowed = TRUE + var/splitter = " " + +/datum/config_entry/keyed_string_list/vv_edit_var(var_name, var_value) + return var_name != "splitter" && ..() + +/datum/config_entry/keyed_string_list/ValidateAndSet(str_val) + return ValidateKeyedList(str_val, LIST_MODE_TEXT, splitter) + +#undef LIST_MODE_NUM +#undef LIST_MODE_TEXT +#undef LIST_MODE_FLAG diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm new file mode 100644 index 00000000000..7624d2473d0 --- /dev/null +++ b/code/controllers/configuration/configuration.dm @@ -0,0 +1,281 @@ +GLOBAL_VAR_INIT(config_dir, "config/") +GLOBAL_PROTECT(config_dir) + +/datum/controller/configuration + name = "Configuration" + + var/hiding_entries_by_type = TRUE //Set for readability, admins can set this to FALSE if they want to debug it + var/list/entries + var/list/entries_by_type + + var/list/maplist + var/datum/map_config/defaultmap + + var/list/modes // allowed modes + var/list/gamemode_cache + var/list/votable_modes // votable modes + var/list/mode_names + var/list/mode_reports + var/list/mode_false_report_weight + +/datum/controller/configuration/New() + config = src + var/list/config_files = InitEntries() + LoadModes() + for(var/I in config_files) + LoadEntries(I) + if(Get(/datum/config_entry/flag/maprotation)) + loadmaplist(CONFIG_MAPS_FILE) + +/datum/controller/configuration/Destroy() + entries_by_type.Cut() + QDEL_LIST_ASSOC_VAL(entries) + QDEL_LIST_ASSOC_VAL(maplist) + QDEL_NULL(defaultmap) + + config = null + + return ..() + +/datum/controller/configuration/proc/InitEntries() + var/list/_entries = list() + entries = _entries + var/list/_entries_by_type = list() + entries_by_type = _entries_by_type + + . = list() + + for(var/I in typesof(/datum/config_entry)) //typesof is faster in this case + var/datum/config_entry/E = I + if(initial(E.abstract_type) == I) + continue + E = new I + _entries_by_type[I] = E + var/esname = E.name + var/datum/config_entry/test = _entries[esname] + if(test) + log_config("Error: [test.type] has the same name as [E.type]: [esname]! Not initializing [E.type]!") + qdel(E) + continue + _entries[esname] = E + .[E.resident_file] = TRUE + +/datum/controller/configuration/proc/RemoveEntry(datum/config_entry/CE) + entries -= CE.name + entries_by_type -= CE.type + +/datum/controller/configuration/proc/LoadEntries(filename) + log_config("Loading config file [filename]...") + var/list/lines = world.file2list("[GLOB.config_dir][filename]") + var/list/_entries = entries + for(var/L in lines) + if(!L) + continue + + if(copytext(L, 1, 2) == "#") + continue + + var/pos = findtext(L, " ") + var/entry = null + var/value = null + + if(pos) + entry = lowertext(copytext(L, 1, pos)) + value = copytext(L, pos + 1) + else + entry = lowertext(L) + + if(!entry) + continue + + var/datum/config_entry/E = _entries[entry] + if(!E) + log_config("Unknown setting in configuration: '[entry]'") + continue + + if(filename != E.resident_file) + log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.") + continue + + var/validated = E.ValidateAndSet(value) + if(!validated) + log_config("Failed to validate setting \"[value]\" for [entry]") + else if(E.modified && !E.dupes_allowed) + log_config("Duplicate setting for [entry] ([value]) detected! Using latest.") + + if(validated) + E.modified = TRUE + +/datum/controller/configuration/can_vv_get(var_name) + return (var_name != "entries_by_type" || !hiding_entries_by_type) && ..() + +/datum/controller/configuration/vv_edit_var(var_name, var_value) + return !(var_name in list("entries_by_type", "entries")) && ..() + +/datum/controller/configuration/stat_entry() + if(!statclick) + statclick = new/obj/effect/statclick/debug(null, "Edit", src) + stat("[name]:", statclick) + +/datum/controller/configuration/proc/Get(entry_type) + var/datum/config_entry/E = entry_type + var/entry_is_abstract = initial(E.abstract_type) == entry_type + if(entry_is_abstract) + CRASH("Tried to retrieve an abstract config_entry: [entry_type]") + E = entries_by_type[entry_type] + if(!E) + CRASH("Missing config entry for [entry_type]!") + return E.value + +/datum/controller/configuration/proc/Set(entry_type, new_val) + var/datum/config_entry/E = entry_type + var/entry_is_abstract = initial(E.abstract_type) == entry_type + if(entry_is_abstract) + CRASH("Tried to retrieve an abstract config_entry: [entry_type]") + E = entries_by_type[entry_type] + if(!E) + CRASH("Missing config entry for [entry_type]!") + return E.ValidateAndSet(new_val) + +/datum/controller/configuration/proc/LoadModes() + gamemode_cache = typecacheof(/datum/game_mode, TRUE) + modes = list() + mode_names = list() + mode_reports = list() + mode_false_report_weight = list() + votable_modes = list() + var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability) + for(var/T in gamemode_cache) + // I wish I didn't have to instance the game modes in order to look up + // their information, but it is the only way (at least that I know of). + var/datum/game_mode/M = new T() + + if(M.config_tag) + if(!(M.config_tag in modes)) // ensure each mode is added only once + modes += M.config_tag + mode_names[M.config_tag] = M.name + probabilities[M.config_tag] = M.probability + mode_reports[M.config_tag] = M.generate_report() + mode_false_report_weight[M.config_tag] = M.false_report_weight + if(M.votable) + votable_modes += M.config_tag + qdel(M) + votable_modes += "secret" + +/datum/controller/configuration/proc/loadmaplist(filename) + filename = "[GLOB.config_dir][filename]" + var/list/Lines = world.file2list(filename) + + var/datum/map_config/currentmap = null + for(var/t in Lines) + if(!t) + continue + + t = trim(t) + if(length(t) == 0) + continue + else if(copytext(t, 1, 2) == "#") + continue + + var/pos = findtext(t, " ") + var/command = null + var/data = null + + if(pos) + command = lowertext(copytext(t, 1, pos)) + data = copytext(t, pos + 1) + else + command = lowertext(t) + + if(!command) + continue + + if (!currentmap && command != "map") + continue + + switch (command) + if ("map") + currentmap = new ("_maps/[data].json") + if(currentmap.defaulted) + log_config("Failed to load map config for [data]!") + if ("minplayers","minplayer") + currentmap.config_min_users = text2num(data) + if ("maxplayers","maxplayer") + currentmap.config_max_users = text2num(data) + if ("weight","voteweight") + currentmap.voteweight = text2num(data) + if ("default","defaultmap") + defaultmap = currentmap + if ("endmap") + LAZYINITLIST(maplist) + maplist[currentmap.map_name] = currentmap + currentmap = null + if ("disabled") + currentmap = null + else + WRITE_FILE(GLOB.config_error_log, "Unknown command in map vote config: '[command]'") + + +/datum/controller/configuration/proc/pick_mode(mode_name) + // I wish I didn't have to instance the game modes in order to look up + // their information, but it is the only way (at least that I know of). + // ^ This guy didn't try hard enough + for(var/T in gamemode_cache) + var/datum/game_mode/M = T + var/ct = initial(M.config_tag) + if(ct && ct == mode_name) + return new T + return new /datum/game_mode/extended() + +/datum/controller/configuration/proc/get_runnable_modes() + var/list/datum/game_mode/runnable_modes = new + var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability) + var/list/min_pop = Get(/datum/config_entry/keyed_number_list/min_pop) + var/list/max_pop = Get(/datum/config_entry/keyed_number_list/max_pop) + var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust) + for(var/T in gamemode_cache) + var/datum/game_mode/M = new T() + if(!(M.config_tag in modes)) + qdel(M) + continue + if(probabilities[M.config_tag]<=0) + qdel(M) + continue + if(min_pop[M.config_tag]) + M.required_players = min_pop[M.config_tag] + if(max_pop[M.config_tag]) + M.maximum_players = max_pop[M.config_tag] + if(M.can_start()) + var/final_weight = probabilities[M.config_tag] + if(SSpersistence.saved_modes.len == 3 && repeated_mode_adjust.len == 3) + var/recent_round = min(SSpersistence.saved_modes.Find(M.config_tag),3) + var/adjustment = 0 + while(recent_round) + adjustment += repeated_mode_adjust[recent_round] + recent_round = SSpersistence.saved_modes.Find(M.config_tag,recent_round+1,0) + final_weight *= ((100-adjustment)/100) + runnable_modes[M] = final_weight + return runnable_modes + +/datum/controller/configuration/proc/get_runnable_midround_modes(crew) + var/list/datum/game_mode/runnable_modes = new + var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability) + var/list/min_pop = Get(/datum/config_entry/keyed_number_list/min_pop) + var/list/max_pop = Get(/datum/config_entry/keyed_number_list/max_pop) + for(var/T in (gamemode_cache - SSticker.mode.type)) + var/datum/game_mode/M = new T() + if(!(M.config_tag in modes)) + qdel(M) + continue + if(probabilities[M.config_tag]<=0) + qdel(M) + continue + if(min_pop[M.config_tag]) + M.required_players = min_pop[M.config_tag] + if(max_pop[M.config_tag]) + M.maximum_players = max_pop[M.config_tag] + if(M.required_players <= crew) + if(M.maximum_players >= 0 && M.maximum_players < crew) + continue + runnable_modes[M] = probabilities[M.config_tag] + return runnable_modes diff --git a/code/controllers/configuration/entries/comms.dm b/code/controllers/configuration/entries/comms.dm new file mode 100644 index 00000000000..bf099f6cb62 --- /dev/null +++ b/code/controllers/configuration/entries/comms.dm @@ -0,0 +1,22 @@ +#define CURRENT_RESIDENT_FILE "comms.txt" + +CONFIG_DEF(string/comms_key) + protection = CONFIG_ENTRY_HIDDEN + +/datum/config_entry/string/comms_key/ValidateAndSet(str_val) + return str_val != "default_pwd" && length(str_val) > 6 && ..() + +CONFIG_DEF(string/cross_server_address) + protection = CONFIG_ENTRY_LOCKED + +/datum/config_entry/string/cross_server_address/ValidateAndSet(str_val) + return str_val != "byond:\\address:port" && ..() + +CONFIG_DEF(string/cross_comms_name) + +GLOBAL_VAR_INIT(medals_enabled, TRUE) //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls. + +CONFIG_DEF(string/medal_hub_address) + +CONFIG_DEF(string/medal_hub_password) + protection = CONFIG_ENTRY_HIDDEN \ No newline at end of file diff --git a/code/controllers/configuration/entries/config.dm b/code/controllers/configuration/entries/config.dm new file mode 100644 index 00000000000..cabb6dca27f --- /dev/null +++ b/code/controllers/configuration/entries/config.dm @@ -0,0 +1,387 @@ +#define CURRENT_RESIDENT_FILE "config.txt" + +CONFIG_DEF(flag/autoadmin) // if autoadmin is enabled + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(string/autoadmin_rank) // the rank for autoadmins + value = "Game Master" + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(string/servername) // server name (the name of the game window) + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(string/serversqlname) // short form server name used for the DB + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(string/stationname) // station name (the name of the station in-game) + +CONFIG_DEF(number/lobby_countdown) // In between round countdown. + value = 120 + min_val = 0 + +CONFIG_DEF(number/round_end_countdown) // Post round murder death kill countdown + value = 25 + min_val = 0 + +CONFIG_DEF(flag/hub) // if the game appears on the hub or not + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_ooc) // log OOC channel + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_access) // log login/logout + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_say) // log client say + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_admin) // log admin actions + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_prayer) // log prayers + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_law) // log lawchanges + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_game) // log game events + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_vote) // log voting + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_whisper) // log client whisper + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_attack) // log attack messages + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_emote) // log emotes + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_adminchat) // log admin chat messages + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_pda) // log pda messages + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_twitter) // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases. + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/log_world_topic) // log all world.Topic() calls + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/allow_admin_ooccolor) // Allows admins with relevant permissions to have their own ooc colour + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/allow_vote_restart) // allow votes to restart + +CONFIG_DEF(flag/allow_vote_mode) // allow votes to change mode + +CONFIG_DEF(number/vote_delay) // minimum time between voting sessions (deciseconds, 10 minute default) + value = 6000 + min_val = 0 + +CONFIG_DEF(number/vote_period) // length of voting period (deciseconds, default 1 minute) + value = 600 + min_val = 0 + +CONFIG_DEF(flag/default_no_vote) // vote does not default to nochange/norestart + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/no_dead_vote) // dead people can't vote + +CONFIG_DEF(flag/allow_metadata) // Metadata is supported. + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/popup_admin_pm) // adminPMs to non-admins show in a pop-up 'reply' window when set + +CONFIG_DEF(number/fps) + value = 20 + min_val = 1 + max_val = 100 //byond will start crapping out at 50, so this is just ridic + var/sync_validate = FALSE + +/datum/config_entry/number/fps/ValidateAndSet(str_val) + . = ..() + if(.) + sync_validate = TRUE + var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag] + if(!TL.sync_validate) + TL.ValidateAndSet(10 / value) + sync_validate = FALSE + +CONFIG_DEF(number/ticklag) + integer = FALSE + var/sync_validate = FALSE + +/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps + var/datum/config_entry/CE = /datum/config_entry/number/fps + value = 10 / initial(CE.value) + ..() + +/datum/config_entry/number/ticklag/ValidateAndSet(str_val) + . = text2num(str_val) > 0 && ..() + if(.) + sync_validate = TRUE + var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps] + if(!FPS.sync_validate) + FPS.ValidateAndSet(10 / value) + sync_validate = FALSE + +CONFIG_DEF(flag/allow_holidays) + +CONFIG_DEF(number/tick_limit_mc_init) //SSinitialization throttling + value = TICK_LIMIT_MC_INIT_DEFAULT + min_val = 0 //oranges warned us + integer = FALSE + +CONFIG_DEF(flag/admin_legacy_system) //Defines whether the server uses the legacy admin system with admins.txt or the SQL system + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(string/hostedby) + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/norespawn) + +CONFIG_DEF(flag/guest_jobban) + +CONFIG_DEF(flag/usewhitelist) + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/ban_legacy_system) //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/use_age_restriction_for_jobs) //Do jobs use account age restrictions? --requires database + +CONFIG_DEF(flag/use_account_age_for_jobs) //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected. + +CONFIG_DEF(flag/use_exp_tracking) + +CONFIG_DEF(flag/use_exp_restrictions_heads) + +CONFIG_DEF(number/use_exp_restrictions_heads_hours) + value = 0 + min_val = 0 + +CONFIG_DEF(flag/use_exp_restrictions_heads_department) + +CONFIG_DEF(flag/use_exp_restrictions_other) + +CONFIG_DEF(flag/use_exp_restrictions_admin_bypass) + +CONFIG_DEF(string/server) + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(string/banappeals) + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(string/wikiurl) + protection = CONFIG_ENTRY_LOCKED + value = "http://www.tgstation13.org/wiki" + +CONFIG_DEF(string/forumurl) + protection = CONFIG_ENTRY_LOCKED + value = "http://tgstation13.org/phpBB/index.php" + +CONFIG_DEF(string/rulesurl) + protection = CONFIG_ENTRY_LOCKED + value = "http://www.tgstation13.org/wiki/Rules" + +CONFIG_DEF(string/githuburl) + protection = CONFIG_ENTRY_LOCKED + value = "https://www.github.com/tgstation/-tg-station" + +CONFIG_DEF(number/githubrepoid) + protection = CONFIG_ENTRY_LOCKED + value = null + min_val = 0 + +CONFIG_DEF(flag/guest_ban) + +CONFIG_DEF(number/id_console_jobslot_delay) + value = 30 + min_val = 0 + +CONFIG_DEF(number/inactivity_period) //time in ds until a player is considered inactive) + value = 3000 + min_val = 0 + +/datum/config_entry/number/inactivity_period/ValidateAndSet(str_val) + . = ..() + if(.) + value *= 10 //documented as seconds in config.txt + +CONFIG_DEF(number/afk_period) //time in ds until a player is considered inactive) + value = 3000 + min_val = 0 + +/datum/config_entry/number/afk_period/ValidateAndSet(str_val) + . = ..() + if(.) + value *= 10 //documented as seconds in config.txt + +CONFIG_DEF(flag/kick_inactive) //force disconnect for inactive players + +CONFIG_DEF(flag/load_jobs_from_txt) + +CONFIG_DEF(flag/forbid_singulo_possession) + +CONFIG_DEF(flag/useircbot) //tgs2 support + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/automute_on) //enables automuting/spam prevention + +CONFIG_DEF(string/panic_server_name) + protection = CONFIG_ENTRY_LOCKED + +/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val) + return str_val != "\[Put the name here\]" && ..() + +CONFIG_DEF(string/panic_address) //Reconnect a player this linked server if this server isn't accepting new players + +/datum/config_entry/string/panic_address/ValidateAndSet(str_val) + return str_val != "byond://address:port" && ..() + +CONFIG_DEF(string/invoke_youtubedl) + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN + +CONFIG_DEF(flag/show_irc_name) + +CONFIG_DEF(flag/see_own_notes) //Can players see their own admin notes (read-only)? + +CONFIG_DEF(number/note_fresh_days) + value = null + min_val = 0 + integer = FALSE + +CONFIG_DEF(number/note_stale_days) + value = null + min_val = 0 + integer = FALSE + +CONFIG_DEF(flag/maprotation) + +CONFIG_DEF(number/maprotatechancedelta) + value = 0.75 + min_val = 0 + max_val = 1 + integer = FALSE + +CONFIG_DEF(number/soft_popcap) + value = null + min_val = 0 + +CONFIG_DEF(number/hard_popcap) + value = null + min_val = 0 + +CONFIG_DEF(number/extreme_popcap) + value = null + min_val = 0 + +CONFIG_DEF(string/soft_popcap_message) + value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers." + +CONFIG_DEF(string/hard_popcap_message) + value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers." + +CONFIG_DEF(string/extreme_popcap_message) + value = "The server is currently serving a high number of users, find alternative servers." + +CONFIG_DEF(flag/panic_bunker) // prevents people the server hasn't seen before from connecting + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(number/notify_new_player_age) // how long do we notify admins of a new player + min_val = -1 + +CONFIG_DEF(number/notify_new_player_account_age) // how long do we notify admins of a new byond account + min_val = 0 + +CONFIG_DEF(flag/irc_first_connection_alert) // do we notify the irc channel when somebody is connecting for the first time? + +CONFIG_DEF(flag/check_randomizer) + +CONFIG_DEF(string/ipintel_email) + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN + +/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val) + return str_val != "ch@nge.me" && ..() + +CONFIG_DEF(number/ipintel_rating_bad) + value = 1 + integer = FALSE + min_val = 0 + max_val = 1 + +CONFIG_DEF(number/ipintel_save_good) + protection = CONFIG_ENTRY_LOCKED + value = 12 + min_val = 0 + +CONFIG_DEF(number/ipintel_save_bad) + protection = CONFIG_ENTRY_LOCKED + value = 1 + min_val = 0 + +CONFIG_DEF(string/ipintel_domain) + protection = CONFIG_ENTRY_LOCKED + value = "check.getipintel.net" + +CONFIG_DEF(flag/aggressive_changelog) + +CONFIG_DEF(flag/autoconvert_notes) //if all connecting player's notes should attempt to be converted to the database + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(flag/allow_webclient) + +CONFIG_DEF(flag/webclient_only_byond_members) + +CONFIG_DEF(flag/announce_admin_logout) + +CONFIG_DEF(flag/announce_admin_login) + +CONFIG_DEF(flag/allow_map_voting) + +CONFIG_DEF(flag/generate_minimaps) + +CONFIG_DEF(number/client_warn_version) + value = null + min_val = 500 + max_val = DM_VERSION - 1 + +CONFIG_DEF(string/client_warn_message) + value = "Your version of byond may have issues or be blocked from accessing this server in the future." + +CONFIG_DEF(number/client_error_version) + value = null + min_val = 500 + max_val = DM_VERSION - 1 + +CONFIG_DEF(string/client_error_message) + value = "Your version of byond is too old, may have issues, and is blocked from accessing this server." + +CONFIG_DEF(number/minute_topic_limit) + value = null + min_val = 0 + +CONFIG_DEF(number/second_topic_limit) + value = null + min_val = 0 + +CONFIG_DEF(number/error_cooldown) // The "cooldown" time for each occurrence of a unique error) + value = 600 + min_val = 0 + +CONFIG_DEF(number/error_limit) // How many occurrences before the next will silence them + value = 50 + +CONFIG_DEF(number/error_silence_time) // How long a unique error will be silenced for + value = 6000 + +CONFIG_DEF(number/error_msg_delay) // How long to wait between messaging admins about occurrences of a unique error + value = 50 + +CONFIG_DEF(flag/irc_announce_new_game) + +CONFIG_DEF(flag/debug_admin_hrefs) \ No newline at end of file diff --git a/code/controllers/configuration/entries/dbconfig.dm b/code/controllers/configuration/entries/dbconfig.dm new file mode 100644 index 00000000000..c46880686ac --- /dev/null +++ b/code/controllers/configuration/entries/dbconfig.dm @@ -0,0 +1,28 @@ +#define CURRENT_RESIDENT_FILE "dbconfig.txt" + +CONFIG_DEF(flag/sql_enabled) // for sql switching + protection = CONFIG_ENTRY_LOCKED + +CONFIG_DEF(string/address) + value = "localhost" + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN + +CONFIG_DEF(number/port) + value = 3306 + min_val = 0 + max_val = 65535 + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN + +CONFIG_DEF(string/feedback_database) + value = "test" + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN + +CONFIG_DEF(string/feedback_login) + value = "root" + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN + +CONFIG_DEF(string/feedback_password) + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN + +CONFIG_DEF(string/feedback_tableprefix) + protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm new file mode 100644 index 00000000000..106804a576e --- /dev/null +++ b/code/controllers/configuration/entries/game_options.dm @@ -0,0 +1,266 @@ +#define CURRENT_RESIDENT_FILE "game_options.txt" + +CONFIG_DEF(number_list/repeated_mode_adjust) + +CONFIG_DEF(keyed_number_list/probability) + +/datum/config_entry/keyed_number_list/probability/ValidateKeyName(key_name) + return key_name in config.modes + +CONFIG_DEF(keyed_number_list/max_pop) + +/datum/config_entry/keyed_number_list/max_pop/ValidateKeyName(key_name) + return key_name in config.modes + +CONFIG_DEF(keyed_number_list/min_pop) + +/datum/config_entry/keyed_number_list/min_pop/ValidateKeyName(key_name) + return key_name in config.modes + +CONFIG_DEF(keyed_flag_list/continuous) // which roundtypes continue if all antagonists die + +/datum/config_entry/keyed_flag_list/continuous/ValidateKeyName(key_name) + return key_name in config.modes + +CONFIG_DEF(keyed_flag_list/midround_antag) // which roundtypes use the midround antagonist system + +/datum/config_entry/keyed_flag_list/midround_antag/ValidateKeyName(key_name) + return key_name in config.modes + +CONFIG_DEF(keyed_string_list/policy) + +CONFIG_DEF(number/damage_multiplier) + value = 1 + integer = FALSE + +CONFIG_DEF(number/minimal_access_threshold) //If the number of players is larger than this threshold, minimal access will be turned on. + min_val = 0 + +CONFIG_DEF(flag/jobs_have_minimal_access) //determines whether jobs use minimal access or expanded access. + +CONFIG_DEF(flag/assistants_have_maint_access) + +CONFIG_DEF(flag/security_has_maint_access) + +CONFIG_DEF(flag/everyone_has_maint_access) + +CONFIG_DEF(flag/sec_start_brig) //makes sec start in brig instead of dept sec posts + +CONFIG_DEF(flag/force_random_names) + +CONFIG_DEF(flag/humans_need_surnames) + +CONFIG_DEF(flag/allow_ai) // allow ai job + +CONFIG_DEF(flag/disable_secborg) // disallow secborg module to be chosen. + +CONFIG_DEF(flag/disable_peaceborg) + +CONFIG_DEF(number/traitor_scaling_coeff) //how much does the amount of players get divided by to determine traitors + value = 6 + min_val = 1 + +CONFIG_DEF(number/brother_scaling_coeff) //how many players per brother team + value = 25 + min_val = 1 + +CONFIG_DEF(number/changeling_scaling_coeff) //how much does the amount of players get divided by to determine changelings + value = 6 + min_val = 1 + +CONFIG_DEF(number/security_scaling_coeff) //how much does the amount of players get divided by to determine open security officer positions + value = 8 + min_val = 1 + +CONFIG_DEF(number/abductor_scaling_coeff) //how many players per abductor team + value = 15 + min_val = 1 + +CONFIG_DEF(number/traitor_objectives_amount) + value = 2 + min_val = 0 + +CONFIG_DEF(number/brother_objectives_amount) + value = 2 + min_val = 0 + +CONFIG_DEF(flag/reactionary_explosions) //If we use reactionary explosions, explosions that react to walls and doors + +CONFIG_DEF(flag/protect_roles_from_antagonist) //If security and such can be traitor/cult/other + +CONFIG_DEF(flag/protect_assistant_from_antagonist) //If assistants can be traitor/cult/other + +CONFIG_DEF(flag/enforce_human_authority) //If non-human species are barred from joining as a head of staff + +CONFIG_DEF(flag/allow_latejoin_antagonists) // If late-joining players can be traitor/changeling + +CONFIG_DEF(number/midround_antag_time_check) // How late (in minutes) you want the midround antag system to stay on, setting this to 0 will disable the system + value = 60 + min_val = 0 + +CONFIG_DEF(number/midround_antag_life_check) // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist + value = 0.7 + integer = FALSE + min_val = 0 + max_val = 1 + +CONFIG_DEF(number/shuttle_refuel_delay) + value = 12000 + min_val = 0 + +CONFIG_DEF(flag/show_game_type_odds) //if set this allows players to see the odds of each roundtype on the get revision screen + +CONFIG_DEF(flag/join_with_mutant_race) //players can choose their mutant race before joining the game + +CONFIG_DEF(keyed_flag_list/roundstart_races) //races you can play as from the get go. If left undefined the game's roundstart var for species is used + var/first_edit = TRUE + +/datum/config_entry/keyed_flag_list/roundstart_races/New() + for(var/I in subtypesof(/datum/species)) + var/datum/species/S = I + if(initial(S.roundstart)) + value[initial(S.id)] = TRUE + ..() + +/datum/config_entry/keyed_flag_list/roundstart_races/ValidateAndSet(str_val) + var/list/old_val + if(first_edit) + old_val = value + old_val = old_val.Copy() + . = ..() + if(first_edit) + if(!.) + value = old_val + else + first_edit = FALSE + +CONFIG_DEF(flag/join_with_mutant_humans) //players can pick mutant bodyparts for humans before joining the game + +CONFIG_DEF(flag/no_summon_guns) //No + +CONFIG_DEF(flag/no_summon_magic) //Fun + +CONFIG_DEF(flag/no_summon_events) //Allowed + +CONFIG_DEF(flag/no_intercept_report) //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes. + +CONFIG_DEF(number/arrivals_shuttle_dock_window) //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station + value = 55 + min_val = 30 + +CONFIG_DEF(flag/arrivals_shuttle_require_undocked) //Require the arrivals shuttle to be undocked before latejoiners can join + +CONFIG_DEF(flag/arrivals_shuttle_require_safe_latejoin) //Require the arrivals shuttle to be operational in order for latejoiners to join + +CONFIG_DEF(string/alert_green) + value = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced." + +CONFIG_DEF(string/alert_blue_upto) + value = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted." + +CONFIG_DEF(string/alert_blue_downto) + value = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed." + +CONFIG_DEF(string/alert_red_upto) + value = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised." + +CONFIG_DEF(string/alert_red_downto) + value = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised." + +CONFIG_DEF(string/alert_delta) + value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill." + +CONFIG_DEF(flag/revival_pod_plants) + +CONFIG_DEF(flag/revival_cloning) + +CONFIG_DEF(number/revival_brain_life) + value = -1 + min_val = -1 + +CONFIG_DEF(flag/rename_cyborg) + +CONFIG_DEF(flag/ooc_during_round) + +CONFIG_DEF(flag/emojis) + +CONFIG_DEF(number/run_delay) //Used for modifying movement speed for mobs. + +CONFIG_DEF(number/walk_delay) + + +CONFIG_DEF(number/human_delay) //Mob specific modifiers. NOTE: These will affect different mob types in different ways +CONFIG_DEF(number/robot_delay) +CONFIG_DEF(number/monkey_delay) +CONFIG_DEF(number/alien_delay) +CONFIG_DEF(number/slime_delay) +CONFIG_DEF(number/animal_delay) + +CONFIG_DEF(number/gateway_delay) //How long the gateway takes before it activates. Default is half an hour. + value = 18000 + min_val = 0 + +CONFIG_DEF(flag/ghost_interaction) + +CONFIG_DEF(flag/silent_ai) +CONFIG_DEF(flag/silent_borg) + +CONFIG_DEF(flag/sandbox_autoclose) // close the sandbox panel after spawning an item, potentially reducing griff + +CONFIG_DEF(number/default_laws) //Controls what laws the AI spawns with. + value = 0 + min_val = 0 + max_val = 3 + +CONFIG_DEF(number/silicon_max_law_amount) + value = 12 + min_val = 0 + +CONFIG_DEF(keyed_flag_list/random_laws) + +CONFIG_DEF(keyed_number_list/law_weight) + splitter = "," + +CONFIG_DEF(number/assistant_cap) + value = -1 + min_val = -1 + +CONFIG_DEF(flag/starlight) +CONFIG_DEF(flag/grey_assistants) + +CONFIG_DEF(number/lavaland_budget) + value = 60 + min_val = 0 + +CONFIG_DEF(number/space_budget) + value = 16 + min_val = 0 + +CONFIG_DEF(flag/allow_random_events) // Enables random events mid-round when set + +CONFIG_DEF(number/events_min_time_mul) // Multipliers for random events minimal starting time and minimal players amounts + value = 1 + min_val = 0 + integer = FALSE + +CONFIG_DEF(number/events_min_players_mul) + value = 1 + min_val = 0 + integer = FALSE + +CONFIG_DEF(number/mice_roundstart) + value = 10 + min_val = 0 + +CONFIG_DEF(number/bombcap) + value = 14 + min_val = 4 + +/datum/config_entry/number/bombcap/ValidateAndSet(str_val) + . = ..() + if(.) + GLOB.MAX_EX_DEVESTATION_RANGE = round(value / 4) + GLOB.MAX_EX_HEAVY_RANGE = round(value / 2) + GLOB.MAX_EX_LIGHT_RANGE = value + GLOB.MAX_EX_FLASH_RANGE = value + GLOB.MAX_EX_FLAME_RANGE = value diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 11c460e326c..6ed3121179d 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -169,7 +169,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/start_timeofday = REALTIMEOFDAY // Initialize subsystems. - current_ticklimit = config.tick_limit_mc_init + current_ticklimit = CONFIG_GET(number/tick_limit_mc_init) for (var/datum/controller/subsystem/SS in subsystems) if (SS.flags & SS_NO_INIT) continue @@ -189,7 +189,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new sortTim(subsystems, /proc/cmp_subsystem_display) // Set world options. world.sleep_offline = 1 - world.fps = config.fps + world.fps = CONFIG_GET(number/fps) var/initialized_tod = REALTIMEOFDAY sleep(1) initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10 diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 2870305c3e0..56238d5b85b 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -38,7 +38,7 @@ SUBSYSTEM_DEF(blackbox) var/datum/DBQuery/query_record_playercount = SSdbcore.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time, server_ip, server_port, round_id) VALUES ([playercount], [admincount], '[SQLtime()]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]')") query_record_playercount.Execute() - if(config.use_exp_tracking) + if(CONFIG_GET(flag/use_exp_tracking)) if((triggertime < 0) || (world.time > (triggertime +3000))) //subsystem fires once at roundstart then once every 10 minutes. a 5 min check skips the first fire. The <0 is midnight rollover check update_exp(10,FALSE) diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index 864274b8fb0..12a5342e33f 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -54,32 +54,27 @@ SUBSYSTEM_DEF(dbcore) if(failed_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect anymore. return FALSE - if(!config.sql_enabled) + if(!CONFIG_GET(flag/sql_enabled)) return FALSE - var/user = global.sqlfdbklogin - var/pass = global.sqlfdbkpass - var/db = global.sqlfdbkdb - var/address = global.sqladdress - var/port = global.sqlport + var/user = CONFIG_GET(string/feedback_login) + var/pass = CONFIG_GET(string/feedback_password) + var/db = CONFIG_GET(string/feedback_database) + var/address = CONFIG_GET(string/address) + var/port = CONFIG_GET(number/port) - doConnect("dbi:mysql:[db]:[address]:[port]", user, pass) + _dm_db_connect(_db_con, "dbi:mysql:[db]:[address]:[port]", user, pass, Default_Cursor, null) . = IsConnected() if (!.) log_sql("Connect() failed | [ErrorMsg()]") ++failed_connections -/datum/controller/subsystem/dbcore/proc/doConnect(dbi_handler, user_handler, password_handler) - if(!config.sql_enabled) - return FALSE - return _dm_db_connect(_db_con, dbi_handler, user_handler, password_handler, Default_Cursor, null) - /datum/controller/subsystem/dbcore/proc/Disconnect() failed_connections = 0 return _dm_db_close(_db_con) /datum/controller/subsystem/dbcore/proc/IsConnected() - if(!config.sql_enabled) + if(!CONFIG_GET(flag/sql_enabled)) return FALSE return _dm_db_is_connected(_db_con) @@ -87,7 +82,7 @@ SUBSYSTEM_DEF(dbcore) return _dm_db_quote(_db_con, str) /datum/controller/subsystem/dbcore/proc/ErrorMsg() - if(!config.sql_enabled) + if(!CONFIG_GET(flag/sql_enabled)) return "Database disabled by configuration" return _dm_db_error_msg(_db_con) diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm index 7816a6bdf8d..f435d7e8196 100644 --- a/code/controllers/subsystem/events.dm +++ b/code/controllers/subsystem/events.dm @@ -56,7 +56,7 @@ SUBSYSTEM_DEF(events) //selects a random event based on whether it can occur and it's 'weight'(probability) /datum/controller/subsystem/events/proc/spawnEvent() set waitfor = FALSE //for the admin prompt - if(!config.allow_random_events) + if(!CONFIG_GET(flag/allow_random_events)) // var/datum/round_event_control/E = locate(/datum/round_event_control/dust) in control // if(E) E.runEvent() return @@ -171,7 +171,7 @@ SUBSYSTEM_DEF(events) //sets up the holidays and holidays list /datum/controller/subsystem/events/proc/getHoliday() - if(!config.allow_holidays) + if(!CONFIG_GET(flag/allow_holidays)) return // Holiday stuff was not enabled in the config! var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 1be36e5ac75..80f2c12f80b 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -16,7 +16,7 @@ SUBSYSTEM_DEF(job) /datum/controller/subsystem/job/Initialize(timeofday) if(!occupations.len) SetupOccupations() - if(config.load_jobs_from_txt) + if(CONFIG_GET(flag/load_jobs_from_txt)) LoadJobs() ..() @@ -106,7 +106,7 @@ SUBSYSTEM_DEF(job) if(player.mind && job.title in player.mind.restricted_roles) Debug("FOC incompatible with antagonist role, Player: [player]") continue - if(config.enforce_human_authority && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) + if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) Debug("FOC non-human failed, Player: [player]") continue if(player.client.prefs.GetJobDepartment(job, level) & job.flag) @@ -143,7 +143,7 @@ SUBSYSTEM_DEF(job) Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]") continue - if(config.enforce_human_authority && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) + if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) Debug("GRJ non-human failed, Player: [player]") continue @@ -245,11 +245,12 @@ SUBSYSTEM_DEF(job) setup_officer_positions() //Jobs will have fewer access permissions if the number of players exceeds the threshold defined in game_options.txt - if(config.minimal_access_threshold) - if(config.minimal_access_threshold > unassigned.len) - config.jobs_have_minimal_access = 0 + var/mat = CONFIG_GET(number/minimal_access_threshold) + if(mat) + if(mat > unassigned.len) + CONFIG_SET(flag/jobs_have_minimal_access, FALSE) else - config.jobs_have_minimal_access = 1 + CONFIG_SET(flag/jobs_have_minimal_access, TRUE) //Shuffle players and jobs unassigned = shuffle(unassigned) @@ -317,7 +318,7 @@ SUBSYSTEM_DEF(job) Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]") continue - if(config.enforce_human_authority && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) + if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) Debug("DO non-human failed, Player: [player], Job:[job.title]") continue @@ -415,8 +416,8 @@ SUBSYSTEM_DEF(job) to_chat(M, "To speak on your departments radio, use the :h button. To see others, look closely at your headset.") if(job.req_admin_notify) to_chat(M, "You are playing a job that is important for Game Progression. If you have to disconnect, please notify the admins via adminhelp.") - if(config.minimal_access_threshold) - to_chat(M, "As this station was initially staffed with a [config.jobs_have_minimal_access ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.") + if(CONFIG_GET(number/minimal_access_threshold)) + to_chat(M, "As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.") if(job && H) job.after_spawn(H, M) @@ -429,9 +430,10 @@ SUBSYSTEM_DEF(job) if(!J) throw EXCEPTION("setup_officer_positions(): Security officer job is missing") - if(config.security_scaling_coeff > 0) + var/ssc = CONFIG_GET(number/security_scaling_coeff) + if(ssc > 0) if(J.spawn_positions > 0) - var/officer_positions = min(12, max(J.spawn_positions, round(unassigned.len/config.security_scaling_coeff))) //Scale between configured minimum and 12 officers + var/officer_positions = min(12, max(J.spawn_positions, round(unassigned.len / ssc))) //Scale between configured minimum and 12 officers Debug("Setting open security officer positions to [officer_positions]") J.total_positions = officer_positions J.spawn_positions = officer_positions @@ -491,8 +493,10 @@ SUBSYSTEM_DEF(job) SSblackbox.add_details("job_preferences",tmp_str) /datum/controller/subsystem/job/proc/PopcapReached() - if(config.hard_popcap || config.extreme_popcap) - var/relevent_cap = max(config.hard_popcap, config.extreme_popcap) + var/hpc = CONFIG_GET(number/hard_popcap) + var/epc = CONFIG_GET(number/extreme_popcap) + if(hpc || epc) + var/relevent_cap = max(hpc, epc) if((initial_players_to_assign - unassigned.len) >= relevent_cap) return 1 return 0 diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index bcb94c835b6..231cb37ae49 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -16,7 +16,7 @@ SUBSYSTEM_DEF(lighting) /datum/controller/subsystem/lighting/Initialize(timeofday) if(!initialized) - if (config.starlight) + if (CONFIG_GET(flag/starlight)) for(var/I in GLOB.sortedAreas) var/area/A = I if (A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 9549cf7b180..ab2ba544316 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -43,7 +43,7 @@ SUBSYSTEM_DEF(mapping) loading_ruins = TRUE var/mining_type = config.minetype if (mining_type == "lavaland") - seedRuins(list(ZLEVEL_LAVALAND), global.config.lavaland_budget, /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates) + seedRuins(list(ZLEVEL_LAVALAND), CONFIG_GET(number/lavaland_budget), /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates) spawn_rivers() // deep space ruins @@ -55,7 +55,7 @@ SUBSYSTEM_DEF(mapping) else space_zlevels += i - seedRuins(space_zlevels, global.config.space_budget, /area/space, space_ruins_templates) + seedRuins(space_zlevels, CONFIG_GET(number/space_budget), /area/space, space_ruins_templates) loading_ruins = FALSE repopulate_sorted_areas() // Set up Z-level transistions. @@ -141,7 +141,8 @@ SUBSYSTEM_DEF(mapping) var/players = GLOB.clients.len var/list/mapvotes = list() //count votes - if(global.config.allow_map_voting) + var/amv = CONFIG_GET(flag/allow_map_voting) + if(amv) for (var/client/c in GLOB.clients) var/vote = c.prefs.preferred_map if (!vote) @@ -174,7 +175,7 @@ SUBSYSTEM_DEF(mapping) mapvotes.Remove(map) continue - if(global.config.allow_map_voting) + if(amv) mapvotes[map] = mapvotes[map]*VM.voteweight var/pickedmap = pickweight(mapvotes) diff --git a/code/controllers/subsystem/minimap.dm b/code/controllers/subsystem/minimap.dm index 4e58212b44d..463b82b13ef 100644 --- a/code/controllers/subsystem/minimap.dm +++ b/code/controllers/subsystem/minimap.dm @@ -9,7 +9,7 @@ SUBSYSTEM_DEF(minimap) /datum/controller/subsystem/minimap/Initialize(timeofday) var/hash = md5(SSmapping.config.GetFullMapPath()) - if(config.generate_minimaps) + if(CONFIG_GET(flag/generate_minimaps)) if(hash == trim(file2text(hash_path()))) for(var/z in z_levels) //We have these files cached, let's register them register_asset("minimap_[z].png", fcopy_rsc(map_path(z))) diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm index 87b06cd5879..0b8fa750b6d 100644 --- a/code/controllers/subsystem/server_maint.dm +++ b/code/controllers/subsystem/server_maint.dm @@ -10,7 +10,7 @@ SUBSYSTEM_DEF(server_maint) var/list/currentrun /datum/controller/subsystem/server_maint/Initialize(timeofday) - if (config.hub) + if (CONFIG_GET(flag/hub)) world.update_hub_visibility(TRUE) ..() @@ -21,16 +21,19 @@ SUBSYSTEM_DEF(server_maint) var/list/currentrun = src.currentrun var/round_started = SSticker.HasRoundStarted() + var/kick_inactive = CONFIG_GET(flag/kick_inactive) + var/afk_period + if(kick_inactive) + afk_period = CONFIG_GET(number/afk_period) for(var/I in currentrun) var/client/C = I //handle kicking inactive players - if(round_started && config.kick_inactive) - if(C.is_afk(config.afk_period)) - var/cmob = C.mob - if(!(isobserver(cmob) || (isdead(cmob) && C.holder))) - log_access("AFK: [key_name(C)]") - to_chat(C, "You have been inactive for more than [DisplayTimeText(config.afk_period)] and have been disconnected.") - qdel(C) + if(round_started && kick_inactive && C.is_afk(afk_period)) + var/cmob = C.mob + if(!(isobserver(cmob) || (isdead(cmob) && C.holder))) + log_access("AFK: [key_name(C)]") + to_chat(C, "You have been inactive for more than [DisplayTimeText(afk_period)] and have been disconnected.") + qdel(C) if (!(!C || world.time - C.connection_time < PING_BUFFER_TIME || C.inactivity >= (wait-1))) winset(C, null, "command=.update_ping+[world.time+world.tick_lag*TICK_USAGE_REAL/100]") @@ -40,7 +43,7 @@ SUBSYSTEM_DEF(server_maint) /datum/controller/subsystem/server_maint/Shutdown() kick_clients_in_lobby("The round came to an end with you in the lobby.", TRUE) //second parameter ensures only afk clients are kicked - var/server = config.server + var/server = CONFIG_GET(string/server) for(var/thing in GLOB.clients) if(!thing) continue diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 31c4b4ca2ec..93ccb750070 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -174,9 +174,9 @@ SUBSYSTEM_DEF(shuttle) Good luck.") return emergency = backup_shuttle - - if(world.time - SSticker.round_start_time < config.shuttle_refuel_delay) - to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)] before trying again.") + var/srd = CONFIG_GET(number/shuttle_refuel_delay) + if(world.time - SSticker.round_start_time < srd) + to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText((world.time - SSticker.round_start_time) - srd)] before trying again.") return switch(emergency.mode) diff --git a/code/controllers/subsystem/squeak.dm b/code/controllers/subsystem/squeak.dm index d2268bdc253..022b659d8a2 100644 --- a/code/controllers/subsystem/squeak.dm +++ b/code/controllers/subsystem/squeak.dm @@ -10,7 +10,7 @@ SUBSYSTEM_DEF(squeak) var/list/exposed_wires = list() /datum/controller/subsystem/squeak/Initialize(timeofday) - trigger_migration(config.mice_roundstart) + trigger_migration(CONFIG_GET(number/mice_roundstart)) return ..() /datum/controller/subsystem/squeak/proc/trigger_migration(num_mice=10) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 01422c92f21..6b17522ebe0 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -77,13 +77,13 @@ SUBSYSTEM_DEF(ticker) if(!GLOB.syndicate_code_response) GLOB.syndicate_code_response = generate_code_phrase() ..() - start_at = world.time + (config.lobby_countdown * 10) + start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10) /datum/controller/subsystem/ticker/fire() switch(current_state) if(GAME_STATE_STARTUP) if(Master.initializations_finished_with_no_players_logged_in) - start_at = world.time + (config.lobby_countdown * 10) + start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10) for(var/client/C in GLOB.clients) window_flash(C, ignorepref = TRUE) //let them know lobby has opened up. to_chat(world, "Welcome to [station_name()]!") @@ -202,7 +202,7 @@ SUBSYSTEM_DEF(ticker) else mode.announce() - if(!config.ooc_during_round) + if(!CONFIG_GET(flag/ooc_during_round)) toggle_ooc(FALSE) // Turn it off CHECK_TICK @@ -423,7 +423,7 @@ SUBSYSTEM_DEF(ticker) CHECK_TICK - if(config.cross_allowed) + if(CONFIG_GET(string/cross_server_address)) send_news_report() CHECK_TICK @@ -489,7 +489,8 @@ SUBSYSTEM_DEF(ticker) to_chat(world, "Tip of the round: [html_encode(m)]") /datum/controller/subsystem/ticker/proc/check_queue() - if(!queued_players.len || !config.hard_popcap) + var/hpc = CONFIG_GET(number/hard_popcap) + if(!queued_players.len || !hpc) return queue_delay++ @@ -497,7 +498,7 @@ SUBSYSTEM_DEF(ticker) switch(queue_delay) if(5) //every 5 ticks check if there is a slot available - if(living_player_count() < config.hard_popcap) + if(living_player_count() < hpc) if(next_in_line && next_in_line.client) to_chat(next_in_line, "A slot has opened! You have approximately 20 seconds to join. \>\>Join Game\<\<") SEND_SOUND(next_in_line, sound('sound/misc/notice1.ogg')) @@ -511,7 +512,7 @@ SUBSYSTEM_DEF(ticker) queue_delay = 0 /datum/controller/subsystem/ticker/proc/check_maprotate() - if (!config.maprotation) + if (!CONFIG_GET(flag/maprotation)) return if (SSshuttle.emergency && SSshuttle.emergency.mode != SHUTTLE_ESCAPE || SSshuttle.canRecall()) return @@ -521,7 +522,7 @@ SUBSYSTEM_DEF(ticker) maprotatechecked = 1 //map rotate chance defaults to 75% of the length of the round (in minutes) - if (!prob((world.time/600)*config.maprotatechancedelta)) + if (!prob((world.time/600)*CONFIG_GET(number/maprotatechancedelta))) return INVOKE_ASYNC(SSmapping, /datum/controller/subsystem/mapping/.proc/maprotate) @@ -672,7 +673,7 @@ SUBSYSTEM_DEF(ticker) return if(!delay) - delay = config.round_end_countdown * 10 + delay = CONFIG_GET(number/round_end_countdown) * 10 var/skip_delay = check_rights() if(delay_end && !skip_delay) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 180f8598d07..1f03cf15f3e 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -18,7 +18,7 @@ SUBSYSTEM_DEF(vote) /datum/controller/subsystem/vote/fire() //called by master_controller if(mode) - time_remaining = round((started_time + config.vote_period - world.time)/10) + time_remaining = round((started_time + CONFIG_GET(number/vote_period) - world.time)/10) if(time_remaining < 0) result() @@ -54,7 +54,7 @@ SUBSYSTEM_DEF(vote) if(votes > greatest_votes) greatest_votes = votes //default-vote for everyone who didn't vote - if(!config.vote_no_default && choices.len) + if(!CONFIG_GET(flag/default_no_vote) && choices.len) var/list/non_voters = GLOB.directory.Copy() non_voters -= voted for (var/non_voter_ckey in non_voters) @@ -139,7 +139,7 @@ SUBSYSTEM_DEF(vote) /datum/controller/subsystem/vote/proc/submit_vote(vote) if(mode) - if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder) + if(CONFIG_GET(flag/no_dead_vote) && usr.stat == DEAD && !usr.client.holder) return 0 if(!(usr.ckey in voted)) if(vote && 1<=vote && vote<=choices.len) @@ -151,7 +151,7 @@ SUBSYSTEM_DEF(vote) /datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key) if(!mode) if(started_time) - var/next_allowed_time = (started_time + config.vote_delay) + var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay)) if(mode) to_chat(usr, "There is already a vote in progress! please wait for it to finish.") return 0 @@ -189,8 +189,9 @@ SUBSYSTEM_DEF(vote) if(mode == "custom") text += "\n[question]" log_vote(text) - to_chat(world, "\n[text]\nType vote or click here to place your votes.\nYou have [DisplayTimeText(config.vote_period)] to vote.") - time_remaining = round(config.vote_period/10) + var/vp = CONFIG_GET(number/vote_period) + to_chat(world, "\n[text]\nType vote or click here to place your votes.\nYou have [DisplayTimeText(vp)] to vote.") + time_remaining = round(vp/10) for(var/c in GLOB.clients) var/client/C = c var/datum/action/vote/V = new @@ -229,20 +230,22 @@ SUBSYSTEM_DEF(vote) else . += "

Start a vote: