Author Topic: [Solved] 2 Questions about Worldmap  (Read 3372 times)

Offline C4N

[Solved] 2 Questions about Worldmap
« on: September 14, 2018, 05:55:04 pm »
I'm trying to make some kind of "more realistic" traveling system, but I stumbled upon a problem I cannot solve.

How can you edit the speed at which players move around the world map?
I found this var in script/config.fos, but changing it to a lower or higher number doesn't seems to do anything related to worldmap speed at all.

Code: [Select]
    __GlobalMapMoveTime         = 250;
FOnline API says this: Указывает на то как часто вызывать обработчик глобальной карты GLOBAL_PROCESS_MOVE.

Which means: Indicates how often to call the GLOBAL_PROCESS_MOVE global map handler.
And that just doesn't make any sense to me... I honestly have no idea what is that for.

ANSWER:
First question - Open your scripts.cfg file in a server/scripts directory, look for @server bind global_process, you will find out where the function is bounded from to the engine. Everything else from this point should be very simple.

Te other question is a bit more complex, can we change the behavior of the server's way to read the heightmap image in maps/? Or it is hardcoded into the engine?
Currently it is a simple PNG, but I want it to be multiple PNG, to make a heightmap that works the same way the original game reads the "bigmap", ie:

Instead of one image, I want it to be four, like:
Code: [Select]
heightmap-01.png  -  top left
heightmap-02.png  -  top right
heightmap-03.png  -  bottom left
heightmap-04.png  -  bottom right

ANSWER:
I concluded my research on this topic... sadly, it can't be done.
TL;DR for the curious, don't make maps bigger than 8192 px, a 100x100x81 setup is the biggest I could manage to do.

Thanks in advance for any help with this.
« Last Edit: September 15, 2018, 08:10:14 pm by C4N »

Re: 2 Questions about Worldmap
« Reply #1 on: September 14, 2018, 08:24:20 pm »
First question - Open your scripts.cfg file in a server/scripts directory, look for @server bind global_process, you will find out where the function is bounded from to the engine. Everything else from this point should be very simple.

Second question - seems like you want to split the globalmap picture into pieces ? For client its possible. Search for GmapTilesX and GmapTilesY entries in your interface configuration file ( default.ini in example ). But if question is about the worldmap mask picture, I dont really understand why would you need that, because normally its used with GetGlobalMapRelief server function that cuts off low 4 bits of blue piece of a pixel colour of the given position ( up to 16 masks support by default ). Where pixel is the actual position on the worldmap *picture*. And honestly, if anyone knows if this is possible without hard magik ?

Re: 2 Questions about Worldmap
« Reply #2 on: September 14, 2018, 09:08:42 pm »
I'm trying to make some kind of "more realistic" traveling system...

What SDK version are you talking about? It's important issue

Offline C4N

Re: 2 Questions about Worldmap
« Reply #3 on: September 15, 2018, 03:58:22 am »
First question - Open your scripts.cfg file in a server/scripts directory, look for @server bind global_process, you will find out where the function is bounded from to the engine. Everything else from this point should be very simple.

Second question - seems like you want to split the globalmap picture into pieces ? For client its possible. Search for GmapTilesX and GmapTilesY entries in your interface configuration file ( default.ini in example ). But if question is about the worldmap mask picture, I dont really understand why would you need that, because normally its used with GetGlobalMapRelief server function that cuts off low 4 bits of blue piece of a pixel colour of the given position ( up to 16 masks support by default ). Where pixel is the actual position on the worldmap *picture*. And honestly, if anyone knows if this is possible without hard magik ?

Thanks, this is what I was looking for. I found the procedure with the pixel speed logic, there is a math line where you can easily increase the divider value to practically make the player move slower.
Looking at the code I realized that things like roads, where only cars travel faster could be possible (even mud areas where it gets stuck), interesting stuff in here, I also saw what you said about the mask, mask ID are retrieved from GetGlobalMapRelief, that function made me to think about what I want to do with the heightmap. Actually, to correct myself (sorry I'm no English native speaker), when I said heightmap, I meant this image where you use different colors to define a different worldmap movement logic on the server, it's not an actual heightmap, but I don't know how to call it, heheh.

To the point.
From WorldmapInit, I can initialize multiple images, create the definitions for every image and modify GetGlobalMapRelief logic to something like this:

if coords in section1
 retrieve pixel from image 1
if coords in section2
 retrieve pixel from image 2
if coords in section3
 retrieve pixel from image 3
and so on...
.
.
return pixel

So I think its possible, I'll try this 'hard magik' later on, I need to put my brain into coffee to make this thing clear (I just woke up).

What SDK version are you talking about? It's important issue

I think that to answer this I need to give a bit of background, but, TL;DR: /Koniiko

So, to explain myself a bit further, I'm in the first phase of a project idea, conceptualizing, I currently have a little team; a writer (historian) and a designer, we are talking and drawing things so this project has a solid start. But to do so, I (as the developer of the team) need to understand what are the limits of this engine, that's why I'm trying some crazy stuff to push the engine and find the practical limits. In the process, I'm learning how everything works... not an easy task without a lovely well documented API.

I first tried to use the original SDK (rev 800 if I remember well) from cvet, but I didn't manage to make it work, I couldn't even launch the server.
Then I started to search for options and found the Reloaded 1 and 2, I tried both and both worked, I though that was a good start.
But then, I suddenly found what Koniiko released a couple of days ago, so I decided to use that instead, it looks more solid than Reloaded2.

And now, I'm looking at the code trying things, a little funny anecdote to share. When my writer asked me, - How big can the map be?. I was like... - I have no idea let me see.
That's when I realized that traveling to city A to city B in 20 seconds was pretty bollocks and I started this research on "a new traveling system".

I have on my bag-of-things-to-do, questions like; how many cities can we have? How many NPCs can the server handle? Are any limitations on how many critters and different objects can the client load? And a large etc.

From this I can't say more, as I said we are in concept phase and it has no point to say more until we have something. But do not worry, we'll release here when we have a solid alpha.
« Last Edit: September 15, 2018, 04:36:09 am by C4N »

Re: 2 Questions about Worldmap
« Reply #4 on: September 15, 2018, 11:09:43 am »
How big can the map be?.

Max size of global map is 100x100 zones, max width of zone is 500 pixels. (__GlobalMapWidth, etc, in config.fos )

You can manage the global movement speed by using image masks. Color of pixel refers some speed koefficient.
For example (from old TLA content):
   mask
   (script: function void global_process)
« Last Edit: September 15, 2018, 11:11:22 am by rifleman17 »

Offline C4N

Re: 2 Questions about Worldmap
« Reply #5 on: September 15, 2018, 11:43:31 am »
Thanks rifleman17, I already figured about all of that, the problem about this is that you can't just have a 50000x50000 png image (this is an editing software issue not an actual limitation to the png format), you need to slice it into 25 10000x10000 png images.

And when you have all those 25 images, you need to logically (with what I said before) mash them up together like this:

01 02 03 04 05
06 07 08 09 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

Also, theoretically (I need to look further into this) slicing this (even further than this kind of 10kpx resolution limit) could improve performance on the server, my point here is that the server shouldn't call a big ass image every time it calls for a pixel, instead, it should call for the smaller corresponding one. Just a theory, but it may works.
I'm currently working on a template to make the biggest map currently possible, I'll release it here later.

I need to ask something on this topic, Where does the 100x100x500 limitation comes from? Is it some kind of bit overflow on the engine? Shouldn't this limitation could be solved by using double precision values?

Edit.
To put all of this into scale in a visually way, I made this to picture the scale. Top left black square is the base FOnline map:



As for a final conclusion, by slowing down the worldmap movement, the size of the map can be virtually incremented by huge proportions (at least the feeling of it).
« Last Edit: September 15, 2018, 12:15:09 pm by C4N »

Offline C4N

Re: 2 Questions about Worldmap
« Reply #6 on: September 15, 2018, 12:20:12 pm »
btw that question about the map size, it was made by a non-dev person, so he actually asked me about size in Km hehe, It was meant to define how far in geographical terms could the plot be written.

Offline C4N

Re: 2 Questions about Worldmap
« Reply #7 on: September 15, 2018, 08:00:55 pm »
I concluded my research on this topic... sadly, it can't be done.
TL;DR for the curious, don't make maps bigger than 8192 px, a 100x100x81 setup is the biggest I could manage to do.

Point by point.
The biggest of the issues is that the client can't handle an image bigger than 8192px. Because of that, the biggest worldmap I managed to make was 8100x8100, thats 100x100x81.
The second  problem, as I already said, is that even if the server could handle a 100x100x500 setup, I have no way to test it because I can't compile a 50000x50000 png image (not even a white flat one), because of that, the biggest map I could manage to make the server load was 10000x10000, but the client would CTD trying to load it. Unless you are ok with a black map on the client side, I wouldn't recommend this.

As a final note, I wasn't able to make the server load this grid worldmap image idea I was talking about, this is what I tried so far (ugly coding):

_defines.fos
Code: [Select]
#define IMAGE_RELIEF01                             ( 0 ) // Global map relief
#define IMAGE_RELIEF02                             ( 1 )
#define IMAGE_RELIEF03                             ( 2 )
#define IMAGE_RELIEF04                             ( 3 )
#define IMAGE_RELIEF05                             ( 4 )
#define IMAGE_RELIEF06                             ( 5 )
#define IMAGE_RELIEF07                             ( 6 )
#define IMAGE_RELIEF08                             ( 7 )
#define IMAGE_RELIEF09                             ( 8 )
#define IMAGE_RELIEF10                             ( 9 )
#define IMAGE_RELIEF11                             ( 10 )
#define IMAGE_RELIEF12                             ( 11 )
#define IMAGE_RELIEF13                             ( 12 )
#define IMAGE_RELIEF14                             ( 13 )
#define IMAGE_RELIEF15                             ( 14 )
#define IMAGE_RELIEF16                             ( 15 )
#define IMAGE_RELIEF17                             ( 16 )
#define IMAGE_RELIEF18                             ( 17 )
#define IMAGE_RELIEF19                             ( 18 )
#define IMAGE_RELIEF20                             ( 19 )
#define IMAGE_RELIEF21                             ( 20 )
#define IMAGE_RELIEF22                             ( 21 )
#define IMAGE_RELIEF23                             ( 22 )
#define IMAGE_RELIEF24                             ( 23 )
#define IMAGE_RELIEF25                             ( 24 )

worldmap.fos
Code: [Select]
uint GetGlobalMapRelief( uint x, uint y )
{
    // Used low four bits of image
    // Zero is water
if(y<=10000) // Row 1
{
    if(x<=10000)
{
    return GetImageColor( IMAGE_RELIEF01, x, y ) & 0xF; // Column 1
}
else if(x<=20000)
{
    return GetImageColor( IMAGE_RELIEF02, x, y ) & 0xF; // Column 2
}
else if(x<=30000)
{
    return GetImageColor( IMAGE_RELIEF03, x, y ) & 0xF; // Column 3
}
else if(x<=40000)
{
    return GetImageColor( IMAGE_RELIEF04, x, y ) & 0xF; // Column 4
}
else
{
    return GetImageColor( IMAGE_RELIEF05, x, y ) & 0xF; // Column 5
}
}
else if(y<=20000) // Row 2
{
    if(x<=10000)
{
    return GetImageColor( IMAGE_RELIEF06, x, y ) & 0xF; // Column 1
}
else if(x<=20000)
{
    return GetImageColor( IMAGE_RELIEF07, x, y ) & 0xF; // Column 2
}
else if(x<=30000)
{
    return GetImageColor( IMAGE_RELIEF08, x, y ) & 0xF; // Column 3
}
else if(x<=40000)
{
    return GetImageColor( IMAGE_RELIEF09, x, y ) & 0xF; // Column 4
}
else
{
    return GetImageColor( IMAGE_RELIEF10, x, y ) & 0xF; // Column 5
}
}
else if(y<=30000) // Row 3
{
    if(x<=10000)
{
    return GetImageColor( IMAGE_RELIEF11, x, y ) & 0xF; // Column 1
}
else if(x<=20000)
{
    return GetImageColor( IMAGE_RELIEF12, x, y ) & 0xF; // Column 2
}
else if(x<=30000)
{
    return GetImageColor( IMAGE_RELIEF13, x, y ) & 0xF; // Column 3
}
else if(x<=40000)
{
    return GetImageColor( IMAGE_RELIEF14, x, y ) & 0xF; // Column 4
}
else
{
    return GetImageColor( IMAGE_RELIEF15, x, y ) & 0xF; // Column 5
}
}
else if(y<=40000) // Row 4
{
    if(x<=10000)
{
    return GetImageColor( IMAGE_RELIEF16, x, y ) & 0xF; // Column 1
}
else if(x<=20000)
{
    return GetImageColor( IMAGE_RELIEF17, x, y ) & 0xF; // Column 2
}
else if(x<=30000)
{
    return GetImageColor( IMAGE_RELIEF18, x, y ) & 0xF; // Column 3
}
else if(x<=40000)
{
    return GetImageColor( IMAGE_RELIEF19, x, y ) & 0xF; // Column 4
}
else
{
    return GetImageColor( IMAGE_RELIEF20, x, y ) & 0xF; // Column 5
}
}
else // Row 5
{
    if(x<=10000)
{
    return GetImageColor( IMAGE_RELIEF21, x, y ) & 0xF; // Column 1
}
else if(x<=20000)
{
    return GetImageColor( IMAGE_RELIEF22, x, y ) & 0xF; // Column 2
}
else if(x<=30000)
{
    return GetImageColor( IMAGE_RELIEF23, x, y ) & 0xF; // Column 3
}
else if(x<=40000)
{
    return GetImageColor( IMAGE_RELIEF24, x, y ) & 0xF; // Column 4
}
else
{
    return GetImageColor( IMAGE_RELIEF25, x, y ) & 0xF; // Column 5
}
}
}
.
.
.
.
.
.
.
void WorldmapInit()
{
    LoadImage( IMAGE_RELIEF01, "BIGASM01.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF02, "BIGASM02.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF03, "BIGASM03.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF04, "BIGASM04.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF05, "BIGASM05.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF06, "BIGASM06.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF07, "BIGASM07.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF08, "BIGASM08.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF09, "BIGASM09.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF10, "BIGASM10.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF11, "BIGASM11.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF12, "BIGASM12.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF13, "BIGASM13.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF14, "BIGASM14.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF15, "BIGASM15.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF16, "BIGASM16.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF17, "BIGASM17.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF18, "BIGASM18.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF19, "BIGASM19.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF20, "BIGASM20.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF21, "BIGASM21.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF22, "BIGASM22.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF23, "BIGASM23.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF24, "BIGASM24.png", 1, PT_SERVER_MAPS );
LoadImage( IMAGE_RELIEF25, "BIGASM25.png", 1, PT_SERVER_MAPS );
    for(uint i = 0, j = Worldmap.length(); i < j; i++)
        @Worldmap[i] = CZone(i % ZONE_COUNT_X, i / ZONE_COUNT_X);

// Groups be here
    LoadWorldmapGroups("maps/groups.fowm");
    Log("Encounter groups loaded.");
 
RecolorLocations();
    Log("Locations Colored.");

    LoadWorldmapTables("maps/worldmap.focwm");
    Log("Worldmap loaded.");
    //LoadGroupsQuantities();
}

config.fos
Code: [Select]
    __GlobalMapWidth            = 100;     // Maximum 100
    __GlobalMapHeight           = 100;     // Maximum 100
    __GlobalMapZoneLength       = 500;     // Maximum 500

worldmap_h.fos
Code: [Select]
#define ZONE_COUNT_X                       (100)
#define ZONE_COUNT_Y                       (100)
#define ZONE_LENGTH                        (500)

The result was the server loading only the first image, so the player only was able to move inside a 10000x10000 worldmap (black clientside of course).
I'm dropping any further effort on this, since the client can't handle large image setups (not even sliced little images), I don't think it's worth the trouble.
« Last Edit: September 15, 2018, 08:13:07 pm by C4N »