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..8a51495f541
--- /dev/null
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -0,0 +1,426 @@
+// Code taken from /bay/station.
+
+/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 += "\ref[t]: [t] at ([a.x], [a.y], [a.z])
"
+
+ else if(a.loc && a.loc.x)
+ text += "\ref[t]: [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])
"
+
+ else
+ text += "\ref[t]: [t]
"
+
+ else
+ text += "\ref[t]: [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(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: \"[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 << "\red 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 << "\red 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 << "\red 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..d1d30b33b5e
--- /dev/null
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_parser.dm
@@ -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 : ['(' [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 << "\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: '=' 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)
+
+ 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*/
\ No newline at end of file
diff --git a/tgstation.dme b/tgstation.dme
index 58437ae429a..bb8565986f5 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -705,6 +705,8 @@
#include "code\modules\admin\verbs\randomverbs.dm"
#include "code\modules\admin\verbs\ticklag.dm"
#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\assembly\assembly.dm"
#include "code\modules\assembly\bomb.dm"
#include "code\modules\assembly\helpers.dm"