LuaWML/Misc

From The Battle for Wesnoth Wiki
< LuaWML
Revision as of 16:10, 13 April 2014 by Gfgtdf (talk | contribs) (wesnoth.synchronize_choice)

This page describes miscellaneous LuaWML objects and helpers.

wesnoth.game_config

Contrarily to the other values of the wesnoth table, game_config is simply a proxy table. Its fields offer an interface to the global settings of Wesnoth:

  • version: string (read only)
  • base_income: integer (read/write)
  • village_income: integer (read/write)
  • poison_amount: integer (read/write)
  • rest_heal_amount: integer (read/write)
  • recall_cost: integer (read/write)
  • kill_experience: integer (read/write)
  • last_turn: integer (read/write) turn limit, maximum number of turns
  • debug: boolean (read only)
  • mp_debug: boolean (read only) Template:DevFeature1.11
  • campaign_type: string (read only) Template:DevFeature1.11 Indicates what type of game this is, e.g. "multiplayer"
  • mp_settings: table Template:DevFeature1.11 In a multiplayer game, this is a proxy table which gives read only access to all MP-only configuration options which appear as attributes of [multiplayer] tag in a save game file:
    • active_mods: string (read only) A list of all active modifications
    • hash: string (read only) A hash of mp data
    • mp_campaign: string (read only) Name of mp campaign
    • mp_scenario: string (read only) ID of this mp scenario
    • mp_scenario_name: string (read only) Name of this mp scenario
    • scenario: string (read only) MP lobby title
    • difficulty_define: string (read only) The campaign difficulty string for an mp campaign
    • mp_village_gold: integer (read only)
    • mp_village_support: integer (read only)
    • mp_num_turns: integer (read only)
    • mp_era: string (read only) The id of the era
    • mp_fog: boolean (read only)
    • mp_shroud: boolean (read only)
    • mp_random_start_time: boolean (read only)
    • experience_modifier: integer (read only)
    • mp_use_map_settings: boolean (read only)
    • mp_countdown: boolean (read only) Whether the timer is enabled
    • mp_countdown_action_bonus: integer (read only)
    • mp_countdown_init_time: integer (read only)
    • mp_countdown_reservoir_time: integer (read only)
    • mp_countdown_turn_bonus: integer (read only)
    • observer: boolean (read only)
    • shuffle_sides: boolean (read only)
    • savegame: boolean (read only) Whether this is a reloaded game
    • side_users: string (read only) List of how sides are assigned to users (at game start)
  • era: table Template:DevFeature1.11 A proxy table for the entire era tag corresponding to the current era. Its id will always match wesnoth.game_config.mp_settings.mp_era

Note: wesnoth.game_config.mp_settings, and wesnoth.game_config.era, will only exist if wesnoth.game_config.campaign_type == "multiplayer"


-- Poison a bit weak? Let's boost it!
wesnoth.game_config.poison_amount = 15
-- Warn users when they use bad settings:
if (wesnoth.game_config.mp_settings.shuffle_sides) then
   wesnoth.message("Warning: This scenario is not intended to be played with shuffle sides!")
end
-- Collect basic info about the current era:
local era = wesnoth.game_config.era
local helper = wesnoth.require("lua/helper.lua")
local count = 0
wesnoth.set_variable("era_name", era.name)
for multiplayer_side in helper.child_range(era, "multiplayer_side") do
    count = count + 1
    wesnoth.set_variable("faction" .. tostring(count) .. "_name", multiplayer_side.name)
    wesnoth.set_variable("faction" .. tostring(count) .. "_recruit", multiplayer_side.recruit)
end
wesnoth.set_variable("num_factions", count)

wesnoth.current

As with game_config, current is a proxy table. Its fields are getter for game-related properties:

  • side: integer (read only)
  • turn: integer (read only)
  • event_context: WML table with attributes name, x1, y1, x2, y2, and children weapon, second_weapon, describing the trigger for the current event.
wesnoth.message(string.format("Turn %d, side %d is playing.", wesnoth.current.turn, wesnoth.current.side))

wesnoth.synchronize_choice

Recovers a WML table that was computed on one client only or was stored in a replay. The actual computation is performed by the function passed as the first argument, assuming that the client is the side currently playing. For all the other clients, the function will not be called. An optional second function can be passed; if present, it will be used instead of the first one when the client happens to be an AI (hence not enable to interact with a user interface).

local result = wesnoth.synchronize_choice(
  function()
    -- Called only on the client handling the current side, if it is a human.
    local choice = 0
    wesnoth.show_dialog(
      some_dialog_cfg, nil,
      function()
        choice = wesnoth.get_dialog_value "some_list"
      end)
    return { value = choice }
  end,
  function()
    -- Called only on the client handling the current side, if it is an AI.
    return { value = math.random(some_list_size) }
  end)
wesnoth.message(string.format("Selected item: %d", result.value))

Note: The return value must be a valid WML table - the same kind of thing you could store to a WML variable, and not, for instance, a proxy unit, anything else that uses metatables, or a lua table with another table as the value of a string attribute. Unlike other lua functions, wesnoth.synchronize_choice will NOT throw an error if the table is invalid, but will silently strip out the contents of any invalid subtag.

Template:DevFeature1.11 In 1.11+dev and future versions, when wesnoth is running in debug mode (e.g. --debug flag on command line) synchronize_choice will now chat a "Lua Warning" if it finds that the table returned was partially invalid.

(Version 1.13.0 and later only) This function now accepts a third (array) argument which allows to decide on which sides the action is executed. If a third argument is passed this function also returns table. If mutiple sides are passed in a mp game, the function wil be executed simultaniously so one side don't have to wait unti the other side decides. Example:

[event]
  name = "start"
  [lua]
  code = <<
    wesnoth.set_variable("input1",nil)
    local result = wesnoth.synchronize_choice(
    function()
      local option1 = T.option { message = "No", T.command { T.set_variable { name = "input1", value = "No"}}}
      local option2 = T.option { message = "Yes", T.command { T.set_variable { name = "input1", value = "Yes"}}}
      wesnoth.fire(T.message{ message =  "Are you sure you want to play this game?", option1, option2})
      return { value = wesnoth.get_variable("input1") }
    end,
    function()
      return { value = math.random(30) }
    end, {1,2})
    wesnoth.set_variable("input1",nil)
    wesnoth.message("Player 1 wants to play: " .. result[1].value)
    wesnoth.message("Player 2 wants to play: " .. result[2].value)
  >>
  [/lua]
[/event]

wesnoth.get_image_size

Returns the width and height of an image.

local w, h = wesnoth.get_image_size "units/transport/galleon.png"

wesnoth.compare_versions

Takes two versions strings and an operator, returns whether the comparison yields true. Follows the same rules like the #ifver preprocessor statement.

local function version_is_sufficient(required)
 if not wesnoth.compare_versions then return false end
 return wesnoth.compare_versions(wesnoth.game_config.version, ">=", required)
end
local required = "1.9.6"
if not version_is_sufficient(required) then wesnoth.message(string.format(
 "Your BfW version is insufficient, please get BfW %s or greater!", required)) end

wesnoth.have_file

Template:DevFeature1.11Checks if the file (not necessarily a Lua file) or the directory passed as argument exists. Returns true if the file exists, false otherwise. Follows the same rules like the #ifhave preprocessor statement.

-- Does the user have installed the UMC Music Book 1?
local umc_music = wesnoth.have_file( "~add-ons/UMC_Music_Book_1/_main.cfg" )
-- and if we want to check for the folder?
local music_folder = wesnoth.have_file( "~add-ons/UMC_Music_Book_1/" )

wesnoth.debug

Takes a userdata with metatable wml object or a wml table and dumps its content into a pretty string.

wesnoth.set_variable("number", 100)
local vconfig = wesnoth.tovconfig({ key = "$number", another_key = true,
    {"a_subtag", { a_key_in_the_subtag = "foo" }}
})
wesnoth.message(wesnoth.debug(vconfig))
wesnoth.message(wesnoth.debug(vconfig.__literal))

wesnoth.get_time_stamp

Template:DevFeature1.11This function retrieves the current time stamp, that is the amount of milliseconds passed from when the SDL library was initialized. It takes no arguments and returns an integer. WARNING: this function uses the same code as [set_variable] time=stamp, and so it is MP-unsafe. It is provided only for benchmark purposes and AI development, although it should work inside wesnoth.synchronize_choice() as well.

local stamp = wesnoth.get_time_stamp()

helper.set_wml_tag_metatable

Sets the metable of a table so that it can be used to create subtags with less brackets. Returns the table. The fields of the table are simple wrappers around table constructors.

T = helper.set_wml_tag_metatable {}
W.event { name = "new turn", T.message { speaker = "narrator", message = "?" } }

helper.modify_unit

Modifies all the units satisfying the given filter (argument 1) with some WML attributes/objects (argument 2). This is a Lua implementation of the MODIFY_UNIT macro.

helper.modify_unit({ id="Delfador" }, { moves=0 })

helper.move_unit_fake

Fakes the move of a unit satisfying the given filter (argument 1) to the given position (argument 2). This is a Lua implementation of the MOVE_UNIT macro.

helper.move_unit_fake({ id="Delfador" }, 14, 8)

helper.rand

(A shortcut to set_variable's rand= since math.rand is an OOS magnet and therefore disabled.) Pass a string like you would to set_variable's rand=.

create a random unit at (1, 1) on side=1 :

wesnoth.put_unit(1, 1, { type = helper.rand("Dwarvish Fighter,Dwarvish Thunderer,Dwarvish Scout") })

helper.round

Template:DevFeature1.11Unlike other languages (Python, Perl, Javascript, ...), Lua does not include a round function. This helper function allows rounding numbers, following the "round half away from zero method", see Wikipedia [[1]]. Returns the number rounded to the nearest integer.

-- this number will be rounded up
helper.round(345.67) -- returns 346
-- this one will be rounded down
helper.round(543.21) -- returns 543
-- an integer stays integer
helper.round(123) -- returns 123
-- works also for negative numbers
helper.round(-369.84) -- returns -370
helper.round(-246.42) -- returns -246

helper.shuffle

Template:DevFeature1.11This function randomly sorts in place the elements of the table passed as argument, following the Fisher-Yates algorithm. It returns no value. WARNING: this function uses Lua's math.random(), and so it is MP-unsafe. It is provided mainly for AI development, although it should work inside wesnoth.synchronize_choice() as well.

local locs = wesnoth.get_locations( { terrain="G*" } )
helper.shuffle( locs )