Lua API: Enable plugins to play a campaign

This also fixes some issues that can prevent a plugin from working with the GUI (that is, only working in headless mode). Plugins should work in both headless and GUI mode.
This commit is contained in:
Celtic Minstrel 2024-09-15 00:37:21 -04:00
parent b1eb871df7
commit a1c78edda5
8 changed files with 73 additions and 26 deletions

View file

@ -751,14 +751,20 @@ std::string game_launcher::jump_to_campaign_id() const
return jump_to_campaign_.campaign_id;
}
bool game_launcher::play_campaign() {
if(new_campaign()) {
state_.set_skip_story(jump_to_campaign_.skip_story);
jump_to_campaign_.jump = false;
launch_game(reload_mode::NO_RELOAD_DATA);
return true;
}
return false;
}
bool game_launcher::goto_campaign()
{
if(jump_to_campaign_.jump) {
if(new_campaign()) {
state_.set_skip_story(jump_to_campaign_.skip_story);
jump_to_campaign_.jump = false;
launch_game(reload_mode::NO_RELOAD_DATA);
} else {
if(!play_campaign()) {
jump_to_campaign_.jump = false;
return false;
}

View file

@ -102,6 +102,7 @@ public:
void select_mp_server(const std::string& server) { multiplayer_server_ = server; }
bool play_multiplayer(mp_mode mode);
bool play_multiplayer_commandline();
bool play_campaign();
bool change_language();
void launch_game(reload_mode reload = reload_mode::RELOAD_DATA);

View file

@ -39,6 +39,23 @@ namespace gui2::dialogs
REGISTER_DIALOG(campaign_selection)
campaign_selection::campaign_selection(ng::create_engine& eng)
: modal_dialog(window_id())
, engine_(eng)
, choice_(-1)
, rng_mode_(RNG_DEFAULT)
, mod_states_()
, page_ids_()
, difficulties_()
, current_difficulty_()
, current_sorting_(RANK)
, currently_sorted_asc_(true)
, mod_ids_()
{
set_show_even_without_video(true);
set_allow_plugin_skip(false);
}
void campaign_selection::campaign_selected()
{
tree_view& tree = find_widget<tree_view>("campaign_tree");
@ -425,6 +442,28 @@ void campaign_selection::pre_show()
connect_signal_notify_modified(diff_menu, std::bind(&campaign_selection::difficulty_selected, this));
campaign_selected();
plugins_context_.reset(new plugins_context("Campaign Selection"));
plugins_context_->set_callback("create", [this](const config&) { set_retval(retval::OK); }, false);
plugins_context_->set_callback("quit", [this](const config&) { set_retval(retval::CANCEL); }, false);
plugins_context_->set_accessor("find_level", [this](const config& cfg) {
const std::string id = cfg["id"].str();
auto result = engine_.find_level_by_id(id);
return config {
"index", result.second,
"type", level_type::get_string(result.first),
};
});
plugins_context_->set_accessor_int("find_mod", [this](const config& cfg) {
return engine_.find_extra_by_id(ng::create_engine::MOD, cfg["id"]);
});
plugins_context_->set_callback("select_level", [this](const config& cfg) {
choice_ = cfg["index"].to_int();
engine_.set_current_level(choice_);
}, true);
}
void campaign_selection::add_campaign_to_tree(const config& campaign)

View file

@ -18,13 +18,14 @@
#include "gui/dialogs/modal_dialog.hpp"
#include "game_initialization/create_engine.hpp"
#include "gui/dialogs/multiplayer/plugin_executor.hpp"
#include <boost/dynamic_bitset.hpp>
namespace gui2::dialogs
{
class campaign_selection : public modal_dialog
class campaign_selection : public modal_dialog, private plugin_executor
{
enum CAMPAIGN_ORDER {RANK, DATE, NAME};
public:
@ -41,20 +42,7 @@ public:
RNG_BIASED,
};
explicit campaign_selection(ng::create_engine& eng)
: modal_dialog(window_id())
, engine_(eng)
, choice_(-1)
, rng_mode_(RNG_DEFAULT)
, mod_states_()
, page_ids_()
, difficulties_()
, current_difficulty_()
, current_sorting_(RANK)
, currently_sorted_asc_(true)
, mod_ids_()
{
}
explicit campaign_selection(ng::create_engine& eng);
/***** ***** ***** setters / getters for members ***** ****** *****/

View file

@ -93,6 +93,7 @@ loading_screen::loading_screen(std::function<void()> f)
current_visible_stage_ = visible_stages_.end();
singleton_ = this;
set_allow_plugin_skip(false);
}
void loading_screen::pre_show()

View file

@ -66,20 +66,25 @@ bool modal_dialog::show(const unsigned auto_close_time)
{
if(video::headless() && !show_even_without_video_) {
DBG_DP << "modal_dialog::show denied";
if(!allow_plugin_skip_) {
return false;
}
return false;
}
if(allow_plugin_skip_) {
bool skipped = false;
plugins_manager* pm = plugins_manager::get();
if (pm && pm->any_running())
{
plugins_context pc("Dialog");
pc.set_callback("skip_dialog", [this](config) { retval_ = retval::OK; }, false);
pc.set_callback("quit", [](config) {}, false);
pc.set_callback("skip_dialog", [this, &skipped](config) { retval_ = retval::OK; skipped = true; }, false);
pc.set_callback("quit", [this, &skipped](config) { retval_ = retval::CANCEL; skipped = true; }, false);
pc.set_callback("select", [this, &skipped](config c) { retval_ = c["retval"].to_int(); skipped = true; }, false);
pc.set_accessor_string("id", [this](config) { return window_id(); });
pc.play_slice();
}
return false;
if(skipped) {
return false;
}
}
init_fields();

View file

@ -28,12 +28,17 @@ sp_options_configure::sp_options_configure(ng::create_engine& create_engine, ng:
, config_engine_(config_engine)
, options_manager_()
{
set_show_even_without_video(true);
set_allow_plugin_skip(false);
}
void sp_options_configure::pre_show()
{
options_manager_.reset(new mp_options_helper(*this, create_engine_));
options_manager_->update_all_options();
plugins_context_.reset(new plugins_context("Campaign Configure"));
plugins_context_->set_callback("launch", [this](const config&) { set_retval(retval::OK); }, false);
}
void sp_options_configure::post_show()

View file

@ -762,6 +762,8 @@ static int do_gameloop(commandline_options& cmdline_opts)
const plugins_context::reg_vec callbacks {
{"play_multiplayer", std::bind(&game_launcher::play_multiplayer, game.get(), game_launcher::mp_mode::CONNECT)},
{"play_local", std::bind(&game_launcher::play_multiplayer, game.get(), game_launcher::mp_mode::LOCAL)},
{"play_campaign", std::bind(&game_launcher::play_campaign, game.get())},
};
const plugins_context::areg_vec accessors {