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); }
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_TYPE_MAIL); clif_Mail_getattachment(sd->fd, 0); } if( zeny > 0 ) { //Zeny recieve log_zeny(sd, LOG_TYPE_MAIL, sd, zeny); pc_getzeny(sd, zeny); } }
int mail_removezeny(struct map_session_data *sd, short flag) { nullpo_ret(sd); if (flag && sd->mail.zeny > 0) { //Zeny send log_zeny(sd, LOG_TYPE_MAIL, sd, -sd->mail.zeny); sd->status.zeny -= sd->mail.zeny; } sd->mail.zeny = 0; pc_onstatuschanged(sd, SP_ZENY); return 1; }
int mail_removezeny(struct map_session_data *sd, short flag) { nullpo_retr(0,sd); if (flag && sd->mail.zeny > 0) { //Zeny send if(log_config.zeny) log_zeny(sd, "E", sd, -sd->mail.zeny); sd->status.zeny -= sd->mail.zeny; } sd->mail.zeny = 0; clif_updatestatus(sd, SP_ZENY); return 1; }
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); } }
void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg) { nullpo_retv(sd); nullpo_retv(msg); if( msg->item.amount > 0 ) pc_additem(sd, &msg->item, msg->item.amount, LOG_TYPE_MAIL); if( msg->zeny > 0 ) { //Zeny recieve (due to failure) log_zeny(sd, LOG_TYPE_MAIL, sd, msg->zeny); sd->status.zeny += msg->zeny; pc_onstatuschanged(sd, SP_ZENY); } clif_Mail_send(sd->fd, true); }
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); }
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); } }
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); }
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); } }
/*========================================== * 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? } } }
/*========================================== * lock sd and tsd trade data, execute the trade, clear, then save players *------------------------------------------*/ 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,LOG_TYPE_TRADE); if (flag == 0) pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); 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,LOG_TYPE_TRADE); if (flag == 0) pc_delitem(tsd, n, tsd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); 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_zeny(tsd, LOG_TYPE_TRADE, sd, sd->deal.zeny); if( tsd->deal.zeny ) log_zeny(sd, LOG_TYPE_TRADE, 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); } }
/*========================================== * 取引許諾(trade押し) *------------------------------------------ */ void trade_tradecommit(struct map_session_data *sd) { struct map_session_data *target_sd; int trade_i; int flag; nullpo_retv(sd); if (sd->state.trading && (target_sd = map_id2sd(sd->trade_partner)) != NULL) { if ((sd->state.deal_locked >= 1) && (target_sd->state.deal_locked >= 1)) { // both have pressed 'ok' if (sd->state.deal_locked < 2) { // set locked to 2 sd->state.deal_locked = 2; } if (target_sd->state.deal_locked == 2) { // the other one pressed 'trade' too // check exploit (trade more items that you have) if (impossible_trade_check(sd)) { trade_tradecancel(sd); return; } // check exploit (trade more items that you have) if (impossible_trade_check(target_sd)) { trade_tradecancel(target_sd); return; } // check zenys value against hackers if (sd->deal.zeny >= 0 && sd->deal.zeny <= MAX_ZENY && sd->deal.zeny <= sd->status.zeny && // check amount (target_sd->status.zeny + sd->deal.zeny) <= MAX_ZENY && // fix positiv overflow target_sd->deal.zeny >= 0 && target_sd->deal.zeny <= MAX_ZENY && target_sd->deal.zeny <= target_sd->status.zeny && // check amount (sd->status.zeny + target_sd->deal.zeny) <= MAX_ZENY) { // fix positiv overflow // check for full inventory (can not add traded items) if (!trade_check(sd)) { // check the both players trade_tradecancel(sd); return; } // trade is accepted for(trade_i = 0; trade_i < 10; trade_i++) { if (sd->deal.item[trade_i].amount != 0) { int n = sd->deal.item[trade_i].index; if (sd->status.inventory[n].amount < sd->deal.item[trade_i].amount) sd->deal.item[trade_i].amount = sd->status.inventory[n].amount; log_trade(sd, target_sd, n, sd->deal.item[trade_i].amount); flag = pc_additem(target_sd, &sd->status.inventory[n], sd->deal.item[trade_i].amount); if (flag == 0) { //Logs (T)rade [Lupus] if(log_config.pick > 0 ) log_pick(sd, "T", 0, sd->status.inventory[n].nameid, -(sd->deal.item[trade_i].amount), &sd->status.inventory[n]); log_pick(target_sd, "T", 0, sd->status.inventory[n].nameid, sd->deal.item[trade_i].amount, &sd->status.inventory[n]); //Logs pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1); } else { clif_additem(sd, n, sd->deal.item[trade_i].amount, 0); } sd->deal.item[trade_i].index = 0; sd->deal.item[trade_i].amount = 0; } if (target_sd->deal.item[trade_i].amount != 0) { int n = target_sd->deal.item[trade_i].index; if (target_sd->status.inventory[n].amount < target_sd->deal.item[trade_i].amount) target_sd->deal.item[trade_i].amount = target_sd->status.inventory[n].amount; log_trade(target_sd, sd, n, target_sd->deal.item[trade_i].amount); flag = pc_additem(sd, &target_sd->status.inventory[n], target_sd->deal.item[trade_i].amount); if (flag == 0) { //Logs (T)rade [Lupus] if(log_config.pick > 0 ) log_pick(target_sd, "T", 0, target_sd->status.inventory[n].nameid, -(target_sd->deal.item[trade_i].amount), &target_sd->status.inventory[n]); log_pick(sd, "T", 0, target_sd->status.inventory[n].nameid, target_sd->deal.item[trade_i].amount, &target_sd->status.inventory[n]); //Logs pc_delitem(target_sd, n, target_sd->deal.item[trade_i].amount, 1); } else { clif_additem(target_sd, n, target_sd->deal.item[trade_i].amount, 0); } target_sd->deal.item[trade_i].index = 0; target_sd->deal.item[trade_i].amount = 0; } } if (sd->deal.zeny) { //Logs Zeny (T)rade [Lupus] if(log_config.zeny > 0 ) log_zeny(target_sd, "T", sd, sd->deal.zeny); //Logs sd->status.zeny -= sd->deal.zeny; target_sd->status.zeny += sd->deal.zeny; } if (target_sd->deal.zeny) { //Logs Zeny (T)rade [Lupus] if(log_config.zeny > 0 ) log_zeny(sd, "T", target_sd, target_sd->deal.zeny); //Logs target_sd->status.zeny -= target_sd->deal.zeny; sd->status.zeny += target_sd->deal.zeny; } if (sd->deal.zeny || target_sd->deal.zeny) { clif_updatestatus(sd, SP_ZENY); sd->deal.zeny = 0; clif_updatestatus(target_sd, SP_ZENY); target_sd->deal.zeny = 0; } sd->state.deal_locked = 0; sd->trade_partner = 0; sd->state.trading = 0; target_sd->state.deal_locked = 0; target_sd->trade_partner = 0; target_sd->state.trading = 0; clif_tradecompleted(sd, 0); clif_tradecompleted(target_sd, 0); // save both player to avoid crash: they always have no advantage/disadvantage between the 2 players chrif_save(sd,0); // do pc_makesavestatus and save storage too chrif_save(target_sd,0); // do pc_makesavestatus and save storage too // zeny value was modified!!!! hacker with packet modified } else { trade_tradecancel(sd); } } } } }