PLP Posted January 31, 2014 Posted January 31, 2014 Hi all, Is there any reason that Do Script and Do Script file with the exact same script in the file that is in Do script are different? Is it normal for it not to be possible to to define a function in "do script"? Furthermore, If I copy the code from my function and put it in a Do Script, it gives a different outcome. (I changed all the variable names and defined all the arguments with the good value.) My question is really: Am I missing something, or is this not really normal? I'm kinda confused:confused: Thanks in advance for any answers I attached an example of a mission giving me issues. Mist is used. Execution at time 3 and 30 should be exactly the same. More precisely the infantryman should be moving at second 3 and the tank should re-explode at second 30.Mistv3_2.luaMist_check.mizexplodetest.lua [sIGPIC][/sIGPIC]
Wrecking Crew Posted January 31, 2014 Posted January 31, 2014 I'll toss in my two cents, but it isn't going to answer your question... I'm a Mist user and not an expert with it. To make a Do Script File event work, the file must be available to the mission, so, like with your attachments, you need two files -- the mission file and the Mist file. With a Do Script event the Mist file's content (or whatever script you write) is in the Do Script dialog box and you don't need to make the Mist file available for the mission when it loads. This is critical if the mission is shared and run on multiple servers; also critical when the Mist file is updated because you would need a copy of each Mist version that is used in all of your missions or you would have to go back to each mission and update the file link to the new file version. I have older missions that certainly have the Mistv2_0.lua file content in the Do Script action, and while my new missions are all using Mistv3_2.lua I did not need to go back to the old missions and update them. My understanding is that a new Mist version is a continuation of previous versions with new features / functions added, and bug fixes of course. I have never used the Do Script File --> that's why I don't have the answer to your question. But hopefully my response will help folks decide which route to take. WC Visit the Hollo Pointe DCS World server -- an open server with a variety of COOP & H2H missions including Combined Arms. All released missions are available for free download, modification and public hosting, from my Wrecking Crew Projects site.
Wrecking Crew Posted January 31, 2014 Posted January 31, 2014 Looking at your mission events... You not bracketing and indenting the script correctly in the third event -- you have this, as seen with Notepad++ -- mist.groupToPoint("Inf","TZ1",nil,270,14,0) local fakeZone2 = {} pos = Unit.getByName("A"):getPosition().p fakeZone2.point = {x = pos.x,y = pos.y, z = pos.z} trigger.action.explosion(fakeZone2, 100) It needs to look more like -- mist.flagFunc.units_in_zones{ units = {'[red][plane]'}, zones = {'Ready to Attack Ground Units'}, flag = 10007, zone_type = 'cylinder', stopflag = 10004, toggle = true, } In your first event you have two Do Script File actions -- the first that loads the Mist file and the second to do an action. Separate these into two events -- load Mist at about 1-2 seconds and then execute the second Do Script File a few seconds later (I use 4 and 8 or so). In your second event you have this -- EXPLODETEST("Inf","A") ^^^ I don't see how this could work, but then I'm not the expert :-P WC Visit the Hollo Pointe DCS World server -- an open server with a variety of COOP & H2H missions including Combined Arms. All released missions are available for free download, modification and public hosting, from my Wrecking Crew Projects site.
Speed Posted January 31, 2014 Posted January 31, 2014 (edited) I don't have DCS in front of me right now, and I don't have a lot of time, but I'll try to help. Well, I'm no expert on the groupToPoint function, I didn't write it. But you do clearly have an issue with your EXPLODETEST function- EXPLODETEST = function(goupname,unitname) mist.groupToPoint(groupname,"TZ1",nil,270,14,0) local fakeZone = {} pos = Unit.getByName(unitName):getPosition().p fakeZone.point = {x = pos.x,y = pos.y, z = pos.z} trigger.action.explosion(fakeZone, 100) return end Two issues, actually, one that will cause it not to work, and the second that is usually bad programming practice. The most severe issue is that you are passing in a variable named "unitname", but you use a variable named "unitName" in your function. unitName will be nil, unless you have it globally defined somewhere. Secondly, because you do not write "local" in front of the first declaration of "pos", then "pos" is a global variable that every single other thing in Lua can now see. Global variables need to be restricted to only those things that absolutely have to be global variables. There are two reasons- 1) It's good programming practice; you don't want a mess of global variables filling your global namespace and causing problems with unrelated parts of your code. 2) Secondly, due to the way that Lua retrieves the values of variables, using global variables is less efficient than using local variables. In sections of code where, for example, you use a global function like table.remove hundreds or thousands of times in a loop, I usually make a local reference to the function to improve the efficiency and speed of my code. Oh and finally, you only need to use "return" if you need to break out of a function before it would naturally return, or you need to return a value. You don't need to put "return" at the very end of a function, when it would just return anyways. Rarely though, I do put a "return nil" in my code, usually in my object destructor functions, but that's just to remind myself that I should use it like obj = obj:destroy(). Edited January 31, 2014 by Speed Intelligent discourse can only begin with the honest admission of your own fallibility. Member of the Virtual Tactical Air Group: http://vtacticalairgroup.com/ Lua scripts and mods: MIssion Scripting Tools (Mist): http://forums.eagle.ru/showthread.php?t=98616 Slmod version 7.0 for DCS: World: http://forums.eagle.ru/showthread.php?t=80979 Now includes remote server administration tools for kicking, banning, loading missions, etc.
PLP Posted February 1, 2014 Author Posted February 1, 2014 Thank you so much for your prompt answers. You raise many good points and expose a lot of my bad coding habits:music_whistling:. In your first event you have two Do Script File actions -- the first that loads the Mist file and the second to do an action. Separate these into two events -- load Mist at about 1-2 seconds and then execute the second Do Script File a few seconds later (I use 4 and 8 or so). Well since the second script does nothing more than define a function I though it would still work, but yeah you're right I'll do it this way from now on :) . The most severe issue is that you are passing in a variable named "unitname", but you use a variable named "unitName" in your function. unitName will be nil, unless you have it globally defined somewhere. Oups :shocking:, ok I wrote this example a little bit too fast... Secondly, because you do not write "local" in front of the first declaration of "pos", then "pos" is a global variable that every single other thing in Lua can now see. Global variables need to be restricted to only those things that absolutely have to be global variables. There are two reasons- 1) It's good programming practice; you don't want a mess of global variables filling your global namespace and causing problems with unrelated parts of your code. 2) Secondly, due to the way that Lua retrieves the values of variables, using global variables is less efficient than using local variables. In sections of code where, for example, you use a global function like table.remove hundreds or thousands of times in a loop, I usually make a local reference to the function to improve the efficiency and speed of my code. Oh, I naively though everything that was not public was local, but I guess that's just a C habit... I stand corrected! Thanks I corrected my code (attached), unfortunately I am still experiencing different results when I copy the content of the function as defined in the lua file in a "do script" (with function args defined just above), which really confuses me to be honest. Maybe variables that are accessible from the main are not accessible from a subfunction? how could that be? It gives a strange error at second 15 (execute from function), but the explosion at a point does not work at second 30.Mist_check-corrected.mizTestFct.lua [sIGPIC][/sIGPIC]
Speed Posted February 1, 2014 Posted February 1, 2014 (edited) Thank you so much for your prompt answers. You raise many good points and expose a lot of my bad coding habits:music_whistling:. Well since the second script does nothing more than define a function I though it would still work, but yeah you're right I'll do it this way from now on :) . Oups :shocking:, ok I wrote this example a little bit too fast... Oh, I naively though everything that was not public was local, but I guess that's just a C habit... I stand corrected! Thanks Lua is kinda ridiculous like that- things default global if you don't put local in front of them. It's because it's a scripting language intended for simple things, usually. But it runs fast enough that you CAN create fairly complicated scripts with it. You can change the default behavior of Lua, however, by modifying the __newindex metamethod of _G. I haven't tested this particular code, but this ought to make it impossible to declare global variables except with rawset or the function "makeGlobal": function makeGlobal(key, val) assert(type(key) == 'string', "Why would you want to create a global variable with a key type of " .. type(key) .. "?!?!") rawset(_G, key, val) end do local function _GNewIndex(G, key, val) -- G in this case is _G. assert(false, "Attempt to create new global variable at key \"" .. tostring(key) .. "\". Please use rawset(_G, <key>, <val>) or makeGlobal(<key>, <val>) to make a global variable.") end setmetatable(_G, {__newindex = _GNewIndex}) end Though, if you don't get into the habit of using "local", you'll keep making mistakes. I'll check out your mission. In the future though, please elaborate further than "strange error", Lua usually tells you very clearly what went wrong. Edited February 1, 2014 by Speed Intelligent discourse can only begin with the honest admission of your own fallibility. Member of the Virtual Tactical Air Group: http://vtacticalairgroup.com/ Lua scripts and mods: MIssion Scripting Tools (Mist): http://forums.eagle.ru/showthread.php?t=98616 Slmod version 7.0 for DCS: World: http://forums.eagle.ru/showthread.php?t=80979 Now includes remote server administration tools for kicking, banning, loading missions, etc.
Speed Posted February 1, 2014 Posted February 1, 2014 (edited) OK, look very closely at the spelling of the first argument in TestFct TestFct = function(goupName,unitName) mist.groupToPoint(groupName,"TZ1",nil,270,14,0) local fakeZone = {} local pos = Unit.getByName(unitName):getPosition().p fakeZone.point = { x = pos.x, y = pos.y, z = pos.z} trigger.action.explosion(fakeZone, 100) end See it yet? "goupName" should be groupName This is why Lua does not make a good language to program anything extremely complex in... Heck, Lua even officially admits this, I came across a statement the other day, when trying to figure out if it was possible to make private data fields for Lua objects that could only be accessed from getter or setter methods of the object itself. The statement basically said, in a more verbose fashion, "sorry, Lua is supposed to be used for simple stuff". Of course, that doesn't mean you CAN'T write complex stuff in Lua, but you'll spend more time trouble-shooting than you would in some other languages... and if you are slightly dyslexic... you might spend A LOT more time trouble-shooting :D Secondly, you are not using trigger.action.explosion correctly. It expects a Vec3 argument as its first variable. It does not expect anything like a "zone". Vec3 is {x = number, y = number, z = number}. Here is a corrected version of your TestFnc TestFct = function(groupName,unitName) mist.groupToPoint(groupName,"TZ1",nil,270,14,0) trigger.action.explosion(Unit.getByName(unitName):getPosition().p, 100) end Edited February 1, 2014 by Speed 1 Intelligent discourse can only begin with the honest admission of your own fallibility. Member of the Virtual Tactical Air Group: http://vtacticalairgroup.com/ Lua scripts and mods: MIssion Scripting Tools (Mist): http://forums.eagle.ru/showthread.php?t=98616 Slmod version 7.0 for DCS: World: http://forums.eagle.ru/showthread.php?t=80979 Now includes remote server administration tools for kicking, banning, loading missions, etc.
PLP Posted February 1, 2014 Author Posted February 1, 2014 OK, look very closely at the spelling of the first argument in TestFct TestFct = function(goupName,unitName) mist.groupToPoint(groupName,"TZ1",nil,270,14,0) local fakeZone = {} local pos = Unit.getByName(unitName):getPosition().p fakeZone.point = { x = pos.x, y = pos.y, z = pos.z} trigger.action.explosion(fakeZone, 100) end See it yet? "goupName" should be groupName This is why Lua does not make a good language to program anything extremely complex in... Heck, Lua even officially admits this, I came across a statement the other day, when trying to figure out if it was possible to make private data fields for Lua objects that could only be accessed from getter or setter methods of the object itself. The statement basically said, in a more verbose fashion, "sorry, Lua is supposed to be used for simple stuff". Of course, that doesn't mean you CAN'T write complex stuff in Lua, but you'll spend more time trouble-shooting than you would in some other languages... and if you are slightly dyslexic... you might spend A LOT more time trouble-shooting :D Secondly, you are not using trigger.action.explosion correctly. It expects a Vec3 argument as its first variable. It does not expect anything like a "zone". Vec3 is {x = number, y = number, z = number}. Here is a corrected version of your TestFnc TestFct = function(groupName,unitName) mist.groupToPoint(groupName,"TZ1",nil,270,14,0) trigger.action.explosion(Unit.getByName(unitName):getPosition().p, 100) end goupName... :doh::wallbash:. Thank you so much sir! It now works, and my knowledge of lua programming is much better. I think a lot of my confusion came from the fact DCS does not automatically reload the script somehow. I once commented a part of it, saved, relaunched the mission, and the commented part still executed! Seemingly you need to reload the script from the Mission editor Do script file. The reason I used a fakeZone and not a vec3d is that the initial point of the script was to have troops run to your Huey wherever you landed in the LZ, using mist.groupToPoint which needs a zone. The group inside moving zone condition then triggers the pickup. I can now go extract hiding troops under heavy enemy fire :). :pilotfly::joystick::gun_smilie: Then I ran into the strange behaviour (due to DCS not always reloading the script file I guess.) The function (groupGoUnit) now works, and I am not sure 100% why earlier attemps at the exact same thing did not work, but who cares:)? groupGoUnit = function(groupName,unitName,form,heading,speed,onroads) local fakeZone = {} local pos = Unit.getByName(unitName):getPosition().p fakeZone.point = { x = pos.x, y = pos.y, z = pos.z} mist.groupToPoint(groupName,fakeZone,form,heading,speed,onroads) end groupGoUnitDef = function(groupName,unitName) local fakeZone = {} local pos = Unit.getByName(unitName):getPosition().p fakeZone.point = { x = pos.x, y = pos.y, z = pos.z} mist.groupToPoint(groupName,fakeZone,"Custom",nil,9999,0) end [sIGPIC][/sIGPIC]
Recommended Posts