exil Posted April 18, 2021 Posted April 18, 2021 Gents, i kindly ask for your help again since i am banging my head against walls right now. Here is the problem: I am writing a script for my squadrons MP Server where we can "winch" some units with helicopters. Everything is working as intended. I am able to "winch" the units with every "blue" helicopter. The unit to be winched itsef will generate a moving zone around itself. As soon as one helicopter is inside that zone (and some other parameters for the helicopter are met) a counter starts. As long as the parameters are given (steady hover and so on) the counter will count up to 45 seconds. After that time, the unit shall be destroyed. My big problem right now is, i can't assess that specific unit. After timer counts down, all units from the table will be destroyed. Is there any specific way to assess that exact unit and further use it (spawn smoke, destroy, etc...)? Any slight help is highly appreciated! I will attach the lua script (i know, for the lua pros it looks horrible): function checkWinch() local blueHelos = mist.makeUnitTable({'[blue][helicopter]'}) --get all blue helicopters for i = 1, #blueHelos do if Unit.getByName(blueHelos[i]) then local u = Unit.getByName(blueHelos[i]) if u:getLife() > 0 then mist.flagFunc.units_in_moving_zones -- check, if some of blue helos are inside moving zone 'a' or 'b' { units = {blueHelos[i]}, zone_units = {'a', 'b'}, radius = 150, flag = 1001 } if trigger.misc.getUserFlag(1001) > 0 then -- check if helo is in air hover = false local unit = Unit.getByName('' ..blueHelos[i]) local inAir = unit:inAir() if inAir then hover = true --trigger.action.outText('' .. blueHelos[i] .. ' is in air', 10) else hover = false --trigger.action.outText('' .. blueHelos[i] .. ' is not in air', 10) end -- check if helos speed is suitable to winch steady = false local unit = UNIT:FindByName('' ..blueHelos[i]) local speed = unit:GetVelocityKNOTS() if speed < 1.5 then steady = true --trigger.action.outText('' .. blueHelos[i] .. ' speed zero', 10) else steady = false --trigger.action.outText('' .. blueHelos[i] .. ' speed more than zero', 10) end -- check if helos height is not too high for the winch height = false local unit = UNIT:FindByName('' ..blueHelos[i]) local agl = unit:GetHeight() if agl < 60 then height = true --trigger.action.outText('' .. blueHelos[i] .. ' right height', 10) else height = false --trigger.action.outText('' .. blueHelos[i] .. ' wrong height', 10) end end end end end -- check if all 3 reqiurements are met if (hover or not hover) and steady and height then trigger.action.setUserFlag('1002', true) else trigger.action.setUserFlag('1002', false) end end checktimer = mist.scheduleFunction(checkWinch, {}, timer.getTime() + 1, 1) function stopWinch() if trigger.misc.getUserFlag(1002) > 0 then if time == nil then time = 0 else time = time + 1 end else time = 0 end --trigger.action.outText('Timer counts ' .. tostring(time) .. ' seconds.', 1) local blueHelos = mist.makeUnitTable({'[blue][helicopter]'}) for i = 1, #blueHelos do if Unit.getByName(blueHelos[i]) then local u = Unit.getByName(blueHelos[i]) if u:getLife() > 0 then mist.flagFunc.units_in_moving_zones { units = {'a', 'b'}, zone_units = {blueHelos[i]}, radius = 150, flag = 1003 } -- the textmsg are in german but basically they are giving information about the winching status if (trigger.misc.getUserFlag(1003) > 0 and time == 1) then local msg = {} msg.text = 'SEIL FÄHRT' msg.displayTime = 4 msg.msgFor = { units = {'' ..blueHelos[i]}} mist.message.add(msg) end if (trigger.misc.getUserFlag(1003) > 0 and time == 7) then local msg = {} msg.text = 'SEIL NOCH 3 ZUM BODEN' msg.displayTime = 4 msg.msgFor = { units = {'' ..blueHelos[i]}} mist.message.add(msg) end if (trigger.misc.getUserFlag(1003) > 0 and time == 12) then local msg = {} msg.text = 'SEIL IST AM BODEN, PERSON WIRD EINGEHÄNGT' msg.displayTime = 4 msg.msgFor = { units = {'' ..blueHelos[i]}} mist.message.add(msg) end if (trigger.misc.getUserFlag(1003) > 0 and time == 20) then local msg = {} msg.text = 'SEIL WIRD EINGEHOLT' msg.displayTime = 4 msg.msgFor = { units = {'' ..blueHelos[i]}} mist.message.add(msg) end if (trigger.misc.getUserFlag(1003) > 0 and time == 25) then local msg = {} msg.text = 'SEIL NOCH 3 ZUR ZELLE' msg.displayTime = 4 msg.msgFor = { units = {'' ..blueHelos[i]}} mist.message.add(msg) end if (trigger.misc.getUserFlag(1003) > 0 and time == 30) then local msg = {} msg.text = 'PERSON WIRD EINGEHOLT' msg.displayTime = 4 msg.msgFor = { units = {'' ..blueHelos[i]}} mist.message.add(msg) end -- this is the big problem...i don't see a way to assess the specific unit wich is inside the zone where the helicopter is in right now to destroy it if (trigger.misc.getUserFlag(1003) > 0 and time == 40) then local blueinf = mist.makeUnitTable({'a', 'b'}) for i = 1, #blueinf do if Unit.getByName('' ..blueinf[i]) then local u = Unit.getByName('' ..blueinf[i]) if u:getLife() > 0 then u:destroy() local msg = {} msg.text = 'PERSON IM HUBSCHRAUBER, CABIN READY' msg.displayTime = 4 msg.msgFor = { units = {'' ..blueHelos[i]}} mist.message.add(msg) end end end end end end end end stoptimer = mist.scheduleFunction(stopWinch, {}, timer.getTime() + 1, 1) GeForce RTX 4090 Founders Edition - AMD Ryzen 7 5800X3D - 64Gb RAM - Win11 - HP Reverb G1 - Thrustmaster Warthog HOTAS (40cm extension) - VKB Sim T-Rudder MKIV Pedals
Grimes Posted April 19, 2021 Posted April 19, 2021 (edited) You would have to run a distance check for each unit you want it to be able to be moved and keep track of the winch time for each of them. However there are quite a few problems and optimizations you can make with your code. For starters the function mist.flagFunc.units_in_moving_zones creates an automated self check each time it is run. It just needs to be run once and then whenever mist sees any of those units are in a zone it'll set flag 1001 to true. Flag 1001 also never gets set to false so it is always true. You are also running Unit.getByName() multiple times when you already have that unit. local blueHelos = mist.makeUnitTable({'[blue][helicopter]'}) --get all blue helicopters. This list wont change for client units so it only needs to be created once local winchUnits = {'a', 'b'} local winchStatus = {} function checkWinch() local wPos = {} -- for storing the position of the unit. Here so that it only gets the position once for i = 1, #blueHelos do local u = Unit.getByName(blueHelos[i]) if u then local inAir = u:inAir() local uPos = u:getPoint() if u:getLife() > 0 and inAir == true then for j = 1, #winchUnits do local wName = winchUnits[j] local w = Unit.getByName(wName) if w then -- unit object only exists if returned if not wPos[wName] then wPos[wName] = w:getPoint() -- updates the position of the unit within the shared folder end if mist.utils.get2DDist(uPos, wPos[wName]) < 150 then -- within range if mist.vec.mag(u:getVelocity())*(3600/1852) < 1.5 and uPos.y - wPos[wName].y < 60 then -- hovering and within 60 meters above the unit if not winchStatus[wName] then -- creates the table winchStatus[wName] = {t = 0, heli = blueHelos[i]} -- stored as a table so you could add other information if you wanted to. -- for example adding a entry for its current status. winchStatus[wName].s = "loaded" end winchStatus[wName].t = winchStatus[wName].t + 1 -- adds to the time associated with that unit -- You can insert all of your code for displaying the status updates in this section -- You can remove the checking of flag 1003 and just use if statements on winchStatus[wName].t == whatever if winchStatus[wName].t == 40 then -- unit has been winched w:destroy() end elseif winchStatus[wName] then -- renove the entry winchStatus[wName] = nil end end end end end end end end Edited April 19, 2021 by Grimes 1 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
exil Posted April 19, 2021 Author Posted April 19, 2021 @GrimesYou really are a genius! I don't know how to thank you! You didn't just take the time to give me a hint, you totally made it work! Wow! You just saved me a lot of time and nerves. I already changed the script and created an advanced fast rope script which was next on my list. It works like a charm! I only can't see what I can do with that line: - for example adding a entry for its current status. winchStatus[wName].s = "loaded" Is it basically a table where I can access that specific unit again(that unit that has completed the winch process and has a unit "on board"? For exaple: if loaded then "Spawn a ground unit if the specific heli is inside another zone" end Do I get that right? Again, thank you so much for your help! GeForce RTX 4090 Founders Edition - AMD Ryzen 7 5800X3D - 64Gb RAM - Win11 - HP Reverb G1 - Thrustmaster Warthog HOTAS (40cm extension) - VKB Sim T-Rudder MKIV Pedals
toutenglisse Posted April 19, 2021 Posted April 19, 2021 16 hours ago, Grimes said: ... For starters the function mist.flagFunc.units_in_moving_zones creates an automated self check each time it is run. It just needs to be run once and then whenever mist sees any of those units are in a zone it'll set flag 1001 to true.... Hi Grimes, sorry OP for out-thread : I don't understand the self-check part of this function. It is supposed to self check with an interval of 1 sec by default when run once. but I've never seen that. If I run once it is checked at this moment and never after. I always schedule this function every 2 or 10 seconds relatively to interval I want. (2 examples attached - a F18c do some flyby above a ground unit that triggers message. Ex 1 function is ran once, Ex 2 function is scheduled) test-mist-UIMZ-schedulled.miz test-mist-UIMZ-selfcheck.miz
exil Posted April 19, 2021 Author Posted April 19, 2021 46 minutes ago, toutenglisse said: It is supposed to self check with an interval of 1 sec by default when run once. but I've never seen that. I noticed that too. I've read about that it schedules itself. But it never worked for me, that's the reason why I used a scheduler in the original script. GeForce RTX 4090 Founders Edition - AMD Ryzen 7 5800X3D - 64Gb RAM - Win11 - HP Reverb G1 - Thrustmaster Warthog HOTAS (40cm extension) - VKB Sim T-Rudder MKIV Pedals
Grimes Posted April 20, 2021 Posted April 20, 2021 3 hours ago, toutenglisse said: Hi Grimes, sorry OP for out-thread : I don't understand the self-check part of this function. It is supposed to self check with an interval of 1 sec by default when run once. but I've never seen that. If I run once it is checked at this moment and never after. I always schedule this function every 2 or 10 seconds relatively to interval I want. (2 examples attached - a F18c do some flyby above a ground unit that triggers message. Ex 1 function is ran once, Ex 2 function is scheduled) function unitinzone1() mist.flagFunc.units_in_moving_zones({ units = {'Aerial-1'}, zone_units = {'Ground-1'}, flag = "1", radius = 3000, toggle = true, }) if trigger.misc.getUserFlag("1") > 0 then trigger.action.outText('unit is in the moving zone', 5) end end unitinzone1() You have the creation and evaluation of the flag in the same block. When you run it once it will create the flag function in mist, which it will check every second, but since you are only evaluating whether flag 1 is true that one time it'll never return true. Code like the following would be one way to change it. Generally speaking though the idea of the flagFuncs are to set a flag value. So just creating a do script with the flagFunc definition and another trigger where it is checking the value for that flag to do a given action is more in line with the design usage. Though you can certainly just check the flag value via code as exampled below. function unitinzone1() if trigger.misc.getUserFlag("1") > 0 then trigger.action.outText('unit is in the moving zone', 5) end timer.scheduleFunction(unitinzone1, {}, timer.getTime() + 1) -- reschedule the check end mist.flagFunc.units_in_moving_zones({ -- create flag func units = {'Aerial-1'}, zone_units = {'Ground-1'}, flag = "1", radius = 3000, toggle = true, }) unitinzone1() -- run the check The attached screenshot is a quick test of a simple outText statement added into the mist code that displays the time that flagFunc is run and what happens if you constantly keep calling the function. Since the functions automatically reschedule themselves until told to stop each time you manually call it again it is adding more and more checks. As you can see it runs once, then twice, then 3 times, 4, 5, 6, etc. 3 hours ago, exil said: I only can't see what I can do with that line: - for example adding a entry for its current status. winchStatus[wName].s = "loaded" Is it basically a table where I can access that specific unit again(that unit that has completed the winch process and has a unit "on board"? For exaple: if loaded then "Spawn a ground unit if the specific heli is inside another zone" end Do I get that right? Again, thank you so much for your help! Yeah kinda. Its keeping track of which units have been winched and where they are in a sense. So perhaps if you had command to unload those units then it could check to see who sent the command, use the name to get the unit's properties, modify the point values, and the respawn the group where it was dropped off. Honestly it is a little backwards because for something like that it might be better to index it by the helicopter rather than what is winched. 1 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
toutenglisse Posted April 20, 2021 Posted April 20, 2021 14 minutes ago, Grimes said: ...You have the creation and evaluation of the flag in the same block. When you run it once it will create the flag function in mist, which it will check every second, but since you are only evaluating whether flag 1 is true that one time it'll never return true. Code like the following would be one way to change it. Generally speaking though the idea of the flagFuncs are to set a flag value. So just creating a do script with the flagFunc definition and another trigger where it is checking the value for that flag to do a given action is more in line with the design usage. Though you can certainly just check the flag value via code as exampled below. ... Thanks, I get it now. The way I used it was dumb.
Recommended Posts