Merge branch 'master' into ghost-rad-hud

This commit is contained in:
Matt
2021-08-10 11:14:35 -07:00
committed by GitHub
593 changed files with 28984 additions and 43984 deletions
+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
+1 -1
View File
@@ -1,7 +1,7 @@
SUBSYSTEM_DEF(alarm)
name = "Alarm"
flags = SS_NO_INIT | SS_NO_FIRE
var/list/alarms = list("Motion" = list(), "Fire" = list(), "Atmosphere" = list(), "Power" = list(), "Camera" = list(), "Burglar" = list())
var/list/alarms = list("Motion" = list(), "Fire" = list(), "Atmosphere" = list(), "Power" = list(), "Burglar" = list())
/datum/controller/subsystem/alarm/proc/triggerAlarm(class, area/A, list/O, obj/alarmsource)
var/list/L = alarms[class]
+2 -2
View File
@@ -65,7 +65,7 @@ SUBSYSTEM_DEF(blackbox)
sqlversion = versions[FV.key]
var/datum/db_query/query_feedback_save = SSdbcore.NewQuery({"
INSERT IGNORE INTO [format_table_name("feedback")] (datetime, round_id, key_name, key_type, version, json)
INSERT IGNORE INTO feedback (datetime, round_id, key_name, key_type, version, json)
VALUES (NOW(), :rid, :keyname, :keytype, :version, :json)"}, list(
"rid" = text2num(GLOB.round_id),
"keyname" = FV.key,
@@ -287,7 +287,7 @@ SUBSYSTEM_DEF(blackbox)
lakey = L.lastattackerckey
var/datum/db_query/deathquery = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord)
INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord)
VALUES (:name, :key, :job, :special, :pod, NOW(), :laname, :lakey, :gender, :bruteloss, :fireloss, :brainloss, :oxyloss, :coord)"},
list(
"name" = L.real_name,
+4 -4
View File
@@ -24,7 +24,7 @@ SUBSYSTEM_DEF(changelog)
if(!SSdbcore.IsConnected())
return ..()
var/datum/db_query/latest_cl_date = SSdbcore.NewQuery("SELECT CAST(UNIX_TIMESTAMP(date_merged) AS CHAR) AS ut FROM [format_table_name("changelog")] ORDER BY date_merged DESC LIMIT 1")
var/datum/db_query/latest_cl_date = SSdbcore.NewQuery("SELECT CAST(UNIX_TIMESTAMP(date_merged) AS CHAR) AS ut FROM changelog ORDER BY date_merged DESC LIMIT 1")
if(!latest_cl_date.warn_execute())
qdel(latest_cl_date)
// Abort if we cant do this
@@ -63,7 +63,7 @@ SUBSYSTEM_DEF(changelog)
C.prefs.lastchangelog = current_cl_timestamp
var/datum/db_query/updatePlayerCLTime = SSdbcore.NewQuery(
"UPDATE [format_table_name("player")] SET lastchangelog=:lastchangelog WHERE ckey=:ckey",
"UPDATE player SET lastchangelog=:lastchangelog WHERE ckey=:ckey",
list(
"lastchangelog" = current_cl_timestamp,
"ckey" = C.ckey
@@ -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>")
+20 -20
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")
@@ -142,7 +142,7 @@ SUBSYSTEM_DEF(dbcore)
//This is as close as we can get to the true round end before Disconnect() without changing where it's called, defeating the reason this is a subsystem
if(SSdbcore.Connect())
var/datum/db_query/query_round_shutdown = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET shutdown_datetime = Now(), end_state = :end_state WHERE id = :round_id",
"UPDATE round SET shutdown_datetime = Now(), end_state = :end_state WHERE id = :round_id",
list("end_state" = SSticker.end_state, "round_id" = GLOB.round_id)
)
query_round_shutdown.Execute()
@@ -160,7 +160,7 @@ SUBSYSTEM_DEF(dbcore)
if(!IsConnected())
return
var/datum/db_query/query_round_initialize = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("round")] (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(:internet_address), :port)",
"INSERT INTO round (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(:internet_address), :port)",
list("internet_address" = world.internet_address || "0", "port" = "[world.port]")
)
query_round_initialize.Execute(async = FALSE)
@@ -177,7 +177,7 @@ SUBSYSTEM_DEF(dbcore)
if(!IsConnected())
return
var/datum/db_query/query_round_start = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET start_datetime=NOW(), commit_hash=:hash WHERE id=:round_id",
"UPDATE round SET start_datetime=NOW(), commit_hash=:hash WHERE id=:round_id",
list("hash" = GLOB.revision_info.commit_hash, "round_id" = GLOB.round_id)
)
query_round_start.Execute(async = FALSE) // This happens during a time of intense server lag, so should be non-async
@@ -193,7 +193,7 @@ SUBSYSTEM_DEF(dbcore)
if(!IsConnected())
return
var/datum/db_query/query_round_end = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = :game_mode_result WHERE id = :round_id",
"UPDATE round SET end_datetime = Now(), game_mode_result = :game_mode_result WHERE id = :round_id",
list("game_mode_result" = SSticker.mode_result, "station_name" = station_name(), "round_id" = GLOB.round_id)
)
query_round_end.Execute()
@@ -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
+365 -4
View File
@@ -3,13 +3,374 @@ SUBSYSTEM_DEF(ipintel)
wait = 1
flags = SS_NO_FIRE
init_order = INIT_ORDER_XKEYSCORE // 10
var/enabled = 0 //disable at round start to avoid checking reconnects
// Are we enabled? Auto disable at world init to avoid checking reconnects
var/enabled = FALSE
var/throttle = 0
var/errors = 0
var/list/cache = list()
/datum/controller/subsystem/ipintel/Initialize(timeofday, zlevel)
enabled = 1
. = ..()
/datum/controller/subsystem/ipintel/Initialize(timeofday)
enabled = TRUE
return ..()
// Represents an IP intel holder datum
/datum/ipintel
/// The IP being checked
var/ip
/// The current rating, 0-1 float.
var/intel = 0
/// Whether this was loaded from the cache or not
var/cache = FALSE
/// How many minutes ago it was cached
var/cacheminutesago = 0
/// The date it was cached
var/cachedate = ""
/// The real time it was cached
var/cacherealtime = 0
/datum/ipintel/New()
cachedate = SQLtime()
cacherealtime = world.realtime
/datum/ipintel/proc/is_valid()
. = FALSE
if(intel < 0)
return
if(intel <= GLOB.configuration.ipintel.bad_rating)
if(world.realtime < cacherealtime + (GLOB.configuration.ipintel.hours_save_good HOURS))
return TRUE
else
if(world.realtime < cacherealtime + (GLOB.configuration.ipintel.hours_save_bad HOURS))
return TRUE
/**
* Get IP intel
*
* Performs a lookup of the rating for an IP provided
*
* Arguments:
* * ip - The IP to lookup
* * bypasscache - Do we want to bypass the DB cache?
* * updatecache - Do we want to update the DB cache?
*/
/datum/controller/subsystem/ipintel/proc/get_ip_intel(ip, bypasscache = FALSE, updatecache = TRUE)
var/datum/ipintel/res = new()
res.ip = ip
. = res
if(!ip || !GLOB.configuration.ipintel.contact_email || !GLOB.configuration.ipintel.enabled || !enabled)
return
if(!bypasscache)
var/datum/ipintel/cachedintel = cache[ip]
if(cachedintel && cachedintel.is_valid())
cachedintel.cache = TRUE
return cachedintel
if(SSdbcore.IsConnected())
var/datum/db_query/query_get_ip_intel = SSdbcore.NewQuery({"
SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW())
FROM ipintel
WHERE
ip = INET_ATON(:ip)
AND ((
intel < :rating_bad
AND
date + INTERVAL :save_good HOUR > NOW()
) OR (
intel >= :rating_bad
AND
date + INTERVAL :save_bad HOUR > NOW()
))
"}, list(
"ip" = ip,
"rating_bad" = GLOB.configuration.ipintel.bad_rating,
"save_good" = GLOB.configuration.ipintel.hours_save_good,
"save_bad" = GLOB.configuration.ipintel.hours_save_bad,
))
if(!query_get_ip_intel.warn_execute())
qdel(query_get_ip_intel)
return
if(query_get_ip_intel.NextRow())
res.cache = TRUE
res.cachedate = query_get_ip_intel.item[1]
res.intel = text2num(query_get_ip_intel.item[2])
res.cacheminutesago = text2num(query_get_ip_intel.item[3])
res.cacherealtime = world.realtime - (text2num(query_get_ip_intel.item[3])*10*60)
cache[ip] = res
qdel(query_get_ip_intel)
return
qdel(query_get_ip_intel)
res.intel = ip_intel_query(ip)
if(updatecache && res.intel >= 0)
cache[ip] = res
if(SSdbcore.IsConnected())
var/datum/db_query/query_add_ip_intel = SSdbcore.NewQuery({"
INSERT INTO ipintel (ip, intel) VALUES (INET_ATON(:ip), :intel)
ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()"},
list(
"ip" = ip,
"intel" = res.intel
)
)
query_add_ip_intel.warn_execute()
qdel(query_add_ip_intel)
/**
* Performs the remote IPintel lookup
*
*
*
* Arguments:
* * ip - The IP to lookup
* * retried - Was this attempt retried?
*/
/datum/controller/subsystem/ipintel/proc/ip_intel_query(ip, retried = FALSE)
. = -1 //default
if(!ip)
return
if(throttle > world.timeofday)
return
if(!enabled)
return
// Do not refactor this to use SShttp, because that requires the subsystem to be firing for requests to be made, and this will be triggered before the MC has finished loading
var/list/http[] = world.Export("http://[GLOB.configuration.ipintel.ipintel_domain]/check.php?ip=[ip]&contact=[GLOB.configuration.ipintel.contact_email]&format=json&flags=b")
if(http)
var/status = text2num(http["STATUS"])
if(status == 200)
var/response = json_decode(file2text(http["CONTENT"]))
if(response)
if(response["status"] == "success")
var/intelnum = text2num(response["result"])
if(isnum(intelnum))
return text2num(response["result"])
else
ipintel_handle_error("Bad intel from server: [response["result"]].", ip, retried)
if(!retried)
sleep(25)
return .(ip, 1)
else
ipintel_handle_error("Bad response from server: [response["status"]].", ip, retried)
if(!retried)
sleep(25)
return .(ip, 1)
else if(status == 429)
ipintel_handle_error("Error #429: We have exceeded the rate limit.", ip, 1)
return
else
ipintel_handle_error("Unknown status code: [status].", ip, retried)
if(!retried)
sleep(25)
return .(ip, 1)
else
ipintel_handle_error("Unable to connect to API.", ip, retried)
if(!retried)
sleep(25)
return .(ip, 1)
/**
* Error handler
*
* Handles an IP intel error, also throttling the susbystem if required
*
* Arguments:
* * error - The error description
* * ip - The IP that was tried
* * retried - Was this on a retried attempt
*/
/datum/controller/subsystem/ipintel/proc/ipintel_handle_error(error, ip, retried)
if(retried)
errors++
error += " Could not check [ip]. Disabling IPINTEL for [errors] minute[(errors == 1 ? "" : "s")]"
throttle = world.timeofday + (2 * errors MINUTES)
else
error += " Attempting retry on [ip]."
log_ipintel(error)
/**
* Logs an IPintel error
*
* Pretty self explanatory. Logs errors regarding ipintel.
*
* Arguments:
* * text - Argument 1
*/
/datum/controller/subsystem/ipintel/proc/log_ipintel(text)
log_game("IPINTEL: [text]")
log_debug("IPINTEL: [text]")
/**
* IPIntel Ban Checker
*
* Checks if a user is banned due to IPintel. It will check configuration, DB, whitelist checks, and more
*
* Arguments:
* * t_ckey - The ckey to check
* * t_ip - The IP to check
*/
/datum/controller/subsystem/ipintel/proc/ipintel_is_banned(t_ckey, t_ip)
if(!GLOB.configuration.ipintel.contact_email)
return FALSE
if(!GLOB.configuration.ipintel.enabled)
return FALSE
if(!GLOB.configuration.ipintel.whitelist_mode)
return FALSE
if(!SSdbcore.IsConnected())
return FALSE
if(!ipintel_badip_check(t_ip))
return FALSE
if(vpn_whitelist_check(t_ckey))
return FALSE
return TRUE
/**
* IP Rating Checker
*
* Checks if a provided IP passes the config threshold for denial
*
* Arguments:
* * target_ip - The IP to check
*/
/datum/controller/subsystem/ipintel/proc/ipintel_badip_check(target_ip)
var/rating_bad = GLOB.configuration.ipintel.bad_rating
if(!rating_bad)
log_debug("ipintel_badip_check reports misconfigured rating_bad directive")
return FALSE
var/valid_hours = GLOB.configuration.ipintel.hours_save_bad
if(!valid_hours)
log_debug("ipintel_badip_check reports misconfigured ipintel_save_bad directive")
return FALSE
var/datum/db_query/query_get_ip_intel = SSdbcore.NewQuery({"
SELECT * FROM ipintel WHERE ip = INET_ATON(:target_ip)
AND intel >= :rating_bad AND (date + INTERVAL :valid_hours HOUR) > NOW()"},
list(
"target_ip" = target_ip,
"rating_bad" = rating_bad,
"valid_hours" = valid_hours
)
)
if(!query_get_ip_intel.warn_execute())
log_debug("ipintel_badip_check reports failed query execution")
qdel(query_get_ip_intel)
return FALSE
if(!query_get_ip_intel.NextRow())
qdel(query_get_ip_intel)
return FALSE
qdel(query_get_ip_intel)
return TRUE
/**
* VPN whitelist checker
*
* Checks if a ckey is whitelisted to be using a VPN against the DB
*
* Arguments:
* * target_ckey - The ckey to check
*/
/datum/controller/subsystem/ipintel/proc/vpn_whitelist_check(target_ckey)
if(!GLOB.configuration.ipintel.whitelist_mode)
return FALSE
var/datum/db_query/query_whitelist_check = SSdbcore.NewQuery("SELECT * FROM vpn_whitelist WHERE ckey=:ckey", list(
"ckey" = target_ckey
))
if(!query_whitelist_check.warn_execute())
qdel(query_whitelist_check)
return FALSE
if(query_whitelist_check.NextRow())
qdel(query_whitelist_check)
return TRUE // At least one row in the whitelist names their ckey. That means they are whitelisted.
qdel(query_whitelist_check)
return FALSE
/**
* VPN whitelist adder
*
* Adds a ckey to the VPN whitelist. Asks the admin to also provide a link to their request.
*
* Arguments:
* * target_ckey - The ckey to whitelist
*/
/datum/controller/subsystem/ipintel/proc/vpn_whitelist_add(target_ckey)
var/reason_string = input(usr, "Enter link to the URL of their whitelist request on the forum.","Reason required") as message|null
if(!reason_string)
return FALSE
var/datum/db_query/query_whitelist_add = SSdbcore.NewQuery("INSERT INTO vpn_whitelist (ckey,reason) VALUES (:targetckey, :reason)", list(
"targetckey" = target_ckey,
"reason" = reason_string
))
if(!query_whitelist_add.warn_execute())
qdel(query_whitelist_add)
return FALSE
qdel(query_whitelist_add)
return TRUE
/**
* VPN whitelist remover
*
* Removes a ckey from the VPN whitelist. Pretty simple.
*
* Arguments:
* * target_ckey - The ckey to remove
*/
/datum/controller/subsystem/ipintel/proc/vpn_whitelist_remove(target_ckey)
var/datum/db_query/query_whitelist_remove = SSdbcore.NewQuery("DELETE FROM vpn_whitelist WHERE ckey=:targetckey", list(
"targetckey" = target_ckey
))
if(!query_whitelist_remove.warn_execute())
qdel(query_whitelist_remove)
return FALSE
qdel(query_whitelist_remove)
return TRUE
/**
* VPN whitelist panel
*
* Doesnt actually open a panel, this is just a verb to handle the rest of the whitelist operations
*
* Arguments:
* * target_ckey - The ckey to add/remove
*/
/datum/controller/subsystem/ipintel/proc/vpn_whitelist_panel(target_ckey as text)
if(!check_rights(R_ADMIN))
return
if(!target_ckey)
return
var/is_already_whitelisted = vpn_whitelist_check(target_ckey)
if(is_already_whitelisted)
var/confirm = alert("[target_ckey] is already whitelisted. Remove them?", "Confirm Removal", "No", "Yes")
if(!confirm || confirm != "Yes")
to_chat(usr, "VPN whitelist alteration cancelled.")
return
else if(vpn_whitelist_remove(target_ckey))
to_chat(usr, "[target_ckey] was removed from the VPN whitelist.")
else
to_chat(usr, "VPN whitelist unchanged.")
else
if(vpn_whitelist_add(target_ckey))
to_chat(usr, "[target_ckey] was added to the VPN whitelist.")
else
to_chat(usr, "VPN whitelist unchanged.")
+25 -35
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()
@@ -750,7 +740,7 @@ SUBSYSTEM_DEF(jobs)
continue // If a client logs out in the middle of this
var/datum/db_query/exp_read = SSdbcore.NewQuery(
"SELECT exp FROM [format_table_name("player")] WHERE ckey=:ckey",
"SELECT exp FROM player WHERE ckey=:ckey",
list("ckey" = C.ckey)
)
@@ -834,7 +824,7 @@ SUBSYSTEM_DEF(jobs)
C.prefs.exp = new_exp
var/datum/db_query/update_query = SSdbcore.NewQuery(
"UPDATE [format_table_name("player")] SET exp =:newexp, lastseen=NOW() WHERE ckey=:ckey",
"UPDATE player SET exp =:newexp, lastseen=NOW() WHERE ckey=:ckey",
list(
"newexp" = new_exp,
"ckey" = C.ckey
@@ -844,7 +834,7 @@ SUBSYSTEM_DEF(jobs)
player_update_queries += update_query
var/datum/db_query/update_query_history = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("playtime_history")] (ckey, date, time_living, time_ghost)
INSERT INTO playtime_history (ckey, date, time_living, time_ghost)
VALUES (:ckey, CURDATE(), :addedliving, :addedghost)
ON DUPLICATE KEY UPDATE time_living=time_living + VALUES(time_living), time_ghost=time_ghost + VALUES(time_ghost)"},
list(
+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)
+22 -16
View File
@@ -6,6 +6,10 @@ SUBSYSTEM_DEF(mapping)
var/datum/map/map_datum
/// What map will be used next round
var/datum/map/next_map
/// List of all areas that can be accessed via IC means
var/list/teleportlocs
/// List of all areas that can be accessed via IC and OOC means
var/list/ghostteleportlocs
// This has to be here because world/New() uses [station_name()], which looks this datum up
/datum/controller/subsystem/mapping/PreInit()
@@ -40,11 +44,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,35 +61,37 @@ 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
teleportlocs = list()
for(var/area/AR in world)
if(AR.no_teleportlocs)
continue
if(GLOB.teleportlocs[AR.name])
if(teleportlocs[AR.name])
continue
var/turf/picked = safepick(get_area_turfs(AR.type))
if(picked && is_station_level(picked.z))
GLOB.teleportlocs[AR.name] = AR
teleportlocs[AR.name] = AR
GLOB.teleportlocs = sortAssoc(GLOB.teleportlocs)
teleportlocs = sortAssoc(teleportlocs)
ghostteleportlocs = list()
for(var/area/AR in world)
if(GLOB.ghostteleportlocs[AR.name])
if(ghostteleportlocs[AR.name])
continue
var/list/turfs = get_area_turfs(AR.type)
if(turfs.len)
GLOB.ghostteleportlocs[AR.name] = AR
ghostteleportlocs[AR.name] = AR
GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs)
ghostteleportlocs = sortAssoc(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 +102,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.")
@@ -128,7 +134,7 @@ SUBSYSTEM_DEF(mapping)
if(!SSdbcore.IsConnected())
return
var/datum/db_query/query_set_map = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET start_datetime=NOW(), map_name=:mapname, station_name=:stationname WHERE id=:round_id",
"UPDATE round SET start_datetime=NOW(), map_name=:mapname, station_name=:stationname WHERE id=:round_id",
list("mapname" = map_datum.technical_name, "stationname" = map_datum.fluff_name, "round_id" = GLOB.round_id)
)
query_set_map.Execute(async = FALSE) // This happens during a time of intense server lag, so should be non-async
@@ -230,11 +236,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
View File
@@ -9,6 +9,8 @@ SUBSYSTEM_DEF(mobs)
var/static/list/clients_by_zlevel[][]
var/static/list/dead_players_by_zlevel[][] = list(list()) // Needs to support zlevel 1 here, MaxZChanged only happens when CC is created and new_players can login before that.
var/static/list/cubemonkeys = list()
/// The amount of giant spiders that exist in the world. Used for mob capping.
var/giant_spiders = 0
/datum/controller/subsystem/mobs/stat_entry()
..("P:[GLOB.mob_living_list.len]")
+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)
+2 -2
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 ..()
@@ -18,7 +18,7 @@ SUBSYSTEM_DEF(statistics)
return
else
var/datum/db_query/statquery = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time) VALUES (:playercount, :admincount, NOW())",
"INSERT INTO legacy_population (playercount, admincount, time) VALUES (:playercount, :admincount, NOW())",
list(
"playercount" = length(GLOB.clients),
"admincount" = length(GLOB.admins)
+19 -13
View File
@@ -7,10 +7,12 @@ SUBSYSTEM_DEF(ticker)
runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME
offline_implications = "The game is no longer aware of when the round ends. Immediate server restart recommended."
/// Time the world started, relative to world.time
/// Time the game should start, relative to world.time
var/round_start_time = 0
/// Time that the round started
var/time_game_started = 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 +81,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 +116,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 +131,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 +151,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 +159,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 +169,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.")
@@ -264,10 +268,10 @@ SUBSYSTEM_DEF(ticker)
SSdiscord.send2discord_simple_noadmins("**\[Info]** Round has started")
auto_toggle_ooc(FALSE) // Turn it off
round_start_time = world.time
time_game_started = 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 +283,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)