Difference between revisions of "BuildingScenariosAdvanced"

From The Battle for Wesnoth Wiki
m (id isn't a title anymore)
(GetText & Translations: Link to the main GettextForWesnothDevelopers#Marking_up_strings_in_WML)
 
(35 intermediate revisions by 12 users not shown)
Line 1: Line 1:
<table width=100% border=0>
+
{{BuildingScenariosNav}}
<tr>
 
<td>[[BuildingScenarios]]</td>
 
<td>[[BuildingScenariosWML]]</td>
 
<td>[[BuildingScenariosSimple]]</td>
 
<td>[[BuildingScenariosIntermediate]]</td>
 
<td>[[BuildingScenariosAdvanced]]</td>
 
</tr><tr>
 
<td></td>
 
<td>[[BuildingScenariosComments]]</td>
 
<td>[[BuildingScenariosSamples]]</td>
 
<td>[[BuildingScenariosFAQ]]</td>
 
<td></td>
 
</tr>
 
</table>
 
  
 +
== Advanced Events ==
  
<<<<<<< [[BuildingScenariosAdvanced]]
+
===Internal Actions===
Ok, so as you have seen in [[BuildingScenariosSimple]], you can setup what the human player and AI player start with. From
+
See [[InternalActionsWML]] for a complete list of all tags and values. In what follows, the basics of variable creation and manipulation are explained.
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. I'm not going to explain all the keys, just the new ones.
 
  
 +
====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]
 
   
 
   
[side]
+
    #After we have changed the values, we need to apply them.
side=2
+
    #We do this by using the unstore_unit tag like this:
enemy=1
+
    [unstore_unit]
+
      variable=unit
canrecruit=1
+
      find_vacant=no
+
    [/unstore_unit]
type=Lich
+
  [/event]
description=Galga
+
  #We're finished!
+
  .
#ifdef EASY
+
  .
  recruit=Skeleton,Revenant,Blood Bat,Ghost,Bone Shooter
+
  .
  recruitment_pattern=fighter,fighter,archer,scout
+
  [/scenario]
  gold=300
+
 
  #endif
+
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].
   
 
  #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]
 
  
As you can see from the above listing, the '''[side]''' tag can get a little complex. The ''#ifdef'' is relatively simple
+
As of version 1.9, this can also be done much easier:
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
 
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
 
may choose. There are also four new keys listed, '''recruitment_pattern''', '''aggression''', '''village_value''' and '''leader_value'''.
 
  
If a scenario is meant to be translated, it must have ids
+
  [event]
(Editor's Note: For 0.8.3 and later, scenarios no longer need IDs.).
+
    #A unit moves onto a tile:
IDs are used to represent text in the scenario.
+
    name=moveto
A translation maps the ID of each text in the scenario to a translation text.
+
    [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!
  
Example:
+
[/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]
 
  [message]
message= _ "Where are we? Which way now? I am tired of this darkness!"
+
  speaker=narrator
  description=Konrad
+
  message= _ "Your variable's value: $my_variable# will be showed as "Your variable value: 5"
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
 
  
hasty_1="Où sommes-nous ? Quel chemin devons-nous emprunter maintenant ? Je suis fatigué de cette obscurité !"
+
<!-- ====Conditionals: [if] and [while]====
 +
 
 +
 
 +
 
 +
===Direct Actions===
 +
===Interface Actions===
 +
//-->
 +
 
 +
== [[GetText]] & Translations ==
 +
[http://www.wesnoth.org/forum/viewtopic.php?t=11445 As Viliam pointed out] (reordered his words):
  
in the French translation file and when Wesnoth is played in French this message will be displayed rather than the
+
Translating programs has two steps. The first step is making [...] scenarios that are
original one. The key
+
<b>possible</b> to translate; <b>preferably easy</b> to translate. [...] The second
''' id ''' should be added to any tag with text that is meant to be translated (remember, the [scenario] tag already has an
+
step is the translating of the texts... leave this to  translators.
id, do not add
 
another one).
 
  
Now you have enough information to make some interesting looking scenarios with tuned AI players.
+
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.
This is a big step.
+
To make it ever more clear, here's an example:
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.
+
.
 +
[message]
 +
  speaker=Konrad
 +
  message= <b>_</b> "I am mighty Konrad! I fought many dummies and now I will fight you!"
 +
[/message]
 +
.
 +
.
 +
.
  
See [[ReferenceWML]] for a more complete description of what WML can do.
+
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]].
 +
 
 +
Viliam also said:
 +
 
 +
The most important rule of all is: <b>Do not split sentences.</b>
 +
In some languages placing a word in a sentence requires more than mere string concatenation.
 +
Some languages use [http://en.wikipedia.org/wiki/Declension declension].
  
 
== See Also ==
 
== See Also ==
 +
* [[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.