Jump to content

Why I get failed to call [string "?"] error?


thund3rbird23

Recommended Posts

I'm trying to call a function:

exports["s_phone"]:showPhoneFunction(itemValue)

But I get this error, why? what's wrong?

Quote

call: failed to call 's_phone:showPhoneFunction' [string "?"]

function showPhoneFunction(itemValue)
	if showPhone then
		exports.chat:sendLocalMeAction(localPlayer, "open")
		showPhone = false
		loadedPhoneInterFace = false
		actualPhoneID = -1
		menu = -1
		currentChat = -1
		musicID = -1
		removeEventHandler("onClientRender", getRootElement(), PlayedSound)
		if isElement(sound) then
			stopSound(sound)
		end	

	else
		exports.chat:sendLocalMeAction(localPlayer, "close")
		showPhone = true
		inCallMember = nil
		actualPhoneID = itemValue
		triggerServerEvent("getPhoneDataFromServer", localPlayer, localPlayer, actualPhoneID)
		triggerServerEvent("getPhoneContactFromServer", localPlayer, localPlayer, actualPhoneID)			
		menu = 1
		numberText = {}
		callMessages = {}
		phoneContacts = {}
		currentCallMSG = -3
	end
end

I'm added to meta.xml the following line:

 <export function="showPhoneFunction" type="client" />

 

Link to comment
  • Moderators
2 hours ago, thund3rbird23 said:

But I get this error, why? what's wrong?

Is the file you called from clientside?

Did you make your call after the s_phone resource has been started?

Try also this function, it might be character related:

call

 

Link to comment

As far as I know you get this error message in case the called function / resource has errors or as IIYAMA said the resource with the exported function is not started.

So in case the required resource is started, check for errors in the debugscript that got outputted before your 'failed to call' error.

Link to comment
On 10/09/2019 at 17:42, IIYAMA said:

Is the file you called from clientside?

Did you make your call after the s_phone resource has been started?

Try also this function, it might be character related:


call

 

Yes, I make the call after the resource has been started.

I think the call code is wrong but don't know why.

addEvent("useItem", true)
addEventHandler("useItem", getRootElement(),
	function(dbID, use)

		if isElement(source) and dbID then
			local item = false
			for k, v in pairs(itemsTable[source]) do
				if v.dbID == dbID then
					item = v
					break
				end
			end

			if item then
				local playerInterior = getElementInterior(source)
				local playerDimension = getElementDimension(source)
				local itemId = item.itemId

				if itemId == 71
					if use then
                        exports["s_phone"]:showPhoneFunction()

 

Edited by thund3rbird23
Link to comment
  • Moderators
7 hours ago, thund3rbird23 said:

I think the call code is wrong but don't know why.

 

Debug the export list and see if the resource can be found.

iprint(exports["s_phone"])

 

Else as I said before, use the call function. That one has never failed for me without a logic error.

Link to comment
1 hour ago, IIYAMA said:

 

Debug the export list and see if the resource can be found.


iprint(exports["s_phone"])

 

Else as I said before, use the call function. That one has never failed for me without a logic error.

 

Quote

INFO: { res = resource[s_phone], <metatable> = { __index = <function 1> } }

 

and the call function returns the same as exports.

Link to comment
  • Moderators

 

1 hour ago, thund3rbird23 said:

Umm yes.

So the situation is the following, I want to call the showPhoneFunction and set the itemValue to the item.data1 (this is from server side) 

You will need triggerClientEvent for that. exports only work on the same client/server-side.

 

Server (resource 1)

triggerClientEvent (source, "fill in eventName", source, itemValue)

Client (resource 1) It is important to place the addEvent on the resource that is triggering, this reduces errors: "event isn't added"

addEvent("fill in eventName", true)

 

 


 

Client (resource 2)

addEventHandler("fill in eventName", localPlayer, showPhoneFunction, false)

 

 

 

  • Thanks 1
Link to comment
1 hour ago, IIYAMA said:

 

You will need triggerClientEvent for that. exports only work on the same client/server-side.

 

Server (resource 1)


triggerClientEvent (source, "fill in eventName", source, itemValue)

Client (resource 1) It is important to place the addEvent on the resource that is triggering, this reduces errors: "event isn't added"


addEvent("fill in eventName", true)

 

 


 

Client (resource 2)


addEventHandler("fill in eventName", localPlayer, showPhoneFunction, false)

Okay, now the phone showing. Thank you so much!

 

 

  • Like 1
Link to comment
9 hours ago, IIYAMA said:

 

You will need triggerClientEvent for that. exports only work on the same client/server-side.

 

Server (resource 1)


triggerClientEvent (source, "fill in eventName", source, itemValue)

Client (resource 1) It is important to place the addEvent on the resource that is triggering, this reduces errors: "event isn't added"


addEvent("fill in eventName", true)

 

 


 

Client (resource 2)


addEventHandler("fill in eventName", localPlayer, showPhoneFunction, false)

 

 

 

Can you help me a bit more please?

Almost everything works fine, except the "callTargetInServer" and the "onClientCallAd" functions.

 

function callTargetInServer(playerSource, number, playerNumber)
	if number then
		targetPlayer = callMember(number)
		if targetPlayer ~= false and targetPlayer ~= "inCall" then
			triggerClientEvent(targetPlayer, "showMenu", targetPlayer, playerNumber, 6, playerSource, number)
			triggerClientEvent(playerSource, "showMenu", playerSource, number, 7, targetPlayer, playerNumber)
			triggerClientEvent(targetPlayer, "showSound", targetPlayer)	
			exports.s_chat:sendLocalDoAction(targetPlayer, " 's phone ringing")				
		elseif targetPlayer == "inCall" then
			outputChatBox("#D64541[Error] #ffffffThis number already in a call!", playerSource,255,255,255,true)
		else
			outputChatBox("#D64541[Error] #ffffffNumber doesn't found", playerSource,255,255,255,true)
		end
	end
end
addEvent("callTargetInServer", true)
addEventHandler("callTargetInServer", getRootElement(), callTargetInServer)

This is always call one player if more players in the server. If I'm alone then always calls me and if I put fake number then doing the same.
 

function onClientCallAd(player, ad, ara, numberCall)
	local amout = math.ceil(ara)
	setElementData(player, "char:check", true) 
	local money = getElementData(player,"char.Money")
	if(money<amout)then
		outputChatBox("You don't have enough money!", player, 255,0,0)
		return
	end
	setElementData(player,"char.Money",getElementData(player,"char.Money") - amout)
	for index , value in ipairs (getElementsByType("player")) do  
		if (getElementData(value, "loggedin") and not getElementData(value, "char:check")) or player == value   then
			outputChatBox ("#66ff66 AD: #ffcc00" ..ad.. " ((" ..getPlayerName(player):gsub("_", " ") .. "))",value,0, 233, 58,true)
			outputChatBox ("#66ff66 Contact: #ffcc00" .. numberCall,value,0, 233, 58,true)
		end
	end
end
addEvent("onClientCallForAdData", true )
addEventHandler("onClientCallForAdData", getRootElement(), onClientCallAd)

The players doesn't see each others ad only their own ads.

Edited by thund3rbird23
Link to comment
  • Moderators
7 hours ago, thund3rbird23 said:

The players doesn't see each others ad only their own ads.

Send the message to the root. Which includes all players.(currently ingame)

triggerClientEvent(root, "showMenu",

 

Edited by IIYAMA
Link to comment
6 hours ago, IIYAMA said:

Send the message to the root. Which includes all players.(currently ingame)


triggerClientEvent(root, "showMenu",

 

That's "showMenu" trigger is for calling others not for displaying the ads. But I fixed it so now we can see each others ad.

But what about the calling? 

 

function callTargetInServer(playerSource, number, playerNumber)
	if number then
		targetPlayer = callMember(number)
		if targetPlayer ~= false and targetPlayer ~= "inCall" then
			triggerClientEvent(targetPlayer, "showMenu", targetPlayer, playerNumber, 6, playerSource, number)
			triggerClientEvent(playerSource, "showMenu", playerSource, number, 7, targetPlayer, playerNumber)
			triggerClientEvent(targetPlayer, "showSound", targetPlayer)	
			exports.s_chat:sendLocalDoAction(targetPlayer, " 's phone ringing")				
		elseif targetPlayer == "inCall" then
			outputChatBox("#D64541[Error] #ffffffThis number already in a call!", playerSource,255,255,255,true)
		else
			outputChatBox("#D64541[Error] #ffffffNumber doesn't found", playerSource,255,255,255,true)
		end
	end
end
addEvent("callTargetInServer", true)
addEventHandler("callTargetInServer", getRootElement(), callTargetInServer)

This is picks a random player in the server and calls him instead of the entered number... 



showMenu function in client side:

function showMenu(number, menuid, playerSource, actualPhoneID)
	if menuid and number then
		triggerServerEvent("getPhoneDataFromServer", localPlayer, localPlayer, actualPhoneID)
		numberCall = number
		menu = menuid
		setElementData(playerSource, "inCall", true)
		showPhone = true
		inCallMember = playerSource
		
	end
end
addEvent("showMenu", true)
addEventHandler("showMenu", getRootElement(), showMenu)

getPhoneDataFromServer function in server side:
 

function getPhoneDataFromServer(playerSource, phoneID)
	if tonumber(phoneID) then
		local checkID = dbPoll(dbQuery(connection, "SELECT * FROM phones WHERE number = ?", tonumber(phoneID)), -1)
		if (checkID) then
			for k, v in ipairs(checkID) do
				setElementData(playerSource, "musicID", v["music"])
				triggerClientEvent(playerSource, "getPhoneDataToClient", playerSource, v["wallpaper"], v["music"], v["battery"])
			end
			
		end		
	end
end
addEvent("getPhoneDataFromServer", true)
addEventHandler("getPhoneDataFromServer", getRootElement(), getPhoneDataFromServer)

 

getPhoneDataToClient in client side:

function getPhoneDataToClient(wallpaper, music, battery)
	wallPaperID = wallpaper
	musicID = music
	batteryState = battery
	loadedPhoneInterFace = true
end
addEvent("getPhoneDataToClient", true)
addEventHandler("getPhoneDataToClient", getRootElement(), getPhoneDataToClient)

 

Edited by thund3rbird23
Link to comment
  • Moderators
16 minutes ago, thund3rbird23 said:

This is picks a random player in the server and calls him instead of the entered number... 

Is the callMember function not broken then? Or is the number incorrect?

 

Debug this!

 

 

 


 

This loop makes no sense. What if there are accidentally two phones with the same number?

for k, v in ipairs(checkID) do

 

Limit the query

"SELECT * FROM phones WHERE number = ? LIMIT 1"

 

And get only the first result:

if #checkID == 1 then
	local v = checkID[1]

 

Link to comment
48 minutes ago, IIYAMA said:

Is the callMember function not broken then? Or is the number incorrect?

 

Debug this!

 

 

 


 

This loop makes no sense. What if there are accidentally two phones with the same number?


for k, v in ipairs(checkID) do

 

Limit the query


"SELECT * FROM phones WHERE number = ? LIMIT 1"

 

And get only the first result:


if #checkID == 1 then	local v = checkID[1]

 

Ok, so if I debug the number in the callMember function then it's correct because that display the number which I dialing.

But if I debug the targetPlayer in the callTargetInServer function then always shows me (Jeff) as player "elem:player[Jeff]" when I type any number. So what? I don't understand

targetPlayer = callMember(number)
iprint(targetPlayer)

--- callMember function ---

 

function callMember(number)
	for k, v in ipairs(getElementsByType("player")) do
		if v and number and exports.s_inventory:hasItem(v, 43, number) then
			if (getElementData(v, "inCall")) then
				return "inCall"
			else
				return v
			end
		end
	end
	return false
end

 

Edited by thund3rbird23
Link to comment
  • Moderators

 

Add local in front of it, it should be scoped.

local targetPlayer = callMember(number)

 


 

1 minute ago, thund3rbird23 said:

So what? I don't understand

With other words the callMember function does not work correctly.

Go debug it!  It is not an MTA function, so you will have to search for it in your files.

Link to comment
  • Moderators
31 minutes ago, thund3rbird23 said:

exports.s_inventory:hasItem(v, 43, number)

This goes wrong. It seems like Jeff has an item with the selected number.

Make sure to check the syntax of this function, the function itself and his data in the database.

 

 

Link to comment
1 hour ago, IIYAMA said:

This goes wrong. It seems like Jeff has an item with the selected number.

Make sure to check the syntax of this function, the function itself and his data in the database.

 

 

I need to check if the player have an item with itemID = 43 and with value = number but yes I think too that the syntax is wrong.

I give the phone to the players with:
 

exports.s_inventory:giveItem(playerSource, 43, 1, tonumber(phoneID))

and the hasItem function is:
 

function hasItem(sourceElement, itemId)
	if itemsTable[sourceElement] then
		for k, v in pairs(itemsTable[sourceElement]) do
			if v.itemId == itemId then
				return v
			end
		end
	end

	return false
end

So how can I check if the player have the item with the itemid 43 and with the value = number?

Link to comment
  • Moderators

 

 

 

exports.s_inventory:hasItem(v, 43, number)

function hasItem(sourceElement, itemId)

The number is not being used.

 

How does the giveItem looks like?

 

44 minutes ago, thund3rbird23 said:

So how can I check if the player have the item with the itemid 43 and with the value = number?

 

One thing that could work is:

exports.s_inventory:giveItem(playerSource, "phoneNumber-" .. tostring(tonumber(phoneID)), 1)

 

if v and number and exports.s_inventory:hasItem(v, "phoneNumber-" .. tostring(tonumber(number))) then

 

Link to comment
36 minutes ago, IIYAMA said:

 

 

 

exports.s_inventory:hasItem(v, 43, number)

function hasItem(sourceElement, itemId)

The number is not being used.

 

How does the giveItem looks like?

 

 

One thing that could work is:


exports.s_inventory:giveItem(playerSource, "phoneNumber-" .. tostring(tonumber(phoneID)), 1)

 


if v and number and exports.s_inventory:hasItem(v, "phoneNumber-" .. tostring(tonumber(number))) then

 

giveItem looks like:

 

exports.s_inventory:giveItem(playerSource, 43, 1, tonumber(phoneID))

player,itemid,amount,value

This is works, adding a phone and sets the value to the random generated number which saved in the database.

I must specify the item id after v, otherwise always says "Number doesn't found". But if I specify the item id then always rings my phone no matter what number was typed.
 

if v and number and exports.s_inventory:hasItem(v, 43, tonumber(number)) then

The debug says: "elem:player[Jeff] "234434" so my name and the number which I typed.

Maybe the error is in the callTargetInServer function? I commented that function too before.

Edited by thund3rbird23
Link to comment
  • Moderators

 

51 minutes ago, thund3rbird23 said:

Maybe the error is in the callTargetInServer function? I commented that function too before.

No. The bug is caused, because you are only storing the phonenumber. But not using it when checking if the number is matching.

 

39 minutes ago, thund3rbird23 said:

player,itemid,amount,value

Where in this code do you see that value is used?

function hasItem(sourceElement, itemId)
	if itemsTable[sourceElement] then
		for k, v in pairs(itemsTable[sourceElement]) do
			if v.itemId == itemId then
				return v
			end
		end
	end

	return false
end

I do not see it. Only matching the itemid, which is not the value.

 

 

Is there perhaps this function:

getItemValue

?

 

 

Link to comment
18 minutes ago, IIYAMA said:

 

No. The bug is caused, because you are only storing the phonenumber. But not using it when checking if the number is matching.

 

Where in this code do you see that value is used?


function hasItem(sourceElement, itemId)	if itemsTable[sourceElement] then		for k, v in pairs(itemsTable[sourceElement]) do			if v.itemId == itemId then				return v			end		end	end	return falseend

I do not see it. Only matching the itemid, which is not the value.

 

 

Is there perhaps this function:

getItemValue

?

 

 

No. Check this out:

 

function addItemEx(sourceElement, dbID, slot, itemId, amount, data1, data2, data3)
	itemsTable[sourceElement][slot] = {}
	itemsTable[sourceElement][slot].dbID = dbID
	itemsTable[sourceElement][slot].slot = slot
	itemsTable[sourceElement][slot].itemId = itemId
	itemsTable[sourceElement][slot].amount = amount
	itemsTable[sourceElement][slot].data1 = data1
	itemsTable[sourceElement][slot].data2 = data2
	itemsTable[sourceElement][slot].data3 = data3
	itemsTable[sourceElement][slot].inUse = false
	itemsTable[sourceElement][slot].locked = false
end

function giveItem(sourceElement, itemId, amount, data1, data2, data3)
	addItem(sourceElement, itemId, amount, false, data1, data2, data3)
end

function addItem(sourceElement, itemId, amount, slotId, data1, data2, data3)
	if isElement(sourceElement) and itemId and amount then
		itemId = tonumber(itemId)
		amount = tonumber(amount)

		if not itemsTable[sourceElement] then
			itemsTable[sourceElement] = {}
		end

		if not slotId then
			slotId = findEmptySlot(sourceElement, itemId)
		elseif tonumber(slotId) then
			if itemsTable[sourceElement][slotId] then
				slotId = findEmptySlot(sourceElement, itemId)
			end
		end

		if slotId then
			local ownerType = getElementType(sourceElement)
			local ownerId = getElementDatabaseId(sourceElement)

			if tonumber(ownerId) then
				itemsTable[sourceElement][slotId] = {}
				itemsTable[sourceElement][slotId].locked = true

				dbQuery(
					function (qh, sourceElement)
						if isElement(sourceElement) then
							local result = dbPoll(qh, 0, true)[2][1][1]

							if result then
								addItemEx(sourceElement, result.dbID, result.slot, result.itemId, result.amount, result.data1, result.data2, result.data3)

								triggerItemEvent(sourceElement, "addItem", getElementType(sourceElement), result)
							end
						end
					end, {sourceElement}, connection, "INSERT INTO items (itemId, slot, amount, data1, data2, data3, ownerType, ownerId) VALUES (?,?,?,?,?,?,?,?); SELECT * FROM items ORDER BY dbID DESC LIMIT 1", itemId, slotId, amount, data1, data2, data3, ownerType, ownerId
				)

				return true
			else
				return false
			end
		else
			return false
		end
	else
		return false
	end
end
addEvent("addItem", true)
addEventHandler("addItem", getRootElement(), addItem)

I mean the value is the itemstable data1. But how can I reference in the phone's code? this is in the inventory server code.

Link to comment
  • Moderators
26 minutes ago, thund3rbird23 said:

But how can I reference in the phone's code? this is in the inventory server code.

Are you telling me that there is no function for? Maybe search a little bit more?

 

 

local ownerId = tonumber(getElementDatabaseId(player))
local ownerType = getElementType(player) -- "player"


if ownerId then
  
end

 

query should look a bit like this.

SELECT data1 FROM items WHERE itemId = 43 AND ownerId = ? AND ownerType = ? LIMIT 1

 

Link to comment
5 hours ago, IIYAMA said:

Are you telling me that there is no function for? Maybe search a little bit more?

 

 


local ownerId = tonumber(getElementDatabaseId(player))local ownerType = getElementType(player) -- "player"if ownerId then  end

 

query should look a bit like this.


SELECT data1 FROM items WHERE itemId = 43 AND ownerId = ? AND ownerType = ? LIMIT 1

 

I don't know but if I debug

for k, v in ipairs(getElementsByType("player")) do
	iprint(k,v)

then only showing the first connected player's id and name not the target's id&name (who is called). Is this okay?

Link to comment
  • Moderators
4 hours ago, thund3rbird23 said:

I don't know but if I debug


for k, v in ipairs(getElementsByType("player")) do
	iprint(k,v)

then only showing the first connected player's id and name not the target's id&name (who is called). Is this okay?

This is a loop, it goes trough all items, in this case all players. And can be stopped with the keyword break or return.

 

 

 

 

What if you add another export function, for the call :

(The only strange thing about it is that in the orginal code the slot id is not being used. Could itemsTable be a meta table?)

function hasItemAndData1(sourceElement, itemId, data1)
	if itemsTable[sourceElement] then
		for k, v in pairs(itemsTable[sourceElement]) do
			if v.itemId == itemId and v.data1 == data1 then
				return v
			end
		end
	end

	return false
end

 

  • Thanks 1
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...