Useful Functions

Quote:
Originally Posted by newbie scripter
Посмотреть сообщение
Can u make a code which returns an random point Count in the zone area??
Quote:
Originally Posted by Konstantinos
Посмотреть сообщение
pawn Код:
forward Float: FRandomEx( Float: min, Float: max );

public OnFilterScriptInit( )
{
    new
        Float: rX = FRandomEx( 625.6991, 631.7022 ), // minX, maxX
        Float: rY = FRandomEx( -1895.0369, -1888.4351 ) // minY, maxY
    ;
   
    printf( "%f | %f", rX, rY );
    return 1;
}

stock Float: FRandomEx( Float: min, Float: max ) // The original RandomEx by ******, edited for the floats.
{
    return random( floatround( max ) - floatround( min ) ) + floatround( min );
}


@Emmet_ Thanks for the tips
Reply

Frankly yours uses a collection of some of the worst methods in coding combined - I'm surprised strcmp is "only" 3.5 times faster!
Reply

Quote:
Originally Posted by kaZax
View Post
No, look at the results again
There's no need - strcmp is still faster and it supports certain traits that yours does not (case sensitivity, length checking).

Anyways, I wouldn't suggest writing other variations of native functions, especially if the native function already works just as fine - it's bad coding practice!
Reply

Someone was asking in Scripting Help how to convert a Weapon ID into Object Model, It took me like 15 minutes to create this, because it was so confusing, tab & write, sometimes I get lost :P
but enjoy the script, it is tested

pawn Code:
stock GetWeaponModel(playerid)
{
    new
        _ObjectModel = 0;
    switch( GetPlayerWeapon( playerid ) )
    {
        case 1: _ObjectModel = 331;
        case 2: _ObjectModel = 333;
        case 3: _ObjectModel = 334;
        case 4: _ObjectModel = 335;
        case 5: _ObjectModel = 336;
        case 6: _ObjectModel = 337;
        case 7: _ObjectModel = 338;
        case 8: _ObjectModel = 339;
        case 9: _ObjectModel = 341;
        case 10: _ObjectModel = 321;
        case 11: _ObjectModel = 322;
        case 12: _ObjectModel = 323;
        case 13: _ObjectModel = 324;
        case 14: _ObjectModel = 325;
        case 15: _ObjectModel = 326;
        case 16: _ObjectModel = 342;
        case 17: _ObjectModel = 343;
        case 18: _ObjectModel = 344;
        case 22: _ObjectModel = 346;
        case 23: _ObjectModel = 347;
        case 24: _ObjectModel = 348;
        case 25: _ObjectModel = 349;
        case 26: _ObjectModel = 350;
        case 27: _ObjectModel = 351;
        case 28: _ObjectModel = 352;
        case 29: _ObjectModel = 353;
        case 30: _ObjectModel = 354;
        case 31: _ObjectModel = 356;
        case 32: _ObjectModel = 372;
        case 33: _ObjectModel = 357;
        case 34: _ObjectModel = 358;
        case 35: _ObjectModel = 359;
        case 36: _ObjectModel = 360;
        case 37: _ObjectModel = 361;
        case 38: _ObjectModel = 362;
        case 39: _ObjectModel = 363;
        case 40: _ObjectModel = 364;
        case 41: _ObjectModel = 365;
        case 42: _ObjectModel = 366;
        case 43: _ObjectModel = 367;
        case 44: _ObjectModel = 368;
        case 45: _ObjectModel = 369;
        case 46: _ObjectModel = 371;
    }
    return _ObjectModel;
}
Result
Code:
[13:08:37] 348 --> Deagle
[13:08:34] 356 --> M4A1
[13:09:16] 358 --> Sniper
Reply

Nice function, however you should use a static constant array instead of multiple switch values, like so:

pawn Code:
stock GetWeaponModel(playerid)
{
    static const MyArray[] =
    {
        0,
        331,
        333,
        334,
        // so on...
    };
    return MyArray[GetPlayerWeapon(playerid)]);
}
---

Swap any values (float, boolean) with this function:

pawn Code:
stock swap(&{Float,_}:var1, &{Float,_}:var2)
{
    #emit LREF.S.pri var1
    #emit LREF.S.alt var2
   
    #emit SREF.S.pri var2
    #emit SREF.S.alt var1
}
Reply

Months ago ..
http://forum.sa-mp.com/showpost.php?...postcount=1013
Reply

pawn Code:
// Many thanks to Y_Less, Nero, RyDeR for teaching me some assembly tips.
// Based on the SYSREQ.C calling method by Zeex - credits to him also.

forward @concat_fix(); @concat_fix()
{
    format("", 1, "");
}

stock concat(output[], len, const str[], {Float,_}:...)
{
    static
        string[512],
        start,
        end,
        args;

    args = numargs() * 4;

    if (args >= 16)
    {
        // Load the address of the last static parameter.
        #emit ADDR.pri str
        #emit STOR.pri start

        for (end = start + (args - 12); end > start; end -= 4)
        {
            // Load the parameter address of this function.
            #emit LREF.alt end
           
            // Push it onto the stack.
            #emit PUSH.alt
        }
        // Push the other arguments into "format".
        #emit PUSH.S str
        #emit PUSH.C 512
        #emit PUSH.C string
       
        // Push the number of arguments (in bytes).
        #emit PUSH.C args
       
        // Call the function.
        #emit SYSREQ.C format

        strcat(output, string, len);

        // Clear the stack. This is done by loading the previous stack
        // level before the function call.
        #emit LCTRL 5
        #emit SCTRL 4
       
        // Return the function and clean up the local variables.
        #emit RETN
    }
    return strcat(output, str, len);
}
pawn Code:
new str[64];
   
concat(str, sizeof(str), "I like to eat");
concat(str, sizeof(str), " %s and %s.", "bread", "butter");
   
print(str);
That will give us:

Code:
I like to eat bread and butter.
Speaking of which, I'm actually working on a method that pushes function parameters without a loop, but it's not ready yet.
Reply

Get Slot ID through WeaponID

PHP Code:
GetSlotWhithID(weaponid){
    switch(
weaponid){
    case 
0,1:return 0;
    case 
2,3,4,5,6,7,8,9:return 1;
    case 
22,23,24:return 2;
    case 
25,26,27:return 3;
    case 
28,29,32:return 4;
    case 
30,31:return 5;
    case 
33,34:return 6;
    case 
35,36,37,38:return 7;
    case 
16,17,18,39:return 8;
    case 
41,42,43:return 9;
    case 
10,11,12,13,14,15:return 10;
    case 
44,45,46:return 11;
    case 
40:return 12;
    }
    return -
1;

Quote:

Why is this?

I came in handy for creating antiweaponhack.
Reply

What's wrong with an array, like one of the many arrays already released for exactly this purpose?
Reply

This function checks if the specified game text is faulty or can cause crashes.

pawn Code:
static stock isFaultyGameText(const string[])
{
    new
        i,
        len;

    while ((i = strfind(string, "~", true, (!i) ? (0) : (i + 1))) != -1) {
        len++;
    }
    if (len % 2 != 0)
        return 1;

    else for (i = 0, len = strlen(string); i != len; i ++)
    {
        if (string[i] != '~')
            continue;
                   
        else switch (string[i + 1])
        {
            case 'k', 'K':
            {
                if (!string[(i += strfind(string, "~", true, i + 4))])
                    break;

                continue;
            }
            case 'a'..'j', 'l'..'z', 'A'..'J', 'L'..'Z':
            {
                if (string[(i += 2)] == '~')
                    continue;

                return 1;
            }
            default:
            {
                return 1;
            }
        }
    }
    return 0;
}
pawn Code:
main()
{
    if (isFaultyGameText("I am a ~r~boss")) print("1");
    if (isFaultyGameText("Press ~k~~VEHICLE_FIREWEAPON_ALT~ to answer your phone.")) print("2");
    if (isFaultyGameText("I like to eat ~~cookies.")) print("3");
    if (isFaultyGameText("This is ~r~red~w~ and this is ~y~yellow.")) print("4");
    if (isFaultyGameText("Dude, ~r~~where's ~~r~~ my car?")) print("5");
}
Outputs:

Code:
3
5
Reply

I believe this will cause infinite-loops, I strongly suggest you retest everything:
pawn Code:
isFaultyGameText("~r~")
Also, I don't think you need all that jazz. As long as the amount of tildes are even, the gametext or textdraw won't really cause bugs (even with wrong letters in-between). I'm simply using this code in my gamemode:
pawn Code:
stock isValidGameText(szText[]) {
    new
        iTildes
    ;
    for(new i = 0; szText[i] != EOS; ++i) {
        if(szText[i] == '~') {
            iTildes++;
        }
    }
    return !(iTildes & 0b1);
}
Reply

Made fast a version which uses the header, is around the speed as the first (macro)
pawn Код:
stock SCM4(playerid, color, form[], {Float, _}: ...) {
    #pragma unused form

    static
        tmp[145]
    ;
    new
        t1 = playerid,
        t2 = color
    ;
    const
        n4 = -4,
        n16 = -16,
        size = sizeof tmp
    ;
    #emit stack 28
    #emit push.c size
    #emit push.c tmp
    #emit stack n4
    #emit sysreq.c format
    #emit stack n16

    return SendClientMessage(t1, t2, tmp);
}
Reply

Nice job!

Edit: I did some searching around and found that Slice also did it without loops:

http://forum.sa-mp.com/showthread.ph...tf#post2041134
Reply

Quote:
Originally Posted by ******
Посмотреть сообщение
The stack abuse method is very interesting though. I wouldn't have thought of that, Slice's method is how I would have done it (the "proper" way), but you couldn't do it Nero_3D's way without "playerid" and "color" because there's not enough stack space without destrying the frame header.
I also used a similar method as his, except that he stored the frame header and I didn't.. . The old fashioned loop and push would have to suffice for now, since copying the stack could be real challenging.

---

WordWrap
An improvement of the function I've posted years back - wraps text into a destination string.

pawn Код:
stock WordWrap(source[], bool:spaces, dest[], size = sizeof(dest), chars = 20)
{
    new length = strlen(source);

    strcat((dest[0] = '\0', dest), source, size);

    if (length <= 0)
        return 0;

    while (--length != 0) if ((length % chars) == 0)
    {
        if (!spaces) {
            strins(dest, "\r\n", length, size);
        }
        else for (new i = length; dest[i] != '\0'; i ++) if (dest[i] == ' ' && dest[i + 1] != '\r') {
            strins(dest, "\r\n", i + 1, size); break;
        }
    }
    return 1;
}
An example:

pawn Код:
new dest[128];

WordWrap("I like to eat jelly donuts.", true, dest, sizeof(dest), 10);
print(dest);

WordWrap("I like to eat jelly donuts.", false, dest, sizeof(dest), 10);
print(dest);
Output:

Код:
I like
to eat
jelly 
donuts.
Код:
I lik
e to
eat j
elly 
donut
s.
Reply

Nice, that method does gives me an idea though.

---

Here's a function I've written for my mode.

INI_WriteData
Allows you to write arguments into an INI file - y_ini only.

pawn Код:
stock INI_WriteData(INI:file, const fmat[], {Float,_}:...)
{
    static
        i,
        ch,
        idx,
        str[32],
        string[YSI_MAX_STRING];

    if (((numargs() - 2) / 2) != strlen(fmat))
        return printf("** Warning: %d specifiers, but only %d arguments.", strlen(fmat), (numargs() - 2) / 2);

    while ((ch = fmat[i++]))
    {
        if (!('z' >= ch >= 'a'))
            continue;

        va_getstring(str, (idx = ((i - 1) << 1) + 2));

        switch (ch)
        {
            case 'd', 'i':
                INI_WriteInt(file, str, getarg(idx + 1));

            case 'f':
                INI_WriteFloat(file, str, Float:getarg(idx + 1));

            case 'h':
                INI_WriteHex(file, str, getarg(idx + 1));

            case 's':
                INI_WriteString(file, str, (va_getstring(string, idx + 1), string));

            default:
                printf("** Warning: Invalid specifier '%c'.", ch);
        }
    }
    return 1;
}
Example:

pawn Код:
new
    INI:file = INI_Open("file.ini");

INI_WriteData(file, "sdf",
    "String", "My name is Emmet.",
    "Integer", 50,
    "Float", 73.8
);

INI_Close(file);
And the output:

Код:
Float = 73.800003
Integer = 50
String = My name is Emmet.
Reply

@Emmet_ Awwww sweeet!
Reply

Nice, I suppose yours would be better since it has the extras!

Would one for reading be possible to make, based on how Y_INI works?
Reply

Was just playing with PAWN this evening and came out wit this, using strreplace you could use Gametext Colours in SendClientMessage and any function that uses HTML color codes.

pawn Код:
#include <a_samp>
#include <strlib> //by Slice, not Westie

main()
{
    new
        formatStr[184];
    formatStr = "~r~ Red\n";
    strcat(formatStr, "~g~ Green\n"), strcat(formatStr, "~b~ Blue\n"),
    strcat(formatStr, "~w~ White\n"), strcat(formatStr, "~y~ Yellow\n"),
    strcat(formatStr, "~p~ Purple\n"), strcat(formatStr, "~bl~ Black\n"),
    strcat(formatStr, "~c~ Cyan\n"), strcat(formatStr, "~o~ Orange\n"),
    strcat(formatStr, "~pk~ Pink\n"), strcat(formatStr, "~lb~ Light Blue\n"),
    strcat(formatStr, "~br~ Brown\n"), UseGameTextColours(formatStr, sizeof(formatStr));
    print(formatStr);

}

stock UseGameTextColours( string[], size = sizeof(string) )
{
    strreplace(string, "~r~", "{f90303}", false, 0, -1, size); //red
    strreplace(string, "~g~", "{03f90a}", false, 0, -1, size); //green
    strreplace(string, "~b~", "{030af9}", false, 0, -1, size); //blue
    strreplace(string, "~w~", "{ffffff}", false, 0, -1, size); //white
    strreplace(string, "~y~", "{f0ff00}", false, 0, -1, size); //yellow
    strreplace(string, "~p~", "{8000ff}", false, 0, -1, size); //purple
    strreplace(string, "~bl~", "{000000}", false, 0, -1, size); //black
    strreplace(string, "~c~", "{00FFFF}", false, 0, -1, size); //cyan
    strreplace(string, "~o~", "{FF9900}", false, 0, -1, size); //orange
    strreplace(string, "~pk~", "{FF3399}", false, 0, -1, size); //pink
    strreplace(string, "~lb~", "{66CCFF}", false, 0, -1, size); //lightblue
    strreplace(string, "~br~", "{CC6600}", false, 0, -1, size); //brown
    //just follow the format above if you want to add colour, just playing with pawn :D
}
pawn Код:
{f90303} Red
{03f90a} Green
{030af9} Blue
{ffffff} White
{f0ff00} Yellow
{8000ff} Purple
{000000} Black
{00FFFF} Cyan
{FF9900} Orange
{FF3399} Pink
{66CCFF} Light Blue
{CC6600} Brown
Reply

Quote:
Originally Posted by pds2k12
Посмотреть сообщение
Was just playing with PAWN this evening and came out wit this, using strreplace you could use Gametext Colours in SendClientMessage and any function that uses HTML color codes.

pawn Код:
code
ok?? post in til or something. and you can already do this in y_colours..
Reply

Here's a "SetPlayerAnimationIndex" function.

I found it pretty pointless to store 256 cells of memory for the animation name and library, so I figured, why not save it by the index?

pawn Код:
stock SetPlayerAnimationIndex(playerid, index, Float:fDelta, loop, lockx, locky, freeze, time)
{
    static
        name[32],
        library[32]
    ;
    if (1 <= index <= 1812)
    {
        GetAnimationName(index, name, sizeof name, library, sizeof library);
        ApplyAnimation(playerid, library, name, fDelta, loop, lockx, locky, freeze, time);
    }
    return 1;
}
Reply


Forum Jump:


Users browsing this thread: 39 Guest(s)