Merge branch 'master' into tgglassfloors

This commit is contained in:
S34NW
2021-08-05 15:17:09 +01:00
456 changed files with 7608 additions and 8114 deletions
+28 -11
View File
@@ -28,26 +28,26 @@
admin = 1
//Guest Checking
if(!GLOB.guests_allowed && IsGuestKey(key))
if(GLOB.configuration.general.guest_ban && IsGuestKey(key))
log_adminwarn("Failed Login: [key] [computer_id] [address] - Guests not allowed")
// message_admins("<span class='notice'>Failed Login: [key] - Guests not allowed</span>")
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_BANNED)
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
//check if the IP address is a known proxy/vpn, and the user is not whitelisted
if(check_ipintel && config.ipintel_email && config.ipintel_whitelist && ipintel_is_banned(key, address))
if(check_ipintel && GLOB.configuration.ipintel.contact_email && GLOB.configuration.ipintel.whitelist_mode && SSipintel.ipintel_is_banned(key, address))
log_adminwarn("Failed Login: [key] [computer_id] [address] - Proxy/VPN")
var/mistakemessage = ""
if(config.banappeals)
mistakemessage = "\nIf you have to use one, request whitelisting at: [config.banappeals]"
if(GLOB.configuration.url.banappeals_url)
mistakemessage = "\nIf you have to use one, request whitelisting at: [GLOB.configuration.url.banappeals_url]"
INVOKE_ASYNC(GLOBAL_PROC, .proc/log_connection, ckey(key), address, computer_id, CONNECTION_TYPE_DROPPED_IPINTEL)
return list("reason"="using proxy or vpn", "desc"="\nReason: Proxies/VPNs are not allowed here. [mistakemessage]")
// If 2FA is enabled, makes sure they were authed within the last minute
if(check_2fa && config._2fa_auth_host)
if(check_2fa && GLOB.configuration.system._2fa_auth_host)
// First see if they exist at all
var/datum/db_query/check_query = SSdbcore.NewQuery("SELECT 2fa_status, ip FROM [format_table_name("player")] WHERE ckey=:ckey", list("ckey" = ckey(key)))
var/datum/db_query/check_query = SSdbcore.NewQuery("SELECT 2fa_status, ip FROM player WHERE ckey=:ckey", list("ckey" = ckey(key)))
if(!check_query.warn_execute())
message_admins("Failed to do a DB 2FA check for [key]. You have been warned.")
@@ -71,7 +71,7 @@
// Have it set to always check, or their IP is different
if(_2fa_enabled && (always_check || (address != last_ip)))
// They have 2FA enabled, lets make sure they have authed within the last minute
var/datum/db_query/verify_query = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("2fa_secrets")] WHERE (last_time BETWEEN NOW() - INTERVAL 1 MINUTE AND NOW()) AND ckey=:ckey LIMIT 1", list(
var/datum/db_query/verify_query = SSdbcore.NewQuery("SELECT ckey FROM 2fa_secrets WHERE (last_time BETWEEN NOW() - INTERVAL 1 MINUTE AND NOW()) AND ckey=:ckey LIMIT 1", list(
"ckey" = ckey(key)
))
@@ -87,7 +87,24 @@
qdel(verify_query)
if(config.ban_legacy_system)
if(SSdbcore.IsConnected())
// If we have a DB, see if the player has been seen before
var/datum/db_query/exist_query = SSdbcore.NewQuery("SELECT ckey FROM player WHERE ckey=:ckey", list(
"ckey" = ckey
))
// If we didnt execute, skip this part
if(!exist_query.warn_execute())
qdel(exist_query)
else
if(!exist_query.NextRow()) // If there isnt a row, they aint been seen before
if(GLOB.panic_bunker_enabled)
qdel(exist_query)
var/threshold = GLOB.configuration.general.panic_bunker_threshold
return list("reason" = "panic bunker", "desc" = "Server is not accepting connections from never-before-seen players until player count is less than [threshold]. Please try again later.")
qdel(exist_query)
if(!GLOB.configuration.general.use_database_bans)
//Ban Checking
. = CheckBan(ckey(key), computer_id, address)
if(.)
@@ -120,7 +137,7 @@
sql_query_params["cid"] = computer_id
var/datum/db_query/query = SSdbcore.NewQuery({"
SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype, ban_round_id FROM [format_table_name("ban")]
SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype, ban_round_id FROM ban
WHERE (ckey=:ckeytext [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN'
OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)"}, sql_query_params)
@@ -159,8 +176,8 @@
expires = " The ban is for [duration] minutes and expires on [expiration] (server time)."
else
var/appealmessage = ""
if(config.banappeals)
appealmessage = " You may appeal it at <a href='[config.banappeals]'>[config.banappeals]</a>."
if(GLOB.configuration.url.banappeals_url)
appealmessage = " You may appeal it at <a href='[GLOB.configuration.url.banappeals_url]'>[GLOB.configuration.url.banappeals_url]</a>."
expires = " This ban does not expire automatically and must be appealed.[appealmessage]"
var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime][ban_round_id ? " (Round [ban_round_id])" : ""].[expires]"
+2 -2
View File
@@ -10,8 +10,8 @@ GLOBAL_PROTECT(banlist_savefile) // Obvious reasons
. = list()
var/appeal
if(config && config.banappeals)
appeal = "\nFor more information on your ban, or to appeal, head to <a href='[config.banappeals]'>[config.banappeals]</a>"
if(GLOB.configuration.url.banappeals_url)
appeal = "\nFor more information on your ban, or to appeal, head to <a href='[GLOB.configuration.url.banappeals_url]'>[GLOB.configuration.url.banappeals_url]</a>"
GLOB.banlist_savefile.cd = "/base"
if( "[ckey][id]" in GLOB.banlist_savefile.dir )
GLOB.banlist_savefile.cd = "[ckey][id]"
+29 -23
View File
@@ -91,8 +91,8 @@ GLOBAL_VAR_INIT(nologevent, 0)
else
body += "\[[M.client.holder ? M.client.holder.rank : "Player"]\] "
body += "\[<A href='?_src_=holder;getplaytimewindow=[M.UID()]'>" + M.client.get_exp_type(EXP_TYPE_CREW) + " as [EXP_TYPE_CREW]</a>\]"
body += "<br>BYOND account registration date: [M.client.byondacc_date || "ERROR"] [M.client.byondacc_age <= config.byond_account_age_threshold ? "<b>" : ""]([M.client.byondacc_age] days old)[M.client.byondacc_age <= config.byond_account_age_threshold ? "</b>" : ""]"
body += "<br>Global Ban DB Lookup: [config.centcom_ban_db_url ? "<a href='?_src_=holder;open_ccbdb=[M.client.ckey]'>Lookup</a>" : "<i>Disabled</i>"]"
body += "<br>BYOND account registration date: [M.client.byondacc_date || "ERROR"] [M.client.byondacc_age <= GLOB.configuration.general.byond_account_age_threshold ? "<b>" : ""]([M.client.byondacc_age] days old)[M.client.byondacc_age <= GLOB.configuration.general.byond_account_age_threshold ? "</b>" : ""]"
body += "<br>Global Ban DB Lookup: [GLOB.configuration.url.centcom_ban_db_url ? "<a href='?_src_=holder;open_ccbdb=[M.client.ckey]'>Lookup</a>" : "<i>Disabled</i>"]"
body += "<br>"
@@ -127,7 +127,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
body += "<A href='?_src_=holder;appearanceban=[M.UID()];dbbanaddckey=[M.ckey]'>Appearance Ban</A> | "
body += "<A href='?_src_=holder;shownoteckey=[M.ckey]'>Notes</A> | "
body += "<A href='?_src_=holder;viewkarma=[M.ckey]'>View Karma</A> | "
if(config.forum_playerinfo_url)
if(GLOB.configuration.url.forum_playerinfo_url)
body += "<A href='?_src_=holder;webtools=[M.ckey]'>WebInfo</A> | "
if(M.client)
if(check_watchlist(M.client.ckey))
@@ -315,7 +315,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
return
var/key = stripped_input(usr, "Enter ckey to add/remove, or leave blank to cancel:", "VPN Whitelist add/remove", max_length=32)
if(key)
vpn_whitelist_panel(key)
SSipintel.vpn_whitelist_panel(key)
/datum/admins/proc/Jobbans()
if(!check_rights(R_BAN))
@@ -462,8 +462,8 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_ADMIN))
return
config.looc_allowed = !(config.looc_allowed)
if(config.looc_allowed)
GLOB.looc_enabled = !(GLOB.looc_enabled)
if(GLOB.looc_enabled)
to_chat(world, "<B>The LOOC channel has been globally enabled!</B>")
else
to_chat(world, "<B>The LOOC channel has been globally disabled!</B>")
@@ -478,8 +478,8 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_ADMIN))
return
config.dsay_allowed = !(config.dsay_allowed)
if(config.dsay_allowed)
GLOB.dsay_enabled = !(GLOB.dsay_enabled)
if(GLOB.dsay_enabled)
to_chat(world, "<B>Deadchat has been globally enabled!</B>")
else
to_chat(world, "<B>Deadchat has been globally disabled!</B>")
@@ -495,7 +495,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_ADMIN))
return
config.dooc_allowed = !( config.dooc_allowed )
GLOB.dooc_enabled = !(GLOB.dooc_enabled)
log_admin("[key_name(usr)] toggled Dead OOC.")
message_admins("[key_name_admin(usr)] toggled Dead OOC.", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Dead OOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -508,7 +508,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_ADMIN))
return
config.disable_ooc_emoji = !(config.disable_ooc_emoji)
GLOB.configuration.general.enable_ooc_emoji = !(GLOB.configuration.general.enable_ooc_emoji)
log_admin("[key_name(usr)] toggled OOC Emoji.")
message_admins("[key_name_admin(usr)] toggled OOC Emoji.", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle OOC Emoji")
@@ -525,7 +525,7 @@ GLOBAL_VAR_INIT(nologevent, 0)
alert("Unable to start the game as it is not set up.")
return
if(config.start_now_confirmation)
if(GLOB.configuration.general.start_now_confirmation)
if(alert(usr, "This is a live server. Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
return
@@ -568,8 +568,9 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_EVENT))
return
config.allow_ai = !( config.allow_ai )
if(!( config.allow_ai ))
GLOB.configuration.jobs.allow_ai = !(GLOB.configuration.jobs.allow_ai)
if(!GLOB.configuration.jobs.allow_ai)
to_chat(world, "<B>The AI job is no longer chooseable.</B>")
else
to_chat(world, "<B>The AI job is chooseable now.</B>")
@@ -586,13 +587,13 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_SERVER))
return
GLOB.abandon_allowed = !( GLOB.abandon_allowed )
if(GLOB.abandon_allowed)
GLOB.configuration.general.respawn_enabled = !(GLOB.configuration.general.respawn_enabled)
if(GLOB.configuration.general.respawn_enabled)
to_chat(world, "<B>You may now respawn.</B>")
else
to_chat(world, "<B>You may no longer respawn :(</B>")
message_admins("[key_name_admin(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].", 1)
log_admin("[key_name(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].")
to_chat(world, "<B>You may no longer respawn</B>")
message_admins("[key_name_admin(usr)] toggled respawn to [GLOB.configuration.general.respawn_enabled ? "On" : "Off"].", 1)
log_admin("[key_name(usr)] toggled respawn to [GLOB.configuration.general.respawn_enabled ? "On" : "Off"].")
world.update_status()
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Respawn") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -724,13 +725,13 @@ GLOBAL_VAR_INIT(nologevent, 0)
if(!check_rights(R_SERVER))
return
GLOB.guests_allowed = !( GLOB.guests_allowed )
if(!( GLOB.guests_allowed ))
GLOB.configuration.general.guest_ban = !(GLOB.configuration.general.guest_ban)
if(GLOB.configuration.general.guest_ban)
to_chat(world, "<B>Guests may no longer enter the game.</B>")
else
to_chat(world, "<B>Guests may now enter the game.</B>")
log_admin("[key_name(usr)] toggled guests game entering [GLOB.guests_allowed ? "" : "dis"]allowed.")
message_admins("<span class='notice'>[key_name_admin(usr)] toggled guests game entering [GLOB.guests_allowed ? "" : "dis"]allowed.</span>", 1)
log_admin("[key_name(usr)] toggled guests game entering [GLOB.configuration?.general.guest_ban ? "dis" : ""]allowed.")
message_admins("<span class='notice'>[key_name_admin(usr)] toggled guests game entering [GLOB.configuration?.general.guest_ban ? "dis" : ""]allowed.</span>", 1)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Guests") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/output_ai_laws()
@@ -787,9 +788,15 @@ GLOBAL_VAR_INIT(gamma_ship_location, 1) // 0 = station , 1 = space
if(GLOB.gamma_ship_location == 1)
fromArea = locate(/area/shuttle/gamma/space)
toArea = locate(/area/shuttle/gamma/station)
for(var/obj/machinery/door/airlock/hatch/gamma/H in GLOB.airlocks)
H.unlock(TRUE)
GLOB.event_announcement.Announce("Central Command has deployed the Gamma Armory shuttle.", new_sound = 'sound/AI/commandreport.ogg')
else
fromArea = locate(/area/shuttle/gamma/station)
toArea = locate(/area/shuttle/gamma/space)
for(var/obj/machinery/door/airlock/hatch/gamma/H in GLOB.airlocks)
H.lock(TRUE)
GLOB.event_announcement.Announce("Central Command has recalled the Gamma Armory shuttle.", new_sound = 'sound/AI/commandreport.ogg')
fromArea.move_contents_to(toArea)
for(var/obj/machinery/mech_bay_recharge_port/P in toArea)
@@ -917,4 +924,3 @@ GLOBAL_VAR_INIT(gamma_ship_location, 1) // 0 = station , 1 = space
continue
result[1]++
return result
+1 -1
View File
@@ -43,7 +43,7 @@
watchlist_show()
if("hrefs") //persistant logs and stuff
if(config && config.log_hrefs)
if(GLOB.configuration.logging.href_logging)
if(GLOB.world_href_log)
src << browse(file(GLOB.world_href_log), "window=investigate[subject];size=800x300")
else
+8 -8
View File
@@ -22,7 +22,7 @@
switch(task)
if("Write")
var/datum/db_query/query_memocheck = SSdbcore.NewQuery(
"SELECT ckey FROM [format_table_name("memo")] WHERE ckey=:ckey",
"SELECT ckey FROM memo WHERE ckey=:ckey",
list("ckey" = ckey)
)
@@ -41,7 +41,7 @@
return
var/datum/db_query/query_memoadd = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("memo")] (ckey, memotext, timestamp) VALUES (:ckey, :memotext, NOW())",
"INSERT INTO memo (ckey, memotext, timestamp) VALUES (:ckey, :memotext, NOW())",
list(
"ckey" = ckey,
"memotext" = memotext
@@ -57,7 +57,7 @@
qdel(query_memoadd)
if("Edit")
var/datum/db_query/query_memolist = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
var/datum/db_query/query_memolist = SSdbcore.NewQuery("SELECT ckey FROM memo")
if(!query_memolist.warn_execute())
qdel(query_memolist)
@@ -78,7 +78,7 @@
return
var/datum/db_query/query_memofind = SSdbcore.NewQuery(
"SELECT memotext FROM [format_table_name("memo")] WHERE ckey=:ckey",
"SELECT memotext FROM memo WHERE ckey=:ckey",
list("ckey" = target_ckey)
)
@@ -96,7 +96,7 @@
var/edit_text = "Edited by [target_ckey] on [SQLtime()] from<br>[old_memo]<br>to<br>[new_memo]<hr>"
var/datum/db_query/update_query = SSdbcore.NewQuery(
"UPDATE [format_table_name("memo")] SET memotext=:newmemo, last_editor=:lasteditor, edits=CONCAT(IFNULL(edits,''),:edittext) WHERE ckey=:targetckey",
"UPDATE memo SET memotext=:newmemo, last_editor=:lasteditor, edits=CONCAT(IFNULL(edits,''),:edittext) WHERE ckey=:targetckey",
list(
"newmemo" = new_memo,
"lasteditor" = ckey,
@@ -120,7 +120,7 @@
qdel(query_memofind)
if("Show")
var/datum/db_query/query_memoshow = SSdbcore.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM [format_table_name("memo")]")
var/datum/db_query/query_memoshow = SSdbcore.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM memo")
if(!query_memoshow.warn_execute())
qdel(query_memoshow)
return
@@ -141,7 +141,7 @@
qdel(query_memoshow)
if("Remove")
var/datum/db_query/query_memodellist = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("memo")]")
var/datum/db_query/query_memodellist = SSdbcore.NewQuery("SELECT ckey FROM memo")
if(!query_memodellist.warn_execute())
qdel(query_memodellist)
return
@@ -161,7 +161,7 @@
return
var/datum/db_query/query_memodel = SSdbcore.NewQuery(
"DELETE FROM [format_table_name("memo")] WHERE ckey=:ckey",
"DELETE FROM memo WHERE ckey=:ckey",
list("ckey" = target_ckey)
)
+15 -41
View File
@@ -7,25 +7,15 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
var/previous_rights = 0
//load text from file
var/list/Lines = file2list("config/admin_ranks.txt")
//process each line seperately
for(var/line in Lines)
if(!length(line)) continue
if(copytext(line,1,2) == "#") continue
var/list/List = splittext(line,"+")
if(!List.len) continue
var/rank = ckeyEx(List[1])
switch(rank)
if(null,"") continue
if("Removed") continue //Reserved
// Process each rank set seperately
// key: rank name | value: list of rights
for(var/rankname in GLOB.configuration.admin.rank_rights_map)
var/list/rank_right_tokens = GLOB.configuration.admin.rank_rights_map[rankname]
var/rights = 0
for(var/i=2, i<=List.len, i++)
switch(ckey(List[i]))
for(var/right_token in rank_right_tokens)
var/token = lowertext(splittext(right_token, "+")[2])
switch(token)
if("@","prev") rights |= previous_rights
if("buildmode","build") rights |= R_BUILDMODE
if("admin") rights |= R_ADMIN
@@ -46,7 +36,7 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
if("proccall") rights |= R_PROCCALL
if("viewruntimes") rights |= R_VIEWRUNTIMES
GLOB.admin_ranks[rank] = rights
GLOB.admin_ranks[rankname] = rights
previous_rights = rights
#ifdef TESTING
@@ -73,29 +63,13 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
for(var/A in world.GetConfig("admin"))
world.SetConfig("APP/admin", A, null)
if(config.admin_legacy_system)
if(!GLOB.configuration.admin.use_database_admins)
load_admin_ranks()
//load text from file
var/list/Lines = file2list("config/admins.txt")
//process each line seperately
for(var/line in Lines)
if(!length(line)) continue
if(copytext(line,1,2) == "#") continue
//Split the line at every "-"
var/list/List = splittext(line, "-")
if(!List.len) continue
//ckey is before the first "-"
var/ckey = ckey(List[1])
if(!ckey) continue
//rank follows the first "-"
var/rank = ""
if(List.len >= 2)
rank = ckeyEx(List[2])
for(var/iterator_key in GLOB.configuration.admin.ckey_rank_map)
var/ckey = ckey(iterator_key) // Snip out formatting
var/rank = GLOB.configuration.admin.ckey_rank_map[iterator_key]
//load permissions associated with this rank
var/rights = GLOB.admin_ranks[rank]
@@ -113,11 +87,11 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
//The current admin system uses SQL
if(!SSdbcore.IsConnected())
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
config.admin_legacy_system = 1
GLOB.configuration.admin.use_database_admins = FALSE
load_admins()
return
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, admin_rank, level, flags FROM [format_table_name("admin")]")
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, admin_rank, level, flags FROM admin")
if(!query.warn_execute(async=run_async))
qdel(query)
return
@@ -141,7 +115,7 @@ GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons
if(!GLOB.admin_datums)
log_world("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.")
config.admin_legacy_system = 1
GLOB.configuration.admin.use_database_admins = FALSE
load_admins()
return
+17 -37
View File
@@ -137,7 +137,6 @@ GLOBAL_LIST_INIT(admin_verbs_server, list(
/client/proc/toggle_antagHUD_restrictions,
/client/proc/set_ooc,
/client/proc/reset_ooc,
/client/proc/toggledrones,
/client/proc/set_next_map
))
GLOBAL_LIST_INIT(admin_verbs_debug, list(
@@ -403,7 +402,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
if(!check_rights(R_BAN))
return
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
holder.unbanpanel()
else
holder.DB_ban_panel()
@@ -679,28 +678,20 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
var/datum/admins/D = GLOB.admin_datums[ckey]
var/rank = null
if(config.admin_legacy_system)
//load text from file
var/list/Lines = file2list("config/admins.txt")
for(var/line in Lines)
if(findtext(line, "#")) // Skip comments
if(!GLOB.configuration.admin.use_database_admins)
for(var/iterator_key in GLOB.configuration.admin.ckey_rank_map)
var/_ckey = ckey(iterator_key) // Snip out formatting
if(ckey != _ckey)
continue
var/list/splitline = splittext(line, " - ")
if(length(splitline) != 2) // Always 'ckey - rank'
continue
if(lowertext(splitline[1]) == ckey)
rank = ckeyEx(splitline[2])
break
continue
rank = GLOB.configuration.admin.ckey_rank_map[iterator_key]
break
else
if(!SSdbcore.IsConnected())
to_chat(src, "Warning, MYSQL database is not connected.")
return
var/datum/db_query/rank_read = SSdbcore.NewQuery(
"SELECT admin_rank FROM [format_table_name("admin")] WHERE ckey=:ckey",
"SELECT admin_rank FROM admin WHERE ckey=:ckey",
list("ckey" = ckey)
)
@@ -713,7 +704,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
qdel(rank_read)
if(!D)
if(config.admin_legacy_system)
if(!GLOB.configuration.admin.use_database_admins)
if(GLOB.admin_ranks[rank] == null)
error("Error while re-adminning [src], admin rank ([rank]) does not exist.")
to_chat(src, "Error while re-adminning, admin rank ([rank]) does not exist.")
@@ -726,7 +717,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
return
var/datum/db_query/admin_read = SSdbcore.NewQuery(
"SELECT ckey, admin_rank, flags FROM [format_table_name("admin")] WHERE ckey=:ckey",
"SELECT ckey, admin_rank, flags FROM admin WHERE ckey=:ckey",
list("ckey" = ckey)
)
@@ -773,13 +764,13 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
if(!check_rights(R_SERVER))
return
if(config)
if(config.log_hrefs)
config.log_hrefs = 0
to_chat(src, "<b>Stopped logging hrefs</b>")
else
config.log_hrefs = 1
to_chat(src, "<b>Started logging hrefs</b>")
// Why would we ever turn this off?
if(GLOB.configuration.logging.href_logging)
GLOB.configuration.logging.href_logging = FALSE
to_chat(src, "<b>Stopped logging hrefs</b>")
else
GLOB.configuration.logging.href_logging = TRUE
to_chat(src, "<b>Started logging hrefs</b>")
/client/proc/check_ai_laws()
set name = "Check AI Laws"
@@ -956,17 +947,6 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
else
to_chat(usr, "You now will get admin ticket messages.")
/client/proc/toggledrones()
set name = "Toggle Maintenance Drones"
set category = "Server"
if(!check_rights(R_SERVER))
return
config.allow_drone_spawn = !(config.allow_drone_spawn)
log_admin("[key_name(usr)] has [config.allow_drone_spawn ? "enabled" : "disabled"] maintenance drones.")
message_admins("[key_name_admin(usr)] has [config.allow_drone_spawn ? "enabled" : "disabled"] maintenance drones.")
/client/proc/toggledebuglogs()
set name = "Toggle Debug Log Messages"
set category = "Preferences"
+4 -3
View File
@@ -40,8 +40,9 @@ DEBUG
appearance_loadbanfile()
*/
// AA 2020-11-25: This entire proc isnt even called. What the actual fuck.
// AA 2021-05-23: This entire proc STILL isnt even called. I am going to screan.
/proc/appearance_loadbanfile()
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
var/savefile/S=new("data/appearance_full.ban")
S["keys[0]"] >> GLOB.appearance_keylist
log_admin("Loading appearance_rank")
@@ -53,12 +54,12 @@ DEBUG
else
if(!SSdbcore.IsConnected())
log_world("Database connection failed. Reverting to the legacy ban system.")
config.ban_legacy_system = 1
GLOB.configuration.general.use_database_bans = FALSE
appearance_loadbanfile()
return
//appearance bans
var/datum/db_query/appearanceban_query = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1")
var/datum/db_query/appearanceban_query = SSdbcore.NewQuery("SELECT ckey FROM ban WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1")
if(!appearanceban_query.warn_execute())
qdel(appearanceban_query)
+13 -13
View File
@@ -17,7 +17,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
return
GLOB.jobban_keylist.Add(text("[M.ckey] - [rank] ## [reason]"))
jobban_assoc_insert(M.ckey, rank, reason)
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
jobban_savebanfile()
/proc/jobban_client_fullban(ckey, rank)
@@ -25,7 +25,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
return
GLOB.jobban_keylist.Add(text("[ckey] - [rank]"))
jobban_assoc_insert(ckey, rank)
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
jobban_savebanfile()
//returns a reason if M is banned from rank, returns 0 otherwise
@@ -33,7 +33,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
if(!M || !rank)
return 0
if(config.guest_jobban && guest_jobbans(rank))
if(GLOB.configuration.jobs.guest_job_ban && guest_jobbans(rank))
if(IsGuestKey(M.key))
return "Guest Job-ban"
@@ -46,7 +46,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
if(!ckey || !rank)
return null
if(config.guest_jobban && guest_jobbans(rank))
if(GLOB.configuration.jobs.guest_job_ban && guest_jobbans(rank))
if(IsGuestKey(ckey))
return "Guest Job-ban"
@@ -56,7 +56,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
return null
/proc/jobban_loadbanfile()
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
var/savefile/S=new("data/job_full.ban")
S["keys[0]"] >> GLOB.jobban_keylist
log_admin("Loading jobban_rank")
@@ -74,12 +74,12 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
else
if(!SSdbcore.IsConnected())
log_world("Database connection failed. Reverting to the legacy ban system.")
config.ban_legacy_system = 1
GLOB.configuration.general.use_database_bans = FALSE
jobban_loadbanfile()
return
//Job permabans
var/datum/db_query/permabans = SSdbcore.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
var/datum/db_query/permabans = SSdbcore.NewQuery("SELECT ckey, job FROM ban WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)")
if(!permabans.warn_execute(async=FALSE))
qdel(permabans)
@@ -94,7 +94,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
qdel(permabans)
// Job tempbans
var/datum/db_query/tempbans = SSdbcore.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
var/datum/db_query/tempbans = SSdbcore.NewQuery("SELECT ckey, job FROM ban WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()")
if(!tempbans.warn_execute(async=FALSE))
qdel(tempbans)
@@ -132,7 +132,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
else
log_runtime(EXCEPTION("Failed to remove malformed job ban from associative list: [X]"))
GLOB.jobban_keylist.Remove(GLOB.jobban_keylist[i])
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
jobban_savebanfile()
return 1
return 0
@@ -144,7 +144,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
if(!client || !ckey)
return
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
//using the legacy .txt ban system
to_chat(src, "The server is using the legacy ban system. Ask an administrator for help!")
@@ -152,7 +152,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
//using the SQL ban system
var/is_actually_banned = FALSE
var/datum/db_query/select_query = SSdbcore.NewQuery({"
SELECT bantime, bantype, reason, job, duration, expiration_time, a_ckey FROM [format_table_name("ban")]
SELECT bantime, bantype, reason, job, duration, expiration_time, a_ckey FROM ban
WHERE ckey LIKE :ckey AND ((bantype like 'JOB_TEMPBAN' AND expiration_time > Now()) OR (bantype like 'JOB_PERMABAN')) AND isnull(unbanned)
ORDER BY bantime DESC LIMIT 100"},
list("ckey" = ckey)
@@ -182,7 +182,7 @@ GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ##
qdel(select_query)
if(is_actually_banned)
if(config.banappeals)
to_chat(src, "<span class='warning'>You can appeal the bans at: [config.banappeals]</span>")
if(GLOB.configuration.url.banappeals_url)
to_chat(src, "<span class='warning'>You can appeal the bans at: [GLOB.configuration.url.banappeals_url]</span>")
else
to_chat(src, "<span class='warning'>You have no active jobbans!</span>")
+2 -2
View File
@@ -14,7 +14,7 @@
*/
/datum/admins/proc/create_ccbdb_lookup(ckey)
// Bail if disabled
if(!config.centcom_ban_db_url)
if(!GLOB.configuration.url.centcom_ban_db_url)
to_chat(usr, "<span class='warning'>The CentCom Ban DB lookup is disabled. Please inform a maintainer or server host.</span>")
return
// Bail if no ckey is supplied
@@ -22,7 +22,7 @@
return
var/datum/callback/cb = CALLBACK(src, /datum/admins/.proc/ccbdb_lookup_callback, usr, ckey)
SShttp.create_async_request(RUSTG_HTTP_METHOD_GET, "[config.centcom_ban_db_url][ckey]", proc_callback=cb)
SShttp.create_async_request(RUSTG_HTTP_METHOD_GET, "[GLOB.configuration.url.centcom_ban_db_url][ckey]", proc_callback=cb)
/**
* CCBDB Lookup Callback
+2 -2
View File
@@ -35,7 +35,7 @@
var/has_note = FALSE
var/raw_text = ""
// Now lets see if we have a note logging the infraction in the past
var/datum/db_query/check_existing_note = SSdbcore.NewQuery("SELECT notetext FROM [format_table_name("notes")] WHERE ckey=:ckey AND adminckey=:ackey", list(
var/datum/db_query/check_existing_note = SSdbcore.NewQuery("SELECT notetext FROM notes WHERE ckey=:ckey AND adminckey=:ackey", list(
"ckey" = cookie_holder_ckey,
"ackey" = COOKIERECORD_PSUEDO_CKEY
))
@@ -99,7 +99,7 @@
serialized_text = serialized_list.Join("<br>")
if(has_note) // They have a note. Update.
var/datum/db_query/update_existing_note = SSdbcore.NewQuery("UPDATE [format_table_name("notes")] SET notetext=:nt, timestamp=NOW(), round_id=:rid WHERE ckey=:ckey AND adminckey=:ackey", list(
var/datum/db_query/update_existing_note = SSdbcore.NewQuery("UPDATE notes SET notetext=:nt, timestamp=NOW(), round_id=:rid WHERE ckey=:ckey AND adminckey=:ackey", list(
"nt" = serialized_text,
"rid" = GLOB.round_id,
"ckey" = cookie_holder_ckey,
+11 -11
View File
@@ -86,7 +86,7 @@
message_admins("<font color='red'>[key_name_admin(usr)] attempted to add a ban based on a non-existent mob, with no ckey provided. Report this bug.",1)
return
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey=:ckey", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id FROM player WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
@@ -131,7 +131,7 @@
adminwho += ", [C]"
if(maxadminbancheck)
var/datum/db_query/adm_query = SSdbcore.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey=:a_ckey) AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)", list(
var/datum/db_query/adm_query = SSdbcore.NewQuery("SELECT count(id) AS num FROM ban WHERE (a_ckey=:a_ckey) AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)", list(
"a_ckey" = a_ckey
))
if(!adm_query.warn_execute())
@@ -146,7 +146,7 @@
qdel(adm_query)
var/datum/db_query/query_insert = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`,`ban_round_id`,`unbanned_round_id`)
INSERT INTO ban (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`,`ban_round_id`,`unbanned_round_id`)
VALUES (null, Now(), :serverip, :bantype_str, :reason, :job, :duration, :rounds, Now() + INTERVAL :duration MINUTE, :ckey, :computerid, :ip, :a_ckey, :a_computerid, :a_ip, :who, :adminwho, '', null, null, null, null, null, :roundid, null)
"}, list(
// Get ready for parameters
@@ -233,7 +233,7 @@
else
bantype_sql = "bantype = '[bantype_str]'"
var/sql = "SELECT id FROM [format_table_name("ban")] WHERE ckey=:ckey AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
var/sql = "SELECT id FROM ban WHERE ckey=:ckey AND [bantype_sql] AND (unbanned is null OR unbanned = false)"
var/list/sql_params = list(
"ckey" = ckey
)
@@ -283,7 +283,7 @@
to_chat(usr, "Cancelled")
return
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, duration, reason, job FROM [format_table_name("ban")] WHERE id=:banid", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, duration, reason, job FROM ban WHERE id=:banid", list(
"banid" = banid
))
if(!query.warn_execute())
@@ -318,7 +318,7 @@
return
var/edit_reason = "- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>"
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET reason=:value, edits = CONCAT(IFNULL(edits,''), :edittext) WHERE id=:banid", list(
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE ban SET reason=:value, edits = CONCAT(IFNULL(edits,''), :edittext) WHERE id=:banid", list(
"edittext" = edit_reason,
"banid" = banid,
"value" = value
@@ -337,7 +337,7 @@
return
var/edittext = "- [eckey] changed ban duration from [duration] to [value]<br>"
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET duration=:value, edits = CONCAT(IFNULL(edits, ''), :edittext), expiration_time = DATE_ADD(bantime, INTERVAL :value MINUTE) WHERE id=:banid", list(
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE ban SET duration=:value, edits = CONCAT(IFNULL(edits, ''), :edittext), expiration_time = DATE_ADD(bantime, INTERVAL :value MINUTE) WHERE id=:banid", list(
"edittext" = edittext,
"banid" = banid,
"value" = value
@@ -373,7 +373,7 @@
var/ban_number = 0 //failsafe
var/pckey
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE id=:banid", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM ban WHERE id=:banid", list(
"banid" = id
))
if(!query.warn_execute())
@@ -400,7 +400,7 @@
var/unban_computerid = src.owner:computer_id
var/unban_ip = src.owner:address
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey=:unban_ckey, unbanned_computerid=:unban_computerid, unbanned_ip=:unban_ip, unbanned_round_id=:roundid WHERE id=:id", list(
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE ban SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey=:unban_ckey, unbanned_computerid=:unban_computerid, unbanned_ip=:unban_ip, unbanned_round_id=:roundid WHERE id=:id", list(
"unban_ckey" = unban_ckey,
"unban_computerid" = unban_computerid,
"unban_ip" = unban_ip,
@@ -587,7 +587,7 @@
var/datum/db_query/select_query = SSdbcore.NewQuery({"
SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid, ban_round_id, unbanned_round_id
FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100"}, sql_params)
FROM ban WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100"}, sql_params)
if(!select_query.warn_execute())
qdel(select_query)
@@ -673,7 +673,7 @@
/proc/flag_account_for_forum_sync(ckey)
if(!SSdbcore.IsConnected())
return
var/datum/db_query/adm_query = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET fupdate = 1 WHERE ckey=:ckey", list(
var/datum/db_query/adm_query = SSdbcore.NewQuery("UPDATE player SET fupdate = 1 WHERE ckey=:ckey", list(
"ckey" = ckey
))
// We do nothing with output here so we dont need to wrap the warn_execute() inside an if statement
-247
View File
@@ -1,247 +0,0 @@
/datum/ipintel
var/ip
var/intel = 0
var/cache = FALSE
var/cacheminutesago = 0
var/cachedate = ""
var/cacherealtime = 0
/datum/ipintel/New()
cachedate = SQLtime()
cacherealtime = world.realtime
/datum/ipintel/proc/is_valid()
. = FALSE
if(intel < 0)
return
if(intel <= config.ipintel_rating_bad)
if(world.realtime < cacherealtime + (config.ipintel_save_good HOURS))
return TRUE
else
if(world.realtime < cacherealtime + (config.ipintel_save_bad HOURS))
return TRUE
/proc/get_ip_intel(ip, bypasscache = FALSE, updatecache = TRUE)
var/datum/ipintel/res = new()
res.ip = ip
. = res
if(!ip || !config.ipintel_email || !SSipintel.enabled)
return
if(!bypasscache)
var/datum/ipintel/cachedintel = SSipintel.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 [format_table_name("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" = config.ipintel_rating_bad,
"save_good" = config.ipintel_save_good,
"save_bad" = config.ipintel_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)
SSipintel.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)
SSipintel.cache[ip] = res
if(SSdbcore.IsConnected())
var/datum/db_query/query_add_ip_intel = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("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)
/proc/ip_intel_query(ip, retryed=0)
. = -1 //default
if(!ip)
return
if(SSipintel.throttle > world.timeofday)
return
if(!SSipintel.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://[config.ipintel_domain]/check.php?ip=[ip]&contact=[config.ipintel_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, retryed)
if(!retryed)
sleep(25)
return .(ip, 1)
else
ipintel_handle_error("Bad response from server: [response["status"]].", ip, retryed)
if(!retryed)
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, retryed)
if(!retryed)
sleep(25)
return .(ip, 1)
else
ipintel_handle_error("Unable to connect to API.", ip, retryed)
if(!retryed)
sleep(25)
return .(ip, 1)
/proc/ipintel_handle_error(error, ip, retryed)
if(retryed)
SSipintel.errors++
error += " Could not check [ip]. Disabling IPINTEL for [SSipintel.errors] minute[( SSipintel.errors == 1 ? "" : "s" )]"
SSipintel.throttle = world.timeofday + (2 * SSipintel.errors MINUTES)
else
error += " Attempting retry on [ip]."
log_ipintel(error)
/proc/log_ipintel(text)
log_game("IPINTEL: [text]")
log_debug("IPINTEL: [text]")
/proc/ipintel_is_banned(t_ckey, t_ip)
if(!config.ipintel_email)
return FALSE
if(!config.ipintel_whitelist)
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
/proc/ipintel_badip_check(target_ip)
var/rating_bad = config.ipintel_rating_bad
if(!rating_bad)
log_debug("ipintel_badip_check reports misconfigured rating_bad directive")
return FALSE
var/valid_hours = config.ipintel_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 [format_table_name("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
/proc/vpn_whitelist_check(target_ckey)
if(!config.ipintel_whitelist)
return FALSE
var/datum/db_query/query_whitelist_check = SSdbcore.NewQuery("SELECT * FROM [format_table_name("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
/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 [format_table_name("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
/proc/vpn_whitelist_remove(target_ckey)
var/datum/db_query/query_whitelist_remove = SSdbcore.NewQuery("DELETE FROM [format_table_name("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
/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.")
@@ -52,7 +52,8 @@
usr << browse(output,"window=editrights;size=600x500")
/datum/admins/proc/log_admin_rank_modification(adm_ckey, new_rank)
if(config.admin_legacy_system) return
if(!GLOB.configuration.admin.use_database_admins)
return
if(!usr.client)
return
@@ -75,7 +76,7 @@
if(!istext(adm_ckey) || !istext(new_rank))
return
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey=:adm_ckey", list(
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id FROM admin WHERE ckey=:adm_ckey", list(
"adm_ckey" = adm_ckey
))
if(!select_query.warn_execute())
@@ -90,7 +91,7 @@
qdel(select_query)
flag_account_for_forum_sync(adm_ckey)
if(new_admin)
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `admin_rank`, `level`, `flags`) VALUES (null, :adm_ckey, :new_rank, -1, 0)", list(
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO admin (`id`, `ckey`, `admin_rank`, `level`, `flags`) VALUES (null, :adm_ckey, :new_rank, -1, 0)", list(
"adm_ckey" = adm_ckey,
"new_rank" = new_rank
))
@@ -100,7 +101,7 @@
qdel(insert_query)
var/logtxt = "Added new admin [adm_ckey] to rank [new_rank]"
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , :uckey, :uip, :logtxt)", list(
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO admin_log (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , :uckey, :uip, :logtxt)", list(
"uckey" = usr.ckey,
"uip" = usr.client.address,
"logtxt" = logtxt
@@ -113,7 +114,7 @@
to_chat(usr, "<span class='notice'>New admin added.</span>")
else
if(!isnull(admin_id) && isnum(admin_id))
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET admin_rank=:new_rank WHERE id=:admin_id", list(
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE admin SET admin_rank=:new_rank WHERE id=:admin_id", list(
"new_rank" = new_rank,
"admin_id" = admin_id,
))
@@ -123,7 +124,7 @@
qdel(insert_query)
var/logtxt = "Edited the rank of [adm_ckey] to [new_rank]"
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , :uckey, :uip, :logtxt)", list(
var/datum/db_query/log_query = SSdbcore.NewQuery("INSERT INTO admin_log (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , :uckey, :uip, :logtxt)", list(
"uckey" = usr.ckey,
"uip" = usr.client.address,
"logtxt" = logtxt,
@@ -140,7 +141,7 @@
message_admins("[key_name(usr)] attempted to edit admin ranks via advanced proc-call")
log_admin("[key_name(usr)] attempted to edit admin ranks via advanced proc-call")
return
if(config.admin_legacy_system)
if(!GLOB.configuration.admin.use_database_admins)
return
if(!usr.client)
@@ -167,7 +168,7 @@
if(!istext(adm_ckey) || !isnum(new_permission))
return
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey=:adm_ckey", list(
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT id, flags FROM admin WHERE ckey=:adm_ckey", list(
"adm_ckey" = adm_ckey
))
if(!select_query.warn_execute())
@@ -186,7 +187,7 @@
flag_account_for_forum_sync(adm_ckey)
if(admin_rights & new_permission) //This admin already has this permission, so we are removing it.
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET flags=:newflags WHERE id=:admin_id", list(
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE admin SET flags=:newflags WHERE id=:admin_id", list(
"newflags" = (admin_rights & ~new_permission),
"admin_id" = admin_id
))
@@ -197,7 +198,7 @@
var/logtxt = "Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]"
var/datum/db_query/log_query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log`)
INSERT INTO admin_log (`datetime` ,`adminckey` ,`adminip` ,`log`)
VALUES (Now() , :uckey, :uip, :logtxt)"}, list(
"uckey" = usr.ckey,
"uip" = usr.client.address,
@@ -209,7 +210,7 @@
qdel(log_query)
to_chat(usr, "<span class='notice'>Permission removed.</span>")
else //This admin doesn't have this permission, so we are adding it.
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET flags=:newflags WHERE id=:admin_id", list(
var/datum/db_query/insert_query = SSdbcore.NewQuery("UPDATE admin SET flags=:newflags WHERE id=:admin_id", list(
"newflags" = (admin_rights | new_permission),
"admin_id" = admin_id
))
@@ -220,7 +221,7 @@
var/logtxt = "Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]"
var/datum/db_query/log_query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log`)
INSERT INTO admin_log (`datetime` ,`adminckey` ,`adminip` ,`log`)
VALUES (Now() , :uckey, :uip, :logtxt)"}, list(
"uckey" = usr.ckey,
"uip" = usr.client.address,
@@ -239,7 +240,7 @@
if(!check_rights(R_PERMISSIONS))
return
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank=:admin_rank WHERE ckey=:ckey", list(
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE player SET lastadminrank=:admin_rank WHERE ckey=:ckey", list(
"admin_rank" = newrank,
"ckey" = ckey
))
+1 -1
View File
@@ -418,7 +418,7 @@
var/mob/M = blob.current
if(M)
dat += "<tr><td>[ADMIN_PP(M,"[M.real_name]")][M.client ? "" : " <i>(ghost)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.client?.ckey]'>PM</A></td>"
dat += "<td><A href='?priv_msg=[M.client?.ckey]'>PM</A> [ADMIN_FLW(M, "FLW")]</td>"
else
dat += "<tr><td><i>Blob not found!</i></td></tr>"
dat += "</table>"
+3
View File
@@ -81,6 +81,9 @@
<b>Create Weather</b><BR>
<A href='?src=[UID()];secretsfun=weatherashstorm'>Weather - Ash Storm</A>&nbsp;&nbsp;
<BR>
<b>Reinforce Station</b><BR>
<A href='?src=[UID()];secretsfun=gammashuttle'>Move the Gamma Armory</A>&nbsp;&nbsp;
<BR>
</center>"}
if(2)
+10 -10
View File
@@ -15,7 +15,7 @@
else
target_ckey = ckey(target_ckey)
var/datum/db_query/query_find_ckey = SSdbcore.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey=:ckey", list(
var/datum/db_query/query_find_ckey = SSdbcore.NewQuery("SELECT ckey, exp FROM player WHERE ckey=:ckey", list(
"ckey" = target_ckey
))
@@ -54,14 +54,14 @@
adminckey = ckey(adminckey)
if(!server)
if(config && config.server_name)
server = config.server_name
if(GLOB.configuration.general.server_name)
server = GLOB.configuration.general.server_name
// Force cast this to 1/0 incase someone tries to feed bad data
automated = !!automated
var/datum/db_query/query_noteadd = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime, round_id, automated)
INSERT INTO notes (ckey, timestamp, notetext, adminckey, server, crew_playtime, round_id, automated)
VALUES (:targetckey, NOW(), :notetext, :adminkey, :server, :crewnum, :roundid, :automated)
"}, list(
"targetckey" = target_ckey,
@@ -95,7 +95,7 @@
if(!note_id)
return
note_id = text2num(note_id)
var/datum/db_query/query_find_note_del = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id=:note_id", list(
var/datum/db_query/query_find_note_del = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey FROM notes WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_find_note_del.warn_execute())
@@ -107,7 +107,7 @@
adminckey = query_find_note_del.item[3]
qdel(query_find_note_del)
var/datum/db_query/query_del_note = SSdbcore.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id=:note_id", list(
var/datum/db_query/query_del_note = SSdbcore.NewQuery("DELETE FROM notes WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_del_note.warn_execute())
@@ -130,7 +130,7 @@
return
note_id = text2num(note_id)
var/target_ckey
var/datum/db_query/query_find_note_edit = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey, automated FROM [format_table_name("notes")] WHERE id=:note_id", list(
var/datum/db_query/query_find_note_edit = SSdbcore.NewQuery("SELECT ckey, notetext, adminckey, automated FROM notes WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_find_note_edit.warn_execute())
@@ -148,7 +148,7 @@
if(!new_note)
return
var/edit_text = "Edited by [usr.ckey] on [SQLtime()] from \"[old_note]\" to \"[new_note]\"<hr>"
var/datum/db_query/query_update_note = SSdbcore.NewQuery("UPDATE [format_table_name("notes")] SET notetext=:new_note, last_editor=:akey, edits = CONCAT(IFNULL(edits,''),:edit_text) WHERE id=:note_id", list(
var/datum/db_query/query_update_note = SSdbcore.NewQuery("UPDATE notes SET notetext=:new_note, last_editor=:akey, edits = CONCAT(IFNULL(edits,''),:edit_text) WHERE id=:note_id", list(
"new_note" = new_note,
"akey" = usr.ckey,
"edit_text" = edit_text,
@@ -182,7 +182,7 @@
var/target_sql_ckey = ckey(target_ckey)
var/datum/db_query/query_get_notes = SSdbcore.NewQuery({"
SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime, round_id, automated
FROM [format_table_name("notes")] WHERE ckey=:targetkey ORDER BY timestamp"}, list(
FROM notes WHERE ckey=:targetkey ORDER BY timestamp"}, list(
"targetkey" = target_sql_ckey
))
if(!query_get_notes.warn_execute())
@@ -226,7 +226,7 @@
search = "^\[^\[:alpha:\]\]"
else
search = "^[index]"
var/datum/db_query/query_list_notes = SSdbcore.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP :search ORDER BY ckey", list(
var/datum/db_query/query_list_notes = SSdbcore.NewQuery("SELECT DISTINCT ckey FROM notes WHERE ckey REGEXP :search ORDER BY ckey", list(
"search" = search
))
if(!query_list_notes.warn_execute())
+42 -42
View File
@@ -287,19 +287,19 @@
if(null,"") return
if("*New Rank*")
new_rank = input("Please input a new rank", "New custom rank", null, null) as null|text
if(config.admin_legacy_system)
if(!GLOB.configuration.admin.use_database_admins)
new_rank = ckeyEx(new_rank)
if(!new_rank)
to_chat(usr, "<font color='red'>Error: Topic 'editrights': Invalid rank</font>")
return
if(config.admin_legacy_system)
if(!GLOB.configuration.admin.use_database_admins)
if(GLOB.admin_ranks.len)
if(new_rank in GLOB.admin_ranks)
rights = GLOB.admin_ranks[new_rank] //we typed a rank which already exists, use its rights
else
GLOB.admin_ranks[new_rank] = 0 //add the new rank to admin_ranks
else
if(config.admin_legacy_system)
if(!GLOB.configuration.admin.use_database_admins)
new_rank = ckeyEx(new_rank)
rights = GLOB.admin_ranks[new_rank] //we input an existing rank, use its rights
@@ -538,8 +538,8 @@
to_chat(M, "<span class='warning'><big><b>You have been appearance banned by [usr.client.ckey].</b></big></span>")
to_chat(M, "<span class='danger'>The reason is: [reason]</span>")
to_chat(M, "<span class='warning'>Appearance ban can be lifted only upon request.</span>")
if(config.banappeals)
to_chat(M, "<span class='warning'>To try to resolve this matter head to [config.banappeals]</span>")
if(GLOB.configuration.url.banappeals_url)
to_chat(M, "<span class='warning'>To try to resolve this matter head to [GLOB.configuration.url.banappeals_url]</span>")
else
to_chat(M, "<span class='warning'>No ban appeals URL has been set.</span>")
if("No")
@@ -877,7 +877,7 @@
if(notbannedlist.len) //at least 1 unbanned job exists in joblist so we have stuff to ban.
switch(alert("Temporary Ban of [M.ckey]?",,"Yes","No", "Cancel"))
if("Yes")
if(config.ban_legacy_system)
if(!GLOB.configuration.general.use_database_bans)
to_chat(usr, "<span class='warning'>Your server is using the legacy banning system, which does not support temporary job bans. Consider upgrading. Aborting ban.</span>")
return
var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null
@@ -928,7 +928,7 @@
//Unbanning joblist
//all jobs in joblist are banned already OR we didn't give a reason (implying they shouldn't be banned)
if(joblist.len) //at least 1 banned job exists in joblist so we have stuff to unban.
if(!config.ban_legacy_system)
if(GLOB.configuration.general.use_database_bans)
to_chat(usr, "<span class='warning'>Unfortunately, database based unbanning cannot be done through this panel</span>")
DB_ban_panel(M.ckey)
return
@@ -1002,8 +1002,8 @@
else if(href_list["webtools"])
var/target_ckey = href_list["webtools"]
if(config.forum_playerinfo_url)
var/url_to_open = config.forum_playerinfo_url + target_ckey
if(GLOB.configuration.url.forum_playerinfo_url)
var/url_to_open = "[GLOB.configuration.url.forum_playerinfo_url][target_ckey]"
if(alert("Open [url_to_open]",,"Yes","No")=="Yes")
usr.client << link(url_to_open)
@@ -1017,7 +1017,7 @@
else if(href_list["noteedits"])
var/note_id = text2num(href_list["noteedits"])
var/datum/db_query/query_noteedits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("notes")] WHERE id=:note_id", list(
var/datum/db_query/query_noteedits = SSdbcore.NewQuery("SELECT edits FROM notes WHERE id=:note_id", list(
"note_id" = note_id
))
if(!query_noteedits.warn_execute())
@@ -1067,8 +1067,8 @@
DB_ban_record(BANTYPE_TEMP, M, mins, reason)
if(M.client)
M.client.link_forum_account(TRUE)
if(config.banappeals)
to_chat(M, "<span class='warning'>To try to resolve this matter head to [config.banappeals]</span>")
if(GLOB.configuration.url.banappeals_url)
to_chat(M, "<span class='warning'>To try to resolve this matter head to [GLOB.configuration.url.banappeals_url]</span>")
else
to_chat(M, "<span class='warning'>No ban appeals URL has been set.</span>")
log_admin("[key_name(usr)] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
@@ -1084,8 +1084,8 @@
to_chat(M, "<span class='warning'>This ban does not expire automatically and must be appealed.</span>")
if(M.client)
M.client.link_forum_account(TRUE)
if(config.banappeals)
to_chat(M, "<span class='warning'>To try to resolve this matter head to [config.banappeals]</span>")
if(GLOB.configuration.url.banappeals_url)
to_chat(M, "<span class='warning'>To try to resolve this matter head to [GLOB.configuration.url.banappeals_url]</span>")
else
to_chat(M, "<span class='warning'>No ban appeals URL has been set.</span>")
log_admin("[key_name(usr)] has banned [M.ckey].\nReason: [reason]\nThis ban does not expire automatically and must be appealed.")
@@ -1132,7 +1132,7 @@
else if(href_list["watcheditlog"])
var/target_ckey = href_list["watcheditlog"]
var/datum/db_query/query_watchedits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("watch")] WHERE ckey=:targetkey", list(
var/datum/db_query/query_watchedits = SSdbcore.NewQuery("SELECT edits FROM watch WHERE ckey=:targetkey", list(
"targetkey" = target_ckey
))
if(!query_watchedits.warn_execute())
@@ -1163,8 +1163,8 @@
if(SSticker && SSticker.mode)
return alert(usr, "The game has already started.", null, null, null, null)
var/dat = {"<b>What mode do you wish to play?</b><hr>"}
for(var/mode in config.modes)
dat += {"<A href='?src=[UID()];c_mode2=[mode]'>[config.mode_names[mode]]</A><br>"}
for(var/mode in GLOB.configuration.gamemode.gamemodes)
dat += {"<A href='?src=[UID()];c_mode2=[mode]'>[GLOB.configuration.gamemode.gamemode_names[mode]]</A><br>"}
dat += {"<A href='?src=[UID()];c_mode2=secret'>Secret</A><br>"}
dat += {"<A href='?src=[UID()];c_mode2=random'>Random</A><br>"}
dat += {"Now: [GLOB.master_mode]"}
@@ -1178,8 +1178,8 @@
if(GLOB.master_mode != "secret")
return alert(usr, "The game mode has to be secret!", null, null, null, null)
var/dat = {"<b>What game mode do you want to force secret to be? Use this if you want to change the game mode, but want the players to believe it's secret. This will only work if the current game mode is secret.</b><hr>"}
for(var/mode in config.modes)
dat += {"<A href='?src=[UID()];f_secret2=[mode]'>[config.mode_names[mode]]</A><br>"}
for(var/mode in GLOB.configuration.gamemode.gamemodes)
dat += {"<A href='?src=[UID()];f_secret2=[mode]'>[GLOB.configuration.gamemode.gamemode_names[mode]]</A><br>"}
dat += {"<A href='?src=[UID()];f_secret2=secret'>Random (default)</A><br>"}
dat += {"Now: [GLOB.secret_force_mode]"}
usr << browse(dat, "window=f_secret")
@@ -2165,7 +2165,7 @@
if(!istype(M))
to_chat(usr, "<span class='warning'>This can only be used on instances of type /mob/living</span>")
return
var/ptypes = list("Lightning bolt", "Fire Death", "Gib")
var/ptypes = list("Lightning bolt", "Fire Death", "Gib", "Dust")
if(ishuman(M))
H = M
ptypes += "Brain Damage"
@@ -2180,7 +2180,6 @@
ptypes += "Crew Traitor"
ptypes += "Floor Cluwne"
ptypes += "Shamebrero"
ptypes += "Dust"
var/punishment = input(owner, "How would you like to smite [M]?", "Its good to be baaaad...", "") as null|anything in ptypes
if(!(punishment in ptypes))
return
@@ -2203,6 +2202,9 @@
if("Gib")
M.gib(FALSE)
logmsg = "gibbed."
if("Dust")
M.dust()
logmsg = "dust"
// These smiting types are only valid for ishuman() mobs
if("Brain Damage")
@@ -2292,9 +2294,6 @@
var/obj/item/clothing/head/sombrero/shamebrero/S = new(H.loc)
H.equip_to_slot_or_del(S, slot_head)
logmsg = "shamebrero"
if("Dust")
H.dust()
logmsg = "dust"
if(logmsg)
log_admin("[key_name(owner)] smited [key_name(M)] with: [logmsg]")
message_admins("[key_name_admin(owner)] smited [key_name_admin(M)] with: [logmsg]")
@@ -2510,7 +2509,7 @@
if("Central Command")
stamptype = "icon"
stampvalue = "cent"
sendername = command_name()
sendername = "NAS Trurl"
if("Syndicate")
stamptype = "icon"
stampvalue = "syndicate"
@@ -2840,7 +2839,7 @@
else if(href_list["memoeditlist"])
if(!check_rights(R_SERVER)) return
var/sql_key = href_list["memoeditlist"]
var/datum/db_query/query_memoedits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("memo")] WHERE (ckey=:sql_key)", list(
var/datum/db_query/query_memoedits = SSdbcore.NewQuery("SELECT edits FROM memo WHERE (ckey=:sql_key)", list(
"sql_key" = sql_key
))
if(!query_memoedits.warn_execute())
@@ -3008,21 +3007,16 @@
if("togglebombcap")
SSblackbox.record_feedback("tally", "admin_secrets_fun_used", 1, "Bomb Cap")
var/newBombCap = input(usr,"What would you like the new bomb cap to be. (entered as the light damage range (the 3rd number in common (1,2,3) notation)) Must be between 4 and 128)", "New Bomb Cap", GLOB.max_ex_light_range) as num|null
var/newBombCap = input(usr,"What would you like the new bomb cap to be. (entered as the light damage range (the 3rd number in common (1,2,3) notation)) Must be between 4 and 128)", "New Bomb Cap", GLOB.configuration.general.bomb_cap) as num|null
if(newBombCap < 4)
return
if(newBombCap > 128)
newBombCap = 128
GLOB.max_ex_devastation_range = round(newBombCap/4)
GLOB.max_ex_heavy_range = round(newBombCap/2)
GLOB.max_ex_light_range = newBombCap
//I don't know why these are their own variables, but fuck it, they are.
GLOB.max_ex_flash_range = newBombCap
GLOB.max_ex_flame_range = newBombCap
GLOB.configuration.general.bomb_cap = newBombCap
message_admins("<span class='boldannounce'>[key_name_admin(usr)] changed the bomb cap to [GLOB.max_ex_devastation_range], [GLOB.max_ex_heavy_range], [GLOB.max_ex_light_range]</span>")
log_admin("[key_name(usr)] changed the bomb cap to [GLOB.max_ex_devastation_range], [GLOB.max_ex_heavy_range], [GLOB.max_ex_light_range]")
message_admins("<span class='boldannounce'>[key_name_admin(usr)] changed the bomb cap to [GLOB.configuration.general.bomb_cap / 4], [GLOB.configuration.general.bomb_cap / 2], [GLOB.configuration.general.bomb_cap]</span>")
log_admin("[key_name(usr)] changed the bomb cap to [GLOB.configuration.general.bomb_cap / 4], [GLOB.configuration.general.bomb_cap / 2], [GLOB.configuration.general.bomb_cap]")
if("flicklights")
SSblackbox.record_feedback("tally", "admin_secrets_fun_used", 1, "Flicker Lights")
@@ -3220,6 +3214,12 @@
message_admins("[key_name_admin(usr)] moved the centcom ferry")
log_admin("[key_name(usr)] moved the centcom ferry")
if("gammashuttle")
SSblackbox.record_feedback("tally", "admin_secrets_fun_used", 1, "Send Gamma Armory")
message_admins("[key_name_admin(usr)] moved the gamma armory")
log_admin("[key_name(usr)] moved the gamma armory")
move_gamma_ship()
if(usr)
log_admin("[key_name(usr)] used secret [href_list["secretsfun"]]")
if(ok)
@@ -3299,7 +3299,7 @@
var/val = alert(usr, "What do you want to set night shift to? This will override the automatic system until set to automatic again.", "Night Shift", "On", "Off", "Automatic")
switch(val)
if("Automatic")
if(config.enable_night_shifts)
if(GLOB.configuration.general.enable_night_shifts)
SSnightshift.can_fire = TRUE
SSnightshift.fire()
else
@@ -3378,7 +3378,7 @@
if(!newname)
return
G.name = newname
var/description = input("Enter [command_name()] message contents:") as message|null
var/description = input("Enter NAS Trurl message contents:") as message|null
if(!description)
return
G.report_message = description
@@ -3398,7 +3398,7 @@
var/isbn = text2num(href_list["library_book_id"])
if(href_list["view_library_book"])
var/datum/db_query/query_view_book = SSdbcore.NewQuery("SELECT content, title FROM [format_table_name("library")] WHERE id=:isbn", list(
var/datum/db_query/query_view_book = SSdbcore.NewQuery("SELECT content, title FROM library WHERE id=:isbn", list(
"isbn" = isbn
))
if(!query_view_book.warn_execute())
@@ -3425,7 +3425,7 @@
return
else if(href_list["unflag_library_book"])
var/datum/db_query/query_unflag_book = SSdbcore.NewQuery("UPDATE [format_table_name("library")] SET flagged = 0 WHERE id=:isbn", list(
var/datum/db_query/query_unflag_book = SSdbcore.NewQuery("UPDATE library SET flagged = 0 WHERE id=:isbn", list(
"isbn" = isbn
))
if(!query_unflag_book.warn_execute())
@@ -3437,7 +3437,7 @@
message_admins("[key_name_admin(usr)] has unflagged the book [isbn].")
else if(href_list["delete_library_book"])
var/datum/db_query/query_delbook = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=:isbn", list(
var/datum/db_query/query_delbook = SSdbcore.NewQuery("DELETE FROM library WHERE id=:isbn", list(
"isbn" = isbn
))
if(!query_delbook.warn_execute())
@@ -3505,7 +3505,7 @@
var/unlocked_jobs = ""
var/unlocked_species = ""
// Get their totals
var/datum/db_query/query_get_totals = SSdbcore.NewQuery("SELECT karma, karmaspent FROM [format_table_name("karmatotals")] WHERE byondkey=:ckey", list(
var/datum/db_query/query_get_totals = SSdbcore.NewQuery("SELECT karma, karmaspent FROM karmatotals WHERE byondkey=:ckey", list(
"ckey" = target_ckey
))
if(!query_get_totals.warn_execute())
@@ -3519,7 +3519,7 @@
qdel(query_get_totals)
// Now get their unlocks
var/datum/db_query/query_get_unlocks = SSdbcore.NewQuery("SELECT job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
var/datum/db_query/query_get_unlocks = SSdbcore.NewQuery("SELECT job, species FROM whitelist WHERE ckey=:ckey", list(
"ckey" = target_ckey
))
if(!query_get_unlocks.warn_execute())
+1 -1
View File
@@ -142,7 +142,7 @@
C.adminhelped = 0
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(config.popup_admin_pm)
if(GLOB.configuration.general.popup_admin_pm)
spawn(0) //so we don't hold the caller proc up
var/sender = src
var/sendername = key
@@ -34,7 +34,7 @@ GLOBAL_VAR_INIT(sent_syndicate_infiltration_team, 0)
return
var/tctext = input(src, "How much TC do you want to give each team member? Suggested: 20-30. They cannot trade TC.") as num
var/tcamount = text2num(tctext)
tcamount = between(0, tcamount, 1000)
tcamount = clamp(tcamount, 0, 1000)
if(GLOB.sent_syndicate_infiltration_team == 1)
if(alert("A Syndicate Infiltration Team has already been sent. Sure you want to send another?",,"Yes","No")=="No")
return
+7 -7
View File
@@ -45,7 +45,7 @@
/datum/admins/proc/makeTraitors()
var/datum/game_mode/traitor/temp = new
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
@@ -76,7 +76,7 @@
/datum/admins/proc/makeChangelings()
var/datum/game_mode/changeling/temp = new
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
@@ -106,7 +106,7 @@
/datum/admins/proc/makeRevs()
var/datum/game_mode/revolution/temp = new
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
@@ -156,7 +156,7 @@
/datum/admins/proc/makeCult()
var/datum/game_mode/cult/temp = new
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
@@ -517,7 +517,7 @@
/datum/admins/proc/makeVampires()
var/datum/game_mode/vampire/temp = new
if(config.protect_roles_from_antagonist)
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
temp.restricted_jobs += temp.protected_jobs
var/list/mob/living/carbon/human/candidates = list()
@@ -527,8 +527,8 @@
if(!antnum || antnum <= 0)
return
log_admin("[key_name(owner)] tried making Vampires with One-Click-Antag")
message_admins("[key_name_admin(owner)] tried making Vampires with One-Click-Antag")
log_admin("[key_name(owner)] tried making [antnum] Vampires with One-Click-Antag")
message_admins("[key_name_admin(owner)] tried making [antnum] Vampires with One-Click-Antag")
for(var/mob/living/carbon/human/applicant in GLOB.player_list)
if(CandCheck(ROLE_VAMPIRE, applicant, temp))
+1 -1
View File
@@ -6,7 +6,7 @@
return
if(istype(O,/obj/singularity))
if(config.forbid_singulo_possession)
if(GLOB.configuration.general.forbid_singulo_possession) // I love how this needs to exist
to_chat(usr, "It is forbidden to possess singularities.")
return
+15 -15
View File
@@ -203,7 +203,7 @@
/proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
if(automute)
if(!config.automute_on)
if(!GLOB.configuration.general.enable_auto_mute)
return
else
if(!usr || !usr.client)
@@ -276,21 +276,21 @@
return
var/action=""
if(config.antag_hud_allowed)
if(GLOB.configuration.general.allow_antag_hud)
for(var/mob/dead/observer/g in get_ghosts())
if(g.antagHUD)
g.antagHUD = FALSE // Disable it on those that have it enabled
g.has_enabled_antagHUD = FALSE // We'll allow them to respawn
to_chat(g, "<span class='danger'>The Administrator has disabled AntagHUD </span>")
config.antag_hud_allowed = 0
to_chat(g, "<span class='danger'>The Administrators have disabled AntagHUD </span>")
GLOB.configuration.general.allow_antag_hud = FALSE
to_chat(src, "<span class='danger'>AntagHUD usage has been disabled</span>")
action = "disabled"
else
for(var/mob/dead/observer/g in get_ghosts())
if(!g.client.holder) // Add the verb back for all non-admin ghosts
to_chat(g, "<span class='boldnotice'>The Administrator has enabled AntagHUD </span>")// Notify all observers they can now use AntagHUD
to_chat(g, "<span class='boldnotice'>The Administrators have enabled AntagHUD </span>")// Notify all observers they can now use AntagHUD
config.antag_hud_allowed = 1
GLOB.configuration.general.allow_antag_hud = TRUE
action = "enabled"
to_chat(src, "<span class='boldnotice'>AntagHUD usage has been enabled</span>")
@@ -307,11 +307,11 @@
return
var/action=""
if(config.antag_hud_restricted)
if(GLOB.configuration.general.restrict_antag_hud_rejoin)
for(var/mob/dead/observer/g in get_ghosts())
to_chat(g, "<span class='boldnotice'>The administrator has lifted restrictions on joining the round if you use AntagHUD</span>")
action = "lifted restrictions"
config.antag_hud_restricted = 0
GLOB.configuration.general.restrict_antag_hud_rejoin = FALSE
to_chat(src, "<span class='boldnotice'>AntagHUD restrictions have been lifted</span>")
else
for(var/mob/dead/observer/g in get_ghosts())
@@ -320,7 +320,7 @@
g.antagHUD = FALSE
g.has_enabled_antagHUD = FALSE
action = "placed restrictions"
config.antag_hud_restricted = 1
GLOB.configuration.general.restrict_antag_hud_rejoin = TRUE
to_chat(src, "<span class='danger'>AntagHUD restrictions have been enabled</span>")
log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD")
@@ -941,14 +941,14 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_SERVER|R_EVENT))
return
if(!config.allow_random_events)
config.allow_random_events = 1
if(!GLOB.configuration.event.enable_random_events)
GLOB.configuration.event.enable_random_events = TRUE
to_chat(usr, "Random events enabled")
message_admins("Admin [key_name_admin(usr)] has enabled random events.", 1)
message_admins("Admin [key_name_admin(usr)] has enabled random events.")
else
config.allow_random_events = 0
GLOB.configuration.event.enable_random_events = FALSE
to_chat(usr, "Random events disabled")
message_admins("Admin [key_name_admin(usr)] has disabled random events.", 1)
message_admins("Admin [key_name_admin(usr)] has disabled random events.")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Toggle Random Events") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/reset_all_tcs()
@@ -1031,7 +1031,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(H.client == null || H.stat == DEAD) // No clientless or dead
continue
mins_afk = round(H.client.inactivity / 600)
if(mins_afk < config.list_afk_minimum)
if(mins_afk < 5)
continue
if(H.job)
job_string = H.job
+7 -7
View File
@@ -5,7 +5,7 @@
var/new_ckey = ckey(clean_input("Who would you like to add to the watchlist?","Enter a ckey",null))
if(!new_ckey)
return
var/datum/db_query/query_watchfind = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey=:new_ckey", list(
var/datum/db_query/query_watchfind = SSdbcore.NewQuery("SELECT ckey FROM player WHERE ckey=:new_ckey", list(
"new_ckey" = new_ckey
))
if(!query_watchfind.warn_execute())
@@ -27,7 +27,7 @@
if(!adminckey)
return
var/datum/db_query/query_watchadd = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("watch")] (ckey, reason, adminckey, timestamp)
INSERT INTO watch (ckey, reason, adminckey, timestamp)
VALUES (:targetkey, :reason, :adminkey, NOW())"},
list(
"targetkey" = target_ckey,
@@ -50,7 +50,7 @@
/client/proc/watchlist_remove(target_ckey, browse = 0)
if(!check_rights(R_ADMIN))
return
var/datum/db_query/query_watchdel = SSdbcore.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
var/datum/db_query/query_watchdel = SSdbcore.NewQuery("DELETE FROM watch WHERE ckey=:target_ckey", list(
"target_ckey" = target_ckey
))
if(!query_watchdel.warn_execute())
@@ -68,7 +68,7 @@
/client/proc/watchlist_edit(target_ckey, browse = 0)
if(!check_rights(R_ADMIN))
return
var/datum/db_query/query_watchreason = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
var/datum/db_query/query_watchreason = SSdbcore.NewQuery("SELECT reason FROM watch WHERE ckey=:target_ckey", list(
"target_ckey" = target_ckey
))
if(!query_watchreason.warn_execute())
@@ -82,7 +82,7 @@
var/sql_ckey = usr.ckey
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from \"[watch_reason]\" to \"[new_reason]\""
var/datum/db_query/query_watchupdate = SSdbcore.NewQuery("UPDATE [format_table_name("watch")] SET reason=:new_reason, last_editor=:sql_ckey, edits = CONCAT(IFNULL(edits,''), :edit_text) WHERE ckey=:target_ckey", list(
var/datum/db_query/query_watchupdate = SSdbcore.NewQuery("UPDATE watch SET reason=:new_reason, last_editor=:sql_ckey, edits = CONCAT(IFNULL(edits,''), :edit_text) WHERE ckey=:target_ckey", list(
"new_reason" = new_reason,
"sql_ckey" = sql_ckey,
"edit_text" = edit_text,
@@ -114,7 +114,7 @@
else
search = "^."
var/datum/db_query/query_watchlist = SSdbcore.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM [format_table_name("watch")] WHERE ckey REGEXP :search ORDER BY ckey", list(
var/datum/db_query/query_watchlist = SSdbcore.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM watch WHERE ckey REGEXP :search ORDER BY ckey", list(
"search" = search
))
if(!query_watchlist.warn_execute())
@@ -134,7 +134,7 @@
qdel(query_watchlist)
/proc/check_watchlist(target_ckey)
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey=:target_ckey", list(
var/datum/db_query/query_watch = SSdbcore.NewQuery("SELECT reason FROM watch WHERE ckey=:target_ckey", list(
"target_ckey" = target_ckey
))
if(!query_watch.warn_execute())
@@ -117,7 +117,7 @@
objective_count += 1 //Exchange counts towards number of objectives
var/objective_amount = config.traitor_objectives_amount
var/objective_amount = GLOB.configuration.gamemode.traitor_objectives_amount
if(is_hijacker && objective_count <= objective_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
if (!(locate(/datum/objective/hijack) in objectives))
@@ -154,7 +154,7 @@
objective_count += forge_single_objective()
for(var/i = objective_count, i < config.traitor_objectives_amount)
for(var/i = objective_count, i < GLOB.configuration.gamemode.traitor_objectives_amount)
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
@@ -248,7 +248,7 @@
owner.announce_objectives()
if(should_give_codewords)
give_codewords()
to_chat(owner.current, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Traitor)</span>")
to_chat(owner.current, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Traitor)</span>")
/datum/antagonist/traitor/proc/update_traitor_icons_added(datum/mind/traitor_mind)
@@ -228,7 +228,12 @@
for(var/mob/living/L in T)
L.adjust_fire_stacks(3)
L.IgniteMob()
L.bodytemperature = max(temp / 3, L.bodytemperature)
if(ishuman(L))
var/mob/living/carbon/human/M = L
var/heatBlockPercent = 1 - M.get_heat_protection(temp)
M.bodytemperature += (temp - M.bodytemperature) * heatBlockPercent / 3
else
L.bodytemperature = (2 * L.bodytemperature + temp) / 3
/proc/fireflash_s(atom/center, radius, temp, falloff)
if(temp < T0C + 60)
@@ -291,7 +296,12 @@
for(var/mob/living/L in T)
L.adjust_fire_stacks(3)
L.IgniteMob()
L.bodytemperature = (2 * L.bodytemperature + temp) / 3
if(ishuman(L))
var/mob/living/carbon/human/M = L
var/heatBlockPercent = 1 - M.get_heat_protection(temp)
M.bodytemperature += (temp - M.bodytemperature) * heatBlockPercent / 3
else
L.bodytemperature = (2 * L.bodytemperature + temp) / 3
if(T.density)
continue
+21 -16
View File
@@ -112,6 +112,7 @@
var/target_temperature = T20C
var/regulating_temperature = 0
var/thermostat_state = FALSE
var/list/TLV = list()
@@ -329,8 +330,8 @@
var/datum/gas_mixture/gas = location.remove_air(0.25 * environment.total_moles())
if(!gas)
return
if(!regulating_temperature)
regulating_temperature = 1
if(!regulating_temperature && thermostat_state == TRUE)
regulating_temperature = TRUE
visible_message("\The [src] clicks as it starts [environment.temperature > target_temperature ? "cooling" : "heating"] the room.", "You hear a click and a faint electronic hum.")
if(target_temperature > MAX_TEMPERATURE)
@@ -339,25 +340,26 @@
if(target_temperature < MIN_TEMPERATURE)
target_temperature = MIN_TEMPERATURE
var/heat_capacity = gas.heat_capacity()
var/energy_used = max(abs(heat_capacity * (gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
if(thermostat_state == TRUE)
var/heat_capacity = gas.heat_capacity()
var/energy_used = max(abs(heat_capacity * (gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
//Use power. Assuming that each power unit represents 1000 watts....
use_power(energy_used/1000, ENVIRON)
//Use power. Assuming that each power unit represents 1000 watts....
use_power(energy_used / 1000, ENVIRON)
//We need to cool ourselves.
if(heat_capacity)
if(environment.temperature > target_temperature)
gas.temperature -= energy_used / heat_capacity
else
gas.temperature += energy_used / heat_capacity
//We need to cool ourselves.
if(heat_capacity)
if(environment.temperature > target_temperature)
gas.temperature -= energy_used / heat_capacity
else
gas.temperature += energy_used / heat_capacity
if(abs(environment.temperature - target_temperature) <= 0.5)
regulating_temperature = FALSE
visible_message("[src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.", "You hear a click as a faint electronic humming stops.")
environment.merge(gas)
if(abs(environment.temperature - target_temperature) <= 0.5)
regulating_temperature = 0
visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.", "You hear a click as a faint electronic humming stops.")
/obj/machinery/alarm/update_icon()
if(wiresexposed)
icon_state = "alarmx"
@@ -642,6 +644,7 @@
data["pressure"] = environment_pressure
data["temperature"] = environment.temperature
data["temperature_c"] = round(environment.temperature - T0C, 0.1)
data["thermostat_state"] = thermostat_state
var/list/percentages = list()
percentages["oxygen"] = oxygen_percent
@@ -931,6 +934,8 @@
else
target_temperature = input_temperature
if("thermostat_state")
thermostat_state = !thermostat_state
/obj/machinery/alarm/emag_act(mob/user)
if(!emagged)
@@ -20,7 +20,10 @@ Pipelines + Other Objects -> Pipe network
on_blueprints = TRUE
var/nodealert = 0
var/can_unwrench = 0
/// If the machine is currently operating or not.
var/on = FALSE
/// The amount of pressure the machine wants to operate at.
var/target_pressure = 0
var/connect_types[] = list(1) //1=regular, 2=supply, 3=scrubber
var/connected_to = 1 //same as above, currently not used for anything
var/icon_connect_type = "" //"-supply" or "-scrubbers"
@@ -373,3 +376,35 @@ Pipelines + Other Objects -> Pipe network
//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it.
/obj/machinery/atmospherics/proc/can_see_pipes()
return TRUE
/**
* Turns the machine either on, or off. If this is done by a user, display a message to them.
*
* NOTE: Only applies to atmospherics machines which can be toggled on or off, such as pumps, or other devices.
*
* Arguments:
* * user - the mob who is toggling the machine.
*/
/obj/machinery/atmospherics/proc/toggle(mob/living/user)
if(!powered())
return
on = !on
update_icon()
if(user)
to_chat(user, "<span class='notice'>You toggle [src] [on ? "on" : "off"].</span>")
/**
* Maxes the output pressure of the machine. If this is done by a user, display a message to them.
*
* NOTE: Only applies to atmospherics machines which allow a `target_pressure` to be set, such as pumps, or other devices.
*
* Arguments:
* * user - the mob who is setting the output pressure to maximum.
*/
/obj/machinery/atmospherics/proc/set_max(mob/living/user)
if(!powered())
return
target_pressure = MAX_OUTPUT_PRESSURE
update_icon()
if(user)
to_chat(user, "<span class='notice'>You set the target pressure of [src] to maximum.</span>")
@@ -16,6 +16,10 @@
can_unwrench = 1
var/side_inverted = 0
/obj/machinery/atmospherics/binary/circulator/detailed_examine()
return "This generates electricity, depending on the difference in temperature between each side of the machine. The meter in \
the center of the machine gives an indicator of how much electricity is being generated."
// Creating a custom circulator pipe subtype to be delivered through cargo
/obj/item/pipe/circulator
name = "circulator/heat exchanger fitting"
@@ -16,7 +16,6 @@
connect_types = list(1,2,3) //connects to regular, supply and scrubbers pipes
var/on = 0
var/pump_direction = 1 //0 = siphoning, 1 = releasing
var/external_pressure_bound = ONE_ATMOSPHERE
@@ -206,23 +205,23 @@
pump_direction = 1
if(signal.data["set_input_pressure"] != null)
input_pressure_min = between(
0,
input_pressure_min = clamp(
text2num(signal.data["set_input_pressure"]),
0,
ONE_ATMOSPHERE*50
)
if(signal.data["set_output_pressure"] != null)
output_pressure_max = between(
0,
output_pressure_max = clamp(
text2num(signal.data["set_output_pressure"]),
0,
ONE_ATMOSPHERE*50
)
if(signal.data["set_external_pressure"] != null)
external_pressure_bound = between(
0,
external_pressure_bound = clamp(
text2num(signal.data["set_external_pressure"]),
0,
ONE_ATMOSPHERE*50
)
@@ -9,11 +9,13 @@
can_unwrench = 1
var/on = 0
var/target_pressure = ONE_ATMOSPHERE
target_pressure = ONE_ATMOSPHERE
var/id = null
/obj/machinery/atmospherics/binary/passive_gate/detailed_examine()
return "This is a one-way regulator, allowing gas to flow only at a specific pressure and flow rate. If the light is green, it is flowing."
/obj/machinery/atmospherics/binary/passive_gate/atmos_init()
..()
if(frequency)
@@ -100,9 +102,9 @@
on = !on
if("set_output_pressure" in signal.data)
target_pressure = between(
0,
target_pressure = clamp(
text2num(signal.data["set_output_pressure"]),
0,
ONE_ATMOSPHERE*50
)
@@ -171,11 +173,6 @@
if(.)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
/obj/machinery/atmospherics/binary/passive_gate/proc/toggle()
if(powered())
on = !on
update_icon()
/obj/machinery/atmospherics/binary/passive_gate/attackby(obj/item/W, mob/user, params)
if(!istype(W, /obj/item/wrench))
return ..()
@@ -21,50 +21,31 @@ Thus, the two variables affect pump operation are set in New():
can_unwrench = 1
var/on = 0
var/target_pressure = ONE_ATMOSPHERE
target_pressure = ONE_ATMOSPHERE
var/id = null
/obj/machinery/atmospherics/binary/pump/detailed_examine()
return "This moves gas from one pipe to another. A higher target pressure demands more energy. The side with the red end is the output."
// So we can CtrlClick without triggering the anchored message.
/obj/machinery/atmospherics/binary/pump/can_be_pulled(user, grab_state, force, show_message)
return FALSE
/obj/machinery/atmospherics/binary/pump/CtrlClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user) && !issilicon(usr))
return
if(!ishuman(usr) && !issilicon(usr))
return
toggle()
if(can_use_shortcut(user))
toggle(user)
return ..()
/obj/machinery/atmospherics/binary/pump/AICtrlClick()
toggle()
return ..()
/obj/machinery/atmospherics/binary/pump/AICtrlClick(mob/living/silicon/user)
toggle(user)
/obj/machinery/atmospherics/binary/pump/AltClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user) && !issilicon(usr))
return
if(!ishuman(usr) && !issilicon(usr))
return
set_max()
return
if(can_use_shortcut(user))
set_max(user)
/obj/machinery/atmospherics/binary/pump/AIAltClick()
set_max()
return ..()
/obj/machinery/atmospherics/binary/pump/proc/toggle()
if(powered())
on = !on
update_icon()
/obj/machinery/atmospherics/binary/pump/proc/set_max()
if(powered())
target_pressure = MAX_OUTPUT_PRESSURE
update_icon()
/obj/machinery/atmospherics/binary/pump/AIAltClick(mob/living/silicon/user)
set_max(user)
/obj/machinery/atmospherics/binary/pump/Destroy()
if(SSradio)
@@ -155,9 +136,9 @@ Thus, the two variables affect pump operation are set in New():
on = !on
if(signal.data["set_output_pressure"])
target_pressure = between(
0,
target_pressure = clamp(
text2num(signal.data["set_output_pressure"]),
0,
ONE_ATMOSPHERE*50
)
@@ -11,6 +11,9 @@
req_one_access_txt = "24;10"
/obj/machinery/atmospherics/binary/valve/detailed_examine()
return "Click this to turn the valve. If red, the pipes on each end are separated. Otherwise, they are connected."
/obj/machinery/atmospherics/binary/valve/open
open = 1
icon_state = "map_valve1"
@@ -21,50 +21,28 @@ Thus, the two variables affect pump operation are set in New():
can_unwrench = 1
var/on = 0
var/transfer_rate = 200
var/id = null
// So we can CtrlClick without triggering the anchored message.
/obj/machinery/atmospherics/binary/volume_pump/can_be_pulled(user, grab_state, force, show_message)
return FALSE
/obj/machinery/atmospherics/binary/volume_pump/CtrlClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user) && !issilicon(usr))
return
if(!ishuman(usr) && !issilicon(usr))
return
toggle()
if(can_use_shortcut(user))
toggle(user)
return ..()
/obj/machinery/atmospherics/binary/volume_pump/AICtrlClick()
toggle()
return ..()
/obj/machinery/atmospherics/binary/volume_pump/AICtrlClick(mob/living/silicon/user)
toggle(user)
/obj/machinery/atmospherics/binary/volume_pump/AltClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user) && !issilicon(usr))
return
if(!ishuman(usr) && !issilicon(usr))
return
set_max()
return
if(can_use_shortcut(user))
set_max(user)
/obj/machinery/atmospherics/binary/volume_pump/AIAltClick()
set_max()
return ..()
/obj/machinery/atmospherics/binary/volume_pump/proc/toggle()
if(powered())
on = !on
update_icon()
/obj/machinery/atmospherics/binary/volume_pump/proc/set_max()
if(powered())
transfer_rate = MAX_TRANSFER_RATE
update_icon()
/obj/machinery/atmospherics/binary/volume_pump/AIAltClick(mob/living/silicon/user)
set_max(user)
/obj/machinery/atmospherics/binary/volume_pump/Destroy()
if(SSradio)
@@ -153,9 +131,9 @@ Thus, the two variables affect pump operation are set in New():
on = !on
if(signal.data["set_transfer_rate"])
transfer_rate = between(
0,
transfer_rate = clamp(
text2num(signal.data["set_transfer_rate"]),
0,
air1.volume
)
@@ -17,8 +17,8 @@
icon = 'icons/atmos/filter.dmi'
icon_state = "map"
can_unwrench = TRUE
/// The amount of pressure the filter wants to operate at.
var/target_pressure = ONE_ATMOSPHERE
target_pressure = ONE_ATMOSPHERE
/// The type of gas we want to filter. Valid values that go here are from the `FILTER` defines at the top of the file.
var/filter_type = FILTER_TOXINS
/// A list of available filter options. Used with `ui_data`.
@@ -31,45 +31,24 @@
"N2O" = FILTER_N2O
)
// So we can CtrlClick without triggering the anchored message.
/obj/machinery/atmospherics/trinary/filter/can_be_pulled(user, grab_state, force, show_message)
return FALSE
/obj/machinery/atmospherics/trinary/filter/CtrlClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user) && !issilicon(usr))
return
if(!ishuman(usr) && !issilicon(usr))
return
toggle()
if(can_use_shortcut(user))
toggle(user)
return ..()
/obj/machinery/atmospherics/trinary/filter/AICtrlClick()
toggle()
return ..()
/obj/machinery/atmospherics/trinary/filter/AICtrlClick(mob/living/silicon/user)
toggle(user)
/obj/machinery/atmospherics/trinary/filter/AltClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user) && !issilicon(usr))
return
if(!ishuman(usr) && !issilicon(usr))
return
set_max()
return
if(can_use_shortcut(user))
set_max(user)
/obj/machinery/atmospherics/trinary/filter/AIAltClick()
set_max()
return ..()
/obj/machinery/atmospherics/trinary/filter/proc/toggle()
if(powered())
on = !on
update_icon()
/obj/machinery/atmospherics/trinary/filter/proc/set_max()
if(powered())
target_pressure = MAX_OUTPUT_PRESSURE
update_icon()
/obj/machinery/atmospherics/trinary/filter/AIAltClick(mob/living/silicon/user)
set_max(user)
/obj/machinery/atmospherics/trinary/filter/Destroy()
if(SSradio)
@@ -6,56 +6,35 @@
name = "gas mixer"
var/target_pressure = ONE_ATMOSPHERE
target_pressure = ONE_ATMOSPHERE
var/node1_concentration = 0.5
var/node2_concentration = 0.5
//node 3 is the outlet, nodes 1 & 2 are intakes
// So we can CtrlClick without triggering the anchored message.
/obj/machinery/atmospherics/trinary/mixer/can_be_pulled(user, grab_state, force, show_message)
return FALSE
/obj/machinery/atmospherics/trinary/mixer/CtrlClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user) && !issilicon(usr))
return
if(!ishuman(usr) && !issilicon(usr))
return
toggle()
if(can_use_shortcut(user))
toggle(user)
return ..()
/obj/machinery/atmospherics/trinary/mixer/AICtrlClick()
toggle()
return ..()
/obj/machinery/atmospherics/trinary/mixer/AICtrlClick(mob/living/silicon/user)
toggle(user)
/obj/machinery/atmospherics/trinary/mixer/AltClick(mob/living/user)
if(!istype(user) || user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user) && !issilicon(usr))
return
if(!ishuman(usr) && !issilicon(usr))
return
set_max()
return
if(can_use_shortcut(user))
set_max(user)
/obj/machinery/atmospherics/trinary/mixer/AIAltClick()
set_max()
return ..()
/obj/machinery/atmospherics/trinary/mixer/AIAltClick(mob/living/silicon/user)
set_max(user)
/obj/machinery/atmospherics/trinary/mixer/flipped
icon_state = "mmap"
flipped = 1
/obj/machinery/atmospherics/trinary/mixer/proc/toggle()
if(powered())
on = !on
update_icon()
/obj/machinery/atmospherics/trinary/mixer/proc/set_max()
if(powered())
target_pressure = MAX_OUTPUT_PRESSURE
update_icon()
/obj/machinery/atmospherics/trinary/mixer/update_icon(safety = 0)
..()
@@ -3,7 +3,6 @@
initialize_directions = SOUTH|NORTH|WEST
use_power = IDLE_POWER_USE
var/on = 0
layer = GAS_FILTER_LAYER
var/datum/gas_mixture/air1
@@ -12,6 +12,9 @@
var/state = TVALVE_STATE_STRAIGHT
/obj/machinery/atmospherics/trinary/tvalve/detailed_examine()
return "Click this to toggle the mode. The direction with the green light is where the gas will flow."
/obj/machinery/atmospherics/trinary/tvalve/bypass
icon_state = "map_tvalve1"
state = TVALVE_STATE_SIDE
@@ -13,12 +13,11 @@
interact_offline = 1
max_integrity = 350
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 30, "acid" = 30)
var/on = FALSE
var/temperature_archived
var/mob/living/carbon/occupant = null
var/obj/item/reagent_containers/glass/beaker = null
/// Holds two bitflags, AUTO_EJECT_DEAD and AUTO_EJECT_HEALTHY. Used to determine if the cryo cell will auto-eject dead and/or completely health patients.
var/auto_eject_prefs = NONE
/// Holds two bitflags, AUTO_EJECT_DEAD and AUTO_EJECT_HEALTHY. Used to determine if the cryo cell will auto-eject dead and/or completely healthy patients.
var/auto_eject_prefs = AUTO_EJECT_HEALTHY | AUTO_EJECT_DEAD
var/next_trans = 0
var/current_heat_capacity = 50
@@ -28,6 +27,23 @@
light_color = LIGHT_COLOR_WHITE
/obj/machinery/atmospherics/unary/cryo_cell/detailed_examine()
return "The cryogenic chamber, or 'cryo', treats most damage types, most notably genetic damage. It also stabilizes patients \
in critical condition by placing them in stasis, so they can be treated at a later time.<br>\
<br>\
In order for it to work, it must be loaded with chemicals, and the temperature of the solution must reach a certain point. Additionally, it \
requires a supply of pure oxygen, provided by canisters that are attached. The most commonly used chemicals in the chambers is Cryoxadone, which \
heals most damage types including genetic damage.<br>\
<br>\
Activating the freezer nearby, and setting it to a temperature setting below 150, is recommended before operation! Further, any clothing the patient \
is wearing that act as an insulator will reduce its effectiveness, and should be removed.<br>\
<br>\
Clicking the tube with a beaker full of chemicals in hand will place it in its storage to distribute when it is activated.<br>\
<br>\
Click your target with Grab intent, then click on the tube, with an empty hand, to place them in it. Click the tube again to open the menu. \
Press the button on the menu to activate it. Once they have reached 100 health, right-click the cell and click 'Eject Occupant' to remove them. \
Remember to turn it off, once you've finished, to save power and chemicals!"
/obj/machinery/atmospherics/unary/cryo_cell/power_change()
..()
if(!(stat & (BROKEN|NOPOWER)))
@@ -13,7 +13,6 @@
req_one_access_txt = "24;10"
var/on = 0
var/injecting = 0
var/volume_rate = 50
@@ -30,6 +29,10 @@
if(id && !id_tag)//I'm not dealing with any more merge conflicts
id_tag = id
/obj/machinery/atmospherics/unary/outlet_injector/detailed_examine()
return "Outputs the pipe's gas into the atmosphere, similar to an air vent. It can be controlled by a nearby atmospherics computer. \
A green light on it means it is on."
/obj/machinery/atmospherics/unary/outlet_injector/Destroy()
if(SSradio)
SSradio.remove_object(src, frequency)
@@ -135,7 +138,7 @@
if(signal.data["set_volume_rate"] != null)
var/number = text2num(signal.data["set_volume_rate"])
volume_rate = between(0, number, air_contents.volume)
volume_rate = clamp(number, 0, air_contents.volume)
if(signal.data["status"])
broadcast_status()
@@ -9,8 +9,6 @@
dir = SOUTH
initialize_directions = SOUTH
var/on = 0
var/oxygen_content = 10
/obj/machinery/atmospherics/unary/oxygen_generator/update_icon()
@@ -23,6 +23,10 @@
if(!node)
return 0
var/turf/T = loc
if(T.density) //No, you should not be able to get free air from walls
return
var/datum/gas_mixture/environment = loc.return_air()
var/pressure_delta = air_contents.return_pressure() - environment.return_pressure()
@@ -10,8 +10,6 @@
var/obj/machinery/portable_atmospherics/connected_device
var/on = 0
/obj/machinery/atmospherics/unary/portables_connector/Destroy()
if(connected_device)
connected_device.disconnect()
@@ -10,9 +10,6 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 30)
layer = OBJ_LAYER
///Check if the device should be on or off
var/on = FALSE
var/icon_state_off = "freezer"
var/icon_state_on = "freezer_1"
var/icon_state_open = "freezer-o"
@@ -40,6 +37,11 @@
RefreshParts()
update_icon()
/obj/machinery/atmospherics/unary/thermomachine/detailed_examine()
return "Cools or heats the gas of the pipe it is connected to. It uses massive amounts of electricity while on. \
It can be upgraded by replacing the capacitors, manipulators, and matter bins. It can be deconstructed by screwing the maintenance panel open with a \
screwdriver, and then using a crowbar."
/obj/machinery/atmospherics/unary/thermomachine/proc/swap_function()
cooling = !cooling
if(cooling)
@@ -20,7 +20,6 @@
req_one_access_txt = "24;10"
var/on = 0
var/pump_direction = 1 //0 = siphoning, 1 = releasing
var/external_pressure_bound = EXTERNAL_PRESSURE_BOUND
@@ -47,6 +46,9 @@
connect_types = list(1,2) //connects to regular and supply pipes
/obj/machinery/atmospherics/unary/vent_pump/detailed_examine()
return "This pumps the contents of the attached pipe out into the atmosphere, if needed. It can be controlled from an Air Alarm."
/obj/machinery/atmospherics/unary/vent_pump/on
on = 1
icon_state = "map_vent_out"
@@ -128,6 +130,9 @@
..()
if(stat & (NOPOWER|BROKEN))
return FALSE
var/turf/T = loc
if(T.density) //No, you should not be able to get free air from walls
return
if(!node)
on = FALSE
//broadcast_status() // from now air alarm/control computer should request update purposely --rastaf0
@@ -20,7 +20,6 @@
var/list/turf/simulated/adjacent_turfs = list()
var/on = 0
var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
var/scrub_O2 = 0
var/scrub_N2 = 0
@@ -51,6 +50,10 @@
assign_uid()
id_tag = num2text(uid)
/obj/machinery/atmospherics/unary/vent_scrubber/detailed_examine()
return "This filters the atmosphere of harmful gas. Filtered gas goes to the pipes connected to it, typically a scrubber pipe. \
It can be controlled from an Air Alarm. It can be configured to drain all air rapidly with a 'panic syphon' from an air alarm."
/obj/machinery/atmospherics/unary/vent_scrubber/Destroy()
if(initial_loc && frequency == ATMOS_VENTSCRUB)
initial_loc.air_scrub_info -= id_tag
@@ -193,6 +196,10 @@
if(stat & (NOPOWER|BROKEN))
return
var/turf/T = loc
if(T.density) //No, you should not be able to get free air from walls
return
if(!node)
on = 0
@@ -39,6 +39,9 @@
if(!target)
target = locate(/obj/machinery/atmospherics/pipe) in loc
/obj/machinery/meter/detailed_examine()
return "Measures the volume and temperature of the pipe under the meter."
/obj/machinery/meter/process_atmos()
if(!target)
icon_state = "meterX"
@@ -16,6 +16,9 @@
..()
initialize_directions = dir
/obj/machinery/atmospherics/pipe/cap/detailed_examine()
return "This is a cosmetic attachment, as pipes currently do not spill their contents into the air."
/obj/machinery/atmospherics/pipe/cap/hide(i)
if(level == 1 && istype(loc, /turf/simulated))
invisibility = i ? INVISIBILITY_MAXIMUM : 0
@@ -16,7 +16,6 @@
level = 1
/obj/machinery/atmospherics/pipe/manifold/New()
..()
alpha = 255
@@ -31,6 +30,9 @@
if(WEST)
initialize_directions = NORTH|EAST|SOUTH
/obj/machinery/atmospherics/pipe/manifold/detailed_examine()
return "A normal pipe with three ends to connect to."
/obj/machinery/atmospherics/pipe/manifold/atmos_init()
..()
for(var/D in GLOB.cardinal)
@@ -170,6 +172,10 @@
icon_connect_type = "-scrubbers"
color = PIPE_COLOR_RED
/obj/machinery/atmospherics/pipe/manifold/visible/scrubbers/detailed_examine()
return "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/visible/supply
name="Air supply pipe manifold"
desc = "A manifold composed of supply pipes"
@@ -179,6 +185,10 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
/obj/machinery/atmospherics/pipe/manifold/visible/supply/detailed_examine()
return "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/visible/yellow
color = PIPE_COLOR_YELLOW
@@ -211,6 +221,10 @@
icon_connect_type = "-scrubbers"
color = PIPE_COLOR_RED
/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers/detailed_examine()
return "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/hidden/supply
name="Air supply pipe manifold"
desc = "A manifold composed of supply pipes"
@@ -220,6 +234,10 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
/obj/machinery/atmospherics/pipe/manifold/hidden/supply/detailed_examine()
return "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/hidden/yellow
color = PIPE_COLOR_YELLOW
@@ -21,6 +21,9 @@
alpha = 255
icon = null
/obj/machinery/atmospherics/pipe/manifold4w/detailed_examine()
return "This is a four-way pipe."
/obj/machinery/atmospherics/pipe/manifold4w/pipeline_expansion()
return list(node1, node2, node3, node4)
@@ -179,6 +182,10 @@
icon_connect_type = "-scrubbers"
color = PIPE_COLOR_RED
/obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers/detailed_examine()
return "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold4w/visible/supply
name="4-way air supply pipe manifold"
desc = "A manifold composed of supply pipes"
@@ -188,6 +195,10 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
/obj/machinery/atmospherics/pipe/manifold4w/visible/supply/detailed_examine()
return "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold4w/visible/yellow
color = PIPE_COLOR_YELLOW
@@ -214,6 +225,10 @@
icon_connect_type = "-scrubbers"
color = PIPE_COLOR_RED
/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers/detailed_examine()
return "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply
name="4-way air supply pipe manifold"
desc = "A manifold composed of supply pipes"
@@ -223,6 +238,10 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply/detailed_examine()
return "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold4w/hidden/yellow
color = PIPE_COLOR_YELLOW
@@ -36,6 +36,12 @@
qdel(parent)
parent = null
/obj/machinery/atmospherics/pipe/detailed_examine()
return "This pipe, and all other pipes, can be connected or disconnected by a wrench. The internal pressure of the pipe must \
be below 300 kPa to do this. More pipes can be obtained from the pipe dispenser.<br> \
Most pipes and atmospheric devices can be connected or disconnected with a wrench. The pipe's pressure must not be too high, \
or if it is a device, it must be turned off first."
/obj/machinery/atmospherics/pipe/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/analyzer))
atmosanalyzer_scan(parent.air, user)
@@ -14,6 +14,9 @@
var/icon_temperature = T20C //stop small changes in temperature causing icon refresh
resistance_flags = LAVA_PROOF | FIRE_PROOF
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/detailed_examine()
return "This radiates heat from the pipe's gas to space, cooling it down."
/obj/machinery/atmospherics/pipe/simple/heat_exchanging/process_atmos()
var/environment_temperature = 0
var/datum/gas_mixture/pipe_air = return_air()
@@ -12,6 +12,10 @@
icon_connect_type = "-scrubbers"
color = PIPE_COLOR_RED
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers/detailed_examine()
return "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/hidden/supply
name = "Air supply pipe"
desc = "A one meter section of supply pipe"
@@ -21,12 +25,19 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
/obj/machinery/atmospherics/pipe/simple/hidden/supply/detailed_examine()
return "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/hidden/universal
name="Universal pipe adapter"
desc = "An adapter for regular, supply and scrubbers pipes"
connect_types = list(1,2,3)
icon_state = "map_universal"
/obj/machinery/atmospherics/pipe/simple/hidden/universal/detailed_examine()
return "This allows you to connect 'normal' pipes, red 'scrubber' pipes, and blue 'supply' pipes."
/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_icon(safety = 0)
..()
@@ -9,3 +9,6 @@
alert_pressure = 900*ONE_ATMOSPHERE
level = 2
/obj/machinery/atmospherics/pipe/simple/insulated/detailed_examine()
return "This is completely useless, use a normal pipe." //Sorry, but it's true.
@@ -11,6 +11,10 @@
icon_connect_type = "-scrubbers"
color = PIPE_COLOR_RED
/obj/machinery/atmospherics/pipe/simple/visible/scrubbers/detailed_examine()
return "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/visible/supply
name = "Air supply pipe"
desc = "A one meter section of supply pipe"
@@ -20,6 +24,10 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
/obj/machinery/atmospherics/pipe/simple/visible/supply/detailed_examine()
return "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/visible/yellow
color = PIPE_COLOR_YELLOW
@@ -44,6 +52,9 @@
connect_types = list(1,2,3)
icon_state = "map_universal"
/obj/machinery/atmospherics/pipe/simple/visible/universal/detailed_examine()
return "This allows you to connect 'normal' pipes, red 'scrubber' pipes, and blue 'supply' pipes."
/obj/machinery/atmospherics/pipe/simple/visible/universal/update_icon(safety = 0)
..()
@@ -101,6 +101,14 @@ GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new())
color_index = list()
update_icon()
/obj/machinery/portable_atmospherics/canister/detailed_examine()
return "The canister can be connected to a connector port with a wrench. Tanks of gas (the kind you can hold in your hand) \
can be filled by the canister, by using the tank on the canister, increasing the release pressure, then opening the valve until it is full, and then close it. \
*DO NOT* remove the tank until the valve is closed. A gas analyzer can be used to check the contents of the canister."
/obj/machinery/portable_atmospherics/canister/detailed_examine_antag()
return "Canisters can be damaged, spilling their contents into the air, or you can just leave the release valve open."
/obj/machinery/portable_atmospherics/canister/proc/check_change()
var/old_flag = update_flag
update_flag = 0
@@ -19,6 +19,11 @@
/// The desired pressure the pump should be outputting, either into the atmosphere, or into a holding tank.
var/target_pressure = 101.325
/obj/machinery/portable_atmospherics/pump/detailed_examine()
return "Invaluable for filling air in a room rapidly after a breach repair. The internal gas container can be filled by \
connecting it to a connector port. The pump can pump the air in (sucking) or out (blowing), at a specific target pressure. The powercell inside can be \
replaced by using a screwdriver, and then adding a new cell. A tank of gas can also be attached to the air pump."
/obj/machinery/portable_atmospherics/pump/update_icon()
overlays = 0
@@ -14,6 +14,11 @@
/// Is this scrubber acting on the 3x3 area around it.
var/widenet = FALSE
/obj/machinery/portable_atmospherics/scrubber/detailed_examine()
return "Filters the air, placing harmful gases into the internal gas container. The container can be emptied by \
connecting it to a connector port. The pump can pump the air in (sucking) or out (blowing), at a specific target pressure. The powercell inside can be \
replaced by using a screwdriver, and then adding a new cell. A tank of gas can also be attached to the scrubber."
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
..(severity)
-4
View File
@@ -36,7 +36,6 @@
var/death_cooldown = 0 // How long you have to wait after dying before using it again, in deciseconds. People that join as observers are not included.
/obj/effect/mob_spawn/attack_ghost(mob/user)
var/mob/dead/observer/O = user
if(SSticker.current_state != GAME_STATE_PLAYING || !loc || !ghost_usable)
return
if(!uses)
@@ -48,9 +47,6 @@
if(cannotPossess(user))
to_chat(user, "<span class='warning'>Upon using the antagHUD you forfeited the ability to join the round.</span>")
return
if(!O.can_reenter_corpse)
to_chat(user, "<span class='warning'>You have forfeited the right to respawn.</span>")
return
if(time_check(user))
return
var/ghost_role = alert("Become [mob_name]? (Warning, You can no longer be cloned!)",,"Yes","No")
+1 -1
View File
@@ -47,7 +47,7 @@ GLOBAL_DATUM_INIT(the_gateway, /obj/machinery/gateway/centerstation, null)
/obj/machinery/gateway/centerstation/Initialize()
..()
update_icon()
wait = world.time + config.gateway_delay
wait = world.time + GLOB.configuration.gateway.away_mission_delay
return INITIALIZE_HINT_LATELOAD
/obj/machinery/gateway/centerstation/LateInitialize()
@@ -124,6 +124,13 @@
if(.)
return
if(isgolem(user) && can_transfer)
var/datum/species/golem/g = user.dna.species
if(g.owner)
has_owner = TRUE
owner = g.owner
else
has_owner = FALSE
owner = null
var/transfer_choice = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No")
if(transfer_choice != "Yes")
return
@@ -144,9 +151,17 @@
return
if(QDELETED(src) || uses <= 0 || user.stat >= 1 || QDELETED(I))
return
if(istype(src, /obj/effect/mob_spawn/human/golem/servant))
if(istype(src, /obj/effect/mob_spawn/human/golem/servant) && !isgolem(user))
has_owner = FALSE
flavour_text = null
if(isgolem(user) && can_transfer)
var/datum/species/golem/g = user.dna.species
if(g.owner)
has_owner = TRUE
owner = g.owner
else
has_owner = FALSE
owner = null
flavour_text = null
user.visible_message("<span class='notice'>As [user] applies the potion on the golem shell, a faint light leaves them, moving to [src] and animating it!</span>",
"<span class='notice'>You apply the potion to [src], feeling your mind leave your body!</span>")
message_admins("[key_name(user)] used [I] to transfer their mind into [src]")
-35
View File
@@ -1,5 +1,3 @@
GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away_mission_config.txt"))
// Call this before you remove the last dirt on a z level - that way, all objects
// will have proper atmos and other important enviro things
/proc/late_setup_level(turfs, smoothTurfs)
@@ -38,39 +36,6 @@ GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away
qdel(otherthing)
T.ChangeTurf(T.baseturf)
/proc/generateMapList(filename)
var/list/potentialMaps = list()
var/list/Lines = file2list(filename)
if(!Lines.len)
return
for(var/t in Lines)
if(!t)
continue
t = trim(t)
if(length(t) == 0)
continue
else if(copytext(t, 1, 2) == "#")
continue
var/pos = findtext(t, " ")
var/name = null
if(pos)
name = lowertext(copytext(t, 1, pos))
else
name = lowertext(t)
if(!name)
continue
potentialMaps.Add(t)
return potentialMaps
/datum/map_template/ruin/proc/try_to_place(z,allowed_areas)
var/sanity = PLACEMENT_TRIES
while(sanity > 0)
+7 -7
View File
@@ -1,12 +1,12 @@
// This is in its own file as it has so much stuff to contend with
/client/proc/edit_2fa()
if(!config._2fa_auth_host)
if(!GLOB.configuration.system._2fa_auth_host)
alert(usr, "This server does not have 2FA enabled.")
return
// Client does not have 2FA enabled. Set it up.
if(prefs._2fa_status == _2FA_DISABLED)
// Get us an auth token
var/datum/http_response/qrcr = wrap_http_get("[config._2fa_auth_host]/generateQR?ckey=[ckey]")
var/datum/http_response/qrcr = wrap_http_get("[GLOB.configuration.system._2fa_auth_host]/generateQR?ckey=[ckey]")
// If this fails, shits gone bad
if(qrcr.errored)
alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [qrcr.error]")
@@ -27,13 +27,13 @@
var/entered_code = input(usr, "Please enter a code from your auth app. Failure to enter the code correctly will abort 2FA setup.", "2FA Validation")
if(!entered_code)
// Cleanup so they can start again
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM [format_table_name("2fa_secrets")] WHERE ckey=:ckey", list("ckey" = ckey))
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM 2fa_secrets WHERE ckey=:ckey", list("ckey" = ckey))
dbq.warn_execute()
alert(usr, "2FA Setup aborted!")
B.close()
return
var/datum/http_response/vr = wrap_http_get("[config._2fa_auth_host]/validateCode?ckey=[ckey]&code=[entered_code]")
var/datum/http_response/vr = wrap_http_get("[GLOB.configuration.system._2fa_auth_host]/validateCode?ckey=[ckey]&code=[entered_code]")
// If this fails, shits gone bad
if(vr.errored)
alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [vr.error]")
@@ -42,7 +42,7 @@
if(vr.status_code != 200)
// Cleanup so they can start again
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM [format_table_name("2fa_secrets")] WHERE ckey=:ckey", list("ckey" = ckey))
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM 2fa_secrets WHERE ckey=:ckey", list("ckey" = ckey))
dbq.warn_execute()
// See if its unauthorised. I used 400 for that dont at me
@@ -86,7 +86,7 @@
alert(usr, "2FA deactivation aborted!")
return
var/datum/http_response/vr = wrap_http_get("[config._2fa_auth_host]/validateCode?ckey=[ckey]&code=[entered_code]")
var/datum/http_response/vr = wrap_http_get("[GLOB.configuration.system._2fa_auth_host]/validateCode?ckey=[ckey]&code=[entered_code]")
// If this fails, shits gone bad
if(vr.errored)
alert(usr, "Something has gone VERY wrong ingame. Please inform the server host.\nError details: [vr.error]")
@@ -101,7 +101,7 @@
return
// If we are here, they authed properly
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM [format_table_name("2fa_secrets")] WHERE ckey=:ckey", list("ckey" = ckey))
var/datum/db_query/dbq = SSdbcore.NewQuery("DELETE FROM 2fa_secrets WHERE ckey=:ckey", list("ckey" = ckey))
dbq.warn_execute()
prefs._2fa_status = _2FA_DISABLED
prefs.save_preferences(src)
+3 -1
View File
@@ -56,7 +56,6 @@
var/global/obj/screen/click_catcher/void
var/karma = 0
var/karma_spent = 0
var/karma_tab = 0
@@ -69,6 +68,9 @@
//datum that controls the displaying and hiding of tooltips
var/datum/tooltip/tooltips
/// Persistent storage for the flavour text of examined atoms.
var/list/description_holders = list()
// Their chat window, sort of important.
// See /goon/code/datums/browserOutput.dm
var/datum/chatOutput/chatOutput
+51 -59
View File
@@ -122,11 +122,12 @@
//Logs all hrefs
if(config && config.log_hrefs)
if(GLOB.configuration.logging.href_logging)
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
if(href_list["karmashop"])
if(config.disable_karma)
if(!GLOB.configuration.general.enable_karma)
to_chat(src, "Karma is disabled on this server.")
return
switch(href_list["karmashop"])
@@ -218,7 +219,7 @@
to_chat(src, "<span class='danger'>You are sending messages to quickly. Please wait [wait_time] [wait_time == 1 ? "second" : "seconds"] before sending another message.</span>")
return 1
last_message_time = world.time
if(config.automute_on && !check_rights(R_ADMIN, 0) && last_message == message)
if(GLOB.configuration.general.enable_auto_mute && !check_rights(R_ADMIN, 0) && last_message == message)
last_message_count++
if(last_message_count >= SPAM_TRIGGER_AUTOMUTE)
to_chat(src, "<span class='danger'>You have exceeded the spam filter limit for identical messages. An auto-mute was applied.</span>")
@@ -259,7 +260,7 @@
return null
if(byond_version < MIN_CLIENT_VERSION) // Too out of date to play at all. Unfortunately, we can't send them a message here.
version_blocked = TRUE
if(byond_build < config.minimum_client_build)
if(byond_build < GLOB.configuration.general.minimum_client_build)
version_blocked = TRUE
var/show_update_prompt = FALSE
@@ -274,7 +275,7 @@
GLOB.directory[ckey] = src
//Admin Authorisation
// Automatically makes localhost connection an admin
if(!config.disable_localhost_admin)
if(GLOB.configuration.admin.enable_localhost_autoadmin)
if(is_connecting_from_localhost())
new /datum/admins("!LOCALHOST!", R_HOST, ckey) // Makes localhost rank
holder = GLOB.admin_datums[ckey]
@@ -306,10 +307,6 @@
spawn() // Goonchat does some non-instant checks in start()
chatOutput.start()
if( (world.address == address || !address) && !GLOB.host )
GLOB.host = key
world.update_status()
if(holder)
on_holder_add()
add_admin_verbs()
@@ -383,7 +380,7 @@
playercount += 1
// Update the state of the panic bunker based on current playercount
var/threshold = config.panic_bunker_threshold
var/threshold = GLOB.configuration.general.panic_bunker_threshold
if((playercount > threshold) && (GLOB.panic_bunker_enabled == FALSE))
GLOB.panic_bunker_enabled = TRUE
@@ -445,7 +442,7 @@
return
//Donator stuff.
var/datum/db_query/query_donor_select = SSdbcore.NewQuery("SELECT ckey, tier, active FROM `[format_table_name("donators")]` WHERE ckey=:ckey", list(
var/datum/db_query/query_donor_select = SSdbcore.NewQuery("SELECT ckey, tier, active FROM donators WHERE ckey=:ckey", list(
"ckey" = ckey
))
@@ -466,7 +463,7 @@
/client/proc/donor_loadout_points()
if(donator_level > 0 && prefs)
prefs.max_gear_slots = config.max_loadout_points + 5
prefs.max_gear_slots = GLOB.configuration.general.base_loadout_points + 5
/client/proc/log_client_to_db(connectiontopic)
set waitfor = FALSE // This needs to run async because any sleep() inside /client/New() breaks stuff badly
@@ -476,7 +473,7 @@
if(!SSdbcore.IsConnected())
return
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey=:ckey", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM player WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
@@ -491,7 +488,7 @@
break
qdel(query)
var/datum/db_query/query_ip = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip=:address", list(
var/datum/db_query/query_ip = SSdbcore.NewQuery("SELECT ckey FROM player WHERE ip=:address", list(
"address" = address
))
if(!query_ip.warn_execute())
@@ -504,7 +501,7 @@
qdel(query_ip)
var/datum/db_query/query_cid = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid=:cid", list(
var/datum/db_query/query_cid = SSdbcore.NewQuery("SELECT ckey FROM player WHERE computerid=:cid", list(
"cid" = computer_id
))
if(!query_cid.warn_execute())
@@ -551,7 +548,7 @@
if(!client_address) // Localhost can sometimes have no address set
client_address = "127.0.0.1"
//Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip=:sql_ip, computerid=:sql_cid, lastadminrank=:sql_ar WHERE id=:sql_id", list(
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE player SET lastseen = Now(), ip=:sql_ip, computerid=:sql_cid, lastadminrank=:sql_ar WHERE id=:sql_id", list(
"sql_ip" = client_address,
"sql_cid" = computer_id,
"sql_ar" = admin_rank,
@@ -566,15 +563,7 @@
INVOKE_ASYNC(src, /client/.proc/get_byond_account_date, FALSE) // Async to avoid other procs in the client chain being delayed by a web request
else
//New player!! Need to insert all the stuff
// Check new peeps for panic bunker
if(GLOB.panic_bunker_enabled)
var/threshold = config.panic_bunker_threshold
src << "Server is not accepting connections from never-before-seen players until player count is less than [threshold]. Please try again later."
qdel(src)
return // Dont insert or they can just go in again
var/datum/db_query/query_insert = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, :ckey, Now(), Now(), :ip, :cid, :rank)", list(
var/datum/db_query/query_insert = SSdbcore.NewQuery("INSERT INTO player (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, :ckey, Now(), Now(), :ip, :cid, :rank)", list(
"ckey" = ckey,
"ip" = address,
"cid" = computer_id,
@@ -593,33 +582,36 @@
/client/proc/check_ip_intel()
set waitfor = 0 //we sleep when getting the intel, no need to hold up the client connection while we sleep
if(config.ipintel_email)
if(config.ipintel_maxplaytime && config.use_exp_tracking)
if(GLOB.configuration.ipintel.enabled)
if(GLOB.configuration.ipintel.playtime_ignore_threshold && GLOB.configuration.jobs.enable_exp_tracking)
var/living_hours = get_exp_type_num(EXP_TYPE_LIVING) / 60
if(living_hours >= config.ipintel_maxplaytime)
if(living_hours >= GLOB.configuration.ipintel.playtime_ignore_threshold)
return
if(is_connecting_from_localhost())
log_debug("check_ip_intel: skip check for player [key_name_admin(src)] connecting from localhost.")
return
if(vpn_whitelist_check(ckey))
if(SSipintel.vpn_whitelist_check(ckey))
log_debug("check_ip_intel: skip check for player [key_name_admin(src)] [address] on whitelist.")
return
var/datum/ipintel/res = get_ip_intel(address)
var/datum/ipintel/res = SSipintel.get_ip_intel(address)
ip_intel = res.intel
verify_ip_intel()
/client/proc/verify_ip_intel()
if(ip_intel >= config.ipintel_rating_bad)
var/detailsurl = config.ipintel_detailsurl ? "(<a href='[config.ipintel_detailsurl][address]'>IP Info</a>)" : ""
if(config.ipintel_whitelist)
if(ip_intel >= GLOB.configuration.ipintel.bad_rating)
var/detailsurl = GLOB.configuration.ipintel.details_url ? "(<a href='[GLOB.configuration.ipintel.details_url][address]'>IP Info</a>)" : ""
if(GLOB.configuration.ipintel.whitelist_mode)
// Do not move this to isBanned(). This may sound weird, but:
// This needs to happen after their account is put into the DB
// This way, admins can then note people
spawn(40) // This is necessary because without it, they won't see the message, and addtimer cannot be used because the timer system may not have initialized yet
message_admins("<span class='adminnotice'>IPIntel: [key_name_admin(src)] on IP [address] was rejected. [detailsurl]</span>")
var/blockmsg = "<B>Error: proxy/VPN detected. Proxy/VPN use is not allowed here. Deactivate it before you reconnect.</B>"
if(config.banappeals)
blockmsg += "\nIf you are not actually using a proxy/VPN, or have no choice but to use one, request whitelisting at: [config.banappeals]"
if(GLOB.configuration.url.banappeals_url)
blockmsg += "\nIf you are not actually using a proxy/VPN, or have no choice but to use one, request whitelisting at: [GLOB.configuration.url.banappeals_url]"
to_chat(src, blockmsg)
qdel(src)
else
@@ -627,16 +619,16 @@
/client/proc/check_forum_link()
if(!config.forum_link_url || !prefs || prefs.fuid)
if(!GLOB.configuration.url.forum_link_url || !prefs || prefs.fuid)
return
if(config.use_exp_tracking)
if(GLOB.configuration.jobs.enable_exp_tracking)
var/living_hours = get_exp_type_num(EXP_TYPE_LIVING) / 60
if(living_hours < 20)
return
to_chat(src, "<B>You have no verified forum account. <a href='?src=[UID()];link_forum_account=true'>VERIFY FORUM ACCOUNT</a></B>")
/client/proc/create_oauth_token()
var/datum/db_query/query_find_token = SSdbcore.NewQuery("SELECT token FROM [format_table_name("oauth_tokens")] WHERE ckey=:ckey limit 1", list(
var/datum/db_query/query_find_token = SSdbcore.NewQuery("SELECT token FROM oauth_tokens WHERE ckey=:ckey limit 1", list(
"ckey" = ckey
))
// These queries have log_error=FALSE to avoid auth tokens being in plaintext logs
@@ -651,7 +643,7 @@
var/tokenstr = md5("[rand(0,9999)][world.time][rand(0,9999)][ckey][rand(0,9999)][address][rand(0,9999)][computer_id][rand(0,9999)]")
var/datum/db_query/query_insert_token = SSdbcore.NewQuery("INSERT INTO [format_table_name("oauth_tokens")] (ckey, token) VALUES(:ckey, :tokenstr)", list(
var/datum/db_query/query_insert_token = SSdbcore.NewQuery("INSERT INTO oauth_tokens (ckey, token) VALUES(:ckey, :tokenstr)", list(
"ckey" = ckey,
"tokenstr" = tokenstr,
))
@@ -663,7 +655,7 @@
return tokenstr
/client/proc/link_forum_account(fromban)
if(!config.forum_link_url)
if(!GLOB.configuration.url.forum_link_url)
return
if(IsGuestKey(key))
to_chat(src, "Guest keys cannot be linked.")
@@ -672,7 +664,7 @@
if(!fromban)
to_chat(src, "Your forum account is already set.")
return
var/datum/db_query/query_find_link = SSdbcore.NewQuery("SELECT fuid FROM [format_table_name("player")] WHERE ckey=:ckey LIMIT 1", list(
var/datum/db_query/query_find_link = SSdbcore.NewQuery("SELECT fuid FROM player WHERE ckey=:ckey LIMIT 1", list(
"ckey" = ckey
))
if(!query_find_link.warn_execute())
@@ -689,7 +681,7 @@
if(!tokenid)
to_chat(src, "link_forum_account: unable to create token")
return
var/url = "[config.forum_link_url][tokenid]"
var/url = "[GLOB.configuration.url.forum_link_url][tokenid]"
if(fromban)
url += "&fwd=appeal"
to_chat(src, {"Now opening a window to verify your information with the forums, so that you can appeal your ban. If the window does not load, please copy/paste this link: <a href="[url]">[url]</a>"})
@@ -709,7 +701,7 @@
if(connection != "seeker") //Invalid connection type.
return null
topic = params2list(topic)
if(!config.check_randomizer)
if(!GLOB.configuration.general.enabled_cid_randomiser_buster)
return
// Stash o' ckeys
var/static/cidcheck = list()
@@ -721,7 +713,7 @@
var/oldcid = cidcheck[ckey]
if(!oldcid)
var/datum/db_query/query_cidcheck = SSdbcore.NewQuery("SELECT computerid FROM [format_table_name("player")] WHERE ckey=:ckey", list(
var/datum/db_query/query_cidcheck = SSdbcore.NewQuery("SELECT computerid FROM player WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_cidcheck.warn_execute())
@@ -791,7 +783,7 @@
var/const/adminckey = "CID-Error"
// Check for notes in the last day - only 1 note per 24 hours
var/datum/db_query/query_get_notes = SSdbcore.NewQuery("SELECT id from [format_table_name("notes")] WHERE ckey=:ckey AND adminckey=:adminckey AND timestamp + INTERVAL 1 DAY < NOW()", list(
var/datum/db_query/query_get_notes = SSdbcore.NewQuery("SELECT id from notes WHERE ckey=:ckey AND adminckey=:adminckey AND timestamp + INTERVAL 1 DAY < NOW()", list(
"ckey" = ckey,
"adminckey" = adminckey
))
@@ -804,7 +796,7 @@
qdel(query_get_notes)
// Only add a note if their most recent note isn't from the randomizer blocker, either
var/datum/db_query/query_get_note = SSdbcore.NewQuery("SELECT adminckey FROM [format_table_name("notes")] WHERE ckey=:ckey ORDER BY timestamp DESC LIMIT 1", list(
var/datum/db_query/query_get_note = SSdbcore.NewQuery("SELECT adminckey FROM notes WHERE ckey=:ckey ORDER BY timestamp DESC LIMIT 1", list(
"ckey" = ckey
))
if(!query_get_note.warn_execute())
@@ -842,8 +834,8 @@
//Send resources to the client.
/client/proc/send_resources()
// Change the way they should download resources.
if(config.resource_urls)
preload_rsc = pick(config.resource_urls)
if(length(GLOB.configuration.url.rsc_urls))
preload_rsc = pick(GLOB.configuration.url.rsc_urls)
else
preload_rsc = 1 // If config.resource_urls is not set, preload like normal.
// Most assets are now handled through global_cache.dm
@@ -949,7 +941,7 @@
void.UpdateGreed(actualview[1],actualview[2])
/client/proc/send_ssd_warning(mob/M)
if(!config.ssd_warning)
if(!GLOB.configuration.general.ssd_warning)
return FALSE
if(ssd_warning_acknowledged)
return FALSE
@@ -1054,7 +1046,7 @@
*/
/client/proc/get_byond_account_date(notify = FALSE)
// First we see if the client has a saved date in the DB
var/datum/db_query/query_date = SSdbcore.NewQuery("SELECT byond_date, DATEDIFF(Now(), byond_date) FROM [format_table_name("player")] WHERE ckey=:ckey", list(
var/datum/db_query/query_date = SSdbcore.NewQuery("SELECT byond_date, DATEDIFF(Now(), byond_date) FROM player WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_date.warn_execute())
@@ -1080,7 +1072,7 @@
byondacc_date = byond_data["general"]["joined"]
// Now save it
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET byond_date=:date WHERE ckey=:ckey", list(
var/datum/db_query/query_update = SSdbcore.NewQuery("UPDATE player SET byond_date=:date WHERE ckey=:ckey", list(
"date" = byondacc_date,
"ckey" = ckey
))
@@ -1090,7 +1082,7 @@
qdel(query_update)
// Now retrieve the age again because BYOND doesnt have native methods for this
var/datum/db_query/query_age = SSdbcore.NewQuery("SELECT DATEDIFF(Now(), byond_date) FROM [format_table_name("player")] WHERE ckey=:ckey", list(
var/datum/db_query/query_age = SSdbcore.NewQuery("SELECT DATEDIFF(Now(), byond_date) FROM player WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query_age.warn_execute())
@@ -1102,7 +1094,7 @@
qdel(query_age)
// Notify admins on new clients connecting, if the byond account age is less than a config value
if(notify && (byondacc_age < config.byond_account_age_threshold))
if(notify && (byondacc_age < GLOB.configuration.general.byond_account_age_threshold))
message_admins("[key] has just connected for the first time. BYOND account registered on [byondacc_date] ([byondacc_age] days old)")
/client/proc/show_update_notice()
@@ -1125,7 +1117,7 @@
tos_consent = TRUE
return TRUE
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("privacy")] WHERE ckey=:ckey AND consent=1", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey FROM privacy WHERE ckey=:ckey AND consent=1", list(
"ckey" = ckey
))
if(!query.warn_execute())
@@ -1149,7 +1141,7 @@
*/
/client/proc/cid_count_check()
// If the config is 0, disable this
if(config.max_client_cid_history == 0)
if(GLOB.configuration.general.max_client_cid_history == 0)
return
// If we have no DB, dont even bother
@@ -1169,11 +1161,11 @@
cidcount = query_cidcheck.item[1]
qdel(query_cidcheck)
if(cidcount > config.max_client_cid_history)
if(cidcount > GLOB.configuration.general.max_client_cid_history)
// Check their notes for CID tracking in the past
var/has_note = FALSE
var/note_text = ""
var/datum/db_query/query_find_track_note = SSdbcore.NewQuery("SELECT notetext FROM [format_table_name("notes")] WHERE ckey=:ckey AND adminckey=:ackey", list(
var/datum/db_query/query_find_track_note = SSdbcore.NewQuery("SELECT notetext FROM notes WHERE ckey=:ckey AND adminckey=:ackey", list(
"ckey" = ckey,
"ackey" = CIDTRACKING_PSUEDO_CKEY
))
@@ -1190,7 +1182,7 @@
var/new_text = "Connected on the date of this note with unique CID #[cidcount]"
// Only update the note if the text is different. Otherwise it bumps the timestamp when it shouldnt
if(note_text != new_text)
var/datum/db_query/query_update_track_note = SSdbcore.NewQuery("UPDATE [format_table_name("notes")] SET notetext=:notetext, timestamp=NOW(), round_id=:rid WHERE ckey=:ckey AND adminckey=:ackey", list(
var/datum/db_query/query_update_track_note = SSdbcore.NewQuery("UPDATE notes SET notetext=:notetext, timestamp=NOW(), round_id=:rid WHERE ckey=:ckey AND adminckey=:ackey", list(
"notetext" = new_text,
"ckey" = ckey,
"ackey" = CIDTRACKING_PSUEDO_CKEY,
@@ -1208,7 +1200,7 @@
var/show_warning = TRUE
// Check if they have a note that matches the warning suppressor
var/datum/db_query/query_find_note = SSdbcore.NewQuery("SELECT id FROM [format_table_name("notes")] WHERE ckey=:ckey AND notetext=:notetext", list(
var/datum/db_query/query_find_note = SSdbcore.NewQuery("SELECT id FROM notes WHERE ckey=:ckey AND notetext=:notetext", list(
"ckey" = ckey,
"notetext" = CIDWARNING_SUPPRESSED_NOTETEXT
))
@@ -34,13 +34,13 @@
description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races."
path = /obj/item/clothing/glasses/tajblind/eng
cost = 2
/datum/gear/racial/taj/cargo
display_name = "khaki veil"
description = "A common traditional nano-fiber veil worn by many Tajaran, It is rare and offensive to see it on other races. It is light and comfy!"
path = /obj/item/clothing/glasses/tajblind/cargo
cost = 2
/datum/gear/racial/footwraps
display_name = "cloth footwraps"
path = /obj/item/clothing/shoes/footwraps
@@ -108,6 +108,11 @@
path = /obj/item/clothing/suit/armor/secjacket
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Security Pod Pilot")
/datum/gear/suit/secbomberjacket
display_name = "security bomber jacket"
path = /obj/item/clothing/suit/jacket/pilot
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Security Pod Pilot")
/datum/gear/suit/ianshirt
display_name = "Ian Shirt"
path = /obj/item/clothing/suit/ianshirt
+11 -38
View File
@@ -38,7 +38,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
return 0
if(!role)
return 0
if(!config.use_age_restriction_for_antags)
if(!GLOB.configuration.gamemode.antag_account_age_restriction)
return 0
if(!isnum(C.player_age))
return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced
@@ -214,7 +214,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
parent = C
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
max_gear_slots = config.max_loadout_points
max_gear_slots = GLOB.configuration.general.base_loadout_points
var/loaded_preferences_successfully = FALSE
if(istype(C))
if(!IsGuestKey(C.key))
@@ -473,7 +473,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
dat += "<b>Ghost PDA:</b> <a href='?_src_=prefs;preference=ghost_pda'><b>[(toggles & PREFTOGGLE_CHAT_GHOSTPDA) ? "All PDA Messages" : "No PDA Messages"]</b></a><br>"
if(check_rights(R_ADMIN,0))
dat += "<b>OOC Color:</b> <span style='border: 1px solid #161616; background-color: [ooccolor ? ooccolor : GLOB.normal_ooc_colour];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=ooccolor;task=input'><b>Change</b></a><br>"
if(config.allow_Metadata)
if(GLOB.configuration.general.allow_character_metadata)
dat += "<b>OOC Notes:</b> <a href='?_src_=prefs;preference=metadata;task=input'><b>Edit</b></a><br>"
dat += "<b>Parallax (Fancy Space):</b> <a href='?_src_=prefs;preference=parallax'>"
switch (parallax)
@@ -1102,9 +1102,9 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
ResetJobs()
SetChoices(user)
if("learnaboutselection")
if(config.wikiurl)
if(GLOB.configuration.url.wiki_url)
if(alert("Would you like to open the Job selection info in your browser?", "Open Job Selection", "Yes", "No") == "Yes")
user << link("[config.wikiurl]/index.php/Job_Selection_and_Assignment")
user << link("[GLOB.configuration.url.wiki_url]/index.php/Job_Selection_and_Assignment")
else
to_chat(user, "<span class='danger'>The Wiki URL is not set in the server configuration.</span>")
if("random")
@@ -1321,17 +1321,10 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
if("species")
var/list/new_species = list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin")
var/prev_species = species
// var/whitelisted = 0
if(config.usealienwhitelist) //If we're using the whitelist, make sure to check it!
for(var/Spec in GLOB.whitelisted_species)
if(is_alien_whitelisted(user,Spec))
new_species += Spec
// whitelisted = 1
// if(!whitelisted)
// alert(user, "You cannot change your species as you need to be whitelisted. If you wish to be whitelisted contact an admin in-game, on the forums, or on IRC.")
else //Not using the whitelist? Aliens for everyone!
new_species += GLOB.whitelisted_species
for(var/species in GLOB.whitelisted_species)
if(is_alien_whitelisted(user, species))
new_species += species
species = input("Please select a species", "Character Generation", null) in sortTim(new_species, /proc/cmp_text_asc)
var/datum/species/NS = GLOB.all_species[species]
@@ -1414,18 +1407,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
if("language")
// var/languages_available
var/list/new_languages = list("None")
/*
if(config.usealienwhitelist)
for(var/L in GLOB.all_languages)
var/datum/language/lang = GLOB.all_languages[L]
if((!(lang.flags & RESTRICTED)) && (is_alien_whitelisted(user, L)||(!( lang.flags & WHITELISTED ))))
new_languages += lang
languages_available = 1
if(!(languages_available))
alert(user, "There are not currently any available secondary languages.")
else
*/
for(var/L in GLOB.all_languages)
var/datum/language/lang = GLOB.all_languages[L]
if(!(lang.flags & RESTRICTED))
@@ -2029,8 +2010,8 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
if("afk_watch")
if(!(toggles2 & PREFTOGGLE_2_AFKWATCH))
to_chat(user, "<span class='info'>You will now get put into cryo dorms after [config.auto_cryo_afk] minutes. \
Then after [config.auto_despawn_afk] minutes you will be fully despawned. You will receive a visual and auditory warning before you will be put into cryodorms.</span>")
to_chat(user, "<span class='info'>You will now get put into cryo dorms after [GLOB.configuration.afk.auto_cryo_minutes] minutes. \
Then after [GLOB.configuration.afk.auto_despawn_minutes] minutes you will be fully despawned. You will receive a visual and auditory warning before you will be put into cryodorms.</span>")
else
to_chat(user, "<span class='info'>Automatic cryoing turned off.</span>")
toggles2 ^= PREFTOGGLE_2_AFKWATCH
@@ -2162,14 +2143,6 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
if(be_random_name)
real_name = random_name(gender,species)
if(config.humans_need_surnames)
var/firstspace = findtext(real_name, " ")
var/name_length = length(real_name)
if(!firstspace) //we need a surname
real_name += " [pick(GLOB.last_names)]"
else if(firstspace == name_length)
real_name += "[pick(GLOB.last_names)]"
character.add_language(language)
@@ -2326,7 +2299,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
/datum/preferences/proc/open_load_dialog(mob/user)
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot, real_name FROM [format_table_name("characters")] WHERE ckey=:ckey ORDER BY slot", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot, real_name FROM characters WHERE ckey=:ckey ORDER BY slot", list(
"ckey" = user.ckey
))
var/list/slotnames[max_save_slots]
@@ -18,7 +18,7 @@
fuid,
parallax,
2fa_status
FROM [format_table_name("player")]
FROM player
WHERE ckey=:ckey"}, list(
"ckey" = C.ckey
))
@@ -80,7 +80,7 @@
deltimer(volume_mixer_saving)
volume_mixer_saving = null
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE [format_table_name("player")]
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE player
SET
ooccolor=:ooccolour,
UI_style=:ui_style,
@@ -126,14 +126,15 @@
qdel(query)
return 1
/datum/preferences/proc/load_character(client/C,slot)
/datum/preferences/proc/load_character(client/C, slot)
saved = FALSE
if(!slot) slot = default_slot
if(!slot)
slot = default_slot
slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot))
if(slot != default_slot)
default_slot = slot
var/datum/db_query/firstquery = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET default_slot=:slot WHERE ckey=:ckey", list(
var/datum/db_query/firstquery = SSdbcore.NewQuery("UPDATE player SET default_slot=:slot WHERE ckey=:ckey", list(
"slot" = slot,
"ckey" = C.ckey
))
@@ -142,6 +143,10 @@
return
qdel(firstquery)
if(!C) // If the client disconnected during the query, try again later.
qdel(src)
return TRUE
// Let's not have this explode if you sneeze on the DB
var/datum/db_query/query = SSdbcore.NewQuery({"SELECT
OOC_Notes,
@@ -196,7 +201,7 @@
body_accessory,
gear,
autohiss
FROM [format_table_name("characters")] WHERE ckey=:ckey AND slot=:slot"}, list(
FROM characters WHERE ckey=:ckey AND slot=:slot"}, list(
"ckey" = C.ckey,
"slot" = slot
))
@@ -360,7 +365,7 @@
if(!isemptylist(loadout_gear))
gearlist = list2params(loadout_gear)
var/datum/db_query/firstquery = SSdbcore.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey=:ckey ORDER BY slot", list(
var/datum/db_query/firstquery = SSdbcore.NewQuery("SELECT slot FROM characters WHERE ckey=:ckey ORDER BY slot", list(
"ckey" = C.ckey
))
if(!firstquery.warn_execute())
@@ -368,7 +373,7 @@
return
while(firstquery.NextRow())
if(text2num(firstquery.item[1]) == default_slot)
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE [format_table_name("characters")]
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE characters
SET
OOC_Notes=:metadata,
real_name=:real_name,
@@ -493,7 +498,7 @@
qdel(firstquery)
var/datum/db_query/query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("characters")] (ckey, slot, OOC_Notes, real_name, name_is_always_random, gender,
INSERT INTO characters (ckey, slot, OOC_Notes, real_name, name_is_always_random, gender,
age, species, language,
hair_colour, secondary_hair_colour,
facial_hair_colour, secondary_facial_hair_colour,
@@ -615,7 +620,7 @@
return 1
/datum/preferences/proc/load_random_character_slot(client/C)
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey=:ckey ORDER BY slot", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot FROM characters WHERE ckey=:ckey ORDER BY slot", list(
"ckey" = C.ckey
))
var/list/saves = list()
@@ -637,7 +642,7 @@
/datum/preferences/proc/clear_character_slot(client/C)
. = FALSE
// Is there a character in that slot?
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey=:ckey AND slot=:slot", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT slot FROM characters WHERE ckey=:ckey AND slot=:slot", list(
"ckey" = C.ckey,
"slot" = default_slot
))
@@ -652,7 +657,7 @@
qdel(query)
var/datum/db_query/delete_query = SSdbcore.NewQuery("DELETE FROM [format_table_name("characters")] WHERE ckey=:ckey AND slot=:slot", list(
var/datum/db_query/delete_query = SSdbcore.NewQuery("DELETE FROM characters WHERE ckey=:ckey AND slot=:slot", list(
"ckey" = C.ckey,
"slot" = default_slot
))
@@ -673,7 +678,7 @@
volume_mixer_saving = null
var/datum/db_query/update_query = SSdbcore.NewQuery(
"UPDATE [format_table_name("player")] SET volume_mixer=:volume_mixer WHERE ckey=:ckey",
"UPDATE player SET volume_mixer=:volume_mixer WHERE ckey=:ckey",
list(
"volume_mixer" = serialize_volume_mixer(volume_mixer),
"ckey" = parent.ckey
+2 -4
View File
@@ -394,8 +394,7 @@ BLIND // can't see anything
if(H.l_hand && H.r_hand) //If both hands are occupied, drop the object on the ground.
user.unEquip(src)
else //Otherwise, put it in an available hand, the active one preferentially.
src.loc = user
H.head = null
user.unEquip(src)
user.put_in_hands(src)
else
icon_state += "_up"
@@ -420,8 +419,7 @@ BLIND // can't see anything
if(H.l_hand && H.r_hand) //If both hands are occupied, drop the object on the ground.
user.unEquip(src)
else //Otherwise, put it in an available hand, the active one preferentially.
src.loc = user
user.wear_mask = null
user.unEquip(src)
user.put_in_hands(src)
H.wear_mask_update(src, toggle_off = mask_adjusted)
usr.update_inv_wear_mask()
+1
View File
@@ -171,6 +171,7 @@
desc = "An Ahdominian made veil that allows the user to see while obscuring their eyes. This one has an in-built security HUD."
icon_state = "tajblind_sec"
item_state = "tajblind_sec"
flash_protect = FLASH_PROTECTION_FLASH
flags_cover = GLASSESCOVERSEYES
actions_types = list(/datum/action/item_action/toggle)
up = 0
+3 -1
View File
@@ -9,13 +9,15 @@
resistance_flags = NONE
/obj/item/clothing/gloves/color/yellow/power
description_antag = "These are a pair of power gloves, and can be used to fire bolts of electricity while standing over powered power cables."
var/old_mclick_override
var/datum/middleClickOverride/power_gloves/mclick_override = new /datum/middleClickOverride/power_gloves
var/last_shocked = 0
var/shock_delay = 40
var/unlimited_power = FALSE // Does this really need explanation?
/obj/item/clothing/gloves/color/yellow/power/detailed_examine_antag()
return "These are a pair of power gloves, and can be used to fire bolts of electricity while standing over powered power cables."
/obj/item/clothing/gloves/color/yellow/power/equipped(mob/user, slot)
if(!ishuman(user))
return
+1 -1
View File
@@ -120,7 +120,7 @@
strip_delay = 80
/obj/item/clothing/suit/armor/hos/alt
name = "armored trenchoat"
name = "armored trenchcoat"
desc = "A trenchcoat enhanced with a special lightweight kevlar. The epitome of tactical plainclothes."
icon_state = "hostrench_open"
item_state = "hostrench_open"
+4 -2
View File
@@ -803,7 +803,7 @@
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
strip_delay = 60
put_on_delay = 40
armor = list(melee = 25, bullet = 15, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0, fire = 50, acid = 50)
armor = list(melee = 15, bullet = 5, laser = 15, energy = 5, bomb = 15, bio = 0, rad = 0, fire = 30, acid = 30)
//End of inheritance from Security armour.
/obj/item/clothing/suit/jacket/leather
@@ -967,11 +967,13 @@
//Syndicate Chaplain Robe (WOLOLO!)
/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe
description_antag = "This robe is made of reinforced fibers, granting it superior protection. The robes also wirelessly generate power for the neurotransmitter in the linked missionary staff while being worn."
w_class = WEIGHT_CLASS_NORMAL
armor = list(melee = 10, bullet = 10, laser = 5, energy = 5, bomb = 0, bio = 0, rad = 15, fire = 30, acid = 30)
var/obj/item/nullrod/missionary_staff/linked_staff = null
/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe/detailed_examine_antag()
return "This robe is made of reinforced fibers, granting it superior protection. The robes also wirelessly generate power for the neurotransmitter in the linked missionary staff while being worn."
/obj/item/clothing/suit/hooded/chaplain_hoodie/missionary_robe/Destroy()
if(linked_staff) //delink on destruction
linked_staff.robes = null
+3 -3
View File
@@ -1470,13 +1470,13 @@
/obj/item/clothing/head/fluff/lfbowler //Lightfire: Hyperion
name = "Classy bowler hat"
desc = "a very classy looking bowler hat"
name = "classy bowler hat"
desc = "A very classy looking bowler hat."
icon = 'icons/obj/custom_items.dmi'
icon_state = "bowler_lightfire"
/obj/item/clothing/under/fluff/lfvicsuit //Lightfire: Hyperion
name = "Classy victorian suit"
name = "classy victorian suit"
desc = "A blue and black victorian suit with silver buttons, very fancy!"
icon = 'icons/obj/custom_items.dmi'
lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi'
+1 -1
View File
@@ -4,7 +4,7 @@
// Grab the info we want.
var/datum/db_query/query = SSdbcore.NewQuery({"
SELECT cuiPath, cuiPropAdjust, cuiJobMask, cuiDescription, cuiItemName FROM [format_table_name("customuseritems")]
SELECT cuiPath, cuiPropAdjust, cuiJobMask, cuiDescription, cuiItemName FROM customuseritems
WHERE cuiCKey=:ckey AND (cuiRealName=:realname OR cuiRealName='*')"}, list(
"ckey" = M.ckey,
"realname" = M.real_name
+1 -2
View File
@@ -115,8 +115,7 @@ GLOBAL_DATUM(error_cache, /datum/ErrorViewer/ErrorCache)
// Show the error to admins with debug messages turned on, but only if one
// from the same source hasn't been shown too recently
// (Also, make sure config is initialized, or log_debug will runtime)
if(config && error_source.next_message_at <= world.time)
if(error_source.next_message_at <= world.time)
var/const/viewtext = "\[view]" // Nesting these in other brackets went poorly
log_debug("Runtime in [e.file],[e.line]: [html_encode(e.name)] [error_entry.makeLink(viewtext)]")
error_source.next_message_at = world.time + ERROR_MSG_DELAY
+1 -1
View File
@@ -30,6 +30,6 @@
SSticker.mode.update_blob_icons_added(B.mind)
to_chat(B, "<span class='userdanger'>You are now a mouse, infected with blob spores. Find somewhere isolated... before you burst and become the blob! Use ventcrawl (alt-click on vents) to move around.</span>")
to_chat(B, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Blob)</span>")
to_chat(B, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Blob)</span>")
notify_ghosts("Infected Mouse has appeared in [get_area(B)].", source = B)
successSpawn = TRUE
-5
View File
@@ -40,11 +40,6 @@
return clamp((weight + job_weight) * weight_mod, min_weight, max_weight)
/datum/event_meta/alien/get_weight(list/active_with_role)
if(GLOB.aliens_allowed)
return ..(active_with_role)
return 0
/*/datum/event_meta/ninja/get_weight(var/list/active_with_role)
if(toggle_space_ninja)
return ..(active_with_role)
+7 -7
View File
@@ -29,7 +29,8 @@ GLOBAL_LIST_EMPTY(event_last_fired)
if(delayed)
next_event_time += (world.time - last_world_time)
else if(world.time > next_event_time)
start_event()
if(GLOB.configuration.event.enable_random_events)
start_event()
last_world_time = world.time
@@ -66,7 +67,7 @@ GLOBAL_LIST_EMPTY(event_last_fired)
for(var/event_meta in last_event_time) if(possible_events[event_meta])
var/time_passed = world.time - GLOB.event_last_fired[event_meta]
var/weight_modifier = max(0, (config.expected_round_length - time_passed) / 300)
var/weight_modifier = max(0, (GLOB.configuration.event.expected_round_length - time_passed) / 300)
var/new_weight = max(possible_events[event_meta] - weight_modifier, 0)
if(new_weight)
@@ -84,9 +85,9 @@ GLOBAL_LIST_EMPTY(event_last_fired)
/datum/event_container/proc/set_event_delay()
// If the next event time has not yet been set and we have a custom first time start
if(next_event_time == 0 && config.event_first_run[severity])
var/lower = config.event_first_run[severity]["lower"]
var/upper = config.event_first_run[severity]["upper"]
if(next_event_time == 0 && GLOB.configuration.event.first_run_times[severity])
var/lower = GLOB.configuration.event.first_run_times[severity]["lower"]
var/upper = GLOB.configuration.event.first_run_times[severity]["upper"]
var/event_delay = rand(lower, upper)
next_event_time = world.time + event_delay
// Otherwise, follow the standard setup process
@@ -110,7 +111,7 @@ GLOBAL_LIST_EMPTY(event_last_fired)
playercount_modifier = playercount_modifier * delay_modifier
var/event_delay = rand(config.event_delay_lower[severity], config.event_delay_upper[severity]) * playercount_modifier
var/event_delay = rand(GLOB.configuration.event.delay_lower_bound[severity], GLOB.configuration.event.delay_upper_bound[severity]) * playercount_modifier
next_event_time = world.time + event_delay
log_debug("Next event of severity [GLOB.severity_to_string[severity]] in [(next_event_time - world.time)/600] minutes.")
@@ -182,7 +183,6 @@ GLOBAL_LIST_EMPTY(event_last_fired)
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Swarmer Spawn", /datum/event/spawn_swarmer, 150, is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/spawn_morph, 40, list(ASSIGNMENT_SECURITY = 10), is_one_shot = TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Disease Outbreak", /datum/event/disease_outbreak, 0, list(ASSIGNMENT_MEDICAL = 150), TRUE),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Headcrabs", /datum/event/headcrabs, 0, list(ASSIGNMENT_SECURITY = 20)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Door Runtime", /datum/event/door_runtime, 50, list(ASSIGNMENT_ENGINEER = 25, ASSIGNMENT_AI = 150), TRUE)
)
-65
View File
@@ -1,65 +0,0 @@
#define HEADCRAB_NORMAL 0
#define HEADCRAB_FASTMIX 1
#define HEADCRAB_FAST 2
#define HEADCRAB_POISONMIX 3
#define HEADCRAB_POISON 4
#define HEADCRAB_SPAWNER 5
/datum/event/headcrabs
announceWhen = 10
endWhen = 11
var/locstring
var/headcrab_type
/datum/event/headcrabs/start()
var/list/availableareas = list()
for(var/area/maintenance/A in world)
availableareas += A
var/area/randomarea = pick(availableareas)
var/list/turf/simulated/floor/turfs = list()
for(var/turf/simulated/floor/F in randomarea)
if(turf_clear(F))
turfs += F
var/list/spawn_types = list()
var/max_number
headcrab_type = rand(0, 5)
switch(headcrab_type)
if(HEADCRAB_NORMAL)
spawn_types = list(/mob/living/simple_animal/hostile/headcrab)
max_number = 6
if(HEADCRAB_FASTMIX)
spawn_types = list(/mob/living/simple_animal/hostile/headcrab, /mob/living/simple_animal/hostile/headcrab/fast)
max_number = 8
if(HEADCRAB_FAST)
spawn_types = list(/mob/living/simple_animal/hostile/headcrab/fast)
max_number = 6
if(HEADCRAB_POISONMIX)
spawn_types = list(/mob/living/simple_animal/hostile/headcrab, /mob/living/simple_animal/hostile/headcrab/poison)
max_number = 4
if(HEADCRAB_POISON)
spawn_types = list(/mob/living/simple_animal/hostile/headcrab/poison)
max_number = 3
if(HEADCRAB_SPAWNER)
spawn_types = list(/obj/structure/spawner/headcrab)
max_number = 2
var/num = rand(2,max_number)
while(turfs.len > 0 && num > 0)
var/turf/simulated/floor/T = pick(turfs)
turfs.Remove(T)
num--
var/spawn_type = pick(spawn_types)
new spawn_type(T)
/datum/event/headcrabs/announce()
GLOB.event_announcement.Announce("Bioscans indicate that headcrabs have been breeding on the station. Clear them out, before this starts to affect productivity", "Lifesign Alert")
#undef HEADCRAB_NORMAL
#undef HEADCRAB_FASTMIX
#undef HEADCRAB_FAST
#undef HEADCRAB_POISONMIX
#undef HEADCRAB_POISON
#undef HEADCRAB_SPAWNER
+2 -2
View File
@@ -21,7 +21,7 @@
var/mob/living/simple_animal/SA = pick(potential)
var/mob/SG = pick(candidates)
var/sentience_report = "<font size=3><b>[command_name()] Medium-Priority Update</b></font>"
var/sentience_report = "<font size=3><b>NAS Trurl Medium-Priority Update</b></font>"
var/data = pick("scans from our long-range sensors", "our sophisticated probabilistic models", "our omnipotence", "the communications traffic on your station", "energy emissions we detected", "\[REDACTED\]", "Steve")
var/pets = pick("animals", "pets", "simple animals", "lesser lifeforms", "\[REDACTED\]")
@@ -40,7 +40,7 @@
SA.health = SA.maxHealth
SA.del_on_death = FALSE
greet_sentient(SA)
print_command_report(sentience_report, "[command_name()] Update", FALSE)
print_command_report(sentience_report, "NAS Trurl Update", FALSE)
/datum/event/sentience/proc/greet_sentient(mob/living/carbon/human/M)
to_chat(M, "<span class='userdanger'>Hello world!</span>")
+1 -1
View File
@@ -56,7 +56,7 @@
var/mob/living/simple_animal/hostile/poison/terror_spider/S = new spider_type(vent.loc)
var/mob/M = pick_n_take(candidates)
S.key = M.key
to_chat(S, "<span class='motd'>For more information, check the wiki page: ([config.wikiurl]/index.php/Terror_Spider)</span>")
to_chat(S, "<span class='motd'>For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Terror_Spider)</span>")
spawncount--
successSpawn = TRUE
@@ -1,151 +0,0 @@
/obj/machinery/atmospherics/pipe
description_info = "This pipe, and all other pipes, can be connected or disconnected by a wrench. The internal pressure of the pipe must \
be below 300 kPa to do this. More pipes can be obtained from the pipe dispenser."
/obj/machinery/atmospherics/pipe/New() //This is needed or else 20+ lines of copypasta to dance around inheritence.
..()
description_info += "<br>Most pipes and atmospheric devices can be connected or disconnected with a wrench. The pipe's pressure must not be too high, \
or if it is a device, it must be turned off first."
//HE pipes
/obj/machinery/atmospherics/pipe/simple/heat_exchanging
description_info = "This radiates heat from the pipe's gas to space, cooling it down."
//Supply/Scrubber pipes
/obj/machinery/atmospherics/pipe/simple/visible/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/visible/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/hidden/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
//Universal adapters
/obj/machinery/atmospherics/pipe/simple/visible/universal
description_info = "This allows you to connect 'normal' pipes, red 'scrubber' pipes, and blue 'supply' pipes."
/obj/machinery/atmospherics/pipe/simple/hidden/universal
description_info = "This allows you to connect 'normal' pipes, red 'scrubber' pipes, and blue 'supply' pipes."
//Three way manifolds
/obj/machinery/atmospherics/pipe/manifold
description_info = "A normal pipe with three ends to connect to."
/obj/machinery/atmospherics/pipe/manifold/visible/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/visible/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/hidden/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
//Insulated pipes
/obj/machinery/atmospherics/pipe/simple/insulated
description_info = "This is completely useless, use a normal pipe." //Sorry, but it's true.
//Four way manifolds
/obj/machinery/atmospherics/pipe/manifold4w
description_info = "This is a four-way pipe."
/obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
//Endcaps
/obj/machinery/atmospherics/pipe/cap
description_info = "This is a cosmetic attachment, as pipes currently do not spill their contents into the air."
//T-shaped valves
/obj/machinery/atmospherics/trinary/tvalve
description_info = "Click this to toggle the mode. The direction with the green light is where the gas will flow."
//Normal valves
/obj/machinery/atmospherics/binary/valve
description_info = "Click this to turn the valve. If red, the pipes on each end are separated. Otherwise, they are connected."
//TEG ports
/obj/machinery/atmospherics/binary/circulator
description_info = "This generates electricity, depending on the difference in temperature between each side of the machine. The meter in \
the center of the machine gives an indicator of how much electricity is being generated."
//Passive gates
/obj/machinery/atmospherics/binary/passive_gate
description_info = "This is a one-way regulator, allowing gas to flow only at a specific pressure and flow rate. If the light is green, it is flowing."
//Normal pumps (high power one inherits from this)
/obj/machinery/atmospherics/binary/pump
description_info = "This moves gas from one pipe to another. A higher target pressure demands more energy. The side with the red end is the output."
//Vents
/obj/machinery/atmospherics/unary/vent_pump
description_info = "This pumps the contents of the attached pipe out into the atmosphere, if needed. It can be controlled from an Air Alarm."
//Freezer and Heater
/obj/machinery/atmospherics/unary/thermomachine
description_info = "Cools or heats the gas of the pipe it is connected to. It uses massive amounts of electricity while on. \
It can be upgraded by replacing the capacitors, manipulators, and matter bins. It can be deconstructed by screwing the maintenance panel open with a \
screwdriver, and then using a crowbar."
//Gas injectors
/obj/machinery/atmospherics/unary/outlet_injector
description_info = "Outputs the pipe's gas into the atmosphere, similar to an air vent. It can be controlled by a nearby atmospherics computer. \
A green light on it means it is on."
//Scrubbers
/obj/machinery/atmospherics/unary/vent_scrubber
description_info = "This filters the atmosphere of harmful gas. Filtered gas goes to the pipes connected to it, typically a scrubber pipe. \
It can be controlled from an Air Alarm. It can be configured to drain all air rapidly with a 'panic syphon' from an air alarm."
//Canisters
/obj/machinery/portable_atmospherics/canister
description_info = "The canister can be connected to a connector port with a wrench. Tanks of gas (the kind you can hold in your hand) \
can be filled by the canister, by using the tank on the canister, increasing the release pressure, then opening the valve until it is full, and then close it. \
*DO NOT* remove the tank until the valve is closed. A gas analyzer can be used to check the contents of the canister."
description_antag = "Canisters can be damaged, spilling their contents into the air, or you can just leave the release valve open."
//Portable pumps
/obj/machinery/portable_atmospherics/pump
description_info = "Invaluable for filling air in a room rapidly after a breach repair. The internal gas container can be filled by \
connecting it to a connector port. The pump can pump the air in (sucking) or out (blowing), at a specific target pressure. The powercell inside can be \
replaced by using a screwdriver, and then adding a new cell. A tank of gas can also be attached to the air pump."
//Portable scrubbers
/obj/machinery/portable_atmospherics/scrubber
description_info = "Filters the air, placing harmful gases into the internal gas container. The container can be emptied by \
connecting it to a connector port. The pump can pump the air in (sucking) or out (blowing), at a specific target pressure. The powercell inside can be \
replaced by using a screwdriver, and then adding a new cell. A tank of gas can also be attached to the scrubber. "
//Meters
/obj/machinery/meter
description_info = "Measures the volume and temperature of the pipe under the meter."
//Pipe dispensers
/obj/machinery/pipedispenser
description_info = "This can be moved by using a wrench. You will need to wrench it again when you want to use it. You can put \
excess (atmospheric) pipes into the dispenser, as well. The dispenser requires electricity to function."
@@ -1,35 +0,0 @@
/obj/machinery/power/supermatter_crystal
description_info = "When energized by a laser (or something hitting it), it emits radiation and heat. If the heat reaches above 7000 kelvin, it will send an alert and start taking damage. \
After integrity falls to zero percent, it will delaminate, causing a massive explosion, station-wide radiation spikes, and hallucinations. \
Supermatter reacts badly to oxygen in the atmosphere. It'll also heat up really quick if it is in vacuum.<br>\
<br>\
Supermatter cores are extremely dangerous to be close to, and requires protection to handle properly. The protection you will need is:<br>\
Optical meson scanners on your eyes, to prevent hallucinations when looking at the supermatter.<br>\
Radiation helmet and suit, as the supermatter is radioactive.<br>\
<br>\
Touching the supermatter will result in *instant death*, with no corpse left behind! You can drag the supermatter, but anything else will kill you. \
It is advised to obtain a genetic backup before trying to drag it."
description_antag = "Exposing the supermatter to oxygen or vacuum will cause it to start rapidly heating up. Sabotaging the supermatter and making it explode will \
cause a period of lag as the explosion is processed by the server, as well as irradiating the entire station and causing hallucinations to happen. \
Wearing radiation equipment will protect you from most of the delamination effects sans explosion."
/obj/machinery/power/apc
description_info = "An APC (Area Power Controller) regulates and supplies backup power for the area they are in. Their power channels are divided \
out into 'environmental' (Items that manipulate airflow and temperature), 'lighting' (the lights), and 'equipment' (Everything else that consumes power). \
Power consumption and backup power cell charge can be seen from the interface, further controls (turning a specific channel on, off or automatic, \
toggling the APC's ability to charge the backup cell, or toggling power for the entire area via master breaker) first requires the interface to be unlocked \
with an ID with Engineering access or by one of the station's robots or the artificial intelligence."
description_antag = "This can be emagged to unlock it. It will cause the APC to have a blue error screen. \
Wires can be pulsed remotely with a signaler attached to it. A powersink will also drain any APCs connected to the same wire the powersink is on."
/obj/item/inflatable
description_info = "Inflate by using it in your hand. The inflatable barrier will inflate on your tile. To deflate it, use the 'deflate' verb."
/obj/structure/inflatable
description_info = "To remove these safely, use the 'deflate' verb. Hitting these with any objects will probably puncture and break it forever."
/obj/structure/inflatable/door
description_info = "Click the door to open or close it. It only stops air while closed.<br>\
To remove these safely, use the 'deflate' verb. Hitting these with any objects will probably puncture and break it forever."
@@ -1,42 +0,0 @@
/obj/machinery/bodyscanner
description_info = "The advanced scanner detects and reports internal injuries such as bone fractures, internal bleeding, and organ damage. \
This is useful if you are about to perform surgery.<br>\
<br>\
Click your target with Grab intent, then click on the scanner to place them in it. Click the red terminal to operate. \
Right-click the scanner and click 'Eject Occupant' to remove them. You can enter the scanner yourself in a similar way, using the 'Enter Body Scanner' \
verb."
/obj/machinery/atmospherics/unary/cryo_cell
description_info = "The cryogenic chamber, or 'cryo', treats most damage types, most notably genetic damage. It also stabilizes patients \
in critical condition by placing them in stasis, so they can be treated at a later time.<br>\
<br>\
In order for it to work, it must be loaded with chemicals, and the temperature of the solution must reach a certain point. Additionally, it \
requires a supply of pure oxygen, provided by canisters that are attached. The most commonly used chemicals in the chambers is Cryoxadone, which \
heals most damage types including genetic damage.<br>\
<br>\
Activating the freezer nearby, and setting it to a temperature setting below 150, is recommended before operation! Further, any clothing the patient \
is wearing that act as an insulator will reduce its effectiveness, and should be removed.<br>\
<br>\
Clicking the tube with a beaker full of chemicals in hand will place it in its storage to distribute when it is activated.<br>\
<br>\
Click your target with Grab intent, then click on the tube, with an empty hand, to place them in it. Click the tube again to open the menu. \
Press the button on the menu to activate it. Once they have reached 100 health, right-click the cell and click 'Eject Occupant' to remove them. \
Remember to turn it off, once you've finished, to save power and chemicals!"
/obj/machinery/optable
description_info = "Click your target with Grab intent, then click on the table with an empty hand, to place them on it."
/obj/machinery/computer/operating
description_info = "This console gives information on the status of the patient on the adjacent operating table, notably their consciousness."
/obj/machinery/sleeper
description_info = "The sleeper allows you to clean the blood by means of dialysis, and to administer medication in a controlled environment.<br>\
<br>\
Click your target with Grab intent, then click on the sleeper to place them in it. Click the green console, with an empty hand, to open the menu. \
Click 'Start Dialysis' to begin filtering unwanted chemicals from the occupant's blood. The beaker contained will begin to fill with their \
contaminated blood, and will need to be emptied when full.<br>\
<br>\
You can also inject common medicines directly into their bloodstream.\
<br>\
Right-click the cell and click 'Eject Occupant' to remove them. You can enter the cell yourself by right clicking and selecting 'Enter Sleeper'. \
Note that you cannot control the sleeper while inside of it."
@@ -1,8 +0,0 @@
/mob/living/silicon/robot/drone
description_info = "Drones are player-controlled synthetics which are lawed to maintain the station and not \
interact with anyone else, except for other drones. They hold a wide array of tools to build, repair, maintain, and clean. \
They function similarly to other synthetics, in that they require recharging regularly, have laws, and are resilient to many hazards, \
such as fire, radiation, vacuum, and more. Ghosts can join the round as a maintenance drone by using the appropriate verb in the 'ghost' tab. \
An inactive drone can be rebooted by swiping an ID card on it with engineering or robotics access."
description_antag = "An Electromagnetic Sequencer can be used to subvert the drone to your cause."
@@ -1,24 +0,0 @@
/obj/item/stack/rods
description_info = "Made from metal sheets. You can build a grille by using it in your hand. \
Clicking on a floor without any tiles will reinforce the floor. You can make reinforced glass by combining rods and normal glass sheets."
/obj/item/stack/sheet/glass
description_info = "Use in your hand to build a window. Can be upgraded to reinforced glass by adding metal rods, which are made from metal sheets."
/obj/item/stack/sheet/glass/cyborg
description_info = "Use in your hand to build a window. Can be upgraded to reinforced glass by adding metal rods, which are made from metal sheets.<br>\
As a synthetic, you can acquire more sheets of glass by recharging."
/obj/item/stack/sheet/rglass
description_info = "Use in your hand to build a window. Reinforced glass is much stronger against damage."
/obj/item/stack/sheet/rglass/cyborg
description_info = "Use in your hand to build a window. Reinforced glass is much stronger against damage.<br>\
As a synthetic, you can gain more reinforced glass by recharging."
/obj/item/stack/sheet/metal/cyborg
description_info = "Use in your hand to bring up the recipe menu. If you have enough sheets, click on something on the list to build it.<br>\
You can replenish your supply of metal as a synthetic by recharging."
/obj/item/stack/sheet
description_info = "Use in your hand to bring up the recipe menu. If you have enough sheets, click on something on the list to build it."
@@ -1,21 +0,0 @@
/obj/structure/girder
description_info = "Use metal sheets on this to build a normal wall. Adding plasteel instead will make a reinforced wall.<br>\
A false wall can be made by using a crowbar on this girder, and then adding metal or plasteel.<br>\
You can dismantle the girder with a wrench."
/obj/structure/girder/reinforced
description_info = "Add another sheet of plasteel to finish."
/obj/structure/grille
description_info = "A powered and knotted wire underneath this will cause the grille to shock anyone not wearing insulated gloves.<br>\
Wirecutters will turn the grille into metal rods instantly. Grilles are made with metal rods."
/obj/structure/lattice
description_info = "Add a metal floor tile to build a floor on top of the lattice.<br>\
Lattices can be made by applying metal rods to a space tile."
/obj/structure/bed
description_info = "Click and drag yourself (or anyone) to this to buckle in. Click on this with an empty hand to undo the buckles.<br>\
<br>\
Anyone with restraints, such as handcuffs, will not be able to unbuckle themselves. They must use the Resist button, or verb, to break free of \
the buckles, instead."
@@ -1,3 +0,0 @@
/turf/simulated/wall
description_info = "You can deconstruct this by welding it, and then wrenching the girder.<br>\
You can build a wall by using metal sheets and making a girder, then adding more metal or plasteel."
@@ -1,68 +0,0 @@
/*
Note: This file is meant for actual weapons (guns, swords, etc), and not the stupid 'every obj is a weapon, except when it's not' thing.
*/
//******
//*Guns*
//******
//This contains a lot of copypasta but I'm told it's better then a lot of New()s appending the var.
/obj/item/gun
description_info = "This is a gun."
/obj/item/gun/energy
description_info = "This is an energy weapon. Most energy weapons can fire through windows harmlessly. To recharge this weapon, use a weapon recharger."
/obj/item/gun/energy/kinetic_accelerator/crossbow
description_info = "This is an energy weapon. To fire the weapon, have your gun mode set to 'fire', \
then click where you want to fire."
description_antag = "This is a stealthy weapon which fires poisoned bolts at your target. When it hits someone, they will suffer a stun effect, in \
addition to toxins. The energy crossbow recharges itself slowly, and can be concealed in your pocket or bag."
/obj/item/gun/energy/gun
description_info = "This is an energy weapon. Most energy weapons can fire through windows harmlessly. To switch between stun and lethal, click the weapon \
in your hand. To recharge this weapon, use a weapon recharger."
/obj/item/gun/energy/gun/advtaser
description_info = "This is an energy weapon. To recharge this weapon, use a weapon recharger. \
To switch between insta-stun and disabler beams, click the weapon in your hand. This weapon can only fire through glass if it is set to disabler beams."
/obj/item/gun/energy/gun/nuclear
description_info = "This is an energy weapon. Most energy weapons can fire through windows harmlessly. To switch between stun and lethal, click the weapon \
in your hand. Unlike most weapons, this weapon recharges itself."
/obj/item/gun/energy/laser/captain
description_info = "This is an energy weapon. Most energy weapons can fire through windows harmlessly. Unlike most weapons, this weapon recharges itself."
/obj/item/gun/energy/sniperrifle
description_info = "This is an energy weapon. Most energy weapons can fire through windows harmlessly. To recharge this weapon, use a weapon recharger. \
To use the scope, use the appropriate verb in the object tab."
/obj/item/gun/projectile
description_info = "This is a ballistic weapon. To reload, click the weapon in your hand to unload (if needed), then add the appropriate ammo. The description \
will tell you what caliber you need."
/obj/item/gun/projectile/shotgun/pump
description_info = "This is a ballistic weapon. After firing, you will need to pump the gun, by clicking on the gun in your hand. To reload, load more shotgun \
shells into the gun."
/obj/item/toy/russian_revolver/trick_revolver //oh no
description_info = "This is a ballistic weapon. To reload, click the weapon in your hand to unload (if needed), then add the appropriate ammo. The description \
will tell you what caliber you need."
//*******
//*Melee*
//*******
/obj/item/melee/baton
description_info = "The baton needs to be turned on to apply the stunning effect. Use it in your hand to toggle it on or off. If your intent is \
set to 'harm', you will inflict damage when using it, regardless if it is on or not. Each stun reduces the baton's charge, which can be replenished by \
putting it inside a weapon recharger."
/obj/item/melee/energy/sword
description_antag = "The energy sword is a very strong melee weapon, capable of severing limbs easily, if they are targeted. It can also has a chance \
to block projectiles and melee attacks while it is on and being held. The sword can be toggled on or off by using it in your hand. While it is off, \
it can be concealed in your pocket or bag."
/obj/item/melee/cultblade
description_antag = "This sword is a powerful weapon, capable of severing limbs easily, if they are targeted. Nonbelievers are unable to use this weapon."
+35 -43
View File
@@ -1,62 +1,54 @@
/* This code is responsible for the examine tab. When someone examines something, it copies the examined object's description_info,
description_fluff, and description_antag, and shows it in a new tab.
/**
* Used for showing a more detailed description in the 'Examine' tab after examining the atom.
*
* Shown as blue text in the Examine tab.
*/
/atom/proc/detailed_examine()
return null
In this file, some atom and mob stuff is defined here. It is defined here instead of in the normal files, to keep the whole system self-contained.
This means that this file can be unchecked, along with the other examine files, and can be removed entirely with no effort.
*/
/**
* Used for showing a more detailed description to antags in the 'Examine' after examining the atom.
*
* Shown as red text in the Examine tab.
*/
/atom/proc/detailed_examine_antag()
return null
/**
* Used for showing flavour text in the 'Examine' tab after examining the atom.
*
* Shown as green text in the Examine tab. The custom flavour text of `/mob` subtypes override this.
*/
/atom/proc/detailed_examine_fluff()
return null
/atom/
var/description_info = null //Helpful blue text.
var/description_fluff = null //Green text about the atom's fluff, if any exists.
var/description_antag = null //Malicious red text, for the antags.
//Override these if you need special behaviour for a specific type.
/atom/proc/get_description_info()
if(description_info)
return description_info
return
/atom/proc/get_description_fluff()
if(description_fluff)
return description_fluff
return
/atom/proc/get_description_antag()
if(description_antag)
return description_antag
return
/mob/living/get_description_fluff()
/mob/detailed_examine_fluff()
if(flavor_text) //Get flavor text for the green text.
return flavor_text
else //No flavor text? Try for hardcoded fluff instead.
else //No flavor text? Try for hardcoded fluff instead.
return ..()
/mob/living/carbon/human/get_description_fluff()
/mob/living/carbon/human/detailed_examine_fluff()
return print_flavor_text()
/* The examine panel itself */
/client/var/description_holders[0]
/client/proc/update_description_holders(atom/A, update_antag_info=0)
description_holders["info"] = A.get_description_info()
description_holders["fluff"] = A.get_description_fluff()
description_holders["antag"] = (update_antag_info)? A.get_description_antag() : ""
/client/proc/update_description_holders(atom/A, update_antag_info = FALSE)
description_holders["name"] = "[A.name]"
description_holders["icon"] = "[bicon(A)]"
description_holders["desc"] = A.desc
description_holders["info"] = A.detailed_examine()
description_holders["fluff"] = A.detailed_examine_fluff()
description_holders["antag"] = update_antag_info ? A.detailed_examine_antag() : null
// The examine panel itself
/client/Stat()
. = ..()
if(usr && statpanel("Examine"))
stat(null,"[description_holders["icon"]] <font size='5'>[description_holders["name"]]</font>") //The name, written in big letters.
stat(null,"[description_holders["desc"]]") //the default examine text.
stat(null, "<font size='5'>[description_holders["name"]]</font>") //The name, written in big letters.
stat(null, "[description_holders["desc"]]") //the default examine text.
if(description_holders["info"])
stat(null,"<font color='#084B8A'><b>[description_holders["info"]]</b></font>") //Blue, informative text.
stat(null, "<font color='#084B8A'><b>[description_holders["info"]]</b></font>") //Blue, informative text.
if(description_holders["fluff"])
stat(null,"<font color='#298A08'><b>[description_holders["fluff"]]</b></font>") //Yellow, fluff-related text.
stat(null, "<font color='#298A08'><b>[description_holders["fluff"]]</b></font>") //Yellow, fluff-related text.
if(description_holders["antag"])
stat(null,"<font color='#8A0808'><b>[description_holders["antag"]]</b></font>") //Red, malicious antag-related text
stat(null, "<font color='#8A0808'><b>[description_holders["antag"]]</b></font>") //Red, malicious antag-related text
@@ -293,9 +293,9 @@
return 1
/obj/item/reagent_containers/food/snacks/monkeycube/proc/Expand()
if(LAZYLEN(SSmobs.cubemonkeys) >= config.cubemonkeycap)
if(LAZYLEN(SSmobs.cubemonkeys) >= GLOB.configuration.general.monkey_cube_cap)
if(fingerprintslast)
to_chat(get_mob_by_ckey(fingerprintslast), "<span class='warning'>Bluespace harmonics prevent the spawning of more than [config.cubemonkeycap] monkeys on the station at one time!</span>")
to_chat(get_mob_by_ckey(fingerprintslast), "<span class='warning'>Bluespace harmonics prevent the spawning of more than [GLOB.configuration.general.monkey_cube_cap] monkeys on the station at one time!</span>")
else
visible_message("<span class='notice'>[src] fails to expand!</span>")
return
@@ -35,6 +35,10 @@
var/datum/wires/smartfridge/wires
/// Typecache of accepted item types, init it in [/obj/machinery/smartfridge/Initialize].
var/list/accepted_items_typecache
/// Associative list (/obj/item => /number) representing the items the fridge should initially contain.
var/list/starting_items
/// The type of the circuitboard dropped on deconstruction. This is how to avoid getting subtypes into the board.
var/board_type = /obj/machinery/smartfridge
/obj/machinery/smartfridge/Initialize(mapload)
. = ..()
@@ -44,8 +48,12 @@
reagents.set_reacting(FALSE)
// Components
component_parts = list()
var/obj/item/circuitboard/smartfridge/board = new(null)
board.set_type(null, type)
if(board_type)
board.set_type(null, board_type)
else
board.set_type(null, type)
component_parts += board
component_parts += new /obj/item/stock_parts/matter_bin(null)
RefreshParts()
@@ -54,6 +62,14 @@
wires = new/datum/wires/smartfridge/secure(src)
else
wires = new/datum/wires/smartfridge(src)
//Add starting items
if(starting_items)
for(var/typekey in starting_items)
var/amount = starting_items[typekey] || 1
while(amount--)
var/obj/item/I = new typekey(src)
item_quants[I.name] += 1
update_icon()
// Accepted items
accepted_items_typecache = typecacheof(list(
/obj/item/reagent_containers/food/snacks/grown,
@@ -371,6 +387,7 @@
desc = "When you need seeds fast!"
icon = 'icons/obj/vending.dmi'
icon_state = "seeds"
board_type = /obj/machinery/smartfridge/seeds
/obj/machinery/smartfridge/seeds/Initialize(mapload)
. = ..()
@@ -378,6 +395,84 @@
/obj/item/seeds
))
/**
* # Circuit Boards Storage
*
* Circuit variant of the [Smart Fridge][/obj/machinery/smartfridge].
*
*/
/obj/machinery/smartfridge/secure/circuits
name = "\improper Circuit Board Storage"
desc = "A storage unit for circuits."
icon_state = "circuits"
visible_contents = TRUE
board_type = /obj/machinery/smartfridge/secure/circuits
/obj/machinery/smartfridge/secure/circuits/Initialize(mapload)
. = ..()
accepted_items_typecache = typecacheof(list(
/obj/item/aiModule,
/obj/item/circuitboard
))
/obj/machinery/smartfridge/secure/circuits/update_icon()
var/prefix = initial(icon_state)
if(stat & (BROKEN|NOPOWER))
icon_state = "[prefix]-off"
else if(visible_contents)
switch(length(contents))
if(0)
icon_state = "[prefix]"
if(1 to 2)
icon_state = "[prefix]1"
if(3 to 5)
icon_state = "[prefix]2"
if(6 to INFINITY)
icon_state = "[prefix]3"
else
icon_state = "[prefix]"
/obj/machinery/smartfridge/secure/circuits/aiupload
name = "\improper AI Laws Storage"
desc = "A storage unit filled with circuits to be uploaded to an Artificial Intelligence."
board_type = /obj/machinery/smartfridge/secure/circuits/aiupload
/obj/machinery/smartfridge/secure/circuits/aiupload/Initialize(mapload)
. = ..()
req_access_txt = "[ACCESS_AI_UPLOAD]"
/obj/machinery/smartfridge/secure/circuits/aiupload/experimental
name = "\improper Experimental Laws Storage"
starting_items = list(
/obj/item/aiModule/cctv = 1,
/obj/item/aiModule/hippocratic = 1,
/obj/item/aiModule/maintain = 1,
/obj/item/aiModule/paladin = 1,
/obj/item/aiModule/peacekeeper = 1,
/obj/item/aiModule/quarantine = 1,
/obj/item/aiModule/robocop = 1
)
/obj/machinery/smartfridge/secure/circuits/aiupload/experimental/Initialize(mapload)
. = ..()
req_access_txt = "[ACCESS_RD]"
/obj/machinery/smartfridge/secure/circuits/aiupload/highrisk
name = "\improper High-Risk Laws Storage"
starting_items = list(
/obj/item/aiModule/freeform = 1,
/obj/item/aiModule/freeformcore = 1,
/obj/item/aiModule/nanotrasen_aggressive = 1,
/obj/item/aiModule/oneCrewMember = 1,
/obj/item/aiModule/protectStation = 1,
/obj/item/aiModule/purge = 1,
/obj/item/aiModule/tyrant = 1
)
/obj/machinery/smartfridge/secure/circuits/aiupload/highrisk/Initialize(mapload)
. = ..()
req_access_txt = "[ACCESS_CAPTAIN]"
/**
* # Refrigerated Medicine Storage
*
@@ -387,6 +482,7 @@
name = "\improper Refrigerated Medicine Storage"
desc = "A refrigerated storage unit for storing medicine and chemicals."
icon_state = "smartfridge" //To fix the icon in the map editor.
board_type = /obj/machinery/smartfridge/medbay
/obj/machinery/smartfridge/medbay/Initialize(mapload)
. = ..()
@@ -406,6 +502,7 @@
/obj/machinery/smartfridge/secure/extract
name = "\improper Slime Extract Storage"
desc = "A refrigerated storage unit for slime extracts"
board_type = /obj/machinery/smartfridge/secure/extract
/obj/machinery/smartfridge/secure/extract/Initialize(mapload)
. = ..()
@@ -424,6 +521,7 @@
desc = "A refrigerated storage unit for storing medicine and chemicals."
icon_state = "smartfridge" //To fix the icon in the map editor.
req_one_access_txt = "5;33"
board_type = /obj/machinery/smartfridge/secure/medbay
/obj/machinery/smartfridge/secure/medbay/Initialize(mapload)
. = ..()
@@ -444,21 +542,11 @@
name = "\improper Smart Chemical Storage"
desc = "A refrigerated storage unit for medicine and chemical storage."
icon_state = "smartfridge" //To fix the icon in the map editor.
/// Associative list (/obj/item => /number) representing the items the fridge should initially contain.
var/list/spawn_meds
board_type = /obj/machinery/smartfridge/secure/chemistry
/obj/machinery/smartfridge/secure/chemistry/Initialize(mapload)
. = ..()
req_access_txt = "[ACCESS_CHEMISTRY]"
// Spawn initial chemicals
if(mapload)
LAZYINITLIST(spawn_meds)
for(var/typekey in spawn_meds)
var/amount = spawn_meds[typekey] || 1
while(amount--)
var/obj/item/I = new typekey(src)
item_quants[I.name] += 1
update_icon()
// Accepted items
accepted_items_typecache = typecacheof(list(
/obj/item/storage/pill_bottle,
@@ -474,7 +562,7 @@
// I exist!
/obj/machinery/smartfridge/secure/chemistry/preloaded/Initialize(mapload)
spawn_meds = list(
starting_items = list(
/obj/item/reagent_containers/food/pill/epinephrine = 12,
/obj/item/reagent_containers/food/pill/charcoal = 5,
/obj/item/reagent_containers/glass/bottle/epinephrine = 1,
@@ -505,6 +593,7 @@
icon_state = "disktoaster"
pass_flags = PASSTABLE
visible_contents = FALSE
board_type = /obj/machinery/smartfridge/disks
/obj/machinery/smartfridge/disks/Initialize(mapload)
. = ..()
@@ -516,21 +605,14 @@
* # Smart Virus Storage
*
* Secure, Virology variant of the [Smart Chemical Storage][/obj/machinery/smartfridge/secure/chemistry].
* Comes with some items.
*
*/
/obj/machinery/smartfridge/secure/chemistry/virology
name = "\improper Smart Virus Storage"
desc = "A refrigerated storage unit for volatile sample storage."
board_type = /obj/machinery/smartfridge/secure/chemistry/virology
/obj/machinery/smartfridge/secure/chemistry/virology/Initialize(mapload)
spawn_meds = list(
/obj/item/reagent_containers/syringe/antiviral = 4,
/obj/item/reagent_containers/glass/bottle/cold = 1,
/obj/item/reagent_containers/glass/bottle/flu_virion = 1,
/obj/item/reagent_containers/glass/bottle/mutagen = 1,
/obj/item/reagent_containers/glass/bottle/plasma = 1,
/obj/item/reagent_containers/glass/bottle/diphenhydramine = 1
)
. = ..()
req_access_txt = "[ACCESS_VIROLOGY]"
accepted_items_typecache = typecacheof(list(
@@ -548,14 +630,13 @@
// I exist!
/obj/machinery/smartfridge/secure/chemistry/virology/preloaded/Initialize(mapload)
spawn_meds = list(
starting_items = list(
/obj/item/reagent_containers/syringe/antiviral = 4,
/obj/item/reagent_containers/glass/bottle/cold = 1,
/obj/item/reagent_containers/glass/bottle/flu_virion = 1,
/obj/item/reagent_containers/glass/bottle/mutagen = 1,
/obj/item/reagent_containers/glass/bottle/plasma = 1,
/obj/item/reagent_containers/glass/bottle/reagent/synaptizine = 1,
/obj/item/reagent_containers/glass/bottle/reagent/formaldehyde = 1
/obj/item/reagent_containers/glass/bottle/diphenhydramine = 1
)
. = ..()
@@ -568,6 +649,15 @@
req_access_txt = null
/obj/machinery/smartfridge/secure/chemistry/virology/preloaded/syndicate/Initialize(mapload)
starting_items = list(
/obj/item/reagent_containers/syringe/antiviral = 4,
/obj/item/reagent_containers/glass/bottle/cold = 1,
/obj/item/reagent_containers/glass/bottle/flu_virion = 1,
/obj/item/reagent_containers/glass/bottle/mutagen = 1,
/obj/item/reagent_containers/glass/bottle/plasma = 1,
/obj/item/reagent_containers/glass/bottle/reagent/synaptizine = 1,
/obj/item/reagent_containers/glass/bottle/reagent/formaldehyde = 1
)
. = ..()
req_access = list(ACCESS_SYNDICATE)
@@ -579,6 +669,7 @@
/obj/machinery/smartfridge/drinks
name = "\improper Drink Showcase"
desc = "A refrigerated storage unit for tasty tasty alcohol."
board_type = /obj/machinery/smartfridge/drinks
/obj/machinery/smartfridge/drinks/Initialize(mapload)
. = ..()
+1 -1
View File
@@ -58,7 +58,7 @@
var/obj/machinery/hydroponics/parent = loc
var/make_podman = 0
var/ckey_holder = null
if(config.revival_pod_plants)
if(GLOB.configuration.general.enable_revival_pod_plants)
if(ckey)
for(var/mob/M in GLOB.player_list)
if(isobserver(M))
+24 -25
View File
@@ -16,7 +16,7 @@
return
var/datum/db_query/log_query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("karma")] (spendername, spenderkey, receivername, receiverkey, receiverrole, receiverspecial, spenderip, time)
INSERT INTO karma (spendername, spenderkey, receivername, receiverkey, receiverrole, receiverspecial, spenderip, time)
VALUES (:sname, :skey, :rname, :rkey, :rrole, :rspecial, :sip, Now())"}, list(
"sname" = spender.name,
"skey" = spender.ckey,
@@ -33,7 +33,7 @@
qdel(log_query)
var/datum/db_query/select_spender = SSdbcore.NewQuery("SELECT id, karma FROM [format_table_name("karmatotals")] WHERE byondkey=:rkey", list(
var/datum/db_query/select_spender = SSdbcore.NewQuery("SELECT id, karma FROM karmatotals WHERE byondkey=:rkey", list(
"rkey" = receiver.ckey
))
@@ -52,7 +52,7 @@
if(karma == null)
karma = 1
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("karmatotals")] (byondkey, karma) VALUES (:rkey, :karma)", list(
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO karmatotals (byondkey, karma) VALUES (:rkey, :karma)", list(
"rkey" = receiver.ckey,
"karma" = karma
))
@@ -62,7 +62,7 @@
qdel(insert_query)
else
karma++
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("karmatotals")] SET karma=:karma WHERE id=:id", list(
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE karmatotals SET karma=:karma WHERE id=:id", list(
"karma" = karma,
"id" = id
))
@@ -78,7 +78,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
if(!client)
to_chat(src, "<span class='warning'>You can't award karma without being connected.</span>")
return FALSE
if(config.disable_karma)
if(!GLOB.configuration.general.enable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return FALSE
if(!SSticker || !GLOB.player_list.len || (SSticker.current_state == GAME_STATE_PREGAME))
@@ -152,7 +152,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
if(!M)
to_chat(usr, "Please right click a mob to award karma directly, or use the 'Award Karma' verb to select a player from the player listing.")
return
if(config.disable_karma) // this is here because someone thought it was a good idea to add an alert box before checking if they can even give a mob karma
if(!GLOB.configuration.general.enable_karma) // this is here because someone thought it was a good idea to add an alert box before checking if they can even give a mob karma
to_chat(usr, "<span class='warning'>Karma is disabled.</span>")
return
if(alert("Give [M.name] good karma?", "Karma", "Yes", "No") != "Yes")
@@ -160,20 +160,19 @@ GLOBAL_LIST_EMPTY(karma_spenders)
if(!can_give_karma_to_mob(M))
return // Check again, just in case things changed while the alert box was up
M.client.karma++
to_chat(usr, "Good karma spent on [M.name].")
client.karma_spent = TRUE
GLOB.karma_spenders += ckey
var/special_role = "None"
var/assigned_role = "None"
var/karma_diary = file("[GLOB.log_directory]/karma.log")
if(M.mind)
if(M.mind.special_role)
special_role = M.mind.special_role
if(M.mind.assigned_role)
assigned_role = M.mind.assigned_role
karma_diary << "[M.name] ([M.key]) [assigned_role]/[special_role]: [M.client.karma] - [time2text(world.timeofday, "hh:mm:ss")] given by [key]"
rustg_log_write("[GLOB.log_directory]/karma.log", "Karma awarded to [M.name] ([M.key]) (Role: [assigned_role] | Special: [special_role]) - Awarded by [ckey]")
sql_report_karma(src, M)
@@ -182,7 +181,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
set desc = "Reports how much karma you have accrued."
set category = "Special Verbs"
if(config.disable_karma)
if(!GLOB.configuration.general.enable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return
@@ -196,7 +195,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
to_chat(usr, "<span class='warning'>Unable to connect to karma database. Please try again later.<br></span>")
return
var/datum/db_query/query = SSdbcore.NewQuery("SELECT karma, karmaspent FROM [format_table_name("karmatotals")] WHERE byondkey=:ckey", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT karma, karmaspent FROM karmatotals WHERE byondkey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
@@ -218,13 +217,13 @@ GLOBAL_LIST_EMPTY(karma_spenders)
set desc = "Spend your hard-earned karma here"
set hidden = TRUE
if(config.disable_karma)
if(!GLOB.configuration.general.enable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return
karmashopmenu()
/client/proc/karmashopmenu()
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM whitelist WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
@@ -382,7 +381,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
karmashopmenu()
/client/proc/DB_job_unlock(job, cost)
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT ckey, job FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT ckey, job FROM whitelist WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!select_query.warn_execute())
@@ -397,7 +396,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
qdel(select_query)
if(!dbckey)
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("whitelist")] (ckey, job) VALUES (:ckey, :job)", list(
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO whitelist (ckey, job) VALUES (:ckey, :job)", list(
"ckey" = ckey,
"job" = job
))
@@ -416,7 +415,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
if(!(job in joblist))
joblist += job
var/newjoblist = jointext(joblist,",")
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("whitelist")] SET job=:newjoblist WHERE ckey=:ckey", list(
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE whitelist SET job=:newjoblist WHERE ckey=:ckey", list(
"newjoblist" = newjoblist,
"ckey" = ckey
))
@@ -433,7 +432,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
return
/client/proc/DB_species_unlock(species, cost)
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT ckey, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT ckey, species FROM whitelist WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!select_query.warn_execute())
@@ -447,7 +446,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
dbspecies = select_query.item[2]
qdel(select_query)
if(!dbckey)
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO [format_table_name("whitelist")] (ckey, species) VALUES (:ckey, :species)", list(
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO whitelist (ckey, species) VALUES (:ckey, :species)", list(
"ckey" = ckey,
"species" = species
))
@@ -465,7 +464,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
if(!(species in specieslist))
specieslist += species
var/newspecieslist = jointext(specieslist,",")
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("whitelist")] SET species=:newspecieslist WHERE ckey=:ckey", list(
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE whitelist SET species=:newspecieslist WHERE ckey=:ckey", list(
"newspecieslist" = newspecieslist,
"ckey" = ckey
))
@@ -482,7 +481,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
return
/client/proc/karmacharge(cost, refund = FALSE)
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT karmaspent FROM [format_table_name("karmatotals")] WHERE byondkey=:ckey", list(
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT karmaspent FROM karmatotals WHERE byondkey=:ckey", list(
"ckey" = ckey
))
if(!select_query.warn_execute())
@@ -495,7 +494,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
spent -= cost
else
spent += cost
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("karmatotals")] SET karmaspent=:spent WHERE byondkey=:ckey", list(
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE karmatotals SET karmaspent=:spent WHERE byondkey=:ckey", list(
"spent" = spent,
"ckey" = ckey
))
@@ -521,7 +520,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
to_chat(usr, "<span class='warning'>That job is not refundable.</span>")
return
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM whitelist WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
@@ -544,10 +543,10 @@ GLOBAL_LIST_EMPTY(karma_spenders)
switch(type)
if("job")
typelist = splittext(dbjob,",")
statement = "UPDATE [format_table_name("whitelist")] SET job=:newtypelist WHERE ckey=:ckey"
statement = "UPDATE whitelist SET job=:newtypelist WHERE ckey=:ckey"
if("species")
typelist = splittext(dbspecies,",")
statement = "UPDATE [format_table_name("whitelist")] SET species=:newtypelist WHERE ckey=:ckey"
statement = "UPDATE whitelist SET species=:newtypelist WHERE ckey=:ckey"
else
to_chat(usr, "<span class='warning'>Type [type] is not a valid column.</span>")
@@ -573,7 +572,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
to_chat(usr, "<span class='warning'>Your ckey ([dbckey]) was not found.</span>")
/client/proc/checkpurchased(name = null) // If the first parameter is null, return a full list of purchases
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM [format_table_name("whitelist")] WHERE ckey=:ckey", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT ckey, job, species FROM whitelist WHERE ckey=:ckey", list(
"ckey" = ckey
))
if(!query.warn_execute())
+2 -2
View File
@@ -10,7 +10,7 @@
if(!isbn)
return
var/datum/db_query/query_delbook = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=:isbn", list(
var/datum/db_query/query_delbook = SSdbcore.NewQuery("DELETE FROM library WHERE id=:isbn", list(
"isbn" = text2num(isbn) // just to be sure
))
if(!query_delbook.warn_execute())
@@ -37,7 +37,7 @@
var/dat = "<table><tr><th>ISBN</th><th>Title</th><th>Total Flags</th><th>Options</th></tr>"
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, title, flagged FROM [format_table_name("library")] WHERE flagged > 0 ORDER BY flagged DESC")
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, title, flagged FROM library WHERE flagged > 0 ORDER BY flagged DESC")
if(!query.warn_execute())
qdel(query)
return
+2 -2
View File
@@ -51,7 +51,7 @@
// This one doesnt take player input directly, so it doesnt require params
searchquery += " [!where ? "WHERE" : "AND"] flagged < [MAX_BOOK_FLAGS]"
// This does though
var/sql = "SELECT id, author, title, category, ckey, flagged FROM [format_table_name("library")] [searchquery] LIMIT :lowerlimit, :upperlimit"
var/sql = "SELECT id, author, title, category, ckey, flagged FROM library [searchquery] LIMIT :lowerlimit, :upperlimit"
sql_params["lowerlimit"] = text2num((page_num - 1) * LIBRARY_BOOKS_PER_PAGE)
sql_params["upperlimit"] = LIBRARY_BOOKS_PER_PAGE
@@ -78,7 +78,7 @@
return results
/obj/machinery/computer/library/proc/get_num_results()
var/sql = "SELECT COUNT(id) FROM [format_table_name("library")]"
var/sql = "SELECT COUNT(id) FROM library"
var/datum/db_query/count_query = SSdbcore.NewQuery(sql)
if(!count_query.warn_execute())
+3 -3
View File
@@ -262,7 +262,7 @@
var/datum/cachedbook/target = getBookByID(href_list["del"]) // Sanitized in getBookByID
var/ans = alert(usr, "Are you sure you wish to delete \"[target.title]\", by [target.author]? This cannot be undone.", "Library System", "Yes", "No")
if(ans=="Yes")
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=:id", list(
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM library WHERE id=:id", list(
"id" = text2num(target.id)
))
if(!query.warn_execute())
@@ -280,7 +280,7 @@
var/tckey = ckey(href_list["delbyckey"])
var/ans = alert(usr,"Are you sure you wish to delete all books by [tckey]? This cannot be undone.", "Library System", "Yes", "No")
if(ans=="Yes")
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE ckey=:ckey", list(
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM library WHERE ckey=:ckey", list(
"ckey" = tckey
))
if(!query.warn_execute())
@@ -387,7 +387,7 @@
alert("Connection to Archive has been severed. Aborting.")
else
var/datum/db_query/query = SSdbcore.NewQuery({"
INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, flagged)
INSERT INTO library (author, title, content, category, ckey, flagged)
VALUES (:author, :title, :content, :category, :ckey, 0)"}, list(
"author" = scanner.cache.author,
"title" = scanner.cache.name,
+3 -3
View File
@@ -78,7 +78,7 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
books_flagged_this_round["[id]"] = 1
message_admins("[key_name_admin(user)] has flagged book #[id] as inappropriate.")
var/datum/db_query/query = SSdbcore.NewQuery("UPDATE [format_table_name("library")] SET flagged = flagged + 1 WHERE id=:id", list(
var/datum/db_query/query = SSdbcore.NewQuery("UPDATE library SET flagged = flagged + 1 WHERE id=:id", list(
"id" = text2num(id)
))
if(!query.warn_execute())
@@ -93,7 +93,7 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
to_chat(user, "<span class='danger'>That book cannot be removed from the system, as it does not actually exist in the database.</span>")
return
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=:id", list(
var/datum/db_query/query = SSdbcore.NewQuery("DELETE FROM library WHERE id=:id", list(
"id" = text2num(id)
))
if(!query.warn_execute())
@@ -105,7 +105,7 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
if("[id]" in cached_books)
return cached_books["[id]"]
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, author, title, category, content, ckey, flagged FROM [format_table_name("library")] WHERE id=:id", list(
var/datum/db_query/query = SSdbcore.NewQuery("SELECT id, author, title, category, content, ckey, flagged FROM library WHERE id=:id", list(
"id" = text2num(id)
))
if(!query.warn_execute())

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