mirror of
https://github.com/CHOMPstation/CHOMPstation.git
synced 2026-08-19 18:16:39 +01:00
Merge branch 'dev' of https://github.com/Baystation12/Baystation12 into boozetaketwo
This commit is contained in:
@@ -806,7 +806,7 @@ var/global/floorIsLava = 0
|
||||
set desc="Delay the game start/end"
|
||||
set name="Delay"
|
||||
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
if(!check_rights(R_SERVER)) return
|
||||
if (!ticker || ticker.current_state != GAME_STATE_PREGAME)
|
||||
ticker.delay_end = !ticker.delay_end
|
||||
log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
|
||||
|
||||
@@ -139,7 +139,9 @@ var/list/admin_verbs_debug = list(
|
||||
/client/proc/restart_controller,
|
||||
/client/proc/enable_debug_verbs,
|
||||
/client/proc/callproc,
|
||||
/client/proc/toggledebuglogs
|
||||
/client/proc/toggledebuglogs,
|
||||
/client/proc/SDQL_query,
|
||||
/client/proc/SDQL2_query
|
||||
)
|
||||
var/list/admin_verbs_possess = list(
|
||||
/proc/possess,
|
||||
|
||||
@@ -0,0 +1,497 @@
|
||||
|
||||
//Structured Datum Query Language. Basically SQL meets BYOND objects.
|
||||
|
||||
//Note: For use in BS12, need text_starts_with proc, and to modify the action on select to use BS12's object edit command(s).
|
||||
|
||||
/client/proc/SDQL_query(query_text as message)
|
||||
set category = "Admin"
|
||||
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
|
||||
message_admins("\red ERROR: Non-admin [usr.key] attempted to execute a SDQL query!")
|
||||
log_admin("Non-admin [usr.key] attempted to execute a SDQL query!")
|
||||
|
||||
var/list/query_list = SDQL_tokenize(query_text)
|
||||
|
||||
if(query_list.len < 2)
|
||||
if(query_list.len > 0)
|
||||
usr << "\red SDQL: Too few discrete tokens in query \"[query_text]\". Please check your syntax and try again."
|
||||
return
|
||||
|
||||
if(!(lowertext(query_list[1]) in list("select", "delete", "update")))
|
||||
usr << "\red SDQL: Unknown query type: \"[query_list[1]]\" in query \"[query_text]\". Please check your syntax and try again."
|
||||
return
|
||||
|
||||
var/list/types = list()
|
||||
|
||||
var/i
|
||||
for(i = 2; i <= query_list.len; i += 2)
|
||||
types += query_list[i]
|
||||
|
||||
if(i + 1 >= query_list.len || query_list[i + 1] != ",")
|
||||
break
|
||||
|
||||
i++
|
||||
|
||||
var/list/from = list()
|
||||
|
||||
if(i <= query_list.len)
|
||||
if(lowertext(query_list[i]) in list("from", "in"))
|
||||
for(i++; i <= query_list.len; i += 2)
|
||||
from += query_list[i]
|
||||
|
||||
if(i + 1 >= query_list.len || query_list[i + 1] != ",")
|
||||
break
|
||||
|
||||
i++
|
||||
|
||||
if(from.len < 1)
|
||||
from += "world"
|
||||
|
||||
var/list/set_vars = list()
|
||||
|
||||
if(lowertext(query_list[1]) == "update")
|
||||
if(i <= query_list.len && lowertext(query_list[i]) == "set")
|
||||
for(i++; i <= query_list.len; i++)
|
||||
if(i + 2 <= query_list.len && query_list[i + 1] == "=")
|
||||
set_vars += query_list[i]
|
||||
set_vars[query_list[i]] = query_list[i + 2]
|
||||
|
||||
else
|
||||
usr << "\red SDQL: Invalid set parameter in query \"[query_text]\". Please check your syntax and try again."
|
||||
return
|
||||
|
||||
i += 3
|
||||
|
||||
if(i >= query_list.len || query_list[i] != ",")
|
||||
break
|
||||
|
||||
if(set_vars.len < 1)
|
||||
usr << "\red SDQL: Invalid or missing set in query \"[query_text]\". Please check your syntax and try again."
|
||||
return
|
||||
|
||||
var/list/where = list()
|
||||
|
||||
if(i <= query_list.len && lowertext(query_list[i]) == "where")
|
||||
where = query_list.Copy(i + 1)
|
||||
|
||||
var/list/from_objs = list()
|
||||
if("world" in from)
|
||||
from_objs += world
|
||||
else
|
||||
for(var/f in from)
|
||||
if(copytext(f, 1, 2) == "'" || copytext(f, 1, 2) == "\"")
|
||||
from_objs += locate(copytext(f, 2, length(f)))
|
||||
else if(copytext(f, 1, 2) != "/")
|
||||
from_objs += locate(f)
|
||||
else
|
||||
var/f2 = text2path(f)
|
||||
if(text_starts_with(f, "/mob"))
|
||||
for(var/mob/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/space"))
|
||||
for(var/turf/space/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/simulated"))
|
||||
for(var/turf/simulated/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/unsimulated"))
|
||||
for(var/turf/unsimulated/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf"))
|
||||
for(var/turf/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/area"))
|
||||
for(var/area/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj/item"))
|
||||
for(var/obj/item/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj/machinery"))
|
||||
for(var/obj/machinery/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj"))
|
||||
for(var/obj/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
|
||||
else if(text_starts_with(f, "/atom"))
|
||||
for(var/atom/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
/*
|
||||
else
|
||||
for(var/datum/m in world)
|
||||
if(istype(m, f2))
|
||||
from_objs += m
|
||||
*/
|
||||
|
||||
var/list/objs = list()
|
||||
|
||||
for(var/from_obj in from_objs)
|
||||
if("*" in types)
|
||||
objs += from_obj:contents
|
||||
else
|
||||
for(var/f in types)
|
||||
if(copytext(f, 1, 2) == "'" || copytext(f, 1, 2) == "\"")
|
||||
objs += locate(copytext(f, 2, length(f))) in from_obj
|
||||
else if(copytext(f, 1, 2) != "/")
|
||||
objs += locate(f) in from_obj
|
||||
else
|
||||
var/f2 = text2path(f)
|
||||
if(text_starts_with(f, "/mob"))
|
||||
for(var/mob/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/space"))
|
||||
for(var/turf/space/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/simulated"))
|
||||
for(var/turf/simulated/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf/unsimulated"))
|
||||
for(var/turf/unsimulated/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/turf"))
|
||||
for(var/turf/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/area"))
|
||||
for(var/area/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj/item"))
|
||||
for(var/obj/item/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj/machinery"))
|
||||
for(var/obj/machinery/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/obj"))
|
||||
for(var/obj/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else if(text_starts_with(f, "/atom"))
|
||||
for(var/atom/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
else
|
||||
for(var/datum/m in from_obj)
|
||||
if(istype(m, f2))
|
||||
objs += m
|
||||
|
||||
|
||||
for(var/datum/t in objs)
|
||||
var/currently_false = 0
|
||||
for(i = 1, i - 1 < where.len, i++)
|
||||
var/v = where[i++]
|
||||
var/compare_op = where[i++]
|
||||
if(!(compare_op in list("==", "=", "<>", "<", ">", "<=", ">=", "!=")))
|
||||
usr << "\red SDQL: Unknown comparison operator [compare_op] in where clause following [v] in query \"[query_text]\". Please check your syntax and try again."
|
||||
return
|
||||
|
||||
var/j
|
||||
for(j = i, j <= where.len, j++)
|
||||
if(lowertext(where[j]) in list("and", "or", ";"))
|
||||
break
|
||||
|
||||
if(!currently_false)
|
||||
var/value = SDQL_text2value(t, v)
|
||||
var/result = SDQL_evaluate(t, where.Copy(i, j))
|
||||
|
||||
switch(compare_op)
|
||||
if("=", "==")
|
||||
currently_false = !(value == result)
|
||||
|
||||
if("!=", "<>")
|
||||
currently_false = !(value != result)
|
||||
|
||||
if("<")
|
||||
currently_false = !(value < result)
|
||||
|
||||
if(">")
|
||||
currently_false = !(value > result)
|
||||
|
||||
if("<=")
|
||||
currently_false = !(value <= result)
|
||||
|
||||
if(">=")
|
||||
currently_false = !(value >= result)
|
||||
|
||||
|
||||
if(j > where.len || lowertext(where[j]) == ";")
|
||||
break
|
||||
else if(lowertext(where[j]) == "or")
|
||||
if(currently_false)
|
||||
currently_false = 0
|
||||
else
|
||||
break
|
||||
|
||||
i = j
|
||||
|
||||
if(currently_false)
|
||||
objs -= t
|
||||
|
||||
|
||||
|
||||
usr << "\blue SQDL Query: [query_text]"
|
||||
message_admins("[usr] executed SDQL query: \"[query_text]\".")
|
||||
/*
|
||||
for(var/t in types)
|
||||
usr << "Type: [t]"
|
||||
|
||||
for(var/t in from)
|
||||
usr << "From: [t]"
|
||||
|
||||
for(var/t in set_vars)
|
||||
usr << "Set: [t] = [set_vars[t]]"
|
||||
|
||||
if(where.len)
|
||||
var/where_str = ""
|
||||
for(var/t in where)
|
||||
where_str += "[t] "
|
||||
|
||||
usr << "Where: [where_str]"
|
||||
|
||||
usr << "From objects:"
|
||||
for(var/datum/t in from_objs)
|
||||
usr << t
|
||||
|
||||
usr << "Objects:"
|
||||
for(var/datum/t in objs)
|
||||
usr << t
|
||||
*/
|
||||
switch(lowertext(query_list[1]))
|
||||
if("delete")
|
||||
for(var/datum/t in objs)
|
||||
del t
|
||||
|
||||
if("update")
|
||||
for(var/datum/t in objs)
|
||||
objs[t] = list()
|
||||
for(var/v in set_vars)
|
||||
if(v in t.vars)
|
||||
objs[t][v] = SDQL_text2value(t, set_vars[v])
|
||||
|
||||
for(var/datum/t in objs)
|
||||
for(var/v in objs[t])
|
||||
t.vars[v] = objs[t][v]
|
||||
|
||||
if("select")
|
||||
var/text = ""
|
||||
for(var/datum/t in objs)
|
||||
if(istype(t, /atom))
|
||||
var/atom/a = t
|
||||
|
||||
if(a.x)
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] at ([a.x], [a.y], [a.z])<br>"
|
||||
|
||||
else if(a.loc && a.loc.x)
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
|
||||
|
||||
else
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
|
||||
|
||||
else
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
|
||||
|
||||
//text += "[t]<br>"
|
||||
usr << browse(text, "window=sdql_result")
|
||||
|
||||
|
||||
/client/Topic(href,href_list[],hsrc)
|
||||
if(href_list["SDQL_select"])
|
||||
debug_variables(locate(href_list["SDQL_select"]))
|
||||
|
||||
..()
|
||||
|
||||
|
||||
/proc/SDQL_evaluate(datum/object, list/equation)
|
||||
if(equation.len == 0)
|
||||
return null
|
||||
|
||||
else if(equation.len == 1)
|
||||
return SDQL_text2value(object, equation[1])
|
||||
|
||||
else if(equation[1] == "!")
|
||||
return !SDQL_evaluate(object, equation.Copy(2))
|
||||
|
||||
else if(equation[1] == "-")
|
||||
return -SDQL_evaluate(object, equation.Copy(2))
|
||||
|
||||
|
||||
else
|
||||
usr << "\red SDQL: Sorry, equations not yet supported :("
|
||||
return null
|
||||
|
||||
|
||||
/proc/SDQL_text2value(datum/object, text)
|
||||
if(text2num(text) != null)
|
||||
return text2num(text)
|
||||
else if(text == "null")
|
||||
return null
|
||||
else if(copytext(text, 1, 2) == "'" || copytext(text, 1, 2) == "\"" )
|
||||
return copytext(text, 2, length(text))
|
||||
else if(copytext(text, 1, 2) == "/")
|
||||
return text2path(text)
|
||||
else
|
||||
if(findtext(text, "."))
|
||||
var/split = findtext(text, ".")
|
||||
var/v = copytext(text, 1, split)
|
||||
|
||||
if((v in object.vars) && istype(object.vars[v], /datum))
|
||||
return SDQL_text2value(object.vars[v], copytext(text, split + 1))
|
||||
else
|
||||
return null
|
||||
|
||||
else
|
||||
if(text in object.vars)
|
||||
return object.vars[text]
|
||||
else
|
||||
return null
|
||||
|
||||
|
||||
/proc/text_starts_with(text, start)
|
||||
if(copytext(text, 1, length(start) + 1) == start)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/proc/SDQL_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 << "\red SDQL: You have an error in your SDQL syntax, unexpected ' in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". 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 << "\red SDQL: You have an error in your SDQL syntax, unmatched ' in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
|
||||
return null
|
||||
|
||||
query_list += "[word]'"
|
||||
word = ""
|
||||
|
||||
else if(char == "\"")
|
||||
if(word != "")
|
||||
usr << "\red SDQL: You have an error in your SDQL syntax, unexpected \" in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". 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 << "\red SDQL: You have an error in your SDQL syntax, unmatched \" in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
|
||||
return null
|
||||
|
||||
query_list += "[word]\""
|
||||
word = ""
|
||||
|
||||
else
|
||||
word += char
|
||||
|
||||
if(word != "")
|
||||
query_list += word
|
||||
|
||||
return query_list
|
||||
@@ -0,0 +1,426 @@
|
||||
|
||||
|
||||
/client/proc/SDQL2_query(query_text as message)
|
||||
set category = "Admin"
|
||||
if(!check_rights(R_DEBUG)) //Shouldn't happen... but just to be safe.
|
||||
message_admins("\red ERROR: Non-admin [usr.key] attempted to execute a SDQL query!")
|
||||
log_admin("Non-admin [usr.key] 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/query_tree = SDQL_parse(query_list)
|
||||
|
||||
if(query_tree.len < 1)
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
//usr << "Query: [query_text]"
|
||||
message_admins("[usr] executed SDQL query: \"[query_text]\".")
|
||||
|
||||
switch(query_tree[1])
|
||||
if("delete")
|
||||
for(var/datum/d in objs)
|
||||
del d
|
||||
|
||||
if("select")
|
||||
var/text = ""
|
||||
for(var/datum/t in objs)
|
||||
if(istype(t, /atom))
|
||||
var/atom/a = t
|
||||
|
||||
if(a.x)
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] at ([a.x], [a.y], [a.z])<br>"
|
||||
|
||||
else if(a.loc && a.loc.x)
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
|
||||
|
||||
else
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
|
||||
|
||||
else
|
||||
text += "<a href='?src=\ref[t];SDQL_select=\ref[t]'>\ref[t]</a>: [t]<br>"
|
||||
|
||||
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(query_list)
|
||||
var/list/query_tree = parser.parse()
|
||||
|
||||
del(parser)
|
||||
|
||||
return query_tree
|
||||
|
||||
|
||||
|
||||
/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))
|
||||
world << "[spaces]("
|
||||
SDQL_testout(item, indent + 1)
|
||||
world << "[spaces])"
|
||||
|
||||
else
|
||||
world << "[spaces][item]"
|
||||
|
||||
if(!isnum(item) && query_tree[item])
|
||||
|
||||
if(istype(query_tree[item], /list))
|
||||
world << "[spaces] ("
|
||||
SDQL_testout(query_tree[item], indent + 2)
|
||||
world << "[spaces] )"
|
||||
|
||||
else
|
||||
world << "[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 << "\red 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 << "\red SDQL2: You have an error in your SDQL syntax, unexpected ' in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". 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 << "\red SDQL2: You have an error in your SDQL syntax, unmatched ' in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
|
||||
return null
|
||||
|
||||
query_list += "[word]'"
|
||||
word = ""
|
||||
|
||||
else if(char == "\"")
|
||||
if(word != "")
|
||||
usr << "\red SDQL2: You have an error in your SDQL syntax, unexpected \" in query: \"<font color=gray>[query_text]</font>\" following \"<font color=gray>[word]</font>\". 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 << "\red SDQL2: You have an error in your SDQL syntax, unmatched \" in query: \"<font color=gray>[query_text]</font>\". Please check your syntax, and try again."
|
||||
return null
|
||||
|
||||
query_list += "[word]\""
|
||||
word = ""
|
||||
|
||||
else
|
||||
word += char
|
||||
|
||||
if(word != "")
|
||||
query_list += word
|
||||
|
||||
return query_list
|
||||
@@ -0,0 +1,531 @@
|
||||
//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 : <function name> ['(' [arguments] ')']
|
||||
// arguments : expression [',' arguments]
|
||||
//
|
||||
// object_type : <type path> | string
|
||||
//
|
||||
// assignments : assignment, [',' assignments]
|
||||
// assignment : <variable name> '=' expression
|
||||
// variable : <variable name> | <variable name> '.' 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 : ''' <some text> ''' | '"' <some text > '"'
|
||||
// number : <some digits>
|
||||
//
|
||||
//////////
|
||||
|
||||
/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 << "\red 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()
|
||||
i = call_function(i + 1, func)
|
||||
|
||||
node += "call"
|
||||
node["call"] = func
|
||||
|
||||
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: <variable name> '=' 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 name> | <variable name> '.' 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: <type path> | 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: ''' <some text> ''' | '"' <some text > '"'
|
||||
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: <function name> ['(' [arguments] ')']
|
||||
call_function(i, list/node)
|
||||
|
||||
parse_error("Sorry, function calls aren't available yet")
|
||||
|
||||
return i
|
||||
|
||||
|
||||
//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*/
|
||||
@@ -66,7 +66,7 @@ var/global/vox_tick = 1
|
||||
C.registered_user = src
|
||||
var/obj/item/weapon/storage/wallet/W = new(src)
|
||||
W.handle_item_insertion(C)
|
||||
spawn_money(rand(100,300)*5,W)
|
||||
spawn_money(rand(50,150)*10,W)
|
||||
equip_to_slot_or_del(W, slot_wear_id)
|
||||
|
||||
var/obj/item/weapon/implant/cortical/I = new(src)
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
s.start()
|
||||
|
||||
if(entersmoke)
|
||||
var/datum/effect/effect/system/harmless_smoke_spread/s = new /datum/effect/effect/system/harmless_smoke_spread
|
||||
var/datum/effect/effect/system/smoke_spread/s = new /datum/effect/effect/system/smoke_spread
|
||||
s.set_up(4, 1, src, 0)
|
||||
s.start()
|
||||
if(exitsmoke)
|
||||
var/datum/effect/effect/system/harmless_smoke_spread/s = new /datum/effect/effect/system/harmless_smoke_spread
|
||||
var/datum/effect/effect/system/smoke_spread/s = new /datum/effect/effect/system/smoke_spread
|
||||
s.set_up(4, 1, dest, 0)
|
||||
s.start()
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
breath = loc.remove_air(breath_moles)
|
||||
|
||||
// Handle chem smoke effect -- Doohl
|
||||
for(var/obj/effect/effect/chem_smoke/smoke in view(1, src))
|
||||
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
|
||||
if(smoke.reagents.total_volume)
|
||||
smoke.reagents.reaction(src, INGEST)
|
||||
spawn(5)
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
breath = loc.remove_air(breath_moles)
|
||||
|
||||
// Handle chem smoke effect -- Doohl
|
||||
for(var/obj/effect/effect/chem_smoke/smoke in view(1, src))
|
||||
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
|
||||
if(smoke.reagents.total_volume)
|
||||
smoke.reagents.reaction(src, INGEST)
|
||||
spawn(5)
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
|
||||
if(!block)
|
||||
|
||||
for(var/obj/effect/effect/chem_smoke/smoke in view(1, src))
|
||||
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
|
||||
if(smoke.reagents.total_volume)
|
||||
smoke.reagents.reaction(src, INGEST)
|
||||
spawn(5)
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
block = 1
|
||||
|
||||
if(!block)
|
||||
for(var/obj/effect/effect/chem_smoke/smoke in view(1, src))
|
||||
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
|
||||
if(smoke.reagents.total_volume)
|
||||
smoke.reagents.reaction(src, INGEST)
|
||||
spawn(5)
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
//smoke, water and steam calms us down
|
||||
var/calming = 0
|
||||
var/list/calmers = list(/obj/effect/effect/chem_smoke, \
|
||||
var/list/calmers = list(/obj/effect/effect/smoke/chem, \
|
||||
/obj/effect/effect/water, \
|
||||
/obj/effect/effect/foam, \
|
||||
/obj/effect/effect/steam, \
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
New()
|
||||
..()
|
||||
var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(5, 0, src.loc)
|
||||
smoke.start()
|
||||
visible_message("\red <B>The [src] warps in!</B>")
|
||||
|
||||
@@ -240,6 +240,8 @@ var/list/slot_equipment_priority = list( \
|
||||
set category = "Object"
|
||||
set src = usr
|
||||
|
||||
if(istype(loc,/obj/mecha)) return
|
||||
|
||||
if(hand)
|
||||
var/obj/item/W = l_hand
|
||||
if (W)
|
||||
|
||||
@@ -338,8 +338,9 @@ This function completely restores a damaged organ to perfect condition.
|
||||
|
||||
for(var/datum/wound/W in wounds)
|
||||
// wounds can disappear after 10 minutes at the earliest
|
||||
if(W.damage == 0 && W.created + 10 * 10 * 60 <= world.time)
|
||||
if(W.damage <= 0 && W.created + 10 * 10 * 60 <= world.time)
|
||||
wounds -= W
|
||||
continue
|
||||
// let the GC handle the deletion of the wound
|
||||
|
||||
// Internal wounds get worse over time. Low temperatures (cryo) stop them.
|
||||
@@ -347,17 +348,14 @@ This function completely restores a damaged organ to perfect condition.
|
||||
if(!owner.reagents.has_reagent("bicaridine")) //bicard stops internal wounds from growing bigger with time, and also stop bleeding
|
||||
W.open_wound(0.1 * wound_update_accuracy)
|
||||
owner.vessel.remove_reagent("blood",0.05 * W.damage * wound_update_accuracy)
|
||||
|
||||
owner.vessel.remove_reagent("blood",0.02 * W.damage * wound_update_accuracy)//Bicaridine slows Internal Bleeding
|
||||
if(prob(1 * wound_update_accuracy))
|
||||
owner.custom_pain("You feel a stabbing pain in your [display_name]!",1)
|
||||
|
||||
//overdose of bicaridine begins healing IB
|
||||
if(owner.reagents.has_reagent("bicaridine") && (owner.reagents.get_reagent_amount("bicaridine") >= 30))
|
||||
var/healinternal = 0.2
|
||||
if(W.damage <= healinternal)
|
||||
W.damage = 0
|
||||
else
|
||||
W.damage -= healinternal
|
||||
//overdose of bicaridine begins healing IB
|
||||
if(owner.reagents.get_reagent_amount("bicaridine") >= 30)
|
||||
W.damage = max(0, W.damage - 0.2)
|
||||
|
||||
// slow healing
|
||||
var/heal_amt = 0
|
||||
@@ -417,7 +415,10 @@ This function completely restores a damaged organ to perfect condition.
|
||||
var/n_is = damage_state_text()
|
||||
if (n_is != damage_state)
|
||||
damage_state = n_is
|
||||
owner.update_body(1)
|
||||
if(status & ORGAN_DESTROYED)
|
||||
owner.update_body(1)
|
||||
else
|
||||
owner.UpdateDamageIcon(1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@@ -962,7 +962,7 @@
|
||||
cell.corrupt()
|
||||
src.malfhack = 1
|
||||
update_icon()
|
||||
var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(3, 0, src.loc)
|
||||
smoke.attach(src)
|
||||
smoke.start()
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
for(var/mob/M in viewers(src))
|
||||
M.show_message("\red The [src.name] is making strange noises!", 3, "\red You hear sizzling electronics.", 2)
|
||||
sleep(10*pick(4,5,6,7,10,14))
|
||||
var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(3, 0, src.loc)
|
||||
smoke.attach(src)
|
||||
smoke.start()
|
||||
@@ -321,7 +321,7 @@
|
||||
emp_act(2)
|
||||
if(prob(5)) //smoke only
|
||||
world << "\red SMES smoke in [src.loc.loc]"
|
||||
var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(3, 0, src.loc)
|
||||
smoke.attach(src)
|
||||
smoke.start()
|
||||
|
||||
@@ -31,7 +31,7 @@ datum
|
||||
var/datum/reagent/self = src
|
||||
src = null //of the reagent to the mob on TOUCHING it.
|
||||
|
||||
if(!istype(self.holder.my_atom, /obj/effect/effect/chem_smoke))
|
||||
if(!istype(self.holder.my_atom, /obj/effect/effect/smoke/chem))
|
||||
// If the chemicals are in a smoke cloud, do not try to let the chemicals "penetrate" into the mob's system (balance station 13) -- Doohl
|
||||
|
||||
if(method == TOUCH)
|
||||
@@ -3091,7 +3091,7 @@ datum
|
||||
var/datum/organ/internal/heart/L = H.internal_organs["heart"]
|
||||
if (istype(L))
|
||||
L.take_damage(100, 0)
|
||||
|
||||
holder.remove_reagent(src.id, FOOD_METABOLISM)
|
||||
|
||||
ethanol/deadrum
|
||||
name = "Deadrum"
|
||||
|
||||
@@ -433,7 +433,7 @@ datum
|
||||
secondary = 1
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
var/datum/effect/effect/system/chem_smoke_spread/S = new /datum/effect/effect/system/chem_smoke_spread
|
||||
var/datum/effect/effect/system/smoke_spread/chem/S = new /datum/effect/effect/system/smoke_spread/chem
|
||||
S.attach(location)
|
||||
S.set_up(holder, 10, 0, location)
|
||||
playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
if(istype(W,/obj/item/weapon/storage))
|
||||
..() // -> item/attackby()
|
||||
if((slices_num <= 0 || !slices_num) || !slice_path)
|
||||
return 1
|
||||
return 0
|
||||
var/inaccurate = 0
|
||||
if( \
|
||||
istype(W, /obj/item/weapon/kitchenknife) || \
|
||||
|
||||
@@ -101,7 +101,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
|
||||
user << "\The [name] must be linked to an R&D console first!"
|
||||
return 1
|
||||
if (O.is_open_container())
|
||||
return 1
|
||||
return 0
|
||||
if (!istype(O, /obj/item/stack/sheet/glass) && !istype(O, /obj/item/stack/sheet/mineral/gold) && !istype(O, /obj/item/stack/sheet/mineral/diamond) && !istype(O, /obj/item/stack/sheet/mineral/uranium))
|
||||
user << "\red You cannot insert this item into the [name]!"
|
||||
return 1
|
||||
|
||||
@@ -99,6 +99,7 @@ Note: Must be placed within 3 tiles of the R&D Console
|
||||
spawn(10)
|
||||
icon_state = "d_analyzer_l"
|
||||
busy = 0
|
||||
return 1
|
||||
return
|
||||
|
||||
//For testing purposes only.
|
||||
|
||||
Reference in New Issue
Block a user