LUA Scripting Guide
for Blitzkrieg® Maps




by kaoz MMXI

 
 
  01. Introduction
02. Map Structure
03. Lua Basic Aknowledgements
04. Setting Map Markers
05. Objectives
06. Win or Lose
07. ScriptID

08. Area's
09. Start Commands
10. Reinforcements
11. Aviation
12. Weather
13. Variables
14. A Few More Tricks

 


 
 

01. Introduction

This guide is an attempt to make the Lua Script file, added to a Blitzkrieg map, understandable for mappers. It is not an explanation of the script language itself. Therefore, all Lua references are only in relation to a Blitzkrieg map.

This guide will show a lot of examples, but it does not claim to hold all the answers and/or solutions. Undoubtedly, more experienced scripters could come up with a thousand more ingenious possibilities, however, for the beginner, none of these make it easier to understand. The given examples in this guide, however, will add flavour to a map, because even with a simple script, the map possibilities are still interesting and providing more fun to play the map.

Make it easy on yourself and use the program SciTE to create or open Lua files; not only does it provide a recognizable icon to your Lua files, but through the use of different colours, the script simply shows more lucid. Also included, is a search and replace function that come in very useful. You can download it here: SciTE

Included in this guide, are also explanations that handle about map making, rather than Lua, but I consider these essential, because they are needed to see the complete picture.

I would not have been able to create this without those who created earlier guides. Therefore, I need to thank hitandrun, [BKP], Wespex, Rémy, Tangram and Leon. Besides, I studied and learned a lot from other Lua files, therefore, I would also need to thank Dimitry M., Kristallagent, CC_Commander, Milknova, Zigfrid and so many others.

Return to index

 
 

02. Map Structure

Obviously, there's two important things to create a map: the MapEditor and a Lua script.

The MapEditor is used to create this map graphically, to place objects and units, set planes and map tools, create reinforcements, add start commands and so on. The map is saved as a bzm-file or xml-file in the folder: Blitzkrieg\Run\data\maps. In case of a mod, this would be: Blitzkrieg\Run\Mods\MyMod\data\maps.

The Lua-file is used to create functions, conditions, counters, troop reinforcements and behaviors for the map that cannot be achieved through the MapEditor. This Lua-file also needs to be saved in the folder: Blitzkrieg\Run\data\maps. (Admitted, you could put this file somewhere else and link to it, but keeping the map-file and lua-file together gives you less headaches afterwards).


The Lua-file must be attached to the map through the MapEditor.
To attach this file, in the MapEditor, press the Set Script File button and browse to the specific Lua-file.


A third important thing to finalize the map, is to create a folder in the Blitzkrieg\Run\data\scenarios\Custom\Missions directory with the name of the map. In this map are placed the txt-files for the ingame objectives and one 1.xml-file that holds map info, map settings and map markers. These files can be created with the ResEditor, but can also be copied from an existing map and then changed.


Make sure to save the txt-files in Unicode format, if not, it will only show square digits.
Open txt-files and 1.xml-file from existing maps to learn from it!

Return to index

 
 

03. Lua Basic Aknowledgements

Lua scripting allows you to use some powerful tools that bring action to a map. The main tool being a function, which will "do" something. Within a function, you can start another function or set a condition and moreover, various functions after the condition. This way it is possible to let specific things happen, accordingly to the player's or AI's behavior and that's where it becomes very interesting.

Every Lua script needs a initializing function; the function Init().
Look at it as if it's the ignition of the script: when the map loads in the game, it will always start reading this (regardless of where this is placed within the script).


In the above picture, the function Init() will start the function RevealObjective0 after 1 second. Next, the function Info, will start after 19 seconds. (1000ms being 1 second). The pre-defined command RunScript will call the function only by its title. There are several pre-defined so called keywords for the Lua language itself and several especially for the Blitzkrieg engine. The latter are summarized in Calvin's Lua Scripting Guide (which should always be next to you when you are map scripting) and we'll deal with most of them in this guide. (I sometimes refer to these keywords as commands).

Notice that a script-line ends with a ; (semicolon) and that a function needs to be closed with end;.

Personally, i believe typing a script character by character, is a waste of time and more vulnerable to typos. Use copy/paste and simply change the concerning parameters. This doesn't mean you shouldn't copy without care of course. When a script becomes larger, it's easy to lose focus. For this same reason, it is better to cluster or group the script functions logically.

The Lua language is case-sensitive, meaning that it will see a difference between upper and lower cases. Therefore, writing Function init() will not work!

Using -- (dashes) allows you to put comments in a script. Any line preceded with 2 dashes will be ignored by the engine reading the script. This can also be used to temporarely switch on or off a certain line.


The example above shows a function with the name DebugView that is handy when testing your map. Unlike the function Init(), you can specify the function names yourself, but it is advised to keep this also logical. If the name shows what it does or wants to execute, it just makes more sense.

Let's run through the script above:
The function Init() would start the function DebugView after a second, if it wasn't preceded by the 2 dashes. This is what i mean by switching on/off a specific line. Imagine that it did start; it will first set the Password Panzerklein, which enables other keywords like ShowActiveScripts, ChangeWarFog and God.
After this, DisplayTrace will show the string Test123 in the upper left corner of the game screen. This is used so you get informed whether the script is loaded and running or not.
Next, the ShowActiveScripts() function shows the current functions executed by the RunScript() functions of the script. Again, you get informed in Console mode during a game whether the specific RunScript is executed or not.
Next, the ChangeWarFog is set to player 1 (the AI), so in testing mode, you'll be able to see the enemy movements.
Next, God is set to player 0 and to mode 2, in which the player is invulnerable and the opponents are killed at the first contact. In this example the keyword God is also disabled by the 2 dashes and will not work. Using God mode can be handy in the beginning of testing maps, but it is advised to test in normal mode in later stages also, especially when you need to test balances in strenght.

Notice that, the function DebugView() uses the keyword Suicide(). Unlike the function Init(), all other functions need this to prevent the function from re-executing itself infinitely.

When a function is made to check a specific condition, you need to also close this condition with another end;.


The above function ToLose states that if the player 0 has less than 5 units, then a screen message will be displayed and another function Lost will run after 9 seconds. The if/then is a condition within the function ToLose. From the moment this function has started, it will check the keyword GetNUnitsInSide and proceed once the condition is true, in this case less than 5 units. But for now, remember that with a condition you need another end;.

Return to index

 
 

04. Setting Map Markers

Okay, imagine you, me or we have created a map with the MapEditor. So we have a .bzm (or .xml) file in our maps folder. (Always keep a backup copy in case something happens...!). Now before starting to script the .lua file, you will probably have a good idea what the objective(s) of your map should be like. To describe the objective(s), set map markers for them and setting up the map for the BK engine to find it, we need the files in the folder Blitzkrieg\Run\data\scenarios\Custom\Missions\MyNewMap.


You'll see a few txt-files and one 1.xml file.
What is written in the header.txt is what will appear as a title in the game missions overview, so you want to keep this short and informative. Long titles make the missions list unreadable.
The description.txt is used to describe the map's background, obviously. It is however, only shown in the game when it is part of a chapter. So even there's no real use of it in a single mission, you should still describe your map as some players might open and read the file to get a better idea what the map is about.
Same for the subheader.txt: it isn't really shown in the game, but it is mostly used to write the author's name into it.
Then there's the objectives: in this example MyNewMap, there's 2 objectives, being 0.txt and 1txt. These objectives have both a title or header, being 0h.txt and 1h.txt.


So, if you need more objectives, keep counting and create 2.txt - 2h.txt - 3.txt - 3h.txt and so on.

Now, let's take a look to the 1.xml. This file can be made with the ResEditor, but it's easier to copy one and adapt it.
In xml-language, you will mainly see tags, like <base></base>. Some tags are placed inbetween tags and some tags require a reference to a specific file. Don't worry if you don't understand xml, this is just how it works, but you should be able to read it and understand which particular reference you need to change.

Everything between <History></History> tags isn't really necessary. It only holds information about the path, time and date, author, etc. when the file was created (through the ResEditor). You could if you want, change the date and author to your desire.

On the other hand, the tags between <RPG></RPG> are very important! Let's look at the first part:


So when the game loads, it will load and read this 1.xml file. The path between the <HeaderText></HeaderText> tags needs to point to the specific header.txt file in your mission folder. If, for example, you have copied this 1.xml and you have a mission folder called Belgium1940, then you simply change all the MyNewMap's into Belgium1940.


Okay, let's move on further through the xml:


The <FinalMap></FinalMap> tags are also very important and refer to the name of your map, being the .bzm file. The game will look in the maps folder and search for the name. If, for example, you have a map Ardennes.bzm, you refer to it in the 1.xml as <FinalMap>Ardennes</FinalMap>.

Next, you can set the music for the map. Some tags, like these, have items. If, for instance, you want more music, you could add items, so it would look this:


In case you don't want any music, just leave it empty between the tags, like <CombatMusics></CombatMusics>. Or you can also write <CombatMusics/> which is the same, but shorter than <CombatMusics></CombatMusics>. It's not of that great importance though.

Next important part of the 1.xml are the objectives:


So again, you will see reference paths to the txt-files in your mission folder. Again, change the MyNewMap into the name of the mission folder.

As you can see, these 2 objectives are items between the <Objectives></Objectives> tags. The item Secret can be set to 0 or 1, where 0 will show the objective from the beginning of the game, in contrast to 1, that will keep the objective secret until you call upon it through the lua script. If you need more objectives, copy/paste more items and change them.

Now take a good look to the part that says: <PosOnMap x="96" y="419"/>
These coordinates are used to place the map marker on the minimap for the objective. In case you don't want any map marker, but still the objective, simply set their value to zero.

How to find the correct coordinates for your map markers?
These could be set with the ResEditor, but there's an easier way. When your map is loaded in the MapEditor and in the editor, you would press the Create button on the bottom left, a minimap will be created. These files are then created in your Blitzkrieg\Run\data\maps. There you will find 2 .tga files and some .dds files. Open MyMap_large.tga with Photoshop or Gimp.


This large .tga file is always 512 pixels on 512 pixels, no matter the measures of the actual map. In the picture above, you see a .tga loaded in Photoshop. Going over the picture, the mouse pointer will show the exact xy coordinates in the info panel.

So logically, <PosOnMap x="0" y="0"/> would be the upper left corner, <PosOnMap x="512" y="512"/> the bottom right corner and <PosOnMap x="256" y="256"/> the middle. There is however, a small glitch as many times I noticed it wasn't shown exact. To solve this, you just add 8 or 10 pixels to the value and you get a better result. Thus <PosOnMap x="266" y="266"/> would be the exact middle (shown on the minimap in the game that is). You will notice this glitch very clear when you for example want a map marker upon a bridge or a house. In Gimp or Photoshop you get the exact xy coordinates, but in the game the marker is not exactly on top of the bridge or house. Like I said, add 8 or 10 pixels and it will shown correct.

Return to index

 
 

05. Objectives

The following picture shows a basic example with one objective and one reinforcement.

Let's "drive" through the script:

At the bottom, the function Init() starts the function RevealObjective0() after 1 second and function Info after 19 seconds.

Jump to the function RevealObjective0() and notice it will first set the keyword ObjectiveChanged to (0, 0) and then start the function Objective0(), after again 1 second.
For the ObjectiveChanged: (0=objective#, 0=not accomplished)

From the function RevealObjective0(), let's jump further to the function Objective0().
This function holds a condition: if all units from ScriptGroup 119 of player 1 (enemy AI) is less or equal to 1, then the ObjectiveChanged is set to (0, 1), thus accomplished, and next, the keyword LandReinforcement will start and drop units with GroupScriptID 0 into the game.


In later chapters, we'll go deeper into reinforcements and ScriptID's. For now, if you were able to follow and read the script, then you should have gotten a basic idea of how a Lua script is running. Which is only very logical in fact.

So, let's try more objectives:

This script has 3 objectives that follow one another. Setting the secrecy to the flag (in the 1.xml or Mission Editor), the next objective and flag will only appear after a particular objective is completed.

Again at the bottom, the function Init() will start the function RevealObjective0() after 1 second.
Next, the function RevealObjective0() sets the ObjectiveChanged and then runs the function Objective0() that states if the units with ScriptID 200 of player 1 are equal to zero, then the ObjectiveChanged is accomplished and the next function RevealObjective1() will start running after 19 seconds.

The same happens for the second objective: function RevealObjective1() sets the ObjectiveChanged of objective #1 to not accomplished and then runs Objective1. When enemy units of ScriptID 201 are all dead, the objective is accomplished and function RevealObjective2() will be called.

The last objective states that if all units of player 1 in Area "totalMap" is less or equal to 3, then player 0 will win.


Of course, you don't want the player to wait 19 seconds for the next objective, but it should show that you can play around with timings. And alternatively, in case you don't want the objectives one after another, you can start more or all of them at the same time, whenever you like this to happen.
In the following example, when the objective is reached, it will set off 3 other objectives with different time intervals.


In fact, you can start various functions at various time intervals:


At this point, you should start to see the possibilities that you are able to call any function at a specific time whenever you desire, in this case, after an objective is reached.

In case you want all objectives at the start, you could also script:


or even:


Do not "overscript" the function Init() though; if you would script a dozen RunScript's or more that would start running at the same time, you might ask for trouble. Avoid script failures and try to set up a logical time schedule.

Return to index

 
 

06. Win or Lose

The 2 keywords Win and Loose of course are of great importance in determining the game's outcome. Determining when a player should win is mostly very easy, but the Loose command, imho, is being very underestimated by most mappers. True, some maps may not need this at all, but personally I think that if the player has a chance to be beaten by f.e. an AI enemy attack, the game becomes more challenging.

Let's imagine a map where you have to defend a certain Area and capture one. Player 0 has units with ScriptID 101 at the Area "warehouse" and units with ScriptID 100 to attack the Area "station". The enemy player 1 has units with whatever ScriptID and some of them will attack the Area "Warehouse".

The function Init() starts the function ToWin() and function ToLose(). Player 0 will win if more or equal to 6 of units with ScriptID 100 are in the Area "station" or will lose if less then 6 units with ScriptID 101 are present in the Area "warehouse".


Or imagine a map where the player will lose if the general of his forces gets killed.

The script doesn't show everything, but the function Trigger01() states that if unit with ScriptID 19 of player 0 is equal to zero (thus killed), then a screen message will explain why. The keyword Loose is put in a separate function and only starts after 7 seconds, so the player gets the time for reading the onscreen message.


Or in this example, the player will lose if he has less then 5 units left.

Of course, this example also doesn't show the complete script. The function Trigger01() must be called upon into the function Init() or somewhere else in the script...


How to create AI enemy attacks and Area's will be explained in later chapters, but I wanted to focus on Win/Loose first. Experiment with these to add spice to your scenario.

Return to index

 
 

07. ScriptID

Another important thing is the ScriptID. In the MapEditor you can give any unit, building or object a ScriptID, which can be referred to in the Lua script. Double click to open the Properties window of any object. By default, the value -1 is given by the editor.


There exists a suggestion to use the ScriptID's as follows:
ScriptIDs 0 - 999 for terrain objects and buildings
ScriptIDs 1000 - 1999 for AI (enemy) units
ScriptIDs 2000 - 2999 for player units
However, this is not a written law, instead it is an advise to maintain order over chaos.

From the moment you have defined ScriptID's, you can do remarkable things in the Lua script:

The function Trux() will change the units with ScriptID 200 to player 0. You are able to let units switch from sides, player 0, enemy or neutral. I used this function a lot where the player gains enemy trucks when a specific area is taken.

The function FrostBite() will damage the object with ScriptID 100. Using the following parameter 0 will cause to completely destroy it. This object can be anything, a tank, a squad, a building, a group of objects, etc.

The function EnterHouse() will give a command to the (infantry) unit with ScriptID 300 to enter the house/building with ScriptID 10.


So, at this point, you should understand that ScriptID's are a necessary thing in order to be able to let things happen to them. This will bring action to your map in every way.

Return to index

 
 

08. Area's

Let's go back to the MapEditor for a moment; on the left side you'll see the Map Tools panel. With this tool, you can draw retangular or round Area's upon the map. Hold the left mouse button and use the keyboard arrows to enlarge the Area, if needed. When you release the mouse button, you'll be prompted to set a name for the Area. Take care, because this is case-sensitive!
Later on in the Lua script, you'll be able to refer to these Area names.



In earlier examples, you have already seen some examples where an Area was used. It's really handy to create triggers and thus things will happen from the moment a specific unit or units come in or leave a certain Area.

Here are 2 more examples:

The function Objective2() states that if more or equal than 2 units with ScriptID 100 or more or equal than 2 units with ScriptID 102 are present in Area "Fuel Dump", then the objective is reached and it will start to rain ("RainyDay") after 30 seconds.


The function Trigger08() states that if more than 0 units from Player 0 are present in Area "zone1", then a command will be given to unit with ScriptID 111 (which in this case is a artillery gun) to start shelling the Area "zone1". After approximately 2 minutes it will run the function HoldFire() and stop shelling.


These examples should give a good idea of what is possible with Area's in combination with the amount of units in or out them. There's also a few keywords/commands that return the number of mines, fences and trenches from a specific Area. Check out Calvin's Lua Scripting Guide for this.

Return to index

 
 

09. Start Commands

In the MapEditor, one can use the Add Start Command function to command a certain, selected unit or even a group.
Select a unit, click on the icon and the Unit Start Command Property window will open.



From a drop-down list, there's quite some choices of command. Select one and next, with the window still open, you can click on any spot in the map to set the x,y positions (notice the pink circle). Or you could set these manually if you'd like.

You are able to set multiple commands in a row.


Use these commands logically; some commands work only in combination with a specific unit. Although you can set the command, it might not work. A tank cannot heal infantry and a truck cannot use a spyglass, and so forth.

Some of these commands can also be achieved through a Lua script, but not all and vice versa, there are commands within Lua that cannot be found in the Add Start Command from the MapEditor. It demands a little practice to know what is where. Again, check out Calvin's Lua Scripting Guide for the possibilities in Lua.

In Lua, the keywords Cmd and QCmd are used to command specific units.
Pre-defined actions like MOVE_TO, SWARM_TO, CALL_BOMBERS, etc. are used to specify the command. These actions are connected to numbers, which can also be used instead. All actions are summorized in Calvin's Lua Scripting Guide.

Let's show a few examples:

Imagine you have a tank with ScriptID 100. From the moment you call upon the function Attack01(), the Cmd will move the tank to the given coordinates. Next, the QCmd will let the tank swarm to the given coordinates and finally the next QCmd will let the tank attack the unit with ScriptID 200 .


Here, I have changed the actions with their corresponding numbers, so this function will do exactly the same as the one in the previous example.
MOVE_TO = 0
SWARM_TO = 3
ATTACK_UNIT = 1


This example shows a simple function that calls an enemy scout plane with ScriptID 999. It will fly and scout (action = 21) to the given coordinates in the different command lines.


This example shows, let's say an infantry unit with ScriptID 19.
After 1 second, it will enter the building with ScriptID 1000.
After 2 minutes, the same unit will leave the building and go to the given coordinates.
From there, it will start to swarm to the new given coordinates.


All these commands can be set for the AI enemy, but also for the player. However, a player can chose to select the specific unit and change its purpose; in that case, any given command will get cancelled. It may also happen that you command a plane and then it suddenly starts to rain, cancelling any given commands to it.

At this point, you should have a serious idea of command possibilities. Again, these will bring action to your map. Beware although and always test your given commands. In a lot of cases, the given commands might react in the game different as expected. If you, for example, connect a trigger to a certain action and when the action gets blocked or cancelled in some way in the game, your trigger will also not work anymore. The more complicated you make this, the more testing it will need, from various points of view.

Return to index

 
 

10. Reinforcements

Let's return again to the MapEditor, where on the left side, you'll notice the Reinforcement Groups panel.

First, click on New Group and the Reinforcement Group ID window opens. There, set the number you desire and click ok. In this picture, I have already made a group called 0 and the Reinforcement Group ID window shows I am making a second called 1.

When you select a group in the upper window, like Group N:0 which is blue lined, then in the lower window, you can click the Add group with scriptID button. As the picture shows, I have already added ScriptID 1000, ScriptID 1001 and ScriptID 2000 to this group.

So, it is possible to create one group that gives reinforcements to both the player and the AI enemy. In Lua, you'll need to use the keyword/command LandReinforcement(0). The parameter of the command refers to the GroupID, in this case 0. Thus, not to the individual ScriptID's!

If you have a map where you have lots of groups of units that you want to "control" more separately, you could give the same GroupID like the ScriptID, which makes it a little easier to remember who's who when you are scripting. So, GroupID 1000 holds the units with ScriptID 1000, GroupID 1001 holds units with ScriptID 1001, and so forth.
Then in Lua, when you use LandReinforcement(1001), you see the concerning units more directly.

By the way, clicking and checking the small white square before Group N:0 will hide all units belonging to that group from the map in the editor, which is handy in some cases.


We've seen the command earlier in an example, but here's a few more:

When function Ambush() is running, it will check the Area "ambush" and if there's more than 2 units of player 0 present, then the reinforcements of GroupID 0 will immediatly take place.


In case you want to have more control over the timing of your reinforcements, it's better to put the LandReinforcement() in a separate function, like in the example, function Reinforce0 and function Reinforce1.

When function Objective0() is reached, it will run RevealObjective1 after 1 second. Next, LandReinforcement(1001) will happen after 3 minutes and LandReinforcement(1002) will happen after 5 minutes.


There is one thing you need to pay attention to, when you combine actions to reinforcements. Reinforcements do take some time to take place. If a group of tanks would land, they'll do this in an unpredictable way, one by one. It will not land all the tanks at the same time.
Have a look to the following function:

This function makes perfect sense, but will perform poorly in the game. So, imagine that group of tanks with ScriptID 1001; they will land, but the following command Cmd will only apply to the first landed unit. Because it takes time for the other units to land, they will completely miss the following command and they won't do anything.


One way to solve this, is using the Add Start Command in the MapEditor and add it manually. These commands work fine from the moment the units land.

However, if you need to set the commands in Lua, then put the command in a separate function, which takes place after a certain amount of time (at least the time that is needed to land all concerning units).
So, in the example, when function Trigger_01() is reached, it will land that group of tanks with ScriptID 1001 and after 1 minute it will start the function Attack_01() so that the whole group of tanks start swarming to Area "zone1".


Well, that's pretty much it concerning reinforcements. There is still the keyword DeleteReinforcement(), which you obviously, can use to remove reinforcements with GroupID x.

Return to index

 
 

11. Aviation

Aviation works a bit the same like reinforcements. Back again, in the MapEditor, pressing the little plane icon in the menu, will enable you to set plane types, appear points and such. You ought to do this before anything else, I think btw.


Once that is set, you have a little more options to "control" the aviation through Lua: some Lua script commands let you play with their appearance and behavior.

In this script, the function Init() disables all aviation (-1) for both parties and starts function Objective0() after 1 second and function AirForce() after 2 minutes.

The function Objective0() states that if more than 2 units of player 0 enter the "facility" area, then both players receive recon planes (0).

Next after 2 minutes, the function AirForce() will check the "facility" area and if there are more than 2 units of ScriptID 19 in there, then both parties receive paratrooper planes (2).

For all the iTypes of Aviation, please refer to Calvin's Lua Scripting Guide.


In this next example, both parties start with no aviation.

After 10 seconds, the function BomberPlanez() will enable this type for player 1 and fly to the given coordinates in the Cmd command.

50 seconds later the function Attackplanez() again will enable attack planes for player 1 that fly to the same coordinates.

iAction 19 = CALL_BOMBERS
iAction 36 = CALL_GROUND_ATTACK


I've used this one in maps where the player has to conquer an enemy airfield. It would only be logical that from that moment, enemy aviation becomes disabled.

The function Objective_00 (the given function name may seem a little odd, but never mind that) states that if there is less than 1 enemy in the "airport" area, then aviation will become disabled for player 1.


Return to index

 
 

12. Weather

Setting the weather is really easy in Lua, and especially handy when you need good weather to call (enemy) planes or when you need rain in case you surely don't want any aviation to happen (for a specific time).

I often use these 2 functions because they give me exactly what I need.

When I call upon function Holiday(), it will switch the weather to good (0). It will NOT switch the weather automatically (0), so sunny days remain infinite until I call upon function RainyDay().

When I call upon function RainyDay(), it will switch the weather to bad (1). And it will switch the weather automatically (1), back to random.


This works fine for me, but you could change it any way you want.

Return to index

 
 

13. Variables

In Lua (as in other script languages), you can assign a decimal, an integer or a string value to a global or local variable. Using a function, you can then check whether it's value corresponds to a certain condition or not. And this can be extremely handy!

Global means that this variable is set, covering the whole script. Local means that the variable is set and covering a part of the script. I can't explain variables fully detailed here, because I don't consider myself such a great scripter and so this task isn't up to me really. However, I hope the following examples may show some of the possibilities.

In this script example, each time an objective is reached, a SetIGlobalVar() with a particular name (temp.template00.objective.1) is given the integer value 1.

Next, using the GetIGlobalVar(), the function ToWin() will check if all variables are equal to 1 (and then the player will win).

Again, the script is not complete and of course, the functions need to be running/triggered in order to work!


In this example, the variable is being used as a counter.

Setting a local variable i, one can add a +1 value to a global variable ("numbMissionDone", i).

So, when the first objective is reached, it will take the local i (which is 0). It will also take the global variable (which is also 0) and add +1, thus, it will set the global variable to 1.

After the second objective is reached, it will again take the local i, but it will also get the global variable (which is now 1) and add +1, so now the global variable is 2.

When the function ToWin() realizes the value of the global variable is 2, the player will win...

I know, when you see this for the first time, it seems a bit like rocket science, but if you practice this more, you will get to understand it.


Return to index

 
 

14. A Few More Tricks

In this final chapter, you'll find a few examples of more complex situations or goals, achievable through Lua. These were not invented by myself, but I have adapted them and I often use them when a particular situation asks for them.

This script shows how to use a neutral plane (which will not get shot down by the AI enemy) and drop a para-squad that will change sides from the moment it enters a specific Area.

The function Init() will set the global variable "ParadropSquad.ScriptID" to 2019, so the para-squad will have ScriptID 2019 right from the start.

Two seconds later, a transport plane with ScriptID 999 of player 2 (neutral) will paradrop (22) the squad at the given coordinates. And calls the function MoveIt().

GetUnitState() will check whether unit(s) 2019 are waiting. If so, they receive the command to move to the "LandingZone" area.

The function ChangePara() will check if units with ScriptID 2019 are present in the "LandingZone" area, and if so, it will change the player side of with ScriptID 2019 to 0.

Thx to Leon.


This script is again, not complete, but imagine the functions are running.

In this scenario, we have an enemy group of units with ScriptID 101. They have commands added and they are attacking the player within an Area "Town". When they are all dead, they will respawn and start attacking again. Look at the function Respawn_00() and function Reinforce_00() and notice they keep on triggering each other infinitely.

However, from the moment where the player has more than 3 units (thus 4), the KillScript() will stop the respawning of the enemy units.

You can use the KillScript() for other purposes as well; it can stop any named function.

Thx to GordonCZ.


In this scenario, we have a fort that needs to be defended by the player, while the AI enemy is attacking with a group of units with ScriptID 100, 101, 102.

What's important here, is the elseif. The objective may have two outcomes; if the player has no more units within the "fort" area and the AI enemy has more than 3 units in the "nibeiwa" area, then the player will lose and the objective has failed (0, 2).

Otherwise (elseif), when all AI enemy units with ScriptID 100, 101, 102 are less than 1 (meaning dead), the objective is reached (0, 1) and the player wins.

Thx to runrum for pointing at the 2 Suicide()'s.


This function MissionTimer() can be used to display the time and so call upon the global variables when you need to time something.

Thx to danzig70.


The keyword AskClient("SetCamera(x,y)") will move the camera view to the given coordinates. To move the camera to a more or less correct point, try to divide the coordinates seen in the MapEditor by a value of 1.4 (meaning that if the place is located in 3000,15000 in the MapEditor, then divide both values by 1.4 and you will get coordinates 2143,10714 for the script file).

Thx to [BKP], GordonCZ, cc_commander, runrum.


Return to index

 
 


created by kaoz - MMXI