[debug] Run time error 4: "Array index out of bounds"
#1

hi
i have a problem when i try to run my gamemode
ss :


this is LoadHouses function :
Код HTML:
function LoadHouses()
{
    new PropertyString[1024];
	houses = cache_num_rows();
	for(new i = 1; i <= houses; i++)
	{
		new j = i - 1;
		HouseInfo[i][hID] 					= i;
		HouseInfo[i][hEntrancex] 			= cache_get_field_content_float(j, "Entrancex");
		HouseInfo[i][hEntrancey] 			= cache_get_field_content_float(j, "Entrancey");
		HouseInfo[i][hEntrancez] 			= cache_get_field_content_float(j, "Entrancez");
		HouseInfo[i][hExitx] 				= cache_get_field_content_float(j, "Exitx");
		HouseInfo[i][hExity] 				= cache_get_field_content_float(j, "Exity");
		HouseInfo[i][hExitz] 				= cache_get_field_content_float(j, "Exitz");
		HouseInfo[i][hHealth] 				= cache_get_field_content_int(j, "Health");
		HouseInfo[i][hArmour] 				= cache_get_field_content_int(j, "Armour");
		cache_get_field_content(j, "Owner", HouseInfo[i][hOwner], SQL, 129);
		HouseInfo[i][hValue] 				= cache_get_field_content_int(j, "Value");
		HouseInfo[i][hInt] 					= cache_get_field_content_int(j, "Int");
		HouseInfo[i][hLock] 				= cache_get_field_content_int(j, "Lockk");
		HouseInfo[i][hOwned] 				= cache_get_field_content_int(j, "Owned");
		HouseInfo[i][hRent] 				= cache_get_field_content_int(j, "Rent");
		HouseInfo[i][hRentabil] 			= cache_get_field_content_int(j, "Rentabil");
		HouseInfo[i][hTakings] 				= cache_get_field_content_int(j, "Takings");
		HouseInfo[i][hDate] 				= cache_get_field_content_int(j, "Date");
		HouseInfo[i][hLevel] 				= cache_get_field_content_int(j, "Level");
		if(HouseInfo[i][hOwned] == 0)
		{
			format(PropertyString, sizeof(PropertyString), "{009900}House %d\nThis house is for sale\nPrice: {00FF00}$%s\n{009900}Level: {00FF00}%d\n{009900}Type {00FF00}/buyhouse {009900}to buy",i,Decimal(HouseInfo[i][hValue]),HouseInfo[i][hLevel]);
			HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25, INVALID_PLAYER_ID, INVALID_VEHICLE_ID, 1, -1, -1, -1, 100.0);
		}
		else if(HouseInfo[i][hOwned] == 1)
		{
			if(HouseInfo[i][hRentabil] == 1)
			{
				format(PropertyString, sizeof(PropertyString), "{009900}House %d\nOwner: {00FF00}%s\n{009900}Level: {00FF00}%d",i,HouseInfo[i][hOwner],HouseInfo[i][hLevel]);
				HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25, INVALID_PLAYER_ID, INVALID_VEHICLE_ID, 1, -1, -1, -1, 100.0);
			}
			else
			{
				format(PropertyString, sizeof(PropertyString), "{009900}House %d\nOwner: {00FF00}%s\n{009900}Level: {00FF00}%d\n{009900}Rent: {00FF00}$%s\n{009900}to rent a room type {00FF00}/rentroom",i,HouseInfo[i][hOwner],HouseInfo[i][hLevel],Decimal(HouseInfo[i][hRent]));
				HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25, INVALID_PLAYER_ID, INVALID_VEHICLE_ID, 1, -1, -1, -1, 100.0);
			}
		}
	}
	printf("[MYSQL] Houses: %d", houses);
}
what i must do ?
Reply
#2

Try

PHP код:

function LoadHouses()
{
        new 
PropertyString[1024], filashouses;
    if(
cache_get_row_count(filas))
{
    for(new 
0<= filasi++)
    {
        new 
1;
        
HouseInfo[i][hID]                     = i;
        
HouseInfo[i][hEntrancex]             = cache_get_field_content_float(j"Entrancex");
        
HouseInfo[i][hEntrancey]             = cache_get_field_content_float(j"Entrancey");
        
HouseInfo[i][hEntrancez]             = cache_get_field_content_float(j"Entrancez");
        
HouseInfo[i][hExitx]                 = cache_get_field_content_float(j"Exitx");
        
HouseInfo[i][hExity]                 = cache_get_field_content_float(j"Exity");
        
HouseInfo[i][hExitz]                 = cache_get_field_content_float(j"Exitz");
        
HouseInfo[i][hHealth]                 = cache_get_field_content_int(j"Health");
        
HouseInfo[i][hArmour]                 = cache_get_field_content_int(j"Armour");
        
cache_get_field_content(j"Owner"HouseInfo[i][hOwner], SQL129);
        
HouseInfo[i][hValue]                 = cache_get_field_content_int(j"Value");
        
HouseInfo[i][hInt]                     = cache_get_field_content_int(j"Int");
        
HouseInfo[i][hLock]                 = cache_get_field_content_int(j"Lockk");
        
HouseInfo[i][hOwned]                 = cache_get_field_content_int(j"Owned");
        
HouseInfo[i][hRent]                 = cache_get_field_content_int(j"Rent");
        
HouseInfo[i][hRentabil]             = cache_get_field_content_int(j"Rentabil");
        
HouseInfo[i][hTakings]                 = cache_get_field_content_int(j"Takings");
        
HouseInfo[i][hDate]                 = cache_get_field_content_int(j"Date");
        
HouseInfo[i][hLevel]                 = cache_get_field_content_int(j"Level");
        if(
HouseInfo[i][hOwned] == 0)
        {
            
format(PropertyStringsizeof(PropertyString), "{009900}House %d\nThis house is for sale\nPrice: {00FF00}$%s\n{009900}Level: {00FF00}%d\n{009900}Type {00FF00}/buyhouse {009900}to buy",i,Decimal(HouseInfo[i][hValue]),HouseInfo[i][hLevel]);
            
HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25INVALID_PLAYER_IDINVALID_VEHICLE_ID1, -1, -1, -1100.0);
        }
        else if(
HouseInfo[i][hOwned] == 1)
        {
            if(
HouseInfo[i][hRentabil] == 1)
            {
                
format(PropertyStringsizeof(PropertyString), "{009900}House %d\nOwner: {00FF00}%s\n{009900}Level: {00FF00}%d",i,HouseInfo[i][hOwner],HouseInfo[i][hLevel]);
                
HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25INVALID_PLAYER_IDINVALID_VEHICLE_ID1, -1, -1, -1100.0);
            }
            else
            {
                
format(PropertyStringsizeof(PropertyString), "{009900}House %d\nOwner: {00FF00}%s\n{009900}Level: {00FF00}%d\n{009900}Rent: {00FF00}$%s\n{009900}to rent a room type {00FF00}/rentroom",i,HouseInfo[i][hOwner],HouseInfo[i][hLevel],Decimal(HouseInfo[i][hRent]));
                
HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25INVALID_PLAYER_IDINVALID_VEHICLE_ID1, -1, -1, -1100.0);
            }
        }
houses++;
    }
}
    
printf("[MYSQL] Houses: %d"houses);

Reply
#3

Every house should have it's own ID stored in the database as well to be able to identify each house separately when you want to adjust data for a house later.

You can then use that ID as the index of your array.
PHP код:
// This function is called to load the houses from MySQL during OnGameModeInit
Houses_Load()
{
    
// Setup local variables
    
new query[256], Cache:resultrowscountsuccesscountfailedID;
    
// Send a query to load all houses from MySQL (connect the UserName from playeraccounts to the result based on the OwnerID of the house (OwnerName results in "NULL" when there is no owner))
    
format(querysizeof(query), "SELECT a.*, (SELECT b.Name FROM playeraccounts b WHERE b.UserID = a.OwnerID) AS OwnerName FROM houses a");
    
result mysql_query(SQL_dbquerytrue);
    
// Print some debug info to the server console
    
printf("*** Loading houses from MySQL");
    
// Get the amount of rows (houses)
    
cache_get_row_count(rows);
    
// If there are any rows (houses) loaded, load data
    
if (rows >= 1)
    {
        
// Loop through all rows
        
for (new rowrow rowsrow++)
        {
            
// Load the ID first
            
cache_get_value_name_int(row"ID"ID);
            
// Check if the ID is invalid (out of range)
            
if ((ID 1) || (ID >= MAX_HOUSES))
            {
                
// Count the amount of failed houses entries (invalid ID's)
                
countfailed++;
                
// Add a message to the server-console to inform the admin about the wrong ID
                
printf("*** ERROR: Invalid ID found in table \"houses\": %i"ID);
                
// Continue with the next house entry from the MySQL query
                
continue;
            }
            
// Read remaining data and store it
            
cache_get_value_name(row"Name"AHouses[ID][Name], 50);
            
cache_get_value_name_float(row"X"AHouses[ID][X]);
            
cache_get_value_name_float(row"Y"AHouses[ID][Y]);
            
cache_get_value_name_float(row"Z"AHouses[ID][Z]);
            
cache_get_value_name_int(row"HouseType"AHouses[ID][HouseType]);
            
cache_get_value_name_int(row"Interior"AHouses[ID][Interior]);
            
cache_get_value_name_int(row"Level"AHouses[ID][Level]);
            
cache_get_value_name_int(row"MaxLevel"AHouses[ID][MaxLevel]);
            
cache_get_value_name_int(row"BuyPrice"AHouses[ID][BuyPrice]);
            
cache_get_value_name_int(row"OwnerID"AHouses[ID][OwnerID]);
            
cache_get_value_name(row"OwnerName"AHouses[ID][OwnerName], 25);
            
cache_get_value_name_int(row"DoorStatus"AHouses[ID][DoorStatus]);
            
cache_get_value_name_int(row"HouseValue"AHouses[ID][HouseValue]);
            
cache_get_value_name_int(row"MaintenanceTime"AHouses[ID][MaintenanceTime]);
            
cache_get_value_name_int(row"MaintenanceFee"AHouses[ID][MaintenanceFee]);
            
cache_get_value_name_int(row"AuctionEndTime"AHouses[ID][AuctionEndTime]);
            
cache_get_value_name_int(row"LastBid"AHouses[ID][LastBid]);
            
// Create the 3DText, mapicon and pickup that appears at the house entrance
            
House_UpdateEntrance(ID);
            
// Count the succesfully loaded house entries
            
countsuccess++;
        }
    }
    
// Print the amount of houses entries loaded for debugging
    
printf("*** >>> Houses loaded: %i (successful: %i, failed: %i)"rowscountsuccesscountfailed);
    
printf("");
    
// Clear the cache to prevent memory-leaks
    
cache_delete(result);
    return 
1;

This is my loading function for houses in my own gamemode and works perfectly.

You'll see that it loads the ID first, and the rest uses that ID to index the array for storing the remaining data.

When creating houses using some /createhouse command, start from ID 1.
PHP код:
// Lets the player add new houses
COMMAND:createhouse(playeridparams[])
{
    
// Setup local variables
    
new buypricemaxlevelIDFloat:xFloat:yFloat:zmsg[128], query[160];
    
// If the player has an insufficient admin-level (he needs level 6), exit the command
    
if (APlayerData[playerid][AdminLevel] < 6) return SendClientMessage(playerid0xFFFFFFFF"{FF0000}Only admins level 6 and higher can use this command");
    
// If the player is the driver of a vehicle, exit the command
    
if(GetPlayerVehicleID(playerid) != 0) return SendClientMessage(playerid0xFFFFFFFF"{FF0000}You must be on foot to create a house");
    
// Split parameters
    
if (sscanf(params"ii"buypricemaxlevel)) return SendClientMessage(playerid0xFF0000AA"Usage: \"/createhouse <price> <maxlevel (1-10)>\"");
    
// Exit the function if the player entered an invalid maxlevel
    
if ((maxlevel 1) || (maxlevel 10)) return SendClientMessage(playerid0xFFFFFFFF"{FF0000}MaxLevel must be from 1 to 10");
    
// Find the first free HouseID
    
for (ID 1ID MAX_HOUSESID++)
        if (
AHouses[ID][PickupID] == 0// Check if an empty house-index has been found (PickupID is 0)
            
break; // Stop searching, the first free HouseID has been found now
    // Exit the function if the maximum amount of houses has been reached
    
if (ID == MAX_HOUSES) return SendClientMessage(playerid0xFFFFFFFF"{FF0000}The maximum amount of houses has been reached");
    
// Get the player's position
    
GetPlayerPos(playeridxyz);
    
// Set some default data
    
format(AHouses[ID][Name], 50"NoName"); // Default name of the house
    
AHouses[ID][X] = x;
    
AHouses[ID][Y] = y;
    
AHouses[ID][Z] = z;
    
AHouses[ID][HouseType] = 0// Normal upgradable house
    
AHouses[ID][Interior] = 0;
    
AHouses[ID][Level] = 0;
    
AHouses[ID][MaxLevel] = maxlevel;
    
AHouses[ID][BuyPrice] = buyprice;
    
AHouses[ID][OwnerID] = 0;
    
AHouses[ID][OwnerName][0] = 0;
    
AHouses[ID][DoorStatus] = 0;
    
// Create the 3DText that appears above the house-pickup (displays the price of the house)
    
House_UpdateEntrance(ID);
    
// Save the house into the database
    
mysql_format(SQL_dbquerysizeof(query), "INSERT INTO houses (ID, X, Y, Z, MaxLevel, BuyPrice) VALUES ('%i', '%f', '%f', '%f', '%i', '%i')"IDxyzmaxlevelbuyprice);
    
mysql_tquery(SQL_dbquery"""");
    
// Inform the player that he created a new house
    
format(msgsizeof(msg), "{00FF00}You've succesfully created house {FFFF00}%i"ID);
    
SendClientMessage(playerid0xFFFFFFFFmsg);
    
// Let the server know that this was a valid command
    
return 1;

I wonder how you update certain data later on when a house gets bought, sold, upgraded, changed interior, ...
I don't see any variable to uniquely identify each house.
What do you use in your WHERE clause to update a house when it levels up for example?
If you use the hID variable, why don't you load that from the database and use it, instead of using some "i" variable and using another "j" (with a different value as well) to access the rows?
Never assume that "i" will be equal to the hID in your database.

As you might have noticed, I've built a few safe-guards in my code to prevent houseID's going outside the allowed range of the array, effectively protecting the code from array-out-of-bounds errors, even if some admin inserts an invalid ID directly inside the database.

PHP код:
mysql_format(SQL_dbquerysizeof(query), "UPDATE houses SET Name = '%e', Interior = '1', Level = '%i', OwnerID = '%i', DoorStatus = '%i', HouseValue = '%i', MaintenanceTime = '%i', MaintenanceFee = '%i' WHERE ID = '%i'"AHouses[ID][Name], AHouses[ID][Level], AHouses[ID][OwnerID], AHouses[ID][DoorStatus], AHouses[ID][HouseValue], AHouses[ID][MaintenanceTime], AHouses[ID][MaintenanceFee], ID);
mysql_format(SQL_dbquerysizeof(query), "UPDATE houses SET Level = '%i' WHERE ID = '%i'"newlevelhouseid);
mysql_format(SQL_dbquerysizeof(query), "UPDATE houses SET Interior = '%i' WHERE ID = '%i'"AHouses[houseid][Interior], houseid);
mysql_format(SQL_dbquerysizeof(query), "UPDATE houses SET LastBid = '%i' WHERE ID = '%i'"AHouses[houseid][LastBid], houseid);
mysql_format(SQL_dbquerysizeof(query), "UPDATE houses SET Name = '%e' WHERE ID = '%i'"AHouses[houseid][Name], houseid);
mysql_format(SQL_dbquerysizeof(query), "UPDATE houses SET AuctionEndTime = '%i' WHERE ID = '%i'"AHouses[houseid][AuctionEndTime], houseid);
mysql_format(SQL_dbquerysizeof(query), "UPDATE houses SET AuctionEndTime = '0', MaintenanceTime = '%i', LastBid = '0' WHERE ID = '%i'"AHouses[houseid][MaintenanceTime], houseid);
mysql_format(SQL_dbquerysizeof(query), "UPDATE houses SET HouseValue = '%i', MaintenanceFee = '%i' WHERE ID = '%i'"AHouses[houseid][HouseValue], AHouses[houseid][MaintenanceFee], houseid); 
As you can see here, it's easy when you just can use the ID variable, which is actually the index of the array.

Of course, the ID in my database isn't set to auto-increment.
Otherwise the ID will soon be larger than MAX_HOUSES and there will be gaps in the ID's when you delete houses.

I'm letting the script decide which ID the house gets when it's created.
If there is a house deleted, that gap will be filled again when I create a new house later on.
Reply
#4

Quote:
Originally Posted by Eloy
Посмотреть сообщение
Try

PHP код:

function LoadHouses()
{
        new 
PropertyString[1024], filashouses;
    if(
cache_get_row_count(filas))
{
    for(new 
0<= filasi++)
    {
        new 
1;
        
HouseInfo[i][hID]                     = i;
        
HouseInfo[i][hEntrancex]             = cache_get_field_content_float(j"Entrancex");
        
HouseInfo[i][hEntrancey]             = cache_get_field_content_float(j"Entrancey");
        
HouseInfo[i][hEntrancez]             = cache_get_field_content_float(j"Entrancez");
        
HouseInfo[i][hExitx]                 = cache_get_field_content_float(j"Exitx");
        
HouseInfo[i][hExity]                 = cache_get_field_content_float(j"Exity");
        
HouseInfo[i][hExitz]                 = cache_get_field_content_float(j"Exitz");
        
HouseInfo[i][hHealth]                 = cache_get_field_content_int(j"Health");
        
HouseInfo[i][hArmour]                 = cache_get_field_content_int(j"Armour");
        
cache_get_field_content(j"Owner"HouseInfo[i][hOwner], SQL129);
        
HouseInfo[i][hValue]                 = cache_get_field_content_int(j"Value");
        
HouseInfo[i][hInt]                     = cache_get_field_content_int(j"Int");
        
HouseInfo[i][hLock]                 = cache_get_field_content_int(j"Lockk");
        
HouseInfo[i][hOwned]                 = cache_get_field_content_int(j"Owned");
        
HouseInfo[i][hRent]                 = cache_get_field_content_int(j"Rent");
        
HouseInfo[i][hRentabil]             = cache_get_field_content_int(j"Rentabil");
        
HouseInfo[i][hTakings]                 = cache_get_field_content_int(j"Takings");
        
HouseInfo[i][hDate]                 = cache_get_field_content_int(j"Date");
        
HouseInfo[i][hLevel]                 = cache_get_field_content_int(j"Level");
        if(
HouseInfo[i][hOwned] == 0)
        {
            
format(PropertyStringsizeof(PropertyString), "{009900}House %d\nThis house is for sale\nPrice: {00FF00}$%s\n{009900}Level: {00FF00}%d\n{009900}Type {00FF00}/buyhouse {009900}to buy",i,Decimal(HouseInfo[i][hValue]),HouseInfo[i][hLevel]);
            
HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25INVALID_PLAYER_IDINVALID_VEHICLE_ID1, -1, -1, -1100.0);
        }
        else if(
HouseInfo[i][hOwned] == 1)
        {
            if(
HouseInfo[i][hRentabil] == 1)
            {
                
format(PropertyStringsizeof(PropertyString), "{009900}House %d\nOwner: {00FF00}%s\n{009900}Level: {00FF00}%d",i,HouseInfo[i][hOwner],HouseInfo[i][hLevel]);
                
HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25INVALID_PLAYER_IDINVALID_VEHICLE_ID1, -1, -1, -1100.0);
            }
            else
            {
                
format(PropertyStringsizeof(PropertyString), "{009900}House %d\nOwner: {00FF00}%s\n{009900}Level: {00FF00}%d\n{009900}Rent: {00FF00}$%s\n{009900}to rent a room type {00FF00}/rentroom",i,HouseInfo[i][hOwner],HouseInfo[i][hLevel],Decimal(HouseInfo[i][hRent]));
                
HouseLabel[i] = CreateDynamic3DTextLabel(PropertyString ,0x09FF00FF,HouseInfo[i][hEntrancex], HouseInfo[i][hEntrancey], HouseInfo[i][hEntrancez],25INVALID_PLAYER_IDINVALID_VEHICLE_ID1, -1, -1, -1100.0);
            }
        }
houses++;
    }
}
    
printf("[MYSQL] Houses: %d"houses);

with this when i run server that load just 1 houses
but i have 999 houses in my db
Reply
#5

pawn Код:
for(new i = 1; i <= houses; i++)
I guess these has to be:
pawn Код:
for(new i = 0; i < houses; i++)
Now you will need to remove
pawn Код:
new j = i - 1;
and dont forget to replace j with i in that public.

pawn Код:
HouseInfo[i][hID]                   = i;
The fuck? Maybe you meant to retrieve house id from database
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)