- 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:
parent
4fa4e26d99
commit
0cf60d9ca1
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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)));
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
166
src/map/script.c
166
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,12 +1538,30 @@ 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++){
|
||||
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);
|
||||
|
||||
if ( ( amount=conv_num(st,& (st->stack->stack_data[st->start+3])) ) <= 0)
|
||||
return 0; //return if amount <=0, skip the useles iteration
|
||||
|
||||
//Violet Box, Blue Box, etc - random item pick
|
||||
if(nameid <0) {
|
||||
if( nameid < 0 ) {
|
||||
nameid=itemdb_searchrandomid(-nameid);
|
||||
flag = 1;
|
||||
}
|
||||
|
||||
if(nameid <= 0 || !itemdb_exists(nameid)) {
|
||||
ShowWarning("buildin_getitem: Nonexistant item %d requested.\n", nameid);
|
||||
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;
|
||||
}
|
||||
|
||||
malloc_set(&item_tmp,0,sizeof(item_tmp));
|
||||
item_tmp.nameid=nameid;
|
||||
// <amount>
|
||||
if( (amount=conv_num(st, script_getdata(st,3))) <= 0)
|
||||
return 0; //return if amount <=0, skip the useles iteration
|
||||
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user