Useful Functions

Quote:
Originally Posted by Y_Less
Посмотреть сообщение
Two things:

1) You just gave me -rep for the 3 digit random number code I posted a few posts back (don't forget that mods can see names). If you know a better way of writing that code I'm more than happy to hear it. I'm not bothered about the decrease itself, but if you're going to get upset about, and accuse me of something, don't have done the exact same thing yourself!

2) Whoever did -rep you (if someone claimed to be me it probably wasn't me), I fully support their decision regardless (mods can also view old post edits) - strtok is a terrible method of coding, there was a discussion about it recently in this very thread. In that case discussion didn't do much as the original function that sparked that debate is still there. Clearly your version has now gone, proving -rep as the better incentive to not post rubbish.
1) I've must of -repped the wrong post then. I was just angry that somebody out there didn't like my very awesome strtok alternative.

2) Sorry about that. I thought you -repped me lol, I lost like a huge amount so I thought it was you, but what should I care about a number saved in a SQL database, lol.

Okay to stay on topic, here's another function I just pulled out of my ass:

pawn Код:
stock SendClientMessageEx(playerid, color, const string[], {Float,_}:...)
{
    new
        temp[12],
        value[128],
        formatted[255],
        argIndex = 3,
        argCount = numargs();

    strcat(formatted, string, sizeof(formatted));
    for (new i = 0; i < strlen(formatted) && argIndex < argCount; i ++)
    {
        if (formatted[i] != '%')
            continue;

        else switch (formatted[i + 1])
        {
            case 'c', 'd', 'f', 'i':
            {
                strmid(temp, formatted, i, i + 2);
                format(value, sizeof(value), temp, getarg(argIndex));
            }
            case 's':
            {
                for (new j, ch = 0; (ch = getarg(argIndex, j)) != '\0'; j ++) {
                    value[j] = ch;
                    if (j + 1 < sizeof(value)) value[j + 1] = '\0';
                }
            }
            case '.', '0':
            {
                strmid(temp, formatted, i, i + 4);
                format(value, sizeof(value), temp, getarg(argIndex));
            }
            default:
            {
                continue;
            }
        }
        strdel(formatted, i, (formatted[i + 1] == '.' || formatted[i + 1] == '0') ? (i + 4) : (i + 2));
        strins(formatted, value, i);
        argIndex++;
    }
    return SendClientMessage(playerid, color, formatted);
}
It's a mixture of format and SendClientMessage which supports %.1f, %02d, etc.

pawn Код:
new playername[24];
GetPlayerName(playerid, playername, sizeof(playername));
SendClientMessageEx(playerid, -1, "Hello there, %s. You have $%d money.", playername, GetPlayerMoney(playerid));
Reply

Could you explain the addition method, I am not familiar with it
Reply

Get the higher free slot

pawn Код:
stock FindLastFreeSlot()
{
    new slot = INVALID_PLAYER_ID;
    for(new i = GetMaxPlayers() - 1; i != -1; i--)
    {
        if(IsPlayerConnected(i)) continue;
        slot = i;
        break;
    }
    return slot;
}
by OKStyle

pawn Код:
stock FindLastFreeSlot()
{
    for(new i = GetMaxPlayers() - 1; i > -1; i--)
    {
        if(IsPlayerConnected(i)) continue;
        return i;
    }
    return INVALID_PLAYER_ID; // no free slots
}
by Caypen
Reply

pawn Код:
#define ConvertDays(%0) (gettime() + (86400 * (%0)))
stock ConvertToDays(n)
{
    static d, h, m, s, r;
    r = n-gettime();
    s = r % 60, r /= 60;
    m = r % 60, r /= 60;
    h = r % 24, r /= 24, d = r;

    static str[50];
    if(d ^ 0)
    {
        format(str, sizeof(str), "%dd, %02dh %02dm %02ds", d, h, m, s);
        return str;
    }
    if(h ^ 0)
    {
        format(str, sizeof(str), "%02dh %02dm %02ds", h, m, s);
        return str;
    }
    format(str, sizeof(str), "%02dm %02ds", m, s);
    return str;
}
Thanks to:
Willian Luigi - ConvertToDays
Reply

bin2dec

pawn Код:
bin2dec(n[]) {

    static c, l, j;

    c = 0;

    for(l = strlen(n) - 1, j = l  ; j > -1 ; j--) {
        if(n[j] == '1') c +=  (1 << (l-j));
    }

    return c;
}
Reply

UTF-8 encode/decode. Written using this as a reference.

pawn Код:
stock utf8encode(dest[], const source[], maxlength = sizeof(dest)) {
    new len = strlen(source);
    new packed = ispacked(source);
   
    dest[0] = '\0';
   
    new idx = 0;
   
    for (new i = 0; i < len; i++) {
        new c = packed ? source{i} : source[i];
       
        if (c >= 0x80) {
            if (c > 0x4000000) {
                // 6 byte
                dest[idx++] = 0b11111100 | ((c >>> 30) & 0b00000001);
                dest[idx++] = 0b10000000 | ((c >>> 24) & 0b00111111);
                dest[idx++] = 0b10000000 | ((c >>> 18) & 0b00111111);
                dest[idx++] = 0b10000000 | ((c >>> 12) & 0b00111111);
                dest[idx++] = 0b10000000 | ((c >>> 6) & 0b00111111);
                dest[idx++] = 0b10000000 | (c & 0b00111111);
            } else if (c > 0x200000) {
                // 5 byte
                dest[idx++] = 0b11111000 | ((c >>> 24) & 0b00000011);
                dest[idx++] = 0b10000000 | ((c >>> 18) & 0b00111111);
                dest[idx++] = 0b10000000 | ((c >>> 12) & 0b00111111);
                dest[idx++] = 0b10000000 | ((c >>> 6) & 0b00111111);
                dest[idx++] = 0b10000000 | (c & 0b00111111);
            } else if (c > 0x10000) {
                // 4 byte
                dest[idx++] = 0b11110000 | ((c >>> 18) & 0b00000111);
                dest[idx++] = 0b10000000 | ((c >>> 12) & 0b00111111);
                dest[idx++] = 0b10000000 | ((c >>> 6) & 0b00111111);
                dest[idx++] = 0b10000000 | (c & 0b00111111);
            } else if (c > 0x800) {
                // 3 byte
                dest[idx++] = 0b11100000 | ((c >>> 12) & 0b00001111);
                dest[idx++] = 0b10000000 | ((c >>> 6) & 0b00111111);
                dest[idx++] = 0b10000000 | (c & 0b00111111);
            } else {
                // 2 byte
                dest[idx++] = 0b11000000 | ((c >>> 6) & 0b00011111);
                dest[idx++] = 0b10000000 | (c & 0b00111111);
               
            }
        } else if (c > 0) {
            dest[idx++] = c;
        }
    }
   
    dest[idx++] = '\0';
}

stock utf8decode(dest[], const source[], maxlength = sizeof(dest)) {
    new len = strlen(source);
    new packed = ispacked(source);
   
    dest[0] = '\0';
   
    new idx = 0;
   
    for (new i = 0; i < len; i++) {
        new c = source[i];
       
        if (c & 0b10000000) {
            if (c & 0b11100000 == 0b11000000) {
                // 2 byte
                if (i + 3 >= len) continue;
               
                dest[idx++] = (c & 0b00011111) << 6 | (source[++i] & 0b00111111);
            } else if (c & 0b11110000 == 0b11100000) {
                // 3 byte
                if (i + 4 >= len) continue;
               
                dest[idx++] = (c & 0b00001111) << 12 |
                              (source[++i] & 0b00111111) << 6 |
                              (source[++i] & 0b00111111);
            } else if (c & 0b11111000 == 0b11110000) {
                // 4 byte
                if (i + 5 >= len) continue;
               
                dest[idx++] = (c & 0b00000111) << 18 |
                              (source[++i] & 0b00111111) << 12 |
                              (source[++i] & 0b00111111) << 6 |
                              (source[++i] & 0b00111111);
            } else if (c & 0b11111100 == 0b11111000) {
                // 5 byte
                if (i + 6 >= len) continue;
               
                dest[idx++] = (c & 0b00000011) << 24 |
                              (source[++i] & 0b00111111) << 18 |
                              (source[++i] & 0b00111111) << 12 |
                              (source[++i] & 0b00111111) << 6 |
                              (source[++i] & 0b00111111);
            } else if (c & 0b11111110 == 0b11111100) {
                // 6 byte
                if (i + 7 >= len) continue;
               
                dest[idx++] = (c & 0b00000001) << 30 |
                              (source[++i] & 0b00111111) << 24 |
                              (source[++i] & 0b00111111) << 18 |
                              (source[++i] & 0b00111111) << 12 |
                              (source[++i] & 0b00111111) << 6 |
                              (source[++i] & 0b00111111);
            }
        } else {
            dest[idx++] = c;
        }
    }
   
    dest[idx++] = 0;
}
Reply

pawn Код:
#define doAdd%2(%0,%1)  ((%0)+(%1))
pawn Код:
#define doMul%2(%0,%1)  ((%0)*(%1))
actually uneeded, because "c=a+b" and "c=a*b" requires less letters to type than "c=doAdd(a,b)" and "c=doMul(a,b)"

or

Thanks to topics like #emit and Abstract machine and emit:
pawn Код:
new a, b, c;
// Setting "a" and "b"
#emit CONST.pri 10
#emit STOR.S.pri a
#emit CONST.pri 20
#emit STOR.pri b

// c=a+b
#emit LOAD.S.pri a
#emit LOAD.S.alt b
#emit ADD
#emit STOR.S.pri c
8 instructions except new

optimized:
pawn Код:
new a, b, c;
// Stores "10" into "a" and "20" into "b", adds both values and stores into "c"
#emit CONST.pri 10
#emit CONST.alt 20
#emit STOR.S.pri a
#emit STOR.S.alt b
#emit ADD
#emit STOR.S.pri c
6 instructions except new


pawn Код:
new a, b, c;
// Setting "a" and "b"
#emit CONST.pri 10
#emit STOR.S.pri a
#emit CONST.pri 20
#emit STOR.pri b

// c=a*b
#emit LOAD.S.pri a
#emit LOAD.S.alt b
#emit SMUL
#emit STOR.S.pri c
8 instructions except new

optimized:
pawn Код:
new a, b, c;
// Stores "10" into "a" and "20" into "b", multiplies both values and stores into "c"
#emit CONST.pri 10
#emit CONST.alt 20
#emit STOR.S.pri a
#emit STOR.S.alt b
#emit SMUL
#emit STOR.S.pri c
6 instructions except new
Reply

Quote:
Originally Posted by admantis
Посмотреть сообщение
pawn Код:
doAdd(a, b)
return (a+b);

doMul(x, y)
return (x*y);
Really?



Good work Slice!
Reply

pawn Код:
// Usage
main(){
    printf("%d", hexToInt("FFFF"));
}

// Function
stock hexToInt(const szString[]) {
    new
        iVal = 0,
        iLen = strlen(szString);
    for (new x = 0; x != iLen; ++ x) {
        if (szString[x] <= 57) {
            iVal += (szString[x] -48)*(1 << (4*(iLen -1 -x)));
        } else {
            iVal += (szString[x] -55)*(1 << (4*(iLen -1 -x)));
        }
    }
    return iVal;
}
Reply

SetAll


pawn Код:
SetAll(array[][], value = 0, size_1 = sizeof array, size_2 = sizeof array[]) {

    static
        x,
        addr1,
        addr2,
        slot;

    for( x = 0; x != size_2; ++x )
        array[0][x] = value;

    // get array
    #emit load.s.pri        array
   
    // move to pri -> alt
    #emit move.alt
   
    // load in pri first idx of array
    #emit load.i
   
    // add pri with alt
    #emit add
   
    // stor in addr result
    #emit stor.pri  addr1

    for( x = 1; x != size_1; ++x ) {

        slot = x;

        #emit LOAD.S.pri    array
        #emit SHL.C.alt     2
        #emit ADD
        #emit STOR.pri  slot

        #emit LOAD.I
        #emit ADD
        #emit STOR.pri  addr2

        #emit LOAD.pri  addr1
        #emit LOAD.alt  slot
        #emit SUB
        #emit STOR.I
    }

    return true;

}


pawn Код:
new array[6][3];


SetAll( array, -1 );

for(new x = 0; x != sizeof array; x++)
    for(new i = 0;i != sizeof array[]; i++)
        printf("%d", array[x][i]);

Created by Me, Thanks to Slice.
Reply

Can't you just do this:

Код:
#define SetAll(%0,%1) \
	for (new _a = 0; _a < sizeof(%0); _a ++) \
	    for (new _b = 0; _b < sizeof(%0[]); _b ++) \
		    %0[_a][_b] = %1
Reply

Say goodbye to drift counting plugins and includes:
pawn Код:
stock Float:ReturnDriftAngle(playerid)
{
    new vehicleid = GetPlayerVehicleID(playerid);
    if(vehicleid == INVALID_VEHICLE_ID || !vehicleid) return 0.0;
    new Float:v[3], Float:a[3];
    GetVehicleVelocity(vehicleid, v[0], v[1], v[2]); GetVehicleZAngle(vehicleid, a[0]);
    if(floatmul(floatsqroot(floatadd(floatadd(floatpower(v[0], 2), floatpower(v[1], 2)), floatpower(v[2], 2))), 181.5) < 20.0) return 0;
    a[0] = (a[0] >= 360.0) ? (floatsub(a[0], 360.0)) : (a[0] < 0.0) ? (floatadd(a[0], 360.0)) : (a[0]);
    a[0] = (a[0] > 180.0) ? (floatsub(0.0, floatsub(360.0, a[0]))) : (a[0]);
    a[1] = floatsub(atan2(v[1], v[0]), 90.0);
    a[1] = (a[1] >= 360.0) ? (floatsub(a[1], 360.0)) : (a[1] < 0.0) ? (floatadd(a[1], 360.0)) : (a[1]);
    a[1] = (a[1] > 180.0) ? (floatsub(0.0, floatsub(360.0, a[1]))) : (a[1]);
    a[2] = floatabs(floatsub(a[0], a[1]));
    a[2] = (a[2] > 180.0) ? (floatsub(a[2], 180.0)) : (a[2]);
    return (a[2] >= 90.0) ? (floatsub(180.0, a[2])) : (a[2]);
}
This lil' code will return the difference between facing angle and heading angle.
This difference will always be <= 90 degrees (That's the maximum angle of drift possible).

Tested for a whole hour with one hundred 100ms timers consecutively at a home test server, in a low spec PC (504 MB of RAM) for 1 player, with absolutely no lag.

Important: If you get any "function with tag result used before definition, forcing reparse" warning, place the code after the includes.
Reply

I thought about this before I made the function. It won't return more than 90 degrees. Driving backwards would return 180 degrees normally, but further testing shows that this piece of code ain't going to do that mistake.

Edit:
pawn Код:
a[0] = (a[0] >= 360.0) ? (floatsub(a[0], 360.0)) : (a[0] < 0.0) ? (floatadd(a[0], 360.0)) : (a[0]); // Adjusts the angle between 0 and 360 degrees.
a[0] = (a[0] > 180.0) ? (floatsub(0.0, floatsub(360.0, a[0]))) : (a[0]); // Adjusts between -180 and 180 degrees.
a[1] = floatsub(atan2(v[1], v[0]), 90.0); // Gets the heading angle from the speed.
a[1] = (a[1] >= 360.0) ? (floatsub(a[1], 360.0)) : (a[1] < 0.0) ? (floatadd(a[1], 360.0)) : (a[1]);  // Same things with heading angle.
a[1] = (a[1] > 180.0) ? (floatsub(0.0, floatsub(360.0, a[1]))) : (a[1]); // Again.
a[2] = floatabs(floatsub(a[0], a[1]));  // Gets the difference between the angles.
a[2] = (a[2] > 180.0) ? (floatsub(a[2], 180.0)) : (a[2]);  // Sets the value between 0 and 180 degrees.
return (a[2] >= 90.0) ? (floatsub(180.0, a[2])) : (a[2]);  // Adjusts the value between 0 and 90 degrees.
// Returns pure drift.
Edit: Made little adjustments.
Reply

i think you can use that for check, dont know.

pawn Код:
stock bool:IsVehicleDrivingBackwards(vehicleid)
{
    new Float:Float[3];
    if(GetVehicleVelocity(vehicleid, Float[1], Float[2], Float[0])) {
        GetVehicleZAngle(vehicleid, Float[0]);
        if(Float[0] < 90) {
            if(Float[1] > 0 && Float[2] < 0)    return true;
        } else if(Float[0] < 180) {
            if(Float[1] > 0 && Float[2] > 0)    return true;
        } else if(Float[0] < 270) {
            if(Float[1] < 0 && Float[2] > 0)    return true;
        } else if(Float[1] < 0 && Float[2] < 0) return true;
    }
    return false;
}
by Nero_3D
Reply

Quote:
Originally Posted by ******
Посмотреть сообщение
I misread the thing, didn't realise it said "difference". However, in that case what happens if you spin out instead of nicely drift?
If by "spin out" meaning burnout or even no speed? I had also a speedcheck on my own function.
If I got it right: Without moving, the facing angle is x and speed angle is 0, then the drift angle will be x... without even drifting and moving... So if I add the speed check, freed of bugs?
Reply

seeking function of the vehicle near the player data
Код:
stock visible_vehicles(playerid){

	new Float:distrace,Float:pos[ 4 ], vid ;
	GetPlayerPos( playerid, pos[0], pos[1], pos[2] );

	for(new i;i<MAX_VEHICLES;i++){
		distrace = GetVehicleDistanceFromPoint(i, pos[0], pos[1], pos[2] );
		if( distrace == 0.0 ) continue;
		if( distrace <= pos[ 3 ] ){	
			pos[ 3 ] = distrace;
			vid = i;
		}else if( pos[ 3 ] == 0.0 ){
			pos[ 3 ] = 5000.0;
		}
	}
	if( pos[ 3 ] != 5000.0 ){
		return vid;
	}
	return INVALID_VEHICLE_ID;
}
Explame
Код:
CMD:puth_to_vehicle( playerid, params[] ){
	
	new vehicle = visible_vehicles(playerid);
	if( vehicle == INVALID_VEHICLE_ID ) return 0;
	printf("vid %d", vehicle);
	PutPlayerInVehicle( playerid, vehicle, 0);
	
	return 1;
}
Converter unix time to hours, minutes (and seconds)

Time_Convert - minutes, seconds.
Time_ConvertEx - hours, minutes, seconds.

Код:
#define Time_Convert(%0,%1,%2) new %1 = floatround(((%0) / 60)); new %2 = floatround((%0) - (60 * (%1)))
#define Time_ConvertEx(%0,%1,%2,%3) new %1 = floatround(((%0) / 3600)); new %2 = floatround(((%0) / 60) % 60); new %3 = floatround(((%0) - (60 * (%2))) - (3600 * %1) )
Explame #1
Код:
public OnFilterScriptInit()
{

	new czas = 99;
	
	Time_Convert(czas, tc_min, tc_sek);
	
	printf("%d sek  to %dmin %ds", czas, tc_min, tc_sek);
	
	Time_ConvertEx(czas, tcex_h, tcex_min, tcex_sek);
	
	printf("%d sek  to %dh %dmin %ds",czas, tcex_h, tcex_min, tcex_sek);
	
 	return 1;
}
Explame #2
Код:
#include a_samp
#include zcmd

#define Time_ConvertEx(%0,%1,%2,%3) new %1 = floatround(((%0) / 3600)); new %2 = floatround(((%0) / 60) % 60); new %3 = floatround(((%0) - (60 * (%2))) - (3600 * %1) )

new pOnline[MAX_PLAYERS];

public OnPlayerConnect(playerid)
{
	pOnline[playerid] = gettime();
	
	return 1;
}



CMD:ilegram(playerid, cmdtext[])
{
	new str[128];
	
	Time_ConvertEx(gettime()-pOnline[playerid], h, m, s);
	
	format(str, sizeof(str), "Grasz %dh %dm %ds", h, m, s);
	
	SendClientMessage(playerid, -1, str);
	return 1;
}
Reply

Quote:
Originally Posted by ******
Посмотреть сообщение
No, I mean spinning the car. So instead of drifting you end up going backwards (like a reverse J-turn).
I didn't know what J-turn is, but after googling (The answer of your question is at point 4):

Let's say the vehicle's heading angle (The one generated from the velocity vectors) is 0 degrees, so the vehicle is heading north.

1) When going straight, drift angle is 0.
2) When the facing angle is acute to the heading angle (0 < angle < 90 or 270 < angle < 360), the vehicle's drift will be 0 < drift < 90 degrees.
3) When the facing angle is perpendicular to the heading angle (90 or -90 degrees), the vehicle's drift is 90 degrees.
4) When the facing angle is obtuse according to the heading angle, which means the vehicle is going backwards with some angle (0 < angle < 90 or 270 < angle < 360) the theoretical angle would be 90 < drift < 180 degrees (?!?!). In this case the real drift should be decreading after the facing angle reaches 90 degrees.
That's what these lines do:
pawn Код:
a[2] = (a[2] > 180.0) ? (floatsub(a[2], 180.0)) : (a[2]);
return (a[2] >= 90.0) ? (floatsub(180.0, a[2])) : (a[2]);
5) The facing angle is 180 degrees, while heading angle is 0. So theoretically the drift angle is 180 (?!?!).
But the vehicle's not drifting. So the lines above take case of this issue.

Basically:
1) Drift is 0.
2) Drift increases.
2) Drift reaches the max value.
4) Drift decreases.
5) Drift is again 0.

J-turn: Starts from 0 drift, continues to 90 (When the facing angle is perpendicular to the heading angle), decreases when the angle is > 90 and turns back to 0, when the difference between facing angle and heading angle is 180 degrees.

Same logic if the car continues to spin until reaches back to it's first stage (Facing angle = heading angle).
I hope I cleared something with this reply
Reply

Well this is the function that i made by a mistake but is working so...


pawn Код:
stock CreateRandomPosInZonePerimeter(Count, Float:MinX, Float:MinY, Float:MaxX, Float:MaxY)
{
    new Float:Width = floatabs(MaxX - MinX);
    new Float:Height = floatabs(MaxY - MinY);
    new Float:Perimeter = (Width * 2) + (Height * 2);
    for(new i = 0; i != Count; i++) {
        new Float:C[2],Float:dist = modulus(random(9000), Perimeter);
        if(dist <= Width) {
            C[0] = modulus(random(9000), Width) + MinX;
            C[1] = MinY;
        } else if(dist <= Width + Height) {
            C[0] = MaxX;
            C[1] = modulus(random(9000), Height) + MinY;
        } else if(dist <= (Width * 2) + Height) {
            C[0] = modulus(random(9000), Width) + MinX;
            C[1] = MaxY;
        } else {
            C[0] = MinX;
            C[1] = modulus(random(9000), Height) + MinY;
        }
    //Do something with X = (C[0]) Y = (C[1])
        printf("%f : %f",C[0],C[1]);
    }
}

pawn Код:
stock Float:modulus(Float:a, Float:b)
{
    while(a > b)
        a -= b;
    return a;
}
The modulus function i dont know if is ok :/



This return a random point * Count in a zone perimeter


Reply

That's nice @iJumbo, but instead of using a "while" loop inside the modulus function, you could do this:

pawn Код:
#define modulus(%0,%1) (floatround((%0)) % floatround((%1)))
Just some small but useful information.
Reply

Quote:
Originally Posted by iJumbo
Посмотреть сообщение
Well this is the function that i made by a mistake but is working so...


pawn Код:
stock CreateRandomPosInZonePerimeter(Count, Float:MinX, Float:MinY, Float:MaxX, Float:MaxY)
{
    new Float:Width = floatabs(MaxX - MinX);
    new Float:Height = floatabs(MaxY - MinY);
    new Float:Perimeter = (Width * 2) + (Height * 2);
    for(new i = 0; i != Count; i++) {
        new Float:C[2],Float:dist = modulus(random(9000), Perimeter);
        if(dist <= Width) {
            C[0] = modulus(random(9000), Width) + MinX;
            C[1] = MinY;
        } else if(dist <= Width + Height) {
            C[0] = MaxX;
            C[1] = modulus(random(9000), Height) + MinY;
        } else if(dist <= (Width * 2) + Height) {
            C[0] = modulus(random(9000), Width) + MinX;
            C[1] = MaxY;
        } else {
            C[0] = MinX;
            C[1] = modulus(random(9000), Height) + MinY;
        }
    //Do something with X = (C[0]) Y = (C[1])
        printf("%f : %f",C[0],C[1]);
    }
}

pawn Код:
stock Float:modulus(Float:a, Float:b)
{
    while(a > b)
        a -= b;
    return a;
}
The modulus function i dont know if is ok :/



This return a random point * Count in a zone perimeter


Can u make a code which returns an random point Count in the zone area??
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)