> See https://gna.org/patch/index.php?1120 for a proof of concept.
>
> This patch implements a [lua] tag that he can used as an event action.

It now works well enough, so that I have convinced myself this
approach is sensible. As a consequence, once I have tackled all the
items on my TODO list and once the 1.7 branch opens, I would like to
push the patch. Any suggestions or objections?

Best regards,

Guillaume

The C++ wrapper provides five functions for Lua scripts to use. More
could be added, but it currently seems sufficient to achieve
everything WML can perfom inside WML event handlers.

*** Interface:

1. void fire(string handler, table data?, int x1?, int y1?, int x2?, int y2?)

Executes a WML handler with optionally some config and some locations.

Example:

   function narrator_says(m)
       wesnoth.fire("message", { speaker="narrator", message=m })
   end

   narrator_says("I'm alive!")

2. any get_variable(string name)
3. void set_variable(string name, any value)

Reads and writes Lua expressions into game variables. (These variables
are persistent and available to WML code.) Converts from/to the proper
Lua types, e.g. boolean <-> "yes"/"no".

Note that WML allows several nested tags with the same name, so Lua
tables are a bit convoluted as they have to contain an indirection.
Consider the WML object
   [object]b="42" [a](A1)[/a] [b](B)[/b] [a](A2)[/a][/object].
It cannot be converted to the following erroneous Lua table
   { b = 42, a = (A1'), b??? = (B'), a??? = (A2') },
so it is converted to
   { b = 42, { "a", (A1') }, { "b", (B') }, { "a", (A2') } }.

Example:

   local t = wesnoth.get_variable("stored_unit")
   t[#t + 1] = { "modifications", { [1] = loyal_trait() } }
   wesnoth.set_variable("stored_unit", t)

The syntax is a bit verbose, so it can be improved on the Lua side if needed:

   variables = setmetatable({},
       { __index    = function(i)   wesnoth.get_variable(i)   end,
         __newindex = function(i,v) wesnoth.set_variable(i,v) end })

   local next_turn = variables["turn_number"] + 1
   variables["sidekick_died"] = true

4. abstr textdomain(string)

Returns a thing with a __call metamethod that performs a translation.

Example:

   local _ = wesnoth.textdomain("wesnoth-utbs")
   narrator_says(_("The water of the lake suddenly goes dark and [...]"))

5. table get_units(table filter?)

Returns a table containing proxies to units on the map. (Strictly
speaking, this function can be implemented with the functions above.
But this won't be that easy once there are Lua filters, since firing
an action while filtering things may lead to interesting results...)

Example:

   local units = get_units({ side=1 })
   local count = 0
   for index,unit in pairs(units) do
       if unit.name == string.reverse(unit.name) then count = count + 1 end
   end
   narrator_says(string.format("%d units on side 1 have palindromic
names", count))


*** Known issues:

1. Translations are not lazy yet. If you switch language after
creating an object with Lua, the sentences contained in the object
will keep the old translation. For instance, if a Lua script creates a
unit with the name _("William") while playing in French and if you
later switch to German, the unit will still be called "Guillaume"
instead of automagically switching to the "Wilhelm" name.

2. Recall lists are not yet visible from the get_units interface. They
can be accessed through their WML storage though, but that's a bit
cumbersome.


*** TODO list:

1. Fix known issues above.

2. Either allow [lua] tags at the global scope or create a "onload"
event, so that scenarios can preload some functions/variables in the
Lua environment. Among other things, it will make it possible to write
helper libraries.

3. Allow [lua] tags inside filters.

4. Add other query functions like get_units.

_______________________________________________
Wesnoth-dev mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-dev

Reply via email to