Merge pull request #15980 from AffectedArc07/toml-config

[READY] Converts configs to use TOML + Configuration refactor
This commit is contained in:
variableundefined
2021-07-25 08:26:29 -04:00
committed by GitHub
193 changed files with 2577 additions and 2858 deletions
+4 -5
View File
@@ -41,15 +41,14 @@ something has gone wrong - possibly a corrupt download or the files extracted wr
or a code issue on the main repo. Feel free to ask on Discord.
Once that's done, open up the config folder.
Firstly, you will want to copy everything from the example folder into the regular config folder.
EG: Move `config/example/config.txt` to `config/config.txt`, and do the same for all the other files.
You'll want to edit `config.txt` to set your server location,
Firstly, you will want to copy `config.toml` from the example folder into the regular config folder.
You'll want to edit the url configuration section of `config.toml` to set your server location,
so that all your players don't get disconnected at the end of each round.
It's recommended you don't turn on the gamemodes with probability 0,
as they have various issues and aren't currently being tested,
so they may have unknown and bizarre bugs.
You'll also want to edit admins.txt to remove the default admins and add your own.
You'll also want to edit the admin configuration of `config.toml` to remove the default admins and add your own.
If you are connecting from localhost to your own test server, you should automatically be admin.
"Host" is the highest level of access, and the other recommended admin levels for now are
"Game Admin" and "Moderator". The format is:
@@ -60,7 +59,7 @@ If you are connecting from localhost to your own test server, you should automat
where the BYOND key must be in lowercase and the admin rank must be properly capitalised.
There are a bunch more admin ranks, but these two should be enough for most servers,
assuming you have trustworthy admins. You can define your own ranks in `admin_ranks.txt`
assuming you have trustworthy admins. You can define your own ranks in the admin section of `config.toml`
Finally, to start the server,
run Dream Daemon and enter the path to your compiled paradise.dmb file.
-2
View File
@@ -7,5 +7,3 @@ export NODE_VERSION=12
export BYOND_MAJOR=513
# Byond Minor
export BYOND_MINOR=1528
# For the RUSTG library. Not actually installed by CI but kept as a reference
export RUSTG_VERSION=2.1-P
+1 -1
View File
@@ -309,7 +309,7 @@
#define ROUND_TIME (SSticker.round_start_time ? (world.time - SSticker.round_start_time) : 0)
// Macro that returns true if it's too early in a round to freely ghost out
#define TOO_EARLY_TO_GHOST (config && (ROUND_TIME < (config.round_abandon_penalty_period)))
#define TOO_EARLY_TO_GHOST (ROUND_TIME < GLOB.configuration.general.cryo_penalty_period)
// Used by radios to indicate that they have sent a message via something other than subspace
#define RADIO_CONNECTION_FAIL 0
+36 -1
View File
@@ -18,14 +18,46 @@
// Noise related operations //
#define rustg_noise_get_at_coordinates(seed, x, y) call(RUST_G, "noise_get_at_coordinates")(seed, x, y)
// File related operations //
#define rustg_file_read(fname) call(RUST_G, "file_read")(fname)
#define rustg_file_write(text, fname) call(RUST_G, "file_write")(text, fname)
#define rustg_file_append(text, fname) call(RUST_G, "file_append")(text, fname)
#ifdef RUSTG_OVERRIDE_BUILTINS
#define file2text(fname) rustg_file_read(fname)
#define text2file(text, fname) rustg_file_append(text, fname)
#endif
// Git related operations //
#define rustg_git_revparse(rev) call(RUST_G, "rg_git_revparse")(rev)
#define rustg_git_commit_date(rev) call(RUST_G, "rg_git_commit_date")(rev)
// Hash related operations //
#define rustg_hash_string(algorithm, text) call(RUST_G, "hash_string")(algorithm, text)
#define rustg_hash_file(algorithm, fname) call(RUST_G, "hash_file")(algorithm, fname)
#define RUSTG_HASH_MD5 "md5"
#define RUSTG_HASH_SHA1 "sha1"
#define RUSTG_HASH_SHA256 "sha256"
#define RUSTG_HASH_SHA512 "sha512"
#ifdef RUSTG_OVERRIDE_BUILTINS
#define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing))
#endif
// Logging stuff //
#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text)
/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")()
// URL encoding stuff
#define rustg_url_encode(text) call(RUST_G, "url_encode")(text)
#define rustg_url_decode(text) call(RUST_G, "url_decode")(text)
#ifdef RUSTG_OVERRIDE_BUILTINS
#define url_encode(text) rustg_url_encode(text)
#define url_decode(text) rustg_url_decode(text)
#endif
// HTTP library stuff //
#define RUSTG_HTTP_METHOD_GET "get"
#define RUSTG_HTTP_METHOD_PUT "put"
@@ -50,5 +82,8 @@
#define rustg_sql_disconnect_pool(handle) call(RUST_G, "sql_disconnect_pool")(handle)
#define rustg_sql_check_query(job_id) call(RUST_G, "sql_check_query")("[job_id]")
// toml2json stuff //
#define rustg_toml2json(tomlfile) call(RUST_G, "toml2json")(tomlfile)
// RUSTG Version //
#define RUST_G_VERSION "0.4.5-P2"
#define RUST_G_VERSION "0.4.5-P3"
+23 -21
View File
@@ -28,11 +28,12 @@ GLOBAL_PROTECT(log_end)
/proc/log_admin(text)
GLOB.admin_log.Add(text)
if(config.log_admin)
if(GLOB.configuration.logging.admin_logging)
rustg_log_write(GLOB.world_game_log, "ADMIN: [text][GLOB.log_end]")
/proc/log_debug(text)
if(config.log_debug)
// This has presence checks as this may be called before GLOB has loaded
if(GLOB?.configuration?.logging.debug_logging)
rustg_log_write(GLOB.world_game_log, "DEBUG: [text][GLOB.log_end]")
for(var/client/C in GLOB.admins)
@@ -40,80 +41,80 @@ GLOBAL_PROTECT(log_end)
to_chat(C, "DEBUG: [text]")
/proc/log_game(text)
if(config.log_game)
if(GLOB.configuration.logging.game_logging)
rustg_log_write(GLOB.world_game_log, "GAME: [text][GLOB.log_end]")
/proc/log_vote(text)
if(config.log_vote)
if(GLOB.configuration.logging.vote_logging)
rustg_log_write(GLOB.world_game_log, "VOTE: [text][GLOB.log_end]")
/proc/log_access_in(client/new_client)
if(config.log_access)
if(GLOB.configuration.logging.access_logging)
var/message = "[key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version]"
rustg_log_write(GLOB.world_game_log, "ACCESS IN: [message][GLOB.log_end]")
/proc/log_access_out(mob/last_mob)
if(config.log_access)
if(GLOB.configuration.logging.access_logging)
var/message = "[key_name(last_mob)] - IP:[last_mob.lastKnownIP] - CID:[last_mob.computer_id] - BYOND Logged Out"
rustg_log_write(GLOB.world_game_log, "ACCESS OUT: [message][GLOB.log_end]")
/proc/log_say(text, mob/speaker)
if(config.log_say)
if(GLOB.configuration.logging.say_logging)
rustg_log_write(GLOB.world_game_log, "SAY: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_whisper(text, mob/speaker)
if(config.log_whisper)
if(GLOB.configuration.logging.whisper_logging)
rustg_log_write(GLOB.world_game_log, "WHISPER: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_ooc(text, client/user)
if(config.log_ooc)
if(GLOB.configuration.logging.ooc_logging)
rustg_log_write(GLOB.world_game_log, "OOC: [user.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_aooc(text, client/user)
if(config.log_ooc)
if(GLOB.configuration.logging.ooc_logging)
rustg_log_write(GLOB.world_game_log, "AOOC: [user.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_looc(text, client/user)
if(config.log_ooc)
if(GLOB.configuration.logging.ooc_logging)
rustg_log_write(GLOB.world_game_log, "LOOC: [user.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_emote(text, mob/speaker)
if(config.log_emote)
if(GLOB.configuration.logging.emote_logging)
rustg_log_write(GLOB.world_game_log, "EMOTE: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_attack(attacker, defender, message)
if(config.log_attack)
if(GLOB.configuration.logging.attack_logging)
rustg_log_write(GLOB.world_game_log, "ATTACK: [attacker] against [defender]: [message][GLOB.log_end]") //Seperate attack logs? Why?
/proc/log_adminsay(text, mob/speaker)
if(config.log_adminchat)
if(GLOB.configuration.logging.adminchat_logging)
rustg_log_write(GLOB.world_game_log, "ADMINSAY: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_qdel(text)
rustg_log_write(GLOB.world_qdel_log, "QDEL: [text][GLOB.log_end]")
/proc/log_mentorsay(text, mob/speaker)
if(config.log_adminchat)
if(GLOB.configuration.logging.adminchat_logging)
rustg_log_write(GLOB.world_game_log, "MENTORSAY: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_ghostsay(text, mob/speaker)
if(config.log_say)
if(GLOB.configuration.logging.say_logging)
rustg_log_write(GLOB.world_game_log, "DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_ghostemote(text, mob/speaker)
if(config.log_emote)
if(GLOB.configuration.logging.emote_logging)
rustg_log_write(GLOB.world_game_log, "DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_adminwarn(text)
if(config.log_adminwarn)
if(GLOB.configuration.logging.admin_warning_logging)
rustg_log_write(GLOB.world_game_log, "ADMINWARN: [html_decode(text)][GLOB.log_end]")
/proc/log_pda(text, mob/speaker)
if(config.log_pda)
if(GLOB.configuration.logging.pda_logging)
rustg_log_write(GLOB.world_game_log, "PDA: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]")
/proc/log_chat(text, mob/speaker)
if(config.log_pda)
if(GLOB.configuration.logging.pda_logging)
rustg_log_write(GLOB.world_game_log, "CHAT: [speaker.simple_info_line()] [html_decode(text)][GLOB.log_end]")
/proc/log_misc(text)
@@ -121,7 +122,8 @@ GLOBAL_PROTECT(log_end)
/proc/log_world(text)
SEND_TEXT(world.log, text)
if(config && config.log_world_output)
// This has to be presence checked as log_world() is used before world/New().
if(GLOB?.configuration?.logging.world_logging)
rustg_log_write(GLOB.world_game_log, "WORLD: [html_decode(text)][GLOB.log_end]")
/proc/log_runtime_txt(text) // different from /tg/'s log_runtime because our error handler has a log_runtime proc already that does other stuff
+1 -1
View File
@@ -15,7 +15,7 @@ GLOBAL_VAR(church_name)
return name
// TODO: Remove this. Its always gonna be NAS Trurl
// AA TODO: Remove this. Its always gonna be NAS Trurl
/proc/command_name()
return "NAS Trurl"
+3 -3
View File
@@ -10,7 +10,7 @@
/proc/format_table_name(table as text)
return sqlfdbktableprefix + table
return GLOB.configuration.database.table_prefix + table
/*
* Text sanitization
@@ -720,9 +720,9 @@
/proc/client2rankcolour(client/C)
// First check if end user is an admin
if(C.holder)
if(C.holder.rank in GLOB.rank_colour_map)
if(C.holder.rank in GLOB.configuration.admin.rank_colour_map)
// Return their rank colour if they are in here
return GLOB.rank_colour_map[C.holder.rank]
return GLOB.configuration.admin.rank_colour_map[C.holder.rank]
// If they arent an admin, see if they are a patreon. Just accept any level
if(C.donator_level)
+21 -35
View File
@@ -1,44 +1,30 @@
GLOBAL_REAL(config, /datum/configuration)
GLOBAL_VAR(host)
/// Join MOTD for the server
GLOBAL_VAR(join_motd)
GLOBAL_PROTECT(join_motd) // Takes up a lot of space in VV
/// Join TOS for the server
GLOBAL_VAR(join_tos)
GLOBAL_VAR_INIT(game_version, "ParaCode")
GLOBAL_PROTECT(join_tos) // Takes up a lot of space. Also dont touch this shit
/// The current game year
GLOBAL_VAR_INIT(game_year, (text2num(time2text(world.realtime, "YYYY")) + 544))
GLOBAL_VAR_INIT(aliens_allowed, 1)
GLOBAL_VAR_INIT(traitor_scaling, 1)
//GLOBAL_VAR_INIT(goonsay_allowed, 0)
GLOBAL_VAR_INIT(dna_ident, 1)
GLOBAL_VAR_INIT(abandon_allowed, 0)
GLOBAL_VAR_INIT(enter_allowed, 1)
GLOBAL_VAR_INIT(guests_allowed, 1)
GLOBAL_VAR_INIT(shuttle_frozen, 0)
GLOBAL_VAR_INIT(shuttle_left, 0)
GLOBAL_VAR_INIT(tinted_weldhelh, 1)
GLOBAL_VAR_INIT(mouse_respawn_time, 5) //Amount of time that must pass between a player dying as a mouse and repawning as a mouse. In minutes.
/// Allow new players to enter the game?
GLOBAL_VAR_INIT(enter_allowed, TRUE)
// Debug is used exactly once (in living.dm) but is commented out in a lot of places. It is not set anywhere and only checked.
// Debug2 is used in conjunction with a lot of admin verbs and therefore is actually legit.
GLOBAL_VAR_INIT(debug, 0) // global debug switch
GLOBAL_VAR_INIT(debug2, 1) // enables detailed job debug file in secrets
/// Is OOC currently enabled?
GLOBAL_VAR_INIT(ooc_enabled, TRUE)
//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
GLOBAL_VAR_INIT(max_ex_devastation_range, 3)
GLOBAL_VAR_INIT(max_ex_heavy_range, 7)
GLOBAL_VAR_INIT(max_ex_light_range, 14)
GLOBAL_VAR_INIT(max_ex_flash_range, 14)
GLOBAL_VAR_INIT(max_ex_flame_range, 14)
/// Is LOOC currently enabled?
GLOBAL_VAR_INIT(looc_enabled, TRUE)
//Random event stuff, apparently used
GLOBAL_VAR_INIT(eventchance, 10) //% per 5 mins
GLOBAL_VAR_INIT(event, 0)
GLOBAL_VAR_INIT(hadevent, 0)
GLOBAL_VAR_INIT(blobevent, 0)
/// Is OOC currently enabled for dead people?
GLOBAL_VAR_INIT(dooc_enabled, TRUE)
// These vars are protected because changing them could pose a security risk, though they are fine to be read since they are just system paths
GLOBAL_VAR(shutdown_shell_command) // Command to run if shutting down (SHUTDOWN_ON_REBOOT) instead of rebooting
GLOBAL_PROTECT(shutdown_shell_command)
/// Is deadchat currently enabled?
GLOBAL_VAR_INIT(dsay_enabled, TRUE)
GLOBAL_VAR(python_path) //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix
GLOBAL_PROTECT(python_path)
/// Amount of time (in minutes) that must pass between a player dying as a mouse and repawning as a mouse
GLOBAL_VAR_INIT(mouse_respawn_time, 5)
/// Enable debugging of things such as job starts and other things
GLOBAL_VAR_INIT(debug2, TRUE)
-3
View File
@@ -55,7 +55,4 @@ GLOBAL_LIST_INIT(cooking_recipes, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN =
GLOBAL_LIST_INIT(cooking_ingredients, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list()))
GLOBAL_LIST_INIT(cooking_reagents, list(RECIPE_MICROWAVE = list(), RECIPE_OVEN = list(), RECIPE_GRILL = list(), RECIPE_CANDY = list()))
/// Associative list of admin rank to colour. Set in config/rank_colours.txt
GLOBAL_LIST_EMPTY(rank_colour_map)
#define EGG_LAYING_MESSAGES list("lays an egg.", "squats down and croons.", "begins making a huge racket.", "begins clucking raucously.")
-12
View File
@@ -1,12 +0,0 @@
// All global vars in this file require a different handler as we dont want their data to be exposed, not even to admins with permission to view globals
// They write as native BYOND globals, which means they cant be edited at all, and also use a format
// Please only throw absolutely crucial do-not-view shit in here please. -aa07
// 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) = "erro_"
GLOBAL_REAL_VAR(sql_version) = 0
-968
View File
@@ -1,968 +0,0 @@
/datum/configuration
var/server_name = null // server name (for world name / status)
var/server_tag_line = null // server tagline (for showing on hub entry)
var/server_extra_features = null // server-specific extra features (for hub entry)
var/server_suffix = 0 // generate numeric suffix based on server port
var/minimum_client_build = 1421 // Build 1421 due to the middle mouse button exploit
var/nudge_script_path = "nudge.py" // where the nudge.py script is located
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_debug = 1 // log debug output
var/log_game = 0 // log game events
var/log_vote = 0 // log voting
var/log_whisper = 0 // log client whisper
var/log_emote = 0 // log emotes
var/log_attack = 0 // log attack messages
var/log_adminchat = 0 // log admin chat messages
var/log_adminwarn = 0 // log warnings admins get about bomb construction and such
var/log_pda = 0 // log pda messages
var/log_world_output = 0 // log world.log << messages
var/log_runtimes = 0 // logs world.log to a file
var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
var/sql_enabled = 0 // for sql switching
var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
var/pregame_timestart = 240 // Time it takes for the server to start the game
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_autotransfer_initial = 72000 // Length of time before the first autotransfer vote is called
var/vote_autotransfer_interval = 18000 // length of time before next sequential autotransfer vote
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/enable_authentication = 0 // goon authentication
var/del_new_on_log = 1 // qdel's new players if they log before they spawn in
var/feature_object_spell_system = 0 //spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
var/traitor_scaling = 0 //if amount of traitors scales based on amount of players
var/protect_roles_from_antagonist = 0// If security and such can be tratior/cult/other
var/continuous_rounds = 0 // Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke.
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/Ticklag = 0.5
var/socket_talk = 0 // use socket_talk to communicate with other processes
var/list/resource_urls = null
var/antag_hud_allowed = 0 // Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round.
var/antag_hud_restricted = 0 // Ghosts that turn on Antagovision cannot rejoin the round.
var/list/mode_names = list()
var/list/modes = list() // allowed modes
var/list/votable_modes = list() // votable modes
var/list/probabilities = list() // relative probability of each mode
var/humans_need_surnames = 0
var/allow_random_events = 0 // enables random events mid-round when set to 1
var/allow_ai = 1 // allow ai job
var/respawn = 0
var/guest_jobban = 1
var/panic_bunker_threshold = 150 // above this player count threshold, never-before-seen players are blocked from connecting
var/usewhitelist = 0
var/mods_are_mentors = 0
var/load_jobs_from_txt = 0
var/automute_on = 0 //enables automuting/spam prevention
var/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access.
var/round_abandon_penalty_period = 30 MINUTES // Time from round start during which ghosting out is penalized
var/medal_hub_address = null
var/medal_hub_password = null
var/reactionary_explosions = 0 //If we use reactionary explosions, explosions that react to walls and doors
var/assistantlimit = 0 //enables assistant limiting
var/assistantratio = 2 //how many assistants to security members
// The AFK subsystem will not be activated if any of the below config values are equal or less than 0
var/warn_afk_minimum = 0 // How long till you get a warning while being AFK
var/auto_cryo_afk = 0 // How long till you get put into cryo when you're AFK
var/auto_despawn_afk = 0 // How long till you actually despawn in cryo when you're AFK (Not ssd so not automatic)
var/auto_cryo_ssd_mins = 0
var/ssd_warning = 0
var/list_afk_minimum = 5 // How long people have to be AFK before it's listed on the "List AFK players" verb
var/traitor_objectives_amount = 2
var/shadowling_max_age = 0
var/max_maint_drones = 5 //This many drones can spawn,
var/allow_drone_spawn = 1 //assuming the admin allow them to.
var/drone_build_time = 1200 //A drone will become available every X ticks since last drone spawn. Default is 2 minutes.
var/usealienwhitelist = 0
var/limitalienplayers = 0
var/alien_to_human_ratio = 0.5
var/server
var/banappeals
var/wikiurl = "http://example.org"
var/forumurl = "http://example.org"
var/rulesurl = "http://example.org"
var/githuburl = "http://example.org"
var/donationsurl = "http://example.org"
var/repositoryurl = "http://example.org"
var/discordurl = "http://example.org"
var/discordforumurl = "http://example.org"
var/overflow_server_url
var/forbid_singulo_possession = 0
var/check_randomizer = 0
//game_options.txt configs
var/bones_can_break = 1
var/revival_pod_plants = 1
var/revival_cloning = 1
var/revival_brain_life = -1
var/auto_toggle_ooc_during_round = 0
var/shuttle_refuel_delay = 12000
//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
//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/ipintel_maxplaytime = 0
var/ipintel_whitelist = 0
var/ipintel_detailsurl = "https://iphub.info/?ip="
var/forum_link_url
var/forum_playerinfo_url
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_age_restriction_for_antags = 0 //Do antags use account age restrictions? --requires database
var/use_exp_tracking = 0
var/use_exp_restrictions = 0
var/use_exp_restrictions_admin_bypass = 0
var/simultaneous_pm_warning_timeout = 100
var/assistant_maint = 0 //Do assistants get maint access?
var/gateway_delay = 6000
var/ghost_interaction = 0
var/comms_password = ""
var/default_laws = 0 //Controls what laws the AI spawns with.
var/const/minutes_to_ticks = 60 * 10
// Event settings
var/expected_round_length = 60 * 2 * minutes_to_ticks // 2 hours
// If the first delay has a custom start time
// No custom time, no custom time, between 80 to 100 minutes respectively.
var/list/event_first_run = list(EVENT_LEVEL_MUNDANE = null, EVENT_LEVEL_MODERATE = null, EVENT_LEVEL_MAJOR = list("lower" = 48000, "upper" = 60000))
// The lowest delay until next event
// 10, 30, 50 minutes respectively
var/list/event_delay_lower = list(EVENT_LEVEL_MUNDANE = 6000, EVENT_LEVEL_MODERATE = 18000, EVENT_LEVEL_MAJOR = 30000)
// The upper delay until next event
// 15, 45, 70 minutes respectively
var/list/event_delay_upper = list(EVENT_LEVEL_MUNDANE = 9000, EVENT_LEVEL_MODERATE = 27000, EVENT_LEVEL_MAJOR = 42000)
var/starlight = 0 // Whether space turfs have ambient light or not
var/allow_holidays = 0
var/player_overflow_cap = 0 //number of players before the server starts rerouting
var/list/overflow_whitelist = list() //whitelist for overflow
var/disable_away_missions = 0 // disable away missions
var/disable_space_ruins = 0 //disable space ruins
var/extra_space_ruin_levels_min = 4
var/extra_space_ruin_levels_max = 8
var/ooc_allowed = 1
var/looc_allowed = 1
var/dooc_allowed = 1
var/dsay_allowed = 1
var/disable_lobby_music = 0 // Disables the lobby music
var/disable_cid_warn_popup = 0 //disables the annoying "You have already logged in this round, disconnect or be banned" popup, because it annoys the shit out of me when testing.
var/max_loadout_points = 5 // How many points can be spent on extra items in character setup
var/disable_ooc_emoji = 0 // prevents people from using emoji in OOC
var/shutdown_on_reboot = 0 // Whether to shut down the world instead of rebooting it
var/disable_karma = 0 // Disable all karma functions and unlock karma jobs by default
// StonedMC
var/tick_limit_mc_init = TICK_LIMIT_MC_INIT_DEFAULT //SSinitialization throttling
// Highpop tickrates
var/base_mc_tick_rate = 1
var/high_pop_mc_tick_rate = 1.1
var/high_pop_mc_mode_amount = 65
var/disable_high_pop_mc_mode_amount = 60
// Nightshift
var/randomize_shift_time = FALSE
var/enable_night_shifts = FALSE
// Developer
var/developer_express_start = 0
// Automatic localhost admin disable
var/disable_localhost_admin = 0
//Start now warning
var/start_now_confirmation = 0
// Lavaland
var/lavaland_budget = 60
//cube monkey limit
var/cubemonkeycap = 20
// Makes gamemodes respect player limits
var/enable_gamemode_player_limit = 0
/// BYOND account age limit for notifcations of new accounts (Any accounts older than this value will not send notifications on first join)
var/byond_account_age_threshold = 7
/// Are discord webhooks enabled?
var/discord_webhooks_enabled = FALSE
/// Role ID to be pinged for administrative events
var/discord_admin_role_id = null // Intentional null usage
/// Webhook URLs for the main public webhook
var/list/discord_main_webhook_urls = list()
/// Webhook URLs for the admin webhook
var/list/discord_admin_webhook_urls = list()
/// Webhook URLs for the mentor webhook
var/list/discord_mentor_webhook_urls = list()
/// Do we want to forward all adminhelps to the discord or just ahelps when admins are offline.
/// (This does not mean all ahelps are pinged, only ahelps sent when staff are offline get the ping, regardless of this setting)
var/discord_forward_all_ahelps = FALSE
/// URL for the CentCom Ban DB API
var/centcom_ban_db_url = null
/// Timeout (seconds) for async SQL queries
var/async_sql_query_timeout = 10 SECONDS
/// Limit of how many SQL threads can run at once
var/rust_sql_thread_limit = 50
/// Max amount of CIDs that one ckey can have attached to them before they trip a warning
var/max_client_cid_history = 3
/// Enable auto profiler of rounds
var/auto_profile = FALSE
// Enable map voting
var/map_voting_enabled = FALSE
// 2FA auth host
var/_2fa_auth_host = null
/datum/configuration/New()
for(var/T in subtypesof(/datum/game_mode))
var/datum/game_mode/M = T
if(initial(M.config_tag))
if(!(initial(M.config_tag) in modes)) // ensure each mode is added only once
src.modes += initial(M.config_tag)
src.mode_names[initial(M.config_tag)] = initial(M.name)
src.probabilities[initial(M.config_tag)] = initial(M.probability)
if(initial(M.votable))
src.votable_modes += initial(M.config_tag)
src.votable_modes += "secret"
/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
if(IsAdminAdvancedProcCall())
to_chat(usr, "<span class='boldannounce'>Config reload blocked: Advanced ProcCall detected.</span>")
message_admins("[key_name(usr)] attempted to reload configuration via advanced proc-call")
log_admin("[key_name(usr)] attempted to reload configuration via advanced proc-call")
return
var/list/Lines = 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("resource_urls")
config.resource_urls = splittext(value, " ")
if("admin_legacy_system")
config.admin_legacy_system = 1
if("ban_legacy_system")
config.ban_legacy_system = 1
if("use_age_restriction_for_jobs")
config.use_age_restriction_for_jobs = 1
if("use_age_restriction_for_antags")
config.use_age_restriction_for_antags = 1
if("use_exp_tracking")
config.use_exp_tracking = 1
if("use_exp_restrictions")
config.use_exp_restrictions = 1
if("use_exp_restrictions_admin_bypass")
config.use_exp_restrictions_admin_bypass = 1
if("jobs_have_minimal_access")
config.jobs_have_minimal_access = 1
if("shadowling_max_age")
config.shadowling_max_age = text2num(value)
if("warn_afk_minimum")
config.warn_afk_minimum = text2num(value)
if("auto_cryo_afk")
config.auto_cryo_afk = text2num(value)
if("auto_despawn_afk")
config.auto_despawn_afk = text2num(value)
if("auto_cryo_ssd_mins")
config.auto_cryo_ssd_mins = text2num(value)
if("ssd_warning")
config.ssd_warning = 1
if("list_afk_minimum")
config.list_afk_minimum = text2num(value)
if("ipintel_email")
if(value != "ch@nge.me")
config.ipintel_email = value
if("ipintel_rating_bad")
config.ipintel_rating_bad = text2num(value)
if("ipintel_domain")
config.ipintel_domain = value
if("ipintel_save_good")
config.ipintel_save_good = text2num(value)
if("ipintel_save_bad")
config.ipintel_save_bad = text2num(value)
if("ipintel_maxplaytime")
config.ipintel_maxplaytime = text2num(value)
if("ipintel_whitelist")
config.ipintel_whitelist = 1
if("ipintel_detailsurl")
config.ipintel_detailsurl = value
if("forum_link_url")
config.forum_link_url = value
if("forum_playerinfo_url")
config.forum_playerinfo_url = value
if("log_ooc")
config.log_ooc = 1
if("log_access")
config.log_access = 1
if("log_say")
config.log_say = 1
if("log_admin")
config.log_admin = 1
if("log_debug")
config.log_debug = 1
if("log_game")
config.log_game = 1
if("log_vote")
config.log_vote = 1
if("log_whisper")
config.log_whisper = 1
if("log_attack")
config.log_attack = 1
if("log_emote")
config.log_emote = 1
if("log_adminchat")
config.log_adminchat = 1
if("log_adminwarn")
config.log_adminwarn = 1
if("log_pda")
config.log_pda = 1
if("log_world_output")
config.log_world_output = 1
if("log_hrefs")
config.log_hrefs = 1
if("log_runtime")
config.log_runtimes = 1
if("mentors")
config.mods_are_mentors = 1
if("allow_admin_ooccolor")
config.allow_admin_ooccolor = 1
if("pregame_timestart")
config.pregame_timestart = text2num(value)
if("allow_vote_restart")
config.allow_vote_restart = 1
if("allow_vote_mode")
config.allow_vote_mode = 1
if("no_dead_vote")
config.vote_no_dead = 1
if("vote_autotransfer_initial")
config.vote_autotransfer_initial = text2num(value)
if("vote_autotransfer_interval")
config.vote_autotransfer_interval = text2num(value)
if("default_no_vote")
config.vote_no_default = 1
if("vote_delay")
config.vote_delay = text2num(value)
if("vote_period")
config.vote_period = text2num(value)
if("allow_ai")
config.allow_ai = 1
// if("authentication")
// config.enable_authentication = 1
if("norespawn")
config.respawn = 0
if("servername")
config.server_name = value
if("server_tag_line")
config.server_tag_line = value
if("server_extra_features")
config.server_extra_features = value
if("serversuffix")
config.server_suffix = 1
if("minimum_client_build")
config.minimum_client_build = text2num(value)
if("nudge_script_path")
config.nudge_script_path = value
if("server")
config.server = value
if("banappeals")
config.banappeals = value
if("wikiurl")
config.wikiurl = value
if("forumurl")
config.forumurl = value
if("rulesurl")
config.rulesurl = value
if("githuburl")
config.githuburl = value
if("discordurl")
config.discordurl = value
if("discordforumurl")
config.discordforumurl = value
if("donationsurl")
config.donationsurl = value
if("repositoryurl")
config.repositoryurl = value
if("guest_jobban")
config.guest_jobban = 1
if("guest_ban")
GLOB.guests_allowed = 0
if("panic_bunker_threshold")
config.panic_bunker_threshold = text2num(value)
if("usewhitelist")
config.usewhitelist = 1
if("feature_object_spell_system")
config.feature_object_spell_system = 1
if("allow_metadata")
config.allow_Metadata = 1
if("traitor_scaling")
config.traitor_scaling = 1
if("protect_roles_from_antagonist")
config.protect_roles_from_antagonist = 1
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 config.modes)
config.probabilities[prob_name] = text2num(prob_value)
else
log_config("Unknown game mode probability configuration definition: [prob_name].")
else
log_config("Incorrect probability configuration definition: [prob_name] [prob_value].")
if("allow_random_events")
config.allow_random_events = 1
if("load_jobs_from_txt")
load_jobs_from_txt = 1
if("forbid_singulo_possession")
forbid_singulo_possession = 1
if("check_randomizer")
check_randomizer = 1
if("popup_admin_pm")
config.popup_admin_pm = 1
if("allow_holidays")
config.allow_holidays = 1
if("ticklag")
Ticklag = text2num(value)
if("socket_talk")
socket_talk = text2num(value)
if("allow_antag_hud")
config.antag_hud_allowed = 1
if("antag_hud_restricted")
config.antag_hud_restricted = 1
if("humans_need_surnames")
humans_need_surnames = 1
if("automute_on")
automute_on = 1
if("usealienwhitelist")
usealienwhitelist = 1
if("alien_player_ratio")
limitalienplayers = 1
alien_to_human_ratio = text2num(value)
if("assistant_maint")
config.assistant_maint = 1
if("gateway_delay")
config.gateway_delay = text2num(value)
if("continuous_rounds")
config.continuous_rounds = 1
if("ghost_interaction")
config.ghost_interaction = 1
if("comms_password")
config.comms_password = value
if("python_path")
if(value)
GLOB.python_path = value
else
if(world.system_type == UNIX)
GLOB.python_path = "/usr/bin/env python2"
else //probably windows, if not this should work anyway
GLOB.python_path = "pythonw"
if("assistant_limit")
config.assistantlimit = 1
if("assistant_ratio")
config.assistantratio = text2num(value)
if("allow_drone_spawn")
config.allow_drone_spawn = text2num(value)
if("drone_build_time")
config.drone_build_time = text2num(value)
if("max_maint_drones")
config.max_maint_drones = text2num(value)
if("expected_round_length")
config.expected_round_length = text2num(value) MINUTES
if("event_custom_start_mundane")
var/values = text2numlist(value, ";")
config.event_first_run[EVENT_LEVEL_MUNDANE] = list("lower" = values[1] MINUTES, "upper" = values[2] MINUTES)
if("event_custom_start_moderate")
var/values = text2numlist(value, ";")
config.event_first_run[EVENT_LEVEL_MODERATE] = list("lower" = values[1] MINUTES, "upper" = values[2] MINUTES)
if("event_custom_start_major")
var/values = text2numlist(value, ";")
config.event_first_run[EVENT_LEVEL_MAJOR] = list("lower" = values[1] MINUTES, "upper" = values[2] MINUTES)
if("event_delay_lower")
var/values = text2numlist(value, ";")
config.event_delay_lower[EVENT_LEVEL_MUNDANE] = values[1] MINUTES
config.event_delay_lower[EVENT_LEVEL_MODERATE] = values[2] MINUTES
config.event_delay_lower[EVENT_LEVEL_MAJOR] = values[3] MINUTES
if("event_delay_upper")
var/values = text2numlist(value, ";")
config.event_delay_upper[EVENT_LEVEL_MUNDANE] = values[1] MINUTES
config.event_delay_upper[EVENT_LEVEL_MODERATE] = values[2] MINUTES
config.event_delay_upper[EVENT_LEVEL_MAJOR] = values[3] MINUTES
if("starlight")
config.starlight = 1
if("player_reroute_cap")
var/vvalue = text2num(value)
config.player_overflow_cap = vvalue >= 0 ? vvalue : 0
if("overflow_server_url")
config.overflow_server_url = value
if("disable_away_missions")
config.disable_away_missions = 1
if("disable_space_ruins")
config.disable_space_ruins = 1
if("disable_lobby_music")
config.disable_lobby_music = 1
if("disable_cid_warn_popup")
config.disable_cid_warn_popup = 1
if("extra_space_ruin_levels_min")
var/vvalue = text2num(value)
config.extra_space_ruin_levels_min = max(vvalue, 0)
if("extra_space_ruin_levels_max")
var/vvalue = text2num(value)
config.extra_space_ruin_levels_max = max(vvalue, 0)
if("max_loadout_points")
config.max_loadout_points = text2num(value)
if("round_abandon_penalty_period")
config.round_abandon_penalty_period = text2num(value) MINUTES
if("medal_hub_address")
config.medal_hub_address = value
if("medal_hub_password")
config.medal_hub_password = value
if("disable_ooc_emoji")
config.disable_ooc_emoji = 1
if("shutdown_on_reboot")
config.shutdown_on_reboot = 1
if("shutdown_shell_command")
GLOB.shutdown_shell_command = value
if("disable_karma")
config.disable_karma = 1
if("start_now_confirmation")
config.start_now_confirmation = 1
if("tick_limit_mc_init")
config.tick_limit_mc_init = text2num(value)
if("base_mc_tick_rate")
config.base_mc_tick_rate = text2num(value)
if("high_pop_mc_tick_rate")
config.high_pop_mc_tick_rate = text2num(value)
if("high_pop_mc_mode_amount")
config.high_pop_mc_mode_amount = text2num(value)
if("disable_high_pop_mc_mode_amount")
config.disable_high_pop_mc_mode_amount = text2num(value)
if("developer_express_start")
config.developer_express_start = 1
if("disable_localhost_admin")
config.disable_localhost_admin = 1
if("enable_gamemode_player_limit")
config.enable_gamemode_player_limit = 1
if("byond_account_age_threshold")
config.byond_account_age_threshold = text2num(value)
// Discord stuff
if("enable_discord_webhooks")
discord_webhooks_enabled = TRUE
if("discord_webhooks_admin_role_id")
discord_admin_role_id = "[value]" // This MUST be a string because BYOND doesnt like massive integers
if("discord_webhooks_main_url")
discord_main_webhook_urls = splittext(value, "|")
if("discord_webhooks_admin_url")
discord_admin_webhook_urls = splittext(value, "|")
if("discord_webhooks_mentor_url")
discord_mentor_webhook_urls = splittext(value, "|")
if("discord_forward_all_ahelps")
discord_forward_all_ahelps = TRUE
// End discord stuff
if("centcom_ban_db_url")
centcom_ban_db_url = value
if("max_client_cid_history")
max_client_cid_history = text2num(value)
if("enable_auto_profiler")
auto_profile = TRUE
if("enable_map_voting")
map_voting_enabled = TRUE
if("2fa_host")
_2fa_auth_host = value
else
log_config("Unknown setting in configuration: '[name]'")
else if(type == "game_options")
value = text2num(value)
switch(name)
if("revival_pod_plants")
config.revival_pod_plants = value
if("revival_cloning")
config.revival_cloning = value
if("revival_brain_life")
config.revival_brain_life = value
if("auto_toggle_ooc_during_round")
config.auto_toggle_ooc_during_round = 1
if("run_speed")
config.run_speed = value
if("walk_speed")
config.walk_speed = value
if("human_delay")
config.human_delay = value
if("robot_delay")
config.robot_delay = value
if("monkey_delay")
config.monkey_delay = value
if("alien_delay")
config.alien_delay = value
if("slime_delay")
config.slime_delay = value
if("animal_delay")
config.animal_delay = value
if("bones_can_break")
config.bones_can_break = value
if("shuttle_refuel_delay")
config.shuttle_refuel_delay = text2num(value)
if("traitor_objectives_amount")
config.traitor_objectives_amount = text2num(value)
if("reactionary_explosions")
config.reactionary_explosions = 1
if("bombcap")
var/BombCap = text2num(value)
if(!BombCap)
continue
if(BombCap < 4)
BombCap = 4
if(BombCap > 128)
BombCap = 128
GLOB.max_ex_devastation_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("default_laws")
config.default_laws = text2num(value)
if("randomize_shift_time")
config.randomize_shift_time = TRUE
if("enable_night_shifts")
config.enable_night_shifts = TRUE
if("lavaland_budget")
config.lavaland_budget = text2num(value)
if("cubemonkey_cap")
config.cubemonkeycap = text2num(value)
else
log_config("Unknown setting in configuration: '[name]'")
/datum/configuration/proc/loadsql(filename) // -- TLE
if(IsAdminAdvancedProcCall())
to_chat(usr, "<span class='boldannounce'>SQL configuration reload blocked: Advanced ProcCall detected.</span>")
message_admins("[key_name(usr)] attempted to reload SQL configuration via advanced proc-call")
log_admin("[key_name(usr)] attempted to reload SQL configuration via advanced proc-call")
return
var/list/Lines = 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")
config.sql_enabled = 1
if("address")
sqladdress = value
if("port")
sqlport = value
if("feedback_database")
sqlfdbkdb = value
if("feedback_login")
sqlfdbklogin = value
if("feedback_password")
sqlfdbkpass = value
if("feedback_tableprefix")
sqlfdbktableprefix = value
if("db_version")
sql_version = text2num(value)
if("async_query_timeout")
async_sql_query_timeout = text2num(value)
if("rust_sql_thread_limit")
config.rust_sql_thread_limit = text2num(value)
else
log_config("Unknown setting in configuration: '[name]'")
/datum/configuration/proc/loadoverflowwhitelist(filename)
var/list/Lines = 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
config.overflow_whitelist += t
/datum/configuration/proc/pick_mode(mode_name)
for(var/T in subtypesof(/datum/game_mode))
var/datum/game_mode/M = T
if(initial(M.config_tag) && initial(M.config_tag) == 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 subtypesof(/datum/game_mode))
var/datum/game_mode/M = new T()
// to_chat(world, "DEBUG: [T], tag=[M.config_tag], prob=[probabilities[M.config_tag]]")
if(!(M.config_tag in modes))
qdel(M)
continue
if(probabilities[M.config_tag]<=0)
qdel(M)
continue
if(M.can_start())
runnable_modes[M] = probabilities[M.config_tag]
// to_chat(world, "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]")
return runnable_modes
/datum/configuration/proc/load_rank_colour_map()
var/list/lines = file2list("config/rank_colours.txt")
for(var/line in lines)
// Skip newlines
if(!length(line))
continue
// Skip comments
if(line[1] == "#")
continue
//Split the line at every " - "
var/list/split_holder = splittext(line, " - ")
if(!length(split_holder))
continue
// Rank is before the " - "
var/rank = split_holder[1]
if(!rank)
continue
// Color is after the " - "
var/colour = ""
if(length(split_holder) >= 2)
colour = split_holder[2]
if(rank && colour)
GLOB.rank_colour_map[rank] = colour
else
stack_trace("Invalid colour for rank '[rank]' in config/rank_colours.txt")
@@ -0,0 +1,40 @@
// Config protection states
#define PROTECTION_PRIVATE "PRIVATE"
#define PROTECTION_READONLY "READONLY"
#define PROTECTION_NONE "NONE"
/// Wrapper to not overwrite a variable if a list key doesnt exist. Auto casts to bools.
#define CONFIG_LOAD_BOOL(target, input) \
if(!isnull(input)) {\
target = ((input == 1) ? TRUE : FALSE)\
}
/// Wrapper to not overwrite a variable if a list key doesnt exist. Auto casts to number.
#define CONFIG_LOAD_NUM(target, input) \
if(!isnull(input)) {\
target = text2num(input)\
}
/// Wrapper to not overwrite a variable if a list key doesnt exist. Auto casts to number, and accepts a macro argument for number maths (ds to min for example)
#define CONFIG_LOAD_NUM_MULT(target, input, multiplier) \
if(!isnull(input)) {\
target = text2num(input) multiplier\
}
/// Wrapper to not overwrite a variable if a list key doesnt exist. Auto casts to string.
#define CONFIG_LOAD_STR(target, input) \
if(!isnull(input)) {\
target = "[input]"\
}
/// Wrapper to not overwrite a variable if a list key doesnt exist. No casting done.
#define CONFIG_LOAD_RAW(target, input) \
if(!isnull(input)) {\
target = input\
}
/// Wrapper to not overwrite a variable if a list key doesnt exist. Ensures target is a list.
#define CONFIG_LOAD_LIST(target, input) \
if(islist(input)) {\
target = input\
}
@@ -0,0 +1,142 @@
// Paradise SS13 Configuration System
// Refactored to use config sections as part of a single TOML file, since thats much better to deal with
/// Global configuration datum holder for all the config sections
GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new())
/// Represents a base configuration datum. Has everything else bundled into it
/datum/server_configuration
/// Holder for the admin configuration datum
var/datum/configuration_section/admin_configuration/admin
/// Holder for the AFK configuration datum
var/datum/configuration_section/afk_configuration/afk
/// Holder for the custom sprites configuration datum
var/datum/configuration_section/custom_sprites_configuration/custom_sprites
/// Holder for the DB configuration datum
var/datum/configuration_section/database_configuration/database
/// Holder for the Discord configuration datum
var/datum/configuration_section/discord_configuration/discord
/// Holder for the Event configuration datum
var/datum/configuration_section/event_configuration/event
/// Holder for the gamemode configuration datum
var/datum/configuration_section/gamemode_configuration/gamemode
/// Holder for the gateway configuration datum
var/datum/configuration_section/gateway_configuration/gateway
/// Holder for the general configuration datum
var/datum/configuration_section/general_configuration/general
/// Holder for the IPIntel configuration datum
var/datum/configuration_section/ipintel_configuration/ipintel
/// Holder for the job configuration datum
var/datum/configuration_section/job_configuration/jobs
/// Holder for the logging configuration datum
var/datum/configuration_section/logging_configuration/logging
/// Holder for the MC configuration datum
var/datum/configuration_section/mc_configuration/mc
/// Holder for the MC configuration datum
var/datum/configuration_section/movement_configuration/movement
/// Holder for the overflow configuration datum
var/datum/configuration_section/overflow_configuration/overflow
/// Holder for the ruins configuration datum
var/datum/configuration_section/ruin_configuration/ruins
/// Holder for the system configuration datum
var/datum/configuration_section/system_configuration/system
/// Holder for the URL configuration datum
var/datum/configuration_section/url_configuration/url
/// Holder for the voting configuration datum
var/datum/configuration_section/vote_configuration/vote
/datum/server_configuration/Destroy(force)
SHOULD_CALL_PARENT(FALSE)
// This is going to stay existing. I dont care.
return QDEL_HINT_LETMELIVE
/datum/server_configuration/CanProcCall(procname)
return FALSE // No thanks
/datum/server_configuration/proc/load_configuration()
var/start = start_watch() // Time tracking
// Initialize all our holders
admin = new()
afk = new()
custom_sprites = new()
database = new()
discord = new()
event = new()
gamemode = new()
gateway = new()
general = new()
ipintel = new()
jobs = new()
logging = new()
mc = new()
movement = new()
overflow = new()
ruins = new()
system = new()
url = new()
vote = new()
// Load our stuff up
var/config_file = "config/config.toml"
if(!fexists(config_file))
config_file = "config/example/config.toml" // Fallback to example if user hasnt setup config properly
var/raw_json = rustg_toml2json(config_file)
var/list/raw_config_data = json_decode(raw_json)
// Now pass through all our stuff
admin.load_data(raw_config_data["admin_configuration"])
afk.load_data(raw_config_data["afk_configuration"])
custom_sprites.load_data(raw_config_data["custom_sprites_configuration"])
database.load_data(raw_config_data["database_configuration"])
discord.load_data(raw_config_data["discord_configuration"])
event.load_data(raw_config_data["event_configuration"])
gamemode.load_data(raw_config_data["gamemode_configuration"])
gateway.load_data(raw_config_data["gateway_configuration"])
general.load_data(raw_config_data["general_configuration"])
ipintel.load_data(raw_config_data["ipintel_configuration"])
jobs.load_data(raw_config_data["job_configuration"])
logging.load_data(raw_config_data["logging_configuration"])
mc.load_data(raw_config_data["mc_configuration"])
movement.load_data(raw_config_data["movement_configuration"])
overflow.load_data(raw_config_data["overflow_configuration"])
ruins.load_data(raw_config_data["ruin_configuration"])
system.load_data(raw_config_data["system_configuration"])
url.load_data(raw_config_data["url_configuration"])
vote.load_data(raw_config_data["voting_configuration"])
// And report the load
DIRECT_OUTPUT(world.log, "Config loaded in [stop_watch(start)]s")
/datum/configuration_section
/// See __config_defines.dm
var/protection_state = PROTECTION_NONE
/datum/configuration_section/proc/load_data(list/data)
CRASH("load() not overriden for [type]!")
// Maximum protection
/datum/configuration_section/can_vv_get(var_name)
if(protection_state == PROTECTION_PRIVATE)
return FALSE
return ..()
/datum/configuration_section/vv_edit_var(var_name, var_value)
if(protection_state in list(PROTECTION_PRIVATE, PROTECTION_READONLY))
return FALSE
return ..()
/datum/configuration_section/vv_get_var(var_name)
if(protection_state == PROTECTION_PRIVATE)
return FALSE
return ..()
/datum/configuration_section/Destroy(force)
SHOULD_CALL_PARENT(FALSE)
// This is going to stay existing. I dont care.
return QDEL_HINT_LETMELIVE
/datum/configuration_section/CanProcCall(procname)
return FALSE // No thanks
@@ -0,0 +1,43 @@
/// Config holder for all admin related things
/datum/configuration_section/admin_configuration
protection_state = PROTECTION_READONLY // Dont even think about it
/// Do we want to load admins from the database?
var/use_database_admins = FALSE
/// Do we want to auto enable admin rights if you connect from localhost?
var/enable_localhost_autoadmin = TRUE
/// Do we want to allow admins to set their own OOC colour?
var/allow_admin_ooc_colour = TRUE
/// Assoc list of admin ranks and their stuff. key: rank name string | value: list of rights
var/list/rank_rights_map = list()
/// Assoc list of admin ckeys and their ranks. key: ckey | value: rank name
var/list/ckey_rank_map = list()
/// Assoc list of admin ranks and their colours. key: rank | value: rank colour
var/list/rank_colour_map = list()
/datum/configuration_section/admin_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(use_database_admins, data["use_database_admins"])
CONFIG_LOAD_BOOL(enable_localhost_autoadmin, data["enable_localhost_autoadmin"])
CONFIG_LOAD_BOOL(allow_admin_ooc_colour, data["allow_admin_ooc_colour"])
// Load admin rank tokens
if(islist(data["admin_ranks"]))
rank_rights_map.Cut()
for(var/list/kvset in data["admin_ranks"])
rank_rights_map[kvset["name"]] = kvset["rights"]
// Load admin assignments
if(islist(data["admin_assignments"]))
ckey_rank_map.Cut()
for(var/list/kvset in data["admin_assignments"])
ckey_rank_map[kvset["ckey"]] = kvset["rank"]
// Load admin colours
if(islist(data["admin_rank_colour_map"]))
rank_colour_map.Cut()
for(var/list/kvset in data["admin_rank_colour_map"])
rank_colour_map[kvset["name"]] = kvset["colour"]
// For the person who asks "Why not put admin datum generation in this step?", well I will tell you why
// Admins can be reloaded at runtime when DB edits are made and such, and I dont want an entire config reload to be part of this
// Separation makes sense. That and in prod we use the DB anyways.
@@ -0,0 +1,17 @@
/// Config holder for all AFK related things
/datum/configuration_section/afk_configuration
/// Minutes before someone gets an AFK warning
var/warning_minutes = 0
/// Minutes before someone is auto moved to cryo
var/auto_cryo_minutes = 0
/// Minutes before someone is auto despawned
var/auto_despawn_minutes = 0
/// Time before SSD people are auto cryo'd
var/ssd_auto_cryo_minutes = 0
/datum/configuration_section/afk_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_NUM(warning_minutes, data["afk_warning_minutes"])
CONFIG_LOAD_NUM(auto_cryo_minutes, data["afk_auto_cryo_minutes"])
CONFIG_LOAD_NUM(auto_despawn_minutes, data["afk_auto_despawn_minutes"])
CONFIG_LOAD_NUM(ssd_auto_cryo_minutes, data["ssd_auto_cryo_minutes"])
@@ -0,0 +1,25 @@
/// Config holder for all things regarding custom sprites
/datum/configuration_section/custom_sprites_configuration
/// List of ckeys that have custom cyborg skins
var/list/cyborg_ckeys = list()
/// List of ckeys that have custom AI core skins
var/list/ai_core_ckeys = list()
/// List of ckeys that have custom AI hologram skins
var/list/ai_hologram_ckeys = list()
/// List of ckeys that have custom pAI holoforms
var/list/pai_holoform_ckeys = list()
/// Assoc of ckeys that have custom pAI screens. Key: ckey | value: list of icon states
var/list/ipc_screen_map = list()
/datum/configuration_section/custom_sprites_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_LIST(cyborg_ckeys, data["cyborgs"])
CONFIG_LOAD_LIST(ai_core_ckeys, data["ai_core"])
CONFIG_LOAD_LIST(ai_hologram_ckeys, data["ai_hologram"])
CONFIG_LOAD_LIST(pai_holoform_ckeys, data["pai_holoform"])
// Load the ipc screens
if(islist(data["ipc_screens"]))
ipc_screen_map.Cut()
for(var/kvp in data["ipc_screens"])
ipc_screen_map[kvp["ckey"]] = kvp["screens"]
@@ -0,0 +1,47 @@
/// Config holder for all database related things
/datum/configuration_section/database_configuration
protection_state = PROTECTION_PRIVATE // NO! BAD!
/// SQL enabled or not
var/enabled = FALSE
/// What SQL version are we on
var/version = 0
/// Address of the SQL server
var/address = "127.0.0.1"
/// Port of the SQL server
var/port = 3306
/// SQL usename
var/username = "root"
/// SQL password
var/password = "root" // Dont do this in prod. Please......
/// Database name
var/db = "feedback" // AA TODO: Rename to paradise_gamedb
/// Table prefix
var/table_prefix = "erro_" // AA TODO: Remove table prefixes
/// Time in seconds for async queries to time out
var/async_query_timeout = 10
/// Thread limit for async queries
var/async_thread_limit = 50
/datum/configuration_section/database_configuration/load_data(list/data)
// UNIT TESTS ARE DEFINED - USE CUSTOM CI VALUES
#ifdef UNIT_TESTS
enabled = TRUE
table_prefix = ""
// This needs to happen in the CI environment to ensure the example SQL version gets updated.
CONFIG_LOAD_NUM(version, data["sql_version"])
#else
// Load the normal config. Were not in CI mode
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(enabled, data["sql_enabled"])
CONFIG_LOAD_NUM(version, data["sql_version"])
CONFIG_LOAD_STR(address, data["sql_address"])
CONFIG_LOAD_NUM(port, data["sql_port"])
CONFIG_LOAD_STR(username, data["sql_username"])
CONFIG_LOAD_STR(password, data["sql_password"])
CONFIG_LOAD_STR(db, data["sql_database"])
CONFIG_LOAD_STR(table_prefix, data["sql_table_prefix"])
CONFIG_LOAD_NUM(async_query_timeout, data["async_query_timeout"])
CONFIG_LOAD_NUM(async_thread_limit, data["async_thread_limit"])
#endif
@@ -0,0 +1,26 @@
/// Config holder for all things relating to discord webhooks
/datum/configuration_section/discord_configuration
protection_state = PROTECTION_PRIVATE // No hook reading
/// Are webhooks enabled at all
var/webhooks_enabled = FALSE
/// Do we want to forward all ahelps or just ones sent with no active admins
var/forward_all_ahelps = TRUE
/// Admin role to ping if no admins are online. Disables if empty string
var/admin_role_id = ""
/// List of all URLs for the main webhooks
var/list/main_webhook_urls = list()
/// List of all URLs for the admin webhooks
var/list/mentor_webhook_urls = list()
/// List of all URLs for the mentor webhooks
var/list/admin_webhook_urls = list()
/datum/configuration_section/discord_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(webhooks_enabled, data["enable_discord_webhooks"])
CONFIG_LOAD_BOOL(forward_all_ahelps, data["forward_all_ahelps"])
CONFIG_LOAD_STR(admin_role_id, data["admin_role_id"])
CONFIG_LOAD_LIST(main_webhook_urls, data["main_webhook_urls"])
CONFIG_LOAD_LIST(mentor_webhook_urls, data["mentor_webhook_urls"])
CONFIG_LOAD_LIST(admin_webhook_urls, data["admin_webhook_urls"])
@@ -0,0 +1,61 @@
/// Config holder for all stuff relating to ingame random events
/datum/configuration_section/event_configuration
/// Do we want to enable random events at all
var/enable_random_events = TRUE
/// Assoc list of when the first event in a group can run. key: severity | value: assoc list with upper and low bounds (key: "upper"/"lower" | value: time in deciseconds)
var/list/first_run_times = list(
EVENT_LEVEL_MUNDANE = null,
EVENT_LEVEL_MODERATE = null,
EVENT_LEVEL_MAJOR = list("lower" = 40 MINUTES, "upper" = 50 MINUTES)
) // <---- Whoever designed this needs to be shot
/// Assoc list of lower bounds of event delays. key: severity | value: delay (deciseconds)
var/list/delay_lower_bound = list(
EVENT_LEVEL_MUNDANE = 5 MINUTES,
EVENT_LEVEL_MODERATE = 15 MINUTES,
EVENT_LEVEL_MAJOR = 25 MINUTES
)
/// Assoc list of lower bounds of event delays. key: severity | value: delay (deciseconds)
var/list/delay_upper_bound = list(
EVENT_LEVEL_MUNDANE = 7.5 MINUTES,
EVENT_LEVEL_MODERATE = 22.5 MINUTES,
EVENT_LEVEL_MAJOR = 35 MINUTES
)
/// Expected time of a round in deciseconds
var/expected_round_length = 120 MINUTES // This macro is equivilent to 72,000 deciseconds
/datum/configuration_section/event_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(enable_random_events, data["allow_random_events"])
// Wrapper cant be used here due to it being multiplied
if(isnum(data["expected_round_length"]))
expected_round_length = data["expected_round_length"] MINUTES // Convert from minutes to deciseconds
// Load event severities. This is quite awful but needs to be done so we can account for config mistakes. This event system is awful
if(islist(data["event_delay_lower_bounds"]))
CONFIG_LOAD_NUM_MULT(delay_lower_bound[EVENT_LEVEL_MUNDANE], data["event_delay_lower_bounds"]["mundane"], MINUTES)
CONFIG_LOAD_NUM_MULT(delay_lower_bound[EVENT_LEVEL_MODERATE], data["event_delay_lower_bounds"]["moderate"], MINUTES)
CONFIG_LOAD_NUM_MULT(delay_lower_bound[EVENT_LEVEL_MAJOR], data["event_delay_lower_bounds"]["major"], MINUTES)
// Same here. I hate this.
if(islist(data["event_delay_upper_bounds"]))
CONFIG_LOAD_NUM_MULT(delay_upper_bound[EVENT_LEVEL_MUNDANE], data["event_delay_upper_bounds"]["mundane"], MINUTES)
CONFIG_LOAD_NUM_MULT(delay_upper_bound[EVENT_LEVEL_MODERATE], data["event_delay_upper_bounds"]["moderate"], MINUTES)
CONFIG_LOAD_NUM_MULT(delay_upper_bound[EVENT_LEVEL_MAJOR], data["event_delay_upper_bounds"]["major"], MINUTES)
// And for the worst, the first run delays. I hate this so much -aa07
if(islist(data["event_initial_delays"]))
for(var/list/assoclist in data["event_initial_delays"])
var/target = null
switch(assoclist["severity"])
if("mundane")
target = EVENT_LEVEL_MUNDANE
if("moderate")
target = EVENT_LEVEL_MODERATE
if("major")
target = EVENT_LEVEL_MAJOR
ASSERT(target in list(EVENT_LEVEL_MUNDANE, EVENT_LEVEL_MODERATE, EVENT_LEVEL_MAJOR))
first_run_times[target] = list("lower" = assoclist["lower_bound"] MINUTES, "upper" = assoclist["upper_bound"] MINUTES)
@@ -0,0 +1,96 @@
/// Config holder for everything regarding gamemodes
/datum/configuration_section/gamemode_configuration
/// List of all gamemodes (value: config-tag)
var/list/gamemodes = list()
/// Assoc list of gamemode names (key: config-tag | value: mode name)
var/list/gamemode_names = list()
/// Assoc list of gamemode probabilities (key: config-tag | value: probability)
var/list/probabilities = list()
/// List of all gamemodes that can be voted for (value: config-tag)
var/list/votable_modes = list()
/// Should antags be restricted based on account age?
var/antag_account_age_restriction = FALSE
/// Max age (in SSmobs cycles, [2 seconds]) before a shadowling starts to take damage if they have not hatched
var/shadowling_max_age = 600 // 20 mins
/// Scale amount of traitors with population
var/traitor_scaling = TRUE
/// Prevent mindshield roles getting antagonist status
var/prevent_mindshield_antags = TRUE
/// Rounds such as rev, wizard and malf end instantly when the antag has won. Enable the setting below to not do that.
var/disable_certain_round_early_end = FALSE
/// Amount of objectives traitors should get. Does not include escape or hijack.
var/traitor_objectives_amount = 2
/// Enable player limits on gamemodes? Disabling can be useful for testing
var/enable_gamemode_player_limit = TRUE
// Dynamically setup a list of all gamemodes
/datum/configuration_section/gamemode_configuration/New()
for(var/T in subtypesof(/datum/game_mode))
var/datum/game_mode/M = T
// Dont bother if theres no tag
if(!initial(M.config_tag))
continue
// Ensure each mode is added only once
if(initial(M.config_tag) in gamemodes)
continue
// Add it in
gamemodes += initial(M.config_tag)
gamemode_names[initial(M.config_tag)] = initial(M.name)
probabilities[initial(M.config_tag)] = initial(M.probability)
if(initial(M.votable))
votable_modes += initial(M.config_tag)
// Add secret to the votable pool
votable_modes += "secret"
/datum/configuration_section/gamemode_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(antag_account_age_restriction, data["antag_account_age_restrictions"])
CONFIG_LOAD_BOOL(traitor_scaling, data["traitor_scaling"])
CONFIG_LOAD_BOOL(prevent_mindshield_antags, data["prevent_mindshield_antag"])
CONFIG_LOAD_BOOL(disable_certain_round_early_end, data["disable_certain_round_early_end"])
CONFIG_LOAD_BOOL(enable_gamemode_player_limit, data["enable_gamemode_player_limit"])
CONFIG_LOAD_NUM(traitor_objectives_amount, data["traitor_objective_amount"])
CONFIG_LOAD_NUM(shadowling_max_age, data["shadowling_max_age"])
// Load gamemode probabilities
if(islist(data["gamemode_probabilities"]))
for(var/list/assocset in data["gamemode_probabilities"])
// Make sure it exists
if(assocset["gamemode"] in gamemodes)
probabilities[assocset["gamemode"]] = assocset["probability"]
else
stack_trace("Gamemode [assocset["gamemode"]] has a probability in config, but does not exist!")
/datum/configuration_section/gamemode_configuration/proc/pick_mode(mode_name)
for(var/T in subtypesof(/datum/game_mode))
var/datum/game_mode/M = T
// If the tag exists, and its the same as the mode
if(initial(M.config_tag) && (initial(M.config_tag) == mode_name))
return new T()
// Default to extended if it didnt work
stack_trace("Could not pick a gamemode. Defaulting to extended. (Attempted mode: [mode_name])")
return new /datum/game_mode/extended()
/datum/configuration_section/gamemode_configuration/proc/get_runnable_modes()
var/list/datum/game_mode/runnable_modes = new
for(var/T in subtypesof(/datum/game_mode))
var/datum/game_mode/M = new T()
if(!(M.config_tag in gamemodes))
qdel(M)
continue
if(probabilities[M.config_tag] <= 0)
qdel(M)
continue
if(M.can_start())
runnable_modes[M] = probabilities[M.config_tag]
return runnable_modes
@@ -0,0 +1,14 @@
/// Config holder for all gateway related things
/datum/configuration_section/gateway_configuration
/// Do we want to enable away missions or not
var/enable_away_mission = TRUE
/// Delay (in deciseconds) before the gateway is usable
var/away_mission_delay = 6000
/// List of all available away missions
var/list/enabled_away_missions = list()
/datum/configuration_section/gateway_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(enable_away_mission, data["enable_away_mission"])
CONFIG_LOAD_NUM(away_mission_delay, data["away_mission_delay"])
CONFIG_LOAD_LIST(enabled_away_missions, data["enabled_away_missions"])
@@ -0,0 +1,137 @@
/// Config holder for all general/misc things
/datum/configuration_section/general_configuration
/// Server name for the BYOND hub
var/server_name = "Paradise Station"
/// Tagline for the hub entry
var/server_tag_line = "The perfect mix of RP & action"
/// Server features in a newline
var/server_features = "Medium RP, varied species/jobs"
/// Should bans be stored in the DB
var/use_database_bans = FALSE
/// Allow character OOC notes
var/allow_character_metadata = TRUE
/// Time in seconds for the pregame lobby
var/lobby_time = 240
/// Ban all Guest BYOND accounts
var/guest_ban = TRUE
/// Player threshold to automatically enable panic bunker
var/panic_bunker_threshold = 150
/// Allow players to use AntagHUD?
var/allow_antag_hud = TRUE
/// Forbid players from rejoining if they use AntagHUD?
var/restrict_antag_hud_rejoin = TRUE
/// Enable respanws by default?
var/respawn_enabled = FALSE
/// Enable karma? Disable to lockout awarding and unlock everything
var/enable_karma = TRUE
/// Enable CID randomiser buster?
var/enabled_cid_randomiser_buster = FALSE
/// Forbid admins from posessing and flying the singulo round
var/forbid_singulo_possession = FALSE
/// Force open a PM window when replied to? This is very annoying
var/popup_admin_pm = FALSE
/// Announce holidays (christmas, halloween, etc etc)
var/allow_holidays = TRUE
/// Enable auto muting in all chat channels
var/enable_auto_mute = FALSE
/// Show a warning to players to make them accept touching an SSD
var/ssd_warning = TRUE
/// Allow ghosts to spin chairs round
var/ghost_interaction = FALSE
/// Enable/disable starlight to light up space
var/starlight = TRUE
/// Disable lobby music?
var/disable_lobby_music = FALSE
/// Disable a popup if 2 users are on the same CID?
var/disable_cid_warning_popup = FALSE
/// Amount of loadout points non-donors should get
var/base_loadout_points = 5
/// Respawnability loss penalty for eary cryoing (minutes)
var/cryo_penalty_period = 30
/// Enable OOC emojis?
var/enable_ooc_emoji = TRUE
/// Auto start the game if on a local test server
var/developer_express_start = FALSE
/// Minimum client build. Keep above 1421 due to exploits
var/minimum_client_build = 1421
/// Give a confirm button for the "Start Now" verb
var/start_now_confirmation = TRUE
/// BYOND account age threshold for first join alerts
var/byond_account_age_threshold = 3
/// Max CIDs a client can have history of before a warning is thrown
var/max_client_cid_history = 20
/// Enable automatic profiling to profile.json
var/enable_auto_profiler = TRUE
/// Auto disable OOC on roundstart?
var/auto_disable_ooc = TRUE
/// Do we want to allow bones to break?
var/breakable_bones = TRUE
/// Enable/disable revival pod plants
var/enable_revival_pod_plants = TRUE
/// Enable/disable cloning
var/enable_cloning = TRUE
/// Randomise shift time instead of it always being 12:00?
var/randomise_shift_time = TRUE
/// Enable night-shift lighting?
var/enable_night_shifts = TRUE
/// Cap for monkey cube monkey spawns
var/monkey_cube_cap = 32
/// Enable to make explosions react to obstacles instead of ignoring them
var/reactionary_explosions = TRUE
/// Bomb cap (Devastation) Other values will be calculated around this
var/bomb_cap = 20
/// Time for a brain to keep its spark of life (deciseconds)
var/revival_brain_life = 10 MINUTES
/// Enable random AI lawsets from the default=TRUE pool
var/random_ai_lawset = TRUE
/datum/configuration_section/general_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
// A lot of bools
CONFIG_LOAD_BOOL(use_database_bans, data["use_database_bans"])
CONFIG_LOAD_BOOL(allow_character_metadata, data["allow_character_metadata"])
CONFIG_LOAD_BOOL(guest_ban, data["guest_ban"])
CONFIG_LOAD_BOOL(allow_antag_hud, data["allow_antag_hud"])
CONFIG_LOAD_BOOL(restrict_antag_hud_rejoin, data["restrict_antag_hud_rejoin"])
CONFIG_LOAD_BOOL(respawn_enabled, data["respawn_enabled"])
CONFIG_LOAD_BOOL(enable_karma, data["enable_karma"])
CONFIG_LOAD_BOOL(enabled_cid_randomiser_buster, data["enable_cid_randomiser_buster"])
CONFIG_LOAD_BOOL(forbid_singulo_possession, data["prevent_admin_singlo_possession"])
CONFIG_LOAD_BOOL(popup_admin_pm, data["popup_admin_pm"])
CONFIG_LOAD_BOOL(allow_holidays, data["allow_holidays"])
CONFIG_LOAD_BOOL(enable_auto_mute, data["enable_auto_mute"])
CONFIG_LOAD_BOOL(ssd_warning, data["ssd_warning"])
CONFIG_LOAD_BOOL(ghost_interaction, data["ghost_interaction"])
CONFIG_LOAD_BOOL(starlight, data["starlight"])
CONFIG_LOAD_BOOL(disable_lobby_music, data["disable_lobby_music"])
CONFIG_LOAD_BOOL(disable_cid_warning_popup, data["disable_cid_warning_popup"])
CONFIG_LOAD_BOOL(enable_ooc_emoji, data["enable_ooc_emoji"])
CONFIG_LOAD_BOOL(developer_express_start, data["developer_express_start"])
CONFIG_LOAD_BOOL(start_now_confirmation, data["start_now_confirmation"])
CONFIG_LOAD_BOOL(enable_auto_profiler, data["enable_auto_profiler"])
CONFIG_LOAD_BOOL(auto_disable_ooc, data["auto_disable_ooc"])
CONFIG_LOAD_BOOL(breakable_bones, data["breakable_bones"])
CONFIG_LOAD_BOOL(enable_revival_pod_plants, data["enable_revival_pod_plants"])
CONFIG_LOAD_BOOL(enable_cloning, data["enable_cloning"])
CONFIG_LOAD_BOOL(randomise_shift_time, data["randomise_shift_time"])
CONFIG_LOAD_BOOL(enable_night_shifts, data["enable_night_shifts"])
CONFIG_LOAD_BOOL(reactionary_explosions, data["reactionary_explosions"])
CONFIG_LOAD_BOOL(random_ai_lawset, data["random_ai_lawset"])
// Numbers
CONFIG_LOAD_NUM(lobby_time, data["lobby_time"])
CONFIG_LOAD_NUM(panic_bunker_threshold, data["panic_bunker_threshold"])
CONFIG_LOAD_NUM(base_loadout_points, data["base_loadout_points"])
CONFIG_LOAD_NUM(cryo_penalty_period, data["cryo_penalty_period"])
CONFIG_LOAD_NUM(minimum_client_build, data["minimum_client_build"])
CONFIG_LOAD_NUM(byond_account_age_threshold, data["byond_account_age_threshold"])
CONFIG_LOAD_NUM(max_client_cid_history, data["max_client_cid_history"])
CONFIG_LOAD_NUM(monkey_cube_cap, data["monkey_cube_cap"])
CONFIG_LOAD_NUM(bomb_cap, data["bomb_cap"])
CONFIG_LOAD_NUM(revival_brain_life, data["revival_brain_life"])
// Strings
CONFIG_LOAD_STR(server_name, data["server_name"])
CONFIG_LOAD_STR(server_tag_line, data["server_tag_line"])
CONFIG_LOAD_STR(server_features, data["server_features"])
@@ -0,0 +1,34 @@
/// Config holder for all things relating to IPIntel
/datum/configuration_section/ipintel_configuration
/// Is IPIntel enabled
var/enabled = FALSE
/// Are we in whitelist mode (Auto-kick people who are on proxies/VPNs)
var/whitelist_mode = TRUE
/// 0-1 float for percentage threshold to kick people out
var/bad_rating = 0.9
/// IPIntel contact email. Required.
var/contact_email = null
/// How many hours to save good matches for. Cached due to rate limits
var/hours_save_good = 72
/// How many hours to save bad matches for. Cached due to rate limits
var/hours_save_bad = 24
/// IPIntel Domain. Do not prefix with a protocol
var/ipintel_domain = "check.getipintel.net"
/// Do not proxy-check players with more hours than the below threshold
var/playtime_ignore_threshold = 10
/// Details URL for more info on an IP, including ASN. IP is tacked straight on the end.
var/details_url = "https://iphub.info/?ip="
/datum/configuration_section/ipintel_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(enabled, data["ipintel_enabled"])
CONFIG_LOAD_BOOL(whitelist_mode, data["whitelist_mode"])
CONFIG_LOAD_NUM(bad_rating, data["bad_rating"])
CONFIG_LOAD_NUM(hours_save_good, data["hours_save_good"])
CONFIG_LOAD_NUM(hours_save_bad, data["hours_save_bad"])
CONFIG_LOAD_NUM(playtime_ignore_threshold, data["playtime_ignore_threshold"])
CONFIG_LOAD_STR(contact_email, data["contact_email"])
CONFIG_LOAD_STR(ipintel_domain, data["ipintel_domain"])
CONFIG_LOAD_STR(details_url, data["details_url"])
@@ -0,0 +1,55 @@
/// Config holder for all job related things
/datum/configuration_section/job_configuration
/// Do we want jobs to have minimal access or extra access (IE: Scientists having robotics access)
var/jobs_have_minimal_access = TRUE
/// Do we want to restrict jobs based on account age
var/restrict_jobs_on_account_age = FALSE
/// Allow admins to bypass age-based job restrictions
var/restrict_jobs_on_account_age_admin_bypass = TRUE
/// Enable EXP logging and tracking
var/enable_exp_tracking = FALSE
/// Lockout jobs based on EXP
var/enable_exp_restrictions = FALSE
/// Allow admins to bypass EXP restrictions
var/enable_exp_admin_bypass = TRUE
/// Allow non-admins to play as AI
var/allow_ai = TRUE
/// Prevent guests from playing high profile roles
var/guest_job_ban = TRUE
/// Grant assistants maint access
var/assistant_maint_access = TRUE
/// Limit amount of assistants?
var/assistant_limit = FALSE
/// If yes to above, ratio of assistants per security officer (IE: 4:1)
var/assistant_security_ratio = 2
/// Enable loading of job overrides from the config
var/enable_job_amount_overrides = TRUE
/// Map of job:amount for lowpop. key: Job | value: amount
var/list/lowpop_job_map = list()
/// Map of job:amount for highpop. key: Job | value: amount
var/list/highpop_job_map = list()
/datum/configuration_section/job_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(jobs_have_minimal_access, data["jobs_have_minimal_access"])
CONFIG_LOAD_BOOL(restrict_jobs_on_account_age, data["restrict_jobs_on_account_age"])
CONFIG_LOAD_BOOL(restrict_jobs_on_account_age_admin_bypass, data["restrict_jobs_on_account_age_admin_bypass"])
CONFIG_LOAD_BOOL(enable_exp_tracking, data["enable_exp_tracking"])
CONFIG_LOAD_BOOL(enable_exp_restrictions, data["enable_exp_restrictions"])
CONFIG_LOAD_BOOL(enable_exp_admin_bypass, data["enable_exp_admin_bypass"])
CONFIG_LOAD_BOOL(allow_ai, data["allow_ai"])
CONFIG_LOAD_BOOL(guest_job_ban, data["guest_job_ban"])
CONFIG_LOAD_BOOL(assistant_maint_access, data["assistant_maint_access"])
CONFIG_LOAD_BOOL(assistant_limit, data["assistant_limit"])
CONFIG_LOAD_NUM(assistant_security_ratio, data["assistant_security_ratio"])
CONFIG_LOAD_BOOL(enable_job_amount_overrides, data["enable_job_amount_overrides"])
if(enable_job_amount_overrides && islist(data["job_slot_amounts"]))
lowpop_job_map.Cut()
highpop_job_map.Cut()
for(var/kvp in data["job_slot_amounts"])
if(!isnull(kvp["name"]))
if(!isnull(kvp["lowpop"]))
lowpop_job_map[kvp["name"]] = kvp["lowpop"]
if(!isnull(kvp["highpop"]))
highpop_job_map[kvp["name"]] = kvp["highpop"]
@@ -0,0 +1,53 @@
/// Config holder for all things regarding logging
/datum/configuration_section/logging_configuration
/// Log OOC messages
var/ooc_logging = TRUE
/// Log ingame say messages
var/say_logging = TRUE
/// Log admin actions
var/admin_logging = TRUE
/// Log client access (login/logout)
var/access_logging = TRUE
/// Log game events (roundstart, results, a lot of other things)
var/game_logging = TRUE
/// Enable logging of votes and their results
var/vote_logging = TRUE
/// Enable logging of whipers
var/whisper_logging = TRUE
/// Enable logging of emotes
var/emote_logging = TRUE
/// Enable logging of attacks between players
var/attack_logging = TRUE
/// Enable logging of PDA messages
var/pda_logging = TRUE
/// Enable runtime logging
var/runtime_logging = TRUE
/// Enable world.log output logging
var/world_logging = TRUE
/// Log hrefs
var/href_logging = TRUE
/// Log admin warning messages
var/admin_warning_logging = TRUE
/// Log asay messages
var/adminchat_logging = TRUE
/// Log debug messages
var/debug_logging = TRUE
/datum/configuration_section/logging_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(ooc_logging, data["enable_ooc_logging"])
CONFIG_LOAD_BOOL(say_logging, data["enable_say_logging"])
CONFIG_LOAD_BOOL(admin_logging, data["enable_admin_logging"])
CONFIG_LOAD_BOOL(access_logging, data["enable_access_logging"])
CONFIG_LOAD_BOOL(game_logging, data["enable_game_logging"])
CONFIG_LOAD_BOOL(vote_logging, data["enable_vote_logging"])
CONFIG_LOAD_BOOL(whisper_logging, data["enable_whisper_logging"])
CONFIG_LOAD_BOOL(emote_logging, data["enable_emote_logging"])
CONFIG_LOAD_BOOL(attack_logging, data["enable_attack_logging"])
CONFIG_LOAD_BOOL(pda_logging, data["enable_pda_logging"])
CONFIG_LOAD_BOOL(runtime_logging, data["enable_runtime_logging"])
CONFIG_LOAD_BOOL(world_logging, data["enable_world_logging"])
CONFIG_LOAD_BOOL(href_logging, data["enable_href_logging"])
CONFIG_LOAD_BOOL(admin_warning_logging, data["enable_admin_warning_logging"])
CONFIG_LOAD_BOOL(adminchat_logging, data["enable_adminchat_logging"])
CONFIG_LOAD_BOOL(debug_logging, data["enable_debug_logging"])
@@ -0,0 +1,23 @@
/// Config holder for all things regarding the MC
/datum/configuration_section/mc_configuration
/// Server ticklag
var/ticklag = 0.5
/// Tick limit % during world Init
var/world_init_tick_limit = TICK_LIMIT_MC_INIT_DEFAULT
/// Base MC tick rate
var/base_tickrate = 1
/// Highpop MC tickrate
var/highpop_tickrate = 1.1
/// MC Highpop enable threshold
var/highpop_enable_threshold = 65
/// MC Highpop disable threshold
var/highpop_disable_threshold = 60
/datum/configuration_section/mc_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_NUM(ticklag, data["ticklag"])
CONFIG_LOAD_NUM(world_init_tick_limit, data["world_init_mc_tick_limit"])
CONFIG_LOAD_NUM(base_tickrate, data["base_mc_tick_rate"])
CONFIG_LOAD_NUM(highpop_tickrate, data["highpop_mc_tick_rate"])
CONFIG_LOAD_NUM(highpop_enable_threshold, data["mc_highpop_threshold_enable"])
CONFIG_LOAD_NUM(highpop_disable_threshold, data["mc_highpop_threshold_disable"])
@@ -0,0 +1,26 @@
/// Config holder for values relating to mob movement speeds
/datum/configuration_section/movement_configuration
/// Base run speed before modifiers
var/base_run_speed = 1
/// Base walk speed before modifiers
var/base_walk_speed = 4
/// Move delay for humanoids
var/human_delay = 1.5
/// Move delay for cyborgs
var/robot_delay = 2.5
/// Move delay for xenomorphs
var/alien_delay = 1.5
/// Move delay for slimes (xenobio, not slimepeople)
var/slime_delay = 1.5
/// Move delay for other simple animals
var/animal_delay = 2.5
/datum/configuration_section/movement_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_NUM(base_run_speed, data["base_run_speed"])
CONFIG_LOAD_NUM(base_walk_speed, data["base_walk_speed"])
CONFIG_LOAD_NUM(human_delay, data["human_delay"])
CONFIG_LOAD_NUM(robot_delay, data["robot_delay"])
CONFIG_LOAD_NUM(alien_delay, data["alien_delay"])
CONFIG_LOAD_NUM(slime_delay, data["slime_delay"])
CONFIG_LOAD_NUM(animal_delay, data["animal_delay"])
@@ -0,0 +1,14 @@
/// Config holder for all overflow-server related things
/datum/configuration_section/overflow_configuration
/// Amount of players before reroute server is used. 0 to disable.
var/reroute_cap = 0
/// Location of the overflow server
var/overflow_server_location = null
/// List of ckeys who will never be routed to the overflow server
var/list/overflow_whitelist = list()
/datum/configuration_section/overflow_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_NUM(reroute_cap, data["player_reroute_cap"])
CONFIG_LOAD_STR(overflow_server_location, data["overflow_server"])
CONFIG_LOAD_LIST(overflow_whitelist, data["overflow_whitelist"])
@@ -0,0 +1,23 @@
/// Config holder for all things regarding space ruins and lavaland ruins
/datum/configuration_section/ruin_configuration
/// Enable or disable space ruins
var/enable_space_ruins = TRUE
/// Minimum number of extra zlevels to fill with ruins
var/extra_levels_min = 2
/// Maximum number of extra zlevels to fill with ruins
var/extra_levels_max = 4
/// List of all active space ruins
var/list/active_space_ruins = list()
/// List of all active lavaland ruins
var/list/active_lava_ruins = list()
/// Budget for lavaland ruins
var/lavaland_ruin_budget = 60
/datum/configuration_section/ruin_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(enable_space_ruins, data["enable_space_ruins"])
CONFIG_LOAD_NUM(extra_levels_min, data["minimum_zlevels"])
CONFIG_LOAD_NUM(extra_levels_max, data["maximum_zlevels"])
CONFIG_LOAD_LIST(active_space_ruins, data["active_space_ruins"])
CONFIG_LOAD_LIST(active_lava_ruins, data["active_lava_ruins"])
CONFIG_LOAD_NUM(lavaland_ruin_budget, data["lavaland_ruin_budget"])
@@ -0,0 +1,26 @@
/// Config holder for stuff relating to server backend management and secrets
/datum/configuration_section/system_configuration
// NO EDITS OR READS TO THIS WHAT SOEVER
protection_state = PROTECTION_PRIVATE
/// Password for authorising world/Topic requests
var/topic_key = null
/// Medal hub address for lavaland stats
var/medal_hub_address = null
/// Medal hub password for lavaland stats
var/medal_hub_password = null
/// Do we want the server to kill on reboot instead of keeping the same DD session
var/shutdown_on_reboot = FALSE
/// If above is true, you can run a shell command
var/shutdown_shell_command = null
/// 2FA backend server host
var/_2fa_auth_host = null
/datum/configuration_section/system_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(shutdown_on_reboot, data["shutdown_on_reboot"])
CONFIG_LOAD_STR(topic_key, data["communications_password"])
CONFIG_LOAD_STR(medal_hub_address, data["medal_hub_address"])
CONFIG_LOAD_STR(medal_hub_password, data["medal_hub_password"])
CONFIG_LOAD_STR(shutdown_shell_command, data["shutdown_shell_command"])
CONFIG_LOAD_STR(_2fa_auth_host, data["_2fa_auth_host"])
@@ -0,0 +1,47 @@
/// Config holder for all the server URLs
/datum/configuration_section/url_configuration
// Dont tweak these. You can read them though.
protection_state = PROTECTION_READONLY
/// List of URLs for the server RSC data
var/list/rsc_urls = list()
/// Server URL for auto-reconnecting people at end round
var/server_url
/// URL for the server ban appeals forum
var/banappeals_url
/// URL for the server wiki
var/wiki_url
/// URL for the server forums
var/forum_url
/// URL for the server rules
var/rules_url
/// URL for the server github repository
var/github_url
/// URL for server donations
var/donations_url
/// URL for a direct discord invite
var/discord_url
/// URL for a discord invite going via the forums
var/discord_forum_url
/// URL for linking ingame accounts and forum accounts. Token is appended to end
var/forum_link_url
/// URL for pulling player info on webtools
var/forum_playerinfo_url
/// URL for the CentCom Ban DB API
var/centcom_ban_db_url
/datum/configuration_section/url_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_LIST(rsc_urls, data["rsc_urls"])
CONFIG_LOAD_STR(server_url, data["reboot_url"])
CONFIG_LOAD_STR(banappeals_url, data["ban_appeals_url"])
CONFIG_LOAD_STR(wiki_url, data["wiki_url"])
CONFIG_LOAD_STR(forum_url, data["forum_url"])
CONFIG_LOAD_STR(rules_url, data["rules_url"])
CONFIG_LOAD_STR(github_url, data["github_url"])
CONFIG_LOAD_STR(donations_url, data["donations_url"])
CONFIG_LOAD_STR(discord_url, data["discord_url"])
CONFIG_LOAD_STR(discord_forum_url, data["discord_forum_url"])
CONFIG_LOAD_STR(forum_link_url, data["forum_link_url"])
CONFIG_LOAD_STR(forum_playerinfo_url, data["forum_playerinfo_url"])
CONFIG_LOAD_STR(centcom_ban_db_url, data["centcomm_ban_db_url"])
@@ -0,0 +1,33 @@
/// Config holder for stuff relating to the ingame vote system
/datum/configuration_section/vote_configuration
/// Allow players to start restart votes?
var/allow_restart_votes = FALSE
/// Allow players to start gamemode votes?
var/allow_mode_votes = FALSE
/// Minimum delay between each vote (deciseconds)
var/vote_delay = 18000 // 30 mins
/// How long will a vote last for (deciseconds)
var/vote_time = 600 // 60 seconds
/// Time before the first shuttle vote (deciseconds)
var/autotransfer_initial_time = 72000 // 2 hours
/// Time between subsequent shuttle votes if the first one is not successful (deciseconds)
var/autotransfer_interval_time = 18000 // 30 mins
/// Prevent dead players from voting
var/prevent_dead_voting = FALSE
/// Default to players not voting
var/disable_default_vote = TRUE
/// Enable map voting?
var/enable_map_voting = FALSE
/datum/configuration_section/vote_configuration/load_data(list/data)
// Use the load wrappers here. That way the default isnt made 'null' if you comment out the config line
CONFIG_LOAD_BOOL(allow_restart_votes, data["allow_vote_restart"])
CONFIG_LOAD_BOOL(allow_mode_votes, data["allow_vote_mode"])
CONFIG_LOAD_BOOL(prevent_dead_voting, data["prevent_dead_voting"])
CONFIG_LOAD_BOOL(disable_default_vote, data["disable_default_vote"])
CONFIG_LOAD_BOOL(enable_map_voting, data["enable_map_voting"])
CONFIG_LOAD_NUM(vote_delay, data["vote_delay"])
CONFIG_LOAD_NUM(vote_time, data["vote_time"])
CONFIG_LOAD_NUM(autotransfer_initial_time, data["autotransfer_initial_time"])
CONFIG_LOAD_NUM(autotransfer_interval_time, data["autotransfer_interval_time"])
+8 -8
View File
@@ -194,7 +194,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/start_timeofday = REALTIMEOFDAY
// Initialize subsystems.
current_ticklimit = config.tick_limit_mc_init
current_ticklimit = GLOB.configuration.mc.world_init_tick_limit
for(var/datum/controller/subsystem/SS in subsystems)
if(SS.flags & SS_NO_INIT)
continue
@@ -206,8 +206,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
log_startup_progress("Initializations complete within [time] second[time == 1 ? "" : "s"]!")
if(config.developer_express_start & SSticker.current_state == GAME_STATE_PREGAME)
SSticker.current_state = GAME_STATE_SETTING_UP
if(GLOB.configuration.general.developer_express_start)
SSticker.force_start = TRUE
if(!current_runlevel)
SetRunLevel(1)
@@ -216,7 +216,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
sortTim(subsystems, /proc/cmp_subsystem_display)
// Set world options.
// world.fps = CONFIG_GET(number/fps) // TIGER TODO
world.tick_lag = config.Ticklag
world.tick_lag = GLOB.configuration.mc.ticklag
var/initialized_tod = REALTIMEOFDAY
if(sleep_offline_after_initializations)
@@ -626,10 +626,10 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
if(!processing)
return
var/client_count = length(GLOB.clients)
if(client_count < config.disable_high_pop_mc_mode_amount)
processing = config.base_mc_tick_rate
else if(client_count > config.high_pop_mc_mode_amount)
processing = config.high_pop_mc_tick_rate
if(client_count < GLOB.configuration.mc.highpop_disable_threshold)
processing = GLOB.configuration.mc.base_tickrate
else if(client_count > GLOB.configuration.mc.highpop_enable_threshold)
processing = GLOB.configuration.mc.highpop_tickrate
/datum/controller/master/proc/formatcpu()
switch(world.cpu)
+8 -6
View File
@@ -12,7 +12,8 @@ SUBSYSTEM_DEF(afk)
/datum/controller/subsystem/afk/Initialize()
if(config.warn_afk_minimum <= 0 || config.auto_cryo_afk <= 0 || config.auto_despawn_afk <= 0)
if(GLOB.configuration.afk.warning_minutes <= 0 || GLOB.configuration.afk.auto_cryo_minutes <= 0 || GLOB.configuration.afk.auto_despawn_minutes <= 0)
flags |= SS_NO_FIRE
else
non_cryo_antags = list(SPECIAL_ROLE_ABDUCTOR_AGENT, SPECIAL_ROLE_ABDUCTOR_SCIENTIST, \
@@ -35,19 +36,20 @@ SUBSYSTEM_DEF(afk)
toRemove += H.ckey
continue
var/mins_afk = round(H.client.inactivity / 600)
if(mins_afk < config.warn_afk_minimum)
if(mins_afk < GLOB.configuration.afk.warning_minutes)
if(afk_players[H.ckey])
toRemove += H.ckey
continue
if(!afk_players[H.ckey])
afk_players[H.ckey] = AFK_WARNED
warn(H, "<span class='danger'>You are AFK for [mins_afk] minutes. You will be cryod after [config.auto_cryo_afk] total minutes and fully despawned after [config.auto_despawn_afk] total minutes. Please move or click in game if you want to avoid being despawned.</span>")
warn(H, "<span class='danger'>You are AFK for [mins_afk] minutes. You will be cryod after [GLOB.configuration.afk.auto_cryo_minutes] total minutes and fully despawned after [GLOB.configuration.afk.auto_despawn_minutes] total minutes. Please move or click in game if you want to avoid being despawned.</span>")
else
var/area/A = T.loc // Turfs loc is the area
if(afk_players[H.ckey] == AFK_WARNED)
if(mins_afk >= config.auto_cryo_afk && A.can_get_auto_cryod)
if(mins_afk >= GLOB.configuration.afk.auto_cryo_minutes && A.can_get_auto_cryod)
if(A.fast_despawn)
toRemove += H.ckey
warn(H, "<span class='danger'>You have been despawned after being AFK for [mins_afk] minutes. You have been despawned instantly due to you being in a secure area.</span>")
@@ -60,13 +62,13 @@ SUBSYSTEM_DEF(afk)
afk_players[H.ckey] = AFK_CRYOD
log_afk_action(H, mins_afk, T, "put into cryostorage")
warn(H, "<span class='danger'>You are AFK for [mins_afk] minutes and have been moved to cryostorage. \
After being AFK for another [config.auto_despawn_afk] minutes you will be fully despawned. \
After being AFK for another [GLOB.configuration.afk.auto_despawn_minutes] minutes you will be fully despawned. \
Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.</span>")
else
message_admins("[key_name_admin(H)] at ([get_area(T).name] [ADMIN_JMP(T)]) is AFK for [mins_afk] and can't be automatically cryod due to it's antag status: ([H.mind.special_role]).")
afk_players[H.ckey] = AFK_ADMINS_WARNED
else if(afk_players[H.ckey] != AFK_ADMINS_WARNED && mins_afk >= config.auto_despawn_afk)
else if(afk_players[H.ckey] != AFK_ADMINS_WARNED && mins_afk >= GLOB.configuration.afk.auto_despawn_minutes)
log_afk_action(H, mins_afk, T, "despawned")
warn(H, "<span class='danger'>You have been despawned after being AFK for [mins_afk] minutes.</span>")
toRemove += H.ckey
+2 -2
View File
@@ -266,11 +266,11 @@ SUBSYSTEM_DEF(changelog)
usr.client.github()
// Takes a PR number as argument
if(href_list["openPR"])
if(config.githuburl)
if(GLOB.configuration.url.github_url)
if(alert("This will open PR #[href_list["openPR"]] in your browser. Are you sure?",,"Yes","No")=="No")
return
// If the github URL in the config has a trailing slash, it doesnt matter here, thankfully github accepts having a double slash: https://github.com/org/repo//pull/1
var/url = "[config.githuburl]/pull/[href_list["openPR"]]"
var/url = "[GLOB.configuration.url.github_url]/pull/[href_list["openPR"]]"
usr << link(url)
else
to_chat(usr, "<span class='danger'>The GitHub URL is not set in the server configuration. PRs cannot be opened from changelog view. Please inform the server host.</span>")
+16 -16
View File
@@ -30,7 +30,7 @@ SUBSYSTEM_DEF(dbcore)
// This is in Initialize() so that its actually seen in chat
/datum/controller/subsystem/dbcore/Initialize()
if(!schema_valid)
to_chat(world, "<span class='boldannounce'>Database schema ([sql_version]) doesn't match the latest schema version ([SQL_VERSION]). Roundstart has been delayed.</span>")
to_chat(world, "<span class='boldannounce'>Database schema ([GLOB.configuration.database.version]) doesn't match the latest schema version ([SQL_VERSION]). Roundstart has been delayed.</span>")
return ..()
@@ -66,7 +66,7 @@ SUBSYSTEM_DEF(dbcore)
if(IsConnected())
return TRUE
if(!config.sql_enabled)
if(!GLOB.configuration.database.enabled)
return FALSE
if(failed_connection_timeout <= world.time) //it's been more than 5 seconds since we failed to connect, reset the counter
@@ -77,14 +77,14 @@ SUBSYSTEM_DEF(dbcore)
return FALSE
var/result = json_decode(rustg_sql_connect_pool(json_encode(list(
"host" = sqladdress,
"port" = text2num(sqlport),
"user" = sqlfdbklogin,
"pass" = sqlfdbkpass,
"db_name" = sqlfdbkdb,
"read_timeout" = config.async_sql_query_timeout,
"write_timeout" = config.async_sql_query_timeout,
"max_threads" = config.rust_sql_thread_limit,
"host" = GLOB.configuration.database.address,
"port" = GLOB.configuration.database.port,
"user" = GLOB.configuration.database.username,
"pass" = GLOB.configuration.database.password,
"db_name" = GLOB.configuration.database.db,
"read_timeout" = GLOB.configuration.database.async_query_timeout,
"write_timeout" = GLOB.configuration.database.async_query_timeout,
"max_threads" = GLOB.configuration.database.async_thread_limit,
))))
. = (result["status"] == "ok")
if(.)
@@ -102,11 +102,11 @@ SUBSYSTEM_DEF(dbcore)
* If it is a valid version, the DB will then connect.
*/
/datum/controller/subsystem/dbcore/proc/CheckSchemaVersion()
if(config.sql_enabled)
if(GLOB.configuration.database.enabled)
// The unit tests have their own version of this check, which wont hold the server up infinitely, so this is disabled if we are running unit tests
#ifndef UNIT_TESTS
if(config.sql_enabled && sql_version != SQL_VERSION)
config.sql_enabled = FALSE
if(GLOB.configuration.database.enabled && GLOB.configuration.database.version != SQL_VERSION)
GLOB.configuration.database.enabled = FALSE
schema_valid = FALSE
SSticker.ticker_going = FALSE
SEND_TEXT(world.log, "Database connection failed: Invalid SQL Versions")
@@ -206,7 +206,7 @@ SUBSYSTEM_DEF(dbcore)
* Does a few sanity checks, then asks the DLL if we are properly connected
*/
/datum/controller/subsystem/dbcore/proc/IsConnected()
if(!config.sql_enabled)
if(!GLOB.configuration.database.enabled)
return FALSE
if(!schema_valid)
return FALSE
@@ -222,7 +222,7 @@ SUBSYSTEM_DEF(dbcore)
* Will always report "Database disabled by configuration" if the DB is disabled.
*/
/datum/controller/subsystem/dbcore/proc/ErrorMsg()
if(!config.sql_enabled)
if(!GLOB.configuration.database.enabled)
return "Database disabled by configuration"
return last_error
@@ -492,7 +492,7 @@ SUBSYSTEM_DEF(dbcore)
/client/proc/reestablish_db_connection()
set category = "Debug"
set name = "Reestablish DB Connection"
if(!config.sql_enabled)
if(!GLOB.configuration.database.enabled)
to_chat(usr, "<span class='warning'>The Database is not enabled in the server configuration!</span>")
return
+14 -10
View File
@@ -7,7 +7,7 @@ SUBSYSTEM_DEF(discord)
var/last_administration_ping = 0
/datum/controller/subsystem/discord/Initialize(start_timeofday)
if(config.discord_webhooks_enabled)
if(GLOB.configuration.discord.webhooks_enabled)
enabled = TRUE
return ..()
@@ -18,11 +18,11 @@ SUBSYSTEM_DEF(discord)
var/list/webhook_urls
switch(destination)
if(DISCORD_WEBHOOK_ADMIN)
webhook_urls = config.discord_admin_webhook_urls
webhook_urls = GLOB.configuration.discord.admin_webhook_urls
if(DISCORD_WEBHOOK_PRIMARY)
webhook_urls = config.discord_main_webhook_urls
webhook_urls = GLOB.configuration.discord.main_webhook_urls
if(DISCORD_WEBHOOK_MENTOR)
webhook_urls = config.discord_mentor_webhook_urls
webhook_urls = GLOB.configuration.discord.mentor_webhook_urls
var/datum/discord_webhook_payload/dwp = new()
dwp.webhook_content = content
@@ -36,14 +36,18 @@ SUBSYSTEM_DEF(discord)
var/list/webhook_urls
switch(destination)
if(DISCORD_WEBHOOK_ADMIN)
webhook_urls = config.discord_admin_webhook_urls
webhook_urls = GLOB.configuration.discord.admin_webhook_urls
if(DISCORD_WEBHOOK_PRIMARY)
webhook_urls = config.discord_main_webhook_urls
webhook_urls = GLOB.configuration.discord.main_webhook_urls
if(DISCORD_WEBHOOK_MENTOR)
webhook_urls = GLOB.configuration.discord.mentor_webhook_urls
for(var/url in webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
// This one is for sending messages to the admin channel if no admins are active, complete with a ping to the game admins role
/datum/controller/subsystem/discord/proc/send2discord_simple_noadmins(content, check_send_always = FALSE)
if(!enabled)
return
// Setup some stuff
var/alerttext
var/list/admincounter = staff_countup(R_BAN)
@@ -57,7 +61,7 @@ SUBSYSTEM_DEF(discord)
else
alerttext = " | **NO ADMINS ONLINE**"
else
if(check_send_always && config.discord_forward_all_ahelps)
if(check_send_always && GLOB.configuration.discord.forward_all_ahelps)
// If we are here, there are admins online. We want to forward everything, but obviously dont want to add a ping, so we do this
add_ping = FALSE
else
@@ -68,17 +72,17 @@ SUBSYSTEM_DEF(discord)
var/datum/discord_webhook_payload/dwp = new()
dwp.webhook_content = message
for(var/url in config.discord_admin_webhook_urls)
for(var/url in GLOB.configuration.discord.admin_webhook_urls)
SShttp.create_async_request(RUSTG_HTTP_METHOD_POST, url, dwp.serialize2json(), list("content-type" = "application/json"))
// Helper to make administrator ping easier
/datum/controller/subsystem/discord/proc/handle_administrator_ping()
// Check if a role is even set
if(config.discord_admin_role_id)
if(GLOB.configuration.discord.admin_role_id)
if(last_administration_ping > world.time)
return "*(Role pinged recently)*"
last_administration_ping = world.time + 60 SECONDS
return "<@&[config.discord_admin_role_id]>"
return "<@&[GLOB.configuration.discord.admin_role_id]>"
return ""
+1 -1
View File
@@ -166,7 +166,7 @@ SUBSYSTEM_DEF(ghost_spawns)
if(role_text)
if(jobban_isbanned(M, role_text) || jobban_isbanned(M, ROLE_SYNDICATE))
return
if(config.use_exp_restrictions && min_hours)
if(GLOB.configuration.jobs.enable_exp_restrictions && min_hours)
if(M.client.get_exp_type_num(EXP_TYPE_LIVING) < min_hours * 60)
return
if(check_antaghud && cannotPossess(M))
+1 -1
View File
@@ -5,7 +5,7 @@ SUBSYSTEM_DEF(holiday)
var/list/holidays
/datum/controller/subsystem/holiday/Initialize(start_timeofday)
if(!config.allow_holidays)
if(!GLOB.configuration.general.allow_holidays)
return ..() //Holiday stuff was not enabled in the config!
var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year
+22 -32
View File
@@ -20,12 +20,12 @@ SUBSYSTEM_DEF(jobs)
/datum/controller/subsystem/jobs/Initialize(timeofday)
if(!occupations.len)
SetupOccupations()
LoadJobs("config/jobs.txt")
LoadJobs(FALSE)
return ..()
// Only fires every 5 minutes
/datum/controller/subsystem/jobs/fire()
if(!SSdbcore.IsConnected() || !config.use_exp_tracking)
if(!SSdbcore.IsConnected() || !GLOB.configuration.jobs.enable_exp_tracking)
return
batch_update_player_exp(announce = FALSE) // Set this to true if you ever want to inform players about their EXP gains
@@ -242,8 +242,8 @@ SUBSYSTEM_DEF(jobs)
/datum/controller/subsystem/jobs/proc/FillAIPosition()
if(config && !config.allow_ai)
return 0
if(!GLOB.configuration.jobs.allow_ai)
return FALSE
var/ai_selected = 0
var/datum/job/job = GetJob("AI")
@@ -514,39 +514,29 @@ SUBSYSTEM_DEF(jobs)
/datum/controller/subsystem/jobs/proc/LoadJobs(jobsfile) //ran during round setup, reads info from jobs.txt -- Urist
if(!config.load_jobs_from_txt)
return 0
/datum/controller/subsystem/jobs/proc/LoadJobs(highpop = FALSE) //ran during round setup, reads info from jobs list
if(!GLOB.configuration.jobs.enable_job_amount_overrides)
return FALSE
var/list/jobEntries = file2list(jobsfile)
var/list/joblist = list()
for(var/job in jobEntries)
if(!job)
if(highpop)
joblist = GLOB.configuration.jobs.highpop_job_map.Copy()
else
joblist = GLOB.configuration.jobs.lowpop_job_map.Copy()
for(var/job in joblist)
// Key: name | Value: Amount
var/datum/job/J = GetJob(job)
if(!J)
continue
J.total_positions = text2num(joblist[job])
J.spawn_positions = text2num(joblist[job])
job = trim(job)
if(!length(job))
continue
if(job == "AI" || job == "Cyborg") //I dont like this here but it will do for now
J.total_positions = 0
var/pos = findtext(job, "=")
var/name = null
var/value = null
if(pos)
name = copytext(job, 1, pos)
value = copytext(job, pos + 1)
else
continue
if(name && value)
var/datum/job/J = GetJob(name)
if(!J) continue
J.total_positions = text2num(value)
J.spawn_positions = text2num(value)
if(name == "AI" || name == "Cyborg")//I dont like this here but it will do for now
J.total_positions = 0
return 1
return TRUE
/datum/controller/subsystem/jobs/proc/HandleFeedbackGathering()
+1 -1
View File
@@ -13,7 +13,7 @@ SUBSYSTEM_DEF(lighting)
/datum/controller/subsystem/lighting/Initialize(timeofday)
if(!initialized)
if(config.starlight)
if(GLOB.configuration.general.starlight)
for(var/I in GLOB.all_areas)
var/area/A = I
if(A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
+9 -9
View File
@@ -40,11 +40,11 @@ SUBSYSTEM_DEF(mapping)
loadLavaland()
// Pick a random away mission.
if(!config.disable_away_missions)
if(GLOB.configuration.gateway.enable_away_mission)
load_away_mission()
// Seed space ruins
if(!config.disable_space_ruins)
if(GLOB.configuration.ruins.enable_space_ruins)
handleRuins()
// Makes a blank space level for the sake of randomness
@@ -57,12 +57,12 @@ SUBSYSTEM_DEF(mapping)
// Spawn Lavaland ruins and rivers.
log_startup_progress("Populating lavaland...")
var/lavaland_setup_timer = start_watch()
seedRuins(list(level_name_to_num(MINING)), config.lavaland_budget, /area/lavaland/surface/outdoors/unexplored, GLOB.lava_ruins_templates)
seedRuins(list(level_name_to_num(MINING)), GLOB.configuration.ruins.lavaland_ruin_budget, /area/lavaland/surface/outdoors/unexplored, GLOB.lava_ruins_templates)
spawn_rivers(list(level_name_to_num(MINING)))
log_startup_progress("Successfully populated lavaland in [stop_watch(lavaland_setup_timer)]s.")
// Now we make a list of areas for teleport locs
// TOOD: Make these locs into lists on the SS itself, not globs
// AA TODO: Make these locs into lists on the SS itself, not globs
for(var/area/AR in world)
if(AR.no_teleportlocs)
continue
@@ -84,8 +84,8 @@ SUBSYSTEM_DEF(mapping)
GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs)
// World name
if(config && config.server_name)
world.name = "[config.server_name]: [station_name()]"
if(GLOB.configuration.general.server_name)
world.name = "[GLOB.configuration.general.server_name]: [station_name()]"
else
world.name = station_name()
@@ -96,7 +96,7 @@ SUBSYSTEM_DEF(mapping)
// load in extra levels of space ruins
var/load_zlevels_timer = start_watch()
log_startup_progress("Creating random space levels...")
var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max)
var/num_extra_space = rand(GLOB.configuration.ruins.extra_levels_min, GLOB.configuration.ruins.extra_levels_max)
for(var/i in 1 to num_extra_space)
GLOB.space_manager.add_new_zlevel("Ruin Area #[i]", linkage = CROSSLINKED, traits = list(REACHABLE, SPAWN_RUINS))
log_startup_progress("Loaded random space levels in [stop_watch(load_zlevels_timer)]s.")
@@ -230,11 +230,11 @@ SUBSYSTEM_DEF(mapping)
if(length(GLOB.awaydestinations))
return
if(GLOB.potentialRandomZlevels && length(GLOB.potentialRandomZlevels))
if(length(GLOB.configuration.gateway.enabled_away_missions))
var/watch = start_watch()
log_startup_progress("Loading away mission...")
var/map = pick(GLOB.potentialRandomZlevels)
var/map = pick(GLOB.configuration.gateway.enabled_away_missions)
var/file = file(map)
if(isfile(file))
var/zlev = GLOB.space_manager.add_new_zlevel(AWAY_MISSION, linkage = UNAFFECTED, traits = list(AWAY_LEVEL,BLOCK_TELEPORT))
+8 -8
View File
@@ -4,15 +4,15 @@ SUBSYSTEM_DEF(medals)
var/hub_enabled = FALSE
/datum/controller/subsystem/medals/Initialize(timeofday)
if(config.medal_hub_address && config.medal_hub_password)
if(GLOB.configuration.system.medal_hub_address && GLOB.configuration.system.medal_hub_password)
hub_enabled = TRUE
..()
return ..()
/datum/controller/subsystem/medals/proc/UnlockMedal(medal, client/player)
set waitfor = FALSE
if(!medal || !hub_enabled)
return
if(isnull(world.SetMedal(medal, player, config.medal_hub_address, config.medal_hub_password)))
if(isnull(world.SetMedal(medal, player, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)))
hub_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to award medal [medal] to player [player.ckey].")
message_admins("Error! Failed to contact hub to award [medal] medal to [player.ckey]!")
@@ -35,7 +35,7 @@ SUBSYSTEM_DEF(medals)
var/newscoreparam = list2params(oldscore)
if(isnull(world.SetScores(player.ckey, newscoreparam, config.medal_hub_address, config.medal_hub_password)))
if(isnull(world.SetScores(player.ckey, newscoreparam, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)))
hub_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to set score. Score [score] for player [player.ckey].")
message_admins("Error! Failed to contact hub to set [score] score for [player.ckey]!")
@@ -44,7 +44,7 @@ SUBSYSTEM_DEF(medals)
if(!score || !hub_enabled)
return
var/scoreget = world.GetScores(player.ckey, score, config.medal_hub_address, config.medal_hub_password)
var/scoreget = world.GetScores(player.ckey, score, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)
if(isnull(scoreget))
hub_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to get score. Score [score] for player [player.ckey].")
@@ -58,7 +58,7 @@ SUBSYSTEM_DEF(medals)
if(!medal || !hub_enabled)
return
if(isnull(world.GetMedal(medal, player, config.medal_hub_address, config.medal_hub_password)))
if(isnull(world.GetMedal(medal, player, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)))
hub_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to get medal [medal] for player [player.ckey]")
message_admins("Error! Failed to contact hub to get [medal] medal for [player.ckey]!")
@@ -68,7 +68,7 @@ SUBSYSTEM_DEF(medals)
/datum/controller/subsystem/medals/proc/LockMedal(medal, client/player)
if(!player || !medal || !hub_enabled)
return
var/result = world.ClearMedal(medal, player, config.medal_hub_address, config.medal_hub_password)
var/result = world.ClearMedal(medal, player, GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)
switch(result)
if(null)
hub_enabled = FALSE
@@ -81,6 +81,6 @@ SUBSYSTEM_DEF(medals)
/datum/controller/subsystem/medals/proc/ClearScore(client/player)
if(isnull(world.SetScores(player.ckey, "", config.medal_hub_address, config.medal_hub_password)))
if(isnull(world.SetScores(player.ckey, "", GLOB.configuration.system.medal_hub_address, GLOB.configuration.system.medal_hub_password)))
log_game("MEDAL ERROR: Could not contact hub to clear scores for [player.ckey].")
message_admins("Error! Failed to contact hub to clear scores for [player.ckey]!")
+2 -2
View File
@@ -14,9 +14,9 @@ SUBSYSTEM_DEF(nightshift)
var/high_security_mode = FALSE
/datum/controller/subsystem/nightshift/Initialize()
if(!config.enable_night_shifts)
if(!GLOB.configuration.general.enable_night_shifts)
can_fire = FALSE
if(config.randomize_shift_time)
if(GLOB.configuration.general.randomise_shift_time)
GLOB.gametime_offset = rand(0, 23) HOURS
return ..()
+2 -2
View File
@@ -13,7 +13,7 @@ SUBSYSTEM_DEF(profiler)
..("F:[round(fetch_cost, 1)]ms | W:[round(write_cost, 1)]ms")
/datum/controller/subsystem/profiler/Initialize()
if(!config.auto_profile)
if(!GLOB.configuration.general.enable_auto_profiler)
StopProfiling() //Stop the early start profiler if we dont want it on in the config
flags |= SS_NO_FIRE
return ..()
@@ -22,7 +22,7 @@ SUBSYSTEM_DEF(profiler)
DumpFile()
/datum/controller/subsystem/profiler/Shutdown()
if(config.auto_profile)
if(GLOB.configuration.general.enable_auto_profiler)
DumpFile()
return ..()
+4 -3
View File
@@ -1,5 +1,4 @@
#define CALL_SHUTTLE_REASON_LENGTH 12
SUBSYSTEM_DEF(shuttle)
name = "Shuttle"
wait = 10
@@ -42,6 +41,8 @@ SUBSYSTEM_DEF(shuttle)
var/sold_atoms = ""
var/list/hidden_shuttle_turfs = list() //all turfs hidden from navigation computers associated with a list containing the image hiding them and the type of the turf they are pretending to be
var/list/hidden_shuttle_turf_images = list() //only the images from the above list
/// Default refuel delay
var/refuel_delay = 20 MINUTES
/datum/controller/subsystem/shuttle/Initialize(start_timeofday)
ordernum = rand(1,9000)
@@ -97,7 +98,7 @@ SUBSYSTEM_DEF(shuttle)
/datum/controller/subsystem/shuttle/proc/secondsToRefuel()
var/elapsed = world.time - SSticker.round_start_time
var/remaining = round((config.shuttle_refuel_delay - elapsed) / 10)
var/remaining = round((refuel_delay - elapsed) / 10)
return remaining > 0 ? remaining : 0
/datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason)
@@ -115,7 +116,7 @@ SUBSYSTEM_DEF(shuttle)
emergency = backup_shuttle
if(secondsToRefuel())
to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.")
to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - SSticker.round_start_time) - refuel_delay)/600))] minutes before trying again.")
return
switch(emergency.mode)
+1 -1
View File
@@ -6,7 +6,7 @@ SUBSYSTEM_DEF(statistics)
/datum/controller/subsystem/statistics/Initialize(start_timeofday)
if(!config.sql_enabled)
if(!SSdbcore.IsConnected())
flags |= SS_NO_FIRE // Disable firing if SQL is disabled
return ..()
+15 -11
View File
@@ -10,7 +10,7 @@ SUBSYSTEM_DEF(ticker)
/// Time the world started, relative to world.time
var/round_start_time = 0
/// Default timeout for if world.Reboot() doesnt have a time specified
var/const/restart_timeout = 600
var/const/restart_timeout = 75 SECONDS
/// Current status of the game. See code\__DEFINES\game.dm
var/current_state = GAME_STATE_STARTUP
/// Do we want to force-start as soon as we can
@@ -79,9 +79,9 @@ SUBSYSTEM_DEF(ticker)
switch(current_state)
if(GAME_STATE_STARTUP)
// This is ran as soon as the MC starts firing, and should only run ONCE, unless startup fails
round_start_time = world.time + (config.pregame_timestart * 10)
round_start_time = world.time + (GLOB.configuration.general.lobby_time SECONDS)
to_chat(world, "<B><span class='darkmblue'>Welcome to the pre-game lobby!</span></B>")
to_chat(world, "Please, setup your character and select ready. Game will start in [config.pregame_timestart] seconds")
to_chat(world, "Please, setup your character and select ready. Game will start in [GLOB.configuration.general.lobby_time] seconds")
current_state = GAME_STATE_PREGAME
fire() // TG says this is a good idea
for(var/mob/new_player/N in GLOB.player_list)
@@ -114,10 +114,10 @@ SUBSYSTEM_DEF(ticker)
if(world.time > next_autotransfer)
SSvote.autotransfer()
next_autotransfer = world.time + config.vote_autotransfer_interval
next_autotransfer = world.time + GLOB.configuration.vote.autotransfer_interval_time
var/game_finished = SSshuttle.emergency.mode >= SHUTTLE_ENDGAME || mode.station_was_nuked
if(config.continuous_rounds)
if(GLOB.configuration.gamemode.disable_certain_round_early_end)
mode.check_finished() // some modes contain var-changing code in here, so call even if we don't uses result
else
game_finished |= mode.check_finished()
@@ -129,6 +129,8 @@ SUBSYSTEM_DEF(ticker)
auto_toggle_ooc(TRUE) // Turn it on
declare_completion()
addtimer(CALLBACK(src, .proc/call_reboot), 5 SECONDS)
if(GLOB.configuration.vote.enable_map_voting)
SSvote.initiate_vote("map", "the server", TRUE) // Start a map vote. Timing is a little tight here but we should be good.
/datum/controller/subsystem/ticker/proc/call_reboot()
if(mode.station_was_nuked)
@@ -147,7 +149,7 @@ SUBSYSTEM_DEF(ticker)
var/list/datum/game_mode/runnable_modes
if(GLOB.master_mode == "random" || GLOB.master_mode == "secret")
runnable_modes = config.get_runnable_modes()
runnable_modes = GLOB.configuration.gamemode.get_runnable_modes()
if(!length(runnable_modes))
to_chat(world, "<B>Unable to choose playable game mode.</B> Reverting to pre-game lobby.")
force_start = FALSE
@@ -155,9 +157,9 @@ SUBSYSTEM_DEF(ticker)
Master.SetRunLevel(RUNLEVEL_LOBBY)
return FALSE
if(GLOB.secret_force_mode != "secret")
var/datum/game_mode/M = config.pick_mode(GLOB.secret_force_mode)
var/datum/game_mode/M = GLOB.configuration.gamemode.pick_mode(GLOB.secret_force_mode)
if(M.can_start())
mode = config.pick_mode(GLOB.secret_force_mode)
mode = GLOB.configuration.gamemode.pick_mode(GLOB.secret_force_mode)
SSjobs.ResetOccupations()
if(!mode)
mode = pickweight(runnable_modes)
@@ -165,7 +167,7 @@ SUBSYSTEM_DEF(ticker)
var/mtype = mode.type
mode = new mtype
else
mode = config.pick_mode(GLOB.master_mode)
mode = GLOB.configuration.gamemode.pick_mode(GLOB.master_mode)
if(!mode.can_start())
to_chat(world, "<B>Unable to start [mode.name].</B> Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby.")
@@ -267,7 +269,7 @@ SUBSYSTEM_DEF(ticker)
round_start_time = world.time
// Sets the auto shuttle vote to happen after the config duration
next_autotransfer = world.time + config.vote_autotransfer_initial
next_autotransfer = world.time + GLOB.configuration.vote.autotransfer_initial_time
for(var/mob/new_player/N in GLOB.mob_list)
if(N.client)
@@ -279,10 +281,12 @@ SUBSYSTEM_DEF(ticker)
if(playercount >= highpop_trigger)
log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - loading highpop job config")
SSjobs.LoadJobs("config/jobs_highpop.txt")
SSjobs.LoadJobs(TRUE)
else
log_debug("Playercount: [playercount] versus trigger: [highpop_trigger] - keeping standard job config")
SSnightshift.check_nightshift()
#ifdef UNIT_TESTS
RunUnitTests()
#endif
@@ -214,14 +214,18 @@ SUBSYSTEM_DEF(tickets)
"Already Resolved" = "The problem has been resolved already.",
"Mentorhelp" = "Please redirect your question to Mentorhelp, as they are better experienced with these types of questions.",
"Happens Again" = "Thanks, let us know if it continues to happen.",
"Github Issue Report" = "To report a bug, please go to our <a href='[config.githuburl]'>Github page</a>. Then go to 'Issues'. Then 'New Issue'. Then fill out the report form. If the report would reveal current-round information, file it after the round ends.",
"Clear Cache" = "To fix a blank screen, go to the 'Special Verbs' tab and press 'Reload UI Resources'. If that fails, clear your BYOND cache (instructions provided with 'Reload UI Resources'). If that still fails, please adminhelp again, stating you have already done the following." ,
"IC Issue" = "This is an In Character (IC) issue and will not be handled by admins. You could speak to Security, Internal Affairs, a Departmental Head, Nanotrasen Representetive, or any other relevant authority currently on station.",
"Reject" = "Reject",
"Man Up" = "Man Up",
"Appeal on the Forums" = "Appealing a ban must occur on the forums. Privately messaging, or adminhelping about your ban will not resolve it. To appeal your ban, please head to <a href='[config.banappeals]'>[config.banappeals]</a>"
)
if(GLOB.configuration.url.banappeals_url)
response_phrases["Appeal on the Forums"] = "Appealing a ban must occur on the forums. Privately messaging, or adminhelping about your ban will not resolve it. To appeal your ban, please head to <a href='[GLOB.configuration.url.banappeals_url]'>[GLOB.configuration.url.banappeals_url]</a>"
if(GLOB.configuration.url.github_url)
response_phrases["Github Issue Report"] = "To report a bug, please go to our <a href='[GLOB.configuration.url.github_url]'>Github page</a>. Then go to 'Issues'. Then 'New Issue'. Then fill out the report form. If the report would reveal current-round information, file it after the round ends."
var/sorted_responses = list()
for(var/key in response_phrases) //build a new list based on the short descriptive keys of the master list so we can send this as the input instead of the full paragraphs to the admin choosing which autoresponse
sorted_responses += key
+28 -28
View File
@@ -27,7 +27,7 @@ SUBSYSTEM_DEF(vote)
// Calculate how much time is remaining by comparing current time, to time of vote start,
// plus vote duration
time_remaining = round((started_time + config.vote_period - world.time)/10)
time_remaining = round((started_time + GLOB.configuration.vote.vote_time - world.time)/10)
if(time_remaining < 0)
result()
@@ -53,9 +53,9 @@ SUBSYSTEM_DEF(vote)
voting.Cut()
current_votes.Cut()
if(auto_muted && !config.ooc_allowed && !(config.auto_toggle_ooc_during_round && SSticker.current_state == GAME_STATE_PLAYING))
if(auto_muted && !GLOB.ooc_enabled && !(GLOB.configuration.general.auto_disable_ooc && SSticker.current_state == GAME_STATE_PLAYING))
auto_muted = 0
config.ooc_allowed = !( config.ooc_allowed )
GLOB.ooc_enabled = TRUE
to_chat(world, "<b>The OOC channel has been automatically enabled due to vote end.</b>")
log_admin("OOC was toggled automatically due to vote end.")
message_admins("OOC has been toggled on automatically.")
@@ -83,7 +83,7 @@ SUBSYSTEM_DEF(vote)
choices -= sorted_highest
choices = sorted_choices
//default-vote for everyone who didn't vote
if(!config.vote_no_default && choices.len)
if(!GLOB.configuration.vote.disable_default_vote && choices.len)
var/non_voters = (GLOB.clients.len - total_votes)
if(non_voters > 0)
if(mode == "restart")
@@ -196,7 +196,7 @@ SUBSYSTEM_DEF(vote)
/datum/controller/subsystem/vote/proc/submit_vote(ckey, vote)
if(mode)
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
if(GLOB.configuration.vote.prevent_dead_voting && usr.stat == DEAD && !usr.client.holder)
return 0
if(current_votes[ckey])
choices[choices[current_votes[ckey]]]--
@@ -210,7 +210,7 @@ SUBSYSTEM_DEF(vote)
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key, code_invoked = FALSE)
if(!mode)
if(started_time != null && !check_rights(R_ADMIN))
var/next_allowed_time = (started_time + config.vote_delay)
var/next_allowed_time = (started_time + GLOB.configuration.vote.vote_delay)
if(next_allowed_time > world.time)
return 0
@@ -221,7 +221,7 @@ SUBSYSTEM_DEF(vote)
if("gamemode")
if(SSticker.current_state >= 2)
return 0
choices.Add(config.votable_modes)
choices.Add(GLOB.configuration.gamemode.votable_modes)
if("crew_transfer")
if(check_rights(R_ADMIN|R_MOD))
if(SSticker.current_state <= 2)
@@ -264,33 +264,33 @@ SUBSYSTEM_DEF(vote)
log_vote(text)
to_chat(world, {"<font color='purple'><b>[text]</b>
<a href='?src=[UID()];vote=open'>Click here or type vote to place your vote.</a>
You have [config.vote_period/10] seconds to vote.</font>"})
You have [GLOB.configuration.vote.vote_time / 10] seconds to vote.</font>"})
switch(vote_type)
if("crew_transfer", "gamemode", "custom", "map")
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
if(mode == "gamemode" && SSticker.ticker_going)
SSticker.ticker_going = FALSE
to_chat(world, "<font color='red'><b>Round start has been delayed.</b></font>")
if(mode == "crew_transfer" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
if(mode == "crew_transfer" && GLOB.ooc_enabled)
auto_muted = TRUE
GLOB.ooc_enabled = FALSE
to_chat(world, "<b>The OOC channel has been automatically disabled due to a crew transfer vote.</b>")
log_admin("OOC was toggled automatically due to crew_transfer vote.")
message_admins("OOC has been toggled off automatically.")
if(mode == "gamemode" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
if(mode == "gamemode" && GLOB.ooc_enabled)
auto_muted = TRUE
GLOB.ooc_enabled = FALSE
to_chat(world, "<b>The OOC channel has been automatically disabled due to the gamemode vote.</b>")
log_admin("OOC was toggled automatically due to gamemode vote.")
message_admins("OOC has been toggled off automatically.")
if(mode == "custom" && config.ooc_allowed)
auto_muted = 1
config.ooc_allowed = !( config.ooc_allowed )
if(mode == "custom" && GLOB.ooc_enabled)
auto_muted = TRUE
GLOB.ooc_enabled = FALSE
to_chat(world, "<b>The OOC channel has been automatically disabled due to a custom vote.</b>")
log_admin("OOC was toggled automatically due to custom vote.")
message_admins("OOC has been toggled off automatically.")
time_remaining = round(config.vote_period/10)
time_remaining = round(GLOB.configuration.vote.vote_time / 10)
return 1
return 0
@@ -315,25 +315,25 @@ SUBSYSTEM_DEF(vote)
else
dat += "<div id='vote_div'><h2>Start a vote:</h2><hr><ul><li>"
//restart
if(admin || config.allow_vote_restart)
if(admin || GLOB.configuration.vote.allow_restart_votes)
dat += "<a href='?src=[UID()];vote=restart'>Restart</a>"
else
dat += "<font color='grey'>Restart (Disallowed)</font>"
dat += "</li><li>"
if(admin || config.allow_vote_restart)
if(admin || GLOB.configuration.vote.allow_restart_votes)
dat += "<a href='?src=[UID()];vote=crew_transfer'>Crew Transfer</a>"
else
dat += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(admin)
dat += "\t(<a href='?src=[UID()];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
dat += "\t(<a href='?src=[UID()];vote=toggle_restart'>[GLOB.configuration.vote.allow_restart_votes ? "Allowed" : "Disallowed"]</a>)"
dat += "</li><li>"
//gamemode
if(admin || config.allow_vote_mode)
if(admin || GLOB.configuration.vote.allow_mode_votes)
dat += "<a href='?src=[UID()];vote=gamemode'>GameMode</a>"
else
dat += "<font color='grey'>GameMode (Disallowed)</font>"
if(admin)
dat += "\t(<a href='?src=[UID()];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
dat += "\t(<a href='?src=[UID()];vote=toggle_gamemode'>[GLOB.configuration.vote.allow_mode_votes ? "Allowed" : "Disallowed"]</a>)"
dat += "</li><li>"
if(admin)
@@ -391,21 +391,21 @@ SUBSYSTEM_DEF(vote)
reset()
if("toggle_restart")
if(admin)
config.allow_vote_restart = !config.allow_vote_restart
GLOB.configuration.vote.allow_restart_votes = !GLOB.configuration.vote.allow_restart_votes
if("toggle_gamemode")
if(admin)
config.allow_vote_mode = !config.allow_vote_mode
GLOB.configuration.vote.allow_mode_votes = !GLOB.configuration.vote.allow_mode_votes
if("restart")
if(config.allow_vote_restart || admin)
if(GLOB.configuration.vote.allow_restart_votes || admin)
initiate_vote("restart",usr.key)
if("gamemode")
if(config.allow_vote_mode || admin)
if(GLOB.configuration.vote.allow_mode_votes || admin)
initiate_vote("gamemode",usr.key)
if("map")
if(admin)
initiate_vote("map", usr.key)
if("crew_transfer")
if(config.allow_vote_restart || admin)
if(GLOB.configuration.vote.allow_restart_votes || admin)
initiate_vote("crew_transfer",usr.key)
if("custom")
if(admin)
+1 -1
View File
@@ -28,7 +28,7 @@
return
switch(controller)
if("Configuration")
debug_variables(config)
debug_variables(GLOB.configuration)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Debug Config")
if("pAI")
debug_variables(GLOB.paiController)
+9 -9
View File
@@ -5,6 +5,8 @@
var/mappath = null
var/mapfile = null
var/loaded = 0 // Times loaded this round
/// Do we exclude this from CI checks? If so, set this to the templates pathtype itself to avoid it getting passed down
var/ci_exclude = null // DO NOT SET THIS IF YOU DO NOT KNOW WHAT YOU ARE DOING
/datum/map_template/New(path = null, map = null, rename = null)
if(path)
@@ -110,19 +112,16 @@
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
GLOB.map_templates[T.name] = T
if(!config.disable_space_ruins) // so we don't unnecessarily clutter start-up
if(GLOB.configuration.ruins.enable_space_ruins) // so we don't unnecessarily clutter start-up
preloadRuinTemplates()
preloadShelterTemplates()
preloadShuttleTemplates()
/proc/preloadRuinTemplates()
// Still supporting bans by filename
var/list/banned
if(fexists("config/spaceRuinBlacklist.txt"))
banned = generateMapList("config/spaceRuinBlacklist.txt")
else
banned = generateMapList("config/example/spaceRuinBlacklist.txt")
banned += generateMapList("config/lavaRuinBlacklist.txt")
// Merge the active lists together
var/list/space_ruins = GLOB.configuration.ruins.active_space_ruins.Copy()
var/list/lava_ruins = GLOB.configuration.ruins.active_lava_ruins.Copy()
var/list/all_ruins = space_ruins | lava_ruins
for(var/item in subtypesof(/datum/map_template/ruin))
var/datum/map_template/ruin/ruin_type = item
@@ -131,7 +130,8 @@
continue
var/datum/map_template/ruin/R = new ruin_type()
if(banned.Find(R.mappath))
// If not in the active list, skip it
if(!(R.mappath in all_ruins))
continue
GLOB.map_templates[R.name] = R
+3 -3
View File
@@ -93,10 +93,10 @@ GLOBAL_PROTECT(revision_info) // Dont mess with this
msg += "<b>Round ID:</b> [GLOB.round_id ? GLOB.round_id : "NULL"]"
// Commit info
if(GLOB.revision_info.commit_hash && GLOB.revision_info.commit_date)
msg += "<b>Server Commit:</b> <a href='[config.githuburl]/commit/[GLOB.revision_info.commit_hash]'>[GLOB.revision_info.commit_hash]</a> (Date: [GLOB.revision_info.commit_date])"
if(GLOB.revision_info.commit_hash && GLOB.revision_info.commit_date && GLOB.configuration.url.github_url)
msg += "<b>Server Commit:</b> <a href='[GLOB.configuration.url.github_url]/commit/[GLOB.revision_info.commit_hash]'>[GLOB.revision_info.commit_hash]</a> (Date: [GLOB.revision_info.commit_date])"
if(GLOB.revision_info.origin_commit && (GLOB.revision_info.commit_hash != GLOB.revision_info.origin_commit))
msg += "<b>Origin Commit:</b> <a href='[config.githuburl]/commit/[GLOB.revision_info.origin_commit]'>[GLOB.revision_info.origin_commit]</a>"
msg += "<b>Origin Commit:</b> <a href='[GLOB.configuration.url.github_url]/commit/[GLOB.revision_info.origin_commit]'>[GLOB.revision_info.origin_commit]</a>"
else
msg += "<b>Server Commit:</b> <i>Unable to determine</i>"
+3
View File
@@ -1,9 +1,11 @@
/datum/map_template/ruin/lavaland
prefix = "_maps/map_files/RandomRuins/LavaRuins/"
ci_exclude = /datum/map_template/ruin/lavaland
/datum/map_template/ruin/lavaland/biodome
cost = 5
allow_duplicates = FALSE
ci_exclude = /datum/map_template/ruin/lavaland/biodome // This is a parent holder, not a ruin itself
/datum/map_template/ruin/lavaland/biodome/beach
name = "Biodome Beach"
@@ -71,6 +73,7 @@
/datum/map_template/ruin/lavaland/sin
cost = 10
allow_duplicates = FALSE
ci_exclude = /datum/map_template/ruin/lavaland/sin // This is a parent holder, not a ruin itself
/datum/map_template/ruin/lavaland/sin/envy
name = "Ruin of Envy"
+1
View File
@@ -2,6 +2,7 @@
/datum/map_template/ruin/space
prefix = "_maps/map_files/RandomRuins/SpaceRuins/"
cost = 1
ci_exclude = /datum/map_template/ruin/space
/datum/map_template/ruin/space/zoo
id = "zoo"
+4 -4
View File
@@ -25,13 +25,13 @@
if(istype(S,/obj/effect/proc_holder/spell/targeted/lichdom) && S != src)
return ..()
if(existence_stops_round_end)
config.continuous_rounds = 0
GLOB.configuration.gamemode.disable_certain_round_early_end = FALSE
return ..()
/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets, mob/user = usr)
if(!config.continuous_rounds)
existence_stops_round_end = 1
config.continuous_rounds = 1
if(!GLOB.configuration.gamemode.disable_certain_round_early_end)
existence_stops_round_end = TRUE
GLOB.configuration.gamemode.disable_certain_round_early_end = TRUE
for(var/mob/M in targets)
var/list/hand_items = list()
+1 -1
View File
@@ -102,7 +102,7 @@
else if(dynamic_lighting != DYNAMIC_LIGHTING_IFSTARLIGHT)
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
if(dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
dynamic_lighting = config.starlight ? DYNAMIC_LIGHTING_ENABLED : DYNAMIC_LIGHTING_DISABLED
dynamic_lighting = GLOB.configuration.general.starlight ? DYNAMIC_LIGHTING_ENABLED : DYNAMIC_LIGHTING_DISABLED
. = ..()
@@ -15,7 +15,7 @@
/datum/game_mode/traitor/autotraitor/pre_setup()
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
possible_traitors = get_players_for_role(ROLE_TRAITOR)
@@ -35,7 +35,7 @@
if(!possible_traitors.len)
return 0
if(config.traitor_scaling)
if(GLOB.configuration.gamemode.traitor_scaling)
num_traitors = max_traitors - 1 + prob(traitor_prob)
log_game("Number of traitors: [num_traitors]")
message_admins("Players counted: [num_players] Number of traitors chosen: [num_traitors]")
+1 -1
View File
@@ -101,7 +101,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
to_chat(blob.current, "<b>Find a good location to spawn the core and then take control and overwhelm the station!</b>")
to_chat(blob.current, "<b>When you have found a location, wait until you spawn; this will happen automatically and you cannot speed up the process.</b>")
to_chat(blob.current, "<b>If you go outside of the station level, or in space, then you will die; make sure your location has lots of ground to cover.</b>")
to_chat(blob.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Blob)</span>")
to_chat(blob.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Blob)</span>")
SEND_SOUND(blob.current, sound('sound/magic/mutate.ogg'))
return
+2 -2
View File
@@ -41,7 +41,7 @@ GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","E
to_chat(world, "<B>There are alien changelings on the station. Do not let the changelings succeed!</B>")
/datum/game_mode/changeling/pre_setup()
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING)
@@ -147,7 +147,7 @@ GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","E
for(var/datum/objective/objective in changeling.objectives)
to_chat(changeling.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
obj_count++
to_chat(changeling.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Changeling)</span>")
to_chat(changeling.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Changeling)</span>")
return
/datum/game_mode/proc/remove_changeling(datum/mind/changeling_mind)
@@ -16,7 +16,7 @@
/datum/game_mode/traitor/changeling/pre_setup()
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING)
+3 -3
View File
@@ -62,7 +62,7 @@ GLOBAL_LIST_EMPTY(all_cults)
to_chat(world, "<B>Some crewmembers are attempting to start a cult!<BR>\nCultists - complete your objectives. Convert crewmembers to your cause by using the offer rune. Remember - there is no you, there is only the cult.<BR>\nPersonnel - Do not let the cult succeed in its mission. Brainwashing them with holy water reverts them to whatever CentComm-allowed faith they had.</B>")
/datum/game_mode/cult/pre_setup()
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
var/list/cultists_possible = get_players_for_role(ROLE_CULTIST)
@@ -99,7 +99,7 @@ GLOBAL_LIST_EMPTY(all_cults)
add_cult_actions(cult_mind)
update_cult_icons_added(cult_mind)
cult_objs.study(cult_mind.current)
to_chat(cult_mind.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Cultist)</span>")
to_chat(cult_mind.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Cultist)</span>")
cult_threshold_check()
addtimer(CALLBACK(src, .proc/cult_threshold_check), 2 MINUTES) // Check again in 2 minutes for latejoiners
..()
@@ -167,7 +167,7 @@ GLOBAL_LIST_EMPTY(all_cults)
ascend(cult_mind.current)
check_cult_size()
cult_objs.study(cult_mind.current)
to_chat(cult_mind.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Cultist)</span>")
to_chat(cult_mind.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Cultist)</span>")
return TRUE
/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind, show_message = TRUE, remove_gear = FALSE)
+1 -1
View File
@@ -54,7 +54,7 @@
if((player.client)&&(player.ready))
playerC++
if(!config.enable_gamemode_player_limit || (playerC >= required_players))
if(!GLOB.configuration.gamemode.enable_gamemode_player_limit || (playerC >= required_players))
return 1
return 0
+1 -1
View File
@@ -181,7 +181,7 @@ GLOBAL_LIST_EMPTY(cortical_stacks) //Stacks for 'leave nobody behind' objective.
to_chat(raider.current, "<span class='notice'>Vox are cowardly and will flee from larger groups, but corner one or find them en masse and they are vicious.</span>")
to_chat(raider.current, "<span class='notice'>Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to turn on your nitrogen internals!</span>")
to_chat(raider.current, "<span class='notice'>Choose to accomplish your objectives by either raiding the crew and taking what you need, or by attempting to trade with them.</span>")
to_chat(raider.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Vox_Raider)</span>")
to_chat(raider.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Vox_Raider)</span>")
spawn(25)
show_objectives(raider)
@@ -158,7 +158,7 @@
to_chat(abductor.current, "<span class='notice'>You are an agent of [team_name]!</span>")
to_chat(abductor.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
to_chat(abductor.current, "<span class='notice'>Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve.</span>")
to_chat(abductor.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Abductor)</span>")
to_chat(abductor.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Abductor)</span>")
abductor.announce_objectives()
@@ -171,7 +171,7 @@
to_chat(abductor.current, "<span class='notice'>You are a scientist of [team_name]!</span>")
to_chat(abductor.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
to_chat(abductor.current, "<span class='notice'>Use your tool and ship consoles to support the agent and retrieve human specimens.</span>")
to_chat(abductor.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Abductor)</span>")
to_chat(abductor.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Abductor)</span>")
abductor.announce_objectives()
@@ -837,7 +837,7 @@
to_chat(src, "You are a brain slug that worms its way into the head of its victim. Use stealth, persuasion and your powers of mind control to keep you, your host and your eventual spawn safe and warm.")
to_chat(src, "Sugar nullifies your abilities, avoid it at all costs!")
to_chat(src, "You can speak to your fellow borers by prefixing your messages with ':bo'. Check out your Borer tab to see your abilities.")
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Cortical_Borer)</span>")
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Cortical_Borer)</span>")
/proc/create_borer_mind(key)
var/datum/mind/M = new /datum/mind(key)
@@ -112,7 +112,7 @@
to_chat(src, "1. Consume resources and replicate until there are no more resources left.")
to_chat(src, "2. Ensure that the station is fit for invasion at a later date, do not perform actions that would render it dangerous or inhospitable.")
to_chat(src, "3. Biological and sentient resources will be harvested at a later date, do not harm them.")
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Swarmer)</span>")
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Swarmer)</span>")
/mob/living/simple_animal/hostile/swarmer/New()
..()
@@ -343,7 +343,7 @@
to_chat(G, "You are capable of manifesting or recalling to your master with verbs in the Guardian tab. You will also find a verb to communicate with them privately there.")
to_chat(G, "While personally invincible, you will die if [user.real_name] does, and any damage dealt to you will have a portion passed on to them as you feed upon them to sustain yourself.")
to_chat(G, "[G.playstyle_string]")
to_chat(G, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Guardian)</span>")
to_chat(G, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Guardian)</span>")
G.faction = user.faction
var/color = pick(color_list)
@@ -26,7 +26,7 @@
player_mind.special_role = SPECIAL_ROLE_MORPH
SSticker.mode.traitors |= player_mind
to_chat(S, S.playstyle_string)
to_chat(S, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Morph)</span>")
to_chat(S, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Morph)</span>")
SEND_SOUND(S, sound('sound/magic/mutate.ogg'))
message_admins("[key_of_morph] has been made into morph by an event.")
log_game("[key_of_morph] was spawned as a morph by an event.")
@@ -168,7 +168,7 @@
to_chat(src, "<b>You are invincible and invisible to everyone but other ghosts. Most abilities will reveal you, rendering you vulnerable.</b>")
to_chat(src, "<b>To function, you are to drain the life essence from humans. This essence is a resource, as well as your health, and will power all of your abilities.</b>")
to_chat(src, "<b><i>You do not remember anything of your past lives, nor will you remember anything about this one after your death.</i></b>")
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Revenant)</span>")
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Revenant)</span>")
var/datum/objective/revenant/objective = new
objective.owner = mind
mind.objectives += objective
@@ -92,7 +92,7 @@
mind.objectives += fluffObjective
to_chat(src, "<B>Objective #[1]</B>: [objective.explanation_text]")
to_chat(src, "<B>Objective #[2]</B>: [fluffObjective.explanation_text]")
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Slaughter_Demon)</span>")
to_chat(src, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Slaughter_Demon)</span>")
/obj/effect/decal/cleanable/blood/innards
+1 -1
View File
@@ -250,7 +250,7 @@
for(var/datum/objective/objective in syndicate.objectives)
to_chat(syndicate.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
obj_count++
to_chat(syndicate.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Nuclear_Agent)</span>")
to_chat(syndicate.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Nuclear_Agent)</span>")
return
@@ -60,7 +60,7 @@
// No. of player - Min. Player to dec, divided by player per bonus, then multipled by TC per bonus. Rounded.
total_tc = CHALLENGE_TELECRYSTALS + round((((GLOB.player_list.len - CHALLENGE_MIN_PLAYERS)/CHALLENGE_SCALE_PLAYER) * CHALLENGE_SCALE_BONUS))
share_telecrystals()
config.shuttle_refuel_delay = CHALLENGE_SHUTTLE_DELAY
SSshuttle.refuel_delay = CHALLENGE_SHUTTLE_DELAY
qdel(src)
/obj/item/nuclear_challenge/proc/share_telecrystals()
+3 -3
View File
@@ -38,7 +38,7 @@
/datum/game_mode/revolution/pre_setup()
possible_revolutionaries = get_players_for_role(ROLE_REV)
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
@@ -110,7 +110,7 @@
to_chat(rev_mind.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
rev_mind.special_role = SPECIAL_ROLE_HEAD_REV
obj_count++
to_chat(rev_mind.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Revolution)</span>")
to_chat(rev_mind.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Revolution)</span>")
/////////////////////////////////////////////////////////////////////////////////
//This are equips the rev heads with their gear, and makes the clown not clumsy//
@@ -214,7 +214,7 @@
//Checks if the round is over//
///////////////////////////////
/datum/game_mode/revolution/check_finished()
if(config.continuous_rounds)
if(GLOB.configuration.gamemode.disable_certain_round_early_end)
if(finished != 0)
SSshuttle.emergencyNoEscape = 0
if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
+5 -5
View File
@@ -81,7 +81,7 @@ Made by Xhuis
to_chat(world, "<b>There are alien <span class='deadsay'>shadowlings</span> on the station. Crew: Kill the shadowlings before they can eat or enthrall the crew. Shadowlings: Enthrall the crew while remaining in hiding.</b>")
/datum/game_mode/shadowling/pre_setup()
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
var/list/datum/mind/possible_shadowlings = get_players_for_role(ROLE_SHADOWLING)
@@ -126,7 +126,7 @@ Made by Xhuis
to_chat(shadow.current, "<b>Currently, you are disguised as an employee aboard [world.name].</b>")
to_chat(shadow.current, "<b>In your limited state, you have two abilities: Hatch and Shadowling Hivemind (:8).</b>")
to_chat(shadow.current, "<b>Any other shadowlings are your allies. You must assist them as they shall assist you.</b>")
to_chat(shadow.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Shadowling)</span>")
to_chat(shadow.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Shadowling)</span>")
/datum/game_mode/proc/process_shadow_objectives(datum/mind/shadow_mind)
@@ -168,7 +168,7 @@ Made by Xhuis
to_chat(new_thrall_mind.current, "<span class='shadowling'>Your body has been irreversibly altered. The attentive can see this - you may conceal it by wearing a mask.</span>")
to_chat(new_thrall_mind.current, "<span class='shadowling'>Though not nearly as powerful as your masters, you possess some weak powers. These can be found in the Thrall Abilities tab.</span>")
to_chat(new_thrall_mind.current, "<span class='shadowling'>You may communicate with your allies by speaking in the Shadowling Hivemind (:8).</span>")
to_chat(new_thrall_mind.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Shadowling)</span>")
to_chat(new_thrall_mind.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Shadowling)</span>")
if(jobban_isbanned(new_thrall_mind.current, ROLE_SHADOWLING) || jobban_isbanned(new_thrall_mind.current, ROLE_SYNDICATE))
replace_jobbanned_player(new_thrall_mind.current, ROLE_SHADOWLING)
if(!victory_warning_announced && (length(shadowling_thralls) >= warning_threshold))//are the slings very close to winning?
@@ -216,13 +216,13 @@ Made by Xhuis
if(shadow.current.stat == DEAD)
continue
shadows_alive++
if(shadow.special_role == SPECIAL_ROLE_SHADOWLING && config.shadowling_max_age)
if(shadow.special_role == SPECIAL_ROLE_SHADOWLING && GLOB.configuration.gamemode.shadowling_max_age)
if(ishuman(shadow.current))
var/mob/living/carbon/human/H = shadow.current
if(!isshadowling(H))
for(var/obj/effect/proc_holder/spell/targeted/shadowling_hatch/hatch_ability in shadow.spell_list)
hatch_ability.cycles_unused++
if(!H.stunned && prob(20) && hatch_ability.cycles_unused > config.shadowling_max_age)
if(!H.stunned && prob(20) && hatch_ability.cycles_unused > GLOB.configuration.gamemode.shadowling_max_age)
var/shadow_nag_messages = list("You can barely hold yourself in this lesser form!", "The urge to become something greater is overwhelming!", "You feel a burning passion to hatch free of this shell and assume godhood!")
H.take_overall_damage(0, 3)
to_chat(H, "<span class='userdanger'>[pick(shadow_nag_messages)]</span>")
+2 -2
View File
@@ -28,7 +28,7 @@
/datum/game_mode/traitor/pre_setup()
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
var/list/possible_traitors = get_players_for_role(ROLE_TRAITOR)
@@ -39,7 +39,7 @@
var/num_traitors = 1
if(config.traitor_scaling)
if(GLOB.configuration.gamemode.traitor_scaling)
num_traitors = max(1, round((num_players())/(traitor_scaling_coeff)))
else
num_traitors = max(1, min(num_players(), traitors_possible))
+1 -1
View File
@@ -17,7 +17,7 @@
/datum/game_mode/traitor/vampire/pre_setup()
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
var/list/datum/mind/possible_vampires = get_players_for_role(ROLE_VAMPIRE)
+2 -2
View File
@@ -40,7 +40,7 @@
/datum/game_mode/vampire/pre_setup()
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
restricted_jobs += protected_jobs
var/list/datum/mind/possible_vampires = get_players_for_role(ROLE_VAMPIRE)
@@ -193,7 +193,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
for(var/datum/objective/objective in vampire.objectives)
to_chat(vampire.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
obj_count++
to_chat(vampire.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Vampire)</span>")
to_chat(vampire.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Vampire)</span>")
return
/datum/vampire
var/bloodtotal = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS
+1 -1
View File
@@ -328,7 +328,7 @@
var/mob/living/simple_animal/hostile/construct/C = new picked_class(shell.loc)
C.init_construct(shade, src, shell)
to_chat(C, C.playstyle_string)
to_chat(C, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Construct)</span>")
to_chat(C, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Construct)</span>")
else
to_chat(user, "<span class='danger'>Creation failed!</span>: The soul stone is empty! Go kill someone!")
+1 -11
View File
@@ -108,19 +108,9 @@
for(var/datum/objective/objective in wizard.objectives)
to_chat(wizard.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
obj_count++
to_chat(wizard.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Wizard)</span>")
to_chat(wizard.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Wizard)</span>")
return
/*/datum/game_mode/proc/learn_basic_spells(mob/living/carbon/human/wizard_mob)
if(!istype(wizard_mob))
return
if(!config.feature_object_spell_system)
wizard_mob.verbs += /client/proc/jaunt
wizard_mob.mind.special_verbs += /client/proc/jaunt
else
wizard_mob.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(usr)
*/
/datum/game_mode/proc/equip_wizard(mob/living/carbon/human/wizard_mob)
if(!istype(wizard_mob))
return
+1 -1
View File
@@ -13,7 +13,7 @@
outfit = /datum/outfit/job/assistant
/datum/job/civilian/get_access()
if(config.assistant_maint)
if(GLOB.configuration.jobs.assistant_maint_access)
return list(ACCESS_MAINT_TUNNELS)
else
return list()
+4 -3
View File
@@ -85,10 +85,11 @@
announce(H)
/datum/job/proc/get_access()
if(!config) //Needed for robots.
if(!GLOB?.configuration?.jobs) //Needed for robots.
// AA TODO: Remove this once mulebots and stuff use Initialize()
return src.minimal_access.Copy()
if(config.jobs_have_minimal_access)
if(GLOB.configuration.jobs.jobs_have_minimal_access)
return src.minimal_access.Copy()
else
return src.access.Copy()
@@ -103,7 +104,7 @@
/datum/job/proc/available_in_days(client/C)
if(!C)
return 0
if(!config.use_age_restriction_for_jobs)
if(!GLOB.configuration.jobs.restrict_jobs_on_account_age)
return 0
if(!isnum(C.player_age))
return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced
+8 -8
View File
@@ -43,7 +43,7 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list(
set category = "Special Verbs"
set name = "Check my playtime"
if(!config.use_exp_tracking)
if(!GLOB.configuration.jobs.enable_exp_tracking)
to_chat(src, "<span class='warning'>Playtime tracking is not enabled.</span>")
return
@@ -105,9 +105,9 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list(
return 0
if(!role)
return 0
if(!config.use_exp_restrictions)
if(!GLOB.configuration.jobs.enable_exp_restrictions)
return 0
if(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, 0, C.mob))
if(GLOB.configuration.jobs.enable_exp_admin_bypass && check_rights(R_ADMIN, 0, C.mob))
return 0
var/list/play_records = params2list(C.prefs.exp)
var/isexempt = text2num(play_records[EXP_TYPE_EXEMPT])
@@ -128,9 +128,9 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list(
return 0
if(!exp_requirements || !exp_type)
return 0
if(!config.use_exp_restrictions)
if(!GLOB.configuration.jobs.enable_exp_restrictions)
return 0
if(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, 0, C.mob))
if(GLOB.configuration.jobs.enable_exp_admin_bypass && check_rights(R_ADMIN, 0, C.mob))
return 0
var/list/play_records = params2list(C.prefs.exp)
var/isexempt = text2num(play_records[EXP_TYPE_EXEMPT])
@@ -156,7 +156,7 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list(
return "[src] has no client."
/client/proc/get_exp_report()
if(!config.use_exp_tracking)
if(!GLOB.configuration.jobs.enable_exp_tracking)
return "Tracking is disabled in the server configuration file."
var/list/play_records = params2list(prefs.exp)
if(!play_records.len)
@@ -174,10 +174,10 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list(
return_text += "<LI>Exempt (all jobs auto-unlocked)</LI>"
else if(exp_data[EXP_TYPE_LIVING] > 0)
return_text += "<LI>[dep]: [get_exp_format(exp_data[dep])]</LI>"
if(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, 0, mob))
if(GLOB.configuration.jobs.enable_exp_admin_bypass && check_rights(R_ADMIN, 0, mob))
return_text += "<LI>Admin</LI>"
return_text += "</UL>"
if(config.use_exp_restrictions)
if(GLOB.configuration.jobs.enable_exp_restrictions)
var/list/jobs_locked = list()
var/list/jobs_unlocked = list()
for(var/datum/job/job in SSjobs.occupations)
+2 -53
View File
@@ -1,29 +1,6 @@
#define WHITELISTFILE "data/whitelist.txt"
GLOBAL_LIST_EMPTY(whitelist)
/proc/init_whitelists()
if(config.usewhitelist)
load_whitelist()
if(config.usealienwhitelist)
load_alienwhitelist()
/proc/load_whitelist()
GLOB.whitelist = file2list(WHITELISTFILE)
if(!GLOB.whitelist.len)
GLOB.whitelist = null
/*
/proc/check_whitelist(mob/M, rank)
if(!whitelist)
return 0
return ("[M.ckey]" in whitelist)
*/
/proc/is_job_whitelisted(mob/M, rank)
if(guest_jobbans(rank))
if(!config.usewhitelist)
return TRUE
if(config.disable_karma)
if(!GLOB.configuration.general.enable_karma)
return TRUE
if(check_rights(R_ADMIN, 0, M))
return TRUE
@@ -55,30 +32,13 @@ GLOBAL_LIST_EMPTY(whitelist)
else
return TRUE
GLOBAL_LIST_EMPTY(alien_whitelist)
/proc/load_alienwhitelist()
var/text = file2text("config/alienwhitelist.txt")
if(!text)
log_config("Failed to load config/alienwhitelist.txt\n")
else
GLOB.alien_whitelist = splittext(text, "\n")
//todo: admin aliens
/proc/is_alien_whitelisted(mob/M, species)
if(!config.usealienwhitelist)
return TRUE
if(config.disable_karma)
if(!GLOB.configuration.general.enable_karma)
return TRUE
if(species == "human" || species == "Human")
return TRUE
if(check_rights(R_ADMIN, 0))
return TRUE
if(!GLOB.alien_whitelist)
return FALSE
if(!SSdbcore.IsConnected())
return FALSE
else
@@ -104,14 +64,3 @@ GLOBAL_LIST_EMPTY(alien_whitelist)
break
qdel(species_read)
/*
if(M && species)
for(var/s in alien_whitelist)
if(findtext(s,"[M.ckey] - [species]"))
return 1
if(findtext(s,"[M.ckey] - All"))
return 1
*/
#undef WHITELISTFILE
+1 -1
View File
@@ -338,7 +338,7 @@
set_temp("Error: Not enough biomass.", "danger")
else if(pod.mess)
set_temp("Error: The cloning pod is malfunctioning.", "danger")
else if(!config.revival_cloning)
else if(!GLOB.configuration.general.enable_cloning)
set_temp("Error: Unable to initiate cloning cycle.", "danger")
else
cloneresult = pod.growclone(C)
@@ -45,15 +45,15 @@
var/light = -1
var/flash = -1
// Clamp all values to MAX_EXPLOSION_RANGE
// We dont need to clamp here. It gets clamped inside explosion()
if(round(amount/12) > 0)
devastation = min (GLOB.max_ex_devastation_range, devastation + round(amount/12))
devastation += round(amount/12)
if(round(amount/6) > 0)
heavy = min (GLOB.max_ex_heavy_range, heavy + round(amount/6))
heavy += round(amount/6)
if(round(amount/3) > 0)
light = min (GLOB.max_ex_light_range, light + round(amount/3))
light += round(amount/3)
if(flashing && flashing_factor)
flash += (round(amount/4) * flashing_factor)
+7 -7
View File
@@ -24,11 +24,11 @@
if(!ignorecap)
// Clamp all values to MAX_EXPLOSION_RANGE
devastation_range = min (GLOB.max_ex_devastation_range, devastation_range)
heavy_impact_range = min (GLOB.max_ex_heavy_range, heavy_impact_range)
light_impact_range = min (GLOB.max_ex_light_range, light_impact_range)
flash_range = min (GLOB.max_ex_flash_range, flash_range)
flame_range = min (GLOB.max_ex_flame_range, flame_range)
devastation_range = min(GLOB.configuration.general.bomb_cap / 4, devastation_range)
heavy_impact_range = min(GLOB.configuration.general.bomb_cap / 2, heavy_impact_range)
light_impact_range = min(GLOB.configuration.general.bomb_cap, light_impact_range)
flash_range = min(GLOB.configuration.general.bomb_cap, flash_range)
flame_range = min(GLOB.configuration.general.bomb_cap, flame_range)
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
@@ -118,7 +118,7 @@
var/list/affected_turfs = spiral_range_turfs(max_range, epicenter)
if(config.reactionary_explosions)
if(GLOB.configuration.general.reactionary_explosions)
for(var/A in affected_turfs) // we cache the explosion block rating of every turf in the explosion area
var/turf/T = A
cached_exp_block[T] = 0
@@ -136,7 +136,7 @@
continue
var/dist = HYPOTENUSE(T.x, T.y, x0, y0)
if(config.reactionary_explosions)
if(GLOB.configuration.general.reactionary_explosions)
var/turf/Trajectory = T
while(Trajectory != epicenter)
Trajectory = get_step_towards(Trajectory, epicenter)
+4 -5
View File
@@ -179,12 +179,11 @@
addtimer(CALLBACK(src, .proc/boom, user, result), 4 SECONDS)
/obj/item/dice/d20/e20/proc/boom(mob/user, result)
var/capped = FALSE
var/capped = TRUE
var/actual_result = result
if(result != 20)
capped = TRUE
result = min(result, GLOB.max_ex_light_range) // Apply the bombcap
else // Rolled a nat 20, screw the bombcap
// Rolled a nat 20, screw the bombcap
if(result == 20)
capped = FALSE
result = 24
var/turf/epicenter = get_turf(src)
@@ -24,7 +24,7 @@
var/oldloc = loc
step(src, direction)
if(oldloc != loc)
addtimer(CALLBACK(src, .proc/ResetMoveDelay), config.walk_speed)
addtimer(CALLBACK(src, .proc/ResetMoveDelay), GLOB.configuration.movement.base_walk_speed)
else
move_delay = FALSE
+3 -6
View File
@@ -114,12 +114,9 @@
if("Body")
var/list/race_list = list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin")
if(config.usealienwhitelist)
for(var/Spec in GLOB.whitelisted_species)
if(is_alien_whitelisted(H, Spec))
race_list += Spec
else
race_list += GLOB.whitelisted_species
for(var/species in GLOB.whitelisted_species)
if(is_alien_whitelisted(H, species))
race_list += species
var/datum/ui_module/appearance_changer/AC = ui_users[user]
if(!AC)
@@ -116,7 +116,7 @@
set category = "Object"
set src in oview(1)
if(config.ghost_interaction)
if(GLOB.configuration.general.ghost_interaction)
setDir(turn(dir, 90))
handle_rotation()
return
+1 -1
View File
@@ -178,7 +178,7 @@ falloff_distance - Distance at which falloff begins. Sound is at peak volume (in
SEND_SOUND(src, S)
/client/proc/playtitlemusic()
if(!SSticker || !SSticker.login_music || config.disable_lobby_music)
if(!SSticker || !SSticker.login_music || GLOB.configuration.general.disable_lobby_music)
return
if(prefs.sound & SOUND_LOBBY)
SEND_SOUND(src, sound(SSticker.login_music, repeat = 0, wait = 0, volume = 85 * prefs.get_channel_volume(CHANNEL_LOBBYMUSIC), channel = CHANNEL_LOBBYMUSIC)) // MAD JAMS
+1 -1
View File
@@ -54,7 +54,7 @@
S.apply_transition(src)
/turf/space/proc/update_starlight()
if(config.starlight)
if(GLOB.configuration.general.starlight)
for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm
if(isspaceturf(t))
//let's NOT update this that much pls
+10 -10
View File
@@ -19,10 +19,10 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
return
if(!check_rights(R_ADMIN|R_MOD, 0))
if(!config.ooc_allowed)
if(!GLOB.ooc_enabled)
to_chat(src, "<span class='danger'>OOC is globally muted.</span>")
return
if(!config.dooc_allowed && (mob.stat == DEAD))
if(!GLOB.dooc_enabled && (mob.stat == DEAD))
to_chat(usr, "<span class='danger'>OOC for dead mobs has been turned off.</span>")
return
if(prefs.muted & MUTE_OOC)
@@ -41,7 +41,7 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
return
if(!check_rights(R_ADMIN|R_MOD,0))
if(!config.ooc_allowed)
if(!GLOB.ooc_enabled)
to_chat(src, "<span class='danger'>OOC is globally muted.</span>")
return
if(handle_spam_prevention(msg, MUTE_OOC, OOC_COOLDOWN))
@@ -61,7 +61,7 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
if(check_rights(R_MOD,0) && !check_rights(R_ADMIN,0))
display_colour = GLOB.moderator_ooc_colour
else if(check_rights(R_ADMIN,0))
if(config.allow_admin_ooccolor)
if(GLOB.configuration.admin.allow_admin_ooc_colour)
display_colour = src.prefs.ooccolor
else
display_colour = GLOB.admin_ooc_colour
@@ -92,20 +92,20 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
else
display_name = holder.fakekey
if(!config.disable_ooc_emoji)
if(GLOB.configuration.general.enable_ooc_emoji)
msg = "<span class='emoji_enabled'>[msg]</span>"
to_chat(C, "<font color='[display_colour]'><span class='ooc'><span class='prefix'>OOC:</span> <EM>[display_name]:</EM> <span class='message'>[msg]</span></span></font>")
/proc/toggle_ooc()
config.ooc_allowed = ( !config.ooc_allowed )
if(config.ooc_allowed)
GLOB.ooc_enabled = (!GLOB.ooc_enabled)
if(GLOB.ooc_enabled)
to_chat(world, "<B>The OOC channel has been globally enabled!</B>")
else
to_chat(world, "<B>The OOC channel has been globally disabled!</B>")
/proc/auto_toggle_ooc(on)
if(config.auto_toggle_ooc_during_round && config.ooc_allowed != on)
if(GLOB.configuration.general.auto_disable_ooc && GLOB.ooc_enabled != on)
toggle_ooc()
/client/proc/set_ooc(newColor as color)
@@ -175,10 +175,10 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
return
if(!check_rights(R_ADMIN|R_MOD,0))
if(!config.looc_allowed)
if(!GLOB.looc_enabled)
to_chat(src, "<span class='danger'>LOOC is globally muted.</span>")
return
if(!config.dooc_allowed && (mob.stat == DEAD))
if(!GLOB.dooc_enabled && (mob.stat == DEAD))
to_chat(usr, "<span class='danger'>LOOC for dead mobs has been turned off.</span>")
return
if(prefs.muted & MUTE_OOC)
+33 -44
View File
@@ -8,9 +8,19 @@ GLOBAL_LIST_INIT(map_transition_config, list(CC_TRANSITION_CONFIG))
// Right off the bat
enable_auxtools_debugger()
// Do sanity checks to ensure RUST actually exists
if(!fexists(RUST_G))
DIRECT_OUTPUT(world.log, "ERROR: RUSTG was not found and is required for the game to function. Server will now exit.")
del(world)
var/rustg_version = rustg_get_version()
if(rustg_version != RUST_G_VERSION)
DIRECT_OUTPUT(world.log, "ERROR: RUSTG version mismatch. Library is [rustg_version], code wants [RUST_G_VERSION]. Server will now exit.")
del(world)
//temporary file used to record errors with loading config and the database, moved to log directory once logging is set up
GLOB.config_error_log = GLOB.world_game_log = GLOB.world_runtime_log = GLOB.sql_log = "data/logs/config_error.log"
load_configuration()
GLOB.configuration.load_configuration()
// Right off the bat, load up the DB
SSdbcore.CheckSchemaVersion() // This doesnt just check the schema version, it also connects to the db! This needs to happen super early! I cannot stress this enough!
@@ -18,6 +28,7 @@ GLOBAL_LIST_INIT(map_transition_config, list(CC_TRANSITION_CONFIG))
// Setup all log paths and stamp them with startups, including round IDs
SetupLogs()
load_files() // Loads up the MOTD (Welcome message players see when joining the server), TOS and gamemode
// This needs to happen early, otherwise people can get a null species, nuking their character
makeDatumRefLists()
@@ -32,16 +43,9 @@ GLOBAL_LIST_INIT(map_transition_config, list(CC_TRANSITION_CONFIG))
log_world("Unit Tests Are Enabled!")
#endif
if(!fexists("config/config.txt") || !fexists("config/game_options.txt"))
stack_trace("The game config files have not been properly set! Please copy ALL files from '/config/example' into the parent folder, '/config'.")
if(byond_version < MIN_COMPILER_VERSION || byond_build < MIN_COMPILER_BUILD)
log_world("Your server's byond version does not meet the recommended requirements for this code. Please update BYOND")
if(config && config.server_name != null && config.server_suffix && world.port > 0)
// dumb and hardcoded but I don't care~
config.server_name += " #[(world.port % 1000) / 100]"
GLOB.timezoneOffset = text2num(time2text(0, "hh")) * 36000
startup_procs() // Call procs that need to occur on startup (Generate lists, load MOTD, etc)
@@ -69,8 +73,6 @@ GLOBAL_LIST_INIT(map_transition_config, list(CC_TRANSITION_CONFIG))
/world/proc/startup_procs()
LoadBans() // Load up who is banned and who isnt. DONT PUT THIS IN A SUBSYSTEM IT WILL TAKE TOO LONG TO BE CALLED
jobban_loadbanfile() // Load up jobbans. Again, DO NOT PUT THIS IN A SUBSYSTEM IT WILL TAKE TOO LONG TO BE CALLED
load_motd() // Loads up the MOTD (Welcome message players see when joining the server)
load_mode() // Loads up the gamemode
investigate_reset() // This is part of the admin investigate system. PLEASE DONT SS THIS EITHER
/// List of all world topic spam prevention handlers. See code/modules/world_topic/_spam_prevention_handler.dm
@@ -122,10 +124,10 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
to_chat(world, "<span class='boldannounce'>Rebooting world immediately due to host request</span>")
rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
// Now handle a reboot
if(config && config.shutdown_on_reboot)
if(GLOB.configuration.system.shutdown_on_reboot)
sleep(0)
if(GLOB.shutdown_shell_command)
shell(GLOB.shutdown_shell_command)
if(GLOB.configuration.system.shutdown_shell_command)
shell(GLOB.configuration.system.shutdown_shell_command)
del(world)
TgsEndProcess() // We want to shutdown on reboot. That means kill our TGS process "gracefully", instead of the watchdog crying
return
@@ -151,15 +153,15 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
// Send the reboot banner to all players
for(var/client/C in GLOB.clients)
C << output(list2params(list(secs_before_auto_reconnect)), "browseroutput:reboot")
if(config.server) // If you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[config.server]")
if(GLOB.configuration.url.server_url) // If you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
C << link("byond://[GLOB.configuration.url.server_url]")
// And begin the real shutdown
rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
if(config && config.shutdown_on_reboot)
if(GLOB.configuration.system.shutdown_on_reboot)
sleep(0)
if(GLOB.shutdown_shell_command)
shell(GLOB.shutdown_shell_command)
if(GLOB.configuration.system.shutdown_shell_command)
shell(GLOB.configuration.system.shutdown_shell_command)
rustg_log_close_all() // Past this point, no logging procs can be used, at risk of data loss.
del(world)
TgsEndProcess() // We want to shutdown on reboot. That means kill our TGS process "gracefully", instead of the watchdog crying
@@ -180,39 +182,26 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
fdel(F)
F << the_mode
/world/proc/load_motd()
/world/proc/load_files()
GLOB.join_motd = file2text("config/motd.txt")
GLOB.join_tos = file2text("config/tos.txt")
/proc/load_configuration()
config = new /datum/configuration()
config.load("config/config.txt")
config.load("config/game_options.txt","game_options")
config.loadsql("config/dbconfig.txt")
config.loadoverflowwhitelist("config/ofwhitelist.txt")
config.load_rank_colour_map()
// apply some settings from config..
load_mode()
/world/proc/update_status()
status = get_status_text()
/proc/get_world_status_text()
return world.get_status_text()
/world/proc/get_status_text()
var/s = ""
if(config && config.server_name)
s += "<b>[config.server_name]</b> &#8212; "
if(GLOB.configuration.general.server_name)
s += "<b>[GLOB.configuration.general.server_name]</b> &#8212; "
s += "<b>[station_name()]</b> "
if(config && config.githuburl)
s+= "([GLOB.game_version])"
if(config && config.server_tag_line)
s += "<br>[config.server_tag_line]"
if(GLOB.configuration.general.server_tag_line)
s += "<br>[GLOB.configuration.general.server_tag_line]"
if(SSticker && ROUND_TIME > 0)
s += "<br>[round(ROUND_TIME / 36000)]:[add_zero(num2text(ROUND_TIME / 600 % 60), 2)], " + capitalize(get_security_level())
s += "<br>[round(ROUND_TIME / 36000)]:[add_zero(num2text(ROUND_TIME / 600 % 60), 2)], [capitalize(get_security_level())]"
else
s += "<br><b>STARTING</b>"
@@ -222,16 +211,16 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
if(!GLOB.enter_allowed)
features += "closed"
if(config && config.server_extra_features)
features += config.server_extra_features
if(GLOB.configuration.general.server_features)
features += GLOB.configuration.general.server_features
if(config && config.allow_vote_mode)
if(GLOB.configuration.vote.allow_restart_votes)
features += "vote"
if(config && config.wikiurl)
features += "<a href=\"[config.wikiurl]\">Wiki</a>"
if(GLOB.configuration.url.wiki_url)
features += "<a href=\"[GLOB.configuration.url.wiki_url]\">Wiki</a>"
if(GLOB.abandon_allowed)
if(GLOB.configuration.general.respawn_enabled)
features += "respawn"
if(features)
+8 -8
View File
@@ -28,24 +28,24 @@
admin = 1
//Guest Checking
if(!GLOB.guests_allowed && IsGuestKey(key))
if(GLOB.configuration.general.guest_ban && IsGuestKey(key))
log_adminwarn("Failed Login: [key] [computer_id] [address] - Guests not allowed")
// message_admins("<span class='notice'>Failed Login: [key] - Guests not allowed</span>")
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED)
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
//check if the IP address is a known proxy/vpn, and the user is not whitelisted
if(check_ipintel && config.ipintel_email && config.ipintel_whitelist && ipintel_is_banned(key, address))
if(check_ipintel && GLOB.configuration.ipintel.contact_email && GLOB.configuration.ipintel.whitelist_mode && ipintel_is_banned(key, address))
log_adminwarn("Failed Login: [key] [computer_id] [address] - Proxy/VPN")
var/mistakemessage = ""
if(config.banappeals)
mistakemessage = "\nIf you have to use one, request whitelisting at: [config.banappeals]"
if(GLOB.configuration.url.banappeals_url)
mistakemessage = "\nIf you have to use one, request whitelisting at: [GLOB.configuration.url.banappeals_url]"
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_IPINTEL)
return list("reason"="using proxy or vpn", "desc"="\nReason: Proxies/VPNs are not allowed here. [mistakemessage]")
// If 2FA is enabled, makes sure they were authed within the last minute
if(check_2fa && config._2fa_auth_host)
if(check_2fa && GLOB.configuration.system._2fa_auth_host)
// First see if they exist at all
var/datum/db_query/check_query = SSdbcore.NewQuery("SELECT 2fa_status, ip FROM [format_table_name("player")] WHERE ckey=:ckey", list("ckey" = ckey(key)))
@@ -87,7 +87,7 @@
qdel(verify_query)
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
//Ban Checking
. = CheckBan(ckey(key), computer_id, address)
if(.)
@@ -159,8 +159,8 @@
expires = " The ban is for [duration] minutes and expires on [expiration] (server time)."
else
var/appealmessage = ""
if(config.banappeals)
appealmessage = " You may appeal it at <a href='[config.banappeals]'>[config.banappeals]</a>."
if(GLOB.configuration.url.banappeals_url)
appealmessage = " You may appeal it at <a href='[GLOB.configuration.url.banappeals_url]'>[GLOB.configuration.url.banappeals_url]</a>."
expires = " This ban does not expire automatically and must be appealed.[appealmessage]"
var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime][ban_round_id ? " (Round [ban_round_id])" : ""].[expires]"
+2 -2
View File
@@ -10,8 +10,8 @@ GLOBAL_PROTECT(banlist_savefile) // Obvious reasons
. = list()
var/appeal
if(config && config.banappeals)
appeal = "\nFor more information on your ban, or to appeal, head to <a href='[config.banappeals]'>[config.banappeals]</a>"
if(GLOB.configuration.url.banappeals_url)
appeal = "\nFor more information on your ban, or to appeal, head to <a href='[GLOB.configuration.url.banappeals_url]'>[GLOB.configuration.url.banappeals_url]</a>"
GLOB.banlist_savefile.cd = "/base"
if( "[ckey][id]" in GLOB.banlist_savefile.dir )
GLOB.banlist_savefile.cd = "[ckey][id]"
+22 -22
View File
@@ -91,8 +91,8 @@ GLOBAL_VAR_INIT(nologevent, 0)
else
body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\] "
body += "\[<A href='?_src_=holder;getplaytimewindow=[M.UID()]'>" + M.client.get_exp_type(EXP_TYPE_CREW) + " as [EXP_TYPE_CREW]</a>\]"
body += "<br>BYOND account registration date: [M.client.byondacc_date || "ERROR"] [M.client.byondacc_age <= config.byond_account_age_threshold ? "<b>" : ""]([M.client.byondacc_age] days old)[M.client.byondacc_age <= config.byond_account_age_threshold ? "</b>" : ""]"
body += "<br>Global Ban DB Lookup: [config.centcom_ban_db_url ? "<a href='?_src_=holder;open_ccbdb=[M.client.ckey]'>Lookup</a>" : "<i>Disabled</i>"]"
body += "<br>BYOND account registration date: [M.client.byondacc_date || "ERROR"] [M.client.byondacc_age <= GLOB.configuration.general.byond_account_age_threshold ? "<b>" : ""]([M.client.byondacc_age] days old)[M.client.byondacc_age <= GLOB.configuration.general.byond_account_age_threshold ? "</b>" : ""]"
body += "<br>Global Ban DB Lookup: [GLOB.configuration.url.centcom_ban_db_url ? "<a href='?_src_=holder;open_ccbdb=[M.client.ckey]'>Lookup</a>" : "<i>Disabled</i>"]"
body += "<br>"
@@ -127,7 +127,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
body += "<A href='?_src_=holder;appearanceban=[M.UID()];dbbanaddckey=[M.ckey]'>Appearance Ban</A> | "
body += "<A href='?_src_=holder;shownoteckey=[M.ckey]'>Notes</A> | "
body += "<A href='?_src_=holder;viewkarma=[M.ckey]'>View Karma</A> | "
if(config.forum_playerinfo_url)
if(GLOB.configuration.url.forum_playerinfo_url)
body += "<A href='?_src_=holder;webtools=[M.ckey]'>WebInfo</A> | "
if(M.client)
if(check_watchlist(M.client.ckey))
@@ -462,8 +462,8 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_ADMIN))
return
config.looc_allowed = !(config.looc_allowed)
if(config.looc_allowed)
GLOB.looc_enabled = !(GLOB.looc_enabled)
if(GLOB.looc_enabled)
to_chat(world, "<B>The LOOC channel has been globally enabled!</B>")
else
to_chat(world, "<B>The LOOC channel has been globally disabled!</B>")
@@ -478,8 +478,8 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_ADMIN))
return
config.dsay_allowed = !(config.dsay_allowed)
if(config.dsay_allowed)
GLOB.dsay_enabled = !(GLOB.dsay_enabled)
if(GLOB.dsay_enabled)
to_chat(world, "<B>Deadchat has been globally enabled!</B>")
else
to_chat(world, "<B>Deadchat has been globally disabled!</B>")
@@ -495,7 +495,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_ADMIN))
return
config.dooc_allowed = !( config.dooc_allowed )
GLOB.dooc_enabled = !(GLOB.dooc_enabled)
log_admin("[key_name(usr)] toggled Dead OOC.")
message_admins("[key_name_admin(usr)] toggled Dead OOC.", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Dead OOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -508,7 +508,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_ADMIN))
return
config.disable_ooc_emoji = !(config.disable_ooc_emoji)
GLOB.configuration.general.enable_ooc_emoji = !(GLOB.configuration.general.enable_ooc_emoji)
log_admin("[key_name(usr)] toggled OOC Emoji.")
message_admins("[key_name_admin(usr)] toggled OOC Emoji.", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle OOC Emoji")
@@ -525,7 +525,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
alert("Unable to start the game as it is not set up.")
return
if(config.start_now_confirmation)
if(GLOB.configuration.general.start_now_confirmation)
if(alert(usr, "This is a live server. Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
return
@@ -568,8 +568,9 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_EVENT))
return
config.allow_ai = !( config.allow_ai )
if(!( config.allow_ai ))
GLOB.configuration.jobs.allow_ai = !(GLOB.configuration.jobs.allow_ai)
if(!GLOB.configuration.jobs.allow_ai)
to_chat(world, "<B>The AI job is no longer chooseable.</B>")
else
to_chat(world, "<B>The AI job is chooseable now.</B>")
@@ -586,13 +587,13 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_SERVER))
return
GLOB.abandon_allowed = !( GLOB.abandon_allowed )
if(GLOB.abandon_allowed)
GLOB.configuration.general.respawn_enabled = !(GLOB.configuration.general.respawn_enabled)
if(GLOB.configuration.general.respawn_enabled)
to_chat(world, "<B>You may now respawn.</B>")
else
to_chat(world, "<B>You may no longer respawn :(</B>")
message_admins("[key_name_admin(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].", 1)
log_admin("[key_name(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].")
to_chat(world, "<B>You may no longer respawn</B>")
message_admins("[key_name_admin(usr)] toggled respawn to [GLOB.configuration.general.respawn_enabled ? "On" : "Off"].", 1)
log_admin("[key_name(usr)] toggled respawn to [GLOB.configuration.general.respawn_enabled ? "On" : "Off"].")
world.update_status()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Respawn") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -724,13 +725,13 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_SERVER))
return
GLOB.guests_allowed = !( GLOB.guests_allowed )
if(!( GLOB.guests_allowed ))
GLOB.configuration.general.guest_ban = !(GLOB.configuration.general.guest_ban)
if(GLOB.configuration.general.guest_ban)
to_chat(world, "<B>Guests may no longer enter the game.</B>")
else
to_chat(world, "<B>Guests may now enter the game.</B>")
log_admin("[key_name(usr)] toggled guests game entering [GLOB.guests_allowed ? "" : "dis"]allowed.")
message_admins("<span class='notice'>[key_name_admin(usr)] toggled guests game entering [GLOB.guests_allowed ? "" : "dis"]allowed.</span>", 1)
log_admin("[key_name(usr)] toggled guests game entering [GLOB.configuration?.general.guest_ban ? "dis" : ""]allowed.")
message_admins("<span class='notice'>[key_name_admin(usr)] toggled guests game entering [GLOB.configuration?.general.guest_ban ? "dis" : ""]allowed.</span>", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Guests") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/output_ai_laws()
@@ -917,4 +918,3 @@ GLOBAL_VAR_INIT(gamma_ship_location, 1) // 0 = station , 1 = space
continue
result[1]++
return result
+1 -1
View File
@@ -43,7 +43,7 @@
watchlist_show()
if("hrefs") //persistant logs and stuff
if(config && config.log_hrefs)
if(GLOB.configuration.logging.href_logging)
if(GLOB.world_href_log)
src << browse(file(GLOB.world_href_log), "window=investigate[subject];size=800x300")
else
+14 -40
View File
@@ -7,25 +7,15 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
var/previous_rights = 0
//load text from file
var/list/Lines = file2list("config/admin_ranks.txt")
//process each line seperately
for(var/line in Lines)
if(!length(line)) continue
if(copytext(line,1,2) == "#") continue
var/list/List = splittext(line,"+")
if(!List.len) continue
var/rank = ckeyEx(List[1])
switch(rank)
if(null,"") continue
if("Removed") continue //Reserved
// Process each rank set seperately
// key: rank name | value: list of rights
for(var/rankname in GLOB.configuration.admin.rank_rights_map)
var/list/rank_right_tokens = GLOB.configuration.admin.rank_rights_map[rankname]
var/rights = 0
for(var/i=2, i<=List.len, i++)
switch(ckey(List[i]))
for(var/right_token in rank_right_tokens)
var/token = lowertext(splittext(right_token, "+")[2])
switch(token)
if("@","prev") rights |= previous_rights
if("buildmode","build") rights |= R_BUILDMODE
if("admin") rights |= R_ADMIN
@@ -46,7 +36,7 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
if("proccall") rights |= R_PROCCALL
if("viewruntimes") rights |= R_VIEWRUNTIMES
GLOB.admin_ranks[rank] = rights
GLOB.admin_ranks[rankname] = rights
previous_rights = rights
#ifdef TESTING
@@ -73,29 +63,13 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
for(var/A in world.GetConfig("admin"))
world.SetConfig("APP/admin", A, null)
if(config.admin_legacy_system)
if(!GLOB.configuration.admin.use_database_admins)
load_admin_ranks()
//load text from file
var/list/Lines = file2list("config/admins.txt")
//process each line seperately
for(var/line in Lines)
if(!length(line)) continue
if(copytext(line,1,2) == "#") continue
//Split the line at every "-"
var/list/List = splittext(line, "-")
if(!List.len) continue
//ckey is before the first "-"
var/ckey = ckey(List[1])
if(!ckey) continue
//rank follows the first "-"
var/rank = ""
if(List.len >= 2)
rank = ckeyEx(List[2])
for(var/iterator_key in GLOB.configuration.admin.ckey_rank_map)
var/ckey = ckey(iterator_key) // Snip out formatting
var/rank = GLOB.configuration.admin.ckey_rank_map[iterator_key]
//load permissions associated with this rank
var/rights = GLOB.admin_ranks[rank]
@@ -113,7 +87,7 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
//The current admin system uses SQL
if(!SSdbcore.IsConnected())
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
config.admin_legacy_system = 1
GLOB.configuration.admin.use_database_admins = FALSE
load_admins()
return
@@ -141,7 +115,7 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
if(!GLOB.admin_datums)
log_world("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.")
config.admin_legacy_system = 1
GLOB.configuration.admin.use_database_admins = FALSE
load_admins()
return

Some files were not shown because too many files have changed in this diff Show More