Zuher Laith

boneAttach gets Invisible on entering another interior/dimension

Recommended Posts

Hi everyone,

So recently I have been working on some scripting with the famous bone_attach script
and I've noticed something important, when I attach object to the client and the client teleports to another interior/dimension, the objects gets invisible
but when I go back to the 0 dimension&interior, It gets visible !
plus, even If I created and attached the object in dimension/interior other than 0, its Invisible, I teleport to 0 it gets visible .

In this case, how should I make the object that attached to the client visible when he goes to another dimension & interior ?
Any help is appreciated .

Share this post


Link to post

You could try:

setElementParent(object, player)

 

Not sure if it works, because I haven't tested it with dimension change before.

 

Share this post


Link to post
9 minutes ago, IIYAMA said:

You could try:


setElementParent(object, player)

 

Not sure if it works, because I haven't tested it with dimension change before.

unfortunately, it didn't work on dimension change ..

function attachToPedHandler ()   
	PepsiCan = createObject(1487,0,0,0)
	exports.bone_attach:attachElementToBone(PepsiCan, client, 12,0,0,0,0,-130,20)
	setElementParent(PepsiCan, client)
end

but I thought about using SetElementDimension & SetElementInterior , but how do I check for dimension/interior player change ?
 

Share this post


Link to post

There is no event for that.

What you need to do is either find the player where the dimension/interior changes. Or use a timer to detect if it has changed.

 

The attached elements can be retrieved like this: (if setElementParent is used)

local attachedObjects = getElementChildren ( player, "object") 

-- this one might work as well, not tested.
local attachedObjects = getElementsByType ("object", player ) 

 

Share this post


Link to post

You could also make it an event yourself:
 

local DIM_REFRESH_FREQ = 1000
addEvent("onClientDimensionChange")

local lastDimension = getElementDimension( localPlayer )
function CheckPlayerDimension()
	local curDim = getElementDimension( localPlayer )
	if curDim ~= lastDimension then
		triggerEvent( "onClientDimensionChange", localPlayer, lastDimension, curDim)
		lastDimension = curDim
	end
end
setTimer( CheckPlayerDimension, DIM_REFRESH_FREQ, 0 )

it does check if player dimension changed every second, and if it happened it triggers event, it passes last dimension and new one as event arguments.

Share this post


Link to post
24 minutes ago, IIYAMA said:

There is no event for that.

What you need to do is either find the player where the dimension/interior changes. Or use a timer to detect if it has changed.

 

The attached elements can be retrieved like this: (if setElementParent is used)


local attachedObjects = getElementChildren ( player, "object") 

-- this one might work as well, not tested.
local attachedObjects = getElementsByType ("object", player ) 

 

well, this was the result and it worked without a timer :

function attachPepsiHandler ()   
	PepsiCan = createObject(1487,0,0,0)
	setElementParent(PepsiCan, client)
	exports.bone_attach:attachElementToBone(PepsiCan, client, 12,0,0,0,0,-130,20)
	
	-- the code works like this (with uncomment):
	--setTimer(function()
	--local attachedObjects = getElementChildren ( client, PepsiCan) -- problem here
    if not ( getElementDimension ( client ) == 0 ) then -- And here
		--if attachedObjects then
			playerdim = getElementDimension ( client )
			setElementDimension ( PepsiCan, playerdim )
		--end
	end
	--end, 1000, 0)

	-- if I uncomment them, here are the errors:
	[15:22:59] WARNING: vend\server.lua:22: Bad argument @ 'getElementChildren'
	[Expected element at argument 1, got nil]  [DUP x4]
	[15:22:59] WARNING: vend\server.lua:23: Bad argument @ 'getElementDimension
 	[Expected element at argument 1, got nil]  [DUP x4]
end

 

Share this post


Link to post

It looks like you are trying to use the predefined variable `client` within a function that is not called by an addEventHandler.

Also you can't fill in PepsiCan as second argument, only an elementType in the form of a string is acceptable. So use the type "object", because that is what PepsiCan is.

Edited by IIYAMA

Share this post


Link to post

why don not you edit attach's resources? You can add setElementDimension/Interior in the render event.

  • Like 1

Share this post


Link to post

There is now many different replays and ideas in the topic, lets make them one.

I've created a function in the bone_attach (idea by Enargy,)
and used isElementAttachedToBone to check if object is destroyed later instead of attachedObjects

Spoiler

-- Server side:
function attachPepsiHandler ( thePlayer )   
	PepsiCan = createObject(1487,0,0,0)
	exports.bone_attach:attachElementToBone(PepsiCan, thePlayer, 12,0,0,0,0,-130,20)

	-- this point here, it takes a second to attach the element to player in a dimension other than 0
	playerdim = getElementDimension ( thePlayer )
	playerint = getElementInterior ( thePlayer )
	exports.bone_attach:setElementDimInt(PepsiCan, thePlayer, playerdim, playerint)
	-- so I wrote this to attach it instantly

	setTimer(function()
	if exports.bone_attach:isElementAttachedToBone(PepsiCan) then
		playerdim = getElementDimension ( thePlayer )
		playerint = getElementInterior ( thePlayer )
		exports.bone_attach:setElementDimInt(PepsiCan, thePlayer, playerdim, playerint)
	else return end
	end, 1000, 0)
end
addEvent( "AttachPepsi", true )
addEventHandler( "AttachPepsi", resourceRoot, attachPepsiHandler )

and the attach_func.lua in bone_attach resource:


function setElementDimInt(element,ped,dim,int)
	if not (isElement(element) and isElement(ped)) then return false end
	if not dim then return false end
	if not int then return false end
	if getElementType(ped) ~= "ped" and getElementType(ped) ~= "player" then return false end
	dim,int = tonumber(dim) or 0,tonumber(int) or 0
	setElementDimension(element, dim)
	setElementInterior(element, int)
	return true
end

 


Everything works as suppose to be,
but I'm afraid of timers, is this going to be a cause of server usage if I change the timer interval to "100" ? .. because this is on server side .

Edited by Zuher Laith

Share this post


Link to post
4 hours ago, quindo said:

it does check if player dimension changed every second, and if it happened it triggers event, it passes last dimension and new one as event arguments.

let me be honest with you,
it became confusing to me since I have a problem with understanding events, client, server ..

As I saw your code, I thought this is a client and I didn't understand how should I correctly use it .
would you please explain to me how can I change the element dimension based on the code you provide on server side ?

Share this post


Link to post

Ah, my code is client sided, and it only detects if local player changed dimension, if you need something that can update each player server sided i don't think something like that would be a good choice.

Share this post


Link to post
3 minutes ago, quindo said:

Ah, my code is client sided, and it only detects if local player changed dimension, if you need something that can update each player server sided i don't think something like that would be a good choice.

Didn't expect that, but anyways I appreciate your help ..

Share this post


Link to post

Actually, can you check if it works?
 

local DIM_REFRESH_FREQ = 1000
addEvent("onPlayerDimIntChange")

local lastDimIntTable = {}
function CheckPlayerDimension()
	local players = getElementsByType("player", root)
	for _,player in ipairs(players) do
		local curDim = getElementDimension( player )
		local curInt = getElementInterior( player )
		if not lastDimIntTable[player] then lastDimIntTable[player] = {dim = curDim, int = curInt}
		if (curDim ~= lastDimIntTable[player].dim) or (curInt ~= lastDimIntTable[player].int) then
			triggerEvent( "onPlayerDimIntChange", player, lastDimensionPlayer[player].int, lastDimensionPlayer[player].dim, curInt, curDim)
			lastDimensionTable[player].dim = curDim
			lastDimensionTable[player].int = curInt
		end
end
setTimer( CheckPlayerDimension, DIM_REFRESH_FREQ, 0 )

function updatePlayerAttachedElements(lastInt, lastDim, curInt, curDim)
	local attachedObjects = getElementChildren ( source, "object")
	for _,elem in pairs(attachedObjects)
		setElementDimension( elem, curDim )
		setElementInterior( elem, curInt )
	end
end
addEventHandler( "onPlayerDimIntChange", root, updatePlayerAttachedElements )


function AttachElementToBone(element, player, ...)
	if isElement(element) and isElement(player) then
		setElementParent(element, player)
	end
	return exports.bone_attach:attachElementToBone(element, player, ...)
end

It's not optimised at all, but it should automatically detect if player has changed dimension or interior, and update attached elements too.
use AttachElementToBone function instead of exports.bone_attach:attachElementToBone
I haven't tested it, so if there are any errors post it here

Share this post


Link to post
32 minutes ago, quindo said:

Actually, can you check if it works?

I got one error here:

function updatePlayerAttachedElements(lastInt, lastDim, curInt, curDim)
	local attachedObjects = getElementChildren ( source, "object")
	for _,elem in pairs(attachedObjects)
		setElementDimension( elem, curDim ) -- here
		setElementInterior( elem, curInt )
	end
end
addEventHandler( "onPlayerDimIntChange", root, updatePlayerAttachedElements )

-- errors:
[21:21:15] ERROR: Loading script failed: vend\server.lua:52: 'do' expected n
ear 'setElementDimension'
[21:21:24] ERROR: Client (NiGht) triggered serverside event AttachPepsi, but eve
nt is not added serverside
[21:21:24] ERROR: Client (NiGht) triggered serverside event takeCash, but event

 

Share this post


Link to post
function updatePlayerAttachedElements(lastInt, lastDim, curInt, curDim)
	local attachedObjects = getElementChildren ( source, "object")
	for _,elem in pairs(attachedObjects) do
		setElementDimension( elem, curDim )
		setElementInterior( elem, curInt )
	end
end
addEventHandler( "onPlayerDimIntChange", root, updatePlayerAttachedElements )

 

Share this post


Link to post

@quindo
I feel so stupid after that small edit... I didn't notice ..

After testing it gives no errors at start and no specific error line at debugscript 3 .
but basically the code you provided made the whole server.lua like it doesn't exist and each event called from client gives the following error:

Quote

[21:51:06] ERROR: Client (NiGht) triggered serverside event AttachPepsi, but event is not added serverside
[21:51:06] ERROR: Client (NiGht) triggered serverside event takeCash, but eventis not added serverside
[21:51:08] ERROR: Client (NiGht) triggered serverside event OnDrink, but event is not added serverside
and more ...

 

Edited by Zuher Laith

Share this post


Link to post

Where are those events defined? I mean the AttachPepsi, takeCash, OnDrink ones?

Edited by quindo

Share this post


Link to post
3 minutes ago, quindo said:

Where are those event's defined? I mean the AttachPepsi, takeCash, OnDrink ones?

-- server side:
function takeCashHandler ( thePlayer, amount ) 
     takePlayerMoney ( thePlayer, tonumber(amount) )
end
addEvent( "takeCash", true )
addEventHandler( "takeCash", resourceRoot, takeCashHandler )

-- client side:
triggerServerEvent ( "takeCash", resourceRoot, localPlayer, 3 )

same for the rest of those events .

Share this post


Link to post

Aren't there any other errors from the script i gave you? It seems that rest of the script fails to load.

Share this post


Link to post
16 minutes ago, quindo said:

Aren't there any other errors from the script i gave you? It seems that rest of the script fails to load.

I think you forgot a lot of end if here..
 

Spoiler

local DIM_REFRESH_FREQ = 1000
addEvent("onPlayerDimIntChange")

local lastDimIntTable = {}
function CheckPlayerDimension()
	local players = getElementsByType("player", root)
	for _,player in ipairs(players) do
		outputDebugString ( "We passed Check #1", 3)
		local curDim = getElementDimension( player )
		local curInt = getElementInterior( player )
		if not lastDimIntTable[player] then lastDimIntTable[player] = {dim = curDim, int = curInt}
		if (curDim ~= lastDimIntTable[player].dim) or (curInt ~= lastDimIntTable[player].int) then
			outputDebugString ( "We passed Check #2", 3)
			triggerEvent( "onPlayerDimIntChange", player, lastDimensionPlayer[player].int, lastDimensionPlayer[player].dim, curInt, curDim) -- error here
			lastDimensionTable[player].dim = curDim
			lastDimensionTable[player].int = curInt
		end
		end
	end
end
setTimer( CheckPlayerDimension, DIM_REFRESH_FREQ, 0 )

---- Log : ----
[22:34:18] INFO: We passed Check #1  [DUP x5]
[22:34:18] INFO: We passed Check #2  [DUP x5]
[22:34:18] ERROR: vend\server.lua:44: attempt to index global 'lastDimensionPlayer' (a nil value)  [DUP x5]

 

Alright,
everything works fine, but it doesn't change element dim/int on player change dim/int ,
and there is one error I found, you may want to look at the code ..

Edited by Zuher Laith

Share this post


Link to post
local DIM_REFRESH_FREQ = 1000
addEvent("onPlayerDimIntChange")

local lastDimIntTable = {}
function CheckPlayerDimension()
	local players = getElementsByType("player", root)
	for _,player in ipairs(players) do
		outputDebugString ( "We passed Check #1", 3)
		local curDim = getElementDimension( player )
		local curInt = getElementInterior( player )
		if not lastDimIntTable[player] then lastDimIntTable[player] = {dim = curDim, int = curInt} end
		if (curDim ~= lastDimIntTable[player].dim) or (curInt ~= lastDimIntTable[player].int) then
			outputDebugString ( "We passed Check #2", 3)
			triggerEvent( "onPlayerDimIntChange", player, lastDimIntTable[player].int, lastDimIntTable[player].dim, curInt, curDim) -- error here
			lastDimensionTable[player].dim = curDim
			lastDimensionTable[player].int = curInt
		end
	end
end
setTimer( CheckPlayerDimension, DIM_REFRESH_FREQ, 0 )

 

Edited by quindo

Share this post


Link to post
4 minutes ago, quindo said:

local DIM_REFRESH_FREQ = 1000
addEvent("onPlayerDimIntChange")

local lastDimIntTable = {}
function CheckPlayerDimension()
	local players = getElementsByType("player", root)
	for _,player in ipairs(players) do
		outputDebugString ( "We passed Check #1", 3)
		local curDim = getElementDimension( player )
		local curInt = getElementInterior( player )
		if not lastDimIntTable[player] then lastDimIntTable[player] = {dim = curDim, int = curInt} end
		if (curDim ~= lastDimIntTable[player].dim) or (curInt ~= lastDimIntTable[player].int) then
			outputDebugString ( "We passed Check #2", 3)
			triggerEvent( "onPlayerDimIntChange", player, lastDimIntTable[player].int, lastDimIntTable[player].dim, curInt, curDim) -- error here
			lastDimensionTable[player].dim = curDim
			lastDimensionTable[player].int = curInt
		end
	end
end
setTimer( CheckPlayerDimension, DIM_REFRESH_FREQ, 0 )

 

triggerEvent( "onPlayerDimIntChange", player, lastDimIntTable[player].int, lastDimIntTable[player].dim, curInt, curDim)
lastDimensionTable[player].dim = curDim
lastDimensionTable[player].int = curInt

-- edit:
lastDimIntTable[player].dim = curDim
lastDimIntTable[player].int = curInt

Well, now no error given & no result on changing dim/int ..

Share this post


Link to post

How are you attaching the Element now? using the orignial export function, or by the one i wrote earlier?

Share this post


Link to post
1 minute ago, quindo said:

How are you attaching the Element now? using the orignial export function, or by the one i wrote earlier?

the one you recommended,

PepsiCan = createObject(1487,0,0,0)
AttachElementToBone(PepsiCan, thePlayer, 12,0,0,0,0,-130,20) -- it works fine .

 

Share this post


Link to post

Looks like it fails to refresh, maybe something wrong with event triggering, can you check what shows in debugscript when you change this:
 

function updatePlayerAttachedElements(lastInt, lastDim, curInt, curDim)
	outputDebugString ( "Sanity check: "..tostring(source).." - "..tostring(lastInt).." - "..tostring(lastDim).." - "..tostring(curInt).." - "..tostring(curDim) )
	local attachedObjects = getElementChildren ( source, "object")
	outputDebugString( "Number of attached objects: "..tostring(#attachedObjects) )
	for _,elem in pairs(attachedObjects) do
		setElementDimension( elem, curDim )
		setElementInterior( elem, curInt )
	end
end
addEventHandler( "onPlayerDimIntChange", root, updatePlayerAttachedElements )

 

Share this post


Link to post

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.