home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 July / maximum-cd-2010-07.iso / DiscContents / wesnoth-1.8-win32.exe / data / lua / helper.lua next >
Encoding:
Text File  |  2010-03-25  |  7.5 KB  |  275 lines

  1. --! #textdomain wesnoth
  2.  
  3. local helper = {}
  4.  
  5. --! Interrupts the current execution and displays a chat message that looks like a WML error.
  6. function helper.wml_error(m)
  7.     error("~wml:" .. m, 0)
  8. end
  9.  
  10. --! Returns an iterator over teams that can be used in a for-in loop.
  11. function helper.all_teams()
  12.     local function f(s)
  13.         local i = s.i
  14.         local team = wesnoth.get_side(i)
  15.         s.i = i + 1
  16.         return team
  17.     end
  18.     return f, { i = 1 }
  19. end
  20.  
  21. --! Returns the first subtag of @a cfg with the given @a name.
  22. --! If @a id is not nil, the "id" attribute of the subtag has to match too.
  23. --! The function also returns the index of the subtag in the array.
  24. function helper.get_child(cfg, name, id)
  25.     -- ipairs cannot be used on a vconfig object
  26.     for i = 1, #cfg do
  27.         local v = cfg[i]
  28.         if v[1] == name then
  29.             local w = v[2]
  30.             if not id or w.id == id then return w, i end
  31.         end
  32.     end
  33. end
  34.  
  35. --! Returns an iterator over all the subtags of @a cfg with the given @a name.
  36. function helper.child_range(cfg, tag)
  37.     local function f(s)
  38.         local c
  39.         repeat
  40.             local i = s.i
  41.             c = cfg[i]
  42.             if not c then return end
  43.             s.i = i + 1
  44.         until c[1] == tag
  45.         return c[2]
  46.     end
  47.     return f, { i = 1 }
  48. end
  49.  
  50. --! Modifies all the units satisfying the given @a filter.
  51. --! @param vars key/value pairs that need changing.
  52. --! @note Usable only during WML actions.
  53. function helper.modify_unit(filter, vars)
  54.     wesnoth.fire("store_unit", {
  55.         [1] = { "filter", filter },
  56.         variable = "LUA_modify_unit",
  57.         kill = true
  58.     })
  59.     for i = 0, wesnoth.get_variable("LUA_modify_unit.length") - 1 do
  60.         local u = "LUA_modify_unit[" .. i .. "]"
  61.         for k, v in pairs(vars) do
  62.             wesnoth.set_variable(u .. '.' .. k, v)
  63.         end
  64.         wesnoth.fire("unstore_unit", {
  65.             variable = u,
  66.             find_vacant = false
  67.         })
  68.     end
  69.     wesnoth.set_variable("LUA_modify_unit")
  70. end
  71.  
  72. --! Fakes the move of a unit satisfying the given @a filter to position @a x, @a y.
  73. --! @note Usable only during WML actions.
  74. function helper.move_unit_fake(filter, to_x, to_y)
  75.     wesnoth.fire("store_unit", {
  76.         [1] = { "filter", filter },
  77.         variable = "LUA_move_unit",
  78.         kill = false
  79.     })
  80.     local from_x = wesnoth.get_variable("LUA_move_unit.x")
  81.     local from_y = wesnoth.get_variable("LUA_move_unit.y")
  82.  
  83.     wesnoth.fire("scroll_to", { x=from_x, y=from_y })
  84.  
  85.     if to_x < from_x then
  86.         wesnoth.set_variable("LUA_move_unit.facing", "sw")
  87.     elseif to_x > from_x then
  88.         wesnoth.set_variable("LUA_move_unit.facing", "se")
  89.     end
  90.     wesnoth.set_variable("LUA_move_unit.x", to_x)
  91.     wesnoth.set_variable("LUA_move_unit.y", to_y)
  92.  
  93.     wesnoth.fire("kill", {
  94.         x = from_x,
  95.         y = from_y,
  96.         animate = false,
  97.         fire_event = false
  98.     })
  99.  
  100.     wesnoth.fire("move_unit_fake", {
  101.         type      = "$LUA_move_unit.type",
  102.         gender    = "$LUA_move_unit.gender",
  103.         variation = "$LUA_move_unit.variation",
  104.         side      = "$LUA_move_unit.side",
  105.         x         = from_x .. ',' .. to_x,
  106.         y         = from_y .. ',' .. to_y
  107.     })
  108.  
  109.     wesnoth.fire("unstore_unit", { variable="LUA_move_unit", find_vacant=true })
  110.     wesnoth.fire("redraw")
  111.     wesnoth.set_variable("LUA_move_unit")
  112. end
  113.  
  114. local variable_mt = {}
  115.  
  116. local function get_variable_proxy(k)
  117.     local v = wesnoth.get_variable(k, true)
  118.     if type(v) == "table" then
  119.         v = setmetatable({ __varname = k }, variable_mt)
  120.     end
  121.     return v
  122. end
  123.  
  124. local function set_variable_proxy(k, v)
  125.     if getmetatable(v) == variable_mt then
  126.         v = wesnoth.get_variable(v.__varname)
  127.     end
  128.     wesnoth.set_variable(k, v)
  129. end
  130.  
  131. function variable_mt.__index(t, k)
  132.     local i = tonumber(k)
  133.     if i then
  134.         k = t.__varname .. '[' .. i .. ']'
  135.     else
  136.         k = t.__varname .. '.' .. k
  137.     end
  138.     return get_variable_proxy(k)
  139. end
  140.  
  141. function variable_mt.__newindex(t, k, v)
  142.     local i = tonumber(k)
  143.     if i then
  144.         k = t.__varname .. '[' .. i .. ']'
  145.     else
  146.         k = t.__varname .. '.' .. k
  147.     end
  148.     set_variable_proxy(k, v)
  149. end
  150.  
  151. local root_variable_mt = {
  152.     __index    = function(t, k)    return get_variable_proxy(k)    end,
  153.     __newindex = function(t, k, v)
  154.         if type(v) == "function" then
  155.             -- User-friendliness when _G is overloaded early.
  156.             -- FIXME: It should be disabled outside the "preload" event.
  157.             rawset(t, k, v)
  158.         else
  159.             set_variable_proxy(k, v)
  160.         end
  161.     end
  162. }
  163.  
  164. --! Sets the metable of @a t so that it can be used to access WML variables.
  165. --! @return @a t.
  166. --! @code
  167. --! helper.set_wml_var_metatable(_G)
  168. --! my_persistent_variable = 42
  169. --! @endcode
  170. function helper.set_wml_var_metatable(t)
  171.     return setmetatable(t, root_variable_mt)
  172. end
  173.  
  174. local fire_action_mt = {
  175.     __index = function(t, n)
  176.         return function(cfg) wesnoth.fire(n, cfg) end
  177.     end
  178. }
  179.  
  180. --! Sets the metable of @a t so that it can be used to fire WML actions.
  181. --! @return @a t.
  182. --! @code
  183. --! W = helper.set_wml_action_metatable {}
  184. --! W.message { speaker = "narrator", message = "?" }
  185. --! @endcode
  186. function helper.set_wml_action_metatable(t)
  187.     return setmetatable(t, fire_action_mt)
  188. end
  189.  
  190. local create_tag_mt = {
  191.     __index = function(t, n)
  192.         return function(cfg) return { n, cfg } end
  193.     end
  194. }
  195.  
  196. --! Sets the metable of @a t so that it can be used to create subtags with less brackets.
  197. --! @return @a t.
  198. --! @code
  199. --! T = helper.set_wml_tag_metatable {}
  200. --! W.event { name = "new turn", T.message { speaker = "narrator", message = "?" } }
  201. --! @endcode
  202. function helper.set_wml_tag_metatable(t)
  203.     return setmetatable(t, create_tag_mt)
  204. end
  205.  
  206. --! Fetches all the WML container variables with name @a var.
  207. --! @returns a table containing all the variables (starting at index 1).
  208. function helper.get_variable_array(var)
  209.     local result = {}
  210.     for i = 1, wesnoth.get_variable(var .. ".length") do
  211.         result[i] = wesnoth.get_variable(string.format("%s[%d]", var, i - 1))
  212.     end
  213.     return result
  214. end
  215.  
  216. --! Puts all the elements of table @a t inside a WML container with name @a var.
  217. function helper.set_variable_array(var, t)
  218.     wesnoth.set_variable(var)
  219.     for i, v in ipairs(t) do
  220.         wesnoth.set_variable(string.format("%s[%d]", var, i - 1), v)
  221.     end
  222. end
  223.  
  224. --! Creates proxies for all the WML container variables with name @a var.
  225. --! This is similar to helper.get_variable_array, except that the elements
  226. --! can be used for writing too.
  227. --! @returns a table containing all the variable proxies (starting at index 1).
  228. function helper.get_variable_proxy_array(var)
  229.     local result = {}
  230.     for i = 1, wesnoth.get_variable(var .. ".length") do
  231.         result[i] = get_variable_proxy(string.format("%s[%d]", var, i - 1))
  232.     end
  233.     return result
  234. end
  235.  
  236. --! Displays a WML message box with attributes from table @attr and options
  237. --! from table @options.
  238. --! @return the index of the selected option.
  239. --! @code
  240. --! local result = helper.get_user_choice({ speaker = "narrator" },
  241. --!     { "Choice 1", "Choice 2" })
  242. --! @endcode
  243. function helper.get_user_choice(attr, options)
  244.     local result = 0
  245.     function wesnoth.__user_choice_helper(i)
  246.         result = i
  247.     end
  248.     local msg = {}
  249.     for k,v in pairs(attr) do
  250.         msg[k] = attr[k]
  251.     end
  252.     for k,v in ipairs(options) do
  253.         table.insert(msg, { "option", { message = v,
  254.             { "command", { { "lua", {
  255.                 code = string.format("wesnoth.__user_choice_helper(%d)", k)
  256.             }}}}}})
  257.     end
  258.     wesnoth.fire("message", msg)
  259.     wesnoth.__user_choice_helper = nil
  260.     return result
  261. end
  262.  
  263. --! Returns the distance between two tiles given by their WML coordinates.
  264. function helper.distance_between(x1, y1, x2, y2)
  265.     local function is_even(v) return v % 2 == 0 end
  266.     local hdist = math.abs(x1 - x2)
  267.     local vdist = math.abs(y1 - y2)
  268.     if (y1 < y2 and not is_even(x1) and is_even(x2)) or
  269.        (y2 < y1 and not is_even(x2) and is_even(x1))
  270.     then vdist = vdist + 1 end
  271.     return math.max(hdist, vdist + math.floor(hdist / 2))
  272. end
  273.  
  274. return helper
  275.