diff --git a/src/map/clif.cpp b/src/map/clif.cpp index def2f29686..e64d76bfc3 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -12295,16 +12295,15 @@ void clif_npc_sell_result(struct map_session_data* sd, unsigned char result) void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) { int fail=0,n; - unsigned short *item_list; struct s_packet_db* info = &packet_db[RFIFOW(fd,0)]; + PACKET_CZ_PC_SELL_ITEMLIST* p = reinterpret_cast(RFIFOP(fd, 0)); - n = (RFIFOW(fd,info->pos[0])-4) /4; // (pktlen-(cmd+len))/listsize - item_list = (unsigned short*)RFIFOP(fd,info->pos[1]); - + n = (p->packetLength - 4) / sizeof(PACKET_CZ_PC_SELL_ITEMLIST_sub); // (pktlen-(cmd+len))/listsize + if (sd->state.trading || !sd->npc_shopid) fail = 1; else - fail = npc_selllist(sd,n,item_list); + fail = npc_selllist(sd, n, p->sellList); sd->npc_shopid = 0; //Clear shop data. clif_npc_sell_result(sd, fail); diff --git a/src/map/clif_packetdb.hpp b/src/map/clif_packetdb.hpp index ce355db155..8d0baad394 100644 --- a/src/map/clif_packetdb.hpp +++ b/src/map/clif_packetdb.hpp @@ -107,7 +107,7 @@ packet(0x00c6,-1); packet(0x00c7,-1); parseable_packet(0x00c8,-1,clif_parse_NpcBuyListSend,2,4); - parseable_packet(0x00c9,-1,clif_parse_NpcSellListSend,2,4); + parseable_packet(HEADER_CZ_PC_SELL_ITEMLIST,-1,clif_parse_NpcSellListSend,2,4); packet(0x00ca,3); packet(0x00cb,3); parseable_packet(0x00cc,6,clif_parse_GMKick,2); diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 07ed461a90..09ee429340 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -2849,7 +2849,7 @@ e_purchase_result npc_buylist( struct map_session_data* sd, std::vectorinventory.u.items_inventory[idx].nameid, &key_nameid ); - script_setarray_pc( sd, "@sold_quantity", i, item_list[i*2+1], &key_amount ); + script_setarray_pc( sd, "@sold_quantity", i, item_list[i].amount, &key_amount ); if( itemdb_isequip(sd->inventory.u.items_inventory[idx].nameid) ) {// process equipment based information into the arrays @@ -2933,7 +2933,7 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* /// /// @param item_list 'n' pairs /// @return result code for clif_parse_NpcSellListSend -uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list) +uint8 npc_selllist(struct map_session_data* sd, int list_length, PACKET_CZ_PC_SELL_ITEMLIST_sub* item_list) { double z; int i,skill; @@ -2950,13 +2950,13 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list z = 0; // verify the sell list - for( i = 0; i < n; i++ ) + for( i = 0; i < list_length; i++ ) { t_itemid nameid; int amount, idx, value; - idx = item_list[i*2]-2; - amount = item_list[i*2+1]; + idx = item_list[i].index - 2; + amount = item_list[i].amount; if( idx >= MAX_INVENTORY || idx < 0 || amount < 0 ) { @@ -2965,7 +2965,7 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list nameid = sd->inventory.u.items_inventory[idx].nameid; - if( !nameid || !sd->inventory_data[idx] || sd->inventory.u.items_inventory[idx].amount < amount ) + if( !nameid || !sd->inventory_data[idx] || sd->inventory.u.items_inventory[idx].amount < amount) { return 1; } @@ -2989,16 +2989,16 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list if( nd->master_nd ) {// Script-controlled shops - return npc_selllist_sub(sd, n, item_list, nd->master_nd); + return npc_selllist_sub(sd, list_length, item_list, nd->master_nd); } // delete items - for( i = 0; i < n; i++ ) + for( i = 0; i < list_length; i++ ) { int amount, idx; - idx = item_list[i*2]-2; - amount = item_list[i*2+1]; + idx = item_list[i].index - 2; + amount = item_list[i].amount; // Forged packet, we do not care if he loses items if( sd->inventory_data[idx] == nullptr ){ @@ -3013,7 +3013,9 @@ uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list } } - pc_delitem(sd, idx, amount, 0, 6, LOG_TYPE_NPC); + if (pc_delitem(sd, idx, amount, 0, 6, LOG_TYPE_NPC)) { + return 1; + } } if( z > MAX_ZENY ) diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 3c23228307..7af4bd8e1e 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -1488,7 +1488,7 @@ struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* b int npc_buysellsel(struct map_session_data* sd, int id, int type); e_purchase_result npc_buylist(struct map_session_data* sd, std::vector& item_list); static int npc_buylist_sub(struct map_session_data* sd, std::vector& item_list, struct npc_data* nd); -uint8 npc_selllist(struct map_session_data* sd, int n, unsigned short *item_list); +uint8 npc_selllist(struct map_session_data* sd, int list_length, PACKET_CZ_PC_SELL_ITEMLIST_sub* item_list); e_purchase_result npc_barter_purchase( struct map_session_data& sd, std::shared_ptr barter, std::vector& purchases ); void npc_parse_mob2(struct spawn_data* mob); struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y); diff --git a/src/map/packets.hpp b/src/map/packets.hpp index b6498f627d..9b18da73db 100644 --- a/src/map/packets.hpp +++ b/src/map/packets.hpp @@ -344,6 +344,17 @@ struct PACKET_ZC_FRIENDS_LIST{ struct PACKET_ZC_FRIENDS_LIST_sub friends[]; } __attribute__((packed)); +struct PACKET_CZ_PC_SELL_ITEMLIST_sub { + uint16 index; + uint16 amount; +} __attribute__((packed)); + +struct PACKET_CZ_PC_SELL_ITEMLIST { + int16 packetType; + int16 packetLength; + PACKET_CZ_PC_SELL_ITEMLIST_sub sellList[]; +} __attribute__((packed)); + // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute #if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 ) #pragma pack( pop ) @@ -412,6 +423,7 @@ DEFINE_PACKET_HEADER(CZ_REQUEST_RESET_ENCHANT, 0x0b9e) DEFINE_PACKET_HEADER(ZC_RESPONSE_ENCHANT, 0x0b9f) DEFINE_PACKET_HEADER(CZ_CLOSE_UI_ENCHANT, 0x0ba0) DEFINE_PACKET_HEADER(CZ_USE_PACKAGEITEM, 0x0baf) +DEFINE_PACKET_HEADER(CZ_PC_SELL_ITEMLIST, 0x00c9) const int16 MAX_INVENTORY_ITEM_PACKET_NORMAL = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_normal ) - ( sizeof( struct NORMALITEM_INFO ) * MAX_ITEMLIST) ) ) / sizeof( struct NORMALITEM_INFO ) ); const int16 MAX_INVENTORY_ITEM_PACKET_EQUIP = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_equip ) - ( sizeof( struct EQUIPITEM_INFO ) * MAX_ITEMLIST ) ) ) / sizeof( struct EQUIPITEM_INFO ) );