Hooking up vehicles to iterator -
Misiur - 26.10.2013
Hello guys! I want to reduce CPU usage a little, and I decided to start with optimising loops. Now, in the script I'm working on there are tons of loops going through vehicles, your good ol' pal classic vehicle for loop:
pawn Код:
for(new v = 1; v != (MAX_VEHICLES + 1); ++v)
Now, that's 2000 iterations, even when on server there is single vehicle only.
Let's go through my current code (really simplified)
pawn Код:
static
CarInfo[MAX_VEHICLES],
Iterator:CarInfo<MAX_VEHICLES>;
stock CST_CreateVehicle(modelid, Float:x, Float:y, Float:z, Float:angle, color1, color2, respawn_delay)
{
new
vehicle = INVALID_VEHICLE_ID;
vehicle = CreateVehicle(modelid, x, y, z, angle, color1, color2, respawn_delay);
Iter_Add(CarInfo, vehicle);
return vehicle;
}
#if defined _ALS_CreateVehicle
#undef CreateVehicle
#else
#define _ALS_CreateVehicle
#endif
#define CreateVehicle CST_CreateVehicle
stock CST_AddStaticVehicle(modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:angle, color1, color2)
{
new
vehicle = INVALID_VEHICLE_ID;
vehicle = AddStaticVehicle(modelid, spawn_x, spawn_y, spawn_z, angle, color1, color2);
Iter_Add(CarInfo, vehicle);
return vehicle;
}
#if defined _ALS_AddStaticVehicle
#undef AddStaticVehicle
#else
#define _ALS_AddStaticVehicle
#endif
#define AddStaticVehicle CST_AddStaticVehicle
stock CST_AddStaticVehicleEx(modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:angle, color1, color2, respawn_delay)
{
new
vehicle = INVALID_VEHICLE_ID;
vehicle = AddStaticVehicleEx(modelid, spawn_x, spawn_y, spawn_z, angle, color1, color2, respawn_delay);
Iter_Add(CarInfo, vehicle);
return vehicle;
}
#if defined _ALS_AddStaticVehicleEx
#undef AddStaticVehicleEx
#else
#define _ALS_AddStaticVehicleEx
#endif
#define AddStaticVehicleEx CST_AddStaticVehicleEx
stock CST_DestroyVehicle(vehicleid)
{
RemoveVehicle(vehicleid);
return DestroyVehicle(vehicleid);
}
#if defined _ALS_DestroyVehicle
#undef DestroyVehicle
#else
#define _ALS_DestroyVehicle
#endif
#define DestroyVehicle CST_DestroyVehicle
stock RemoveVehicle(vehicleid) {
Iter_Remove(CarInfo, vehicleid);
}
public OnVehicleDeath(vehicleid, killerid)
{
RemoveVehicle(vehicleid);
return 1;
}
RemoveVehicle has some more stuff to do, and the CarInfo is in fact 2d enumerated array, but that doesn't matter at the moment. Now, did I cover all possible vehicle creation moments? Also, are there any more places where vehicle can get destroyed? Does the vehicle after respawn reclaim its previous id, or it gets assigned a new one? Does SetVehicleToRespawn assign a new vehicle id, or it stays the same? Are there any serious flaws in my code? I'll test everything extensively, but with more eyes stuff is spotted easier.
Re: Hooking up vehicles to iterator -
Konstantinos - 26.10.2013
Before I start, may I ask why do you use the same name twice?
pawn Код:
CarInfo[MAX_VEHICLES]
Iterator:CarInfo<MAX_VEHICLES>
No, there are only those 3 functions you used for vehicle creation. I only tested it with CreateVehicle and when a vehicle re-spawns, it gets the same vehicleid as it had before being set to respawn or its death. Honestly, removing the vehicleid from the iterator when OnVehicleDeath is called is pointless unless you destroy the vehicle when that callback is called (like some do). Otherwise, removing and re-adding (in OnVehicleSpawn) the vehicle is useless. The vehicleids are only overwritten when a vehicle was destroyed and a new one was created, not on respawn.
Last one, is the declaration of CarInfo since it's 1-2000 and 0 is not used, wouldn't it be MAX_VEHICLES + 1? Because I've the feeling it'll give index out of bounds for accessing element at index 2000 past array upper bound 1999.
Re: Hooking up vehicles to iterator -
Misiur - 26.10.2013
That's kind of mine convention, because there isn't a name conflict (Iterator returns something like CarInfo@YSII_Cg, CarInfo@YSII_Ag), and it's easier to remember only one label
The OnVehicleDeath is special case for vehicles with -1 respawn delay. I'm a little worried about note in wiki and the callback called when vehicle submerges. No idea how to handle that case.
Your last point is valid. There is also additional important thing to remember - vehicles start at 1, not 0, so either we have to create a macro to overwrite array access from CarInfo[vehicleid] to CarInfo[(vehicleid - 1)] (then MAX_VEHICLES is sufficient, and the cell @0 isn't wasted), or add on script init Iter_Add(CarInfo, 0).
Re: Hooking up vehicles to iterator -
Konstantinos - 26.10.2013
I didn't think of that before, you're right about foreach.
Well I created a vehicle with CreateVehicle and respawn_delay to -1. When I exit the vehicle the vehicle does not respawn at all after a while (normal), however I let the car upside down and it got fire. The vehicle was respawned, even if it was created with -1 as respawn delay. Both OnVehicleDeath and OnVehicleSpawn callbacks were called. I think I do know what you were worried about, the thing it says about when a vehicle is in the water the OnVehicleDeath is called, however if you teleport the car or jump (depending on the type of the server) then you can "save" it. And even if the vehicle with -1 as respawn delay be in a water without the driver, both those callbacks are called. If the player is in the vehicle, after the player dies because he ran out of the oxygen, then the vehicle is dying too. And still both callbacks are called.
Thanks for the overwriting thing, I always used 1-2000 for that and 0 was indeed not used at all (though I don't use any array with MAX_VEHICLES anymore).