[Tutorial] Trucking Missions
#1

I've recently had a snoop around the forums and what was brought to my attention was that there was no decent tutorial explaining how to create trucking missions! This tutorial is the first in a series of tutorials I will be creating. In each of the tutorials that I create, I will provide you with the full script, however, I strongly advise that you run through the tutorial so you know what's actually happening in the script.

Things this tutorial does not provide for you:
  • Maps for truckers
  • Many mission locations
  • Administration Script
  • Any other class other than trucker
Throughout the tutorial I will be putting little things called 'checkup' in. They provide a link to what the script should look like up to that point.

This tutorial will give you the basic enumeration and 'getting' the information from an array that you have created. (Don't worry if you don't get what that means, I will explain later.

In this tutorial I will be using dcmd. I know it's not the speediest command processor, but I'm doing it so you can add it to the script easier.

Tutorial:

- Step 1:
At the top of the script you need the following line:
pawn Код:
#include <a_samp>
This will ensure that you have all the sa-mp callbacks.


- Step 2:
Also at the top of the script you will need the dcmd define line.
pawn Код:
#define dcmd(%1,%2,%3) if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1
This is the command processing system. I won't explain it because I cant be bothered


- Step 3:
Below your dcmd line, we need some color defines.
pawn Код:
#define COLOR_ORANGE 0xFFA500FF
#define COLOR_LIMEGREEN 0x32CD32FF
#define COLOR_ROYALBLUE 0x4169E1FF
#define COLOR_SALMON 0xFA8072FF
#define COLOR_GREY 0xAFAFAFAA
#define COLOR_GREEN 0x33AA33AA
#define COLOR_RED 0xAA3333AA
#define COLOR_YELLOW 0xFFFF00AA
#define COLOR_WHITE 0xFFFFFFAA
#define COLOR_BLUE 0x0000BBAA
#define COLOR_LIGHTBLUE 0x33CCFFAA
#define COLOR_RED 0xAA3333AA
These will make it easier for us to call back colors in messages.

**Checkup: http://pastebin.com/0dn3dFbm


- Step 4:
Now we will create an enumerator. This is where you create an array.
pawn Код:
enum MisLocationsEnum
{
    ID,
    LoadName[128],
    Float:LoadX,
    Float:LoadY,
    Float:LoadZ,
    Float:UnloadX,
    Float:UnloadY,
    Float:UnloadZ,
    Pay
}

- Step 5:
After the enum, we need the actual array in which the data will be called from.
pawn Код:
new MisLocations[][MisLocationsEnum] =
{
    {0, "Beer from Red County Brewery to Bone County Diner",-24.4073,-281.8898,5.9985,-305.4319,1315.6797,54.6189, 5980},
    {1, "Fuel from LV Oil Refinery to LV Dirtring",266.8981,1416.5417,10.2001,1097.5164,1741.7422,10.5474, 5700},
    {2, "Vehicle Parts from SF Airport ATC to Wang Cars",-1268.8223,13.6925,14.8682,-1986.3477,253.9728,35.8985, 3000},
    {3, "Fuel from SF Oil Refinery to RS Haul",-1016.3634,-688.2434,32.7284,-55.3397,-1138.2479,0.8052, 18770}//The last one in the array doesn't have a comma at the end.
};
An array will store all the data. As you may or may not have noticed, each part of the array follows the format in the enum!

i.e:
Код:
{id, text of mission, load:x co-ord, load:y co-ord, load:z co-ord, unload:x co-ord, unload:y co-ord, unload:z co-ord, pay}
**Checkup: http://pastebin.com/4BUYizkG


- Step 6:
Now we need to define the ID of the Trucking Class
pawn Код:
#define TEAM_TRUCKER 1
This will come in handy when we need to check what team a player is in!


- Step 7:
Now we need to add our class for truckers.
pawn Код:
main(){}

public OnGameModeInit()
{
    AddPlayerClass(72, -2105.3228, -124.2982, 37.2531, 0.0, 0,0,0,0,0,0);//Change the co-ords to where you want the player to spawn!
    return 1;
}
Okay, the part where it says main is required, but we dont use it at the moment, but it will come in useful in future tutorials.


- Step 8:
Of course we want text to appear on the screen when the player requests the class:

pawn Код:
public OnPlayerRequestClass(playerid, classid)
{
    switch (classid)
    {
        case 0:
        {
            GameTextForPlayer(playerid, "Trucker", 3000, 4);
            SetPlayerTeam(playerid, TEAM_TRUCKER);
        }
    }
    return 1;
}
This will show text for the player when they get to that class.
Also, remember in step 6 we defined 'TEAM_TRUCKER'? This is what we are using when we set the players team!

- Step 9:
A little feature I like is setting a players color for their icon depending upon which class they are in.
pawn Код:
public OnPlayerSpawn(playerid)
{
    if(GetPlayerTeam(playerid) == TEAM_TRUCKER)
    {
        SetPlayerColor(playerid, COLOR_GREEN);
    }
    return 1;
}

- Step 10:
In this script we will be using two commands. These are /work and /stopwork.
pawn Код:
public OnPlayerCommandText(playerid, cmdtext[])
{
    dcmd(work, 4, cmdtext);
    dcmd(stopwork, 8, cmdtext);
    return 0;
}
dcmd requires that you put this in OnPlayerCommandText, so you need to put in the command, the length of the command, and cmdtext.


- Step 11:
Beneath everything we have done so far, put in this code:
pawn Код:
dcmd_work(playerid, params[])
{
    #pragma unused params
    if(GetPlayerTeam(playerid) == TEAM_TRUCKER) return T_NewJob(playerid);
    return 1;
}

dcmd_stopwork(playerid, params[])
{
        #pragma unused params
    if(GetPlayerTeam(playerid) == TEAM_TRUCKER) return StopWork(playerid);
    return 1;
}
The #pragma unused params part tells the compiler that there are no parameters being used in that command.
The second line of each command then checks weather the player is a trucker and then if they are calls the command that we will create below.


- Step 12:
This bit is basically some things that will be used in the T_NewJob.
pawn Код:
new iMissionText[512][MAX_PLAYERS], Float:unx[MAX_PLAYERS], Float:uny[MAX_PLAYERS], Float:unz[MAX_PLAYERS], iPay[MAX_PLAYERS], MissionStatus[MAX_PLAYERS];
IMPORTANT: Put that line of code below the #define TEAM_TRUCKER 1 line near the top!


- Step 13:
Okay, this bit is big, so I will explain each line as a comment after each one. (a comment is everything after '//').
You need to put this underneath the commands.

pawn Код:
stock T_NewJob(playerid)
{
        new vID = GetPlayerVehicleID(playerid); //gets called on the next line
    if(GetVehicleModel(vID)== 403 || GetVehicleModel(vID)== 515 || GetVehicleModel(vID) == 514)//this checks wether the player is in a Roadtrain, Tanker or Linerunner
    {
        if(IsTrailerAttachedToVehicle(vID))// This checks wether the player has a trailer attached
        {
            MissionStatus[playerid] = 1;// this sets the players mission status as 1 - So they are on a mission.
            new MisRand = random(sizeof(MisLocations));// this is the line that will call a random mission.
            new LoadText[128], Float:x, Float:y, Float:z;// these are where we will store each co-ord and the text for the mission
            x = MisLocations[MisRand][LoadX];//this sets one of the above
            y = MisLocations[MisRand][LoadY];//this sets one of the above
            z = MisLocations[MisRand][LoadZ];//this sets one of the above
            unx[playerid] = MisLocations[MisRand][UnloadX];//these set what we made in step 10.
            uny[playerid] = MisLocations[MisRand][UnloadY];//these set what we made in step 10.
            unz[playerid] = MisLocations[MisRand][UnloadZ];//these set what we made in step 10.
            iPay[playerid] = MisLocations[MisRand][Pay];//these set what we made in step 10.
            SetPlayerCheckpoint(playerid, x, y, z, 7);//This creates the checkpoint that the player will enter.
            format(LoadText, 128, "%s",MisLocations[MisRand][LoadName]);// this is formatting the text the player will see in the console
            SendClientMessage(playerid, COLOR_GREEN, "Mission:");//sends message in console
            SendClientMessage(playerid, COLOR_GREEN, "_____________________");//sends message in console
            SendClientMessage(playerid, COLOR_GREEN, "");//sends message in console
            SendClientMessage(playerid, 0xFFFFFFFF, LoadText);//sends the text we formatted earlier in console
            SendClientMessage(playerid, COLOR_GREEN, "_____________________");//sends message in console
        }
        else//if the player doesnt have a trailer attached
        {
            SendClientMessage(playerid, COLOR_RED, "You need a trailer!");//sends message in console
        }
    }
    else//if the player isnt in a truck
    {
        SendClientMessage(playerid, COLOR_RED, "You must be in a Truck to perform this!");//sends message in console
    }
    return 1;
}


- Step 14:
After
pawn Код:
stock StopWork(playerid)
{
    DisablePlayerCheckpoint(playerid);
    SendClientMessage(playerid, COLOR_RED, "You chose to cancel the mission and got fined $100");
    GivePlayerMoney(playerid, -100);
    MissionStatus[playerid] = 0;
    return 1;
}
This basically disables the checkpoint, sends the player a message, takes the money off the player and sets his mission status to '0'


- Step 15:
Now we need to call when the player enters the checkpoint.
pawn Код:
public OnPlayerEnterCheckpoint(playerid)
{
    CheckpointEntered(playerid);
    return 1;
}
In the next step, we will make the function 'CheckpointEntered'.


- Step 16:
pawn Код:
stock CheckpointEntered(playerid)
{
    new gString[128];//A new string for storage
    new vID = GetPlayerVehicleID(playerid);//Explained earlier
    if(!IsTrailerAttachedToVehicle(vID)) return SendClientMessage(playerid, COLOR_RED, "You need a trailer to unload!");//This line checks wether the player has a trailer attached to their truck.
    if(MissionStatus[playerid] == 1)//checks the players mission status
    {
        DisablePlayerCheckpoint(playerid);//disables the checkpoint
        SetPlayerCheckpoint(playerid, unx[playerid], uny[playerid], unz[playerid], 7);//creates the new checkpoint from the saved positions we made earlier
        SendClientMessage(playerid, COLOR_ORANGE, "Loaded. Please head to the second checkpoint!");//sends message
        MissionStatus[playerid] = 2;//sets the players mission status
    }
    else if(MissionStatus[playerid] == 2)//checks the mission status of the player
    {
        DisablePlayerCheckpoint(playerid);//disables the checkpoint
        GivePlayerMoney(playerid, iPay[playerid]);//gives the money that was defined earlier
        SendClientMessage(playerid, COLOR_GREEN, "Well done! You completed the mission!");//sends the player a message
        format(gString, 512, "%s has completed mission: %s", pName(playerid), iMissionText[playerid]);//formats the message
        SendClientMessageToAll(COLOR_GREEN, gString);//sends everyone message saying player completed mission
        SetPlayerScore(playerid, GetPlayerScore(playerid)+2);//gives the player 2 score
        MissionStatus[playerid] = 0;//sets the mission status of the player to '0'
    }
    return 1;
}
- Step 16:
Finally, at various points in the script we have had something called pName floating around. This basically gets the players name. Its a bit of a pain putting it in every callback, so I made it a function in itself.

pawn Код:
stock pName(PN)
{
    new PX[MAX_PLAYER_NAME];
    GetPlayerName(PN, PX, sizeof(PX));
    return PX;
}


And thats it. Here is the complete script: http://pastebin.com/1dEzd29F

Hope you enjoyed it!

Thanks,

Jack_Rocker
Reply
#2

Nice one mate

ps: msn?
Reply
#3

I started to read this and then i seen
pawn Код:
#define dcmd(%1,%2,%3) if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1


Its great to get a good tutorial on stuff like this,
but it would be better to use one of the better command processors,
when writing a tutorial you should always make sure your using the best coding practices.

another thing is a stock function is NOT a callback.
a callback is a function that is called after an event takes place.
a stock is just a function that is removed at compile time when it is not used.
So that statement might mislead some,
Sorry to be such an ass%$#^ but its just how i am lol.

With all that said, I do like the way you have written this
and how you provide code updates threw out the steps.
It was explained well enough for me to understand without any issues.

I rate it 5/10
Reply
#4

Quote:
Originally Posted by Jonny5
Посмотреть сообщение
I started to read this and then i seen
pawn Код:
#define dcmd(%1,%2,%3) if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1


Its great to get a good tutorial on stuff like this,
but it would be better to use one of the better command processors,
when writing a tutorial you should always make sure your using the best coding practices.
Well, I used dcmd for simplicity sake, as mentioned. People will spend ages trying to find zcmd or something like that.

I did originally make the script with zcmd, however I converted it to dcmd. I like to provide nessecary resources within the tutorial itself.

Also, callbacks... *facepalm* I meant to write functions... :/
Reply
#5

Nice tutorial dude!
But.. When I write /work I only get this message "SERVER:Unknown command" And I'm in the vehicle and also I'm in the right team. Please help me!

EDIT: I converted it to ZCMD, so it's working fine now
Reply
#6

Good work mate , Looks you really spent a while doing this
Reply
#7

Quote:
Originally Posted by Karl[NDZ]
Посмотреть сообщение
Nice tutorial dude!
But.. When I write /work I only get this message "SERVER:Unknown command" And I'm in the vehicle and also I'm in the right team. Please help me!

EDIT: I converted it to ZCMD, so it's working fine now
You didn't #define dcmd...

I think I will convert the whole tutorial to zcmd soon anyway
Reply
#8

Quote:
Originally Posted by Jack_Rocker
Посмотреть сообщение
You didn't #define dcmd...

I think I will convert the whole tutorial to zcmd soon anyway
Isn't this the dcmd define?

pawn Код:
#define dcmd(%1,%2,%3) if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)