summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt16
-rw-r--r--doc/script_commands.txt33
-rw-r--r--src/common/socket.c2
-rw-r--r--src/map/log.c8
-rw-r--r--src/map/log.h17
-rw-r--r--src/map/script.c182
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;
}