Data Types
C4Script supports the following data types for variables, parameters, and return values:
Type Name |
Full Name |
Contents of Variable |
Example |
int |
Integer |
A whole number from -2.147.483.648 to +2.147.483.647. |
42 |
bool |
Boolean |
"true" (value true ) or "false" (value false ). Expected as parameter by many structures such as if and while. |
true |
id |
definition id |
ID of an object definition (see Object Definitions) |
CLNK |
string |
String |
Any text. Single characters can be extracted as int with . Furthermore, it is possible to extract single characters as single-character-strings using "string"[index] . Strings can not be modified this way. Negative indices count backwards, starting from the end. |
"Dies ist ein Text!" |
object |
Object pointer |
Reference to an existing object at runtime. No direct representation. See FindObject(). Access to local variables is possible via obj["name"] or obj.name , the latter if #strict 3 is activated. |
- |
array |
array |
A type containing multiple variables, whose number can be enquired with GetLength, and which can be recalled with array[index] . Since CR. |
[0,42,CLNK] |
map |
Map |
A type that allows storing values associated with keys of arbitrary types. GetKeys and GetValues can be used to determine the set keys and values of the map as array. Values can be accessed by their key using map[key] . If the key is a fixed string containing only characters allowed in identifiers the access can also happen via map.key . Since LC [334], only with #strict 3 or above. |
{ X: 10, Y: 50 } |
Additionally, there are two special types:
-
any
: The type is unknown or does not matter. "nil" always has this type.
-
&
: The value is a reference, for example to a variable. It behaves exactly as the target value, but can be changed (for example with the operator "=
"). See also Reference parameters.
Arrays
Arrays can be created directly with
[expression 1, expression 2, ...]
or indirectly with
CreateArray(). They are automatically enlarged if necessary on element access, but it's faster to create them with the needed length from the start. If an array is stored in a variable or used as a parameter to a function, the new variable has it's own copy of the array. The actual copy is deferred if possible, though. If an array is passed to a function for modification, a reference has to be used.
Access to element i
of array a
is achieved through a[i]
. i=0
is the first element.
Elements can be appended to the array using a[] = value;
Example 1
func ArraySum(array a)
{
var l = GetLength(a);
var result = 0;
for (var i = 0; i < l; ++i)
{
result += a[i];
}
return (result);
}
This function adds up all elements of an array.
Example 2
func RandomID()
{
var a = [CLNK, WIPF, BIRD, HUT1];
return (a[Random(4)]);
}
This function randomly chooses one out of four ids and returns it.
Maps
Maps are also known as hashes or associative arrays in other languages. Maps are only available if
#strict 3 or higher is enabled. Maps can be created directly with
{ Key 1 = Expression 1, Key 2 = Expression 2, "key3" = "Expression 3, [Key Expression] = Expression 4, ... }
. To ease future additions, a comma may be placed after the last key-value-pair. An empty map can be created with
{}
. If a key contains characters not allowed in identifiers the key must be enclosed in "" (quotation marks), otherwise quotation marks are optional. To use values of types different than string or the result of an expression as key, enclose it in
[]
(see example).
The syntax for accessing map values is map[key]
. If the key is a fixed string containing only characters allowed in identifiers the access can also happen via map.key
. To remove a key from the map set its value to nil
.
If a map is stored in a variable or used as a parameter to a function, the new variable has it's own copy of the map. The actual copy is deferred if possible, though. If a map is passed to a function for modification, a reference has to be used.
Using a special
for variant it is possible to iterate over all key-value-pairs of a map.
GetKeys and
GetValues can be used to determine the set keys and values of the map as array. Internally, maps are implemented using a hash. To ensure synchronization in the network mode, additionally the insertion order of the keys is stored. Insertion order in this case means the order in which each key is set in a map for the first time, possibly after it has been already deleted.
Attention
If an object is used directly as key and in the meantime it is deleted, the related value is removed from the map. However, if the object is contained arbitrarily in a map or array that is being used as a key and the object is deleted, the associated value becomes inaccessible and also can not be removed. The only way to get rid of such a state is resetting the whole map by assigning a new one to the variable.
Example 1
func MapPlayground(int plr)
{
var clonk = GetCursor(plr);
var m = {
Position = { X = GetX(clonk), Y = GetY(clonk) },
Name = GetName(clonk),
Contents = {},
"Player's Name" = GetPlayerName(plr),
};
Log("Der Clonk von %s heißt %s und befindet sich bei Position %v.", m["Player's Name"], m.Name, m.Position);
var flint = clonk->CreateContents(FLNT);
var rock = clonk->CreateContents(ROCK);
m.Contents[0] = flint;
m.Contents[1] = rock;
m.Contents[FLNT] = flint;
m.Contents[ROCK] = rock;
Log("%v", m);
m.Contents[FLNT] = nil;
Log("Contents: %v", m.Contents);
}
This function demonstrates the usage of maps.
Example 2
#strict 3
local discounts;
func Initialize()
{
discounts = {
// [discount in %, pieces left], could also be maps, but would be more writing effort :p
[CLNK] = [10, 3],
[EFLN] = [25, 4],
[WOOD] = [50, 50],
[GetID(GetCursor(0))] = [5, 1],
// ...
};
}
func GetDiscount(id ID)
{
return discounts[ID]?[0] || 0;
}
func SoldItem(id ID)
{
if(discounts[ID])
{
if(--discounts[ID][1] == 0)
{
discounts[ID] = nil;
}
}
}
Part of an object script that manages discounts for various articles of limited amount using a map.
Conversion
Consult the following table to determine which types can be converted and which conversions might cause errors:
to -> |
int |
bool |
id |
object |
string |
array |
map |
int |
OK |
OK |
if <= 9999 |
Error |
Error |
Error |
Error |
bool |
OK |
OK |
Error |
Error |
Error |
Error |
Error |
id |
#strict |
OK |
OK |
Error |
Error |
Error |
Error |
object |
#strict |
OK |
Error |
OK |
Error |
Error |
Error |
string |
#strict |
OK |
Error |
Error |
OK |
Error |
Error |
array |
Error |
OK |
Error |
Error |
Error |
OK |
Error |
map |
Error |
OK |
Error |
Error |
Error |
Error |
OK |
Additional information:
- Conversions marked #strict will only throw an error if the script is #strict. This only concerns harmless but nonsense conversions which might have appeared in older scripts.
- Conversion to id is valid only if the number is greater than or equal to 0 and less that or equal to 9999. This procedure also supports IDs that contain digits only.
- Conversion to bool is generally allowed. All values except 0 are
true
.
Günther, April 2006
PeterW, April 2006