Scripting Documentation: Difference between revisions

Ringwaul (talk | contribs)
No edit summary
Ringwaul (talk | contribs)
No edit summary
 
(5 intermediate revisions by the same user not shown)
Line 13: Line 13:
Here we will cover the basic steps on creating a new object usable within OpenClonk.
Here we will cover the basic steps on creating a new object usable within OpenClonk.


Because creating each new object from scratch would be tedious, repetitive work, we provide a template object to work with. This is available within the base Objects.ocd (TemplateObject.ocd).
Because creating each new object from scratch would be tedious, repetitive work, we provide a template object to work with.


'''Step 1'''
'''Step 1'''
Line 25: Line 25:
[DefCore]
[DefCore]
id=TemplateObject
id=TemplateObject
Version=4,10,0,0
Version=5,2,0,1
Category=C4D_Object
Category=C4D_Object
Width=8
Width=8
Line 40: Line 40:
</pre>
</pre>


What do all these things do? Here's a breakdown of the definitions we're using:
DefCores contain a fair amount of basic object data, but for now we only need to change the ID to something unique; for example:
{| class="gallery"  border = 1 style="width:100%; margin-right:0;"
|-
! style="width:10%;"| Property
! style="width:15%;"| Data Type
! style="width:75%;"| Usage
|-
|id
|definition ID
|An identifier the engine uses to name the object (must be unique!).
|-
|Version
|4 integers
|Minimal engine version required by the object. Should be always the current engine version at the time of the last change. Let's leave it as 4,10,0,0 (default OpenClonk).
|-
|Category
|String (max. 30 chars)
|Defines the base functionality of the object. Default here is C4D_Object (has gravity, collides with terrain, etc.). A thorough description of the different categories can be found [http://docs.openclonk.org/en/sdk/definition/category.html here].
|-
|Width
|Integer
|The X-length of the object. This relates to the graphics data used.
|-
|Height
|Integer
|The Y-length of the object. Relates to the graphics data used.
|-
|Offset
|2 Integers
|The offset is where the object's pivot-point (or centre-point) is. Normally, you'd want it to be in the centre of the object. Since the object is X=8, Y=8, the centre-point should go back to the half of X (-4) and to the half of Y (-4).
|-
|Vertices
|Integer
|The amount of vertex points the object has (1 to 30). Primarly used for collision. The following 'Vertex' properties refine the vertices' properties.
|-
|VertexX
|up to 30 integers
|List of horizontal vertex coordinates of the object. Vertex 1 is the first integer, vertex 2 is the second integer, etc.
|-
|VertexY
|up to 30 integers
|List of vertical vertex coordinates of the object. Follows the same pattern as VertexX (now it defines the vertices' vertical coordinate).
|-
|VertexFriction
|up to 30 integers
|List of friction values of the object vertices, each 1 to 100. (How frictional a vertex is with the landscape)
|-
|Value
|Integer
|How much the object can be sold/bought for.
|-
|Mass
|Integer
|Weight of the object. For reference, rock = 10, clonk = 50, hut = 1,000, castle = 10,000.
|-
|Components
|ID list
|Objects from which the object is composed. Uncompleted or half grown objects will only have the respective fraction of the components. (The template object is made of 1 rock and 1 wood).
|-
|Rotate
|Integer
|0 no rotation, 1 full rotation, 2-360 limited rotation.
|}
 
Okay! Now that we're done reading that, we'll need to change the object's ID to something unique. This can be exactly the same as the object's folder. For example:
<pre width=40>
<pre width=40>
[DefCore]
[DefCore]
id=MyObject
id=MyObject
Version=4,10,0,0
Version=5,2,0,1
...etc.
...etc.
</pre>
</pre>
Line 153: Line 89:


====Make it Bounce!====
====Make it Bounce!====
For this example, we'll make a secondary function that the Hit() function will call. While not quite necessary, this is a good way to become familiar with how functions work.
For this example, we'll make use of the variables given by the Hit callback. The Hit callback is a function called by the engine whenever an object strikes the ground with sufficient force.
 
Underneath the Hit function, start a new function called 'Bounce'. The syntax should look as such:
[[File:BounceFunction.png|border]]
 
Where the commented line is ( // ), remove that and add this function: 'SetYDir(-20);'. Under that line, add a  
'return 1;' to end the function. Now let's look back at the Hit() function. Remove the 'Explode()' function there. This time, write in: 'Bounce(GetYDir());'.
 
Now when the Hit() function is called, it will call the Bounce function, passing '-20' as the 'level' parameter. Test it out in game, see if it works.
 
 
Unfortunately, this bounce isn't very realistic. And further unfortunately, due to when the hit function is called we can't simply put 'SetYDir((GetYDir() * -1) / 2);' into the Hit Function for a quick and realistic bounce. This problem requires an effect to get the last vertical speed (ydir) before it hit the ground (which is now zero, causing no bounce to occur).
 
Make your script as such for a realistic bounce:
 
<pre>
local currentydir;
local lastydir;
 
protected func Initialize()
{
lastydir = 0;
currentydir = 0;
AddEffect("Bounce", this, 1,1,this);
}


The Hit function used in the previous example didn't make use of the variables which the Hit callback uses, so we'll have to add those into the script. Formerly the Hit function was written as such:
<pre width=40>
protected func Hit()
protected func Hit()
{
{
Sound("RockHit*");
    //
SetYDir((lastydir * -1) / 2);
return 1;
}
 
func FxBounceTimer(object target, int num, int timer)
{
lastydir = crntydir;
currentydir = GetYDir();
}
}
</pre>
</pre>


Here we are using some local variables for the object, and a timed effect. The FxBounceTimer function sets the 'lastydir' to the previous 'currentydir' and updates the 'currentydir' variable to the actual vertical speed at the current frame. Thus two variables are stored; last frame's vertical speed and the current frame's vertical speed.
Within the brackets, add "int xdir, int ydir". This will allow the Hit callback to receive the x speed and y speed of the object when it hit the ground. Now we can use these variables within the Hit function and manipulate the object's speed to simulate a bounce.


Now in the Hit() function, we can use the 'lastydir' variable. Test it in game, and watch your object bounce about. :]
To do this, a simple reversal of the ydir is enough. To set an object's y speed, we use the function "SetYDir()". The new speed we wish the object to have will be written inside the brackets (the first parameter). Of course, to reverse a value, all we have to do is multiply the number by negative one. There is another thing we need to pay attention to specific to the Hit function; the variables for xdir and ydir have a precision value of 100. Therefore, in the SetYDir function we must define that (the second parameter).


Remember, to quickly test objects use '/script GetCursor()->CreateContents(MyObject)', where 'MyObject' is the ID of your object.
The script should be written something like this:
 
<pre width=50>
'''Todo: Some more basic tuts'''
protected func Hit(int xdir, int ydir)
{
    SetYDir(ydir * -1, 100);
    return 1;
}</pre>

Latest revision as of 20:22, 5 October 2011

C4Script

C4Script is the C-like script-language used by OpenClonk. C4Script controls in-game objects; from the Clonk to the GUI, everything is programmed with C4Script.

The C4Script Reference Library is an online resource containing documentation of nearly all C4Script functions, as well as information on syntax and how to use many different features of the language.

As a side note, the name 'C4Script' comes from the first game it was used in, Clonk 4. Each following game in the series has vastly expanded on and improved the language since it's inception.

An Introduction to C4Script

Learning a new script language can be difficult, especially if you do not have any previous programming knowledge. This introduction will appeal to these users, as we do not expect any new developer to have a firm basis in C before starting. ;-)

Creating your First Object

Here we will cover the basic steps on creating a new object usable within OpenClonk.

Because creating each new object from scratch would be tedious, repetitive work, we provide a template object to work with.

Step 1

Copy the template into the root directory of OpenClonk (the folder containing your game executable), and rename it to something such as 'MyObject.ocd'. Now have a look inside your object's folder. There are a few things we'll need to change before it will load as your object, instead of over-riding the template.

The DefCore

Open the DefCore.txt file. You'll see something similar to this:

[DefCore]
id=TemplateObject
Version=5,2,0,1
Category=C4D_Object
Width=8
Height=8
Offset=-4,-4
Vertices=3
VertexX=0,2,-2
VertexY=1,-1,-1
VertexFriction=20,20,20
Value=1
Mass=10
Components=Rock=1;Wood=1;
Rotate=1

DefCores contain a fair amount of basic object data, but for now we only need to change the ID to something unique; for example:

[DefCore]
id=MyObject
Version=5,2,0,1
...etc.

Everything else in the DefCore is fine for our purposes, so let's have a look at the script.

The Script File

View of the script file.

The script file contains the object's 'code', or the 'programming' of the object. This is the real meat of custom objects.

If you use Windows, to edit Script files in a more user-friendly way it is suggested you use a program such as Notepad++ instead of the default text editor.


Have a look at the 'Hit()' function. Currently when the object hits the landscape, it makes a RockHit* sound. Let's make it explode instead. ;D

Delete the line containing the Sound function, and write 'Explode(30);' instead:

protected func Hit()
{
	Explode(30);
	return 1;
}

Also, make sure to modify the header for you object. Add the name, a description, and fill in the author! :]


Test your object!

Now it's time to try out your object in game. Run the game, and start a test scenario. Hit Ctrl+F5 to start Dev-mode, and type this in as a message (replace 'MyObject' with the ID of your object):

Your clonk should have the new object appear in his inventory. Throw it on the ground!

Other Fun Example Scripts for your Object

These examples will make you familiar with a few common script functions.

Make it Bounce!

For this example, we'll make use of the variables given by the Hit callback. The Hit callback is a function called by the engine whenever an object strikes the ground with sufficient force.

The Hit function used in the previous example didn't make use of the variables which the Hit callback uses, so we'll have to add those into the script. Formerly the Hit function was written as such:

protected func Hit()
{
    //
}

Within the brackets, add "int xdir, int ydir". This will allow the Hit callback to receive the x speed and y speed of the object when it hit the ground. Now we can use these variables within the Hit function and manipulate the object's speed to simulate a bounce.

To do this, a simple reversal of the ydir is enough. To set an object's y speed, we use the function "SetYDir()". The new speed we wish the object to have will be written inside the brackets (the first parameter). Of course, to reverse a value, all we have to do is multiply the number by negative one. There is another thing we need to pay attention to specific to the Hit function; the variables for xdir and ydir have a precision value of 100. Therefore, in the SetYDir function we must define that (the second parameter).

The script should be written something like this:

protected func Hit(int xdir, int ydir)
{
    SetYDir(ydir * -1, 100);
    return 1;
}