How to Create a Settlement Scenario
NOT YET FINISHED
Welcome to this guide on how to create a Settlement scenario!
This is a follow-up tutorial, so all knowledge and progress from the previous guide is required.
In the last tutorial, you learned how to create a basic scenario with a map and how to add objects to the map. However, a few more things are required for a complete settlement scenario:
Goals, rules, base material like shovels and axes, etc. - all these things are set in the script.
Script? But I have no idea of programming! :(
Don't worry, you don't need to be a C++ expert to get things working. OpenClonk features an easy-to-learn scripting language called C4Script. Here is a short overview. Typically, the best way to get into scripting is looking at scripts from other objects and scenarios and finding out what they do. There is also an extensive documentation I will often link to in this tutorial.
And even if you have no idea of C4Script, this guide will give you templates and code snippets you can use and easily customise to fit your needs.
Preparations
Expand your scenario and open the scenario script (docs), a file called "Script.c". It should look similar to this:
Everything between /* and */ is a comment, highlighted in red by the Eclipse text editor. It will be ignored by the engine when executing the code. You can write a short description of your scenario below the name like I did. Next we have this:
func Initialize()
{
CreateEnvironment();
}
It is a function (keyword func) called Initialize. Everything between the curly brackets is executed when the function is called. (More about functions). It calls the function CreateEnvironment which is declared below and is empty as you can see in the screenshot. Delete both the call CreateEnvironment(); and the function below, so we are left with an empty Initialize function.
Goals
First you'll need to decide which goal(s) you want to have for your scenario. Inside Eclipse, you can scroll down, expand "Objects.ocd" and then "Goals.ocd" to see all goals currently in the game. In the screenshot, I highlighted the ones which work with settlement scenarios, I will go through all of them.
Wealth
This one's very easy to set up, just paste the following code into your Initialize function:
var goal = CreateObject(Goal_Wealth);
goal -> SetWealthGoal(XYXY);
Replace XYXY with the wealth the player should achieve to win.
Resource Extraction
The goal is to mine all of a specific resource. Paste the following code into the Initialize function:
var goal = CreateObject(Goal_ResourceExtraction);
goal -> SetResource("XYXY");
Replace XYXY with the name of the ressource to extract, for example: SetRessource("Granite"); or SetRessource("Gold");
Expansion
A certain amount of the map must be claimed by constructing flags. Paste the following code into your Initialize function:
var goal = CreateObject(Goal_Expansion);
goal -> SetExpansionGoal(XYXY);
Replace XYXY with the area to be covered in promillage of the total map. So for covering half the map, it would be SetExpansionGoal(500);
Rules
Rules restrict or allow something. As well as for the goals, you can look them up in the objects browser. Adding rules is easy: Copy the following piece of code into your Initialize function:
CreateObject(XYXY, 0, 0, NO_OWNER);
where "XYXY" is replaced by the ID of the rule. The ID is the unique identifier every object has, like it's internal name. To find out the ID of an object, expand it and open the file "DefCore.txt". In the second line, it says id=XYXY, that's the ID. If you want multiple rules, just copy the snippet and insert another ID. Note: You don't need to have rules, Goldrush, a standard settlement scenario, has no rules set.
This is what my Initialize function looks like after adding two goals and two rules.
Start Position and Equipment
There is another important function: InitializePlayer. While Initalize is used to set up goals, rules, place objects, etc. (so gameworld-related things), InitializePlayer is for player-related stuff, like start position, base materials, or view range.
Preparations
Leave out one line after the closing curly bracket of the Initialize function and add this empty function below:
func InitializePlayer(int plr)
{
}
Right now not much is happening, put the following code into the newly created function:
var clonk;
for(var index = 0; clonk = GetCrew(plr, index); ++index)
{
}
That may look quite complicated, but it's basically a loop (a for loop, to be precise) which runs through all the crew members. What we write into that loop (again between the curly braces) will be executed for every crew member (the variable "clonk") the player gets at the beginning of the scenario. The variable "index" is the index of the respective clonk, starting from 0 and then counting up until no more crew member is found, then the loop will end.
Start Position
Note: If you want the player to spawn at a random position, you can leave this out.
First you'll need to find out the coordinates of the position at which you want the players to get spawned. OpenClonk uses a 2D coordinate system, point 0X,0Y is the upper left corner. The X axis goes right, the Y axis goes down. One unit corresponds to 1 pixel ingame. To find out the coordinates, you need to start your scenario in editor mode and select the editing cursor. Then move the cursor to your desired start point (the center of the clonk will be at this position, so don't set it too close to the ground or the clonk will stuck) and read the coordinates in the lower left corner of the engine window. Keep them in mind, you will need them shortly. Now copy this code into your loop:
clonk -> SetPosition(X, Y);
And replace X and Y with your coordinates.
Equipment
The command we need for placing something in a clonks inventory is CreateContents. It needs two arguments, ID and count of the object to be created (If count is not given, the default amount of 1 will be used). So if we wanted to give every crew member a shovel and a hammer, it would look like this:
var clonk;
for(var index = 0; clonk = GetCrew(plr, index); ++index)
{
clonk -> CreateContents(Shovel);
clonk -> CreateContents(Hammer);
}
But we don't want the same equipment for every crew member, we want the first one to have shovel and hammer, the second one shovel and axe. How to do this? Using an if condition and else! Basically, you enter a condition inside the parentheses and if it returns true, the following command or code block will be executed. If it returns false, else will be executed. We have the variable index from the for loop which indicates the number of the current crew member. Let's use this and say: If it is the first crew member (index = 0), give it shovel and hammer, else give it shovel and axe. It looks like that:
Note that you can not only put the CreateContents commands into the if block, but also other things. You could for example let one crew member spawn at the left side of an abyss and the other one on the right side!
View Range
You may want to limit the zoom range so the player can't zoom out the whole map. This is also done in the InitializePlayer function, but it isn't applied to individual clonks, but to the player. As our for loop runs through all crew members, we don't write the following code into it, but outside of it below. We need two commands, SetPlayerZoomByViewRange and SetPlayerViewLock. First we will limit the zoom range so the player cannot some out farther than 500 pixels:
SetPlayerZoomByViewRange(plr, 500, nil, PLRZOOM_LimitMax);
(The data type nil can be used to leave out a parameter.) Then we will lock his view so he can't scroll around to explore the map:
SetPlayerViewLock(plr, true);
// Some natural disasters, earthquakes, volcanos, meteorites. Meteor->SetChance(15); Earthquake->SetChance(2); Volcano->SetChance(4); Volcano->SetMaterial("DuroLava");
Addendum - Components of .ocs files
This is an overview of all the files a Scenario.ocs can contain. [img]http://img705.imageshack.us/img705/7878/confusingfiles.png[/img]
[b]Material.ocg[/b] Contains material-texture combinations. Don't change it, otherwise you will get a [tt]FATAL ERROR: Error loading materials.[/tt] and the game won't start. If that happens, just delete the file, it will be recreated.
[b]Script.c[/b] Contains the scenario script.
[b]Game.txt[/b] Contains information about every object that has been saved and will be created on scenario startup. These are informations like position, size, category, flags, properties, etc. Don't touch it and everything will be fine.
[b]Landscape.txt[/b] As mentioned before this file contains code to dynamically create a map. You can create complex landscapes that look different every game. Have a look at it: [url=http://docs.openclonk.org/en/sdk/scenario/MapCreatorS2.html]More information.[/url] [url=http://www.cc.striver.net/texts.php?action=sh&id=13]German tutorial.[/url] Not needed if you are manually painting a map.
[b]Scenario.txt[/b] Contains general scenario settings. These are some of the most important ones:
[i]MinPlayer/MaxPlayer[/i] Sets the minimum and maximum number of players to play this scenario. You could for example only make it playable with 2 to 4 players using [tt]MinPlayer=2[/tt] and [tt]MaxPlayer=4[/tt].
[i]MapWidth/MapHeight[/i] Specifies the map size. [b]Note:[/b] Doesn't work if there already is a Map.bmp file. Use the method explained below to change the size of a painted map afterwards: Painting with an external program.
[i]MapZoom[/i] Something between 5 and 15. The factor the Map.bmp file is zoomed by for the actual gameworld. So if you have a 300x100 bitmap file and MapZoom=15, the ingame landscape will be 4500x1500 pixels big.
[i]BottomOpen/TopOpen[/i] If 1, objects and Clonks can fall out of the map.
For all options, see [url=http://docs.openclonk.org/en/sdk/scenario/scenario.html]Scenario.txt.[/url]
[b]Teams.txt[/b] (See [url=http://docs.openclonk.org/en/sdk/scenario/Teams.html]docs[/url]) Used to define Teams. I will do another tutorial on that later.
[b]Title.txt[/b] Contains the scenario titel which is shown in the frontend. DE: is the German titel and US: the English one.
[b]Title.png[/b] The title graphic which will be shown alongside the description in the frontend. Has to have an aspect ratio of 4:3, preferably 640x480. Here is an article about how to design a good title graphics
[b]Map.bmp[/b] The static map is saved into this bitmap. The colours do not necessarily correspond with the actual materials, so don't worry if it is pink and green. :) You can edit it with an external program, that way it is possible to change the map dimensions even after already having painted something. (Scale canvas) [b]Attention Windows 7 users:[/b] The "Paint" program shipped by default can't handle OpenClonks colour palette properly and will break your map! Use another program like [url=http://www.softpedia.com/get/Multimedia/Graphic/Graphic-Editors/Paint-XP.shtml]Paint XP[/url].
[img]http://img547.imageshack.us/img547/6122/crasha.png[/img] [i]A typical Map.bmp (Crash landing)[/i]
The easiest way to get the materials right is to paint all the materials you want into the map in the engine, and then open the Map.bmp and use the Colour Picker tool to copy a material colour. [url=http://www.cc.striver.net/texts.php?action=sh&id=7]Here[/url] is an extensive tutorial about materials. (German only D: | outdated D;)
[b]DescDE.rtf/DescUS.rtf[/b] Contain the description in the respective language. Don't forget to write a description before releasing your work. :)