add lua function "fire_wml_menu_item" and unit tests for menu items

this commit also changed slightly the way that wml menu events
are synced. previously they were run via "run_in_synced_context",
now they are run via "run_in_synced_context_if_not_already", which
makes it safe to fire them from lua (a synced context).
This commit is contained in:
Chris Beck 2015-01-05 20:34:12 -05:00
parent d71d39ec7a
commit 8459bf7104
5 changed files with 152 additions and 1 deletions

View file

@ -0,0 +1,118 @@
#
# Test if wml menu items are working
#
{GENERIC_UNIT_TEST "test_wml_menu_items_1" (
[event]
name = start
[set_menu_item]
id=test1
description="store location"
[command]
{VARIABLE mx $x1}
{VARIABLE my $y1}
[/command]
[/set_menu_item]
[lua]
code = << wesnoth.fire_wml_menu_item("test1", 3, 3) >>
[/lua]
{ASSERT {VARIABLE_CONDITIONAL mx equals 3}}
{ASSERT {VARIABLE_CONDITIONAL my equals 3}}
{RETURN ([true][/true])}
[/event]
)}
#
# This test should be failing although you might think it succeeds.
# The test asserts that if filter_location for a menu_item is false,
# it should return false if wesnoth attempts to fire it. However this
# isn't the case, filter_location is normally checked before the
# attempt to fire it.
#
{GENERIC_UNIT_TEST "test_wml_menu_items_2" (
[event]
name = start
[set_menu_item]
id=test2
description="spawn a unit"
[filter_location]
[not]
[have_unit]
x=$x1
y=$y1
[/have_unit]
[/not]
[/filter_location]
[command]
{UNIT 2 "Orcish Grunt" $x1 $y1 ()}
[/command]
[/set_menu_item]
[lua]
code = << r = wesnoth.fire_wml_menu_item("test2", 3, 3)
r = r and not wesnoth.fire_wml_menu_item("test2", 3, 3)
r = r and wesnoth.fire_wml_menu_item("test2", 4, 4)
r = r and not wesnoth.fire_wml_menu_item("test2", 4, 4)
wesnoth.set_variable("result", r) >>
[/lua]
{RETURN {VARIABLE_CONDITIONAL result boolean_equals true}}
[/event]
)}
#
# An ammended form of the above test, which checks a menu item which creates a unit,
# being fired twice.
#
{GENERIC_UNIT_TEST "test_wml_menu_items_3" (
[event]
name = start
[set_menu_item]
id=test3
description="Summon Troll"
[show_if]
[not]
[have_unit]
x,y=$x1,$y1
[/have_unit]
[/not]
[/show_if]
[filter_location]
[/filter_location]
[command]
{NAMED_LOYAL_UNIT $side_number (Troll) $x1 $y1 (MagicTroll) ("Magic Troll")}
[fire_event]
name=apply_troll_skin
[primary_unit]
x=$x1
y=$y1
[/primary_unit]
[/fire_event]
[/command]
[/set_menu_item]
[lua]
code = << r = wesnoth.fire_wml_menu_item("test3", 3, 3) >>
[/lua]
{ASSERT ([have_unit]
x,y = 3,3
[/have_unit])}
[lua]
code = << r = r and wesnoth.fire_wml_menu_item("test3", 4, 4) >>
[/lua]
{ASSERT ([have_unit]
x,y = 4,4
[/have_unit])}
[lua]
code = << wesnoth.set_variable("result", r) >>
[/lua]
{RETURN {VARIABLE_CONDITIONAL result boolean_equals true}}
[/event]
)}

View file

@ -212,7 +212,7 @@ void wml_menu_item::fire_event(const map_location & event_hex, const game_data &
}
else
{
synced_context::run_in_synced_context("fire_event", replay_helper::get_event(event_name_, event_hex, NULL));
synced_context::run_in_synced_context_if_not_already("fire_event", replay_helper::get_event(event_name_, event_hex, NULL));
}
}

View file

@ -666,6 +666,31 @@ int game_lua_kernel::intf_fire_event(lua_State *L)
return 1;
}
/**
* Fires a wml menu item.
* - Arg 1: id of the item. it is not possible to fire items that don't have ids with this function.
* - Arg 2,3: optional first location.
* - Ret 1: boolean, true indicating that the event was fired successfully
*
* NOTE: This is not an "official" feature, it may currently cause assertion failures if used with
* menu items which have "needs_select". It is not supported right now to use it this way.
* The purpose of this function right now is to make it possible to have automated sanity tests for
* the wml menu items system.
*/
int game_lua_kernel::intf_fire_wml_menu_item(lua_State *L)
{
char const *m = luaL_checkstring(L, 1);
map_location l1;
l1.x = luaL_checkinteger(L, 2) - 1;
l1.y = luaL_checkinteger(L, 3) - 1;
bool b = gamedata().get_wml_menu_items().fire_item(m, l1, gamedata(), game_state_, units());
lua_pushboolean(L, b);
return 1;
}
/**
* Gets a WML variable.
* - Arg 1: string containing the variable name.
@ -3643,6 +3668,7 @@ game_lua_kernel::game_lua_kernel(const config &cfg, CVideo * video, game_state &
{ "find_reach", boost::bind(&game_lua_kernel::intf_find_reach, this, _1 )},
{ "find_vacant_tile", boost::bind(&game_lua_kernel::intf_find_vacant_tile, this, _1 )},
{ "fire_event", boost::bind(&game_lua_kernel::intf_fire_event, this, _1 )},
{ "fire_wml_menu_item", boost::bind(&game_lua_kernel::intf_fire_wml_menu_item, this, _1 )},
{ "float_label", boost::bind(&game_lua_kernel::intf_float_label, this, _1 )},
{ "gamestate_inspector", boost::bind(&game_lua_kernel::intf_gamestate_inspector, this, _1 )},
{ "get_all_vars", boost::bind(&game_lua_kernel::intf_get_all_vars, this, _1 )},

View file

@ -151,6 +151,7 @@ class game_lua_kernel : public lua_kernel_base
int impl_theme_items_set(lua_State *L);
int cfun_wml_action(lua_State *L);
int intf_fire_event(lua_State *L);
int intf_fire_wml_menu_item(lua_State *L);
//private helpers
std::string synced_state();

View file

@ -125,3 +125,9 @@
0 recruit_facing_enemy_two
0 recruit_facing_leader
0 recruit_facing_center
#
# Interface tests
#
0 test_wml_menu_items_1
1 test_wml_menu_items_2
0 test_wml_menu_items_3