Difference between revisions of "BuildingScenariosAdvanced"

From The Battle for Wesnoth Wiki
(Building scenarios: Advanced)
(GetText & Translations: Link to the main GettextForWesnothDevelopers#Marking_up_strings_in_WML)
 
(30 intermediate revisions by 12 users not shown)
Line 1: Line 1:
==== Quick Navigation: ====
+
{{BuildingScenariosNav}}
[[BuildingScenarios]]
 
:'''[[BuildingScenariosSimple]]''' - [[BuildingScenariosIntermediate]] - [[BuildingScenariosAdvanced]]
 
:[[BuildingScenariosWML]]
 
:[[BuildingScenariosComments]]
 
:[[BuildingScenariosSamples]]
 
:[[BuildingScenariosFAQ]]
 
<br>
 
----
 
  
 +
== Advanced Events ==
  
= Building scenarios: Advanced =
+
===Internal Actions===
 +
See [[InternalActionsWML]] for a complete list of all tags and values. In what follows, the basics of variable creation and manipulation are explained.
  
Ok, so as you have seen in [[BuildingScenariosSimple]], you can setup what the human player and AI player start with. From the '''[side]''' tag listed below you can see we are going to learn some more interesting things about AI that can be controlled from there. We'll have a look at the new keys one by one.
+
====Variables====
 +
(This can be skipped if you're familiar with the concept of variables)
  
 +
(See [[VariablesWML]] for more)
 +
 +
What are variables? Variables are basically names. And with those names, we associate a certain value. You can compare this with the words, because words are associated with (several) objects, people, feelings, ... So a variable is just a way of communication: you and the computer (the Wesnoth engine really) are communicating with each other!
 +
 +
The most important aspect of variables is that they can change with time. (If they don't we call them constants.) Because they change, we can use them to trigger events, or to detect something has happened. You did this already in [[BuildingScenariosIntermediate]], using the [event] tag. We only wanted to trigger the actions inside the [event] when Konrad moved onto tile 4,8. To do so we had to make use of the variables x,y and description.
 +
 +
Most variables provided by the engine are associated with a certain tag and can thus only be used inside them.
 +
 +
====Manipulating====
 +
These three actions can be executed in one single tag: ''''[set_variable]''''
 +
Say we wanted to store 'Hello World' in a variable named ''message_to_the_world''. This is how we would do this:
 +
[event]
 +
.
 +
.
 +
.
 +
  [set_variable]
 +
    #The name of our variable:
 +
    name=message_to_the_world
 +
    #The value of message_to_the_world, notice the underscore!
 +
    value= _ "Hello World!"
 +
  [/set_variable]
 +
  .
 +
  .
 +
  .
 +
[/event]
 +
Now, if we want to change the value to something else later on, e.g. 'Goodbye World', we can use the exact same code as above.
 +
If we want to add something to our message we need to use this:
 +
 +
[event]
 +
.
 +
.
 +
.
 +
  [set_variable]
 +
    name=message_to_the_world
 +
    value= _ "$message_to_the_world Have a nice day!"
 +
  [/set_variable]
 +
  .
 +
  .
 +
  .
 +
[/event]
 +
We've been using text variables (called strings) for now. But we can also store numbers and do some basic math with them. The following example clarifies this:
 +
 +
[event]
 +
.
 +
.
 +
.
 +
  [set_variable]
 +
    name=number_x
 +
    value=10
 +
  [/set_variable]
 +
  [set_variable]
 +
    name=number_x
 +
    add=-9
 +
  [/set_variable]
 +
  [set_variable]
 +
    name=number_x
 +
    multiply=200
 +
  [/set_variable]
 +
  [set_variable]
 +
    name=number_x
 +
    multiply=0.5
 +
  [/set_variable]
 +
  .
 +
  .
 +
  .
 +
[/event]
 +
In the above, we set a variable named ''number_x'' to the value of 10. We subtract 9 (=1), multiply with 200 (=200) and divide by two (or multiply with 0.5) resulting in 100.
 +
 +
====Using Variables====
 +
Now that we know how to create and manipulate variables, we'll learn how to use them.
 +
First of all, you need to know what variables you always have at your disposal! In an event tag, these variables are
 +
* '''side_number''': the number of the current player's side (may be empty during start or prestart events)
 +
* '''turn_number''': the number of the current turn (may be empty during start or prestart events)
 +
* '''x1''': this is the x-coordinate of the location where the most recent event was triggered
 +
* '''y1''': this is the y-coordinate of the location where the most recent event was triggered
 +
* '''x2''': this is the x-coordinate of the location that assisted in triggering the most recent event
 +
* '''y2''': this is the y-coordinate of the location that assisted in triggering the most recent event
 +
* '''unit''': inside an event, this is the unit at $x1,$y1
 +
* '''second_unit''': inside an event, this is the unit at $x2,$y2
 +
* '''this_unit''': inside a standard unit filter, this is the unit currently being considered for a possible match.
 +
 +
Some of these are only containers for other variables. The ''unit'' variable is an example. You can acces those 'sub'-variables by using dots:
 +
unit.hitpoints
 +
unit.side
 +
...
 +
 +
We will use '''unit''' in an example to show you how you can use all this:
 
  [scenario]
 
  [scenario]
 
  .
 
  .
 
  .
 
  .
 
  .
 
  .
   [side]
+
   [event]
     side=2
+
     #A unit moves onto a tile:
     enemy=1
+
    name=moveto
 +
    [filter]
 +
      x,y=25,26
 +
    [/filter]
 +
   
 +
   
 +
     [set_variable]
 +
      name=unit.hitpoints
 +
      add=-5
 +
    [/set_variable]
 +
    [set_variable]
 +
      name=unit.status.poisoned
 +
      value=yes
 +
    [/set_variable]
 
   
 
   
    canrecruit=1
+
     #After we have changed the values, we need to apply them.
+
     #We do this by using the unstore_unit tag like this:
    type=Lich
+
     [unstore_unit]
    description=Galga
+
       variable=unit
+
       find_vacant=no
     #ifdef EASY
+
     [/unstore_unit]
      recruit=Skeleton,Revenant,Blood Bat,Ghost,Bone Shooter
+
   [/event]
      recruitment_pattern=fighter,fighter,archer,scout
+
  #We're finished!
      gold=300
 
     #endif
 
 
     #ifdef NORMAL
 
      recruit=Skeleton,Revenant,Chocobone,Blood Bat,Wraith,Bone Shooter,Dark Adept
 
       recruitment_pattern=fighter,fighter,archer,scout
 
       gold=500
 
     #endif
 
 
    #ifdef HARD
 
      recruit=Skeleton,Revenant,Chocobone,Wraith,Bone Shooter,Dark Adept
 
      recruitment_pattern=fighter,fighter,archer,scout
 
      gold=700
 
    #endif
 
 
    aggression=1.0
 
    village_value=0.0
 
    leader_value=50.0
 
   [/side]
 
 
  .
 
  .
 
  .
 
  .
Line 54: Line 130:
 
  [/scenario]
 
  [/scenario]
  
As you can see from the above listing, the '''[side]''' tag can get a little complex. The ''#ifdef'' is relatively simple
+
There's one tag you don't know yet, and that's the '''[unstore_unit]''' tag. To explain this tag I'll explain it's counterparts; '''[store_unit]'''. [store_unit] stores a unit, or several units, in a variable you choose. You can then manipulate those variables as described above. However, you will need to apply these changes, and this is done by using the [unstore_unit] tag. For more see [http://www.wesnoth.org/wiki/InternalActionsWML#.5Bevent.5D InternalActions].
to explain. If the user is playing EASY then everything between '''#ifdef EASY''' and '''#endif''' is set and the others
+
 
are ignored. If the user is playing NORMAL then everything between '''#ifdef NORMAL''' and '''#endif''' is set and the
+
As of version 1.9, this can also be done much easier:
others are ignored. Finally if the user is playing HARD then everything between '''#ifdef HARD''' and '''#endif''' is set
+
 
and the others are ignored. This allows a scenario to be configured differently for each level of gameplay the user
+
  [event]
may choose. There are also four new keys listed, '''recruitment_pattern''', '''aggression''', '''village_value''' and '''leader_value'''.
+
    #A unit moves onto a tile:
 +
    name=moveto
 +
    [filter]
 +
      x,y=25,26
 +
    [/filter]
 +
    #modify the unit 
 +
    [modify_unit]
 +
        [filter]
 +
            x,y=25,26 
 +
        [/filter]
 +
        hitpoints=$($unit.hitpoints - 5)
 +
        status.poisoned=yes
 +
    [/modify_unit]
 +
  [/event]
 +
  #We're finished!
 +
 
 +
[/scenario]
 +
 
 +
You also might have seen that there's sometimes a Dollar sign ($) in front of a variable name. This indicates that the engine will replace the '$your_variable_name' with the exact value of this variable. Example:
 +
[set_variable]
 +
  name=my_variable  # here you refer to the variable itself
 +
  value=5
 +
[/set_variable]
 +
[message]
 +
  speaker=narrator
 +
  message= _ "Your variable's value: $my_variable"  # will be showed as "Your variable value: 5"
 +
[/message]
 +
 
 +
 
 +
<!-- ====Conditionals: [if] and [while]====
  
  
''''THIS IS OBSOLETE:'''' '''Editor's Note: For 0.8.3 and later, scenarios no longer need IDs'''
 
  
If a scenario is meant to be translated, it must have ID's. ID's are used to represent text in the scenario. A translation maps the ID of each text in the scenario to a translation text.
+
===Direct Actions===
 +
===Interface Actions===
 +
//-->
  
Example:
+
== [[GetText]] & Translations ==
 +
[http://www.wesnoth.org/forum/viewtopic.php?t=11445 As Viliam pointed out] (reordered his words):
  
 +
Translating programs has two steps. The first step is making [...] scenarios that are
 +
<b>possible</b> to translate; <b>preferably easy</b> to translate. [...] The second
 +
step is the translating of the texts... leave this to  translators.
 +
 +
So, as a campaign/scenario developer you have to make sure your campaign will be easy to translate. You can achieve this very easily by preceding all text the user might see on the screen with an underscore. This indicates it is a translatable string. [[GetText]] will then be able to look up a translation, based on your localization settings.
 +
To make it ever more clear, here's an example:
 +
.
 +
.
 +
.
 
  [message]
 
  [message]
message= _ "Where are we? Which way now? I am tired of this darkness!"
+
  speaker=Konrad
description=Konrad
+
  message= <b>_</b> "I am mighty Konrad! I fought many dummies and now I will fight you!"
id=hasty_1
 
 
  [/message]
 
  [/message]
 +
.
 +
.
 +
.
  
This is the first message in the scenario "Hasty Alliance". To translate this message into French, we put the key
+
The message key contains the words that will be displayed when Konrad speaks. So this is a translatable string. So it is preceded with an underscore. For more details and examples, see [[GettextForWesnothDevelopers#Marking_up_strings_in_WML|marking up strings in WML]].
  
hasty_1="Où sommes-nous ? Quel chemin devons-nous emprunter maintenant ? Je suis fatigué de cette obscurité !"
+
Viliam also said:
  
in the French translation file and when Wesnoth is played in French this message will be displayed rather than the
+
The most important rule of all is: <b>Do not split sentences.</b>
original one. The key
+
In some languages placing a word in a sentence requires more than mere string concatenation.
''' id ''' should be added to any tag with text that is meant to be translated (remember, the [scenario] tag already has an
+
Some languages use [http://en.wikipedia.org/wiki/Declension declension].
id, do not add
 
another one).
 
 
 
Now you have enough information to make some interesting looking scenarios with tuned AI players.
 
This is a big step.
 
Next we are going to learn how to make your newly created scenario fit nicely into a campaign.
 
This involves making a descriptive intro shown before the scenario is played.
 
See [[IntroWML]] for a description of the intro screen.
 
  
 
== See Also ==
 
== See Also ==
 
* [[ScenarioWML]], [[SyntaxWML]] & [[ReferenceWML]]
 
* [[ScenarioWML]], [[SyntaxWML]] & [[ReferenceWML]]
 
* [[BuildingScenarios]]
 
* [[BuildingScenarios]]
 +
 +
[[Category:Create]]

Latest revision as of 08:24, 23 April 2021

Advanced Events

Internal Actions

See InternalActionsWML for a complete list of all tags and values. In what follows, the basics of variable creation and manipulation are explained.

Variables

(This can be skipped if you're familiar with the concept of variables)

(See VariablesWML for more)

What are variables? Variables are basically names. And with those names, we associate a certain value. You can compare this with the words, because words are associated with (several) objects, people, feelings, ... So a variable is just a way of communication: you and the computer (the Wesnoth engine really) are communicating with each other!

The most important aspect of variables is that they can change with time. (If they don't we call them constants.) Because they change, we can use them to trigger events, or to detect something has happened. You did this already in BuildingScenariosIntermediate, using the [event] tag. We only wanted to trigger the actions inside the [event] when Konrad moved onto tile 4,8. To do so we had to make use of the variables x,y and description.

Most variables provided by the engine are associated with a certain tag and can thus only be used inside them.

Manipulating

These three actions can be executed in one single tag: '[set_variable]' Say we wanted to store 'Hello World' in a variable named message_to_the_world. This is how we would do this:

[event]
.
.
.
  [set_variable]
    #The name of our variable:
    name=message_to_the_world
    #The value of message_to_the_world, notice the underscore!
    value= _ "Hello World!"
  [/set_variable]
 .
 .
 .
[/event]

Now, if we want to change the value to something else later on, e.g. 'Goodbye World', we can use the exact same code as above. If we want to add something to our message we need to use this:

[event]
.
.
.
  [set_variable]
    name=message_to_the_world
    value= _ "$message_to_the_world Have a nice day!"
  [/set_variable]
 .
 .
 .
[/event]

We've been using text variables (called strings) for now. But we can also store numbers and do some basic math with them. The following example clarifies this:

[event]
.
.
.
  [set_variable]
    name=number_x
    value=10
  [/set_variable]
  [set_variable]
    name=number_x
    add=-9
  [/set_variable]
  [set_variable]
    name=number_x
    multiply=200
  [/set_variable]
  [set_variable]
    name=number_x
    multiply=0.5
  [/set_variable]
 .
 .
 .
[/event]

In the above, we set a variable named number_x to the value of 10. We subtract 9 (=1), multiply with 200 (=200) and divide by two (or multiply with 0.5) resulting in 100.

Using Variables

Now that we know how to create and manipulate variables, we'll learn how to use them. First of all, you need to know what variables you always have at your disposal! In an event tag, these variables are

  • side_number: the number of the current player's side (may be empty during start or prestart events)
  • turn_number: the number of the current turn (may be empty during start or prestart events)
  • x1: this is the x-coordinate of the location where the most recent event was triggered
  • y1: this is the y-coordinate of the location where the most recent event was triggered
  • x2: this is the x-coordinate of the location that assisted in triggering the most recent event
  • y2: this is the y-coordinate of the location that assisted in triggering the most recent event
  • unit: inside an event, this is the unit at $x1,$y1
  • second_unit: inside an event, this is the unit at $x2,$y2
  • this_unit: inside a standard unit filter, this is the unit currently being considered for a possible match.

Some of these are only containers for other variables. The unit variable is an example. You can acces those 'sub'-variables by using dots:

unit.hitpoints
unit.side
...

We will use unit in an example to show you how you can use all this:

[scenario]
.
.
.
  [event]
    #A unit moves onto a tile:
    name=moveto
    [filter]
      x,y=25,26
    [/filter]
    
    
    [set_variable]
      name=unit.hitpoints
      add=-5
    [/set_variable]
    [set_variable]
      name=unit.status.poisoned
      value=yes
    [/set_variable]

    #After we have changed the values, we need to apply them.
    #We do this by using the unstore_unit tag like this:
    [unstore_unit]
      variable=unit
      find_vacant=no
    [/unstore_unit]
  [/event]
  #We're finished!
.
.
.
[/scenario]

There's one tag you don't know yet, and that's the [unstore_unit] tag. To explain this tag I'll explain it's counterparts; [store_unit]. [store_unit] stores a unit, or several units, in a variable you choose. You can then manipulate those variables as described above. However, you will need to apply these changes, and this is done by using the [unstore_unit] tag. For more see InternalActions.

As of version 1.9, this can also be done much easier:

  [event]
    #A unit moves onto a tile:
    name=moveto
    [filter]
      x,y=25,26
    [/filter]
    #modify the unit   
    [modify_unit]
        [filter]
            x,y=25,26  
        [/filter]
        hitpoints=$($unit.hitpoints - 5)
        status.poisoned=yes
    [/modify_unit]
  [/event]
  #We're finished!
[/scenario]

You also might have seen that there's sometimes a Dollar sign ($) in front of a variable name. This indicates that the engine will replace the '$your_variable_name' with the exact value of this variable. Example:

[set_variable]
  name=my_variable   # here you refer to the variable itself
  value=5
[/set_variable]
[message]
  speaker=narrator
  message= _ "Your variable's value: $my_variable"  # will be showed as "Your variable value: 5"
[/message]


GetText & Translations

As Viliam pointed out (reordered his words):

Translating programs has two steps. The first step is making [...] scenarios that are
possible to translate; preferably easy to translate. [...] The second 
step is the translating of the texts... leave this to  translators.

So, as a campaign/scenario developer you have to make sure your campaign will be easy to translate. You can achieve this very easily by preceding all text the user might see on the screen with an underscore. This indicates it is a translatable string. GetText will then be able to look up a translation, based on your localization settings. To make it ever more clear, here's an example:

.
.
.
[message]
  speaker=Konrad
  message= _ "I am mighty Konrad! I fought many dummies and now I will fight you!"
[/message]
.
.
.

The message key contains the words that will be displayed when Konrad speaks. So this is a translatable string. So it is preceded with an underscore. For more details and examples, see marking up strings in WML.

Viliam also said:

The most important rule of all is: Do not split sentences.
In some languages placing a word in a sentence requires more than mere string concatenation.
Some languages use declension.

See Also

This page was last edited on 23 April 2021, at 08:24.