Include builtin conditions in wesnoth.wml_conditions

This excludes the [true] and [false] ConditionalWML tags,
which are still hard-coded. (People shouldn't be trying to
override or extend these anyway.)
This commit is contained in:
Celtic Minstrel 2016-08-02 16:56:55 -04:00
parent e75eaca5a0
commit 44d171ab58
5 changed files with 49 additions and 8 deletions

View file

@ -31,6 +31,9 @@ Version 1.13.5+dev:
modifications of the chosen type from a unit. The most efficient use is to
remove all modifications with a specific duration value.
Also callable as u:remove_modifications.
* The built-in conditionals have_unit, have_location, and variable are now
present in the wesnoth.wml_conditionals table. This means they can be directly
called, extended with new features, or even overridden with custom implementations.
* Performance:
* When a heuristic determines that it's probably faster, the game predicts battle
outcome by simulating a few thousand fights instead of calculating exact

View file

@ -43,7 +43,7 @@ static lg::log_domain log_engine("engine");
// This file is in the game_events namespace.
namespace game_events {
namespace { // Support functions
namespace builtin_conditions {
std::vector<std::pair<int,int> > default_counts = utils::parse_ranges("1-99999");
bool have_unit(const vconfig& cfg)
@ -143,7 +143,9 @@ namespace { // Support functions
#undef TEST_BOL_ATTR
return true;
}
}
namespace { // Support functions
bool internal_conditional_passed(const vconfig& cond)
{
if(cond.has_child("true")) {
@ -160,13 +162,7 @@ namespace { // Support functions
for(vconfig::all_children_iterator it = cond.ordered_begin(); it != cond_end; ++it) {
std::string key = it.get_key();
bool result = true;
if(key == "have_unit") {
result = have_unit(it.get_child());
} else if(key == "have_location") {
result = have_location(it.get_child());
} else if(key == "variable") {
result = variable_matches(it.get_child());
} else if(std::find(skip.begin(), skip.end(), key) == skip.end()) {
if(std::find(skip.begin(), skip.end(), key) == skip.end()) {
assert(resources::lua_kernel);
result = resources::lua_kernel->run_wml_conditional(key, it.get_child());
}

View file

@ -29,6 +29,12 @@ namespace game_events
{
bool conditional_passed(const vconfig& cond);
bool matches_special_filter(const config &cfg, const vconfig& filter);
namespace builtin_conditions {
bool have_unit(const vconfig& cfg);
bool have_location(const vconfig& cfg);
bool variable_matches(const vconfig& cfg);
}
}
#endif // GAME_EVENTS_CONDITIONAL_WML_H_INCLUDED

View file

@ -4895,6 +4895,9 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
lua_newtable(L);
lua_setfield(L, -2, "wml_conditionals");
lua_pop(L, 1);
set_wml_condition("have_unit", &game_events::builtin_conditions::have_unit);
set_wml_condition("have_location", &game_events::builtin_conditions::have_location);
set_wml_condition("variable", &game_events::builtin_conditions::variable_matches);
// Create the effects table.
cmd_log_ << "Adding effects table...\n";
@ -5225,6 +5228,38 @@ void game_lua_kernel::set_wml_action(std::string const &cmd, game_events::wml_ac
lua_pop(L, 2);
}
using wml_conditional_handler = bool(*)(const vconfig&);
/**
* Executes its upvalue as a wml condition and returns the result.
*/
static int cfun_wml_condition(lua_State *L)
{
wml_conditional_handler h = reinterpret_cast<wml_conditional_handler>
(lua_touserdata(L, lua_upvalueindex(1)));
vconfig vcfg = luaW_checkvconfig(L, 1);
lua_pushboolean(L, h(vcfg));
return 1;
}
/**
* Registers a function for use as a conditional handler.
*/
void game_lua_kernel::set_wml_condition(std::string const &cmd, wml_conditional_handler h)
{
lua_State *L = mState;
lua_getglobal(L, "wesnoth");
lua_pushstring(L, "wml_conditionals");
lua_rawget(L, -2);
lua_pushstring(L, cmd.c_str());
lua_pushlightuserdata(L, reinterpret_cast<void *>(h));
lua_pushcclosure(L, &cfun_wml_condition, 1);
lua_rawset(L, -3);
lua_pop(L, 2);
}
/**
* Runs a command from an event handler.
* @return true if there is a handler for the command.

View file

@ -201,6 +201,7 @@ public:
bool run_event(game_events::queued_event const &);
void push_builtin_effect();
void set_wml_action(std::string const &, game_events::wml_action::handler);
void set_wml_condition(std::string const &, bool(*)(const vconfig&));
bool run_wml_action(std::string const &, vconfig const &,
game_events::queued_event const &);
bool run_filter(char const *name, unit const &u);