Jump to content

attempt to index field '?' (a nil value)


Recommended Posts

Bonjour, 

J'ai créer un script de banque ayaant l'erreur:

attempt to index field '?' (a nil value)

Ce qui entraine bien entendu des dysfonctionnement au niveau des autres scripts utilisant cette fonction que voici:

addEvent("bank:transfer", true)
addEventHandler("bank:transfer", root, function(id, amount, to, reason)
	if(transferBank(id, amount, to, reason)) then
		triggerClientEvent(client, "bank:transferRecieve", client, true)
	else
		triggerClientEvent(client, "bank:transferRecieve", client, false)
	end
end)

function transferBank(id, amount, to, reason)
	if(id and amount and to and reason) then
		if(BANK_ACCOUNTS[to]) then
			if(BANK_ACCOUNTS[id].balance >= amount) then
				dbExec(connection, "INSERT INTO bank_records (bank_id, record_type, record_from, reason, amount, date) VALUES(?, ?, ?, ?, ?, NOW())", to, 3, id, reason, amount)
				dbExec(connection, "UPDATE bank_accounts SET balance = balance - ? WHERE id=?", amount, id)
				dbExec(connection, "UPDATE bank_accounts SET balance = balance + ? WHERE id=?", amount, to)
				BANK_ACCOUNTS[to].balance = BANK_ACCOUNTS[to].balance + amount
				BANK_ACCOUNTS[id].balance = BANK_ACCOUNTS[id].balance - amount
			
				return true
			else
				return false, "Le compte bancaire spécifié n'a pas assez d'argent."
			end
		else
			return false, "Le compte bancaire spécifié n'existe pas."
		end
	else
		return false, "Argument Invalide."
	end
end

Je ne vois pas d'où provient cette erreur. 

 

Link to comment

Est-ce qu'inverser to avec id peut créer cette erreur ?

Voilà le tableau:

	BANK_ACCOUNTS[id] = {
		["id"] = id, 
		["code"] = code,
		["owner"] = owner, 
		["faction"] = faction, 
		["balance"] = balance,
		["name"] = name,
	}

 

Edited by Ea7gign
Link to comment

Pour moi, c'est la définition de ta table qui est pas bonne.

Car si tu l'appelles avec "BANK_ACCOUNTS[id].balance" par exemple, il faut donc un index balance, mais sans mettre entre guillemets.

Je veux dire par là que tu devrais faire :

  1. BANK_ACCOUNTS[id] = {
  2. balance = maBalance,
  3. }

Au lieu de :

  1. BANK_ACCOUNTS[id] = {
  2. ["balance"] = maBalance,
  3. }

Tu vois ? Je pense que c'est ça, mais du coup il faut un nom différent de l'index et de la valeur à définir, tu peux pas mettre "balance = balance", c'est pour ça j'ai mis "maBalance"

Link to comment

Je ne pense pas que se soit ça, parce que les autres fonctions qui utilisent ["balance"] fonctionnent.

Exemple:

addEvent("bank:deposit", true)
addEventHandler("bank:deposit", root, function(id, amount, balance, atm)
	if(id and amount and balance) then
		if(exports["item-manager"]:takeMoney(client, amount, true)) then
			if(atm) then
				dbExec(connection, "UPDATE bank_atms SET balance = balance + ? WHERE id=?", amount, data:get(atm, "atm:id"))
				data:set(atm, "atm:balance", data:get(atm, "atm:balance")+amount)
			end
			
			dbExec(connection, "INSERT INTO bank_records (bank_id, record_type, reason, record_from, amount, date) VALUES(?, ?, ?, ?, ?, NOW())", id, 2, "Deposer", G_BANK_ACCOUNTS.VCBANK, amount)
			dbExec(connection, "UPDATE bank_accounts SET balance = balance + ? WHERE id=?", amount, id)
			BANK_ACCOUNTS[id].balance = BANK_ACCOUNTS[id].balance + amount
		else
			outputChatBox("Impossible de déposer l'argent sur ton compte bancaire pour le moment.", client, 255, 0, 0)
		end
	end
end)

Parce que maintenant si je fait /dpayday sa me met:

attempt to compare nil with number

 

Edited by Ea7gign
Link to comment
  • Moderators
On 25/04/2018 at 14:15, Citizen said:

Essaye de vérifier la valeur id ainsi que le contenu de BANK_ACCOUNTS au moment de l'appel.

Je me répète mais tant que ce n'est pas fait je ne peux pas t'indiquer d'où vient le problème.

Egalement, tu nous as montré la structure du tableau (c'est une bonne chose): a quelle moment est-il créé ? au démarrage du script et en parcourant tous les comptes enregistrés ? ou seulement joueur par joueur au fur et à mesure qu'il se connecte ?

Link to comment
  • Moderators

Bah un simple outputChatBox en début de fonction par exemple ?

addEvent("bank:transfer", true)
addEventHandler("bank:transfer", root, function(id, amount, to, reason)
    outputChatBox(id) -- et la valeur d'id s'affichera dans la chatbox
	if(transferBank(id, amount, to, reason)) then
		triggerClientEvent(client, "bank:transferRecieve", client, true)
	else
		triggerClientEvent(client, "bank:transferRecieve", client, false)
	end
end)

function transferBank(id, amount, to, reason)
	if(id and amount and to and reason) then
		if(BANK_ACCOUNTS[to]) then
			if(BANK_ACCOUNTS[id].balance >= amount) then
				dbExec(connection, "INSERT INTO bank_records (bank_id, record_type, record_from, reason, amount, date) VALUES(?, ?, ?, ?, ?, NOW())", to, 3, id, reason, amount)
				dbExec(connection, "UPDATE bank_accounts SET balance = balance - ? WHERE id=?", amount, id)
				dbExec(connection, "UPDATE bank_accounts SET balance = balance + ? WHERE id=?", amount, to)
				BANK_ACCOUNTS[to].balance = BANK_ACCOUNTS[to].balance + amount
				BANK_ACCOUNTS[id].balance = BANK_ACCOUNTS[id].balance - amount
			
				return true
			else
				return false, "Le compte bancaire spécifié n'a pas assez d'argent."
			end
		else
			return false, "Le compte bancaire spécifié n'existe pas."
		end
	else
		return false, "Argument Invalide."
	end
end

 

Et pour la table tu peux utiliser var_dump qui est une fonction à copier dans ton code (car ce n'est pas une fonction de base de MTA)

var_dump("-v", BANK_ACCOUNTS) -- affiche le contenu de BANK_ACCOUNTS dans la console

 

Link to comment
  • Moderators
Quote

123456789
1
1

parce que tu as fait 3 fois la commande ? (enfin je sais pas si c'est une commande ou un GUI mais si t'as 3 lignes c'est que t'as fait 3 fois un transfert nan ?)

et pour le BANK_ACCOUNTS ?? (j'ai demandé 2 choses, le var_dump met le juste après l'outputChatBox :))
 

Link to comment
  • Moderators
Quote

C'est une commande, je l'ai faite 1 fois, pour le var_dump

C'est bizarre que ça sorte 3 lignes dans la chatbox o_O

Quote

pour le var_dump, sa me met une erreur


attempt to call global 'var_dump' (a nil value)

Hmmm là je veux pas être méchant mais soit plus attentif, on ne va pas y arriver si à chaque fois tu ne fais que la moitié des instructions. J'ai des contraintes IRL qui, en ce moment, ne me permettent pas de te répondre rapidement, donc si en plus je dois répéter, on va pas aller très vite ^_^ Je dis ça pour toi, j'imagine que tu veux régler ce problème au plus vite.

Je cite ce que j'avais marqué concernant la fonction var_dump:

On 27/04/2018 at 17:08, Citizen said:

Et pour la table tu peux utiliser var_dump qui est une fonction à copier dans ton code (car ce n'est pas une fonction de base de MTA)

Donc ce que j'attendais de toi c'est que tu cliques sur var_dump qui est un lien vers la page wiki de cette fonction:
https://wiki.multitheftauto.com/wiki/Var_dump

Sur la page, ils te fournissent le code de cette fonction:

Spoiler

-- modifiers: v - verbose (all subtables), n - normal, s - silent (no output), dx - up to depth x, u - unnamed
function var_dump(...)
	-- default options
	local verbose = false
	local firstLevel = true
	local outputDirectly = true
	local noNames = false
	local indentation = "\t\t\t\t\t\t"
	local depth = nil

	local name = nil
	local output = {}
	for k,v in ipairs(arg) do
		-- check for modifiers
		if type(v) == "string" and k < #arg and v:sub(1,1) == "-" then
			local modifiers = v:sub(2)
			if modifiers:find("v") ~= nil then
				verbose = true
			end
			if modifiers:find("s") ~= nil then
				outputDirectly = false
			end
			if modifiers:find("n") ~= nil then
				verbose = false
			end
			if modifiers:find("u") ~= nil then
				noNames = true
			end
			local s,e = modifiers:find("d%d+")
			if s ~= nil then
				depth = tonumber(string.sub(modifiers,s+1,e))
			end
		-- set name if appropriate
		elseif type(v) == "string" and k < #arg and name == nil and not noNames then
			name = v
		else
			if name ~= nil then
				name = ""..name..": "
			else
				name = ""
			end

			local o = ""
			if type(v) == "string" then
				table.insert(output,name..type(v).."("..v:len()..") \""..v.."\"")
			elseif type(v) == "userdata" then
				local elementType = "no valid MTA element"
				if isElement(v) then
					elementType = getElementType(v)
				end
				table.insert(output,name..type(v).."("..elementType..") \""..tostring(v).."\"")
			elseif type(v) == "table" then
				local count = 0
				for key,value in pairs(v) do
					count = count + 1
				end
				table.insert(output,name..type(v).."("..count..") \""..tostring(v).."\"")
				if verbose and count > 0 and (depth == nil or depth > 0) then
					table.insert(output,"\t{")
					for key,value in pairs(v) do
						-- calls itself, so be careful when you change anything
						local newModifiers = "-s"
						if depth == nil then
							newModifiers = "-sv"
						elseif  depth > 1 then
							local newDepth = depth - 1
							newModifiers = "-svd"..newDepth
						end
						local keyString, keyTable = var_dump(newModifiers,key)
						local valueString, valueTable = var_dump(newModifiers,value)
						
						if #keyTable == 1 and #valueTable == 1 then
							table.insert(output,indentation.."["..keyString.."]\t=>\t"..valueString)
						elseif #keyTable == 1 then
							table.insert(output,indentation.."["..keyString.."]\t=>")
							for k,v in ipairs(valueTable) do
								table.insert(output,indentation..v)
							end
						elseif #valueTable == 1 then
							for k,v in ipairs(keyTable) do
								if k == 1 then
									table.insert(output,indentation.."["..v)
								elseif k == #keyTable then
									table.insert(output,indentation..v.."]")
								else
									table.insert(output,indentation..v)
								end
							end
							table.insert(output,indentation.."\t=>\t"..valueString)
						else
							for k,v in ipairs(keyTable) do
								if k == 1 then
									table.insert(output,indentation.."["..v)
								elseif k == #keyTable then
									table.insert(output,indentation..v.."]")
								else
									table.insert(output,indentation..v)
								end
							end
							for k,v in ipairs(valueTable) do
								if k == 1 then
									table.insert(output,indentation.." => "..v)
								else
									table.insert(output,indentation..v)
								end
							end
						end
					end
					table.insert(output,"\t}")
				end
			else
				table.insert(output,name..type(v).." \""..tostring(v).."\"")
			end
			name = nil
		end
	end
	local string = ""
	for k,v in ipairs(output) do
		if outputDirectly then
			outputConsole(v)
		end
		string = string..v
	end
	return string, output
end

 

Tu copies tout le code et tu le colles dans le même fichier où tu veux l'utiliser.

Nous on l'utilise juste après le outputChatBox et faut le laisser le temps de nos tests.

On s'en sert pour débuguer ton script, et une fois terminé tu pourras supprimer ce code.

J'espère que c'est plus clair maintenant.

Du coup j'attend le résultat de la chatbox et du var_dump (pour lui ça s'écrira dans la console F8 ingame) et également la commande complète que tu tapes.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...