|
Post by Quintaxel on Jul 30, 2017 15:33:02 GMT 1
To script it's important to understand how variables are used in Lua. So what is a variable? In programming, a variable is a value that can change, depending on conditions or on information passed to the program. As I said earlier we can use scripting to get information from the game engine in general or the map in particular. Let's look at this in practice. Suppose we want to know the number of units that are on the map belonging to the AI then this number would vary depending on the map and/or the moment the units are counted. The number of units would be a variable. So in human language we are asking the BK engine to do the following; Return the number of AI units on the map as a the variable aiunits. Fortunately BK has a function for this. GetNUnitsInParty (iparty);Where Iparty is 1 for the AI player. the function would be; I've added a little demo map here to show what happens. When you run the map you will see the number of AI units displayed in the top left corner at fixed intervals. Kill the AI units and see the number of AI units that are stored in the variable aiunits drop know that when counting the units using the function GetNUnitsInParty (iparty); a) A squad returns the number of men it composes b) Artillery including gunners counts for 1 More in the next post .
|
|
|
Post by Quintaxel on Jul 30, 2017 16:12:50 GMT 1
Taking a look at the script Lines 15The function Message () is run 2000 miliseconds after the game starts. RunScript ("Message",2000,1);
Now RunScript will make the function Message () only run once because we can add an extra argument to the RunScript function. This argument is the number of times we want the RunScript function to be executed. If we change the argument to let's say 3 RunScript ("Message",2000,3);
The the function Message will be run 3 times namely at 2000 miliseconds, 4000, miliseconds and 6000 miliseconds. Lines 1-8Nothing new here line 10the BKfunction GetNUnitsInParty (1); will put the number of AI units on the map in the variable aiunits.
You'll notice that there is no Suicide (); before end;
This means that the function will continue to run every 5 seconds (5000 miliseconds) and that is exactly what we want here. In the next post I'll discuss the scope of variables.
|
|
|
Post by Quintaxel on Jul 31, 2017 13:34:54 GMT 1
In Lua scripting we can make a distinction global and local variables. Global variableThe scope of a global variable is the whole script. A global variable does not have to be declared. If we take a look at the scrip then aiunits is a global variable. Its scope is the whole script. This means that the value stored in the variable aiunits is visible to all other functions. Local variablesThe scope of a local variable is limited to the function it's declared in (*) A local function is created using the local statement. (makes sense, doesn't it ) So setting a variable's scope defines how visible it is to the rest of the script. (*) I'm aware that this is not a 100% correct. The scope of a local variable is the block or chunk it's declared in but for practical reasons we can agree for now that the scope of local variables is a function.
Continued in the next post
|
|
|
Post by Quintaxel on Jul 31, 2017 14:06:52 GMT 1
To demonstrate the difference between local and global variables I have made some modifications to the script for counting the number of AI units on the map. You should be able to read this script with was explained in the previous posts but let go through it again. The function CountAiUnitsOnMap () will put the number of AI units in the variable aiunits. The function Init () makes it run every 5 seconds. Contrary to the previous script, the function CountAiUnitsOnMap will not display the variable aiunits on the map but will run the function DisplayAIUnits ()
The function DisplayAIUnits () will simply display a message that it is running and also the display the value of the variable aiunits. As aiunits is global variable it can be seen by both function. Now change line 10 of the script to; local aiunits = GetNUnitsInParty (1); By declaring the variable aiunits as local it can no longer 'be seen' by the function DisplayAIUnits (). Its scope is now limited to the function CountAiUnitsOnMap ()
It's important to understand the difference between local an global variables. Should this not be the case then let me know. Remember that if there is something that you do not understand then it's because I did not explain it well enough. More later.
|
|
|
Post by Quintaxel on Jul 31, 2017 23:25:03 GMT 1
There a couple of other things we need to know about variables before we can continue to script.
Naming variablesThe name of a variable can be composed of letters, digits, and the underscore character but must begin with either a letter or an underscore. Lua is case-sensitive so upper and lowercase letters are distinct. Examples of variables; local i; local Obi1; local What_Ever;Defining variablesVariables can be defined in different ways. Defining a variable simply means to tell the interpreter to create the storage for the variable. As said in Lua global variables do not have to be declared but local variables are by using the local statement. Examples local a;Defines the variable a and declares it as local. Initializing variablesAn initial value can be assigned to a variable in its declaration. This is called initializing the variable. The examples below should clarify ho this works. local a = 10; -- Defines the variable a , declares a as local and gives is the value 10 local x,y = 2,4; -- Defines the variables x and y, declares them a local. x = initialized as 2 and y is initialized as 4 local a,b,c,d = 1,2,3,5; -- Defines variables a,b,c,d, declares them as local. The value of a = 1, b=2, c=3 and d=5 It's good practice to give variables names that are more or less meaningful. If, for example, store the x,y coordinates of a unit with Script ID 100 in two variables then the variables could be named something like this; local xcoord100, ycoord100 = 2250,1300; Now do not worry too much about the theory. As I promised anyone can write a BK script and I'll prove it in the coming posts
|
|
|
Post by Quintaxel on Aug 1, 2017 19:15:16 GMT 1
Arithmetic Operators
If we want to script the we will need to use arithmetic operators at some point. In BK Lua only the following arithmetic operators can be used
`+´ addition `-´ subtraction `*´ multiplication `/´ division
´^´ exponentiation is not possible in BK Lua but we won't be needing this.
Some examples of expression in which arithmetic operators are used
example 1
a = 2 + 4; -- the global variable a is the sum of 2 and 4, so 6
example 2
local x; local a,b,c = 2,3,5; x = a*b-c; -- local variable x = 2 multiplied by 3 minus 5, so the variable x gets the value 1
Note that in the example above the variable x has been declared as a local variable first (local x;). The variable x was initialized, given a value, in the statement x = a*b-c;
In the next post we have a look at relational expressions and then we can put it all to practice in a simple script.
|
|
|
Post by Quintaxel on Aug 1, 2017 19:29:37 GMT 1
Relational expressions In the script we will use relational expression to check if conditions are true are false and make the script do or not do something based upon the outcome of the expression. This may sound like mumbo-jumbo (I think it does ) but it will all become clear in the scripting examples. The rational expressions used in BK Lua are. == equal to ~= not equal to < less than > greater than <= less than or equal to >= greater than or equal to
|
|
|
Post by Quintaxel on Aug 1, 2017 20:01:25 GMT 1
In lesson 2 we have seen the command Cmd(0, iScriptID, x, y); to move a unit with a ScriptID to x,y coordinates on the map. Using the x,y coordinates is fine but there's better way to get control over the movement of units, especially when you want to keep oversight. To do this we'll need to create so called script areas on the map. This can be done in the map editor under map tools. In the image below I've put script areas on the map were the barrels are placed. remember that the barrels were only placed on the map to indicate the different x,y coordinates we wanted the unit to move to. There's a BK function that returns the coordinates of the centre point of a script area ; GetScriptAreaParams ("ScriptAreaName"); will return the x,y coordinates of the script area with the name ScriptAreaNameThis function works with both rectangular and circular script areas. (see image below) Now instead of moving or unit to x,y coordinates on the map we can make use of the function GetScriptAreaParams ("ScriptAreaName"); to get the coordinates of a script area first and then make or the move to these coordinates. Do demonstrate this I've changed the script of lesson 2 Line 8variables x and y are declared as local variables. x and y get the value of the centre point of the script area P1 line 9The sniper gets the command to move to point x, y on the map. Line 10Here we do the same as in line 9 and line 10 but instead of getting the x,y values of the script area first and then move the unit to these x,y values this is now done in a single command. So we can replace lines 9 and 10 with It's not necessary do declare the variables x and y and you do not have to worry about them as. GetScriptAreaParams ("ScriptAreaName"); takes care of the variables of. Line 15
Also here the function GetScriptAreaParams ("ScriptAreaName"); is used to set the direction in which the sniper should look. The map and script discussed in this lesson can be found here
|
|
bb
General
Blitzkrieg junkie (tried to quit several times).
Posts: 1,356
|
Post by bb on Aug 1, 2017 20:07:56 GMT 1
Quint: may I ask you about a pdf?
|
|
|
Post by Quintaxel on Aug 1, 2017 20:16:08 GMT 1
I could wrap things up in a pdf if this is useful. It's more difficult to explain BK Lua than it is to script
|
|
|
Post by marinernl on Aug 1, 2017 20:45:16 GMT 1
Thanks Quintaxel,
Great tutorial.
|
|
|
Post by Quintaxel on Aug 2, 2017 14:10:33 GMT 1
BK scripts will often follow the following flow.
a) Getting information from the BK engine b) Check that information against set conditions, true or false c) Execute commands based upon the condition set in b)
We have already seen some BK functions to get information from the map and to execute a command. To explain how to check conditions I'll build on the script of the previous lesson.
Suppose that we want to script the following;
Our sniper needs to move under the tree following the path set out by the script areas. if the sniper reaches his destination then we want the officer to move straight to the script area called "Zone1" if the officer has reached "Zone1" then we order the sniper to use his binoculars to look in the direction of the farm.
I'll explain how this is translated into a Lua script in the next post.
|
|
|
Post by Quintaxel on Aug 2, 2017 17:37:13 GMT 1
You can find the map and script of lesson 5 herePlease run it and see what happens. I'll explain the script in detail in the next post. The script wraps up what we have seen so far so it is important that you understand how it works.
|
|
|
Post by Quintaxel on Aug 3, 2017 12:40:38 GMT 1
Let's take a closer look at the script. I'll follow the flow of the script. I have posted a printout of the script in the posts following this one. Line 5 to 10
You will have already figured out its possible to add comments to a script. A comment starts anywhere with a double hyphen (--) and runs until the end of the line. As scripts become more complex and/or longer you might want to add comments to the scrip to clarify anything that may be confusing or just as a reminder. I make it a habit of putting the script ID's of units used in the script at the beginning of a script. Line 63 to 65
The function Init () will run automatically when the game start and start the function MoveUnit110() after 5 seconds. Line 13 to 23 MoveUnit110()This script was already discussed. In line 21 the script CheckStatusGrot () starts to run after 3 seconds. Line 22 tells the script it is no longer needed. Line 25 to 33 CheckStatusGrot ()line 26 the BK function Trace ("StrText",params); is used. This function is similar to the DisplayTrace ("StrText",params); but with Trace () function the information is displayed in the console. To open the console press the '~' key. Trace () is very useful when debugging a script. In this case Trace () is used to check the status of the Sniper. Checking the status of a unit can be done using the BK function GetUnitState (ScriptID);We'll get back to this later. Line 27 In line 27 the script will check if the Sniper has arrived in script area 'P6' This is done using an if..then statement. The syntax of the if...then statement is; if [condition] then[Statement] end;so only if the [condition] is met (True) then all script between then and end; will be executed. Important: Each if...then statement MUST be closed with and end;
This is very important and a common error in scripting. Therefore my advise is to use an indentation for if...then statements. Also if you start an if...then statement put the end; statement right after it and fill in the rest later. To check if the sniper has arrived in script area "P6" the BK function GetNScriptUnitsInArea (ScriptID, "ScriptAreaName"); is used. The moment the sniper enters the script area "P6" then the condition is TRUE and the lines 28 to 32 will be executed. This also means that the script will stop running because of the Suicide (); statement in line 31. Line 29 Cmd(9,110); is and action command. 9 is the action code used to stop a unit. We do not want our Sniper to start shooting at the Soviets in the Farm Line 30
The script MoveOfficer100 () starts to run after 2 seconds. As long as the sniper has not yet entered the script area "P6" the condition is FALSE de and everything between line 28 and 32 will be ignored. The script will continue to run every 3 seconds as there is no Suicide (); statement to prevent the function from running again. Line 56 to 61 MoveOfficer100 ()
Simlilar to the function MoveUnit110 ()
Line 35 to 41
Again a condition to check if the officer has reached the script area "Zone1" If the condition is TRUE then line 38 will run function GrotUseBinoculars () after 4 seconds. Line 39 will stop the script with the Suicide (); statement. Line 43 to 48 GrotUseBinoculars ()Nothing new here. Line 46 runs the function TheEnd () after 4 seconds. Line 50 to 54 TheEnd ()Nothing new here. Line 53 stops the function from running again. That's it. The scripts are no longer active as they were all stopped with a Suicide (); statement
|
|
|
Post by Quintaxel on Aug 3, 2017 12:51:29 GMT 1
|
|