diff options
Diffstat (limited to 'src/map/script.c')
-rw-r--r-- | src/map/script.c | 4207 |
1 files changed, 2125 insertions, 2082 deletions
diff --git a/src/map/script.c b/src/map/script.c index 1571d7d5d..2458cc840 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -12,10 +12,10 @@ #include <math.h> #ifndef _WIN32 -#include <sys/time.h> + #include <sys/time.h> #endif - #include <time.h> +#include <setjmp.h> #include "../common/socket.h" #include "../common/timer.h" @@ -49,24 +49,24 @@ #include "unit.h" #include "irc.h" #include "pet.h" -#define SCRIPT_BLOCK_SIZE 256 #define FETCH(n, t) \ if(st->end>st->start+(n)) \ (t)=conv_num(st,&(st->stack->stack_data[st->start+(n)])); +#define SCRIPT_BLOCK_SIZE 512 enum { LABEL_NEXTLINE=1,LABEL_START }; static unsigned char * script_buf = NULL; static int script_pos,script_size; -char *str_buf; -int str_pos,str_size; +static char *str_buf; +static int str_pos,str_size; static struct str_data_struct { int type; int str; int backpatch; int label; - int (*func)(struct script_state *); + int (*func)(struct script_state *st); int val; int next; } *str_data = NULL; @@ -77,20 +77,22 @@ static struct dbt *mapreg_db=NULL; static struct dbt *mapregstr_db=NULL; static int mapreg_dirty=-1; char mapreg_txt[256]="save/mapreg.txt"; -#define MAPREG_AUTOSAVE_INTERVAL (10*1000) +#define MAPREG_AUTOSAVE_INTERVAL (300*1000) static struct dbt *scriptlabel_db=NULL; static struct dbt *userfunc_db=NULL; - struct dbt* script_get_label_db(){ return scriptlabel_db; } struct dbt* script_get_userfunc_db(){ return userfunc_db; } static char pos[11][100] = {"頭","体","左手","右手","ローブ","靴","アクセサリー1","アクセサリー2","頭2","頭3","装着していない"}; struct Script_Config script_config; - static int parse_cmd; +static jmp_buf error_jump; +static char* error_msg; +static char* error_pos; + // for advanced scripting support ( nested if, switch, while, for, do-while, function, etc ) // [Eoe / jA 1080, 1081, 1094, 1164] enum { TYPE_NULL = 0 , TYPE_IF , TYPE_SWITCH , TYPE_WHILE , TYPE_FOR , TYPE_DO , TYPE_USERFUNC}; @@ -125,6 +127,15 @@ char tmp_sql[65535]; // -------------------------------------------------------- #endif +int get_com(unsigned char *script,int *pos); +int get_num(unsigned char *script,int *pos); + +extern struct script_function { + int (*func)(struct script_state *st); + char *name; + char *arg; +} buildin_func[]; + static struct linkdb_node *sleep_db; #define not_server_variable(prefix) (prefix != '$' && prefix != '.') @@ -133,664 +144,12 @@ static struct linkdb_node *sleep_db; *------------------------------------------ */ unsigned char* parse_subexpr(unsigned char *,int); -#ifndef TXT_ONLY -int buildin_query_sql(struct script_state *st); -int buildin_escape_sql(struct script_state *st); -#endif -int buildin_atoi(struct script_state *st); -int buildin_axtoi(struct script_state *st); -int buildin_mes(struct script_state *st); -int buildin_goto(struct script_state *st); -int buildin_callsub(struct script_state *st); -int buildin_callfunc(struct script_state *st); -int buildin_return(struct script_state *st); -int buildin_getarg(struct script_state *st); -int buildin_next(struct script_state *st); -int buildin_close(struct script_state *st); -int buildin_close2(struct script_state *st); -int buildin_menu(struct script_state *st); -int buildin_rand(struct script_state *st); -int buildin_warp(struct script_state *st); -int buildin_areawarp(struct script_state *st); -int buildin_warpchar(struct script_state *st); // [LuzZza] -int buildin_warpparty(struct script_state *st); //[Fredzilla] -int buildin_warpguild(struct script_state *st); //[Fredzilla] -int buildin_heal(struct script_state *st); -int buildin_itemheal(struct script_state *st); -int buildin_percentheal(struct script_state *st); -int buildin_jobchange(struct script_state *st); -int buildin_input(struct script_state *st); -int buildin_setlook(struct script_state *st); -int buildin_set(struct script_state *st); -int buildin_setarray(struct script_state *st); -int buildin_cleararray(struct script_state *st); -int buildin_copyarray(struct script_state *st); -int buildin_getarraysize(struct script_state *st); -int buildin_deletearray(struct script_state *st); -int buildin_getelementofarray(struct script_state *st); -int buildin_getitem(struct script_state *st); -int buildin_getitem2(struct script_state *st); -int buildin_getnameditem(struct script_state *st); -int buildin_grouprandomitem(struct script_state *st); -int buildin_makeitem(struct script_state *st); -int buildin_delitem(struct script_state *st); -int buildin_delitem2(struct script_state *st); -int buildin_enableitemuse(struct script_state *st); -int buildin_disableitemuse(struct script_state *st); -int buildin_viewpoint(struct script_state *st); -int buildin_countitem(struct script_state *st); -int buildin_countitem2(struct script_state *st); -int buildin_checkweight(struct script_state *st); -int buildin_readparam(struct script_state *st); -int buildin_getcharid(struct script_state *st); -int buildin_getpartyname(struct script_state *st); -int buildin_getpartymember(struct script_state *st); -int buildin_getguildname(struct script_state *st); -int buildin_getguildmaster(struct script_state *st); -int buildin_getguildmasterid(struct script_state *st); -int buildin_strcharinfo(struct script_state *st); -int buildin_getequipid(struct script_state *st); -int buildin_getequipname(struct script_state *st); -int buildin_getbrokenid(struct script_state *st); // [Valaris] -int buildin_repair(struct script_state *st); // [Valaris] -int buildin_getequipisequiped(struct script_state *st); -int buildin_getequipisenableref(struct script_state *st); -int buildin_getequipisidentify(struct script_state *st); -int buildin_getequiprefinerycnt(struct script_state *st); -int buildin_getequipweaponlv(struct script_state *st); -int buildin_getequippercentrefinery(struct script_state *st); -int buildin_successrefitem(struct script_state *st); -int buildin_failedrefitem(struct script_state *st); -int buildin_cutin(struct script_state *st); -int buildin_cutincard(struct script_state *st); -int buildin_statusup(struct script_state *st); -int buildin_statusup2(struct script_state *st); -int buildin_bonus(struct script_state *st); -int buildin_bonus2(struct script_state *st); -int buildin_bonus3(struct script_state *st); -int buildin_bonus4(struct script_state *st); -int buildin_skill(struct script_state *st); -int buildin_addtoskill(struct script_state *st); // [Valaris] -int buildin_guildskill(struct script_state *st); -int buildin_getskilllv(struct script_state *st); -int buildin_getgdskilllv(struct script_state *st); -int buildin_basicskillcheck(struct script_state *st); -int buildin_getgmlevel(struct script_state *st); -int buildin_end(struct script_state *st); -int buildin_checkoption(struct script_state *st); -int buildin_setoption(struct script_state *st); -int buildin_setcart(struct script_state *st); -int buildin_checkcart(struct script_state *st); // check cart [Valaris] -int buildin_setfalcon(struct script_state *st); -int buildin_checkfalcon(struct script_state *st); // check falcon [Valaris] -int buildin_setriding(struct script_state *st); -int buildin_checkriding(struct script_state *st); // check for pecopeco [Valaris] -int buildin_savepoint(struct script_state *st); -int buildin_gettimetick(struct script_state *st); -int buildin_gettime(struct script_state *st); -int buildin_gettimestr(struct script_state *st); -int buildin_openstorage(struct script_state *st); -int buildin_guildopenstorage(struct script_state *st); -int buildin_itemskill(struct script_state *st); -int buildin_produce(struct script_state *st); -int buildin_monster(struct script_state *st); -int buildin_areamonster(struct script_state *st); -int buildin_killmonster(struct script_state *st); -int buildin_killmonsterall(struct script_state *st); -int buildin_clone(struct script_state *st); -int buildin_doevent(struct script_state *st); -int buildin_donpcevent(struct script_state *st); -int buildin_addtimer(struct script_state *st); -int buildin_deltimer(struct script_state *st); -int buildin_addtimercount(struct script_state *st); -int buildin_initnpctimer(struct script_state *st); -int buildin_stopnpctimer(struct script_state *st); -int buildin_startnpctimer(struct script_state *st); -int buildin_setnpctimer(struct script_state *st); -int buildin_getnpctimer(struct script_state *st); -int buildin_attachnpctimer(struct script_state *st); // [celest] -int buildin_detachnpctimer(struct script_state *st); // [celest] -int buildin_playerattached(struct script_state *st); // [Skotlex] -int buildin_announce(struct script_state *st); -int buildin_mapannounce(struct script_state *st); -int buildin_areaannounce(struct script_state *st); -int buildin_getusers(struct script_state *st); -int buildin_getmapusers(struct script_state *st); -int buildin_getareausers(struct script_state *st); -int buildin_getareadropitem(struct script_state *st); -int buildin_enablenpc(struct script_state *st); -int buildin_disablenpc(struct script_state *st); -int buildin_enablearena(struct script_state *st); // Added by RoVeRT -int buildin_disablearena(struct script_state *st); // Added by RoVeRT -int buildin_hideoffnpc(struct script_state *st); -int buildin_hideonnpc(struct script_state *st); -int buildin_sc_start(struct script_state *st); -int buildin_sc_start2(struct script_state *st); -int buildin_sc_start4(struct script_state *st); -int buildin_sc_end(struct script_state *st); -int buildin_getscrate(struct script_state *st); -int buildin_debugmes(struct script_state *st); -int buildin_catchpet(struct script_state *st); -int buildin_birthpet(struct script_state *st); -int buildin_resetlvl(struct script_state *st); -int buildin_resetstatus(struct script_state *st); -int buildin_resetskill(struct script_state *st); -int buildin_skillpointcount(struct script_state *st); -int buildin_changebase(struct script_state *st); -int buildin_changesex(struct script_state *st); -int buildin_waitingroom(struct script_state *st); -int buildin_delwaitingroom(struct script_state *st); -int buildin_enablewaitingroomevent(struct script_state *st); -int buildin_disablewaitingroomevent(struct script_state *st); -int buildin_getwaitingroomstate(struct script_state *st); -int buildin_warpwaitingpc(struct script_state *st); -int buildin_attachrid(struct script_state *st); -int buildin_detachrid(struct script_state *st); -int buildin_isloggedin(struct script_state *st); -int buildin_setmapflagnosave(struct script_state *st); -int buildin_setmapflag(struct script_state *st); -int buildin_removemapflag(struct script_state *st); -int buildin_pvpon(struct script_state *st); -int buildin_pvpoff(struct script_state *st); -int buildin_gvgon(struct script_state *st); -int buildin_gvgoff(struct script_state *st); -int buildin_emotion(struct script_state *st); -int buildin_maprespawnguildid(struct script_state *st); -int buildin_agitstart(struct script_state *st); // <Agit> -int buildin_agitend(struct script_state *st); -int buildin_agitcheck(struct script_state *st); // <Agitcheck> -int buildin_flagemblem(struct script_state *st); // Flag Emblem -int buildin_getcastlename(struct script_state *st); -int buildin_getcastledata(struct script_state *st); -int buildin_setcastledata(struct script_state *st); -int buildin_requestguildinfo(struct script_state *st); -int buildin_getequipcardcnt(struct script_state *st); -int buildin_successremovecards(struct script_state *st); -int buildin_failedremovecards(struct script_state *st); -int buildin_marriage(struct script_state *st); -int buildin_wedding_effect(struct script_state *st); -int buildin_divorce(struct script_state *st); -int buildin_ispartneron(struct script_state *st); // MouseJstr -int buildin_getpartnerid(struct script_state *st); // MouseJstr -int buildin_getchildid(struct script_state *st); // Skotlex -int buildin_getmotherid(struct script_state *st); // Lupus -int buildin_getfatherid(struct script_state *st); // Lupus -int buildin_warppartner(struct script_state *st); // MouseJstr -int buildin_getitemname(struct script_state *st); -int buildin_getitemslots(struct script_state *st); -int buildin_makepet(struct script_state *st); -int buildin_getexp(struct script_state *st); -int buildin_getinventorylist(struct script_state *st); -int buildin_getskilllist(struct script_state *st); -int buildin_clearitem(struct script_state *st); -int buildin_classchange(struct script_state *st); -int buildin_misceffect(struct script_state *st); -int buildin_soundeffect(struct script_state *st); -int buildin_soundeffectall(struct script_state *st); -int buildin_setcastledata(struct script_state *st); -int buildin_mapwarp(struct script_state *st); -int buildin_inittimer(struct script_state *st); -int buildin_stoptimer(struct script_state *st); -int buildin_cmdothernpc(struct script_state *st); -int buildin_mobcount(struct script_state *st); -int buildin_strmobinfo(struct script_state *st); // Script for displaying mob info [Valaris] -int buildin_guardian(struct script_state *st); // Script for displaying mob info [Valaris] -int buildin_guardianinfo(struct script_state *st); // Script for displaying mob info [Valaris] -int buildin_petskillbonus(struct script_state *st); // petskillbonus [Valaris] -int buildin_petrecovery(struct script_state *st); // pet skill for curing status [Valaris] -int buildin_petloot(struct script_state *st); // pet looting [Valaris] -int buildin_petheal(struct script_state *st); // pet healing [Valaris] -//int buildin_petmag(struct script_state *st); // pet magnificat [Valaris] -int buildin_petskillattack(struct script_state *st); // pet skill attacks [Skotlex] -int buildin_petskillattack2(struct script_state *st); // pet skill attacks [Skotlex] -int buildin_petskillsupport(struct script_state *st); // pet support skill [Valaris] -int buildin_skilleffect(struct script_state *st); // skill effects [Celest] -int buildin_npcskilleffect(struct script_state *st); // skill effects for npcs [Valaris] -int buildin_specialeffect(struct script_state *st); // special effect script [Valaris] -int buildin_specialeffect2(struct script_state *st); // special effect script [Valaris] -int buildin_nude(struct script_state *st); // nude [Valaris] -int buildin_atcommand(struct script_state *st); // [MouseJstr] -int buildin_charcommand(struct script_state *st); // [MouseJstr] -int buildin_movenpc(struct script_state *st); // [MouseJstr] -int buildin_message(struct script_state *st); // [MouseJstr] -int buildin_npctalk(struct script_state *st); // [Valaris] -int buildin_hasitems(struct script_state *st); // [Valaris] -int buildin_getlook(struct script_state *st); //Lorky [Lupus] -int buildin_getsavepoint(struct script_state *st); //Lorky [Lupus] -int buildin_npcspeed(struct script_state *st); // [Valaris] -int buildin_npcwalkto(struct script_state *st); // [Valaris] -int buildin_npcstop(struct script_state *st); // [Valaris] -int buildin_getmapxy(struct script_state *st); //get map position for player/npc/pet/mob by Lorky [Lupus] -int buildin_checkoption1(struct script_state *st); // [celest] -int buildin_checkoption2(struct script_state *st); // [celest] -int buildin_guildgetexp(struct script_state *st); // [celest] -int buildin_guildchangegm(struct script_state *st); // [Skotlex] -int buildin_logmes(struct script_state *st); // [Lupus] -int buildin_summon(struct script_state *st); // [celest] -int buildin_isnight(struct script_state *st); // [celest] -int buildin_isday(struct script_state *st); // [celest] -int buildin_isequipped(struct script_state *st); // [celest] -int buildin_isequippedcnt(struct script_state *st); // [celest] -int buildin_cardscnt(struct script_state *st); // [Lupus] -int buildin_getrefine(struct script_state *st); // [celest] -int buildin_adopt(struct script_state *st); -int buildin_night(struct script_state *st); -int buildin_day(struct script_state *st); -int buildin_getusersname(struct script_state *st); //jA commands added [Lupus] -int buildin_dispbottom(struct script_state *st); -int buildin_recovery(struct script_state *st); -int buildin_getpetinfo(struct script_state *st); -int buildin_checkequipedcard(struct script_state *st); -int buildin_globalmes(struct script_state *st); -int buildin_jump_zero(struct script_state *st); -int buildin_select(struct script_state *st); -int buildin_getmapmobs(struct script_state *st); //jA addition end -int buildin_unequip(struct script_state *st); // unequip [Spectre] -int buildin_getstrlen(struct script_state *st); //strlen [valaris] -int buildin_charisalpha(struct script_state *st);//isalpha [valaris] -int buildin_fakenpcname(struct script_state *st); // [Lance] -int buildin_compare(struct script_state *st); // Lordalfa, to bring strstr to Scripting Engine -int buildin_getiteminfo(struct script_state *st); //[Lupus] returns Items Buy / sell Price, etc info -int buildin_getequipcardid(struct script_state *st); //[Lupus] returns card id from quipped item card slot N -// [zBuffer] List of mathematics commands ---> -int buildin_sqrt(struct script_state *st); -int buildin_pow(struct script_state *st); -int buildin_distance(struct script_state *st); -int buildin_checkcell(struct script_state *st); -// <--- [zBuffer] List of mathematics commands -// [zBuffer] List of dynamic var commands ---> -int buildin_getd(struct script_state *st); -int buildin_setd(struct script_state *st); -// <--- [zBuffer] List of dynamic var commands -int buildin_petstat(struct script_state *st); // [Lance] Pet Stat Rq: Dubby -int buildin_callshop(struct script_state *st); // [Skotlex] -int buildin_npcshopitem(struct script_state *st); // [Lance] -int buildin_npcshopadditem(struct script_state *st); -int buildin_npcshopdelitem(struct script_state *st); -int buildin_equip(struct script_state *st); -int buildin_autoequip(struct script_state *st); -int buildin_setbattleflag(struct script_state *st); -int buildin_getbattleflag(struct script_state *st); -// [zBuffer] List of player cont commands ---> -int buildin_rid2name(struct script_state *st); -int buildin_pcfollow(struct script_state *st); -int buildin_pcstopfollow(struct script_state *st); -int buildin_pcblockmove(struct script_state *st); -// <--- [zBuffer] List of player cont commands -// [zBuffer] List of mob control commands ---> -int buildin_mobspawn(struct script_state *st); -int buildin_mobremove(struct script_state *st); -int buildin_getmobdata(struct script_state *st); -int buildin_setmobdata(struct script_state *st); -int buildin_mobassist(struct script_state *st); -int buildin_mobattach(struct script_state *st); -int buildin_unitwalk(struct script_state *st); -int buildin_unitkill(struct script_state *st); -int buildin_unitwarp(struct script_state *st); -int buildin_unitattack(struct script_state *st); -int buildin_unitstop(struct script_state *st); -int buildin_unittalk(struct script_state *st); -int buildin_unitemote(struct script_state *st); -int buildin_unitdeadsit(struct script_state *st); -int buildin_unitskilluseid(struct script_state *st); // originally by Qamera [celest] -int buildin_unitskillusepos(struct script_state *st); // originally by Qamera [celest] -// <--- [zBuffer] List of mob control commands -int buildin_sleep(struct script_state *st); -int buildin_sleep2(struct script_state *st); -int buildin_awake(struct script_state *st); -int buildin_getvariableofnpc(struct script_state *st); -// [blackhole89] --> -int buildin_warpportal(struct script_state *st); -// <-- [blackhole89] -int buildin_homunculus_evolution(struct script_state *st) ; //[orn] void push_val(struct script_stack *stack,int type,int val); int run_func(struct script_state *st); int mapreg_setreg(int num,int val); int mapreg_setregstr(int num,const char *str); -int buildin_setitemscript(struct script_state *st); -int buildin_disguise(struct script_state *st); -int buildin_undisguise(struct script_state *st); -int buildin_getmonsterinfo(struct script_state *st); // [Lupus] - -#ifdef PCRE_SUPPORT -int buildin_defpattern(struct script_state *st); // MouseJstr -int buildin_activatepset(struct script_state *st); // MouseJstr -int buildin_deactivatepset(struct script_state *st); // MouseJstr -int buildin_deletepset(struct script_state *st); // MouseJstr -#endif - -struct { - int (*func)(struct script_state *); - char *name; - char *arg; -} buildin_func[]={ - {buildin_axtoi,"axtoi","s"}, -#ifndef TXT_ONLY - {buildin_query_sql, "query_sql", "s*"}, - {buildin_escape_sql, "escape_sql", "s"}, -#endif - {buildin_atoi,"atoi","s"}, - {buildin_mes,"mes","s"}, - {buildin_next,"next",""}, - {buildin_close,"close",""}, - {buildin_close2,"close2",""}, - {buildin_menu,"menu","*"}, - {buildin_goto,"goto","l"}, - {buildin_callsub,"callsub","i*"}, - {buildin_callfunc,"callfunc","s*"}, - {buildin_return,"return","*"}, - {buildin_getarg,"getarg","i"}, - {buildin_jobchange,"jobchange","i*"}, - {buildin_input,"input","*"}, - {buildin_warp,"warp","sii"}, - {buildin_areawarp,"areawarp","siiiisii"}, - {buildin_warpchar,"warpchar","siii"}, // [LuzZza] - {buildin_warpparty,"warpparty","siii"}, // [Fredzilla] - {buildin_warpguild,"warpguild","siii"}, // [Fredzilla] - {buildin_setlook,"setlook","ii"}, - {buildin_set,"set","ii"}, - {buildin_setarray,"setarray","ii*"}, - {buildin_cleararray,"cleararray","iii"}, - {buildin_copyarray,"copyarray","iii"}, - {buildin_getarraysize,"getarraysize","i"}, - {buildin_deletearray,"deletearray","ii"}, - {buildin_getelementofarray,"getelementofarray","ii"}, - {buildin_getitem,"getitem","ii**"}, - {buildin_getitem2,"getitem2","iiiiiiiii*"}, - {buildin_getnameditem,"getnameditem","is"}, - {buildin_grouprandomitem,"groupranditem","i"}, - {buildin_makeitem,"makeitem","iisii"}, - {buildin_delitem,"delitem","ii"}, - {buildin_delitem2,"delitem2","iiiiiiiii"}, - {buildin_enableitemuse,"enable_items",""}, - {buildin_disableitemuse,"disable_items",""}, - {buildin_cutin,"cutin","si"}, - {buildin_cutincard,"cutincard","i"}, - {buildin_viewpoint,"viewpoint","iiiii"}, - {buildin_heal,"heal","ii"}, - {buildin_itemheal,"itemheal","ii"}, - {buildin_percentheal,"percentheal","ii"}, - {buildin_rand,"rand","i*"}, - {buildin_countitem,"countitem","i"}, - {buildin_countitem2,"countitem2","iiiiiiii"}, - {buildin_checkweight,"checkweight","ii"}, - {buildin_readparam,"readparam","i*"}, - {buildin_getcharid,"getcharid","i*"}, - {buildin_getpartyname,"getpartyname","i"}, - {buildin_getpartymember,"getpartymember","i*"}, - {buildin_getguildname,"getguildname","i"}, - {buildin_getguildmaster,"getguildmaster","i"}, - {buildin_getguildmasterid,"getguildmasterid","i"}, - {buildin_strcharinfo,"strcharinfo","i"}, - {buildin_getequipid,"getequipid","i"}, - {buildin_getequipname,"getequipname","i"}, - {buildin_getbrokenid,"getbrokenid","i"}, // [Valaris] - {buildin_repair,"repair","i"}, // [Valaris] - {buildin_getequipisequiped,"getequipisequiped","i"}, - {buildin_getequipisenableref,"getequipisenableref","i"}, - {buildin_getequipisidentify,"getequipisidentify","i"}, - {buildin_getequiprefinerycnt,"getequiprefinerycnt","i"}, - {buildin_getequipweaponlv,"getequipweaponlv","i"}, - {buildin_getequippercentrefinery,"getequippercentrefinery","i"}, - {buildin_successrefitem,"successrefitem","i"}, - {buildin_failedrefitem,"failedrefitem","i"}, - {buildin_statusup,"statusup","i"}, - {buildin_statusup2,"statusup2","ii"}, - {buildin_bonus,"bonus","ii"}, - {buildin_bonus2,"bonus2","iii"}, - {buildin_bonus3,"bonus3","iiii"}, - {buildin_bonus4,"bonus4","iiiii"}, - {buildin_skill,"skill","ii*"}, - {buildin_addtoskill,"addtoskill","ii*"}, // [Valaris] - {buildin_guildskill,"guildskill","ii"}, - {buildin_getskilllv,"getskilllv","i"}, - {buildin_getgdskilllv,"getgdskilllv","ii"}, - {buildin_basicskillcheck,"basicskillcheck","*"}, - {buildin_getgmlevel,"getgmlevel","*"}, - {buildin_end,"end",""}, -// {buildin_end,"break",""}, this might confuse advanced scripting support [Eoe] - {buildin_checkoption,"checkoption","i"}, - {buildin_setoption,"setoption","i*"}, - {buildin_setcart,"setcart",""}, - {buildin_checkcart,"checkcart","*"}, //fixed by Lupus (added '*') - {buildin_setfalcon,"setfalcon",""}, - {buildin_checkfalcon,"checkfalcon","*"}, //fixed by Lupus (fixed wrong pointer, added '*') - {buildin_setriding,"setriding",""}, - {buildin_checkriding,"checkriding","*"}, //fixed by Lupus (fixed wrong pointer, added '*') - {buildin_savepoint,"save","sii"}, - {buildin_savepoint,"savepoint","sii"}, - {buildin_gettimetick,"gettimetick","i"}, - {buildin_gettime,"gettime","i"}, - {buildin_gettimestr,"gettimestr","si"}, - {buildin_openstorage,"openstorage",""}, - {buildin_guildopenstorage,"guildopenstorage","*"}, - {buildin_itemskill,"itemskill","iis"}, - {buildin_produce,"produce","i"}, - {buildin_monster,"monster","siisii*"}, - {buildin_areamonster,"areamonster","siiiisii*"}, - {buildin_killmonster,"killmonster","ss"}, - {buildin_killmonsterall,"killmonsterall","s"}, - {buildin_clone,"clone","siisi*"}, - {buildin_doevent,"doevent","s"}, - {buildin_donpcevent,"donpcevent","s"}, - {buildin_addtimer,"addtimer","is"}, - {buildin_deltimer,"deltimer","s"}, - {buildin_addtimercount,"addtimercount","si"}, - {buildin_initnpctimer,"initnpctimer","*"}, - {buildin_stopnpctimer,"stopnpctimer","*"}, - {buildin_startnpctimer,"startnpctimer","*"}, - {buildin_setnpctimer,"setnpctimer","*"}, - {buildin_getnpctimer,"getnpctimer","i*"}, - {buildin_attachnpctimer,"attachnpctimer","*"}, // attached the player id to the npc timer [Celest] - {buildin_detachnpctimer,"detachnpctimer","*"}, // detached the player id from the npc timer [Celest] - {buildin_playerattached,"playerattached",""}, // returns id of the current attached player. [Skotlex] - {buildin_announce,"announce","si*"}, - {buildin_mapannounce,"mapannounce","ssi*"}, - {buildin_areaannounce,"areaannounce","siiiisi*"}, - {buildin_getusers,"getusers","i"}, - {buildin_getmapusers,"getmapusers","s"}, - {buildin_getareausers,"getareausers","siiii"}, - {buildin_getareadropitem,"getareadropitem","siiiii"}, - {buildin_enablenpc,"enablenpc","s"}, - {buildin_disablenpc,"disablenpc","s"}, - {buildin_enablearena,"enablearena",""}, // Added by RoVeRT - {buildin_disablearena,"disablearena",""}, // Added by RoVeRT - {buildin_hideoffnpc,"hideoffnpc","s"}, - {buildin_hideonnpc,"hideonnpc","s"}, - {buildin_sc_start,"sc_start","iii*"}, - {buildin_sc_start2,"sc_start2","iiii*"}, - {buildin_sc_start4,"sc_start4","iiiiii*"}, - {buildin_sc_end,"sc_end","i"}, - {buildin_getscrate,"getscrate","ii*"}, - {buildin_debugmes,"debugmes","s"}, - {buildin_catchpet,"pet","i"}, - {buildin_birthpet,"bpet",""}, - {buildin_resetlvl,"resetlvl","i"}, - {buildin_resetstatus,"resetstatus",""}, - {buildin_resetskill,"resetskill",""}, - {buildin_skillpointcount,"skillpointcount",""}, - {buildin_changebase,"changebase","i"}, - {buildin_changesex,"changesex",""}, - {buildin_waitingroom,"waitingroom","si*"}, - {buildin_warpwaitingpc,"warpwaitingpc","sii"}, - {buildin_delwaitingroom,"delwaitingroom","*"}, - {buildin_enablewaitingroomevent,"enablewaitingroomevent","*"}, - {buildin_disablewaitingroomevent,"disablewaitingroomevent","*"}, - {buildin_getwaitingroomstate,"getwaitingroomstate","i*"}, - {buildin_warpwaitingpc,"warpwaitingpc","sii*"}, - {buildin_attachrid,"attachrid","i"}, - {buildin_detachrid,"detachrid",""}, - {buildin_isloggedin,"isloggedin","i"}, - {buildin_setmapflagnosave,"setmapflagnosave","ssii"}, - {buildin_setmapflag,"setmapflag","si*"}, - {buildin_removemapflag,"removemapflag","si"}, - {buildin_pvpon,"pvpon","s"}, - {buildin_pvpoff,"pvpoff","s"}, - {buildin_gvgon,"gvgon","s"}, - {buildin_gvgoff,"gvgoff","s"}, - {buildin_emotion,"emotion","i*"}, - {buildin_maprespawnguildid,"maprespawnguildid","sii"}, - {buildin_agitstart,"agitstart",""}, // <Agit> - {buildin_agitend,"agitend",""}, - {buildin_agitcheck,"agitcheck","i"}, // <Agitcheck> - {buildin_flagemblem,"flagemblem","i"}, // Flag Emblem - {buildin_getcastlename,"getcastlename","s"}, - {buildin_getcastledata,"getcastledata","si*"}, - {buildin_setcastledata,"setcastledata","sii"}, - {buildin_requestguildinfo,"requestguildinfo","i*"}, - {buildin_getequipcardcnt,"getequipcardcnt","i"}, - {buildin_successremovecards,"successremovecards","i"}, - {buildin_failedremovecards,"failedremovecards","ii"}, - {buildin_marriage,"marriage","s"}, - {buildin_wedding_effect,"wedding",""}, - {buildin_divorce,"divorce",""}, - {buildin_ispartneron,"ispartneron",""}, - {buildin_getpartnerid,"getpartnerid",""}, - {buildin_getchildid,"getchildid",""}, - {buildin_getmotherid,"getmotherid",""}, - {buildin_getfatherid,"getfatherid",""}, - {buildin_warppartner,"warppartner","sii"}, - {buildin_getitemname,"getitemname","i"}, - {buildin_getitemslots,"getitemslots","i"}, - {buildin_makepet,"makepet","i"}, - {buildin_getexp,"getexp","ii"}, - {buildin_getinventorylist,"getinventorylist",""}, - {buildin_getskilllist,"getskilllist",""}, - {buildin_clearitem,"clearitem",""}, - {buildin_classchange,"classchange","ii"}, - {buildin_misceffect,"misceffect","i"}, - {buildin_soundeffect,"soundeffect","si"}, - {buildin_soundeffectall,"soundeffectall","si*"}, // SoundEffectAll [Codemaster] - {buildin_strmobinfo,"strmobinfo","ii"}, // display mob data [Valaris] - {buildin_guardian,"guardian","siisii*i"}, // summon guardians - {buildin_guardianinfo,"guardianinfo","i"}, // display guardian data [Valaris] - {buildin_petskillbonus,"petskillbonus","iiii"}, // [Valaris] - {buildin_petrecovery,"petrecovery","ii"}, // [Valaris] - {buildin_petloot,"petloot","i"}, // [Valaris] - {buildin_petheal,"petheal","iiii"}, // [Valaris] -// {buildin_petmag,"petmag","iiii"}, // [Valaris] - {buildin_petskillattack,"petskillattack","iiii"}, // [Skotlex] - {buildin_petskillattack2,"petskillattack2","iiiii"}, // [Valaris] - {buildin_petskillsupport,"petskillsupport","iiiii"}, // [Skotlex] - {buildin_skilleffect,"skilleffect","ii"}, // skill effect [Celest] - {buildin_npcskilleffect,"npcskilleffect","iiii"}, // npc skill effect [Valaris] - {buildin_specialeffect,"specialeffect","i*"}, // npc skill effect [Valaris] - {buildin_specialeffect2,"specialeffect2","i*"}, // skill effect on players[Valaris] - {buildin_nude,"nude",""}, // nude command [Valaris] - {buildin_mapwarp,"mapwarp","ssii"}, // Added by RoVeRT - {buildin_inittimer,"inittimer",""}, - {buildin_stoptimer,"stoptimer",""}, - {buildin_cmdothernpc,"cmdothernpc","ss"}, - {buildin_atcommand,"atcommand","*"}, // [MouseJstr] - {buildin_charcommand,"charcommand","*"}, // [MouseJstr] - {buildin_movenpc,"movenpc","sii"}, // [MouseJstr] - {buildin_message,"message","s*"}, // [MouseJstr] - {buildin_npctalk,"npctalk","*"}, // [Valaris] - {buildin_hasitems,"hasitems","*"}, // [Valaris] - {buildin_mobcount,"mobcount","ss"}, - {buildin_getlook,"getlook","i"}, - {buildin_getsavepoint,"getsavepoint","i"}, - {buildin_npcspeed,"npcspeed","i"}, // [Valaris] - {buildin_npcwalkto,"npcwalkto","ii"}, // [Valaris] - {buildin_npcstop,"npcstop",""}, // [Valaris] - {buildin_getmapxy,"getmapxy","siii*"}, //by Lorky [Lupus] - {buildin_checkoption1,"checkoption1","i"}, - {buildin_checkoption2,"checkoption2","i"}, - {buildin_guildgetexp,"guildgetexp","i"}, - {buildin_guildchangegm,"guildchangegm","is"}, - {buildin_logmes,"logmes","s"}, //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] - {buildin_summon,"summon","si*"}, // summons a slave monster [Celest] - {buildin_isnight,"isnight",""}, // check whether it is night time [Celest] - {buildin_isday,"isday",""}, // check whether it is day time [Celest] - {buildin_isequipped,"isequipped","i*"}, // check whether another item/card has been equipped [Celest] - {buildin_isequippedcnt,"isequippedcnt","i*"}, // check how many items/cards are being equipped [Celest] - {buildin_cardscnt,"cardscnt","i*"}, // check how many items/cards are being equipped in the same arm [Lupus] - {buildin_getrefine,"getrefine","*"}, // returns the refined number of the current item, or an item with index specified [celest] - {buildin_adopt,"adopt","sss"}, // allows 2 parents to adopt a child - {buildin_night,"night",""}, // sets the server to night time - {buildin_day,"day",""}, // sets the server to day time -#ifdef PCRE_SUPPORT - {buildin_defpattern, "defpattern", "iss"}, // Define pattern to listen for [MouseJstr] - {buildin_activatepset, "activatepset", "i"}, // Activate a pattern set [MouseJstr] - {buildin_deactivatepset, "deactivatepset", "i"}, // Deactive a pattern set [MouseJstr] - {buildin_deletepset, "deletepset", "i"}, // Delete a pattern set [MouseJstr] -#endif - {buildin_dispbottom,"dispbottom","s"}, //added from jA [Lupus] - {buildin_getusersname,"getusersname","*"}, - {buildin_recovery,"recovery",""}, - {buildin_getpetinfo,"getpetinfo","i"}, - {buildin_checkequipedcard,"checkequipedcard","i"}, - {buildin_jump_zero,"jump_zero","ii"}, //for future jA script compatibility - {buildin_select,"select","*"}, //for future jA script compatibility - {buildin_globalmes,"globalmes","s*"}, - {buildin_getmapmobs,"getmapmobs","s"}, //end jA addition - {buildin_unequip,"unequip","i"}, // unequip command [Spectre] - {buildin_getstrlen,"getstrlen","s"}, //strlen [Valaris] - {buildin_charisalpha,"charisalpha","si"}, //isalpha [Valaris] - {buildin_fakenpcname,"fakenpcname","ssi"}, // [Lance] - {buildin_compare,"compare","ss"}, // Lordalfa - To bring strstr to scripting Engine. - {buildin_getiteminfo,"getiteminfo","ii"}, //[Lupus] returns Items Buy / sell Price, etc info - {buildin_getequipcardid,"getequipcardid","ii"}, //[Lupus] returns CARD ID or other info from CARD slot N of equipped item - // [zBuffer] List of mathematics commands ---> - {buildin_sqrt,"sqrt","i"}, - {buildin_pow,"pow","ii"}, - {buildin_distance,"distance","iiii"}, - {buildin_checkcell,"checkcell","siii"}, - // <--- [zBuffer] List of mathematics commands - // [zBuffer] List of dynamic var commands ---> - {buildin_getd,"getd","*"}, - {buildin_setd,"setd","*"}, - // <--- [zBuffer] List of dynamic var commands - {buildin_petstat,"petstat","i"}, - {buildin_callshop,"callshop","si"}, // [Skotlex] - {buildin_npcshopitem,"npcshopitem","sii*"}, // [Lance] - {buildin_npcshopadditem,"npcshopadditem","sii*"}, - {buildin_npcshopdelitem,"npcshopdelitem","si*"}, - {buildin_equip,"equip","i"}, - {buildin_autoequip,"autoequip","ii"}, - {buildin_setbattleflag,"setbattleflag","ss"}, - {buildin_getbattleflag,"getbattleflag","s"}, - {buildin_setitemscript,"setitemscript","is"}, //Set NEW item bonus script. Lupus - {buildin_disguise,"disguise","i"}, //disguise player. Lupus - {buildin_undisguise,"undisguise","i"}, //undisguise player. Lupus - {buildin_getmonsterinfo,"getmonsterinfo","ii"}, //Lupus - // [zBuffer] List of player cont commands ---> - {buildin_rid2name,"rid2name","i"}, - {buildin_pcfollow,"pcfollow","ii"}, - {buildin_pcstopfollow,"pcstopfollow","i"}, - {buildin_pcblockmove,"pcblockmove","ii"}, - // <--- [zBuffer] List of player cont commands - // [zBuffer] List of mob control commands ---> - {buildin_mobspawn,"mobspawn","*"}, - {buildin_mobremove,"mobremove","i"}, - {buildin_getmobdata,"getmobdata","i*"}, - {buildin_setmobdata,"setmobdata","iii"}, - {buildin_mobassist,"mobassist","i*"}, - {buildin_mobattach,"mobattach","i*"}, - {buildin_unitwalk,"unitwalk","i*"}, - {buildin_unitkill,"unitkill","i"}, - {buildin_unitwarp,"unitwarp","isii"}, - {buildin_unitattack,"unitattack","i*"}, - {buildin_unitstop,"unitstop","i"}, - {buildin_unittalk,"unittalk","is"}, - {buildin_unitemote,"unitemote","ii"}, - {buildin_unitdeadsit,"unitdeadsit","ii"}, - {buildin_unitskilluseid,"unitskilluseid","iii*"}, // originally by Qamera [Celest] - {buildin_unitskillusepos,"unitskillusepos","iiiii"}, // [Celest] -// <--- [zBuffer] List of mob control commands - {buildin_sleep,"sleep","i"}, - {buildin_sleep2,"sleep2","i"}, - {buildin_awake,"awake","s"}, - {buildin_getvariableofnpc,"getvariableofnpc","is"}, - // [blackhole89] --> - {buildin_warpportal,"warpportal","iisii"}, - // <--- [blackhole89] - {buildin_homunculus_evolution,"homevolution",""}, //[orn] - {NULL,NULL,NULL}, -}; - enum { C_NOP,C_POS,C_INT,C_PARAM,C_FUNC,C_STR,C_CONSTSTR,C_ARG, C_NAME,C_EOL, C_RETINFO, @@ -800,6 +159,53 @@ enum { C_XOR,C_OR,C_AND,C_ADD,C_SUB,C_MUL,C_DIV,C_MOD,C_NEG,C_LNOT,C_NOT,C_R_SHIFT,C_L_SHIFT }; +enum { + MF_NOMEMO, + MF_NOTELEPORT, + MF_NOSAVE, + MF_NOBRANCH, + MF_NOPENALTY, + MF_NOZENYPENALTY, + MF_PVP, + MF_PVP_NOPARTY, + MF_PVP_NOGUILD, + MF_GVG, + MF_GVG_NOPARTY, + MF_NOTRADE, + MF_NOSKILL, + MF_NOWARP, + MF_FREE, + MF_NOICEWALL, + MF_SNOW, + MF_FOG, + MF_SAKURA, + MF_LEAVES, + MF_RAIN, + MF_INDOORS, + MF_NOGO, + MF_CLOUDS, + MF_CLOUDS2, + MF_FIREWORKS, + MF_GVG_CASTLE, + MF_GVG_DUNGEON, + MF_NIGHTENABLED, + MF_NOBASEEXP, + MF_NOJOBEXP, + MF_NOMOBLOOT, + MF_NOMVPLOOT, + MF_NORETURN, + MF_NOWARPTO, + MF_NIGHTMAREDROP, + MF_RESTRICTED, + MF_NOCOMMAND, + MF_NODROP, + MF_JEXP, + MF_BEXP, + MF_NOVENDING, + MF_LOADEVENT, + MF_NOCHAT +}; + //Reports on the console the src of an script error. static void report_src(struct script_state *st) { struct block_list *bl; @@ -898,7 +304,7 @@ int add_str(const unsigned char *p) } if(str_num>=str_data_size){ str_data_size+=128; - str_data=(struct str_data_struct *) aRealloc(str_data,sizeof(str_data[0])*str_data_size); + str_data=aRealloc(str_data,sizeof(str_data[0])*str_data_size); memset(str_data + (str_data_size - 128), '\0', 128); } while(str_pos+(int)strlen((char *) p)+1>=str_size){ @@ -936,11 +342,16 @@ static void check_script_buf(int size) * スクリプトバッファに1バイト書き込む *------------------------------------------ */ + +#define add_scriptb(a) if( script_pos+1>=script_size ) check_script_buf(1); script_buf[script_pos++]=(a); + +#if 0 static void add_scriptb(int a) { check_script_buf(1); script_buf[script_pos++]=a; } +#endif /*========================================== * スクリプトバッファにデータタイプを書き込む @@ -1063,59 +474,27 @@ static unsigned char *skip_word(unsigned char *p) if(*p=='#') p++; // account変数用 if(*p=='#') p++; // ワールドaccount変数用 - while(isalnum(*p)||*p=='_'|| *p>=0x81) + while(isalnum(*p)||*p=='_'|| *p>=0x81) { if(*p>=0x81 && p[1]){ p+=2; } else p++; - + } // postfix if(*p=='$') p++; // 文字列変数 return p; } -static unsigned char *startptr; -static int startline; - /*========================================== * エラーメッセージ出力 *------------------------------------------ */ -static void disp_error_message(const char *mes,const unsigned char *pos) +static void disp_error_message(const char *mes,unsigned char *pos) { - int line,c=0,i; - unsigned char *p,*linestart,*lineend; - - for(line=startline,p=startptr;p && *p;line++){ - linestart=p; - lineend=(unsigned char *) strchr((char *) p,'\n'); - if(lineend){ - c=*lineend; - *lineend=0; - } - if(lineend==NULL || pos<lineend){ - fprintf(stderr, "\r"); //To not printout the error next to the spinner... - ShowError(" "); //Better error display [Skotlex] - if (current_file) { - printf("%s in "CL_WHITE"\'%s\'"CL_RESET" line "CL_WHITE"\'%d\'"CL_RESET" : ", mes, current_file, line); - } else { - printf("%s line "CL_WHITE"\'%d\'"CL_RESET" : ", mes, line); - } - for(i=0;(linestart[i]!='\r') && (linestart[i]!='\n') && linestart[i];i++){ - if(linestart+i!=pos) - printf("%c",linestart[i]); - else - printf("\'%c\'",linestart[i]); - } - printf("\a\n"); - if(lineend) - *lineend=c; - return; - } - *lineend=c; - p=lineend+1; - } + error_msg = aStrdup(mes); + error_pos = pos; + longjmp( error_jump, 1 ); } /*========================================== @@ -1136,7 +515,6 @@ unsigned char* parse_simpleexpr(unsigned char *p) exit(1); } if(*p=='('){ - p=parse_subexpr(p+1,-1); p=skip_space(p); if((*p++)!=')'){ @@ -1170,7 +548,8 @@ unsigned char* parse_simpleexpr(unsigned char *p) int c,l; char *p2; // label , register , function etc - if(skip_word(p)==p && !(*p==')' && p[-1]=='(')){ + //From what I read, jA figured a better way to handle empty parenthesis '()' + if(skip_word(p)==p/* && !(*p==')' && p[-1]=='(')*/){ disp_error_message("unexpected character",p); exit(1); } @@ -1189,6 +568,7 @@ unsigned char* parse_simpleexpr(unsigned char *p) add_scriptl(search_str((unsigned char *) "getelementofarray")); add_scriptc(C_ARG); add_scriptl(l); + p=parse_subexpr(p+1,-1); p=skip_space(p); if((*p++)!=']'){ @@ -1242,7 +622,8 @@ unsigned char* parse_subexpr(unsigned char *p,int limit) } else p=parse_simpleexpr(p); p=skip_space(p); - while(((op=C_ADD,opl=6,len=1,*p=='+') || + while(( + (op=C_ADD,opl=6,len=1,*p=='+') || (op=C_SUB,opl=6,len=1,*p=='-') || (op=C_MUL,opl=7,len=1,*p=='*') || (op=C_DIV,opl=7,len=1,*p=='/') || @@ -1281,7 +662,7 @@ unsigned char* parse_subexpr(unsigned char *p,int limit) } func=parse_cmd; - do { + while(*p && *p!=')' && i<128) { plist[i]=(char *) p; p=parse_subexpr(p,-1); p=skip_space(p); @@ -1291,14 +672,14 @@ unsigned char* parse_subexpr(unsigned char *p,int limit) } p=skip_space(p); i++; - } while(*p && *p!=')' && i<128); + }; plist[i]=(char *) p; if(*(p++)!=')'){ disp_error_message("func request '(' ')'",p); exit(1); } - if (str_data[func].type == C_FUNC && script_config.warn_func_mismatch_paramnum) { + if( str_data[func].type==C_FUNC && script_config.warn_func_mismatch_paramnum){ const char *arg = buildin_func[str_data[func].val].arg; int j = 0; for (; arg[j]; j++) if (arg[j] == '*') break; @@ -1335,6 +716,12 @@ unsigned char* parse_expr(unsigned char *p) disp_error_message("unexpected char",p); exit(1); } + if(*p == '(') { + unsigned char *p2 = skip_space(p + 1); + if(*p2 == ')') { + return p2 + 1; + } + } p=parse_subexpr(p,-1); #ifdef DEBUG_FUNCIN if(battle_config.etc_log) @@ -1355,8 +742,13 @@ unsigned char* parse_line(unsigned char *p) char end; p=skip_space(p); - if(*p==';') - return p + 1; + if(*p==';') { + // if(); for(); while(); のために閉じ判定 + p = parse_syntax_close(p); + return p+1; + } + if(*p==')' && parse_syntax_for_flag) + return p+1; p = skip_space(p); if(p[0] == '{') { @@ -1398,7 +790,7 @@ unsigned char* parse_line(unsigned char *p) } else { end = ';'; } - while(p && *p && *p!=end && i<128){ + while(p && *p && *p != end && i<128){ plist[i]=(char *) p; p=parse_expr(p); @@ -1437,12 +829,9 @@ unsigned char* parse_line(unsigned char *p) disp_error_message("illegal number of parameters",(unsigned char *) (plist[(i<j)?i:j])); } } - - return p; } - // { ... } の閉じ処理 unsigned char* parse_curly_close(unsigned char *p) { if(syntax.curly_count <= 0) { @@ -1505,8 +894,8 @@ unsigned char* parse_curly_close(unsigned char *p) { } // 構文関連の処理 -// break, case, continue, default, do, for, function, -// if, switch, while をこの内部で処理します。 +// break, case, continue, default, do, for, function, +// if, switch, while をこの内部で処理します。 unsigned char* parse_syntax(unsigned char *p) { switch(p[0]) { case 'b': @@ -1644,10 +1033,10 @@ unsigned char* parse_syntax(unsigned char *p) { if(!strncmp(p,"default",7) && !isalpha(*(p + 7))) { // switch - default の処理 if(syntax.curly_count <= 0 || syntax.curly[syntax.curly_count - 1].type != TYPE_SWITCH) { - disp_error_message("unexpected 'delault'",p); + disp_error_message("unexpected 'default'",p); return p+1; } else if(syntax.curly[syntax.curly_count - 1].flag) { - disp_error_message("dup 'delault'",p); + disp_error_message("dup 'default'",p); return p+1; } else { char label[256]; @@ -1745,6 +1134,7 @@ unsigned char* parse_syntax(unsigned char *p) { } set_label(l,script_pos); + p=skip_space(p); if(*p == ';') { // for(;;) のパターンなので必ず真 ; @@ -1780,7 +1170,7 @@ unsigned char* parse_syntax(unsigned char *p) { set_label(l,script_pos); // 次のループに入る時の処理 - // for 最後の '(' を ';' として扱うフラグ + // for 最後の ')' を ';' として扱うフラグ parse_syntax_for_flag = 1; syntax.curly[syntax.curly_count++].type = TYPE_NULL; p=parse_line(p); @@ -1949,8 +1339,8 @@ unsigned char* parse_syntax_close(unsigned char *p) { } // if, for , while , do の閉じ判定 -// flag == 1 : 閉じられた -// flag == 0 : 閉じられない +// flag == 1 : 閉じられた +// flag == 0 : 閉じられない unsigned char* parse_syntax_close_sub(unsigned char *p,int *flag) { unsigned char label[256]; int pos = syntax.curly_count - 1; @@ -2185,123 +1575,197 @@ static void read_constdb(void) } /*========================================== + * エラー表示 + *------------------------------------------ + */ + +const char* script_print_line( const char *p, const char *mark, int line ); + +void script_error(char *src,const char *file,int start_line, const char *error_msg, const char *error_pos) { + // エラーが発生した行を求める + int j; + int line = start_line; + const char *p; + const char *linestart[5] = { NULL, NULL, NULL, NULL, NULL }; + + for(p=src;p && *p;line++){ + char *lineend=strchr(p,'\n'); + if(lineend==NULL || error_pos<lineend){ + break; + } + for( j = 0; j < 4; j++ ) { + linestart[j] = linestart[j+1]; + } + linestart[4] = p; + p=lineend+1; + } + + printf("\a\n"); + printf("script error on %s line %d\n", file, line); + printf(" %s\n", error_msg); + for(j = 0; j < 5; j++ ) { + script_print_line( linestart[j], NULL, line + j - 5); + } + p = script_print_line( p, error_pos, -line); + for(j = 0; j < 5; j++) { + p = script_print_line( p, NULL, line + j + 1 ); + } +} + +const char* script_print_line( const char *p, const char *mark, int line ) { + int i; + if( p == NULL || !p[0] ) return NULL; + if( line < 0 ) + printf("*% 5d : ", -line); + else + printf(" % 5d : ", line); + for(i=0;p[i] && p[i] != '\n';i++){ + if(p + i != mark) + printf("%c",p[i]); + else + printf("\'%c\'",p[i]); + } + printf("\n"); + return p+i+(p[i] == '\n' ? 1 : 0); +} + +/*========================================== * スクリプトの解析 *------------------------------------------ */ -struct script_code* parse_script(unsigned char *src,int line) + +struct script_code* parse_script(unsigned char *src,const char *file,int line) { - unsigned char *p, *tmpp; + unsigned char *p,*tmpp; int i; struct script_code *code; - static int first = 1; + static int first=1; - if (first) { + memset(&syntax,0,sizeof(syntax)); + if(first){ add_buildin_func(); read_constdb(); } - first = 0; + first=0; -////////////////////////////////////////////// -// additional check on the input to filter empty scripts ("{}" and "{ }") - p = src; - p = skip_space(p); - if (*p != '{') { - disp_error_message("not found '{'", p); + script_buf=(unsigned char *)aCalloc(SCRIPT_BLOCK_SIZE,sizeof(unsigned char)); + script_pos=0; + script_size=SCRIPT_BLOCK_SIZE; + str_data[LABEL_NEXTLINE].type=C_NOP; + str_data[LABEL_NEXTLINE].backpatch=-1; + str_data[LABEL_NEXTLINE].label=-1; + for(i=LABEL_START;i<str_num;i++){ + if( + str_data[i].type==C_POS || str_data[i].type==C_NAME || + str_data[i].type==C_USERFUNC || str_data[i].type == C_USERFUNC_POS + ){ + str_data[i].type=C_NOP; + str_data[i].backpatch=-1; + str_data[i].label=-1; + } + } + + //Labels must be reparsed for the script.... + scriptlabel_db->clear(scriptlabel_db, NULL); + if( setjmp( error_jump ) != 0 ) { + //Restore program state when script has problems. [from jA] + script_error(src,file,line,error_msg,error_pos); + aFree( error_msg ); + aFree( script_buf ); + script_pos = 0; + script_size = 0; + script_buf = NULL; + for(i=LABEL_START;i<str_num;i++){ + if(str_data[i].type == C_NOP) str_data[i].type = C_NAME; + } return NULL; } + + p=src; + p=skip_space(p); + if(*p!='{'){ + disp_error_message("not found '{'",p); + exit(1); + } p++; p = skip_space(p); - if (*p == '}') { + if (p && *p == '}') { // an empty function, just return + aFree( script_buf ); + script_pos = 0; + script_size = 0; + script_buf = NULL; return NULL; } - script_buf = (unsigned char *) aCallocA(SCRIPT_BLOCK_SIZE, sizeof(unsigned char)); - script_pos = 0; - script_size = SCRIPT_BLOCK_SIZE; - str_data[LABEL_NEXTLINE].type = C_NOP; - str_data[LABEL_NEXTLINE].backpatch = -1; - str_data[LABEL_NEXTLINE].label = -1; - for (i = LABEL_START; i < str_num; i++) { - if ( - str_data[i].type == C_POS || str_data[i].type == C_NAME || - str_data[i].type == C_USERFUNC || str_data[i].type == C_USERFUNC_POS - ) { - str_data[i].type = C_NOP; - str_data[i].backpatch = -1; - str_data[i].label = -1; - } - } - - //Labels must be reparsed for the script.... - scriptlabel_db->clear(scriptlabel_db, NULL); - // for error message - startptr = src; - startline = line; - - while (p && *p && (*p != '}' || syntax.curly_count != 0)) { - p = skip_space(p); + while (p && *p && (*p!='}' || syntax.curly_count != 0)) { + p=skip_space(p); // labelだけ特殊処理 - tmpp = skip_space(skip_word(p)); - if (*tmpp == ':' && !(!strncmp(p,"default",7) && !isalpha(*(p + 7)))) { - int l, c; - c = *skip_word(p); - *skip_word(p) = 0; - l = add_str(p); - if (str_data[l].label != -1) { - *skip_word(p) = c; - disp_error_message("dup label ", p); + tmpp=skip_space(skip_word(p)); + if(*tmpp==':' && !(!strncmp(p,"default:",8) && p + 7 == tmpp)){ + int l,c; + + c=*skip_word(p); + *skip_word(p)=0; + if(*p == 0) { + *skip_word(p)=c; + disp_error_message("label length 0 ",p); + exit(1); + } + l=add_str(p); + if(str_data[l].label!=-1){ + *skip_word(p)=c; + disp_error_message("dup label ",p); exit(1); } - set_label(l, script_pos); + set_label(l,script_pos); strdb_put(scriptlabel_db, p, (void*)script_pos); // 外部用label db登録 - *skip_word(p) = c; - p = tmpp + 1; + *skip_word(p)=c; + p=tmpp+1; continue; } // 他は全部一緒くた - p = parse_line(p); - p = skip_space(p); + p=parse_line(p); + p=skip_space(p); add_scriptc(C_EOL); - set_label(LABEL_NEXTLINE, script_pos); - str_data[LABEL_NEXTLINE].type = C_NOP; - str_data[LABEL_NEXTLINE].backpatch = -1; - str_data[LABEL_NEXTLINE].label = -1; + set_label(LABEL_NEXTLINE,script_pos); + str_data[LABEL_NEXTLINE].type=C_NOP; + str_data[LABEL_NEXTLINE].backpatch=-1; + str_data[LABEL_NEXTLINE].label=-1; } add_scriptc(C_NOP); script_size = script_pos; - script_buf = (unsigned char *)aRealloc(script_buf, script_pos + 1); + script_buf=(unsigned char *)aRealloc(script_buf,script_pos); // 未解決のラベルを解決 - for (i = LABEL_START; i < str_num; i++) { - if (str_data[i].type == C_NOP) { - int j, next; - str_data[i].type = C_NAME; - str_data[i].label = i; - for (j = str_data[i].backpatch; j >= 0 && j != 0x00ffffff; ) { - next = (*(int*)(script_buf+j)) & 0x00ffffff; - script_buf[j] = i; - script_buf[j+1] = i>>8; - script_buf[j+2] = i>>16; - j = next; + for(i=LABEL_START;i<str_num;i++){ + if(str_data[i].type==C_NOP){ + int j,next; + str_data[i].type=C_NAME; + str_data[i].label=i; + for(j=str_data[i].backpatch;j>=0 && j!=0x00ffffff;){ + next=(*(int*)(script_buf+j)) & 0x00ffffff; + script_buf[j]=i; + script_buf[j+1]=i>>8; + script_buf[j+2]=i>>16; + j=next; } } } #ifdef DEBUG_DISP - for (i = 0; i < script_pos; i++) { - if ((i & 15) == 0) printf("%04x : ", i); - printf("%02x ", script_buf[i]); - if((i&15) == 15) printf("\n"); + for(i=0;i<script_pos;i++){ + if((i&15)==0) printf("%04x : ",i); + printf("%02x ",script_buf[i]); + if((i&15)==15) printf("\n"); } printf("\n"); #endif - startptr = NULL; //Clear pointer to prevent future references to a src that may be free'd. [Skotlex] code = aCalloc(1, sizeof(struct script_code)); code->script_buf = script_buf; code->script_size = script_size; @@ -2350,7 +1814,7 @@ int get_val(struct script_state*st,struct script_data* data) data->type=C_CONSTSTR; if( prefix=='@'){ if(sd) - data->u.str = pc_readregstr(sd,data->u.num); + data->u.str = pc_readregstr(sd,data->u.num); }else if(prefix=='$'){ data->u.str = (char *)idb_get(mapregstr_db,data->u.num); }else if(prefix=='#'){ @@ -2389,19 +1853,19 @@ int get_val(struct script_state*st,struct script_data* data) data->u.num = str_data[data->u.num&0x00ffffff].val; }else if(str_data[data->u.num&0x00ffffff].type==C_PARAM){ if(sd) - data->u.num = pc_readparam(sd,str_data[data->u.num&0x00ffffff].val); + data->u.num = pc_readparam(sd,str_data[data->u.num&0x00ffffff].val); }else if(prefix=='@'){ if(sd) - data->u.num = pc_readreg(sd,data->u.num); + data->u.num = pc_readreg(sd,data->u.num); }else if(prefix=='$'){ data->u.num = (int)idb_get(mapreg_db,data->u.num); }else if(prefix=='#'){ if( name[1]=='#'){ if(sd) - data->u.num = pc_readaccountreg2(sd,name); + data->u.num = pc_readaccountreg2(sd,name); }else{ if(sd) - data->u.num = pc_readaccountreg(sd,name); + data->u.num = pc_readaccountreg(sd,name); } }else if(prefix=='.'){ struct linkdb_node **n; @@ -2415,7 +1879,7 @@ int get_val(struct script_state*st,struct script_data* data) data->u.num = (int)linkdb_search(n, (void*)data->u.num); }else{ if(sd) - data->u.num = pc_readglobalreg(sd,name); + data->u.num = pc_readglobalreg(sd,name); } } } @@ -2430,7 +1894,7 @@ void* get_val2(struct script_state*st,int num,struct linkdb_node **ref) struct script_data dat; dat.type=C_NAME; dat.u.num=num; - dat.ref = ref; + dat.ref=ref; get_val(st,&dat); if( dat.type==C_INT ) return (void*)dat.u.num; else return (void*)dat.u.str; @@ -2476,10 +1940,6 @@ static int set_reg(struct script_state*st,struct map_session_data *sd,int num,ch }else{ pc_setglobalreg_str(sd,name,str); } // [zBuffer] - - /*else{ - ShowWarning("script: set_reg: illegal scope string variable !"); - }*/ }else{ // 数値 int val = (int)v; @@ -2676,17 +2136,13 @@ void script_free_vars(struct linkdb_node **node) { * Free's the whole stack. Invoked when clearing a character. [Skotlex] *------------------------------------------ */ -void script_free_stack(struct script_stack* stack) -{ +void script_free_stack(struct script_stack *stack) { int i; - for (i = 0; i < stack->sp; i++) - { - if(stack->stack_data[i].type==C_STR) - { - //ShowDebug ("script_free_stack: freeing %p at sp=%d.\n", stack->stack_data[i].u.str, i); + for(i = 0; i < stack->sp; i++) { + if( stack->stack_data[i].type == C_STR ) { aFree(stack->stack_data[i].u.str); stack->stack_data[i].type = C_INT; - }else if( i > 0 && stack->stack_data[i].type == C_RETINFO ) { + } else if( i > 0 && stack->stack_data[i].type == C_RETINFO ) { struct linkdb_node** n = (struct linkdb_node**)stack->stack_data[i-1].u.num; script_free_vars( n ); aFree( n ); @@ -2694,8 +2150,8 @@ void script_free_stack(struct script_stack* stack) } script_free_vars( stack->var_function ); aFree(stack->var_function); - aFree (stack->stack_data); - aFree (stack); + aFree(stack->stack_data); + aFree(stack); } void script_free_code(struct script_code* code) { @@ -2704,49 +2160,1796 @@ void script_free_code(struct script_code* code) { aFree( code ); } -int axtoi(char *hexStg) { - int n = 0; // position in string - int m = 0; // position in digit[] to shift - int count; // loop index - int intValue = 0; // integer value of hex string - int digit[11]; // hold values to convert - while (n < 10) { - if (hexStg[n]=='\0') +// +// 実行部main +// +/*========================================== + * コマンドの読み取り + *------------------------------------------ + */ +static int unget_com_data=-1; +int get_com(unsigned char *script,int *pos) +{ + int i,j; + if(unget_com_data>=0){ + i=unget_com_data; + unget_com_data=-1; + return i; + } + if(script[*pos]>=0x80){ + return C_INT; + } + i=0; j=0; + while(script[*pos]>=0x40){ + i=script[(*pos)++]<<j; + j+=6; + } + return i+(script[(*pos)++]<<j); +} + +/*========================================== + * コマンドのプッシュバック + *------------------------------------------ + */ +void unget_com(int c) +{ + if(unget_com_data!=-1){ + if(battle_config.error_log) + ShowError("unget_com can back only 1 data\n"); + } + unget_com_data=c; +} + +/*========================================== + * 数値の所得 + *------------------------------------------ + */ +int get_num(unsigned char *script,int *pos) +{ + int i,j; + i=0; j=0; + while(script[*pos]>=0xc0){ + i+=(script[(*pos)++]&0x7f)<<j; + j+=6; + } + return i+((script[(*pos)++]&0x7f)<<j); +} + +/*========================================== + * スタックから値を取り出す + *------------------------------------------ + */ +int pop_val(struct script_state* st) +{ + if(st->stack->sp<=0) + return 0; + st->stack->sp--; + get_val(st,&(st->stack->stack_data[st->stack->sp])); + if(st->stack->stack_data[st->stack->sp].type==C_INT) + return st->stack->stack_data[st->stack->sp].u.num; + return 0; +} + +int isstr(struct script_data *c) { + if( c->type == C_STR || c->type == C_CONSTSTR ) + return 1; + else if( c->type == C_NAME ) { + char *p = str_buf + str_data[c->u.num & 0xffffff].str; + char postfix = p[strlen(p)-1]; + return (postfix == '$'); + } + return 0; +} + +/*========================================== + * 加算演算子 + *------------------------------------------ + */ +void op_add(struct script_state* st) +{ + st->stack->sp--; + get_val(st,&(st->stack->stack_data[st->stack->sp])); + get_val(st,&(st->stack->stack_data[st->stack->sp-1])); + + if(isstr(&st->stack->stack_data[st->stack->sp]) || isstr(&st->stack->stack_data[st->stack->sp-1])){ + conv_str(st,&(st->stack->stack_data[st->stack->sp])); + conv_str(st,&(st->stack->stack_data[st->stack->sp-1])); + } + if(st->stack->stack_data[st->stack->sp].type==C_INT){ // ii + int *i1 = &st->stack->stack_data[st->stack->sp-1].u.num; + int *i2 = &st->stack->stack_data[st->stack->sp].u.num; + int ret = *i1 + *i2; + double ret_double = (double)*i1 + (double)*i2; + if(ret_double > INT_MAX|| ret_double < INT_MIN) { + ShowWarning("script::op_add overflow detected op:%d\n",C_ADD); + report_src(st); + ret = cap_value(ret, INT_MIN, INT_MAX); + } + *i1 = ret; + } else { // ssの予定 + char *buf; + buf=(char *)aMallocA((strlen(st->stack->stack_data[st->stack->sp-1].u.str)+ + strlen(st->stack->stack_data[st->stack->sp].u.str)+1)*sizeof(char)); + strcpy(buf,st->stack->stack_data[st->stack->sp-1].u.str); + strcat(buf,st->stack->stack_data[st->stack->sp].u.str); + if(st->stack->stack_data[st->stack->sp-1].type==C_STR) + { + aFree(st->stack->stack_data[st->stack->sp-1].u.str); + st->stack->stack_data[st->stack->sp-1].type=C_INT; + } + if(st->stack->stack_data[st->stack->sp].type==C_STR) + { + aFree(st->stack->stack_data[st->stack->sp].u.str); + st->stack->stack_data[st->stack->sp].type=C_INT; + } + st->stack->stack_data[st->stack->sp-1].type=C_STR; + st->stack->stack_data[st->stack->sp-1].u.str=buf; + } + st->stack->stack_data[st->stack->sp-1].ref = NULL; +} + +/*========================================== + * 二項演算子(文字列) + *------------------------------------------ + */ +void op_2str(struct script_state *st,int op,int sp1,int sp2) +{ + char *s1=st->stack->stack_data[sp1].u.str, + *s2=st->stack->stack_data[sp2].u.str; + int a=0; + + switch(op){ + case C_EQ: + a= (strcmp(s1,s2)==0); + break; + case C_NE: + a= (strcmp(s1,s2)!=0); + break; + case C_GT: + a= (strcmp(s1,s2)> 0); + break; + case C_GE: + a= (strcmp(s1,s2)>=0); + break; + case C_LT: + a= (strcmp(s1,s2)< 0); + break; + case C_LE: + a= (strcmp(s1,s2)<=0); + break; + default: + ShowWarning("script: illegal string operator\n"); + break; + } + + // Because push_val() overwrite stack_data[sp1], C_STR on stack_data[sp1] won't be freed. + // So, call push_val() after freeing strings. [jA1783] + // push_val(st->stack,C_INT,a); + if(st->stack->stack_data[sp1].type==C_STR) + { + aFree(s1); + st->stack->stack_data[sp1].type=C_INT; + } + if(st->stack->stack_data[sp2].type==C_STR) + { + aFree(s2); + st->stack->stack_data[sp2].type=C_INT; + } + push_val(st->stack,C_INT,a); +} + +/*========================================== + * 二項演算子(数値) + *------------------------------------------ + */ +void op_2num(struct script_state *st,int op,int i1,int i2) +{ + int ret = 0; + double ret_double = 0; + switch(op){ + case C_MOD: ret = i1 % i2; break; + case C_AND: ret = i1 & i2; break; + case C_OR: ret = i1 | i2; break; + case C_XOR: ret = i1 ^ i2; break; + case C_LAND: ret = (i1 && i2); break; + case C_LOR: ret = (i1 || i2); break; + case C_EQ: ret = (i1 == i2); break; + case C_NE: ret = (i1 != i2); break; + case C_GT: ret = (i1 > i2); break; + case C_GE: ret = (i1 >= i2); break; + case C_LT: ret = (i1 < i2); break; + case C_LE: ret = (i1 <= i2); break; + case C_R_SHIFT: ret = i1>>i2; break; + case C_L_SHIFT: ret = i1<<i2; break; + default: + switch(op) { + case C_SUB: ret = i1 - i2; ret_double = (double)i1 - (double)i2; break; + case C_MUL: ret = i1 * i2; ret_double = (double)i1 * (double)i2; break; + case C_DIV: + if(i2 == 0) { + printf("script::op_2num division by zero.\n"); + ret = INT_MAX; + ret_double = 0; // doubleの精度が怪しいのでオーバーフロー対策を飛ばす + } else { + ret = i1 / i2; ret_double = (double)i1 / (double)i2; + } break; - if (hexStg[n] > 0x29 && hexStg[n] < 0x40 ) //if 0 to 9 - digit[n] = hexStg[n] & 0x0f; //convert to int - else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f - digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int - else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F - digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int - else break; - n++; + } + if(ret_double > INT_MAX || ret_double < INT_MIN) { + printf("script::op_2num overflow detected op:%d\n",op); + report_src(st); + ret = cap_value(ret_double,INT_MAX,INT_MIN); + } } - count = n; - m = n - 1; - n = 0; - while(n < count) { - // digit[n] is value of hex digit at position n - // (m << 2) is the number of positions to shift - // OR the bits into return value - intValue = intValue | (digit[n] << (m << 2)); - m--; // adjust the position to set - n++; // next digit to process + push_val(st->stack,C_INT,ret); +} + +/*========================================== + * 二項演算子 + *------------------------------------------ + */ +void op_2(struct script_state *st,int op) +{ + int i1,i2; + char *s1=NULL,*s2=NULL; + + i2=pop_val(st); + if( isstr(&st->stack->stack_data[st->stack->sp]) ) + s2=st->stack->stack_data[st->stack->sp].u.str; + + i1=pop_val(st); + if( isstr(&st->stack->stack_data[st->stack->sp]) ) + s1=st->stack->stack_data[st->stack->sp].u.str; + + if( s1!=NULL && s2!=NULL ){ + // ss => op_2str + op_2str(st,op,st->stack->sp,st->stack->sp+1); + }else if( s1==NULL && s2==NULL ){ + // ii => op_2num + op_2num(st,op,i1,i2); + }else{ + // si,is => error + ShowWarning("script: op_2: int&str, str&int not allow.\n"); + report_src(st); + if(s1 && st->stack->stack_data[st->stack->sp].type == C_STR) + { + aFree(s1); + st->stack->stack_data[st->stack->sp].type = C_INT; + } + if(s2 && st->stack->stack_data[st->stack->sp+1].type == C_STR) + { + aFree(s2); + st->stack->stack_data[st->stack->sp+1].type = C_INT; + } + push_val(st->stack,C_INT,0); } - return (intValue); } -// [Lance] Hex string to integer converter -int buildin_axtoi(struct script_state *st) +/*========================================== + * 単項演算子 + *------------------------------------------ + */ +void op_1num(struct script_state *st,int op) { - char *hex = conv_str(st,& (st->stack->stack_data[st->start+2])); - push_val(st->stack, C_INT, axtoi(hex)); + int i1; + i1=pop_val(st); + switch(op){ + case C_NEG: + i1=-i1; + break; + case C_NOT: + i1=~i1; + break; + case C_LNOT: + i1=!i1; + break; + } + push_val(st->stack,C_INT,i1); +} + + +/*========================================== + * 関数の実行 + *------------------------------------------ + */ +int run_func(struct script_state *st) +{ + int i,start_sp,end_sp,func; + + end_sp=st->stack->sp; +#ifdef DEBUG_RUN + if(battle_config.etc_log) { + ShowDebug("run_func : %s? (%d(%d)) sp=%d (%d...%d)\n",str_buf+str_data[func].str, func, str_data[func].type, st->stack->sp, st->start, st->end); + ShowDebug("stack dump :"); + for(i=0;i<end_sp;i++){ + switch(st->stack->stack_data[i].type){ + case C_INT: + printf(" int(%d)",st->stack->stack_data[i].u.num); + break; + case C_NAME: + printf(" name(%s)",str_buf+str_data[st->stack->stack_data[i].u.num & 0xffffff].str); + break; + case C_ARG: + printf(" arg"); + break; + case C_POS: + printf(" pos(%d)",st->stack->stack_data[i].u.num); + break; + case C_STR: + printf(" str(%s)",st->stack->stack_data[i].u.str); + break; + case C_CONSTSTR: + printf(" cstr(%s)",st->stack->stack_data[i].u.str); + break; + default: + printf(" etc(%d,%d)",st->stack->stack_data[i].type,st->stack->stack_data[i].u.num); + } + } + printf("\n"); + } +#endif + for(i=end_sp-1;i>=0 && st->stack->stack_data[i].type!=C_ARG;i--); + if(i==0){ + if(battle_config.error_log) + ShowError("function not found\n"); +// st->stack->sp=0; + st->state=END; + report_src(st); + return 1; + } + start_sp=i-1; + st->start=i-1; + st->end=end_sp; + + func=st->stack->stack_data[st->start].u.num; + if(str_data[func].type!=C_FUNC ){ + ShowMessage ("run_func: '"CL_WHITE"%s"CL_RESET"' (type %d) is not function and command!\n"); +// st->stack->sp=0; + st->state=END; + report_src(st); + return 1; + } +#ifdef DEBUG_RUN + ShowDebug("run_func : %s (func_no : %d , func_type : %d pos : 0x%x)\n", + str_buf+str_data[func].str,func,str_data[func].type,st->pos + ); +#endif + if(str_data[func].func){ + if (str_data[func].func(st)) //Report error + report_src(st); + } else { + if(battle_config.error_log) + ShowError("run_func : %s? (%d(%d))\n",str_buf+str_data[func].str,func,str_data[func].type); + push_val(st->stack,C_INT,0); + report_src(st); + } + + // Stack's datum are used when re-run functions [Eoe] + if(st->state != RERUNLINE) { + pop_stack(st->stack,start_sp,end_sp); + } + + if(st->state==RETFUNC){ + // ユーザー定義関数からの復帰 + int olddefsp=st->stack->defsp; + int i; + + pop_stack(st->stack,st->stack->defsp,start_sp); // 復帰に邪魔なスタック削除 + if(st->stack->defsp<5 || st->stack->stack_data[st->stack->defsp-1].type!=C_RETINFO){ + ShowWarning("script:run_func(return) return without callfunc or callsub!\n"); + st->state=END; + report_src(st); + return 1; + } + script_free_vars( st->stack->var_function ); + aFree(st->stack->var_function); + + i = conv_num(st,& (st->stack->stack_data[st->stack->defsp-5])); // 引数の数所得 + st->pos=conv_num(st,& (st->stack->stack_data[st->stack->defsp-1])); // スクリプト位置の復元 + st->script=(struct script_code*)conv_num(st,& (st->stack->stack_data[st->stack->defsp-3])); // スクリプトを復元 + st->stack->var_function = (struct linkdb_node**)st->stack->stack_data[st->stack->defsp-2].u.num; // 関数依存変数 + + st->stack->defsp=conv_num(st,& (st->stack->stack_data[st->stack->defsp-4])); // 基準スタックポインタを復元 + pop_stack(st->stack,olddefsp-5-i,olddefsp); // 要らなくなったスタック(引数と復帰用データ)削除 + + st->state=GOTO; + } + + return 0; +} + +/*========================================== + * スクリプトの実行 + *------------------------------------------ + */ +void run_script_main(struct script_state *st); + +void run_script(struct script_code *rootscript,int pos,int rid,int oid) +{ + struct script_state *st; + struct map_session_data *sd=NULL; + + if(rootscript==NULL || pos<0) + return; + + if (rid) sd = map_id2sd(rid); + if (sd && sd->st && sd->st->scriptroot == rootscript && sd->st->pos == pos){ + //Resume script. + st = sd->st; + } else { + st = aCalloc(sizeof(struct script_state), 1); + // the script is different, make new script_state and stack + st->stack = aMalloc (sizeof(struct script_stack)); + st->stack->sp=0; + st->stack->sp_max=64; + st->stack->stack_data = (struct script_data *)aCalloc(st->stack->sp_max,sizeof(st->stack->stack_data[0])); + st->stack->defsp = st->stack->sp; + st->stack->var_function = aCalloc(1, sizeof(struct linkdb_node*)); + st->state = RUN; + st->script = rootscript; + } + st->pos = pos; + st->rid = rid; + st->oid = oid; + st->sleep.timer = -1; + run_script_main(st); +} + +/*========================================== + * 指定ノードをsleep_dbから削除 + *------------------------------------------ + */ +struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n) +{ + struct linkdb_node *retnode; + + if( n == NULL) + return NULL; + if( n->prev == NULL ) + sleep_db = n->next; + else + n->prev->next = n->next; + if( n->next ) + n->next->prev = n->prev; + retnode = n->next; + aFree( n ); + return retnode; // 次のノードを返す +} + +/*========================================== + * sleep用タイマー関数 + *------------------------------------------ + */ +int run_script_timer(int tid, unsigned int tick, int id, int data) +{ + struct script_state *st = (struct script_state *)data; + struct linkdb_node *node = (struct linkdb_node *)sleep_db; + struct map_session_data *sd = map_id2sd(st->rid); + + if((sd && sd->char_id != id) || (st->rid && !sd)) + { //Character mismatch. Cancel execution. + st->rid = 0; + st->state = END; + } + while( node && st->sleep.timer != -1 ) { + if( (int)node->key == st->oid && ((struct script_state *)node->data)->sleep.timer == st->sleep.timer ) { + script_erase_sleepdb(node); + st->sleep.timer = -1; + break; + } + node = node->next; + } + run_script_main(st); + return 0; +} + +/*========================================== + * スクリプトの実行メイン部分 + *------------------------------------------ + */ +void run_script_main(struct script_state *st) +{ + int c; + int cmdcount=script_config.check_cmdcount; + int gotocount=script_config.check_gotocount; + struct map_session_data *sd; + //For backing up purposes + struct script_state *bk_st = NULL; + int bk_npcid = 0; + struct script_stack *stack=st->stack; + + if(st->rid) sd = map_id2sd(st->rid); + if(sd){ + if(sd->st != st){ + bk_st = sd->st; + bk_npcid = sd->npc_id; + } + sd->st = st; + sd->npc_id = st->oid; + } + + if(st->state == RERUNLINE) { + st->state = RUN; + run_func(st); + if(st->state == GOTO) + st->state = RUN; + } else if(st->state != END) + st->state = RUN; + + while(st->state == RUN){ + c= get_com((unsigned char *) st->script->script_buf,&st->pos); + switch(c){ + case C_EOL: + if(stack->sp!=stack->defsp){ + if(stack->sp > stack->defsp) + { //sp > defsp is valid in cases when you invoke functions and don't use the returned value. [Skotlex] + //Since sp is supposed to be defsp in these cases, we could assume the extra stack elements are unneeded. + if (battle_config.etc_log) + ShowWarning("Clearing unused stack stack.sp(%d) -> default(%d)\n",stack->sp,stack->defsp); + pop_stack(stack, stack->defsp, stack->sp); //Clear out the unused stack-section. + } else if(battle_config.error_log) + ShowError("stack.sp(%d) != default(%d)\n",stack->sp,stack->defsp); + stack->sp=stack->defsp; + } + break; + case C_INT: + push_val(stack,C_INT,get_num((unsigned char *) st->script->script_buf,&st->pos)); + break; + case C_POS: + case C_NAME: + push_val(stack,c,(*(int*)(st->script->script_buf+st->pos))&0xffffff); + st->pos+=3; + break; + case C_ARG: + push_val(stack,c,0); + break; + case C_STR: + push_str(stack,C_CONSTSTR,(unsigned char *) (st->script->script_buf+st->pos)); + while(st->script->script_buf[st->pos++]); + break; + case C_FUNC: + run_func(st); + if(st->state==GOTO){ + st->state = RUN; + if( gotocount>0 && (--gotocount)<=0 ){ + ShowError("run_script: infinity loop !\n"); + st->state=END; + } + } + break; + + case C_ADD: + op_add(st); + break; + + case C_SUB: + case C_MUL: + case C_DIV: + case C_MOD: + case C_EQ: + case C_NE: + case C_GT: + case C_GE: + case C_LT: + case C_LE: + case C_AND: + case C_OR: + case C_XOR: + case C_LAND: + case C_LOR: + case C_R_SHIFT: + case C_L_SHIFT: + op_2(st,c); + break; + + case C_NEG: + case C_NOT: + case C_LNOT: + op_1num(st,c); + break; + + case C_NOP: + st->state=END; + break; + + default: + if(battle_config.error_log) + ShowError("unknown command : %d @ %d\n",c,pos); + st->state=END; + break; + } + if( cmdcount>0 && (--cmdcount)<=0 ){ + ShowError("run_script: infinity loop !\n"); + st->state=END; + } + } + + if(st->sleep.tick > 0) { + //Delay execution + st->sleep.charid = sd?sd->char_id:0; + st->sleep.timer = add_timer(gettick()+st->sleep.tick, + run_script_timer, st->sleep.charid, (int)st); + linkdb_insert(&sleep_db, (void*)st->oid, st); + //Restore previous script + sd->st = bk_st; + sd->npc_id = bk_npcid; + bk_st = NULL; //Remove tag for removal. + } + else if(st->state != END && sd){ + //Resume later (st is already attached to player). + if(bk_st && sd->st != bk_st) + ShowWarning("Unable to restore stack! Double continuation!\n"); + } else { + //Dispose of script. + if (sd) + { //Restore previous stack and save char. + if(sd->state.using_fake_npc){ + clif_clearchar_id(sd->npc_id, 0, sd->fd); + sd->state.using_fake_npc = 0; + } + //Restore previous script if any. + sd->st = bk_st; + sd->npc_id = bk_npcid; + if (!bk_st) + npc_event_dequeue(sd); + else + bk_st = NULL; //Remove tag for removal. + if (sd->state.reg_dirty&2) + intif_saveregistry(sd,2); + if (sd->state.reg_dirty&1) + intif_saveregistry(sd,1); + } + st->pos = -1; + script_free_stack (st->stack); + aFree(st); + } + + if (bk_st) + { //Remove previous script + bk_st->pos = -1; + script_free_stack(bk_st->stack); + aFree(bk_st); + bk_st = NULL; + } + + + +} + +/*========================================== + * マップ変数の変更 + *------------------------------------------ + */ +int mapreg_setreg(int num,int val) +{ +#if !defined(TXT_ONLY) && defined(MAPREGSQL) + int i=num>>24; + char *name=str_buf+str_data[num&0x00ffffff].str; + char tmp_str[64]; +#endif + + if(val!=0) { + if(idb_put(mapreg_db,num,(void*)val)) + ; +#if !defined(TXT_ONLY) && defined(MAPREGSQL) + else if(name[1] != '@') { + sprintf(tmp_sql,"INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%d')",mapregsql_db,mapregsql_db_varname,mapregsql_db_index,mapregsql_db_value,jstrescapecpy(tmp_str,name),i,val); + if(mysql_query(&mmysql_handle,tmp_sql)){ + ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } + } +#endif + // else + } else { // [zBuffer] +#if !defined(TXT_ONLY) && defined(MAPREGSQL) + if(name[1] != '@') { // Remove from database because it is unused. + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_varname,name,mapregsql_db_index,i); + if(mysql_query(&mmysql_handle,tmp_sql)){ + ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } + } +#endif + idb_remove(mapreg_db,num); + } + + mapreg_dirty=1; + return 0; +} +/*========================================== + * 文字列型マップ変数の変更 + *------------------------------------------ + */ +int mapreg_setregstr(int num,const char *str) +{ + char *p; +#if !defined(TXT_ONLY) && defined(MAPREGSQL) + char tmp_str[64]; + char tmp_str2[512]; + int i=num>>24; // [zBuffer] + char *name=str_buf+str_data[num&0x00ffffff].str; +#endif + + if( str==NULL || *str==0 ){ +#if !defined(TXT_ONLY) && defined(MAPREGSQL) + if(name[1] != '@') { + sprintf(tmp_sql,"DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_varname,name,mapregsql_db_index,i); + if(mysql_query(&mmysql_handle,tmp_sql)){ + ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } + } +#endif + idb_remove(mapregstr_db,num); + mapreg_dirty=1; + return 0; + } + p=(char *)aMallocA((strlen(str)+1)*sizeof(char)); + strcpy(p,str); + + if (idb_put(mapregstr_db,num,p)) + ; +#if !defined(TXT_ONLY) && defined(MAPREGSQL) + else if(name[1] != '@'){ //put returned null, so we must insert. + // Someone is causing a database size infinite increase here without name[1] != '@' [Lance] + sprintf(tmp_sql,"INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%s')",mapregsql_db,mapregsql_db_varname,mapregsql_db_index,mapregsql_db_value,jstrescapecpy(tmp_str,name),i,jstrescapecpy(tmp_str2,p)); + if(mysql_query(&mmysql_handle,tmp_sql)){ + ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } + } +#endif + mapreg_dirty=1; + return 0; +} + +/*========================================== + * 永続的マップ変数の読み込み + *------------------------------------------ + */ +static int script_load_mapreg(void) +{ +#if defined(TXT_ONLY) || !defined(MAPREGSQL) + FILE *fp; + char line[1024]; + + if( (fp=fopen(mapreg_txt,"rt"))==NULL ) + return -1; + + while(fgets(line,sizeof(line),fp)){ + char buf1[256],buf2[1024],*p; + int n,v,s,i; + if( sscanf(line,"%255[^,],%d\t%n",buf1,&i,&n)!=2 && + (i=0,sscanf(line,"%[^\t]\t%n",buf1,&n)!=1) ) + continue; + if( buf1[strlen(buf1)-1]=='$' ){ + if( sscanf(line+n,"%[^\n\r]",buf2)!=1 ){ + ShowError("%s: %s broken data !\n",mapreg_txt,buf1); + continue; + } + p=(char *)aMallocA((strlen(buf2) + 1)*sizeof(char)); + strcpy(p,buf2); + s= add_str((unsigned char *) buf1); + idb_put(mapregstr_db,(i<<24)|s,p); + }else{ + if( sscanf(line+n,"%d",&v)!=1 ){ + ShowError("%s: %s broken data !\n",mapreg_txt,buf1); + continue; + } + s= add_str((unsigned char *) buf1); + idb_put(mapreg_db,(i<<24)|s,(void*)v); + } + } + fclose(fp); + mapreg_dirty=0; + return 0; +#else + // SQL mapreg code start [zBuffer] + /* + 0 1 2 + +-------------------------+ + | varname | index | value | + +-------------------------+ + */ + unsigned int perfomance = (unsigned int)time(NULL); + sprintf(tmp_sql,"SELECT * FROM `%s`",mapregsql_db); + ShowInfo("Querying script_load_mapreg ...\n"); + if(mysql_query(&mmysql_handle, tmp_sql) ) { + ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + return -1; + } + ShowInfo("Success! Returning results ...\n"); + sql_res = mysql_store_result(&mmysql_handle); + if (sql_res) { + while ((sql_row = mysql_fetch_row(sql_res))) { + char buf1[33], *p = NULL; + int i,v,s; + strcpy(buf1,sql_row[0]); + if( buf1[strlen(buf1)-1]=='$' ){ + i = atoi(sql_row[1]); + p=(char *)aMallocA((strlen(sql_row[2]) + 1)*sizeof(char)); + strcpy(p,sql_row[2]); + s= add_str((unsigned char *) buf1); + idb_put(mapregstr_db,(i<<24)|s,p); + }else{ + s= add_str((unsigned char *) buf1); + v= atoi(sql_row[2]); + i = atoi(sql_row[1]); + idb_put(mapreg_db,(i<<24)|s,(void *)v); + } + } + } + ShowInfo("Freeing results...\n"); + mysql_free_result(sql_res); + mapreg_dirty=0; + perfomance = ((unsigned int)time(NULL) - perfomance); + ShowInfo("SQL Mapreg Loading Completed Under %d Seconds.\n",perfomance); + return 0; +#endif /* TXT_ONLY */ +} +/*========================================== + * 永続的マップ変数の書き込み + *------------------------------------------ + */ +static int script_save_mapreg_intsub(DBKey key,void *data,va_list ap) +{ +#if defined(TXT_ONLY) || !defined(MAPREGSQL) + FILE *fp=va_arg(ap,FILE*); + int num=key.i&0x00ffffff, i=key.i>>24; + char *name=str_buf+str_data[num].str; + if( name[1]!='@' ){ + if(i==0) + fprintf(fp,"%s\t%d\n", name, (int)data); + else + fprintf(fp,"%s,%d\t%d\n", name, i, (int)data); + } + return 0; +#else + int num=key.i&0x00ffffff, i=key.i>>24; // [zBuffer] + char *name=str_buf+str_data[num].str; + if ( name[1] != '@') { + sprintf(tmp_sql,"UPDATE `%s` SET `%s`='%d' WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_value,(int)data,mapregsql_db_varname,name,mapregsql_db_index,i); + if(mysql_query(&mmysql_handle, tmp_sql) ) { + ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } + } + return 0; +#endif +} +static int script_save_mapreg_strsub(DBKey key,void *data,va_list ap) +{ +#if defined(TXT_ONLY) || !defined(MAPREGSQL) + FILE *fp=va_arg(ap,FILE*); + int num=key.i&0x00ffffff, i=key.i>>24; + char *name=str_buf+str_data[num].str; + if( name[1]!='@' ){ + if(i==0) + fprintf(fp,"%s\t%s\n", name, (char *)data); + else + fprintf(fp,"%s,%d\t%s\n", name, i, (char *)data); + } + return 0; +#else + char tmp_str2[512]; + int num=key.i&0x00ffffff, i=key.i>>24; + char *name=str_buf+str_data[num].str; + if ( name[1] != '@') { + sprintf(tmp_sql,"UPDATE `%s` SET `%s`='%s' WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_value,jstrescapecpy(tmp_str2,(char *)data),mapregsql_db_varname,name,mapregsql_db_index,i); + if(mysql_query(&mmysql_handle, tmp_sql) ) { + ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); + ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + } + } + return 0; +#endif +} +static int script_save_mapreg(void) +{ +#if defined(TXT_ONLY) || !defined(MAPREGSQL) + FILE *fp; + int lock; + + if( (fp=lock_fopen(mapreg_txt,&lock))==NULL ) { + ShowError("script_save_mapreg: Unable to lock-open file [%s]\n",mapreg_txt); + return -1; + } + mapreg_db->foreach(mapreg_db,script_save_mapreg_intsub,fp); + mapregstr_db->foreach(mapregstr_db,script_save_mapreg_strsub,fp); + lock_fclose(fp,mapreg_txt,&lock); +#else + unsigned int perfomance = (unsigned int)time(NULL); + mapreg_db->foreach(mapreg_db,script_save_mapreg_intsub); // [zBuffer] + mapregstr_db->foreach(mapregstr_db,script_save_mapreg_strsub); + perfomance = ((unsigned int)time(NULL) - perfomance); + if(perfomance > 2) + ShowWarning("Slow Query: MapregSQL Saving @ %d second(s).\n", perfomance); +#endif + mapreg_dirty=0; + return 0; +} +static int script_autosave_mapreg(int tid,unsigned int tick,int id,int data) +{ + if(mapreg_dirty) + if (script_save_mapreg() == -1) + ShowError("Failed to save the mapreg data!\n"); return 0; } -// -// 埋め込み関数 -// +/*========================================== + * + *------------------------------------------ + */ +static int set_posword(char *p) +{ + char* np,* str[15]; + int i=0; + for(i=0;i<11;i++) { + if((np=strchr(p,','))!=NULL) { + str[i]=p; + *np=0; + p=np+1; + } else { + str[i]=p; + p+=strlen(p); + } + if(str[i]) + strcpy(pos[i],str[i]); + } + return 0; +} + +int script_config_read_sub(char *cfgName) +{ + int i; + char line[1024],w1[1024],w2[1024]; + FILE *fp; + + + fp=fopen(cfgName,"r"); + if(fp==NULL){ + ShowError("file not found: [%s]\n", cfgName); + return 1; + } + while(fgets(line,sizeof(line)-1,fp)){ + if(line[0] == '/' && line[1] == '/') + continue; + i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); + if(i!=2) + continue; + if(strcmpi(w1,"refine_posword")==0) { + set_posword(w2); + } + else if(strcmpi(w1,"verbose_mode")==0) { + script_config.verbose_mode = battle_config_switch(w2); + } + else if(strcmpi(w1,"warn_func_no_comma")==0) { + script_config.warn_func_no_comma = battle_config_switch(w2); + } + else if(strcmpi(w1,"warn_cmd_no_comma")==0) { + script_config.warn_cmd_no_comma = battle_config_switch(w2); + } + else if(strcmpi(w1,"warn_func_mismatch_paramnum")==0) { + script_config.warn_func_mismatch_paramnum = battle_config_switch(w2); + } + else if(strcmpi(w1,"warn_cmd_mismatch_paramnum")==0) { + script_config.warn_cmd_mismatch_paramnum = battle_config_switch(w2); + } + else if(strcmpi(w1,"check_cmdcount")==0) { + script_config.check_cmdcount = battle_config_switch(w2); + } + else if(strcmpi(w1,"check_gotocount")==0) { + script_config.check_gotocount = battle_config_switch(w2); + } + else if(strcmpi(w1,"event_script_type")==0) { + script_config.event_script_type = battle_config_switch(w2); + } + else if(strcmpi(w1,"event_requires_trigger")==0) { + script_config.event_requires_trigger = battle_config_switch(w2); + } + else if(strcmpi(w1,"die_event_name")==0) { + strncpy(script_config.die_event_name, w2, NAME_LENGTH-1); + if (strlen(script_config.die_event_name) != strlen(w2)) + ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.die_event_name); + } + else if(strcmpi(w1,"kill_pc_event_name")==0) { + strncpy(script_config.kill_pc_event_name, w2, NAME_LENGTH-1); + if (strlen(script_config.kill_pc_event_name) != strlen(w2)) + ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.kill_pc_event_name); + } + else if(strcmpi(w1,"kill_mob_event_name")==0) { + strncpy(script_config.kill_mob_event_name, w2, NAME_LENGTH-1); + if (strlen(script_config.kill_mob_event_name) != strlen(w2)) + ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.kill_mob_event_name); + } + else if(strcmpi(w1,"login_event_name")==0) { + strncpy(script_config.login_event_name, w2, NAME_LENGTH-1); + if (strlen(script_config.login_event_name) != strlen(w2)) + ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.login_event_name); + } + else if(strcmpi(w1,"logout_event_name")==0) { + strncpy(script_config.logout_event_name, w2, NAME_LENGTH-1); + if (strlen(script_config.logout_event_name) != strlen(w2)) + ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.logout_event_name); + } + else if(strcmpi(w1,"loadmap_event_name")==0) { + strncpy(script_config.loadmap_event_name, w2, NAME_LENGTH-1); + if (strlen(script_config.loadmap_event_name) != strlen(w2)) + ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.loadmap_event_name); + } + else if(strcmpi(w1,"baselvup_event_name")==0) { + strncpy(script_config.baselvup_event_name, w2, NAME_LENGTH-1); + if (strlen(script_config.baselvup_event_name) != strlen(w2)) + ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.baselvup_event_name); + } + else if(strcmpi(w1,"joblvup_event_name")==0) { + strncpy(script_config.joblvup_event_name, w2, NAME_LENGTH-1); + if (strlen(script_config.joblvup_event_name) != strlen(w2)) + ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.joblvup_event_name); + } + else if(strcmpi(w1,"import")==0){ + script_config_read_sub(w2); + } + } + fclose(fp); + + return 0; +} + +int script_config_read(char *cfgName) +{ //Script related variables should be initialized once! [Skotlex] + + memset (&script_config, 0, sizeof(script_config)); + script_config.verbose_mode = 0; + script_config.warn_func_no_comma = 1; + script_config.warn_cmd_no_comma = 1; + script_config.warn_func_mismatch_paramnum = 1; + script_config.warn_cmd_mismatch_paramnum = 1; + script_config.check_cmdcount = 65535; + script_config.check_gotocount = 2048; + + script_config.event_script_type = 0; + script_config.event_requires_trigger = 1; + + return script_config_read_sub(cfgName); +} + + +static int do_final_userfunc_sub (DBKey key,void *data,va_list ap){ + struct script_code *code = (struct script_code *)data; + if(code){ + script_free_vars( &code->script_vars ); + aFree( code->script_buf ); + } + return 0; +} + +/*========================================== + * 終了 + *------------------------------------------ + */ +int do_final_script() +{ + if(mapreg_dirty>=0) + script_save_mapreg(); + + mapreg_db->destroy(mapreg_db,NULL); + mapregstr_db->destroy(mapregstr_db,NULL); + scriptlabel_db->destroy(scriptlabel_db,NULL); + userfunc_db->destroy(userfunc_db,do_final_userfunc_sub); + if(sleep_db) { + struct linkdb_node *n = (struct linkdb_node *)sleep_db; + while(n) { + struct script_state *st = (struct script_state *)n->data; + script_free_stack(st->stack); + free(st); + n = n->next; + } + linkdb_final(&sleep_db); + } + + if (str_data) + aFree(str_data); + if (str_buf) + aFree(str_buf); + + return 0; +} +/*========================================== + * 初期化 + *------------------------------------------ + */ +int do_init_script() +{ + mapreg_db= db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); + mapregstr_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); + userfunc_db=db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_RELEASE_BOTH,50); + scriptlabel_db=db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_ALLOW_NULL_DATA,50); + + script_load_mapreg(); + + add_timer_func_list(script_autosave_mapreg,"script_autosave_mapreg"); + add_timer_interval(gettick()+MAPREG_AUTOSAVE_INTERVAL, + script_autosave_mapreg,0,0,MAPREG_AUTOSAVE_INTERVAL); + + return 0; +} + +int script_reload() +{ + if(mapreg_dirty>=0) + script_save_mapreg(); + + mapreg_db->clear(mapreg_db, NULL); + mapregstr_db->clear(mapregstr_db, NULL); + userfunc_db->clear(userfunc_db,do_final_userfunc_sub); + scriptlabel_db->clear(scriptlabel_db, NULL); + + if(sleep_db) { + struct linkdb_node *n = (struct linkdb_node *)sleep_db; + while(n) { + struct script_state *st = (struct script_state *)n->data; + script_free_stack(st->stack); + free(st); + n = n->next; + } + linkdb_final(&sleep_db); + } + + script_load_mapreg(); + return 0; +} + +int buildin_mes(struct script_state *st); +int buildin_goto(struct script_state *st); +int buildin_callsub(struct script_state *st); +int buildin_callfunc(struct script_state *st); +int buildin_return(struct script_state *st); +int buildin_getarg(struct script_state *st); +int buildin_next(struct script_state *st); +int buildin_close(struct script_state *st); +int buildin_close2(struct script_state *st); +int buildin_menu(struct script_state *st); +int buildin_rand(struct script_state *st); +int buildin_warp(struct script_state *st); +int buildin_areawarp(struct script_state *st); +int buildin_warpchar(struct script_state *st); // [LuzZza] +int buildin_warpparty(struct script_state *st); //[Fredzilla] +int buildin_warpguild(struct script_state *st); //[Fredzilla] +int buildin_heal(struct script_state *st); +int buildin_itemheal(struct script_state *st); +int buildin_percentheal(struct script_state *st); +int buildin_jobchange(struct script_state *st); +int buildin_input(struct script_state *st); +int buildin_setlook(struct script_state *st); +int buildin_set(struct script_state *st); +int buildin_setarray(struct script_state *st); +int buildin_cleararray(struct script_state *st); +int buildin_copyarray(struct script_state *st); +int buildin_getarraysize(struct script_state *st); +int buildin_deletearray(struct script_state *st); +int buildin_getelementofarray(struct script_state *st); +int buildin_getitem(struct script_state *st); +int buildin_getitem2(struct script_state *st); +int buildin_getnameditem(struct script_state *st); +int buildin_grouprandomitem(struct script_state *st); +int buildin_makeitem(struct script_state *st); +int buildin_delitem(struct script_state *st); +int buildin_delitem2(struct script_state *st); +int buildin_enableitemuse(struct script_state *st); +int buildin_disableitemuse(struct script_state *st); +int buildin_viewpoint(struct script_state *st); +int buildin_countitem(struct script_state *st); +int buildin_countitem2(struct script_state *st); +int buildin_checkweight(struct script_state *st); +int buildin_readparam(struct script_state *st); +int buildin_getcharid(struct script_state *st); +int buildin_getpartyname(struct script_state *st); +int buildin_getpartymember(struct script_state *st); +int buildin_getguildname(struct script_state *st); +int buildin_getguildmaster(struct script_state *st); +int buildin_getguildmasterid(struct script_state *st); +int buildin_strcharinfo(struct script_state *st); +int buildin_getequipid(struct script_state *st); +int buildin_getequipname(struct script_state *st); +int buildin_getbrokenid(struct script_state *st); // [Valaris] +int buildin_repair(struct script_state *st); // [Valaris] +int buildin_getequipisequiped(struct script_state *st); +int buildin_getequipisenableref(struct script_state *st); +int buildin_getequipisidentify(struct script_state *st); +int buildin_getequiprefinerycnt(struct script_state *st); +int buildin_getequipweaponlv(struct script_state *st); +int buildin_getequippercentrefinery(struct script_state *st); +int buildin_successrefitem(struct script_state *st); +int buildin_failedrefitem(struct script_state *st); +int buildin_cutin(struct script_state *st); +int buildin_cutincard(struct script_state *st); +int buildin_statusup(struct script_state *st); +int buildin_statusup2(struct script_state *st); +int buildin_bonus(struct script_state *st); +int buildin_bonus2(struct script_state *st); +int buildin_bonus3(struct script_state *st); +int buildin_bonus4(struct script_state *st); +int buildin_skill(struct script_state *st); +int buildin_addtoskill(struct script_state *st); // [Valaris] +int buildin_guildskill(struct script_state *st); +int buildin_getskilllv(struct script_state *st); +int buildin_getgdskilllv(struct script_state *st); +int buildin_basicskillcheck(struct script_state *st); +int buildin_getgmlevel(struct script_state *st); +int buildin_end(struct script_state *st); +int buildin_checkoption(struct script_state *st); +int buildin_setoption(struct script_state *st); +int buildin_setcart(struct script_state *st); +int buildin_checkcart(struct script_state *st); // check cart [Valaris] +int buildin_setfalcon(struct script_state *st); +int buildin_checkfalcon(struct script_state *st); // check falcon [Valaris] +int buildin_setriding(struct script_state *st); +int buildin_checkriding(struct script_state *st); // check for pecopeco [Valaris] +int buildin_savepoint(struct script_state *st); +int buildin_gettimetick(struct script_state *st); +int buildin_gettime(struct script_state *st); +int buildin_gettimestr(struct script_state *st); +int buildin_openstorage(struct script_state *st); +int buildin_guildopenstorage(struct script_state *st); +int buildin_itemskill(struct script_state *st); +int buildin_produce(struct script_state *st); +int buildin_monster(struct script_state *st); +int buildin_areamonster(struct script_state *st); +int buildin_killmonster(struct script_state *st); +int buildin_killmonsterall(struct script_state *st); +int buildin_clone(struct script_state *st); +int buildin_doevent(struct script_state *st); +int buildin_donpcevent(struct script_state *st); +int buildin_addtimer(struct script_state *st); +int buildin_deltimer(struct script_state *st); +int buildin_addtimercount(struct script_state *st); +int buildin_initnpctimer(struct script_state *st); +int buildin_stopnpctimer(struct script_state *st); +int buildin_startnpctimer(struct script_state *st); +int buildin_setnpctimer(struct script_state *st); +int buildin_getnpctimer(struct script_state *st); +int buildin_attachnpctimer(struct script_state *st); // [celest] +int buildin_detachnpctimer(struct script_state *st); // [celest] +int buildin_playerattached(struct script_state *st); // [Skotlex] +int buildin_announce(struct script_state *st); +int buildin_mapannounce(struct script_state *st); +int buildin_areaannounce(struct script_state *st); +int buildin_getusers(struct script_state *st); +int buildin_getmapusers(struct script_state *st); +int buildin_getareausers(struct script_state *st); +int buildin_getareadropitem(struct script_state *st); +int buildin_enablenpc(struct script_state *st); +int buildin_disablenpc(struct script_state *st); +int buildin_enablearena(struct script_state *st); // Added by RoVeRT +int buildin_disablearena(struct script_state *st); // Added by RoVeRT +int buildin_hideoffnpc(struct script_state *st); +int buildin_hideonnpc(struct script_state *st); +int buildin_sc_start(struct script_state *st); +int buildin_sc_start2(struct script_state *st); +int buildin_sc_start4(struct script_state *st); +int buildin_sc_end(struct script_state *st); +int buildin_getscrate(struct script_state *st); +int buildin_debugmes(struct script_state *st); +int buildin_catchpet(struct script_state *st); +int buildin_birthpet(struct script_state *st); +int buildin_resetlvl(struct script_state *st); +int buildin_resetstatus(struct script_state *st); +int buildin_resetskill(struct script_state *st); +int buildin_skillpointcount(struct script_state *st); +int buildin_changebase(struct script_state *st); +int buildin_changesex(struct script_state *st); +int buildin_waitingroom(struct script_state *st); +int buildin_delwaitingroom(struct script_state *st); +int buildin_enablewaitingroomevent(struct script_state *st); +int buildin_disablewaitingroomevent(struct script_state *st); +int buildin_getwaitingroomstate(struct script_state *st); +int buildin_warpwaitingpc(struct script_state *st); +int buildin_attachrid(struct script_state *st); +int buildin_detachrid(struct script_state *st); +int buildin_isloggedin(struct script_state *st); +int buildin_setmapflagnosave(struct script_state *st); +int buildin_setmapflag(struct script_state *st); +int buildin_removemapflag(struct script_state *st); +int buildin_pvpon(struct script_state *st); +int buildin_pvpoff(struct script_state *st); +int buildin_gvgon(struct script_state *st); +int buildin_gvgoff(struct script_state *st); +int buildin_emotion(struct script_state *st); +int buildin_maprespawnguildid(struct script_state *st); +int buildin_agitstart(struct script_state *st); // <Agit> +int buildin_agitend(struct script_state *st); +int buildin_agitcheck(struct script_state *st); // <Agitcheck> +int buildin_flagemblem(struct script_state *st); // Flag Emblem +int buildin_getcastlename(struct script_state *st); +int buildin_getcastledata(struct script_state *st); +int buildin_setcastledata(struct script_state *st); +int buildin_requestguildinfo(struct script_state *st); +int buildin_getequipcardcnt(struct script_state *st); +int buildin_successremovecards(struct script_state *st); +int buildin_failedremovecards(struct script_state *st); +int buildin_marriage(struct script_state *st); +int buildin_wedding_effect(struct script_state *st); +int buildin_divorce(struct script_state *st); +int buildin_ispartneron(struct script_state *st); // MouseJstr +int buildin_getpartnerid(struct script_state *st); // MouseJstr +int buildin_getchildid(struct script_state *st); // Skotlex +int buildin_getmotherid(struct script_state *st); // Lupus +int buildin_getfatherid(struct script_state *st); // Lupus +int buildin_warppartner(struct script_state *st); // MouseJstr +int buildin_getitemname(struct script_state *st); +int buildin_getitemslots(struct script_state *st); +int buildin_makepet(struct script_state *st); +int buildin_getexp(struct script_state *st); +int buildin_getinventorylist(struct script_state *st); +int buildin_getskilllist(struct script_state *st); +int buildin_clearitem(struct script_state *st); +int buildin_classchange(struct script_state *st); +int buildin_misceffect(struct script_state *st); +int buildin_soundeffect(struct script_state *st); +int buildin_soundeffectall(struct script_state *st); +int buildin_setcastledata(struct script_state *st); +int buildin_mapwarp(struct script_state *st); +int buildin_inittimer(struct script_state *st); +int buildin_stoptimer(struct script_state *st); +int buildin_cmdothernpc(struct script_state *st); +int buildin_mobcount(struct script_state *st); +int buildin_strmobinfo(struct script_state *st); // Script for displaying mob info [Valaris] +int buildin_guardian(struct script_state *st); // Script for displaying mob info [Valaris] +int buildin_guardianinfo(struct script_state *st); // Script for displaying mob info [Valaris] +int buildin_petskillbonus(struct script_state *st); // petskillbonus [Valaris] +int buildin_petrecovery(struct script_state *st); // pet skill for curing status [Valaris] +int buildin_petloot(struct script_state *st); // pet looting [Valaris] +int buildin_petheal(struct script_state *st); // pet healing [Valaris] +//int buildin_petmag(struct script_state *st); // pet magnificat [Valaris] +int buildin_petskillattack(struct script_state *st); // pet skill attacks [Skotlex] +int buildin_petskillattack2(struct script_state *st); // pet skill attacks [Skotlex] +int buildin_petskillsupport(struct script_state *st); // pet support skill [Valaris] +int buildin_skilleffect(struct script_state *st); // skill effects [Celest] +int buildin_npcskilleffect(struct script_state *st); // skill effects for npcs [Valaris] +int buildin_specialeffect(struct script_state *st); // special effect script [Valaris] +int buildin_specialeffect2(struct script_state *st); // special effect script [Valaris] +int buildin_nude(struct script_state *st); // nude [Valaris] +int buildin_atcommand(struct script_state *st); // [MouseJstr] +int buildin_charcommand(struct script_state *st); // [MouseJstr] +int buildin_movenpc(struct script_state *st); // [MouseJstr] +int buildin_message(struct script_state *st); // [MouseJstr] +int buildin_npctalk(struct script_state *st); // [Valaris] +int buildin_hasitems(struct script_state *st); // [Valaris] +int buildin_getlook(struct script_state *st); //Lorky [Lupus] +int buildin_getsavepoint(struct script_state *st); //Lorky [Lupus] +int buildin_npcspeed(struct script_state *st); // [Valaris] +int buildin_npcwalkto(struct script_state *st); // [Valaris] +int buildin_npcstop(struct script_state *st); // [Valaris] +int buildin_getmapxy(struct script_state *st); //get map position for player/npc/pet/mob by Lorky [Lupus] +int buildin_checkoption1(struct script_state *st); // [celest] +int buildin_checkoption2(struct script_state *st); // [celest] +int buildin_guildgetexp(struct script_state *st); // [celest] +int buildin_guildchangegm(struct script_state *st); // [Skotlex] +int buildin_logmes(struct script_state *st); // [Lupus] +int buildin_summon(struct script_state *st); // [celest] +int buildin_isnight(struct script_state *st); // [celest] +int buildin_isday(struct script_state *st); // [celest] +int buildin_isequipped(struct script_state *st); // [celest] +int buildin_isequippedcnt(struct script_state *st); // [celest] +int buildin_cardscnt(struct script_state *st); // [Lupus] +int buildin_getrefine(struct script_state *st); // [celest] +int buildin_adopt(struct script_state *st); +int buildin_night(struct script_state *st); +int buildin_day(struct script_state *st); +int buildin_getusersname(struct script_state *st); //jA commands added [Lupus] +int buildin_dispbottom(struct script_state *st); +int buildin_recovery(struct script_state *st); +int buildin_getpetinfo(struct script_state *st); +int buildin_checkequipedcard(struct script_state *st); +int buildin_globalmes(struct script_state *st); +int buildin_jump_zero(struct script_state *st); +int buildin_select(struct script_state *st); +int buildin_getmapmobs(struct script_state *st); //jA addition end +int buildin_unequip(struct script_state *st); // unequip [Spectre] +int buildin_getstrlen(struct script_state *st); //strlen [valaris] +int buildin_charisalpha(struct script_state *st);//isalpha [valaris] +int buildin_fakenpcname(struct script_state *st); // [Lance] +int buildin_compare(struct script_state *st); // Lordalfa, to bring strstr to Scripting Engine +int buildin_getiteminfo(struct script_state *st); //[Lupus] returns Items Buy / sell Price, etc info +int buildin_getequipcardid(struct script_state *st); //[Lupus] returns card id from quipped item card slot N +// [zBuffer] List of mathematics commands ---> +int buildin_sqrt(struct script_state *st); +int buildin_pow(struct script_state *st); +int buildin_distance(struct script_state *st); +int buildin_checkcell(struct script_state *st); +// <--- [zBuffer] List of mathematics commands +// [zBuffer] List of dynamic var commands ---> +int buildin_getd(struct script_state *st); +int buildin_setd(struct script_state *st); +// <--- [zBuffer] List of dynamic var commands +int buildin_petstat(struct script_state *st); // [Lance] Pet Stat Rq: Dubby +int buildin_callshop(struct script_state *st); // [Skotlex] +int buildin_npcshopitem(struct script_state *st); // [Lance] +int buildin_npcshopadditem(struct script_state *st); +int buildin_npcshopdelitem(struct script_state *st); +int buildin_equip(struct script_state *st); +int buildin_autoequip(struct script_state *st); +int buildin_setbattleflag(struct script_state *st); +int buildin_getbattleflag(struct script_state *st); +#ifndef TXT_ONLY +int buildin_query_sql(struct script_state *st); +int buildin_escape_sql(struct script_state *st); +#endif +int buildin_atoi(struct script_state *st); +int buildin_axtoi(struct script_state *st); +// [zBuffer] List of player cont commands ---> +int buildin_rid2name(struct script_state *st); +int buildin_pcfollow(struct script_state *st); +int buildin_pcstopfollow(struct script_state *st); +int buildin_pcblockmove(struct script_state *st); +// <--- [zBuffer] List of player cont commands +// [zBuffer] List of mob control commands ---> +int buildin_mobspawn(struct script_state *st); +int buildin_mobremove(struct script_state *st); +int buildin_getmobdata(struct script_state *st); +int buildin_setmobdata(struct script_state *st); +int buildin_mobassist(struct script_state *st); +int buildin_mobattach(struct script_state *st); +int buildin_unitwalk(struct script_state *st); +int buildin_unitkill(struct script_state *st); +int buildin_unitwarp(struct script_state *st); +int buildin_unitattack(struct script_state *st); +int buildin_unitstop(struct script_state *st); +int buildin_unittalk(struct script_state *st); +int buildin_unitemote(struct script_state *st); +int buildin_unitdeadsit(struct script_state *st); +int buildin_unitskilluseid(struct script_state *st); // originally by Qamera [celest] +int buildin_unitskillusepos(struct script_state *st); // originally by Qamera [celest] +// <--- [zBuffer] List of mob control commands +int buildin_sleep(struct script_state *st); +int buildin_sleep2(struct script_state *st); +int buildin_awake(struct script_state *st); +int buildin_getvariableofnpc(struct script_state *st); +// [blackhole89] --> +int buildin_warpportal(struct script_state *st); +// <-- [blackhole89] +int buildin_homunculus_evolution(struct script_state *st) ; //[orn] +int buildin_setitemscript(struct script_state *st); +int buildin_disguise(struct script_state *st); +int buildin_undisguise(struct script_state *st); +int buildin_getmonsterinfo(struct script_state *st); // [Lupus] + +#ifdef PCRE_SUPPORT +int buildin_defpattern(struct script_state *st); // MouseJstr +int buildin_activatepset(struct script_state *st); // MouseJstr +int buildin_deactivatepset(struct script_state *st); // MouseJstr +int buildin_deletepset(struct script_state *st); // MouseJstr +#endif + +struct script_function buildin_func[] = { + {buildin_mes,"mes","s"}, + {buildin_next,"next",""}, + {buildin_close,"close",""}, + {buildin_close2,"close2",""}, + {buildin_menu,"menu","*"}, + {buildin_goto,"goto","l"}, + {buildin_callsub,"callsub","i*"}, + {buildin_callfunc,"callfunc","s*"}, + {buildin_return,"return","*"}, + {buildin_getarg,"getarg","i"}, + {buildin_jobchange,"jobchange","i*"}, + {buildin_input,"input","*"}, + {buildin_warp,"warp","sii"}, + {buildin_areawarp,"areawarp","siiiisii"}, + {buildin_warpchar,"warpchar","siii"}, // [LuzZza] + {buildin_warpparty,"warpparty","siii"}, // [Fredzilla] + {buildin_warpguild,"warpguild","siii"}, // [Fredzilla] + {buildin_setlook,"setlook","ii"}, + {buildin_set,"set","ii"}, + {buildin_setarray,"setarray","ii*"}, + {buildin_cleararray,"cleararray","iii"}, + {buildin_copyarray,"copyarray","iii"}, + {buildin_getarraysize,"getarraysize","i"}, + {buildin_deletearray,"deletearray","ii"}, + {buildin_getelementofarray,"getelementofarray","ii"}, + {buildin_getitem,"getitem","ii**"}, + {buildin_getitem2,"getitem2","iiiiiiiii*"}, + {buildin_getnameditem,"getnameditem","is"}, + {buildin_grouprandomitem,"groupranditem","i"}, + {buildin_makeitem,"makeitem","iisii"}, + {buildin_delitem,"delitem","ii"}, + {buildin_delitem2,"delitem2","iiiiiiiii"}, + {buildin_enableitemuse,"enable_items",""}, + {buildin_disableitemuse,"disable_items",""}, + {buildin_cutin,"cutin","si"}, + {buildin_cutincard,"cutincard","i"}, + {buildin_viewpoint,"viewpoint","iiiii"}, + {buildin_heal,"heal","ii"}, + {buildin_itemheal,"itemheal","ii"}, + {buildin_percentheal,"percentheal","ii"}, + {buildin_rand,"rand","i*"}, + {buildin_countitem,"countitem","i"}, + {buildin_countitem2,"countitem2","iiiiiiii"}, + {buildin_checkweight,"checkweight","ii"}, + {buildin_readparam,"readparam","i*"}, + {buildin_getcharid,"getcharid","i*"}, + {buildin_getpartyname,"getpartyname","i"}, + {buildin_getpartymember,"getpartymember","i*"}, + {buildin_getguildname,"getguildname","i"}, + {buildin_getguildmaster,"getguildmaster","i"}, + {buildin_getguildmasterid,"getguildmasterid","i"}, + {buildin_strcharinfo,"strcharinfo","i"}, + {buildin_getequipid,"getequipid","i"}, + {buildin_getequipname,"getequipname","i"}, + {buildin_getbrokenid,"getbrokenid","i"}, // [Valaris] + {buildin_repair,"repair","i"}, // [Valaris] + {buildin_getequipisequiped,"getequipisequiped","i"}, + {buildin_getequipisenableref,"getequipisenableref","i"}, + {buildin_getequipisidentify,"getequipisidentify","i"}, + {buildin_getequiprefinerycnt,"getequiprefinerycnt","i"}, + {buildin_getequipweaponlv,"getequipweaponlv","i"}, + {buildin_getequippercentrefinery,"getequippercentrefinery","i"}, + {buildin_successrefitem,"successrefitem","i"}, + {buildin_failedrefitem,"failedrefitem","i"}, + {buildin_statusup,"statusup","i"}, + {buildin_statusup2,"statusup2","ii"}, + {buildin_bonus,"bonus","ii"}, + {buildin_bonus2,"bonus2","iii"}, + {buildin_bonus3,"bonus3","iiii"}, + {buildin_bonus4,"bonus4","iiiii"}, + {buildin_skill,"skill","ii*"}, + {buildin_addtoskill,"addtoskill","ii*"}, // [Valaris] + {buildin_guildskill,"guildskill","ii"}, + {buildin_getskilllv,"getskilllv","i"}, + {buildin_getgdskilllv,"getgdskilllv","ii"}, + {buildin_basicskillcheck,"basicskillcheck","*"}, + {buildin_getgmlevel,"getgmlevel","*"}, + {buildin_end,"end",""}, +// {buildin_end,"break",""}, this might confuse advanced scripting support [Eoe] + {buildin_checkoption,"checkoption","i"}, + {buildin_setoption,"setoption","i*"}, + {buildin_setcart,"setcart",""}, + {buildin_checkcart,"checkcart","*"}, //fixed by Lupus (added '*') + {buildin_setfalcon,"setfalcon",""}, + {buildin_checkfalcon,"checkfalcon","*"}, //fixed by Lupus (fixed wrong pointer, added '*') + {buildin_setriding,"setriding",""}, + {buildin_checkriding,"checkriding","*"}, //fixed by Lupus (fixed wrong pointer, added '*') + {buildin_savepoint,"save","sii"}, + {buildin_savepoint,"savepoint","sii"}, + {buildin_gettimetick,"gettimetick","i"}, + {buildin_gettime,"gettime","i"}, + {buildin_gettimestr,"gettimestr","si"}, + {buildin_openstorage,"openstorage",""}, + {buildin_guildopenstorage,"guildopenstorage","*"}, + {buildin_itemskill,"itemskill","iis"}, + {buildin_produce,"produce","i"}, + {buildin_monster,"monster","siisii*"}, + {buildin_areamonster,"areamonster","siiiisii*"}, + {buildin_killmonster,"killmonster","ss"}, + {buildin_killmonsterall,"killmonsterall","s"}, + {buildin_clone,"clone","siisi*"}, + {buildin_doevent,"doevent","s"}, + {buildin_donpcevent,"donpcevent","s"}, + {buildin_addtimer,"addtimer","is"}, + {buildin_deltimer,"deltimer","s"}, + {buildin_addtimercount,"addtimercount","si"}, + {buildin_initnpctimer,"initnpctimer","*"}, + {buildin_stopnpctimer,"stopnpctimer","*"}, + {buildin_startnpctimer,"startnpctimer","*"}, + {buildin_setnpctimer,"setnpctimer","*"}, + {buildin_getnpctimer,"getnpctimer","i*"}, + {buildin_attachnpctimer,"attachnpctimer","*"}, // attached the player id to the npc timer [Celest] + {buildin_detachnpctimer,"detachnpctimer","*"}, // detached the player id from the npc timer [Celest] + {buildin_playerattached,"playerattached",""}, // returns id of the current attached player. [Skotlex] + {buildin_announce,"announce","si*"}, + {buildin_mapannounce,"mapannounce","ssi*"}, + {buildin_areaannounce,"areaannounce","siiiisi*"}, + {buildin_getusers,"getusers","i"}, + {buildin_getmapusers,"getmapusers","s"}, + {buildin_getareausers,"getareausers","siiii"}, + {buildin_getareadropitem,"getareadropitem","siiiii"}, + {buildin_enablenpc,"enablenpc","s"}, + {buildin_disablenpc,"disablenpc","s"}, + {buildin_enablearena,"enablearena",""}, // Added by RoVeRT + {buildin_disablearena,"disablearena",""}, // Added by RoVeRT + {buildin_hideoffnpc,"hideoffnpc","s"}, + {buildin_hideonnpc,"hideonnpc","s"}, + {buildin_sc_start,"sc_start","iii*"}, + {buildin_sc_start2,"sc_start2","iiii*"}, + {buildin_sc_start4,"sc_start4","iiiiii*"}, + {buildin_sc_end,"sc_end","i"}, + {buildin_getscrate,"getscrate","ii*"}, + {buildin_debugmes,"debugmes","s"}, + {buildin_catchpet,"pet","i"}, + {buildin_birthpet,"bpet",""}, + {buildin_resetlvl,"resetlvl","i"}, + {buildin_resetstatus,"resetstatus",""}, + {buildin_resetskill,"resetskill",""}, + {buildin_skillpointcount,"skillpointcount",""}, + {buildin_changebase,"changebase","i"}, + {buildin_changesex,"changesex",""}, + {buildin_waitingroom,"waitingroom","si*"}, + {buildin_warpwaitingpc,"warpwaitingpc","sii"}, + {buildin_delwaitingroom,"delwaitingroom","*"}, + {buildin_enablewaitingroomevent,"enablewaitingroomevent","*"}, + {buildin_disablewaitingroomevent,"disablewaitingroomevent","*"}, + {buildin_getwaitingroomstate,"getwaitingroomstate","i*"}, + {buildin_warpwaitingpc,"warpwaitingpc","sii*"}, + {buildin_attachrid,"attachrid","i"}, + {buildin_detachrid,"detachrid",""}, + {buildin_isloggedin,"isloggedin","i"}, + {buildin_setmapflagnosave,"setmapflagnosave","ssii"}, + {buildin_setmapflag,"setmapflag","si*"}, + {buildin_removemapflag,"removemapflag","si"}, + {buildin_pvpon,"pvpon","s"}, + {buildin_pvpoff,"pvpoff","s"}, + {buildin_gvgon,"gvgon","s"}, + {buildin_gvgoff,"gvgoff","s"}, + {buildin_emotion,"emotion","i*"}, + {buildin_maprespawnguildid,"maprespawnguildid","sii"}, + {buildin_agitstart,"agitstart",""}, // <Agit> + {buildin_agitend,"agitend",""}, + {buildin_agitcheck,"agitcheck","i"}, // <Agitcheck> + {buildin_flagemblem,"flagemblem","i"}, // Flag Emblem + {buildin_getcastlename,"getcastlename","s"}, + {buildin_getcastledata,"getcastledata","si*"}, + {buildin_setcastledata,"setcastledata","sii"}, + {buildin_requestguildinfo,"requestguildinfo","i*"}, + {buildin_getequipcardcnt,"getequipcardcnt","i"}, + {buildin_successremovecards,"successremovecards","i"}, + {buildin_failedremovecards,"failedremovecards","ii"}, + {buildin_marriage,"marriage","s"}, + {buildin_wedding_effect,"wedding",""}, + {buildin_divorce,"divorce",""}, + {buildin_ispartneron,"ispartneron",""}, + {buildin_getpartnerid,"getpartnerid",""}, + {buildin_getchildid,"getchildid",""}, + {buildin_getmotherid,"getmotherid",""}, + {buildin_getfatherid,"getfatherid",""}, + {buildin_warppartner,"warppartner","sii"}, + {buildin_getitemname,"getitemname","i"}, + {buildin_getitemslots,"getitemslots","i"}, + {buildin_makepet,"makepet","i"}, + {buildin_getexp,"getexp","ii"}, + {buildin_getinventorylist,"getinventorylist",""}, + {buildin_getskilllist,"getskilllist",""}, + {buildin_clearitem,"clearitem",""}, + {buildin_classchange,"classchange","ii"}, + {buildin_misceffect,"misceffect","i"}, + {buildin_soundeffect,"soundeffect","si"}, + {buildin_soundeffectall,"soundeffectall","si*"}, // SoundEffectAll [Codemaster] + {buildin_strmobinfo,"strmobinfo","ii"}, // display mob data [Valaris] + {buildin_guardian,"guardian","siisii*i"}, // summon guardians + {buildin_guardianinfo,"guardianinfo","i"}, // display guardian data [Valaris] + {buildin_petskillbonus,"petskillbonus","iiii"}, // [Valaris] + {buildin_petrecovery,"petrecovery","ii"}, // [Valaris] + {buildin_petloot,"petloot","i"}, // [Valaris] + {buildin_petheal,"petheal","iiii"}, // [Valaris] +// {buildin_petmag,"petmag","iiii"}, // [Valaris] + {buildin_petskillattack,"petskillattack","iiii"}, // [Skotlex] + {buildin_petskillattack2,"petskillattack2","iiiii"}, // [Valaris] + {buildin_petskillsupport,"petskillsupport","iiiii"}, // [Skotlex] + {buildin_skilleffect,"skilleffect","ii"}, // skill effect [Celest] + {buildin_npcskilleffect,"npcskilleffect","iiii"}, // npc skill effect [Valaris] + {buildin_specialeffect,"specialeffect","i*"}, // npc skill effect [Valaris] + {buildin_specialeffect2,"specialeffect2","i*"}, // skill effect on players[Valaris] + {buildin_nude,"nude",""}, // nude command [Valaris] + {buildin_mapwarp,"mapwarp","ssii"}, // Added by RoVeRT + {buildin_inittimer,"inittimer",""}, + {buildin_stoptimer,"stoptimer",""}, + {buildin_cmdothernpc,"cmdothernpc","ss"}, + {buildin_atcommand,"atcommand","*"}, // [MouseJstr] + {buildin_charcommand,"charcommand","*"}, // [MouseJstr] + {buildin_movenpc,"movenpc","sii"}, // [MouseJstr] + {buildin_message,"message","s*"}, // [MouseJstr] + {buildin_npctalk,"npctalk","*"}, // [Valaris] + {buildin_hasitems,"hasitems","*"}, // [Valaris] + {buildin_mobcount,"mobcount","ss"}, + {buildin_getlook,"getlook","i"}, + {buildin_getsavepoint,"getsavepoint","i"}, + {buildin_npcspeed,"npcspeed","i"}, // [Valaris] + {buildin_npcwalkto,"npcwalkto","ii"}, // [Valaris] + {buildin_npcstop,"npcstop",""}, // [Valaris] + {buildin_getmapxy,"getmapxy","siii*"}, //by Lorky [Lupus] + {buildin_checkoption1,"checkoption1","i"}, + {buildin_checkoption2,"checkoption2","i"}, + {buildin_guildgetexp,"guildgetexp","i"}, + {buildin_guildchangegm,"guildchangegm","is"}, + {buildin_logmes,"logmes","s"}, //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] + {buildin_summon,"summon","si*"}, // summons a slave monster [Celest] + {buildin_isnight,"isnight",""}, // check whether it is night time [Celest] + {buildin_isday,"isday",""}, // check whether it is day time [Celest] + {buildin_isequipped,"isequipped","i*"}, // check whether another item/card has been equipped [Celest] + {buildin_isequippedcnt,"isequippedcnt","i*"}, // check how many items/cards are being equipped [Celest] + {buildin_cardscnt,"cardscnt","i*"}, // check how many items/cards are being equipped in the same arm [Lupus] + {buildin_getrefine,"getrefine","*"}, // returns the refined number of the current item, or an item with index specified [celest] + {buildin_adopt,"adopt","sss"}, // allows 2 parents to adopt a child + {buildin_night,"night",""}, // sets the server to night time + {buildin_day,"day",""}, // sets the server to day time +#ifdef PCRE_SUPPORT + {buildin_defpattern, "defpattern", "iss"}, // Define pattern to listen for [MouseJstr] + {buildin_activatepset, "activatepset", "i"}, // Activate a pattern set [MouseJstr] + {buildin_deactivatepset, "deactivatepset", "i"}, // Deactive a pattern set [MouseJstr] + {buildin_deletepset, "deletepset", "i"}, // Delete a pattern set [MouseJstr] +#endif + {buildin_dispbottom,"dispbottom","s"}, //added from jA [Lupus] + {buildin_getusersname,"getusersname","*"}, + {buildin_recovery,"recovery",""}, + {buildin_getpetinfo,"getpetinfo","i"}, + {buildin_checkequipedcard,"checkequipedcard","i"}, + {buildin_jump_zero,"jump_zero","ii"}, //for future jA script compatibility + {buildin_select,"select","*"}, //for future jA script compatibility + {buildin_globalmes,"globalmes","s*"}, + {buildin_getmapmobs,"getmapmobs","s"}, //end jA addition + {buildin_unequip,"unequip","i"}, // unequip command [Spectre] + {buildin_getstrlen,"getstrlen","s"}, //strlen [Valaris] + {buildin_charisalpha,"charisalpha","si"}, //isalpha [Valaris] + {buildin_fakenpcname,"fakenpcname","ssi"}, // [Lance] + {buildin_compare,"compare","ss"}, // Lordalfa - To bring strstr to scripting Engine. + {buildin_getiteminfo,"getiteminfo","ii"}, //[Lupus] returns Items Buy / sell Price, etc info + {buildin_getequipcardid,"getequipcardid","ii"}, //[Lupus] returns CARD ID or other info from CARD slot N of equipped item + // [zBuffer] List of mathematics commands ---> + {buildin_sqrt,"sqrt","i"}, + {buildin_pow,"pow","ii"}, + {buildin_distance,"distance","iiii"}, + {buildin_checkcell,"checkcell","siii"}, + // <--- [zBuffer] List of mathematics commands + // [zBuffer] List of dynamic var commands ---> + {buildin_getd,"getd","*"}, + {buildin_setd,"setd","*"}, + // <--- [zBuffer] List of dynamic var commands + {buildin_petstat,"petstat","i"}, + {buildin_callshop,"callshop","si"}, // [Skotlex] + {buildin_npcshopitem,"npcshopitem","sii*"}, // [Lance] + {buildin_npcshopadditem,"npcshopadditem","sii*"}, + {buildin_npcshopdelitem,"npcshopdelitem","si*"}, + {buildin_equip,"equip","i"}, + {buildin_autoequip,"autoequip","ii"}, + {buildin_setbattleflag,"setbattleflag","ss"}, + {buildin_getbattleflag,"getbattleflag","s"}, + {buildin_setitemscript,"setitemscript","is"}, //Set NEW item bonus script. Lupus + {buildin_disguise,"disguise","i"}, //disguise player. Lupus + {buildin_undisguise,"undisguise","i"}, //undisguise player. Lupus + {buildin_getmonsterinfo,"getmonsterinfo","ii"}, //Lupus + {buildin_axtoi,"axtoi","s"}, +#ifndef TXT_ONLY + {buildin_query_sql, "query_sql", "s*"}, + {buildin_escape_sql, "escape_sql", "s"}, +#endif + {buildin_atoi,"atoi","s"}, + // [zBuffer] List of player cont commands ---> + {buildin_rid2name,"rid2name","i"}, + {buildin_pcfollow,"pcfollow","ii"}, + {buildin_pcstopfollow,"pcstopfollow","i"}, + {buildin_pcblockmove,"pcblockmove","ii"}, + // <--- [zBuffer] List of player cont commands + // [zBuffer] List of mob control commands ---> + {buildin_mobspawn,"mobspawn","*"}, + {buildin_mobremove,"mobremove","i"}, + {buildin_getmobdata,"getmobdata","i*"}, + {buildin_setmobdata,"setmobdata","iii"}, + {buildin_mobassist,"mobassist","i*"}, + {buildin_mobattach,"mobattach","i*"}, + {buildin_unitwalk,"unitwalk","i*"}, + {buildin_unitkill,"unitkill","i"}, + {buildin_unitwarp,"unitwarp","isii"}, + {buildin_unitattack,"unitattack","i*"}, + {buildin_unitstop,"unitstop","i"}, + {buildin_unittalk,"unittalk","is"}, + {buildin_unitemote,"unitemote","ii"}, + {buildin_unitdeadsit,"unitdeadsit","ii"}, + {buildin_unitskilluseid,"unitskilluseid","iii*"}, // originally by Qamera [Celest] + {buildin_unitskillusepos,"unitskillusepos","iiiii"}, // [Celest] +// <--- [zBuffer] List of mob control commands + {buildin_sleep,"sleep","i"}, + {buildin_sleep2,"sleep2","i"}, + {buildin_awake,"awake","s"}, + {buildin_getvariableofnpc,"getvariableofnpc","is"}, + // [blackhole89] --> + {buildin_warpportal,"warpportal","iisii"}, + // <--- [blackhole89] + {buildin_homunculus_evolution,"homevolution",""}, //[orn] + {NULL,NULL,NULL}, +}; + /*========================================== * *------------------------------------------ @@ -2766,16 +3969,15 @@ int buildin_goto(struct script_state *st) { int pos; - if (st->stack->stack_data[st->start+2].type != C_POS){ - int func = st->stack->stack_data[st->start+2].u.num; - ShowMessage("script: goto '"CL_WHITE"%s"CL_RESET"': not label!\n", str_buf + str_data[func].str); - st->state = END; + if( st->stack->stack_data[st->start+2].type!=C_POS){ + ShowMessage("script: goto: not label!\n"); + st->state=END; return 1; } - pos = conv_num(st,& (st->stack->stack_data[st->start+2])); - st->pos = pos; - st->state = GOTO; + pos=conv_num(st,& (st->stack->stack_data[st->start+2])); + st->pos=pos; + st->state=GOTO; return 0; } @@ -2788,7 +3990,7 @@ int buildin_callfunc(struct script_state *st) struct script_code *scr, *oldscr; char *str=conv_str(st,& (st->stack->stack_data[st->start+2])); - if( (scr=(struct script_code *) strdb_get(userfunc_db,(unsigned char*)str)) ){ + if( (scr=strdb_get(userfunc_db,(unsigned char*)str)) ){ int i,j; struct linkdb_node **oldval = st->stack->var_function; for(i=st->start+3,j=0;i<st->end;i++,j++) @@ -2841,6 +4043,7 @@ int buildin_callsub(struct script_state *st) return 1; } else { struct linkdb_node **oldval = st->stack->var_function; + for(i=st->start+3,j=0;i<st->end;i++,j++) push_copy(st->stack,i); @@ -2956,22 +4159,31 @@ int buildin_menu(struct script_state *st) { char *buf; int len,i; - struct map_session_data *sd; + struct map_session_data *sd = script_rid2sd(st); - sd=script_rid2sd(st); + nullpo_retr(0, sd); if(sd->state.menu_or_input==0){ st->state=RERUNLINE; sd->state.menu_or_input=1; - for(i=st->start+2,len=16;i<st->end;i+=2){ + if( (st->end - st->start - 2) % 2 == 1 ) { + // 引数の数が奇数なのでエラー扱い + ShowError("buildin_menu: illigal argument count(%d).\n", st->end - st->start - 2); + sd->state.menu_or_input=0; + st->state=END; + return 1; + } + for(i=st->start+2,len=0;i<st->end;i+=2){ conv_str(st,& (st->stack->stack_data[i])); len+=(int)strlen(st->stack->stack_data[i].u.str)+1; } buf=(char *)aMallocA((len+1)*sizeof(char)); buf[0]=0; for(i=st->start+2,len=0;i<st->end;i+=2){ - strcat(buf,st->stack->stack_data[i].u.str); - strcat(buf,":"); + if( st->stack->stack_data[i].u.str[0] ) { + strcat(buf,st->stack->stack_data[i].u.str); + strcat(buf,":"); + } } clif_scriptmenu(script_rid2sd(st),st->oid,buf); aFree(buf); @@ -2982,8 +4194,7 @@ int buildin_menu(struct script_state *st) sd->state.menu_or_input=0; if(sd->npc_menu>0){ //Skip empty menu entries which weren't displayed on the client (blackhole89) - for(i=st->start+2;i<=(st->start+sd->npc_menu*2) && sd->npc_menu<(st->end-st->start)/2;i+=2) - { + for(i=st->start+2;i<=(st->start+sd->npc_menu*2) && sd->npc_menu<(st->end-st->start)/2;i+=2) { conv_str(st,& (st->stack->stack_data[i])); // we should convert variables to strings before access it [jA1983] [EoE] if((int)strlen(st->stack->stack_data[i].u.str) < 1) sd->npc_menu++; //Empty selection which wasn't displayed on the client. @@ -2999,7 +4210,7 @@ int buildin_menu(struct script_state *st) return 1; } pc_setreg(sd,add_str((unsigned char *) "@menu"),sd->npc_menu); - st->pos= conv_num(st,& (st->stack->stack_data[st->start+sd->npc_menu*2+1])); + st->pos=conv_num(st,& (st->stack->stack_data[st->start+sd->npc_menu*2+1])); st->state=GOTO; } } @@ -3012,17 +4223,16 @@ int buildin_menu(struct script_state *st) */ int buildin_rand(struct script_state *st) { - int range; + int range,min,max; if (st->end > st->start+3){ - int min, max; min = conv_num(st,& (st->stack->stack_data[st->start+2])); max = conv_num(st,& (st->stack->stack_data[st->start+3])); if (max == min){ //Why would someone do this? push_val(st->stack,C_INT,min); return 0; } - if (max < min){ + if(max<min){ int tmp = min; min = max; max = tmp; @@ -3048,6 +4258,8 @@ int buildin_warp(struct script_state *st) char *str; struct map_session_data *sd=script_rid2sd(st); + nullpo_retr(0, sd); + str=conv_str(st,& (st->stack->stack_data[st->start+2])); x=conv_num(st,& (st->stack->stack_data[st->start+3])); y=conv_num(st,& (st->stack->stack_data[st->start+4])); @@ -3411,13 +4623,13 @@ int buildin_jobchange(struct script_state *st) */ int buildin_input(struct script_state *st) { - struct map_session_data *sd=NULL; - int num=(st->end>st->start+2)?st->stack->stack_data[st->start+2].u.num:0; - char *name=(char *) ((st->end>st->start+2)?str_buf+str_data[num&0x00ffffff].str:""); -// char prefix=*name; + struct map_session_data *sd = script_rid2sd(st); + int num = (st->end>st->start+2)? st->stack->stack_data[st->start+2].u.num: 0; + char *name = (st->end>st->start+2)? str_buf+str_data[num&0x00ffffff].str: ""; char postfix=name[strlen(name)-1]; - sd=script_rid2sd(st); + nullpo_retr(0, sd); + if(sd->state.menu_or_input){ sd->state.menu_or_input=0; if( postfix=='$' ){ @@ -3479,7 +4691,6 @@ int buildin_set(struct script_state *st) if(not_server_variable(prefix)) sd=script_rid2sd(st); - if( postfix=='$' ){ // 文字列 char *str = conv_str(st,& (st->stack->stack_data[st->start+3])); @@ -3492,6 +4703,7 @@ int buildin_set(struct script_state *st) return 0; } + /*========================================== * 配列変数設定 *------------------------------------------ @@ -6905,13 +8117,6 @@ int buildin_isloggedin(struct script_state *st) * *------------------------------------------ */ -enum { MF_NOMEMO,MF_NOTELEPORT,MF_NOSAVE,MF_NOBRANCH,MF_NOPENALTY,MF_NOZENYPENALTY, - MF_PVP,MF_PVP_NOPARTY,MF_PVP_NOGUILD,MF_GVG,MF_GVG_NOPARTY,MF_NOTRADE,MF_NOSKILL, - MF_NOWARP,MF_FREE,MF_NOICEWALL,MF_SNOW,MF_FOG,MF_SAKURA,MF_LEAVES,MF_RAIN, - MF_INDOORS,MF_NOGO,MF_CLOUDS,MF_CLOUDS2,MF_FIREWORKS,MF_GVG_CASTLE,MF_GVG_DUNGEON,MF_NIGHTENABLED, - MF_NOBASEEXP, MF_NOJOBEXP, MF_NOMOBLOOT, MF_NOMVPLOOT, MF_NORETURN, MF_NOWARPTO, MF_NIGHTMAREDROP, - MF_RESTRICTED, MF_NOCOMMAND, MF_NODROP, MF_JEXP, MF_BEXP, MF_NOVENDING, MF_LOADEVENT, MF_NOCHAT }; - int buildin_setmapflagnosave(struct script_state *st) { int m,x,y; @@ -10275,7 +11480,7 @@ int buildin_setitemscript(struct script_state *st) if (i_data && script!=NULL && script[0]=='{') { if(i_data->script!=NULL) script_free_code(i_data->script); - i_data->script = parse_script((unsigned char *) script, 0); + i_data->script = parse_script((unsigned char *) script, "script_setitemscript", 0); push_val(st->stack,C_INT,1); } else push_val(st->stack,C_INT,0); @@ -10399,6 +11604,47 @@ int buildin_getmonsterinfo(struct script_state *st) return 0; } +int axtoi(char *hexStg) { + int n = 0; // position in string + int m = 0; // position in digit[] to shift + int count; // loop index + int intValue = 0; // integer value of hex string + int digit[11]; // hold values to convert + while (n < 10) { + if (hexStg[n]=='\0') + break; + if (hexStg[n] > 0x29 && hexStg[n] < 0x40 ) //if 0 to 9 + digit[n] = hexStg[n] & 0x0f; //convert to int + else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f + digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int + else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F + digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int + else break; + n++; + } + count = n; + m = n - 1; + n = 0; + while(n < count) { + // digit[n] is value of hex digit at position n + // (m << 2) is the number of positions to shift + // OR the bits into return value + intValue = intValue | (digit[n] << (m << 2)); + m--; // adjust the position to set + n++; // next digit to process + } + return (intValue); +} + +// [Lance] Hex string to integer converter +int buildin_axtoi(struct script_state *st) +{ + char *hex = conv_str(st,& (st->stack->stack_data[st->start+2])); + push_val(st->stack, C_INT, axtoi(hex)); + return 0; +} + + // [zBuffer] List of player cont commands ---> int buildin_rid2name(struct script_state *st){ struct block_list *bl = NULL; @@ -11078,1206 +12324,3 @@ int buildin_warpportal(struct script_state *st){ // <-- [blackhole89] -// -// 実行部main -// -/*========================================== - * コマンドの読み取り - *------------------------------------------ - */ -static int unget_com_data=-1; -int get_com(unsigned char *script,int *pos) -{ - int i,j; - if(unget_com_data>=0){ - i=unget_com_data; - unget_com_data=-1; - return i; - } - if(script[*pos]>=0x80){ - return C_INT; - } - i=0; j=0; - while(script[*pos]>=0x40){ - i=script[(*pos)++]<<j; - j+=6; - } - return i+(script[(*pos)++]<<j); -} - -/*========================================== - * コマンドのプッシュバック - *------------------------------------------ - */ -void unget_com(int c) -{ - if(unget_com_data!=-1){ - if(battle_config.error_log) - ShowError("unget_com can back only 1 data\n"); - } - unget_com_data=c; -} - -/*========================================== - * 数値の所得 - *------------------------------------------ - */ -int get_num(unsigned char *script,int *pos) -{ - int i,j; - i=0; j=0; - while(script[*pos]>=0xc0){ - i+=(script[(*pos)++]&0x7f)<<j; - j+=6; - } - return i+((script[(*pos)++]&0x7f)<<j); -} - -/*========================================== - * スタックから値を取り出す - *------------------------------------------ - */ -int pop_val(struct script_state* st) -{ - if(st->stack->sp<=0) - return 0; - st->stack->sp--; - get_val(st,&(st->stack->stack_data[st->stack->sp])); - if(st->stack->stack_data[st->stack->sp].type==C_INT) - return st->stack->stack_data[st->stack->sp].u.num; - return 0; -} - -#define isstr(c) ((c).type==C_STR || (c).type==C_CONSTSTR) - -/*========================================== - * 加算演算子 - *------------------------------------------ - */ -void op_add(struct script_state* st) -{ - st->stack->sp--; - get_val(st,&(st->stack->stack_data[st->stack->sp])); - get_val(st,&(st->stack->stack_data[st->stack->sp-1])); - - if(isstr(st->stack->stack_data[st->stack->sp]) || isstr(st->stack->stack_data[st->stack->sp-1])){ - conv_str(st,&(st->stack->stack_data[st->stack->sp])); - conv_str(st,&(st->stack->stack_data[st->stack->sp-1])); - } - if(st->stack->stack_data[st->stack->sp].type==C_INT){ // ii - st->stack->stack_data[st->stack->sp-1].u.num += st->stack->stack_data[st->stack->sp].u.num; - } else { // ssの予定 - char *buf; - buf=(char *)aMallocA((strlen(st->stack->stack_data[st->stack->sp-1].u.str)+ - strlen(st->stack->stack_data[st->stack->sp].u.str)+1)*sizeof(char)); - strcpy(buf,st->stack->stack_data[st->stack->sp-1].u.str); - strcat(buf,st->stack->stack_data[st->stack->sp].u.str); - if(st->stack->stack_data[st->stack->sp-1].type==C_STR) - { - aFree(st->stack->stack_data[st->stack->sp-1].u.str); - st->stack->stack_data[st->stack->sp-1].type=C_INT; - } - if(st->stack->stack_data[st->stack->sp].type==C_STR) - { - aFree(st->stack->stack_data[st->stack->sp].u.str); - st->stack->stack_data[st->stack->sp].type=C_INT; - } - st->stack->stack_data[st->stack->sp-1].type=C_STR; - st->stack->stack_data[st->stack->sp-1].u.str=buf; - } -} - -/*========================================== - * 二項演算子(文字列) - *------------------------------------------ - */ -void op_2str(struct script_state *st,int op,int sp1,int sp2) -{ - char *s1=st->stack->stack_data[sp1].u.str, - *s2=st->stack->stack_data[sp2].u.str; - int a=0; - - switch(op){ - case C_EQ: - a= (strcmp(s1,s2)==0); - break; - case C_NE: - a= (strcmp(s1,s2)!=0); - break; - case C_GT: - a= (strcmp(s1,s2)> 0); - break; - case C_GE: - a= (strcmp(s1,s2)>=0); - break; - case C_LT: - a= (strcmp(s1,s2)< 0); - break; - case C_LE: - a= (strcmp(s1,s2)<=0); - break; - default: - ShowWarning("script: illegal string operator\n"); - break; - } - - // Because push_val() overwrite stack_data[sp1], C_STR on stack_data[sp1] won't be freed. - // So, call push_val() after freeing strings. [jA1783] - // push_val(st->stack,C_INT,a); - if(st->stack->stack_data[sp1].type==C_STR) - { - aFree(s1); - st->stack->stack_data[sp1].type=C_INT; - } - if(st->stack->stack_data[sp2].type==C_STR) - { - aFree(s2); - st->stack->stack_data[sp2].type=C_INT; - } - push_val(st->stack,C_INT,a); -} -/*========================================== - * 二項演算子(数値) - *------------------------------------------ - */ -void op_2num(struct script_state *st,int op,int i1,int i2) -{ - switch(op){ - case C_SUB: - i1-=i2; - break; - case C_MUL: - { - #ifndef _MSC_VER - long long res = i1 * i2; - #else - __int64 res = i1 * i2; - #endif - if (res > 2147483647 ) - i1 = 2147483647; - else - i1*=i2; - } - break; - case C_DIV: - if (i2 != 0) - i1/=i2; - else - ShowWarning("op_2num: Attempted to divide by 0 in a script (operation C_DIV)!\n"); - break; - case C_MOD: - if (i2 != 0) - i1%=i2; - else - ShowWarning("op_2num: Attempted to divide by 0 in a script (operation C_MOD)!\n"); - break; - case C_AND: - i1&=i2; - break; - case C_OR: - i1|=i2; - break; - case C_XOR: - i1^=i2; - break; - case C_LAND: - i1=i1&&i2; - break; - case C_LOR: - i1=i1||i2; - break; - case C_EQ: - i1=i1==i2; - break; - case C_NE: - i1=i1!=i2; - break; - case C_GT: - i1=i1>i2; - break; - case C_GE: - i1=i1>=i2; - break; - case C_LT: - i1=i1<i2; - break; - case C_LE: - i1=i1<=i2; - break; - case C_R_SHIFT: - i1=i1>>i2; - break; - case C_L_SHIFT: - i1=i1<<i2; - break; - } - push_val(st->stack,C_INT,i1); -} -/*========================================== - * 二項演算子 - *------------------------------------------ - */ -void op_2(struct script_state *st,int op) -{ - int i1,i2; - char *s1=NULL,*s2=NULL; - - i2=pop_val(st); - if( isstr(st->stack->stack_data[st->stack->sp]) ) - s2=st->stack->stack_data[st->stack->sp].u.str; - - i1=pop_val(st); - if( isstr(st->stack->stack_data[st->stack->sp]) ) - s1=st->stack->stack_data[st->stack->sp].u.str; - - if( s1!=NULL && s2!=NULL ){ - // ss => op_2str - op_2str(st,op,st->stack->sp,st->stack->sp+1); - }else if( s1==NULL && s2==NULL ){ - // ii => op_2num - op_2num(st,op,i1,i2); - }else{ - // si,is => error - ShowWarning("script: op_2: int&str, str&int not allow.\n"); - report_src(st); - push_val(st->stack,C_INT,0); - } -} - -/*========================================== - * 単項演算子 - *------------------------------------------ - */ -void op_1num(struct script_state *st,int op) -{ - int i1; - i1=pop_val(st); - switch(op){ - case C_NEG: - i1=-i1; - break; - case C_NOT: - i1=~i1; - break; - case C_LNOT: - i1=!i1; - break; - } - push_val(st->stack,C_INT,i1); -} - - -/*========================================== - * 関数の実行 - *------------------------------------------ - */ -int run_func(struct script_state *st) -{ - int i,start_sp,end_sp,func; - - end_sp=st->stack->sp; - for(i=end_sp-1;i>=0 && st->stack->stack_data[i].type!=C_ARG;i--); - if(i==0){ - if(battle_config.error_log) - ShowError("function not found\n"); -// st->stack->sp=0; - st->state=END; - report_src(st); - return 1; - } - start_sp=i-1; - st->start=i-1; - st->end=end_sp; - - func=st->stack->stack_data[st->start].u.num; - if( st->stack->stack_data[st->start].type!=C_NAME || str_data[func].type!=C_FUNC ){ - ShowMessage ("run_func: '"CL_WHITE"%s"CL_RESET"' (type %d) is not function and command!\n", - str_buf + str_data[func].str, str_data[func].type); -// st->stack->sp=0; - st->state=END; - report_src(st); - return 1; - } -#ifdef DEBUG_RUN - if(battle_config.etc_log) { - ShowDebug("run_func : %s? (%d(%d)) sp=%d (%d...%d)\n",str_buf+str_data[func].str, func, str_data[func].type, st->stack->sp, st->start, st->end); - ShowDebug("stack dump :"); - for(i=0;i<end_sp;i++){ - switch(st->stack->stack_data[i].type){ - case C_INT: - printf(" int(%d)",st->stack->stack_data[i].u.num); - break; - case C_NAME: - printf(" name(%s)",str_buf+str_data[st->stack->stack_data[i].u.num].str); - break; - case C_ARG: - printf(" arg"); - break; - case C_POS: - printf(" pos(%d)",st->stack->stack_data[i].u.num); - break; - case C_STR: - printf(" str(%s)",st->stack->stack_data[i].u.str); - break; - case C_CONSTSTR: - printf(" cstr(%s)",st->stack->stack_data[i].u.str); - break; - default: - printf(" %d,%d",st->stack->stack_data[i].type,st->stack->stack_data[i].u.num); - } - } - printf("\n"); - } -#endif - if(str_data[func].func){ - if (str_data[func].func(st)) //Report error - report_src(st); - } else { - if(battle_config.error_log) - ShowError("run_func : %s? (%d(%d))\n",str_buf+str_data[func].str,func,str_data[func].type); - push_val(st->stack,C_INT,0); - report_src(st); - } - - // Stack's datum are used when re-run functions [Eoe] - if(st->state != RERUNLINE) { - pop_stack(st->stack,start_sp,end_sp); - } - - if(st->state==RETFUNC){ - // ユーザー定義関数からの復帰 - int olddefsp=st->stack->defsp; - int i; - - pop_stack(st->stack,st->stack->defsp,start_sp); // 復帰に邪魔なスタック削除 - if(st->stack->defsp<5 || st->stack->stack_data[st->stack->defsp-1].type!=C_RETINFO){ - ShowWarning("script:run_func(return) return without callfunc or callsub!\n"); - st->state=END; - report_src(st); - return 1; - } - script_free_vars( st->stack->var_function ); - aFree(st->stack->var_function); - i = conv_num(st,& (st->stack->stack_data[st->stack->defsp-5])); // 引数の数所得 - st->pos=conv_num(st,& (st->stack->stack_data[st->stack->defsp-1])); // スクリプト位置の復元 - st->script=(struct script_code *)conv_num(st,& (st->stack->stack_data[st->stack->defsp-3])); // スクリプトを復元 - st->stack->var_function = (struct linkdb_node**)st->stack->stack_data[st->stack->defsp-2].u.num; // 関数依存変数 - st->stack->defsp=conv_num(st,& (st->stack->stack_data[st->stack->defsp-4])); // 基準スタックポインタを復元 - - pop_stack(st->stack,olddefsp-5-i,olddefsp); // 要らなくなったスタック(引数と復帰用データ)削除 - - st->state=GOTO; - } - - return 0; -} - -/*========================================== - * スクリプトの実行メイン部分 - *------------------------------------------ - */ -void run_script_main(struct script_state *st) -{ - int c/*,rerun_pos*/; - int cmdcount=script_config.check_cmdcount; - int gotocount=script_config.check_gotocount; - struct script_stack *stack=st->stack; - TBL_PC *sd = map_id2sd(st->rid); - struct script_state *bk_st = NULL; - int bk_npcid = 0; - - if(sd){ - if(sd->st != st){ - bk_st = sd->st; - bk_npcid = sd->npc_id; - } - sd->st = st; - sd->npc_id = st->oid; - } - - if(st->state == RERUNLINE) { - st->state = RUN; - run_func(st); - if(st->state == GOTO) - st->state = RUN; - } else if(st->state != END) - st->state = RUN; - - while( st->state == RUN) { - c= get_com((unsigned char *) st->script->script_buf,&st->pos); - switch(c){ - case C_EOL: - if(stack->sp!=stack->defsp){ - if(stack->sp > stack->defsp) - { //sp > defsp is valid in cases when you invoke functions and don't use the returned value. [Skotlex] - //Since sp is supposed to be defsp in these cases, we could assume the extra stack elements are unneeded. - if (battle_config.etc_log) - ShowWarning("Clearing unused stack stack.sp(%d) -> default(%d)\n",stack->sp,stack->defsp); - pop_stack(stack, stack->defsp, stack->sp); //Clear out the unused stack-section. - } else if(battle_config.error_log) - ShowError("stack.sp(%d) != default(%d)\n",stack->sp,stack->defsp); - stack->sp=stack->defsp; - } - // rerun_pos=st->pos; - break; - case C_INT: - push_val(stack,C_INT,get_num((unsigned char *) st->script->script_buf,&st->pos)); - break; - case C_POS: - case C_NAME: - push_val(stack,c,(*(int*)(st->script->script_buf+st->pos))&0xffffff); - st->pos+=3; - break; - case C_ARG: - push_val(stack,c,0); - break; - case C_STR: - push_str(stack,C_CONSTSTR,(unsigned char *) (st->script->script_buf+st->pos)); - while(st->script->script_buf[st->pos++]); - break; - case C_FUNC: - run_func(st); - if(st->state==GOTO){ - // rerun_pos=st->pos; - st->state=RUN; - if( gotocount>0 && (--gotocount)<=0 ){ - ShowError("run_script: infinity loop !\n"); - st->state=END; - } - } - break; - - case C_ADD: - op_add(st); - break; - - case C_SUB: - case C_MUL: - case C_DIV: - case C_MOD: - case C_EQ: - case C_NE: - case C_GT: - case C_GE: - case C_LT: - case C_LE: - case C_AND: - case C_OR: - case C_XOR: - case C_LAND: - case C_LOR: - case C_R_SHIFT: - case C_L_SHIFT: - op_2(st,c); - break; - - case C_NEG: - case C_NOT: - case C_LNOT: - op_1num(st,c); - break; - - case C_NOP: - st->state=END; - break; - - default: - if(battle_config.error_log) - ShowError("unknown command : %d @ %d\n",c,pos); - st->state=END; - break; - } - if( cmdcount>0 && (--cmdcount)<=0 ){ - ShowError("run_script: infinity loop !\n"); - st->state=END; - } - } - switch(st->state){ - case STOP: - break; - case END: - { - st->pos=-1; - if(sd){ - if(sd->state.using_fake_npc){ - clif_clearchar_id(sd->npc_id, 0, sd->fd); - sd->state.using_fake_npc = 0; - } - npc_event_dequeue(sd); - //Restore previous script if any. - sd->st = bk_st; - sd->npc_id = bk_npcid; - bk_st = NULL; //Remove tag for removal. - if (sd->state.reg_dirty&2) - intif_saveregistry(sd,2); - if (sd->state.reg_dirty&1) - intif_saveregistry(sd,1); - } - //Remove unneeded script. - script_free_stack (st->stack); - aFree(st); - } - break; - case RERUNLINE: - if(bk_st && sd->st != bk_st && st->sleep.tick <= 0) - ShowWarning("Unable to restore stack! Double continuation!\n"); - - if(st->sleep.tick > 0) - { //Delay execution - if(sd) - st->sleep.charid = sd->char_id; - else - st->sleep.charid = 0; - st->sleep.timer = add_timer(gettick()+st->sleep.tick, - run_script_timer, st->sleep.charid, (int)st); - linkdb_insert(&sleep_db, (void*)st->oid, st); - //Restore previous script/ - sd->st = bk_st; - sd->npc_id = bk_npcid; - bk_st = NULL; //Remove tag for removal. - } - // Do not call function of commands two time! [ Eoe / jA 1094 ] - // For example: select "1", "2", callsub(...); - // If current script position is changed, callsub will be called two time. - // - // { - // st->pos=rerun_pos; - // } - break; - } - - if (bk_st) - { //Remove previous script - script_free_stack(bk_st->stack); - aFree(bk_st); - bk_st = NULL; - } - - //FIXME: Is it correct to NOT free the script when the state is not END AND there's NO PLAYER running it?? - return; -} - -/*========================================== - * スクリプトの実行 - *------------------------------------------ - */ -void run_script(struct script_code *rootscript,int pos,int rid,int oid) -{ - struct script_state *st; - struct map_session_data *sd=NULL; - - //Variables for backing up the previous script and restore it if needed. [Skotlex] - //struct script_code *bck_script = NULL; - //struct script_code *bck_scriptroot = NULL; - //int bck_scriptstate = 0,bck_npcid = 0; - //struct script_stack *bck_stack = NULL; - - if (rootscript == NULL || pos < 0) - return; - - if ((sd = map_id2sd(rid)) && sd->st && sd->st->scriptroot == rootscript && sd->st->pos == pos){ - st = sd->st; - } else { - st = aCalloc(sizeof(struct script_state), 1); - // the script is different, make new script_state and stack - st->stack = aMalloc (sizeof(struct script_stack)); - st->stack->sp = 0; - st->stack->sp_max = 64; - st->stack->stack_data = (struct script_data *) aCalloc (st->stack->sp_max,sizeof(st->stack->stack_data[0])); - st->stack->defsp = st->stack->sp; - st->stack->var_function = aCalloc(1, sizeof(struct linkdb_node*)); - st->state = RUN; - st->script = rootscript; - - /*if (sd){ - if(sd->stack) { - // if there's a sd and a stack - back it up and restore it if possible. - bck_script = sd->npc_script; - bck_scriptroot = sd->npc_scriptroot; - bck_scriptstate = sd->npc_scriptstate; - bck_stack = sd->stack; - sd->stack = NULL; - } - bck_npcid = sd->npc_id; - sd->npc_id = oid; - }*/ - } - st->pos = pos; - st->rid = rid; - st->oid = oid; - st->sleep.timer = -1; - - run_script_main(st); - /* if (st->state != END){ - pos = st->pos; - if(!st->sleep.tick && sd) { - // script is not finished, store data in sd. - sd->npc_script = st->script; - sd->npc_scriptroot = rootscript; - sd->npc_scriptstate = st->state; - sd->stack = st->stack; - if (bck_stack) //Get rid of the backup as it can't be restored. - script_free_stack (bck_stack); - aFree(st); - } - return pos; - } else { - if(st->stack) - script_free_stack(st->stack); - aFree(st); - } - } else { - //Script finished. - if (sd) - { //Clear or restore previous script. - sd->npc_script = bck_script; - sd->npc_scriptroot = bck_scriptroot; - sd->npc_scriptstate = bck_scriptstate; - sd->stack = bck_stack; - sd->npc_id = bck_npcid; - //Since the script is done, save any changed account variables [Skotlex] - if (sd->state.reg_dirty&2) - intif_saveregistry(sd,2); - if (sd->state.reg_dirty&1) - intif_saveregistry(sd,1); - } - }*/ - return; -} - -/*========================================== - * 指定ノードをsleep_dbから削除 - *------------------------------------------ - */ -struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n) -{ - struct linkdb_node *retnode; - - if( n == NULL) - return NULL; - if( n->prev == NULL ) - sleep_db = n->next; - else - n->prev->next = n->next; - if( n->next ) - n->next->prev = n->prev; - retnode = n->next; - aFree( n ); - return retnode; // 次のノードを返す -} - - -/*========================================== - * sleep用タイマー関数 - *------------------------------------------ - */ -int run_script_timer(int tid, unsigned int tick, int id, int data) -{ - struct script_state *st = (struct script_state *)data; - struct linkdb_node *node = (struct linkdb_node *)sleep_db; - struct map_session_data *sd = map_id2sd(st->rid); - - if((sd && sd->char_id != id) || (st->rid && !sd)) - { //Character mismatch. Cancel execution. - st->rid = 0; - st->state = END; - } - - while( node && st->sleep.timer != -1 ) { - if( (int)node->key == st->oid && ((struct script_state *)node->data)->sleep.timer == st->sleep.timer ) { - script_erase_sleepdb(node); - st->sleep.timer = -1; - break; - } - node = node->next; - } - - run_script_main(st); - return 0; -} - - -/*========================================== - * マップ変数の変更 - *------------------------------------------ - */ -int mapreg_setreg(int num,int val) -{ -#if !defined(TXT_ONLY) && defined(MAPREGSQL) - int i=num>>24; - char *name=str_buf+str_data[num&0x00ffffff].str; - char tmp_str[64]; -#endif - - if(val!=0) { - if(idb_put(mapreg_db,num,(void*)val)) - ; -#if !defined(TXT_ONLY) && defined(MAPREGSQL) - else if(name[1] != '@') { - sprintf(tmp_sql,"INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%d')",mapregsql_db,mapregsql_db_varname,mapregsql_db_index,mapregsql_db_value,jstrescapecpy(tmp_str,name),i,val); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } -#endif - // else - } else { // [zBuffer] -#if !defined(TXT_ONLY) && defined(MAPREGSQL) - if(name[1] != '@') { // Remove from database because it is unused. - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_varname,name,mapregsql_db_index,i); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } -#endif - idb_remove(mapreg_db,num); - } - - mapreg_dirty=1; - return 0; -} -/*========================================== - * 文字列型マップ変数の変更 - *------------------------------------------ - */ -int mapreg_setregstr(int num,const char *str) -{ - char *p; -#if !defined(TXT_ONLY) && defined(MAPREGSQL) - char tmp_str[64]; - char tmp_str2[512]; - int i=num>>24; // [zBuffer] - char *name=str_buf+str_data[num&0x00ffffff].str; -#endif - - if( str==NULL || *str==0 ){ -#if !defined(TXT_ONLY) && defined(MAPREGSQL) - if(name[1] != '@') { - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_varname,name,mapregsql_db_index,i); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } -#endif - idb_remove(mapregstr_db,num); - mapreg_dirty=1; - return 0; - } - p=(char *)aMallocA((strlen(str)+1)*sizeof(char)); - strcpy(p,str); - - if (idb_put(mapregstr_db,num,p)) - ; -#if !defined(TXT_ONLY) && defined(MAPREGSQL) - else if(name[1] != '@'){ //put returned null, so we must insert. - // Someone is causing a database size infinite increase here without name[1] != '@' [Lance] - sprintf(tmp_sql,"INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%s')",mapregsql_db,mapregsql_db_varname,mapregsql_db_index,mapregsql_db_value,jstrescapecpy(tmp_str,name),i,jstrescapecpy(tmp_str2,p)); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } -#endif - mapreg_dirty=1; - return 0; -} - -/*========================================== - * 永続的マップ変数の読み込み - *------------------------------------------ - */ -static int script_load_mapreg(void) -{ -#if defined(TXT_ONLY) || !defined(MAPREGSQL) - FILE *fp; - char line[1024]; - - if( (fp=fopen(mapreg_txt,"rt"))==NULL ) - return -1; - - while(fgets(line,sizeof(line),fp)){ - char buf1[256],buf2[1024],*p; - int n,v,s,i; - if( sscanf(line,"%255[^,],%d\t%n",buf1,&i,&n)!=2 && - (i=0,sscanf(line,"%[^\t]\t%n",buf1,&n)!=1) ) - continue; - if( buf1[strlen(buf1)-1]=='$' ){ - if( sscanf(line+n,"%[^\n\r]",buf2)!=1 ){ - ShowError("%s: %s broken data !\n",mapreg_txt,buf1); - continue; - } - p=(char *)aMallocA((strlen(buf2) + 1)*sizeof(char)); - strcpy(p,buf2); - s= add_str((unsigned char *) buf1); - idb_put(mapregstr_db,(i<<24)|s,p); - }else{ - if( sscanf(line+n,"%d",&v)!=1 ){ - ShowError("%s: %s broken data !\n",mapreg_txt,buf1); - continue; - } - s= add_str((unsigned char *) buf1); - idb_put(mapreg_db,(i<<24)|s,(void*)v); - } - } - fclose(fp); - mapreg_dirty=0; - return 0; -#else - // SQL mapreg code start [zBuffer] - /* - 0 1 2 - +-------------------------+ - | varname | index | value | - +-------------------------+ - */ - unsigned int perfomance = (unsigned int)time(NULL); - sprintf(tmp_sql,"SELECT * FROM `%s`",mapregsql_db); - ShowInfo("Querying script_load_mapreg ...\n"); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return -1; - } - ShowInfo("Success! Returning results ...\n"); - sql_res = mysql_store_result(&mmysql_handle); - if (sql_res) { - while ((sql_row = mysql_fetch_row(sql_res))) { - char buf1[33], *p = NULL; - int i,v,s; - strcpy(buf1,sql_row[0]); - if( buf1[strlen(buf1)-1]=='$' ){ - i = atoi(sql_row[1]); - p=(char *)aMallocA((strlen(sql_row[2]) + 1)*sizeof(char)); - strcpy(p,sql_row[2]); - s= add_str((unsigned char *) buf1); - idb_put(mapregstr_db,(i<<24)|s,p); - }else{ - s= add_str((unsigned char *) buf1); - v= atoi(sql_row[2]); - i = atoi(sql_row[1]); - idb_put(mapreg_db,(i<<24)|s,(void *)v); - } - } - } - ShowInfo("Freeing results...\n"); - mysql_free_result(sql_res); - mapreg_dirty=0; - perfomance = ((unsigned int)time(NULL) - perfomance); - ShowInfo("SQL Mapreg Loading Completed Under %d Seconds.\n",perfomance); - return 0; -#endif /* TXT_ONLY */ -} -/*========================================== - * 永続的マップ変数の書き込み - *------------------------------------------ - */ -static int script_save_mapreg_intsub(DBKey key,void *data,va_list ap) -{ -#if defined(TXT_ONLY) || !defined(MAPREGSQL) - FILE *fp=va_arg(ap,FILE*); - int num=key.i&0x00ffffff, i=key.i>>24; - char *name=str_buf+str_data[num].str; - if( name[1]!='@' ){ - if(i==0) - fprintf(fp,"%s\t%d\n", name, (int)data); - else - fprintf(fp,"%s,%d\t%d\n", name, i, (int)data); - } - return 0; -#else - int num=key.i&0x00ffffff, i=key.i>>24; // [zBuffer] - char *name=str_buf+str_data[num].str; - if ( name[1] != '@') { - sprintf(tmp_sql,"UPDATE `%s` SET `%s`='%d' WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_value,(int)data,mapregsql_db_varname,name,mapregsql_db_index,i); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } - return 0; -#endif -} -static int script_save_mapreg_strsub(DBKey key,void *data,va_list ap) -{ -#if defined(TXT_ONLY) || !defined(MAPREGSQL) - FILE *fp=va_arg(ap,FILE*); - int num=key.i&0x00ffffff, i=key.i>>24; - char *name=str_buf+str_data[num].str; - if( name[1]!='@' ){ - if(i==0) - fprintf(fp,"%s\t%s\n", name, (char *)data); - else - fprintf(fp,"%s,%d\t%s\n", name, i, (char *)data); - } - return 0; -#else - char tmp_str2[512]; - int num=key.i&0x00ffffff, i=key.i>>24; - char *name=str_buf+str_data[num].str; - if ( name[1] != '@') { - sprintf(tmp_sql,"UPDATE `%s` SET `%s`='%s' WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_value,jstrescapecpy(tmp_str2,(char *)data),mapregsql_db_varname,name,mapregsql_db_index,i); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } - return 0; -#endif -} -static int script_save_mapreg(void) -{ -#if defined(TXT_ONLY) || !defined(MAPREGSQL) - FILE *fp; - int lock; - - if( (fp=lock_fopen(mapreg_txt,&lock))==NULL ) { - ShowError("script_save_mapreg: Unable to lock-open file [%s]\n",mapreg_txt); - return -1; - } - mapreg_db->foreach(mapreg_db,script_save_mapreg_intsub,fp); - mapregstr_db->foreach(mapregstr_db,script_save_mapreg_strsub,fp); - lock_fclose(fp,mapreg_txt,&lock); -#else - unsigned int perfomance = (unsigned int)time(NULL); - mapreg_db->foreach(mapreg_db,script_save_mapreg_intsub); // [zBuffer] - mapregstr_db->foreach(mapregstr_db,script_save_mapreg_strsub); - perfomance = ((unsigned int)time(NULL) - perfomance); - if(perfomance > 2) - ShowWarning("Slow Query: MapregSQL Saving @ %d second(s).\n", perfomance); -#endif - mapreg_dirty=0; - return 0; -} -static int script_autosave_mapreg(int tid,unsigned int tick,int id,int data) -{ - if(mapreg_dirty) - if (script_save_mapreg() == -1) - ShowError("Failed to save the mapreg data!\n"); - return 0; -} - -/*========================================== - * - *------------------------------------------ - */ -static int set_posword(char *p) -{ - char* np,* str[15]; - int i=0; - for(i=0;i<11;i++) { - if((np=strchr(p,','))!=NULL) { - str[i]=p; - *np=0; - p=np+1; - } else { - str[i]=p; - p+=strlen(p); - } - if(str[i]) - strcpy(pos[i],str[i]); - } - return 0; -} - -int script_config_read_sub(char *cfgName) -{ - int i; - char line[1024],w1[1024],w2[1024]; - FILE *fp; - - - fp = fopen(cfgName, "r"); - if (fp == NULL) { - ShowError("file not found: [%s]\n", cfgName); - return 1; - } - while (fgets(line, sizeof(line) - 1, fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - i = sscanf(line,"%[^:]: %[^\r\n]",w1,w2); - if (i != 2) - continue; - if(strcmpi(w1,"refine_posword")==0) { - set_posword(w2); - } - else if(strcmpi(w1,"verbose_mode")==0) { - script_config.verbose_mode = battle_config_switch(w2); - } - else if(strcmpi(w1,"warn_func_no_comma")==0) { - script_config.warn_func_no_comma = battle_config_switch(w2); - } - else if(strcmpi(w1,"warn_cmd_no_comma")==0) { - script_config.warn_cmd_no_comma = battle_config_switch(w2); - } - else if(strcmpi(w1,"warn_func_mismatch_paramnum")==0) { - script_config.warn_func_mismatch_paramnum = battle_config_switch(w2); - } - else if(strcmpi(w1,"warn_cmd_mismatch_paramnum")==0) { - script_config.warn_cmd_mismatch_paramnum = battle_config_switch(w2); - } - else if(strcmpi(w1,"check_cmdcount")==0) { - script_config.check_cmdcount = battle_config_switch(w2); - } - else if(strcmpi(w1,"check_gotocount")==0) { - script_config.check_gotocount = battle_config_switch(w2); - } - else if(strcmpi(w1,"event_script_type")==0) { - script_config.event_script_type = battle_config_switch(w2); - } - else if(strcmpi(w1,"event_requires_trigger")==0) { - script_config.event_requires_trigger = battle_config_switch(w2); - } - else if(strcmpi(w1,"die_event_name")==0) { - strncpy(script_config.die_event_name, w2, NAME_LENGTH-1); - if (strlen(script_config.die_event_name) != strlen(w2)) - ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.die_event_name); - } - else if(strcmpi(w1,"kill_pc_event_name")==0) { - strncpy(script_config.kill_pc_event_name, w2, NAME_LENGTH-1); - if (strlen(script_config.kill_pc_event_name) != strlen(w2)) - ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.kill_pc_event_name); - } - else if(strcmpi(w1,"kill_mob_event_name")==0) { - strncpy(script_config.kill_mob_event_name, w2, NAME_LENGTH-1); - if (strlen(script_config.kill_mob_event_name) != strlen(w2)) - ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.kill_mob_event_name); - } - else if(strcmpi(w1,"login_event_name")==0) { - strncpy(script_config.login_event_name, w2, NAME_LENGTH-1); - if (strlen(script_config.login_event_name) != strlen(w2)) - ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.login_event_name); - } - else if(strcmpi(w1,"logout_event_name")==0) { - strncpy(script_config.logout_event_name, w2, NAME_LENGTH-1); - if (strlen(script_config.logout_event_name) != strlen(w2)) - ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.logout_event_name); - } - else if(strcmpi(w1,"loadmap_event_name")==0) { - strncpy(script_config.loadmap_event_name, w2, NAME_LENGTH-1); - if (strlen(script_config.loadmap_event_name) != strlen(w2)) - ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.loadmap_event_name); - } - else if(strcmpi(w1,"baselvup_event_name")==0) { - strncpy(script_config.baselvup_event_name, w2, NAME_LENGTH-1); - if (strlen(script_config.baselvup_event_name) != strlen(w2)) - ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.baselvup_event_name); - } - else if(strcmpi(w1,"joblvup_event_name")==0) { - strncpy(script_config.joblvup_event_name, w2, NAME_LENGTH-1); - if (strlen(script_config.joblvup_event_name) != strlen(w2)) - ShowWarning("script_config_read: Event label truncated (max length is 23 chars): %d\n", script_config.joblvup_event_name); - } - else if(strcmpi(w1,"import")==0){ - script_config_read_sub(w2); - } - } - fclose(fp); - - return 0; -} - -int script_config_read(char *cfgName) -{ //Script related variables should be initialized once! [Skotlex] - - memset (&script_config, 0, sizeof(script_config)); - script_config.verbose_mode = 0; - script_config.warn_func_no_comma = 1; - script_config.warn_cmd_no_comma = 1; - script_config.warn_func_mismatch_paramnum = 1; - script_config.warn_cmd_mismatch_paramnum = 1; - script_config.check_cmdcount = 65535; - script_config.check_gotocount = 2048; - - script_config.event_script_type = 0; - script_config.event_requires_trigger = 1; - - return script_config_read_sub(cfgName); -} - -static int do_final_userfunc_sub (DBKey key,void *data,va_list ap){ - struct script_code *code = (struct script_code *)data; - if(code){ - script_free_vars( &code->script_vars ); - aFree( code->script_buf ); - } - return 0; -} - -/*========================================== - * 終了 - *------------------------------------------ - */ -int do_final_script() -{ - if(mapreg_dirty>=0) - script_save_mapreg(); - - mapreg_db->destroy(mapreg_db,NULL); - mapregstr_db->destroy(mapregstr_db,NULL); - scriptlabel_db->destroy(scriptlabel_db,NULL); - userfunc_db->destroy(userfunc_db,do_final_userfunc_sub); - if(sleep_db) { - struct linkdb_node *n = (struct linkdb_node *)sleep_db; - while(n) { - struct script_state *st = (struct script_state *)n->data; - script_free_stack(st->stack); - free(st); - n = n->next; - } - linkdb_final(&sleep_db); - } - - if (str_data) - aFree(str_data); - if (str_buf) - aFree(str_buf); - - return 0; -} -/*========================================== - * 初期化 - *------------------------------------------ - */ -int do_init_script() -{ - mapreg_db= db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); - mapregstr_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); - userfunc_db=db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_RELEASE_BOTH,50); - scriptlabel_db=db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_ALLOW_NULL_DATA,50); - - script_load_mapreg(); - - add_timer_func_list(script_autosave_mapreg,"script_autosave_mapreg"); - add_timer_interval(gettick()+MAPREG_AUTOSAVE_INTERVAL, - script_autosave_mapreg,0,0,MAPREG_AUTOSAVE_INTERVAL); - - return 0; -} - -int script_reload() -{ - if(mapreg_dirty>=0) - script_save_mapreg(); - - mapreg_db->clear(mapreg_db, NULL); - mapregstr_db->clear(mapregstr_db, NULL); - userfunc_db->clear(userfunc_db,do_final_userfunc_sub); - scriptlabel_db->clear(scriptlabel_db, NULL); - - if(sleep_db) { - struct linkdb_node *n = (struct linkdb_node *)sleep_db; - while(n) { - struct script_state *st = (struct script_state *)n->data; - script_free_stack(st->stack); - free(st); - n = n->next; - } - linkdb_final(&sleep_db); - } - - script_load_mapreg(); - return 0; -} |