rendered paste body//To run a Lua scripts, it calls sl_Doscript_blargs, which in turn calls sl_doscript_stackargs.
// TODO: pcl functions like dialog and menu should accept an npc parameter!
#include "sl.h"
#include <lauxlib.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include "clif.h"
#include <assert.h>
#include <stdarg.h>
#include <sys/stat.h>
#include "pc.h"
#include "mob.h"
#include "itemdb.h"
#include "map.h"
#include "socket.h"
#include "clan_db.h"
#include "mmo.h"
#include "malloc.h"
#define sl_redtext(text) "\033[31;1m" text "\033[0m"
#define sl_err(text) printf(sl_redtext("Lua error:") " %s\n", text)
#define sl_err_print(state) sl_err(lua_tostring(state, -1))
// accessors should return 1 if the attribute was handled; otherwise an error will be raised
typedef int (*typel_getattrfunc)(lua_State *, void * /* self */, char * /* attrname */);
typedef int (*typel_setattrfunc)(lua_State *, void * /* self */, char * /*attrname */);
typedef int (*typel_initfunc)(lua_State *, void * /* self */, int /* dataref */, void * /* param */);
typedef struct typel_class_ {
// an luaL_ref reference to the prototype table for this class. the prototype table holds
// the functions for this class.
int protoref;
char *name;
typel_getattrfunc getattr;
typel_setattrfunc setattr;
typel_initfunc init;
// remember when implementing the ctor that the first argument will always be the class
// however, luaL_argerror uses normal indices; as in 1 still refers to the first real argument
lua_CFunction ctor;
} typel_class;
typedef struct typel_inst_ {
typel_class *type;
int dataref;
void *self;
} typel_inst;
int typel_mtindex(lua_State *);
int typel_mtnewindex(lua_State *);
int typel_mtgc(lua_State *);
int typel_mtref;
// TODO: actually use this!
#define sl_ensureasync(state) \
if(state == sl_gstate) { luaL_error(state, "this function must be called from a coroutine; " \
"that is, the calling method must be marked with async()"); }
// TODO: do we even need this anymore?
#define typel_err_invalidattr(state, type, attrname) \
luaL_error(state, "'%s' object has no attribute '%s'", type->name, attrname)
void typel_staticinit();
void typel_staticdestroy(); // TODO: this should unref typel_mtref?
typedef int (*typel_func)(lua_State *, void * /* self */);
#define typel_topointer(state, index) (((typel_inst *)lua_touserdata(state, index))->self)
#define typel_check(state, index, type) (((typel_inst *)lua_touserdata(state, index))->type == type)
int typel_boundfunc(lua_State *);
void typel_pushinst(lua_State *, typel_class *, void *, void *);
typel_class typel_new(char *, lua_CFunction);
void typel_extendproto(typel_class *, char *, typel_func);
#define sl_memberarg(x) (x + 1)
#define sl_memberself 1
int bll_getattr(lua_State *, struct block_list *, char *attrname);
int bll_setattr(lua_State *, struct block_list *, char *attrname);
void bll_pushinst(lua_State *, struct block_list *, void *);
#define pcl_pushinst(state, sd) typel_pushinst(state, &pcl_type, sd, 0)
typel_class pcl_type;
void pcl_staticinit();
#define regl_pushinst(state, sd) typel_pushinst(state, ®l_type, sd, 0)
typel_class regl_type;
void regl_staticinit();
#define fll_pushinst(state,fl) typel_pushinst(state, &fll_type, fl, 0)
typel_class fll_type;
void fll_staticinit();
#define mapregl_pushinst(state,sd) typel_pushinst(state,&mapregl_type,sd,0)
typel_class mapregl_type;
void mapregl_staticinit();
#define mobl_pushinst(state, mob) typel_pushinst(state, &mobl_type, mob, 0)
typel_class mobl_type;
void mobl_staticinit();
#define npcl_pushinst(state, nd) typel_pushinst(state, &npcl_type, nd, 0)
typel_class npcl_type;
void npcl_staticinit();
#define iteml_pushinst(state, item) typel_pushinst(state, &iteml_type, item, 0)
typel_class iteml_type;
void iteml_staticinit();
#define biteml_pushinst(state, bitem) typel_pushinst(state, &biteml_type, bitem, 0)
typel_class biteml_type;
void biteml_staticinit();
#define SL_EXPOSE_ENUM(val) lua_pushnumber(sl_gstate, val); lua_setglobal(sl_gstate, #val)
#define sl_pushref(state, ref) lua_rawgeti(state, LUA_REGISTRYINDEX, ref)
void sl_checkargs(lua_State *, char *fmt);
void sl_loaddir(char *);
int sl_async(lua_State *);
int sl_async_done(lua_State *);
void sl_async_freeco(struct map_sessiondata *);
void sl_async_resume(struct map_sessiondata *, int);
int bll_spawn(lua_State *state, struct block_list* bl) {
sl_checkargs(state,"nnnn");
mobspawn_onetime(lua_tonumber(state,sl_memberarg(1)),
bl->m,lua_tonumber(state,sl_memberarg(2)),
lua_tonumber(state,sl_memberarg(3)),
lua_tonumber(state,sl_memberarg(4)));
return 0;
}
void bll_getobjects_helper(struct block_list *bl, va_list ap) {
lua_State *state = va_arg(ap, lua_State *);
bll_pushinst(state, bl, 0);
lua_rawseti(state, -2, lua_objlen(state, -2) + 1);
}
int bll_getobjects(lua_State *state, void *self, int area) {
sl_checkargs(state, "n");
struct block_list *bl=(struct block_list*)self;
/*#define NUMBER_FIELD(name) \
lua_getfield(state, sl_memberself, #name); \
int name = lua_tonumber(state, -1); \
lua_pop(state, 1)
NUMBER_FIELD(m);
NUMBER_FIELD(x);
NUMBER_FIELD(y);
#undef NUMBER_FIELD*/
lua_newtable(state);
int type = lua_tonumber(state, sl_memberarg(1));
map_foreachinarea(bll_getobjects_helper, bl->m, bl->x, bl->y, area, type, state);
return 1;
}
int bll_getobjects_cell(lua_State *state, void *self) {
sl_checkargs(state, "nnnn");
int m = lua_tonumber(state, sl_memberarg(1)),
x = lua_tonumber(state, sl_memberarg(2)),
y = lua_tonumber(state, sl_memberarg(3)),
type = lua_tonumber(state, sl_memberarg(4));
lua_newtable(state);
map_foreachincell(bll_getobjects_helper, m, x, y, type, state);
return 1;
}
int bll_getobjects_area(lua_State *state, void *self) {
return bll_getobjects(state, self, AREA);
}
int bll_getobjects_samemap(lua_State *state, void *self) {
return bll_getobjects(state, self, SAMEMAP);
}
int bll_sendanim(lua_State *state, void *self) {
sl_checkargs(state, "n");
struct block_list *bl = (struct block_list*)self;
int anim = lua_tonumber(state, sl_memberarg(1));
map_foreachinarea(clif_sendanimation, bl->m, bl->x, bl->y, AREA, BL_PC, anim, bl);
return 0;
}
int bll_sendaction(lua_State *state,void *self) {
sl_checkargs(state,"nn");
struct block_list *bl=(struct block_list*)self;
int action=lua_tonumber(state,sl_memberarg(1));
int time=lua_tonumber(state,sl_memberarg(2));
clif_sendaction(bl,action,time,0);
return 0;
}
int bll_getusers(lua_State *state, void *self) {
struct map_sessiondata *tsd;
//struct block_list *bl= (struct block_list*)self;
int i;
lua_newtable(state);
for(i=0;i<fd_max;i++) {
if(session[i] && (tsd=session[i]->session_data)) {
bll_pushinst(state, &tsd->bl, 0);
lua_rawseti(state, -2, lua_objlen(state, -2) + 1);
}
}
return 1;
}
int getobjectsmap(lua_State *state) {
int m=lua_tonumber(state,1);
int type=lua_tonumber(state,2);
int x;
struct mobspawn_data *te;
lua_newtable(state);
//printf("Map: %d\n",type);
//map_foreachinarea(bll_getobjects_helper, m, 1, 1, SAMEMAP, type, state);
for(x=1;x<map[m].block_mob_count+1;x++) {
te=map[m].block_mob[x];
bll_pushinst(state,&te->bl,0);
lua_rawseti(state,-2,x+1);
}
return 1;
}
void sl_checkargs(lua_State *state, char *fmt) {
int narg;
for(narg = 1; fmt[narg - 1]; ++narg) {
int expectedtype = LUA_TNIL, gottype = lua_type(state, sl_memberarg(narg));
switch(fmt[narg - 1]) {
case 'n': expectedtype = LUA_TNUMBER; break;
case 'b': expectedtype = LUA_TBOOLEAN; break;
case 't': expectedtype = LUA_TTABLE; break;
case 's': expectedtype = LUA_TSTRING; break;
case 'f': expectedtype = LUA_TFUNCTION; break;
case 'u': expectedtype = LUA_TUSERDATA; break;
}
if(gottype != expectedtype) {
char message[512];
message[0] = 0;
sprintf(message, "%s expected, got %s",
lua_typename(state, expectedtype), lua_typename(state, gottype));
luaL_argerror(state, sl_memberarg(narg), message);
}
}
}
int sl_exec_redirectio(lua_State *state) {
struct map_sessiondata *sd = lua_touserdata(state, lua_upvalueindex(1));
char *msg = lua_tostring(state, 1);
int msglen = lua_objlen(state, 1);
clif_sendwisp(sd, "lua", msg, msglen);
return 0;
}
int sl_luasize(struct map_sessiondata* sd) {
char buf[255];
sprintf(buf,"LUA is using %u KB",lua_gc(sl_gstate,LUA_GCCOUNT,0));
clif_sendminitext(sd,buf,0);
return 0;
}
int getobject(lua_State *state) {
//sl_checkargs(state,"nnn");
int m=lua_tonumber(state,1);
int x=lua_tonumber(state,2);
int y=lua_tonumber(state,3);
if(map_isloaded(m)) {
lua_pushnumber(state,map[m].obj[x+y*map[m].xs]);
}
return 1;
}
int sl_updatepeople(struct block_list *bl, va_list ap) {
struct map_sessiondata *sd;
nullpo_ret(0,sd=(struct map_sessiondata*)bl);
pc_warp(sd,sd->bl.m,sd->bl.x,sd->bl.y);
return 0;
}
int setpostcolor(lua_State *state) {
int board=lua_tonumber(state,1);
int post=lua_tonumber(state,2);
int color=lua_tonumber(state,3);
map_changepostcolor(board,post,color);
}
int setobject(lua_State *state) {
//sl_checkargs(state,"nnnn");
int m=lua_tonumber(state,1);
int x=lua_tonumber(state,2);
int y=lua_tonumber(state,3);
int newnum=lua_tonumber(state,4);
if(map_isloaded(m)) {
map[m].obj[x+y*map[m].xs]=newnum;
map_foreachinarea(sl_updatepeople,m,x,y,AREA,BL_PC);
}
return 0;
}
int setpass(lua_State *state) {
int m=lua_tonumber(state,1);
int x=lua_tonumber(state,2);
int y=lua_tonumber(state,3);
int newnum=lua_tonumber(state,4);
if(map_isloaded(m)) {
map[m].pass[x+y*map[m].xs]=newnum;
map_foreachinarea(sl_updatepeople,m,x,y,AREA,BL_PC);
}
return 0;
}
int getpass(lua_State *state) {
int m=lua_tonumber(state,1);
int x=lua_tonumber(state,2);
int y=lua_tonumber(state,3);
if(map_isloaded(m)) {
lua_pushnumber(state,map[m].pass[x+y*map[m].xs]);
}
return 1;
}
void sl_exec(struct map_sessiondata *sd, char *str) {
#define sl_exec_err() \
char *msg = lua_tostring(sl_gstate, -1); \
int msglen = lua_objlen(sl_gstate, -1); \
clif_sendwisp(sd, "lua-error", msg, msglen)
if(luaL_loadstring(sl_gstate, str) != 0) {
sl_exec_err();
lua_pop(sl_gstate, 1);
return;
}
lua_newtable(sl_gstate); // the environment table
lua_pushlightuserdata(sl_gstate, sd);
lua_pushcclosure(sl_gstate, sl_exec_redirectio, 1);
lua_setfield(sl_gstate, -2, "print"); // set the new print
lua_newtable(sl_gstate); // the metatable for the environment
lua_pushvalue(sl_gstate, LUA_GLOBALSINDEX);
lua_setfield(sl_gstate, -2, "__index"); // set __index = _G
lua_setmetatable(sl_gstate, -2);
lua_setfenv(sl_gstate, -2);
if(lua_pcall(sl_gstate, 0, 0, 0) != 0) {
sl_exec_err();
lua_pop(sl_gstate, 1); // pop the error string
return;
}
#undef sl_exec_err
}
void sl_init() {
int i,count=0;
sl_gstate = lua_open();
luaL_openlibs(sl_gstate);
//lua_gc(sl_gstate,LUA_GCSTOP,0); //TEMPORARILY IN..THIS MAKES YIELD WORK
typel_staticinit();
pcl_staticinit();
regl_staticinit();
mapregl_staticinit();
mobl_staticinit();
npcl_staticinit();
iteml_staticinit();
biteml_staticinit();
fll_staticinit();
{
SL_EXPOSE_ENUM(MOB_ALIVE);
SL_EXPOSE_ENUM(MOB_DEAD);
SL_EXPOSE_ENUM(MOB_HIT);
SL_EXPOSE_ENUM(MOB_AGGRESSIVE);
SL_EXPOSE_ENUM(MOB_STATIONARY);
SL_EXPOSE_ENUM(MOB_NORMAL);
}
{
SL_EXPOSE_ENUM(BL_PC);
SL_EXPOSE_ENUM(BL_NPC);
SL_EXPOSE_ENUM(BL_ITEM);
SL_EXPOSE_ENUM(BL_MOB);
SL_EXPOSE_ENUM(BL_NUL);
}
{
SL_EXPOSE_ENUM(EQ_WEAP);
SL_EXPOSE_ENUM(EQ_ARMOR);
SL_EXPOSE_ENUM(EQ_SHIELD);
SL_EXPOSE_ENUM(EQ_HELM);
SL_EXPOSE_ENUM(EQ_RIGHT);
SL_EXPOSE_ENUM(EQ_LEFT);
SL_EXPOSE_ENUM(EQ_SCRIPT1);
SL_EXPOSE_ENUM(EQ_SCRIPT2);
SL_EXPOSE_ENUM(EQ_FACEACC);
SL_EXPOSE_ENUM(EQ_CROWN);
SL_EXPOSE_ENUM(EQ_MANTLE);
SL_EXPOSE_ENUM(EQ_NECKLACE);
SL_EXPOSE_ENUM(EQ_BOOTS);
SL_EXPOSE_ENUM(EQ_COAT);
}
//lua_newtable(sl_gstate);
/*for(i=0;i<65535;i++) {
if(map_isloaded(i)) {
lua_pushnumber(sl_gstate,i);
lua_rawseti(sl_gstate,-2,count+1);
count++;
}
}
*/
//lua_setglobal(sl_gstate,"maps");
lua_register(sl_gstate, "_async", sl_async);
lua_register(sl_gstate, "_asyncDone", sl_async_done);
//lua_pushcclosure(sl_gstate,getobjectsmap,1);
lua_register(sl_gstate,"getObjectsMap",getobjectsmap);
lua_register(sl_gstate,"getObject",getobject);
lua_register(sl_gstate,"setObject",setobject);
lua_register(sl_gstate,"setPass",setpass);
lua_register(sl_gstate,"getPass",getpass);
lua_register(sl_gstate,"setPostColor",setpostcolor);
// make sure to load the sys.lua file before anything else!
if(luaL_dofile(sl_gstate, "./lua/sys.lua")) {
sl_err_print(sl_gstate);
return;
}
sl_reload();
}
void sl_loaddir(char *dirpath) {
DIR *dir = opendir(dirpath);
struct dirent *dir_entry;
char path[512];
char dirpath_tail = dirpath[strlen(dirpath) - 1];
int dirpath_hasslash = dirpath_tail == '/' || dirpath_tail == '\\';
while(0 != (dir_entry = readdir(dir))) {
char *filename = dir_entry->d_name;
int filename_len = strlen(filename);
// ignore special files
if(!strcmp(filename, ".") || !strcmp(filename, "..") ||
!strcmp(filename, ".svn") || !strcmp(filename, "sys.lua")) continue;
strcpy(path, dirpath);
if(!dirpath_hasslash) strcat(path, "/");
strcat(path, dir_entry->d_name);
struct stat dir_entry_stat;
stat(path, &dir_entry_stat);
if(S_ISDIR(dir_entry_stat.st_mode)) {
sl_loaddir(path);
} else if(S_ISREG(dir_entry_stat.st_mode)) {
// only load files with the extension ".lua"
if(filename_len < 4) continue;
if(strcmp(&filename[filename_len - 4], ".lua")) continue;
if(luaL_dofile(sl_gstate, path))
sl_err_print(sl_gstate);
}
}
closedir(dir);
}
void sl_reload() {
sl_loaddir("./lua/");
}
void sl_fixmem() {
lua_gc(sl_gstate,LUA_GCCOLLECT,0);
return 0;
}
int sl_async_done(lua_State *state) {
// free the coroutine
struct map_sessiondata *sd = typel_topointer(state, 1);
sl_async_freeco(sd);
}
void sl_async_freeco(struct map_sessiondata *sd) {
if(!sd->coref) return 0;
luaL_unref(sl_gstate, LUA_REGISTRYINDEX, sd->coref);
sd->coref = 0;
}
void sl_async_resume(struct map_sessiondata *sd, int nargs) {
unsigned int coref;
struct map_sessiondata *nsd;
if(!sd->coref) {
nsd=map_id2sd(sd->coref_container);
if(!nsd) return 0;
coref=nsd->coref;
} else {
coref=sd->coref;
}
lua_State *costate;
sl_pushref(sl_gstate, coref);
if(lua_isthread(sl_gstate,-1)) {
costate = lua_tothread(sl_gstate, -1);
lua_pop(sl_gstate, 1); // pop the thread
//printf("%d\n",lua_status(costate));
lua_xmove(sl_gstate, costate, nargs);
if(lua_resume(costate, nargs) == LUA_ERRRUN) {
char *err = lua_tostring(costate, -1);
lua_pop(costate, 1);
sl_async_freeco(sd);
sl_err(err);
}
}
}
int sl_async(lua_State *state) {
// first argument should be a player object, second argument should be a function to call
struct map_sessiondata *sd = typel_topointer(state, 1);
if(!sd) return 0;
if(sd->coref) { clif_sendminitext(sd,"You are busy.",0); return 0; };
lua_State *costate = lua_newthread(state);
sd->coref = luaL_ref(state, LUA_REGISTRYINDEX);
lua_pushvalue(state, 2); // push a copy of the function
lua_xmove(state, costate, 1); // move the function into the coroutine state
if(lua_resume(costate, 0) == LUA_ERRRUN) {
lua_xmove(costate, state, 1);
sl_async_freeco(sd);
return lua_error(state);
}
return 0;
}
int sl_doscript_stackargs(char *root, char *method, int nargs) {
int argsindex = lua_gettop(sl_gstate) - (nargs - 1), errhandler, i;
;
lua_getglobal(sl_gstate, "_errhandler");
errhandler = lua_gettop(sl_gstate);
lua_getglobal(sl_gstate, root);
if(lua_isnil(sl_gstate, -1)) {
lua_pop(sl_gstate, 2 + nargs); // pop _errhandler, the table, and the args
/*ntop=lua_gettop(sl_gstate);
dif=ntop-top;
printf("1Difference is %d\n",ntop-top);
*/
return 0;
}
lua_getfield(sl_gstate, -1, method);
lua_replace(sl_gstate, -2); // essentially remove the table leaving only the field
if(lua_isnil(sl_gstate, -1)) {
lua_pop(sl_gstate, 2 + nargs); // pop _errhandler, the field, and the args
/*ntop=lua_gettop(sl_gstate);
dif=ntop-top;
printf("2Difference is %d\n",ntop-top);
*/
return 0;
}
// push copies of the arguments onto the stack
for(i = 0; i < nargs; ++i)
lua_pushvalue(sl_gstate, argsindex + i);
if(lua_pcall(sl_gstate, nargs, 0, errhandler) != 0) {
sl_err_print(sl_gstate);
lua_pop(sl_gstate, 1); // pop the error string
/*ntop=lua_gettop(sl_gstate);
dif=ntop-top;
//if(dif<(nargs+2))
printf("3Difference is %d\n",dif);*/
}
lua_pop(sl_gstate, nargs+1); // pop the original arguments, and _errhandler
/*ntop=lua_gettop(sl_gstate);
dif=ntop-top;
printf("Difference is %d\n",dif);*/
return 1;
}
int sl_doscript_blargs(char *root, char *method, int nargs, ...) {
int i;
struct block_list *bl=NULL;
va_list argp;
va_start(argp, nargs);
for(i = 0; i < nargs; ++i) {
bl=NULL;
bl = va_arg(argp, struct block_list *);
bll_pushinst(sl_gstate, bl, 0);
//if(bl) newargs++;
}
va_end(argp);
return sl_doscript_stackargs(root, method, nargs);
}
void sl_resumemenu(int selection, struct map_sessiondata *sd) {
/*if(sd->coroutine) {
if(lua_status(sd->coroutine)==LUA_YIELD) {
lua_pushnumber(sd->coroutine, selection);
lua_resume(sd->coroutine, 1);
}
}*/
sd->in_menu=0;
lua_pushnumber(sl_gstate, selection);
sl_async_resume(sd, 1);
}
void sl_resumemenu2(int selection, int choice, struct map_sessiondata *sd) {
if(selection==1) { //Quit
sl_async_freeco(sd);
}
if(selection==2) { //Selected(Next)
lua_pushnumber(sl_gstate,choice);
sl_async_resume(sd,1);
}
}
void sl_resumedialog(int choice, struct map_sessiondata *sd) {
/*if(sd->coroutine) {
if(lua_status(sd->coroutine)==LUA_YIELD) {
if(choice == 0) lua_pushstring(sd->coroutine, "previous");
else if(choice == 1) lua_pushstring(sd->coroutine, "quit");
else if(choice == 2) lua_pushstring(sd->coroutine, "next");
else lua_pushnil(sd->coroutine);
lua_resume(sd->coroutine, 1);
}
}*/
if(choice == 0) { lua_pushstring(sl_gstate, "previous"); }
//else if(choice == 1) { lua_pushstring(sl_gstate, "quit"); }
else if(choice == 1) { sl_async_freeco(sd); return; }
else if(choice == 2) { lua_pushstring(sl_gstate, "next"); }
else { lua_pushstring(sl_gstate,"quit"); }
sl_async_resume(sd, 1);
}
void sl_resumebuy(int choice, struct map_sessiondata *sd) {
/*if(sd->coroutine) {
if((lua_status(sd->coroutine)==LUA_YIELD)) {
lua_pushnumber(sd->coroutine,choice);
lua_resume(sd->coroutine,1);
} else {
//sl_err_print(sd->coroutine);
}
}*/
sd->in_menu=0;
lua_pushnumber(sl_gstate, choice);
sl_async_resume(sd, 1);
}
void sl_resumesell(int choice, struct map_sessiondata *sd) {
/*if(sd->coroutine) {
if(lua_status(sd->coroutine)==LUA_YIELD) {
lua_pushnumber(sd->coroutine,choice);
lua_resume(sd->coroutine,1);
}
}*/
sd->in_menu=0;
lua_pushnumber(sl_gstate, choice);
sl_async_resume(sd, 1);
}
void sl_resumeinput(char* output, char* output2, struct map_sessiondata *sd) {
/*if(sd->coroutine) {
if(lua_status(sd->coroutine)==LUA_YIELD) {
//lua_pushstring(sd->coroutine,output);
lua_pushstring(sd->coroutine,output2);
lua_resume(sd->coroutine,1);
}
}*/
sd->in_menu=0;
lua_pushstring(sl_gstate, output2);
sl_async_resume(sd, 1);
}
void sl_resume(char* output,struct map_sessiondata *sd) {
/*if(sd->coroutine) {
if(lua_status(sd->coroutine)==LUA_YIELD) {
lua_pushstring(sd->coroutine,output);
lua_resume(sd->coroutine,1);
}
}*/
lua_pushstring(sl_gstate, output);
sl_async_resume(sd, 1);
}
int iteml_getattr(lua_State *, struct item_data *, char *);
int iteml_ctor(lua_State *);
void iteml_staticinit() {
iteml_type = typel_new("Item", iteml_ctor);
iteml_type.getattr = iteml_getattr;
}
int iteml_ctor(lua_State *state) {
struct item_data *item = 0;
if(lua_isnumber(state, 2))
item = itemdb_search(lua_tonumber(state, 2));
else if(lua_isstring(state, 2))
item = itemdb_searchname(lua_tostring(state, 2));
else luaL_argerror(state, 1, "expected string or number");
if(!item) luaL_error(state, "could not find item in the database");
iteml_pushinst(state, item);
return 1;
}
int iteml_getattr(lua_State *state, struct item_data *item, char *attrname) {
if(!strcmp(attrname, "vita")) lua_pushnumber(state, item->vita);
else if(!strcmp(attrname, "mana")) lua_pushnumber(state, item->mana);
else if(!strcmp(attrname, "dam")) lua_pushnumber(state, item->dam);
else if(!strcmp(attrname, "price")) lua_pushnumber(state,item->price);
else if(!strcmp(attrname, "sell")) lua_pushnumber(state,item->sell);
else if(!strcmp(attrname, "name")) lua_pushstring(state,item->name);
else if(!strcmp(attrname, "id")) lua_pushnumber(state,item->id);
else if(!strcmp(attrname, "maxAmount")) lua_pushnumber(state,item->max_amount);
else if(!strcmp(attrname, "maxDura")) lua_pushnumber(state,item->dura);
else if(!strcmp(attrname, "type")) lua_pushnumber(state,item->type);
else if(!strcmp(attrname, "depositable")) lua_pushboolean(state,item->depositable^1);
else if(!strcmp(attrname, "exchangeable")) lua_pushboolean(state,item->exchangeable^1);
else if(!strcmp(attrname, "droppable")) lua_pushboolean(state,item->droppable^1);
else return 0; // the attribute was not handled
return 1;
}
int biteml_getattr(lua_State *, struct item *, char *);
int biteml_setattr(lua_State *, struct item *, char *);
void biteml_staticinit() {
biteml_type = typel_new("BoundItem", 0);
biteml_type.getattr = biteml_getattr;
biteml_type.setattr = biteml_setattr;
}
int biteml_setattr(lua_State *state, struct item *bitem, char *attrname) {
if(!strcmp(attrname,"amount")) bitem->amount=lua_tonumber(state,-1);
else if(!strcmp(attrname,"dura")) bitem->dura=lua_tonumber(state,-1);
else if(!strcmp(attrname,"owner")) bitem->owner_id=lua_tonumber(state,-1);
else if(!strcmp(attrname,"realName")) strcpy(bitem->real_name,lua_tostring(state,-1));
return 1;
}
int biteml_getattr(lua_State *state, struct item *bitem, char *attrname) {
if(!strcmp(attrname, "amount")) lua_pushnumber(state, bitem->amount);
else if(!strcmp(attrname, "dura")) lua_pushnumber(state, bitem->dura);
else if(!strcmp(attrname, "owner")) lua_pushnumber(state,bitem->owner_id);
else if(!strcmp(attrname, "realName")) lua_pushstring(state,bitem->real_name);
else {
struct item_data *item = itemdb_search(bitem->id); // NOTE: this may be slow...?
assert(item);
return iteml_getattr(state, item, attrname);
}
return 1;
}
int regl_getattr(lua_State *, struct map_sessiondata *, char *);
int regl_setattr(lua_State *, struct map_sessiondata *, char *);
struct global_reg *regl_findreg(struct map_sessiondata *, char *);
void regl_staticinit() {
regl_type = typel_new("Registry", 0);
regl_type.getattr = regl_getattr;
regl_type.setattr = regl_setattr;
}
int regl_getattr(lua_State *state, struct map_sessiondata *sd, char *attrname) {
lua_pushnumber(state, pc_readglobalreg(sd, attrname));
return 1;
}
int regl_setattr(lua_State *state, struct map_sessiondata *sd, char *attrname) {
pc_setglobalreg(sd, attrname, lua_tonumber(state, -1));
return 1;
}
void typel_staticinit() {
lua_newtable(sl_gstate); // the global metatable
lua_pushcfunction(sl_gstate, typel_mtindex);
lua_setfield(sl_gstate, -2, "__index");
lua_pushcfunction(sl_gstate, typel_mtnewindex);
lua_setfield(sl_gstate, -2, "__newindex");
lua_pushcfunction(sl_gstate, typel_mtgc);
lua_setfield(sl_gstate, -2, "__gc");
typel_mtref = luaL_ref(sl_gstate, LUA_REGISTRYINDEX);
}
typel_class typel_new(char *name, lua_CFunction ctor) {
typel_class type;
memset(&type, 0, sizeof(typel_class));
// TODO: expose the type object, not the prototype, to lua
lua_newtable(sl_gstate); // the prototype table
if(ctor) {
lua_newtable(sl_gstate);
lua_pushcfunction(sl_gstate, ctor);
lua_setfield(sl_gstate, -2, "__call");
lua_setmetatable(sl_gstate, -2);
type.ctor = ctor;
}
type.protoref = luaL_ref(sl_gstate, LUA_REGISTRYINDEX);
sl_pushref(sl_gstate, type.protoref); // expose the prototype table to lua
lua_setglobal(sl_gstate, name);
type.name = name;
return type;
}
int typel_mtgc(lua_State *state) {
typel_inst *inst = lua_touserdata(state, 1);
//struct block_list *bl=(struct block_list*)inst->self;
luaL_unref(state, LUA_REGISTRYINDEX, inst->dataref);
//inst->dataref=0;
//inst->self=0;
//inst->type=0;
//(inst->type);
//FREE(inst);
return 0;
}
void typel_pushinst(lua_State *state, typel_class *type, void *self, void *param) {
typel_inst *inst = lua_newuserdata(state, sizeof(typel_inst));
inst->self = self;
inst->type = type;
sl_pushref(state, typel_mtref); // set the metatable
lua_setmetatable(state, -2);
lua_newtable(state); // create a new data table and store a ref
inst->dataref = luaL_ref(state, LUA_REGISTRYINDEX);
if(type->init && inst->self) { type->init(state, inst->self, inst->dataref, param); }
//else { luaL_error(state,"dataref no longer exists"); }
}
void typel_extendproto(typel_class *type, char *name, typel_func func) {
sl_pushref(sl_gstate, type->protoref);
lua_pushlightuserdata(sl_gstate, func);
lua_pushcclosure(sl_gstate, typel_boundfunc, 1);
lua_setfield(sl_gstate, -2, name);
lua_pop(sl_gstate, 1); // pop the prototype table
}
int typel_boundfunc(lua_State *state) {
typel_func wrapped = lua_touserdata(state, lua_upvalueindex(1));
typel_inst *inst = lua_touserdata(state, 1); // the first parameter is the userdata object
if(inst->self) {
return wrapped(state, inst->self);
}
}
int typel_mtindex(lua_State *state) {
typel_inst *inst = lua_touserdata(state, 1);
typel_class *type = inst->type;
char *attrname = lua_tostring(state, 2);
int result = 0;
if(!inst->self) { lua_pushnil(state); return 1; }
if(type->getattr)
result = type->getattr(state, inst->self, attrname);
if(!result) {
// the attribute was not handled by the getattr method
// next, try the prototype table
sl_pushref(state, type->protoref);
lua_getfield(state, -1, attrname);
if(lua_isnil(state, -1)) {
lua_pop(state, 2); // clean up the stack
// then try the data table associated with the instance
sl_pushref(state, inst->dataref);
lua_getfield(state, -1, attrname);
if(lua_isnil(state, -1)) {
// there is no such attribute; push nil
lua_pop(state, 1);
lua_pushnil(state);
}
}
lua_replace(state, -2);
}
return 1;
}
int typel_mtnewindex(lua_State *state) {
typel_inst *inst = lua_touserdata(state, 1);
typel_class *type = inst->type;
char *attrname = lua_tostring(state, 2);
if(!inst->self) { return 0; }
int result = 0;
if(type->setattr)
result = type->setattr(state, inst->self, attrname);
if(!result) { /* TODO: error */ }
return 0;
}
int bll_deliddb(lua_State *state, struct block_list *bl) {
map_deliddb(bl->id);
return 0;
}
int bll_playsound(lua_State *state, struct block_list *bl) {
int sound=lua_tonumber(state,sl_memberarg(1));
clif_playsound(bl,sound);
return 0;
}
int bll_talk(lua_State *state, struct block_list *bl) {
sl_checkargs(state, "ns");
int type=lua_tonumber(state,sl_memberarg(1));
char *msg = lua_tostring(state, sl_memberarg(2));
map_foreachinarea(clif_speak, bl->m, bl->x, bl->y, AREA, BL_PC, msg, bl,type);
return 0;
}
int bll_permspawn(lua_State *state, struct block_list *bl) {
return 0;
}
int bll_year(lua_State *state, struct block_list *bl) {
lua_pushnumber(state,cur_year);
return 1;
}
int bll_day(lua_State* state,struct block_list *bl)
{
lua_pushnumber(state,cur_day);
return 1;
}
int bll_time(lua_State* state, struct block_list *bl) {
lua_pushnumber(state,cur_time);
return 1;
}
int bll_sendside(lua_State *state, struct block_list* bl) {
//printf("Done it?!\n");
clif_sendside(bl);
return 0;
}
int bll_delete(lua_State *state, struct block_list* bl) {
if(bl->id) {
map_deliddb(bl->id);
}
map_delblock(bl);
if(bl->id>0) {
clif_lookgone(bl);
}
FREE(bl);
}
int bll_addnpc(lua_State *state, struct block_list* bl) {
struct npc_data *nd;
CALLOC(nd,struct npc_data,1);
strcpy(nd->name, lua_tostring(state,sl_memberarg(1)));
strcpy(nd->npc_name, "nothing");
nd->bl.type=BL_NPC;
nd->bl.subtype=2;
nd->bl.m=lua_tonumber(state,sl_memberarg(2));
nd->bl.x=lua_tonumber(state,sl_memberarg(3));
nd->bl.y=lua_tonumber(state,sl_memberarg(4));
nd->bl.graphic_id=0;
nd->bl.graphic_color=0;
nd->bl.prev=NULL;
nd->bl.next=NULL;
map_addblock(&nd->bl);
}
int bll_dropitem(lua_State* state, struct block_list* bl) {
int id;
int amount;
id=itemdb_id(lua_tostring(state,2));
amount=lua_tonumber(state,3);
mobdb_dropitem(id,amount,bl->m,bl->x,bl->y);
return 0;
}
void bll_extendproto(typel_class *class) {
typel_extendproto(class, "getObjectsInCell", bll_getobjects_cell);
typel_extendproto(class, "getObjectsInArea", bll_getobjects_area);
typel_extendproto(class, "getObjectsInSameMap", bll_getobjects_samemap);
typel_extendproto(class, "sendAnimation",bll_sendanim);
typel_extendproto(class, "getUsers",bll_getusers);
typel_extendproto(class, "delFromIDDB",bll_deliddb);
typel_extendproto(class, "playSound",bll_playsound);
typel_extendproto(class, "sendAction",bll_sendaction);
typel_extendproto(class, "talk",bll_talk);
typel_extendproto(class, "spawn",bll_spawn);
typel_extendproto(class, "addPermanentSpawn",bll_permspawn);
typel_extendproto(class, "curYear",bll_year);
typel_extendproto(class, "curDay",bll_day);
typel_extendproto(class, "curTime",bll_time);
typel_extendproto(class, "sendSide",bll_sendside);
typel_extendproto(class, "delete",bll_delete);
typel_extendproto(class, "addNPC",bll_addnpc);
typel_extendproto(class, "dropItem",bll_dropitem);
}
void bll_pushinst(lua_State *state, struct block_list *bl, void *param) {
if(!bl) {
lua_pushnil(state);
return;
}
if(bl->type == BL_PC) {
struct map_sessiondata *sd = map_id2sd(bl->id);
typel_pushinst(state, &pcl_type, sd, param);
} else if(bl->type == BL_MOB) {
struct mobspawn_data *mob = (struct mobspawn_data *)bl;
typel_pushinst(state, &mobl_type, mob, param);
} else if(bl->type == BL_NPC) {
struct npc_data *nd = (struct npc_data *)bl;
typel_pushinst(state, &npcl_type, nd, param);
} else if(bl->type == BL_ITEM) {
struct flooritem_data *fl = (struct flooritem_data*)bl;
typel_pushinst(state, &fll_type, fl, param);
} else lua_pushnil(state); // TODO: should this be an error?
}
int bll_getattr(lua_State *state, struct block_list *bl, char *attrname) {
if(!bl) return 0;
if(!strcmp(attrname, "x")) lua_pushnumber(state, bl->x);
else if(!strcmp(attrname, "y")) lua_pushnumber(state, bl->y);
else if(!strcmp(attrname, "m")) lua_pushnumber(state, bl->m);
else if(!strcmp(attrname, "blType")) lua_pushnumber(state,bl->type);
else if(!strcmp(attrname,"ID")) lua_pushnumber(state,bl->id);
else if(!strcmp(attrname,"pvp")) lua_pushboolean(state,map[bl->m].pvp);
else return 0; // the attribute was not handled
return 1;
}
int bll_setattr(lua_State *state, struct block_list *bl, char*attrname) {
if(!bl) return 0;
if(!strcmp(attrname,"pvp")) lua_toboolean(state,-1);
else return 0;
return 1;
}
int fll_getattr(lua_State *, struct flooritem_data *, char *);
int fll_setattr(lua_State *, struct flooritem_data *, char *);
int fll_move(lua_State *, struct flooritem_data *);
int fll_init(lua_State *, struct flooritem_data *, int, void *);
int fll_ctor(lua_State *);
void fll_staticinit() {
fll_type = typel_new("FloorItem", fll_ctor);
fll_type.getattr = fll_getattr;
fll_type.setattr = fll_setattr;
fll_type.init = fll_init;
/*typel_extendproto(&mobl_type, "attack", mobl_attack);
typel_extendproto(&mobl_type, "addHealth", mobl_addhealth);
typel_extendproto(&mobl_type, "move",mobl_move);
typel_extendproto(&mobl_type,"setDuration",mobl_setduration);
typel_extendproto(&mobl_type,"moveIntent",mobl_moveintent);
typel_extendproto(&mobl_type, "hasDuration",mobl_hasduration);
typel_extendproto(&mobl_type,"removeHealth",mobl_removehealth);
typel_extendproto(&mobl_type,"flushDuration",mobl_flushduration);
typel_extendproto(&mobl_type,"durationAmount",mobl_durationamount);
*/
bll_extendproto(&mobl_type);
}
int fll_ctor(lua_State *state) {
if(!lua_isnumber(state, 1)) luaL_argerror(state, 1, "expected number");
struct flooritem_data *fl = (struct flooritem_data*)map_id2bl(lua_tonumber(state, 1));
if(!fl) return 0;
fll_pushinst(state, fl);
return 1;
}
int fll_init(lua_State *state, struct flooritem_data *fl, int dataref, void *param) {
sl_pushref(state, dataref);
biteml_pushinst(state,&fl->data);
lua_setfield(state,-2,"data");
lua_pop(state, 1); // pop the data table
}
int fll_getattr(lua_State *state, struct flooritem_data *fl, char* attrname) {
return bll_getattr(state,&fl->bl,attrname);
}
int fll_setattr(lua_State *state, struct flooritem_data *fl, char* attrname) {
if(bll_setattr(state,&fl->bl,attrname)) return 1;
else return 0;
}
int npcl_getattr(lua_State *, struct npc_data *, char *);
void npcl_staticinit() {
npcl_type = typel_new("NPC", 0);
npcl_type.getattr = npcl_getattr;
bll_extendproto(&npcl_type);
}
int npcl_getattr(lua_State *state, struct npc_data *nd, char *attrname) {
return bll_getattr(state, &nd->bl, attrname); }
int mobl_attack(lua_State *, struct mobspawn_data *);
int mobl_addhealth(lua_State *, struct mobspawn_data *);
int mobl_getattr(lua_State *, struct mobspawn_data *, char *);
int mobl_setattr(lua_State *, struct mobspawn_data *, char *);
int mobl_move(lua_State *, struct mobspawn_data *);
int mobl_init(lua_State *, struct mobspawn_data *, int, void *);
int mobl_ctor(lua_State *);
int mobl_setduration(lua_State *,struct mobspawn_data*);
int mobl_moveintent(lua_State*,struct mobspawn_data*);
int mobl_hasduration(lua_State*, struct mobspawn_data*);
int mobl_removehealth(lua_State*,struct mobspawn_data*);
int mobl_flushduration(lua_State*,struct mobspawn_data*);
int mobl_durationamount(lua_State*,struct mobspawn_data*);
void mobl_staticinit() {
mobl_type = typel_new("Mob", mobl_ctor);
mobl_type.getattr = mobl_getattr;
mobl_type.setattr = mobl_setattr;
mobl_type.init = mobl_init;
typel_extendproto(&mobl_type, "attack", mobl_attack);
typel_extendproto(&mobl_type, "addHealth", mobl_addhealth);
typel_extendproto(&mobl_type, "move",mobl_move);
typel_extendproto(&mobl_type,"setDuration",mobl_setduration);
typel_extendproto(&mobl_type,"moveIntent",mobl_moveintent);
typel_extendproto(&mobl_type, "hasDuration",mobl_hasduration);
typel_extendproto(&mobl_type,"removeHealth",mobl_removehealth);
typel_extendproto(&mobl_type,"flushDuration",mobl_flushduration);
typel_extendproto(&mobl_type,"durationAmount",mobl_durationamount);
bll_extendproto(&mobl_type);
}
int mobl_durationamount(lua_State* state,struct mobspawn_data* mob) {
int x,id;
id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
for(x=0;x<50;x++) {
if(mob->da[x].id==id) {
if(mob->da[x].duration>0) {
lua_pushnumber(state,mob->da[x].duration);
return 1;
}
}
}
lua_pushnumber(state,0);
return 1;
}
int mobl_ctor(lua_State *state) {
if(!lua_isnumber(state, 1)) luaL_argerror(state, 1, "expected number");
struct mobspawn_data *mob = map_id2mob(lua_tonumber(state, 1));
if(!mob) return 0;
mobl_pushinst(state, mob);
return 1;
}
int mobl_removehealth(lua_State *state, struct mobspawn_data *mob) {
//struct map_sessiondata* sd=map_id2sd(lua_tonumber(state,sl_memberarg(1)));
int damage=lua_tonumber(state,sl_memberarg(1));
clif_send_mob_health(mob,damage,0);
return 0;
}
int mobl_moveintent(lua_State *state, struct mobspawn_data *mob) {
struct block_list* bl=map_id2bl(mob->target);
nullpo_ret(0,bl);
lua_pushnumber(state,move_mob_intent(mob,bl));
return 1;
}
int mobl_setduration(lua_State *state,struct mobspawn_data *mob) {
//sl_checkargs(state, "nn");
int id,time,x;
id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
time=lua_tonumber(state,sl_memberarg(2));
for(x=0;x<50;x++) {
if(mob->da[x].id==id) {
mob->da[x].duration=time;
return 0;
} else if(mob->da[x].id==0) {
mob->da[x].id=id;
mob->da[x].duration=time;
return 0;
}
}
return 0;
}
int mobl_flushduration(lua_State *state, struct mobspawn_data *mob) {
/*int x;
for(x=0;x<50;x++) {
if(mob->da[x].id>0) {
//mob->da[x].time=0;
//sl_doscript_blargs(magicdb_yname(mob->da[x].id),"uncast",1,&mob->bl);
mob->da[x].duration=250;
}
}*/
mob_flushmagic(mob);
return 0;
}
int mobl_hasduration(lua_State *state, struct mobspawn_data* mob) {
//sl_checkargs(state, "n");
int x,id;
id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
for(x=0;x<50;x++) {
if(mob->da[x].id==id) {
if(mob->da[x].duration>0) {
lua_pushboolean(state,1);
return 1;
}
}
}
lua_pushboolean(state,0);
return 1;
}
int mobl_init(lua_State *state, struct mobspawn_data *mob, int dataref, void *param) {
//int top=lua_gettop(state);
//int ntop=0;
sl_pushref(state, dataref);
if(mob->target && param == 0) {
// the param is used to stop infinite recursion
/*struct block_list *bl = map_id2bl(mob->target);
if(bl) {
bll_pushinst(state, bl, 1);
lua_setfield(state, -2, "target");
}*/
}
//ntop=lua_gettop(state);
//printf("Top is %d\n",ntop-top);
lua_pop(state, 1); // pop the data table
}
int mobl_getattr(lua_State *state, struct mobspawn_data *mob, char *attrname) {
if(bll_getattr(state, &mob->bl, attrname)) return 1;
if(!strcmp(attrname,"state")) lua_pushnumber(state,mob->state);
else if(!strcmp(attrname,"type")) lua_pushnumber(state,mobdb_type(mob->id));
else if(!strcmp(attrname,"side")) lua_pushnumber(state,mob->side);
//else if(!strcmp(attrname,"blType")) lua_pushnumber(state,mob->bl.type);
else if(!strcmp(attrname,"name")) lua_pushstring(state,mobdb_name(mob->id));
else if(!strcmp(attrname,"paralyzed")) lua_pushboolean(state,mob->paralyzed);
else if(!strcmp(attrname,"blind")) lua_pushboolean(state,mob->blind);
else if(!strcmp(attrname,"hit")) lua_pushnumber(state,mobdb_hit(mob->id));
else if(!strcmp(attrname,"level")) lua_pushnumber(state,mobdb_level(mob->id));
else if(!strcmp(attrname,"grace")) lua_pushnumber(state,mobdb_grace(mob->id));
else if(!strcmp(attrname,"might")) lua_pushnumber(state,mobdb_might(mob->id));
else if(!strcmp(attrname,"health")) lua_pushnumber(state,mob->current_vita);
else if(!strcmp(attrname,"maxHealth")) lua_pushnumber(state,mobdb_getvita(mob->id));
else if(!strcmp(attrname,"ac")) lua_pushnumber(state,mob->ac);
else if(!strcmp(attrname,"baseAc")) lua_pushnumber(state,mobdb_baseac(mob->id));
else if(!strcmp(attrname,"attacker")) lua_pushnumber(state,mob->attacker);
else if(!strcmp(attrname,"confused")) lua_pushboolean(state,mob->confused);
else if(!strcmp(attrname,"controlled")) lua_pushboolean(state,mob->controlled);
else if(!strcmp(attrname,"controller")) lua_pushnumber(state,mob->controller);
else if(!strcmp(attrname,"sleep")) lua_pushnumber(state,mob->sleep);
else if(!strcmp(attrname,"target")) lua_pushnumber(state,mob->target);
else if(!strcmp(attrname,"confuseTarget")) lua_pushnumber(state,mob->confused_target);
else if(!strcmp(attrname,"deduction")) lua_pushnumber(state,mob->deduction);
else if(!strcmp(attrname,"sound")) lua_pushnumber(state,mobdb_sound(mob->id));
//else if(!strcmp(attrname,"attacker"
//else if(!strcmp(attrname,"graphic"
else return 0;
return 1;
}
int mobl_setattr(lua_State *state, struct mobspawn_data *mob, char* attrname) {
if(bll_setattr(state,&mob->bl,attrname)) return 1;
if(!strcmp(attrname,"x")) mob->bl.x=lua_tonumber(state,-1);
else if(!strcmp(attrname,"y")) mob->bl.y=lua_tonumber(state,-1);
else if(!strcmp(attrname,"m")) mob->bl.m=lua_tonumber(state,-1);
else if(!strcmp(attrname,"side")) mob->side=lua_tonumber(state,-1);
else if(!strcmp(attrname,"time")) mob->time=lua_tonumber(state,-1);
else if(!strcmp(attrname,"paralyzed")) mob->paralyzed=lua_toboolean(state,-1);
else if(!strcmp(attrname,"blind")) mob->blind=lua_toboolean(state,-1);
else if(!strcmp(attrname,"health")) mob->current_vita=lua_tonumber(state,-1);
else if(!strcmp(attrname,"ac")) mob->ac=lua_tonumber(state,-1);
else if(!strcmp(attrname,"health")) mob->current_vita=lua_tonumber(state,-1);
else if(!strcmp(attrname,"attacker")) mob->attacker=lua_tonumber(state,-1);
else if(!strcmp(attrname,"confused")) mob->confused=lua_toboolean(state,-1);
else if(!strcmp(attrname,"controlled")) mob->controlled=lua_toboolean(state,-1);
else if(!strcmp(attrname,"controller")) mob->controller=lua_tonumber(state,-1);
else if(!strcmp(attrname,"sleep")) mob->sleep=lua_tonumber(state,-1);
else if(!strcmp(attrname,"target")) mob->target=lua_tonumber(state,-1);
else if(!strcmp(attrname,"confuseTarget")) mob->confused_target=lua_tonumber(state,-1);
else if(!strcmp(attrname,"deduction")) mob->deduction=lua_tonumber(state,-1);
else if(!strcmp(attrname,"state")) mob->state=lua_tonumber(state,-1);
else return 0;
return 1;
}
int mobl_attack(lua_State *state, struct mobspawn_data *mob) {
sl_checkargs(state, "u");
struct map_sessiondata *attacksd = typel_topointer(state, sl_memberarg(1));
mob_attack(mob, attacksd);
return 0;
}
int mobl_addhealth(lua_State *state, struct mobspawn_data *mob) {
sl_checkargs(state, "n");
// TODO: this bounds checking on the health should probably be factored out
int addvita = lua_tonumber(state, sl_memberarg(1));
int maxvita = mobdb_getvita(mob->id);
mob->current_vita += addvita;
if(mob->current_vita > maxvita) mob->current_vita = maxvita;
if(mob->current_vita < 0) mob->current_vita = 0;
return 0;
}
int mobl_move(lua_State *state, struct mobspawn_data *mob) {
lua_pushboolean(state,move_mob(mob));
return 1;
}
int pcl_addmagic(lua_State *, struct map_sessiondata *);
int pcl_addhealth(lua_State *, struct map_sessiondata *);
int pcl_resurrect(lua_State *, struct map_sessiondata *);
int pcl_warp(lua_State *, struct map_sessiondata *);
int pcl_useitem(lua_State *, struct map_sessiondata *);
int pcl_level(lua_State *, struct map_sessiondata *);
int pcl_sendminitext(lua_State*,struct map_sessiondata *);
int pcl_setduration(lua_State*,struct map_sessiondata *);
int pcl_dialog(lua_State *, struct map_sessiondata *);
int pcl_getattr(lua_State *, struct map_sessiondata *, char *);
int pcl_setattr(lua_State *, struct map_sessiondata *, char *);
int pcl_setaether(lua_State *, struct map_sessiondata *);
int pcl_hasduration(lua_State *, struct map_sessiondata *);
int pcl_addlegend(lua_State *, struct map_sessiondata *);
int pcl_buy(lua_State *, struct map_sessiondata *);
int pcl_input(lua_State *, struct map_sessiondata *);
int pcl_sell(lua_State *,struct map_sessiondata *);
int pcl_sell2(lua_State *,struct map_sessiondata *);
int pcl_sendstatus(lua_State*,struct map_sessiondata *);
int pcl_getinventoryitem(lua_State*,struct map_sessiondata *);
int pcl_getequippeditem(lua_State*,struct map_sessiondata *);
int pcl_removelegendbyname(lua_State*,struct map_sessiondata *);
int pcl_removelegendbycolor(lua_State*,struct map_sessiondata *);
int pcl_menu(lua_State *, void*);
int pcl_showhealth(lua_State *, struct map_sessiondata *);
int pcl_addclan(lua_State *, struct map_sessiondata *);
int pcl_updatestate(lua_State*, struct map_sessiondata *);
int pcl_ctor(lua_State *);
int pcl_hasequipped(lua_State*, struct map_sessiondata *);
int pcl_killcount(lua_State*, struct map_sessiondata *);
int pcl_killrank(lua_State*,struct map_sessiondata *);
int pcl_flushkills(lua_State*, struct map_sessiondata *);
int pcl_removeinventoryitem(lua_State*, struct map_sessiondata*);
int pcl_additem(lua_State*,struct map_sessiondata*);
int pcl_init(lua_State *, struct map_sessiondata *, int, void *);
int pcl_showboard(lua_State *, struct map_sessiondata*);
int pcl_hasitem(lua_State*, struct map_sessiondata*);
int pcl_addspell(lua_State*, struct map_sessiondata*);
int pcl_removespell(lua_State*, struct map_sessiondata*);
int pcl_broadcast(lua_State*, struct map_sessiondata*);
int pcl_mapselect(lua_State*, struct map_sessiondata*);
int pcl_hasspell(lua_State*, struct map_sessiondata*);
int pcl_flushduration(lua_State*,struct map_sessiondata*);
int pcl_hasspace(lua_State*,struct map_sessiondata*);
int pcl_deductarmor(lua_State*,struct map_sessiondata*);
int pcl_updateinv(lua_State*,struct map_sessiondata*);
int pcl_durationamount(lua_State*,struct map_sessiondata*);
int pcl_addguide(lua_State*,struct map_sessiondata*);
int pcl_delguide(lua_State*,struct map_sessiondata*);
int pcl_popup(lua_State*,struct map_sessiondata*);
int pcl_menu2(lua_State*, void*);
int pcl_powerboard(lua_State*, struct map_sessiondata*);
void pcl_staticinit() {
pcl_type = typel_new("Player", pcl_ctor);
pcl_type.getattr = pcl_getattr;
pcl_type.setattr = pcl_setattr;
pcl_type.init = pcl_init;
typel_extendproto(&pcl_type, "addHealth", pcl_addhealth);
typel_extendproto(&pcl_type, "addMagic", pcl_addmagic);
typel_extendproto(&pcl_type, "menu", pcl_menu);
typel_extendproto(&pcl_type, "resurrect", pcl_resurrect);
typel_extendproto(&pcl_type, "sendMinitext",pcl_sendminitext);
typel_extendproto(&pcl_type, "setDuration",pcl_setduration);
typel_extendproto(&pcl_type, "dialog", pcl_dialog);
typel_extendproto(&pcl_type, "setAether",pcl_setaether);
typel_extendproto(&pcl_type, "hasDuration",pcl_hasduration);
typel_extendproto(&pcl_type, "hasSpace",pcl_hasspace);
typel_extendproto(&pcl_type, "flushDuration",pcl_flushduration);
typel_extendproto(&pcl_type, "addLegend",pcl_addlegend);
typel_extendproto(&pcl_type, "buy",pcl_buy);
typel_extendproto(&pcl_type, "input",pcl_input);
typel_extendproto(&pcl_type, "sell",pcl_sell);
typel_extendproto(&pcl_type, "sell2",pcl_sell2);
typel_extendproto(&pcl_type, "sendStatus",pcl_sendstatus);
typel_extendproto(&pcl_type, "getInventoryItem",pcl_getinventoryitem);
typel_extendproto(&pcl_type, "getEquippedItem",pcl_getequippeditem);
typel_extendproto(&pcl_type, "removeLegendbyName",pcl_removelegendbyname);
typel_extendproto(&pcl_type, "removeLegendbyColor",pcl_removelegendbycolor);
typel_extendproto(&pcl_type, "warp",pcl_warp);
typel_extendproto(&pcl_type, "showHealth",pcl_showhealth);
typel_extendproto(&pcl_type, "addClan", pcl_addclan);
typel_extendproto(&pcl_type, "updateState",pcl_updatestate);
typel_extendproto(&pcl_type, "hasEquipped",pcl_hasequipped);
typel_extendproto(&pcl_type, "killCount",pcl_killcount);
typel_extendproto(&pcl_type, "killRank",pcl_killrank);
typel_extendproto(&pcl_type, "flushKills",pcl_flushkills);
typel_extendproto(&pcl_type, "removeItem",pcl_removeinventoryitem);
typel_extendproto(&pcl_type, "addItem",pcl_additem);
typel_extendproto(&pcl_type, "showBoard",pcl_showboard);
typel_extendproto(&pcl_type, "hasItem",pcl_hasitem);
typel_extendproto(&pcl_type, "addSpell",pcl_addspell);
typel_extendproto(&pcl_type, "removeSpell",pcl_removespell);
typel_extendproto(&pcl_type, "hasSpell",pcl_hasspell);
typel_extendproto(&pcl_type, "broadcast",pcl_broadcast);
typel_extendproto(&pcl_type, "mapSelection",pcl_mapselect);
typel_extendproto(&pcl_type, "deductArmor",pcl_deductarmor);
typel_extendproto(&pcl_type, "updateInv",pcl_updateinv);
typel_extendproto(&pcl_type, "durationAmount",pcl_durationamount);
typel_extendproto(&pcl_type, "addGuide",pcl_addguide);
typel_extendproto(&pcl_type, "delGuide",pcl_delguide);
typel_extendproto(&pcl_type, "popUp",pcl_popup);
typel_extendproto(&pcl_type, "menu2",pcl_menu2);
typel_extendproto(&pcl_type, "powerBoard",pcl_powerboard);
bll_extendproto(&pcl_type);
}
int pcl_menu2(lua_State *state, void *self) {
struct map_sessiondata *sd = (struct map_sessiondata*)self;
sl_checkargs(state, "st");
int size = lua_objlen(state, sl_memberarg(2));
char *menuopts[size + 1];
lua_pushnil(state);
while(lua_next(state, sl_memberarg(2)) != 0) {
// key is at -2, value at -1
int index = lua_tonumber(state, -2);
menuopts[index] = lua_tostring(state, -1);
lua_pop(state, 1);
}
char *topic = lua_tostring(state, sl_memberarg(1));
clif_scriptmenu2(sd, 0, topic, menuopts, size);
//sd->coroutine = state; TEMP
return lua_yield(state, 0);
}
int pcl_popup(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"s");
clif_popup(sd,lua_tostring(state,2));
return 0;
}
int pcl_addguide(lua_State *state, struct map_sessiondata *sd) {
int id=guidedb_id(lua_tostring(state,sl_memberarg(1)));
int x;
for(x=0;x<256;x++) {
if(sd->status.guide[x]==id) return 0;
if(sd->status.guide[x]==0) {
sd->status.guide[x]=id;
clif_sendguidespecific(sd,id);
return 0;
}
}
return 0;
}
int pcl_delguide(lua_State *state, struct map_sessiondata *sd) {
int id=guidedb_id(lua_tostring(state,sl_memberarg(1)));
int x;
for(x=0;x<256;x++) {
if(sd->status.guide[x]==id) {
sd->status.guide[x]=0;
return 0;
}
}
return 0;
}
int pcl_durationamount(lua_State *state, struct map_sessiondata *sd) {
int x,id;
id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
for(x=0;x<200;x++) {
if(sd->status.dura_aether[x].id==id) {
if(sd->status.dura_aether[x].duration>0) {
lua_pushnumber(state,sd->status.dura_aether[x].duration);
return 1;
}
}
}
lua_pushnumber(state,0);
return 1;
}
int pcl_updateinv(lua_State *state, struct map_sessiondata *sd) {
pc_loaditem(sd);
return 0;
}
int pcl_deductarmor(lua_State *state, struct map_sessiondata *sd) {
clif_deductarmor(sd);
return 0;
}
int pcl_flushduration(lua_State *state, struct map_sessiondata *sd) {
int x;
for(x=0;x<200;x++) {
if(sd->status.dura_aether[x].id>0) {
sd->status.dura_aether[x].duration=250;
//sl_doscript_blargs(magicdb_yname(sd->status.dura_aether[x].id),"uncast",1,&sd->bl);
clif_send_duration(sd,sd->status.dura_aether[x].id,0);
//sd->status.dura_aether[x].id=0;
}
}
return 0;
}
int pcl_broadcast(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"ns");
clif_broadcast(lua_tostring(state,sl_memberarg(2)),lua_tonumber(state,sl_memberarg(1)));
return 0;
}
int pcl_killcount(lua_State *state, struct map_sessiondata *sd) {
int x;
int id;
id=mobdb_id(lua_tostring(state,sl_memberarg(1)));
for(x=0;x<10;x++) {
if(sd->status.quest[x].mob_id==id) {
lua_pushnumber(state,sd->status.quest[x].amount);
return 1;
}
}
lua_pushnumber(state,0);
return 1;
}
int pcl_killrank(lua_State *state, struct map_sessiondata *sd) {
int x;
int id;
id=mobdb_id(lua_tostring(state,sl_memberarg(1)));
for(x=0;x<10;x++) {
if(sd->status.quest[x].mob_id==id) {
lua_pushnumber(state,x+1);
return 1;
}
}
lua_pushnumber(state,0);
return 1;
}
int pcl_flushkills(lua_State *state, struct map_sessiondata *sd) {
int x;
for(x=0;x<10;x++) {
sd->status.quest[x].mob_id=0;
sd->status.quest[x].amount=0;
}
return 0;
}
int pcl_showhealth(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"n");
clif_send_pc_health(sd,1,lua_tonumber(state,sl_memberarg(1)));
return 0;
}
int pcl_addclan(lua_State *state, struct map_sessiondata *sd) {
struct clan_data* clan;
sl_checkargs(state,"s");
char* c_name=lua_tostring(state,sl_memberarg(1));
clan=clandb_searchname(c_name);
if(clan) {
lua_pushboolean(state,0);
} else {
clandb_add(sd,c_name);
lua_pushboolean(state,1);
}
return 1;
}
int pcl_hasequipped(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"t");
int found=0;
int count=0;
int id;
int x;
lua_pushnil(state);
while (lua_next(state, sl_memberarg(1)) != 0) {
id=0;
// key is at -2, value is at -1
if(lua_isstring(state,-1)) {
id=itemdb_id(lua_tostring(state,-1));
} else {
id=lua_tonumber(state,-1);
}
count++;
for(x=0;x<15;x++) {
if((sd->status.equip[x].id==id) && (id>0)) {
found++;
break;
}
}
lua_pop(state, 1);
}
if(found==count) {
lua_pushboolean(state,1);
} else {
lua_pushboolean(state,0);
}
return 1;
}
int pcl_ctor(lua_State *state) {
struct map_sessiondata *sd;
if(lua_isnumber(state, 2)) {
int id = lua_tonumber(state, 2);
sd = map_id2sd(id);
if(!sd) return luaL_error(state, "invalid player id (%i)", id);
} else if(lua_isstring(state, 2)) {
char *name = lua_tostring(state, 2);
sd = map_name2sd(name);
if(!sd) return luaL_error(state, "invalid player name (%s)", name);
} else luaL_argerror(state, 1, "expected string or number");
pcl_pushinst(state, sd);
return 1;
}
int pcl_setattr(lua_State *state, struct map_sessiondata *sd, char *attrname) {
if(bll_setattr(state,&sd->bl,attrname)) return 1;
if(!strcmp(attrname, "npcGraphic")) sd->npc_g = lua_tonumber(state, -1);
else if(!strcmp(attrname, "npcColor")) sd->npc_gc = lua_tonumber(state, -1);
else if(!strcmp(attrname, "title")) strcpy(sd->status.title,lua_tostring(state,-1));
else if(!strcmp(attrname, "clanTitle")) strcpy(sd->status.clan_title,lua_tostring(state,-1));
else if(!strcmp(attrname, "maxHealth")) sd->max_hp = lua_tonumber(state,-1);
else if(!strcmp(attrname, "maxMagic")) sd->max_mp = lua_tonumber(state,-1);
else if(!strcmp(attrname, "polearm")) sd->polearm=lua_tonumber(state,-1);
else if(!strcmp(attrname, "rage")) sd->rage=lua_tonumber(state,-1);
else if(!strcmp(attrname, "clan")) sd->status.clan_id=lua_tonumber(state,-1);
else if(!strcmp(attrname, "gmLevel")) sd->status.gm_level=lua_tonumber(state,-1);
else if(!strcmp(attrname,"class")) sd->status.class=lua_tonumber(state,-1);
else if(!strcmp(attrname,"rank")) sd->status.subclass=lua_tonumber(state,-1);
else if(!strcmp(attrname,"health")) sd->status.hp=lua_tonumber(state,-1);
else if(!strcmp(attrname,"magic")) sd->status.mp=lua_tonumber(state,-1);
else if(!strcmp(attrname,"baseHealth")) sd->status.basehp=lua_tonumber(state,-1);
else if(!strcmp(attrname,"baseMagic")) sd->status.basemp=lua_tonumber(state,-1);
else if(!strcmp(attrname,"exp")) sd->status.exp=lua_tonumber(state,-1);
else if(!strcmp(attrname,"expCounter")) sd->status.expcounter=lua_tonumber(state,-1);
else if(!strcmp(attrname,"state")) sd->status.state=lua_tonumber(state,-1);
else if(!strcmp(attrname,"hair")) sd->status.hair=lua_tonumber(state,-1);
else if(!strcmp(attrname,"paralyzed")) sd->paralyzed=lua_toboolean(state,-1);
else if(!strcmp(attrname,"blind")) { sd->blind=lua_toboolean(state,-1); clif_sendstatus2(sd); }
else if(!strcmp(attrname,"backstab")) sd->backstab=lua_tonumber(state,-1);
else if(!strcmp(attrname,"flank")) sd->flank=lua_tonumber(state,-1);
else if(!strcmp(attrname,"ac")) sd->ac=lua_tonumber(state,-1);
else if(!strcmp(attrname,"dam")) sd->dam=lua_tonumber(state,-1);
else if(!strcmp(attrname,"hit")) sd->hit=lua_tonumber(state,-1);
else if(!strcmp(attrname,"might")) sd->might=lua_tonumber(state,-1);
else if(!strcmp(attrname,"will")) sd->will=lua_tonumber(state,-1);
else if(!strcmp(attrname,"grace")) sd->grace=lua_tonumber(state,-1);
else if(!strcmp(attrname,"boardDel")) sd->board_candel=lua_tonumber(state,-1);
else if(!strcmp(attrname,"boardWrite")) sd->board_canwrite=lua_tonumber(state,-1);
else if(!strcmp(attrname,"side")) sd->status.side=lua_tonumber(state,-1);
else if(!strcmp(attrname,"attackSpeed")) sd->attack_speed=lua_tonumber(state,-1);
else if(!strcmp(attrname,"enchant")) sd->enchanted=lua_tonumber(state,-1);
else if(!strcmp(attrname,"money")) sd->status.money=lua_tonumber(state,-1);
else if(!strcmp(attrname,"confused")) sd->confused=lua_toboolean(state,-1);
else if(!strcmp(attrname,"skinColor")) sd->status.skin_color=lua_tonumber(state,-1);
else if(!strcmp(attrname,"target")) sd->target=lua_tonumber(state,-1);
else if(!strcmp(attrname,"deduction")) sd->deduction=lua_tonumber(state,-1);
else if(!strcmp(attrname,"hairColor")) sd->status.hair_color=lua_tonumber(state,-1);
else if(!strcmp(attrname,"face")) sd->status.face=lua_tonumber(state,-1);
else if(!strcmp(attrname,"faceColor")) sd->status.face_color=lua_tonumber(state,-1);
else if(!strcmp(attrname,"speed")) sd->speed=lua_tonumber(state,-1);
else if(!strcmp(attrname,"armorColor")) sd->status.armor_color=lua_tonumber(state,-1);
else if(!strcmp(attrname,"spouse")) sd->status.spouse=lua_tonumber(state,-1);
else if(!strcmp(attrname,"disguise")) sd->disguise=lua_tonumber(state,-1);
else if(!strcmp(attrname,"disguiseColor")) sd->disguise_color=lua_tonumber(state,-1);
else if(!strcmp(attrname,"attacker")) sd->attacker=lua_tonumber(state,-1);
else if(!strcmp(attrname,"invis")) sd->invis=lua_tonumber(state,-1);
else if(!strcmp(attrname,"coContainer")) sd->coref_container=lua_tonumber(state,-1);
//else if(!strcmp(attrname,"expCounter")) sd->status.
else return 0;
return 1;
}
int pcl_dialog(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state, "st");
int previous = 0, next = 0;
lua_pushnil(state);
while (lua_next(state, sl_memberarg(2)) != 0) {
// key is at -2, value is at -1
if(!strcmp(lua_tostring(state, -1), "previous")) previous = 1;
else if(!strcmp(lua_tostring(state, -1), "next")) next = 1;
lua_pop(state, 1);
}
char *msg = lua_tostring(state, sl_memberarg(1));
//sd->coroutine = state; TEMP
clif_scriptmes(sd, 0, msg, previous, next);
return lua_yield(state, 0);
}
int pcl_init(lua_State *state, struct map_sessiondata *sd, int dataref, void *param) {
//struct map_sessiondata *tsd;
//int top=lua_gettop(state);
//int ntop=0;
int userc=0;
//if(!sd) {
//luaL_error(state,"cannot do that.");
//sl_err_print(state);
// lua_pop(state,1);
// return 0;
//}
sl_pushref(state, dataref);
regl_pushinst(state, sd);
lua_setfield(state, -2, "registry");
mapregl_pushinst(state,sd);
lua_setfield(state,-2,"mapRegistry");
/*if(sd->target) {
if(sd->target == sd->bl.id) {
lua_pushvalue(state, -2); // push a copy of the player object
lua_setfield(state, -2, "target");
} else if(param == 0) {
// the param is used to stop infinite recursion
struct block_list *bl = map_id2bl(sd->target);
if(bl) {
bll_pushinst(state, bl, 1);
lua_setfield(state, -2, "target");
}
}
}*/
if(sd->group_count > 0) {
int i;
lua_newtable(state);
for(i = 0; i < sd->group_count; ++i) {
lua_pushnumber(state, sd->group[i]);
lua_rawseti(state, -2, i + 1);
}
lua_setfield(state, -2, "group");
}
//lua_newtable(state);
//map_foreachinarea(sl_mob_look,sd->bl.m,sd->bl.x,sd->bl.y,SAMEMAP,BL_MOB,sd);
//lua_setfield(state,-2,"mobs");
/*int i;
lua_newtable(state);
for(i=0;i<26;i++) {
lua_pushnumber(state, sd->status.inventory[i].id);
lua_rawseti(state, -2, i + 1);
}
lua_setfield(state,-2,"inventory");
*/
//ntop=lua_gettop(state);
//printf("Player Top is %d\n",ntop-top);
lua_pop(state, 1); // pop the data table
}
int sl_mob_look(struct block_list *bl, va_list ap) {
return 0;
}
int pcl_getattr(lua_State *state, struct map_sessiondata *sd, char *attrname) {
if(bll_getattr(state, &sd->bl, attrname)) return 1;
if(!strcmp(attrname, "health")) lua_pushnumber(state, sd->status.hp);
else if(!strcmp(attrname, "magic")) lua_pushnumber(state, sd->status.mp);
else if(!strcmp(attrname, "level")) lua_pushnumber(state, sd->status.level);
else if(!strcmp(attrname, "name")) lua_pushstring(state, sd->status.name);
else if(!strcmp(attrname, "title")) lua_pushstring(state, sd->status.title);
else if(!strcmp(attrname,"maxHealth")) lua_pushnumber(state,sd->max_hp);
else if(!strcmp(attrname,"maxMagic")) lua_pushnumber(state,sd->max_mp);
else if(!strcmp(attrname,"rage")) {
if(sd->rage) {
lua_pushnumber(state,sd->rage);
} else {
lua_pushnumber(state,1);
}
}
else if(!strcmp(attrname,"clanTitle")) lua_pushstring(state,sd->status.clan_title);
else if(!strcmp(attrname,"polearm")) lua_pushnumber(state,sd->polearm);
else if(!strcmp(attrname,"clan")) lua_pushnumber(state,sd->status.clan_id);
else if(!strcmp(attrname,"gmLevel")) lua_pushnumber(state,sd->status.gm_level);
else if(!strcmp(attrname,"class")) lua_pushnumber(state,sd->status.class);
else if(!strcmp(attrname,"rank")) lua_pushnumber(state,sd->status.subclass);
else if(!strcmp(attrname,"baseHealth")) lua_pushnumber(state,sd->status.basehp);
else if(!strcmp(attrname,"baseMagic")) lua_pushnumber(state,sd->status.basemp);
else if(!strcmp(attrname,"exp")) lua_pushnumber(state,sd->status.exp);
else if(!strcmp(attrname,"expCounter")) lua_pushnumber(state,sd->status.expcounter);
else if(!strcmp(attrname,"state")) lua_pushnumber(state,sd->status.state);
else if(!strcmp(attrname,"hair")) lua_pushnumber(state,sd->status.hair);
else if(!strcmp(attrname,"paralyzed")) lua_pushboolean(state,sd->paralyzed);
else if(!strcmp(attrname,"blind")) lua_pushboolean(state,sd->blind);
else if(!strcmp(attrname,"board")) lua_pushnumber(state,sd->board);
else if(!strcmp(attrname,"boardDel")) lua_pushnumber(state,sd->board_candel);
else if(!strcmp(attrname,"boardWrite")) lua_pushnumber(state,sd->board_canwrite);
else if(!strcmp(attrname,"sex")) lua_pushnumber(state,sd->status.sex);
else if(!strcmp(attrname,"side")) lua_pushnumber(state,sd->status.side);
else if(!strcmp(attrname,"grace")) lua_pushnumber(state,sd->grace);
else if(!strcmp(attrname,"might")) lua_pushnumber(state,sd->might);
else if(!strcmp(attrname,"will")) lua_pushnumber(state,sd->will);
else if(!strcmp(attrname,"ac")) lua_pushnumber(state,sd->ac);
else if(!strcmp(attrname,"dam")) lua_pushnumber(state,sd->dam);
else if(!strcmp(attrname,"hit")) lua_pushnumber(state,sd->hit);
else if(!strcmp(attrname,"attackSpeed")) lua_pushnumber(state,sd->attack_speed);
else if(!strcmp(attrname,"question")) lua_pushstring(state,sd->question);
else if(!strcmp(attrname,"enchant")) lua_pushnumber(state,sd->enchanted);
else if(!strcmp(attrname,"speech")) lua_pushstring(state,sd->speech);
else if(!strcmp(attrname,"money")) lua_pushnumber(state,sd->status.money);
else if(!strcmp(attrname,"confused")) lua_pushboolean(state,sd->confused);
else if(!strcmp(attrname,"skinColor")) lua_pushnumber(state,sd->status.skin_color);
else if(!strcmp(attrname,"target")) lua_pushnumber(state,sd->target);
else if(!strcmp(attrname,"deduction")) lua_pushnumber(state,sd->deduction);
else if(!strcmp(attrname,"speed")) lua_pushnumber(state,sd->speed);
else if(!strcmp(attrname,"spouse")) lua_pushnumber(state,sd->status.spouse);
else if(!strcmp(attrname,"disguise")) lua_pushnumber(state,sd->disguise);
else if(!strcmp(attrname,"disguiseColor")) lua_pushnumber(state,sd->disguise_color);
else if(!strcmp(attrname,"attacker")) lua_pushnumber(state,sd->attacker);
else if(!strcmp(attrname,"invis")) lua_pushnumber(state,sd->invis);
else if(!strcmp(attrname,"armorColor")) lua_pushnumber(state,sd->status.armor_color);
//else if(!strcmp(attrname,"blType")) lua_pushnumber(state,sd->bl.type);
//else if(!strcmp(attrname,"expCounter")) lua_pushnumber(state,sd->status.exp_counter);
// TODO: else if(!strcmp(attrname, "clan")) lua_pushnumber(state, sd->status.clan);
else return 0; // the attribute wasn't handled
return 1;
}
int pcl_useitem(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state, "s");
char *itemname = lua_tostring(state, sl_memberarg(1));
int i;
for(i = 0; i < 26; ++i) {
if(!strcmpi(itemdb_name(sd->status.inventory[i].id), itemname)) {
pc_useitem(sd, i);
return 0;
}
}
return 0;
}
int pcl_warp(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state, "nn");
int m = lua_tonumber(state, sl_memberarg(1)),
x = lua_tonumber(state, sl_memberarg(2)),
y = lua_tonumber(state, sl_memberarg(3));
pc_warp(sd, m, x, y);
}
int pcl_resurrect(lua_State *state, struct map_sessiondata *sd) {
pc_res(sd);
return 0;
}
int pcl_addhealth(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state, "n");
pc_heal(sd, lua_tonumber(state, sl_memberarg(1)), 0);
return 0;
}
int pcl_addmagic(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state, "n");
pc_heal(0, sd, lua_tonumber(state, sl_memberarg(1)));
return 0;
}
int pcl_menu(lua_State *state, void *self) {
struct map_sessiondata *sd = (struct map_sessiondata*)self;
sl_checkargs(state, "st");
int size = lua_objlen(state, sl_memberarg(2));
char *menuopts[size + 1];
lua_pushnil(state);
while(lua_next(state, sl_memberarg(2)) != 0) {
// key is at -2, value at -1
int index = lua_tonumber(state, -2);
menuopts[index] = lua_tostring(state, -1);
lua_pop(state, 1);
}
char *topic = lua_tostring(state, sl_memberarg(1));
sd->in_menu=1;
sd->co_timer=0;
clif_scriptmenu(sd, 0, topic, menuopts, size);
//sd->coroutine = state; TEMP
return lua_yield(state, 0);
}
int pcl_sendminitext(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state, "s");
char* msg;
msg=lua_tostring(state,sl_memberarg(1));
clif_sendminitext(sd,msg,strlen(msg));
return 0;
}
int pcl_setduration(lua_State *state, struct map_sessiondata *sd) {
//sl_checkargs(state, "nn");
int id,time,x;
id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
time=lua_tonumber(state,sl_memberarg(2));
//printf("%d\n",id);
for(x=0;x<200;x++) {
if(sd->status.dura_aether[x].id==id) {
sd->status.dura_aether[x].duration=time;
clif_send_duration(sd,id,time/1000);
return 0;
} else if(sd->status.dura_aether[x].id==0) {
sd->status.dura_aether[x].id=id;
sd->status.dura_aether[x].duration=time;
clif_send_duration(sd,id,time/1000);
return 0;
}
}
return 0;
}
int pcl_setaether(lua_State *state, struct map_sessiondata *sd) {
int id;
int time;
int x;
id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
time=lua_tonumber(state,sl_memberarg(2));
for(x=0;x<200;x++) {
if(sd->status.dura_aether[x].id==id) {
sd->status.dura_aether[x].aether=time;
clif_send_aether(sd,id,time/1000);
return 0;
}
if(sd->status.dura_aether[x].id==0) { //blank
sd->status.dura_aether[x].aether=time;
if(!sd->status.dura_aether[x].duration) sd->status.dura_aether[x].duration=-1;
sd->status.dura_aether[x].id=id;
clif_send_aether(sd,id,time/1000);
return 0;
}
}
return 0;
}
int pcl_hasduration(lua_State *state, struct map_sessiondata *sd) {
//sl_checkargs(state, "n");
int x,id;
id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
for(x=0;x<50;x++) {
if(sd->status.dura_aether[x].id==id) {
if(sd->status.dura_aether[x].duration>0) {
lua_pushboolean(state,1);
return 1;
}
}
}
lua_pushboolean(state,0);
return 1;
}
int pcl_addlegend(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"ssnn");
int icon,color,x;
int y=0;
int found=0;
icon=lua_tonumber(state,sl_memberarg(3));
color=lua_tonumber(state,sl_memberarg(4));
for(x=0;x<200;x++) {
if(!strcmpi(sd->status.legends[x].name,lua_tostring(state,sl_memberarg(2)))) {
y=1;
}
if(y) {
memset(sd->status.legends[x].text,0,64);
memset(sd->status.legends[x].name,0,32);
strcpy(sd->status.legends[x].text,sd->status.legends[x+1].text);
strcpy(sd->status.legends[x].name,sd->status.legends[x+1].name);
sd->status.legends[x].icon=sd->status.legends[x+1].icon;
sd->status.legends[x].color=sd->status.legends[x+1].color;
}
}
for(x=0;x<200;x++) {
if(!strlen(sd->status.legends[x].text)) {
memset(sd->status.legends[x].text,0,64);
memset(sd->status.legends[x].name,0,32);
strcpy(sd->status.legends[x].text,lua_tostring(state,sl_memberarg(1)));
strcpy(sd->status.legends[x].name,lua_tostring(state,sl_memberarg(2)));
sd->status.legends[x].icon=icon;
sd->status.legends[x].color=color;
return 0;
}
}
/*for(x=0;x<200;x++) {
if(strlen(sd->status.legends[x].text)<1) {
strcpy(sd->status.legends[x].text,lua_tostring(state,sl_memberarg(1)));
strcpy(sd->status.legends[x].name,lua_tostring(state,sl_memberarg(2)));
sd->status.legends[x].icon=icon;
sd->status.legends[x].color=color;
return 0;
}
if(!strcmpi(sd->status.legends[x].name,lua_tostring(state,sl_memberarg(2)))) {
strcpy(sd->status.legends[x].text,lua_tostring(state,sl_memberarg(1)));
sd->status.legends[x].icon=icon;
sd->status.legends[x].color=color;
return 0;
}
}*/
return 0;
}
int pcl_buy(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"stt");
int x;
int amount=lua_objlen(state,sl_memberarg(2));
struct item_data *item[amount+1];
int var2[amount+1];
char* dialog;
lua_pushnil(state);
while(lua_next(state, sl_memberarg(2)) != 0) {
// key is at -2, value at -1
int index = lua_tonumber(state, -2);
item[index-1] = itemdb_search(itemdb_id(lua_tostring(state, -1)));
//var2[index-1]=1;
lua_pop(state, 1);
}
lua_pushnil(state);
while(lua_next(state, sl_memberarg(3)) != 0) {
int index=lua_tonumber(state,-2);
var2[index-1]=lua_tonumber(state,-1);
lua_pop(state,1);
}
dialog=lua_tostring(state,sl_memberarg(1));
sd->in_menu=1;
sd->co_timer=0;
clif_buydialog(sd,0,dialog,item,var2,amount);
// sd->coroutine=state;//sd->coroutine=state; TEMP
return lua_yield(state,0);
}
int pcl_mapselect(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"st");
int index=0;
int key=0;
char* wm;
int map_x0[255];
int map_y0[255];
char* map_name[255];
int map_id[255];
int map_x1[255];
int map_y1[255];
wm=lua_tostring(state,sl_memberarg(1));
lua_pushnil(state);
while(lua_next(state,sl_memberarg(2)) !=0) {
if(key==6) {
key=0;
index++;
}
switch(key) {
case 0:
map_x0[index]=lua_tonumber(state,-1);
break;
case 1:
map_y0[index]=lua_tonumber(state,-1);
break;
case 2:
map_name[index]=lua_tostring(state,-1);
break;
case 3:
map_id[index]=lua_tonumber(state,-1);
break;
case 4:
map_x1[index]=lua_tonumber(state,-1);
break;
case 5:
map_y1[index]=lua_tonumber(state,-1);
break;
}
key++;
lua_pop(state,1);
}
clif_mapselect(sd,wm,map_x0,map_y0,map_name,map_id,map_x1,map_y1,index);
return 0;
}
int pcl_bank(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"s");
int x;
//for(x=0;x<sd->status.bank
}
int pcl_input(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"s");
int count=lua_gettop(state);
char* dialog=lua_tostring(state,sl_memberarg(1));
lua_pushnil(state);
//if(count==2) {
//clif_input(sd,0,dialog,itemdb_name(lua_tonumber(state,2)));
//} else {
sd->in_menu=1;
sd->co_timer=0;
clif_input(sd,0,dialog,"");
// sd->coroutine=state; TEMP
return lua_yield(state,0);
}
int pcl_sell(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"st");
char* dialog=lua_tostring(state,sl_memberarg(1));
int amount=lua_objlen(state,sl_memberarg(2));
int item[60];
int taken[26];
int count=0;
int lastcount=0;
char* temp;
int x,y;
lua_pushnil(state);
while(lua_next(state,sl_memberarg(2))!=0) {
int index=lua_tonumber(state,-2);
temp=lua_tostring(state,-1);
for(x=0;x<26;x++) {
lastcount=0;
if(sd->status.inventory[x].id==itemdb_id(temp)) {
item[count]=x;
//lastcount=count;
count++;
}
}
//printf("%d\n",count);
//if(count>lastcount) item[count]=0;
lua_pop(state,1);
}
sd->in_menu=1;
sd->co_timer=0;
// sd->coroutine=state; TEMP
clif_selldialog(sd,dialog,item,count);
return lua_yield(state,0);
}
int pcl_sell2(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"st");
char* dialog=lua_tostring(state,sl_memberarg(1));
int amount=lua_objlen(state,sl_memberarg(2));
int item[60];
int taken[26];
int count=0;
int lastcount=0;
char* temp;
int x,y;
lua_pushnil(state);
while(lua_next(state,sl_memberarg(2))!=0) {
int index=lua_tonumber(state,-2);
temp=lua_tostring(state,-1);
item[count]=atoi(temp);
count++;
//lastcount=count;
//printf("%d\n",count);
//if(count>lastcount) item[count]=0;
lua_pop(state,1);
}
sd->in_menu=1;
sd->co_timer=0;
// sd->coroutine=state; TEMP
clif_selldialog(sd,dialog,item,count);
return lua_yield(state,0);
}
int pcl_sendstatus(lua_State *state, struct map_sessiondata *sd) {
clif_sendstatus(sd);
return 0;
}
int pcl_getinventoryitem(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"n");
int num=lua_tonumber(state,sl_memberarg(1));
if(sd->status.inventory[num].id != 0)
biteml_pushinst(state, &sd->status.inventory[num]);
else lua_pushnil(state);
return 1;
}
int pcl_addinventoryitem(lua_State *state, struct map_sessiondata *sd) {
return 1;
}
int pcl_getequippeditem(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"n");
int num=lua_tonumber(state,sl_memberarg(1));
if(sd->status.inventory[num].id != 0)
biteml_pushinst(state, &sd->status.equip[num]);
else lua_pushnil(state);
}
int pcl_removelegendbyname(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"s");
char* find=lua_tostring(state,sl_memberarg(1));
int x,count=0;
for(x=0;x<200;x++) {
if(!strcmpi(sd->status.legends[x].name,find)) {
count++;
}
if(x+count<200) {
strcpy(sd->status.legends[x].text,sd->status.legends[x+count].text);
strcpy(sd->status.legends[x].name,sd->status.legends[x+count].name);
sd->status.legends[x].icon=sd->status.legends[x+count].icon;
sd->status.legends[x].color=sd->status.legends[x+count].color;
}
}
return 0;
}
int pcl_removelegendbycolor(lua_State *state, struct map_sessiondata *sd) {
sl_checkargs(state,"n");
int find=lua_tonumber(state,sl_memberarg(1));
int x,count=0;
for(x=0;x<200;x++) {
if(sd->status.legends[x].color==find) {
count++;
}
if(x+count<200) {
strcpy(sd->status.legends[x].text,sd->status.legends[x+count].text);
strcpy(sd->status.legends[x].name,sd->status.legends[x+count].name);
sd->status.legends[x].icon=sd->status.legends[x+count].icon;
sd->status.legends[x].color=sd->status.legends[x+count].color;
}
}
return 0;
}
int pcl_updatestate(lua_State *state, struct map_sessiondata *sd) {
map_foreachinarea(clif_updatestate,sd->bl.m,sd->bl.x,sd->bl.y,AREA,BL_PC,sd);
return 0;
}
int pcl_removeinventoryitem(lua_State *state, struct map_sessiondata *sd) {
//sl_checkargs(state,"");
int id=0;
int amount=0,max=0;
int x;
int count=0;
id=itemdb_id(lua_tostring(state,sl_memberarg(1)));
amount=lua_tonumber(state,sl_memberarg(2));
max=amount;
if(!id) { lua_pushboolean(state,0); return 1; }
for(x=0;x<26;x++) {
if(sd->status.inventory[x].id==id) {
if((sd->status.inventory[x].amount<amount) && (sd->status.inventory[x].amount>0)) {
count+=sd->status.inventory[x].amount;
amount-=sd->status.inventory[x].amount;
pc_delitem(sd,x,sd->status.inventory[x].amount,itemdb_type(sd->status.inventory[x].id));
//valid[x]=1;
if(count==max) {
lua_pushboolean(state,1);
return 1;
}
} else if(sd->status.inventory[x].amount>=amount){
//if(!valid[x]) break;
count+=amount;
pc_delitem(sd,x,amount,itemdb_type(sd->status.inventory[x].id));
lua_pushboolean(state,1);
return 1;
}
}
}
lua_pushboolean(state,0);
return 1;
}
int pcl_additem(lua_State *state, struct map_sessiondata* sd) {
int id=0;
int amount=0;
int bound=0;
struct item *fl;
if(lua_gettop(state)==3) {
bound=lua_toboolean(state,sl_memberarg(3));
}
CALLOC(fl,struct item,1);
id=itemdb_id(lua_tostring(state,sl_memberarg(1)));
amount=lua_tonumber(state,sl_memberarg(2));
fl->id=id;
fl->amount=amount;
if(bound) {
fl->owner_id=sd->bl.id;
} else {
fl->owner_id=0;
}
fl->dura=itemdb_dura(id);
//map_additem(&fl->bl);
if(!pc_additem(sd,fl)) {
lua_pushboolean(state,1);
} else {
lua_pushboolean(state,0);
}
FREE(fl);
return 1;
}
int pcl_showboard(lua_State *state, struct map_sessiondata* sd) {
sl_checkargs(state,"n");
sd->bcount=0;
sd->board_popup=1;
boards_showposts(sd,lua_tonumber(state,sl_memberarg(1)));
return 0;
}
int pcl_hasitem(lua_State *state, struct map_sessiondata* sd) {
int id=0;
int amount=0,max=0;
int x;
int count=0;
id=itemdb_id(lua_tostring(state,sl_memberarg(1)));
amount=lua_tonumber(state,sl_memberarg(2));
max=amount;
for(x=0;x<26;x++) {
if(sd->status.inventory[x].id==id) {
if((sd->status.inventory[x].amount<amount) && (sd->status.inventory[x].amount>0)) {
count+=sd->status.inventory[x].amount;
//pc_delitem(sd,x,sd->status.inventory[x].amount,itemdb_type(sd->status.inventory[x].id));
if(count==max) {
lua_pushboolean(state,1);
return 1;
}
amount--;
} else if(sd->status.inventory[x].amount>=amount){
count+=amount;
//pc_delitem(sd,x,count,itemdb_type(sd->status.inventory[x].id));
lua_pushboolean(state,1);
return 1;
}
}
}
lua_pushboolean(state,0);
return 1;
}
int pcl_addspell(lua_State* state, struct map_sessiondata *sd) {
//sl_checkargs(state,"n");
int spell=magicdb_id(lua_tostring(state,sl_memberarg(1)));
//char name[32];
int x;
//if(sscanf(line,"%d",&spell)<1)
// return -1;
for(x=0;x<52;x++) {
if(sd->status.skill[x]<=0) { //vacant spot
sd->status.skill[x]=spell;
pc_loadmagic(sd);
break;
}
if(sd->status.skill[x]==spell) {
break;
}
}
return 0;
}
int pcl_hasspell(lua_State* state, struct map_sessiondata *sd) {
//sl_checkargs(state,"n");
int spell=magicdb_id(lua_tostring(state,sl_memberarg(1)));
//char name[32];
int x;
//if(sscanf(line,"%d",&spell)<1)
// return -1;
for(x=0;x<52;x++) {
if(sd->status.skill[x]==spell) {
lua_pushboolean(state,1);
return 1;
}
}
lua_pushboolean(state,0);
return 1;
}
int pcl_hasspace(lua_State* state, struct map_sessiondata *sd) {
int id=itemdb_id(lua_tostring(state,sl_memberarg(1)));
int amount=lua_tonumber(state,sl_memberarg(2));
int namount=0;
int a,x;
if(pc_isinvenspace(sd,id)>=26) {
lua_pushboolean(state,0);
return 1;
}
namount=amount;
for(x=0;x<26;x++) {
//printf("%d\n",namount);
if(namount==0) {
lua_pushboolean(state,1);
return 1;
}
if(sd->status.inventory[x].id==id) {
if(sd->status.inventory[x].amount<itemdb_maxamount(id)) {
//sd->status.inventory[x].amount+=nwamount;
a=sd->status.inventory[x].amount+namount;
if(itemdb_maxamount(id)<a) {
namount=a-itemdb_maxamount(id);
}
}
}
if(sd->status.inventory[x].id<=0) {
if(namount<=itemdb_maxamount(id)) {
namount=0;
} else {
namount-=itemdb_maxamount(id);
}
}
}
if(namount==0) {
lua_pushboolean(state,1);
} else {
lua_pushboolean(state,0);
}
return 1;
}
int pcl_removespell(lua_State* state, struct map_sessiondata *sd) {
int spell=magicdb_id(lua_tostring(state,sl_memberarg(1)));
int x;
for(x=0;x<52;x++) {
if(sd->status.skill[x]==spell) {
sd->status.skill[x]=0;
clif_removespell(sd,x);
//pc_loadmagic(sd);
return 0;
}
}
return 0;
}
int pcl_powerboard(lua_State* state, struct map_sessiondata *sd) {
clif_sendpowerboard(sd);
}
int mapregl_getattr(lua_State*,struct map_sessiondata*,char*);
int mapregl_setattr(lua_State*,struct map_sessiondata*,char*);
void mapregl_staticinit() {
mapregl_type=typel_new("Mapregistry",0);
mapregl_type.getattr=mapregl_getattr;
mapregl_type.setattr=mapregl_setattr;
}
int mapregl_setattr(lua_State* state,struct map_sessiondata* sd,char* attrname) {
map_setglobalreg(sd->bl.m,attrname,lua_tonumber(state,-1));
return 1;
}
int mapregl_getattr(lua_State* state,struct map_sessiondata* sd,char* attrname) {
lua_pushnumber(state,map_readglobalreg(sd->bl.m,attrname));
return 1;
}