Переглянути джерело

* Added item stacking limit database (item_stack.txt) required for runes and other 3rd class related skill items.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/renewal@14635 54d463be-8e91-2dee-dedb-b68131a5f0ec
ai4rei 14 роки тому
батько
коміт
8b9b627e1e
7 змінених файлів з 113 додано та 6 видалено
  1. 1 0
      Changelog-Renewal.txt
  2. 2 0
      db/Changelog.txt
  3. 27 0
      db/item_stack.txt
  4. 41 0
      src/map/itemdb.c
  5. 8 0
      src/map/itemdb.h
  6. 22 4
      src/map/pc.c
  7. 12 2
      src/map/storage.c

+ 1 - 0
Changelog-Renewal.txt

@@ -1,6 +1,7 @@
 Date	Added
 
 2010/12/27
+	* Added item stacking limit database (item_stack.txt) required for runes and other 3rd class related skill items. [Ai4rei]
 	* Merged fixes from trunk for script command 'checkweight' (r14631) and skill-based item production (r14633). [Ai4rei]
 2010/12/26
 	* Merged changes from trunk (r14496:14630). [Ai4rei]

+ 2 - 0
db/Changelog.txt

@@ -8,6 +8,8 @@
 	1475 Equestrian's Spear:	NEED INFO.
 	13005 Angelic Wing Dagger:	NEED INFO.
 =======================
+2010/12/27
+	* Rev. 14634 Added item stacking limitation database 'item_stack.txt'. [Ai4rei]
 2010/12/16
 	* Rev. 14596 Added missing pet db documentation for fields 'attack_rate', 'defence_attack_rate', 'change_target_rate', 'pet_script' and 'loyal_script' based on the one provided by frenzmu06 (bugreport:4636, follow up to r13752). [Ai4rei]
 2010/12/13

+ 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

+ 41 - 0
src/map/itemdb.c

@@ -724,6 +724,46 @@ static int itemdb_read_itemdelay(void)
 	return 0;
 }
 
+/*==================================================================
+ * 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;
+}
+
 /*======================================
  * Applies gender restrictions according to settings. [Skotlex]
  *======================================*/
@@ -1040,6 +1080,7 @@ static void itemdb_read(void)
 	itemdb_read_noequip();
 	itemdb_read_itemtrade();
 	itemdb_read_itemdelay();
+	sv_readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack);
 }
 
 /*==========================================

+ 8 - 0
src/map/itemdb.h

@@ -77,6 +77,14 @@ struct item_data {
 		unsigned trade_restriction : 7;	//Item restrictions mask [Skotlex]
 		unsigned autoequip: 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
 };
 

+ 22 - 4
src/map/pc.c

@@ -3200,18 +3200,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;
 		}
@@ -3349,6 +3356,12 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
 		return 5;
 	
 	data = itemdb_search(item_data->nameid);
+
+	if( data->stack.inventory && amount > data->stack.amount )
+	{// item stack limitation
+		return 5;
+	}
+
 	w = data->weight*amount;
 	if(sd->weight + w > sd->max_weight)
 		return 2;
@@ -3361,7 +3374,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
 		{
 			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);
@@ -3787,6 +3800,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_isGM(sd)) )
 	{ // Check item trade restrictions	[Skotlex]
 		clif_displaymessage (sd->fd, msg_txt(264));
@@ -3807,7 +3825,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

@@ -138,6 +138,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_isGM(sd)) )
 	{	//Check if item is storable. [Skotlex]
 		clif_displaymessage (sd->fd, msg_txt(264));
@@ -150,7 +155,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);
@@ -398,6 +403,11 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
 	if(item_data->nameid <= 0 || amount <= 0)
 		return 1;
 
+	if( data->stack.guildstorage && amount > data->stack.amount )
+	{// item stack limitation
+		return 1;
+	}
+
 	if( !itemdb_canguildstore(item_data, pc_isGM(sd)) || item_data->expire_time )
 	{	//Check if item is storable. [Skotlex]
 		clif_displaymessage (sd->fd, msg_txt(264));
@@ -407,7 +417,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);