/*==========================================
* 露店アイテム購入
*------------------------------------------
*/
void vending_purchasereq(struct map_session_data *sd, unsigned short len, int id, unsigned char *p)
{
int i, j, w, new_, blank, vend_list[MAX_VENDING];
double z;
short amount, idx;
struct map_session_data *vsd;
struct vending vending[MAX_VENDING]; // against duplicate packets/items
//------------------追加-------------by mame-------
int w2 = 0; //購入者の重量
int num; //購入者のアイテム数
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = battle_config.vending_item_id; //アイテムID
item_tmp.identify = 1; //鑑定
//---------------------ここまで--------------------
nullpo_retv(sd);
vsd = map_id2sd(id);
if (vsd == NULL)
return;
if (vsd->bl.prev == NULL)
return;
if (vsd->vender_id == 0)
return;
if (vsd->vender_id == sd->bl.id)
return;
if (sd->bl.m != vsd->bl.m)
return;
if (unit_distance(sd->bl.x,sd->bl.y,vsd->bl.x,vsd->bl.y) > AREA_SIZE)
return;
// check number of buying items
if (len < 8 + 4 || len > 8 + 4 * MAX_VENDING) {
clif_buyvending(sd, 0, 0x7fff, 4); // not enough quantity (index and amount are unknown)
return;
}
blank = pc_inventoryblank(sd);
// duplicate items in vending to check hacker with multiple packets
memcpy(&vending, &vsd->vending, sizeof(struct vending) * MAX_VENDING); // copy vending list
// some checks
z = 0.;
w = 0;
new_ = 0;
for(i = 0; 8 + 4 * i < len; i++) {
amount = *(short*)(p + 4 * i);
if (amount <= 0)
return;
idx = *(short*)(p + 2 + 4 * i) - 2;
// check of index
if (idx < 0 || idx >= MAX_CART)
return;
for(j = 0; j < vsd->vend_num; j++) {
if (vsd->vending[j].index == idx) {
vend_list[i] = j;
break;
}
}
if (j == vsd->vend_num)
return; // 売り切れ
z += ((double)vsd->vending[j].value * (double)amount);
//------------------追加-------------by mame-------
// if(pc_checkadditem(sd,item_tmp.nameid,amount) == ADDITEM_NEW){
if(pc_search_inventory(sd,item_tmp.nameid) < 0){//何も持っていない
if(z != 0.){ //価格が0でないとき
clif_buyvending(sd, idx, amount, 1);
return;
}
num = 0;
} else { //アイテムの数を数える
num = sd->status.inventory[pc_search_inventory(sd,item_tmp.nameid)].amount;
}
if (z >(double)num || z < 0. || z > (double)MAX_AMOUNT) { // fix positiv overflow (buyer)
//---------------------ここまで--------------------
// if (z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY) { // fix positiv overflow (buyer)
clif_buyvending(sd, idx, amount, 1); // you don't have enough zenys
return; // zeny不足
}
//------------------追加-------------by mame-------
if (z + (double)vsd->status.inventory[pc_search_inventory(vsd,item_tmp.nameid)].amount > (double)MAX_AMOUNT) { // fix positiv overflow (merchand)
//---------------------ここまで--------------------
// if (z + (double)vsd->status.zeny > (double)MAX_ZENY) { // fix positiv overflow (merchand)
clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity
return; // zeny不足
}
//------------------追加-------------by mame-------
w += itemdb_weight(vsd->status.cart[idx].nameid) * amount - itemdb_weight(item_tmp.nameid) * (int)z;
//---------------------ここまで--------------------
// w += itemdb_weight(vsd->status.cart[idx].nameid) * amount;
if (w + sd->weight > sd->max_weight) {
clif_buyvending(sd, idx, amount, 2); // you can not buy, because overweight
return; // 重量超過
}
//------------------追加-------------by mame-------
w2 += itemdb_weight(item_tmp.nameid) * (int)z;
if (w2 + vsd->weight > vsd->max_weight) {
return; // sell重量超過
}
//---------------------ここまで--------------------
// if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples).
// here, we check cumulativ amounts
if (vending[j].amount < amount) { // send more quantity is not a hack (an other player can have buy items just before)
clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity
return;
}
vending[j].amount -= amount;
switch(pc_checkadditem(sd, vsd->status.cart[idx].nameid, amount)) {
case ADDITEM_EXIST:
break;
case ADDITEM_NEW:
new_++;
if (new_ > blank)
return; // 種類数超過
break;
case ADDITEM_OVERAMOUNT:
return; // アイテム数超過
}
}
// ゼニー支払い
//------------------追加-------------by mame-------
pc_delitem(sd,pc_search_inventory(sd,item_tmp.nameid),(int)z,0);
//---------------------ここまで--------------------
// pc_payzeny(sd, (int)z);
// 税金を差し引く
// if(battle_config.tax_rate)
// z = z * (100 - battle_config.tax_rate) / 100;
// ゼニー受け取り
//------------------追加-------------by mame-------
pc_additem(vsd,&item_tmp,(int)z);
//---------------------ここまで--------------------
// pc_getzeny(vsd, (int)z);
// vending items
for(i = 0; 8 + 4 * i < len; i++) {
amount = *(short*)(p + 4 * i);
idx = *(short*)(p + 2 + 4 * i) - 2;
pc_additem(sd, &vsd->status.cart[idx], amount);
vsd->vending[vend_list[i]].amount -= amount;
pc_cart_delitem(vsd, idx, amount, 0);
clif_vendingreport(vsd, idx, amount);
if (battle_config.buyer_name) {
char output[128];
snprintf(output, sizeof(output), msg_txt(148), sd->status.name);
clif_disp_onlyself(vsd->fd, output);
}
}
// save both players to avoid crash: they always have no advantage/disadvantage between the 2 players
chrif_save(sd,0);
chrif_save(vsd,0);
return;
}