Moved [role] to Lua

This fixes indirectly bug #23630
This commit is contained in:
Elvish_Hunter 2015-06-10 22:36:08 +02:00
parent 1b239aa3e6
commit 787bd1b9c5
2 changed files with 44 additions and 70 deletions

View file

@ -1460,3 +1460,47 @@ end
function wml_actions.print(cfg)
wesnoth.print(cfg)
end
function wml_actions.role(cfg)
-- role= and type= are handled differently than in other tags,
-- so we need to remove them from the filter
local role = cfg.role
local filter = cfg.__shallow_literal
filter.role, filter.type = nil, nil
local types = {}
for value in split(cfg.type) do
table.insert(types, value)
end
-- first attempt to match units on the map
local i = 1
repeat
-- give precedence based on the order specified in type=
if #types > 0 then
filter.type = types[i]
end
local unit = wesnoth.get_units(filter)[1]
if unit then
unit.role = cfg.role
return
end
i = i + 1
until #types == 0 or i > #types
-- then try to match units on the recall lists
i = 1
repeat
if #types > 0 then
filter.type = types[i]
end
local unit = wesnoth.get_recall_units(filter)[1]
if unit then
unit.role = cfg.role
return
end
i = i + 1
until #types == 0 or i > #types
-- no matching unit found, fail silently
end

View file

@ -1021,76 +1021,6 @@ WML_HANDLER_FUNCTION(reset_fog, /*event_info*/, cfg)
toggle_fog(false, cfg, cfg["reset_view"].to_bool(false));
}
WML_HANDLER_FUNCTION(role, /*event_info*/, cfg)
{
bool found = false;
// role= represents the instruction, so we can't filter on it
config item = cfg.get_config();
item.remove_attribute("role");
vconfig filter(item);
// try to match units on the gamemap before the recall lists
std::vector<std::string> types = utils::split(filter["type"]);
const bool has_any_types = !types.empty();
std::vector<std::string>::iterator ti = types.begin(),
ti_end = types.end();
// loop to give precedence based on type order
const unit_filter ufilt(filter, resources::filter_con);
do {
if (has_any_types) {
item["type"] = *ti;
}
BOOST_FOREACH(unit &u, *resources::units) {
if ( ufilt(u) ) {
u.set_role(cfg["role"]);
found = true;
break;
}
}
} while(!found && has_any_types && ++ti != ti_end);
if(!found) {
// next try to match units on the recall lists
std::set<std::string> player_ids;
std::vector<std::string> sides = utils::split(cfg["side"]);
const bool has_any_sides = !sides.empty();
BOOST_FOREACH(std::string const& side_str, sides) {
size_t side_num = lexical_cast_default<size_t>(side_str,0);
if(side_num > 0 && side_num <= resources::teams->size()) {
player_ids.insert((resources::teams->begin() + (side_num - 1))->save_id());
}
}
// loop to give precedence based on type order
std::vector<std::string>::iterator ti = types.begin();
const unit_filter ufilt(filter, resources::filter_con);
do {
if (has_any_types) {
item["type"] = *ti;
}
std::vector<team>::iterator pi,
pi_end = resources::teams->end();
for (pi = resources::teams->begin(); pi != pi_end; ++pi)
{
std::string const& player_id = pi->save_id();
// Verify the filter's side= includes this player
if(has_any_sides && !player_ids.count(player_id)) {
continue;
}
// Iterate over the player's recall list to find a match
for(size_t i=0; i < pi->recall_list().size(); ++i) {
unit_ptr u = pi->recall_list()[i];
scoped_recall_unit auto_store("this_unit", player_id, i); //TODO: Should this not be inside the if? Explain me.
if (ufilt( *u, map_location() )) {
u->set_role(cfg["role"]);
found=true;
break;
}
}
}
} while(!found && has_any_types && ++ti != ti_end);
}
}
/// Experimental data persistence
/// @todo Finish experimenting.
WML_HANDLER_FUNCTION(set_global_variable,/**/,pcfg)