//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 #include #include #include #include "clif.h" #include #include #include #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;isession_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;xbl,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;xstatus.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].amountstatus.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].amountstatus.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].amountstatus.inventory[x].amount+=nwamount; a=sd->status.inventory[x].amount+namount; if(itemdb_maxamount(id)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; }