diff options
21 files changed, 465 insertions, 104 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 718ff3dba20..404ffbb6593 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -1639,6 +1639,9 @@ CREATE TABLE `guild` ( `motd` varchar(128) NOT NULL DEFAULT '', `createdate` int(10) unsigned NOT NULL DEFAULT '0', `BankMoney` bigint(20) unsigned NOT NULL DEFAULT '0', + `level` int(10) unsigned DEFAULT '1', + `experience` bigint(20) unsigned DEFAULT '0', + `todayExperience` bigint(20) unsigned DEFAULT '0', PRIMARY KEY (`guildid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Guild System'; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/sql/updates/characters/2012_09_07_00_characters_guild_434.sql b/sql/updates/characters/2012_09_07_00_characters_guild_434.sql new file mode 100644 index 00000000000..31695bab93f --- /dev/null +++ b/sql/updates/characters/2012_09_07_00_characters_guild_434.sql @@ -0,0 +1,3 @@ +ALTER TABLE guild ADD `level` INT(10) unsigned DEFAULT '1' AFTER `BankMoney`; +ALTER TABLE guild ADD `experience` BIGINT(20) unsigned DEFAULT '0' AFTER `level`; +ALTER TABLE guild ADD `todayExperience` BIGINT(20) unsigned DEFAULT '0' AFTER `experience`; diff --git a/sql/updates/world/2012_09_09_00_world_guild_xp_for_level.sql b/sql/updates/world/2012_09_09_00_world_guild_xp_for_level.sql new file mode 100644 index 00000000000..aa2ee143d53 --- /dev/null +++ b/sql/updates/world/2012_09_09_00_world_guild_xp_for_level.sql @@ -0,0 +1,33 @@ +DROP TABLE IF EXISTS `guild_xp_for_level`; +CREATE TABLE `guild_xp_for_level` ( + `lvl` int(11) unsigned NOT NULL, + `xp_for_next_level` bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`lvl`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `guild_xp_for_level` VALUES +(1,16580000), +(2,18240000), +(3,19900000), +(4,21550000), +(5,23220000), +(6,24880000), +(7,26530000), +(8,28190000), +(9,29850000), +(10,31510000), +(11,33170000), +(12,34820000), +(13,36490000), +(14,38140000), +(15,39800000), +(16,41450000), +(17,43120000), +(18,44780000), +(19,46430000), +(20,48090000), +(21,49750000), +(22,51410000), +(23,53060000), +(24,54730000), +(25,56390000); 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 + +# +################################################################################################### |