summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
authorKevin <Kevin@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-04-27 07:18:21 +0000
committerKevin <Kevin@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-04-27 07:18:21 +0000
commit677598256feaad3bcef53805ad8c70e744a9b7d3 (patch)
tree3a4b061dc62ac53fbd80c1434990a47dca0d54d9 /src/map
parentab60cf06afb586b106991b4b9848dd9c107ddec2 (diff)
downloadhercules-677598256feaad3bcef53805ad8c70e744a9b7d3.tar.gz
hercules-677598256feaad3bcef53805ad8c70e744a9b7d3.tar.bz2
hercules-677598256feaad3bcef53805ad8c70e744a9b7d3.tar.xz
hercules-677598256feaad3bcef53805ad8c70e744a9b7d3.zip
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. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@12661 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map')
-rw-r--r--src/map/clif.c31
-rw-r--r--src/map/itemdb.c156
-rw-r--r--src/map/mob.h5
-rw-r--r--src/map/npc.c13
-rw-r--r--src/map/npc.h2
-rw-r--r--src/map/pc.c5
-rw-r--r--src/map/storage.c2
-rw-r--r--src/map/storage.h2
8 files changed, 188 insertions, 28 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 55e9b1776..66a01b867 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1894,20 +1894,27 @@ void clif_storagelist(struct map_session_data *sd,struct storage *stor)
if(stor->storage_[i].nameid<=0)
continue;
id = itemdb_search(stor->storage_[i].nameid);
- if(!itemdb_isstackable2(id))
- { //Equippable
- WBUFW(bufe,ne*20+4)=i+1;
- clif_item_sub(bufe, ne*20+6, &stor->storage_[i], id, id->equip);
- clif_addcards(WBUFP(bufe, ne*20+16), &stor->storage_[i]);
- ne++;
- } else { //Stackable
- WBUFW(buf,n*s+4)=i+1;
- clif_item_sub(buf, n*s+6, &stor->storage_[i], id,-1);
+ if(!id)
+ {
+ //Item not found, was probably deleted and then map server reloaded/item db reloaded
+ storage_delitem(sd, stor, i, stor->storage_[i].amount);
+ return;
+ }
+ else
+ if(!itemdb_isstackable2(id))
+ { //Equippable
+ WBUFW(bufe,ne*20+4)=i+1;
+ clif_item_sub(bufe, ne*20+6, &stor->storage_[i], id, id->equip);
+ clif_addcards(WBUFP(bufe, ne*20+16), &stor->storage_[i]);
+ ne++;
+ } else { //Stackable
+ WBUFW(buf,n*s+4)=i+1;
+ clif_item_sub(buf, n*s+6, &stor->storage_[i], id,-1);
#if PACKETVER >= 5
- clif_addcards(WBUFP(buf,n*s+14), &stor->storage_[i]);
+ clif_addcards(WBUFP(buf,n*s+14), &stor->storage_[i]);
#endif
- n++;
- }
+ n++;
+ }
}
if(n){
#if PACKETVER < 5
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 442508775..6cfbbca97 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -10,6 +10,10 @@
#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>
@@ -1008,6 +1012,22 @@ static void destroy_item_data(struct item_data* self, int free_self)
aFree(self);
}
+/*==========================================
+ * Looks for an item, returns NULL if not found
+ *------------------------------------------*/
+struct item_data* itemdb_search2(int nameid)
+{
+ if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
+ {
+ DBKey key;
+ if( itemdb_array[nameid] )
+ return itemdb_array[nameid];
+ key.i = nameid;
+ return NULL;
+ }
+ return (struct item_data*)idb_get(itemdb_other,nameid);
+}
+
static int itemdb_final_sub(DBKey key,void *data,va_list ap)
{
struct item_data *id = (struct item_data *)data;
@@ -1018,32 +1038,142 @@ static int itemdb_final_sub(DBKey key,void *data,va_list ap)
return 0;
}
-static int itemdb_reload_sub(DBKey key,void *data,va_list ap)
+int itemdb_reload_check_npc(DBKey key,void * data,va_list ap)
{
- struct item_data *id = (struct item_data *)data;
+ struct npc_data * nd = (struct npc_data *)data;
+ int offset = 0, i = 0;
- if( id != &dummy_item && id->flag.db2)
- destroy_item_data(id, 1);
+ if(nd->subtype != SHOP && nd->subtype != CASHSHOP)
+ return 0;
+
+ while(i < nd->u.shop.count)
+ {
+
+ if(itemdb_search2(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;
}
-void itemdb_reload(void)
+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;
- for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
- if( itemdb_array[i] )
- if( itemdb_array[i]->flag.db2 )
+ 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_search2(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_search2(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++)
{
- destroy_item_data(itemdb_array[i], 1);
- memset(itemdb_array[i], 0, sizeof(struct item_data));
+ if(!sd->status.inventory[i].nameid)
+ continue;
+
+ if(itemdb_search2(sd->status.inventory[i].nameid) == NULL)
+ storage_delitem(sd, stor, i, stor->storage_[i].amount);
}
+ }
+ }
- itemdb_other->clear(itemdb_other, itemdb_reload_sub);
+ return 0;
+}
- itemdb_read();
+//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_search2(mdb->dropitem[j].nameid);
+ if(id == NULL)
+ {
+ mdb->dropitem[j].nameid = 0;
+ mdb->dropitem[j].p = 0;
+ }
+ }
+ }
+}
+
+void itemdb_reload(void)
+{
+
+ do_final_itemdb();
+ do_init_itemdb();
+
+ //Update ALL items on the server
+ map_foreachpc(itemdb_reload_check);
+ npc_foreach(itemdb_reload_check_npc);
+ itemdb_foreach_mobdb();
}
void do_final_itemdb(void)
diff --git a/src/map/mob.h b/src/map/mob.h
index f01b4fff1..44fae102e 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -83,6 +83,11 @@ 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;
diff --git a/src/map/npc.c b/src/map/npc.c
index 98dd2d609..f1ff119da 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -150,6 +150,19 @@ 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);
+}
+
/*==========================================
* イベントキューのイベント処理
*------------------------------------------*/
diff --git a/src/map/npc.h b/src/map/npc.h
index f75ede9c5..93fb3fa60 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -146,6 +146,8 @@ 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_ */
diff --git a/src/map/pc.c b/src/map/pc.c
index 29dfd1b30..7d268a0f5 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -2965,11 +2965,12 @@ 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)
+ if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || (sd->inventory_data[n] == NULL && ~type&4))
return 1;
sd->status.inventory[n].amount -= amount;
- sd->weight -= sd->inventory_data[n]->weight*amount ;
+ if(~type&4)
+ 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);
diff --git a/src/map/storage.c b/src/map/storage.c
index c2e4bf5f7..f43ee7f04 100644
--- a/src/map/storage.c
+++ b/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
*------------------------------------------*/
-static int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount)
+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)
diff --git a/src/map/storage.h b/src/map/storage.h
index 6764d4956..fa33e2050 100644
--- a/src/map/storage.h
+++ b/src/map/storage.h
@@ -11,9 +11,11 @@ struct item;
//#include "map.h"
struct map_session_data;
+struct storage *account2storage2(int account_id);
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);