diff options
-rw-r--r-- | db/packet_db.txt | 1 | ||||
-rw-r--r-- | src/map/clif.c | 42 | ||||
-rw-r--r-- | src/map/npc.c | 85 | ||||
-rw-r--r-- | src/map/npc.h | 2 |
4 files changed, 115 insertions, 15 deletions
diff --git a/db/packet_db.txt b/db/packet_db.txt index fc54a6f25..2be49523e 100644 --- a/db/packet_db.txt +++ b/db/packet_db.txt @@ -1612,6 +1612,7 @@ packet_ver: 25 //2010-11-24aRagexeRE packet_ver: 26 +0x0288,-1,cashshopbuy,4:8 0x0436,19,wanttoconnection,2:6:10:14:18 0x035f,5,walktoxy,2 0x0360,6,ticksend,2 diff --git a/src/map/clif.c b/src/map/clif.c index 8b6284a9c..576aaa4d1 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -13609,22 +13609,36 @@ void clif_cashshop_ack(struct map_session_data* sd, int error) /// 0288 <packet len>.W <kafra points>.L <count>.W { <amount>.W <name id>.W }.4B*count (PACKETVER >= 20100803) void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) { - int fail = 0, amount, points = 0; - short nameid; - nullpo_retv(sd); - - nameid = RFIFOW(fd,2); - amount = RFIFOW(fd,4); -#if PACKETVER >= 20070711 - points = RFIFOL(fd,6); // Not Implemented. Should be 0 -#endif + int fail = 0; + struct npc_data *nd; + nullpo_retv(sd); - if( sd->state.trading || !sd->npc_shopid ) - fail = 1; - else - fail = npc_cashshop_buy(sd, nameid, amount, points); + if( sd->state.trading || !sd->npc_shopid ) + fail = 1; + else + { +#if PACKETVER < 20101116 + short nameid = RFIFOW(fd,2); + short amount = RFIFOW(fd,4); + int points = RFIFOL(fd,6); - clif_cashshop_ack(sd, fail); + fail = npc_cashshop_buy(sd, nameid, amount, points); +#else + int len = RFIFOW(fd,2); + int points = RFIFOL(fd,4); + int count = RFIFOW(fd,8); + unsigned short* item_list = (unsigned short*)RFIFOP(fd,10); + + if( len < 10 || len != 10 + count * 4) + { + ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * 4); + return; + } + fail = npc_cashshop_buylist(sd,points,count,item_list); +#endif + } + + clif_cashshop_ack(sd,fail); } /*========================================== diff --git a/src/map/npc.c b/src/map/npc.c index 3a8ea376f..17a8e19be 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1190,7 +1190,90 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) } return 0; } - +/*========================================== +* Cash Shop Buy List +*------------------------------------------*/ +int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list) +{ + int i, j, nameid, amount, new_, w, vt; + struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid); + + if( !nd || nd->subtype != CASHSHOP ) + return 1; + + if( sd->state.trading ) + return 4; + + new_ = 0; + w = 0; + vt = 0; // Global Value + + // Validating Process ---------------------------------------------------- + for( i = 0; i < count; i++ ) + { + nameid = item_list[i*2+1]; + amount = item_list[i*2+0]; + + if( !itemdb_exists(nameid) || amount <= 0 ) + return 5; + + ARR_FIND(0,nd->u.shop.count,j,nd->u.shop.shop_item[j].nameid == nameid); + if( j == nd->u.shop.count || nd->u.shop.shop_item[j].value <= 0 ) + return 5; + + if( !itemdb_isstackable(nameid) && amount > 1 ) + { + ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); + amount = item_list[i*2+0] = 1; + } + + switch( pc_checkadditem(sd,nameid,amount) ) + { + case ADDITEM_NEW: + new_++; + break; + case ADDITEM_OVERAMOUNT: + return 3; + } + + vt += nd->u.shop.shop_item[j].value * amount; + w += itemdb_weight(nameid) * amount; + } + + if( w + sd->weight > sd->max_weight ) + return 3; + if( pc_inventoryblank(sd) < new_ ) + return 3; + if( points > vt ) points = vt; + + // Payment Process ---------------------------------------------------- + if( sd->kafraPoints < points || sd->cashPoints < (vt - points) ) + return 6; + pc_paycash(sd,vt,points); + + // Delivery Process ---------------------------------------------------- + for( i = 0; i < count; i++ ) + { + struct item item_tmp; + + nameid = item_list[i*2+1]; + amount = item_list[i*2+0]; + + memset(&item_tmp,0,sizeof(item_tmp)); + + if( !pet_create_egg(sd,nameid) ) + { + item_tmp.nameid = nameid; + item_tmp.identify = 1; + pc_additem(sd,&item_tmp,amount); + } + + if( log_config.enable_logs&0x20 ) + log_pick_pc(sd, "S", nameid, amount, NULL); + } + + return 0; +} //npc_buylist for script-controlled shops. static int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd) { diff --git a/src/map/npc.h b/src/map/npc.h index ac411697e..5911a338d 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -157,6 +157,8 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po extern struct npc_data* fake_nd; +int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list); + /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ |