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
|
||||
end
|
||||
|
||||
function wml_actions.clear_variable(cfg)
|
||||
function wml_actions.clear_variable(cfg, variables)
|
||||
local names = cfg.name or
|
||||
helper.wml_error "[clear_variable] missing required name= attribute."
|
||||
if variables == nil then variables = wml.variables end
|
||||
for w in utils.split(names) do
|
||||
wml.variables[utils.trim(w)] = nil
|
||||
variables[utils.trim(w)] = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -91,16 +91,24 @@ function wesnoth.wml_actions.modify_side(cfg)
|
|||
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
|
||||
wesnoth.switch_ai(side.side, cfg.switch_ai)
|
||||
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 replace_ai then
|
||||
wesnoth.switch_ai(side.side, ai)
|
||||
|
|
|
@ -55,6 +55,9 @@ local known_tags = make_set {
|
|||
"trait",
|
||||
"filter",
|
||||
"status",
|
||||
"set_variable",
|
||||
-- todo: "set_variables",
|
||||
"clear_variable",
|
||||
}
|
||||
|
||||
local function is_simple(cfg)
|
||||
|
@ -137,11 +140,14 @@ local function simple_modify_unit(cfg)
|
|||
tagcontent = wml.parsed(tagcontent)
|
||||
end
|
||||
u:add_modification(tagname, tagcontent);
|
||||
end
|
||||
if tagname == "status" then
|
||||
elseif tagname == "status" then
|
||||
for i, v in pairs(tagcontent) do
|
||||
u.status[i] = v
|
||||
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
|
||||
|
||||
|
@ -233,6 +239,14 @@ function wml_actions.modify_unit(cfg)
|
|||
else
|
||||
helper.wml_error("[modify_unit] had invalid [effect]apply_to value")
|
||||
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
|
||||
if replace_mode then
|
||||
wml.variables[string.format("%s.%s", unit_path, current_tag)] = {}
|
||||
|
|
|
@ -1,54 +1,55 @@
|
|||
local helper = wesnoth.require "helper"
|
||||
|
||||
function wesnoth.wml_actions.set_variable(cfg)
|
||||
local name = cfg.name or helper.wml_error "trying to set a variable with an empty name"
|
||||
function wesnoth.wml_actions.set_variable(cfg, variables)
|
||||
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
|
||||
wml.variables[name] = cfg.value
|
||||
variables[name] = cfg.value
|
||||
end
|
||||
|
||||
if cfg.literal ~= nil then
|
||||
wml.variables[name] = wml.shallow_literal(cfg).literal
|
||||
variables[name] = wml.shallow_literal(cfg).literal
|
||||
end
|
||||
|
||||
if cfg.to_variable then
|
||||
wml.variables[name] = wml.variables[cfg.to_variable]
|
||||
variables[name] = variables[cfg.to_variable]
|
||||
end
|
||||
|
||||
if cfg.suffix then
|
||||
wml.variables[name] = (wml.variables[name] or '') .. (cfg.suffix or '')
|
||||
variables[name] = (variables[name] or '') .. (cfg.suffix or '')
|
||||
end
|
||||
|
||||
if cfg.prefix then
|
||||
wml.variables[name] = (cfg.prefix or '') .. (wml.variables[name] or '')
|
||||
variables[name] = (cfg.prefix or '') .. (variables[name] or '')
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
if cfg.divide then
|
||||
local divide = tonumber(cfg.divide) or 0
|
||||
if divide == 0 then helper.wml_error("division by zero on variable " .. name) end
|
||||
wml.variables[name] = (tonumber(wml.variables[name]) or 0) / divide
|
||||
if divide == 0 then wml.error("division by zero on variable " .. name) end
|
||||
variables[name] = (tonumber(variables[name]) or 0) / divide
|
||||
end
|
||||
|
||||
if cfg.modulo then
|
||||
local modulo = tonumber(cfg.modulo) or 0
|
||||
if modulo == 0 then helper.wml_error("division by zero on variable " .. name) end
|
||||
wml.variables[name] = (tonumber(wml.variables[name]) or 0) % modulo
|
||||
if modulo == 0 then wml.error("division by zero on variable " .. name) end
|
||||
variables[name] = (tonumber(variables[name]) or 0) % modulo
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
if cfg.root then
|
||||
|
@ -64,40 +65,40 @@ function wesnoth.wml_actions.set_variable(cfg)
|
|||
root_fcn = function(n) return n ^ (1 / root) 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 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
|
||||
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
|
||||
|
||||
wml.variables[name] = root_fcn(radicand)
|
||||
variables[name] = root_fcn(radicand)
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
if cfg.round then
|
||||
local var = tonumber(wml.variables[name] or 0)
|
||||
local var = tonumber(variables[name] or 0)
|
||||
local round_val = cfg.round
|
||||
if round_val == "ceil" then
|
||||
wml.variables[name] = math.ceil(var)
|
||||
variables[name] = math.ceil(var)
|
||||
elseif round_val == "floor" then
|
||||
wml.variables[name] = math.floor(var)
|
||||
variables[name] = math.floor(var)
|
||||
elseif round_val == "trunc" then
|
||||
-- Storing to a variable first because modf returns two values,
|
||||
-- and I'm not sure if set_variable will complain about the extra parameter
|
||||
local new_val = math.modf(var)
|
||||
wml.variables[name] = new_val
|
||||
variables[name] = new_val
|
||||
else
|
||||
local decimals = math.modf(tonumber(round_val) or 0)
|
||||
local value = var * (10 ^ decimals)
|
||||
value = helper.round(value)
|
||||
value = value * (10 ^ -decimals)
|
||||
wml.variables[name] = value
|
||||
variables[name] = value
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -106,36 +107,36 @@ function wesnoth.wml_actions.set_variable(cfg)
|
|||
-- but on the value assigned to the respective key
|
||||
if cfg.ipart then
|
||||
local ivalue = math.modf(tonumber(cfg.ipart) or 0)
|
||||
wml.variables[name] = ivalue
|
||||
variables[name] = ivalue
|
||||
end
|
||||
|
||||
if cfg.fpart then
|
||||
local ivalue, fvalue = math.modf(tonumber(cfg.fpart) or 0)
|
||||
wml.variables[name] = fvalue
|
||||
variables[name] = fvalue
|
||||
end
|
||||
|
||||
if cfg.string_length ~= nil then
|
||||
wml.variables[name] = string.len(tostring(cfg.string_length))
|
||||
variables[name] = string.len(tostring(cfg.string_length))
|
||||
end
|
||||
|
||||
if cfg.time then
|
||||
if cfg.time == "stamp" then
|
||||
wml.variables[name] = wesnoth.get_time_stamp()
|
||||
variables[name] = wesnoth.get_time_stamp()
|
||||
end
|
||||
end
|
||||
|
||||
if cfg.rand then
|
||||
wml.variables[name] = helper.rand(tostring(cfg.rand))
|
||||
variables[name] = helper.rand(tostring(cfg.rand))
|
||||
end
|
||||
|
||||
if cfg.formula then
|
||||
local fcn = wesnoth.compile_formula(cfg.formula)
|
||||
wml.variables[name] = fcn(wml.variables[name])
|
||||
variables[name] = fcn(variables[name])
|
||||
end
|
||||
|
||||
local join_child = wml.get_child(cfg, "join")
|
||||
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 key_name = join_child.key or "value"
|
||||
local remove_empty = join_child.remove_empty
|
||||
|
@ -151,6 +152,6 @@ function wesnoth.wml_actions.set_variable(cfg)
|
|||
end
|
||||
end
|
||||
|
||||
wml.variables[name] = string_to_join
|
||||
variables[name] = string_to_join
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
// Registry key
|
||||
static const char * Team = "side";
|
||||
static const char teamVar[] = "side variables";
|
||||
|
||||
/**
|
||||
* Gets some data on a side (__index metamethod).
|
||||
|
@ -102,6 +103,13 @@ static int impl_side_get(lua_State *L)
|
|||
}
|
||||
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.
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
std::string register_metatable(lua_State * L)
|
||||
{
|
||||
std::ostringstream cmd_out;
|
||||
|
||||
cmd_out << "Adding getside metatable...\n";
|
||||
|
||||
luaL_newmetatable(L, Team);
|
||||
|
||||
static luaL_Reg const callbacks[] {
|
||||
|
@ -232,7 +297,18 @@ namespace lua_team {
|
|||
luaW_getglobal(L, "wesnoth", "match_side");
|
||||
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