瀏覽代碼

* Merged /branches/renewal/ r14635 Item Stacking System to /trunk (follow up to r15060) pid:106973

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16279 54d463be-8e91-2dee-dedb-b68131a5f0ec
brianluau 13 年之前
父節點
當前提交
6261742ed4
共有 5 個文件被更改,包括 114 次插入11 次删除
  1. 27 0
      db/item_stack.txt
  2. 46 5
      src/map/itemdb.c
  3. 8 0
      src/map/itemdb.h
  4. 21 4
      src/map/pc.c
  5. 12 2
      src/map/storage.c

+ 27 - 0
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

+ 46 - 5
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);
 }
 
 /*==========================================

+ 8 - 0
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
 };
 

+ 21 - 4
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;

+ 12 - 2
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);