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)) ) return 1; sd->mail.index = idx; sd->mail.nameid = sd->status.inventory[idx].nameid; sd->mail.amount = amount; return 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; } }
bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg) { int n; nullpo_retr(false,sd); nullpo_retr(false,msg); if( sd->mail.zeny < 0 || sd->mail.zeny > sd->status.zeny ) return false; n = sd->mail.index; if( sd->mail.amount ) { if( sd->status.inventory[n].nameid != sd->mail.nameid ) return false; if( sd->status.inventory[n].amount < sd->mail.amount ) return false; memcpy(&msg->item, &sd->status.inventory[n], sizeof(struct item)); msg->item.amount = sd->mail.amount; } else memset(&msg->item, 0x00, sizeof(struct item)); msg->zeny = sd->mail.zeny; // Removes the attachment from sender mail_removeitem(sd,1); mail_removezeny(sd,1); return true; }
/** * 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; } }
bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg) { int i, amount; nullpo_retr(false,sd); nullpo_retr(false,msg); for( i = 0, amount = 0; i < MAIL_MAX_ITEM; i++ ){ int index = sd->mail.item[i].index; if( sd->mail.item[i].nameid == 0 || sd->mail.item[i].amount == 0 ){ memset(&msg->item[i], 0x00, sizeof(struct item)); continue; } amount++; if( sd->inventory.u.items_inventory[index].nameid != sd->mail.item[i].nameid ) return false; if( sd->inventory.u.items_inventory[index].amount < sd->mail.item[i].amount ) return false; if( sd->weight > sd->max_weight ) // TODO: Why check something weird like this here? return false; memcpy(&msg->item[i], &sd->inventory.u.items_inventory[index], sizeof(struct item)); msg->item[i].amount = sd->mail.item[i].amount; } if( sd->mail.zeny < 0 || ( sd->mail.zeny + sd->mail.zeny * battle_config.mail_zeny_fee / 100 + amount * battle_config.mail_attachment_price ) > sd->status.zeny ) return false; msg->zeny = sd->mail.zeny; // Removes the attachment from sender for( i = 0; i < MAIL_MAX_ITEM; i++ ){ if( sd->mail.item[i].nameid == 0 || sd->mail.item[i].amount == 0 ){ // Exit the loop on the first empty entry break; } mail_removeitem(sd,1,sd->mail.item[i].index + 2,sd->mail.item[i].amount); } mail_removezeny(sd,true); return true; }
/** * 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; } }
/** * Attempt to send mail * @param sd Sender * @param dest_name Destination name * @param title Mail title * @param body_msg Mail message * @param body_len Message's length */ void mail_send(struct map_session_data *sd, const char *dest_name, const char *title, const char *body_msg, int body_len) { struct mail_message msg; nullpo_retv(sd); if( sd->state.trading ) return; if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 ) { clif_displaymessage(sd->fd,msg_txt(sd,675)); //"Cannot send mails too fast!!." clif_Mail_send(sd->fd, true); // fail return; } if( body_len > MAIL_BODY_LENGTH ) body_len = MAIL_BODY_LENGTH; if( !mail_setattachment(sd, &msg) ) { // Invalid Append condition clif_Mail_send(sd->fd, true); // fail mail_removeitem(sd,0); mail_removezeny(sd,0); return; } msg.id = 0; // id will be assigned by charserver msg.send_id = sd->status.char_id; msg.dest_id = 0; // will attempt to resolve name safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH); safestrncpy(msg.dest_name, (char*)dest_name, NAME_LENGTH); safestrncpy(msg.title, (char*)title, MAIL_TITLE_LENGTH); if (msg.title[0] == '\0') { return; // Message has no length and somehow client verification was skipped. } if (body_len) safestrncpy(msg.body, (char*)body_msg, body_len + 1); else memset(msg.body, 0x00, MAIL_BODY_LENGTH); msg.timestamp = time(NULL); if( !intif_Mail_send(sd->status.account_id, &msg) ) mail_deliveryfail(sd, &msg); sd->cansendmail_tick = gettick() + battle_config.mail_delay; // Flood Protection }
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; } }
/** * Attempt to send mail * @param sd Sender * @param dest_name Destination name * @param title Mail title * @param body_msg Mail message * @param body_len Message's length */ void mail_send(struct map_session_data *sd, const char *dest_name, const char *title, const char *body_msg, int body_len) { struct mail_message msg; nullpo_retv(sd); if( sd->state.trading ) return; if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 ) { clif_displaymessage(sd->fd,msg_txt(sd,675)); //"Cannot send mails too fast!!." clif_Mail_send(sd, WRITE_MAIL_FAILED); // fail return; } if( battle_config.mail_daily_count ){ mail_refresh_remaining_amount(sd); // After calling mail_refresh_remaining_amount the status should always be there if( sd->sc.data[SC_DAILYSENDMAILCNT] == NULL || sd->sc.data[SC_DAILYSENDMAILCNT]->val2 >= battle_config.mail_daily_count ){ clif_Mail_send(sd, WRITE_MAIL_FAILED_CNT); return; }else{ sc_start2( &sd->bl, &sd->bl, SC_DAILYSENDMAILCNT, 100, date_get_dayofyear(), sd->sc.data[SC_DAILYSENDMAILCNT]->val2 + 1, -1 ); } } if( body_len > MAIL_BODY_LENGTH ) body_len = MAIL_BODY_LENGTH; if( !mail_setattachment(sd, &msg) ) { // Invalid Append condition int i; clif_Mail_send(sd, WRITE_MAIL_FAILED); // fail for( i = 0; i < MAIL_MAX_ITEM; i++ ){ mail_removeitem(sd,0,sd->mail.item[i].index + 2, sd->mail.item[i].amount); } mail_removezeny(sd,false); return; } msg.id = 0; // id will be assigned by charserver msg.send_id = sd->status.char_id; msg.dest_id = 0; // will attempt to resolve name safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH); safestrncpy(msg.dest_name, (char*)dest_name, NAME_LENGTH); safestrncpy(msg.title, (char*)title, MAIL_TITLE_LENGTH); msg.type = MAIL_INBOX_NORMAL; if (msg.title[0] == '\0') { return; // Message has no length and somehow client verification was skipped. } if (body_len) safestrncpy(msg.body, (char*)body_msg, body_len + 1); else memset(msg.body, 0x00, MAIL_BODY_LENGTH); msg.timestamp = time(NULL); if( !intif_Mail_send(sd->status.account_id, &msg) ) mail_deliveryfail(sd, &msg); sd->cansendmail_tick = gettick() + battle_config.mail_delay; // Flood Protection }
/** * 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; } }