diff options
Diffstat (limited to 'src/server/game/Guilds')
| -rw-r--r-- | src/server/game/Guilds/Guild.cpp | 132 | ||||
| -rwxr-xr-x | src/server/game/Guilds/Guild.h | 14 | ||||
| -rw-r--r-- | src/server/game/Guilds/GuildMgr.cpp | 78 | ||||
| -rw-r--r-- | src/server/game/Guilds/GuildMgr.h | 9 |
4 files changed, 215 insertions, 18 deletions
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index ba9d8610c12..322e953be4a 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1060,7 +1060,8 @@ InventoryResult Guild::BankMoveItemData::CanStore(Item* pItem, bool swap) /////////////////////////////////////////////////////////////////////////////// // Guild -Guild::Guild() : m_id(0), m_leaderGuid(0), m_createdDate(0), m_accountsNumber(0), m_bankMoney(0), m_eventLog(NULL), m_achievementMgr(this), m_level(1) +Guild::Guild() : m_id(0), m_leaderGuid(0), m_createdDate(0), m_accountsNumber(0), m_bankMoney(0), m_eventLog(NULL), + m_achievementMgr(this), _level(1), _experience(0), _todayExperience(0) { memset(&m_bankEventLog, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(LogHolder*)); } @@ -1098,7 +1099,7 @@ bool Guild::Create(Player* pLeader, const std::string& name) m_motd = "No message set."; m_bankMoney = 0; m_createdDate = ::time(NULL); - m_level = 1; + _level = 1; _CreateLogHolders(); sLog->outDebug(LOG_FILTER_GUILD, "GUILD: creating guild [%s] for leader %s (%u)", @@ -1196,6 +1197,13 @@ void Guild::SaveToDB() { SQLTransaction trans = CharacterDatabase.BeginTransaction(); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_EXPERIENCE); + stmt->setUInt32(0, GetLevel()); + stmt->setUInt64(1, GetExperience()); + stmt->setUInt64(2, GetTodayExperience()); + stmt->setUInt32(3, GetId()); + trans->Append(stmt); + m_achievementMgr.SaveToDB(trans); CharacterDatabase.CommitTransaction(trans); @@ -1291,7 +1299,7 @@ void Guild::HandleRoster(WorldSession* session /*= NULL*/) data.WriteString(m_motd); data << uint32(m_accountsNumber); - data << uint32(GUILD_REPUTATION_WEEKLY_CAP); + data << uint32(sWorld->getIntConfig(CONFIG_GUILD_WEEKLY_REP_CAP)); data << uint32(secsToTimeBitFields(m_createdDate)); data << uint32(0); @@ -1669,6 +1677,8 @@ 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); + else if (GetLevel() >= sWorld->getIntConfig(CONFIG_GUILD_UNDELETABLE_LEVEL)) + SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL); else // Guild is disbanded if leader leaves. Disband(); @@ -1924,6 +1934,8 @@ 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 (GetLevel() >= sWorld->getIntConfig(CONFIG_GUILD_UNDELETABLE_LEVEL)) + Guild::SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL); else { Disband(); @@ -1941,11 +1953,11 @@ void Guild::HandleGuildPartyRequest(WorldSession* session) return; WorldPacket data(SMSG_GUILD_PARTY_STATE_RESPONSE, 13); - data.WriteBit(0); // Is guild group + data.WriteBit(player->GetMap()->GetOwnerGuildId(player->GetTeam()) == GetId()); // Is guild group data.FlushBits(); - data << float(0.f); // Guild XP multiplier - data << uint32(0); // Current guild members - data << uint32(0); // Needed guild members + data << float(0.f); // Guild XP multiplier + data << uint32(0); // Current guild members + data << uint32(0); // Needed guild members session->SendPacket(&data); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_GUILD_PARTY_STATE_RESPONSE)"); @@ -2129,17 +2141,20 @@ void Guild::SendLoginInfo(WorldSession* session) const data << uint64(session->GetPlayer()->GetGUID()); session->SendPacket(&data); + data.Initialize(SMSG_GUILD_MEMBER_DAILY_RESET, 0); // tells the client to request bank withdrawal limit + session->SendPacket(&data); + + if (!sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED)) + return; + for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i) if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i)) if (entry->Level >= GetLevel()) - session->GetPlayer()->learnSpell(entry->SpellId, false); + session->GetPlayer()->learnSpell(entry->SpellId, true); SendGuildReputationWeeklyCap(session); GetAchievementMgr().SendAllAchievementData(session->GetPlayer()); - - data.Initialize(SMSG_GUILD_MEMBER_DAILY_RESET, 0); // tells the client to request bank withdrawal limit - session->SendPacket(&data); } void Guild::SendGuildReputationWeeklyCap(WorldSession* session) const @@ -2164,8 +2179,11 @@ bool Guild::LoadFromDB(Field* fields) m_motd = fields[9].GetString(); m_createdDate = time_t(fields[10].GetUInt32()); m_bankMoney = fields[11].GetUInt64(); + _level = fields[12].GetUInt32(); + _experience = fields[13].GetUInt64(); + _todayExperience = fields[14].GetUInt64(); - uint8 purchasedTabs = uint8(fields[12].GetUInt64()); + uint8 purchasedTabs = uint8(fields[15].GetUInt64()); if (purchasedTabs > GUILD_BANK_MAX_TABS) purchasedTabs = GUILD_BANK_MAX_TABS; @@ -2459,8 +2477,16 @@ bool Guild::AddMember(uint64 guid, uint8 rankId) { player->SetInGuild(m_id); player->SetRank(rankId); - player->SetGuildLevel(m_level); + player->SetGuildLevel(GetLevel()); player->SetGuildIdInvited(0); + + if (sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED)) + { + for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i) + if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i)) + if (entry->Level >= GetLevel()) + player->learnSpell(entry->SpellId, true); + } } _UpdateAccountsNumber(); @@ -2520,6 +2546,11 @@ void Guild::DeleteMember(uint64 guid, bool isDisbanding, bool isKicked) { player->SetInGuild(0); player->SetRank(0); + player->SetGuildLevel(0); + for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i) + if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i)) + if (entry->Level >= GetLevel()) + player->removeSpell(entry->SpellId, false, false); } _DeleteMemberFromDB(lowguid); @@ -3152,3 +3183,78 @@ void Guild::SendGuildRanksUpdate(uint64 setterGuid, uint64 targetGuid, uint32 ra sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_GUILD_RANKS_UPDATE"); } + +void Guild::GiveXP(uint32 xp, Player* source) +{ + if (!sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED)) + return; + + /// @TODO: Award reputation and count activity for player + + if (GetLevel() >= sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL)) + xp = 0; // SMSG_GUILD_XP_GAIN is always sent, even for no gains + + if (GetLevel() >= GUILD_EXPERIENCE_UNCAPPED_LEVEL) + xp = std::min(xp, sWorld->getIntConfig(CONFIG_GUILD_DAILY_XP_CAP) - uint32(_todayExperience)); + + WorldPacket data(SMSG_GUILD_XP_GAIN, 8); + data << uint64(xp); + source->GetSession()->SendPacket(&data); + + _experience += xp; + _todayExperience += xp; + + if (!xp) + return; + + uint32 oldLevel = GetLevel(); + + // Ding, mon! + while (GetExperience() >= sGuildMgr->GetXPForGuildLevel(GetLevel()) && GetLevel() < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL)) + { + _experience -= sGuildMgr->GetXPForGuildLevel(GetLevel()); + ++_level; + } + + // Find all guild perks to learn + std::vector<uint32> perksToLearn; + for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i) + if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i)) + if (entry->Level > oldLevel && entry->Level <= GetLevel()) + perksToLearn.push_back(entry->SpellId); + + // Notify all online players that guild level changed and learn perks + for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) + { + if (Player* player = itr->second->FindPlayer()) + { + player->SetGuildLevel(GetLevel()); + for (size_t i = 0; i < perksToLearn.size(); ++i) + player->learnSpell(perksToLearn[i], true); + } + } + + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL, GetLevel(), 0, NULL, source); +} + +void Guild::SendGuildXP(WorldSession* session) const +{ + Member const* member = GetMember(session->GetGuidLow()); + + WorldPacket data(SMSG_GUILD_XP, 40); + data << uint64(/*member ? member->GetTotalActivity() :*/ 0); + data << uint64(sGuildMgr->GetXPForGuildLevel(GetLevel()) - GetExperience()); // XP missing for next level + data << uint64(GetTodayExperience()); + data << uint64(/*member ? member->GetWeeklyActivity() :*/ 0); + data << uint64(GetExperience()); + session->SendPacket(&data); +} + +void Guild::ResetDailyExperience() +{ + _todayExperience = 0; + + for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) + if (Player* player = itr->second->FindPlayer()) + SendGuildXP(player->GetSession()); +} diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index 1adf1675c45..b7613957a45 100755 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -225,7 +225,7 @@ enum GuildMemberFlags GUILDMEMBER_STATUS_MOBILE = 0x0008, // remote chat from mobile app }; -#define GUILD_REPUTATION_WEEKLY_CAP 4375 +#define GUILD_EXPERIENCE_UNCAPPED_LEVEL 20 ///> Hardcoded in client, starting from this level, guild daily experience gain is unlimited. //////////////////////////////////////////////////////////////////////////////////////////// // Emblem info @@ -675,6 +675,7 @@ public: void SendMoneyInfo(WorldSession* session) const; void SendLoginInfo(WorldSession* session) const; void SendGuildReputationWeeklyCap(WorldSession* session) const; + void SendGuildXP(WorldSession* session) const; // Load from DB bool LoadFromDB(Field* fields); @@ -720,7 +721,12 @@ public: AchievementMgr<Guild>& GetAchievementMgr() { return m_achievementMgr; } AchievementMgr<Guild> const& GetAchievementMgr() const { return m_achievementMgr; } - uint32 GetLevel() const { return m_level; } + // Guild leveling + uint32 GetLevel() const { return _level; } + void GiveXP(uint32 xp, Player* source); + uint64 GetExperience() const { return _experience; } + uint64 GetTodayExperience() const { return _todayExperience; } + void ResetDailyExperience(); protected: uint32 m_id; @@ -744,7 +750,9 @@ protected: AchievementMgr<Guild> m_achievementMgr; - uint32 m_level; + uint32 _level; + uint64 _experience; + uint64 _todayExperience; private: inline uint32 _GetRanksSize() const { return uint32(m_ranks.size()); } diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp index 04b0cfeaa39..726add2cf44 100644 --- a/src/server/game/Guilds/GuildMgr.cpp +++ b/src/server/game/Guilds/GuildMgr.cpp @@ -107,6 +107,26 @@ Guild* GuildMgr::GetGuildByLeader(uint64 guid) const return NULL; } +uint32 GuildMgr::GetXPForGuildLevel(uint8 level) const +{ + if (level < GuildXPperLevel.size()) + return GuildXPperLevel[level]; + return 0; +} + +void GuildMgr::ResetExperienceCaps() +{ + CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE)); + + for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr) + itr->second->ResetDailyExperience(); +} + +void GuildMgr::ResetReputationCaps() +{ + /// @TODO: Implement +} + void GuildMgr::LoadGuilds() { // 1. Load all guilds @@ -116,8 +136,8 @@ void GuildMgr::LoadGuilds() // 0 1 2 3 4 5 6 QueryResult result = CharacterDatabase.Query("SELECT g.guildid, g.name, g.leaderguid, g.EmblemStyle, g.EmblemColor, g.BorderStyle, g.BorderColor, " - // 7 8 9 10 11 12 - "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, COUNT(gbt.guildid) " + // 7 8 9 10 11 12 13 14 15 + "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, g.level, g.experience, g.todayExperience, COUNT(gbt.guildid) " "FROM guild g LEFT JOIN guild_bank_tab gbt ON g.guildid = gbt.guildid GROUP BY g.guildid ORDER BY g.guildid ASC"); if (!result) @@ -435,3 +455,57 @@ void GuildMgr::LoadGuilds() sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Validated data of loaded guilds in %u ms", GetMSTimeDiffToNow(oldMSTime)); } } + +void GuildMgr::LoadGuildXpForLevel() +{ + uint32 oldMSTime = getMSTime(); + + GuildXPperLevel.resize(sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL)); + for (uint8 level = 0; level < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL); ++level) + GuildXPperLevel[level] = 0; + + // 0 1 + QueryResult result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM guild_xp_for_level"); + + if (!result) + { + sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 xp for guild level definitions. DB table `guild_xp_for_level` is empty."); + return; + } + + uint32 count = 0; + + do + { + Field* fields = result->Fetch(); + + uint32 level = fields[0].GetUInt8(); + uint32 requiredXP = fields[1].GetUInt64(); + + if (level >= sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL)) + { + sLog->outInfo(LOG_FILTER_GENERAL, "Unused (> Guild.MaxLevel in worldserver.conf) level %u in `guild_xp_for_level` table, ignoring.", uint32(level)); + continue; + } + + GuildXPperLevel[level] = requiredXP; + ++count; + } while (result->NextRow()); + + // fill level gaps + for (uint8 level = 1; level < sWorld->getIntConfig(CONFIG_GUILD_MAX_LEVEL); ++level) + { + if (!GuildXPperLevel[level]) + { + sLog->outError(LOG_FILTER_SQL, "Level %i does not have XP for guild level data. Using data of level [%i] + 1660000.", level+1, level); + GuildXPperLevel[level] = GuildXPperLevel[level - 1] + 1660000; + } + } + + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u xp for guild level definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + +void GuildMgr::LoadGuildRewards() +{ + /// @TODO: Implement +} diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h index 4b999c9231a..a2bf6d268b5 100644 --- a/src/server/game/Guilds/GuildMgr.h +++ b/src/server/game/Guilds/GuildMgr.h @@ -36,18 +36,27 @@ public: Guild* GetGuildByName(const std::string& guildName) const; std::string GetGuildNameById(uint32 guildId) const; + void LoadGuildXpForLevel(); + void LoadGuildRewards(); + void LoadGuilds(); void AddGuild(Guild* guild); void RemoveGuild(uint32 guildId); void SaveGuilds(); + void ResetExperienceCaps(); + void ResetReputationCaps(); + uint32 GenerateGuildId(); void SetNextGuildId(uint32 Id) { NextGuildId = Id; } + uint32 GetXPForGuildLevel(uint8 level) const; + protected: uint32 NextGuildId; GuildContainer GuildStore; + std::vector<uint64> GuildXPperLevel; }; #define sGuildMgr ACE_Singleton<GuildMgr, ACE_Null_Mutex>::instance() |
