Add a utility function to extract a location from the front of a variadic parameter pack

The purpose of this is to make it easy for functions implemented in Lua to handle locations
in the same way as functions implemented in C++.

The location_set module has been updated to make use of this functionality in its setter functions.

Usage example:

Imagine a function foo with the following signature:

foo(bar : string, home : location, mode : string, target : location, moo : boolean) -> boolean

With the new read_location function it could be implemented as follows:

function foo(...)
	-- First argument goes in bar
	local bar = ...
	-- Read location starting at the second argument
	local home, n = wesnoth.mP.read_location(select(2, ...))
	-- note: n will be 0 if a location wasn't found at that position
	-- This could be an error, or it could be handled as an optional parameter
	-- Next argument after that goes in mode
	local mode = select(n + 2, ...)
	-- Then read a location into target
	local target, m = wesnoth.map.read_location(select(n + 2, ...))
	-- Finally, read a parameter into moo
	local moo = select(m + n + 2, ...)
	-- Do stuff with all these parameters
	return true
end

With that code, all the following invocations of foo work:

foo('a', 'b', true) -- both optional locations omitted
foo('a', 1, 2, 'q', 5, 6, false) -- locations given as separate integer parameters
foo('a', 'm', {1, 7},  true) -- first location omitted, second given as 2-element array
foo('a', some_unit, 'z', {x = 5, y = 10}, false) -- a unit also functions as a location
foo('a', 7, 12, 'q', my_leader, true) -- mixing different forms also works
This commit is contained in:
Celtic Minstrel 2021-02-19 01:08:14 -05:00
parent dacd5b323e
commit 51cf2621f7
2 changed files with 27 additions and 6 deletions

View file

@ -5,6 +5,23 @@ function wesnoth.map.split_terrain_code(code)
return table.unpack(code:split('^', {remove_empty = false}))
end
function wesnoth.map.read_location(...)
local x, y = ...
if y == nil then
if type(x.x) == 'number' and type(x.y) == 'number' then
x, y = x.x, x.y
elseif type(x[1]) == 'number' and type(x[2]) == 'number' then
x, y = table.unpack(x)
else
return nil, 0
end
return {x = x, y = y}, 1
elseif type(x) == 'number' or type(y) == 'number' then
return {x = x, y = y}, 2
end
return nil, 0
end
if wesnoth.kernel_type() ~= "Application Lua Kernel" then
-- possible terrain string inputs:
-- A A^ A^B ^ ^B

View file

@ -84,16 +84,20 @@ function methods:clear()
self.values = {}
end
function methods:get(x, y)
return self.values[index(x, y)]
function methods:get(...)
local loc = wesnoth.map.read_location(...)
return self.values[index(loc.x, loc.y)]
end
function methods:insert(x, y, v)
self.values[index(x, y)] = v or true
function methods:insert(...)
local loc, n = wesnoth.map.read_location(...)
local v = select(n + 1, ...)
self.values[index(loc.x, loc.y)] = v or true
end
function methods:remove(x, y)
self.values[index(x, y)] = nil
function methods:remove(...)
local loc = wesnoth.map.read_location(...)
self.values[index(loc.x, loc.y)] = nil
end
function methods:clone()