Jump to content

boneAttach gets Invisible on entering another interior/dimension


Zuher Laith

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 .

Link to comment
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 ?
 

Link to comment
  • Moderators

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 ) 

 

Link to comment

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.

Link to comment
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

 

Link to comment
  • Moderators

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
Link to comment

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
Link to comment
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 ?

Link to comment
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 ..

Link to comment

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

Link to comment
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

 

Link to comment
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 )

 

Link to comment

@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
Link to comment
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 .

Link to comment
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
Link to comment
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
Link to comment
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 ..

Link to comment

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 )

 

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...