Squirrel: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(Added/extended examples and tried to make them more understandable by adding more comments. Added section about Generators.)
Line 2: Line 2:
{{sq}} [http://squirrel-lang.org/ Squirrel] is a programming language similar to [http://www.lua.org/ Lua], but uses a C like syntax. In Source Squirrel is used as one of the scripting languages in the [[VScript]] scripting system. The official Squirrel documentation can be found [http://squirrel-lang.org/doc/squirrel3.html here]
{{sq}} [http://squirrel-lang.org/ Squirrel] is a programming language similar to [http://www.lua.org/ Lua], but uses a C like syntax. In Source Squirrel is used as one of the scripting languages in the [[VScript]] scripting system. The official Squirrel documentation can be found [http://squirrel-lang.org/doc/squirrel3.html here]


Squirrel heavily uses an [https://en.wikipedia.org/wiki/Associative_array associative array] data structure called a ''table''. Both the keys and values of a table can contain almost any kind of variable. The scripting environment consists of nested tables, and when a script is executed its variables and functions are added as table slots.
Squirrel heavily uses an [[w:associative array|associative array]] data structure called a ''table''. Both the keys and values of a table can contain almost any kind of variable. The scripting environment consists of nested tables, and when a script is executed its variables and functions are added as table slots.
 
<source lang=cpp style="float:right; background-color:transparent">
printl("Hello World"); // statements can end with both a semicolon...
printl("Hello World")  // ...or a newline character
</source>
Squirrel's syntax is similar to C/C++/Java etc... but the language has a very dynamic nature like Python/Lua etc.
Statements can be separated with both a new line or <code>;</code> (or with the keywords <code>case</code> or <code>default</code> if inside a switch/case statement), both symbols are not required if the statement is followed by <code>}</code>.


==Variables==
==Variables==
Squirrel has two kinds of variables: '''table slots''' and '''<code>local</code>''' variables.
Squirrel has two kinds of variables: '''table slots''' and '''<code>local</code>''' variables.
Since the execution scope is always a table, any variables declared outside functions will always be table slots.
Since the execution scope is always a table, any variables declared outside functions will always be table slots.
* Table slots have to be declared using the <code><-</code> operator.  
* Table slots have to be declared using the <code><-</code> operator. These are to be used for values that should remain when a function ends. Once a slot exists, it can be reassigned with both the <code>{{=}}</code> or the <code><-</code> operator.
* Variables local to functions can be declared using the <code>local</code> keyword. These should be used for temporary values or as helpers.
* Global variables are slots in the root table (<code>getroottable()</code>). They can be declared using the <code>::</code> scoping operator and accessed without it.
* Global variables are slots in the root table, and can be declared using the <code>::</code> scoping operator.
* Variables local to functions can be declared using the <code>local</code> keyword. These are to be used for temporary values or helpers that can be discarded after a function call.
 
* Constants are declared with the <code>const</code> keyword and computed compile-time. Their value can only be an integer, float or string. During runtime, <code>getconsttable()</code> returns a table with all constants.
Here are examples illustrating the declaration and use of variables.
{{note|<code>local</code> and <code>const</code> variables are declared with the <code>{{=}}</code> operator. Using <code><-</code> for those yields a compile time error.}}
{|
<!--Here are examples illustrating the declaration and use of variables.
-->{|
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| <source lang=cpp>
| <source lang=cpp>
// Variable declaration.
a <- 5               // creates a table slot in this table
a <- 5
b <- "A text string" // creates a table slot in this table
b <- "A text string"
::x <- 10            // creates a table slot in the root table
local i = 0          // initializes a temporary variable
const PI = 3.14159  // creates a new constant


// Modifying the variable.
b = "New string"     // modifies the existing table slot
b = "New string"
x = 11              // modifies the existing table slot
</source>
</source>
|}
The <code>in</code> operator can be used to test whether a table slot exists. One could also use <code>try {a} catch (e) { /*...*/ }</code>. The following code is assumed to be executed after the above, i.e. in the same environment.
{|
| <source lang=cpp>
| <source lang=cpp>
function MultiplyWithTwo(inValue)
"a" in this  // true
{
"x" in this  // false, unless we're in the root table
// Local variable declaration.
"i" in this  // false, local variables aren't table slots
local factor = 2
"PI" in this // true
delete a    // deletes a table slot
return inValue * factor
"a" in this  // false, no longer exists
}
</source>
| <source lang=cpp>
// Global variable declaration. Sets x to 10.
::x <- MultiplyWithTwo(a)
</source>
</source>
|}
|}
Line 48: Line 56:
|-
|-
|<code>Integer</code>
|<code>Integer</code>
| The integers <code>-2147483648</code> to <code>2147483647</code>.
| The integers <code>-2,147,483,648</code> to <code>2,147,483,647</code>, namely -2<sup>31</sup> to 2<sup>31</sup>-1.
|-
|-
|<code>Float</code>
|<code>Float</code>
| <code>-3.4028235e38</code> to <code>3.4028235e38</code>, which equal -3.4028235 × 10<sup>38</sup> to 3.4028235 × 10<sup>38</sup>.
| <code>-3.4028235e38</code> to <code>3.4028235e38</code>, namely -3.4028235 × 10<sup>38</sup> to 3.4028235 × 10<sup>38</sup>.
|-
|-
|<code>String</code>
|<code>String</code>
Line 62: Line 70:
| Boolean data type that can be <code>true</code> or <code>false</code>.
| Boolean data type that can be <code>true</code> or <code>false</code>.
|-
|-
|<code>[[Squirrel#Tables|Table]]</code>
|<code>[[#Tables|Table]]</code>
|Associative array.
|Associative array.
|-
|-
|<code>[[Squirrel#Arrays|Array]]</code>
|<code>[[#Arrays|Array]]</code>
|Mutable C style array.
|Mutable C style array.
|-
|-
|<code>[[Squirrel#Functions|Function]]</code>
|<code>[[#Functions|Function]]</code>
|Second order functions are supported, so functions can assigned as values to variables.
|Second order functions are supported, so functions can assigned as values to variables.
|-
|-
|<code>Class</code>
|<code>[[#Classes|Class]]</code>
|Object oriented class. Implementation similar to tables.
|Object oriented class. Implementation similar to tables.
|-
|-
Line 77: Line 85:
|Object instances of classes. [[Vscript_Fundamentals#Script_Handles|Script handles]] generated by the game also identify as instances.
|Object instances of classes. [[Vscript_Fundamentals#Script_Handles|Script handles]] generated by the game also identify as instances.
|-
|-
|<code>Generator</code>
|<code>[[#Generators|Generator]]</code>
|{{todo|Possibly unavailable in VScript}}
|{{todo|Possibly unavailable in VScript}}
|-
|-
Line 90: Line 98:
|}
|}


 
===Bool===
==Data Structures==
Squirrel considers <code>null</code>, <code>0</code> (type Integer) and <code>0.0</code> (type Float) as <code>false</code>, any other value is considered <code>true</code>. This allows you for example to null-check variables using <code>if (var)</code>.
Squirrel has built-in support for two different data structures: arrays and tables.
{{warning|Don't null-check Integers or Floats like this if they may be 0 or 0.0, obviously. This concerns the built-in string function <code>find(<substring>)</code> which returns either the index where it found the given substring or null. Do <code>if (var {{=}}{{=}} null)</code> instead.}}
 
===Arrays===
 
Arrays are sequences of objects that are numerically indexed starting from 0. Syntactically they function similarly to C arrays, but unlike C arrays, they are mutable and values can be inserted and removed using a set of [http://squirrel-lang.org/doc/squirrel3.html#d0e3058 built in functions].
 
Arrays are defined using square brackets.
 
{|
{|
|- style="vertical-align:top;"
| <source lang=cpp>
| <source lang=cpp>
// Array definition.
if (false) { /* ... */ } // not executed
myArray <-
if (null)  { /* ... */ } // not executed
[
if (0)     { /* ... */ } // not executed
7,
if (0.0)   { /* ... */ } // not executed
"more text",
null,
1
]
</source>
| <source lang=cpp>
// Prints "7"
printl(myArray[0])
 
myArray.remove(0)
 
// Prints "more text"
printl(myArray[0])
</source>
</source>
|}
|}
Line 127: Line 114:
Tables are associative arrays, meaning that they contain a collection of key-value pairs, called slots. A table can be indexed into using the key, returning the associated value. The keys and values can be of any data type (except <code>null</code> for the key), including other tables, allowing the creation of more complex data structures.
Tables are associative arrays, meaning that they contain a collection of key-value pairs, called slots. A table can be indexed into using the key, returning the associated value. The keys and values can be of any data type (except <code>null</code> for the key), including other tables, allowing the creation of more complex data structures.


Tables are defined using curly brackets. Inside a table definition slots can be defined using the <code>key = value</code> pattern. Outside of the definition, new slots can be added to existing tables using the <code>table.key <- value</code> pattern.
Tables are defined using curly brackets. Inside a table definition slots can be defined using the <code>key1 = value1, key2 = value2, ...</code> pattern. Outside of the definition, new slots can be added to existing tables using the <code>table.key <- value</code> pattern.


Using the <code>.</code> operator to index a key only works when the key is a string or numerical literal. Array style indexing <code>table[keyVariable]</code> can be used to index any kind of key.
Using the <code>.</code> operator to index a key only works when the key is a string or numerical literal. Array style indexing <code>table[keyVariable]</code> can be used to index any kind of key.
{{tip|Some of the built-in functions for tables are <code>len(), clear(), keys(), values()</code>.}}


{|
{|
Line 137: Line 126:
myTable <-
myTable <-
{
{
a = 3,
a = 3,             // key: "a", value: 3
b = 7,
b = 7,             // key: "b", value: 7
x = "example text",
x = "example text", // key: "x", value: "example text"
[5] = "five"        // key:  5 , value: "five"
nestedTable =
nestedTable =
Line 146: Line 136:
}
}
}
}
// alternatively:
myTable <- {}
myTable["a"] <- 3 // string keys can be indexed...
myTable.b    <- 7 // ...in two ways
myTable.x    <- "example text"
myTable[5]  <- "five" // numbers must be indexed like this
myTable.nestedTable <- { z = "another string" }
</source>
| <source lang=cpp>
foreach (key, value in myTable)
{
printl(key + ": " + value)
}
// Prints (order might vary!):
// a: 3
// x: example text
// b: 4
// 5: five
// nestedTable: (table : 0x000000000069D130)
printl("a" in myTable) // prints "true"
printl( 3  in myTable) // prints "false"
</source>
</source>
| <source lang=cpp>
| <source lang=cpp>
// Adding non-string keys
// Adding non-string keys
a <- "0"
a <- "0"
myTable[a] <- 11
myTable[a] <- 11     // key: "0", value: 11
myTable[["u", "v", "w"]] <- null


// Prints "3"
printl(myTable.a)    // prints "3"
printl(myTable.a)
printl(myTable[a])   // prints "11"
printl(myTable["0"]) // prints "11"
printl(myTable[0])  // exception, key 0 doesn't exist


// Prints "11"
printl(myTable.nestedTable.z) // prints "another string"
printl(myTable[a])
</source>
</source>
|}
===Arrays===
Arrays are sequences of objects that are numerically indexed starting from 0. Syntactically they function similarly to C arrays, but unlike C arrays, they are mutable and values can be inserted and removed using a set of [http://squirrel-lang.org/doc/squirrel3.html#d0e3058 built in functions].
Arrays are defined using square brackets.
{{warning|You can't use the <code>in</code> operator to test whether some value is in the array because for Squirrel, arrays are tables where the keys are the indices. The <code>in</code> operator would look through the indices that the array has and not its values.}}
{{tip|Some of the built-in functions for arrays are <code>len(), clear(), append(<value>), insert(<index>, <value>), remove(<index>), find(<value>)</code>.}}
{|
|- style="vertical-align:top;"
| <source lang=cpp>
| <source lang=cpp>
// Prints all the key-value pairs in the table.
// Array definition.
foreach(key, value in myTable)
myArray <-
[
7,          // key: 0, value: 7
"more text", // key: 1, value: "more text"
null        // key: 2, value: null
]
 
// alternatively:
myArray <- []
myArray.append(7)
myArray.append("more text")
myArray.append(null)
 
// alternatively:
myArray <- array(3)
myArray[0] = 7
myArray[1] = "more text"
myArray[2] = null
</source>
| <source lang=cpp>
foreach (index, value in myArray)
{
{
printl(key + ": " + value)
printl(index + ": " + value)
}
}
// Prints:
// 0: 7
// 1: more text
// 2: null


// Prints the value of the key in the nested table.
printl(    2      in myArray) // prints "true"
printl(myTable.nestedTable.z)
printl("more text" in myArray) // prints "false"
</source>
| <source lang=cpp>
printl(myArray[0]) // prints "7"
 
myArray.remove(0)
 
printl(myArray[0]) // prints "more text"
</source>
</source>
|
|}
|}


==Functions==
===Functions===
Functions in Squirrel work similarly to their C counterparts. Second order functions are supported, so functions can be directly manipulated like other values, including it being possible to store them in variables and table slots. Default parameter values and variable numbers of parameters are also supported.
Functions in Squirrel work similarly to their C counterparts. Second order functions are supported, so functions can be directly manipulated like other values, including it being possible to store them in variables and table slots. Default parameter values and variable numbers of parameters are also supported.


For more details, see the [http://www.squirrel-lang.org/squirreldoc/reference/language/functions.html Squirrel API about functions].
For more details, see the [http://www.squirrel-lang.org/squirreldoc/reference/language/functions.html Squirrel API about functions].
===Declaration and Definition===


It is common practice to begin with a capital letter when naming functions.
It is common practice to begin with a capital letter when naming functions.
Line 187: Line 240:
function Greet()
function Greet()
{
{
  printl("Hello!")
printl("Hello!")
}
}


Line 196: Line 249:
Greet <- function()
Greet <- function()
{
{
  printl("Hello!")
printl("Hello!")
}
}


Line 205: Line 258:
Greet = function()
Greet = function()
{
{
  printl("Hello!")
printl("Hello!")
}
}


Line 211: Line 264:
</source>
</source>
|}
|}
===Parameters===


When a function is called, it can be made so that it can or must receive input values that determine the function's side effects and/or its return value.
When a function is called, it can be made so that it can or must receive input values that determine the function's side effects and/or its return value.
Line 226: Line 277:
function Greet(name)
function Greet(name)
{
{
  printl("Hello, " + name + "!")
printl("Hello, " + name + "!")
}
}


Line 236: Line 287:
function Greet(name="Gordon")
function Greet(name="Gordon")
{
{
  printl("Hello, " + name + "!")
printl("Hello, " + name + "!")
}
}


Line 244: Line 295:
|}
|}


===Return Value===
A function is ended with the optional <code>return</code> statement, where it is also possible to ''return'' a value.
A function is ended with the optional <code>return</code> statement, where it is also possible to ''return'' a value.
You can imagine a return value as being 'inserted' into where the function was called. If no return value is specified within the function, it returns the value as <code>null</code>.
You can imagine a return value as being 'inserted' into where the function was called. If no return value is specified within the function, it returns the value as <code>null</code>.
Line 251: Line 301:
function IsEven(n)
function IsEven(n)
{
{
  if (n % 2 == 0)
if (n % 2 == 0)
    return true
return true
  else
else
    return false
return false
}
}


if (IsEven(42)) // (42 % 2 == 0) == true
if (IsEven(42)) // (42 % 2 == 0) == true
{
{
  printl("42 is even!")
printl("42 is even!")
}
}
</source>
</source>
|}
|}


==Classes==
===Classes===
The following is just an example of some basic class syntax. For details, see [http://www.squirrel-lang.org/squirreldoc/reference/language/classes.html Squirrel API about classes].
The following is just an example of some basic class syntax. For details, see [http://www.squirrel-lang.org/squirreldoc/reference/language/classes.html Squirrel API about classes].
<source lang=cpp>
{{tip|Some of the [http://www.squirrel-lang.org/squirreldoc/reference/language/metamethods.html#metamethods metamethods] you might want to override include <code>_tostring(), _typeof(), _cmp(other), _add(other), _sub(other), _mul(other), _div(other), _modulo(other), _nexti(previdx)</code>.}}
<source lang=cpp style="display:table-cell; background-color:transparent">
class Weapon
class Weapon
{
{
static prefix = "weapon_" // static variables are read-only!
static prefix = "weapon_" // static variables are read-only!
// For instance-individual variables it's best to declare them with anything and overwrite them on construction.
// For instance-individual variables it's best to declare
// them with anything and overwrite them on construction.
name    = null
name    = null
primMax = null
primMax = null
secMax  = null
secMax  = null
count = [0] // Containers and instances are not copied per instance, just the reference. count[0] is the same for all of instances.
// Containers and instances are not copied per instance, just
// the reference. count[0] is the same for all of instances.
count = [0]
constructor(name0, prim, sec)
constructor(name0, prim, sec)
Line 286: Line 340:
}
}
function GetAll()
function GetEntities()
{
{
local list = []
local list = []
Line 302: Line 356:
awp  <- Weapon("awp", 10, 30)
awp  <- Weapon("awp", 10, 30)
ak47 <- Weapon("ak47", 30, 90)
ak47 <- Weapon("ak47", 30, 90)
// can access class variables and class functions with awp.[...]
// can access class variables and functions
// with awp.primMax, awp.GetEntities(), etc.
</source>
 
===Generators===
A [http://www.squirrel-lang.org/squirreldoc/reference/language/generators.html#generators generator] is a function where the key word <code>yield</code> appears; It suspends the execution of that generator function and can return some expression to the function that had <tt>resume</tt>d it. Some generator <code>g</code> can be resumed with the expression <code>resume g</code>; The value of this <code>resume</code> expression is what was <code>yield</code>ed when the function has been suspended the last time. The <code>return</code> value of a generator does not matter.
 
Generators can be used in <code>foreach</code> statements, such that no <code>resume</code> statement must be typed.
<source lang=cpp style="display:table-cell; background-color:transparent">
function PowersOfTwo()
{
for (local n = 1; true; n *= 2)
yield n
}
 
local x = 100
// Set x to the smallest power of 2
// that is larger than or equal to x:
foreach (i,pow in PowersOfTwo())
{
if (pow >= x)
{
x = pow
break
}
}
</source>
</source>
{{Todo | Get a better example.}}


==Scripting==
==Scripting==
Line 319: Line 397:
* [[VScript Fundamentals]]
* [[VScript Fundamentals]]
* {{l4d2}} [[L4D2 Vscripts|Scripting in L4D2]]
* {{l4d2}} [[L4D2 Vscripts|Scripting in L4D2]]
* {{csgo}} [[List of Counter-Strike: Global Offensive Script Functions]]
* {{csgo}} [[List of CS:GO Script Functions]]


==External Links==
==External Links==

Revision as of 20:03, 20 September 2022

English (en)Translate (Translate)

Squirrel Squirrel is a programming language similar to Lua, but uses a C like syntax. In Source Squirrel is used as one of the scripting languages in the VScript scripting system. The official Squirrel documentation can be found here

Squirrel heavily uses an associative array data structure called a table. Both the keys and values of a table can contain almost any kind of variable. The scripting environment consists of nested tables, and when a script is executed its variables and functions are added as table slots.

printl("Hello World"); // statements can end with both a semicolon...
printl("Hello World")  // ...or a newline character

Squirrel's syntax is similar to C/C++/Java etc... but the language has a very dynamic nature like Python/Lua etc. Statements can be separated with both a new line or ; (or with the keywords case or default if inside a switch/case statement), both symbols are not required if the statement is followed by }.

Variables

Squirrel has two kinds of variables: table slots and local variables. Since the execution scope is always a table, any variables declared outside functions will always be table slots.

  • Table slots have to be declared using the <- operator. These are to be used for values that should remain when a function ends. Once a slot exists, it can be reassigned with both the = or the <- operator.
  • Global variables are slots in the root table (getroottable()). They can be declared using the :: scoping operator and accessed without it.
  • Variables local to functions can be declared using the local keyword. These are to be used for temporary values or helpers that can be discarded after a function call.
  • Constants are declared with the const keyword and computed compile-time. Their value can only be an integer, float or string. During runtime, getconsttable() returns a table with all constants.
Note.pngNote:local and const variables are declared with the = operator. Using <- for those yields a compile time error.
a <- 5               // creates a table slot in this table
b <- "A text string" // creates a table slot in this table
::x <- 10            // creates a table slot in the root table
local i = 0          // initializes a temporary variable
const PI = 3.14159   // creates a new constant

b = "New string"     // modifies the existing table slot
x = 11               // modifies the existing table slot

The in operator can be used to test whether a table slot exists. One could also use try {a} catch (e) { /*...*/ }. The following code is assumed to be executed after the above, i.e. in the same environment.

"a" in this  // true
"x" in this  // false, unless we're in the root table
"i" in this  // false, local variables aren't table slots
"PI" in this // true
delete a     // deletes a table slot
"a" in this  // false, no longer exists

Data Types

Squirrel is a dynamically typed language. Any variable can be assigned a value of any type.

Note.pngNote: The VScript API functions are bindings to the Source C++ code, so while it may seem possible to pass values of any type to them, they only accept specific types.

The built-in function typeof returns the type of an input value as a string in lower case, e.g. typeof(5) == "integer".

Type Description
Integer The integers -2,147,483,648 to 2,147,483,647, namely -231 to 231-1.
Float -3.4028235e38 to 3.4028235e38, namely -3.4028235 × 1038 to 3.4028235 × 1038.
String An immutable string. They behave like C strings, and support escape sequences (\t,\a,\b,\n,\r,\v,\f,\\,\",\',\0,\xhhhh).
Null
Bool Boolean data type that can be true or false.
Table Associative array.
Array Mutable C style array.
Function Second order functions are supported, so functions can assigned as values to variables.
Class Object oriented class. Implementation similar to tables.
Class Instance Object instances of classes. Script handles generated by the game also identify as instances.
Generator
Todo: Possibly unavailable in VScript
Userdata Opaque data used by the game.
Thread
Todo: Possibly unavailable in VScript
Weak reference

Bool

Squirrel considers null, 0 (type Integer) and 0.0 (type Float) as false, any other value is considered true. This allows you for example to null-check variables using if (var).

Warning.pngWarning:Don't null-check Integers or Floats like this if they may be 0 or 0.0, obviously. This concerns the built-in string function find(<substring>) which returns either the index where it found the given substring or null. Do if (var == null) instead.
if (false) { /* ... */ } // not executed
if (null)  { /* ... */ } // not executed
if (0)     { /* ... */ } // not executed
if (0.0)   { /* ... */ } // not executed

Tables

Tables are associative arrays, meaning that they contain a collection of key-value pairs, called slots. A table can be indexed into using the key, returning the associated value. The keys and values can be of any data type (except null for the key), including other tables, allowing the creation of more complex data structures.

Tables are defined using curly brackets. Inside a table definition slots can be defined using the key1 = value1, key2 = value2, ... pattern. Outside of the definition, new slots can be added to existing tables using the table.key <- value pattern.

Using the . operator to index a key only works when the key is a string or numerical literal. Array style indexing table[keyVariable] can be used to index any kind of key.

Tip.pngTip:Some of the built-in functions for tables are len(), clear(), keys(), values().
// Table defintion.
myTable <-
{
	a = 3,              // key: "a", value: 3
	b = 7,              // key: "b", value: 7
	x = "example text", // key: "x", value: "example text"
	[5] = "five"        // key:  5 , value: "five"
	
	nestedTable =
	{
		z = "another string"
	}
}

// alternatively:
myTable <- {}
myTable["a"] <- 3 // string keys can be indexed...
myTable.b    <- 7 // ...in two ways
myTable.x    <- "example text"
myTable[5]   <- "five" // numbers must be indexed like this
myTable.nestedTable <- { z = "another string" }
foreach (key, value in myTable)
{
	printl(key + ": " + value)
}
// Prints (order might vary!):
// a: 3
// x: example text
// b: 4
// 5: five
// nestedTable: (table : 0x000000000069D130)

printl("a" in myTable) // prints "true"
printl( 3  in myTable) // prints "false"
// Adding non-string keys
a <- "0"
myTable[a] <- 11     // key: "0", value: 11

printl(myTable.a)    // prints "3"
printl(myTable[a])   // prints "11"
printl(myTable["0"]) // prints "11"
printl(myTable[0])   // exception, key 0 doesn't exist

printl(myTable.nestedTable.z) // prints "another string"

Arrays

Arrays are sequences of objects that are numerically indexed starting from 0. Syntactically they function similarly to C arrays, but unlike C arrays, they are mutable and values can be inserted and removed using a set of built in functions.

Arrays are defined using square brackets.

Warning.pngWarning:You can't use the in operator to test whether some value is in the array because for Squirrel, arrays are tables where the keys are the indices. The in operator would look through the indices that the array has and not its values.
Tip.pngTip:Some of the built-in functions for arrays are len(), clear(), append(<value>), insert(<index>, <value>), remove(<index>), find(<value>).
// Array definition.
myArray <- 
[
	7,           // key: 0, value: 7
	"more text", // key: 1, value: "more text"
	null         // key: 2, value: null
]

// alternatively:
myArray <- []
myArray.append(7)
myArray.append("more text")
myArray.append(null)

// alternatively:
myArray <- array(3)
myArray[0] = 7
myArray[1] = "more text"
myArray[2] = null
foreach (index, value in myArray)
{
	printl(index + ": " + value)
}
// Prints:
// 0: 7
// 1: more text
// 2: null

printl(     2      in myArray) // prints "true"
printl("more text" in myArray) // prints "false"
printl(myArray[0]) // prints "7"

myArray.remove(0)

printl(myArray[0]) // prints "more text"

Functions

Functions in Squirrel work similarly to their C counterparts. Second order functions are supported, so functions can be directly manipulated like other values, including it being possible to store them in variables and table slots. Default parameter values and variable numbers of parameters are also supported.

For more details, see the Squirrel API about functions.

It is common practice to begin with a capital letter when naming functions.

// declares and (re)defines "Greet"
function Greet()
{
	printl("Hello!")
}

Greet() // prints "Hello!"
// declares and (re)defines "Greet"
Greet <- function()
{
	printl("Hello!")
}

Greet() // prints "Hello!"
// (re)defines "Greet"; exception if "Greet" not declared!
Greet = function()
{
	printl("Hello!")
}

Greet() // prints "Hello!"

When a function is called, it can be made so that it can or must receive input values that determine the function's side effects and/or its return value.

  • Multiple parameters must be comma delimited: function Test( a , b , c , d=4, e=5) {...}
  • All parameters with no default value must be ordered first.
  • To avoid exceptions, it is often a good idea to check if a parameter is not null. The statements if (object != null) {...} and if (object) {...} are equivalent.
  • As parameters are not restricted to a type, the typeof function can be used to handle different types differently.
// normal parameter
function Greet(name)
{
	printl("Hello, " + name + "!")
}

Greet()       // exception
Greet("Gabe") // prints "Hello, Gabe!"
// parameter with default value
function Greet(name="Gordon")
{
	printl("Hello, " + name + "!")
}

Greet()       // prints "Hello, Gordon!"
Greet("Gabe") // prints "Hello, Gabe!"

A function is ended with the optional return statement, where it is also possible to return a value. You can imagine a return value as being 'inserted' into where the function was called. If no return value is specified within the function, it returns the value as null.

function IsEven(n)
{
	if (n % 2 == 0)
		return true
	else
		return false
}

if (IsEven(42)) // (42 % 2 == 0) == true
{
	printl("42 is even!")
}

Classes

The following is just an example of some basic class syntax. For details, see Squirrel API about classes.

Tip.pngTip:Some of the metamethods you might want to override include _tostring(), _typeof(), _cmp(other), _add(other), _sub(other), _mul(other), _div(other), _modulo(other), _nexti(previdx).
class Weapon
{
	static prefix = "weapon_" // static variables are read-only!
	
	// For instance-individual variables it's best to declare
	// them with anything and overwrite them on construction.
	name    = null
	primMax = null
	secMax  = null
	
	// Containers and instances are not copied per instance, just
	// the reference. count[0] is the same for all of instances.
	count = [0]
	
	constructor(name0, prim, sec)
	{
		name    = prefix + name0
		primMax = prim
		secMax  = sec
		count[0]++
	}
	
	function GetEntities()
	{
		local list = []
		local wep = null
		while ( wep = Entities.FindByClassname(wep, name) )
		{
			list.append(wep)
		}
		return list
	}
	
	// ... more useful functions ...
}

awp  <- Weapon("awp", 10, 30)
ak47 <- Weapon("ak47", 30, 90)
// can access class variables and functions
// with awp.primMax, awp.GetEntities(), etc.

Generators

A generator is a function where the key word yield appears; It suspends the execution of that generator function and can return some expression to the function that had resumed it. Some generator g can be resumed with the expression resume g; The value of this resume expression is what was yielded when the function has been suspended the last time. The return value of a generator does not matter.

Generators can be used in foreach statements, such that no resume statement must be typed.

function PowersOfTwo()
{
	for (local n = 1; true; n *= 2)
		yield n
}

local x = 100
// Set x to the smallest power of 2
// that is larger than or equal to x:
foreach (i,pow in PowersOfTwo())
{
	if (pow >= x)
	{
		x = pow
		break
	}
}

Scripting

Please see VScript Fundamentals for more information.

With the Source VScript system, scripts are stored in the game\scripts\vscripts\ directory. Squirrel scripts use the .nut file extension, and the .nuc extension for ICE encrypted files.

Common to all Squirrel using games, scripts can be associated to a game entity as an entity script that is executed then the entity spawns, and has access to the script handle of its entity through the self variable. Specific games can also have other methods of executing scripts.

Script files can also be executed from the Developer Console using the script_execute command. Lines of code can even be executed in-line with the script command.

See Also

External Links