move the carryover gold handling and dialog to lua

The idea is to make it easier for umc devs to implement
their own carryover / early finish bonus mechanics. Maybe
we can also make use of it in Worls Conquest.
This commit is contained in:
gfgtdf 2023-05-08 15:17:06 +02:00
parent 893b31e769
commit f29f8fb368
9 changed files with 148 additions and 195 deletions

View file

@ -9,6 +9,7 @@ wesnoth.dofile 'lua/wml-tags.lua'
wesnoth.dofile 'lua/feeding.lua'
wesnoth.dofile 'lua/diversion.lua'
wesnoth.dofile 'lua/stun.lua'
wesnoth.dofile 'lua/carryover_gold.lua'
>>
[/lua]

147
data/lua/carryover_gold.lua Normal file
View file

@ -0,0 +1,147 @@
local _ = wesnoth.textdomain "wesnoth"
local function get_is_observer()
for _, side in ipairs(wesnoth.sides) do
if side.controller == "human" and side.is_local then
return false
end
end
return true
end
local function get_num_persistent_teams()
local res = 0
for _, side in ipairs(wesnoth.sides) do
if side.persistent then
res = res + 1
end
end
return res
end
local function get_num_villages()
return #(wesnoth.map.find{ gives_income = true })
end
local function half_signed_value(num)
return tostring(num)
end
local function get_popup_text_basic()
local is_observer = get_is_observer()
local is_victory = wesnoth.scenario.end_level_data.is_victory
local report = ""
local title = ""
if is_observer then
title = _("Scenario Report")
elseif is_victory then
title = _("Victory")
report = report .. "<b>" .. _("You have emerged victorious!") .. "</b>"
else
title = _("Defeat")
report = report .. _("You have been defeated!")
end
return title, report
end
local function do_carryover_gold()
local endlevel_data = wesnoth.scenario.end_level_data
local has_next_scenario = wesnoth.scenario.next ~= "" and wesnoth.scenario.next ~= "null" and endlevel_data.proceed_to_next_level
local is_victory = endlevel_data.is_victory
local is_observer = get_is_observer()
local is_replay = wesnoth.current.iser_is_replaying
local show_report = endlevel_data.carryover_report and (not is_observer) and (not is_replay)
local num_villages = get_num_villages()
local turns_left = math.max(0, wesnoth.scenario.turns - wesnoth.current.turn)
local num_persistent_teams = get_num_persistent_teams()
local title, report = get_popup_text_basic()
if has_next_scenario then
for __, side in ipairs(wesnoth.sides) do
if (not side.persistent) or side.lost then
goto continue
end
local finishing_bonus_per_turn = num_villages * side.village_gold + side.base_income
local finishing_bonus = side.carryover_bonus * finishing_bonus_per_turn * turns_left
side.carryover_gold = math.ceil((side.gold + finishing_bonus) * side.carryover_percentage / 100)
local is_human = side.controller == "human"
if (not side.is_local) or (not is_human) then
goto continue
end
if num_persistent_teams > 1 then
report = report .. "\n\n<b>" .. side.side_name .. "</b>"
end
report = report .. "<small>\n" .. _("Remaining gold: ") .. half_signed_value(side.gold) .. "</small>"
if side.carryover_bonus ~= 0 then
if turns_left > -1 then
report = report .. "\n\n<b>" ..
_("Turns finished early: ") .. turns_left .. "</b>\n" .. "<small>" ..
_("Early finish bonus: ") .. finishing_bonus_per_turn .. _(" per turn") .. "</small>\n" .. "<small>" ..
_("Total bonus: ") .. finishing_bonus .. "</small>\n"
end
report = report .. "<small>" .. _("Total gold: ") .. half_signed_value(side.gold + finishing_bonus) .. "</small>"
end
if side.gold > 0 then
report = report .. "\n<small>" .. _("Carryover percentage: ") .. side.carryover_percentage .. "</small>"
end
if side.carryover_add then
report = report .. "\n\n<big><b>" .. _("Bonus gold: ") .. half_signed_value(side.carryover_gold) .. "</b></big>"
else
report = report .. "\n\n<big><b>" .. _("Retained gold: ") .. half_signed_value(side.carryover_gold) .. "</b></big>"
end
local goldmsg = ""
-- Note that both strings are the same in English, but some languages will
-- want to translate them differently.
if side.carryover_add then
if side.carryover_gold > 0 then
goldmsg = _("You will start the next scenario with $gold on top of the defined minimum starting gold.",
"You will start the next scenario with $gold on top of the defined minimum starting gold.", side.carryover_gold)
else
goldmsg = _("You will start the next scenario with the defined minimum starting gold.",
"You will start the next scenario with the defined minimum starting gold.", side.carryover_gold)
end
else
goldmsg = _(
"You will start the next scenario with $gold or its defined minimum starting gold, whichever is higher.",
"You will start the next scenario with $gold or its defined minimum starting gold, whichever is higher.",
side.carryover_gold)
end
-- xgettext:no-c-format
report = report .. "\n" .. goldmsg:vformat{ gold = tostring(side.carryover_gold) }
::continue::
end
end
if show_report then
gui.show_popup(title, report)
end
end
wesnoth.game_events.add {
name = "scenario_end",
id = "carryover_gold",
first_time_only = false,
--priority = -1000,
action = function()
do_carryover_gold()
end
}

View file

@ -233,8 +233,6 @@
<Unit filename="../../src/campaign_type.hpp" />
<Unit filename="../../src/carryover.cpp" />
<Unit filename="../../src/carryover.hpp" />
<Unit filename="../../src/carryover_show_gold.cpp" />
<Unit filename="../../src/carryover_show_gold.hpp" />
<Unit filename="../../src/chat_command_handler.cpp" />
<Unit filename="../../src/chat_command_handler.hpp" />
<Unit filename="../../src/chat_events.cpp" />

View file

@ -231,8 +231,6 @@
<Unit filename="../../src/campaign_type.hpp" />
<Unit filename="../../src/carryover.cpp" />
<Unit filename="../../src/carryover.hpp" />
<Unit filename="../../src/carryover_show_gold.cpp" />
<Unit filename="../../src/carryover_show_gold.hpp" />
<Unit filename="../../src/chat_command_handler.cpp" />
<Unit filename="../../src/chat_command_handler.hpp" />
<Unit filename="../../src/chat_events.cpp" />

View file

@ -661,7 +661,6 @@
7FDF4E8D9C94E7DA8F41F7BB /* tod_new_schedule.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 5D46466DBCD81B13621C7342 /* tod_new_schedule.hpp */; };
805143B8BABF92CA79BEC8F5 /* gui_test_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBD4033B4B52E9424819B5F /* gui_test_dialog.cpp */; };
80724CBB88A3B6C36D1E3199 /* spritesheet_generator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D284B9A81882806D8B25006 /* spritesheet_generator.hpp */; };
867141839BDB89BFE876E310 /* carryover_show_gold.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */; };
87744447951D17AA38BE5F48 /* mp_report.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 58C649488B3014E6F7254B62 /* mp_report.cpp */; };
8C704B6F99C824A4073EEBEE /* prompt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 67044415B63F5888193BD7A6 /* prompt.cpp */; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
@ -1128,7 +1127,6 @@
9577DD332C1E1C150031135F /* team_shared_vision.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD322C1E1C150031135F /* team_shared_vision.hpp */; };
9577DD352C1E1E1D0031135F /* wesnoth_epoch.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD342C1E1E1C0031135F /* wesnoth_epoch.hpp */; };
9577DD3E2C1E2EC60031135F /* preferences_list.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD3D2C1E2EC60031135F /* preferences_list.hpp */; };
9577DD402C1E36170031135F /* carryover_show_gold.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD3F2C1E36170031135F /* carryover_show_gold.hpp */; };
9577DD422C1E368B0031135F /* statistics_record.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD412C1E368B0031135F /* statistics_record.hpp */; };
9577DD442C1E36D40031135F /* from_chars.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD432C1E36D40031135F /* from_chars.hpp */; };
9577DD462C1E36E20031135F /* any.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 9577DD452C1E36E20031135F /* any.hpp */; };
@ -1143,7 +1141,6 @@
95EB8A55287A02EC00B09F95 /* top_level_drawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95EB8A54287A02EC00B09F95 /* top_level_drawable.cpp */; };
95EB8A58287B138700B09F95 /* draw_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95EB8A50287A02B800B09F95 /* draw_manager.cpp */; };
95EB8A59287B139800B09F95 /* top_level_drawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95EB8A54287A02EC00B09F95 /* top_level_drawable.cpp */; };
97714C7A9FF444E29DCEF0BA /* carryover_show_gold.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */; };
99494BD0ABBAE79FB3814E00 /* charconv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CDC443798CB3254283483D0 /* charconv.cpp */; };
9B4B41D29C90B05F03DE21B0 /* edit_pbl_translation.hpp in Headers */ = {isa = PBXBuildFile; fileRef = C679447D91FD3623CC852FF8 /* edit_pbl_translation.hpp */; };
9C2743DE8100448B66F7E0AF /* combobox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 875E45698F8A8D5B750E7317 /* combobox.cpp */; };
@ -1600,7 +1597,6 @@
000000000000000000000010 /* network_download_file.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = network_download_file.hpp; sourceTree = "<group>"; };
00574699A982AA23F12B39E0 /* edit_pbl_translation.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = edit_pbl_translation.cpp; sourceTree = "<group>"; };
0110429EAA81AED07D53B749 /* gui_test_dialog.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gui_test_dialog.hpp; sourceTree = "<group>"; };
09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = carryover_show_gold.cpp; sourceTree = "<group>"; };
0B0F48CE9CF65D9813BE6CDC /* multiline_text.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = multiline_text.cpp; sourceTree = "<group>"; };
0CDC443798CB3254283483D0 /* charconv.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = charconv.cpp; path = charconv.cpp; sourceTree = "<group>"; };
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
@ -2435,7 +2431,6 @@
9577DD322C1E1C150031135F /* team_shared_vision.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = team_shared_vision.hpp; sourceTree = "<group>"; };
9577DD342C1E1E1C0031135F /* wesnoth_epoch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = wesnoth_epoch.hpp; sourceTree = "<group>"; };
9577DD3D2C1E2EC60031135F /* preferences_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = preferences_list.hpp; path = preferences/preferences_list.hpp; sourceTree = "<group>"; };
9577DD3F2C1E36170031135F /* carryover_show_gold.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = carryover_show_gold.hpp; sourceTree = "<group>"; };
9577DD412C1E368B0031135F /* statistics_record.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = statistics_record.hpp; sourceTree = "<group>"; };
9577DD432C1E36D40031135F /* from_chars.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = from_chars.hpp; sourceTree = "<group>"; };
9577DD452C1E36E20031135F /* any.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = any.hpp; sourceTree = "<group>"; };
@ -3269,8 +3264,6 @@
91B621A11B76A3CC00B00E0F /* build_info.cpp */,
91B621A31B76A5FA00B00E0F /* build_info.hpp */,
9577DD1A2C1E0AF40031135F /* campaign_type.hpp */,
09A440B1A671C45BE2924FB4 /* carryover_show_gold.cpp */,
9577DD3F2C1E36170031135F /* carryover_show_gold.hpp */,
ECFB9FA7193BFAD900146ED0 /* carryover.cpp */,
91B621811B766F1900B00E0F /* carryover.hpp */,
918C8A161D05F9AA009744A0 /* chat_command_handler.cpp */,
@ -5233,7 +5226,6 @@
3DED4C43AC1B737C15549CEC /* rich_label.hpp in Headers */,
9577DD292C1E0E530031135F /* sort_order.hpp in Headers */,
9C6342BC8A95B6D23D384486 /* gui_test_dialog.hpp in Headers */,
9577DD402C1E36170031135F /* carryover_show_gold.hpp in Headers */,
80724CBB88A3B6C36D1E3199 /* spritesheet_generator.hpp in Headers */,
0DA840E1AD033775DD626F42 /* markup.hpp in Headers */,
F7524948ADF9BC097E6D8DBC /* charconv.hpp in Headers */,
@ -5979,7 +5971,6 @@
46F92E212174F6A400602C1C /* mp_change_control.cpp in Sources */,
36B146FAA79A55E9F43723B1 /* general.cpp in Sources */,
3C254DF5B7DF196F2041955F /* mp_report.cpp in Sources */,
97714C7A9FF444E29DCEF0BA /* carryover_show_gold.cpp in Sources */,
6D574EACA3483ABEE72819F0 /* statistics_record.cpp in Sources */,
4E19429E82899A42A73BBE91 /* choose_addon.cpp in Sources */,
36D74F7F8D7655ACCABE562D /* edit_pbl.cpp in Sources */,
@ -6654,7 +6645,6 @@
915C68EC1DF1DCB000594B07 /* color.cpp in Sources */,
4291489DA38012477DA3BA7C /* general.cpp in Sources */,
87744447951D17AA38BE5F48 /* mp_report.cpp in Sources */,
867141839BDB89BFE876E310 /* carryover_show_gold.cpp in Sources */,
3E9A4297B4A2828C569C8927 /* statistics_record.cpp in Sources */,
E79249078ACE777D1E219DED /* choose_addon.cpp in Sources */,
04C748F7835C62498D27442D /* edit_pbl.cpp in Sources */,

View file

@ -61,7 +61,6 @@ animated.cpp
attack_prediction.cpp
build_info.cpp
carryover.cpp
carryover_show_gold.cpp
chat_command_handler.cpp
chat_events.cpp
chat_log.cpp

View file

@ -1,158 +0,0 @@
/*
Copyright (C) 2003 - 2024
by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "carryover_show_gold.hpp"
#include "log.hpp"
#include "team.hpp"
#include "game_state.hpp"
#include "gettext.hpp"
#include "gui/dialogs/transient_message.hpp"
#include "formula/string_utils.hpp"
#include "map/map.hpp"
#include "serialization/markup.hpp"
#include <cassert>
static lg::log_domain log_engine("engine");
#define LOG_NG LOG_STREAM(info, log_engine)
#define ERR_NG LOG_STREAM(err, log_engine)
void carryover_show_gold(game_state& state, bool hidden, bool is_observer, bool is_test)
{
assert(state.end_level_data_);
game_board& board = state.board_;
const end_level_data& end_level = *state.end_level_data_;
const bool is_victory = end_level.is_victory;
// We need to write the carryover amount to the team that's why we need non const
std::vector<team>& teams = board.teams();
// maybe this can be the case for scenario that only contain a story and end during the prestart event ?
if(teams.size() < 1) {
return;
}
std::ostringstream report;
std::string title;
if(is_observer) {
title = _("Scenario Report");
} else if(is_victory) {
title = _("Victory");
report << markup::bold(_("You have emerged victorious!"));
} else {
title = _("Defeat");
report << _("You have been defeated!");
}
const std::string& next_scenario = state.get_game_data()->next_scenario();
const bool has_next_scenario = !next_scenario.empty() && next_scenario != "null";
int persistent_teams = 0;
for(const team& t : teams) {
if(t.persistent()) {
++persistent_teams;
}
}
if(persistent_teams > 0 && ((has_next_scenario && end_level.proceed_to_next_level) || is_test)) {
const gamemap& map = board.map();
const tod_manager& tod = state.get_tod_man();
const int turns_left = std::max<int>(0, tod.number_of_turns() - tod.turn());
for(team& t : teams) {
if(!t.persistent() || t.lost()) {
continue;
}
const int finishing_bonus_per_turn = map.villages().size() * t.village_gold() + t.base_income();
const int finishing_bonus = t.carryover_bonus() * finishing_bonus_per_turn * turns_left;
t.set_carryover_gold(div100rounded((t.gold() + finishing_bonus) * t.carryover_percentage()));
if(!t.is_local_human()) {
continue;
}
if(persistent_teams > 1) {
report << "\n\n" << markup::bold(t.side_name());
}
report << "\n" << markup::tag("small", _("Remaining gold: "), utils::half_signed_value(t.gold()));
if(t.carryover_bonus() != 0) {
if(turns_left > -1) {
report << "\n\n"
<< markup::bold(_("Turns finished early: "), turns_left) << "\n"
<< markup::tag("small",
_("Early finish bonus: "), finishing_bonus_per_turn, _(" per turn"), "\n",
_("Total bonus: "), finishing_bonus, "\n");
}
report << markup::tag("small", _("Total gold: "), utils::half_signed_value(t.gold() + finishing_bonus));
}
if(t.gold() > 0) {
report << "\n" << markup::tag("small", _("Carryover percentage: "), t.carryover_percentage());
}
if(t.carryover_add()) {
report << "\n\n" << markup::tag("big", markup::bold(_("Bonus gold: "), utils::half_signed_value(t.carryover_gold())));
} else {
report << "\n\n" << markup::tag("big", markup::bold(_("Retained gold: "), utils::half_signed_value(t.carryover_gold())));
}
std::string goldmsg;
utils::string_map symbols;
symbols["gold"] = lexical_cast_default<std::string>(t.carryover_gold());
// Note that both strings are the same in English, but some languages will
// want to translate them differently.
if(t.carryover_add()) {
if(t.carryover_gold() > 0) {
goldmsg = VNGETTEXT(
"You will start the next scenario with $gold on top of the defined minimum starting gold.",
"You will start the next scenario with $gold on top of the defined minimum starting gold.",
t.carryover_gold(), symbols
);
} else {
goldmsg = VNGETTEXT(
"You will start the next scenario with the defined minimum starting gold.",
"You will start the next scenario with the defined minimum starting gold.",
t.carryover_gold(), symbols
);
}
} else {
goldmsg = VNGETTEXT(
"You will start the next scenario with $gold or its defined minimum starting gold, "
"whichever is higher.",
"You will start the next scenario with $gold or its defined minimum starting gold, "
"whichever is higher.",
t.carryover_gold(), symbols
);
}
// xgettext:no-c-format
report << "\n" << goldmsg;
}
}
if(end_level.transient.carryover_report && !hidden) {
gui2::show_transient_message(title, report.str(), "", true);
}
}

View file

@ -1,19 +0,0 @@
/*
Copyright (C) 2022 - 2024
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
class game_state;
/// calculates the amount of gold carried over for each team,
/// stores the data in the team object and shows the carryover message
void carryover_show_gold(game_state& state, bool hidden, bool is_observer, bool is_test);

View file

@ -25,7 +25,6 @@
#include "ai/manager.hpp"
#include "ai/testing.hpp"
#include "display_chat_manager.hpp"
#include "carryover_show_gold.hpp"
#include "formula/string_utils.hpp"
#include "game_end_exceptions.hpp"
#include "game_events/pump.hpp"
@ -410,8 +409,6 @@ void playsingle_controller::do_end_level()
}
persist_.end_transaction();
carryover_show_gold(gamestate(), is_observer() || is_replay(), is_observer(), saved_game_.classification().is_test());
}
level_result::type playsingle_controller::play_scenario(const config& level)