Skip to content

Commit

Permalink
add access to unit attacks to lua
Browse files Browse the repository at this point in the history
  • Loading branch information
gfgtdf committed Mar 29, 2015
1 parent f9698dd commit 43c10ec
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 0 deletions.
211 changes: 211 additions & 0 deletions src/scripting/game_lua_kernel.cpp
Expand Up @@ -297,6 +297,16 @@ static int impl_unit_get(lua_State *L)
lua_setmetatable(L, -2);
return 1;
}
if (strcmp(m, "attacks") == 0) {
lua_createtable(L, 1, 0);
lua_pushvalue(L, 1);
// hack: store the unit at -1 becasue we want positive indexes to refers to the attacks.
lua_rawseti(L, -2, -1);
lua_pushlightuserdata(L, uattacksKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
return 1;
}
return_bool_attrib("hidden", u.get_hidden());
return_bool_attrib("petrified", u.incapacitated());
return_bool_attrib("resting", u.resting());
Expand Down Expand Up @@ -402,6 +412,182 @@ static int impl_unit_variables_get(lua_State *L)
luaW_pushscalar(L, u->variables()[m]);
return 1;
}
/**
* Gets the attacks of a unit (__index metamethod).
* - Arg 1: table containing the userdata containing the unit id.
* - Arg 2: index (int) or id (string) identyfying teh units attack.
* - Ret 1: the units attack.
*/
static int impl_unit_attacks_get(lua_State *L)
{
if (!lua_istable(L, 1)) {
return luaL_typerror(L, 1, "unit attacks");
}
lua_rawgeti(L, 1, -1);
const unit_const_ptr u = luaW_tounit(L, -1);
if (!u) {
return luaL_argerror(L, 1, "unknown unit");
}
const attack_type* attack = NULL;
const std::vector<attack_type>& attacks = u->attacks();
if(!lua_isnumber(L,2)) {
std::string attack_id = luaL_checkstring(L, 2);
BOOST_FOREACH(const attack_type& at, attacks) {
if(at.id() == attack_id) {
attack = &at;
break;
}
}
if (attack == NULL) {
//return nil on invalid index, just like lua tables do.
return 0;
}
}
else
{
//
size_t index = luaL_checkinteger(L, 2) - 1;
if (index >= attacks.size()) {
//return nil on invalid index, just like lua tables do.
return 0;
}
attack = &attacks[index];
}

// stack { lua_unit }, id/index, lua_unit
lua_createtable(L, 2, 0);
// stack { lua_unit }, id/index, lua_unit, table
lua_pushvalue(L, -2);
// stack { lua_unit }, id/index, lua_unit, table, lua_unit
lua_rawseti(L, -2, 1);
// stack { lua_unit }, id/index, lua_unit, table
lua_pushstring(L, attack->id().c_str());
// stack { lua_unit }, id/index, lua_unit, table, attack id
lua_rawseti(L, -2, 2);
// stack { lua_unit }, id/index, lua_unit, table
lua_pushlightuserdata(L, uattackKey);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
return 1;
}

/**
* Counts the attacks of a unit (__len metamethod).
* - Arg 1: table containing the userdata containing the unit id.
* - Ret 1: size of unit attacks vector.
*/
static int impl_unit_attacks_len(lua_State *L)
{
if (!lua_istable(L, 1)) {
return luaL_typerror(L, 1, "unit attacks");
}
lua_rawgeti(L, 1, -1);
const unit_const_ptr u = luaW_tounit(L, -1);
if (!u) {
return luaL_argerror(L, 1, "unknown unit");
}
lua_pushinteger(L, u->attacks().size());
return 1;
}

/**
* Gets a propoerty of a units attack (__index metamethod).
* - Arg 1: table containing the userdata containing the unit id. and a string identyfying the attack.
* - Arg 2: string
* - Ret 1:
*/
static int impl_unit_attack_get(lua_State *L)
{
if (!lua_istable(L, 1)) {
return luaL_typerror(L, 1, "unit attack");
}
lua_rawgeti(L, 1, 1);
const unit_const_ptr u = luaW_tounit(L, -1);
if (!u) {
return luaL_argerror(L, 1, "unknown unit");
}
lua_rawgeti(L, 1, 2);
std::string attack_id = luaL_checkstring(L, -1);
char const *m = luaL_checkstring(L, 2);
BOOST_FOREACH(const attack_type& attack, u->attacks())
{
if(attack.id() == attack_id)
{

return_string_attrib("description", attack.name());
return_string_attrib("name", attack.id());
return_string_attrib("type", attack.type());
return_string_attrib("icon", attack.icon());
return_string_attrib("range", attack.range());
// "min_range"
// "max_range"
return_int_attrib("damage", attack.damage());
return_int_attrib("number", attack.num_attacks());
return_int_attrib("attack_weight", attack.attack_weight());
return_int_attrib("defense_weight", attack.defense_weight());
//"accuracy"
return_int_attrib("movement_used", attack.movement_used());
// "parry"
return_cfgref_attrib("specials", attack.specials());
std::string err_msg = "unknown property of attack: ";
err_msg += m;
return luaL_argerror(L, 2, err_msg.c_str());
}
}
return luaL_argerror(L, 1, "invalid attack id");
}

/**
* Gets a propoerty of a units attack (__index metamethod).
* - Arg 1: table containing the userdata containing the unit id. and a string identyfying the attack.
* - Arg 2: string
* - Ret 1:
*/
static int impl_unit_attack_set(lua_State *L)
{
if (!lua_istable(L, 1)) {
return luaL_typerror(L, 1, "unit attack");
}
lua_rawgeti(L, 1, 1);
const unit_ptr u = luaW_tounit(L, -1);
if (!u) {
return luaL_argerror(L, 1, "unknown unit");
}
lua_rawgeti(L, 1, 2);
std::string attack_id = luaL_checkstring(L, -1);
char const *m = luaL_checkstring(L, 2);
BOOST_FOREACH(attack_type& attack, u->attacks())
{
if(attack.id() == attack_id)
{

modify_tstring_attrib("description", attack.set_name(value));
// modify_string_attrib("name", attack.set_id(value));
modify_string_attrib("type", attack.set_type(value));
modify_string_attrib("icon", attack.set_icon(value));
modify_string_attrib("range", attack.set_range(value));
// "min_range"
// "max_range"
modify_int_attrib("damage", attack.set_damage(value));
modify_int_attrib("number", attack.set_num_attacks(value));
modify_int_attrib("attack_weight", attack.set_attack_weight(value));
modify_int_attrib("defense_weight", attack.set_defense_weight(value));
//"accuracy"
modify_int_attrib("movement_used", attack.set_movement_used(value));
// "parry"

if (strcmp(m, "specials") == 0) { \
attack.set_specials(luaW_checkconfig(L, 3));
return 0;
}
return_cfgref_attrib("specials", attack.specials());
std::string err_msg = "unknown modifyable property of attack: ";
err_msg += m;
return luaL_argerror(L, 2, err_msg.c_str());
}
}
return luaL_argerror(L, 1, "invalid attack id");
}

/**
* Sets the variable of a unit (__newindex metamethod).
Expand Down Expand Up @@ -3881,6 +4067,31 @@ game_lua_kernel::game_lua_kernel(const config &cfg, CVideo * video, game_state &
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);

// Create the unit attacks metatable.
cmd_log_ << "Adding unit attacks metatable...\n";

lua_pushlightuserdata(L, uattacksKey);
lua_createtable(L, 0, 3);
lua_pushcfunction(L, impl_unit_attacks_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, impl_unit_attacks_len);
lua_setfield(L, -2, "__len");
lua_pushstring(L, "unit attacks");
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);



lua_pushlightuserdata(L, uattackKey);
lua_createtable(L, 0, 3);
lua_pushcfunction(L, impl_unit_attack_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, impl_unit_attack_set);
lua_setfield(L, -2, "__newindex");
lua_pushstring(L, "unit attack");
lua_setfield(L, -2, "__metatable");
lua_rawset(L, LUA_REGISTRYINDEX);

// Create the unit variables metatable.
cmd_log_ << "Adding unit variables metatable...\n";

Expand Down
4 changes: 4 additions & 0 deletions src/scripting/lua_types.cpp
Expand Up @@ -19,9 +19,13 @@ static char const v_executeKey = 0;
static char const v_getunitKey = 0;
static char const v_unitvarKey = 0;
static char const v_ustatusKey = 0;
static char const v_uattacksKey = 0;
static char const v_uattackKey = 0;


luatypekey const executeKey = static_cast<void *>(const_cast<char *>(&v_executeKey));
luatypekey const getunitKey = static_cast<void *>(const_cast<char *>(&v_getunitKey));
luatypekey const unitvarKey = static_cast<void *>(const_cast<char *>(&v_unitvarKey));
luatypekey const ustatusKey = static_cast<void *>(const_cast<char *>(&v_ustatusKey));
luatypekey const uattacksKey = static_cast<void *>(const_cast<char *>(&v_uattacksKey));
luatypekey const uattackKey = static_cast<void *>(const_cast<char *>(&v_uattackKey));
2 changes: 2 additions & 0 deletions src/scripting/lua_types.hpp
Expand Up @@ -23,5 +23,7 @@ extern luatypekey const executeKey;
extern luatypekey const getunitKey;
extern luatypekey const unitvarKey;
extern luatypekey const ustatusKey;
extern luatypekey const uattacksKey;
extern luatypekey const uattackKey;

#endif
18 changes: 18 additions & 0 deletions src/unit_attack_type.hpp
Expand Up @@ -46,6 +46,23 @@ class attack_type
int num_attacks() const { return num_attacks_; }
double attack_weight() const { return attack_weight_; }
double defense_weight() const { return defense_weight_; }
const config specials() const { return specials_; }

void set_name(const t_string& value) { description_ = value; }
// void set_id(const std::string& value) { return id = value; }
void set_type(const std::string& value) { type_ = value; }
void set_icon(const std::string& value) { icon_ = value; }
void set_range(const std::string& value) { range_ = value; }
// void set_min_range(int value) { min_range_ = value; }
// void set_max_range(int value) { max_range_ = value; }
// void set_accuracy(int value) { accuracy_ = value; }
// void set_parry(int value) { parry_ = value; }
void set_damage(int value) { damage_ = value; }
void set_num_attacks(int value) { num_attacks_ = value; }
void set_attack_weight(double value) { attack_weight_ = value; }
void set_defense_weight(double value) { defense_weight_ = value; }
void set_specials(config value) { specials_ = value; }


// In unit_abilities.cpp:

Expand All @@ -70,6 +87,7 @@ class attack_type
bool describe_modification(const config& cfg,std::string* description);

int movement_used() const { return movement_used_; }
void set_movement_used(int value) { movement_used_ = value; }

void write(config& cfg) const;
inline config to_config() const { config c; write(c); return c; }
Expand Down

0 comments on commit 43c10ec

Please sign in to comment.