[Tutorial] Getting a player's position in a race (GetPlayerRacePosition)
#1

Hello I have been making a race system for my GM, and used this tutorial for it: https://sampforum.blast.hk/showthread.php?tid=401252

However I noticed it did not include a race position thing, and we all know that every single race on a decent server has a race position thing, no?

So I searched for tutorials and looked in other filterscripts (such as yRace and rRace).
But I couldn't find a way of doing it, so I tried to do it myself and succeeded.
So because there's no (good) tutorial of doing this I'm going to show you how I did it.

IMPORTANT: I use this function with the race system I made from the tutorial (see top), if your race system operates differently, chances are that this isn't going to work...

So how is this tutorial going to be?
Well I just made the following function:
pawn Код:
GetPlayerPosition(playerid, raceid)
which returns the player's position
And I'll just show you the stock code, and then explain every line.

| Step One |

Ok so step one, as always is adding a new array.
I'm only going to show you the array to store the position, not all other race arrays in the racing system...

Add this to your PlayerInfo enum (I guess you have one?)
pawn Код:
enum PlayerInfo
{
    //blabla
    Pos,
}

new PInfo[MAX_PLAYERS][PlayerInfo];
This simply stores the player's position.
Now we for safety reasons I like to set this array to 0 in several callbacks, I don't think it's really necesairy, but I do it to make sure there's no bugs...
So add this:
pawn Код:
PInfo[playerid][PlayerInfo] = 0;
under the following Callbacks:
pawn Код:
public OnPlayerConnect(playerid)
stock LeaveRace(playerid, raceid) //Or whathever you use in your script when a player leaves a race
| Step Two |

Ok now let's go to the function itself.

here's the code
pawn Код:
stock GetPlayerPosition(playerid, raceid)
{
    new index = 0;
    for(new j = 0; j < MAX_PLAYERS; j++)
    {
        if(PInfo[j][Racing] == raceid)
        {
            if(j != playerid)
            {
                if(PInfo[playerid][RaceCheckpoint] < PInfo[j][RaceCheckpoint])
                {
                    index++; //for everyone who is in front of the player index goes ++
                }
               
                if(PInfo[playerid][RaceCheckpoint] == PInfo[j][RaceCheckpoint]) //who is in the same section as the player
                {
                    new PlayerCheckPoint = PInfo[playerid][RaceCheckpoint];
                    new ElseCheckPoint = PInfo[j][RaceCheckpoint];
                   
                    if(GetPlayerDistanceFromPoint(playerid, RaceInfo[raceid][checkpointx][PlayerCheckPoint]+1,RaceInfo[raceid][checkpointy][PlayerCheckPoint]+1, RaceInfo[raceid][checkpointz][PlayerCheckPoint]+1) > GetPlayerDistanceFromPoint(j, RaceInfo[raceid][checkpointx][ElseCheckPoint]+1, RaceInfo[raceid][checkpointy][ElseCheckPoint]+1, RaceInfo[raceid][checkpointz][ElseCheckPoint]+1))
                    {
                        index++;
                    }
                }
            }
        }
    }
   
    PInfo[playerid][Pos] = index +1;
   
    return PInfo[playerid][Pos];
}
Let's explain line by line:
pawn Код:
new index = 0;
This is a new 'index', we'll use it to store the amount of players that are infront of the player we track the position.
-> the player's position will eventually be index +1 , since it's all the players in front of him +1
But how do we count the amount of players in front of the tracked one?

here's how:
pawn Код:
for(new j = 0; j < MAX_PLAYERS; j++) //everyone
    {
This just loops through all the players that could be online
-> i equals all the players that could be online

pawn Код:
if(PInfo[j][Racing] == raceid)  //Use your own variable to define wether a player is racing or not
        {
-> now i stands for everyone who is racing the/a race, because we filtered everyone who isn't in the race.

pawn Код:
if(j != playerid) // who is not the checked player
            {
We just filtered ourself, since we cannot really see if 'you' are in front of 'you'...

pawn Код:
if(PInfo[playerid][RaceCheckpoint] < PInfo[j][RaceCheckpoint]) //use your own variable to get the player's checkpoint
                {
Now I'm going to give some explanation:
pawn Код:
PInfo[playerid][RaceCheckpoint]
This is the checkpoint the player has last entered, the progress of the player in the race. If a player has already done 2 checkpoints, this will be2.
I'm sure your racing system has something similar to track the player's progress, no?
pawn Код:
PInfo[j][RaceCheckpoint]
This is the checkpoint all the other racers have last entered, the same story as the previous variable, but this is for every other racer.

So this:
pawn Код:
if(PInfo[playerid][RaceCheckpoint] < PInfo[j][RaceCheckpoint])
Means if the tracked player has done less checkpoints than all the other racers.
Let's move on:
pawn Код:
index++; //for everyone who is in front of the player index goes ++
So, what's this?
Well we constantly do our first loop, and now we end up here, so everything that happens in here has passed all the "if's" hence, index will go ++ for everyone who is in front of the player, right?



Now whe have only checked for all the players that have done more checkpoints than the tracked player.
But what about all the players that have done the same amount of checkpoints as i, but is in front of me?

you can see it like this:

Код:
 . | . 0 .. | ... |


. represents a racer
0 represents me
| represents a checkpoint

So now index has only gone up for the first three racers, since they have done more checkpoints than me, but what about the 3 other racers that have done the same amount of checkpoints yet as me?
So this code:
pawn Код:
if(PInfo[playerid][RaceCheckpoint] == PInfo[j][RaceCheckpoint]) //who is in the same section as the player
                {
This checks if all the other races have done the same amount of checkpoints as I -> they are in the same 'section'.
So now 'j' represents that.

pawn Код:
new PlayerCheckPoint = PInfo[playerid][RaceCheckpoint];
                    new ElseCheckPoint = PInfo[j][RaceCheckpoint];
This is just to make things shorter, PlayerCheckPoint is the last checkpoint the player has entered, ElseCheckPoint is the amount of checkpoints all the other racers (who are in the same section as me) have done.


pawn Код:
if(GetPlayerDistanceFromPoint(playerid, RaceInfo[raceid][checkpointx][PlayerCheckPoint]+1,RaceInfo[raceid][checkpointy][PlayerCheckPoint]+1, RaceInfo[raceid][checkpointz][PlayerCheckPoint]+1) > GetPlayerDistanceFromPoint(j, RaceInfo[raceid][checkpointx][ElseCheckPoint]+1, RaceInfo[raceid][checkpointy][ElseCheckPoint]+1, RaceInfo[raceid][checkpointz][ElseCheckPoint]+1))
                    {
Let's filter 'j' again, so now we calculate the distance the player is away from their next checkpoint ([PlayerCheckPoint] +1), and the distance in between every other racer and their next checkpoint.

So if the racer's distance is bigger than the others we continue:
pawn Код:
index++;
So index goes up for every racer that has done the same amount of checkpoints than me, and is closer to the next one than me.

So there we go.

Last bits:
pawn Код:
}
                }
            }
        }
    }
   
    PInfo[playerid][Pos] = index +1;
   
    return PInfo[playerid][Pos];
}
Now, index represents the amount of players in front of you
-> your position = index +1

I don't think you really need to make the PInfo[playerid][Pos] variable, you can also just return index +1, but I like to make a P variable.

So we returned the position, now when you use the function, it will output the player's position.


| Step Three |

Here's an example script:
pawn Код:
public RaceTimeS(raceid) //Called every second when a race has started
{
    for(new i; i<MAX_PLAYERS; i++)
    {
        if( !IsPlayerConnected( i ) ) continue;
        printf( "if(PInfo[i][Racing] == raceid)::if(%d == %d)", PInfo[i][Racing], raceid );
        if(PInfo[i][Racing] == raceid)
        {
            print( "PInfo[i][racetimeS] ++;" );
            RaceInfo[raceid][racetimeS] ++;
            printf( "PInfo[i][racetimeS] = %d", RaceInfo[raceid][racetimeS] );

            print( "TD: Time Taken will be called.." );
            new string[56];
            format (string, sizeof string, "%s Time Taken" , ReturnSToM(RaceInfo[raceid][racetimeS]));
            TextDrawSetString(TD_TIME[i], string);
            print( "TD: Time Taken has been called.." );

            print( "TD: Position will be called.." );
            new Position[26];
            format(Position, sizeof Position, "%d/%d Position",GetPlayerPosition(i, raceid), RaceInfo[raceid][originalcount]);
            TextDrawSetString(TD_POS[i], Position);
            print( "TD: Position has been called.." );
        }
    }
    return 1;
}
This code works fine for me, but I have only tested it with 2 players yet, not with 3 or more...
So hopefully it will work aswell.

Hope it helped you.
Bye.
Reply


Messages In This Thread

Forum Jump:


Users browsing this thread: 2 Guest(s)