prccowboy Posted March 30, 2018 Posted March 30, 2018 I've been attempting to learn scripting in DCS (and by extension lua) and I have some newbie questions. I've written the script below to check if any RED coalition can visibly see a particular unit, and if so then perform an action (in this example, mark the position with smoke). I used the MIST DB "aliveUnits" to first determine valid RED units that could see the target unit. My questions: 1) Once the target is seen, can I somehow stop the check (additional checks are redundant and I want to minimize machine cycles) => meaning can I stop the for in pairs loop? 2) Can I clean up the code? ex: I use Unit.getByName often. Is that necessary? Is there a better way to address "self"? 3) I used the TargetUnitName's position instead of TargetLastPos because I was getting nil values for TargetLastPos even when TargetIsDetected was true. Did I do something wrong there? 4) I want to minimize the overhead burden of the code, is there a good way to schedule the check or use an eventhandler? 5) Maybe most important (although this has been a good exercise to learn), is there a better way? Does DCS already check this and can I somehow tap those results rather than checking again? Thanks for your patience and feedback... local myTarget = Unit.getByName('TargetUnitName') local myTable = mist.utils.deepCopy(mist.DBs.aliveUnits) for i, v in pairs(myTable) do if (v.coalition == 'red') then local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity = Unit.getByName(v.unitName):getController():isTargetDetected(myTarget) if TargetIsVisible == true then local pos = Unit.getByName('TargetUnitName'):getPosition().p pos.x = pos.x + math.random(50,100) pos.z = pos.z + math.random(50,100) trigger.action.smoke(pos, 2) end end end
Grimes Posted March 30, 2018 Posted March 30, 2018 1. You'd have to make a new value to check against to see if it already has smoke on it. It can't be local to that specific function because it will need stored from one run to the next. Also may have to compare when the smoke was added to "refresh" it since the smoke will disappear after a certain amount of time. I wanna say 5 minutes. if TargetIsVisible == true and ((targetSmoked[targetName] and targetSmoked[targetName] + 300 < timger.getTime()) or not targetSmoked[targetName])then targetSmoked[targetName] = timer.getTime() local pos = myTarget:getPosition().p pos.x = pos.x + math.random(50,100) pos.z = pos.z + math.random(50,100) trigger.action.smoke(pos, 2) end I made a targetSmoked table that will manage that. Basically it checks to see if it has an entry, if it does then checks to see if the smoke was created more than 5 minutes ago. If it was or there is no entry it will create one. 2. See the above example I changed the pos line to reflect how it can work. Alternative you can use Unit.getPosition(myTarget).p. The mist.DBs.aliveUnits table actually does store the unit object for each unit. So Unit.getController(v.unit):isTargetDetected(myTarget) would work for that line. 3. I'd have to experiment with it, but I think that value is only used whenever the target is no longer detected or if the target is moving. 4. Wrap that all into a a function and call it with schedule functions. The mist function for this can be used to repeat the function automatically every so many seconds. I also included how the targetSmoked value can be created so that it wouldn't be overwritten each time the function is called. local targetSmoked = {} local function checkTarget() -- your code here end mist.scheduleFunction(checkTarget, {}, timer.getTime() + 1, 300) 5. Not really. DCS at an engine level probably does checks like this occasionally for the AI algorithms. The Controller.isTargetDetected function is in a way querying those results for you to use. Overall it doesn't hurt things massively if you run something like this once every few seconds. Hell doing it once a second probably wouldn't cause a noticeable performance impact. It all depends on the number of units in the mission. If you had like 1000 units then I would try to optimize it some by breaking it down so it isn't checking as many units at once. It does a quick iteration of all units and gets a list of red ground units. Then iterates that list to actually check the Controller state. The right man in the wrong place makes all the difference in the world. Current Projects: Grayflag Server, Scripting Wiki Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread) SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum
prccowboy Posted March 30, 2018 Author Posted March 30, 2018 1. You'd have to make a new value to check against to see if it already has smoke on it I was already thinking of something like that, but my real question is: say I have 1000 units in the table but I find the answer I want on unit #5, can I stop the for in pairs command from running through the entire table (and wasting cycles)? Grimes, thanks for the code examples and feedback! I appreciate the help.
Grimes Posted March 31, 2018 Posted March 31, 2018 break is the command you are thinking of. It will break out of whatever loop it is in for i, v, in pairs(whatever) do if v == 'something' then break end end The right man in the wrong place makes all the difference in the world. Current Projects: Grayflag Server, Scripting Wiki Useful Links: Mission Scripting Tools MIST-(GitHub) MIST-(Thread) SLMOD, Wiki wishlist, Mission Editing Wiki!, Mission Building Forum
prccowboy Posted March 31, 2018 Author Posted March 31, 2018 break is the command you are thinking of perfect! thanks again
Recommended Posts