Documentation

Table Of Content

1: Introduction

2: Setting up a development environment

2.1: Cellblock9's 2 data folders

2.2: Copy original data

2.3: Create development shortcut

2.4: Associate the internal editor with scripts

3: File formats and their uses

3.1: .png files for textures

3.2: .ogm files for sounds

3.3: .xml files

3.3.1: character xml

3.3.2: move xml

3.3.3: cb9enginedefaults.xml

3.4: .lgs files

4: The internal script editor

5: The LGS scripting language

5.1: Goals for LGS:

5.2: Programming styles officially supported by LGS:

5.2.1: Event based programming:

5.2.2: C-ish functions:

5.2.3: object oriented programming C++-style:

5.3: Control logic:

5.3.1: If/else:

5.3.2: foreach

5.3.3: for

5.3.4: while

5.4: Data types & declaring variables:

5.4.1: LGS Supports the following basic data types:

5.4.2: You can declare your own variables like this:

5.4.3: Variable scopes:

5.5: Declaring functions:

5.6: Custom datatypes (classes):

5.6.1: Function overriding in classes: (polymorphism)

5.7: List of all keywords:

5.8: List of all operators:

5.9: List of all functions/api's:

5.9.1: Level manipulation:

5.9.2: Physics engine:

5.9.3: Related to moves:

5.9.4: Related to players:

5.9.5: Graphics: predefined rendering

5.9.6: Graphics: particles

5.9.7: Graphics: models

5.9.8: Graphics: camera

5.9.9: Graphics: shaders

5.9.10: Graphics: opengl

5.9.11: Graphics: messages

5.9.12: Time related functions:

5.9.13: Scoring/gamemode:

5.9.14: Math:

5.9.15: String manipulation:

5.9.16: Object manipulation:

5.9.17: Event programming:

5.9.18: Sounds:

5.9.19: HTML manipulation:

5.9.20: Menu navigation & manipulation:

5.9.21: Character api:

5.9.22: Type conversions/casting:

5.9.23: networking/synchronisation

5.9.24: Files/web resources:

5.9.25: Tables/internal tables:

5.9.26: Utilities:

6: Useful links

1: Introduction

This page contains some work-in-progres documentation for the game and how to modify it.

Lemmingball Z was originaly designed as just a simple game, but I do have a new goal with it. I want to make the technology behind LBZ available for other game projects. Right now, very little about the technology is written down. These pages server to make a start. The technology behind LBZ is called the "Cellblock 9 engine" or CB9 for short. This is because i am a huge fan of the bluesbrothers movie and blues music in general.

Features of the engine include:

  • Built-in level editor
  • Built-in script/xml editor with syntax highlighting
  • Built-in model viewer/importer
  • Destructable terrain
  • Use XML to define your own moves, with very little programming
  • A networking system that "just works" like "magic", no need to think about synchronizing characters/moves over the internet.

2: Setting up a development environment

If you want to build a mod to LBZ or if you just want to edit the game a bit you will need a development version of the game.
In this document i will detail how to set up a current development environment for modding LBZ.

2.1: Cellblock9's 2 data folders

  • The installation folder: that is the folder where you extracted the ZIP file. Usually something like "c:\games\downloaded\Lemmingball Z"
  • The profile folder: this is created by the LBZ updater to store settings. Usually "C:\Users\[your username]\Documents\LBZ Alpha Game Data"

2.2: Copy original data

To create a development environment for LBZ copy the data folder from the profile folder to the installation folder and name it dev-data.
Do not overwrite the data folder that is already there... in your installation folder should now be a data folder and a folder named dev-data.

2.3: Create development shortcut

  • In the installation folder create a new shortcut to lbzwin.exe.
  • Right-click the new shortcut and select properties.
  • A screen should open with all properties of the shortcut: The first field should be target and should contain a full path to lbzwin.exe.
  • To this field add --debug without the quotes.
  • The field should read something like: "C:\games\downloaded\LBZ\lbzwin.exe" --debug
  • Click OK to save the shortcut.

You now have a working development install of LBZ! When you start LBZ with the newly created shortcut: all data will be loaded from the dev-data folder instead of the regular data. You can verify this by checking the console and scrolling up: you should see a message: "Found 'dev-data' directory in developer mode!!!" The updater will never tough this folder. if the game gets updated and you want/need the new files, manually copy over the profile/data folder to dev-data Now you can mod/hack/edit as much as you want.

2.4: Associate the internal editor with scripts

To open .lgs script files with LBZ's internal script editor, navigate to the dev-data folder, find an LGS scriptfile, right-click and select open with. Click the browse button and navigate to the shortcut. Select the shortcut and click ok. From this moment on clicking an LGS file in the dev-data folder will open up LBZ's internal editor with syntax highlighting.

 

3: File formats and their uses

LBZ makes use of a lot of different files, almost all files can be edited with a simple text editor, or with the ingame script editor.

3.1: .png files for textures

As a general rule: the engine does not put size limits on textures.
Textures are stored as .png files (portable network graphics) .png have loss-less compression and can be easily loaded without big image libraries.

Textures can have specular maps, normal maps and "inner textures". (inner textures are used when destroying/tunneling inside objects carrying this texture)

Say you have a nice grass texture (1024x1024) called grass.png

  • Specular map: the A channel of the base texture can be used as a specular map (reversed specularity... to 255 == no specularity, 0 == full specularity)
  • To use a normal map with the texture: Create a png called grass.nmap.png , the RGB channels are for normal map data
  • To use an inner material with the grass texture: Create a png file grass.destroy.png , of course this can have its own nmap... grass.destroy.nmap.png

 

3.2: .ogm files for sounds

Ogm files are simply used for sound. They are referenced from the move files. A good sound editor that can export ogm files is audacity.

(TO BE EXPANDED)

3.3: .xml files

XML stands for EXtensible Markup Language. XML was designed to store and transport data. XML was designed to be both human- and machine-readable.

The CB9 engine uses XML files for many things: this is an example XML file:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<gamedefaults> 
 <name>Lemmingball Z</name> <!--The full name of the game--> 
 <shortname>LBZ</shortname> <!--The short name of the game--> 
 <newsurl>http://www.lbz3d.com/?rml</newsurl>
</gamedefaults>

CB9 has 2 features that can be used in ANY XML file it reads:

  • Including of other XML files:
    <lxi:include src="someotherxml.xml">path/to/stuff</lxi:include>
  • Inline scripts: Any tag that is supposed to contain a filename that points to a script can use the lxi:inlinelgs option to inline the script...
    <script id="addgamescript">data/moves/myscript.lgs</script>
    Can be inlined like:
    <script id="addgamescript" lxi:inlinelgs="1">
      <![CDATA[
        /*CONTENT OF SCRIPT*/
      ]]>
    </script>
    
    

3.3.1: character xml

Character XML is used to define selectable characters for the game. (TO BE EXPANDED)

3.3.2: move xml

Move XML is used to define attacks (moves). (TO BE EXPANDED)

3.3.3: cb9enginedefaults.xml

This XML file contains the minimal information the engine requires to start and function. (TO BE EXPANDED)

3.4: .lgs files

The Cellblock9 engine comes with its own scripting language called LGS. LGS stands for "Lemmingball Game Script", it is used for make game rules and decisions like who gets points, who lives, who dies. It is also fast enough to be used for graphics. LGS is a simple language and it's design is based on C++. In LGS you do not have to manage memory, making it safe to play around in.

4: The internal script editor

CB9 comes equiped with a syntax highlighting editor. To open the editor press CTRL+q while inside the game. The game needs to be started with the --debug paramater. (see here). (TO BE EXPANDED)

5: The LGS scripting language

5.1: Goals for LGS:

  • Fast enough to be used in graphics and in gameplay
  • Display errors fast and early to help you write good code
  • Easy to understand
  • Includes advanced features such as object oriented programming, event based programming etc etc

5.2: Programming styles officially supported by LGS:

5.2.1: Event based programming:

React to a specific event generated by the gameengine, or another script For example:

//When a player dies
catchallevents(_SYS_PLAYER_DEATH) {
	//I want to write to console:
	print(Player_name+" died!");
}
	

5.2.2: C-ish functions:

Easy to understand flow of the program For example:

function isPlayerDead(int player) return int{
	//
	return 1;
}
//Check if player 2 is dead
if(isPlayerDead(2)) {
	print("Hah! player 2 is dead!");
}

5.2.3: object oriented programming C++-style:

Can organize your code/data in a better way. (Good for communication) For example:

//Define a base class for mammals
class _mammal {
	float health=100;
	function kill() {
		health = 0;
	}
}

//Define a base class for greed
class _greedy {
	int cashInCents=100000;

	function withdraw(int amount) return int {
		cashInCents -= amount;
		return amount;
	}
}

//Define a human as a mammal with greed and a name:
class _human extends _mammal,_greedy {
	string name;	
}

//Create a human:
object _human myself;
myself->name = "Menne Kamminga";
//I am rich:
myself->cashInCents = 100;
//Now i am broke:
myself->withdraw(100);
//Dont want to life as a poor man:
myself->kill();

//Print my current state:
print("My health is:"+cast_ftos(myself->health,2));

5.3: Control logic:

5.3.1: If/else:

Basic control logic, like a question:

if(health < 0) {
	//i am dead
} elseif(health < 10){
	//i am alive, but almost dead
} else {
	//i am alilve!
}

5.3.2: foreach

Loop trough a list of things:

//Have a list of names
string names[]={"AnalyticaL","LSDuck"};
//Loop trough all names:
foreach(names index a) {
	//Print out the names:
	print(names[a]);
}

5.3.3: for

A custom loop:

//Countdown from 10:
for(int c = 10;c>0;c--) {
	//Prints 10, then 9, then 8 etc etc
	print(cast_itos(c));
}

5.3.4: while

Loop for as long as a condition is true:

//For as long as i am alive:
while(Player_health > 1) {
	//Eat cookies:
}

5.4: Data types & declaring variables:

5.4.1: LGS Supports the following basic data types:

  • float - representes numbers with an imaginary part like -1000.50 or 3.14750
  • int - Represents whole (integer) number like -1, 1000 or 777
  • string - Represents text string line = "this is a line of text";
  • resource - Represents a system resource, like a texture or a sound. Also used to store things like "events"
  • object - Magic store, can store a whole bunch of things together. can optionally have a class with its own functions.
    Example: 
    object myStore;
    myStore["name"] = "My first magick store object";
    myStore["number"] = 10;

5.4.2: You can declare your own variables like this:

{1 or more type selectors} (Optional class name) {name}([Optional list size]) (=Optional initializer). Available type selectors are:

  • float: sets primary type to float
  • int: sets primary type to int
  • string: sets primary type to string
  • resource: sets primary type to resource
  • object: sets primary type to object. objects can store anything, can optionally have a class name
  • var: sets primary type to "unknown"
  • global: changes the memory location of this variable to "global" AKA "this variable is the same in every script"
  • moveglobal: changes the memory location of this variable to "moveglobal" AKA "this variable is unique for every move and the same in every script for that move"
  • playerglobal: changes the memory location of this variable to "playerglobal" AKA "this variable is unique for every player and the same in every script for that player, including all the players moves"
  • ref: turns the variable into a "reference": this means the variable "points" to another variable instead of having memory of its own. (for strings or objects)
  • auto: Guess the variable type from it's initializer (requires initializer).

A couple of examples:

  • int age=42; //Declare an integer number named "age" and set it to 42
  • int ages[4] = {15,16,17,18}; //Declare a list of 4 integers named ages and fill it with 15,16,17,18
  • string name="LSDuck"; //Declare a bit of text named "name" and set contents to LSDuck
  • string ref namePoint = name; //Declare a reference to a bit of text and point it to "name"
  • object dork; //Declare an object that can store anything.
  • object _human dork2; //Declare an object that stores everything defined in class "_human"
  • auto dork3 = dork2; //Make a copy of the dork2 object... note the use of auto to guess the type.

5.4.3: Variable scopes:

By default, each variable you declare is only available inside the scope you declare it in. You can spot scopes easily. Each scope starts with { and ends with } For example:

float myhealth = 100.1;
if(1) { // Watch it, starting new scope:
	float myhealth = 0;//New variable also called myhealth, but in different scope!
}
//myhealth is still 100.1

5.5: Declaring functions:

Most (almost ALL) of the time, when you write a piece code, you want to reuse it in a different spot. For example: you might want to damage your enemy, then tell the world about what you did:

	
Enemy_health -= 10;
print("Hah! i damaged "+Enemy_name+" for 10 points!");

You probably want to do this multiple times so you can write it as a function:

//Declare a function:
function damageEnemy(float points) return float {
	Enemy_health -= points;
	print("Hah! i damaged "+Enemy_name+" for "+cast_ftos(points,0)+" points!");
	
	return Enemy_health;
}

Now you can just write:

float health_remaining = damageEnemy(10);

5.6: Custom datatypes (classes):

With the magic "object" datatype you can also declare your own "custom" datatypes... These are called classes. A class is defined as follows:

class {name} (Optional: extends {other class},{another class}) {
	{variable declarations}
	
	(Optional function declarations)
}

For example:

	
class myFirstClass extends someBaseClass {
	int myFirstVariableInAClass;
	
	function increase() return int {
		myFirstVariableInAClass++;
		return myFirstVariableInAClass;
	}
}

5.6.1: Function overriding in classes: (polymorphism)

Consider these classes:

//Define base class for color:
class color {		
	function use() {
		//Nothing to do here
		print("ERROR! base color used");
	}
}

//Define "red" color:
final class red extends color{
	function use() {
		glColor4f(1,0,0,1);
	}
}

//Define "blue" color:
final class blue extends color{
	function use() {
		glColor4f(0,0,1,1);
	}
}

//If i have an object of class color:
object color myTeamColor;

//And some color objects:
object blue myBlue;
object red myRed;

//You can do this: (make the team color blue)
myTeamColor = myBlue;
myTeamColor->use();//Even though myTeamColor is of class "color", this will call the use() from the "blue" class!
myTeamColor = myRed;
myTeamColor->use();//Even though myTeamColor is of class "color", This will call the use() from the "red" class!

5.7: List of all keywords:

Keywords are words that have special meaning in the LGS language: this is a list of all such keywords. If you ever need to have a variable with the same name as a keyword, you can use $. ($construct means variable with name construct, just using construct will not work as it has special meaning)

  • #uctexture
    	Define an uncompressed texture: #uctexture "myfile.png" as myTex
    	This defines a resource variable myTex holding texture data from file "myfile.png"
    
  •  	
    #texture
    	Define a regular texture: #texture "myfile.png" as myTex
    
  •  
    #sound
    	Define a sound: #sound "myname.ogm" as mySound
    	Defines a resource variable holding a sound
    
  •  	
    #htmlfile
    	Define a html file: #htmlfile "myname.html" as myDocument
    	Defines a resource variable holding a html document
    
  •  		
    #htmlelement
    	Define a html element: #htmlelement "_myelementid_" as myElement
    	Defines a resource variable holding an element retrieved by getElementById from last loaded document.
    
  •  		
    #model
    	Define a model: #model "myname.xml" as myModel
    	Defines a resource variable holding a model
    
  •  
    #modelanim
    	Define an animation: #modelanim "myanimationname" as myAnim
    	Defines a resource variable holding an animation loaded from last loaded #model
    
  •  	
    #warning
    	Give out a warning: #warning "This file should not be used anymore"
    	Will print the warning when the script is used. Usefull for detecting scripts that use old includes for example.
    
  •  	
    #event
    	Declare an event: #event _MY_FIRST_EVENT
    	This will define a global event.
    	You can trigger an event with fireEvent(_MY_FIRST_EVENT);
    	Then another script, (or same script) can "catch" that event: catchevent(_MY_FIRST_EVENT) {/*Some code to execute on event*/}
    
  •  		
    #timer
    	Declare a timer: #timer _MYTIME
    	use with timeMark function and timeSince to get high-resolution time data.
    
  •  		
    #include
    	Include a file into your script: #include "someotherfile.inc"
    	All the stuff defined in someotherfile.inc becomes available in your current script.
    
  •  	
    for
    	The custom for loop (See control logic)
    
  •  		
    foreach
    	The foreach for loop (See control logic)
    
  •  		
    as
    	Used while declaring resources: #texture "blah" as ...
    
  •  		
    return
    	Returns from the current function, if this function is "main()" then exit script.
    	Can optionally return a variable from a function: 
    		function test() return float {
    			float myFloat = 7.0;
    			return myFloat;
    		}
    
  •  
    index
    	Used in the foreach loop: foreach(myArray index a) 
    	Names the index... in this example, if myArray has 10 elements, then "a" would count from 0 to 9
    
  •  		
    while
    	A while loop: while(CONDITION) {/*code*/}
    	Basicly: for a long as CONDITION is true: execute code inside the brackets.
    
  •  		
    catchevent
    	Catches an event exactly once: catchEvent(_SYS_PLAYER_DEATH) { /*Do something the next time the player dies...*/ }
    	Can catch multiple events at once: catchEvent(_SYS_PLAYER_DEATH,_SOME_OTHER_EVENT) {}
    
  •  		
    catchallevents
    	Permanently catches all events: catchAllEvents(_SYS_PLAYER_DEATH) { /*Do something every time the player dies...*/ }
    	Can catch multiple events at once: catchEvent(_SYS_PLAYER_DEATH,_SOME_OTHER_EVENT) {}
    
  •  		
    function
    	Starts the declaration of a new function: function myName() {}
    	Code between the {} gets called each time you call the function with "myname()"
    
  •  		
    if
    	(See control logic)
    	if(CONDITION) {/*CODE*/} //Execute CODE if CONDITION == true
    
  •  		
    elseif
    	(See control logic)
    	Can be appended to an if or another elseif code block to put multiple conditions together
    
  •  		
    else
    	(See control logic)
    	Can be appended to an if or an elseif, if the previous condition is NOT true, execute this.
    
  •  		
    class
    	Start defining a class: see: Custom datatypes (classes)
    	class myClassName { /*Some variables and/or functions */ }
    
  •  		
    extends
    	For classes, declares that this class is an extension of an existing class:
    	class myOtherClass extends myBaseClass,myOtherBaseClass { /*Some more variables*/ }
    	extended classes inherit all the variables&function from the base class it extends, and can then add it's own stuff...
    	You can extend multiple classes at once...
    	You can override functions from a base class. (see: Custom datatypes (classes))
    
  •  			
    _event
    	Define an inline event: _event{/*Code to execute on event*/}
    	This is usefull for functions that take an event as parameter.
    	For example: webMessage("http://url","My message to send",_event{ /*Code to execute when the webserver has replied to message */} ,1.0);
    	Basicly triggerEvent(_event{/*code*/}); is the same as:
    		#event _MY_EVENT
    		catchAllEvents(_MY_EVENT) {/*code*/}
    		triggerEvent(_MY_EVENT);
    	So in some cases, this is just less typing...
    
  •  				
    break
    	Break away from a while, for, or foreach loop. (stops the loop.)
    	For example: 
    	foreach(arrayOfColors index i) {
    		if(arrayOfColors[i] == "blue") {
    			print("i found the color blue");
    			break;//Can stop the loop now.
    		}
    	}
    
  •  	
    typename
    	Returns the typename of an argument as a string: print(typename(MYVARIABLE));
    	For example: if the type of MYVARIABLE is "float", this would print "float"
    
  •  		
    deref
    	De-reference a reference to an object or a string: (See: Data types & declaring variables)
    	Consider 2 strings and a reference to a string:
    		string A="Menne"; 
    		string B=" Kamminga";
    		string ref C;
    		
    		//This will make C point to A: (C does not have memory of its own, it is now pointed to A)
    		C = A;
    		
    		//Now this will overwrite A: (After all, C = pointed to A)
    		deref(C) = "David";
    		
    		//This will point C to B:
    		C = B;
    		
    		//This will print David Kamminga
    		print(A+B);
    	References, and dereferences can be used to gain speed boosts by NOT copying objects or strings around.
    	It can also simplyfy some algorithms. They can be tough to understand, so only use it if you understand it!
    
  •  			
    construct
    	Force construction of an unconstructed object: construct(A);
    	object storage is only actually created when the object gets used. This forces an to be created.
    	Also, references to objects with classes are also not created.
    	Consider this slightly complecated example:
    		class _tree{
    			//These children do NOT get constructed, if they would be, this would mean an endless loop since they are of the same type (_tree) as the parent.
    			object _tree children[2];
    			function getChild(int numChild) return object _tree{
    				//Here we force construction of a specific child and then return it.
    				return construct(children[numChild]);
    			}
    		}
    
  •  	
    __construct
    	For classes: Special function inside a class that gets called when object of that class gets constructed.
    		class myClass{
    			function __construct() {
    				print("Hi! I get called each time an object of class myClass is created...");
    			}
    		}
    
  •  		
    private:
    	For classes: class members (variables or functions) that follow this are private and cannot be called outside of the class.
    		class myClass {
    			private:
    			int i;
    			public:
    			int c;
    		}
    		object myClass A;
    		A->i = 0; //Error: "i" is private
    		A->c = 0; //Correct: "c" is public
    
  •  			
    public:
    	The opposite of private: (see private:)
    
  •  		
    final
    	The final keyword marks classes or class members as final:
    	final class myClass{} // Other classes cannot extend this class (see "extends") since it is marked final.
    	class myNotSoFinalClass {// Other class CAN extend this class:
    		final function myFunc() {// But this myFunc, cannot be overriden in any class that extends myNotSoFinalClass.
    		
    		}
    	}
    

5.8: List of all operators:

Operators are composed of 1 or 2 characters and have special meaning in the LGS language. This is a list of all operator and their meaning and priority (from lowest to highest priority)

  • operator =
    	The assignment operator. A = B;
    	//Copy content from B to A
    	A = B; 
    	//(If A is a reference, point A to B instead of performing a copy)
    
  •  
    operator +=
    	Add B to A: A += B; //(same as A = A + B)
    
  •  
    operator -=
    	Substract B from A:	A -= B; //(Same as A = A - B)
    
  •  
    operator *=
    	Multiply A by B: A *= B; //(Same as A = A * B)
    
  •  
    operator /=
    	Divide A by B: A /= B; //(Same as A = A / B)
    
  •  
    operator %=
    	Set A  to the modulus of A / B: A %= B; //(Same as A = A % B)
    	A modulus is the leftover value from a division. (6/4 == 1, 6%4 == 2)
    
  •  
    operator &=
    	Binary AND operation on A & B: A = A & B 
    	If A in binary is 0001 and B is 1001, then the result is 0001
    
  •  
    operator |=
    	Binary OR operation on A | B: A = A | B 
    	If A in binary is 0001 and B is 1001, then the result is 1001
    
  •  
    operator ^=
    	Binary EXCLUSIVE OR operation on A ^ B: A = A ^ B 
    	If A in binary is 0001 and B is 1001, then the result is 1000
    
  •  
    operator ||
    	Logical OR operation. A || B will be true when either A OR B is true.
    	primary use: if(A || B || C) { doSomthing() }
    
  •  
    operator &&
    	Logical AND operation. A && B will be true when both A AND B are true.
    	primary use: if(A && B && C) { doSomthing() }
    
  •  
    operator |
    	Binary OR operator: C = A | B; 1001 = 1000 | 0001;
    
  •  
    operator ^
    	Binary EXCUSIVE OR operator: C = A ^ B; 1110 = 0001 ^ 1111;
    
  •  
    operator &
    	Binary AND operator: C = A & B; 0001 = 1111 & 0001;
    
  •  
    operator !=
    	Does not equal: A != B  is true when A is different from B
    
  •  
    operator ==
    	Equal: A == B is true when A is the same as B
    
  •  
    operator >
    	Greater then: A > B is true when A is bigger then B
    
  •  
    operator >=
    	Greater then or equal: A >= B is true when A is bigger then B or A == B
    
  •  
    operator <=
    	Less then or equal: A <= B is true when A is smaller then B or A == B
    
  •  
    operator <
    	Less then: A < B is true when A is smaller then B
    
  •  
    operator +
    	Add: C = A + B;
    
  •  
    operator -
    	Minus: C = A - B;
    
  •  
    operator *
    	Multiply: C = A * B;
    
  •  
    operator /
    	Divide: C = A / B;
    
  •  
    operator %
    	Modulus: C = A % B;
    
  •  
    operator !
    	NOT operator: !A is true when A is false
    
  •  
    operator ++
    	Increment: A++ means: A = A + 1
    
  •  
    operator --
    	Decrement: A-- means: A = A - 1
    
  •  
    operator []
    	Subscript... A[N] extract N'th from A.
    	If A is an array, then N is the index of the element you want.
    	If A is an object, then N is the string name of the property you want.
    
  •  
    operator {}
    	Extract property: A{N} extract property with name N from object A
    
  •  
    operator ->
    	Extractor operator A->B extracts member "B" from object A.
    	member B can be a function: A->B();
    	member B can be a variable: A->B = 0.1;
    

5.9: List of all functions/api's:

5.9.1: Level manipulation:

function	Level_Decal(float P0,resource P1,float P2,float P3,float P4);		
//Place a decal @ coords P0, texture P1, brightness P2, size P3, Rotation P4
function	Level_DisplaceWater(float P0,float P1,float P2,float P3);		
//Displace water at position P0,P1,P2 by P3
function	Level_PointIsInAir(float P0) return int ;		
//Returns 1 if point P0 (x,y,z) is in open air, 0 when in level.
function	levelDigHole(float P0,float P1,float P2);		
//Blast a round hole of size P2 at x P0 y P1 in the level
function	levelHeal();		
//heal all level damage

5.9.2: Physics engine:

function	Physics_ApplySForce(int P0,float P1,float P2,float P3);		
//Add a force to object P0, P1-P3 == force
function	Physics_ApplySForcePivot(int P0,float P1,float P2,float P3,float P4,float P5,float P6);		
//Add a force to object P0, P1-P3 == force, P54-6 == pivot point
function	Physics_Ball(float P0,float P1,float P2,float P3,float P4);		
//Put a force at P0,P1,P2 with strength P3, radius P4
function	Physics_CollisionStrength(int P0,float P1);		
//Calculate collision power acting on P0, and return it in P1
function	Physics_DidHitGround(int P0,int P1);		
//Check if object P0 has hit the ground, result in P1
function	Physics_DidHitObject(int P0,int P1);		
//Check if object P0 has hit an object, result in P1
function	Physics_Explosion(float P0,float P1,float P2,float P3);		
//Put an explosion force at P0,P1,P2 with strength P3
function	Physics_ForceCone(float P0,float P1,float P2,float P3,float P4);		
//Put a forcecone at P0,P1,P2 strength P3, radius P4
function	Physics_FreeMoveInTimeStop(int P0,int P1);		
//Check if Body P0 can move in a timestop, result in P1
function	Physics_GetPos(int P0,float P1,float P2,float P3);		
//Return the positon of Body P0 into P1,P2,P3
function	Physics_GetRotationVector(int P0,float P1,float P2,float P3);		
//Return the rotation speed of Body P0 into P1,P2,P3
function	Physics_GetVelocity(int P0,float P1,float P2,float P3);		
//Return the speed of Body P0 into P1,P2,P3
function	Physics_KeepInAir(int P0);		
//Apply reverse gravity to body P0
function	Physics_LastCollidedObject(int P0,int P1);		
//Return the object that last bumped into P0 into P1
function	Physics_Lock(int P0);		
//Lock body P0
function	Physics_Phase(int P0);		
//Put physics body P0 out of phase
function	Physics_RotationForceCone(float P0,float P1,float P2,float P3,float P4,float P5);		
//Put a force at P0,P1,P2 with rotation P3, strength P4, radius P5
function	Physics_SetMaxAirSpeed(int P0,float P1);		
//Limit physics airspeed of P0 to P1
function	Physics_SetVelocity(int P0,float P1,float P2,float P3);		
//Set the speed of Body P0 to P1,P2,P3
function	Physics_Teleport(int P0,float P1,float P2,float P3);		
//Teleport physics object P0 to position P1,P2,P3
function	Physics_TimestopMass(int P0,int P1,float P2);		
//Stop time, except for body P0, P1 == on/off, P2 == length of timestop
function	Move_bounceAttacks();		
//Bounce all attacks of this move!
function	move_switch_state(int P0);		
//Switches the move safely to a new state

function	Player_cancelMove(int P0,int P1);		
//Cancel move of player P0, if P1 is nonzero, also cancel locking moves (beams)
function	Player_ischarging(int P0) return int ;		
//Returns 1 if player P0 is charging a move currently
function	Player_setCombo(string P0);		
//Let player execute combo P0
function	Player_setTarget(int P0,int P1);		
//Set target of player P0 to player P1
function	Player_setXxComboTime(int P0);		
//For player P0 resets the combo timer to current time (calling this extends combo time by Movesystem_special_combotimeinseconds)
function	damageplayer(float P0,int P1,int P2);		
//Deal P0 damage to player P1, damage is done by P2
function	getPlayerVar(int P0,string P1) return var ;		
//Fetch variable P1 from player P0's context or currently held move.
function	getSelectedChar(int P0) return int ;		
//Get selected character for player with number P0
function	playerCanMove(int P0);		
//puts 1 into P0 when player is allowed to move
function	playerGetMoveAnims(resource P0,resource P1);		
//Get animations as choosen by the move system int P0 and P1
function	playerGetTimeSinceLastHit(float P0);		
//Get seconds since player last got hit.
function	swapRenderScript(int P0,int P1);		
//Swap player P0's render script with player P1's render script

5.9.5: Graphics: predefined rendering

function	Static_DrawFlash(float P0,float P1,float P2,float P3);		
//Draw a flash at P0=x P1=y P2=size P3= rotation
function	fastQuad();		
//Renders a quad to the screen from 0,0 to 1,1 coords (fast)
function	addLight(float P0,float P1,float P2,float P3,float P4,float P5,float P6,int P7);		
//add a light to the scene, XYZ, Size, RGB, optimize
function	renderShockWave(float P0,float P1,float P2);		
//Render a shader effect of a shockwave
function	smoothShading(int P0);		
//Turn on/off smoothshading
function	solidSphere(float P0);		
//(Sphere, With cellshading)
function	drawTail();		
//(Render a tail on object that have one.)
function	getWorldColor(float P0);		
//get current color into array P0[3]
function	getWorldPosition(float P0);		
//get current coordinates into array P0[3]
function	sphere(float P0);		
//(Draw a sphere (A1 == size))
function	sphereNotrans(float P0);		
//(Sphere, only without translation.)
function	sphereTex(float P0);		
//(Sphere, With textureing)
function	sprite();		
//(Render a sprite with current defined settings)
function	textureAspect(resource P0,float P1);		
//Retrieves the aspect ratio for a texture into P1
function	texture_set(resource P0);		
//(set texture P0 (0 == first loaded texture, 1 second etc etc))

5.9.6: Graphics: particles

function	clearParticleSystem(resource P0);		
//Clear particle system P0
function	createParticleSystem() return resource ;		
//creates a new particle system and returns it
function	spawnParticles(resource P0,int P1,float P2,float P3,int P4);		
//Spawn particles in system: P0: particlesystem, P1: numberOfParticles, P2: 3 floats position, P3: radius, P4: Physics body to spawn from (-1 for none)
function	drawParticleSystem(resource P0,int P1);		
//render particle system P0 to the screen with mode P1
function	updateParticleAttract(resource P0,float P1,float P2,float P3);		
//Attract particles towards point P1[3], with strength P2, radius P3 == particle death zone
function	updateParticleMove(resource P0,float P1,float P2,float P3);		
//Move particles at postion P1[3] -radius P3, to position P2[3] 
function	updateParticleSpawnColor(resource P0,float P1,float P2);		
//updates particle system P0 new min/max color P1[3],P2[3]
function	updateParticleSpawnDir(resource P0,float P1);		
//updates particle system P0 new direction P1[3]
function	updateParticleSystem(resource P0,float P1);		
//updates particle system P0 with timeRelative variable P1
function	updateParticleSystemSettings(resource P0,object P1);		
//updates particle system P0 with settings from object P1

5.9.7: Graphics: models

function	modelAddColor(float P0,float P1,float P2,float P3);		
//sets an additive color for rendering
function	modelAnim(resource P0);		
//Set animation P0 on current Model
function	modelAttachBones();		
//Attach Bones to model skeleton
function	modelColor(float P0,float P1,float P2,float P3);		
//Set model color.
function	modelDetachBones(float P0,float P1,float P2,float P3,float P4,float P5);		
//Detach Bones from model skeleton, postion P0,P1,P2 velocity P3,P4,P5
function	modelGetAnim(resource P0);		
//Retrieve animation from current model P0
function	modelGetEndOfAnim(int P0);		
//Get end of animation flag into P0
function	setModel(resource P0);		
//Set current model to P0
function	drawModel();		
//render model
function	updateModel();		
//Update model animation
function	updateModelTS(float P0);		
//Update model with TimeRelative variable P0

5.9.8: Graphics: camera

function	gameSpace();		
//Set camera mode to gameplay
function	hudSpace();		
//Set camera mode to hud rendering
function	playerSpace();		
//Set opengl matrices for rendering player models
function	skyboxSpace();		
//Set camera mode to skybox rendering

5.9.9: Graphics: shaders

function	shaderActivate(string P0);		
//Loads and activates shader data/shaders/P0.xml, drawing function will use this shader
function	shaderDeactivate();		
//Stops using last loaded shader, drawing function will use their own shaders
function	shaderSetFlr(string P0,float P1);		
//Set's a shader uniform with name P0 to float P1
function	shaderSetInt(string P0,int P1);		
//Set's a shader uniform with name P0 to int P1
function	shaderSetVec3(string P0,float P1);		
//Set's a shader uniform with name P0 to vec3 P1
function	shaderSetVec4(string P0,float P1);		
//Set's a shader uniform with name P0 to vec4 P1

5.9.10: Graphics: opengl

//See opengl manual (WARNING! SLOW)
function	glBegin(var P0);		
function	glBindTexture(int P0);		
function	glBlendFunc(var P0,var P1);		
function	glColor4f(float P0,float P1,float P2,float P3);		
function	glDisable(var P0);		
function	glEnable(var P0);		
function	glEnd();		
function	glLoadIdentity();		
function	glRotatef(float P0,float P1,float P2,float P3);		
function	glScalef(float P0,float P1,float P2);		
function	glTexCoord2f(float P0,float P1);		
function	glTranslatef(float P0,float P1,float P2);		
//See opengl manual (also includes camera calculations)
function	glTranslatefFORCE(float P0,float P1,float P2);		
//See opengl manual (does not includes camera calculations)
function	glVertex2f(float P0,float P1);		
function	glVertex3f(float P0,float P1,float P2);		

5.9.11: Graphics: messages

function	centerMessage(string P0);		
//Add message P0 to center of screen.
function	message(string P0);		
//Add message P0 to top of screen

function	timeMark(resource P0);		
//Mark current time into timer P0
function	timeSinceMark(resource P0,float P1);		
//put time since marked timer P0 into P1

5.9.13: Scoring/gamemode:

function	addScoreTeam(int P0,int P1);		
//Add P1 points to Team P0
function	cheat(int P0,string P1) return int ;		
//Cheating!, set player P0 attribute P1 to a higher value: return true on success (attributes: pl, health, energy, size)
function	endGameMode();		
//end game and show scoreboard
function	getCategoryString(string P0) return string ;		
//Return a string from the gamemode database from category P
function	getLevelBounds(float P0);		
//Put the levels maximum bounds in array P0[4]
function	getScoreLimit(int P0);		
//Get the scorelimit into P0
function	getScoreTeam(int P0,int P1);		
//Set P0 to score of Team P1
function	restartGameMode();		
//restart the gamemode
function	setScoreLimit(int P0);		
//Set the scorelimit P0
function	setTeam(int P0,int P1);		
//Set team of playernum
function	switchTeam(int P0,int P1);		
//Switch player P0 to Team P1

5.9.14: Math:

function	cosf(float P0) return float ;		
//return cosinus of P0
function	floor(float P0,int P1);		
//floor P0 and put result into P1
function	inv(int P0);		
//Invert P0
function	invf(float P0);		
//Invert P0
function	length3d(float P0,float P1,float P2,float P3);		
//Put distance from P1,P2,P3 to Offset into P0
function	length_3d(float P0,float P1,float P2,float P3,float P4,float P5) return float ;		
//return distance from P1,P2,P3 to P4,P5,P6
function	random() return float ;		
//Return a random number between 0.0 and 1.0
function	sinf(float P0) return float ;		
//return sinus of P0
function	sqrt(float P0) return float ;		
//return square root of P0
function	swapf(float P0,float P1);		
//Swap values of P0 and P1
function	swapi(int P0,int P1);		
//Swap values of P0 and P1
function	xor(int P0,int P1);		
//Xor P0 With P1

5.9.15: String manipulation:

function	isStringTempUnlocked(string P0) return int ;		
//Return 1 when resource identified by P0 is unlocked temporarily
function	isStringUnlocked(string P0) return int ;		
//Return 1 when resource identified by P0 is unlocked
function	quoteString(string P0) return string ;		
//Put quotes inside string P0  and return it.
function	print(string P0);		
//Print string P0
function	regex_match(string P0,object P1,string P2) return int ;		
//run regular expression P2 over subject string P0 and store matches in object P1, return number of matches
function	regex_replace(string P0,string P1,string P2) return string ;		
//replaces occurences of regex P1 with P2 in string P0 and return result
function	str_replace(string P0,string P1,string P2) return string ;		
//replaces P0 with P1 in string P2 and returns P2, P2 is modified
function	str_substr(string P0,int P1,int P2) return string ;		
//returns substring out of P0 offset P1 length P2
function	strlen(string P0) return int ;		
//returns length of string P0
function	tempUnlockString(string P0) return int ;		
//Unlock resource identified by P0 for this session, returns number of new unlocks
function	unlockString(string P0) return int ;		
//Unlock resource identified by P0 permanently, returns number of new unlocks

5.9.16: Object manipulation:

function	objectClear(object P0);		
//Clears object P0 (makes it empty)
function	objectClearProperty(object P0,string P1) return int ;		
//Clears property P1 from object P0 returns 1 on success
function	objectGetPropSize(object P0,string P1) return int ;		
//gets the size of property P1 from object P0
function	objectHasFunction(object P0,string P1) return int ;		
//Returns 1 when object P0 has a function by name P1
function	objectHasProperty(object P0,string P1) return int ;		
//Returns 1 if object P0 has property with name P1
function	objectIsEmpty(object P0) return int ;		
//Returns true if object P0 is empty
function	objectIsPersistent(object P0) return int ;		
//Returns true if object P0 is persistent
function	objectSerialize(object P0) return string ;		
//Serializes object P0 and returns it as an JSON string
function	objectSetPersistent(object P0,int P1);		
//Set object P0's persistent state to P1
function	objectUnSerialize(string P0,object P1) return int ;		
//UnSerializes JSON string P0 and put the resulting object in P1, returns 1 on success 0 on failure

5.9.17: Event programming:

function	fireEvent(resource P0);		
//Fires off event P1
function	getEventData() return object ;		
//Retrieve information about current triggered event as an object
function	getEventId(string P0) return resource ;		
//Translates an event Name to an event ID resource
function	getEventName(resource P0) return string ;		
//Translates an event ID to an event name
function	setEventData(object P0);		
//Store event return information object P0

5.9.18: Sounds:

function	playAnnounce(resource P0);		
//Play sound effect P0 over announce channel
function	playEffect(resource P0);		
//Play sound effect P0

5.9.19: HTML manipulation:

function	addClassToClass(string P0,string P1);		
//(HTML ONLY) add class P0 to elements with CLASS P1
function	addClassToId(string P0,string P1);		
//(HTML ONLY) add class P0 to element with ID P1
function	close();		
//(HTML ONLY) Close current menu
function	closeOverlay();		
//(HTML ONLY) Close current overlay
function	getElementAttribute(resource P0,string P1) return string ;		
//get Attribute with name P1 from HTML element P0
function	getElementByID(resource P0,string P1) return resource ;		
//Return a resource to element with ID P1 in document P0, returns -1 on error
function	guiHideDoc(resource P0);		
//GUI, hide document P0
function	guiHideElement(resource P0);		
//GUI, show element P0
function	guiInsertNumber(float P0,int P1,resource P2);		
//insert number P0 with P1 decimals into element P2
function	guiMessage(int P0,string P1,string P2) return int ;		
//Displays GUI message of type P0, title P1, and text P2
function	guiPlayerHinttext(resource P0);		
//GUI, show player's hinttext in  element P0
function	guiPositionDoc(resource P0,float P1,float P2,float P3,float P4);		
//Position document P0 -> top:P1,left:P2,bottom:P3,right:P4, -1 means a position is not used
function	guiSetBarColor(resource P0,float P1,float P2,float P3,float P4);		
//GUI, If P0 is a  element set bar color to P1-P4
function	guiSetBarPRC(resource P0,float P1);		
//GUI, If P0 is a  element set bar percentage to P1
function	guiSetTexture(resource P0,resource P1);		
//Set texture P1 on HTMLELEMENT P0
function	guiShowDoc(resource P0);		
//GUI, show document P0
function	guiShowElement(resource P0);		
//GUI, show element P0
function	hideClass(string P0);		
//(HTML ONLY) hide elements with CLASS P0 in current document
function	hideId(string P0);		
//(HTML ONLY) hide element with ID P0 in current document
function	myDoc() return resource ;		
//(HTML ONLY) Return a resource to the current document.
function	open(string P0) return int ;		
//(HTML ONLY) Open HTML file P0 and show it as a menu
function	openOverlay(string P0) return int ;		
//(HTML ONLY) Open HTML file P0 and show it as an overlay
function	refocus();		
//(HTML ONLY) refocus on the right element in the document
function	reload(string P0) return int ;		
//(HTML ONLY) Unload current document and replace it with P0, returns true on success.
function	removeClassFromClass(string P0,string P1);		
//(HTML ONLY) remove class P0 from elements with CLASS P1
function	removeClassFromId(string P0,string P1);		
//(HTML ONLY) remove class P0 from element with ID P1
function	setElementAttribute(resource P0,string P1,string P2);		
//set Attribute with name P1 from HTML element P0 to P2
function	setElementCSSProperty(resource P0,string P1,string P2) return int ;		
//set CSS Property with name P1 from HTML element P0 to P2
function	setInnerHtml(resource P0,string P1);		
//Set the Inner HTML of element P0 to P1
function	showId(string P0);		
//(HTML ONLY) show element with ID P0 in current document


function	le_saveLevel();		
//Stores the current level to disk.
function	le_selectTexture();		
//(HTML ONLY) Selects the (int)value of the current element as a new texture for the leveleditor
function	le_setMode(string P0) return int ;		
//Set mode P0 as the new mode for the leveleditor return true on success
function	le_setShape(string P0);		
//Set the shape P0 as the current shape of the leveleditor
function	leveleditor_load();		
//(HTML ONLY) loads currently selected level in leveleditor.
function	leveleditor_new() return int ;		
//(HTML ONLY) creates a new level based on input settings, return true on success
function	local_start_game();		
//(HTML ONLY) Starts a local game
function	local_stop_game();		
//(HTML ONLY) Stops a local game
function	mod_disable(int P0);		
//(HTML ONLY) disable mod P0 in the mod list
function	mod_disable_all();		
//(HTML ONLY) enable all mods
function	mod_enable(int P0);		
//(HTML ONLY) enable mod P0 in the mod list
function	mod_enable_all();		
//(HTML ONLY) disable all mods
function	mod_save();		
//(HTML ONLY) save the mod list
function	console(string P0);		
//(HTML ONLY) Execute console command P0
function	consoleinput();		
//(HTML ONLY) When this function is used in an event, it will execute commands in console and/or tab-complete
function	engineInputDown(string P0);		
//(HTML ONLY) send a keydown event into the engine
function	engineInputUp(string P0);		
//(HTML ONLY) send a keyup event into the engine
function	modelview_setAnim(int P0);		
//set animation P0 in the model viewer
function	modelview_unload() return int ;		
//close the model viewer.
function	net_block();		
//(HTML ONLY) blocks currently selected server
function	net_join();		
//(HTML ONLY) joins currently selected server
function	net_join_lan();		
//(HTML ONLY) joins a lan game
function	net_join_lan_quick();		
//(HTML ONLY) quickjoin nearest lan game.
function	net_login() return int ;		
//(HTML ONLY) tries to login into the central chatserver, return true on success false on failure
function	net_logout();		
//(HTML ONLY) logs out of internetplay.
function	net_pause();		
//(HTML ONLY) pauses a network game (to show the chatmenu)
function	net_privatemessage(string P0);		
//(HTML ONLY) Focus field with ID P0 and input the sequence for sending a private message
function	net_resume();		
//(HTML ONLY) resumes a paused network game.
function	net_selectplayer(int P0);		
//(HTML ONLY) select player/server P0 in the netplay table
function	net_sendChat();		
//(HTML ONLY) input function for sending the current value of a field as a chatmessage when enter is pressed.
function	net_sendInGameChat();		
//(HTML ONLY) input function for sending the current value of a field as an ingame chatmessage when enter is pressed.
function	net_start_game();		
//(HTML ONLY) starts a new networked game
function	updateGameMode();		
//(HTML ONLY) Internal function that loads the right scorelimits.

5.9.21: Character api:

function	addCharacter(object P0) return int ;		
//add character from object P0
function	replaceCharacter(object P0,int P1) return int ;		
//replace char

5.9.22: Type conversions/casting:

function	cast_FtoI(float P0) return int ;		
//cast float P0 to int and return it 
function	cast_FtoS(float P0,int P1) return string ;		
//Cast P0 to a string with precision p1
function	cast_ItoF(int P0) return float ;		
//cast int P0 to int and return it 
function	cast_ItoR(int P0) return resource ;		
//cast int P0 to resource and return it 
function	cast_ItoS(int P0) return string ;		
//Cast P0 to a string
function	cast_RtoI(resource P0) return int ;		
//cast resource P0 to int and return it 
function	cast_StoF(string P0) return float ;		
//Cast string P0 into an float and return it
function	cast_StoI(string P0) return int ;		
//Cast string P0 into an int and return it
function	itof(int P0,float P1);		
//Convert P0 to float and put result in P1

5.9.23: networking/synchronisation

function	checkServerSideOnly(int P0);		
//put 1 into P0 when we are running a server, or when we are playing local.
function	getFirstLocalPlayerNum() return int ;		
//return Player ID of 1st local player.
function	getNumLocalControllers() return int ;		
//return number of local controllers (players behind local screen)
function	netAddCustomData(string P0,string P1) return int ;		
//Add an sync object of type P0 into syncStream with P1 as initial data.
function	netAddCustomType(string P0,resource P1);		
//Add's a custom data sync type with name P0. event P1 is called when data of this type is received on the client side.
function	netRemoveCustomData(int P0) return int ;		
//Remove data of sync object P0
function	netSync(var P0,string P1,int P2) return int ;		
//sync int or float P0 with networked clients under name P1 (P2==0 to sync @ player, P2==1 to sync @ move) On client this receives, on server this sends.
function	netUpdateCustomData(int P0,string P1) return int ;		
//Change data of sync object P0 to P1
function	sendServiceMessage(string P0);		
//Send a message to the other players across the network, other players receive it using the _SYS_SERVICEMESSAGERECEIVED event

5.9.24: Files/web resources:

function	webMessage(string P0,string P1,resource P2,float P3);		
//Sends HTTP POST request to URL P0, with message P1 in post variable 'msg', on return of data, calls event P2. Task is run in background with priority P3 (lower is higher priority)
function	fileGetContents(string P0,int P1) return string ;		
//Return contents of file P0 as string P1 == true means from LBZ virtual filesystem, 0 == from main OS filesystem
function	filePutContents(string P0,string P1) return resource ;		
//Puts content P1 into file with name P0
function	systemOpen(string P0,int P1);		
//Open file/URL P0 with system program, P1 == 1 means minimize the game first.
function	getAppPathTo(string P0) return string ;		
//Returns [path to profile directory]+P0

5.9.25: Tables/internal tables:

function	getTableNumRows(string P0) return int ;		
//Returns total number of rows in internal table P0
function	getTableRow(int P0,string P1,string P2,string P3) return string ;		
//Returns row number P0 from internal table P1 where P2 is a list of colums and P3 is a seperator
function	nofityTableChange(string P0);		
//let the engine know that table P0 changed

5.9.26: Utilities:

function	dbg_steptrough(int P0);		
//Step trough this script
function	dbghud(string P0,string P1);		
//Add debug information P1 to the fullperformancehud under name P0
function	die(string P0);		
//Kill current script and crash with error P0
function	exit();		
//(Exit LGS and return control to the game)
function	getHelp(string P0) return string ;		
//Get description for for function or symbol P0
function	getLevelEditorActive() return int ;		
//return true is level editor is active
function	getPerformanceData() return object ;		
//Retrieve information about performance graphs as an object
function	getRunningProcesses(object P0) return int ;		
//get all processes running on computer into object P0
function	getTmpFile(string P0) return string ;		
//Returns a filename for temporary file P0
function	inputNewKey(string P0);		
//(HTML ONLY) Captures current key from HTML keydown or keyup event and maps it to function P0
function	lastError() return string ;		
//returns a string with last error set by system
function	pop(var P0);		
//Pop P0 from the stack
function	push(var P0);		
//Push P0 on the stack
function	quit_cb9(int P0,string P1);		
//Quit the game with error code P0 and error message P1 (errorcode 0 ==success 777 === restart)
function	resetarray(var P0);		
//Reset values in array P0 to zero
function	sizeof(var P0) return int ;		
//return array size of P0
function	store_settings();		
//stores all configuration variables.
function	testout(string P0);		
//Output line P0 into test log (for lgstests.xml)

 

How to create a normal map: https://developer.valvesoftware.com/wiki/Normal_Map_Creation_in_The_GIMP

Leave a Reply

Your email address will not be published. Required fields are marked *