diff options
-rw-r--r-- | Changelog-Trunk.txt | 16 | ||||
-rw-r--r-- | doc/script_commands.txt | 33 | ||||
-rw-r--r-- | src/common/socket.c | 2 | ||||
-rw-r--r-- | src/map/log.c | 8 | ||||
-rw-r--r-- | src/map/log.h | 17 | ||||
-rw-r--r-- | src/map/script.c | 182 |
6 files changed, 170 insertions, 88 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 5cf0d96af..d4637634f 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,9 +3,21 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +2006/12/31 + * Updated getitem and guardian entries in script_commands.txt. + * Fixed getitem trying to get <character ID> from the wrong argument. + * Now getitem can be run on scripts without a player attached if + <character ID> is specified. + * Now the two last arguments of guardian are optional and independant of + each other ("<event label>" and <guardian index>). This way the previous + implementation and script_commands definition are still valid code. + * Now buildin function names and argument definitions are checked for + validity before adding the function to the script engine. + Argument definitions follow the pattern: (v|s|i|l)*\?*\*? [FlavioJS] 2006/12/30 - * Reverted the packet structure changes to mmo_char_send006b in r9588 and - corrected the bug that I was originally fixing. [FlavioJS] + * Reverted the packet structure changes to mmo_char_send006b in r9588 (was + using the wrong exe for the final tests) except for the bug that I was + originally fixing. [FlavioJS] 2006/12/29 * Skill use is now cancelled when you use it while cloaking, and the uncloaking process warps you. [Skotlex] diff --git a/doc/script_commands.txt b/doc/script_commands.txt index bb3438ef1..d7483b1c0 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -9,7 +9,7 @@ //= Maeki Rika - A section on general concepts and lots of //= other updates and additions. //===== Version =========================================== -//= 2.8a +//= 2.9 //========================================================= //= 1.0 - First release, filled will as much info as I could //= remember or figure out, most likely there are errors, @@ -37,6 +37,7 @@ //= 2.8 - Deleted a copy of the nude command. Added axtoi command (needing a clearer //= explanation of atoi.Gave a better explanation of OnLabels and modified //= monster explanation due that L_Label isn't working with monster. +//= 2.9.20061230 - Updated getitem and guardian [FlavioJS] //===== Compatible With =================================== //= LOL, can be used by anyone hopefully //===== Description ======================================= @@ -1663,16 +1664,16 @@ Example 6: Using complex conditions. *getitem <item id>,<amount>{,<character ID>}; *getitem "<item name>",<amount>{,<character ID>}; -This command will give a specific amount of specified items to the invoking -character. If an optional character ID is specified, and that character is -currently online, items will be created in their inventory instead. If they are -not online, nothing will happen. +This command will give a specific amount of specified items to the target +character. If the character is not online, nothing will happen. +If <character ID> is not specified, items will be created in the invoking +character inventory instead. -In the first and most commonly used version of this command, tems are referred -to by their database ID number found inside 'db/item_db.txt'. +In the first and most commonly used version of this command, items are +referred to by their database ID number found inside 'db/item_db.txt'. - getitem 502,10 // The person will recieve 10 apples - getitem 617,1 // The person will recieve 1 Old Violet Box + getitem 502,10 // The person will receive 10 apples + getitem 617,1 // The person will receive 1 Old Violet Box Giving an item ID of -1 will give a specified number of random items from the list of those that fall out of Old Blue Box. Unlike in all other cases, these @@ -1687,19 +1688,19 @@ Giving an item ID of -4 will produce the effects of Gift Box. Giving an item ID of -5 will produce the effects of Worn Out Scroll, which, in current SVN, drops only Jellopies anyway. -Calling this command with a negative item ID to create a random item will create -an entry in the log file for those if such logging is enabled. +This transaction is logged if the log script generated transactions option is +enabled. -You may also create an item by it's name in the 'english name' field in the item -database: +You may also create an item by it's name in the 'english name' field in the +item database: getitem "RED_POTION",10; Which will do what you'd expect. If it can't find that name in the database, apples will be created anyway. It is often a VERY GOOD IDEA to use it like this. -This used in pretty much all NPC scripts that have to do with items and quite a -few item scripts. For more examples check just about any official script. +This is used in pretty much all NPC scripts that have to do with items and +quite a few item scripts. For more examples check just about any official script. --------------------------------------- @@ -4306,7 +4307,7 @@ per 'db/mob_db.txt'. Type is the kind of information returned. Valid types are: --------------------------------------- -*guardian "<map name>",<x>,<y>,"<name to show>",<mob id>,<amount>{,"<event label>"}; +*guardian "<map name>",<x>,<y>,"<name to show>",<mob id>,<amount>{,"<event label>"}{,<guardian index>}; This command is roughly equivalent to 'monster', but is meant to be used with castle guardian monsters and will only work with them. It will set the guardian diff --git a/src/common/socket.c b/src/common/socket.c index f8e65fb60..4e25abbb1 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -571,7 +571,7 @@ int WFIFOSET(int fd,int len) if(s->wdata_size+len > s->max_wdata) { // actually there was a buffer overflow already unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr; - ShowFatalError("socket: Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d byteson a %d/%d bytes buffer.\n", fd, + ShowFatalError("socket: Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n", fd, sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3], len, s->wdata_size, s->max_wdata); ShowDebug("Likely command that caused it: 0x%x\n", (*(unsigned short*)(s->wdata+s->wdata_size))); diff --git a/src/map/log.c b/src/map/log.c index 209b81d32..ff1487d0c 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -15,13 +15,9 @@ #include "log.h" #ifndef SQL_DEBUG - -#define mysql_query(_x, _y) mysql_real_query(_x, _y, strlen(_y)) //supports ' in names and runs faster [Kevin] - + #define mysql_query(_x, _y) mysql_real_query(_x, _y, strlen(_y)) //supports ' in names and runs faster [Kevin] #else - -#define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) - + #define mysql_query(_x, _y) debug_mysql_query(__FILE__, __LINE__, _x, _y) #endif struct Log_Config log_config; diff --git a/src/map/log.h b/src/map/log.h index 1cc2247db..c9d88cc37 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -29,8 +29,23 @@ int log_config_read(char *cfgName); int should_log_item(int filter, int nameid, int amount); //log filter check +enum log_what { + LOG_ALL = 0xFFF, + LOG_TRADES = 0x002, + LOG_VENDING = 0x004, + LOG_PLAYER_ITEMS = 0x008, // dropped/picked + LOG_MONTER_ITEMS = 0x010, // dropped/looted + LOG_NPC_TRANSACTIONS = 0x020, // npc shops? + LOG_SCRIPT_TRANSACTIONS = 0x040, + LOG_STOLEN_ITEMS = 0x080, // stolen from mobs + LOG_USED_ITEMS = 0x100, // used by player + LOG_MVP_PRIZE = 0x200, + LOG_COMMAND_ITEMS = 0x400 // created/deleted through @/# commands +}; + extern struct Log_Config { - int enable_logs, filter; + enum log_what enable_logs; + int filter; int sql_logs; int rare_items_log,refine_items_log,price_items_log,amount_items_log; //for filter int branch, drop, mvpdrop, zeny, gm, npc, chat; diff --git a/src/map/script.c b/src/map/script.c index 8d338c6a4..0e1f03f16 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -53,9 +53,18 @@ #include "irc.h" #include "pet.h" + +/////////////////////////////////////////////////////////////////////////////// +/// Returns the stack_data at the target index +#define script_getdata(st,i) &((st)->stack->stack_data[(st)->start+(i)]) +/// Returns if the stack contains data at the target index +#define script_hasdata(st,i) ( (st)->end > (st)->start + (i) ) +#define script_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR ) +#define script_isint(data) ( (data)->type == C_INT ) + #define FETCH(n, t) \ - if(st->end>st->start+(n)) \ - (t)=conv_num(st,&(st->stack->stack_data[st->start+(n)])); + if( script_hasdata(st,n) ) \ + (t)=conv_num(st,script_getdata(st,n)); #define SCRIPT_BLOCK_SIZE 512 enum { LABEL_NEXTLINE=1,LABEL_START }; @@ -158,8 +167,8 @@ int get_num(unsigned char *script,int *pos); extern struct script_function { int (*func)(struct script_state *st); - char *name; - char *arg; + const char *name; + const char *arg; } buildin_func[]; static struct linkdb_node *sleep_db; @@ -270,12 +279,13 @@ static void disp_error_message2(const char *mes,const char *pos,int report) } #define disp_error_message(mes,pos) disp_error_message2(mes,pos,1) -static void check_event(struct script_state *st, const char *event){ - if(event != NULL && event[0] != '\0' && !stristr(event,"::On")){ - ShowError("NPC event parameter deprecated! Please use 'NPCNAME::OnEVENT' instead of '%s'.\n",event); +/// Checks event parameter validity +static void check_event(struct script_state *st, const char *evt) +{ + if( evt != NULL && *evt != '\0' && !stristr(evt,"::On") ){ + ShowError("NPC event parameter deprecated! Please use 'NPCNAME::OnEVENT' instead of '%s'.\n",evt); report_src(st); } - return; } /*========================================== @@ -657,7 +667,7 @@ static const char* parse_callfunc(const char *p, int require_paren) } --syntax.curly_count; } - if( *arg && *arg != '*' ) + if( *arg && *arg != '?' && *arg != '*' ) disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script_config.warn_func_mismatch_paramnum); if( syntax.curly[syntax.curly_count].type != TYPE_ARGLIST ) disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p); @@ -1528,11 +1538,29 @@ const char* parse_syntax_close_sub(const char* p,int* flag) { static void add_buildin_func(void) { int i,n; - for(i=0;buildin_func[i].func;i++){ - n=add_str(buildin_func[i].name); - str_data[n].type=C_FUNC; - str_data[n].val=i; - str_data[n].func=buildin_func[i].func; + const char* p; + for( i=0; buildin_func[i].func; i++ ){ + /// arg must follow the pattern: (v|s|i|l)*\?*\*? + /// 'v' - value (either string or int) + /// 's' - string + /// 'i' - int + /// 'l' - label + /// '?' - one optional parameter + /// '*' - unknown number of optional parameters + p=buildin_func[i].arg; + while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'l' ) ++p; + while( *p == '?' ) ++p; + if( *p == '*' ) ++p; + if( *p != 0){ + ShowWarning("add_buildin_func: ignoring function \"%s\" with invalid arg \"%s\".\n", buildin_func[i].name, buildin_func[i].arg); + } else if( *skip_word(buildin_func[i].name) != 0 ){ + ShowWarning("add_buildin_func: ignoring function with invalid name \"%s\" (must be a word).\n", buildin_func[i].name); + } else { + n=add_str(buildin_func[i].name); + str_data[n].type=C_FUNC; + str_data[n].val=i; + str_data[n].func=buildin_func[i].func; + } } } @@ -3778,7 +3806,7 @@ struct script_function buildin_func[] = { {buildin_getarraysize,"getarraysize","i"}, {buildin_deletearray,"deletearray","ii"}, {buildin_getelementofarray,"getelementofarray","ii"}, - {buildin_getitem,"getitem","ii**"}, + {buildin_getitem,"getitem","vi?"}, {buildin_getitem2,"getitem2","iiiiiiiii*"}, {buildin_getnameditem,"getnameditem","is"}, {buildin_grouprandomitem,"groupranditem","i"}, @@ -3948,7 +3976,7 @@ struct script_function buildin_func[] = { {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_guardian,"guardian","siisii??"}, // summon guardians {buildin_guardianinfo,"guardianinfo","i"}, // display guardian data [Valaris] {buildin_petskillbonus,"petskillbonus","iiii"}, // [Valaris] {buildin_petrecovery,"petrecovery","ii"}, // [Valaris] @@ -5282,66 +5310,77 @@ int buildin_checkweight(struct script_state *st) } /*========================================== - * + * getitem <item id>,<amount>{,<character ID>}; + * getitem "<item name>",<amount>{,<character ID>}; *------------------------------------------ */ int buildin_getitem(struct script_state *st) { int nameid,amount,flag = 0; - struct item item_tmp; + struct item it; struct map_session_data *sd; struct script_data *data; - sd = script_rid2sd(st); - - data=&(st->stack->stack_data[st->start+2]); + data=script_getdata(st,2); get_val(st,data); - if( data->type==C_STR || data->type==C_CONSTSTR ){ + if( script_isstring(data) ) + {// "<item name>" const char *name=conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); - if( item_data == NULL) { - ShowWarning("buildin_getitem: Nonexistant item %s requested.\n", name); + if( item_data == NULL ){ + ShowError("buildin_getitem: Nonexistant item %s requested.\n", name); + report_src(st); return 1; //No item created. } nameid=item_data->nameid; - }else + } else if( script_isint(data) ) + {// <item id> nameid=conv_num(st,data); + //Violet Box, Blue Box, etc - random item pick + if( nameid < 0 ) { + nameid=itemdb_searchrandomid(-nameid); + flag = 1; + } + if( nameid <= 0 || !itemdb_exists(nameid) ){ + ShowError("buildin_getitem: Nonexistant item %d requested.\n", nameid); + report_src(st); + return 1; //No item created. + } + } else { + ShowError("buildin_getitem: invalid data type for argument #1 (%d).", data->type); + report_src(st); + return 1; + } - if ( ( amount=conv_num(st,& (st->stack->stack_data[st->start+3])) ) <= 0) + // <amount> + if( (amount=conv_num(st, script_getdata(st,3))) <= 0) return 0; //return if amount <=0, skip the useles iteration - //Violet Box, Blue Box, etc - random item pick - if(nameid <0) { - nameid=itemdb_searchrandomid(-nameid); - flag = 1; - } - - if(nameid <= 0 || !itemdb_exists(nameid)) { - ShowWarning("buildin_getitem: Nonexistant item %d requested.\n", nameid); - return 1; //No item created. - } - - malloc_set(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid=nameid; + malloc_set(&it,0,sizeof(it)); + it.nameid=nameid; if(!flag) - item_tmp.identify=1; + it.identify=1; else - item_tmp.identify=itemdb_isidentified(nameid); - if( st->end>st->start+5 ) //アイテムを指定したIDに渡す - sd=map_id2sd(conv_num(st,& (st->stack->stack_data[st->start+5]))); - if(sd == NULL) //アイテムを渡す相手がいなかったらお帰り + it.identify=itemdb_isidentified(nameid); + if( script_hasdata(st,4) ) + {// <character ID> + sd=map_id2sd(conv_num(st,script_getdata(st,4))); + } else + {// attached player + sd=script_rid2sd(st); + } + if( sd == NULL ) // no target return 0; - if(pet_create_egg(sd, nameid)) + if( pet_create_egg(sd, nameid) ) amount = 1; //This is a pet! - else - if((flag = pc_additem(sd,&item_tmp,amount))) { + else if( (flag=pc_additem(sd,&it,amount)) ){ clif_additem(sd,0,0,flag); - if (pc_candrop(sd, &item_tmp)) - map_addflooritem(&item_tmp,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); + if( pc_candrop(sd,&it) ) + map_addflooritem(&it,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); } //Logs items, got from (N)PC scripts [Lupus] - if(log_config.enable_logs&0x40) + if(log_config.enable_logs&LOG_SCRIPT_TRANSACTIONS) log_pick_pc(sd, "N", nameid, amount, NULL); return 0; @@ -9550,26 +9589,45 @@ int buildin_strmobinfo(struct script_state *st) /*========================================== * Summon guardians [Valaris] + * guardian "<map name>",<x>,<y>,"<name to show>",<mob id>,<amount>{,"<event label>"}{,<guardian index>}; *------------------------------------------ */ int buildin_guardian(struct script_state *st) { int class_=0,amount=1,x=0,y=0,guardian=0; - char *str,*map,*event=""; + char *str,*map,*evt=""; + struct script_data *data; - map =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])); - str =conv_str(st,& (st->stack->stack_data[st->start+5])); - class_=conv_num(st,& (st->stack->stack_data[st->start+6])); - amount=conv_num(st,& (st->stack->stack_data[st->start+7])); - event=conv_str(st,& (st->stack->stack_data[st->start+8])); - if( st->end>st->start+9 ) - guardian=conv_num(st,& (st->stack->stack_data[st->start+9])); + map =conv_str(st,script_getdata(st,2)); + x =conv_num(st,script_getdata(st,3)); + y =conv_num(st,script_getdata(st,4)); + str =conv_str(st,script_getdata(st,5)); + class_=conv_num(st,script_getdata(st,6)); + amount=conv_num(st,script_getdata(st,7)); + + if( script_hasdata(st,9) ) + {// "<event label>",<guardian index> + evt=conv_str(st,script_getdata(st,8)); + guardian=conv_num(st,script_getdata(st,9)); + } else if( script_hasdata(st,8) ){ + data=script_getdata(st,8); + get_val(st,data); + if( script_isstring(data) ) + {// "<event label>" + evt=conv_str(st,script_getdata(st,8)); + } else if( script_isint(data) ) + {// <guardian index> + guardian=conv_num(st,script_getdata(st,8)); + } else { + ShowError("buildin_guardian: invalid data type for argument #8 (%d).", data->type); + report_src(st); + return 1; + } + } - check_event(st, event); + check_event(st, evt); - mob_spawn_guardian(map_id2sd(st->rid),map,x,y,str,class_,amount,event,guardian); + mob_spawn_guardian(map_id2sd(st->rid),map,x,y,str,class_,amount,evt,guardian); return 0; } |