int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount)
{
	struct item_data *data;
	int i;

	nullpo_retr(1, sd);
	nullpo_retr(1, stor);
	nullpo_retr(1, item_data);

	if(item_data->nameid <= 0 || amount <= 0)
		return 1;

	data = itemdb_search(item_data->nameid);

	if( !itemdb_canguildstore(item_data, pc_isGM(sd)) || item_data->expire_time || item_data->bound )
	{	//Check if item is storable. [Skotlex]
		clif_displaymessage (sd->fd, msg_txt(264));
		return 1;
	}

	if( sd->state.secure_items )
	{
		clif_displaymessage(sd->fd, "You can't store items on Guild Storage. Blocked with @security");
		return 1;
	}

	if(itemdb_isstackable2(data)){ //Stackable
		for(i=0;i<MAX_GUILD_STORAGE;i++){
			if(compare_item(&stor->items[i], item_data)) {
				if(stor->items[i].amount+amount > MAX_AMOUNT)
					return 1;
				stor->items[i].amount+=amount;
				clif_storageitemadded(sd,&stor->items[i],i,amount);
				stor->dirty = 1;
				if(log_config.enable_logs&0x1000)
					log_pick_pc(sd, "G", item_data->nameid, -amount, item_data, 0);
				return 0;
			}
		}
	}
	//Add item
	for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++);
	
	if(i>=MAX_GUILD_STORAGE)
		return 1;
	
	memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
	stor->items[i].amount=amount;
	stor->storage_amount++;
	clif_storageitemadded(sd,&stor->items[i],i,amount);
	clif_updateguildstorageamount(sd,stor->storage_amount);
	stor->dirty = 1;
	if(log_config.enable_logs&0x1000)
		log_pick_pc(sd, "G", item_data->nameid, -amount, item_data, item_data->serial );
	return 0;
}
/*==========================================
 * Internal add-item function.
 *------------------------------------------*/
static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount, int flag)
{
	struct storage_data* stor = &sd->status.storage;
	struct item_data *data;
	int i;

	if( item_data->nameid <= 0 || amount <= 0 )
		return 1;
	
	data = itemdb_search(item_data->nameid);

	if( !itemdb_canstore(item_data, pc_isGM(sd)) )
	{	//Check if item is storable. [Skotlex]
		clif_displaymessage (sd->fd, msg_txt(264));
		return 1;
	}
	
	if( itemdb_isstackable2(data) )
	{//Stackable
		for( i = 0; i < MAX_STORAGE; i++ )
		{
			if( compare_item(&stor->items[i], item_data) )
			{// existing items found, stack them
				if( amount > MAX_AMOUNT - stor->items[i].amount )
					return 1;
				stor->items[i].amount += amount;
				if( flag ) clif_storageitemadded(sd,&stor->items[i],i,amount);
				if(log_config.enable_logs&0x800)
					log_pick_pc(sd, "R", item_data->nameid, -amount, item_data, 0);
				return 0;
			}
		}
	}

	// find free slot
	ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 );
	if( i >= MAX_STORAGE )
		return 1;

	// add item to slot
	memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
	stor->storage_amount++;
	stor->items[i].amount = amount;
	if( flag )
	{
		clif_storageitemadded(sd,&stor->items[i],i,amount);
		clif_updatestorageamount(sd,stor->storage_amount);
	}
	if(log_config.enable_logs&0x800)
		log_pick_pc(sd, "R", item_data->nameid, -amount, item_data, item_data->serial );

	return 0;
}
Exemple #3
0
/*==========================================
 * Internal add-item function.
 *------------------------------------------
 */
static int storage_additem(struct map_session_data *sd,struct storage *stor,struct item *item_data,int amount)
{
	struct item_data *data;
	int i;

	if (sd->state.finalsave)
		return 1;

	if(item_data->nameid <= 0 || amount <= 0)
		return 1;
	
	data = itemdb_search(item_data->nameid);

	if (!itemdb_canstore(item_data, pc_isGM(sd)))
	{	//Check if item is storable. [Skotlex]
		clif_displaymessage (sd->fd, msg_txt(264));
		return 1;
	}
	
	if(itemdb_isstackable2(data)){ //Stackable
		for(i=0;i<MAX_STORAGE;i++){
			if( compare_item (&stor->storage_[i], item_data)) {
				if(amount > MAX_AMOUNT - stor->storage_[i].amount)
					return 1;
				stor->storage_[i].amount+=amount;
				clif_storageitemadded(sd,stor,i,amount);
				stor->dirty = 1;
				if(log_config.enable_logs&0x800)
					log_pick_pc(sd, "R", item_data->nameid, -amount, item_data);
				return 0;
			}
		}
	}
	//Add item
	for(i=0;i<MAX_STORAGE && stor->storage_[i].nameid;i++);
	
	if(i>=MAX_STORAGE)
		return 1;

	memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0]));
	stor->storage_[i].amount=amount;
	stor->storage_amount++;
	clif_storageitemadded(sd,stor,i,amount);
	clif_updatestorageamount(sd,stor);
	stor->dirty = 1;
	if(log_config.enable_logs&0x800)
		log_pick_pc(sd, "R", item_data->nameid, -amount, item_data);
	return 0;
}
Exemple #4
0
void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
{
	nullpo_retv(sd);
	nullpo_retv(msg);

	if( msg->item.amount > 0 )
	{
		// Item recieve (due to failure)
		if(log_config.enable_logs&0x2000)
			log_pick_pc(sd, "E", msg->item.nameid, msg->item.amount, &msg->item, msg->item.serial);
		if( battle_config.lootevent & 8 ) {
			pc_setglobalreg( sd, "LastLootID", msg->item.nameid ); //Last lootet Item ID
			pc_setglobalreg( sd, "LastLootAmount", msg->item.amount ); //Last looted Item Amount
			npc_event_doall_id( "OnLoot", sd->bl.id );
		} 

		pc_additem(sd, &msg->item, msg->item.amount);
	}

	if( msg->zeny > 0 )
	{
		//Zeny recieve (due to failure)
		if(log_config.zeny)
			log_zeny(sd, "E", sd, msg->zeny);

		sd->status.zeny += msg->zeny;
		clif_updatestatus(sd, SP_ZENY);
	}
	
	clif_Mail_send(sd->fd, true);
}
Exemple #5
0
/// logs item transactions
void log_pick(struct block_list* bl, e_log_pick_type type, int nameid, int amount, struct item* itm)
{
	if( bl == NULL )
	{
		ShowError("log_pick: bl == NULL\n");
	}
	else switch( bl->type )
	{
		case BL_PC:  log_pick_pc((TBL_PC*)bl, type, nameid, amount, itm);   break;
		case BL_MOB: log_pick_mob((TBL_MOB*)bl, type, nameid, amount, itm); break;
		default:
			ShowDebug("log_pick: Unhandled bl type %d.\n", bl->type);
	}
}
Exemple #6
0
void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item)
{

	if( item->nameid > 0 && item->amount > 0 )
	{

		pc_additem(sd, item, item->amount);

		log_pick_pc(sd, LOG_TYPE_MAIL, item->nameid, item->amount, item);
		clif_Mail_getattachment(sd->fd, 0);
	}

	if( zeny > 0 )
	{  //Zeny recieve
		log_zeny(sd, LOG_TYPE_MAIL, sd, zeny);
		pc_getzeny(sd, zeny);
	}
}
/*==========================================
 * Internal del-item function
 *------------------------------------------*/
int storage_delitem(struct map_session_data* sd, int n, int amount)
{
	if( sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount )
		return 1;

	sd->status.storage.items[n].amount -= amount;

	if(log_config.enable_logs&0x800)
		log_pick_pc(sd, "R", sd->status.storage.items[n].nameid, amount, &sd->status.storage.items[n]);

	if( sd->status.storage.items[n].amount == 0 )
	{
		memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0]));
		sd->status.storage.storage_amount--;
		if( sd->state.storage_flag == 1 ) clif_updatestorageamount(sd,sd->status.storage.storage_amount);
	}
	if( sd->state.storage_flag == 1 ) clif_storageitemremoved(sd,n,amount);
	return 0;
}
Exemple #8
0
/*==========================================
 * Internal del-item function
 *------------------------------------------
 */
static int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount)
{

	if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount)
		return 1;

	stor->storage_[n].amount-=amount;
	if(log_config.enable_logs&0x800)
		log_pick_pc(sd, "R", stor->storage_[n].nameid, amount, &stor->storage_[n]);
	if(stor->storage_[n].amount==0){
		memset(&stor->storage_[n],0,sizeof(stor->storage_[0]));
		stor->storage_amount--;
		clif_updatestorageamount(sd,stor);
	}
	clif_storageitemremoved(sd,n,amount);

	stor->dirty = 1;
	return 0;
}
Exemple #9
0
void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item)
{
	if( item->nameid > 0 && item->amount > 0 )
	{
		pc_additem(sd, item, item->amount);

		if(log_config.enable_logs&0x2000)
			log_pick_pc(sd, "E", item->nameid, item->amount, item);

		clif_Mail_getattachment(sd->fd, 0);
	}

	if( zeny > 0 )
	{  //Zeny recieve
		if(log_config.zeny)
			log_zeny(sd, "E", sd, zeny);
		pc_getzeny(sd, zeny);
	}
}
int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount)
{
	nullpo_retr(1, sd);
	nullpo_retr(1, stor);

	if(stor->items[n].nameid==0 || stor->items[n].amount<amount)
		return 1;

	stor->items[n].amount-=amount;
	if(log_config.enable_logs&0x1000)
		log_pick_pc(sd, "G", stor->items[n].nameid, amount, &stor->items[n], stor->items[n].serial);
	if(stor->items[n].amount==0){
		memset(&stor->items[n],0,sizeof(stor->items[0]));
		stor->storage_amount--;
		clif_updateguildstorageamount(sd,stor->storage_amount);
	}
	clif_storageitemremoved(sd,n,amount);
	stor->dirty = 1;
	return 0;
}
Exemple #11
0
int mail_removeitem(struct map_session_data *sd, short flag)
{
	nullpo_ret(sd);	

	if( sd->mail.amount )
	{
		if (flag)
		{ // Item send
			log_pick_pc(sd, LOG_TYPE_MAIL, sd->mail.nameid, -sd->mail.amount, &sd->status.inventory[sd->mail.index]);

			pc_delitem(sd, sd->mail.index, sd->mail.amount, 1, 0);
		}
		else
			clif_additem(sd, sd->mail.index, sd->mail.amount, 0);
	}

	sd->mail.nameid = 0;
	sd->mail.index = 0;
	sd->mail.amount = 0;
	return 1;
}
Exemple #12
0
int mail_removeitem(struct map_session_data *sd, short flag)
{
	nullpo_retr(0,sd);

	if( sd->mail.amount )
	{
		if (flag)
		{ // Item send
			if(log_config.enable_logs&0x2000)
				log_pick_pc(sd, "E", sd->mail.nameid, -sd->mail.amount, &sd->status.inventory[sd->mail.index]);

			pc_delitem(sd, sd->mail.index, sd->mail.amount, 1);
		}
		else
			clif_additem(sd, sd->mail.index, sd->mail.amount, 0);
	}

	sd->mail.nameid = 0;
	sd->mail.index = 0;
	sd->mail.amount = 0;
	return 1;
}
Exemple #13
0
void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
{
	nullpo_retv(sd);
	nullpo_retv(msg);

	// Item  recieve (due to failure)
	if(log_config.enable_logs&0x2000)
		log_pick_pc(sd, "E", msg->item.nameid, msg->item.amount, &msg->item);

	pc_additem(sd, &msg->item, msg->item.amount);
	
	if( msg->zeny > 0 )
	{
		//Zeny recieve (due to failure)
		if(log_config.zeny)
			log_zeny(sd, "E", sd, msg->zeny);

		sd->status.zeny += msg->zeny;
		clif_updatestatus(sd, SP_ZENY);
	}
	
	clif_Mail_send(sd->fd, true);
}
Exemple #14
0
void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item)
{
	if( item->nameid > 0 && item->amount > 0 )
	{
		pc_additem(sd, item, item->amount);

		if(log_config.enable_logs&0x2000)
			log_pick_pc(sd, "E", item->nameid, item->amount, item, item->serial);
		if( battle_config.lootevent & 8 ) {
			pc_setglobalreg( sd, "LastLootID", item->nameid ); //Last lootet Item ID
			pc_setglobalreg( sd, "LastLootAmount", item->amount ); //Last looted Item Amount
			npc_event_doall_id( "OnLoot", sd->bl.id );
		}

		clif_Mail_getattachment(sd->fd, 0);
	}

	if( zeny > 0 )
	{  //Zeny recieve
		if(log_config.zeny)
			log_zeny(sd, "E", sd, zeny);
		pc_getzeny(sd, zeny);
	}
}
Exemple #15
0
void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
{
	nullpo_retv(sd);
	nullpo_retv(msg);

	if( msg->item.amount > 0 )
	{
		// Item recieve (due to failure)
		log_pick_pc(sd, LOG_TYPE_MAIL, msg->item.nameid, msg->item.amount, &msg->item);

		pc_additem(sd, &msg->item, msg->item.amount);
	}

	if( msg->zeny > 0 )
	{
		//Zeny recieve (due to failure)
		log_zeny(sd, LOG_TYPE_MAIL, sd, msg->zeny);

		sd->status.zeny += msg->zeny;
		clif_updatestatus(sd, SP_ZENY);
	}
	
	clif_Mail_send(sd->fd, true);
}
/*==========================================
 * 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);
	char output[256];

	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( !vsd->vend_coin || vsd->vend_coin == battle_config.vending_zeny_id )
		{ // Normal Vending - Zeny Option
			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;
			}
 		}
		else if( battle_config.vending_cash_id && vsd->vend_coin == battle_config.vending_cash_id )
		{ // Cash Shop
			if( z > (double)sd->cashPoints || z < 0. || z > (double)MAX_ZENY )
			{
				sprintf(output,msg_txt(915),itemdb_jname(vsd->vend_coin));
				clif_displaymessage(sd->fd,output);
				return;
			}
			if( z + (double)vsd->cashPoints > (double)MAX_ZENY && !battle_config.vending_over_max )
			{
				sprintf(output,msg_txt(916),itemdb_jname(vsd->vend_coin));
				clif_displaymessage(sd->fd,output);
				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
		}
	}

	// Payments
	if( !vsd->vend_coin || vsd->vend_coin == battle_config.vending_zeny_id )
	{
		if( log_config.zeny > 0 )
			log_zeny(vsd, "V", sd, (int)z); //Logs (V)ending Zeny [Lupus]

		pc_payzeny(sd, (int)z);

		if( battle_config.vending_tax || (vsd->state.autotrade && battle_config.at_tax && !pc_isPremium(vsd)) )
			z -= z * ((battle_config.vending_tax + ((vsd->state.autotrade && !pc_isPremium(vsd)) ? battle_config.at_tax : 0)) / 10000.);

		pc_getzeny(vsd, (int)z);
	}
	else if( battle_config.vending_cash_id && vsd->vend_coin == battle_config.vending_cash_id )
	{
		pc_paycash(sd,(int)z,0);
		pc_getcash(vsd,(int)z,0);
	}
	else
	{
		if( z < 0. || (i = pc_search_inventory(sd,vsd->vend_coin)) < 0 || z > (double)sd->status.inventory[i].amount )
		{
			sprintf(output,msg_txt(915),itemdb_jname(vsd->vend_coin));
			clif_displaymessage(sd->fd,output);
			return;
		}

		switch( pc_checkadditem(vsd,vsd->vend_coin,(int)z) )
		{
		case ADDITEM_NEW:
			if( pc_inventoryblank(vsd) > 0 )
				break;
		case ADDITEM_OVERAMOUNT:
			sprintf(output,msg_txt(916),itemdb_jname(vsd->vend_coin));
			clif_displaymessage(sd->fd,output);
			return;
		}

		pc_additem(vsd,&sd->status.inventory[i],(int)z);
		pc_delitem(sd,i,(int)z,0,6);
	}
	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]
		if(log_config.enable_logs&0x4) {
			log_pick_pc(vsd, "V", vsd->status.cart[idx].nameid, -amount, &vsd->status.cart[idx], vsd->status.cart[idx].serial );
			log_pick_pc( sd, "V", vsd->status.cart[idx].nameid,  amount, &vsd->status.cart[idx], vsd->status.cart[idx].serial );
		}

		// 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?
		}
	}
}
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_pc(sd, LOG_TYPE_BUYING_STORE, nameid, -((int)amount), &sd->status.inventory[index]);
		log_pick_pc(pl_sd, 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);
	}
}
Exemple #18
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;
	}

	if(log_config.enable_logs&0x8) //Logs items, taken by (P)layers [Lupus]
		log_pick_pc(target, "P", item_data->nameid, item_data->amount, item_data);
	
	if(battle_config.party_show_share_picker && target != sd) {
		char output[80];
		sprintf(output, "%s acquired %s.",target->status.name, itemdb_jname(item_data->nameid));
		clif_disp_onlyself(sd,output,strlen(output));
	}
	return 0;
}
/*==========================================
 * Žæˆø‹–‘ø(trade‰Ÿ‚µ)
 *------------------------------------------*/
void trade_tradecommit(struct map_session_data *sd)
{
	struct map_session_data *tsd;
	int trade_i;
	int flag;

	if (!sd->state.trading || !sd->state.deal_locked) //Locked should be 1 (pressed ok) before you can press trade.
		return;

	if ((tsd = map_id2sd(sd->trade_partner)) == NULL) {
		trade_tradecancel(sd);
		return;
	}
	
	sd->state.deal_locked = 2;
	
	if (tsd->state.deal_locked < 2)
		return; //Not yet time for trading.

	//Now is a good time (to save on resources) to check that the trade can indeed be made and it's not exploitable.
	// 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(tsd)) {
		trade_tradecancel(tsd);
		return;
	}
	// check for full inventory (can not add traded items)
	if (!trade_check(sd,tsd)) { // check the both players
		trade_tradecancel(sd);
		return;
	}
	
	// trade is accepted and correct.
	for( trade_i = 0; trade_i < 10; trade_i++ )
	{
		int n;
		if (sd->deal.item[trade_i].amount)
		{
			n = sd->deal.item[trade_i].index;

			flag = pc_additem(tsd, &sd->status.inventory[n], sd->deal.item[trade_i].amount);
			if (flag == 0)
			{
				//Logs (T)rade [Lupus]
				if(log_config.enable_logs&0x2)
				{
					log_pick_pc(sd, "T", sd->status.inventory[n].nameid, -(sd->deal.item[trade_i].amount), &sd->status.inventory[n]);
					log_pick_pc(tsd, "T", sd->status.inventory[n].nameid, sd->deal.item[trade_i].amount, &sd->status.inventory[n]);
				}
				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 (tsd->deal.item[trade_i].amount)
		{
			n = tsd->deal.item[trade_i].index;

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

	if( sd->deal.zeny || tsd->deal.zeny )
	{
		sd->status.zeny += tsd->deal.zeny - sd->deal.zeny;
		tsd->status.zeny += sd->deal.zeny - tsd->deal.zeny;

		//Logs Zeny (T)rade [Lupus]
		if( sd->deal.zeny && log_config.zeny )
			log_zeny(tsd, "T", sd, sd->deal.zeny);
		if( tsd->deal.zeny && log_config.zeny )
			log_zeny(sd, "T", tsd, tsd->deal.zeny);

		sd->deal.zeny = 0;
		tsd->deal.zeny = 0;

		clif_updatestatus(sd, SP_ZENY);
		clif_updatestatus(tsd, SP_ZENY);
	}
	
	sd->state.deal_locked = 0;
	sd->trade_partner = 0;
	sd->state.trading = 0;
	
	tsd->state.deal_locked = 0;
	tsd->trade_partner = 0;
	tsd->state.trading = 0;
	
	clif_tradecompleted(sd, 0);
	clif_tradecompleted(tsd, 0);

	// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
	if (save_settings&1)
  	{
		chrif_save(sd,0); 
		chrif_save(tsd,0);
	}
}