diff options
Diffstat (limited to 'src/server/game/Guilds/Guild.cpp')
-rwxr-xr-x | src/server/game/Guilds/Guild.cpp | 1092 |
1 files changed, 579 insertions, 513 deletions
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 7ab356ac318..e41b8ff4ac8 100755 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -43,7 +43,7 @@ inline uint32 _GetGuildBankTabPrice(uint8 tabId) } } -void Guild::SendCommandResult(WorldSession* session, GuildCommandType type, GuildCommandError errCode, const std::string& param) +void Guild::SendCommandResult(WorldSession* session, GuildCommandType type, GuildCommandError errCode, std::string const& param) { WorldPacket data(SMSG_GUILD_COMMAND_RESULT, 8 + param.size() + 1); data << uint32(type); @@ -51,7 +51,8 @@ void Guild::SendCommandResult(WorldSession* session, GuildCommandType type, Guil data << uint32(errCode); session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_COMMAND_RESULT)"); + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_COMMAND_RESULT [%s]: Type: %u, code: %u, param: %s" + , session->GetPlayerInfo().c_str(), type, errCode, param.c_str()); } void Guild::SendSaveEmblemResult(WorldSession* session, GuildEmblemError errCode) @@ -60,7 +61,7 @@ void Guild::SendSaveEmblemResult(WorldSession* session, GuildEmblemError errCode data << uint32(errCode); session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (MSG_SAVE_GUILD_EMBLEM)"); + sLog->outDebug(LOG_FILTER_GUILD, "MSG_SAVE_GUILD_EMBLEM [%s] Code: %u", session->GetPlayerInfo().c_str(), errCode); } // LogHolder @@ -115,13 +116,10 @@ inline uint32 Guild::LogHolder::GetNextGUID() return m_nextGUID; } -/////////////////////////////////////////////////////////////////////////////// // EventLogEntry void Guild::EventLogEntry::SaveToDB(SQLTransaction& trans) const { - PreparedStatement* stmt = NULL; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_EVENTLOG); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_EVENTLOG); stmt->setUInt32(0, m_guildId); stmt->setUInt32(1, m_guid); CharacterDatabase.ExecuteOrAppend(trans, stmt); @@ -154,14 +152,12 @@ void Guild::EventLogEntry::WritePacket(WorldPacket& data) const data << uint32(::time(NULL) - m_timestamp); } -/////////////////////////////////////////////////////////////////////////////// // BankEventLogEntry void Guild::BankEventLogEntry::SaveToDB(SQLTransaction& trans) const { - PreparedStatement* stmt = NULL; uint8 index = 0; - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_EVENTLOG); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_EVENTLOG); stmt->setUInt32( index, m_guildId); stmt->setUInt32(++index, m_guid); stmt->setUInt8 (++index, m_bankTabId); @@ -185,19 +181,27 @@ void Guild::BankEventLogEntry::WritePacket(WorldPacket& data) const { data << uint8(m_eventType); data << uint64(MAKE_NEW_GUID(m_playerGuid, 0, HIGHGUID_PLAYER)); - data << uint32(m_itemOrMoney); - // if ( m_eventType != 4 || m_eventType != 5 || m_eventType != 6 || m_eventType != 8 || m_eventType != 9 ) - if (m_eventType < GUILD_BANK_LOG_DEPOSIT_MONEY) - { - data << uint32(m_itemStackCount); - if (m_eventType == GUILD_BANK_LOG_MOVE_ITEM || m_eventType == GUILD_BANK_LOG_MOVE_ITEM2) + + switch(m_eventType) + { + case GUILD_BANK_LOG_DEPOSIT_ITEM: + case GUILD_BANK_LOG_WITHDRAW_ITEM: + data << uint32(m_itemOrMoney); + data << uint32(m_itemStackCount); + break; + case GUILD_BANK_LOG_MOVE_ITEM: + case GUILD_BANK_LOG_MOVE_ITEM2: + data << uint32(m_itemOrMoney); + data << uint32(m_itemStackCount); data << uint8(m_destTabId); + break; + default: + data << uint64(m_itemOrMoney); } data << uint32(time(NULL) - m_timestamp); } -/////////////////////////////////////////////////////////////////////////////// // RankInfo void Guild::RankInfo::LoadFromDB(Field* fields) { @@ -219,18 +223,47 @@ void Guild::RankInfo::SaveToDB(SQLTransaction& trans) const CharacterDatabase.ExecuteOrAppend(trans, stmt); } +bool Guild::RankInfo::CreateMissingTabsIfNeeded(uint8 ranks, SQLTransaction& trans) +{ + bool ret = false; + for (uint8 i = 0; i < ranks; ++i) + { + GuildBankRightsAndSlots& rightsAndSlots = m_bankTabRightsAndSlots[i]; + if (rightsAndSlots.GetTabId() == i) + continue; + + rightsAndSlots.SetTabId(i); + if (m_rankId == GR_GUILDMASTER) + rightsAndSlots.SetGuildMasterValues(); + + ret = true; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_RIGHT); + stmt->setUInt32(0, m_guildId); + stmt->setUInt8 (1, i); + stmt->setUInt8 (2, m_rankId); + stmt->setUInt32(3, rightsAndSlots.GetRights()); + stmt->setUInt32(4, rightsAndSlots.GetSlots()); + trans->Append(stmt); + } + + return ret; +} + void Guild::RankInfo::WritePacket(WorldPacket& data) const { data << uint32(m_rights); - data << uint32(m_bankMoneyPerDay); // In game set in gold, in packet set in bronze. + if (m_bankMoneyPerDay == GUILD_WITHDRAW_MONEY_UNLIMITED) + data << uint32(GUILD_WITHDRAW_MONEY_UNLIMITED); + else + data << uint32(m_bankMoneyPerDay); for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i) { - data << uint32(m_bankTabRightsAndSlots[i].rights); - data << uint32(m_bankTabRightsAndSlots[i].slots); + data << uint32(m_bankTabRightsAndSlots[i].GetRights()); + data << uint32(m_bankTabRightsAndSlots[i].GetSlots()); } } -void Guild::RankInfo::SetName(const std::string& name) +void Guild::RankInfo::SetName(std::string const& name) { if (m_name == name) return; @@ -271,62 +304,39 @@ void Guild::RankInfo::SetBankMoneyPerDay(uint32 money) m_bankMoneyPerDay = money; - PreparedStatement* stmt = NULL; - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_BANK_MONEY); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_BANK_MONEY); stmt->setUInt32(0, money); stmt->setUInt8 (1, m_rankId); stmt->setUInt32(2, m_guildId); CharacterDatabase.Execute(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_BANK_RESET_TIME); - stmt->setUInt32(0, m_guildId); - stmt->setUInt8 (1, m_rankId); - CharacterDatabase.Execute(stmt); } -void Guild::RankInfo::SetBankTabSlotsAndRights(uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB) +void Guild::RankInfo::SetBankTabSlotsAndRights(GuildBankRightsAndSlots rightsAndSlots, bool saveToDB) { if (m_rankId == GR_GUILDMASTER) // Prevent loss of leader rights rightsAndSlots.SetGuildMasterValues(); - if (m_bankTabRightsAndSlots[tabId].IsEqual(rightsAndSlots)) - return; - - m_bankTabRightsAndSlots[tabId] = rightsAndSlots; + GuildBankRightsAndSlots& guildBR = m_bankTabRightsAndSlots[rightsAndSlots.GetTabId()]; + guildBR = rightsAndSlots; if (saveToDB) { - PreparedStatement* stmt = NULL; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHT); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_RIGHT); stmt->setUInt32(0, m_guildId); - stmt->setUInt8 (1, tabId); + stmt->setUInt8 (1, guildBR.GetTabId()); stmt->setUInt8 (2, m_rankId); - CharacterDatabase.Execute(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_RIGHT); - stmt->setUInt32(0, m_guildId); - stmt->setUInt8 (1, tabId); - stmt->setUInt8 (2, m_rankId); - stmt->setUInt8 (3, m_bankTabRightsAndSlots[tabId].rights); - stmt->setUInt32(4, m_bankTabRightsAndSlots[tabId].slots); - CharacterDatabase.Execute(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RANK_BANK_TIME0 + tabId); - stmt->setUInt32(0, m_guildId); - stmt->setUInt8 (1, m_rankId); + stmt->setUInt8 (3, guildBR.GetRights()); + stmt->setUInt32(4, guildBR.GetSlots()); CharacterDatabase.Execute(stmt); } } -/////////////////////////////////////////////////////////////////////////////// // BankTab -bool Guild::BankTab::LoadFromDB(Field* fields) +void Guild::BankTab::LoadFromDB(Field* fields) { m_name = fields[2].GetString(); m_icon = fields[3].GetString(); m_text = fields[4].GetString(); - return true; } bool Guild::BankTab::LoadItemFromDB(Field* fields) @@ -352,7 +362,7 @@ bool Guild::BankTab::LoadItemFromDB(Field* fields) { sLog->outError(LOG_FILTER_GUILD, "Item (GUID %u, id: %u) not found in item_instance, deleting from guild bank!", itemGuid, itemEntry); - PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM); stmt->setUInt32(0, m_guildId); stmt->setUInt8 (1, m_tabId); stmt->setUInt8 (2, slotId); @@ -383,26 +393,41 @@ void Guild::BankTab::Delete(SQLTransaction& trans, bool removeItemsFromDB) inline void Guild::BankTab::WritePacket(WorldPacket& data) const { - data << uint8(GUILD_BANK_MAX_SLOTS); + uint8 count = 0; + + size_t pos = data.wpos(); + data << uint8(0); + for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId) - WriteSlotPacket(data, slotId); + if (WriteSlotPacket(data, slotId)) + ++count; + + data.put<uint8>(pos, count); } // Writes information about contents of specified slot into packet. -void Guild::BankTab::WriteSlotPacket(WorldPacket& data, uint8 slotId) const +bool Guild::BankTab::WriteSlotPacket(WorldPacket& data, uint8 slotId, bool ignoreEmpty /* = true */) const { Item* pItem = GetItem(slotId); uint32 itemEntry = pItem ? pItem->GetEntry() : 0; + if (!itemEntry && ignoreEmpty) + return false; + data << uint8(slotId); data << uint32(itemEntry); if (itemEntry) { data << uint32(0); // 3.3.0 (0x00018020, 0x00018000) - data << uint32(pItem->GetItemRandomPropertyId()); // Random item property id - if (pItem->GetItemRandomPropertyId()) + + if (uint32 random = pItem->GetItemRandomPropertyId()) + { + data << uint32(random); // Random item property id data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor + } + else + data << uint32(0); data << uint32(pItem->GetCount()); // ITEM_FIELD_STACK_COUNT data << uint32(0); @@ -421,9 +446,10 @@ void Guild::BankTab::WriteSlotPacket(WorldPacket& data, uint8 slotId) const } data.put<uint8>(enchCountPos, enchCount); } + return true; } -void Guild::BankTab::SetInfo(const std::string& name, const std::string& icon) +void Guild::BankTab::SetInfo(std::string const& name, std::string const& icon) { if (m_name == name && m_icon == icon) return; @@ -439,7 +465,7 @@ void Guild::BankTab::SetInfo(const std::string& name, const std::string& icon) CharacterDatabase.Execute(stmt); } -void Guild::BankTab::SetText(const std::string& text) +void Guild::BankTab::SetText(std::string const& text) { if (m_text == text) return; @@ -456,51 +482,55 @@ void Guild::BankTab::SetText(const std::string& text) // Sets/removes contents of specified slot. // If pItem == NULL contents are removed. -bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem) +bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* item) { if (slotId >= GUILD_BANK_MAX_SLOTS) return false; - m_items[slotId] = pItem; - - PreparedStatement* stmt = NULL; + m_items[slotId] = item; - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_ITEM); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_ITEM); stmt->setUInt32(0, m_guildId); stmt->setUInt8 (1, m_tabId); stmt->setUInt8 (2, slotId); CharacterDatabase.ExecuteOrAppend(trans, stmt); - if (pItem) + if (item) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_ITEM); stmt->setUInt32(0, m_guildId); stmt->setUInt8 (1, m_tabId); stmt->setUInt8 (2, slotId); - stmt->setUInt32(3, pItem->GetGUIDLow()); + stmt->setUInt32(3, item->GetGUIDLow()); CharacterDatabase.ExecuteOrAppend(trans, stmt); - pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, 0); - pItem->SetUInt64Value(ITEM_FIELD_OWNER, 0); - pItem->FSetState(ITEM_NEW); - pItem->SaveToDB(trans); // Not in inventory and can be saved standalone + item->SetUInt64Value(ITEM_FIELD_CONTAINED, 0); + item->SetUInt64Value(ITEM_FIELD_OWNER, 0); + item->FSetState(ITEM_NEW); + item->SaveToDB(trans); // Not in inventory and can be saved standalone } return true; } -void Guild::BankTab::SendText(const Guild* guild, WorldSession* session) const +void Guild::BankTab::SendText(Guild const* guild, WorldSession* session) const { WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1 + m_text.size() + 1); data << uint8(m_tabId); data << m_text; if (session) + { + sLog->outDebug(LOG_FILTER_GUILD, "MSG_QUERY_GUILD_BANK_TEXT [%s]: Tabid: %u, Text: %s" + , session->GetPlayerInfo().c_str(), m_tabId, m_text.c_str()); session->SendPacket(&data); + } else + { + sLog->outDebug(LOG_FILTER_GUILD, "MSG_QUERY_GUILD_BANK_TEXT [Broadcast]: Tabid: %u, Text: %s", m_tabId, m_text.c_str()); guild->BroadcastPacket(&data); + } } -/////////////////////////////////////////////////////////////////////////////// // Member void Guild::Member::SetStats(Player* player) { @@ -511,7 +541,7 @@ void Guild::Member::SetStats(Player* player) m_accountId = player->GetSession()->GetAccountId(); } -void Guild::Member::SetStats(const std::string& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId) +void Guild::Member::SetStats(std::string const& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId) { m_name = name; m_level = level; @@ -520,7 +550,7 @@ void Guild::Member::SetStats(const std::string& name, uint8 level, uint8 _class, m_accountId = accountId; } -void Guild::Member::SetPublicNote(const std::string& publicNote) +void Guild::Member::SetPublicNote(std::string const& publicNote) { if (m_publicNote == publicNote) return; @@ -533,7 +563,7 @@ void Guild::Member::SetPublicNote(const std::string& publicNote) CharacterDatabase.Execute(stmt); } -void Guild::Member::SetOfficerNote(const std::string& officerNote) +void Guild::Member::SetOfficerNote(std::string const& officerNote) { if (m_officerNote == officerNote) return; @@ -576,22 +606,18 @@ void Guild::Member::SaveToDB(SQLTransaction& trans) const // In this case member has to be removed from guild. bool Guild::Member::LoadFromDB(Field* fields) { - m_publicNote = fields[3].GetString(); - m_officerNote = fields[4].GetString(); - m_bankRemaining[GUILD_BANK_MAX_TABS].resetTime = fields[5].GetUInt32(); - m_bankRemaining[GUILD_BANK_MAX_TABS].value = fields[6].GetUInt32(); - for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i) - { - m_bankRemaining[i].resetTime = fields[7 + i * 2].GetUInt32(); - m_bankRemaining[i].value = fields[8 + i * 2].GetUInt32(); - } + m_publicNote = fields[3].GetString(); + m_officerNote = fields[4].GetString(); + + for (uint8 i = 0; i <= GUILD_BANK_MAX_TABS; ++i) + m_bankWithdraw[i] = fields[5 + i].GetUInt32(); - SetStats(fields[19].GetString(), - fields[20].GetUInt8(), // characters.level - fields[21].GetUInt8(), // characters.class - fields[22].GetUInt16(), // characters.zone - fields[23].GetUInt32()); // characters.account - m_logoutTime = fields[24].GetUInt32(); // characters.logout_time + SetStats(fields[12].GetString(), + fields[13].GetUInt8(), // characters.level + fields[14].GetUInt8(), // characters.class + fields[15].GetUInt16(), // characters.zone + fields[16].GetUInt32()); // characters.account + m_logoutTime = fields[17].GetUInt32(); // characters.logout_time if (!CheckStats()) return false; @@ -601,6 +627,7 @@ bool Guild::Member::LoadFromDB(Field* fields) sLog->outError(LOG_FILTER_GUILD, "Player (GUID: %u) has broken zone-data", GUID_LOPART(m_guid)); m_zoneId = Player::GetZoneIdFromDB(m_guid); } + ResetFlags(); return true; } @@ -612,6 +639,7 @@ bool Guild::Member::CheckStats() const sLog->outError(LOG_FILTER_GUILD, "Player (GUID: %u) has a broken data in field `characters`.`level`, deleting him from guild!", GUID_LOPART(m_guid)); return false; } + if (m_class < CLASS_WARRIOR || m_class >= MAX_CLASSES) { sLog->outError(LOG_FILTER_GUILD, "Player (GUID: %u) has a broken data in field `characters`.`class`, deleting him from guild!", GUID_LOPART(m_guid)); @@ -622,100 +650,64 @@ bool Guild::Member::CheckStats() const void Guild::Member::WritePacket(WorldPacket& data) const { - if (Player* player = FindPlayer()) - { - data << uint64(player->GetGUID()); - data << uint8(1); - data << player->GetName(); - data << uint32(m_rankId); - data << uint8(player->getLevel()); - data << uint8(player->getClass()); - data << uint8(0); // new 2.4.0 - data << uint32(player->GetZoneId()); - } - else - { - data << m_guid; - data << uint8(0); - data << m_name; - data << uint32(m_rankId); - data << uint8(m_level); - data << uint8(m_class); - data << uint8(0); // new 2.4.0 - data << uint32(m_zoneId); + data << uint64(m_guid) + << uint8(m_flags) + << m_name + << uint32(m_rankId) + << uint8(m_level) + << uint8(m_class) + << uint8(0) + << uint32(m_zoneId); + + if (!m_flags) data << float(float(::time(NULL) - m_logoutTime) / DAY); - } - data << m_publicNote; - data << m_officerNote; + + data << m_publicNote + << m_officerNote; } // Decreases amount of money/slots left for today. // If (tabId == GUILD_BANK_MAX_TABS) decrease money amount. // Otherwise decrease remaining items amount for specified tab. -void Guild::Member::DecreaseBankRemainingValue(SQLTransaction& trans, uint8 tabId, uint32 amount) +void Guild::Member::UpdateBankWithdrawValue(SQLTransaction& trans, uint8 tabId, uint32 amount) { - m_bankRemaining[tabId].value -= amount; + m_bankWithdraw[tabId] += amount; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_MEMBER_WITHDRAW); + stmt->setUInt32(0, GUID_LOPART(m_guid)); + for (uint8 i = 0; i <= GUILD_BANK_MAX_TABS;) + { + uint32 withdraw = m_bankWithdraw[i++]; + stmt->setUInt32(i, withdraw); + } - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement( - tabId == GUILD_BANK_MAX_TABS ? - CHAR_UPD_GUILD_MEMBER_BANK_REM_MONEY : - CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS0 + tabId); - stmt->setUInt32(0, m_bankRemaining[tabId].value); - stmt->setUInt32(1, m_guildId); - stmt->setUInt32(2, GUID_LOPART(m_guid)); CharacterDatabase.ExecuteOrAppend(trans, stmt); } +void Guild::Member::ResetValues() +{ + for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId) + m_bankWithdraw[tabId] = 0; +} + // Get amount of money/slots left for today. // If (tabId == GUILD_BANK_MAX_TABS) return money amount. // Otherwise return remaining items amount for specified tab. -// If reset time was more than 24 hours ago, renew reset time and reset amount to maximum value. -uint32 Guild::Member::GetBankRemainingValue(uint8 tabId, const Guild* guild) const +int32 Guild::Member::GetBankWithdrawValue(uint8 tabId) const { // Guild master has unlimited amount. if (IsRank(GR_GUILDMASTER)) return tabId == GUILD_BANK_MAX_TABS ? GUILD_WITHDRAW_MONEY_UNLIMITED : GUILD_WITHDRAW_SLOT_UNLIMITED; - // Check rights for non-money tab. - if (tabId != GUILD_BANK_MAX_TABS) - if ((guild->_GetRankBankTabRights(m_rankId, tabId) & GUILD_BANK_RIGHT_VIEW_TAB) != GUILD_BANK_RIGHT_VIEW_TAB) - return 0; - - uint32 curTime = uint32(::time(NULL) / MINUTE); // minutes - if (curTime > m_bankRemaining[tabId].resetTime + 24 * HOUR / MINUTE) - { - RemainingValue& rv = const_cast <RemainingValue&> (m_bankRemaining[tabId]); - rv.resetTime = curTime; - rv.value = tabId == GUILD_BANK_MAX_TABS ? - guild->_GetRankBankMoneyPerDay(m_rankId) : - guild->_GetRankBankTabSlotsPerDay(m_rankId, tabId); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement( - tabId == GUILD_BANK_MAX_TABS ? - CHAR_UPD_GUILD_MEMBER_BANK_TIME_MONEY : - CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS0 + tabId); - stmt->setUInt32(0, m_bankRemaining[tabId].resetTime); - stmt->setUInt32(1, m_bankRemaining[tabId].value); - stmt->setUInt32(2, m_guildId); - stmt->setUInt32(3, GUID_LOPART(m_guid)); - CharacterDatabase.Execute(stmt); - } - return m_bankRemaining[tabId].value; -} - -inline void Guild::Member::ResetTabTimes() -{ - for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId) - m_bankRemaining[tabId].resetTime = 0; + return m_bankWithdraw[tabId]; } -inline void Guild::Member::ResetMoneyTime() +// EmblemInfo +void EmblemInfo::ReadPacket(WorldPacket& recv) { - m_bankRemaining[GUILD_BANK_MAX_TABS].resetTime = 0; + recv >> m_style >> m_color >> m_borderStyle >> m_borderColor >> m_backgroundColor; } -/////////////////////////////////////////////////////////////////////////////// -// EmblemInfo void EmblemInfo::LoadFromDB(Field* fields) { m_style = fields[3].GetUInt8(); @@ -746,7 +738,6 @@ void EmblemInfo::SaveToDB(uint32 guildId) const CharacterDatabase.Execute(stmt); } -/////////////////////////////////////////////////////////////////////////////// // MoveItemData bool Guild::MoveItemData::CheckItem(uint32& splitedAmount) { @@ -794,7 +785,6 @@ inline void Guild::MoveItemData::CopySlots(SlotIds& ids) const ids.insert(uint8(itr->pos)); } -/////////////////////////////////////////////////////////////////////////////// // PlayerMoveItemData bool Guild::PlayerMoveItemData::InitItem() { @@ -854,7 +844,6 @@ inline InventoryResult Guild::PlayerMoveItemData::CanStore(Item* pItem, bool swa return m_pPlayer->CanStoreItem(m_container, m_slotId, m_vec, pItem, swap); } -/////////////////////////////////////////////////////////////////////////////// // BankMoveItemData bool Guild::BankMoveItemData::InitItem() { @@ -877,7 +866,12 @@ bool Guild::BankMoveItemData::HasWithdrawRights(MoveItemData* pOther) const // Do not check rights if item is being swapped within the same bank tab if (pOther->IsBank() && pOther->GetContainer() == m_container) return true; - return (m_pGuild->_GetMemberRemainingSlots(m_pPlayer->GetGUID(), m_container) != 0); + + int32 slots = 0; + if (Member const* member = m_pGuild->GetMember(m_pPlayer->GetGUID())) + slots = m_pGuild->_GetMemberRemainingSlots(member, m_container); + + return slots != 0; } void Guild::BankMoveItemData::RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount) @@ -896,7 +890,7 @@ void Guild::BankMoveItemData::RemoveItem(SQLTransaction& trans, MoveItemData* pO } // Decrease amount of player's remaining items (if item is moved to different tab or to player) if (!pOther->IsBank() || pOther->GetContainer() != m_container) - m_pGuild->_DecreaseMemberRemainingSlots(trans, m_pPlayer->GetGUID(), m_container); + m_pGuild->_UpdateMemberWithdrawSlots(trans, m_pPlayer->GetGUID(), m_container); } Item* Guild::BankMoveItemData::StoreItem(SQLTransaction& trans, Item* pItem) @@ -1067,9 +1061,14 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap) return EQUIP_ERR_BANK_FULL; } -/////////////////////////////////////////////////////////////////////////////// // Guild -Guild::Guild() : m_id(0), m_leaderGuid(0), m_createdDate(0), m_accountsNumber(0), m_bankMoney(0), m_eventLog(NULL) +Guild::Guild(): + m_id(0), + m_leaderGuid(0), + m_createdDate(0), + m_accountsNumber(0), + m_bankMoney(0), + m_eventLog(NULL) { memset(&m_bankEventLog, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(LogHolder*)); } @@ -1080,17 +1079,24 @@ Guild::~Guild() _DeleteBankItems(temp); // Cleanup - if (m_eventLog) - delete m_eventLog; + delete m_eventLog; + m_eventLog = NULL; + for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId) - if (m_bankEventLog[tabId]) - delete m_bankEventLog[tabId]; + { + delete m_bankEventLog[tabId]; + m_bankEventLog[tabId] = NULL; + } + for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) + { delete itr->second; + itr->second = NULL; + } } // Creates new guild with default data and saves it to database. -bool Guild::Create(Player* pLeader, const std::string& name) +bool Guild::Create(Player* pLeader, std::string const& name) { // Check if guild with such name already exists if (sGuildMgr->GetGuildByName(name)) @@ -1112,10 +1118,9 @@ bool Guild::Create(Player* pLeader, const std::string& name) sLog->outDebug(LOG_FILTER_GUILD, "GUILD: creating guild [%s] for leader %s (%u)", name.c_str(), pLeader->GetName().c_str(), GUID_LOPART(m_leaderGuid)); - PreparedStatement* stmt = NULL; SQLTransaction trans = CharacterDatabase.BeginTransaction(); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBERS); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBERS); stmt->setUInt32(0, m_id); trans->Append(stmt); @@ -1136,12 +1141,10 @@ bool Guild::Create(Player* pLeader, const std::string& name) trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); - // Create default ranks - _CreateDefaultGuildRanks(pLeaderSession->GetSessionDbLocaleIndex()); - // Add guildmaster - bool ret = AddMember(m_leaderGuid, GR_GUILDMASTER); + _CreateDefaultGuildRanks(pLeaderSession->GetSessionDbLocaleIndex()); // Create default ranks + bool ret = AddMember(m_leaderGuid, GR_GUILDMASTER); // Add guildmaster + if (ret) - // Call scripts on successful create sScriptMgr->OnGuildCreate(this, pLeader, name); return ret; @@ -1161,9 +1164,9 @@ void Guild::Disband() DeleteMember(itr->second->GetGUID(), true); } - PreparedStatement* stmt = NULL; SQLTransaction trans = CharacterDatabase.BeginTransaction(); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD); stmt->setUInt32(0, m_id); trans->Append(stmt); @@ -1198,8 +1201,36 @@ void Guild::Disband() sGuildMgr->RemoveGuild(m_id); } -/////////////////////////////////////////////////////////////////////////////// -// HANDLE CLIENT COMMANDS +void Guild::UpdateMemberData(Player* player, uint8 dataid, uint32 value) +{ + if (Member* member = GetMember(player->GetGUID())) + { + switch (dataid) + { + case GUILD_MEMBER_DATA_ZONEID: + member->SetZoneID(value); + break; + case GUILD_MEMBER_DATA_LEVEL: + member->SetLevel(value); + break; + default: + sLog->outError(LOG_FILTER_GUILD, "Guild::UpdateMemberData: Called with incorrect DATAID %u (value %u)", dataid, value); + return; + } + //HandleRoster(); + } +} + +void Guild::OnPlayerStatusChange(Player* player, uint32 flag, bool state) +{ + if (Member* member = GetMember(player->GetGUID())) + { + if (state) + member->AddFlag(flag); + else member->RemFlag(flag); + } +} + void Guild::HandleRoster(WorldSession* session /*= NULL*/) { // Guess size @@ -1216,10 +1247,15 @@ void Guild::HandleRoster(WorldSession* session /*= NULL*/) itr->second->WritePacket(data); if (session) + { + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_ROSTER [%s]", session->GetPlayerInfo().c_str()); session->SendPacket(&data); + } else + { + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_ROSTER [Broadcast]"); BroadcastPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_ROSTER)"); + } } void Guild::HandleQuery(WorldSession* session) @@ -1228,6 +1264,7 @@ void Guild::HandleQuery(WorldSession* session) data << uint32(m_id); data << m_name; + // Rank name for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i) // Always show 10 ranks { if (i < _GetRanksSize()) @@ -1237,20 +1274,20 @@ void Guild::HandleQuery(WorldSession* session) } m_emblemInfo.WritePacket(data); - data << uint32(_GetRanksSize()); // Amount of ranks - session->SendPacket(&data); + data << uint32(_GetRanksSize()); // Number of ranks used - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)"); + session->SendPacket(&data); + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_QUERY_RESPONSE [%s]", session->GetPlayerInfo().c_str()); } -void Guild::HandleSetMOTD(WorldSession* session, const std::string& motd) +void Guild::HandleSetMOTD(WorldSession* session, std::string const& motd) { if (m_motd == motd) return; // Player must have rights to set MOTD if (!_HasRankRight(session->GetPlayer(), GR_RIGHT_SETMOTD)) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); + SendCommandResult(session, GUILD_COMMAND_EDIT_MOTD, ERR_GUILD_PERMISSIONS); else { m_motd = motd; @@ -1266,15 +1303,13 @@ void Guild::HandleSetMOTD(WorldSession* session, const std::string& motd) } } -void Guild::HandleSetInfo(WorldSession* session, const std::string& info) +void Guild::HandleSetInfo(WorldSession* session, std::string const& info) { if (m_info == info) return; // Player must have rights to set guild's info - if (!_HasRankRight(session->GetPlayer(), GR_RIGHT_MODIFY_GUILD_INFO)) - SendCommandResult(session, GUILD_CREATE_S, ERR_GUILD_PERMISSIONS); - else + if (_HasRankRight(session->GetPlayer(), GR_RIGHT_MODIFY_GUILD_INFO)) { m_info = info; @@ -1291,11 +1326,9 @@ void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo) { Player* player = session->GetPlayer(); if (!_IsLeader(player)) - // "Only guild leaders can create emblems." - SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTGUILDMASTER); + SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTGUILDMASTER); // "Only guild leaders can create emblems." else if (!player->HasEnoughMoney(EMBLEM_PRICE)) - // "You can't afford to do that." - SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTENOUGHMONEY); + SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTENOUGHMONEY); // "You can't afford to do that." else { player->ModifyMoney(-int32(EMBLEM_PRICE)); @@ -1303,102 +1336,116 @@ void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo) m_emblemInfo = emblemInfo; m_emblemInfo.SaveToDB(m_id); - // "Guild Emblem saved." - SendSaveEmblemResult(session, ERR_GUILDEMBLEM_SUCCESS); + SendSaveEmblemResult(session, ERR_GUILDEMBLEM_SUCCESS); // "Guild Emblem saved." HandleQuery(session); } } -void Guild::HandleSetLeader(WorldSession* session, const std::string& name) +void Guild::HandleSetLeader(WorldSession* session, std::string const& name) { Player* player = session->GetPlayer(); // Only leader can assign new leader if (!_IsLeader(player)) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); + SendCommandResult(session, GUILD_COMMAND_CHANGE_LEADER, ERR_GUILD_PERMISSIONS); // Old leader must be a member of guild else if (Member* pOldLeader = GetMember(player->GetGUID())) { // New leader must be a member of guild - if (Member* pNewLeader = GetMember(session, name)) + if (Member* pNewLeader = GetMember(name)) { _SetLeaderGUID(pNewLeader); pOldLeader->ChangeRank(GR_OFFICER); _BroadcastEvent(GE_LEADER_CHANGED, 0, player->GetName().c_str(), name.c_str()); } } - else - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); } -void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, const std::string& name, const std::string& icon) +void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon) { - if (BankTab* pTab = GetBankTab(tabId)) + BankTab* tab = GetBankTab(tabId); + if (!tab) { - pTab->SetInfo(name, icon); - SendBankTabsInfo(session); - _SendBankContent(session, tabId); + sLog->outError(LOG_FILTER_GUILD, "Guild::HandleSetBankTabInfo: Player %s trying to change bank tab info from unexisting tab %d.", + session->GetPlayerInfo().c_str(), tabId); + return; } + + char aux[2]; + sprintf(aux, "%u", tabId); + + tab->SetInfo(name, icon); + _BroadcastEvent(GE_BANK_TAB_UPDATED, 0, aux, name.c_str(), icon.c_str()); } -void Guild::HandleSetMemberNote(WorldSession* session, const std::string& name, const std::string& note, bool officer) +void Guild::HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool isPublic) { // Player must have rights to set public/officer note - if (!_HasRankRight(session->GetPlayer(), officer ? GR_RIGHT_EOFFNOTE : GR_RIGHT_EPNOTE)) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); - // Noted player must be a member of guild - else if (Member* member = GetMember(session, name)) + if (!_HasRankRight(session->GetPlayer(), isPublic ? GR_RIGHT_EPNOTE : GR_RIGHT_EOFFNOTE)) + SendCommandResult(session, GUILD_COMMAND_PUBLIC_NOTE, ERR_GUILD_PERMISSIONS); + else if (Member* member = GetMember(name)) { - if (officer) - member->SetOfficerNote(note); - else + if (isPublic) member->SetPublicNote(note); + else + member->SetOfficerNote(note); + HandleRoster(session); } } -void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, const std::string& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots) +void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots) { // Only leader can modify ranks if (!_IsLeader(session->GetPlayer())) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); + SendCommandResult(session, GUILD_COMMAND_CHANGE_RANK, ERR_GUILD_PERMISSIONS); else if (RankInfo* rankInfo = GetRankInfo(rankId)) { - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Changed RankName to '%s', rights to 0x%08X", name.c_str(), rights); + sLog->outDebug(LOG_FILTER_GUILD, "Changed RankName to '%s', rights to 0x%08X", name.c_str(), rights); rankInfo->SetName(name); rankInfo->SetRights(rights); _SetRankBankMoneyPerDay(rankId, moneyPerDay); - uint8 tabId = 0; for (GuildBankRightsAndSlotsVec::const_iterator itr = rightsAndSlots.begin(); itr != rightsAndSlots.end(); ++itr) - _SetRankBankTabRightsAndSlots(rankId, tabId++, *itr); + _SetRankBankTabRightsAndSlots(rankId, *itr); - HandleQuery(session); - HandleRoster(); // Broadcast for tab rights update + char aux[2]; + sprintf(aux, "%u", rankId); + _BroadcastEvent(GE_RANK_UPDATED, 0, aux, name.c_str()); } } void Guild::HandleBuyBankTab(WorldSession* session, uint8 tabId) { - if (tabId != _GetPurchasedTabsSize()) + Player* player = session->GetPlayer(); + if (!player) return; - uint32 tabCost = _GetGuildBankTabPrice(tabId) * GOLD; - if (!tabCost) + Member const* member = GetMember(player->GetGUID()); + if (!member) return; - Player* player = session->GetPlayer(); - if (!player->HasEnoughMoney(tabCost)) // Should not happen, this is checked by client + if (_GetPurchasedTabsSize() >= GUILD_BANK_MAX_TABS) return; - if (!_CreateNewBankTab()) - return; + if (tabId != _GetPurchasedTabsSize()) + return; + + uint32 tabCost = _GetGuildBankTabPrice(tabId) * GOLD; + if (!tabCost) + return; - player->ModifyMoney(-int32(tabCost)); - _SetRankBankMoneyPerDay(player->GetRank(), uint32(GUILD_WITHDRAW_MONEY_UNLIMITED)); - _SetRankBankTabRightsAndSlots(player->GetRank(), tabId, GuildBankRightsAndSlots(GUILD_BANK_RIGHT_FULL, uint32(GUILD_WITHDRAW_SLOT_UNLIMITED))); - HandleRoster(); // Broadcast for tab rights update + if (!player->HasEnoughMoney(tabCost)) // Should not happen, this is checked by client + return; + + player->ModifyMoney(-int32(tabCost)); + + uint8 rankId = member->GetRankId(); + _CreateNewBankTab(); + _SetRankBankMoneyPerDay(rankId, uint32(GUILD_WITHDRAW_MONEY_UNLIMITED)); + GuildBankRightsAndSlots rightsAndSlots(tabId); + _SetRankBankTabRightsAndSlots(rankId, rightsAndSlots); SendBankTabsInfo(session); } @@ -1407,7 +1454,7 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name) Player* pInvitee = sObjectAccessor->FindPlayerByName(name); if (!pInvitee) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PLAYER_NOT_FOUND_S, name); + SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_PLAYER_NOT_FOUND_S, name); return; } @@ -1415,30 +1462,33 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name) // Do not show invitations from ignored players if (pInvitee->GetSocial()->HasIgnore(player->GetGUIDLow())) return; + if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && pInvitee->GetTeam() != player->GetTeam()) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_NOT_ALLIED, name); + SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_NOT_ALLIED, name); return; } // Invited player cannot be in another guild if (pInvitee->GetGuildId()) { - SendCommandResult(session, GUILD_INVITE_S, ERR_ALREADY_IN_GUILD_S, name); + SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_ALREADY_IN_GUILD_S, name); return; } // Invited player cannot be invited if (pInvitee->GetGuildIdInvited()) { - SendCommandResult(session, GUILD_INVITE_S, ERR_ALREADY_INVITED_TO_GUILD_S, name); + SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_ALREADY_INVITED_TO_GUILD_S, name); return; } // Inviting player must have rights to invite if (!_HasRankRight(player, GR_RIGHT_INVITE)) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); + SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_PERMISSIONS); return; } + SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_COMMAND_SUCCESS, name); + sLog->outDebug(LOG_FILTER_GUILD, "Player %s invited %s to join his Guild", player->GetName().c_str(), name.c_str()); pInvitee->SetGuildIdInvited(m_id); @@ -1448,8 +1498,7 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name) data << player->GetName(); data << m_name; pInvitee->GetSession()->SendPacket(&data); - - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_INVITE)"); + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_INVITE [%s]", pInvitee->GetName().c_str()); } void Guild::HandleAcceptMember(WorldSession* session) @@ -1459,11 +1508,7 @@ void Guild::HandleAcceptMember(WorldSession* session) player->GetTeam() != sObjectMgr->GetPlayerTeamByGUID(GetLeaderGUID())) return; - if (AddMember(player->GetGUID())) - { - _LogEvent(GUILD_EVENT_LOG_JOIN_GUILD, player->GetGUIDLow()); - _BroadcastEvent(GE_JOINED, player->GetGUID(), player->GetName().c_str()); - } + AddMember(player->GetGUID()); } void Guild::HandleLeaveMember(WorldSession* session) @@ -1474,7 +1519,7 @@ void Guild::HandleLeaveMember(WorldSession* session) { if (m_members.size() > 1) // Leader cannot leave if he is not the last member - SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_LEADER_LEAVE); + SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_LEADER_LEAVE); else // Guild is disbanded if leader leaves. Disband(); @@ -1486,79 +1531,84 @@ void Guild::HandleLeaveMember(WorldSession* session) _LogEvent(GUILD_EVENT_LOG_LEAVE_GUILD, player->GetGUIDLow()); _BroadcastEvent(GE_LEFT, player->GetGUID(), player->GetName().c_str()); - SendCommandResult(session, GUILD_QUIT_S, ERR_PLAYER_NO_MORE_IN_GUILD, m_name); + SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_COMMAND_SUCCESS, m_name); } } -void Guild::HandleRemoveMember(WorldSession* session, const std::string& name) +void Guild::HandleRemoveMember(WorldSession* session, std::string const& name) { Player* player = session->GetPlayer(); // Player must have rights to remove members if (!_HasRankRight(player, GR_RIGHT_REMOVE)) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); - // Removed player must be a member of guild - else if (Member* member = GetMember(session, name)) + SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_PERMISSIONS); + else if (Member* member = GetMember(name)) { - // Leader cannot be removed + // Guild masters cannot be removed if (member->IsRank(GR_GUILDMASTER)) - SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_LEADER_LEAVE); + SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_LEADER_LEAVE); // Do not allow to remove player with the same rank or higher - else if (member->IsRankNotLower(player->GetRank())) - SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_RANK_TOO_HIGH_S, name); else { - uint64 guid = member->GetGUID(); - // After call to DeleteMember pointer to member becomes invalid - DeleteMember(guid, false, true); - _LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUIDLow(), GUID_LOPART(guid)); - _BroadcastEvent(GE_REMOVED, 0, name.c_str(), player->GetName().c_str()); + Member const* memberMe = GetMember(player->GetGUID()); + if (!memberMe || member->IsRankNotLower(memberMe->GetRankId())) + SendCommandResult(session, GUILD_COMMAND_REMOVE, ERR_GUILD_RANK_TOO_HIGH_S, name); + else + { + uint64 guid = member->GetGUID(); + // After call to DeleteMember pointer to member becomes invalid + DeleteMember(guid, false, true); + _LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUIDLow(), GUID_LOPART(guid)); + _BroadcastEvent(GE_REMOVED, 0, name.c_str(), player->GetName().c_str()); + } } } } -void Guild::HandleUpdateMemberRank(WorldSession* session, const std::string& name, bool demote) +void Guild::HandleUpdateMemberRank(WorldSession* session, std::string const& name, bool demote) { Player* player = session->GetPlayer(); + GuildCommandType type = demote ? GUILD_COMMAND_DEMOTE : GUILD_COMMAND_PROMOTE; // Player must have rights to promote if (!_HasRankRight(player, demote ? GR_RIGHT_DEMOTE : GR_RIGHT_PROMOTE)) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); + SendCommandResult(session, type, ERR_GUILD_PERMISSIONS); // Promoted player must be a member of guild - else if (Member* member = GetMember(session, name)) + else if (Member* member = GetMember(name)) { // Player cannot promote himself if (member->IsSamePlayer(player->GetGUID())) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_NAME_INVALID); + SendCommandResult(session, type, ERR_GUILD_NAME_INVALID); return; } + Member const* memberMe = GetMember(player->GetGUID()); + uint8 rankId = memberMe->GetRankId(); if (demote) { // Player can demote only lower rank members - if (member->IsRankNotLower(player->GetRank())) + if (member->IsRankNotLower(rankId)) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_HIGH_S, name); + SendCommandResult(session, type, ERR_GUILD_RANK_TOO_HIGH_S, name); return; } // Lowest rank cannot be demoted if (member->GetRankId() >= _GetLowestRankId()) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_LOW_S, name); + SendCommandResult(session, type, ERR_GUILD_RANK_TOO_LOW_S, name); return; } } else { // Allow to promote only to lower rank than member's rank - // member->GetRank() + 1 is the highest rank that current player can promote to - if (member->IsRankNotLower(player->GetRank() + 1)) + // member->GetRankId() + 1 is the highest rank that current player can promote to + if (member->IsRankNotLower(rankId + 1)) { - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_HIGH_S, name); + SendCommandResult(session, type, ERR_GUILD_RANK_TOO_HIGH_S, name); return; } } - // When promoting player, rank is decreased, when demoting - increased uint32 newRankId = member->GetRankId() + (demote ? 1 : -1); member->ChangeRank(newRankId); _LogEvent(demote ? GUILD_EVENT_LOG_DEMOTE_PLAYER : GUILD_EVENT_LOG_PROMOTE_PLAYER, player->GetGUIDLow(), GUID_LOPART(member->GetGUID()), newRankId); @@ -1566,50 +1616,47 @@ void Guild::HandleUpdateMemberRank(WorldSession* session, const std::string& nam } } -void Guild::HandleAddNewRank(WorldSession* session, const std::string& name) +void Guild::HandleAddNewRank(WorldSession* session, std::string const& name) { - if (_GetRanksSize() >= GUILD_RANKS_MAX_COUNT) + uint8 size = _GetRanksSize(); + if (size >= GUILD_RANKS_MAX_COUNT) return; // Only leader can add new rank - if (!_IsLeader(session->GetPlayer())) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); - else - { - _CreateRank(name, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); - HandleQuery(session); - HandleRoster(); // Broadcast for tab rights update - } + if (_IsLeader(session->GetPlayer())) + if (_CreateRank(name, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK)) + { + char aux[2]; + sprintf(aux, "%u", size); + _BroadcastEvent(GE_RANK_UPDATED, 0, aux, name.c_str()); + } } void Guild::HandleRemoveLowestRank(WorldSession* session) { - // Cannot remove rank if total count is minimum allowed by the client - if (_GetRanksSize() <= GUILD_RANKS_MIN_COUNT) + HandleRemoveRank(session, _GetLowestRankId()); +} + +void Guild::HandleRemoveRank(WorldSession* session, uint8 rankId) +{ + // Cannot remove rank if total count is minimum allowed by the client or is not leader + if (_GetRanksSize() <= GUILD_RANKS_MIN_COUNT || rankId >= _GetRanksSize() || !_IsLeader(session->GetPlayer())) return; - // Only leader can delete ranks - if (!_IsLeader(session->GetPlayer())) - SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); - else - { - uint8 rankId = _GetLowestRankId(); - // Delete bank rights for rank - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHTS_FOR_RANK); - stmt->setUInt32(0, m_id); - stmt->setUInt8 (1, rankId); - CharacterDatabase.Execute(stmt); - // Delete rank - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_LOWEST_RANK); - stmt->setUInt32(0, m_id); - stmt->setUInt8 (1, rankId); - CharacterDatabase.Execute(stmt); + // Delete bank rights for rank + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHTS_FOR_RANK); + stmt->setUInt32(0, m_id); + stmt->setUInt8(1, rankId); + CharacterDatabase.Execute(stmt); + // Delete rank + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_LOWEST_RANK); + stmt->setUInt32(0, m_id); + stmt->setUInt8(1, rankId); + CharacterDatabase.Execute(stmt); - m_ranks.pop_back(); + m_ranks.pop_back(); - HandleQuery(session); - HandleRoster(); // Broadcast for tab rights update - } + _BroadcastEvent(GE_RANK_DELETED, 0); } void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount) @@ -1620,26 +1667,23 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount) sScriptMgr->OnGuildMemberDepositMoney(this, player, amount); SQLTransaction trans = CharacterDatabase.BeginTransaction(); - // Add money to bank _ModifyBankMoney(trans, amount, true); - // Remove money from player + player->ModifyMoney(-int32(amount)); player->SaveGoldToDB(trans); - // Log GM action (TODO: move to scripts) + _LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUIDLow(), amount); + + CharacterDatabase.CommitTransaction(trans); + + std::string aux = ByteArrayToHexStr(reinterpret_cast<uint8*>(&amount), 8, true); + _BroadcastEvent(GE_BANK_MONEY_CHANGED, 0, aux.c_str()); + if (!AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(player->GetSession()->GetAccountId(), "GM %s (Account: %u) deposit money (Amount: %u) to guild bank (Guild ID %u)", player->GetName().c_str(), player->GetSession()->GetAccountId(), amount, m_id); } - // Log guild bank event - _LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUIDLow(), amount); - - CharacterDatabase.CommitTransaction(trans); - - SendBankTabsInfo(session); - _SendBankContent(session, 0); - _SendBankMoneyUpdate(session); } bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair) @@ -1648,24 +1692,20 @@ bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool return false; Player* player = session->GetPlayer(); - if (!_HasRankRight(player, repair ? GR_RIGHT_WITHDRAW_REPAIR : GR_RIGHT_WITHDRAW_GOLD)) - return false; - uint32 remainingMoney = _GetMemberRemainingMoney(player->GetGUID()); - if (!remainingMoney) + Member* member = GetMember(player->GetGUID()); + if (!member) return false; - if (remainingMoney < amount) - return false; + if (uint32(_GetMemberRemainingMoney(member)) < amount) // Check if we have enough slot/money today + return false; // Call script after validation and before money transfer. sScriptMgr->OnGuildMemberWitdrawMoney(this, player, amount, repair); SQLTransaction trans = CharacterDatabase.BeginTransaction(); // Update remaining money amount - if (remainingMoney < uint32(GUILD_WITHDRAW_MONEY_UNLIMITED)) - if (Member* member = GetMember(player->GetGUID())) - member->DecreaseBankRemainingValue(trans, GUILD_BANK_MAX_TABS, amount); + member->UpdateBankWithdrawValue(trans, GUILD_BANK_MAX_TABS, amount); // Remove money from bank _ModifyBankMoney(trans, amount, false); // Add money to player (if required) @@ -1678,13 +1718,8 @@ bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool _LogBankEvent(trans, repair ? GUILD_BANK_LOG_REPAIR_MONEY : GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), player->GetGUIDLow(), amount); CharacterDatabase.CommitTransaction(trans); - SendMoneyInfo(session); - if (!repair) - { - SendBankTabsInfo(session); - _SendBankContent(session, 0); - _SendBankMoneyUpdate(session); - } + std::string aux = ByteArrayToHexStr(reinterpret_cast<uint8*>(&amount), 8, true); + _BroadcastEvent(GE_BANK_MONEY_CHANGED, 0, aux.c_str()); return true; } @@ -1695,6 +1730,7 @@ void Guild::HandleMemberLogout(WorldSession* session) { member->SetStats(player); member->UpdateLogoutTime(); + member->ResetFlags(); } _BroadcastEvent(GE_SIGNED_OFF, player->GetGUID(), player->GetName().c_str()); } @@ -1702,16 +1738,13 @@ void Guild::HandleMemberLogout(WorldSession* session) void Guild::HandleDisband(WorldSession* session) { // Only leader can disband guild - if (!_IsLeader(session->GetPlayer())) - Guild::SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS); - else + if (_IsLeader(session->GetPlayer())) { Disband(); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Guild Successfully Disbanded"); + sLog->outDebug(LOG_FILTER_GUILD, "Guild Successfully Disbanded"); } } -/////////////////////////////////////////////////////////////////////////////// // Send data to client void Guild::SendInfo(WorldSession* session) const { @@ -1722,7 +1755,7 @@ void Guild::SendInfo(WorldSession* session) const data << m_accountsNumber; // Number of accounts session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_INFO)"); + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_INFO [%s]", session->GetPlayerInfo().c_str()); } void Guild::SendEventLog(WorldSession* session) const @@ -1730,7 +1763,7 @@ void Guild::SendEventLog(WorldSession* session) const WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 1 + m_eventLog->GetSize() * (1 + 8 + 4)); m_eventLog->WritePacket(data); session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)"); + sLog->outDebug(LOG_FILTER_GUILD, "MSG_GUILD_EVENT_LOG_QUERY [%s]", session->GetPlayerInfo().c_str()); } void Guild::SendBankLog(WorldSession* session, uint8 tabId) const @@ -1743,87 +1776,87 @@ void Guild::SendBankLog(WorldSession* session, uint8 tabId) const data << uint8(tabId); pLog->WritePacket(data); session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (MSG_GUILD_BANK_LOG_QUERY)"); + sLog->outDebug(LOG_FILTER_GUILD, "MSG_GUILD_BANK_LOG_QUERY [%s]", session->GetPlayerInfo().c_str()); } } void Guild::SendBankTabData(WorldSession* session, uint8 tabId) const { if (tabId < _GetPurchasedTabsSize()) - { - SendMoneyInfo(session); _SendBankContent(session, tabId); - } } -void Guild::SendBankTabsInfo(WorldSession* session) const +void Guild::SendBankTabsInfo(WorldSession* session, bool sendAllSlots /*= false*/) const { - WorldPacket data(SMSG_GUILD_BANK_LIST, 500); - - data << uint64(m_bankMoney); - data << uint8(0); // TabInfo packet must be for tabId 0 - data << uint32(_GetMemberRemainingSlots(session->GetPlayer()->GetGUID(), 0)); - data << uint8(1); // Tell client that this packet includes tab info - - data << uint8(_GetPurchasedTabsSize()); // Number of tabs - for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i) - m_bankTabs[i]->WriteInfoPacket(data); - - data << uint8(0); // Do not send tab content - session->SendPacket(&data); - - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)"); + _SendBankList(session, 0, sendAllSlots); } void Guild::SendBankTabText(WorldSession* session, uint8 tabId) const { - if (const BankTab* pTab = GetBankTab(tabId)) - pTab->SendText(this, session); + if (BankTab const* tab = GetBankTab(tabId)) + tab->SendText(this, session); } void Guild::SendPermissions(WorldSession* session) const { - uint64 guid = session->GetPlayer()->GetGUID(); - uint8 rankId = session->GetPlayer()->GetRank(); + Member const* member = GetMember(session->GetPlayer()->GetGUID()); + if (!member) + return; + + uint8 rankId = member->GetRankId(); WorldPacket data(MSG_GUILD_PERMISSIONS, 4 * 15 + 1); data << uint32(rankId); data << uint32(_GetRankRights(rankId)); - data << uint32(_GetMemberRemainingMoney(guid)); - data << uint8 (_GetPurchasedTabsSize()); - // Why sending all info when not all tabs are purchased??? + data << uint32(_GetMemberRemainingMoney(member)); + data << uint8(_GetPurchasedTabsSize()); for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId) { data << uint32(_GetRankBankTabRights(rankId, tabId)); - data << uint32(_GetMemberRemainingSlots(guid, tabId)); + data << uint32(_GetMemberRemainingSlots(member, tabId)); } + session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (MSG_GUILD_PERMISSIONS)"); + sLog->outDebug(LOG_FILTER_GUILD, "MSG_GUILD_PERMISSIONS [%s] Rank: %u", session->GetPlayerInfo().c_str(), rankId); } void Guild::SendMoneyInfo(WorldSession* session) const { + Member const* member = GetMember(session->GetPlayer()->GetGUID()); + if (!member) + return; + + int32 amount = _GetMemberRemainingMoney(member); WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4); - data << uint32(_GetMemberRemainingMoney(session->GetPlayer()->GetGUID())); + data << int32(amount); session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN"); + sLog->outDebug(LOG_FILTER_GUILD, "MSG_GUILD_BANK_MONEY_WITHDRAWN [%s] Money: %u", session->GetPlayerInfo().c_str(), amount); } -void Guild::SendLoginInfo(WorldSession* session) const +void Guild::SendLoginInfo(WorldSession* session) { WorldPacket data(SMSG_GUILD_EVENT, 1 + 1 + m_motd.size() + 1); data << uint8(GE_MOTD); data << uint8(1); data << m_motd; session->SendPacket(&data); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent guild MOTD (SMSG_GUILD_EVENT)"); + + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_EVENT [%s] MOTD", session->GetPlayerInfo().c_str()); SendBankTabsInfo(session); - _BroadcastEvent(GE_SIGNED_ON, session->GetPlayer()->GetGUID(), session->GetPlayer()->GetName().c_str()); + Player* player = session->GetPlayer(); + + HandleRoster(session); + _BroadcastEvent(GE_SIGNED_ON, player->GetGUID(), player->GetName().c_str()); + + if (Member* member = GetMember(player->GetGUID())) + { + member->SetStats(player); + member->AddFlag(GUILDMEMBER_STATUS_ONLINE); + } } -/////////////////////////////////////////////////////////////////////////////// // Loading methods bool Guild::LoadFromDB(Field* fields) { @@ -1873,10 +1906,10 @@ bool Guild::LoadMemberFromDB(Field* fields) void Guild::LoadBankRightFromDB(Field* fields) { - // rights slots - GuildBankRightsAndSlots rightsAndSlots(fields[3].GetUInt8(), fields[4].GetUInt32()); - // rankId tabId - _SetRankBankTabRightsAndSlots(fields[2].GetUInt8(), fields[1].GetUInt8(), rightsAndSlots, false); + // tabId rights slots + GuildBankRightsAndSlots rightsAndSlots(fields[1].GetUInt8(), fields[3].GetUInt8(), fields[4].GetUInt32()); + // rankId + _SetRankBankTabRightsAndSlots(fields[2].GetUInt8(), rightsAndSlots, false); } bool Guild::LoadEventLogFromDB(Field* fields) @@ -1936,15 +1969,13 @@ bool Guild::LoadBankEventLogFromDB(Field* fields) return true; } -bool Guild::LoadBankTabFromDB(Field* fields) +void Guild::LoadBankTabFromDB(Field* fields) { uint8 tabId = fields[1].GetUInt8(); if (tabId >= _GetPurchasedTabsSize()) - { sLog->outError(LOG_FILTER_GUILD, "Invalid tab (tabId: %u) in guild bank, skipped.", tabId); - return false; - } - return m_bankTabs[tabId]->LoadFromDB(fields); + else + m_bankTabs[tabId]->LoadFromDB(fields); } bool Guild::LoadBankItemFromDB(Field* fields) @@ -1968,14 +1999,15 @@ bool Guild::Validate() // Between ranks in sequence cannot be gaps - so 0, 1, 2, 4 is impossible // Min ranks count is 5 and max is 10. bool broken_ranks = false; - if (_GetRanksSize() < GUILD_RANKS_MIN_COUNT || _GetRanksSize() > GUILD_RANKS_MAX_COUNT) + uint8 ranks = _GetRanksSize(); + if (ranks < GUILD_RANKS_MIN_COUNT || ranks > GUILD_RANKS_MAX_COUNT) { sLog->outError(LOG_FILTER_GUILD, "Guild %u has invalid number of ranks, creating new...", m_id); broken_ranks = true; } else { - for (uint8 rankId = 0; rankId < _GetRanksSize(); ++rankId) + for (uint8 rankId = 0; rankId < ranks; ++rankId) { RankInfo* rankInfo = GetRankInfo(rankId); if (rankInfo->GetId() != rankId) @@ -1983,6 +2015,15 @@ bool Guild::Validate() sLog->outError(LOG_FILTER_GUILD, "Guild %u has broken rank id %u, creating default set of ranks...", m_id, rankId); broken_ranks = true; } + else + { + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + if (rankInfo->CreateMissingTabsIfNeeded(_GetPurchasedTabsSize(), trans)) + { + sLog->outError(LOG_FILTER_GUILD, "Guild %u has broken Tabs for rank id %u, creating default tab...", m_id, rankId); + CharacterDatabase.CommitTransaction(trans); + } + } } } @@ -2024,9 +2065,8 @@ bool Guild::Validate() return true; } -/////////////////////////////////////////////////////////////////////////////// // Broadcasts -void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, const std::string& msg, uint32 language) const +void Guild::BroadcastToGuild(WorldSession* session, bool officerOnly, std::string const& msg, uint32 language) const { if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK)) { @@ -2055,7 +2095,6 @@ void Guild::BroadcastPacket(WorldPacket* packet) const player->GetSession()->SendPacket(packet); } -/////////////////////////////////////////////////////////////////////////////// // Members handling bool Guild::AddMember(uint64 guid, uint8 rankId) { @@ -2075,15 +2114,26 @@ bool Guild::AddMember(uint64 guid, uint8 rankId) uint32 lowguid = GUID_LOPART(guid); - // If rank was not passed, assing lowest possible rank + // If rank was not passed, assign lowest possible rank if (rankId == GUILD_RANK_NONE) rankId = _GetLowestRankId(); Member* member = new Member(m_id, guid, rankId); + std::string name; if (player) + { + m_members[lowguid] = member; + player->SetInGuild(m_id); + player->SetGuildIdInvited(0); + player->SetRank(rankId); member->SetStats(player); + SendLoginInfo(player->GetSession()); + name = player->GetName(); + } else { + member->ResetFlags(); + bool ok = false; // Player must exist PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DATA_FOR_GUILD); @@ -2091,8 +2141,9 @@ bool Guild::AddMember(uint64 guid, uint8 rankId) if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) { Field* fields = result->Fetch(); + name = fields[0].GetString(); member->SetStats( - fields[0].GetString(), + name, fields[1].GetUInt8(), fields[2].GetUInt8(), fields[3].GetUInt16(), @@ -2105,20 +2156,15 @@ bool Guild::AddMember(uint64 guid, uint8 rankId) delete member; return false; } + m_members[lowguid] = member; } - m_members[lowguid] = member; SQLTransaction trans(NULL); member->SaveToDB(trans); - // If player not in game data in will be loaded from guild tables, so no need to update it! - if (player) - { - player->SetInGuild(m_id); - player->SetRank(rankId); - player->SetGuildIdInvited(0); - } _UpdateAccountsNumber(); + _LogEvent(GUILD_EVENT_LOG_JOIN_GUILD, lowguid); + _BroadcastEvent(GE_JOINED, guid, name.c_str()); // Call scripts if member was succesfully added (and stored to database) sScriptMgr->OnGuildAddMember(this, player, rankId); @@ -2144,6 +2190,7 @@ void Guild::DeleteMember(uint64 guid, bool isDisbanding, bool isKicked) else if (!newLeader || newLeader->GetRankId() > i->second->GetRankId()) newLeader = i->second; } + if (!newLeader) { Disband(); @@ -2163,7 +2210,7 @@ void Guild::DeleteMember(uint64 guid, bool isDisbanding, bool isKicked) _BroadcastEvent(GE_LEFT, guid, oldLeader->GetName().c_str()); } } - // Call script on remove before member is acutally removed from guild (and database) + // Call script on remove before member is actually removed from guild (and database) sScriptMgr->OnGuildRemoveMember(this, player, isDisbanding, isKicked); if (Member* member = GetMember(guid)) @@ -2193,7 +2240,6 @@ bool Guild::ChangeMemberRank(uint64 guid, uint8 newRank) return false; } -/////////////////////////////////////////////////////////////////////////////// // Bank (items move) void Guild::SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount) { @@ -2222,9 +2268,8 @@ void Guild::SwapItemsWithInventory(Player* player, bool toChar, uint8 tabId, uin _MoveItems(&charData, &bankData, splitedAmount); } -/////////////////////////////////////////////////////////////////////////////// // Bank tabs -void Guild::SetBankTabText(uint8 tabId, const std::string& text) +void Guild::SetBankTabText(uint8 tabId, std::string const& text) { if (BankTab* pTab = GetBankTab(tabId)) { @@ -2233,7 +2278,6 @@ void Guild::SetBankTabText(uint8 tabId, const std::string& text) } } -/////////////////////////////////////////////////////////////////////////////// // Private methods void Guild::_CreateLogHolders() { @@ -2242,18 +2286,14 @@ void Guild::_CreateLogHolders() m_bankEventLog[tabId] = new LogHolder(m_id, sWorld->getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT)); } -bool Guild::_CreateNewBankTab() +void Guild::_CreateNewBankTab() { - if (_GetPurchasedTabsSize() >= GUILD_BANK_MAX_TABS) - return false; - uint8 tabId = _GetPurchasedTabsSize(); // Next free id m_bankTabs.push_back(new BankTab(m_id, tabId)); - PreparedStatement* stmt = NULL; SQLTransaction trans = CharacterDatabase.BeginTransaction(); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_TAB); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_TAB); stmt->setUInt32(0, m_id); stmt->setUInt8 (1, tabId); trans->Append(stmt); @@ -2264,14 +2304,11 @@ bool Guild::_CreateNewBankTab() trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); - return true; } void Guild::_CreateDefaultGuildRanks(LocaleConstant loc) { - PreparedStatement* stmt = NULL; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_RANKS); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_RANKS); stmt->setUInt32(0, m_id); CharacterDatabase.Execute(stmt); @@ -2286,29 +2323,22 @@ void Guild::_CreateDefaultGuildRanks(LocaleConstant loc) _CreateRank(sObjectMgr->GetTrinityString(LANG_GUILD_INITIATE, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK); } -void Guild::_CreateRank(const std::string& name, uint32 rights) +bool Guild::_CreateRank(std::string const& name, uint32 rights) { - if (_GetRanksSize() >= GUILD_RANKS_MAX_COUNT) - return; - - // Ranks represent sequence 0, 1, 2, ... where 0 means guildmaster uint8 newRankId = _GetRanksSize(); + if (newRankId >= GUILD_RANKS_MAX_COUNT) + return false; + // Ranks represent sequence 0, 1, 2, ... where 0 means guildmaster RankInfo info(m_id, newRankId, name, rights, 0); m_ranks.push_back(info); SQLTransaction trans = CharacterDatabase.BeginTransaction(); - for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i) - { - // Create bank rights with default values - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_BANK_RIGHT_DEFAULT); - stmt->setUInt32(0, m_id); - stmt->setUInt8 (1, i); - stmt->setUInt8 (2, newRankId); - trans->Append(stmt); - } + info.CreateMissingTabsIfNeeded(_GetPurchasedTabsSize(), trans); info.SaveToDB(trans); CharacterDatabase.CommitTransaction(trans); + + return true; } // Updates the number of accounts that are in the guild @@ -2382,28 +2412,16 @@ void Guild::_SetLeaderGUID(Member* pLeader) void Guild::_SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay) { if (RankInfo* rankInfo = GetRankInfo(rankId)) - { - for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) - if (itr->second->IsRank(rankId)) - itr->second->ResetMoneyTime(); - rankInfo->SetBankMoneyPerDay(moneyPerDay); - } } -void Guild::_SetRankBankTabRightsAndSlots(uint8 rankId, uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB) +void Guild::_SetRankBankTabRightsAndSlots(uint8 rankId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB) { - if (tabId >= _GetPurchasedTabsSize()) + if (rightsAndSlots.GetTabId() >= _GetPurchasedTabsSize()) return; if (RankInfo* rankInfo = GetRankInfo(rankId)) - { - for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) - if (itr->second->IsRank(rankId)) - itr->second->ResetTabTimes(); - - rankInfo->SetBankTabSlotsAndRights(tabId, rightsAndSlots, saveToDB); - } + rankInfo->SetBankTabSlotsAndRights(rightsAndSlots, saveToDB); } inline std::string Guild::_GetRankName(uint8 rankId) const @@ -2420,14 +2438,14 @@ inline uint32 Guild::_GetRankRights(uint8 rankId) const return 0; } -inline uint32 Guild::_GetRankBankMoneyPerDay(uint8 rankId) const +inline int32 Guild::_GetRankBankMoneyPerDay(uint8 rankId) const { if (const RankInfo* rankInfo = GetRankInfo(rankId)) return rankInfo->GetBankMoneyPerDay(); return 0; } -inline uint32 Guild::_GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const +inline int32 Guild::_GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const { if (tabId < _GetPurchasedTabsSize()) if (const RankInfo* rankInfo = GetRankInfo(rankId)) @@ -2435,35 +2453,57 @@ inline uint32 Guild::_GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const return 0; } -inline uint8 Guild::_GetRankBankTabRights(uint8 rankId, uint8 tabId) const +inline int8 Guild::_GetRankBankTabRights(uint8 rankId, uint8 tabId) const { if (const RankInfo* rankInfo = GetRankInfo(rankId)) return rankInfo->GetBankTabRights(tabId); return 0; } -inline uint32 Guild::_GetMemberRemainingSlots(uint64 guid, uint8 tabId) const +inline int32 Guild::_GetMemberRemainingSlots(Member const* member, uint8 tabId) const { - if (const Member* member = GetMember(guid)) - return member->GetBankRemainingValue(tabId, this); + if (member) + { + uint8 rankId = member->GetRankId(); + if (rankId == GR_GUILDMASTER) + return GUILD_WITHDRAW_SLOT_UNLIMITED; + if ((_GetRankBankTabRights(rankId, tabId) & GUILD_BANK_RIGHT_VIEW_TAB) != GR_RIGHT_EMPTY) + { + int32 remaining = _GetRankBankTabSlotsPerDay(rankId, tabId) - member->GetBankWithdrawValue(tabId); + if (remaining > 0) + return remaining; + } + } return 0; } -inline uint32 Guild::_GetMemberRemainingMoney(uint64 guid) const +inline int32 Guild::_GetMemberRemainingMoney(Member const* member) const { - if (const Member* member = GetMember(guid)) - return member->GetBankRemainingValue(GUILD_BANK_MAX_TABS, this); + if (member) + { + uint8 rankId = member->GetRankId(); + if (rankId == GR_GUILDMASTER) + return GUILD_WITHDRAW_MONEY_UNLIMITED; + + if ((_GetRankRights(rankId) & (GR_RIGHT_WITHDRAW_REPAIR | GR_RIGHT_WITHDRAW_GOLD)) != GR_RIGHT_EMPTY) + { + int32 remaining = _GetRankBankMoneyPerDay(rankId) - member->GetBankWithdrawValue(GUILD_BANK_MAX_TABS); + if (remaining > 0) + return remaining; + } + } return 0; } -inline void Guild::_DecreaseMemberRemainingSlots(SQLTransaction& trans, uint64 guid, uint8 tabId) +inline void Guild::_UpdateMemberWithdrawSlots(SQLTransaction& trans, uint64 guid, uint8 tabId) { - // Remaining slots must be more then 0 - if (uint32 remainingSlots = _GetMemberRemainingSlots(guid, tabId)) - // Ignore guild master - if (remainingSlots < uint32(GUILD_WITHDRAW_SLOT_UNLIMITED)) - if (Member* member = GetMember(guid)) - member->DecreaseBankRemainingValue(trans, tabId, 1); + if (Member* member = GetMember(guid)) + { + uint8 rankId = member->GetRankId(); + if (rankId != GR_GUILDMASTER + && member->GetBankWithdrawValue(tabId) < _GetRankBankTabSlotsPerDay(rankId, tabId)) + member->UpdateBankWithdrawValue(trans, tabId, 1); + } } inline bool Guild::_MemberHasTabRights(uint64 guid, uint8 tabId, uint32 rights) const @@ -2494,6 +2534,10 @@ void Guild::_LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventTyp if (tabId > GUILD_BANK_MAX_TABS) return; + // not logging moves within the same tab + if (eventType == GUILD_BANK_LOG_MOVE_ITEM && tabId == destTabId) + return; + uint8 dbTabId = tabId; if (BankEventLogEntry::IsMoneyEvent(eventType)) { @@ -2531,7 +2575,7 @@ void Guild::_MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAm /* if (pItemSrc->GetCount() == 0) { - sLog->outFatal(LOG_FILTER_GENERAL, "Guild::SwapItems: Player %s(GUIDLow: %u) tried to move item %u from tab %u slot %u to tab %u slot %u, but item %u has a stack of zero!", + sLog->outFatal(LOG_FILTER_GUILD, "Guild::SwapItems: Player %s(GUIDLow: %u) tried to move item %u from tab %u slot %u to tab %u slot %u, but item %u has a stack of zero!", player->GetName(), player->GetGUIDLow(), pItemSrc->GetEntry(), tabId, slotId, destTabId, destSlotId, pItemSrc->GetEntry()); //return; // Commented out for now, uncomment when it's verified that this causes a crash!! } @@ -2627,36 +2671,15 @@ bool Guild::_DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError void Guild::_SendBankContent(WorldSession* session, uint8 tabId) const { uint64 guid = session->GetPlayer()->GetGUID(); - if (_MemberHasTabRights(guid, tabId, GUILD_BANK_RIGHT_VIEW_TAB)) - if (const BankTab* pTab = GetBankTab(tabId)) - { - WorldPacket data(SMSG_GUILD_BANK_LIST, 1200); - - data << uint64(m_bankMoney); - data << uint8(tabId); - data << uint32(_GetMemberRemainingSlots(guid, tabId)); - data << uint8(0); // Tell client that there's no tab info in this packet - - pTab->WritePacket(data); - - session->SendPacket(&data); + if (!_MemberHasTabRights(guid, tabId, GUILD_BANK_RIGHT_VIEW_TAB)) + return; - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)"); - } + _SendBankList(session, tabId, true); } void Guild::_SendBankMoneyUpdate(WorldSession* session) const { - WorldPacket data(SMSG_GUILD_BANK_LIST, 8 + 1 + 4 + 1 + 1); - - data << uint64(m_bankMoney); - data << uint8(0); // tabId, default 0 - data << uint32(_GetMemberRemainingSlots(session->GetPlayer()->GetGUID(), 0)); - data << uint8(0); // Tell that there's no tab info in this packet - data << uint8(0); // No items - BroadcastPacket(&data); - - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)"); + _SendBankList(session); } void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const @@ -2687,37 +2710,13 @@ void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) cons tabId = pDest->GetContainer(); pDest->CopySlots(slots); } + _SendBankContentUpdate(tabId, slots); } void Guild::_SendBankContentUpdate(uint8 tabId, SlotIds slots) const { - if (const BankTab* pTab = GetBankTab(tabId)) - { - WorldPacket data(SMSG_GUILD_BANK_LIST, 1200); - - data << uint64(m_bankMoney); - 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 - - data << uint8(slots.size()); - for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId) - if (slots.find(slotId) != slots.end()) - pTab->WriteSlotPacket(data, slotId); - - for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) - if (_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB)) - if (Player* player = itr->second->FindPlayer()) - { - data.put<uint32>(rempos, uint32(_GetMemberRemainingSlots(player->GetGUID(), tabId))); - player->GetSession()->SendPacket(&data); - } - - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent (SMSG_GUILD_BANK_LIST)"); - } + _SendBankList(NULL, tabId, false, &slots); } void Guild::_BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* param1, const char* param2, const char* param3) const @@ -2739,6 +2738,73 @@ void Guild::_BroadcastEvent(GuildEvents guildEvent, uint64 guid, const char* par data << uint64(guid); BroadcastPacket(&data); + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_EVENT [Broadcast] Event: %u", guildEvent); +} + +void Guild::_SendBankList(WorldSession* session /* = NULL*/, uint8 tabId /*= 0*/, bool sendAllSlots /*= false*/, SlotIds *slots /*= NULL*/) const +{ + WorldPacket data(SMSG_GUILD_BANK_LIST, 500); + data << uint64(m_bankMoney); + data << uint8(tabId); + size_t rempos = data.wpos(); + data << uint32(0); + data << uint8(sendAllSlots); + + if (sendAllSlots && !tabId) + { + data << uint8(_GetPurchasedTabsSize()); // Number of tabs + for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i) + m_bankTabs[i]->WriteInfoPacket(data); + } + + BankTab const* tab = GetBankTab(tabId); + if (!tab) + data << uint8(0); + else if (sendAllSlots) + tab->WritePacket(data); + else if (slots && !slots->empty()) + { + data << uint8(slots->size()); + for (SlotIds::const_iterator itr = slots->begin(); itr != slots->end(); ++itr) + tab->WriteSlotPacket(data, *itr, false); + } + else + data << uint8(0); + + if (session) + { + int32 numSlots = 0; + if (Member const* member = GetMember(session->GetPlayer()->GetGUID())) + numSlots = _GetMemberRemainingSlots(member, tabId); + data.put<uint32>(rempos, numSlots); + session->SendPacket(&data); + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_BANK_LIST [%s]: TabId: %u, FullSlots: %u, slots: %d", + session->GetPlayerInfo().c_str(), tabId, sendAllSlots, numSlots); + } + else // TODO - Probably this is just sent to session + those that have sent CMSG_GUILD_BANKER_ACTIVATE + { + for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) + { + if (!_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB)) + continue; + Player* player = itr->second->FindPlayer(); + if (!player) + continue; + + uint32 numSlots = _GetMemberRemainingSlots(itr->second, tabId); + data.put<uint32>(rempos, numSlots); + player->GetSession()->SendPacket(&data); + sLog->outDebug(LOG_FILTER_GUILD, "SMSG_GUILD_BANK_LIST [%s]: TabId: %u, FullSlots: %u, slots: %u" + , player->GetName().c_str(), tabId, sendAllSlots, numSlots); + } + } +} + +void Guild::ResetTimes() +{ + for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) + itr->second->ResetValues(); - sLog->outDebug(LOG_FILTER_GUILD, "WORLD: Sent SMSG_GUILD_EVENT"); + // Hack... way to force client to ask for money/slots + _BroadcastEvent(GE_RANK_UPDATED, 0, "0", GetRankInfo(0)->GetName().c_str()); } |