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
This commit is contained in:
giacomand@gmail.com
2013-02-13 21:43:34 +00:00
parent 9f1318f48d
commit 39a97a6f77
11 changed files with 96 additions and 15 deletions

View File

@@ -51,7 +51,6 @@
var/aiHacking = 0 var/aiHacking = 0
var/obj/machinery/door/airlock/closeOther = null var/obj/machinery/door/airlock/closeOther = null
var/closeOtherId = null var/closeOtherId = null
var/list/signalers[12]
var/lockdownbyai = 0 var/lockdownbyai = 0
autoclose = 1 autoclose = 1
var/doortype = 0 var/doortype = 0

View File

@@ -519,6 +519,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
// would add up to md5("password123comsat") // would add up to md5("password123comsat")
var/language = "human" var/language = "human"
var/obj/item/device/radio/headset/server_radio = null var/obj/item/device/radio/headset/server_radio = null
var/last_signal = 0 // Last time it sent a signal
/obj/machinery/telecomms/server/New() /obj/machinery/telecomms/server/New()
..() ..()

View File

@@ -135,7 +135,6 @@
if(signal.encryption != code) return 0 if(signal.encryption != code) return 0
if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0 if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0
pulse(1) pulse(1)
for(var/mob/O in hearers(1, src.loc)) for(var/mob/O in hearers(1, src.loc))
O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2)
return return

View File

@@ -69,11 +69,15 @@
// //
IfStatement IfStatement
var var
skip = 0
node node
BlockDefinition BlockDefinition
block block
else_block //may be null else_block //may be null
expression/cond expression/cond
statement/else_if
ElseIf
/* /*
Class: WhileLoop Class: WhileLoop

View File

@@ -92,6 +92,15 @@
*/ */
interpreter.SetProc("broadcast", "tcombroadcast", signal, list("message", "freq", "source", "job")) 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) -> Store a value permanently to the server machine (not the actual game hosting machine, the ingame machine)
@format: mem(address, value) @format: mem(address, value)
@@ -210,6 +219,8 @@
/* -- Actual language proc code -- */ /* -- Actual language proc code -- */
var/const/SIGNAL_COOLDOWN = 20 // 2 seconds
datum/signal datum/signal
proc/mem(var/address, var/value) proc/mem(var/address, var/value)
@@ -224,6 +235,33 @@ datum/signal
S.memory[address] = value 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] <B>:</B> [S.id] sent a signal command, which was triggered by NTSL.<B>:</B> [format_frequency(freq)]/[code]")
proc/tcombroadcast(var/message, var/freq, var/source, var/job) proc/tcombroadcast(var/message, var/freq, var/source, var/job)
var/datum/signal/newsign = new var/datum/signal/newsign = new
@@ -239,7 +277,7 @@ datum/signal
if(!source) if(!source)
source = "[html_encode(uppertext(S.id))]" source = "[html_encode(uppertext(S.id))]"
hradio = new // sets the hradio as a radio intercom hradio = new // sets the hradio as a radio intercom
if(!freq) if(!freq || (!isnum(freq) && text2num(freq) == null))
freq = 1459 freq = 1459
if(findtext(num2text(freq), ".")) // if the frequency has been set as a decimal if(findtext(num2text(freq), ".")) // if the frequency has been set as a decimal
freq *= 10 // shift the decimal one place freq *= 10 // shift the decimal one place
@@ -250,13 +288,13 @@ datum/signal
newsign.data["mob"] = null newsign.data["mob"] = null
newsign.data["mobtype"] = /mob/living/carbon/human newsign.data["mobtype"] = /mob/living/carbon/human
if(source in S.stored_names) if(source in S.stored_names)
newsign.data["name"] = source newsign.data["name"] = "[source]"
else else
newsign.data["name"] = "<i>[html_encode(uppertext(source))]<i>" newsign.data["name"] = "<i>[html_encode(uppertext(source))]<i>"
newsign.data["realname"] = newsign.data["name"] newsign.data["realname"] = newsign.data["name"]
newsign.data["job"] = job newsign.data["job"] = "[job]"
newsign.data["compression"] = 0 newsign.data["compression"] = 0
newsign.data["message"] = message newsign.data["message"] = "[message]"
newsign.data["type"] = 2 // artificial broadcast newsign.data["type"] = 2 // artificial broadcast
if(!isnum(freq)) if(!isnum(freq))
freq = text2num(freq) freq = text2num(freq)

View File

@@ -223,10 +223,21 @@
Checks a condition and runs either the if block or else block. Checks a condition and runs either the if block or else block.
*/ */
RunIf(node/statement/IfStatement/stmt) RunIf(node/statement/IfStatement/stmt)
if(Eval(stmt.cond)) if(!stmt.skip)
RunBlock(stmt.block) if(Eval(stmt.cond))
else if(stmt.else_block) RunBlock(stmt.block)
RunBlock(stmt.else_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 Proc: RunWhile

View File

@@ -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 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 <nS_Keyword> types of which the <n_Keyword.Parse()> proc will be called. associated values are <nS_Keyword> types of which the <n_Keyword.Parse()> 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, \ "while" = /n_Keyword/nS_Keyword/kwWhile, "break" = /n_Keyword/nS_Keyword/kwBreak, \
"continue" = /n_Keyword/nS_Keyword/kwContinue, \ "continue" = /n_Keyword/nS_Keyword/kwContinue, \
"return" = /n_Keyword/nS_Keyword/kwReturn, "def" = /n_Keyword/nS_Keyword/kwDef) "return" = /n_Keyword/nS_Keyword/kwReturn, "def" = /n_Keyword/nS_Keyword/kwDef)

View File

@@ -281,7 +281,8 @@
for() for()
loops++ loops++
if(loops>=1000) 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==")") if(istype(curToken, /token/symbol) && curToken.value==")")
return exp return exp

View File

@@ -51,9 +51,9 @@ var/const/Represents a special statement in the code triggered by a keyword.
kwReturn kwReturn
Parse(n_Parser/nS_Parser/parser) Parse(n_Parser/nS_Parser/parser)
.=KW_PASS .=KW_PASS
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock)) if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock)) // Exit out of the program by setting the tokens list size to the same as index.
parser.errors+=new/scriptError/BadReturn(parser.curToken) parser.tokens.len = parser.index
. = KW_WARN return
var/node/statement/ReturnStatement/stmt=new var/node/statement/ReturnStatement/stmt=new
parser.NextToken() //skip 'return' token parser.NextToken() //skip 'return' token
stmt.value=parser.ParseExpression() stmt.value=parser.ParseExpression()
@@ -73,6 +73,31 @@ var/const/Represents a special statement in the code triggered by a keyword.
stmt.block=new stmt.block=new
parser.AddBlock(stmt.block) 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 kwElse
Parse(n_Parser/nS_Parser/parser) Parse(n_Parser/nS_Parser/parser)
.=KW_PASS .=KW_PASS

View File

@@ -3,6 +3,7 @@
#define DEBUG #define DEBUG
#define PI 3.1415 #define PI 3.1415
#define MIDNIGHT_ROLLOVER 864000
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol) #define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
#define ONE_ATMOSPHERE 101.325 //kPa #define ONE_ATMOSPHERE 101.325 //kPa

View File

@@ -54,6 +54,8 @@ should be listed in the changelog upon commit tho. Thanks. -->
<ul class="changes bgimages16"> <ul class="changes bgimages16">
<li class="rscadd">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.</li> <li class="rscadd">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.</li>
<li class="imageadd">New staff of animation icon by Teh Wolf!</li> <li class="imageadd">New staff of animation icon by Teh Wolf!</li>
<li class="rscadd">You can now hack plastic explosives (C4)!</li>
<li class="rscadd">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!</li>
</ul> </ul>
</div> </div>