/* * 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 * [url]http://www.mozilla.org/MPL/[/url] * * 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 (C) 2010 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Special Thanks to: * * SA:MP Team past, present and future */ #if defined _inc_a_npc #pragma library sscanf #elseif !defined _inc_a_samp #error Please include or first. #endif #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); native SSCANF_Option(const name[], value); stock const SSCANF_QUIET[] = "SSCANF_QUIET", OLD_DEFAULT_NAME[] = "OLD_DEFAULT_NAME", MATCH_NAME_PARTIAL[] = "MATCH_NAME_PARTIAL", CELLMIN_ON_MATCHES[] = "CELLMIN_ON_MATCHES", OLD_DEFAULT_KUSTOM[] = "OLD_DEFAULT_KUSTOM", OLD_DEFAULT_CUSTOM[] = "OLD_DEFAULT_CUSTOM"; static stock bool:SSCANF_gInit = false, SSCANF_g_sPlayers[MAX_PLAYERS char]; #if defined _inc_a_npc forward SSCANF_PlayerCheck(); /* OnNPCModeInit Called when the script starts if it is a NPC mode, sets up the system, then calls the "real" OnNPCModeInit (using the new ALS 2 hook method). */ public OnNPCModeInit() { SSCANF_Init(MAX_PLAYERS, INVALID_PLAYER_ID, MAX_PLAYER_NAME); #if !defined SSCANF_NO_PLAYERS // Initialise the system. SSCANF_PlayerCheck(); SetTimer("SSCANF_PlayerCheck", 1, 1); #endif #if defined SSCANF_OnNPCModeInit SSCANF_OnNPCModeInit(); #endif return 1; } #if defined _ALS_OnNPCModeInit #undef OnNPCModeInit #else #define _ALS_OnNPCModeInit #endif #define OnNPCModeInit SSCANF_OnNPCModeInit #if defined SSCANF_OnNPCModeInit forward SSCANF_OnNPCModeInit(); #endif /* SSCANF_PlayerCheck NPC modes have no "OnPlayerConnect callback, so we need to simulate one. */ #if !defined SSCANF_NO_PLAYERS public SSCANF_PlayerCheck() { for (new i = 0; i != MAX_PLAYERS; ++i) { if (IsPlayerConnected(i)) { if (!SSCANF_g_sPlayers{i}) { new name[MAX_PLAYER_NAME]; GetPlayerName(i, name, sizeof (name)); // We have no way to know if they are an NPC or not! SSCANF_Join(i, name, 0); SSCANF_g_sPlayers{i} = 1; } } else { if (SSCANF_g_sPlayers{i}) { SSCANF_Leave(i); SSCANF_g_sPlayers{i} = 0; } } } } #endif #else /* OnFilterScriptInit Called when the script starts if it is a filterscript, sets up the system, then calls the "real" OnFilterScriptInit (using the new ALS 2 hook method). */ public OnFilterScriptInit() { SSCANF_Init(GetMaxPlayers(), INVALID_PLAYER_ID, MAX_PLAYER_NAME); SSCANF_gInit = true; #if defined SSCANF_OnFilterScriptInit SSCANF_OnFilterScriptInit(); #endif return 1; } #if defined _ALS_OnFilterScriptInit #undef OnFilterScriptInit #else #define _ALS_OnFilterScriptInit #endif #define OnFilterScriptInit SSCANF_OnFilterScriptInit #if defined SSCANF_OnFilterScriptInit forward SSCANF_OnFilterScriptInit(); #endif /* OnGameModeInit Called when the script starts if it is a gamemode. This callback is also called in filterscripts so we don't want to reinitialise the system in that case. */ public OnGameModeInit() { if (!SSCANF_gInit) { SSCANF_Init(GetMaxPlayers(), INVALID_PLAYER_ID, MAX_PLAYER_NAME); SSCANF_gInit = true; } #if defined SSCANF_OnGameModeInit SSCANF_OnGameModeInit(); #endif return 1; } #if defined _ALS_OnGameModeInit #undef OnGameModeInit #else #define _ALS_OnGameModeInit #endif #define OnGameModeInit SSCANF_OnGameModeInit #if defined SSCANF_OnGameModeInit forward SSCANF_OnGameModeInit(); #endif /* OnPlayerConnect Called when a player connects. Actually increments an internal count so that if a script ends and "OnPlayerDisconnect" is called then "sscanf" still knows that the player is really connected. Also stores their name internally. */ public OnPlayerConnect(playerid) { new name[MAX_PLAYER_NAME]; GetPlayerName(playerid, name, sizeof (name)); SSCANF_Join(playerid, name, IsPlayerNPC(playerid)); #if defined SSCANF_OnPlayerConnect SSCANF_OnPlayerConnect(playerid); #endif return 1; } #if defined _ALS_OnPlayerConnect #undef OnPlayerConnect #else #define _ALS_OnPlayerConnect #endif #define OnPlayerConnect SSCANF_OnPlayerConnect #if defined SSCANF_OnPlayerConnect forward SSCANF_OnPlayerConnect(playerid); #endif /* OnPlayerDisconnect Called when a player disconnects, or when a script is ended. */ public OnPlayerDisconnect(playerid, reason) { #if defined SSCANF_OnPlayerDisconnect SSCANF_OnPlayerDisconnect(playerid, reason); #endif SSCANF_Leave(playerid); return 1; } #if defined _ALS_OnPlayerDisconnect #undef OnPlayerDisconnect #else #define _ALS_OnPlayerDisconnect #endif #define OnPlayerDisconnect SSCANF_OnPlayerDisconnect #if defined SSCANF_OnPlayerDisconnect forward SSCANF_OnPlayerDisconnect(playerid, reason); #endif #endif #define SSCANF_Init #define SSCANF_Join #define SSCANF_Leave #define extract%0->%1; EXTRN%1;unformat(_:EXTRZ:EXTRV:EXTRX:%0,##,%1,,); #define unformat(_:EXTRZ:EXTRV:EXTRX:%0,##,%1);%2else if (unformat(_:EXTRV:EXTRX:%0,##,%1)) #define EXTRV:EXTRX:%0<%3>##,%9new%1,%2) EXTRY:%0##P<%3>,|||%1|||%2) #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[%7],%2,%3|||%4|||%5) #define Float_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1a[%7],%2,%3|||%4|||%5) #define player_EXTRW:%0##%1,%2|||%3[%7]|||%4,%5) EXTRY:%0##%1a[%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[%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[%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[%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 40