[Tutorial] Anti Car-Pushers(Freeze Vehicles)!
#1

We all love GTA SA, the reduced BUT nice graphics, the animations, the attempt to respect the physic laws, etc. But I bet we all have that one moment when we hate that GTA SA cannot be more like real-life! For example, in a RolePlay server, a very common problem consists of "Car-Pushers", those players who find it very funny to push owned vehicles far away from its parking lot. They do this MOST likely on foot, very rare on vehicles.

Therefor, I decided to write a code, that will FREEZE the vehicle on place if it's unoccupied and you try to move it(while on foot). Why? Well, in real life you can't push vehicles on foot by runing into it, can you? BUT, the question is how does the code work?

How should we start? What are the variables we need? Well, obviusly we need the vehicle's position, but we also need the ZAngle, because, otherwise you still can push/rotate the car a little bit. We need separate variables for each vehicle, that's why we will use globaly declare them(somewhere at the top of your script):

pawn Code:
new Float:vPosX[MAX_VEHICLES],Float:vPosY[MAX_VEHICLES],Float:vPosZ[MAX_VEHICLES],Float:vZAngle[MAX_VEHICLES]; // Position X of the vehicle, Position Y of the vehicle, Position Z of the vehicle, Angle of the vehicle
Good, but, another queston might be: "Why do we need the variables, how does the code work!!?" Well, the asnwer is that the code saves the unoccupied vehicle's position and angle and stores them into those variables, when the vehicle's speed is 0.
Great, but you might say: "Wait, he saves the position and the angle of the vehicle, whenever it's unoccupied and stands still!!!? That doesn't make sense..."
Yes, it doesn't make sense, but that's not how the code works, the code only executes ONCE, whenever a vehicle's speed is 0, and unoccupied. We will need a variable that will tell us if we already stored the data into the variables. We will also declare this variable as a global one(also somewhere at the top of your script):

pawn Code:
new vUsed[MAX_VEHICLES]; //tells us if the vehicle is in use, or if the vehicle is already frozen
Great, so that variable can be 0(the vehicle is unoccupied, but it's not frozen yet), 1(the vehicle is unoccupied, and frozen), 2. BUT, before that we must think that when a vehicle spawns, the code must execute immediatly, or else, the code will most likely work only after a player gets in and out a vehicle, THEREFOR, we must save the data of each vehicle, as soon as it spawns/respawns:

pawn Code:
public OnVehicleSpawn(vehicleid)
{
    GetVehiclePos(vehicleid,vPosX[vehicleid],vPosY[vehicleid],vPosZ[vehicleid]); //storing the position of the vehicle
    GetVehicleZAngle(vehicleid,vZAngle[vehicleid]); //storing the angle of the vehicle
    vUsed[vehicleid]=1; // as mentioned before, when the variable is 1, means the vehicle is frozen
    return 1;
}
Good, and now, as I said, when a player gets inside a car, the vUsed variable will become 2, telling us that the vehicle is in use. So we must work inside the function "OnPlayerStateChange". When the player exits the vehicle, the variable will become 0, telling us that the vehicle is unoccupied, but NOT frozen yet. We will work, of course, with the function "OnPlayerExitVehicle":

pawn Code:
public OnPlayerStateChange(playerid, newstate, oldstate)
{
    if(newstate==PLAYER_STATE_DRIVER||newstate==PLAYER_STATE_PASSENGER)
    {
             new vehicleid=GetPlayerVehicleID(playerid);
             vUsed[vehicleid]=2; //the vehicle is in use
    }
   return 1;
}

public OnPlayerExitVehicle(playerid, vehicleid)
{
    vUsed[vehicleid]=0; //the vehicle is unoccupied, but also unfrozen
   return 1;
}
Good, so now that we have that, here comes the actual code. So, the code will execute when the vehicle is unoccupied, therefor we will make use of the function "OnUnoccupiedVehicleUpdate". First we need to get the vehicle's speed, to see if the vehicle is not moving. Why? Because you know that you can jump out the vehicle, even if the vehicle is still moving. Also, if someone comes on a car and crashes into an unoccupied vehicle, it will start moving, and therefor we need to reset the its position and angle. Otherwise, when you try to push the vehicle(on foot), it will be respawned at the position where it could be found before someone came on car and crashed into it. So, here's the function to get the vehicle's speed:

pawn Code:
stock GetVehicleSpeed(vehicleid, bool:kmh = true)
{
    new
        Float:xx,
        Float:yy,
        Float:zz,
        Float:vehSpeed;
   
    GetVehicleVelocity(vehicleid,xx,yy,zz);
    vehSpeed  = floatsqroot((xx * xx) + (yy * yy) + (zz * zz));
    return kmh ? floatround((vehSpeed * 195.12)) : floatround((vehSpeed * 136.66667));
}
That simply get's the vehicle's velocity, and uses it to calculate it's speed, returning the vehicle's speed in "kmph" format. Can be changed to "mph" as well, but for our code it's the same thing, we just need to know if the vehicle is moving or not. So, now, we check that inside the function mentioned before, "OnUnoccupiedVehicleUpdate":

pawn Code:
public OnUnoccupiedVehicleUpdate(vehicleid, playerid, passenger_seat)
{
    //We need this check, because as I mentioned before, someone may come on a vehicle and crash into your car
    if(GetVehicleSpeed(vehicleid)!=0) //if the vehicle is moving
        if(vUsed[vehicleid]!=0) //if the vehicle is frozen
            vUsed[vehicleid]=0; //then we reset the variable to 0(meaning that the vehicle is unoccupied, and unfrozen)
   return 1;
}
Good, now, if the vehicle's speed is 0, and unfrozen, we can finally freeze the vehicle. And now, I'll explain what the code actually does. When the vehicle is unoccupied, and frozen, we check if there's a player(on foot), in the range of the vehicle. If there is one, we then reset the vehicle's position to the coords and angle before it got pushed:

pawn Code:
public OnUnoccupiedVehicleUpdate(vehicleid, playerid, passenger_seat)
{
    //We need this check, because as I mentioned before, someone may come on a vehicle and crash into your car
    if(GetVehicleSpeed(vehicleid)!=0) //if the vehicle is moving
        if(vUsed[vehicleid]!=0) //if the vehicle is frozen
            vUsed[vehicleid]=0; //then we reset the variable to 0(meaning that the vehicle is unoccupied, and unfrozen)
        if(vUsed[vehicleid]==0) //if the vehicle is unfrozen
        if(GetVehicleSpeed(vehicleid)==0) //if the vehicle's not moving
        {
            GetVehiclePos(vehicleid,vPosX[vehicleid],vPosY[vehicleid],vPosZ[vehicleid]); //we store its position
            GetVehicleZAngle(vehicleid,vZAngle[vehicleid]); //we store its angle
            vUsed[vehicleid]=1; //and we indicate that the vehicle is frozen
        }
    if(vUsed[vehicleid]==1) //if the vehicle is frozen
    {
        for(new i=0;i<MAX_PLAYERS;i++) //we loop through the players
            if(IsPlayerConnected(i)) //and see if he's connected
                if(GetPlayerState(i)==PLAYER_STATE_ONFOOT) //and IF he IS NOT in any vehicle(or any other state)
                    if(IsPlayerInRangeOfPoint(i,3.2,vPosX[vehicleid],vPosY[vehicleid],vPosZ[vehicleid])) // we see if he's near the car
                    {
                         SetVehiclePos(vehicleid,vPosX[vehicleid],vPosY[vehicleid],vPosZ[vehicleid]); //and we reset the vehicle's position
                         SetVehicleZAngle(vehicleid,vZAngle[vehicleid]); //also we reset its angle
                    }
    }
   return 1;
}
And, that should be all. The code has been tested and it's working. If you have any question just ask. As far as I am concerned, I've seen someone asking for this code, and someone pointed to a topic(a Vehicle Dealership system that included this feature), but many mentioned that it's not working, that they could still push the vehicles on foot.
Reply
#2

This is very useful! Thanks i hope it works, i'll try it now.

EDIT: Ups! got this:
Code:
.pwn(1127) : error 017: undefined symbol "vehicleid"
.pwn(1128) : error 017: undefined symbol "vehicleid"
.pwn(1129) : error 017: undefined symbol "vehicleid"
Pawn compiler 3.2.3664	 	 	Copyright © 1997-2006, ITB CompuPhase

3 Errors.
Reply
#3

Not bad, I might use this. It will avoid adding extra mapping to prevent pushing faction vehicles in the ls sewers.
Reply
#4

Bro i need it, please...

Quote:
Originally Posted by RiChArD_A
View Post
This is very useful! Thanks i hope it works, i'll try it now.

EDIT: Ups! got this:
Code:
.pwn(1127) : error 017: undefined symbol "vehicleid"
.pwn(1128) : error 017: undefined symbol "vehicleid"
.pwn(1129) : error 017: undefined symbol "vehicleid"
Pawn compiler 3.2.3664	 	 	Copyright © 1997-2006, ITB CompuPhase

3 Errors.
Reply
#5

You won't even show me the lines where the errors occur? HOW am I supossed to know where your problem is !!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)