diff options
Diffstat (limited to 'src/map/trade.c')
-rw-r--r-- | src/map/trade.c | 87 |
1 files changed, 52 insertions, 35 deletions
diff --git a/src/map/trade.c b/src/map/trade.c index 6352c3a4d..e727c3c70 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -2,8 +2,8 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team - * Copyright (C) Athena Dev Teams + * Copyright (C) 2012-2020 Hercules Dev Team + * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,19 +40,22 @@ #include <stdio.h> #include <string.h> -struct trade_interface trade_s; +static struct trade_interface trade_s; struct trade_interface *trade; /*========================================== * Initiates a trade request. *------------------------------------------*/ -void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd) +static void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd) { nullpo_retv(sd); + if (sd == target_sd) + return; + if (map->list[sd->bl.m].flag.notrade) { - clif->message (sd->fd, msg_sd(sd,272)); - return; //Can't trade in notrade mapflag maps. + clif->message (sd->fd, msg_sd(sd,272)); // You can't trade in this map + return; } if (target_sd == NULL || sd == target_sd) { @@ -90,7 +93,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) //check if both GMs are allowed to trade { - clif->message(sd->fd, msg_sd(sd,246)); + clif->message(sd->fd, msg_sd(sd,246)); // Your GM level doesn't authorize you to perform this action. clif->tradestart(sd, 2); // GM is not allowed to trade return; } @@ -118,7 +121,8 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta * Weird enough, the client should only send 3/4 * and the server is the one that can reply 0~2 *------------------------------------------*/ -void trade_tradeack(struct map_session_data *sd, int type) { +static void trade_tradeack(struct map_session_data *sd, int type) +{ struct map_session_data *tsd; nullpo_retv(sd); @@ -162,8 +166,8 @@ void trade_tradeack(struct map_session_data *sd, int type) { } //Check if you can start trade. - if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag != STORAGE_FLAG_CLOSED - || tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag != STORAGE_FLAG_CLOSED + if (sd->npc_id || sd->state.vending || sd->state.prevend || sd->state.buyingstore || sd->state.storage_flag != STORAGE_FLAG_CLOSED + || tsd->npc_id || tsd->state.vending || tsd->state.prevend || tsd->state.buyingstore || tsd->state.storage_flag != STORAGE_FLAG_CLOSED ) { //Fail clif->tradestart(sd, 2); @@ -191,7 +195,7 @@ void trade_tradeack(struct map_session_data *sd, int type) { * @retval 0 The trade can continue * @retval 1 Hack attempt **/ -int impossible_trade_check(struct map_session_data *sd) +static int impossible_trade_check(struct map_session_data *sd) { struct item inventory[MAX_INVENTORY]; char message_to_gm[200]; @@ -208,7 +212,7 @@ int impossible_trade_check(struct map_session_data *sd) // remove this part: arrows can be trade and equipped // re-added! [celest] // remove equipped items (they can not be trade) - for (i = 0; i < MAX_INVENTORY; i++) + for (i = 0; i < sd->status.inventorySize; i++) if (inventory[i].nameid > 0 && inventory[i].equip && !(inventory[i].equip & EQP_AMMO)) memset(&inventory[i], 0, sizeof(struct item)); @@ -217,12 +221,14 @@ int impossible_trade_check(struct map_session_data *sd) if (!sd->deal.item[i].amount) continue; index = sd->deal.item[i].index; + if (index < 0 || index >= sd->status.inventorySize) + return 1; if (inventory[index].amount < sd->deal.item[i].amount) { // if more than the player have -> hack snprintf(message_to_gm, sizeof(message_to_gm), msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has. - intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); + pc->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); snprintf(message_to_gm, sizeof(message_to_gm), msg_txt(539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them. - intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); + pc->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); // if we block people if (battle_config.ban_hack_trade < 0) { chrif->char_ask_name(-1, sd->status.name, CHAR_ASK_NAME_BLOCK, 0, 0, 0, 0, 0, 0); @@ -239,7 +245,7 @@ int impossible_trade_check(struct map_session_data *sd) // message about the ban safestrncpy(message_to_gm, msg_txt(508), sizeof(message_to_gm)); // This player hasn't been banned (Ban option is disabled). - intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); + pc->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); return 1; } inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory @@ -250,13 +256,15 @@ int impossible_trade_check(struct map_session_data *sd) /*========================================== * Checks if trade is possible (against zeny limits, inventory limits, etc) *------------------------------------------*/ -int trade_check(struct map_session_data *sd, struct map_session_data *tsd) +static int trade_check(struct map_session_data *sd, struct map_session_data *tsd) { struct item inventory[MAX_INVENTORY]; struct item inventory2[MAX_INVENTORY]; struct item_data *data; int trade_i, i, n; + nullpo_ret(sd); + nullpo_ret(tsd); // check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then. if(sd->deal.zeny > sd->status.zeny || (tsd->status.zeny > MAX_ZENY - sd->deal.zeny)) return 0; @@ -276,9 +284,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) return 0; //qty Exploit? data = itemdb->search(inventory[n].nameid); - i = MAX_INVENTORY; + i = tsd->status.inventorySize; if (itemdb->isstackable2(data)) { //Stackable item. - for(i = 0; i < MAX_INVENTORY; i++) + for(i = 0; i < tsd->status.inventorySize; i++) if (inventory2[i].nameid == inventory[n].nameid && inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] && inventory2[i].card[2] == inventory[n].card[2] && inventory2[i].card[3] == inventory[n].card[3]) { @@ -290,9 +298,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) } } - if (i == MAX_INVENTORY) {// look for an empty slot. - for(i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++); - if (i == MAX_INVENTORY) + if (i == tsd->status.inventorySize) {// look for an empty slot. + for (i = 0; i < tsd->status.inventorySize && inventory2[i].nameid; i++); + if (i == tsd->status.inventorySize) return 0; memcpy(&inventory2[i], &inventory[n], sizeof(struct item)); inventory2[i].amount = amount; @@ -303,13 +311,15 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) if (!amount) continue; n = tsd->deal.item[trade_i].index; + if (n < 0 || n >= tsd->status.inventorySize) + return 0; if (amount > inventory2[n].amount) return 0; // search if it's possible to add item (for full inventory) data = itemdb->search(inventory2[n].nameid); - i = MAX_INVENTORY; + i = sd->status.inventorySize; if (itemdb->isstackable2(data)) { - for(i = 0; i < MAX_INVENTORY; i++) + for(i = 0; i < sd->status.inventorySize; i++) if (inventory[i].nameid == inventory2[n].nameid && inventory[i].card[0] == inventory2[n].card[0] && inventory[i].card[1] == inventory2[n].card[1] && inventory[i].card[2] == inventory2[n].card[2] && inventory[i].card[3] == inventory2[n].card[3]) { @@ -320,9 +330,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) break; } } - if (i == MAX_INVENTORY) { - for(i = 0; i < MAX_INVENTORY && inventory[i].nameid; i++); - if (i == MAX_INVENTORY) + if (i == sd->status.inventorySize) { + for(i = 0; i < sd->status.inventorySize && inventory[i].nameid; i++); + if (i == sd->status.inventorySize) return 0; memcpy(&inventory[i], &inventory2[n], sizeof(struct item)); inventory[i].amount = amount; @@ -336,7 +346,8 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) /*========================================== * Adds an item/qty to the trade window *------------------------------------------*/ -void trade_tradeadditem(struct map_session_data *sd, short index, short amount) { +static void trade_tradeadditem(struct map_session_data *sd, short index, short amount) +{ struct map_session_data *target_sd; struct item *item; int trade_i, trade_weight; @@ -361,7 +372,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) index -= 2; // 0 is for zeny, 1 is unknown. Gravity, go figure... //Item checks... - if( index < 0 || index >= MAX_INVENTORY ) + if (index < 0 || index >= sd->status.inventorySize) return; if( amount < 0 || amount > sd->status.inventory[index].amount ) return; @@ -372,14 +383,14 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) if( !itemdb_cantrade(item, src_lv, dst_lv) && //Can't trade (pc->get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) //Can't partner-trade { - clif->message (sd->fd, msg_sd(sd,260)); + clif->message (sd->fd, msg_sd(sd,260)); // This item cannot be traded. clif->tradeitemok(sd, index+2, TIO_INDROCKS); return; } if( item->expire_time ) { // Rental System - clif->message (sd->fd, msg_sd(sd,260)); + clif->message (sd->fd, msg_sd(sd,260)); // This item cannot be traded. clif->tradeitemok(sd, index+2, TIO_INDROCKS); return; } @@ -388,7 +399,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) !( item->bound == IBT_GUILD && sd->status.guild_id == target_sd->status.guild_id ) && !( item->bound == IBT_PARTY && sd->status.party_id == target_sd->status.party_id ) && !pc_can_give_bound_items(sd) ) { - clif->message(sd->fd, msg_sd(sd,293)); + clif->message(sd->fd, msg_sd(sd,293)); // This bound item cannot be traded to that character. clif->tradeitemok(sd, index+2, TIO_INDROCKS); return; } @@ -430,7 +441,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) /*========================================== * Adds the specified amount of zeny to the trade window *------------------------------------------*/ -void trade_tradeaddzeny(struct map_session_data* sd, int amount) +static void trade_tradeaddzeny(struct map_session_data *sd, int amount) { struct map_session_data* target_sd; nullpo_retv(sd); @@ -456,9 +467,11 @@ void trade_tradeaddzeny(struct map_session_data* sd, int amount) /*========================================== * 'Ok' button on the trade window is pressed. *------------------------------------------*/ -void trade_tradeok(struct map_session_data *sd) { +static void trade_tradeok(struct map_session_data *sd) +{ struct map_session_data *target_sd; + nullpo_retv(sd); if(sd->state.deal_locked || !sd->state.trading) return; @@ -475,10 +488,12 @@ void trade_tradeok(struct map_session_data *sd) { /*========================================== * 'Cancel' is pressed. (or trade was force-canceled by the code) *------------------------------------------*/ -void trade_tradecancel(struct map_session_data *sd) { +static void trade_tradecancel(struct map_session_data *sd) +{ struct map_session_data *target_sd; int trade_i; + nullpo_retv(sd); target_sd = map->id2sd(sd->trade_partner); if(!sd->state.trading) @@ -533,11 +548,13 @@ void trade_tradecancel(struct map_session_data *sd) { /*========================================== * lock sd and tsd trade data, execute the trade, clear, then save players *------------------------------------------*/ -void trade_tradecommit(struct map_session_data *sd) { +static void trade_tradecommit(struct map_session_data *sd) +{ struct map_session_data *tsd; int trade_i; int flag; + nullpo_retv(sd); if (!sd->state.trading || !sd->state.deal_locked) //Locked should be 1 (pressed ok) before you can press trade. return; |