Example #1
0
// exp share and added zeny share [Valaris]
int party_exp_share(struct party *p,int map,int base_exp,int job_exp,int zeny)
{
	struct map_session_data* sd[MAX_PARTY];
	int i;
	short c, bonus =100; // modified [Valaris]
	unsigned long base, job;

	nullpo_retr(0, p);

	for (i = c = 0; i < MAX_PARTY; i++)
		if ((sd[c] = p->member[i].sd)!=NULL && sd[c]->bl.m == map && !pc_isdead(sd[c])) {
			if (battle_config.idle_no_share && (pc_issit(sd[c]) || sd[c]->chatID || (sd[c]->idletime < (last_tick - battle_config.idle_no_share))))
				continue;
			c++;
		}
	if (c < 1)
		return 0;
	if (battle_config.party_even_share_bonus) //Valaris's even share exp bonus equation.
		bonus += (battle_config.party_even_share_bonus*c*(c-1)/10);	//Changed Valaris's bonus switch to an equation [Skotlex]
	else	//Official kRO/iRO sites state that the even share bonus is 10% per additional party member.
		bonus += (c-1)*10;
	base = (unsigned long)(base_exp/c)*bonus/100;
	job = (unsigned long)(job_exp/c)*bonus/100;
	if (base > 0x7fffffff)
		base = 0x7fffffff;
	if (job > 0x7fffffff)
		job = 0x7fffffff;
	for (i = 0; i < c; i++)
	{
		pc_gainexp(sd[i], base, job);
		if (battle_config.zeny_from_mobs) // zeny from mobs [Valaris]
			pc_getzeny(sd[i],bonus*zeny/(c*100));
	}
	return 0;
}
Example #2
0
/**
 * Player setup a new shop
 * @param sd : player opening the shop
 * @param message : shop title
 * @param data : itemlist data \n
 *	data := {<index>.w <amount>.w <value>.l}[count]
 * @param count : number of different items
 * @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - Cart data isn't saved yet, 5 - No valid item found
 */
char vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) {
	int i, j;
	int vending_skill_lvl;
	char message_sql[MESSAGE_SIZE*2];
	
	nullpo_retr(false,sd);

	if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) {
		return 1; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once
	}

	vending_skill_lvl = pc_checkskill(sd, MC_VENDING);
	
	// skill level and cart check
	if( !vending_skill_lvl || !pc_iscarton(sd) ) {
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
		return 2;
	}

	// check number of items in shop
	if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl )
	{	// invalid item count
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
		return 3;
	}

	if (save_settings&2) // Avoid invalid data from saving
		chrif_save(sd, 0);

	// filter out invalid items
	i = 0;
	for( j = 0; j < count; j++ ) {
		short index        = *(uint16*)(data + 8*j + 0);
		short amount       = *(uint16*)(data + 8*j + 2);
		unsigned int value = *(uint32*)(data + 8*j + 4);

		index -= 2; // offset adjustment (client says that the first cart position is 2)

		if( index < 0 || index >= MAX_CART // invalid position
		||  pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity
		//NOTE: official server does not do any of the following checks!
		||  !sd->status.cart[index].identify // unidentified item
		||  sd->status.cart[index].attribute == 1 // broken item
		||  sd->status.cart[index].expire_time // It should not be in the cart but just in case
		||  (sd->status.cart[index].bound && !pc_can_give_bounded_items(sd)) // can't trade account bound items and has no permission
		||  !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item
			continue;

		sd->vending[i].index = index;
		sd->vending[i].amount = amount;
		sd->vending[i].value = min(value, (unsigned int)battle_config.vending_max_value);

		// Player just moved item to cart and we don't have the correct cart ID yet.
		if (sd->status.cart[sd->vending[i].index].id == 0) {
			struct item_data *idb = itemdb_search(sd->status.cart[index].nameid);
			char msg[256];

			sprintf(msg, msg_txt(sd, 733), idb->jname);
			clif_displaymessage(sd->fd, msg);
			clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
			return 4;
		}

		i++; // item successfully added
	}

	if( i != j )
		clif_displaymessage (sd->fd, msg_txt(sd,266)); //"Some of your items cannot be vended and were removed from the shop."

	if( i == 0 ) { // no valid item found
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
		return 5;
	}
	sd->state.prevend = 0;
	sd->state.vending = true;
	sd->vender_id = vending_getuid();
	sd->vend_num = i;
	safestrncpy(sd->message, message, MESSAGE_SIZE);
	
	Sql_EscapeString( mmysql_handle, message_sql, sd->message );

	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`autotrade`, `body_direction`, `head_direction`, `sit`) "
		"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d' );",
		vendings_db, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ){
		Sql_ShowDebug(mmysql_handle);
	}

	for( i = 0; i < count; i++ ) {
		if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES( %d, %d, %d, %d, %d );", vending_items_db, sd->vender_id, i, sd->status.cart[sd->vending[i].index].id, sd->vending[i].amount, sd->vending[i].value ) != SQL_SUCCESS ){
			Sql_ShowDebug(mmysql_handle);
		}
	}

	clif_openvending(sd,sd->bl.id,sd->vending);
	clif_showvendingboard(&sd->bl,message,0);

	idb_put(vending_db, sd->status.char_id, sd);

	return 0;
}
Example #3
0
/**
* Attempt to create new buying store
* @param sd
* @param zenylimit
* @param result
* @param storename
* @param *itemlist { <nameid>.W, <amount>.W, <price>.L }*
* @param count Number of item on the itemlist
* @return 0 If success, 1 - Cannot open, 2 - Manner penalty, 3 - Mapflag restiction, 4 - Cell restriction, 5 - Invalid count/result, 6 - Cannot give item, 7 - Will be overweight
*/
char buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count)
{
	unsigned int i, weight, listidx;
	char message_sql[MESSAGE_SIZE*2];

	nullpo_retr(1, sd);

	if( !result || count == 0 )
	{// canceled, or no items
		return 5;
	}

	if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] )
	{// disabled or invalid input
		sd->buyingstore.slots = 0;
		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
		return 1;
	}

	if( !pc_can_give_items(sd) )
	{// custom: GM is not allowed to buy (give zeny)
		sd->buyingstore.slots = 0;
		clif_displaymessage(sd->fd, msg_txt(sd,246));
		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
		return 6;
	}

	if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) )
	{// custom: mute limitation
		return 2;
	}

	if( map[sd->bl.m].flag.novending )
	{// custom: no vending maps
		clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
		return 3;
	}

	if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
	{// custom: no vending cells
		clif_displaymessage(sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell."
		return 4;
	}

	weight = sd->weight;

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

		nameid = RBUFW(itemlist,i*8+0);
		amount = RBUFW(itemlist,i*8+2);
		price  = RBUFL(itemlist,i*8+4);

		if( ( id = itemdb_exists(nameid) ) == NULL || amount == 0 )
		{// invalid input
			break;
		}

		if( price <= 0 || price > BUYINGSTORE_MAX_PRICE )
		{// invalid price: unlike vending, items cannot be bought at 0 Zeny
			break;
		}

		if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_get_group_level(sd), pc_get_group_level(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 )
		{// restrictions: allowed, no character-bound items and at least one must be owned
			break;
		}

		if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT )
		{// too many items of same kind
			break;
		}

		if( i )
		{// duplicate check. as the client does this too, only malicious intent should be caught here
			ARR_FIND( 0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid );
			if( listidx != i )
			{// duplicate
				ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id);
				break;
			}
		}

		weight+= id->weight*amount;
		sd->buyingstore.items[i].nameid = nameid;
		sd->buyingstore.items[i].amount = amount;
		sd->buyingstore.items[i].price  = price;
	}

	if( i != count )
	{// invalid item/amount/price
		sd->buyingstore.slots = 0;
		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
		return 5;
	}

	if( (sd->max_weight*90)/100 < weight )
	{// not able to carry all wanted items without getting overweight (90%)
		sd->buyingstore.slots = 0;
		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight);
		return 7;
	}

	// success
	sd->state.buyingstore = true;
	sd->buyer_id = buyingstore_getuid();
	sd->buyingstore.zenylimit = zenylimit;
	sd->buyingstore.slots = i;  // store actual amount of items
	safestrncpy(sd->message, storename, sizeof(sd->message));

	Sql_EscapeString( mmysql_handle, message_sql, sd->message );

	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`limit`,`autotrade`, `body_direction`, `head_direction`, `sit`) "
		"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, %d, '%d', '%d', '%d' );",
		buyingstores_db, sd->buyer_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->buyingstore.zenylimit, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ){
		Sql_ShowDebug(mmysql_handle);
	}

	for( i = 0; i < sd->buyingstore.slots; i++ ){
		if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`buyingstore_id`,`index`,`item_id`,`amount`,`price`) VALUES( %d, %d, %hu, %d, %d );", buyingstore_items_db, sd->buyer_id, i, sd->buyingstore.items[i].nameid, sd->buyingstore.items[i].amount, sd->buyingstore.items[i].price ) != SQL_SUCCESS ){
			Sql_ShowDebug(mmysql_handle);
		}
	}

	clif_buyingstore_myitemlist(sd);
	clif_buyingstore_entry(sd);
	idb_put(buyingstore_db, sd->status.char_id, sd);

	return 0;
}
Example #4
0
/**
 * Player setup a new shop
 * @param sd : player opening the shop
 * @param message : shop title
 * @param data : itemlist data
 *	data := {<index>.w <amount>.w <value>.l}[count]
 * @param count : number of different items
 * @param at Autotrader info, or NULL if requetsed not from autotrade persistance
 * @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - Cart data isn't saved yet, 5 - No valid item found
 */
int8 vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count, struct s_autotrader *at)
{
	int i, j, k, n;
	int vending_skill_lvl;
	char message_sql[MESSAGE_SIZE*2];
	int item_bad_price[MAX_VENDING];
	StringBuf buf;
	struct item_data *item;
	
	nullpo_retr(false,sd);

	if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) {
		return 1; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once
	}

	vending_skill_lvl = pc_checkskill(sd, MC_VENDING);
	
	// skill level and cart check
	if( !vending_skill_lvl || !pc_iscarton(sd) ) {
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
		return 2;
	}

	// check number of items in shop
	if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
		return 3;
	}

	if (save_settings&CHARSAVE_VENDING) // Avoid invalid data from saving
		chrif_save(sd, 0);

	// filter out invalid items
	i = k = 0;
	for( j = 0; j < count; j++ ) {
		short index        = *(uint16*)(data + 8*j + 0);
		short amount       = *(uint16*)(data + 8*j + 2);
		unsigned int value = *(uint32*)(data + 8*j + 4);

		index -= 2; // offset adjustment (client says that the first cart position is 2)

		if( index < 0 || index >= MAX_CART // invalid position
		||  pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity
		//NOTE: official server does not do any of the following checks!
		||  !sd->status.cart[index].identify // unidentified item
		||  sd->status.cart[index].attribute == 1 // broken item
		||  sd->status.cart[index].expire_time // It should not be in the cart but just in case
		||  (sd->status.cart[index].bound && !pc_can_give_bounded_items(sd)) // can't trade account bound items and has no permission
		||  !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item
			continue;

		item = itemdb_search(sd->status.cart[index].nameid);

		if (item->value_buy_min > 0 && value > item->value_buy_min)
		{
			if (battle_config.vending_price_min_overflow  > 0 )
			{
				if (value > item->value_buy_min + (item->value_buy_min * (battle_config.vending_price_min_overflow / 10000.)))
				{
					item_bad_price[k++] = sd->status.cart[index].nameid;
					continue;
				}
			}
			else
			{
				item_bad_price[k++] = sd->status.cart[index].nameid;
				continue;
			}
		}

		sd->vending[i].index = index;
		sd->vending[i].amount = amount;
		sd->vending[i].value = min(value, (unsigned int)battle_config.vending_max_value);

		// Player just moved item to cart and we don't have the correct cart ID yet.
		if (sd->status.cart[sd->vending[i].index].id == 0) {
			char msg[256];

			snprintf(msg, 256, "äÍà·çÁ %s ÂѧäÁèä´éºÑ¹·Ö¡. ¡ÃسÒÍÍ¡à¢éÒãËÁè à¾×èÍãËéäÍà·çÁ·Ó¡ÒÃ૿ŧÃéÒ¹¤éÒ", item->jname);
			clif_displaymessage(sd->fd, msg);
			clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
			return 4;
		}

		i++; // item successfully added
	}

	//if( i != j )
		//clif_displaymessage (sd->fd, msg_txt(sd,266)); //"Some of your items cannot be vended and were removed from the shop."

	for (n = 0; n < k; n++)
	{
		char msg[512];

		item = itemdb_search(item_bad_price[n]);
		
		if (battle_config.vending_price_min_overflow > 0)
			sprintf(msg, "%s µÑé§ÃÒ¤Ò¢ÒÂÊÙ§¡ÇèÒ·Õè NPC ÁÕ¢ÒÂÍÂÙèà¡Ô¹ %d%% ¨Ð¶Ù¡µÑ´ÍÍ¡¨Ò¡ÃÒ¡ÒÃà¾×èÍ»éͧ¡Ñ¹¡ÒÃâ¡è§ÃÒ¤Ò", item->jname, battle_config.vending_price_min_overflow/100);
		else
			sprintf(msg, "%s µÑé§ÃÒ¤Ò¢ÒÂÊÙ§¡ÇèÒ·Õè NPC ÁÕ¢ÒÂÍÂÙè ¨Ð¶Ù¡µÑ´ÍÍ¡¨Ò¡ÃÒ¡ÒÃà¾×èÍ»éͧ¡Ñ¹¡ÒÃâ¡è§ÃÒ¤Ò", item->jname);
		clif_displaymessage(sd->fd, msg);
	}

	if( i == 0 ) { // no valid item found
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
		return 5;
	}

	sd->state.prevend = 0;
	sd->state.vending = true;
	sd->vender_id = vending_getuid();
	sd->vend_num = i;
	safestrncpy(sd->message, message, MESSAGE_SIZE);
	
	Sql_EscapeString( mmysql_handle, message_sql, sd->message );

	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`, `account_id`, `char_id`, `sex`, `map`, `x`, `y`, `title`, `autotrade`, `body_direction`, `head_direction`, `sit`) "
		"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d' );",
		vendings_db, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ) {
		Sql_ShowDebug(mmysql_handle);
	}

	StringBuf_Init(&buf);
	StringBuf_Printf(&buf, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES", vending_items_db);
	for (i = 0; i < count; i++) {
		StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd->vender_id, i, sd->status.cart[sd->vending[i].index].id, sd->vending[i].amount, sd->vending[i].value);
		if (i < count-1)
			StringBuf_AppendStr(&buf, ",");
	}
	if (SQL_ERROR == Sql_QueryStr(mmysql_handle, StringBuf_Value(&buf)))
		Sql_ShowDebug(mmysql_handle);
	StringBuf_Destroy(&buf);

	clif_openvending(sd,sd->bl.id,sd->vending);
	clif_showvendingboard(&sd->bl,message,0);

	idb_put(vending_db, sd->status.char_id, sd);

	return 0;
}
Example #5
0
/**
 * Player setup a new shop
 * @param sd : player opening the shop
 * @param message : shop title
 * @param data : itemlist data
 *  data := {<index>.w <amount>.w <value>.l}[count]
 * @param count : number of different items
 * @param at Autotrader info, or NULL if requetsed not from autotrade persistance
 * @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - No valid item found
 */
int8 vending_openvending(struct map_session_data *sd, const char *message, const uint8 *data, int count, struct s_autotrader *at) {
	int i, j;
	int vending_skill_lvl;
	char message_sql[MESSAGE_SIZE * 2];
	StringBuf buf;

	nullpo_retr(1, sd);

	if( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd) )
		return 1; //Can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once

	vending_skill_lvl = pc_checkskill(sd, MC_VENDING);

	//Skill level and cart check
	if( !vending_skill_lvl || !pc_iscarton(sd) ) {
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0);
		return 2;
	}

	//Check number of items in shop
	if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { //Invalid item count
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0);
		return 3;
	}

	if( save_settings&CHARSAVE_VENDING ) // Avoid invalid data from saving
		chrif_save(sd, CSAVE_INVENTORY|CSAVE_CART);

	//Filter out invalid items
	i = 0;
	for( j = 0; j < count; j++ ) {
		short index        = *(uint16 *)(data + 8 * j + 0);
		short amount       = *(uint16 *)(data + 8 * j + 2);
		unsigned int value = *(uint32 *)(data + 8 * j + 4);

		index -= 2; //Offset adjustment (client says that the first cart position is 2)

		if( index < 0 || index >= MAX_CART || //Invalid position
			pc_cartitem_amount(sd, index, amount) < 0 || //Invalid item or insufficient quantity
			//NOTE: Official server does not do any of the following checks!
			!sd->cart.u.items_cart[index].identify || //Unidentified item
			sd->cart.u.items_cart[index].attribute || //Broken item
			sd->cart.u.items_cart[index].expire_time || //It should not be in the cart but just in case
			(sd->cart.u.items_cart[index].bound && !pc_can_give_bounded_items(sd)) || //Can't trade account bound items and has no permission
			!itemdb_cantrade(&sd->cart.u.items_cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) //Untradeable item
			continue;

		sd->vending[i].index = index;
		sd->vending[i].amount = amount;
		sd->vending[i].value = umin(value, (unsigned int)battle_config.vending_max_value);
		i++; //Item successfully added
	}

	if( i != j )
		clif_displaymessage(sd->fd, msg_txt(266)); // "Some of your items cannot be vended and were removed from the shop."

	if( i == 0 ) { //No valid item found
		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0); //Custom reply packet
		return 4;
	}

	sd->state.prevend = 0;
	sd->state.vending = 1;
	sd->vender_id = vending_getuid();
	sd->vend_num = i;
	safestrncpy(sd->message, message, MESSAGE_SIZE);

	Sql_EscapeString(mmysql_handle, message_sql, sd->message);

	if( Sql_Query(mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`autotrade`,`body_direction`,`head_direction`,`sit`) VALUES(%d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d');",
		vendings_db, sd->vender_id, sd->status.account_id, sd->status.char_id, (!sd->status.sex ? 'F' : 'M'), map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, (at ? at->dir : sd->ud.dir), (at ? at->head_dir : sd->head_dir), (at ? at->sit : pc_issit(sd))) != SQL_SUCCESS )
		Sql_ShowDebug(mmysql_handle);

	StringBuf_Init(&buf);
	StringBuf_Printf(&buf, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES", vending_items_db);
	for( j = 0; j < i; j++ ) {
		StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd->vender_id, j, sd->cart.u.items_cart[sd->vending[j].index].id, sd->vending[j].amount, sd->vending[j].value);
		if( j < i - 1 )
			StringBuf_AppendStr(&buf, ",");
	}
	if( SQL_ERROR == Sql_QueryStr(mmysql_handle, StringBuf_Value(&buf)) )
		Sql_ShowDebug(mmysql_handle);
	StringBuf_Destroy(&buf);

	clif_openvending(sd, sd->bl.id, sd->vending);
	clif_showvendingboard(&sd->bl, message, 0);

	idb_put(vending_db, sd->status.char_id, sd);

	return 0;
}