Merge pull request #499 from CelticMinstrel/lua-unit

Lua API changes (mainly relating to units)
This commit is contained in:
CelticMinstrel 2015-10-03 21:13:04 -04:00
commit 33385f97b8
5 changed files with 209 additions and 22 deletions

View file

@ -576,7 +576,7 @@ function wml_actions.store_unit(cfg)
for i,u in ipairs(units) do
utils.vwriter.write(writer, u.__cfg)
if kill_units then wesnoth.put_unit(u.x, u.y) end
if kill_units then wesnoth.erase_unit(u) end
end
if (not filter.x or filter.x == "recall") and (not filter.y or filter.y == "recall") then
@ -585,7 +585,7 @@ function wml_actions.store_unit(cfg)
ucfg.x = "recall"
ucfg.y = "recall"
utils.vwriter.write(writer, ucfg)
if kill_units then wesnoth.extract_unit(u) end
if kill_units then wesnoth.erase_unit(u) end
end
end
end
@ -851,7 +851,7 @@ function wml_actions.petrify(cfg)
unit.status.petrified = true
-- Extract unit and put it back to update animation (not needed for recall units)
wesnoth.extract_unit(unit)
wesnoth.put_unit(unit, unit.x, unit.y)
wesnoth.put_unit(unit)
end
for index, unit in ipairs(wesnoth.get_recall_units(cfg)) do
@ -864,7 +864,7 @@ function wml_actions.unpetrify(cfg)
unit.status.petrified = false
-- Extract unit and put it back to update animation (not needed for recall units)
wesnoth.extract_unit(unit)
wesnoth.put_unit(unit, unit.x, unit.y)
wesnoth.put_unit(unit)
end
for index, unit in ipairs(wesnoth.get_recall_units(cfg)) do
@ -993,7 +993,7 @@ function wml_actions.harm_unit(cfg)
-- Extract unit and put it back to update animation if status was changed
wesnoth.extract_unit(unit_to_harm)
wesnoth.put_unit(unit_to_harm, unit_to_harm.x, unit_to_harm.y)
wesnoth.put_unit(unit_to_harm)
if add_tab then
text = string.format("%s%s", "\t", text)
@ -1317,7 +1317,7 @@ function wml_actions.put_to_recall_list(cfg)
unit.status.slowed = false
end
wesnoth.put_recall_unit(unit, unit.side)
wesnoth.put_unit(unit.x, unit.y)
wesnoth.erase_unit(unit)
end
end

View file

@ -336,7 +336,8 @@ static int impl_unit_get(lua_State *L)
return_bool_attrib("zoc", u.get_emit_zoc());
return_string_attrib("facing", map_location::write_direction(u.facing()));
return_cfg_attrib("__cfg", u.write(cfg); u.get_location().write(cfg));
return 0;
return lua_kernel_base::get_lua_kernel<game_lua_kernel>(L).return_unit_method(L, m);
}
/**
@ -699,23 +700,48 @@ int game_lua_kernel::intf_gamestate_inspector(lua_State *L)
/**
* Gets the unit at the given location or with the given id.
* - Arg 1: integer.
* - Arg 1: table containing location either at indices 1,2 or at keys x,y.
* OR
* - Arg 1: string ID
* OR
* - Args 1, 2: location.
* - Ret 1: full userdata with __index pointing to impl_unit_get and
* __newindex pointing to impl_unit_set.
*/
int game_lua_kernel::intf_get_unit(lua_State *L)
{
int x = luaL_checkinteger(L, 1) - 1;
int y = luaL_optint(L, 2, 0) - 1;
unit_map::const_iterator ui;
int x, y;
if (lua_isnoneornil(L, 2)) {
ui = units().find(x + 1);
if (lua_istable(L, 1)) {
lua_rawgeti(L, 1, 1);
if (lua_isnoneornil(L, -1)) {
lua_getfield(L, 1, "x");
x = luaL_checkinteger(L, -1) - 1;
lua_getfield(L, 1, "y");
y = luaL_checkinteger(L, -1) - 1;
} else {
x = luaL_checkinteger(L, -1) - 1;
lua_rawgeti(L, 1, 2);
y = luaL_checkinteger(L, -1) - 1;
}
} else if(lua_isstring(L, 1)) {
// Forward to wesnoth.get_units and return the first result
luaW_getglobal(L, "wesnoth", "get_units", NULL);
lua_newtable(L);
lua_pushstring(L, "id");
lua_pushvalue(L, 1);
lua_rawset(L, -3);
lua_call(L, 1, 1);
lua_rawgeti(L, -1, 1);
return 1;
} else {
return luaL_argerror(L, 1, "expected string, location table, or integer");
}
} else {
ui = units().find(map_location(x, y));
x = luaL_checkinteger(L, 1) - 1;
y = luaL_checkinteger(L, 2) - 1;
}
unit_map::const_iterator ui = units().find(map_location(x, y));
if (!ui.valid()) return 0;
@ -1633,12 +1659,12 @@ int game_lua_kernel::impl_current_get(lua_State *L)
*/
int game_lua_kernel::intf_message(lua_State *L)
{
char const *m = luaL_checkstring(L, 1);
char const *h = m;
t_string m = luaW_checktstring(L, 1);
t_string h = m;
if (lua_isnone(L, 2)) {
h = "Lua";
} else {
m = luaL_checkstring(L, 2);
m = luaW_checktstring(L, 2);
}
lua_chat(h, m);
LOG_LUA << "Script says: \"" << m << "\"\n";
@ -2384,7 +2410,10 @@ int game_lua_kernel::intf_print(lua_State *L) {
/**
* Places a unit on the map.
* - Args 1,2: (optional) location.
* - Arg 3: WML table describing a unit, or nothing/nil to delete.
* - Arg 3: Unit (WML table or proxy), or nothing/nil to delete.
* OR
* - Arg 1: Unit (WML table or proxy)
* - Args 2,3: (optional) location
*/
int game_lua_kernel::intf_put_unit(lua_State *L)
{
@ -2397,8 +2426,15 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
unit_arg = 3;
loc.x = lua_tointeger(L, 1) - 1;
loc.y = luaL_checkinteger(L, 2) - 1;
if (!map().on_board(loc))
if (!map().on_board(loc)) {
return luaL_argerror(L, 1, "invalid location");
}
} else if (lua_isnumber(L, 2)) {
loc.x = lua_tointeger(L, 2) - 1;
loc.y = luaL_checkinteger(L, 3) - 1;
if (!map().on_board(loc)) {
return luaL_argerror(L, 1, "invalid location");
}
}
if (luaW_hasmetatable(L, unit_arg, getunitKey))
@ -2409,10 +2445,12 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
if (lu->on_map() && (unit_arg == 1 || u->get_location() == loc)) {
return 0;
}
if (unit_arg == 1) {
if (!loc.valid()) {
loc = u->get_location();
if (!map().on_board(loc))
return luaL_argerror(L, 1, "invalid location");
} else {
WRN_LUA << "wesnoth.put_unit(x, y, unit) is deprecated. Use wesnoth.put_unit(unit, x, y) instead\n";
}
}
else if (!lua_isnoneornil(L, unit_arg))
@ -2423,6 +2461,8 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
loc.y = cfg["y"] - 1;
if (!map().on_board(loc))
return luaL_argerror(L, 1, "invalid location");
} else {
WRN_LUA << "wesnoth.put_unit(x, y, unit) is deprecated. Use wesnoth.put_unit(unit, x, y) instead\n";
}
u = unit_ptr (new unit(cfg, true));
}
@ -2431,8 +2471,14 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
game_display_->invalidate(loc);
}
if (!u) {
if (unit_arg == 3) {
WRN_LUA << "wesnoth.put_unit(x, y) is deprecated. Use wesnoth.erase_unit(x, y) instead\n";
units().erase(loc);
}
return 0;
}
units().erase(loc);
if (!u) return 0;
if (lu) {
lu->put_map(loc);
@ -2445,6 +2491,55 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
return 0;
}
/**
* Erases a unit from the map
* - Arg 1: Unit to erase
* OR
* - Args 1,2: Location to erase unit
*/
int game_lua_kernel::intf_erase_unit(lua_State *L)
{
map_location loc;
if (lua_isnumber(L, 1)) {
loc.x = lua_tointeger(L, 2) - 1;
loc.y = luaL_checkinteger(L, 3) - 1;
if (!map().on_board(loc)) {
return luaL_argerror(L, 1, "invalid location");
}
} else if (luaW_hasmetatable(L, 1, getunitKey)) {
lua_unit *lu = static_cast<lua_unit *>(lua_touserdata(L, 1));
unit_ptr u = lu->get();
if (!lu->get()) {
return luaL_argerror(L, 1, "unit not found");
}
if (lu->on_map()) {
loc = u->get_location();
if (!map().on_board(loc)) {
return luaL_argerror(L, 1, "invalid location");
}
} else if (int side = lu->on_recall_list()) {
team &t = teams()[side - 1];
// Should it use underlying ID instead?
t.recall_list().erase_if_matches_id(u->id());
} else {
return luaL_argerror(L, 1, "can't erase private units");
}
} else if (!lua_isnoneornil(L, 1)) {
config cfg = luaW_checkconfig(L, 1);
loc.x = cfg["x"] - 1;
loc.y = cfg["y"] - 1;
if (!map().on_board(loc)) {
return luaL_argerror(L, 1, "invalid location");
}
} else {
return luaL_argerror(L, 1, "expected unit or integer");
}
units().erase(loc);
return 0;
}
/**
* Puts a unit on a recall list.
* - Arg 1: WML table or unit.
@ -2636,6 +2731,36 @@ static int intf_unit_movement_cost(lua_State *L)
return 1;
}
/**
* Returns unit vision cost on a given terrain.
* - Arg 1: unit userdata.
* - Arg 2: string containing the terrain type.
* - Ret 1: integer.
*/
static int intf_unit_vision_cost(lua_State *L)
{
const unit_const_ptr u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
t_translation::t_terrain t = t_translation::read_terrain_code(m);
lua_pushinteger(L, u->vision_cost(t));
return 1;
}
/**
* Returns unit jamming cost on a given terrain.
* - Arg 1: unit userdata.
* - Arg 2: string containing the terrain type.
* - Ret 1: integer.
*/
static int intf_unit_jamming_cost(lua_State *L)
{
const unit_const_ptr u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
t_translation::t_terrain t = t_translation::read_terrain_code(m);
lua_pushinteger(L, u->jamming_cost(t));
return 1;
}
/**
* Returns unit defense on a given terrain.
* - Arg 1: unit userdata.
@ -4193,6 +4318,8 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
{ "unit_ability", &intf_unit_ability },
{ "unit_defense", &intf_unit_defense },
{ "unit_movement_cost", &intf_unit_movement_cost },
{ "unit_vision_cost", &intf_unit_vision_cost },
{ "unit_jamming_cost", &intf_unit_jamming_cost },
{ "unit_resistance", &intf_unit_resistance },
{ "unsynced", &intf_do_unsynced },
{ "add_event_handler", &dispatch<&game_lua_kernel::intf_add_event > },
@ -4208,6 +4335,7 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
{ "delay", &dispatch<&game_lua_kernel::intf_delay > },
{ "end_turn", &dispatch<&game_lua_kernel::intf_end_turn > },
{ "end_level", &dispatch<&game_lua_kernel::intf_end_level > },
{ "erase_unit", &dispatch<&game_lua_kernel::intf_erase_unit > },
{ "extract_unit", &dispatch<&game_lua_kernel::intf_extract_unit > },
{ "find_cost_map", &dispatch<&game_lua_kernel::intf_find_cost_map > },
{ "find_path", &dispatch<&game_lua_kernel::intf_find_path > },
@ -4506,6 +4634,35 @@ void game_lua_kernel::initialize(const config& level)
load_game(level);
}
int game_lua_kernel::return_unit_method(lua_State *L, char const *m) {
static luaL_Reg const methods[] = {
{"matches", &dispatch<&game_lua_kernel::intf_match_unit>},
{"to_recall", &dispatch<&game_lua_kernel::intf_put_recall_unit>},
{"to_map", &dispatch<&game_lua_kernel::intf_put_unit>},
{"erase", &dispatch<&game_lua_kernel::intf_erase_unit>},
{"clone", intf_copy_unit},
{"extract", &dispatch<&game_lua_kernel::intf_extract_unit>},
{"advance", intf_advance_unit},
{"add_modification", intf_add_modification},
{"resistance", intf_unit_resistance},
{"defense", intf_unit_defense},
{"movement", intf_unit_movement_cost},
{"vision", intf_unit_movement_cost},
{"jamming", intf_unit_movement_cost},
{"ability", intf_unit_ability},
{"transform", intf_transform_unit},
};
BOOST_FOREACH(const luaL_Reg& r, methods) {
if (strcmp(m, r.name) == 0) {
lua_pushcfunction(L, r.func);
return 1;
}
}
return 0;
}
void game_lua_kernel::set_game_display(game_display * gd) {
game_display_ = gd;
if (gd) {

View file

@ -115,6 +115,7 @@ class game_lua_kernel : public lua_kernel_base
int intf_play_sound(lua_State *L);
int intf_print(lua_State *L);
int intf_put_unit(lua_State *L);
int intf_erase_unit(lua_State *L);
int intf_put_recall_unit(lua_State *L);
int intf_extract_unit(lua_State *L);
int intf_find_vacant_tile(lua_State *L);
@ -184,6 +185,7 @@ public:
ai::lua_ai_context* create_lua_ai_context(char const *code, ai::engine_lua *engine);
ai::lua_ai_action_handler* create_lua_ai_action_handler(char const *code, ai::lua_ai_context &context);
int return_unit_method(lua_State *L, char const *m);
};
#endif

View file

@ -54,6 +54,24 @@ static int impl_race_get(lua_State* L)
return_bool_attrib("ignore_global_traits", !race.uses_global_traits());
return_string_attrib("undead_variation", race.undead_variation());
return_cfgref_attrib("__cfg", race.get_cfg());
if (strcmp(m, "traits") == 0) {
lua_newtable(L);
if (race.uses_global_traits()) {
BOOST_FOREACH(const config& trait, unit_types.traits()) {
const std::string& id = trait["id"];
lua_pushlstring(L, id.c_str(), id.length());
luaW_pushconfig(L, trait);
lua_rawset(L, -3);
}
}
BOOST_FOREACH(const config& trait, race.additional_traits()) {
const std::string& id = trait["id"];
lua_pushlstring(L, id.c_str(), id.length());
luaW_pushconfig(L, trait);
lua_rawset(L, -3);
}
return 1;
}
return 0;
}

View file

@ -54,6 +54,16 @@ static int impl_unit_type_get(lua_State *L)
return_int_attrib("level", ut.level());
return_int_attrib("recall_cost", ut.recall_cost());
return_cfgref_attrib("__cfg", ut.get_cfg());
if (strcmp(m, "traits") == 0) {
lua_newtable(L);
BOOST_FOREACH(const config& trait, ut.possible_traits()) {
const std::string& id = trait["id"];
lua_pushlstring(L, id.c_str(), id.length());
luaW_pushconfig(L, trait);
lua_rawset(L, -3);
}
return 1;
}
return 0;
}