5.3 Scripting Basics/DR2 Script structure

Scripting
If you have any previous programming or scripting experience, the following should come naturally to you. If you don't, it may be very difficult at first but don't give up, it not so hard with some practice. If you find yourself totally lost, try to find a friend or a forum that can help you out. After you read the following sections, the greatest piece of advice we can give you is to unzip the single player missions that came with DR2, and dive into the .cfgs and see how things are done firsthand!

Each basic script or instruction (herein called "Objective"), consists of two basic parts-the "Condition" statement, and the "Action" statement. When all conditions in the Condition statement are met, or are true, then the instructions in the Action statement are carried out. The script is saying "If this is true (condition), then do this (action)". If the conditions in the Condition statement are not true, it will wait indefinitly until they are true (or the objective is cancelled). After the Condition has become true, and the Action has been carried out, the objective will unload itself from memory and will never be carried out again (unless it is re-loaded in another objective).

Below is the basic structure of an Objective:


CreateObjectType("[objective name]", "Objective")
{
 GameObj();
 ObjectiveObj()
 {
   Condition([type])
   {
     [condition];
   }
   Action()
   {
     [action];
   }
 }
}

"objective name" will be different for each objective you make. Each must have a unique name.

The word next to it "Objective" will never change.

GameObj(); and ObjectiveObj() will never change.

The condition goes between the brackets under Condition()

The action goes between the brackets under Action()

Note the bracket structure. Brackets divide the statement down into smaller and smaller units. Notice that the entire statement is enclosed in the two outermost brackets (top and bottom ones).

Within those, there is two more statements - "GameObj();" and "ObjectiveObj()".

In "ObjectiveObj()", there are two more statements called "Condition()" and "Action()".

Also note that every statement ends with a semi-colon. Mistakes as simple as a wrong bracket or missing semi-colon will crash a mission!

Now, we are going to add two Objectives to the file objective_start.cfg.

Open objective_start.cfg. Cut and paste the following into the file:


CreateObjectType("objective_start_player", "Objective")
{
 GameObj();
 ObjectiveObj()
 {
   Condition("TRUE");
   Action()
   {
     NewObjective("objective_player_at_goal");
   }
 }
}


This will be the initial script for the player team. TRUE is a type of condition. It means the condition will automatically be true whenever it is loaded, and immediately carry out the Action statement. Since the statement doesn't need any more information, there are no brackets needed in the condition statement. (The semi-colon after ("TRUE") shows that the Condition statement is over.) 'NewObjective' is our script command that loads a new objective. You can call a NewObjective in any Action scope anywhere in your scripts. "objective_player_at_goal" is an objective we will create later, but keep the line there for now.

Now, we need to tell the Editor that this Objective is going to be the initial Objective for the player's team. Load your map in the Editor (if you try to load it in the game at this point you'll crash!) Double-click on the player's team in the team menu of the Editor. On the right side you'll see a large window called "Objectives". This window lists all of the Objectives it can currently read from all your .cfg files. The Objectve we just created, "objective_start_player", should now be on this list. Highlight "objective_start_player" on the list, and click "OK" and save the map. Now the game knows to look at this objective first!

If you don't see "objective_start_player" on the list make sure you:

  • Saved your .cfg files
  • Reloaded the map after you edited the .cfg files
  • All your .cfg files are in the mission folder

    If it still doesn't work, go back through the steps and be sure you did everything correctly.

    Now add the AI team's initial objective to objective_start.cfg. Open objective_start.cfg and add the following:


    CreateObjectType("objective_start_AI", "Objective")
    {
     GameObj();
     ObjectiveObj()
     {
       Condition("TRUE");
       Action()
       {
         NewObjective("objective_attack_player");
       }
     }
    }


    "objective_attack_player" is an objective we will create later. As you did with the player's team, go into the editor, enter the AI team's setup, and highlight "objective_start_ai", click OK and save the map. The game will now look at this objective first for the AI's team.

    Now lets create the missing objectives we are referring to in our script (objective_player_at_goal and objective_attack_player)

    Open "objectives_player.cfg". Add the following and save:


    CreateObjectType("objective_player_at_goal", "Objective")
    {
     GameObj();
     ObjectiveObj()
     {
       Condition("TRUE");
       Action();
     }
    }


    Open "objectives_ai.cfg". Add the following and save:
    CreateObjectType("objective_attack_player", "Objective")
    {
     GameObj();
     ObjectiveObj()
     {
       Condition("TRUE");
       Action();
     }
    }


    As you probably noticed there are no conditions or actions, we will add these later. Your map should now load correctly in the game. Nothing will happen, but if it loads without crashing you've done everything correctly.

    To sum up what we've covered, this is what happened in the game's logic: First the map was loaded. The game noticed types_mission.cfg and strategic.cfg in the mission folder and read the files. The game included all the .cfg files specified in these files:

    strategic_scripts.cfg
    types_objects_special.cfg
    objective_start.cfg
    objective_ai.cfg
    objective_player.cfg

    Then the game looked at the Team config settings for it's initial objectives. The player's team specified "objective_start_player". The game then searched all the .cfg files included in types_mission.cfg for "objective_start_player" and found it in the file objective_start.cfg. "Objective_start_player" had a TRUE condition, so it immediately carried out the action of loading the new objective "objective_player_at_goal". Again, the game searched all the .cfg's for "objective_player_at_goal" and found it. The condition was TRUE, but nothing happened since there was no Action specified. Since we set up the AI side like the player's, the same process happened there.

    If you get a "unknown objective" error, that means the script cannot find the objective that it's asking for. Either your #include settings are off in types_missions.cfg, or you've made a typo with the objective names.

    If you get errors like "expected } but found ;" (symbols may vary), you've made a typo in your script or there is a syntax mistake in your script.

    So, as you can see if an Objective is anywhere in the included .cfg's in types_mission.cfg, the game will find it. So, you could have everything we have in objective_start.cfg, objective_ai.cfg, and objective_player.cfg in one file if you wanted, but that could get really confusing. You can structure it however you wish. The structure presented in this doc is what we found to be the easiest to work with and organize.