var/global/automation_types=typesof(/datum/automation) - /datum/automation #define AUTOM_RT_NULL 0 #define AUTOM_RT_NUM 1 #define AUTOM_RT_STRING 2 /datum/automation // Name of the Automation var/name = "Base Automation" // For labelling what shit does on the AAC. var/label = "Unnamed Script" var/desc = "No Description." var/obj/machinery/computer/general_air_control/atmos_automation/parent var/list/valid_child_returntypes = list() var/list/datum/automation/children = list() var/returntype = AUTOM_RT_NULL /datum/automation/New(var/obj/machinery/computer/general_air_control/atmos_automation/aa) parent = aa /datum/automation/proc/GetText() return "[type] doesn't override GetText()!" /datum/automation/proc/OnReset() return /datum/automation/proc/OnRemove() return /datum/automation/proc/process() return /datum/automation/proc/Evaluate() return 0 /datum/automation/proc/Export() var/list/R = list("type" = type) if(initial(label) != label) R["label"] = label if(initial(desc) != desc) R["desc"] = desc if(children.len) var/list/C = list() for(var/datum/automation/A in children) C += list(A.Export()) R["children"] = C return R /datum/automation/proc/unpackChild(var/list/cData) if(isnull(cData) || !("type" in cData)) return null var/Atype = text2path(cData["type"]) if(!(Atype in automation_types)) return null var/datum/automation/A = new Atype(parent) A.Import(cData) return A /datum/automation/proc/unpackChildren(var/list/childList) . = list() if(childList.len > 0) for(var/list/cData in childList) if(isnull(cData) || !("type" in cData)) . += null continue var/Atype = text2path(cData["type"]) if(!(Atype in automation_types)) continue var/datum/automation/A = new Atype(parent) A.Import(cData) . += A /datum/automation/proc/packChildren(var/list/childList) . = list() if(childList.len > 0) for(var/datum/automation/A in childList) if(isnull(A) || !istype(A)) . += null continue . += list(A.Export()) /datum/automation/proc/Import(var/list/json) if("label" in json) label = json["label"] if("desc" in json) desc = json["desc"] if("children" in json) children = unpackChildren(json["children"]) /datum/automation/proc/fmtString(var/str) return str || "-----" // TODO: Standardize this somewhere. // This determines if a mob can send hrefs or other commands. /datum/automation/proc/canWriteState(var/mob/user, var/href) if(isobserver(user)) var/mob/dead/observer/O = user var/ghost_flags = 0 if(parent.ghost_write) ghost_flags |= PERMIT_ALL if(canGhostWrite(O,parent,"",ghost_flags) || isAdminGhost(O)) if(!parent.custom_aghost_alerts) log_adminghost("[key_name(user)] screwed with [parent] ([href])!") return TRUE // Ghost is admin or otherwise allowed to dick with things. return FALSE // Ghost is NOT admin? Bail. if(user.incapacitated() || user.lying) return FALSE // Lying down, or incapacitated. if (!user.dexterity_check()) to_chat(user, "You don't have the dexterity to do this!") return FALSE // Silicons can access shit from out of range. if(istype(user, /mob/living/silicon)) return TRUE // RAAAANGE CHEEEECK return in_range(parent, user) && isturf(parent.loc) /datum/automation/Topic(var/href, var/list/href_list) if(!canWriteState(usr, href)) return 1 if(href_list["add"]) var/new_child = selectValidChildFor(usr) if(!new_child) return 1 children += new_child parent.updateUsrDialog() return 1 if(href_list["remove"]) if(href_list["remove"] == "*") var/confirm=alert("Are you sure you want to remove ALL automations?", "Automations", "Yes", "No") if(confirm == "No") return 0 for(var/datum/automation/A in children) A.OnRemove() children.Remove(A) else var/datum/automation/A=locate(href_list["remove"]) if(!A) return 1 var/confirm = alert("Are you sure you want to remove this automation?", "Automations", "Yes", "No") if(confirm == "No") return 0 A.OnRemove() children.Remove(A) parent.updateUsrDialog() return 1 if(href_list["reset"]) if(href_list["reset"] == "*") for(var/datum/automation/A in children) A.OnReset() else var/datum/automation/A=locate(href_list["reset"]) if(!A) return 1 A.OnReset() parent.updateUsrDialog() return 1 parent.add_fingerprint(usr) return 0 // 1 if handled /datum/automation/proc/selectValidChildFor(var/mob/user, var/list/returntypes = valid_child_returntypes) return parent.selectValidChildFor(src, user, returntypes) /////////////////////////////////////////// // AND /////////////////////////////////////////// /datum/automation/and name = "AND statement" returntype = AUTOM_RT_NUM valid_child_returntypes = list(AUTOM_RT_NUM) /datum/automation/and/Evaluate() if(!children.len) return 0 for(var/datum/automation/stmt in children) if(!stmt.Evaluate()) return 0 return 1 /datum/automation/and/GetText() . = "AND (Add)" if(children.len > 0) . += "
" else . += "No statements to evaluate." /////////////////////////////////////////// // OR /////////////////////////////////////////// /datum/automation/or name = "OR statement" returntype = AUTOM_RT_NUM valid_child_returntypes = list(AUTOM_RT_NUM) /datum/automation/or/Evaluate() if(!children.len) return 0 for(var/datum/automation/stmt in children) if(stmt.Evaluate()) return 1 return 0 /datum/automation/or/GetText() . = "OR (Add)" if(children.len>0) . += "" else . += "
No statements to evaluate." /////////////////////////////////////////// // if .. then /////////////////////////////////////////// /datum/automation/if_statement name = "IF statement" var/datum/automation/condition = null valid_child_returntypes = list(AUTOM_RT_NULL) var/list/valid_conditions = list(AUTOM_RT_NUM) var/list/children_then = list() var/list/children_else = list() /datum/automation/if_statement/Export() var/list/R = ..() if(children_then.len > 0) R["then"] = packChildren(children_then) if(children_else.len > 0) R["else"] = packChildren(children_else) if(condition) R["condition"] = condition.Export() return R /datum/automation/if_statement/Import(var/list/json) ..() if("then" in json) children_then = unpackChildren(json["then"]) if("else" in json) children_else = unpackChildren(json["else"]) if("condition" in json) condition = unpackChild(json["condition"]) /datum/automation/if_statement/GetText() . = "IF (SET):
" if(condition) . += condition.GetText() else . += "Not set" . += "" . += "THEN: (Add)" if(children_then.len) . += "" else . += "
(No statements to run)" . += "ELSE: (Add)" if(children_then.len) . += "" else . += "
(No statements to run)" /datum/automation/if_statement/Topic(var/href, var/list/href_list) if(..(href, href_list - list("add", "remove", "reset"))) // So we can do sanity but not make it trigger on these specific hrefs overriden with shitcode here. return 1 if(href_list["add"]) var/new_child = selectValidChildFor(usr) if(!new_child) return 1 switch(href_list["add"]) if("then") children_then += new_child if("else") children_else += new_child else warning("Unknown add value given to [type]/Topic():[__LINE__]: [href]") return 1 parent.updateUsrDialog() return 1 if(href_list["remove"]) if(href_list["remove"] == "*") var/confirm=input("Are you sure you want to remove ALL automations?", "Automations", "No") in list("Yes", "No") if(confirm == "No") return 0 for(var/datum/automation/A in children_then) A.OnRemove() children_then.Remove(A) for(var/datum/automation/A in children_else) A.OnRemove() children_else.Remove(A) else var/datum/automation/A = locate(href_list["remove"]) if(!A) return 1 var/confirm = input("Are you sure you want to remove this automation?", "Automations", "No") in list("Yes", "No") if(confirm == "No") return 0 A.OnRemove() switch(href_list["context"]) if("then") children_then.Remove(A) if("else") children_else.Remove(A) parent.updateUsrDialog() return 1 if(href_list["reset"]) if(href_list["reset"] == "*") for(var/datum/automation/A in children_then) A.OnReset() for(var/datum/automation/A in children_else) A.OnReset() else var/datum/automation/A=locate(href_list["reset"]) if(!A) return 1 A.OnReset() parent.updateUsrDialog() return 1 if(href_list["set_condition"]) var/new_condition = selectValidChildFor(usr, valid_conditions) //testing("Selected condition: [new_condition]") if(!new_condition) return 1 condition = new_condition parent.updateUsrDialog() return 1 /datum/automation/if_statement/process() if(condition) if(condition.Evaluate()) for(var/datum/automation/stmt in children_then) stmt.process() else for(var/datum/automation/stmt in children_else) stmt.process() /////////////////////////////////////////// // compare /////////////////////////////////////////// /datum/automation/compare name = "comparison" var/comparator = "Greater Than" returntype = AUTOM_RT_NUM valid_child_returntypes = list(AUTOM_RT_NUM) /datum/automation/compare/New(var/obj/machinery/computer/general_air_control/atmos_automation/aa) ..() children = list(null, null) /datum/automation/compare/Export() var/list/json = ..() json["cmp"] = comparator return json /datum/automation/compare/Import(var/list/json) ..() comparator = json["cmp"] /datum/automation/compare/Evaluate() if(children.len < 2) return 0 var/datum/automation/d_left = children[1] var/datum/automation/d_right = children[2] if(!d_left || !d_right) return 0 var/left = d_left.Evaluate() var/right = d_right.Evaluate() switch(comparator) if("Greater Than") return left > right if("Greater Than or Equal to") return left >= right if("Less Than") return left < right if("Less Than or Equal to") return left <= right if("Equal to") return left == right if("NOT Equal To") return left != right else return 0 /datum/automation/compare/GetText() var/datum/automation/left = children[1] var/datum/automation/right = children[2] . = "(Set Left) (" if(left == null) . += "-----" else . += left.GetText() . += ") is [comparator]: (Set Right) (" if(right==null) . += "-----" else . += right.GetText() . +=")" /datum/automation/compare/Topic(href,href_list) . = ..() if(.) return if(href_list["set_comparator"]) comparator = input("Select a comparison operator:", "Compare", "Greater Than") in list("Greater Than", "Greater Than or Equal to", "Less Than", "Less Than or Equal to", "Equal to", "NOT Equal To") parent.updateUsrDialog() return 1 if(href_list["set_field"]) var/idx = text2num(href_list["set_field"]) var/new_child = selectValidChildFor(usr) if(!new_child) return 1 children[idx] = new_child parent.updateUsrDialog() return 1 /////////////////////////////////////////// // static value /////////////////////////////////////////// /datum/automation/static_value name = "Number" var/value = 0 returntype = AUTOM_RT_NUM /datum/automation/static_value/Evaluate() return value /datum/automation/static_value/Export() var/list/json = ..() json["value"] = value return json /datum/automation/static_value/Import(var/list/json) ..() value = text2num(json["value"]) /datum/automation/static_value/GetText() return "[value]" /datum/automation/static_value/Topic(href,href_list) . = ..() if(.) return if(href_list["set_value"]) value = input("Set a value:", "Static Value", value) as num parent.updateUsrDialog() return 1 /////////////////////////////////////////// // add /////////////////////////////////////////// /datum/automation/sum name = "sum statement" returntype = AUTOM_RT_NUM valid_child_returntypes = list(AUTOM_RT_NUM) /datum/automation/sum/Evaluate() if(!children.len) return 0 . = 0 for(var/datum/automation/stmt in children) . += stmt.Evaluate() /datum/automation/sum/GetText() . = "SUM (Add)" if(children.len) . += "" else . += "
No statements to evaluate." /////////////////////////////////////////// // average /////////////////////////////////////////// /datum/automation/avg name = "avg statement" returntype = AUTOM_RT_NUM valid_child_returntypes = list(AUTOM_RT_NUM) /datum/automation/avg/Evaluate() if(!children.len) return 0 . = 0 for(var/datum/automation/stmt in children) . += stmt.Evaluate() . /= children.len /datum/automation/avg/GetText() . = "AVG (Add)" if(children.len) . += "" else . += "
No statements to evaluate." /////////////////////////////////////////// // binary operators (left and right) /////////////////////////////////////////// /datum/automation/binary name = "binary statement" returntype = null valid_child_returntypes = list(AUTOM_RT_NUM) var/operator = "???" /datum/automation/binary/New() ..() children = list(null, null) /datum/automation/binary/Evaluate() if(children.len != 2) return 0 var/datum/automation/a = children[1] var/datum/automation/b = children[2] if(!a || !b) return 0 return do_operation(a.Evaluate(), b.Evaluate()) /datum/automation/binary/proc/do_operation(var/a, var/b) return 0 /datum/automation/binary/GetText() var/datum/automation/left = children[1] var/datum/automation/right = children[2] . = "(Set Left) (" if(left == null) . += "-----" else . += left.GetText() . += ") [operator] (Set Right) (" if(right == null) . += "-----" else . += right.GetText() . += ")" /datum/automation/binary/Topic(var/href, var/list/href_list) . = ..() if(.) return if(href_list["set_field"]) var/idx = text2num(href_list["set_field"]) var/new_child = selectValidChildFor(usr) if(!new_child) return 1 children[idx] = new_child parent.updateUsrDialog() return 1 /datum/automation/binary/add name = "add" returntype = AUTOM_RT_NUM operator = "+" /datum/automation/binary/add/do_operation(var/a, var/b) return a + b /datum/automation/binary/subtract name ="subtract" returntype =AUTOM_RT_NUM operator = "-" /datum/automation/binary/subtract/do_operation(var/a, var/b) return a - b /datum/automation/binary/multiply name = "multiply" returntype = AUTOM_RT_NUM operator = "*" /datum/automation/binary/multiply/do_operation(var/a, var/b) return a * b /datum/automation/binary/divide name = "divide" returntype = AUTOM_RT_NUM operator = "/" /datum/automation/binary/divide/do_operation(var/a, var/b) if(!b) return INFINITY // Not how division by zero works but alright. return a / b /datum/automation/binary/modulus name = "modulus" returntype = AUTOM_RT_NUM operator = "%" /datum/automation/binary/modulus/do_operation(var/a, var/b) if(!b) return INFINITY return a % b