WML for Complete Beginners: Chapter 3

From The Battle for Wesnoth Wiki

Chapter 3: The _main.cfg

Note: this page borrows heavily from the BuildingCampaignsTheCampaignFile page.

So we've created a campaign folder, but as of yet the game doesn't even know this new folder exists. In order for the game to find the folder, we have to create a special file called "_main.cfg" that tells the game where to find all of your campaign's data. Without this file, the game won't be able to find your campaign when it starts up, and consequently you won't be able to play your campaign.

So let's get started creating a "_main.cfg" file so that the game can find your campaign.

Navigate to your campaign folder, if you aren't already there. Now create a new text file and name it "_main.cfg" (just like that, including the underscore but without the quotes). Make sure you select a save-type of 'all files' and not 'text document (.txt)' for this file. If you selected 'text document (.txt)' you will actually save a file named "_main.cfg.txt" which will not be recognized by Wesnoth. Now you have created a file called "_main.cfg", but we're not done yet. Right now the file is empty, so the game still won't be able to locate your campaign yet. But fear not, all you have to do is write some specific WML inside the "_main.cfg" file and the game will be able to find your campaign just fine.

The Text Domain

Open the "_main.cfg" file in your text editor if you haven't already. and add the following tagset:

[textdomain]
[/textdomain]

This tagset which specifies where the game should look for translations to the strings in the campaign (at this stage you probably won't have any translations, but it's a common practice to add a text domain just in case you get translations later on). The textdomain tag specifies a name for the textdomain, which is what is used in the [campaign] tag, and is used in campaign scenarios to connect the strings with translations.

Inside the [textdomain] tag, include the attributes name and path (don't assign values to them just yet, we'll do that in a moment):

[textdomain]
    name=
    path=
[/textdomain]
  • The "name" Attribute

The attribute name specifies the name of the text domain you are creating. The textdomain name should be unique, and start with 'wesnoth-', to ensure that it does not conflict with other textdomains that might be specified on a given system. Let's name our text domain "my_first_campaign". Don't forget to start it with "wesnoth-". Now the contents of your _main.cfg file should look exactly like this:

[textdomain]
    name="wesnoth-my_first_campaign"
    path=
[/textdomain]
  • The "path" Attribute

The attribute path specifies a path to the directory where the compiled translation files will be stored. This should be a file inside the campaign directory. Right now our translations folder is empty, but if you ever get translations for your campaign, this is the folder in which they would go. Let's assign the "translations" folder directory path, which should be "data/add-ons/my_first_campaign/translations", to this attribute. Your _main.cfg should now look like this:

[textdomain]
    name="wesnoth-my_first_campaign"
    path="data/add-ons/my_first_campaign/translations"
[/textdomain]

Defining the Campaign

And now we're going to add the [campaign] tagset. Yes, it's our old friend, the [campaign] tagset, from Chapter 1.

[campaign]
[/campaign]

Next, inside the [campaign] tagset, include the following line:

#textdomain wesnoth-my_first_campaign

This tells the game that the text strings in this file belong to the text domain you just defined above

Next we need to give the attributes id, name, abbrev, icon, image, first_scenario, and description, and define your campaign difficulties. Don't assign any values to these attributes yet, we'll do that in a moment. For now, just make sure that you have all of these attributes in between the campaign tags, like so (the exact order of the attributes doesn't matter, but it is recommended that you follow the order given below to make things easier for yourself when following this tutorial):

[campaign]
    #textdomain wesnoth-my_first_campaign
    id=
    name=
    abbrev=
    define=
    icon=
    image=
    first_scenario=
    description=
[/campaign]

Now let's go over the attributes one by one and give them their values. I'll give you a specific value to assign to each attribute, and then I'll explain why we use that particular value.

  • The "id" Attribute
The unique identifier of your campaign. The value of an "id" attribute can only contain lowercase alphanumeric characters and underscores. We are going to give this attribute the value "my_first_campaign", like so:
id=my_first_campaign
  • The "name" Attribute
The name of your campaign. This translatable string is the name that will show up in the in-game campaign menu, where you can select which campaign you want to play. Let's give it the value "My First Campaign". Since we want this string to be translatable, don't forget to include the translation mark (the underscore) in front of the first double quote.
name= _ "My First Campaign"
  • The "abbrev" Attribute
This attribute defines a campaign abbreviation that will be used as a prefix for the names of save files from that campaign. It should generally consist of the acronym of the campaign's name (i.e., the first letter of each of the words in the campaign's name, capitalized).
  • The "define" Attribute

This attribute creates a key that lets the game know when a user has selected to play a scenario from your campaign.

  • The "icon" Attribute

The image that will be displayed next to the name of your campaign in the in-game campaign selection menu. Since we need the game to locate a specific file, we [...]

  • The "image" Attribute

This defines the image that will appear under your campaign's description when your campaign is selected in the in-game campaign selection menu.

  • The "first_scenario" Attribute
  • The "description" Attribute
  • Campaign difficulties

The campaign difficulties can be set with the difficulty tag or the CAMPAIGN_DIFFICULTYmacro. Please refer to a this tutorial, and in that tutorial read on to its macros section too.

[campaign]
    #textdomain wesnoth-my_first_campaign
    id=my_first_campaign
    name= _ "My First Campaign"
    abbrev= _ "MFC"
    define=CAMPAIGN_MY_FIRST_CAMPAIGN
    icon=
    image=
    first_scenario=my_first_scenario
    description= _ "This is my first campaign."
    {CAMPAIGN_DIFFICULTY EASY  "units/human-loyalists/spearman.png~RC(magenta>red)" ( _ "Spearman") ( _ "Normal")}
[/campaign]

The Preprocessor

Before any WML file is read by Wesnoth, it goes through the preprocessor. The preprocessor will prepare the file to be read by the game. It doesn't actually recognize WML. In fact, it ignores it. Instead, it reads the preprocessor directives, used to create and use macros. Macros are used to reduce the repetition of information just like pronouns do with names and identifiers in the English language. Don't worry about macros now, we will talk about them later.


Preprocessor Directives

As mentioned above, the Preprocessor doesn't recognize WML code. It only recognizes preprocessor directives. While apparently similar to comments, they have a much greater impact on the code. Not only can they define and use macros, they can also be used to apply a condition for the reading of a part of the file by Wesnoth (making a part of the code be read only if you are in the Hard difficulty, for example). Using preprocessor directives can create many things, but don't worry about it yet. We will talk about it in the future.


The Binary Path

The binary path is used to tell the game to include a certain directory in the userdata folder whenever it searches for a file. For instance, if you had a custom image in your campaign called "my_face.png", whenever the game finds a reference to that file in a scenario (e.g., you want to display that image at one of the story screens in a scenario), it will first search the core gamedata directories, then it will search any folders included in the binary path. If it cannot find the file in either the gamedata directory or in any of the directories specified in the binary path, then it will give you an error.

You will only need to include a binary path if your campaign contains custom images, sounds or music that is not included in mainline Wesnoth. The binary path can also be used to location maps. If you do not have any custom images, sounds or music, then you should not include a binary path. Since we will be including some custom images in our campaign, we are going to need to include a binary path.

To create a binary path, use the following syntax:

[binary_path]
    path=data/add-ons/my_first_campaign
[/binary_path]

This tells the game to search the specified userdata directory whenever it cannot locate a certain file in the gamedata directory. Note that the value of the "path" key must always begin with "data/add-ons/" followed by the name of your campaign folder.

Directory Inclusion

(The final _main.cfg should end up looking something like this:)

[textdomain]
    name="wesnoth-my_first_campaign"
    path="data/add-ons/my_first_campaign/translations"
[/textdomain]

#textdomain wesnoth-my_first_campaign

[campaign]
    #wesnoth-My_First_Campaign
    id=my_first_campaign
    name= _ "My First Campaign"
    abbrev= _ "MFC"
    define=CAMPAIGN_MY_FIRST_CAMPAIGN
#need icon and image (take from core files, don't include external files for sake of simplicity)
    icon=
    image=
    first_scenario=my_first_scenario
    description= _ "This is my first campaign."
    {CAMPAIGN_DIFFICULTY EASY  "units/human-loyalists/spearman.png~RC(magenta>red)" ( _ "Spearman") ( _ "Normal")}
[/campaign]

#ifdef CAMPAIGN_MY_FIRST_CAMPAIGN

[binary_path]
    path=data/add-ons/my_first_campaign
[/binary_path]

{~add-ons/my_first_campaign/macros}
{~add-ons/my_first_campaign/utils}

{~add-ons/my_first_campaign/scenarios}
#endif

(note: no units yet, save that for the adding custom units section)

Navigation
Chapter 2
The Userdata Directory
and the Campaign Folder
WML for Complete Beginners: Chapter 3 Chapter 4
Creating Your First Scenario
This page was last edited on 29 January 2023, at 19:52.