Here's the problem : If I load my scenario from the Scenario menu, the lua script won't activate. But, if I reset the scenario then the lua will work. I would like the lua to work since I select the scenario from the Scenario menu. Here's how I tell the extension to load in the .json : "extensions": [ "race","test" ], Here's a simplified version of the lua ( the file is test.lua and is in Documents\BeamNG.drive\lua\scenario) : Code: local M = {} print("Hello world") return M I also noticed a message on the console that might help to solve the problem : (it only shows up after a restart of the scenario, when the lua script actually works) Code: GELua.lua.utils|{ GELua.lua.utils| name = "maze1" GELua.lua.utils| optional = true GELua.lua.utils|} (maze1 is the name of the prefab and the .json loaded in this scenario) If you can't see the problem from these indications, please ask me for the files I'll PM them to you ( I don't want these posted in public to not spoil my next mod update )
That console message simply displays the attempt to load the optional "maze1" Lua extension: that attempt is what causes a Lua file with the same name as the scenario to be automatically loaded. Try checking the log instead of the console for the output of your script: there's a bug in the console that causes it to not display all output written to it, but the log does contain it (this is easily reproduced by executing "print(1)" a few times in vehicle Lua). That said, this would be a lot easier to analyse with your code. I'm not sure why you're worried about spoilers, as A) you already posted what you were doing elsewhere and B) most people can't understand Lua anyway, but feel free to PM me the files. --- Post updated --- Your scenario Lua gets loaded fine. Your problem is that you're executing code when the scenario Lua is executed, which happens before the map is even loaded. This is why it works when you reset: it re-executes the Lua, then restarts the scenario. You want to execute your code in a hook that happens somewhere near the start of the scenario: onRaceInit (or onScenarioChange, as long as you only execute when state == 'pre-start') will probably do.
Thank you very much for the clear explanations I had trouble making the hook, so I just took (a lot) of inspiration from one of your function in your random tour scenario. Here's the final code : Code: local function functionName() [the function] end local function onScenarioChange(scenario) if scenario and scenario.state == 'pre-start' then log('I', 'mazes.onScenarioChange', 'Scenario started, starting set-up') functionName() log('I', 'mazes.onScenarioChange', 'Scenario set-up complete') end end return { onScenarioChange = onScenarioChange } It's working, but I have difficulties understanding how the hook works. I understand the function onScenarioChange, but the "return onScenarioChange = onScenarioChange" seems a little counter-intuitive for me. Do you have any idea of what it does ?
If I didn't, I wouldn't have typed it. What you'll see in many official scripts is something like the following (with comments, to explain what's happening): Code: -- Create an empty object M local M = {} -- Declare a function local function doStuff() doCoolStuff() doMoreStuff() end -- Assign our function to a field on the object called 'onScenarioChange' M.onScenarioChange = doStuff -- Return our object return M Now when this is executed, the extension manager looks at all the fields on the returned object and remembers them. Then, some part of the game Lua calls extensions.hook('onScenarioChange'), the extension manager looks at all fields called "onScenarioChange", finds ours, and calls the function. What I do is simply another way of building the object: instead of declaring an empty object, I declare one with a field called "onScenarioChange" that has the value "doStuff": Code: -- Create our object local M = { onScenarioChange = doStuff } -- Return our object return M Except instead of first assigning it to M, I directly return it. There's many other ways to create the object, you could use the indexing syntax instead of the field syntax: Code: local hookName = "onScenarioChange" M[hookName] = doStuff or you can create the whole object in one go: Code: return { onScenarioChange = function() doCoolStuff() doMoreStuff() end }