mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-18 19:44:58 +01:00
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:
@@ -69,11 +69,15 @@
|
||||
//
|
||||
IfStatement
|
||||
var
|
||||
skip = 0
|
||||
node
|
||||
BlockDefinition
|
||||
block
|
||||
else_block //may be null
|
||||
expression/cond
|
||||
statement/else_if
|
||||
|
||||
ElseIf
|
||||
|
||||
/*
|
||||
Class: WhileLoop
|
||||
|
||||
@@ -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] <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)
|
||||
|
||||
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"] = "<i>[html_encode(uppertext(source))]<i>"
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <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, \
|
||||
"continue" = /n_Keyword/nS_Keyword/kwContinue, \
|
||||
"return" = /n_Keyword/nS_Keyword/kwReturn, "def" = /n_Keyword/nS_Keyword/kwDef)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user