diff --git a/src/map/clif.cpp b/src/map/clif.cpp index a34d9a8113..c118718f4a 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -56,7 +56,6 @@ #include "skill.hpp" #include "status.hpp" #include "storage.hpp" -#include "trade.hpp" #include "unit.hpp" #include "vending.hpp" @@ -4646,33 +4645,27 @@ void clif_leavechat(struct chat_data* cd, map_session_data* sd, bool flag) /// Opens a trade request window from char 'name'. /// 00e5 .24B (ZC_REQ_EXCHANGE_ITEM) -/// 01f4 .24B .L .W (ZC_REQ_EXCHANGE_ITEM2) -void clif_traderequest(map_session_data* sd, const char* name) -{ - int fd = sd->fd; +/// 01f4 .24B .L .W (ZC_REQ_EXCHANGE_ITEM2) +void clif_traderequest(map_session_data& sd, const char* name){ -#if PACKETVER < 6 - WFIFOHEAD(fd,packet_len(0xe5)); - WFIFOW(fd,0) = 0xe5; - safestrncpy(WFIFOCP(fd,2), name, NAME_LENGTH); - WFIFOSET(fd,packet_len(0xe5)); -#else - map_session_data* tsd = map_id2sd(sd->trade_partner); - if( !tsd ) return; + PACKET_ZC_REQ_EXCHANGE_ITEM p{}; - WFIFOHEAD(fd,packet_len(0x1f4)); - WFIFOW(fd,0) = 0x1f4; - safestrncpy(WFIFOCP(fd,2), name, NAME_LENGTH); - WFIFOL(fd,26) = tsd->status.char_id; - WFIFOW(fd,30) = tsd->status.base_level; - WFIFOSET(fd,packet_len(0x1f4)); + p.packetType = HEADER_ZC_REQ_EXCHANGE_ITEM; + safestrncpy(p.requesterName, name, sizeof(p.requesterName)); + +#if PACKETVER > 6 + p.targetId = sd.trade_partner.id; // Client generates a random char[5] with this info + p.targetLv = sd.trade_partner.lv; #endif + + clif_send(&p,sizeof(p),&sd.bl,SELF); + } /// Reply to a trade-request. /// 00e7 .B (ZC_ACK_EXCHANGE_ITEM) -/// 01f5 .B .L .W (ZC_ACK_EXCHANGE_ITEM2) +/// 01f5 .B .L .W (ZC_ACK_EXCHANGE_ITEM2) /// result: /// 0 = Char is too far /// 1 = Character does not exist @@ -4680,23 +4673,19 @@ void clif_traderequest(map_session_data* sd, const char* name) /// 3 = Accept /// 4 = Cancel /// 5 = Busy -void clif_tradestart(map_session_data* sd, uint8 type) -{ - int fd = sd->fd; - map_session_data* tsd = map_id2sd(sd->trade_partner); - if( PACKETVER < 6 || !tsd ) { - WFIFOHEAD(fd,packet_len(0xe7)); - WFIFOW(fd,0) = 0xe7; - WFIFOB(fd,2) = type; - WFIFOSET(fd,packet_len(0xe7)); - } else { - WFIFOHEAD(fd,packet_len(0x1f5)); - WFIFOW(fd,0) = 0x1f5; - WFIFOB(fd,2) = type; - WFIFOL(fd,3) = tsd->status.char_id; - WFIFOW(fd,7) = tsd->status.base_level; - WFIFOSET(fd,packet_len(0x1f5)); - } +void clif_traderesponse( map_session_data& sd, e_ack_trade_response result ){ + + PACKET_ZC_ACK_EXCHANGE_ITEM p{}; + + p.packetType = HEADER_ZC_ACK_EXCHANGE_ITEM; + p.result = static_cast( result ); + +#if PACKETVER > 6 + p.targetId = sd.trade_partner.id; // Client generates a random char[5] with this info + p.targetLv = sd.trade_partner.lv; +#endif + + clif_send(&p,sizeof(p),&sd.bl,SELF); } @@ -12338,13 +12327,8 @@ void clif_parse_TradeRequest(int fd,map_session_data *sd) } if (t_sd->state.mail_writing) { - int old = sd->trade_partner; - // Fake trading - sd->trade_partner = t_sd->status.account_id; - clif_tradestart(sd, 5); - // Restore old state - sd->trade_partner = old; + clif_traderesponse(*sd,TRADE_ACK_BUSY); return; } @@ -16191,7 +16175,7 @@ void clif_parse_Mail_beginwrite( int fd, map_session_data *sd ){ return; } - if( sd->state.storage_flag || sd->state.mail_writing || sd->trade_partner ){ + if( sd->state.storage_flag || sd->state.mail_writing || sd->state.trading ){ clif_send_Mail_beginwrite_ack(sd, name, false); return; } diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 3a2bc89f66..951c884612 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -14,6 +14,7 @@ #include "packets.hpp" #include "script.hpp" +#include "trade.hpp" struct Channel; struct clan; @@ -905,8 +906,8 @@ void clif_parse_LoadEndAck(int fd,map_session_data *sd); void clif_hotkeys_send(map_session_data *sd, int tab); // trade -void clif_traderequest(map_session_data* sd, const char* name); -void clif_tradestart(map_session_data* sd, uint8 type); +void clif_traderequest(map_session_data& sd, const char* name); +void clif_traderesponse( map_session_data& sd, e_ack_trade_response result ); void clif_tradeadditem(map_session_data* sd, map_session_data* tsd, int index, int amount); void clif_tradeitemok(map_session_data& sd, int index, e_exitem_add_result result); void clif_tradedeal_lock( map_session_data& sd, bool who ); diff --git a/src/map/clif_packetdb.hpp b/src/map/clif_packetdb.hpp index 7591a05a96..4999e1f509 100644 --- a/src/map/clif_packetdb.hpp +++ b/src/map/clif_packetdb.hpp @@ -46,7 +46,6 @@ parseable_packet(0x0094,6,clif_parse_GetCharNameRequest,2); parseable_packet(0x0096,-1,clif_parse_WisMessage,2,4,28); parseable_packet(0x0099,-1,clif_parse_Broadcast,2,4); - packet(0x009a,-1); parseable_packet(0x009b,5,clif_parse_ChangeDir,2,4); packet( HEADER_ZC_ITEM_ENTRY, sizeof( struct PACKET_ZC_ITEM_ENTRY ) ); packet(0x009e,17); @@ -100,7 +99,6 @@ parseable_packet(0x00e4,6,clif_parse_TradeRequest,2); packet(0x00e5,26); parseable_packet(0x00e6,3,clif_parse_TradeAck,2); - packet(0x00e7,3); parseable_packet(0x00e8,8,clif_parse_TradeAddItem,2,4); packet(0x00ea,5); parseable_packet(0x00eb,2,clif_parse_TradeOk,0); @@ -300,8 +298,6 @@ packet(0x01f1,-1); packet(0x01f2,20); packet(0x01f3,10); - packet(0x01f4,32); - packet(0x01f5,9); packet(0x01f6,34); parseable_packet(0x01f7,14,clif_parse_Adopt_reply,2,6,10); packet(0x01f8,2); diff --git a/src/map/guild.cpp b/src/map/guild.cpp index 885d1194b9..8023786359 100644 --- a/src/map/guild.cpp +++ b/src/map/guild.cpp @@ -963,7 +963,7 @@ bool guild_invite( map_session_data& sd, map_session_data* tsd ){ } // Checking if there no other invitation pending - if( !battle_config.invite_request_check && ( tsd->party_invite > 0 || tsd->trade_partner || tsd->adopt_invite ) ){ + if( !battle_config.invite_request_check && ( tsd->party_invite > 0 || tsd->state.trading || tsd->adopt_invite ) ){ clif_guild_inviteack( sd, 0 ); return false; } diff --git a/src/map/packets.hpp b/src/map/packets.hpp index 0588aa1572..3435092d13 100644 --- a/src/map/packets.hpp +++ b/src/map/packets.hpp @@ -362,6 +362,38 @@ struct PACKET_ZC_ACK_OPEN_BANKING{ } __attribute__((packed)); DEFINE_PACKET_HEADER(ZC_ACK_OPEN_BANKING, 0x9b7) +#if PACKETVER > 6 +struct PACKET_ZC_REQ_EXCHANGE_ITEM{ + uint16 packetType; + char requesterName[NAME_LENGTH]; + uint32 targetId; + uint16 targetLv; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_REQ_EXCHANGE_ITEM, 0x1f4) +#else +struct PACKET_ZC_REQ_EXCHANGE_ITEM{ + uint16 packetType; + char requesterName[NAME_LENGTH]; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_REQ_EXCHANGE_ITEM, 0x9a) +#endif + +#if PACKETVER > 6 +struct PACKET_ZC_ACK_EXCHANGE_ITEM{ + uint16 packetType; + uint8 result; + uint32 targetId; + uint16 targetLv; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_ACK_EXCHANGE_ITEM, 0x1f5) +#else +struct PACKET_ZC_ACK_EXCHANGE_ITEM{ + uint16 packetType; + uint8 result; +} __attribute__((packed)); +DEFINE_PACKET_HEADER(ZC_ACK_EXCHANGE_ITEM, 0xe7) +#endif + struct PACKET_ZC_ACK_ADD_EXCHANGE_ITEM { int16 packetType; uint16 index; diff --git a/src/map/party.cpp b/src/map/party.cpp index d644e3937b..1e1dc4b400 100644 --- a/src/map/party.cpp +++ b/src/map/party.cpp @@ -446,7 +446,7 @@ bool party_invite( map_session_data& sd, map_session_data *tsd ){ return false; } - if( !battle_config.invite_request_check && ( tsd->guild_invite > 0 || tsd->trade_partner || tsd->adopt_invite ) ){ + if( !battle_config.invite_request_check && ( tsd->guild_invite > 0 || tsd->state.trading || tsd->adopt_invite ) ){ clif_party_invite_reply( sd, tsd->status.name, PARTY_REPLY_JOIN_OTHER_PARTY ); return false; } diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 4a8f7955ab..ab57cc4c00 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -706,7 +706,11 @@ public: int united_soul[MAX_UNITED_SOULS]; // Stores the account ID's of character's who's soul is united. int servant_sign[MAX_SERVANT_SIGN]; // Stores the account ID's of character's with a servant sign. - int trade_partner; + struct{ + uint32 id; + unsigned int lv; + }trade_partner; + struct s_deal { struct s_item { short index, amount; diff --git a/src/map/pet.cpp b/src/map/pet.cpp index e67a244fec..d8d13a9363 100644 --- a/src/map/pet.cpp +++ b/src/map/pet.cpp @@ -1192,7 +1192,7 @@ int pet_select_egg(map_session_data *sd,short egg_index) if(egg_index < 0 || egg_index >= MAX_INVENTORY) return 0; //Forged packet! - if(sd->trade_partner) //The player have trade in progress. + if(sd->state.trading) //The player have trade in progress. return 0; std::shared_ptr pet = pet_db_search(sd->inventory.u.items_inventory[egg_index].nameid, PET_EGG); diff --git a/src/map/trade.cpp b/src/map/trade.cpp index d23de14545..dfebd12116 100644 --- a/src/map/trade.cpp +++ b/src/map/trade.cpp @@ -38,54 +38,58 @@ void trade_traderequest(map_session_data *sd, map_session_data *target_sd) } if (target_sd == nullptr || sd == target_sd) { - clif_tradestart(sd, 1); // character does not exist + clif_traderesponse(*sd, TRADE_ACK_CHARNOTEXIST); return; } if (target_sd->npc_id) { // Trade fails if you are using an NPC. - clif_tradestart(sd, 2); + clif_traderesponse(*sd, TRADE_ACK_FAILED); 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); + clif_traderesponse(*sd, TRADE_ACK_FAILED); return; } } - if ( sd->trade_partner != 0 ) { // If a character tries to trade to another one then cancel the previous one - map_session_data *previous_sd = map_id2sd(sd->trade_partner); + if ( sd->trade_partner.id != 0 ) { // If a character tries to trade to another one then cancel the previous one + map_session_data *previous_sd = map_id2sd(sd->trade_partner.id); if( previous_sd != nullptr ){ - previous_sd->trade_partner = 0; + previous_sd->trade_partner = {0,0}; clif_tradecancelled( *previous_sd ); } // Once cancelled then continue to the new one. - sd->trade_partner = 0; + sd->trade_partner = {0,0}; clif_tradecancelled( *sd ); } - if (target_sd->trade_partner != 0) { - clif_tradestart(sd, 2); // person is in another trade + if (target_sd->trade_partner.id != 0) { + clif_traderesponse(*sd, TRADE_ACK_FAILED); // 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(sd,246)); - clif_tradestart(sd, 2); // GM is not allowed to trade + clif_traderesponse(*sd, TRADE_ACK_FAILED); // 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 + clif_traderesponse(*sd, TRADE_ACK_TOOFAR); return ; } - target_sd->trade_partner = sd->status.account_id; - sd->trade_partner = target_sd->status.account_id; - clif_traderequest(target_sd, sd->status.name); + target_sd->trade_partner.id = sd->status.account_id; + target_sd->trade_partner.lv = sd->status.base_level; + + sd->trade_partner.id = target_sd->status.account_id; + sd->trade_partner.lv = target_sd->status.base_level; + + clif_traderequest(*target_sd, sd->status.name); } @@ -107,28 +111,28 @@ void trade_tradeack(map_session_data *sd, int type) nullpo_retv(sd); - if (sd->state.trading || !sd->trade_partner) + if (sd->state.trading || !sd->trade_partner.id) return; // Already trading or no partner set. - if ((tsd = map_id2sd(sd->trade_partner)) == nullptr) { - clif_tradestart(sd, 1); // Character does not exist - sd->trade_partner=0; + if ((tsd = map_id2sd(sd->trade_partner.id)) == nullptr) { + clif_traderesponse(*sd, TRADE_ACK_CHARNOTEXIST); + sd->trade_partner = {0,0}; return; } - if (tsd->state.trading || tsd->trade_partner != sd->bl.id) { - clif_tradestart(sd, 2); - sd->trade_partner=0; + if (tsd->state.trading || tsd->trade_partner.id != sd->bl.id) { + clif_traderesponse(*sd, TRADE_ACK_FAILED); + sd->trade_partner = {0,0}; return; // Already trading or wrong partner. } if (type == 4) { // Cancel - clif_tradestart(tsd, type); - clif_tradestart(sd, type); + clif_traderesponse(*tsd, TRADE_ACK_CANCEL); + clif_traderesponse(*sd, TRADE_ACK_CANCEL); sd->state.deal_locked = 0; - sd->trade_partner = 0; + sd->trade_partner = {0,0}; tsd->state.deal_locked = 0; - tsd->trade_partner = 0; + tsd->trade_partner = {0,0}; return; } @@ -139,21 +143,21 @@ void trade_tradeack(map_session_data *sd, int type) // Check here as well since the original character could had warped. if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && (sd->bl.m != tsd->bl.m || !check_distance_bl(&sd->bl, &tsd->bl, TRADE_DISTANCE))) { - clif_tradestart(sd, 0); // too far - sd->trade_partner=0; - tsd->trade_partner = 0; + clif_traderesponse(*sd, TRADE_ACK_TOOFAR); + sd->trade_partner = {0,0}; + tsd->trade_partner = {0,0}; return; } // Check if you can start trade. if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag || tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag) { // Fail - clif_tradestart(sd, 2); - clif_tradestart(tsd, 2); + clif_traderesponse(*sd, TRADE_ACK_FAILED); + clif_traderesponse(*tsd, TRADE_ACK_FAILED); sd->state.deal_locked = 0; - sd->trade_partner = 0; + sd->trade_partner = {0,0}; tsd->state.deal_locked = 0; - tsd->trade_partner = 0; + tsd->trade_partner = {0,0}; return; } @@ -162,8 +166,8 @@ void trade_tradeack(map_session_data *sd, int type) tsd->state.trading = 1; memset(&sd->deal, 0, sizeof(sd->deal)); memset(&tsd->deal, 0, sizeof(tsd->deal)); - clif_tradestart(tsd, type); - clif_tradestart(sd, type); + clif_traderesponse(*tsd, static_cast( type )); + clif_traderesponse(*sd, static_cast( type )); } /** @@ -356,7 +360,7 @@ void trade_tradeadditem(map_session_data *sd, short index, short amount) if( !sd->state.trading || sd->state.deal_locked > 0 ) return; // Can't add stuff. - if( (target_sd = map_id2sd(sd->trade_partner)) == nullptr ) { + if( (target_sd = map_id2sd(sd->trade_partner.id)) == nullptr ) { trade_tradecancel(sd); return; } @@ -453,7 +457,7 @@ void trade_tradeaddzeny(map_session_data* sd, int amount) if( !sd->state.trading || sd->state.deal_locked > 0 ) return; //Can't add stuff. - if( (target_sd = map_id2sd(sd->trade_partner)) == nullptr ) { + if( (target_sd = map_id2sd(sd->trade_partner.id)) == nullptr ) { trade_tradecancel(sd); return; } @@ -478,7 +482,7 @@ void trade_tradeok(map_session_data *sd) if(sd->state.deal_locked || !sd->state.trading) return; - if ((target_sd = map_id2sd(sd->trade_partner)) == nullptr) { + if ((target_sd = map_id2sd(sd->trade_partner.id)) == nullptr) { trade_tradecancel(sd); return; } @@ -500,15 +504,15 @@ void trade_tradecancel(map_session_data *sd) nullpo_retv(sd); - target_sd = map_id2sd(sd->trade_partner); + target_sd = map_id2sd(sd->trade_partner.id); sd->state.isBoundTrading = 0; if(!sd->state.trading) { // Not trade accepted if( target_sd != nullptr ) { - target_sd->trade_partner = 0; + target_sd->trade_partner = {0,0}; clif_tradecancelled( *target_sd ); } - sd->trade_partner = 0; + sd->trade_partner = {0,0}; clif_tradecancelled( *sd ); return; } @@ -529,7 +533,7 @@ void trade_tradecancel(map_session_data *sd) sd->state.deal_locked = 0; sd->state.trading = 0; - sd->trade_partner = 0; + sd->trade_partner = {0,0}; clif_tradecancelled( *sd ); if (!target_sd) @@ -549,7 +553,7 @@ void trade_tradecancel(map_session_data *sd) } target_sd->state.deal_locked = 0; - target_sd->trade_partner = 0; + target_sd->trade_partner = {0,0}; target_sd->state.trading = 0; clif_tradecancelled( *target_sd ); } @@ -569,7 +573,7 @@ void trade_tradecommit(map_session_data *sd) 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)) == nullptr) { + if ((tsd = map_id2sd(sd->trade_partner.id)) == nullptr) { trade_tradecancel(sd); return; } @@ -642,12 +646,12 @@ void trade_tradecommit(map_session_data *sd) } sd->state.deal_locked = 0; - sd->trade_partner = 0; + sd->trade_partner = {0,0}; sd->state.trading = 0; sd->state.isBoundTrading = 0; tsd->state.deal_locked = 0; - tsd->trade_partner = 0; + tsd->trade_partner = {0,0}; tsd->state.trading = 0; tsd->state.isBoundTrading = 0; diff --git a/src/map/trade.hpp b/src/map/trade.hpp index 7567408f49..3f2d207344 100644 --- a/src/map/trade.hpp +++ b/src/map/trade.hpp @@ -4,8 +4,19 @@ #ifndef TRADE_HPP #define TRADE_HPP +#include + class map_session_data; +enum e_ack_trade_response : uint8 { + TRADE_ACK_TOOFAR = 0, + TRADE_ACK_CHARNOTEXIST, + TRADE_ACK_FAILED, + TRADE_ACK_ACCEPT, + TRADE_ACK_CANCEL, + TRADE_ACK_BUSY +}; + void trade_traderequest(map_session_data *sd, map_session_data *target_sd); void trade_tradeack(map_session_data *sd,int type); void trade_tradeadditem(map_session_data *sd,short index,short amount); diff --git a/src/map/unit.cpp b/src/map/unit.cpp index 230949bcb2..c600fe4323 100644 --- a/src/map/unit.cpp +++ b/src/map/unit.cpp @@ -3239,7 +3239,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, if(sd->chatID) chat_leavechat(sd,0); - if(sd->trade_partner) + if(sd->trade_partner.id > 0) trade_tradecancel(sd); searchstore_close(*sd);