Useful Functions

Quote:
Originally Posted by ******
Посмотреть сообщение
No it doesn't, it overwrites part of the stack, and you don't know WHAT part of the stack - it just happened to work in your exact use-case.
Functions that return strings/arrays stores their addresses at 12+numargs() so that function appears to be legit.

Furthermore, if you're returning strings in a variadic function it will only count the static arguments, which is a bug. Here's how I fixed that: https://github.com/oscar-broman/strl...rlib.inc#L1304
Reply

SetPlayerPosEx - It sets the player's position just like setplayerpos does and sets the player's vehicle position if player is in a vehicle and is a driver.
SetPlayerInteriorEx - Just like above mentioned, but sets the interior.
OnPlayerTeleport - Calls when 'SetPlayerPos' is being called in the script for player.
OnVehicleTeleport - Calls when 'SetVehiclePos' is being called in the script for vehicle.

Both the above callbacks requires to the hooked stuff to be added in scripts which uses teleportation or else the calls won't work well.

Functions which need to be added in every script which uses 'SetPlayerPos' or 'SetVehiclePos' if the callback must work perfectly. NOTE: Must be added before using those functions in the script or else it won't work well.
pawn Код:
stock ___SetPos(playerid, Float:X, Float:Y, Float:Z)
{
 SetPlayerPos(playerid, X, Y, Z);
 CallLocalFunction("OnPlayerTeleport", "i", playerid);
 return 1;
}

stock ___SetvPos(vehicleid, Float:X, Float:Y, Float:Z)
{
 SetVehiclePos(vehicleid, X, Y, Z);
 CallLocalFunction("OnVehicleTeleport", "i", vehicleid);
 return 1;
}

stock __SetInt(playerid, inte)
{
 SetPlayerInterior(playerid, inte);
 CallLocalFunction("OnPlayerTeleport", "i", playerid);
 return 1;
}

stock __SetvInt(vehicleid, inte)
{
 LinkVehicleToInterior(vehicleid, inte);
 CallLocalFunction("OnVehicleTeleport", "i", vehicleid);
 return 1;
}

#if defined _ALS_SetPlayerPos
 #undef SetPlayerPos
#else
 #define _ALS_SetPlayerPos
#endif

#if defined _ALS_SetVehiclePos
 #undef SetVehiclePos
#else
 #define _ALS_SetVehiclePos
#endif

#if defined _ALS_SetPlayerInterior
 #undef SetPlayerInterior
#else
 #define _ALS_SetPlayerInterior
#endif

#if defined _ALS_LinkVehicleToInterior
 #undef LinkVehicleToInterior
#else
 #define _ALS_LinkVehicleToInterior
#endif

#define SetPlayerPos ___SetPos
#define SetVehiclePos ___SetvPos
#define SetPlayerInterior __SetInt
#define LinkVehicleToInterior __SetvInt

forward OnPlayerTeleport(playerid);
forward OnVehicleTeleport(vehicleid);
pawn Код:
stock SetPlayerPosEx(playerid, Float:X, Float:Y, Float:Z)
{
 if(IsPlayerInAnyVehicle(playerid))
 {
  new __vid__ = GetPlayerVehicleID(playerid);
  SetVehiclePos(__vid__, X, Y, Z);
 }
 else
 {
  SetPlayerPos(playerid, X, Y, Z);
 }
 return 1;
}

stock SetPlayerInteriorEx(playerid, interior)
{
 if(IsPlayerInAnyVehicle(playerid))
 {
  new _ivid_ = GetPlayerVehicleID(playerid);
  LinkVehicleToInterior(_ivid_, interior);
 }
 else
 {
  SetPlayerInterior(playerid, interior);
 }
 return 1;
}
Reply

Код:
stock strcatEx(fstring[], ...)
{
    new temp[2];
 	const STATIC_ARGS = 1;
 	fstring[0] = EOS;
    for(new i = STATIC_ARGS, args = numargs(); i != args; ++i)
    {
        new x,
            string[128],
			chari = -1;
        while(chari != 0)
		{
            chari = getarg(i, x);
            format(temp, sizeof temp, "%c", chari);
            strcat(string, temp);
            x++;
            if(!chari) break;
        }
		format(fstring, 128, "%s%s%s", fstring, (fstring[0] != EOS) ? (" ") : (""), string);
    }
	return 1;
}
Example:
Код:
new result[70];
strcatEx(result, "This", "is", "Sparta!");
print(result);
Will print "This is Sparta!"
Reply

Can be improved, just pass the address to strcat directly instead of getting it first.
pawn Код:
stock implode(const szDelim[], szBuf[], const iSize, ...) {
    static
        iStart,
        iEnd
    ;
    #emit ADDR.PRI  iSize
    #emit ADD.C     4
    #emit STOR.PRI  iStart
   
    iEnd = iStart + ((numargs() - 3) << 2);
   
    while(iStart != iEnd) {
        #emit LOAD.PRI  iStart
        #emit LOAD.I
       
        #emit PUSH.S    iSize
        #emit PUSH.PRI
        #emit PUSH.ADR  szBuf
        #emit PUSH.C    12
        #emit SYSREQ.C  strcat
        #emit STACK     16
       
        iStart += 4;
       
        if(iStart < iEnd) {
            strcat(szBuf, szDelim, iSize);
        }
    }
}
pawn Код:
new result[70];
implode(" ", result, sizeof(result), "This", "is", "Sparta!");
print(result);
Reply

Код:
stock Check_If_Point_In_Triangle(playerid,Float:X,Float:Y,Float:Z,Float:R,Float:MAX_Z)
{
    new const Float:Winkel = 60.0,Float:Weite = 30.0;
	new Float:Pos[8];
	GetPlayerPos(playerid,Pos[0],Pos[1],Pos[2]);
	Pos[4] = Y+(Weite*floatsin(Winkel+R,degrees));
	Pos[5] = Y-(Weite*floatsin(R-Winkel,degrees));
	Pos[6] = X+(Weite*floatcos(Winkel+R,degrees));
	Pos[7] = X-(Weite*floatcos(R-Winkel,degrees));
    return (((Y-Pos[4])*(Pos[0]-X) + (Pos[6]-X)*(Pos[1]-Y)) <0 ||((Pos[4]-Pos[5])*(Pos[0]-Pos[6]) + (Pos[7]-Pos[6])*(Pos[1]-Pos[4])) <0 ||((Pos[5]-Y)*(Pos[0]-Pos[7]) + (X-Pos[7])*(Pos[1]-Pos[5])) <0 || Pos[2] > MAX_Z || Pos[2] < Z) ? 0:1;
}
With this code you can check if someone in a triangle area.

It`s maybe good for a blitzersystem

A littel picture

Reply

Playing audio streams with a volume parameter:

pawn Код:
stock PlayStream(playerid, url[], volume = 100)
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    PlayAudioStreamForPlayer(playerid, url, x, y, z + volume, volume + 10, 1);
    return 1;
}
Tested and it works.
Reply

Quote:
Originally Posted by Emmet_
Посмотреть сообщение
Playing audio streams with a volume parameter:

pawn Код:
stock PlayStream(playerid, url[], volume = 100)
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    PlayAudioStreamForPlayer(playerid, url, x, y, z + volume, volume + 10, 1);
    return 1;
}
Tested and it works.
Oh nice one! :P That could come in handy.
Reply

Quote:
Originally Posted by Emmet_
Посмотреть сообщение
Playing audio streams with a volume parameter:

pawn Код:
stock PlayStream(playerid, url[], volume = 100)
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    PlayAudioStreamForPlayer(playerid, url, x, y, z + volume, volume + 10, 1);
    return 1;
}
Tested and it works.
Very nice !
Reply

pawn Код:
#define ACCURACY 0.5 // lower the number more accurate the result
stock IsThereLOS(Float:point1[3], Float:point2[3])
{
    new Float: vector[3];
    new Float: dpoint[3];
    dpoint[0] = point2[0];
    dpoint[1] = point2[1];
    dpoint[2] = point2[2];
    new Float:konst;
    do
    {
        vector[0] = point1[0]-dpoint[0];
        vector[1] = point1[1]-dpoint[1];
        vector[2] = point1[2]-dpoint[2];
        konst = ACCURACY/floatsqroot(vector[0]*vector[0]+vector[1]*vector[1]+vector[2]*vector[2]);
        vector[0] = konst*vector[0];
        vector[1] = konst*vector[1];
        vector[2] = konst*vector[2];
        dpoint[0] = dpoint[0]+vector[0];
        dpoint[1] = dpoint[1]+vector[1];
        dpoint[2] = dpoint[2]+vector[2];
        new Float:zpoint;
        GetPointZPos(dpoint[0],dpoint[1], zpoint);
        //CreateObject(19130,dpoint[0],dpoint[1],zpoint+0.5,0.0,0.0,0.0);
        //CreateObject(19130,dpoint[0],dpoint[1],dpoint[2]+0.5,0.0,0.0,0.0);
        //printf("%.2f | %.2f",dpoint[2], zpoint);
        if(dpoint[2] < zpoint) return 0;
    }while(konst<1);
    return 1;
}
This requires MapAndreas include or plugin (if you use plugin replace GetPointZPos with MapAndreas_FindZ_For2DCord)
How does it work?
For every x,y,z that is on vector going from point1 to point2 it checks for real Z coordinate. If the real Z coordinate is bigger than Z coordinate of x,y on than vector it means that there is an obstacle between the two points.
NOTE
Since this uses MapAndreas it has the same drawbacks.
Reply

Here's a useful function:
pawn Код:
stock IsVehicleAimingAtPlayer(vid, pid, Float:r = 2.0)
{
    new
        Float:d,
        Float:sx,
        Float:sz,
        Float:cx,
        Float:cz,
        Float:px,
        Float:py,
        Float:pz,
        Float:rx,
        Float:ry,
        Float:rz;
    GetVehiclePos(vid, px, py, pz);
    GetVehicleRot(vid, rx, ry, rz);
    d = GetPlayerDistanceFromPoint(pid, px, py, pz);
    sx = floatsin(rx, degrees);
    sz = floatsin(rz, degrees);
    cx = floatcos(rx, degrees);
    cz = floatcos(rz, degrees);
    px = px + d *-cx * sz;
    py = py + d * cx * cz;
    pz = pz + d * sx;
    if (IsPlayerInRangeOfPoint(pid, r, px, py, pz))
    {
        return 1;
    }
    return 0;
}

stock GetVehicleRot(vehicleid, &Float:rx, &Float:ry, &Float:rz)
{
    new
        Float:qw,
        Float:qx,
        Float:qy,
        Float:qz;
    GetVehicleRotationQuat(vehicleid, qw, qx, qy, qz);
    ConvertQuatToEuler(qw, -qx, -qy, -qz, rx, ry, rz);
    return 1;
}

stock ConvertQuatToEuler(Float:qw, Float:qx, Float:qy, Float:qz, &Float:rx, &Float:ry, &Float:rz)
{
    new
        Float:sqw = qw * qw,
        Float:sqx = qx * qx,
        Float:sqy = qy * qy,
        Float:sqz = qz * qz;
    rx = asin (2 * (qw * qx + qy * qz) / (sqw + sqx + sqy + sqz));
    ry = atan2(2 * (qw * qy - qx * qz), 1 - 2 * (sqy + sqx));
    rz = atan2(2 * (qw * qz - qx * qy), 1 - 2 * (sqz + sqx));
    return 1;
}
Reply

I have been looking for a function like IsVehicleAimingAtPlayer for AGES, Stylock. Thanks!
Reply

Quote:
Originally Posted by JustBored
Посмотреть сообщение
It already exists:
https://sampwiki.blast.hk/wiki/SetVehicleZAngle
My function:
pawn Код:
stock ShowPlayerFormatedDialog(playerid, dialogid, style, caption[], info[], button1[], button2[])
{
    new str[128];
    format(str, sizeof(str), "%s", info);
    ShowPlayerDialog(playerid, dialogid, style, caption, str, button1, button2);
    return 1;
}

how is this formatted function ? , u just copying a string into other ..
also about cellsize, how about info will be bigger ?
this actually doing nothing ..
Reply

Can someone make a fuction that creates a object in front of player ?

Edit:
nvm. I found it

pawn Код:
stock GetXYInFrontOfPlayer(playerid, &Float:x, &Float:y, Float:distance)
{
    new Float:Angle;
    GetPlayerPos(playerid, x, y, Angle);
    GetPlayerFacingAngle(playerid, Angle);
    if (GetPlayerVehicleID(playerid))
    {
        GetVehicleZAngle(GetPlayerVehicleID(playerid), Angle);
    }
    x += (distance * floatsin(-Angle, degrees));
    y += (distance * floatcos(-Angle, degrees));
}
Reply

I saw some peoples uses old and slow split.
I was interested to improve the old split to be more faster then it is now and so I did.

Here my final code:
Код:
stock split(const src[], dest[][], const delimiter = ',', size = 128)
{
    new
		i, li,
		index;
	new const
		len = strlen( src );
    while( ++i <= len ) if( src[ i ] == delimiter || i >= len )
    {
		strmid( dest[ ++index ], src, li, i, size );
		li = i + 1;
    }
    return true;
}
If we will compare this to the old split this is used less memory end much faster for those reasons:
1. I not checking every round the length (twice!) like the old split.
2. I does not have len variable (for none reason).
3. I not storing data that for no reason.

If you want some speed comparison so I did it for you, here the final result:
Looping 100,000 times:
Mine split - 2017 - Just two seconds
Old split - 14317 - Just over 10 seconds

Looping 1,000,000 times:
Mine split - 20213 - Just 20 seconds
Old split - 143105 - Just over 2 minutes

The code that I used to those tests:
Код:
new
    t0, t1, t2,
    test[4][128];
t0 = GetTickCount();
for (new i = 0; i < LLOP; i++ )
{
    split("test|is|mine|test", test, '|');
}
t1 = GetTickCount();
printf("< speed > mine split: %d", t1 - t0);


for (new  i = 0; i < LLOP; i++ )
{
    split2("test|is|mine|test", test, '|');
}
t2 = GetTickCount();
printf("< speed > frenzys split: %d", t2 - t1);
    
///////////////////////////////////////////////////////////////////////////


stock split(const src[], dest[][], const delimiter = ',', size = 128)
{
    new
		i, li,
		index;
	new const
		len = strlen( src );
    while( ++i <= len ) if( src[ i ] == delimiter || i >= len )
    {
		strmid( dest[ ++index ], src, li, i, size );
		li = i + 1;
    }
    return true;
}

stock split2(const strsrc[], strdest[][], delimiter)
{
    new i, li;
    new aNum;
    new len;
    while(i <= strlen(strsrc))
    {
        if(strsrc[i] == delimiter || i == strlen(strsrc))
        {
            len = strmid(strdest[aNum], strsrc, li, i, 128);
            strdest[aNum][len] = 0;
            li = i+1;
            aNum++;
        }
        i++;
    }
    return 1;
}
Enjoy of using this, all rights for the PAWN split goes to the old split creator - I only improved this.
Reply

Why would you still use split if sscanf is available, though..?
Reply

Quote:
Originally Posted by RealCop228
Посмотреть сообщение
Why would you still use split if sscanf is available, though..?
I using sscanf2 but there are still peoples that uses split so if they want to use split at least the split will faster then the old one.
Reply

Quote:
Originally Posted by Swimor
Посмотреть сообщение
I using sscanf2 but there are still peoples that uses split so if they want to use split at least the split will faster then the old one.
Not sure which the "old one" is, but this one is the most complete one out there. It supports packed strings and won't cause buffer overflows.
Reply

Quote:
Originally Posted by Slice
Посмотреть сообщение
Not sure which the "old one" is, but this one is the most complete one out there. It supports packed strings and won't cause buffer overflows.
Can you make some Speed tests please?
Reply

pawn Код:
GetSuffix(iNumber)
{
    new
        iSuffix[4]
    ;
    switch (iNumber)
    {
        case 1, 21, 31, 41: iSuffix = "st";
        case 2, 22, 32, 42: iSuffix = "nd";
        case 3, 23, 33, 43: iSuffix = "rd";
        default: iSuffix = "th";
    }
    return iSuffix;
}
Reply

Quote:
Originally Posted by Djole1337
Посмотреть сообщение
pawn Код:
// CODE
Can be made more general like this.
Reply


Forum Jump:


Users browsing this thread: 36 Guest(s)