Lua countdown (for traffic light)

Discussion in 'Programming' started by xnx1985, Dec 15, 2023.

  1. xnx1985

    xnx1985
    Expand Collapse

    Joined:
    Aug 7, 2014
    Messages:
    145
    Hey

    I try to make a simple code in which an object is always shown, but when the vehicle enters the Lua trigger
    after like 3-5 seconds it will change to hidden for 3 seconds and then return to unhidden.
    this is an example of my code
    Thank you!

    Code:
    local function BeamNGTrigger_obj1(data)
      if data.event == 'enter'  then   
        local obj1 = scenetree.findObject('obj1')
        obj1.hidden = false
    
      end
      if data.event == 'exit'  then
    
        local obj1 = scenetree.findObject('obj1')
    
      obj1.hidden = true
    
      end
    end
    return BeamNGTrigger_obj1
     
  2. r3eckon

    r3eckon
    Expand Collapse

    Joined:
    Jun 15, 2013
    Messages:
    594
    You can create a timer variable and increment it with dtSim in a hook function, something like this:

    Code:
    local time = 0
    local function onPreRender(dtReal,dtSim,dtRaw)
    time = time + dtSim
    end
    
    To delay some action by 3 seconds store the current time in another variable when you want to start the delay, say when the player enters the trigger. Then inside onPreRender check if the current time is greater or equal to the stored time value + 3. If so you execute the delayed action. To make sure it only happens once set a boolean variable to true after trigger enter, then false after the delayed action happened and only check the time difference if that bool is true.
     
    • Like Like x 1
  3. xnx1985

    xnx1985
    Expand Collapse

    Joined:
    Aug 7, 2014
    Messages:
    145
    Thank's for the help :)
    I tried this but it looks like it doesn't count (I'm not very good at coding :p)
    If I change the "<" time <=3 it is hidden or not hidden but maybe I need to add something to make it change from 3 to 0?

    one more question maybe it would be simple:
    can I make a code that changes the object value only when the vehicle completely stops?

    Code:
    local function BeamNGTrigger_INS(data)
    local time = 0
    local function onPreRender(dtReal,dtSim,dtRaw)
    time = time + dtSim
    end
    
        if data.event == 'enter' and time <=3 then
            local INS_red = scenetree.findObject('INS_red')
            INS_red.hidden = true
    
        end
    
        if data.event == 'exit' then
            local INS_red = scenetree.findObject('INS_red')
            INS_red.hidden = false
    
        end
    end
    
    return BeamNGTrigger_INS
     
  4. r3eckon

    r3eckon
    Expand Collapse

    Joined:
    Jun 15, 2013
    Messages:
    594
    Don't nest onPreRender inside the trigger function. That function won't be able to count time if it only executes for a single frame when a trigger event happens. Also you misunderstood what I explained about executing an action after the delay. I'll share a script I'm using for queuing delayed functions, put this code in a file inside userfolder/lua/ge/extensions/ and give it a unique name like myDelay.lua:

    Code:
    -- To queue function calls with a set frame/time delay before execution.
    -- Can be called from flowgraph or other lua scripts.
    -- Delay mode can be nil or "frame" for frames, "time" for seconds.
    -- Time based delay will ignore slow motion but still work with pause.
    
    local M = {}
    
    local cframe = 0
    local ctime = 0
    
    local ftable = {}
    
    ftable["test"] = function(p)
    print(p)
    end
    
    -- add custom functions below this line
    
    
    -- add custom functions above this line
    
    local fqueue = {} -- frame delay queue
    local squeue = {} -- time delay queue
    
    local ptable = {}
    local rtable = {}
    
    local function setParamTableValue(p,ti,v)
    if ptable[p] == nil then ptable[p] = {} end
    ptable[p][ti] = v
    end
    
    local function setParam(p,v)
    ptable[p] = v
    end
    
    local function queue(f,p,d, mode)
    if (not mode) or (mode == "frame") then
    table.insert(fqueue, {f, p, cframe+d})
    elseif mode == "time" then
    table.insert(squeue, {f, p, ctime+d})
    end
    end
    
    
    local function exec(f,p)
    if p ~= nil then
    rtable[f] = ftable[f](ptable[p])
    else
    rtable[f] = ftable[f](0)
    end
    end
    
    local function getReturnValue(f)
    return rtable[f] or "nil"
    end
    
    
    local fdequeue = {}
    local sdequeue = {}
    local simspeed = 1
    local function onPreRender(dtReal,dtSim,dtRaw)
    cframe = cframe+1
    simspeed = simTimeAuthority.getReal()
    if simspeed > 0 then
    ctime = ctime+(dtSim / simspeed)
    end
    fdequeue = {}
    sdequeue = {}
    for k,v in pairs(fqueue) do
    if cframe >= v[3] then
    exec(v[1], v[2])
    table.insert(fdequeue, k)
    end
    end
    for k,v in pairs(squeue) do
    if ctime >= v[3] then
    exec(v[1], v[2])
    table.insert(sdequeue, k)
    end
    end
    for k,v in pairs(fdequeue) do
    fqueue[v] = nil
    end
    for k,v in pairs(sdequeue) do
    squeue[v] = nil
    end
    end
    
    M.setParamTableValue = setParamTableValue
    M.setParam = setParam
    M.queue = queue
    M.getReturnValue = getReturnValue
    M.onPreRender = onPreRender
    
    return M
    It might be a bit hard to understand how this works since you aren't used to lua programming but basically you add your custom functions like this, below the "test" function:
    Code:
    ftable["myFunction"] = function(p)
    -- do stuff in here, p can be a single value or a table containing multiple parameters
    end
    Then to use this function you set the needed parameter like this for a single parameter:
    Code:
    extensions.myDelay.setParam("myParameter", SOME_VALUE)
    Finally you queue the function like this:
    Code:
    extensions.myDelay.queue(FUNCTION, PARAMETER,DELAY,MODE)
    For example to queue a test message with a delay of 3.5 seconds:
    Code:
    extensions.myDelay.setParam("msg", "Hello World!")
    extensions.myDelay.queue("test", "msg", 3.5 , "time")
    
    So 3.5 seconds after the queue function is called "Hello World!" will show up in console.

    In your case, you would want your custom function to find the obj1 object and use the p parameter as the true or false for the hidden state, something like this:
    Code:
    ftable["setHidden"] = function(p)
    local obj1 = scenetree.findObject('obj1')
    obj1.hidden = p
    end
    
    To get the desired effect when you detect the trigger enter state queue both hide and unhide with extra time delay for the unhide so it executes say 3 seconds later:
    Code:
    extensions.myDelay.setParam("hide", true)
    extensions.myDelay.setParam("show", false)
    extensions.myDelay.queue("setHidden", "hide", 5 , "time") -- in 5 seconds the object will be hidden
    extensions.myDelay.queue("setHidden", "show", 8 , "time")  -- 3 seconds later the object will be shown
    
    Remember that if the game is running when you do all this you need to reload lua scripts with CTRL+L if you don't do this changes to lua code won't be reflected in game. Final tip, if you want to detect the player vehicle to trigger this function use this:
    Code:
    if data.event == 'enter' and data.subjectID == be:getPlayerVehicleID(0) then
    -- do stuff when the player vehicle enters a trigger
    end
    
     
    • Like Like x 1
  5. xnx1985

    xnx1985
    Expand Collapse

    Joined:
    Aug 7, 2014
    Messages:
    145
    Ok If I'm getting this right I need to write this in Lua file in the level map folder and then use this function inside the lua trigger?
    I will try this thanks a lot!
     
  6. r3eckon

    r3eckon
    Expand Collapse

    Joined:
    Jun 15, 2013
    Messages:
    594
    Please read more carefully, I didn't say anything about the level map folder. You have to add the script in userfolder/lua/ge/extensions/ see this link to find your userfolder. You then need to modify it slightly to add your custom function that will hide/show the object, as I've explained. You might also need to add this line to the top of your trigger script so it can use extensions, in case you get errors about extensions being nil or missing:
    Code:
    local extensions = require("extensions")
     
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice