diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/script.c | 788 |
1 files changed, 434 insertions, 354 deletions
diff --git a/src/map/script.c b/src/map/script.c index 7a2b9bea2..db2c2832e 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -72,7 +72,7 @@ //## TODO possible enhancements: [FlavioJS] // - 'callfunc' supporting labels in the current npc "::LabelName" // - 'callfunc' supporting labels in other npcs "NpcName::LabelName" -// - 'function FuncName;' function declarations reverting to global functions +// - 'function FuncName;' function declarations reverting to global functions // if local label isn't found // - join callfunc and callsub's functionality // - remove dynamic allocation in add_word() @@ -230,7 +230,7 @@ static int buildin_callsub_ref = 0; static int buildin_callfunc_ref = 0; static int buildin_getelementofarray_ref = 0; -// Caches compiled autoscript item code. +// Caches compiled autoscript item code. // Note: This is not cleared when reloading itemdb. static DBMap* autobonus_db=NULL; // char* script -> char* bytecode @@ -947,7 +947,7 @@ int add_word(const char* p) word = (char*)aMalloc(len+1); memcpy(word, p, len); word[len] = 0; - + // add the word i = add_str(word); aFree(word); @@ -1080,7 +1080,7 @@ const char* parse_variable(const char* p) { c_op type = C_NOP; const char *p2 = NULL; const char *var = p; - + // skip the variable where applicable p = skip_word(p); p = skip_space(p); @@ -1140,7 +1140,7 @@ const char* parse_variable(const char* p) { if( p == NULL ) {// end of line or invalid buffer return NULL; } - + // push the set function onto the stack add_scriptl(buildin_set_ref); add_scriptc(C_ARG); @@ -1152,7 +1152,7 @@ const char* parse_variable(const char* p) { // increment the total curly count for the position in the script ++ syntax.curly_count; - + // parse the variable currently being modified word = add_word(var); @@ -1168,7 +1168,7 @@ const char* parse_variable(const char* p) { add_scriptl(buildin_getelementofarray_ref); add_scriptc(C_ARG); add_scriptl(word); - + // process the sub-expression for this assignment p3 = parse_subexpr(p2 + 1, 1); p3 = skip_space(p3); @@ -1183,10 +1183,10 @@ const char* parse_variable(const char* p) { } else {// simply push the variable or value onto the stack add_scriptl(word); } - + if( type != C_EQ ) add_scriptc(C_REF); - + if( type == C_ADD_PP || type == C_SUB_PP ) {// incremental operator for the method add_scripti(1); add_scriptc(type == C_ADD_PP ? C_ADD : C_SUB); @@ -1201,10 +1201,10 @@ const char* parse_variable(const char* p) { // decrement the curly count for the position within the script -- syntax.curly_count; - + // close the script by appending the function operator add_scriptc(C_FUNC); - + // push the buffer from the method return p; } @@ -1296,7 +1296,7 @@ const char* parse_simpleexpr(const char *p) add_scriptl(buildin_getelementofarray_ref); add_scriptc(C_ARG); add_scriptl(l); - + p=parse_subexpr(p+1,-1); p=skip_space(p); if( *p != ']' ) @@ -1396,7 +1396,7 @@ const char* parse_line(const char* p) p=skip_space(p); if(*p==';') { - //Close decision for if(); for(); while(); + //Close decision for if(); for(); while(); p = parse_syntax_close(p + 1); return p; } @@ -1413,7 +1413,7 @@ const char* parse_line(const char* p) } else if(p[0] == '}') { return parse_curly_close(p); } - + // Syntax-related processing p2 = parse_syntax(p); if(p2 != NULL) @@ -1429,7 +1429,7 @@ const char* parse_line(const char* p) p = parse_callfunc(p,0,0); p = skip_space(p); - + if(parse_syntax_for_flag) { if( *p != ')' ) disp_error_message("parse_line: need ')'",p); @@ -1438,7 +1438,7 @@ const char* parse_line(const char* p) disp_error_message("parse_line: need ';'",p); } - //Binding decision for if(), for(), while() + //Binding decision for if(), for(), while() p = parse_syntax_close(p+1); return p; @@ -1478,7 +1478,7 @@ const char* parse_curly_close(const char* p) set_label(l,script_pos, p); if(syntax.curly[pos].flag) { - //Exists default + //Exists default sprintf(label,"goto __SW%x_DEF;",syntax.curly[pos].index); syntax.curly[syntax.curly_count++].type = TYPE_NULL; parse_line(label); @@ -1614,7 +1614,7 @@ const char* parse_syntax(const char* p) sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index); syntax.curly[syntax.curly_count++].type = TYPE_NULL; - + parse_line(label); syntax.curly_count--; syntax.curly[pos].count++; @@ -1751,7 +1751,7 @@ const char* parse_syntax(const char* p) if(*p != ';') disp_error_message("parse_syntax: need ';'",p); p++; - + // Skip to the beginning of the loop sprintf(label,"goto __FR%x_BGN;",syntax.curly[pos].index); syntax.curly[syntax.curly_count++].type = TYPE_NULL; @@ -1762,7 +1762,7 @@ const char* parse_syntax(const char* p) sprintf(label,"__FR%x_NXT",syntax.curly[pos].index); l=add_str(label); set_label(l,script_pos,p); - + // Process the next time you enter the loop // A ')' last for; flag to be treated as' parse_syntax_for_flag = 1; @@ -2229,7 +2229,7 @@ static const char* script_print_line(StringBuf* buf, const char* p, const char* { int i; if( p == NULL || !p[0] ) return NULL; - if( line < 0 ) + if( line < 0 ) StringBuf_Printf(buf, "*% 5d : ", -line); else StringBuf_Printf(buf, " % 5d : ", line); @@ -2828,7 +2828,7 @@ int conv_num(struct script_state* st, struct script_data* data) data->u.num = (int)num; } #if 0 - // FIXME this function is being used to retrieve the position of labels and + // FIXME this function is being used to retrieve the position of labels and // probably other stuff [FlavioJS] else {// unsupported data type @@ -3968,89 +3968,89 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle); int queryThread_timer(int tid, unsigned int tick, int id, intptr_t data) { int i, cursor = 0; bool allOk = true; - + EnterSpinLock(&queryThreadLock); - + for( i = 0; i < queryThreadData.count; i++ ) { struct queryThreadEntry *entry = queryThreadData.entry[i]; - + if( !entry->ok ) { allOk = false; continue; } run_script_main(entry->st); - + entry->st = NULL;/* empty entries */ aFree(entry); queryThreadData.entry[i] = NULL; } - + if( allOk ) { /* cancel the repeating timer -- it'll re-create itself when necessary, dont need to remain looping */ delete_timer(queryThreadData.timer, queryThread_timer); queryThreadData.timer = INVALID_TIMER; } - + /* now lets clear the mess. */ for( i = 0; i < queryThreadData.count; i++ ) { struct queryThreadEntry *entry = queryThreadData.entry[i]; if( entry == NULL ) continue;/* entry on hold */ - + /* move */ memmove(&queryThreadData.entry[cursor], &queryThreadData.entry[i], sizeof(struct queryThreadEntry*)); - + cursor++; } - + queryThreadData.count = cursor; - + LeaveSpinLock(&queryThreadLock); - + return 0; } void queryThread_add(struct script_state *st, bool type) { int idx = 0; struct queryThreadEntry* entry = NULL; - + EnterSpinLock(&queryThreadLock); - + if( queryThreadData.count++ != 0 ) RECREATE(queryThreadData.entry, struct queryThreadEntry* , queryThreadData.count); - + idx = queryThreadData.count-1; - + CREATE(queryThreadData.entry[idx],struct queryThreadEntry,1); - + entry = queryThreadData.entry[idx]; - + entry->st = st; entry->ok = false; entry->type = type; if( queryThreadData.timer == INVALID_TIMER ) { /* start the receiver timer */ queryThreadData.timer = add_timer_interval(gettick() + 100, queryThread_timer, 0, 0, 100); } - + LeaveSpinLock(&queryThreadLock); - + /* unlock the queryThread */ racond_signal(queryThreadCond); } /* adds a new log to the queue */ void queryThread_log(char * entry, int length) { int idx = logThreadData.count; - + EnterSpinLock(&queryThreadLock); - + if( logThreadData.count++ != 0 ) - RECREATE(logThreadData.entry, char* , logThreadData.count); - + RECREATE(logThreadData.entry, char* , logThreadData.count); + CREATE(logThreadData.entry[idx], char, length + 1 ); safestrncpy(logThreadData.entry[idx], entry, length + 1 ); - + LeaveSpinLock(&queryThreadLock); /* unlock the queryThread */ @@ -4061,48 +4061,48 @@ void queryThread_log(char * entry, int length) { static void *queryThread_main(void *x) { Sql *queryThread_handle = Sql_Malloc(); int i; - + if ( SQL_ERROR == Sql_Connect(queryThread_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db) ) exit(EXIT_FAILURE); - + if( strlen(default_codepage) > 0 ) if ( SQL_ERROR == Sql_SetEncoding(queryThread_handle, default_codepage) ) Sql_ShowDebug(queryThread_handle); if( log_config.sql_logs ) { logmysql_handle = Sql_Malloc(); - + if ( SQL_ERROR == Sql_Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db) ) exit(EXIT_FAILURE); - + if( strlen(default_codepage) > 0 ) if ( SQL_ERROR == Sql_SetEncoding(logmysql_handle, default_codepage) ) Sql_ShowDebug(logmysql_handle); } - + while( 1 ) { - + if(queryThreadTerminate > 0) break; - + EnterSpinLock(&queryThreadLock); - + /* mess with queryThreadData within the lock */ for( i = 0; i < queryThreadData.count; i++ ) { struct queryThreadEntry *entry = queryThreadData.entry[i]; - + if( entry->ok ) continue; else if ( !entry->st || !entry->st->stack ) { entry->ok = true;/* dispose */ continue; } - + buildin_query_sql_sub(entry->st, entry->type ? logmysql_handle : queryThread_handle); - + entry->ok = true;/* we're done with this */ } - + /* also check for any logs in need to be sent */ if( log_config.sql_logs ) { for( i = 0; i < logThreadData.count; i++ ) { @@ -4112,21 +4112,21 @@ static void *queryThread_main(void *x) { } logThreadData.count = 0; } - + LeaveSpinLock(&queryThreadLock); - + ramutex_lock( queryThreadMutex ); racond_wait( queryThreadCond, queryThreadMutex, -1 ); ramutex_unlock( queryThreadMutex ); } - + Sql_Free(queryThread_handle); - + if( log_config.sql_logs ) { Sql_Free(logmysql_handle); } - + return NULL; } #endif @@ -4213,7 +4213,7 @@ int do_final_script() { for( i = 0; i < atcmd_binding_count; i++ ) { aFree(atcmd_binding[i]); } - + if( atcmd_binding_count != 0 ) aFree(atcmd_binding); #ifdef BETA_THREAD_TEST @@ -4221,25 +4221,25 @@ int do_final_script() { InterlockedIncrement(&queryThreadTerminate); racond_signal(queryThreadCond); rathread_wait(queryThread, NULL); - + // Destroy cond var and mutex. racond_destroy( queryThreadCond ); ramutex_destroy( queryThreadMutex ); - + /* Clear missing vars */ for( i = 0; i < queryThreadData.count; i++ ) { aFree(queryThreadData.entry[i]); } - + aFree(queryThreadData.entry); - + for( i = 0; i < logThreadData.count; i++ ) { aFree(logThreadData.entry[i]); } - - aFree(logThreadData.entry); + + aFree(logThreadData.entry); #endif - + return 0; } /*========================================== @@ -4257,16 +4257,16 @@ int do_init_script() { CREATE(logThreadData.entry, char *, 1); logThreadData.count = 0; /* QueryThread Start */ - + InitializeSpinLock(&queryThreadLock); - + queryThreadData.timer = INVALID_TIMER; queryThreadTerminate = 0; queryThreadMutex = ramutex_create(); queryThreadCond = racond_create(); - + queryThread = rathread_create(queryThread_main, NULL); - + if(queryThread == NULL){ ShowFatalError("do_init_script: cannot spawn Query Thread.\n"); exit(EXIT_FAILURE); @@ -4283,21 +4283,21 @@ int script_reload() { #ifdef BETA_THREAD_TEST /* we're reloading so any queries undergoing should be...exterminated. */ EnterSpinLock(&queryThreadLock); - + for( i = 0; i < queryThreadData.count; i++ ) { aFree(queryThreadData.entry[i]); } queryThreadData.count = 0; - + if( queryThreadData.timer != INVALID_TIMER ) { delete_timer(queryThreadData.timer, queryThread_timer); queryThreadData.timer = INVALID_TIMER; } - + LeaveSpinLock(&queryThreadLock); #endif - + userfunc_db->clear(userfunc_db, db_script_free_code_sub); db_clear(scriptlabel_db); @@ -4306,10 +4306,10 @@ int script_reload() { for( i = 0; i < atcmd_binding_count; i++ ) { aFree(atcmd_binding[i]); } - + if( atcmd_binding_count != 0 ) aFree(atcmd_binding); - + atcmd_binding_count = 0; if(sleep_db) { @@ -4519,7 +4519,7 @@ BUILDIN_FUNC(menu) } st->state = RERUNLINE; sd->state.menu_or_input = 1; - + /** * menus beyond this length crash the client (see bugreport:6402) **/ @@ -4533,7 +4533,7 @@ BUILDIN_FUNC(menu) aFree(menu); } else clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); - + StringBuf_Destroy(&buf); if( sd->npc_menu >= 0xff ) @@ -4610,7 +4610,7 @@ BUILDIN_FUNC(select) sd->npc_menu = 0; for( i = 2; i <= script_lastdata(st); ++i ) { text = script_getstr(st, i); - + if( sd->npc_menu > 0 ) StringBuf_AppendStr(&buf, ":"); @@ -4620,7 +4620,7 @@ BUILDIN_FUNC(select) st->state = RERUNLINE; sd->state.menu_or_input = 1; - + /** * menus beyond this length crash the client (see bugreport:6402) **/ @@ -4661,7 +4661,7 @@ BUILDIN_FUNC(select) } /// Displays a menu with options and returns the selected option. -/// Behaves like 'menu' without the target labels, except when cancel is +/// Behaves like 'menu' without the target labels, except when cancel is /// pressed. /// When cancel is pressed, the script continues and 255 is returned. /// @@ -4695,7 +4695,7 @@ BUILDIN_FUNC(prompt) st->state = RERUNLINE; sd->state.menu_or_input = 1; - + /** * menus beyond this length crash the client (see bugreport:6402) **/ @@ -4966,7 +4966,7 @@ BUILDIN_FUNC(rand) } /*========================================== - * Warp sd to str,x,y or Random or SavePoint/Save + * Warp sd to str,x,y or Random or SavePoint/Save *------------------------------------------*/ BUILDIN_FUNC(warp) { @@ -5004,29 +5004,29 @@ static int buildin_areawarp_sub(struct block_list *bl,va_list ap) { int x2,y2,x3,y3; unsigned int index; - + index = va_arg(ap,unsigned int); x2 = va_arg(ap,int); y2 = va_arg(ap,int); x3 = va_arg(ap,int); y3 = va_arg(ap,int); - + if(index == 0) pc_randomwarp((TBL_PC *)bl,CLR_TELEPORT); else if(x3 && y3) { int max, tx, ty, j = 0; - + // choose a suitable max number of attempts if( (max = (y3-y2+1)*(x3-x2+1)*3) > 1000 ) max = 1000; - + // find a suitable map cell do { tx = rnd()%(x3-x2+1)+x2; ty = rnd()%(y3-y2+1)+y2; j++; } while( map_getcell(index,tx,ty,CELL_CHKNOPASS) && j < max ); - + pc_setpos((TBL_PC *)bl,index,tx,ty,CLR_OUTSIGHT); } else @@ -5048,7 +5048,7 @@ BUILDIN_FUNC(areawarp) str = script_getstr(st,7); x2 = script_getnum(st,8); y2 = script_getnum(st,9); - + if( script_hasdata(st,10) && script_hasdata(st,11) ) { // Warp area to area if( (x3 = script_getnum(st,10)) < 0 || (y3 = script_getnum(st,11)) < 0 ){ x3 = 0; @@ -5106,7 +5106,7 @@ BUILDIN_FUNC(areapercentheal) /*========================================== * warpchar [LuzZza] - * Useful for warp one player from + * Useful for warp one player from * another player npc-session. * Using: warpchar "mapname",x,y,Char_ID; *------------------------------------------*/ @@ -5115,7 +5115,7 @@ BUILDIN_FUNC(warpchar) int x,y,a; const char *str; TBL_PC *sd; - + str=script_getstr(st,2); x=script_getnum(st,3); y=script_getnum(st,4); @@ -5132,9 +5132,9 @@ BUILDIN_FUNC(warpchar) pc_setpos(sd, sd->status.save_point.map,sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); else pc_setpos(sd, mapindex_name2id(str), x, y, CLR_TELEPORT); - + return 0; -} +} /*========================================== * Warpparty - [Fredzilla] [Paradox924X] * Syntax: warpparty "to_mapname",x,y,Party_ID,{"from_mapname"}; @@ -5160,7 +5160,7 @@ BUILDIN_FUNC(warpparty) p = party_search(p_id); if(!p) return 0; - + type = ( strcmp(str,"Random")==0 ) ? 0 : ( strcmp(str,"SavePointAll")==0 ) ? 1 : ( strcmp(str,"SavePoint")==0 ) ? 2 @@ -5217,7 +5217,7 @@ BUILDIN_FUNC(warpparty) break; case 3: // Leader case 4: // m,x,y - if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) + if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); break; } @@ -5245,7 +5245,7 @@ BUILDIN_FUNC(warpguild) g = guild_search(gid); if( g == NULL ) return 0; - + type = ( strcmp(str,"Random")==0 ) ? 0 : ( strcmp(str,"SavePointAll")==0 ) ? 1 : ( strcmp(str,"SavePoint")==0 ) ? 2 @@ -5293,10 +5293,10 @@ BUILDIN_FUNC(heal) { TBL_PC *sd; int hp,sp; - + sd = script_rid2sd(st); if (!sd) return 0; - + hp=script_getnum(st,2); sp=script_getnum(st,3); status_heal(&sd->bl, hp, sp, 1); @@ -5318,7 +5318,7 @@ BUILDIN_FUNC(itemheal) potion_sp = sp; return 0; } - + sd = script_rid2sd(st); if (!sd) return 0; pc_itemheal(sd,sd->itemid,hp,sp); @@ -5366,7 +5366,7 @@ BUILDIN_FUNC(jobchange) if (pcdb_checkid(job)) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) return 0; @@ -5388,9 +5388,9 @@ BUILDIN_FUNC(jobname) } /// Get input from the player. -/// For numeric inputs the value is capped to the range [min,max]. Returns 1 if +/// For numeric inputs the value is capped to the range [min,max]. Returns 1 if /// the value was higher than 'max', -1 if lower than 'min' and 0 otherwise. -/// For string inputs it returns 1 if the string was longer than 'max', -1 is +/// For string inputs it returns 1 if the string was longer than 'max', -1 is /// shorter than 'min' and 0 otherwise. /// /// input(<var>{,<min>{,<max>}}) -> <int> @@ -5868,7 +5868,7 @@ BUILDIN_FUNC(deletearray) for( ; start < end; ++start ) set_reg(st, sd, reference_uid(id, start), name, (void *)"", reference_getref(data)); } - else + else { for( ; start < end; ++start ) set_reg(st, sd, reference_uid(id, start), name, (void*)0, reference_getref(data)); @@ -5991,7 +5991,7 @@ BUILDIN_FUNC(viewpoint) y=script_getnum(st,4); id=script_getnum(st,5); color=script_getnum(st,6); - + sd = script_rid2sd(st); if( sd == NULL ) return 0; @@ -6057,7 +6057,7 @@ BUILDIN_FUNC(countitem2) int i; struct item_data* id = NULL; struct script_data* data; - + TBL_PC* sd = script_rid2sd(st); if (!sd) { script_pushint(st,0); @@ -6108,93 +6108,190 @@ BUILDIN_FUNC(countitem2) /*========================================== * Check if item with this amount can fit in inventory - * Checking : weight, stack amount >32k, slots amount >(MAX_INVENTORY) + * Checking : weight, stack amount >32k, slots amount >(MAX_INVENTORY) * Return * 0 : fail * 1 : success (npc side only) *------------------------------------------*/ BUILDIN_FUNC(checkweight) { - int nameid, amount, slots; - unsigned int weight; + int nameid, amount, slots, amount2=0; + unsigned int weight=0, i, nbargs; struct item_data* id = NULL; struct map_session_data* sd; struct script_data* data; - if( ( sd = script_rid2sd(st) ) == NULL ) - { + if( ( sd = script_rid2sd(st) ) == NULL ){ return 0; } - - data = script_getdata(st,2); - get_val(st, data); // convert into value in case of a variable - - if( data_isstring(data) ) - {// item name - id = itemdb_searchname(conv_str(st, data)); - } - else - {// item id - id = itemdb_exists(conv_num(st, data)); + nbargs = script_lastdata(st)+1; + ShowInfo("nb args = %d\n",nbargs); + if(nbargs%2){ + ShowError("buildin_checkweight: Invalid nb of args should be a multiple of 2.\n"); // returns string, regardless of what it was + script_pushint(st,0); + return 1; + } + slots = pc_inventoryblank(sd); //nb of empty slot + + for(i=2; i<nbargs; i=i+2){ + data = script_getdata(st,i); + get_val(st, data); // convert into value in case of a variable + if( data_isstring(data) ){// item name + id = itemdb_searchname(conv_str(st, data)); + } else {// item id + id = itemdb_exists(conv_num(st, data)); + } + if( id == NULL ) { + ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,i)); // returns string, regardless of what it was + script_pushint(st,0); + return 1; + } + nameid = id->nameid; + + amount = script_getnum(st,i+1); + if( amount < 1 ) { + ShowError("buildin_checkweight: Invalid amount '%d'.\n", amount); + script_pushint(st,0); + return 1; + } + + weight += itemdb_weight(nameid)*amount; //total weight for all chk + if( weight + sd->weight > sd->max_weight ) + {// too heavy + script_pushint(st,0); + return 0; + } + + switch( pc_checkadditem(sd, nameid, amount) ) + { + case ADDITEM_EXIST: + // item is already in inventory, but there is still space for the requested amount + break; + case ADDITEM_NEW: + if( itemdb_isstackable(nameid) ) {// stackable + amount2++; + if( slots < amount2 ) { + script_pushint(st,0); + return 0; + } + } + else {// non-stackable + amount2 += amount; + if( slots < amount2){ + script_pushint(st,0); + return 0; + } + } + break; + case ADDITEM_OVERAMOUNT: + script_pushint(st,0); + return 0; + } } + script_pushint(st,1); + return 0; +} - if( id == NULL ) - { - ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was - script_pushint(st,0); - return 1; - } +BUILDIN_FUNC(checkweight2) +{ + //variable sub checkweight + int32 nameid=-1, amount=-1; + int i=0, amount2=0, slots=0, weight=0; + short fail=0; - nameid = id->nameid; - amount = script_getnum(st,3); + //variable for array parsing + struct script_data* data_it; + struct script_data* data_nb; + const char* name_it; + const char* name_nb; + int32 id_it, id_nb; + int32 idx_it, idx_nb; + int nb_it, nb_nb; //array size - if( amount < 1 ) - { - ShowError("buildin_checkweight: Invalid amount '%d'.\n", amount); - script_pushint(st,0); - return 1; - } + TBL_PC *sd = script_rid2sd(st); + nullpo_retr(1,sd); - weight = itemdb_weight(nameid)*amount; + data_it = script_getdata(st, 2); + data_nb = script_getdata(st, 3); - if( weight + sd->weight > sd->max_weight ) - {// too heavy - script_pushint(st,0); - return 0; - } + if( !data_isreference(data_it) || !data_isreference(data_nb)) + { + ShowError("script:checkweight3: parameter not a variable\n"); + script_pushint(st,0); + return 1;// not a variable + } + id_it = reference_getid(data_it); + id_nb = reference_getid(data_nb); + idx_it = reference_getindex(data_it); + idx_nb = reference_getindex(data_nb); + name_it = reference_getname(data_it); + name_nb = reference_getname(data_nb); + + if( not_array_variable(*name_it) || not_array_variable(*name_nb)) + { + ShowError("script:checkweight3: illegal scope\n"); + script_pushint(st,0); + return 1;// not supported + } + if(is_string_variable(name_it) || is_string_variable(name_nb)){ + ShowError("script:checkweight3: illegal type, need int\n"); + script_pushint(st,0); + return 1;// not supported + } + nb_it = getarraysize(st, id_it, idx_it, 0, reference_getref(data_it)); + nb_nb = getarraysize(st, id_nb, idx_nb, 0, reference_getref(data_nb)); + if(nb_it != nb_nb){ + ShowError("Size mistmatch: nb_it=%d, nb_nb=%d\n",nb_it,nb_nb); + fail = 1; + } - switch( pc_checkadditem(sd, nameid, amount) ) - { - case ADDITEM_EXIST: + slots = pc_inventoryblank(sd); + for(i=0; i<nb_it; i++){ + nameid = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it))); + script_removetop(st, -1, 0); + amount = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb))); + script_removetop(st, -1, 0); + if(fail) continue; //cpntonie to depop rest + + if(itemdb_exists(nameid) == NULL ){ + ShowError("buildin_checkweight3: Invalid item '%d'.\n", nameid); + fail=1; + continue; + } + if(amount < 0 ){ + ShowError("buildin_checkweight3: Invalid amount '%d'.\n", amount); + fail = 1; + continue; + } + weight += itemdb_weight(nameid)*amount; + if( weight + sd->weight > sd->max_weight ){ + fail = 1; + continue; + } + switch( pc_checkadditem(sd, nameid, amount) ) { + case ADDITEM_EXIST: // item is already in inventory, but there is still space for the requested amount - break; - case ADDITEM_NEW: - slots = pc_inventoryblank(sd); - - if( itemdb_isstackable(nameid) ) - {// stackable - if( slots < 1 ) - { - script_pushint(st,0); - return 0; - } - } - else - {// non-stackable - if( slots < amount ) - { - script_pushint(st,0); - return 0; - } - } - break; - case ADDITEM_OVERAMOUNT: - script_pushint(st,0); - return 0; - } - - script_pushint(st,1); - return 0; + break; + case ADDITEM_NEW: + if( itemdb_isstackable(nameid) ){// stackable + amount2++; + if( slots < amount2 ) + fail = 1; + } + else {// non-stackable + amount2 += amount; + if( slots < amount2 ){ + fail = 1; + } + } + break; + case ADDITEM_OVERAMOUNT: + fail = 1; + } //end switch + } //end loop DO NOT break it prematurly we need to depop all stack + + fail?script_pushint(st,0):script_pushint(st,1); + return 0; } /*========================================== @@ -6432,7 +6529,7 @@ BUILDIN_FUNC(rentitem) clif_additem(sd, 0, 0, flag); return 1; } - + return 0; } @@ -6453,9 +6550,9 @@ BUILDIN_FUNC(getnameditem) if (sd == NULL) { //Player not attached! script_pushint(st,0); - return 0; + return 0; } - + data=script_getdata(st,2); get_val(st,data); if( data_isstring(data) ){ @@ -6482,7 +6579,7 @@ BUILDIN_FUNC(getnameditem) tsd=map_nick2sd(conv_str(st,data)); else //Char Id was given tsd=map_charid2sd(conv_num(st,data)); - + if( tsd == NULL ) { //Failed script_pushint(st,0); @@ -6944,7 +7041,7 @@ BUILDIN_FUNC(getcharid) script_pushint(st,0); break; } - + return 0; } /*========================================== @@ -7017,7 +7114,7 @@ BUILDIN_FUNC(getpartymember) if( script_hasdata(st,3) ) type=script_getnum(st,3); - + if(p!=NULL){ for(i=0;i<MAX_PARTY;i++){ if(p->party.member[i].account_id){ @@ -7041,7 +7138,7 @@ BUILDIN_FUNC(getpartymember) } /*========================================== - * Retrieves party leader. if flag is specified, + * Retrieves party leader. if flag is specified, * return some of the leader data. Otherwise, return name. *------------------------------------------*/ BUILDIN_FUNC(getpartyleader) @@ -7282,7 +7379,7 @@ BUILDIN_FUNC(getequipid) script_pushint(st,-1); return 0; } - + item = sd->inventory_data[i]; if( item != 0 ) script_pushint(st,item->nameid); @@ -7445,8 +7542,8 @@ BUILDIN_FUNC(getequipisequiped) /*========================================== * Chk if the player have something equiped at pos * if so chk if this item ain't marked not refinable or rental - * return (npc) - * 1 : true + * return (npc) + * 1 : true * 0 : false *------------------------------------------*/ BUILDIN_FUNC(getequipisenableref) @@ -7471,8 +7568,8 @@ BUILDIN_FUNC(getequipisenableref) /*========================================== * Chk if the item equiped at pos is identify (huh ?) - * return (npc) - * 1 : true + * return (npc) + * 1 : true * 0 : false *------------------------------------------*/ BUILDIN_FUNC(getequipisidentify) @@ -7497,8 +7594,8 @@ BUILDIN_FUNC(getequipisidentify) /*========================================== * Get the item refined value at pos - * return (npc) - * x : refine amount + * return (npc) + * x : refine amount * 0 : false (not refined) *------------------------------------------*/ BUILDIN_FUNC(getequiprefinerycnt) @@ -7524,8 +7621,8 @@ BUILDIN_FUNC(getequiprefinerycnt) /*========================================== * Get the weapon level value at pos * (pos should normally only be EQI_HAND_L or EQI_HAND_R) - * return (npc) - * x : weapon level + * return (npc) + * x : weapon level * 0 : false *------------------------------------------*/ BUILDIN_FUNC(getequipweaponlv) @@ -7550,7 +7647,7 @@ BUILDIN_FUNC(getequipweaponlv) /*========================================== * Get the item refine chance (from refine.txt) for item at pos - * return (npc) + * return (npc) * x : refine chance * 0 : false (max refine level or unequip..) *------------------------------------------*/ @@ -7645,11 +7742,11 @@ BUILDIN_FUNC(failedrefitem) i=pc_checkequip(sd,equip[num-1]); if(i >= 0) { sd->status.inventory[i].refine = 0; - pc_unequipitem(sd,i,3); //recalculate bonus + pc_unequipitem(sd,i,3); //recalculate bonus clif_refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); - + clif_misceffect(&sd->bl,2); // display failure effect } @@ -8050,7 +8147,7 @@ BUILDIN_FUNC(getgdskilllv) } /// Returns the 'basic_skill_check' setting. -/// This config determines if the server checks the skill level of NV_BASIC +/// This config determines if the server checks the skill level of NV_BASIC /// before allowing the basic actions. /// /// basicskillcheck() -> <bool> @@ -8432,7 +8529,7 @@ BUILDIN_FUNC(gettimetick) /* Asgard Version */ type=script_getnum(st,2); switch(type){ - case 2: + case 2: //type 2:(Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC // from the system clock.) script_pushint(st,(int)time(NULL)); @@ -8706,7 +8803,7 @@ BUILDIN_FUNC(guildchangegm) /*========================================== * Spawn a monster : - @mapn,x,y : location + @mapn,x,y : location @str : monster name @class_ : mob_id @amount : nb to spawn @@ -8732,7 +8829,7 @@ BUILDIN_FUNC(monster) event = script_getstr(st, 8); check_event(st, event); } - + if (script_hasdata(st, 9)) { size = script_getnum(st, 9); @@ -8742,7 +8839,7 @@ BUILDIN_FUNC(monster) return 1; } } - + if (script_hasdata(st, 10)) { ai = script_getnum(st, 10); @@ -8839,7 +8936,7 @@ BUILDIN_FUNC(areamonster) event = script_getstr(st, 10); check_event(st, event); } - + if (script_hasdata(st, 11)) { size = script_getnum(st, 11); @@ -8849,7 +8946,7 @@ BUILDIN_FUNC(areamonster) return 1; } } - + if (script_hasdata(st, 12)) { ai = script_getnum(st, 12); @@ -8876,7 +8973,7 @@ BUILDIN_FUNC(areamonster) } } } - + mob_once_spawn_area(sd, m, x0, y0, x1, y1, str, class_, amount, event, size, ai); return 0; } @@ -8890,7 +8987,7 @@ BUILDIN_FUNC(areamonster) int allflag=va_arg(ap,int); md->state.npc_killmonster = 1; - + if(!allflag){ if(strcmp(event,md->npc_event)==0) status_kill(bl); @@ -8929,7 +9026,7 @@ BUILDIN_FUNC(killmonster) if( (m=map_mapname2mapid(mapname))<0 ) return 0; - + if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) return 0; @@ -8939,7 +9036,7 @@ BUILDIN_FUNC(killmonster) return 0; } } - + map_freeblock_lock(); map_foreachinmap(buildin_killmonster_sub_strip, m, BL_MOB, event ,allflag); map_freeblock_unlock(); @@ -8949,11 +9046,11 @@ BUILDIN_FUNC(killmonster) static int buildin_killmonsterall_sub_strip(struct block_list *bl,va_list ap) { //Strips the event from the mob if it's killed the old method. struct mob_data *md; - + md = BL_CAST(BL_MOB, bl); if (md->npc_event[0]) md->npc_event[0] = 0; - + status_kill(bl); return 0; } @@ -8967,7 +9064,7 @@ BUILDIN_FUNC(killmonsterall) const char *mapname; int m; mapname=script_getstr(st,2); - + if( (m = map_mapname2mapid(mapname))<0 ) return 0; @@ -8980,7 +9077,7 @@ BUILDIN_FUNC(killmonsterall) return 0; } } - + map_foreachinmap(buildin_killmonsterall_sub_strip,m,BL_MOB); return 0; } @@ -9010,7 +9107,7 @@ BUILDIN_FUNC(clone) if( script_hasdata(st,9) ) flag=script_getnum(st,9); - + if( script_hasdata(st,10) ) duration=script_getnum(st,10); @@ -9036,7 +9133,6 @@ BUILDIN_FUNC(clone) return 0; } /*========================================== - * イベント実行 *------------------------------------------*/ BUILDIN_FUNC(doevent) { @@ -9053,7 +9149,6 @@ BUILDIN_FUNC(doevent) return 0; } /*========================================== - * NPC主体イベント実行 *------------------------------------------*/ BUILDIN_FUNC(donpcevent) { @@ -9082,7 +9177,6 @@ BUILDIN_FUNC(cmdothernpc) // Added by RoVeRT } /*========================================== - * イベントタイマー追加 *------------------------------------------*/ BUILDIN_FUNC(addtimer) { @@ -9099,7 +9193,6 @@ BUILDIN_FUNC(addtimer) return 0; } /*========================================== - * イベントタイマー削除 *------------------------------------------*/ BUILDIN_FUNC(deltimer) { @@ -9116,7 +9209,6 @@ BUILDIN_FUNC(deltimer) return 0; } /*========================================== - * イベントタイマーのカウント値追加 *------------------------------------------*/ BUILDIN_FUNC(addtimercount) { @@ -9136,7 +9228,6 @@ BUILDIN_FUNC(addtimercount) } /*========================================== - * NPCタイマー初期化 *------------------------------------------*/ BUILDIN_FUNC(initnpctimer) { @@ -9185,7 +9276,6 @@ BUILDIN_FUNC(initnpctimer) return 0; } /*========================================== - * NPCタイマー開始 *------------------------------------------*/ BUILDIN_FUNC(startnpctimer) { @@ -9232,7 +9322,6 @@ BUILDIN_FUNC(startnpctimer) return 0; } /*========================================== - * NPCタイマー停止 *------------------------------------------*/ BUILDIN_FUNC(stopnpctimer) { @@ -9274,7 +9363,6 @@ BUILDIN_FUNC(stopnpctimer) return 0; } /*========================================== - * NPCタイマー情報所得 *------------------------------------------*/ BUILDIN_FUNC(getnpctimer) { @@ -9287,7 +9375,7 @@ BUILDIN_FUNC(getnpctimer) nd = npc_name2id(script_getstr(st,3)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( !nd || nd->bl.type != BL_NPC ) { script_pushint(st,0); @@ -9319,7 +9407,6 @@ BUILDIN_FUNC(getnpctimer) return 0; } /*========================================== - * NPCタイマー値設定 *------------------------------------------*/ BUILDIN_FUNC(setnpctimer) { @@ -9415,7 +9502,6 @@ BUILDIN_FUNC(playerattached) } /*========================================== - * 天の声アナウンス *------------------------------------------*/ BUILDIN_FUNC(announce) { @@ -9426,14 +9512,14 @@ BUILDIN_FUNC(announce) int fontSize = script_hasdata(st,6) ? script_getnum(st,6) : 12; // default fontSize int fontAlign = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontAlign int fontY = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontY - + if (flag&0x0f) // Broadcast source or broadcast region defined { send_target target; struct block_list *bl = (flag&0x08) ? map_id2bl(st->oid) : (struct block_list *)script_rid2sd(st); // If bc_npc flag is set, use NPC as broadcast source if (bl == NULL) return 0; - + flag &= 0x07; target = (flag == 1) ? ALL_SAMEMAP : (flag == 2) ? AREA : @@ -9454,7 +9540,6 @@ BUILDIN_FUNC(announce) return 0; } /*========================================== - * 天の声アナウンス(特定マップ) *------------------------------------------*/ static int buildin_announce_sub(struct block_list *bl, va_list ap) { @@ -9493,7 +9578,6 @@ BUILDIN_FUNC(mapannounce) return 0; } /*========================================== - * 天の声アナウンス(特定エリア) *------------------------------------------*/ BUILDIN_FUNC(areaannounce) { @@ -9520,7 +9604,6 @@ BUILDIN_FUNC(areaannounce) } /*========================================== - * ユーザー数所得 *------------------------------------------*/ BUILDIN_FUNC(getusers) { @@ -9583,7 +9666,7 @@ BUILDIN_FUNC(getusersname) clif_scriptmes(sd,st->oid,pl_sd->status.name); } mapit_free(iter); - + return 0; } /*========================================== @@ -9615,7 +9698,6 @@ BUILDIN_FUNC(getmapguildusers) return 0; } /*========================================== - * マップ指定ユーザー数所得 *------------------------------------------*/ BUILDIN_FUNC(getmapusers) { @@ -9630,7 +9712,6 @@ BUILDIN_FUNC(getmapusers) return 0; } /*========================================== - * エリア指定ユーザー数所得 *------------------------------------------*/ static int buildin_getareausers_sub(struct block_list *bl,va_list ap) { @@ -9658,7 +9739,6 @@ BUILDIN_FUNC(getareausers) } /*========================================== - * エリア指定ドロップアイテム数所得 *------------------------------------------*/ static int buildin_getareadropitem_sub(struct block_list *bl,va_list ap) { @@ -9704,7 +9784,6 @@ BUILDIN_FUNC(getareadropitem) return 0; } /*========================================== - * NPCの有効化 *------------------------------------------*/ BUILDIN_FUNC(enablenpc) { @@ -9714,7 +9793,6 @@ BUILDIN_FUNC(enablenpc) return 0; } /*========================================== - * NPCの無効化 *------------------------------------------*/ BUILDIN_FUNC(disablenpc) { @@ -9725,7 +9803,6 @@ BUILDIN_FUNC(disablenpc) } /*========================================== - * 隠れているNPCの表示 *------------------------------------------*/ BUILDIN_FUNC(hideoffnpc) { @@ -9735,7 +9812,6 @@ BUILDIN_FUNC(hideoffnpc) return 0; } /*========================================== - * NPCをハイディング *------------------------------------------*/ BUILDIN_FUNC(hideonnpc) { @@ -9875,7 +9951,7 @@ BUILDIN_FUNC(sc_end) bl = map_id2bl(script_getnum(st,3)); else bl = map_id2bl(st->rid); - + if( potion_flag==1 && potion_target ) {//##TODO how does this work [FlavioJS] bl = map_id2bl(potion_target); @@ -9945,7 +10021,7 @@ BUILDIN_FUNC(getstatus) script_pushint(st, 0); return 0; } - + switch( type ) { case 1: script_pushint(st, sd->sc.data[id]->val1); break; @@ -9980,7 +10056,6 @@ BUILDIN_FUNC(debugmes) } /*========================================== - *捕獲アイテム使用 *------------------------------------------*/ BUILDIN_FUNC(catchpet) { @@ -10038,7 +10113,7 @@ BUILDIN_FUNC(homunculus_mutate) if(merc_is_hom_active(sd->hd)) { m_class = hom_class2mapid(sd->hd->homunculus.class_); m_id = hom_class2mapid(homun_id); - + if ( m_class != -1 && m_id != -1 && m_class&HOM_EVO && m_id&HOM_S && sd->hd->homunculus.level >= 99 ) hom_mutate(sd->hd, homun_id); else @@ -10119,6 +10194,11 @@ BUILDIN_FUNC(birthpet) /*========================================== * Added - AppleGirl For Advanced Classes, (Updated for Cleaner Script Purposes) + * @type + * 1 : make like after rebirth + * 2 : blvl,jlvl=1, skillpoint=0 + * 3 : don't reset skill, blvl=1 + * 4 : jlvl=0 *------------------------------------------*/ BUILDIN_FUNC(resetlvl) { @@ -10134,7 +10214,7 @@ BUILDIN_FUNC(resetlvl) return 0; } /*========================================== - * ステータスリセット + * Reset a player status point *------------------------------------------*/ BUILDIN_FUNC(resetstatus) { @@ -10187,7 +10267,7 @@ BUILDIN_FUNC(changebase) { if (!battle_config.wedding_modifydisplay || //Do not show the wedding sprites sd->class_&JOBL_BABY //Baby classes screw up when showing wedding sprites. [Skotlex] They don't seem to anymore. - ) + ) return 0; } @@ -10232,7 +10312,7 @@ BUILDIN_FUNC(globalmes) mes=script_getstr(st,2); if(mes==NULL) return 0; - + if(script_hasdata(st,3)){ // npc name to display name=script_getstr(st,3); } else { @@ -10528,7 +10608,7 @@ BUILDIN_FUNC(setmapflagnosave) y=script_getnum(st,5); m = map_mapname2mapid(str); mapindex = mapindex_name2id(str2); - + if(m >= 0 && mapindex) { map[m].flag.nosave=1; map[m].save.map=mapindex; @@ -10858,7 +10938,7 @@ BUILDIN_FUNC(pvpoff) if(battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris] return 0; - + map_foreachinmap(buildin_pvpoff_sub, m, BL_PC); return 0; } @@ -10900,14 +10980,14 @@ BUILDIN_FUNC(emotion) { int type; int player=0; - + type=script_getnum(st,2); if(type < 0 || type > 100) return 0; if( script_hasdata(st,3) ) player=script_getnum(st,3); - + if (player) { TBL_PC *sd = NULL; if( script_hasdata(st,4) ) @@ -11125,7 +11205,6 @@ BUILDIN_FUNC(setcastledata) } /* ===================================================================== - * ?ソスM?ソス?ソス?ソスh?ソス?ソス?ソス?ソスv?ソス?ソス?ソス?ソス?ソス?ソス * ---------------------------------------------------------------------*/ BUILDIN_FUNC(requestguildinfo) { @@ -11191,7 +11270,7 @@ BUILDIN_FUNC(successremovecards) { return 0; } - if(itemdb_isspecial(sd->status.inventory[i].card[0])) + if(itemdb_isspecial(sd->status.inventory[i].card[0])) return 0; for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { @@ -11214,7 +11293,7 @@ BUILDIN_FUNC(successremovecards) { int flag; struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - + item_tmp.nameid = sd->status.inventory[i].nameid; item_tmp.identify = 1; item_tmp.refine = sd->status.inventory[i].refine; @@ -11261,12 +11340,12 @@ BUILDIN_FUNC(failedremovecards) { if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) { cardflag = 1; - if(typefail == 2) {// add cards to inventory, clear + if(typefail == 2) {// add cards to inventory, clear int flag; struct item item_tmp; - + memset(&item_tmp,0,sizeof(item_tmp)); - + item_tmp.nameid = sd->status.inventory[i].card[c]; item_tmp.identify = 1; @@ -11285,9 +11364,9 @@ BUILDIN_FUNC(failedremovecards) { if(typefail == 1){ // destroy the card int flag; struct item item_tmp; - + memset(&item_tmp,0,sizeof(item_tmp)); - + item_tmp.nameid = sd->status.inventory[i].nameid; item_tmp.identify = 1; item_tmp.refine = sd->status.inventory[i].refine; @@ -11296,7 +11375,7 @@ BUILDIN_FUNC(failedremovecards) { for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) item_tmp.card[j]=sd->status.inventory[i].card[j]; - + pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ @@ -11402,7 +11481,7 @@ BUILDIN_FUNC(mobcount) // Added by RoVeRT script_pushint(st,-1); return 0; } - + if( map[m].flag.src4instance && map[m].instance_id == 0 && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) { script_pushint(st,-1); @@ -11621,7 +11700,7 @@ BUILDIN_FUNC(setwall) const char *map, *name; int x, y, m, size, dir; bool shootable; - + map = script_getstr(st,2); x = script_getnum(st,3); y = script_getnum(st,4); @@ -11897,7 +11976,7 @@ BUILDIN_FUNC(petloot) int max; struct pet_data *pd; TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || sd->pd==NULL) return 0; @@ -11907,7 +11986,7 @@ BUILDIN_FUNC(petloot) max = 1; //Let'em loot at least 1 item. else if (max > MAX_PETLOOT_SIZE) max = MAX_PETLOOT_SIZE; - + pd = sd->pd; if (pd->loot != NULL) { //Release whatever was there already and reallocate memory @@ -11918,7 +11997,7 @@ BUILDIN_FUNC(petloot) pd->loot = (struct pet_loot *)aMalloc(sizeof(struct pet_loot)); pd->loot->item = (struct item *)aCalloc(max,sizeof(struct item)); - + pd->loot->max=max; pd->loot->count = 0; pd->loot->weight = 0; @@ -11927,7 +12006,7 @@ BUILDIN_FUNC(petloot) } /*========================================== * Set arrays with info of all sd inventory : - * @inventorylist_id, @inventorylist_amount, @inventorylist_equip, + * @inventorylist_id, @inventorylist_amount, @inventorylist_equip, * @inventorylist_refine, @inventorylist_identify, @inventorylist_attribute, * @inventorylist_card(0..3), @inventorylist_expire * @inventorylist_count = scalar @@ -11936,7 +12015,7 @@ BUILDIN_FUNC(getinventorylist) { TBL_PC *sd=script_rid2sd(st); char card_var[NAME_LENGTH]; - + int i,j=0,k; if(!sd) return 0; for(i=0;i<MAX_INVENTORY;i++){ @@ -12028,7 +12107,7 @@ BUILDIN_FUNC(undisguise) } /*========================================== - * Transform a bl to another _class, + * Transform a bl to another _class, * @type unused *------------------------------------------*/ BUILDIN_FUNC(classchange) @@ -12215,14 +12294,14 @@ BUILDIN_FUNC(petrecovery) return 0; pd=sd->pd; - + if (pd->recovery) { //Halt previous bonus if (pd->recovery->timer != INVALID_TIMER) delete_timer(pd->recovery->timer, pet_recovery_timer); } else //Init pd->recovery = (struct pet_recovery *)aMalloc(sizeof(struct pet_recovery)); - + pd->recovery->type = (sc_type)script_getnum(st,2); pd->recovery->delay = script_getnum(st,3); pd->recovery->timer = INVALID_TIMER; @@ -12252,8 +12331,8 @@ BUILDIN_FUNC(petheal) delete_timer(pd->s_skill->timer, pet_heal_timer); } } else //init memory - pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); - + pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); + pd->s_skill->id=0; //This id identifies that it IS petheal rather than pet_skillsupport //Use the lv as the amount to heal pd->s_skill->lv=script_getnum(st,2); @@ -12286,7 +12365,7 @@ BUILDIN_FUNC(petskillattack) pd=sd->pd; if (pd->a_skill == NULL) pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack)); - + pd->a_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); pd->a_skill->lv=script_getnum(st,3); pd->a_skill->div_ = 0; @@ -12312,7 +12391,7 @@ BUILDIN_FUNC(petskillattack2) pd=sd->pd; if (pd->a_skill == NULL) pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack)); - + pd->a_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); pd->a_skill->lv=script_getnum(st,3); pd->a_skill->div_ = script_getnum(st,4); @@ -12346,8 +12425,8 @@ BUILDIN_FUNC(petskillsupport) delete_timer(pd->s_skill->timer, pet_heal_timer); } } else //init memory - pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); - + pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); + pd->s_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); pd->s_skill->lv=script_getnum(st,3); pd->s_skill->delay=script_getnum(st,4); @@ -12546,7 +12625,7 @@ BUILDIN_FUNC(recovery) return 0; } /*========================================== - * Get your pet info: getpetinfo(n) + * Get your pet info: getpetinfo(n) * n -> 0:pet_id 1:pet_class 2:pet_name * 3:friendly 4:hungry, 5: rename flag. *------------------------------------------*/ @@ -12555,7 +12634,7 @@ BUILDIN_FUNC(getpetinfo) TBL_PC *sd=script_rid2sd(st); TBL_PET *pd; int type=script_getnum(st,2); - + if(!sd || !sd->pd) { if (type == 2) script_pushconststr(st,"null"); @@ -12579,7 +12658,7 @@ BUILDIN_FUNC(getpetinfo) } /*========================================== - * Get your homunculus info: gethominfo(n) + * Get your homunculus info: gethominfo(n) * n -> 0:hom_id 1:class 2:name * 3:friendly 4:hungry, 5: rename flag. * 6: level @@ -13005,7 +13084,7 @@ BUILDIN_FUNC(getmapxy) x= bl->x; y= bl->y; safestrncpy(mapname, map[bl->m].name, MAP_NAME_LENGTH); - + //Set MapName$ num=st->stack->stack_data[st->start+2].u.num; name=get_str(num&0x00ffffff); @@ -13071,7 +13150,7 @@ BUILDIN_FUNC(summon) sd=script_rid2sd(st); if (!sd) return 0; - + str =script_getstr(st,2); _class=script_getnum(st,3); if( script_hasdata(st,4) ) @@ -13127,12 +13206,12 @@ BUILDIN_FUNC(isequippedcnt) script_pushint(st,0); return 0; } - + for (i=0; id!=0; i++) { FETCH (i+2, id) else id = 0; if (id <= 0) continue; - + for (j=0; j<EQI_MAX; j++) { int index; index = sd->equip_index[j]; @@ -13140,7 +13219,7 @@ BUILDIN_FUNC(isequippedcnt) if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; - + if(!sd->inventory_data[index]) continue; @@ -13151,13 +13230,13 @@ BUILDIN_FUNC(isequippedcnt) if (itemdb_isspecial(sd->status.inventory[index].card[0])) continue; //No cards for(k=0; k<sd->inventory_data[index]->slot; k++) { - if (sd->status.inventory[index].card[k] == id) + if (sd->status.inventory[index].card[k] == id) ret++; //[Lupus] } } } } - + script_pushint(st,ret); return 0; } @@ -13178,7 +13257,7 @@ BUILDIN_FUNC(isequipped) unsigned int setitem_hash = 0, setitem_hash2 = 0; sd = script_rid2sd(st); - + if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... script_pushint(st,0); return 0; @@ -13197,10 +13276,10 @@ BUILDIN_FUNC(isequipped) if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; - + if(!sd->inventory_data[index]) continue; - + if (itemdb_type(id) != IT_CARD) { if (sd->inventory_data[index]->nameid != id) continue; @@ -13260,15 +13339,15 @@ BUILDIN_FUNC(cardscnt) int index; sd = script_rid2sd(st); - + for (i=0; id!=0; i++) { FETCH (i+2, id) else id = 0; if (id <= 0) continue; - + index = current_equip_item_index; //we get CURRENT WEAPON inventory index from status.c [Lupus] if(index < 0) continue; - + if(!sd->inventory_data[index]) continue; @@ -13387,7 +13466,7 @@ BUILDIN_FUNC(setbattleflag) flag = script_getstr(st,2); value = script_getstr(st,3); // HACK: Retrieve number as string (auto-converted) for battle_set_value - + if (battle_set_value(flag, value) == 0) ShowWarning("buildin_setbattleflag: unknown battle_config flag '%s'\n",flag); else @@ -13465,7 +13544,7 @@ BUILDIN_FUNC(charislower) BUILDIN_FUNC(charat) { const char *str = script_getstr(st,2); int pos = script_getnum(st,3); - + if( pos >= 0 && (unsigned int)pos < strlen(str) ) { char output[2]; output[0] = str[pos]; @@ -13598,7 +13677,7 @@ BUILDIN_FUNC(substr) len = end - start + 1; output = (char*)aMalloc(len + 1); memcpy(output, &str[start], len); - } else + } else output = (char*)aMalloc(1); output[len] = '\0'; @@ -13620,7 +13699,7 @@ BUILDIN_FUNC(explode) size_t len = strlen(str); int i = 0, j = 0; int start; - + char *temp; const char* name; @@ -14065,8 +14144,8 @@ BUILDIN_FUNC(strpos) { //=============================================================== // replacestr <input>, <search>, <replace>{, <usecase>{, <count>}} // -// Note: Finds all instances of <search> in <input> and replaces -// with <replace>. If specified will only replace as many +// Note: Finds all instances of <search> in <input> and replaces +// with <replace>. If specified will only replace as many // instances as specified in <count>. By default will be case // sensitive. //--------------------------------------------------------------- @@ -14151,7 +14230,7 @@ BUILDIN_FUNC(replacestr) //======================================================== // countstr <input>, <search>{, <usecase>} // -// Note: Counts the number of times <search> occurs in +// Note: Counts the number of times <search> occurs in // <input>. By default will be case sensitive. //-------------------------------------------------------- BUILDIN_FUNC(countstr) @@ -14362,7 +14441,7 @@ BUILDIN_FUNC(setd) } else { setd_sub(st, sd, varname, elem, (void *)__64BPRTSIZE(script_getnum(st, 3)), NULL); } - + return 0; } @@ -14450,7 +14529,7 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) // Free data Sql_FreeResult(handle); script_pushint(st, i); - + return 0; } @@ -14462,7 +14541,7 @@ BUILDIN_FUNC(query_sql) { st->state = RERUNLINE;/* will continue when the query is finished running. */ } else st->state = RUN; - + return 0; #else return buildin_query_sql_sub(st, mmysql_handle); @@ -14478,12 +14557,12 @@ BUILDIN_FUNC(query_logsql) { #ifdef BETA_THREAD_TEST if( st->state != RERUNLINE ) { queryThread_add(st,true); - + st->state = RERUNLINE;/* will continue when the query is finished running. */ } else st->state = RUN; - - return 0; + + return 0; #else return buildin_query_sql_sub(st, logmysql_handle); #endif @@ -14571,7 +14650,7 @@ BUILDIN_FUNC(callshop) script_pushint(st,0); return 1; } - + if( nd->subtype == SHOP ) { // flag the user as using a valid script call for opening the shop (for floating NPCs) @@ -15124,7 +15203,7 @@ BUILDIN_FUNC(unitwarp) mapname = script_getstr(st, 3); x = (short)script_getnum(st,4); y = (short)script_getnum(st,5); - + if (!unit_id) //Warp the script's runner bl = map_id2bl(st->rid); else @@ -15144,7 +15223,7 @@ BUILDIN_FUNC(unitwarp) } /// Makes the unit attack the target. -/// If the unit is a player and <action type> is not 0, it does a continuous +/// If the unit is a player and <action type> is not 0, it does a continuous /// attack instead of a single attack. /// Returns if the request was successfull. /// @@ -15163,7 +15242,7 @@ BUILDIN_FUNC(unitattack) script_pushint(st, 0); return 0; } - + data = script_getdata(st, 3); get_val(st, data); if( data_isstring(data) ) @@ -15179,7 +15258,7 @@ BUILDIN_FUNC(unitattack) script_pushint(st, 0); return 0; } - + // get actiontype if( script_hasdata(st,4) ) actiontype = script_getnum(st,4); @@ -15332,7 +15411,7 @@ BUILDIN_FUNC(unitskillusepos) BUILDIN_FUNC(sleep) { int ticks; - + ticks = script_getnum(st,2); // detach the player @@ -15361,7 +15440,7 @@ BUILDIN_FUNC(sleep) BUILDIN_FUNC(sleep2) { int ticks; - + ticks = script_getnum(st,2); if( ticks <= 0 ) @@ -15593,7 +15672,7 @@ BUILDIN_FUNC(mercenary_create) if( (sd = script_rid2sd(st)) == NULL || sd->md || sd->status.mer_id != 0 ) return 0; - + class_ = script_getnum(st,2); if( !merc_class(class_) ) @@ -15992,7 +16071,7 @@ BUILDIN_FUNC(bg_monster_set_team) struct block_list *mbl; int id = script_getnum(st,2), bg_id = script_getnum(st,3); - + if( (mbl = map_id2bl(id)) == NULL || mbl->type != BL_MOB ) return 0; md = (TBL_MOB *)mbl; @@ -16011,7 +16090,7 @@ BUILDIN_FUNC(bg_leave) struct map_session_data *sd = script_rid2sd(st); if( sd == NULL || !sd->bg_id ) return 0; - + bg_team_leave(sd,0); return 0; } @@ -16129,7 +16208,7 @@ BUILDIN_FUNC(instance_create) script_pushint(st, -2); return 0; } - + script_pushint(st, res); return 0; } @@ -16164,7 +16243,7 @@ BUILDIN_FUNC(instance_attachmap) int m; int instance_id; bool usebasename = false; - + name = script_getstr(st,2); instance_id = script_getnum(st,3); if( script_hasdata(st,4) && script_getnum(st,4) > 0) @@ -16177,7 +16256,7 @@ BUILDIN_FUNC(instance_attachmap) return 0; } script_pushconststr(st, map[m].name); - + return 0; } @@ -16187,7 +16266,7 @@ BUILDIN_FUNC(instance_detachmap) struct party_data *p; const char *str; int m, instance_id; - + str = script_getstr(st, 2); if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); @@ -16196,7 +16275,7 @@ BUILDIN_FUNC(instance_detachmap) else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) instance_id = p->instance_id; else return 0; - + if( (m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m,instance_id)) < 0 ) { ShowError("buildin_instance_detachmap: Trying to detach invalid map %s\n", str); @@ -16210,11 +16289,11 @@ BUILDIN_FUNC(instance_detachmap) BUILDIN_FUNC(instance_attach) { int instance_id; - + instance_id = script_getnum(st, 2); if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) return 0; - + st->instance_id = instance_id; return 0; } @@ -16224,7 +16303,7 @@ BUILDIN_FUNC(instance_id) int type, instance_id; struct map_session_data *sd; struct party_data *p; - + if( script_hasdata(st, 2) ) { type = script_getnum(st, 2); @@ -16248,7 +16327,7 @@ BUILDIN_FUNC(instance_set_timeout) int instance_id; struct map_session_data *sd; struct party_data *p; - + progress_timeout = script_getnum(st, 2); idle_timeout = script_getnum(st, 3); @@ -16262,7 +16341,7 @@ BUILDIN_FUNC(instance_set_timeout) if( instance_id > 0 ) instance_set_timeout(instance_id, progress_timeout, idle_timeout); - + return 0; } @@ -16306,7 +16385,7 @@ BUILDIN_FUNC(instance_announce) if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) return 0; - + for( i = 0; i < instance[instance_id].num_map; i++ ) map_foreachinmap(buildin_announce_sub, instance[instance_id].map[i], BL_PC, mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); @@ -16322,7 +16401,7 @@ BUILDIN_FUNC(instance_npcname) struct map_session_data *sd; struct party_data *p; struct npc_data *nd; - + str = script_getstr(st, 2); if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); @@ -16353,7 +16432,7 @@ BUILDIN_FUNC(has_instance) struct party_data *p; const char *str; int m, instance_id = 0; - + str = script_getstr(st, 2); if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); @@ -16443,21 +16522,21 @@ BUILDIN_FUNC(instance_check_party) } for( i = 0; i < MAX_PARTY; i++ ) - if( (pl_sd = p->data[i].sd) ) - if(map_id2bl(pl_sd->bl.id)){ + if( (pl_sd = p->data[i].sd) ) + if(map_id2bl(pl_sd->bl.id)){ if(pl_sd->status.base_level < min){ script_pushint(st, 0); - return 0; + return 0; }else if(pl_sd->status.base_level > max){ script_pushint(st, 0); return 0; } c++; } - + if(c < amount){ script_pushint(st, 0); // Not enough Members in the Party to join Instance. - }else + }else script_pushint(st, 1); return 0; @@ -16477,7 +16556,7 @@ BUILDIN_FUNC(setfont) sd->user_font = font; else sd->user_font = 0; - + clif_font(sd); return 0; } @@ -16551,7 +16630,7 @@ BUILDIN_FUNC(areamobuseskill) cancel = script_getnum(st,10); emotion = script_getnum(st,11); target = script_getnum(st,12); - + map_foreachinrange(buildin_mobuseskill_sub, ¢er, range, BL_MOB, mobid, skillid, skilllv, casttime, cancel, emotion, target); return 0; } @@ -16858,19 +16937,19 @@ BUILDIN_FUNC(bindatcmd) { const char* eventName; int i, level = 0, level2 = 0; bool create = false; - + atcmd = script_getstr(st,2); eventName = script_getstr(st,3); if( *atcmd == atcommand_symbol || *atcmd == charcommand_symbol ) atcmd++; - + if( script_hasdata(st,4) ) level = script_getnum(st,4); if( script_hasdata(st,5) ) level2 = script_getnum(st,5); if( atcmd_binding_count == 0 ) { CREATE(atcmd_binding,struct atcmd_binding_data*,1); - + create = true; } else { ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command,atcmd) == 0); @@ -16881,21 +16960,21 @@ BUILDIN_FUNC(bindatcmd) { } else create = true; } - + if( create ) { i = atcmd_binding_count; - + if( atcmd_binding_count++ != 0 ) RECREATE(atcmd_binding,struct atcmd_binding_data*,atcmd_binding_count); - + CREATE(atcmd_binding[i],struct atcmd_binding_data,1); - + safestrncpy(atcmd_binding[i]->command, atcmd, 50); safestrncpy(atcmd_binding[i]->npc_event, eventName, 50); atcmd_binding[i]->level = level; atcmd_binding[i]->level2 = level2; } - + return 0; } @@ -16907,12 +16986,12 @@ BUILDIN_FUNC(unbindatcmd) { if( *atcmd == atcommand_symbol || *atcmd == charcommand_symbol ) atcmd++; - + if( atcmd_binding_count == 0 ) { script_pushint(st, 0); return 0; } - + ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, atcmd) == 0); if( i < atcmd_binding_count ) { int cursor = 0; @@ -16922,21 +17001,21 @@ BUILDIN_FUNC(unbindatcmd) { for( i = 0, cursor = 0; i < atcmd_binding_count; i++ ) { if( atcmd_binding[i] == NULL ) continue; - + if( cursor != i ) { memmove(&atcmd_binding[cursor], &atcmd_binding[i], sizeof(struct atcmd_binding_data*)); } - + cursor++; } if( (atcmd_binding_count = cursor) == 0 ) aFree(atcmd_binding); - + script_pushint(st, 1); } else script_pushint(st, 0);/* not found */ - + return 0; } @@ -17048,10 +17127,10 @@ BUILDIN_FUNC(getrandgroupitem) { TBL_PC* sd; int i, get_count = 0, flag, nameid, group = script_getnum(st, 2), qty = script_getnum(st,3); struct item item_tmp; - + if( !( sd = script_rid2sd(st) ) ) return 0; - + if( qty <= 0 ) { ShowError("getrandgroupitem: qty is <= 0!\n"); return 1; @@ -17059,18 +17138,18 @@ BUILDIN_FUNC(getrandgroupitem) { if( (nameid = itemdb_searchrandomid(group)) == UNKNOWN_ITEM_ID ) { return 1;/* itemdb_searchrandomid will already scream a error */ } - + memset(&item_tmp,0,sizeof(item_tmp)); - + item_tmp.nameid = nameid; item_tmp.identify = itemdb_isidentified(nameid); - + //Check if it's stackable. if (!itemdb_isstackable(nameid)) get_count = 1; else get_count = qty; - + for (i = 0; i < qty; i += get_count) { // if not pet egg if (!pet_create_egg(sd, nameid)) { @@ -17081,7 +17160,7 @@ BUILDIN_FUNC(getrandgroupitem) { } } } - + return 0; } @@ -17146,7 +17225,8 @@ struct script_function buildin_func[] = { BUILDIN_DEF(rand,"i?"), BUILDIN_DEF(countitem,"v"), BUILDIN_DEF(countitem2,"viiiiiii"), - BUILDIN_DEF(checkweight,"vi"), + BUILDIN_DEF(checkweight,"vi*"), + BUILDIN_DEF(checkweight2,"rr"), BUILDIN_DEF(readparam,"i?"), BUILDIN_DEF(getcharid,"i?"), BUILDIN_DEF(getnpcid,"i?"), |