Cleaning up the itemdb reload mess (see r12635, r12643, r12650, r12661, r12662, r12663)
* the player data inventory-itemdb index is now refreshed using pc_setinventorydata() * mobdb will no longer initialize with nonexistent items, and mobs will no longer drop them in case of a reload * the clif_buylist() function once again hides invalid npc shop items * it is no longer possible to purchase nonexistent items from a npc shop * npc shop loading will not abort if there is a nonexistent item entry, it will just skip over it git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12665 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
e50dd25ec2
commit
7a9a3a12bb
@ -3,16 +3,6 @@ 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.
|
||||
|
||||
2008/04/27
|
||||
* Fixed "suggest parentheses around assignment ..." gcc warning [Toms]
|
||||
* Some major changes to @reloaditemdb to allow unloading of any item
|
||||
while map server is running.
|
||||
- Delete any item from inventory/cart/open storages that went missing
|
||||
during the reload.
|
||||
- Delete item from any shop that has this item.
|
||||
- Refresh item screen for anyone who has a shop open.
|
||||
- Delete mob db drop table references.
|
||||
- Delete item from storage during load if it isn't in the item db. [Kevin]
|
||||
2008/04/26
|
||||
* Added script function hasquest. [Kevin]
|
||||
* Fixed OnGuildBreak. [Kevin]
|
||||
|
@ -700,9 +700,6 @@ mapflag: 99
|
||||
// Re-load item database (admin command)
|
||||
reloaditemdb: 99
|
||||
|
||||
// Re-load item database and delete all references to it (admin command)
|
||||
reloaditemdb2: 99
|
||||
|
||||
// Re-load monsters database (admin command)
|
||||
reloadmobdb: 99
|
||||
|
||||
|
@ -4049,25 +4049,12 @@ int atcommand_partyrecall(const int fd, struct map_session_data* sd, const char*
|
||||
int atcommand_reloaditemdb(const int fd, struct map_session_data* sd, const char* command, const char* message)
|
||||
{
|
||||
nullpo_retr(-1, sd);
|
||||
itemdb_reload(0);
|
||||
itemdb_reload();
|
||||
clif_displaymessage(fd, msg_txt(97)); // Item database reloaded.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
*------------------------------------------*/
|
||||
int atcommand_reloaditemdb2(const int fd, struct map_session_data* sd, const char* command, const char* message)
|
||||
{
|
||||
nullpo_retr(-1, sd);
|
||||
itemdb_reload(1);
|
||||
clif_displaymessage(fd, msg_txt(97)); // Item database reloaded.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
*------------------------------------------*/
|
||||
@ -8386,7 +8373,6 @@ AtCommandInfo atcommand_info[] = {
|
||||
{ "localbroadcast", 40, atcommand_localbroadcast }, // + /lb and /nlb
|
||||
{ "recallall", 80, atcommand_recallall },
|
||||
{ "reloaditemdb", 99, atcommand_reloaditemdb },
|
||||
{ "reloaditemdb2", 99, atcommand_reloaditemdb2 },
|
||||
{ "reloadmobdb", 99, atcommand_reloadmobdb },
|
||||
{ "reloadskilldb", 99, atcommand_reloadskilldb },
|
||||
{ "reloadscript", 99, atcommand_reloadscript },
|
||||
|
@ -1389,26 +1389,32 @@ int clif_npcbuysell(struct map_session_data* sd, int id)
|
||||
*------------------------------------------*/
|
||||
int clif_buylist(struct map_session_data *sd, struct npc_data *nd)
|
||||
{
|
||||
int fd,i;
|
||||
int fd,i,c;
|
||||
|
||||
nullpo_retr(0, sd);
|
||||
nullpo_retr(0, nd);
|
||||
|
||||
fd = sd->fd;
|
||||
WFIFOHEAD(fd, 200 * 11 + 4);
|
||||
WFIFOHEAD(fd, 4 + nd->u.shop.count * 11);
|
||||
WFIFOW(fd,0) = 0xc6;
|
||||
WFIFOW(fd,2) = 4 + nd->u.shop.count*11;
|
||||
|
||||
c = 0;
|
||||
for( i = 0; i < nd->u.shop.count; i++ )
|
||||
{
|
||||
struct item_data* id = itemdb_search(nd->u.shop.shop_item[i].nameid);
|
||||
struct item_data* id = itemdb_exists(nd->u.shop.shop_item[i].nameid);
|
||||
int val = nd->u.shop.shop_item[i].value;
|
||||
WFIFOL(fd,4+i*11) = val;
|
||||
if( id == NULL )
|
||||
continue;
|
||||
WFIFOL(fd, 4+c*11) = val;
|
||||
if (!id->flag.value_notdc)
|
||||
val = pc_modifybuyvalue(sd,val);
|
||||
WFIFOL(fd,8+i*11) = val;
|
||||
WFIFOB(fd,12+i*11) = itemtype(id->type);
|
||||
WFIFOW(fd,13+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
|
||||
WFIFOL(fd, 8+c*11) = val;
|
||||
WFIFOB(fd,12+c*11) = itemtype(id->type);
|
||||
WFIFOW(fd,13+c*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
|
||||
c++;
|
||||
}
|
||||
|
||||
WFIFOW(fd,2) = 4 + c*11;
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
|
||||
return 0;
|
||||
@ -8838,6 +8844,7 @@ void clif_parse_NpcBuyListSend(int fd,struct map_session_data *sd)
|
||||
fail = npc_buylist(sd,n,item_list);
|
||||
|
||||
sd->npc_shopid = 0; //Clear shop data.
|
||||
|
||||
WFIFOHEAD(fd,packet_len(0xca));
|
||||
WFIFOW(fd,0)=0xca;
|
||||
WFIFOB(fd,2)=fail;
|
||||
|
172
src/map/itemdb.c
172
src/map/itemdb.c
@ -10,10 +10,6 @@
|
||||
#include "battle.h" // struct battle_config
|
||||
#include "script.h" // item script processing
|
||||
#include "pc.h" // W_MUSICAL, W_WHIP
|
||||
#include "storage.h"
|
||||
#include "npc.h"
|
||||
#include "clif.h"
|
||||
#include "mob.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -693,7 +689,7 @@ static int itemdb_gendercheck(struct item_data *id)
|
||||
/*==========================================
|
||||
* processes one itemdb entry
|
||||
*------------------------------------------*/
|
||||
static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt, int db)
|
||||
static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt)
|
||||
{
|
||||
/*
|
||||
+----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
|
||||
@ -717,9 +713,6 @@ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scr
|
||||
safestrncpy(id->name, str[1], sizeof(id->name));
|
||||
safestrncpy(id->jname, str[2], sizeof(id->jname));
|
||||
|
||||
if(db == 1)
|
||||
id->flag.db2 = 1;
|
||||
|
||||
id->type = atoi(str[3]);
|
||||
if (id->type == IT_DELAYCONSUME)
|
||||
{ //Items that are consumed only after target confirmation
|
||||
@ -907,7 +900,8 @@ static int itemdb_readdb(void)
|
||||
}
|
||||
str[21] = p;
|
||||
|
||||
if (!itemdb_parse_dbrow(str, path, lines, 0, fi))
|
||||
|
||||
if (!itemdb_parse_dbrow(str, path, lines, 0))
|
||||
continue;
|
||||
|
||||
count++;
|
||||
@ -954,7 +948,7 @@ static int itemdb_read_sqldb(void)
|
||||
if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns
|
||||
}
|
||||
|
||||
if (!itemdb_parse_dbrow(str, item_db_name[fi], lines, SCRIPT_IGNORE_EXTERNAL_BRACKETS, fi))
|
||||
if (!itemdb_parse_dbrow(str, item_db_name[fi], lines, SCRIPT_IGNORE_EXTERNAL_BRACKETS))
|
||||
continue;
|
||||
++count;
|
||||
}
|
||||
@ -1012,13 +1006,6 @@ static void destroy_item_data(struct item_data* self, int free_self)
|
||||
aFree(self);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* This comment shall be a monument to cake.
|
||||
* The cake is NOT a lie in eAthena.
|
||||
* We are so awesome we have our own cake.
|
||||
* Please spam Cyxult with endless PMs to get your cake.
|
||||
*------------------------------------------*/
|
||||
|
||||
static int itemdb_final_sub(DBKey key,void *data,va_list ap)
|
||||
{
|
||||
struct item_data *id = (struct item_data *)data;
|
||||
@ -1029,149 +1016,30 @@ static int itemdb_final_sub(DBKey key,void *data,va_list ap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Uncomment this if you're an elitist jerk who thinks this code is unecessary
|
||||
//#define I_HATE_KEVIN
|
||||
#ifndef I_HATE_KEVIN
|
||||
int itemdb_reload_check_npc(DBKey key,void * data,va_list ap)
|
||||
void itemdb_reload(void)
|
||||
{
|
||||
struct npc_data * nd = (struct npc_data *)data;
|
||||
int offset = 0, i = 0;
|
||||
struct s_mapiterator* iter;
|
||||
struct map_session_data* sd;
|
||||
|
||||
if(nd->subtype != SHOP && nd->subtype != CASHSHOP)
|
||||
return 0;
|
||||
|
||||
while(i < nd->u.shop.count)
|
||||
{
|
||||
|
||||
if(itemdb_exists(nd->u.shop.shop_item[i].nameid) == NULL)
|
||||
{
|
||||
|
||||
nd->u.shop.count--;
|
||||
|
||||
//Shift array to left, overwriting old data
|
||||
for(offset = i; offset+1 < nd->u.shop.count; offset++);
|
||||
{
|
||||
nd->u.shop.shop_item[offset].nameid = nd->u.shop.shop_item[offset+1].nameid;
|
||||
nd->u.shop.shop_item[offset].value = nd->u.shop.shop_item[offset+1].value;
|
||||
}
|
||||
|
||||
}
|
||||
//increment counter if we didn't delete something
|
||||
else
|
||||
i++;
|
||||
|
||||
}
|
||||
|
||||
//Resize array
|
||||
RECREATE(nd->u.shop.shop_item, struct npc_item_list, nd->u.shop.count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int itemdb_reload_check(DBKey key,void *data,va_list ap)
|
||||
{
|
||||
int i;
|
||||
struct map_session_data *sd = (struct map_session_data *)data;
|
||||
struct storage * stor;
|
||||
struct item_data * id;
|
||||
struct npc_data * nd;
|
||||
|
||||
if(sd->npc_shopid)
|
||||
{
|
||||
nd = (struct npc_data*)map_id2bl(sd->npc_shopid);
|
||||
clif_buylist(sd, nd);
|
||||
}
|
||||
// clear the previous itemdb data
|
||||
for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
|
||||
if( itemdb_array[i] )
|
||||
destroy_item_data(itemdb_array[i], 1);
|
||||
|
||||
//First, handle all items in inventories/equiped, cart, and storage
|
||||
for(i = 0; i < MAX_INVENTORY; i++)
|
||||
{
|
||||
if(!sd->status.inventory[i].nameid)
|
||||
continue;
|
||||
itemdb_other->clear(itemdb_other, itemdb_final_sub);
|
||||
|
||||
id = itemdb_exists(sd->status.inventory[i].nameid);
|
||||
if(id == NULL)
|
||||
{
|
||||
sd->inventory_data[i] = NULL;
|
||||
pc_delitem(sd, i, sd->status.inventory[i].amount, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
sd->inventory_data[i] = id;
|
||||
}
|
||||
}
|
||||
memset(itemdb_array, 0, sizeof(itemdb_array));
|
||||
|
||||
//Delete nonexistant items from cart
|
||||
for(i = 0; i < MAX_CART; i++)
|
||||
{
|
||||
if(!sd->status.cart[i].nameid)
|
||||
continue;
|
||||
// read new data
|
||||
itemdb_read();
|
||||
|
||||
id = itemdb_exists(sd->status.cart[i].nameid);
|
||||
if(id == NULL)
|
||||
{
|
||||
sd->inventory_data[i] = NULL;
|
||||
pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//Delete storage
|
||||
if((stor = account2storage2(sd->status.account_id)))
|
||||
{
|
||||
//If storage isn't found, it will be deleted whenever storage is loaded again
|
||||
if(stor)
|
||||
{
|
||||
for(i = 0; i < MAX_STORAGE; i++)
|
||||
{
|
||||
if(!sd->status.inventory[i].nameid)
|
||||
continue;
|
||||
|
||||
if(itemdb_exists(sd->status.inventory[i].nameid) == NULL)
|
||||
storage_delitem(sd, stor, i, stor->storage_[i].amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Cleanup mob db drop tables
|
||||
void itemdb_foreach_mobdb(void)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
struct item_data * id;
|
||||
s_mob_db * mdb;
|
||||
|
||||
for(i=0; i < MAX_MOB_DB; i++)
|
||||
{
|
||||
mdb = mob_db(i);
|
||||
if(mdb == mob_dummy)
|
||||
continue;
|
||||
for(j=0; j < MAX_MOB_DROP; j++)
|
||||
{
|
||||
id = itemdb_exists(mdb->dropitem[j].nameid);
|
||||
if(id == NULL)
|
||||
{
|
||||
mdb->dropitem[j].nameid = 0;
|
||||
mdb->dropitem[j].p = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void itemdb_reload(int flag)
|
||||
{
|
||||
|
||||
do_final_itemdb();
|
||||
do_init_itemdb();
|
||||
|
||||
if(flag)
|
||||
{
|
||||
//Update ALL items on the server
|
||||
map_foreachpc(itemdb_reload_check);
|
||||
npc_foreach(itemdb_reload_check_npc);
|
||||
itemdb_foreach_mobdb();
|
||||
}
|
||||
// readjust itemdb pointer cache for each player
|
||||
iter = mapit_geteachpc();
|
||||
for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) )
|
||||
pc_setinventorydata(sd);
|
||||
mapit_free(iter);
|
||||
}
|
||||
|
||||
void do_final_itemdb(void)
|
||||
|
@ -34,8 +34,8 @@
|
||||
#define UNKNOWN_ITEM_ID 512
|
||||
|
||||
struct item_data {
|
||||
char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
|
||||
int nameid;
|
||||
char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
|
||||
//Do not add stuff between value_buy and wlv (see how getiteminfo works)
|
||||
int value_buy;
|
||||
int value_sell;
|
||||
@ -56,27 +56,24 @@ struct item_data {
|
||||
// some script commands should be revised as well...
|
||||
unsigned int class_base[3]; //Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2)
|
||||
unsigned class_upper : 3; //Specifies if the upper-type can equip it (bitfield, 1: normal, 2: upper, 3: baby)
|
||||
unsigned unused : 5;
|
||||
struct {
|
||||
unsigned short chance;
|
||||
int id;
|
||||
} mob[MAX_SEARCH]; //Holds the mobs that have the highest drop rate for this item. [Skotlex]
|
||||
struct script_code *script; //Default script for everything.
|
||||
struct script_code *equip_script; //Script executed once when equipping.
|
||||
struct script_code *unequip_script;//Script executed once when unequipping.
|
||||
struct {
|
||||
unsigned available : 1;
|
||||
unsigned value_notdc : 1;
|
||||
unsigned value_notoc : 1;
|
||||
short no_equip;
|
||||
unsigned no_refine : 1; // [celest]
|
||||
unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex]
|
||||
unsigned autoequip: 1;
|
||||
unsigned unused:2;
|
||||
unsigned db2: 1; //Items from the custom item database (item_db2)
|
||||
unsigned trade_restriction : 7; //Item restrictions mask [Skotlex]
|
||||
short no_equip;
|
||||
unsigned autoequip: 1;
|
||||
} flag;
|
||||
short gm_lv_trade_override; //GM-level to override trade_restriction
|
||||
struct script_code *script; //Default script for everything.
|
||||
struct script_code *equip_script; //Script executed once when equipping.
|
||||
struct script_code *unequip_script;//Script executed once when unequipping.
|
||||
};
|
||||
|
||||
struct item_group {
|
||||
@ -137,7 +134,7 @@ int itemdb_isidentified(int);
|
||||
int itemdb_isstackable(int);
|
||||
int itemdb_isstackable2(struct item_data *);
|
||||
|
||||
void itemdb_reload(int flag);
|
||||
void itemdb_reload(void);
|
||||
|
||||
void do_final_itemdb(void);
|
||||
int do_init_itemdb(void);
|
||||
|
@ -2310,12 +2310,15 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
{
|
||||
if (md->db->dropitem[i].nameid <= 0)
|
||||
continue;
|
||||
if (!itemdb_exists(md->db->dropitem[i].nameid))
|
||||
continue;
|
||||
drop_rate = md->db->dropitem[i].p;
|
||||
if (drop_rate <= 0) {
|
||||
if (battle_config.drop_rate0item)
|
||||
continue;
|
||||
drop_rate = 1;
|
||||
}
|
||||
|
||||
// change drops depending on monsters size [Valaris]
|
||||
if(md->special_state.size==1 && drop_rate >= 2)
|
||||
drop_rate/=2;
|
||||
@ -2456,6 +2459,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
|
||||
if(md->db->mvpitem[i].nameid <= 0)
|
||||
continue;
|
||||
if(!itemdb_exists(md->db->mvpitem[i].nameid))
|
||||
continue;
|
||||
|
||||
temp = md->db->mvpitem[i].p;
|
||||
if(temp <= 0 && !battle_config.drop_rate0item)
|
||||
|
@ -83,11 +83,6 @@ struct mob_db {
|
||||
struct spawn_info spawn[10];
|
||||
};
|
||||
|
||||
typedef struct mob_db s_mob_db;
|
||||
extern struct mob_db *mob_db_data[MAX_MOB_DB+1];
|
||||
struct mob_db *mob_db(int index);
|
||||
extern struct mob_db *mob_dummy;
|
||||
|
||||
struct mob_data {
|
||||
struct block_list bl;
|
||||
struct unit_data ud;
|
||||
|
@ -150,19 +150,6 @@ struct npc_data* npc_name2id(const char* name)
|
||||
return (struct npc_data *) strdb_get(npcname_db, name);
|
||||
}
|
||||
|
||||
|
||||
/*==========================================
|
||||
* Run function for each npc
|
||||
*------------------------------------------*/
|
||||
|
||||
void npc_foreach(int (*func)(DBKey, void*, va_list), ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, func);
|
||||
npcname_db->vforeach(npcname_db, func, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* イベントキューのイベント処理
|
||||
*------------------------------------------*/
|
||||
@ -1128,7 +1115,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
|
||||
itemdb_viewid(nd->u.shop.shop_item[j].nameid)==item_list[i*2+1]) //item_avail replacement
|
||||
break;
|
||||
}
|
||||
if (nd->u.shop.shop_item[j].nameid == 0)
|
||||
if (nd->u.shop.shop_item[j].nameid == 0 || !itemdb_exists(nd->u.shop.shop_item[j].nameid))
|
||||
return 3;
|
||||
|
||||
if (!itemdb_isstackable(nd->u.shop.shop_item[j].nameid) && item_list[i*2] > 1)
|
||||
@ -1687,8 +1674,9 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
|
||||
|
||||
if( (id = itemdb_exists(nameid)) == NULL )
|
||||
{
|
||||
ShowError("npc_parse_shop: Invalid sell item in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
|
||||
break;
|
||||
ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%d').\n", filepath, strline(buffer,start-buffer), nameid);
|
||||
p = strchr(p+1,',');
|
||||
continue;
|
||||
}
|
||||
|
||||
if( value < 0 )
|
||||
|
@ -146,8 +146,6 @@ int npc_script_event(struct map_session_data* sd, enum npce_event type);
|
||||
|
||||
int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points);
|
||||
|
||||
void npc_foreach(int (*func)(DBKey,void*,va_list), ...);
|
||||
|
||||
extern struct npc_data* fake_nd;
|
||||
|
||||
#endif /* _NPC_H_ */
|
||||
|
@ -2965,12 +2965,11 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type)
|
||||
{
|
||||
nullpo_retr(1, sd);
|
||||
|
||||
if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || (sd->inventory_data[n] == NULL && ~type&4))
|
||||
if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL)
|
||||
return 1;
|
||||
|
||||
sd->status.inventory[n].amount -= amount;
|
||||
if(~type&4)
|
||||
sd->weight -= sd->inventory_data[n]->weight*amount ;
|
||||
sd->weight -= sd->inventory_data[n]->weight*amount ;
|
||||
if(sd->status.inventory[n].amount<=0){
|
||||
if(sd->status.inventory[n].equip)
|
||||
pc_unequipitem(sd,n,3);
|
||||
@ -3458,7 +3457,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, int lv)
|
||||
// Try dropping one item, in the order from first to last possible slot.
|
||||
// Droprate is affected by the skill success rate.
|
||||
for( i = 0; i < MAX_STEAL_DROP; i++ )
|
||||
if( md->db->dropitem[i].nameid > 0 && rand() % 10000 < md->db->dropitem[i].p * rate/100. )
|
||||
if( md->db->dropitem[i].nameid > 0 && itemdb_exists(md->db->dropitem[i].nameid) && rand() % 10000 < md->db->dropitem[i].p * rate/100. )
|
||||
break;
|
||||
if( i == MAX_STEAL_DROP )
|
||||
return 0;
|
||||
|
@ -502,6 +502,7 @@ int pc_reg_received(struct map_session_data *sd);
|
||||
|
||||
int pc_isequip(struct map_session_data *sd,int n);
|
||||
int pc_equippoint(struct map_session_data *sd,int n);
|
||||
int pc_setinventorydata(struct map_session_data *sd);
|
||||
|
||||
int pc_checkskill(struct map_session_data *sd,int skill_id);
|
||||
int pc_checkallowskill(struct map_session_data *sd);
|
||||
|
@ -224,7 +224,7 @@ static int storage_additem(struct map_session_data *sd,struct storage *stor,stru
|
||||
/*==========================================
|
||||
* Internal del-item function
|
||||
*------------------------------------------*/
|
||||
int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount)
|
||||
static int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount)
|
||||
{
|
||||
|
||||
if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount)
|
||||
|
@ -14,7 +14,6 @@ struct map_session_data;
|
||||
int storage_storageopen(struct map_session_data *sd);
|
||||
int storage_storageadd(struct map_session_data *sd,int index,int amount);
|
||||
int storage_storageget(struct map_session_data *sd,int index,int amount);
|
||||
int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount);
|
||||
int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount);
|
||||
int storage_storagegettocart(struct map_session_data *sd,int index,int amount);
|
||||
int storage_storageclose(struct map_session_data *sd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user