Cubescript
Cubescript is the scripting language utilised within the sauerbraten/cube2 engine. it is used to set aliases, variables, create binds and generate the menu.
List of commands
These are just a list of commands, what they actually do will be covered a bit later in this topic.
General
The following commands are quite often used in a lot of scripts.
- alias
- at
- do
- getalias
- getname
- getteam
- if
- listlen
- loop
- result
- rnd
- sleep
- while
Map Configuration
The following commands are useful in level only aliases
- triggerstate
- level_trigger
- level trigger is invoked as level_trigger_1 = [] as an example, the end number is the 4th number in the mapmodel's strings
- level_base
- Used to give bases names in capture mode. This is unfortunately unused in PAS
Binds
The following commands are useful in binds.
- onrelease
Gui Creation
These commands are used to create various menus.
- cleargui
- guibar
- guibutton
- guicheckbox
- guifield
- guikeyfield
- guiimage
- guilist
- guirolloveraction
- guirollovername
- guislider
- guilistslider
- guinameslider
- guistayopen
- guitab
- guitext
- guititle
- guistrut
- newgui
Comparisons
The functions here can change the values, or return a logical comparison for all intents and purposes, the C version of booleans apply here; values not equal to 0 are true - and functions that return true return 1
Integer Arithmetic
- + A B
- returns the value of the numbers added together
- * A B
- returns the result of multiplying A and B
- - A B
- returns the value of A - B
- = A B
- returns true of the two are equal
- != A B
- returns true if the two aren't equal
- < A B
- returns true if A is less-than B
- > A B
- returns true if A is greater-than B
- <= A B
- returns true if A is less-than-or-equal-to B
- >= A B
- returns true if A is greater-than-or-equal-to B
- ! A
- if the argument is false, it returns true
- &&
- returns true if all arguments are true
- ||
- returns true it at least one argument is true
- div A B
- returns the value of A divided by B
- mod A B
- returns the modulus of the two arguments
- min
- returns the lowest valued argument of all provided arguments
- max
- returns the highest valued argument of all provided arguments
Bitwise Integer Operations
- ^ A B
- returns the value of A xor B ie (^ 8 4) is 12 - (^ 12 4) is 8
- & A B
- returns the value of the bits both A and B have
- | A B
- returns the value of the bits either A or B have
- ~ A
- returns the inverted bitwise version of A ie (& (~ 128) 255) is 127
- ^~ A B
- xor;s the arguments after applying an inversion on B
- &~ A B
- and's the arguments after applying an inversion on B
- |~ A B
- or's the arguments after applying an inversion on B
- << A N
- shifts A N bits
- >> A N
- shifts A -N bits
Floating Point Arithmetic
Generally these just have an -f suffix
- +f A B
- returns the value of the numbers added together
- *f A B
- returns the result of multiplying A and B
- -f A B
- returns the value of A - B
- =f A B
- returns true of the two are equal
- !=f A B
- returns true if the two aren't equal
- <f A B
- returns true if A is less-than B
- >f A B
- returns true if A is greater-than B
- <=f A B
- returns true if A is less-than-or-equal-to B
- >=f A B
- returns true if A is greater-than-or-equal-to B
- divf A B
- returns the value of A divided by B
- modf A B
- returns the modulus of the two arguments
- minf
- returns the lowest valued argument of all provided arguments
- maxf
- returns the highest valued argument of all provided arguments
Strings
- =s A B
- returns 1 if the string matches, 0 otherwise
- !=s A B
- returns 0 if the string matches, 1 otherwise
- <s A B
- returns true if the C strcmp returns less-than 0
- >s A B
- returns true if the C strcmp returns greater-than 0
- <=s A B
- returns true if the C strcmp returns less-than-or-equal-to 0
- >=s A B
- returns true if the C strcmp returns greater-than-or-equal-to 0
- strcmp A B
- returns 1 if the string matches, 0 otherwise (unlike the C version with returns the disparity)
- strstr H N
- returns the position of N in H - otherwise -1 is returned
- strlen S
- returns the length of the string
- strreplace S O N
- replaces all instances of O inside string S with N
String/text formatting
These commands are used to format aliases which are normally huge bits of text
- concat
- concatword
- format
Shaders
All of the nice graphical effects were programmed in ASL (assembly shading language), and formatted in cubescript themselves.
- altshader
- fastshader
- macro
- setpixelparam
- setuniformparam
- setvertexparam
- shader
Writing in Cubescript
Syntax
Cubescript has many similarities with C, mostly in the way the script is formatted. But there are some HUGE differences. Newlines for one mean it's both the end of a function and the end of a string (should you have forgotten to close one off). The scripts below do the exact same thing.
one liner example
alias hi [say "hi"; sleep 5000 [say "Hi again"]]
multi liner example
alias hi [ say "hi" sleep 5000 [ say "Hi again" ] ]
it's obvious what the above code does, it'll make your character say hi, and wait 5 seconds before saying hi again.
indenting is done in levels, the Tabulator (TAB) key is usually used to indent the text. while not necessary, it tends to make it bigger, and more legible as seen in the above example (when you get to big stuff, you'll thank yourself for indenting it.
As a rule of thumb, pretty much only [ increases the indentation level. Also note, ", ] and ) can close each other, so make sure you close them off properly
containers
Containers in cubescript are of 3 specific types, "", () and [] - both of these have huge differences in operation and use
"" container
"" containers are used to store things EXACTLY as they are written, with a few small exceptions - in-text commands which are denoted by a preceding ^. They are as follows
- ^f#
- ^f# is used to colour text. # must be replaced by either a number or a capital letter (A-Z). r and s are special control characters which will restore and save the text's current colour respectively.
- ^n
- insert a '\n' character (newline/linefeed)
- ^t
- inserts a '\t' character (tabulator)
- ^"
- inserts a quote (")
() container
() containers are used mainly for logic/arithmetic operations. They are usually nested inside [] blocks, and unless they are nested inside []'s they're permanently substituted with their results.
For example - the following will turn into an infinite loop. The condition is initially evaluated and substituted with one and since 1 can never = 0, it's true forever more
i = 0 while (= $i 0) [i = $i + 1]
the following code on the otherhand is devoid of such issues. Being nested inside the [] means it's not substituted and evaluated each cycle
i = 0 while [(= $i 0)] [i = $i + 1]
[] container
This container is used for nesting, deferring execution of it's contents, deferring calculations and substitutions of () containers, and substitutions of aliases/variables written with a @ prefix (note several levels are needed to achieve this). [] containers are also the ONLY container capable of spanning multiple lines.
This is the most used container and due to it's properties, is ideal for creating aliases.
generally statements in cubescript can't span multiple lines. If you should use this container and occupy several, the execution of the prior command continues exactly where this container finished off. This can be demonstrated with an if statement.
if 1 [ do stuff ] [ do other stuff ]
substitution
there are two principle ways of substituting values in cubescript, the first is through the use of $ tokens, the second is through the use of @ tokens.
a very simple example:
myalias = 5 echo $myalias
myalias is substituted into the echo statement, so you should see 5 printed to the top-left of the screen
using the @ token would have also resulted in the same behaviour
myalias = 5 echo @myalias
There's a big difference between the two, the @ token can be used to concatenate stuff together, $ can't. @ is also substituted immediately up to the first level of nesting. (this can be incremented by using additional @ tokens, ie @@ for 2 levels of nesting)
An example of use in a level 1 nest
myalias = "I am awesome" mymenu = [guitext @myalias]
if you were to type /echo $mymenu, it should read: guitext "I am awesome"; using the $ token on the other hand
myalias = "I am awesome" mymenu = [guitext $myalias]
typing /echo $mymenu should produce: guitext $mymenu
An example of concatenation
as i mentioned, @ also allows you to concatenate stuff together, which could result in shorter and simpler scripts. It should be noted that this can also result in extreme obfuscation
myalias1 = 5 myalias2 = 3.1415 myalias3 = 2.481 loop i 3 [ echo $myalias@i ]
this should print 5, 3.1415 and 2.481 respectively
the purely $ token equivalent
myalias1 = 5 myalias2 = 3.1415 myalias3 = 2.481 loop i 3 [ echo (getalias (concatword myalias $i)) ]
Examples
For the sake of being lazy, I may not bother to format them correctly. also I'll be type blah = blahblah instead of alias blah blahblah, it's still the same as aliases can be created both ways.
Loops
loops are used to quickly execute code, and are usually invoked with /loop. the loop is invoked as such /loop alias value-to-stop-at [commands to execute] eg /loop i 10 will loop it 10 times, each time it'll increase i by one. The example will also demonstrate a use of format. which can take up to 10 arguments. the first is the string of text, and the subsequent stuff are what'll replace %1 %2 %3 %4 %5 %6 %7 %8 and %9 respectively. You would've also noticed that the executed function like - + div etc is at the beginning of the (). and not inbetween the two values like we're normally used to. if you want to see the original when there's 100 bottles, use /conskip 99 to go to the top of the history. you can also increase the size of the text displayed with /consize.
loop i 100 [say (format "%1 bottles of juice on the wall, %1 bottles of juice" (- 100 $i))]
you should see similar at the top of your screen by executing that
Sandboxer: 5 bottles of juice on the wall, 5 bottles of juice
Sandboxer: 4 bottles of juice on the wall, 4 bottles of juice
Sandboxer: 3 bottles of juice on the wall, 3 bottles of juice
Sandboxer: 2 bottles of juice on the wall, 2 bottles of juice
Sandboxer: 1 bottles of juice on the wall, 1 bottles of juice
Unfortunately with the above, this'll be executed as fast as possible, so we can revamp the script a bit to this
juicecount = 0
juicecounter = "juicecount = (+ $juicecount 1)"
juice = [
if (= $juicecount 10) [
juicecount = 0
] [
say
(format "%1 bottles of juice on the wall, %1 bottles of juice. You take
one down, pass it around, %2 bottles of juice on the wall" (-
10 $juicecount) (- 9 $juicecount))
juicecounter
sleep
1000 [
juice
]
]
]
very simple it is. this script will wait a few seconds before execution of each loop. a loop limit is imposed as well, so it'll only go to 10. This is alsop without using the /loop command, so there's more than one way to do things
Getting Input
cubescript is limited to an array of 25 arguments most per alias. To actually do anything with the input, you need to use $ and @, usually appended with an arg to say which of the arguments it accepts
text = [say "$arg1 $arg3"]
then typing /text 1 2 3 in the game should return 1 3
lets try a slightly more complex example
mod10 = [say (mod $arg1 10)]
mod stands for modulus, This'll work an any number, as cubescript it limited to integers (no decimal accuracy). 99 mod 10 is 9, and 90 mod 10 is 0. As you probably just realised, it finds the remainder of a division sum.
so typing /mod10 100 should make you say 0
you also have +, -, *, /, !, =, > and < available to use, so go nuts