diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index 1bcd5f5a3f4..5d63e777087 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -37,7 +37,8 @@
#define R_SPAWN 4096
#define R_MOD 8192
#define R_MENTOR 16384
+#define R_PROCCALL 32768
-#define R_MAXPERMISSION 16384 //This holds the maximum value for a permission. It is used in iteration, so keep it updated.
+#define R_MAXPERMISSION 32768 //This holds the maximum value for a permission. It is used in iteration, so keep it updated.
#define R_HOST 65535
\ No newline at end of file
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index 251206bbdbf..7fedc81d617 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -346,6 +346,7 @@ proc/tg_text2list(text, glue=",", assocglue=";")
if(rights & R_VAREDIT) . += "[seperator]+VAREDIT"
if(rights & R_SOUNDS) . += "[seperator]+SOUND"
if(rights & R_SPAWN) . += "[seperator]+SPAWN"
+ if(rights & R_PROCCALL) . += "[seperator]+PROCCALL"
if(rights & R_MOD) . += "[seperator]+MODERATOR"
if(rights & R_MENTOR) . += "[seperator]+MENTOR"
return .
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index af4f203ebf8..40799c58197 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -439,7 +439,7 @@ client
//~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records).
else if(href_list["rename"])
- if(!check_rights(R_VAREDIT)) return
+ if(!check_rights(R_ADMIN)) return
var/mob/M = locate(href_list["rename"])
if(!istype(M))
@@ -498,7 +498,7 @@ client
cmd_mass_modify_object_variables(A, href_list["varnamemass"])
else if(href_list["mob_player_panel"])
- if(!check_rights(0)) return
+ if(!check_rights(R_ADMIN|R_MOD)) return
var/mob/M = locate(href_list["mob_player_panel"])
if(!istype(M))
@@ -543,7 +543,7 @@ client
href_list["datumrefresh"] = href_list["godmode"]
else if(href_list["gib"])
- if(!check_rights(0)) return
+ if(!check_rights(R_ADMIN|R_EVENT)) return
var/mob/M = locate(href_list["gib"])
if(!istype(M))
@@ -575,7 +575,7 @@ client
usr.client.cmd_admin_drop_everything(M)
else if(href_list["direct_control"])
- if(!check_rights(0)) return
+ if(!check_rights(R_DEBUG|R_ADMIN)) return
var/mob/M = locate(href_list["direct_control"])
if(!istype(M))
@@ -668,7 +668,7 @@ client
message_admins("\blue [key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ")
else if(href_list["addreagent"]) /* Made on /TG/, credit to them. */
- if(!check_rights(0)) return
+ if(!check_rights(R_DEBUG|R_ADMIN)) return
var/atom/A = locate(href_list["addreagent"])
@@ -731,7 +731,7 @@ client
href_list["datumrefresh"] = href_list["mark_object"]
else if(href_list["proc_call"])
- if(!check_rights(0))
+ if(!check_rights(R_PROCCALL))
return
var/T = locate(href_list["proc_call"])
@@ -740,7 +740,7 @@ client
callproc_datum(T)
else if(href_list["rotatedatum"])
- if(!check_rights(0)) return
+ if(!check_rights(R_DEBUG|R_ADMIN)) return
var/atom/A = locate(href_list["rotatedatum"])
if(!istype(A))
diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm
deleted file mode 100644
index 512e9f02dce..00000000000
--- a/code/datums/helper_datums/getrev.dm
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * This datum gets revision info from local svn 'entries' file
- * Path to the directory containing it should be in 'config/svndir.txt' file
- *
- */
-
-var/global/datum/getrev/revdata = new("config/svndir.txt")
-
-//Oh yeah, I'm an OOP fag, lalala
-/datum/getrev
- var/revision
- var/commiter
- var/svndirpath
- var/revhref
-
- proc/abort()
- spawn()
- del src
-
- New(filename)
- ..()
- var/list/Lines = file2list(filename)
- if(!Lines.len) return abort()
- for(var/t in Lines)
- if(!t) continue
- t = trim(t)
- if (length(t) == 0)
- continue
- else if (copytext(t, 1, 2) == "#")
- continue
- var/pos = findtext(t, " ")
- var/name = null
- var/value = null
- if (pos)
- name = lowertext(copytext(t, 1, pos))
- value = copytext(t, pos + 1)
- else
- name = lowertext(t)
- if(!name)
- continue
- switch(name)
- if("svndir")
- svndirpath = value
- if("revhref")
- revhref = value
-
- if(svndirpath && fexists(svndirpath) && fexists("[svndirpath]/entries") && isfile(file("[svndirpath]/entries")))
- var/list/filelist = file2list("[svndirpath]/entries")
- var/s_archive = "" //Stores the previous line so the revision owner can be assigned.
-
- //This thing doesn't count blank lines, so doing filelist[4] isn't working.
- for(var/s in filelist)
- if(!commiter)
- if(s == "has-props")//The line before this is the committer.
- commiter = s_archive
- if(!revision)
- var/n = text2num(s)
- if(isnum(n))
- if(n > 5000 && n < 99999) //Do you think we'll still be up and running at r100000? :) ~Errorage
- revision = s
- if(revision && commiter)
- break
- s_archive = s
- if(!revision)
- abort()
- diary << "Revision info loaded succesfully"
- return
- return abort()
-
- proc/getRevisionText()
- var/output
- if(revhref)
- output = {"[revision]"}
- else
- output = revision
- return output
-
- proc/showInfo()
- return {"
-
-
-
- Server Revision: [getRevisionText()]
- Author: [commiter]
-
- "}
-
-client/verb/showrevinfo()
- set category = "OOC"
- set name = "Show Server Revision"
- var/output = "Sorry, the revision info is unavailable."
- output = file2text("/home/bay12/live/data/gitcommit")
- output += "Current Infomational Settings:
"
- output += "Protect Authority Roles From Tratior: [config.protect_roles_from_antagonist]
"
- usr << browse(output,"window=revdata");
- return
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index b7a5fa46935..4ec840223aa 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -800,7 +800,7 @@ var/global/nologevent = 0
set desc = "Edit mobs's memory and role"
set name = "Show Traitor Panel"
- if(!check_rights(R_ADMIN))
+ if(!check_rights(R_ADMIN|R_MOD))
return
if(!istype(M))
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index 236fbe42779..ae6ea3c4aae 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -42,6 +42,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
if("spawn","create") rights |= R_SPAWN
if("mod") rights |= R_MOD
if("mentor") rights |= R_MENTOR
+ if("proccall") rights |= R_PROCCALL
admin_ranks[rank] = rights
previous_rights = rights
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 839634b2887..5184f4e7dd2 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -69,7 +69,8 @@ var/list/admin_verbs_admin = list(
/client/proc/alt_check,
/client/proc/secrets,
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
- /client/proc/change_human_appearance_self /* Allows the human-based mob itself change its basic appearance */
+ /client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
+ /client/proc/debug_variables
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
@@ -139,8 +140,6 @@ var/list/admin_verbs_debug = list(
/client/proc/reload_admins,
/client/proc/restart_controller,
/client/proc/enable_debug_verbs,
- /client/proc/callproc,
- /client/proc/callproc_datum,
/client/proc/toggledebuglogs,
/client/proc/qdel_toggle,
/client/proc/gc_dump_hdl,
@@ -179,12 +178,16 @@ var/list/admin_verbs_mod = list(
/client/proc/jobbans,
/client/proc/debug_variables /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
)
-
var/list/admin_verbs_mentor = list(
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/cmd_admin_pm_by_key_panel /*admin-pm list by key*/
)
+var/list/admin_verbs_proccall = list (
+ /client/proc/callproc,
+ /client/proc/callproc_datum,
+ /client/proc/SDQL2_query
+)
/client/proc/add_admin_verbs()
if(holder)
@@ -203,6 +206,7 @@ var/list/admin_verbs_mentor = list(
if(holder.rights & R_SPAWN) verbs += admin_verbs_spawn
if(holder.rights & R_MOD) verbs += admin_verbs_mod
if(holder.rights & R_MENTOR) verbs += admin_verbs_mentor
+ if(holder.rights & R_PROCCALL) verbs += admin_verbs_proccall
/client/proc/remove_admin_verbs()
verbs.Remove(
diff --git a/code/modules/admin/machine_upgrade.dm b/code/modules/admin/machine_upgrade.dm
index 9f2039fdd0f..a0e97c4ae7b 100644
--- a/code/modules/admin/machine_upgrade.dm
+++ b/code/modules/admin/machine_upgrade.dm
@@ -1,10 +1,21 @@
/proc/machine_upgrade(obj/machinery/M in world)
set name = "Tweak Component Ratings"
set category = "Debug"
+
+ if(!check_rights(R_DEBUG))
+ return
+
+ if(!istype(M))
+ usr << "This can only be used on subtypes of /obj/machinery."
+ return
+
var/new_rating = input("Enter new rating:","Num") as num
- if(new_rating && M.component_parts)
+ if(!isnull(new_rating) && M.component_parts)
for(var/obj/item/weapon/stock_parts/P in M.component_parts)
P.rating = new_rating
M.RefreshParts()
+
+ message_admins("[key_name_admin(usr)] has set the component rating of [M] to [new_rating]")
+ log_admin("[key_name(usr)] has set the component rating of [M] to [new_rating]")
feedback_add_details("admin_verb","MU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm
index e53d4644c33..19ca9ef9b4f 100644
--- a/code/modules/admin/permissionverbs/permissionedit.dm
+++ b/code/modules/admin/permissionverbs/permissionedit.dm
@@ -2,11 +2,13 @@
set category = "Admin"
set name = "Permissions Panel"
set desc = "Edit admin permissions"
- if(!check_rights(R_PERMISSIONS)) return
+ if(!check_rights(R_PERMISSIONS))
+ return
usr.client.holder.edit_admin_permissions()
/datum/admins/proc/edit_admin_permissions()
- if(!check_rights(R_PERMISSIONS)) return
+ if(!check_rights(R_PERMISSIONS))
+ return
var/output = {"
@@ -55,8 +57,7 @@
if(!usr.client)
return
- if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS))
- usr << "\red You do not have permission to do this!"
+ if(!check_rights(R_PERMISSIONS))
return
establish_db_connection()
@@ -100,13 +101,13 @@
usr << "\blue Admin rank changed."
/datum/admins/proc/log_admin_permission_modification(var/adm_ckey, var/new_permission)
- if(config.admin_legacy_system) return
+ if(config.admin_legacy_system)
+ return
if(!usr.client)
return
- if(!usr.client.holder || !(usr.client.holder.rights & R_PERMISSIONS))
- usr << "\red You do not have permission to do this!"
+ if(!check_rights(R_PERMISSIONS))
return
establish_db_connection()
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
new file mode 100644
index 00000000000..5fcfa3a12c3
--- /dev/null
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -0,0 +1,477 @@
+// Examples
+/*
+ -- Will call the proc for all computers in the world, thats dir is 2.
+ CALL ex_act(1) ON /obj/machinery/computer IN world WHERE dir == 2
+ -- Will open a window with a list of all the closets in the world, with a link to VV them.
+ SELECT /obj/structure/closet/secure_closet/security/cargo IN world WHERE icon_off == "secoff"
+ -- Will change all the tube lights to green
+ UPDATE /obj/machinery/light IN world SET color = "#0F0" WHERE icon_state == "tube1"
+ -- Will delete all pickaxes. "IN world" is not required.
+ DELETE /obj/item/weapon/pickaxe
+ -- Will flicker the lights once, then turn all mobs green. The semicolon is important to separate the consecutive querys, but is not required for standard one-query use
+ CALL flicker(1) ON /obj/machinery/light; UPDATE /mob SET color = "#00cc00"
+
+ --You can use operators other than ==, such as >, <=, != and etc..
+
+*/
+
+/client/proc/SDQL2_query(query_text as message)
+ set category = "Debug"
+
+ if(!check_rights(R_PROCCALL)) //Shouldn't happen... but just to be safe.
+ message_admins("ERROR: Non-admin [key_name_admin(usr)] attempted to execute a SDQL query!")
+ log_admin("Non-admin [key_name(usr)] attempted to execute a SDQL query!")
+
+ if(!query_text || length(query_text) < 1)
+ return
+
+ //world << query_text
+
+ var/list/query_list = SDQL2_tokenize(query_text)
+
+ if(!query_list || query_list.len < 1)
+ return
+
+ var/list/querys = SDQL_parse(query_list)
+
+ if(!querys || querys.len < 1)
+ return
+
+ var/query_log = "executed SDQL query: \"[query_text]\"."
+ message_admins("[key_name_admin(usr)] [query_log]")
+ query_log = "[key_name(usr)] [query_log]"
+ log_admin(query_log)
+
+ for(var/list/query_tree in querys)
+ var/list/from_objs = list()
+ var/list/select_types = list()
+
+ switch(query_tree[1])
+ if("explain")
+ SDQL_testout(query_tree["explain"])
+ return
+
+ if("call")
+ if("on" in query_tree)
+ select_types = query_tree["on"]
+ else
+ return
+
+ if("select", "delete", "update")
+ select_types = query_tree[query_tree[1]]
+
+ from_objs = SDQL_from_objs(query_tree["from"])
+
+ var/list/objs = list()
+
+ for(var/type in select_types)
+ var/char = copytext(type, 1, 2)
+
+ if(char == "/" || char == "*")
+ for(var/from in from_objs)
+ objs += SDQL_get_all(type, from)
+
+ else if(char == "'" || char == "\"")
+ objs += locate(copytext(type, 2, length(type)))
+
+ if("where" in query_tree)
+ var/objs_temp = objs
+ objs = list()
+ for(var/datum/d in objs_temp)
+ if(SDQL_expression(d, query_tree["where"]))
+ objs += d
+
+ switch(query_tree[1])
+ if("call")
+ var/list/call_list = query_tree["call"]
+ var/list/args_list = query_tree["args"]
+
+ for(var/datum/d in objs)
+ for(var/v in call_list)
+ // To stop any procs which sleep from executing slowly.
+ if(d)
+ if(hascall(d, v))
+ spawn() call(d, v)(arglist(args_list)) // Spawn in case the function sleeps.
+
+ if("delete")
+ for(var/datum/d in objs)
+ del d
+
+ if("select")
+ var/text = ""
+ for(var/datum/t in objs)
+ text += "\ref[t]"
+ if(istype(t, /atom))
+ var/atom/a = t
+
+ if(a.x)
+ text += ": [t] at ([a.x], [a.y], [a.z])
"
+
+ else if(a.loc && a.loc.x)
+ text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
"
+
+ else
+ text += ": [t]
"
+
+ else
+ text += ": [t]
"
+
+ usr << browse(text, "window=SDQL-result")
+
+ if("update")
+ if("set" in query_tree)
+ var/list/set_list = query_tree["set"]
+ for(var/datum/d in objs)
+ var/list/vals = list()
+ for(var/v in set_list)
+ if(v in d.vars)
+ vals += v
+ vals[v] = SDQL_expression(d, set_list[v])
+
+ if(istype(d, /turf))
+ for(var/v in vals)
+ if(v == "x" || v == "y" || v == "z")
+ continue
+
+ d.vars[v] = vals[v]
+
+ else
+ for(var/v in vals)
+ d.vars[v] = vals[v]
+
+/proc/SDQL_parse(list/query_list)
+ var/datum/SDQL_parser/parser = new()
+ var/list/querys = list()
+ var/list/query_tree = list()
+ var/pos = 1
+ var/querys_pos = 1
+ var/do_parse = 0
+
+ for(var/val in query_list)
+ if(val == ";")
+ do_parse = 1
+ else if(pos >= query_list.len)
+ query_tree += val
+ do_parse = 1
+
+ if(do_parse)
+ parser.query = query_tree
+ var/list/parsed_tree
+ parsed_tree = parser.parse()
+ if(parsed_tree.len > 0)
+ querys.len = querys_pos
+ querys[querys_pos] = parsed_tree
+ querys_pos++
+ else //There was an error so don't run anything, and tell the user which query has errored.
+ usr << "Parsing error on [querys_pos]\th query. Nothing was executed."
+ return list()
+ query_tree = list()
+ do_parse = 0
+ else
+ query_tree += val
+ pos++
+
+ qdel(parser)
+
+ return querys
+
+
+
+/proc/SDQL_testout(list/query_tree, indent = 0)
+ var/spaces = ""
+ for(var/s = 0, s < indent, s++)
+ spaces += " "
+
+ for(var/item in query_tree)
+ if(istype(item, /list))
+ usr << "[spaces]("
+ SDQL_testout(item, indent + 1)
+ usr << "[spaces])"
+
+ else
+ usr << "[spaces][item]"
+
+ if(!isnum(item) && query_tree[item])
+
+ if(istype(query_tree[item], /list))
+ usr << "[spaces] ("
+ SDQL_testout(query_tree[item], indent + 2)
+ usr << "[spaces] )"
+
+ else
+ usr << "[spaces] [query_tree[item]]"
+
+/proc/SDQL_from_objs(list/tree)
+ if("world" in tree)
+ return list(world)
+
+ var/list/out = list()
+
+ for(var/type in tree)
+ var/char = copytext(type, 1, 2)
+
+ if(char == "/")
+ out += SDQL_get_all(type, world)
+
+ else if(char == "'" || char == "\"")
+ out += locate(copytext(type, 2, length(type)))
+
+ return out
+
+/proc/SDQL_get_all(type, location)
+ var/list/out = list()
+
+ if(type == "*")
+ for(var/datum/d in location)
+ out += d
+
+ return out
+
+ type = text2path(type)
+
+ if(ispath(type, /mob))
+ for(var/mob/d in location)
+ if(istype(d, type))
+ out += d
+
+ else if(ispath(type, /turf))
+ for(var/turf/d in location)
+ if(istype(d, type))
+ out += d
+
+ else if(ispath(type, /obj))
+ for(var/obj/d in location)
+ if(istype(d, type))
+ out += d
+
+ else if(ispath(type, /area))
+ for(var/area/d in location)
+ if(istype(d, type))
+ out += d
+
+ else if(ispath(type, /atom))
+ for(var/atom/d in location)
+ if(istype(d, type))
+ out += d
+
+ else
+ for(var/datum/d in location)
+ if(istype(d, type))
+ out += d
+
+ return out
+
+/proc/SDQL_expression(datum/object, list/expression, start = 1)
+ var/result = 0
+ var/val
+
+ for(var/i = start, i <= expression.len, i++)
+ var/op = ""
+
+ if(i > start)
+ op = expression[i]
+ i++
+
+ var/list/ret = SDQL_value(object, expression, i)
+ val = ret["val"]
+ i = ret["i"]
+
+ if(op != "")
+ switch(op)
+ if("+")
+ result += val
+ if("-")
+ result -= val
+ if("*")
+ result *= val
+ if("/")
+ result /= val
+ if("&")
+ result &= val
+ if("|")
+ result |= val
+ if("^")
+ result ^= val
+ if("=", "==")
+ result = (result == val)
+ if("!=", "<>")
+ result = (result != val)
+ if("<")
+ result = (result < val)
+ if("<=")
+ result = (result <= val)
+ if(">")
+ result = (result > val)
+ if(">=")
+ result = (result >= val)
+ if("and", "&&")
+ result = (result && val)
+ if("or", "||")
+ result = (result || val)
+ else
+ usr << "SDQL2: Unknown op [op]"
+ result = null
+ else
+ result = val
+
+ return result
+
+/proc/SDQL_value(datum/object, list/expression, start = 1)
+ var/i = start
+ var/val = null
+
+ if(i > expression.len)
+ return list("val" = null, "i" = i)
+
+ if(istype(expression[i], /list))
+ val = SDQL_expression(object, expression[i])
+
+ else if(expression[i] == "!")
+ var/list/ret = SDQL_value(object, expression, i + 1)
+ val = !ret["val"]
+ i = ret["i"]
+
+ else if(expression[i] == "~")
+ var/list/ret = SDQL_value(object, expression, i + 1)
+ val = ~ret["val"]
+ i = ret["i"]
+
+ else if(expression[i] == "-")
+ var/list/ret = SDQL_value(object, expression, i + 1)
+ val = -ret["val"]
+ i = ret["i"]
+
+ else if(expression[i] == "null")
+ val = null
+
+ else if(isnum(expression[i]))
+ val = expression[i]
+
+ else if(copytext(expression[i], 1, 2) in list("'", "\""))
+ val = copytext(expression[i], 2, length(expression[i]))
+
+ else
+ val = SDQL_var(object, expression, i)
+ i = expression.len
+
+ return list("val" = val, "i" = i)
+
+/proc/SDQL_var(datum/object, list/expression, start = 1)
+
+ if(expression[start] in object.vars)
+
+ if(start < expression.len && expression[start + 1] == ".")
+ return SDQL_var(object.vars[expression[start]], expression[start + 2])
+
+ else
+ return object.vars[expression[start]]
+
+ else
+ return null
+
+/proc/SDQL2_tokenize(query_text)
+
+ var/list/whitespace = list(" ", "\n", "\t")
+ var/list/single = list("(", ")", ",", "+", "-", ".", ";")
+ var/list/multi = list(
+ "=" = list("", "="),
+ "<" = list("", "=", ">"),
+ ">" = list("", "="),
+ "!" = list("", "="))
+
+ var/word = ""
+ var/list/query_list = list()
+ var/len = length(query_text)
+
+ for(var/i = 1, i <= len, i++)
+ var/char = copytext(query_text, i, i + 1)
+
+ if(char in whitespace)
+ if(word != "")
+ query_list += word
+ word = ""
+
+ else if(char in single)
+ if(word != "")
+ query_list += word
+ word = ""
+
+ query_list += char
+
+ else if(char in multi)
+ if(word != "")
+ query_list += word
+ word = ""
+
+ var/char2 = copytext(query_text, i + 1, i + 2)
+
+ if(char2 in multi[char])
+ query_list += "[char][char2]"
+ i++
+
+ else
+ query_list += char
+
+ else if(char == "'")
+ if(word != "")
+ usr << "SDQL2: You have an error in your SDQL syntax, unexpected ' in query: \"[query_text]\" following \"[word]\". Please check your syntax, and try again."
+ return null
+
+ word = "'"
+
+ for(i++, i <= len, i++)
+ char = copytext(query_text, i, i + 1)
+
+ if(char == "'")
+ if(copytext(query_text, i + 1, i + 2) == "'")
+ word += "'"
+ i++
+
+ else
+ break
+
+ else
+ word += char
+
+ if(i > len)
+ usr << "SDQL2: You have an error in your SDQL syntax, unmatched ' in query: \"[query_text]\". Please check your syntax, and try again."
+ return null
+
+ query_list += "[word]'"
+ word = ""
+
+ else if(char == "\"")
+ if(word != "")
+ usr << "SDQL2: You have an error in your SDQL syntax, unexpected \" in query: \"[query_text]\" following \"[word]\". Please check your syntax, and try again."
+ return null
+
+ word = "\""
+
+ for(i++, i <= len, i++)
+ char = copytext(query_text, i, i + 1)
+
+ if(char == "\"")
+ if(copytext(query_text, i + 1, i + 2) == "'")
+ word += "\""
+ i++
+
+ else
+ break
+
+ else
+ word += char
+
+ if(i > len)
+ usr << "SDQL2: You have an error in your SDQL syntax, unmatched \" in query: \"[query_text]\". Please check your syntax, and try again."
+ return null
+
+ query_list += "[word]\""
+ word = ""
+
+ else
+ word += char
+
+ if(word != "")
+ query_list += word
+ return query_list
+
\ No newline at end of file
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
new file mode 100644
index 00000000000..007453a980d
--- /dev/null
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
@@ -0,0 +1,530 @@
+//I'm pretty sure that this is a recursive [s]descent[/s] ascent parser.
+//Spec
+//////////
+//
+// query : select_query | delete_query | update_query | call_query | explain
+// explain : 'EXPLAIN' query
+//
+// select_query : 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
+// delete_query : 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
+// update_query : 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
+// call_query : 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
+//
+// select_list : select_item [',' select_list]
+// select_item : '*' | select_function | object_type
+// select_function : count_function
+// count_function : 'COUNT' '(' '*' ')' | 'COUNT' '(' object_types ')'
+//
+// from_list : from_item [',' from_list]
+// from_item : 'world' | object_type
+//
+// call_function : ['(' [arguments] ')']
+// arguments : expression [',' arguments]
+//
+// object_type : | string
+//
+// assignments : assignment, [',' assignments]
+// assignment : '=' expression
+// variable : | '.' variable
+//
+// bool_expression : expression comparitor expression [bool_operator bool_expression]
+// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
+// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
+// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
+// value : variable | string | number | 'null'
+// unary_operator : '!' | '-' | '~'
+// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
+// bool_operator : 'AND' | '&&' | 'OR' | '||'
+//
+// string : ''' ''' | '"' '"'
+// number :
+//
+//////////
+
+/datum/SDQL_parser
+ var/query_type
+ var/error = 0
+
+ var/list/query
+ var/list/tree
+
+ var/list/select_functions = list("count")
+ var/list/boolean_operators = list("and", "or", "&&", "||")
+ var/list/unary_operators = list("!", "-", "~")
+ var/list/binary_operators = list("+", "-", "/", "*", "&", "|", "^")
+ var/list/comparitors = list("=", "==", "!=", "<>", "<", "<=", ">", ">=")
+
+/datum/SDQL_parser/New(query_list)
+ query = query_list
+
+/datum/SDQL_parser/proc/parse_error(error_message)
+ error = 1
+ usr << "SQDL2 Parsing Error: [error_message]"
+ return query.len + 1
+
+/datum/SDQL_parser/proc/parse()
+ tree = list()
+ query(1, tree)
+
+ if(error)
+ return list()
+ else
+ return tree
+
+/datum/SDQL_parser/proc/token(i)
+ if(i <= query.len)
+ return query[i]
+
+ else
+ return null
+
+/datum/SDQL_parser/proc/tokens(i, num)
+ if(i + num <= query.len)
+ return query.Copy(i, i + num)
+
+ else
+ return null
+
+/datum/SDQL_parser/proc/tokenl(i)
+ return lowertext(token(i))
+
+/datum/SDQL_parser/proc
+
+//query: select_query | delete_query | update_query
+ query(i, list/node)
+ query_type = tokenl(i)
+
+ switch(query_type)
+ if("select")
+ select_query(i, node)
+
+ if("delete")
+ delete_query(i, node)
+
+ if("update")
+ update_query(i, node)
+
+ if("call")
+ call_query(i, node)
+
+ if("explain")
+ node += "explain"
+ node["explain"] = list()
+ query(i + 1, node["explain"])
+
+
+// select_query: 'SELECT' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
+ select_query(i, list/node)
+ var/list/select = list()
+ i = select_list(i + 1, select)
+
+ node += "select"
+ node["select"] = select
+
+ var/list/from = list()
+ if(tokenl(i) in list("from", "in"))
+ i = from_list(i + 1, from)
+ else
+ from += "world"
+
+ node += "from"
+ node["from"] = from
+
+ if(tokenl(i) == "where")
+ var/list/where = list()
+ i = bool_expression(i + 1, where)
+
+ node += "where"
+ node["where"] = where
+
+ return i
+
+
+//delete_query: 'DELETE' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]
+ delete_query(i, list/node)
+ var/list/select = list()
+ i = select_list(i + 1, select)
+
+ node += "delete"
+ node["delete"] = select
+
+ var/list/from = list()
+ if(tokenl(i) in list("from", "in"))
+ i = from_list(i + 1, from)
+ else
+ from += "world"
+
+ node += "from"
+ node["from"] = from
+
+ if(tokenl(i) == "where")
+ var/list/where = list()
+ i = bool_expression(i + 1, where)
+
+ node += "where"
+ node["where"] = where
+
+ return i
+
+
+//update_query: 'UPDATE' select_list [('FROM' | 'IN') from_list] 'SET' assignments ['WHERE' bool_expression]
+ update_query(i, list/node)
+ var/list/select = list()
+ i = select_list(i + 1, select)
+
+ node += "update"
+ node["update"] = select
+
+ var/list/from = list()
+ if(tokenl(i) in list("from", "in"))
+ i = from_list(i + 1, from)
+ else
+ from += "world"
+
+ node += "from"
+ node["from"] = from
+
+ if(tokenl(i) != "set")
+ i = parse_error("UPDATE has misplaced SET")
+
+ var/list/set_assignments = list()
+ i = assignments(i + 1, set_assignments)
+
+ node += "set"
+ node["set"] = set_assignments
+
+ if(tokenl(i) == "where")
+ var/list/where = list()
+ i = bool_expression(i + 1, where)
+
+ node += "where"
+ node["where"] = where
+
+ return i
+
+
+//call_query: 'CALL' call_function ['ON' select_list [('FROM' | 'IN') from_list] ['WHERE' bool_expression]]
+ call_query(i, list/node)
+ var/list/func = list()
+ var/list/arguments = list()
+ i = call_function(i + 1, func, arguments)
+
+ node += "call"
+ node["call"] = func
+ node["args"] = arguments
+
+ if(tokenl(i) != "on")
+ return i
+
+ var/list/select = list()
+ i = select_list(i + 1, select)
+
+ node += "on"
+ node["on"] = select
+
+ var/list/from = list()
+ if(tokenl(i) in list("from", "in"))
+ i = from_list(i + 1, from)
+ else
+ from += "world"
+
+ node += "from"
+ node["from"] = from
+
+ if(tokenl(i) == "where")
+ var/list/where = list()
+ i = bool_expression(i + 1, where)
+
+ node += "where"
+ node["where"] = where
+
+ return i
+
+
+//select_list: select_item [',' select_list]
+ select_list(i, list/node)
+ i = select_item(i, node)
+
+ if(token(i) == ",")
+ i = select_list(i + 1, node)
+
+ return i
+
+
+//from_list: from_item [',' from_list]
+ from_list(i, list/node)
+ i = from_item(i, node)
+
+ if(token(i) == ",")
+ i = from_list(i + 1, node)
+
+ return i
+
+
+//assignments: assignment, [',' assignments]
+ assignments(i, list/node)
+ i = assignment(i, node)
+
+ if(token(i) == ",")
+ i = assignments(i + 1, node)
+
+ return i
+
+
+//select_item: '*' | select_function | object_type
+ select_item(i, list/node)
+
+ if(token(i) == "*")
+ node += "*"
+ i++
+
+ else if(tokenl(i) in select_functions)
+ i = select_function(i, node)
+
+ else
+ i = object_type(i, node)
+
+ return i
+
+
+//from_item: 'world' | object_type
+ from_item(i, list/node)
+
+ if(token(i) == "world")
+ node += "world"
+ i++
+
+ else
+ i = object_type(i, node)
+
+ return i
+
+
+//bool_expression: expression [bool_operator bool_expression]
+ bool_expression(i, list/node)
+
+ var/list/bool = list()
+ i = expression(i, bool)
+
+ node[++node.len] = bool
+
+ if(tokenl(i) in boolean_operators)
+ i = bool_operator(i, node)
+ i = bool_expression(i, node)
+
+ return i
+
+
+//assignment: '=' expression
+ assignment(i, list/node)
+
+ node += token(i)
+
+ if(token(i + 1) == "=")
+ var/varname = token(i)
+ node[varname] = list()
+
+ i = expression(i + 2, node[varname])
+
+ else
+ parse_error("Assignment expected, but no = found")
+
+ return i
+
+
+//variable: | '.' variable
+ variable(i, list/node)
+ var/list/L = list(token(i))
+ node[++node.len] = L
+
+ if(token(i + 1) == ".")
+ L += "."
+ i = variable(i + 2, L)
+
+ else
+ i++
+
+ return i
+
+
+//object_type: | string
+ object_type(i, list/node)
+
+ if(copytext(token(i), 1, 2) == "/")
+ node += token(i)
+
+ else
+ i = string(i, node)
+
+ return i + 1
+
+
+//comparitor: '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
+ comparitor(i, list/node)
+
+ if(token(i) in list("=", "==", "!=", "<>", "<", "<=", ">", ">="))
+ node += token(i)
+
+ else
+ parse_error("Unknown comparitor [token(i)]")
+
+ return i + 1
+
+
+//bool_operator: 'AND' | '&&' | 'OR' | '||'
+ bool_operator(i, list/node)
+
+ if(tokenl(i) in list("and", "or", "&&", "||"))
+ node += token(i)
+
+ else
+ parse_error("Unknown comparitor [token(i)]")
+
+ return i + 1
+
+
+//string: ''' ''' | '"' '"'
+ string(i, list/node)
+
+ if(copytext(token(i), 1, 2) in list("'", "\""))
+ node += token(i)
+
+ else
+ parse_error("Expected string but found '[token(i)]'")
+
+ return i + 1
+
+
+//call_function: ['(' [arguments] ')']
+ call_function(i, list/node, list/arguments)
+ if(length(tokenl(i)))
+ node += token(i++)
+ if(token(i) != "(")
+ parse_error("Expected ( but found '[token(i)]'")
+ else if(token(i + 1) != ")")
+ do
+ i = expression(i + 1, arguments)
+ if(token(i) == ",")
+ continue
+ while(token(i) && token(i) != ")")
+ else
+ i++
+ else
+ parse_error("Expected a function but found nothing")
+ return i + 1
+
+
+//select_function: count_function
+ select_function(i, list/node)
+
+ parse_error("Sorry, function calls aren't available yet")
+
+ return i
+
+
+//expression: ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
+ expression(i, list/node)
+
+ if(token(i) in unary_operators)
+ i = unary_expression(i, node)
+
+ else if(token(i) == "(")
+ var/list/expr = list()
+
+ i = expression(i + 1, expr)
+
+ if(token(i) != ")")
+ parse_error("Missing ) at end of expression.")
+
+ else
+ i++
+
+ node[++node.len] = expr
+
+ else
+ i = value(i, node)
+
+ if(token(i) in binary_operators)
+ i = binary_operator(i, node)
+ i = expression(i, node)
+
+ else if(token(i) in comparitors)
+ i = binary_operator(i, node)
+
+ var/list/rhs = list()
+ i = expression(i, rhs)
+
+ node[++node.len] = rhs
+
+
+ return i
+
+
+//unary_expression: unary_operator ( unary_expression | value | '(' expression ')' )
+ unary_expression(i, list/node)
+
+ if(token(i) in unary_operators)
+ var/list/unary_exp = list()
+
+ unary_exp += token(i)
+ i++
+
+ if(token(i) in unary_operators)
+ i = unary_expression(i, unary_exp)
+
+ else if(token(i) == "(")
+ var/list/expr = list()
+
+ i = expression(i + 1, expr)
+
+ if(token(i) != ")")
+ parse_error("Missing ) at end of expression.")
+
+ else
+ i++
+
+ unary_exp[++unary_exp.len] = expr
+
+ else
+ i = value(i, unary_exp)
+
+ node[++node.len] = unary_exp
+
+
+ else
+ parse_error("Expected unary operator but found '[token(i)]'")
+
+ return i
+
+
+//binary_operator: comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
+ binary_operator(i, list/node)
+
+ if(token(i) in (binary_operators + comparitors))
+ node += token(i)
+
+ else
+ parse_error("Unknown binary operator [token(i)]")
+
+ return i + 1
+
+
+//value: variable | string | number | 'null'
+ value(i, list/node)
+
+ if(token(i) == "null")
+ node += "null"
+ i++
+
+ else if(isnum(text2num(token(i))))
+ node += text2num(token(i))
+ i++
+
+ else if(copytext(token(i), 1, 2) in list("'", "\""))
+ i = string(i, node)
+
+ else
+ i = variable(i, node)
+
+ return i
+/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/
diff --git a/code/modules/admin/verbs/check_customitem_activity.dm b/code/modules/admin/verbs/check_customitem_activity.dm
deleted file mode 100644
index 18a796a0b08..00000000000
--- a/code/modules/admin/verbs/check_customitem_activity.dm
+++ /dev/null
@@ -1,85 +0,0 @@
-var/checked_for_inactives = 0
-var/inactive_keys = "None
"
-
-/client/proc/check_customitem_activity()
- set category = "Admin"
- set name = "Check activity of players with custom items"
-
- var/dat = "Inactive players with custom items
"
- dat += "
"
- dat += "The list below contains players with custom items that have not logged\
- in for the past two months, or have not logged in since this system was implemented.\
- This system requires the feedback SQL database to be properly setup and linked.
"
- dat += "
"
- dat += "Populating this list is done automatically, but must be manually triggered on a per\
- round basis. Populating the list may cause a lag spike, so use it sparingly.
"
- dat += "
"
- if(checked_for_inactives)
- dat += inactive_keys
- dat += "
"
- dat += "This system was implemented on March 1 2013, and the database a few days before that. Root server access is required to add or disable access to specific custom items.
"
- else
- dat += "Populate list (requires an active database connection)
"
-
- usr << browse(dat, "window=inactive_customitems;size=600x480")
-
-/proc/populate_inactive_customitems_list(var/client/C)
- //set background = 1
-
- if(checked_for_inactives)
- return
-
- establish_db_connection()
- if(!dbcon.IsConnected())
- return
-
- //grab all ckeys associated with custom items
- var/list/ckeys_with_customitems = list()
-
- var/file = file2text("config/custom_items.txt")
- var/lines = text2list(file, "\n")
-
- for(var/line in lines)
- // split & clean up
- var/list/Entry = text2list(line, ":")
- for(var/i = 1 to Entry.len)
- Entry[i] = trim(Entry[i])
-
- if(Entry.len < 1)
- continue
-
- var/cur_key = Entry[1]
- if(!ckeys_with_customitems.Find(cur_key))
- ckeys_with_customitems.Add(cur_key)
-
- //run a query to get all ckeys inactive for over 2 months
- var/list/inactive_ckeys = list()
- if(ckeys_with_customitems.len)
- var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey, lastseen FROM [format_table_name("player")] WHERE datediff(Now(), lastseen) > 60")
- query_inactive.Execute()
- while(query_inactive.NextRow())
- var/cur_ckey = query_inactive.item[1]
- //if the ckey has a custom item attached, output it
- if(ckeys_with_customitems.Find(cur_ckey))
- ckeys_with_customitems.Remove(cur_ckey)
- inactive_ckeys[cur_ckey] = "last seen on [query_inactive.item[2]]"
-
- //if there are ckeys left over, check whether they have a database entry at all
- if(ckeys_with_customitems.len)
- for(var/cur_ckey in ckeys_with_customitems)
- var/DBQuery/query_inactive = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[cur_ckey]'")
- query_inactive.Execute()
- if(!query_inactive.RowCount())
- inactive_ckeys += cur_ckey
-
- if(inactive_ckeys.len)
- inactive_keys = ""
- for(var/cur_key in inactive_ckeys)
- if(inactive_ckeys[cur_key])
- inactive_keys += "[cur_key] - [inactive_ckeys[cur_key]]
"
- else
- inactive_keys += "[cur_key] - no database entry
"
-
- checked_for_inactives = 1
- if(C)
- C.check_customitem_activity()
diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm
index 453e6d81f69..22d6d4b2a7a 100644
--- a/code/modules/admin/verbs/deadsay.dm
+++ b/code/modules/admin/verbs/deadsay.dm
@@ -20,13 +20,13 @@
var/stafftype = null
- if (src.holder.rights & R_MENTOR)
+ if (check_rights(R_MENTOR, 0))
stafftype = "MENTOR"
- if (src.holder.rights & R_MOD)
+ if (check_rights(R_MOD, 0))
stafftype = "MOD"
- if (src.holder.rights & R_ADMIN)
+ if (check_rights(R_ADMIN, 0))
stafftype = "ADMIN"
msg = sanitize(copytext(msg, 1, MAX_MESSAGE_LEN))
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 2dd0e2adb71..542a02ee231 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -1,7 +1,9 @@
/client/proc/Debug2()
set category = "Debug"
set name = "Debug-Game"
- if(!check_rights(R_DEBUG)) return
+
+ if(!check_rights(R_DEBUG))
+ return
if(Debug2)
Debug2 = 0
@@ -28,7 +30,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set category = "Debug"
set name = "Advanced ProcCall"
- if(!check_rights(R_DEBUG)) return
+ if(!check_rights(R_PROCCALL))
+ return
spawn(0)
var/target = null
@@ -94,7 +97,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set category = "Debug"
set name = "Atom ProcCall"
- if(!check_rights(R_DEBUG))
+ if(!check_rights(R_PROCCALL))
return
var/procname = input("Proc name, eg: fake_blood","Proc:", null) as text|null
@@ -180,6 +183,10 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/Cell()
set category = "Debug"
set name = "Air Status in Location"
+
+ if(!check_rights(R_DEBUG))
+ return
+
if(!mob)
return
var/turf/T = mob.loc
@@ -201,6 +208,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_robotize(var/mob/M in mob_list)
set category = "Event"
set name = "Make Robot"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -216,6 +226,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_animalize(var/mob/M in mob_list)
set category = "Event"
set name = "Make Simple Animal"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -238,6 +251,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set category = "Event"
set name = "Make pAI"
set desc = "Specify a location to spawn a pAI device, then specify a key to play that pAI"
+
+ if(!check_rights(R_SPAWN))
+ return
var/list/available = list()
for(var/mob/C in mob_list)
@@ -264,6 +280,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_alienize(var/mob/M in mob_list)
set category = "Event"
set name = "Make Alien"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -281,6 +300,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_slimeize(var/mob/M in mob_list)
set category = "Event"
set name = "Make slime"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -298,6 +320,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_super(var/mob/M in mob_list)
set category = "Event"
set name = "Make Superhero"
+
+ if(!check_rights(R_SPAWN))
+ return
if(!ticker)
alert("Wait until the game starts")
@@ -312,102 +337,14 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
else
alert("Invalid mob")
-/*
-/client/proc/cmd_admin_monkeyize(var/mob/M in world)
- set category = "Event"
- set name = "Make Monkey"
-
- if(!ticker)
- alert("Wait until the game starts")
- return
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/target = M
- log_admin("[key_name(src)] is attempting to monkeyize [M.key].")
- spawn(10)
- target.monkeyize()
- else
- alert("Invalid mob")
-
-/client/proc/cmd_admin_changelinginize(var/mob/M in world)
- set category = "Event"
- set name = "Make Changeling"
-
- if(!ticker)
- alert("Wait until the game starts")
- return
- if(istype(M, /mob/living/carbon/human))
- log_admin("[key_name(src)] has made [M.key] a changeling.")
- spawn(10)
- M.absorbed_dna[M.real_name] = M.dna.Clone()
- M.make_changeling()
- if(M.mind)
- M.mind.special_role = "Changeling"
- else
- alert("Invalid mob")
-*/
-/*
-/client/proc/cmd_admin_abominize(var/mob/M in world)
- set category = null
- set name = "Make Abomination"
-
- usr << "Ruby Mode disabled. Command aborted."
- return
- if(!ticker)
- alert("Wait until the game starts.")
- return
- if(istype(M, /mob/living/carbon/human))
- log_admin("[key_name(src)] has made [M.key] an abomination.")
-
- // spawn(10)
- // M.make_abomination()
-
-*/
-/*
-/client/proc/make_cultist(var/mob/M in world) // -- TLE, modified by Urist
- set category = "Event"
- set name = "Make Cultist"
- set desc = "Makes target a cultist"
- if(!cultwords["travel"])
- runerandom()
- if(M)
- if(M.mind in ticker.mode.cult)
- return
- else
- if(alert("Spawn that person a tome?",,"Yes","No")=="Yes")
- M << "\red You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie. A tome, a message from your new master, appears on the ground."
- new /obj/item/weapon/tome(M.loc)
- else
- M << "\red You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie."
- var/glimpse=pick("1","2","3","4","5","6","7","8")
- switch(glimpse)
- if("1")
- M << "\red You remembered one thing from the glimpse... [cultwords["travel"]] is travel..."
- if("2")
- M << "\red You remembered one thing from the glimpse... [cultwords["blood"]] is blood..."
- if("3")
- M << "\red You remembered one thing from the glimpse... [cultwords["join"]] is join..."
- if("4")
- M << "\red You remembered one thing from the glimpse... [cultwords["hell"]] is Hell..."
- if("5")
- M << "\red You remembered one thing from the glimpse... [cultwords["destroy"]] is destroy..."
- if("6")
- M << "\red You remembered one thing from the glimpse... [cultwords["technology"]] is technology..."
- if("7")
- M << "\red You remembered one thing from the glimpse... [cultwords["self"]] is self..."
- if("8")
- M << "\red You remembered one thing from the glimpse... [cultwords["see"]] is see..."
-
- if(M.mind)
- M.mind.special_role = "Cultist"
- ticker.mode.cult += M.mind
- src << "Made [M] a cultist."
-*/
-
//TODO: merge the vievars version into this or something maybe mayhaps
/client/proc/cmd_debug_del_all()
set category = "Debug"
set name = "Del-All"
+ if(!check_rights(R_DEBUG))
+ return
+
// to prevent REALLY stupid deletions
var/blocked = list(/mob/living, /mob/living/carbon, /mob/living/carbon/human, /mob/dead, /mob/dead/observer, /mob/living/silicon, /mob/living/silicon/robot, /mob/living/silicon/ai)
var/hsbitem = input(usr, "Choose an object to delete.", "Delete:") as null|anything in subtypesof(/obj) + subtypesof(/mob) - blocked
@@ -422,6 +359,10 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_debug_make_powernets()
set category = "Debug"
set name = "Make Powernets"
+
+ if(!check_rights(R_DEBUG))
+ return
+
makepowernets()
log_admin("[key_name(src)] has remade the powernet. makepowernets() called.")
message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.", 0)
@@ -430,6 +371,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_grantfullaccess(var/mob/M in mob_list)
set category = "Admin"
set name = "Grant Full Access"
+
+ if(!check_rights(R_EVENT))
+ return
if (!ticker)
alert("Wait until the game starts")
@@ -463,7 +407,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set name = "Assume direct control"
set desc = "Direct intervention"
- if(!check_rights(R_DEBUG|R_ADMIN)) return
+ if(!check_rights(R_DEBUG|R_ADMIN))
+ return
+
if(M.ckey)
if(alert("This mob is being controlled by [M.ckey]. Are you sure you wish to assume control of it? [M.ckey] will be made a ghost.",,"Yes","No") != "Yes")
return
@@ -482,6 +428,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_areatest()
set category = "Mapping"
set name = "Test areas"
+
+ if(!check_rights(R_DEBUG))
+ return
var/list/areas_all = list()
var/list/areas_with_APC = list()
@@ -570,9 +519,14 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_dress(var/mob/living/carbon/human/M in mob_list)
set category = "Event"
set name = "Select equipment"
+
+ if(!check_rights(R_EVENT))
+ return
+
if(!ishuman(M))
alert("Invalid mob")
return
+
//log_admin("[key_name(src)] has alienized [M.key].")
var/list/dresspacks = list(
"strip",
@@ -1106,11 +1060,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return
/client/proc/startSinglo()
-
set category = "Debug"
set name = "Start Singularity"
set desc = "Sets up the singularity and all machines to get power flowing through the station"
+ if(!check_rights(R_DEBUG))
+ return
+
if(alert("Are you sure? This will start up the engine. Should only be used during debug!",,"Yes","No") != "Yes")
return
@@ -1160,6 +1116,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
set category = "Debug"
set name = "Debug Mob Lists"
set desc = "For when you just gotta know"
+
+ if(!check_rights(R_DEBUG))
+ return
switch(input("Which list?") in list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Silicons","Clients","Respawnable Mobs"))
if("Players")
@@ -1181,6 +1140,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/cmd_admin_toggle_block(var/mob/M,var/block)
+ if(!check_rights(R_SPAWN))
+ return
+
if(!ticker)
alert("Wait until the game starts")
return
@@ -1194,4 +1156,3 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!")
else
alert("Invalid mob")
-
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 5acf6c21b44..cc7f9f1befa 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -40,14 +40,15 @@ var/intercom_range_display_status = 0
/client/proc/camera_view()
set category = "Mapping"
set name = "Camera Range Display"
+
+ if(!check_rights(R_DEBUG))
+ return
if(camera_range_display_status)
camera_range_display_status = 0
else
camera_range_display_status = 1
-
-
for(var/obj/effect/debugging/camera_range/C in world)
del(C)
@@ -56,15 +57,12 @@ var/intercom_range_display_status = 0
new/obj/effect/debugging/camera_range(C.loc)
feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-
/client/proc/sec_camera_report()
set category = "Mapping"
set name = "Camera Report"
-
- if(!master_controller)
- alert(usr,"Master_controller not found.","Sec Camera Report")
- return 0
+
+ if(!check_rights(R_DEBUG))
+ return
var/list/obj/machinery/camera/CL = list()
@@ -101,6 +99,9 @@ var/intercom_range_display_status = 0
/client/proc/intercom_view()
set category = "Mapping"
set name = "Intercom Range Display"
+
+ if(!check_rights(R_DEBUG))
+ return
if(intercom_range_display_status)
intercom_range_display_status = 0
@@ -119,26 +120,24 @@ var/intercom_range_display_status = 0
feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
var/list/admin_verbs_show_debug_verbs = list(
- /client/proc/camera_view, //-errorage
- /client/proc/sec_camera_report, //-errorage
- /client/proc/intercom_view, //-errorage
+ /client/proc/camera_view,
+ /client/proc/sec_camera_report,
+ /client/proc/intercom_view,
/client/proc/Cell, //More air things
/client/proc/atmosscan, //check plumbing
/client/proc/powerdebug, //check power
/client/proc/count_objects_on_z_level,
/client/proc/count_objects_all,
- /client/proc/cmd_assume_direct_control, //-errorage
+ /client/proc/cmd_assume_direct_control,
/client/proc/startSinglo,
/client/proc/ticklag,
/client/proc/cmd_admin_grantfullaccess,
-// /client/proc/splash,
/client/proc/cmd_admin_areatest,
/client/proc/cmd_admin_rejuvenate,
/datum/admins/proc/show_traitor_panel,
/client/proc/print_jobban_old,
/client/proc/print_jobban_old_filter,
/client/proc/forceEvent,
- ///client/proc/cmd_admin_rejuvenate,
/client/proc/nanomapgen_DumpImage
)
@@ -146,7 +145,8 @@ var/list/admin_verbs_show_debug_verbs = list(
set category = "Debug"
set name = "Debug verbs"
- if(!check_rights(R_DEBUG)) return
+ if(!check_rights(R_DEBUG))
+ return
verbs += admin_verbs_show_debug_verbs
@@ -155,6 +155,10 @@ var/list/admin_verbs_show_debug_verbs = list(
/client/proc/count_objects_on_z_level()
set category = "Mapping"
set name = "Count Objects On Level"
+
+ if(!check_rights(R_DEBUG))
+ return
+
var/level = input("Which z-level?","Level?") as text
if(!level) return
var/num_level = text2num(level)
@@ -182,22 +186,16 @@ var/list/admin_verbs_show_debug_verbs = list(
if(B.z == num_level)
count++
atom_list += A
- /*
- var/atom/temp_atom
- for(var/i = 0; i <= (atom_list.len/10); i++)
- var/line = ""
- for(var/j = 1; j <= 10; j++)
- if(i*10+j <= atom_list.len)
- temp_atom = atom_list[i*10+j]
- line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; "
- world << line*/
- world << "There are [count] objects of type [type_path] on z-level [num_level]"
+ world << "There are [count] objects of type [type_path] on z-level [num_level]."
feedback_add_details("admin_verb","mOBJZ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/count_objects_all()
set category = "Mapping"
set name = "Count Objects All"
+
+ if(!check_rights(R_DEBUG))
+ return
var/type_text = input("Which type path?","") as text
if(!type_text) return
@@ -209,15 +207,6 @@ var/list/admin_verbs_show_debug_verbs = list(
for(var/atom/A in world)
if(istype(A,type_path))
count++
- /*
- var/atom/temp_atom
- for(var/i = 0; i <= (atom_list.len/10); i++)
- var/line = ""
- for(var/j = 1; j <= 10; j++)
- if(i*10+j <= atom_list.len)
- temp_atom = atom_list[i*10+j]
- line += " no.[i+10+j]@\[[temp_atom.x], [temp_atom.y], [temp_atom.z]\]; "
- world << line*/
- world << "There are [count] objects of type [type_path] in the game world"
+ world << "There are [count] objects of type [type_path] in the game world."
feedback_add_details("admin_verb","mOBJ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 37110c3c237..a49cd02c06b 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1,8 +1,8 @@
/client/proc/cmd_admin_drop_everything(mob/M as mob in mob_list)
set category = null
set name = "Drop Everything"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_DEBUG|R_ADMIN))
return
var/confirm = alert(src, "Make [M] drop everything?", "Message", "Yes", "No")
@@ -19,9 +19,10 @@
/client/proc/cmd_admin_prison(mob/M as mob in mob_list)
set category = "Admin"
set name = "Prison"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_ADMIN))
return
+
if (ismob(M))
if(istype(M, /mob/living/silicon/ai))
alert("The AI can't be sent to prison you jerk!", null, null, null, null, null)
@@ -47,9 +48,11 @@
set category = "Event"
set name = "Subtle Message"
- if(!ismob(M)) return
+ if(!ismob(M))
+ return
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
var/msg = input("Message:", text("Subtle PM to [M.key]")) as text
@@ -67,8 +70,9 @@
/client/proc/cmd_mentor_check_new_players() //Allows mentors / admins to determine who the newer players are.
set category = "Admin"
set name = "Check new Players"
- if(!holder)
- src << "Only staff members may use this command."
+
+ if(!check_rights(R_MENTOR|R_MOD|R_ADMIN))
+ return
var/age = alert(src, "Age check", "Show accounts yonger then _____ days","7", "30" , "All")
@@ -99,7 +103,8 @@
set category = "Event"
set name = "Global Narrate"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
var/msg = input("Message:", text("Enter the text you wish to appear to everyone:")) as text
@@ -114,7 +119,8 @@
set category = "Event"
set name = "Direct Narrate"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
if(!M)
M = input("Direct narrate to who?", "Active Players") as null|anything in get_mob_with_client_list()
@@ -135,9 +141,10 @@
/client/proc/cmd_admin_godmode(mob/M as mob in mob_list)
set category = "Special Verbs"
set name = "Godmode"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_ADMIN))
return
+
M.status_flags ^= GODMODE
usr << "\blue Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]"
@@ -148,7 +155,8 @@
proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
if(automute)
- if(!config.automute_on) return
+ if(!config.automute_on)
+ return
else
if(!usr || !usr.client)
return
@@ -157,7 +165,8 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
return
if(!M.client)
usr << "Error: cmd_admin_mute: This mob doesn't have a client tied to it."
- if(!M.client) return
+ if(!M.client)
+ return
var/muteunmute
var/mute_string
@@ -195,9 +204,10 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
/client/proc/cmd_admin_add_random_ai_law()
set category = "Event"
set name = "Add Random AI Law"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_EVENT))
return
+
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
log_admin("[key_name(src)] has added a random AI law.")
@@ -209,105 +219,14 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0)
new /datum/event/ion_storm(0, announce_ion_laws)
feedback_add_details("admin_verb","ION") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
-//I use this proc for respawn character too. /N
-/proc/create_xeno(ckey)
- if(!ckey)
- var/list/candidates = list()
- for(var/mob/M in player_list)
- if(M.stat != DEAD) continue //we are not dead!
- if(!M.client.prefs.be_special & BE_ALIEN) continue //we don't want to be an alium
- if(jobban_isbanned(M, "alien") || jobban_isbanned(M, "Syndicate")) continue //we are jobbanned
- if(M.client.is_afk()) continue //we are afk
- if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to
- candidates += M.ckey
- if(candidates.len)
- ckey = input("Pick the player you want to respawn as a xeno.", "Suitable Candidates") as null|anything in candidates
- else
- usr << "Error: create_xeno(): no suitable candidates."
- if(!istext(ckey)) return 0
-
- var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva")
- var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin)
- var/mob/living/carbon/alien/new_xeno
- switch(alien_caste)
- if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen/large(spawn_here)
- if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(spawn_here)
- if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(spawn_here)
- if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(spawn_here)
- if("Larva") new_xeno = new /mob/living/carbon/alien/larva(spawn_here)
- else return 0
-
- new_xeno.ckey = ckey
- message_admins("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1)
- return 1
-
-/*
-Allow admins to set players to be able to respawn/bypass 30 min wait, without the admin having to edit variables directly
-Ccomp's first proc.
-*/
-
-/client/proc/get_ghosts(var/notify = 0,var/what = 2)
- // what = 1, return ghosts ass list.
- // what = 2, return mob list
-
- var/list/mobs = list()
- var/list/ghosts = list()
- var/list/sortmob = sortAtom(mob_list) // get the mob list.
- /var/any=0
- for(var/mob/dead/observer/M in sortmob)
- mobs.Add(M) //filter it where it's only ghosts
- any = 1 //if no ghosts show up, any will just be 0
- if(!any)
- if(notify)
- src << "There doesn't appear to be any ghosts for you to select."
- return
-
- for(var/mob/M in mobs)
- var/name = M.name
- ghosts[name] = M //get the name of the mob for the popup list
- if(what==1)
- return ghosts
- else
- return mobs
-/*
-
-/client/proc/allow_character_respawn()
- set category = "Special Verbs"
- set name = "Allow player to respawn"
- set desc = "Let's the player bypass the 30 minute wait to respawn or allow them to re-enter their corpse."
- if(!holder)
- src << "Only administrators may use this command."
- var/list/ghosts= get_ghosts(1,1)
-
- var/target = input("Please, select a ghost!", "COME BACK TO LIFE!", null, null) as null|anything in ghosts
- if(!target)
- src << "Hrm, appears you didn't select a ghost" // Sanity check, if no ghosts in the list we don't want to edit a null variable and cause a runtime error.
- return
-
- var/mob/dead/observer/G = ghosts[target]
- if(G.has_enabled_antagHUD && config.antag_hud_restricted)
- var/response = alert(src, "Are you sure you wish to allow this individual to play?","Ghost has used AntagHUD","Yes","No")
- if(response == "No") return
- G.timeofdeath=-19999 /* time of death is checked in /mob/verb/abandon_mob() which is the Respawn verb.
- timeofdeath is used for bodies on autopsy but since we're messing with a ghost I'm pretty sure
- there won't be an autopsy.
- */
- G.has_enabled_antagHUD = 2
- G.can_reenter_corpse = 1
-
- G:show_message(text("\blue You may now respawn. You should roleplay as if you learned nothing about the round during your time with the dead."), 1)
- log_admin("[key_name(usr)] allowed [key_name(G)] to bypass the 30 minute respawn limit")
- message_admins("Admin [key_name_admin(usr)] allowed [key_name_admin(G)] to bypass the 30 minute respawn limit", 1)
-
-
/client/proc/toggle_antagHUD_use()
set category = "Server"
set name = "Toggle antagHUD usage"
set desc = "Toggles antagHUD usage for observers"
- if(!holder)
- src << "Only administrators may use this command."
+ if(!check_rights(R_SERVER))
+ return
+
var/action=""
if(config.antag_hud_allowed)
for(var/mob/dead/observer/g in get_ghosts())
@@ -333,14 +252,14 @@ Ccomp's first proc.
log_admin("[key_name(usr)] has [action] antagHUD usage for observers")
message_admins("Admin [key_name_admin(usr)] has [action] antagHUD usage for observers", 1)
-
-
/client/proc/toggle_antagHUD_restrictions()
set category = "Server"
set name = "Toggle antagHUD Restrictions"
set desc = "Restricts players that have used antagHUD from being able to join this round."
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_SERVER))
+ return
+
var/action=""
if(config.antag_hud_restricted)
for(var/mob/dead/observer/g in get_ghosts())
@@ -360,7 +279,6 @@ Ccomp's first proc.
log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD")
message_admins("Admin [key_name_admin(usr)] has [action] on joining the round if they use AntagHUD", 1)
-*/
/*
If a guy was gibbed and you want to revive him, this is a good way to do so.
@@ -371,9 +289,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Special Verbs"
set name = "Respawn Character"
set desc = "Respawn a person that has been gibbed/dusted/killed. They must be a ghost for this to work and preferably should not have a body to go back into."
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_SPAWN))
return
+
var/input = ckey(input(src, "Please specify which key will be respawned.", "Key", ""))
if(!input)
return
@@ -519,71 +438,70 @@ Traitors and the like can also be revived with the previous role mostly intact.
feedback_add_details("admin_verb","RSPCH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return new_character
-/client/proc/toggle_antagHUD_use()
- set category = "Server"
- set name = "Toggle antagHUD usage"
- set desc = "Toggles antagHUD usage for observers"
+//I use this proc for respawn character too. /N
+/proc/create_xeno(ckey)
+ if(!ckey)
+ var/list/candidates = list()
+ for(var/mob/M in player_list)
+ if(M.stat != DEAD) continue //we are not dead!
+ if(!M.client.prefs.be_special & BE_ALIEN) continue //we don't want to be an alium
+ if(jobban_isbanned(M, "alien") || jobban_isbanned(M, "Syndicate")) continue //we are jobbanned
+ if(M.client.is_afk()) continue //we are afk
+ if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to
+ candidates += M.ckey
+ if(candidates.len)
+ ckey = input("Pick the player you want to respawn as a xeno.", "Suitable Candidates") as null|anything in candidates
+ else
+ usr << "Error: create_xeno(): no suitable candidates."
+ if(!istext(ckey)) return 0
- if(!holder)
- src << "Only administrators may use this command."
- var/action=""
- if(config.antag_hud_allowed)
- for(var/mob/dead/observer/g in get_ghosts())
- if(!g.client.holder) //Remove the verb from non-admin ghosts
- g.verbs -= /mob/dead/observer/verb/toggle_antagHUD
- if(g.antagHUD)
- g.antagHUD = 0 // Disable it on those that have it enabled
- g.has_enabled_antagHUD = 2 // We'll allow them to respawn
- g << "\red The Administrator has disabled AntagHUD "
- config.antag_hud_allowed = 0
- src << "\red AntagHUD usage has been disabled"
- action = "disabled"
+ var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva")
+ var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin)
+ var/mob/living/carbon/alien/new_xeno
+ switch(alien_caste)
+ if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen/large(spawn_here)
+ if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(spawn_here)
+ if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(spawn_here)
+ if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(spawn_here)
+ if("Larva") new_xeno = new /mob/living/carbon/alien/larva(spawn_here)
+ else return 0
+
+ new_xeno.ckey = ckey
+ message_admins("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1)
+ return 1
+
+
+/client/proc/get_ghosts(var/notify = 0,var/what = 2)
+ // what = 1, return ghosts ass list.
+ // what = 2, return mob list
+
+ var/list/mobs = list()
+ var/list/ghosts = list()
+ var/list/sortmob = sortAtom(mob_list) // get the mob list.
+ /var/any=0
+ for(var/mob/dead/observer/M in sortmob)
+ mobs.Add(M) //filter it where it's only ghosts
+ any = 1 //if no ghosts show up, any will just be 0
+ if(!any)
+ if(notify)
+ src << "There doesn't appear to be any ghosts for you to select."
+ return
+
+ for(var/mob/M in mobs)
+ var/name = M.name
+ ghosts[name] = M //get the name of the mob for the popup list
+ if(what==1)
+ return ghosts
else
- for(var/mob/dead/observer/g in get_ghosts())
- if(!g.client.holder) // Add the verb back for all non-admin ghosts
- g.verbs += /mob/dead/observer/verb/toggle_antagHUD
- g << "\blue The Administrator has enabled AntagHUD " // Notify all observers they can now use AntagHUD
- config.antag_hud_allowed = 1
- action = "enabled"
- src << "\blue AntagHUD usage has been enabled"
-
-
- log_admin("[key_name(usr)] has [action] antagHUD usage for observers")
- message_admins("Admin [key_name_admin(usr)] has [action] antagHUD usage for observers", 1)
-
-
-/client/proc/toggle_antagHUD_restrictions()
- set category = "Server"
- set name = "Toggle antagHUD Restrictions"
- set desc = "Restricts players that have used antagHUD from being able to join this round."
- if(!holder)
- src << "Only administrators may use this command."
- var/action=""
- if(config.antag_hud_restricted)
- for(var/mob/dead/observer/g in get_ghosts())
- g << "\blue The administrator has lifted restrictions on joining the round if you use AntagHUD"
- action = "lifted restrictions"
- config.antag_hud_restricted = 0
- src << "\blue AntagHUD restrictions have been lifted"
- else
- for(var/mob/dead/observer/g in get_ghosts())
- g << "\red The administrator has placed restrictions on joining the round if you use AntagHUD"
- g << "\red Your AntagHUD has been disabled, you may choose to re-enabled it but will be under restrictions "
- g.antagHUD = 0
- g.has_enabled_antagHUD = 0
- action = "placed restrictions"
- config.antag_hud_restricted = 1
- src << "\red AntagHUD restrictions have been enabled"
-
- log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD")
- message_admins("Admin [key_name_admin(usr)] has [action] on joining the round if they use AntagHUD", 1)
-
+ return mobs
+
/client/proc/cmd_admin_add_freeform_ai_law()
set category = "Event"
set name = "Add Custom AI law"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_EVENT))
return
+
var/input = input(usr, "Please enter anything you want the AI to do. Anything. Serious.", "What?", "") as text|null
if(!input)
return
@@ -601,9 +519,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
/client/proc/cmd_admin_rejuvenate(mob/living/M as mob in mob_list)
set category = "Special Verbs"
set name = "Rejuvenate"
- if(!holder)
- src << "Only administrators may use this command."
+
+ if(!check_rights(R_REJUVINATE))
return
+
if(!mob)
return
if(!istype(M))
@@ -619,7 +538,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Event"
set name = "Create Command Report"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
var/input = input(usr, "Please enter anything you want. Anything. Serious.", "What?", "") as message|null
var/customname = input(usr, "Pick a title for the report.", "Title") as text|null
@@ -651,8 +571,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Admin"
set name = "Delete"
- if (!holder)
- src << "Only administrators may use this command."
+ if(!check_rights(R_ADMIN))
return
if (alert(src, "Are you sure you want to delete:\n[O]\nat ([O.x], [O.y], [O.z])?", "Confirmation", "Yes", "No") == "Yes")
@@ -669,9 +588,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Admin"
set name = "List free slots"
- if (!holder)
- src << "Only administrators may use this command."
+ if(!check_rights(R_ADMIN))
return
+
if(job_master)
for(var/datum/job/job in job_master.occupations)
src << "[job.title]: [job.total_positions]"
@@ -681,7 +600,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Event"
set name = "Explosion"
- if(!check_rights(R_DEBUG|R_EVENT)) return
+ if(!check_rights(R_DEBUG|R_EVENT))
+ return
var/devastation = input("Range of total devastation. -1 to none", text("Input")) as num|null
if(devastation == null) return
@@ -711,7 +631,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Special Verbs"
set name = "EM Pulse"
- if(!check_rights(R_DEBUG|R_EVENT)) return
+ if(!check_rights(R_DEBUG|R_EVENT))
+ return
var/heavy = input("Range of heavy pulse.", text("Input")) as num|null
if(heavy == null) return
@@ -733,7 +654,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Special Verbs"
set name = "Gib"
- if(!check_rights(R_ADMIN|R_EVENT)) return
+ if(!check_rights(R_ADMIN|R_EVENT))
+ return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
@@ -754,6 +676,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
set name = "Gibself"
set category = "Event"
+ if(!check_rights(R_ADMIN|R_EVENT))
+ return
+
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm == "Yes")
if (istype(mob, /mob/dead/observer)) // so they don't spam gibs everywhere
@@ -764,115 +689,29 @@ Traitors and the like can also be revived with the previous role mostly intact.
log_admin("[key_name(usr)] used gibself.")
message_admins("\blue [key_name_admin(usr)] used gibself.", 1)
feedback_add_details("admin_verb","GIBS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/*
-/client/proc/cmd_manual_ban()
- set name = "Manual Ban"
- set category = "Special Verbs"
- if(!authenticated || !holder)
- src << "Only administrators may use this command."
- return
- var/mob/M = null
- switch(alert("How would you like to ban someone today?", "Manual Ban", "Key List", "Enter Manually", "Cancel"))
- if("Key List")
- var/list/keys = list()
- for(var/mob/M in world)
- keys += M.client
- var/selection = input("Please, select a player!", "Admin Jumping", null, null) as null|anything in keys
- if(!selection)
- return
- M = selection:mob
- if ((M.client && M.client.holder && (M.client.holder.level >= holder.level)))
- alert("You cannot perform this action. You must be of a higher administrative rank!")
- return
-
- switch(alert("Temporary Ban?",,"Yes","No"))
- if("Yes")
- var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num
- if(!mins)
- return
- if(mins >= 525600) mins = 525599
- var/reason = input(usr,"Reason?","reason","Griefer") as text
- if(!reason)
- return
- if(M)
- AddBan(M.ckey, M.computer_id, reason, usr.ckey, 1, mins)
- M << "\redYou have been banned by [usr.client.ckey].\nReason: [reason]."
- M << "\red This is a temporary ban, it will be removed in [mins] minutes."
- M << "\red To try to resolve this matter head to http://ss13.donglabs.com/forum/"
- log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
- message_admins("\blue[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis will be removed in [mins] minutes.")
- world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=[mins]&server=[replacetext(config.server_name, "#", "")]")
- del(M.client)
- del(M)
- else
-
- if("No")
- var/reason = input(usr,"Reason?","reason","Griefer") as text
- if(!reason)
- return
- AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0)
- M << "\redYou have been banned by [usr.client.ckey].\nReason: [reason]."
- M << "\red This is a permanent ban."
- M << "\red To try to resolve this matter head to http://ss13.donglabs.com/forum/"
- log_admin("[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.")
- message_admins("\blue[usr.client.ckey] has banned [M.ckey].\nReason: [reason]\nThis is a permanent ban.")
- world.Export("http://216.38.134.132/adminlog.php?type=ban&key=[usr.client.key]&key2=[M.key]&msg=[html_decode(reason)]&time=perma&server=[replacetext(config.server_name, "#", "")]")
- del(M.client)
- del(M)
-*/
-
-/client/proc/update_world()
- // If I see anyone granting powers to specific keys like the code that was here,
- // I will both remove their SVN access and permanently ban them from my servers.
- return
/client/proc/cmd_admin_check_contents(mob/living/M as mob in mob_list)
set category = "Special Verbs"
set name = "Check Contents"
+
+ if(!check_rights(R_ADMIN))
+ return
var/list/L = M.get_contents()
for(var/t in L)
usr << "[t]"
feedback_add_details("admin_verb","CC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/* This proc is DEFERRED. Does not do anything.
-/client/proc/cmd_admin_remove_plasma()
- set category = "Debug"
- set name = "Stabilize Atmos."
- if(!holder)
- src << "Only administrators may use this command."
- return
- feedback_add_details("admin_verb","STATM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-// DEFERRED
- spawn(0)
- for(var/turf/T in view())
- T.poison = 0
- T.oldpoison = 0
- T.tmppoison = 0
- T.oxygen = 755985
- T.oldoxy = 755985
- T.tmpoxy = 755985
- T.co2 = 14.8176
- T.oldco2 = 14.8176
- T.tmpco2 = 14.8176
- T.n2 = 2.844e+006
- T.on2 = 2.844e+006
- T.tn2 = 2.844e+006
- T.tsl_gas = 0
- T.osl_gas = 0
- T.sl_gas = 0
- T.temp = 293.15
- T.otemp = 293.15
- T.ttemp = 293.15
-*/
-
/client/proc/toggle_view_range()
set category = "Special Verbs"
set name = "Change View Range"
set desc = "switches between 1x and custom views"
+
+ if(!check_rights(R_ADMIN))
+ return
if(view == world.view)
- view = input("Select view range:", "View Range", 9) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
+ view = input("Select view range:", "View Range", world.view) in list(1,2,3,4,5,6,7,8,9,10,11,12,13,14,128)
else
view = world.view
@@ -882,14 +721,14 @@ Traitors and the like can also be revived with the previous role mostly intact.
feedback_add_details("admin_verb","CVRA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/admin_call_shuttle()
-
set category = "Admin"
set name = "Call Shuttle"
if ((!( ticker ) || !emergency_shuttle.location()))
return
- if(!check_rights(R_ADMIN)) return
+ if(!check_rights(R_ADMIN))
+ return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
@@ -924,7 +763,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Admin"
set name = "Cancel Shuttle"
- if(!check_rights(R_ADMIN)) return
+ if(!check_rights(R_ADMIN))
+ return
if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") return
@@ -945,7 +785,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
if (!ticker)
return
- if(!check_rights(R_ADMIN)) return
+ if(!check_rights(R_ADMIN))
+ return
emergency_shuttle.deny_shuttle = !emergency_shuttle.deny_shuttle
@@ -956,6 +797,9 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Special Verbs"
set name = "Attack Log"
+ if(!check_rights(R_ADMIN))
+ return
+
usr << text("\red Attack Log for []", mob)
for(var/t in M.attack_log)
usr << t
@@ -967,7 +811,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set name = "Make Everyone Random"
set desc = "Make everyone have a random appearance. You can only use this before rounds!"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
if (ticker && ticker.mode)
usr << "Nope you can't do this, the game's already started. This only works before rounds!"
@@ -995,13 +840,13 @@ Traitors and the like can also be revived with the previous role mostly intact.
ticker.random_players = 1
feedback_add_details("admin_verb","MER") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
/client/proc/toggle_random_events()
set category = "Event"
set name = "Toggle random events on/off"
set desc = "Toggles random events such as meteors, black holes, blob (but not space dust) on/off"
- if(!check_rights(R_SERVER|R_EVENT)) return
+ if(!check_rights(R_SERVER|R_EVENT))
+ return
if(!config.allow_random_events)
config.allow_random_events = 1
@@ -1018,7 +863,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
set name = "Toggle ERT"
set desc = "Toggle the station's ability to call a response team."
- if(!check_rights(R_EVENT)) return
+ if(!check_rights(R_EVENT))
+ return
if(ticker.mode.ert_disabled)
ticker.mode.ert_disabled = 0
diff --git a/code/modules/reagents/newchem/toxins.dm b/code/modules/reagents/newchem/toxins.dm
index 2176171bc11..d5d20843759 100644
--- a/code/modules/reagents/newchem/toxins.dm
+++ b/code/modules/reagents/newchem/toxins.dm
@@ -15,7 +15,7 @@ datum/reagent/polonium
datum/reagent/polonium/on_mob_life(var/mob/living/M as mob)
if(!M) M = holder.my_atom
- M.apply_effect(8, IRRADIATE)
+ M.apply_effect(8, IRRADIATE, negate_armor = 1)
..()
return
@@ -712,7 +712,7 @@ datum/reagent/glowing_slurry/reaction_mob(var/mob/M, var/method=TOUCH, var/volum
datum/reagent/glowing_slurry/on_mob_life(var/mob/living/M as mob)
if(!M) M = holder.my_atom
- M.apply_effect(2*REM,IRRADIATE,0)
+ M.apply_effect(2*REM, IRRADIATE, 0, negate_armor = 1)
if(prob(15))
randmutb(M)
if(prob(5))
diff --git a/code/world.dm b/code/world.dm
index 78ba88f840c..14b23b525b5 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -334,32 +334,6 @@ var/world_topic_spam_protect_time = world.timeofday
config.loadoverflowwhitelist("config/ofwhitelist.txt")
// apply some settings from config..
-/hook/startup/proc/loadMods()
- world.load_mods()
- return 1
-
-/world/proc/load_mods()
- if(config.admin_legacy_system)
- var/text = file2text("config/moderators.txt")
- if (!text)
- diary << "Failed to load config/mods.txt\n"
- else
- var/list/lines = text2list(text, "\n")
- for(var/line in lines)
- if (!line)
- continue
-
- if (copytext(line, 1, 2) == ";")
- continue
-
- var/title = "Moderator"
- if(config.mods_are_mentors) title = "Mentor"
- var/rights = admin_ranks[title]
-
- var/ckey = copytext(line, 1, length(line)+1)
- var/datum/admins/D = new /datum/admins(title, rights, ckey)
- D.associate(directory[ckey])
-
/world/proc/update_status()
var/s = ""
diff --git a/config/example/access levels.txt b/config/example/access levels.txt
deleted file mode 100644
index 8068be153fa..00000000000
--- a/config/example/access levels.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-HOW TO CONVERT A MAP TO THE NEW (june 2008) ACCESS LEVEL SYSTEM
-1. Open the .dmp file up in Notepad
-2. Find all the "access = blahblah" attributes of doors.
-3. Delete them.
-4. Open the map up in Dream Maker. If you didn't get them all, it'll tell you so.
-5. Assign the existing doors new access permissions using the method below.
-
-HOW TO MAKE A MAP USING THE NEW (june 2008) ACCESS LEVEL SYSTEM
-1. Make a map as normal
-2. Select a door that you want to not be accessible to everybody
-3. Right click on it and edit its attributes
-4. Make the "req_access_txt" attribute be a semicolon-separated list of the permissions required to open the doors
-5. Repeat for all doors.
-
-For example, a brig door would have it be "2" while a door that requires you have toxins and teleporter access (for whatever reason) would have it be "9;20"
-
-Here is a list of the permissions and their numbers (this may be out of date, see code/game/access.dm for an updated version):
-
-access_security = 1
-access_brig = 2
-access_armory = 3
-access_forensics_lockers= 4
-access_medical = 5
-access_morgue = 6
-access_tox = 7
-access_tox_storage = 8
-access_genetics = 9
-access_engine = 10
-access_engine_equip= 11
-access_maint_tunnels = 12
-access_external_airlocks = 13
-access_emergency_storage = 14
-access_change_ids = 15
-access_ai_upload = 16
-access_teleporter = 17
-access_eva = 18
-access_heads = 19
-access_captain = 20
-access_all_personal_lockers = 21
-access_chapel_office = 22
-access_tech_storage = 23
-access_atmospherics = 24
-access_bar = 25
-access_janitor = 26
-access_crematorium = 27
-access_kitchen = 28
-access_robotics = 29
-access_rd = 30
-access_cargo = 31
-access_construction = 32
-access_chemistry = 33
-access_cargo_bot = 34
-access_hydroponics = 35
-access_manufacturing = 36
-access_library = 37
-access_lawyer = 38
-access_virology = 39
-access_cmo = 40
-access_qm = 41
-access_court = 42
-access_clown = 43
-access_mime = 44
-access_surgery = 45
-access_theatre = 46
-access_research = 47
-access_mining = 48
-access_mining_office = 49 //not in use
-access_mailsorting = 50
-access_mint = 51
-access_mint_vault = 52
-access_heads_vault = 53
-access_mining_station = 54
-access_xenobiology = 55
-access_ce = 56
-access_hop = 57
-access_hos = 58
-access_RC_announce = 59 //Request console announcements
-access_keycard_auth = 60 //Used for events which require at least two people to confirm them
-access_tcomsat = 61 // has access to the entire telecomms satellite / machinery
\ No newline at end of file
diff --git a/config/example/admin_ranks.txt b/config/example/admin_ranks.txt
index e02a56df044..db2118ee8b7 100644
--- a/config/example/admin_ranks.txt
+++ b/config/example/admin_ranks.txt
@@ -5,31 +5,30 @@
# Each rank is then followed by keywords with the prefix "+". #
# These keywords represent groups of verbs and abilities which are given to that rank. #
# +@ (or +prev) is a special shorthand which adds all the rights of the rank above it. #
-# Ranks with no keywords will just be given the most basic verbs and abilities ~Carn #
+# Ranks with no keywords will just be given the most basic verbs and abilities #
########################################################################################
-# PLEASE NOTE: depending on config options, some abilities will be unavailable regardless if you have permission to use them!
-# ALSO NOTE: this is a WorkInProgress at the moment. Most of this is just arbitrarily thrown in whatever group because LoadsaWork2Do+LittleTime.
-# I'll be doing more moving around as feedback comes in. So be sure to check the notes after updates.
-
# KEYWORDS:
-# +ADMIN = general admin tools, verbs etc
-# +FUN = events, other event-orientated actions. Access to the fun secrets in the secrets panel.
-# +BAN = the ability to ban, jobban and fullban
-# +STEALTH = the ability to stealthmin (make yourself appear with a fake name to everyone but other admins
-# +POSSESS = the ability to possess objects
-# +REJUV (or +REJUVINATE) = the ability to heal, respawn, modify damage and use godmode
-# +BUILD (or +BUILDMODE) = the ability to use buildmode
-# +SERVER = higher-risk admin verbs and abilities, such as those which affect the server configuration.
-# +DEBUG = debug tools used for diagnosing and fixing problems. It's useful to give this to coders so they can investigate problems on a live server.
-# +VAREDIT = everyone may view viewvars/debugvars/whatever you call it. This keyword allows you to actually EDIT those variables.
-# +RIGHTS (or +PERMISSIONS) = allows you to promote and/or demote people.
-# +SOUND (or +SOUNDS) = allows you to upload and play sounds
-# +SPAWN (or +CREATE) = mob transformations, spawning of most atoms including mobs (high-risk atoms, e.g. blackholes, will require the +FUN flag too)
-# +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag
+# +ADMIN = General admin tools and verbs.
+# +FUN = Events and other event-orientated actions.
+# +BAN = The ability to ban and jobban.
+# +STEALTH = The ability to stealthmin (make yourself appear with a fake name to everyone but other admins).
+# +POSSESS = The ability to possess objects.
+# +REJUV (or +REJUVINATE) = The ability to heal, respawn, modify damage and use godmode.
+# +BUILD (or +BUILDMODE) = The ability to use buildmode.
+# +SERVER = Higher-risk admin verbs and abilities, such as those which affect the server configuration.
+# +DEBUG = Debug tools used for diagnosing and fixing problems. It's useful to give this to coders so they can investigate problems on a live server.
+# +VAREDIT = Allows you to actually modify variables in the view variables window.
+# +RIGHTS (or +PERMISSIONS) = Allows you to promote and demote people.
+# +SOUND (or +SOUNDS) = Allows you to upload and play sounds.
+# +SPAWN (or +CREATE) = Mob transformations, spawning of most atoms including mobs (high-risk atoms will require the +FUN flag too).
+# +PROCCALL = The ability to call any proc on any entity.
+# +MOD = Low level admin abilities.
+# +MENTOR = The ability to answer questions.
+# +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag.
Admin Observer
+Mentor +MENTOR
Moderator +MOD
-Mentor +MENTOR
Admin Candidate +ADMIN
Trial Admin +@ +SPAWN +REJUV +VAREDIT +BAN
@@ -41,5 +40,4 @@ Retired Admin +ADMIN +STEALTH
Host +EVERYTHING
-Developer +DEBUG +VAREDIT +SERVER +SPAWN +REJUV +POSSESS +BUILDMODE
-Dev Mod +@ +MOD
+Developer +DEBUG +VAREDIT +SERVER +SPAWN +REJUV +POSSESS +BUILDMODE
\ No newline at end of file
diff --git a/config/example/admins.txt b/config/example/admins.txt
index 3b830cd27ff..0e89ae17e23 100644
--- a/config/example/admins.txt
+++ b/config/example/admins.txt
@@ -2,7 +2,7 @@
# Basically, ckey goes first. Rank goes after the "-" #
# Case is not important for ckey. #
# Case IS important for the rank. However punctuation/spaces are not #
-# Ranks can be anything defined in admin_ranks.txt ~Carn #
+# Ranks can be anything defined in admin_ranks.txt #
######################################################################
-# not_a_user - Admin
+# example - Admin
diff --git a/config/example/custom_items.txt b/config/example/custom_items.txt
deleted file mode 100644
index f4bb1a7028b..00000000000
--- a/config/example/custom_items.txt
+++ /dev/null
@@ -1 +0,0 @@
-ckey: name: /path/to/obj
diff --git a/config/example/moderators.txt b/config/example/moderators.txt
deleted file mode 100644
index b14d8e49f43..00000000000
--- a/config/example/moderators.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-; just add the ckey (lowercase) of every moderator on a separate line
-; lines starting with ; are comments and will be ignored
-
diff --git a/config/example/svndir.txt b/config/example/svndir.txt
deleted file mode 100644
index 5c907c92f1f..00000000000
--- a/config/example/svndir.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-#Path to the .svn directory. Used to get server revision info.
-SVNDIR .svn
-
-#Link to revision details.
-REVHREF http://code.google.com/p/tgstation13/source/detail?r=
\ No newline at end of file
diff --git a/paradise.dme b/paradise.dme
index 5fcbab6ee36..76969b151fa 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -944,6 +944,8 @@
#include "code\modules\admin\verbs\ticklag.dm"
#include "code\modules\admin\verbs\tripAI.dm"
#include "code\modules\admin\verbs\vox_raiders.dm"
+#include "code\modules\admin\verbs\SDQL2\SDQL_2.dm"
+#include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm"
#include "code\modules\alarm\alarm.dm"
#include "code\modules\alarm\alarm_handler.dm"
#include "code\modules\alarm\atmosphere_alarm.dm"