Core/Guild: Implement guild master dethrone feature (#168)

This commit is contained in:
Roc13x authored and GitHub committed 2020-08-24 23:48:30 +02:00
1 parent d8478b689c
commit 31a04a1de1
9 files changed
+95 -44

No files matched your search

+2 -2
View File
@@ -1744,8 +1744,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SendUpdateToOutOfRangeGroupMembers();
void SetInGuild(uint32 guildId);
void SetRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); }
uint8 GetRank() const { return uint8(GetUInt32Value(PLAYER_GUILDRANK)); }
void SetGuildRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); }
uint8 GetGuildRank() const { return uint8(GetUInt32Value(PLAYER_GUILDRANK)); }
void SetGuildLevel(uint32 level) { SetUInt32Value(PLAYER_GUILDLEVEL, level); }
uint32 GetGuildLevel() { return GetUInt32Value(PLAYER_GUILDLEVEL); }
void SetGuildIdInvited(uint32 GuildId) { m_GuildIdInvited = GuildId; }
+48 -30
View File
@@ -736,8 +736,8 @@ void Guild::Member::ChangeRank(CharacterDatabaseTransaction& trans, uint8 newRan
m_rankId = newRank;
// Update rank information in player's field, if he is online.
if (Player* player = FindPlayer())
player->SetRank(newRank);
if (Player* player = FindConnectedPlayer())
player->SetGuildRank(newRank);
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_MEMBER_RANK);
stmt->setUInt8 (0, newRank);
@@ -1819,24 +1819,45 @@ void Guild::HandleSetEmblem(WorldSession* session, EmblemInfo const& emblemInfo)
}
}
void Guild::HandleSetNewGuildMaster(WorldSession* session, std::string const& name)
void Guild::HandleSetNewGuildMaster(WorldSession* session, std::string const& name, bool isSelfPromote)
{
Player* player = session->GetPlayer();
// Only the guild master can throne a new guild master
if (!_IsLeader(player))
SendCommandResult(session, GUILD_COMMAND_CHANGE_LEADER, ERR_GUILD_PERMISSIONS);
// Old GM must be a guild member
else if (Member* oldGuildMaster = GetMember(player->GetGUID()))
Member* oldGuildMaster = GetMember(GetLeaderGUID());
ASSERT(oldGuildMaster);
Member* newGuildMaster;
if (isSelfPromote)
{
// Same for the new one
if (Member* newGuildMaster = GetMember(name))
newGuildMaster = GetMember(player->GetGUID());
if (!newGuildMaster)
return;
if (!newGuildMaster->IsRankNotLower(GR_MEMBER) || uint32(oldGuildMaster->GetInactiveDays()) < GUILD_MASTER_DETHRONE_INACTIVE_DAYS)
{
_SetLeaderGUID(newGuildMaster);
CharacterDatabaseTransaction trans(nullptr);
oldGuildMaster->ChangeRank(trans, GR_INITIATE);
_BroadcastEvent(GE_LEADER_CHANGED, ObjectGuid::Empty, player->GetName().c_str(), name.c_str());
SendCommandResult(session, GUILD_COMMAND_CHANGE_LEADER, ERR_GUILD_PERMISSIONS);
return;
}
}
else
{
if (!_IsLeader(player))
{
SendCommandResult(session, GUILD_COMMAND_CHANGE_LEADER, ERR_GUILD_PERMISSIONS);
return;
}
newGuildMaster = GetMember(name);
if (!newGuildMaster)
return;
}
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
_SetLeader(trans, newGuildMaster);
oldGuildMaster->ChangeRank(trans, GR_INITIATE);
_BroadcastEvent(GE_LEADER_CHANGED, ObjectGuid::Empty, player->GetName().c_str(), newGuildMaster->GetName().c_str());
CharacterDatabase.CommitTransaction(trans);
}
void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon)
@@ -2814,7 +2835,6 @@ bool Guild::Validate()
Member* pLeader = GetMember(m_leaderGuid);
if (!pLeader)
{
CharacterDatabaseTransaction trans(nullptr);
DeleteMember(trans, m_leaderGuid);
// If no more members left, disband guild
if (m_members.empty())
@@ -2824,7 +2844,7 @@ bool Guild::Validate()
}
}
else if (!pLeader->IsRank(GR_GUILDMASTER))
_SetLeaderGUID(pLeader);
_SetLeader(trans, pLeader);
// Check config if multiple guildmasters are allowed
if (!sConfigMgr->GetBoolDefault("Guild.AllowMultipleGuildMaster", 0))
@@ -2988,7 +3008,7 @@ bool Guild::AddMember(CharacterDatabaseTransaction& trans, ObjectGuid guid, uint
m_members[lowguid] = member;
player->SetInGuild(m_id);
player->SetGuildIdInvited(0);
player->SetRank(rankId);
player->SetGuildRank(rankId);
player->SetGuildLevel(GetLevel());
member->UpdateProfessionData();
SendLoginInfo(player->GetSession());
@@ -3088,11 +3108,7 @@ void Guild::DeleteMember(CharacterDatabaseTransaction& trans, ObjectGuid guid, b
return;
}
_SetLeaderGUID(newLeader);
// If player not online data in data field will be loaded from guild tabs no need to update it !!
if (Player* newLeaderPlayer = newLeader->FindPlayer())
newLeaderPlayer->SetRank(GR_GUILDMASTER);
_SetLeader(trans, newLeader);
// If leader does not exist (at guild loading with deleted leader) do not send broadcasts
if (oldLeader)
@@ -3123,13 +3139,11 @@ void Guild::DeleteMember(CharacterDatabaseTransaction& trans, ObjectGuid guid, b
if (player)
{
player->SetInGuild(0);
player->SetRank(0);
player->SetGuildRank(0);
player->SetGuildLevel(0);
for (uint32 i = 0; i < sGuildPerkSpellsStore.GetNumRows(); ++i)
if (GuildPerkSpellsEntry const* entry = sGuildPerkSpellsStore.LookupEntry(i))
if (entry->GuildLevel <= GetLevel())
player->RemoveSpell(entry->SpellID, false, false);
for (GuildPerkSpellsEntry const* entry : sGuildPerkSpellsStore)
player->RemoveSpell(entry->SpellID, false, false);
// Update GuildId in group
if (Group* group = player->GetGroup())
@@ -3330,12 +3344,15 @@ bool Guild::_ModifyBankMoney(CharacterDatabaseTransaction& trans, uint64 amount,
return true;
}
void Guild::_SetLeaderGUID(Member* pLeader)
void Guild::_SetLeader(CharacterDatabaseTransaction& trans, Member* pLeader)
{
if (!pLeader)
return;
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
bool isInTransaction = bool(trans);
if (!isInTransaction)
trans = CharacterDatabase.BeginTransaction();
m_leaderGuid = pLeader->GetGUID();
pLeader->ChangeRank(trans, GR_GUILDMASTER);
@@ -3344,7 +3361,8 @@ void Guild::_SetLeaderGUID(Member* pLeader)
stmt->setUInt32(1, m_id);
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
if (!isInTransaction)
CharacterDatabase.CommitTransaction(trans);
}
void Guild::_SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay)
+3 -2
View File
@@ -44,6 +44,7 @@ enum GuildMisc
GUILD_BANK_MAX_TABS = 8, // send by client for money log also
GUILD_BANK_MAX_SLOTS = 98,
GUILD_BANK_MONEY_LOGS_TAB = 100, // used for money log in DB
GUILD_MASTER_DETHRONE_INACTIVE_DAYS = 90,
GUILD_RANKS_MIN_COUNT = 2,
GUILD_RANKS_MAX_COUNT = 10,
GUILD_RANK_NONE = 0xFF,
@@ -794,7 +795,7 @@ public:
void HandleSetMOTD(WorldSession* session, std::string const& motd);
void HandleSetInfo(WorldSession* session, std::string const& info);
void HandleSetEmblem(WorldSession* session, EmblemInfo const& emblemInfo);
void HandleSetNewGuildMaster(WorldSession* session, std::string const& name);
void HandleSetNewGuildMaster(WorldSession* session, std::string const& name, bool isSelfPromote);
void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon);
void HandleSetMemberNote(WorldSession* session, std::string const& note, ObjectGuid guid, bool isPublic);
void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec const& rightsAndSlots);
@@ -988,7 +989,7 @@ private:
bool _IsLeader(Player* player) const;
void _DeleteBankItems(CharacterDatabaseTransaction& trans, bool removeItemsFromDB = false);
bool _ModifyBankMoney(CharacterDatabaseTransaction& trans, uint64 amount, bool add);
void _SetLeaderGUID(Member* pLeader);
void _SetLeader(CharacterDatabaseTransaction& trans, Member* pLeader);
void _SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay);
void _SetRankBankTabRightsAndSlots(uint8 rankId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB = true);
@@ -892,7 +892,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
{
Field* fields = resultGuild->Fetch();
pCurrChar->SetInGuild(fields[0].GetUInt32());
pCurrChar->SetRank(fields[1].GetUInt8());
pCurrChar->SetGuildRank(fields[1].GetUInt8());
if (Guild* guild = sGuildMgr->GetGuildById(pCurrChar->GetGuildId()))
{
pCurrChar->SetGuildLevel(guild->GetLevel());
@@ -906,7 +906,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership
{
pCurrChar->SetInGuild(0);
pCurrChar->SetRank(0);
pCurrChar->SetGuildRank(0);
pCurrChar->SetGuildLevel(0);
}
+8 -6
View File
@@ -701,14 +701,16 @@ void WorldSession::HandleGuildNewsUpdateStickyOpcode(WorldPacket& recvPacket)
guild->HandleNewsSetSticky(this, newsId, sticky);
}
void WorldSession::HandleGuildSetGuildMaster(WorldPacket& recvPacket)
void WorldSession::HandleGuildReplaceGuildMaster(WorldPackets::Guild::ReplaceGuildMaster& /*packet */)
{
uint8 nameLength = recvPacket.ReadBits(7);
// This is related to guild master inactivity.
/*bool isDethrone = */recvPacket.ReadBit();
std::string playerName = recvPacket.ReadString(nameLength);
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleSetNewGuildMaster(this, playerName);
guild->HandleSetNewGuildMaster(this, "", true);
}
void WorldSession::HandleGuildSetGuildMaster(WorldPackets::Guild::SetGuildMaster& packet)
{
if (Guild* guild = GetPlayer()->GetGuild())
guild->HandleSetNewGuildMaster(this, packet.NewMasterName, packet.IsDethrone);
}
void WorldSession::HandleGuildSetAchievementTracking(WorldPacket& recvPacket)
@@ -690,3 +690,11 @@ WorldPacket const* WorldPackets::Guild::GuildRanks::Write()
return &_worldPacket;
}
void WorldPackets::Guild::SetGuildMaster::Read()
{
uint8 nameLen = _worldPacket.ReadBits(7);
IsDethrone = _worldPacket.ReadBit();
NewMasterName = _worldPacket.ReadString(nameLen);
}
@@ -552,6 +552,25 @@ namespace WorldPackets
std::vector<GuildRankData> Ranks;
};
class ReplaceGuildMaster final : public ClientPacket
{
public:
ReplaceGuildMaster(WorldPacket&& packet) : ClientPacket(CMSG_GUILD_REPLACE_GUILD_MASTER, std::move(packet)) { }
void Read() override { }
};
class SetGuildMaster final : public ClientPacket
{
public:
SetGuildMaster(WorldPacket&& packet) : ClientPacket(CMSG_GUILD_SET_GUILD_MASTER, std::move(packet)) { }
void Read() override;
bool IsDethrone = false;
std::string NewMasterName;
};
}
}
+1 -1
View File
@@ -367,7 +367,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_GUILD_QUERY_MEMBER_RECIPES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryMemberRecipe );
DEFINE_HANDLER(CMSG_GUILD_QUERY_MEMBERS_FOR_RECIPE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryMembersForRecipe);
DEFINE_HANDLER(CMSG_GUILD_REMOVE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRemoveOpcode );
DEFINE_HANDLER(CMSG_GUILD_REPLACE_GUILD_MASTER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_HANDLER(CMSG_GUILD_REPLACE_GUILD_MASTER, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleGuildReplaceGuildMaster );
DEFINE_HANDLER(CMSG_GUILD_REQUEST_CHALLENGE_UPDATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestChallengeUpdate);
DEFINE_HANDLER(CMSG_GUILD_REQUEST_MAX_DAILY_XP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestMaxDailyXP );
DEFINE_HANDLER(CMSG_GUILD_REQUEST_PARTY_STATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRequestPartyState );
+4 -1
View File
@@ -131,6 +131,8 @@ namespace WorldPackets
class GuildQueryMemberRecipes;
class GuildChallengeUpdateRequest;
class RequestGuildRewardsList;
class ReplaceGuildMaster;
class SetGuildMaster;
}
namespace Misc
@@ -785,7 +787,8 @@ class TC_GAME_API WorldSession
void HandleGuildLeaveOpcode(WorldPacket& recvPacket);
void HandleGuildDisbandOpcode(WorldPacket& recvPacket);
void HandleGuildSetAchievementTracking(WorldPacket& recvPacket);
void HandleGuildSetGuildMaster(WorldPacket& recvPacket);
void HandleGuildReplaceGuildMaster(WorldPackets::Guild::ReplaceGuildMaster& packet);
void HandleGuildSetGuildMaster(WorldPackets::Guild::SetGuildMaster& packet);
void HandleGuildMOTDOpcode(WorldPacket& recvPacket);
void HandleGuildNewsUpdateStickyOpcode(WorldPacket& recvPacket);
void HandleGuildSetNoteOpcode(WorldPacket& recvPacket);