Mini-Me Posted January 29, 2012 Share Posted January 29, 2012 Hi fellow scripters, basing on the dimension a player is in I want to use the in MTA 1.3 new functions removeWorldModel and restoreWorldModel, and automatically do that when an other resource changes the player's dimension. Is there an event that gets triggered when a player(/element) changes the dimension? I tried the following code, but if I get it right then that only works with custom data attributes (those ones that are not posX, dimension, etc., for example added with "setElementData ( thePlayer, "tempdata.originalnick", sPlayerNickname )") and it doesn't work: addEventHandler ( "onClientElementDataChange", getRootElement(), function ( dataName, oldValue ) if getElementType ( source ) == "player" and dataName == "dimension" then outputChatBox ( getPlayerName(source).."'s new dimension is "..getElementData (source, "dimension").." and was " .. oldValue .. "!" ) end end ) Is there an other easy way or will I have to write me a loop that constantly check's an element's dimension to then trigger a custom event? Thanks for your answers already, Mini-Me Link to comment
Kenix Posted January 29, 2012 Share Posted January 29, 2012 (edited) This? Client If you use element data.But idk why you need use element data instead of setElementInterior. addEvent( "onClientPlayerChangeDimension",true ) addEventHandler( "onClientPlayerChangeDimension",root, function( new,old ) outputChatBox ( getPlayerName( source ).."'s new dimension is "..tostring( new ).." and was " ..tostring( old ).. "!" ) end ) addEventHandler ( "onClientElementDataChange", root, function ( dataName, oldValue ) if getElementType ( source ) == "player" and dataName == "dimension" then triggerEvent( "onClientPlayerChangeDimension",source,getElementData ( source, "dimension" ),oldValue ) end end ) Edited January 29, 2012 by Guest Link to comment
BinSlayer1 Posted January 29, 2012 Share Posted January 29, 2012 Dimension change event. Put this script in the resource(s) that handle dimension changes: _setElementDimension = setElementDimension function setElementDimension(player, dimension) local bool = _setElementDimension(player, dimension) if bool then --this is used to check if the function actually worked before launching our custom event triggerEvent('onPlayerDimensionChange', player, dimension) end end addEvent('onPlayerDimensionChange', true) addEventHandler('onPlayerDimensionChange', root, function(dimension) outputChatBox(getPlayerName(source).. "'s dimension was changed to: "..dimension) end ) serverside ^ Link to comment
Mini-Me Posted January 29, 2012 Author Share Posted January 29, 2012 @Kenix: That wont work. Like I said, when the "dimension" attribute of an element changes, the event "onClientElementDataChange" is NOT triggered. @BinSlayer1: I guess that's my only option then (apart from the loop I mentioned above). I actually wanted to keep resources separate so that if I were to use a foreign resource I don't have to keep changing the scripts when I download an update, but in this special case the other resource is actually mine as well. Oh, and thank you for the quick answers. Link to comment
Kenix Posted January 29, 2012 Share Posted January 29, 2012 This should work Show full code. And use /debugscript 3. Link to comment
DiSaMe Posted January 29, 2012 Share Posted January 29, 2012 This should workShow full code. And use /debugscript 3. I guess you also forgot "make sure your computer is running", as event won't be triggered if computer is turned off... Link to comment
BinSlayer1 Posted January 29, 2012 Share Posted January 29, 2012 @Kenix:That wont work. Like I said, when the "dimension" attribute of an element changes, the event "onClientElementDataChange" is NOT triggered. @BinSlayer1: I guess that's my only option then (apart from the loop I mentioned above). I actually wanted to keep resources separate so that if I were to use a foreign resource I don't have to keep changing the scripts when I download an update, but in this special case the other resource is actually mine as well. Oh, and thank you for the quick answers. If you REALLY REALLY don't wanna put that code in all resources.. then put it in 1 resource and export setElementDimension and use it like this exports.nameOfResource:setElementDimension(player, 0) Link to comment
Mini-Me Posted January 29, 2012 Author Share Posted January 29, 2012 @Kenix: For a test I created a new resource. It only contains your code, plus this: addCommandHandler("dimension", function(commandName, arg1) arg1 = tonumber(arg1) if (arg1 ~= nil) then setElementDimension(getLocalPlayer(), arg1) else outputChatBox("You need to provide a number as argument!") end end) If I now ingame use the command, my dimension is changed, however I do not get the message from your event handler. Also, there is no error output (that would show up with /debugscript 3). @BinSlayer1: That's not the point, it is that I wouldn't want to change the resource at all. Imagine I download a resource from the webpage here. I'd have to edit it each time when there is an update to it. But as there is no other way really, I'll have to use it. Link to comment
arezu Posted January 29, 2012 Share Posted January 29, 2012 why dont you use a "loop" then? easiest way to detect, isn't it? -- or 1 in case it fails, but probably wont happen local dim = getElementDimension(getLocalPlayer()) or 1 addEvent("onClientPlayerDimensionChange", true) addEventHandler("onClientPlayerDimensionChange", getRootElement(), function(dimension) outputChatBox("Dimension changed to: "..dimension) end) addEventHandler("onClientRender", getRootElement(), function() local _dim = getElementDimension(getLocalPlayer()) if(_dim ~= dim)then dim = _dim triggerEvent("onClientPlayerDimensionChange", getLocalPlayer(), _dim) end end) Link to comment
BinSlayer1 Posted January 29, 2012 Share Posted January 29, 2012 @BinSlayer1: That's not the point, it is that I wouldn't want to change the resource at all. Imagine I download a resource from the webpage here. I'd have to edit it each time when there is an update to it. But as there is no other way really, I'll have to use it. Sorry but you just sound pretty lazy Let's face it, there aren't many resources out there that will use a setElementDimension function.. There's probably the admin panel and a couple more. And it's not like they get updated on daily basis, but on monthly/yearly basis really.. Link to comment
DiSaMe Posted January 29, 2012 Share Posted January 29, 2012 (edited) You can also keep checking player's dimension in some timer function and trigger the event when it changes. An example: old_dimension = {} --make an array to store previous dimensions of players addEvent("onPlayerDimensionChange", true) function checkDimensions() local this_dimension = {} --current dimensions of players local players = getElementsByType("player") for _, player in ipairs(players) do --cycle through all players this_dimension[player] = getElementDimension(player) if this_dimension[player] ~= old_dimension[player] then --if dimension is different than it was triggerEvent("onPlayerDimensionChange", player, old_dimension[player], this_dimension[player]) end end old_dimension = this_dimension --store this_dimension for the next check end setTimer(checkDimensions, 1000, 0) And then you can do: function showDimensionChange(olddim, newdim) outputChatBox(getPlayerName(source).." went from dimension "..olddim.." to dimension "..newdim..".") end addEventHandler("onPlayerDimensionChange", root, showDimensionChange) Not tested, but it should work. You can make put this code into a new resource. However, you will need to improve it because I only showed you how it should work. For example, if the player who just joined is checked, old_dimension[player] will be nil, therefore different than current dimension, so the event will be triggered. Also, the event isn't triggered instantly, but when dimensions are checked. Edited January 29, 2012 by Guest Link to comment
Castillo Posted January 29, 2012 Share Posted January 29, 2012 old_dimension = {} --make an array to store previous dimensions of players addEvent("onPlayerDimensionChange", true) function checkDimensions() local this_dimension = {} --current dimensions of players local players = getElementsByType("player") for _, player in ipairs(players) do --cycle through all players this_dimension[player] = getElementDimension(player) if this_dimension[player] ~= old_dimension[player] then --if dimension is different than it was triggerEvent("onPlayerDimensionChange", player, old_dimension[player], this_dimension[player]) end end old_dimension = this_dimension --store this_dimension for the next check end setTimer(checkDimensions, 1000, 0) You put getElementPosition instead of getElementDimension at line 7. Link to comment
Mini-Me Posted January 29, 2012 Author Share Posted January 29, 2012 @BinSlayer1: So the software quality characteristic maintainability is just based on laziness? @arezu and CrystalMV: Thinking about it again that is actually the better idea, since I also change the palyer's dimension in a second script. I suggested that in my first post to point out that I could've written that myself, but thanks though. Link to comment
Kenix Posted January 29, 2012 Share Posted January 29, 2012 @Kenix:For a test I created a new resource. It only contains your code, plus this: addCommandHandler("dimension", function(commandName, arg1) arg1 = tonumber(arg1) if (arg1 ~= nil) then setElementDimension(getLocalPlayer(), arg1) else outputChatBox("You need to provide a number as argument!") end end) If I now ingame use the command, my dimension is changed, however I do not get the message from your event handler. Also, there is no error output (that would show up with /debugscript 3). If you use element data.But idk why you need use element data instead of setElementInterior. addEvent( "onClientPlayerChangeDimension",true ) addEventHandler( "onClientPlayerChangeDimension",root, function( new,old ) outputChatBox ( getPlayerName( source ).."'s new dimension is "..tostring( new ).." and was " ..tostring( old ).. "!" ) end ) addEventHandler ( "onClientElementDataChange", root, function ( dataName, oldValue ) if getElementType ( source ) == "player" and dataName == "dimension" then triggerEvent( "onClientPlayerChangeDimension",source,getElementData ( source, "dimension" ),oldValue ) end end ) Link to comment
AGENT_STEELMEAT Posted January 30, 2012 Share Posted January 30, 2012 This implements a clientside onClientElementDimensionChange event, which triggers whenever the local player's dimension changes. The source of the event is the local player, and it passes two arguments: the current dimension and the last dimension. You could extend this by adding using triggerServerEvent, or even by looping through all streamed in elements and checking their status if isElementSyncer() returns true. That's a bit complicated however. addEvent("onClientElementDimensionChange", true) local lastDimension = getElementDimension(localPlayer) local function processDimensionChanges() local currentDimension = getElementDimension(localPlayer) if currentDimension ~= lastDimension then lastDimension = currentDimension triggerEvent("onClientElementDimensionChange", localPlayer, currentDimension, lastDimension) end end addEventHandler("onClientRender", root, processDimensionChanges) -- Example usage: local function outputDimensionChange(currentDimension, lastDimension) outputChatBox("You have traveled from the "..lastDimension.." to the "..currentDimension.."!", 0, 255, 0) end addEventHandler("onClientElementDimensionChange", localPlayer, outputDimensionChange) Link to comment
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now