5.4 Win/Lose Conditions

Lets make our mission winnable by adding a Win condition. If you haven't given the player any units to start with, do so now (place a couple units on the player's team near the player's start location). Place all of the player's starting units into a Tag (see Section 2.6: Tags Menu). Name the tag "players_units".

Lets say that the player needs to move his troops to a specific spot to win the mission. Create a Region somewhere near the player's start location. Name it "goal". Make it large enough to fit a few units inside. (see Section 2.5: Regions Menu). This will be where the player needs to go to win. You may want to texture or color the area under the region, or place an object there, so you can tell where it is in the game.

Now lets alter the "objective_player_at_goal" objective, so that it will test when the player is in the "goal" region, and give the Win screen when he is. There is a condition type for just this type of thing called "InRegion".

Open "objective_player.cfg". Change the condition statement of the Objective to:


Condition("InRegion")
{
 Region("goal");
 Tag("players_units")
 {
   Amount(0);
   Operator(">");
 }
 Team("player");
}


…and replace the action statement with
Action()
{
 Win();
}


Your objective should now look just like this:
CreateObjectType("objective_player_at_goal", "Objective")
{
 GameObj();
 ObjectiveObj()
 {
   Condition("InRegion")
   {
     Region("goal");
     Tag("players_units")
     {
       Amount(0);
       Operator(">");
     }
     Team("player");
   }

   Action()
   {
     Win();
   }
 }
}



The condition type InRegion calls for several bits of info as you can see. 'Region' is the region to be tested. 'Tag' is which tag will be tested. Associated with the tag is an 'Amount' and 'Operator'. The example above is saying "greater than zero", or in other words "one or more" - "is there one or more object from this tag in the region?". (you can change the Amount and Operator values to suit many purposes. Amount can be any number. Operator is either < (less than), > (greater than), or == (is).

Finally, the InRegion condition type asks for the team. The team will be whatever team the tag is on.

The command to give the victory screen is simply Win()

Now load up your mission in the game. When you move your starting troops into the goal area, you should get the Victory screen. If you don't, go back and make sure you did everything correctly.

Our mission seems a bit easy, don't you think? Let's make a way to lose. Place some enemies near the start location. Place them OUTSIDE THE LINE OF SIGHT of the players units (we will move them in script). Make the enemy force roughly match your player force. Place all the enemy units into a tag and call it "enemy_units". The player will lose if all his units get destroyed before he can reach the goal.

Now we'll edit the AI's objective "objective_attack_player". Open objective_ai.cfg. Replace the current objective_attack_player Objective with this one:


CreateObjectType("objective_attack_player", "Objective")
{
 GameObj();
 ObjectiveObj()
 {
   Condition("TRUE");
   Action()
   {
     ExecuteScript("attack1", "squad.move.tagtotag")
     {
       Op("%.tag.src", "=", "enemy_units");
       Op("%.tag.dst", "=", "players_units");
     }
   }
 }
}


"ExecuteScript" is a command that will execute a pre-made script. "attack1" is the unique name of this instance of the script (you can name it whatever you want, as long as it's unique from any other ExecuteScript commands in the rest of your mission). "squad.move.tagtotag" is a pre-made script, and is one of many that we created while designing the game. (The "squad.move.tagtotag" script is in strategic_scripts.cfg, the file we pointed to in strategic.cfg in our mission folder)

The squad.move.tagtotag script calls for two bits of info, the tag source, and the tag destination (tag.src, tag.dst). See the syntax above. So this script is telling the tag "enemy_units" to move to the tag "players_units". Once the enemy is close enough, they will engage automatically making it appear as though they ran towards the player to attack.

Load your map in the game. The enemy troops should now run towards the player in the beginning of the mission.

Now we need the condition that will make the player get the Defeat screen if all his units get destroyed. Open objective_start.cfg. In the Action scope of "objective_start_player", add the line:


NewObjective("objective_player_defeat");



The entire objective should now look like:
CreateObjectType("objective_start_player", "Objective")
{
 GameObj();
 ObjectiveObj()
 {
   Condition("TRUE");
   Action()
   {
     NewObjective("objective_player_at_goal");
     NewObjective("objective_player_defeat");
   }
 }
}


Now open objectives_player.cfg. Add the "objective_player_defeat" Objective:
CreateObjectType("objective_player_defeat", "Objective")
{
 GameObj();
 ObjectiveObj()
 {
   Condition("TagCount")
   {
     Tag("players_units")
     {
       Operator("==");
       Amount(0);
     }
   }
   Action()
   {
     Lose();
   }
 }
}


"TagCount" is a condition type that can test how many objects of a certain tag there is in the world at a given time. TagCount calls for which tag to test, then has an Operator/Amount variable. The operator "==" means "is", so it's asking "Is the amount of objects in the Tag "players_units" zero?" Lose() is the script command to give the Defeat screen.

Try the mission in the game. Allow the enemy to kill all your units, you should get the Defeat screen.

This concludes the creation of the tutorial map! You should now have a mission that you can win and lose.