aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Guilds
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2012-09-07 14:39:19 +0200
committerShauren <shauren.trinity@gmail.com>2012-09-07 14:39:19 +0200
commit6ca7a7b78d2e08d9eae4b38d18ef7303c19acd82 (patch)
tree08b5f306b8f62d50795c9076d98f9b358ad7ed58 /src/server/game/Guilds
parent19b400761d011b920de808c80265225096eda7fb (diff)
Core/Guilds: Implemented basic guild leveling (no player statistics/reputation)
Diffstat (limited to 'src/server/game/Guilds')
-rw-r--r--src/server/game/Guilds/Guild.cpp132
-rwxr-xr-xsrc/server/game/Guilds/Guild.h14
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp78
-rw-r--r--src/server/game/Guilds/GuildMgr.h9
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()