JCUAPVDH47W6LG4LU6S4QP6FZJJ2NVXJ6LKFSBMVY3AWMC2PALIAC
N276A6EITTZ5F6LCJDHUJIHPS5KZ4S37DE2ZO72AZBXZ6PFNV4NQC
WNC5SY6P2PBCU62Q2DB5J2M4HPDS5EJY76ZEPHRGGCLJ4BSLBSSQC
WQBSKRTHZRKIYIDHROBSIEHEEQX26UAFDTMYY24UOPYNMYWXDFCAC
LPTP6ZL7U4OVXLZ56TJKJ6HENDHE7ITFMFBXC5BKEBVXEGXPW44AC
MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC
UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC
CJKLBIIM2ZTWTLGISXEZOGK2JANEYUSLOKG3BBOAYAY7AFG33ELQC
3A5FX3Y4RPKWQEHKKXZKXZJ7RKV6RKWT7GTR4WFE5UBWKV2HT4RQC
W52PCSHX72WAMWKG6L4BPUBVMO6E72KYYBNKAA7554KNOTY6V7WQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
SSCG2FLJMUTTIRXBFSPLAUUBUIN375ZGL5UOAF3SC62ZIILSMMKAC
NKONHW4JNY6HP2M63MNPM3H64ZWSUNUT5FX2STW4KTS4AMXJXXVQC
MT3256427VMCV4JUFWCN7ULY4KXSND5ZL5THDKYNWWYOXXR5DLIQC
5PE244O6RR2LB5YNIHPXYMOUYCDR4WIAQNV4DRPRZBXNGEC2K4XQC
RA7UG6FR2WA4AWD3PW4Z25PKPP6ZX3LOA3V55CZHJHBH677MTUCQC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
EGOIFEAXIWSCOQ5RHOXNA45JN6HNUI2KOPLGWGPJSXA7EXIAJ6QQC
ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC
YFJLINBBEHE7RBETTARSYNWSO6QJ6MSPXFMSPSH2742QFC3L55SQC
#include "AppHdr.h"
#include "clua.h"
#include "l_libs.h"
#include "delay.h"
#include "mon-util.h"
#include "monstuff.h"
/////////////////////////////////////////////////////////////////////
// Monster handling
#define MONS_METATABLE "monster.monsaccess"
struct MonsterWrap
{
monsters *mons;
long turn;
};
void push_monster(lua_State *ls, monsters *mons)
{
MonsterWrap *mw = clua_new_userdata< MonsterWrap >(ls, MONS_METATABLE);
mw->turn = you.num_turns;
mw->mons = mons;
}
#define MDEF(name) \
static int l_mons_##name(lua_State *ls, monsters *mons, \
const char *attr) \
#define MDEFN(name, closure) \
static int l_mons_##name(lua_State *ls, monsters *mons, const char *attrs) \
{ \
lua_pushlightuserdata(ls, mons); \
lua_pushcclosure(ls, l_mons_do_dismiss, 1); \
return (1); \
}
MDEF(name)
{
PLUARET(string, mons_type_name(mons->type, DESC_PLAIN).c_str());
}
MDEF(x)
{
PLUARET(number, int(mons->pos().x) - int(you.pos().x));
}
MDEF(y)
{
PLUARET(number, int(mons->pos().y) - int(you.pos().y));
}
MDEF(hd)
{
PLUARET(number, mons->hit_dice);
}
static const char *_monuse_names[] =
{
"nothing", "open_doors", "starting_equipment", "weapons_armour",
"magic_items"
};
static const char *_monuse_to_str(mon_itemuse_type utyp)
{
COMPILE_CHECK(ARRAYSZ(_monuse_names) == NUM_MONUSE, c1);
return _monuse_names[utyp];
}
MDEF(muse)
{
if (const monsterentry *me = mons->find_monsterentry())
{
PLUARET(string, _monuse_to_str(me->gmon_use));
}
return (0);
}
static const char *_moneat_names[] =
{
"nothing", "items", "corpses", "food"
};
static const char *_moneat_to_str(mon_itemeat_type etyp)
{
COMPILE_CHECK(ARRAYSZ(_moneat_names) == NUM_MONEAT, c1);
return _moneat_names[etyp];
}
MDEF(meat)
{
if (const monsterentry *me = mons->find_monsterentry())
{
PLUARET(string, _moneat_to_str(me->gmon_eat));
}
return (0);
}
static int l_mons_do_dismiss(lua_State *ls)
{
// dismiss is only callable from dlua, not from managed VMs (i.e.
// end-user scripts cannot dismiss monsters).
ASSERT_DLUA;
monsters *mons =
util_get_userdata<monsters>(ls, lua_upvalueindex(1));
if (mons->alive())
{
mons->flags |= MF_HARD_RESET;
monster_die(mons, KILL_DISMISSED, NON_MONSTER);
}
return (0);
}
MDEFN(dismiss, do_dismiss)
MDEF(experience)
{
ASSERT_DLUA;
PLUARET(number, exper_value(mons));
}
struct MonsAccessor
{
const char *attribute;
int (*accessor)(lua_State *ls, monsters *mons, const char *attr);
};
static MonsAccessor mons_attrs[] =
{
{ "name", l_mons_name },
{ "x" , l_mons_x },
{ "y" , l_mons_y },
{ "hd" , l_mons_hd },
{ "muse", l_mons_muse },
{ "meat", l_mons_meat },
{ "dismiss", l_mons_dismiss },
{ "experience", l_mons_experience },
};
static int monster_get(lua_State *ls)
{
MonsterWrap *mw = clua_get_userdata< MonsterWrap >(ls, MONS_METATABLE);
if (!mw || mw->turn != you.num_turns || !mw->mons)
return (0);
const char *attr = luaL_checkstring(ls, 2);
if (!attr)
return (0);
for (unsigned i = 0; i < sizeof(mons_attrs) / sizeof(mons_attrs[0]); ++i)
{
if (!strcmp(attr, mons_attrs[i].attribute))
return (mons_attrs[i].accessor(ls, mw->mons, attr));
}
return (0);
}
static const char *_monster_behaviour_names[] = {
"sleep",
"wander",
"seek",
"flee",
"cornered",
"panic",
"lurk"
};
static beh_type behaviour_by_name(const std::string &name) {
ASSERT(ARRAYSZ(_monster_behaviour_names) == NUM_BEHAVIOURS);
for (unsigned i = 0; i < ARRAYSZ(_monster_behaviour_names); ++i)
if (name == _monster_behaviour_names[i])
return static_cast<beh_type>(i);
return NUM_BEHAVIOURS;
}
static int monster_set(lua_State *ls)
{
// Changing monster behaviour is for the dungeon builder only,
// never for user scripts.
ASSERT_DLUA;
MonsterWrap *mw = clua_get_userdata< MonsterWrap >(ls, MONS_METATABLE);
if (!mw || !mw->mons)
return (0);
const char *attr = luaL_checkstring(ls, 2);
if (!attr)
return (0);
if (!strcmp(attr, "beh")) {
const beh_type beh =
lua_isnumber(ls, 3) ?
static_cast<beh_type>(luaL_checkint(ls, 3)) :
lua_isstring(ls, 3) ? behaviour_by_name(lua_tostring(ls, 3)) :
NUM_BEHAVIOURS;
if (beh != NUM_BEHAVIOURS)
mw->mons->behaviour = beh;
}
return (0);
}
static int mons_behaviour(lua_State *ls) {
if (lua_gettop(ls) < 1)
return (0);
if (lua_isnumber(ls, 1)) {
lua_pushvalue(ls, 1);
return (1);
}
else if (lua_isstring(ls, 1)) {
const beh_type beh = behaviour_by_name(lua_tostring(ls, 1));
if (beh != NUM_BEHAVIOURS) {
lua_pushnumber(ls, beh);
return (1);
}
}
return (0);
}
static const struct luaL_reg mons_lib[] =
{
{ "behaviour", mons_behaviour },
{ NULL, NULL }
};
void cluaopen_monsters(lua_State *ls)
{
luaL_newmetatable(ls, MONS_METATABLE);
lua_pushstring(ls, "__index");
lua_pushcfunction(ls, monster_get);
lua_settable(ls, -3);
lua_pushstring(ls, "__newindex");
lua_pushcfunction(ls, monster_set);
lua_settable(ls, -3);
// Pop the metatable off the stack.
lua_pop(ls, 1);
luaL_openlib(ls, "mons", mons_lib, 0);
}
}
/////////////////////////////////////////////////////////////////////
// Monster handling
#define MONS_METATABLE "monster.monsaccess"
struct MonsterWrap
{
monsters *mons;
long turn;
};
#define MDEF(name) \
static int l_mons_##name(lua_State *ls, monsters *mons, \
const char *attr) \
#define MDEFN(name, closure) \
static int l_mons_##name(lua_State *ls, monsters *mons, const char *attrs) \
{ \
lua_pushlightuserdata(ls, mons); \
lua_pushcclosure(ls, l_mons_do_dismiss, 1); \
return (1); \
}
MDEF(name)
{
PLUARET(string, mons_type_name(mons->type, DESC_PLAIN).c_str());
}
MDEF(x)
{
PLUARET(number, int(mons->pos().x) - int(you.pos().x));
}
MDEF(y)
{
PLUARET(number, int(mons->pos().y) - int(you.pos().y));
}
MDEF(hd)
{
PLUARET(number, mons->hit_dice);
}
static const char *_monuse_names[] =
{
"nothing", "open_doors", "starting_equipment", "weapons_armour",
"magic_items"
};
static const char *_monuse_to_str(mon_itemuse_type utyp)
{
COMPILE_CHECK(ARRAYSZ(_monuse_names) == NUM_MONUSE, c1);
return _monuse_names[utyp];
}
MDEF(muse)
{
if (const monsterentry *me = mons->find_monsterentry())
{
PLUARET(string, _monuse_to_str(me->gmon_use));
}
return (0);
}
static const char *_moneat_names[] =
{
"nothing", "items", "corpses", "food"
};
static const char *_moneat_to_str(mon_itemeat_type etyp)
{
COMPILE_CHECK(ARRAYSZ(_moneat_names) == NUM_MONEAT, c1);
return _moneat_names[etyp];
}
MDEF(meat)
{
if (const monsterentry *me = mons->find_monsterentry())
{
PLUARET(string, _moneat_to_str(me->gmon_eat));
}
return (0);
}
static int l_mons_do_dismiss(lua_State *ls)
{
// dismiss is only callable from dlua, not from managed VMs (i.e.
// end-user scripts cannot dismiss monsters).
ASSERT_DLUA;
monsters *mons =
util_get_userdata<monsters>(ls, lua_upvalueindex(1));
if (mons->alive())
{
mons->flags |= MF_HARD_RESET;
monster_die(mons, KILL_DISMISSED, NON_MONSTER);
}
return (0);
}
MDEFN(dismiss, do_dismiss)
MDEF(experience)
{
ASSERT_DLUA;
PLUARET(number, exper_value(mons));
}
struct MonsAccessor
{
const char *attribute;
int (*accessor)(lua_State *ls, monsters *mons, const char *attr);
};
static MonsAccessor mons_attrs[] =
{
{ "name", l_mons_name },
{ "x" , l_mons_x },
{ "y" , l_mons_y },
{ "hd" , l_mons_hd },
{ "muse", l_mons_muse },
{ "meat", l_mons_meat },
{ "dismiss", l_mons_dismiss },
{ "experience", l_mons_experience },
};
static int monster_get(lua_State *ls)
{
MonsterWrap *mw = clua_get_userdata< MonsterWrap >(ls, MONS_METATABLE);
if (!mw || mw->turn != you.num_turns || !mw->mons)
return (0);
const char *attr = luaL_checkstring(ls, 2);
if (!attr)
return (0);
for (unsigned i = 0; i < sizeof(mons_attrs) / sizeof(mons_attrs[0]); ++i)
{
if (!strcmp(attr, mons_attrs[i].attribute))
return (mons_attrs[i].accessor(ls, mw->mons, attr));
}
return (0);
}
static const char *_monster_behaviour_names[] = {
"sleep",
"wander",
"seek",
"flee",
"cornered",
"panic",
"lurk"
};
static beh_type behaviour_by_name(const std::string &name) {
ASSERT(ARRAYSZ(_monster_behaviour_names) == NUM_BEHAVIOURS);
for (unsigned i = 0; i < ARRAYSZ(_monster_behaviour_names); ++i)
if (name == _monster_behaviour_names[i])
return static_cast<beh_type>(i);
return NUM_BEHAVIOURS;
MonsterWrap *mw = clua_get_userdata< MonsterWrap >(ls, MONS_METATABLE);
if (!mw || !mw->mons)
return (0);
const char *attr = luaL_checkstring(ls, 2);
if (!attr)
return (0);
if (!strcmp(attr, "beh")) {
const beh_type beh =
lua_isnumber(ls, 3) ?
static_cast<beh_type>(luaL_checkint(ls, 3)) :
lua_isstring(ls, 3) ? behaviour_by_name(lua_tostring(ls, 3)) :
NUM_BEHAVIOURS;
if (beh != NUM_BEHAVIOURS)
mw->mons->behaviour = beh;
}
return (0);
}
}
void push_monster(lua_State *ls, monsters *mons)
{
MonsterWrap *mw = clua_new_userdata< MonsterWrap >(ls, MONS_METATABLE);
mw->turn = you.num_turns;
mw->mons = mons;
if (lua_isnumber(ls, 1)) {
lua_pushvalue(ls, 1);
return (1);
}
else if (lua_isstring(ls, 1)) {
const beh_type beh = behaviour_by_name(lua_tostring(ls, 1));
if (beh != NUM_BEHAVIOURS) {
lua_pushnumber(ls, beh);
return (1);
}
}
return (0);
}
static const struct luaL_reg mons_lib[] =
{
{ "behaviour", mons_behaviour },
{ NULL, NULL }
};
void luaopen_monsters(lua_State *ls)
{
luaL_newmetatable(ls, MONS_METATABLE);
lua_pushstring(ls, "__index");
lua_pushcfunction(ls, monster_get);
lua_settable(ls, -3);
lua_pushstring(ls, "__newindex");
lua_pushcfunction(ls, monster_set);
lua_settable(ls, -3);
// Pop the metatable off the stack.
lua_pop(ls, 1);
luaL_openlib(ls, "mons", mons_lib, 0);
}