Yurgon Posted March 9, 2015 Posted March 9, 2015 I recently spent several hours debugging a script that revolved around timer.scheduleFunction(). Since I didn't find any meaningful reference to it in the forum, maybe this will help someone avoid some headache in the future. Note, I'm specifically talking about timer.scheduleFunction(), a function that comes with the DCS Simulator Scripting Engine (SSE). I'm not talking about mist.scheduleFunction() that comes with the 3rd party library "MIssion Scripting Tools", which may or may not behave alike. Note 2, I mostly wrote the following code examples in the forum's message box, it's entirely possible that they will cause scripting errors if you copy & paste them. This post isn't meant as a working template, it's supposed to be an addendum to the documentation. If by now you have absolutely no clue what I'm talking about, you're probably reading the wrong post. :smartass: Okay, so what is it about? I wanted to play sound files in order (dynamic MGRS read-out; requires that the mission contains "A.ogg", "B.ogg", ..., "Z.ogg", "0.ogg", ..., "9.ogg"). Consider the following basic example: -- This example will play only the last sound file -- (At least that's what happens when I run it in a test mission) function MGRS2Speech (mgrs_string) local char for i = 1, string.len(mgrs_string), 1 do char = string.sub(mgrs_string, i, i) if char ~= " " then trigger.action.outSound(char .. ".ogg") end end end MGRS2Speech("GH 234987") What happens is that "7.ogg" will be played once, nothing else. I assume that the Simulator Scripting Engine has some kind of sound buffer that doesn't automatically append sounds one after the other, instead (maybe someone can explain the reason) it just plays one sound. So, the obvious answer is to delay the outSound() calls with timer.scheduleFunction(). Hoggit Wiki documentation: -- Wiki documentation functionId timer.scheduleFunction(function functionToCall, functionArgs anyFunctionArguement, time modelTime ) -- The following will run a function named "main" 120 seconds from one the code would run. timer.scheduleFunction(main, {}, timer.getTime() + 120) Now my problem was that I didn't want to write 36 different functions, I just wanted to pass a single parameter, and whenever I ran my mission the scheduled function failed and failed and failed to execute, and worse, there wasn't even any log entry in DCS.log. So here's what works for me. I'll highlight the way parameters are passed, because that's what I found particularly difficult to understand. Isolated working code with timer.scheduleFunction(): -- WORKING EXAMPLE -- This example should play the following sound files: -- "G.ogg" (1 second after function call) -- "H.ogg" (1.7 seconds after function call) -- "2.ogg" (2.4 seconds after function call) -- "3.ogg" (3.1 seconds after function call) -- "4.ogg" (3.8 seconds after function call) -- "9.ogg" (4.5 seconds after function call) -- "8.ogg" (5.2 seconds after function call) -- "7.ogg" (5.9 seconds after function call) function MGRS2Speech (mgrs_string) local char local delay = 1 -- Read out the next char after this time has passed for i = 1, string.len(mgrs_string), 1 do char = string.sub(mgrs_string, i, i) if char ~= " " then timer.scheduleFunction(MGRS2SpeechSound,[b] { ["sound_file"] = char .. ".ogg" }[/b], timer.getTime() + delay) delay = delay + 0.7 -- Wait this long in seconds until the next sound gets played end end end function MGRS2SpeechSound (params) if params == nil then params = {} end local sound_file = params["sound_file"] or "" if sound_file == "" or sound_file == " " then return "" end trigger.action.outSound(sound_file) end MGRS2Speech("GH 234987") Now, one last thing. Let me focus on the parameter-passing to timer.scheduleFunction(): -- This example will lead to the exact same parameter value being passed to -- each call of the scheduled function function MGRS2Speech (mgrs_string) local char local delay = 1 -- Read out the next char after this time has passed local param = {} for i = 1, string.len(mgrs_string), 1 do char = string.sub(mgrs_string, i, i) if char ~= " " then [b]param["sound_file"] = char .. ".ogg"[/b] timer.scheduleFunction(MGRS2SpeechSound, [b]param[/b], timer.getTime() + delay) delay = delay + 0.7 -- Wait this long in seconds until the next sound gets played end end end MGRS2Speech("GH 234987") In my case and in the above example, the function MGRS2SpeechSound would be called 8 times, and each time the parameter would be ["sound_file"] = "7.ogg". It appears as if the SSE passes the parameter by reference, leading to the same parameter value each time the function is then actually called. Therefore, in the above WORKING EXAMPLE, I chose to pass the parameter as an anonymous variable, leading to pass by value. Okay, and finally an example to pass multiple parameters to a scheduled function: params = {} params["some_element"] = "Some element" params["other_element"] = "Another element" params[0] = "Yet another element" params["some_number"] = 47 -- Call someFunc(params) in 10 seconds timer.scheduleFunction(someFunc, params, timer.getTime() + 10) function someFunc(args) env.info("someFunc() called at " .. timer.getTime() .. " with these parameters: some_element: " .. args["some_element"] .. ", other_element: " .. args["other_element"] .. ", 0: " .. args[0] .. ", some_number: " .. args["some_number"]) end
shagrat Posted March 9, 2015 Posted March 9, 2015 Good find! So that's what I call a brutal night shift. And thanks for the "working example"... That is exactly what I am missing in almost every documentation. Simple working examples that actually use real parameters, not a syntax showcase that doesn't execute. Really helpful. Shagrat - Flying Sims since 1984 - Win 10 | i5 10600K@4.1GHz | 64GB | GeForce RTX 3090 - Asus VG34VQL1B | TrackIR5 | Simshaker & Jetseat | VPForce Rhino Base & VIRPIL T50 CM2 Stick on 200mm curved extension | VIRPIL T50 CM2 Throttle | VPC Rotor TCS Plus/Apache64 Grip | MFG Crosswind Rudder Pedals | WW Top Gun MIP | a hand made AHCP | 2x Elgato StreamDeck (Buttons galore)
etcher Posted March 10, 2015 Posted March 10, 2015 Thank you very much, this will prove most helpful. Impressive analysis ! [sIGPIC][/sIGPIC]
Recommended Posts