|
The most complex aspect of TorqueScript involves dealing with game objects. Much of your object creation will be performed in the World Editor, but you should still know how to manipulate objects at a script level. One thing to remember is that everything in TorqueScript is an object: players, vehicles, items, etc.
Every object added in the level is saved to a mission file, which is written entirely in TorqueScript. This also means every game object is accessible from script. First, we will study the syntax of object creation.
Even though objects are originally created in C++, they are exposed to script in a way that allows them to be declared using the following syntax:
Object Definition:
// In TorqueScript %objectID = new ObjectType(Name : CopySource, arg0, ..., argn) { <datablock = DatablockIdentifier;> [existing_field0 = InitialValue0;] ... [existing_fieldN = InitialValueN;] [dynamic_field0 = InitialValue0;] ... [dynamic_fieldN = InitialValueN;] };
Syntax Breakdown:
The main object variants you can create are SimObjects without a datablock, and game objects which require a datablock. The most basic SimObject can be created in a single line of code:
Example:
// Create a SimObject without any name, argument, or fields. $exampleSimObject = new SimObject();
The $exampleSimObject variable now has access to all the properties and functions of a basic SimOBject. Usually, when you are creating a SimObject you will want custom fields to define features
Example:
// Create a SimObject with a custom field $exampleSimObject = new SimObject() { catchPhrase = "Hello world!"; };
As with the previous example, the above code creates a SimObject without a name which can be referenced by the global variable $exampleSimObject. This time, we have added a user defined field called "catchPhrase." There is not a single stock Torque 3D object that has a field called "catchPhrase." However, by adding this field to the SimObject it is now stored as long as that object exists.
The other game object variant mentioned previously involves the usage of datablocks. Datablocks contain static information used by a game object with a similar purpose. Datablocks are transmitted from a server to client, which means they cannot be modified while the game is running.
We will cover datablocks in more detail later, but the following syntax shows how to create a game object using a datablock.
Example:
// create a StaticShape using a datablock datablock StaticShapeData(ceiling_fan) { category = "Misc"; shapeFile = "art/shapes/undercity/cfan.dts"; isInvincible = true; }; new StaticShape(CistFan) { dataBlock = "ceiling_fan"; position = "12.5693 35.5857 59.5747"; rotation = "1 0 0 0"; scale = "1 1 1"; };
Once you have learned about datablocks, the process is quite simple:
Every game object added to a level can be accessed by two parameters:
Example:
// In this example, CistFan is the name of the object new StaticShape(CistFan) { dataBlock = "ceiling_fan"; position = "12.5693 35.5857 59.5747"; rotation = "1 0 0 0"; scale = "1 1 1"; };
While in the World Editor, you will not be allowed to assign the same name to multiple, separate objects. The editor will ignore the attempt. If you manually name two objects the same thing in script, the game will only load the first object and ignore the second.
If you need a global script object with only a single instance, you can use the singleton keyword. Singletons, in TorqueScript, are mostly used for unique shaders, materials, and other client-side only objects.
For example, SSAO (screen space ambient occlusion) is a post-processing effect. The game will only ever need a single instance of the shader, but it needs to be globally accessible on the client. The declaration of the SSAO shader in TorqueScript can be shown below:
singleton ShaderData( SSAOShader ) { DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; DXPixelShaderFile = "shaders/common/postFx/ssao/SSAO_P.hlsl"; pixVersion = 3.0; };
In addition to the creation of stand-alone functions, TorqueScript allows you to create and call methods attached to objects. Some of the more important ConsoleMethods are already written in C++, then exposed to script. You can call these methods by using the dot (.) notation.
Syntax:
objHandle.function_name(); objName.function_name();
Example:
new StaticShape(CistFan) { dataBlock = "ceiling_fan"; position = "12.5693 35.5857 59.5747"; rotation = "1 0 0 0"; scale = "1 1 1"; }; // Write all the objects methods to the console log CistFan.dump(); // Get the ID of an object, using the object's name $objID = CistFan.getID(); // Print the ID to the console echo("Object ID: ", $objID); // Get the object's position, using the object's handle %position = $objID.getPosition(); // Print the position to the console echo("Object Position: ", %position);
The above example shows how you can call an object's method by using its name or a variable containing its handle (unique ID number). Additionally, TorqueScript supports the creation of methods that have no associated C++ counterpart.
Syntax:
// function - Is a keyword telling TorqueScript we are defining a new function. // ClassName::- Is the class type this function is supposed to work with. // function_name - Is the name of the function we are creating. // ... - Is any number of additional arguments. // statements - Your custom logic executed when function is called // %this- Is a variable that will contain the handle of the 'calling object'. // return val - The value the function will give back after it has completed. Optional. function Classname::func_name(%this, [arg0],...,[argn]) { statements; [return val;] }
At a minimum, object methods require that you pass them an object handle. You will often see the first argument named this. People use this as a hint, but you can name it anything you want. As with Console functions any number of additional arguments can be specified separated by commas.
As a simple example, let's say there is an object called Samurai, derived from the Player class. It is likely that a specific appearance and play style will be given to the samurai, so custom ConsoleMethods can be written. Here is a sample:
Example:
function Samurai::sheatheSword(%this) { echo("Katana sheathed"); }
When you add a Samurai object to your level via the World Editor, it will be given an ID. Let's pretend the handle (ID number) is 1042. We can call its ConsoleMethod once it is defined, using the period syntax:
Example:
1042.sheatheSword();
// OUTPUT: "Katana sheathed"
Notice that no parameters were passed into the function. The this parameter is inherent, and the original function did not require any other parameters.