浏览代码

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

ultramage 17 年之前
父节点
当前提交
7a9a3a12bb
共有 14 个文件被更改,包括 57 次插入227 次删除
  1. 0 10
      Changelog-Trunk.txt
  2. 0 3
      conf/atcommand_athena.conf
  3. 1 15
      src/map/atcommand.c
  4. 15 8
      src/map/clif.c
  5. 20 152
      src/map/itemdb.c
  6. 7 10
      src/map/itemdb.h
  7. 5 0
      src/map/mob.c
  8. 0 5
      src/map/mob.h
  9. 4 16
      src/map/npc.c
  10. 0 2
      src/map/npc.h
  11. 3 4
      src/map/pc.c
  12. 1 0
      src/map/pc.h
  13. 1 1
      src/map/storage.c
  14. 0 1
      src/map/storage.h

+ 0 - 10
Changelog-Trunk.txt

@@ -3,16 +3,6 @@ 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/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
 2008/04/26
 	* Added script function hasquest. [Kevin]
 	* Added script function hasquest. [Kevin]
 	* Fixed OnGuildBreak. [Kevin]
 	* Fixed OnGuildBreak. [Kevin]

+ 0 - 3
conf/atcommand_athena.conf

@@ -700,9 +700,6 @@ mapflag: 99
 // Re-load item database (admin command)
 // Re-load item database (admin command)
 reloaditemdb: 99
 reloaditemdb: 99
 
 
-// Re-load item database and delete all references to it (admin command)
-reloaditemdb2: 99
-
 // Re-load monsters database (admin command)
 // Re-load monsters database (admin command)
 reloadmobdb: 99
 reloadmobdb: 99
 
 

+ 1 - 15
src/map/atcommand.c

@@ -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)
 int atcommand_reloaditemdb(const int fd, struct map_session_data* sd, const char* command, const char* message)
 {
 {
 	nullpo_retr(-1, sd);
 	nullpo_retr(-1, sd);
-	itemdb_reload(0);
+	itemdb_reload();
 	clif_displaymessage(fd, msg_txt(97)); // Item database reloaded.
 	clif_displaymessage(fd, msg_txt(97)); // Item database reloaded.
 
 
 	return 0;
 	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
 	{ "localbroadcast",    40,     atcommand_localbroadcast }, // + /lb and /nlb
 	{ "recallall",         80,     atcommand_recallall },
 	{ "recallall",         80,     atcommand_recallall },
 	{ "reloaditemdb",      99,     atcommand_reloaditemdb },
 	{ "reloaditemdb",      99,     atcommand_reloaditemdb },
-	{ "reloaditemdb2",      99,     atcommand_reloaditemdb2 },
 	{ "reloadmobdb",       99,     atcommand_reloadmobdb },
 	{ "reloadmobdb",       99,     atcommand_reloadmobdb },
 	{ "reloadskilldb",     99,     atcommand_reloadskilldb },
 	{ "reloadskilldb",     99,     atcommand_reloadskilldb },
 	{ "reloadscript",      99,     atcommand_reloadscript },
 	{ "reloadscript",      99,     atcommand_reloadscript },

+ 15 - 8
src/map/clif.c

@@ -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 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, sd);
 	nullpo_retr(0, nd);
 	nullpo_retr(0, nd);
 
 
 	fd = sd->fd;
 	fd = sd->fd;
- 	WFIFOHEAD(fd, 200 * 11 + 4);
+ 	WFIFOHEAD(fd, 4 + nd->u.shop.count * 11);
 	WFIFOW(fd,0) = 0xc6;
 	WFIFOW(fd,0) = 0xc6;
-	WFIFOW(fd,2) = 4 + nd->u.shop.count*11;
+
+	c = 0;
 	for( i = 0; i < nd->u.shop.count; i++ )
 	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;
 		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)
 		if (!id->flag.value_notdc)
 			val = pc_modifybuyvalue(sd,val);
 			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));
 	WFIFOSET(fd,WFIFOW(fd,2));
 
 
 	return 0;
 	return 0;
@@ -8838,6 +8844,7 @@ void clif_parse_NpcBuyListSend(int fd,struct map_session_data *sd)
 		fail = npc_buylist(sd,n,item_list);
 		fail = npc_buylist(sd,n,item_list);
 
 
 	sd->npc_shopid = 0; //Clear shop data.
 	sd->npc_shopid = 0; //Clear shop data.
+
 	WFIFOHEAD(fd,packet_len(0xca));
 	WFIFOHEAD(fd,packet_len(0xca));
 	WFIFOW(fd,0)=0xca;
 	WFIFOW(fd,0)=0xca;
 	WFIFOB(fd,2)=fail;
 	WFIFOB(fd,2)=fail;

+ 20 - 152
src/map/itemdb.c

@@ -10,10 +10,6 @@
 #include "battle.h" // struct battle_config
 #include "battle.h" // struct battle_config
 #include "script.h" // item script processing
 #include "script.h" // item script processing
 #include "pc.h"     // W_MUSICAL, W_WHIP
 #include "pc.h"     // W_MUSICAL, W_WHIP
-#include "storage.h"
-#include "npc.h"
-#include "clif.h"
-#include "mob.h"
 
 
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
@@ -693,7 +689,7 @@ static int itemdb_gendercheck(struct item_data *id)
 /*==========================================
 /*==========================================
  * processes one itemdb entry
  * 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->name, str[1], sizeof(id->name));
 	safestrncpy(id->jname, str[2], sizeof(id->jname));
 	safestrncpy(id->jname, str[2], sizeof(id->jname));
 
 
-	if(db == 1)
-		id->flag.db2 = 1;
-
 	id->type = atoi(str[3]);
 	id->type = atoi(str[3]);
 	if (id->type == IT_DELAYCONSUME)
 	if (id->type == IT_DELAYCONSUME)
 	{	//Items that are consumed only after target confirmation
 	{	//Items that are consumed only after target confirmation
@@ -907,7 +900,8 @@ static int itemdb_readdb(void)
 			}
 			}
 			str[21] = p;
 			str[21] = p;
 
 
-			if (!itemdb_parse_dbrow(str, path, lines, 0, fi))
+
+			if (!itemdb_parse_dbrow(str, path, lines, 0))
 				continue;
 				continue;
 
 
 			count++;
 			count++;
@@ -954,7 +948,7 @@ static int itemdb_read_sqldb(void)
 				if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns
 				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;
 				continue;
 			++count;
 			++count;
 		}
 		}
@@ -1012,13 +1006,6 @@ static void destroy_item_data(struct item_data* self, int free_self)
 		aFree(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)
 static int itemdb_final_sub(DBKey key,void *data,va_list ap)
 {
 {
 	struct item_data *id = (struct item_data *)data;
 	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;
 	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;
-
-	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;
-}
+	struct s_mapiterator* iter;
+	struct map_session_data* sd;
 
 
-static int itemdb_reload_check(DBKey key,void *data,va_list ap)
-{
 	int i;
 	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);
-	}
-
-	//First, handle all items in inventories/equiped, cart, and storage
-	for(i = 0; i < MAX_INVENTORY; i++)
-	{
-		if(!sd->status.inventory[i].nameid)
-			continue;
-
-		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;
-		}
-	}
 
 
-	//Delete nonexistant items from cart
-	for(i = 0; i < MAX_CART; i++)
-	{
-		if(!sd->status.cart[i].nameid)
-			continue;
-
-		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;
+	// clear the previous itemdb data
+	for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
+		if( itemdb_array[i] )
+			destroy_item_data(itemdb_array[i], 1);
 
 
-	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
+	itemdb_other->clear(itemdb_other, itemdb_final_sub);
 
 
-void itemdb_reload(int flag)
-{
+	memset(itemdb_array, 0, sizeof(itemdb_array));
 
 
-	do_final_itemdb();
-	do_init_itemdb();
+	// read new data
+	itemdb_read();
 
 
-	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)
 void do_final_itemdb(void)

+ 7 - 10
src/map/itemdb.h

@@ -34,8 +34,8 @@
 #define UNKNOWN_ITEM_ID 512
 #define UNKNOWN_ITEM_ID 512
 
 
 struct item_data {
 struct item_data {
-	char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
 	int nameid;
 	int nameid;
+	char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
 	//Do not add stuff between value_buy and wlv (see how getiteminfo works)
 	//Do not add stuff between value_buy and wlv (see how getiteminfo works)
 	int value_buy;
 	int value_buy;
 	int value_sell;
 	int value_sell;
@@ -56,27 +56,24 @@ struct item_data {
 //		some script commands should be revised as well...
 //		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 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 class_upper : 3; //Specifies if the upper-type can equip it (bitfield, 1: normal, 2: upper, 3: baby)
-	unsigned unused : 5;
 	struct {
 	struct {
 		unsigned short chance;
 		unsigned short chance;
 		int id;
 		int id;
 	} mob[MAX_SEARCH]; //Holds the mobs that have the highest drop rate for this item. [Skotlex]
 	} 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 {
 	struct {
 		unsigned available : 1;
 		unsigned available : 1;
 		unsigned value_notdc : 1;
 		unsigned value_notdc : 1;
 		unsigned value_notoc : 1;
 		unsigned value_notoc : 1;
+		short no_equip;
 		unsigned no_refine : 1;	// [celest]
 		unsigned no_refine : 1;	// [celest]
 		unsigned delay_consume : 1;	// Signifies items that are not consumed immediately upon double-click [Skotlex]
 		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]
 		unsigned trade_restriction : 7;	//Item restrictions mask [Skotlex]
-		short no_equip;
+		unsigned autoequip: 1;
 	} flag;
 	} flag;
 	short gm_lv_trade_override;	//GM-level to override trade_restriction
 	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 {
 struct item_group {
@@ -137,7 +134,7 @@ int itemdb_isidentified(int);
 int itemdb_isstackable(int);
 int itemdb_isstackable(int);
 int itemdb_isstackable2(struct item_data *);
 int itemdb_isstackable2(struct item_data *);
 
 
-void itemdb_reload(int flag);
+void itemdb_reload(void);
 
 
 void do_final_itemdb(void);
 void do_final_itemdb(void);
 int do_init_itemdb(void);
 int do_init_itemdb(void);

+ 5 - 0
src/map/mob.c

@@ -2310,12 +2310,15 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 		{
 		{
 			if (md->db->dropitem[i].nameid <= 0)
 			if (md->db->dropitem[i].nameid <= 0)
 				continue;
 				continue;
+			if (!itemdb_exists(md->db->dropitem[i].nameid))
+				continue;
 			drop_rate = md->db->dropitem[i].p;
 			drop_rate = md->db->dropitem[i].p;
 			if (drop_rate <= 0) {
 			if (drop_rate <= 0) {
 				if (battle_config.drop_rate0item)
 				if (battle_config.drop_rate0item)
 					continue;
 					continue;
 				drop_rate = 1;
 				drop_rate = 1;
 			}
 			}
+
 			// change drops depending on monsters size [Valaris]
 			// change drops depending on monsters size [Valaris]
 			if(md->special_state.size==1 && drop_rate >= 2)
 			if(md->special_state.size==1 && drop_rate >= 2)
 				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)
 			if(md->db->mvpitem[i].nameid <= 0)
 				continue;
 				continue;
+			if(!itemdb_exists(md->db->mvpitem[i].nameid))
+				continue;
 			
 			
 			temp = md->db->mvpitem[i].p;
 			temp = md->db->mvpitem[i].p;
 			if(temp <= 0 && !battle_config.drop_rate0item)
 			if(temp <= 0 && !battle_config.drop_rate0item)

+ 0 - 5
src/map/mob.h

@@ -83,11 +83,6 @@ struct mob_db {
 	struct spawn_info spawn[10];
 	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 mob_data {
 	struct block_list bl;
 	struct block_list bl;
 	struct unit_data  ud;
 	struct unit_data  ud;

+ 4 - 16
src/map/npc.c

@@ -150,19 +150,6 @@ struct npc_data* npc_name2id(const char* name)
 	return (struct npc_data *) strdb_get(npcname_db, 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
 				itemdb_viewid(nd->u.shop.shop_item[j].nameid)==item_list[i*2+1]) //item_avail replacement
 				break;
 				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;
 			return 3;
 
 
 		if (!itemdb_isstackable(nd->u.shop.shop_item[j].nameid) && item_list[i*2] > 1)
 		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 )
 		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 )
 		if( value < 0 )

+ 0 - 2
src/map/npc.h

@@ -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);
 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;
 extern struct npc_data* fake_nd;
 
 
 #endif /* _NPC_H_ */
 #endif /* _NPC_H_ */

+ 3 - 4
src/map/pc.c

@@ -2965,12 +2965,11 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type)
 {
 {
 	nullpo_retr(1, sd);
 	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;
 		return 1;
 
 
 	sd->status.inventory[n].amount -= amount;
 	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].amount<=0){
 		if(sd->status.inventory[n].equip)
 		if(sd->status.inventory[n].equip)
 			pc_unequipitem(sd,n,3);
 			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.
 	// Try dropping one item, in the order from first to last possible slot.
 	// Droprate is affected by the skill success rate.
 	// Droprate is affected by the skill success rate.
 	for( i = 0; i < MAX_STEAL_DROP; i++ )
 	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;
 			break;
 	if( i == MAX_STEAL_DROP )
 	if( i == MAX_STEAL_DROP )
 		return 0;
 		return 0;

+ 1 - 0
src/map/pc.h

@@ -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_isequip(struct map_session_data *sd,int n);
 int pc_equippoint(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_checkskill(struct map_session_data *sd,int skill_id);
 int pc_checkallowskill(struct map_session_data *sd);
 int pc_checkallowskill(struct map_session_data *sd);

+ 1 - 1
src/map/storage.c

@@ -224,7 +224,7 @@ static int storage_additem(struct map_session_data *sd,struct storage *stor,stru
 /*==========================================
 /*==========================================
  * Internal del-item function
  * 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)
 	if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount)

+ 0 - 1
src/map/storage.h

@@ -14,7 +14,6 @@ struct map_session_data;
 int storage_storageopen(struct map_session_data *sd);
 int storage_storageopen(struct map_session_data *sd);
 int storage_storageadd(struct map_session_data *sd,int index,int amount);
 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_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_storageaddfromcart(struct map_session_data *sd,int index,int amount);
 int storage_storagegettocart(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);
 int storage_storageclose(struct map_session_data *sd);