Core/Guild: Implement guild master dethrone feature (#168)
This commit is contained in:
1 parent
d8478b689c
commit
31a04a1de1
9 files changed
+95
-44
No files matched your search
@@ -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; }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user