From d40a402849595e51aff219b74c323008467ce67e Mon Sep 17 00:00:00 2001 From: ai4rei Date: Wed, 26 Jan 2011 11:52:44 +0000 Subject: * Fixed buyers, that are currently in a vending shop could be fooled into buying an item at different price than they see by reopening the vending shop (bugreport:4728). - This implements the official vending shop unique id handling (previously mistaken for char id), made compatible with packets before it's introduction (follow up to r14234). git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@14682 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/clif.c | 28 ++++++++++++++++++---------- src/map/pc.h | 1 + src/map/vending.c | 33 +++++++++++++++++++++++++-------- src/map/vending.h | 2 +- 4 files changed, 45 insertions(+), 19 deletions(-) (limited to 'src/map') diff --git a/src/map/clif.c b/src/map/clif.c index 332f396f9..e36418706 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -5599,9 +5599,9 @@ void clif_closevendingboard(struct block_list* bl, int fd) } /*========================================== - * Sends a list of items in a shop + * Sends a list of items in a shop (ZC_PC_PURCHASE_ITEMLIST_FROMMC/ZC_PC_PURCHASE_ITEMLIST_FROMMC2) * R 0133 .w .l {.l .w .w .B .w .B .B .B .4w}.22B - * R 0800 .w .l .l {.l .w .w .B .w .B .B .B .4w}.22B + * R 0800 .w .l .l {.l .w .w .B .w .B .B .B .4w}.22B *------------------------------------------*/ void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* vending) { @@ -5628,7 +5628,7 @@ void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* ven WFIFOW(fd,2) = offset+count*22; WFIFOL(fd,4) = id; #if PACKETVER >= 20100105 - WFIFOL(fd,8) = vsd->status.char_id; + WFIFOL(fd,8) = vsd->vender_id; #endif for( i = 0; i < count; i++ ) @@ -5649,12 +5649,14 @@ void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* ven } /*========================================== - * Shop purchase failure + * Shop purchase failure (ZC_PC_PURCHASE_RESULT_FROMMC) * R 0135 .w .w .B * fail=1 - not enough zeny * fail=2 - overweight * fail=4 - out of stock * fail=5 - "cannot use an npc shop while in a trade" + * fail=6 - Because the store information was incorrect the item was not purchased. + * fail=7 - No sales information. *------------------------------------------*/ void clif_buyvending(struct map_session_data* sd, int index, int amount, int fail) { @@ -10884,7 +10886,7 @@ void clif_parse_VendingListReq(int fd, struct map_session_data* sd) } /*========================================== - * Shop item(s) purchase request + * Shop item(s) purchase request (CZ_PC_PURCHASE_ITEMLIST_FROMMC) * S 0134 .w .l {.w .w}.4B* *------------------------------------------*/ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) @@ -10893,21 +10895,27 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) int id = (int)RFIFOL(fd,4); const uint8* data = (uint8*)RFIFOP(fd,8); - vending_purchasereq(sd, id, -1, data, len/4); + vending_purchasereq(sd, id, sd->vended_id, data, len/4); + + // whether it fails or not, the buy window is closed + sd->vended_id = 0; } /*========================================== - * Shop item(s) purchase request - * S 0134/0801 .w .l .l {.w .w}.4B* + * Shop item(s) purchase request (CZ_PC_PURCHASE_ITEMLIST_FROMMC2) + * S 0801 .w .l .l {.w .w}.4B* *------------------------------------------*/ void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) { int len = (int)RFIFOW(fd,2) - 12; int aid = (int)RFIFOL(fd,4); - int cid = (int)RFIFOL(fd,8); + int uid = (int)RFIFOL(fd,8); const uint8* data = (uint8*)RFIFOP(fd,12); - vending_purchasereq(sd, aid, cid, data, len/4); + vending_purchasereq(sd, aid, uid, data, len/4); + + // whether it fails or not, the buy window is closed + sd->vended_id = 0; } /*========================================== diff --git a/src/map/pc.h b/src/map/pc.h index 2921b4527..24d52a466 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -350,6 +350,7 @@ struct map_session_data { int guildspy; // [Syrus22] int partyspy; // [Syrus22] + int vended_id; int vender_id; int vend_num; char message[MESSAGE_SIZE]; diff --git a/src/map/vending.c b/src/map/vending.c index 90bff7399..a47be9057 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -19,6 +19,18 @@ #include #include +static int vending_nextid = 1; + +/// Returns an unique vending shop id. +static int vending_getuid(void) +{ + if(!vending_nextid) + {// wrapped around, 0 is reserved for "not vending" state on eathena + vending_nextid = 1; + } + + return vending_nextid++; +} /*========================================== * Close shop @@ -50,13 +62,15 @@ void vending_vendinglistreq(struct map_session_data* sd, int id) return; } + sd->vended_id = vsd->vender_id; // register vending uid + clif_vendinglist(sd, id, vsd->vending); } /*========================================== * Purchase item(s) from a shop *------------------------------------------*/ -void vending_purchasereq(struct map_session_data* sd, int aid, int cid, const uint8* data, int count) +void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count) { int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING]; double z; @@ -64,12 +78,15 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int cid, const ui struct map_session_data* vsd = map_id2sd(aid); nullpo_retv(sd); - if( vsd == NULL || vsd->vender_id == 0 || vsd->vender_id == sd->bl.id ) + if( vsd == NULL || vsd->vender_id == 0 || vsd->bl.id == sd->bl.id ) return; // invalid shop -#if PACKETVER >= 20100105 - if( vsd->status.char_id != cid ) - return; //Char-ID check -#endif + + if( vsd->vender_id != uid ) + {// shop has changed + clif_buyvending(sd, 0, 0, 6); // store information was incorrect + return; + } + if( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) ) return; // shop too far away if( count < 1 || count > MAX_VENDING || count > vsd->vend_num ) @@ -289,11 +306,11 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool return; } - sd->vender_id = sd->bl.id; + sd->vender_id = vending_getuid(); sd->vend_num = i; safestrncpy(sd->message, message, MESSAGE_SIZE); pc_stop_walking(sd,1); - clif_openvending(sd,sd->vender_id,sd->vending); + clif_openvending(sd,sd->bl.id,sd->vending); clif_showvendingboard(&sd->bl,message,0); } diff --git a/src/map/vending.h b/src/map/vending.h index 9748b675a..3c483a38c 100644 --- a/src/map/vending.h +++ b/src/map/vending.h @@ -17,6 +17,6 @@ struct s_vending { void vending_closevending(struct map_session_data* sd); void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count); void vending_vendinglistreq(struct map_session_data* sd, int id); -void vending_purchasereq(struct map_session_data* sd, int aid, int cid, const uint8* data, int count); +void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count); #endif /* _VENDING_H_ */ -- cgit v1.2.3-70-g09d2