[Tutorial] How to easily cover any San Andreas part with snow
#1

General:

Some of you may remember my releases "Snow in Los Santos" and "Snow in Desert", and now I present you an easy way to cover any part of San Andreas map by simply inserting minimum X, Y and maximum X, Y coordinates or range arguments (and some additional arguments).



Required files:
You can download the script here, rather than copying every chunk of code from the tutorial.




Code:

You'll need function which will retexture your objects with snow texture.
pawn Code:
stock AddSnowObject(modelid, Float:x, Float:y, Float:z, Float:rx, Float:ry, Float:rz, Float:d_stream = 200.0)
{
    new
            object = CreateDynamicObject(modelid, (x + 0.075), (y + 0.15), (z + 0.15), rx, ry, rz, .streamdistance = d_stream);
    for(new a = 0; a < 30; a++)
        SetDynamicObjectMaterial(object, a, 17944, "lngblok_lae2", "white64bumpy");
    return object;
}
Area creation:

Next, you'll need a function to check if position is in specified area.
pawn Code:
stock IsPosInArea(Float:pos_x, Float:pos_y, Float:min_x, Float:min_y, Float:max_x, Float:max_y)
{
    if(pos_x >= min_x && pos_x <= max_x
    && pos_y >= min_y && pos_y <= max_y)
        return true;
    return false;
}
Now, this function will create snow objects based on your area arguments (minimum X&Y and maximum X&Y), maximum Z and minimum model size of the snow objects. Make sure to read more information below this code.
pawn Code:
stock CreateSnowInArea(Float:min_x, Float:min_y, Float:max_x, Float:max_y, Float:max_z = 300.0, Float:min_obj_model_size = 30.0)
{
    new
            count;
    for(new a = 0; a < SEARCH_DATA_SIZE; a++)
    {
        if(SearchData[a][SearchZ] > max_z)
            continue;
        if(!IsPosInArea(SearchData[a][SearchX], SearchData[a][SearchY], min_x, min_y, max_x, max_y))
            continue;
        if(GetColSphereRadius(SearchData[a][Search_Model]) < min_obj_model_size)
            continue;
        if(IsObjectRemoved(SearchData[a][Search_Model], SearchData[a][SearchX], SearchData[a][SearchY], SearchData[a][SearchZ]))
            continue;
        AddSnowObject(
            SearchData[a][Search_Model],
            SearchData[a][SearchX],
            SearchData[a][SearchY],
            SearchData[a][SearchZ],
            SearchData[a][SearchRX],
            SearchData[a][SearchRY],
            SearchData[a][SearchRZ],
            (100.0 + GetColSphereRadius(SearchData[a][Search_Model]))
        );
        count++;
    }
    printf("Total snow objects: %i", count);
    return true;
}
This function will loop through every San Andreas map object and create the snow copies based on your arguments (min_x, min_y, max_x, max_y, max_z, min_obj_model_size). I do not encourage you to use this as it is, so you should rather use printing function below.

This function will print your raw snow object codes, which you can later copy from your "server_log.txt" file.
pawn Code:
stock PrintSnowForArea(Float:min_x, Float:min_y, Float:max_x, Float:max_y, Float:max_z = 300.0, Float:min_obj_model_size = 30.0)
{
    new
            count;
    for(new a = 0; a < SEARCH_DATA_SIZE; a++)
    {
        if(SearchData[a][SearchZ] > max_z)
            continue;
        if(!IsPosInArea(SearchData[a][SearchX], SearchData[a][SearchY], min_x, min_y, max_x, max_y))
            continue;
        if(GetColSphereRadius(SearchData[a][Search_Model]) < min_obj_model_size)
            continue;
        if(IsObjectRemoved(SearchData[a][Search_Model], SearchData[a][SearchX], SearchData[a][SearchY], SearchData[a][SearchZ]))
            continue;
        printf("AddSnowObject(%i, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.1f);",
            SearchData[a][Search_Model],
            SearchData[a][SearchX],
            SearchData[a][SearchY],
            SearchData[a][SearchZ],
            SearchData[a][SearchRX],
            SearchData[a][SearchRY],
            SearchData[a][SearchRZ],
            (100.0 + GetColSphereRadius(SearchData[a][Search_Model]))
        );
        count++;
    }
    printf("Total snow objects: %i", count);
    return true;
}
The streaming distance of every object if based on the model size of the object. The streaming distance is 100.0 units + the model size.

Range creation:

Next, you'll need a function to check if position is in specified range.
pawn Code:
stock IsPosInRangeOfPoint2D(Float:pos_x, Float:pos_y, Float:range, Float:range_x, Float:range_y)
{
    pos_x -= range_x;
    pos_y -= range_y;
    return ((pos_x * pos_x) + (pos_y * pos_y)) < (range * range);
}
Now, this function will create snow objects based on your range arguments (X&Y center coordinates and range), maximum Z and minimum model size of the snow objects. Make sure to read more information below this code.
pawn Code:
stock CreateSnowInRange(Float:pos_x, Float:pos_y, Float:range, Float:max_z = 300.0, Float:min_obj_model_size = 30.0)
{
    new
            count;
    for(new a = 0; a < SEARCH_DATA_SIZE; a++)
    {
        if(SearchData[a][SearchZ] > max_z)
            continue;
        if(!IsPosInRangeOfPoint2D(SearchData[a][SearchX], SearchData[a][SearchY], range, pos_x, pos_y))
            continue;
        if(GetColSphereRadius(SearchData[a][Search_Model]) < min_obj_model_size)
            continue;
        if(IsObjectRemoved(SearchData[a][Search_Model], SearchData[a][SearchX], SearchData[a][SearchY], SearchData[a][SearchZ]))
            continue;
        AddSnowObject(
            SearchData[a][Search_Model],
            SearchData[a][SearchX],
            SearchData[a][SearchY],
            SearchData[a][SearchZ],
            SearchData[a][SearchRX],
            SearchData[a][SearchRY],
            SearchData[a][SearchRZ],
            (100.0 + GetColSphereRadius(SearchData[a][Search_Model]))
        );
        count++;
    }
    printf("Total snow objects: %i", count);
    return true;
}
This function will loop through every San Andreas map object and create the snow copies based on your arguments (pos_x, pos_y, range, max_z, min_obj_model_size). I do not encourage you to use this as it is, so you should rather use printing function below.

This function will print your raw snow object codes, which you can later copy from your "server_log.txt" file.
pawn Code:
stock PrintSnowForRange(Float:pos_x, Float:pos_y, Float:range, Float:max_z = 300.0, Float:min_obj_model_size = 30.0)
{
    new
            count;
    for(new a = 0; a < SEARCH_DATA_SIZE; a++)
    {
        if(SearchData[a][SearchZ] > max_z)
            continue;
        if(!IsPosInRangeOfPoint2D(SearchData[a][SearchX], SearchData[a][SearchY], range, pos_x, pos_y))
            continue;
        if(GetColSphereRadius(SearchData[a][Search_Model]) < min_obj_model_size)
            continue;
        if(IsObjectRemoved(SearchData[a][Search_Model], SearchData[a][SearchX], SearchData[a][SearchY], SearchData[a][SearchZ]))
            continue;
        printf("AddSnowObject(%i, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.3f, %0.1f);",
            SearchData[a][Search_Model],
            SearchData[a][SearchX],
            SearchData[a][SearchY],
            SearchData[a][SearchZ],
            SearchData[a][SearchRX],
            SearchData[a][SearchRY],
            SearchData[a][SearchRZ],
            (100.0 + GetColSphereRadius(SearchData[a][Search_Model]))
        );
        count++;
    }
    printf("Total snow objects: %i", count);
    return true;
}
The streaming distance of every object if based on the model size of the object. The streaming distance is 100.0 units + the model size.



Function arguments:

Area creation:
  • @Float: min_x - minimum X coordinate for your area
  • @Float: min_y - minimum Y coordinate for your area
  • @Float: max_x - maximum X coordinate for your area
  • @Float: max_y - maximum Y coordinate for your area
  • @Float: max_z - maximum Z coordinate (this limit is useful for stopping snow object creation on interior objects which are located at 1000.0 units approximately)
  • @Float: min_obj_model_size - minimum object radius of the collision sphere
Range creation:
  • @Float: pos_x - center X coordinate for your range
  • @Float: pos_y - center Y coordinate for your range
  • @Float: range - range
  • @Float: max_z - maximum Z coordinate (this limit is useful for stopping snow object creation on interior objects which are located at 1000.0 units approximately)
  • @Float: min_obj_model_size - minimum object radius of the collision sphere


How to get minimum and maximum X, Y area coordinates:

You can read more about the area checking here.

Area example (Los Santos area).


Coordinate 1 (minimum): A1(X: 50.0, Y: -3000.0)
Coordinate 2 (maximum): A2(X: 3000.0, Y: -750.0)

Range example (San Andreas map center at 0.0 with range of 1000.0).


Use the SA-MP command "/save" while in-game to gather coordinates.



Example:

pawn Code:
public OnGameModeInit()
{
    PrintSnowForArea(50.0, -3000.0, 3000.0, -750.0, 300.0, 30.0);
    return true;
}
This code will print 1506 snow objects for Los Santos area (marked on area map above).

pawn Code:
public OnGameModeInit()
{
    PrintSnowForRange(0.0, 0.0, 1000.0, 500.0, 30.0);
    return true;
}
This code will print 367 snow objects for 1000.0 range of 0.0 center (marked on range map above).

Once you compile your script and execute it, it will print raw snow object code. Close the server and open your "server_log.txt" file. Clear the unnecessary logs and time prints from object code (CTRL + H -> "Search for: [hh : mm : ss]" and leave "Replace with:" empty).

Put your printed snow objects in your script and don't forget to include the streamer plugin include file in the script and to run the plugin.

This is the result for LS area.


You can download the LS area raw snow objects here (1506 snow objects).




Removed objects support:

You can skip the snow creating on areas where you removed objects (with "RemoveBuildingForPlayer" function) for your maps.

This is the code you'll need. The checking code is already added to the Create/Print functions.
pawn Code:
#define MAX_REMOVED_OBJECTS (500) // Value of maximum objects which can be removed. Set your own value.
pawn Code:
enum ObjectRemoved
{
    Model,
    Float:Location[3]
}
pawn Code:
new
        RemovedObject[MAX_REMOVED_OBJECTS][ObjectRemoved],
        g_SlotID = -1
;
pawn Code:
stock IsPosInRangeOfPoint3D(Float:pos_x, Float:pos_y, Float:pos_z, Float:range, Float:range_x, Float:range_y, Float:range_z)
{
    pos_x -= range_x;
    pos_y -= range_y;
    pos_z -= range_z;
    return ((pos_x * pos_x) + (pos_y * pos_y) + (pos_z * pos_z)) < (range * range);
}
pawn Code:
stock RemoveObject(modelid, Float:pos_x, Float:pos_y, Float:pos_z)
{
    g_SlotID++;
    if(g_SlotID == MAX_REMOVED_OBJECTS)
    {
        printf("Error: Limit for removed objects is reached. Open your script and change \"MAX_REMOVED_OBJECTS\" definition to a bigger value if you want to have more removed objects.");
        g_SlotID--;
        return -1;
    }
    if(g_SlotID == 1000)
    {
        printf("SA-MP limit: There appears to be a limit of around 1000 lines/objects. There is no workaround.");
        g_SlotID--;
        return -1;
    }
    RemovedObject[g_SlotID][Model]      =   modelid;
    RemovedObject[g_SlotID][Location][0]    =     pos_x;
    RemovedObject[g_SlotID][Location][1]    =     pos_y;
    RemovedObject[g_SlotID][Location][2]    =     pos_z;
    return g_SlotID;
}
pawn Code:
stock GetNumberOfRemovedObjects()
    return (g_SlotID + 1);
pawn Code:
stock IsObjectRemoved(modelid, Float:pos_x, Float:pos_y, Float:pos_z)
{
    if(!GetNumberOfRemovedObjects())
        return false;
    for(new a = 0; a < GetNumberOfRemovedObjects(); a++)
    {
        if(modelid == RemovedObject[a][Model])
        {
            if(IsPosInRangeOfPoint3D(pos_x, pos_y, pos_z, 0.5, RemovedObject[a][Location][0], RemovedObject[a][Location][1], RemovedObject[a][Location][2]))
                return true;
        }
    }
    return false;
}
Example how to use the removing function.
pawn Code:
public OnGameModeInit()
{
    /*
        @modelid - model of your object
        @Float: pos_x - X coordinate for your object
        @Float: pos_y - Y coordinate for your object
        @Float: pos_z - Z coordinate for your object
    */

    RemoveObject(4024, 1479.8672, -1790.3984, 56.0234);
    RemoveObject(4044, 1481.1875, -1785.0703, 22.3828);
    RemoveObject(4045, 1479.3359, -1802.2891, 12.5469);
    RemoveObject(4046, 1479.5234, -1852.6406, 24.5156);
    RemoveObject(4047, 1531.6328, -1852.6406, 24.5156);
    return true;
}
Don't forget to remove all the objects when player connects to the server.
pawn Code:
public OnPlayerConnect(playerid)
{
    if(GetNumberOfRemovedObjects())
    {
        for(new a = 0; a < GetNumberOfRemovedObjects(); a++)
        {
            RemoveBuildingForPlayer(
                playerid,
                RemovedObject[a][Model],
                RemovedObject[a][Location][0],
                RemovedObject[a][Location][1],
                RemovedObject[a][Location][2],
                0.5
            );
        }
    }
    return true;
}
Example with removed objects.




Problems:



Textures on some objects like trees, bushes and electrical wires will look a bit wierd, so you may want to exclude these objects from the creating/printing code. I don't think there's an easy way to do that. Only way I see it, is to open the Map Editor, search for every tree, bush, electrical wire and similar objects and exclude them.
Reply
#2

Nice
Reply
#3

Nice one mate! +rep
Reply
#4

May use this in my upcoming X-Mas update, thanks.
Reply
#5

You can easily bypass trees, bushes and electrical wires when you use those functions (CreateSnowInArea and PrintSnowForArea). Here is how it should be done, before checking their ColSphere:

pawn Code:
switch (SearchData[a][Search_Model])
{
    case tree_object: continue;
}
Reply
#6

Quote:
Originally Posted by Gammix
View Post
You can easily bypass trees, bushes and electrical wires when you use those functions (CreateSnowInArea and PrintSnowForArea). Here is how it should be done, before checking their ColSphere:

pawn Code:
switch (SearchData[a][Search_Model])
{
    case tree_object: continue;
}
Indeed, but you still need model IDs.
Reply
#7

Tutorial updated.
  • The script/tutorial now supports skipping creation of removed objects,
  • range functions are added (CreateSnowInRange, PrintSnowForRange).
Example with removed objects.


Range example (San Andreas map center at 0.0 with range of 1000.0).


You can download the script here, rather than copying every chunk of code from the tutorial.
Reply
#8

Quote:

Model sizes include by ******.

Well... you should be using the model sizes include that I put up. It's a LOT more accurate than the old one. And to go with it, check out the db-mode branch on the repo.
Quote:

All GTA SA Object Array include by Pottus

I also create a db-mode for this, it's packaged into Texture Studio but I might as well release it. It obviously decreases compile time and it increases operation speed (I kinda found this a bit surprising).

Not that speed or accuracy is extremely important here, but keeping up to date is always great.
Reply
#9

Will sure check it out, thanks.
Reply
#10

Hi, i'm trying to make San Fierro full of snow, with your script, but i have an issue. SF is really hilly, have different levels, in every streets. When i want to retexture only the grounds, many walls, buildings turns to white. Have you any advice?
Reply
#11

Correli it's Cool But can you change link of the Download because SolidFiles m is blocked in my Country.
Reply
#12

Sweet! I could use this on my server when there are some sort of Christmas Season Events etc..
Reply
#13

Quote:
Originally Posted by Ben666
View Post
Hi, i'm trying to make San Fierro full of snow, with your script, but i have an issue. SF is really hilly, have different levels, in every streets. When i want to retexture only the grounds, many walls, buildings turns to white. Have you any advice?
Fixed. We need to duplicate the original objects, then increase the X and Y coordinates of the copy, to cover the white walls. And need to decrease the Z coordinates, to keep the snow grounds above.
Reply
#14

Noice, +REP
Reply
#15

Quote:
Originally Posted by Joron
View Post
Nice
3 Years.

Quote:
Originally Posted by Gammix
View Post
You can easily bypass trees, bushes and electrical wires when you use those functions (CreateSnowInArea and PrintSnowForArea). Here is how it should be done, before checking their ColSphere:

pawn Code:
switch (SearchData[a][Search_Model])
{
    case tree_object: continue;
}
Quote:
Originally Posted by Correlli
View Post
Indeed, but you still need model IDs.
Haven't used this in a while and much people may not even know it exists. So Thread Bump.

However about object ID's these would cut out great. (Trees, Wires, Poles etc)

PHP Code:
    for(new 0SEARCH_DATA_SIZEa++)
    {
        switch (
SearchData[a][Search_Model])
        {
            case 
615..892: continue;
            case 
3505..3517: continue;
            case 
389888379019903490351606016061187331873419076: continue;
            case 
325114131141414400144021446814469: continue;
        }
        
// Code... 
Reply
#16

IKR it's kinda old topic, but... Is there anyone who've made snow map for the whole state excluding alpha-containing objects such as trees, and some others, like those that couldn't have such snow on, like decals, wires etc.?

Because, honestly, I don't feel like making an array of objects I don't want to generate snow for - this array can get quite big in size, and can probably become hard later to thin out the objects you don't need to use since walking around whole GTA SA map is well... You know. :P
Reply
#17

Quote:
Originally Posted by Maxandmov
View Post
IKR it's kinda old topic, but... Is there anyone who've made snow map for the whole state excluding alpha-containing objects such as trees, and some others, like those that couldn't have such snow on, like decals, wires etc.?

Because, honestly, I don't feel like making an array of objects I don't want to generate snow for - this array can get quite big in size, and can probably become hard later to thin out the objects you don't need to use since walking around whole GTA SA map is well... You know. :P
You're joking, right? Literally, there's a post above yours that did that lol.

It excludes all that, just simply download the generate from the first post cause it's a lot to copy and paste to send to someone.
Reply
#18

For deciduous trees you could just remove the leafs completely so the trees look bare, coniferous trees don't shed their leaves but these type of trees tend to turn brownish during the winter so setting their colour to a brownish green would look realistic.
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)