[12175] Fix trade.

TODO: operate with 64-bit money amount

Signed-off-by: Yaki Khadafi <elsoldollo@gmail.com>
This commit is contained in:
Yaki Khadafi 2012-09-03 15:11:24 +03:00 committed by Antz
parent fc28fef1c1
commit c166741bad
7 changed files with 157 additions and 108 deletions

View file

@ -345,18 +345,18 @@ void InitializeOpcodes()
OPCODE(SMSG_OPEN_CONTAINER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
OPCODE(CMSG_INSPECT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectOpcode );
//OPCODE(SMSG_INSPECT_RESULTS_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(CMSG_INITIATE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateTradeOpcode );
//OPCODE(CMSG_BEGIN_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode );
//OPCODE(CMSG_BUSY_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode );
//OPCODE(CMSG_IGNORE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode );
//OPCODE(CMSG_ACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode );
//OPCODE(CMSG_UNACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode );
//OPCODE(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode);
//OPCODE(CMSG_SET_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode );
//OPCODE(CMSG_CLEAR_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode );
//OPCODE(CMSG_SET_TRADE_GOLD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode );
//OPCODE(SMSG_TRADE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_TRADE_STATUS_EXTENDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
OPCODE(CMSG_INITIATE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleInitiateTradeOpcode );
OPCODE(CMSG_BEGIN_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode );
OPCODE(CMSG_BUSY_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleBusyTradeOpcode );
OPCODE(CMSG_IGNORE_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode );
OPCODE(CMSG_ACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode );
OPCODE(CMSG_UNACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode );
OPCODE(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode);
OPCODE(CMSG_SET_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode );
OPCODE(CMSG_CLEAR_TRADE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode );
OPCODE(CMSG_SET_TRADE_GOLD, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode );
OPCODE(SMSG_TRADE_STATUS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
OPCODE(SMSG_TRADE_STATUS_EXTENDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
OPCODE(SMSG_INITIALIZE_FACTIONS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_SET_FACTION_VISIBLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//OPCODE(SMSG_SET_FACTION_STANDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );

View file

@ -330,18 +330,18 @@ enum Opcodes
SMSG_OPEN_CONTAINER = 0x4714, // 4.3.4 15595
CMSG_INSPECT = 0x0927, // 4.3.4 15595
SMSG_INSPECT_RESULTS_UPDATE = 0x1116,
CMSG_INITIATE_TRADE = 0x1117,
CMSG_BEGIN_TRADE = 0x1118,
CMSG_BUSY_TRADE = 0x1119,
CMSG_IGNORE_TRADE = 0x111A,
CMSG_ACCEPT_TRADE = 0x111B,
CMSG_UNACCEPT_TRADE = 0x111C,
CMSG_CANCEL_TRADE = 0x111D,
CMSG_SET_TRADE_ITEM = 0x111E,
CMSG_CLEAR_TRADE_ITEM = 0x111F,
CMSG_SET_TRADE_GOLD = 0x1120,
SMSG_TRADE_STATUS = 0x1121,
SMSG_TRADE_STATUS_EXTENDED = 0x1122,
CMSG_INITIATE_TRADE = 0x7916, // 4.3.4 15595
CMSG_BEGIN_TRADE = 0x721E, // 4.3.4 15595
CMSG_BUSY_TRADE = 0x331C, // 4.3.4 15595
CMSG_IGNORE_TRADE = 0x7112, // 4.3.4 15595
CMSG_ACCEPT_TRADE = 0x7110, // 4.3.4 15595
CMSG_UNACCEPT_TRADE = 0x391A, // 4.3.4 15595
CMSG_CANCEL_TRADE = 0x731E, // 4.3.4 15595
CMSG_SET_TRADE_ITEM = 0x7B0C, // 4.3.4 15595
CMSG_CLEAR_TRADE_ITEM = 0x7018, // 4.3.4 15595
CMSG_SET_TRADE_GOLD = 0x3008, // 4.3.4 15595
SMSG_TRADE_STATUS = 0x5CA3, // 4.3.4 15595
SMSG_TRADE_STATUS_EXTENDED = 0x70A2, // 4.3.4 15595
SMSG_INITIALIZE_FACTIONS = 0x4634, // 4.3.4 15595
SMSG_SET_FACTION_VISIBLE = 0x1124,
SMSG_SET_FACTION_STANDING = 0x1125,

View file

@ -350,7 +350,7 @@ void TradeData::SetSpell(uint32 spell_id, Item* castItem /*= NULL*/)
Update(false); // send spell info to caster self
}
void TradeData::SetMoney(uint32 money)
void TradeData::SetMoney(uint64 money)
{
if (m_money == money)
return;

View file

@ -1002,7 +1002,7 @@ class TradeData
Item* GetSpellCastItem() const;
bool HasSpellCastItem() const { return !m_spellCastItem.IsEmpty(); }
uint32 GetMoney() const { return m_money; }
uint64 GetMoney() const { return m_money; }
bool IsAccepted() const { return m_accepted; }
bool IsInAcceptProcess() const { return m_acceptProccess; }
@ -1010,7 +1010,7 @@ class TradeData
void SetItem(TradeSlots slot, Item* item);
void SetSpell(uint32 spell_id, Item* castItem = NULL);
void SetMoney(uint32 money);
void SetMoney(uint64 money);
void SetAccepted(bool state, bool crosssend = false);
@ -1029,7 +1029,7 @@ class TradeData
bool m_accepted; // m_player press accept for trade list
bool m_acceptProccess; // one from player/trader press accept and this processed
uint32 m_money; // m_player place money to trade
uint64 m_money; // m_player place money to trade
uint32 m_spell; // m_player apply spell to non-traded slot item
ObjectGuid m_spellCastItem; // applied spell casted by item use
@ -1515,7 +1515,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void setRegenTimer(uint32 time) {m_regenTimer = time;}
void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;}
uint32 GetMoney() const { return GetUInt32Value(PLAYER_FIELD_COINAGE); }
uint64 GetMoney() const { return GetUInt64Value(PLAYER_FIELD_COINAGE); }
void ModifyMoney(int32 d)
{
if (d < 0)

View file

@ -3139,29 +3139,31 @@ enum TotemSlot
enum TradeStatus
{
TRADE_STATUS_BUSY = 0,
TRADE_STATUS_BEGIN_TRADE = 1,
TRADE_STATUS_OPEN_WINDOW = 2,
TRADE_STATUS_TRADE_CANCELED = 3,
TRADE_STATUS_TRADE_ACCEPT = 4,
TRADE_STATUS_BUSY_2 = 5,
TRADE_STATUS_NO_TARGET = 6,
TRADE_STATUS_BACK_TO_TRADE = 7,
TRADE_STATUS_TRADE_COMPLETE = 8,
// 9?
TRADE_STATUS_TARGET_TO_FAR = 10,
TRADE_STATUS_WRONG_FACTION = 11,
TRADE_STATUS_CLOSE_WINDOW = 12,
// 13?
TRADE_STATUS_IGNORE_YOU = 14,
TRADE_STATUS_YOU_STUNNED = 15,
TRADE_STATUS_TARGET_STUNNED = 16,
TRADE_STATUS_YOU_DEAD = 17,
TRADE_STATUS_TARGET_DEAD = 18,
TRADE_STATUS_YOU_LOGOUT = 19,
TRADE_STATUS_TARGET_LOGOUT = 20,
TRADE_STATUS_TRIAL_ACCOUNT = 21, // Trial accounts can not perform that action
TRADE_STATUS_ONLY_CONJURED = 22 // You can only trade conjured items... (cross realm BG related).
TRADE_STATUS_OPEN_WINDOW = 0,
//TRADE_STATUS_TRADE_CANCELED_NO_REPORT = 1,
TRADE_STATUS_NOT_ON_TAPLIST = 2, // You may only trade bound items to players that were originally eligible to loot them
TRADE_STATUS_YOU_LOGOUT = 3,
TRADE_STATUS_IGNORE_YOU = 4,
TRADE_STATUS_TARGET_DEAD = 5,
TRADE_STATUS_TRADE_ACCEPT = 6,
TRADE_STATUS_TARGET_LOGOUT = 7,
TRADE_STATUS_TRADE_COMPLETE = 9,
//TRADE_STATUS_TRIAL_ACCOUNT = 10, // Trial accounts can not perform that action
TRADE_STATUS_BEGIN_TRADE = 12,
TRADE_STATUS_YOU_DEAD = 13,
TRADE_STATUS_TARGET_TO_FAR = 16,
TRADE_STATUS_NO_TARGET = 17,
//TRADE_STATUS_BUSY_2 = 18,
TRADE_STATUS_CURRENCY_NOT_TRADEABLE = 19, // guessed
TRADE_STATUS_WRONG_FACTION = 20,
TRADE_STATUS_BUSY = 21,
TRADE_STATUS_TRADE_CANCELED = 23,
TRADE_STATUS_CLOSE_WINDOW = 24, // guessed
TRADE_STATUS_BACK_TO_TRADE = 25,
TRADE_STATUS_ONLY_CONJURED = 26, // You can only trade conjured items to players from other realms
TRADE_STATUS_YOU_STUNNED = 27,
TRADE_STATUS_TARGET_STUNNED = 29,
// item related = 31 // closes trade
};
enum EncounterCreditType

View file

@ -32,35 +32,45 @@
void WorldSession::SendTradeStatus(TradeStatus status)
{
WorldPacket data;
WorldPacket data(SMSG_TRADE_STATUS, 4 + 8);
switch (status)
data.WriteBit(false);
data.WriteBits(status, 5);
switch(status)
{
case TRADE_STATUS_BEGIN_TRADE:
data.Initialize(SMSG_TRADE_STATUS, 4 + 8);
data << uint32(status);
data << uint64(0);
break;
case TRADE_STATUS_OPEN_WINDOW:
data.Initialize(SMSG_TRADE_STATUS, 4 + 4);
data << uint32(status);
data << uint32(0); // added in 2.4.0
break;
case TRADE_STATUS_CLOSE_WINDOW:
data.Initialize(SMSG_TRADE_STATUS, 4 + 4 + 1 + 4);
data << uint32(status);
data << uint32(0);
data << uint8(0);
{
data << uint32(0);
break;
}
case TRADE_STATUS_NOT_ON_TAPLIST:
case TRADE_STATUS_ONLY_CONJURED:
data.Initialize(SMSG_TRADE_STATUS, 4 + 1);
data << uint32(status);
{
data << uint8(0);
break;
}
case TRADE_STATUS_BEGIN_TRADE:
{
data.WriteGuidMask<2, 4, 6, 0, 1, 3, 7, 5>(ObjectGuid());
data.WriteGuidBytes<4, 1, 2, 3, 0, 7, 6, 5>(ObjectGuid());
break;
}
case TRADE_STATUS_CURRENCY_NOT_TRADEABLE:
case TRADE_STATUS_CLOSE_WINDOW:
{
data << uint32(0);
data << uint32(0);
break;
}
case 31:
{
data.WriteBit(false);
data << uint32(0);
data << uint32(0);
break;
}
default:
data.Initialize(SMSG_TRADE_STATUS, 4);
data << uint32(status);
break;
}
@ -84,46 +94,78 @@ void WorldSession::SendUpdateTrade(bool trader_state /*= true*/)
TradeData* view_trade = trader_state ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData();
WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, (100)); // guess size
data << uint8(trader_state ? 1 : 0); // send trader or own trade windows state (last need for proper show spell apply to non-trade slot)
data << uint32(0); // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?)
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = next field in most cases
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = prev field in most cases
data << uint32(view_trade->GetMoney()); // trader gold
data << uint32(0); // unk 2
data << uint64(view_trade->GetMoney()); // trader gold
data << uint32(view_trade->GetSpell()); // spell casted on lowest slot item
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?
data << uint32(0); // unk 5
data << uint8(trader_state ? 1 : 0); // send trader or own trade windows state (last need for proper show spell apply to non-trade slot)
data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?
uint8 itemCount = 0;
for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
if (Item* item = view_trade->GetItem(TradeSlots(i)))
++itemCount;
data.WriteBits(itemCount, 22);
for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
{
data << uint8(i); // trade slot number, if not specified, then end of packet
if (Item* item = view_trade->GetItem(TradeSlots(i)))
{
data << uint32(item->GetProto()->ItemId); // entry
data << uint32(item->GetProto()->DisplayInfoID);// display id
data << uint32(item->GetCount()); // stack count
// wrapped: hide stats but show giftcreator name
data << uint32(item->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED) ? 1 : 0);
data << item->GetGuidValue(ITEM_FIELD_GIFTCREATOR);
ObjectGuid creatorGuid = item->GetGuidValue(ITEM_FIELD_CREATOR);
ObjectGuid giftCreatorGuid = item->GetGuidValue(ITEM_FIELD_GIFTCREATOR);
data << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
data << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
// creator
data << item->GetGuidValue(ITEM_FIELD_CREATOR);
data << uint32(item->GetSpellCharges()); // charges
data << uint32(item->GetItemSuffixFactor()); // SuffixFactor
data << uint32(item->GetItemRandomPropertyId());// random properties id
data << uint32(item->GetProto()->LockID); // lock id
// max durability
data << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
// durability
data << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
}
else
{
for (uint8 j = 0; j < 18; ++j)
data << uint32(0);
data.WriteGuidMask<7, 1>(giftCreatorGuid);
data.WriteBit(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED));
data.WriteGuidMask<3>(giftCreatorGuid);
if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED))
{
data.WriteGuidMask<7, 1, 4, 6, 2, 3, 5>(creatorGuid);
data.WriteBit(item->GetProto()->LockID && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_UNLOCKED));
data.WriteGuidMask<0>(creatorGuid);
}
data.WriteGuidMask<6, 4, 2, 0, 5>(giftCreatorGuid);
}
}
for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i)
{
if (Item* item = view_trade->GetItem(TradeSlots(i)))
{
ObjectGuid creatorGuid = item->GetGuidValue(ITEM_FIELD_CREATOR);
ObjectGuid giftCreatorGuid = item->GetGuidValue(ITEM_FIELD_GIFTCREATOR);
if (!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED))
{
data.WriteGuidBytes<1>(creatorGuid);
data << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT));
for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
data << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot)));
data << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
data.WriteGuidBytes<6, 2, 7, 4>(creatorGuid);
data << uint32(0); // reforge Id
data << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
data << uint32(item->GetItemRandomPropertyId());
data.WriteGuidBytes<3>(creatorGuid);
data << uint32(0); // unk
data.WriteGuidBytes<0>(creatorGuid);
data << uint32(item->GetSpellCharges()); // charges
data << uint32(item->GetItemSuffixFactor());
data.WriteGuidBytes<5>(creatorGuid);
}
data.WriteGuidBytes<6, 1, 7, 4>(giftCreatorGuid);
data << uint32(item->GetProto()->ItemId); // entry
data.WriteGuidBytes<0>(giftCreatorGuid);
data << uint32(item->GetCount()); // stack count
data.WriteGuidBytes<5>(giftCreatorGuid);
data << uint8(i); // slot id
data.WriteGuidBytes<2, 3>(giftCreatorGuid);
}
}
SendPacket(&data);
}
@ -531,7 +573,8 @@ void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
{
ObjectGuid otherGuid;
recvPacket >> otherGuid;
recvPacket.ReadGuidMask<0, 3, 5, 1, 4, 6, 7, 2>(otherGuid);
recvPacket.ReadGuidBytes<7, 4, 3, 5, 1, 2, 6, 0>(otherGuid);
if (GetPlayer()->m_trade)
return;
@ -621,14 +664,18 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
pOther->m_trade = new TradeData(pOther, _player);
WorldPacket data(SMSG_TRADE_STATUS, 12);
data << uint32(TRADE_STATUS_BEGIN_TRADE);
data << ObjectGuid(_player->GetObjectGuid());
data.WriteBit(false);
data.WriteBits(TRADE_STATUS_BEGIN_TRADE, 5);
data.WriteGuidMask<2, 4, 6, 0, 1, 3, 7, 5>(_player->GetObjectGuid());
data.WriteGuidBytes<4, 1, 2, 3, 0, 7, 6, 5>(_player->GetObjectGuid());
data << uint32(0);
pOther->GetSession()->SendPacket(&data);
}
void WorldSession::HandleSetTradeGoldOpcode(WorldPacket& recvPacket)
{
uint32 gold;
uint64 gold;
recvPacket >> gold;
@ -647,9 +694,9 @@ void WorldSession::HandleSetTradeItemOpcode(WorldPacket& recvPacket)
uint8 bag;
uint8 slot;
recvPacket >> slot;
recvPacket >> tradeSlot;
recvPacket >> bag;
recvPacket >> slot;
TradeData* my_trade = _player->m_trade;
if (!my_trade)

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "12174"
#define REVISION_NR "12175"
#endif // __REVISION_NR_H__