-- This Source Code Form is subject to the terms of the bCDDL, v. 1.1. -- If a copy of the bCDDL was not distributed with this -- file, You can obtain one at http://beamng.com/bCDDL-1.1.txt local M = {} local groups = { main = {name = 'garageLight', triggers = {'garageLightsMainTrigger_1', 'garageLightsMainTrigger_2'}, linkedLights = {'garageBounce_1', 'garageBounce_2', 'garageBounce_3'}}, office = {name = 'garageOfficeLight', triggers = {'garageOfficeLightsTrigger'}}, bench = {name = 'garageBenchLight', triggers = {'garageBenchLightsTrigger'}} } local propSuffixes = {main = '_', on = 'PropOn_', off = 'PropOff_'} local garageObjects = {} local anyLightsActive = false local function setupGarageTables() -- creates garage lights data table.clear(garageObjects) for _, v in pairs(groups) do garageObjects[v.name] = { triggers = {}, lightsCount = 0, linkedLights = v.linkedLights, active = false, activeTimer = -1, activeTimingOn = 0.5, activeTimingOff = 2, delayTimer = -1, delayTimeMin = 0, delayTimeMax = 0, delayTiming = 0, delayIndex = 0, delayInstantOff = false } for _, t in ipairs(v.triggers) do garageObjects[v.name].triggers[t] = false end for i = 1, 100 do if not scenetree.findObject(v.name..propSuffixes.main..i) then garageObjects[v.name].lightsCount = i - 1 break end end end local garageLights = garageObjects[groups.main.name] garageLights.activeTimingOn = 1.5 garageLights.activeTimingOff = 5 garageLights.delayTimeMax = 0.3 end local function setLight(name, index, state) -- sets a light and its related props to on or off if state == nil then state = false end local light = scenetree.findObject(name..propSuffixes.main..index) local propOn = scenetree.findObject(name..propSuffixes.on..index) local propOff = scenetree.findObject(name..propSuffixes.off..index) if light then light.isEnabled = state end if propOn then propOn.hidden = not state end if propOff then propOff.hidden = state end end local function onPreRender(dt, dtSim) if not anyLightsActive then return end -- ignore everything if all lights are not active local lightsDone = false for k, v in pairs(garageObjects) do if v.activeTimer >= 0 then -- timing until light sequence starts or stops local timing = v.active and v.activeTimingOn or v.activeTimingOff if v.activeTimer >= timing then if v.linkedLights then for _, o in ipairs(v.linkedLights) do local obj = scenetree.findObject(o) if obj then obj.isEnabled = v.active end end end v.activeTimer = -1 v.delayIndex = math.random(v.lightsCount) -- random start index v.delayIndexOrig = v.delayIndex v.delayTimer = 0 else v.activeTimer = v.activeTimer + dtSim end end if v.delayTimer >= 0 then -- delay timing for individual lights in a sequence if v.delayTimer >= v.delayTiming then setLight(k, v.delayIndex, v.active) if not v.active and v.delayInstantOff then v.delayTiming = 0 else if v.delayTimeMax > 0 then v.delayTiming = lerp(v.delayTimeMin, v.delayTimeMax, math.random()) -- random duration until next light changes else v.delayTiming = 0 end end v.delayIndex = v.delayIndex + 1 if v.delayIndex > v.lightsCount then v.delayIndex = 1 end if v.delayIndex == v.delayIndexOrig then v.delayTimer = -1 lightsDone = true break end else v.delayTimer = v.delayTimer + dtSim end end end if lightsDone then -- checks if any lights are still active for k, v in pairs(garageObjects) do anyLightsActive = false if v.active then anyLightsActive = true break end end end end local function onBeamNGTrigger(data) if data.subjectID == be:getPlayerVehicleID(0) and (data.event == 'enter' or data.event == 'exit') then if not next(garageObjects) then setupGarageTables() end for k, v in pairs(garageObjects) do local stateChanged = false for t, _ in pairs(v.triggers) do -- handles multiple triggers; ideally, they should be touching each other if data.triggerName == t then v.triggers[t] = data.event == 'enter' stateChanged = true end end if stateChanged then local active = false for t, state in pairs(v.triggers) do if state then active = true break end end if v.active ~= active then anyLightsActive = true v.active = active v.activeTimer = 0 end end end end end M.onPreRender = onPreRender M.onBeamNGTrigger = onBeamNGTrigger return M