From 91943451c7320c308d5b53638bb438e778a165f7 Mon Sep 17 00:00:00 2001 From: gfgtdf Date: Mon, 30 Nov 2015 02:49:00 +0100 Subject: [PATCH] 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. --- data/lua/wml-tags.lua | 63 +++++++++++++++- src/scripting/game_lua_kernel.cpp | 120 +----------------------------- src/scripting/lua_team.cpp | 6 ++ 3 files changed, 70 insertions(+), 119 deletions(-) diff --git a/data/lua/wml-tags.lua b/data/lua/wml-tags.lua index 57de9cfcbe1..b61ccbfa244 100644 --- a/data/lua/wml-tags.lua +++ b/data/lua/wml-tags.lua @@ -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) diff --git a/src/scripting/game_lua_kernel.cpp b/src/scripting/game_lua_kernel.cpp index ab792d499be..c7c362409da 100644 --- a/src/scripting/game_lua_kernel.cpp +++ b/src/scripting/game_lua_kernel.cpp @@ -1684,28 +1684,7 @@ int game_lua_kernel::intf_clear_messages(lua_State*) } return 0; } -namespace { - struct optional_int_visitor : public boost::static_visitor > - { - template 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(u); } - }; - struct optional_bool_visitor : public boost::static_visitor > - { - template 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(b); } - result_type operator()(const config::attribute_value::true_false & b) const - { return static_cast(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/*bonus*/, boost::optional/*percentage*/, boost::optional/*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 side_results = std::vector(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 bonus = side_result["bonus"].apply_visitor(optional_bool_visitor())){ - side_results[side].get<1>() = bonus; - } - if(boost::optional percentage = side_result["carryover_percentage"].apply_visitor(optional_int_visitor())){ - side_results[side].get<2>() = percentage; - } - if(boost::optional 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(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 bonus = result.get<1>()){ - t.set_carryover_bonus(bonus.get()); - } - if(boost::optional percentage = result.get<2>()){ - t.set_carryover_percentage(percentage.get()); - } - if(boost::optional 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; } diff --git a/src/scripting/lua_team.cpp b/src/scripting/lua_team.cpp index 96e8b351b23..2608731b19f 100644 --- a/src/scripting/lua_team.cpp +++ b/src/scripting/lua_team.cpp @@ -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) {