| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- // formatex.inc by Slice
- #include <a_samp>
- //Dependencies added by dy1zan;
- #include <sarputil>
- #if defined FORMAT_EXTRA_TAGS
- #define FORMAT_TAGS _, PlayerText3D, Text, Text3D, Menu, DB, DBResult, File, Float, FORMAT_EXTRA_TAGS
- #else
- #define FORMAT_TAGS _, PlayerText3D, Text, Text3D, Menu, DB, DBResult, File, Float
- #endif
- #if !defined FORMAT_BUFFER_SIZE
- #define FORMAT_BUFFER_SIZE 2048
- #endif
- #if !defined FORMAT_PRINT_BUFFER_SIZE
- #define FORMAT_PRINT_BUFFER_SIZE 512
- #endif
- #if !defined FORMAT_CUSTOM_SPEC_BUFFER_SIZE
- #define FORMAT_CUSTOM_SPEC_BUFFER_SIZE 512
- #endif
- #if !defined FORMAT_REPLACE_NATIVES
- #define FORMAT_REPLACE_NATIVES true
- #endif
- #define FormatSpecifier<'%1'>(%2[%3],%4) FMAT@1:F@%1(%2[FORMAT_CUSTOM_SPEC_BUFFER_SIZE],FMAT@2:___unused,%4)
- #define FMAT@2:___unused,%1[ %1[
- #define FMAT@1:%1(%2) forward %1(%2); public %1(%2)
- static stock
- gs_CustomFormatFunctions[127] = {-1, ...},
- bool:gs_bIsInitialized = false
- ;
- forward __fmt_funcinc();
- public __fmt_funcinc() {
- new szOutput[1];
-
- format(szOutput, 0, "");
- }
- static stock InitializeFormatSpecifiers() {
- new
- szFunctionName[4 char] = !"F@_",
- iIndex,
- iFunctionAddress
- ;
-
- gs_bIsInitialized = true;
-
- for (new c = '@'; c <= 'z'; c++) {
- // Skip the chars that can't be used in function names
- if (c == 'Z' + 1)
- c = '_';
- else if (c == '_' + 1)
- c = 'a';
-
- szFunctionName{2} = c;
-
- // Get the function's address if it exists
- if (-1 != (iIndex = funcidx(szFunctionName))) {
- #emit LCTRL 1
- #emit NEG
- #emit MOVE.alt
- #emit ADD.C 32
- #emit STOR.S.pri iFunctionAddress
- #emit LREF.S.pri iFunctionAddress
- #emit ADD
- #emit LOAD.S.alt iIndex
- #emit SHL.C.alt 3
- #emit ADD
- #emit STOR.S.pri iFunctionAddress
- #emit LREF.S.pri iFunctionAddress
- #emit STOR.S.pri iFunctionAddress
-
- gs_CustomFormatFunctions[c] = iFunctionAddress;
- }
- }
- }
- stock formatex(szOutput[], iLength = sizeof(szOutput), const szFormatString[], {FORMAT_TAGS}:...) {
- static
- s_szBuffer[FORMAT_BUFFER_SIZE],
- bool:s_bIsInCustomSpecifier = false
- ;
-
- // If formatex is called inside a custom specifier, the original "format" will be used
- // to prevent having s_szBuffer overwritten. Specifiers shouldn't depend on other specifiers, anyway.
- if (s_bIsInCustomSpecifier) {
- new
- iNumArgs,
- i
- ;
-
- #emit LOAD.S.pri 8
- #emit STOR.S.pri iNumArgs
- #emit SHR.C.pri 2
- #emit STOR.S.pri i
- while (--i >= 0) {
- #emit LOAD.S.pri i
- #emit SHL.C.pri 2
- #emit ADD.C 12
- #emit MOVE.alt
- #emit LCTRL 5
- #emit ADD
- #emit LOAD.I
- #emit PUSH.pri
- }
-
- #emit LOAD.S.pri iNumArgs
- #emit PUSH.pri
- #emit MOVE.alt
- #emit SYSREQ.C format
- #emit CONST.pri 4
- #emit ADD
- #emit MOVE.alt
- #emit LCTRL 4
- #emit ADD
- #emit SCTRL 4
- } else {
- new
- iPos = -1,
- iArg = 12 + (3 * 4),
- iArgCount,
- iAddress,
- iArgValue,
- aiArgs[128],
- i
- ;
-
- if (!gs_bIsInitialized)
- InitializeFormatSpecifiers();
-
- iLength = min(FORMAT_BUFFER_SIZE, iLength);
-
- s_szBuffer[0] = 0;
-
- strunpack(s_szBuffer, szFormatString);
-
- while (-1 != (iPos = strfind(s_szBuffer, !"%", _, ++iPos))) {
- while (s_szBuffer[++iPos]) {
- // Look for custom formats
- if (1 <= s_szBuffer[iPos] < sizeof(gs_CustomFormatFunctions) && gs_CustomFormatFunctions[s_szBuffer[iPos]] != -1) {
- new
- iFunc = gs_CustomFormatFunctions[s_szBuffer[iPos]]
- ;
-
- static
- s_szCustomFormatBuffer[FORMAT_CUSTOM_SPEC_BUFFER_SIZE]
- ;
-
- strdel(s_szBuffer, iPos - 1, iPos + 1);
-
- s_szCustomFormatBuffer[0] = 0;
-
- #emit LCTRL 5
- #emit LOAD.S.alt iArg
- #emit ADD
- #emit LOAD.I
- #emit MOVE.alt
- #emit LOAD.I
- #emit PUSH.pri
- #emit PUSH.alt
-
- iArg += 4;
-
- s_bIsInCustomSpecifier = true;
-
- #emit PUSH.C s_szCustomFormatBuffer
- #emit PUSH.C 12
- #emit LCTRL 6
- #emit ADD.C 28
- #emit PUSH.pri
- #emit LOAD.S.pri iFunc
- #emit SCTRL 6
-
- s_bIsInCustomSpecifier = false;
-
- strins(s_szBuffer, s_szCustomFormatBuffer, iPos - 1);
-
- break;
- }
-
- switch (s_szBuffer[iPos]) {
- // Handled by the original format function
- case '*', 'i', 'd', 'x', 'h', 'c', 's', 'f', 'b', 'q': {
- // Get the argument address and save it for later
- #emit LCTRL 5
- #emit LOAD.S.alt iArg
- #emit ADD
- #emit LOAD.I
- #emit STOR.S.pri iAddress
- #emit MOVE.pri
- #emit ADD.C 4
- #emit STOR.S.pri iArg
-
- aiArgs[iArgCount++] = iAddress;
-
- if (s_szBuffer[iPos] == '*')
- continue;
-
- break;
- }
-
- // Unsigned numbers
- case 'u': {
- new
- szBuffer[11]
- ;
-
- #emit LCTRL 5
- #emit LOAD.S.alt iArg
- #emit ADD
- #emit LOAD.I
- #emit LOAD.I
- #emit STOR.S.pri iArgValue
- #emit MOVE.pri
- #emit ADD.C 4
- #emit STOR.S.pri iArg
-
- strdel(s_szBuffer, iPos - 1, iPos + 1);
-
- if (!iArgValue) {
- strins(s_szBuffer, "0", iPos - 1);
- } else {
- new
- j = sizeof(szBuffer) - 1
- ;
-
- while (iArgValue) {
- // szBuffer[--i]
- #emit ADDR.alt szBuffer // alt = *szBuffer
- #emit LOAD.S.pri j // pri = i
- #emit DEC.pri // pri -= 1
- #emit STOR.S.pri j // i = pri
- #emit IDXADDR // pri = alt + i * 4
- #emit PUSH.pri // Store pri for later
- // Now do an unsigned divide on uValue then use both the quotient and remainder!
- #emit LOAD.S.pri iArgValue // pri = uValue
- #emit CONST.alt 10
- #emit UDIV // pri = uValue / 10; alt = uValue % 10
- #emit STOR.S.pri iArgValue // uValue = pri
- #emit CONST.pri '0'
- #emit ADD // pri = '0' + (uValue % 10)
- #emit POP.alt // alt = szBuffer[i]
- #emit STOR.I // szBuffer[i] = pri
- }
-
- strins(s_szBuffer, szBuffer[j], iPos - 1);
- }
- }
-
- case '0' .. '9', ' ', '.':
- continue;
-
- case '%':
- break;
-
- default: {
- break;
- }
- }
- }
- }
-
- i = iArgCount;
-
- // Push the arguments we stored above
- while (--i >= 0) {
- #emit ADDR.alt aiArgs
- #emit LOAD.S.pri i
- #emit LIDX
- #emit PUSH.pri
- #emit STOR.S.pri iAddress
- }
-
- // New format specifier
- #emit PUSH.C s_szBuffer
-
- // Max length
- #emit PUSH.S iLength
-
- // Output string
- #emit PUSH.S szOutput
-
- // Argument count
- #emit LOAD.S.pri iArgCount
- #emit SHL.C.pri 2
- #emit ADD.C 12
- #emit PUSH.pri
-
- // Save the argument count for later
- #emit MOVE.alt
-
- // Call format (duh)
- #emit SYSREQ.C format
-
- // Add 4 to the argument count
- #emit CONST.pri 4
- #emit ADD
- #emit MOVE.alt
-
- // Remove <argument count> from the stack
- #emit LCTRL 4
- #emit ADD
- #emit SCTRL 4
- }
-
- // Return in case anyone uses it
- return 1;
- }
- stock printfex(const szFormatString[], {FORMAT_TAGS}:...) {
- const
- iBufferSize = FORMAT_PRINT_BUFFER_SIZE
- ;
-
- static
- s_szBuffer[FORMAT_PRINT_BUFFER_SIZE]
- ;
-
- new
- iNumArgs = numargs(),
- i = iNumArgs - 1
- ;
-
- while (--i >= 0) {
- #emit LOAD.S.pri i
- #emit SHL.C.pri 2
- #emit ADD.C 16
- #emit MOVE.alt
- #emit LCTRL 5
- #emit ADD
- #emit LOAD.I
- #emit PUSH.pri
- }
-
- #emit PUSH.S szFormatString
- #emit PUSH.C iBufferSize
- #emit PUSH.C s_szBuffer
- #emit LOAD.S.pri iNumArgs
- #emit SHL.C.pri 2
- #emit ADD.C 8
- #emit PUSH.pri
- #emit LCTRL 6
- #emit ADD.C 28
- #emit PUSH.pri
- #emit CONST.pri formatex
- #emit SCTRL 6
-
- print(s_szBuffer);
- return 1;
- }
- // -----------------------------------------------------------------------------------------------------
- // Specifiers
- // -----------------------------------------------------------------------------------------------------
- // Inline color
- FormatSpecifier<'C'>(output[], color) {
- format(output, sizeof(output), "{%06x}", color >>> 8);
- }
- // Player name
- FormatSpecifier<'p'>(output[], playerid) {
- if (0 <= playerid < GetMaxPlayers() && IsPlayerConnected(playerid))
- format(output, sizeof output, "%s", Util:PlayerICName(playerid));
- else
- strcat(output, "<UNKNOWN>");
- }
- // Player name and color
- FormatSpecifier<'P'>(output[], playerid) {
- if (0 <= playerid < GetMaxPlayers() && IsPlayerConnected(playerid)) {
- format(output, sizeof(output), "{%06x}", GetPlayerColor(playerid) >>> 8);
- format(output, sizeof output, "%s%s", output, Util:PlayerICName(playerid));
- } else
- strcat(output, "{FFFFFF}<UNKNOWN>");
- }
- // Weapon name
- FormatSpecifier<'W'>(output[], weapon) {
- static const
- s_WeaponNames[][] = {
- {!"Fists" }, {!"Brass Knuckles" }, {!"Golf club" }, // 0, 1, 2
- {!"Nightstick" }, {!"Knife" }, {!"Baseball Bat" }, // 3, 4, 5
- {!"Shovel" }, {!"Pool Cue" }, {!"Katana" }, // 6, 7, 8
- {!"Chainsaw" }, {!"Purple Dildo" }, {!"Dildo" }, // 9, 10, 11
- {!"Vibrator" }, {!"Silver Vibrator" }, {!"Flowers" }, // 12, 13, 14
- {!"Cane" }, {!"Grenade" }, {!"Tear Gas" }, // 15, 16, 17
- {!"Molotov Cocktail" }, {!"" }, {!"" }, // 18, ,
- {!"" }, {!"9mm" }, {!"Silenced 9mm" }, // , 22, 23
- {!"Desert Eagle" }, {!"Shotgun" }, {!"Sawnoff Shotgun" }, // 24, 25, 26
- {!"Combat Shotgun" }, {!"Micro Uzi" }, {!"MP5" }, // 27, 28, 29
- {!"AK-47" }, {!"M4" }, {!"Tec-9" }, // 30, 31, 32
- {!"Country Rifle" }, {!"Sniper Rifle" }, {!"RPG" }, // 33, 34, 35
- {!"HS Rocket" }, {!"Flamethrower" }, {!"Minigun" }, // 36, 37, 38
- {!"Satchel Charge" }, {!"Detonator" }, {!"Spraycan" }, // 39, 40, 41
- {!"Fire Extinguisher" }, {!"Camera" }, {!"Nightvision Goggles" }, // 42, 43, 44
- {!"Thermal Goggles" }, {!"Parachute" }, {!"Fake Pistol" }, // 45, 46, 47
- {!"" }, {!"Vehicle" }, {!"Helikill" }, // , 49, 50
- {!"Explosion" }, {!"" }, {!"Drown" }, // 51, , 53
- {!"Collision" }, {!"Splat" }, {!"Unknown" } // 54, 55, 56
- }
- ;
-
- if (0 <= weapon < sizeof(s_WeaponNames))
- strcat(output, s_WeaponNames[weapon]);
- else
- strcat(output, "Unknown");
- }
- // Weapon name, lower-case singular (for sentences)
- FormatSpecifier<'w'>(output[], weapon) {
- static const
- s_WeaponNamesLowercaseSingular[][] = {
- {!"fists" }, {!"brass knuckles" }, {!"a golfclub" }, // 0, 1, 2
- {!"a nightstick" }, {!"a knife" }, {!"a baseball bat" }, // 3, 4, 5
- {!"a shovel" }, {!"a pool cue" }, {!"a katana" }, // 6, 7, 8
- {!"a chainsaw" }, {!"a purple dildo" }, {!"a dildo" }, // 9, 10, 11
- {!"a vibrator" }, {!"a silver vibrator" }, {!"flowers" }, // 12, 13, 14
- {!"a cane" }, {!"a grenade" }, {!"tear gas" }, // 15, 16, 17
- {!"a molotov cocktail" }, {!"" }, {!"" }, // 18, ,
- {!"" }, {!"a 9mm" }, {!"a silenced 9mm"}, // , 22, 23
- {!"a desert eagle" }, {!"a shotgun" }, {!"swanoff shotgun" }, // 24, 25, 26
- {!"a combat shotgun" }, {!"a micro uzi" }, {!"an mp5" }, // 27, 28, 29
- {!"an ak-47" }, {!"an m4" }, {!"a tec-9" }, // 30, 31, 32
- {!"a country rifle" }, {!"a sniper rifle" }, {!"an rpg" }, // 33, 34, 35
- {!"a hs rpg" }, {!"a flamethrower" }, {!"a minigun" }, // 36, 37, 38
- {!"a satchel charge" }, {!"a detonator" }, {!"a spraycan" }, // 39, 40, 41
- {!"a fire extinguisher" }, {!"a camera" }, {!"nightvision" }, // 42, 43, 44
- {!"an infrared" }, {!"a parachute" }, {!"a fake pistol" }, // 45, 46, 47
- {!"" }, {!"a vehicle" }, {!"a helikill" }, // , 49, 50
- {!"an explosion" }, {!"" }, {!"drowning" }, // 51, , 53
- {!"a collision" }, {!"a splat" }, {!"something unknown"} // 54, 55, 56
- }
- ;
-
- if (0 <= weapon < sizeof(s_WeaponNamesLowercaseSingular))
- strcat(output, s_WeaponNamesLowercaseSingular[weapon]);
- else
- strcat(output, "something unknown");
- }
- // Vehicle name
- FormatSpecifier<'v'>(output[], modelid) {
- static const
- s_VehicleNames[][] = {
- {!"Landstalker" }, {!"Bravura" }, {!"Buffalo" }, {!"Linerunner" },
- {!"Perrenial" }, {!"Sentinel" }, {!"Dumper" }, {!"Firetruck" },
- {!"Trashmaster" }, {!"Stretch" }, {!"Manana" }, {!"Infernus" },
- {!"Voodoo" }, {!"Pony" }, {!"Mule" }, {!"Cheetah" },
- {!"Ambulance" }, {!"Leviathan" }, {!"Moonbeam" }, {!"Esperanto" },
- {!"Taxi" }, {!"Washington" }, {!"Bobcat" }, {!"Mr Whoopee" },
- {!"BF Injection" }, {!"Hunter" }, {!"Premier" }, {!"Enforcer" },
- {!"Securicar" }, {!"Banshee" }, {!"Predator" }, {!"Bus" },
- {!"Rhino" }, {!"Barracks" }, {!"Hotknife" }, {!"Trailer 1" },
- {!"Previon" }, {!"Coach" }, {!"Cabbie" }, {!"Stallion" },
- {!"Rumpo" }, {!"RC Bandit" }, {!"Romero" }, {!"Packer" },
- {!"Monster" }, {!"Admiral" }, {!"Squalo" }, {!"Seasparrow" },
- {!"Pizzaboy" }, {!"Tram" }, {!"Trailer 2" }, {!"Turismo" },
- {!"Speeder" }, {!"Reefer" }, {!"Tropic" }, {!"Flatbed" },
- {!"Yankee" }, {!"Caddy" }, {!"Solair" }, {!"Berkley's RC Van" },
- {!"Skimmer" }, {!"PCJ-600" }, {!"Faggio" }, {!"Freeway" },
- {!"RC Baron" }, {!"RC Raider" }, {!"Glendale" }, {!"Oceanic" },
- {!"Sanchez" }, {!"Sparrow" }, {!"Patriot" }, {!"Quad" },
- {!"Coastguard" }, {!"Dinghy" }, {!"Hermes" }, {!"Sabre" },
- {!"Rustler" }, {!"ZR-350" }, {!"Walton" }, {!"Regina" },
- {!"Comet" }, {!"BMX" }, {!"Burrito" }, {!"Camper" },
- {!"Marquis" }, {!"Baggage" }, {!"Dozer" }, {!"Maverick" },
- {!"News Chopper" }, {!"Rancher" }, {!"FBI Rancher" }, {!"Virgo" },
- {!"Greenwood" }, {!"Jetmax" }, {!"Hotring" }, {!"Sandking" },
- {!"Blista Compact" }, {!"Police Maverick" }, {!"Boxville" }, {!"Benson" },
- {!"Mesa" }, {!"RC Goblin" }, {!"Hotring Racer A" }, {!"Hotring Racer B" },
- {!"Bloodring Banger" }, {!"Rancher" }, {!"Super GT" }, {!"Elegant" },
- {!"Journey" }, {!"Bike" }, {!"Mountain Bike" }, {!"Beagle" },
- {!"Cropdust" }, {!"Stunt" }, {!"Tanker" }, {!"Roadtrain" },
- {!"Nebula" }, {!"Majestic" }, {!"Buccaneer" }, {!"Shamal" },
- {!"Hydra" }, {!"FCR-900" }, {!"NRG-500" }, {!"HPV1000" },
- {!"Cement Truck" }, {!"Tow Truck" }, {!"Fortune" }, {!"Cadrona" },
- {!"FBI Truck" }, {!"Willard" }, {!"Forklift" }, {!"Tractor" },
- {!"Combine" }, {!"Feltzer" }, {!"Remington" }, {!"Slamvan" },
- {!"Blade" }, {!"Freight" }, {!"Streak" }, {!"Vortex" },
- {!"Vincent" }, {!"Bullet" }, {!"Clover" }, {!"Sadler" },
- {!"Firetruck LA" }, {!"Hustler" }, {!"Intruder" }, {!"Primo" },
- {!"Cargobob" }, {!"Tampa" }, {!"Sunrise" }, {!"Merit" },
- {!"Utility" }, {!"Nevada" }, {!"Yosemite" }, {!"Windsor" },
- {!"Monster A" }, {!"Monster B" }, {!"Uranus" }, {!"Jester" },
- {!"Sultan" }, {!"Stratum" }, {!"Elegy" }, {!"Raindance" },
- {!"RC Tiger" }, {!"Flash" }, {!"Tahoma" }, {!"Savanna" },
- {!"Bandito" }, {!"Freight Flat" }, {!"Streak Carriage" }, {!"Kart" },
- {!"Mower" }, {!"Duneride" }, {!"Sweeper" }, {!"Broadway" },
- {!"Tornado" }, {!"AT-400" }, {!"DFT-30" }, {!"Huntley" },
- {!"Stafford" }, {!"BF-400" }, {!"Newsvan" }, {!"Tug" },
- {!"Trailer 3" }, {!"Emperor" }, {!"Wayfarer" }, {!"Euros" },
- {!"Hotdog" }, {!"Club" }, {!"Freight Carriage" }, {!"Trailer 3" },
- {!"Andromada" }, {!"Dodo" }, {!"RC Cam" }, {!"Launch" },
- {!"Police Car (LSPD)"}, {!"Police Car (SFPD)"}, {!"Police Car (LVPD)"}, {!"Police Ranger" },
- {!"Picador" }, {!"S.W.A.T. Van" }, {!"Alpha" }, {!"Phoenix" },
- {!"Glendale" }, {!"Sadler" }, {!"Luggage Trailer A"}, {!"Luggage Trailer B"},
- {!"Stair Trailer" }, {!"Boxville" }, {!"Farm Plow" }, {!"Utility Trailer" }
- }
- ;
-
- if (0 <= (modelid -= 400) < sizeof(s_VehicleNames))
- strcat(output, s_VehicleNames[modelid]);
- else
- strcat(output, "Unknown");
- }
- // Unsigned 4-byte hex
- FormatSpecifier<'X'>(output[], value) {
- format(output, sizeof(output), "%02x%06x", value >>> 24, value & 0xFFFFFF);
- }
- // Do this last so the specifiers always use the native function
- #if FORMAT_REPLACE_NATIVES
- #define format formatex
- #define printf printfex
- #endif
|