SA-MP Forums Archive
[SOLVED \o/]sscanf and multiple optional parameters - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+---- Forum: Help Archive (https://sampforum.blast.hk/forumdisplay.php?fid=89)
+---- Thread: [SOLVED \o/]sscanf and multiple optional parameters (/showthread.php?tid=143248)

Pages: 1 2


[SOLVED \o/]sscanf and multiple optional parameters - dcmd_crash - 22.04.2010

Hi, I'm trying to convert my whole gamemode (235 commands -_-) to sscanf and ZCMD .. it's going great, but I have come up against a problem.

The command below is to spawn a vehicle with optional colour params.. basically, if they don't enter a colour .. or two colours then the vehicle colour is set to a random colour. Could someone please explain to me how I would do this? I can't see any way to use !strlen and it doesn't even work with ZCMD anyways.

pawn Код:
CMD:v(playerid, params[])
{
    if(PlayerInfo[playerid][Level] >= 3 || IsPlayerAdmin(playerid))
    {
        new car, colour1, colour2, vehicle, Int, Float: Angle, Float: X,Float: Y,Float: Z, world;
        GetPlayerPos(playerid, X, Y, Z); Int = GetPlayerInterior(playerid); world = GetPlayerVirtualWorld(playerid); GetPlayerFacingAngle(playerid,Angle);
        if(sscanf(params, "dzz", car, colour1, colour2)) return SendClientMessage(playerid, Red,"USAGE: /v [model ID] [colour 1] [colour 2]");
        if(!strlen(colour1)) colour1st = random(126); else colour1st = strval(tmp2);
        if(!strlen(colour2)) colour2nd = random(126); else colour2nd = strval(tmp3);

        if(!strlen(params)) return SendClientMessage(playerid, Red,"USAGE: /v [model ID] [colour 1] [colour 2]");
        if(car < 400 || car > 611) return SendClientMessage(playerid, Red, "Invalid Vehicle Model");
      vehicle = CreateVehicle(car, X+3, Y, Z, Angle, colour1, colour2, -1);
      vName = GetVehicleName(vehicle);
      if(world > 0) return SetVehicleVirtualWorld(vehicle,world);
      LinkVehicleToInterior(vehicle,Int);
      format(string, sizeof(string), "%s successfully spawned. To destroy it, use /dv", vName);
      return SendClientMessage(playerid,White,string);
    } else return 0;
}
Any help appreciated, thanks.


Re: sscanf and multiple optional parameters - cessil - 22.04.2010

new car;
new colour1 = random(number here);
new colour2 = random(number here);

if(sscanf(params, "d", car)) return SendClientMessage(playerid, Red,"USAGE: /v [model ID] [colour 1] [colour 2]");
if(!sscanf(params, "ddd", car,colour1,colour2))
{
rest of code here


}


Re: sscanf and multiple optional parameters - dcmd_crash - 22.04.2010

Is there not any way to make the colour params optional with "z" but also check if they have entered an optional param... so like, if they don't enter a colour it will be a random one and if they do it will be that..? I'm new to sscanf so forgive my ignorance.


Re: sscanf and multiple optional parameters - ¤Adas¤ - 22.04.2010

Define "color" as a string, then it will be possible. and use strval


Re: sscanf and multiple optional parameters - dcmd_crash - 22.04.2010

Not being funny, but the whole point in using sscanf (for me) was to get rid of strval and strtok.. plus if the colours were defined as a string, would they not have to be entered as a string? It wouldn't process it if it was a numeric entry would it?


Re: sscanf and multiple optional parameters - dcmd_crash - 23.04.2010

Hi.


Re: sscanf and multiple optional parameters - woot - 23.04.2010

pawn Код:
else colour1st = strval(colour1);
else colour2nd = strval(colour2);
I wonder why it didn't output a compiling error with tmp2,tmp3.



Re: sscanf and multiple optional parameters - dcmd_crash - 23.04.2010

Quote:
Originally Posted by //exora
pawn Код:
else colour1st = strval(colour1);
else colour2nd = strval(colour2);
I wonder why it didn't output a compiling error with tmp2,tmp3.
Meh, those are some bits of code that I was trying out .. I still can't understand how to do this with sscanf


Re: sscanf and multiple optional parameters - biltong - 23.04.2010

I can answer the random colour part, just use CreateVehicle(modelid, x, y, z, -1, -1, 60);

Then -1s mean random colour.

As for the optional parameters, I think if you do something like this:
pawn Код:
CMD:v(playerid, params[]
{
    new car, colour1, colour2;
    if(!sscanf(params, "ddd", car, colour1, colour2))
    {
         //code here
    }
    else if(!sscanf(params, "d", car))
    {
        //same code here with random colours
    }
    else return SendClientMessage(playerid, Red, "USAGE: /v [modelid] [colour1 optional] [colour2 optional]");
    return 1;
}
would work.



Re: sscanf and multiple optional parameters - Calgon - 23.04.2010

strval() isn't necessarily slow, strtook is slow. There's no point in not using it at all, because there's definitely going to be instances where you need to use it.


Re: sscanf and multiple optional parameters - dice7 - 23.04.2010

Here's a snippet I made some time ago for a script
pawn Код:
new
        car[20],
        col1 = -1,
        col2 = -1,
        spaces = 0;
    if (sscanf(params, "sz", car, msg4))
    {
        SendClientMessage(playerid, COLOR_SYSTEM, "*** USAGE: /gangcar [carname] [custom name] [color1] [color2]");
    SendClientMessage(playerid, COLOR_SYSTEM, "*** You need to be in a turf you own to use this command.");
    SendClientMessage(playerid, COLOR_SYSTEM, "*** Color1 and Color2 are optional.");
    return 1;
    }
  new lenght, idx;
    for(lenght = strlen(msg4), idx = 0; idx < lenght; idx++) //checks for spaces (name_SPACE_color1_SPACE_color2)
    {
      if(msg4[idx] == ' ')
      {
        spaces++;
      }
    }

    if(spaces > 2) //more then just 3 words, cancel the process
    {
        SendClientMessage(playerid, COLOR_SYSTEM, "*** USAGE: /gangcar [carname] [custom name] [color1] [color2]");
        SendClientMessage(playerid, COLOR_SYSTEM, "*** You need to be in a turf you own to use this command.");
        SendClientMessage(playerid, COLOR_SYSTEM, "*** Color1 and Color2 are optional.");
        return 1;
    }
    else if(spaces == 0) //just the car name, store in the global variable
    {
      format(CarName[ turf ], MAX_PLAYER_NAME, "%s", msg4);
    }
    else if (spaces == 1) //one parameter to much, the last one will be ignored
    {
        if (sscanf(msg4, "sz", CarName[ turf ], msg1))
        {
            SendClientMessage(playerid, COLOR_SYSTEM, "*** USAGE: /gangcar [carname] [custom name] [color1] [color2]");
            SendClientMessage(playerid, COLOR_SYSTEM, "*** You need to be in a turf you own to use this command.");
            SendClientMessage(playerid, COLOR_SYSTEM, "*** Color1 and Color2 are optional.");
            return 1;
        }
    }
    else if (spaces == 2)//car name, col1, col2 = perfect
    {
        if (sscanf(msg4, "sdd", CarName[ turf ], col1, col2))
        {
            SendClientMessage(playerid, COLOR_SYSTEM, "*** USAGE: /gangcar [carname] [custom name] [color1] [color2]");
            SendClientMessage(playerid, COLOR_SYSTEM, "*** You need to be in a turf you own to use this command.");
            SendClientMessage(playerid, COLOR_SYSTEM, "*** Color1 and Color2 are optional.");
            return 1;
        }
    }
It can be vastly improved, but you'll get the idea. Or you could try
pawn Код:
new id, col1, col2, string[128];
sscanf(cmdtext, "dz", id, string);

if(sscanf(string, "dd", col1, col2))
{
    //use random colors
}



Re: sscanf and multiple optional parameters - dcmd_crash - 23.04.2010

Thanks for the help, dudes. Those last few posts explained it better.


Re: sscanf and multiple optional parameters - dcmd_crash - 24.04.2010

Ok, cannot believe I'm still stuck on this crap. Basically, I've written the command .. but now I have no idea how to let the user enter either a partial or full name of the car (Infernus, Inf, etc.) or the model ID, I mean, it was EASY with strtok, but now I'm stuck ..

pawn Код:
CMD:v(playerid, params[])
{
    if(PlayerInfo[playerid][Level] >= 3 || IsPlayerAdmin(playerid))
    {
        new car, vIsName, colour1, colour2, vehicle, Int, Float: Angle, Float: X,Float: Y,Float: Z, world;
        if(sscanf(params, "ddd", car, colour1, colour2)) return SendClientMessage(playerid, Red, "USAGE: /v [ModelID/Name] [Colour 1] [Colour 2] (Colours optional)");
        {
            GetPlayerPos(playerid, X, Y, Z); Int = GetPlayerInterior(playerid); world = GetPlayerVirtualWorld(playerid); GetPlayerFacingAngle(playerid,Angle);
            if(car < 400 || car > 611) return SendClientMessage(playerid, Red, "Invalid Vehicle Model");
      if(!IsNumeric(car)) vIsName = GetVehicleModelIDFromName(car); else vIsName = strval(car); // This bit I'm stuck at :|
            vehicle = CreateVehicle(vIsName, X+3, Y, Z, Angle, colour1, colour2, -1);
        vName = GetVehicleName(vehicle);
        if(world > 0) return SetVehicleVirtualWorld(vehicle,world);
        LinkVehicleToInterior(vehicle,Int);
        DynamicV[vehicle] = 1;
        format(string, sizeof(string), "%s successfully spawned. To destroy it, use /dc", vName);
        return SendClientMessage(playerid,White,string);
        }
        else if(sscanf(params, "d", car))
        {
      GetPlayerPos(playerid, X, Y, Z); Int = GetPlayerInterior(playerid); world = GetPlayerVirtualWorld(playerid); GetPlayerFacingAngle(playerid,Angle);
            if(car < 400 || car > 611) return SendClientMessage(playerid, Red, "Invalid Vehicle Model");
      if(!IsNumeric(car)) vIsName = GetVehicleModelIDFromName(car); else vIsName = strval(car);
            vehicle = CreateVehicle(vIsName, X+3, Y, Z, Angle, -1, -1, -1);
        vName = GetVehicleName(vehicle);
        if(world > 0) return SetVehicleVirtualWorld(vehicle,world);
        LinkVehicleToInterior(vehicle,Int);
        DynamicV[vehicle] = 1;
        format(string, sizeof(string), "%s successfully spawned. To destroy it, use /dc", vName);
        return SendClientMessage(playerid,White,string);
        }
    } else return 0;
    return 1;
}
Any help is appreciated, as usual.


Re: sscanf and multiple optional parameters - woot - 24.04.2010

pawn Код:
CMD:v(playerid, params[])
{
    if(PlayerInfo[playerid][Level] >= 3 || IsPlayerAdmin(playerid))
    {
        new car[ 64 ], vIsName, colour1, colour2, vehicle, Int, Float: Angle, Float: X,Float: Y,Float: Z, world;
        if(sscanf(params, "sdd", car, colour1, colour2)) return SendClientMessage(playerid, Red, "USAGE: /v [ModelID/Name] [Colour 1] [Colour 2] (Colours optional)");
        {
            GetPlayerPos(playerid, X, Y, Z); Int = GetPlayerInterior(playerid); world = GetPlayerVirtualWorld(playerid); GetPlayerFacingAngle(playerid,Angle);
            if(!IsNumeric(car)) vIsName = GetVehicleModelIDFromName(car); else vIsName = strval(car); // This bit I'm stuck at :|
            if(car < 400 || car > 611) return SendClientMessage(playerid, Red, "Invalid Vehicle Model");
            vehicle = CreateVehicle(vIsName, X+3, Y, Z, Angle, colour1, colour2, -1);
            if(world > 0) return SetVehicleVirtualWorld(vehicle,world);
            LinkVehicleToInterior(vehicle,Int);
            DynamicV[vehicle] = 1;
            format(string, sizeof(string), "%s successfully spawned. To destroy it, use /dc", GetVehicleName(vehicle));
            return SendClientMessage(playerid,White,string);
        }
        else if(sscanf(params, "s", car))
        {
            GetPlayerPos(playerid, X, Y, Z); Int = GetPlayerInterior(playerid); world = GetPlayerVirtualWorld(playerid); GetPlayerFacingAngle(playerid,Angle);
            if(!IsNumeric(car)) vIsName = GetVehicleModelIDFromName(car); else vIsName = strval(car);
            if(car < 400 || car > 611) return SendClientMessage(playerid, Red, "Invalid Vehicle Model");
            vehicle = CreateVehicle(vIsName, X+3, Y, Z, Angle, -1, -1, -1);
            if(world > 0) return SetVehicleVirtualWorld(vehicle,world);
            LinkVehicleToInterior(vehicle,Int);
            DynamicV[vehicle] = 1;
            format(string, sizeof(string), "%s successfully spawned. To destroy it, use /dc", GetVehicleName(vehicle));
            return SendClientMessage(playerid,White,string);
        }
    } else return 0;
    return 1;
}



Re: sscanf and multiple optional parameters - dcmd_crash - 24.04.2010

Here are the compile errors for your edit .. the one's I've commented out are the one's that have nothing to do with it or I know what the problem is.


pawn Код:
(4147) : error 033: array must be indexed (variable "car")
//(4152) : error 017: undefined symbol "GetVehicleName"
(4155) : warning 225: unreachable code
(4155) : error 029: invalid expression, assumed zero
(4155) : warning 215: expression has no effect
(4155) : error 001: expected token: ";", but found "if"
(4159) : error 033: array must be indexed (variable "car")
//(4164) : error 017: undefined symbol "GetVehicleName"
Here is the code again:

pawn Код:
CMD:v(playerid, params[])
{
    if(PlayerInfo[playerid][Level] >= 3 || IsPlayerAdmin(playerid))
    {
        new car[ 64 ], string[128], vIsName, colour1, colour2, vehicle, Int, Float: Angle, Float: X,Float: Y,Float: Z, world;
        if(sscanf(params, "sdd", car, colour1, colour2)) return SendClientMessage(playerid, Red, "USAGE: /v [ModelID/Name] [Colour 1] [Colour 2] (Colours optional)");
        {
            GetPlayerPos(playerid, X, Y, Z); Int = GetPlayerInterior(playerid); world = GetPlayerVirtualWorld(playerid); GetPlayerFacingAngle(playerid,Angle);
            if(!IsNumeric(car)) vIsName = GetVehicleModelIDFromName(car); else vIsName = strval(car); // This bit I'm stuck at :|
            if(car < 400 || car > 611) return SendClientMessage(playerid, Red, "Invalid Vehicle Model");
            vehicle = CreateVehicle(vIsName, X+3, Y, Z, Angle, colour1, colour2, -1);
            if(world > 0) return SetVehicleVirtualWorld(vehicle,world);
            LinkVehicleToInterior(vehicle,Int);
        DynamicV[vehicle] = 1;
        format(string, sizeof(string), "%s successfully spawned. To destroy it, use /dc", GetVehicleName(vehicle));
        return SendClientMessage(playerid,White,string);
        }
        else if(sscanf(params, "s", car)) // Line 4155 here
        {
      GetPlayerPos(playerid, X, Y, Z); Int = GetPlayerInterior(playerid); world = GetPlayerVirtualWorld(playerid); GetPlayerFacingAngle(playerid,Angle);
      if(!IsNumeric(car)) vIsName = GetVehicleModelIDFromName(car); else vIsName = strval(car);
      if(car < 400 || car > 611) return SendClientMessage(playerid, Red, "Invalid Vehicle Model");
            vehicle = CreateVehicle(vIsName, X+3, Y, Z, Angle, -1, -1, -1);
        if(world > 0) return SetVehicleVirtualWorld(vehicle,world);
        LinkVehicleToInterior(vehicle,Int);
        DynamicV[vehicle] = 1;
        format(string, sizeof(string), "%s successfully spawned. To destroy it, use /dc", GetVehicleName(vehicle));
        return SendClientMessage(playerid,White,string);
        }
    } else return 0;
    return 1;
}



Re: sscanf and multiple optional parameters - woot - 24.04.2010

Do you use the old sscanf or sscanf 2.0 (plugin) ?


Re: sscanf and multiple optional parameters - dcmd_crash - 24.04.2010

The old one, I thought I'd start off with the original one, thought it might be easier to learn/implement?


Re: sscanf and multiple optional parameters - biltong - 24.04.2010

I believe sscanf returns 0 if it's conditions are met or something. At line 4155, it should be:
pawn Код:
if(sscanf(params, "s", car)) return SendClientMessage(/*error message*/
else
{
  //code...
}



Re: sscanf and multiple optional parameters - dcmd_crash - 24.04.2010

All I really need is a way to check if they entered a colour param and then I wouldn't need to rewrite a perfectly fine command, I thought ssacanf is meant to makes things easier lol. If only there was some way to check like using if(!strlen(params) does with strtok .. but if I use !strlen it doesn't work at all .. don't know whether that's ZCMD's fault or sscanf


Re: sscanf and multiple optional parameters - Virtual1ty - 24.04.2010

So... you want to check if a string is empty? Use isnull. I'm sure sscanf must have inbuilt isnull checking.

Edit: check at this, might help you:
pawn Код:
CMD:car(playerid,params[]) {
    if(AccountInfo[playerid][aAdminLevel] >= 1) {
      new tmp[128], tmp2[128], tmp3[128], Index; tmp = strtok(params,Index), tmp2 = strtok(params,Index); tmp3 = strtok(params,Index);
      if(isnull(tmp)) return SendClientMessage(playerid, red, "USAGE: /car [Modelid/Name] [colour1] [colour2]");
        new car, colour1, colour2, sendername[MAX_PLAYER_NAME];
        if(!IsNumeric(tmp)) car = GetVehicleModelIDFromName(tmp); else car = strval(tmp);
        if(car < 400 || car > 611) return SendClientMessage(playerid, red, "ERROR: Invalid Vehicle Model");
        if(isnull(tmp2)) colour1 = random(126); else colour1 = strval(tmp2);
        if(isnull(tmp3)) colour2 = random(126); else colour2 = strval(tmp3);
        new LVehicleID,Float:X,Float:Y,Float:Z, Float:Angle,int1; GetPlayerPos(playerid, X,Y,Z); GetPlayerFacingAngle(playerid,Angle); int1 = GetPlayerInterior(playerid);
        LVehicleID = CreateVehicle(car, X+3,Y,Z, Angle, colour1, colour2, -1); LinkVehicleToInterior(LVehicleID,int1);
        CreatedCars[CreatedCar] = LVehicleID;
        CreatedCar ++;
        GetPlayerName(playerid, sendername, sizeof(sendername));
        //format(string, sizeof(string), "%s spawned a \"%s\" (Model:%d) colour (%d, %d), at %0.2f, %0.2f, %0.2f", sendername, VehNames[car-400], car, colour1, colour2, X, Y, Z);
        format(string, sizeof(string), "You have spawned a \"%s\" (Model:%d) colour (%d, %d)", VehNames[car-400], car, colour1, colour2);
        PutPlayerInVehicle(playerid, LVehicleID, 0);
        return SendClientMessageToAdmins(ADMIN_RED, string, 1);
    }
    return 1;
}
Edit2: I'm off, good night all, @_❼_ : hope it helped you.