[c12642] Fix client crash on guild bank display

This commit is contained in:
Dramacydal 2013-06-17 10:51:21 +01:00 committed by Antz
parent 5c21144f6b
commit c3eccda44d
3 changed files with 539 additions and 277 deletions

View file

@ -29,6 +29,7 @@
#include "Util.h" #include "Util.h"
#include "Language.h" #include "Language.h"
#include "World.h" #include "World.h"
#include "Calendar.h"
//// MemberSlot //////////////////////////////////////////// //// MemberSlot ////////////////////////////////////////////
void MemberSlot::SetMemberStats(Player* player) void MemberSlot::SetMemberStats(Player* player)
@ -79,6 +80,7 @@ void MemberSlot::ChangeRank(uint32 newRank)
Guild::Guild() Guild::Guild()
{ {
m_Id = 0; m_Id = 0;
m_Level = 1;
m_Name = ""; m_Name = "";
GINFO = MOTD = ""; GINFO = MOTD = "";
m_EmblemStyle = 0; m_EmblemStyle = 0;
@ -173,7 +175,7 @@ bool Guild::AddMember(ObjectGuid plGuid, uint32 plRank)
// remove all player signs from another petitions // remove all player signs from another petitions
// this will be prevent attempt joining player to many guilds and corrupt guild data integrity // this will be prevent attempt joining player to many guilds and corrupt guild data integrity
Player::RemovePetitionsAndSigns(plGuid, 9); Player::RemovePetitionsAndSigns(plGuid);
uint32 lowguid = plGuid.GetCounter(); uint32 lowguid = plGuid.GetCounter();
@ -234,8 +236,9 @@ bool Guild::AddMember(ObjectGuid plGuid, uint32 plRank)
if (pl) if (pl)
{ {
pl->SetInGuild(m_Id); pl->SetInGuild(m_Id);
pl->SetGuildLevel(GetLevel());
pl->SetRank(newmember.RankId); pl->SetRank(newmember.RankId);
pl->SetGuildIdInvited(0); pl->SetGuildInvited(0);
} }
UpdateAccountsNumber(); UpdateAccountsNumber();
@ -465,7 +468,6 @@ bool Guild::LoadMembersFromDB(QueryResult* guildMembersResult)
} }
members[lowguid] = newmember; members[lowguid] = newmember;
} }
while (guildMembersResult->NextRow()); while (guildMembersResult->NextRow());
@ -547,6 +549,7 @@ bool Guild::DelMember(ObjectGuid guid, bool isDisbanding)
if (player) if (player)
{ {
player->SetInGuild(0); player->SetInGuild(0);
player->SetGuildLevel(0);
player->SetRank(0); player->SetRank(0);
} }
@ -649,6 +652,39 @@ void Guild::BroadcastPacketToRank(WorldPacket* packet, uint32 rankId)
} }
} }
// add new event to all already connected guild memebers
void Guild::MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 maxLevel, uint32 minRank)
{
uint32 count = 0;
WorldPacket data(SMSG_CALENDAR_FILTER_GUILD);
data << uint32(count); // count placeholder
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
{
// not sure if needed, maybe client checks it as well
if (count >= CALENDAR_MAX_INVITES)
{
sCalendarMgr.SendCalendarCommandResult(session->GetPlayer(), CALENDAR_ERROR_INVITES_EXCEEDED);
return;
}
MemberSlot const* member = &itr->second;
uint32 level = Player::GetLevelFromDB(member->guid);
if (member->guid != session->GetPlayer()->GetObjectGuid() && level >= minLevel && level <= maxLevel && member->RankId <= minRank)
{
data << member->guid.WriteAsPacked();
data << uint8(level);
++count;
}
}
data.put<uint32>(0, count);
session->SendPacket(&data);
}
void Guild::CreateRank(std::string name_, uint32 rights) void Guild::CreateRank(std::string name_, uint32 rights)
{ {
if (m_Ranks.size() >= GUILD_RANKS_MAX_COUNT) if (m_Ranks.size() >= GUILD_RANKS_MAX_COUNT)
@ -676,18 +712,59 @@ void Guild::AddRank(const std::string& name_, uint32 rights, uint32 money)
m_Ranks.push_back(RankInfo(name_, rights, money)); m_Ranks.push_back(RankInfo(name_, rights, money));
} }
void Guild::DelRank() void Guild::DelRank(uint32 rankId)
{ {
// client won't allow to have less than GUILD_RANKS_MIN_COUNT ranks in guild if (rankId >= m_Ranks.size())
if (m_Ranks.size() <= GUILD_RANKS_MIN_COUNT)
return; return;
// delete lowest guild_rank // client won't allow to have less than GUILD_RANKS_MIN_COUNT ranks in guild
uint32 rank = GetLowestRank(); if (m_Ranks.size() <= GUILD_RANKS_MIN_COUNT || rankId < GUILD_RANKS_MIN_COUNT)
CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE rid>='%u' AND guildid='%u'", rank, m_Id); return;
CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE rid>='%u' AND guildid='%u'", rank, m_Id);
m_Ranks.pop_back(); RankList::iterator itr = m_Ranks.erase(m_Ranks.begin() + rankId);
// delete lowest guild_rank
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE rid ='%u' AND guildid='%u'", rankId, m_Id);
CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE rid ='%u' AND guildid='%u'", rankId, m_Id);
CharacterDatabase.PExecute("UPDATE guild_rank SET rid = rid - 1 WHERE rid > '%u' AND guildid='%u'", rankId, m_Id);
CharacterDatabase.PExecute("UPDATE guild_bank_right SET rid = rid - 1 WHERE rid > '%u' AND guildid='%u'", rankId, m_Id);
CharacterDatabase.CommitTransaction();
}
void Guild::SwitchRank(uint32 rankId, bool up)
{
if (rankId >= m_Ranks.size())
return;
if (rankId == GR_GUILDMASTER && up || rankId == GetLowestRank() && !up)
return;
uint32 otherRankId = rankId + (up ? -1 : 1);
DEBUG_LOG("rank: %u otherrank %u", rankId, otherRankId);
std::swap(m_Ranks[rankId], m_Ranks[otherRankId]);
CharacterDatabase.BeginTransaction();
for (uint32 i = 0; i < uint32(GetPurchasedTabs()); ++i)
{
CharacterDatabase.PExecute("REPLACE INTO guild_bank_right (guildid,TabId,rid,gbright,SlotPerDay) "
"VALUES ('%u','%u','%u','%u','%u')", m_Id, i, rankId, m_Ranks[rankId].TabRight[i], m_Ranks[rankId].TabSlotPerDay[i]);
CharacterDatabase.PExecute("REPLACE INTO guild_bank_right (guildid,TabId,rid,gbright,SlotPerDay) "
"VALUES ('%u','%u','%u','%u','%u')", m_Id, i, otherRankId, m_Ranks[otherRankId].TabRight[i], m_Ranks[otherRankId].TabSlotPerDay[i]);
}
CharacterDatabase.PExecute("REPLACE INTO guild_rank (guildid,rid,rname,rights,BankMoneyPerDay) "
"VALUES ('%u', '%u', '%s', '%u', '%u')", m_Id, rankId, m_Ranks[rankId].Name.c_str(),m_Ranks[rankId].Rights,m_Ranks[rankId].BankMoneyPerDay);
CharacterDatabase.PExecute("REPLACE INTO guild_rank (guildid,rid,rname,rights,BankMoneyPerDay) "
"VALUES ('%u', '%u', '%s', '%u', '%u')", m_Id, otherRankId, m_Ranks[otherRankId].Name.c_str(),m_Ranks[otherRankId].Rights,m_Ranks[otherRankId].BankMoneyPerDay);
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
if (itr->second.RankId == rankId)
itr->second.ChangeRank(otherRankId);
else if (itr->second.RankId == otherRankId)
itr->second.ChangeRank(rankId);
CharacterDatabase.CommitTransaction();
} }
std::string Guild::GetRankName(uint32 rankId) std::string Guild::GetRankName(uint32 rankId)
@ -761,53 +838,85 @@ void Guild::Disband()
void Guild::Roster(WorldSession* session /*= NULL*/) void Guild::Roster(WorldSession* session /*= NULL*/)
{ {
// we can only guess size ByteBuffer buffer;
WorldPacket data(SMSG_GUILD_ROSTER, (4 + MOTD.length() + 1 + GINFO.length() + 1 + 4 + m_Ranks.size() * (4 + 4 + GUILD_BANK_MAX_TABS * (4 + 4)) + members.size() * 50));
data << uint32(members.size()); // we can only guess size
data << MOTD; WorldPacket data(SMSG_GUILD_ROSTER, (4 + MOTD.length() + 1 + GINFO.length() + 1 + 4 + members.size() * 50));
data << GINFO; data.WriteBits(MOTD.length(), 11);
data.WriteBits(members.size(), 18);
data << uint32(m_Ranks.size());
for (RankList::const_iterator ritr = m_Ranks.begin(); ritr != m_Ranks.end(); ++ritr)
{
data << uint32(ritr->Rights);
data << uint32(ritr->BankMoneyPerDay); // count of: withdraw gold(gold/day) Note: in game set gold, in packet set bronze.
for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{
data << uint32(ritr->TabRight[i]); // for TAB_i rights: view tabs = 0x01, deposit items =0x02
data << uint32(ritr->TabSlotPerDay[i]); // for TAB_i count of: withdraw items(stack/day)
}
}
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
{ {
if (Player* pl = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first))) MemberSlot const member = itr->second;
Player* player = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first));
ObjectGuid guid = member.guid;
data.WriteGuidMask<3, 4>(guid);
data.WriteBit(false); // Has Authenticator
data.WriteBit(false); // Can Scroll of Ressurect
data.WriteBits(member.Pnote.length(), 8);
data.WriteBits(member.OFFnote.length(), 8);
data.WriteGuidMask<0>(guid);
data.WriteBits(member.Name.length(), 7);
data.WriteGuidMask<1, 2, 6, 5, 7>(guid);
uint8 flags = GUILDMEMBER_STATUS_NONE;
if (player)
{ {
data << pl->GetObjectGuid(); flags |= GUILDMEMBER_STATUS_ONLINE;
data << uint8(1); if (player->isAFK())
data << pl->GetName(); flags |= GUILDMEMBER_STATUS_AFK;
data << uint32(itr->second.RankId); if (player->isDND())
data << uint8(pl->getLevel()); flags |= GUILDMEMBER_STATUS_DND;
data << uint8(pl->getClass());
data << uint8(0); // new 2.4.0
data << uint32(pl->GetZoneId());
data << itr->second.Pnote;
data << itr->second.OFFnote;
}
else
{
data << ObjectGuid(HIGHGUID_PLAYER, itr->first);
data << uint8(0);
data << itr->second.Name;
data << uint32(itr->second.RankId);
data << uint8(itr->second.Level);
data << uint8(itr->second.Class);
data << uint8(0); // new 2.4.0
data << uint32(itr->second.ZoneId);
data << float(float(time(NULL) - itr->second.LogoutTime) / DAY);
data << itr->second.Pnote;
data << itr->second.OFFnote;
} }
buffer << uint8(member.Class);
buffer << int32(0); // unk
buffer.WriteGuidBytes<0>(guid);
buffer << uint64(0); // weekly activity
buffer << uint32(member.RankId);
buffer << uint32(0); // achievement points
// professions: id, value, rank
buffer << uint32(0) << uint32(0) << uint32(0);
buffer << uint32(0) << uint32(0) << uint32(0);
buffer.WriteGuidBytes<2>(guid);
buffer << uint8(flags);
buffer << uint32(player ? player->GetZoneId() : member.ZoneId);
buffer << uint64(0); // Total activity
buffer.WriteGuidBytes<7>(guid);
buffer << uint32(0); // Remaining guild week Rep
buffer.WriteStringData(member.Pnote);
buffer.WriteGuidBytes<3>(guid);
buffer << uint8(player ? player->getLevel() : member.Level);
buffer << int32(0); // unk
buffer.WriteGuidBytes<5, 4>(guid);
buffer << uint8(0); // unk
buffer.WriteGuidBytes<1>(guid);
buffer << float(player ? 0.0f : float(time(NULL) - itr->second.LogoutTime) / DAY);
buffer.WriteStringData(member.OFFnote);
buffer.WriteGuidBytes<6>(guid);
buffer.WriteStringData(member.Name);
} }
data.WriteBits(GINFO.length(), 12);
data.FlushBits();
data.append(buffer);
data.WriteStringData(GINFO);
data.WriteStringData(MOTD);
data << uint32(m_accountsNumber);
data << uint32(0); // weekly rep cap
data << secsToTimeBitFields(m_CreatedDate);
data << uint32(0);
if (session) if (session)
session->SendPacket(&data); session->SendPacket(&data);
else else
@ -817,9 +926,9 @@ void Guild::Roster(WorldSession* session /*= NULL*/)
void Guild::Query(WorldSession* session) void Guild::Query(WorldSession* session)
{ {
WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, (8 * 32 + 200)); // we can only guess size WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, 8 * 32 + 200); // we can only guess size
data << uint32(m_Id); data << GetObjectGuid();
data << m_Name; data << m_Name;
for (size_t i = 0 ; i < GUILD_RANKS_MAX_COUNT; ++i) // show always 10 ranks for (size_t i = 0 ; i < GUILD_RANKS_MAX_COUNT; ++i) // show always 10 ranks
@ -830,17 +939,65 @@ void Guild::Query(WorldSession* session)
data << uint8(0); // null string data << uint8(0); // null string
} }
// Rank order of creation
for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i)
{
if (i < m_Ranks.size())
data << uint32(i);
else
data << uint32(0);
}
// Rank order of "importance" (sorting by rights)
for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i)
{
if (i < m_Ranks.size())
data << uint32(i);
else
data << uint32(0);
}
data << uint32(m_EmblemStyle); data << uint32(m_EmblemStyle);
data << uint32(m_EmblemColor); data << uint32(m_EmblemColor);
data << uint32(m_BorderStyle); data << uint32(m_BorderStyle);
data << uint32(m_BorderColor); data << uint32(m_BorderColor);
data << uint32(m_BackgroundColor); data << uint32(m_BackgroundColor);
data << uint32(0); // probably real ranks count data << uint32(m_Ranks.size());
session->SendPacket(&data); session->SendPacket(&data);
DEBUG_LOG("WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)"); DEBUG_LOG("WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)");
} }
void Guild::QueryRanks(WorldSession* session)
{
WorldPacket data(SMSG_GUILD_QUERY_RANKS_RESULT, (4 * 2 * 8 + 4 * 3 + 1) * m_Ranks.size()); // we can only guess size
data.WriteBits(m_Ranks.size(), 18);
for (uint8 i = 0; i < m_Ranks.size(); ++i)
data.WriteBits(m_Ranks[i].Name.length(), 7);
for (uint8 i = 0; i < m_Ranks.size(); ++i)
{
data << uint32(i);
for (uint8 j = 0; j < GUILD_BANK_MAX_TABS; ++j)
{
data << uint32(m_Ranks[i].TabSlotPerDay[j]);
data << uint32(m_Ranks[i].TabRight[j]);
}
data << uint32(m_Ranks[i].BankMoneyPerDay);
data << uint32(m_Ranks[i].Rights);
data.WriteStringData(m_Ranks[i].Name);
data << uint32(i); // rank id
}
session->SendPacket(&data);
}
void Guild::SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor) void Guild::SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor)
{ {
m_EmblemStyle = emblemStyle; m_EmblemStyle = emblemStyle;
@ -879,26 +1036,19 @@ uint32 Guild::GetAccountsNumber()
void Guild::DisplayGuildEventLog(WorldSession* session) void Guild::DisplayGuildEventLog(WorldSession* session)
{ {
// Sending result // Sending result
WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 0); ByteBuffer buffer;
WorldPacket data(SMSG_GUILD_EVENT_LOG, 0);
// count, max count == 100 // count, max count == 100
data << uint8(m_GuildEventLog.size()); data.WriteBits(m_GuildEventLog.size(), 23);
for (GuildEventLog::const_iterator itr = m_GuildEventLog.begin(); itr != m_GuildEventLog.end(); ++itr) for (GuildEventLog::iterator itr = m_GuildEventLog.begin(); itr != m_GuildEventLog.end(); ++itr)
itr->WriteData(data, buffer);
if (!buffer.empty())
{ {
// Event type data.FlushBits();
data << uint8(itr->EventType); data.append(buffer);
// Player 1
data << ObjectGuid(HIGHGUID_PLAYER, itr->PlayerGuid1);
// Player 2 not for left/join guild events
if (itr->EventType != GUILD_EVENT_LOG_JOIN_GUILD && itr->EventType != GUILD_EVENT_LOG_LEAVE_GUILD)
data << ObjectGuid(HIGHGUID_PLAYER, itr->PlayerGuid2);
// New Rank - only for promote/demote guild events
if (itr->EventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || itr->EventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
data << uint8(itr->NewRank);
// Event timestamp
data << uint32(time(NULL) - itr->TimeStamp);
} }
session->SendPacket(&data); session->SendPacket(&data);
DEBUG_LOG("WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)"); DEBUG_LOG("WORLD: Sent (SMSG_GUILD_EVENT_LOG)");
} }
// Load guild eventlog from DB // Load guild eventlog from DB
@ -933,7 +1083,6 @@ void Guild::LoadGuildEventLogFromDB()
// Add entry to list // Add entry to list
m_GuildEventLog.push_front(NewEvent); m_GuildEventLog.push_front(NewEvent);
} }
while (result->NextRow()); while (result->NextRow());
delete result; delete result;
@ -968,38 +1117,51 @@ void Guild::LogGuildEvent(uint8 EventType, ObjectGuid playerGuid1, ObjectGuid pl
// Bank content related // Bank content related
void Guild::DisplayGuildBankContent(WorldSession* session, uint8 TabId) void Guild::DisplayGuildBankContent(WorldSession* session, uint8 TabId)
{ {
if (TabId >= GetPurchasedTabs())
return;
GuildBankTab const* tab = m_TabListMap[TabId]; GuildBankTab const* tab = m_TabListMap[TabId];
if (!IsMemberHaveRights(session->GetPlayer()->GetGUIDLow(), TabId, GUILD_BANK_RIGHT_VIEW_TAB)) if (!IsMemberHaveRights(session->GetPlayer()->GetGUIDLow(), TabId, GUILD_BANK_RIGHT_VIEW_TAB))
return; return;
WorldPacket data(SMSG_GUILD_BANK_LIST, 1200); WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
ByteBuffer buffer;
data << uint64(GetGuildBankMoney()); data.WriteBit(0);
data << uint8(TabId); uint32 itemCount = 0;
// remaining slots for today
data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), TabId));
data << uint8(0); // Tell client that there's no tab info in this packet
data << uint8(GUILD_BANK_MAX_SLOTS);
for (int i = 0; i < GUILD_BANK_MAX_SLOTS; ++i) for (int i = 0; i < GUILD_BANK_MAX_SLOTS; ++i)
AppendDisplayGuildBankSlot(data, tab, i); if (tab->Slots[i])
++itemCount;
data.WriteBits(itemCount, 20);
data.WriteBits(0, 22); // Tell client that there's no tab info in this packet
for (int i = 0; i < GUILD_BANK_MAX_SLOTS; ++i)
if (tab->Slots[i])
AppendDisplayGuildBankSlot(data, buffer, tab, i);
data << uint64(m_GuildBankMoney);
if (!buffer.empty())
data.append(buffer);
data << uint32(TabId);
data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetObjectGuid(), TabId));
session->SendPacket(&data); session->SendPacket(&data);
DEBUG_LOG("WORLD: Sent (SMSG_GUILD_BANK_LIST)"); DEBUG_LOG("WORLD: Sent (SMSG_GUILD_BANK_LIST), tabid %u itemCount %u", TabId, itemCount);
} }
void Guild::DisplayGuildBankMoneyUpdate(WorldSession* session) void Guild::DisplayGuildBankMoneyUpdate(WorldSession* session)
{ {
WorldPacket data(SMSG_GUILD_BANK_LIST, 8 + 1 + 4 + 1 + 1); WorldPacket data(SMSG_GUILD_BANK_LIST, 8 + 1 + 4 + 1 + 1);
data.WriteBit(0);
data.WriteBits(0, 20); // not send items
data.WriteBits(0, 22); // Tell that there's no tab info in this packet
data << uint64(GetGuildBankMoney()); data << uint64(GetGuildBankMoney());
data << uint8(0); // TabId, default 0 data << uint32(0); // TabId, default 0
data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), 0)); data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetObjectGuid(), 0));
data << uint8(0); // Tell that there's no tab info in this packet
data << uint8(0); // not send items
BroadcastPacket(&data); BroadcastPacket(&data);
DEBUG_LOG("WORLD: Sent (SMSG_GUILD_BANK_LIST)"); DEBUG_LOG("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
@ -1009,32 +1171,35 @@ void Guild::DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2)
{ {
GuildBankTab const* tab = m_TabListMap[TabId]; GuildBankTab const* tab = m_TabListMap[TabId];
ByteBuffer buffer;
WorldPacket data(SMSG_GUILD_BANK_LIST, 1200); WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
data << uint64(GetGuildBankMoney()); data.WriteBit(0);
data << uint8(TabId);
size_t rempos = data.wpos();
data << uint32(0); // item withdraw amount, will be filled later
data << uint8(0); // Tell client that there's no tab info in this packet
if (slot2 == -1) // single item in slot1 if (slot2 == -1) // single item in slot1
{ data.WriteBits(1, 20); // item count
data << uint8(1); // item count
AppendDisplayGuildBankSlot(data, tab, slot1);
}
else // 2 items (in slot1 and slot2) else // 2 items (in slot1 and slot2)
{ data.WriteBits(2, 20); // item count
data << uint8(2); // item count data.WriteBits(0, 22); // Tell client that there's no tab info in this packet
if (slot2 == -1)
AppendDisplayGuildBankSlot(data, buffer, tab, slot1);
else
{
if (slot1 > slot2) if (slot1 > slot2)
std::swap(slot1, slot2); std::swap(slot1, slot2);
AppendDisplayGuildBankSlot(data, tab, slot1); AppendDisplayGuildBankSlot(data, buffer, tab, slot1);
AppendDisplayGuildBankSlot(data, tab, slot2); AppendDisplayGuildBankSlot(data, buffer, tab, slot2);
} }
data << uint64(GetGuildBankMoney());
if (!buffer.empty())
data.append(buffer);
data << uint32(TabId);
size_t rempos = data.wpos();
data << uint32(0); // item withdraw amount, will be filled later
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
{ {
Player* player = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first)); Player* player = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first));
@ -1056,19 +1221,23 @@ void Guild::DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec cons
{ {
GuildBankTab const* tab = m_TabListMap[TabId]; GuildBankTab const* tab = m_TabListMap[TabId];
ByteBuffer buffer;
WorldPacket data(SMSG_GUILD_BANK_LIST, 1200); WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
data.WriteBit(0);
data.WriteBits(slots.size(), 20); // updates count
data.WriteBits(0, 22); // Tell client that there's no tab info in this packet
for (GuildItemPosCountVec::const_iterator itr = slots.begin(); itr != slots.end(); ++itr)
AppendDisplayGuildBankSlot(data, buffer, tab, itr->Slot);
data << uint64(GetGuildBankMoney()); data << uint64(GetGuildBankMoney());
data << uint8(TabId); if (!buffer.empty())
data.append(buffer);
data << uint32(TabId);
size_t rempos = data.wpos(); size_t rempos = data.wpos();
data << uint32(0); // item withdraw amount, will be filled later data << uint32(0); // item withdraw amount, will be filled later
data << uint8(0); // Tell client that there's no tab info in this packet
data << uint8(slots.size()); // updates count
for (GuildItemPosCountVec::const_iterator itr = slots.begin(); itr != slots.end(); ++itr)
AppendDisplayGuildBankSlot(data, tab, itr->Slot);
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
{ {
@ -1100,23 +1269,32 @@ Item* Guild::GetItem(uint8 TabId, uint8 SlotId)
void Guild::DisplayGuildBankTabsInfo(WorldSession* session) void Guild::DisplayGuildBankTabsInfo(WorldSession* session)
{ {
WorldPacket data(SMSG_GUILD_BANK_LIST, 500); WorldPacket data(SMSG_GUILD_BANK_LIST, 500);
data.WriteBit(0);
data << uint64(GetGuildBankMoney()); data.WriteBits(0, 20); // Do not send tab content
data << uint8(0); // TabInfo packet must be for TabId 0 data.WriteBits(GetPurchasedTabs(), 22); // here is the number of tabs
data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), 0));
data << uint8(1); // Tell client that this packet includes tab info
data << uint8(GetPurchasedTabs()); // here is the number of tabs
for (uint8 i = 0; i < GetPurchasedTabs(); ++i) for (uint8 i = 0; i < GetPurchasedTabs(); ++i)
{ {
data << m_TabListMap[i]->Name.c_str(); data.WriteBits(m_TabListMap[i]->Icon.length(), 9);
data << m_TabListMap[i]->Icon.c_str(); data.WriteBits(m_TabListMap[i]->Name.length(), 7);
} }
data << uint8(0); // Do not send tab content
data.FlushBits();
for (uint8 i = 0; i < GetPurchasedTabs(); ++i)
{
data.WriteStringData(m_TabListMap[i]->Icon);
data << uint32(i);
data.WriteStringData(m_TabListMap[i]->Name);
}
data << uint64(GetGuildBankMoney());
data << uint32(0); // TabInfo packet must be for TabId 0
data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), 0));
session->SendPacket(&data); session->SendPacket(&data);
DEBUG_LOG("WORLD: Sent (SMSG_GUILD_BANK_LIST)"); DEBUG_LOG("WORLD: Sent SMSG_GUILD_BANK_LIST (Guild::DisplayGuildBankTabsInfo)");
} }
void Guild::CreateNewBankTab() void Guild::CreateNewBankTab()
@ -1246,15 +1424,15 @@ void Guild::LoadGuildBankFromDB()
void Guild::SendMoneyInfo(WorldSession* session, uint32 LowGuid) void Guild::SendMoneyInfo(WorldSession* session, uint32 LowGuid)
{ {
WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4); WorldPacket data(SMSG_GUILD_BANK_MONEY_WITHDRAWN, 8);
data << uint32(GetMemberMoneyWithdrawRem(LowGuid)); data << uint64(GetMemberMoneyWithdrawRem(LowGuid));
session->SendPacket(&data); session->SendPacket(&data);
DEBUG_LOG("WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN"); DEBUG_LOG("WORLD: Sent SMSG_GUILD_BANK_MONEY_WITHDRAWN");
} }
bool Guild::MemberMoneyWithdraw(uint32 amount, uint32 LowGuid) bool Guild::MemberMoneyWithdraw(uint64 amount, uint32 LowGuid)
{ {
uint32 MoneyWithDrawRight = GetMemberMoneyWithdrawRem(LowGuid); uint64 MoneyWithDrawRight = GetMemberMoneyWithdrawRem(LowGuid);
if (MoneyWithDrawRight < amount || GetGuildBankMoney() < amount) if (MoneyWithDrawRight < amount || GetGuildBankMoney() < amount)
return false; return false;
@ -1339,7 +1517,7 @@ uint32 Guild::GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId)
return itr->second.BankRemSlotsTab[TabId]; return itr->second.BankRemSlotsTab[TabId];
} }
uint32 Guild::GetMemberMoneyWithdrawRem(uint32 LowGuid) uint64 Guild::GetMemberMoneyWithdrawRem(uint32 LowGuid)
{ {
MemberList::iterator itr = members.find(LowGuid); MemberList::iterator itr = members.find(LowGuid);
if (itr == members.end()) if (itr == members.end())
@ -1462,7 +1640,6 @@ bool Guild::LoadBankRightsFromDB(QueryResult* guildBankTabRightsResult)
uint16 SlotPerDay = fields[4].GetUInt16(); uint16 SlotPerDay = fields[4].GetUInt16();
SetBankRightsAndSlots(rankId, TabId, right, SlotPerDay, false); SetBankRightsAndSlots(rankId, TabId, right, SlotPerDay, false);
} }
while (guildBankTabRightsResult->NextRow()); while (guildBankTabRightsResult->NextRow());
@ -1554,7 +1731,6 @@ void Guild::LoadGuildBankEventLogFromDB()
// add event to list // add event to list
// events are ordered from oldest (in beginning) to latest (in the end) // events are ordered from oldest (in beginning) to latest (in the end)
m_GuildBankEventLog_Money.push_front(NewEvent); m_GuildBankEventLog_Money.push_front(NewEvent);
} }
while (result->NextRow()); while (result->NextRow());
delete result; delete result;
@ -1565,66 +1741,39 @@ void Guild::DisplayGuildBankLogs(WorldSession* session, uint8 TabId)
if (TabId > GUILD_BANK_MAX_TABS) if (TabId > GUILD_BANK_MAX_TABS)
return; return;
ByteBuffer buffer;
bool hasCashFlow = GetLevel() >= 5 && TabId == GUILD_BANK_MAX_TABS; // has Cash Flow perk
WorldPacket data(SMSG_GUILD_BANK_LOG_QUERY_RESULT, m_GuildBankEventLog_Money.size() * (4 * 4 + 1) + 1 + 1);
data.WriteBit(hasCashFlow);
if (TabId == GUILD_BANK_MAX_TABS) if (TabId == GUILD_BANK_MAX_TABS)
{ {
// Here we display money logs // Here we display money logs
WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, m_GuildBankEventLog_Money.size() * (4 * 4 + 1) + 1 + 1); data.WriteBits(m_GuildBankEventLog_Money.size(), 23);
data << uint8(TabId); // Here GUILD_BANK_MAX_TABS for (GuildBankEventLog::iterator itr = m_GuildBankEventLog_Money.begin(); itr != m_GuildBankEventLog_Money.end(); ++itr)
data << uint8(m_GuildBankEventLog_Money.size()); // number of log entries itr->WriteData(data, buffer);
for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Money.begin(); itr != m_GuildBankEventLog_Money.end(); ++itr)
{
data << uint8(itr->EventType);
data << ObjectGuid(HIGHGUID_PLAYER, itr->PlayerGuid);
if (itr->EventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
itr->EventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
itr->EventType == GUILD_BANK_LOG_REPAIR_MONEY ||
itr->EventType == GUILD_BANK_LOG_UNK1 ||
itr->EventType == GUILD_BANK_LOG_UNK2)
{
data << uint32(itr->ItemOrMoney);
}
else
{
data << uint32(itr->ItemOrMoney);
data << uint32(itr->ItemStackCount);
if (itr->EventType == GUILD_BANK_LOG_MOVE_ITEM || itr->EventType == GUILD_BANK_LOG_MOVE_ITEM2)
data << uint8(itr->DestTabId); // moved tab
}
data << uint32(time(NULL) - itr->TimeStamp);
}
session->SendPacket(&data);
} }
else else
{ {
// here we display current tab logs // here we display current tab logs
WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, m_GuildBankEventLog_Item[TabId].size() * (4 * 4 + 1 + 1) + 1 + 1);
data << uint8(TabId); // Here a real Tab Id
// number of log entries // number of log entries
data << uint8(m_GuildBankEventLog_Item[TabId].size()); data.WriteBits(m_GuildBankEventLog_Item[TabId].size(), 23);
for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Item[TabId].begin(); itr != m_GuildBankEventLog_Item[TabId].end(); ++itr) for (GuildBankEventLog::iterator itr = m_GuildBankEventLog_Item[TabId].begin(); itr != m_GuildBankEventLog_Item[TabId].end(); ++itr)
{ itr->WriteData(data, buffer);
data << uint8(itr->EventType);
data << ObjectGuid(HIGHGUID_PLAYER, itr->PlayerGuid);
if (itr->EventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
itr->EventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
itr->EventType == GUILD_BANK_LOG_REPAIR_MONEY ||
itr->EventType == GUILD_BANK_LOG_UNK1 ||
itr->EventType == GUILD_BANK_LOG_UNK2)
{
data << uint32(itr->ItemOrMoney);
}
else
{
data << uint32(itr->ItemOrMoney);
data << uint32(itr->ItemStackCount);
if (itr->EventType == GUILD_BANK_LOG_MOVE_ITEM || itr->EventType == GUILD_BANK_LOG_MOVE_ITEM2)
data << uint8(itr->DestTabId); // moved tab
}
data << uint32(time(NULL) - itr->TimeStamp);
}
session->SendPacket(&data);
} }
DEBUG_LOG("WORLD: Sent (MSG_GUILD_BANK_LOG_QUERY)"); if (!buffer.empty())
{
data.FlushBits();
data.append(buffer);
}
data << uint32(TabId);
if (hasCashFlow)
data << uint64(0); // cash flow contribution
session->SendPacket(&data);
DEBUG_LOG("WORLD: Sent (SMSG_GUILD_BANK_LOG_QUERY_RESULT)");
} }
void Guild::LogBankEvent(uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount, uint8 DestTabId) void Guild::LogBankEvent(uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount, uint8 DestTabId)
@ -1676,40 +1825,38 @@ bool Guild::AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot
return true; return true;
} }
void Guild::AppendDisplayGuildBankSlot(WorldPacket& data, GuildBankTab const* tab, int slot) void Guild::AppendDisplayGuildBankSlot(WorldPacket& data, ByteBuffer& buffer, GuildBankTab const* tab, int slot)
{ {
Item* pItem = tab->Slots[slot]; Item* pItem = tab->Slots[slot];
uint32 entry = pItem ? pItem->GetEntry() : 0; uint32 entry = pItem ? pItem->GetEntry() : 0;
data << uint8(slot); uint32 enchCount = 0;
data << uint32(entry);
if (entry) if (entry)
{ {
data << uint32(0); // 3.3.0 (0x8000, 0x8020)
data << uint32(pItem->GetItemRandomPropertyId()); // random item property id + 8
if (pItem->GetItemRandomPropertyId())
data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor + 4
data << uint32(pItem->GetCount()); // +12 ITEM_FIELD_STACK_COUNT
data << uint32(0); // +16 Unknown value
data << uint8(0); // +20
uint8 enchCount = 0;
size_t enchCountPos = data.wpos();
data << uint8(enchCount); // number of enchantments
for (uint32 i = PERM_ENCHANTMENT_SLOT; i < MAX_ENCHANTMENT_SLOT; ++i) for (uint32 i = PERM_ENCHANTMENT_SLOT; i < MAX_ENCHANTMENT_SLOT; ++i)
{ {
if (uint32 enchId = pItem->GetEnchantmentId(EnchantmentSlot(i))) if (uint32 enchId = pItem->GetEnchantmentId(EnchantmentSlot(i)))
{ {
data << uint8(i); buffer << uint32(enchId);
data << uint32(enchId); buffer << uint32(i);
++enchCount; ++enchCount;
} }
} }
data.put<uint8>(enchCountPos, enchCount);
} }
data.WriteBit(0); // unk
data.WriteBits(enchCount, 23); // number of enchantments
buffer << uint32(0);
buffer << uint32(0);
buffer << uint32(0);
buffer << uint32(entry ? pItem->GetCount() : 0); // ITEM_FIELD_STACK_COUNT
buffer << uint32(slot);
buffer << uint32(0);
buffer << uint32(entry);
buffer << uint32(entry ? pItem->GetItemRandomPropertyId() : 0); // random item property id
buffer << uint32(entry ? abs(pItem->GetSpellCharges()) : 0); // Spell charges
buffer << uint32(entry ? pItem->GetItemSuffixFactor() : 0); // SuffixFactor
} }
Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pItem) Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pItem)
@ -1963,9 +2110,10 @@ void Guild::SendGuildBankTabText(WorldSession* session, uint8 TabId)
{ {
GuildBankTab const* tab = m_TabListMap[TabId]; GuildBankTab const* tab = m_TabListMap[TabId];
WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1 + tab->Text.size() + 1); WorldPacket data(SMSG_GUILD_BANK_TEXT, 1 + tab->Text.size() + 1);
data << uint8(TabId); data.WriteBits(tab->Text.length(), 14);
data << tab->Text; data << uint32(TabId);
data.WriteStringData(tab->Text);
if (session) if (session)
session->SendPacket(&data); session->SendPacket(&data);
@ -2097,7 +2245,6 @@ void Guild::SwapItems(Player* pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankTa
DisplayGuildBankContentUpdate(BankTabDst, BankTabSlotDst); DisplayGuildBankContentUpdate(BankTabDst, BankTabSlotDst);
} }
void Guild::MoveFromBankToChar(Player* pl, uint8 BankTab, uint8 BankTabSlot, uint8 PlayerBag, uint8 PlayerSlot, uint32 SplitedAmount) void Guild::MoveFromBankToChar(Player* pl, uint8 BankTab, uint8 BankTabSlot, uint8 PlayerBag, uint8 PlayerSlot, uint32 SplitedAmount)
{ {
Item* pItemBank = GetItem(BankTab, BankTabSlot); Item* pItemBank = GetItem(BankTab, BankTabSlot);
@ -2246,7 +2393,6 @@ void Guild::MoveFromBankToChar(Player* pl, uint8 BankTab, uint8 BankTabSlot, uin
DisplayGuildBankContentUpdate(BankTab, BankTabSlot); DisplayGuildBankContentUpdate(BankTab, BankTabSlot);
} }
void Guild::MoveFromCharToBank(Player* pl, uint8 PlayerBag, uint8 PlayerSlot, uint8 BankTab, uint8 BankTabSlot, uint32 SplitedAmount) void Guild::MoveFromCharToBank(Player* pl, uint8 PlayerBag, uint8 PlayerSlot, uint8 BankTab, uint8 BankTabSlot, uint32 SplitedAmount)
{ {
Item* pItemBank = GetItem(BankTab, BankTabSlot); Item* pItemBank = GetItem(BankTab, BankTabSlot);
@ -2455,3 +2601,76 @@ bool GuildItemPosCount::isContainedIn(GuildItemPosCountVec const& vec) const
return false; return false;
} }
void GuildEventLogEntry::WriteData(WorldPacket& data, ByteBuffer& buffer)
{
// Player 1
ObjectGuid guid1 = ObjectGuid(HIGHGUID_PLAYER, PlayerGuid1);
// Player 2 not for left/join guild events
ObjectGuid guid2 = ObjectGuid(HIGHGUID_PLAYER, PlayerGuid2);
data.WriteGuidMask<2, 4>(guid1);
data.WriteGuidMask<7, 6>(guid2);
data.WriteGuidMask<3>(guid1);
data.WriteGuidMask<3, 5>(guid2);
data.WriteGuidMask<7, 5, 0>(guid1);
data.WriteGuidMask<4, 2, 0, 1>(guid2);
data.WriteGuidMask<1, 6>(guid1);
buffer.WriteGuidBytes<3, 2, 5>(guid2);
// New Rank - only for promote/demote guild events
buffer << uint8(NewRank);
buffer.WriteGuidBytes<4>(guid2);
buffer.WriteGuidBytes<0, 4>(guid1);
// Event timestamp
buffer << uint32(time(NULL) - TimeStamp);
buffer.WriteGuidBytes<7, 3>(guid1);
buffer.WriteGuidBytes<0, 6, 7>(guid2);
buffer.WriteGuidBytes<5>(guid1);
// Event type
buffer << uint8(EventType);
buffer.WriteGuidBytes<1>(guid2);
buffer.WriteGuidBytes<2, 6, 1>(guid1);
}
void GuildBankEventLogEntry::WriteData(WorldPacket& data, ByteBuffer& buffer)
{
ObjectGuid logGuid = ObjectGuid(HIGHGUID_PLAYER, PlayerGuid);
bool hasItem = EventType == GUILD_BANK_LOG_DEPOSIT_ITEM || EventType == GUILD_BANK_LOG_WITHDRAW_ITEM ||
EventType == GUILD_BANK_LOG_MOVE_ITEM || EventType == GUILD_BANK_LOG_MOVE_ITEM2;
bool itemMoved = EventType == GUILD_BANK_LOG_MOVE_ITEM || EventType == GUILD_BANK_LOG_MOVE_ITEM2;
bool hasStack = hasItem && ItemStackCount > 1 || itemMoved;
data.WriteBit(isMoneyEvent());
data.WriteGuidMask<4, 1>(logGuid);
data.WriteBit(hasItem);
data.WriteBit(hasStack);
data.WriteGuidMask<2, 5, 3, 6, 0>(logGuid);
data.WriteBit(itemMoved);
data.WriteGuidMask<7>(logGuid);
buffer.WriteGuidBytes<6, 1, 5>(logGuid);
if (hasStack)
buffer << uint32(ItemStackCount);
buffer << uint8(EventType);
buffer.WriteGuidBytes<2, 4, 0, 7, 3>(logGuid);
if (hasItem)
buffer << uint32(ItemOrMoney);
buffer << uint32(time(NULL) - TimeStamp);
if (isMoneyEvent())
buffer << uint64(ItemOrMoney);
if (itemMoved)
buffer << uint8(DestTabId); // moved tab
}

View file

@ -19,7 +19,7 @@
#ifndef MANGOSSERVER_GUILD_H #ifndef MANGOSSERVER_GUILD_H
#define MANGOSSERVER_GUILD_H #define MANGOSSERVER_GUILD_H
#define WITHDRAW_MONEY_UNLIMITED 0xFFFFFFFF #define WITHDRAW_MONEY_UNLIMITED UI64LIT(0xFFFFFFFFFFFFFFFF)
#define WITHDRAW_SLOT_UNLIMITED 0xFFFFFFFF #define WITHDRAW_SLOT_UNLIMITED 0xFFFFFFFF
#include "Common.h" #include "Common.h"
@ -29,9 +29,6 @@
class Item; class Item;
#define GUILD_RANKS_MIN_COUNT 5
#define GUILD_RANKS_MAX_COUNT 10
enum GuildDefaultRanks enum GuildDefaultRanks
{ {
// these ranks can be modified, but they cannot be deleted // these ranks can be modified, but they cannot be deleted
@ -46,25 +43,28 @@ enum GuildDefaultRanks
enum GuildRankRights enum GuildRankRights
{ {
GR_RIGHT_EMPTY = 0x00000040, GR_RIGHT_EMPTY = 0x00000040,
GR_RIGHT_GCHATLISTEN = 0x00000041, GR_RIGHT_GCHATLISTEN = 0x00000041,
GR_RIGHT_GCHATSPEAK = 0x00000042, GR_RIGHT_GCHATSPEAK = 0x00000042,
GR_RIGHT_OFFCHATLISTEN = 0x00000044, GR_RIGHT_OFFCHATLISTEN = 0x00000044,
GR_RIGHT_OFFCHATSPEAK = 0x00000048, GR_RIGHT_OFFCHATSPEAK = 0x00000048,
GR_RIGHT_PROMOTE = 0x000000C0, GR_RIGHT_PROMOTE = 0x000000C0,
GR_RIGHT_DEMOTE = 0x00000140, GR_RIGHT_DEMOTE = 0x00000140,
GR_RIGHT_INVITE = 0x00000050, GR_RIGHT_INVITE = 0x00000050,
GR_RIGHT_REMOVE = 0x00000060, GR_RIGHT_REMOVE = 0x00000060,
GR_RIGHT_SETMOTD = 0x00001040, GR_RIGHT_SETMOTD = 0x00001040,
GR_RIGHT_EPNOTE = 0x00002040, GR_RIGHT_EPNOTE = 0x00002040,
GR_RIGHT_VIEWOFFNOTE = 0x00004040, GR_RIGHT_VIEWOFFNOTE = 0x00004040,
GR_RIGHT_EOFFNOTE = 0x00008040, GR_RIGHT_EOFFNOTE = 0x00008040,
GR_RIGHT_MODIFY_GUILD_INFO = 0x00010040, GR_RIGHT_MODIFY_GUILD_INFO = 0x00010040,
GR_RIGHT_WITHDRAW_GOLD_LOCK = 0x00020000, // remove money withdraw capacity GR_RIGHT_WITHDRAW_GOLD_LOCK = 0x00020000, // remove money withdraw capacity
GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair
GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold
GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk
GR_RIGHT_ALL = 0x001DF1FF GR_RIGHT_REQUIRES_AUTHENTICATOR = 0x00200000,
GR_RIGHT_MODIFY_BANK_TABS = 0x00400000, // cata?
GR_RIGHT_REMOVE_GUILD_EVENT = 0x00800000, // wotlk
GR_RIGHT_ALL = 0x00DDF1FF,
}; };
enum Typecommand enum Typecommand
@ -74,36 +74,44 @@ enum Typecommand
GUILD_QUIT_S = 0x03, GUILD_QUIT_S = 0x03,
// 0x05? // 0x05?
GUILD_FOUNDER_S = 0x0E, GUILD_FOUNDER_S = 0x0E,
GUILD_UNK1 = 0x13, GUILD_UNK1 = 0x14,
GUILD_UNK2 = 0x14 GUILD_UNK2 = 0x15,
}; };
enum CommandErrors enum CommandErrors
{ {
ERR_PLAYER_NO_MORE_IN_GUILD = 0x00, ERR_PLAYER_NO_MORE_IN_GUILD = 0x00,
ERR_GUILD_INTERNAL = 0x01, ERR_GUILD_INTERNAL = 0x01,
ERR_ALREADY_IN_GUILD = 0x02, ERR_ALREADY_IN_GUILD = 0x02,
ERR_ALREADY_IN_GUILD_S = 0x03, ERR_ALREADY_IN_GUILD_S = 0x03,
ERR_INVITED_TO_GUILD = 0x04, ERR_INVITED_TO_GUILD = 0x04,
ERR_ALREADY_INVITED_TO_GUILD_S = 0x05, ERR_ALREADY_INVITED_TO_GUILD_S = 0x05,
ERR_GUILD_NAME_INVALID = 0x06, ERR_GUILD_NAME_INVALID = 0x06,
ERR_GUILD_NAME_EXISTS_S = 0x07, ERR_GUILD_NAME_EXISTS_S = 0x07,
ERR_GUILD_LEADER_LEAVE = 0x08, ERR_GUILD_LEADER_LEAVE = 0x08,
ERR_GUILD_PERMISSIONS = 0x08, ERR_GUILD_PERMISSIONS = 0x08,
ERR_GUILD_PLAYER_NOT_IN_GUILD = 0x09, ERR_GUILD_PLAYER_NOT_IN_GUILD = 0x09,
ERR_GUILD_PLAYER_NOT_IN_GUILD_S = 0x0A, ERR_GUILD_PLAYER_NOT_IN_GUILD_S = 0x0A,
ERR_GUILD_PLAYER_NOT_FOUND_S = 0x0B, ERR_GUILD_PLAYER_NOT_FOUND_S = 0x0B,
ERR_GUILD_NOT_ALLIED = 0x0C, ERR_GUILD_NOT_ALLIED = 0x0C,
ERR_GUILD_RANK_TOO_HIGH_S = 0x0D, ERR_GUILD_RANK_TOO_HIGH_S = 0x0D,
ERR_GUILD_RANK_TOO_LOW_S = 0x0E, ERR_GUILD_RANK_TOO_LOW_S = 0x0E,
ERR_GUILD_RANKS_LOCKED = 0x11, ERR_GUILD_RANKS_LOCKED = 0x11,
ERR_GUILD_RANK_IN_USE = 0x12, ERR_GUILD_RANK_IN_USE = 0x12,
ERR_GUILD_IGNORING_YOU_S = 0x13, ERR_GUILD_IGNORING_YOU_S = 0x13,
ERR_GUILD_UNK1 = 0x14, ERR_GUILD_UNK1 = 0x14,
ERR_GUILD_WITHDRAW_LIMIT = 0x19, ERR_GUILD_WITHDRAW_LIMIT = 0x19,
ERR_GUILD_NOT_ENOUGH_MONEY = 0x1A, ERR_GUILD_NOT_ENOUGH_MONEY = 0x1A,
ERR_GUILD_BANK_FULL = 0x1C, ERR_GUILD_BANK_FULL = 0x1C,
ERR_GUILD_ITEM_NOT_FOUND = 0x1D ERR_GUILD_ITEM_NOT_FOUND = 0x1D,
ERR_GUILD_TOO_MUCH_MONEY = 0x1F,
ERR_GUILD_BANK_WRONG_TAB = 0x20,
ERR_RANK_REQUIRES_AUTHENTICATOR = 0x22,
ERR_GUILD_BANK_VOUCHER_FAILED = 0x23,
ERR_GUILD_TRIAL_ACCOUNT = 0x24,
ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL = 0x25,
ERR_GUILD_MOVE_STARTING = 0x26,
ERR_GUILD_REP_TOO_LOW = 0x27,
}; };
enum GuildEvents enum GuildEvents
@ -117,7 +125,7 @@ enum GuildEvents
GE_LEADER_IS = 0x07, GE_LEADER_IS = 0x07,
GE_LEADER_CHANGED = 0x08, GE_LEADER_CHANGED = 0x08,
GE_DISBANDED = 0x09, GE_DISBANDED = 0x09,
GE_TABARDCHANGE = 0x0A, //GE_TABARDCHANGE = 0x0A, // not exists in 4.3.4
GE_UPDATE_RANK = 0x0B, // string, string EVENT_GUILD_ROSTER_UPDATE tab content change? GE_UPDATE_RANK = 0x0B, // string, string EVENT_GUILD_ROSTER_UPDATE tab content change?
GE_CREATE_RANK = 0x0C, // EVENT_GUILD_ROSTER_UPDATE GE_CREATE_RANK = 0x0C, // EVENT_GUILD_ROSTER_UPDATE
GE_DELETE_RANK = 0x0D, GE_DELETE_RANK = 0x0D,
@ -129,7 +137,7 @@ enum GuildEvents
GE_BANKTAB_PURCHASED = 0x13, // EVENT_GUILDBANK_UPDATE_TABS GE_BANKTAB_PURCHASED = 0x13, // EVENT_GUILDBANK_UPDATE_TABS
GE_BANKTAB_UPDATED = 0x14, // EVENT_GUILDBANK_UPDATE_TABS GE_BANKTAB_UPDATED = 0x14, // EVENT_GUILDBANK_UPDATE_TABS
GE_GUILDBANK_UPDATE_MONEY = 0x15, // EVENT_GUILDBANK_UPDATE_MONEY, string 0000000000002710 is 1 gold GE_GUILDBANK_UPDATE_MONEY = 0x15, // EVENT_GUILDBANK_UPDATE_MONEY, string 0000000000002710 is 1 gold
GE_GUILD_BANK_MONEY_WITHDRAWN = 0x16, // MSG_GUILD_BANK_MONEY_WITHDRAWN //GE_GUILD_BANK_MONEY_WITHDRAWN = 0x16, // not exists in 4.3.4
GE_GUILDBANK_TEXT_CHANGED = 0x17 // EVENT_GUILDBANK_TEXT_CHANGED GE_GUILDBANK_TEXT_CHANGED = 0x17 // EVENT_GUILDBANK_TEXT_CHANGED
}; };
@ -138,15 +146,20 @@ enum PetitionTurns
PETITION_TURN_OK = 0, PETITION_TURN_OK = 0,
PETITION_TURN_ALREADY_IN_GUILD = 2, PETITION_TURN_ALREADY_IN_GUILD = 2,
PETITION_TURN_NEED_MORE_SIGNATURES = 4, PETITION_TURN_NEED_MORE_SIGNATURES = 4,
PETITION_TURN_GUILD_PERMISSIONS = 11,
PETITION_TURN_GUILD_NAME_INVALID = 12,
}; };
enum PetitionSigns enum PetitionSigns
{ {
PETITION_SIGN_OK = 0, PETITION_SIGN_OK = 0,
PETITION_SIGN_ALREADY_SIGNED = 1, PETITION_SIGN_ALREADY_SIGNED = 1,
PETITION_SIGN_ALREADY_IN_GUILD = 2, PETITION_SIGN_ALREADY_IN_GUILD = 2,
PETITION_SIGN_CANT_SIGN_OWN = 3, PETITION_SIGN_CANT_SIGN_OWN = 3,
PETITION_SIGN_NOT_SERVER = 4, PETITION_SIGN_NOT_SAME_SERVER = 5,
PETITION_SIGN_PETITION_FULL = 8,
PETITION_SIGN_ALREADY_SIGNED_OTHER = 10,
PETITION_SIGN_RESTRICTED_ACCOUNT = 11,
}; };
enum GuildBankRights enum GuildBankRights
@ -161,15 +174,16 @@ enum GuildBankRights
enum GuildBankEventLogTypes enum GuildBankEventLogTypes
{ {
GUILD_BANK_LOG_DEPOSIT_ITEM = 1, GUILD_BANK_LOG_DEPOSIT_ITEM = 1,
GUILD_BANK_LOG_WITHDRAW_ITEM = 2, GUILD_BANK_LOG_WITHDRAW_ITEM = 2,
GUILD_BANK_LOG_MOVE_ITEM = 3, GUILD_BANK_LOG_MOVE_ITEM = 3,
GUILD_BANK_LOG_DEPOSIT_MONEY = 4, GUILD_BANK_LOG_DEPOSIT_MONEY = 4,
GUILD_BANK_LOG_WITHDRAW_MONEY = 5, GUILD_BANK_LOG_WITHDRAW_MONEY = 5,
GUILD_BANK_LOG_REPAIR_MONEY = 6, GUILD_BANK_LOG_REPAIR_MONEY = 6,
GUILD_BANK_LOG_MOVE_ITEM2 = 7, GUILD_BANK_LOG_MOVE_ITEM2 = 7,
GUILD_BANK_LOG_UNK1 = 8, GUILD_BANK_LOG_UNK1 = 8,
GUILD_BANK_LOG_UNK2 = 9, GUILD_BANK_LOG_BUY_SLOT = 9,
GUILD_BANK_LOG_CASH_FLOW_DEPOSIT = 10,
}; };
enum GuildEventLogTypes enum GuildEventLogTypes
@ -192,7 +206,16 @@ enum GuildEmblem
ERR_GUILDEMBLEM_INVALIDVENDOR = 5 ERR_GUILDEMBLEM_INVALIDVENDOR = 5
}; };
inline uint32 GetGuildBankTabPrice(uint8 Index) enum GuildMemberFlags
{
GUILDMEMBER_STATUS_NONE = 0x0000,
GUILDMEMBER_STATUS_ONLINE = 0x0001,
GUILDMEMBER_STATUS_AFK = 0x0002,
GUILDMEMBER_STATUS_DND = 0x0004,
GUILDMEMBER_STATUS_MOBILE = 0x0008,
};
inline uint64 GetGuildBankTabPrice(uint8 Index)
{ {
switch (Index) switch (Index)
{ {
@ -214,6 +237,8 @@ struct GuildEventLogEntry
uint32 PlayerGuid2; uint32 PlayerGuid2;
uint8 NewRank; uint8 NewRank;
uint64 TimeStamp; uint64 TimeStamp;
void WriteData(WorldPacket& data, ByteBuffer& buffer);
}; };
struct GuildBankEventLogEntry struct GuildBankEventLogEntry
@ -231,6 +256,8 @@ struct GuildBankEventLogEntry
EventType == GUILD_BANK_LOG_WITHDRAW_MONEY || EventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
EventType == GUILD_BANK_LOG_REPAIR_MONEY; EventType == GUILD_BANK_LOG_REPAIR_MONEY;
} }
void WriteData(WorldPacket& data, ByteBuffer& buffer);
}; };
struct GuildBankTab struct GuildBankTab
@ -310,7 +337,9 @@ class Guild
typedef UNORDERED_MAP<uint32, MemberSlot> MemberList; typedef UNORDERED_MAP<uint32, MemberSlot> MemberList;
typedef std::vector<RankInfo> RankList; typedef std::vector<RankInfo> RankList;
uint32 GetId() { return m_Id; } uint32 GetId() const { return m_Id; }
uint32 GetLevel() const { return m_Level; }
ObjectGuid GetObjectGuid() const { return ObjectGuid(HIGHGUID_GUILD, 0, m_Id); }
ObjectGuid GetLeaderGuid() const { return m_LeaderGuid; } ObjectGuid GetLeaderGuid() const { return m_LeaderGuid; }
std::string const& GetName() const { return m_Name; } std::string const& GetName() const { return m_Name; }
std::string const& GetMOTD() const { return MOTD; } std::string const& GetMOTD() const { return MOTD; }
@ -348,6 +377,8 @@ class Guild
void BroadcastAddonToOfficers(WorldSession* session, const std::string& msg, const std::string& prefix); void BroadcastAddonToOfficers(WorldSession* session, const std::string& msg, const std::string& prefix);
void BroadcastPacketToRank(WorldPacket* packet, uint32 rankId); void BroadcastPacketToRank(WorldPacket* packet, uint32 rankId);
void BroadcastPacket(WorldPacket* packet); void BroadcastPacket(WorldPacket* packet);
// for calendar
void MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 maxLevel, uint32 minRank);
void BroadcastEvent(GuildEvents event, ObjectGuid guid, char const* str1 = NULL, char const* str2 = NULL, char const* str3 = NULL); void BroadcastEvent(GuildEvents event, ObjectGuid guid, char const* str1 = NULL, char const* str2 = NULL, char const* str3 = NULL);
void BroadcastEvent(GuildEvents event, char const* str1 = NULL, char const* str2 = NULL, char const* str3 = NULL) void BroadcastEvent(GuildEvents event, char const* str1 = NULL, char const* str2 = NULL, char const* str3 = NULL)
@ -365,7 +396,8 @@ class Guild
} }
void CreateRank(std::string name, uint32 rights); void CreateRank(std::string name, uint32 rights);
void DelRank(); void DelRank(uint32 rankId);
void SwitchRank(uint32 rankId, bool up);
std::string GetRankName(uint32 rankId); std::string GetRankName(uint32 rankId);
uint32 GetRankRights(uint32 rankId); uint32 GetRankRights(uint32 rankId);
uint32 GetRanksSize() const { return m_Ranks.size(); } uint32 GetRanksSize() const { return m_Ranks.size(); }
@ -377,6 +409,15 @@ class Guild
return ((GetRankRights(rankId) & right) != GR_RIGHT_EMPTY) ? true : false; return ((GetRankRights(rankId) & right) != GR_RIGHT_EMPTY) ? true : false;
} }
bool HasMembersWithRank(uint32 rankId) const
{
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
if (itr->second.RankId == rankId)
return true;
return false;
}
int32 GetRank(ObjectGuid guid) int32 GetRank(ObjectGuid guid)
{ {
MemberSlot* slot = GetMemberSlot(guid); MemberSlot* slot = GetMemberSlot(guid);
@ -400,6 +441,7 @@ class Guild
void Roster(WorldSession* session = NULL); // NULL = broadcast void Roster(WorldSession* session = NULL); // NULL = broadcast
void Query(WorldSession* session); void Query(WorldSession* session);
void QueryRanks(WorldSession* session);
// Guild EventLog // Guild EventLog
void LoadGuildEventLogFromDB(); void LoadGuildEventLogFromDB();
@ -429,13 +471,13 @@ class Guild
void LoadGuildBankFromDB(); void LoadGuildBankFromDB();
// Money deposit/withdraw // Money deposit/withdraw
void SendMoneyInfo(WorldSession* session, uint32 LowGuid); void SendMoneyInfo(WorldSession* session, uint32 LowGuid);
bool MemberMoneyWithdraw(uint32 amount, uint32 LowGuid); bool MemberMoneyWithdraw(uint64 amount, uint32 LowGuid);
uint64 GetGuildBankMoney() { return m_GuildBankMoney; } uint64 GetGuildBankMoney() { return m_GuildBankMoney; }
void SetBankMoney(int64 money); void SetBankMoney(int64 money);
// per days // per days
bool MemberItemWithdraw(uint8 TabId, uint32 LowGuid); bool MemberItemWithdraw(uint8 TabId, uint32 LowGuid);
uint32 GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId); uint32 GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId);
uint32 GetMemberMoneyWithdrawRem(uint32 LowGuid); uint64 GetMemberMoneyWithdrawRem(uint32 LowGuid);
void SetBankMoneyPerDay(uint32 rankId, uint32 money); void SetBankMoneyPerDay(uint32 rankId, uint32 money);
void SetBankRightsAndSlots(uint32 rankId, uint8 TabId, uint32 right, uint32 SlotPerDay, bool db); void SetBankRightsAndSlots(uint32 rankId, uint8 TabId, uint32 right, uint32 SlotPerDay, bool db);
uint32 GetBankMoneyPerDay(uint32 rankId); uint32 GetBankMoneyPerDay(uint32 rankId);
@ -452,6 +494,7 @@ class Guild
void AddRank(const std::string& name, uint32 rights, uint32 money); void AddRank(const std::string& name, uint32 rights, uint32 money);
uint32 m_Id; uint32 m_Id;
uint32 m_Level;
std::string m_Name; std::string m_Name;
ObjectGuid m_LeaderGuid; ObjectGuid m_LeaderGuid;
std::string MOTD; std::string MOTD;
@ -498,7 +541,7 @@ class Guild
void DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots); void DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots);
// internal common parts for CanStore/StoreItem functions // internal common parts for CanStore/StoreItem functions
void AppendDisplayGuildBankSlot(WorldPacket& data, GuildBankTab const* tab, int32 slot); void AppendDisplayGuildBankSlot(WorldPacket& data, ByteBuffer& buffer, GuildBankTab const* tab, int32 slot);
InventoryResult _CanStoreItem_InSpecificSlot(uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32& count, bool swap, Item* pSrcItem) const; InventoryResult _CanStoreItem_InSpecificSlot(uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32& count, bool swap, Item* pSrcItem) const;
InventoryResult _CanStoreItem_InTab(uint8 tab, GuildItemPosCountVec& dest, uint32& count, bool merge, Item* pSrcItem, uint8 skip_slot) const; InventoryResult _CanStoreItem_InTab(uint8 tab, GuildItemPosCountVec& dest, uint32& count, bool merge, Item* pSrcItem, uint8 skip_slot) const;
Item* _StoreItem(uint8 tab, uint8 slot, Item* pItem, uint32 count, bool clone); Item* _StoreItem(uint8 tab, uint8 slot, Item* pItem, uint32 count, bool clone);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "12641" #define REVISION_NR "12642"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__