Support [set/clear_variable] inside [modify_unit/side]
This commit is contained in:
parent
6371f0497c
commit
f6b6854c8d
5 changed files with 145 additions and 45 deletions
|
@ -105,11 +105,12 @@ function wml_actions.store_gold(cfg)
|
||||||
if team then wml.variables[cfg.variable or "gold"] = team.gold end
|
if team then wml.variables[cfg.variable or "gold"] = team.gold end
|
||||||
end
|
end
|
||||||
|
|
||||||
function wml_actions.clear_variable(cfg)
|
function wml_actions.clear_variable(cfg, variables)
|
||||||
local names = cfg.name or
|
local names = cfg.name or
|
||||||
helper.wml_error "[clear_variable] missing required name= attribute."
|
helper.wml_error "[clear_variable] missing required name= attribute."
|
||||||
|
if variables == nil then variables = wml.variables end
|
||||||
for w in utils.split(names) do
|
for w in utils.split(names) do
|
||||||
wml.variables[utils.trim(w)] = nil
|
variables[utils.trim(w)] = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -91,16 +91,24 @@ function wesnoth.wml_actions.modify_side(cfg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local ai, replace_ai = {}, false
|
||||||
|
for k, v in ipairs(cfg) do
|
||||||
|
local tag, content = v[1], v[2]
|
||||||
|
if tag == "ai" then
|
||||||
|
table.insert(ai, T.ai(content))
|
||||||
|
if content.ai_algorithm then
|
||||||
|
replace_ai = true
|
||||||
|
end
|
||||||
|
elseif tag == "set_variable" then
|
||||||
|
wesnoth.wml_actions.set_variable(v[2], side.variables)
|
||||||
|
elseif tag == "clear_variable" then
|
||||||
|
wesnoth.wml_actions.clear_variable(cfg, side.variables)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if cfg.switch_ai then
|
if cfg.switch_ai then
|
||||||
wesnoth.switch_ai(side.side, cfg.switch_ai)
|
wesnoth.switch_ai(side.side, cfg.switch_ai)
|
||||||
end
|
end
|
||||||
local ai, replace_ai = {}, false
|
|
||||||
for next_ai in wml.child_range(cfg, "ai") do
|
|
||||||
table.insert(ai, T.ai(next_ai))
|
|
||||||
if next_ai.ai_algorithm then
|
|
||||||
replace_ai = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #ai > 0 then
|
if #ai > 0 then
|
||||||
if replace_ai then
|
if replace_ai then
|
||||||
wesnoth.switch_ai(side.side, ai)
|
wesnoth.switch_ai(side.side, ai)
|
||||||
|
|
|
@ -55,6 +55,9 @@ local known_tags = make_set {
|
||||||
"trait",
|
"trait",
|
||||||
"filter",
|
"filter",
|
||||||
"status",
|
"status",
|
||||||
|
"set_variable",
|
||||||
|
-- todo: "set_variables",
|
||||||
|
"clear_variable",
|
||||||
}
|
}
|
||||||
|
|
||||||
local function is_simple(cfg)
|
local function is_simple(cfg)
|
||||||
|
@ -137,11 +140,14 @@ local function simple_modify_unit(cfg)
|
||||||
tagcontent = wml.parsed(tagcontent)
|
tagcontent = wml.parsed(tagcontent)
|
||||||
end
|
end
|
||||||
u:add_modification(tagname, tagcontent);
|
u:add_modification(tagname, tagcontent);
|
||||||
end
|
elseif tagname == "status" then
|
||||||
if tagname == "status" then
|
|
||||||
for i, v in pairs(tagcontent) do
|
for i, v in pairs(tagcontent) do
|
||||||
u.status[i] = v
|
u.status[i] = v
|
||||||
end
|
end
|
||||||
|
elseif tagname == "set_variable" then
|
||||||
|
wesnoth.wml_actions.set_variable(tagcontent, u.variables)
|
||||||
|
elseif tagname == "clear_variable" then
|
||||||
|
wesnoth.wml_actions.clear_variable(tagcontent, u.variables)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -233,6 +239,14 @@ function wml_actions.modify_unit(cfg)
|
||||||
else
|
else
|
||||||
helper.wml_error("[modify_unit] had invalid [effect]apply_to value")
|
helper.wml_error("[modify_unit] had invalid [effect]apply_to value")
|
||||||
end
|
end
|
||||||
|
elseif current_tag == "set_variable" then
|
||||||
|
local unit = wesnoth.create_unit(wml.variables[unit_path])
|
||||||
|
wesnoth.wml_actions.set_variable(current_table[2], unit.variables)
|
||||||
|
wml.variables[unit_path] = unit.__cfg
|
||||||
|
elseif current_tag == "clear_variable" then
|
||||||
|
local unit = wesnoth.create_unit(wml.variables[unit_path])
|
||||||
|
wesnoth.wml_actions.clear_variable(current_table[2], unit.variables)
|
||||||
|
wml.variables[unit_path] = unit.__cfg
|
||||||
else
|
else
|
||||||
if replace_mode then
|
if replace_mode then
|
||||||
wml.variables[string.format("%s.%s", unit_path, current_tag)] = {}
|
wml.variables[string.format("%s.%s", unit_path, current_tag)] = {}
|
||||||
|
|
|
@ -1,54 +1,55 @@
|
||||||
local helper = wesnoth.require "helper"
|
local helper = wesnoth.require "helper"
|
||||||
|
|
||||||
function wesnoth.wml_actions.set_variable(cfg)
|
function wesnoth.wml_actions.set_variable(cfg, variables)
|
||||||
local name = cfg.name or helper.wml_error "trying to set a variable with an empty name"
|
local name = cfg.name or wml.error "trying to set a variable with an empty name"
|
||||||
|
if variables == nil then variables = wml.variables end
|
||||||
|
|
||||||
if cfg.value ~= nil then -- check for nil because user may try to set a variable as false
|
if cfg.value ~= nil then -- check for nil because user may try to set a variable as false
|
||||||
wml.variables[name] = cfg.value
|
variables[name] = cfg.value
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.literal ~= nil then
|
if cfg.literal ~= nil then
|
||||||
wml.variables[name] = wml.shallow_literal(cfg).literal
|
variables[name] = wml.shallow_literal(cfg).literal
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.to_variable then
|
if cfg.to_variable then
|
||||||
wml.variables[name] = wml.variables[cfg.to_variable]
|
variables[name] = variables[cfg.to_variable]
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.suffix then
|
if cfg.suffix then
|
||||||
wml.variables[name] = (wml.variables[name] or '') .. (cfg.suffix or '')
|
variables[name] = (variables[name] or '') .. (cfg.suffix or '')
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.prefix then
|
if cfg.prefix then
|
||||||
wml.variables[name] = (cfg.prefix or '') .. (wml.variables[name] or '')
|
variables[name] = (cfg.prefix or '') .. (variables[name] or '')
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.add then
|
if cfg.add then
|
||||||
wml.variables[name] = (tonumber(wml.variables[name]) or 0) + (tonumber(cfg.add) or 0)
|
variables[name] = (tonumber(variables[name]) or 0) + (tonumber(cfg.add) or 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.sub then
|
if cfg.sub then
|
||||||
wml.variables[name] = (tonumber(wml.variables[name]) or 0) - (tonumber(cfg.sub) or 0)
|
variables[name] = (tonumber(variables[name]) or 0) - (tonumber(cfg.sub) or 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.multiply then
|
if cfg.multiply then
|
||||||
wml.variables[name] = (tonumber(wml.variables[name]) or 0) * (tonumber(cfg.multiply) or 0)
|
variables[name] = (tonumber(variables[name]) or 0) * (tonumber(cfg.multiply) or 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.divide then
|
if cfg.divide then
|
||||||
local divide = tonumber(cfg.divide) or 0
|
local divide = tonumber(cfg.divide) or 0
|
||||||
if divide == 0 then helper.wml_error("division by zero on variable " .. name) end
|
if divide == 0 then wml.error("division by zero on variable " .. name) end
|
||||||
wml.variables[name] = (tonumber(wml.variables[name]) or 0) / divide
|
variables[name] = (tonumber(variables[name]) or 0) / divide
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.modulo then
|
if cfg.modulo then
|
||||||
local modulo = tonumber(cfg.modulo) or 0
|
local modulo = tonumber(cfg.modulo) or 0
|
||||||
if modulo == 0 then helper.wml_error("division by zero on variable " .. name) end
|
if modulo == 0 then wml.error("division by zero on variable " .. name) end
|
||||||
wml.variables[name] = (tonumber(wml.variables[name]) or 0) % modulo
|
variables[name] = (tonumber(variables[name]) or 0) % modulo
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.abs then
|
if cfg.abs then
|
||||||
wml.variables[name] = math.abs(tonumber(wml.variables[name]) or 0)
|
variables[name] = math.abs(tonumber(variables[name]) or 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.root then
|
if cfg.root then
|
||||||
|
@ -64,40 +65,40 @@ function wesnoth.wml_actions.set_variable(cfg)
|
||||||
root_fcn = function(n) return n ^ (1 / root) end
|
root_fcn = function(n) return n ^ (1 / root) end
|
||||||
end
|
end
|
||||||
|
|
||||||
local radicand = tonumber(wml.variables[name]) or 0
|
local radicand = tonumber(variables[name]) or 0
|
||||||
if radicand < 0 and root % 2 == 0 then
|
if radicand < 0 and root % 2 == 0 then
|
||||||
if root == 2 then
|
if root == 2 then
|
||||||
helper.wml_error("square root of negative number on variable " .. name)
|
wml.error("square root of negative number on variable " .. name)
|
||||||
else
|
else
|
||||||
helper.wml_error(string.format("%dth root of negative number on variable %s", root, name))
|
wml.error(string.format("%dth root of negative number on variable %s", root, name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
wml.variables[name] = root_fcn(radicand)
|
variables[name] = root_fcn(radicand)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.power then
|
if cfg.power then
|
||||||
wml.variables[name] = (tonumber(wml.variables[name]) or 0) ^ (tonumber(cfg.power) or 0)
|
variables[name] = (tonumber(variables[name]) or 0) ^ (tonumber(cfg.power) or 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.round then
|
if cfg.round then
|
||||||
local var = tonumber(wml.variables[name] or 0)
|
local var = tonumber(variables[name] or 0)
|
||||||
local round_val = cfg.round
|
local round_val = cfg.round
|
||||||
if round_val == "ceil" then
|
if round_val == "ceil" then
|
||||||
wml.variables[name] = math.ceil(var)
|
variables[name] = math.ceil(var)
|
||||||
elseif round_val == "floor" then
|
elseif round_val == "floor" then
|
||||||
wml.variables[name] = math.floor(var)
|
variables[name] = math.floor(var)
|
||||||
elseif round_val == "trunc" then
|
elseif round_val == "trunc" then
|
||||||
-- Storing to a variable first because modf returns two values,
|
-- Storing to a variable first because modf returns two values,
|
||||||
-- and I'm not sure if set_variable will complain about the extra parameter
|
-- and I'm not sure if set_variable will complain about the extra parameter
|
||||||
local new_val = math.modf(var)
|
local new_val = math.modf(var)
|
||||||
wml.variables[name] = new_val
|
variables[name] = new_val
|
||||||
else
|
else
|
||||||
local decimals = math.modf(tonumber(round_val) or 0)
|
local decimals = math.modf(tonumber(round_val) or 0)
|
||||||
local value = var * (10 ^ decimals)
|
local value = var * (10 ^ decimals)
|
||||||
value = helper.round(value)
|
value = helper.round(value)
|
||||||
value = value * (10 ^ -decimals)
|
value = value * (10 ^ -decimals)
|
||||||
wml.variables[name] = value
|
variables[name] = value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -106,36 +107,36 @@ function wesnoth.wml_actions.set_variable(cfg)
|
||||||
-- but on the value assigned to the respective key
|
-- but on the value assigned to the respective key
|
||||||
if cfg.ipart then
|
if cfg.ipart then
|
||||||
local ivalue = math.modf(tonumber(cfg.ipart) or 0)
|
local ivalue = math.modf(tonumber(cfg.ipart) or 0)
|
||||||
wml.variables[name] = ivalue
|
variables[name] = ivalue
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.fpart then
|
if cfg.fpart then
|
||||||
local ivalue, fvalue = math.modf(tonumber(cfg.fpart) or 0)
|
local ivalue, fvalue = math.modf(tonumber(cfg.fpart) or 0)
|
||||||
wml.variables[name] = fvalue
|
variables[name] = fvalue
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.string_length ~= nil then
|
if cfg.string_length ~= nil then
|
||||||
wml.variables[name] = string.len(tostring(cfg.string_length))
|
variables[name] = string.len(tostring(cfg.string_length))
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.time then
|
if cfg.time then
|
||||||
if cfg.time == "stamp" then
|
if cfg.time == "stamp" then
|
||||||
wml.variables[name] = wesnoth.get_time_stamp()
|
variables[name] = wesnoth.get_time_stamp()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.rand then
|
if cfg.rand then
|
||||||
wml.variables[name] = helper.rand(tostring(cfg.rand))
|
variables[name] = helper.rand(tostring(cfg.rand))
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfg.formula then
|
if cfg.formula then
|
||||||
local fcn = wesnoth.compile_formula(cfg.formula)
|
local fcn = wesnoth.compile_formula(cfg.formula)
|
||||||
wml.variables[name] = fcn(wml.variables[name])
|
variables[name] = fcn(variables[name])
|
||||||
end
|
end
|
||||||
|
|
||||||
local join_child = wml.get_child(cfg, "join")
|
local join_child = wml.get_child(cfg, "join")
|
||||||
if join_child then
|
if join_child then
|
||||||
local array_name = join_child.variable or helper.wml_error "missing variable= attribute in [join]"
|
local array_name = join_child.variable or wml.error "missing variable= attribute in [join]"
|
||||||
local separator = join_child.separator
|
local separator = join_child.separator
|
||||||
local key_name = join_child.key or "value"
|
local key_name = join_child.key or "value"
|
||||||
local remove_empty = join_child.remove_empty
|
local remove_empty = join_child.remove_empty
|
||||||
|
@ -151,6 +152,6 @@ function wesnoth.wml_actions.set_variable(cfg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
wml.variables[name] = string_to_join
|
variables[name] = string_to_join
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
// Registry key
|
// Registry key
|
||||||
static const char * Team = "side";
|
static const char * Team = "side";
|
||||||
|
static const char teamVar[] = "side variables";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets some data on a side (__index metamethod).
|
* Gets some data on a side (__index metamethod).
|
||||||
|
@ -102,6 +103,13 @@ static int impl_side_get(lua_State *L)
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if(strcmp(m, "variables") == 0) {
|
||||||
|
lua_createtable(L, 1, 0);
|
||||||
|
lua_pushvalue(L, 1);
|
||||||
|
lua_rawseti(L, -2, 1);
|
||||||
|
luaL_setmetatable(L, teamVar);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// These are blocked together because they are all part of the team_data struct.
|
// These are blocked together because they are all part of the team_data struct.
|
||||||
// Some of these values involve iterating over the units map to calculate them.
|
// Some of these values involve iterating over the units map to calculate them.
|
||||||
|
@ -212,10 +220,67 @@ static int impl_side_equal(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the variable of a side (__index metamethod).
|
||||||
|
* - Arg 1: table containing the userdata containing the side id.
|
||||||
|
* - Arg 2: string containing the name of the status.
|
||||||
|
* - Ret 1: boolean.
|
||||||
|
*/
|
||||||
|
static int impl_side_variables_get(lua_State *L)
|
||||||
|
{
|
||||||
|
if(!lua_istable(L, 1)) {
|
||||||
|
return luaW_type_error(L, 1, "side variables");
|
||||||
|
}
|
||||||
|
lua_rawgeti(L, 1, 1);
|
||||||
|
const team& side = luaW_checkteam(L, -1);
|
||||||
|
|
||||||
|
char const *m = luaL_checkstring(L, 2);
|
||||||
|
return_cfgref_attrib("__cfg", side.variables());
|
||||||
|
|
||||||
|
variable_access_const v(m, side.variables());
|
||||||
|
return luaW_pushvariable(L, v) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the variable of a side (__newindex metamethod).
|
||||||
|
* - Arg 1: table containing the userdata containing the side id.
|
||||||
|
* - Arg 2: string containing the name of the status.
|
||||||
|
* - Arg 3: scalar.
|
||||||
|
*/
|
||||||
|
static int impl_side_variables_set(lua_State *L)
|
||||||
|
{
|
||||||
|
if(!lua_istable(L, 1)) {
|
||||||
|
return luaW_type_error(L, 1, "side variables");
|
||||||
|
}
|
||||||
|
lua_rawgeti(L, 1, 1);
|
||||||
|
team& side = luaW_checkteam(L, -1);
|
||||||
|
|
||||||
|
char const *m = luaL_checkstring(L, 2);
|
||||||
|
if(strcmp(m, "__cfg") == 0) {
|
||||||
|
side.variables() = luaW_checkconfig(L, 3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
config& vars = side.variables();
|
||||||
|
if(lua_isnoneornil(L, 3)) {
|
||||||
|
try {
|
||||||
|
variable_access_throw(m, vars).clear(false);
|
||||||
|
} catch(const invalid_variablename_exception&) {
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
variable_access_create v(m, vars);
|
||||||
|
luaW_checkvariable(L, v, 3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
namespace lua_team {
|
namespace lua_team {
|
||||||
|
|
||||||
std::string register_metatable(lua_State * L)
|
std::string register_metatable(lua_State * L)
|
||||||
{
|
{
|
||||||
|
std::ostringstream cmd_out;
|
||||||
|
|
||||||
|
cmd_out << "Adding getside metatable...\n";
|
||||||
|
|
||||||
luaL_newmetatable(L, Team);
|
luaL_newmetatable(L, Team);
|
||||||
|
|
||||||
static luaL_Reg const callbacks[] {
|
static luaL_Reg const callbacks[] {
|
||||||
|
@ -232,7 +297,18 @@ namespace lua_team {
|
||||||
luaW_getglobal(L, "wesnoth", "match_side");
|
luaW_getglobal(L, "wesnoth", "match_side");
|
||||||
lua_setfield(L, -2, "matches");
|
lua_setfield(L, -2, "matches");
|
||||||
|
|
||||||
return "Adding getside metatable...\n";
|
// Create the side variables metatable.
|
||||||
|
cmd_out << "Adding side variables metatable...\n";
|
||||||
|
|
||||||
|
luaL_newmetatable(L, teamVar);
|
||||||
|
lua_pushcfunction(L, impl_side_variables_get);
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
|
lua_pushcfunction(L, impl_side_variables_set);
|
||||||
|
lua_setfield(L, -2, "__newindex");
|
||||||
|
lua_pushstring(L, "side variables");
|
||||||
|
lua_setfield(L, -2, "__metatable");
|
||||||
|
|
||||||
|
return cmd_out.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue