[Tutorial] How to create a fishing command.
#1

Hello, thank you for visiting my tutorial today.

First things first, I am going to list the items that this tutorial will involve, which hopefully by the end you will understand!
  • How to create a /fish command.
  • How to create a timer to release what fish you have got.
  • How to create a /buy command working with dialogs.
  • How to create a /sell command to sell the fish you have caught.
Note: This will be for use in a Filterscript, you must edit it to work in your own system.

This system will be using ZCMD for the command processor. (To download it, hover over "ZCMD" and go to that page. Then read through it until you get to "download").

It will also be using sscanf2, for work with the command processor. (To download it, hover over "sscanf2" and go to that page. Then read through it until you get to "download").

I will be making clear comments about what I am doing, so if you struggle you should be able to read them and then you should be good to continue. Although, if you have any problems, please don't hesitate to post on here!

Let's get started!

First things first:
(Includes and define)

At the top of the script, make sure that you have got this included:
pawn Код:
#include <a_samp>
This here, will allow you the usage of the "Pawn" scripting for SA-MP. Without this, you will struggle to script anything.

You must also include the following:
pawn Код:
#include <zcmd>
This here, is ensuring that you are using the command processor that is by Zeex. You must have the zcmd.inc from the download page which is linked at the top of this tutorial, inside of your "Pawno\includes" folder, if you don't you will have an error saying that it can't read from the file. Just like this:
Код:
fatal error 100: cannot read from file: "zcmd"
If you don't get that error and you receive this:

Код:
Pawn compiler 3.2.3664	 	 	Copyright © 1997-2006, ITB CompuPhase
You are doing it fine up to now.

pawn Код:
#include <sscanf2>
This here, is ensuring that you are using the command processor that is by ******. You must have the sscanf2.inc from the download page which is linked at the top of this tutorial, inside of your "Pawno\includes" folder, if you don't you have have an error saying that it can't read from the file. Just like this:
Код:
fatal error 100: cannot read from file: "sscanf2"
If you don't get that error and you receive this:

Код:
Pawn compiler 3.2.3664	 	 	Copyright © 1997-2006, ITB CompuPhase
You are doing it fine up to now.

Now that we have got that part done, we need to define some colours into the script!

We are going to be defining two colours, "Red" and "White".

To do this, underneath where you have done the "#include" sections, add the two following pieces of script:

pawn Код:
#define WHITE 0xFFFFFFAA
#define RED 0xAA3333AA
This is defining the colours, so that when we use them in a SendClientMessage; it will work.

Example:
pawn Код:
SendClientMessage(playerid, WHITE, "This will show the colour in WHITE.");
SendClientMessage(playerid, RED, "This will show the colour in RED.");
If you understand so far, please continue reading...

Second section:
(Player variables and forwards)

Let's start by explaining to you the function that involves "forward".

To create a timer, for example. What we are doing is when we have /fish, the timer will start an 5 seconds later; we will have our fish.

A forward, will define a "public" function.

So, to define our public function, we are going to need to add something along the lines of this:

pawn Код:
forward FishCatchTimer(playerid);
The function is now called: FishCatchTimer. The "(playerid)" section of this forward means that it will be used for a player who set the timer off.

Next, we need to add our player variables!

To do this, all we need to do is add "new WhatOurVariableIs[MAX_PLAYERS];", that would define it for the player's that are in the game.

So, to add ours we will need to add this to the top of the script:
pawn Код:
new HasRod[MAX_PLAYERS], HasBait[MAX_PLAYERS], Fishing[MAX_PLAYERS], Fish[MAX_PLAYERS][5];
If you try to compile when you have just added these; you are going to get 3 warnings. Not errors, but warnings because none of the "new's" have been used as of yet. Here is what the warning will look like:
Код:
warning 203: symbol is never used: "Fishing"
warning 203: symbol is never used: "HasBait"
warning 203: symbol is never used: "HasRod"
warning 203: symbol is never used: "Fish"
Don't worry about these warnings though, because they will all be removed by you in time, along more of the script.

Under "OnPlayerConnect(playerid)", you will want to notify the script to clear all player variables, so then the player doesn't have any items such as a fishing rod or bait. More is explained below.

pawn Код:
public OnPlayerConnect(playerid)
{
    //You will want to add the following:
    Fishing[playerid] = 0;
    HasBait[playerid] = 0;
    HasRod[playerid] = 0;
    Fish[playerid][1] = 0;
    Fish[playerid][2] = 0;
    Fish[playerid][3] = 0;
    Fish[playerid][4] = 0;
    return 1;
}
The reason for this is, to reset all player variables that we have just added.

Having: "Fishing[playerid] = 0;" will make it so the script can see that the player isn't currently fishing.
Having: "HasBait[playerid] = 0;" will make it so the script can see that the player doesn't have any bait.
Having: "HasRod[playerid] = 0;" will make it so the script can see that the player doesn't have a fishing rod.
Having: "Fish[playerid][1-4] = 0;" will make it so the script can see that the player hasn't caught any fish yet.

Also, now if you tried to compile. You should have noticed that the warning codes have gone. This is because you have now used the variables in the script, so they aren't "Not being used".

The thing that I have show you above with OnPlayerConnect(playerid), you need to do the same for OnPlayerDisconnect(playerid, reason).

pawn Код:
public OnPlayerDisconnect(playerid, reason)
{
    //You will want to add the following:
    Fishing[playerid] = 0;
    HasBait[playerid] = 0;
    HasRod[playerid] = 0;
    Fish[playerid][1] = 0;
    Fish[playerid][2] = 0;
    Fish[playerid][3] = 0;
    Fish[playerid][4] = 0;
    return 1;
}
That will ensure the script that when a player disconnects, it will remove all of the variables that have been stored in the script, whilst the player has been connected.

Now that we have the defines, includes and player variables out of the way, we can crack on with the rest of the script!

Third section:
(Commands and timers(with public function))

This section of the tutorial, will show you the basics of commands with "zcmd", also how to create timers with a public function to display the outcome.

Commands with zcmd are a lot easier that using strcmp. The reason being, you don't have to worry about having an "if" statement on the command line, instead it's just as easy as this:

pawn Код:
command(fish, playerid, params[])
That above, defines the command "fish". That means that when we go in game, we can then do /fish and we will get an outcome instead of "Server: Unknown command".

To carry on the command, we must first place an opening bracket, like so:

pawn Код:
command(fish, playerid, params[])
{
    if(IsPlayerInRangeOfPoint(playerid, 5.0, -2105.3228, -124.2982, 37.2531))
    {
        if(Fishing[playerid] == 1) return SendClientMessage(playerid, RED, "You are already fishing!");
        if(Fish[playerid][1] >= 1 && Fish[playerid][2] >= 1 && Fish[playerid][3] >= 1 && Fish[playerid][4] >= 1) return SendClientMessage(playerid, WHITE, "You have too many fish to fish again.");
        if(HasRod[playerid] == 1)
        {
            if(HasBait[playerid] == 1)
            {
                Fishing[playerid] = 1;
                SendClientMessage(playerid, WHITE, "You have started to fish. Please wait 5 seconds.");
                SetTimerEx("FishCatchTimer", 5000, false, "i", playerid);
            }
            else return SendClientMessage(playerid, RED, "You don't have any bait!");
        }
        else return SendClientMessage(playerid, RED, "You haven't got a fishing rod!");
    }
    return 1;
}
Now to explain:

The "if(IsPlayerInRangeOfPoint(playerid, Float: range, Float: x, Float: y, Float: z))" section, is there to make sure that a player is in range of a certain point. This isn't needed in all cases, but if you want to have your /fish on one certain part of the map, then you can add this.

playerid - This is the playerid of who it is checking is in the range of the fishing spot.
Float:range - This is how far away from the actual spot the person can use /fish at.
Float: x - This is the X axis on the map where the spot is.
Float: y - This is the Y axis on the map where the spot is.
Float: z - This is the Z axis on the map where the spot is.

To get the position that you want to have the /fish command for, all you need to do is:

1. Go in game on a Server.
2. Go to the spot in the server you want to have your /fish command.
3. When you are on the spot for the command, use '/save'.
4. Quit GTA SA-MP and go into you "My documents" then into the "GTA San Andreas User Files", then go to the following folder: "SAMP". Then inside that folder, there should be a .txt file called: "savedpositions".

If it is there, you should have something along the lines of this:

Код:
AddPlayerClass(72, -2105.3228, -124.2982, 37.2531, 0.0, 0,0,0,0,0,0);
I will explain how to get the X, Y and Z coordinates from here.

If you look, it has:

AddPlayerClass - We can ignore this.
The, it has an open bracket with "72" - We can ignore this too, this is just the skin ID.
Then, it has a coordinate, this is the X coordinate - -2105.3228, this is the X coordinate.
Then, it has another coordinate, this is the Y coordinate - -124.2982, this is the Y coordinate.
Then, it has yet another coordinate, this is the Z coordinate - 37.2531, this is the Z coordinate.

That's how to get the X Y and Z coordinate from your savedpositions.txt file.

The next part is:

"if(Fishing[playerid] == 1) return SendClientMessage(playerid, RED, "You are already fishing!");"

This is checking if the playerid is already fishing or not. If the players variable is equal to 1, that means that he is already fishing, therefore he can't spam /fish for rewards.

"if(HasRod[playerid] == 1)"

This is checking if the playerid has got a fishing rod. If the player hasn't got one, the code will stop here.

"if(HasBait[playerid] == 1)"

This is checking if the playerid has got some bait. If the player hasn't got any, the code will stop here.

"if(Fish[playerid][1] >= 1 && Fish[playerid][2] >= 1 && Fish[playerid][3] >= 1 && Fish[playerid][4] >= 1) return SendClientMessage(playerid, WHITE, "You have too many fish to fish again.");"

This is checking to see if the player has caught too many fish and they have been stored in the variable. (Each fish will add an amount to one of the variables).

"Fishing[playerid] = 1;"

This is setting the players variable to 1, so then if he attempts to do the /fish command again, it will have an anti-spam usage on it.

"SendClientMessage(playerid, WHITE, "You have started to fish. Please wait 5 seconds.");"

This is sending a message to the player, notifying him that he has started to fish.

"SetTimerEx("FishCatchTimer", 5000, false, "i", playerid);"

This is setting a timer for the player, so then the player can catch a fish! The timer is 5 seconds long, which will NOT repeat itself.

"else return SendClientMessage(playerid, RED, "You don't have any bait!");"

This else statement, is checking if the player has any bait. If the player doesn't have bait, it will return the message "You don't have any bait!".

"else return SendClientMessage(playerid, RED, "You haven't got a fishing rod!");"

This else statement, is checking if the player has a rod. If the player doesn't have a rod, it will return the message "You haven't got a fishing rod!".

Now, onto the public funtion.

This is called when the 5 seconds are up with the fishing timer; EG: /fish [wait 5 seconds] [catch fish].

This is what it would look like:

pawn Код:
public FishCatchTimer(playerid)
{
    Fishing[playerid] = 0;
    switch(random(3))
    {
        case 0:
        {
            if(Fish[playerid][1] < 1)
            {
                SendClientMessage(playerid, WHITE, "You have caught a 41 pound catfish!");
                Fish[playerid][4] = 41;
            }
            else if(Fish[playerid][2] < 1)
            {
                SendClientMessage(playerid, WHITE, "You have caught a 41 pound catfish!");
                Fish[playerid][4] = 41;
            }
            else if(Fish[playerid][3] < 1)
            {
                SendClientMessage(playerid, WHITE, "You have caught a 41 pound catfish!");
                Fish[playerid][4] = 41;
            }
            else if(Fish[playerid][4] < 1)
            {
                SendClientMessage(playerid, WHITE, "You have caught a 41 pound catfish!");
                Fish[playerid][4] = 41;
            }
            else return 1;
        }
        case 1:
        {
            if(Fish[playerid][1] < 1)
            {
                SendClientMessage(playerid, WHITE, "You have caught a mammoth whale! It weighs 12552 pound!");
                Fish[playerid][1] = 12552;
            }
            else if(Fish[playerid][2] < 1)
            {
                SendClientMessage(playerid, WHITE, "You have caught a mammoth whale! It weighs 12552 pound!");
                Fish[playerid][2] = 12552;
            }
            else if(Fish[playerid][3] < 1)
            {
                SendClientMessage(playerid, WHITE, "You have caught a mammoth whale! It weighs 12552 pound!");
                Fish[playerid][3] = 12552;
            }
            else if(Fish[playerid][4] < 1)
            {
                SendClientMessage(playerid, WHITE, "You have caught a mammoth whale! It weighs 12552 pound!");
                Fish[playerid][4] = 12552;
            }
        }
        case 2:
        {
            SendClientMessage(playerid, WHITE, "You have caught a tin-can and threw it away.");
            GameTextForPlayer(playerid, "~r~Can thrown away.", 3000, 5);
        }
    }
    return 1;
}

Time to explain:

"Fishing[playerid] = 0;" - This is telling the script that the playerid isn't fishing anymore and can /fish again.

"switch(random(3))" - This is a "switch". The switch is selecting from 3 different outputs. Meaning, it will "randomize" which one to choose and then it will do one of the cases.

"case 0:" - Always start off with "case 0:", as this is the first case to be called.

"SendClientMessage(playerid, WHITE, "You have caught a 41 pound catfish!");" - This is sending a message to the player notifying him of catching a fish.

if(Fish[playerid][1] < 1) (and the others) - This is checking to see if there is a fish in each slot and which slot to put it in.

Fish[playerid][4] = 41; - This indicates that it has gone into slot 4, weighing 41 pounds.

With the rest being self-explanatory I will move onto the /buy command.

pawn Код:
command(buy, playerid, params[])
{
    ShowPlayerDialog(playerid, 1, DIALOG_STYLE_LIST, "Fish shop", "Fishing Rod (FREE)\nFishing Bait(FREE)", "Buy", "Cancel");
    return 1;
}
Here is what this command does:

ShowPlayerDialog(playerid, 1, DIALOG_STYLE_LIST, "Fish shop", "Fishing Rod(FREE)\nFishing Bait(FREE)", "Buy", "Cancel"); - This shows a dialog on screen to the player. With the ID of the dialog being "1", the style being a list.

This is how we would function the dialog to work, with OnDialogResponse.

pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    switch(dialogid)
    {
        case 1:
        {
            if(!response) return 1;
            else
            {
                switch(listitem)
                {
                    case 0:
                    {
                        SendClientMessage(playerid, RED, "You have purchased a fishing rod!");
                        HasRod[playerid] = 1;
                    }
                    case 1:
                    {
                        SendClientMessage(playerid, RED, "You have purchased some fishing bait!");
                        HasBait[playerid] = 1;
                    }
                }
            }
            return 1;
        }
    }
    return 1;
}
Time to narrow it down.

"switch(dialogid)" - This is switching the dialogid's, which is pretty much self explanatory.

"case 1:" - The dialogid is "1", therefore the case will become "case 1:".

"if(!response) return 1;" - If the person presses "Cancel" on the Dialog, it will return 1 and continue gameplay.

"switch(listitem)" - This is switching through cases of listitems.

"case 0:" - This means that it's the first item on the list.

"SendClientMessage(playerid, RED, "You have purchased a fishing rod!");" - This is notifying the playerid that they have bought a fishing rod.

"HasRod[playerid] = 1;" - This is telling the script that the playerid has now got a fishing rod.

"case 1:" - This means that it's the second item on the list.

"SendClientMessage(playerid, RED, "You have purchased some fishing bait!");" - This is notifying the playerid that they have bought some fishing bait.

"HasBait[playerid] = 1;" - This is telling the script that the playerid has now got some bait.

Now on to the /sell command.

pawn Код:
command(sell, playerid, params[])
{
    new fishslot, string[256];
    if(sscanf(params, "i", fishslot)) return SendClientMessage(playerid, WHITE, "Server: /sell [fish slot(1-4)]");
    {
        if(fishslot > 4 || fishslot < 1) return SendClientMessage(playerid, WHITE, "Fish slots are from 1 - 4.");
        else
        {
            if(Fish[playerid][fishslot] > 1)
            {
                GivePlayerMoney(playerid, Fish[playerid][fishslot] * 2);
                format(string, sizeof(string), "You have sold a fish out of slot %d for $%d!", fishslot, Fish[playerid][fishslot] * 2);
                SendClientMessage(playerid, WHITE, string);
                format(string, sizeof(string), "~g~+$%d", Fish[playerid][fishslot] * 2);
                GameTextForPlayer(playerid, string, 3000, 5);
            }
        }
    }
    return 1;
}
"new fishslot, string[256];" - These are creating variables that will be used in the future for this command.

"if(sscanf(params, "i", fishslot)) return SendClientMessage(playerid, WHITE, "Server: /sell [fish slot(1-4)]");" - This is checking if the player has typed a number after "/sell" instead of just /sell.

"if(fishslot > 4 || fishslot < 1) return SendClientMessage(playerid, WHITE, "Fish slots are from 1 - 4.");" - This is checking if the player has used /sell 5 or above or /sell 0 or below. If they do, it will stop the command and tell them that the slots are between 1 and 4.

"GivePlayerMoney(playerid, Fish[playerid][fishslot] * 2);" - This is multiplying the size of the fish by two and giving the player that much money. For example; I caught a 422 pound fish, I would receive $844 to my character.

That comes to an end of my tutorial, thank you for reading and if you have got any questions, please post them here!

I know that there is a lot of writing, but it all will help newbie's in scripting. I hope that people will learn something from this because it will make me feel better :3.

Otherwise, good luck with your scripting!

- iGetty out.
Reply
#2

Good job buddy. Very well done!

Very helpful and detailed. Having suggested this, I hope to see some other great tutorials!
Reply
#3

Thank you Freddy!

I'll be doing more :3 I just need some suggestions D:

Because my mind erases -.- haha.

Thanks mate! <3
Reply
#4

No worries buddy. You've done a great job here so far!
Reply
#5

How about you make a sell command for fishes?
Reply
#6

Good job man.This I was searching for .Thanks....
Reply
#7

His current one gives money upon catching of fish by the looks of it.
Reply
#8

Hmm ok didn't notice that

thanks for the tutorial
Reply
#9

You're welcome I will update it for the /sell command if you want?
Reply
#10

Yea would be great, then i can use it for my rpg server
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)