* Updated script_commands.txt

* Made scripts terminate with an error: (fixes bugreport:2429)
- when getitem/getitem2 tries to delete more items than the player has
- when trying to set Zeny to a negative number.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13368 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
FlavioJS 2008-11-11 04:02:48 +00:00
parent 227444c5d6
commit f74b445add
4 changed files with 111 additions and 52 deletions

View File

@ -3,6 +3,11 @@ 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.
2008/11/11
* Updated script_commands.txt [FlavioJS]
* Made scripts terminate with an error: (fixes bugreport:2429)
- when getitem/getitem2 tries to delete more items than the player has
- when trying to set Zeny to a negative number.
2008/11/09 2008/11/09
* Added a check to make sure killed monster's level was greater than half of the mercenary owner's level before incrementing mercenary's killcount. (bugreport:2410) [Paradox924X] * Added a check to make sure killed monster's level was greater than half of the mercenary owner's level before incrementing mercenary's killcount. (bugreport:2410) [Paradox924X]
2008/11/07 2008/11/07

View File

@ -4,7 +4,7 @@
//= A reference manual for the eAthena scripting language. //= A reference manual for the eAthena scripting language.
//= Commands are sorted depending on their functionality. //= Commands are sorted depending on their functionality.
//===== Version =========================================== //===== Version ===========================================
//= 3.23.20080909 //= 3.34.20081111
//========================================================= //=========================================================
//= 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,
@ -124,6 +124,8 @@
//= Adjusted the 'getequipname' description to match src [ultramage] //= Adjusted the 'getequipname' description to match src [ultramage]
//= 3.23.20080909 //= 3.23.20080909
//= Added WoE SE related commands. [L0ne_W0lf] //= Added WoE SE related commands. [L0ne_W0lf]
//= 3.34.20081111
//= Changed the error behaviour of delitem/delitem2/Zeny. [FlavioJS]
//========================================================= //=========================================================
This document is a reference manual for all the scripting commands and functions This document is a reference manual for all the scripting commands and functions
@ -631,6 +633,7 @@ not certain whether this will work for all of them. Whenever there is a command
or a function to set something, it's usually preferable to use that instead. The or a function to set something, it's usually preferable to use that instead. The
notable exception is Zeny, which you can and often will address directly - notable exception is Zeny, which you can and often will address directly -
setting it will make the character own this number of zeny. setting it will make the character own this number of zeny.
If you try to set Zeny to a negative number, the script will be terminated with an error.
Strings Strings
------- -------
@ -3872,7 +3875,7 @@ If the map name is given as "this", the map the invoking character is on will be
*delitem <item id>,<amount>{,<account ID>}; *delitem <item id>,<amount>{,<account ID>};
*delitem "<item name>",<amount>{,<account ID>}; *delitem "<item name>",<amount>{,<account ID>};
This command will take a specified amount of items from the invoking character. This command will take a specified amount of items from the invoking/target character.
As all the item commands, this one uses the ID of the item found inside As all the item commands, this one uses the ID of the item found inside
'db/item_db.txt'. The items are destroyed - there is no way an NPC can simply 'db/item_db.txt'. The items are destroyed - there is no way an NPC can simply
own items and have an inventory of them, other as by destroying and recreating own items and have an inventory of them, other as by destroying and recreating
@ -3881,10 +3884,9 @@ them when needed.
delitem 502,10 // The person will lose 10 apples delitem 502,10 // The person will lose 10 apples
delitem 617,1 // The person will lose 1 Old Violet Box delitem 617,1 // The person will lose 1 Old Violet Box
It is always a good idea to to check if the player actually has the item before It is always a good idea to check if the player actually has the items before you delete them.
you take it from them, Otherwise, you could try to delete items which the If you try to delete more items that the player has, the player will lose the ones he/she has
players don't actually have, which won't fail and won't give an error message, and the script will be terminated with an error.
but might open up ways to exploit your script.
Like 'getitem' this command will also accept an 'english name' field from the Like 'getitem' this command will also accept an 'english name' field from the
database. If the name is not found, nothing will be deleted. database. If the name is not found, nothing will be deleted.
@ -3894,7 +3896,7 @@ database. If the name is not found, nothing will be deleted.
*delitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}; *delitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
*delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}; *delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
This command will take a specified amount of items from the invoking character. This command will take a specified amount of items from the invoking/target character.
Check 'getitem2' to understand its expanded parameters. Check 'getitem2' to understand its expanded parameters.
--------------------------------------- ---------------------------------------

View File

@ -5399,6 +5399,8 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
sd->status.status_point = val; sd->status.status_point = val;
break; break;
case SP_ZENY: case SP_ZENY:
if( val < 0 )
return 0;// can't set negative zeny
sd->status.zeny = cap_value(val, 0, MAX_ZENY); sd->status.zeny = cap_value(val, 0, MAX_ZENY);
break; break;
case SP_BASEEXP: case SP_BASEEXP:

View File

@ -2273,7 +2273,19 @@ static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* nam
{// integer variable {// integer variable
int val = (int)value; int val = (int)value;
if(str_data[num&0x00ffffff].type == C_PARAM) if(str_data[num&0x00ffffff].type == C_PARAM)
return pc_setparam(sd, str_data[num&0x00ffffff].val, val); {
if( pc_setparam(sd, str_data[num&0x00ffffff].val, val) == 0 )
{
if( st != NULL )
{
ShowError("script:set_reg: failed to set param '%s' to %d.\n", name, val);
script_reportsrc(st);
st->state = END;
}
return 0;
}
return 1;
}
switch (prefix) { switch (prefix) {
case '@': case '@':
@ -5367,9 +5379,12 @@ BUILDIN_FUNC(makeitem)
return 0; return 0;
} }
/*==========================================
* script DELITEM command (fixed 2 bugs by Lupus, added deletion priority by Lupus) /// Deletes items from the target/attached player.
*------------------------------------------*/ /// Prioritizes ordinary items.
///
/// delitem <item id>,<amount>{,<account id>}
/// delitem "<item name>",<amount>{,<account id>}
BUILDIN_FUNC(delitem) BUILDIN_FUNC(delitem)
{ {
int nameid=0,amount,i,important_item=0; int nameid=0,amount,i,important_item=0;
@ -5377,30 +5392,45 @@ BUILDIN_FUNC(delitem)
struct script_data *data; struct script_data *data;
if( script_hasdata(st,4) ) if( script_hasdata(st,4) )
sd=map_id2sd(script_getnum(st,4)); // <Account ID> {
int account_id = script_getnum(st,4);
sd = map_id2sd(account_id); // <account id>
if( sd == NULL )
{
ShowError("script:delitem: player not found (AID=%d).\n", account_id);
st->state = END;
return 1;
}
}
else else
sd=script_rid2sd(st); // Attached player {
sd = script_rid2sd(st);// attached player
if( sd == NULL )
return 0;
}
if( sd == NULL ) // no target data = script_getdata(st,2);
return 0;
data=script_getdata(st,2);
get_val(st,data); get_val(st,data);
if( data_isstring(data) ){ if( data_isstring(data) )
const char *name=conv_str(st,data); {
struct item_data *item_data = itemdb_searchname(name); const char* item_name = conv_str(st,data);
//nameid=UNKNOWN_ITEM_ID; struct item_data* id = itemdb_searchname(item_name);
if( item_data ) if( id == NULL )
nameid=item_data->nameid; {
}else ShowError("script:delitem: unknown item \"%s\".\n", item_name);
nameid=conv_num(st,data); st->state = END;
return 1;
}
nameid = id->nameid;// "<item name>"
}
else
nameid = conv_num(st,data);// <item id>
amount=script_getnum(st,3); amount=script_getnum(st,3);
if (nameid<500 || amount<=0 ) {//by Lupus. Don't run FOR if u got wrong item ID or amount<=0 if( amount <= 0 )
//eprintf("wrong item ID or amount<=0 : delitem %i,\n",nameid,amount); return 0;// nothing to do
return 0;
}
//1st pass //1st pass
//here we won't delete items with CARDS, named items but we count them //here we won't delete items with CARDS, named items but we count them
for(i=0;i<MAX_INVENTORY;i++){ for(i=0;i<MAX_INVENTORY;i++){
@ -5473,12 +5503,15 @@ BUILDIN_FUNC(delitem)
} }
} }
return 0; ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).\n", amount, sd->status.account_id, nameid);
st->state = END;
return 1;
} }
/*========================================== /// Deletes items from the target/attached player.
* advanced version of delitem [modified by Mihilion] ///
*------------------------------------------*/ /// delitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}
/// delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}
BUILDIN_FUNC(delitem2) BUILDIN_FUNC(delitem2)
{ {
int nameid=0,amount,i=0; int nameid=0,amount,i=0;
@ -5487,23 +5520,39 @@ BUILDIN_FUNC(delitem2)
struct script_data *data; struct script_data *data;
if( script_hasdata(st,11) ) if( script_hasdata(st,11) )
sd=map_id2sd(script_getnum(st,11)); // <Account ID> {
int account_id = script_getnum(st,11);
sd = map_id2sd(account_id); // <account id>
if( sd == NULL )
{
ShowError("script:delitem2: player not found (AID=%d).\n", account_id);
st->state = END;
return 1;
}
}
else else
sd=script_rid2sd(st); // Attached player {
sd = script_rid2sd(st);// attached player
if( sd == NULL )
return 0;
}
if( sd == NULL ) // no target data = script_getdata(st,2);
return 0;
data=script_getdata(st,2);
get_val(st,data); get_val(st,data);
if( data_isstring(data) ){ if( data_isstring(data) )
const char *name=conv_str(st,data); {
struct item_data *item_data = itemdb_searchname(name); const char* item_name = conv_str(st,data);
//nameid=UNKNOWN_ITEM_ID; struct item_data* id = itemdb_searchname(item_name);
if( item_data ) if( id == NULL )
nameid=item_data->nameid; {
}else ShowError("script:delitem2: unknown item \"%s\".\n", item_name);
nameid=conv_num(st,data); st->state = END;
return 1;
}
nameid = id->nameid;// "<item name>"
}
else
nameid = conv_num(st,data);// <item id>
amount=script_getnum(st,3); amount=script_getnum(st,3);
iden=script_getnum(st,4); iden=script_getnum(st,4);
@ -5514,10 +5563,8 @@ BUILDIN_FUNC(delitem2)
c3=script_getnum(st,9); c3=script_getnum(st,9);
c4=script_getnum(st,10); c4=script_getnum(st,10);
if (!itemdb_exists(nameid) || amount<=0 ) {//by Lupus. Don't run FOR if u got wrong item ID or amount<=0 if( amount <= 0 )
//eprintf("wrong item ID or amount<=0 : delitem %i,\n",nameid,amount); return 0;// nothing to do
return 0;
}
for(i=0;i<MAX_INVENTORY;i++){ for(i=0;i<MAX_INVENTORY;i++){
//we don't delete wrong item or equipped item //we don't delete wrong item or equipped item
@ -5553,7 +5600,10 @@ BUILDIN_FUNC(delitem2)
pc_delitem(sd,i,sd->status.inventory[i].amount,0); pc_delitem(sd,i,sd->status.inventory[i].amount,0);
} }
} }
return 0;
ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).\n", amount, sd->status.account_id, nameid);
st->state = END;
return 1;
} }
/*========================================== /*==========================================