Beispiel #1
0
/// logs item transactions (players)
void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm)
{
	nullpo_retv(sd);
	log_pick(sd->status.char_id, sd->bl.m, type, amount, itm);
}
Beispiel #2
0
/// logs item transactions (monsters)
void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm)
{
	nullpo_retv(md);
	log_pick(md->mob_id, md->bl.m, type, amount, itm);
}
Beispiel #3
0
/// logs item transactions (players)
void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
	nullpo_retv(sd);
	log_pick(sd->status.char_id, sd->bl.m, type, amount, itm, data ? data : itemdb->exists(itm->nameid));
}
Beispiel #4
0
/// logs item transactions (monsters)
void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
	nullpo_retv(md);
	log_pick(md->class_, md->bl.m, type, amount, itm, data ? data : itemdb->exists(itm->nameid));
}
Beispiel #5
0
//Does party loot. first_charid holds the charid of the player who has time priority to take the item.
int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid)
{
	TBL_PC* target = NULL;
	int i;
	if (p && p->party.item&2 && (first_charid || !(battle_config.party_share_type&1)))
	{
		//item distribution to party members.
		if (battle_config.party_share_type&2)
		{	//Round Robin
			TBL_PC* psd;
			i = p->itemc;
			do {
				i++;
				if (i >= MAX_PARTY)
					i = 0;	// reset counter to 1st person in party so it'll stop when it reaches "itemc"

				if( (psd = p->data[i].sd) == NULL || sd->bl.m != psd->bl.m || pc_isdead(psd) || (battle_config.idle_no_share && pc_isidle(psd)) )
					continue;
				
				if (pc_additem(psd,item_data,item_data->amount))
					continue; //Chosen char can't pick up loot.

				//Successful pick.
				p->itemc = i;
				target = psd;
				break;
			} while (i != p->itemc);
		}
		else
		{	//Random pick
			TBL_PC* psd[MAX_PARTY];
			int count = 0;
			//Collect pick candidates
			for (i = 0; i < MAX_PARTY; i++) {
				if( (psd[count] = p->data[i].sd) == NULL || psd[count]->bl.m != sd->bl.m || pc_isdead(psd[count]) || (battle_config.idle_no_share && pc_isidle(psd[count])) )
					continue;

				count++;
			}
			while (count > 0) { //Pick a random member.
				i = rand()%count;
				if (pc_additem(psd[i],item_data,item_data->amount))
				{	//Discard this receiver.
					psd[i] = psd[count-1];
					count--;
				} else { //Successful pick.
					target = psd[i];
					break;
				}
			}
		}
	}

	if (!target) { 
		target = sd; //Give it to the char that picked it up
		if ((i=pc_additem(sd,item_data,item_data->amount)))
			return i;
	}

	//Logs items, taken by (P)layers [Lupus]
	log_pick(&target->bl, LOG_TYPE_PICKDROP_PLAYER, item_data->nameid, item_data->amount, item_data);
	
	if( p && battle_config.party_show_share_picker && battle_config.show_picker_item_type&(1<<itemdb_type(item_data->nameid)) )
		clif_party_show_picker(target, item_data);

	return 0;
}
Beispiel #6
0
/*==========================================
 * Purchase item(s) from a shop
 *------------------------------------------*/
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;
    struct s_vending vending[MAX_VENDING]; // against duplicate packets
    struct map_session_data* vsd = map_id2sd(aid);

    nullpo_retv(sd);
    if( vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id )
        return; // invalid shop

    if( vsd->vender_id != uid )
    {   // shop has changed
        clif_buyvending(sd, 0, 0, 6);  // store information was incorrect
        return;
    }

    if( !searchstore_queryremote(sd, aid) && ( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) ) )
        return; // shop too far away

    searchstore_clearremote(sd);

    if( count < 1 || count > MAX_VENDING || count > vsd->vend_num )
        return; // invalid amount of purchased items

    blank = pc_inventoryblank(sd); //number of free cells in the buyer's inventory

    // duplicate item in vending to check hacker with multiple packets
    memcpy(&vending, &vsd->vending, sizeof(vsd->vending)); // copy vending list

    // some checks
    z = 0.; // zeny counter
    w = 0;  // weight counter
    for( i = 0; i < count; i++ )
    {
        short amount = *(uint16*)(data + 4*i + 0);
        short idx    = *(uint16*)(data + 4*i + 2);
        idx -= 2;

        if( amount <= 0 )
            return;

        // check of item index in the cart
        if( idx < 0 || idx >= MAX_CART )
            return;

        ARR_FIND( 0, vsd->vend_num, j, vsd->vending[j].index == idx );
        if( j == vsd->vend_num )
            return; //picked non-existing item
        else
            vend_list[i] = j;

        z += ((double)vsd->vending[j].value * (double)amount);
        if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY )
        {
            clif_buyvending(sd, idx, amount, 1); // you don't have enough zeny
            return;
        }
        if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max )
        {
            clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow
            return;

        }
        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;
        }

        //Check to see if cart/vend info is in sync.
        if( vending[j].amount > vsd->status.cart[idx].amount )
            vending[j].amount = vsd->status.cart[idx].amount;

        // if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples).
        // here, we check cumulative 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;	//We'd add this item to the existing one (in buyers inventory)
        case ADDITEM_NEW:
            new_++;
            if (new_ > blank)
                return; //Buyer has no space in his inventory
            break;
        case ADDITEM_OVERAMOUNT:
            return; //too many items
        }
    }

    //Logs (V)ending Zeny [Lupus]
    log_zeny(vsd, LOG_TYPE_VENDING, sd, (int)z);

    pc_payzeny(sd, (int)z);
    if( battle_config.vending_tax )
        z -= z * (battle_config.vending_tax/10000.);
    pc_getzeny(vsd, (int)z);

    for( i = 0; i < count; i++ )
    {
        short amount = *(uint16*)(data + 4*i + 0);
        short idx    = *(uint16*)(data + 4*i + 2);
        idx -= 2;

        //Logs sold (V)ending items [Lupus]
        log_pick(&vsd->bl, LOG_TYPE_VENDING, vsd->status.cart[idx].nameid, -amount, &vsd->status.cart[idx]);
        log_pick( &sd->bl, LOG_TYPE_VENDING, vsd->status.cart[idx].nameid,  amount, &vsd->status.cart[idx]);

        // vending item
        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);

        //print buyer's name
        if( battle_config.buyer_name )
        {
            char temp[256];
            sprintf(temp, msg_txt(265), sd->status.name);
            clif_disp_onlyself(vsd,temp,strlen(temp));
        }
    }

    // compact the vending list
    for( i = 0, cursor = 0; i < vsd->vend_num; i++ )
    {
        if( vsd->vending[i].amount == 0 )
            continue;

        if( cursor != i ) // speedup
        {
            vsd->vending[cursor].index = vsd->vending[i].index;
            vsd->vending[cursor].amount = vsd->vending[i].amount;
            vsd->vending[cursor].value = vsd->vending[i].value;
        }

        cursor++;
    }
    vsd->vend_num = cursor;

    //Always save BOTH: buyer and customer
    if( save_settings&2 )
    {
        chrif_save(sd,0);
        chrif_save(vsd,0);
    }

    //check for @AUTOTRADE users [durf]
    if( vsd->state.autotrade )
    {
        //see if there is anything left in the shop
        ARR_FIND( 0, vsd->vend_num, i, vsd->vending[i].amount > 0 );
        if( i == vsd->vend_num )
        {
            //Close Vending (this was automatically done by the client, we have to do it manually for autovenders) [Skotlex]
            vending_closevending(vsd);
            map_quit(vsd);	//They have no reason to stay around anymore, do they?
        }
    }
}
Beispiel #7
0
int party_share_loot(struct party *p, TBL_PC *sd, struct item *item_data)
{
	TBL_PC *target=NULL;
	int i;
	if (p && p->item&2) {
		//item distribution to party members.
		if (battle_config.party_share_type) { //Round Robin
			TBL_PC *psd;
			i = p->itemc;
			do {
				i++;
				if (i >= MAX_PARTY)
					i = 0;	// reset counter to 1st person in party so it'll stop when it reaches "itemc"
				if ((psd=p->member[i].sd)==NULL || sd->bl.m != psd->bl.m)
					continue;
				
				if (pc_additem(psd,item_data,item_data->amount))
					continue; //Chosen char can't pick up loot.
				//Successful pick.
				p->itemc = i;
				target = psd;
				break;
			} while (i != p->itemc);
		} else { //Random pick
			TBL_PC *psd[MAX_PARTY];
			int count=0;
			//Collect pick candidates
			for (i = 0; i < MAX_PARTY; i++) {
				if ((psd[count]=p->member[i].sd) && psd[count]->bl.m == sd->bl.m)
					count++;
			}
			if (count > 0) { //Pick a random member.
				do {
					i = rand()%count;
					if (pc_additem(psd[i],item_data,item_data->amount))
					{	//Discard this receiver.
						psd[i] = psd[count-1];
						count--;
					} else { //Successful pick.
						target = psd[i];
						break;
					}
				} while (count > 0);
			}
		}
	}
	if (!target) { //Give it to the owner.
		target = sd;
		if ((i=pc_additem(sd,item_data,item_data->amount)))
			return i;
	}

	if(log_config.pick) //Logs items, taken by (P)layers [Lupus]
		log_pick(target, "P", 0, item_data->nameid, item_data->amount, item_data);
	//Logs
	if(battle_config.party_show_share_picker && target != sd){
		char output[80];
		sprintf(output, "%s acquired the item.",target->status.name);
		clif_disp_onlyself(sd,output,strlen(output));
	}
	return 0;
}
Beispiel #8
0
/*==========================================
 * 取引許諾(trade押し)
 *------------------------------------------
 */
void trade_tradecommit(struct map_session_data *sd) {
	struct map_session_data *target_sd;
	int trade_i;
	int flag;

	nullpo_retv(sd);

	if (sd->state.trading && (target_sd = map_id2sd(sd->trade_partner)) != NULL) {
		if ((sd->state.deal_locked >= 1) && (target_sd->state.deal_locked >= 1)) { // both have pressed 'ok'
			if (sd->state.deal_locked < 2) { // set locked to 2
				sd->state.deal_locked = 2;
			}
			if (target_sd->state.deal_locked == 2) { // the other one pressed 'trade' too
				// check exploit (trade more items that you have)
				if (impossible_trade_check(sd)) {
					trade_tradecancel(sd);
					return;
				}
				// check exploit (trade more items that you have)
				if (impossible_trade_check(target_sd)) {
					trade_tradecancel(target_sd);
					return;
				}
				// check zenys value against hackers
				if (sd->deal.zeny >= 0 && sd->deal.zeny <= MAX_ZENY && sd->deal.zeny <= sd->status.zeny && // check amount
				    (target_sd->status.zeny + sd->deal.zeny) <= MAX_ZENY && // fix positiv overflow
				    target_sd->deal.zeny >= 0 && target_sd->deal.zeny <= MAX_ZENY && target_sd->deal.zeny <= target_sd->status.zeny && // check amount
				    (sd->status.zeny + target_sd->deal.zeny) <= MAX_ZENY) { // fix positiv overflow

					// check for full inventory (can not add traded items)
					if (!trade_check(sd)) { // check the both players
						trade_tradecancel(sd);
						return;
					}

					// trade is accepted
					for(trade_i = 0; trade_i < 10; trade_i++) {
						if (sd->deal.item[trade_i].amount != 0) {
							int n = sd->deal.item[trade_i].index;

							if (sd->status.inventory[n].amount < sd->deal.item[trade_i].amount)
								sd->deal.item[trade_i].amount = sd->status.inventory[n].amount;
                                                        log_trade(sd, target_sd, n, sd->deal.item[trade_i].amount);

							flag = pc_additem(target_sd, &sd->status.inventory[n], sd->deal.item[trade_i].amount);
							if (flag == 0) {
								//Logs (T)rade [Lupus]
								if(log_config.pick > 0 )
									log_pick(sd, "T", 0, sd->status.inventory[n].nameid, -(sd->deal.item[trade_i].amount), &sd->status.inventory[n]);
									log_pick(target_sd, "T", 0, sd->status.inventory[n].nameid, sd->deal.item[trade_i].amount, &sd->status.inventory[n]);
								//Logs
								pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1);
							} else {
								clif_additem(sd, n, sd->deal.item[trade_i].amount, 0);
							}
							sd->deal.item[trade_i].index = 0;
							sd->deal.item[trade_i].amount = 0;
                                                        
						}
						if (target_sd->deal.item[trade_i].amount != 0) {
							int n = target_sd->deal.item[trade_i].index;

							if (target_sd->status.inventory[n].amount < target_sd->deal.item[trade_i].amount)
								target_sd->deal.item[trade_i].amount = target_sd->status.inventory[n].amount;

							log_trade(target_sd, sd, n, target_sd->deal.item[trade_i].amount);

							flag = pc_additem(sd, &target_sd->status.inventory[n], target_sd->deal.item[trade_i].amount);
							if (flag == 0) {
								//Logs (T)rade [Lupus]
								if(log_config.pick > 0 )
									log_pick(target_sd, "T", 0, target_sd->status.inventory[n].nameid, -(target_sd->deal.item[trade_i].amount), &target_sd->status.inventory[n]);
									log_pick(sd, "T", 0, target_sd->status.inventory[n].nameid, target_sd->deal.item[trade_i].amount, &target_sd->status.inventory[n]);
								//Logs
								pc_delitem(target_sd, n, target_sd->deal.item[trade_i].amount, 1);
							} else {
								clif_additem(target_sd, n, target_sd->deal.item[trade_i].amount, 0);
							}
							target_sd->deal.item[trade_i].index = 0;
							target_sd->deal.item[trade_i].amount = 0;
						}
					}
					if (sd->deal.zeny) {
						//Logs Zeny (T)rade [Lupus]
						if(log_config.zeny > 0 )
							log_zeny(target_sd, "T", sd, sd->deal.zeny);
						//Logs
						sd->status.zeny -= sd->deal.zeny;
						target_sd->status.zeny += sd->deal.zeny;
					}
					if (target_sd->deal.zeny) {
						//Logs Zeny (T)rade [Lupus]
						if(log_config.zeny > 0 )
							log_zeny(sd, "T", target_sd, target_sd->deal.zeny);
						//Logs
						target_sd->status.zeny -= target_sd->deal.zeny;
						sd->status.zeny += target_sd->deal.zeny;
					}
					if (sd->deal.zeny || target_sd->deal.zeny) {
						clif_updatestatus(sd, SP_ZENY);
						sd->deal.zeny = 0;
						clif_updatestatus(target_sd, SP_ZENY);
						target_sd->deal.zeny = 0;
					}
					sd->state.deal_locked = 0;
					sd->trade_partner = 0;
					sd->state.trading = 0;
					target_sd->state.deal_locked = 0;
					target_sd->trade_partner = 0;
					target_sd->state.trading = 0;
					clif_tradecompleted(sd, 0);
					clif_tradecompleted(target_sd, 0);
					// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
					chrif_save(sd,0); // do pc_makesavestatus and save storage too
					chrif_save(target_sd,0); // do pc_makesavestatus and save storage too
				// zeny value was modified!!!! hacker with packet modified
				} else {
					trade_tradecancel(sd);
				}
			}
		}
	}
}
Beispiel #9
0
void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count)
{
	int zeny = 0;
	unsigned int i, weight, listidx, k;
	struct map_session_data* pl_sd;

	if( count == 0 )
	{// nothing to do
		return;
	}

	if( !battle_config.feature_buying_store || pc_istrading(sd) )
	{// not allowed to sell
		clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
		return;
	}

	if( !pc_can_give_items(pc_isGM(sd)) )
	{// custom: GM is not allowed to sell
		clif_displaymessage(sd->fd, msg_txt(246));
		clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
		return;
	}

	if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id )
	{// not online, not buying or not same store
		clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
		return;
	}

	if( !searchstore_queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) )
	{// out of view range
		clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
		return;
	}

	searchstore_clearremote(sd);

	if( pl_sd->status.zeny < pl_sd->buyingstore.zenylimit )
	{// buyer lost zeny in the mean time? fix the limit
		pl_sd->buyingstore.zenylimit = pl_sd->status.zeny;
	}
	weight = pl_sd->weight;

	// check item list
	for( i = 0; i < count; i++ )
	{// itemlist: <index>.W <name id>.W <amount>.W
		unsigned short nameid, amount;
		int index;

		index  = RBUFW(itemlist,i*6+0)-2;
		nameid = RBUFW(itemlist,i*6+2);
		amount = RBUFW(itemlist,i*6+4);

		if( i )
		{// duplicate check. as the client does this too, only malicious intent should be caught here
			ARR_FIND( 0, i, k, RBUFW(itemlist,k*6+0)-2 == index );
			if( k != i )
			{// duplicate
				ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n",
					RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id);
				clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
				return;
			}
		}

		if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount )
		{// invalid input
			clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
			return;
		}

		if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_isGM(sd), pc_isGM(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) )
		{// non-tradable item
			clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
			return;
		}

		ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
		if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 )
		{// there is no such item or the buyer has already bought all of them
			clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
			return;
		}

		if( pl_sd->buyingstore.items[listidx].amount < amount )
		{// buyer does not need that much of the item
			clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid);
			return;
		}

		if( pc_checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT )
		{// buyer does not have enough space for this item
			clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
			return;
		}

		if( amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight )
		{// normally this is not supposed to happen, as the total weight is
		 // checked upon creation, but the buyer could have gained items
			clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
			return;
		}
		weight+= amount*sd->inventory_data[index]->weight;

		if( amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny )
		{// buyer does not have enough zeny
			clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid);
			return;
		}
		zeny+= amount*pl_sd->buyingstore.items[listidx].price;
	}

	// process item list
	for( i = 0; i < count; i++ )
	{// itemlist: <index>.W <name id>.W <amount>.W
		unsigned short nameid, amount;
		int index;

		index  = RBUFW(itemlist,i*6+0)-2;
		nameid = RBUFW(itemlist,i*6+2);
		amount = RBUFW(itemlist,i*6+4);

		ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
		zeny = amount*pl_sd->buyingstore.items[listidx].price;

		// log
		log_pick(&sd->bl, LOG_TYPE_BUYING_STORE, nameid, -((int)amount), &sd->status.inventory[index]);
		log_pick(&pl_sd->bl, LOG_TYPE_BUYING_STORE, nameid, amount, &sd->status.inventory[index]);
		log_zeny(sd, LOG_TYPE_BUYING_STORE, pl_sd, zeny);

		// move item
		pc_additem(pl_sd, &sd->status.inventory[index], amount);
		pc_delitem(sd, index, amount, 1, 0);
		pl_sd->buyingstore.items[listidx].amount-= amount;

		// pay up
		pc_payzeny(pl_sd, zeny);
		pc_getzeny(sd, zeny);
		pl_sd->buyingstore.zenylimit-= zeny;

		// notify clients
		clif_buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price);
		clif_buyingstore_update_item(pl_sd, nameid, amount);
	}

	// check whether or not there is still something to buy
	ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 );
	if( i == pl_sd->buyingstore.slots )
	{// everything was bought
		clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS);
	}
	else if( pl_sd->buyingstore.zenylimit == 0 )
	{// zeny limit reached
		clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY);
	}
	else
	{// continue buying
		return;
	}

	// cannot continue buying
	buyingstore_close(pl_sd);

	// remove auto-trader
	if( pl_sd->state.autotrade )
	{
		map_quit(pl_sd);
	}
}