mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-11 15:14:27 +01:00
Merge branch 'master' into ghost-rad-hud
This commit is contained in:
@@ -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,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]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 ""
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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]!")
|
||||
|
||||
@@ -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]")
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user