diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index bc3def4bc5..78c5ceba85 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -826,3 +826,7 @@ var/global/BSACooldown = 0
"Admin login: [key_name(src)]")
if(string)
message_admins("[string]")
+
+
+/datum/admins/SDQL_update()
+ return FALSE //No.
\ No newline at end of file
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index 5b4f92335c..ac24f3bde2 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -6,6 +6,9 @@ var/list/admin_ranks = list() //list of all admin_rank datums
var/list/adds
var/list/subs
+/datum/admin_rank/SDQL_update()
+ return FALSE //Nice try trivialadmin!
+
/datum/admin_rank/New(init_name, init_rights, list/init_adds, list/init_subs)
name = init_name
switch(name)
diff --git a/code/modules/admin/sql_message_system.dm b/code/modules/admin/sql_message_system.dm
index 0a11abba05..037f69d281 100644
--- a/code/modules/admin/sql_message_system.dm
+++ b/code/modules/admin/sql_message_system.dm
@@ -154,7 +154,7 @@
message_admins("[key_name_admin(usr)] has toggled [target_ckey]'s [type] made by [admin_ckey] to [secret ? "not secret" : "secret"]")
browse_messages(target_ckey = target_ckey)
-/proc/browse_messages(type, target_ckey, index, linkless = 0)
+/proc/browse_messages(type, target_ckey, index, linkless = 0, filter)
if(!dbcon.IsConnected())
usr << "Failed to establish database connection."
return
@@ -176,7 +176,11 @@
output += "\[Add memo\]"
else if(type == "watchlist entry")
output += "
Watchlist entries
"
- output += "\[Add watchlist entry\]"
+ output += "\[Add watchlist entry\]"
+ if(filter)
+ output += "|\[Unfilter clients\]"
+ else
+ output += "|\[Filter offline clients\]"
output += ruler
var/DBQuery/query_get_type_messages = dbcon.NewQuery("SELECT id, targetckey, adminckey, text, timestamp, server, lasteditor FROM [format_table_name("messages")] WHERE type = '[type]'")
if(!query_get_type_messages.Execute())
@@ -186,6 +190,8 @@
while(query_get_type_messages.NextRow())
var/id = query_get_type_messages.item[1]
var/t_ckey = query_get_type_messages.item[2]
+ if(type == "watchlist entry" && filter && !(t_ckey in directory))
+ continue
var/admin_ckey = query_get_type_messages.item[3]
var/text = query_get_type_messages.item[4]
var/timestamp = query_get_type_messages.item[5]
@@ -229,13 +235,20 @@
data += " \[Delete\]"
if(type == "note")
data += " [secret ? "\[Secret\]" : "\[Not secret\]"]"
- data += " \[Edit\]"
+ if(type == "message sent")
+ data += " Message has been sent"
+ if(editor_ckey)
+ data += "|"
+ else
+ data += " \[Edit\]"
if(editor_ckey)
data += " Last edit by [editor_ckey] (Click here to see edit log)"
data += "
[text]
"
switch(type)
if("message")
messagedata += data
+ if("message sent")
+ messagedata += data
if("watchlist entry")
watchdata += data
if("note")
@@ -303,7 +316,7 @@ proc/get_message_output(type, target_ckey)
log_game("SQL ERROR obtaining id, adminckey, text, timestamp, lasteditor from messages table. Error : \[[err]\]\n")
return
while(query_get_message_output.NextRow())
- var/id = query_get_message_output.item[1]
+ var/message_id = query_get_message_output.item[1]
var/admin_ckey = query_get_message_output.item[2]
var/text = query_get_message_output.item[3]
var/timestamp = query_get_message_output.item[4]
@@ -311,15 +324,19 @@ proc/get_message_output(type, target_ckey)
switch(type)
if("message")
output += "Admin message left by [admin_ckey] on [timestamp]"
- output += "
[text]"
- delete_message(id, 0)
+ output += "
[text]
"
+ var/DBQuery/query_message_read = dbcon.NewQuery("UPDATE [format_table_name("messages")] SET type = 'message sent' WHERE id = [message_id]")
+ if(!query_message_read.Execute())
+ var/err = query_message_read.ErrorMsg()
+ log_game("SQL ERROR updating message type. Error : \[[err]\]\n")
+ return
if("watchlist entry")
message_admins("Notice: [key_name_admin(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
send2admindiscord("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
if("memo")
output += "Memo by [admin_ckey] on [timestamp]"
if(editor_ckey)
- output += "
Last edit by [editor_ckey] (Click here to see edit log)"
+ output += "
Last edit by [editor_ckey] (Click here to see edit log)"
output += "
[text]
"
return output
@@ -368,4 +385,4 @@ this proc can take several minutes to execute fully if converting and cause DD t
world << "Deleting NOTESFILE"
fdel(NOTESFILE)
world << "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES"*/
-#undef NOTESFILE
\ No newline at end of file
+#undef NOTESFILE
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 00f7dd2e7e..200ec20df6 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1131,6 +1131,9 @@
else if(href_list["showwatch"])
browse_messages("watchlist entry")
+ else if(href_list["showwatchfilter"])
+ browse_messages("watchlist entry", filter = 1)
+
else if(href_list["showmessageckey"])
var/target = href_list["showmessageckey"]
browse_messages(target_ckey = target)
@@ -1744,12 +1747,42 @@
H << "Your prayers have been answered!! You received the best cookie!"
H << 'sound/effects/pray_chaplain.ogg'
+ else if(href_list["adminsmite"])
+ if(!check_rights(R_ADMIN|R_FUN))
+ return
+
+ var/mob/living/carbon/human/H = locate(href_list["adminsmite"]) in mob_list
+ if(!H || !istype(H))
+ return
+
+ var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB)
+
+ var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
+
+ if(QDELETED(H) || !punishment)
+ return
+
+ switch(punishment)
+ if(ADMIN_PUNISHMENT_LIGHTNING)
+ var/turf/T = get_step(get_step(H, NORTH), NORTH)
+ T.Beam(H, icon_state="lightning[rand(1,12)]", time = 5)
+ H.adjustFireLoss(75)
+ H.electrocution_animation(40)
+ H << "The gods have punished you for your sins!"
+ if(ADMIN_PUNISHMENT_BRAINDAMAGE)
+ H.adjustBrainLoss(75)
+ if(ADMIN_PUNISHMENT_GIB)
+ H.gib(FALSE)
+
+ message_admins("[key_name_admin(usr)] punished [key_name_admin(H)] with [punishment].")
+ log_admin("[key_name(usr)] punished [key_name(H)] with [punishment].")
+
else if(href_list["BlueSpaceArtillery"])
- var/mob/living/M = locate(href_list["BlueSpaceArtillery"])
+ var/mob/living/M = locate(href_list["BlueSpaceArtillery"]) in mob_list
usr.client.bluespace_artillery(M)
else if(href_list["CentcommReply"])
- var/mob/living/carbon/human/H = locate(href_list["CentcommReply"])
+ var/mob/living/carbon/human/H = locate(href_list["CentcommReply"]) in mob_list
if(!istype(H))
usr << "This can only be used on instances of type /mob/living/carbon/human"
return
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index aaead53f54..5d935439a8 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -18,11 +18,22 @@
*/
+/datum/proc/SDQL_update(const/var_name, new_value)
+ vars[var_name] = new_value
+ return TRUE
+
/client/proc/SDQL2_query(query_text as message)
set category = "Debug"
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
message_admins("ERROR: Non-admin [key_name(usr, usr.client)] attempted to execute a SDQL query!")
log_admin("Non-admin [usr.ckey]([usr]) attempted to execute a SDQL query!")
+ return FALSE
+
+ var/query_log = "executed SDQL query: \"[query_text]\"."
+ message_admins("[key_name_admin(usr)] [query_log]")
+ query_log = "[usr.ckey]([usr]) [query_log]"
+ log_game(query_log)
+ NOTICE(query_log)
if(!query_text || length(query_text) < 1)
return
@@ -39,119 +50,122 @@
if(!querys || querys.len < 1)
return
+ try
- var/query_log = "executed SDQL query: \"[query_text]\"."
- message_admins("[key_name_admin(usr)] [query_log]")
- query_log = "[usr.ckey]([usr]) [query_log]"
- log_game(query_log)
- NOTICE(query_log)
+ for(var/list/query_tree in querys)
+ var/list/from_objs = list()
+ var/list/select_types = list()
-
- 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
+ switch(query_tree[1])
+ if("explain")
+ SDQL_testout(query_tree["explain"])
return
- if("select", "delete", "update")
- select_types = query_tree[query_tree[1]]
+ if("call")
+ if("on" in query_tree)
+ select_types = query_tree["on"]
+ else
+ return
- from_objs = SDQL_from_objs(query_tree["from"])
+ if("select", "delete", "update")
+ select_types = query_tree[query_tree[1]]
- var/list/objs = list()
+ from_objs = SDQL_from_objs(query_tree["from"])
- for(var/type in select_types)
- var/char = copytext(type, 1, 2)
+ var/list/objs = list()
- if(char == "/" || char == "*")
- for(var/from in from_objs)
- objs += SDQL_get_all(type, from)
- CHECK_TICK
+ for(var/type in select_types)
+ var/char = copytext(type, 1, 2)
- 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
- CHECK_TICK
-
- 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)
- SDQL_callproc(d, v, args_list)
+ if(char == "/" || char == "*")
+ for(var/from in from_objs)
+ objs += SDQL_get_all(type, from)
CHECK_TICK
- if("delete")
- for(var/datum/d in objs)
- qdel(d)
+ 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
CHECK_TICK
- if("select")
- var/text = ""
- for(var/datum/t in objs)
- text += "\ref[t]"
- if(istype(t, /atom))
- var/atom/a = t
+ switch(query_tree[1])
+ if("call")
+ var/list/call_list = query_tree["call"]
+ var/list/args_list = query_tree["args"]
- if(a.x)
- text += ": [t] at ([a.x], [a.y], [a.z])
"
+ for(var/datum/d in objs)
+ var/list/new_args = list()
+ for(var/a in args_list)
+ new_args += SDQL_expression(d,a)
+ for(var/v in call_list)
+ if(copytext(v,1,8) == "global.")
+ v = "/proc/[copytext(v,8)]"
+ SDQL_callproc_global(v,new_args)
+ else
+ SDQL_callproc(d, v, new_args)
+ CHECK_TICK
- else if(a.loc && a.loc.x)
- text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
"
+ if("delete")
+ for(var/datum/d in objs)
+ qdel(d)
+ CHECK_TICK
+
+ 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]
"
-
- else
- text += ": [t]
"
- CHECK_TICK
-
- 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(isturf(d))
- 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]
CHECK_TICK
+ 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)
+ for(var/list/sets in set_list)
+ var/datum/temp = d
+ var/i = 0
+ for(var/v in sets)
+ if(++i == sets.len)
+ temp.SDQL_update(v, SDQL_expression(d, set_list[sets]))
+ break
+ if(temp.vars.Find(v) && (istype(temp.vars[v], /datum)))
+ temp = temp.vars[v]
+ else
+ break
+ CHECK_TICK
+ catch(var/exception/e)
+ usr << "A runtime error has occured in your SDQL2-query."
+ usr << "\[NAME\][e.name]"
+ usr << "\[FILE\][e.file]"
+ usr << "\[LINE\][e.line]"
+
+/proc/SDQL_callproc_global(procname,args_list)
+ set waitfor = FALSE
+ call(procname)(arglist(args_list))
/proc/SDQL_callproc(thing, procname, args_list)
- set waitfor = 0
+ set waitfor = FALSE
if(hascall(thing, procname))
call(thing, procname)(arglist(args_list))
@@ -248,7 +262,7 @@
type = text2path(type)
var/typecache = typecacheof(type)
-
+
if(ispath(type, /mob))
for(var/mob/d in location)
if(typecache[d.type])
@@ -382,6 +396,12 @@
else if(copytext(expression[i], 1, 2) in list("'", "\""))
val = copytext(expression[i], 2, length(expression[i]))
+ else if(expression[i] == "\[")
+ var/list/expressions_list = expression[++i]
+ var/list/val2 = list()
+ for(var/list/expression_list in expressions_list)
+ val2[++val2.len] = SDQL_expression(object, expression_list)
+ val = val2
else
val = SDQL_var(object, expression, i)
i = expression.len
@@ -389,22 +409,40 @@
return list("val" = val, "i" = i)
/proc/SDQL_var(datum/object, list/expression, start = 1)
-
+ var/v
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]]
-
+ v = object.vars[expression[start]]
+ else if(expression[start] == "{" && start < expression.len)
+ if(lowertext(copytext(expression[start + 1], 1, 3)) != "0x")
+ usr << "Invalid pointer syntax: [expression[start + 1]]"
+ return null
+ v = locate("\[[expression[start + 1]]]")
+ if(!v)
+ usr << "Invalid pointer: [expression[start + 1]]"
+ return null
+ start++
else
- return null
+ switch(expression[start])
+ if("usr")
+ v = usr
+ if("src")
+ v = object
+ if("marked")
+ if(usr.client && usr.client.holder && usr.client.holder.marked_datum)
+ v = usr.client.holder.marked_datum
+ else
+ return null
+ else
+ return null
+ if(start < expression.len && expression[start + 1] == ".")
+ return SDQL_var(v, expression[start + 2])
+ else
+ return v
/proc/SDQL2_tokenize(query_text)
var/list/whitespace = list(" ", "\n", "\t")
- var/list/single = list("(", ")", ",", "+", "-", ".", ";")
+ var/list/single = list("(", ")", ",", "+", "-", ".", ";", "{", "}", "\[", "]")
var/list/multi = list(
"=" = list("", "="),
"<" = list("", "=", ">"),
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
index 3dbe45235a..591e824312 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
@@ -57,13 +57,9 @@
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]"
@@ -96,448 +92,354 @@
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"])
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/assignment(var/i, var/list/node, var/list/assignment_list = list())
+ assignment_list += token(i)
+ if(token(i + 1) == ".")
+ i = assignment(i + 2, node, assignment_list)
+ else if(token(i + 1) == "=")
+ var/exp_list = list()
+ node[assignment_list] = exp_list
+ i = expression(i + 2, exp_list)
+ 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
+/datum/SDQL_parser/proc/variable(i, list/node)
+ var/list/L = list(token(i))
+ node[++node.len] = L
+ if(token(i) == "{")
+ L += token(i+1)
+ i += 2
+ if(token(i) != "}")
+ parse_error("Missing } at end of pointer.")
+ if(token(i + 1) == ".")
+ L += "."
+ i = variable(i + 2, L)
+ else
+ i++
+ return i
+//array: '[' expression, expression, ... ']'
+/datum/SDQL_parser/proc/array(i, list/node)
+ if(copytext(token(i), 1, 2) != "\[")
+ parse_error("Expected an array but found '[token(i)]'")
+ return i + 1
+ node += token(i)
+ var/list/expression_list = list()
+ if(token(i + 1) != "]")
+ var/list/temp_expression_list = list()
+ do
+ i = expression(i + 1, temp_expression_list)
+ if(token(i) == ",")
+ expression_list[++expression_list.len] = temp_expression_list
+ temp_expression_list = list()
+ while(token(i) && token(i) != "]")
+ expression_list[++expression_list.len] = temp_expression_list
+ else
+ i++
+ node[++node.len] = expression_list
+ return i + 1
//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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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 += copytext(token(i),2,-1)
-
- else
- parse_error("Expected string but found '[token(i)]'")
-
- return i + 1
-
+/datum/SDQL_parser/proc/string(i, list/node)
+ if(copytext(token(i), 1, 2) in list("'", "\""))
+ node += copytext(token(i),2,-1)
+ 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++
+/datum/SDQL_parser/proc/call_function(i, list/node, list/arguments)
+ if(length(tokenl(i)))
+ var/procname = ""
+ if(token(i) == "global" && token(i+1) == ".")
+ i += 2
+ procname = "global."
+ node += procname + token(i++)
+ if(token(i) != "(")
+ parse_error("Expected ( but found '[token(i)]'")
+ else if(token(i + 1) != ")")
+ var/list/expression_list_temp = list()
+ do
+ i = expression(i + 1, expression_list_temp)
+ if(token(i) == ",")
+ arguments[++arguments.len] = expression_list_temp
+ expression_list_temp = list()
+ continue
+ while(token(i) && token(i) != ")")
+ arguments[++arguments.len] = expression_list_temp
else
- parse_error("Expected a function but found nothing")
- return i + 1
-
+ 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
-
+/datum/SDQL_parser/proc/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
-
+/datum/SDQL_parser/proc/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 = 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
-
+ 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)
-
+/datum/SDQL_parser/proc/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)
- 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
-
+ 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 = value(i, unary_exp)
-
- node[++node.len] = unary_exp
-
-
+ i++
+ unary_exp[++unary_exp.len] = expr
else
- parse_error("Expected unary operator but found '[token(i)]'")
-
- return i
-
+ 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
-
+/datum/SDQL_parser/proc/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)
+/datum/SDQL_parser/proc/value(i, list/node)
+ if(token(i) == "null")
+ node += "null"
+ i++
+ else if(lowertext(copytext(token(i),1,3)) == "0x" && isnum(hex2num(copytext(token(i),3))))
+ node += hex2num(copytext(token(i),3))
+ 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 if(copytext(token(i), 1, 2) == "\[") // Start a list.
+ i = array(i, node)
+ else
+ i = variable(i, node)
+ return i
- 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*/
\ No newline at end of file
+/*EXPLAIN SELECT * WHERE 42 = 6 * 9 OR val = - 5 == 7*/
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm
new file mode 100644
index 0000000000..286e3a890f
--- /dev/null
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm
@@ -0,0 +1,174 @@
+// Wrappers for BYOND default procs which can't directly be called by call().
+
+/proc/_abs(A)
+ return abs(A)
+
+/*/proc/_animate(atom/A, set_vars, time = 10, loop = 1, easing = LINEAR_EASING, flags = null)
+ animate(A, set_vars, time, loop, easing, flags)
+ Borked. If anyone wants to fix this be my guest.*/
+
+/proc/_acrccos(A)
+ return arccos(A)
+
+/proc/_arcsin(A)
+ return arcsin(A)
+
+/proc/_ascii2text(A)
+ return ascii2text(A)
+
+/proc/_block(Start, End)
+ return block(Start, End)
+
+/proc/_ckey(Key)
+ return ckey(Key)
+
+/proc/_ckeyEx(Key)
+ return ckeyEx(Key)
+
+/proc/_copytext(T, Start = 1, End = 0)
+ return copytext(T, Start, End)
+
+/proc/_cos(X)
+ return cos(X)
+
+/proc/_get_dir(Loc1, Loc2)
+ return get_dir(Loc1, Loc2)
+
+/proc/_get_dist(Loc1, Loc2)
+ return get_dist(Loc1, Loc2)
+
+/proc/_get_step(Ref, Dir)
+ return get_step(Ref, Dir)
+
+/proc/_hearers(Depth = world.view, Center = usr)
+ return hearers(Depth, Center)
+
+/proc/_image(icon, loc, icon_state, layer, dir)
+ return image(icon, loc, icon_state, layer, dir)
+
+/proc/_length(E)
+ return length(E)
+
+/proc/_link(thing, url)
+ thing << link(url)
+
+/proc/_locate(X, Y, Z)
+ if (isnull(Y)) // Assuming that it's only a single-argument call.
+ return locate(X)
+
+ return locate(X, Y, Z)
+
+/proc/_log(X, Y)
+ return log(X, Y)
+
+/proc/_lowertext(T)
+ return lowertext(T)
+
+/proc/_matrix(a, b, c, d, e, f)
+ return matrix(a, b, c, d, e, f)
+
+/proc/_max(...)
+ return max(arglist(args))
+
+/proc/_md5(T)
+ return md5(T)
+
+/proc/_min(...)
+ return min(arglist(args))
+
+/proc/_new(type, arguments)
+ return new type (arglist(arguments))
+
+/proc/_num2text(N, SigFig = 6)
+ return num2text(N, SigFig)
+
+/proc/_ohearers(Dist, Center = usr)
+ return ohearers(Dist, Center)
+
+/proc/_orange(Dist, Center = usr)
+ return orange(Dist, Center)
+
+/proc/_output(thing, msg, control)
+ thing << output(msg, control)
+
+/proc/_oview(Dist, Center = usr)
+ return oview(Dist, Center)
+
+/proc/_oviewers(Dist, Center = usr)
+ return oviewers(Dist, Center)
+
+/proc/_params2list(Params)
+ return params2list(Params)
+
+/proc/_pick(...)
+ return pick(arglist(args))
+
+/proc/_prob(P)
+ return prob(P)
+
+/proc/_rand(L = 0, H = 1)
+ return rand(L, H)
+
+/proc/_range(Dist, Center = usr)
+ return range(Dist, Center)
+
+/proc/_regex(pattern, flags)
+ return regex(pattern, flags)
+
+/proc/_REGEX_QUOTE(text)
+ return REGEX_QUOTE(text)
+
+/proc/_REGEX_QUOTE_REPLACEMENT(text)
+ return REGEX_QUOTE_REPLACEMENT(text)
+
+/proc/_replacetext(Haystack, Needle, Replacement, Start = 1,End = 0)
+ return replacetext(Haystack, Needle, Replacement, Start, End)
+
+/proc/_replacetextEx(Haystack, Needle, Replacement, Start = 1,End = 0)
+ return replacetextEx(Haystack, Needle, Replacement, Start, End)
+
+/proc/_rgb(R, G, B)
+ return rgb(R, G, B)
+
+/proc/_rgba(R, G, B, A)
+ return rgb(R, G, B, A)
+
+/proc/_roll(dice)
+ return roll(dice)
+
+/proc/_round(A, B = 1)
+ return round(A, B)
+
+/proc/_sin(X)
+ return sin(X)
+
+/proc/_step(Ref, Dir, Speed = 0)
+ return step(Ref, Dir, Speed)
+
+/proc/_list_add(list/L, ...)
+ if (args.len < 2)
+ return
+ L += args.Copy(2)
+
+/proc/_list_copy(list/L, Start = 1, End = 0)
+ return L.Copy(Start, End)
+
+/proc/_list_cut(list/L, Start = 1, End = 0)
+ L.Cut(Start, End)
+
+/proc/_list_find(list/L, Elem, Start = 1, End = 0)
+ return L.Find(Elem, Start, End)
+
+/proc/_list_insert(list/L, Index, Item)
+ return L.Insert(Index, Item)
+
+/proc/_list_join(list/L, Glue, Start = 0, End = 1)
+ return L.Join(Glue, Start, End)
+
+/proc/_list_remove(list/L, ...)
+ if (args.len < 2)
+ return
+ L -= args.Copy(2)
+
+/proc/_list_swap(list/L, Index1, Index2)
+ L.Swap(Index1, Index2)
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index e08919d9fc..0572aa3347 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -86,7 +86,7 @@
if(T.admin == "N/A")
usr << "Due to the fact your Adminhelp had no assigned admin, admins have been pinged."
message_admins("[src.ckey] has bumped their adminhelp #[T.ID], still no assigned admin!")
- msg = "ADMINHELP: [key_name(src)] (?) (PP) (VV) (SM) (TP) (FLW) (R) (REJT): [T.msg]"
+ msg = "HELP: [key_name(src)] [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)] (REJT) (IC) (R): [msg]"
for(var/client/X in admins)
if(X.prefs.toggles & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index dd3ee471e9..b8593ff877 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -33,10 +33,7 @@
prayer_type = "CULTIST PRAYER"
deity = "Nar-Sie"
- msg = "\icon[cross] \
- [prayer_type][deity ? " (to [deity])" : ""]: \
- [ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]: \
- [msg]"
+ msg = "\icon[cross][prayer_type][deity ? " (to [deity])" : ""]: [ADMIN_FULLMONTY(src)] [ADMIN_SC(src)] [ADMIN_SMITE(src)]: [msg]"
for(var/client/C in admins)
if(C.prefs.chat_toggles & CHAT_PRAYER)
diff --git a/tgstation.dme b/tgstation.dme
index 4fb22b301f..cf9c735941 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -997,6 +997,7 @@
#include "code\modules\admin\verbs\tripAI.dm"
#include "code\modules\admin\verbs\SDQL2\SDQL_2.dm"
#include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm"
+#include "code\modules\admin\verbs\SDQL2\SDQL_2_wrappers.dm"
#include "code\modules\assembly\assembly.dm"
#include "code\modules\assembly\bomb.dm"
#include "code\modules\assembly\doorcontrol.dm"