Avoiding passengers in driverless vehicles
#1

Hi, I would like to write some pieces of script so that players can get in a vehicle as passengers ONLY IF that vehicle has a driver. I guess that the very first part is creating a custom function that checks if a vehicle has a driver:

pawn Код:
forward IsVehicleDriven(vehicleid);
public IsVehicleDriven(vehicleid)
{
    for(new i = 0; i <= MAX_PLAYERS; i++)
    {
        if(GetPlayerState(i) == PLAYER_STATE_DRIVER)
        {
            if(GetPlayerVehicleID(i) == vehicleid)
            {
                return i;
            }
        }
    }
    return -1;
}
And then calling this custom function in OnPlayerEnterVehicle:

pawn Код:
public OnPlayerEnterVehicle(playerid, vehicleid, ispassenger)
{
    if(ispassenger == 1)
    {
        if(IsVehicleDriven(vehicleid) == -1)
        {
            SendClientMessage(playerid, 0xFFFFFFFF, "You can't enter that vehicle as passenger because it has no driver");
            new Float:x, Float:y, Float:z;
            GetPlayerPos(playerid, x, y, z);
            SetPlayerPos( playerid, x, y, (z + 1) );
        }
    }
    return 1;
}
Ok, this was the easy part, now comes the hard part: imagine that a vehicle has a driver and a passenger, so everything is ok. But now, the driver gets out of the vehicle, or he disconnects from the server, so the passenger is left alone in the vehicle. I need a piece of script that detects this and ejects that passenger, and only two ways have come to my mind:
  • Using OnPlayerUpdate:

    pawn Код:
    public OnPlayerUpdate(playerid)
    {
        if(GetPlayerState(playerid) == PLAYER_STATE_PASSENGER)
        {
            new vehicleid;
            vehicleid = GetPlayerVehicleID(playerid);
            if(IsVehicleDriven(vehicleid) == -1)
            {
                new Float:x, Float:y, Float:z;
                GetPlayerPos(playerid, x, y, z);
                SetPlayerPos( playerid, x, y, (z + 1) );
                SendClientMessage(playerid, 0xFFFFFFFF, "You were ejected from the vehicle because it doesn't have a driver any more");
            }
        }
        return 1;
    }
    The problem I see with this method is that IsVehicleDriven loops through all players, so if the server has to repeat that loop over and over again for every single update that players send while being passengers, the cpu might get overloaded. So here comes my other method:
  • Creating a second custom function and calling it both in OnPlayerDisconnect and in OnPlayerStateChange:

    pawn Код:
    forward SearchForAlonePassengers();
    public SearchForAlonePassengers()
    {
        new vehicleid, Float:x, Float:y, Float:z;
        for(new i = 0; i <= MAX_PLAYERS; i++)
        {
            if(GetPlayerState(i) == PLAYER_STATE_PASSENGER)
            {
                vehicleid = GetPlayerVehicleID(i);
                if(IsVehicleDriven(vehicleid) == -1)
                {
                    GetPlayerPos(i, x, y, z);
                    SetPlayerPos( i, x, y, (z + 1) );
                    SendClientMessage(i, 0xFFFFFFFF, "You were ejected from the vehicle because it doesn't have a driver any more");
                }
            }
        }
        return 1;
    }

    public OnPlayerDisconnect(playerid, reason)
    {
        SearchForAlonePassengers();
        return 1;
    }

    public OnPlayerStateChange(playerid, newstate, oldstate)
    {
        if(oldstate == PLAYER_STATE_DRIVER)
        {
            SearchForAlonePassengers();
        }
        return 1;
    }
    This other method has the advantage of not making OnPlayerUpdate too heavy, because the custom function is called only when a player disconnects and when he stops being a driver. However, the function SearchForAlonePassengers first loops through all players, and in some cases it calls IsVehicleDriven, which also loops through all players, so it would be like having a loop inside another, and I don't know if also that might overload the server.
So what's your advice?
Reply
#2

https://sampwiki.blast.hk/wiki/OnUnoccupiedVehicleUpdate
Might be useful to you. Also your MAX_PLAYER loops are incorrect. Use just <, not <=. Furthermore, you can use IsPlayerInVehicle rather than GetPlayerState.
Reply
#3

Thank you Vince, only two things:

Quote:
Originally Posted by Vince
Посмотреть сообщение
Is that callback called also when the vehicle is NOT moving?

Quote:
Originally Posted by Vince
Посмотреть сообщение
Furthermore, you can use IsPlayerInVehicle rather than GetPlayerState.
But IsPlayerInVehicle doesn't make a distinction between the player being driver or passenger.
Reply
#4

OnPlayerUpdate is bad option. I would go for the second one.

pawn Код:
EjectAllPassengers(vehicleid)
{
    for(new i = 0; i < MAX_PLAYERS; i++)
    {
        if(GetPlayerState(i) == PLAYER_STATE_PASSENGER)
        {
            if(GetPlayerVehicleID(i) == vehicleid)
            {
                RemovePlayerFromVehicle(i);
                SendClientMessage(i, 0xFFFFFFFF, "You were ejected from the vehicle because it doesn't have a driver any more");
            }
        }
    }
}
pawn Код:
public OnPlayerDisconnect(playerid, reason)
{
    if(GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
    {
        new vehicleid = GetPlayerVehicleID(playerid);
        EjectAllPassengers(vehicleid);
    }
    return 1;
}
pawn Код:
public OnPlayerStateChange(playerid, newstate, oldstate)
{
    if(oldstate == PLAYER_STATE_DRIVER)
    {
        new vehicleid = GetPlayerVehicleID(playerid);
        EjectAllPassengers(vehicleid);
    }
    return 1;
}
Also, I don't see any reason why IsVehicleDriven needs to be public.
Reply
#5

Quote:
Originally Posted by MadeMan
Посмотреть сообщение
OnPlayerUpdate is bad option. I would go for the second one.
pawn Код:
public OnPlayerStateChange(playerid, newstate, oldstate)
{
    if(oldstate == PLAYER_STATE_DRIVER)
    {
        [b]new vehicleid = GetPlayerVehicleID(playerid);[/b]
        EjectAllPassengers(vehicleid);
    }
    return 1;
}
OnPlayerStateChange with oldstate as PLAYER_STATE_DRIVER is called after he left the vehicle, not when he is leaving, so the ID would be 0.
Reply
#6

Ok I have just made a brief test and have found out that the callback OnUnoccupiedVehicleUpdate is called only when the vehicle is moving, and that if you are a passenger in a completely motionless vehicle, this callback is not called. Therefore, I can't rely on this callback for my purpose.

This is the code I wrote for the test:

pawn Код:
public OnUnoccupiedVehicleUpdate(vehicleid, playerid, passenger_seat)
{
    GameTextForPlayer(playerid, "called", 250, 4);
    return 1;
}
Reply
#7

Why all this unnecessary shit? All you need to do is check 3 times; when a driver disconnects, when a driver exits a vehicle or when a passenger enters a vehicle. No need for timers or loops or OPU or the vehicle update callback.

Never seen such unnecessary stuff. Give me 10 minutes and I'll whip it up.
Reply
#8

pawn Код:
new LastCar[MAX_PLAYERS], bool: VehicleDriven[MAX_VEHICLES];

public OnPlayerDisconnect(playerid)
{
    if(GetPlayerState(playerid) == PLAYER_STATE_DRIVER)
    {
        VehicleDriven[LastCar[playerid]] = false;
    }

    return 1;
}

public OnPlayerStateChange(playerid, newstate, oldstate)
{
    if(oldstate == PLAYER_STATE_DRIVER)
    {
        VehicleDriven[LastCar[playerid]] = false;
    }

    if(newstate == PLAYER_STATE_DRIVER)
    {
        LastCar[playerid] = GetPlayerVehicleID(playerid);
        VehicleDriven[LastCar[playerid]] = true;
    }

    if(newstate == PLAYER_STATE_PASSENGER)
    {
        if(VehicleDriven[GetPlayerVehicleID(playerid)] == false)
        {
            RemovePlayerFromVehicle(playerid);
            return SendClientMessage(playerid, -1, "This vehicle has no driver, therefore you may not enter as a passenger.");
        }
    }

    return 1;
}
Reply
#9

So I say I'm going to whip it up, and you decide to be a cunt and post your own. Nice move dickhead.

http://pastebin.ca/2196428

Consider yourself on my 'people I dislike' list.
Reply
#10

Quote:
Originally Posted by MP2
Посмотреть сообщение
So I say I'm going to whip it up, and you decide to be a cunt and post your own. Nice move dickhead.

http://pastebin.ca/2196428

Consider yourself on my 'people I dislike' list.
Big whoop? Anyways, my code doesn't use any loops and you took more than 20 minutes.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)