diff --git a/src/map/cashshop.cpp b/src/map/cashshop.cpp index df26abde73..862a02e59a 100644 --- a/src/map/cashshop.cpp +++ b/src/map/cashshop.cpp @@ -471,6 +471,7 @@ bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u uint32 totalcash = 0; uint32 totalweight = 0; int i,new_; + item_data *id; #if PACKETVER_SUPPORTS_SALES struct sale_item_data* sale = NULL; #endif @@ -504,13 +505,11 @@ bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u } nameid = *( item_list + i * 5 ) = cash_shop_items[tab].item[j]->nameid; //item_avail replacement + id = itemdb_exists(nameid); - if( !itemdb_exists( nameid ) ){ + if( !id ){ clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_UNKONWN_ITEM ); return false; - }else if( !itemdb_isstackable( nameid ) && quantity > 1 ){ - /* ShowWarning( "Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable cash item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, quantity, nameid ); */ - quantity = *( item_list + i * 5 + 2 ) = 1; } if( quantity > 99 ){ @@ -544,7 +543,7 @@ bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u break; case CHKADDITEM_NEW: - new_++; + new_ += id->inventorySlotNeeded(quantity); break; case CHKADDITEM_OVERAMOUNT: @@ -580,13 +579,10 @@ bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u if (!id) continue; - if (!itemdb_isstackable2(id) && quantity > 1) - quantity = 1; - if (!pet_create_egg(sd, nameid)) { unsigned short get_amt = quantity, j; - if (id->flag.guid) + if (id->flag.guid || !itemdb_isstackable2(id)) get_amt = 1; for (j = 0; j < quantity; j += get_amt) { diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index 46b662852b..98bd999a54 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -502,19 +502,9 @@ bool itemdb_isequip2(struct item_data *id) { bool itemdb_isstackable2(struct item_data *id) { nullpo_ret(id); - switch(id->type) { - case IT_WEAPON: - case IT_ARMOR: - case IT_PETEGG: - case IT_PETARMOR: - case IT_SHADOWGEAR: - return false; - default: - return true; - } + return id->isStackable(); } - /*========================================== * Trade Restriction functions [Skotlex] *------------------------------------------*/ @@ -1981,6 +1971,24 @@ static int itemdb_randomopt_free(DBKey key, DBData *data, va_list ap) { return 1; } +bool item_data::isStackable() +{ + switch (this->type) { + case IT_WEAPON: + case IT_ARMOR: + case IT_PETEGG: + case IT_PETARMOR: + case IT_SHADOWGEAR: + return false; + } + return true; +} + +int item_data::inventorySlotNeeded(int quantity) +{ + return (this->flag.guid || !this->isStackable()) ? quantity : 1; +} + /** * Reload Item DB */ diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp index 91b263bc78..564a80ca17 100644 --- a/src/map/itemdb.hpp +++ b/src/map/itemdb.hpp @@ -861,6 +861,9 @@ struct item_data struct item_combo **combos; unsigned char combos_count; short delay_sc; ///< Use delay group if any instead using player's item_delay data [Cydh] + + bool isStackable(); + int inventorySlotNeeded(int quantity); }; // Struct for item random option [Secret] diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 369cf18558..b0523ecfc0 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -1563,6 +1563,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns unsigned short nameid; struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid); enum e_CASHSHOP_ACK res; + item_data *id; if( !nd || ( nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) ) return ERROR_TYPE_NPC; @@ -1578,8 +1579,9 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns { nameid = item_list[i*2+1]; amount = item_list[i*2+0]; + id = itemdb_exists(nameid); - if( !itemdb_exists(nameid) || amount <= 0 ) + if( !id || amount <= 0 ) return ERROR_TYPE_ITEM_ID; ARR_FIND(0,nd->u.shop.count,j,nd->u.shop.shop_item[j].nameid == nameid || itemdb_viewid(nd->u.shop.shop_item[j].nameid) == nameid); @@ -1588,7 +1590,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns nameid = item_list[i*2+1] = nd->u.shop.shop_item[j].nameid; //item_avail replacement - if( !itemdb_isstackable(nameid) && amount > 1 ) + if( !itemdb_isstackable2(id) && amount > 1 ) { ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); amount = item_list[i*2+0] = 1; @@ -1597,7 +1599,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns switch( pc_checkadditem(sd,nameid,amount) ) { case CHKADDITEM_NEW: - new_++; + new_ += id->inventorySlotNeeded(amount); break; case CHKADDITEM_OVERAMOUNT: return ERROR_TYPE_INVENTORY_WEIGHT; @@ -1739,7 +1741,7 @@ int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amo nameid = nd->u.shop.shop_item[i].nameid; //item_avail replacement - if(!itemdb_isstackable(nameid) && amount > 1) + if(!itemdb_isstackable2(item) && amount > 1) { ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); @@ -1749,7 +1751,7 @@ int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amo switch( pc_checkadditem(sd, nameid, amount) ) { case CHKADDITEM_NEW: - if( pc_inventoryblank(sd) == 0 ) + if( pc_inventoryblank(sd) < item->inventorySlotNeeded(amount) ) return ERROR_TYPE_INVENTORY_WEIGHT; break; case CHKADDITEM_OVERAMOUNT: @@ -1857,6 +1859,7 @@ uint8 npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list * for( i = 0; i < n; ++i ) { unsigned short nameid, amount; int value; + item_data *id; // find this entry in the shop's sell list ARR_FIND( 0, nd->u.shop.count, j, @@ -1878,11 +1881,12 @@ uint8 npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list * amount = item_list[i].qty; nameid = item_list[i].nameid = shop[j].nameid; //item_avail replacement value = shop[j].value; + id = itemdb_exists(nameid); - if( !itemdb_exists(nameid) ) + if( !id ) return 3; // item no longer in itemdb - if( !itemdb_isstackable(nameid) && amount > 1 ) { //Exploit? You can't buy more than 1 of equipment types o.O + if( !itemdb_isstackable2(id) && amount > 1 ) { //Exploit? You can't buy more than 1 of equipment types o.O ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); amount = item_list[i].qty = 1; @@ -1897,7 +1901,7 @@ uint8 npc_buylist(struct map_session_data* sd, uint16 n, struct s_npc_buy_list * break; case CHKADDITEM_NEW: - new_++; + new_ += id->inventorySlotNeeded(amount); break; case CHKADDITEM_OVERAMOUNT: diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 9df9658861..af7039811c 100755 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -4577,6 +4577,9 @@ char pc_checkadditem(struct map_session_data *sd, unsigned short nameid, int amo if( data->stack.inventory && amount > data->stack.amount ) return CHKADDITEM_OVERAMOUNT; + if (data->flag.guid) + return CHKADDITEM_NEW; + for(i=0;iinventory.u.items_inventory[i].nameid == nameid){