https://wiki.wesnoth.org/api.php?action=feedcontributions&user=Namhub&feedformat=atomThe Battle for Wesnoth Wiki - User contributions [en]2024-03-29T10:49:14ZUser contributionsMediaWiki 1.31.16https://wiki.wesnoth.org/index.php?title=LuaWML/Units&diff=60001LuaWML/Units2018-11-05T02:16:47Z<p>Namhub: /* wesnoth.remove_modifications */ FilterWML matching previous example</p>
<hr />
<div>This page describes the [[LuaWML]] functions for handling units.<br />
<br />
A unit is a proxy table with the following fields:<br />
* '''x''', '''y''': integers (read only, read/write if the unit is not on the map. {{DevFeature1.13|11}} These are now read/write under all circumstances, including for on-map units)<br />
* '''loc''': {{DevFeature1.13|11}} shortcut to get/set both x and y at once (read/write). Setting x and y individually would result in two moves, and there's the possibility that the intermediate move fails if the hex is occupied by another unit. In general, note that moving a unit by changing the proxy unit's coordinates does not work if the goal hex is occupied (it is not executed), so it is necessary to check if the hex is available first.<br />
* '''side''': integer (read/write)<br />
* '''id''': string (read only)<br />
* '''type''': string (read only)<br />
* '''name''': translatable string (read only)<br />
* '''cost''' {{DevFeature1.13|10}}: integer (read)<br />
* '''max_hitpoints''', '''max_experience''', '''max_moves''': integers (read only)<br />
* '''max_attacks''': integer (read only)<br />
* '''attacks_left''': integer (read/write) Setting below 0 is limited to 0.<br />
* '''extra_recruit''': table (read/write)<br />
* '''advances_to''': table (read/write)<br />
* '''hitpoints''', '''experience''': integer (read/write)<br />
* '''moves''': integer (read/write)<br />
* '''level''': {{DevFeature1.13|5}} integer (read/write)<br />
* '''resting''': boolean (read/write)<br />
* '''hidden''': boolean (read/write)<br />
* '''petrified''', '''canrecruit''': booleans (read only)<br />
* '''role''', '''facing''': strings (read/write)<br />
* '''status''': proxy associative table (read only, read/write fields), provides fields like [[SingleUnitWML#Unit_State|poisoned, slowed, petrified, uncovered, guardian, unhealable, invulnerable]]<br />
* '''image_mods''': string (read only)<br />
* '''upkeep''' {{DevFeature1.13|5}}: one of 'loyal', 'full' or a number (read/writre)<br />
* '''variables''': proxy associative table (read only, read/write fields, including ''variables.__cfg''), only toplevel named fields are proxied. {{DevFeature1.13|2}} subcontainers can be accessed by using the usual variable syntax: <syntaxhighlight inline lang='lua'>unit.variables["a.b.c[6].d"]</syntaxhighlight><br />
* '''attacks''': {{DevFeature1.13|0}}an object to access the units attacks, you can use the attacks index or the attacks name to index an attack. every attack has the following members:<br />
** '''description''': translatable string (read/write)<br />
** '''name''': string (read)<br />
** '''type''': string (read/write)<br />
** '''range''': string (read/write)<br />
** '''damage''': number(read/write)<br />
** '''number''': number(read/write)<br />
** '''movement_used''': number(read/write)<br />
** '''attack_weight''': number(read/write)<br />
** '''defense_weight''': number(read/write)<br />
** '''specials''' wml table(read/write)<br />
* '''valid''': string or nil (read only)<br />
* '''advancements''': {{DevFeature1.13|2}} an array of wml tables (read/write)<br />
* '''__cfg''': WML table (dump) ([[SingleUnitWML]])<br />
* {{DevFeature1.13|2}} The following fields are unit methods synonymous to one of the functions described on this page:<br />
** '''[[#wesnoth.match_unit|matches]]'''<br />
** '''[[#wesnoth.put_recall_unit|to_recall]]'''<br />
** '''[[#wesnoth.put_unit|to_map]]'''<br />
** '''[[#wesnoth.erase_unit|erase]]'''<br />
** '''[[#wesnoth.copy_unit|clone]]'''<br />
** '''[[#wesnoth.extract_unit|extract]]'''<br />
** '''[[#wesnoth.advance_unit|advance]]'''<br />
** '''[[#wesnoth.add_modification|add_modification]]'''<br />
** '''[[#wesnoth.remove_modifications|remove_modifications]]'''<br />
** '''[[#wesnoth.unit_resistance|resistance]]'''<br />
** '''[[#wesnoth.unit_defense|defense]]'''<br />
** '''[[#wesnoth.unit_movement_cost|movement]]'''<br />
** '''[[#wesnoth.unit_vision_cost|vision]]'''<br />
** '''[[#wesnoth.unit_jamming_cost|jamming]]'''<br />
** '''[[#wesnoth.unit_ability|ability]]'''<br />
** '''[[#wesnoth.transform_unit|transform]]'''<br />
The metatable of these proxy tables appears as '''"unit"'''.<br />
<br />
A unit can be either visible on the map ([[#wesnoth.get_units]], [[#wesnoth.put_unit]]), or on a recall list ([[#wesnoth.get_recall_units]], [[#wesnoth.put_recall_unit]]), or private to the Lua code ([[#wesnoth.create_unit]], [[#wesnoth.copy_unit]], [[#wesnoth.extract_unit]]). The Lua code has complete control over the private units; they will not be modified unless accessed through the proxy unit. Units on the map and on the recall lists, however, can be modified by the user, the engine, WML, independently of the Lua code. In particular, if a unit is killed, any further use of the proxy unit will cause an error. For units on the map, the proxy unit is valid as long as there is a unit on the map that has the same "underlying_id" WML field as the original one. The behavior is similar for units on the recall lists. The ''valid'' field reflects the unit availability by returning '''"map"''', '''"recall"''', '''"private"''', or ''nil''. The latter value is used for units that were removed (e.g. killed). In that case, the ''valid'' field is the only one that can be read without causing an error.<br />
<br />
The term "proxy", here in particular "proxy unit", means that the variable retrieved in the lua code (with get_units for example) is an accessor (reference) to the C++ object which represents that unit. This is very different from unit variables obtained by [store_unit] in wml. The fields marked as "writable" above can be modified without the need to use put_unit afterwards. This same reason explains that modifications to the unit from outside the lua code (like [kill] invalidating the proxy unit) have immediate effect on the lua code's proxy unit variable (with the exception of private proxy units).<br />
<br />
<br />
==== wesnoth.get_units ====<br />
<br />
* '''wesnoth.get_units(''filter'')'''<br />
* {{DevFeature1.13|12}} '''wesnoth.get_units(''filter'', ''fake_location'')'''<br />
* {{DevFeature1.13|12}} '''wesnoth.get_units(''filter'', ''other_unit'')'''<br />
<br />
Returns an array of all the units on the map matching the WML filter passed as the first argument. See [[StandardUnitFilter]] for details about filters. If a second unit is passed, it can be referenced via the $other_unit variable in the main filter as well as via the "other" variable in WFL formulas used in the main filter. If a location is passed, the filter is run as if the unit were at that location (rather than its real location). This affects things such as [filter_adjacent] and ability_active, and should work even for a unit on the recall list.<br />
<br />
<syntaxhighlight lang='lua'><br />
local leaders_on_side_two = wesnoth.get_units { side = 2, canrecruit = true }<br />
local name_of_leader = leaders_on_side_two[1].name<br />
</syntaxhighlight><br />
<br />
==== wesnoth.get_unit ====<br />
<br />
* '''wesnoth.get_unit(''x'', ''y'')'''<br />
* '''wesnoth.get_unit(''underlying_id'')'''<br />
<br />
Returns the unit at the given location or with the given underlying ID.<br />
<br />
<syntaxhighlight lang='lua'><br />
local args = ...<br />
local unit = wesnoth.get_unit(args.x1, args.y1)<br />
</syntaxhighlight><br />
<br />
==== wesnoth.match_unit ====<br />
<br />
* '''wesnoth.match_unit(''unit'', ''filter'')'''<br />
* {{DevFeature1.13|2}} '''wesnoth.match_unit(''unit'', ''filter'', ''other_unit'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':matches(''filter'', [''other_unit''])'''<br />
* {{DevFeature1.13|2}} '''wesnoth.match_unit(''unit'', ''filter'', ''location'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':matches(''filter'', [''location''])'''<br />
<br />
Returns true if the given unit matches the WML filter passed as the second argument. If ''other_unit'' is specified, it is used for the ''$other_unit'' auto-stored variable in the filter. Otherwise, this variable is not stored for the filter. If an extra ''location'' is specified, the filter matches as if the unit were at that location.<br />
<br />
<syntaxhighlight lang='lua'><br />
assert(unit.canrecruit == wesnoth.match_unit(unit, { canrecruit = true }))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.put_unit ====<br />
<br />
* '''wesnoth.put_unit(''unit'')'''<br />
* '''wesnoth.put_unit(''x'', ''y'', ''unit'')'''<br />
* '''wesnoth.put_unit(''x'', ''y'')'''<br />
* {{DevFeature1.13|2}} '''wesnoth.put_unit(''unit'', ''x'', ''y'')''' -- The above two forms are also deprecated.<br />
* {{DevFeature1.13|2}} '''''unit'':to_map([''x'', ''y''])<br />
<br />
Places a unit on the map. This unit is described either by a WML table or by a proxy unit. Coordinates can be passed as the first two arguments, otherwise the table is expected to have two fields '''x''' and '''y''', which indicate where the unit will be placed. If the function is called with coordinates only, the unit on the map at the given coordinates is removed instead. {{DevFeature1.13|2}} This use is now deprecated; use wesnoth.erase_unit instead.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- create a unit with random traits, then erase it<br />
wesnoth.put_unit(17, 42, { type = "Elvish Lady" })<br />
wesnoth.put_unit(17, 42)<br />
</syntaxhighlight><br />
<br />
When the argument is a proxy unit, no duplicate is created. In particular, if the unit was private or on a recall list, it no longer is; and if the unit was on the map, it has been moved to the new location. Note: passing a WML table is just a shortcut for calling [[#wesnoth.create_unit]] and then putting the resulting unit on the map.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- move the leader back to the top-left corner<br />
wesnoth.put_unit(1, 1, wesnoth.get_units({ canrecruit = true })[1])<br />
</syntaxhighlight><br />
<br />
==== wesnoth.erase_unit ====<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
* '''wesnoth.erase_unit(''unit'')'''<br />
* '''wesnoth.erase_unit(''x'', ''y'')'''<br />
* '''''unit'':erase()'''<br />
<br />
Erases a unit from the map. After calling this on a unit, the unit is no longer valid.<br />
<br />
==== wesnoth.get_recall_units ====<br />
<br />
* '''wesnoth.get_recall_units()'''<br />
<br />
Returns an array of all the units on the recall lists matching the WML filter passed as the first argument.<br />
<br />
==== wesnoth.put_recall_unit ====<br />
<br />
* '''wesnoth.put_recall_unit(''unit'', [''side''])'''<br />
* {{DevFeature1.13|2}} '''''unit'':to_recall([''side''])'''<br />
<br />
Places a unit on a recall list. This unit is described either by a WML table or by a proxy unit. The side of the recall list is given by the second argument, or by the side of the unit if missing.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- put the unit at location 17,42 on the recall list for side 2<br />
wesnoth.put_recall_unit(wesnoth.get_units({ x= 17, y = 42 })[1], 2)<br />
</syntaxhighlight><br />
<br />
When the argument is a proxy unit, no duplicate is created. In particular, if the unit was private or on the map, it no longer is. Note: passing a WML table is just a shortcut for calling [[#wesnoth.create_unit]] and then putting the resulting unit on a recall list.<br />
<br />
==== wesnoth.create_unit ====<br />
<br />
* '''wesnoth.create_unit(''unit_info'')'''<br />
<br />
Creates a private unit from a WML table.<br />
<br />
<syntaxhighlight lang='lua'><br />
local u = wesnoth.create_unit { type = "White Mage", gender = "female" }<br />
</syntaxhighlight><br />
<br />
==== wesnoth.copy_unit ====<br />
<br />
* '''wesnoth.copy_unit(''unit'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':clone()'''<br />
<br />
Creates a private unit from another unit.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- extract a unit from the map<br />
local u = wesnoth.copy_unit(wesnoth.get_units({ type = "Thug" })[1])<br />
wesnoth.erase_unit(u.x, u.y)<br />
-- u is still valid at this point<br />
</syntaxhighlight><br />
<br />
==== wesnoth.extract_unit ====<br />
<br />
* '''wesnoth.extract_unit(''unit'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':extract()'''<br />
<br />
Removes a unit from the map or from a recall list and makes it private.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- remove all the units from the recall list of side 1 and put them in a WML container<br />
local l = {}<br />
for i,u in ipairs(wesnoth.get_recall_units { side = 1 }) do<br />
wesnoth.extract_unit(u)<br />
table.insert(l, u.__cfg)<br />
end<br />
helper.set_variable_array("player_recall_list", l)<br />
</syntaxhighlight><br />
<br />
Note: if the unit is on the map, it is just a shortcut for calling [[#wesnoth.copy_unit]] and then [[#wesnoth.put_unit]] without a unit. It is, however, the only way for removing a unit from a recall list without putting it on the map.<br />
<br />
<br />
==== wesnoth.advance_unit ====<br />
<br />
* '''wesnoth.advance_unit(''unit'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':advance()'''<br />
<br />
{{DevFeature1.13|0}} Advances the unit (and shows the advance unit dialog if needed) if the unit has enough xp. This function should be called after modifying the units experience directly. A similar function is called by wesnoth internally after unit combat. The second argument is a boodean value that specifies whether the advancement should be animated. The third agrument is a boodean value that specifies whether advancement related events should be fired.<br />
<br />
<br />
This function only works for units on the map.<br />
<br />
This function can also trigger multiple advancements if the unit has enough xp.<br />
<br />
==== wesnoth.add_modification ====<br />
<br />
* '''wesnoth.add_modification(''unit'', ''type'', ''effects'', [''write_to_mods''])'''<br />
* {{DevFeature1.13|2}} '''''unit'':add_modification(''type'', ''effects'', [''write_to_mods''])'''<br />
<br />
Modifies a given unit. It needs to be a proxy unit. The second argument is the type of the modification (one of "trait", "object", or "advance"). The option "advance" applies effects as if the unit would advance (e.g. AMLA effects). The third argument is a WML table describing the effect, so mostly containing '''[effect]''' children. See [[EffectWML]] for details about effects.<br />
<br />
{{DevFeature1.13|2}} In 1.13.2 and later, the "advance" type is replaced with "advancement", to match the equivalent tag in [[UnitTypeWML|[unit_type]]]. Also, it takes a fourth argument which, if false, causes it to not write the modification tag to the unit's [modifications] (as would be done with an [object] with no_write=true).<br />
<br />
<syntaxhighlight lang='lua'><br />
local T = wml.tags<br />
local u = wesnoth.get_units { canrecruit = true }[1]<br />
local effects = {<br />
id = "my_effect_id",<br />
T.effect { <br />
apply_to = "image_mod", <br />
replace = "RC(red>blue)" <br />
},<br />
T.effect {<br />
apply_to = "new_animation",<br />
T.standing_animation {<br />
-- AnimationWML<br />
}<br />
}<br />
} <br />
wesnoth.add_modification(u, "object", effects)<br />
</syntaxhighlight><br />
<br />
==== wesnoth.remove_modifications ====<br />
<br />
* {{DevFeature1.13|?}} '''wesnoth.remove_modifications(''unit'', ''cfg'' [, ''type''])'''<br />
* {{DevFeature1.13|?}} '''''unit'':remove_modifications(''cfg'' [, ''type''])'''<br />
<br />
Modifies a given unit. The unit needs to be a proxy unit. The second argument is a filter for the modifications to remove. It takes the same syntax as [[FilterWML#Filtering_on_WML_data|[filter_wml]]]; all matching modifications will be removed. The third argument is the type (tag name) of the modifications to search for; it defaults to <tt>"object"</tt>, but you can also pass <tt>"trait"</tt> or <tt>"advancement"</tt>.<br />
<br />
<syntaxhighlight lang='lua'><br />
local u = wesnoth.get_units { canrecruit = true }[1]<br />
wesnoth.remove_modifications(u, { id = "my_effect_id" })<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_resistance ====<br />
<br />
* '''wesnoth.unit_resistance(''unit'', ''damage_type'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':resistance(''damage_type'')'''<br />
<br />
Returns the resistance of a unit against an attack type. (Note: it is a WML resistance. So the higher it is, the weaker the unit is.) The third argument indicates whether the unit is the attacker. Last arguments are the coordinates of an optional map location (for the purpose of taking abilities into account).<br />
<br />
<syntaxhighlight lang='lua'><br />
local fire_resistance = 100 - wesnoth.unit_resistance(u, "fire")<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_defense ====<br />
<br />
* '''wesnoth.unit_defense(''unit'', ''terrain_code'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':defense(''terrain_code'')'''<br />
<br />
Returns the defense of a unit on a particular terrain. (Note: it is a WML defense. So the higher it is, the weaker the unit is.)<br />
<br />
<syntaxhighlight lang='lua'><br />
local flat_defense = 100 - wesnoth.unit_defense(u, "Gt")<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_movement_cost ====<br />
<br />
* '''wesnoth.unit_movement_cost(''unit'', ''terrain_code'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':movement(''terrain_code'')'''<br />
<br />
Returns the movement cost of a unit on a particular terrain.<br />
<br />
<syntaxhighlight lang='lua'><br />
local move_cost = wesnoth.unit_movement_cost(u, "Gt")<br />
<syntaxhighlight><br />
<br />
==== wesnoth.unit_vision_cost ====<br />
<br />
* '''wesnoth.unit_vision_cost(''unit'', ''terrain_code'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':vision(''terrain_code'')'''<br />
<br />
Returns the vision cost of a unit on a particular terrain.<br />
<br />
<syntaxhighlight lang='lua'><br />
local see_cost = wesnoth.unit_vision_cost(u, "Gt")<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_jamming_cost ====<br />
<br />
* '''wesnoth.unit_jamming_cost(''unit'', ''terrain_code'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':jamming(''terrain_code'')'''<br />
<br />
Returns the jamming cost of a unit on a particular terrain.<br />
<br />
<syntaxhighlight lang='lua'><br />
local jam_cost = wesnoth.unit_jamming_cost(u, "Gt")<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_ability ====<br />
<br />
* '''wesnoth.unit_ability(''unit'', ''ability_tag'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':ability(''ability_tag'')'''<br />
<br />
Returns true if the unit is currently under effect by an ability with this given TAG NAME. This means that the ability could be owned by the unit itself, or by an adjacent unit.<br />
<br />
<syntaxhighlight lang='lua'><br />
function has_teleport(u)<br />
return wesnoth.unit_ability(u, "teleport")<br />
end<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_types ====<br />
<br />
This is not a function but a read-only table indexed by unit type ids. Its elements are proxy tables with these fields:<br />
<br />
* '''id''': string<br />
* '''name''': translatable string (read only)<br />
* '''max_moves''', '''max_experience''', '''max_hitpoints''', '''level''', '''cost''': integers (read only)<br />
* '''abilities''': array of ability keys (strings), e.g. {"curing", "regenerates"}<br />
* {{DevFeature1.13|11}} '''advances_to''': array of unit types to which unit can advance<br />
* {{DevFeature1.13|11}} '''advances_from''': array of unit types from which unit can advance. Note: this is OOS-unsafe in Multiplayer games. Different clients may have additional Era-s with units upgradable to this unit type.<br />
* '''__cfg''': WML table (dump), see [[UnitTypeWML]]<br />
<br />
The metatable of these proxy tables appears as '''"unit type"'''.<br />
<br />
<syntaxhighlight lang='lua'><br />
local lich_cost = wesnoth.unit_types["Ancient Lich"].cost<br />
</syntaxhighlight><br />
<br />
Note that different clients have different set of available units in a Multiplayer game. It is OOS-unsafe to e.g. count the number of units.<br />
Presuming correctly written add-ons, it is still safe to e.g. access any given unit or its properties.<br />
<br />
==== wesnoth.races ====<br />
<br />
This is not a function but a table indexed by race ids. Its elements are proxy tables for all races the engine knows about.<br />
known fields of each element:<br />
* '''id''': string<br />
* '''description''', '''name''', '''plural_name''' (translatable strings)<br />
* '''num_traits''' (integer)<br />
* '''ignore_global_traits''' (boolean)<br />
* '''undead_variation''' (string)<br />
(all read only)<br />
* '''__cfg''': WML table (dump)<br />
<br />
<syntaxhighlight lang='lua'><br />
wesnoth.message(tostring(wesnoth.races["lizard"].name))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.get_traits ====<br />
<br />
* '''wesnoth.get_traits()'''<br />
<br />
Returns a table with named fields (trait id strings) holding the wml tables defining the traits. arguments: none. All global traits the engine knows about, race-specific traits are not included.<br />
Known fields and subtags of each element are the ones which were given in the wml definition of the [[SingleUnitWML|trait]].<br />
wesnoth.message(tostring(wesnoth.get_traits().strong.male_name))<br />
<br />
==== wesnoth.simulate_combat ====<br />
<br />
* '''wesnoth.simulate_combat(''attacker'', [''attacker_weapon_index''], ''defender'', [''defender_weapon_index''])'''<br />
<br />
Computes the hitpoint distribution and status chance after a combat between two units. The first unit is the attacker; it does not have to be on the map, though its location should be meaningful. The second unit is the defender; it has to be on the map.<br />
<br />
Optional integers can be passed after each unit to select a particular weapon, otherwise the "best" one is selected. When giving the weapon, the parameter is the weapon number (integer, starting at 1) and not an element from the table returned by helper.child_range(att, "attack").<br />
<br />
<syntaxhighlight lang='lua'><br />
local function display_stats(n, t)<br />
wesnoth.message(string.format(<br />
"Chance for the %s\n to be slowed: %f,\n to be poisoned: %f,\n to die: %f.\nAverage HP: %f.",<br />
n, t.slowed, t.poisoned, t.hp_chance[0], t.average_hp))<br />
end<br />
local att_stats, def_stats = wesnoth.simulate_combat(att, att_weapon, def, def_weapon)<br />
display_stats("attacker", att_stats)<br />
display_stats("defender", def_stats)<br />
</syntaxhighlight><br />
<br />
Returns 2 additional tables which contain information about the weapons and the effect of single hits with these keys: num_blows, damage, chance_to_hit, poisons, slows, petrifies, plagues, plague_type, backstabs, rounds, firststrike, drains, drain_constant, drain_percent, attack_num, name. <br />
Name is the wml name not the description. If there is no weapon, then name will be nil<br />
<br />
<syntaxhighlight lang='lua'><br />
local att_stats, def_stats, att_weapon, def_weapon = wesnoth.simulate_combat(attacker, att_weapon_number, defender)<br />
wesnoth.message(string.format(<br />
"The attack %s should be countered with %s, which does %d damage, has %d%% chance to hit and forces %d attack rounds due to its berserk ability.",<br />
att_weapon.name, def_weapon.name or "no weapon", def_weapon.damage, def_weapon.chance_to_hit, def_weapon.rounds))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.transform_unit ====<br />
<br />
* '''wesnoth.transform_unit(''unit'', ''to_type'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':transform(''to_type'')'''<br />
<br />
Changes the type of a unit and adjust attributes accordingly. Note that hit points are only changed if necessary to accommodate the new maximum hit points. Poison is automatically removed if the transformed unit is immune.<br />
<br />
<syntaxhighlight lang='lua'><br />
local ev = wesnoth.current.event_context<br />
local u = wesnoth.get_units{x=ev.x1, y=ev.y1}[1]<br />
wesnoth.transform_unit(u, "Spearman")<br />
-- If a full heal is desired:<br />
u.hitpoints = u.max_hitpoints<br />
u.status.poisoned = false<br />
</syntaxhighlight><br />
<br />
==== wesnoth.add_known_unit ====<br />
<br />
* {{DevFeature1.13|10}} '''wesnoth.add_known_unit(''unit_type_id'')'''<br />
<br />
adds the unit type with the given id to the list of known units (so that they appear in the help)<br />
<br />
==== wesnoth.create_animator ====<br />
<br />
{{DevFeature1.13|7}}<br />
<br />
* '''wesnoth.create_animator()'''<br />
<br />
Returns an object that can be used to set up and run an animation. The object has three methods:<br />
<br />
* '''animator:run()'''<br />
<br />
Runs the animation. {{DevFeature1.15|0}} Implicitly clears the animator.<br />
<br />
* '''animator:clear()'''<br />
<br />
Clears any units previously added to the animation.<br />
<br />
* '''animator:add(''unit'', ''flag'', ''hits'', ''params'')'''<br />
<br />
Adds a unit to the animation. The ''flag'' specifies which animation to play, and the ''hits'' parameter is required for attack animations to specify which variant of the animation to play. Possibly keys in ''params'' are:<br />
<br />
* '''facing''': A location. The animation will be played with the unit facing that location.<br />
* '''value''': Either a number or a list of two numbers. Use this to pass ''value'' and/or ''value_second'' to default animations that use them.<br />
* '''with_bars''': Whether to show HP bars and such while the animation plays.<br />
* '''text''': Text to float as the animation plays.<br />
* '''color''': Color of the floating text - a list of red, green, blue.<br />
* '''primary''': The primary weapon to use for the animation. Must be a Lua unit attack proxy.<br />
* '''secondary''': The secondary weapon to use for the animation.<br />
<br />
Normal usage would be to create it, call '''add''' one or more times, then call '''run'''.<br />
<br />
==== wesnoth.effects ====<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
This table contains the implementation of custom [[EffectWML|[effect]]]s. Each value is a function that takes a unit and the effect config. Note that the default effects defined by the Wesnoth engine are not in this table. <br />
<br />
<syntaxhighlight lang='lua'><br />
function wesnoth.effects.min_resistance(u, cfg)<br />
local resistance_new = {}<br />
local resistance_old = helper.parsed(helper.get_child(cfg, "resistance"))<br />
for k,v in pairs(resistance_old) do<br />
if type(k) == "string" and type(v) == "number" and wesnoth.unit_resistance(u, k) >= v then<br />
resistance_new[k] = v<br />
end<br />
end<br />
--important: use wesnoth.add_modification(..., false) so that the function will only execute the effects of that object and not store the object in the unit.<br />
wesnoth.add_modification(u, "object", {<br />
T.effect {<br />
apply_to = "resistance",<br />
replace = true,<br />
T.resistance (resistance_new),<br />
},<br />
}, false)<br />
end<br />
</syntaxhighlight><br />
<br />
The code above adds a new <code>min_resistance</code> effect that will set the resistances to specific values if they are currently below that value. It can then be used like this (for example, in [[DirectActionsWML#.5Bobject.5D|[object]]]):<br />
<br />
<syntaxhighlight lang='wml'><br />
[effect]<br />
apply_to=min_resistance<br />
[resistance]<br />
cold=50<br />
[/resistance]<br />
[/effect]<br />
</syntaxhighlight><br />
<br />
Note that because currently all Lua code is executed after [unit]s in [side] are created, it is currently not possible to use these effects in [unit]s in [side]<br />
<br />
{{DevFeature1.13|5}}<br />
<br />
Built-in effects are now present in the <code>wesnoth.effects</code> table and can be called by custom effects or by other Lua code. They take the same two arguments that a custom effect function does - the unit, and the effect WML.<br />
<br />
In addition, you can now specify description modifiers to be used if a custom effect is placed in a <code>[trait]</code> tag. Instead of setting a function as the effect, you set a table with a <code>__call</code> metafunction which does what the function would have done. The table can then have an additional <code>__descr</code> metafunction which updates descriptions as necessary. The built-in effects all use this structure. This metafunction takes the same arguments as the regular effect function, but should not modify the unit. Instead, it returns a string to be appended to the trait's effect description.<br />
<br />
[[Category: Lua Reference]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=LuaWML/Units&diff=60000LuaWML/Units2018-11-05T02:16:02Z<p>Namhub: /* wesnoth.add_modification */ improve add_modification example</p>
<hr />
<div>This page describes the [[LuaWML]] functions for handling units.<br />
<br />
A unit is a proxy table with the following fields:<br />
* '''x''', '''y''': integers (read only, read/write if the unit is not on the map. {{DevFeature1.13|11}} These are now read/write under all circumstances, including for on-map units)<br />
* '''loc''': {{DevFeature1.13|11}} shortcut to get/set both x and y at once (read/write). Setting x and y individually would result in two moves, and there's the possibility that the intermediate move fails if the hex is occupied by another unit. In general, note that moving a unit by changing the proxy unit's coordinates does not work if the goal hex is occupied (it is not executed), so it is necessary to check if the hex is available first.<br />
* '''side''': integer (read/write)<br />
* '''id''': string (read only)<br />
* '''type''': string (read only)<br />
* '''name''': translatable string (read only)<br />
* '''cost''' {{DevFeature1.13|10}}: integer (read)<br />
* '''max_hitpoints''', '''max_experience''', '''max_moves''': integers (read only)<br />
* '''max_attacks''': integer (read only)<br />
* '''attacks_left''': integer (read/write) Setting below 0 is limited to 0.<br />
* '''extra_recruit''': table (read/write)<br />
* '''advances_to''': table (read/write)<br />
* '''hitpoints''', '''experience''': integer (read/write)<br />
* '''moves''': integer (read/write)<br />
* '''level''': {{DevFeature1.13|5}} integer (read/write)<br />
* '''resting''': boolean (read/write)<br />
* '''hidden''': boolean (read/write)<br />
* '''petrified''', '''canrecruit''': booleans (read only)<br />
* '''role''', '''facing''': strings (read/write)<br />
* '''status''': proxy associative table (read only, read/write fields), provides fields like [[SingleUnitWML#Unit_State|poisoned, slowed, petrified, uncovered, guardian, unhealable, invulnerable]]<br />
* '''image_mods''': string (read only)<br />
* '''upkeep''' {{DevFeature1.13|5}}: one of 'loyal', 'full' or a number (read/writre)<br />
* '''variables''': proxy associative table (read only, read/write fields, including ''variables.__cfg''), only toplevel named fields are proxied. {{DevFeature1.13|2}} subcontainers can be accessed by using the usual variable syntax: <syntaxhighlight inline lang='lua'>unit.variables["a.b.c[6].d"]</syntaxhighlight><br />
* '''attacks''': {{DevFeature1.13|0}}an object to access the units attacks, you can use the attacks index or the attacks name to index an attack. every attack has the following members:<br />
** '''description''': translatable string (read/write)<br />
** '''name''': string (read)<br />
** '''type''': string (read/write)<br />
** '''range''': string (read/write)<br />
** '''damage''': number(read/write)<br />
** '''number''': number(read/write)<br />
** '''movement_used''': number(read/write)<br />
** '''attack_weight''': number(read/write)<br />
** '''defense_weight''': number(read/write)<br />
** '''specials''' wml table(read/write)<br />
* '''valid''': string or nil (read only)<br />
* '''advancements''': {{DevFeature1.13|2}} an array of wml tables (read/write)<br />
* '''__cfg''': WML table (dump) ([[SingleUnitWML]])<br />
* {{DevFeature1.13|2}} The following fields are unit methods synonymous to one of the functions described on this page:<br />
** '''[[#wesnoth.match_unit|matches]]'''<br />
** '''[[#wesnoth.put_recall_unit|to_recall]]'''<br />
** '''[[#wesnoth.put_unit|to_map]]'''<br />
** '''[[#wesnoth.erase_unit|erase]]'''<br />
** '''[[#wesnoth.copy_unit|clone]]'''<br />
** '''[[#wesnoth.extract_unit|extract]]'''<br />
** '''[[#wesnoth.advance_unit|advance]]'''<br />
** '''[[#wesnoth.add_modification|add_modification]]'''<br />
** '''[[#wesnoth.remove_modifications|remove_modifications]]'''<br />
** '''[[#wesnoth.unit_resistance|resistance]]'''<br />
** '''[[#wesnoth.unit_defense|defense]]'''<br />
** '''[[#wesnoth.unit_movement_cost|movement]]'''<br />
** '''[[#wesnoth.unit_vision_cost|vision]]'''<br />
** '''[[#wesnoth.unit_jamming_cost|jamming]]'''<br />
** '''[[#wesnoth.unit_ability|ability]]'''<br />
** '''[[#wesnoth.transform_unit|transform]]'''<br />
The metatable of these proxy tables appears as '''"unit"'''.<br />
<br />
A unit can be either visible on the map ([[#wesnoth.get_units]], [[#wesnoth.put_unit]]), or on a recall list ([[#wesnoth.get_recall_units]], [[#wesnoth.put_recall_unit]]), or private to the Lua code ([[#wesnoth.create_unit]], [[#wesnoth.copy_unit]], [[#wesnoth.extract_unit]]). The Lua code has complete control over the private units; they will not be modified unless accessed through the proxy unit. Units on the map and on the recall lists, however, can be modified by the user, the engine, WML, independently of the Lua code. In particular, if a unit is killed, any further use of the proxy unit will cause an error. For units on the map, the proxy unit is valid as long as there is a unit on the map that has the same "underlying_id" WML field as the original one. The behavior is similar for units on the recall lists. The ''valid'' field reflects the unit availability by returning '''"map"''', '''"recall"''', '''"private"''', or ''nil''. The latter value is used for units that were removed (e.g. killed). In that case, the ''valid'' field is the only one that can be read without causing an error.<br />
<br />
The term "proxy", here in particular "proxy unit", means that the variable retrieved in the lua code (with get_units for example) is an accessor (reference) to the C++ object which represents that unit. This is very different from unit variables obtained by [store_unit] in wml. The fields marked as "writable" above can be modified without the need to use put_unit afterwards. This same reason explains that modifications to the unit from outside the lua code (like [kill] invalidating the proxy unit) have immediate effect on the lua code's proxy unit variable (with the exception of private proxy units).<br />
<br />
<br />
==== wesnoth.get_units ====<br />
<br />
* '''wesnoth.get_units(''filter'')'''<br />
* {{DevFeature1.13|12}} '''wesnoth.get_units(''filter'', ''fake_location'')'''<br />
* {{DevFeature1.13|12}} '''wesnoth.get_units(''filter'', ''other_unit'')'''<br />
<br />
Returns an array of all the units on the map matching the WML filter passed as the first argument. See [[StandardUnitFilter]] for details about filters. If a second unit is passed, it can be referenced via the $other_unit variable in the main filter as well as via the "other" variable in WFL formulas used in the main filter. If a location is passed, the filter is run as if the unit were at that location (rather than its real location). This affects things such as [filter_adjacent] and ability_active, and should work even for a unit on the recall list.<br />
<br />
<syntaxhighlight lang='lua'><br />
local leaders_on_side_two = wesnoth.get_units { side = 2, canrecruit = true }<br />
local name_of_leader = leaders_on_side_two[1].name<br />
</syntaxhighlight><br />
<br />
==== wesnoth.get_unit ====<br />
<br />
* '''wesnoth.get_unit(''x'', ''y'')'''<br />
* '''wesnoth.get_unit(''underlying_id'')'''<br />
<br />
Returns the unit at the given location or with the given underlying ID.<br />
<br />
<syntaxhighlight lang='lua'><br />
local args = ...<br />
local unit = wesnoth.get_unit(args.x1, args.y1)<br />
</syntaxhighlight><br />
<br />
==== wesnoth.match_unit ====<br />
<br />
* '''wesnoth.match_unit(''unit'', ''filter'')'''<br />
* {{DevFeature1.13|2}} '''wesnoth.match_unit(''unit'', ''filter'', ''other_unit'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':matches(''filter'', [''other_unit''])'''<br />
* {{DevFeature1.13|2}} '''wesnoth.match_unit(''unit'', ''filter'', ''location'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':matches(''filter'', [''location''])'''<br />
<br />
Returns true if the given unit matches the WML filter passed as the second argument. If ''other_unit'' is specified, it is used for the ''$other_unit'' auto-stored variable in the filter. Otherwise, this variable is not stored for the filter. If an extra ''location'' is specified, the filter matches as if the unit were at that location.<br />
<br />
<syntaxhighlight lang='lua'><br />
assert(unit.canrecruit == wesnoth.match_unit(unit, { canrecruit = true }))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.put_unit ====<br />
<br />
* '''wesnoth.put_unit(''unit'')'''<br />
* '''wesnoth.put_unit(''x'', ''y'', ''unit'')'''<br />
* '''wesnoth.put_unit(''x'', ''y'')'''<br />
* {{DevFeature1.13|2}} '''wesnoth.put_unit(''unit'', ''x'', ''y'')''' -- The above two forms are also deprecated.<br />
* {{DevFeature1.13|2}} '''''unit'':to_map([''x'', ''y''])<br />
<br />
Places a unit on the map. This unit is described either by a WML table or by a proxy unit. Coordinates can be passed as the first two arguments, otherwise the table is expected to have two fields '''x''' and '''y''', which indicate where the unit will be placed. If the function is called with coordinates only, the unit on the map at the given coordinates is removed instead. {{DevFeature1.13|2}} This use is now deprecated; use wesnoth.erase_unit instead.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- create a unit with random traits, then erase it<br />
wesnoth.put_unit(17, 42, { type = "Elvish Lady" })<br />
wesnoth.put_unit(17, 42)<br />
</syntaxhighlight><br />
<br />
When the argument is a proxy unit, no duplicate is created. In particular, if the unit was private or on a recall list, it no longer is; and if the unit was on the map, it has been moved to the new location. Note: passing a WML table is just a shortcut for calling [[#wesnoth.create_unit]] and then putting the resulting unit on the map.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- move the leader back to the top-left corner<br />
wesnoth.put_unit(1, 1, wesnoth.get_units({ canrecruit = true })[1])<br />
</syntaxhighlight><br />
<br />
==== wesnoth.erase_unit ====<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
* '''wesnoth.erase_unit(''unit'')'''<br />
* '''wesnoth.erase_unit(''x'', ''y'')'''<br />
* '''''unit'':erase()'''<br />
<br />
Erases a unit from the map. After calling this on a unit, the unit is no longer valid.<br />
<br />
==== wesnoth.get_recall_units ====<br />
<br />
* '''wesnoth.get_recall_units()'''<br />
<br />
Returns an array of all the units on the recall lists matching the WML filter passed as the first argument.<br />
<br />
==== wesnoth.put_recall_unit ====<br />
<br />
* '''wesnoth.put_recall_unit(''unit'', [''side''])'''<br />
* {{DevFeature1.13|2}} '''''unit'':to_recall([''side''])'''<br />
<br />
Places a unit on a recall list. This unit is described either by a WML table or by a proxy unit. The side of the recall list is given by the second argument, or by the side of the unit if missing.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- put the unit at location 17,42 on the recall list for side 2<br />
wesnoth.put_recall_unit(wesnoth.get_units({ x= 17, y = 42 })[1], 2)<br />
</syntaxhighlight><br />
<br />
When the argument is a proxy unit, no duplicate is created. In particular, if the unit was private or on the map, it no longer is. Note: passing a WML table is just a shortcut for calling [[#wesnoth.create_unit]] and then putting the resulting unit on a recall list.<br />
<br />
==== wesnoth.create_unit ====<br />
<br />
* '''wesnoth.create_unit(''unit_info'')'''<br />
<br />
Creates a private unit from a WML table.<br />
<br />
<syntaxhighlight lang='lua'><br />
local u = wesnoth.create_unit { type = "White Mage", gender = "female" }<br />
</syntaxhighlight><br />
<br />
==== wesnoth.copy_unit ====<br />
<br />
* '''wesnoth.copy_unit(''unit'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':clone()'''<br />
<br />
Creates a private unit from another unit.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- extract a unit from the map<br />
local u = wesnoth.copy_unit(wesnoth.get_units({ type = "Thug" })[1])<br />
wesnoth.erase_unit(u.x, u.y)<br />
-- u is still valid at this point<br />
</syntaxhighlight><br />
<br />
==== wesnoth.extract_unit ====<br />
<br />
* '''wesnoth.extract_unit(''unit'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':extract()'''<br />
<br />
Removes a unit from the map or from a recall list and makes it private.<br />
<br />
<syntaxhighlight lang='lua'><br />
-- remove all the units from the recall list of side 1 and put them in a WML container<br />
local l = {}<br />
for i,u in ipairs(wesnoth.get_recall_units { side = 1 }) do<br />
wesnoth.extract_unit(u)<br />
table.insert(l, u.__cfg)<br />
end<br />
helper.set_variable_array("player_recall_list", l)<br />
</syntaxhighlight><br />
<br />
Note: if the unit is on the map, it is just a shortcut for calling [[#wesnoth.copy_unit]] and then [[#wesnoth.put_unit]] without a unit. It is, however, the only way for removing a unit from a recall list without putting it on the map.<br />
<br />
<br />
==== wesnoth.advance_unit ====<br />
<br />
* '''wesnoth.advance_unit(''unit'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':advance()'''<br />
<br />
{{DevFeature1.13|0}} Advances the unit (and shows the advance unit dialog if needed) if the unit has enough xp. This function should be called after modifying the units experience directly. A similar function is called by wesnoth internally after unit combat. The second argument is a boodean value that specifies whether the advancement should be animated. The third agrument is a boodean value that specifies whether advancement related events should be fired.<br />
<br />
<br />
This function only works for units on the map.<br />
<br />
This function can also trigger multiple advancements if the unit has enough xp.<br />
<br />
==== wesnoth.add_modification ====<br />
<br />
* '''wesnoth.add_modification(''unit'', ''type'', ''effects'', [''write_to_mods''])'''<br />
* {{DevFeature1.13|2}} '''''unit'':add_modification(''type'', ''effects'', [''write_to_mods''])'''<br />
<br />
Modifies a given unit. It needs to be a proxy unit. The second argument is the type of the modification (one of "trait", "object", or "advance"). The option "advance" applies effects as if the unit would advance (e.g. AMLA effects). The third argument is a WML table describing the effect, so mostly containing '''[effect]''' children. See [[EffectWML]] for details about effects.<br />
<br />
{{DevFeature1.13|2}} In 1.13.2 and later, the "advance" type is replaced with "advancement", to match the equivalent tag in [[UnitTypeWML|[unit_type]]]. Also, it takes a fourth argument which, if false, causes it to not write the modification tag to the unit's [modifications] (as would be done with an [object] with no_write=true).<br />
<br />
<syntaxhighlight lang='lua'><br />
local T = wml.tags<br />
local u = wesnoth.get_units { canrecruit = true }[1]<br />
local effects = {<br />
id = "my_effect_id",<br />
T.effect { <br />
apply_to = "image_mod", <br />
replace = "RC(red>blue)" <br />
},<br />
T.effect {<br />
apply_to = "new_animation",<br />
T.standing_animation {<br />
-- AnimationWML<br />
}<br />
}<br />
} <br />
wesnoth.add_modification(u, "object", effects)<br />
</syntaxhighlight><br />
<br />
==== wesnoth.remove_modifications ====<br />
<br />
* {{DevFeature1.13|?}} '''wesnoth.remove_modifications(''unit'', ''cfg'' [, ''type''])'''<br />
* {{DevFeature1.13|?}} '''''unit'':remove_modifications(''cfg'' [, ''type''])'''<br />
<br />
Modifies a given unit. The unit needs to be a proxy unit. The second argument is a filter for the modifications to remove. It takes the same syntax as [[FilterWML#Filtering_on_WML_data|[filter_wml]]]; all matching modifications will be removed. The third argument is the type (tag name) of the modifications to search for; it defaults to <tt>"object"</tt>, but you can also pass <tt>"trait"</tt> or <tt>"advancement"</tt>.<br />
<br />
<syntaxhighlight lang='lua'><br />
local u = wesnoth.get_units { canrecruit = true }[1]<br />
wesnoth.remove_modifications(u, { id = your_object_id })<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_resistance ====<br />
<br />
* '''wesnoth.unit_resistance(''unit'', ''damage_type'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':resistance(''damage_type'')'''<br />
<br />
Returns the resistance of a unit against an attack type. (Note: it is a WML resistance. So the higher it is, the weaker the unit is.) The third argument indicates whether the unit is the attacker. Last arguments are the coordinates of an optional map location (for the purpose of taking abilities into account).<br />
<br />
<syntaxhighlight lang='lua'><br />
local fire_resistance = 100 - wesnoth.unit_resistance(u, "fire")<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_defense ====<br />
<br />
* '''wesnoth.unit_defense(''unit'', ''terrain_code'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':defense(''terrain_code'')'''<br />
<br />
Returns the defense of a unit on a particular terrain. (Note: it is a WML defense. So the higher it is, the weaker the unit is.)<br />
<br />
<syntaxhighlight lang='lua'><br />
local flat_defense = 100 - wesnoth.unit_defense(u, "Gt")<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_movement_cost ====<br />
<br />
* '''wesnoth.unit_movement_cost(''unit'', ''terrain_code'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':movement(''terrain_code'')'''<br />
<br />
Returns the movement cost of a unit on a particular terrain.<br />
<br />
<syntaxhighlight lang='lua'><br />
local move_cost = wesnoth.unit_movement_cost(u, "Gt")<br />
<syntaxhighlight><br />
<br />
==== wesnoth.unit_vision_cost ====<br />
<br />
* '''wesnoth.unit_vision_cost(''unit'', ''terrain_code'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':vision(''terrain_code'')'''<br />
<br />
Returns the vision cost of a unit on a particular terrain.<br />
<br />
<syntaxhighlight lang='lua'><br />
local see_cost = wesnoth.unit_vision_cost(u, "Gt")<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_jamming_cost ====<br />
<br />
* '''wesnoth.unit_jamming_cost(''unit'', ''terrain_code'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':jamming(''terrain_code'')'''<br />
<br />
Returns the jamming cost of a unit on a particular terrain.<br />
<br />
<syntaxhighlight lang='lua'><br />
local jam_cost = wesnoth.unit_jamming_cost(u, "Gt")<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_ability ====<br />
<br />
* '''wesnoth.unit_ability(''unit'', ''ability_tag'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':ability(''ability_tag'')'''<br />
<br />
Returns true if the unit is currently under effect by an ability with this given TAG NAME. This means that the ability could be owned by the unit itself, or by an adjacent unit.<br />
<br />
<syntaxhighlight lang='lua'><br />
function has_teleport(u)<br />
return wesnoth.unit_ability(u, "teleport")<br />
end<br />
</syntaxhighlight><br />
<br />
==== wesnoth.unit_types ====<br />
<br />
This is not a function but a read-only table indexed by unit type ids. Its elements are proxy tables with these fields:<br />
<br />
* '''id''': string<br />
* '''name''': translatable string (read only)<br />
* '''max_moves''', '''max_experience''', '''max_hitpoints''', '''level''', '''cost''': integers (read only)<br />
* '''abilities''': array of ability keys (strings), e.g. {"curing", "regenerates"}<br />
* {{DevFeature1.13|11}} '''advances_to''': array of unit types to which unit can advance<br />
* {{DevFeature1.13|11}} '''advances_from''': array of unit types from which unit can advance. Note: this is OOS-unsafe in Multiplayer games. Different clients may have additional Era-s with units upgradable to this unit type.<br />
* '''__cfg''': WML table (dump), see [[UnitTypeWML]]<br />
<br />
The metatable of these proxy tables appears as '''"unit type"'''.<br />
<br />
<syntaxhighlight lang='lua'><br />
local lich_cost = wesnoth.unit_types["Ancient Lich"].cost<br />
</syntaxhighlight><br />
<br />
Note that different clients have different set of available units in a Multiplayer game. It is OOS-unsafe to e.g. count the number of units.<br />
Presuming correctly written add-ons, it is still safe to e.g. access any given unit or its properties.<br />
<br />
==== wesnoth.races ====<br />
<br />
This is not a function but a table indexed by race ids. Its elements are proxy tables for all races the engine knows about.<br />
known fields of each element:<br />
* '''id''': string<br />
* '''description''', '''name''', '''plural_name''' (translatable strings)<br />
* '''num_traits''' (integer)<br />
* '''ignore_global_traits''' (boolean)<br />
* '''undead_variation''' (string)<br />
(all read only)<br />
* '''__cfg''': WML table (dump)<br />
<br />
<syntaxhighlight lang='lua'><br />
wesnoth.message(tostring(wesnoth.races["lizard"].name))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.get_traits ====<br />
<br />
* '''wesnoth.get_traits()'''<br />
<br />
Returns a table with named fields (trait id strings) holding the wml tables defining the traits. arguments: none. All global traits the engine knows about, race-specific traits are not included.<br />
Known fields and subtags of each element are the ones which were given in the wml definition of the [[SingleUnitWML|trait]].<br />
wesnoth.message(tostring(wesnoth.get_traits().strong.male_name))<br />
<br />
==== wesnoth.simulate_combat ====<br />
<br />
* '''wesnoth.simulate_combat(''attacker'', [''attacker_weapon_index''], ''defender'', [''defender_weapon_index''])'''<br />
<br />
Computes the hitpoint distribution and status chance after a combat between two units. The first unit is the attacker; it does not have to be on the map, though its location should be meaningful. The second unit is the defender; it has to be on the map.<br />
<br />
Optional integers can be passed after each unit to select a particular weapon, otherwise the "best" one is selected. When giving the weapon, the parameter is the weapon number (integer, starting at 1) and not an element from the table returned by helper.child_range(att, "attack").<br />
<br />
<syntaxhighlight lang='lua'><br />
local function display_stats(n, t)<br />
wesnoth.message(string.format(<br />
"Chance for the %s\n to be slowed: %f,\n to be poisoned: %f,\n to die: %f.\nAverage HP: %f.",<br />
n, t.slowed, t.poisoned, t.hp_chance[0], t.average_hp))<br />
end<br />
local att_stats, def_stats = wesnoth.simulate_combat(att, att_weapon, def, def_weapon)<br />
display_stats("attacker", att_stats)<br />
display_stats("defender", def_stats)<br />
</syntaxhighlight><br />
<br />
Returns 2 additional tables which contain information about the weapons and the effect of single hits with these keys: num_blows, damage, chance_to_hit, poisons, slows, petrifies, plagues, plague_type, backstabs, rounds, firststrike, drains, drain_constant, drain_percent, attack_num, name. <br />
Name is the wml name not the description. If there is no weapon, then name will be nil<br />
<br />
<syntaxhighlight lang='lua'><br />
local att_stats, def_stats, att_weapon, def_weapon = wesnoth.simulate_combat(attacker, att_weapon_number, defender)<br />
wesnoth.message(string.format(<br />
"The attack %s should be countered with %s, which does %d damage, has %d%% chance to hit and forces %d attack rounds due to its berserk ability.",<br />
att_weapon.name, def_weapon.name or "no weapon", def_weapon.damage, def_weapon.chance_to_hit, def_weapon.rounds))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.transform_unit ====<br />
<br />
* '''wesnoth.transform_unit(''unit'', ''to_type'')'''<br />
* {{DevFeature1.13|2}} '''''unit'':transform(''to_type'')'''<br />
<br />
Changes the type of a unit and adjust attributes accordingly. Note that hit points are only changed if necessary to accommodate the new maximum hit points. Poison is automatically removed if the transformed unit is immune.<br />
<br />
<syntaxhighlight lang='lua'><br />
local ev = wesnoth.current.event_context<br />
local u = wesnoth.get_units{x=ev.x1, y=ev.y1}[1]<br />
wesnoth.transform_unit(u, "Spearman")<br />
-- If a full heal is desired:<br />
u.hitpoints = u.max_hitpoints<br />
u.status.poisoned = false<br />
</syntaxhighlight><br />
<br />
==== wesnoth.add_known_unit ====<br />
<br />
* {{DevFeature1.13|10}} '''wesnoth.add_known_unit(''unit_type_id'')'''<br />
<br />
adds the unit type with the given id to the list of known units (so that they appear in the help)<br />
<br />
==== wesnoth.create_animator ====<br />
<br />
{{DevFeature1.13|7}}<br />
<br />
* '''wesnoth.create_animator()'''<br />
<br />
Returns an object that can be used to set up and run an animation. The object has three methods:<br />
<br />
* '''animator:run()'''<br />
<br />
Runs the animation. {{DevFeature1.15|0}} Implicitly clears the animator.<br />
<br />
* '''animator:clear()'''<br />
<br />
Clears any units previously added to the animation.<br />
<br />
* '''animator:add(''unit'', ''flag'', ''hits'', ''params'')'''<br />
<br />
Adds a unit to the animation. The ''flag'' specifies which animation to play, and the ''hits'' parameter is required for attack animations to specify which variant of the animation to play. Possibly keys in ''params'' are:<br />
<br />
* '''facing''': A location. The animation will be played with the unit facing that location.<br />
* '''value''': Either a number or a list of two numbers. Use this to pass ''value'' and/or ''value_second'' to default animations that use them.<br />
* '''with_bars''': Whether to show HP bars and such while the animation plays.<br />
* '''text''': Text to float as the animation plays.<br />
* '''color''': Color of the floating text - a list of red, green, blue.<br />
* '''primary''': The primary weapon to use for the animation. Must be a Lua unit attack proxy.<br />
* '''secondary''': The secondary weapon to use for the animation.<br />
<br />
Normal usage would be to create it, call '''add''' one or more times, then call '''run'''.<br />
<br />
==== wesnoth.effects ====<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
This table contains the implementation of custom [[EffectWML|[effect]]]s. Each value is a function that takes a unit and the effect config. Note that the default effects defined by the Wesnoth engine are not in this table. <br />
<br />
<syntaxhighlight lang='lua'><br />
function wesnoth.effects.min_resistance(u, cfg)<br />
local resistance_new = {}<br />
local resistance_old = helper.parsed(helper.get_child(cfg, "resistance"))<br />
for k,v in pairs(resistance_old) do<br />
if type(k) == "string" and type(v) == "number" and wesnoth.unit_resistance(u, k) >= v then<br />
resistance_new[k] = v<br />
end<br />
end<br />
--important: use wesnoth.add_modification(..., false) so that the function will only execute the effects of that object and not store the object in the unit.<br />
wesnoth.add_modification(u, "object", {<br />
T.effect {<br />
apply_to = "resistance",<br />
replace = true,<br />
T.resistance (resistance_new),<br />
},<br />
}, false)<br />
end<br />
</syntaxhighlight><br />
<br />
The code above adds a new <code>min_resistance</code> effect that will set the resistances to specific values if they are currently below that value. It can then be used like this (for example, in [[DirectActionsWML#.5Bobject.5D|[object]]]):<br />
<br />
<syntaxhighlight lang='wml'><br />
[effect]<br />
apply_to=min_resistance<br />
[resistance]<br />
cold=50<br />
[/resistance]<br />
[/effect]<br />
</syntaxhighlight><br />
<br />
Note that because currently all Lua code is executed after [unit]s in [side] are created, it is currently not possible to use these effects in [unit]s in [side]<br />
<br />
{{DevFeature1.13|5}}<br />
<br />
Built-in effects are now present in the <code>wesnoth.effects</code> table and can be called by custom effects or by other Lua code. They take the same two arguments that a custom effect function does - the unit, and the effect WML.<br />
<br />
In addition, you can now specify description modifiers to be used if a custom effect is placed in a <code>[trait]</code> tag. Instead of setting a function as the effect, you set a table with a <code>__call</code> metafunction which does what the function would have done. The table can then have an additional <code>__descr</code> metafunction which updates descriptions as necessary. The built-in effects all use this structure. This metafunction takes the same arguments as the regular effect function, but should not modify the unit. Instead, it returns a string to be appended to the trait's effect description.<br />
<br />
[[Category: Lua Reference]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=LuaWML/Display&diff=59989LuaWML/Display2018-10-16T03:00:58Z<p>Namhub: /* wesnoth.theme_items */</p>
<hr />
<div>This page describes the [[LuaWML]] functions and helpers for interfacing with the user.<br />
<br />
==== wesnoth.message ====<br />
<br />
* '''wesnoth.message([''speaker'',] ''message'')'''<br />
<br />
Displays a string in the chat window and dumps it to the lua/info log domain (''--log-info=scripting/lua'' on the command-line).<br />
<br />
wesnoth.message "Hello World!"<br />
<br />
The chat line header is "<Lua>" by default, but it can be changed by passing a string before the message.<br />
<br />
wesnoth.message("Big Brother", "I'm watching you.") -- will result in "&lt;Big Brother&gt; I'm watching you."<br />
<br />
See also [[LuaWML:Events#helper.wml_error|helper.wml_error]] for displaying error messages.<br />
<br />
==== wesnoth.clear_messages ====<br />
<br />
* '''wesnoth.clear_messages()'''<br />
<br />
Removes all messages from the chat window. No argument or returned values.<br />
<br />
==== wesnoth.textdomain ====<br />
<br />
* '''wesnoth.textdomain(''domain'')'''<br />
<br />
Creates a function proxy for lazily translating strings from the given domain.<br />
<br />
-- #textdomain "my-campaign"<br />
-- the comment above ensures the subsequent strings will be extracted to the proper domain<br />
_ = wesnoth.textdomain "my-campaign"<br />
wesnoth.set_variable("my_unit.description", _ "the unit formerly known as Hero")<br />
<br />
The metatable of the function proxy appears as '''"message domain"'''. The metatable of the translatable strings (results of the proxy) appears as '''"translatable string"'''.<br />
<br />
The translatable strings can be appended to other strings/numbers with the standard '''..''' operator. Translation can be forced with the standard '''tostring''' operator in order to get a plain string.<br />
<br />
wesnoth.message(string.format(tostring(_ "You gain %d gold."), amount))<br />
<br />
==== wesnoth.delay ====<br />
<br />
* '''wesnoth.delay(''milliseconds'')'''<br />
<br />
Delays the engine like the [delay] tag. one argument: time to delay in milliseconds<br />
<br />
wesnoth.delay(500)<br />
<br />
==== wesnoth.float_label ====<br />
<br />
* '''wesnoth.float_label(''x'', ''y'', ''text'')'''<br />
<br />
Pops some text above a map tile.<br />
<br />
wesnoth.float_label(unit.x, unit.y, "&lt;span color='#ff0000'&gt;Ouch&lt;/span&gt;")<br />
<br />
==== wesnoth.get_viewing_side ====<br />
<br />
* '''wesnoth.get_viewing_side()'''<br />
<br />
returns two values 1) the number of the side of the current viewpoint, 2) a boolean specifying whether it has full vision (can only only true happen in replays or for observers)<br />
<br />
==== wesnoth.select_unit ====<br />
<br />
* '''wesnoth.select_hex(''x'', ''y'', [''show_movement'', [''fire_events'']])'''<br />
* {{DevFeature1.13|5}} '''wesnoth.select_unit(''unit'', [''show_movement'', [''fire_events'']])'''<br />
* {{DevFeature1.13|5}} '''''unit'':select([''show_movement'', [''fire_events'']])'''<br />
<br />
Selects the given unit in the game map as if the player had clicked on it.<br />
Argument 3: boolean, whether to show the movement range of any unit on that location (def: true)<br />
Argument 4: boolean, whether to fire any select events (def: false). Note: currently (1.14.1), this argument has no effect (events are never fired).<br />
<br />
wesnoth.select_unit(14,6, true, true)<br />
<br />
The '''wesnoth.select_hex''' form is deprecated. If there is a unit on the location, it does the same thing as '''wesnoth.select_unit''', but if ''show_movement'' is true it also calls '''wesnoth.highlight_hex''' for the location. If there is no unit on the location, '''wesnoth.select_hex''' does not do anything useful.<br />
<br />
If called without arguments, '''wesnoth.select_unit''' deselects the current unit from the map as long as the mouse cursor is not on its hex. It will continue to be displayed on the UI sidebar in any case.<br />
<br />
==== wesnoth.highlight_hex ====<br />
<br />
* '''wesnoth.highlight_hex(''x'', ''y'')'''<br />
<br />
Draws an outline around the specified hex.<br />
<br />
==== wesnoth.deselect_hex ====<br />
<br />
* '''wesnoth.deselect_hex()'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Reverses any select_hex call, leaving all locations unhighlighted. Takes no arguments.<br />
<br />
==== wesnoth.scroll_to_tile ====<br />
<br />
* '''wesnoth.scroll_to_tile(''x'', ''y'', [''only_if_visible'', [''instant'']])'''<br />
* {{DevFeature1.13|7}} '''wesnoth.scroll_to_tile(''x'', ''y'', [''only_if_visible'', [''instant'', [''only_if_needed'']]])'''<br />
<br />
Scrolls the map to the given location. If true is passed as the third parameter, scrolling is disabled if the tile is hidden under the fog. If true is passed as the fourth parameter, the view instantly warps to the location regardless of the scroll speed setting in Preferences. If true is passed as the fifth parameter, no scrolling occurs if the target location is already visible onscreen.<br />
<br />
local u = wesnoth.get_units({ id = "hero" })[1]<br />
wesnoth.scroll_to_tile(u.x, u.y)<br />
<br />
==== wesnoth.lock_view ====<br />
<br />
* '''wesnoth.lock_view(''lock'')'''<br />
<br />
Locks or unlocks gamemap view scrolling for human players. If true is passed as the first parameter, the view is locked; pass false to unlock.<br />
<br />
Human players cannot scroll the gamemap view as long as it is locked, but Lua or WML actions such as wesnoth.scroll_to_tile still can; the locked/unlocked state is preserved when saving the current game. This feature is generally intended to be used in cutscenes to prevent the player scrolling away from scripted actions.<br />
<br />
wesnoth.lock_view(true)<br />
wesnoth.scroll_to_tile(12, 14, false, true)<br />
<br />
==== wesnoth.view_locked ====<br />
<br />
* '''wesnoth.view_locked()'''<br />
<br />
Returns a boolean indicating whether gamemap view scrolling is currently locked.<br />
<br />
==== wesnoth.play_sound ====<br />
<br />
* '''wesnoth.play_sound(''sound'', [''repeat_count''])'''<br />
<br />
Plays the given sound file once, optionally repeating it one or more more times if an integer value is provided as a second argument (note that the sound is ''repeated'' the number of times specified in the second argument, i.e. a second argument of 4 will cause the sound to be played once and then repeated four more times for a total of 5 plays. See the example below).<br />
<br />
wesnoth.play_sound "ambient/birds1.ogg"<br />
wesnoth.play_sound("magic-holy-miss-3.ogg", 4) -- played 1 + 4 = 5 times<br />
<br />
==== wesnoth.set_music ====<br />
<br />
* '''wesnoth.set_music(''music_entry'')'''<br />
<br />
Sets the given table as an entry into the music list. See [[MusicListWML]] for the recognized attributes.<br />
<br />
wesnoth.set_music { name = "traveling_minstrels.ogg" }<br />
<br />
Passing no argument forces the engine to take into account all the recent changes to the music list. (Note: this is done automatically when sequences of WML commands end, so it is useful only for long events.)<br />
<br />
{{DevFeature1.13|8}} This function is now deprecated. Use the '''wesnoth.music_list''' table instead<br />
<br />
==== wesnoth.music_list ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
This is a table giving access to the current music playlist. It can be accessed as a normal array, including the Lua length operator. If you assign a music config to an entry, the track is replaced. It is not a normal array however and cannot be manipulated with the table library.<br />
<br />
In addition, it has the following named fields:<br />
<br />
* '''wesnoth.music_list.current''' (read-write): The currently-playing track. This may sometimes be a track that's not on the playlist - "play once" tracks are not placed on the playlist.<br />
* '''wesnoth.music_list.current.__cfg''' (read-only): Returns a copy of the current track information.<br />
* '''wesnoth.music_list.previous''' (read-write): The track played before the current one. This may sometimes be a track that's not on the playlist - "play once" tracks are not placed on the playlist.<br />
* '''wesnoth.music_list.previous.__cfg''' (read-only): Returns a copy of the previous track information. NOTE: Wesnoth's playlist implementation effectively "plays" every song as it's added to the playlist, so when replacing one playlist with another, this will return information on the second-to-last track added to the new playlist, not the track you actually heard playing from the playlist that was replaced.<br />
* '''wesnoth.music_list.current_i''' (read-write): The index of the currently-playing track on the playlist, or nil if the currently-playing track is not on the playlist.<br />
* '''wesnoth.music_list.volume''' (read-write): The current music volume, as a percentage of the user's preferred volume set in preferences.<br />
* '''wesnoth.music_list.all''' (read-only): Returns a copy of the music list as an array of WML tables.<br />
<br />
It also contains some functions:<br />
<br />
* '''wesnoth.music_list.add(''track_name'', [''immediate'',] [''ms_before'', [''ms_after'']])''': Appends a track to the playlist. If true is passed, also start playing the new track.<br />
* '''wesnoth.music_list.remove(''n1'', ...)''': Removes one or more tracks by their index. You can pass as many indices as you wish. If one of the removed tracks is currently playing, it continues to play.<br />
* '''wesnoth.music_list.clear()''': Clears the playlist. The currently-playing track continues to play.<br />
* '''wesnoth.music_list.next()''': Stop playing the current track and move on to the next one. This honours the shuffle settings.<br />
* '''wesnoth.music_list.play(''track_name'')''': Start playing a track without appending it to the playlist.<br />
<br />
Each track contains the following fields:<br />
<br />
* '''shuffle''' (read-write)<br />
* '''once''' (read-write): generally only true for '''wesnoth.music_list.current'''<br />
* '''ms_before''' (read-write)<br />
* '''ms_after''' (read-write)<br />
* '''immediate''' (read-only)<br />
* '''name''' (read-only): the unresolved track filename<br />
* '''title''' (read-only): a user-friendly track title<br />
<br />
==== wesnoth.sound_volume ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
* '''wesnoth.sound_volume(''new_volume'')'''<br />
<br />
Sets the current sound volume, as a percentage of the user's preferred volume set in preferences.<br />
Returns the previous sound volume in the same format.<br />
<br />
==== wesnoth.show_menu ====<br />
<br />
* '''wesnoth.show_menu(''items'' [, ''initial''] [, ''markup''])'''<br />
<br />
Shows a popup menu onscreen at the current mouse location. This could be used for example to produce a sort of submenu in a <tt>[set_menu_item]</tt>. The items are specified as a Lua array of tables, each of which supports the following keys:<br />
<br />
* ''icon'': An icon to display in the leftmost column of the menu.<br />
* ''image'': An image to display in the main column of the menu. If this is present, ''label'' is ignored.<br />
* ''label'': A label to display in the main column of the menu.<br />
* ''second_label'': A secondary label to display in the right column of the menu.<br />
* ''tooltip'': Text to display when mousing over this option.<br />
<br />
The ''initial'' argument must be a valid index into the ''items'' array, or 0 to indicate that no element is initially selected (which is the default but typically not what you want).<br />
<br />
The ''markup'' argument specifies whether Pango markup will be parsed in the menuitems. It defaults to false.<br />
<br />
The ''initial'' and ''markup'' arguments can be passed in either order; the game will understand which is meant based on the type of the argument.<br />
<br />
==== wesnoth.show_message_box ====<br />
<br />
* '''wesnoth.show_message_box(''title'', ''message'' [, ''button''] [, ''markup''])'''<br />
* '''wesnoth.confirm([''title'',] ''message'')'''<br />
* '''wesnoth.alert([''title''], ''message'')'''<br />
<br />
Shows a standard message box onscreen (similar to the quit confirmation message, for example). The button can be any arbitrary potentially-translatable string (in which case, there will be one button with that label), or it can be one of the following special values:<br />
<br />
* ''ok'' or nil: A single OK button; this is the default<br />
* ''cancel'': A single Cancel button<br />
* ''close'': A single Close button<br />
* ''ok_cancel'': Two buttons labelled OK and Cancel<br />
* ''yes_no'': Two buttons labelled Yes and No<br />
* an empty string: No buttons; the dialog automatically closes after a few seconds<br />
<br />
The alert and confirm functions are simpler wrappers for this function, using a single OK button and a pair of Yes/No buttons, respectively. Both confirm and show_message_box return false if No or Cancel was clicked, and true otherwise.<br />
<br />
==== wesnoth.show_message_dialog ====<br />
<br />
* '''wesnoth.show_message_dialog(''attributes'', [''options'', [''text_input_attributes'']])'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Shows a message dialog, of the type used by the [message] ActionWML tag. Unlike the [message] tag, this is unsynced; if you need it synced, you must do it yourself. The first argument is a table describing the dialog with the following keys:<br />
<br />
* ''title'' - The title to show on the message. For example, the speaker's name.<br />
* ''message'' - The message content.<br />
* ''portrait'' - An image to show along with the message. By default, no image is shown.<br />
* ''left_side'' - The default is true; set to false to show the image on the right.<br />
* ''mirror'' - If true, the image will be flipped horizontally.<br />
<br />
The second argument is a list of options as a Lua array. Each option is either a (possibly-translatable) string or a config with [[DescriptionWML#WML_Format|DescriptionWML]] keys. The array itself can also have an optional '''default''' key which if present should be the index of the initially selected option (useful if you don't need full DescriptionWML but want to set a default). If present it overrides any defaults set in individual options.<br />
<br />
The third argument is a table describing the text input field with the following keys:<br />
<br />
* ''label'' - A label to show to the left of the text field.<br />
* ''text'' - Initial contents of the text field.<br />
* ''max_length'' - Maximum input length in characters (defaults to 256).<br />
<br />
You need at least one key for the text input to be shown. Both the second arguments are option, but if you want text input with no options, you must pass nil for the second parameter.<br />
<br />
This function returns two values. The first is the numeric result of the dialog. If there are no options and no text input, this is -2 if the user closed by pressing Escape, otherwise it's -1. If there are options, this is the index of the option chosen (starting from 1). If there is text input but no options, the first return value is 0. If there was text input, the second value contains the text entered.<br />
<br />
Example:<br />
<br />
wesnoth.show_message_dialog({<br />
title = "Make your choice:",<br />
message = "Select an option and enter some text.",<br />
portrait = "wesnoth-icon.png",<br />
}, {<br />
"The first choice is always the best!",<br />
"Pick me! Second choices are better!",<br />
"You know you want the third option!",<br />
}, {<br />
label = "Text:",<br />
text = "?",<br />
max_length = 16<br />
})<br />
<br />
(You don't have to format it like that, of course.)<br />
<br />
==== wesnoth.show_popup_dialog ====<br />
<br />
* '''wesnoth.show_popup_dialog(''title'', ''message'', [''image''])'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Shows a simple popup dialog in the centre of the screen. Takes three arguments, which in order are:<br />
<br />
# A title string for the dialog<br />
# The message content for the dialog.<br />
# An image to show.<br />
<br />
Both the title and the message support Pango markup. The image is optional.<br />
<br />
==== wesnoth.show_story ====<br />
<br />
* '''wesnoth.show_story(''story_config'', ''default_title'')'''<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
Shows the storyscreen. The passed config is identical to the contents of [[IntroWML|[story]]]. The second parameter is the default title used if a part does not specify one — unlike intro storyscreens, a Lua-invoked one does not default to the scenario name.<br />
<br />
==== wesnoth.show_dialog ====<br />
<br />
* '''wesnoth.show_dialog(''wml_dialog_table'', [''pre_show_function'', [''post_show_function'']])'''<br />
<br />
Displays a dialog box described by a WML table and returns:<br />
* if the dialog was dismissed by a button click, the integer value associated to the button via the "return_value" keyword.<br />
* if the dialog was closed with the enter key, -1.<br />
* if the dialog was closed with the escape key, -2.<br />
<br />
The dialog box is equivalent to the resolution section of a GUI window as described in [[GUIToolkitWML#Window_definition|GUIToolkitWML]] and must therefore contain at least the following children: '''[tooltip]''', '''[helptip]''', and '''[grid]'''. The [grid] must contain nested [row], [column] and [grid] tags which describe the layout of the window. (More information can be found in [[GUILayout]]; suffice to say that the basic structure is grid -> row -> column -> widget, where the widget is considered to be in a cell defined by the row and column of the grid. A list of widgets can be found at [[GUIWidgetInstanceWML]].)<br />
<br />
Two optional functions can be passed as second and third arguments; the first one is called once the dialog is created and before it is shown; the second one is called once the dialog is closed. These functions are helpful in setting the initial values of the fields and in recovering the final user values. These functions can call the [[#wesnoth.set_dialog_value]], [[#wesnoth.get_dialog_value]], and [[#wesnoth.set_dialog_callback]] functions for this purpose.<br />
<br />
This function should be called in conjunction with [[LuaWML:Misc#wesnoth.synchronize_choice|#wesnoth.synchronize_choice]], in order to ensure that only one client displays the dialog and that the other ones recover the same input values from this single client.<br />
<br />
The example below defines a dialog with a list and two buttons on the left, and a big image on the right. The ''preshow'' function fills the list and defines a callback on it. This ''select'' callback changes the displayed image whenever a new list item is selected. The ''postshow'' function recovers the selected item before the dialog is destroyed.<br />
<br />
<syntaxhighlight lang=lua><br />
local helper = wesnoth.require "lua/helper.lua"<br />
local T = helper.set_wml_tag_metatable {}<br />
local _ = wesnoth.textdomain "wesnoth"<br />
<br />
local dialog = {<br />
T.tooltip { id = "tooltip_large" },<br />
T.helptip { id = "tooltip_large" },<br />
T.grid { T.row {<br />
T.column { T.grid {<br />
T.row { T.column { horizontal_grow = true, T.listbox { id = "the_list",<br />
T.list_definition { T.row { T.column { horizontal_grow = true,<br />
T.toggle_panel { return_value = -1, T.grid { T.row {<br />
T.column { horizontal_alignment = "left", T.label { id = "the_label" } },<br />
T.column { T.image { id = "the_icon" } }<br />
} } }<br />
} } }<br />
} } },<br />
T.row { T.column { T.grid { T.row {<br />
T.column { T.button { id = "ok", label = _"OK" } },<br />
T.column { T.button { id = "cancel", label = _"Cancel" } }<br />
} } } }<br />
} },<br />
T.column { T.image { id = "the_image" } }<br />
} }<br />
}<br />
<br />
local function preshow()<br />
local t = { "Ancient Lich", "Ancient Wose", "Elvish Avenger" }<br />
local function select()<br />
local i = wesnoth.get_dialog_value "the_list"<br />
local ut = wesnoth.unit_types[t[i]].__cfg<br />
wesnoth.set_dialog_value(string.gsub(ut.profile, "([^/]+)$", "transparent/%1"), "the_image")<br />
end<br />
wesnoth.set_dialog_callback(select, "the_list")<br />
for i,v in ipairs(t) do<br />
local ut = wesnoth.unit_types[v].__cfg<br />
wesnoth.set_dialog_value(ut.name, "the_list", i, "the_label")<br />
wesnoth.set_dialog_value(ut.image, "the_list", i, "the_icon")<br />
end<br />
wesnoth.set_dialog_value(2, "the_list")<br />
select()<br />
end<br />
<br />
local li<br />
local function postshow()<br />
li = wesnoth.get_dialog_value "the_list"<br />
end<br />
<br />
local r = wesnoth.show_dialog(dialog, preshow, postshow)<br />
wesnoth.message(string.format("Button %d pressed. Item %d selected.", r, li))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.set_dialog_value ====<br />
<br />
* '''wesnoth.set_dialog_value(''value'', ''path, to, widget, id'')'''<br />
<br />
Sets the value of a widget on the current dialog. The value is given by the first argument; its semantic depends on the type of widget it is applied to. The last argument is the ''id'' of the widget. If it does not point to a unique widget in the dialog, some discriminating parents should be given on its left, making a path that is read from left to right by the engine. The row of a list is specified by giving the ''id' of the list as a first argument and the 1-based row number as the next argument.<br />
<br />
-- sets the value of a widget "bar" in the 7th row of the list "foo"<br />
wesnoth.set_dialog_value(_"Hello world", "foo", 7, "bar")<br />
<br />
Notes: When the row of a list does not exist, it is created. The value associated to a list is the selected row.<br />
<br />
==== wesnoth.get_dialog_value ====<br />
<br />
* '''wesnoth.get_dialog_value(''path, to, widget, id'')'''<br />
<br />
Gets the value of a widget on the current dialog. The arguments described the path for reaching the widget (see [[#wesnoth.set_dialog_value]]).<br />
<br />
{{DevFeature1.13|0}}<br />
For treeviews this function returns a table descibing the currently selected node.<br />
If for example in this treeview<br />
+Section1<br />
+Subsection11<br />
*Item1<br />
*Item2<br />
*Item3<br />
+Subsection12<br />
*Item4<br />
*Item5<br />
*Item6<br />
+Section2<br />
+Subsection21<br />
*Item7<br />
*Item8<br />
*Item9<br />
+Subsection22<br />
*Item10<br />
*Item11<br />
*Item12<br />
Item 9 is selcted the value will be {2,1,3}<br />
<br />
==== wesnoth.set_dialog_active ====<br />
<br />
* '''wesnoth.set_dialog_active(''active?'', ''path, to, widget, id'')'''<br />
<br />
Enables or disables a widget. The first argument is a boolean specifying whether the widget should be active (true) or inactive (false). The remaining arguments are the path to locate the widget in question (see [[#wesnoth.set_dialog_value]]).<br />
<br />
==== wesnoth.set_dialog_callback ====<br />
<br />
* '''wesnoth.set_dialog_callback(''callback_function'', ''path, to, widget, id'')'''<br />
<br />
Sets the first argument as a callback function for the widget obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). This function will be called whenever the user modifies something about the widget, so that the dialog can react to it.<br />
<br />
==== wesnoth.set_dialog_markup ====<br />
<br />
* '''wesnoth.set_dialog_markup(''allowed?'', ''path, to, widget, id'')'''<br />
<br />
Sets the flag associated to a widget to enable or disable Pango markup. The new flag value is passed as the first argument (boolean), and the widget to modify is obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). Most widgets start with Pango markup disabled unless this function is used to set their flag to true.<br />
<br />
wesnoth.set_dialog_markup(true, "notice_label")<br />
wesnoth.set_dialog_value("&lt;big&gt;NOTICE!&lt;/big&gt;", "notice_label")<br />
<br />
==== wesnoth.set_dialog_focus ====<br />
<br />
* '''wesnoth.set_dialog_focus(''focused?'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Switches the keyboard focus to the widget found following the given path (see [[#wesnoth.set_dialog_value]]). This is often useful for dialogs containing a central listbox, so that it can be controlled with the keyboard as soon as it is displayed.<br />
<br />
wesnoth.set_dialog_focus("my_listbox")<br />
<br />
==== wesnoth.set_dialog_visible ====<br />
<br />
* '''wesnoth.set_dialog_visible(''visible?'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Sets a widget's visibility status. The new status is passed as the first argument, and the path to the widget is specified by the remaining arguments (see [[#wesnoth.set_dialog_value]]). The following visibility statuses are recognized:<br />
<br />
{| clasS="wikitable"<br />
! String value !! Boolean shorthand !! Meaning<br />
|-<br />
| visible || true || The widget is visible and handles events.<br />
|-<br />
| hidden || || The widget is not visible, doesn't handle events, but still takes up space on the dialog grid.<br />
|-<br />
| invisible || false || The widget is not visible, doesn't handle events, and does not take up space on the dialog grid.<br />
|}<br />
<br />
wesnoth.set_dialog_visible(false, "secret_button")<br />
<br />
==== wesnoth.set_dialog_canvas ====<br />
<br />
* '''wesnoth.set_dialog_canvas(''index'', ''content'', ''path, to, widget, id'')'''<br />
<br />
Sets the WML passed as the second argument as the canvas content (index given by the first argument) of the widget obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). The content of the WML table is described at [[GUICanvasWML]].<br />
<br />
-- draw two rectangles in the upper-left corner of the window (empty path = window widget)<br />
wesnoth.set_dialog_canvas(2, {<br />
T.rectangle { x = 20, y = 20, w = 20, h = 20, fill_color= "0,0,255,255" },<br />
T.rectangle { x = 30, y = 30, w = 20, h = 20, fill_color = "255,0,0,255" }<br />
})<br />
<br />
The meaning of the canvas index depends on the chosen widget. It may be the disabled / enabled states of the widget, or its background / foreground planes, or... For instance, overwriting canvas 1 of the window with an empty canvas causes the window to become transparent.<br />
<br />
==== wesnoth.add_dialog_tree_node ====<br />
<br />
* '''wesnoth.add_dialog_tree_node(''type'', ''index'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|0}}<br />
<br />
Adds a childnode to a treeview widget or a treeview node. The type (id of the node definition) of the node is passed in the first parameter. The second parameter (integer) spcifies where the node should be inserted in the parentnode. The other arguments describe the path of the parent treeview (-node)<br />
<br />
==== wesnoth.remove_dialog_item ====<br />
<br />
* '''wesnoth.remove_dialog_item(''index'', ''count'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|1}}<br />
<br />
Removes an item from a listbox, a multipage or a treeview. First parameter is the index of the item to delete, second parameter is the number of items to delete and the remaining parameters describe the path to the listbox, the multipage or the parent treview node.<br />
<br />
<br />
==== wesnoth.add_widget_definition====<br />
<br />
* '''wesnoth.add_widget_definition(''widget_type'', ''definition_id'', ''wml_content'')'''<br />
<br />
{{DevFeature1.13|?}}<br />
<br />
Creates a new wml widget definition see https://github.com/wesnoth/wesnoth/tree/1.14/data/gui/widget for examples wml_content<br />
<br />
==== wesnoth.is_skipping_messages ====<br />
<br />
* '''wesnoth.is_skipping_messages()'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Returns true if messages are currently being skipped, for example because the player has chosen to skip replay, or has pressed escape to dismiss a message.<br />
<br />
==== wesnoth.skip_messages ====<br />
<br />
* '''wesnoth.skip_messages([''skip?'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Sets the skip messages flag. By default it sets it to true, but you can also pass false to unset the flag.<br />
<br />
==== wesnoth.get_displayed_unit ====<br />
<br />
* '''wesnoth.get_displayed_unit()'''<br />
<br />
Returns a proxy to the unit currently displayed in the side pane of the user interface, if any.<br />
<br />
local name = tostring(wesnoth.get_displayed_unit().name)<br />
<br />
==== wesnoth.log ====<br />
<br />
* '''wesnoth.log([''logger''], ''message', ''in_chat'')'''<br />
<br />
{{DevFeature1.13|5}} Logs a message to the console. These messages are normally not visible unless Wesnoth is run from the command-line or (in Windows) with the --wconsole switch. The in_chat argument, however, can be set to true to also echo the message to the in-game chat area.<br />
<br />
Possible loggers are info, debug, warning, error, and wml. The wml logger is special and is intended for WML errors; it always goes to chat, so the in_chat argument is ignored and can be omitted. The default logger is info.<br />
<br />
==== wesnoth.theme_items ====<br />
<br />
This field is not a function but an associative table. It links item names to the functions that describe their content. These functions are called whenever the user interface is refreshed. The description of an item is a WML table containing '''[element]''' children. Each subtag shall contain either a '''text''' or an '''image''' field that is displayed to the user. It can also contain a '''tooltip''' field that is displayed to the user when moused over, and a "help" field that points to the help section that is displayed when the user clicks on the theme item.<br />
<br />
Note that the ''wesnoth.theme_items'' table is originally empty and using ''pairs'' or ''next'' on it will not return the items from the current theme. Its metatable ensures that the drawing functions of existing items can be recovered though, as long as their name is known. The example below shows how to modify the ''unit_status'' item to display a custom status:<br />
<br />
<syntaxhighlight lang=lua><br />
local old_unit_status = wesnoth.theme_items.unit_status<br />
function wesnoth.theme_items.unit_status()<br />
local _ = wesnoth.textdomain "mydomain"<br />
local u = wesnoth.get_displayed_unit()<br />
if not u then return {} end<br />
local s = old_unit_status()<br />
if u.status.entangled then<br />
table.insert(s, wml.tag.element {<br />
image = "entangled.png",<br />
tooltip = _"entangled: This unit is entangled. It cannot move but it can still attack."<br />
})<br />
end<br />
return s<br />
end<br />
</syntaxhighlight><br />
<br />
The things that would need to be to modified in the above code are:<br />
<br />
* the domain of your addon ("mydomain"), assuming that you are using translations. Otherwise just remove the underscore in the tooltip line.<br />
* the name of the status (u.status.entangled). Note that if the attribute happens to be inside [variables], so be it: u.variables.whatever.<br />
* the path to the image ("entangled.png").<br />
* the tooltip of the status ("entangled: This unit ...").<br />
<br />
The following is a list of valid entries in wesnoth.theme_items which will have an effect in the game. Unfortunately when this feature was created the full range of capabilities of the feature was never properly documented. The following list is automatically generated. To find out what each entry will do, you will have to make guesses and experiment, or read the source code at src/reports.cpp. If you find out what an entry does, you are more than welcome to edit the wiki and give a proper description to any of these fields.<br />
<br />
* '''unit_name'''<br />
* '''selected_unit_name'''<br />
* '''unit_type'''<br />
* '''selected_unit_type'''<br />
* '''unit_race'''<br />
* '''selected_unit_race'''<br />
* '''unit_side'''<br />
* '''selected_unit_side'''<br />
* '''unit_level'''<br />
* '''selected_unit_level'''<br />
* '''unit_amla'''<br />
* '''unit_traits'''<br />
* '''selected_unit_traits'''<br />
* '''unit_status'''<br />
* '''selected_unit_status'''<br />
* '''unit_alignment'''<br />
* '''selected_unit_alignment'''<br />
* '''unit_abilities'''<br />
* '''selected_unit_abilities'''<br />
* '''unit_hp'''<br />
* '''selected_unit_hp'''<br />
* '''unit_xp'''<br />
* '''selected_unit_xp'''<br />
* '''unit_advancement_options'''<br />
* '''selected_unit_advancement_options'''<br />
* '''unit_defense'''<br />
* '''selected_unit_defense'''<br />
* '''unit_vision'''<br />
* '''selected_unit_vision'''<br />
* '''unit_moves'''<br />
* '''selected_unit_moves'''<br />
* '''unit_weapons'''<br />
The default generator expresses each weapon line as a separate <code>element</code><br />
<syntaxhighlight lang=lua><br />
return { <br />
{ "element", <br />
{ text = "weapon text",<br />
tooltip = _"weapon tooltip"<br />
}<br />
},<br />
...<br />
}<br />
</syntaxhighlight><br />
* '''highlighted_unit_weapons'''<br />
* '''selected_unit_weapons'''<br />
* '''unit_image'''<br />
* '''selected_unit_image'''<br />
* '''selected_unit_profile'''<br />
* '''unit_profile'''<br />
* '''tod_stats'''<br />
* '''time_of_day'''<br />
* '''unit_box'''<br />
* '''turn'''<br />
* '''gold'''<br />
* '''villages'''<br />
* '''num_units'''<br />
* '''upkeep'''<br />
* '''expenses'''<br />
* '''income'''<br />
* '''terrain_info'''<br />
* '''terrain'''<br />
** <nowiki>Text for terrain of the active hex. Same as the one displayed on the UI. It probably returns an empty table when no hex is active. Otherwise, it returns something like {{"element",{text="Grassland (Flat)"}}}.</nowiki><br />
* '''zoom_level'''<br />
* '''position'''<br />
* '''side_playing'''<br />
* '''observers'''<br />
** <nowiki>When there is no observer, it returns an empty table. When there are observers, it gives<br />
{{"element",<br />
{tooltip="Observers\n<observer1>\n<observer2>\n", image="misc/eye.png"}<br />
}}<br />
<br />
</nowiki><br />
* '''selected_terrain'''<br />
* '''edit_left_button_function'''<br />
* '''report_clock'''<br />
** <nowiki>wesnoth.theme_items.report_clock() gives a table {{"element", text=<time>}}, where <time> is HH:MM of local time. It probably return 12hr or 24hr formats depending on user preference. </nowiki><br />
* '''report_countdown'''<br />
** <nowiki>wesnoth.theme_items.report_countdown() gives a table {{"element", text=<time>}}, where <time> is MM:SS of time limit for player's turn. If turn limit < 120 or 60, add <span foreground="#c8c800"><br />
or <span foreground="#c80000"> html tags. </nowiki><br />
<br />
==== helper.get_user_choice ====<br />
<br />
* '''helper.get_user_choice(''message_table'', ''options'')'''<br />
<br />
Displays a WML message box querying a choice from the user. Attributes and options are taken from given tables (see [[InterfaceActionsWML#.5Bmessage.5D|[message]]]). The index of the selected option is returned.<br />
<br />
local result = helper.get_user_choice({ speaker = "narrator" }, { "Choice 1", "Choice 2" })<br />
<br />
[[Category: Lua Reference]]<br />
<br />
==== wesnoth.zoom ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
* '''wesnoth.zoom(''factor''[, ''relative''])'''<br />
<br />
Changes the zoom level of the map. If relative is false, which is the default, it simply sets the zoom level. If relative is true, it zooms relative to the current zoom level. So, for example, if the zoom level is currently 0.5, then wesnoth.zoom(2) sets it to 2, while wesnoth.zoom(2, true) sets it to 1 (2 * 0.5).<br />
<br />
This function also returns the resulting zoom level. Because of this, you can call wesnoth.zoom(1) to simply get the current zoom level.<br />
<br />
Note that this function cannot zoom to a level that the user would not be able to reach from the UI. Attempting to do so will simply select the nearest allowed zoom level.</div>Namhubhttps://wiki.wesnoth.org/index.php?title=LuaWML/Display&diff=59988LuaWML/Display2018-10-16T02:57:51Z<p>Namhub: /* wesnoth.theme_items */</p>
<hr />
<div>This page describes the [[LuaWML]] functions and helpers for interfacing with the user.<br />
<br />
==== wesnoth.message ====<br />
<br />
* '''wesnoth.message([''speaker'',] ''message'')'''<br />
<br />
Displays a string in the chat window and dumps it to the lua/info log domain (''--log-info=scripting/lua'' on the command-line).<br />
<br />
wesnoth.message "Hello World!"<br />
<br />
The chat line header is "<Lua>" by default, but it can be changed by passing a string before the message.<br />
<br />
wesnoth.message("Big Brother", "I'm watching you.") -- will result in "&lt;Big Brother&gt; I'm watching you."<br />
<br />
See also [[LuaWML:Events#helper.wml_error|helper.wml_error]] for displaying error messages.<br />
<br />
==== wesnoth.clear_messages ====<br />
<br />
* '''wesnoth.clear_messages()'''<br />
<br />
Removes all messages from the chat window. No argument or returned values.<br />
<br />
==== wesnoth.textdomain ====<br />
<br />
* '''wesnoth.textdomain(''domain'')'''<br />
<br />
Creates a function proxy for lazily translating strings from the given domain.<br />
<br />
-- #textdomain "my-campaign"<br />
-- the comment above ensures the subsequent strings will be extracted to the proper domain<br />
_ = wesnoth.textdomain "my-campaign"<br />
wesnoth.set_variable("my_unit.description", _ "the unit formerly known as Hero")<br />
<br />
The metatable of the function proxy appears as '''"message domain"'''. The metatable of the translatable strings (results of the proxy) appears as '''"translatable string"'''.<br />
<br />
The translatable strings can be appended to other strings/numbers with the standard '''..''' operator. Translation can be forced with the standard '''tostring''' operator in order to get a plain string.<br />
<br />
wesnoth.message(string.format(tostring(_ "You gain %d gold."), amount))<br />
<br />
==== wesnoth.delay ====<br />
<br />
* '''wesnoth.delay(''milliseconds'')'''<br />
<br />
Delays the engine like the [delay] tag. one argument: time to delay in milliseconds<br />
<br />
wesnoth.delay(500)<br />
<br />
==== wesnoth.float_label ====<br />
<br />
* '''wesnoth.float_label(''x'', ''y'', ''text'')'''<br />
<br />
Pops some text above a map tile.<br />
<br />
wesnoth.float_label(unit.x, unit.y, "&lt;span color='#ff0000'&gt;Ouch&lt;/span&gt;")<br />
<br />
==== wesnoth.get_viewing_side ====<br />
<br />
* '''wesnoth.get_viewing_side()'''<br />
<br />
returns two values 1) the number of the side of the current viewpoint, 2) a boolean specifying whether it has full vision (can only only true happen in replays or for observers)<br />
<br />
==== wesnoth.select_unit ====<br />
<br />
* '''wesnoth.select_hex(''x'', ''y'', [''show_movement'', [''fire_events'']])'''<br />
* {{DevFeature1.13|5}} '''wesnoth.select_unit(''unit'', [''show_movement'', [''fire_events'']])'''<br />
* {{DevFeature1.13|5}} '''''unit'':select([''show_movement'', [''fire_events'']])'''<br />
<br />
Selects the given unit in the game map as if the player had clicked on it.<br />
Argument 3: boolean, whether to show the movement range of any unit on that location (def: true)<br />
Argument 4: boolean, whether to fire any select events (def: false). Note: currently (1.14.1), this argument has no effect (events are never fired).<br />
<br />
wesnoth.select_unit(14,6, true, true)<br />
<br />
The '''wesnoth.select_hex''' form is deprecated. If there is a unit on the location, it does the same thing as '''wesnoth.select_unit''', but if ''show_movement'' is true it also calls '''wesnoth.highlight_hex''' for the location. If there is no unit on the location, '''wesnoth.select_hex''' does not do anything useful.<br />
<br />
If called without arguments, '''wesnoth.select_unit''' deselects the current unit from the map as long as the mouse cursor is not on its hex. It will continue to be displayed on the UI sidebar in any case.<br />
<br />
==== wesnoth.highlight_hex ====<br />
<br />
* '''wesnoth.highlight_hex(''x'', ''y'')'''<br />
<br />
Draws an outline around the specified hex.<br />
<br />
==== wesnoth.deselect_hex ====<br />
<br />
* '''wesnoth.deselect_hex()'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Reverses any select_hex call, leaving all locations unhighlighted. Takes no arguments.<br />
<br />
==== wesnoth.scroll_to_tile ====<br />
<br />
* '''wesnoth.scroll_to_tile(''x'', ''y'', [''only_if_visible'', [''instant'']])'''<br />
* {{DevFeature1.13|7}} '''wesnoth.scroll_to_tile(''x'', ''y'', [''only_if_visible'', [''instant'', [''only_if_needed'']]])'''<br />
<br />
Scrolls the map to the given location. If true is passed as the third parameter, scrolling is disabled if the tile is hidden under the fog. If true is passed as the fourth parameter, the view instantly warps to the location regardless of the scroll speed setting in Preferences. If true is passed as the fifth parameter, no scrolling occurs if the target location is already visible onscreen.<br />
<br />
local u = wesnoth.get_units({ id = "hero" })[1]<br />
wesnoth.scroll_to_tile(u.x, u.y)<br />
<br />
==== wesnoth.lock_view ====<br />
<br />
* '''wesnoth.lock_view(''lock'')'''<br />
<br />
Locks or unlocks gamemap view scrolling for human players. If true is passed as the first parameter, the view is locked; pass false to unlock.<br />
<br />
Human players cannot scroll the gamemap view as long as it is locked, but Lua or WML actions such as wesnoth.scroll_to_tile still can; the locked/unlocked state is preserved when saving the current game. This feature is generally intended to be used in cutscenes to prevent the player scrolling away from scripted actions.<br />
<br />
wesnoth.lock_view(true)<br />
wesnoth.scroll_to_tile(12, 14, false, true)<br />
<br />
==== wesnoth.view_locked ====<br />
<br />
* '''wesnoth.view_locked()'''<br />
<br />
Returns a boolean indicating whether gamemap view scrolling is currently locked.<br />
<br />
==== wesnoth.play_sound ====<br />
<br />
* '''wesnoth.play_sound(''sound'', [''repeat_count''])'''<br />
<br />
Plays the given sound file once, optionally repeating it one or more more times if an integer value is provided as a second argument (note that the sound is ''repeated'' the number of times specified in the second argument, i.e. a second argument of 4 will cause the sound to be played once and then repeated four more times for a total of 5 plays. See the example below).<br />
<br />
wesnoth.play_sound "ambient/birds1.ogg"<br />
wesnoth.play_sound("magic-holy-miss-3.ogg", 4) -- played 1 + 4 = 5 times<br />
<br />
==== wesnoth.set_music ====<br />
<br />
* '''wesnoth.set_music(''music_entry'')'''<br />
<br />
Sets the given table as an entry into the music list. See [[MusicListWML]] for the recognized attributes.<br />
<br />
wesnoth.set_music { name = "traveling_minstrels.ogg" }<br />
<br />
Passing no argument forces the engine to take into account all the recent changes to the music list. (Note: this is done automatically when sequences of WML commands end, so it is useful only for long events.)<br />
<br />
{{DevFeature1.13|8}} This function is now deprecated. Use the '''wesnoth.music_list''' table instead<br />
<br />
==== wesnoth.music_list ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
This is a table giving access to the current music playlist. It can be accessed as a normal array, including the Lua length operator. If you assign a music config to an entry, the track is replaced. It is not a normal array however and cannot be manipulated with the table library.<br />
<br />
In addition, it has the following named fields:<br />
<br />
* '''wesnoth.music_list.current''' (read-write): The currently-playing track. This may sometimes be a track that's not on the playlist - "play once" tracks are not placed on the playlist.<br />
* '''wesnoth.music_list.current.__cfg''' (read-only): Returns a copy of the current track information.<br />
* '''wesnoth.music_list.previous''' (read-write): The track played before the current one. This may sometimes be a track that's not on the playlist - "play once" tracks are not placed on the playlist.<br />
* '''wesnoth.music_list.previous.__cfg''' (read-only): Returns a copy of the previous track information. NOTE: Wesnoth's playlist implementation effectively "plays" every song as it's added to the playlist, so when replacing one playlist with another, this will return information on the second-to-last track added to the new playlist, not the track you actually heard playing from the playlist that was replaced.<br />
* '''wesnoth.music_list.current_i''' (read-write): The index of the currently-playing track on the playlist, or nil if the currently-playing track is not on the playlist.<br />
* '''wesnoth.music_list.volume''' (read-write): The current music volume, as a percentage of the user's preferred volume set in preferences.<br />
* '''wesnoth.music_list.all''' (read-only): Returns a copy of the music list as an array of WML tables.<br />
<br />
It also contains some functions:<br />
<br />
* '''wesnoth.music_list.add(''track_name'', [''immediate'',] [''ms_before'', [''ms_after'']])''': Appends a track to the playlist. If true is passed, also start playing the new track.<br />
* '''wesnoth.music_list.remove(''n1'', ...)''': Removes one or more tracks by their index. You can pass as many indices as you wish. If one of the removed tracks is currently playing, it continues to play.<br />
* '''wesnoth.music_list.clear()''': Clears the playlist. The currently-playing track continues to play.<br />
* '''wesnoth.music_list.next()''': Stop playing the current track and move on to the next one. This honours the shuffle settings.<br />
* '''wesnoth.music_list.play(''track_name'')''': Start playing a track without appending it to the playlist.<br />
<br />
Each track contains the following fields:<br />
<br />
* '''shuffle''' (read-write)<br />
* '''once''' (read-write): generally only true for '''wesnoth.music_list.current'''<br />
* '''ms_before''' (read-write)<br />
* '''ms_after''' (read-write)<br />
* '''immediate''' (read-only)<br />
* '''name''' (read-only): the unresolved track filename<br />
* '''title''' (read-only): a user-friendly track title<br />
<br />
==== wesnoth.sound_volume ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
* '''wesnoth.sound_volume(''new_volume'')'''<br />
<br />
Sets the current sound volume, as a percentage of the user's preferred volume set in preferences.<br />
Returns the previous sound volume in the same format.<br />
<br />
==== wesnoth.show_menu ====<br />
<br />
* '''wesnoth.show_menu(''items'' [, ''initial''] [, ''markup''])'''<br />
<br />
Shows a popup menu onscreen at the current mouse location. This could be used for example to produce a sort of submenu in a <tt>[set_menu_item]</tt>. The items are specified as a Lua array of tables, each of which supports the following keys:<br />
<br />
* ''icon'': An icon to display in the leftmost column of the menu.<br />
* ''image'': An image to display in the main column of the menu. If this is present, ''label'' is ignored.<br />
* ''label'': A label to display in the main column of the menu.<br />
* ''second_label'': A secondary label to display in the right column of the menu.<br />
* ''tooltip'': Text to display when mousing over this option.<br />
<br />
The ''initial'' argument must be a valid index into the ''items'' array, or 0 to indicate that no element is initially selected (which is the default but typically not what you want).<br />
<br />
The ''markup'' argument specifies whether Pango markup will be parsed in the menuitems. It defaults to false.<br />
<br />
The ''initial'' and ''markup'' arguments can be passed in either order; the game will understand which is meant based on the type of the argument.<br />
<br />
==== wesnoth.show_message_box ====<br />
<br />
* '''wesnoth.show_message_box(''title'', ''message'' [, ''button''] [, ''markup''])'''<br />
* '''wesnoth.confirm([''title'',] ''message'')'''<br />
* '''wesnoth.alert([''title''], ''message'')'''<br />
<br />
Shows a standard message box onscreen (similar to the quit confirmation message, for example). The button can be any arbitrary potentially-translatable string (in which case, there will be one button with that label), or it can be one of the following special values:<br />
<br />
* ''ok'' or nil: A single OK button; this is the default<br />
* ''cancel'': A single Cancel button<br />
* ''close'': A single Close button<br />
* ''ok_cancel'': Two buttons labelled OK and Cancel<br />
* ''yes_no'': Two buttons labelled Yes and No<br />
* an empty string: No buttons; the dialog automatically closes after a few seconds<br />
<br />
The alert and confirm functions are simpler wrappers for this function, using a single OK button and a pair of Yes/No buttons, respectively. Both confirm and show_message_box return false if No or Cancel was clicked, and true otherwise.<br />
<br />
==== wesnoth.show_message_dialog ====<br />
<br />
* '''wesnoth.show_message_dialog(''attributes'', [''options'', [''text_input_attributes'']])'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Shows a message dialog, of the type used by the [message] ActionWML tag. Unlike the [message] tag, this is unsynced; if you need it synced, you must do it yourself. The first argument is a table describing the dialog with the following keys:<br />
<br />
* ''title'' - The title to show on the message. For example, the speaker's name.<br />
* ''message'' - The message content.<br />
* ''portrait'' - An image to show along with the message. By default, no image is shown.<br />
* ''left_side'' - The default is true; set to false to show the image on the right.<br />
* ''mirror'' - If true, the image will be flipped horizontally.<br />
<br />
The second argument is a list of options as a Lua array. Each option is either a (possibly-translatable) string or a config with [[DescriptionWML#WML_Format|DescriptionWML]] keys. The array itself can also have an optional '''default''' key which if present should be the index of the initially selected option (useful if you don't need full DescriptionWML but want to set a default). If present it overrides any defaults set in individual options.<br />
<br />
The third argument is a table describing the text input field with the following keys:<br />
<br />
* ''label'' - A label to show to the left of the text field.<br />
* ''text'' - Initial contents of the text field.<br />
* ''max_length'' - Maximum input length in characters (defaults to 256).<br />
<br />
You need at least one key for the text input to be shown. Both the second arguments are option, but if you want text input with no options, you must pass nil for the second parameter.<br />
<br />
This function returns two values. The first is the numeric result of the dialog. If there are no options and no text input, this is -2 if the user closed by pressing Escape, otherwise it's -1. If there are options, this is the index of the option chosen (starting from 1). If there is text input but no options, the first return value is 0. If there was text input, the second value contains the text entered.<br />
<br />
Example:<br />
<br />
wesnoth.show_message_dialog({<br />
title = "Make your choice:",<br />
message = "Select an option and enter some text.",<br />
portrait = "wesnoth-icon.png",<br />
}, {<br />
"The first choice is always the best!",<br />
"Pick me! Second choices are better!",<br />
"You know you want the third option!",<br />
}, {<br />
label = "Text:",<br />
text = "?",<br />
max_length = 16<br />
})<br />
<br />
(You don't have to format it like that, of course.)<br />
<br />
==== wesnoth.show_popup_dialog ====<br />
<br />
* '''wesnoth.show_popup_dialog(''title'', ''message'', [''image''])'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Shows a simple popup dialog in the centre of the screen. Takes three arguments, which in order are:<br />
<br />
# A title string for the dialog<br />
# The message content for the dialog.<br />
# An image to show.<br />
<br />
Both the title and the message support Pango markup. The image is optional.<br />
<br />
==== wesnoth.show_story ====<br />
<br />
* '''wesnoth.show_story(''story_config'', ''default_title'')'''<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
Shows the storyscreen. The passed config is identical to the contents of [[IntroWML|[story]]]. The second parameter is the default title used if a part does not specify one — unlike intro storyscreens, a Lua-invoked one does not default to the scenario name.<br />
<br />
==== wesnoth.show_dialog ====<br />
<br />
* '''wesnoth.show_dialog(''wml_dialog_table'', [''pre_show_function'', [''post_show_function'']])'''<br />
<br />
Displays a dialog box described by a WML table and returns:<br />
* if the dialog was dismissed by a button click, the integer value associated to the button via the "return_value" keyword.<br />
* if the dialog was closed with the enter key, -1.<br />
* if the dialog was closed with the escape key, -2.<br />
<br />
The dialog box is equivalent to the resolution section of a GUI window as described in [[GUIToolkitWML#Window_definition|GUIToolkitWML]] and must therefore contain at least the following children: '''[tooltip]''', '''[helptip]''', and '''[grid]'''. The [grid] must contain nested [row], [column] and [grid] tags which describe the layout of the window. (More information can be found in [[GUILayout]]; suffice to say that the basic structure is grid -> row -> column -> widget, where the widget is considered to be in a cell defined by the row and column of the grid. A list of widgets can be found at [[GUIWidgetInstanceWML]].)<br />
<br />
Two optional functions can be passed as second and third arguments; the first one is called once the dialog is created and before it is shown; the second one is called once the dialog is closed. These functions are helpful in setting the initial values of the fields and in recovering the final user values. These functions can call the [[#wesnoth.set_dialog_value]], [[#wesnoth.get_dialog_value]], and [[#wesnoth.set_dialog_callback]] functions for this purpose.<br />
<br />
This function should be called in conjunction with [[LuaWML:Misc#wesnoth.synchronize_choice|#wesnoth.synchronize_choice]], in order to ensure that only one client displays the dialog and that the other ones recover the same input values from this single client.<br />
<br />
The example below defines a dialog with a list and two buttons on the left, and a big image on the right. The ''preshow'' function fills the list and defines a callback on it. This ''select'' callback changes the displayed image whenever a new list item is selected. The ''postshow'' function recovers the selected item before the dialog is destroyed.<br />
<br />
<syntaxhighlight lang=lua><br />
local helper = wesnoth.require "lua/helper.lua"<br />
local T = helper.set_wml_tag_metatable {}<br />
local _ = wesnoth.textdomain "wesnoth"<br />
<br />
local dialog = {<br />
T.tooltip { id = "tooltip_large" },<br />
T.helptip { id = "tooltip_large" },<br />
T.grid { T.row {<br />
T.column { T.grid {<br />
T.row { T.column { horizontal_grow = true, T.listbox { id = "the_list",<br />
T.list_definition { T.row { T.column { horizontal_grow = true,<br />
T.toggle_panel { return_value = -1, T.grid { T.row {<br />
T.column { horizontal_alignment = "left", T.label { id = "the_label" } },<br />
T.column { T.image { id = "the_icon" } }<br />
} } }<br />
} } }<br />
} } },<br />
T.row { T.column { T.grid { T.row {<br />
T.column { T.button { id = "ok", label = _"OK" } },<br />
T.column { T.button { id = "cancel", label = _"Cancel" } }<br />
} } } }<br />
} },<br />
T.column { T.image { id = "the_image" } }<br />
} }<br />
}<br />
<br />
local function preshow()<br />
local t = { "Ancient Lich", "Ancient Wose", "Elvish Avenger" }<br />
local function select()<br />
local i = wesnoth.get_dialog_value "the_list"<br />
local ut = wesnoth.unit_types[t[i]].__cfg<br />
wesnoth.set_dialog_value(string.gsub(ut.profile, "([^/]+)$", "transparent/%1"), "the_image")<br />
end<br />
wesnoth.set_dialog_callback(select, "the_list")<br />
for i,v in ipairs(t) do<br />
local ut = wesnoth.unit_types[v].__cfg<br />
wesnoth.set_dialog_value(ut.name, "the_list", i, "the_label")<br />
wesnoth.set_dialog_value(ut.image, "the_list", i, "the_icon")<br />
end<br />
wesnoth.set_dialog_value(2, "the_list")<br />
select()<br />
end<br />
<br />
local li<br />
local function postshow()<br />
li = wesnoth.get_dialog_value "the_list"<br />
end<br />
<br />
local r = wesnoth.show_dialog(dialog, preshow, postshow)<br />
wesnoth.message(string.format("Button %d pressed. Item %d selected.", r, li))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.set_dialog_value ====<br />
<br />
* '''wesnoth.set_dialog_value(''value'', ''path, to, widget, id'')'''<br />
<br />
Sets the value of a widget on the current dialog. The value is given by the first argument; its semantic depends on the type of widget it is applied to. The last argument is the ''id'' of the widget. If it does not point to a unique widget in the dialog, some discriminating parents should be given on its left, making a path that is read from left to right by the engine. The row of a list is specified by giving the ''id' of the list as a first argument and the 1-based row number as the next argument.<br />
<br />
-- sets the value of a widget "bar" in the 7th row of the list "foo"<br />
wesnoth.set_dialog_value(_"Hello world", "foo", 7, "bar")<br />
<br />
Notes: When the row of a list does not exist, it is created. The value associated to a list is the selected row.<br />
<br />
==== wesnoth.get_dialog_value ====<br />
<br />
* '''wesnoth.get_dialog_value(''path, to, widget, id'')'''<br />
<br />
Gets the value of a widget on the current dialog. The arguments described the path for reaching the widget (see [[#wesnoth.set_dialog_value]]).<br />
<br />
{{DevFeature1.13|0}}<br />
For treeviews this function returns a table descibing the currently selected node.<br />
If for example in this treeview<br />
+Section1<br />
+Subsection11<br />
*Item1<br />
*Item2<br />
*Item3<br />
+Subsection12<br />
*Item4<br />
*Item5<br />
*Item6<br />
+Section2<br />
+Subsection21<br />
*Item7<br />
*Item8<br />
*Item9<br />
+Subsection22<br />
*Item10<br />
*Item11<br />
*Item12<br />
Item 9 is selcted the value will be {2,1,3}<br />
<br />
==== wesnoth.set_dialog_active ====<br />
<br />
* '''wesnoth.set_dialog_active(''active?'', ''path, to, widget, id'')'''<br />
<br />
Enables or disables a widget. The first argument is a boolean specifying whether the widget should be active (true) or inactive (false). The remaining arguments are the path to locate the widget in question (see [[#wesnoth.set_dialog_value]]).<br />
<br />
==== wesnoth.set_dialog_callback ====<br />
<br />
* '''wesnoth.set_dialog_callback(''callback_function'', ''path, to, widget, id'')'''<br />
<br />
Sets the first argument as a callback function for the widget obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). This function will be called whenever the user modifies something about the widget, so that the dialog can react to it.<br />
<br />
==== wesnoth.set_dialog_markup ====<br />
<br />
* '''wesnoth.set_dialog_markup(''allowed?'', ''path, to, widget, id'')'''<br />
<br />
Sets the flag associated to a widget to enable or disable Pango markup. The new flag value is passed as the first argument (boolean), and the widget to modify is obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). Most widgets start with Pango markup disabled unless this function is used to set their flag to true.<br />
<br />
wesnoth.set_dialog_markup(true, "notice_label")<br />
wesnoth.set_dialog_value("&lt;big&gt;NOTICE!&lt;/big&gt;", "notice_label")<br />
<br />
==== wesnoth.set_dialog_focus ====<br />
<br />
* '''wesnoth.set_dialog_focus(''focused?'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Switches the keyboard focus to the widget found following the given path (see [[#wesnoth.set_dialog_value]]). This is often useful for dialogs containing a central listbox, so that it can be controlled with the keyboard as soon as it is displayed.<br />
<br />
wesnoth.set_dialog_focus("my_listbox")<br />
<br />
==== wesnoth.set_dialog_visible ====<br />
<br />
* '''wesnoth.set_dialog_visible(''visible?'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Sets a widget's visibility status. The new status is passed as the first argument, and the path to the widget is specified by the remaining arguments (see [[#wesnoth.set_dialog_value]]). The following visibility statuses are recognized:<br />
<br />
{| clasS="wikitable"<br />
! String value !! Boolean shorthand !! Meaning<br />
|-<br />
| visible || true || The widget is visible and handles events.<br />
|-<br />
| hidden || || The widget is not visible, doesn't handle events, but still takes up space on the dialog grid.<br />
|-<br />
| invisible || false || The widget is not visible, doesn't handle events, and does not take up space on the dialog grid.<br />
|}<br />
<br />
wesnoth.set_dialog_visible(false, "secret_button")<br />
<br />
==== wesnoth.set_dialog_canvas ====<br />
<br />
* '''wesnoth.set_dialog_canvas(''index'', ''content'', ''path, to, widget, id'')'''<br />
<br />
Sets the WML passed as the second argument as the canvas content (index given by the first argument) of the widget obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). The content of the WML table is described at [[GUICanvasWML]].<br />
<br />
-- draw two rectangles in the upper-left corner of the window (empty path = window widget)<br />
wesnoth.set_dialog_canvas(2, {<br />
T.rectangle { x = 20, y = 20, w = 20, h = 20, fill_color= "0,0,255,255" },<br />
T.rectangle { x = 30, y = 30, w = 20, h = 20, fill_color = "255,0,0,255" }<br />
})<br />
<br />
The meaning of the canvas index depends on the chosen widget. It may be the disabled / enabled states of the widget, or its background / foreground planes, or... For instance, overwriting canvas 1 of the window with an empty canvas causes the window to become transparent.<br />
<br />
==== wesnoth.add_dialog_tree_node ====<br />
<br />
* '''wesnoth.add_dialog_tree_node(''type'', ''index'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|0}}<br />
<br />
Adds a childnode to a treeview widget or a treeview node. The type (id of the node definition) of the node is passed in the first parameter. The second parameter (integer) spcifies where the node should be inserted in the parentnode. The other arguments describe the path of the parent treeview (-node)<br />
<br />
==== wesnoth.remove_dialog_item ====<br />
<br />
* '''wesnoth.remove_dialog_item(''index'', ''count'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|1}}<br />
<br />
Removes an item from a listbox, a multipage or a treeview. First parameter is the index of the item to delete, second parameter is the number of items to delete and the remaining parameters describe the path to the listbox, the multipage or the parent treview node.<br />
<br />
<br />
==== wesnoth.add_widget_definition====<br />
<br />
* '''wesnoth.add_widget_definition(''widget_type'', ''definition_id'', ''wml_content'')'''<br />
<br />
{{DevFeature1.13|?}}<br />
<br />
Creates a new wml widget definition see https://github.com/wesnoth/wesnoth/tree/1.14/data/gui/widget for examples wml_content<br />
<br />
==== wesnoth.is_skipping_messages ====<br />
<br />
* '''wesnoth.is_skipping_messages()'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Returns true if messages are currently being skipped, for example because the player has chosen to skip replay, or has pressed escape to dismiss a message.<br />
<br />
==== wesnoth.skip_messages ====<br />
<br />
* '''wesnoth.skip_messages([''skip?'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Sets the skip messages flag. By default it sets it to true, but you can also pass false to unset the flag.<br />
<br />
==== wesnoth.get_displayed_unit ====<br />
<br />
* '''wesnoth.get_displayed_unit()'''<br />
<br />
Returns a proxy to the unit currently displayed in the side pane of the user interface, if any.<br />
<br />
local name = tostring(wesnoth.get_displayed_unit().name)<br />
<br />
==== wesnoth.log ====<br />
<br />
* '''wesnoth.log([''logger''], ''message', ''in_chat'')'''<br />
<br />
{{DevFeature1.13|5}} Logs a message to the console. These messages are normally not visible unless Wesnoth is run from the command-line or (in Windows) with the --wconsole switch. The in_chat argument, however, can be set to true to also echo the message to the in-game chat area.<br />
<br />
Possible loggers are info, debug, warning, error, and wml. The wml logger is special and is intended for WML errors; it always goes to chat, so the in_chat argument is ignored and can be omitted. The default logger is info.<br />
<br />
==== wesnoth.theme_items ====<br />
<br />
This field is not a function but an associative table. It links item names to the functions that describe their content. These functions are called whenever the user interface is refreshed. The description of an item is a WML table containing '''[element]''' children. Each subtag shall contain either a '''text''' or an '''image''' field that is displayed to the user. It can also contain a '''tooltip''' field that is displayed to the user when moused over, and a "help" field that points to the help section that is displayed when the user clicks on the theme item.<br />
<br />
Note that the ''wesnoth.theme_items'' table is originally empty and using ''pairs'' or ''next'' on it will not return the items from the current theme. Its metatable ensures that the drawing functions of existing items can be recovered though, as long as their name is known. The example below shows how to modify the ''unit_status'' item to display a custom status:<br />
<br />
<syntaxhighlight lang=lua><br />
local old_unit_status = wesnoth.theme_items.unit_status<br />
function wesnoth.theme_items.unit_status()<br />
local _ = wesnoth.textdomain "mydomain"<br />
local u = wesnoth.get_displayed_unit()<br />
if not u then return {} end<br />
local s = old_unit_status()<br />
if u.status.entangled then<br />
table.insert(s, wml.tag.element {<br />
image = "entangled.png",<br />
tooltip = _"entangled: This unit is entangled. It cannot move but it can still attack."<br />
})<br />
end<br />
return s<br />
end<br />
</syntaxhighlight><br />
<br />
The things that would need to be to modified in the above code are:<br />
<br />
* the domain of your addon ("mydomain"), assuming that you are using translations. Otherwise just remove the underscore in the tooltip line.<br />
* the name of the status (u.status.entangled). Note that if the attribute happens to be inside [variables], so be it: u.variables.whatever.<br />
* the path to the image ("entangled.png").<br />
* the tooltip of the status ("entangled: This unit ...").<br />
<br />
The following is a list of valid entries in wesnoth.theme_items which will have an effect in the game. Unfortunately when this feature was created the full range of capabilities of the feature was never properly documented. The following list is automatically generated. To find out what each entry will do, you will have to make guesses and experiment, or read the source code at src/reports.cpp. If you find out what an entry does, you are more than welcome to edit the wiki and give a proper description to any of these fields.<br />
<br />
* '''unit_name'''<br />
* '''selected_unit_name'''<br />
* '''unit_type'''<br />
* '''selected_unit_type'''<br />
* '''unit_race'''<br />
* '''selected_unit_race'''<br />
* '''unit_side'''<br />
* '''selected_unit_side'''<br />
* '''unit_level'''<br />
* '''selected_unit_level'''<br />
* '''unit_amla'''<br />
* '''unit_traits'''<br />
* '''selected_unit_traits'''<br />
* '''unit_status'''<br />
* '''selected_unit_status'''<br />
* '''unit_alignment'''<br />
* '''selected_unit_alignment'''<br />
* '''unit_abilities'''<br />
* '''selected_unit_abilities'''<br />
* '''unit_hp'''<br />
* '''selected_unit_hp'''<br />
* '''unit_xp'''<br />
* '''selected_unit_xp'''<br />
* '''unit_advancement_options'''<br />
* '''selected_unit_advancement_options'''<br />
* '''unit_defense'''<br />
* '''selected_unit_defense'''<br />
* '''unit_vision'''<br />
* '''selected_unit_vision'''<br />
* '''unit_moves'''<br />
* '''selected_unit_moves'''<br />
* '''unit_weapons'''<br />
<syntaxhighlight lang=lua><br />
return { <br />
{ "element", <br />
{ text = "weapon text",<br />
tooltip = _"weapon tooltip"<br />
}<br />
},<br />
...<br />
}<br />
</syntaxhighlight><br />
* '''highlighted_unit_weapons'''<br />
* '''selected_unit_weapons'''<br />
* '''unit_image'''<br />
* '''selected_unit_image'''<br />
* '''selected_unit_profile'''<br />
* '''unit_profile'''<br />
* '''tod_stats'''<br />
* '''time_of_day'''<br />
* '''unit_box'''<br />
* '''turn'''<br />
* '''gold'''<br />
* '''villages'''<br />
* '''num_units'''<br />
* '''upkeep'''<br />
* '''expenses'''<br />
* '''income'''<br />
* '''terrain_info'''<br />
* '''terrain'''<br />
** <nowiki>Text for terrain of the active hex. Same as the one displayed on the UI. It probably returns an empty table when no hex is active. Otherwise, it returns something like {{"element",{text="Grassland (Flat)"}}}.</nowiki><br />
* '''zoom_level'''<br />
* '''position'''<br />
* '''side_playing'''<br />
* '''observers'''<br />
** <nowiki>When there is no observer, it returns an empty table. When there are observers, it gives<br />
{{"element",<br />
{tooltip="Observers\n<observer1>\n<observer2>\n", image="misc/eye.png"}<br />
}}<br />
<br />
</nowiki><br />
* '''selected_terrain'''<br />
* '''edit_left_button_function'''<br />
* '''report_clock'''<br />
** <nowiki>wesnoth.theme_items.report_clock() gives a table {{"element", text=<time>}}, where <time> is HH:MM of local time. It probably return 12hr or 24hr formats depending on user preference. </nowiki><br />
* '''report_countdown'''<br />
** <nowiki>wesnoth.theme_items.report_countdown() gives a table {{"element", text=<time>}}, where <time> is MM:SS of time limit for player's turn. If turn limit < 120 or 60, add <span foreground="#c8c800"><br />
or <span foreground="#c80000"> html tags. </nowiki><br />
<br />
==== helper.get_user_choice ====<br />
<br />
* '''helper.get_user_choice(''message_table'', ''options'')'''<br />
<br />
Displays a WML message box querying a choice from the user. Attributes and options are taken from given tables (see [[InterfaceActionsWML#.5Bmessage.5D|[message]]]). The index of the selected option is returned.<br />
<br />
local result = helper.get_user_choice({ speaker = "narrator" }, { "Choice 1", "Choice 2" })<br />
<br />
[[Category: Lua Reference]]<br />
<br />
==== wesnoth.zoom ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
* '''wesnoth.zoom(''factor''[, ''relative''])'''<br />
<br />
Changes the zoom level of the map. If relative is false, which is the default, it simply sets the zoom level. If relative is true, it zooms relative to the current zoom level. So, for example, if the zoom level is currently 0.5, then wesnoth.zoom(2) sets it to 2, while wesnoth.zoom(2, true) sets it to 1 (2 * 0.5).<br />
<br />
This function also returns the resulting zoom level. Because of this, you can call wesnoth.zoom(1) to simply get the current zoom level.<br />
<br />
Note that this function cannot zoom to a level that the user would not be able to reach from the UI. Attempting to do so will simply select the nearest allowed zoom level.</div>Namhubhttps://wiki.wesnoth.org/index.php?title=LuaWML/Display&diff=59987LuaWML/Display2018-10-16T02:57:00Z<p>Namhub: /* wesnoth.theme_items */</p>
<hr />
<div>This page describes the [[LuaWML]] functions and helpers for interfacing with the user.<br />
<br />
==== wesnoth.message ====<br />
<br />
* '''wesnoth.message([''speaker'',] ''message'')'''<br />
<br />
Displays a string in the chat window and dumps it to the lua/info log domain (''--log-info=scripting/lua'' on the command-line).<br />
<br />
wesnoth.message "Hello World!"<br />
<br />
The chat line header is "<Lua>" by default, but it can be changed by passing a string before the message.<br />
<br />
wesnoth.message("Big Brother", "I'm watching you.") -- will result in "&lt;Big Brother&gt; I'm watching you."<br />
<br />
See also [[LuaWML:Events#helper.wml_error|helper.wml_error]] for displaying error messages.<br />
<br />
==== wesnoth.clear_messages ====<br />
<br />
* '''wesnoth.clear_messages()'''<br />
<br />
Removes all messages from the chat window. No argument or returned values.<br />
<br />
==== wesnoth.textdomain ====<br />
<br />
* '''wesnoth.textdomain(''domain'')'''<br />
<br />
Creates a function proxy for lazily translating strings from the given domain.<br />
<br />
-- #textdomain "my-campaign"<br />
-- the comment above ensures the subsequent strings will be extracted to the proper domain<br />
_ = wesnoth.textdomain "my-campaign"<br />
wesnoth.set_variable("my_unit.description", _ "the unit formerly known as Hero")<br />
<br />
The metatable of the function proxy appears as '''"message domain"'''. The metatable of the translatable strings (results of the proxy) appears as '''"translatable string"'''.<br />
<br />
The translatable strings can be appended to other strings/numbers with the standard '''..''' operator. Translation can be forced with the standard '''tostring''' operator in order to get a plain string.<br />
<br />
wesnoth.message(string.format(tostring(_ "You gain %d gold."), amount))<br />
<br />
==== wesnoth.delay ====<br />
<br />
* '''wesnoth.delay(''milliseconds'')'''<br />
<br />
Delays the engine like the [delay] tag. one argument: time to delay in milliseconds<br />
<br />
wesnoth.delay(500)<br />
<br />
==== wesnoth.float_label ====<br />
<br />
* '''wesnoth.float_label(''x'', ''y'', ''text'')'''<br />
<br />
Pops some text above a map tile.<br />
<br />
wesnoth.float_label(unit.x, unit.y, "&lt;span color='#ff0000'&gt;Ouch&lt;/span&gt;")<br />
<br />
==== wesnoth.get_viewing_side ====<br />
<br />
* '''wesnoth.get_viewing_side()'''<br />
<br />
returns two values 1) the number of the side of the current viewpoint, 2) a boolean specifying whether it has full vision (can only only true happen in replays or for observers)<br />
<br />
==== wesnoth.select_unit ====<br />
<br />
* '''wesnoth.select_hex(''x'', ''y'', [''show_movement'', [''fire_events'']])'''<br />
* {{DevFeature1.13|5}} '''wesnoth.select_unit(''unit'', [''show_movement'', [''fire_events'']])'''<br />
* {{DevFeature1.13|5}} '''''unit'':select([''show_movement'', [''fire_events'']])'''<br />
<br />
Selects the given unit in the game map as if the player had clicked on it.<br />
Argument 3: boolean, whether to show the movement range of any unit on that location (def: true)<br />
Argument 4: boolean, whether to fire any select events (def: false). Note: currently (1.14.1), this argument has no effect (events are never fired).<br />
<br />
wesnoth.select_unit(14,6, true, true)<br />
<br />
The '''wesnoth.select_hex''' form is deprecated. If there is a unit on the location, it does the same thing as '''wesnoth.select_unit''', but if ''show_movement'' is true it also calls '''wesnoth.highlight_hex''' for the location. If there is no unit on the location, '''wesnoth.select_hex''' does not do anything useful.<br />
<br />
If called without arguments, '''wesnoth.select_unit''' deselects the current unit from the map as long as the mouse cursor is not on its hex. It will continue to be displayed on the UI sidebar in any case.<br />
<br />
==== wesnoth.highlight_hex ====<br />
<br />
* '''wesnoth.highlight_hex(''x'', ''y'')'''<br />
<br />
Draws an outline around the specified hex.<br />
<br />
==== wesnoth.deselect_hex ====<br />
<br />
* '''wesnoth.deselect_hex()'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Reverses any select_hex call, leaving all locations unhighlighted. Takes no arguments.<br />
<br />
==== wesnoth.scroll_to_tile ====<br />
<br />
* '''wesnoth.scroll_to_tile(''x'', ''y'', [''only_if_visible'', [''instant'']])'''<br />
* {{DevFeature1.13|7}} '''wesnoth.scroll_to_tile(''x'', ''y'', [''only_if_visible'', [''instant'', [''only_if_needed'']]])'''<br />
<br />
Scrolls the map to the given location. If true is passed as the third parameter, scrolling is disabled if the tile is hidden under the fog. If true is passed as the fourth parameter, the view instantly warps to the location regardless of the scroll speed setting in Preferences. If true is passed as the fifth parameter, no scrolling occurs if the target location is already visible onscreen.<br />
<br />
local u = wesnoth.get_units({ id = "hero" })[1]<br />
wesnoth.scroll_to_tile(u.x, u.y)<br />
<br />
==== wesnoth.lock_view ====<br />
<br />
* '''wesnoth.lock_view(''lock'')'''<br />
<br />
Locks or unlocks gamemap view scrolling for human players. If true is passed as the first parameter, the view is locked; pass false to unlock.<br />
<br />
Human players cannot scroll the gamemap view as long as it is locked, but Lua or WML actions such as wesnoth.scroll_to_tile still can; the locked/unlocked state is preserved when saving the current game. This feature is generally intended to be used in cutscenes to prevent the player scrolling away from scripted actions.<br />
<br />
wesnoth.lock_view(true)<br />
wesnoth.scroll_to_tile(12, 14, false, true)<br />
<br />
==== wesnoth.view_locked ====<br />
<br />
* '''wesnoth.view_locked()'''<br />
<br />
Returns a boolean indicating whether gamemap view scrolling is currently locked.<br />
<br />
==== wesnoth.play_sound ====<br />
<br />
* '''wesnoth.play_sound(''sound'', [''repeat_count''])'''<br />
<br />
Plays the given sound file once, optionally repeating it one or more more times if an integer value is provided as a second argument (note that the sound is ''repeated'' the number of times specified in the second argument, i.e. a second argument of 4 will cause the sound to be played once and then repeated four more times for a total of 5 plays. See the example below).<br />
<br />
wesnoth.play_sound "ambient/birds1.ogg"<br />
wesnoth.play_sound("magic-holy-miss-3.ogg", 4) -- played 1 + 4 = 5 times<br />
<br />
==== wesnoth.set_music ====<br />
<br />
* '''wesnoth.set_music(''music_entry'')'''<br />
<br />
Sets the given table as an entry into the music list. See [[MusicListWML]] for the recognized attributes.<br />
<br />
wesnoth.set_music { name = "traveling_minstrels.ogg" }<br />
<br />
Passing no argument forces the engine to take into account all the recent changes to the music list. (Note: this is done automatically when sequences of WML commands end, so it is useful only for long events.)<br />
<br />
{{DevFeature1.13|8}} This function is now deprecated. Use the '''wesnoth.music_list''' table instead<br />
<br />
==== wesnoth.music_list ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
This is a table giving access to the current music playlist. It can be accessed as a normal array, including the Lua length operator. If you assign a music config to an entry, the track is replaced. It is not a normal array however and cannot be manipulated with the table library.<br />
<br />
In addition, it has the following named fields:<br />
<br />
* '''wesnoth.music_list.current''' (read-write): The currently-playing track. This may sometimes be a track that's not on the playlist - "play once" tracks are not placed on the playlist.<br />
* '''wesnoth.music_list.current.__cfg''' (read-only): Returns a copy of the current track information.<br />
* '''wesnoth.music_list.previous''' (read-write): The track played before the current one. This may sometimes be a track that's not on the playlist - "play once" tracks are not placed on the playlist.<br />
* '''wesnoth.music_list.previous.__cfg''' (read-only): Returns a copy of the previous track information. NOTE: Wesnoth's playlist implementation effectively "plays" every song as it's added to the playlist, so when replacing one playlist with another, this will return information on the second-to-last track added to the new playlist, not the track you actually heard playing from the playlist that was replaced.<br />
* '''wesnoth.music_list.current_i''' (read-write): The index of the currently-playing track on the playlist, or nil if the currently-playing track is not on the playlist.<br />
* '''wesnoth.music_list.volume''' (read-write): The current music volume, as a percentage of the user's preferred volume set in preferences.<br />
* '''wesnoth.music_list.all''' (read-only): Returns a copy of the music list as an array of WML tables.<br />
<br />
It also contains some functions:<br />
<br />
* '''wesnoth.music_list.add(''track_name'', [''immediate'',] [''ms_before'', [''ms_after'']])''': Appends a track to the playlist. If true is passed, also start playing the new track.<br />
* '''wesnoth.music_list.remove(''n1'', ...)''': Removes one or more tracks by their index. You can pass as many indices as you wish. If one of the removed tracks is currently playing, it continues to play.<br />
* '''wesnoth.music_list.clear()''': Clears the playlist. The currently-playing track continues to play.<br />
* '''wesnoth.music_list.next()''': Stop playing the current track and move on to the next one. This honours the shuffle settings.<br />
* '''wesnoth.music_list.play(''track_name'')''': Start playing a track without appending it to the playlist.<br />
<br />
Each track contains the following fields:<br />
<br />
* '''shuffle''' (read-write)<br />
* '''once''' (read-write): generally only true for '''wesnoth.music_list.current'''<br />
* '''ms_before''' (read-write)<br />
* '''ms_after''' (read-write)<br />
* '''immediate''' (read-only)<br />
* '''name''' (read-only): the unresolved track filename<br />
* '''title''' (read-only): a user-friendly track title<br />
<br />
==== wesnoth.sound_volume ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
* '''wesnoth.sound_volume(''new_volume'')'''<br />
<br />
Sets the current sound volume, as a percentage of the user's preferred volume set in preferences.<br />
Returns the previous sound volume in the same format.<br />
<br />
==== wesnoth.show_menu ====<br />
<br />
* '''wesnoth.show_menu(''items'' [, ''initial''] [, ''markup''])'''<br />
<br />
Shows a popup menu onscreen at the current mouse location. This could be used for example to produce a sort of submenu in a <tt>[set_menu_item]</tt>. The items are specified as a Lua array of tables, each of which supports the following keys:<br />
<br />
* ''icon'': An icon to display in the leftmost column of the menu.<br />
* ''image'': An image to display in the main column of the menu. If this is present, ''label'' is ignored.<br />
* ''label'': A label to display in the main column of the menu.<br />
* ''second_label'': A secondary label to display in the right column of the menu.<br />
* ''tooltip'': Text to display when mousing over this option.<br />
<br />
The ''initial'' argument must be a valid index into the ''items'' array, or 0 to indicate that no element is initially selected (which is the default but typically not what you want).<br />
<br />
The ''markup'' argument specifies whether Pango markup will be parsed in the menuitems. It defaults to false.<br />
<br />
The ''initial'' and ''markup'' arguments can be passed in either order; the game will understand which is meant based on the type of the argument.<br />
<br />
==== wesnoth.show_message_box ====<br />
<br />
* '''wesnoth.show_message_box(''title'', ''message'' [, ''button''] [, ''markup''])'''<br />
* '''wesnoth.confirm([''title'',] ''message'')'''<br />
* '''wesnoth.alert([''title''], ''message'')'''<br />
<br />
Shows a standard message box onscreen (similar to the quit confirmation message, for example). The button can be any arbitrary potentially-translatable string (in which case, there will be one button with that label), or it can be one of the following special values:<br />
<br />
* ''ok'' or nil: A single OK button; this is the default<br />
* ''cancel'': A single Cancel button<br />
* ''close'': A single Close button<br />
* ''ok_cancel'': Two buttons labelled OK and Cancel<br />
* ''yes_no'': Two buttons labelled Yes and No<br />
* an empty string: No buttons; the dialog automatically closes after a few seconds<br />
<br />
The alert and confirm functions are simpler wrappers for this function, using a single OK button and a pair of Yes/No buttons, respectively. Both confirm and show_message_box return false if No or Cancel was clicked, and true otherwise.<br />
<br />
==== wesnoth.show_message_dialog ====<br />
<br />
* '''wesnoth.show_message_dialog(''attributes'', [''options'', [''text_input_attributes'']])'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Shows a message dialog, of the type used by the [message] ActionWML tag. Unlike the [message] tag, this is unsynced; if you need it synced, you must do it yourself. The first argument is a table describing the dialog with the following keys:<br />
<br />
* ''title'' - The title to show on the message. For example, the speaker's name.<br />
* ''message'' - The message content.<br />
* ''portrait'' - An image to show along with the message. By default, no image is shown.<br />
* ''left_side'' - The default is true; set to false to show the image on the right.<br />
* ''mirror'' - If true, the image will be flipped horizontally.<br />
<br />
The second argument is a list of options as a Lua array. Each option is either a (possibly-translatable) string or a config with [[DescriptionWML#WML_Format|DescriptionWML]] keys. The array itself can also have an optional '''default''' key which if present should be the index of the initially selected option (useful if you don't need full DescriptionWML but want to set a default). If present it overrides any defaults set in individual options.<br />
<br />
The third argument is a table describing the text input field with the following keys:<br />
<br />
* ''label'' - A label to show to the left of the text field.<br />
* ''text'' - Initial contents of the text field.<br />
* ''max_length'' - Maximum input length in characters (defaults to 256).<br />
<br />
You need at least one key for the text input to be shown. Both the second arguments are option, but if you want text input with no options, you must pass nil for the second parameter.<br />
<br />
This function returns two values. The first is the numeric result of the dialog. If there are no options and no text input, this is -2 if the user closed by pressing Escape, otherwise it's -1. If there are options, this is the index of the option chosen (starting from 1). If there is text input but no options, the first return value is 0. If there was text input, the second value contains the text entered.<br />
<br />
Example:<br />
<br />
wesnoth.show_message_dialog({<br />
title = "Make your choice:",<br />
message = "Select an option and enter some text.",<br />
portrait = "wesnoth-icon.png",<br />
}, {<br />
"The first choice is always the best!",<br />
"Pick me! Second choices are better!",<br />
"You know you want the third option!",<br />
}, {<br />
label = "Text:",<br />
text = "?",<br />
max_length = 16<br />
})<br />
<br />
(You don't have to format it like that, of course.)<br />
<br />
==== wesnoth.show_popup_dialog ====<br />
<br />
* '''wesnoth.show_popup_dialog(''title'', ''message'', [''image''])'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Shows a simple popup dialog in the centre of the screen. Takes three arguments, which in order are:<br />
<br />
# A title string for the dialog<br />
# The message content for the dialog.<br />
# An image to show.<br />
<br />
Both the title and the message support Pango markup. The image is optional.<br />
<br />
==== wesnoth.show_story ====<br />
<br />
* '''wesnoth.show_story(''story_config'', ''default_title'')'''<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
Shows the storyscreen. The passed config is identical to the contents of [[IntroWML|[story]]]. The second parameter is the default title used if a part does not specify one — unlike intro storyscreens, a Lua-invoked one does not default to the scenario name.<br />
<br />
==== wesnoth.show_dialog ====<br />
<br />
* '''wesnoth.show_dialog(''wml_dialog_table'', [''pre_show_function'', [''post_show_function'']])'''<br />
<br />
Displays a dialog box described by a WML table and returns:<br />
* if the dialog was dismissed by a button click, the integer value associated to the button via the "return_value" keyword.<br />
* if the dialog was closed with the enter key, -1.<br />
* if the dialog was closed with the escape key, -2.<br />
<br />
The dialog box is equivalent to the resolution section of a GUI window as described in [[GUIToolkitWML#Window_definition|GUIToolkitWML]] and must therefore contain at least the following children: '''[tooltip]''', '''[helptip]''', and '''[grid]'''. The [grid] must contain nested [row], [column] and [grid] tags which describe the layout of the window. (More information can be found in [[GUILayout]]; suffice to say that the basic structure is grid -> row -> column -> widget, where the widget is considered to be in a cell defined by the row and column of the grid. A list of widgets can be found at [[GUIWidgetInstanceWML]].)<br />
<br />
Two optional functions can be passed as second and third arguments; the first one is called once the dialog is created and before it is shown; the second one is called once the dialog is closed. These functions are helpful in setting the initial values of the fields and in recovering the final user values. These functions can call the [[#wesnoth.set_dialog_value]], [[#wesnoth.get_dialog_value]], and [[#wesnoth.set_dialog_callback]] functions for this purpose.<br />
<br />
This function should be called in conjunction with [[LuaWML:Misc#wesnoth.synchronize_choice|#wesnoth.synchronize_choice]], in order to ensure that only one client displays the dialog and that the other ones recover the same input values from this single client.<br />
<br />
The example below defines a dialog with a list and two buttons on the left, and a big image on the right. The ''preshow'' function fills the list and defines a callback on it. This ''select'' callback changes the displayed image whenever a new list item is selected. The ''postshow'' function recovers the selected item before the dialog is destroyed.<br />
<br />
<syntaxhighlight lang=lua><br />
local helper = wesnoth.require "lua/helper.lua"<br />
local T = helper.set_wml_tag_metatable {}<br />
local _ = wesnoth.textdomain "wesnoth"<br />
<br />
local dialog = {<br />
T.tooltip { id = "tooltip_large" },<br />
T.helptip { id = "tooltip_large" },<br />
T.grid { T.row {<br />
T.column { T.grid {<br />
T.row { T.column { horizontal_grow = true, T.listbox { id = "the_list",<br />
T.list_definition { T.row { T.column { horizontal_grow = true,<br />
T.toggle_panel { return_value = -1, T.grid { T.row {<br />
T.column { horizontal_alignment = "left", T.label { id = "the_label" } },<br />
T.column { T.image { id = "the_icon" } }<br />
} } }<br />
} } }<br />
} } },<br />
T.row { T.column { T.grid { T.row {<br />
T.column { T.button { id = "ok", label = _"OK" } },<br />
T.column { T.button { id = "cancel", label = _"Cancel" } }<br />
} } } }<br />
} },<br />
T.column { T.image { id = "the_image" } }<br />
} }<br />
}<br />
<br />
local function preshow()<br />
local t = { "Ancient Lich", "Ancient Wose", "Elvish Avenger" }<br />
local function select()<br />
local i = wesnoth.get_dialog_value "the_list"<br />
local ut = wesnoth.unit_types[t[i]].__cfg<br />
wesnoth.set_dialog_value(string.gsub(ut.profile, "([^/]+)$", "transparent/%1"), "the_image")<br />
end<br />
wesnoth.set_dialog_callback(select, "the_list")<br />
for i,v in ipairs(t) do<br />
local ut = wesnoth.unit_types[v].__cfg<br />
wesnoth.set_dialog_value(ut.name, "the_list", i, "the_label")<br />
wesnoth.set_dialog_value(ut.image, "the_list", i, "the_icon")<br />
end<br />
wesnoth.set_dialog_value(2, "the_list")<br />
select()<br />
end<br />
<br />
local li<br />
local function postshow()<br />
li = wesnoth.get_dialog_value "the_list"<br />
end<br />
<br />
local r = wesnoth.show_dialog(dialog, preshow, postshow)<br />
wesnoth.message(string.format("Button %d pressed. Item %d selected.", r, li))<br />
</syntaxhighlight><br />
<br />
==== wesnoth.set_dialog_value ====<br />
<br />
* '''wesnoth.set_dialog_value(''value'', ''path, to, widget, id'')'''<br />
<br />
Sets the value of a widget on the current dialog. The value is given by the first argument; its semantic depends on the type of widget it is applied to. The last argument is the ''id'' of the widget. If it does not point to a unique widget in the dialog, some discriminating parents should be given on its left, making a path that is read from left to right by the engine. The row of a list is specified by giving the ''id' of the list as a first argument and the 1-based row number as the next argument.<br />
<br />
-- sets the value of a widget "bar" in the 7th row of the list "foo"<br />
wesnoth.set_dialog_value(_"Hello world", "foo", 7, "bar")<br />
<br />
Notes: When the row of a list does not exist, it is created. The value associated to a list is the selected row.<br />
<br />
==== wesnoth.get_dialog_value ====<br />
<br />
* '''wesnoth.get_dialog_value(''path, to, widget, id'')'''<br />
<br />
Gets the value of a widget on the current dialog. The arguments described the path for reaching the widget (see [[#wesnoth.set_dialog_value]]).<br />
<br />
{{DevFeature1.13|0}}<br />
For treeviews this function returns a table descibing the currently selected node.<br />
If for example in this treeview<br />
+Section1<br />
+Subsection11<br />
*Item1<br />
*Item2<br />
*Item3<br />
+Subsection12<br />
*Item4<br />
*Item5<br />
*Item6<br />
+Section2<br />
+Subsection21<br />
*Item7<br />
*Item8<br />
*Item9<br />
+Subsection22<br />
*Item10<br />
*Item11<br />
*Item12<br />
Item 9 is selcted the value will be {2,1,3}<br />
<br />
==== wesnoth.set_dialog_active ====<br />
<br />
* '''wesnoth.set_dialog_active(''active?'', ''path, to, widget, id'')'''<br />
<br />
Enables or disables a widget. The first argument is a boolean specifying whether the widget should be active (true) or inactive (false). The remaining arguments are the path to locate the widget in question (see [[#wesnoth.set_dialog_value]]).<br />
<br />
==== wesnoth.set_dialog_callback ====<br />
<br />
* '''wesnoth.set_dialog_callback(''callback_function'', ''path, to, widget, id'')'''<br />
<br />
Sets the first argument as a callback function for the widget obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). This function will be called whenever the user modifies something about the widget, so that the dialog can react to it.<br />
<br />
==== wesnoth.set_dialog_markup ====<br />
<br />
* '''wesnoth.set_dialog_markup(''allowed?'', ''path, to, widget, id'')'''<br />
<br />
Sets the flag associated to a widget to enable or disable Pango markup. The new flag value is passed as the first argument (boolean), and the widget to modify is obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). Most widgets start with Pango markup disabled unless this function is used to set their flag to true.<br />
<br />
wesnoth.set_dialog_markup(true, "notice_label")<br />
wesnoth.set_dialog_value("&lt;big&gt;NOTICE!&lt;/big&gt;", "notice_label")<br />
<br />
==== wesnoth.set_dialog_focus ====<br />
<br />
* '''wesnoth.set_dialog_focus(''focused?'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Switches the keyboard focus to the widget found following the given path (see [[#wesnoth.set_dialog_value]]). This is often useful for dialogs containing a central listbox, so that it can be controlled with the keyboard as soon as it is displayed.<br />
<br />
wesnoth.set_dialog_focus("my_listbox")<br />
<br />
==== wesnoth.set_dialog_visible ====<br />
<br />
* '''wesnoth.set_dialog_visible(''visible?'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Sets a widget's visibility status. The new status is passed as the first argument, and the path to the widget is specified by the remaining arguments (see [[#wesnoth.set_dialog_value]]). The following visibility statuses are recognized:<br />
<br />
{| clasS="wikitable"<br />
! String value !! Boolean shorthand !! Meaning<br />
|-<br />
| visible || true || The widget is visible and handles events.<br />
|-<br />
| hidden || || The widget is not visible, doesn't handle events, but still takes up space on the dialog grid.<br />
|-<br />
| invisible || false || The widget is not visible, doesn't handle events, and does not take up space on the dialog grid.<br />
|}<br />
<br />
wesnoth.set_dialog_visible(false, "secret_button")<br />
<br />
==== wesnoth.set_dialog_canvas ====<br />
<br />
* '''wesnoth.set_dialog_canvas(''index'', ''content'', ''path, to, widget, id'')'''<br />
<br />
Sets the WML passed as the second argument as the canvas content (index given by the first argument) of the widget obtained by following the path of the other arguments (see [[#wesnoth.set_dialog_value]]). The content of the WML table is described at [[GUICanvasWML]].<br />
<br />
-- draw two rectangles in the upper-left corner of the window (empty path = window widget)<br />
wesnoth.set_dialog_canvas(2, {<br />
T.rectangle { x = 20, y = 20, w = 20, h = 20, fill_color= "0,0,255,255" },<br />
T.rectangle { x = 30, y = 30, w = 20, h = 20, fill_color = "255,0,0,255" }<br />
})<br />
<br />
The meaning of the canvas index depends on the chosen widget. It may be the disabled / enabled states of the widget, or its background / foreground planes, or... For instance, overwriting canvas 1 of the window with an empty canvas causes the window to become transparent.<br />
<br />
==== wesnoth.add_dialog_tree_node ====<br />
<br />
* '''wesnoth.add_dialog_tree_node(''type'', ''index'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|0}}<br />
<br />
Adds a childnode to a treeview widget or a treeview node. The type (id of the node definition) of the node is passed in the first parameter. The second parameter (integer) spcifies where the node should be inserted in the parentnode. The other arguments describe the path of the parent treeview (-node)<br />
<br />
==== wesnoth.remove_dialog_item ====<br />
<br />
* '''wesnoth.remove_dialog_item(''index'', ''count'', ''path, to, widget, id'')'''<br />
<br />
{{DevFeature1.13|1}}<br />
<br />
Removes an item from a listbox, a multipage or a treeview. First parameter is the index of the item to delete, second parameter is the number of items to delete and the remaining parameters describe the path to the listbox, the multipage or the parent treview node.<br />
<br />
<br />
==== wesnoth.add_widget_definition====<br />
<br />
* '''wesnoth.add_widget_definition(''widget_type'', ''definition_id'', ''wml_content'')'''<br />
<br />
{{DevFeature1.13|?}}<br />
<br />
Creates a new wml widget definition see https://github.com/wesnoth/wesnoth/tree/1.14/data/gui/widget for examples wml_content<br />
<br />
==== wesnoth.is_skipping_messages ====<br />
<br />
* '''wesnoth.is_skipping_messages()'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Returns true if messages are currently being skipped, for example because the player has chosen to skip replay, or has pressed escape to dismiss a message.<br />
<br />
==== wesnoth.skip_messages ====<br />
<br />
* '''wesnoth.skip_messages([''skip?'')'''<br />
<br />
{{DevFeature1.13|2}}<br />
<br />
Sets the skip messages flag. By default it sets it to true, but you can also pass false to unset the flag.<br />
<br />
==== wesnoth.get_displayed_unit ====<br />
<br />
* '''wesnoth.get_displayed_unit()'''<br />
<br />
Returns a proxy to the unit currently displayed in the side pane of the user interface, if any.<br />
<br />
local name = tostring(wesnoth.get_displayed_unit().name)<br />
<br />
==== wesnoth.log ====<br />
<br />
* '''wesnoth.log([''logger''], ''message', ''in_chat'')'''<br />
<br />
{{DevFeature1.13|5}} Logs a message to the console. These messages are normally not visible unless Wesnoth is run from the command-line or (in Windows) with the --wconsole switch. The in_chat argument, however, can be set to true to also echo the message to the in-game chat area.<br />
<br />
Possible loggers are info, debug, warning, error, and wml. The wml logger is special and is intended for WML errors; it always goes to chat, so the in_chat argument is ignored and can be omitted. The default logger is info.<br />
<br />
==== wesnoth.theme_items ====<br />
<br />
This field is not a function but an associative table. It links item names to the functions that describe their content. These functions are called whenever the user interface is refreshed. The description of an item is a WML table containing '''[element]''' children. Each subtag shall contain either a '''text''' or an '''image''' field that is displayed to the user. It can also contain a '''tooltip''' field that is displayed to the user when moused over, and a "help" field that points to the help section that is displayed when the user clicks on the theme item.<br />
<br />
Note that the ''wesnoth.theme_items'' table is originally empty and using ''pairs'' or ''next'' on it will not return the items from the current theme. Its metatable ensures that the drawing functions of existing items can be recovered though, as long as their name is known. The example below shows how to modify the ''unit_status'' item to display a custom status:<br />
<br />
<syntaxhighlight lang=lua><br />
local old_unit_status = wesnoth.theme_items.unit_status<br />
function wesnoth.theme_items.unit_status()<br />
local _ = wesnoth.textdomain "mydomain"<br />
local u = wesnoth.get_displayed_unit()<br />
if not u then return {} end<br />
local s = old_unit_status()<br />
if u.status.entangled then<br />
table.insert(s, wml.tag.element {<br />
image = "entangled.png",<br />
tooltip = _"entangled: This unit is entangled. It cannot move but it can still attack."<br />
})<br />
end<br />
return s<br />
end<br />
</syntaxhighlight><br />
<br />
The things that would need to be to modified in the above code are:<br />
<br />
* the domain of your addon ("mydomain"), assuming that you are using translations. Otherwise just remove the underscore in the tooltip line.<br />
* the name of the status (u.status.entangled). Note that if the attribute happens to be inside [variables], so be it: u.variables.whatever.<br />
* the path to the image ("entangled.png").<br />
* the tooltip of the status ("entangled: This unit ...").<br />
<br />
The following is a list of valid entries in wesnoth.theme_items which will have an effect in the game. Unfortunately when this feature was created the full range of capabilities of the feature was never properly documented. The following list is automatically generated. To find out what each entry will do, you will have to make guesses and experiment, or read the source code at src/reports.cpp. If you find out what an entry does, you are more than welcome to edit the wiki and give a proper description to any of these fields.<br />
<br />
* '''unit_name'''<br />
* '''selected_unit_name'''<br />
* '''unit_type'''<br />
* '''selected_unit_type'''<br />
* '''unit_race'''<br />
* '''selected_unit_race'''<br />
* '''unit_side'''<br />
* '''selected_unit_side'''<br />
* '''unit_level'''<br />
* '''selected_unit_level'''<br />
* '''unit_amla'''<br />
* '''unit_traits'''<br />
* '''selected_unit_traits'''<br />
* '''unit_status'''<br />
* '''selected_unit_status'''<br />
* '''unit_alignment'''<br />
* '''selected_unit_alignment'''<br />
* '''unit_abilities'''<br />
* '''selected_unit_abilities'''<br />
* '''unit_hp'''<br />
* '''selected_unit_hp'''<br />
* '''unit_xp'''<br />
* '''selected_unit_xp'''<br />
* '''unit_advancement_options'''<br />
* '''selected_unit_advancement_options'''<br />
* '''unit_defense'''<br />
* '''selected_unit_defense'''<br />
* '''unit_vision'''<br />
* '''selected_unit_vision'''<br />
* '''unit_moves'''<br />
* '''selected_unit_moves'''<br />
* '''unit_weapons'''<br />
<syntaxhighlight lang=lua><br />
return { <br />
{<br />
"element", <br />
{<br />
text = "weapon text",<br />
tooltip = _"weapon tooltip"<br />
}<br />
},<br />
...<br />
}<br />
</syntaxhighlight><br />
* '''highlighted_unit_weapons'''<br />
* '''selected_unit_weapons'''<br />
* '''unit_image'''<br />
* '''selected_unit_image'''<br />
* '''selected_unit_profile'''<br />
* '''unit_profile'''<br />
* '''tod_stats'''<br />
* '''time_of_day'''<br />
* '''unit_box'''<br />
* '''turn'''<br />
* '''gold'''<br />
* '''villages'''<br />
* '''num_units'''<br />
* '''upkeep'''<br />
* '''expenses'''<br />
* '''income'''<br />
* '''terrain_info'''<br />
* '''terrain'''<br />
** <nowiki>Text for terrain of the active hex. Same as the one displayed on the UI. It probably returns an empty table when no hex is active. Otherwise, it returns something like {{"element",{text="Grassland (Flat)"}}}.</nowiki><br />
* '''zoom_level'''<br />
* '''position'''<br />
* '''side_playing'''<br />
* '''observers'''<br />
** <nowiki>When there is no observer, it returns an empty table. When there are observers, it gives<br />
{{"element",<br />
{tooltip="Observers\n<observer1>\n<observer2>\n", image="misc/eye.png"}<br />
}}<br />
<br />
</nowiki><br />
* '''selected_terrain'''<br />
* '''edit_left_button_function'''<br />
* '''report_clock'''<br />
** <nowiki>wesnoth.theme_items.report_clock() gives a table {{"element", text=<time>}}, where <time> is HH:MM of local time. It probably return 12hr or 24hr formats depending on user preference. </nowiki><br />
* '''report_countdown'''<br />
** <nowiki>wesnoth.theme_items.report_countdown() gives a table {{"element", text=<time>}}, where <time> is MM:SS of time limit for player's turn. If turn limit < 120 or 60, add <span foreground="#c8c800"><br />
or <span foreground="#c80000"> html tags. </nowiki><br />
<br />
==== helper.get_user_choice ====<br />
<br />
* '''helper.get_user_choice(''message_table'', ''options'')'''<br />
<br />
Displays a WML message box querying a choice from the user. Attributes and options are taken from given tables (see [[InterfaceActionsWML#.5Bmessage.5D|[message]]]). The index of the selected option is returned.<br />
<br />
local result = helper.get_user_choice({ speaker = "narrator" }, { "Choice 1", "Choice 2" })<br />
<br />
[[Category: Lua Reference]]<br />
<br />
==== wesnoth.zoom ====<br />
<br />
{{DevFeature1.13|8}}<br />
<br />
* '''wesnoth.zoom(''factor''[, ''relative''])'''<br />
<br />
Changes the zoom level of the map. If relative is false, which is the default, it simply sets the zoom level. If relative is true, it zooms relative to the current zoom level. So, for example, if the zoom level is currently 0.5, then wesnoth.zoom(2) sets it to 2, while wesnoth.zoom(2, true) sets it to 1 (2 * 0.5).<br />
<br />
This function also returns the resulting zoom level. Because of this, you can call wesnoth.zoom(1) to simply get the current zoom level.<br />
<br />
Note that this function cannot zoom to a level that the user would not be able to reach from the UI. Attempting to do so will simply select the nearest allowed zoom level.</div>Namhubhttps://wiki.wesnoth.org/index.php?title=BuildingScenariosAdvanced&diff=59982BuildingScenariosAdvanced2018-10-10T22:07:27Z<p>Namhub: </p>
<hr />
<div>{{BuildingScenariosNav}}<br />
<br />
== '''TODO:''' ==<br />
This contained a repetition of what was already inside [[BuildingScenariosIntermediate]]<br />
This should contain: <br />
* (more) information about making & using preprocessors ([[PreprocessorRef]])<br />
* information on guidelines concerning the general layout of a scenario file<br />
* advanced filtering<br />
* ...<br />
<br />
Ayone who feels like writing something, go ahead<br />
<br />
== Advanced Events ==<br />
<br />
===Internal Actions===<br />
See [[InternalActionsWML]] for a complete list of all tags and values. In what follows, the basics of variable creation and manipulation are explained.<br />
<br />
====Variables====<br />
(This can be skipped if you're familiar with the concept of variables)<br />
<br />
(See [[VariablesWML]] for more)<br />
<br />
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!<br />
<br />
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.<br />
<br />
Most variables provided by the engine are associated with a certain tag and can thus only be used inside them.<br />
<br />
====Manipulating====<br />
These three actions can be executed in one single tag: ''''[set_variable]''''<br />
Say we wanted to store 'Hello World' in a variable named ''message_to_the_world''. This is how we would do this:<br />
[event]<br />
.<br />
.<br />
.<br />
[set_variable]<br />
#The name of our variable:<br />
name=message_to_the_world<br />
#The value of message_to_the_world, notice the underscore!<br />
value= _ "Hello World!"<br />
[/set_variable]<br />
.<br />
.<br />
.<br />
[/event]<br />
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. <br />
If we want to add something to our message we need to use this:<br />
<br />
[event]<br />
.<br />
.<br />
.<br />
[set_variable]<br />
name=message_to_the_world<br />
value= _ "$message_to_the_world Have a nice day!"<br />
[/set_variable]<br />
.<br />
.<br />
.<br />
[/event]<br />
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:<br />
<br />
[event]<br />
.<br />
.<br />
.<br />
[set_variable]<br />
name=number_x<br />
value=10<br />
[/set_variable]<br />
[set_variable]<br />
name=number_x<br />
add=-9<br />
[/set_variable]<br />
[set_variable]<br />
name=number_x<br />
multiply=200<br />
[/set_variable]<br />
[set_variable]<br />
name=number_x<br />
multiply=0.5<br />
[/set_variable]<br />
.<br />
.<br />
.<br />
[/event]<br />
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.<br />
<br />
====Using Variables====<br />
Now that we know how to create and manipulate variables, we'll learn how to use them.<br />
First of all, you need to know what variables you always have at your disposal! In an event tag, these variables are <br />
* '''side_number''': the number of the current player's side (may be empty during start or prestart events)<br />
* '''turn_number''': the number of the current turn (may be empty during start or prestart events)<br />
* '''x1''': this is the x-coordinate of the location where the most recent event was triggered<br />
* '''y1''': this is the y-coordinate of the location where the most recent event was triggered<br />
* '''x2''': this is the x-coordinate of the location that assisted in triggering the most recent event<br />
* '''y2''': this is the y-coordinate of the location that assisted in triggering the most recent event<br />
* '''unit''': inside an event, this is the unit at $x1,$y1<br />
* '''second_unit''': inside an event, this is the unit at $x2,$y2<br />
* '''this_unit''': inside a standard unit filter, this is the unit currently being considered for a possible match.<br />
<br />
Some of these are only containers for other variables. The ''unit'' variable is an example. You can acces those 'sub'-variables by using dots:<br />
unit.hitpoints<br />
unit.side<br />
...<br />
<br />
We will use '''unit''' in an example to show you how you can use all this:<br />
[scenario]<br />
.<br />
.<br />
.<br />
[event]<br />
#A unit moves onto a tile:<br />
name=moveto<br />
[filter]<br />
x,y=25,26<br />
[/filter]<br />
<br />
<br />
[set_variable]<br />
name=unit.hitpoints<br />
add=-5<br />
[/set_variable]<br />
[set_variable]<br />
name=unit.status.poisoned<br />
value=yes<br />
[/set_variable]<br />
<br />
#After we have changed the values, we need to apply them.<br />
#We do this by using the unstore_unit tag like this:<br />
[unstore_unit]<br />
variable=unit<br />
find_vacant=no<br />
[/unstore_unit]<br />
[/event]<br />
#We're finished!<br />
.<br />
.<br />
.<br />
[/scenario]<br />
<br />
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].<br />
<br />
As of version 1.9, this can also be done much easier:<br />
<br />
[event]<br />
#A unit moves onto a tile:<br />
name=moveto<br />
[filter]<br />
x,y=25,26<br />
[/filter]<br />
#modify the unit <br />
[modify_unit]<br />
[filter]<br />
x,y=25,26 <br />
[/filter]<br />
hitpoints=$($unit.hitpoints - 5)<br />
status.poisoned=yes<br />
[/modify_unit]<br />
[/event]<br />
#We're finished!<br />
<br />
[/scenario]<br />
<br />
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:<br />
[set_variable]<br />
name=my_variable # here you refer to the variable itself<br />
value=5<br />
[/set_variable]<br />
[message]<br />
speaker=narrator<br />
message= _ "Your variable's value: $my_variable" # will be showed as "Your variable value: 5"<br />
[/message]<br />
<br />
<br />
<!-- ====Conditionals: [if] and [while]====<br />
<br />
<br />
<br />
===Direct Actions===<br />
===Interface Actions===<br />
//--><br />
<br />
== [[GetText]] & Translations ==<br />
[http://www.wesnoth.org/forum/viewtopic.php?t=11445 As Viliam pointed out] (reordered his words):<br />
<br />
Translating programs has two steps. The first step is making [...] scenarios that are<br />
<b>possible</b> to translate; <b>preferably easy</b> to translate. [...] The second <br />
step is the translating of the texts... leave this to translators.<br />
<br />
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.<br />
To make it ever more clear, here's an example:<br />
.<br />
.<br />
.<br />
[message]<br />
speaker=Konrad<br />
message= <b>_</b> "I am mighty Konrad! I fought many dummies and now I will fight you!"<br />
[/message]<br />
.<br />
.<br />
.<br />
<br />
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.<br />
<br />
Viliam also said:<br />
<br />
The most important rule of all is: <b>Do not split sentences.</b><br />
In some languages placing a word in a sentence requires more than mere string concatenation.<br />
Some languages use [http://en.wikipedia.org/wiki/Declension declension].<br />
<br />
== See Also ==<br />
* [[ScenarioWML]], [[SyntaxWML]] & [[ReferenceWML]]<br />
* [[BuildingScenarios]]<br />
<br />
[[Category:Create]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=BuildingScenariosSimple&diff=59981BuildingScenariosSimple2018-10-10T22:06:00Z<p>Namhub: </p>
<hr />
<div>{{BuildingScenariosNav}}<br />
<br />
Here we will show you a very simple scenario file and explain each line of it.<br />
The file is not fully functional, but it will show the basics needed to describe what a scenario is all about.<br />
<br />
'''Before reading this, it might prove useful to read something about the syntax of the Wesnoth Markup Language: [[SyntaxWML]]'''<br />
<br />
== First part ==<br />
<br />
<blockquote><br />
<pre><br />
<nowiki><br />
#textdomain wesnoth-Simple_Campaign<br />
[scenario]<br />
<br />
id=01_test-1<br />
next_scenario=02_test-more<br />
<br />
name= _ "A Simple Test Scenario"<br />
map_data="{~add-ons/Test_Campaign/maps/testmap.map}"<br />
turns=20<br />
<br />
{DAWN}<br />
{MORNING}<br />
{AFTERNOON}<br />
{DUSK}<br />
{FIRST_WATCH}<br />
{SECOND_WATCH}<br />
<br />
music=battle.ogg<br />
<br />
[event]<br />
name=prestart<br />
[objectives]<br />
side=1<br />
[objective]<br />
description= _ "Defeat Enemy Leader"<br />
condition=win<br />
[/objective]<br />
[objective]<br />
description= _ "Death of Konrad"<br />
condition=lose<br />
[/objective]<br />
[objective]<br />
description= _ "Turns run out"<br />
condition=lose<br />
[/objective]<br />
[/objectives]<br />
[/event]<br />
</nowiki><br />
</pre><br />
<br />
''continued below''<br />
<br>&nbsp;&nbsp;&nbsp; <font size=5>↓ ↓ ↓</font><br />
</blockquote> <br />
* <code>#textdomain</code> must be provided at the start of your scenario file if you want it to be translated. Format is <code>#textdomain wesnoth-Name_of_your_campaign</code>, as defined in your _main.cfg file.<br />
<br />
<br />
Every scenario must be enclosed in a tag; the <code>[scenario]</code> tag is used for campaign scenarios. The first set of attributes in the scenario tag describe the very basics of this scenario:<br />
<br />
* <code>id</code> (short for ''identifier'') is the computer's name for your scenario and is not displayed during the game. However, it will be used to display game statistics (they will be graphed at http://stats.wesnoth.org in numerical order, so it's also a good idea to give the <code>id</code>'s a number). This name is also referenced in other tags and files, ''e.g.,'' inside a <code>[campaign]</code> tag using the <code>first_scenario</code> attribute (see [[BuildingCampaignsTheCampaignFile]]) or inside a <code>[scenario]</code> tag using the <code>next_scenario</code> attribute (see below).<br />
<br />
* The value of the <code>next_scenario</code> attribute is the <code>id</code> (see above) of the scenario that is played after this one is won. Units from this scenario will be available for recall (unless you modify the recall list, but that's stuff for later). If your scenario is not part of a campaign, or if this is the last scenario you should either skip this line or put <code>next_scenario=null</code> inside the file. This will tell the game to display the ''End'' screen when this scenario is won.<br />
<br />
* The value of the <code>name</code> attribute is shown on the introduction screen before each scenario is played (this may contain a picture of a map or anything else you fancy. See [[BuildingScenariosIntermediate]] for an explanation on how to do that). It's also used to generate the default names of saved files for the level. The underscore before the name marks it as translatable.<br />
<br />
* The next attribute, <code>map_data</code> is a little tricky. Normally, the map data (the text that is used to generate a map) goes directly inside of the quotation marks. However, it is often useful to keep that map data in a separate file, and then include that file (still inside the quotation marks) using a [[PreprocessorRef|preprocesser]] command. The code <code>{~add-ons/Test_Campaign/maps/testmap.map}</code> does just that, telling the wesnoth engine to look in the file <code>add-ons/Test_Campaign/maps/testmap</code> for the map data. The <code>~</code> symbol tells Wesnoth to search for the map file in the ''userdata'' directory (see [[EditingWesnoth]] and [[PreprocessorRef]] for more information). You can create and edit map files using Wesnoth's built-in map editor (see [[BuildingMaps]] for more information).<br />
<br />
* Finally, the last attribute in the top set of keys is <code>turns</code>. This is the number of turns a player is given to finish the scenario (it can be changed during the game, but again, that is stuff for later). If the player fails to finish the scenario in the given time, he has lost (''i.e.,'' the ''defeat'' event is triggered. See [[EventWML]] for more.)<br />
<br />
The next section is a group of macros which will be processed by Wesnoth's [[PreprocessorRef|preprocesser]]. Macros are essentially [[WML]] shortcuts. They allow you to define certain pieces of code which can be re-used whenever they are needed. Wesnoth provides you with a whole series of standard, pre-written macros to make life easier, but you yourself can write them too (again, stuff for later). <br />
Let's get back to this example! The macros listed above describe how a day in this scenario will progress. The list of macros above is the normal day used throughout Wesnoth. If you want the entire scenario to take place at night, remove all the macros except for <code>{SECOND_WATCH}</code>. Doing this might, for example, be useful if you've set Konrad to fight the Undead and also want the Undead to have the upper hand throughout the scenario. Remember, though, by setting this to a single time of day rather than the normal diurnal progression shown above, your scenario will effectively take place during one day (or night) rather than across many days as most scenarios do.<br />
<br />
The <code>music</code> attribute takes for its value the name of a music file (see [[MusicListWML]] for more). This file must be in the <code>music/</code> directory and <b>must</b> be in [http://en.wikipedia.org/wiki/Ogg Ogg] format.<br />
<br />
A tag you'll get to know very well when making scenarios is <code>[event]...[/event]</code>. <code>event</code> tags are used to describe what should be done when various sorts of ''events'' take place. The specific type of event is stated in the <code>event</code>'s <code>name</code> attribute. In this case we're describing the so-called <code>prestart</code> event. This event occurs just ''after'' all the introduction screens for the scenario have been shown but just ''before'' the map itself is displayed. This prestart event is used to set the scenario's objectives, i.e. the contents of the ''Scenario Objectives Dialog'' that will appear once the scenario begins. The purpose of the Scenario Objectives Dialog is to inform the player what must be accomplished to win the scenario and what circumstances bring about defeat. These winning and losing circumstances are defined using the <code>[objectives]</code> tag (N.B. that <code>objectives</code> is plural). Further, each circumstance is defined in its own <code>[objective]</code> (N.B. the singular here) tag with winning circumstances setting <code>condition</code> to <code>win</code>, and with losing circumstances setting it to <code>lose</code>. In the example above, <code>objectives</code> states victory to be "Defeat Enemy Leader". For defeat, however, <code>[objectives]</code> gives the player ''two'' possibilities: either "Death of Konrad" or "Turns run out" (any number of either winning or losing <code>[objective]</code> tags may be given). Accordingly, the Scenario Objectives Dialog will look vaguely like:<br />
<br />
<table border=1><tr><td><br />
'''<font size=e>A Simple Test Scenario</font>'''<br />
<br>'''Victory:'''<br />
<br><font color=green>Defeat Enemy Leader</font><br />
<br>'''Defeat:'''<br />
<br><font color=red>Death of Konrad<br />
<br>Turns run out</font><br />
<br><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ OK ]<br />
</td></tr></table><br />
<br />
Note that the <code>[objectives]</code> tag doesn't define the circumstances of victory or defeat to the game engine. It merely tells the player what they are. Special victory or defeat conditions will have to be coded into the scenario using various [event]s.<br />
<br />
The <code>side</code> attribute in <code>[objectives]</code> indicates that the conditions defined here by the <code>[objective]</code> tags are for the faction or alliance ''side 1'' alone (see below). In a single-player game, side 1 would usually indicate the player's faction or alliance). The underscore ("_") facilitates translation using [[GetText|Gettext]].<br />
<br />
== Second part ==<br />
So far so good! The last necessary part describes what the players (both human and<br />
computer) start with, what they can do, and what they can't do. Each of the players is described in a <code>[side]</code> tag with the word ''side'' referring to a player's faction, band, or horde.<br />
<br />
<blockquote><br />
&nbsp;&nbsp;&nbsp; <font size=5>↑ ↑ ↑</font><br />
<br>''continued from above''<br />
<pre><br />
<nowiki><br />
[side]<br />
side=1<br />
controller=human<br />
team_name=2<br />
user_team_name= _ "Konrad's forces"<br />
<br />
type=Commander<br />
id=Konrad<br />
name= _ "Konrad"<br />
canrecruit=yes<br />
<br />
recruit=Elvish Fighter,Elvish Archer,Horseman,Mage,Elvish Shaman<br />
<br />
{GOLD 100 50 0}<br />
{INCOME 10 5 0}<br />
[/side] <br />
[/scenario]<br />
</nowiki><br />
</pre><br />
</blockquote><br />
<br />
Above you can see a sample <code>[side]</code> for the human player, Konrad. The first group of attributes in the <code>[side]</code> tag pertains to the side generally:<br />
* <code>side</code>: the leader of this side is placed on the tile represented by this digit (see [[BuildingMaps]]). It's a number from 1 to 9.<br />
* <code>controller</code> takes either of two possible values: <code>human</code> or <code>ai</code> (''i.e.,'' ''artificial intelligence'', meaning your computer). If you don't specify this attribute, <code>ai</code> is the default.<br />
* <code>team_name</code> describes which team the side is on. It defaults to the same number as <code>side</code>, but setting it to <code>2</code> allies this side with side 2 (if you haven't changed the <code>team_name</code> of side 2).<br />
* <code>user_team_name</code> is the name displayed when you view the side stats (by pressing <tt>alt+s</tt> during gameplay). The underscore ("_") facilitates translation using [[GetText|Gettext]].<br />
<br />
The next group of attributes describe the leader of this side:<br />
* <code>canrecruit</code>: This attribute can be set to <code>yes</code> or <code>no</code> (the boolean equivalents <code>1</code> and <code>0</code> or <code>true</code> and <code>false</code> also work). If this is set to <code>no</code>, the leader won't be able to recruit (not much of a leader then, is he?). Any side without a <code>canrecruit=yes</code> attribute statement automatically loses, so be sure to include this attribute.<br />
* <code>type</code> describes what type of unit the leader will be. The possible values are listed in [http://units.wesnoth.org the Wesnoth unit tables].<br />
* <code>id</code> is the identifier of the leader, as used by the engine, and is not visible by the player.<br />
* <code>name</code> is the name of the leader, as visible to the player. The underscore marks it as translatable.<br />
<br />
In a campaign, all of these "leader-describing" attributes are ignored for human players (except <code>canrecruit</code>), since the leader from the previous scenario is carried over into the current one. The exception to this is, of course, the first scenario, because there is no leader from previous scenarios. However, the <code>type</code> attribute is still necessary to prevent the scenario from crashing, so be sure to include it.<br />
<br />
The last attribute, <code>recruit</code>, is a comma-separated list of [http://units.wesnoth.org unit types]. These types will become the side's recruitment list. This too is only necessary in a human player's first scenario, because the recruit list is carried over from one scenario to the next.<br />
<br />
Finally, two macros are called. The first, <code>GOLD</code> takes three positive numbers. These indicate the amount of money the player will start with on the <var>easy</var>, <var>normal</var>, and <var>hard</var> difficulty levels, respectively. For a human-controlled side (<code>controller=human</code>), this specifies only the <i>minimum</i> amount of gold. The actual amount the player starts with can be larger if the player has retained gold from previous scenarios. The second macro, <code>INCOME</code>, is analogous to <code>GOLD</code> but for the base income. The defaults values for <code>GOLD</code> and <code>INCOME</code> are 100 gold and 2 base income, respectively.<br />
<br />
== Making it all work ==<br />
To make this scenario playable, we need to make a campaign for it (see [[BuildingCampaignsTheCampaignFile]]).<br />
This should '''not''' be stored in the main directory <tt>data/campaigns</tt> but rather inside <tt>userdata/data/campaigns</tt>. This prevents the breaking of mainline campaigns or, even worse, the entire game.<br />
Please note that all files (''i.e.'', the campaign file and the scenario files for each level) must be saved with the file extension <tt>.cfg</tt> (''e.g.'', <tt>_main.cfg</tt>).<br />
The following is a short, example campaign file:<br />
<br />
[campaign]<br />
name= _ "Test Campaign"<br />
first_scenario=test-1<br />
define=CAMPAIGN_TEST_CAMPAIGN<br />
difficulties=EASY,NORMAL,HARD<br />
difficulty_descriptions={MENU_IMG_TXT2 "units/elves-wood/fighter.png" _"Fighter" _"(Beginner)"} +<br />
";*" + {MENU_IMG_TXT2 "units/elves-wood/hero.png" _"Hero" _"(Normal)"} +<br />
";" + {MENU_IMG_TXT2 "units/elves-wood/champion.png" _"Champion" _"(Hard)"}<br />
icon="units/elves-wood/hero.png" <br />
[/campaign]<br />
#ifdef CAMPAIGN_TEST_CAMPAIGN<br />
{~add-ons/test_campaign/scenarios}<br />
#endif<br />
<br />
The <code>[campaign]</code> tag describes the campaign. The first attribute, <code>name</code>, is displayed in the campaign selector box during gameplay. The second, <code>first_scenario</code>, is set to the ID number of the first scenario of the campaign. Subsequent scenarios are referenced by the <code>next_scenario</code> attribute of their immediately preceding scenarios (see above in the first part of this tutorial). Since the first scenario, obviously, doesn't have a predecessor, it is referenced here in the <code>campaign</code> tag. To allow wesnoth to actually find the first scenario we need to include the scenarios directory of our campaign. The last statement of the campaign file does that. The inclusion is best guarded by a preprocessor symbol ([[PreprocessorRef]]) that is unique to this campaign so all the scenarios get only included when this campaign is actually selected by the player. The preprocessor symbol for a campaign is given by the <code>define</code> key.<br />
<br />
The attribute <code>difficulties=EASY,NORMAL,HARD</code> tells Wesnoth to use the value <code>EASY</code> if the first difficulty choice is chosen during gameplay, <code>NORMAL</code> if the second is chosen, and <code>HARD</code> if the third is chosen.<br />
The expression <code>#ifdef</code> can be used later to test the value of this attribute (see [[PreprocessorRef]]).<br />
It is recommended that you do not use any names other than <code>EASY</code>, <code>NORMAL</code>, or <code>HARD</code> for your macros because doing so will cause some standard macros, such as <code>{GOLD}</code> and <code>{INCOME}</code>, to not work properly.<br />
<br />
Two optional attributes are <code>difficulty_descriptions</code> and <code>icon</code>.<br />
As its value, <code>icon</code> holds the filename of an image to represent this campaign which will be displayed in the campaign list during gameplay.<br />
<br />
The <code>difficulty_descriptions</code> uses a standard syntax. You provide an image, difficulty name, and a level. Unsurprising, in our example during gameplay <tt>elvish-fighter.png</tt> would display associated with the <i>easy</i> level, <tt>elvish-hero.png</tt> with <i>normal</i>, and <tt>elvish-champion.png</tt> with <i>hard</i>. You can use whatever names you want, and don't need to stick with easy, normal and hard here. You do need to do this in the <code>difficulties</code> section, because many macros are based off this.<br />
<br />
Each list item in <code>difficulty_description</code> begins with the macro <code>MENU_IMG_TEXT2</code> which simplifies the syntax (see [[DescriptionWML]]). This is followed by the filename of the image, then an equal sign ("="), and finally the text to display (<i>i.e.</i>, "Easy". Take note that text displayed for the easy level is not "EASY": the text used is that in <code>difficulty_descriptions</code>, not <code>difficulties</code>. Similary, the normal level's text is "Medium"). <br />
<br />
Optionally you may place an asterisk ("*") before one of list items of <code>difficulty_desciptions</code> which will cause that corresponding difficulty level to be selected as the default during gameplay. In the example above, the normal level (along with its elvish hero) is selected as the default.<br />
<br />
== See Also ==<br />
* [[BuildingMaps]]<br />
* [[ScenarioWML]] & [[SyntaxWML]]<br />
* [[BuildingScenarios]]<br />
<br />
[[Category:Create]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=BuildingScenariosIntermediate&diff=59980BuildingScenariosIntermediate2018-10-10T22:05:42Z<p>Namhub: </p>
<hr />
<div>{{BuildingScenariosNav}}<br />
<br />
In this tutorial we will dig somewhat deeper into the secrets of WML and scenario building: events, explaining the use of some special attributes, setting up somewhat more advanced sides, ...<br />
<br />
== Events ==<br />
You can trigger certain actions that occur during a scenario using the events mechanism. Let us look at an example of a simple event. Suppose you wanted Konrad to say "it's getting cold" when he moves to the location (4,8):<br />
<br />
[event]<br />
name=moveto<br />
[filter]<br />
id=Konrad<br />
x=4<br />
y=8<br />
[/filter]<br />
[message]<br />
speaker=Konrad<br />
message= _ "It's getting cold"<br />
[/message]<br />
[/event]<br />
<br />
First you have the name of the event.<br />
Here, we have a 'moveto' event, meaning it is fired every time a unit moves somewhere.<br />
For a list of the different possible event names, see [[EventWML]]<br />
<br />
Of course, we don't want this to be fired every single time some unit moves somewhere! So, we use the '''[filter]''' tag to filter out what kind of moveto event we want.<br />
How filters are used is described in [[FilterWML]].<br />
<br />
== Special attributes ==<br />
<br />
Note that generally, a set of actions is triggered only once.<br />
You can make a set of actions be triggered every time the event occurs<br />
by adding the attribute '''first_time_only=no''' in the event.<br />
<br />
Also, whenever an event is triggered, the player cannot undo the move, even if it was a moveto event. We could make a scenario where moves cannot be undone by adding the event<br />
<br />
[event]<br />
name=moveto<br />
first_time_only=no<br />
[/event]<br />
<br />
(which would not do anything, but would prevent the player from undoing moves)<br />
<br />
The event:<br />
<br />
[event]<br />
name=enemies defeated<br />
[endlevel]<br />
result=victory<br />
bonus=yes<br />
[/endlevel]<br />
[/event]<br />
<br />
is an implied trigger and appears automatically at the end of each scenario.<br />
To prevent this event, add the attribute '''victory_when_enemies_defeated=no''' inside the main tag (usually [scenario]).<br />
<br />
The attribute '''disallow_recall=yes''' prevents the player from recalling units in this scenario.<br />
<br />
The attributes '''fog=yes''' and '''shroud=yes''' can be put in a '''[side]''' tag to make that side have fog of war/shroud. (Fog of war prevents seeing all enemy movement, shroud prevents seeing all of the map.) <br />
<br />
<br />
== Advanced Sides ==<br />
<br />
Ok, so as you have seen in [[BuildingScenariosSimple]], you can setup what the human player and AI player start with, and some simple options for controlling how the AI works. From the '''[side]''' tag listed below you can see we are going to learn some more interesting things that can be controlled from there. I'm not going to explain all the keys, just the new ones.<br />
<br />
[scenario]<br />
.<br />
.<br />
.<br />
<br />
[side]<br />
type=Lich<br />
id=Galga<br />
side=2<br />
canrecruit=yes<br />
<br />
#ifdef EASY<br />
recruit=Skeleton,Revenant,Blood Bat,Ghost,Bone Shooter<br />
recruitment_pattern=fighter,fighter,archer,scout<br />
gold=300<br />
#endif<br />
<br />
#ifdef NORMAL<br />
recruit=Skeleton,Revenant,Chocobone,Blood Bat,Wraith,Bone Shooter,Dark Adept <br />
recruitment_pattern=fighter,fighter,archer,scout<br />
gold=500<br />
#endif<br />
<br />
#ifdef HARD<br />
recruit=Skeleton,Revenant,Chocobone,Wraith,Bone Shooter,Dark Adept<br />
recruitment_pattern=fighter,fighter,archer,scout<br />
gold=700<br />
#endif<br />
<br />
aggression=1.0<br />
village_value=0.0<br />
leader_value=50.0<br />
enemy=1<br />
[/side]<br />
[/scenario]<br />
<br />
As you can see from the above listing, the '''[side]''' tag can get a little complex. <br />
The '''#ifdef''' is relatively simple to understand. 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 two new keys listed, '''village_value''' and '''leader_value'''.<br />
<br />
<br />
Lets get into some more interesting stuff. The map files hold the ground tiles. This is the very bottom layer of things. The units walking around during a game are on the very top layer. This is all well and good, but wouldn't it be nice to be able to place some unique items on the map? What if you wanted to place a building, or a potion, or anything somewhere in your scenario? Well you can! Using the '''[item]''' tag:<br />
<br />
[scenario]<br />
.<br />
.<br />
.<br />
<br />
[item]<br />
x=31<br />
y=43<br />
image=item-holywater.png <br />
[/item]<br />
<br />
.<br />
.<br />
.<br />
[/scenario]<br />
<br />
The '''[item]''' tag is actually very simple to use, as you can see from above. There are three keys, the first two are '''x''' and '''y'''. They are the location on the map. The third key is '''image'''. This it the image file to place in that location. This image must be located in the images directory. Ok, that was simple wasn't it?<br />
<br />
<br />
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 the intro shown before the scenario is played a bit more descriptive. This is all done from within the '''[story]''' tag.<br />
<br />
[scenario]<br />
.<br />
.<br />
.<br />
<br />
[story]<br />
[part]<br />
background=portraits/elves/transparent/high-lord.png<br />
story= _ "...And so he entered the dark and gloomy cave..."<br />
[/part]<br />
.<br />
.<br />
. <br />
[/story]<br />
.<br />
.<br />
. <br />
[/scenario]<br />
<br />
The story tag contains the story told before the player starts the scenario. You can ommit this, then you will skip the introductionary screens. A story tag exists out of parts (inside [part] tags). Each part can contain several keys describing what content it has got. See [[IntroWML]] for more information.<br />
<br />
== See Also ==<br />
* [[ScenarioWML]] & [[SyntaxWML]]<br />
* [[BuildingScenarios]]<br />
<br />
[[Category:Create]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=WML_for_Complete_Beginners:_Chapter_6&diff=59979WML for Complete Beginners: Chapter 62018-10-10T07:21:43Z<p>Namhub: /* Attacks */</p>
<hr />
<div>==Chapter 6: Building and Including a Custom Unit==<br />
<br />
Sometimes campaign authors only use mainline units in their campaigns. Other times, however, they may want to include a custom unit that isn't found in default Wesnoth. Thankfully, including a custom unit is quite easy.<br />
<br />
===Creating the Unit .cfg File===<br />
<br />
Create a new text file in the "units" folder inside the campaign folder. You could name this "my_first_unit.cfg".<br />
<br />
As usual, start with the textdomain and toplevel tag:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
[/unit_type]<br />
<br />
A somewhat minimal set of initial keys might be:<br />
<br />
id=<br />
name=<br />
image=<br />
movement=<br />
hitpoints=<br />
<br />
"id" and "name" work like usual. "movement" is interesting, because by default a unit will have no movement; quite a boring unit! The same goes for hitpoints; you would have 1 hitpoint if unset.<br />
<br />
Filling these out, you might end up with:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image=<br />
movement=10<br />
hitpoints=10<br />
[/unit_type]<br />
<br />
===Creating Unit Images===<br />
<br />
If you were to spawn this unit now, it would look quite strange, because we have not yet assigned an image. [[Creating Unit Art]] describes how to do this in some detail. When you have a reasonably suitable image, you should save this in <code>add-ons/my_first_campaign/images/units</code>.<br />
<br />
Update your my_first_unit.cfg:<br />
<br />
image="units/my_first_art.png"<br />
<br />
If you don't have a perfectly sized image, you'll notice your unit looks strange in menus and when placed on the map. You can also play with the SCALE and CROP functions to adjust this:<br />
<br />
image="units/my_first_art.png~SCALE_SHARP(72,72)"<br />
<br />
This is described in more detail in [[ImagePathFunctionWML]]<br />
<br />
===Including the Custom Unit in your Campaign===<br />
<br />
You can now add your units to <code>_main.cfg</code>:<br />
<br />
[+units]<br />
{~add-ons/my_first_campaign/units}<br />
[/units]<br />
<br />
You might also want to make this unit recruitable by your human-controlled leader in <code>scenarios/my_first_scenario.cfg</code>:<br />
<br />
recruit="Elvish Fighter, My First Unit"<br />
<br />
Try recruiting your first unit!<br />
<br />
===Attacks===<br />
<br />
You will notice quickly that your unit is not able to attack, because we have not assigned it any attacks. <br />
<br />
[attack]<br />
name=sword<br />
type=blade<br />
range=melee<br />
damage=4<br />
number=1<br />
icon=attacks/dagger-human.png<br />
[/attack]<br />
<br />
This is a simple sword attack, reusing mainline art for the attack icon.<br />
<br />
Your complete unit_type tag should now look like this:<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image="units/my_first_art.png"<br />
movement=10<br />
hitpoints=10 <br />
<br />
[attack]<br />
name=sword<br />
type=blade<br />
range=melee<br />
damage=4<br />
number=1<br />
icon=attacks/sword-human.png<br />
[/attack]<br />
[/unit_type]<br />
<br />
===Further reading===<br />
<br />
* [[UnitTypeWML]] reference for the unit_type tag shown in this article<br />
* [[SingleUnitWML]]<br />
<br />
After reading more about UnitTypeWML, you might try extending your first unit with advancement options and variations.<br />
<br />
===Continue===<br />
<br />
Next Chapter:<br />
[[WML for Complete Beginners: Chapter 7]]<br />
<br />
Previous Chapter:<br />
[[WML for Complete Beginners: Chapter 5]]<br />
<br />
Return to Main Index:<br />
[[WML for Complete Beginners]]<br />
<br />
[[Category:WML_for_Complete_Beginners]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=WML_for_Complete_Beginners:_Chapter_6&diff=59978WML for Complete Beginners: Chapter 62018-10-10T07:18:31Z<p>Namhub: /* Creating Unit Images */</p>
<hr />
<div>==Chapter 6: Building and Including a Custom Unit==<br />
<br />
Sometimes campaign authors only use mainline units in their campaigns. Other times, however, they may want to include a custom unit that isn't found in default Wesnoth. Thankfully, including a custom unit is quite easy.<br />
<br />
===Creating the Unit .cfg File===<br />
<br />
Create a new text file in the "units" folder inside the campaign folder. You could name this "my_first_unit.cfg".<br />
<br />
As usual, start with the textdomain and toplevel tag:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
[/unit_type]<br />
<br />
A somewhat minimal set of initial keys might be:<br />
<br />
id=<br />
name=<br />
image=<br />
movement=<br />
hitpoints=<br />
<br />
"id" and "name" work like usual. "movement" is interesting, because by default a unit will have no movement; quite a boring unit! The same goes for hitpoints; you would have 1 hitpoint if unset.<br />
<br />
Filling these out, you might end up with:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image=<br />
movement=10<br />
hitpoints=10<br />
[/unit_type]<br />
<br />
===Creating Unit Images===<br />
<br />
If you were to spawn this unit now, it would look quite strange, because we have not yet assigned an image. [[Creating Unit Art]] describes how to do this in some detail. When you have a reasonably suitable image, you should save this in <code>add-ons/my_first_campaign/images/units</code>.<br />
<br />
Update your my_first_unit.cfg:<br />
<br />
image="units/my_first_art.png"<br />
<br />
If you don't have a perfectly sized image, you'll notice your unit looks strange in menus and when placed on the map. You can also play with the SCALE and CROP functions to adjust this:<br />
<br />
image="units/my_first_art.png~SCALE_SHARP(72,72)"<br />
<br />
This is described in more detail in [[ImagePathFunctionWML]]<br />
<br />
===Including the Custom Unit in your Campaign===<br />
<br />
You can now add your units to <code>_main.cfg</code>:<br />
<br />
[+units]<br />
{~add-ons/my_first_campaign/units}<br />
[/units]<br />
<br />
You might also want to make this unit recruitable by your human-controlled leader in <code>scenarios/my_first_scenario.cfg</code>:<br />
<br />
recruit="Elvish Fighter, My First Unit"<br />
<br />
Try recruiting your first unit!<br />
<br />
===Attacks===<br />
<br />
You will notice quickly that your unit is not able to attack, because we have not assigned it any attacks. <br />
<br />
[attack]<br />
name=sword<br />
type=blade<br />
range=melee<br />
damage=4<br />
number=1<br />
icon=attacks/dagger-human.png<br />
[/attack]<br />
<br />
This also uses an icon from mainline art.<br />
<br />
Your complete unit file should now look like this:<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image="units/my_first_art.png"<br />
movement=10<br />
hitpoints=10 <br />
<br />
[attack]<br />
name=sword<br />
type=blade<br />
range=melee<br />
damage=4<br />
number=1<br />
icon=attacks/sword-human.png<br />
[/attack]<br />
[/unit_type]<br />
<br />
===Further reading===<br />
<br />
* [[UnitTypeWML]] reference for the unit_type tag shown in this article<br />
* [[SingleUnitWML]]<br />
<br />
After reading more about UnitTypeWML, you might try extending your first unit with advancement options and variations.<br />
<br />
===Continue===<br />
<br />
Next Chapter:<br />
[[WML for Complete Beginners: Chapter 7]]<br />
<br />
Previous Chapter:<br />
[[WML for Complete Beginners: Chapter 5]]<br />
<br />
Return to Main Index:<br />
[[WML for Complete Beginners]]<br />
<br />
[[Category:WML_for_Complete_Beginners]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=WML_for_Complete_Beginners:_Chapter_6&diff=59977WML for Complete Beginners: Chapter 62018-10-10T07:17:17Z<p>Namhub: I love tabs</p>
<hr />
<div>==Chapter 6: Building and Including a Custom Unit==<br />
<br />
Sometimes campaign authors only use mainline units in their campaigns. Other times, however, they may want to include a custom unit that isn't found in default Wesnoth. Thankfully, including a custom unit is quite easy.<br />
<br />
===Creating the Unit .cfg File===<br />
<br />
Create a new text file in the "units" folder inside the campaign folder. You could name this "my_first_unit.cfg".<br />
<br />
As usual, start with the textdomain and toplevel tag:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
[/unit_type]<br />
<br />
A somewhat minimal set of initial keys might be:<br />
<br />
id=<br />
name=<br />
image=<br />
movement=<br />
hitpoints=<br />
<br />
"id" and "name" work like usual. "movement" is interesting, because by default a unit will have no movement; quite a boring unit! The same goes for hitpoints; you would have 1 hitpoint if unset.<br />
<br />
Filling these out, you might end up with:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image=<br />
movement=10<br />
hitpoints=10<br />
[/unit_type]<br />
<br />
===Creating Unit Images===<br />
<br />
If you were to spawn this unit now, it would look quite strange, because we have not yet assigned an image. [[Creating Unit Art]] describes how to do this in some detail. When you have a reasonably suitable image, you should save this in <code>add-ons/my_first_campaign/images/units</code>.<br />
<br />
Update your my_first_unit.cfg:<br />
<br />
image="units/my_first_art.png"<br />
<br />
If you don't have a perfectly sized image, you'll notice your unit looks strange in menus and when placed on the map. You can also play with the SCALE and CROP functions to adjust this:<br />
<br />
image="units/my_first_art~SCALE_SHARP(72,72)"<br />
<br />
This is described in more detail in [[ImagePathFunctionWML]]<br />
<br />
===Including the Custom Unit in your Campaign===<br />
<br />
You can now add your units to <code>_main.cfg</code>:<br />
<br />
[+units]<br />
{~add-ons/my_first_campaign/units}<br />
[/units]<br />
<br />
You might also want to make this unit recruitable by your human-controlled leader in <code>scenarios/my_first_scenario.cfg</code>:<br />
<br />
recruit="Elvish Fighter, My First Unit"<br />
<br />
Try recruiting your first unit!<br />
<br />
===Attacks===<br />
<br />
You will notice quickly that your unit is not able to attack, because we have not assigned it any attacks. <br />
<br />
[attack]<br />
name=sword<br />
type=blade<br />
range=melee<br />
damage=4<br />
number=1<br />
icon=attacks/dagger-human.png<br />
[/attack]<br />
<br />
This also uses an icon from mainline art.<br />
<br />
Your complete unit file should now look like this:<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image="units/my_first_art.png"<br />
movement=10<br />
hitpoints=10 <br />
<br />
[attack]<br />
name=sword<br />
type=blade<br />
range=melee<br />
damage=4<br />
number=1<br />
icon=attacks/sword-human.png<br />
[/attack]<br />
[/unit_type]<br />
<br />
===Further reading===<br />
<br />
* [[UnitTypeWML]] reference for the unit_type tag shown in this article<br />
* [[SingleUnitWML]]<br />
<br />
After reading more about UnitTypeWML, you might try extending your first unit with advancement options and variations.<br />
<br />
===Continue===<br />
<br />
Next Chapter:<br />
[[WML for Complete Beginners: Chapter 7]]<br />
<br />
Previous Chapter:<br />
[[WML for Complete Beginners: Chapter 5]]<br />
<br />
Return to Main Index:<br />
[[WML for Complete Beginners]]<br />
<br />
[[Category:WML_for_Complete_Beginners]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=WML_for_Complete_Beginners:_Chapter_6&diff=59976WML for Complete Beginners: Chapter 62018-10-10T07:15:52Z<p>Namhub: add attack and complete example</p>
<hr />
<div>==Chapter 6: Building and Including a Custom Unit==<br />
<br />
Sometimes campaign authors only use mainline units in their campaigns. Other times, however, they may want to include a custom unit that isn't found in default Wesnoth. Thankfully, including a custom unit is quite easy.<br />
<br />
===Creating the Unit .cfg File===<br />
<br />
Create a new text file in the "units" folder inside the campaign folder. You could name this "my_first_unit.cfg".<br />
<br />
As usual, start with the textdomain and toplevel tag:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
[/unit_type]<br />
<br />
A somewhat minimal set of initial keys might be:<br />
<br />
id=<br />
name=<br />
image=<br />
movement=<br />
hitpoints=<br />
<br />
"id" and "name" work like usual. "movement" is interesting, because by default a unit will have no movement; quite a boring unit! The same goes for hitpoints; you would have 1 hitpoint if unset.<br />
<br />
Filling these out, you might end up with:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image=<br />
movement=10<br />
hitpoints=10<br />
[/unit_type]<br />
<br />
===Creating Unit Images===<br />
<br />
If you were to spawn this unit now, it would look quite strange, because we have not yet assigned an image. [[Creating Unit Art]] describes how to do this in some detail. When you have a reasonably suitable image, you should save this in <code>add-ons/my_first_campaign/images/units</code>.<br />
<br />
Update your my_first_unit.cfg:<br />
<br />
image="units/my_first_art.png"<br />
<br />
If you don't have a perfectly sized image, you'll notice your unit looks strange in menus and when placed on the map. You can also play with the SCALE and CROP functions to adjust this:<br />
<br />
image="units/my_first_art~SCALE_SHARP(72,72)"<br />
<br />
This is described in more detail in [[ImagePathFunctionWML]]<br />
<br />
===Including the Custom Unit in your Campaign===<br />
<br />
You can now add your units to <code>_main.cfg</code>:<br />
<br />
[+units]<br />
{~add-ons/my_first_campaign/units}<br />
[/units]<br />
<br />
You might also want to make this unit recruitable by your human-controlled leader in <code>scenarios/my_first_scenario.cfg</code>:<br />
<br />
recruit="Elvish Fighter, My First Unit"<br />
<br />
Try recruiting your first unit!<br />
<br />
===Attacks===<br />
<br />
You will notice quickly that your unit is not able to attack, because we have not assigned it any attacks. <br />
<br />
[attack]<br />
name=sword<br />
type=blade<br />
range=melee<br />
damage=4<br />
number=1<br />
icon=attacks/dagger-human.png<br />
[/attack]<br />
<br />
Your complete unit file should now look like this:<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image="units/my_first_art.png"<br />
movement=10<br />
hitpoints=10 <br />
<br />
[attack]<br />
name=sword<br />
type=blade<br />
range=melee<br />
damage=4<br />
number=1<br />
icon=attacks/sword-human.png<br />
[/attack]<br />
[/unit_type]<br />
<br />
===Further reading===<br />
<br />
* [[UnitTypeWML]] reference for the unit_type tag shown in this article<br />
* [[SingleUnitWML]]<br />
<br />
After reading more about UnitTypeWML, you might try extending your first unit with advancement options and variations.<br />
<br />
===Continue===<br />
<br />
Next Chapter:<br />
[[WML for Complete Beginners: Chapter 7]]<br />
<br />
Previous Chapter:<br />
[[WML for Complete Beginners: Chapter 5]]<br />
<br />
Return to Main Index:<br />
[[WML for Complete Beginners]]<br />
<br />
[[Category:WML_for_Complete_Beginners]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=WML_for_Complete_Beginners:_Chapter_6&diff=59975WML for Complete Beginners: Chapter 62018-10-10T07:06:52Z<p>Namhub: </p>
<hr />
<div>==Chapter 6: Building and Including a Custom Unit==<br />
<br />
Sometimes campaign authors only use mainline units in their campaigns. Other times, however, they may want to include a custom unit that isn't found in default Wesnoth. Thankfully, including a custom unit is quite easy.<br />
<br />
===Creating the Unit .cfg File===<br />
<br />
Create a new text file in the "units" folder inside the campaign folder. You could name this "my_first_unit.cfg".<br />
<br />
As usual, start with the textdomain and toplevel tag:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
[/unit_type]<br />
<br />
A somewhat minimal set of initial keys might be:<br />
<br />
id=<br />
name=<br />
image=<br />
movement=<br />
hitpoints=<br />
<br />
"id" and "name" work like usual. "movement" is interesting, because by default a unit will have no movement; quite a boring unit! The same goes for hitpoints; you would have 1 hitpoint if unset.<br />
<br />
Filling these out, you might end up with:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image=<br />
movement=10<br />
hitpoints=10<br />
[/unit_type]<br />
<br />
===Creating Unit Images===<br />
<br />
If you were to spawn this unit now, it would look quite strange, because we have not yet assigned an image. [[Creating Unit Art]] describes how to do this in some detail. When you have a reasonably suitable image, you should save this in <code>add-ons/my_first_campaign/images/units</code>.<br />
<br />
Update your my_first_unit.cfg:<br />
<br />
image="units/my_first_art.png"<br />
<br />
If you don't have a perfectly sized image, you'll notice your unit looks strange in menus and when placed on the map. You can also play with the SCALE and CROP functions to adjust this:<br />
<br />
image="units/my_first_art~SCALE_SHARP(72,72)"<br />
<br />
This is described in more detail in [[ImagePathFunctionWML]]<br />
<br />
===Including the Custom Unit in your Campaign===<br />
<br />
You can now add your units to <code>_main.cfg</code>:<br />
<br />
[+units]<br />
{~add-ons/my_first_campaign/units}<br />
[/units]<br />
<br />
You might also want to make this unit recruitable by your human-controlled leader in <code>scenarios/my_first_scenario.cfg</code>:<br />
<br />
recruit="Elvish Fighter, My First Unit"<br />
<br />
===Further reading===<br />
<br />
* [[UnitTypeWML]] reference for the unit_type tag shown in this article<br />
* [[SingleUnitWML]]<br />
<br />
===Continue===<br />
<br />
Next Chapter:<br />
[[WML for Complete Beginners: Chapter 7]]<br />
<br />
Previous Chapter:<br />
[[WML for Complete Beginners: Chapter 5]]<br />
<br />
Return to Main Index:<br />
[[WML for Complete Beginners]]<br />
<br />
[[Category:WML_for_Complete_Beginners]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=WML_for_Complete_Beginners:_Chapter_6&diff=59974WML for Complete Beginners: Chapter 62018-10-10T07:00:07Z<p>Namhub: Talk about how unit images work</p>
<hr />
<div>==Chapter 6: Building and Including a Custom Unit==<br />
<br />
Sometimes campaign authors only use mainline units in their campaigns. Other times, however, they may want to include a custom unit that isn't found in default Wesnoth. Thankfully, including a custom unit is quite easy.<br />
<br />
===Creating the Unit .cfg File===<br />
<br />
Create a new text file in the "units" folder inside the campaign folder. You could name this "my_first_unit.cfg".<br />
<br />
As usual, start with the textdomain and toplevel tag:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
[/unit_type]<br />
<br />
A somewhat minimal set of initial keys might be:<br />
<br />
id=<br />
name=<br />
image=<br />
movement=<br />
hitpoints=<br />
<br />
"id" and "name" work like usual. "movement" is interesting, because by default a unit will have no movement; quite a boring unit! The same goes for hitpoints; you would have 1 hitpoint if unset.<br />
<br />
Filling these out, you might end up with:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image=<br />
movement=10<br />
hitpoints=10<br />
[/unit_type]<br />
<br />
===Creating Unit Images===<br />
<br />
If you were to spawn this unit now, it would look quite strange, because we have not yet assigned an image. [[Creating Unit Art]] describes how to do this in some detail. When you have a reasonably suitable image, you should save this in <code>add-ons/my_first_campaign/images/units</code>.<br />
<br />
Update your my_first_unit.cfg:<br />
<br />
image="units/my_first_art.png"<br />
<br />
If you don't have a perfectly sized image, you'll notice your unit looks strange in menus and when placed on the map. You can also play with the SCALE and CROP functions to adjust this:<br />
<br />
image="units/my_first_art~SCALE_SHARP(72,72)"<br />
<br />
This is described in more detail in [[ImagePathFunctionWML]]<br />
<br />
===Including the Custom Unit in your Campaign===<br />
<br />
[+units]<br />
{~add-ons/my_first_campaign/units}<br />
[/units]<br />
<br />
===Useful Links for adding your own Custom Units===<br />
<br />
<br />
Editing your Custom Units .cfg file: <br><br />
http://wiki.wesnoth.org/UnitTypeWML<br><br />
http://wiki.wesnoth.org/SingleUnitWML <br><br />
<br />
===Continue===<br />
<br />
Next Chapter:<br />
[[WML for Complete Beginners: Chapter 7]]<br />
<br />
Previous Chapter:<br />
[[WML for Complete Beginners: Chapter 5]]<br />
<br />
Return to Main Index:<br />
[[WML for Complete Beginners]]<br />
<br />
[[Category:WML_for_Complete_Beginners]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=WML_for_Complete_Beginners:_Chapter_6&diff=59973WML for Complete Beginners: Chapter 62018-10-10T06:46:33Z<p>Namhub: initial unit_type example</p>
<hr />
<div>==Chapter 6: Building and Including a Custom Unit==<br />
<br />
Sometimes campaign authors only use mainline units in their campaigns. Other times, however, they may want to include a custom unit that isn't found in default Wesnoth. Thankfully, including a custom unit is quite easy.<br />
<br />
===Creating the Unit .cfg File===<br />
<br />
Create a new text file in the "units" folder inside the campaign folder. You could name this "my_first_unit.cfg".<br />
<br />
As usual, start with the textdomain and toplevel tag:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
[/unit_type]<br />
<br />
A somewhat minimal set of initial keys might be:<br />
<br />
id=<br />
name=<br />
image=<br />
movement=<br />
hitpoints=<br />
<br />
"id" and "name" work like usual. "movement" is interesting, because by default a unit will have no movement; quite a boring unit! The same goes for hitpoints; you would have 1 hitpoint if unset.<br />
<br />
Filling these out, you might end up with:<br />
<br />
#textdomain wesnoth-my_first_campaign<br />
<br />
[unit_type]<br />
id=My First Unit<br />
name= _ "My First Unit"<br />
image=<br />
movement=10<br />
hitpoints=10<br />
[/unit_type]<br />
<br />
===Creating your Custom Unit's Images===<br />
<br />
Add the images to my_first_campaign/units<br />
<br />
===Including the Custom Unit in your Campaign===<br />
<br />
[+units]<br />
{~add-ons/my_first_campaign/units}<br />
[/units]<br />
<br />
===Useful Links for adding your own Custom Units===<br />
<br />
<br />
Editing your Custom Units .cfg file: <br><br />
http://wiki.wesnoth.org/UnitTypeWML<br><br />
http://wiki.wesnoth.org/SingleUnitWML <br><br />
<br />
===Continue===<br />
<br />
Next Chapter:<br />
[[WML for Complete Beginners: Chapter 7]]<br />
<br />
Previous Chapter:<br />
[[WML for Complete Beginners: Chapter 5]]<br />
<br />
Return to Main Index:<br />
[[WML for Complete Beginners]]<br />
<br />
[[Category:WML_for_Complete_Beginners]]</div>Namhubhttps://wiki.wesnoth.org/index.php?title=WML_for_Complete_Beginners&diff=59972WML for Complete Beginners2018-10-10T06:23:35Z<p>Namhub: describe all chapters</p>
<hr />
<div>{{Translations}}<br />
<br />
Welcome to the WML Guide for Complete Beginners! From here, you can get started directly by heading to the [[WML for Complete Beginners: Introduction|Introduction]] or you can continue from the chapter you left off. <br />
<br />
==Important Notes:==<br />
This is a work in progress.<br />
Minor edits will not cause the edit to be shown immediately on a page to viewers.<br />
-------------<br />
<br />
TODO:<br />
1. Add to the numbers definition that numbers can include decimal point values (and reference the fact that WML will remove any unnecessary 0's when it performs the calculations or accesses the numerical value in question).<br />
<br />
2. Finish chapters 6-11 (Partially Complete)<br />
<br />
-------------<br />
<br />
==Main Index==<br />
<br />
[[WML_for_Complete_Beginners:_Introduction]]<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_1]] Syntax<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_2]] The Userdata Directory and the Campaign Folder<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_3]] The _main.cfg<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_4]] Creating Your First Scenario<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_5]] Events<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_6]] Custom Units<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_7]] Variables Introduction<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_8]] Non-scalar Variables<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_9]] Macros<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_10]] Logic<br />
<br />
[[WML_for_Complete_Beginners:_Chapter_11]] More Logic<br />
<br />
[[WML_for_Complete_Beginners:_Conclusion]]<br />
<br />
[[Category:WML_for_Complete_Beginners]]</div>Namhub