aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp11
-rwxr-xr-xsrc/server/game/DataStores/DBCEnums.h5
-rw-r--r--src/server/game/DataStores/DBCStructure.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp20
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h75
-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
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp3
-rwxr-xr-xsrc/server/game/Handlers/GuildHandler.cpp73
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp10
-rwxr-xr-xsrc/server/game/Server/WorldSession.h1
-rw-r--r--src/server/game/World/World.cpp18
-rwxr-xr-xsrc/server/game/World/World.h6
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.cpp2
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.h2
-rw-r--r--src/server/worldserver/worldserver.conf.dist70
18 files changed, 426 insertions, 104 deletions
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index ee2795a83a8..a0400dad77a 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -1080,6 +1080,10 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
if (referencePlayer->isGameMaster())
return;
+ // Lua_GetGuildLevelEnabled() is checked in achievement UI to display guild tab
+ if (IsGuild<T>() && !sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED))
+ return;
+
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type, IsGuild<T>());
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
@@ -1383,6 +1387,11 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
break;
}
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ {
+ SetCriteriaProgress(achievementCriteria, referencePlayer->GetGuildLevel(), referencePlayer, PROGRESS_SET);
+ break;
+ }
// FIXME: not triggered in code as result, need to implement
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
@@ -1391,7 +1400,6 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL:
case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
@@ -1466,6 +1474,7 @@ bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteriaEntry const* achi
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
return progress->counter >= achievementCriteria->kill_creature.creatureCount;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
return progress->counter >= achievementCriteria->reach_level.level;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
return progress->counter >= achievementCriteria->reach_skill_level.skillLevel;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 5ab9949d9cf..1cf04aefdc1 100755
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -302,11 +302,6 @@ enum AchievementCriteriaTypes
#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 151
-enum AchievementCategory
-{
- CATEGORY_CHILDRENS_WEEK = 163,
-};
-
enum AreaFlags
{
AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring)
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 1d397e8f3ec..552c4d81472 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -87,6 +87,7 @@ struct AchievementCriteriaEntry
} win_bg;
// ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5
+ // ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125
struct
{
uint32 unused; // 3
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 97c52ffd9f9..0579c9a4c36 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -980,7 +980,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo)
SetUInt64Value(OBJECT_FIELD_DATA, 0);
SetUInt32Value(PLAYER_GUILDRANK, 0);
- SetUInt32Value(PLAYER_GUILDLEVEL, 0);
+ SetGuildLevel(0);
SetUInt32Value(PLAYER_GUILD_TIMESTAMP, 0);
for (int i = 0; i < KNOWN_TITLES_SIZE; ++i)
@@ -7581,7 +7581,7 @@ uint32 Player::_GetCurrencyWeekCap(const CurrencyTypesEntry* currency) const
if (cap != currency->WeekCap && IsInWorld() && !GetSession()->PlayerLoading())
{
WorldPacket packet(SMSG_UPDATE_CURRENCY_WEEK_LIMIT, 8);
- packet << uint32(cap / ((currency->Flags & 0x8) ? 100 : 1));
+ packet << uint32(cap / ((currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? 100 : 1));
packet << uint32(currency->ID);
GetSession()->SendPacket(&packet);
}
@@ -7589,6 +7589,17 @@ uint32 Player::_GetCurrencyWeekCap(const CurrencyTypesEntry* currency) const
return cap;
}
+void Player::SetInGuild(uint32 guildId)
+{
+ if (guildId)
+ SetUInt64Value(OBJECT_FIELD_DATA, MAKE_NEW_GUID(guildId, 0, HIGHGUID_GUILD));
+ else
+ SetUInt64Value(OBJECT_FIELD_DATA, 0);
+
+ ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_GUILD_LEVEL_ENABLED, guildId != 0 && sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED));
+ SetUInt16Value(OBJECT_FIELD_TYPE, 1, guildId != 0);
+}
+
uint32 Player::GetGuildIdFromDB(uint64 guid)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER);
@@ -15098,7 +15109,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
bool rewarded = (m_RewardedQuests.find(quest_id) != m_RewardedQuests.end());
// Not give XP in case already completed once repeatable quest
- uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this)*sWorld->getRate(RATE_XP_QUEST));
+ uint32 XP = rewarded ? 0 : uint32(quest->XPValue(this) * sWorld->getRate(RATE_XP_QUEST));
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT);
@@ -15111,6 +15122,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
else
moneyRew = int32(quest->GetRewMoneyMaxLevel() * sWorld->getRate(RATE_DROP_MONEY));
+ if (Guild* guild = sGuildMgr->GetGuildById(GetGuildId()))
+ guild->GiveXP(uint32(quest->XPValue(this) * sWorld->getRate(RATE_XP_QUEST) * sWorld->getRate(RATE_XP_GUILD_MODIFIER)), this);
+
// Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative
if (quest->GetRewOrReqMoney())
moneyRew += quest->GetRewOrReqMoney();
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 368a78d5539..95013eed71c 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -457,38 +457,38 @@ enum DrunkenState
enum PlayerFlags
{
- PLAYER_FLAGS_GROUP_LEADER = 0x00000001,
- PLAYER_FLAGS_AFK = 0x00000002,
- PLAYER_FLAGS_DND = 0x00000004,
- PLAYER_FLAGS_GM = 0x00000008,
- PLAYER_FLAGS_GHOST = 0x00000010,
- PLAYER_FLAGS_RESTING = 0x00000020,
- PLAYER_FLAGS_UNK6 = 0x00000040,
- PLAYER_FLAGS_UNK7 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
- PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
- PLAYER_FLAGS_IN_PVP = 0x00000200,
- PLAYER_FLAGS_HIDE_HELM = 0x00000400,
- PLAYER_FLAGS_HIDE_CLOAK = 0x00000800,
- PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time
- PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time
- PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000,
- PLAYER_FLAGS_DEVELOPER = 0x00008000, // <Dev> prefix for something?
- PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
- PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
- PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
- PLAYER_FLAGS_UNK19 = 0x00080000,
- PLAYER_FLAGS_UNK20 = 0x00100000,
- PLAYER_FLAGS_UNK21 = 0x00200000,
- PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
- PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player
- PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack
- PLAYER_FLAGS_NO_XP_GAIN = 0x02000000,
- PLAYER_FLAGS_UNK26 = 0x04000000,
- PLAYER_FLAGS_UNK27 = 0x08000000,
- PLAYER_FLAGS_UNK28 = 0x10000000,
- PLAYER_FLAGS_VOID_UNLOCKED = 0x20000000, // void storage
- PLAYER_FLAGS_UNK30 = 0x40000000,
- PLAYER_FLAGS_UNK31 = 0x80000000,
+ PLAYER_FLAGS_GROUP_LEADER = 0x00000001,
+ PLAYER_FLAGS_AFK = 0x00000002,
+ PLAYER_FLAGS_DND = 0x00000004,
+ PLAYER_FLAGS_GM = 0x00000008,
+ PLAYER_FLAGS_GHOST = 0x00000010,
+ PLAYER_FLAGS_RESTING = 0x00000020,
+ PLAYER_FLAGS_UNK6 = 0x00000040,
+ PLAYER_FLAGS_UNK7 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
+ PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
+ PLAYER_FLAGS_IN_PVP = 0x00000200,
+ PLAYER_FLAGS_HIDE_HELM = 0x00000400,
+ PLAYER_FLAGS_HIDE_CLOAK = 0x00000800,
+ PLAYER_FLAGS_PLAYED_LONG_TIME = 0x00001000, // played long time
+ PLAYER_FLAGS_PLAYED_TOO_LONG = 0x00002000, // played too long time
+ PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000,
+ PLAYER_FLAGS_DEVELOPER = 0x00008000, // <Dev> prefix for something?
+ PLAYER_FLAGS_UNK16 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary
+ PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
+ PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
+ PLAYER_FLAGS_UNK19 = 0x00080000,
+ PLAYER_FLAGS_UNK20 = 0x00100000,
+ PLAYER_FLAGS_UNK21 = 0x00200000,
+ PLAYER_FLAGS_COMMENTATOR2 = 0x00400000,
+ PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree, allowed only spells with SPELL_ATTR0_REQ_AMMO, SPELL_EFFECT_ATTACK, checked only for active player
+ PLAYER_FLAGS_UNK24 = 0x01000000, // disabled all melee ability on tab include autoattack
+ PLAYER_FLAGS_NO_XP_GAIN = 0x02000000,
+ PLAYER_FLAGS_UNK26 = 0x04000000,
+ PLAYER_FLAGS_UNK27 = 0x08000000,
+ PLAYER_FLAGS_GUILD_LEVEL_ENABLED = 0x10000000, // Lua_GetGuildLevelEnabled() - enables guild leveling related UI
+ PLAYER_FLAGS_VOID_UNLOCKED = 0x20000000, // void storage
+ PLAYER_FLAGS_UNK30 = 0x40000000,
+ PLAYER_FLAGS_UNK31 = 0x80000000,
};
// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
@@ -2010,16 +2010,7 @@ class Player : public Unit, public GridObject<Player>
void RemoveFromGroup(RemoveMethod method = GROUP_REMOVEMETHOD_DEFAULT) { RemoveFromGroup(GetGroup(), GetGUID(), method); }
void SendUpdateToOutOfRangeGroupMembers();
- void SetInGuild(uint32 guildId)
- {
- if (guildId)
- SetUInt64Value(OBJECT_FIELD_DATA, MAKE_NEW_GUID(guildId, 0, HIGHGUID_GUILD));
- else
- SetUInt64Value(OBJECT_FIELD_DATA, 0);
-
- SetUInt16Value(OBJECT_FIELD_TYPE, 1, guildId != 0);
- }
-
+ void SetInGuild(uint32 guildId);
void SetRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); }
uint32 GetRank() { return GetUInt32Value(PLAYER_GUILDRANK); }
void SetGuildLevel(uint32 level) { SetUInt32Value(PLAYER_GUILDLEVEL, level); }
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()
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 6609ef55494..f3f21c40002 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -928,12 +928,13 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
pCurrChar->SetInGuild(fields[0].GetUInt32());
pCurrChar->SetRank(fields[1].GetUInt8());
if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
- pCurrChar->SetUInt32Value(PLAYER_GUILDLEVEL, guild->GetLevel());
+ pCurrChar->SetGuildLevel(guild->GetLevel());
}
else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership
{
pCurrChar->SetInGuild(0);
pCurrChar->SetRank(0);
+ pCurrChar->SetGuildLevel(0);
}
data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4);
diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp
index b3c2d4ae030..06536a90db3 100755
--- a/src/server/game/Handlers/GuildHandler.cpp
+++ b/src/server/game/Handlers/GuildHandler.cpp
@@ -645,32 +645,33 @@ void WorldSession::HandleSetGuildBankTabText(WorldPacket& recvData)
guild->SetBankTabText(tabId, text);
}
-void WorldSession::HandleGuildQueryXPOpcode(WorldPacket& recvData)
+void WorldSession::HandleGuildQueryXPOpcode(WorldPacket& recvPacket)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUERY_GUILD_XP");
ObjectGuid guildGuid;
- guildGuid[2] = recvData.ReadBit();
- guildGuid[1] = recvData.ReadBit();
- guildGuid[0] = recvData.ReadBit();
- guildGuid[5] = recvData.ReadBit();
- guildGuid[4] = recvData.ReadBit();
- guildGuid[7] = recvData.ReadBit();
- guildGuid[6] = recvData.ReadBit();
- guildGuid[3] = recvData.ReadBit();
-
- recvData.ReadByteSeq(guildGuid[7]);
- recvData.ReadByteSeq(guildGuid[2]);
- recvData.ReadByteSeq(guildGuid[3]);
- recvData.ReadByteSeq(guildGuid[6]);
- recvData.ReadByteSeq(guildGuid[1]);
- recvData.ReadByteSeq(guildGuid[5]);
- recvData.ReadByteSeq(guildGuid[0]);
- recvData.ReadByteSeq(guildGuid[4]);
+ guildGuid[2] = recvPacket.ReadBit();
+ guildGuid[1] = recvPacket.ReadBit();
+ guildGuid[0] = recvPacket.ReadBit();
+ guildGuid[5] = recvPacket.ReadBit();
+ guildGuid[4] = recvPacket.ReadBit();
+ guildGuid[7] = recvPacket.ReadBit();
+ guildGuid[6] = recvPacket.ReadBit();
+ guildGuid[3] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guildGuid[7]);
+ recvPacket.ReadByteSeq(guildGuid[2]);
+ recvPacket.ReadByteSeq(guildGuid[3]);
+ recvPacket.ReadByteSeq(guildGuid[6]);
+ recvPacket.ReadByteSeq(guildGuid[1]);
+ recvPacket.ReadByteSeq(guildGuid[5]);
+ recvPacket.ReadByteSeq(guildGuid[0]);
+ recvPacket.ReadByteSeq(guildGuid[4]);
- //if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
- // guild->Send SMSG_GUILD_XP
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
+ if (guild->IsMember(_player->GetGUID()))
+ guild->SendGuildXP(this);
}
void WorldSession::HandleGuildSetRankPermissionsOpcode(WorldPacket& recvPacket)
@@ -741,3 +742,35 @@ void WorldSession::HandleGuildRequestPartyState(WorldPacket& recvData)
if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid))
guild->HandleGuildPartyRequest(this);
}
+
+void WorldSession::HandleGuildRequestMaxDailyXP(WorldPacket& recvPacket)
+{
+ ObjectGuid guid;
+ guid[0] = recvPacket.ReadBit();
+ guid[3] = recvPacket.ReadBit();
+ guid[5] = recvPacket.ReadBit();
+ guid[1] = recvPacket.ReadBit();
+ guid[4] = recvPacket.ReadBit();
+ guid[6] = recvPacket.ReadBit();
+ guid[7] = recvPacket.ReadBit();
+ guid[2] = recvPacket.ReadBit();
+
+ recvPacket.ReadByteSeq(guid[7]);
+ recvPacket.ReadByteSeq(guid[4]);
+ recvPacket.ReadByteSeq(guid[3]);
+ recvPacket.ReadByteSeq(guid[5]);
+ recvPacket.ReadByteSeq(guid[1]);
+ recvPacket.ReadByteSeq(guid[2]);
+ recvPacket.ReadByteSeq(guid[6]);
+ recvPacket.ReadByteSeq(guid[0]);
+
+ if (Guild* guild = sGuildMgr->GetGuildByGuid(guid))
+ {
+ if (guild->IsMember(_player->GetGUID()))
+ {
+ WorldPacket data(SMSG_GUILD_MAX_DAILY_XP, 8);
+ data << uint64(sWorld->getIntConfig(CONFIG_GUILD_DAILY_XP_CAP));
+ SendPacket(&data);
+ }
+ }
+}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 1d5e7a3705b..1989481581f 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -277,7 +277,7 @@ void InitOpcodes()
DEFINE_OPCODE_HANDLER(CMSG_GUILD_REMOVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRemoveOpcode );
DEFINE_OPCODE_HANDLER(CMSG_GUILD_REPLACE_GUILD_MASTER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_CHALLENGE_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
- DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_MAX_DAILY_XP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_MAX_DAILY_XP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestMaxDailyXP );
DEFINE_OPCODE_HANDLER(CMSG_GUILD_REQUEST_PARTY_STATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestPartyState );
DEFINE_OPCODE_HANDLER(CMSG_GUILD_ROSTER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRosterOpcode );
DEFINE_OPCODE_HANDLER(CMSG_GUILD_SET_ACHIEVEMENT_TRACKING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
@@ -420,7 +420,7 @@ void InitOpcodes()
DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_MEMBER_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_REWARDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
- DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_XP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryXPOpcode ); // STATUS_AUTHED
+ DEFINE_OPCODE_HANDLER(CMSG_QUERY_GUILD_XP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryXPOpcode ); // STATUS_AUTHED
DEFINE_OPCODE_HANDLER(CMSG_QUERY_INSPECT_ACHIEVEMENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryInspectAchievements );
DEFINE_OPCODE_HANDLER(CMSG_QUERY_QUESTS_COMPLETED, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryQuestsCompleted );
DEFINE_OPCODE_HANDLER(CMSG_QUERY_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryTimeOpcode );
@@ -866,7 +866,7 @@ void InitOpcodes()
DEFINE_OPCODE_HANDLER(SMSG_GUILD_FLAGGED_FOR_RENAME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_GUILD_INVITE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_GUILD_INVITE_CANCEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
- DEFINE_OPCODE_HANDLER(SMSG_GUILD_MAX_DAILY_XP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_MAX_DAILY_XP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBERS_FOR_RECIPE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBER_DAILY_RESET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_GUILD_MEMBER_RECIPES, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
@@ -888,8 +888,8 @@ void InitOpcodes()
DEFINE_OPCODE_HANDLER(SMSG_GUILD_REWARDS_LIST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_GUILD_ROSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_GUILD_UPDATE_ROSTER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
- DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
- DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP_GAIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ DEFINE_OPCODE_HANDLER(SMSG_GUILD_XP_GAIN, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_HEALTH_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_HIGHEST_THREAT_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER(SMSG_HOTFIX_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 6ff03b9c838..307f61beb4a 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -591,6 +591,7 @@ class WorldSession
void HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket);
void HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket);
void HandleGuildRequestPartyState(WorldPacket& recvPacket);
+ void HandleGuildRequestMaxDailyXP(WorldPacket& recvPacket);
void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket);
void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 0a9af095352..1b3c44375d9 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1198,7 +1198,13 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_DB_PING_INTERVAL] = ConfigMgr::GetIntDefault("MaxPingTime", 30);
// Guild save interval
- m_int_configs[CONFIG_GUILD_SAVE_INTERVAL] = ConfigMgr::GetIntDefault("GuildSaveInterval", 15);
+ m_bool_configs[CONFIG_GUILD_LEVELING_ENABLED] = ConfigMgr::GetBoolDefault("Guild.LevelingEnabled", true);
+ m_int_configs[CONFIG_GUILD_SAVE_INTERVAL] = ConfigMgr::GetIntDefault("Guild.SaveInterval", 15);
+ m_int_configs[CONFIG_GUILD_MAX_LEVEL] = ConfigMgr::GetIntDefault("Guild.MaxLevel", 25);
+ m_int_configs[CONFIG_GUILD_UNDELETABLE_LEVEL] = ConfigMgr::GetIntDefault("Guild.UndeletableLevel", 4);
+ rate_values[RATE_XP_GUILD_MODIFIER] = ConfigMgr::GetFloatDefault("Guild.XPModifier", 0.25f);
+ m_int_configs[CONFIG_GUILD_DAILY_XP_CAP] = ConfigMgr::GetIntDefault("Guild.DailyXPCap", 7807500);
+ m_int_configs[CONFIG_GUILD_WEEKLY_REP_CAP] = ConfigMgr::GetIntDefault("Guild.WeeklyReputationCap", 4375);
// misc
m_bool_configs[CONFIG_PDUMP_NO_PATHS] = ConfigMgr::GetBoolDefault("PlayerDump.DisallowPaths", true);
@@ -1553,6 +1559,12 @@ void World::SetInitialWorldSettings()
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Auctions...");
sAuctionMgr->LoadAuctions();
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Guild XP for level...");
+ sGuildMgr->LoadGuildXpForLevel();
+
+ sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Guild rewards...");
+ sGuildMgr->LoadGuildRewards();
+
sGuildMgr->LoadGuilds();
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading ArenaTeams...");
@@ -1905,10 +1917,14 @@ void World::Update(uint32 diff)
{
ResetDailyQuests();
m_NextDailyQuestReset += DAY;
+ sGuildMgr->ResetExperienceCaps();
}
if (m_gameTime > m_NextWeeklyQuestReset)
+ {
ResetWeeklyQuests();
+ sGuildMgr->ResetReputationCaps();
+ }
if (m_gameTime > m_NextRandomBGReset)
ResetRandomBG();
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index b25444f4865..f0f5e3f723b 100755
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -174,6 +174,7 @@ enum WorldBoolConfigs
CONFIG_QUEST_IGNORE_AUTO_COMPLETE,
CONFIG_WARDEN_ENABLED,
CONFIG_WINTERGRASP_ENABLE,
+ CONFIG_GUILD_LEVELING_ENABLED,
BOOL_CONFIG_VALUE_COUNT
};
@@ -337,6 +338,10 @@ enum WorldIntConfigs
CONFIG_WINTERGRASP_NOBATTLETIME,
CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
CONFIG_GUILD_SAVE_INTERVAL,
+ CONFIG_GUILD_MAX_LEVEL,
+ CONFIG_GUILD_UNDELETABLE_LEVEL,
+ CONFIG_GUILD_DAILY_XP_CAP,
+ CONFIG_GUILD_WEEKLY_REP_CAP,
INT_CONFIG_VALUE_COUNT
};
@@ -364,6 +369,7 @@ enum Rates
RATE_DROP_MONEY,
RATE_XP_KILL,
RATE_XP_QUEST,
+ RATE_XP_GUILD_MODIFIER,
RATE_XP_EXPLORE,
RATE_REPAIRCOST,
RATE_REPUTATION_GAIN,
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 286f2c20811..bb958be8ca7 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -239,6 +239,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA, "DELETE FROM guild_achievement_progress WHERE guildId = ?", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_SEL_GUILD_ACHIEVEMENT, "SELECT achievement, date, guids FROM guild_achievement WHERE guildId = ?", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA, "SELECT criteria, counter, date, completedGuid FROM guild_achievement_progress WHERE guildId = ?", CONNECTION_SYNCH)
+ PREPARE_STATEMENT(CHAR_UPD_GUILD_EXPERIENCE, "UPDATE guild SET level = ?, experience = ?, todayExperience = ? WHERE guildId = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE, "UPDATE guild SET todayExperience = 0", CONNECTION_ASYNC);
// Chat channel handling
PREPARE_STATEMENT(CHAR_SEL_CHANNEL, "SELECT announce, ownership, password, bannedList FROM channels WHERE name = ? AND team = ?", CONNECTION_SYNCH)
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index c134856a74f..9c06c547b39 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -234,6 +234,8 @@ enum CharacterDatabaseStatements
CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA,
CHAR_SEL_GUILD_ACHIEVEMENT,
CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA,
+ CHAR_UPD_GUILD_EXPERIENCE,
+ CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE,
CHAR_SEL_CHANNEL,
CHAR_INS_CHANNEL,
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 83b0edf61df..f8ee2390842 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -393,14 +393,6 @@ CleanCharacterDB = 0
PersistentCharacterCleanFlags = 0
#
-# GuildSaveInterval
-# Description: Time (in minutes) between guild experience saves
-# Default: 15
-#
-
-GuildSaveInterval = 15
-
-#
###################################################################################################
###################################################################################################
@@ -2821,3 +2813,65 @@ Loggers=Root Chat DBErrors GM RA Warden Character Load WorldServer Opcodes
#
###################################################################################################
+
+###################################################################################################
+#
+# GUILD LEVELING SETTINGS
+#
+# Guild.LevelingEnabled
+# Description: Controls whether guild can gain levels
+# Default: 1
+#
+
+Guild.LevelingEnabled = 1
+
+#
+# Guild.SaveInterval
+# Description: Time (in minutes) between guild experience saves
+# Default: 15
+#
+
+Guild.SaveInterval = 15
+
+#
+# Guild.MaxLevel
+# Description: Defines max level a guild can reach
+# Default: 25
+#
+
+Guild.MaxLevel = 25
+
+#
+# Guild.UndeletableLevel
+# Description: Guild reaching this level (and higher) cannot be disbanded anymore
+# Default: 4
+#
+
+Guild.UndeletableLevel = 4
+
+#
+# Guild.XPModifier
+# Description: Multiplier for guild experience gained from quests
+# Default: 0.25
+#
+
+Guild.XPModifier = 0.25
+
+#
+# Guild.DailyXPCap
+# Description: Maximum experience points a guild can earn each day
+# Default: 7807500
+#
+
+Guild.DailyXPCap = 7807500
+
+#
+# Guild.WeeklyReputationCap
+# Description: Maximum guild reputation a player can earn every week
+# Default: 4375
+#
+
+Guild.WeeklyReputationCap = 4375
+
+#
+###################################################################################################