fodev.net

General => Features & Articles => Topic started by: Slowhand on August 01, 2015, 06:21:31 pm

Title: Basic Development Tutorial for FOnline.
Post by: Slowhand on August 01, 2015, 06:21:31 pm
This is a brief development tutorial for developing FOnline. In the tutorial I use the FOnline: Reloaded version of the SDK, but it should be fully compatible with the original SDK.
(Note: As we found out, everything is not compatible, especially scripts. If you plan to follow this tutorial, make it easier on yourself and use the Reloaded version, see first step for install instructions)

Another copy of this tutorial can be found at FOnline: Reloaded (http://forum.fonline-reloaded.net/index.php?topic=8543.msg64921#msg64921) but I belive you need to log into the forums to be able to see it.

Basic Development Tutorial for FOnline.
Contents:

To do list:
Title: 1. Downloading and setting up the Development Kit. (FOnline: Reloaded)
Post by: Slowhand on August 01, 2015, 06:23:53 pm
1. Downloading and setting up the Development Kit.

Title: 2. Modifying existing maps with the Mapper.
Post by: Slowhand on August 01, 2015, 06:26:23 pm
2. Modifying existing maps with the Mapper.

Another easy step, is to modify and existing map and check the effects.
Title: 3. Adding new locations to the world, using the World editor.
Post by: Slowhand on August 01, 2015, 06:44:23 pm
3. Adding new locations to the world, using the World editor.

This isn't hard as well, but here u can mess things up pretty easy if you click around while experimenting.

Now, time to place this map on the world.
Test what you have done. Make sure you delete the World saves, start server, launch client and with a new char you should see the new tutorial location nearby.
Title: 4. Adding dialogues for NPC's
Post by: Slowhand on August 01, 2015, 06:54:55 pm
4. Adding dialogues for NPC's

Okay, let's continue, developing our newbie tutorial. This robot shall give usefull information for newbies who never played any FOnline games and are used to the original Fallout1/2/3/New Vegas etc games. So, our robot shall teach the newbies how to be self sufficient, how to gather resources, harvest, make tents etc. Ofc if they want to. It should introduce the old quality of questing/talking to NPC's where the NPC reacted to the Players stats, actions etc.

Step by step:

I made a little bit more complex dialog for my robot, feel free to understand it and try it. Basically the robot detect the players Intellect and greets him accordingly. The player can gather some extra information if he has high perception. The successfull scenario ends in the robot giving the player a task to gather him flint, so the robot can teach him how to craft a tool.

Here is how it looks. (click on images for normal size)

(https://i.imgur.com/Adj06h3.png?1)
Title: 5. Creating a two map zone.
Post by: Slowhand on August 01, 2015, 07:11:52 pm
5. Creating a two map zone.

Step by step:

Here are my maps:

(https://i.imgur.com/C3NzxeW.png?1)

(https://i.imgur.com/xd4TsMc.png?1)
Title: 6. Adding monsters, loots and some basic (pre-written) scripts.
Post by: Slowhand on August 01, 2015, 07:54:22 pm
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:

Adding some loot for the mobs.

The result should look like this in Mapper:

(https://i.imgur.com/TwOQ2hg.png)

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:
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.

(https://i.imgur.com/rFTJKvp.png)
Title: 7. More on dialogs - Tracking quest progress.
Post by: Slowhand on August 01, 2015, 09:28:13 pm
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:

This is how it looks at my end:

(https://i.imgur.com/Tx7crIG.png)

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.


(https://i.imgur.com/6J30TpE.png)

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.
Title: 8. Creating and using some basic scripts: Scenery scripts.
Post by: Slowhand on August 04, 2015, 11:23:44 pm
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:
Code: [Select]
//  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);
if(valid(questVar))
{
// 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(valid(item))
{
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);
item.Update();
return true;
}
}
}
else
{
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;
}
Title: 9. Creating new quest location from dialog.
Post by: Slowhand on August 07, 2015, 04:21:07 pm
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:

Here is the basic dialog, it's crude but only for demonstration of usage:

(https://i.imgur.com/wKpB9DX.png)

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

Code: [Select]
#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)
return;
// 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;
location.Update();

// set TB combat mode if needed
if(player.Mode[MODE_DEFAULT_COMBAT] == COMBAT_MODE_TURN_BASED)
{
SetTurnBasedAvailability(location);
}

// 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);
DeleteLocation(var.GetValue());
}
Title: 10. Accessing a private location from a public location scenery. (Ladder)
Post by: Slowhand on August 07, 2015, 10:31:49 pm
Coming soonish..

I did not solve this yet, but it seems that map_bosbunker.fos has some nice example, how to make the script for a map, so that the player has to attach a rope to an elevator shaft and climb down on it.

The map for it is, q_bos_oldbunker_level2.fomap, here the elevator shaft does not have a rope attached, but the script "map_bosbunker@s_Shaft" is set up.
Title: 11. Setting up the scripting environment.
Post by: Slowhand on August 10, 2015, 02:25:48 am
11. Setting up the scripting environment.

Scripting from notepad after second day, is no fun. Before touching more of the scripting topics, our first task is to set up a scripting environment, which helps and speeds up our work. We will configure an IDE (Interactive Development Environment) for this, which wil replace the text editor we used to write and read scripts. There are many freee IDE's out there, I tried a few, and here are the results:


Step by step - Configuring Code Blocks for scripting FOnline: Reloaded

This is how my IDE looks like when scripting:

(https://i.imgur.com/yhKtusi.png)
Title: 12. Understanding a full quest script. (LA Boneyard dog quest)
Post by: Slowhand on August 11, 2015, 04:44:04 am
12. Understanding a full quest script. (LA Boneyard dog quest)


Before writing scripts, understanding a few of them could come handy. The repeatable Boneyard dogs quest is perfect for this. It includes new location spawning from script, adding mobs to it and some triggers to run when the quest objective is fulfilled.

I will try to go very detailed on this one, pointing at every feature, or good to know stuff. This might be a bit too basic level, but maybe someone needs it. Having a little bit of C/C++ or any programming experience helps a lot here, but I will assume that you have none. This will be a very long trip, if you get lost, just skip, practice a bit using the previous or next material and come back later.

Very basic general (with examples of  programming info for those who are not proficient with it, or tried to understand the scripts but failed. If you are proficient in proramming head down to1 3. Navigation in the source code for FOnline development specific info.


Here is the script file, with included comments to explain. Copy it and open with Codeblocks.

Code: [Select]
/**< Credits and description */
//
// FOnline: 2238
// Rotators
//
// quest_la_dogs.fos
//

/**< These are includes. They tell the compiler where to look after code not defined in this file. */
#include "quest_killmobs_h.fos"
#include "worldmap_h.fos"
#include "utils_h.fos"
#include "npc_planes_h.fos"
#include "entire.fos"

/**< Same as include, I don't know why this is separated from the other includes. This line includes only one function, not all of them. */
import uint GetZonesWithFlag(uint flag, array<IZone@>@ zones) from "worldmap";

/**< Definitions to help to understand and use the code easier. */
#define ALL_KILLED            (2)

#define IDLE_NORMAL           (3000)
#define DIALOG                (9471)
#define PID                   (82)
// the time after dog group is added to the zone it's been removed from
#define GROUP_RESPAWN_TIME    (REAL_HOUR(Random(20, 30)))

// check if there is some group of dog roaming on the worldmap near LA
/**< Checks the map for roaming dogs. It's use has be shortcut to always return true, that is probably to optimize?. Useless currently.*/
bool d_CheckDogs(Critter& player, Critter@ npc)
{
    return true;
    /*IZone@[] zones;
       uint num = GetZonesWithFlag(FLAG_LA_Surroundings, zones);
       for(uint i = 0; i < num; i++)
            if(zones[i].GetBaseQuantity(GROUP_Dog) > 0) return true;
       return false;*/
}

/**< Opposite of checkdogs, always returns false. Useless currently. */
bool d_NoDogs(Critter& player, Critter@ npc)
{
    return !d_CheckDogs(player, npc);
}

/**< Spawns the location, sets up the critters, events, timers, initializes everything */
void r_SpawnLoc(Critter& player, Critter@ npc)
{
    /**< Get collection of zones near LA Boneyard. */
    array<IZone@> zones;
    uint num = GetZonesWithFlag(FLAG_LA_Surroundings, zones);
    array<IZone@> dogzones;
    /**< Cycle through the zones around LA Boneyard and add the zones that contain dogs to another collection called dogzones */
    for(uint i = 0; i < num; i++)
        if(zones[i].GetBaseQuantity(GROUP_Dog) > 0)
            dogzones.insertLast(zones[i]);
    /**< If no zones with dogs in it found, exit without spawning location.*/
    if(dogzones.length() == 0)
        return;

    /**< Get a random zone from the dogzones. */
    IZone@ zone = random_from_array(dogzones);

    /**< Generate random World Map coordinates. */
    uint   wx = zone.GetX() * __GlobalMapZoneLength;
    uint   wy = zone.GetY() * __GlobalMapZoneLength;
    wx += Random(0, __GlobalMapZoneLength);
    wy += Random(0, __GlobalMapZoneLength);

    /**< Select a random location on the World Map zone. (square)*/
    array<uint16> pids;
    num = zone.GetLocationPids(pids);
    uint16        locPid = pids[Random(0, num - 1)];

    /**< Create the location, add the player */
    Critter@[] crits = { player };
    int           loc = CreateLocation(locPid, wx, wy, crits);
    if(loc == 0)
        return;

    /**< Make the location visible for the player */
    player.SetKnownLoc(true, loc);

    /**< Get the game variable q_la_dogs_locid and store the location id associated with the players quest. */
    GameVar@  locidv = GetLocalVar(LVAR_q_la_dogs_locid, player.Id);

    /**< GameVar is a handle to the _la_dogs_locid game variable, it's value will be stored there when this function terminates. */
    locidv = loc;

    /**< Get the location, allow turn based mode in it, and disable auto garbage, this way the player can revisit the map. */
    Location@ location = GetLocation(loc);
    if(player.Mode[MODE_DEFAULT_COMBAT] == COMBAT_MODE_TURN_BASED)
        SetTurnBasedAvailability(location);
    location.AutoGarbage = false;

    /**< Get the maps of the location and initialize them with default values. */
    array<Map@> maps;
    uint        mapcount = location.GetMaps(maps);
    for(uint c = 0; c < mapcount; c++)
    {
        maps[c].SetScript(null);
        maps[c].SetEvent(MAP_EVENT_IN_CRITTER, null);
        maps[c].SetEvent(MAP_EVENT_CRITTER_DEAD, null);
    }

    /**< Set the player to be the owner of the first map of the location. */
    Map@ map = GetLocation(loc).GetMapByIndex(0);
    SetOwnerId(map, player.Id);
    /**< Repeat until dogs are spawned successfully on the map. */
    // spawn dogz
    bool spawned = false;
    while(!spawned)
    {
        array<Entire> entires;
        ParseEntires(map, entires, 0);

        /**< Get a random Entire to spawn the player to, when he enters the map. */
        Entire@ ent = random_from_array(entires);

        /**< Get a hex position at a random angle and distance from the player to spawn the dogs to. */
        uint16 hx = ent.HexX;
        uint16 hy = ent.HexY;
        map.GetHexCoord(ent.HexX, ent.HexY, hx, hy, Random(0, 359), Random(10, 40));
        for(uint i = 0, j = Random(7, 12); i < j; i++)
        {
            int[] params =
            {
                ST_DIALOG_ID, DIALOG
            };

            /**< Creates a dog and adds it to the map. Assignes critter_init function to dogs, explained below, at definition.*/
            Critter@ doggie = map.AddNpc(PID, hx, hy, Random(0, 5), params, null, "quest_la_dogs@critter_init");

            /**< If creating and adding at least one dog to the map succeded, then the main cycle stops. */
            if(valid(doggie))
            {
                spawned = true;
            }
        }
    }

    /**< Makes sure the location is salvaged after 12 hours, if the player does not finish quest until then.
        It will also set q_la_dogs variable to 3 (need to check dialog tree, probably reseting quest) */
    SetQuestGarbager(12 * 60, player.Id, loc, LVAR_q_la_dogs, 3);
}

/**< Deletes the location the player killed the dogs at. */
void r_DeleteLoc(Critter& player, Critter@ npc)
{
    GameVar@ var = GetLocalVar(LVAR_q_la_dogs_locid, player.Id);
    DeleteLocation(var.GetValue());
}

/**< Critters need an initialization function to be functional, well, this is it. */
void critter_init(Critter& cr, bool firstTime)
{
    /**< Disables replication for killed dogs. */
    cr.StatBase[ST_REPLICATION_TIME] = REPLICATION_DELETE;
    /**< A bunch of event handler: each will set the function to be called when the event happens. */
    cr.SetEvent(CRITTER_EVENT_DEAD, "_DogDead");
    cr.SetEvent(CRITTER_EVENT_ATTACKED, "_DogAttacked");
    cr.SetEvent(CRITTER_EVENT_MESSAGE, "_DogOnMessage");
    cr.SetEvent(CRITTER_EVENT_IDLE, "_DogIdle");
    cr.SetEvent(CRITTER_EVENT_SHOW_CRITTER, "_DogShowCritter");

    /**< I don't understand what this does, if someone finds out, please tell me as well. */
    _CritSetExtMode(cr, MODE_EXT_MOB);
}

/**< Function to run when mob is idle. It move from time to time, but only a few hexes.*/
void _DogIdle(Critter& mob)
{
    MobIdle(mob);
}

/**< This is called when a new critter is in sight of the dog. */
void _DogShowCritter(Critter& mob, Critter& showCrit)
{
    /**< If the seen creature is not the same type, it will attack it. */
    MobShowCritter(mob, showCrit);
}

/**< Checks if all dogs are dead on the map. */
void _DogDead(Critter& cr, Critter@ killer)
{
    uint16[] pids = { cr.GetProtoId() };
    Map@ map = cr.GetMap();
    if(MobsDead(map, pids))
    {
        GameVar@ var = GetLocalVar(LVAR_q_la_dogs, GetOwnerId(map));
        var = ALL_KILLED;

        /**< These parts have been severed by someone, it seems that some useless code remained. */
        // remove one dog group from given zone
        IZone@ zone = GetZone(cr.WorldX, cr.WorldY);
        // zone.ChangeQuantity(GROUP_Dog, -1);
        // spawn event to restore the doggie
        uint[] values = { cr.WorldX, cr.WorldY };
        CreateTimeEvent(AFTER(GROUP_RESPAWN_TIME), "e_SpawnDogGroup", values, true);
    }
}

/**< Useless code, it was used for extra reality, but someone changed the core part. */
uint e_SpawnDogGroup(array<uint>@ values)
{
    IZone@ zone = GetZone(values[0], values[1]);
    // zone.ChangeQuantity(GROUP_Dog, 1);
    return 0;
}

/**< How dog handles when it is attacked. It will send a message on the map to everyone that he is attacked including itself. (Yeah, I know, lol) */
bool _DogAttacked(Critter& cr, Critter& attacker)
{
    return MobAttacked(cr, attacker);
}

/**< If the message is that a dog is attacked, it will attack the attacker. */
void _DogOnMessage(Critter& cr, Critter& fromCr, int message, int value)
{
    MobOnMessage(cr, fromCr, message, value);
}

I have described how to look after specification from the FOnline API and how to find definitions using codeblocks. Use these to navigate throw the code I copied it. It will contain most of the important stuff in comments.

Also, try to make as much as you can out on your own, the code seems to be correct, except at the parts I commented otherwise. I left in the old comments as well, the new ones start like this: "/**<".

The biggest dificulty this script and others presents is that many things are passes through an ID, a numeric value to identify and entity, or message type, etc. Once you get used to it, and you should if you want to write scripts, understanding scripts will go fast and easy. :)
Title: 13. A simple kill target critter quest.
Post by: Slowhand on August 19, 2015, 04:48:42 am
13. A simple kill target critter quest.

Title: 14. Using the "Say" menu from dialogues. (Riddle mini quest.)
Post by: Slowhand on August 20, 2015, 04:45:28 pm
14. Using the "Say" menu from dialogues. (Riddle mini quest.)

It is quite simple actually, all you need to do, is at a dialogue you created, link the function to call at the dialogue, instead of results or demands like before. The signature will change to the following: uint dlg_Name(Critter& player, Critter@ npc, string@ say).

When the client accesses the node which you linked the say-script, it will run the script immediately, will not wait for the client to press "Say", so the first line of the code needs to be something that checks if the user entered something using say. (check code example for it)

The return value of the script function will tell which dialogue node to access next. 0 stands for the same dialogue node, running the script again, -1 stands for exiting the dialogue, and different positive values will try to find and access a dialogue node with that number. In our example, that was the 4.

Here is the code, using the previous tutorials, try to install it, do not forget to add the script to the script lists, the dialogue you created to the dialogue scripts and linking the NPC dialog ID to the ID's you gave to your dialogue at _dialogs.fos.

Script file: tut_say_dialogue.fos (http://pastebin.com/EKndgvPJ)
Dialogue file: tut_say_dialogue.fodlg (http://pastebin.com/hpmtiFLP)

This is how my dialogue file looks like, showing where to add/edit the script functions called (left click on node 3):

(https://i.imgur.com/vse7NkL.png)
Title: 15. Modifying base mechanics - Only the easy parts.
Post by: Slowhand on August 20, 2015, 05:39:56 pm
15. Modifying base mechanics - Only the easy parts.

-to be edited later-

Title: 15.1 Modifying lock pick cooldown mechanic.
Post by: Slowhand on August 20, 2015, 06:26:28 pm
15.1 Modifying lock pick cooldown mechanic.

(Using Reloaded SDK source, version 2.)

This will be an example, how to spice up lock picking mechanic a bit, changing the value of cooldown from a static, to a dynamic value based on the player skill, tools used, lock difficulty and the random roll.


The script file of interest is "lockers.fos". Generally the usage of skills is defined in "main.fos", but this one there is empty.

I do not know how to explain this minor change in basic tutorial level, here is what the old code did:

The new mechanic:

Points of interest:

1. If you didn't so far, make sure you understand the CLAMP(x, min, max) macro:

What it does, is makes sure that a value is between boundaries, like the value of CLAMP(x, 1, 95) will be "x" if that is between 1 and 95, else if "x" is higher than 95, then the value will be 95 or if "x" is lower than 1 the value will be 1. The CLAMP macro is defined using the ternary operator "?:" (actually two of them embedded in each other), which has the following formula: "logical condition ? value_if_true : value_if_false", meaning that if the condition is true, the first value will be returned, else the last. It might be a bit confusing, because of the excessive usage of this operator, but you'll get used to it.

2. Random(x, y) function:

This will generate a random number between two values, the numbers are decimal. Most common use case is: int roll =Random(0, 100); In this case the "roll" variable will be used somewhere against a skill, critical or to hit check.

3. LOCKPICK_TIMEOUT(cr):

This a macro, it's a leftover of some old code, and it has been left there to note the old structure of the code. It is still used, but it is overridden to a static value, which makes the extra "cr" parameter useless. I keep using it and let the owner of the server who use this tutorial code to dispose of it if they want to. Basically, instead of this macro we could have used simply a value.

4. REAL_SECOND(s):

The LOCKPICK_TIMEOUT macro refers to this, and what this macro does transforms real time value into game value, hence the name "real".

5. Locker's parameters:

Lockers as simply Items, you can find a lot in mapper under container, and have 3 parameters regarding locking, which you can modify also in mapper.


The new code fragment to replace the old parts with in the script file: lockers.fos (http://pastebin.com/v26Qz8Db)

Simply replace the old part with the new part, I did not copy the whole file into pastebin, but left enough context ( a few extra lines) and comments, so you can find where to copy paste from.
Title: ??
Post by: Slowhand on December 15, 2015, 01:39:56 am
- to do later -
Title: 1
Post by: Slowhand on December 15, 2015, 01:41:32 am
1
Title: 1
Post by: Slowhand on December 16, 2015, 08:04:47 am
1
Title: 1
Post by: Slowhand on December 16, 2015, 08:08:26 am
1
Title: 1
Post by: Slowhand on December 16, 2015, 08:11:12 am
1
Title: 1
Post by: Slowhand on December 16, 2015, 08:12:36 am
1
Title: 1
Post by: Slowhand on December 16, 2015, 08:13:44 am
1
Title: 1
Post by: Slowhand on December 16, 2015, 08:15:24 am
1
Title: 1
Post by: Slowhand on December 16, 2015, 08:18:44 am
1
Title: 1
Post by: Slowhand on December 16, 2015, 08:22:26 am
1
Title: a
Post by: Slowhand on December 16, 2015, 08:23:31 am
a
Title: Re: Basic Development Tutorial for FOnline.
Post by: Powerack on November 14, 2018, 03:37:27 pm
Hi, I have a problem with the World Editor. This program started only once. I looked at the control and turned it off. When I tried to turn it on again, only a white window appeared and nothing went on. I tried running the program as an administrator, just like I tested compatibility with Windows XP and Windows 7. Nothing helps. I have Windows 10 Pro and .NET Framework 4 installed. Can you help me somehow? Thank you for your answer.
Title: Re: Basic Development Tutorial for FOnline.
Post by: Ghosthack on November 15, 2018, 07:39:29 pm
Hi, I have a problem with the World Editor. This program started only once. I looked at the control and turned it off. When I tried to turn it on again, only a white window appeared and nothing went on. I tried running the program as an administrator, just like I tested compatibility with Windows XP and Windows 7. Nothing helps. I have Windows 10 Pro and .NET Framework 4 installed. Can you help me somehow? Thank you for your answer.

Hi, see https://fodev.net/forum/index.php/topic,30010.0.html - this is an old bug.
Title: Re: Basic Development Tutorial for FOnline.
Post by: testerDEV on November 16, 2018, 10:34:05 pm
Try this: https://forum.fonline-reloaded.net/index.php?topic=13299.0
Title: Re: Basic Development Tutorial for FOnline.
Post by: Powerack on December 15, 2018, 03:32:18 am
No, after reading this I try to change AsyncLoading to false, but program fail with starting. That does nothing.

Problem solved. I created .BAT file named StartWE.bat inside WE folder:

Code: [Select]
@echo off
del cache.dat
WorldEditor.exe

Before start WE delete cache file and from now program always start correctly. No need any other changes.
Title: Re: Basic Development Tutorial for FOnline.
Post by: Powerack on December 16, 2018, 02:45:08 pm
Is there a way to keep the saved world and just update city locations, or do I always have to delete the entire save? I would like to add things gradually without losing the progress of other players in the game.