Help fill the CMANO Entries! See the 2018 Contest for more details. More edits. More quality. More chances to win Steam gift cards.

Lua Beginners Tutorial 2

From Weapons Release Wiki
Jump to: navigation, search

To reduce double handling, I recommend you complete this tutorial first.

This tutorial will step you through the process of randomly selecting a course by creating a table of possible courses and randomly assigning one of them to a unit.

OK here we go;

Open a new blank scenario file.

Create a side, 'Side A' is the name I'll be using in the example code.

Add a ship to your new side, type isn't really important. You can name it whatever you like, but in the example below it's named 'Ship 1'.

Q: Based on the presence of the quotation marks and type of data inside them, what kind of value are the ship and side names? A: The ship and side names are strings.

Plot out a course for your ship in the usual manner (press F3, click to plot, press Esc when you're done).

Click back on your ship and press Ctrl+C. This copies the unit name and GUID in a dictionary table to the clipboard, ready to be used for Lua scriting.

Now open the Lua console; Editor > Lua Script Console.

Use the dropdown function list to find the ScenEdit_GetUnit() function and insert it into the console (or you can just type it in). Now click between the two brackets (if using the insert function drop down, select the word 'table') and press Ctrl+V. Your console input area should look something like this:

1 ScenEdit_GetUnit({name='Ship 1', guid='afabee7b-7dc3-4101-a5b9-4f288b21b16b'})

The GUID will be different, and the name may be different depending on what you named your ship.

Remember from the previous tutorial that we can run this and not much will happen, because the output that is generated by the function we used is actually not being used for anything. Let's change that.

Make the necessary input to your console so it looks like this:

1 Ship_1 = ScenEdit_GetUnit({name='Ship 1', guid='afabee7b-7dc3-4101-a5b9-4f288b21b16b'})
2 print (Ship_1.course)

Click 'Run' and you should get an output similar to this (the latitude and longitude values will obviously be different unless you happened to pick the exact co-ordinates I did)

1 { [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.850046518263, latitude = -33.5171769441731 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 } }

So here we can see that we've retrieved the plotted course from the ship. It's formatted into an array of nested dictionaries. Remember when I said that tables can be really powerful in the last tutorial? We're about to brush up ever so lightly against the power of tables.

Now, we're going to make a script where we have three different possible courses for a ship which are randomly chosen. Using the technique above, create two additional ships (for a total of three), create courses for those ships--these will be the alternate choices--and assign each ship to a variable (i.e. Ship_2 and Ship_3 in addition to Ship_1 above). Note that the actual position of the ship doesn't matter, we're just working with the courses here.

Your console should look something like this:

1 Ship_1 = ScenEdit_GetUnit({name='Ship 1', guid='afabee7b-7dc3-4101-a5b9-4f288b21b16b'})
2 print (Ship_1.course)
3 
4 Ship_2 = ScenEdit_GetUnit({name='Ship 2', guid='b4060416-5dbe-474a-9a94-de18ea047d4e'})
5 print (Ship_2.course)
6 
7 Ship_3 = ScenEdit_GetUnit( {name='Ship 3', guid='fad3dddf-a534-4a15-9c51-978c5db36c85'})
8 print (Ship_3.course)

Now that we've got the course data, there's a myriad of ways we could use it to implement the functionality we desire. I'm choosing a method that is simple and easy to explain. There are other ways to do this with less keystrokes, but they require a deeper understanding--and the end result is the same.

First we're going to clear the output area of the Lua console. Select all the previous output (i.e. the uppermost field in the Lua console), and press delete or backspace to clear it. This functionality will make your life a lot easier when you're working with long pieces of code in the future. Next, clear the 'Echo input script on result text' checkbox. With that box unchecked, we will just see the pure output without any of the input displayed.

Now, click run and something similar to this should appear.

1 { [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.850046518263, latitude = -33.5171769441731 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 } }
2 { [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 } }
3 { [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 }, [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 }, [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 } }

Ok that looks quite intimidating. Lets break it down. What we have here is three seperate tables, none of which are assigned to a variable. Each table is an array of dictionaries, meaning it is a numbered list of seperate lists of keys and values. In the above example there's 3 seperate lists of keys and values in each table. Sound confusing? Let's look at it a different way.

Thankfully, Lua allows us to format code to make it easier for humans to understand. Below is the same code formatted in a style that makes it easier to comprehend:

 1 { 
 2 	[1] = { 
 3 		TypeOf = 'ManualPlottedCourseWaypoint', 
 4 		longitude = 155.850046518263, 
 5 		latitude = -33.5171769441731 
 6 	}, 
 7 	[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 }, 
 8 	[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 } 
 9 }
10 
11 { 
12 	[1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 }, 
13 	[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 }, 
14 	[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 } 
15 }
16 
17 { 
18 	[1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 }, 
19 	[2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 }, 
20 	[3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 } 
21 }

See how the use of seperate lines and indentation makes it easier to understand what's going on? The above code functions exactly the same as the first example, but is much easier to read. I've broken down the first value in the first table onto seperate lines to aid visualisation. You can do this for each value, but for the sake of space I've only done it for one here.

So we have three tables that are each pretty much the same, except for differing values in their nested dictionaries. As you have probably guessed, these are the coordinates of the courses we plotted just moments ago.

Now, we are going to put these three seperate tables into (yet another) table. So it will be a table of tables of tables. You can nest tables in Lua to your hearts content. There may be technical limits on it but they are well beyond anything you would reasonably need to use. To put these tables into our table, we're going to add a curly brace at either end of our pasted output, and then we're going to assign the whole thing a variable so we don't need to keep typing out all those characters over and over.

Add curly braces encapsulating the course tables as described above, and assign your newly created table (of tables of tables) to the variable Courses. Because we're now making these three tables into values in an array, we need to seperate them by commas. After each curly brace closing a table, add a comma. Your code should look like this (It's a good habit to put a comma after every closing curly brace, they don't cause errors if they're not necessary but if you need one and it's not there you'll get an error every time):

 1 Courses = {
 2     { 
 3         [1] = { 
 4             TypeOf = 'ManualPlottedCourseWaypoint', 
 5             longitude = 155.850046518263, 
 6             latitude = -33.5171769441731 
 7         }, 
 8         [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 }, 
 9         [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 } 
10     },
11 
12     { 
13         [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 }, 
14         [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 }, 
15         [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 } 
16     },
17 
18     { 
19         [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 }, 
20         [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 }, 
21         [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 } 
22     },
23 }

Now to make use of our Courses table, we're going to use the math.randomseed, os.time and math.random native functions as we did in the last tutorial, but this time we're going to add in a special operator that returns a table's length.

Q: In the above example how would you print the latitude of the first waypoint in the first possible course? A: print (Courses[1][1].latitude) Q: In the above example how would you print the longitude of the second waypoint in the third possible course? A: print (Courses[3][2].longitude)

Enter the following into your console:

 1 Courses = {
 2     { 
 3         [1] = { 
 4             TypeOf = 'ManualPlottedCourseWaypoint', 
 5             longitude = 155.850046518263, 
 6             latitude = -33.5171769441731 
 7         }, 
 8         [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 153.741376378315, latitude = -36.1508633184308 }, 
 9         [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.425106497074, latitude = -37.2909687028215 } 
10     },
11 
12     { 
13         [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 157.717682505691, latitude = -33.2927324936719 }, 
14         [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.325874940814, latitude = -36.4839544542511 }, 
15         [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 151.927488601182, latitude = -38.078976329408 } 
16     },
17 
18     { 
19         [1] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 154.867658367801, latitude = -34.5840468003736 }, 
20         [2] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 155.244253952917, latitude = -36.8905890685924 }, 
21         [3] = { TypeOf = 'ManualPlottedCourseWaypoint', longitude = 158.688668850101, latitude = -38.822983934233 } 
22     },
23 }
24 
25 math.randomseed(os.time())
26 randomCourse = Courses[math.random(1,#Courses)]
27 ScenEdit_SetUnit({guid=Ship_1.guid,course=randomCourse})

Click run and observe that the course of Ship 1 changes randomly between the three possible courses we plotted earlier.

But how does it work? We've already covered how our table of tables of tables works so I'll spare you from a repeat of that, but lets go through what the other three lines of code do.

1 math.randomseed(os.time())

First we set the random seed to the current operating system time. See the first tutorial for an explanation of why this is important.

1 randomCourse = Courses[math.random(1,#Courses)]

Now we define a new variable (randomCourse) with one of the arrays of the table Courses. Remember from the first tutorial that arrays are referenced with square brackets, and that the math.random function returns a random number between your chosen floor (1 in this case) and ceiling (#Courses). But #Courses isn't a number, you say! #Courses returns the number of items in an array, so it is actually treated as a number. We could have put the number 3 in and it would work, but using the # operator gives us the flexibility to add as many (or remove as many) items from the array in the future as we like, and the code will adapt and work regardless.

Q: For the array Example={'A','B','C','D','E'} what would #Example return? A: 5 Q: How could we print the second item in that array? A: print (Example[2]) Q: How could we print the last item in that array? A: print (Example[#Example])

1 ScenEdit_SetUnit({guid=Ship_1.guid,course=randomCourse})

Now we've randomly chosen a value from our table (i.e. one of the tables describing a course), we use the ScenEdit_SetUnit function to assign it to our example ship. Because we assigned the randomly chosen table to the variable randomCourse we can simply put randomCourse in the course field (value is the proper term, but field makes more sense in this context) of the SetUnit function.

Congratulations, you just wrote a script that randomly chooses a pre-plotted course and assigns it to a unit.