diff --git a/data/lua/wml/endlevel.lua b/data/lua/wml/endlevel.lua index 379d36d0ff72..883b2f0b4c7f 100644 --- a/data/lua/wml/endlevel.lua +++ b/data/lua/wml/endlevel.lua @@ -80,10 +80,17 @@ function wesnoth.wml_actions.endlevel(cfg) 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 victory and cfg.music then + wesnoth.game_config.victory_music = cfg.music + elseif cfg.music then + wesnoth.game_config.defeat_music = cfg.music + end + wesnoth.end_level { - music = cfg.music, carryover_report = cfg.carryover_report, save = cfg.save, replay_save = cfg.replay_save, diff --git a/src/game_data.cpp b/src/game_data.cpp index 040bea5348b5..45db6e16a543 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp @@ -21,6 +21,7 @@ #include "log.hpp" //LOG_STREAM #include "variable.hpp" //scoped_wml_variable +#include "serialization/string_utils.hpp" #include @@ -39,6 +40,10 @@ game_data::game_data(const config& level) , phase_(INITIAL) , can_end_turn_(level["can_end_turn"].to_bool(true)) , next_scenario_(level["next_scenario"]) + , id_(level["id"]) + , theme_(level["theme"]) + , defeat_music_(utils::split(level["defeat_music"])) + , victory_music_(utils::split(level["victory_music"])) { } @@ -121,6 +126,10 @@ void game_data::clear_variable(const std::string& varname) void game_data::write_snapshot(config& cfg) const { cfg["next_scenario"] = next_scenario_; + cfg["id"] = id_; + cfg["theme"] = theme_; + cfg["defeat_music"] = utils::join(defeat_music_); + cfg["victory_music"] = utils::join(victory_music_); cfg["can_end_turn"] = can_end_turn_; diff --git a/src/game_data.hpp b/src/game_data.hpp index 32836063927a..2c5f1c745241 100644 --- a/src/game_data.hpp +++ b/src/game_data.hpp @@ -88,6 +88,18 @@ class game_data : public variable_set { const std::string& next_scenario() const { return next_scenario_; } void set_next_scenario(const std::string& next_scenario) { next_scenario_ = next_scenario; } + const std::string& get_id() const { return id_; } + void set_id(const std::string& value) { id_ = value; } + + const std::string& get_theme() const { return theme_; } + void set_theme(const std::string& value) { theme_ = value; } + + const std::vector& get_defeat_music() const { return defeat_music_; } + void set_defeat_music(std::vector value) { defeat_music_ = std::move(value); } + + const std::vector& get_victory_music() const { return victory_music_; } + void set_victory_music(std::vector value) { victory_music_ = std::move(value); } + private: void activate_scope_variable(std::string var_name) const; ///Used to delete variables. @@ -101,7 +113,13 @@ class game_data : public variable_set { config variables_; PHASE phase_; bool can_end_turn_; - std::string next_scenario_; /**< the scenario coming next (for campaigns) */ + /// the scenario coming next (for campaigns) + std::string next_scenario_; + // the id of a scenario cannot change during a scenario + std::string id_; + std::string theme_; + std::vector defeat_music_; + std::vector victory_music_; }; #endif diff --git a/src/game_end_exceptions.cpp b/src/game_end_exceptions.cpp index eddac8ad9ff1..9496db64e8f3 100644 --- a/src/game_end_exceptions.cpp +++ b/src/game_end_exceptions.cpp @@ -21,7 +21,6 @@ transient_end_level::transient_end_level() : carryover_report(true) , linger_mode(true) - , custom_endlevel_music() , reveal_map(true) {} @@ -70,5 +69,4 @@ void transient_end_level::write(config& cfg) const cfg["carryover_report"] = carryover_report; cfg["linger_mode"] = linger_mode; cfg["reveal_map"] = reveal_map; - cfg["music"] = custom_endlevel_music; } diff --git a/src/game_end_exceptions.hpp b/src/game_end_exceptions.hpp index e2c191ee0aa7..6bb92306e5c6 100644 --- a/src/game_end_exceptions.hpp +++ b/src/game_end_exceptions.hpp @@ -82,7 +82,6 @@ struct transient_end_level{ bool carryover_report; /**< Should a summary of the scenario outcome be displayed? */ bool linger_mode; /**< Should linger mode be invoked? */ - std::string custom_endlevel_music; /**< Custom short music played at the end. */ bool reveal_map; /**< Should we reveal map when game is ended? (Multiplayer only) */ void write(config& cfg) const; diff --git a/src/play_controller.cpp b/src/play_controller.cpp index 83ace2e9afc4..7456d499197d 100644 --- a/src/play_controller.cpp +++ b/src/play_controller.cpp @@ -87,13 +87,8 @@ static lg::log_domain log_engine_enemies("engine/enemies"); static void copy_persistent(const config& src, config& dst) { static const std::set attrs = { - "id", - "theme", - "next_scenario", "description", "name", - "defeat_music", - "victory_music", "victory_when_enemies_defeated", "remove_from_carryover_on_defeat", "disallow_recall", @@ -180,10 +175,6 @@ play_controller::play_controller(const config& level, saved_game& state_of_game, persist_.start_transaction(); - // Setup victory and defeat music - set_victory_music_list(level_["victory_music"]); - set_defeat_music_list(level_["defeat_music"]); - game_config::add_color_info(level); hotkey::deactivate_all_scopes(); hotkey::set_scope_active(hotkey::SCOPE_GAME); @@ -240,7 +231,7 @@ void play_controller::init(CVideo& video, const config& level) LOG_NG << "initializing theme... " << (SDL_GetTicks() - ticks()) << std::endl; gui2::dialogs::loading_screen::progress("init theme"); - const config& theme_cfg = controller_base::get_theme(game_config_, level["theme"]); + const config& theme_cfg = controller_base::get_theme(game_config_, theme()); LOG_NG << "building terrain rules... " << (SDL_GetTicks() - ticks()) << std::endl; gui2::dialogs::loading_screen::progress("build terrain"); @@ -889,32 +880,15 @@ namespace { static const std::string empty_str = ""; } -const std::string& play_controller::select_victory_music() const +const std::string& play_controller::select_music(bool victory) const { - if(victory_music_.empty()) - return empty_str; - return victory_music_[rand() % victory_music_.size()]; -} + const std::vector& music_list = victory + ? (gamestate_->get_game_data()->get_victory_music().empty() ? game_config::default_victory_music : gamestate_->get_game_data()->get_victory_music()) + : (gamestate_->get_game_data()->get_defeat_music().empty() ? game_config::default_defeat_music : gamestate_->get_game_data()->get_defeat_music()); -const std::string& play_controller::select_defeat_music() const -{ - if(defeat_music_.empty()) + if(music_list.empty()) return empty_str; - return defeat_music_[rand() % defeat_music_.size()]; -} - -void play_controller::set_victory_music_list(const std::string& list) -{ - victory_music_ = utils::split(list); - if(victory_music_.empty()) - victory_music_ = game_config::default_victory_music; -} - -void play_controller::set_defeat_music_list(const std::string& list) -{ - defeat_music_ = utils::split(list); - if(defeat_music_.empty()) - defeat_music_ = game_config::default_defeat_music; + return music_list[rand() % music_list.size()]; } void play_controller::check_victory() diff --git a/src/play_controller.hpp b/src/play_controller.hpp index f68e5ac45d4c..aa2ed2d719c0 100644 --- a/src/play_controller.hpp +++ b/src/play_controller.hpp @@ -230,7 +230,7 @@ class play_controller : public controller_base, public events::observer, public std::string theme() const { - return level_["theme"].str(); + return gamestate_->get_game_data()->get_theme(); } virtual bool should_return_to_play_side() const @@ -343,10 +343,7 @@ class play_controller : public controller_base, public events::observer, public * (false = we did init sides before we reloaded the game). */ bool init_side_done_now_; - const std::string& select_victory_music() const; - const std::string& select_defeat_music() const; - void set_victory_music_list(const std::string& list); - void set_defeat_music_list(const std::string& list); + const std::string& select_music(bool victory) const; void reset_gamestate(const config& level, int replay_pos); diff --git a/src/playsingle_controller.cpp b/src/playsingle_controller.cpp index 7123d896e989..f5c032009c10 100644 --- a/src/playsingle_controller.cpp +++ b/src/playsingle_controller.cpp @@ -274,13 +274,6 @@ LEVEL_RESULT playsingle_controller::play_scenario(const config& level) ai_testing::log_game_end(); const end_level_data& end_level = get_end_level_data_const(); - if (!end_level.transient.custom_endlevel_music.empty()) { - if (!is_victory) { - set_defeat_music_list(end_level.transient.custom_endlevel_music); - } else { - set_victory_music_list(end_level.transient.custom_endlevel_music); - } - } if (gamestate().board_.teams().empty()) { @@ -327,7 +320,7 @@ LEVEL_RESULT playsingle_controller::play_scenario(const config& level) // result for something that is not story-wise // a victory, so let them use [music] tags // instead should they want special music. - const std::string& end_music = is_victory ? select_victory_music() : select_defeat_music(); + const std::string& end_music = select_music(is_victory); if((!is_victory || end_level.transient.carryover_report) && !end_music.empty()) { sound::play_music_once(end_music); } diff --git a/src/scripting/game_lua_kernel.cpp b/src/scripting/game_lua_kernel.cpp index 3d67d0a89a97..1126cad12d8c 100644 --- a/src/scripting/game_lua_kernel.cpp +++ b/src/scripting/game_lua_kernel.cpp @@ -1233,6 +1233,9 @@ int game_lua_kernel::impl_game_config_get(lua_State *L) return_bool_attrib("debug", game_config::debug); return_bool_attrib("debug_lua", game_config::debug_lua); return_bool_attrib("mp_debug", game_config::mp_debug); + return_string_attrib("scenario_id", gamedata().get_id()); + return_vector_string_attrib("defeat_music", gamedata().get_defeat_music()); + return_vector_string_attrib("victory_music", gamedata().get_victory_music()); const mp_game_settings& mp_settings = play_controller_.get_mp_settings(); const game_classification & classification = play_controller_.get_classification(); @@ -1276,7 +1279,8 @@ int game_lua_kernel::impl_game_config_set(lua_State *L) modify_int_attrib("kill_experience", game_config::kill_experience = value); modify_int_attrib("last_turn", tod_man().set_number_of_turns_by_wml(value)); modify_string_attrib("next_scenario", gamedata().set_next_scenario(value)); - + modify_vector_string_attrib("defeat_music", gamedata().set_defeat_music(std::move(vector))); + modify_vector_string_attrib("victory_music", gamedata().set_victory_music(std::move(vector))); std::string err_msg = "unknown modifiable property of game_config: "; err_msg += m; return luaL_argerror(L, 2, err_msg.c_str()); @@ -1407,7 +1411,6 @@ static int impl_end_level_data_get(lua_State* L) const end_level_data& data = *static_cast(lua_touserdata(L, 1)); const char* m = luaL_checkstring(L, 2); - return_string_attrib("music", data.transient.custom_endlevel_music); return_bool_attrib("linger_mode", data.transient.linger_mode); return_bool_attrib("reveal_map", data.transient.reveal_map); return_bool_attrib("carryover_report", data.transient.carryover_report); @@ -1440,7 +1443,6 @@ int game_lua_kernel::impl_end_level_data_set(lua_State* L) const char* m = luaL_checkstring(L, 2); end_level_committer commit(data, play_controller_); - modify_string_attrib("music", data.transient.custom_endlevel_music = value); modify_bool_attrib("linger_mode", data.transient.linger_mode = value); modify_bool_attrib("reveal_map", data.transient.reveal_map = value); modify_bool_attrib("carryover_report", data.transient.carryover_report = value); @@ -1483,7 +1485,6 @@ int game_lua_kernel::intf_end_level(lua_State *L) end_level_data data; 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);