WML for Complete Beginners

From The Battle for Wesnoth Wiki
Revision as of 14:54, 11 February 2012 by Artisticdude (talk | contribs)

Template for future "WML for Complete Beginners" tutorial

Note: this is a work in progress.




Introduction

Hey there!

Now I'm guessing that, if you're reading this, you already know what The Battle for Wesnoth is. If you don't, I suggest finding out before reading further. If you have played...blahblahblah. (placeholder)

Who This Tutorial is For

This tutorial is aimed at users with no previous programming knowledge. This tutorial does assume that you have a certain level of competence in basic computer skills and concepts, such as opening and editing text files, and being able to follow folder directories. In this tutorial you will learn WML by building a short single-player campaign from the ground up.

What Tools You Will Need

Programming WML requires only one tool: a basic text editor. You don't need a fancy word processor to program WML; a simple program like Windows Notepad or Mac OS X TextEdit will work just fine. For Linux, there is a very nice text editing application called Kate that actually comes with syntax highlighting for WML.

So What Exactly is WML?

WML is an acronym for the "Wesnoth Markup Language", a custom scripting language that The Battle For Wesnoth uses to allow players to create and modify content without having to learn a much more complex language like Lua or C++. Now I'm going to say this here and now: don't think you can learn WML overnight. Although WML is relatively easy to learn, it will take a certain amount of effort, time and dedication to fully understand the ins and outs of the language.

Chapter 1: Syntax

First things first; let's go over the syntax of WML.

For those of you who might not know what the "syntax" of a language is, think of it as a set of rules for how WML needs to be written in order for the game to understand it. This concept may sound a bit confusing, but whether you realize it or not you have been using the concept of syntax your entire life! Think of the structure of a sentence in English: "I like jelly and cheese sandwiches." That sentence uses a certain set of rules, or syntax in order to make sense to people who hear or read it. If you said instead, "Like cheese I and sandwiches jelly", that would make no sense, and no one would understand what you were saying. Likewise, if you said "I like cheese sandwiches and jelly", that would change the entire meaning of the sentence!

Just like the syntax of the English language, WML syntax also requires proper capitalization, spelling, grammar and punctuation in order for others to understand what you're saying or writing. For example, if you decided to ignore the syntax of the English language and wrote something like this: "won day mary and i had went to seen the elefant at the zoo it's trunc was reely long", chances are people would not understand much of what you wrote. On the other hand, if you used the correct syntax and wrote: "One day Mary and I went to see the elephant at the zoo. Its trunk was really long!", people can easily understand what you wrote because it is written in the syntax they recognize and understand. Just as English-reading people would be unable to understand something were it not written in the correct English syntax, the Battle for Wesnoth game is unable to read any WML that is not written in the correct WML syntax.

So now let's go over the basics of WML syntax. Later on you will be gradually introduced to more complex WML syntax, but for now we'll just go over the basic stuff, enough to get you started.

Basic Components: Tags and Attributes

WML, as one can infer from the meaning of the acronym, is a markup language. This means that the syntax of the entire language consists of two fundamental elements: tags and attributes.

Tags

A tag is a string of lowercase text encapsulated by two square brackets, one at either end. This is an example of a "campaign" tag:
[campaign]
Tags can only contain alphanumeric characters (letters and numbers) and underscores "_". Notice I said earlier that "a tag is a string of lowercase text". This is a fundamental aspect of the WML syntax: all tags are always written in lowercase letters. If you try and use capital letters (even just one), the WML engine won't be able to understand what tag you're trying to use and will give you an error when it tries to read the incorrect tag.
As with most markup languages, in WML tags are always used in pairs: one opening tag and one closing tag. Think of the opening tag and the closing tag like the covers of a book: when you open the front cover, you know you're at the beginning. When you reach the back cover, you know you're done reading the book. Likewise, when the WML engine finds an opening tag, it realizes it's at the beginning of a task. When it reaches the closing tag, it realizes it has finished the task.
Closing tags are exactly the same as opening tags except for one key component: closing tags always have a forward slash "/" immediately after the first square bracket. This forward slash tells the WML engine that this tag is a closing tag and not another opening tag. Here is an example of the closing "campaign" tag:
[/campaign]
The opening and closing tag together are referred to as a "tagset". A tagset always contains exactly two tags: the opening tag and the closing tag. So the "campaign" tagset would look like this:
[campaign]
[/campaign]


So now we know how the WML engine knows where the beginning and end of a task are, and what syntax to use when writing them. These are the basics of tags. Later on we'll go over the more complicated aspects of tags; for now though, make sure you understand the concepts introduced here. Before we move on to the next section, let's review the points we've learned in this section about tags:
  • A tag is a string of lowercase text encapsulated by two square brackets, one at either end.
  • A closing tag is exactly the same as an opening tag except for the forward slash immediately following the first square bracket.
  • The opening tag and the closing tag together are called the tagset.
  • A tagset consists of exactly two tags: the opening tag and the closing tag.
So now we know how to tell the WML engine where the beginning and the end of a task are, but what about actually making it do the task? This is where attributes come in.


Attributes

Attributes consist of two principal elements: keys and values, and are written like so:
key=value
The basic function of attributes is to store information that is needed by the WML engine. The key of the attribute specifies what kind of information is stored, and the value of the attribute is the actual data that is stored. All text to the left of the equals sign "=" is considered to be the key, and all text to the right of the equals sign is considered to be the value of the key.
This may sound rather confusing, so let's illustrate by a practical example:
Let's say you wanted your friend to go to the grocery store and pick you up a loaf of bread. Would you say to him, "Go and come back"? Of course not! He wouldn't understand what you wanted him to do, which means you'd have no bread for dinner. Likewise, if you only write a tagset, that's equivalent to telling the WML engine to do something, but that's not enough. You will need to be more specific about exactly what the WML engine should do. If your friend were a human WML engine and you wanted him to go to the grocery store to get some bread, you might give him this code (note: this code isn't actually real WML, it is made up for the purpose of illustration):
[go]
    where=grocery_store
    get=bread
[/go]
Tags give the WML engine a very very generalized idea of what kind of task to do, but without attributes to specify exactly what to do, the WML engine won't be able to do anything because you haven't given it enough specific information. This is just like if you told your friend to "Go": he'd understand that you want him to go somewhere, but he'd be unable to perform the task because he doesn't know where to go or what to do when he gets there.

This attributes section isn't over yet, it is a WIP and will be expanded.

More About Tags

So now you should understand the basics about tags and attributes. As I alluded earlier, we will now discuss some of the more involved aspects of tags.

Nested Tags

-Discuss nested tags, whitespaces and underscores in tags, toplevel


Chapter 2: The Userdata Directory and the Campaign Folder

The Userdata Directory

There are two main directories that Wesnoth creates on your computer. The installation directory contains all the files for the core game. The userdata directory stores all your personal Wesnoth data, which includes your installed add-ons, your settings and preferences, and your saved games. The userdata directory is where we will store your work throughout this tutorial.

The location of your userdata directory differs depending on your operating system, and in the case of Microsoft Windows, the version of your operating system. Refer to the following table to determine where your userdata directory is located:


Windows XP ~/My Documents/My Games/Wesnoth 1.10/
Windows Vista and above ~/Documents/My Games/Wesnoth 1.10/
Mac OS X ~/Library/Application Support/Wesnoth 1.10/
Linux ~/.local/share/wesnoth/1.10/


Now navigate to your userdata folder. Provided that you have already run the Wesnoth application at least once before, you should see a total of five folders ("cache", "data", "editor", "persist", and "saves") in this directory, along with two files ("preferences" and "save_index.gz"). If you see all seven of these, everything is good. If you do not see all seven, try running the Wesnoth application. If that does not work, try restarting your computer. If neither of these steps work, reinstall Wesnoth.

Of the seven objects contained in the userdata folder, you will only ever need to directly interact with two: the "data" folder and the "editor" folder.

The data folder

The data folder is where all installed add-ons are kept. This is where we will be building our campaign, when we get to that. If you have installed any Wesnoth add-ons, they should show up in this folder.

The editor folder

The editor folder is where all maps created with the in-game map editor are stored. If you have ever created and saved a map in-game, you should see the map file in this directory.

The Campaign Folder

Like I told you earlier, all add-ons are installed in the data folder inside the userdata directory. That means that your campaign will also be located inside the data folder. If you're not already there, enter the data folder now.

Next, create a new folder inside the data folder. Name this new folder "my_campaign" exactly as I wrote it here (but don't include the quotation marks). Make sure you spelled it right, that you didn't accidentally capitalize any letters and that you included the underscore between "my" and "campaign" in the folder name, or your campaign won't work when you try and play it.

Now enter the "my_campaign" folder and create six new folders. Name these folders "images", "macros", "maps", "scenarios", "units" and "utils" (again, make sure you spelled everything right, that you didn't accentually capitalize anything, and that you don't include the quotation marks).

All campaigns share this common folder structure.

Chapter 3: The _main.cfg

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


Chapter 4: Creating Your First Scenario

Now that you have your _main.cfg file, it's time to create your first scenario.

Creating the Scenario Map

All scenarios require a map in order to work. Open the Battle for Wesnoth application. On the mainmenu, you should see an option labeled "Map Editor". Click this option and wait for the editor to load.

By default, Wesnoth creates a blank map with the dimensions 44 x 33 (43 wide and 33 tall). These dimensions will work fine for our purposes, so we won't change them. Hover your cursor over the map and look at the center of the upper edge of the Battle for Wesnoth application window. You should see two numbers separated by a comma.

(screenshot)

These numbers are the X and Y coordinates of the hex over which your cursor is currently hovering. If you move your cursor to another hex, the coordinates will change to show the new location of your cursor. This is a fast and convenient way to locate coordinates on the map.

So we have a map, but let's face it: it's rather dull and uninteresting. Time to add some new terrain. Locate the terrain palette (the area at the far right of your Battle for Wesnoth window that displays the terrains you can use in the editor).

(screenshot)

Towards the top of this window, you should see the terrain category selection buttons. From here you can change what category of terrain is displayed in the terrain palette.

(screenshot)

First, let's add a castle for the leader of the player's side to recruit from in the first scenario. Click on the "castle" terrain category button.

(screenshot of the castle terrain category button)


Creating the Scenario .cfg File

Create a new text file in the "scenarios" folder inside your campaign folder. Name this new text file "my_first_scenario.cfg". Open the "my_first_scenario.cfg" file in your text editor, if you haven't already. Since it is a new file, it should be completely empty right now. It won't be when we're done with it, however!

First, let's add the "scenario" tagset:

[scenario]
[/scenario]

The "scenario" tagset tells the game where the scenario begins and where it ends. All the information for your scenario goes within this tagset.

Next, inside the "scenario" tagset, include the following keys (don't forget to indent 4 spaces before each key):

id=
next_scenario=
name=
map_data=
turns=

Now the contents of the "my_first_scenario.cfg" file should look like this:

[scenario]
    id=
    next_scenario=
    name=
    map_data=
    turns=
[/scenario]

We have provided keys for these attributes, so now it's time to assign them their values.


  • The "id" Key
Assign the value "my_first_scenario" to the "id" key, like so:
id=my_first_scenario
Do you remember the value we assigned to the "first_scenario" key in the "_main.cfg" file? If you followed the instructions given in this tutorial, the value of that key should be "my_first_scenario". It is absolutely imperative that the value of the "first_scenario" key and the "id" key of the first scenario are exactly the same. If you misspelled either of them, introduced an incorrect capitalization into either of them, or made a typo of any kind in either of them, the game will return an error message when it tries to load the scenario. This is because the value of the "first_scenario" key refers to the id of your first scenario. If there is no scenario with an "id" key whose value exactly matches the value of the "first_scenario" key in the "_main.cfg", the game won't be able to find the first scenario and will tell you so by giving you an error message when you try to play your campaign.


  • The "next_scenario" Key
We are going to assign the value "null" to the "next_scenario" key. Example:
next_scenario=null
The "next_scenario" key is a close cousin of the "first_scenario" key found in the "_main.cfg" file. Just as the "first_scenario" tells the game to look for a scenario with an id key whose value matches the value of the the "first_scenario" key, the "next_scenario" key tells the game which scenario to load after the player completes the current scenario. Just like with the "first_scenario" key, make sure the value of the "next_scenario" key exactly matches the id of the next scenario, otherwise you'll get an error message. If there is no next scenario, you would assign the value "null" to the "next_scenario" key, as we did here. This means that when the player completes the current scenario, the game knows that there is no next scenario to go to, and the campaign will end.


  • The "name" Key
For this attribute, we are going to give it this translatable string:
 _ "My First Scenario." 

As you should recall from our previous discussion about translatable strings, the value we give should be enclosed in double quotes and should have a whitespace, an underscore, and then another whitespace immediately before the first double quote. So now your "name" attribute should look like this:

name= _ "My First Scenario"
Technically, the name of the scenario doesn't have to resemble the scenario's id at all. But it's a good idea to have the scenario id and the scenario name be as similar as possible to avoid any confusion later on.


  • The "map_data" Key
For this key, we are going to assign the value "{~add-ons/my_first_campaign/maps/my_first_map.map}". Now it should look like this:
map_data={~add-ons/my_first_campaign/maps/my_first_map.map}


  • The "turns" Key
We are going to assign the number "30" to this key:
turns=30
This attribute specifies how many turns the player will have to complete the scenario. If the player does not complete the scenario objective before the turns run out, then the player will lose the scenario.


Now that we have assigned values to all our keys, the entire contents of the "my_first_scenario.cfg" file should now look like this:

[scenario]
    id=my_first_scenario
    next_scenario=null
    name=_"My First Scenario."
    map_data={~add-ons/my_first_campaign/maps/my_first_map.map}
    turns=30
[/scenario]

Chapter 5: Events

Let's walk through an average morning. When your alarm clock goes off, you wake up. You go downstairs and put some bread in the toaster for breakfast. When the toaster pops, you butter the toast and eat it. When you have eaten breakfast, you go outside and wait for the schoolbus to arrive. When the bus arrives, you get on it. When it stops at your destination, you get off of the bus.

Notice that you do everything “when” something else happens. These are all “events”. The alarm going off caused you to wake up. The toaster popping causes you to butter the toast and eat it. Finishing breakfast go outside. The bus stopping causes you to get on or off. These are all like events in WML.

Chapter 6: Building and Including a Custom Unit

Chapter 7: Introduction to Variables

Now it's time to learn about “variables”. Variables contain things. They're a lot like boxes that you'd use when moving to a new home. You put things in the boxes, and then you label them so that you can find the right things when unpacking later.

Like attributes, every variable has a name and a value. The name of the variable is like the label on the box, and the variable's value is the thing that the variable (or box) contains.

For instance, you might put all of your dishes in a box and label it “dishes”. Similarly you might create a variable named “my_name” and put your name inside of it. Then if you wanted to find your name later, you could look in the variable called “my_name”.

Creating Variables

Referencing Variables

Manipulating Variables

Chapter 8: Scalar, Array, and Container Variables

So far we have only discussed scalar variables, i.e. variables that have only one variable. Believe it or not, there are types of variables than can store more than one value, or even other variables.

Scalar Variables

Array Variables

Container Variables

Container variables are variables that contain other variables within themselves. Returning to the metaphor of boxes, let's say you had three small boxes, labeled "Apples", "Oranges", and "Pears", respectively. Instead of having to carry around three smaller boxes, wouldn't it be much easier if we could just put them all in one large box labeled "fruit"? Well, with container variables, you can!

Container variables are not restricted to containing scalar variables, however. They can also store array variables.

Chapter 9: Macros

Chapter 10: Introduction to Logic

If This, Then That

Else

Chapter 11: More Logic: Cases and Loops

Cases

Loops

Chapter 12: Where to Go From Here

And that's it for this tutorial. You are now well on your way to mastering WML. We have gone over lots of WML over the course of this tutorial...

ReferenceWML