29.06.2013, 07:44
(
Last edited by Cjgogo; 03/07/2013 at 07:57 AM.
)
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):
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):
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:
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":
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:
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":
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:
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.
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
Great, but you might say: "Wait, he saves the position and the angle of the vehicle, whenever it's unoccupied and stands still!!!
![Huh?](images/smilies/confused.gif)
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
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;
}
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;
}
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));
}
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;
}
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;
}