- 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)*\?*\*?
    v - value (string or int)
    s - string
    i - int
    l - label
    ? - one optional parameter
    * - unknown number of optional parameters

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9599 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
FlavioJS 2006-12-31 09:22:25 +00:00
parent 4fa4e26d99
commit 0cf60d9ca1
6 changed files with 170 additions and 88 deletions

View File

@ -3,9 +3,21 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. 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. 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 2006/12/30
* Reverted the packet structure changes to mmo_char_send006b in r9588 and * Reverted the packet structure changes to mmo_char_send006b in r9588 (was
corrected the bug that I was originally fixing. [FlavioJS] using the wrong exe for the final tests) except for the bug that I was
originally fixing. [FlavioJS]
2006/12/29 2006/12/29
* Skill use is now cancelled when you use it while cloaking, and the * Skill use is now cancelled when you use it while cloaking, and the
uncloaking process warps you. [Skotlex] uncloaking process warps you. [Skotlex]

View File

@ -9,7 +9,7 @@
//= Maeki Rika - A section on general concepts and lots of //= Maeki Rika - A section on general concepts and lots of
//= other updates and additions. //= other updates and additions.
//===== Version =========================================== //===== Version ===========================================
//= 2.8a //= 2.9
//========================================================= //=========================================================
//= 1.0 - First release, filled will as much info as I could //= 1.0 - First release, filled will as much info as I could
//= remember or figure out, most likely there are errors, //= 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 //= 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 //= explanation of atoi.Gave a better explanation of OnLabels and modified
//= monster explanation due that L_Label isn't working with monster. //= monster explanation due that L_Label isn't working with monster.
//= 2.9.20061230 - Updated getitem and guardian [FlavioJS]
//===== Compatible With =================================== //===== Compatible With ===================================
//= LOL, can be used by anyone hopefully //= LOL, can be used by anyone hopefully
//===== Description ======================================= //===== Description =======================================
@ -1663,16 +1664,16 @@ Example 6: Using complex conditions.
*getitem <item id>,<amount>{,<character ID>}; *getitem <item id>,<amount>{,<character ID>};
*getitem "<item name>",<amount>{,<character ID>}; *getitem "<item name>",<amount>{,<character ID>};
This command will give a specific amount of specified items to the invoking This command will give a specific amount of specified items to the target
character. If an optional character ID is specified, and that character is character. If the character is not online, nothing will happen.
currently online, items will be created in their inventory instead. If they are If <character ID> is not specified, items will be created in the invoking
not online, nothing will happen. character inventory instead.
In the first and most commonly used version of this command, tems are referred In the first and most commonly used version of this command, items are
to by their database ID number found inside 'db/item_db.txt'. referred to by their database ID number found inside 'db/item_db.txt'.
getitem 502,10 // The person will recieve 10 apples getitem 502,10 // The person will receive 10 apples
getitem 617,1 // The person will recieve 1 Old Violet Box 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 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 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 Giving an item ID of -5 will produce the effects of Worn Out Scroll, which, in
current SVN, drops only Jellopies anyway. current SVN, drops only Jellopies anyway.
Calling this command with a negative item ID to create a random item will create This transaction is logged if the log script generated transactions option is
an entry in the log file for those if such logging is enabled. enabled.
You may also create an item by it's name in the 'english name' field in the item You may also create an item by it's name in the 'english name' field in the
database: item database:
getitem "RED_POTION",10; getitem "RED_POTION",10;
Which will do what you'd expect. If it can't find that name in the database, 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. 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 This is used in pretty much all NPC scripts that have to do with items and
few item scripts. For more examples check just about any official script. 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 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 castle guardian monsters and will only work with them. It will set the guardian

View File

@ -571,7 +571,7 @@ int WFIFOSET(int fd,int len)
if(s->wdata_size+len > s->max_wdata) if(s->wdata_size+len > s->max_wdata)
{ // actually there was a buffer overflow already { // actually there was a buffer overflow already
unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr; 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); 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", ShowDebug("Likely command that caused it: 0x%x\n",
(*(unsigned short*)(s->wdata+s->wdata_size))); (*(unsigned short*)(s->wdata+s->wdata_size)));

View File

@ -15,13 +15,9 @@
#include "log.h" #include "log.h"
#ifndef SQL_DEBUG #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 #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 #endif
struct Log_Config log_config; struct Log_Config log_config;

View File

@ -29,8 +29,23 @@ int log_config_read(char *cfgName);
int should_log_item(int filter, int nameid, int amount); //log filter check 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 { extern struct Log_Config {
int enable_logs, filter; enum log_what enable_logs;
int filter;
int sql_logs; int sql_logs;
int rare_items_log,refine_items_log,price_items_log,amount_items_log; //for filter int rare_items_log,refine_items_log,price_items_log,amount_items_log; //for filter
int branch, drop, mvpdrop, zeny, gm, npc, chat; int branch, drop, mvpdrop, zeny, gm, npc, chat;

View File

@ -53,9 +53,18 @@
#include "irc.h" #include "irc.h"
#include "pet.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) \ #define FETCH(n, t) \
if(st->end>st->start+(n)) \ if( script_hasdata(st,n) ) \
(t)=conv_num(st,&(st->stack->stack_data[st->start+(n)])); (t)=conv_num(st,script_getdata(st,n));
#define SCRIPT_BLOCK_SIZE 512 #define SCRIPT_BLOCK_SIZE 512
enum { LABEL_NEXTLINE=1,LABEL_START }; enum { LABEL_NEXTLINE=1,LABEL_START };
@ -158,8 +167,8 @@ int get_num(unsigned char *script,int *pos);
extern struct script_function { extern struct script_function {
int (*func)(struct script_state *st); int (*func)(struct script_state *st);
char *name; const char *name;
char *arg; const char *arg;
} buildin_func[]; } buildin_func[];
static struct linkdb_node *sleep_db; 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) #define disp_error_message(mes,pos) disp_error_message2(mes,pos,1)
static void check_event(struct script_state *st, const char *event){ /// Checks event parameter validity
if(event != NULL && event[0] != '\0' && !stristr(event,"::On")){ static void check_event(struct script_state *st, const char *evt)
ShowError("NPC event parameter deprecated! Please use 'NPCNAME::OnEVENT' instead of '%s'.\n",event); {
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); report_src(st);
} }
return;
} }
/*========================================== /*==========================================
@ -657,7 +667,7 @@ static const char* parse_callfunc(const char *p, int require_paren)
} }
--syntax.curly_count; --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); 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 ) if( syntax.curly[syntax.curly_count].type != TYPE_ARGLIST )
disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p); 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) static void add_buildin_func(void)
{ {
int i,n; int i,n;
for(i=0;buildin_func[i].func;i++){ const char* p;
n=add_str(buildin_func[i].name); for( i=0; buildin_func[i].func; i++ ){
str_data[n].type=C_FUNC; /// arg must follow the pattern: (v|s|i|l)*\?*\*?
str_data[n].val=i; /// 'v' - value (either string or int)
str_data[n].func=buildin_func[i].func; /// '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_getarraysize,"getarraysize","i"},
{buildin_deletearray,"deletearray","ii"}, {buildin_deletearray,"deletearray","ii"},
{buildin_getelementofarray,"getelementofarray","ii"}, {buildin_getelementofarray,"getelementofarray","ii"},
{buildin_getitem,"getitem","ii**"}, {buildin_getitem,"getitem","vi?"},
{buildin_getitem2,"getitem2","iiiiiiiii*"}, {buildin_getitem2,"getitem2","iiiiiiiii*"},
{buildin_getnameditem,"getnameditem","is"}, {buildin_getnameditem,"getnameditem","is"},
{buildin_grouprandomitem,"groupranditem","i"}, {buildin_grouprandomitem,"groupranditem","i"},
@ -3948,7 +3976,7 @@ struct script_function buildin_func[] = {
{buildin_soundeffect,"soundeffect","si"}, {buildin_soundeffect,"soundeffect","si"},
{buildin_soundeffectall,"soundeffectall","si*"}, // SoundEffectAll [Codemaster] {buildin_soundeffectall,"soundeffectall","si*"}, // SoundEffectAll [Codemaster]
{buildin_strmobinfo,"strmobinfo","ii"}, // display mob data [Valaris] {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_guardianinfo,"guardianinfo","i"}, // display guardian data [Valaris]
{buildin_petskillbonus,"petskillbonus","iiii"}, // [Valaris] {buildin_petskillbonus,"petskillbonus","iiii"}, // [Valaris]
{buildin_petrecovery,"petrecovery","ii"}, // [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 buildin_getitem(struct script_state *st)
{ {
int nameid,amount,flag = 0; int nameid,amount,flag = 0;
struct item item_tmp; struct item it;
struct map_session_data *sd; struct map_session_data *sd;
struct script_data *data; struct script_data *data;
sd = script_rid2sd(st); data=script_getdata(st,2);
data=&(st->stack->stack_data[st->start+2]);
get_val(st,data); 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); const char *name=conv_str(st,data);
struct item_data *item_data = itemdb_searchname(name); struct item_data *item_data = itemdb_searchname(name);
if( item_data == NULL) { if( item_data == NULL ){
ShowWarning("buildin_getitem: Nonexistant item %s requested.\n", name); ShowError("buildin_getitem: Nonexistant item %s requested.\n", name);
report_src(st);
return 1; //No item created. return 1; //No item created.
} }
nameid=item_data->nameid; nameid=item_data->nameid;
}else } else if( script_isint(data) )
{// <item id>
nameid=conv_num(st,data); 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 return 0; //return if amount <=0, skip the useles iteration
//Violet Box, Blue Box, etc - random item pick malloc_set(&it,0,sizeof(it));
if(nameid <0) { it.nameid=nameid;
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;
if(!flag) if(!flag)
item_tmp.identify=1; it.identify=1;
else else
item_tmp.identify=itemdb_isidentified(nameid); it.identify=itemdb_isidentified(nameid);
if( st->end>st->start+5 ) //アイテムを指定したIDに渡す if( script_hasdata(st,4) )
sd=map_id2sd(conv_num(st,& (st->stack->stack_data[st->start+5]))); {// <character ID>
if(sd == NULL) //アイテムを渡す相手がいなかったらお帰り sd=map_id2sd(conv_num(st,script_getdata(st,4)));
} else
{// attached player
sd=script_rid2sd(st);
}
if( sd == NULL ) // no target
return 0; return 0;
if(pet_create_egg(sd, nameid)) if( pet_create_egg(sd, nameid) )
amount = 1; //This is a pet! amount = 1; //This is a pet!
else else if( (flag=pc_additem(sd,&it,amount)) ){
if((flag = pc_additem(sd,&item_tmp,amount))) {
clif_additem(sd,0,0,flag); clif_additem(sd,0,0,flag);
if (pc_candrop(sd, &item_tmp)) if( pc_candrop(sd,&it) )
map_addflooritem(&item_tmp,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); 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] //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); log_pick_pc(sd, "N", nameid, amount, NULL);
return 0; return 0;
@ -9550,26 +9589,45 @@ int buildin_strmobinfo(struct script_state *st)
/*========================================== /*==========================================
* Summon guardians [Valaris] * 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 buildin_guardian(struct script_state *st)
{ {
int class_=0,amount=1,x=0,y=0,guardian=0; 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])); map =conv_str(st,script_getdata(st,2));
x =conv_num(st,& (st->stack->stack_data[st->start+3])); x =conv_num(st,script_getdata(st,3));
y =conv_num(st,& (st->stack->stack_data[st->start+4])); y =conv_num(st,script_getdata(st,4));
str =conv_str(st,& (st->stack->stack_data[st->start+5])); str =conv_str(st,script_getdata(st,5));
class_=conv_num(st,& (st->stack->stack_data[st->start+6])); class_=conv_num(st,script_getdata(st,6));
amount=conv_num(st,& (st->stack->stack_data[st->start+7])); amount=conv_num(st,script_getdata(st,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]));
check_event(st, event); 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;
}
}
mob_spawn_guardian(map_id2sd(st->rid),map,x,y,str,class_,amount,event,guardian); check_event(st, evt);
mob_spawn_guardian(map_id2sd(st->rid),map,x,y,str,class_,amount,evt,guardian);
return 0; return 0;
} }