#sandngrit onObjectEnterScriptingZone delay

1 messages · Page 1 of 1 (latest)

sour bane
#

just posting this again:

#

run a script when each card enters a zone that modifies their description

after 1 second has passed with no cards being added

run a script that check the outcome on those cards that were added

exotic mortar
sour bane
#

so now we need to add a delay timer, now there's many ways of doing this, and it'll require a bit of a leap from you, but this is how i'd do it

exotic mortar
#

I’m ready.. brew made, glasses on 😂

sour bane
#
delayIDs = {}
function setDelay(delayName, functionToCall, delaySeconds)
  if delayIDs[delayName] then -- if a delay timer with this name (key in table delayIDs) is already running then
    Wait.stop(onObjectEnterScriptingZoneDelayID) -- stop the delay timer
  end
  delayIDs[delayName] = Wait.time( -- get a new wait ID for the following Wait.time function
    functionToCall, -- function to call when the timer runs out. note i have left out the (), as it wants a function _NOT_ a function call
    delaySeconds, -- how many seconds to wait for
  )
end
#

alright so this is a function I just wrote to make the whole process easier for you

#

it uses Wait.time() and Wait.stop() to start and stop a timer

#

after that timer runs out, it then calls a function

#

so put this somewhere in your script in the global scope

#

(that means not inside of another function)

#

to use it in your script you'd do something like this:

setDelay("My Timer Name", myTimerFinished, 1)
exotic mortar
#

So it runs like a callback function ?

sour bane
#

that's a good analogy, even if it is not quite the same thing

#

the important part about the function is you can call it three times, and as long as the delayName is the same, it'll reset the timer each time, and then only call the end function once.

#

so

function myTimerFinished()
  print("my timer is finished!")
end
setDelay("My Timer Name", myTimerFinished, 1)
setDelay("My Timer Name", myTimerFinished, 5)
setDelay("My Timer Name", myTimerFinished, 2)
-- after 2 seconds prints "my timer is finished!" only once
#

now you'll be using this in your script to call a function after I dunno, 0.5 seconds.

exotic mortar
sour bane
#

now you dont actually want the myTimerFinished() function but we'll be writing that in a bit

#

just get it to print something out once and then we can go from there

#

if you get stuck, post your entire code

exotic mortar
exotic mortar
#

I wrote this in the scripting zone under the new onObjectEnter ..

I think from what you said I should have written it in global?

Also I think from what you’ve said it’s not complete yet, but was hesitant to add more as you said we’d be writing more after this, didn’t want to make a mess

#
function onObjectEnterScriptingZone(zone, enter_object)
  if zone == self then
    name = tonumber(enter_object.getName())
    description = tonumber(enter_object.getDescription())
    if 0 == name - description then
      enter_object.setDescription(description + 4)
    end
  end
end

delayIDs = {"cardsEntering", "cardsEntered"}

function setDelay(delayName, functionToCall, delaySeconds)
  if delayIDs[cardsEntering] then

    wait.stop("cardsEntered")
  end
delayIDs[cardsEntered] = Wait.time(function functionToCall, 20)

#

I did add the names “cardsEntering” and “cardsEntered” as I thought it showed my understanding of that part of the code

sour bane
#

that wasn't what I expected, but I can see why you've interpreted it as that

#

ending up with this:

function onObjectEnterScriptingZone(zone, enter_object)
  if zone == self then
    name = tonumber(enter_object.getName())
    description = tonumber(enter_object.getDescription())
    if 0 == name - description then
      enter_object.setDescription(description + 4)
    end
    -- we've done the description part, now we need to set the timer
    -- this is where you'll adapt my example to start a timer

    -- this was my example:
    setDelay("My Timer Name", myTimerFinished, 1)
  end
end

-- below just copy pasted from my above
delayIDs = {} -- yes, this should be empty
function setDelay(delayName, functionToCall, delaySeconds)
  if delayIDs[delayName] then -- if a delay timer with this name (key in table delayIDs) is already running then
    Wait.stop(delayIDs[delayName]) -- stop the delay timer
  end
  delayIDs[delayName] = Wait.time( -- get a new wait ID for the following Wait.time function
    functionToCall, -- function to call when the timer runs out. note i have left out the (), as it wants a function _NOT_ a function call
    delaySeconds -- how many seconds to wait for
  )
end

-- also from my example above:
function myTimerFinished()
  print("my timer is finished!")
end
#

I added a few extra comments to make it clearer

#

bear in mind that all these functions are defined in the "global" scope, the order they are defined in does not matter, except for your ease of reading

exotic mortar
#

Ok I’ve copied and pasted, I get the error “<expression> expected near ‘)’”

sour bane
#

this is why I should test my code before posting

#

ah I bet its the last comma

#

yup, just remove it, after delaySeconds

#

there was another error in there too so copy the code again

exotic mortar
#

Ok done 👍

sour bane
#

so you should get "my timer is finished" printing just once, even if you throw more than one card into the zone

#

which means we've now done step 2 of my three step breakdown:

run a script when each card enters a zone that modifies their description

after 1 second has passed with no cards being added

run a script that check the outcome on those cards that were added

#

now we need to backtrack a little for the third part - at the moment we don't know wihch cards have been added

#

so we need to add them to a table, then clear that table after the script has run so...

#

in an example outside of your function:

objectsEnteringScriptingZone = {} -- make an empty table
-- sometime later, inside onObjectEnterScriptingZone:
table.insert(objectsEnteringScriptingZone, enter_object) -- insert this enter_object to the end of the table
-- sometime later _after_ using the table
objectsEnteringScriptingZone = {} -- set the table to empty again
#

these are the three lines you need, but they all go in different places - any idea where?

#

note we're not actually doing anything with the objects yet.

exotic mortar
#

objectsEnteringScriptingZone = {} this one definitely going before the function onObjectEnterScriptingZone to create the table

The next would be used to insert the enter object into the table, so in the onObjectEnter function

The third would be used (guess) in the myTimerFinished function?

#

Although I suspect that last one would cause the table to clear before the info is used ..

#

Unless I wrote the table clear last

sour bane
#

💯

#

so write it out and go from there

exotic mortar
#

Ok this is where I got to ..

objectsEnteringScriptingZone = {}

function onObjectEnterScriptingZone(zone, enter_object)
  if zone == self then
    table.insert(objectsEnteringScriptingZone, enter_object)
    log(table.insert(objectsEnteringScriptingZone, enter_object))
    name = tonumber(enter_object.getName())
    description = tonumber(enter_object.getDescription())
    if 0 == name - description then
      enter_object.setDescription(description + 4)
      enter_object.addTag("sent")
    end
    -- we've done the description part, now we need to set the timer
    -- this is where you'll adapt my example to start a timer

    -- this was my example:
    setDelay("My Timer Name", myTimerFinished, 1)
  end
end

-- below just copy pasted from my above
delayIDs = {} -- yes, this should be empty
function setDelay(delayName, functionToCall, delaySeconds)
  if delayIDs[delayName] then -- if a delay timer with this name (key in table delayIDs) is already running then
    Wait.stop(delayIDs[delayName]) -- stop the delay timer
  end
  delayIDs[delayName] = Wait.time( -- get a new wait ID for the following Wait.time function
    functionToCall, -- function to call when the timer runs out. note i have left out the (), as it wants a function _NOT_ a function call
    delaySeconds -- how many seconds to wait for
  )
end

-- also from my example above:
function myTimerFinished()
  objectsEntered = objectsEnteringScriptingZone
  log(objectsEntered, "ObjectsEntered")
  log(description, "description")
  if objectEntered.hasTag("freestyle") and objectEntered.hasTag("sent") then
    local success = tonumber(objectEntered.getDescription())
    if success <= 5 then
      log("Success")
    else
      log("Fail")
    end
  end
end

#

Using the log, it‘s saying that within the table “objectsEnteringScriptingZone” there’s 6 entries, where there should only be three.

Then I get an error after the delay that reads “attempt to index a nil value”

I assume that’s because I’ve not inserted the tag information in the table I’m referencing, but that’s because I can’t figure out how to ..

#

Getting somewhere though 😅

sour bane
#

you don't need the tag information in the table because you're keeping the object itself in the table

#

you're missing a few things so let me clean that up
including one part we haven't covered yet, and that's looping through the objectsEnteringScriptingZone which I'll cover another time (I'm going out in a few minutes)

#
objectsEnteringScriptingZone = {}

function onObjectEnterScriptingZone(zone, enter_object)
  if zone == self then
    name = tonumber(enter_object.getName())
    description = tonumber(enter_object.getDescription())
    if 0 == name - description then
      enter_object.setDescription(description + 4)
      enter_object.addTag("sent")
    end
    -- we've done the description part, now we need to set the timer
    -- this is where you'll adapt my example to start a timer

    -- this was my example:
    setDelay("My Timer Name", myTimerFinished, 1)
    -- insert as the last thing we do
    table.insert(objectsEnteringScriptingZone, enter_object)
  end
end

-- below just copy pasted from my above
delayIDs = {} -- yes, this should be empty
function setDelay(delayName, functionToCall, delaySeconds)
  if delayIDs[delayName] then -- if a delay timer with this name (key in table delayIDs) is already running then
    Wait.stop(delayIDs[delayName]) -- stop the delay timer
  end
  delayIDs[delayName] = Wait.time( -- get a new wait ID for the following Wait.time function
    functionToCall, -- function to call when the timer runs out. note i have left out the (), as it wants a function _NOT_ a function call
    delaySeconds -- how many seconds to wait for
  )
end

-- also from my example above:
function myTimerFinished()
  for _,obj in ipairs (objectsEnteringScriptingZone) do -- for each object in our table do
    log(obj, "obj:")
    log(obj.getDescription(), "description")
    if obj.hasTag("freestyle") and obj.hasTag("sent") then
      local success = tonumber(obj.getDescription())
      if success <= 5 then
        log("Success")
      else
        log("Fail")
      end
    end
  end
  -- now we've finished looping, reset the table
  objectsEnteringScriptingZone = {}
end
#

I did add the loop here

#

the part

for _,obj in ipairs(objectsEnteringScriptingZone) do
end

just loops through our table in order where each loop obj is each individual object

#

I then renamed the objectEntered var to simply obj for all the code inside it

#

the _ is a throwaway var name, its used when we don't need to know whats stored there. you could put a var there e.g. i and it'd tell you which number you are on, so it'd go 1 then 2 then 3 for three cards

exotic mortar
#

Right, was just thinking should I do I loop

#

Ok, the script runs for the overall now, but is registering a fail when it should be a success

#

Agh no that was me getting > wrong way round ..

However it’s now not registering when there’s no freestyle tag that it’s a fail .. probably needs to be written in but I’m just telling you that’s what I’m getting. I’ll have a fiddle just need to pop out too.

exotic mortar
#

Ok just getting myself into a mess now ..

Still getting the same problem = script keeps running for the individual card entered …

#
objectsEnteringScriptingZone = {}

function onObjectEnterScriptingZone(zone, enter_object)
  if zone == self then
    name = tonumber(enter_object.getName())
    description = tonumber(enter_object.getDescription())
    if 0 == name - description then
      enter_object.setDescription(description + 4)
      enter_object.addTag("sent")
    end
    -- we've done the description part, now we need to set the timer
    -- this is where you'll adapt my example to start a timer

    -- this was my example:
    setDelay("My Timer Name", myTimerFinished, 1)
    -- insert as the last thing we do
    table.insert(objectsEnteringScriptingZone, enter_object)
  end
end

-- below just copy pasted from my above
delayIDs = {} -- yes, this should be empty
function setDelay(delayName, functionToCall, delaySeconds)
  if delayIDs[delayName] then -- if a delay timer with this name (key in table delayIDs) is already running then
    Wait.stop(delayIDs[delayName]) -- stop the delay timer
  end
  delayIDs[delayName] = Wait.time( -- get a new wait ID for the following Wait.time function
    functionToCall, -- function to call when the timer runs out. note i have left out the (), as it wants a function _NOT_ a function call
      delaySeconds -- how many seconds to wait for
      )
    end

#

-- also from my example above:
    function myTimerFinished()
      sentCard = false
      sentCard2 = false
      log(sentCard, "sentCard:")
      log(sentCard2,"sentCard2:")
      for _,obj in ipairs (objectsEnteringScriptingZone) do -- for each object in our table do
        sentCard = true
        log(sentCard, "sentCard")
        log(obj, "obj:")
        log(obj.getDescription(), "description:")
        log(obj.getTags(), "Tags:")
        if obj.hasTag("freestyle") and obj.hasTag("sent") then
          sentCard2 = true
          log(sentCard2, "sentCard2")
        elseif not obj.hasTag("freestyle") and obj.hasTag("sent") then
          sentCard = false
          log(sentCard, "sentCard")
          if sentCard == false and sentCard2 == false then
            log("fail")
            print("fail")
          elseif sentCard == false and sentCard2 == true then
            log("success")
            print("success")
          end

        end
      end
      objectsEnteringScriptingZone = {}
    end

sour bane
#

Still getting the same problem = script keeps running for the individual card entered …
how are you entering the cards?

exotic mortar
sour bane
#

does your save have local assets? if so this won't work but if it doesn't then email me your save file

exotic mortar
#

I’m currently now trying the following ..

Set a variable to true if a freestyle tag is detected

On a button click from elsewhere, detect whether that variable is true or false, then do accordingly

#

But the variable isn’t being passed or changed by objects, even if I originate it in Global

#

So I’m doing

In global
“success = false”

Then in the zone,
For objects …… do
If freestyle tag found then
Success = true

Then on the button

If success = true then

Do the thing

Else do something else

sour bane
#

i can't read that because it's too pseudo :)

#

i tested the script in my TTS so it was working on my end, but I guess it depends how fast you're putting the cards in

exotic mortar
#

I’ve found a solution .. you’re probably going to laugh ….

#

I’ve ended up giving the zone itself a tag “successful” if the correct card and value is found.

Then a button to check if the zone has the tag or not …….

sour bane
#

that sounds a practical solution, but (again) that wasn't your brief :P