Ejemplo n.º 1
0
Archivo: mail.c Proyecto: 544a/rathena
/**
* Attempt to set item or zeny to a mail
* @param sd : player attaching the content
* @param idx 0 - Zeny; >= 2 - Inventory item
* @param amount : amout of zeny or number of item
* @return True if item/zeny can be set, False if failed
*/
bool mail_setitem(struct map_session_data *sd, short idx, uint32 amount) {

	if( pc_istrading(sd) )
		return false;

	if( idx == 0 ) { // Zeny Transfer
		if( !pc_can_give_items(sd) )
			return false;

		if( amount > sd->status.zeny )
			amount = sd->status.zeny;

		sd->mail.zeny = amount;
		// clif_updatestatus(sd, SP_ZENY);
		return true;
	} else { // Item Transfer
		idx -= 2;
		mail_removeitem(sd, 0);

		if( idx < 0 || idx >= MAX_INVENTORY )
			return false;
		if( amount > sd->status.inventory[idx].amount )
			return false;
		if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time
			|| !itemdb_available(sd->status.inventory[idx].nameid)
			|| !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd))
			|| (sd->status.inventory[idx].bound && !pc_can_give_bounded_items(sd)) )
			return false;

		sd->mail.index = idx;
		sd->mail.nameid = sd->status.inventory[idx].nameid;
		sd->mail.amount = amount;
		return true;
	}
}
Ejemplo n.º 2
0
/*==========================================
 * Initiates a trade request.
 *------------------------------------------*/
void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd)
{
	nullpo_retv(sd);

	if (map[sd->bl.m].flag.notrade) {
		clif_displaymessage (sd->fd, msg_txt(272));
		return; //Can't trade in notrade mapflag maps.
	}

	if (target_sd == NULL || sd == target_sd) {
		clif_tradestart(sd, 1); // character does not exist
		return;
	}

	if (target_sd->npc_id)
	{	//Trade fails if you are using an NPC.
		clif_tradestart(sd, 2);
		return;
	}

	if (!battle_config.invite_request_check) {
		if (target_sd->guild_invite > 0 || target_sd->party_invite > 0 || target_sd->adopt_invite) {
			clif_tradestart(sd, 2);
			return;
		}
	}

	if ( sd->trade_partner != 0 ) { // If a character tries to trade to another one then cancel the previous one
		struct map_session_data *previous_sd = map_id2sd(sd->trade_partner);
		if( previous_sd ){
			previous_sd->trade_partner = 0;
			clif_tradecancelled(previous_sd);
		} // Once cancelled then continue to the new one.
		sd->trade_partner = 0;
		clif_tradecancelled(sd);
	}

	if (target_sd->trade_partner != 0) {
		clif_tradestart(sd, 2); // person is in another trade
		return;
	}

	if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) //check if both GMs are allowed to trade
	{
		clif_displaymessage(sd->fd, msg_txt(246));
		clif_tradestart(sd, 2); // GM is not allowed to trade
		return;
	} 
	
	// Players can not request trade from far away, unless they are allowed to use @trade.
	if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) &&
	    (sd->bl.m != target_sd->bl.m || !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE))) {
		clif_tradestart(sd, 0); // too far
		return ;
	}
	
	target_sd->trade_partner = sd->status.account_id;
	sd->trade_partner = target_sd->status.account_id;
	clif_traderequest(target_sd, sd->status.name);
}
Ejemplo n.º 3
0
unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {

	if( pc_istrading(sd) )
		return 1;

	if( idx == 0 ) { // Zeny Transfer
		if( amount < 0 || !pc_can_give_items(sd) )
			return 1;

		if( amount > sd->status.zeny )
			amount = sd->status.zeny;

		sd->mail.zeny = amount;
		// clif->updatestatus(sd, SP_ZENY);
		return 0;
	} else { // Item Transfer
		idx -= 2;
		mail->removeitem(sd, 0);

		if( idx < 0 || idx >= MAX_INVENTORY )
			return 1;
		if( amount < 0 || amount > sd->status.inventory[idx].amount )
			return 1;
		if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time ||
			!itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd)) ||
			(sd->status.inventory[idx].bound && !pc_can_give_bound_items(sd)) )
			return 1;

		sd->mail.index = idx;
		sd->mail.nameid = sd->status.inventory[idx].nameid;
		sd->mail.amount = amount;

		return 0;
	}
}
Ejemplo n.º 4
0
/*==========================================
 * Request a shop's item list
 *------------------------------------------*/
void vending_vendinglistreq(struct map_session_data* sd, int id)
{
	struct map_session_data* vsd;
	nullpo_retv(sd);

	if( (vsd = map_id2sd(id)) == NULL )
		return;
	if( !vsd->state.vending )
		return; // not vending

	if ( !pc_can_give_items(pc_isGM(sd)) || !pc_can_give_items(pc_isGM(vsd)) ) //check if both GMs are allowed to trade
	{	// GM is not allowed to trade
		clif_displaymessage(sd->fd, msg_txt(246));
		return;
	} 

	sd->vended_id = vsd->vender_id;  // register vending uid
	if( battle_config.vending_zeny_id && vsd->vend_coin )
	{ // Extended Vending System
		char output[256];
		sprintf(output,msg_txt(914),itemdb_jname(vsd->vend_coin));
		clif_displaymessage(sd->fd,output);
	}

	clif_vendinglist(sd, id, vsd->vending);
}
Ejemplo n.º 5
0
/*==========================================
 * Initiates a trade request.
 *------------------------------------------*/
void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd)
{
	int level;

	nullpo_retv(sd);

	if (map[sd->bl.m].flag.notrade) {
		clif_displaymessage (sd->fd, msg_txt(272));
		return; //Can't trade in notrade mapflag maps.
	}

	if (target_sd == NULL || sd == target_sd) {
		clif_tradestart(sd, 1); // character does not exist
		return;
	}

	if (target_sd->npc_id)
	{	//Trade fails if you are using an NPC.
		clif_tradestart(sd, 2);
		return;
	}

	if (!battle_config.invite_request_check) {
		if (target_sd->guild_invite > 0 || target_sd->party_invite > 0 || target_sd->adopt_invite) {
			clif_tradestart(sd, 2);
			return;
		}
	}

	if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) {
		clif_tradestart(sd, 2); // person is in another trade
		return;
	}

	level = pc_isGM(sd);
	if ( !pc_can_give_items(level) || !pc_can_give_items(pc_isGM(target_sd)) ) //check if both GMs are allowed to trade
	{
		clif_displaymessage(sd->fd, msg_txt(246));
		clif_tradestart(sd, 2); // GM is not allowed to trade
		return;
	} 
	
	//Fixed. Only real GMs can request trade from far away! [Lupus] 
	if (level < battle_config.lowest_gm_level && (sd->bl.m != target_sd->bl.m ||
		!check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE)
	)) {
		clif_tradestart(sd, 0); // too far
		return ;
	}
	
	target_sd->trade_partner = sd->status.account_id;
	sd->trade_partner = target_sd->status.account_id;
	clif_traderequest(target_sd, sd->status.name);
}
Ejemplo n.º 6
0
/**
 * Request to open premium storage
 * @param sd Player who request
 * @param num Storage number
 * @param mode Storage mode @see enum e_storage_mode
 * @return 1:Success to request, 0:Failed
 * @author [Cydh]
 **/
bool storage_premiumStorage_load(struct map_session_data *sd, uint8 num, uint8 mode) {
	nullpo_ret(sd);

	if (sd->state.storage_flag)
		return 0;

	if (sd->state.vending || sd->state.buyingstore || sd->state.prevend || sd->state.autotrade)
		return 0;

	if (sd->state.banking || sd->state.callshop)
		return 0;

	if (!pc_can_give_items(sd)) { // check is this GM level is allowed to put items to storage
		clif_displaymessage(sd->fd, msg_txt(sd,246));
		return 0;
	}

	if (!&sd->premiumStorage || sd->premiumStorage.stor_id != num)
		return intif_storage_request(sd, TABLE_STORAGE, num, mode);
	else {
		sd->premiumStorage.state.put = (mode&STOR_MODE_PUT) ? 1 : 0;
		sd->premiumStorage.state.get = (mode&STOR_MODE_GET) ? 1 : 0;
		storage_premiumStorage_open(sd);
	}
	return 1;
}
Ejemplo n.º 7
0
void buyingstore_open(struct map_session_data* sd, int account_id)
{
	struct map_session_data* pl_sd;

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

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

	if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore )
	{// not online or not buying
		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
		return;
	}

	// success
	clif_buyingstore_itemlist(sd, pl_sd);
}
Ejemplo n.º 8
0
/*==========================================
* Attempt to open guild storage for sd
* return
* 	0 : success (open or req to create a new one)
* 	1 : fail
*	2 : no guild for sd
 *------------------------------------------*/
int storage_guild_storageopen(struct map_session_data* sd)
{
	struct guild_storage *gstor;

	nullpo_ret(sd);

	if(sd->status.guild_id <= 0)
		return 2;

	if(sd->state.storage_flag)
		return 1; //Can't open both storages at a time.

	if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus]
		clif_displaymessage(sd->fd, msg_txt(sd,246));
		return 1;
	}

	if((gstor = guild2storage2(sd->status.guild_id)) == NULL) {
		intif_request_guild_storage(sd->status.account_id,sd->status.guild_id);
		return 0;
	}
	if(gstor->storage_status)
		return 1;

	if( gstor->lock )
		return 1;

	gstor->storage_status = 1;
	sd->state.storage_flag = 2;
	storage_sortitem(gstor->items, ARRAYLENGTH(gstor->items));
	clif_storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items));
	clif_updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE);
	return 0;
}
Ejemplo n.º 9
0
int storage_guild_storageopen(struct map_session_data* sd)
{
	struct guild_storage *gstor;

	nullpo_retr(0, sd);

	if(sd->status.guild_id <= 0)
		return 2;

	if(sd->state.storage_flag)
		return 1; //Can't open both storages at a time.
	
	if( !pc_can_give_items(pc_isGM(sd)) ) { //check is this GM level can open guild storage and store items [Lupus]
		clif_displaymessage(sd->fd, msg_txt(246));
		return 1;
	}

	if((gstor = guild2storage2(sd->status.guild_id)) == NULL) {
		intif_request_guild_storage(sd->status.account_id,sd->status.guild_id);
		return 0;
	}
	if(gstor->storage_status)
		return 1;
	
	gstor->storage_status = 1;
	sd->state.storage_flag = 2;
	clif_guildstoragelist(sd,gstor);
	clif_updateguildstorageamount(sd,gstor->storage_amount);
	return 0;
}
Ejemplo n.º 10
0
void buyingstore_open(struct map_session_data* sd, int account_id)
{
	struct map_session_data* pl_sd;

	nullpo_retv(sd);
	if( !battle_config.feature_buying_store || pc_istrading(sd) )
	{// not allowed to sell
		return;
	}

	if( !pc_can_give_items(sd) )
	{// custom: GM is not allowed to sell
		clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
		return;
	}

	if( ( pl_sd = map->id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore ) {
		// not online or not buying
		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
		return;
	}

	// success
	clif->buyingstore_itemlist(sd, pl_sd);
}
Ejemplo n.º 11
0
unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount)
{
	if (idx == 0)
	{ // Zeny Transfer
		if( amount < 0 )
			return 0;
		if( amount > sd->status.zeny )
			amount = sd->status.zeny;

		if( !pc_can_give_items(pc_isGM(sd)) )
			amount = 0;

		sd->mail.zeny = amount;
		// clif_updatestatus(sd, SP_ZENY);
		return 0;
	}
	else
	{ // Item Transfer
		idx -= 2;
		mail_removeitem(sd, 0);

		if( idx < 0 || idx >= MAX_INVENTORY )
			return 1;
		if( amount < 0 || amount > sd->status.inventory[idx].amount )
			return 1;
		if( !pc_candrop(sd, &sd->status.inventory[idx]) )
			return 1;

		sd->mail.index = idx;
		sd->mail.nameid = sd->status.inventory[idx].nameid;
		sd->mail.amount = amount;
		
		return 0;
	}
}
Ejemplo n.º 12
0
/*==========================================
 * Opens a storage. Returns:
 * 0 - success
 * 1 - fail
 * 2 - Storage requested from char-server (will open automatically later)
 *------------------------------------------
 */
int storage_storageopen(struct map_session_data *sd)
{
	struct storage *stor;
	nullpo_retr(0, sd);

	if(sd->state.finalsave) //Refuse to open storage when you had your last save done.
		return 1;

	if(sd->state.storage_flag)
		return 1; //Already open?
	
	if(pc_can_give_items(pc_isGM(sd)))
  	{ //check is this GM level is allowed to put items to storage
		clif_displaymessage(sd->fd, msg_txt(246));
		return 1;
	}
	
	if((stor = idb_get(storage_db,sd->status.account_id)) == NULL)
  	{	//Request storage.
		intif_request_storage(sd->status.account_id);
		return 2;
	}
  
	if (stor->storage_status)
  		return 1; //Already open/player already has it open...

	stor->storage_status = 1;
	sd->state.storage_flag = 1;
	clif_storagelist(sd,stor);
	clif_updatestorageamount(sd,stor);
	return 0;
}
Ejemplo n.º 13
0
/**
* Attempt to set item or zeny
* @param sd
* @param idx 0 - Zeny; >= 2 - Inventory item
* @param amount
* @return True if item/zeny can be set, False if failed
*/
bool mail_setitem(struct map_session_data *sd, short idx, int amount) {
	if( sd->state.secure_items )
	{
		clif_displaymessage(sd->fd, "You can't attach. Blocked with @security");
		return 1;
	}

	if( pc_istrading(sd) )
		return false;

	if( battle_config.super_woe_enable )
	{
		clif_displaymessage(sd->fd, "Super WoE don't allow send items/zeny with attachments");
		return 1;
	}

	if( idx == 0 )
	{ // Zeny Transfer
		if( !pc_can_give_items(sd) )
			return false;

		if( amount > sd->status.zeny )
			amount = sd->status.zeny;

		sd->mail.zeny = amount;
		// clif_updatestatus(sd, SP_ZENY);
		return true;
	} else { // Item Transfer
		idx -= 2;
		mail_removeitem(sd, 0);

		if( idx < 0 || idx >= MAX_INVENTORY )
			return false;
		if( amount > sd->status.inventory[idx].amount )
			return false;
		if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time
			|| !itemdb_available(sd->status.inventory[idx].nameid)
			|| !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd))
			|| (sd->status.inventory[idx].bound && !pc_can_give_bounded_items(sd)) )
			return false;

		sd->mail.index = idx;
		sd->mail.nameid = sd->status.inventory[idx].nameid;
		sd->mail.amount = amount;
		return true;
	}
}
Ejemplo n.º 14
0
/*==========================================
 * Request a shop's item list
 *------------------------------------------*/
void vending_vendinglistreq(struct map_session_data* sd, int id)
{
    struct map_session_data* vsd;
    nullpo_retv(sd);

    if( (vsd = map_id2sd(id)) == NULL )
        return;
    if( vsd->vender_id == 0 )
        return; // not vending

    if ( !pc_can_give_items(pc_isGM(sd)) || !pc_can_give_items(pc_isGM(vsd)) ) //check if both GMs are allowed to trade
    {   // GM is not allowed to trade
        clif_displaymessage(sd->fd, msg_txt(246));
        return;
    }

    clif_vendinglist(sd, id, vsd->vending);
}
Ejemplo n.º 15
0
/*==========================================
 * Request a shop's item list
 *------------------------------------------*/
void vending_vendinglistreq(struct map_session_data *sd, unsigned int id) {
	struct map_session_data *vsd;
	nullpo_retv(sd);

	if((vsd = map->id2sd(id)) == NULL)
		return;
	if(!vsd->state.vending)
		return; // not vending

	if(!pc_can_give_items(sd) || !pc_can_give_items(vsd)) { //check if both GMs are allowed to trade
		// GM is not allowed to trade
		clif_displaymessage(sd->fd, msg_txt(246));
		return;
	}

	sd->vended_id = vsd->vender_id;  // register vending uid

	clif_vendinglist(sd, id, vsd->vending);
}
Ejemplo n.º 16
0
/*==========================================
 * Request a shop's item list
 *------------------------------------------*/
void vending_vendinglistreq(struct map_session_data* sd, unsigned int id)
{
	struct map_session_data* vsd;
	nullpo_retv(sd);

	if( (vsd = map->id2sd(id)) == NULL )
		return;
	if( !vsd->state.vending )
		return; // not vending

	if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) { //check if both GMs are allowed to trade
		clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action.
		return;
	}

	sd->vended_id = vsd->vender_id;  // register vending uid

	clif->vendinglist(sd, id, vsd->vending);
}
Ejemplo n.º 17
0
/*==========================================
 * Solicitando uma lista de itens de venda
 *------------------------------------------*/
void vending_vendinglistreq(struct map_session_data* sd, unsigned int id) {
	struct map_session_data* vsd;
	nullpo_retv(sd);

	if( (vsd = map->id2sd(id)) == NULL )
		return;
	if( !vsd->state.vending )
		return; // nao vendendo

	if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) { //checando se ambos GMs sao permitidos negociar
		// GM nao esta permitido negociar
		clif->message(sd->fd, msg_txt(246));
		return;
	}

	sd->vended_id = vsd->vender_id;  // registra uid de venda

	clif->vendinglist(sd, id, vsd->vending);
}
Ejemplo n.º 18
0
/*==========================================
 * 取引要請を相手に送る
 *------------------------------------------
 */
void trade_traderequest(struct map_session_data *sd, int target_id) {
	struct map_session_data *target_sd;
	int level;

	nullpo_retv(sd);

	if (map[sd->bl.m].flag.notrade) {
		clif_displaymessage (sd->fd, msg_txt(272));
		return; //Can't trade in notrade mapflag maps.
	}

	if ((target_sd = map_id2sd(target_id)) != NULL) {
		if (!battle_config.invite_request_check) {
			if (target_sd->guild_invite > 0 || target_sd->party_invite > 0) {
				clif_tradestart(sd, 2); // 相手はPT要請中かGuild要請中
				return;
			}
		}
		level = pc_isGM(sd);
		if ( pc_can_give_items(level) || pc_can_give_items(pc_isGM(target_sd)) ) //check if both GMs are allowed to trade
		{
			clif_displaymessage(sd->fd, msg_txt(246));
			trade_tradecancel(sd); // GM is not allowed to trade
		} else if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) {
			trade_tradecancel(sd); // person is in another trade
		} else {
			//Fixed. Only real GMs can request trade from far away! [Lupus] 
			if (level < lowest_gm_level && (sd->bl.m != target_sd->bl.m ||
			    (sd->bl.x - target_sd->bl.x <= -5 || sd->bl.x - target_sd->bl.x >= 5) ||
			    (sd->bl.y - target_sd->bl.y <= -5 || sd->bl.y - target_sd->bl.y >= 5))) {
				clif_tradestart(sd, 0); // too far
			} else if (sd != target_sd) {
				target_sd->trade_partner = sd->status.account_id;
				sd->trade_partner = target_sd->status.account_id;
				clif_traderequest(target_sd, sd->status.name);
			}
		}
	} else {
		clif_tradestart(sd, 1); // character does not exist
	}
}
Ejemplo n.º 19
0
unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount)
{
	if( sd->state.secure_items )
	{
		clif_displaymessage(sd->fd, "You can't attach. Blocked with @security");
		return 1;
	}

	if( battle_config.super_woe_enable )
	{
		clif_displaymessage(sd->fd, "Super WoE don't allow send items/zeny with attachments");
		return 1;
	}
	
	if( idx == 0 )
	{ // Zeny Transfer
		if( amount < 0 || !pc_can_give_items(pc_isGM(sd)) )
			return 1;

		if( amount > sd->status.zeny )
			amount = sd->status.zeny;

		sd->mail.zeny = amount;
		// pc_onstatuschanged(sd, SP_ZENY);
		return 0;
	}
	else
	{ // Item Transfer
		idx -= 2;
		mail_removeitem(sd, 0);

		if( idx < 0 || idx >= MAX_INVENTORY )
			return 1;
		if( amount < 0 || amount > sd->status.inventory[idx].amount )
			return 1;
		if( !pc_candrop(sd, &sd->status.inventory[idx]) )
			return 1;

		sd->mail.index = idx;
		sd->mail.nameid = sd->status.inventory[idx].nameid;
		sd->mail.amount = amount;
		
		return 0;
	}
}
Ejemplo n.º 20
0
/**
 * Player attempt tp open his storage.
 * @param sd : player
 * @return 0 : success, 1 : fail
 */
int storage_storageopen(struct map_session_data *sd)
{
	nullpo_ret(sd);

	if (sd->state.storage_flag)
		return 1; //Already open?

	if (!pc_can_give_items(sd)) { //Check is this GM level is allowed to put items to storage
		clif_displaymessage(sd->fd, msg_txt(246));
		return 1;
	}

	sd->state.storage_flag = 1;
	storage_sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
	clif_storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
	clif_updatestorageamount(sd, sd->status.storage.storage_amount, sd->storage_size);
	return 0;
}
Ejemplo n.º 21
0
/*==========================================
 * Opens a storage. Returns:
 * 0 - success
 * 1 - fail
 *------------------------------------------*/
int storage_storageopen(struct map_session_data *sd)
{
	nullpo_retr(0, sd);

	if(sd->state.storage_flag)
		return 1; //Already open?
	
	if( !pc_can_give_items(pc_isGM(sd)) )
  	{ //check is this GM level is allowed to put items to storage
		clif_displaymessage(sd->fd, msg_txt(246));
		return 1;
	}
	
	sd->state.storage_flag = 1;
	clif_storagelist(sd,&sd->status.storage);
	clif_updatestorageamount(sd,sd->status.storage.storage_amount);
	return 0;
}
Ejemplo n.º 22
0
/**
 * Player attempt tp open his storage.
 * @param sd : player
 * @return  0:success, 1:fail
 */
int storage_storageopen(struct map_session_data *sd)
{
	nullpo_ret(sd);

	if(sd->state.storage_flag)
		return 1; //Already open?

	if( !pc_can_give_items(sd) ) { // check is this GM level is allowed to put items to storage
		clif_displaymessage(sd->fd, msg_txt(sd,246));
		return 1;
	}

	sd->state.storage_flag = 1;
	storage_sortitem(sd->storage.u.items_storage, sd->storage.max_amount);
	clif_storagelist(sd, sd->storage.u.items_storage, sd->storage.max_amount, storage_getName(0));
	clif_updatestorageamount(sd, sd->storage.amount, sd->storage.max_amount);

	return 0;
}
Ejemplo n.º 23
0
int ext_storage_open(struct map_session_data *sd)
{
	nullpo_ret(sd);

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

	if( !pc_can_give_items(pc_isGM(sd)) )
  	{ //check is this GM level is allowed to put items to storage
		clif_displaymessage(sd->fd, msg_txt(246));
		return 1;
	}

	sd->state.storage_flag = 3;
	storage_sortitem(sd->status.ext_storage.items, ARRAYLENGTH(sd->status.ext_storage.items));
	clif_storagelist(sd, sd->status.ext_storage.items, ARRAYLENGTH(sd->status.ext_storage.items));
	clif_updateextrastorageamount(sd,sd->status.ext_storage.storage_amount);
	return 0;
}
Ejemplo n.º 24
0
/**
 * Start transaction
 * @param sd Player/Seller
 * @param account_id Buyer account ID
 * @param *itemlist List of sold items { <index>.W, <nameid>.W, <amount>.W }*
 * @param count Number of item on the itemlist
 */
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;

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

	// Not online, not buying or not same store
	if( (pl_sd = map_id2sd(account_id)) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id ) {
		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 || (sd->status.inventory[index].bound && !pc_can_give_bounded_items(sd)) ||
			!itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(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);
		// There is no such item or the buyer has already bought all of them
		if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 ) {
			clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
			return;
		}

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

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

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

		weight += amount * sd->inventory_data[index]->weight;

		// Buyer does not have enough zeny
		if( amount * pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit - 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;

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

		if( pl_sd->buyingstore.items[listidx].amount > 0 ) {
			if( Sql_Query(mmysql_handle, "UPDATE `%s` SET `amount` = %d WHERE `buyingstore_id` = %d AND `index` = %d;",
				buyingstore_items_db, pl_sd->buyingstore.items[listidx].amount, pl_sd->buyer_id, listidx) != SQL_SUCCESS )
				Sql_ShowDebug(mmysql_handle);
		} else {
			if( Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `buyingstore_id` = %d AND `index` = %d;",
				buyingstore_items_db, pl_sd->buyer_id, listidx) != SQL_SUCCESS )
				Sql_ShowDebug(mmysql_handle);
		}

		// Pay up
		pc_payzeny(pl_sd, zeny, LOG_TYPE_BUYING_STORE, sd);
		pc_getzeny(sd, zeny, LOG_TYPE_BUYING_STORE, pl_sd);
		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);
	}

	if( save_settings&128 ) {
		chrif_save(sd, 0);
		chrif_save(pl_sd, 0);
	}

	// 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
		if( Sql_Query(mmysql_handle, "UPDATE `%s` SET `limit` = %d WHERE `id` = %d;",
			buyingstores_db, pl_sd->buyingstore.zenylimit, pl_sd->buyer_id) != SQL_SUCCESS )
			Sql_ShowDebug(mmysql_handle);
		return;
	}

	// Cannot continue buying
	buyingstore_close(pl_sd);

	// Remove auto-trader
	if( pl_sd->state.autotrade )
		map_quit(pl_sd);
}
Ejemplo n.º 25
0
void 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;
	struct item_data* id;

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

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

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

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

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

	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;

		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_isGM(sd), pc_isGM(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;
	}

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

	// 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));
	clif_buyingstore_myitemlist(sd);
	clif_buyingstore_entry(sd);
}
Ejemplo n.º 26
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_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);
	}
}
Ejemplo n.º 27
0
/// Attaches an item to a message being written
/// @param sd : The player who's writting
/// @param idx : the inventory idx of the item
/// @param amount : Amount of the item to be attached
void rodex_add_item(struct map_session_data *sd, int16 idx, int16 amount)
{
	int i;
	bool is_stack = false;

	nullpo_retv(sd);

	if (idx < 0 || idx >= MAX_INVENTORY) {
		clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_FATAL_ERROR);
		return;
	}

	if (amount < 0 || amount > sd->status.inventory[idx].amount) {
		clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_FATAL_ERROR);
		return;
	}

	if (!pc_can_give_items(sd) || sd->status.inventory[idx].expire_time ||
		!itemdb_canmail(&sd->status.inventory[idx], pc_get_group_level(sd)) ||
		(sd->status.inventory[idx].bound && !pc_can_give_bound_items(sd))) {
		clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_NOT_TRADEABLE);
		return;
	}

	if (itemdb->isstackable(sd->status.inventory[idx].nameid) == 1) {
		for (i = 0; i < RODEX_MAX_ITEM; ++i) {
			if (sd->rodex.tmp.items[i].idx == idx) {
				if (sd->status.inventory[idx].nameid == sd->rodex.tmp.items[i].item.nameid &&
					sd->status.inventory[idx].unique_id == sd->rodex.tmp.items[i].item.unique_id) {
					is_stack = true;
					break;
				}
			}
		}

		if (i == RODEX_MAX_ITEM && sd->rodex.tmp.items_count < RODEX_MAX_ITEM) {
			ARR_FIND(0, RODEX_MAX_ITEM, i, sd->rodex.tmp.items[i].idx == 0);
		}
	} else if (sd->rodex.tmp.items_count < RODEX_MAX_ITEM) {
		ARR_FIND(0, RODEX_MAX_ITEM, i, sd->rodex.tmp.items[i].idx == 0);
	} else {
		i = RODEX_MAX_ITEM;
	}

	if (i == RODEX_MAX_ITEM) {
		clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_NO_SPACE);
		return;
	}

	if (sd->rodex.tmp.items[i].item.amount + amount > sd->status.inventory[idx].amount) {
		clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_FATAL_ERROR);
		return;
	}

	if (sd->rodex.tmp.weight + sd->inventory_data[idx]->weight * amount > RODEX_WEIGHT_LIMIT) {
		clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_FATAL_ERROR);
		return;
	}

	sd->rodex.tmp.items[i].idx = idx;
	sd->rodex.tmp.weight += sd->inventory_data[idx]->weight * amount;
	if (is_stack == false) {
		sd->rodex.tmp.items[i].item = sd->status.inventory[idx];
		sd->rodex.tmp.items[i].item.amount = amount;
		sd->rodex.tmp.items_count++;
	} else {
		sd->rodex.tmp.items[i].item.amount += amount;
	}
	sd->rodex.tmp.type |= MAIL_TYPE_ITEM;

	clif->rodex_add_item_result(sd, idx, amount, RODEX_ADD_ITEM_SUCCESS);
}
Ejemplo n.º 28
0
/**
* Attempt to set item or zeny to a mail
* @param sd : player attaching the content
* @param idx 0 - Zeny; >= 2 - Inventory item
* @param amount : amout of zeny or number of item
* @return see enum mail_attach_result in mail.h
*/
enum mail_attach_result mail_setitem(struct map_session_data *sd, short idx, uint32 amount) {
	if( pc_istrading(sd) )
		return MAIL_ATTACH_ERROR;

	if( idx == 0 ) { // Zeny Transfer
		if( !pc_can_give_items(sd) )
			return MAIL_ATTACH_UNTRADEABLE;

#if PACKETVER < 20150513
		if( amount > sd->status.zeny )
			amount = sd->status.zeny; // TODO: confirm this behavior for old mail system
#else
		if( ( amount + battle_config.mail_zeny_fee / 100 * amount ) > sd->status.zeny )
			return MAIL_ATTACH_ERROR;
#endif

		sd->mail.zeny = amount;
		// clif_updatestatus(sd, SP_ZENY);
		return MAIL_ATTACH_SUCCESS;
	} else { // Item Transfer
		int i, j, total = 0;

		idx -= 2;

		if( idx < 0 || idx >= MAX_INVENTORY )
			return MAIL_ATTACH_ERROR;

#if PACKETVER < 20150513
		i = 0;
		// Remove existing item
		mail_removeitem(sd, 0, sd->mail.item[i].index + 2, sd->mail.item[i].amount);
#else
		ARR_FIND(0, MAIL_MAX_ITEM, i, sd->mail.item[i].index == idx && sd->mail.item[i].nameid > 0 );
		
		// The same item had already been added to the mail
		if( i < MAIL_MAX_ITEM ){
			// Check if it is stackable
			if( !itemdb_isstackable(sd->mail.item[i].nameid) ){
				return MAIL_ATTACH_ERROR;
			}

			// Check if it exceeds the total amount
			if( ( amount + sd->mail.item[i].amount ) > sd->inventory.u.items_inventory[idx].amount ){
				return MAIL_ATTACH_ERROR;
			}

			// Check if it exceeds the total weight
			if( battle_config.mail_attachment_weight ){
				for( j = 0; j < i; j++ ){
					total += sd->mail.item[j].amount * ( sd->inventory_data[sd->mail.item[j].index]->weight / 10 );
				}

				total += amount * sd->inventory_data[idx]->weight / 10;

				if( total > battle_config.mail_attachment_weight ){
					return MAIL_ATTACH_WEIGHT;
				}
			}

			sd->mail.item[i].amount += amount;

			return MAIL_ATTACH_SUCCESS;
		}else{
			ARR_FIND(0, MAIL_MAX_ITEM, i, sd->mail.item[i].nameid == 0);

			if( i == MAIL_MAX_ITEM ){
				return MAIL_ATTACH_SPACE;
			}

			// Check if it exceeds the total weight
			if( battle_config.mail_attachment_weight ){
				for( j = 0; j < i; j++ ){
					total += sd->mail.item[j].amount * ( sd->inventory_data[sd->mail.item[j].index]->weight / 10 );
				}

				total += amount * sd->inventory_data[idx]->weight / 10;

				if( total > battle_config.mail_attachment_weight ){
					return MAIL_ATTACH_WEIGHT;
				}
			}
		}
#endif

		if( amount > sd->inventory.u.items_inventory[idx].amount )
			return MAIL_ATTACH_ERROR;
		if( !pc_can_give_items(sd) || sd->inventory.u.items_inventory[idx].expire_time
			|| !itemdb_available(sd->inventory.u.items_inventory[idx].nameid)
			|| !itemdb_canmail(&sd->inventory.u.items_inventory[idx],pc_get_group_level(sd))
			|| (sd->inventory.u.items_inventory[idx].bound && !pc_can_give_bounded_items(sd)) )
			return MAIL_ATTACH_UNTRADEABLE;

		sd->mail.item[i].index = idx;
		sd->mail.item[i].nameid = sd->inventory.u.items_inventory[idx].nameid;
		sd->mail.item[i].amount = amount;
		return MAIL_ATTACH_SUCCESS;
	}
}
Ejemplo n.º 29
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;
}