stock SendClientMessageEx( playerid, color, message[ ], {Float,_}:... ); { new string[ 128 ]; format( string, 128, message, {Float,_}:... ); return SendClientMessage( playerid, -1, string ); }
stock bool:False = false; #define FormatSCLM(%0,%1,%2,%3,%4)\ do\ {\ format(string1, 256, (%2), %4);\ format(string2, 256, (%3), %4);\ SCLM((%0),(%1), string1, string2);\ }\ while ( False )
i don't think you can do it with any kind of parameters, just with '...'
|
You will need to use arguments. See the wiki for more help, or just look at how sscanf v1 is made.
|
How I can make a function with infinite params ? Something like
PS: I looked in sscanf scripted version, but I don't understand from it. |
#define SendClientMessageEx(%0,%1,%2); {new _msg[128]; format(_msg, sizeof(_msg), %2); SendClientMessage(%0, %1, _msg);}
You have to remake a new format function yourself if you want to make a stock.
But you can just use this macro: pawn Код:
|
How I can make a function with infinite params ? Something like Becouse those macros increase the .AMX size .
|
numargs();
getarg(argnum);
What sould the function "FormatSCLM" do?
I can only see 2 formats and a "SCLM" function wich is not shown in your post |
FormatSCLM( playerid, COLOR_WHITE, "Numele tau este %s", "You nick is %s", pName(playerid) );
Yes, that's the one. That takes a variable number of parameters and pushes them to printf.
|
#include <a_samp>
#include <zcmd>
#include <sscanf2>
#include <ysi/y_debug>
stock bool:False = false;
#define CreateStreamedObject CreateDynamicObject
#define DIALOG_EMPTY 3
public OnFilterScriptInit()
{
return 1;
}
CMD:test(playerid, params[])
{
new pName[ MAX_PLAYER_NAME ];
GetPlayerName(playerid, pName, MAX_PLAYER_NAME);
FormatSCLMFS(playerid, -1, "Nickul tau este %s (ID: %d)", "Your nick is %s (ID: %s)", pName, playerid);
return 1;
}
stock FormatSCLMFS(playerid, color, strRO[], strENG[], {Float,_}:...) <ysi_debug:on>
{
// This uses the variable parameter passing method based on code by Zeex.
// See page 15 of the code optimisations topic.
new arguments = (numargs() - 1) * 4;
if (arguments)
{
new
arg_start,
arg_end;
// Load the real address of the last static parameter. Do this by
// loading the address of the parameter and then adding the value of
// [FRM] (frame pointer).
#emit CONST.alt playerid
#emit CONST.alt color
#emit CONST.alt strRO
#emit CONST.alt strENG
#emit LCTRL 5
#emit ADD
#emit STOR.S.pri arg_start
// Load the address of the last variable parameter. Do this by adding
// the number of variables on the value just loaded.
#emit LOAD.S.alt arguments
#emit ADD
#emit STOR.S.pri arg_end
// Push the variable arguments. This is done by loading the value of
// each one in reverse order and pushing them. I'd love to be able to
// rewrite this to use the values of pri and alt for comparison, instead
// of having or constantly reload two variables.
do
{
#emit LOAD.I
#emit PUSH.pri
arg_end -= 4;
#emit LOAD.S.pri arg_end
}
while (arg_end > arg_start);
// Push the static parameter.
#emit PUSH.S playerid
#emit PUSH.S color
#emit PUSH.S strRO
#emit PUSH.S strENG
// Now push the number of parameters sent and call the function.
arguments += 4;
#emit PUSH.S arguments
#emit SYSREQ.C SCLMFS
// Clear the stack, including the return.
arguments += 4;
#emit LCTRL 4
#emit LOAD.S.alt arguments
#emit ADD
#emit SCTRL 4
}
else
{
SCLMFS(playerid, color, strRO, strENG);
}
return 1;
}
stock SCLMFS(playerid, color, ro[], eng[])
{
switch(GetPVarInt(playerid,"Language"))
{
case 0: SendClientMessage(playerid, color, eng);
case 1: SendClientMessage(playerid, color, ro);
}
return 1;
}
H:\Jocuri\server sa-mp 0.3\filterscripts\testinfparams.pwn(0) : warning 230: no implementation for state "off" in function "FormatSCLMFS", no fall-back
There is a link in that function to a post - go read that post as that is all the documentation on this technique that exists.
|
stock FormatSCLMFS(playerid, color, fstringRO[], fstringENG[], {Float, _}:...)
{
// This is the number of parameters which are not variable that are passed
// to this function (i.e. the number of named parameters).
static const STATIC_ARGS = 3;
// Get the number of variable arguments.
new n = (numargs() - STATIC_ARGS) * 4;
if (n)
{
new
messageRO[128],
messageENG[128],
arg_start,
arg_end;
// Load the real address of the last static parameter. Do this by
// loading the address of the last known static parameter and then
// adding the value of [FRM].
#emit CONST.alt fstringRO
#emit CONST.alt fstringENG
#emit LCTRL 5
#emit ADD
#emit STOR.S.pri arg_start
// Load the address of the last variable parameter. Do this by adding
// the number of variable parameters on the value just loaded.
#emit LOAD.S.alt n
#emit ADD
#emit STOR.S.pri arg_end
// Push the variable arguments. This is done by loading the value of
// each one in reverse order and pushing them. I'd love to be able to
// rewrite this to use the values of pri and alt for comparison,
// instead of having to constantly load and reload two variables.
do
{
#emit LOAD.I
#emit PUSH.pri
arg_end -= 4;
#emit LOAD.S.pri arg_end
}
while (arg_end > arg_start);
// Push the static format parameters.
#emit PUSH.S fstringRO
#emit PUSH.S fstringENG
#emit PUSH.C 128
#emit PUSH.ADR messageRO
#emit PUSH.ADR messageENG
// Now push the number of arguments passed to format, including both
// static and variable ones and call the function.
n += 4 * 3;
#emit PUSH.S n
#emit SYSREQ.C format
// Remove all data, including the return value, from the stack.
n += 4;
#emit LCTRL 4
#emit LOAD.S.alt n
#emit ADD
#emit SCTRL 4
return SCLMFS(playerid, color, messageRO, messageENG);
//return print(message);
}
else
{
return SCLMFS(playerid, color, fstringRO, fstringENG);
//return print(fstring);
}
}