move most of [endlevel] implementation to lua

as a side effect we get read/write fields
side.carryover_bonus/carryover_add/carryover_percentage in lua sides.
This commit is contained in:
gfgtdf 2015-11-30 02:49:00 +01:00
parent 554547beac
commit 91943451c7
3 changed files with 70 additions and 119 deletions

View file

@ -146,7 +146,7 @@ function wml_actions.allow_recruit(cfg)
wesnoth.add_known_unit(type)
end
team.recruit = v
end
end
end
function wml_actions.allow_extra_recruit(cfg)
@ -1443,6 +1443,7 @@ function wml_actions.end_turn(cfg)
end
function wml_actions.endlevel(cfg)
local parsed = helper.parsed(cfg)
if wesnoth.check_end_level_disabled() then
wesnoth.message("Repeated [endlevel] execution, ignoring")
return
@ -1463,8 +1464,66 @@ function wml_actions.endlevel(cfg)
if end_credits ~= nil then
wesnoth.set_end_campaign_credits(end_credits)
end
local side_results = {}
for result in helper.child_range(parsed, "result") do
local side = result.side or helper.wml_error("[result] in [endlevel] missing required side= key")
side_results[side] = result
end
local there_is_a_human_victory = false
local there_is_a_human_defeat = false
local there_is_a_local_human_victory = false
local there_is_a_local_human_defeat = false
wesnoth.end_level(cfg)
for k,v in ipairs(wesnoth.sides) do
local side_result = side_results[v.side] or {}
local victory_or_defeat = side_result.result or cfg.result or "victory"
local victory = victory_or_defeat == "victory"
if victory_or_defeat ~= "victory" and victory_or_defeat ~= "defeat" then
return helper.wml_error("invalid result= key in [endlevel] '" .. victory_or_defeat .."'")
end
if v.controller == "human" or v.controller == "network" then
if victory then
there_is_a_human_victory = true
else
there_is_a_human_defeat = true
end
end
if v.controller == "human" then
if victory then
there_is_a_local_human_victory = true
else
there_is_a_local_human_defeat = true
end
end
if side_result.bonus ~= nil then
v.carryover_bonus = side_result.bonus
elseif cfg.bonus ~= nil then
v.carryover_bonus = cfg.bonus
end
if side_result.carryover_add ~= nil then
v.carryover_add = side_result.carryover_add
elseif cfg.carryover_add ~= nil then
v.carryover_add = cfg.carryover_add
end
if side_result.carryover_percentage ~= nil then
v.carryover_percentage = side_result.carryover_percentage
elseif cfg.carryover_percentage ~= nil then
v.carryover_percentage = cfg.carryover_percentage
end
end
local proceed_to_next_level = there_is_a_human_victory or (not there_is_a_human_defeat and cfg.result ~= "defeat")
local victory = there_is_a_local_human_victory or (not there_is_a_local_human_defeat and proceed_to_next_level)
wesnoth.end_level {
music = cfg.music,
carryover_report = cfg.carryover_report,
save = cfg.save,
replay_save = cfg.replay_save,
linger_mode = cfg.linger_mode,
reveal_map = cfg.reveal_map,
proceed_to_next_level = proceed_to_next_level,
result = victory and "victory" or "defeat",
}
end
function wml_actions.event(cfg)

View file

@ -1684,28 +1684,7 @@ int game_lua_kernel::intf_clear_messages(lua_State*)
}
return 0;
}
namespace {
struct optional_int_visitor : public boost::static_visitor<boost::optional<int> >
{
template <typename T> result_type operator()(T const &) const
{ return result_type(); }
result_type operator()(int i) const
{ return i; }
result_type operator()(unsigned long long u) const
{ return static_cast<int>(u); }
};
struct optional_bool_visitor : public boost::static_visitor<boost::optional<bool> >
{
template <typename T> result_type operator()(T const &) const
{ return result_type(); }
//Cannot use bool, the case above would catch the yes_no and true_false values.
result_type operator()(const config::attribute_value::yes_no & b) const
{ return static_cast<bool>(b); }
result_type operator()(const config::attribute_value::true_false & b) const
{ return static_cast<bool>(b); }
};
}
int game_lua_kernel::intf_end_level(lua_State *L)
{
vconfig cfg(luaW_checkvconfig(L, 1));
@ -1715,108 +1694,15 @@ int game_lua_kernel::intf_end_level(lua_State *L)
return 0;
}
end_level_data data;
// TODO: is this still needed?
// Remove 0-hp units from the unit map to avoid the following problem:
// In case a die event triggers an endlevel the dead unit is still as a
// 'ghost' in linger mode. After save loading in linger mode the unit
// is fully visible again.
unit_map & um = units();
unit_map::iterator u = um.begin();
while (u) {
if (u->hitpoints() <= 0) {
um.erase(u++);
} else {
++u;
}
}
typedef boost::tuple<bool/*is_victory*/, boost::optional<bool>/*bonus*/, boost::optional<int>/*percentage*/, boost::optional<bool>/*add*/ > t_side_result;
const t_side_result default_result = t_side_result(
cfg["result"] != "defeat",
cfg["bonus"].to_bool(true),
cfg["carryover_percentage"].apply_visitor(optional_int_visitor()),
cfg["carryover_add"].apply_visitor(optional_bool_visitor())
);
std::vector<t_side_result> side_results = std::vector<t_side_result>(board().teams().size(), default_result);
BOOST_FOREACH(const vconfig& side_result, cfg.get_children("result")) {
size_t side = side_result["side"].to_int();
if(side >= side_results.size()) {
return luaL_error(L, "invalid side index %d in [result] in wesnoth.end_level", side);
}
std::string result = side_result["result"];
VALIDATE_WITH_DEV_MESSAGE(
result.empty() || result == "victory" || result == "defeat"
, _("Invalid value in the result key for [end_level]")
, "result = '" + result + "'.");
if(result != "") {
side_results[side].get<0>() = result != "defeat";
}
if(boost::optional<bool> bonus = side_result["bonus"].apply_visitor(optional_bool_visitor())){
side_results[side].get<1>() = bonus;
}
if(boost::optional<int> percentage = side_result["carryover_percentage"].apply_visitor(optional_int_visitor())){
side_results[side].get<2>() = percentage;
}
if(boost::optional<bool> add = side_result["carryover_add"].apply_visitor(optional_bool_visitor())){
side_results[side].get<3>() = add;
}
}
//Find out whether it is victory or defeat:
// If there is a local human side then we have a victory iff one of those sides has a victory
// If there is no local human side but a remote human side then we have a victory iff one of those sides has a victory
// else we use the default_result from ouside [result].
bool any_human_victory = false;
bool local_human_victory = false;
bool there_is_a_remote_human = false;
bool there_is_a_local_human = false;
for(int i = 0; i < static_cast<int>(side_results.size()); ++i) {
team& t = teams()[i];
const t_side_result result = side_results[i];
if(t.is_local_human()) {
there_is_a_local_human = true;
if(result.get<0>()) {
local_human_victory = true;
any_human_victory = true;
}
}
if(t.is_network_human()) {
there_is_a_remote_human = true;
if(result.get<0>()) {
any_human_victory = true;
}
}
if(boost::optional<bool> bonus = result.get<1>()){
t.set_carryover_bonus(bonus.get());
}
if(boost::optional<int> percentage = result.get<2>()){
t.set_carryover_percentage(percentage.get());
}
if(boost::optional<bool> add = result.get<3>()){
t.set_carryover_add(add.get());
}
}
if(!there_is_a_remote_human && !there_is_a_local_human) {
any_human_victory = default_result.get<0>();
}
if(!there_is_a_local_human) {
local_human_victory = any_human_victory;
}
data.proceed_to_next_level = any_human_victory;
data.proceed_to_next_level = cfg["proceed_to_next_level"].to_bool(true);
data.transient.custom_endlevel_music = cfg["music"].str();
data.transient.carryover_report = cfg["carryover_report"].to_bool(true);
data.prescenario_save = cfg["save"].to_bool(true);
data.replay_save = cfg["replay_save"].to_bool(true);
data.transient.linger_mode = cfg["linger_mode"].to_bool(true)
&& !teams().empty();
data.transient.linger_mode = cfg["linger_mode"].to_bool(true) && !teams().empty();
data.transient.reveal_map = cfg["reveal_map"].to_bool(true);
data.is_victory = local_human_victory;
data.is_victory = cfg["result"] == "victory";
play_controller_.set_end_level_data(data);
return 0;
}

View file

@ -74,6 +74,9 @@ static int impl_side_get(lua_State *L)
return_cstring_attrib("controller", t.controller().to_string().c_str());
return_string_attrib("defeat_condition", t.defeat_condition().to_string());
return_string_attrib("share_vision", t.share_vision().to_string());
return_bool_attrib("carryover_bonus", t.carryover_bonus());
return_int_attrib("carryover_percentage", t.carryover_percentage());
return_bool_attrib("carryover_add", t.carryover_add());
return_bool_attrib("lost", t.lost());
if (strcmp(m, "recruit") == 0) {
@ -118,6 +121,9 @@ static int impl_side_set(lua_State *L)
modify_string_attrib("controller", t.change_controller_by_wml(value));
modify_string_attrib("color", t.set_color(value));
modify_string_attrib("defeat_condition", t.set_defeat_condition_string(value));
modify_bool_attrib("carryover_bonus", t.set_carryover_bonus(value));
modify_int_attrib("carryover_percentage", t.set_carryover_percentage(value));
modify_bool_attrib("carryover_add", t.set_carryover_add(value));
modify_bool_attrib("lost", t.set_lost(value));
if (strcmp(m, "recruit") == 0) {