WIP documentation of TeaScript. Feel free to add any information necessary below.
- 1 Data Types and Variables
- 2 Expressions
- 3 Control Flow
- 4 Loops
- 5 Script
- 6 Oddities and Quirks
Data Types and Variables
Teascript only offers two data types. These are known as doubles and strings.
Doubles are represented as numbers. This includes whole and decimal numbers. (IEEE 64-bit 8-bytes,-1.79769313486232×10308 to -4.94065645841247×10-324 for negative values,4.94065645841247×10-324 to 1.79769313486232×10308 for positive values) variables.
Double variables can be accessed with the following methods:
'Local val(myVar) or v(myVar) 'Global gval(myVar) or gv(myVar) 'Local Concatenation in TXTCreate and Messages &val(myVar) 'Global Concatenation in TXTCreate and Messages &gval(myVar)
Strings are represented as text. You can create a string by surrounding text with quotation marks. "Example"
'Local str(myVar) 'Global gstr(myVar) 'Local Concatenation in TXTCreate and Messages $val(myVar) 'Global Concatenation in TXTCreate and Messages $gvl(myVar)
TeaScript.vbs also lists SMBX Events, Layers, and Scripts as pseudo data types. This data cannot be stored in a variable. This data is used by typing the name of the object without quotation marks in appropriate functions.
Variables can be manipulated in the following ways.
(All variables must be created using the variable interface through View > Variables or Ctrl+i.)
- Local variables are created in the level editor mode and only exist in the level it was created. Local variables reset every time the level start.
- Global variables are created in the world editor mode and exist throughout the entire episode. Global variables are saved even after level-death/exit or when you quit the episode.
'To set and get the value of a variable '(myVar1 and myVar2 are local variables) v(myVar1) = 1 v(myVar2) = v(myVar1) + 1 v(myVar1) = 5 'myVar1 is 5 and myVar2 is 2 str(myVar1) = "Hello" str(myVar1) = str(myVar1)&", how are you?" 'myVar1 is "Hello, how are you?" 'It is to be noted that when you create a local or global variable, as double and a string variable are created simultaneously. 'myVar1 and myVar2 were created as local in the variable interface and the variable us usable as a string and double simultaneously.
Variable Naming Standard
- Names are not case sensitive.
- Names must not contain spaces.
- Names must be made using a combination of using letters and numbers.
- Names must start with a letter.
12 + 3 + 5 'returns 19
12 - 3 - 5 'returns 4
12*2*5 'returns 120
'Note that division by 0 will crash SMBX 12/2/5 'returns 1.2
|\||Division with no remainder|
'Note that division by 0 will crash SMBX 12\2\5 'returns 1
'Note that 0^0 will return 1 12^2 'returns 144
'Note that mudulating by 0 will crash SMBX 12 mod 5 'returns 2
"ABC"&";"&"123" 'returns "ABC;123"
12*(2 + 5) 'returns 84
These are the mathematical functions provided.
Parameters with #param mean that the parameter is a double.
Parameters with "param" mean that the parameter is a string.
|Name and Parameters||Return Type||Description and Example|
|abs(#num)||Double||Returns the absolute value of a number
abs(-3) 'returns 3
|exp(#num)||Double||Returns the number to the power of the e constant
exp(5) 'returns e^5
|log(#num)||Double||Returns the log of the number with a base of e
log(e) 'returns 1
|sgn(#num)||Double||Returns the sign of the number (1, -1, or 0)
sgn(10) 'returns 1 sgn(0) 'returns 0
|int(#num)||Double||Returns the number rounded up. Similar to the common ceiling function
int(2.1) 'returns 3
|fix(#num)||Double||Returns the number rounded down. Similar to the common floor function
fix(2.9) 'returns 2
|sqr(#num)||Double||Returns the square root of a number
sqr(9) 'returns 3
|sin(#num)||Double||Returns the sine of the number. Uses radians
sin(pi) 'returns 0
|cos(#num)||Double||Returns the cosine of the number. Uses radians
cos(pi) 'returns 1
|tan(#num)||Double||Returns the tangent of the number Uses radians
tan(pi/4) 'returns 1
|atn(#num)||Double||Returns the inverse tangent of the number. Uses radians
atn(1) 'returns pi/4
|getangle(#x, #y)||Double||Returns the angle (from 0 to 1) formed between the triangle. Similar to the common atan2 function.
getangle(1, 0) 'returns 0 getangle(1, 1) 'returns .125 getangle(0, 1) 'returns .25 getangle(-1, 0) 'returns 0.5 getangle(0, -1) 'returns 0.75
|rgba(#red, #green, #blue, #alpha)||Double||Returns an SMBX color value. Parameters must be between 0 and 255
rgba(255, 255, 255, 255) 'returns -1
|round(#num, #decimal_place)||Double||Returns the number rounded
round(1.3456, 2) 'returns 1.35
|len("txt")||Double||Returns the length of the text
len("ABC") 'returns 3
|left("txt", #len)||String||Returns the text cropped starting with the length provided. The crop begins from the start|
|right("txt", #len)||String||Returns the text cropped starting with the length provided. The crop finished with the end|
|mid("txt", #len)||String||Returns the text cropped starting with the length provided. The crop begins with the number provided.|
|replace("txt", "search", "replacement", #start, #count, #case_insensitive)||String||Replaces a part of the text with a new one.
|asc("character")||Double||Returns the ANSI code. It will use the first character if more than one is passed|
|chr(#code)||String||Returns a string using the ANSI code. Accepts 0-255|
|ascw("character")||Double||Returns the unicode code. It will use the first character if more than one is passed|
|chrw(#code)||String||Returns a string using the unicode code. Accepts 0-65535|
|cstr(#num)||String||Converts the number to a string|
|cdbl("txt")||Double||Converts the string into a number|
|instr(#start, "string1", "string2")||Double||To return the point of the first appearance of a given string in another string.
These special values behave like numbers.
|rnd||A random number between 0 and 1|
Note that all comparative operators require both sides use the same data type. (You can compare doubles with other doubles and strings with other strings, but you cannot compare doubles with strings)
|=||Equal||Doubles Returns -1 if both sides are equal, otherwise 0|
|Strings Returns -1 if both sides are equal, otherwise 0|
|<>||Not equal||Doubles Returns -1 if both sides are not equal, otherwise 0|
|Strings Returns -1 if both sides are not equal, otherwise 0|
|>||Grater than||Doubles Returns -1 if the value on the left is larger, otherwise 0|
|Strings Unknown pattern|
|<||Less than||Doubles Returns -1 if the value on the left is smaller, otherwise 0|
|Strings Unknown pattern|
|>=||Greater than or equal||Doubles Returns -1 if the value on the left is larger or equal, otherwise 0|
|Strings Unknown pattern|
|<=||Less than or equal||Doubles Returns -1 if the value on the left is smaller or equal, otherwise 0|
|Strings Unknown pattern|
|like||Like||Doubles Not compatible|
Logical operators only work on doubles. They are commonly used with 0 and -1. Other numbers can be used but it may yield different patterns.
|P||Q||not P||P and Q||P or Q||P xor Q||P eqv Q||P imp Q|
When a script is run in TeaScript it will start reading the script from top to bottom, left to right. It will read and execute the code in that order. the following is a list of ways to customize and manipulate what code gets executed.
The "if statement" is a basic but useful statement. It has one parameter being "condition".
'Basic if statement if conditon then 'code that should run if the condition is "true" end if 'If statement using one elseif and an else statements if conditon then 'code that should run if the condition is "true" elseif condition then 'code that should run if the second condition is "true" else 'code that should run if all the other conditions are "false" end if
When TeaScript reads an if statements it will check each condition from top to bottom until it reaches a condition that is true. When it reaches a condition that is true, it will execute the code that is inside that statement and continue the code after the entire "if statement". This means that conditions written on the top will have priority over those in the bottom.
The "else" is special since it does not require any conditions. An else must be written in the bottom after all other "elseif"s statements (if there are any). The code inside the "else" will only run if every other "if" and "elseif" had "false" in their conditions.
It is important to note that TeaScript does not have booleans (true and false values). Instead, 0 is considered to be false and any other number is considered to be true. Strings are not accepted as conditions, only doubles are accepted.
Select Case lets you easily organize the control flow based on a value. It has one parameter being "value".
select case value case -1 'Code that should pass if the value is exactly -1 case 0 to 1 'Code that should pass if the value is between (inclusive) 0 and 1 case is < -1 'Code that should pass if the value is less than negative one case 2, 3, 4 'Code that should pass if the value is exactly 2, 3 or 4 case "example" 'Script that should pass if the value is exactly "example". case else 'Code that should pass if the value does not match any of the other conditions end select
"Select case" at its core is similar to various "if statement"s and behaves similarly to the common "switch" statement in other languages. It will read the value that is passed and only executes the code in which the value matches. It will read the cases from top to bottom giving priority to cases at the top.
The "to" keyword can be used when checking for a case.
- Doubles Will be true if the value is between (inclusive) the two numbers provided.
- Strings Unknown pattern
The "is" keyword can be used to make comparisons to the value. It can be used with "<", ">", "<=", or ">=" symbols.
You can use commas to check for multiple cases at once. The commas behave similarly to an "or" operator. The case will go through if it matches with any of the cases.
With statements are useful to set multiple statements to a given object.
with object [statement] end with
Object means an object of the game. Here's an example:
with npc(1) .x = 12345 .y = 54321 end with
Using goto will force the script to jump to a specific line using a label.
Example: [statements] goto Example
When the script reached "goto Example" it will jump to "Example" and execute the script below it. The labels used with goto statements must: have names that do not contain characters that do not follow variable name rules, there must not be two labels with the same name and there should not be goto statements inside "with" statements either (meaning you can't use them when scripting an npc).
Gosub statements are very similar to goto ones, but there is a noticeable difference.
mysub1: [statement 1] gosub mysub1 return mysub2: [statement 2] gosub mysub2 return
While goto statements will simply jump into a given line, gosub statement can keep track of where it came from. This means the program won't search through the whole stack to find a given label, instead it will do from the last "return" found. Gosub statements must follow the same rules as goto statements.
It is important to note that you should avoid an infinite loop. Make sure to either have a "sleep" function (if the script was called by an event) or an "exit" if you set up a for loop to go indefinitely.
A "pure loop" is a very simple and basic form of a loop.
'Pure loop: do 'Code that will be executed multiple times loop
The loop will run indefinitely.
The game will repeat executing statements inside do statement until condition returns true. The condition be checked at the beginning or either at the end of the loop.
In this example the game checks the condition at the beginning, meaning if condition is false the game won't execute statements inside "do".
do while condition [statement] loop
In this example the condition is checked at the end of the loop. This means that is condition is false the game will execute anyway statements inside "do" until it reaches "while" and verify the condition.
do [statement] loop while condition
The game will repeat executing statements inside do statement until condition returns false. You can also make the game check the condition at the beginning or at the end of the loop like with "while" statements.
do until condition 'Code that will be executed multiple times loop do 'Code that will be executed multiple times loop until condition
A "for" loop is a loop that will run a certain amount of times. It has three parameters: "initial_value", "ending_value", and "setp_value".
for v(myCounter) = initial_value to ending_value step step_value 'code that will be executed multiple times next 'step_value is optional and if omitted the loop will behave with a step of 1 for v(myCounter) = initial_value to ending_value 'code that will be executed multiple times next
An already existing variable must be set to "initial_value". The variable will start the loop with this and increment by the value set in "step_value". You can still manipulate the variable while inside the "for loop".
The loop will continue going until the variable is larger or equal to "ending_value" when the script reaches "next". The loop will also stop if the variable is less than the "initial value" when it reaches next. Once the loop stops it will continue reading the script.
When TeaScript reads an "exit for" while inside a "for loop" it will immediately skip to the next keyword and resume the script.
An exit will terminate a loop and skip the code after it until it reaches the "loop" or "next" keyword (Depending on what loop it was used on).
'This will work while inside a pure, while, or until loop exit do 'This will work while inside a for loop exit for 'This will force the game to stop immediately executing the script exit script
Using the script keyword, it allows you to make useful custom functions and procedures in Teascript.
v(myvar) = exampleWithReturn(5, "test") call exampleWithNoReturn() 'A script set up as a function (has a return) script exampleWithReturn(myDoubleParam as double, myStringParam as string, return double) return param(myDoubleParam) + len(strparam(myStringParam)) end script 'A script set up as a procedure (has no return) script exampleWithNoReturn() v(myVar) = v(myVar)*2 end script
When setting up a script, all parameters must be defined by name and type as shown below. You may have as many parameters as needed. Note that return is optional. All script and parameter naming standards are similar to variable naming standards with one exception. Script names must not contain numbers.
script example(name as type, name as type, ..., return type) param(name) 'Use param when reading the value of a double strparam(name) 'Use strparam when reading the value of a string end script
Unlike common functions in other languages, TeaScript cannot do the following:
- Set the value of passed down parameters. All parameters passed down are read-only.
- Create recursive scripts. You cannot call a script within itself.
The "return" keyword will only in functions. If a function has no return, then it will return 0 or "" (based on the return type that was specified. SMBX will error if you include a return in a procedure.
It is important to note that when called, procedures must have the "call" keyword. This also applies to a function if you do not read the returned value.
Oddities and Quirks
The following is a list of oddities that you may experience when using TeaScript
Writing Double Quotation Marks
Since double quotation marks are reserved for defining string, you must use chr or chrW to write a double quotation mark inside a string.
str(myVar1) = chrW(34) '34 is the ID of the double quotation marks. (ID 34 works too in chr() too) 'You can define a variable as a quotation mark or call the quotation mark directly, both work (the first one is recommended if used a lot) str(myVar2) = "These are some "&str(myVar1)&"special"&chrW(34)&" marks" 'str(myVar2) is "These are some "special" marks"
> THESE PROBLEMS ARE FIXED in 1.4.5 <
Writing Decimal Numbers
When writing decimal number, you must include a number before the decimal point.
'Wrong v(myVar) = .1 'Correct v(myVar) = 0.1
Writing negative numbers
When writing a negative number, make sure there are no other symbols beforehand (except parenthesis).
'Wrong (Teascript errors due to seeing * and - next to each other) v(myVar) = 5*-4 'Correct v(myVar) = 5*(-4) v(myVar) = -4*5