mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-11 18:33:36 +00:00
modules
This commit is contained in:
@@ -39,7 +39,7 @@
|
|||||||
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
|
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
|
||||||
if (CONFIG_GET(flag/panic_bunker) && SSdbcore.Connect())
|
if (CONFIG_GET(flag/panic_bunker) && SSdbcore.Connect())
|
||||||
log_access("Failed Login: [key] - Guests not allowed during panic bunker")
|
log_access("Failed Login: [key] - Guests not allowed during panic bunker")
|
||||||
return list("reason"="guest", "desc"="\nReason: You must first join the Discord to verify your account before joining this server. Please ping an admin once you've joined and read the rules. https://discord.gg/E6SQuhz")
|
return list("reason"="guest", "desc"="\nReason: Sorry but the server is currently not accepting connections from never before seen players or guests. If you have played on this server with a byond account before, please log in to the byond account you have played from.")
|
||||||
|
|
||||||
//Population Cap Checking
|
//Population Cap Checking
|
||||||
var/extreme_popcap = CONFIG_GET(number/extreme_popcap)
|
var/extreme_popcap = CONFIG_GET(number/extreme_popcap)
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
GLOBAL_LIST_EMPTY(admin_ranks) //list of all admin_rank datums
|
GLOBAL_LIST_EMPTY(admin_ranks) //list of all admin_rank datums
|
||||||
GLOBAL_PROTECT(admin_ranks)
|
GLOBAL_PROTECT(admin_ranks)
|
||||||
|
|
||||||
|
GLOBAL_LIST_EMPTY(protected_ranks) //admin ranks loaded from txt
|
||||||
|
GLOBAL_PROTECT(protected_ranks)
|
||||||
|
|
||||||
/datum/admin_rank
|
/datum/admin_rank
|
||||||
var/name = "NoRank"
|
var/name = "NoRank"
|
||||||
var/rights = R_DEFAULT
|
var/rights = R_DEFAULT
|
||||||
var/list/adds
|
var/exclude_rights = 0
|
||||||
var/list/subs
|
var/include_rights = 0
|
||||||
|
var/can_edit_rights = 0
|
||||||
|
|
||||||
/datum/admin_rank/New(init_name, init_rights, list/init_adds, list/init_subs)
|
/datum/admin_rank/New(init_name, init_rights, init_exclude_rights, init_edit_rights)
|
||||||
if(IsAdminAdvancedProcCall())
|
if(IsAdminAdvancedProcCall())
|
||||||
var/msg = " has tried to elevate permissions!"
|
var/msg = " has tried to elevate permissions!"
|
||||||
message_admins("[key_name_admin(usr)][msg]")
|
message_admins("[key_name_admin(usr)][msg]")
|
||||||
@@ -17,19 +21,18 @@ GLOBAL_PROTECT(admin_ranks)
|
|||||||
CRASH("Admin proc call creation of admin datum")
|
CRASH("Admin proc call creation of admin datum")
|
||||||
return
|
return
|
||||||
name = init_name
|
name = init_name
|
||||||
switch(name)
|
if(!name)
|
||||||
if("Removed",null,"")
|
qdel(src)
|
||||||
QDEL_IN(src, 0)
|
throw EXCEPTION("Admin rank created without name.")
|
||||||
throw EXCEPTION("invalid admin-rank name")
|
return
|
||||||
return
|
|
||||||
if(init_rights)
|
if(init_rights)
|
||||||
rights = init_rights
|
rights = init_rights
|
||||||
if(!init_adds)
|
include_rights = rights
|
||||||
init_adds = list()
|
if(init_exclude_rights)
|
||||||
if(!init_subs)
|
exclude_rights = init_exclude_rights
|
||||||
init_subs = list()
|
rights &= ~exclude_rights
|
||||||
adds = init_adds
|
if(init_edit_rights)
|
||||||
subs = init_subs
|
can_edit_rights = init_edit_rights
|
||||||
|
|
||||||
/datum/admin_rank/Destroy()
|
/datum/admin_rank/Destroy()
|
||||||
if(IsAdminAdvancedProcCall())
|
if(IsAdminAdvancedProcCall())
|
||||||
@@ -75,13 +78,12 @@ GLOBAL_PROTECT(admin_ranks)
|
|||||||
flag = R_SPAWN
|
flag = R_SPAWN
|
||||||
if("autologin", "autoadmin")
|
if("autologin", "autoadmin")
|
||||||
flag = R_AUTOLOGIN
|
flag = R_AUTOLOGIN
|
||||||
|
if("dbranks")
|
||||||
|
flag = R_DBRANKS
|
||||||
if("@","prev")
|
if("@","prev")
|
||||||
flag = previous_rights
|
flag = previous_rights
|
||||||
return flag
|
return flag
|
||||||
|
|
||||||
/proc/admin_keyword_to_path(word) //use this with verb keywords eg +/client/proc/blah
|
|
||||||
return text2path(copytext(word, 2, findtext(word, " ", 2, 0)))
|
|
||||||
|
|
||||||
// Adds/removes rights to this admin_rank
|
// Adds/removes rights to this admin_rank
|
||||||
/datum/admin_rank/proc/process_keyword(word, previous_rights=0)
|
/datum/admin_rank/proc/process_keyword(word, previous_rights=0)
|
||||||
if(IsAdminAdvancedProcCall())
|
if(IsAdminAdvancedProcCall())
|
||||||
@@ -94,157 +96,156 @@ GLOBAL_PROTECT(admin_ranks)
|
|||||||
switch(text2ascii(word,1))
|
switch(text2ascii(word,1))
|
||||||
if(43)
|
if(43)
|
||||||
rights |= flag //+
|
rights |= flag //+
|
||||||
|
include_rights |= flag
|
||||||
if(45)
|
if(45)
|
||||||
rights &= ~flag //-
|
rights &= ~flag //-
|
||||||
else
|
exclude_rights |= flag
|
||||||
//isn't a keyword so maybe it's a verbpath?
|
if(42)
|
||||||
var/path = admin_keyword_to_path(word)
|
can_edit_rights |= flag //*
|
||||||
if(path)
|
|
||||||
switch(text2ascii(word,1))
|
|
||||||
if(43)
|
|
||||||
if(!subs.Remove(path))
|
|
||||||
adds += path //+
|
|
||||||
if(45)
|
|
||||||
if(!adds.Remove(path))
|
|
||||||
subs += path //-
|
|
||||||
|
|
||||||
|
|
||||||
// Checks for (keyword-formatted) rights on this admin
|
// Checks for (keyword-formatted) rights on this admin
|
||||||
/datum/admins/proc/check_keyword(word)
|
/datum/admins/proc/check_keyword(word)
|
||||||
var/flag = admin_keyword_to_flag(word)
|
var/flag = admin_keyword_to_flag(word)
|
||||||
if(flag)
|
if(flag)
|
||||||
return ((rank.rights & flag) == flag) //true only if right has everything in flag
|
return ((rank.rights & flag) == flag) //true only if right has everything in flag
|
||||||
else
|
|
||||||
var/path = admin_keyword_to_path(word)
|
|
||||||
for(var/i in owner.verbs) //this needs to be a foreach loop for some reason. in operator and verbs.Find() don't work
|
|
||||||
if(i == path)
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
//load our rank - > rights associations
|
//load our rank - > rights associations
|
||||||
/proc/load_admin_ranks()
|
/proc/load_admin_ranks(dbfail)
|
||||||
if(IsAdminAdvancedProcCall())
|
if(IsAdminAdvancedProcCall())
|
||||||
to_chat(usr, "<span class='admin prefix'>Admin Reload blocked: Advanced ProcCall detected.</span>")
|
to_chat(usr, "<span class='admin prefix'>Admin Reload blocked: Advanced ProcCall detected.</span>")
|
||||||
return
|
return
|
||||||
GLOB.admin_ranks.Cut()
|
GLOB.admin_ranks.Cut()
|
||||||
|
GLOB.protected_ranks.Cut()
|
||||||
if(CONFIG_GET(flag/admin_legacy_system))
|
var/previous_rights = 0
|
||||||
var/previous_rights = 0
|
//load text from file and process each line separately
|
||||||
//load text from file and process each line separately
|
for(var/line in world.file2list("[global.config.directory]/admin_ranks.txt"))
|
||||||
for(var/line in world.file2list("[global.config.directory]/admin_ranks.txt"))
|
if(!line || findtextEx(line,"#",1,2))
|
||||||
if(!line)
|
continue
|
||||||
continue
|
var/next = findtext(line, "=")
|
||||||
if(findtextEx(line,"#",1,2))
|
var/datum/admin_rank/R = new(ckeyEx(copytext(line, 1, next)))
|
||||||
continue
|
if(!R)
|
||||||
|
continue
|
||||||
var/next = findtext(line, "=")
|
GLOB.admin_ranks += R
|
||||||
var/datum/admin_rank/R = new(ckeyEx(copytext(line, 1, next)))
|
GLOB.protected_ranks += R
|
||||||
if(!R)
|
var/prev = findchar(line, "+-*", next, 0)
|
||||||
continue
|
while(prev)
|
||||||
GLOB.admin_ranks += R
|
next = findchar(line, "+-*", prev + 1, 0)
|
||||||
|
R.process_keyword(copytext(line, prev, next), previous_rights)
|
||||||
var/prev = findchar(line, "+-", next, 0)
|
prev = next
|
||||||
while(prev)
|
previous_rights = R.rights
|
||||||
next = findchar(line, "+-", prev + 1, 0)
|
if(!CONFIG_GET(flag/admin_legacy_system) || dbfail)
|
||||||
R.process_keyword(copytext(line, prev, next), previous_rights)
|
var/datum/DBQuery/query_load_admin_ranks = SSdbcore.NewQuery("SELECT rank, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")]")
|
||||||
prev = next
|
|
||||||
|
|
||||||
previous_rights = R.rights
|
|
||||||
else
|
|
||||||
if(!SSdbcore.Connect())
|
|
||||||
if(CONFIG_GET(flag/sql_enabled))
|
|
||||||
var/msg = "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
|
|
||||||
log_world(msg)
|
|
||||||
WRITE_FILE(GLOB.world_game_log, msg)
|
|
||||||
CONFIG_SET(flag/admin_legacy_system, TRUE)
|
|
||||||
load_admin_ranks()
|
|
||||||
return
|
|
||||||
|
|
||||||
var/datum/DBQuery/query_load_admin_ranks = SSdbcore.NewQuery("SELECT rank, flags FROM [format_table_name("admin_ranks")]")
|
|
||||||
if(!query_load_admin_ranks.Execute())
|
if(!query_load_admin_ranks.Execute())
|
||||||
|
message_admins("Error loading admin ranks from database. Loading from backup.")
|
||||||
|
log_sql("Error loading admin ranks from database. Loading from backup.")
|
||||||
|
dbfail = 1
|
||||||
|
else
|
||||||
|
while(query_load_admin_ranks.NextRow())
|
||||||
|
var/skip
|
||||||
|
var/rank_name = query_load_admin_ranks.item[1]
|
||||||
|
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||||
|
if(R.name == rank_name) //this rank was already loaded from txt override
|
||||||
|
skip = 1
|
||||||
|
break
|
||||||
|
if(!skip)
|
||||||
|
var/rank_flags = text2num(query_load_admin_ranks.item[2])
|
||||||
|
var/rank_exclude_flags = text2num(query_load_admin_ranks.item[3])
|
||||||
|
var/rank_can_edit_flags = text2num(query_load_admin_ranks.item[4])
|
||||||
|
var/datum/admin_rank/R = new(rank_name, rank_flags, rank_exclude_flags, rank_can_edit_flags)
|
||||||
|
if(!R)
|
||||||
|
continue
|
||||||
|
GLOB.admin_ranks += R
|
||||||
|
//load ranks from backup file
|
||||||
|
if(dbfail)
|
||||||
|
var/backup_file = file("data/admins_backup.json")
|
||||||
|
if(!fexists(backup_file))
|
||||||
|
log_world("Unable to locate admins backup file.")
|
||||||
return
|
return
|
||||||
while(query_load_admin_ranks.NextRow())
|
var/list/json = json_decode(file2text(backup_file))
|
||||||
var/rank_name = ckeyEx(query_load_admin_ranks.item[1])
|
for(var/J in json["ranks"])
|
||||||
var/flags = query_load_admin_ranks.item[2]
|
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||||
if(istext(flags))
|
if(R.name == "[J]") //this rank was already loaded from txt override
|
||||||
flags = text2num(flags)
|
continue
|
||||||
var/datum/admin_rank/R = new(rank_name, flags)
|
var/datum/admin_rank/R = new("[J]", json["ranks"]["[J]"]["include rights"], json["ranks"]["[J]"]["exclude rights"], json["ranks"]["[J]"]["can edit rights"])
|
||||||
if(!R)
|
if(!R)
|
||||||
continue
|
continue
|
||||||
GLOB.admin_ranks += R
|
GLOB.admin_ranks += R
|
||||||
|
return 1
|
||||||
#ifdef TESTING
|
#ifdef TESTING
|
||||||
var/msg = "Permission Sets Built:\n"
|
var/msg = "Permission Sets Built:\n"
|
||||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||||
msg += "\t[R.name]"
|
msg += "\t[R.name]"
|
||||||
var/rights = rights2text(R.rights,"\n\t\t",R.adds,R.subs)
|
var/rights = rights2text(R.rights,"\n\t\t")
|
||||||
if(rights)
|
if(rights)
|
||||||
msg += "\t\t[rights]\n"
|
msg += "\t\t[rights]\n"
|
||||||
testing(msg)
|
testing(msg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/proc/load_admins()
|
/proc/load_admins()
|
||||||
|
var/dbfail
|
||||||
|
if(!CONFIG_GET(flag/admin_legacy_system) && !SSdbcore.Connect())
|
||||||
|
message_admins("Failed to connect to database while loading admins. Loading from backup.")
|
||||||
|
log_sql("Failed to connect to database while loading admins. Loading from backup.")
|
||||||
|
dbfail = 1
|
||||||
//clear the datums references
|
//clear the datums references
|
||||||
|
|
||||||
GLOB.admin_datums.Cut()
|
GLOB.admin_datums.Cut()
|
||||||
for(var/client/C in GLOB.admins)
|
for(var/client/C in GLOB.admins)
|
||||||
C.remove_admin_verbs()
|
C.remove_admin_verbs()
|
||||||
C.holder = null
|
C.holder = null
|
||||||
GLOB.admins.Cut()
|
GLOB.admins.Cut()
|
||||||
|
GLOB.protected_admins.Cut()
|
||||||
GLOB.deadmins.Cut()
|
GLOB.deadmins.Cut()
|
||||||
load_admin_ranks()
|
dbfail = load_admin_ranks(dbfail)
|
||||||
//Clear profile access
|
//Clear profile access
|
||||||
for(var/A in world.GetConfig("admin"))
|
for(var/A in world.GetConfig("admin"))
|
||||||
world.SetConfig("APP/admin", A, null)
|
world.SetConfig("APP/admin", A, null)
|
||||||
|
|
||||||
var/list/rank_names = list()
|
var/list/rank_names = list()
|
||||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||||
rank_names[R.name] = R
|
rank_names[R.name] = R
|
||||||
|
//ckeys listed in admins.txt are always made admins before sql loading is attempted
|
||||||
if(CONFIG_GET(flag/admin_legacy_system))
|
var/list/lines = world.file2list("[global.config.directory]/admins.txt")
|
||||||
//load text from file
|
for(var/line in lines)
|
||||||
var/list/lines = world.file2list("[global.config.directory]/admins.txt")
|
if(!length(line) || findtextEx(line, "#", 1, 2))
|
||||||
|
continue
|
||||||
//process each line separately
|
var/list/entry = splittext(line, "=")
|
||||||
for(var/line in lines)
|
if(entry.len < 2)
|
||||||
if(!length(line))
|
continue
|
||||||
continue
|
var/ckey = ckey(entry[1])
|
||||||
if(findtextEx(line, "#", 1, 2))
|
var/rank = ckeyEx(entry[2])
|
||||||
continue
|
if(!ckey || !rank)
|
||||||
|
continue
|
||||||
var/list/entry = splittext(line, "=")
|
new /datum/admins(rank_names[rank], ckey, 0, 1)
|
||||||
if(entry.len < 2)
|
if(!CONFIG_GET(flag/admin_legacy_system) || dbfail)
|
||||||
continue
|
|
||||||
|
|
||||||
var/ckey = ckey(entry[1])
|
|
||||||
var/rank = ckeyEx(entry[2])
|
|
||||||
if(!ckey || !rank)
|
|
||||||
continue
|
|
||||||
|
|
||||||
new /datum/admins(rank_names[rank], ckey)
|
|
||||||
|
|
||||||
else
|
|
||||||
if(!SSdbcore.Connect())
|
|
||||||
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
|
|
||||||
WRITE_FILE(GLOB.world_game_log, "Failed to connect to database in load_admins(). Reverting to legacy system.")
|
|
||||||
CONFIG_SET(flag/admin_legacy_system, TRUE)
|
|
||||||
load_admins()
|
|
||||||
return
|
|
||||||
|
|
||||||
var/datum/DBQuery/query_load_admins = SSdbcore.NewQuery("SELECT ckey, rank FROM [format_table_name("admin")]")
|
var/datum/DBQuery/query_load_admins = SSdbcore.NewQuery("SELECT ckey, rank FROM [format_table_name("admin")]")
|
||||||
if(!query_load_admins.Execute())
|
if(!query_load_admins.Execute())
|
||||||
|
message_admins("Error loading admins from database. Loading from backup.")
|
||||||
|
log_sql("Error loading admins from database. Loading from backup.")
|
||||||
|
dbfail = 1
|
||||||
|
else
|
||||||
|
while(query_load_admins.NextRow())
|
||||||
|
var/admin_ckey = query_load_admins.item[1]
|
||||||
|
var/admin_rank = query_load_admins.item[2]
|
||||||
|
var/skip
|
||||||
|
if(rank_names[admin_rank] == null)
|
||||||
|
message_admins("[admin_ckey] loaded with invalid admin rank [admin_rank].")
|
||||||
|
log_sql("[admin_ckey] loaded with invalid admin rank [admin_rank].")
|
||||||
|
skip = 1
|
||||||
|
if(GLOB.admin_datums[admin_ckey] || GLOB.deadmins[admin_ckey])
|
||||||
|
skip = 1
|
||||||
|
if(!skip)
|
||||||
|
new /datum/admins(rank_names[admin_rank], admin_ckey)
|
||||||
|
//load admins from backup file
|
||||||
|
if(dbfail)
|
||||||
|
var/backup_file = file("data/admins_backup.json")
|
||||||
|
if(!fexists(backup_file))
|
||||||
|
log_world("Unable to locate admins backup file.")
|
||||||
return
|
return
|
||||||
while(query_load_admins.NextRow())
|
var/list/json = json_decode(file2text(backup_file))
|
||||||
var/ckey = ckey(query_load_admins.item[1])
|
for(var/J in json["admins"])
|
||||||
var/rank = ckeyEx(query_load_admins.item[2])
|
for(var/A in GLOB.admin_datums + GLOB.deadmins)
|
||||||
|
if(A == "[J]") //this admin was already loaded from txt override
|
||||||
if(rank_names[rank] == null)
|
continue
|
||||||
WARNING("Admin rank ([rank]) does not exist.")
|
new /datum/admins(rank_names[json["admins"]["[J]"]], "[J]")
|
||||||
continue
|
|
||||||
|
|
||||||
new /datum/admins(rank_names[rank], ckey)
|
|
||||||
|
|
||||||
#ifdef TESTING
|
#ifdef TESTING
|
||||||
var/msg = "Admins Built:\n"
|
var/msg = "Admins Built:\n"
|
||||||
for(var/ckey in GLOB.admin_datums)
|
for(var/ckey in GLOB.admin_datums)
|
||||||
@@ -252,7 +253,7 @@ GLOBAL_PROTECT(admin_ranks)
|
|||||||
msg += "\t[ckey] - [D.rank.name]\n"
|
msg += "\t[ckey] - [D.rank.name]\n"
|
||||||
testing(msg)
|
testing(msg)
|
||||||
#endif
|
#endif
|
||||||
|
return dbfail
|
||||||
|
|
||||||
#ifdef TESTING
|
#ifdef TESTING
|
||||||
/client/verb/changerank(newrank in GLOB.admin_ranks)
|
/client/verb/changerank(newrank in GLOB.admin_ranks)
|
||||||
@@ -271,149 +272,3 @@ GLOBAL_PROTECT(admin_ranks)
|
|||||||
remove_admin_verbs()
|
remove_admin_verbs()
|
||||||
holder.associate(src)
|
holder.associate(src)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/datum/admins/proc/edit_rights_topic(list/href_list)
|
|
||||||
if(!check_rights(R_PERMISSIONS))
|
|
||||||
message_admins("[key_name_admin(usr)] attempted to edit the admin permissions without sufficient rights.")
|
|
||||||
log_admin("[key_name(usr)] attempted to edit the admin permissions without sufficient rights.")
|
|
||||||
return
|
|
||||||
if(IsAdminAdvancedProcCall())
|
|
||||||
to_chat(usr, "<span class='admin prefix'>Admin Edit blocked: Advanced ProcCall detected.</span>")
|
|
||||||
return
|
|
||||||
|
|
||||||
var/adm_ckey
|
|
||||||
var/task = href_list["editrights"]
|
|
||||||
switch(task)
|
|
||||||
if("add")
|
|
||||||
var/new_ckey = ckey(input(usr,"New admin's ckey","Admin ckey", null) as text|null)
|
|
||||||
if(!new_ckey)
|
|
||||||
return
|
|
||||||
if(new_ckey in GLOB.admin_datums)
|
|
||||||
to_chat(usr, "<font color='red'>Error: Topic 'editrights': [new_ckey] is already an admin</font>")
|
|
||||||
return
|
|
||||||
adm_ckey = new_ckey
|
|
||||||
task = "rank"
|
|
||||||
else
|
|
||||||
adm_ckey = ckey(href_list["ckey"])
|
|
||||||
if(!adm_ckey)
|
|
||||||
to_chat(usr, "<font color='red'>Error: Topic 'editrights': No valid ckey</font>")
|
|
||||||
return
|
|
||||||
|
|
||||||
var/datum/admins/D = GLOB.admin_datums[adm_ckey]
|
|
||||||
if (!D)
|
|
||||||
D = GLOB.deadmins[adm_ckey]
|
|
||||||
|
|
||||||
switch(task)
|
|
||||||
if("remove")
|
|
||||||
if(alert("Are you sure you want to remove [adm_ckey]?","Message","Yes","Cancel") == "Yes")
|
|
||||||
if(!D)
|
|
||||||
return
|
|
||||||
if(!check_if_greater_rights_than_holder(D))
|
|
||||||
message_admins("[key_name_admin(usr)] attempted to remove [adm_ckey] from the admins list without sufficient rights.")
|
|
||||||
log_admin("[key_name(usr)] attempted to remove [adm_ckey] from the admins list without sufficient rights.")
|
|
||||||
return
|
|
||||||
GLOB.admin_datums -= adm_ckey
|
|
||||||
GLOB.deadmins -= adm_ckey
|
|
||||||
D.disassociate()
|
|
||||||
|
|
||||||
updateranktodb(adm_ckey, "player")
|
|
||||||
message_admins("[key_name_admin(usr)] removed [adm_ckey] from the admins list")
|
|
||||||
log_admin("[key_name(usr)] removed [adm_ckey] from the admins list")
|
|
||||||
log_admin_rank_modification(adm_ckey, "Removed")
|
|
||||||
|
|
||||||
if("rank")
|
|
||||||
var/datum/admin_rank/R
|
|
||||||
|
|
||||||
var/list/rank_names = list("*New Rank*")
|
|
||||||
for(R in GLOB.admin_ranks)
|
|
||||||
rank_names[R.name] = R
|
|
||||||
|
|
||||||
var/new_rank = input("Please select a rank", "New rank", null, null) as null|anything in rank_names
|
|
||||||
|
|
||||||
switch(new_rank)
|
|
||||||
if(null)
|
|
||||||
return
|
|
||||||
if("*New Rank*")
|
|
||||||
new_rank = ckeyEx(input("Please input a new rank", "New custom rank", null, null) as null|text)
|
|
||||||
if(!new_rank)
|
|
||||||
return
|
|
||||||
|
|
||||||
if(D)
|
|
||||||
if(!check_if_greater_rights_than_holder(D))
|
|
||||||
message_admins("[key_name_admin(usr)] attempted to change the rank of [adm_ckey] to [new_rank] without sufficient rights.")
|
|
||||||
log_admin("[key_name(usr)] attempted to change the rank of [adm_ckey] to [new_rank] without sufficient rights.")
|
|
||||||
return
|
|
||||||
|
|
||||||
R = rank_names[new_rank]
|
|
||||||
if(!R) //rank with that name doesn't exist yet - make it
|
|
||||||
if(D)
|
|
||||||
R = new(new_rank, D.rank.rights, D.rank.adds, D.rank.subs) //duplicate our previous admin_rank but with a new name
|
|
||||||
else
|
|
||||||
R = new(new_rank) //blank new admin_rank
|
|
||||||
GLOB.admin_ranks += R
|
|
||||||
|
|
||||||
if(D) //they were previously an admin
|
|
||||||
D.disassociate() //existing admin needs to be disassociated
|
|
||||||
D.rank = R //set the admin_rank as our rank
|
|
||||||
D.associate()
|
|
||||||
else
|
|
||||||
D = new(R, adm_ckey, TRUE) //new admin
|
|
||||||
|
|
||||||
updateranktodb(adm_ckey, new_rank)
|
|
||||||
message_admins("[key_name_admin(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
|
|
||||||
log_admin("[key_name(usr)] edited the admin rank of [adm_ckey] to [new_rank]")
|
|
||||||
log_admin_rank_modification(adm_ckey, new_rank)
|
|
||||||
|
|
||||||
if("permissions")
|
|
||||||
if(!D)
|
|
||||||
return //they're not an admin!
|
|
||||||
|
|
||||||
var/keyword = input("Input permission keyword (one at a time):\ne.g. +BAN or -FUN or +/client/proc/someverb", "Permission toggle", null, null) as null|text
|
|
||||||
if(!keyword)
|
|
||||||
return
|
|
||||||
|
|
||||||
if(!check_keyword(keyword) || !check_if_greater_rights_than_holder(D))
|
|
||||||
message_admins("[key_name_admin(usr)] attempted to give [adm_ckey] the keyword [keyword] without sufficient rights.")
|
|
||||||
log_admin("[key_name(usr)] attempted to give [adm_ckey] the keyword [keyword] without sufficient rights.")
|
|
||||||
return
|
|
||||||
|
|
||||||
D.disassociate()
|
|
||||||
|
|
||||||
if(!findtext(D.rank.name, "([adm_ckey])")) //not a modified subrank, need to duplicate the admin_rank datum to prevent modifying others too
|
|
||||||
D.rank = new("[D.rank.name]([adm_ckey])", D.rank.rights, D.rank.adds, D.rank.subs) //duplicate our previous admin_rank but with a new name
|
|
||||||
//we don't add this clone to the admin_ranks list, as it is unique to that ckey
|
|
||||||
D.rank.process_keyword(keyword)
|
|
||||||
|
|
||||||
var/client/C = GLOB.directory[adm_ckey] //find the client with the specified ckey (if they are logged in)
|
|
||||||
D.associate(C) //link up with the client and add verbs
|
|
||||||
|
|
||||||
message_admins("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]")
|
|
||||||
log_admin("[key_name(usr)] added keyword [keyword] to permission of [adm_ckey]")
|
|
||||||
log_admin_permission_modification(adm_ckey, D.rank.rights)
|
|
||||||
if("activate") //forcefully readmin
|
|
||||||
if(!D || !D.deadmined)
|
|
||||||
return
|
|
||||||
|
|
||||||
D.activate()
|
|
||||||
|
|
||||||
message_admins("[key_name_admin(usr)] forcefully readmined [adm_ckey]")
|
|
||||||
log_admin("[key_name(usr)] forcefully readmined [adm_ckey]")
|
|
||||||
if("deactivate") //forcefully deadmin
|
|
||||||
if(!D || D.deadmined)
|
|
||||||
return
|
|
||||||
|
|
||||||
message_admins("[key_name_admin(usr)] forcefully deadmined [adm_ckey]")
|
|
||||||
log_admin("[key_name(usr)] forcefully deadmined [adm_ckey]")
|
|
||||||
|
|
||||||
D.deactivate() //after logs so the deadmined admin can see the message.
|
|
||||||
|
|
||||||
edit_admin_permissions()
|
|
||||||
|
|
||||||
/datum/admins/proc/updateranktodb(ckey,newrank)
|
|
||||||
if(!SSdbcore.Connect())
|
|
||||||
return
|
|
||||||
var/sql_ckey = sanitizeSQL(ckey)
|
|
||||||
var/sql_admin_rank = sanitizeSQL(newrank)
|
|
||||||
|
|
||||||
var/datum/DBQuery/query_admin_rank_update = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'")
|
|
||||||
query_admin_rank_update.Execute()
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
|
|||||||
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
|
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
|
||||||
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
|
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
|
||||||
/client/proc/cmd_admin_ticket_panel,
|
/client/proc/cmd_admin_ticket_panel,
|
||||||
/client/proc/panicbunker,
|
|
||||||
/client/proc/stop_sounds
|
/client/proc/stop_sounds
|
||||||
)
|
)
|
||||||
GLOBAL_PROTECT(admin_verbs_admin)
|
GLOBAL_PROTECT(admin_verbs_admin)
|
||||||
@@ -117,6 +116,7 @@ GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
|
|||||||
/client/proc/toggle_random_events,
|
/client/proc/toggle_random_events,
|
||||||
/client/proc/forcerandomrotate,
|
/client/proc/forcerandomrotate,
|
||||||
/client/proc/adminchangemap,
|
/client/proc/adminchangemap,
|
||||||
|
/client/proc/panicbunker,
|
||||||
/client/proc/toggle_hub
|
/client/proc/toggle_hub
|
||||||
)
|
)
|
||||||
GLOBAL_PROTECT(admin_verbs_debug)
|
GLOBAL_PROTECT(admin_verbs_debug)
|
||||||
@@ -157,7 +157,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
|
|||||||
/client/proc/pump_random_event,
|
/client/proc/pump_random_event,
|
||||||
/client/proc/cmd_display_init_log,
|
/client/proc/cmd_display_init_log,
|
||||||
/client/proc/cmd_display_overlay_log,
|
/client/proc/cmd_display_overlay_log,
|
||||||
/datum/admins/proc/create_or_modify_area
|
/datum/admins/proc/create_or_modify_area,
|
||||||
)
|
)
|
||||||
GLOBAL_PROTECT(admin_verbs_possess)
|
GLOBAL_PROTECT(admin_verbs_possess)
|
||||||
GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release))
|
GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release))
|
||||||
@@ -267,11 +267,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
|||||||
if(rights & R_SPAWN)
|
if(rights & R_SPAWN)
|
||||||
verbs += GLOB.admin_verbs_spawn
|
verbs += GLOB.admin_verbs_spawn
|
||||||
|
|
||||||
for(var/path in holder.rank.adds)
|
|
||||||
verbs += path
|
|
||||||
for(var/path in holder.rank.subs)
|
|
||||||
verbs -= path
|
|
||||||
|
|
||||||
/client/proc/remove_admin_verbs()
|
/client/proc/remove_admin_verbs()
|
||||||
verbs.Remove(
|
verbs.Remove(
|
||||||
GLOB.admin_verbs_default,
|
GLOB.admin_verbs_default,
|
||||||
@@ -306,8 +301,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
|||||||
/client/proc/cmd_admin_areatest_station,
|
/client/proc/cmd_admin_areatest_station,
|
||||||
/client/proc/readmin
|
/client/proc/readmin
|
||||||
)
|
)
|
||||||
if(holder)
|
|
||||||
verbs.Remove(holder.rank.adds)
|
|
||||||
|
|
||||||
/client/proc/hide_most_verbs()//Allows you to keep some functionality while hiding some verbs
|
/client/proc/hide_most_verbs()//Allows you to keep some functionality while hiding some verbs
|
||||||
set name = "Adminverbs - Hide Most"
|
set name = "Adminverbs - Hide Most"
|
||||||
@@ -528,8 +521,10 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
|||||||
set desc = "Get the estimated range of a bomb, using explosive power."
|
set desc = "Get the estimated range of a bomb, using explosive power."
|
||||||
|
|
||||||
var/ex_power = input("Explosive Power:") as null|num
|
var/ex_power = input("Explosive Power:") as null|num
|
||||||
|
if (isnull(ex_power))
|
||||||
|
return
|
||||||
var/range = round((2 * ex_power)**GLOB.DYN_EX_SCALE)
|
var/range = round((2 * ex_power)**GLOB.DYN_EX_SCALE)
|
||||||
to_chat(usr, "Estimated Explosive Range: (Devestation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])")
|
to_chat(usr, "Estimated Explosive Range: (Devastation: [round(range*0.25)], Heavy: [round(range*0.5)], Light: [round(range)])")
|
||||||
|
|
||||||
/client/proc/get_dynex_power()
|
/client/proc/get_dynex_power()
|
||||||
set category = "Debug"
|
set category = "Debug"
|
||||||
@@ -537,6 +532,8 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
|||||||
set desc = "Get the estimated required power of a bomb, to reach a specific range."
|
set desc = "Get the estimated required power of a bomb, to reach a specific range."
|
||||||
|
|
||||||
var/ex_range = input("Light Explosion Range:") as null|num
|
var/ex_range = input("Light Explosion Range:") as null|num
|
||||||
|
if (isnull(ex_range))
|
||||||
|
return
|
||||||
var/power = (0.5 * ex_range)**(1/GLOB.DYN_EX_SCALE)
|
var/power = (0.5 * ex_range)**(1/GLOB.DYN_EX_SCALE)
|
||||||
to_chat(usr, "Estimated Explosive Power: [power]")
|
to_chat(usr, "Estimated Explosive Power: [power]")
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
GLOBAL_LIST_EMPTY(admin_datums)
|
GLOBAL_LIST_EMPTY(admin_datums)
|
||||||
GLOBAL_PROTECT(admin_datums)
|
GLOBAL_PROTECT(admin_datums)
|
||||||
|
GLOBAL_LIST_EMPTY(protected_admins)
|
||||||
|
GLOBAL_PROTECT(protected_admins)
|
||||||
|
|
||||||
GLOBAL_VAR_INIT(href_token, GenerateToken())
|
GLOBAL_VAR_INIT(href_token, GenerateToken())
|
||||||
GLOBAL_PROTECT(href_token)
|
GLOBAL_PROTECT(href_token)
|
||||||
@@ -26,7 +28,7 @@ GLOBAL_PROTECT(href_token)
|
|||||||
|
|
||||||
var/deadmined
|
var/deadmined
|
||||||
|
|
||||||
/datum/admins/New(datum/admin_rank/R, ckey, force_active = FALSE)
|
/datum/admins/New(datum/admin_rank/R, ckey, force_active = FALSE, protected)
|
||||||
if(IsAdminAdvancedProcCall())
|
if(IsAdminAdvancedProcCall())
|
||||||
var/msg = " has tried to elevate permissions!"
|
var/msg = " has tried to elevate permissions!"
|
||||||
message_admins("[key_name_admin(usr)][msg]")
|
message_admins("[key_name_admin(usr)][msg]")
|
||||||
@@ -51,6 +53,8 @@ GLOBAL_PROTECT(href_token)
|
|||||||
if(R.rights & R_DEBUG) //grant profile access
|
if(R.rights & R_DEBUG) //grant profile access
|
||||||
world.SetConfig("APP/admin", ckey, "role=admin")
|
world.SetConfig("APP/admin", ckey, "role=admin")
|
||||||
//only admins with +ADMIN start admined
|
//only admins with +ADMIN start admined
|
||||||
|
if(protected)
|
||||||
|
GLOB.protected_admins[target] = src
|
||||||
if (force_active || (R.rights & R_AUTOLOGIN))
|
if (force_active || (R.rights & R_AUTOLOGIN))
|
||||||
activate()
|
activate()
|
||||||
else
|
else
|
||||||
|
|||||||
274
code/modules/admin/permissionedit.dm
Normal file
274
code/modules/admin/permissionedit.dm
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
/client/proc/edit_admin_permissions()
|
||||||
|
set category = "Admin"
|
||||||
|
set name = "Permissions Panel"
|
||||||
|
set desc = "Edit admin permissions"
|
||||||
|
if(!check_rights(R_PERMISSIONS))
|
||||||
|
return
|
||||||
|
usr.client.holder.edit_admin_permissions()
|
||||||
|
|
||||||
|
/datum/admins/proc/edit_admin_permissions()
|
||||||
|
if(!check_rights(R_PERMISSIONS))
|
||||||
|
return
|
||||||
|
|
||||||
|
var/list/output = list({"<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Permissions Panel</title>
|
||||||
|
<script type='text/javascript' src='search.js'></script>
|
||||||
|
<link rel='stylesheet' type='text/css' href='panels.css'>
|
||||||
|
</head>
|
||||||
|
<body onload='selectTextField();updateSearch();'>
|
||||||
|
<div id='main'><table id='searchable' cellspacing='0'>
|
||||||
|
<tr class='title'>
|
||||||
|
<th style='width:150px;text-align:right;'>CKEY <a class='small' href='?src=[REF(src)];[HrefToken()];editrights=add'>\[+\]</a></th>
|
||||||
|
<th style='width:125px;'>RANK</th>
|
||||||
|
<th style='width:40%;'>PERMISSIONS</th>
|
||||||
|
<th style='width:20%;'>DENIED</th>
|
||||||
|
<th style='width:40%;'>ALLOWED TO EDIT</th>
|
||||||
|
</tr>
|
||||||
|
"})
|
||||||
|
|
||||||
|
for(var/adm_ckey in GLOB.admin_datums+GLOB.deadmins)
|
||||||
|
var/datum/admins/D = GLOB.admin_datums[adm_ckey]
|
||||||
|
if(!D)
|
||||||
|
D = GLOB.deadmins[adm_ckey]
|
||||||
|
if (!D)
|
||||||
|
continue
|
||||||
|
|
||||||
|
var/deadminlink = ""
|
||||||
|
if (D.deadmined)
|
||||||
|
deadminlink = " <a class='small' href='?src=[REF(src)];[HrefToken()];editrights=activate;ckey=[adm_ckey]'>\[RA\]</a>"
|
||||||
|
else
|
||||||
|
deadminlink = " <a class='small' href='?src=[REF(src)];[HrefToken()];editrights=deactivate;ckey=[adm_ckey]'>\[DA\]</a>"
|
||||||
|
|
||||||
|
output += "<tr>"
|
||||||
|
output += "<td style='text-align:right;'>[adm_ckey] [deadminlink]<a class='small' href='?src=[REF(src)];[HrefToken()];editrights=remove;ckey=[adm_ckey]'>\[-\]</a></td>"
|
||||||
|
output += "<td><a href='?src=[REF(src)];[HrefToken()];editrights=rank;ckey=[adm_ckey]'>[D.rank.name]</a></td>"
|
||||||
|
output += "<td><a class='small' href='?src=[REF(src)];[HrefToken()];editrights=permissions;ckey=[adm_ckey]'>[rights2text(D.rank.include_rights," ")]</a></td>"
|
||||||
|
output += "<td><a class='small' href='?src=[REF(src)];[HrefToken()];editrights=permissions;ckey=[adm_ckey]'>[rights2text(D.rank.exclude_rights," ", "-")]</a></td>"
|
||||||
|
output += "<td><a class='small' href='?src=[REF(src)];[HrefToken()];editrights=permissions;ckey=[adm_ckey]'>[rights2text(D.rank.can_edit_rights," ", "*")]</a></td>"
|
||||||
|
output += "</tr>"
|
||||||
|
|
||||||
|
output += {"
|
||||||
|
</table></div>
|
||||||
|
<div id='top'><b>Search:</b> <input type='text' id='filter' value='' style='width:70%;' onkeyup='updateSearch();'></div>
|
||||||
|
</body>
|
||||||
|
</html>"}
|
||||||
|
|
||||||
|
usr << browse(jointext(output, ""),"window=editrights;size=1000x650")
|
||||||
|
|
||||||
|
/datum/admins/proc/edit_rights_topic(list/href_list)
|
||||||
|
if(!check_rights(R_PERMISSIONS))
|
||||||
|
message_admins("[key_name_admin(usr)] attempted to edit admin permissions without sufficient rights.")
|
||||||
|
log_admin("[key_name(usr)] attempted to edit admin permissions without sufficient rights.")
|
||||||
|
return
|
||||||
|
if(IsAdminAdvancedProcCall())
|
||||||
|
to_chat(usr, "<span class='admin prefix'>Admin Edit blocked: Advanced ProcCall detected.</span>")
|
||||||
|
return
|
||||||
|
var/datum/asset/permissions_assets = get_asset_datum(/datum/asset/simple/permissions)
|
||||||
|
permissions_assets.send(src)
|
||||||
|
var/admin_ckey = ckey(href_list["ckey"])
|
||||||
|
var/datum/admins/D = GLOB.admin_datums[admin_ckey]
|
||||||
|
var/use_db
|
||||||
|
var/task = href_list["editrights"]
|
||||||
|
var/skip
|
||||||
|
if(task == "activate" || task == "deactivate")
|
||||||
|
skip = 1
|
||||||
|
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_admins) && task == "rank")
|
||||||
|
if(admin_ckey in GLOB.protected_admins)
|
||||||
|
to_chat(usr, "<span class='admin prefix'>Editing the rank of this admin is blocked by server configuration.</span>")
|
||||||
|
return
|
||||||
|
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_ranks) && task == "permissions")
|
||||||
|
if(D.rank in GLOB.protected_ranks)
|
||||||
|
to_chat(usr, "<span class='admin prefix'>Editing the flags of this rank is blocked by server configuration.</span>")
|
||||||
|
return
|
||||||
|
if(check_rights(R_DBRANKS, 0))
|
||||||
|
if(!skip)
|
||||||
|
if(!SSdbcore.Connect())
|
||||||
|
to_chat(usr, "<span class='danger'>Unable to connect to database, changes are temporary only.</span>")
|
||||||
|
use_db = "Temporary"
|
||||||
|
if(!use_db)
|
||||||
|
use_db = alert("Permanent changes are saved to the database for future rounds, temporary changes will affect only the current round", "Permanent or Temporary?", "Permanent", "Temporary", "Cancel")
|
||||||
|
if(use_db == "Cancel")
|
||||||
|
return
|
||||||
|
if(use_db == "Permanent")
|
||||||
|
use_db = 1
|
||||||
|
admin_ckey = sanitizeSQL(admin_ckey)
|
||||||
|
else
|
||||||
|
use_db = 0
|
||||||
|
if(task != "add")
|
||||||
|
D = GLOB.admin_datums[admin_ckey]
|
||||||
|
if(!D)
|
||||||
|
D = GLOB.deadmins[admin_ckey]
|
||||||
|
if(!D)
|
||||||
|
return
|
||||||
|
if(!check_if_greater_rights_than_holder(D))
|
||||||
|
message_admins("[key_name_admin(usr)] attempted to change the rank of [admin_ckey] without sufficient rights.")
|
||||||
|
log_admin("[key_name(usr)] attempted to change the rank of [admin_ckey] without sufficient rights.")
|
||||||
|
switch(task)
|
||||||
|
if("add")
|
||||||
|
admin_ckey = add_admin(use_db)
|
||||||
|
if(!admin_ckey)
|
||||||
|
return
|
||||||
|
change_admin_rank(admin_ckey, use_db)
|
||||||
|
if("remove")
|
||||||
|
remove_admin(admin_ckey, use_db, D)
|
||||||
|
if("rank")
|
||||||
|
change_admin_rank(admin_ckey, use_db, D)
|
||||||
|
if("permissions")
|
||||||
|
change_admin_flags(admin_ckey, use_db, D)
|
||||||
|
if("activate")
|
||||||
|
force_readmin(admin_ckey, D)
|
||||||
|
if("deactivate")
|
||||||
|
force_deadmin(admin_ckey, D)
|
||||||
|
edit_admin_permissions()
|
||||||
|
|
||||||
|
/datum/admins/proc/add_admin(use_db)
|
||||||
|
. = sanitizeSQL(ckey(input("New admin's ckey","Admin ckey") as text|null))
|
||||||
|
if(!.)
|
||||||
|
return 0
|
||||||
|
if(. in GLOB.admin_datums+GLOB.deadmins)
|
||||||
|
to_chat(usr, "<span class='danger'>[.] is already an admin.</span>")
|
||||||
|
return 0
|
||||||
|
if(use_db)
|
||||||
|
var/datum/DBQuery/query_add_admin = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin")] (ckey, rank) VALUES ('[.]', 'NEW ADMIN')")
|
||||||
|
if(!query_add_admin.warn_execute())
|
||||||
|
return 0
|
||||||
|
var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, adminckey, adminip, operation, log) VALUES ('[SQLtime()]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'add admin', 'New admin added: [.]')")
|
||||||
|
if(!query_add_admin_log.warn_execute())
|
||||||
|
return 0
|
||||||
|
|
||||||
|
/datum/admins/proc/remove_admin(admin_ckey, use_db, datum/admins/D)
|
||||||
|
if(alert("Are you sure you want to remove [admin_ckey]?","Confirm Removal","Do it","Cancel") == "Do it")
|
||||||
|
GLOB.admin_datums -= admin_ckey
|
||||||
|
GLOB.deadmins -= admin_ckey
|
||||||
|
D.disassociate()
|
||||||
|
if(use_db)
|
||||||
|
var/datum/DBQuery/query_add_rank = SSdbcore.NewQuery("DELETE FROM [format_table_name("admin")] WHERE ckey = '[admin_ckey]'")
|
||||||
|
if(!query_add_rank.warn_execute())
|
||||||
|
return
|
||||||
|
var/datum/DBQuery/query_add_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, adminckey, adminip, operation, log) VALUES ('[SQLtime()]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'remove admin', 'Admin removed: [admin_ckey]')")
|
||||||
|
if(!query_add_rank_log.warn_execute())
|
||||||
|
return
|
||||||
|
message_admins("[key_name_admin(usr)] removed [admin_ckey] from the admins list [use_db ? "permanently" : "temporarily"]")
|
||||||
|
log_admin("[key_name(usr)] removed [admin_ckey] from the admins list [use_db ? "permanently" : "temporarily"]")
|
||||||
|
|
||||||
|
/datum/admins/proc/force_readmin(admin_ckey, datum/admins/D)
|
||||||
|
if(!D || !D.deadmined)
|
||||||
|
return
|
||||||
|
D.activate()
|
||||||
|
message_admins("[key_name_admin(usr)] forcefully readmined [admin_ckey]")
|
||||||
|
log_admin("[key_name(usr)] forcefully readmined [admin_ckey]")
|
||||||
|
|
||||||
|
/datum/admins/proc/force_deadmin(admin_ckey, datum/admins/D)
|
||||||
|
if(!D || D.deadmined)
|
||||||
|
return
|
||||||
|
message_admins("[key_name_admin(usr)] forcefully deadmined [admin_ckey]")
|
||||||
|
log_admin("[key_name(usr)] forcefully deadmined [admin_ckey]")
|
||||||
|
D.deactivate() //after logs so the deadmined admin can see the message.
|
||||||
|
|
||||||
|
/datum/admins/proc/change_admin_rank(admin_ckey, use_db, datum/admins/D)
|
||||||
|
var/datum/admin_rank/R
|
||||||
|
var/list/rank_names = list("*New Rank*")
|
||||||
|
for(R in GLOB.admin_ranks)
|
||||||
|
if((R.rights & usr.client.holder.rank.can_edit_rights) == R.rights)
|
||||||
|
rank_names[R.name] = R
|
||||||
|
var/new_rank = input("Please select a rank", "New rank") as null|anything in rank_names
|
||||||
|
if(new_rank == "*New Rank*")
|
||||||
|
new_rank = sanitizeSQL(ckeyEx(input("Please input a new rank", "New custom rank") as text|null))
|
||||||
|
if(!new_rank)
|
||||||
|
return
|
||||||
|
R = rank_names[new_rank]
|
||||||
|
if(!R) //rank with that name doesn't exist yet - make it
|
||||||
|
if(D)
|
||||||
|
R = new(new_rank, D.rank.rights) //duplicate our previous admin_rank but with a new name
|
||||||
|
else
|
||||||
|
R = new(new_rank) //blank new admin_rank
|
||||||
|
GLOB.admin_ranks += R
|
||||||
|
if(use_db)
|
||||||
|
if(!R)
|
||||||
|
var/datum/DBQuery/query_add_rank = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_ranks")] (rank, flags, exclude_flags, can_edit_rights) VALUES ('[new_rank]', '0', '0', '0')")
|
||||||
|
if(!query_add_rank.warn_execute())
|
||||||
|
return
|
||||||
|
var/datum/DBQuery/query_add_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, adminckey, adminip, operation, log) VALUES ('[SQLtime()]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'add rank', 'New rank added: [admin_ckey]')")
|
||||||
|
if(!query_add_rank_log.warn_execute())
|
||||||
|
return
|
||||||
|
var/old_rank
|
||||||
|
var/datum/DBQuery/query_get_rank = SSdbcore.NewQuery("SELECT rank FROM [format_table_name("admin")] WHERE ckey = '[admin_ckey]'")
|
||||||
|
if(!query_get_rank.warn_execute())
|
||||||
|
return
|
||||||
|
if(query_get_rank.NextRow())
|
||||||
|
old_rank = query_get_rank.item[1]
|
||||||
|
var/datum/DBQuery/query_change_rank = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE ckey = '[admin_ckey]'")
|
||||||
|
if(!query_change_rank.warn_execute())
|
||||||
|
return
|
||||||
|
var/datum/DBQuery/query_change_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, adminckey, adminip, operation, log) VALUES ('[SQLtime()]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'change admin rank', 'Rank of [admin_ckey] changed from [old_rank] to [new_rank]')")
|
||||||
|
if(!query_change_rank_log.warn_execute())
|
||||||
|
return
|
||||||
|
if(D) //they were previously an admin
|
||||||
|
D.disassociate() //existing admin needs to be disassociated
|
||||||
|
D.rank = R //set the admin_rank as our rank
|
||||||
|
D.associate()
|
||||||
|
else
|
||||||
|
D = new(R, admin_ckey, TRUE) //new admin
|
||||||
|
message_admins("[key_name_admin(usr)] edited the admin rank of [admin_ckey] to [new_rank] [use_db ? "permanently" : "temporarily"]")
|
||||||
|
log_admin("[key_name(usr)] edited the admin rank of [admin_ckey] to [new_rank] [use_db ? "permanently" : "temporarily"]")
|
||||||
|
|
||||||
|
/datum/admins/proc/change_admin_flags(admin_ckey, use_db, datum/admins/D)
|
||||||
|
var/new_flags = input_bitfield(usr, "Include permission flags<br>[use_db ? "This will affect ALL admins with this rank." : "This will affect only the current admin [admin_ckey]"]", "admin_flags", D.rank.include_rights, 350, 590, allowed_edit_list = usr.client.holder.rank.can_edit_rights)
|
||||||
|
if(isnull(new_flags))
|
||||||
|
return
|
||||||
|
var/new_exclude_flags = input_bitfield(usr, "Exclude permission flags<br>Flags enabled here will be removed from a rank.<br>Note these take precedence over included flags.<br>[use_db ? "This will affect ALL admins with this rank." : "This will affect only the current admin [admin_ckey]"]", "admin_flags", D.rank.exclude_rights, 350, 660, "red", usr.client.holder.rank.can_edit_rights)
|
||||||
|
if(isnull(new_exclude_flags))
|
||||||
|
return
|
||||||
|
var/new_can_edit_flags = input_bitfield(usr, "Editable permission flags<br>These are the flags this rank is allowed to edit if they have access to the permissions panel.<br>They will be unable to modify admins to a rank that has a flag not included here.<br>[use_db ? "This will affect ALL admins with this rank." : "This will affect only the current admin [admin_ckey]"]", "admin_flags", D.rank.can_edit_rights, 350, 710, allowed_edit_list = usr.client.holder.rank.can_edit_rights)
|
||||||
|
if(isnull(new_can_edit_flags))
|
||||||
|
return
|
||||||
|
if(use_db)
|
||||||
|
var/old_flags
|
||||||
|
var/old_exclude_flags
|
||||||
|
var/old_can_edit_flags
|
||||||
|
var/datum/DBQuery/query_get_rank_flags = SSdbcore.NewQuery("SELECT flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] WHERE rank = '[D.rank.name]'")
|
||||||
|
if(!query_get_rank_flags.warn_execute())
|
||||||
|
return
|
||||||
|
if(query_get_rank_flags.NextRow())
|
||||||
|
old_flags = text2num(query_get_rank_flags.item[1])
|
||||||
|
old_exclude_flags = text2num(query_get_rank_flags.item[2])
|
||||||
|
old_can_edit_flags = text2num(query_get_rank_flags.item[3])
|
||||||
|
var/datum/DBQuery/query_change_rank_flags = SSdbcore.NewQuery("UPDATE [format_table_name("admin_ranks")] SET flags = '[new_flags]', exclude_flags = '[new_exclude_flags]', can_edit_flags = '[new_can_edit_flags]' WHERE rank = '[D.rank.name]'")
|
||||||
|
if(!query_change_rank_flags.warn_execute())
|
||||||
|
return
|
||||||
|
var/datum/DBQuery/query_change_rank_flags_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, adminckey, adminip, operation, log) VALUES ('[SQLtime()]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'change rank flags', 'Permissions of [admin_ckey] changed from[rights2text(old_flags," ")][rights2text(old_exclude_flags," ", "-")][rights2text(old_can_edit_flags," ", "*")] to[rights2text(new_flags," ")][rights2text(new_exclude_flags," ", "-")][rights2text(new_can_edit_flags," ", "*")]')")
|
||||||
|
if(!query_change_rank_flags_log.warn_execute())
|
||||||
|
return
|
||||||
|
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||||
|
if(R.name != D.rank.name)
|
||||||
|
continue
|
||||||
|
R.rights = new_flags &= ~new_exclude_flags
|
||||||
|
R.exclude_rights = new_exclude_flags
|
||||||
|
R.include_rights = new_flags
|
||||||
|
R.can_edit_rights = new_can_edit_flags
|
||||||
|
for(var/i in GLOB.admin_datums+GLOB.deadmins)
|
||||||
|
var/datum/admins/A = GLOB.admin_datums[i]
|
||||||
|
if(!A)
|
||||||
|
A = GLOB.deadmins[i]
|
||||||
|
if (!A)
|
||||||
|
continue
|
||||||
|
if(A.rank.name != D.rank.name)
|
||||||
|
continue
|
||||||
|
var/client/C = GLOB.directory[A.target]
|
||||||
|
A.disassociate()
|
||||||
|
A.associate(C)
|
||||||
|
else
|
||||||
|
D.disassociate()
|
||||||
|
if(!findtext(D.rank.name, "([admin_ckey])")) //not a modified subrank, need to duplicate the admin_rank datum to prevent modifying others too
|
||||||
|
D.rank = new("[D.rank.name]([admin_ckey])", new_flags, new_exclude_flags, new_can_edit_flags) //duplicate our previous admin_rank but with a new name
|
||||||
|
//we don't add this clone to the admin_ranks list, as it is unique to that ckey
|
||||||
|
else
|
||||||
|
D.rank.rights = new_flags &= ~new_exclude_flags
|
||||||
|
D.rank.include_rights = new_flags
|
||||||
|
D.rank.exclude_rights = new_exclude_flags
|
||||||
|
var/client/C = GLOB.directory[admin_ckey] //find the client with the specified ckey (if they are logged in)
|
||||||
|
D.associate(C) //link up with the client and add verbs
|
||||||
|
message_admins("[key_name_admin(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_ckey] temporarily"]")
|
||||||
|
log_admin("[key_name(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_ckey] temporarily"]")
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=tdomereset'>Reset Thunderdome to default state</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=tdomereset'>Reset Thunderdome to default state</A><BR>
|
||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=set_name'>Rename Station Name</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=set_name'>Rename Station Name</A><BR>
|
||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=reset_name'>Reset Station Name</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=reset_name'>Reset Station Name</A><BR>
|
||||||
|
<A href='?src=[REF(src)];[HrefToken()];secrets=night_shift_set'>Set Night Shift Mode</A><BR>
|
||||||
<BR>
|
<BR>
|
||||||
<B>Shuttles</B><BR>
|
<B>Shuttles</B><BR>
|
||||||
<BR>
|
<BR>
|
||||||
@@ -54,7 +55,6 @@
|
|||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=quickpower'>Power all SMES</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=quickpower'>Power all SMES</A><BR>
|
||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=tripleAI'>Triple AI mode (needs to be used in the lobby)</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=tripleAI'>Triple AI mode (needs to be used in the lobby)</A><BR>
|
||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=traitor_all'>Everyone is the traitor</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=traitor_all'>Everyone is the traitor</A><BR>
|
||||||
<A href='?src=\ref[src];[HrefToken()];secrets=ak47s'>AK-47s For Everyone!</A><BR>
|
|
||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=guns'>Summon Guns</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=guns'>Summon Guns</A><BR>
|
||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=magic'>Summon Magic</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=magic'>Summon Magic</A><BR>
|
||||||
<A href='?src=[REF(src)];[HrefToken()];secrets=events'>Summon Events (Toggle)</A><BR>
|
<A href='?src=[REF(src)];[HrefToken()];secrets=events'>Summon Events (Toggle)</A><BR>
|
||||||
@@ -107,8 +107,6 @@
|
|||||||
dat += "No-one has done anything this round!"
|
dat += "No-one has done anything this round!"
|
||||||
usr << browse(dat, "window=admin_log")
|
usr << browse(dat, "window=admin_log")
|
||||||
|
|
||||||
if("mentor_log")
|
|
||||||
CitadelMentorLogSecret()
|
|
||||||
if("list_job_debug")
|
if("list_job_debug")
|
||||||
var/dat = "<B>Job Debug info.</B><HR>"
|
var/dat = "<B>Job Debug info.</B><HR>"
|
||||||
for(var/line in SSjob.job_debug)
|
for(var/line in SSjob.job_debug)
|
||||||
@@ -167,6 +165,23 @@
|
|||||||
log_admin("[key_name(usr)] renamed the station to \"[new_name]\".")
|
log_admin("[key_name(usr)] renamed the station to \"[new_name]\".")
|
||||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] renamed the station to: [new_name].</span>")
|
message_admins("<span class='adminnotice'>[key_name_admin(usr)] renamed the station to: [new_name].</span>")
|
||||||
priority_announce("[command_name()] has renamed the station to \"[new_name]\".")
|
priority_announce("[command_name()] has renamed the station to \"[new_name]\".")
|
||||||
|
if("night_shift_set")
|
||||||
|
if(!check_rights(R_ADMIN))
|
||||||
|
return
|
||||||
|
var/val = alert(usr, "What do you want to set night shift to? This will override the automatic system until set to automatic again.", "On", "Off", "Automatic")
|
||||||
|
switch(val)
|
||||||
|
if("Automatic")
|
||||||
|
if(CONFIG_GET(flag/enable_night_shifts))
|
||||||
|
SSnightshift.can_fire = TRUE
|
||||||
|
SSnightshift.fire()
|
||||||
|
else
|
||||||
|
SSnightshift.update_nightshift(FALSE, TRUE)
|
||||||
|
if("On")
|
||||||
|
SSnightshift.can_fire = FALSE
|
||||||
|
SSnightshift.update_nightshift(TRUE, TRUE)
|
||||||
|
if("Off")
|
||||||
|
SSnightshift.can_fire = FALSE
|
||||||
|
SSnightshift.update_nightshift(FALSE, TRUE)
|
||||||
|
|
||||||
if("reset_name")
|
if("reset_name")
|
||||||
if(!check_rights(R_ADMIN))
|
if(!check_rights(R_ADMIN))
|
||||||
@@ -460,13 +475,6 @@
|
|||||||
message_admins("[key_name_admin(usr)] activated Egalitarian Station mode")
|
message_admins("[key_name_admin(usr)] activated Egalitarian Station mode")
|
||||||
priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, 'sound/ai/commandreport.ogg')
|
priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, 'sound/ai/commandreport.ogg')
|
||||||
|
|
||||||
if("ak47s")
|
|
||||||
if(!check_rights(R_FUN))
|
|
||||||
return
|
|
||||||
message_admins("[key_name_admin(usr)] activated AK-47s for Everyone!")
|
|
||||||
usr.client.ak47s()
|
|
||||||
sound_to_playing_players('sound/misc/ak47s.ogg')
|
|
||||||
|
|
||||||
if("guns")
|
if("guns")
|
||||||
if(!check_rights(R_FUN))
|
if(!check_rights(R_FUN))
|
||||||
return
|
return
|
||||||
@@ -613,13 +621,13 @@
|
|||||||
var/list/new_movement = list()
|
var/list/new_movement = list()
|
||||||
for(var/i in 1 to movement_keys.len)
|
for(var/i in 1 to movement_keys.len)
|
||||||
var/key = movement_keys[i]
|
var/key = movement_keys[i]
|
||||||
|
|
||||||
var/msg = "Please input the new movement direction when the user presses [key]. Ex. northeast"
|
var/msg = "Please input the new movement direction when the user presses [key]. Ex. northeast"
|
||||||
var/title = "New direction for [key]"
|
var/title = "New direction for [key]"
|
||||||
var/new_direction = text2dir(input(usr, msg, title) as text|null)
|
var/new_direction = text2dir(input(usr, msg, title) as text|null)
|
||||||
if(!new_direction)
|
if(!new_direction)
|
||||||
new_direction = movement_keys[key]
|
new_direction = movement_keys[key]
|
||||||
|
|
||||||
new_movement[key] = new_direction
|
new_movement[key] = new_direction
|
||||||
SSinput.movement_keys = new_movement
|
SSinput.movement_keys = new_movement
|
||||||
message_admins("[key_name_admin(usr)] has configured all movement directions.")
|
message_admins("[key_name_admin(usr)] has configured all movement directions.")
|
||||||
|
|||||||
@@ -271,50 +271,6 @@
|
|||||||
return
|
return
|
||||||
create_message("note", banckey, null, banreason, null, null, 0, 0)
|
create_message("note", banckey, null, banreason, null, null, 0, 0)
|
||||||
|
|
||||||
else if(href_list["mentor"])
|
|
||||||
if(!check_rights(R_ADMIN)) return
|
|
||||||
|
|
||||||
var/mob/M = locate(href_list["mentor"])
|
|
||||||
if(!ismob(M))
|
|
||||||
to_chat(usr, "<span class='danger'>this can be only used on instances of type /mob!</span>")
|
|
||||||
return
|
|
||||||
|
|
||||||
if(!M.client)
|
|
||||||
to_chat(usr, "<span class='danger'>No client.</span>")
|
|
||||||
return
|
|
||||||
|
|
||||||
log_admin("[key_name(usr)] has granted [key_name(M)] mentor access")
|
|
||||||
message_admins("<span class='adminnotice'> [key_name_admin(usr)] has granted [key_name_admin(M)] mentor access.</span>")
|
|
||||||
|
|
||||||
var/datum/DBQuery/query_add_mentors = SSdbcore.NewQuery("INSERT INTO [format_table_name("mentor")] (ckey) VALUES ('[M.client.ckey]')")
|
|
||||||
if(!query_add_mentors.Execute())
|
|
||||||
var/err = query_add_mentors.ErrorMsg()
|
|
||||||
log_game("SQL ERROR during adding new mentor. Error : \[[err]\]\n")
|
|
||||||
load_mentors()
|
|
||||||
M.verbs += /client/proc/cmd_mentor_say
|
|
||||||
M.verbs += /client/proc/show_mentor_memo
|
|
||||||
to_chat(M, "<span class='adminnotice'> You've been granted mentor access! Help people who send mentor-pms.</span>")
|
|
||||||
|
|
||||||
else if(href_list["removementor"])
|
|
||||||
if(!check_rights(R_ADMIN)) return
|
|
||||||
|
|
||||||
var/mob/living/carbon/human/M = locate(href_list["removementor"])
|
|
||||||
if(!ismob(M))
|
|
||||||
usr << "this can be only used on instances of type /mob"
|
|
||||||
return
|
|
||||||
|
|
||||||
log_admin("[key_name(usr)] has removed mentor access from [key_name(M)]")
|
|
||||||
message_admins("<span class='adminnotice'> [key_name_admin(usr)] has removed mentor access from [key_name_admin(M)].</span>")
|
|
||||||
|
|
||||||
var/datum/DBQuery/query_remove_mentors = SSdbcore.NewQuery("DELETE FROM [format_table_name("mentor")] WHERE ckey = '[M.client.ckey]'")
|
|
||||||
if(!query_remove_mentors.Execute())
|
|
||||||
var/err = query_remove_mentors.ErrorMsg()
|
|
||||||
log_game("SQL ERROR during removing mentor. Error : \[[err]\]\n")
|
|
||||||
load_mentors()
|
|
||||||
to_chat(M, "<span class='adminnotice'>Your mentor access has been revoked.</span>")
|
|
||||||
M.verbs -= /client/proc/cmd_mentor_say
|
|
||||||
M.verbs -= /client/proc/show_mentor_memo
|
|
||||||
|
|
||||||
else if(href_list["editrights"])
|
else if(href_list["editrights"])
|
||||||
edit_rights_topic(href_list)
|
edit_rights_topic(href_list)
|
||||||
|
|
||||||
@@ -916,12 +872,6 @@
|
|||||||
else
|
else
|
||||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=abductor;jobban4=[REF(M)]'>Abductor</a></td>"
|
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=abductor;jobban4=[REF(M)]'>Abductor</a></td>"
|
||||||
|
|
||||||
//Borer
|
|
||||||
if(jobban_isbanned(M, "borer") || isbanned_dept)
|
|
||||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=borer;jobban4=[REF(M)]'><font color=red>Borer</font></a></td>"
|
|
||||||
else
|
|
||||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=borer;jobban4=[REF(M)]'>Borer</a></td>"
|
|
||||||
|
|
||||||
//Alien
|
//Alien
|
||||||
if(jobban_isbanned(M, ROLE_ALIEN) || isbanned_dept)
|
if(jobban_isbanned(M, ROLE_ALIEN) || isbanned_dept)
|
||||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=alien;jobban4=[REF(M)]'><font color=red>Alien</font></a></td>"
|
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=alien;jobban4=[REF(M)]'><font color=red>Alien</font></a></td>"
|
||||||
@@ -1709,7 +1659,7 @@
|
|||||||
var/mob/living/L = M
|
var/mob/living/L = M
|
||||||
var/status
|
var/status
|
||||||
switch (M.stat)
|
switch (M.stat)
|
||||||
if (CONSCIOUS)
|
if(CONSCIOUS)
|
||||||
status = "Alive"
|
status = "Alive"
|
||||||
if(SOFT_CRIT)
|
if(SOFT_CRIT)
|
||||||
status = "<font color='orange'><b>Dying</b></font>"
|
status = "<font color='orange'><b>Dying</b></font>"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
admin_sound.status = SOUND_STREAM
|
admin_sound.status = SOUND_STREAM
|
||||||
admin_sound.volume = vol
|
admin_sound.volume = vol
|
||||||
|
|
||||||
var/res = alert(usr, "Show the title of this song to the players?",, "No", "Yes", "Cancel")
|
var/res = alert(usr, "Show the title of this song to the players?",, "Yes","No", "Cancel")
|
||||||
switch(res)
|
switch(res)
|
||||||
if("Yes")
|
if("Yes")
|
||||||
to_chat(world, "<span class='boldannounce'>An admin played: [S]</span>")
|
to_chat(world, "<span class='boldannounce'>An admin played: [S]</span>")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
//Admin-spawn or random event
|
//Admin-spawn or random event
|
||||||
|
|
||||||
#define INVISIBILITY_REVENANT 50
|
#define INVISIBILITY_REVENANT 50
|
||||||
|
#define REVENANT_NAME_FILE "revenant_names.json"
|
||||||
|
|
||||||
/mob/living/simple_animal/revenant
|
/mob/living/simple_animal/revenant
|
||||||
name = "\a Revenant"
|
name = "\a Revenant"
|
||||||
@@ -70,6 +71,15 @@
|
|||||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/overload(null))
|
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/overload(null))
|
||||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/blight(null))
|
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/blight(null))
|
||||||
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/malfunction(null))
|
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/malfunction(null))
|
||||||
|
random_revenant_name()
|
||||||
|
|
||||||
|
/mob/living/simple_animal/revenant/proc/random_revenant_name()
|
||||||
|
var/built_name = ""
|
||||||
|
built_name += pick(strings(REVENANT_NAME_FILE, "spirit_type"))
|
||||||
|
built_name += " of "
|
||||||
|
built_name += pick(strings(REVENANT_NAME_FILE, "adverb"))
|
||||||
|
built_name += pick(strings(REVENANT_NAME_FILE, "theme"))
|
||||||
|
name = built_name
|
||||||
|
|
||||||
/mob/living/simple_animal/revenant/Login()
|
/mob/living/simple_animal/revenant/Login()
|
||||||
..()
|
..()
|
||||||
|
|||||||
@@ -98,11 +98,11 @@
|
|||||||
var/list/new_overlay_types = tile_graphic()
|
var/list/new_overlay_types = tile_graphic()
|
||||||
var/list/atmos_overlay_types = src.atmos_overlay_types // Cache for free performance
|
var/list/atmos_overlay_types = src.atmos_overlay_types // Cache for free performance
|
||||||
|
|
||||||
/*#if DM_VERSION >= 513
|
#if DM_VERSION >= 513
|
||||||
#warning 512 is stable now for sure, remove the old code
|
#warning 512 is stable now for sure, remove the old code
|
||||||
#endif*/
|
#endif
|
||||||
|
|
||||||
/*#if DM_VERSION >= 512
|
#if DM_VERSION >= 512
|
||||||
if (atmos_overlay_types)
|
if (atmos_overlay_types)
|
||||||
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
|
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
|
||||||
vars["vis_contents"] -= overlay
|
vars["vis_contents"] -= overlay
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
vars["vis_contents"] += new_overlay_types - atmos_overlay_types //don't add overlays that already exist
|
vars["vis_contents"] += new_overlay_types - atmos_overlay_types //don't add overlays that already exist
|
||||||
else
|
else
|
||||||
vars["vis_contents"] += new_overlay_types
|
vars["vis_contents"] += new_overlay_types
|
||||||
#else*/
|
#else
|
||||||
if (atmos_overlay_types)
|
if (atmos_overlay_types)
|
||||||
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
|
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
|
||||||
cut_overlay(overlay)
|
cut_overlay(overlay)
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
add_overlay(new_overlay_types - atmos_overlay_types) //don't add overlays that already exist
|
add_overlay(new_overlay_types - atmos_overlay_types) //don't add overlays that already exist
|
||||||
else
|
else
|
||||||
add_overlay(new_overlay_types)
|
add_overlay(new_overlay_types)
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
UNSETEMPTY(new_overlay_types)
|
UNSETEMPTY(new_overlay_types)
|
||||||
src.atmos_overlay_types = new_overlay_types
|
src.atmos_overlay_types = new_overlay_types
|
||||||
|
|||||||
@@ -57,11 +57,6 @@ It's like a regular ol' straight pipe, but you can turn it on and off.
|
|||||||
close()
|
close()
|
||||||
return
|
return
|
||||||
open()
|
open()
|
||||||
var/turf/T = get_turf(src)
|
|
||||||
var/area/A = get_area(src)
|
|
||||||
investigate_log("Valve, [src.name], was manipiulated by [key_name(usr)] at [x], [y], [z], [A]", "atmos")
|
|
||||||
message_admins("Valve, [src.name], was manipulated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(T)], [A]")
|
|
||||||
|
|
||||||
|
|
||||||
/obj/machinery/atmospherics/components/binary/valve/digital // can be controlled by AI
|
/obj/machinery/atmospherics/components/binary/valve/digital // can be controlled by AI
|
||||||
name = "digital valve"
|
name = "digital valve"
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
continue // i'd be right happy to
|
continue // i'd be right happy to
|
||||||
meme_pack_data[P.group]["packs"] += list(list(
|
meme_pack_data[P.group]["packs"] += list(list(
|
||||||
"name" = P.name,
|
"name" = P.name,
|
||||||
"cost" = P.cost * 2, //displays twice the normal cost
|
"cost" = P.cost,
|
||||||
"id" = pack
|
"id" = pack
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -120,12 +120,12 @@
|
|||||||
CHECK_TICK
|
CHECK_TICK
|
||||||
if(empty_turfs && empty_turfs.len)
|
if(empty_turfs && empty_turfs.len)
|
||||||
var/LZ = empty_turfs[rand(empty_turfs.len-1)]
|
var/LZ = empty_turfs[rand(empty_turfs.len-1)]
|
||||||
SSshuttle.points -= SO.pack.cost * 2
|
SSshuttle.points -= SO.pack.cost
|
||||||
new /obj/effect/DPtarget(LZ, SO, podID)
|
new /obj/effect/DPtarget(LZ, SO, podID)
|
||||||
. = TRUE
|
. = TRUE
|
||||||
update_icon()
|
update_icon()
|
||||||
else
|
else
|
||||||
if(SO.pack.cost * (1.2*MAX_EMAG_ROCKETS) <= SSshuttle.points) // bulk discount :^)
|
if(SO.pack.cost * (0.72*MAX_EMAG_ROCKETS) <= SSshuttle.points) // bulk discount :^)
|
||||||
landingzone = locate(pick(GLOB.the_station_areas)) in GLOB.sortedAreas
|
landingzone = locate(pick(GLOB.the_station_areas)) in GLOB.sortedAreas
|
||||||
for(var/turf/open/floor/T in landingzone.contents)
|
for(var/turf/open/floor/T in landingzone.contents)
|
||||||
if(is_blocked_turf(T))
|
if(is_blocked_turf(T))
|
||||||
|
|||||||
@@ -988,8 +988,9 @@
|
|||||||
/obj/item/reagent_containers/pill/insulin,
|
/obj/item/reagent_containers/pill/insulin,
|
||||||
/obj/item/stack/medical/gauze,
|
/obj/item/stack/medical/gauze,
|
||||||
/obj/item/storage/box/beakers,
|
/obj/item/storage/box/beakers,
|
||||||
|
/obj/item/storage/box/medsprays,
|
||||||
/obj/item/storage/box/syringes,
|
/obj/item/storage/box/syringes,
|
||||||
/obj/item/storage/box/bodybags)
|
/obj/item/storage/box/bodybags)
|
||||||
crate_name = "medical supplies crate"
|
crate_name = "medical supplies crate"
|
||||||
|
|
||||||
/datum/supply_pack/medical/vending
|
/datum/supply_pack/medical/vending
|
||||||
@@ -1983,4 +1984,4 @@
|
|||||||
/obj/item/toy/redbutton,
|
/obj/item/toy/redbutton,
|
||||||
/obj/item/toy/eightball,
|
/obj/item/toy/eightball,
|
||||||
/obj/item/vending_refill/donksoft)
|
/obj/item/vending_refill/donksoft)
|
||||||
crate_name = "toy crate"
|
crate_name = "toy crate"
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
|
|||||||
if(!verify) // Can't access the asset cache browser, rip.
|
if(!verify) // Can't access the asset cache browser, rip.
|
||||||
client.cache += unreceived
|
client.cache += unreceived
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
client.sending |= unreceived
|
client.sending |= unreceived
|
||||||
var/job = ++client.last_asset_job
|
var/job = ++client.last_asset_job
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
|
|||||||
else
|
else
|
||||||
concurrent_tracker++
|
concurrent_tracker++
|
||||||
send_asset(client, file, verify=FALSE)
|
send_asset(client, file, verify=FALSE)
|
||||||
|
|
||||||
stoplag(0) //queuing calls like this too quickly can cause issues in some client versions
|
stoplag(0) //queuing calls like this too quickly can cause issues in some client versions
|
||||||
|
|
||||||
//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up.
|
//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up.
|
||||||
@@ -350,6 +350,11 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
|||||||
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
|
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/datum/asset/simple/permissions
|
||||||
|
assets = list(
|
||||||
|
"padlock.png" = 'html/padlock.png'
|
||||||
|
)
|
||||||
|
|
||||||
//this exists purely to avoid meta by pre-loading all language icons.
|
//this exists purely to avoid meta by pre-loading all language icons.
|
||||||
/datum/asset/language/register()
|
/datum/asset/language/register()
|
||||||
for(var/path in typesof(/datum/language))
|
for(var/path in typesof(/datum/language))
|
||||||
|
|||||||
@@ -88,22 +88,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
|||||||
cmd_admin_pm(href_list["priv_msg"],null)
|
cmd_admin_pm(href_list["priv_msg"],null)
|
||||||
return
|
return
|
||||||
|
|
||||||
// Mentor PM
|
|
||||||
if(href_list["mentor_msg"])
|
|
||||||
if(CONFIG_GET(flag.mentors_mobname_only))
|
|
||||||
var/mob/M = locate(href_list["mentor_msg"])
|
|
||||||
cmd_mentor_pm(M,null)
|
|
||||||
else
|
|
||||||
cmd_mentor_pm(href_list["mentor_msg"],null)
|
|
||||||
return
|
|
||||||
|
|
||||||
switch(href_list["_src_"])
|
switch(href_list["_src_"])
|
||||||
if("holder")
|
if("holder")
|
||||||
hsrc = holder
|
hsrc = holder
|
||||||
if("usr")
|
if("usr")
|
||||||
hsrc = mob
|
hsrc = mob
|
||||||
if("mentor") // CITADEL
|
|
||||||
hsrc = mentor_datum // CITADEL END
|
|
||||||
if("prefs")
|
if("prefs")
|
||||||
if (inprefs)
|
if (inprefs)
|
||||||
return
|
return
|
||||||
@@ -239,16 +228,23 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
|||||||
|
|
||||||
. = ..() //calls mob.Login()
|
. = ..() //calls mob.Login()
|
||||||
#if DM_VERSION >= 512
|
#if DM_VERSION >= 512
|
||||||
if (num2text(byond_build) in GLOB.blacklisted_builds)
|
if (byond_version >= 512)
|
||||||
log_access("Failed login: blacklisted byond version")
|
if (!byond_build || byond_build < 1386)
|
||||||
to_chat(src, "<span class='userdanger'>Your version of byond is blacklisted.</span>")
|
message_admins("<span class='adminnotice'>[key_name(src)] has been detected as spoofing their byond version. Connection rejected.</span>")
|
||||||
to_chat(src, "<span class='danger'>Byond build [byond_build] ([byond_version].[byond_build]) has been blacklisted for the following reason: [GLOB.blacklisted_builds[num2text(byond_build)]].</span>")
|
add_system_note("Spoofed-Byond-Version", "Detected as using a spoofed byond version.")
|
||||||
to_chat(src, "<span class='danger'>Please download a new version of byond. if [byond_build] is the latest, you can go to http://www.byond.com/download/build/ to download other versions.</span>")
|
log_access("Failed Login: [key] - Spoofed byond version")
|
||||||
if(connecting_admin)
|
|
||||||
to_chat(src, "As an admin, you are being allowed to continue using this version, but please consider changing byond versions")
|
|
||||||
else
|
|
||||||
qdel(src)
|
qdel(src)
|
||||||
return
|
|
||||||
|
if (num2text(byond_build) in GLOB.blacklisted_builds)
|
||||||
|
log_access("Failed login: [key] - blacklisted byond version")
|
||||||
|
to_chat(src, "<span class='userdanger'>Your version of byond is blacklisted.</span>")
|
||||||
|
to_chat(src, "<span class='danger'>Byond build [byond_build] ([byond_version].[byond_build]) has been blacklisted for the following reason: [GLOB.blacklisted_builds[num2text(byond_build)]].</span>")
|
||||||
|
to_chat(src, "<span class='danger'>Please download a new version of byond. if [byond_build] is the latest, you can go to http://www.byond.com/download/build/ to download other versions.</span>")
|
||||||
|
if(connecting_admin)
|
||||||
|
to_chat(src, "As an admin, you are being allowed to continue using this version, but please consider changing byond versions")
|
||||||
|
else
|
||||||
|
qdel(src)
|
||||||
|
return
|
||||||
#endif
|
#endif
|
||||||
if(SSinput.initialized)
|
if(SSinput.initialized)
|
||||||
set_macros()
|
set_macros()
|
||||||
@@ -380,8 +376,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
|||||||
if (menuitem)
|
if (menuitem)
|
||||||
menuitem.Load_checked(src)
|
menuitem.Load_checked(src)
|
||||||
|
|
||||||
hook_vr("client_new",list(src)) // CIT CHANGE - hook for client/New() changes
|
|
||||||
|
|
||||||
Master.UpdateTickRate()
|
Master.UpdateTickRate()
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
@@ -409,21 +403,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
|||||||
"Someone come hold me :(",\
|
"Someone come hold me :(",\
|
||||||
"I need someone on me :(",\
|
"I need someone on me :(",\
|
||||||
"What happened? Where has everyone gone?",\
|
"What happened? Where has everyone gone?",\
|
||||||
"Forever alone :(",\
|
"Forever alone :("\
|
||||||
"My nipples are so stiff, but Zelda ain't here. :(",\
|
|
||||||
"Leon senpai, play more Spessmans. :(",\
|
|
||||||
"If only Serdy were here...",\
|
|
||||||
"Panic bunker can't keep my love for you out.",\
|
|
||||||
"Cebu needs to Awoo herself back into my heart.",\
|
|
||||||
"I don't even have a Turry to snuggle viciously here.",\
|
|
||||||
"MOM, WHERE ARE YOU??? D:",\
|
|
||||||
"It's a beautiful day outside. Birds are singing, flowers are blooming. On days like this...kids like you...SHOULD BE BURNING IN HELL.",\
|
|
||||||
"Sometimes when I have sex, I think about putting an entire peanut butter and jelly sandwich in the VCR.",\
|
|
||||||
"Oh good, no-one around to watch me lick Goofball's nipples. :D",\
|
|
||||||
"I've replaced Beepsky with a fidget spinner, glory be autism abuse.",\
|
|
||||||
"i shure hop dere are no PRED arund!!!!",\
|
|
||||||
"NO PRED CAN eVER CATCH MI",\
|
|
||||||
"help, the clown is honking his horn in front of dorms and its interrupting everyones erp"\
|
|
||||||
)
|
)
|
||||||
|
|
||||||
send2irc("Server", "[cheesy_message] (No admins online)")
|
send2irc("Server", "[cheesy_message] (No admins online)")
|
||||||
@@ -623,10 +603,13 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
|||||||
to_chat(src, {"<a href="byond://[url]?token=[token]">You will be automatically taken to the game, if not, click here to be taken manually</a>"})
|
to_chat(src, {"<a href="byond://[url]?token=[token]">You will be automatically taken to the game, if not, click here to be taken manually</a>"})
|
||||||
|
|
||||||
/client/proc/note_randomizer_user()
|
/client/proc/note_randomizer_user()
|
||||||
var/const/adminckey = "CID-Error"
|
add_system_note("CID-Error", "Detected as using a cid randomizer.")
|
||||||
|
|
||||||
|
/client/proc/add_system_note(system_ckey, message)
|
||||||
|
var/sql_system_ckey = sanitizeSQL(system_ckey)
|
||||||
var/sql_ckey = sanitizeSQL(ckey)
|
var/sql_ckey = sanitizeSQL(ckey)
|
||||||
//check to see if we noted them in the last day.
|
//check to see if we noted them in the last day.
|
||||||
var/datum/DBQuery/query_get_notes = SSdbcore.NewQuery("SELECT id FROM [format_table_name("messages")] WHERE type = 'note' AND targetckey = '[sql_ckey]' AND adminckey = '[adminckey]' AND timestamp + INTERVAL 1 DAY < NOW() AND deleted = 0")
|
var/datum/DBQuery/query_get_notes = SSdbcore.NewQuery("SELECT id FROM [format_table_name("messages")] WHERE type = 'note' AND targetckey = '[sql_ckey]' AND adminckey = '[sql_system_ckey]' AND timestamp + INTERVAL 1 DAY < NOW() AND deleted = 0")
|
||||||
if(!query_get_notes.Execute())
|
if(!query_get_notes.Execute())
|
||||||
return
|
return
|
||||||
if(query_get_notes.NextRow())
|
if(query_get_notes.NextRow())
|
||||||
@@ -636,9 +619,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
|||||||
if(!query_get_notes.Execute())
|
if(!query_get_notes.Execute())
|
||||||
return
|
return
|
||||||
if(query_get_notes.NextRow())
|
if(query_get_notes.NextRow())
|
||||||
if (query_get_notes.item[1] == adminckey)
|
if (query_get_notes.item[1] == system_ckey)
|
||||||
return
|
return
|
||||||
create_message("note", sql_ckey, adminckey, "Detected as using a cid randomizer.", null, null, 0, 0)
|
create_message("note", ckey, system_ckey, message, null, null, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
/client/proc/check_ip_intel()
|
/client/proc/check_ip_intel()
|
||||||
@@ -730,12 +713,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
|||||||
if (isnull(new_size))
|
if (isnull(new_size))
|
||||||
CRASH("change_view called without argument.")
|
CRASH("change_view called without argument.")
|
||||||
|
|
||||||
//CIT CHANGES START HERE - makes change_view change DEFAULT_VIEW to 15x15 depending on preferences
|
|
||||||
if(prefs && CONFIG_GET(string/default_view))
|
|
||||||
if(!prefs.widescreenpref && new_size == CONFIG_GET(string/default_view))
|
|
||||||
new_size = "15x15"
|
|
||||||
//END OF CIT CHANGES
|
|
||||||
|
|
||||||
view = new_size
|
view = new_size
|
||||||
apply_clickcatcher()
|
apply_clickcatcher()
|
||||||
if (isliving(mob))
|
if (isliving(mob))
|
||||||
@@ -754,4 +731,4 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
|||||||
|
|
||||||
/client/proc/AnnouncePR(announcement)
|
/client/proc/AnnouncePR(announcement)
|
||||||
if(prefs && prefs.chat_toggles & CHAT_PULLR)
|
if(prefs && prefs.chat_toggles & CHAT_PULLR)
|
||||||
to_chat(src, announcement)
|
to_chat(src, announcement)
|
||||||
|
|||||||
@@ -250,20 +250,6 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings, listen_ooc)()
|
|||||||
/datum/verbs/menu/Settings/listen_ooc/Get_checked(client/C)
|
/datum/verbs/menu/Settings/listen_ooc/Get_checked(client/C)
|
||||||
return C.prefs.chat_toggles & CHAT_OOC
|
return C.prefs.chat_toggles & CHAT_OOC
|
||||||
|
|
||||||
TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, togglehoundsleeper)()
|
|
||||||
set name = "Allow/Deny Hound Sleeper"
|
|
||||||
set category = "Preferences"
|
|
||||||
set desc = "Allow MediHound Sleepers"
|
|
||||||
usr.client.prefs.toggles ^= MEDIHOUND_SLEEPER
|
|
||||||
usr.client.prefs.save_preferences()
|
|
||||||
if(usr.client.prefs.toggles & MEDIHOUND_SLEEPER)
|
|
||||||
to_chat(usr, "You will now allow MediHounds to place you in their sleeper.")
|
|
||||||
else
|
|
||||||
to_chat(usr, "You will no longer allow MediHounds to place you in their sleeper.")
|
|
||||||
SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle MediHound Sleeper", "[usr.client.prefs.toggles & MEDIHOUND_SLEEPER ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
|
||||||
/datum/verbs/menu/Settings/Sound/togglehoundsleeper/Get_checked(client/C)
|
|
||||||
return C.prefs.toggles & MEDIHOUND_SLEEPER
|
|
||||||
|
|
||||||
|
|
||||||
GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
|
GLOBAL_LIST_INIT(ghost_forms, list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \
|
||||||
"ghost_blue","ghost_yellow","ghost_green","ghost_pink", \
|
"ghost_blue","ghost_yellow","ghost_green","ghost_pink", \
|
||||||
@@ -429,4 +415,3 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
|
|||||||
prefs.save_preferences()
|
prefs.save_preferences()
|
||||||
to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
|
to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
|
||||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Prayer Visibility", "[prefs.chat_toggles & CHAT_PRAYER ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Prayer Visibility", "[prefs.chat_toggles & CHAT_PRAYER ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
var/blood_type = null
|
var/blood_type = null
|
||||||
var/list/features = null
|
var/list/features = null
|
||||||
var/factions = null
|
var/factions = null
|
||||||
|
var/list/traits = null
|
||||||
var/contains_sample = 0
|
var/contains_sample = 0
|
||||||
|
|
||||||
/obj/item/seeds/replicapod/attackby(obj/item/W, mob/user, params)
|
/obj/item/seeds/replicapod/attackby(obj/item/W, mob/user, params)
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
blood_type = bloodSample.data["blood_type"]
|
blood_type = bloodSample.data["blood_type"]
|
||||||
features = bloodSample.data["features"]
|
features = bloodSample.data["features"]
|
||||||
factions = bloodSample.data["factions"]
|
factions = bloodSample.data["factions"]
|
||||||
|
traits = bloodSample.data["traits"]
|
||||||
W.reagents.clear_reagents()
|
W.reagents.clear_reagents()
|
||||||
to_chat(user, "<span class='notice'>You inject the contents of the syringe into the seeds.</span>")
|
to_chat(user, "<span class='notice'>You inject the contents of the syringe into the seeds.</span>")
|
||||||
contains_sample = 1
|
contains_sample = 1
|
||||||
@@ -99,6 +101,8 @@
|
|||||||
podman.faction |= factions
|
podman.faction |= factions
|
||||||
if(!features["mcolor"])
|
if(!features["mcolor"])
|
||||||
features["mcolor"] = "#59CE00"
|
features["mcolor"] = "#59CE00"
|
||||||
|
for(var/V in traits)
|
||||||
|
new V(podman)
|
||||||
podman.hardset_dna(null,null,podman.real_name,blood_type, new /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
|
podman.hardset_dna(null,null,podman.real_name,blood_type, new /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
|
||||||
podman.set_cloned_appearance()
|
podman.set_cloned_appearance()
|
||||||
|
|
||||||
|
|||||||
@@ -160,3 +160,4 @@ GLOBAL_LIST_EMPTY(z_is_planet)
|
|||||||
. = ..()
|
. = ..()
|
||||||
var/turf/T = get_turf(src)
|
var/turf/T = get_turf(src)
|
||||||
GLOB.z_is_planet["[T.z]"] = TRUE
|
GLOB.z_is_planet["[T.z]"] = TRUE
|
||||||
|
|
||||||
|
|||||||
@@ -125,4 +125,4 @@
|
|||||||
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
|
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
|
||||||
force = 5
|
force = 5
|
||||||
throwforce = 7
|
throwforce = 7
|
||||||
w_class = WEIGHT_CLASS_SMALL
|
w_class = WEIGHT_CLASS_SMALL
|
||||||
|
|||||||
@@ -379,9 +379,8 @@
|
|||||||
if(SSshuttle.emergency.timeLeft(1) > initial(SSshuttle.emergencyCallTime)*0.5)
|
if(SSshuttle.emergency.timeLeft(1) > initial(SSshuttle.emergencyCallTime)*0.5)
|
||||||
SSticker.mode.make_antag_chance(humanc)
|
SSticker.mode.make_antag_chance(humanc)
|
||||||
|
|
||||||
for(var/V in character.roundstart_traits)
|
if(CONFIG_GET(flag/roundstart_traits))
|
||||||
var/datum/trait/T = V
|
SStraits.AssignTraits(humanc, humanc.client, TRUE)
|
||||||
T.on_spawn() //so latejoins still get their correct traits
|
|
||||||
|
|
||||||
log_manifest(character.mind.key,character.mind,character,latejoin = TRUE)
|
log_manifest(character.mind.key,character.mind,character,latejoin = TRUE)
|
||||||
|
|
||||||
|
|||||||
@@ -191,6 +191,10 @@
|
|||||||
blood_data["real_name"] = real_name
|
blood_data["real_name"] = real_name
|
||||||
blood_data["features"] = dna.features
|
blood_data["features"] = dna.features
|
||||||
blood_data["factions"] = faction
|
blood_data["factions"] = faction
|
||||||
|
blood_data["traits"] = list()
|
||||||
|
for(var/V in roundstart_traits)
|
||||||
|
var/datum/trait/T = V
|
||||||
|
blood_data["traits"] += T.type
|
||||||
return blood_data
|
return blood_data
|
||||||
|
|
||||||
//get the id of the substance this mob use as blood.
|
//get the id of the substance this mob use as blood.
|
||||||
|
|||||||
@@ -17,4 +17,4 @@
|
|||||||
use_skintones = 0
|
use_skintones = 0
|
||||||
species_traits = list(SPECIES_ORGANIC,NOBLOOD,EYECOLOR)
|
species_traits = list(SPECIES_ORGANIC,NOBLOOD,EYECOLOR)
|
||||||
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER)
|
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER)
|
||||||
sexes = 0
|
sexes = 0
|
||||||
@@ -4,15 +4,12 @@
|
|||||||
id = "jelly"
|
id = "jelly"
|
||||||
default_color = "00FF90"
|
default_color = "00FF90"
|
||||||
say_mod = "chirps"
|
say_mod = "chirps"
|
||||||
species_traits = list(SPECIES_ORGANIC,MUTCOLORS,EYECOLOR,,HAIR,FACEHAIR,NOBLOOD)
|
species_traits = list(SPECIES_ORGANIC,MUTCOLORS,EYECOLOR,NOBLOOD)
|
||||||
inherent_traits = list(TRAIT_TOXINLOVER)
|
inherent_traits = list(TRAIT_TOXINLOVER)
|
||||||
mutant_bodyparts = list("mam_tail", "mam_ears", "taur") //CIT CHANGE
|
|
||||||
default_features = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None") //CIT CHANGE
|
|
||||||
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
|
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
|
||||||
exotic_blood = "slimejelly"
|
exotic_blood = "slimejelly"
|
||||||
damage_overlay_type = ""
|
damage_overlay_type = ""
|
||||||
var/datum/action/innate/regenerate_limbs/regenerate_limbs
|
var/datum/action/innate/regenerate_limbs/regenerate_limbs
|
||||||
var/datum/action/innate/slime_change/slime_change //CIT CHANGE
|
|
||||||
liked_food = MEAT
|
liked_food = MEAT
|
||||||
coldmod = 6 // = 3x cold damage
|
coldmod = 6 // = 3x cold damage
|
||||||
heatmod = 0.5 // = 1/4x heat damage
|
heatmod = 0.5 // = 1/4x heat damage
|
||||||
@@ -21,8 +18,6 @@
|
|||||||
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
|
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
|
||||||
if(regenerate_limbs)
|
if(regenerate_limbs)
|
||||||
regenerate_limbs.Remove(C)
|
regenerate_limbs.Remove(C)
|
||||||
if(slime_change) //CIT CHANGE
|
|
||||||
slime_change.Remove(C) //CIT CHANGE
|
|
||||||
C.remove_language(/datum/language/slime)
|
C.remove_language(/datum/language/slime)
|
||||||
C.faction -= "slime"
|
C.faction -= "slime"
|
||||||
..()
|
..()
|
||||||
@@ -34,8 +29,6 @@
|
|||||||
if(ishuman(C))
|
if(ishuman(C))
|
||||||
regenerate_limbs = new
|
regenerate_limbs = new
|
||||||
regenerate_limbs.Grant(C)
|
regenerate_limbs.Grant(C)
|
||||||
slime_change = new //CIT CHANGE
|
|
||||||
slime_change.Grant(C) //CIT CHANGE
|
|
||||||
C.faction |= "slime"
|
C.faction |= "slime"
|
||||||
|
|
||||||
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
|
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
|
||||||
@@ -384,6 +377,7 @@
|
|||||||
around.</span>",
|
around.</span>",
|
||||||
"<span class='notice'>...and move this one instead.</span>")
|
"<span class='notice'>...and move this one instead.</span>")
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////LUMINESCENTS//////////////////////////////////////////
|
///////////////////////////////////LUMINESCENTS//////////////////////////////////////////
|
||||||
|
|
||||||
//Luminescents are able to consume and use slime extracts, without them decaying.
|
//Luminescents are able to consume and use slime extracts, without them decaying.
|
||||||
@@ -542,7 +536,6 @@
|
|||||||
|
|
||||||
if(species.current_extract)
|
if(species.current_extract)
|
||||||
species.extract_cooldown = world.time + 100
|
species.extract_cooldown = world.time + 100
|
||||||
|
|
||||||
var/cooldown = species.current_extract.activate(H, species, activation_type)
|
var/cooldown = species.current_extract.activate(H, species, activation_type)
|
||||||
species.extract_cooldown = world.time + cooldown
|
species.extract_cooldown = world.time + cooldown
|
||||||
|
|
||||||
@@ -555,8 +548,6 @@
|
|||||||
///////////////////////////////////STARGAZERS//////////////////////////////////////////
|
///////////////////////////////////STARGAZERS//////////////////////////////////////////
|
||||||
|
|
||||||
//Stargazers are the telepathic branch of jellypeople, able to project psychic messages and to link minds with willing participants.
|
//Stargazers are the telepathic branch of jellypeople, able to project psychic messages and to link minds with willing participants.
|
||||||
//Admin spawn only
|
|
||||||
|
|
||||||
|
|
||||||
/datum/species/jelly/stargazer
|
/datum/species/jelly/stargazer
|
||||||
name = "Stargazer"
|
name = "Stargazer"
|
||||||
@@ -725,5 +716,4 @@
|
|||||||
to_chat(H, "<span class='notice'>You connect [target]'s mind to your slime link!</span>")
|
to_chat(H, "<span class='notice'>You connect [target]'s mind to your slime link!</span>")
|
||||||
else
|
else
|
||||||
to_chat(H, "<span class='warning'>You can't seem to link [target]'s mind...</span>")
|
to_chat(H, "<span class='warning'>You can't seem to link [target]'s mind...</span>")
|
||||||
to_chat(target, "<span class='warning'>The foreign presence leaves your mind.</span>")
|
to_chat(target, "<span class='warning'>The foreign presence leaves your mind.</span>")
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
/datum/species/moth/space_move(mob/living/carbon/human/H)
|
/datum/species/moth/space_move(mob/living/carbon/human/H)
|
||||||
. = ..()
|
. = ..()
|
||||||
if(H.loc && !isspaceturf(H.loc) && H.dna.features["moth_wings"] != "Burnt Off" || "None")
|
if(H.loc && !isspaceturf(H.loc) && H.dna.features["moth_wings"] != "Burnt Off")
|
||||||
var/datum/gas_mixture/current = H.loc.return_air()
|
var/datum/gas_mixture/current = H.loc.return_air()
|
||||||
if(current && (current.return_pressure() >= ONE_ATMOSPHERE*0.85)) //as long as there's reasonable pressure and no gravity, flight is possible
|
if(current && (current.return_pressure() >= ONE_ATMOSPHERE*0.85)) //as long as there's reasonable pressure and no gravity, flight is possible
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|||||||
@@ -66,4 +66,4 @@
|
|||||||
temp = master.supplied[index]
|
temp = master.supplied[index]
|
||||||
if (length(temp) > 0)
|
if (length(temp) > 0)
|
||||||
laws.supplied[index] = temp
|
laws.supplied[index] = temp
|
||||||
return
|
return
|
||||||
@@ -159,8 +159,6 @@
|
|||||||
toner = tonermax
|
toner = tonermax
|
||||||
diag_hud_set_borgcell()
|
diag_hud_set_borgcell()
|
||||||
|
|
||||||
verbs += /mob/living/proc/lay_down //CITADEL EDIT borgs have rest verb now for snowflake reasons
|
|
||||||
|
|
||||||
//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
|
//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
|
||||||
/mob/living/silicon/robot/Destroy()
|
/mob/living/silicon/robot/Destroy()
|
||||||
if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
|
if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
|
||||||
@@ -212,8 +210,6 @@
|
|||||||
if(!CONFIG_GET(flag/disable_secborg))
|
if(!CONFIG_GET(flag/disable_secborg))
|
||||||
modulelist["Security"] = /obj/item/robot_module/security
|
modulelist["Security"] = /obj/item/robot_module/security
|
||||||
|
|
||||||
modulelist += get_cit_modules() //Citadel change - adds Citadel's borg modules.
|
|
||||||
|
|
||||||
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in modulelist
|
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in modulelist
|
||||||
if(!input_module || module.type != /obj/item/robot_module)
|
if(!input_module || module.type != /obj/item/robot_module)
|
||||||
return
|
return
|
||||||
@@ -367,12 +363,8 @@
|
|||||||
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
|
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
|
||||||
if(!W.use_tool(src, user, 50))
|
if(!W.use_tool(src, user, 50))
|
||||||
return
|
return
|
||||||
adjustBruteLoss(-10)
|
|
||||||
else
|
adjustBruteLoss(-30)
|
||||||
to_chat(user, "<span class='notice'>You start fixing [src]...</span>")
|
|
||||||
if(!do_after(user, 30, target = src))
|
|
||||||
return
|
|
||||||
adjustBruteLoss(-30)
|
|
||||||
updatehealth()
|
updatehealth()
|
||||||
add_fingerprint(user)
|
add_fingerprint(user)
|
||||||
visible_message("<span class='notice'>[user] has fixed some of the dents on [src].</span>")
|
visible_message("<span class='notice'>[user] has fixed some of the dents on [src].</span>")
|
||||||
@@ -382,16 +374,11 @@
|
|||||||
user.changeNext_move(CLICK_CD_MELEE)
|
user.changeNext_move(CLICK_CD_MELEE)
|
||||||
var/obj/item/stack/cable_coil/coil = W
|
var/obj/item/stack/cable_coil/coil = W
|
||||||
if (getFireLoss() > 0 || getToxLoss() > 0)
|
if (getFireLoss() > 0 || getToxLoss() > 0)
|
||||||
if(src == user && coil.use(1))
|
if(src == user)
|
||||||
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
|
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
|
||||||
if(!do_after(user, 50, target = src))
|
if(!do_after(user, 50, target = src))
|
||||||
return
|
return
|
||||||
adjustFireLoss(-10)
|
|
||||||
adjustToxLoss(-10)
|
|
||||||
if (coil.use(1))
|
if (coil.use(1))
|
||||||
to_chat(user, "<span class='notice'>You start fixing [src]...</span>")
|
|
||||||
if(!do_after(user, 30, target = src))
|
|
||||||
return
|
|
||||||
adjustFireLoss(-30)
|
adjustFireLoss(-30)
|
||||||
adjustToxLoss(-30)
|
adjustToxLoss(-30)
|
||||||
updatehealth()
|
updatehealth()
|
||||||
@@ -600,36 +587,6 @@
|
|||||||
/mob/living/silicon/robot/update_icons()
|
/mob/living/silicon/robot/update_icons()
|
||||||
cut_overlays()
|
cut_overlays()
|
||||||
icon_state = module.cyborg_base_icon
|
icon_state = module.cyborg_base_icon
|
||||||
|
|
||||||
//Citadel changes start here - Allows modules to use different icon files, and allows modules to specify a pixel offset
|
|
||||||
icon = (module.cyborg_icon_override ? module.cyborg_icon_override : initial(icon))
|
|
||||||
if(laser)
|
|
||||||
add_overlay("laser")//Is this even used??? - Yes borg/inventory.dm
|
|
||||||
if(disabler)
|
|
||||||
add_overlay("disabler")//ditto
|
|
||||||
|
|
||||||
if(sleeper_g && module.sleeper_overlay)
|
|
||||||
add_overlay("[module.sleeper_overlay]_g")
|
|
||||||
if(sleeper_r && module.sleeper_overlay)
|
|
||||||
add_overlay("[module.sleeper_overlay]_r")
|
|
||||||
if(module.dogborg == TRUE)
|
|
||||||
if(resting)
|
|
||||||
cut_overlays()
|
|
||||||
icon_state = "[module.cyborg_base_icon]-rest"
|
|
||||||
else
|
|
||||||
icon_state = "[module.cyborg_base_icon]"
|
|
||||||
|
|
||||||
if(stat == DEAD && module.has_snowflake_deadsprite)
|
|
||||||
icon_state = "[module.cyborg_base_icon]-wreck"
|
|
||||||
|
|
||||||
if(module.cyborg_pixel_offset)
|
|
||||||
pixel_x = module.cyborg_pixel_offset
|
|
||||||
//End of citadel changes
|
|
||||||
|
|
||||||
if(module.cyborg_base_icon == "robot")
|
|
||||||
icon = 'icons/mob/robots.dmi'
|
|
||||||
pixel_x = initial(pixel_x)
|
|
||||||
|
|
||||||
if(stat != DEAD && !(IsUnconscious() || IsStun() || IsKnockdown() || low_power_mode)) //Not dead, not stunned.
|
if(stat != DEAD && !(IsUnconscious() || IsStun() || IsKnockdown() || low_power_mode)) //Not dead, not stunned.
|
||||||
if(!eye_lights)
|
if(!eye_lights)
|
||||||
eye_lights = new()
|
eye_lights = new()
|
||||||
@@ -1023,7 +980,6 @@
|
|||||||
designation = module.name
|
designation = module.name
|
||||||
if(hands)
|
if(hands)
|
||||||
hands.icon_state = module.moduleselect_icon
|
hands.icon_state = module.moduleselect_icon
|
||||||
hands.icon = (module.moduleselect_alternate_icon ? module.moduleselect_alternate_icon : initial(hands.icon)) //CITADEL CHANGE - allows module select icons to use a different icon file
|
|
||||||
if(module.can_be_pushed)
|
if(module.can_be_pushed)
|
||||||
status_flags |= CANPUSH
|
status_flags |= CANPUSH
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
ventcrawler = VENTCRAWLER_ALWAYS
|
ventcrawler = VENTCRAWLER_ALWAYS
|
||||||
var/datum/mind/origin
|
var/datum/mind/origin
|
||||||
var/egg_lain = 0
|
var/egg_lain = 0
|
||||||
//gold_core_spawnable = HOSTILE_SPAWN //are you sure about this??
|
gold_core_spawnable = NO_SPAWN //are you sure about this?? // CITADEL CHANGE, Yes.
|
||||||
|
|
||||||
/mob/living/simple_animal/hostile/headcrab/proc/Infect(mob/living/carbon/victim)
|
/mob/living/simple_animal/hostile/headcrab/proc/Infect(mob/living/carbon/victim)
|
||||||
var/obj/item/organ/body_egg/changeling_egg/egg = new(victim)
|
var/obj/item/organ/body_egg/changeling_egg/egg = new(victim)
|
||||||
|
|||||||
@@ -146,13 +146,13 @@
|
|||||||
else
|
else
|
||||||
status_traits[trait] |= list(source)
|
status_traits[trait] |= list(source)
|
||||||
|
|
||||||
/mob/living/proc/add_trait_datum(trait) //separate proc due to the way these ones are handled
|
/mob/living/proc/add_trait_datum(trait, spawn_effects) //separate proc due to the way these ones are handled
|
||||||
if(has_trait(trait))
|
if(has_trait(trait))
|
||||||
return
|
return
|
||||||
if(!SStraits || !SStraits.traits[trait])
|
if(!SStraits || !SStraits.traits[trait])
|
||||||
return
|
return
|
||||||
var/datum/trait/T = SStraits.traits[trait]
|
var/datum/trait/T = SStraits.traits[trait]
|
||||||
new T (src)
|
new T (src, spawn_effects)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/mob/living/proc/remove_trait(trait, list/sources, force)
|
/mob/living/proc/remove_trait(trait, list/sources, force)
|
||||||
@@ -192,13 +192,14 @@
|
|||||||
|
|
||||||
. = FALSE
|
. = FALSE
|
||||||
|
|
||||||
|
if(sources && !islist(sources))
|
||||||
|
sources = list(sources)
|
||||||
if(LAZYLEN(sources))
|
if(LAZYLEN(sources))
|
||||||
for(var/S in sources)
|
for(var/S in sources)
|
||||||
if(S in status_traits[trait])
|
if(S in status_traits[trait])
|
||||||
return TRUE
|
return TRUE
|
||||||
else
|
else if(LAZYLEN(status_traits[trait]))
|
||||||
if(LAZYLEN(status_traits[trait]))
|
return TRUE
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/mob/living/proc/has_trait_datum(trait)
|
/mob/living/proc/has_trait_datum(trait)
|
||||||
return roundstart_traits[trait]
|
return roundstart_traits[trait]
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
var/recharged = 0
|
var/recharged = 0
|
||||||
var/recharge_delay = 5
|
var/recharge_delay = 5
|
||||||
var/mutable_appearance/beaker_overlay
|
var/mutable_appearance/beaker_overlay
|
||||||
|
var/working_state = "dispenser_working"
|
||||||
|
var/nopower_state = "dispenser_nopower"
|
||||||
var/obj/item/reagent_containers/beaker = null
|
var/obj/item/reagent_containers/beaker = null
|
||||||
var/list/dispensable_reagents = list(
|
var/list/dispensable_reagents = list(
|
||||||
"hydrogen",
|
"hydrogen",
|
||||||
@@ -60,6 +62,7 @@
|
|||||||
cell = new cell_type
|
cell = new cell_type
|
||||||
recharge()
|
recharge()
|
||||||
dispensable_reagents = sortList(dispensable_reagents)
|
dispensable_reagents = sortList(dispensable_reagents)
|
||||||
|
update_icon()
|
||||||
|
|
||||||
/obj/machinery/chem_dispenser/Destroy()
|
/obj/machinery/chem_dispenser/Destroy()
|
||||||
QDEL_NULL(beaker)
|
QDEL_NULL(beaker)
|
||||||
@@ -67,13 +70,36 @@
|
|||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/machinery/chem_dispenser/process()
|
/obj/machinery/chem_dispenser/process()
|
||||||
|
|
||||||
if(recharged < 0)
|
if(recharged < 0)
|
||||||
recharge()
|
recharge()
|
||||||
recharged = recharge_delay
|
recharged = recharge_delay
|
||||||
else
|
else
|
||||||
recharged -= 1
|
recharged -= 1
|
||||||
|
|
||||||
|
/obj/machinery/chem_dispenser/proc/display_beaker()
|
||||||
|
..()
|
||||||
|
var/mutable_appearance/b_o = beaker_overlay || mutable_appearance(icon, "disp_beaker")
|
||||||
|
b_o.pixel_y = -4
|
||||||
|
b_o.pixel_x = -7
|
||||||
|
return b_o
|
||||||
|
|
||||||
|
obj/machinery/chem_dispenser/proc/work_animation()
|
||||||
|
if(working_state)
|
||||||
|
flick(working_state,src)
|
||||||
|
|
||||||
|
/obj/machinery/chem_dispenser/power_change()
|
||||||
|
..()
|
||||||
|
if(!powered() && nopower_state)
|
||||||
|
icon_state = nopower_state
|
||||||
|
else
|
||||||
|
icon_state = initial(icon_state)
|
||||||
|
|
||||||
|
obj/machinery/chem_dispenser/update_icon()
|
||||||
|
cut_overlays()
|
||||||
|
if(beaker)
|
||||||
|
beaker_overlay = display_beaker()
|
||||||
|
add_overlay(beaker_overlay)
|
||||||
|
|
||||||
/obj/machinery/chem_dispenser/proc/recharge()
|
/obj/machinery/chem_dispenser/proc/recharge()
|
||||||
if(stat & (BROKEN|NOPOWER))
|
if(stat & (BROKEN|NOPOWER))
|
||||||
return
|
return
|
||||||
@@ -163,6 +189,7 @@
|
|||||||
var/target = text2num(params["target"])
|
var/target = text2num(params["target"])
|
||||||
if(target in beaker.possible_transfer_amounts)
|
if(target in beaker.possible_transfer_amounts)
|
||||||
amount = target
|
amount = target
|
||||||
|
work_animation()
|
||||||
. = TRUE
|
. = TRUE
|
||||||
if("dispense")
|
if("dispense")
|
||||||
var/reagent = params["reagent"]
|
var/reagent = params["reagent"]
|
||||||
@@ -173,11 +200,13 @@
|
|||||||
|
|
||||||
R.add_reagent(reagent, actual)
|
R.add_reagent(reagent, actual)
|
||||||
cell.use((actual / 10) / powerefficiency)
|
cell.use((actual / 10) / powerefficiency)
|
||||||
|
work_animation()
|
||||||
. = TRUE
|
. = TRUE
|
||||||
if("remove")
|
if("remove")
|
||||||
var/amount = text2num(params["amount"])
|
var/amount = text2num(params["amount"])
|
||||||
if(beaker && amount in beaker.possible_transfer_amounts)
|
if(beaker && amount in beaker.possible_transfer_amounts)
|
||||||
beaker.reagents.remove_all(amount)
|
beaker.reagents.remove_all(amount)
|
||||||
|
work_animation()
|
||||||
. = TRUE
|
. = TRUE
|
||||||
if("eject")
|
if("eject")
|
||||||
if(beaker)
|
if(beaker)
|
||||||
@@ -185,7 +214,7 @@
|
|||||||
if(Adjacent(usr) && !issilicon(usr))
|
if(Adjacent(usr) && !issilicon(usr))
|
||||||
usr.put_in_hands(beaker)
|
usr.put_in_hands(beaker)
|
||||||
beaker = null
|
beaker = null
|
||||||
cut_overlays()
|
update_icon()
|
||||||
. = TRUE
|
. = TRUE
|
||||||
if("dispense_recipe")
|
if("dispense_recipe")
|
||||||
var/recipe_to_use = params["recipe"]
|
var/recipe_to_use = params["recipe"]
|
||||||
@@ -200,6 +229,7 @@
|
|||||||
if(actual)
|
if(actual)
|
||||||
R.add_reagent(r_id, actual)
|
R.add_reagent(r_id, actual)
|
||||||
cell.use((actual / 10) / powerefficiency)
|
cell.use((actual / 10) / powerefficiency)
|
||||||
|
work_animation()
|
||||||
if("clear_recipes")
|
if("clear_recipes")
|
||||||
var/yesno = alert("Clear all recipes?",, "Yes","No")
|
var/yesno = alert("Clear all recipes?",, "Yes","No")
|
||||||
if(yesno == "Yes")
|
if(yesno == "Yes")
|
||||||
@@ -226,23 +256,17 @@
|
|||||||
/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params)
|
/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params)
|
||||||
if(default_unfasten_wrench(user, I))
|
if(default_unfasten_wrench(user, I))
|
||||||
return
|
return
|
||||||
|
|
||||||
if(istype(I, /obj/item/reagent_containers) && !(I.flags_1 & ABSTRACT_1) && I.is_open_container())
|
if(istype(I, /obj/item/reagent_containers) && !(I.flags_1 & ABSTRACT_1) && I.is_open_container())
|
||||||
var/obj/item/reagent_containers/B = I
|
var/obj/item/reagent_containers/B = I
|
||||||
. = 1 //no afterattack
|
. = 1 //no afterattack
|
||||||
if(beaker)
|
if(beaker)
|
||||||
to_chat(user, "<span class='warning'>A container is already loaded into [src]!</span>")
|
to_chat(user, "<span class='warning'>A container is already loaded into [src]!</span>")
|
||||||
return
|
return
|
||||||
|
|
||||||
if(!user.transferItemToLoc(B, src))
|
if(!user.transferItemToLoc(B, src))
|
||||||
return
|
return
|
||||||
|
|
||||||
beaker = B
|
beaker = B
|
||||||
to_chat(user, "<span class='notice'>You add [B] to [src].</span>")
|
to_chat(user, "<span class='notice'>You add [B] to [src].</span>")
|
||||||
|
update_icon()
|
||||||
beaker_overlay = beaker_overlay || mutable_appearance(icon, "disp_beaker")
|
|
||||||
beaker_overlay.pixel_x = rand(-10, 5)//randomize beaker overlay position.
|
|
||||||
add_overlay(beaker_overlay)
|
|
||||||
else if(user.a_intent != INTENT_HARM && !istype(I, /obj/item/card/emag))
|
else if(user.a_intent != INTENT_HARM && !istype(I, /obj/item/card/emag))
|
||||||
to_chat(user, "<span class='warning'>You can't load [I] into [src]!</span>")
|
to_chat(user, "<span class='warning'>You can't load [I] into [src]!</span>")
|
||||||
return ..()
|
return ..()
|
||||||
@@ -266,6 +290,7 @@
|
|||||||
beaker.reagents.remove_all()
|
beaker.reagents.remove_all()
|
||||||
cell.use(total/powerefficiency)
|
cell.use(total/powerefficiency)
|
||||||
cell.emp_act(severity)
|
cell.emp_act(severity)
|
||||||
|
work_animation()
|
||||||
visible_message("<span class='danger'>[src] malfunctions, spraying chemicals everywhere!</span>")
|
visible_message("<span class='danger'>[src] malfunctions, spraying chemicals everywhere!</span>")
|
||||||
..()
|
..()
|
||||||
|
|
||||||
@@ -278,6 +303,8 @@
|
|||||||
recharge_delay = 20
|
recharge_delay = 20
|
||||||
dispensable_reagents = list()
|
dispensable_reagents = list()
|
||||||
circuit = /obj/item/circuitboard/machine/chem_dispenser
|
circuit = /obj/item/circuitboard/machine/chem_dispenser
|
||||||
|
working_state = "minidispenser_working"
|
||||||
|
nopower_state = "minidispenser_nopower"
|
||||||
var/static/list/dispensable_reagent_tiers = list(
|
var/static/list/dispensable_reagent_tiers = list(
|
||||||
list(
|
list(
|
||||||
"hydrogen",
|
"hydrogen",
|
||||||
@@ -362,6 +389,29 @@
|
|||||||
final_list += list(avoid_assoc_duplicate_keys(fuck[1],key_list) = text2num(fuck[2]))
|
final_list += list(avoid_assoc_duplicate_keys(fuck[1],key_list) = text2num(fuck[2]))
|
||||||
return final_list
|
return final_list
|
||||||
|
|
||||||
|
/obj/machinery/chem_dispenser/constructable/display_beaker()
|
||||||
|
var/mutable_appearance/b_o = beaker_overlay || mutable_appearance(icon, "disp_beaker")
|
||||||
|
b_o.pixel_y = -4
|
||||||
|
b_o.pixel_x = -4
|
||||||
|
return b_o
|
||||||
|
|
||||||
|
/obj/machinery/chem_dispenser/drinks/display_beaker()
|
||||||
|
var/mutable_appearance/b_o = beaker_overlay || mutable_appearance(icon, "disp_beaker")
|
||||||
|
switch(dir)
|
||||||
|
if(NORTH)
|
||||||
|
b_o.pixel_y = 7
|
||||||
|
b_o.pixel_x = rand(-9, 9)
|
||||||
|
if(EAST)
|
||||||
|
b_o.pixel_x = 4
|
||||||
|
b_o.pixel_y = rand(-5, 7)
|
||||||
|
if(WEST)
|
||||||
|
b_o.pixel_x = -5
|
||||||
|
b_o.pixel_y = rand(-5, 7)
|
||||||
|
else//SOUTH
|
||||||
|
b_o.pixel_y = -7
|
||||||
|
b_o.pixel_x = rand(-9, 9)
|
||||||
|
return b_o
|
||||||
|
|
||||||
/obj/machinery/chem_dispenser/drinks
|
/obj/machinery/chem_dispenser/drinks
|
||||||
name = "soda dispenser"
|
name = "soda dispenser"
|
||||||
desc = "Contains a large reservoir of soft drinks."
|
desc = "Contains a large reservoir of soft drinks."
|
||||||
@@ -369,6 +419,10 @@
|
|||||||
icon = 'icons/obj/chemical.dmi'
|
icon = 'icons/obj/chemical.dmi'
|
||||||
icon_state = "soda_dispenser"
|
icon_state = "soda_dispenser"
|
||||||
amount = 10
|
amount = 10
|
||||||
|
pixel_y = 6
|
||||||
|
layer = WALL_OBJ_LAYER
|
||||||
|
working_state = null
|
||||||
|
nopower_state = null
|
||||||
dispensable_reagents = list(
|
dispensable_reagents = list(
|
||||||
"water",
|
"water",
|
||||||
"ice",
|
"ice",
|
||||||
@@ -398,8 +452,6 @@
|
|||||||
"tirizene"
|
"tirizene"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/obj/machinery/chem_dispenser/drinks/beer
|
/obj/machinery/chem_dispenser/drinks/beer
|
||||||
name = "booze dispenser"
|
name = "booze dispenser"
|
||||||
desc = "Contains a large reservoir of the good stuff."
|
desc = "Contains a large reservoir of the good stuff."
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
icon_state = "294_bottom"
|
icon_state = "294_bottom"
|
||||||
amount = 10
|
amount = 10
|
||||||
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
|
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
|
||||||
|
working_state = null
|
||||||
|
nopower_state = null
|
||||||
var/static/list/shortcuts = list(
|
var/static/list/shortcuts = list(
|
||||||
"meth" = "methamphetamine",
|
"meth" = "methamphetamine",
|
||||||
"tricord" = "tricordrazine"
|
"tricord" = "tricordrazine"
|
||||||
@@ -25,7 +27,7 @@
|
|||||||
GLOB.poi_list += src
|
GLOB.poi_list += src
|
||||||
top_overlay = mutable_appearance(icon, "294_top", layer = ABOVE_ALL_MOB_LAYER)
|
top_overlay = mutable_appearance(icon, "294_top", layer = ABOVE_ALL_MOB_LAYER)
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
|
|
||||||
/obj/machinery/chem_dispenser/scp_294/update_icon()
|
/obj/machinery/chem_dispenser/scp_294/update_icon()
|
||||||
cut_overlays()
|
cut_overlays()
|
||||||
@@ -36,6 +38,9 @@
|
|||||||
GLOB.poi_list -= src
|
GLOB.poi_list -= src
|
||||||
QDEL_NULL(top_overlay)
|
QDEL_NULL(top_overlay)
|
||||||
|
|
||||||
|
/obj/machinery/chem_dispenser/scp_294/display_beaker()
|
||||||
|
return
|
||||||
|
|
||||||
/obj/machinery/chem_dispenser/scp_294/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
/obj/machinery/chem_dispenser/scp_294/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||||
|
|||||||
91
code/modules/reagents/reagent_containers/medspray.dm
Normal file
91
code/modules/reagents/reagent_containers/medspray.dm
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/obj/item/reagent_containers/medspray
|
||||||
|
name = "medical spray"
|
||||||
|
desc = "A medical spray bottle, designed for precision application, with an unscrewable cap."
|
||||||
|
icon = 'icons/obj/chemical.dmi'
|
||||||
|
icon_state = "medspray"
|
||||||
|
item_state = "spraycan"
|
||||||
|
lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi'
|
||||||
|
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
|
||||||
|
flags_1 = NOBLUDGEON_1
|
||||||
|
obj_flags = UNIQUE_RENAME
|
||||||
|
container_type = OPENCONTAINER
|
||||||
|
slot_flags = SLOT_BELT
|
||||||
|
throwforce = 0
|
||||||
|
w_class = WEIGHT_CLASS_SMALL
|
||||||
|
throw_speed = 3
|
||||||
|
throw_range = 7
|
||||||
|
amount_per_transfer_from_this = 10
|
||||||
|
volume = 60
|
||||||
|
var/can_fill_from_container = TRUE
|
||||||
|
var/apply_type = PATCH
|
||||||
|
var/apply_method = "spray"
|
||||||
|
var/self_delay = 30
|
||||||
|
var/squirt_mode = 0
|
||||||
|
var/squirt_amount = 5
|
||||||
|
|
||||||
|
/obj/item/reagent_containers/medspray/attack_self(mob/user)
|
||||||
|
squirt_mode = !squirt_mode
|
||||||
|
if(squirt_mode)
|
||||||
|
amount_per_transfer_from_this = squirt_amount
|
||||||
|
else
|
||||||
|
amount_per_transfer_from_this = initial(amount_per_transfer_from_this)
|
||||||
|
to_chat(user, "<span class='notice'>You will now apply the medspray's contents in [squirt_mode ? "short bursts":"extended sprays"]. You'll now use [amount_per_transfer_from_this] units per use.</span>")
|
||||||
|
|
||||||
|
/obj/item/reagent_containers/medspray/attack(mob/M, mob/user, def_zone)
|
||||||
|
if(!reagents || !reagents.total_volume)
|
||||||
|
to_chat(user, "<span class='warning'>[src] is empty!</span>")
|
||||||
|
return
|
||||||
|
|
||||||
|
if(M == user)
|
||||||
|
M.visible_message("<span class='notice'>[user] attempts to [apply_method] [src] on themselves.</span>")
|
||||||
|
if(self_delay)
|
||||||
|
if(!do_mob(user, M, self_delay))
|
||||||
|
return
|
||||||
|
if(!reagents || !reagents.total_volume)
|
||||||
|
return
|
||||||
|
to_chat(M, "<span class='notice'>You [apply_method] yourself with [src].</span>")
|
||||||
|
|
||||||
|
else
|
||||||
|
add_logs(user, M, "attempted to apply", src, reagents.log_list())
|
||||||
|
M.visible_message("<span class='danger'>[user] attempts to [apply_method] [src] on [M].</span>", \
|
||||||
|
"<span class='userdanger'>[user] attempts to [apply_method] [src] on [M].</span>")
|
||||||
|
if(!do_mob(user, M))
|
||||||
|
return
|
||||||
|
if(!reagents || !reagents.total_volume)
|
||||||
|
return
|
||||||
|
M.visible_message("<span class='danger'>[user] [apply_method]s [M] down with [src].</span>", \
|
||||||
|
"<span class='userdanger'>[user] [apply_method]s [M] down with [src].</span>")
|
||||||
|
|
||||||
|
if(!reagents || !reagents.total_volume)
|
||||||
|
return
|
||||||
|
|
||||||
|
else
|
||||||
|
add_logs(user, M, "applied", src, reagents.log_list())
|
||||||
|
playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6)
|
||||||
|
var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
|
||||||
|
reagents.reaction(M, apply_type, fraction)
|
||||||
|
reagents.trans_to(M, amount_per_transfer_from_this)
|
||||||
|
return
|
||||||
|
|
||||||
|
/obj/item/reagent_containers/medspray/styptic
|
||||||
|
name = "medical spray (styptic powder)"
|
||||||
|
desc = "A medical spray bottle, designed for precision application, with an unscrewable cap. This one contains styptic powder, for treating cuts and bruises."
|
||||||
|
icon_state = "brutespray"
|
||||||
|
list_reagents = list("styptic_powder" = 60)
|
||||||
|
|
||||||
|
/obj/item/reagent_containers/medspray/silver_sulf
|
||||||
|
name = "medical spray (silver sulfadiazine)"
|
||||||
|
desc = "A medical spray bottle, designed for precision application, with an unscrewable cap. This one contains silver sulfadiazine, useful for treating burns."
|
||||||
|
icon_state = "burnspray"
|
||||||
|
list_reagents = list("silver_sulfadiazine" = 60)
|
||||||
|
|
||||||
|
/obj/item/reagent_containers/medspray/synthflesh
|
||||||
|
name = "medical spray (synthflesh)"
|
||||||
|
desc = "A medical spray bottle, designed for precision application, with an unscrewable cap. This one contains synthflesh, an apex brute and burn healing agent."
|
||||||
|
icon_state = "synthspray"
|
||||||
|
list_reagents = list("synthflesh" = 60)
|
||||||
|
|
||||||
|
/obj/item/reagent_containers/medspray/sterilizine
|
||||||
|
name = "sterilizer spray"
|
||||||
|
desc = "Spray bottle loaded with non-toxic sterilizer. Useful in preparation for surgery."
|
||||||
|
list_reagents = list("sterilizine" = 60)
|
||||||
@@ -171,19 +171,6 @@
|
|||||||
list_reagents = list("spraytan" = 50)
|
list_reagents = list("spraytan" = 50)
|
||||||
|
|
||||||
|
|
||||||
/obj/item/reagent_containers/spray/medical
|
|
||||||
name = "medical spray"
|
|
||||||
icon = 'icons/obj/chemical.dmi'
|
|
||||||
icon_state = "medspray"
|
|
||||||
volume = 100
|
|
||||||
|
|
||||||
|
|
||||||
/obj/item/reagent_containers/spray/medical/sterilizer
|
|
||||||
name = "sterilizer spray"
|
|
||||||
desc = "Spray bottle loaded with non-toxic sterilizer. Useful in preparation for surgery."
|
|
||||||
list_reagents = list("sterilizine" = 100)
|
|
||||||
|
|
||||||
|
|
||||||
//pepperspray
|
//pepperspray
|
||||||
/obj/item/reagent_containers/spray/pepper
|
/obj/item/reagent_containers/spray/pepper
|
||||||
name = "pepperspray"
|
name = "pepperspray"
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN)
|
|||||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL)
|
if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL)
|
||||||
SSshuttle.emergency.modTimer(2)
|
SSshuttle.emergency.modTimer(2)
|
||||||
GLOB.security_level = SEC_LEVEL_BLUE
|
GLOB.security_level = SEC_LEVEL_BLUE
|
||||||
sound_to_playing_players('sound/misc/voybluealert.ogg') // Citadel change - Makes alerts play a sound
|
|
||||||
|
|
||||||
for(var/obj/machinery/firealarm/FA in GLOB.machines)
|
for(var/obj/machinery/firealarm/FA in GLOB.machines)
|
||||||
if(is_station_level(FA.z))
|
if(is_station_level(FA.z))
|
||||||
FA.update_icon()
|
FA.update_icon()
|
||||||
@@ -57,7 +55,6 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN)
|
|||||||
else
|
else
|
||||||
minor_announce(CONFIG_GET(string/alert_red_downto), "Attention! Code red!")
|
minor_announce(CONFIG_GET(string/alert_red_downto), "Attention! Code red!")
|
||||||
GLOB.security_level = SEC_LEVEL_RED
|
GLOB.security_level = SEC_LEVEL_RED
|
||||||
sound_to_playing_players('sound/misc/voyalert.ogg') // Citadel change - Makes alerts play a sound
|
|
||||||
|
|
||||||
for(var/obj/machinery/firealarm/FA in GLOB.machines)
|
for(var/obj/machinery/firealarm/FA in GLOB.machines)
|
||||||
if(is_station_level(FA.z))
|
if(is_station_level(FA.z))
|
||||||
@@ -72,8 +69,6 @@ GLOBAL_VAR_INIT(security_level, SEC_LEVEL_GREEN)
|
|||||||
else if(GLOB.security_level == SEC_LEVEL_BLUE)
|
else if(GLOB.security_level == SEC_LEVEL_BLUE)
|
||||||
SSshuttle.emergency.modTimer(0.5)
|
SSshuttle.emergency.modTimer(0.5)
|
||||||
GLOB.security_level = SEC_LEVEL_DELTA
|
GLOB.security_level = SEC_LEVEL_DELTA
|
||||||
sound_to_playing_players('sound/misc/deltakalaxon.ogg') // Citadel change - Makes alerts play a sound
|
|
||||||
|
|
||||||
for(var/obj/machinery/firealarm/FA in GLOB.machines)
|
for(var/obj/machinery/firealarm/FA in GLOB.machines)
|
||||||
if(is_station_level(FA.z))
|
if(is_station_level(FA.z))
|
||||||
FA.update_icon()
|
FA.update_icon()
|
||||||
|
|||||||
@@ -15,4 +15,4 @@
|
|||||||
continue
|
continue
|
||||||
empulse(target.loc, emp_heavy, emp_light)
|
empulse(target.loc, emp_heavy, emp_light)
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -49,4 +49,4 @@
|
|||||||
target.blur_eyes(amt_eye_blurry)
|
target.blur_eyes(amt_eye_blurry)
|
||||||
//summoning
|
//summoning
|
||||||
if(summon_type)
|
if(summon_type)
|
||||||
new summon_type(target.loc, target)
|
new summon_type(target.loc, target)
|
||||||
@@ -20,3 +20,17 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggledigestionnoise)()
|
|||||||
to_chat(usr, "You will [(usr.client.prefs.toggles & DIGESTION_NOISES) ? "now" : "no longer"] hear digestion noises.")
|
to_chat(usr, "You will [(usr.client.prefs.toggles & DIGESTION_NOISES) ? "now" : "no longer"] hear digestion noises.")
|
||||||
/datum/verbs/menu/Settings/Sound/toggledigestionnoise/Get_checked(client/C)
|
/datum/verbs/menu/Settings/Sound/toggledigestionnoise/Get_checked(client/C)
|
||||||
return !(C.prefs.toggles & DIGESTION_NOISES)
|
return !(C.prefs.toggles & DIGESTION_NOISES)
|
||||||
|
|
||||||
|
TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, togglehoundsleeper)()
|
||||||
|
set name = "Allow/Deny Hound Sleeper"
|
||||||
|
set category = "Preferences"
|
||||||
|
set desc = "Allow MediHound Sleepers"
|
||||||
|
usr.client.prefs.toggles ^= MEDIHOUND_SLEEPER
|
||||||
|
usr.client.prefs.save_preferences()
|
||||||
|
if(usr.client.prefs.toggles & MEDIHOUND_SLEEPER)
|
||||||
|
to_chat(usr, "You will now allow MediHounds to place you in their sleeper.")
|
||||||
|
else
|
||||||
|
to_chat(usr, "You will no longer allow MediHounds to place you in their sleeper.")
|
||||||
|
SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle MediHound Sleeper", "[usr.client.prefs.toggles & MEDIHOUND_SLEEPER ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||||
|
/datum/verbs/menu/Settings/Sound/togglehoundsleeper/Get_checked(client/C)
|
||||||
|
return C.prefs.toggles & MEDIHOUND_SLEEPER
|
||||||
Reference in New Issue
Block a user