Useful Functions

I get "getArg" almost working but there are still problems I need to figure out. Will post the code when it's done soon. Here's another function which was a lot easier to make (but again unnecessary):
pawn Код:
stock numArgs()
{
    // Get the adress
    #emit LOAD.S.PRI 0
    // Skip over the function header
    #emit ADD.C 8
    // Load the address
    #emit LOAD.I
    // Convert from bytes to cells
    #emit SHR.C.PRI 2
    // Return the value
    #emit RETN
    // Return a random value to ignore the warning
    return 0;
}
I tested a several times and it did work good for me.
Reply

pawn Код:
stock
    GetXYZInViewOfPlayer(playerid, &Float:X, &Float:Y, &Float:Z, Float:distance)
{
    new Float:VX, Float:VY, Float:VZ;
   
    GetPlayerPos(playerid, X, Y, Z);
    GetPlayerCameraFrontVector(playerid, VX, VY, VZ);
   
    X += (distance * VX);
    Y += (distance * VY);
    Z += (distance * VZ);
}
Just like ******'s GetXYInFrontOfPlayer. But this one uses cam vector for getting coords.

Example Usage:

pawn Код:
CMD:xyztest(playerid, params[])
{
    new Float:X, Float:Y, Float:Z;

    GetPlayerPos(playerid, X,Y,Z);

    new object = CreateObject(18647, X, Y, Z, 0, 0, 0, 100);

    GetXYZInViewOfPlayer(playerid, X, Y, Z, 10);

    MoveObject(object, X,Y,Z, 2);
   
    return true;
}
Reply

Quote:
Originally Posted by iPLEOMAX
Посмотреть сообщение
pawn Код:
stock
    GetXYZInViewOfPlayer(playerid, &Float:X, &Float:Y, &Float:Z, Float:distance)
{
    new Float:VX, Float:VY, Float:VZ;
   
    GetPlayerPos(playerid, X, Y, Z);
    GetPlayerCameraFrontVector(playerid, VX, VY, VZ);
   
    X += (distance * VX);
    Y += (distance * VY);
    Z += (distance * VZ);
}
Just like ******'s GetXYInFrontOfPlayer. But this one uses cam vector for getting coords.

Example Usage:

pawn Код:
CMD:xyztest(playerid, params[])
{
    new Float:X, Float:Y, Float:Z;

    GetPlayerPos(playerid, X,Y,Z);

    new object = CreateObject(18647, X, Y, Z, 0, 0, 0, 100);

    GetXYZInViewOfPlayer(playerid, X, Y, Z, 10);

    MoveObject(object, X,Y,Z, 2);
   
    return true;
}
That indeed is a nice function
Reply

Or something similar:

https://sampforum.blast.hk/showthread.php?tid=38965&p=1394066
Reply

@RyDeR`

That's a pretty cool function. I'm bad with Trigonometry or i would make some advanced ones.. xD
Reply

"getArg" is finally done!
pawn Код:
stock getArg(iArg, iIdx)
{
    #emit LOAD.S.PRI iArg   // Load parameter address
    #emit SHL.C.PRI 2       // Convert that value from cells to bytes
    #emit ADD.C 12          // Add 12 to skip the function header
    #emit LOAD.S.ALT 0      // Get previous function's frame
    #emit ADD               // Add to pri
    #emit LOAD.I            // Load address
    #emit LOAD.S.ALT iIdx   // Load parameter address
    #emit SHL.C.ALT 2       // Convert that value from cells to bytes
    #emit ADD               // Add to pri
    #emit LOAD.I            // Load address
    #emit RETN              // Return value
   
    return 0;               // Random return to ignore compiler warning
}
I want to thank ****** for all his help and making things easier to understand.

Here's also a "setArg" function based of "getArg":
pawn Код:
stock setArg(iArg, iIdx, iValue)
{
    new
        iAddr
    ;
    #emit LOAD.S.PRI iArg   // Load parameter address
    #emit SHL.C.PRI 2       // Convert that value from cells to bytes
    #emit ADD.C 12          // Add 12 to skip the function header
    #emit LOAD.S.ALT 0      // Get previous function's frame
    #emit ADD               // Add to pri
    #emit LOAD.I            // Load address
    #emit LOAD.S.ALT iIdx   // Load parameter address
    #emit SHL.C.ALT 2       // Convert that value from cells to bytes
    #emit ADD               // Add to pri
    #emit STOR.S.PRI iAddr  // Store pri to iAddr
    #emit LOAD.S.ALT iValue // Load parameter address
    #emit SREF.S.ALT iAddr  // Store value to reference parameters
   
    return 1;
}
Reply

Quote:

stock
GetXYZInViewOfPlayer(playerid, &Float:X, &Float:Y, &Float:Z, Float:distance)
{
new Float:VX, Float:VY, Float:VZ;

GetPlayerPos(playerid, X, Y, Z);
GetPlayerCameraFrontVector(playerid, VX, VY, VZ);

X += (distance * VX);
Y += (distance * VY);
Z += (distance * VZ);
}

Hm I through about this function but I think it needs a little correction:
pawn Код:
stock GetXYZInViewOfPlayer(playerid, &Float:X, &Float:Y, &Float:Z, Float:distance)
{
    new Float:VX, Float:VY, Float:VZ;
   
    //GetPlayerPos(playerid, X, Y, Z);
    GetPlayerCameraPos(playerid,X,Y,Z);
    //I change this because the Cameravector starts from the CameraPos and not from the Player.
    //If it would start from the Player the Cameravector would be a little bit different.
    //Now you have to think that the distance you choose for this function is not from Player to a point,
    //it is from the CameraPos... (Don't forget it)
    GetPlayerCameraFrontVector(playerid, VX, VY, VZ);
   
    //--[Correction of the CameraVector]----------------------------------------------
    new Float:tmpfloat;
    tmpfloat = floatdiv(1,floatsqroot(floatpower(VX,2)+floatpower(VY,2)+floatpower(VZ,2)));
    // I don't know how it is called in english but in Germany we say "Betrag"
    // With this calculation "floatsqroot(floatpower(VX,2)+floatpower(VY,2)+floatpower(VZ,2))" i know how long the vector is.
    // For example the vector could be 2.34 feet/meter/inch long...
    VX = floatmul(VX, tmpfloat);
    VY = floatmul(VY, tmpfloat);
    VZ = floatmul(VZ, tmpfloat);
    // Now the cameravector is exactly 1 "distance" long...
    // I calculate (1 div [How Long the vector is]) * [Vector] = [Vector which is 1 "distance" long]
    //-------------------------------------------------------------------
   
    X += (distance * VX);
    Y += (distance * VY);
    Z += (distance * VZ);
}
The image should explain my correction...


I. GetPlayerCameraFrontVector returns the vector from the camera, but you can see that the vector which would start from the Player would be another like the "GetPlayerCameraFrontVector"... It's the reason why I change "GetPlayerPos" to "GetPlayerCameraPos"

II. I have done a "Correction of the CameraVector" because GetPlayerCameraFrontVector could return a vector which isn't 1 "Distance" long, so i have to change the normal cameravector to the modify cameravector...
Reply

Quote:
Originally Posted by Nanory
Посмотреть сообщение
Hm I through about this function but I think it needs a little correction:
pawn Код:
//CODE
The image should explain my correction...
[img][/img]

I. GetPlayerCameraFrontVector returns the vector from the camera, but you can see that the vector which would start from the Player would be another like the "GetPlayerCameraFrontVector"... It's the reason why I change "GetPlayerPos" to "GetPlayerCameraPos"

II. I have done a "Correction of the CameraVector" because GetPlayerCameraFrontVector could return a vector which isn't 1 "Distance" long, so i have to change the normal cameravector to the modify cameravector...
Did you test that the vector from GetPlayerCameraFrontVector isnt normalized ?, I thought it was. ("Betrag" = "absolute value")

And you forgot to change the old variable names
Reply

Oh sry, I mixed the variable names with the variablenames of the example from wiki.sa-mp.com

Well, i don't :P but i will test it now...

Edit: Dam, In future i should check my theory first... (Shame on me :P)
The Cameravector is 1 "distance" long (always), so my first post can be delete.
Such a work for nothing

Edit2: The only thing which is true is the fact that GetPlayerPos have to be change to GetPlayerCameraPos.
Reply

good damn it I've never know that float functions...
Reply

Okay, this function is perfect for rotating a plane around a point however, rotating the object to face this specific way of movement may need to be tweaked with some correct offsets;

pawn Код:
static
    Float: g_ObjectDeg [ MAX_OBJECTS ]
;

stock SetObjectMoveAroundPoint( objectid, Float: X, Float: Y, Float: Z, Float: distance, Float: speed = 1.0, Float: face = false)
{
    new
        Float: nX, Float: nY
    ;
    if( g_ObjectDeg[ objectid ] >= 360 ) g_ObjectDeg[ objectid ] = 0;
    else g_ObjectDeg[ objectid ] += speed;

    nX = X + distance * floatcos( g_ObjectDeg[ objectid ], degrees );
    nY = Y + distance * floatsin( g_ObjectDeg[ objectid ], degrees );

    SetObjectPos( objectid, nX, nY, Z );
    if(face) SetObjectRot( objectid, 0.0, 0.0, 90 - g_ObjectDeg[ objectid ] );
}
Enjoy your time!
Reply

Quote:
Originally Posted by RyDeR`
Посмотреть сообщение
"getArg" is finally done!
pawn Код:
stock getArg(iArg, iIdx)
{
    #emit LOAD.S.PRI iArg   // Load parameter address
    #emit SHL.C.PRI 2       // Convert that value from cells to bytes
    #emit ADD.C 12          // Add 12 to skip the function header
    #emit LOAD.S.ALT 0      // Get previous function's frame
    #emit ADD               // Add to pri
    #emit LOAD.I            // Load address
    #emit LOAD.S.ALT iIdx   // Load parameter address
    #emit SHL.C.ALT 2       // Convert that value from cells to bytes
    #emit ADD               // Add to pri
    #emit LOAD.I            // Load address
    #emit RETN              // Return value
   
    return 0;               // Random return to ignore compiler warning
}
I want to thank ****** for all his help and making things easier to understand.

Here's also a "setArg" function based of "getArg":
pawn Код:
stock setArg(iArg, iIdx, iValue)
{
    new
        iAddr
    ;
    #emit LOAD.S.PRI iArg   // Load parameter address
    #emit SHL.C.PRI 2       // Convert that value from cells to bytes
    #emit ADD.C 12          // Add 12 to skip the function header
    #emit LOAD.S.ALT 0      // Get previous function's frame
    #emit ADD               // Add to pri
    #emit LOAD.I            // Load address
    #emit LOAD.S.ALT iIdx   // Load parameter address
    #emit SHL.C.ALT 2       // Convert that value from cells to bytes
    #emit ADD               // Add to pri
    #emit STOR.S.PRI iAddr  // Store pri to iAddr
    #emit LOAD.S.ALT iValue // Load parameter address
    #emit SREF.S.ALT iAddr  // Store value to reference parameters
   
    return 1;
}
I don't understand. Why can't we just use getarg and setarg, Nor how is this an usefull function.
Reply

Quote:
Originally Posted by wups
Посмотреть сообщение
I don't understand. Why can't we just use getarg and setarg, Nor how is this an usefull function.
http://forum.sa-mp.com/showpost.php?...postcount=2496

Read.
Reply

Quote:
Originally Posted by RyDeR`
Посмотреть сообщение
So why do you post in the Usefull functions topic? There's scripting discussion for that.
Reply

Probably not the right topic for personal achievements, yea.
Reply

Well, it could have been useful if we had no native functions to do this. But still, it can be useful for some other people that want to learn something more about ─ see comments in the function ─ and therefore this is the correct place to post it as far as I'm concerned.
Reply

Quote:
Originally Posted by System64
Посмотреть сообщение
I'm looking but I don't understand?
Use a loop with the number of arguments and get the arguments.
  • getarg(arg)
  • numargs()
However, follow what ****** said, It'll not work my way anyway.

pawn Код:
stock SendClientMessageFormatted(playerid, color, fstring[], {Float, _}:...)
{
    #define BYTES_PER_CELL              4
    static const STATIC_ARGS = 3;
    new n = (numargs() - STATIC_ARGS) * BYTES_PER_CELL;
    if(n)
    {
        new message[144],arg_start,arg_end;
        #emit CONST.alt        fstring
        #emit LCTRL          5
        #emit ADD
        #emit STOR.S.pri        arg_start

        #emit LOAD.S.alt        n
        #emit ADD
        #emit STOR.S.pri        arg_end
        do
        {
            #emit LOAD.I
            #emit PUSH.pri
            arg_end -= BYTES_PER_CELL;
            #emit LOAD.S.pri      arg_end
        }
        while(arg_end > arg_start);

        #emit PUSH.S          fstring
        #emit PUSH.C          144
        #emit PUSH.ADR         message

        n += BYTES_PER_CELL * 3;
        #emit PUSH.S          n
        #emit SYSREQ.C         format

        n += BYTES_PER_CELL;
        #emit LCTRL          4
        #emit LOAD.S.alt        n
        #emit ADD
        #emit SCTRL          4

        if(playerid == INVALID_PLAYER_ID)
        {
            #pragma unused playerid
            return SendClientMessageToAll(color, message);
        } else {
            return SendClientMessage(playerid, color, message);
        }
    } else {
        if(playerid == INVALID_PLAYER_ID)
        {
            #pragma unused playerid
            return SendClientMessageToAll(color, fstring);
        } else {
            return SendClientMessage(playerid, color, fstring);
        }
    }
}
Epic function.
Reply

Wait, your code works or?
So I have to use EMIT's and that shit for that function o.O?
Reply

Quote:
Originally Posted by System64
Посмотреть сообщение
Wait, your code works or?
So I have to use EMIT's and that shit for that function o.O?
Would say so.

It works however it's created by ****** and ZeeX I suppose. (was told by someone)
Reply

Why not use the macros posted in this topic? 1 line for each function :/
Reply


Forum Jump:


Users browsing this thread: 34 Guest(s)