From bda3cf231e178643cf8578f64114d10a2b19a5d9 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Fri, 19 Feb 2021 01:08:14 -0500 Subject: [PATCH] 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 --- data/lua/core/map.lua | 17 +++++++++++++++++ data/lua/location_set.lua | 14 +++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/data/lua/core/map.lua b/data/lua/core/map.lua index 34333516f122..2879956e51a7 100644 --- a/data/lua/core/map.lua +++ b/data/lua/core/map.lua @@ -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 diff --git a/data/lua/location_set.lua b/data/lua/location_set.lua index a9b61f180a51..6e90010358fd 100644 --- a/data/lua/location_set.lua +++ b/data/lua/location_set.lua @@ -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 + local loc = wesnoth.map.read_location(...) + self.values[index(loc.x, loc.y)] = nil end function methods:clone()