summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--db/item_stack.txt27
-rw-r--r--src/map/itemdb.c51
-rw-r--r--src/map/itemdb.h8
-rw-r--r--src/map/pc.c25
-rw-r--r--src/map/storage.c14
5 files changed, 114 insertions, 11 deletions
diff --git a/db/item_stack.txt b/db/item_stack.txt
new file mode 100644
index 000000000..b2932b56b
--- /dev/null
+++ b/db/item_stack.txt
@@ -0,0 +1,27 @@
+// Item Stacking Restriction File
+// Prevents an item to be stacked more than x times in given
+// inventory types. Generally used by 3rd class related skill items.
+// Format: <item id>,<stack limit amount>,<type>
+// Type mask values:
+// &1: Character inventory restriction
+// &2: Character cart restriction
+// &4: Account storage restriction
+// &8: Guild storage restriction
+// Example:
+// 512,4,12 // Will not allow more than 4 Apples in storages.
+// Note:
+// Stack limit of 0 will disable a restriction.
+
+// Rune Knight
+12725,20,1 // Nauthiz Rune
+12726,20,1 // Raido Rune
+12727,20,1 // Berkana Rune
+12728,20,1 // Isa Rune
+12729,20,1 // Othila Rune
+12730,20,1 // Uruz Rune
+12731,20,1 // Thurisaz Rune
+12732,20,1 // Wyrd Rune
+12733,20,1 // Hagalaz Rune
+
+// Arch Bishop
+12333,3,1 // Ancilla
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 7059cbee7..f7b2da7cb 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -670,6 +670,46 @@ static bool itemdb_read_itemdelay(char* str[], int columns, int current)
return true;
}
+/*==================================================================
+ * Reads item stacking restrictions
+ *----------------------------------------------------------------*/
+static bool itemdb_read_stack(char* fields[], int columns, int current)
+{// <item id>,<stack limit amount>,<type>
+ unsigned short nameid, amount;
+ unsigned int type;
+ struct item_data* id;
+
+ nameid = (unsigned short)strtoul(fields[0], NULL, 10);
+
+ if( ( id = itemdb_exists(nameid) ) == NULL )
+ {
+ ShowWarning("itemdb_read_stack: Unknown item id '%hu'.\n", nameid);
+ return false;
+ }
+
+ if( !itemdb_isstackable2(id) )
+ {
+ ShowWarning("itemdb_read_stack: Item id '%hu' is not stackable.\n", nameid);
+ return false;
+ }
+
+ amount = (unsigned short)strtoul(fields[1], NULL, 10);
+ type = strtoul(fields[2], NULL, 10);
+
+ if( !amount )
+ {// ignore
+ return true;
+ }
+
+ id->stack.amount = amount;
+ id->stack.inventory = (type&1)!=0;
+ id->stack.cart = (type&2)!=0;
+ id->stack.storage = (type&4)!=0;
+ id->stack.guildstorage = (type&8)!=0;
+
+ return true;
+}
+
/// Reads items allowed to be sold in buying stores
static bool itemdb_read_buyingstore(char* fields[], int columns, int current)
@@ -1050,11 +1090,12 @@ static void itemdb_read(void)
itemdb_readdb();
itemdb_read_itemgroup();
- sv_readdb(db_path, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail);
- sv_readdb(db_path, DBPATH"item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip);
- sv_readdb(db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade);
- sv_readdb(db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay);
- sv_readdb(db_path, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore);
+ sv_readdb(db_path, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail);
+ sv_readdb(db_path, DBPATH"item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip);
+ sv_readdb(db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade);
+ sv_readdb(db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay);
+ sv_readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack);
+ sv_readdb(db_path, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore);
}
/*==========================================
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 5471fe7e6..539bd2cce 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -125,6 +125,14 @@ struct item_data {
unsigned autoequip: 1;
unsigned buyingstore : 1;
} flag;
+ struct
+ {// item stacking limitation
+ unsigned short amount;
+ unsigned int inventory:1;
+ unsigned int cart:1;
+ unsigned int storage:1;
+ unsigned int guildstorage:1;
+ } stack;
short gm_lv_trade_override; //GM-level to override trade_restriction
};
diff --git a/src/map/pc.c b/src/map/pc.c
index 26f60c0af..b6f71d8e6 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -3433,19 +3433,25 @@ int pc_modifysellvalue(struct map_session_data *sd,int orig_value)
int pc_checkadditem(struct map_session_data *sd,int nameid,int amount)
{
int i;
+ struct item_data* data;
nullpo_ret(sd);
if(amount > MAX_AMOUNT)
return ADDITEM_OVERAMOUNT;
- if(!itemdb_isstackable(nameid))
+ data = itemdb_search(nameid);
+
+ if(!itemdb_isstackable2(data))
return ADDITEM_NEW;
+ if( data->stack.inventory && amount > data->stack.amount )
+ return ADDITEM_OVERAMOUNT;
+
for(i=0;i<MAX_INVENTORY;i++){
// FIXME: This does not consider the checked item's cards, thus could check a wrong slot for stackability.
if(sd->status.inventory[i].nameid==nameid){
- if(sd->status.inventory[i].amount+amount > MAX_AMOUNT)
+ if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
return ADDITEM_OVERAMOUNT;
return ADDITEM_EXIST;
}
@@ -3644,6 +3650,12 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
return 5;
data = itemdb_search(item_data->nameid);
+
+ if( data->stack.inventory && amount > data->stack.amount )
+ {// item stack limitation
+ return 7;
+ }
+
w = data->weight*amount;
if(sd->weight + w > sd->max_weight)
return 2;
@@ -3664,7 +3676,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
{
if( sd->status.inventory[i].nameid == item_data->nameid && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
{
- if( amount > MAX_AMOUNT - sd->status.inventory[i].amount )
+ if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
return 5;
sd->status.inventory[i].amount += amount;
clif_additem(sd,i,amount,0);
@@ -4122,6 +4134,11 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
return 1;
data = itemdb_search(item_data->nameid);
+ if( data->stack.cart && amount > data->stack.amount )
+ {// item stack limitation
+ return 1;
+ }
+
if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) )
{ // Check item trade restrictions [Skotlex]
clif_displaymessage (sd->fd, msg_txt(264));
@@ -4142,7 +4159,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
if( i < MAX_CART )
{// item already in cart, stack it
- if(sd->status.cart[i].amount+amount > MAX_AMOUNT)
+ if( amount > MAX_AMOUNT - sd->status.cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->status.cart[i].amount ) )
return 1; // no room
sd->status.cart[i].amount+=amount;
diff --git a/src/map/storage.c b/src/map/storage.c
index d9ab0312f..0bf575c84 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -140,6 +140,11 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
data = itemdb_search(item_data->nameid);
+ if( data->stack.storage && amount > data->stack.amount )
+ {// item stack limitation
+ return 1;
+ }
+
if( !itemdb_canstore(item_data, pc_get_group_level(sd)) )
{ //Check if item is storable. [Skotlex]
clif_displaymessage (sd->fd, msg_txt(264));
@@ -152,7 +157,7 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
{
if( compare_item(&stor->items[i], item_data) )
{// existing items found, stack them
- if( amount > MAX_AMOUNT - stor->items[i].amount )
+ if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) )
return 1;
stor->items[i].amount += amount;
clif_storageitemadded(sd,&stor->items[i],i,amount);
@@ -396,6 +401,11 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
data = itemdb_search(item_data->nameid);
+ if( data->stack.guildstorage && amount > data->stack.amount )
+ {// item stack limitation
+ return 1;
+ }
+
if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time )
{ //Check if item is storable. [Skotlex]
clif_displaymessage (sd->fd, msg_txt(264));
@@ -405,7 +415,7 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
if(itemdb_isstackable2(data)){ //Stackable
for(i=0;i<MAX_GUILD_STORAGE;i++){
if(compare_item(&stor->items[i], item_data)) {
- if(stor->items[i].amount+amount > MAX_AMOUNT)
+ if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.guildstorage && amount > data->stack.amount - stor->items[i].amount ) )
return 1;
stor->items[i].amount+=amount;
clif_storageitemadded(sd,&stor->items[i],i,amount);