Results 1 to 6 of 6

Thread: Avoiding reference to the table and the nudge tool when using onCollisionEnter/Exit

  1. #1

    Avoiding reference to the table and the nudge tool when using onCollisionEnter/Exit

    I have a scripted character sheet. I want to make it dump its stats into another object's description when a button is pressed. Ideally, this other object does not have to be scripted.

    So far I got this working fine. I made a button called dump stats, and it something.setDescription(mystats) to something that touches it.

    I would like to make this button disappear when it's not colliding with something though.
    Problem one, it's always colliding with the table. Okay, so I just make it ignore the table. Now how do I reference the table? As far as I can tell it's a userdata type and short of saving it to a variable beforehand, I have no idea how to create a reference for this type. I think perhaps I can create a whitelist of objects it is allowed to interact with through storing their userdata in variables. But as far as I can tell, the only way to really reference somethings userdata is through the onCollision functions. So to populate this whitelist seems like using a lot of onSave() workarounds. Am I missing something here?

    Problem two, any kind of bouncing completely breaks the button removal script. The table and nudge tool especially likes breaking it. It just gets stuck and completely ceases to function. The script, kindly provided by MrStump:
    Code:
    function findButtonIndex(clickFunction) --used for finding the index of a button based on its click function, great for removing buttons
        allMyButtons = self.getButtons()
        foundIndex = ""
        for ind,val in pairs(allMyButtons) do
            if val.click_function == clickFunction then
                foundIndex = val.index
            end
        end
        return foundIndex
    end
    I want to say this is a problem with onCollisionExit(), but clearButtons() seems to work just fine without issues at all. I'd like not to clear and recreate all my buttons just to remove one though, that makes the game stutter. I really hate the removeButton() function, it's never really worked well for me, even the script above doesn't work well for me.

  2. #2
    Join Date
    May 2016
    Posts
    1,072
    Problem 1) Easiest way might be to get the "name" of the table. When you get the object from onCollision, do a setNotes(object). If the table is like other objects, it will have some name that will print there. Copy and paste it. Once you have the name, delete the setNotes part. And make a condition:

    Code:
    if tostring(object) != "The name you got from the object hitting the table" then
        --Insert code
    end
    Problem 2) Rather than having each contact trigger the function, you can use timer or variables to prevent the code from running too often. Here is psudocode to show you the idea behind my 2 potential solutions.

    Timer solution. Each time the code would trigger, it starts a timer. If it is activated again prior to the timer running out and activating the next bit of code, it will stop the timer and restart it.

    Code:
    --Place this where your code was triggering in onCollision. Move that code into function nameOfFunctionRunAfterTimerEnds()
    Timer.destroy(self.getGUID())
    local timerParams = {
        identifier='uniqueNameWhichIsntRepeatedAnywhereOrYouGetErrors",
        function_name='nameOfFunctionRunAfterTimerEnds',
        function_owner=self, delay=2
    }
    Timer.create(timerParams)
    Variable solution. You make a variable that prevents code from being run multiple times. Variable will disable that code until you re-enable it elsewhere in the code.

    Code:
    function onload()
        someVariable = false
    end
    
    function onCollision(etc etc)
        if someVariable == false then
            --The code you want triggered here to remove buttons
            someVariable = true
    end
    
    --Then you set someVariable back to false somewhere else in the code
    Sorry I don't have a lot of better insight into managing indexes for adding/removing buttons. There are some cheaper (process wise) ways to go about it. Say you spawned 20 edit buttons and wanted to remove them all. Using #object.getButtons() you can get how many total buttons you have (say, 40 total). You can then run a for loop like: for i=20, 40 do self.removeButton(i) end. But doing it this way requires you to write your code in a specific way to capitalize on the method.

  3. #3
    Quote Originally Posted by MrStump View Post
    Code:
    if tostring(object)
    This was the bit I was missing. I had no idea how to reference userdata... so just make it into a not-userdata and reference that!

    The timer thing didn't really work at all. It'd throw many errors stating "An element with the same key already exists in the dictionary". I did make sure the identifier was unique.

    The variable method (#2) you mentioned worked for the table part. For whatever reason, anything colliding with the table collides 4 times, and making the script adopt a more enter-exit-enter-exit structure rather than a enter-enter-exit-exit helped tremendously. So tremendously, that the solution reaches completely out of its scope and will inadvertently fix some other broken thing I had. Unfortunately, it didn't fix the bouncing issue at all, but the structure above provides a workaround. The more I experiment with it, the more I think that it might be a clipping issue and a limitation of onCollisionExit(), in that it's simply not called at all if the object collides briefly enough. I just increased air resistance so the object doesn't hit things so violently and the problem kinda resolved itself.

    Thanks again for the help.

  4. #4
    Join Date
    May 2016
    Posts
    1,072
    Sorry, I messed up my psudo-code. Timer.destroy(self.getGUID()) should be Timer.destroy("that unique timer name")

    The delete prevents multiples of the same name existing. Sorry about that. I had, before (where I first wrote that code) used the item's GUID as a unique name. So I changed it in 1 place but not the other. It may still throw errors. Timers are finicky in my experience, I try not to use them but they are SO useful

    And glad to help

  5. #5
    Join Date
    May 2016
    Posts
    1,072
    Also I thought of another good button workaround if you need it. Rather than removing buttons, you create every button at once, so you know all of their indexes. Place the buttons you don't want showing up on the Y axis by 50 or so. Then when you need them, set their Y back to normal.

    Should be cheap and reliable.

  6. #6
    Quote Originally Posted by MrStump View Post
    Also I thought of another good button workaround if you need it. Rather than removing buttons, you create every button at once, so you know all of their indexes. Place the buttons you don't want showing up on the Y axis by 50 or so. Then when you need them, set their Y back to normal.

    Should be cheap and reliable.
    Yep, I've considered this as well. Except I used 9000, not 50.

    However I sat down and spent a good three hours looking through the button removal script you gave me and wrapping my head around for loops. The issue was that buttons aren't created or destroyed on the frame that you ask them to be. It's on the frame after. This can mislead scripts into thinking buttons are or are not there, when actually they will be created or destroyed immediately following that check.

    I found a fix. Basically I take the script above and replace the 'return index part' with a 'nuke button' part.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •