General > Features & Articles

Basic Development Tutorial for FOnline.

<< < (2/7) > >>

5. Creating a two map zone.

Step by step:

* Create second map and add it to the world.

* Launch the Mapper and open a cave map. Save it to a different name. (I used: q_tut1_in) (q for quest, tut1 for tutorial1, and in for inside)
* Launch the WorldEditor, Tools->Map Data Editor (Ctrl+M), Add New Map. Add q_tut1_in, and assign an ID similar to the previous one. (129 for me)
* Tools->Location Editor (Ctrl+L), find the tutorial location (mine had PID 90) and double click to edit it. Add the new map with PID 129 to it. Now it should have 2 maps.
* Save the World (Ctrl+S) and exit World Editor.
* Link the first map to the second one:

* Launch Mapper again and open the first map. (The one that will be accessed from the world map, I named it: q_tut1_out)
* Add some Ent (Entry point) elements, and set their "EntireNumber" to 0. This is where the player will spawn when he enters the area from the world map.
* Add a cave entrance, add the design elements, and add some Exit Grid (EG) element to the cave entrance. (They can be found at Tech panel)
* Edit the Exit Grid's values: set "ToEntire" to 0, while set "ToMapPid" to 129 (the PID of the second map, the cave)
* Now add some more Ent elements close to the cave entrance, and set the "EntireNumber" value to 1. This is where the player will spawn when he exits the cave.
* The first map is set, save it.
* Link the second map to the first:

* Load the second map (cave).
* Add some Ent elements near the cave entrance and set their "EntireNumber" to 0. Here will the player spawn when enters the cave.
* Fill the entrance of the cave with EG elements with values: set "ToEntire" to 1 and set "ToMapPid" to 128 (the PID of the first map, q_tut1_out in my case)
* Save the map and exit the Mapper.
* Try it out:

* Clean, delete world save files, and run the server.
* Your character should be able to enter and leave the cave at his leisure.
Here are my maps:

6. Adding monsters, loots and some basic (pre-written) scripts.

So, next in line is, adding some monsters to the map, with some basic script. We will not make scripts, only use some default ones.
The first thing you might notice, is that if you place a critter on the map, for example a Mole Rat, it will stay idle and do nothing, unless attacked. In order to make a Critter be agressive or semi-agressive, it will need some scripts. There are some good basic scripts in the Klamath map (Rats/Geckos), we will use those. (The are in the scripts files not in the map ofc, but you can access them by checking Klamath map with Mapper)

So, step by step:

* First things first, if you haven't, create a new bat file to lauch your server. It should delete all fosmapb from the maps, and launch server after. This way you will never run in circles trying to figure out, why things don't works, when the only problem was, that you forgot to clean, rebuild the maps and reload the world.
(In case you don't know how to make batch files, just make a new text file with the name CleanWorld.bat in the Server folder and add the following 3 lines to it:

* "del maps\q*.fomapb"
* "del save\world*.fo"
* "FOnlineServer.exe" This will delete ur current world save as well, so every progress your char had, except it's creation and location is lost.)
* Launch Mapper.
* Create a cave (or copy one, but remove useless "tech" objects so u don't accidentally get random monsters generated) and place some rats in it.
* Use the property editor (press F9 to toggle on/off) to set the mobs (I will refer to monsters/critters as mobs from now on) script to the following:

* set ScriptName to "mob" (This will tell which script file to check for the function below. Server\Scripts\mob.fos )
* set FuncName to "critter_init" (This is the function (script) to be called when creating this mob)

* Save the map and try it. Use your new batch file.
Adding some loot for the mobs.

* Select the mob (click on it, have details window turned on - F9)
* On the bottom panel select Norm, double click it and filter for ammo.(You target on the map still should be the rat.)
* Now Alt+Click on some shotgun shells.
* On the bottom panel select Inve, you should see the shotgun shells added. You can Alt+Click to remove them.
* To set the amount of the shells, just click on the shells and edit the Count to a differnt value than 0.
* Launch server and client, to try it out.
* Kill the mob for your reward: 1 shotgun shell ;)
The result should look like this in Mapper:

Adding agressive mobs usually does not fullfill all of the quest writers desires. So our next step is, to add some mobs, that do not move/attack, until they are triggered to do so. For this, we will also make a new dialog. The molerat will talk to the player, and the player will have some options how to engage it. The choise "I will exterminate you and all your vermints." will trigger all mobs who see the player to attack him, otherwise the player can leave peacefully or take on the molerat in a man versus rat duel.

Step by step:

* Launch Dialog Editor and create a new dialog.
* Make the dialog tree as the picture below shows.
* After saving it, make sure you edit the dialog list (Server\dialogs\dialog.lst)file and add to it the dialog you made, I used 2102 for dialog ID.
* Add the dialog ID to the Molerat Dialog property.
* Add some small rats around the Molerat and set their ScriptName to "mob" and FuncName to "_DontMove".
* Add some weapons to the entrance of the cave, so your character can survive the rat attack.
* Save map and try. Gl.Note: Use Demand or Result to add scripts to dialogs. The one we added, was in the script file named dialog and the scripts function name was r_Alert. We will do more complicated scripts later on, but if you want, feel free to study some of the script files.

7. More on dialogs - Tracking quest progress

The next important thing with dialogs is, to track a given quests progress. For this, we will need to create a game variable, track it through the dialog and through other actions of the player as well.

Step by step:

* Make a quest variable:

* Launch DialogEditor, use the Vars editor tabpage on the top.
* Enter a fitting name, (like "q_tut1" - q for quest, tut1 for tutorial1)
* Enter a unique number for Num, one that is not used, for easy access I used 3, but a number in higher range should be used.
* Set the radio box to Local, leave the checkboxes unchecked.
* Click Add.
* If it fails, this is how you can make it the harder way:

* Open for edit the variable text-file list in your server's script forlder: Server\scripts\_vars.fos
* Add the following lines at their respective places (use your unique Num, not mine which was 3):

* Add the header lines somewhere at the start of the text file, keeping the ordering by Num.

* #define LVAR_q_turo                        (3)
* Add the body lines somewhere where similar lines are, exact place depending on your Num:

*    $   3   1   q_turo   0   0   1000   0
* **********
*    TuRo progress.
* **********
* Create or modify your dialog to support the new quest variable:

* Add a new Dialog with an Aswer, which will end the dialog.
* To the Answer add a Result, which will set the new quest varialbe to 10.
* Add a new Answer to Predialogue Installations, which will lead to a dialog, that will be the progress of the quest.
* Add a Demand to this answer, that requires the quest variable to be 10.
This is how it looks at my end:

On the above picture, the tutorial robot will check if the quest varialble (q_turo_prog) is 10, which means that the player has reached a point in the conversation with the robot, where the robot will ask him, to gather some flint and use his fixboy to make a primitive tool.

On the above picture, the tutorial robot will ask the player to make a primitive tool and to mark the progress so far, will set the quest variable to 10, and exit the dialog. Next time when the player talks to the robot, it will jump to dialog 9 where the robot asks if the task is done. Here the robot checks if the player has a primitive tool on him, and will progress further if so.

This was only a part of the Tutor Robot quest, but enough to point out the example, how to progress using a quest variable. Ofc, other dialogues would lead to incrementing or setting back to quest variable to other values, and because of the Predialogue installation Answer Demands, the right dialog will be selected for the current progress of the quest.

8. Creating and using some basic scripts: Scenery scripts.

A quest complexity will usually require us to use scripts. At this point we will dive into one of the most simple scripts, the Scenery scripts, or scripts associated with scenery objects on the map. For this we will need a Scenery object on our map and a new script we want to call when the user interract with it.

Step by step:

* Create a new scriptfile:

* Create a new textfile named "quest_tut1.fos" in "Server\scripts\"
* Copy paste the content from the code part below.
* Open "Server\scripts\scripts.cfg" with notepad, find the "quest-specific" area, and add an extra line to include the new script in the build/bind process. ("@ server module quest_tut1")
* Bind the script file to the Scenery in Mapper:

* Launch Mapper and the load the map.
* If you haven't add a Scenery object to the map. (I used some defected robot.)
* Set the ScriptName value of the Scenery object to your script files name. (quest_tut1.fos)
* Set the FuncName value of the Scenery object to the function to be called when player interaction. (s_RefillRobot)
* Save the map and exit.
* Run the server to compile your script:

* To test if your script compiles error free, you can use: Server\scripts\compile.bat quest_tut1.fos
* Delete previous script file binaries of your modified script file if they exist. (quest_tut1.fosb, quest_tut1.fosp)

* Run the server.
* Understand the script:

* Study the script file, pretty straightforward, comments are useless but I left them there anyways.
* If the player tries to use the Repair Skill on the robot, it will say that he can't do that without Small Energy Cells.
* If the players tries to use the Science Skill on the robot, the system will say that the robot is out of energy.
* Finally, if the player tries to use Small Energy Cells on the robot, the system will notify about the success and set the quest variable to the desired value. This is how the quest is progressed in this case.
* Also one Small Energy Cell is removed from the backpack of the player.
* If the player tries to use the Repair or Science skills on the robot, the notification will tell, that it is already done. This is ensured by the quest variable chesk at the start.
--- Code: ---//  Includes some definitions
#include "_macros.fos"

//  Function signature for player interactions with Scenery objects
bool s_RefillRobot(Critter& player, Scenery& robot, int skill, Item@ item)
// Retrieve the variable used by the quest to mark it's progress, plus error handling
GameVar@ questVar = GetLocalVar(LVAR_q_turo_prog, player.Id);
// is quest still in progress and before repairing the robot
if (questVar < 30)
//  Check if repair skill is used on the robot
if(skill == SK_REPAIR)
player.Say(SAY_NETMSG, "You don't think it can be done without some small energy cells.");
return true;
// Check if science skill is used on the robot
if(skill == SK_SCIENCE)
player.Say(SAY_NETMSG, "The robot is running very low on energy.");
return true;
// Check if the player used a Small Energy Cell on the robot.
if(item.GetProtoId() == PID_SMALL_ENERGY_CELL)
player.Say(SAY_NETMSG, "You replace one of the energy cells of the robot.");
// Set the quest progress
questVar = 30;
// Remove the Small Energy Cells used.
item.SetCount(item.GetCount() - 1);
return true;
if(skill == SK_REPAIR || skill == SK_SCIENCE)
player.Say(SAY_NETMSG, "You already replaced the energy source of this robot, there is nothing more you can do here.");
return true;
return false;

--- End code ---

9. Creating new quest location from dialog.

After receiving a quest from an NPC, the NPC might in some cases mark a location on the player's map. This location will be known only to the player, and a red dot on the world map will appear. Once the player finished the quest (talks with the questgiver and succedes), the location will disappear.

Step by step:

* Create map data and location:

* Open World Editor
* Press Ctrl+M (Tools->Mapdata Editor) and Add New Map:

* Set a name for the map data (I used: q_generated)
* Set a unique ID (130).
* Set the filename of the map you want to use. You probably need to make a new map with Mapper for this purpose, but for demonstration existing ones can be used.(q_tut1_out)
* Save.
* Press Ctrl+L (Tools->Location Editor) and Add New Location:

* Set a name for the location. (q_tut1_loc)
* Set a unique Id. (91)
* Add the previously made mapdata to it. (q_generated)
* Save.
* Save the World and exit.
* Create the script:

* Create a file with the contents given below in the source tags and save it.(Server\scripts\quest_generateMap.fos)
* Open "Server\scripts\scripts.cfg" with notepad, find the "quest-specific" area, and add an extra line to include the new script in the build/bind process. ("@ server module quest_generateMap")
* Try out if the script compiles: Server\scripts\compile.bat quest_generateMap.fos
* Create the dialog:

* First you need to create a local variable (local if you set it on player, unique if u set it on NPC) to store the location ID which will be generated, so you can delete after it's not needed.(Recycling is important if you want to keep your server up for more than a few hours.)

* Edit "Server\scripts\_vars.fos".
* Add the header line to it's repsective place (use unique number, I used 4):

* #define LVAR_q_gen_loc                     (4)
* Add the body lines to their respective places:

*    $   4   1   q_gen_loc   0   0   1000   0
* **********
*    Generated location progress.
* **********
* Create the dialog to look like on the below picture. (this is for demonstration purposes only)
* On one of the answer you will have to add a Result, which will call the script function to create the map location.
* When completing the quest, don't forget to call the script function which will delete the map location.
* Do a clean on scripts as well, delete world save and launch server, client to try it out.
Here is the basic dialog, it's crude but only for demonstration of usage:

Here is the script that will spawn a location on the map and will delete it afterwards when triggered.

--- Code: ---#include "utils_h.fos"
#include "worldmap_h.fos"
#include "npc_planes_h.fos"
#include "entire.fos"
#include "_colors.fos"
// function called as request from dialog to spawn quest location
void r_SpawnLoc(Critter& player, Critter@ npc)
// roll X,Y value of WM (World Map) zone index, in this case from 3x2 zones area near Hub
uint zoneX = Random(28, 31);   
uint zoneY = Random(39, 40);   

// get X,Y value of quest location position on WM in zone we picked above
uint   wx = zoneX * __GlobalMapZoneLength;          //get zone X,Y start value
uint   wy = zoneY * __GlobalMapZoneLength;
wx += Random(0, __GlobalMapZoneLength);             //add random value from 0 to zone size
wy += Random(0, __GlobalMapZoneLength);

// you can add more map locations here, and select one randomly
array<uint16> locationIds = { 91 };
uint num = locationIds.length;

// pick random encounter map, if only one map, then only one will be selected
uint16        locPid = locationIds[Random(0, num - 1)];

// create quest location
Critter@[] crits = { player };
int           loc = CreateLocation(locPid, wx, wy, crits);
if(loc == 0)
// makes the location visible to the player
player.SetKnownLoc(true, loc);

// change location color on World Map
Location@ location = GetLocation(loc);
location.Color = COLOR_RED;

// set TB combat mode if needed

// set location id to quest lvar (used when you need to delete location)
GameVar@  locidv = GetLocalVar(LVAR_q_gen_locid, player.Id);
locidv = loc;

// player can die and come back, but we will have to delete the location later
location.AutoGarbage = false;
// dialog function used in request to delete quest location (after player report finishing the quest)
void r_DeleteLoc(Critter& player, Critter@ npc)
GameVar@ var = GetLocalVar(LVAR_q_gen_locid, player.Id);

--- End code ---


[0] Message Index

[#] Next page

[*] Previous page

Go to full version