Core/Guilds: guild code was completely refactored and rewritten.

* OOP desing and implementation;
* all the queries are moved to prepared statements;
* guild loading is optimized;
* all the possible interaction with guild's data is done inside the guild class;
* added more hooks to GuildScript class;

WARNING: Make sure you backup your characters database before applying this change (just in case).

Known problems with guilds:
* when new member is added to the guild, MOTD is not displayed for him in guild tab of social window;
* if you add item with random property to guild bank visual representation of item below it becomes wrong (it displays wrong stack number);
* packets order differs from official: currently guild bank packet traffic is twice as more than on offy.

--HG--
branch : trunk
This commit is contained in:
azazel
2010-10-17 19:54:13 +06:00
parent f5911917b4
commit c0faed2251
27 changed files with 3892 additions and 3538 deletions
+592 -304
View File
@@ -19,52 +19,63 @@
#ifndef TRINITYCORE_GUILD_H
#define TRINITYCORE_GUILD_H
#define WITHDRAW_MONEY_UNLIMITED 0xFFFFFFFF
#define WITHDRAW_SLOT_UNLIMITED 0xFFFFFFFF
#include "World.h"
#include "Item.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
#include "Player.h"
class Item;
#define GUILD_RANKS_MIN_COUNT 5
#define GUILD_RANKS_MAX_COUNT 10
enum GuildMisc
{
GUILD_BANK_MAX_TABS = 6, // 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_RANKS_MIN_COUNT = 5,
GUILD_RANKS_MAX_COUNT = 10,
GUILD_RANK_NONE = 0xFF,
GUILD_WITHDRAW_MONEY_UNLIMITED = 0xFFFFFFFF,
GUILD_WITHDRAW_SLOT_UNLIMITED = 0xFFFFFFFF,
GUILD_EVENT_LOG_GUID_UNDEFINED = 0xFFFFFFFF,
};
enum GuildDefaultRanks
{
//these ranks can be modified, but they cannot be deleted
// These ranks can be modified, but they cannot be deleted
GR_GUILDMASTER = 0,
GR_OFFICER = 1,
GR_VETERAN = 2,
GR_MEMBER = 3,
GR_INITIATE = 4,
//When promoting member server does: rank--;!
//When demoting member server does: rank++;!
// When promoting member server does: rank--
// When demoting member server does: rank++
};
enum GuildRankRights
{
GR_RIGHT_EMPTY = 0x00000040,
GR_RIGHT_GCHATLISTEN = 0x00000041,
GR_RIGHT_GCHATSPEAK = 0x00000042,
GR_RIGHT_OFFCHATLISTEN = 0x00000044,
GR_RIGHT_OFFCHATSPEAK = 0x00000048,
GR_RIGHT_PROMOTE = 0x000000C0,
GR_RIGHT_DEMOTE = 0x00000140,
GR_RIGHT_INVITE = 0x00000050,
GR_RIGHT_REMOVE = 0x00000060,
GR_RIGHT_SETMOTD = 0x00001040,
GR_RIGHT_EPNOTE = 0x00002040,
GR_RIGHT_VIEWOFFNOTE = 0x00004040,
GR_RIGHT_EOFFNOTE = 0x00008040,
GR_RIGHT_MODIFY_GUILD_INFO = 0x00010040,
GR_RIGHT_WITHDRAW_GOLD_LOCK = 0x00020000, // remove money withdraw capacity
GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair
GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold
GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk
GR_RIGHT_GCHATLISTEN = GR_RIGHT_EMPTY | 0x00000001,
GR_RIGHT_GCHATSPEAK = GR_RIGHT_EMPTY | 0x00000002,
GR_RIGHT_OFFCHATLISTEN = GR_RIGHT_EMPTY | 0x00000004,
GR_RIGHT_OFFCHATSPEAK = GR_RIGHT_EMPTY | 0x00000008,
GR_RIGHT_INVITE = GR_RIGHT_EMPTY | 0x00000010,
GR_RIGHT_REMOVE = GR_RIGHT_EMPTY | 0x00000020,
GR_RIGHT_PROMOTE = GR_RIGHT_EMPTY | 0x00000080,
GR_RIGHT_DEMOTE = GR_RIGHT_EMPTY | 0x00000100,
GR_RIGHT_SETMOTD = GR_RIGHT_EMPTY | 0x00001000,
GR_RIGHT_EPNOTE = GR_RIGHT_EMPTY | 0x00002000,
GR_RIGHT_VIEWOFFNOTE = GR_RIGHT_EMPTY | 0x00004000,
GR_RIGHT_EOFFNOTE = GR_RIGHT_EMPTY | 0x00008000,
GR_RIGHT_MODIFY_GUILD_INFO = GR_RIGHT_EMPTY | 0x00010000,
GR_RIGHT_WITHDRAW_GOLD_LOCK = 0x00020000, // remove money withdraw capacity
GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair
GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold
GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk
GR_RIGHT_ALL = 0x001DF1FF
};
enum Typecommand
enum GuildCommandType
{
GUILD_CREATE_S = 0x00,
GUILD_INVITE_S = 0x01,
@@ -74,7 +85,7 @@ enum Typecommand
GUILD_UNK2 = 0x14
};
enum CommandErrors
enum GuildCommandError
{
ERR_PLAYER_NO_MORE_IN_GUILD = 0x00,
ERR_GUILD_INTERNAL = 0x01,
@@ -118,11 +129,11 @@ enum GuildEvents
GE_UNK2 = 0x0B, // EVENT_GUILD_ROSTER_UPDATE
GE_SIGNED_ON = 0x0C, // ERR_FRIEND_ONLINE_SS
GE_SIGNED_OFF = 0x0D, // ERR_FRIEND_OFFLINE_S
GE_GUILDBANKBAGSLOTS_CHANGED = 0x0E, // EVENT_GUILDBANKBAGSLOTS_CHANGED
GE_BANKTAB_PURCHASED = 0x0F, // EVENT_GUILDBANK_UPDATE_TABS
GE_GUILDBANK_BAGSLOTS_CHANGED = 0x0E, // EVENT_GUILDBANK_BAGSLOTS_CHANGED
GE_GUILDBANK_TAB_PURCHASED = 0x0F, // EVENT_GUILDBANK_UPDATE_TABS
GE_UNK5 = 0x10, // EVENT_GUILDBANK_UPDATE_TABS
GE_GUILDBANK_UPDATE_MONEY = 0x11, // EVENT_GUILDBANK_UPDATE_MONEY, string 0000000000002710 is 1 gold
GE_GUILD_BANK_MONEY_WITHDRAWN = 0x12, // MSG_GUILD_BANK_MONEY_WITHDRAWN
GE_GUILDBANK_MONEY_UPDATE = 0x11, // EVENT_GUILDBANK_UPDATE_MONEY, string 0000000000002710 is 1 gold
GE_GUILDBANK_MONEY_WITHDRAWN = 0x12, // MSG_GUILD_BANK_MONEY_WITHDRAWN
GE_GUILDBANK_TEXT_CHANGED = 0x13 // EVENT_GUILDBANK_TEXT_CHANGED
};
@@ -175,7 +186,7 @@ enum GuildEventLogTypes
GUILD_EVENT_LOG_LEAVE_GUILD = 6,
};
enum GuildEmblem
enum GuildEmblemError
{
ERR_GUILDEMBLEM_SUCCESS = 0,
ERR_GUILDEMBLEM_INVALID_TABARD_COLORS = 1,
@@ -185,298 +196,575 @@ enum GuildEmblem
ERR_GUILDEMBLEM_INVALIDVENDOR = 5
};
inline uint32 GetGuildBankTabPrice(uint8 Index)
////////////////////////////////////////////////////////////////////////////////////////////
// Emblem info
class EmblemInfo
{
switch(Index)
public:
EmblemInfo() : m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) { }
void LoadFromDB(Field* fields);
void SaveToDB(uint32 guildId) const;
void ReadPacket(WorldPacket& recv) { recv >> m_style >> m_color >> m_borderStyle >> m_borderColor >> m_backgroundColor; }
void WritePacket(WorldPacket& data) const;
uint32 GetStyle() const { return m_style; }
uint32 GetColor() const { return m_color; }
uint32 GetBorderStyle() const { return m_borderStyle; }
uint32 GetBorderColor() const { return m_borderColor; }
uint32 GetBackgroundColor() const { return m_backgroundColor; }
private:
uint32 m_style;
uint32 m_color;
uint32 m_borderStyle;
uint32 m_borderColor;
uint32 m_backgroundColor;
};
// Structure for storing guild bank rights and remaining slots together.
struct GuildBankRightsAndSlots
{
GuildBankRightsAndSlots() : rights(0), slots(0) { }
GuildBankRightsAndSlots(uint8 _rights, uint32 _slots) : rights(_rights), slots(_slots) { }
inline bool IsEqual(const GuildBankRightsAndSlots& rhs) const { return rights == rhs.rights && slots == rhs.slots; }
void SetGuildMasterValues()
{
case 0: return 100;
case 1: return 250;
case 2: return 500;
case 3: return 1000;
case 4: return 2500;
case 5: return 5000;
default:
return 0;
}
}
struct GuildEventLogEntry
{
uint8 EventType;
uint32 PlayerGuid1;
uint32 PlayerGuid2;
uint8 NewRank;
uint64 TimeStamp;
};
struct GuildBankEventLogEntry
{
uint8 EventType;
uint32 PlayerGuid;
uint32 ItemOrMoney;
uint16 ItemStackCount;
uint8 DestTabId;
uint64 TimeStamp;
bool isMoneyEvent()
{
return EventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
EventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
EventType == GUILD_BANK_LOG_REPAIR_MONEY;
}
};
struct GuildBankTab
{
GuildBankTab() { memset(Slots, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*)); }
Item* Slots[GUILD_BANK_MAX_SLOTS];
std::string Name;
std::string Icon;
std::string Text;
};
struct GuildItemPosCount
{
GuildItemPosCount(uint8 _slot, uint32 _count) : Slot(_slot), Count(_count) {}
bool isContainedIn(std::vector<GuildItemPosCount> const& vec) const;
uint8 Slot;
uint32 Count;
};
typedef std::vector<GuildItemPosCount> GuildItemPosCountVec;
struct MemberSlot
{
uint64 LogoutTime;
uint32 accountId;
std::string Name;
std::string Pnote;
std::string OFFnote;
uint32 RankId;
uint32 ZoneId;
uint8 Level;
uint8 Class;
uint32 BankResetTimeMoney;
uint32 BankRemMoney;
uint32 BankResetTimeTab[GUILD_BANK_MAX_TABS];
uint32 BankRemSlotsTab[GUILD_BANK_MAX_TABS];
};
struct RankInfo
{
RankInfo(const std::string& _name, uint32 _rights, uint32 _money) : Name(_name), Rights(_rights), BankMoneyPerDay(_money)
{
for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{
TabRight[i] = 0;
TabSlotPerDay[i] = 0;
}
rights = GUILD_BANK_RIGHT_FULL;
slots = GUILD_WITHDRAW_SLOT_UNLIMITED;
}
std::string Name;
uint32 Rights;
uint32 BankMoneyPerDay;
uint32 TabRight[GUILD_BANK_MAX_TABS];
uint32 TabSlotPerDay[GUILD_BANK_MAX_TABS];
uint8 rights;
uint32 slots;
};
typedef std::vector <GuildBankRightsAndSlots> GuildBankRightsAndSlotsVec;
typedef std::set <uint8> SlotIds;
class Guild
{
friend class ObjectMgr;
private:
// Class representing guild member
class Member
{
struct RemainingValue
{
RemainingValue() : value(0), resetTime(0) { }
uint32 value;
uint32 resetTime;
};
public:
Guild();
~Guild();
Member(uint32 guildId, const uint64& guid, uint8 rankId) : m_guildId(guildId), m_guid(guid), m_logoutTime(::time(NULL)), m_rankId(rankId) { }
bool Create(Player* leader, std::string gname);
void CreateDefaultGuildRanks(LocaleConstant locale_idx);
void Disband();
void SetStats(Player* player);
void SetStats(const std::string& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId);
bool CheckStats() const;
void DeleteGuildBankItems(SQLTransaction& trans, bool alsoInDB = false);
typedef std::map<uint32, MemberSlot> MemberList;
typedef std::vector<RankInfo> RankList;
void SetPublicNote(const std::string& publicNote);
void SetOfficerNote(const std::string& officerNote);
uint32 GetId(){ return m_Id; }
const uint64& GetLeader(){ return m_LeaderGuid; }
std::string const& GetName() const { return m_Name; }
std::string const& GetMOTD() const { return MOTD; }
std::string const& GetGINFO() const { return GINFO; }
bool LoadFromDB(Field* fields);
void SaveToDB(SQLTransaction& trans) const;
void WritePacket(WorldPacket& data) const;
time_t GetCreatedDate() const { return m_CreatedDate; }
const uint64& GetGUID() const { return m_guid; }
std::string GetName() const { return m_name; }
uint32 GetAccountId() const { return m_accountId; }
uint8 GetRankId() const { return m_rankId; }
uint32 GetEmblemStyle() const { return m_EmblemStyle; }
uint32 GetEmblemColor() const { return m_EmblemColor; }
uint32 GetBorderStyle() const { return m_BorderStyle; }
uint32 GetBorderColor() const { return m_BorderColor; }
uint32 GetBackgroundColor() const { return m_BackgroundColor; }
void ChangeRank(uint8 newRank);
void SetLeader(uint64 guid);
bool AddMember(uint64 plGuid, uint32 plRank);
void ChangeRank(uint64 guid, uint32 newRank);
void DelMember(uint64 guid, bool isDisbanding = false, bool isKicked = false);
//lowest rank is the count of ranks - 1 (the highest rank_id in table)
uint32 GetLowestRank() const { return m_Ranks.size() - 1; }
inline void UpdateLogoutTime() { m_logoutTime = ::time(NULL); }
inline bool IsRank(uint8 rankId) const { return m_rankId == rankId; }
inline bool IsRankNotLower(uint8 rankId) const { return m_rankId <= rankId; }
inline bool IsSamePlayer(const uint64& guid) const { return m_guid == guid; }
void SetMOTD(std::string motd);
void SetGINFO(std::string ginfo);
void SetPNOTE(uint64 guid, std::string pnote);
void SetOFFNOTE(uint64 guid, std::string offnote);
void SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor);
void DecreaseBankRemainingValue(SQLTransaction& trans, uint8 tabId, uint32 amount);
uint32 GetBankRemainingValue(uint8 tabId, const Guild* guild) const;
uint32 GetMemberSize() const { return members.size(); }
uint32 GetAccountsNumber() const { return m_accountsNumber; }
void ResetTabTimes();
void ResetMoneyTime();
bool LoadGuildFromDB(QueryResult guildDataResult);
bool CheckGuildStructure();
bool LoadRanksFromDB(QueryResult guildRanksResult);
bool LoadMembersFromDB(QueryResult guildMembersResult);
void SetMemberStats(uint64 guid);
void BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL);
void BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL);
void BroadcastPacketToRank(WorldPacket *packet, uint32 rankId);
void BroadcastPacket(WorldPacket *packet);
void BroadcastEvent(GuildEvents event, uint64 guid, uint8 strCount, std::string str1, std::string str2, std::string str3);
template<class Do>
void BroadcastWorker(Do& _do, Player* except = NULL)
{
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
if (Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
if (player != except)
_do(player);
}
void CreateRank(std::string name,uint32 rights);
void DelRank();
std::string GetRankName(uint32 rankId);
uint32 GetRankRights(uint32 rankId);
uint32 GetRanksSize() const { return m_Ranks.size(); }
void SetRankName(uint32 rankId, std::string name);
void SetRankRights(uint32 rankId, uint32 rights);
bool HasRankRight(uint32 rankId, uint32 right)
{
return ((GetRankRights(rankId) & right) != GR_RIGHT_EMPTY) ? true : false;
}
int32 GetRank(uint32 LowGuid);
bool IsMember(uint32 LowGuid)
{
return (members.find(LowGuid) != members.end());
}
MemberSlot* GetMemberSlot(const std::string& name, uint64& guid)
{
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
{
if (itr->second.Name == name)
{
guid = itr->first;
return &itr->second;
}
}
return NULL;
}
void Roster(WorldSession *session = NULL); // NULL = broadcast
void Query(WorldSession *session);
void UpdateLogoutTime(uint64 guid);
// Guild EventLog
void DisplayGuildEventLog(WorldSession *session);
void LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank);
// ** Guild bank **
// Content & item deposit/withdraw
void DisplayGuildBankContent(WorldSession *session, uint8 TabId);
void DisplayGuildBankMoneyUpdate(WorldSession *session);
void SwapItems(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankTabDst, uint8 BankTabSlotDst, uint32 SplitedAmount);
void MoveFromBankToChar(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 PlayerBag, uint8 PlayerSlot, uint32 SplitedAmount);
void MoveFromCharToBank(Player * pl, uint8 PlayerBag, uint8 PlayerSlot, uint8 BankTab, uint8 BankTabSlot, uint32 SplitedAmount);
// Tabs
void DisplayGuildBankTabsInfo(WorldSession *session);
void CreateNewBankTab();
void SetGuildBankTabText(uint8 TabId, std::string text);
void SendGuildBankTabText(WorldSession *session, uint8 TabId);
void SetGuildBankTabInfo(uint8 TabId, std::string name, std::string icon);
uint8 GetPurchasedTabs() const { return m_TabListMap.size(); }
uint32 GetBankRights(uint32 rankId, uint8 TabId) const;
bool IsMemberHaveRights(uint32 LowGuid, uint8 TabId,uint32 rights) const;
bool CanMemberViewTab(uint32 LowGuid, uint8 TabId) const;
// Money deposit/withdraw
void SendMoneyInfo(WorldSession *session, uint32 LowGuid);
bool MemberMoneyWithdraw(uint32 amount, uint32 LowGuid, SQLTransaction& trans);
uint64 GetGuildBankMoney() { return m_GuildBankMoney; }
void SetBankMoney(int64 money, SQLTransaction& trans);
// per days
bool MemberItemWithdraw(uint8 TabId, uint32 LowGuid, SQLTransaction& trans);
uint32 GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId);
uint32 GetMemberMoneyWithdrawRem(uint32 LowGuid);
void SetBankMoneyPerDay(uint32 rankId, uint32 money);
void SetBankRightsAndSlots(uint32 rankId, uint8 TabId, uint32 right, uint32 SlotPerDay, bool db);
uint32 GetBankMoneyPerDay(uint32 rankId);
uint32 GetBankSlotPerDay(uint32 rankId, uint8 TabId);
// rights per day
bool LoadBankRightsFromDB(QueryResult guildBankTabRightsResult);
// Guild Bank Event Logs
void DisplayGuildBankLogs(WorldSession *session, uint8 TabId);
void LogBankEvent(SQLTransaction& trans, uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint16 ItemStackCount=0, uint8 DestTabId=0);
bool AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry, SQLTransaction& trans);
protected:
void AddRank(const std::string& name,uint32 rights,uint32 money);
uint32 m_Id;
std::string m_Name;
uint64 m_LeaderGuid;
std::string MOTD;
std::string GINFO;
time_t m_CreatedDate;
uint32 m_EmblemStyle;
uint32 m_EmblemColor;
uint32 m_BorderStyle;
uint32 m_BorderColor;
uint32 m_BackgroundColor;
uint32 m_accountsNumber;
RankList m_Ranks;
MemberList members;
typedef std::vector<GuildBankTab*> TabListMap;
TabListMap m_TabListMap;
/** These are actually ordered lists. The first element is the oldest entry.*/
typedef std::list<GuildEventLogEntry> GuildEventLog;
typedef std::list<GuildBankEventLogEntry> GuildBankEventLog;
GuildEventLog m_GuildEventLog;
GuildBankEventLog m_GuildBankEventLog_Money;
GuildBankEventLog m_GuildBankEventLog_Item[GUILD_BANK_MAX_TABS];
uint32 m_GuildEventLogNextGuid;
uint32 m_GuildBankEventLogNextGuid_Money;
uint32 m_GuildBankEventLogNextGuid_Item[GUILD_BANK_MAX_TABS];
uint64 m_GuildBankMoney;
inline Player* FindPlayer() const { return sObjectMgr.GetPlayer(m_guid); }
private:
void UpdateAccountsNumber();
// used only from high level Swap/Move functions
Item* GetItem(uint8 TabId, uint8 SlotId);
uint8 CanStoreItem(uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32 count, Item *pItem, bool swap = false) const;
Item* StoreItem(uint8 tab, GuildItemPosCountVec const& pos, Item *pItem, SQLTransaction& trans);
void RemoveItem(uint8 tab, uint8 slot, SQLTransaction& trans);
void DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2 = -1);
void DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots);
uint32 m_guildId;
// Fields from characters table
uint64 m_guid;
std::string m_name;
uint32 m_zoneId;
uint8 m_level;
uint8 m_class;
uint64 m_logoutTime;
uint32 m_accountId;
// Fields from guild_member table
uint8 m_rankId;
std::string m_publicNote;
std::string m_officerNote;
// internal common parts for CanStore/StoreItem functions
void AppendDisplayGuildBankSlot(WorldPacket& data, GuildBankTab const *tab, int32 slot);
uint8 _CanStoreItem_InSpecificSlot(uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32& count, bool swap, Item *pSrcItem) const;
uint8 _CanStoreItem_InTab(uint8 tab, GuildItemPosCountVec& dest, uint32& count, bool merge, Item *pSrcItem, uint8 skip_slot) const;
Item* _StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone, SQLTransaction& trans);
RemainingValue m_bankRemaining[GUILD_BANK_MAX_TABS + 1];
};
// Base class for event entries
class LogEntry
{
public:
LogEntry(uint32 guildId, uint32 guid) : m_guildId(guildId), m_guid(guid), m_timestamp(::time(NULL)) { }
LogEntry(uint32 guildId, uint32 guid, time_t timestamp) : m_guildId(guildId), m_guid(guid), m_timestamp(timestamp) { }
virtual ~LogEntry() { }
uint32 GetGUID() const { return m_guid; }
virtual void SaveToDB(SQLTransaction& trans) const = 0;
virtual void WritePacket(WorldPacket& data) const = 0;
protected:
uint32 m_guildId;
uint32 m_guid;
uint64 m_timestamp;
};
// Event log entry
class EventLogEntry : public LogEntry
{
public:
EventLogEntry(uint32 guildId, uint32 guid, GuildEventLogTypes eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank) :
LogEntry(guildId, guid), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { }
EventLogEntry(uint32 guildId, uint32 guid, time_t timestamp, GuildEventLogTypes eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank) :
LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_playerGuid1(playerGuid1), m_playerGuid2(playerGuid2), m_newRank(newRank) { }
~EventLogEntry() { }
void SaveToDB(SQLTransaction& trans) const;
void WritePacket(WorldPacket& data) const;
private:
GuildEventLogTypes m_eventType;
uint32 m_playerGuid1;
uint32 m_playerGuid2;
uint8 m_newRank;
};
// Bank event log entry
class BankEventLogEntry : public LogEntry
{
public:
static bool IsMoneyEvent(GuildBankEventLogTypes eventType)
{
return
eventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
eventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
eventType == GUILD_BANK_LOG_REPAIR_MONEY;
}
BankEventLogEntry(uint32 guildId, uint32 guid, GuildBankEventLogTypes eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
BankEventLogEntry(uint32 guildId, uint32 guid, time_t timestamp, uint8 tabId, GuildBankEventLogTypes eventType, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId) :
LogEntry(guildId, guid, timestamp), m_eventType(eventType), m_bankTabId(tabId), m_playerGuid(playerGuid),
m_itemOrMoney(itemOrMoney), m_itemStackCount(itemStackCount), m_destTabId(destTabId) { }
~BankEventLogEntry() { }
void SaveToDB(SQLTransaction& trans) const;
void WritePacket(WorldPacket& data) const;
private:
GuildBankEventLogTypes m_eventType;
uint8 m_bankTabId;
uint32 m_playerGuid;
uint32 m_itemOrMoney;
uint16 m_itemStackCount;
uint8 m_destTabId;
};
// Class encapsulating work with events collection
class LogHolder
{
public:
LogHolder(uint32 guildId, uint32 maxRecords) : m_guildId(guildId), m_maxRecords(maxRecords), m_nextGUID(GUILD_EVENT_LOG_GUID_UNDEFINED) { }
~LogHolder();
uint8 GetSize() const { return uint8(m_log.size()); }
// Checks if new log entry can be added to holder when loading from DB
inline bool CanInsert() const { return m_log.size() < m_maxRecords; }
// Adds event from DB to collection
void LoadEvent(LogEntry* entry);
// Adds new event to collection and saves it to DB
void AddEvent(SQLTransaction& trans, LogEntry* entry);
// Writes information about all events to packet
void WritePacket(WorldPacket& data) const;
uint32 GetNextGUID();
private:
typedef std::list<LogEntry*> GuildLog;
GuildLog m_log;
uint32 m_guildId;
uint32 m_maxRecords;
uint32 m_nextGUID;
};
// Class incapsulating guild rank data
class RankInfo
{
public:
RankInfo(uint32 guildId) : m_guildId(guildId), m_rankId(GUILD_RANK_NONE), m_rights(GR_RIGHT_EMPTY), m_bankMoneyPerDay(0) { }
RankInfo(uint32 guildId, uint8 rankId, const std::string& name, uint32 rights, uint32 money) :
m_guildId(guildId), m_rankId(rankId), m_name(name), m_rights(rights), m_bankMoneyPerDay(money) { }
bool LoadFromDB(Field* fields);
void SaveToDB(SQLTransaction& trans) const;
void WritePacket(WorldPacket& data) const;
uint8 GetId() const { return m_rankId; }
std::string GetName() const { return m_name; }
void SetName(const std::string& name);
uint32 GetRights() const { return m_rights; }
void SetRights(uint32 rights);
uint32 GetBankMoneyPerDay() const { return m_rankId == GR_GUILDMASTER ? GUILD_WITHDRAW_MONEY_UNLIMITED : m_bankMoneyPerDay; }
void SetBankMoneyPerDay(uint32 money);
inline uint8 GetBankTabRights(uint8 tabId) const { return tabId < GUILD_BANK_MAX_TABS ? m_bankTabRightsAndSlots[tabId].rights : 0; }
inline uint32 GetBankTabSlotsPerDay(uint8 tabId) const
{
if (tabId < GUILD_BANK_MAX_TABS)
return m_rankId == GR_GUILDMASTER ? GUILD_WITHDRAW_SLOT_UNLIMITED : m_bankTabRightsAndSlots[tabId].slots;
return 0;
}
void SetBankTabSlotsAndRights(uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB);
private:
uint32 m_guildId;
uint8 m_rankId;
std::string m_name;
uint32 m_rights;
uint32 m_bankMoneyPerDay;
GuildBankRightsAndSlots m_bankTabRightsAndSlots[GUILD_BANK_MAX_TABS];
};
class BankTab
{
public:
BankTab(uint32 guildId, uint8 tabId) : m_guildId(guildId), m_tabId(tabId)
{
memset(m_items, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*));
}
bool LoadFromDB(Field* fields);
bool LoadItemFromDB(Field* fields);
void Delete(SQLTransaction& trans, bool removeItemsFromDB = false);
void WritePacket(WorldPacket& data) const;
void WriteSlotPacket(WorldPacket& data, uint8 slotId) const;
void WriteInfoPacket(WorldPacket& data) const
{
data << m_name;
data << m_icon;
}
void SetInfo(const std::string& name, const std::string& icon);
void SetText(const std::string& text);
void SendText(const Guild* pGuild, WorldSession* session) const;
inline Item* GetItem(uint8 slotId) const { return slotId < GUILD_BANK_MAX_SLOTS ? m_items[slotId] : NULL; }
bool SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem);
private:
uint32 m_guildId;
uint8 m_tabId;
Item* m_items[GUILD_BANK_MAX_SLOTS];
std::string m_name;
std::string m_icon;
std::string m_text;
};
// Movement data
class MoveItemData
{
public:
MoveItemData(Guild* pGuild, Player* player, uint8 container, uint8 slotId) : m_pGuild(pGuild), m_pPlayer(player),
m_container(container), m_slotId(slotId), m_pItem(NULL), m_pClonedItem(NULL) { }
virtual ~MoveItemData() { }
virtual bool IsBank() const = 0;
// Initializes item pointer. Returns true, if item exists, false otherwise.
virtual bool InitItem() = 0;
// Checks splited amount against item. Splited amount cannot be more that number of items in stack.
virtual bool CheckItem(uint32& splitedAmount);
// Defines if player has rights to save item in container
virtual bool HasStoreRights(MoveItemData* /*pOther*/) const { return true; }
// Defines if player has rights to withdraw item from container
virtual bool HasWithdrawRights(MoveItemData* /*pOther*/) const { return true; }
// Checks if container can store specified item
uint8 CanStore(Item* pItem, bool swap, bool sendError);
// Clones stored item
bool CloneItem(uint32 count);
// Remove item from container (if splited update items fields)
virtual void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount = 0) = 0;
// Saves item to container
virtual Item* StoreItem(SQLTransaction& trans, Item* pItem) = 0;
// Log bank event
virtual void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const = 0;
// Log GM action
virtual void LogAction(MoveItemData* pFrom) const;
// Copy slots id from position vector
void CopySlots(SlotIds& ids) const;
Item* GetItem(bool isCloned = false) const { return isCloned ? m_pClonedItem : m_pItem; }
uint8 GetContainer() const { return m_container; }
uint8 GetSlotId() const { return m_slotId; }
protected:
virtual uint8 _CanStore(Item* pItem, bool swap) = 0;
Guild* m_pGuild;
Player *m_pPlayer;
uint8 m_container;
uint8 m_slotId;
Item* m_pItem;
Item* m_pClonedItem;
ItemPosCountVec m_vec;
};
class PlayerMoveItemData : public MoveItemData
{
public:
PlayerMoveItemData(Guild* pGuild, Player* player, uint8 container, uint8 slotId) :
MoveItemData(pGuild, player, container, slotId) { }
bool IsBank() const { return false; }
bool InitItem();
void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount = 0);
Item* StoreItem(SQLTransaction& trans, Item* pItem);
void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const;
protected:
uint8 _CanStore(Item* pItem, bool swap);
};
class BankMoveItemData : public MoveItemData
{
public:
BankMoveItemData(Guild* pGuild, Player* player, uint8 container, uint8 slotId) :
MoveItemData(pGuild, player, container, slotId) { }
bool IsBank() const { return true; }
bool InitItem();
bool HasStoreRights(MoveItemData* pOther) const;
bool HasWithdrawRights(MoveItemData* pOther) const;
void RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount);
Item* StoreItem(SQLTransaction& trans, Item* pItem);
void LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const;
void LogAction(MoveItemData* pFrom) const;
protected:
uint8 _CanStore(Item* pItem, bool swap);
private:
Item* _StoreItem(SQLTransaction& trans, BankTab* pTab, Item *pItem, ItemPosCount& pos, bool clone) const;
bool _ReserveSpace(uint8 slotId, Item* pItem, Item* pItemDest, uint32& count);
void _CanStoreItemInTab(Item* pItem, uint8 skipSlotId, bool merge, uint32& count);
};
typedef UNORDERED_MAP<uint32, Member*> Members;
typedef std::vector<RankInfo> Ranks;
typedef std::vector<BankTab*> BankTabs;
public:
static void SendCommandResult(WorldSession* session, GuildCommandType type, GuildCommandError errCode, const std::string& param = "");
static void SendSaveEmblemResult(WorldSession* session, GuildEmblemError errCode);
Guild();
~Guild();
bool Create(Player* pLeader, const std::string& name);
void Disband();
// Getters
uint32 GetId() const { return m_id; }
const uint64& GetLeaderGUID() const { return m_leaderGuid; }
const std::string& GetName() const { return m_name; }
const std::string& GetMOTD() const { return m_motd; }
const std::string& GetInfo() const { return m_info; }
// Handle client commands
void HandleRoster(WorldSession *session = NULL); // NULL = broadcast
void HandleQuery(WorldSession *session);
void HandleSetMOTD(WorldSession* session, const std::string& motd);
void HandleSetInfo(WorldSession* session, const std::string& info);
void HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo);
void HandleSetLeader(WorldSession* session, const std::string& name);
void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, const std::string& name, const std::string& icon);
void HandleSetMemberNote(WorldSession* session, const std::string& name, const std::string& note, bool officer);
void HandleSetRankInfo(WorldSession* session, uint8 rankId, const std::string& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots);
void HandleBuyBankTab(WorldSession* session, uint8 tabId);
void HandleInviteMember(WorldSession* session, const std::string& name);
void HandleAcceptMember(WorldSession* session);
void HandleLeaveMember(WorldSession* session);
void HandleRemoveMember(WorldSession* session, const std::string& name);
void HandleUpdateMemberRank(WorldSession* session, const std::string& name, bool demote);
void HandleAddNewRank(WorldSession* session, const std::string& name);
void HandleRemoveLowestRank(WorldSession* session);
void HandleMemberDepositMoney(WorldSession* session, uint32 amount);
bool HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair = false);
void HandleMemberLogout(WorldSession* session);
void HandleDisband(WorldSession* session);
// Send info to client
void SendInfo(WorldSession* session) const;
void SendEventLog(WorldSession *session) const;
void SendBankLog(WorldSession *session, uint8 tabId) const;
void SendBankTabsInfo(WorldSession *session) const;
void SendBankTabData(WorldSession* session, uint8 tabId) const;
void SendBankTabText(WorldSession *session, uint8 tabId) const;
void SendPermissions(WorldSession *session) const;
void SendMoneyInfo(WorldSession *session) const;
void SendLoginInfo(WorldSession* session) const;
// Load from DB
bool LoadFromDB(Field* fields);
bool LoadRankFromDB(Field* fields);
bool LoadMemberFromDB(Field* fields);
bool LoadEventLogFromDB(Field* fields);
bool LoadBankRightFromDB(Field* fields);
bool LoadBankTabFromDB(Field* fields);
bool LoadBankEventLogFromDB(Field* fields);
bool LoadBankItemFromDB(Field* fields);
bool Validate();
// Broadcasts
void BroadcastToGuild(WorldSession *session, bool officerOnly, const std::string& msg, uint32 language = LANG_UNIVERSAL) const;
void BroadcastPacketToRank(WorldPacket *packet, uint8 rankId) const;
void BroadcastPacket(WorldPacket *packet) const;
template<class Do>
void BroadcastWorker(Do& _do, Player* except = NULL)
{
for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
if (Player *player = itr->second->FindPlayer())
if (player != except)
_do(player);
}
// Members
// Adds member to guild. If rankId == GUILD_RANK_NONE, lowest rank is assigned.
bool AddMember(const uint64& guid, uint8 rankId = GUILD_RANK_NONE);
void DeleteMember(const uint64& guid, bool isDisbanding = false, bool isKicked = false);
bool ChangeMemberRank(const uint64& guid, uint8 newRank);
// Bank
void SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount);
void SwapItemsWithInventory(Player* player, bool toChar, uint8 tabId, uint8 slotId, uint8 playerBag, uint8 playerSlotId, uint32 splitedAmount);
// Bank tabs
void SetBankTabText(uint8 tabId, const std::string& text);
protected:
uint32 m_id;
std::string m_name;
uint64 m_leaderGuid;
std::string m_motd;
std::string m_info;
time_t m_createdDate;
EmblemInfo m_emblemInfo;
uint32 m_accountsNumber;
uint64 m_bankMoney;
Ranks m_ranks;
Members m_members;
BankTabs m_bankTabs;
// These are actually ordered lists. The first element is the oldest entry.
LogHolder* m_eventLog;
LogHolder* m_bankEventLog[GUILD_BANK_MAX_TABS + 1];
private:
inline uint8 _GetRanksSize() const { return uint8(m_ranks.size()); }
inline const RankInfo *GetRankInfo(uint8 rankId) const { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; }
inline RankInfo *GetRankInfo(uint8 rankId) { return rankId < _GetRanksSize() ? &m_ranks[rankId] : NULL; }
inline bool _HasRankRight(Player* player, uint32 right) const { return (_GetRankRights(player->GetRank()) & right) != GR_RIGHT_EMPTY; }
inline uint8 _GetLowestRankId() const { return uint8(m_ranks.size() - 1); }
inline uint8 _GetPurchasedTabsSize() const { return uint8(m_bankTabs.size()); }
inline BankTab* GetBankTab(uint8 tabId) { return tabId < m_bankTabs.size() ? m_bankTabs[tabId] : NULL; }
inline const BankTab* GetBankTab(uint8 tabId) const { return tabId < m_bankTabs.size() ? m_bankTabs[tabId] : NULL; }
inline const Member* GetMember(const uint64& guid) const
{
Members::const_iterator itr = m_members.find(GUID_LOPART(guid));
return itr != m_members.end() ? itr->second : NULL;
}
inline Member* GetMember(const uint64& guid)
{
Members::iterator itr = m_members.find(GUID_LOPART(guid));
return itr != m_members.end() ? itr->second : NULL;
}
inline Member* GetMember(WorldSession* session, const std::string& name)
{
for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
if (itr->second->GetName() == name)
return itr->second;
SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PLAYER_NOT_IN_GUILD_S, name);
return NULL;
}
inline void _DeleteMemberFromDB(uint32 lowguid) const
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBER);
stmt->setUInt32(0, lowguid);
CharacterDatabase.Execute(stmt);
}
// Creates log holders (either when loading or when creating guild)
void _CreateLogHolders();
// Tries to create new bank tab
bool _CreateNewBankTab();
// Creates default guild ranks with names in given locale
void _CreateDefaultGuildRanks(LocaleConstant loc);
// Creates new rank
void _CreateRank(const std::string& name, uint32 rights);
// Update account number when member added/removed from guild
void _UpdateAccountsNumber();
bool _IsLeader(Player* player) const;
void _DeleteBankItems(SQLTransaction& trans, bool removeItemsFromDB = false);
bool _ModifyBankMoney(SQLTransaction& trans, const uint64& amount, bool add);
void _SetLeaderGUID(Member* pLeader);
void _SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay);
void _SetRankBankTabRightsAndSlots(uint8 rankId, uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB = true);
uint8 _GetRankBankTabRights(uint8 rankId, uint8 tabId) const;
uint32 _GetRankRights(uint8 rankId) const;
uint32 _GetRankBankMoneyPerDay(uint8 rankId) const;
uint32 _GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const;
std::string _GetRankName(uint8 rankId) const;
uint32 _GetMemberRemainingSlots(const uint64& guid, uint8 tabId) const;
uint32 _GetMemberRemainingMoney(const uint64& guid) const;
void _DecreaseMemberRemainingSlots(SQLTransaction& trans, const uint64& guid, uint8 tabId);
bool _MemberHasTabRights(const uint64& guid, uint8 tabId, uint32 rights) const;
void _LogEvent(GuildEventLogTypes eventType, uint32 playerGuid1, uint32 playerGuid2 = 0, uint8 newRank = 0);
void _LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount = 0, uint8 destTabId = 0);
Item* _GetItem(uint8 tabId, uint8 slotId) const;
void _RemoveItem(SQLTransaction& trans, uint8 tabId, uint8 slotId);
void _MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAmount);
bool _DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError, uint32 splitedAmount = 0);
void _SendBankContent(WorldSession *session, uint8 tabId) const;
void _SendBankMoneyUpdate(WorldSession *session) const;
void _SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const;
void _SendBankContentUpdate(uint8 tabId, SlotIds slots) const;
void _BroadcastEvent(GuildEvents guildEvent, const uint64& guid, const char* param1 = NULL, const char* param2 = NULL, const char* param3 = NULL) const;
};
#endif