[Include] Create your own surface with just one line (CreateObjectSurface)
#1

What is this?

With this include you can dynamically create your own surface by inputting starting X and Y and ending X and Y positions, along with the model of the object, height, X and Y object offsets and other additional parameters. You can easily edit your surface once you've created it, or you can destroy it. Read more about functions and their parameters below.



Credits:

- Incognito for streamer plugin,
- ****** for foreach/iterator include.



Pictures:







How to use this?

Scroll down and download the "surface.inc" include file and place it into the "\pawno\include\" folder and do the same thing with "streamer.inc" and "foreach.inc" files.

Open your script and put this ...:
pawn Код:
#include <streamer>
#include <foreach>
#include <surface>
... right after the:
pawn Код:
#include <a_samp>
Also make sure to download the foreach include and streamer plugin and other necessary files with it.

Example:
pawn Код:
// Sand objects (covers the whole San Andreas map plus the sea surrounding it, 5184 objects in total).
CreateSurface(19548, 125.0, 125.0, 35.0, -4500.0, -4500.0, 4500.0, 4500.0, .d_stream = 1000.0);


Functions:


CreateSurface
Information: Use this function to create a surface on the server.

Input parameters:

Main parameters:

@object_model - model ID of the object which will be used to create the surface.
@Float: x_off - object's X offset.
@Float: y_off - object's Y offset.
@Float: height - height of our surface.
@Float: x_start - starting X position of our surface.
@Float: y_start - starting Y position of our surface.
@Float: x_end - ending X position of our surface.
@Float: y_end - ending Y position of our surface.

Additional parameters:
@Float: x_rot - X rotation for objects (it's 0.0 by default).
@Float: y_rot - Y rotation for objects (it's 0.0 by default).
@Float: z_rot - Z rotation for objects (it's 0.0 by default).
@world - the virtual world of our surface (it's -1 by default).
@interior - the interior of our surface (it's -1 by default).
@player - use this if you want to create the surface only for a specific player (it's -1 by default).
@Float: d_stream - streaming distance for objects (it's 200.0 by default).
@Float: d_draw - drawing distance for objects (it's 0.0 by default).

returns - the function returns the ID of the dynamically created surface. It returns -1 if there is a fail in creation, which means there are too many surfaces created. It returns -2 if one of the starting and ending positions (X, Y) is the same (the script will also fail to create the surface).

Example:
pawn Код:
// Breakable glass surface at "The Farm" (1978 objects in total).
new
        s_id = CreateSurface(1649, 4.4, 3.31, 129.0, -1195.0, -1065.0, -1007.0, -916.0, .d_stream = 1000.0, .x_rot = 270.0);

DestroySurface
Information: Use this function to destroy the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns true (1) if the surface was successfully destroyed and false (0) if the surface doesn't exist.

Example:
pawn Код:
DestroySurface(s_id);

SetSurfaceTexture
Information: Use this function to set the material texture for every object created for surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@m_index - the material index on the surface to change.
@txd_model - the modelid on which the replacement texture is located.
@txd_name[] - the name of the txd file which contains the replacement texture.
@texture_name[] - the name of the texture to use as the replacement.
@m_color - the object color to set, as an integer or hex in ARGB color format, using 0 keeps the existing material color (it's 0 by default).

returns - the function returns true (1) if the material texture was successfully applied and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfaceTexture(s_id, 0, 17944, "lngblok_lae2", "white64bumpy");

SetSurfaceObjectTexture
Information: Use this function to set the material texture for a specific object created for surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@slot - the slot where our object is located.
@m_index - the material index on the object to change.
@txd_model - the modelid on which the replacement texture is located.
@txd_name[] - the name of the txd file which contains the replacement texture.
@texture_name[] - the name of the texture to use as the replacement.
@m_color - the object color to set, as an integer or hex in ARGB color format, using 0 keeps the existing material color (it's 0 by default).

returns - the function returns true (1) if the material texture was successfully applied and false (0) if the surface doesn't exist or if the ID of the slot or object is invalid.

Example:
pawn Код:
SetSurfaceObjectTexture(s_id, 5, 0, 17944, "lngblok_lae2", "white64bumpy");

SetSurfaceModel
Information: Use this function to change the object model of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@object_model - model ID of the object which will be used to create/change the surface.
@Float: x_off - object's X offset.
@Float: y_off - object's Y offset.

returns - the function returns true (1) if the object model of the surface was successfully changed and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfaceModel(s_id, 19552, 125.0, 125.0);

GetSurfaceModel
Information: Use this function to get the information about the object model of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the object model if the surface exists and false (0) if it doesn't exist.

Example:
pawn Код:
printf("Object model of the surface is %i.", GetSurfaceModel(s_id));

SetSurfacePos
Information: Use this function to change the starting and ending positions of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@Float: x_start - starting X position of our surface.
@Float: y_start - starting Y position of our surface.
@Float: x_end - ending X position of our surface.
@Float: y_end - ending Y position of our surface.

returns - the function returns true (1) if the positions of the surface were successfully changed and false (0) if the surface doesn't exist or if one of the starting and ending positions (X, Y) is the same.

Example:
pawn Код:
SetSurfacePos(s_id, -500.0, -500.0, 500.0, 500.0);

GetSurfacePos
Information: Use this function to get the information about the starting and ending positions of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@&Float: x_start - a float variable in which to store the starting X position in, passed by reference.
@&Float: y_start - a float variable in which to store the starting Y position in, passed by reference.
@&Float: x_end - a float variable in which to store the ending X position in, passed by reference.
@&Float: y_end - a float variable in which to store the ending Y position in, passed by reference.

returns - the function returns true (1) if the surface exists and false (0) if it doesn't exist.

Example:
pawn Код:
new
        Float:pos[4];
GetSurfacePos(s_id, pos[0], pos[1], pos[2], pos[3]);
printf("Positions of the surface are: starting X (%0.2f), starting Y (%0.2f), ending X (%0.2f), ending Y (%0.2f)", pos[0], pos[1], pos[2], pos[3]);

SetSurfaceHeight
Information: Use this function to change the height of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@Float: height - height of our surface.

returns - the function returns true (1) if the height of the surface was successfully changed and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfaceHeight(s_id, 50.0);

GetSurfaceHeight
Information: Use this function to get the information about the height of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the height (float) if the surface exists and -100.0 if it doesn't exist.

Example:
pawn Код:
printf("Height of the surface is %0.2f.", GetSurfaceHeight(s_id));

SetSurfaceRot
Information: Use this function to change the rotation of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@Float: x_rot - X rotation for objects.
@Float: y_rot - Y rotation for objects.
@Float: z_rot - Z rotation for objects.

returns - the function returns true (1) if the rotation was successfully changed and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfaceRot(s_id, 0.0, 0.0, 90.0);

GetSurfaceRot
Information: Use this function to get the information about the rotation of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@&Float: x_rot - a float variable in which to store the X rotation in, passed by reference.
@&Float: y_rot - a float variable in which to store the Y rotation in, passed by reference.
@&Float: z_rot - a float variable in which to store the Z rotation in, passed by reference.

returns - the function returns true (1) if the surface exists and false (0) if it doesn't exist.

Example:
pawn Код:
new
        Float:pos[3];
GetSurfaceRot(s_id, pos[0], pos[1], pos[2]);
printf("Rotations of the surface are: X (%0.2f), Y (%0.2f), Z (%0.2f)", pos[0], pos[1], pos[2]);

SetSurfaceStreamDistance
Information: Use this function to change the streaming distance of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@Float: d_stream - streaming distance for objects.

returns - the function returns true (1) if the streaming distance of the surface was successfully changed and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfaceStreamDistance(s_id, 400.0);

GetSurfaceStreamDistance
Information: Use this function to get the information about the streaming distance of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the streaming distance (float) if the surface exists and 0.0 if it doesn't exist.

Example:
pawn Код:
printf("Streaming distance of the surface is %0.2f.", GetSurfaceStreamDistance(s_id));

SetSurfaceDrawDistance
Information: Use this function to change the drawing distance of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.
@Float: d_draw - drawing distance for objects.

returns - the function returns true (1) if the drawing distance of the surface was successfully changed and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfaceDrawDistance(s_id, 400.0);

GetSurfaceDrawDistance
Information: Use this function to get the information about the drawing distance of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the drawing distance (float) if the surface exists and -1.0 if it doesn't exist.

Example:
pawn Код:
printf("Drawing distance of the surface is %0.2f.", GetSurfaceDrawDistance(s_id));

SetSurfaceWorld
Information: Use this function to change the virtual world of the surface. Use the -1 value if you want the surface to be visible in all worlds.

Input parameters:
@s_id - the ID of the dynamic surface.
@world - the virtual world of our surface.

returns - the function returns true (1) if the virtual world of the surface was successfully changed and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfaceWorld(s_id, 5);

GetSurfaceWorld
Information: Use this function to get the information about the virtual world of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the virtual world if the surface exists and -2 if it doesn't exist.

Example:
pawn Код:
printf("Virtual world of the surface is %i.", GetSurfaceWorld(s_id));

SetSurfaceInterior
Information: Use this function to change the interior of the surface. Use the -1 value if you want the surface to be visible in all interiors.

Input parameters:
@s_id - the ID of the dynamic surface.
@interior - the interior of our surface.

returns - the function returns true (1) if the interior of the surface was successfully changed and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfaceInterior(s_id, 10);

GetSurfaceInterior
Information: Use this function to get the information about the interior of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the interior if the surface exists and -2 if it doesn't exist.

Example:
pawn Код:
printf("Interior of the surface is %i.", GetSurfaceInterior(s_id));

SetSurfacePlayer
Information: Use this function to change the player of the surface. Use the -1 value if you want the surface to be visible to all players.

Input parameters:
@s_id - the ID of the dynamic surface.
@player - use this if you want to show the surface only to a specific player.

returns - the function returns true (1) if the player of the surface was successfully setted and false (0) if the surface doesn't exist.

Example:
pawn Код:
SetSurfacePlayer(s_id, 20);

GetSurfacePlayer
Information: Use this function to get the information about the player of the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the player ID if the surface exists and -2 if it doesn't exist.

Example:
pawn Код:
printf("Player of the surface is %i (%s).", GetSurfacePlayer(s_id), GetPlayerNameEx(GetSurfacePlayer(s_id)));

GetSurfaceObjectCount
Information: Use this function to get the information about total objects created for the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the total object count if the surface exists and false (0) if it doesn't exist.

Example:
pawn Код:
printf("Total object count for the surface is %i.", GetSurfaceObjectCount(s_id));

GetSurfaceHorizontalObjects
Information: Use this function to get the information about total objects created in horizontal direction (X) for the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the horizontal object count if the surface exists and false (0) if it doesn't exist.

Example:
pawn Код:
printf("Horizontal object count for the surface is %i.", GetSurfaceHorizontalObjects(s_id));

GetSurfaceVerticalObjects
Information: Use this function to get the information about total objects created in vertical direction (Y) for the surface.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the vertical object count if the surface exists and false (0) if it doesn't exist.

Example:
pawn Код:
printf("Vertical object count for the surface is %i.", GetSurfaceVerticalObjects(s_id));

GetSurfaceSurplusObjects
Information: Use this function to get the information about created surplus objects which aren't counted in neither horizontal (X) or vertical direction (Y) for the surface. There will be surplus objects if the calculation for creating objects was disturbed due to objects-per-surface limit.

Input parameters:
@s_id - the ID of the dynamic surface.

returns - the function returns the surplus object count if the surface exists and -1 if it doesn't exist.

Example:
pawn Код:
printf("Surplus object count for the surface is %i.", GetSurfaceSurplusObjects(s_id));


Regarding horizontal, vertical and surplus objects:

pawn Код:
// We change this in our "surface.inc" include file.
#define MAX_SURFACE_OBJECTS (10)

new
        s_id = CreateSurface(18752, 215.0, 215.0, 100.0, 500.0, 500.0, -500.0, -500.0);

printf("Total object count for the surface is %i.", GetSurfaceObjectCount(s_id));
printf("Horizontal object count for the surface is %i.", GetSurfaceHorizontalObjects(s_id));
printf("Vertical object count for the surface is %i.", GetSurfaceVerticalObjects(s_id));
printf("Surplus object count for the surface is %i.", GetSurfaceSurplusObjects(s_id));
This will create our surface from -500.0, -500.0 to 500.0, 500.0.

Total distance in X direction:
500.0 + 500.0 = 1000.0

Total distance in Y direction:
500.0 + 500.0 = 1000.0

X offset
1000.0 / 215.0 = 4.65 ~= 5

Y offset
1000.0 / 215.0 = 4.65 ~= 5

Total object count:
5 * 5 = 25

But our objects-per-surface limit is setted to 10 in this case, so that's the maximum the function will create.

Our "printf" functions will return this:
Код:
Error at "UpdateSurface" function for model 18752 (surface ID: 0) - limit for objects per surface is reached (10/25). Change the "MAX_SURFACE_OBJECTS" definition in your "surface.inc" include file if you want to have more objects per surface.

Created/updated 10 objects at "UpdateSurface" function for model 18752 (surface ID: 0).

Total object count for the surface is 10.
Horizontal object count for the surface is 3.
Vertical object count for the surface is 1.
Surplus object count for the surface is 7.
If we set our objects-per-surface limit to 25 or more in this case, this is what we'll get:
Код:
Created/updated 25 objects at "UpdateSurface" function for model 18752 (surface ID: 0).

Total object count for the surface is 25.
Horizontal object count for the surface is 5.
Vertical object count for the surface is 5.
Surplus object count for the surface is 0.
There were no surplus objects, because the calculation for creating objects wasn't disturbed - the limit was big enough.



Loops:

If you want to loop through all valid (created) objects for the surface, then use the code like this:
pawn Код:
for(new a = 0; a < GetSurfaceObjectCount(s_id); a++)
{
    MySurfaceFunctionForObject(s_id, a);
}
If you want to loop through all valid (created) surfaces, then use the code like this:
pawn Код:
foreach(Iter_Surface, a)
{
    MySurfaceFunction(a);
}


New settings and objects in surface:

If you have for an example 500 objects created for your surface and you change the model, X and Y offset of the object or starting and ending position, so the surface would create more objects, you'll need to re-apply the texture for these additional objects. The old ones will be fine.

In case you also change your settings, but this time so it would produce less objects than before, then you have no worries, the script will delete other unnecessary/surplus objects regarding the old settings of the surface.



Definitions:

These are the definitions in the include file (these values are default in the include file - change them as you like):
pawn Код:
#define MAX_SURFACES (10)
#define MAX_SURFACE_OBJECTS (3000)
#define OBJ_DBG_MSG
Definition "MAX_SURFACES" obviously tells the script how many surfaces are allowed to be created. The "MAX_SURFACE_OBJECTS" definition tells the script how many objects per surface are allowed to be created.

Delete the "OBJ_DBG_MSG" definition if you don't want messages about surface creating/updating in the console/server log.



Download:

Version 2 (latest version - dynamic surfaces):


Version 1 (if you're interested in the main calculation code):
Reply
#2

really nice work
Reply
#3

Awesome work.
Reply
#4

Nice work
Reply
#5

Nice work
Reply
#6

omg, very nice work man!
Reply
#7

Interesting i would check it later!
Reply
#8

It's a good idea but I don't like the design here are my reasons.

1.) There is no saving of objectid's which means you lose all reference of objects!
2.) Too many parameters in the function.
3.) There should be pools of objects this will fix the first two issues.

You need to think dynamic design when it comes to SAMP it's almost always the same refer to this link and specifically the hearts concept.

http://forum.sa-mp.com/showpost.php?...4&postcount=14

So I will just give you an idea here none of this code has been tested.

pawn Код:
#define OBJ_DBG_MSG
#define MAX_SURFACE_GROUPS 10
#define MAX_SURFACE_OBJECTS 200

enum OBJECTSURFACEGROUPINFO
{
        // Parameter settings
        Float:gSI_object_model,
        Float:gSI_x_off,
        Float:gSI_y_off,
        Float:gSI_height,
        Float:gSI_x_start,
        Float:gSI_y_start,
        Float:gSI_x_end,
        Float:gSI_y_end,
        gSI_world,
        gSI_interior,
        gSI_player,
        Float:gSI_d_stream,
        Float:gSI_d_draw,

        // Saved object data
        gSI_ObjectID[MAX_SURFACE_OBJECTS],
        Float:gSI_OX[MAX_SURFACE_OBJECTS],
        Float:gSI_OY[MAX_SURFACE_OBJECTS],

        // Internal data
        bool:gSI_Used,
        gSI_Count,
}

static g_ObjectSurfaceGroups[MAX_SURFACE_GROUPS][OBJECTSURFACEGROUPINFO];
stock CreateObjectSurface(object_model, Float:x_off, Float:y_off, Float:height, Float:x_start, Float:y_start, Float:x_end = 0.0, Float:y_end = 0.0, Float:x_rot = 0.0, Float:y_rot = 0.0, Float:z_rot = 0.0, world = -1, interior = -1, player = -1, Float:d_stream = 200.0, Float:d_draw = 0.0)
{
    for(new i = 0; i < MAX_SURFACE_GROUPS; i++)
    {
            if(g_ObjectSurfaceGroups[i][gSI_Used] == false)
            {
                    if(!x_end)
                    {
                            if(x_start < 0.0)       x_end = floatabs(x_start);
                            else                            x_end = -x_start;
                    }

                    if(!y_end)
                    {
                            if(y_start < 0.0)       y_end = floatabs(y_start);
                            else                            y_end = -y_start;
                    }

                    if(x_start == x_end || y_start == y_end)
                    {
                        printf("Error at \"CreateObjectSurface\" function for model %i - one of the starting and ending positions (X: %0.2f, Y: %0.2f) is the same.",
                                object_model,
                                x_start,
                                y_start
                            );
                        return -1;
                    }
                   
                    // Save all parameter data
                    g_ObjectSurfaceGroups[i][gSI_object_model] = object_model;
                    g_ObjectSurfaceGroups[i][gSI_x_off] = x_off;
                    g_ObjectSurfaceGroups[i][gSI_y_off] = y_off;
                    g_ObjectSurfaceGroups[i][gSI_height] = height;
                    g_ObjectSurfaceGroups[i][gSI_x_start] = x_start;
                    g_ObjectSurfaceGroups[i][gSI_y_start] = y_start;
                    g_ObjectSurfaceGroups[i][gSI_x_end] = x_end;
                    g_ObjectSurfaceGroups[i][gSI_y_end] = y_end;
                    g_ObjectSurfaceGroups[i][gSI_world] = world;
                    g_ObjectSurfaceGroups[i][gSI_interior] = interior;
                    g_ObjectSurfaceGroups[i][gSI_player] = player;
                    g_ObjectSurfaceGroups[i][gSI_d_stream] = d_stream;
                    g_ObjectSurfaceGroups[i][gSI_d_draw] = d_draw;
                    g_ObjectSurfaceGroups[i][gSI_Used] = true;
                   
                    new
                                    Float:coord[2], bool:calculate[2], loop[2], object;

                    if(x_start < 0.0)
                    {
                            // -3000.0, -4000.0 -> 1000.0
                            // -4000.0, -3000.0 -> 1000.0
                            if(x_end < 0.0)
                            {
                                    if(x_start > x_end)
                                            calculate[0] = true;
                                    coord[0] = floatabs(x_start + floatabs(x_end));
                            }
                            // -3000.0, 4000.0 -> 7000.0
                            else
                                    coord[0] = floatabs(x_start) + x_end;
                    }
                    else
                    {
                            // 3000.0, -4000.0 -> 7000.0
                            if(x_end < 0.0)
                            {
                                    calculate[0] = true;
                                    coord[0] = x_start + floatabs(x_end);
                            }
                            // 3000.0, 4000.0 -> 1000.0
                            // 4000.0, 3000.0 -> 1000.0
                            else
                            {
                                    if(x_start > x_end)
                                            calculate[0] = true;
                                    coord[0] = floatabs(x_start - x_end);
                            }
                    }

                    if(y_start < 0.0)
                    {
                            // -3000.0, -4000.0 -> 1000.0
                            // -4000.0, -3000.0 -> 1000.0
                            if(y_end < 0.0)
                            {
                                    if(y_start > y_end)
                                            calculate[1] = true;
                                    coord[1] = floatabs(y_start + floatabs(y_end));
                            }
                            // -3000.0, 4000.0 -> 7000.0
                            else
                                    coord[1] = floatabs(y_start) + y_end;
                    }
                    else
                    {
                            // 3000.0, -4000.0 -> 7000.0
                            if(y_end < 0.0)
                            {
                                    calculate[1] = true;
                                    coord[1] = y_start + floatabs(y_end);
                            }
                            // 3000.0, 4000.0 -> 1000.0
                            // 4000.0, 3000.0 -> 1000.0
                            else
                            {
                                    if(y_start > y_end)
                                            calculate[1] = true;
                                    coord[1] = floatabs(y_start - y_end);
                            }
                    }

                    loop[0] = floatround(coord[0] / x_off, floatround_ceil);
                    loop[1] = floatround(coord[1] / y_off, floatround_ceil);

                    g_Count = 0;

                    for(new a = 0; a < loop[0]; a++)
                    {
                            for(new b = 0; b < loop[1]; b++)
                            {
                                    if(calculate[0])        coord[0] = x_start - (x_off * a);
                                    else                            coord[0] = x_start + (x_off * a);

                                    if(calculate[1])        coord[1] = y_start - (y_off * b);
                                    else                            coord[1] = y_start + (y_off * b);

                                    // Save object id
                                    g_ObjectSurfaceGroups[i][gSI_ObjectID][g_Count] = CreateDynamicObject(
                                            object_model,
                                            coord[0],
                                            coord[1],
                                            height,
                                            x_rot,
                                            y_rot,
                                            z_rot,
                                            world,
                                            interior,
                                            player,
                                            d_stream,
                                            d_draw
                                    );

                                    // Save position data
                                    g_ObjectSurfaceGroups[i][gSI_OX][g_Count] = coord[0];
                                    g_ObjectSurfaceGroups[i][gSI_OY][g_Count] = coord[1];

                                    g_Count++;
                            }
                    }

                    #if defined OBJ_DBG_MSG
                            printf("Created %i objects at \"CreateObjectSurface\" function for model %i.",
                                    g_Count,
                                    object_model
                            );
                    #endif
                   
                    g_ObjectSurfaceGroups[i][gSI_Count] = g_Count;

                    // Return surface group index
                    return i;

                }
        }

        printf("ERROR::CreateObjectSurface()::Too many surfaces");
        return -1;
}

stock SetObjectSurfaceMaterial(index, m_index = 0, txd_model = 0, txd_name[] = "", texture_name[] = "", m_color = 0)
{
        if(index < 0 || index >= MAX_SURFACE_GROUPS)
        {
                printf("ERROR::SetObjectSurfaceMaterial()::Index out of bounds");
                return -1;
        }
        else
        {
                if(g_ObjectSurfaceGroups[index][gSI_Used])
                {
                        for(new i = 0; i < g_ObjectSurfaceGroups[index][gSI_Count]; i++)
                        {
                                SetDynamicObjectMaterial(object, m_index, txd_model, txd_name, texture_name, m_color);
                        }
                        g_ObjectSurfaceGroups[index][gSI_Used] = false;
                        return 1;
                }

        }
        printf("ERROR::SetObjectSurfaceMaterial()::Index does not exist");
        return -1;
}


stock DestroyObjectSurface(index)
{
        if(index < 0 || index >= MAX_SURFACE_GROUPS)
        {
                printf("ERROR::CreateObjectSurface()::Index out of bounds");
                return -1;
        }
        else
        {
                if(g_ObjectSurfaceGroups[index][gSI_Used])
                {
                        for(new i = 0; i < g_ObjectSurfaceGroups[index][gSI_Count]; i++)
                        {
                                DestroyDynamicObject(g_ObjectSurfaceGroups[index][i];
                        }
                        g_ObjectSurfaceGroups[index][gSI_Used] = false;
                        return 1;
                }
       
        }
        printf("ERROR::CreateObjectSurface()::Index does not exist");
        return -1;
}
Reply
#9

As Pottus stated there is no way to detect if an object was created with this function / no way to destroy the surface.
Reply
#10

Quote:
Originally Posted by Pottus
Посмотреть сообщение
1.) There is no saving of objectid's which means you lose all reference of objects!
Usually I would create a dynamic system, but this time I've left it out for the first version, since I was in a hurry and some people were mainly interested in the main code. However, the plan is to update the current version and add additional stuff when I find more time.

Quote:
Originally Posted by Pottus
Посмотреть сообщение
2.) Too many parameters in the function.
More than half of them are additional.

Cheers.
Reply
#11

It'd be easier if it was on GitHub that way people could contribute easily, it'd save you some work.
Reply
#12

I really like the idea.

Try update with Pottus advises.. And maybe use Github is better for updates...
Reply
#13

The include file is updated - the surfaces are now fully dynamic with many functions to manage them.

Some new pictures:


You can get the include file here:


Check the main post for more information about the functions and other stuff.
Reply
#14

Correlli you're a god.
Reply
#15

Woow, Correlli you had a good ideia, this is amazing!
Good job bro!
Reply
#16

I'm going to recommend that you add the ability to set surface rotations as well it's actually easier than it sounds.

By Stylock
This is a standard function for rotating objects around a point it recalculates new the position and rotation.

pawn Код:
stock AttachPoint(Float:offx, Float:offy, Float:offz, Float:offrx, Float:offry, Float:offrz, Float:px, Float:py, Float:pz, Float:prx, Float:pry, Float:prz, &Float:RetX, &Float:RetY, &Float:RetZ, &Float:RetRX, &Float:RetRY, &Float:RetRZ, sync_rotation = 1)
{
    new
        Float:g_sin[3],
        Float:g_cos[3],
        Float:off_x,
        Float:off_y,
        Float:off_z;

    EDIT_FloatEulerFix(prx, pry, prz);

    off_x = offx - px; // static offset
    off_y = offy - py; // static offset
    off_z = offz - pz; // static offset

    // Calculate the new position
    EDIT_FloatConvertValue(prx, pry, prz, g_sin, g_cos);
    RetX = px + off_x * g_cos[1] * g_cos[2] - off_x * g_sin[0] * g_sin[1] * g_sin[2] - off_y * g_cos[0] * g_sin[2] + off_z * g_sin[1] * g_cos[2] + off_z * g_sin[0] * g_cos[1] * g_sin[2];
    RetY = py + off_x * g_cos[1] * g_sin[2] + off_x * g_sin[0] * g_sin[1] * g_cos[2] + off_y * g_cos[0] * g_cos[2] + off_z * g_sin[1] * g_sin[2] - off_z * g_sin[0] * g_cos[1] * g_cos[2];
    RetZ = pz - off_x * g_cos[0] * g_sin[1] + off_y * g_sin[0] + off_z * g_cos[0] * g_cos[1];

    if (sync_rotation)
    {
        // Calculate the new rotation
        EDIT_FloatConvertValue(asin(g_cos[0] * g_cos[1]), atan2(g_sin[0], g_cos[0] * g_sin[1]) + offrz, atan2(g_cos[1] * g_cos[2] * g_sin[0] - g_sin[1] * g_sin[2], g_cos[2] * g_sin[1] - g_cos[1] * g_sin[0] * -g_sin[2]), g_sin, g_cos);
        EDIT_FloatConvertValue(asin(g_cos[0] * g_sin[1]), atan2(g_cos[0] * g_cos[1], g_sin[0]), atan2(g_cos[2] * g_sin[0] * g_sin[1] - g_cos[1] * g_sin[2], g_cos[1] * g_cos[2] + g_sin[0] * g_sin[1] * g_sin[2]), g_sin, g_cos);
        EDIT_FloatConvertValue(atan2(g_sin[0], g_cos[0] * g_cos[1]) + offrx, asin(g_cos[0] * g_sin[1]), atan2(g_cos[2] * g_sin[0] * g_sin[1] + g_cos[1] * g_sin[2], g_cos[1] * g_cos[2] - g_sin[0] * g_sin[1] * g_sin[2]), g_sin, g_cos);

        RetRX = asin(g_cos[1] * g_sin[0]);
        RetRY = atan2(g_sin[1], g_cos[0] * g_cos[1]) + offry;
        RetRZ = atan2(g_cos[0] * g_sin[2] - g_cos[2] * g_sin[0] * g_sin[1], g_cos[0] * g_cos[2] + g_sin[0] * g_sin[1] * g_sin[2]);
    }
}





stock EDIT_FloatConvertValue(Float:rot_x, Float:rot_y, Float:rot_z, Float:sin[3], Float:cos[3])
{
    sin[0] = floatsin(rot_x, degrees);
    sin[1] = floatsin(rot_y, degrees);
    sin[2] = floatsin(rot_z, degrees);
    cos[0] = floatcos(rot_x, degrees);
    cos[1] = floatcos(rot_y, degrees);
    cos[2] = floatcos(rot_z, degrees);
    return 1;
}

/*
 * Fixes a bug that causes objects to not rotate
 * correctly when rotating on the Z axis only.
 */

stock EDIT_FloatEulerFix(&Float:rot_x, &Float:rot_y, &Float:rot_z)
{
    EDIT_FloatGetRemainder(rot_x, rot_y, rot_z);
    if((!floatcmp(rot_x, 0.0) || !floatcmp(rot_x, 360.0))
    && (!floatcmp(rot_y, 0.0) || !floatcmp(rot_y, 360.0)))
    {
        rot_y = 0.00000002;
    }
    return 1;
}

stock EDIT_FloatGetRemainder(&Float:rot_x, &Float:rot_y, &Float:rot_z)
{
    EDIT_FloatRemainder(rot_x, 360.0);
    EDIT_FloatRemainder(rot_y, 360.0);
    EDIT_FloatRemainder(rot_z, 360.0);
    return 1;
}

stock EDIT_FloatRemainder(&Float:remainder, Float:value)
{
    if(remainder >= value)
    {
        while(remainder >= value)
        {
            remainder = remainder - value;
        }
    }
    else if(remainder < 0.0)
    {
        while(remainder < 0.0)
        {
            remainder = remainder + value;
        }
    }
    return 1;
}
Reply
#17

It's just 'osm. Love it. Corelli. You. Are. Awesome.
Reply
#18

OMG this is crazy and just what i needed! THANKS!
Reply
#19

Holy $#!t!!!!!
Nice!!
Reply
#20

Great job!

I wanted to ask you (Correlli) if I can use your include for an small map include I am working on and I will release soon? Obviously respecting your credits.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)