MISSION CREATION TUTORIAL

This tutorial will outline how to create a very basic mission using the World Builder in order to introduce mission development in CoH2. Also, don't forget to have a look at the paired Mission Pack Example.


Files Involved

A mission in CoH2 typically involves several script files as well as the map file. The list below outlines the files involved in this tutorial and their functionality.

  • MapName.sgb: The map
  • MapName.scar: The primary mission script file
  • MapName.events: A script file containing “intel events” (speech, nislets, etc…)
  • MapName.options: A script file containing data on the map options (ie: whether it uses ice)
  • MapName_encounters.scar: A script file containing encounter setup data for the mission
  • MapName_obj_ObjectiveName: Script files containing data and logic for running mission objectives
ObjectPlacement.png

Step 1: Create The map

The first thing to do is create your map. Before doing so, it is best to have an idea of the sort of space your mission will require.

  1. Open World builder
  2. Select File > New Single Player Map
  3. Create a new folder for the mission files (ie: “Example_Mission”)
  4. Set a file name (Should be the same as your folder)
  5. Press the “Save” button
  6. Set your Terrain Size and Playable Area (For Example_Mission these are set to 192x352 and 96x192 respectively)
    • Note: There should be enough room between the playable area and the terrain size to allow for enough out of bounds space to cover up the map edge.
  7. Add a player start point:
    • Go to “Object Placement” mode (ObjectPlacementIcon.png on the toolbar)
    • Expand the “ebps > gameplay” foldout on the right sidebar and select “starting_position_shared_territory”
    • Right click on the appropriate location to place the object.
    • Set the “Player assignment” under “Current” to “Player 1” on the right sidebar
  8. Repeat step 7 for player2 – this will setup a player for the enemy AI.
    • Note: Using “starting_position_sp” instead of “starting_position_shared_territory” will allow you to setup players without giving them a starting base.
  9. Save your map

Step 2: Setup The Options File

In order for your game to load correctly, your .options file will have to be setup correctly. For more information on the .options file, check the Options File Format page.

1. Open the MapName.options file[[/li]]
2. Ensure that the following lines appear as below:

scenario_type = singleplayer_mod
has_scripted_ai = true
sort_index = 0
win_condition = no_win_condition
{
    {status = open, race = soviet, flags = flags_swap },
    {status = ai, race = german, flags = flags_none },
}

Step 3: Setup The scripts

Scripting for CoH2 can follow a large variety of structures depending on style preference and the needs of the specific mission and structure. In this example we will use a simplified version of the structure used for AA campaign missions.
1. Create the following text files in the same directory as your map:

MapName.scar (ie: Example_Mission.scar)
MapName.events (ie: Example_Mission.events – only needed if you will be using dialogue events in your mission)
MapName_encounters.scar (ie: Example_Mission_encounters.scar)
MapName_obj_ObjectiveName.scar (one for each primary objective, ie: Example_Mission_obj_ObjName.scar, Example_Mission_obj_SecondObjective.scar)

2. In MapName.scar, put the following lines at the top of the script to import the all of the necessary files:

import("ScriptSetup.scar")
import("MapName_obj_Objective.scar") --(For each objective file)
import("MapName_Encounters.scar")

3. Next put these lines below the imports – they will initialize the players.

function Mission_SetupPlayers() 
    player1 = World_GetPlayerAt(1)
    player2 = World_GetPlayerAt(2)
end

4. Now, put the following lines below that. We can fill in the g_missiondata table later

function Mission_SetupVariables()
    g_missionData = { }
end

5. Finally, add the following lines below the rest

function Mission_Start()    
end

Step 4: Adding Gameplay

MarkerPlacement.png

From here you can begin putting in whatever functionality and logic you’d like, stemming from the Mission_Start() function. As a basic example, we will give the player some starting units, and setup a simple enemy encounter.

  1. In world builder, add a marker to the position that you want the player’s units to spawn, and another at the position you want the encounter to take place.
    • Select the MarkerIcon.png icon to enter marker mode.
    • Select a type of marker from the right sidebar (any will do, but for consistency select Player Spawn)
    • Right click on the terrain at the location you want the player units to spawn.
    • Double click on the name property in the right sidebar to set the marker’s name (this is what you will reference in script). In this example, we will call it “mkr_playerSpawn”
    • Repeat the same steps for the enemy spawn, but name it “mkr_enemySpawn”
    • Save your map file.

2. Add the following lines inside of your g_missionData table, which is located in Mission_SetupVariables() in the main mission script (ie: MapName.scar). This will setup the player’s starting units at the location you created in the World Builder

startingUnits = {    
    {
        sbp = SBP.SOVIET.CONSCRIPT_SQUAD_MP, 
        numSquads = 2,
        spawn = mkr_playerSpawn,
    },
}

3. Open the encounters file (MapName_Encounters.scar), and enter the following lines in order to setup the enemy units and encounter. This will setup where the units spawn, what units to spawn, and a goal, which will dictate how the units should behave. In this case, they will defend the area they were spawned in to.

ENCOUNTERS = {}

ENCOUNTERS.ExampleEncounter = function()
    local encData = {
        name = "EnemyEncounter", 
        spawn = mkr_enemyDefend, 
        units = { 
            {
                name = "Grens", 
                sbp = SBP.GERMAN.GRENADIER_SQUAD,
            },
        },
        goal = { 
            name = "Defend", 
            target = mkr_enemySpawn, 
            range = 45, 
            leashRange = 45, 
        },
    }
    local enc_newEncounter = Encounter:Create(encData)     
    return enc_newEncounter
end

4. Back in the main script file (MapName.scar), add the following line to the g_missionData table in order to enable the encounter AI system

useEncounterSystem = true,

5. Now put the following line inside the Mission_Start() function in order to tell the script to spawn the enemy encounter at the beginning of the mission

ENCOUNTERS.ExampleEncounter()

6. If you start the mission, you should now have two squads of conscripts, and your opponent will have a squad of grenadiers.

Step 5: Adding Objectives

The next step will be adding an objective and end condition to the mission.
1. Open the objective script file (ie: MapName_obj_ObjName.scar).
2. Add the following lines to the file in order to setup the data for your objective. This will handle setting up the UI for the objective, an event to tell the objective when to end, and it will end the mission when the objective is complete.

function INIT_ObjExample ()
    OBJ_FirstObjective = {
        Title = LOC("Defeat the enemy troops"),
        TitleEnd = LOC("Enemy defeated"), 
        Type = OT_Primary, 
        OnStart = function() 
            Event_PlayerSquadCount(EventHandler_ObjectiveComplete, {objective = OBJ_FirstObjective}, player2, 0)
        end,
        OnComplete = function()  
            Event_Timer(EndMission, nil, 2)
        end,
        OnFail = nil, 
    }    
end
Scar_AddInit(INIT_ObjExample)

3. Below that line, add the following function. This is called by the Event_Timer above, in order to end the mission after the objective is completed.

function EndMission()
    Game_EndSP(true)
end

4. Next, in the main mission scar (MapName.scar) add the following lines to the g_missionData table. This will register the objective with the game.

objectives = {    
    OBJ_FirstObjective,    
},

5. Now, add the following line to the Mission_Start() function. This will start the objective at the beginning of the mission.

Objective_Start(OBJ_FirstObjective)

6. With this, the mission should now function completely. Upon starting, you should have 2 squads of conscripts, be given an objective to destroy the enemy, and when the enemy units are dead the mission should complete.

Final Scripts

File: MapName.scar

import("ScriptSetup.scar")
import("TestExampleNew_obj_FirstObjective.scar")
import("TestExampleNew_Encounters.scar")

function Mission_SetupPlayers() 
    player1 = Setup_Player(1, 11038758, "soviet", 1)    
    player2 = Setup_Player(2, 11038759, "german", 2)    
end

function Mission_SetupVariables()
    g_missionData = {
        objectives = {    
            OBJ_FirstObjective,    
        },
        startingUnits = {    
            {
                sbp = SBP.SOVIET.CONSCRIPT_SQUAD_MP, 
                numSquads = 2,
                spawn = mkr_playerSpawn,
            },
        }
    }
end

function Mission_Start()
    Objective_Start(OBJ_FirstObjective)
    ENCOUNTERS.ExampleEncounter()
end

File: MapName_obj_Example.scar

function INIT_ObjExample()
    OBJ_FirstObjective = {
        Title = LOC("Defeat the enemy troops"),
        TitleEnd = LOC("Enemy defeated"), 
        Type = OT_Primary, 
        OnStart = function() 
            Event_PlayerSquadCount(EventHandler_ObjectiveComplete, {objective = OBJ_FirstObjective}, player2, 0)
        end,
        OnComplete = function()  
            Event_Timer(EndMission, nil, 2)
        end,
        OnFail = nil, 
    }    
end
Scar_AddInit(INIT_ObjExample)    

function EndMission()
    Game_EndSP(true)
end

File: MapName_Encounters.scar

ENCOUNTERS = {}

ENCOUNTERS.ExampleEncounter = function()
    local encData = {
        name = "EnemyEncounter", 
        spawn = mkr_enemySpawn, 
        units = { 
            {
                name = "Grens", 
                sbp = SBP.GERMAN.GRENADIER_SQUAD,
            },
        },
        goal = { 
            name = "Defend", 
            target = mkr_enemySpawn, 
            range = 45, 
            leashRange = 45, 
        },
    }
    local enc_newEncounter = Encounter:Create(encData)     
    return enc_newEncounter
end

File: MapName.options

minimap_size =  
{
    384,
    768,
}
scenario_type = singleplayer_mod
start_location = fixed
uses_ice = false
win_condition = no_win_condition
has_scripted_ai = true
sort_index = 0
slots =
{
    {status = open, race = soviet, flags = flags_swap },
    {status = ai, race = german, flags = flags_none },
}

Next Steps

This completes the basic setup for a mission. For a slightly more complex example of mission scripts, please view the paired Mission Pack Example. Source for this example mission can be found here.