Additional parameters in sscanf, is it possible?
#1

Hello guys,

So I have a tendency to create commands that work like sub-commands, I'm not one to make loads of commands to do one option at a time. I'd rather use parameters to specify what they would like to do when using that command.
However I have came across a problem I keep thinking I'm close to fixing, then finding it doesn't work.

I have an /accept command. Now the /accept works for multiple parameters as shown here USAGE: /accept (hire, interview, gag, tie, ticket) etc.

However, administrators get another parameter they can accept, in which is 'namechange'. When a player uses /changename in my server, it sends a request to admins online to accept it, now that's not the problem, I know what I am doing, it's just the parameters that I have no idea what I'm doing with. Let me show you.

PHP код:
CMD:accept(playeridparams[])
{
    new 
choice[32];
    if(
sscanf(params"s[32]"choice)) return SCM(playeridCOLOR_GREY"USAGE: /accept (hire, interview, gag, tie, ticket)");
    if(!
strcmp(choice"namechange"true))
    {
        if(
PlayerInfo[playerid][AdminLevel] < 1) return AuthorMsg(playerid);
        new 
id;
        if(
sscanf(params"i"id)) return SCM(playeridCOLOR_GREY"USAGE: /accept namechange [id]");
        if(
id == INVALID_PLAYER_ID) return SendClientMessageF(playeridCOLOR_GREY"Invalid Player ID.");
        if(
RequestNameChange[id] != 1) return SCM(playeridCOLOR_GREY"That player is not requesting a name change."); 
When typing /accept namechange it does display the USAGE: /accept namechange [id]. However once typing the ID in after. Nothing happens, it should proceed onto the code thats below (I haven't shown it here). Can anyone assist?
Reply
#2

It is very much possible.

I will show you how I do it myself, which might not be the best way to do it, but it works:

Код:
CMD:taxi(playerid, params[])
{
    if(!IsPlayerInAnyVehicle(playerid))
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You must be driving a vehicle to use this command.");

	if(GetPlayerVehicleSeat(playerid) != 0)
	    return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You must be the driver of this vehicle.");

	new Func[15], amount;

	if(pInfo[playerid][Job] != Taxi)
	    return SendClientMessage(playerid, COLOR_ERROR, NOPE);

	Func = "bla";
	    
    sscanf(params, "s[15]i", Func, amount);
    
    if(!strcmp(Func, "fare", true))
	{
	    if(pInfo[playerid][TaxiDuty] == 0)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You have to be working in order to choose your fare.");
	
		if(sscanf(params, "s[15]i", Func, amount))
		    return SendClientMessage(playerid, COLOR_USAGE, "USAGE: "USAGE"/taxi fare [amount]]");
		    
		if(amount < 1 || amount > 10)
		    return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" The fare may only be between 1 and 10 US dollars.");
		    
		    
		if(pInfo[playerid][TaxiFare] == amount)
		{
		    format(Message, sizeof(Message), "Error:"ERROR" Your taxi fare is already $%d.", amount);
		    return SendClientMessage(playerid, COLOR_ERROR, Message);
		}
		
		pInfo[playerid][TaxiFare] = amount;
		
		format(Message, sizeof(Message), "(Info):"INFO2" You have successfully set your taxi fare to be $%d.", amount);
		SendClientMessage(playerid, COLOR_INFO2, Message);
	}
	else if(!strcmp(Func, "duty", true))
	{
	    if(pInfo[playerid][TaxiDuty] == 0)
		{
		    if(GetVehicleModel(GetPlayerVehicleID(playerid)) != 420 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 438)
		        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You may only use this command while driving a taxi.");
		
		    pInfo[playerid][TaxiDuty] = 1;
		    
		    SendClientMessage(playerid, COLOR_INFO2, "(Info):"INFO2" You are now on taxi duty.");
		}
		else
		{
		    pInfo[playerid][TaxiDuty] = 0;

		    SendClientMessage(playerid, COLOR_ERROR, "(Info):"ERROR" You are now off taxi duty.");
		}
	}
	else if(!strcmp(Func, "startmeter", true))
	{
	    if(pInfo[playerid][TaxiDuty] == 0)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You have to be working in order to start the meter.");
	
	    if(GetVehicleModel(GetPlayerVehicleID(playerid)) != 420 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 438)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You may only use this command while driving a taxi.");
	        
		if(pInfo[playerid][TaxiMeter] == 1)
		    return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" The meter is already running!");
		    
		pInfo[playerid][AmountToPay] = 0;
		pInfo[playerid][TaxiMeter] = 1;
		
		GetPlayerPos(playerid, pInfo[playerid][pX], pInfo[playerid][pY], pInfo[playerid][pZ]);
		
		SetTimerEx("AddToTaxiMoney", 5000, false, "ifff", playerid, pInfo[playerid][pX], pInfo[playerid][pY], pInfo[playerid][pZ]);
		
		SendClientMessage(playerid, COLOR_INFO2, "(Info):"INFO2" The meter is now running.");
	}
	else if(!strcmp(Func, "stopmeter", true))
	{
	    if(pInfo[playerid][TaxiDuty] == 0)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You have to be working in order to stop the meter.");
	
	    if(GetVehicleModel(GetPlayerVehicleID(playerid)) != 420 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 438)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You may only use this command while driving a taxi.");
	        
	    if(pInfo[playerid][TaxiMeter] == 0)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" The meter is not running.");
	        
        pInfo[playerid][TaxiMeter] = 0;
	        
		format(Message, sizeof(Message), "(Info):"INFO2" The meter is no longer running. The amount is $%d.", pInfo[playerid][AmountToPay]);
		SendClientMessage(playerid, COLOR_INFO2, Message);
	}
	else return SendClientMessage(playerid, COLOR_USAGE, "USAGE:"USAGE" /taxi [duty|fare|startmeter|stopmeter]");
	
	return 1;
}
This is my /taxi command. It allows the player to go on duty, off duty, change the driving fare and whatnot. Take a look at it and try to copy the way I did it. If you need an explanation just say so.
Reply
#3

Well, there are multiple ways of doing this. One way to go about this is to use strcmp for each parameter that DOESN'T require additional parameters.

Example:
pawn Код:
CMD:accept(playerid, params[])
{
    if(!strcmp(params, "hire", true))
    {
        // Player used /accept hire
    }
    else if(!strcmp(params, "interview", true))
    {
        // Player used /accept interview
    }
    else if(!strcmp(params, "gag", true))
    {
        // Player used /accept gag
    }
    else if(!strcmp(params, "tie", true))
    {
        // Player used /accept tie
    }
    else if(!strcmp(params, "ticket", true))
    {
        // Player used /accept ticket
    }
Then you can add on the choices that DO require additional parameters, like so:
pawn Код:
CMD:accept(playerid, params[])
{
    if(sscanf(params, "'hire'"(params, "hire", true))
    {
        // Player used /accept hire
    }
    else if(!strcmp(params, "interview", true))
    {
        // Player used /accept interview
    }
    else if(!strcmp(params, "gag", true))
    {
        // Player used /accept gag
    }
    else if(!strcmp(params, "tie", true))
    {
        // Player used /accept tie
    }
    else if(!strcmp(params, "ticket", true))
    {
        // Player used /accept ticket
    }
    else // Command requires additional parameters.
    {
        new id;
        if(sscanf(params, "'namechange'i", id)) return SCM(playerid, COLOR_GREY, "USAGE: /accept namechange [id]");
        if(id == INVALID_PLAYER_ID || !IsPlayerConnected(id)) return SendClientMessageF(playerid, COLOR_GREY, "Invalid Player ID.");
        if(RequestNameChange[id] != 1) return SCM(playerid, COLOR_GREY, "That player is not requesting a name change.");
This line in particular:
pawn Код:
if(sscanf(params, "'namechange'i", id)) return SCM(playerid, COLOR_GREY, "USAGE: /accept namechange [id]");
Will return false when the player types "/accept namechange [id]", where '[id]' is a numerical parameter. You can essentially do this with each choice, but strcmp is the best option for choices that don't require more than 1 parameter.
Reply
#4

Quote:
Originally Posted by Threshold
Посмотреть сообщение
Well, there are multiple ways of doing this. One way to go about this is to use strcmp for each parameter that DOESN'T require additional parameters.

Example:
pawn Код:
CMD:accept(playerid, params[])
{
    if(!strcmp(params, "hire", true))
    {
        // Player used /accept hire
    }
    else if(!strcmp(params, "interview", true))
    {
        // Player used /accept interview
    }
    else if(!strcmp(params, "gag", true))
    {
        // Player used /accept gag
    }
    else if(!strcmp(params, "tie", true))
    {
        // Player used /accept tie
    }
    else if(!strcmp(params, "ticket", true))
    {
        // Player used /accept ticket
    }
Then you can add on the choices that DO require additional parameters, like so:
pawn Код:
CMD:accept(playerid, params[])
{
    if(sscanf(params, "'hire'"(params, "hire", true))
    {
        // Player used /accept hire
    }
    else if(!strcmp(params, "interview", true))
    {
        // Player used /accept interview
    }
    else if(!strcmp(params, "gag", true))
    {
        // Player used /accept gag
    }
    else if(!strcmp(params, "tie", true))
    {
        // Player used /accept tie
    }
    else if(!strcmp(params, "ticket", true))
    {
        // Player used /accept ticket
    }
    else // Command requires additional parameters.
    {
        new id;
        if(sscanf(params, "'namechange'i", id)) return SCM(playerid, COLOR_GREY, "USAGE: /accept namechange [id]");
        if(id == INVALID_PLAYER_ID || !IsPlayerConnected(id)) return SendClientMessageF(playerid, COLOR_GREY, "Invalid Player ID.");
        if(RequestNameChange[id] != 1) return SCM(playerid, COLOR_GREY, "That player is not requesting a name change.");
This line in particular:
pawn Код:
if(sscanf(params, "'namechange'i", id)) return SCM(playerid, COLOR_GREY, "USAGE: /accept namechange [id]");
Will return false when the player types "/accept namechange [id]", where '[id]' is a numerical parameter. You can essentially do this with each choice, but strcmp is the best option for choices that don't require more than 1 parameter.
Hi, yes I use strcmp for the other parameters, the other parameters displayed under the USAGE command are actually all working and I don't need help with those, however, now, it's when someone uses the parameter namechange, it actually has to then open up a secondary parameter to be used which is ID, I'm going to try this option just now.

Quote:
Originally Posted by Denying
Посмотреть сообщение
It is very much possible.

I will show you how I do it myself, which might not be the best way to do it, but it works:

Код:
CMD:taxi(playerid, params[])
{
    if(!IsPlayerInAnyVehicle(playerid))
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You must be driving a vehicle to use this command.");

	if(GetPlayerVehicleSeat(playerid) != 0)
	    return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You must be the driver of this vehicle.");

	new Func[15], amount;

	if(pInfo[playerid][Job] != Taxi)
	    return SendClientMessage(playerid, COLOR_ERROR, NOPE);

	Func = "bla";
	    
    sscanf(params, "s[15]i", Func, amount);
    
    if(!strcmp(Func, "fare", true))
	{
	    if(pInfo[playerid][TaxiDuty] == 0)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You have to be working in order to choose your fare.");
	
		if(sscanf(params, "s[15]i", Func, amount))
		    return SendClientMessage(playerid, COLOR_USAGE, "USAGE: "USAGE"/taxi fare [amount]]");
		    
		if(amount < 1 || amount > 10)
		    return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" The fare may only be between 1 and 10 US dollars.");
		    
		    
		if(pInfo[playerid][TaxiFare] == amount)
		{
		    format(Message, sizeof(Message), "Error:"ERROR" Your taxi fare is already $%d.", amount);
		    return SendClientMessage(playerid, COLOR_ERROR, Message);
		}
		
		pInfo[playerid][TaxiFare] = amount;
		
		format(Message, sizeof(Message), "(Info):"INFO2" You have successfully set your taxi fare to be $%d.", amount);
		SendClientMessage(playerid, COLOR_INFO2, Message);
	}
	else if(!strcmp(Func, "duty", true))
	{
	    if(pInfo[playerid][TaxiDuty] == 0)
		{
		    if(GetVehicleModel(GetPlayerVehicleID(playerid)) != 420 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 438)
		        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You may only use this command while driving a taxi.");
		
		    pInfo[playerid][TaxiDuty] = 1;
		    
		    SendClientMessage(playerid, COLOR_INFO2, "(Info):"INFO2" You are now on taxi duty.");
		}
		else
		{
		    pInfo[playerid][TaxiDuty] = 0;

		    SendClientMessage(playerid, COLOR_ERROR, "(Info):"ERROR" You are now off taxi duty.");
		}
	}
	else if(!strcmp(Func, "startmeter", true))
	{
	    if(pInfo[playerid][TaxiDuty] == 0)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You have to be working in order to start the meter.");
	
	    if(GetVehicleModel(GetPlayerVehicleID(playerid)) != 420 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 438)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You may only use this command while driving a taxi.");
	        
		if(pInfo[playerid][TaxiMeter] == 1)
		    return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" The meter is already running!");
		    
		pInfo[playerid][AmountToPay] = 0;
		pInfo[playerid][TaxiMeter] = 1;
		
		GetPlayerPos(playerid, pInfo[playerid][pX], pInfo[playerid][pY], pInfo[playerid][pZ]);
		
		SetTimerEx("AddToTaxiMoney", 5000, false, "ifff", playerid, pInfo[playerid][pX], pInfo[playerid][pY], pInfo[playerid][pZ]);
		
		SendClientMessage(playerid, COLOR_INFO2, "(Info):"INFO2" The meter is now running.");
	}
	else if(!strcmp(Func, "stopmeter", true))
	{
	    if(pInfo[playerid][TaxiDuty] == 0)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You have to be working in order to stop the meter.");
	
	    if(GetVehicleModel(GetPlayerVehicleID(playerid)) != 420 && GetVehicleModel(GetPlayerVehicleID(playerid)) != 438)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" You may only use this command while driving a taxi.");
	        
	    if(pInfo[playerid][TaxiMeter] == 0)
	        return SendClientMessage(playerid, COLOR_ERROR, "Error:"ERROR" The meter is not running.");
	        
        pInfo[playerid][TaxiMeter] = 0;
	        
		format(Message, sizeof(Message), "(Info):"INFO2" The meter is no longer running. The amount is $%d.", pInfo[playerid][AmountToPay]);
		SendClientMessage(playerid, COLOR_INFO2, Message);
	}
	else return SendClientMessage(playerid, COLOR_USAGE, "USAGE:"USAGE" /taxi [duty|fare|startmeter|stopmeter]");
	
	return 1;
}
This is my /taxi command. It allows the player to go on duty, off duty, change the driving fare and whatnot. Take a look at it and try to copy the way I did it. If you need an explanation just say so.
EDIT: Couldn't get yours to work, man.
Reply
#5

Something like this:

Код:
CMD:accept(playerid, params[])
{
    new choice[32];

    choice = "Teehee";

    sscanf(params, "s[32]", choice);

    if(!strcmp(choice, "namechange", true))
    {
        if(sscanf(params, "s[32]d", choice, id))
            return SCM(playerid, COLOR_GREY, "USAGE: /accept namechange [id]");
    
        if(PlayerInfo[playerid][AdminLevel] < 1) return AuthorMsg(playerid);

        new id;

        if(sscanf(params, "i", id)) return SCM(playerid, COLOR_GREY, "USAGE: /accept namechange [id]");

        if(id == INVALID_PLAYER_ID) return SendClientMessageF(playerid, COLOR_GREY, "Invalid Player ID.");

        if(RequestNameChange[id] != 1) return SCM(playerid, COLOR_GREY, "That player is not requesting a name change.");
    }
    else return SCM(playerid, COLOR_GREY, "USAGE: /accept (hire, interview, gag, tie, ticket)");
	
    return 1;
}
EDIT: You must give a random value to choice or else this doesn't work completely.
Reply
#6

Liam, here's your problem. If you use if(sscanf(params, "s[32]", params)) then check if the params include namechange with if(!strcmp(params, "namechange", true) it will work but once you do if(sscanf(params, "s[32]i", params, id)) the params would become namechange 1 and the only solution is checking by this way : if(!strcmp(params, "namechange", true, 9) where 9 is the string lenght.

PHP код:
CMD:accept(playeridparams[]) 

    if(
sscanf(params"s[32]"params)) return SCM(playeridCOLOR_GREY"USAGE: /accept (hire, interview, gag, tie, ticket)"); 
    if(!
strcmp(params"namechange"true9)) 
    { 
        if(
PlayerInfo[playerid][AdminLevel] < 1) return AuthorMsg(playerid); 
        new 
id
        if(
sscanf(params"s[32]i"paramsid)) return SCM(playeridCOLOR_GREY"USAGE: /accept namechange [id]"); 
        if(
id == INVALID_PLAYER_ID) return SendClientMessageF(playeridCOLOR_GREY"Invalid Player ID."); 
        if(
RequestNameChange[id] != 1) return SCM(playeridCOLOR_GREY"That player is not requesting a name change."); 
Reply
#7

Quote:
Originally Posted by Denying
Посмотреть сообщение
Something like this:

Код:
CMD:accept(playerid, params[])
{
    new choice[32];

    choice = "Teehee";

    sscanf(params, "s[32]", choice);

    if(!strcmp(choice, "namechange", true))
    {
        if(sscanf(params, "s[32]d", choice, id))
            return SCM(playerid, COLOR_GREY, "USAGE: /accept namechange [id]");
    
        if(PlayerInfo[playerid][AdminLevel] < 1) return AuthorMsg(playerid);

        new id;

        if(sscanf(params, "i", id)) return SCM(playerid, COLOR_GREY, "USAGE: /accept namechange [id]");

        if(id == INVALID_PLAYER_ID) return SendClientMessageF(playerid, COLOR_GREY, "Invalid Player ID.");

        if(RequestNameChange[id] != 1) return SCM(playerid, COLOR_GREY, "That player is not requesting a name change.");
    }
    else return SCM(playerid, COLOR_GREY, "USAGE: /accept (hire, interview, gag, tie, ticket)");
	
    return 1;
}
EDIT: You must give a random value to choice or else this doesn't work completely.
How can you do the
PHP код:
if(sscanf(params"s[32]d"choiceid))
            return 
SCM(playeridCOLOR_GREY"USAGE: /accept namechange [id]"); 
yet you declare the id variable AFTER this sscanf?
Reply
#8

Quote:
Originally Posted by thefirestate
Посмотреть сообщение
Liam, here's your problem. If you use if(sscanf(params, "s[32]", params)) then check if the params include namechange with if(!strcmp(params, "namechange", true) it will work but once you do if(sscanf(params, "s[32]i", params, id)) the params would become namechange 1 and the only solution is checking by this way : if(!strcmp(params, "namechange", true, 9) where 9 is the string lenght.

PHP код:
CMD:accept(playeridparams[]) 

    if(
sscanf(params"s[32]"params)) return SCM(playeridCOLOR_GREY"USAGE: /accept (hire, interview, gag, tie, ticket)"); 
    if(!
strcmp(params"namechange"true9)) 
    { 
        if(
PlayerInfo[playerid][AdminLevel] < 1) return AuthorMsg(playerid); 
        new 
id
        if(
sscanf(params"s[32]i"paramsid)) return SCM(playeridCOLOR_GREY"USAGE: /accept namechange [id]"); 
        if(
id == INVALID_PLAYER_ID) return SendClientMessageF(playeridCOLOR_GREY"Invalid Player ID."); 
        if(
RequestNameChange[id] != 1) return SCM(playeridCOLOR_GREY"That player is not requesting a name change."); 
I literally just seen this. This solution fixed it, I tried using strlen on Choice, then doing sscanf(params, "s[%d][i]", strlen(choice) etc etc, however that never worked. TheFireState has got it working. Thanks for the assistance guys, and thank you, firestate
Reply
#9

Quote:
Originally Posted by LiamM
Посмотреть сообщение
How can you do the
PHP код:
if(sscanf(params"s[32]d"choiceid))
            return 
SCM(playeridCOLOR_GREY"USAGE: /accept namechange [id]"); 
yet you declare the id variable AFTER this sscanf?
I copied your command. Didn't even notice the declaration of the variable 'id'.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)