wesnoth/data/lua/wml/endlevel.lua
Pentarctagon 9a0b95f9a0 Separate unit test results from scenario victory/defeat.
This adds an additional `test_result` attribute to [endlevel], intended for use with the automated unit tests. This allows for the unit tests to differentiate a pass/fail result separately from scenario victory or defeat, which allows for more accurately determining the outcome of a test as well as addresses the potential, for example, for a scenario to be expect to pass because of the {SUCCEED} macro but instead passes because the scenario ended as a victory through some other method.

Additional unit tests which were the original motivation for this change are also added as part of this.  They test, as much as possible, that events are executed at all, and are then also executed in the expected order.
2020-04-07 16:45:34 -05:00

106 lines
3.1 KiB
Lua

local already_ended = false
function wesnoth.wml_actions.endlevel(cfg)
local parsed = wml.parsed(cfg)
if already_ended then
wesnoth.message("Repeated [endlevel] execution, ignoring")
return
end
already_ended = true
local next_scenario = cfg.next_scenario
if next_scenario then
wesnoth.game_config.next_scenario = next_scenario
end
local end_text = cfg.end_text
local end_text_duration = cfg.end_text_duration
if end_text or end_text_duration then
wesnoth.set_end_campaign_text(end_text or "", end_text_duration)
end
local end_credits = cfg.end_credits
if end_credits ~= nil then
wesnoth.set_end_campaign_credits(end_credits)
end
local side_results = {}
for result in wml.child_range(parsed, "result") do
local side = result.side or 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
local bool_num = function(b)
if b == true then
return 1
elseif b == false then
return 0
else
return b
end
end
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 wml.error("invalid result= key in [endlevel] '" .. victory_or_defeat .."'")
end
if v.controller == "human" then
if victory then
there_is_a_human_victory = true
else
there_is_a_human_defeat = true
end
end
if v.controller == "human" and v.is_local 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 = bool_num(side_result.bonus)
elseif cfg.bonus ~= nil then
v.carryover_bonus = bool_num(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)
if cfg.music then
local music = cfg.music:split()
if victory then
wesnoth.game_config.victory_music = music
else
wesnoth.game_config.defeat_music = music
end
end
wesnoth.end_level {
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",
test_result = cfg.test_result,
}
end