summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--db/packet_db.txt1
-rw-r--r--src/map/clif.c42
-rw-r--r--src/map/npc.c85
-rw-r--r--src/map/npc.h2
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]
**/