From 39a97a6f772664f3b65b8deed20e83b4728ece4b Mon Sep 17 00:00:00 2001 From: "giacomand@gmail.com" Date: Wed, 13 Feb 2013 21:43:34 +0000 Subject: [PATCH] NTSL Update: - You can now send signals with signal(freq, code). Added a cooldown to limit spamming. - You can now use "elseif" in your scripts to create a chain. - You can now use "return" in the global scope to end the script from running. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@5701 316c924e-a436-60f5-8080-3fe189b3f50e --- code/game/machinery/doors/airlock.dm | 1 - .../machinery/telecomms/telecomunications.dm | 1 + code/modules/assembly/signaler.dm | 1 - code/modules/scripting/AST/Statements.dm | 4 ++ .../scripting/Implementations/Telecomms.dm | 46 +++++++++++++++++-- .../scripting/Interpreter/Interpreter.dm | 19 ++++++-- code/modules/scripting/Options.dm | 2 +- code/modules/scripting/Parser/Expressions.dm | 3 +- code/modules/scripting/Parser/Keywords.dm | 31 +++++++++++-- code/setup.dm | 1 + html/changelog.html | 2 + 11 files changed, 96 insertions(+), 15 deletions(-) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index da40b83308fb..7ef01cc7eb1a 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -51,7 +51,6 @@ var/aiHacking = 0 var/obj/machinery/door/airlock/closeOther = null var/closeOtherId = null - var/list/signalers[12] var/lockdownbyai = 0 autoclose = 1 var/doortype = 0 diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 363e51095d4d..29d92eda7951 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -519,6 +519,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list() // would add up to md5("password123comsat") var/language = "human" var/obj/item/device/radio/headset/server_radio = null + var/last_signal = 0 // Last time it sent a signal /obj/machinery/telecomms/server/New() ..() diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index 19ca750a4a64..2727fe6fe482 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -135,7 +135,6 @@ if(signal.encryption != code) return 0 if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0 pulse(1) - for(var/mob/O in hearers(1, src.loc)) O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) return diff --git a/code/modules/scripting/AST/Statements.dm b/code/modules/scripting/AST/Statements.dm index e60fcb389c54..bde48e0e7fec 100644 --- a/code/modules/scripting/AST/Statements.dm +++ b/code/modules/scripting/AST/Statements.dm @@ -69,11 +69,15 @@ // IfStatement var + skip = 0 node BlockDefinition block else_block //may be null expression/cond + statement/else_if + + ElseIf /* Class: WhileLoop diff --git a/code/modules/scripting/Implementations/Telecomms.dm b/code/modules/scripting/Implementations/Telecomms.dm index c0241f04904f..abb71a9e199a 100644 --- a/code/modules/scripting/Implementations/Telecomms.dm +++ b/code/modules/scripting/Implementations/Telecomms.dm @@ -92,6 +92,15 @@ */ interpreter.SetProc("broadcast", "tcombroadcast", signal, list("message", "freq", "source", "job")) + /* + -> Send a code signal. + @format: signal(frequency, code) + + @param frequency: Frequency to send the signal to + @param code: Encryption code to send the signal with + */ + interpreter.SetProc("signal", "signaler", signal, list("freq", "code")) + /* -> Store a value permanently to the server machine (not the actual game hosting machine, the ingame machine) @format: mem(address, value) @@ -210,6 +219,8 @@ /* -- Actual language proc code -- */ +var/const/SIGNAL_COOLDOWN = 20 // 2 seconds + datum/signal proc/mem(var/address, var/value) @@ -224,6 +235,33 @@ datum/signal S.memory[address] = value + proc/signaler(var/freq = 1459, var/code = 30) + if(isnum(freq) && isnum(code)) + + var/obj/machinery/telecomms/server/S = data["server"] + + if(S.last_signal + SIGNAL_COOLDOWN > world.timeofday && S.last_signal < MIDNIGHT_ROLLOVER) + return + S.last_signal = world.timeofday + + var/datum/radio_frequency/connection = radio_controller.return_frequency(freq) + + if(findtext(num2text(freq), ".")) // if the frequency has been set as a decimal + freq *= 10 // shift the decimal one place + + freq = sanitize_frequency(freq) + + var/datum/signal/signal = new + signal.source = S + signal.encryption = code + signal.data["message"] = "ACTIVATE" + + connection.post_signal(S, signal) + + var/time = time2text(world.realtime,"hh:mm:ss") + lastsignalers.Add("[time] : [S.id] sent a signal command, which was triggered by NTSL.: [format_frequency(freq)]/[code]") + + proc/tcombroadcast(var/message, var/freq, var/source, var/job) var/datum/signal/newsign = new @@ -239,7 +277,7 @@ datum/signal if(!source) source = "[html_encode(uppertext(S.id))]" hradio = new // sets the hradio as a radio intercom - if(!freq) + if(!freq || (!isnum(freq) && text2num(freq) == null)) freq = 1459 if(findtext(num2text(freq), ".")) // if the frequency has been set as a decimal freq *= 10 // shift the decimal one place @@ -250,13 +288,13 @@ datum/signal newsign.data["mob"] = null newsign.data["mobtype"] = /mob/living/carbon/human if(source in S.stored_names) - newsign.data["name"] = source + newsign.data["name"] = "[source]" else newsign.data["name"] = "[html_encode(uppertext(source))]" newsign.data["realname"] = newsign.data["name"] - newsign.data["job"] = job + newsign.data["job"] = "[job]" newsign.data["compression"] = 0 - newsign.data["message"] = message + newsign.data["message"] = "[message]" newsign.data["type"] = 2 // artificial broadcast if(!isnum(freq)) freq = text2num(freq) diff --git a/code/modules/scripting/Interpreter/Interpreter.dm b/code/modules/scripting/Interpreter/Interpreter.dm index 70849ffa157a..43a53a50ee04 100644 --- a/code/modules/scripting/Interpreter/Interpreter.dm +++ b/code/modules/scripting/Interpreter/Interpreter.dm @@ -223,10 +223,21 @@ Checks a condition and runs either the if block or else block. */ RunIf(node/statement/IfStatement/stmt) - if(Eval(stmt.cond)) - RunBlock(stmt.block) - else if(stmt.else_block) - RunBlock(stmt.else_block) + if(!stmt.skip) + if(Eval(stmt.cond)) + RunBlock(stmt.block) + // Loop through the if else chain and tell them to be skipped. + var/node/statement/IfStatement/i = stmt.else_if + var/fail_safe = 800 + while(i && fail_safe) + fail_safe -= 1 + i.skip = 1 + i = i.else_if + + else if(stmt.else_block) + RunBlock(stmt.else_block) + // We don't need to skip you anymore. + stmt.skip = 0 /* Proc: RunWhile diff --git a/code/modules/scripting/Options.dm b/code/modules/scripting/Options.dm index 22774455dc4f..e9d6c3e4ad14 100644 --- a/code/modules/scripting/Options.dm +++ b/code/modules/scripting/Options.dm @@ -50,7 +50,7 @@ n_scriptOptions An associative list used by the parser to parse keywords. Indices are strings which will trigger the keyword when parsed and the associated values are types of which the proc will be called. */ - keywords = list("if" = /n_Keyword/nS_Keyword/kwIf, "else" = /n_Keyword/nS_Keyword/kwElse, \ + keywords = list("if" = /n_Keyword/nS_Keyword/kwIf, "else" = /n_Keyword/nS_Keyword/kwElse, "elseif" = /n_Keyword/nS_Keyword/kwElseIf, \ "while" = /n_Keyword/nS_Keyword/kwWhile, "break" = /n_Keyword/nS_Keyword/kwBreak, \ "continue" = /n_Keyword/nS_Keyword/kwContinue, \ "return" = /n_Keyword/nS_Keyword/kwReturn, "def" = /n_Keyword/nS_Keyword/kwDef) diff --git a/code/modules/scripting/Parser/Expressions.dm b/code/modules/scripting/Parser/Expressions.dm index f27a30d3ad3b..cdbd4ee4ff27 100644 --- a/code/modules/scripting/Parser/Expressions.dm +++ b/code/modules/scripting/Parser/Expressions.dm @@ -281,7 +281,8 @@ for() loops++ if(loops>=1000) - CRASH("Something TERRIBLE has gone wrong in ParseFunctionExpression ;__;") + break + //CRASH("Something TERRIBLE has gone wrong in ParseFunctionExpression ;__;") if(istype(curToken, /token/symbol) && curToken.value==")") return exp diff --git a/code/modules/scripting/Parser/Keywords.dm b/code/modules/scripting/Parser/Keywords.dm index bdd33d8bda02..229e2fd60518 100644 --- a/code/modules/scripting/Parser/Keywords.dm +++ b/code/modules/scripting/Parser/Keywords.dm @@ -51,9 +51,9 @@ var/const/Represents a special statement in the code triggered by a keyword. kwReturn Parse(n_Parser/nS_Parser/parser) .=KW_PASS - if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock)) - parser.errors+=new/scriptError/BadReturn(parser.curToken) - . = KW_WARN + if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock)) // Exit out of the program by setting the tokens list size to the same as index. + parser.tokens.len = parser.index + return var/node/statement/ReturnStatement/stmt=new parser.NextToken() //skip 'return' token stmt.value=parser.ParseExpression() @@ -73,6 +73,31 @@ var/const/Represents a special statement in the code triggered by a keyword. stmt.block=new parser.AddBlock(stmt.block) + kwElseIf + Parse(n_Parser/nS_Parser/parser) + .=KW_PASS + var/list/L=parser.curBlock.statements + var/node/statement/IfStatement/ifstmt + + if(L && L.len) + ifstmt = L[L.len] //Get the last statement in the current block + if(!ifstmt || !istype(ifstmt) || ifstmt.else_if) + parser.errors += new/scriptError/ExpectedToken("if statement", parser.curToken) + return KW_FAIL + + var/node/statement/IfStatement/ElseIf/stmt = new + parser.NextToken() //skip 'if' token + stmt.cond = parser.ParseParenExpression() + if(!parser.CheckToken(")", /token/symbol)) + return KW_FAIL + if(!parser.CheckToken("{", /token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0 + return KW_ERR + parser.curBlock.statements+=stmt + stmt.block=new + ifstmt.else_if = stmt + parser.AddBlock(stmt.block) + + kwElse Parse(n_Parser/nS_Parser/parser) .=KW_PASS diff --git a/code/setup.dm b/code/setup.dm index 4a451ac10be1..4e95606f2aab 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -3,6 +3,7 @@ #define DEBUG #define PI 3.1415 +#define MIDNIGHT_ROLLOVER 864000 #define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol) #define ONE_ATMOSPHERE 101.325 //kPa diff --git a/html/changelog.html b/html/changelog.html index 64bb10adef29..fd63ac00b32d 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -54,6 +54,8 @@ should be listed in the changelog upon commit tho. Thanks. -->
  • There are now hackable wires for the PA computer. To open the interface, click on it while the wires are exposed/panel is open. All but one wire will do something interesting, see if you can figure it out. You can also attach signallers to the wires so have fun remotely releasing the singularity.
  • New staff of animation icon by Teh Wolf!
  • +
  • You can now hack plastic explosives (C4)!
  • +
  • You can now use NTSL to send signals! With the function signal(frequency, code) you can create some clever ways to trigger a bomb. NTSL also has two new additions; return in the global scope will now stop the remaining code from executing and NTSL now has "elseif"s, huzzah!