forked from github/server
1083 lines
29 KiB
C
1083 lines
29 KiB
C
#ifdef _MSC_VER
|
|
#include <platform.h>
|
|
#endif
|
|
|
|
#include "bind_unit.h"
|
|
#include "alchemy.h"
|
|
#include "bindings.h"
|
|
#include "move.h"
|
|
#include "reports.h"
|
|
#include "guard.h"
|
|
|
|
/* attributes includes */
|
|
#include <attributes/racename.h>
|
|
#include <attributes/key.h>
|
|
|
|
/* kernel includes */
|
|
#include <kernel/building.h>
|
|
#include <kernel/config.h>
|
|
#include <kernel/curse.h>
|
|
#include "kernel/equipment.h"
|
|
#include <kernel/faction.h>
|
|
#include <kernel/group.h>
|
|
#include <kernel/item.h>
|
|
#include <kernel/messages.h>
|
|
#include <kernel/order.h>
|
|
#include <kernel/pool.h>
|
|
#include <kernel/race.h>
|
|
#include <kernel/region.h>
|
|
#include <kernel/spellbook.h>
|
|
#include <kernel/ship.h>
|
|
#include <kernel/spell.h>
|
|
#include <kernel/unit.h>
|
|
|
|
/* util includes */
|
|
#include <util/attrib.h>
|
|
#include <util/base36.h>
|
|
#include <util/event.h>
|
|
#include <util/lists.h>
|
|
#include <util/log.h>
|
|
#include <util/macros.h>
|
|
|
|
#include <selist.h>
|
|
|
|
#include <tolua.h>
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
|
|
static int tolua_bufunit(lua_State * L) {
|
|
unit *u = (unit *)tolua_tousertype(L, 1, 0);
|
|
if (u) {
|
|
faction *f = (faction *)tolua_tousertype(L, 2, u->faction);
|
|
if (f) {
|
|
char buf[8192];
|
|
int mode = (int)tolua_tonumber(L, 3, (int)seen_unit);
|
|
bufunit(f, u, mode, buf, sizeof(buf));
|
|
tolua_pushstring(L, buf);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
int tolua_unitlist_nextf(lua_State * L)
|
|
{
|
|
unit **unit_ptr = (unit **)lua_touserdata(L, lua_upvalueindex(1));
|
|
unit *u = *unit_ptr;
|
|
if (u != NULL) {
|
|
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
|
|
*unit_ptr = u->nextF;
|
|
return 1;
|
|
}
|
|
else
|
|
return 0; /* no more values to return */
|
|
}
|
|
|
|
int tolua_unitlist_nextb(lua_State * L)
|
|
{
|
|
unit **unit_ptr = (unit **)lua_touserdata(L, lua_upvalueindex(1));
|
|
unit *u = *unit_ptr;
|
|
if (u != NULL) {
|
|
unit *unext = u->next;
|
|
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
|
|
|
|
while (unext && unext->building != u->building) {
|
|
unext = unext->next;
|
|
}
|
|
*unit_ptr = unext;
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
return 0; /* no more values to return */
|
|
}
|
|
|
|
int tolua_unitlist_nexts(lua_State * L)
|
|
{
|
|
unit **unit_ptr = (unit **)lua_touserdata(L, lua_upvalueindex(1));
|
|
unit *u = *unit_ptr;
|
|
if (u != NULL) {
|
|
unit *unext = u->next;
|
|
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
|
|
|
|
while (unext && unext->ship != u->ship) {
|
|
unext = unext->next;
|
|
}
|
|
*unit_ptr = unext;
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
return 0; /* no more values to return */
|
|
}
|
|
|
|
int tolua_unitlist_next(lua_State * L)
|
|
{
|
|
unit **unit_ptr = (unit **)lua_touserdata(L, lua_upvalueindex(1));
|
|
unit *u = *unit_ptr;
|
|
if (u != NULL) {
|
|
tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit");
|
|
*unit_ptr = u->next;
|
|
return 1;
|
|
}
|
|
else
|
|
return 0; /* no more values to return */
|
|
}
|
|
|
|
static int tolua_unit_get_group(lua_State * L)
|
|
{
|
|
unit *u = (unit *)tolua_tousertype(L, 1, 0);
|
|
group *g = get_group(u);
|
|
if (g) {
|
|
tolua_pushstring(L, g->name);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_set_group(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
group *g = join_group(self, tolua_tostring(L, 2, 0));
|
|
lua_pushboolean(L, g!=NULL);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_name(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
tolua_pushstring(L, unit_getname(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_name(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
unit_setname(self, tolua_tostring(L, 2, 0));
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_info(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
tolua_pushstring(L, unit_getinfo(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_info(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
unit_setinfo(self, tolua_tostring(L, 2, 0));
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_id(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, unit_getid(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_id(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
unit_setid(self, (int)tolua_tonumber(L, 2, 0));
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_auramax(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, max_spellpoints(self->region, self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_hpmax(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, unit_max_hp(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_hp(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, unit_gethp(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_hp(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
unit_sethp(self, (int)tolua_tonumber(L, 2, 0));
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_number(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, self->number);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_number(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
int number = (int)tolua_tonumber(L, 2, 0);
|
|
if (self->number == 0) {
|
|
set_number(self, number);
|
|
self->hp = unit_max_hp(self) * number;
|
|
}
|
|
else {
|
|
scale_number(self, number);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_flags(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, self->flags);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_flags(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
self->flags = (int)tolua_tonumber(L, 2, 0);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_guard(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushboolean(L, is_guard(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_guard(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
unsigned int flags = (unsigned int)tolua_tonumber(L, 2, 0);
|
|
setguard(self, flags!=0);
|
|
return 0;
|
|
}
|
|
|
|
static const char *unit_getmagic(const unit * u)
|
|
{
|
|
sc_mage *mage = get_mage_depr(u);
|
|
return mage ? magic_school[mage->magietyp] : NULL;
|
|
}
|
|
|
|
static int tolua_unit_get_magic(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushstring(L, unit_getmagic(self));
|
|
return 1;
|
|
}
|
|
|
|
static void unit_setmagic(unit * u, const char *type)
|
|
{
|
|
sc_mage *mage = get_mage(u);
|
|
int mtype;
|
|
for (mtype = 0; mtype != MAXMAGIETYP; ++mtype) {
|
|
if (strcmp(magic_school[mtype], type) == 0)
|
|
break;
|
|
}
|
|
if (mtype == MAXMAGIETYP)
|
|
return;
|
|
if (mage == NULL) {
|
|
mage = create_mage(u, (magic_t)mtype);
|
|
}
|
|
}
|
|
|
|
static int tolua_unit_set_magic(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *type = tolua_tostring(L, 2, 0);
|
|
unit_setmagic(self, type);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_aura(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, get_spellpoints(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_aura(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
set_spellpoints(self, (int)tolua_tonumber(L, 2, 0));
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_age(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, self->age);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_age(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
self->age = (int)tolua_tonumber(L, 2, 0);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_status(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, unit_getstatus(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_status(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
unit_setstatus(self, (status_t)tolua_tonumber(L, 2, 0));
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_item(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *iname = tolua_tostring(L, 2, 0);
|
|
int result = -1;
|
|
|
|
if (iname != NULL) {
|
|
const item_type *itype = it_find(iname);
|
|
if (itype != NULL) {
|
|
result = i_get(self->items, itype);
|
|
}
|
|
}
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_effect(lua_State * L)
|
|
{
|
|
const unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *potion_name = tolua_tostring(L, 2, 0);
|
|
int result = -1;
|
|
const item_type *it_potion = it_find(potion_name);
|
|
|
|
if (it_potion != NULL) {
|
|
result = get_effect(self, it_potion);
|
|
}
|
|
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_add_item(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *iname = tolua_tostring(L, 2, 0);
|
|
int number = (int)tolua_tonumber(L, 3, 0);
|
|
int result = -1;
|
|
|
|
if (iname != NULL) {
|
|
const item_type *itype = it_find(iname);
|
|
if (itype != NULL) {
|
|
item *i = i_change(&self->items, itype, number);
|
|
result = i ? i->number : 0;
|
|
}
|
|
}
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_getskill(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *skname = tolua_tostring(L, 2, 0);
|
|
skill_t sk = findskill(skname);
|
|
int value = -1;
|
|
if (sk != NOSKILL) {
|
|
skill *sv = unit_skill(self, sk);
|
|
if (sv) {
|
|
value = sv->level;
|
|
}
|
|
else
|
|
value = 0;
|
|
}
|
|
lua_pushinteger(L, value);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_effskill(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *skname = tolua_tostring(L, 2, 0);
|
|
skill_t sk = findskill(skname);
|
|
int value = (sk == NOSKILL) ? -1 : effskill(self, sk, 0);
|
|
lua_pushinteger(L, value);
|
|
return 1;
|
|
}
|
|
|
|
typedef struct fctr_data {
|
|
unit *target;
|
|
int fhandle;
|
|
} fctr_data;
|
|
|
|
typedef struct event {
|
|
struct event_arg *args;
|
|
char *msg;
|
|
} event;
|
|
|
|
int fctr_handle(struct trigger *tp, void *data)
|
|
{
|
|
trigger *t = tp;
|
|
event evt = { 0 };
|
|
fctr_data *fd = (fctr_data *)t->data.v;
|
|
lua_State *L = (lua_State *)global.vm_state;
|
|
unit *u = fd->target;
|
|
|
|
evt.args = (event_arg *)data;
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, fd->fhandle);
|
|
tolua_pushusertype(L, u, TOLUA_CAST "unit");
|
|
tolua_pushusertype(L, &evt, TOLUA_CAST "event");
|
|
if (lua_pcall(L, 2, 0, 0) != 0) {
|
|
const char *error = lua_tostring(L, -1);
|
|
log_error("event (%s): %s\n", unitname(u), error);
|
|
lua_pop(L, 1);
|
|
tolua_error(L, TOLUA_CAST "event handler call failed", NULL);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void fctr_init(trigger * t)
|
|
{
|
|
t->data.v = calloc(sizeof(fctr_data), 1);
|
|
}
|
|
|
|
static void fctr_done(trigger * t)
|
|
{
|
|
fctr_data *fd = (fctr_data *)t->data.v;
|
|
lua_State *L = (lua_State *)global.vm_state;
|
|
luaL_unref(L, LUA_REGISTRYINDEX, fd->fhandle);
|
|
free(fd);
|
|
}
|
|
|
|
static struct trigger_type tt_lua = {
|
|
"lua_event",
|
|
fctr_init,
|
|
fctr_done,
|
|
fctr_handle
|
|
};
|
|
|
|
static trigger *trigger_lua(struct unit *u, int handle)
|
|
{
|
|
trigger *t = t_new(&tt_lua);
|
|
fctr_data *td = (fctr_data *)t->data.v;
|
|
td->target = u;
|
|
td->fhandle = handle;
|
|
return t;
|
|
}
|
|
|
|
static int tolua_unit_addhandler(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *ename = tolua_tostring(L, 2, 0);
|
|
int handle;
|
|
|
|
lua_pushvalue(L, 3);
|
|
handle = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
add_trigger(&self->attribs, ename, trigger_lua(self, handle));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_addnotice(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *str = tolua_tostring(L, 2, 0);
|
|
|
|
addmessage(self->region, self->faction, str, MSG_MESSAGE, ML_IMPORTANT);
|
|
return 0;
|
|
}
|
|
|
|
static int bind_unit_effect(lua_State * L)
|
|
{
|
|
unit *u = (unit *)tolua_tousertype(L, 1, NULL);
|
|
const char *str = tolua_tostring(L, 2, NULL);
|
|
const item_type *itype = it_find(str);
|
|
if (itype) {
|
|
int effect = get_effect(u, itype);
|
|
lua_pushinteger(L, effect);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void unit_castspell(unit * u, const char *name, int level)
|
|
{
|
|
spell *sp = find_spell(name);
|
|
|
|
if (sp) {
|
|
spellbook *book = unit_get_spellbook(u);
|
|
if (spellbook_get(book, sp)) {
|
|
castorder co;
|
|
create_castorder(&co, u, 0, sp, u->region, level, (double)level, 0, 0, 0);
|
|
cast_spell(&co);
|
|
free_castorder(&co);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int tolua_unit_castspell(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *str = tolua_tostring(L, 2, 0);
|
|
int level = (int)tolua_tonumber(L, 3, 1);
|
|
|
|
unit_castspell(self, str, level);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_addspell(lua_State * L)
|
|
{
|
|
unit *u = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *str = tolua_tostring(L, 2, 0);
|
|
int level = (int)tolua_tonumber(L, 3, 1);
|
|
int err = 0;
|
|
spell *sp = find_spell(str);
|
|
|
|
if (!sp) {
|
|
log_warning("spell %s could not be found\n", str);
|
|
return EINVAL;
|
|
}
|
|
else {
|
|
unit_add_spell(u, 0, sp, level);
|
|
}
|
|
|
|
lua_pushinteger(L, err);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_racename(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *str = tolua_tostring(L, 2, 0);
|
|
|
|
set_racename(&self->attribs, str);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_racename(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
attrib *a = a_find(self->attribs, &at_racename);
|
|
if (a) {
|
|
tolua_pushstring(L, get_racename(a));
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_setskill(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *skname = tolua_tostring(L, 2, 0);
|
|
int level = (int)tolua_tonumber(L, 3, 0);
|
|
skill_t sk = findskill(skname);
|
|
if (sk != NOSKILL) {
|
|
set_level(self, sk, level);
|
|
}
|
|
else {
|
|
level = -1;
|
|
}
|
|
lua_pushinteger(L, level);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_use_pooled(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *iname = tolua_tostring(L, 2, 0);
|
|
int number = (int)tolua_tonumber(L, 3, 0);
|
|
const resource_type *rtype = rt_find(iname);
|
|
int result = -1;
|
|
if (rtype != NULL) {
|
|
result = use_pooled(self, rtype, GET_DEFAULT, number);
|
|
}
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_pooled(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *iname = tolua_tostring(L, 2, 0);
|
|
const resource_type *rtype = rt_find(iname);
|
|
int result = -1;
|
|
if (rtype != NULL) {
|
|
result = get_pooled(self, rtype, GET_DEFAULT, INT_MAX);
|
|
}
|
|
lua_pushinteger(L, result);
|
|
return 1;
|
|
}
|
|
|
|
static unit *unit_getfamiliar(const unit * u)
|
|
{
|
|
attrib *a = a_find(u->attribs, &at_familiar);
|
|
if (a != NULL) {
|
|
return (unit *)a->data.v;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static int tolua_unit_get_familiar(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
tolua_pushusertype(L, unit_getfamiliar(self), TOLUA_CAST "unit");
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_familiar(lua_State * L)
|
|
{
|
|
unit *mag = (unit *)tolua_tousertype(L, 1, NULL);
|
|
unit *fam = (unit *)tolua_tousertype(L, 2, NULL);
|
|
if (fam) {
|
|
set_familiar(mag, fam);
|
|
}
|
|
else {
|
|
remove_familiar(mag);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_building(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
tolua_pushusertype(L, self->building, TOLUA_CAST "building");
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_building(lua_State * L)
|
|
{
|
|
unit *u = (unit *)tolua_tousertype(L, 1, 0);
|
|
if (u->faction) {
|
|
building * b = (building *)tolua_tousertype(L, 2, 0);
|
|
if (b != u->building) {
|
|
leave(u, true);
|
|
if (b) {
|
|
if (u->region != b->region) {
|
|
move_unit(u, b->region, NULL);
|
|
}
|
|
u_set_building(u, b);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_ship(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
tolua_pushusertype(L, self->ship, TOLUA_CAST "ship");
|
|
return 1;
|
|
}
|
|
|
|
static void unit_setship(unit * u, ship * s)
|
|
{
|
|
leave(u, true);
|
|
if (s && u->region != s->region) {
|
|
move_unit(u, s->region, NULL);
|
|
}
|
|
u_set_ship(u, s);
|
|
}
|
|
|
|
static int tolua_unit_set_ship(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
if (self->faction) {
|
|
unit_setship(self, (ship *)tolua_tousertype(L, 2, 0));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_region(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
tolua_pushusertype(L, self->region, TOLUA_CAST "region");
|
|
return 1;
|
|
}
|
|
|
|
static void unit_setregion(unit * u, region * r)
|
|
{
|
|
move_unit(u, r, NULL);
|
|
}
|
|
|
|
static int tolua_unit_set_region(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
unit_setregion(self, (region *)tolua_tousertype(L, 2, 0));
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_order(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
int index = (int)tolua_tonumber(L, 2, -1);
|
|
order *ord = NULL;
|
|
if (index < 0) {
|
|
ord = self->thisorder;
|
|
}
|
|
else {
|
|
int i;
|
|
ord = self->orders;
|
|
for (i = 0; ord && i != index; ++i) {
|
|
ord = ord->next;
|
|
}
|
|
}
|
|
if (ord) {
|
|
char buffer[1024];
|
|
get_command(ord, self->faction->locale, buffer, sizeof(buffer));
|
|
lua_pushstring(L, buffer);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_add_order(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *str = tolua_tostring(L, 2, 0);
|
|
order *ord = parse_order(str, self->faction->locale);
|
|
unit_addorder(self, ord);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_clear_orders(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
free_orders(&self->orders);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_items(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
|
|
item **item_ptr = (item **)lua_newuserdata(L, sizeof(item *));
|
|
|
|
luaL_getmetatable(L, TOLUA_CAST "item");
|
|
lua_setmetatable(L, -2);
|
|
|
|
*item_ptr = self->items;
|
|
|
|
lua_pushcclosure(L, tolua_itemlist_next, 1);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_spells(lua_State * L)
|
|
{
|
|
unit *self = (unit *) tolua_tousertype(L, 1, 0);
|
|
sc_mage *mage = self ? get_mage_depr(self) : 0;
|
|
spellbook *sb = mage ? mage->spellbook : 0;
|
|
selist *slist = 0;
|
|
if (sb) {
|
|
selist **slist_ptr = &sb->spells;
|
|
slist = *slist_ptr;
|
|
}
|
|
return tolua_selist_push(L, "spellbook", "spell_entry", slist);
|
|
}
|
|
|
|
static int tolua_unit_get_curse(lua_State *L) {
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *name = tolua_tostring(L, 2, 0);
|
|
if (self->attribs) {
|
|
curse * c = get_curse(self->attribs, ct_find(name));
|
|
if (c) {
|
|
lua_pushnumber(L, curse_geteffect(c));
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_has_attrib(lua_State *L) {
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *name = tolua_tostring(L, 2, 0);
|
|
attrib * a = self->attribs;
|
|
while (a) {
|
|
if (strcmp(a->type->name, name) == 0) {
|
|
break;
|
|
}
|
|
a = a->nexttype;
|
|
}
|
|
lua_pushboolean(L, a != NULL);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_flag(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *name = tolua_tostring(L, 2, 0);
|
|
int flag = atoi36(name);
|
|
lua_pushboolean(L, key_get(self->attribs, flag));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_flag(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *name = tolua_tostring(L, 2, 0);
|
|
int value = (int)tolua_tonumber(L, 3, 0);
|
|
int flag = atoi36(name);
|
|
if (value) {
|
|
key_set(&self->attribs, flag, value);
|
|
}
|
|
else {
|
|
key_unset(&self->attribs, flag);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_weight(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, unit_getweight(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_capacity(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushinteger(L, unit_getcapacity(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_get_faction(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
tolua_pushusertype(L, (void *)self->faction, TOLUA_CAST "faction");
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_faction(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
faction *f = (faction *)tolua_tousertype(L, 2, 0);
|
|
u_setfaction(self, f);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_get_race(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
tolua_pushstring(L, u_race(self)->_name);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_set_race(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *rcname = tolua_tostring(L, 2, 0);
|
|
const race *rc = rc_find(rcname);
|
|
if (rc != NULL) {
|
|
if (self->irace == u_race(self)) {
|
|
self->irace = NULL;
|
|
}
|
|
u_setrace(self, rc);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_destroy(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
if (self) {
|
|
remove_unit(&self->region->units, self);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_unit_create(lua_State * L)
|
|
{
|
|
faction *f = (faction *)tolua_tousertype(L, 1, 0);
|
|
region *r = (region *)tolua_tousertype(L, 2, 0);
|
|
unit *u;
|
|
const char *rcname = tolua_tostring(L, 4, NULL);
|
|
int num = (int)tolua_tonumber(L, 3, 1);
|
|
const race *rc;
|
|
|
|
assert(f && r);
|
|
rc = rcname ? rc_find(rcname) : f->race;
|
|
assert(rc);
|
|
u = create_unit(r, f, num, rc, 0, NULL, NULL);
|
|
tolua_pushusertype(L, u, TOLUA_CAST "unit");
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_unit_tostring(lua_State * L)
|
|
{
|
|
unit *self = (unit *)tolua_tousertype(L, 1, 0);
|
|
lua_pushstring(L, unitname(self));
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_event_gettype(lua_State * L)
|
|
{
|
|
event *self = (event *)tolua_tousertype(L, 1, 0);
|
|
int index = (int)tolua_tonumber(L, 2, 0);
|
|
lua_pushstring(L, self->args[index].type);
|
|
return 1;
|
|
}
|
|
|
|
static int tolua_event_get(lua_State * L)
|
|
{
|
|
struct event *self = (struct event *)tolua_tousertype(L, 1, 0);
|
|
int index = (int)tolua_tonumber(L, 2, 0);
|
|
|
|
event_arg *arg = self->args + index;
|
|
|
|
if (arg->type) {
|
|
if (strcmp(arg->type, "string") == 0) {
|
|
tolua_pushstring(L, (const char *)arg->data.v);
|
|
}
|
|
else if (strcmp(arg->type, "int") == 0) {
|
|
lua_pushinteger(L, arg->data.i);
|
|
}
|
|
else if (strcmp(arg->type, "float") == 0) {
|
|
lua_pushnumber(L, (lua_Number)arg->data.f);
|
|
}
|
|
else {
|
|
/* this is pretty lazy */
|
|
tolua_pushusertype(L, (void *)arg->data.v, TOLUA_CAST arg->type);
|
|
}
|
|
return 1;
|
|
}
|
|
tolua_error(L, TOLUA_CAST "invalid type argument for event", NULL);
|
|
return 0;
|
|
}
|
|
|
|
static int tolua_equipunit(lua_State * L)
|
|
{
|
|
unit *u = (unit *)tolua_tousertype(L, 1, 0);
|
|
const char *eqname = tolua_tostring(L, 2, 0);
|
|
int mask = (int)tolua_tonumber(L, 3, EQUIP_ALL);
|
|
assert(u && mask > 0);
|
|
equip_unit_mask(u, eqname, mask);
|
|
return 0;
|
|
}
|
|
|
|
void tolua_unit_open(lua_State * L)
|
|
{
|
|
/* register user types */
|
|
tolua_usertype(L, TOLUA_CAST "unit");
|
|
|
|
tolua_module(L, NULL, 0);
|
|
tolua_beginmodule(L, NULL);
|
|
{
|
|
tolua_cclass(L, TOLUA_CAST "event", TOLUA_CAST "event", TOLUA_CAST "",
|
|
NULL);
|
|
tolua_beginmodule(L, TOLUA_CAST "event");
|
|
{
|
|
tolua_function(L, TOLUA_CAST "get_type", tolua_event_gettype);
|
|
tolua_function(L, TOLUA_CAST "get", tolua_event_get);
|
|
}
|
|
tolua_endmodule(L);
|
|
|
|
tolua_cclass(L, TOLUA_CAST "unit", TOLUA_CAST "unit", TOLUA_CAST "", NULL);
|
|
tolua_beginmodule(L, TOLUA_CAST "unit");
|
|
{
|
|
tolua_function(L, TOLUA_CAST "__tostring", tolua_unit_tostring);
|
|
tolua_function(L, TOLUA_CAST "create", tolua_unit_create);
|
|
tolua_function(L, TOLUA_CAST "destroy", tolua_unit_destroy);
|
|
|
|
tolua_variable(L, TOLUA_CAST "name", tolua_unit_get_name,
|
|
tolua_unit_set_name);
|
|
tolua_variable(L, TOLUA_CAST "faction", tolua_unit_get_faction,
|
|
tolua_unit_set_faction);
|
|
tolua_variable(L, TOLUA_CAST "id", tolua_unit_get_id, tolua_unit_set_id);
|
|
tolua_variable(L, TOLUA_CAST "group", tolua_unit_get_group, tolua_unit_set_group);
|
|
tolua_variable(L, TOLUA_CAST "info", tolua_unit_get_info, tolua_unit_set_info);
|
|
tolua_variable(L, TOLUA_CAST "hp", tolua_unit_get_hp, tolua_unit_set_hp);
|
|
tolua_variable(L, TOLUA_CAST "status", tolua_unit_get_status,
|
|
tolua_unit_set_status);
|
|
tolua_variable(L, TOLUA_CAST "familiar", tolua_unit_get_familiar,
|
|
tolua_unit_set_familiar);
|
|
|
|
tolua_variable(L, TOLUA_CAST "weight", tolua_unit_get_weight, 0);
|
|
tolua_variable(L, TOLUA_CAST "capacity", tolua_unit_get_capacity, 0);
|
|
|
|
tolua_function(L, TOLUA_CAST "get_order", tolua_unit_get_order);
|
|
tolua_function(L, TOLUA_CAST "add_order", tolua_unit_add_order);
|
|
tolua_function(L, TOLUA_CAST "clear_orders", tolua_unit_clear_orders);
|
|
tolua_function(L, TOLUA_CAST "get_curse", tolua_unit_get_curse);
|
|
tolua_function(L, TOLUA_CAST "has_attrib", tolua_unit_has_attrib);
|
|
|
|
/* key-attributes for named flags: */
|
|
tolua_function(L, TOLUA_CAST "set_flag", tolua_unit_set_flag);
|
|
tolua_function(L, TOLUA_CAST "get_flag", tolua_unit_get_flag);
|
|
tolua_variable(L, TOLUA_CAST "guard", tolua_unit_get_guard,
|
|
tolua_unit_set_guard);
|
|
tolua_variable(L, TOLUA_CAST "flags", tolua_unit_get_flags,
|
|
tolua_unit_set_flags);
|
|
tolua_variable(L, TOLUA_CAST "age", tolua_unit_get_age,
|
|
tolua_unit_set_age);
|
|
|
|
/* items: */
|
|
tolua_function(L, TOLUA_CAST "get_item", tolua_unit_get_item);
|
|
tolua_function(L, TOLUA_CAST "add_item", tolua_unit_add_item);
|
|
tolua_variable(L, TOLUA_CAST "items", tolua_unit_get_items, 0);
|
|
tolua_function(L, TOLUA_CAST "get_pooled", tolua_unit_get_pooled);
|
|
tolua_function(L, TOLUA_CAST "use_pooled", tolua_unit_use_pooled);
|
|
|
|
/* effects */
|
|
tolua_function(L, TOLUA_CAST "get_potion", tolua_unit_get_effect);
|
|
|
|
/* skills: */
|
|
tolua_function(L, TOLUA_CAST "get_skill", tolua_unit_getskill);
|
|
tolua_function(L, TOLUA_CAST "eff_skill", tolua_unit_effskill);
|
|
tolua_function(L, TOLUA_CAST "set_skill", tolua_unit_setskill);
|
|
|
|
tolua_function(L, TOLUA_CAST "add_notice", tolua_unit_addnotice);
|
|
|
|
/* npc logic: */
|
|
tolua_function(L, TOLUA_CAST "add_handler", tolua_unit_addhandler);
|
|
|
|
tolua_variable(L, TOLUA_CAST "race_name", tolua_unit_get_racename,
|
|
tolua_unit_set_racename);
|
|
tolua_function(L, TOLUA_CAST "add_spell", tolua_unit_addspell);
|
|
tolua_variable(L, TOLUA_CAST "spells", tolua_unit_get_spells, 0);
|
|
tolua_function(L, TOLUA_CAST "cast_spell", tolua_unit_castspell);
|
|
tolua_function(L, TOLUA_CAST "effect", bind_unit_effect);
|
|
|
|
tolua_variable(L, TOLUA_CAST "magic", tolua_unit_get_magic,
|
|
tolua_unit_set_magic);
|
|
tolua_variable(L, TOLUA_CAST "aura", tolua_unit_get_aura,
|
|
tolua_unit_set_aura);
|
|
tolua_variable(L, TOLUA_CAST "building", tolua_unit_get_building,
|
|
tolua_unit_set_building);
|
|
tolua_variable(L, TOLUA_CAST "ship", tolua_unit_get_ship,
|
|
tolua_unit_set_ship);
|
|
tolua_variable(L, TOLUA_CAST "region", tolua_unit_get_region,
|
|
tolua_unit_set_region);
|
|
tolua_variable(L, TOLUA_CAST "number", tolua_unit_get_number,
|
|
tolua_unit_set_number);
|
|
tolua_variable(L, TOLUA_CAST "race", tolua_unit_get_race,
|
|
tolua_unit_set_race);
|
|
tolua_variable(L, TOLUA_CAST "hp_max", tolua_unit_get_hpmax, 0);
|
|
tolua_variable(L, TOLUA_CAST "aura_max", tolua_unit_get_auramax, 0);
|
|
|
|
tolua_function(L, TOLUA_CAST "equip", tolua_equipunit);
|
|
tolua_function(L, TOLUA_CAST "show", tolua_bufunit);
|
|
}
|
|
tolua_endmodule(L);
|
|
}
|
|
tolua_endmodule(L);
|
|
}
|