[GameMode] Death Match ( Zcmd - Sscanf2 - Foreach - Streamer )
#1

Removido ... link novo : https://sampforum.blast.hk/showthread.php?tid=484864
Reply
#2

First o/

Bonzin..

Creditos a [ZNS]Alphadog[750] por algumas funcoes..
Reply
#3

/disarmar й osso.

Bom GM
Reply
#4

Gostei

REP +;

PS: й /desarmar :]]
Reply
#5

Otimo GM ...
Reply
#6

Muito bom, Diogo .

Reskydo.

Sky = Put*
Reply
#7

Esta tudo bem, bom trabalho

Apenas algumas coisas, vocк tem que olhar os Macros e o Consumo de celulas com valores exedidos

Reputado
Reply
#8

Excelente Gamemode, parabens.
Reply
#9

Quote:
Originally Posted by _SysTeM_OFF
View Post
First o/

Bonzin..

Creditos a [ZNS]Alphadog[750] por algumas funcoes..
kkk' sim a API_Teleporte ajudo a poupar muitas linhas jaja eu do o edit nos crйditos

Quote:
Originally Posted by HumildadeAgain
View Post
/disarmar й osso.

Bom GM
Rsrs e q meu portuguкs nгo e boum ^^

Quote:
Originally Posted by iSmir
View Post
Gostei

REP +;

PS: й /desarmar :]]
meu portuguкs nгo e boum ^^


Quote:
Originally Posted by Don_Speed
View Post
Otimo GM ...
Vlw

Quote:
Originally Posted by @Riichard
View Post
Muito bom, Diogo .

Reskydo.

Sky = Put*
kk Vlw

Quote:
Originally Posted by Schocc
View Post
Esta tudo bem, bom trabalho

Apenas algumas coisas, vocк tem que olhar os Macros e o Consumo de celulas com valores exedidos
Okay,se eu fizer uma nova versгo eu arrumo os Macros e tambйm o Consumo Das Cйlulas ^^
Reply
#10

vocк pode postar as includes do GM?

obrigado '-'
Reply
#11

Cades os crйditos do alphadog ? sistemas do gm plagiados do bloody vegas!
Reply
#12

Quote:
Originally Posted by RoacH`
View Post
Cades os crйditos do alphadog ? sistemas do gm plagiados do bloody vegas!
a funзгo API_TELEPORT eu botei os crйditos dele.
Mas o comando /mae e super simples de se fazer ^^

Quote:
Originally Posted by Caio_Freeze
View Post
vocк pode postar as includes do GM?

obrigado '-'
kkk'

sscanf2 :
pawn Code:
/*  
 *  Version: MPL 1.1
 *  
 *  The contents of this file are subject to the Mozilla Public License Version
 *  1.1 (the "License"); you may not use this file except in compliance with
 *  the License. You may obtain a copy of the License at
 *  http://www.mozilla.org/MPL/
 *  
 *  Software distributed under the License is distributed on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 *  for the specific language governing rights and limitations under the
 *  License.
 *  
 *  The Original Code is the sscanf 2.0 SA:MP plugin.
 *  
 *  The Initial Developer of the Original Code is Alex "Y_Less" Cole.
 *  Portions created by the Initial Developer are Copyright © 2010
 *  the Initial Developer. All Rights Reserved.
 *  
 *  Contributor(s):
 *  
 *  Special Thanks to:
 *  
 *  SA:MP Team past, present and future
 */


#define SSCANF:%0(%1) sscanf_%0(%1);public sscanf_%0(%1)

#if defined sscanf
    #error sscanf (possibly the PAWN version) already defined.
#endif
native sscanf(const data[], const format[], {Float,_}:...);
native unformat(const data[], const format[], {Float,_}:...) = sscanf;
native SSCANF_Init(players, invalid, len);
native SSCANF_Join(playerid, const name[], npc);
native SSCANF_Leave(playerid);

static stock
    SSCANF_gInit = 0xFFFFFFFF,
    SSCANF_gOPC,
    SSCANF_gOPDC;

public OnFilterScriptInit()
{
    //printf("OnFilter");
    SSCANF_Init(GetMaxPlayers(), INVALID_PLAYER_ID, MAX_PLAYER_NAME);
    SSCANF_gInit = funcidx("SSCANF_OnGameModeInit") != -1;
    SSCANF_gOPC  = funcidx("SSCANF_OnPlayerConnect") != -1;
    SSCANF_gOPDC = funcidx("SSCANF_OnPlayerDisconnect") != -1;
    return CallLocalFunction("SSCANF_OnFilterScriptInit", "");
}

#if defined _ALS_OnFilterScriptInit
    #undef OnFilterScriptInit
#else
    #define _ALS_OnFilterScriptInit
#endif
#define OnFilterScriptInit SSCANF_OnFilterScriptInit

forward OnFilterScriptInit();

public OnGameModeInit()
{
    //printf("OnGameo");
    if (SSCANF_gInit == -1)
    {
        SSCANF_Init(GetMaxPlayers(), INVALID_PLAYER_ID, MAX_PLAYER_NAME);
        SSCANF_gInit = funcidx("SSCANF_OnGameModeInit") != -1;
        SSCANF_gOPC  = funcidx("SSCANF_OnPlayerConnect") != -1;
        SSCANF_gOPDC = funcidx("SSCANF_OnPlayerDisconnect") != -1;
    }
    if (SSCANF_gInit)
    {
        // Can't do the clever assembly version without y_amx.
        /*#emit PUSH.S   reason
        #emit PUSH.S   playerid
        #emit PUSH.C   8
        #emit LCTRL    6
        #emit ADD.C    28
        #emit PUSH.pri
        #emit LOAD.pri SSCANF_gOPDC
        #emit SCTRL    6
        #emit RETN*/

        return CallLocalFunction("SSCANF_OnGameModeInit", "");
    }
    return 1;
}

#if defined _ALS_OnGameModeInit
    #undef OnGameModeInit
#else
    #define _ALS_OnGameModeInit
#endif
#define OnGameModeInit SSCANF_OnGameModeInit

forward OnGameModeInit();

public OnPlayerConnect(playerid)
{
    new
        name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, sizeof (name));
    SSCANF_Join(playerid, name, IsPlayerNPC(playerid));
    if (SSCANF_gOPC)
    {
        /*#emit PUSH.S   playerid
        #emit PUSH.C   4
        #emit LCTRL    6
        #emit ADD.C    28
        #emit PUSH.pri
        #emit LOAD.pri SSCANF_gOPC
        #emit SCTRL    6
        #emit RETN*/

        return CallLocalFunction("SSCANF_OnPlayerConnect", "i", playerid);
    }
    return 1;
}

#if defined _ALS_OnPlayerConnect
    #undef OnPlayerConnect
#else
    #define _ALS_OnPlayerConnect
#endif
#define OnPlayerConnect SSCANF_OnPlayerConnect

forward OnPlayerConnect(playerid);

public OnPlayerDisconnect(playerid, reason)
{
    new
        ret = 1;
    if (SSCANF_gOPDC)
    {
        /*#emit PUSH.S   reason
        #emit PUSH.S   playerid
        #emit PUSH.C   8
        #emit LCTRL    6
        #emit ADD.C    28
        #emit PUSH.pri
        #emit LOAD.pri SSCANF_gOPDC
        #emit SCTRL    6
        #emit RETN*/

        ret = CallLocalFunction("SSCANF_OnPlayerDisconnect", "ii", playerid, reason);
    }
    SSCANF_Leave(playerid);
    return ret;
}

#if defined _ALS_OnPlayerDisconnect
    #undef OnPlayerDisconnect
#else
    #define _ALS_OnPlayerDisconnect
#endif
#define OnPlayerDisconnect SSCANF_OnPlayerDisconnect

forward OnPlayerDisconnect(playerid, reason);

#define SSCANF_Init
#define SSCANF_Join
#define SSCANF_Leave

#define extract%0->%1; EXTRN%1;unformat(_:EXTRZ:EXTRX:%0,##,%1,,);
#define unformat(_:EXTRZ:EXTRX:%0,##,%1);%2else%3; if (unformat(_:EXTRX:%0,##,%1))%3;

#define EXTRX:%0##,%9new%1,%2) EXTRY:%0##,|||%1|||%2)
#define EXTRY: EXTR8:EXTR9:EXTR0:EXTR1:EXTR2:EXTR3:EXTR4:

#define EXTR8:EXTR9:EXTR0:EXTR1:EXTR2:EXTR3:EXTR4:%0##%1,%2|||%6:%3=%9|||%4) %6_EXTRO:%0##%1,%2|||%3=%9|||%4)
#define EXTR9:EXTR0:EXTR1:EXTR2:EXTR3:EXTR4:%0##%1,%2|||%3=%9|||%4) __EXTRO:%0##%1,%2|||%3=%9|||%4)
#define EXTR0:EXTR1:EXTR2:EXTR3:EXTR4:%0##%1,%2|||%6:%3[%7]|||%4) %6_EXTRW:%0##%1,%2|||%3[%7]|||%4)
#define EXTR1:EXTR2:EXTR3:EXTR4:%0##%1,%2|||%3[%7]|||%4) __EXTRW:%0##%1,%2|||%3|||%4)
#define EXTR2:EXTR3:EXTR4:%0##%1,%2|||%6:%3|||%4) %6_EXTRN:%0##%1,%2|||%3|||%4)
#define EXTR3:EXTR4:%0##%1,,%2||||||%4) %0##%1,%2)
#define EXTR4:%0##%1,%2|||%3|||%4) __EXTRN:%0##%1,%2|||%3|||%4)

// Optional specifiers.
#define __EXTRO:%0##%1,%2|||%3=%9|||%4,%5) EXTRY:%0##%1I"("#%9")"#,%2,%3|||%4|||%5)
#define Float_EXTRO:%0##%1,%2|||%3=%9|||%4,%5) EXTRY:%0##%1F"("#%9")"#,%2,%3|||%4|||%5)
#define player_EXTRO:%0##%1,%2|||%3=%9|||%4,%5) EXTRY:%0##%1U"("#%9")"#,%2,%3|||%4|||%5)
#define string_EXTRO:%0##%1,%2|||%3[%7]=%9|||%4,%5) EXTRY:%0##%1S"("#%9")"#[%7],%2,%3|||%4|||%5)

// Normal specifiers (the double underscore is to work for "_:".
#define __EXTRN:%0##%1,%2|||%3|||%4,%5) EXTRY:%0##%1i,%2,%3|||%4|||%5)
#define Float_EXTRN:%0##%1,%2|||%3|||%4,%5) EXTRY:%0##%1f,%2,%3|||%4|||%5)
#define player_EXTRN:%0##%1,%2|||%3|||%4,%5) EXTRY:%0##%1u,%2,%3|||%4|||%5)
//#define string_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1s[%7],%2,%3|||%4|||%5)

// Array versions of normal specifiers.
#define __EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1a<i>[%7],%2,%3|||%4|||%5)
#define Float_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1a<f>[%7],%2,%3|||%4|||%5)
#define player_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1a<u>[%7],%2,%3|||%4|||%5)
#define string_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1s[%7],%2,%3|||%4|||%5)

// Get rid of excess leading space which causes warnings.
#define EXTRN%0new%1; new%1;

#if !defined string
    #define string:
#endif

#define player:

#define hex:
#define hex_EXTRO:%0##%1,%2|||%3=%9|||%4,%5) EXTRY:%0##%1H"("#%9")"#,%2,%3|||%4|||%5)
#define hex_EXTRN:%0##%1,%2|||%3|||%4,%5) EXTRY:%0##%1h,%2,%3|||%4|||%5)
#define hex_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1a<h>[%7],%2,%3|||%4|||%5)

#define bin:
#define bin_EXTRO:%0##%1,%2|||%3=%9|||%4,%5) EXTRY:%0##%1B"("#%9")"#,%2,%3|||%4|||%5)
#define bin_EXTRN:%0##%1,%2|||%3|||%4,%5) EXTRY:%0##%1b,%2,%3|||%4|||%5)
#define bin_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1a<b>[%7],%2,%3|||%4|||%5)

#define kustom:%0<%1> %0
#define kustom_EXTRO:%0##%1,%2|||%3<%8>=%9|||%4,%5) EXTRY:%0##%1K<%8>"("#%9")"#,%2,%3|||%4|||%5)
#define kustom_EXTRN:%0##%1,%2|||%3<%8>|||%4,%5) EXTRY:%0##%1k<%8>,%2,%3|||%4|||%5)
//#define bin_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1a<b>[%7],%2,%3|||%4|||%5)

SSCANF:weapon(string[])
{
    // This function is VERY basic, needs VASTLY improving to detect variations.
    if ('0' <= string[0] <= '9')
    {
        new
            ret = strval(string);
        if (0 <= ret <= 18 || 22 <= ret <= 46)
        {
            return ret;
        }
    }
    else if (!strcmp(string, "Unarmed")) return 0;
    else if (!strcmp(string, "Brass Knuckles")) return 1;
    else if (!strcmp(string, "Golf Club")) return 2;
    else if (!strcmp(string, "Night Stick")) return 3;
    else if (!strcmp(string, "Knife")) return 4;
    else if (!strcmp(string, "Baseball Bat")) return 5;
    else if (!strcmp(string, "Shovel")) return 6;
    else if (!strcmp(string, "Pool cue")) return 7;
    else if (!strcmp(string, "Katana")) return 8;
    else if (!strcmp(string, "Chainsaw")) return 9;
    else if (!strcmp(string, "Purple Dildo")) return 10;
    else if (!strcmp(string, "White Dildo")) return 11;
    else if (!strcmp(string, "Long White Dildo")) return 12;
    else if (!strcmp(string, "White Dildo 2")) return 13;
    else if (!strcmp(string, "Flowers")) return 14;
    else if (!strcmp(string, "Cane")) return 15;
    else if (!strcmp(string, "Grenades")) return 16;
    else if (!strcmp(string, "Tear Gas")) return 17;
    else if (!strcmp(string, "Molotovs")) return 18;
    else if (!strcmp(string, "Pistol")) return 22;
    else if (!strcmp(string, "Silenced Pistol")) return 23;
    else if (!strcmp(string, "Desert Eagle")) return 24;
    else if (!strcmp(string, "Shotgun")) return 25;
    else if (!strcmp(string, "Sawn Off Shotgun")) return 26;
    else if (!strcmp(string, "Combat Shotgun")) return 27;
    else if (!strcmp(string, "Micro Uzi")) return 28;
    else if (!strcmp(string, "Mac 10")) return 28;
    else if (!strcmp(string, "MP5")) return 29;
    else if (!strcmp(string, "AK47")) return 30;
    else if (!strcmp(string, "M4")) return 31;
    else if (!strcmp(string, "Tec9")) return 32;
    else if (!strcmp(string, "Rifle")) return 33;
    else if (!strcmp(string, "Sniper Rifle")) return 34;
    else if (!strcmp(string, "RPG")) return 35;
    else if (!strcmp(string, "Missile Launcher")) return 36;
    else if (!strcmp(string, "Flame Thrower")) return 37;
    else if (!strcmp(string, "Minigun")) return 38;
    else if (!strcmp(string, "Sachel Charges")) return 39;
    else if (!strcmp(string, "Detonator")) return 40;
    else if (!strcmp(string, "Spray Paint")) return 41;
    else if (!strcmp(string, "Fire Extinguisher")) return 42;
    else if (!strcmp(string, "Camera")) return 43;
    else if (!strcmp(string, "Nightvision Goggles")) return 44;
    else if (!strcmp(string, "Thermal Goggles")) return 45;
    else if (!strcmp(string, "Parachute")) return 46;
    return -1;
}

SSCANF:vehicle(string[])
{
    // This function is VERY basic, needs VASTLY improving to detect variations.
    if ('0' <= string[0] <= '9')
    {
        new
            ret = strval(string);
        if (400 <= ret <= 611)
        {
            return ret;
        }
    }
    else if (!strcmp(string, "Landstalker")) return 400;
    else if (!strcmp(string, "Bravura")) return 401;
    else if (!strcmp(string, "Buffalo")) return 402;
    else if (!strcmp(string, "Linerunner")) return 403;
    else if (!strcmp(string, "Perenniel")) return 404;
    else if (!strcmp(string, "Sentinel")) return 405;
    else if (!strcmp(string, "Dumper")) return 406;
    else if (!strcmp(string, "Firetruck")) return 407;
    else if (!strcmp(string, "Trashmaster")) return 408;
    else if (!strcmp(string, "Stretch")) return 409;
    else if (!strcmp(string, "Manana")) return 410;
    else if (!strcmp(string, "Infernus")) return 411;
    else if (!strcmp(string, "Voodoo")) return 412;
    else if (!strcmp(string, "Pony")) return 413;
    else if (!strcmp(string, "Mule")) return 414;
    else if (!strcmp(string, "Cheetah")) return 415;
    else if (!strcmp(string, "Ambulance")) return 416;
    else if (!strcmp(string, "Leviathan")) return 417;
    else if (!strcmp(string, "Moonbeam")) return 418;
    else if (!strcmp(string, "Esperanto")) return 419;
    else if (!strcmp(string, "Taxi")) return 420;
    else if (!strcmp(string, "Washington")) return 421;
    else if (!strcmp(string, "Bobcat")) return 422;
    else if (!strcmp(string, "Mr Whoopee")) return 423;
    else if (!strcmp(string, "BF Injection")) return 424;
    else if (!strcmp(string, "Hunter")) return 425;
    else if (!strcmp(string, "Premier")) return 426;
    else if (!strcmp(string, "Enforcer")) return 427;
    else if (!strcmp(string, "Securicar")) return 428;
    else if (!strcmp(string, "Banshee")) return 429;
    else if (!strcmp(string, "Predator")) return 430;
    else if (!strcmp(string, "Bus")) return 431;
    else if (!strcmp(string, "Rhino")) return 432;
    else if (!strcmp(string, "Barracks")) return 433;
    else if (!strcmp(string, "Hotknife")) return 434;
    else if (!strcmp(string, "Article Trailer")) return 435;
    else if (!strcmp(string, "Previon")) return 436;
    else if (!strcmp(string, "Coach")) return 437;
    else if (!strcmp(string, "Cabbie")) return 438;
    else if (!strcmp(string, "Stallion")) return 439;
    else if (!strcmp(string, "Rumpo")) return 440;
    else if (!strcmp(string, "RC Bandit")) return 441;
    else if (!strcmp(string, "Romero")) return 442;
    else if (!strcmp(string, "Packer")) return 443;
    else if (!strcmp(string, "Monster")) return 444;
    else if (!strcmp(string, "Admiral")) return 445;
    else if (!strcmp(string, "Squallo")) return 446;
    else if (!strcmp(string, "Seasparrow")) return 447;
    else if (!strcmp(string, "Pizzaboy")) return 448;
    else if (!strcmp(string, "Tram")) return 449;
    else if (!strcmp(string, "Article Trailer 2")) return 450;
    else if (!strcmp(string, "Turismo")) return 451;
    else if (!strcmp(string, "Speeder")) return 452;
    else if (!strcmp(string, "Reefer")) return 453;
    else if (!strcmp(string, "Tropic")) return 454;
    else if (!strcmp(string, "Flatbed")) return 455;
    else if (!strcmp(string, "Yankee")) return 456;
    else if (!strcmp(string, "Caddy")) return 457;
    else if (!strcmp(string, "Solair")) return 458;
    else if (!strcmp(string, "Berkley's RC Van")) return 459;
    else if (!strcmp(string, "Skimmer")) return 460;
    else if (!strcmp(string, "PCJ-600")) return 461;
    else if (!strcmp(string, "Faggio")) return 462;
    else if (!strcmp(string, "Freeway")) return 463;
    else if (!strcmp(string, "RC Baron")) return 464;
    else if (!strcmp(string, "RC Raider")) return 465;
    else if (!strcmp(string, "Glendale")) return 466;
    else if (!strcmp(string, "Oceanic")) return 467;
    else if (!strcmp(string, "Sanchez")) return 468;
    else if (!strcmp(string, "Sparrow")) return 469;
    else if (!strcmp(string, "Patriot")) return 470;
    else if (!strcmp(string, "Quad")) return 471;
    else if (!strcmp(string, "Coastguard")) return 472;
    else if (!strcmp(string, "Dinghy")) return 473;
    else if (!strcmp(string, "Hermes")) return 474;
    else if (!strcmp(string, "Sabre")) return 475;
    else if (!strcmp(string, "Rustler")) return 476;
    else if (!strcmp(string, "ZR-350")) return 477;
    else if (!strcmp(string, "Walton")) return 478;
    else if (!strcmp(string, "Regina")) return 479;
    else if (!strcmp(string, "Comet")) return 480;
    else if (!strcmp(string, "BMX")) return 481;
    else if (!strcmp(string, "Burrito")) return 482;
    else if (!strcmp(string, "Camper")) return 483;
    else if (!strcmp(string, "Marquis")) return 484;
    else if (!strcmp(string, "Baggage")) return 485;
    else if (!strcmp(string, "Dozer")) return 486;
    else if (!strcmp(string, "Maverick")) return 487;
    else if (!strcmp(string, "SAN News Maverick")) return 488;
    else if (!strcmp(string, "Rancher")) return 489;
    else if (!strcmp(string, "FBI Rancher")) return 490;
    else if (!strcmp(string, "Virgo")) return 491;
    else if (!strcmp(string, "Greenwood")) return 492;
    else if (!strcmp(string, "Jetmax")) return 493;
    else if (!strcmp(string, "Hotring Racer")) return 494;
    else if (!strcmp(string, "Sandking")) return 495;
    else if (!strcmp(string, "Blista Compact")) return 496;
    else if (!strcmp(string, "Police Maverick")) return 497;
    else if (!strcmp(string, "Boxville")) return 498;
    else if (!strcmp(string, "Benson")) return 499;
    else if (!strcmp(string, "Mesa")) return 500;
    else if (!strcmp(string, "RC Goblin")) return 501;
    else if (!strcmp(string, "Hotring Racer")) return 502;
    else if (!strcmp(string, "Hotring Racer")) return 503;
    else if (!strcmp(string, "Bloodring Banger")) return 504;
    else if (!strcmp(string, "Rancher")) return 505;
    else if (!strcmp(string, "Super GT")) return 506;
    else if (!strcmp(string, "Elegant")) return 507;
    else if (!strcmp(string, "Journey")) return 508;
    else if (!strcmp(string, "Bike")) return 509;
    else if (!strcmp(string, "Mountain Bike")) return 510;
    else if (!strcmp(string, "Beagle")) return 511;
    else if (!strcmp(string, "Cropduster")) return 512;
    else if (!strcmp(string, "Stuntplane")) return 513;
    else if (!strcmp(string, "Tanker")) return 514;
    else if (!strcmp(string, "Roadtrain")) return 515;
    else if (!strcmp(string, "Nebula")) return 516;
    else if (!strcmp(string, "Majestic")) return 517;
    else if (!strcmp(string, "Buccaneer")) return 518;
    else if (!strcmp(string, "Shamal")) return 519;
    else if (!strcmp(string, "Hydra")) return 520;
    else if (!strcmp(string, "FCR-900")) return 521;
    else if (!strcmp(string, "NRG-500")) return 522;
    else if (!strcmp(string, "HPV1000")) return 523;
    else if (!strcmp(string, "Cement Truck")) return 524;
    else if (!strcmp(string, "Towtruck")) return 525;
    else if (!strcmp(string, "Fortune")) return 526;
    else if (!strcmp(string, "Cadrona")) return 527;
    else if (!strcmp(string, "FBI Truck")) return 528;
    else if (!strcmp(string, "Willard")) return 529;
    else if (!strcmp(string, "Forklift")) return 530;
    else if (!strcmp(string, "Tractor")) return 531;
    else if (!strcmp(string, "Combine Harvester")) return 532;
    else if (!strcmp(string, "Feltzer")) return 533;
    else if (!strcmp(string, "Remington")) return 534;
    else if (!strcmp(string, "Slamvan")) return 535;
    else if (!strcmp(string, "Blade")) return 536;
    else if (!strcmp(string, "Freight (Train)")) return 537;
    else if (!strcmp(string, "Brownstreak (Train)")) return 538;
    else if (!strcmp(string, "Vortex")) return 539;
    else if (!strcmp(string, "Vincent")) return 540;
    else if (!strcmp(string, "Bullet")) return 541;
    else if (!strcmp(string, "Clover")) return 542;
    else if (!strcmp(string, "Sadler")) return 543;
    else if (!strcmp(string, "Firetruck LA")) return 544;
    else if (!strcmp(string, "Hustler")) return 545;
    else if (!strcmp(string, "Intruder")) return 546;
    else if (!strcmp(string, "Primo")) return 547;
    else if (!strcmp(string, "Cargobob")) return 548;
    else if (!strcmp(string, "Tampa")) return 549;
    else if (!strcmp(string, "Sunrise")) return 550;
    else if (!strcmp(string, "Merit")) return 551;
    else if (!strcmp(string, "Utility Van")) return 552;
    else if (!strcmp(string, "Nevada")) return 553;
    else if (!strcmp(string, "Yosemite")) return 554;
    else if (!strcmp(string, "Windsor")) return 555;
    else if (!strcmp(string, "Monster \"A\"")) return 556;
    else if (!strcmp(string, "Monster \"B\"")) return 557;
    else if (!strcmp(string, "Uranus")) return 558;
    else if (!strcmp(string, "Jester")) return 559;
    else if (!strcmp(string, "Sultan")) return 560;
    else if (!strcmp(string, "Stratum")) return 561;
    else if (!strcmp(string, "Elegy")) return 562;
    else if (!strcmp(string, "Raindance")) return 563;
    else if (!strcmp(string, "RC Tiger")) return 564;
    else if (!strcmp(string, "Flash")) return 565;
    else if (!strcmp(string, "Tahoma")) return 566;
    else if (!strcmp(string, "Savanna")) return 567;
    else if (!strcmp(string, "Bandito")) return 568;
    else if (!strcmp(string, "Freight Flat Trailer (Train)")) return 569;
    else if (!strcmp(string, "Streak Trailer (Train)")) return 570;
    else if (!strcmp(string, "Kart")) return 571;
    else if (!strcmp(string, "Mower")) return 572;
    else if (!strcmp(string, "Dune")) return 573;
    else if (!strcmp(string, "Sweeper")) return 574;
    else if (!strcmp(string, "Broadway")) return 575;
    else if (!strcmp(string, "Tornado")) return 576;
    else if (!strcmp(string, "AT400")) return 577;
    else if (!strcmp(string, "DFT-30")) return 578;
    else if (!strcmp(string, "Huntley")) return 579;
    else if (!strcmp(string, "Stafford")) return 580;
    else if (!strcmp(string, "BF-400")) return 581;
    else if (!strcmp(string, "Newsvan")) return 582;
    else if (!strcmp(string, "Tug")) return 583;
    else if (!strcmp(string, "Petrol Trailer")) return 584;
    else if (!strcmp(string, "Emperor")) return 585;
    else if (!strcmp(string, "Wayfarer")) return 586;
    else if (!strcmp(string, "Euros")) return 587;
    else if (!strcmp(string, "Hotdog")) return 588;
    else if (!strcmp(string, "Club")) return 589;
    else if (!strcmp(string, "Freight Box Trailer (Train)")) return 590;
    else if (!strcmp(string, "Article Trailer 3")) return 591;
    else if (!strcmp(string, "Andromada")) return 592;
    else if (!strcmp(string, "Dodo")) return 593;
    else if (!strcmp(string, "RC Cam")) return 594;
    else if (!strcmp(string, "Launch")) return 595;
    else if (!strcmp(string, "Police Car (LSPD)")) return 596;
    else if (!strcmp(string, "Police Car (SFPD)")) return 597;
    else if (!strcmp(string, "Police Car (LVPD)")) return 598;
    else if (!strcmp(string, "Police Ranger")) return 599;
    else if (!strcmp(string, "Picador")) return 600;
    else if (!strcmp(string, "S.W.A.T.")) return 601;
    else if (!strcmp(string, "Alpha")) return 602;
    else if (!strcmp(string, "Phoenix")) return 603;
    else if (!strcmp(string, "Glendale Shit")) return 604;
    else if (!strcmp(string, "Sadler Shit")) return 605;
    else if (!strcmp(string, "Baggage Trailer \"A\"")) return 606;
    else if (!strcmp(string, "Baggage Trailer \"B\"")) return 607;
    else if (!strcmp(string, "Tug Stairs Trailer")) return 608;
    else if (!strcmp(string, "Boxville")) return 609;
    else if (!strcmp(string, "Farm Trailer")) return 610;
    else if (!strcmp(string, "Utility Trailer")) return 611;
    return -1;
}

// Fix the compiler crash when both the PAWN and Plugin versions of sscanf are
// found by renaming the old version at declaration.  (fixes.inc compatible
// naming scheme: "BAD_Function()").
#define sscanf(%0:...) BAD_sscanf(%0:...)

zcmd :

pawn Code:
/**********************************
 *                                *
 *   @Author:      ZeeX           *
 *   @Version:     0.3.1          *
 *   @Released:    31/10/2009     *
 *                                *
 **********************************/


#if defined _zcmd_included
    #endinput
#endif 
#define _zcmd_included

#define MAX_FUNC_NAME (32)

#define COMMAND:%1(%2)          \
            forward cmd_%1(%2); \
            public cmd_%1(%2)      
           
#define CMD:%1(%2) \
            COMMAND:%1(%2)

#define command(%1,%2,%3) \
            COMMAND:%1(%2, %3)      
     
#define cmd(%1,%2,%3) \
            COMMAND:%1(%2, %3)

#if !defined isnull
    #define isnull(%1) \
                ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
#endif


forward OnPlayerCommandReceived(playerid, cmdtext[]);
forward OnPlayerCommandPerformed(playerid, cmdtext[], success);


static
    bool:zcmd_g_HasOPCS = false,
    bool:zcmd_g_HasOPCE = false;

#if defined FILTERSCRIPT

public OnFilterScriptInit()
{
    zcmd_g_HasOPCS = funcidx("OnPlayerCommandReceived") != -1;
    zcmd_g_HasOPCE = funcidx("OnPlayerCommandPerformed") != -1;
    return CallLocalFunction("zcmd_OnFilterScriptInit", "");
}

#if defined _ALS_OnFilterScriptInit
    #undef OnFilterScriptInit
#else
    #define _ALS_OnFilterScriptInit
#endif
#define OnFilterScriptInit zcmd_OnFilterScriptInit
forward zcmd_OnFilterScriptInit();

#else /*not a filterscript*/

public OnGameModeInit()
{
    zcmd_g_HasOPCS = funcidx("OnPlayerCommandReceived") != -1;
    zcmd_g_HasOPCE = funcidx("OnPlayerCommandPerformed") != -1;
    if (funcidx("zcmd_OnGameModeInit") != -1)
    {
        return CallLocalFunction("zcmd_OnGameModeInit", "");
    }  
    return 1;
}

#if defined _ALS_OnGameModeInit
    #undef OnGameModeInit
#else
    #define _ALS_OnGameModeInit
#endif
#define OnGameModeInit zcmd_OnGameModeInit
forward zcmd_OnGameModeInit();

#endif /*if defined FILTERSCRIPT*/

public OnPlayerCommandText(playerid, cmdtext[])
{
    if (zcmd_g_HasOPCS && !CallLocalFunction("OnPlayerCommandReceived", "is", playerid, cmdtext))
    {
        return 1;
    }
    new
        pos,
        funcname[MAX_FUNC_NAME];
    while (cmdtext[++pos] > ' ')
    {
        funcname[pos-1] = tolower(cmdtext[pos]);
    }
    format(funcname, sizeof(funcname), "cmd_%s", funcname);
    while (cmdtext[pos] == ' ') pos++;
    if (!cmdtext[pos])
    {
        if (zcmd_g_HasOPCE)
        {
            return CallLocalFunction("OnPlayerCommandPerformed", "isi", playerid, cmdtext, CallLocalFunction(funcname, "is", playerid, "\1"));
        }
        return CallLocalFunction(funcname, "is", playerid, "\1");  
    }
    if (zcmd_g_HasOPCE)
    {
        return CallLocalFunction("OnPlayerCommandPerformed", "isi", playerid, cmdtext, CallLocalFunction(funcname, "is", playerid, cmdtext[pos]));
    }
    return CallLocalFunction(funcname, "is", playerid, cmdtext[pos]);
}

#if defined _ALS_OnPlayerCommandText
    #undef OnPlayerCommandText
#else
    #define _ALS_OnPlayerCommandText
#endif
#define OnPlayerCommandText zcmd_OnPlayerCommandText
forward zcmd_OnPlayerCommandText(playerid, cmdtext[]);
Foreach :

pawn Code:
/*----------------------------------------------------------------------------*-
                    ===========================
                     foreach efficient looping
                    ===========================
Description:
    Provides efficient looping through sparse data sets, such as connected
    players.  Significantly improved from the original version to be a generic
    loop system, rather then purely a player loop system.  When used for
    players this has constant time O(n) for number of connected players (n),
    unlike standard player loops which are O(MAX_PLAYERS), regardless of the
    actual number of connected players.  Even when n is MAX_PLAYERS this is
    still faster.
Legal:
    Copyright © 2009 Alex "Y_Less" Cole
   
    The contents of this file are subject to the Mozilla Public License Version
    1.1 (the "License"); you may not use this file except in compliance with
    the License. You may obtain a copy of the License at
    http://www.mozilla.org/MPL/
   
    Software distributed under the License is distributed on an "AS IS" basis,
    WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    for the specific language governing rights and limitations under the
    License.
   
    The Original Code is the SA:MP foreach iterator code.
   
    The Initial Developer of the Original Code is Alex "Y_Less" Cole.
Version:
    0.1.8
Changelog:
    05/03/11:
        Added tag-free code.
        Updated to YSI y_iterate compatible code.
        Added self-fixing code for internal errors.
    16/08/10:
        Removed all the "2" versions of the functions.
    14/08/10:
        Added Iter_Clear to reset an array.
    06/08/10:
        Added special array declaration format.
    18/12/09:
        Added Itter_Func2 functions for multi-dimensional iterators.
        Renamed foreact et al as keywords in the documentation.
        Changed licensing from GPL to MPL.
    02/09/09:
        Fixed (again) for 0.3.
        Added free slot finding.
    21/08/09:
        Updated to include random functions.
        Made entirely stand alone.
        Ported to 0.3 (separate version).
        Added automatic callback hook code.
        Removed debug information from stand alone version.
    06/01/08:
        Added debug information.
    09/10/07:
        Moved to system.
    16/09/07:
        Added list sorting.
        Made this part of Y SeRver Includes, not Y Sever Includes.
        Made list sorting optional.
        Fixed version number.
    08/09/07:
        First version.
Functions:
    Public:
        OnPlayerDisconnect - Called when a player leaves to remove them.
        OnPlayerConnect - Called when a player connects to add them.
    Core:
        -
    Stock:
        Itter_ShowArray - Displays the contents of the array.
        Itter_AddInternal - Add a value to an itterator.
        Itter_RemoveInternal - Remove a value from an itterator.
        Itter_RandomInternal - Get a random item from an itterator.
        Itter_FreeInternal - Gets the first free slot in the itterator.
        Itter_InitInternal - Initialises a multi-dimensional itterator.
    Static:
        -
    Inline:
        Itter_Create - Create a new itterator value set.
        Itter_Add - Wraps Itter_AddInternal.
        Itter_Remove - Wraps Itter_RemoveInternal.
        Itter_Random - Wraps Itter_RandomInternal.
        Itter_Count - Gets the number of items in an itterator.
        Itter_Debug - Wraps around Itter_ShowArray.
        Itter_Free - Wraps around Itter_FreeInternal.
        Itter_Create2 - Create a new itterator array value set.
        Itter_Add2 - Wraps Itter_AddInternal for arrays.
        Itter_Remove2 - Wraps Itter_RemoveInternal for arrays.
        Itter_Random2 - Wraps Itter_RandomInternal for arrays.
        Itter_Count2 - Gets the number of items in an itterator array.
        Itter_Debug2 - Wraps around Itter_ShowArray for arrays.
        Itter_Free2 - Wraps around Itter_FreeInternal for arrays.
    API:
        -
Callbacks:
    -
Hooks:
    Itter_OnPlayerConnect - Hook for the OnPlayerConnect callback.
    Itter_OnPlayerDisconnect - Hook for the OnPlayerDisconnect callback.
    Itter_OnGameModeInit - Only exists to make the code compile correctly...
Definitions:
    -
Enums:
    -
Macros:
    -
Keywords:
    foreach - Command to loop an iterator.
    foreachex - Like foreach but without a new variable.
    foreach2 - Command to loop through an iterator array.
    foreachex - Like foreach2 but without a new variable.
Tags:
    Iterator - Declare an iterator.
Variables:
    Global:
        -
    Static:
        YSI_g_OPC - Records wether Itter_OnPlayerConnect exists for speed.
        YSI_g_OPDC - Records wether Itter_OnPlayerDisconnect exists for speed.
Commands:
    -
Compile options:
    YSI_ITTER_NO_SORT - Removed.
    FOREACH_NO_BOTS - Remove the bot iterators for smaller code.
    FOREACH_NO_PLAYERS - Remove all default code for player itteration.
Operators:
    -
Iterators:
    Player - List of all players connected.
    Bot - List of all bots (npcs) connected.
    NPC - Alias of Bot.
    Character - All players and bots.
-*----------------------------------------------------------------------------*/


#define _FOREACH_LOCAL_VERSION        2

// Foreach is testing us.
#if defined _FOREACH_INC_TEST
    #define _FOREACH_CUR_VERSION _FOREACH_LOCAL_VERSION
    #endinput
#endif
#if !defined _FOREACH_NO_TEST
    #define _FOREACH_INC_TEST
    #tryinclude <YSI\y_iterate>
    #undef _FOREACH_INC_TEST
    // <y_iterate> exists - test which is newer.
    #if defined _inc_y_iterate
        #if !defined _FOREACH_CUR_VERSION
            // y_iterate exists, but it's an old version - don't try use this
            // system or the variables will conflict.
            #endinput
        #endif
        #if _FOREACH_CUR_VERSION > _FOREACH_LOCAL_VERSION
            // y_iterate is newer.
            #undef _inc_y_iterate
            #define _FOREACH_NO_TEST
            #include <YSI\y_iterate>
            #endinput
        #endif
    #endif
#endif

#if !defined _samp_included
    #error "Please include a_samp or a_npc before foreach"
#endif

#if defined SendChat || defined FOREACH_NO_PLAYERS
    #define BOTSYNC_IS_BOT     (true)
#endif

#if defined IsPlayerNPC
    #define _FOREACH_BOT
#endif

#if !defined BOTSYNC_IS_BOT
    static
        bool:YSI_g_OPC = false,
        bool:YSI_g_OPDC = false;
#endif

#if defined YSI_ITTER_NO_SORT
    #error YSI_ITTER_NO_SORT is no longer supported by foreach.
#endif

/*----------------------------------------------------------------------------*-
Function:
    Itter_Create2
Params:
    name - Itterator identifier.
    size0 - Number of iterators.
    size1 - Number of items per iterator.
Return:
    -
Notes:
    Creates a new array of itterator start/array pair.
-*----------------------------------------------------------------------------*/


#define Iter_Create2 Itter_Create2
#define Itter_Create2(%1,%2,%3) \
    new \
        YSI_gS%1[%2] = {-1, ...}, \
        YSI_gC%1[%2] = {0}, \
        YSI_gA%1[%2][%3]

#define IteratorArray:%1[%2]<%3> \
    YSI_gS%1[%2] = {-1, ...}, \
    YSI_gC%1[%2] = {0}, \
    YSI_gA%1[%2][%3]

/*----------------------------------------------------------------------------*-
Function:
    Itter_Init2
Params:
    itter - Name of the itterator array to initialise.
Return:
    -
Notes:
    Wrapper for Itter_InitInternal.

native Iter_Init(IteratorArray:Name[]<>);

-*----------------------------------------------------------------------------*/


#define Iter_Init Itter_Init
#define Itter_Init(%1) \
    Itter_InitInternal(YSI_gA%1, sizeof (YSI_gA%1), sizeof (YSI_gA%1[]))

/*----------------------------------------------------------------------------*-
Function:
    Itter_Create
Params:
    name - Itterator identifier.
    size - Number of values.
Return:
    -
Notes:
    Creates a new itterator start/array pair.
-*----------------------------------------------------------------------------*/


#define Iter_Create Itter_Create
#define Itter_Create(%1,%2) \
    new \
        YSI_gS%1 = -1, \
        YSI_gC%1 = 0, \
        YSI_gA%1[%2] = {-1, ...}

/*----------------------------------------------------------------------------*-
Array:
    Iterator
Notes:
    Creates a new itterator start/array pair.
-*----------------------------------------------------------------------------*/


#define Iterator:%1<%2> \
    YSI_gS%1 = -1, \
    YSI_gC%1 = 0, \
    YSI_gA%1[%2] = {-1, ...}

/*----------------------------------------------------------------------------*-
Function:
    Itter_Add
Params:
    itter - Name of the itterator to add the data to.
    value - Value to add to the itterator.
Return:
    -
Notes:
    Wrapper for Itter_AddInternal.

native Iter_Add(Iterator:Name<>, value);

-*----------------------------------------------------------------------------*/


#define Iter_Add Itter_Add
#define Itter_Add(%1,%2) \
    Itter_AddInternal(YSI_gS%1, YSI_gC%1, YSI_gA%1, %2)

/*----------------------------------------------------------------------------*-
Function:
    Itter_Free
Params:
    itter - Name of the itterator to get the first free slot in.
Return:
    -
Notes:
    Wrapper for Itter_FreeInternal.

native Iter_Free(Iterator:Name<>);

-*----------------------------------------------------------------------------*/


#define Iter_Free Itter_Free
#define Itter_Free(%1) \
    Itter_FreeInternal(YSI_gS%1, YSI_gC%1, YSI_gA%1, sizeof (YSI_gA%1))

/*----------------------------------------------------------------------------*-
Function:
    Itter_Remove
Params:
    itter - Name of the itterator to remove data from.
    value - Data to remove.
Return:
    -
Notes:
    Wrapper for Itter_RemoveInternal.

native Iter_Remove(Iterator:Name<>, value);

-*----------------------------------------------------------------------------*/


#define Iter_Remove Itter_Remove
#define Itter_Remove(%1,%2) \
    Itter_RemoveInternal(YSI_gS%1, YSI_gC%1, YSI_gA%1, %2)

/*----------------------------------------------------------------------------*-
Function:
    Itter_Random
Params:
    itter - Name of the itterator to get a random slot from.
Return:
    -
Notes:
    Wrapper for Itter_RandomInternal.

native Iter_Random(Iterator:Name<>);

-*----------------------------------------------------------------------------*/


#define Iter_Random Itter_Random
#define Itter_Random(%1) \
    Itter_RandomInternal(YSI_gS%1, YSI_gC%1, YSI_gA%1)

/*----------------------------------------------------------------------------*-
Function:
    Itter_Debug
Params:
    itter - Name of the itterator to output debug information from.
Return:
    -
Notes:
    Wrapper for Itter_ShowArray.
-*----------------------------------------------------------------------------*/


#define Iter_Debug Itter_Debug
#define Itter_Debug(%1) \
    Itter_ShowArray(YSI_gS%1, YSI_gA%1, YSI_gC%1)

/*----------------------------------------------------------------------------*-
Function:
    Itter_Count
Params:
    itter - Name of the itterator to get a random slot from4.
Return:
    -
Notes:
    Returns the number of items in this itterator.

native Iter_Count(Iterator:Name<>);

-*----------------------------------------------------------------------------*/


#define Iter_Count Itter_Count
#define Itter_Count(%1) \
    YSI_gC%1

/*----------------------------------------------------------------------------*-
Function:
    Itter_Clear
Params:
    itter - Name of the itterator empty.
Return:
    -
Notes:
    Wrapper for Itter_ClearInternal.

native Iter_Clear(IteratorArray:Name[]<>);

-*----------------------------------------------------------------------------*/


#define Iter_Clear Itter_Clear
#define Itter_Clear(%1) \
    Itter_ClearInternal(YSI_gS%1, YSI_gC%1, YSI_gA%1)

/*----------------------------------------------------------------------------*-
Create the internal itterators.
-*----------------------------------------------------------------------------*/


#if !defined BOTSYNC_IS_BOT
    new
        Iterator:Player<MAX_PLAYERS>;
   
    #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS
        new
            Iterator:Bot<MAX_PLAYERS>,
            Iterator:Character<MAX_PLAYERS>;
       
        #define YSI_gNPCS YSI_gBotS
        #define YSI_gNPCC YSI_gBotC
        #define YSI_gNPCA YSI_gBotA
    #endif
#endif

/*----------------------------------------------------------------------------*-
Function:
    foreach
Params:
    data - Data to itterate through.
    as - Variable to set value to.
Return:
    -
Notes:
    Not exactly the same as PHP foreach, just itterates through a list and
    returns the value of the current slot but uses that slot as the next index
    too.  Variables must be in the form YSI_g<name>S for the start index and
    YSI_g<name>A for the data array where <name> is what's entered in data.
-*----------------------------------------------------------------------------*/


#define foreach(%1,%2) \
    for (new %2 = YSI_gS%1; _:%2 != -1; %2 = YSI_gA%1[%2])

/*----------------------------------------------------------------------------*-
Function:
    foreachex
Params:
    data - Data to itterate through.
    as - Variable to set value to.
Return:
    -
Notes:
    Similar to foreach but doesn't declare a new variable for the itterator.
-*----------------------------------------------------------------------------*/


#define foreachex(%1,%2) \
    for (%2 = YSI_gS%1; _:%2 != -1; %2 = YSI_gA%1[%2])

/*----------------------------------------------------------------------------*-
Function:
    Itter_OnPlayerConnect
Params:
    playerid - Player who joined.
Return:
    -
Notes:
    Adds a player to the loop data.  Now sorts the list too.  Note that I found
    the most bizzare bug ever (I *think* it may be a compiler but, but it
    requires further investigation), basically it seems that multiple variables
    were being treated as the same variable (namely YSI_gBotS and
    YSI_gCharacterS were the same and YSI_gBotC and YSI_gCharacterC were the
    same).  Adding print statements which reference these variables seem to fix
    the problem, and I've tried to make sure that the values will never actually
    get printed.
-*----------------------------------------------------------------------------*/


#if !defined BOTSYNC_IS_BOT
    public
        OnPlayerConnect(playerid)
    {
        #if defined _FOREACH_BOT
            if (!IsPlayerNPC(playerid))
            {
                Itter_Add(Player, playerid);
            }
            #if !defined FOREACH_NO_BOTS
                else
                {
                    Itter_Add(Bot, playerid);
                }
                #pragma tabsize 4
                Itter_Add(Character, playerid);
            #endif
        #else
            Itter_Add(Player, playerid);
        #endif
        if (YSI_g_OPC)
        {
            return CallLocalFunction("Itter_OnPlayerConnect", "i", playerid);
        }
        return 1;
    }
   
    #if defined _ALS_OnPlayerConnect
        #undef OnPlayerConnect
    #else
        #define _ALS_OnPlayerConnect
    #endif
    #define OnPlayerConnect Itter_OnPlayerConnect
   
    forward
        Itter_OnPlayerConnect(playerid);
#endif

/*----------------------------------------------------------------------------*-
Function:
    Itter_OnGameModeInit
Params:
    -
Return:
    -
Notes:
    There are WIERD bugs in this script, seemingly caused by the compiler, so
    this hopefully fixes them.  The OnFilterScriptInit code is written to be
    very fast by utilising the internal array structure instead of the regular
    Add functions.
-*----------------------------------------------------------------------------*/


#if !defined BOTSYNC_IS_BOT
    #if defined FILTERSCRIPT
        public
            OnFilterScriptInit()
        {
            if (YSI_gCPlayer)
            {
                print("foreach error: Something went wrong again!  Please tell Y_less");
                // Try reset.
                #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS
                    printf("%d", YSI_gSBot);
                    printf("%d", YSI_gCBot);
                    printf("%d", YSI_gSCharacter);
                    printf("%d", YSI_gCCharacter);
                   
                #endif
                printf("%d", YSI_gSPlayer);
                printf("%d", YSI_gCPlayer);
            }
            #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS
                new
                    lastBot = -1,
                    lastCharacter = -1;
            #endif
            new
                lastPlayer = -1;
            for (new i = 0; i != MAX_PLAYERS; ++i)
            {
                if (IsPlayerConnected(i))
                {
                    #if defined _FOREACH_BOT
                        if (!IsPlayerNPC(i))
                        {
                            if (lastPlayer == -1)
                            {
                                YSI_gSPlayer = i;
                            }
                            else
                            {
                                YSI_gAPlayer[lastPlayer] = i;
                            }
                            ++YSI_gCPlayer;
                            lastPlayer = i;
                        }
                        #if !defined FOREACH_NO_BOTS
                            else
                            {
                                if (lastBot == -1)
                                {
                                    YSI_gSBot = i;
                                }
                                else
                                {
                                    YSI_gABot[lastBot] = i;
                                }
                                ++YSI_gCBot;
                                lastBot = i;
                            }
                            #pragma tabsize 4
                            if (lastCharacter == -1)
                            {
                                YSI_gSCharacter = i;
                            }
                            else
                            {
                                YSI_gACharacter[lastCharacter] = i;
                            }
                            ++YSI_gCCharacter;
                            lastCharacter = i;
                        #endif
                    #else
                        if (lastPlayer == -1)
                        {
                            YSI_gSPlayer = i;
                        }
                        else
                        {
                            YSI_gAPlayer[lastPlayer] = i;
                        }
                        ++YSI_gCPlayer;
                        lastPlayer = i;
                    #endif
                }
            }
            YSI_g_OPC = (funcidx("Itter_OnPlayerConnect") != -1);
            YSI_g_OPDC = (funcidx("Itter_OnPlayerDisconnect") != -1);
            CallLocalFunction("Itter_OnFilterScriptInit", "");
        }
       
        #if defined _ALS_OnFilterScriptInit
            #undef OnFilterScriptInit
        #else
            #define _ALS_OnFilterScriptInit
        #endif
        #define OnFilterScriptInit Itter_OnFilterScriptInit
       
        forward Itter_OnFilterScriptInit();
    #else
        public
            OnGameModeInit()
        {
            if (YSI_gCPlayer)
            {
                print("foreach error: Something went wrong again!  Is this a Filterscript and have you");
                print("foreach error: got \"#define FILTERSCRIPT\" above all your includes?  Resetting...");
                #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS
                    printf("%d", YSI_gSBot);
                    printf("%d", YSI_gCBot);
                    printf("%d", YSI_gSCharacter);
                    printf("%d", YSI_gCCharacter);
                    YSI_gCBot = 0;
                    YSI_gCCharacter = 0;
                    YSI_gSBot = -1;
                    YSI_gSCharacter = -1;
                #endif
                printf("%d", YSI_gSPlayer);
                printf("%d", YSI_gCPlayer);
                YSI_gCPlayer = 0;
                YSI_gSPlayer = -1;
                for (new i = 0; i != MAX_PLAYERS; ++i)
                {
                    #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS
                        YSI_gABot[i] = -1;
                        YSI_gACharacter[i] = -1;
                    #endif
                    YSI_gAPlayer[i] = -1;
                }
            }
            YSI_g_OPC = (funcidx("Itter_OnPlayerConnect") != -1);
            YSI_g_OPDC = (funcidx("Itter_OnPlayerDisconnect") != -1);
            CallLocalFunction("Itter_OnGameModeInit", "");
        }
       
        #if defined _ALS_OnGameModeInit
            #undef OnGameModeInit
        #else
            #define _ALS_OnGameModeInit
        #endif
        #define OnGameModeInit Itter_OnGameModeInit
       
        forward
            Itter_OnGameModeInit();
    #endif
#endif

/*----------------------------------------------------------------------------*-
Function:
    Itter_OnPlayerDisconnect
Params:
    playerid - Player who left.
Return:
    -
Notes:
    Removes a player from the loop data.
-*----------------------------------------------------------------------------*/


#if !defined BOTSYNC_IS_BOT
    public
        OnPlayerDisconnect(playerid, reason)
    {
        #if defined _FOREACH_BOT
            if (!IsPlayerNPC(playerid))
            {
                Itter_Remove(Player, playerid);
            }
            #if !defined FOREACH_NO_BOTS
                else
                {
                    Itter_Remove(Bot, playerid);
                }
                #pragma tabsize 4
                Itter_Remove(Character, playerid);
            #endif
        #else
            Itter_Remove(Player, playerid);
        #endif
        if (YSI_g_OPDC)
        {
            return CallLocalFunction("Itter_OnPlayerDisconnect", "ii", playerid, reason);
        }
        return 1;
    }
   
    #if defined _ALS_OnPlayerDisconnect
        #undef OnPlayerDisconnect
    #else
        #define _ALS_OnPlayerDisconnect
    #endif
    #define OnPlayerDisconnect Itter_OnPlayerDisconnect
   
    forward
        Itter_OnPlayerDisconnect(playerid, reason);
#endif

/*----------------------------------------------------------------------------*-
Function:
    Itter_ShowArray
Params:
    start - Itterator start point.
    members[] - Itterator contents.
    size - Number of itterator values
Return:
    -
Notes:
    Pure debug function.  Has regular prints not debug prints
    as it's only called when debug is on.
-*----------------------------------------------------------------------------*/


stock
    Itter_ShowArray(start, members[], size)
{
    static
        sString[61];
    new
        i,
        j = 10;
    printf("Start: %d", start);
    printf("Size:  %d", size);
    while (i < size)
    {
        sString[0] = '\0';
        while (i < j && i < size)
        {
            format(sString, sizeof (sString), "%s, %d", sString, members[i]);
            i++;
        }
        printf("Array (%d): %s", j, sString);
        j += 10;
    }
}

/*----------------------------------------------------------------------------*-
Function:
    Itter_RandomInternal
Params:
    start - Array start index.
    count - Number of items in the itterator.
    array[] - Itterator data.
Return:
    -
Notes:
    Returns a random value from an iterator.
-*----------------------------------------------------------------------------*/


stock
    Itter_RandomInternal(start, count, array[])
{
    if (count == 0)
    {
        return -1;
    }
    new
        rnd = random(count),
        cur = start;
    while (cur != -1)
    {
        if (rnd--)
        {
            cur = array[cur];
        }
        else
        {
            return cur;
        }
    }
    return -1;
}

/*----------------------------------------------------------------------------*-
Function:
    Itter_FreeInternal
Params:
    start - Array start index.
    count - Number of items in the itterator.
    array[] - Itterator data.
    size - Size of the itterator.
Return:
    -
Notes:
    Finds the first free slot in the itterator.  Itterators now HAVE to be
    sorted for this function to work correctly as it uses that fact to decide
    wether a slot is unused or the last one.  If you want to use the slot
    straight after finding it the itterator will need to re-find it to add in
    the data.
-*----------------------------------------------------------------------------*/


stock
    Itter_FreeInternal(start, count, array[], size)
{
    if (count == size)
    {
        return -1;
    }
    else if (count == 0)
    {
        return 0;
    }
    new
        first = 0;
    while (first != -1)
    {
        if (first == start)
        {
            start = array[start];
        }
        else if (array[first] == -1)
        {
            return first;
        }
        ++first;
    }
    return -1;
}

/*----------------------------------------------------------------------------*-
Function:
    Itter_AddInternal
Params:
    &start - Array start index.
    &count - Number of items in the itterator.
    array[] - Itterator data.
    value - Item to add.
Return:
    -
Notes:
    Adds a value to a given itterator set.
-*----------------------------------------------------------------------------*/


stock
    Itter_AddInternal(&start, &count, array[], value)
{
    if (array[value] != -1)
    {
        return 0;
    }
    ++count;
    if (start == -1)
    {
        start = value;
    }
    else if (start > value)
    {
        array[value] = start;
        start = value;
    }
    else
    {
        new
            cur = start,
            last;
        do
        {
            last = cur;
            cur = array[cur];
            if (cur > value)
            {
                array[value] = cur;
                array[last] = value;
                return 1;
            }
        }
        while (cur != -1);
        array[last] = value;
    }
    return 1;
}

/*----------------------------------------------------------------------------*-
Function:
    Itter_RemoveInternal
Params:
    &start - Array start index.
    &count - Number of items in the itterator.
    array[] - Itterator data.
    value - Item to remove.
Return:
    -
Notes:
    Removes a value from an itterator.
-*----------------------------------------------------------------------------*/


stock
    Itter_RemoveInternal(&start, &count, array[], value)
{
    if (start == -1)
    {
        return 0;
    }
    if (start == value)
    {
        start = array[value];
    }
    else
    {
        new
            cur = start;
        while (array[cur] != value)
        {
            cur = array[cur];
            if (cur == -1)
            {
                return 0;
            }
        }
        array[cur] = array[value];
    }
    array[value] = -1;
    --count;
    return 1;
}

/*----------------------------------------------------------------------------*-
Function:
    Itter_ClearInternal
Params:
    &start - Array start index.
    &count - Number of items in the itterator.
    array[] - Itterator data.
Return:
    -
Notes:
    Resets an iterator.
-*----------------------------------------------------------------------------*/


stock
    Itter_ClearInternal(&start, &count, array[])
{
    if (start != -1)
    {
        new
            cur = start,
            next = array[cur];
        start = -1;
        count = 0;
        while (next != -1)
        {
            array[cur] = -1;
            cur = next;
            next = array[cur];
        }
    }
}

/*----------------------------------------------------------------------------*-
Function:
    Itter_InitInternal
Params:
    array[][] - Itterator array to initialise.
    s0 - Size of first dimension.
    s1 - Size of second dimension.
Return:
    -
Notes:
    Multi-dimensional arrays can't be initialised at compile time, so need to be
    done at run time, which is slightly annoying.
-*----------------------------------------------------------------------------*/


stock
    Itter_InitInternal(arr[][], s0, s1)
{
    for (new i = 0; i != s0; ++i)
    {
        for (new j = 0; j != s1; ++j)
        {
            arr[i][j] = -1;
        }
    }
}

Streamer :

pawn Code:
/*
    SA-MP Streamer Plugin v2.5.2
    Copyright © 2010 Incognito

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#if defined _streamer_included
    #endinput
#endif
#define _streamer_included

#include <a_samp>

// Definitions

#define STREAMER_TYPE_OBJECT (0)
#define STREAMER_TYPE_PICKUP (1)
#define STREAMER_TYPE_CP (2)
#define STREAMER_TYPE_RACE_CP (3)
#define STREAMER_TYPE_MAP_ICON (4)
#define STREAMER_TYPE_3D_TEXT_LABEL (5)
#define STREAMER_TYPE_AREA (6)

// Enumerator

enum
{
    E_STREAMER_ATTACHED_PLAYER,
    E_STREAMER_ATTACHED_VEHICLE,
    E_STREAMER_COLOR,
    E_STREAMER_DISTANCE,
    E_STREAMER_DRAW_DISTANCE,
    E_STREAMER_EXTRA_ID,
    E_STREAMER_INTERIOR_ID,
    E_STREAMER_MAX_X,
    E_STREAMER_MAX_Y,
    E_STREAMER_MAX_Z,
    E_STREAMER_MIN_X,
    E_STREAMER_MIN_Y,
    E_STREAMER_MIN_Z,
    E_STREAMER_MODEL_ID,
    E_STREAMER_MOVE_SPEED,
    E_STREAMER_MOVE_X,
    E_STREAMER_MOVE_Y,
    E_STREAMER_MOVE_Z,
    E_STREAMER_NEXT_X,
    E_STREAMER_NEXT_Y,
    E_STREAMER_NEXT_Z,
    E_STREAMER_PLAYER_ID,
    E_STREAMER_R_X,
    E_STREAMER_R_Y,
    E_STREAMER_R_Z,
    E_STREAMER_SIZE,
    E_STREAMER_STYLE,
    E_STREAMER_TEST_LOS,
    E_STREAMER_TYPE,
    E_STREAMER_WORLD_ID,
    E_STREAMER_X,
    E_STREAMER_Y,
    E_STREAMER_Z
}

// Natives (Settings)

native Streamer_TickRate(rate);
native Streamer_MaxItems(type, items);
native Streamer_VisibleItems(type, items);
native Streamer_CellDistance(Float:distance);
native Streamer_CellSize(Float:size);

// Natives (Updates)

native Streamer_Update(playerid);
native Streamer_UpdateEx(playerid, Float:x, Float:y, Float:z);

// Natives (Data Manipulation)

native Streamer_GetFloatData(type, {Text3D,_}:id, data, &Float:result);
native Streamer_SetFloatData(type, {Text3D,_}:id, data, Float:value);
native Streamer_GetIntData(type, {Text3D,_}:id, data);
native Streamer_SetIntData(type, {Text3D,_}:id, data, value);
native Streamer_IsInArrayData(type, {Text3D,_}:id, data, value);
native Streamer_AppendArrayData(type, {Text3D,_}:id, data, value);
native Streamer_RemoveArrayData(type, {Text3D,_}:id, data, value);
native Streamer_GetUpperBound(type);

// Natives (Miscellaneous)

native Streamer_IsItemVisible(playerid, type, {Text3D,_}:id);
native Streamer_DestroyAllVisibleItems(playerid, type);
native Streamer_CountVisibleItems(playerid, type);

// Natives (Objects)

native CreateDynamicObject(modelid, Float:x, Float:y, Float:z, Float:rx, Float:ry, Float:rz, worldid = -1, interiorid = -1, playerid = -1, Float:distance = 500.0);
native DestroyDynamicObject(objectid);
native IsValidDynamicObject(objectid);
native SetDynamicObjectPos(objectid, Float:x, Float:y, Float:z);
native GetDynamicObjectPos(objectid, &Float:x, &Float:y, &Float:z);
native SetDynamicObjectRot(objectid, Float:rx, Float:ry, Float:rz);
native GetDynamicObjectRot(objectid, &Float:rx, &Float:ry, &Float:rz);
native MoveDynamicObject(objectid, Float:x, Float:y, Float:z, Float:speed);
native StopDynamicObject(objectid);
native DestroyAllDynamicObjects();
native CountDynamicObjects();

// Natives (Pickups)

native CreateDynamicPickup(modelid, type, Float:x, Float:y, Float:z, worldid = -1, interiorid = -1, playerid = -1, Float:distance = 100.0);
native DestroyDynamicPickup(pickupid);
native IsValidDynamicPickup(pickupid);
native DestroyAllDynamicPickups();
native CountDynamicPickups();

// Natives (Checkpoints)

native CreateDynamicCP(Float:x, Float:y, Float:z, Float:size, worldid = -1, interiorid = -1, playerid = -1, Float:distance = 100.0);
native DestroyDynamicCP(checkpointid);
native IsValidDynamicCP(checkpointid);
native TogglePlayerDynamicCP(playerid, checkpointid, toggle);
native TogglePlayerAllDynamicCPs(playerid, toggle);
native IsPlayerInDynamicCP(playerid, checkpointid);
native DestroyAllDynamicCPs();
native CountDynamicCPs();

// Natives (Race Checkpoints)

native CreateDynamicRaceCP(type, Float:x, Float:y, Float:z, Float:nextx, Float:nexty, Float:nextz, Float:size, worldid = -1, interiorid = -1, playerid = -1, Float:distance = 100.0);
native DestroyDynamicRaceCP(checkpointid);
native IsValidDynamicRaceCP(checkpointid);
native TogglePlayerDynamicRaceCP(playerid, checkpointid, toggle);
native TogglePlayerAllDynamicRaceCPs(playerid, toggle);
native IsPlayerInDynamicRaceCP(playerid, checkpointid);
native DestroyAllDynamicRaceCPs();
native CountDynamicRaceCPs();

// Natives (Map Icons)

native CreateDynamicMapIcon(Float:x, Float:y, Float:z, type, color, worldid = -1, interiorid = -1, playerid = -1, Float:distance = 100.0);
native DestroyDynamicMapIcon(iconid);
native IsValidDynamicMapIcon(iconid);
native DestroyAllDynamicMapIcons();
native CountDynamicMapIcons();

// Natives (3D Text Labels)

native Text3D:CreateDynamic3DTextLabel(const text[], color, Float:x, Float:y, Float:z, Float:drawdistance, attachedplayer = INVALID_PLAYER_ID, attachedvehicle = INVALID_VEHICLE_ID, testlos = 0, worldid = -1, interiorid = -1, playerid = -1, Float:distance = 100.0);
native DestroyDynamic3DTextLabel(Text3D:id);
native IsValidDynamic3DTextLabel(Text3D:id);
native UpdateDynamic3DTextLabelText(Text3D:id, color, const text[]);
native DestroyAllDynamic3DTextLabels();
native CountDynamic3DTextLabels();

// Natives (Areas)

native CreateDynamicCircle(Float:x, Float:y, Float:size, worldid = -1, interiorid = -1, playerid = -1);
native CreateDynamicRectangle(Float:minx, Float:miny, Float:maxx, Float:maxy, worldid = -1, interiorid = -1, playerid = -1);
native CreateDynamicSphere(Float:x, Float:y, Float:z, Float:size, worldid = -1, interiorid = -1, playerid = -1);
native CreateDynamicCube(Float:minx, Float:miny, Float:minz, Float:maxx, Float:maxy, Float:maxz, worldid = -1, interiorid = -1, playerid = -1);
native DestroyDynamicArea(areaid);
native IsValidDynamicArea(areaid);
native TogglePlayerDynamicArea(playerid, areaid, toggle);
native TogglePlayerAllDynamicAreas(playerid, toggle);
native IsPlayerInDynamicArea(playerid, areaid);
native AttachDynamicAreaToPlayer(areaid, playerid);
native AttachDynamicAreaToVehicle(areaid, vehicleid);
native DestroyAllDynamicAreas();
native CountDynamicAreas();

// Natives (Internals)

native Streamer_AddPlayer(playerid);
native Streamer_RemovePlayer(playerid);
native Streamer_VerifyPickup(playerid, pickupid);
native Streamer_VerifyCheckpoint(playerid, type, status);
native Streamer_RegisterInterface();

// Callbacks

forward OnDynamicObjectMoved(objectid);
forward OnPlayerPickUpDynamicPickup(playerid, pickupid);
forward OnPlayerEnterDynamicCP(playerid, checkpointid);
forward OnPlayerLeaveDynamicCP(playerid, checkpointid);
forward OnPlayerEnterDynamicRaceCP(playerid, checkpointid);
forward OnPlayerLeaveDynamicRaceCP(playerid, checkpointid);
forward OnPlayerEnterDynamicArea(playerid, areaid);
forward OnPlayerLeaveDynamicArea(playerid, areaid);

// Callback Hook Section

static bool:Streamer_g_OPC = false;
static bool:Streamer_g_OPDC = false;
static bool:Streamer_g_OPPP = false;
static bool:Streamer_g_OPEC = false;
static bool:Streamer_g_OPLC = false;
static bool:Streamer_g_OPERC = false;
static bool:Streamer_g_OPLRC = false;
static bool:Streamer_g_RI = false;

public OnFilterScriptInit()
{
    if (!Streamer_g_RI)
    {
        Streamer_g_OPC = funcidx("Streamer_OnPlayerConnect") != -1;
        Streamer_g_OPDC = funcidx("Streamer_OnPlayerDisconnect") != -1;
        Streamer_g_OPPP = funcidx("Streamer_OnPlayerPickUpPickup") != -1;
        Streamer_g_OPEC = funcidx("Streamer_OnPlayerEnterCP") != -1;
        Streamer_g_OPLC = funcidx("Streamer_OnPlayerLeaveCP") != -1;
        Streamer_g_OPERC = funcidx("Streamer_OnPlayerEnterRaceCP") != -1;
        Streamer_g_OPLRC = funcidx("Streamer_OnPlayerLeaveRaceCP") != -1;
        Streamer_g_RI = true;
        Streamer_RegisterInterface();
    }
    if (funcidx("Streamer_OnFilterScriptInit") != -1)
    {
        return CallLocalFunction("Streamer_OnFilterScriptInit", "");
    }
    return 1;
}

#if defined _ALS_OnFilterScriptInit
    #undef OnFilterScriptInit
#else
    #define _ALS_OnFilterScriptInit
#endif
#define OnFilterScriptInit Streamer_OnFilterScriptInit

forward Streamer_OnFilterScriptInit();

public OnGameModeInit()
{
    if (!Streamer_g_RI)
    {
        Streamer_g_OPC = funcidx("Streamer_OnPlayerConnect") != -1;
        Streamer_g_OPDC = funcidx("Streamer_OnPlayerDisconnect") != -1;
        Streamer_g_OPPP = funcidx("Streamer_OnPlayerPickUpPickup") != -1;
        Streamer_g_OPEC = funcidx("Streamer_OnPlayerEnterCP") != -1;
        Streamer_g_OPLC = funcidx("Streamer_OnPlayerLeaveCP") != -1;
        Streamer_g_OPERC = funcidx("Streamer_OnPlayerEnterRaceCP") != -1;
        Streamer_g_OPLRC = funcidx("Streamer_OnPlayerLeaveRaceCP") != -1;
        Streamer_g_RI = true;
        Streamer_RegisterInterface();
    }
    if (funcidx("Streamer_OnGameModeInit") != -1)
    {
        return CallLocalFunction("Streamer_OnGameModeInit", "");
    }
    return 1;
}

#if defined _ALS_OnGameModeInit
    #undef OnGameModeInit
#else
    #define _ALS_OnGameModeInit
#endif
#define OnGameModeInit Streamer_OnGameModeInit

forward Streamer_OnGameModeInit();

public OnPlayerConnect(playerid)
{
    if (!IsPlayerNPC(playerid))
    {
        Streamer_AddPlayer(playerid);
    }
    if (Streamer_g_OPC)
    {
        return CallLocalFunction("Streamer_OnPlayerConnect", "d", playerid);
    }
    return 1;
}

#if defined _ALS_OnPlayerConnect
    #undef OnPlayerConnect
#else
    #define _ALS_OnPlayerConnect
#endif
#define OnPlayerConnect Streamer_OnPlayerConnect

forward Streamer_OnPlayerConnect(playerid);

public OnPlayerDisconnect(playerid, reason)
{
    if (!IsPlayerNPC(playerid))
    {
        Streamer_RemovePlayer(playerid);
    }
    if (Streamer_g_OPDC)
    {
        return CallLocalFunction("Streamer_OnPlayerDisconnect", "dd", playerid, reason);
    }
    return 1;
}

#if defined _ALS_OnPlayerDisconnect
    #undef OnPlayerDisconnect
#else
    #define _ALS_OnPlayerDisconnect
#endif
#define OnPlayerDisconnect Streamer_OnPlayerDisconnect

forward Streamer_OnPlayerDisconnect(playerid, reason);

public OnPlayerPickUpPickup(playerid, pickupid)
{
    if (!IsPlayerNPC(playerid))
    {
        Streamer_VerifyPickup(playerid, pickupid);
    }
    if (Streamer_g_OPPP)
    {
        return CallLocalFunction("Streamer_OnPlayerPickUpPickup", "dd", playerid, pickupid);
    }
    return 1;
}

#if defined _ALS_OnPlayerPickUpPickup
    #undef OnPlayerPickUpPickup
#else
    #define _ALS_OnPlayerPickUpPickup
#endif
#define OnPlayerPickUpPickup Streamer_OnPlayerPickUpPickup

forward Streamer_OnPlayerPickUpPickup(playerid, pickupid);

public OnPlayerEnterCheckpoint(playerid)
{
    if (!IsPlayerNPC(playerid))
    {
        Streamer_VerifyCheckpoint(playerid, STREAMER_TYPE_CP, 0);
    }
    if (Streamer_g_OPEC)
    {
        return CallLocalFunction("Streamer_OnPlayerEnterCP", "d", playerid);
    }
    return 1;
}

#if defined _ALS_OnPlayerEnterCheckpoint
    #undef OnPlayerEnterCheckpoint
#else
    #define _ALS_OnPlayerEnterCheckpoint
#endif
#define OnPlayerEnterCheckpoint Streamer_OnPlayerEnterCP

forward Streamer_OnPlayerEnterCP(playerid);

public OnPlayerLeaveCheckpoint(playerid)
{
    if (!IsPlayerNPC(playerid))
    {
        Streamer_VerifyCheckpoint(playerid, STREAMER_TYPE_CP, 1);
    }
    if (Streamer_g_OPLC)
    {
        return CallLocalFunction("Streamer_OnPlayerLeaveCP", "d", playerid);
    }
    return 1;
}

#if defined _ALS_OnPlayerLeaveCheckpoint
    #undef OnPlayerLeaveCheckpoint
#else
    #define _ALS_OnPlayerLeaveCheckpoint
#endif
#define OnPlayerLeaveCheckpoint Streamer_OnPlayerLeaveCP

forward Streamer_OnPlayerLeaveCP(playerid);

public OnPlayerEnterRaceCheckpoint(playerid)
{
    if (!IsPlayerNPC(playerid))
    {
        Streamer_VerifyCheckpoint(playerid, STREAMER_TYPE_RACE_CP, 0);
    }
    if (Streamer_g_OPERC)
    {
        return CallLocalFunction("Streamer_OnPlayerEnterRaceCP", "d", playerid);
    }
    return 1;
}

#if defined _ALS_OnPlayerEnterRaceCP
    #undef OnPlayerEnterRaceCheckpoint
#else
    #define _ALS_OnPlayerEnterRaceCP
#endif
#define OnPlayerEnterRaceCheckpoint Streamer_OnPlayerEnterRaceCP

forward Streamer_OnPlayerEnterRaceCP(playerid);

public OnPlayerLeaveRaceCheckpoint(playerid)
{
    if (!IsPlayerNPC(playerid))
    {
        Streamer_VerifyCheckpoint(playerid, STREAMER_TYPE_RACE_CP, 1);
    }
    if (Streamer_g_OPLRC)
    {
        return CallLocalFunction("Streamer_OnPlayerLeaveRaceCP", "d", playerid);
    }
    return 1;
}

#if defined _ALS_OnPlayerLeaveRaceCP
    #undef OnPlayerLeaveRaceCheckpoint
#else
    #define _ALS_OnPlayerLeaveRaceCP
#endif
#define OnPlayerLeaveRaceCheckpoint Streamer_OnPlayerLeaveRaceCP

forward Streamer_OnPlayerLeaveRaceCP(playerid);

// PAWN Invoke Section

forward Streamer_PublicFunction();

public Streamer_PublicFunction()
{
    new Float:value;
    CreatePickup(0, 0, 0.0, 0.0, 0.0, 0);
    CreatePlayer3DTextLabel(0, "", 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0);
    CreatePlayerObject(0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
    DeletePlayer3DTextLabel(0, PlayerText3D:0);
    DestroyPickup(0);
    DestroyPlayerObject(0, 0);
    DisablePlayerCheckpoint(0);
    DisablePlayerRaceCheckpoint(0);
    GetPlayerInterior(0);
    GetPlayerPos(0, value, value, value);
    GetPlayerState(0);
    GetPlayerVirtualWorld(0);
    GetVehiclePos(0, value, value, value);
    MovePlayerObject(0, 0, 0.0, 0.0, 0.0, 0.0);
    RemovePlayerMapIcon(0, 0);
    SetPlayerCheckpoint(0, 0.0, 0.0, 0.0, 0.0);
    SetPlayerMapIcon(0, 0, 0.0, 0.0, 0.0, 0, 0, 0);
    SetPlayerObjectPos(0, 0, 0.0, 0.0, 0.0);
    SetPlayerObjectRot(0, 0, 0.0, 0.0, 0.0);
    SetPlayerRaceCheckpoint(0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
    StopPlayerObject(0, 0);
    UpdatePlayer3DTextLabelText(0, PlayerText3D:0, 0, "");
    return 1;
}

YSI/Y_Ini :

pawn Code:
/*----------------------------------------------------------------------------*\
                    ===========================
                    Y Sever Includes - INI Core
                    ===========================
Description:
    Reads the INI and also exports a number of functions to other "classes" for
    easy reading of data files there.
Legal:
    Version: MPL 1.1
   
    The contents of this file are subject to the Mozilla Public License Version
    1.1 (the "License"); you may not use this file except in compliance with
    the License. You may obtain a copy of the License at
    http://www.mozilla.org/MPL/
   
    Software distributed under the License is distributed on an "AS IS" basis,
    WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    for the specific language governing rights and limitations under the
    License.
   
    The Original Code is the YSI ini include.
   
    The Initial Developer of the Original Code is Alex "Y_Less" Cole.
    Portions created by the Initial Developer are Copyright © 2011
    the Initial Developer. All Rights Reserved.
   
    Contributors:
        ZeeX, koolk, JoeBullet/******63, g_aSlice/Slice
   
    Thanks:
        JoeBullet/******63 - Handy arbitrary ASM jump code using SCTRL.
        ZeeX - Very productive conversations.
        koolk - IsPlayerinAreaEx code.
        TheAlpha - Danish translation.
        breadfish - German translation.
        Fireburn - Dutch translation.
        yom - French translation.
        50p - Polish translation.
        Zamaroht - Spanish translation.
        Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
            for me to strive to better.
        Pixels^ - Running XScripters where the idea was born.
        Matite - Pestering me to release it and using it.
   
    Very special thanks to:
        Thiadmer - PAWN, whose limits continue to amaze me!
        Kye/Kalcor - SA:MP.
        SA:MP Team past, present and future - SA:MP.
   
Version:
    1.0
Changelog:
    08/09/10:
        Started adding sscanf and file plugin compatibility.
        Added tagless data at the start of a file (dini compatible).
        Added new INI:file[tag]() syntax.
        Added options to default file load.
        Fixed bugs in default file load configuration.
        Modified to be stand alone.
    20/02/08:
        Added INI_RemoveEntry.
    18/08/07:
        Fixed bug reading identifiers starting with a tag (i.e. names).
        Added local file reading for non-serverwide broadcasting.
        Added tag passing instead of tag based functions option.
        Increased default pool size.
    30/07/07:
        Added auto creation of non-existant files.
    13/07/07:
        Fixed INI writing to actually work.
        Added support for blank lines in INIs decently and quickly.
    25/06/07:
        Altered file write options to use lists.
        Added buffer overwriting for updating values.
    24/06/07:
        Added file write options.
    21/06/07:
        Added INI_NEW_LINE for future writing functions.
    20/06/07:
        Added support for an optional parameter in broadcastfunc data.
    15/04/07:
        Updated for more whitespaces.
        Added INI comment code.
        Added support for value-less entries.
        Modified entry extraction to use end of name location parameter.
        Removed INI_GetTagName, now done via INI_GetEntryName.
    14/04/07:
        Updated header documentation with more than changelog.
    24/03/07:
        First version.
Functions:
    Public:
        -
    Core:
        -
    Stock:
        INI_Load - Loads an INI file using standard features.
        INI_ParseFile - Loads a file as an ini and distributes data.
        INI_GetEntryName - Gets the name of an INI item.
        INI_GetEntryText - Gets the value of an INI item.
        INI_Open - Opens an INI for writing.
        INI_Close - Closes an INI being written to.
        INI_SetTag - Sets a subheading in an INI fo subsequent writes.
        INI_WriteString - Writes a string to an INI.
        INI_WriteInt - Writes an int to an INI.
        INI_WriteFloat - Writes a float to an INI.
        INI_WriteHex - Writes a hex to an INI.
        INI_WriteBin - Writes a binary to an INI.
        INI_WriteBool - Writes a boolean to an INI.
        INI_RemoveEntry - Remove an entry from a file.
    Static:
        INI_WriteBuffer - Writes an INI's buffer to the file.
        INI_AddToBuffer - Adds a string to an INI buffer.
    Inline:
        INI_Int - Parse an integer INI entry.
        INI_Float - Parse a float INI entry.
        INI_Hex - Parse a hex INI entry.
        INI_Bin - Parse a binary INI entry.
        INI_Bool - Parse a binary INI entry.
        INI_String - Parse a string INI entry.
    API:
        -
Callbacks:
    -
Definitions:
    MAX_INI_TAG - Maximum length of an INI tagname.
    MAX_INI_ENTRY_NAME - Maximum length of an INI entry name.
    MAX_INI_ENTRY_TEXT - Maximum length of an INI's entries' value.
    MAX_INI_LINE - Maximum length of a line in a file.
    INI_NEW_LINE - String for new lines.
    INI_MAX_WRITES - Maximum concurrent files open for writing.
    MAX_INI_TAGS - Number of tags the buffer can hold data for at once.
Enums:
    E_INI_WRITE - Storage for entries to be written.
    E_INI_TAGS - Data for tags with data.
Macros:
    INI_Parse - Header for ini parsing functions.
Tags:
    INI - Handle to an INI file being written to.
Variables:
    Global:
        -
    Static:
        YSI_g_sINIWriteBuffer - Basic data to be written.
        YSI_g_sINIWritePos - Next slot to write to.
        YSI_g_sINITagPos - Next slot to add a tag to.
        YSI_g_sINICurrentTag - Pointer to the tag been writen to.
        YSI_g_sINIWriteTag - Data for tags,
        YSI_g_sINIWriteFile - Current files been written to.
Commands:
    -
Compile options:
    -
Operators:
    -
\*----------------------------------------------------------------------------*/


// Ini file reading is not distributed.  User file reading may be, though I
// doubt it.

#include "internal\y_version"

//#tryinclude <sscanf>

#include "y_utils"
#include "y_bit"
#include "y_debug"
#include "y_inline"

#include "internal\y_natives"

#define MAX_INI_LINE                    (MAX_INI_ENTRY_NAME + MAX_INI_ENTRY_TEXT + 32)

#define INI_NO_FILE                     (INI:-1)

#if !defined INI_NEW_LINE
    #define INI_NEW_LINE                "\r\n"
#endif

#if !defined MAX_INI_TAG
    #define MAX_INI_TAG                 (32)
#endif

#if !defined MAX_INI_ENTRY_NAME
    #define MAX_INI_ENTRY_NAME          (32)
#endif

#if !defined MAX_INI_ENTRY_TEXT
    #define MAX_INI_ENTRY_TEXT          YSI_MAX_STRING
#endif

#if !defined INI_MAX_WRITES
    // I doubt many people will use the multiple ini function.
    #define INI_MAX_WRITES              (2)
#endif

#if !defined INI_BUFFER_SIZE
    #define INI_BUFFER_SIZE             (64)
#endif

/*#if INI_BUFFER_SIZE <= 32
    #define INI_BUFFER_BITS 2
#else
    #define INI_BUFFER_BITS Bit_Bits(INI_BUFFER_SIZE)
#endif*/


#if !defined MAX_INI_TAGS
    #define MAX_INI_TAGS 3
/*#else
    #if MAX_INI_TAGS > 32
        #error Current code only supports up to 32 buffer tags
    #endif*/

#endif

//#define MAX_INI_STRING                  (64)

#define MAX_INI_STRING                  FUNCTION_LENGTH

#define Y_INI_WRITE_ARRAY_SIZE ((MAX_INI_ENTRY_TEXT - 1) / 16 * 16)

enum E_INI_WRITE
{
    E_INI_WRITE_NAME[MAX_INI_ENTRY_NAME],
    E_INI_WRITE_TEXT[MAX_INI_ENTRY_TEXT],
    E_INI_WRITE_NEXT
}

enum E_INI_TAGS
{
    E_INI_TAGS_NAME[MAX_INI_TAG char],
    E_INI_TAGS_START,
    E_INI_TAGS_LAST
}

static stock
    YSI_g_sINIWriteBuffer[INI_MAX_WRITES][INI_BUFFER_SIZE][E_INI_WRITE],
    YSI_g_sINIWritePos[INI_MAX_WRITES],
    YSI_g_sINITagPos[INI_MAX_WRITES],
    YSI_g_sINICurrentTag[INI_MAX_WRITES],
    YSI_g_sINIWriteTag[INI_MAX_WRITES][MAX_INI_TAGS][E_INI_TAGS],
    YSI_g_sINIWriteFile[INI_MAX_WRITES][YSI_MAX_STRING];

#define INI_Parse(%1,%2) \
    forward @INI_%1_%2(name[], value[]); \
    @INI_%1_%2(name[], value[])

#define INI:%0[%1](%2) \
    forward @INI_%0_%1(%2); \
    @INI_%0_%1(%2)

#if defined _inc_sscanf && 0
    /*------------------------------------------------------------------------*-
    Function:
        INI_Int
    Params:
        name[] - Name of the INI textual identifier.
        function - Function to call with integer value.
    Return:
        function().
    Notes:
        -
    -*------------------------------------------------------------------------*/

   
    #define INI_Int(%1,%2) \
        if(!strcmp((%1),name,true)&&!sscanf(value,"d",%2))return;
        //if(!strcmp(){%2=floatstr(value);return;}
        //if (!strcmp((%1), name, true)) return %2(strval(value))
   
    /*------------------------------------------------------------------------*-
    Function:
        INI_Float
    Params:
        name[] - Name of the INI textual identifier.
        function - Function to call with float value.
    Return:
        function().
    Notes:
        -
    -*------------------------------------------------------------------------*/

   
    #define INI_Float(%1,%2) \
        if(!strcmp((%1),name,true)&&!sscanf(value,"f",%2))return;
        //if (!strcmp((%1), name, true)) return %2(floatstr(value))
   
    /*------------------------------------------------------------------------*-
    Function:
        INI_Hex
    Params:
        name[] - Name of the INI textual identifier.
        function - Function to call with hex value.
    Return:
        function().
    Notes:
        -
    -*------------------------------------------------------------------------*/

   
    #define INI_Hex(%1,%2) \
        if(!strcmp((%1),name,true)&&!sscanf(value,"h",%2))return;
        //if (!strcmp((%1), name, true)) return %2(hexstr(value))
   
    /*------------------------------------------------------------------------*-
    Function:
        INI_Bin
    Params:
        name[] - Name of the INI textual identifier.
        function - Function to call with binary value.
    Return:
        function().
    Notes:
        -
    -*------------------------------------------------------------------------*/

   
    #define INI_Bin(%1,%2) \
        if(!strcmp((%1),name,true)&&!sscanf(value,"l",%2))return;
        //if (!strcmp((%1), name, true)) return %2(binstr(value))
   
    /*------------------------------------------------------------------------*-
    Function:
        INI_String
    Params:
        name[] - Name of the INI textual identifier.
        function - Function to call with string value.
    Return:
        function().
    Notes:
        -
    -*------------------------------------------------------------------------*/

   
    #define INI_String(%1,%2,%3) \
        if(!strcmp((%1),name,true)&&!sscanf(value,"s["#%3"]",%2))return;
        //if (!strcmp((%1), name, true)) return %2(value)
#else
    #define INI_Int(%1,%2) \
        if(!strcmp((%1),name,true))return %2=strval(value)
   
    #define INI_Float(%1,%2) \
        if(!strcmp((%1),name,true))return _:(%2=floatstr(value))
   
    #define INI_Hex(%1,%2) \
        if(!strcmp((%1),name,true))return %2=hexstr(value)
   
    #define INI_Bin(%1,%2) \
        if(!strcmp((%1),name,true))return %2=binstr(value)
   
    #define INI_Bool(%1,%2) \
        if(!strcmp((%1),name,true))return %2=boolstr(value)
   
    #define INI_String(%1,%2,%3) \
        if(!strcmp((%1),name,true))return strcpy(%2,value,%3)
#endif

/*----------------------------------------------------------------------------*\
Function:
    INI_GetEntryName
Params:
    source - The string you want to get an entry name from.
    dest - The place you want to store the entry name to
Return:
    bool: Found the name correctly.
Notes:
    -
\*----------------------------------------------------------------------------*/


stock bool:INI_GetEntryName(source[], dest[], &i)
{
    P:3("bool:INI_GetEntryName called: \"%s\", %i, %i", source, dest, i);
    new
        j;
    while (source[j] && source[j] <= ' ') j++;
    P:7("bool:INI_GetEntryName: progress 0");
    i = j;
    while (source[i] > ' ' && source[i] != '=') i++;
    P:7("bool:INI_GetEntryName: progress 1");
    if (i == j) return false;
    P:7("bool:INI_GetEntryName: progress 2");
    i -= j;
    memcpy(dest, source, j, i * 4, MAX_INI_ENTRY_NAME);
    dest[i] = '\0';
    P:7("bool:INI_GetEntryName: progress 3, %s, %i, %s", dest, i, source);
    return true;
}

/*----------------------------------------------------------------------------*\
Function:
    INI_GetEntryText
Params:
    source - The string you want to get an entry from.
    dest - The place you want to store the entry to
Return:
    -
Notes:
\*----------------------------------------------------------------------------*/


stock INI_GetEntryText(source[], dest[], i)
{
    P:3("INI_GetEntryText called: \"%s\", %i, %i", source, dest, i);
    while ('\0' < source[i] <= ' ')
    {
        ++i;
    }
    P:7("bool:INI_GetEntryText: progress 1");
    if (source[i] == '=')
    {
        while ('\0' < source[++i] <= ' ')
        {
            // Do nothing.
        }
    }
    P:7("bool:INI_GetEntryText: progress 2");
    while (source[i] && (source[i] <= ' ' || source[i] == '=')) i++;
    //while (source[i] && (source[i] <= ' ' || source[i] == '=')) i++;
    P:7("bool:INI_GetEntryText: progress 3");
    dest[0] = 1;
    dest[1] = '\0';
    if (!source[i]) return;
    P:7("bool:INI_GetEntryText: progress 4, %s, %d, %s", dest, i, source);
    strcpy(dest, source[i], MAX_INI_ENTRY_TEXT);
}

/*----------------------------------------------------------------------------*\
Function:
    INI_ParseFile
Params:
    filename[] - The file to load.
    remoteFormat[] - The format string to generate the remote function to
        pass the data to once loaded.
    bool:bFileFirst - The order of the remoteFormat parameters.
    bool:bExtra - Send additional data.
    extra - Additional data to send.
    bLocal - Call local functions instead of gloabal ones.
    bPassTag - Pass the tag as an extra parameter not the function name.
    bFilter - Apply the tag name filter to all tags or just prefixed ones?
    filter - Text to use to search for which tags to load.
Return:
    -
Notes:
    bFileFirst sets the order and inclusion of the possible remoteFormat
    parameters.  If true the format will add the filename first then the
    current tag, if false the order will be reversed.  This can also be used
    to exclude one or the other from the function name by setting the required
    parameter to be entered first and then only haing one %s in the format
    sting.  The default order is tag first for languages compatability.
\*----------------------------------------------------------------------------*/


stock bool:INI_ParseFile(fname[], remoteFormat[], bool:bFileFirst = false, bool:bExtra = false, extra = 0, bool:bLocal = true, bool:bPassTag = false, bool:bFilter = true, filter[] = "")
{
    P:3("bool:INI_ParseFile called: \"%s\", \"%s\", %i, %i, %i, %i, %i", fname, remoteFormat, bFileFirst, bExtra, extra, bLocal, bPassTag);
    new
        File:f,
        filename[64],
        callbackFormat;
    if (bExtra)
    {
        if (bPassTag) callbackFormat = _F<isss>;
        else callbackFormat = _F<iss>;
    }
    else
    {
        if (bPassTag) callbackFormat = _F<sss>;
        else callbackFormat = _F<ss>;
    }
    strcpy(filename, fname, 64);
    if (!(f = fopen(filename, io_read))) return false;
    P:5("INI_ParseFile: open");
    new
        line[MAX_INI_LINE],
        tagName[MAX_INI_STRING] = "\1\0",
        function[MAX_INI_STRING],
        comment,
        pos,
        bool:bCallback,
        callback[E_CALLBACK_DATA];
    // Strip the extension from the filename.
    comment = chrfind('.', filename);
    if (comment != -1) filename[comment] = '\0';
    // Now reduce it to only the filename, no path.
    while (comment != -1)
    {
        if (filename[comment] == '\\' || filename[comment] == '/')
        {
            //strcpy(filename, filename[comment + 1], MAX_INI_STRING);
            ++comment;
            new
                i = 0;
            while ((filename[i] = filename[comment + i]))
            {
                ++i;
            }
            break;
        }
        --comment;
    }
    P:5("INI_ParseFile: filename only");
    // Set the default tag value.
    if (bFileFirst)
    {
        format(function, sizeof (function), remoteFormat, filename, "");
    }
    else
    {
        format(function, sizeof (function), remoteFormat, "", filename);
    }
    if (bLocal)
    {
        bCallback = bool:Callback_Get(callback_tag:function, callback, callbackFormat);
    }
    // Now read in the whole data.
    P:5("INI_ParseFile: parse");
    while (fread(f, line))
    {
        StripNL(line);
        if (!line[0]) continue;
        new
            stringIdent[MAX_INI_ENTRY_NAME];
        comment = chrfind(';', line);
        if (comment != -1)
        {
            line[comment] = '\0';
        }
        if (!INI_GetEntryName(line, stringIdent, pos))
        {
            continue;
        }
        if (stringIdent[0] == '[' && (comment = chrfind(']', stringIdent)) != -1 && !stringIdent[comment + 1])
        {
            // Got a tag, update the function to call.
            stringIdent[comment] = '\0';
            P:5("INI_ParseFile: Is checkable %d %d %d", stringIdent[1] == '@', stringIdent[2] == '@', (comment = chrfind('-', stringIdent)) != -1);
            if (stringIdent[1] == '@' && stringIdent[2] == '@' && (comment = chrfind('-', stringIdent)) != -1)
            {
                // We are keeping the ability to filter by tag names, but now
                // we are just using the existing unique tag load code in y_ini.
                stringIdent[comment] = '\0';
                P:5("INI_ParseFile: SingleTag check");
                if (strcmp(filter, stringIdent[3]))
                {
                    P:5("INI_ParseFile: Not this time");
                    // Skip tags we don't care about.  This will not skip
                    // anything if the passed tag is "" (here I'm (ab)using the
                    // fact that "strcmp" returns 0 when an empty string is
                    // involved).
                    function[0] = '\0';
                    continue;
                }
                stringIdent[comment] = '-';
                ++comment;
            }
            else
            {
                P:5("INI_ParseFile: SingleTag check");
                // Apply the filter to non-prefixed tags if desired.
                if (bFilter && strcmp(filter, stringIdent[1]))
                {
                    P:5("INI_ParseFile: Not this time");
                    // Skip tags we don't care about.  This will not skip
                    // anything if the passed tag is "" (here I'm (ab)using the
                    // fact that "strcmp" returns 0 when an empty string is
                    // involved).
                    function[0] = '\0';
                    continue;
                }
                comment = 1;
            }
            if (bFileFirst)
            {
                format(function, sizeof (function), remoteFormat, filename, stringIdent[comment]);
            }
            else
            {
                format(function, sizeof (function), remoteFormat, stringIdent[comment], filename);
            }
            if (bLocal)
            {
                bCallback = bool:Callback_Get(callback_tag:function, callback, callbackFormat);
            }
            P:5("INI_ParseFile: Call it \"%s\", %d, %d", function, bLocal, funcidx(function) == -1);
            // Skip complex checks where possible.
            if (bLocal && funcidx(function) == -1)
            {
                // This needs updating for inline functions.
                function[0] = '\0';
            }
            else
            {
                if (bPassTag)
                {
                    strcpy(tagName, stringIdent[1], MAX_INI_STRING);
                }
            }
        }
        else if (function[0])
        {
            new
                stringText[MAX_INI_ENTRY_TEXT];
            INI_GetEntryText(line, stringText, pos);
            // Read in a value - distribute it as required.
            if (bCallback)
            {
                if (bExtra)
                {
                    if (bPassTag)
                    {
                        Callback_Call(callback, extra, tagName, stringIdent, stringText);
                        //CallLocalFunction(function, "isss", extra, tagName, stringIdent, stringText);
                    }
                    else
                    {
                        Callback_Call(callback, extra, stringIdent, stringText);
                        //CallLocalFunction(function, "iss", extra, stringIdent, stringText);
                    }
                }
                else
                {
                    if (bPassTag)
                    {
                        Callback_Call(callback, tagName, stringIdent, stringText);
                        //CallLocalFunction(function, "sss", tagName, stringIdent, stringText);
                    }
                    else
                    {
                        Callback_Call(callback, stringIdent, stringText);
                        //CallLocalFunction(function, "ss", stringIdent, stringText);
                    }
                }
            }
            else if (!bLocal)
            {
                // Can't use inilne functions remotely (it makes no sense at all
                // - inline functions come from the call point, and the call
                // point is in this local script.
                if (bExtra)
                {
                    if (bPassTag)
                    {
                        CallRemoteFunction(function, "isss", extra, tagName, stringIdent, stringText);
                    }
                    else
                    {
                        CallRemoteFunction(function, "iss", extra, stringIdent, stringText);
                    }
                }
                else
                {
                    if (bPassTag)
                    {
                        CallRemoteFunction(function, "sss", tagName, stringIdent, stringText);
                    }
                    else
                    {
                        CallRemoteFunction(function, "ss", stringIdent, stringText);
                    }
                }
            }
        }
    }
    fclose(f);
    return true;
}

/*----------------------------------------------------------------------------*\
Function:
    INI_Load
Params:
    filename[] - The file to load.
    bool:bExtra - Send additional data.
    extra - Additional data to send.
    bLocal - Call local functions instead of gloabal ones.
Return:
    INI_ParseFile
Notes:
    Wrapper for INI_ParseFile to use standard API features so people can
    worry even less.  Designed for use with INI_Parse.
\*----------------------------------------------------------------------------*/


stock bool:INI_Load(filename[], bool:bExtra = false, extra = 0, bool:bLocal = true)
{
    P:3("bool:INI_Load called: \"%s\", %i, %i, %i", filename, _:bExtra, extra, _:bLocal);
    return INI_ParseFile(filename, "@INI_%s_%s", true, bExtra, extra, bLocal, false);
}

/*----------------------------------------------------------------------------*\
Function:
    INI_Open
Params:
    filename[] - INI file to open.
Return:
    INI - handle to the file or INI_NO_FILE.
Notes:
    Doesn't actually open the file, just starts a new buffer if possible.
\*----------------------------------------------------------------------------*/


stock INI:INI_Open(filename[])
{
    if (ftouch(filename) == -1)
    {
        P:E("INI_Open could not find or create file %s", filename);
    }
    P:3("INI:INI_Open called: \"%s\"", filename);
    new
        i;
    for (i = 0; i < INI_MAX_WRITES; i++)
    {
        if (!YSI_g_sINIWriteFile[i][0]) break;
    }
    if (i == INI_MAX_WRITES)
    {
        return INI_NO_FILE;
    }
    strcpy(YSI_g_sINIWriteFile[i], filename, sizeof (YSI_g_sINIWriteFile[]));
    YSI_g_sINIWritePos[i] = 0;
    YSI_g_sINITagPos[i] = 0;
    // Reset tags.
    YSI_g_sINICurrentTag[i] = 0;
    YSI_g_sINIWriteTag[i][0][E_INI_TAGS_NAME][0] = '\0';
    YSI_g_sINIWriteTag[i][0][E_INI_TAGS_START] = -1;
/*  if (!fexist(filename))
    {
        new
            File:fHnd = fopen(filename, io_write);
        if (fHnd)
        {
            fclose(fHnd);
        }
        else P:E("Could not create target file");
    }*/

    return INI:i;
}

/*----------------------------------------------------------------------------*\
Function:
    INI_Close
Params:
    INI:file - Handle to the ini to close.
Return:
    -
Notes:
    Writes any outstanding buffer data to the file and ends the stream.
\*----------------------------------------------------------------------------*/


stock INI_Close(INI:file)
{
    P:3("INI_Close called: %i", _:file);
    if (YSI_g_sINIWritePos[_:file] || YSI_g_sINITagPos[_:file]) INI_WriteBuffer(file);
    YSI_g_sINIWriteFile[_:file][0] = '\0';
}

/*----------------------------------------------------------------------------*\
Function:
    INI_SetTag
Params:
    INI:file - INI file handle to write to.
    tag[] - Name of the new file subsection for subsequent data to write to.
Return:
    -
Notes:
    Sets a new [tag] section header.  Subsequent data is written under this
    header.  Uses lists for constant tag switching and checks the tag doesn't
    already exist.
\*----------------------------------------------------------------------------*/


stock INI_SetTag(INI:file, tag[])
{
    P:3("INI_SetTag called: %i, \"%s\"", _:file, tag);
    if (file < INI:0 || file >= INI:INI_MAX_WRITES) return;
    new
        pos = YSI_g_sINITagPos[_:file];
    for (new i = 0; i < pos; i++)
    {
        if (YSI_g_sINIWriteTag[_:file][i][E_INI_TAGS_NAME][0] && !strcmp(tag, YSI_g_sINIWriteTag[_:file][i][E_INI_TAGS_NAME], true))
        {
            YSI_g_sINICurrentTag[_:file] = i;
            return;
        }
    }
    // Allow untagged data (not sure how it will go down...).
    /*if (pos == 0 && YSI_g_sINIWriteTag[_:file][0][E_INI_TAGS_START] != -1)
    {
        ++pos;
        ++YSI_g_sINITagPos[_:file];
    }*/

    if (pos >= MAX_INI_TAGS)
    {
        if (!INI_WriteBuffer(file)) return;
        // Loop.
        pos = 0;
    }
    //strcpy(YSI_g_sINIWriteTag[_:file][pos][E_INI_TAGS_NAME], tag, MAX_INI_TAG);
    strpack(YSI_g_sINIWriteTag[_:file][pos][E_INI_TAGS_NAME], tag, MAX_INI_TAG);
    YSI_g_sINIWriteTag[_:file][pos][E_INI_TAGS_START] = -1;
    YSI_g_sINICurrentTag[_:file] = pos;
    ++YSI_g_sINITagPos[_:file];
}

/*----------------------------------------------------------------------------*\
Function:
    INI_DeleteTag
Params:
    INI:file - INI file handle to write to.
    tag[] - Name of the whole section to delete.
Return:
    -
Notes:
    Removes a [tag] section from a file.
\*----------------------------------------------------------------------------*/


stock INI_DeleteTag(INI:file, tag[])
{
    P:3("INI_DeleteTag called: %i, \"%s\"", _:file, tag);
    if (file < INI:0 || file >= INI:INI_MAX_WRITES) return;
    new
        pos = YSI_g_sINITagPos[_:file];
    for (new i = 0; i < pos; i++)
    {
        P:6("INI_DeleteTag: %i, \"%s\", \"%s\"", i, tag, unpack(YSI_g_sINIWriteTag[_:file][i][E_INI_TAGS_NAME]));
        if (YSI_g_sINIWriteTag[_:file][i][E_INI_TAGS_NAME][0] && !strcmp(tag, YSI_g_sINIWriteTag[_:file][i][E_INI_TAGS_NAME], true))
        {
            YSI_g_sINICurrentTag[_:file] = i;
            YSI_g_sINIWriteTag[_:file][i][E_INI_TAGS_START] = cellmax;
            return;
        }
    }
    if (pos >= MAX_INI_TAGS)
    {
        if (!INI_WriteBuffer(file)) return;
        // Loop.
        pos = 0;
    }
    strpack(YSI_g_sINIWriteTag[_:file][pos][E_INI_TAGS_NAME], tag, MAX_INI_TAG);
    YSI_g_sINIWriteTag[_:file][pos][E_INI_TAGS_START] = cellmax;
    YSI_g_sINICurrentTag[_:file] = pos;
    ++YSI_g_sINITagPos[_:file];
}

stock INI_WriteArray(INI:file, const name[], data[], len)
{
    // Write 6 bits at a time, in 3 cell chunks.  It takes 16 bytes to record
    // three cells with 6 bits per byte.
    P:4("INI_WriteArray called");
    new
        dname[MAX_INI_ENTRY_NAME],
        write[Y_INI_WRITE_ARRAY_SIZE + 1],
        idx,
        wi,
        iter;
    // Write the length first just so the data exists.
    //INI_WriteInt(file, name, len);
    valstr(write, len);
    INI_AddToBuffer(file, name, write);
    write[0] = '\0';
    while (idx + 3 < len)
    {
        // Store all the data fast.
        //write[wi++] = (((data[idx] & 0xFC000000) >>> 2) | ((data[idx] & 0x03F00000) >> 4) | ((data[idx] & 0x000FC000) >> 6) | ((data[idx] & 0x00003F00) >> 8))
        write[wi++] = ((data[idx] & 0xFC000000) >>> 26) + '>';
        write[wi++] = ((data[idx] & 0x03F00000) >>> 20) + '>';
        write[wi++] = ((data[idx] & 0x000FC000) >>> 14) + '>';
        write[wi++] = ((data[idx] & 0x00003F00) >>> 8) + '>';
        //write[wi++] = (((data[idx - 1] & 0x000000FC) << 22) | ((data[idx - 1] & 0x00000003) << 20) | ((data[idx] & 0xF0000000) >>> 12) | ((data[idx] & 0x0FC00000) >> 14) | ((data[idx] & 0x003F0000) >> 16))
        write[wi++] = ((data[idx] & 0x000000FC) >>> 2) + '>';
        write[wi++] = (((data[idx] & 0x00000003) << 4) | ((data[idx + 1] & 0xF0000000) >>> 28)) + '>';
        ++idx;
        write[wi++] = ((data[idx] & 0x0FC00000) >>> 22) + '>';
        write[wi++] = ((data[idx] & 0x003F0000) >>> 16) + '>';
        //write[wi++] = (((data[idx] & 0x0000FC00) << 14) | ((data[idx] & 0x000003F0) << 12) | ((data[idx] & 0x0000000F) << 10) | ((data[idx + 1] & 0xC0000000) >>> 22) | ((data[idx + 1] & 0x3F000000) >> 24))
        write[wi++] = ((data[idx] & 0x0000FC00) >>> 10) + '>';
        write[wi++] = ((data[idx] & 0x000003F0) >>> 4) + '>';
        write[wi++] = (((data[idx] & 0x0000000F) << 2) | ((data[idx + 1] & 0xC0000000) >>> 30)) + '>';
        ++idx;
        write[wi++] = ((data[idx] & 0x3F000000) >>> 24) + '>';
        //write[wi++] = (((data[idx] & 0x00FC0000) << 6) | ((data[idx] & 0x0003F000) << 4) | ((data[idx] & 0x00000FC0) << 2) | ((data[idx] & 0x0000003F) << 0))
        write[wi++] = ((data[idx] & 0x00FC0000) >>> 18) + '>';
        write[wi++] = ((data[idx] & 0x0003F000) >>> 12) + '>';
        write[wi++] = ((data[idx] & 0x00000FC0) >>> 6) + '>';
        write[wi++] = ((data[idx] & 0x0000003F) >>> 0) + '>';
        ++idx;
        if (wi == Y_INI_WRITE_ARRAY_SIZE)
        {
            format(dname, sizeof (dname), "@@%s-%d", name, iter++);
            //printf("%s = %s", dname, write);
            P:5("Uvar_WriteArray: write %s = %s", dname, write);
            //Player_WriteString(dname, write);
            write[wi] = '\0';
            INI_AddToBuffer(file, dname, write);
            write[0] = '\0';
            wi = 0;
        }
    }
    // Do the straggling bytes.
    if (idx != len)
    {
        write[wi++] = ((data[idx] & 0xFC000000) >>> 26) + '>';
        write[wi++] = ((data[idx] & 0x03F00000) >>> 20) + '>';
        write[wi++] = ((data[idx] & 0x000FC000) >>> 14) + '>';
        write[wi++] = ((data[idx] & 0x00003F00) >>> 8) + '>';
        //write[wi++] = (((data[idx - 1] & 0x000000FC) << 22) | ((data[idx - 1] & 0x00000003) << 20) | ((data[idx] & 0xF0000000) >>> 12) | ((data[idx] & 0x0FC00000) >> 14) | ((data[idx] & 0x003F0000) >> 16))
        write[wi++] = ((data[idx] & 0x000000FC) >>> 2) + '>';
        if (++idx == len)
        {
            write[wi++] = ((data[idx - 1] & 0x00000003) << 4) + '>';
        }
        else
        {
            write[wi++] = (((data[idx - 1] & 0x00000003) << 4) | ((data[idx] & 0xF0000000) >>> 28)) + '>';
            write[wi++] = ((data[idx] & 0x0FC00000) >>> 22) + '>';
            write[wi++] = ((data[idx] & 0x003F0000) >>> 16) + '>';
            //write[wi++] = (((data[idx] & 0x0000FC00) << 14) | ((data[idx] & 0x000003F0) << 12) | ((data[idx] & 0x0000000F) << 10) | ((data[idx + 1] & 0xC0000000) >>> 22) | ((data[idx + 1] & 0x3F000000) >> 24))
            write[wi++] = ((data[idx] & 0x0000FC00) >>> 10) + '>';
            write[wi++] = ((data[idx] & 0x000003F0) >>> 4) + '>';
            if (++idx == len)
            {
                write[wi++] = ((data[idx - 1] & 0x0000000F) << 2) + '>';
            }
            else
            {
                write[wi++] = (((data[idx - 1] & 0x0000000F) << 2) | ((data[idx] & 0xC0000000) >>> 30)) + '>';
                //++idx;
                write[wi++] = ((data[idx] & 0x3F000000) >>> 24) + '>';
                //write[wi++] = (((data[idx] & 0x00FC0000) << 6) | ((data[idx] & 0x0003F000) << 4) | ((data[idx] & 0x00000FC0) << 2) | ((data[idx] & 0x0000003F) << 0))
                write[wi++] = ((data[idx] & 0x00FC0000) >>> 18) + '>';
                write[wi++] = ((data[idx] & 0x0003F000) >>> 12) + '>';
                write[wi++] = ((data[idx] & 0x00000FC0) >>> 6) + '>';
                write[wi++] = ((data[idx] & 0x0000003F) >>> 0) + '>';
            }
        }
        format(dname, sizeof (dname), "@@%s-%d", name, iter++);
        //printf("%s = %s", dname, write);
        P:5("Uvar_WriteArray: write %s = %s", dname, write);
        //Player_WriteString(dname, write);
        write[wi] = '\0';
        INI_AddToBuffer(file, dname, write);
        write[0] = '\0';
        wi = 0;
    }
    return 1;
}

/*----------------------------------------------------------------------------*\
Function:
    INI_AddToBuffer
Params:
    INI:file - INI file to write to.
    name[] - Data name to write.
    data[] - Data to write.
Return:
    -
Notes:
    First checks the name doesn't already exist under the current tag header
    and if it does overwrites the current value.  If not checks there's room
    in the buffer to write to and purges the buffer if not.  Finally saves the
    data in the buffer for writing when required and adds the data to the
    relevant list for tag inclusion.
\*----------------------------------------------------------------------------*/


static stock INI_AddToBuffer(INI:file, const name[], data[])
{
    P:4("INI_AddToBuffer called: %i, \"%s\", \"%s\"", _:file, name, data);
    if (file < INI:0 || file >= INI:INI_MAX_WRITES)
    {
        return 0;
    }
    if (!YSI_g_sINITagPos[_:file])
    {
        // Tagless data.
        YSI_g_sINITagPos[_:file] = 1;
        YSI_g_sINIWriteTag[_:file][0][E_INI_TAGS_START] = -1;
        YSI_g_sINIWriteTag[_:file][0][E_INI_TAGS_NAME][0] = 0;
    }
    new
        pos = YSI_g_sINIWritePos[_:file],
        tmptag = YSI_g_sINICurrentTag[_:file],
        start = YSI_g_sINIWriteTag[_:file][tmptag][E_INI_TAGS_START];
    if (start == cellmax)
    {
        // Don't write to a deleted tag.
        return 0;
    }
    while (start != -1)
    {
        if (!strcmp(name, YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NAME], true))
        {
            strcpy(YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT], data, MAX_INI_ENTRY_TEXT);
            //strpack(YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT], data, MAX_INI_ENTRY_TEXT);
            return 1;
        }
        start = YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NEXT];
    }
    if (pos >= INI_BUFFER_SIZE)
    {
        if (!INI_WriteBuffer(file))
        {
            return 0;
        }
        INI_SetTag(file, YSI_g_sINIWriteTag[_:file][tmptag][E_INI_TAGS_NAME]);
        pos = 0;
    }
    new
        curtag = YSI_g_sINICurrentTag[_:file];
    if (YSI_g_sINIWriteTag[_:file][curtag][E_INI_TAGS_START] == -1)
    {
        YSI_g_sINIWriteTag[_:file][curtag][E_INI_TAGS_START] = pos;
    }
    else
    {
        YSI_g_sINIWriteBuffer[_:file][YSI_g_sINIWriteTag[_:file][curtag][E_INI_TAGS_LAST]][E_INI_WRITE_NEXT] = pos;
    }
    strcpy(YSI_g_sINIWriteBuffer[_:file][pos][E_INI_WRITE_NAME], name, MAX_INI_ENTRY_NAME);
    //strpack(YSI_g_sINIWriteBuffer[_:file][pos][E_INI_WRITE_NAME], name, MAX_INI_ENTRY_NAME);
    strcpy(YSI_g_sINIWriteBuffer[_:file][pos][E_INI_WRITE_TEXT], data, MAX_INI_ENTRY_TEXT);
    YSI_g_sINIWriteBuffer[_:file][pos][E_INI_WRITE_NEXT] = -1;
    YSI_g_sINIWriteTag[_:file][curtag][E_INI_TAGS_LAST] = pos;
    YSI_g_sINIWritePos[_:file]++;
    return 1;
}

/*----------------------------------------------------------------------------*\
Function:
    INI_RemoveEntry
Params:
    INI:file - File to write to.
    name[] - Item to remove.
Return:
    -
Notes:
    Wrapper for INI_AddToBuffer for removing data.
\*----------------------------------------------------------------------------*/


stock INI_RemoveEntry(INI:file, name[])
{
    P:3("INI_RemoveEntry called: %i, \"%s\"", _:file, name);
    static
        sData[2] = {-1, 0};
    INI_AddToBuffer(file, name, sData);
}

/*----------------------------------------------------------------------------*\
Function:
    INI_WriteString
Params:
    INI:file - File to write to.
    name[] - Data name.
    data[] - Data.
Return:
    -
Notes:
    Wrapper for INI_AddToBuffer for strings.
\*----------------------------------------------------------------------------*/


stock INI_WriteString(INI:file, name[], data[])
{
    P:3("INI_WriteString called: %i, \"%s\", \"%s\"", _:file, name, data);
    INI_AddToBuffer(file, name, data);
}

/*----------------------------------------------------------------------------*\
Function:
    INI_WriteInt
Params:
    INI:file - File to write to.
    name[] - Data name.
    data - Integer data.
Return:
    -
Notes:
    Wrapper for INI_AddToBuffer for integers.
\*----------------------------------------------------------------------------*/


stock INI_WriteInt(INI:file, name[], data)
{
    P:3("INI_WriteInt called: %i, \"%s\", %i", _:file, name, data);
    new
        str[12];
    valstr(str, data);
    INI_AddToBuffer(file, name, str);
}

/*----------------------------------------------------------------------------*\
Function:
    INI_WriteHex
Params:
    INI:file - File to write to.
    name[] - Data name.
    data - Hex data.
Return:
    -
Notes:
    Wrapper for INI_AddToBuffer for integers to be written as hex values.
\*----------------------------------------------------------------------------*/


stock INI_WriteHex(INI:file, name[], data)
{
    P:3("INI_WriteHex called: %i, \"%s\", %i", _:file, name, data);
    static const
        sc_values[] = !"0123456789ABCDEF";
    new
        str[11],
        i = 9;
    do
    {
        str[i--] = sc_values{data & 0x0F};
        data >>>= 4;
    }
    while (data);
    str[i--] = 'x';
    str[i] = '0';
    INI_AddToBuffer(file, name, str[i]);
}

/*----------------------------------------------------------------------------*\
Function:
    INI_WriteBin
Params:
    INI:file - File to write to.
    name[] - Data name.
    data - Binary data.
Return:
    -
Notes:
    Wrapper for INI_AddToBuffer for integers to be written as binary values.
\*----------------------------------------------------------------------------*/


stock INI_WriteBin(INI:file, name[], data)
{
    P:3("INI_WriteBin called: %i, \"%s\", %i", _:file, name, data);
    // Do four values at once for speed.  This uses a packed string and unpacks
    // it so that we can quickly write four values at once.
    static const
        sc_values[] = !"0000" "0001" "0010" "0011" "0100" "0101" "0110" "0111" "1000" "1001" "1010" "1011" "1100" "1101" "1110" "1111";
    new
        str[35],
        i = 10;
    do
    {
        str[--i] = sc_values[data & 0x0F];
        data >>>= 4;
    }
    while (data);
    // Convert the coalesced values to individual values.
    strunpack(str[i], str[i], 33);
    str[--i] = 'b';
    str[--i] = '0';
    INI_AddToBuffer(file, name, str[i]);
}

/*----------------------------------------------------------------------------*\
Function:
    INI_WriteBool
Params:
    INI:file - File to write to.
    name[] - Data name.
    data - Boolean data.
Return:
    -
Notes:
    Wrapper for INI_AddToBuffer for booleans.
\*----------------------------------------------------------------------------*/


stock INI_WriteBool(INI:file, name[], bool:data)
{
    P:3("INI_WriteBool called: %i, \"%s\", %i", _:file, name, _:data);
    if (data)
    {
        INI_AddToBuffer(file, name, "true");
    }
    else
    {
        INI_AddToBuffer(file, name, "false");
    }
}

/*----------------------------------------------------------------------------*\
Function:
    INI_WriteFloat
Params:
    INI:file - File to write to.
    name[] - Data name.
    Float:data - Float data.
    accuracy - number of decimal places to write.
Return:
    -
Notes:
    Wrapper for INI_AddToBuffer for floats.  Uses custom code instead of
    format() as it's actually faster for something simple like this.
\*----------------------------------------------------------------------------*/


stock INI_WriteFloat(INI:file, name[], Float:data, accuracy = 6)
{
    P:3("INI_WriteFloat called: %i, \"%s\", %f, %i", _:file, name, data, accuracy);
    new
        str[32];
    format(str, sizeof (str), "%.*f", accuracy, data);
    INI_AddToBuffer(file, name, str);
}

/*----------------------------------------------------------------------------*\
Function:
    INI_WriteBuffer
Params:
    INI:file - INI stream to write to file.
Return:
    Success/fail.
Notes:
    Opens the required file for reading and a temp file for read/writing.  Goes
    through the entire file reading all contained data.  If it reaches a tag
    line ([tag_name]) it dumps any unwritten data from the last tag (if there
    was one) and starts processing the new tag.  While a tag is being processed
    every line is compared against the UNWRITTEN new data for that tag in the
    buffer, if they're the same it writes the new data instead (it also writes
    any comments which were after the data in the original line back), else it
    writes the original line back.
   
    Once all the new data is written to the temp file any tags which haven't
    been processed at all (i.e. were not found in the original file) are
    written to the temp file along with all their data.  The original file is
    then destroyed and reopend and all the data copied out from the temp file
    to the newly opened original file, closed and saved.
\*----------------------------------------------------------------------------*/


static stock INI_WriteBuffer(INI:file)
{
    P:4("INI_WriteBuffer called: %i", _:file);
    if (_:file < 0 || _:file >= INI_MAX_WRITES) return 0;
    new
        //File:buffer = fopen("_temp_ysi_user_file_.ysi", io_write),
        File:buffer = ftemp(),
        File:source = fopen(YSI_g_sINIWriteFile[_:file], io_read);
    if (buffer)
    {
        new
            line[MAX_INI_LINE],
            BitArray:read<INI_BUFFER_SIZE>, //:read[INI_BUFFER_BITS],
            writing = 0,
            skipTag = 0,
            //Bit:tagswritten,
            BitArray:tagswritten<MAX_INI_TAGS>,
            tagpos = YSI_g_sINITagPos[_:file],
            start = -1,
            blank;
        if (source)
        {
            // Write tagless data.
            if (!YSI_g_sINIWriteTag[_:file][0][E_INI_TAGS_NAME][0])
            {
                start = YSI_g_sINIWriteTag[_:file][0][E_INI_TAGS_START];
                // Will be -1 if there is no tagless data.
                if (start != -1)
                {
                    if (start == cellmax)
                    {
                        skipTag = 1;
                        start = -1;
                    }
                    else
                    {
                        writing = 1;
                    }
                    Bit_Set(tagswritten, 0, true);
                }
            }
            while (fread(source, line))
            {
                new
                    pos = 1;
                for (new i = 0; line[i]; i++)
                {
                    if (line[i] == ';')
                    {
                        goto INI_WriteBuffer_cont1;
                    }
                    else if (line[i] > ' ')
                    {
                        // Determine that the line is not blank.
                        pos = 0;
                        break;
                    }
                }
                if (pos)
                {
                    blank++;
                    continue;
                }
                if (line[0] == '[' && (pos = chrfind(']', line)) != -1 && endofline(line, pos + 1))
                {
                    //pos--;
                    writing = 0;
                    new
                        form[MAX_INI_LINE];
                    // Reached a new tag - flush the rest of the last tag.
                    while (start != -1)
                    {
                        if (!Bit_GetBit(read, start))
                        {
                            if (YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT][0] != -1)
                            {
                                format(form, sizeof (form), "%s = %s" INI_NEW_LINE, YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NAME], YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT]);
                                fwrite(buffer, form);
                            }
                            Bit_Set(read, start, true);
                        }
                        start = YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NEXT];
                    }
                    if (!skipTag)
                    {
                        while (blank--) fwrite(buffer, INI_NEW_LINE);
                    }
                    blank = 0;
                    skipTag = 0;
                    // Note the start of the new tag.
                    line[pos] = '\0';
                    for (new j = 0; j < tagpos; j++)
                    {
                        //if (!Bit_Get(tagswritten, j) && !YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_NAME][pos] && !strcmp(YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_NAME], line[1], true, pos))
                        //printf("compare %d, %s, %s", Bit_Get(tagswritten, j), unpack(YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_NAME]), line[1]);
                        if (!Bit_Get(tagswritten, j) && !strcmp(YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_NAME], line[1])) //, true, pos))
                        {
                            /*if (YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_NAME])
                            {
                                continue;
                            }*/

                            start = YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_START];
                            P:7("INI_WriteBuffer: Next tag: %s, %d", line[1], start);
                            if (start == cellmax)
                            {
                                skipTag = 1;
                                start = -1;
                                writing = 0;
                            }
                            else
                            {
                                writing = 1;
                            }
                            //tagswritten |= Bit:(1 << j);
                            Bit_Set(tagswritten, j, true);
                            break;
                        }
                    }
                    line[pos--] = ']';
                }
                else if (writing)
                {
                    new
                        name[MAX_INI_ENTRY_NAME],
                        temp,
                        liststart = start;
                    INI_GetEntryName(line, name, temp);
                    pos = chrfind(';', line, temp);
                    while (blank--) fwrite(buffer, INI_NEW_LINE);
                    blank = 0;
                    while (start != -1)
                    {
                        if (!Bit_GetBit(read, start) && !strcmp(name, YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NAME]))
                        {
                            Bit_Set(read, start, true);//, INI_BUFFER_SIZE);
                            // Delete the current entry from the file, as per
                            // our request.
                            if (YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT][0] == -1)
                            {
                                // Can't use "continue" as we're in an inner
                                // loop.
                                goto INI_WriteBuffer_cont2;
                            }
                            if (pos != -1)
                            {
                                format(line, sizeof (line), "%s = %s %s", name, YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT], line[pos]);
                            }
                            else
                            {
                                format(line, sizeof (line), "%s = %s" INI_NEW_LINE, name, YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT]);
                            }
                            //start = -1;
                            break;
                        }
                        else
                        {
                            start = YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NEXT];
                        }
                    }
                    /*if (start == -1)
                    {
                        // Wasn't found.
                        start = strlen(line);
                        if (line[start - 1] > ' ')
                        {
                            strcat(line, INI_NEW_LINE);
                        }
                    }*/

                    start = liststart;
                }
                INI_WriteBuffer_cont1:
                if (!skipTag)
                {
                    fwrite(buffer, line);
                }
                INI_WriteBuffer_cont2:
            }
            // Write any data from this tag group not in the original file.
            // I.e. flush the final read tag.
            while (start != -1)
            {
                if (!Bit_GetBit(read, start))
                {
                    if (YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT][0] != -1)
                    {
                        format(line, sizeof (line), "%s = %s" INI_NEW_LINE, YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NAME], YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT]);
                        fwrite(buffer, line);
                    }
                }
                start = YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NEXT];
            }
            fclose(source);
        }
        // Write any tag groups not found in the original file.
        //printf("write some tag");
        for (new j = 0; j < tagpos; j++)
        {
            //if (!(tagswritten & Bit:(1 << j)))
            //printf("write this tag: %s", unpack(YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_NAME]));
            if (!Bit_Get(tagswritten, j))
            {
                start = YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_START];
                if (start == cellmax)
                {
                    continue;
                }
                if (j || YSI_g_sINIWriteTag[_:file][0][E_INI_TAGS_NAME][0])
                {
                    strunpack(line, YSI_g_sINIWriteTag[_:file][j][E_INI_TAGS_NAME]);
                    format(line, sizeof (line), "[%s]" INI_NEW_LINE, line);
                    fwrite(buffer, line);
                }
                while (start != -1)
                {
                    if (YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT][0] != -1)
                    {
                        format(line, sizeof (line), "%s = %s" INI_NEW_LINE, YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NAME], YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_TEXT]);
                        fwrite(buffer, line);
                    }
                    start = YSI_g_sINIWriteBuffer[_:file][start][E_INI_WRITE_NEXT];
                }
            }
        }
        //fclose(buffer);
        // This renames the file back (by copying all the data).
        fremove(YSI_g_sINIWriteFile[_:file]);
        #if defined _inc_TODO_COPY_INC
        #else
            #if defined _int_TODO_OTHER_COPY_INC
            #else
                source = fopen(YSI_g_sINIWriteFile[_:file], io_write);
                //buffer = fopen("_temp_ysi_user_file_.ysi", io_read);
                fseek(buffer);
                if (source) // && buffer)
                {
                    while (fread(buffer, line)) fwrite(source, line);
                    /*new
                        val;
                    printf("start: %d", _:E_INI_WRITE * INI_BUFFER_SIZE);
                    while ((val = fblockread(buffer, YSI_g_sINIWriteBuffer[_:file][0][E_INI_WRITE_NAME], _:E_INI_WRITE * INI_BUFFER_SIZE)))
                    {
                        printf("%d %d", val, strlen(YSI_g_sINIWriteBuffer[_:file][0][E_INI_WRITE_NAME]));
                        printf("%s", YSI_g_sINIWriteBuffer[_:file][0][E_INI_WRITE_NAME]);
                        fblockwrite(source, YSI_g_sINIWriteBuffer[_:file][0][E_INI_WRITE_NAME], val);
                    }*/

                    fclose(buffer);
                    fclose(source);
                }
                //fremove("_temp_ysi_user_file_.ysi");
            #endif
        #endif
        // Reset the write buffer.
        YSI_g_sINITagPos[_:file] = 0;
        YSI_g_sINIWritePos[_:file] = 0;
        YSI_g_sINICurrentTag[_:file] = 0;
        return 1;
    }
    return 0;
}
Baixe o Plugin :

Whirlpool
sscanf
Streamer

._.
Reply
#13

Bem bacaninha
Reply
#14

Quote:
Originally Posted by Dwayne-Pheonix
View Post
Bem bacaninha
Vlw
Reply
#15

Quote:
Originally Posted by RoacH`
View Post
Cades os crйditos do alphadog ? sistemas do gm plagiados do bloody vegas!
------
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)