I'm having a huge problem and I can't fix it.
#1

In my script, there are two vehicle types: player; and faction. This is the enum:

PHP код:
enum carData {
    
carID// This is the SQL ID. 
    
carExists,
    
carModel,
    
carOwner,
    
Float:carPos[4],
    
carColor1,
    
carColor2,
    
carPlate[11],
    
carLocked,
    
carParked,
    
carWorld,
    
carRank,
    
carFaction,
    
carVehicle 
Player Vehicles
Player vehicles only spawn when the player is logged in, and they disappear when the player logs out. The player vehicles are created, saved, loaded and unloaded like so --

Created:
PHP код:
CMD:createpcar(playeridparams[])
{
    static
        
userid,
        
model[32];
        
    if (
PlayerData[playerid][pAdmin] < 4)
        return 
SendErrorMessage(playerid"You don't have permission to use this command.");
        
    if (
sscanf(params"us[32]"useridmodel))
        return 
SendSyntaxMessage(playerid"/createpcar [playerid/name] [modelid/name]");
        
    if (
Car_GetCount(userid) >= MAX_OWNABLE_CARS)
        return 
SendErrorMessage(playerid"This player already owns the maximum amount of cars.");
    if ((
model[0] = GetVehicleModelByName(model)) == 0)
        return 
SendErrorMessage(playerid"Invalid model ID.");
    static
        
Float:x,
        
Float:y,
        
Float:z,
        
Float:angle,
        
id = -1;
    
GetPlayerPos(useridxyz);
    
GetPlayerFacingAngle(useridangle);
    
id PlayerCar_Create(PlayerData[userid][pID], model[0], x21anglerandom(127), random(127));
    if (
id == -1)
        return 
SendErrorMessage(playerid"The server has reached the limit for dynamic vehicles.");
    
SendServerMessage(playerid"You have created vehicle ID: %d for %s."CarData[id][carVehicle], ReturnName(userid0));
    return 
1;
}
PlayerCar_Create(owneridmodelidFloat:xFloat:yFloat:zFloat:anglecolor1color2)
{
    for (new 
0!= MAX_DYNAMIC_CARS++)
    {
        if (!
CarData[i][carExists])
           {
               if (
color1 == -1)
                   
color1 random(127);
            if (
color2 == -1)
                
color2 random(127);
               
CarData[i][carExists] = true;
            
CarData[i][carModel] = modelid;
            
CarData[i][carOwner] = ownerid;
            
CarData[i][carPos][0] = x;
            
CarData[i][carPos][1] = y;
            
CarData[i][carPos][2] = z;
            
CarData[i][carPos][3] = angle;
            
CarData[i][carColor1] = color1;
            
CarData[i][carColor2] = color2;
            
            new 
str[8], query[400];
            
format(strsizeof(str), "%s%s%d%d%s%s%s"LetterList[random(sizeof(LetterList))], LetterList[random(sizeof(LetterList))], random(9), random(9), LetterList[random(sizeof(LetterList))], LetterList[random(sizeof(LetterList))], LetterList[random(sizeof(LetterList))]);
            
SetVehicleNumberPlate(istr);
            
format(CarData[i][carPlate], 11"%s"str);
            
            
CarData[i][carPaintjob] = -1;
            
CarData[i][carLocked] = false;
            
CarData[i][carParked] = 0;
            
CarData[i][carWorld] = 0;
            
CarData[i][carImpounded] = -1;
            
CarData[i][carImpoundPrice] = 0;
        
            for (new 
014++)
            {
                if (
5)
                {
                    
CarData[i][carWeapons][j] = 0;
                    
CarData[i][carAmmo][j] = 0;
                }
                
CarData[i][carMods][j] = 0;
            }
            
CarData[i][carVehicle] = CreateVehicle(modelidxyzanglecolor1color2, -1);
            if (
CarData[i][carVehicle] != INVALID_VEHICLE_ID) {
                
ResetVehicle(CarData[i][carVehicle]);
            }
            
mysql_format(g_iHandlequerysizeof(query), "INSERT INTO `playercars` (carModel, carOwner, carPosX, carPosY, carPosZ, carPosR, carColor1, carColor2, carPlate, carPaintjob, carParked, carWorld) VALUES(%d, %d, %f, %f, %f, %f, %d, %d, '%s', -1, 0, 0)",
                
CarData[i][carModel],
                
CarData[i][carOwner],
                
CarData[i][carPos][0],
                
CarData[i][carPos][1],
                
CarData[i][carPos][2],
                
CarData[i][carPos][3],
                
CarData[i][carColor1],
                
CarData[i][carColor2],
                
CarData[i][carPlate],
                
CarData[i][carPaintjob],
                
CarData[i][carParked],
                
CarData[i][carWorld]);
            
mysql_tquery(g_iHandlequery"OnplayerCarCreated""i"i);
            return 
1;
        }
    }
    return -
1;
}
forward OnPlayerCarCreated(carid);
public 
OnPlayerCarCreated(carid)
{
    if (
carid == -|| !CarData[carid][carExists])
        return 
0;
    
CarData[carid][carID] = mysql_insert_id();
    
PlayerCar_Save(carid);
    return 
1;

Saved:
PHP код:
PlayerCar_Save(carid)
{
    static
        
query[900];
    if (
CarData[carid][carVehicle] != INVALID_VEHICLE_ID)
    {
        for (new 
014++) {
            
CarData[carid][carMods][i] = GetVehicleComponentInSlot(CarData[carid][carVehicle], i);
        }
    }
    
format(querysizeof(query), "UPDATE `playercars` SET `carModel` = '%d', `carOwner` = '%d', `carPosX` = '%.4f', `carPosY` = '%.4f', `carPosZ` = '%.4f', `carPosR` = '%.4f', `carColor1` = '%d', `carColor2` = '%d', `carPlate` = '%s', `carLocked` = '%d', `carParked` = '%d', `carWorld` ='%d'",
        
CarData[carid][carModel],
        
CarData[carid][carOwner],
        
CarData[carid][carPos][0],
        
CarData[carid][carPos][1],
        
CarData[carid][carPos][2],
        
CarData[carid][carPos][3],
        
CarData[carid][carColor1],
        
CarData[carid][carColor2],
        
CarData[carid][carPlate],
        
CarData[carid][carLocked],
        
CarData[carid][carParked],
        
CarData[carid][carWorld]
    );
    return 
mysql_function_query(g_iHandlequeryfalse"""");

Loaded:
PHP код:
public OnPlayerSpawn(playerid)
{    
    new 
query[300];
     
mysql_format(g_iHandlequerysizeof(query), "SELECT * FROM `playercars` WHERE carOwner = %d LIMIT 3"PlayerData[playerid][pID]);
    
mysql_tquery(g_iHandlequery,"PlayerCar_Load""i"playerid);
        return 
1;
}
forward PlayerCar_Load(playerid);
public 
PlayerCar_Load(playerid)
{
    static
        
rows,
        
fields,
        
str[128];
    
cache_get_data(rowsfieldsg_iHandle);
    for (new 
0rows++) if (MAX_DYNAMIC_CARS)
    {
        
CarData[i][carExists] = true;
        
CarData[i][carID] = cache_get_field_int(i"carID");
        
CarData[i][carModel] = cache_get_field_int(i"carModel");
        
CarData[i][carOwner] = cache_get_field_int(i"carOwner");
        
CarData[i][carPos][0] = cache_get_field_float(i"carPosX");
        
CarData[i][carPos][1] = cache_get_field_float(i"carPosY");
        
CarData[i][carPos][2] = cache_get_field_float(i"carPosZ");
        
CarData[i][carPos][3] = cache_get_field_float(i"carPosR");
        
CarData[i][carColor1] = cache_get_field_int(i"carColor1");
        
CarData[i][carColor2] = cache_get_field_int(i"carColor2");
        
cache_get_field_content(i"carPlate"CarData[i][carPlate], g_iHandle12);
        
CarData[i][carLocked] = cache_get_field_int(i"carLocked");
         
CarData[i][carParked] = cache_get_field_int(i"carParked");
         
CarData[i][carWorld] = cache_get_field_int(i"carWorld");
        
CarData[i][carImpounded] = cache_get_field_int(i"carImpounded");
        
CarData[i][carImpoundPrice] = cache_get_field_int(i"carImpoundPrice");
        for (new 
014++)
        {
            if (
5)
            {
                
format(strsizeof(str), "carWeapon%d"1);
                
CarData[i][carWeapons][j] = cache_get_field_int(istr);
                
format(strsizeof(str), "carAmmo%d"1);
                
CarData[i][carAmmo][j] = cache_get_field_int(istr);
            }
            
format(strsizeof(str), "carMod%d"1);
            
CarData[i][carMods][j] = cache_get_field_int(istr);
        }
        
Car_Spawn(i);
    }
    for (new 
0MAX_DYNAMIC_CARS++) if (CarData[i][carExists]) {
        
format(strsizeof(str), "SELECT * FROM `carstorage` WHERE `ID` = '%d'"CarData[i][carID]);
        
mysql_function_query(g_iHandlestrtrue"OnLoadCarStorage""d"i);
    }
    return 
1;

Unloaded:
PHP код:
public OnPlayerDisconnect(playeridreason)
{
    
PlayerCar_Unload(playerid);
    return 
1;
}
stock PlayerCar_Unload(playerid)
{
    for(new 
idid MAX_DYNAMIC_CARSid++)
    {
        if (
IsVehicleSpawned(id))
        {
            if (
PlayerData[playerid][pID] == CarData[id][carOwner])
            {
                
PlayerCar_Save(id);
                
DestroyVehicle(id);
                
CarData[id][carExists] = false;
            }
        }
    }
    return 
1;


Faction Vehicles
Faction vehicles load when the server starts, and remain there permanently. They are created and loaded like so --

PHP код:
CMD:createfcar(playeridparams[])
{
    static
        
model[32],
        
color1,
        
color2,
        
factionid;
    if (
PlayerData[playerid][pAdmin] < 4)
        return 
SendErrorMessage(playerid"You don't have permission to use this command.");
    if (
sscanf(params"s[32]I(-1)I(-1)I(0)"modelcolor1color2factionid))
        return 
SendSyntaxMessage(playerid"/createfcar [modelid/name] [color1] [color2] [faction ID]");
    if ((
model[0] = GetVehicleModelByName(model)) == 0)
        return 
SendErrorMessage(playerid"Invalid model ID.");
    static
        
Float:x,
        
Float:y,
        
Float:z,
        
Float:angle,
        
id = -1;
    
GetPlayerPos(playeridxyz);
    
GetPlayerFacingAngle(playeridangle);
    
id FactionCar_Create(model[0], xy1anglecolor1color2factionidGetPlayerVirtualWorld(playerid));
    if (
id == -1)
        return 
SendErrorMessage(playerid"The server has reached the limit for dynamic vehicles.");
    return 
1;
}
FactionCar_Create(modelidFloat:xFloat:yFloat:zFloat:anglecolor1color2factionworld)
{
    for (new 
0!= MAX_DYNAMIC_CARS++)
    {
        if (!
CarData[i][carExists])
           {
               if (
color1 == -1)
                   
color1 random(127);
            if (
color2 == -1)
                
color2 random(127);
               
CarData[i][carExists] = true;
            
CarData[i][carModel] = modelid;
            
CarData[i][carPos][0] = x;
            
CarData[i][carPos][1] = y;
            
CarData[i][carPos][2] = z;
            
CarData[i][carPos][3] = angle;
            
CarData[i][carColor1] = color1;
            
CarData[i][carColor2] = color2;
            new 
str[8], query[400];
            
format(strsizeof(str), "%s%s%d%d%s%s%s"LetterList[random(sizeof(LetterList))], LetterList[random(sizeof(LetterList))], random(9), random(9), LetterList[random(sizeof(LetterList))], LetterList[random(sizeof(LetterList))], LetterList[random(sizeof(LetterList))]);
            
SetVehicleNumberPlate(istr);
            
format(CarData[i][carPlate], 11"%s"str);
            
CarData[i][carWorld] = world;
            
CarData[i][carFaction] = faction;
            
CarData[i][carRank] = 1;
            
CarData[i][carVehicle] = CreateVehicle(modelidxyzanglecolor1color2, -1);
            if (
CarData[i][carVehicle] != INVALID_VEHICLE_ID) {
                
ResetVehicle(CarData[i][carVehicle]);
            }
            
mysql_format(g_iHandlequerysizeof(query), "INSERT INTO `factioncars` (carModel, carPosX, carPosY, carPosZ, carPosR, carColor1, carColor2, carPlate, carFaction, carWorld, carRank) VALUES(%d, %f, %f, %f, %f, %d, %d, '%s', %d, %d, %d)",
                
CarData[i][carModel],
                
CarData[i][carPos][0],
                
CarData[i][carPos][1],
                
CarData[i][carPos][2],
                
CarData[i][carPos][3],
                
CarData[i][carColor1],
                
CarData[i][carColor2],
                
CarData[i][carPlate],
                
CarData[i][carFaction],
                
CarData[i][carWorld],
                
CarData[i][carRank]
            );
            
mysql_tquery(g_iHandlequery"OnFactionCarCreated""i"i);
            return 
1;
        }
    }
    return -
1;
}
forward OnFactionCarCreated(carid);
public 
OnFactionCarCreated(carid)
{
    if (
carid == -|| !CarData[carid][carExists])
        return 
0;
    
CarData[carid][carID] = mysql_insert_id();
    
FactionCar_Save(carid);
    return 
1;
}
FactionCar_Save(carid)
{
    static
        
query[900];
    if (
CarData[carid][carVehicle] != INVALID_VEHICLE_ID)
    {
        for (new 
014++) {
            
CarData[carid][carMods][i] = GetVehicleComponentInSlot(CarData[carid][carVehicle], i);
        }
    }
    
format(querysizeof(query), "UPDATE `factioncars` SET `carModel` = '%d', `carPosX` = '%.4f', `carPosY` = '%.4f', `carPosZ` = '%.4f', `carPosR` = '%.4f', `carColor1` = '%d', `carColor2` = '%d', `carPlate` = '%s', `carFaction` = '%d', `carWorld` = '%d', `carRank` ='%d' WHERE `carID` = '%d'",
        
CarData[carid][carModel],
        
CarData[carid][carPos][0],
        
CarData[carid][carPos][1],
        
CarData[carid][carPos][2],
        
CarData[carid][carPos][3],
        
CarData[carid][carColor1],
        
CarData[carid][carColor2],
        
CarData[carid][carPlate],
        
CarData[carid][carFaction],
        
CarData[carid][carWorld],
        
CarData[carid][carRank],
        
CarData[carid][carID]
    );
    return 
mysql_function_query(g_iHandlequeryfalse"""");
}
forward FactionCar_Load();
public 
FactionCar_Load()
{
    static
        
rows,
        
fields;
    
cache_get_data(rowsfieldsg_iHandle);
    for (new 
0rows++) if (MAX_DYNAMIC_CARS)
    {
        
CarData[i][carExists] = true;
        
CarData[i][carID] = cache_get_field_int(i"carID");
        
CarData[i][carModel] = cache_get_field_int(i"carModel");
        
CarData[i][carPos][0] = cache_get_field_float(i"carPosX");
        
CarData[i][carPos][1] = cache_get_field_float(i"carPosY");
        
CarData[i][carPos][2] = cache_get_field_float(i"carPosZ");
        
CarData[i][carPos][3] = cache_get_field_float(i"carPosR");
        
CarData[i][carColor1] = cache_get_field_int(i"carColor1");
        
CarData[i][carColor2] = cache_get_field_int(i"carColor2");
        
cache_get_field_content(i"carPlate"CarData[i][carPlate], g_iHandle12);
         
CarData[i][carParked] = cache_get_field_int(i"carFaction");
         
CarData[i][carWorld] = cache_get_field_int(i"carWorld");
        
CarData[i][carImpounded] = cache_get_field_int(i"carRank");
        if(
CarData[i][carModel] > 399 && CarData[i][carModel] < 612)
        {
            new 
FCar CreateVehicle(CarData[i][carModel], CarData[i][carPos][0], CarData[i][carPos][1], CarData[i][carPos][2], CarData[i][carPos][3], CarData[i][carColor1], CarData[i][carColor2], -1);
            
SetVehicleNumberPlate(FCarCarData[i][carPlate]);
            
SetVehicleToRespawn(FCar);
            
            
CarData[FCar][carID] = CarData[i][carID];
            
CarData[FCar][carModel] = CarData[i][carModel];
            
CarData[FCar][carPos][0] = CarData[i][carPos][0];
            
CarData[FCar][carPos][1] = CarData[i][carPos][1];
            
CarData[FCar][carPos][2] = CarData[i][carPos][2];
            
CarData[FCar][carPos][3] = CarData[i][carPos][3];
            
CarData[FCar][carColor1] = CarData[i][carColor1];
            
CarData[FCar][carColor2] = CarData[i][carColor2];
            
CarData[FCar][carFaction] = CarData[i][carFaction];
            
CarData[FCar][carWorld] = CarData[i][carWorld];
            
CarData[FCar][carRank] = CarData[i][carRank];
        }
         else 
printf("[MYSQL] ERROR LOADING FACTION VEHICLE SQLID: %d",CarData[i][carID]);
    }
    return 
1;

Now, BOTH of these work in isolation.

If I create a player car for myself it creates and saves, and then when I logout it disappears, and re-appears on logging back in.

If I create faction cars, they save and load successfully, and re-appear on server restart.

HOWEVER, if I create a faction car AND a player car and then logout, it all goes tits up. It's so random, sometimes both cars will disappear, sometimes the player car will disappear, sometimes the faction car will. Then, when I relog, they will both appear. Sometimes the car will duplicate itself (but not save to the database). If there are two players in-game both with player cars, if ONE of us logs out, BOTH cars will disappear and the random screw ups will start again, with the cars disappearing and respawning at random when someone re-connects or leaves.

I have no idea wtf is causing this, I've tried to fix it and I just can't. Player cars and faction cars save to separate tables in the database. Should I use two separate enums? Are the SQL IDs conflicting? I'm so confused.
Reply
#2

pawn Код:
id = FactionCar_Create
This might be your problem, as FactionCar_Create returns only either 1 or -1.

#e: Nevermind, I see you only check for -1 and not use it anywhere
Reply
#3

Yeah, it can't be that. It's just so weird, can SQL ids conflict with the actual vehicle ID? Or are they not static? Surely if a player logs in one day and the logs in the next day, the DL vehicle ID would be different?

I just don't see why this is happening... everything is coded fine, as far as I can see. They work absolutely great independently, but when there are other players or a mix of player and faction vehicles it just fucks up.

So irritated.
Reply
#4

Alright, I know what's the issue: you use CarData for both player cars and faction cars.

Player cars:
pawn Код:
for (new i = 0; i < rows; i ++) if (i < MAX_DYNAMIC_CARS)
{
    CarData[i][carExists] = true;
Faction cars

pawn Код:
for (new i = 0; i < rows; i ++) if (i < MAX_DYNAMIC_CARS)
{
     CarData[i][carExists] = true;
As you can see, you are overwriting the same indexes. I'd suggest y_iterate/foreach custom iterators, but we'll keep things simple: change the above loops to something like:
pawn Код:
new row = 0;
for (new i = 0; i < MAX_VEHICLES; i++)
{
    if (CarData[i][carExists]) continue;
    if (row++ >= MAX_DYNAMIC_CARS) { // handle too much cars error }
    CarData[i][carExists] = true;
    // All of your logic
Reply
#5

Thanks for the suggestion. What difference does that make? They're still both going to be using CarData, I'm not familiar with y_iterate
Reply
#6

Yes, but they won't be overriding themselves. My loop checks if CarData[index] is taken, if so, it skips the current index and goes forward until it finds empty slot (with CarData[i][carExists] equal to false)
Reply
#7

I see, so in my code if I create a player car, then a faction car, both are created with index 1, and the faction car overwrites the player car because it doesn't check if the index is used? This is making sense now.

Please can you implement your fix into my player car function so I can see how it all pieces together?

I appreciate your help; this issue has had me stumped for hours!
Reply
#8

pawn Код:
public PlayerCar_Load(playerid)
{
    static
        rows,
        fields,
        str[128];

    new
        row = 0
    ;

    cache_get_data(rows, fields, g_iHandle);

    for (new i = 0; i < rows; i ++)
    {
        // Skip current CarData index if it's taken
        if (CarData[i][carExists]) continue;
        if (row++ >= MAX_DYNAMIC_CARS) {
            printf("Exceeded MAX_DYNAMIC_CARS (%d), breaking", MAX_DYNAMIC_CARS);
            break;
        }
        CarData[i][carExists] = true;
        CarData[i][carID] = cache_get_field_int(i, "carID");
        CarData[i][carModel] = cache_get_field_int(i, "carModel");
        CarData[i][carOwner] = cache_get_field_int(i, "carOwner");
        CarData[i][carPos][0] = cache_get_field_float(i, "carPosX");
        CarData[i][carPos][1] = cache_get_field_float(i, "carPosY");
        CarData[i][carPos][2] = cache_get_field_float(i, "carPosZ");
        CarData[i][carPos][3] = cache_get_field_float(i, "carPosR");
        CarData[i][carColor1] = cache_get_field_int(i, "carColor1");
        CarData[i][carColor2] = cache_get_field_int(i, "carColor2");
        cache_get_field_content(i, "carPlate", CarData[i][carPlate], g_iHandle, 12);
        CarData[i][carLocked] = cache_get_field_int(i, "carLocked");
         CarData[i][carParked] = cache_get_field_int(i, "carParked");
         CarData[i][carWorld] = cache_get_field_int(i, "carWorld");
        CarData[i][carImpounded] = cache_get_field_int(i, "carImpounded");
        CarData[i][carImpoundPrice] = cache_get_field_int(i, "carImpoundPrice");

        for (new j = 0; j < 14; j ++)
        {
            if (j < 5)
            {
                format(str, sizeof(str), "carWeapon%d", j + 1);
                CarData[i][carWeapons][j] = cache_get_field_int(i, str);

                format(str, sizeof(str), "carAmmo%d", j + 1);
                CarData[i][carAmmo][j] = cache_get_field_int(i, str);
            }
            format(str, sizeof(str), "carMod%d", j + 1);
            CarData[i][carMods][j] = cache_get_field_int(i, str);
        }
        Car_Spawn(i);
    }
    for (new i = 0; i < MAX_DYNAMIC_CARS; i ++) if (CarData[i][carExists]) {
        format(str, sizeof(str), "SELECT * FROM `carstorage` WHERE `ID` = '%d'", CarData[i][carID]);

        mysql_function_query(g_iHandle, str, true, "OnLoadCarStorage", "d", i);
    }
    return 1;
}
Do the same for faction cars. Also, if you ever see a SELECT query in a loop, you did the wrong thing. Database/file access is the slowest part of the code. Select all rows you need at once, then sort it out in your code.
Reply
#9

Thank you for your help, I'll test this out tomorrow! Would the index issue have also been causing the problem where if two different players each have a car, it would despawn both of them?
Reply
#10

From quick glance it should not, I can't test your code as I don't have your database and declarations of variables, sorry.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)