Jump to content

Help with LUA / MIST


OneFatBird

Recommended Posts

Sorry, before anything else, for possible redundancy in asking for this help. I have a funny way of learning and am short of the commodity of time to plough through dozens of threads hoping to find specific answers to my requirements. Please be patient.

 

I need some assistance in getting started with scripting for DCS, and to that end, want to ask for some help with some basic stuff. I am conversant with programming languages (eg; C++), but need to get some hands on with interfacing LUA and MIST with DCS.

 

Objective 1: Spawning units near another unit.

 

For example, I would like to spawn RPG troops near an APC using the radio menu command. I understand that units can be spawned without them having been precreated in the ME, but how? And, once that's solved, how do I go about forcing them to spawn near a particular unit?

 

I know I have more questions, but they will have ample opportunity to be addressed further along, and may even be solved in the process of resolving the above query, so I will not clog up this post anymore with text, save to say thanks in advance to anyone kind enough to assist.

Link to comment
Share on other sites

You need to break down your problem into smaller sub-problems:

How do I add an entry to the radio menu?

How do I spawn the RPG troops at a specific location on the map?

How do I figure out the location of the APC?

At that point, "how do I spawn the RPG troops near the APC" is just a generic programming problem (take the APC coordinates and add some small offset).

 

Please take a look at the second post in this thread, where I described the process I go through when I want to find out how to do something in a mission script.

It will teach you how to use two important resources:

1) The reference documentation for MiST and the Simulator Scripting Engine on the hoggit wiki -- that tells you which functions you have to work with

2) The Lua Console in my DCS Witchcraft project -- that allows you to try new code snippets within a few seconds instead of spending one or two minutes waiting for DCS to reload your mission

 

You'll want to look at mist.dynAdd, the Group and Unit classes, and the trigger.action.* functions that have "otherCommand" in the name (those refer to the commands in the F10 "Other" radio menu).

 

Another thing that can often help is to find a mission that does something similar to what you want to do and look at their code.

 

Sorry, before anything else, for possible redundancy in asking for this help. I have a funny way of learning and am short of the commodity of time to plough through dozens of threads hoping to find specific answers to my requirements. Please be patient.

 

Please don't take this the wrong way, but the cynic in me reads that as "I can't be bothered to read the documentation, so please do all the work for me, and in the future I still plan to continue asking questions that could mostly be answered by reading the docs instead of trying to solve the problem myself first". I do understand where you are coming from, especially if you were unaware of one or more of the resources I linked above.

 

I promise you that once you get used to the process of "scan the docs for interesting functions, then play around in the Lua Console to see how they work", you will be able to solve a lot of these smaller problems in less time than it would have taken to get an answer on the forums (or even write up the question). And even when you fail, you get to post much better questions, because they will say "I tried X, expected it to do Y, but Z happened", and you can use a specific subject line for your thread so the eventual solution is easier to find for other people who have a similar problem in the future.


Edited by [FSF]Ian
  • Like 1
Link to comment
Share on other sites

Hi, ONEFATBIRD,

 

If you download MIST, the documentation contains an exhaustive list of functions along with specific examples on how to go about making scripts.

 

I learnt a lot going through the examples alone.

 

If you are a beginner, then that is the best place to start.

 

Rig - I7-9700K/GIGABYTE Z390D/RTX-2080 SUPER/32-GB CORSAIR VENGEANCE RAM/1-TB SSD

Mods - A10C / F18C / AV8B / Mig21 / Su33 / SC / F14B

Link to comment
Share on other sites

Ian;2720277']Please don't take this the wrong way' date=' but the cynic in me reads that as "I can't be bothered to read the documentation, so please do all the work for me, and in the future I still plan to continue asking questions that could mostly be answered by reading the docs instead of trying to solve the problem myself first".[/quote']

 

I see your point :doh:.

 

Thanks both for the comments. As it turns out I have looked through the reference documentation pdf (and am still doing so), and had tried a few usages of MiST for the mentioned purpose, with limited success. There are a few things which seem important, like those often mentioned tables, that need a bit of clarifying to me. I don't know how they are indexed or referenced, but I am assuming they are technically an array(?). Anyway, beside the point; that's why I wanted to let the thread evolve from a very basic example. No intention of laziness on my part, promise.

 

That said, here's one example of how I was managing to spawn RPG units.

 

First, I was setting up the radio item for the APC group. I created some hidden RPG infantry and placed them anywhere. I set up a Moving Zone on the APC. When I used the radio item, it would activate one of the RPG units and teleport it to the Moving Zone using this...

 

mist.teleportInZone('Inf','movingzone', true,  250)

However, it was not teleporting to the Moving Zone, but to where the APC had started off.

 

Thanks again, all help is greatly appreciated.

Link to comment
Share on other sites

I set up a Moving Zone on the APC.

 

You did not place a "moving zone" on the APC, because there is no such thing. You placed a trigger zone that happened to be centered at the APC's starting location.

 

How can there be no concept of a moving zone when there are trigger conditions like "unit inside moving zone"? Note that the unit that the zone moves with is an attribute of the trigger condition and not of the zone itself. In other words, placing that zone in the editor is just a convenient way to graphically specify a "radius" parameter. Whether a zone is treated as a moving zone or not depends on the trigger action or script command that you use it with.

 

We can, however, use mist.teleportToPoint instead. The following teleports the infantry to a random point four meters away from the APC, assuming the APC group is called "apc" and the infantry group is called "infantry":

local apc = Group.getByName("apc"):getUnit(1)
mist.teleportToPoint({groupName="infantry", point=apc:getPosition().p, action="teleport", radius=4, innerRadius=4})

 

If you want to, you can get fancy and calculate a spawn position in relation to the APC position. The following example spawns the infantry group five meters behind the center of the APC, so they don't get overrun:

local apc = Group.getByName("apc"):getUnit(1)
local apcPos = apc:getPosition().p
local apcDirection = apc:getPosition().x
local spawnPos = mist.vec.add(apcPos, mist.vec.scalar_mult(apcDirection, -5))
mist.teleportToPoint({groupName="infantry", point=spawnPos, action="teleport"})

 

BTW, when testing these, I wondered why they wouldn't work, then read the ****ing manual and noticed that MiST refuses to spawn units on airports and taxiways to avoid blocking AI aircraft :doh:

Link to comment
Share on other sites

mist.DBs.zonesByName question

 

I have witchcraft installed and have been making lots of progress with my LUA learning but I'm stuck on something that I hope is easy.

 

I'm trying to use mist.DBs.zonesByName to make a table of zone names. In witchcraft the above function returns the following information..

 

{

"New Trigger Zone": {

"color": [

1,

1,

1,

0.15

],

"hidden": false,

"name": "New Trigger Zone",

"point": {

"x": -285658.57142858,

"y": 0,

"z": 616798.57142858

},

"radius": 3000,

"x": -285658.57142858,

"y": 616798.57142858,

"zoneId": 153

},

"New Trigger Zone 1": {

"color": [

1,

1,

1,

0.15

],

"hidden": false,

"name": "New Trigger Zone 1",

"point": {

"x": -285430,

"y": 0,

"z": 622212.85714286

},

"radius": 3000,

"x": -285430,

"y": 622212.85714286,

"zoneId": 154

},

"New Trigger Zone 2": {

"color": [

1,

1,

1,

0.15

],

"hidden": false,

"name": "New Trigger Zone 2",

"point": {

"x": -289372.85714286,

"y": 0,

"z": 619198.57142858

},

"radius": 3000,

"x": -289372.85714286,

"y": 619198.57142858,

"zoneId": 155

}

}

 

My question is how do I create a table with just the zone names?

 

Thanks

Eric

Link to comment
Share on other sites

Iterate through the mist.DBs.zonesByName table and build a new table with the zone names. Warning, the following code is untested:

 

local zoneNames ={}
for k,v in pairs(mist.DBs.zonesByName) do
   zoneNames[#zoneNames+1] = v.name
   -- since the zone names are the table keys, zoneNames[#zoneNames+1] = k would also work here
end

Link to comment
Share on other sites

Ian;2720949']We can, however, use mist.teleportToPoint instead. The following teleports the infantry to a random point four meters away from the APC, assuming the APC group is called "apc" and the infantry group is called "infantry":

 

Nice! That all worked a treat and opens up my understanding of implementing Lua in DCS considerably. Eric here also covers some questions of mine that were going to appear regarding these DBs and Tables (though not related to witch-craft). I have a bit of time tomorrow to try and expand a bit more. I'll try on my own and only bug people if I get really stuck.

 

Thanks!

Link to comment
Share on other sites

  • 2 weeks later...

Okay, as simple as possible. What is going on here? Is this right? I am following what the manual suggests. Not working...

 

-- dynadd example

local apc = Group.getByName('apc'):getUnit(1)

mist.dynAdd
(
   {
       vars.units=
       {
           [1]=
           {
           
               ['x'] = apc:getPosition().x,
               ['y'] = apc:getPosition().y,
               ['type'] = 'Infantry M4'
           }
       }
           ['country'] = 'USA',
           ['category'] = 'INFANTRY'
   }
)

Thanks in advance...

 

EDIT: Nope, it is pretty obvious to me now what I am missing. Before even touching MIST I need to get some hands on with the basic DCS Lua script engine. It is what you said earlier, Ian, thanks for the reference. Finding my way, seen the light!


Edited by OneFatBird
Link to comment
Share on other sites

I cannot get the simplest thing to work. Sorry. I am trying to do this from scratch, because I am not getting anything from looking at example scripts, and the documentation is not exactly clear on a lot of things...

 

local apc = Group.getByName('apc'):getUnit(1)
   
coalition.addGroup(country.id.USA, Group.Category.GROUND, 
{
   ["visible"] = false,
   ["hidden"] = false,
   ["units"] = 
   {
       [1] = 
       {
           ["type"] = "Infantry M4",
           ["name"] = "New UNIT",
           ["unitId"] = 1,
           ["heading"] = 0,
           ["playerCanDrive"] = false,
           ["skill"] = "Excellent",
           ["x"] = apc:getPosition().x,
           ["y"] = apc:getPosition().y
       }
                                   
   }
}
)

 

Can someone please say why this does not work to spawn an infantry unit at the position of the apc when I use the radio item?

Link to comment
Share on other sites

Never give up, you are doing fine!

There are missing some "," and the unit needs a group and y = z. Thats all.

 

local _apc = Unit.getByName("apc")
local _apcPos = _apc:getPosition().p 

rifleman =
{
   ["visible"] = false,
   ["groupId"] = 99,
   ["name"] = "theRifleman",
   ["hidden"] = false,
   ["units"] = 
   {
       [1] = 
       {
           ["type"] = "Soldier M4",
           ["name"] = "theRifleman",
           ["unitId"] = 999,
           ["heading"] = 0,
           ["playerCanDrive"] = false,
           ["skill"] = "Excellent",
           ["x"] = _apcPos.x + 3,
           ["y"] = _apcPos.z,
       },
    },
}
coalition.addGroup(country.id.USA, Group.Category.GROUND, rifleman)

 

I added a .miz file for reference below.

 

Succes,

 

:thumbup:

ScriptspawnSodier.miz

  • Like 1
Link to comment
Share on other sites

Ah! So the vectors matrix's z is the map coords y axis. Awesome, I was missing that completely, thanks. I'm on a double front battle here, converting to Lua from C/C++ and getting to grips with the DCS script engine's syntax. You don't know how much all your comments and help are appreciated...

 

:thumbup:

 

...or how joyful I was when this little posse came into existence...

 

unitsspawned.jpg


Edited by OneFatBird
Link to comment
Share on other sites

I hope the hread startet doesn´t mind if I continue this....

 

 

Would anybody be so kind and give me a hint, how to save a lua table in a way that the order remains the same?

 

I have the following table in a lua script file defined:

 


local sqdrequip = 
{																					
[1]	=	{actype	=	'A-10C'	,	actypecosts	=	18800000	,	srtcosts	=	5000	,	instock	=	20	,	limit	=	20	},
[2]	=	{actype	=	'UH-1H'	,	actypecosts	=	4700000	,	srtcosts	=	1462	,	instock	=	20	,	limit	=	20	},
[3]	=	{actype	=	'Ka-50'	,	actypecosts	=	16000000	,	srtcosts	=	3500	,	instock	=	20	,	limit	=	20	},
[4]	=	{actype	=	'MiG-21Bis', 	actypecosts	=	2300000	,	srtcosts	=	4500	,	instock	=	20	,	limit	=	20	},
[5]	=	{actype	=	'L-39C'	,	actypecosts	=	300000	,		srtcosts	=	1000	,	instock	=	20	,	limit	=	20	},
[6]	=	{actype	=	'L-39ZA'	,actypecosts	=	800000	,		srtcosts	=	1500	,	instock	=	20	,	limit	=	20	},
[7]	=	{actype	=	'M-2000C'	,actypecosts	=	23000000	,	srtcosts	=	7000	,	instock	=	20	,	limit	=	20	},
[8]	=	{actype	=	'Mi-8MT'	,actypecosts	=	8275000	,	srtcosts	=	2820	,	instock	=	20	,	limit	=	20	},
[9]	=	{actype	=	'F-15C'	,	actypecosts	=	29900000	,	srtcosts	=	17000	,	instock	=	20	,	limit	=	20	},
[10]	=	{actype	=	'Su-27'	,	actypecosts	=	27000000	,	srtcosts	=	7000	,	instock	=	20	,	limit	=	20	},
[11]	=	{actype	=	'MiG-29S'	,actypecosts	=	29000000	,	srtcosts	=	8000	,	instock	=	20	,	limit	=	20	},
[12]	=	{actype	=	'MiG-29A'	,actypecosts	=	11000000	,	srtcosts	=	5500	,	instock	=	20	,	limit	=	20	},
}

 

 

Basically I use this code to save a given table to a lua-file:

 

ACsavefile = "vJaboG32AC.lua"
vJaBoG32vJaBoG32ACtable = {}
vJaBoG32vJaBoG32ACtable = {sqdrequip}
					
local actualserializedvJaBoG32ACtable = mist.utils.serialize('actualACituation', vJaBoG32vJaBoG32ACtable)

local exportData = "local " ..actualserializedvJaBoG32ACtable .. "\nreturn actualACituation"

exportFile = io.open(ACsavefile, "w")
exportFile:write(exportData)
exportFile:close()

 

When I open this lua-file, the oder is mixed up, as following example:

 

{
       [7] = 
       {
           ["actypecosts"] = 23000000,
           ["hrscosts"] = 7000,
           ["limit"] = 20,
           ["actype"] = "M-2000C",
           ["instock"] = 20,
       }, -- end of [7]
       [1] = 
       {
        ...
       }, -- end of [1]
       [2] = 
       {
          ...
       }, -- end of [2]
       [4] = 
       {
         ...
       }, -- end of [4]
       [8] = 
       {
         ...
       }, -- end of [8]
       [9] = 
       {
        ...
       }, -- end of [9]
       [5] = 
       {
        ...
       }, -- end of [5]
       [10] = 
       {
          ...
       }, -- end of [10]
       [3] = 
       {
        ...
       }, -- end of [3]
       [6] = 
       {
         ...
       }, -- end of [6]
       [12] = 
       {
         ...
       }, -- end of [12]
       [11] = 
       {
       ...
       }, -- end of [11]
   }, -- end of ["AC"]

 

 

 

I am pretty sure there is a simple function which sorts the table in a way like

 

local table = {

[1] = ...

[2] = ...

[3] = ...

 

[n-1]= ...

[n] = ..

}

 

I just do not find the right solution for this little problem. :joystick:

[sIGPIC][/sIGPIC]

 

Unsere Facebook-Seite

Link to comment
Share on other sites

When I open this lua-file, the oder is mixed up

 

Lua table entries do not have any defined order. The mist.utils.serialize function uses pairs() to iterate over the table entries, which returns the items in whatever order they happen to be in memory (which might depend on the order they were inserted and/or on some internal hash function).

 

You could make a copy of the mist.utils.serialize function and replace the call to pairs() with ipairs(). That would output numeric keys in order, but skip non-numeric keys. To make it work with arbitrary tables, which may include non-numeric keys, you would have to first build a list of all keys and sort it.

 

This wiki page has more information on ways to serialize tables in Lua, but at a quick glance I could not see a solution that (a) sorted keys, (b) produced machine-readable data (i.e. valid Lua) and © was written in pure Lua code.

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...
I hope the hread startet doesn´t mind if I continue this....

 

NP.

 

Now, a very simple thing (for those who know, that is).

 

How do I reference, inside a script function, a flag that I have created in ME? Let's say I have "FLAG 35", and I want a script code that sorts through flags and finds that particualr flag. I'll do this as pseudo-code (I am assuming FLAGS are global here - I'm not getting much from the documentation, yet again);

 

function _sort_through_flags()
  local i
  for i = 0 to 100 step 1
     if
        flags[i].id == 35
        break
     end if
  end  
  
  if i == 100
     return
  else
    flags[i + 1].value = flags[i + 1].value - 1
  end if
  
  return
end

You see what I'm doing? I want to "find" flag 35, then decrease the value of flag 36 by 1. Of course, this is just an example of what I might want to do. the crux of the matter is how I locate (index) flags. I've seen some funny things inside the ME mission file, and tried to use that format, but it does not seem to work.


Edited by OneFatBird
Link to comment
Share on other sites

I don't quite understand what you mean by "finding" a flag.

 

You may want to look at the following two functions:

trigger.misc.getUserFlag(flag)

trigger.action.setUserFlag(flag, value)

 

Example usage:

-- if flag 35 is more than 6,
-- decrease flag 36 by 1 and reset flag 35 to 0
if trigger.misc.getUserFlag(35) > 6 then
   trigger.action.setUserFlag(36, trigger.misc.getUserFlag(36) - 1)
   trigger.action.setUserFlag(35, 0)
end

Link to comment
Share on other sites

OK, everything good. There is however one thing that is really bugging me.

 

What is the SELF class? There is no description of it that I can find in the documentation I'm looking at, and there are a ton of useful commands and functions that are hindered only by the fact that SELF is the argument.

 

Is it the player? Is it the unit that you have "got" by whatever means? Can it be either, or both? I cannot get it to work...

 

Sorry for so much bother with this.

Link to comment
Share on other sites

OK, everything good. There is however one thing that is really bugging me.

 

What is the SELF class? There is no description of it that I can find in the documentation I'm looking at, and there are a ton of useful commands and functions that are hindered only by the fact that SELF is the argument.

 

Is it the player? Is it the unit that you have "got" by whatever means? Can it be either, or both? I cannot get it to work...

 

Sorry for so much bother with this.

 

``self`` is an object. The object making the call, in fact.

 

So, if your object is ``foo`` and you call method ``bar``:

 

foo:bar()

 

in the body of the function ``bar()``, ``self`` will hold a reference to ``foo``.

 

https://www.lua.org/pil/16.html

  • Like 1
Link to comment
Share on other sites

``self`` is an object. The object making the call, in fact.

 

So, if your object is ``foo`` and you call method ``bar``:

 

foo:bar()

in the body of the function ``bar()``, ``self`` will hold a reference to ``foo``.

 

https://www.lua.org/pil/16.html

 

 

Ah, OK, I see. Bit like the Lua version of the this pointer in C++. Here was I thinking it was a specific "hook point" of the DCS scripting engine.

 

Sorry.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...