aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql4
-rw-r--r--sql/updates/10241_characters_guilds.sql2
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp2
-rwxr-xr-xsrc/server/game/Chat/Commands/Level3.cpp13
-rwxr-xr-xsrc/server/game/Entities/Item/Container/Bag.cpp4
-rwxr-xr-xsrc/server/game/Entities/Item/Container/Bag.h2
-rwxr-xr-xsrc/server/game/Entities/Item/Item.cpp10
-rwxr-xr-xsrc/server/game/Entities/Item/Item.h2
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp41
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h6
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp440
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h3
-rwxr-xr-xsrc/server/game/Guilds/Guild.cpp3788
-rwxr-xr-xsrc/server/game/Guilds/Guild.h858
-rwxr-xr-xsrc/server/game/Miscellaneous/SharedDefines.h8
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.cpp42
-rwxr-xr-xsrc/server/game/Scripting/ScriptMgr.h26
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/CharacterHandler.cpp18
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/ChatHandler.cpp4
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/GuildHandler.cpp1145
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/NPCHandler.cpp23
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp40
-rwxr-xr-xsrc/server/game/Server/WorldSession.cpp10
-rwxr-xr-xsrc/server/game/Server/WorldSession.h10
-rwxr-xr-xsrc/server/game/World/World.cpp8
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.cpp116
-rwxr-xr-xsrc/server/shared/Database/Implementation/CharacterDatabase.h75
27 files changed, 3527 insertions, 3173 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index cd460411e9e..74ad13fe060 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -1533,7 +1533,7 @@ DROP TABLE IF EXISTS `guild_bank_right`;
CREATE TABLE `guild_bank_right` (
`guildid` int(11) unsigned NOT NULL default '0',
`TabId` tinyint(1) unsigned NOT NULL default '0',
- `rid` int(11) unsigned NOT NULL default '0',
+ `rid` tinyint(1) unsigned NOT NULL default '0',
`gbright` tinyint(3) unsigned NOT NULL default '0',
`SlotPerDay` int(11) unsigned NOT NULL default '0',
PRIMARY KEY (`guildid`,`TabId`,`rid`),
@@ -1659,7 +1659,7 @@ DROP TABLE IF EXISTS `guild_rank`;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `guild_rank` (
`guildid` int(6) unsigned NOT NULL default '0',
- `rid` int(11) unsigned NOT NULL,
+ `rid` tinyint(1) unsigned NOT NULL,
`rname` varchar(255) NOT NULL default '',
`rights` int(3) unsigned NOT NULL default '0',
`BankMoneyPerDay` int(11) unsigned NOT NULL default '0',
diff --git a/sql/updates/10241_characters_guilds.sql b/sql/updates/10241_characters_guilds.sql
new file mode 100644
index 00000000000..ba2d2cf7277
--- /dev/null
+++ b/sql/updates/10241_characters_guilds.sql
@@ -0,0 +1,2 @@
+ALTER TABLE guild_rank CHANGE COLUMN rid rid TINYINT(1) UNSIGNED NOT NULL;
+ALTER TABLE guild_bank_right CHANGE COLUMN rid rid TINYINT(1) UNSIGNED NOT NULL DEFAULT 0;
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 26d65133125..e506f8c608b 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -340,7 +340,7 @@ void AuctionHouseMgr::LoadAuctionItems()
Item *item = NewItemOrBag(proto);
- if (!item->LoadFromDB(item_guid, 0, result, item_template))
+ if (!item->LoadFromDB(item_guid, 0, fields, item_template))
{
delete item;
continue;
diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp
index 90c766dadfb..3f10d91fc0a 100755
--- a/src/server/game/Chat/Commands/Level3.cpp
+++ b/src/server/game/Chat/Commands/Level3.cpp
@@ -3996,10 +3996,7 @@ bool ChatHandler::HandleGuildInviteCommand(const char *args)
return false;
// player's guild membership checked in AddMember before add
- if (!targetGuild->AddMember (target_guid,targetGuild->GetLowestRank ()))
- return false;
-
- return true;
+ return targetGuild->AddMember(target_guid);
}
bool ChatHandler::HandleGuildUninviteCommand(const char *args)
@@ -4018,7 +4015,7 @@ bool ChatHandler::HandleGuildUninviteCommand(const char *args)
if (!targetGuild)
return false;
- targetGuild->DelMember (target_guid, false, true);
+ targetGuild->DeleteMember(target_guid, false, true);
return true;
}
@@ -4045,11 +4042,7 @@ bool ChatHandler::HandleGuildRankCommand(const char *args)
return false;
uint32 newrank = uint32 (atoi (rankStr));
- if (newrank > targetGuild->GetLowestRank ())
- return false;
-
- targetGuild->ChangeRank (target_guid,newrank);
- return true;
+ return targetGuild->ChangeMemberRank(target_guid, newrank);
}
bool ChatHandler::HandleGuildDeleteCommand(const char *args)
diff --git a/src/server/game/Entities/Item/Container/Bag.cpp b/src/server/game/Entities/Item/Container/Bag.cpp
index 2fe1a7c5ca0..ae04c0e4504 100755
--- a/src/server/game/Entities/Item/Container/Bag.cpp
+++ b/src/server/game/Entities/Item/Container/Bag.cpp
@@ -105,9 +105,9 @@ void Bag::SaveToDB(SQLTransaction& trans)
Item::SaveToDB(trans);
}
-bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, PreparedQueryResult result, uint32 entry)
+bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entry)
{
- if (!Item::LoadFromDB(guid, owner_guid, result, entry))
+ if (!Item::LoadFromDB(guid, owner_guid, fields, entry))
return false;
ItemPrototype const* itemProto = GetProto(); // checked in Item::LoadFromDB
diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h
index eb0df78516b..5ba01ebb9ee 100755
--- a/src/server/game/Entities/Item/Container/Bag.h
+++ b/src/server/game/Entities/Item/Container/Bag.h
@@ -54,7 +54,7 @@ class Bag : public Item
// overwrite virtual Item::SaveToDB
void SaveToDB(SQLTransaction& trans);
// overwrite virtual Item::LoadFromDB
- bool LoadFromDB(uint32 guid, uint64 owner_guid, PreparedQueryResult result, uint32 entry);
+ bool LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entry);
// overwrite virtual Item::DeleteFromDB
void DeleteFromDB(SQLTransaction& trans);
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 8dcce98c040..55d5c80889c 100755
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -383,7 +383,7 @@ void Item::SaveToDB(SQLTransaction& trans)
SetState(ITEM_UNCHANGED);
}
-bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, PreparedQueryResult result, uint32 entry)
+bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entry)
{
// 0 1 2 3 4 5 6 7 8 9 10
//result = CharacterDatabase.PQuery("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text FROM item_instance WHERE guid = '%u'", guid);
@@ -400,14 +400,6 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, PreparedQueryResult result
if (!proto)
return false;
- if (!result)
- {
- sLog.outError("Item (GUID: %u owner: %u) not found in table `item_instance`, can't load. ", guid, GUID_LOPART(owner_guid));
- return false;
- }
-
- Field* fields = result->Fetch();
-
// set owner (not if item is only loaded for gbank/auction/mail
if (owner_guid != 0)
SetOwnerGUID(owner_guid);
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 0de9ed9609c..f42a212dc02 100755
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -245,7 +245,7 @@ class Item : public Object
bool IsBindedNotWith(Player const* player) const;
bool IsBoundByEnchant() const;
virtual void SaveToDB(SQLTransaction& trans);
- virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, PreparedQueryResult result, uint32 entry);
+ virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entry);
virtual void DeleteFromDB(SQLTransaction& trans);
void DeleteFromInventoryDB(SQLTransaction& trans);
void SaveRefundDataToDB();
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index d5c9c6d6d94..53c5f0f2aa2 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -4458,8 +4458,8 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
sObjectAccessor.ConvertCorpseForPlayer(playerguid);
if (uint32 guildId = GetGuildIdFromDB(playerguid))
- if (Guild* guild = sObjectMgr.GetGuildById(guildId))
- guild->DelMember(guid);
+ if (Guild* pGuild = sObjectMgr.GetGuildById(guildId))
+ pGuild->DeleteMember(guid);
// remove from arena teams
LeaveAllArenaTeams(playerguid);
@@ -4522,8 +4522,9 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
{
do
{
- uint32 item_guidlow = (*resultItems)[11].GetUInt32();
- uint32 item_template = (*resultItems)[12].GetUInt32();
+ Field* fields = resultItems->Fetch();
+ uint32 item_guidlow = fields[11].GetUInt32();
+ uint32 item_template = fields[12].GetUInt32();
ItemPrototype const* itemProto = sObjectMgr.GetItemPrototype(item_template);
if (!itemProto)
@@ -4535,7 +4536,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
}
Item *pItem = NewItemOrBag(itemProto);
- if (!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER), resultItems, item_template))
+ if (!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER), fields, item_template))
{
pItem->FSetState(ITEM_REMOVED);
pItem->SaveToDB(trans); // it also deletes item object!
@@ -5117,28 +5118,8 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g
if (!pGuild)
return TotalCost;
- if (!pGuild->HasRankRight(GetRank(), GR_RIGHT_WITHDRAW_REPAIR))
- {
- sLog.outStaticDebug("You do not have rights to withdraw for repairs");
- return TotalCost;
- }
-
- if (pGuild->GetMemberMoneyWithdrawRem(GetGUIDLow()) < costs)
- {
- sLog.outStaticDebug("You do not have enough money withdraw amount remaining");
+ if (!pGuild->HandleMemberWithdrawMoney(GetSession(), costs, true))
return TotalCost;
- }
-
- if (pGuild->GetGuildBankMoney() < costs)
- {
- sLog.outStaticDebug("There is not enough money in bank");
- return TotalCost;
- }
-
- //- TODO: Fix bad function call design
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- pGuild->MemberMoneyWithdraw(costs, GetGUIDLow(), trans);
- CharacterDatabase.CommitTransaction(trans);
TotalCost = costs;
}
@@ -7004,12 +6985,12 @@ uint32 Player::GetGuildIdFromDB(uint64 guid)
return id;
}
-uint32 Player::GetRankFromDB(uint64 guid)
+uint8 Player::GetRankFromDB(uint64 guid)
{
QueryResult result = CharacterDatabase.PQuery("SELECT rank FROM guild_member WHERE guid='%u'", GUID_LOPART(guid));
if (result)
{
- uint32 v = result->Fetch()[0].GetUInt32();
+ uint32 v = result->Fetch()[0].GetUInt8();
return v;
}
else
@@ -16896,7 +16877,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timediff)
Item *item = NewItemOrBag(proto);
- if (!item->LoadFromDB(item_guid, GetGUID(), result, item_id))
+ if (!item->LoadFromDB(item_guid, GetGUID(), fields, item_id))
{
sLog.outError("Player::_LoadInventory: Player %s has broken item (id: #%u) in inventory, deleted.", GetName(),item_id);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVENTORY_ITEM);
@@ -17115,7 +17096,7 @@ void Player::_LoadMailedItems(Mail *mail)
Item *item = NewItemOrBag(proto);
- if (!item->LoadFromDB(item_guid_low, MAKE_NEW_GUID(fields[13].GetUInt32(), 0, HIGHGUID_PLAYER), result, item_template))
+ if (!item->LoadFromDB(item_guid_low, MAKE_NEW_GUID(fields[13].GetUInt32(), 0, HIGHGUID_PLAYER), fields, item_template))
{
sLog.outError("Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: %u, deleted from mail", mail->messageID, item_guid_low);
CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index c0c5d54cba1..42d8bc8b67d 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1715,12 +1715,12 @@ class Player : public Unit, public GridObject<Player>
void SendUpdateToOutOfRangeGroupMembers();
void SetInGuild(uint32 GuildId) { SetUInt32Value(PLAYER_GUILDID, GuildId); }
- void SetRank(uint32 rankId){ SetUInt32Value(PLAYER_GUILDRANK, rankId); }
+ void SetRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); }
+ uint8 GetRank() { return uint8(GetUInt32Value(PLAYER_GUILDRANK)); }
void SetGuildIdInvited(uint32 GuildId) { m_GuildIdInvited = GuildId; }
uint32 GetGuildId() { return GetUInt32Value(PLAYER_GUILDID); }
static uint32 GetGuildIdFromDB(uint64 guid);
- uint32 GetRank(){ return GetUInt32Value(PLAYER_GUILDRANK); }
- static uint32 GetRankFromDB(uint64 guid);
+ static uint8 GetRankFromDB(uint64 guid);
int GetGuildIdInvited() { return m_GuildIdInvited; }
static void RemovePetitionsAndSigns(uint64 guid, uint32 type);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index e0162c4988c..66348e29dc6 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -346,7 +346,7 @@ std::string ObjectMgr::GetGuildNameById(uint32 GuildId) const
Guild* ObjectMgr::GetGuildByLeader(const uint64 &guid) const
{
for (GuildMap::const_iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr)
- if (itr->second->GetLeader() == guid)
+ if (itr->second->GetLeaderGUID() == guid)
return itr->second;
return NULL;
@@ -3488,288 +3488,282 @@ void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, Play
void ObjectMgr::LoadGuilds()
{
- Guild *newGuild;
-
- // 0 1 2 3 4 5 6
- QueryResult result = CharacterDatabase.Query("SELECT guild.guildid,guild.name,leaderguid,EmblemStyle,EmblemColor,BorderStyle,BorderColor,"
- // 7 8 9 10 11 12
- "BackgroundColor,info,motd,createdate,BankMoney,COUNT(guild_bank_tab.guildid) "
- "FROM guild LEFT JOIN guild_bank_tab ON guild.guildid = guild_bank_tab.guildid GROUP BY guild.guildid ORDER BY guildid ASC");
+ PreparedStatement* stmt = NULL;
+ PreparedQueryResult result;
+ sLog.outString("Loading Guilds...");
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILDS);
+ result = CharacterDatabase.Query(stmt);
if (!result)
{
barGoLink bar(1);
-
bar.step();
- sLog.outString();
sLog.outString(">> Loaded 0 guild definitions");
+ sLog.outString();
return;
}
-
- // load guild ranks
- // 0 1 2 3 4
- QueryResult guildRanksResult = CharacterDatabase.Query("SELECT guildid,rid,rname,rights,BankMoneyPerDay FROM guild_rank ORDER BY guildid ASC, rid ASC");
-
- // load guild members
- // 0 1 2 3 4 5 6
- QueryResult guildMembersResult = CharacterDatabase.Query("SELECT guildid,guild_member.guid,rank,pnote,offnote,BankResetTimeMoney,BankRemMoney,"
- // 7 8 9 10 11 12
- "BankResetTimeTab0,BankRemSlotsTab0,BankResetTimeTab1,BankRemSlotsTab1,BankResetTimeTab2,BankRemSlotsTab2,"
- // 13 14 15 16 17 18
- "BankResetTimeTab3,BankRemSlotsTab3,BankResetTimeTab4,BankRemSlotsTab4,BankResetTimeTab5,BankRemSlotsTab5,"
- // 19 20 21 22 23 24
- "characters.name, characters.level, characters.class, characters.zone, characters.logout_time, characters.account "
- "FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid ORDER BY guildid ASC");
-
- // load guild bank tab rights
- // 0 1 2 3 4
- QueryResult guildBankTabRightsResult = CharacterDatabase.Query("SELECT guildid,TabId,rid,gbright,SlotPerDay FROM guild_bank_right ORDER BY guildid ASC, TabId ASC");
-
-
+ // 1. Load all guilds
barGoLink bar(result->GetRowCount());
-
- uint32 maxid = 0;
do
{
- //Field *fields = result->Fetch();
-
bar.step();
- newGuild = new Guild;
- if (!newGuild->LoadGuildFromDB(result) ||
- !newGuild->LoadRanksFromDB(guildRanksResult) ||
- !newGuild->LoadMembersFromDB(guildMembersResult) ||
- !newGuild->LoadBankRightsFromDB(guildBankTabRightsResult) ||
- !newGuild->CheckGuildStructure()
- )
+ Field* fields = result->Fetch();
+ Guild* pNewGuild = new Guild();
+ if (!pNewGuild->LoadFromDB(fields))
{
- newGuild->Disband();
- delete newGuild;
+ delete pNewGuild;
continue;
}
-
- AddGuild(newGuild);
-
- if (maxid < newGuild->GetId())
- maxid = newGuild->GetId();
-
+ AddGuild(pNewGuild);
}
while (result->NextRow());
-
- std::vector<Guild*> GuildVector(maxid + 1);
-
- for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); ++itr)
- GuildVector[itr->second->GetId()] = (*itr).second;
-
- // 0 1 2 3 4 5 6
- QueryResult guildEventResult = CharacterDatabase.Query("SELECT LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp, guildid FROM guild_eventlog ORDER BY TimeStamp DESC, LogGuid DESC");
-
- // 0 1 2 3 4 5 6 7 8
- QueryResult guildBankEventResult = CharacterDatabase.Query("SELECT LogGuid, EventType, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp, guildid, TabId FROM guild_bank_eventlog ORDER BY TimeStamp DESC,LogGuid DESC");
-
- // 0 1 2 3 4
- QueryResult guildBankTabResult = CharacterDatabase.Query("SELECT TabId, TabName, TabIcon, TabText, guildid FROM guild_bank_tab");
-
- PreparedStatement* guildBankItemStmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_BANK_ITEMS);
- PreparedQueryResult guildBankItemResult = CharacterDatabase.Query(guildBankItemStmt);
-
- LoadGuildEvents(GuildVector, guildEventResult);
- LoadGuildBankEvents(GuildVector, guildBankEventResult);
- LoadGuildBanks(GuildVector, guildBankTabResult, guildBankItemResult);
-
- //delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table
- //you can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT
- PreparedStatement *guildEventLogStmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_GUILD_EVENT_LOGS);
- guildEventLogStmt->setUInt32(0, sWorld.getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT));
- CharacterDatabase.Execute(guildEventLogStmt);
-
- PreparedStatement *guildBankEventLogStmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_GUILD_BANK_EVENT_LOGS);
- guildBankEventLogStmt->setUInt32(0, sWorld.getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT));
- CharacterDatabase.Execute(guildBankEventLogStmt);
-
sLog.outString();
- sLog.outString(">> Loaded %u guild definitions", mGuildMap.size());
-}
+ sLog.outString(">> Loaded " UI64FMTD " guilds definitions", result->GetRowCount());
+ sLog.outString();
-void ObjectMgr::LoadGuildEvents(std::vector<Guild*>& GuildVector, QueryResult& result)
-{
+ uint64 rowCount = 0;
+ // 2. Load all guild ranks
+ sLog.outString("Loading guild ranks...");
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_RANKS);
+ result = CharacterDatabase.Query(stmt);
if (result)
{
+ rowCount = result->GetRowCount();
+ barGoLink bar(rowCount);
do
{
- Field *fields = result->Fetch();
- uint32 guildid = fields[6].GetUInt32();
- if (guildid >= GuildVector.size() || GuildVector[guildid] == NULL)
- continue;
-
- if (!GuildVector[guildid]->m_GuildEventLogNextGuid)
- GuildVector[guildid]->m_GuildEventLogNextGuid = fields[0].GetUInt32();
-
- if (GuildVector[guildid]->m_GuildEventLog.size() < GUILD_EVENTLOG_MAX_RECORDS)
- {
- GuildEventLogEntry NewEvent;
- NewEvent.EventType = fields[1].GetUInt8();
- NewEvent.PlayerGuid1 = fields[2].GetUInt32();
- NewEvent.PlayerGuid2 = fields[3].GetUInt32();
- NewEvent.NewRank = fields[4].GetUInt8();
- NewEvent.TimeStamp = fields[5].GetUInt64();
+ bar.step();
- GuildVector[guildid]->m_GuildEventLog.push_front(NewEvent);
- }
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ if (Guild* pGuild = GetGuildById(guildId))
+ pGuild->LoadRankFromDB(fields);
}
while (result->NextRow());
}
-}
+ else
+ {
+ barGoLink bar(1);
+ bar.step();
+ }
+ sLog.outString(">> Loaded " UI64FMTD " ranks for all the guilds", rowCount);
+ sLog.outString();
-void ObjectMgr::LoadGuildBankEvents(std::vector<Guild*>& GuildVector, QueryResult& result)
-{
+ // 3. Load all guild members
+ sLog.outString("Loading guild members...");
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_MEMBERS);
+ result = CharacterDatabase.Query(stmt);
if (result)
{
+ rowCount = result->GetRowCount();
+ barGoLink bar(rowCount);
do
{
- Field *fields = result->Fetch();
- uint32 logGuid = fields[0].GetUInt32();
- uint32 guildid = fields[7].GetUInt32();
- if (guildid >= GuildVector.size() || GuildVector[guildid] == NULL)
- continue;
-
- uint8 TabId = fields[8].GetUInt8();
-
- if (TabId < GuildVector[guildid]->GetPurchasedTabs() || TabId == GUILD_BANK_MONEY_LOGS_TAB)
- {
- bool canInsert;
-
- if (TabId != GUILD_BANK_MONEY_LOGS_TAB)
- {
- if (!GuildVector[guildid]->m_GuildBankEventLogNextGuid_Item[TabId])
- GuildVector[guildid]->m_GuildBankEventLogNextGuid_Item[TabId] = logGuid;
- }
- else
- {
- if (!GuildVector[guildid]->m_GuildBankEventLogNextGuid_Money)
- GuildVector[guildid]->m_GuildBankEventLogNextGuid_Money = logGuid;
- }
-
- if (TabId != GUILD_BANK_MONEY_LOGS_TAB)
- canInsert = GuildVector[guildid]->m_GuildBankEventLog_Item[TabId].size() < GUILD_BANK_MAX_LOGS;
- else
- canInsert = GuildVector[guildid]->m_GuildBankEventLog_Money.size() < GUILD_BANK_MAX_LOGS;
+ bar.step();
- if (canInsert)
- {
- GuildBankEventLogEntry NewEvent;
- NewEvent.EventType = fields[1].GetUInt8();
- NewEvent.PlayerGuid = fields[2].GetUInt32();
- NewEvent.ItemOrMoney = fields[3].GetUInt32();
- NewEvent.ItemStackCount = fields[4].GetUInt8();
- NewEvent.DestTabId = fields[5].GetUInt8();
- NewEvent.TimeStamp = fields[6].GetUInt64();
-
- if (TabId != GUILD_BANK_MONEY_LOGS_TAB)
- {
- if (NewEvent.isMoneyEvent())
- {
- CharacterDatabase.PExecute("UPDATE guild_bank_eventlog SET TabId='%u' WHERE guildid='%u' AND TabId='%u' AND LogGuid='%u'", GUILD_BANK_MONEY_LOGS_TAB, guildid, TabId, logGuid);
- sLog.outError("GuildBankEventLog ERROR: MoneyEvent LogGuid %u for Guild %u had incorrectly set its TabId to %u, correcting it to %u TabId", logGuid, guildid, TabId, GUILD_BANK_MONEY_LOGS_TAB);
- continue;
- }
- else
- GuildVector[guildid]->m_GuildBankEventLog_Item[TabId].push_front(NewEvent);
- }
- else
- {
- if (!NewEvent.isMoneyEvent())
- sLog.outError("GuildBankEventLog ERROR: MoneyEvent LogGuid %u for Guild %u is not MoneyEvent - ignoring...", logGuid, guildid);
- else
- GuildVector[guildid]->m_GuildBankEventLog_Money.push_front(NewEvent);
- }
- }
- }
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ if (Guild* pGuild = GetGuildById(guildId))
+ pGuild->LoadMemberFromDB(fields);
}
while (result->NextRow());
}
-}
+ else
+ {
+ rowCount = 0;
+ barGoLink bar(1);
+ bar.step();
+ }
+ sLog.outString(">> Loaded " UI64FMTD " members from all the guilds", rowCount);
+ sLog.outString();
-void ObjectMgr::LoadGuildBanks(std::vector<Guild*>& GuildVector, QueryResult& result, PreparedQueryResult& itemResult)
-{
+ // 4. Load all guild bank tab rights
+ sLog.outString("Loading bank tab rights...");
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_BANK_RIGHTS);
+ result = CharacterDatabase.Query(stmt);
if (result)
{
+ rowCount = result->GetRowCount();
+ barGoLink bar(rowCount);
do
{
- Field *fields = result->Fetch();
- uint8 TabId = fields[0].GetUInt8();
- uint32 guildid = fields[4].GetUInt32();
-
- if (guildid >= GuildVector.size() || GuildVector[guildid] == NULL)
- continue;
-
- if (TabId < GuildVector[guildid]->GetPurchasedTabs())
- {
- GuildBankTab *NewTab = new GuildBankTab;
-
- NewTab->Name = fields[1].GetString();
- NewTab->Icon = fields[2].GetString();
- NewTab->Text = fields[3].GetString();
+ bar.step();
- GuildVector[guildid]->m_TabListMap[TabId] = NewTab;
- }
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ if (Guild* pGuild = GetGuildById(guildId))
+ pGuild->LoadBankRightFromDB(fields);
}
while (result->NextRow());
}
+ else
+ {
+ rowCount = 0;
+ barGoLink bar(1);
+ bar.step();
+ }
+ sLog.outString(">> Loaded " UI64FMTD " bank tab rights for all the guilds", rowCount);
+ sLog.outString();
- if (itemResult)
+ // 5. Load all event logs
+ sLog.outString("Loading guild event logs...");
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_EVENTLOGS);
+ result = CharacterDatabase.Query(stmt);
+ if (result)
{
+ rowCount = result->GetRowCount();
+ barGoLink bar(rowCount);
do
{
- Field *fields = itemResult->Fetch();
- uint8 TabId = fields[11].GetUInt8();
- uint8 SlotId = fields[12].GetUInt8();
- uint32 ItemGuid = fields[13].GetUInt32();
- uint32 ItemId = fields[14].GetUInt32();
- uint32 guildid = fields[15].GetUInt32();
- if (guildid >= GuildVector.size() || GuildVector[guildid] == NULL)
- continue;
+ bar.step();
- if (TabId >= GuildVector[guildid]->GetPurchasedTabs())
- {
- sLog.outError("Guild::LoadGuildBankFromDB: Invalid tab for item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid, ItemId);
- continue;
- }
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ if (Guild* pGuild = GetGuildById(guildId))
+ pGuild->LoadEventLogFromDB(fields);
+ }
+ while (result->NextRow());
+ }
+ else
+ {
+ rowCount = 0;
+ barGoLink bar(1);
+ bar.step();
+ }
+ sLog.outString(">> Loaded " UI64FMTD " event logs for all the guilds", rowCount);
+ sLog.outString();
- if (SlotId >= GUILD_BANK_MAX_SLOTS)
- {
- sLog.outError("Guild::LoadGuildBankFromDB: Invalid slot for item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid, ItemId);
- continue;
- }
+ // 6. Load all bank event logs
+ sLog.outString("Loading guild bank event logs...");
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_BANK_EVENTLOGS);
+ result = CharacterDatabase.Query(stmt);
+ if (result)
+ {
+ rowCount = result->GetRowCount();
+ barGoLink bar(rowCount);
+ do
+ {
+ bar.step();
- ItemPrototype const *proto = sObjectMgr.GetItemPrototype(ItemId);
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ if (Guild* pGuild = GetGuildById(guildId))
+ pGuild->LoadBankEventLogFromDB(fields);
+ }
+ while (result->NextRow());
+ }
+ else
+ {
+ rowCount = 0;
+ barGoLink bar(1);
+ bar.step();
+ }
+ sLog.outString(">> Loaded " UI64FMTD " bank event logs for all the guilds", rowCount);
+ sLog.outString();
- if (!proto)
- {
- sLog.outError("Guild::LoadGuildBankFromDB: Unknown item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid, ItemId);
- continue;
- }
+ // 7. Load all guild bank tabs
+ sLog.outString("Loading guild bank tabs...");
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_BANK_TABS);
+ result = CharacterDatabase.Query(stmt);
+ if (result)
+ {
+ rowCount = result->GetRowCount();
+ barGoLink bar(rowCount);
+ do
+ {
+ bar.step();
- Item *pItem = NewItemOrBag(proto);
- if (!pItem->LoadFromDB(ItemGuid, 0, itemResult, ItemId))
- {
- PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM);
- stmt->setUInt32(0, guildid);
- stmt->setUInt32(1, uint32(TabId));
- stmt->setUInt32(2, uint32(SlotId));
- CharacterDatabase.Execute(stmt);
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[0].GetUInt32();
+ if (Guild* pGuild = GetGuildById(guildId))
+ pGuild->LoadBankTabFromDB(fields);
+ }
+ while (result->NextRow());
+ }
+ else
+ {
+ rowCount = 0;
+ barGoLink bar(1);
+ bar.step();
+ }
+ sLog.outString(">> Loaded " UI64FMTD " bank tabs for all the guilds", rowCount);
+ sLog.outString();
- sLog.outError("Item GUID %u not found in item_instance, deleting from Guild Bank!", ItemGuid);
- delete pItem;
- continue;
- }
+ // 8. Fill all guild bank tabs
+ sLog.outString("Filling bank tabs with items...");
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_BANK_ITEMS);
+ result = CharacterDatabase.Query(stmt);
+ if (result)
+ {
+ rowCount = result->GetRowCount();
+ barGoLink bar(rowCount);
+ do
+ {
+ bar.step();
- pItem->AddToWorld();
- GuildVector[guildid]->m_TabListMap[TabId]->Slots[SlotId] = pItem;
+ Field* fields = result->Fetch();
+ uint32 guildId = fields[11].GetUInt32();
+ if (Guild* pGuild = GetGuildById(guildId))
+ pGuild->LoadBankItemFromDB(fields);
}
- while (itemResult->NextRow());
+ while (result->NextRow());
}
+ else
+ {
+ rowCount = 0;
+ barGoLink bar(1);
+ bar.step();
+ }
+ sLog.outString(">> Filled bank tabs with " UI64FMTD " items for all the guilds", rowCount);
+ sLog.outString();
+
+ // 9. Validate loaded guild data
+ sLog.outString("Validating data of loaded guilds...");
+ barGoLink barGuilds(mGuildMap.size());
+ for (GuildMap::iterator itr = mGuildMap.begin(); itr != mGuildMap.end(); )
+ {
+ barGuilds.step();
+ Guild* pGuild = itr->second;
+ if (!pGuild->Validate())
+ {
+ ++itr;
+ mGuildMap.erase(pGuild->GetId());
+ delete pGuild;
+ }
+ else
+ ++itr;
+ }
+ // Cleanup
+ // Delete orphan guild ranks
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_CLEAN_GUILD_RANKS);
+ CharacterDatabase.Execute(stmt);
+ // Delete orphan guild members
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_CLEAN_GUILD_MEMBERS);
+ CharacterDatabase.Execute(stmt);
+ // Delete orphan guild bank rights
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_CLEAN_GUILD_BANK_RIGHTS);
+ CharacterDatabase.Execute(stmt);
+ // Delete orphan guild bank tabs
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_CLEAN_GUILD_BANK_TABS);
+ CharacterDatabase.Execute(stmt);
+ // Delete orphan guild bank items
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_CLEAN_GUILD_BANK_ITEMS);
+ CharacterDatabase.Execute(stmt);
+
+ // Delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table.
+ // You can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_GUILD_EVENT_LOGS);
+ stmt->setUInt32(0, sWorld.getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT));
+ CharacterDatabase.Execute(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_GUILD_BANK_EVENT_LOGS);
+ stmt->setUInt32(0, sWorld.getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT));
+ CharacterDatabase.Execute(stmt);
+
+ sLog.outString();
+ sLog.outString(">> Successfully loaded %u guilds", uint32(mGuildMap.size()));
}
void ObjectMgr::LoadArenaTeams()
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index af78f9c5a46..d75ab4c3e9a 100755
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -797,9 +797,6 @@ class ObjectMgr
}
void LoadGuilds();
- void LoadGuildEvents(std::vector<Guild*>& GuildVector, QueryResult& result);
- void LoadGuildBankEvents(std::vector<Guild*>& GuildVector, QueryResult& result);
- void LoadGuildBanks(std::vector<Guild*>& GuildVector, QueryResult& result, PreparedQueryResult& itemResult);
void LoadArenaTeams();
void LoadGroups();
void LoadQuests();
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 3ed1a6a9d7a..b0a4b1f4bc5 100755
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -17,763 +17,1211 @@
*/
#include "DatabaseEnv.h"
-#include "WorldPacket.h"
-#include "WorldSession.h"
-#include "Player.h"
-#include "Opcodes.h"
-#include "ObjectMgr.h"
#include "Guild.h"
+#include "ScriptMgr.h"
#include "Chat.h"
-#include "SocialMgr.h"
-#include "Util.h"
-#include "Language.h"
-#include "World.h"
#include "Config.h"
-#include "ScriptMgr.h"
+#include "SocialMgr.h"
+#include "Log.h"
-Guild::Guild()
+#define MAX_GUILD_BANK_TAB_TEXT_LEN 500
+#define EMBLEM_PRICE 10 * GOLD
+
+inline void _CharacterExecutePreparedStatement(SQLTransaction& trans, PreparedStatement* stmt)
{
- m_Id = 0;
- m_Name = "";
- m_LeaderGuid = 0;
- GINFO = MOTD = "";
- m_EmblemStyle = 0;
- m_EmblemColor = 0;
- m_BorderStyle = 0;
- m_BorderColor = 0;
- m_BackgroundColor = 0;
- m_accountsNumber = 0;
+ if (trans.null())
+ CharacterDatabase.Execute(stmt);
+ else
+ trans->Append(stmt);
+}
- m_CreatedDate = time(0);
+inline uint32 _GetGuildBankTabPrice(uint8 tabId)
+{
+ switch (tabId)
+ {
+ 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;
+ }
+}
- m_GuildBankMoney = 0;
+void Guild::SendCommandResult(WorldSession* session, GuildCommandType type, GuildCommandError errCode, const std::string& param)
+{
+ WorldPacket data(SMSG_GUILD_COMMAND_RESULT, 8 + param.size() + 1);
+ data << uint32(type);
+ data << param;
+ data << uint32(errCode);
+ session->SendPacket(&data);
- m_GuildEventLogNextGuid = 0;
- m_GuildBankEventLogNextGuid_Money = 0;
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_COMMAND_RESULT)");
+}
- for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- m_GuildBankEventLogNextGuid_Item[i] = 0;
+void Guild::SendSaveEmblemResult(WorldSession* session, GuildEmblemError errCode)
+{
+ WorldPacket data(MSG_SAVE_GUILD_EMBLEM, 4);
+ data << uint32(errCode);
+ session->SendPacket(&data);
+
+ sLog.outDebug("WORLD: Sent (MSG_SAVE_GUILD_EMBLEM)");
}
-Guild::~Guild()
+///////////////////////////////////////////////////////////////////////////////
+// LogHolder
+Guild::LogHolder::~LogHolder()
{
- SQLTransaction temp = SQLTransaction(NULL);
- DeleteGuildBankItems(temp);
+ // Cleanup
+ for (GuildLog::iterator itr = m_log.begin(); itr != m_log.end(); ++itr)
+ delete (*itr);
}
-bool Guild::Create(Player* leader, std::string gname)
+// Adds event loaded from database to collection
+inline void Guild::LogHolder::LoadEvent(LogEntry* entry)
{
- if (sObjectMgr.GetGuildByName(gname))
- return false;
+ if (m_nextGUID == GUILD_EVENT_LOG_GUID_UNDEFINED)
+ m_nextGUID = entry->GetGUID();
+ m_log.push_front(entry);
+}
- WorldSession* lSession = leader->GetSession();
- if (!lSession)
- return false;
+// Adds new event happened in game.
+// If maximum number of events is reached, oldest event is removed from collection.
+inline void Guild::LogHolder::AddEvent(SQLTransaction& trans, LogEntry* entry)
+{
+ // Check max records limit
+ if (m_log.size() >= m_maxRecords)
+ {
+ LogEntry* oldEntry = m_log.front();
+ delete oldEntry;
+ m_log.pop_front();
+ }
+ // Add event to list
+ m_log.push_back(entry);
+ // Save to DB
+ entry->SaveToDB(trans);
+}
- m_LeaderGuid = leader->GetGUID();
- m_Name = gname;
- GINFO = "";
- MOTD = "No message set.";
- m_GuildBankMoney = 0;
- m_Id = sObjectMgr.GenerateGuildId();
+// Writes information about all events into packet.
+inline void Guild::LogHolder::WritePacket(WorldPacket& data) const
+{
+ data << uint8(m_log.size());
+ for (GuildLog::const_iterator itr = m_log.begin(); itr != m_log.end(); ++itr)
+ (*itr)->WritePacket(data);
+}
- sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(m_LeaderGuid));
+inline uint32 Guild::LogHolder::GetNextGUID()
+{
+ // Next guid was not initialized. It means there are no records for this holder in DB yet.
+ // Start from the beginning.
+ if (m_nextGUID == GUILD_EVENT_LOG_GUID_UNDEFINED)
+ m_nextGUID = 0;
+ else
+ m_nextGUID = (m_nextGUID + 1) % m_maxRecords;
+ return m_nextGUID;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// EventLogEntry
+void Guild::EventLogEntry::SaveToDB(SQLTransaction& trans) const
+{
+ PreparedStatement* stmt = NULL;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_EVENTLOG);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt32(1, m_guid);
+ _CharacterExecutePreparedStatement(trans, stmt);
+
+ uint8 index = 0;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD_EVENTLOG);
+ stmt->setUInt32( index, m_guildId);
+ stmt->setUInt32(++index, m_guid);
+ stmt->setUInt8 (++index, uint8(m_eventType));
+ stmt->setUInt32(++index, m_playerGuid1);
+ stmt->setUInt32(++index, m_playerGuid2);
+ stmt->setUInt8 (++index, m_newRank);
+ stmt->setUInt64(++index, m_timestamp);
+ _CharacterExecutePreparedStatement(trans, stmt);
+}
+
+void Guild::EventLogEntry::WritePacket(WorldPacket& data) const
+{
+ // Event type
+ data << uint8(m_eventType);
+ // Player 1
+ data << uint64(MAKE_NEW_GUID(m_playerGuid1, 0, HIGHGUID_PLAYER));
+ // Player 2 not for left/join guild events
+ if (m_eventType != GUILD_EVENT_LOG_JOIN_GUILD && m_eventType != GUILD_EVENT_LOG_LEAVE_GUILD)
+ data << uint64(MAKE_NEW_GUID(m_playerGuid2, 0, HIGHGUID_PLAYER));
+ // New Rank - only for promote/demote guild events
+ if (m_eventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || m_eventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
+ data << uint8(m_newRank);
+ // Event timestamp
+ data << uint32(::time(NULL) - m_timestamp);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BankEventLogEntry
+void Guild::BankEventLogEntry::SaveToDB(SQLTransaction& trans) const
+{
+ PreparedStatement* stmt = NULL;
+ uint8 index = 0;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_EVENTLOG);
+ stmt->setUInt32( index, m_guildId);
+ stmt->setUInt32(++index, m_guid);
+ stmt->setUInt8 (++index, m_bankTabId);
+ _CharacterExecutePreparedStatement(trans, stmt);
+
+ index = 0;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD_BANK_EVENTLOG);
+ stmt->setUInt32( index, m_guildId);
+ stmt->setUInt32(++index, m_guid);
+ stmt->setUInt8 (++index, m_bankTabId);
+ stmt->setUInt8 (++index, uint8(m_eventType));
+ stmt->setUInt32(++index, m_playerGuid);
+ stmt->setUInt32(++index, m_itemOrMoney);
+ stmt->setUInt16(++index, m_itemStackCount);
+ stmt->setUInt8 (++index, m_destTabId);
+ stmt->setUInt64(++index, m_timestamp);
+ _CharacterExecutePreparedStatement(trans, stmt);
+}
+
+void Guild::BankEventLogEntry::WritePacket(WorldPacket& data) const
+{
+ data << uint8(m_eventType);
+ data << uint64(MAKE_NEW_GUID(m_playerGuid, 0, HIGHGUID_PLAYER));
+ data << uint32(m_itemOrMoney);
+ if (!IsMoneyEvent(m_eventType))
+ {
+ data << uint32(m_itemStackCount);
+ if (m_eventType == GUILD_BANK_LOG_MOVE_ITEM || m_eventType == GUILD_BANK_LOG_MOVE_ITEM2)
+ data << uint8(m_destTabId);
+ }
+ data << uint32(::time(NULL) - m_timestamp);
+}
- // gname already assigned to Guild::name, use it to encode string for DB
- CharacterDatabase.escape_string(gname);
+///////////////////////////////////////////////////////////////////////////////
+// RankInfo
+bool Guild::RankInfo::LoadFromDB(Field* fields)
+{
+ m_rankId = fields[1].GetUInt8();
+ m_name = fields[2].GetString();
+ m_rights = fields[3].GetUInt32();
+ m_bankMoneyPerDay = fields[4].GetUInt32();
+ if (m_rankId == GR_GUILDMASTER) // Prevent loss of leader rights
+ m_rights |= GR_RIGHT_ALL;
+ return true;
+}
- std::string dbGINFO = GINFO;
- std::string dbMOTD = MOTD;
- CharacterDatabase.escape_string(dbGINFO);
- CharacterDatabase.escape_string(dbMOTD);
+void Guild::RankInfo::SaveToDB(SQLTransaction& trans) const
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD_RANK);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt8 (1, m_rankId);
+ stmt->setString(2, m_name);
+ stmt->setUInt32(3, m_rights);
+ _CharacterExecutePreparedStatement(trans, stmt);
+}
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- // CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid='%u'", Id); - MAX(guildid)+1 not exist
- trans->PAppend("DELETE FROM guild_member WHERE guildid='%u'", m_Id);
- trans->PAppend("INSERT INTO guild (guildid,name,leaderguid,info,motd,createdate,EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor,BankMoney) "
- "VALUES('%u','%s','%u', '%s', '%s', UNIX_TIMESTAMP(NOW()),'%u','%u','%u','%u','%u','" UI64FMTD "')",
- m_Id, gname.c_str(), GUID_LOPART(m_LeaderGuid), dbGINFO.c_str(), dbMOTD.c_str(), m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_BackgroundColor, m_GuildBankMoney);
- CharacterDatabase.CommitTransaction(trans);
+void Guild::RankInfo::WritePacket(WorldPacket& data) const
+{
+ data << uint32(m_rights);
+ data << uint32(m_bankMoneyPerDay); // In game set in gold, in packet set in bronze.
+ for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
+ {
+ data << uint32(m_bankTabRightsAndSlots[i].rights);
+ data << uint32(m_bankTabRightsAndSlots[i].slots);
+ }
+}
- CreateDefaultGuildRanks(lSession->GetSessionDbLocaleIndex());
+void Guild::RankInfo::SetName(const std::string& name)
+{
+ if (m_name == name)
+ return;
- return AddMember(m_LeaderGuid, (uint32)GR_GUILDMASTER);
+ m_name = name;
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_RANK_NAME);
+ stmt->setString(0, m_name);
+ stmt->setUInt8 (1, m_rankId);
+ stmt->setUInt32(2, m_guildId);
+ CharacterDatabase.Execute(stmt);
}
-void Guild::CreateDefaultGuildRanks(LocaleConstant locale_idx)
+void Guild::RankInfo::SetRights(uint32 rights)
{
- CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", m_Id);
- CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", m_Id);
+ if (m_rankId == GR_GUILDMASTER) // Prevent loss of leader rights
+ rights = GR_RIGHT_ALL;
+
+ if (m_rights == rights)
+ return;
+
+ m_rights = rights;
- CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_MASTER, locale_idx), GR_RIGHT_ALL);
- CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_OFFICER, locale_idx), GR_RIGHT_ALL);
- CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_VETERAN, locale_idx), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
- CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_MEMBER, locale_idx), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
- CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_INITIATE, locale_idx), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_RANK_RIGHTS);
+ stmt->setUInt32(0, m_rights);
+ stmt->setUInt8 (1, m_rankId);
+ stmt->setUInt32(2, m_guildId);
+ CharacterDatabase.Execute(stmt);
}
-bool Guild::AddMember(uint64 plGuid, uint32 plRank)
+void Guild::RankInfo::SetBankMoneyPerDay(uint32 money)
{
- Player* pl = sObjectMgr.GetPlayer(plGuid);
- if (pl)
+ if (m_rankId == GR_GUILDMASTER) // Prevent loss of leader rights
+ money = GUILD_WITHDRAW_MONEY_UNLIMITED;
+
+ if (m_bankMoneyPerDay == money)
+ return;
+
+ m_bankMoneyPerDay = money;
+
+ PreparedStatement* stmt = NULL;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_RANK_BANK_MONEY);
+ stmt->setUInt32(0, money);
+ stmt->setUInt8 (1, m_rankId);
+ stmt->setUInt32(2, m_guildId);
+ CharacterDatabase.Execute(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_RESET_GUILD_RANK_BANK_RESET_TIME);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt8 (1, m_rankId);
+ CharacterDatabase.Execute(stmt);
+}
+
+void Guild::RankInfo::SetBankTabSlotsAndRights(uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB)
+{
+ if (m_rankId == GR_GUILDMASTER) // Prevent loss of leader rights
+ rightsAndSlots.SetGuildMasterValues();
+
+ if (m_bankTabRightsAndSlots[tabId].IsEqual(rightsAndSlots))
+ return;
+
+ m_bankTabRightsAndSlots[tabId] = rightsAndSlots;
+
+ if (saveToDB)
{
- if (pl->GetGuildId() != 0)
- return false;
+ PreparedStatement* stmt = NULL;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHT);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt8 (1, tabId);
+ stmt->setUInt8 (2, m_rankId);
+ CharacterDatabase.Execute(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD_BANK_RIGHT);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt8 (1, tabId);
+ stmt->setUInt8 (2, m_rankId);
+ stmt->setUInt8 (3, m_bankTabRightsAndSlots[tabId].rights);
+ stmt->setUInt32(4, m_bankTabRightsAndSlots[tabId].slots);
+ CharacterDatabase.Execute(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_RESET_GUILD_RANK_BANK_TIME0 + tabId);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt8 (1, m_rankId);
+ CharacterDatabase.Execute(stmt);
}
- else
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BankTab
+bool Guild::BankTab::LoadFromDB(Field* fields)
+{
+ m_name = fields[2].GetString();
+ m_icon = fields[3].GetString();
+ m_text = fields[4].GetString();
+ return true;
+}
+
+bool Guild::BankTab::LoadItemFromDB(Field* fields)
+{
+ uint8 slotId = fields[13].GetUInt8();
+ uint32 itemGuid = fields[14].GetUInt32();
+ uint32 itemEntry = fields[15].GetUInt32();
+ if (slotId >= GUILD_BANK_MAX_SLOTS)
{
- if (Player::GetGuildIdFromDB(plGuid) != 0) // player already in guild
- return false;
+ sLog.outError("Invalid slot for item (GUID: %u, id: %u) in guild bank, skipped.", itemGuid, itemEntry);
+ return false;
}
- sScriptMgr.OnGuildAddMember(this, pl, plRank);
+ ItemPrototype const* proto = sObjectMgr.GetItemPrototype(itemEntry);
+ if (!proto)
+ {
+ sLog.outError("Unknown item (GUID: %u, id: %u) in guild bank, skipped.", itemGuid, itemEntry);
+ return false;
+ }
- // remove all player signs from another petitions
- // this will be prevent attempt joining player to many guilds and corrupt guild data integrity
- Player::RemovePetitionsAndSigns(plGuid, 9);
+ Item *pItem = NewItemOrBag(proto);
+ if (!pItem->LoadFromDB(itemGuid, 0, fields, itemEntry))
+ {
+ sLog.outError("Item (GUID %u, id: %u) not found in item_instance, deleting from guild bank!", itemGuid, itemEntry);
- // fill player data
- MemberSlot newmember;
+ PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt8 (1, m_tabId);
+ stmt->setUInt8 (2, slotId);
+ CharacterDatabase.Execute(stmt);
- if (pl)
- {
- newmember.accountId = pl->GetSession()->GetAccountId();
- newmember.Name = pl->GetName();
- newmember.ZoneId = pl->GetZoneId();
- newmember.Level = pl->getLevel();
- newmember.Class = pl->getClass();
+ delete pItem;
+ return false;
}
- else
- {
- QueryResult result = CharacterDatabase.PQuery("SELECT name,zone,level,class,account FROM characters WHERE guid = '%u'", GUID_LOPART(plGuid));
- if (!result)
- return false; // player doesn't exist
- Field *fields = result->Fetch();
- newmember.Name = fields[0].GetString();
- newmember.ZoneId = fields[1].GetUInt32();
- newmember.Level = fields[2].GetUInt8();
- newmember.Class = fields[3].GetUInt8();
- newmember.accountId = fields[4].GetInt32();
+ pItem->AddToWorld();
+ m_items[slotId] = pItem;
+ return true;
+}
- if (newmember.Level < 1 || //newmember.Level > STRONG_MAX_LEVEL ||
- newmember.Class < CLASS_WARRIOR || newmember.Class >= MAX_CLASSES)
+// Deletes contents of the tab from the world (and from DB if necessary)
+void Guild::BankTab::Delete(SQLTransaction& trans, bool removeItemsFromDB)
+{
+ for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
+ if (Item* pItem = m_items[slotId])
{
- sLog.outError("Player (GUID: %u) has a broken data in field `characters` table, cannot add him to guild.",GUID_LOPART(plGuid));
- return false;
+ pItem->RemoveFromWorld();
+ if (removeItemsFromDB)
+ pItem->DeleteFromDB(trans);
+ delete pItem;
+ pItem = NULL;
}
- }
-
- newmember.RankId = plRank;
- newmember.OFFnote = (std::string)"";
- newmember.Pnote = (std::string)"";
- newmember.LogoutTime = time(NULL);
- newmember.BankResetTimeMoney = 0; // this will force update at first query
- for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- newmember.BankResetTimeTab[i] = 0;
- members[GUID_LOPART(plGuid)] = newmember;
+}
- std::string dbPnote = newmember.Pnote;
- std::string dbOFFnote = newmember.OFFnote;
- CharacterDatabase.escape_string(dbPnote);
- CharacterDatabase.escape_string(dbOFFnote);
+inline void Guild::BankTab::WritePacket(WorldPacket& data) const
+{
+ data << uint8(GUILD_BANK_MAX_SLOTS);
+ for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
+ WriteSlotPacket(data, slotId);
+}
- CharacterDatabase.PExecute("INSERT INTO guild_member (guildid,guid,rank,pnote,offnote) VALUES ('%u', '%u', '%u','%s','%s')",
- m_Id, GUID_LOPART(plGuid), newmember.RankId, dbPnote.c_str(), dbOFFnote.c_str());
+// Writes information about contents of specified slot into packet.
+void Guild::BankTab::WriteSlotPacket(WorldPacket& data, uint8 slotId) const
+{
+ Item *pItem = GetItem(slotId);
+ uint32 itemEntry = pItem ? pItem->GetEntry() : 0;
- // If player not in game data in data field will be loaded from guild tables, no need to update it!!
- if (pl)
+ data << uint8(slotId);
+ data << uint32(itemEntry);
+ if (itemEntry)
{
- pl->SetInGuild(m_Id);
- pl->SetRank(newmember.RankId);
- pl->SetGuildIdInvited(0);
- }
+ data << uint32(0); // 3.3.0 (0x00018020, 0x00018000)
+ data << uint32(pItem->GetItemRandomPropertyId()); // Random item property id
- UpdateAccountsNumber();
+ if (pItem->GetItemRandomPropertyId())
+ data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor
- return true;
+ data << uint32(pItem->GetCount()); // ITEM_FIELD_STACK_COUNT
+ data << uint32(0);
+ data << uint8(abs(pItem->GetSpellCharges())); // Spell charges
+
+ uint8 enchCount = 0;
+ size_t enchCountPos = data.wpos();
+
+ data << uint8(enchCount); // Number of enchantments
+ for (uint32 i = PERM_ENCHANTMENT_SLOT; i < MAX_ENCHANTMENT_SLOT; ++i)
+ if (uint32 enchId = pItem->GetEnchantmentId(EnchantmentSlot(i)))
+ {
+ data << uint8(i);
+ data << uint32(enchId);
+ ++enchCount;
+ }
+ data.put<uint8>(enchCountPos, enchCount);
+ }
}
-void Guild::SetMOTD(std::string motd)
+void Guild::BankTab::SetInfo(const std::string& name, const std::string& icon)
{
- MOTD = motd;
+ if (m_name == name && m_icon == icon)
+ return;
- sScriptMgr.OnGuildMOTDChanged(this, motd);
+ m_name = name;
+ m_icon = icon;
- // motd now can be used for encoding to DB
- CharacterDatabase.escape_string(motd);
- CharacterDatabase.PExecute("UPDATE guild SET motd='%s' WHERE guildid='%u'", motd.c_str(), m_Id);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_BANK_TAB_INFO);
+ stmt->setString(0, m_name);
+ stmt->setString(1, m_icon);
+ stmt->setUInt32(2, m_guildId);
+ stmt->setUInt8 (3, m_tabId);
+ CharacterDatabase.Execute(stmt);
}
-void Guild::SetGINFO(std::string ginfo)
+void Guild::BankTab::SetText(const std::string& text)
{
- GINFO = ginfo;
+ if (m_text == text)
+ return;
- sScriptMgr.OnGuildInfoChanged(this, ginfo);
+ m_text = text;
+ utf8truncate(m_text, MAX_GUILD_BANK_TAB_TEXT_LEN); // DB and client size limitation
- // ginfo now can be used for encoding to DB
- CharacterDatabase.escape_string(ginfo);
- CharacterDatabase.PExecute("UPDATE guild SET info='%s' WHERE guildid='%u'", ginfo.c_str(), m_Id);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_BANK_TAB_TEXT);
+ stmt->setString(0, m_text);
+ stmt->setUInt32(1, m_guildId);
+ stmt->setUInt8 (2, m_tabId);
+ CharacterDatabase.Execute(stmt);
}
-bool Guild::LoadGuildFromDB(QueryResult guildDataResult)
+// Sets/removes contents of specified slot.
+// If pItem == NULL contents are removed.
+bool Guild::BankTab::SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem)
{
- if (!guildDataResult)
+ if (slotId >= GUILD_BANK_MAX_SLOTS)
return false;
- Field *fields = guildDataResult->Fetch();
-
- m_Id = fields[0].GetUInt32();
- m_Name = fields[1].GetString();
- m_LeaderGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
- m_EmblemStyle = fields[3].GetUInt32();
- m_EmblemColor = fields[4].GetUInt32();
- m_BorderStyle = fields[5].GetUInt32();
- m_BorderColor = fields[6].GetUInt32();
- m_BackgroundColor = fields[7].GetUInt32();
- GINFO = fields[8].GetString();
- MOTD = fields[9].GetString();
- m_CreatedDate = fields[10].GetUInt64();
- m_GuildBankMoney = fields[11].GetUInt64();
-
- uint32 purchasedTabs = fields[12].GetUInt32();
- if (purchasedTabs > GUILD_BANK_MAX_TABS)
- purchasedTabs = GUILD_BANK_MAX_TABS;
+ m_items[slotId] = pItem;
- m_TabListMap.resize(purchasedTabs);
- for (uint8 i = 0; i < purchasedTabs; ++i)
- m_TabListMap[i] = new GuildBankTab();
+ PreparedStatement* stmt = NULL;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_ITEM);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt8 (1, m_tabId);
+ stmt->setUInt8 (2, slotId);
+ _CharacterExecutePreparedStatement(trans, stmt);
+
+ if (pItem)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD_BANK_ITEM);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt8 (1, m_tabId);
+ stmt->setUInt8 (2, slotId);
+ stmt->setUInt32(3, pItem->GetGUIDLow());
+ stmt->setUInt32(4, pItem->GetEntry());
+ _CharacterExecutePreparedStatement(trans, stmt);
+
+ pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, 0);
+ pItem->SetUInt64Value(ITEM_FIELD_OWNER, 0);
+ pItem->FSetState(ITEM_NEW);
+ pItem->SaveToDB(trans); // Not in inventory and can be saved standalone
+ }
return true;
}
-bool Guild::CheckGuildStructure()
+void Guild::BankTab::SendText(const Guild* pGuild, WorldSession* session) const
{
- // Repair the structure of guild
- // If the guildmaster doesn't exist or isn't the member of guild
- // attempt to promote another member
- int32 GM_rights = GetRank(GUID_LOPART(m_LeaderGuid));
- if (GM_rights == -1)
- {
- DelMember(m_LeaderGuid);
- // check no members case (disbanded)
- if (members.empty())
- return false;
- }
- else if (GM_rights != GR_GUILDMASTER)
- SetLeader(m_LeaderGuid);
+ WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1 + m_text.size() + 1);
+ data << uint8(m_tabId);
+ data << m_text;
- // Check config if multiple guildmasters are allowed
- if (sConfig.GetBoolDefault("Guild.AllowMultipleGuildMaster", 0) == 0)
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
- if (itr->second.RankId == GR_GUILDMASTER && GUID_LOPART(m_LeaderGuid) != itr->first) // Allow only 1 guildmaster
- ChangeRank(itr->first, GR_OFFICER); // set right of member to officer
+ if (session)
+ session->SendPacket(&data);
+ else
+ pGuild->BroadcastPacket(&data);
+}
- return true;
+///////////////////////////////////////////////////////////////////////////////
+// Member
+void Guild::Member::SetStats(Player* player)
+{
+ m_name = player->GetName();
+ m_level = player->getLevel();
+ m_class = player->getClass();
+ m_zoneId = player->GetZoneId();
+ m_accountId = player->GetSession()->GetAccountId();
}
-bool Guild::LoadRanksFromDB(QueryResult guildRanksResult)
+void Guild::Member::SetStats(const std::string& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId)
{
- if (!guildRanksResult)
- {
- sLog.outError("Guild %u has broken `guild_rank` data, creating new...",m_Id);
- CreateDefaultGuildRanks(DEFAULT_LOCALE);
- return true;
- }
+ m_name = name;
+ m_level = level;
+ m_class = _class;
+ m_zoneId = zoneId;
+ m_accountId = accountId;
+}
- Field *fields;
- bool broken_ranks = false;
+void Guild::Member::SetPublicNote(const std::string& publicNote)
+{
+ if (m_publicNote == publicNote)
+ return;
- //GUILD RANKS are sequence starting from 0 = GUILD_MASTER (ALL PRIVILEGES) to max 9 (lowest privileges)
- //the lower rank id is considered higher rank - so promotion does rank-- and demotion does rank++
- //between ranks in sequence cannot be gaps - so 0,1,2,4 cannot be
- //min ranks count is 5 and max is 10.
+ m_publicNote = publicNote;
- do
- {
- fields = guildRanksResult->Fetch();
- //condition that would be true when all ranks in QueryResult will be processed and guild without ranks is being processed
- if (!fields)
- break;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_MEMBER_PNOTE);
+ stmt->setString(0, publicNote);
+ stmt->setUInt32(1, GUID_LOPART(m_guid));
+ CharacterDatabase.Execute(stmt);
+}
- uint32 guildId = fields[0].GetUInt32();
- if (guildId < m_Id)
- {
- //there is in table guild_rank record which doesn't have guildid in guild table, report error
- sLog.outErrorDb("Guild %u does not exist but it has a record in guild_rank table, deleting it!", guildId);
- CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid = '%u'", guildId);
- continue;
- }
+void Guild::Member::SetOfficerNote(const std::string& officerNote)
+{
+ if (m_officerNote == officerNote)
+ return;
- if (guildId > m_Id)
- //we loaded all ranks for this guild already, break cycle
- break;
- uint32 rankID = fields[1].GetUInt32();
- std::string rankName = fields[2].GetString();
- uint32 rankRights = fields[3].GetUInt32();
- uint32 rankMoney = fields[4].GetUInt32();
+ m_officerNote = officerNote;
- if (rankID != m_Ranks.size()) // guild_rank.ids are sequence 0,1,2,3..
- broken_ranks = true;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_MEMBER_OFFNOTE);
+ stmt->setString(0, officerNote);
+ stmt->setUInt32(1, GUID_LOPART(m_guid));
+ CharacterDatabase.Execute(stmt);
+}
+
+void Guild::Member::ChangeRank(uint8 newRank)
+{
+ m_rankId = newRank;
- //first rank is guildmaster, prevent loss leader rights
- if (m_Ranks.empty())
- rankRights |= GR_RIGHT_ALL;
+ // Update rank information in player's field, if he is online.
+ if (Player *player = FindPlayer())
+ player->SetRank(newRank);
- AddRank(rankName,rankRights,rankMoney);
- }while (guildRanksResult->NextRow());
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_MEMBER_RANK);
+ stmt->setUInt8 (0, newRank);
+ stmt->setUInt32(1, GUID_LOPART(m_guid));
+ CharacterDatabase.Execute(stmt);
+}
+
+void Guild::Member::SaveToDB(SQLTransaction& trans) const
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD_MEMBER);
+ stmt->setUInt32(0, m_guildId);
+ stmt->setUInt32(1, GUID_LOPART(m_guid));
+ stmt->setUInt8 (2, m_rankId);
+ stmt->setString(3, m_publicNote);
+ stmt->setString(4, m_officerNote);
+ _CharacterExecutePreparedStatement(trans, stmt);
+}
- if (m_Ranks.size() < GUILD_RANKS_MIN_COUNT) // if too few ranks, renew them
+// Loads member's data from database.
+// If member has broken fields (level, class) returns false.
+// In this case member has to be removed from guild.
+bool Guild::Member::LoadFromDB(Field* fields)
+{
+ m_publicNote = fields[3].GetString();
+ m_officerNote = fields[4].GetString();
+ m_bankRemaining[GUILD_BANK_MAX_TABS].resetTime = fields[5].GetUInt32();
+ m_bankRemaining[GUILD_BANK_MAX_TABS].value = fields[6].GetUInt32();
+ for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{
- m_Ranks.clear();
- sLog.outError("Guild %u has broken `guild_rank` data, creating new...", m_Id);
- CreateDefaultGuildRanks(DEFAULT_LOCALE);
- broken_ranks = false;
+ m_bankRemaining[i].resetTime = fields[7 + i * 2].GetUInt32();
+ m_bankRemaining[i].value = fields[8 + i * 2].GetUInt32();
}
- // guild_rank have wrong numbered ranks, repair
- if (broken_ranks)
+
+ SetStats(fields[19].GetString(),
+ fields[20].GetUInt8(),
+ fields[21].GetUInt8(),
+ fields[22].GetUInt32(),
+ fields[23].GetUInt32());
+ m_logoutTime = fields[24].GetUInt64();
+
+ if (!CheckStats())
+ return false;
+
+ if (!m_zoneId)
{
- sLog.outError("Guild %u has broken `guild_rank` data, repairing...", m_Id);
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- trans->PAppend("DELETE FROM guild_rank WHERE guildid='%u'", m_Id);
- for (size_t i = 0; i < m_Ranks.size(); ++i)
- {
- std::string name = m_Ranks[i].Name;
- uint32 rights = m_Ranks[i].Rights;
- CharacterDatabase.escape_string(name);
- trans->PAppend("INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id, uint32(i), name.c_str(), rights);
- }
- CharacterDatabase.CommitTransaction(trans);
+ sLog.outError("Player (GUID: %u) has broken zone-data", GUID_LOPART(m_guid));
+ m_zoneId = Player::GetZoneIdFromDB(m_guid);
}
-
return true;
}
-bool Guild::LoadMembersFromDB(QueryResult guildMembersResult)
+// Validate player fields. Returns false if corrupted fields are found.
+bool Guild::Member::CheckStats() const
{
- if (!guildMembersResult)
+ if (m_level < 1)
+ {
+ sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`level`, deleting him from guild!", GUID_LOPART(m_guid));
return false;
-
- UpdateAccountsNumber();
-
- do
+ }
+ if (m_class < CLASS_WARRIOR || m_class >= MAX_CLASSES)
{
- Field *fields = guildMembersResult->Fetch();
- //this condition will be true when all rows in QueryResult are processed and new guild without members is going to be loaded - prevent crash
- if (!fields)
- break;
+ sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`, deleting him from guild!", GUID_LOPART(m_guid));
+ return false;
+ }
+ return true;
+}
- uint32 guildId = fields[0].GetUInt32();
- if (guildId < m_Id)
- {
- //there is in table guild_member record which doesn't have guildid in guild table, report error
- sLog.outErrorDb("Guild %u does not exist but it has a record in guild_member table, deleting it!", guildId);
- CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guildid = '%u'", guildId);
- continue;
- }
+void Guild::Member::WritePacket(WorldPacket& data) const
+{
+ if (Player* player = FindPlayer())
+ {
+ data << uint64(player->GetGUID());
+ data << uint8(1);
+ data << player->GetName();
+ data << uint32(m_rankId);
+ data << uint8(player->getLevel());
+ data << uint8(player->getClass());
+ data << uint8(0); // new 2.4.0
+ data << uint32(player->GetZoneId());
+ }
+ else
+ {
+ data << m_guid;
+ data << uint8(0);
+ data << m_name;
+ data << uint32(m_rankId);
+ data << uint8(m_level);
+ data << uint8(m_class);
+ data << uint8(0); // new 2.4.0
+ data << uint32(m_zoneId);
+ data << float(float(::time(NULL) - m_logoutTime) / DAY);
+ }
+ data << m_publicNote;
+ data << m_officerNote;
+}
- if (guildId > m_Id)
- //we loaded all members for this guild already, break cycle
- break;
-
- MemberSlot newmember;
- uint64 guid = MAKE_NEW_GUID(fields[1].GetUInt32(), 0, HIGHGUID_PLAYER);
- newmember.RankId = fields[2].GetUInt32();
- //don't allow member to have not existing rank!
- if (newmember.RankId >= m_Ranks.size())
- newmember.RankId = GetLowestRank();
-
- newmember.Pnote = fields[3].GetString();
- newmember.OFFnote = fields[4].GetString();
- newmember.BankResetTimeMoney = fields[5].GetUInt32();
- newmember.BankRemMoney = fields[6].GetUInt32();
- for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- {
- newmember.BankResetTimeTab[i] = fields[7+(2*i)].GetUInt32();
- newmember.BankRemSlotsTab[i] = fields[8+(2*i)].GetUInt32();
- }
+// Decreases amount of money/slots left for today.
+// If (tabId == GUILD_BANK_MAX_TABS) decrease money amount.
+// Otherwise decrease remaining items amount for specified tab.
+void Guild::Member::DecreaseBankRemainingValue(SQLTransaction& trans, uint8 tabId, uint32 amount)
+{
+ m_bankRemaining[tabId].value -= amount;
- newmember.Name = fields[19].GetString();
- newmember.Level = fields[20].GetUInt8();
- newmember.Class = fields[21].GetUInt8();
- newmember.ZoneId = fields[22].GetUInt32();
- newmember.LogoutTime = fields[23].GetUInt64();
- newmember.accountId = fields[24].GetInt32();
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(
+ tabId == GUILD_BANK_MAX_TABS ?
+ CHAR_SET_GUILD_MEMBER_BANK_REM_MONEY :
+ CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS0 + tabId);
+ stmt->setUInt32(0, m_bankRemaining[tabId].value);
+ stmt->setUInt32(1, m_guildId);
+ stmt->setUInt32(2, GUID_LOPART(m_guid));
+ _CharacterExecutePreparedStatement(trans, stmt);
+}
- //this code will remove unexisting character guids from guild
- if (newmember.Level < 1 /*|| newmember.Level > STRONG_MAX_LEVEL*/) // can be at broken `data` field
- {
- sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`, deleting him from guild!",GUID_LOPART(guid));
- CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid));
- continue;
- }
- if (!newmember.ZoneId)
- {
- sLog.outError("Player (GUID: %u) has broken zone-data", GUID_LOPART(guid));
- // here it will also try the same, to get the zone from characters-table, but additional it tries to find
- // the zone through xy coords .. this is a bit redundant, but shouldn't be called often
- newmember.ZoneId = Player::GetZoneIdFromDB(guid);
- }
- if (newmember.Class < CLASS_WARRIOR || newmember.Class >= MAX_CLASSES) // can be at broken `class` field
- {
- sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`, deleting him from guild!",GUID_LOPART(guid));
- CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid));
- continue;
- }
+// Get amount of money/slots left for today.
+// If (tabId == GUILD_BANK_MAX_TABS) return money amount.
+// Otherwise return remaining items amount for specified tab.
+// If reset time was more than 24 hours ago, renew reset time and reset amount to maximum value.
+uint32 Guild::Member::GetBankRemainingValue(uint8 tabId, const Guild* pGuild) const
+{
+ // Guild master has unlimited amount.
+ if (IsRank(GR_GUILDMASTER))
+ return tabId == GUILD_BANK_MAX_TABS ? GUILD_WITHDRAW_MONEY_UNLIMITED : GUILD_WITHDRAW_SLOT_UNLIMITED;
- members[GUID_LOPART(guid)] = newmember;
+ // Check rights for non-money tab.
+ if (tabId != GUILD_BANK_MAX_TABS)
+ if ((pGuild->_GetRankBankTabRights(m_rankId, tabId) & GUILD_BANK_RIGHT_VIEW_TAB) != GUILD_BANK_RIGHT_VIEW_TAB)
+ return 0;
- }while (guildMembersResult->NextRow());
+ uint32 curTime = uint32(::time(NULL) / MINUTE); // minutes
+ if (curTime > m_bankRemaining[tabId].resetTime + 24 * HOUR / MINUTE)
+ {
+ RemainingValue& rv = const_cast <RemainingValue&> (m_bankRemaining[tabId]);
+ rv.resetTime = curTime;
+ rv.value = tabId == GUILD_BANK_MAX_TABS ?
+ pGuild->_GetRankBankMoneyPerDay(m_rankId) :
+ pGuild->_GetRankBankTabSlotsPerDay(m_rankId, tabId);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(
+ tabId == GUILD_BANK_MAX_TABS ?
+ CHAR_SET_GUILD_MEMBER_BANK_REM_MONEY :
+ CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS0 + tabId);
+ stmt->setUInt32(0, m_bankRemaining[tabId].resetTime);
+ stmt->setUInt32(1, m_bankRemaining[tabId].value);
+ stmt->setUInt32(2, m_guildId);
+ stmt->setUInt32(3, GUID_LOPART(m_guid));
+ CharacterDatabase.Execute(stmt);
+ }
+ return m_bankRemaining[tabId].value;
+}
- if (members.empty())
- return false;
+inline void Guild::Member::ResetTabTimes()
+{
+ for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
+ m_bankRemaining[tabId].resetTime = 0;
+}
- return true;
+inline void Guild::Member::ResetMoneyTime()
+{
+ m_bankRemaining[GUILD_BANK_MAX_TABS].resetTime = 0;
}
-void Guild::SetMemberStats(uint64 guid)
+///////////////////////////////////////////////////////////////////////////////
+// EmblemInfo
+void EmblemInfo::LoadFromDB(Field* fields)
{
- MemberList::iterator itr = members.find(GUID_LOPART(guid));
- if (itr == members.end())
- return;
+ m_style = fields[3].GetUInt32();
+ m_color = fields[4].GetUInt32();
+ m_borderStyle = fields[5].GetUInt32();
+ m_borderColor = fields[6].GetUInt32();
+ m_backgroundColor = fields[7].GetUInt32();
+}
- Player *pl = ObjectAccessor::FindPlayer(guid);
- if (!pl)
- return;
- itr->second.Name = pl->GetName();
- itr->second.Level = pl->getLevel();
- itr->second.Class = pl->getClass();
- itr->second.ZoneId = pl->GetZoneId();
+void EmblemInfo::WritePacket(WorldPacket& data) const
+{
+ data << uint32(m_style);
+ data << uint32(m_color);
+ data << uint32(m_borderStyle);
+ data << uint32(m_borderColor);
+ data << uint32(m_backgroundColor);
}
-void Guild::SetLeader(uint64 guid)
+void EmblemInfo::SaveToDB(uint32 guildId) const
{
- m_LeaderGuid = guid;
- ChangeRank(guid, GR_GUILDMASTER);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_EMBLEM_INFO);
+ stmt->setUInt32(0, m_style);
+ stmt->setUInt32(1, m_color);
+ stmt->setUInt32(2, m_borderStyle);
+ stmt->setUInt32(3, m_borderColor);
+ stmt->setUInt32(4, m_backgroundColor);
+ stmt->setUInt32(5, guildId);
+ CharacterDatabase.Execute(stmt);
+}
- CharacterDatabase.PExecute("UPDATE guild SET leaderguid='%u' WHERE guildid='%u'", GUID_LOPART(guid), m_Id);
+///////////////////////////////////////////////////////////////////////////////
+// MoveItemData
+bool Guild::MoveItemData::CheckItem(uint32& splitedAmount)
+{
+ ASSERT(m_pItem);
+ if (splitedAmount > m_pItem->GetCount())
+ return false;
+ if (splitedAmount == m_pItem->GetCount())
+ splitedAmount = 0;
+ return true;
}
-void Guild::DelMember(uint64 guid, bool isDisbanding, bool isKicked)
+uint8 Guild::MoveItemData::CanStore(Item* pItem, bool swap, bool sendError)
{
- Player *player = sObjectMgr.GetPlayer(guid);
- sScriptMgr.OnGuildRemoveMember(this, player, isDisbanding, isKicked);
+ m_vec.clear();
+ uint8 msg = _CanStore(pItem, swap);
+ if (sendError && msg != EQUIP_ERR_OK)
+ m_pPlayer->SendEquipError(msg, pItem);
+ return (msg == EQUIP_ERR_OK);
+}
- //guild master can be deleted when loading guild and guid doesn't exist in characters table
- //or when he is removed from guild by gm command
- if (m_LeaderGuid == guid && !isDisbanding)
+bool Guild::MoveItemData::CloneItem(uint32 count)
+{
+ ASSERT(m_pItem);
+ m_pClonedItem = m_pItem->CloneItem(count);
+ if (!m_pClonedItem)
{
- MemberSlot* oldLeader = NULL;
- MemberSlot* best = NULL;
- uint64 newLeaderGUID = 0;
- for (Guild::MemberList::iterator i = members.begin(); i != members.end(); ++i)
- {
- if (i->first == GUID_LOPART(guid))
- {
- oldLeader = &(i->second);
- continue;
- }
+ m_pPlayer->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, m_pItem);
+ return false;
+ }
+ return true;
+}
- if (!best || best->RankId > i->second.RankId)
- {
- best = &(i->second);
- newLeaderGUID = i->first;
- }
- }
- if (!best)
- {
- Disband();
- return;
- }
+void Guild::MoveItemData::LogAction(MoveItemData* pFrom) const
+{
+ ASSERT(pFrom->GetItem());
- SetLeader(newLeaderGUID);
+ sScriptMgr.OnGuildItemMove(m_pGuild, m_pPlayer, pFrom->GetItem(),
+ pFrom->IsBank(), pFrom->GetContainer(), pFrom->GetSlotId(),
+ IsBank(), GetContainer(), GetSlotId());
+}
- // If player not online data in data field will be loaded from guild tabs no need to update it !!
- if (Player *newLeader = sObjectMgr.GetPlayer(newLeaderGUID))
- newLeader->SetRank(GR_GUILDMASTER);
+inline void Guild::MoveItemData::CopySlots(SlotIds& ids) const
+{
+ for (ItemPosCountVec::const_iterator itr = m_vec.begin(); itr != m_vec.end(); ++itr)
+ ids.insert(uint8(itr->pos));
+}
- // when leader non-exist (at guild load with deleted leader only) not send broadcasts
- if (oldLeader)
+///////////////////////////////////////////////////////////////////////////////
+// PlayerMoveItemData
+bool Guild::PlayerMoveItemData::InitItem()
+{
+ m_pItem = m_pPlayer->GetItemByPos(m_container, m_slotId);
+ if (m_pItem)
+ {
+ // Anti-WPE protection. Do not move non-empty bags to bank.
+ if (m_pItem->IsBag() && !((Bag*)m_pItem)->IsEmpty())
{
- BroadcastEvent(GE_LEADER_CHANGED, 0, 2, oldLeader->Name, best->Name, "");
-
- BroadcastEvent(GE_LEFT, guid, 1, oldLeader->Name, "", "");
+ m_pPlayer->SendEquipError(EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS, m_pItem);
+ m_pItem = NULL;
+ }
+ // Bound items cannot be put into bank.
+ else if (!m_pItem->CanBeTraded())
+ {
+ m_pPlayer->SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, m_pItem);
+ m_pItem = NULL;
}
}
+ return (m_pItem != NULL);
+}
- members.erase(GUID_LOPART(guid));
-
- // If player not online data in data field will be loaded from guild tabs no need to update it !!
- if (player)
+void Guild::PlayerMoveItemData::RemoveItem(SQLTransaction& trans, MoveItemData* /*pOther*/, uint32 splitedAmount)
+{
+ if (splitedAmount)
{
- player->SetInGuild(0);
- player->SetRank(0);
+ m_pItem->SetCount(m_pItem->GetCount() - splitedAmount);
+ m_pItem->SetState(ITEM_CHANGED, m_pPlayer);
+ m_pPlayer->SaveInventoryAndGoldToDB(trans);
+ }
+ else
+ {
+ m_pPlayer->MoveItemFromInventory(m_container, m_slotId, true);
+ m_pItem->DeleteFromInventoryDB(trans);
+ m_pItem = NULL;
}
-
- CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid));
-
- if (!isDisbanding)
- UpdateAccountsNumber();
}
-void Guild::ChangeRank(uint64 guid, uint32 newRank)
+Item* Guild::PlayerMoveItemData::StoreItem(SQLTransaction& trans, Item* pItem)
{
- MemberList::iterator itr = members.find(GUID_LOPART(guid));
- if (itr != members.end())
- itr->second.RankId = newRank;
-
- Player *player = sObjectMgr.GetPlayer(guid);
- // If player not online data in data field will be loaded from guild tabs no need to update it !!
- if (player)
- player->SetRank(newRank);
+ ASSERT(pItem);
+ m_pPlayer->MoveItemToInventory(m_vec, pItem, true);
+ m_pPlayer->SaveInventoryAndGoldToDB(trans);
+ return pItem;
+}
- CharacterDatabase.PExecute("UPDATE guild_member SET rank='%u' WHERE guid='%u'", newRank, GUID_LOPART(guid));
+void Guild::PlayerMoveItemData::LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const
+{
+ ASSERT(pFrom);
+ // Bank -> Char
+ m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUIDLow(),
+ pFrom->GetItem()->GetEntry(), count);
}
-void Guild::SetPNOTE(uint64 guid,std::string pnote)
+inline uint8 Guild::PlayerMoveItemData::_CanStore(Item* pItem, bool swap)
{
- MemberList::iterator itr = members.find(GUID_LOPART(guid));
- if (itr == members.end())
- return;
+ return m_pPlayer->CanStoreItem(m_container, m_slotId, m_vec, pItem, swap);
+}
- itr->second.Pnote = pnote;
+///////////////////////////////////////////////////////////////////////////////
+// BankMoveItemData
+bool Guild::BankMoveItemData::InitItem()
+{
+ m_pItem = m_pGuild->_GetItem(m_container, m_slotId);
+ return (m_pItem != NULL);
+}
- // pnote now can be used for encoding to DB
- CharacterDatabase.escape_string(pnote);
- CharacterDatabase.PExecute("UPDATE guild_member SET pnote = '%s' WHERE guid = '%u'", pnote.c_str(), itr->first);
+bool Guild::BankMoveItemData::HasStoreRights(MoveItemData* pOther) const
+{
+ ASSERT(pOther);
+ // Do not check rights if item is being swapped within the same bank tab
+ if (pOther->IsBank() && pOther->GetContainer() == m_container)
+ return true;
+ return m_pGuild->_MemberHasTabRights(m_pPlayer->GetGUID(), m_container, GUILD_BANK_RIGHT_DEPOSIT_ITEM);
}
-void Guild::SetOFFNOTE(uint64 guid,std::string offnote)
+bool Guild::BankMoveItemData::HasWithdrawRights(MoveItemData* pOther) const
{
- MemberList::iterator itr = members.find(GUID_LOPART(guid));
- if (itr == members.end())
- return;
- itr->second.OFFnote = offnote;
- // offnote now can be used for encoding to DB
- CharacterDatabase.escape_string(offnote);
- CharacterDatabase.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote.c_str(), itr->first);
+ ASSERT(pOther);
+ // Do not check rights if item is being swapped within the same bank tab
+ if (pOther->IsBank() && pOther->GetContainer() == m_container)
+ return true;
+ return (m_pGuild->_GetMemberRemainingSlots(m_pPlayer->GetGUID(), m_container) != 0);
}
-void Guild::BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language)
+void Guild::BankMoveItemData::RemoveItem(SQLTransaction& trans, MoveItemData* pOther, uint32 splitedAmount)
{
- if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_GCHATSPEAK))
+ ASSERT(m_pItem);
+ if (splitedAmount)
{
- WorldPacket data;
- ChatHandler(session).FillMessageData(&data, CHAT_MSG_GUILD, language, 0, msg.c_str());
-
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
- {
- Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
-
- if (pl && pl->GetSession() && HasRankRight(pl->GetRank(),GR_RIGHT_GCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()))
- pl->GetSession()->SendPacket(&data);
- }
+ m_pItem->SetCount(m_pItem->GetCount() - splitedAmount);
+ m_pItem->FSetState(ITEM_CHANGED);
+ m_pItem->SaveToDB(trans);
}
+ else
+ {
+ m_pGuild->_RemoveItem(trans, m_container, m_slotId);
+ m_pItem = NULL;
+ }
+ // Decrease amount of player's remaining items (if item is moved to different tab or to player)
+ if (!pOther->IsBank() || pOther->GetContainer() != m_container)
+ m_pGuild->_DecreaseMemberRemainingSlots(trans, m_pPlayer->GetGUID(), m_container);
}
-void Guild::BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language)
+Item* Guild::BankMoveItemData::StoreItem(SQLTransaction& trans, Item* pItem)
{
- if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(), GR_RIGHT_OFFCHATSPEAK))
- {
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
- {
- WorldPacket data;
- ChatHandler::FillMessageData(&data, session, CHAT_MSG_OFFICER, language, NULL, 0, msg.c_str(), NULL);
+ if (!pItem)
+ return NULL;
+
+ BankTab* pTab = m_pGuild->GetBankTab(m_container);
+ if (!pTab)
+ return NULL;
- Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
+ Item* pLastItem = pItem;
+ for (ItemPosCountVec::const_iterator itr = m_vec.begin(); itr != m_vec.end(); )
+ {
+ ItemPosCount pos(*itr);
+ ++itr;
- if (pl && pl->GetSession() && HasRankRight(pl->GetRank(),GR_RIGHT_OFFCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()))
- pl->GetSession()->SendPacket(&data);
- }
+ sLog.outDebug("GUILD STORAGE: StoreItem tab = %u, slot = %u, item = %u, count = %u",
+ m_container, m_slotId, pItem->GetEntry(), pItem->GetCount());
+ pLastItem = _StoreItem(trans, pTab, pItem, pos, itr != m_vec.end());
}
+ return pLastItem;
}
-void Guild::BroadcastPacket(WorldPacket *packet)
+void Guild::BankMoveItemData::LogBankEvent(SQLTransaction& trans, MoveItemData* pFrom, uint32 count) const
{
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
- {
- Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
- if (player)
- player->GetSession()->SendPacket(packet);
- }
+ ASSERT(pFrom->GetItem());
+ if (pFrom->IsBank())
+ // Bank -> Bank
+ m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, pFrom->GetContainer(), m_pPlayer->GetGUIDLow(),
+ pFrom->GetItem()->GetEntry(), count, m_container);
+ else
+ // Char -> Bank
+ m_pGuild->_LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, m_container, m_pPlayer->GetGUIDLow(),
+ pFrom->GetItem()->GetEntry(), count);
+}
+
+void Guild::BankMoveItemData::LogAction(MoveItemData* pFrom) const
+{
+ MoveItemData::LogAction(pFrom);
+ if (!pFrom->IsBank() && sWorld.getBoolConfig(CONFIG_GM_LOG_TRADE) && m_pPlayer->GetSession()->GetSecurity() > SEC_PLAYER) // TODO: move to scripts
+ sLog.outCommand(m_pPlayer->GetSession()->GetAccountId(),
+ "GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u)",
+ m_pPlayer->GetName(), m_pPlayer->GetSession()->GetAccountId(),
+ pFrom->GetItem()->GetProto()->Name1, pFrom->GetItem()->GetEntry(), pFrom->GetItem()->GetCount(),
+ m_pGuild->GetId());
}
-void Guild::BroadcastPacketToRank(WorldPacket *packet, uint32 rankId)
+Item* Guild::BankMoveItemData::_StoreItem(SQLTransaction& trans, BankTab* pTab, Item *pItem, ItemPosCount& pos, bool clone) const
{
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
+ uint8 slotId = uint8(pos.pos);
+ uint32 count = pos.count;
+ if (Item* pItemDest = pTab->GetItem(slotId))
{
- if (itr->second.RankId == rankId)
+ pItemDest->SetCount(pItemDest->GetCount() + count);
+ pItemDest->FSetState(ITEM_CHANGED);
+ pItemDest->SaveToDB(trans);
+ if (!clone)
{
- Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
- if (player)
- player->GetSession()->SendPacket(packet);
+ pItem->RemoveFromWorld();
+ pItem->DeleteFromDB(trans);
+ delete pItem;
}
+ return pItemDest;
}
-}
-void Guild::CreateRank(std::string name_,uint32 rights)
-{
- if (m_Ranks.size() >= GUILD_RANKS_MAX_COUNT)
- return;
+ if (clone)
+ pItem = pItem->CloneItem(count);
+ else
+ pItem->SetCount(count);
- // ranks are sequence 0,1,2,... where 0 means guildmaster
- uint32 new_rank_id = m_Ranks.size();
+ if (pItem && pTab->SetItem(trans, slotId, pItem))
+ return pItem;
- AddRank(name_, rights, 0);
+ return NULL;
+}
- //existing records in db should be deleted before calling this procedure and m_PurchasedTabs must be loaded already
+// Tries to reserve space for source item.
+// If item in destination slot exists it must be the item of the same entry
+// and stack must have enough space to take at least one item.
+// Returns false if destination item specified and it cannot be used to reserve space.
+bool Guild::BankMoveItemData::_ReserveSpace(uint8 slotId, Item* pItem, Item* pItemDest, uint32& count)
+{
+ uint32 requiredSpace = pItem->GetMaxStackCount();
+ if (pItemDest)
+ {
+ // Make sure source and destination items match and destination item has space for more stacks.
+ if (pItemDest->GetEntry() != pItem->GetEntry() || pItemDest->GetCount() >= pItem->GetMaxStackCount())
+ return false;
+ requiredSpace -= pItemDest->GetCount();
+ }
+ // Let's not be greedy, reserve only required space
+ requiredSpace = std::min(requiredSpace, count);
- for (uint32 i = 0; i < uint32(GetPurchasedTabs()); ++i)
+ // Reserve space
+ ItemPosCount pos(slotId, requiredSpace);
+ if (!pos.isContainedIn(m_vec))
{
- //create bank rights with 0
- CharacterDatabase.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid) VALUES ('%u','%u','%u')", m_Id, i, new_rank_id);
+ m_vec.push_back(pos);
+ count -= requiredSpace;
}
- // name now can be used for encoding to DB
- CharacterDatabase.escape_string(name_);
- CharacterDatabase.PExecute("INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id, new_rank_id, name_.c_str(), rights);
+ return true;
}
-void Guild::AddRank(const std::string& name_,uint32 rights, uint32 money)
+void Guild::BankMoveItemData::_CanStoreItemInTab(Item* pItem, uint8 skipSlotId, bool merge, uint32& count)
{
- m_Ranks.push_back(RankInfo(name_,rights,money));
+ for (uint8 slotId = 0; (slotId < GUILD_BANK_MAX_SLOTS) && (count > 0); ++slotId)
+ {
+ // Skip slot already processed in _CanStore (when destination slot was specified)
+ if (slotId == skipSlotId)
+ continue;
+
+ Item* pItemDest = m_pGuild->_GetItem(m_container, slotId);
+ if (pItemDest == pItem)
+ pItemDest = NULL;
+
+ // If merge skip empty, if not merge skip non-empty
+ if ((pItemDest != NULL) != merge)
+ continue;
+
+ _ReserveSpace(slotId, pItem, pItemDest, count);
+ }
}
-void Guild::DelRank()
+uint8 Guild::BankMoveItemData::_CanStore(Item* pItem, bool swap)
{
- // client won't allow to have less than GUILD_RANKS_MIN_COUNT ranks in guild
- if (m_Ranks.size() <= GUILD_RANKS_MIN_COUNT)
- return;
+ sLog.outDebug("GUILD STORAGE: CanStore() tab = %u, slot = %u, item = %u, count = %u",
+ m_container, m_slotId, pItem->GetEntry(), pItem->GetCount());
+
+ uint32 count = pItem->GetCount();
+ // Soulbound items cannot be moved
+ if (pItem->IsSoulBound())
+ return EQUIP_ERR_CANT_DROP_SOULBOUND;
+
+ // Make sure destination bank tab exists
+ if (m_container >= m_pGuild->_GetPurchasedTabsSize())
+ return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
- // delete lowest guild_rank
- uint32 rank = GetLowestRank();
- CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE rid >= '%u' AND guildid='%u'", rank, m_Id);
+ // Slot explicitely specified. Check it.
+ if (m_slotId != NULL_SLOT)
+ {
+ Item* pItemDest = m_pGuild->_GetItem(m_container, m_slotId);
+ // Ignore swapped item (this slot will be empty after move)
+ if ((pItemDest == pItem) || swap)
+ pItemDest = NULL;
+
+ if (!_ReserveSpace(m_slotId, pItem, pItemDest, count))
+ return EQUIP_ERR_ITEM_CANT_STACK;
- m_Ranks.pop_back();
+ if (count == 0)
+ return EQUIP_ERR_OK;
+ }
+
+ // Slot was not specified or it has not enough space for all the items in stack
+ // Search for stacks to merge with
+ if (pItem->GetMaxStackCount() > 1)
+ {
+ _CanStoreItemInTab(pItem, m_slotId, true, count);
+ if (count == 0)
+ return EQUIP_ERR_OK;
+ }
+
+ // Search free slot for item
+ _CanStoreItemInTab(pItem, m_slotId, false, count);
+ if (count == 0)
+ return EQUIP_ERR_OK;
+
+ return EQUIP_ERR_BANK_FULL;
}
-std::string Guild::GetRankName(uint32 rankId)
+///////////////////////////////////////////////////////////////////////////////
+// Guild
+Guild::Guild() : m_id(0), m_leaderGuid(0), m_createdDate(0), m_accountsNumber(0), m_bankMoney(0), m_eventLog(NULL)
{
- if (rankId >= m_Ranks.size())
- return "<unknown>";
-
- return m_Ranks[rankId].Name;
+ memset(&m_bankEventLog, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(LogHolder*));
}
-uint32 Guild::GetRankRights(uint32 rankId)
+Guild::~Guild()
{
- if (rankId >= m_Ranks.size())
- return 0;
+ SQLTransaction temp(NULL);
+ _DeleteBankItems(temp);
- return m_Ranks[rankId].Rights;
+ // Cleanup
+ if (m_eventLog)
+ delete m_eventLog;
+ for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
+ if (m_bankEventLog[tabId])
+ delete m_bankEventLog[tabId];
+ for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ delete itr->second;
}
-void Guild::SetRankName(uint32 rankId, std::string name_)
+// Creates new guild with default data and saves it to database.
+bool Guild::Create(Player* pLeader, const std::string& name)
{
- if (rankId >= m_Ranks.size())
- return;
+ // Check if guild with such name already exists
+ if (sObjectMgr.GetGuildByName(name))
+ return false;
- m_Ranks[rankId].Name = name_;
+ WorldSession* pLeaderSession = pLeader->GetSession();
+ if (!pLeaderSession)
+ return false;
- // name now can be used for encoding to DB
- CharacterDatabase.escape_string(name_);
- CharacterDatabase.PExecute("UPDATE guild_rank SET rname='%s' WHERE rid='%u' AND guildid='%u'", name_.c_str(), rankId, m_Id);
-}
+ m_id = sObjectMgr.GenerateGuildId();
+ m_leaderGuid = pLeader->GetGUID();
+ m_name = name;
+ m_info = "";
+ m_motd = "No message set.";
+ m_bankMoney = 0;
+ m_createdDate = ::time(NULL);
+ _CreateLogHolders();
-void Guild::SetRankRights(uint32 rankId, uint32 rights)
-{
- if (rankId >= m_Ranks.size())
- return;
+ sLog.outDebug("GUILD: creating guild [%s] for leader %s (%u)",
+ name.c_str(), pLeader->GetName(), GUID_LOPART(m_leaderGuid));
- m_Ranks[rankId].Rights = rights;
+ PreparedStatement* stmt = NULL;
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
- CharacterDatabase.PExecute("UPDATE guild_rank SET rights='%u' WHERE rid='%u' AND guildid='%u'", rights, rankId, m_Id);
-}
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBERS);
+ stmt->setUInt32(0, m_id);
+ trans->Append(stmt);
+
+ uint8 index = 0;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD);
+ stmt->setUInt32( index, m_id);
+ stmt->setString(++index, name);
+ stmt->setUInt32(++index, GUID_LOPART(m_leaderGuid));
+ stmt->setString(++index, m_info);
+ stmt->setString(++index, m_motd);
+ stmt->setUInt64(++index, uint64(m_createdDate));
+ stmt->setUInt32(++index, m_emblemInfo.GetStyle());
+ stmt->setUInt32(++index, m_emblemInfo.GetColor());
+ stmt->setUInt32(++index, m_emblemInfo.GetBorderStyle());
+ stmt->setUInt32(++index, m_emblemInfo.GetBorderColor());
+ stmt->setUInt32(++index, m_emblemInfo.GetBackgroundColor());
+ stmt->setUInt64(++index, m_bankMoney);
+ trans->Append(stmt);
-int32 Guild::GetRank(uint32 LowGuid)
-{
- MemberList::const_iterator itr = members.find(LowGuid);
- if (itr == members.end())
- return -1;
+ CharacterDatabase.CommitTransaction(trans);
+ // Create default ranks
+ _CreateDefaultGuildRanks(pLeaderSession->GetSessionDbLocaleIndex());
+ // Add guildmaster
+ bool ret = AddMember(m_leaderGuid, GR_GUILDMASTER);
+ if (ret)
+ // Call scripts on successful create
+ sScriptMgr.OnGuildCreate(this, pLeader, name);
- return itr->second.RankId;
+ return ret;
}
+// Disbands guild and deletes all related data from database
void Guild::Disband()
{
+ // Call scripts before guild data removed from database
sScriptMgr.OnGuildDisband(this);
- BroadcastEvent(GE_DISBANDED, 0, 0, "", "", "");
- while (!members.empty())
+ _BroadcastEvent(GE_DISBANDED, 0);
+ // Remove all members
+ while (!m_members.empty())
{
- MemberList::const_iterator itr = members.begin();
- DelMember(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER), true);
+ Members::const_iterator itr = m_members.begin();
+ DeleteMember(itr->second->GetGUID(), true);
}
+ PreparedStatement* stmt = NULL;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- trans->PAppend("DELETE FROM guild WHERE guildid = '%u'", m_Id);
- trans->PAppend("DELETE FROM guild_rank WHERE guildid = '%u'", m_Id);
- trans->PAppend("DELETE FROM guild_bank_tab WHERE guildid = '%u'", m_Id);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD);
+ stmt->setUInt32(0, m_id);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_RANKS);
+ stmt->setUInt32(0, m_id);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_TABS);
+ stmt->setUInt32(0, m_id);
+ trans->Append(stmt);
+
+ // Free bank tab used memory and delete items stored in them
+ _DeleteBankItems(trans, true);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_ITEMS);
+ stmt->setUInt32(0, m_id);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHTS);
+ stmt->setUInt32(0, m_id);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_EVENTLOGS);
+ stmt->setUInt32(0, m_id);
+ trans->Append(stmt);
- //Free bank tab used memory and delete items stored in them
- DeleteGuildBankItems(trans, true);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_EVENTLOGS);
+ stmt->setUInt32(0, m_id);
+ trans->Append(stmt);
- trans->PAppend("DELETE FROM guild_bank_item WHERE guildid = '%u'", m_Id);
- trans->PAppend("DELETE FROM guild_bank_right WHERE guildid = '%u'", m_Id);
- trans->PAppend("DELETE FROM guild_bank_eventlog WHERE guildid = '%u'", m_Id);
- trans->PAppend("DELETE FROM guild_eventlog WHERE guildid = '%u'", m_Id);
CharacterDatabase.CommitTransaction(trans);
- sObjectMgr.RemoveGuild(m_Id);
+ sObjectMgr.RemoveGuild(m_id);
}
-void Guild::Roster(WorldSession *session /*= NULL*/)
+///////////////////////////////////////////////////////////////////////////////
+// HANDLE CLIENT COMMANDS
+void Guild::HandleRoster(WorldSession *session /*= NULL*/)
{
- // we can only guess size
- WorldPacket data(SMSG_GUILD_ROSTER, (4+MOTD.length()+1+GINFO.length()+1+4+m_Ranks.size()*(4+4+GUILD_BANK_MAX_TABS*(4+4))+members.size()*50));
- data << (uint32)members.size();
- data << MOTD;
- data << GINFO;
+ // Guess size
+ WorldPacket data(SMSG_GUILD_ROSTER, (4 + m_motd.length() + 1 + m_info.length() + 1 + 4 + _GetRanksSize() * (4 + 4 + GUILD_BANK_MAX_TABS * (4 + 4)) + m_members.size() * 50));
+ data << uint32(m_members.size());
+ data << m_motd;
+ data << m_info;
+
+ data << uint32(_GetRanksSize());
+ for (Ranks::const_iterator ritr = m_ranks.begin(); ritr != m_ranks.end(); ++ritr)
+ ritr->WritePacket(data);
+
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ itr->second->WritePacket(data);
- data << (uint32)m_Ranks.size();
- for (RankList::const_iterator ritr = m_Ranks.begin(); ritr != m_Ranks.end(); ++ritr)
- {
- data << uint32(ritr->Rights);
- data << uint32(ritr->BankMoneyPerDay); // count of: withdraw gold(gold/day) Note: in game set gold, in packet set bronze.
- for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- {
- data << uint32(ritr->TabRight[i]); // for TAB_i rights: view tabs = 0x01, deposit items =0x02
- data << uint32(ritr->TabSlotPerDay[i]); // for TAB_i count of: withdraw items(stack/day)
- }
- }
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
- {
- if (Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
- {
- data << uint64(pl->GetGUID());
- data << uint8(1);
- data << pl->GetName();
- data << uint32(itr->second.RankId);
- data << uint8(pl->getLevel());
- data << uint8(pl->getClass());
- data << uint8(0); // new 2.4.0
- data << uint32(pl->GetZoneId());
- data << itr->second.Pnote;
- data << itr->second.OFFnote;
- }
- else
- {
- data << uint64(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
- data << uint8(0);
- data << itr->second.Name;
- data << uint32(itr->second.RankId);
- data << uint8(itr->second.Level);
- data << uint8(itr->second.Class);
- data << uint8(0); // new 2.4.0
- data << uint32(itr->second.ZoneId);
- data << float(float(time(NULL)-itr->second.LogoutTime) / DAY);
- data << itr->second.Pnote;
- data << itr->second.OFFnote;
- }
- }
if (session)
session->SendPacket(&data);
else
@@ -781,1372 +1229,1522 @@ void Guild::Roster(WorldSession *session /*= NULL*/)
sLog.outDebug("WORLD: Sent (SMSG_GUILD_ROSTER)");
}
-void Guild::Query(WorldSession *session)
+void Guild::HandleQuery(WorldSession *session)
{
- WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, (8*32+200));// we can only guess size
+ WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, 8 * 32 + 200); // Guess size
- data << uint32(m_Id);
- data << m_Name;
+ data << uint32(m_id);
+ data << m_name;
- for (size_t i = 0 ; i < GUILD_RANKS_MAX_COUNT; ++i) // show always 10 ranks
+ for (uint8 i = 0 ; i < GUILD_RANKS_MAX_COUNT; ++i) // Alwayse show 10 ranks
{
- if (i < m_Ranks.size())
- data << m_Ranks[i].Name;
+ if (i < _GetRanksSize())
+ data << m_ranks[i].GetName();
else
- data << (uint8)0; // null string
+ data << uint8(0); // Empty string
}
- data << uint32(m_EmblemStyle);
- data << uint32(m_EmblemColor);
- data << uint32(m_BorderStyle);
- data << uint32(m_BorderColor);
- data << uint32(m_BackgroundColor);
- data << uint32(0); // something new in WotLK
+ m_emblemInfo.WritePacket(data);
+ data << uint32(0); // Something new in WotLK
session->SendPacket(&data);
sLog.outDebug("WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)");
}
-void Guild::SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor)
-{
- m_EmblemStyle = emblemStyle;
- m_EmblemColor = emblemColor;
- m_BorderStyle = borderStyle;
- m_BorderColor = borderColor;
- m_BackgroundColor = backgroundColor;
-
- CharacterDatabase.PExecute("UPDATE guild SET EmblemStyle=%u, EmblemColor=%u, BorderStyle=%u, BorderColor=%u, BackgroundColor=%u WHERE guildid = %u", m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_BackgroundColor, m_Id);
-}
-
-void Guild::UpdateLogoutTime(uint64 guid)
+void Guild::HandleSetMOTD(WorldSession* session, const std::string& motd)
{
- MemberList::iterator itr = members.find(GUID_LOPART(guid));
- if (itr == members.end())
+ if (m_motd == motd)
return;
- itr->second.LogoutTime = time(NULL);
-}
+ // Player must have rights to set MOTD
+ if (!_HasRankRight(session->GetPlayer(), GR_RIGHT_SETMOTD))
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ else
+ {
+ m_motd = motd;
-/**
- * Updates the number of accounts that are in the guild
- * A player may have many characters in the guild, but with the same account
- */
-void Guild::UpdateAccountsNumber()
-{
- // We use a set to be sure each element will be unique
- std::set<uint32> accountsIdSet;
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
- accountsIdSet.insert(itr->second.accountId);
+ sScriptMgr.OnGuildMOTDChanged(this, motd);
- m_accountsNumber = accountsIdSet.size();
-}
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_MOTD);
+ stmt->setString(0, motd);
+ stmt->setUInt32(1, m_id);
+ CharacterDatabase.Execute(stmt);
-// *************************************************
-// Guild Eventlog part
-// *************************************************
-// Display guild eventlog
-void Guild::DisplayGuildEventLog(WorldSession *session)
-{
- // Sending result
- WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 0);
- // count, max count == 100
- data << uint8(m_GuildEventLog.size());
- for (GuildEventLog::const_iterator itr = m_GuildEventLog.begin(); itr != m_GuildEventLog.end(); ++itr)
- {
- // Event type
- data << uint8(itr->EventType);
- // Player 1
- data << uint64(itr->PlayerGuid1);
- // Player 2 not for left/join guild events
- if (itr->EventType != GUILD_EVENT_LOG_JOIN_GUILD && itr->EventType != GUILD_EVENT_LOG_LEAVE_GUILD)
- data << uint64(itr->PlayerGuid2);
- // New Rank - only for promote/demote guild events
- if (itr->EventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || itr->EventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
- data << uint8(itr->NewRank);
- // Event timestamp
- data << uint32(time(NULL)-itr->TimeStamp);
+ _BroadcastEvent(GE_MOTD, 0, motd.c_str());
}
- session->SendPacket(&data);
- sLog.outDebug("WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)");
}
-// Add entry to guild eventlog
-void Guild::LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank)
+void Guild::HandleSetInfo(WorldSession* session, const std::string& info)
{
- GuildEventLogEntry NewEvent;
- // Create event
- NewEvent.EventType = EventType;
- NewEvent.PlayerGuid1 = PlayerGuid1;
- NewEvent.PlayerGuid2 = PlayerGuid2;
- NewEvent.NewRank = NewRank;
- NewEvent.TimeStamp = uint32(time(NULL));
- // Count new LogGuid
- m_GuildEventLogNextGuid = (m_GuildEventLogNextGuid + 1) % sWorld.getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT);
- // Check max records limit
- if (m_GuildEventLog.size() >= GUILD_EVENTLOG_MAX_RECORDS)
- m_GuildEventLog.pop_front();
- // Add event to list
- m_GuildEventLog.push_back(NewEvent);
- // Save event to DB
- CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid='%u' AND LogGuid='%u'", m_Id, m_GuildEventLogNextGuid);
- CharacterDatabase.PExecute("INSERT INTO guild_eventlog (guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','" UI64FMTD "')",
- m_Id, m_GuildEventLogNextGuid, uint32(NewEvent.EventType), NewEvent.PlayerGuid1, NewEvent.PlayerGuid2, uint32(NewEvent.NewRank), NewEvent.TimeStamp);
-}
-
-// *************************************************
-// Guild Bank part
-// *************************************************
-// Bank content related
-void Guild::DisplayGuildBankContent(WorldSession *session, uint8 TabId)
-{
- GuildBankTab const* tab = m_TabListMap[TabId];
-
- if (!IsMemberHaveRights(session->GetPlayer()->GetGUIDLow(), TabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ if (m_info == info)
return;
- WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
-
- data << uint64(GetGuildBankMoney());
- data << uint8(TabId);
- data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), TabId)); // remaining slots for today
- data << uint8(0); // Tell client that there's no tab info in this packet
-
- data << uint8(GUILD_BANK_MAX_SLOTS);
-
- for (uint8 i=0; i < GUILD_BANK_MAX_SLOTS; ++i)
- AppendDisplayGuildBankSlot(data, tab, i);
+ // Player must have rights to set guild's info
+ if (!_HasRankRight(session->GetPlayer(), GR_RIGHT_MODIFY_GUILD_INFO))
+ SendCommandResult(session, GUILD_CREATE_S, ERR_GUILD_PERMISSIONS);
+ else
+ {
+ m_info = info;
- session->SendPacket(&data);
+ sScriptMgr.OnGuildInfoChanged(this, info);
- sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_INFO);
+ stmt->setString(0, info);
+ stmt->setUInt32(1, m_id);
+ CharacterDatabase.Execute(stmt);
+ }
}
-void Guild::DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2)
+void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo)
{
- GuildBankTab const* tab = m_TabListMap[TabId];
+ Player* player = session->GetPlayer();
+ if (!_IsLeader(player))
+ // "Only pGuild leaders can create emblems."
+ SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTGUILDMASTER);
+ else if (!player->HasEnoughMoney(EMBLEM_PRICE))
+ // "You can't afford to do that."
+ SendSaveEmblemResult(session, ERR_GUILDEMBLEM_NOTENOUGHMONEY);
+ else
+ {
+ player->ModifyMoney(-int32(EMBLEM_PRICE));
- WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
+ m_emblemInfo = emblemInfo;
+ m_emblemInfo.SaveToDB(m_id);
- data << uint64(GetGuildBankMoney());
- data << uint8(TabId);
+ // "Guild Emblem saved."
+ SendSaveEmblemResult(session, ERR_GUILDEMBLEM_SUCCESS);
- size_t rempos = data.wpos();
- data << uint32(0); // item withdraw amount, will be filled later
- data << uint8(0); // Tell client that there's no tab info in this packet
+ HandleQuery(session);
+ }
+}
- if (slot2 == -1) // single item in slot1
+void Guild::HandleSetLeader(WorldSession* session, const std::string& name)
+{
+ Player* player = session->GetPlayer();
+ // Only leader can assign new leader
+ if (!_IsLeader(player))
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ // Old leader must be a member of guild
+ else if (Member* pOldLeader = GetMember(player->GetGUID()))
{
- data << uint8(1); // item count
-
- AppendDisplayGuildBankSlot(data, tab, slot1);
+ // New leader must be a member of guild
+ if (Member* pNewLeader = GetMember(session, name))
+ {
+ _SetLeaderGUID(pNewLeader);
+ pOldLeader->ChangeRank(GR_OFFICER);
+ _BroadcastEvent(GE_LEADER_CHANGED, 0, player->GetName(), name.c_str());
+ }
}
- else // 2 items (in slot1 and slot2)
- {
- data << uint8(2); // item count
+ else
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+}
- if (slot1 > slot2)
- std::swap(slot1,slot2);
+void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, const std::string& name, const std::string& icon)
+{
+ if (BankTab* pTab = GetBankTab(tabId))
+ {
+ pTab->SetInfo(name, icon);
+ SendBankTabsInfo(session);
+ _SendBankContent(session, tabId);
+ }
+}
- AppendDisplayGuildBankSlot(data, tab, slot1);
- AppendDisplayGuildBankSlot(data, tab, slot2);
+void Guild::HandleSetMemberNote(WorldSession* session, const std::string& name, const std::string& note, bool officer)
+{
+ // Player must have rights to set public/officer note
+ if (!_HasRankRight(session->GetPlayer(), officer ? GR_RIGHT_EOFFNOTE : GR_RIGHT_EPNOTE))
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ // Noted player must be a member of guild
+ else if (Member* pMember = GetMember(session, name))
+ {
+ if (officer)
+ pMember->SetOfficerNote(note);
+ else
+ pMember->SetPublicNote(note);
+ HandleRoster(session);
}
+}
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
+void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, const std::string& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots)
+{
+ // Only leader can modify ranks
+ if (!_IsLeader(session->GetPlayer()))
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ else if (RankInfo* rankInfo = GetRankInfo(rankId))
{
- Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
- if (!player)
- continue;
+ sLog.outDebug("WORLD: Changed RankName to '%s', rights to 0x%08X", name.c_str(), rights);
- if (!IsMemberHaveRights(itr->first,TabId,GUILD_BANK_RIGHT_VIEW_TAB))
- continue;
+ rankInfo->SetName(name);
+ rankInfo->SetRights(rights);
+ _SetRankBankMoneyPerDay(rankId, moneyPerDay);
- data.put<uint32>(rempos,uint32(GetMemberSlotWithdrawRem(player->GetGUIDLow(), TabId)));
+ uint8 tabId = 0;
+ for (GuildBankRightsAndSlotsVec::const_iterator itr = rightsAndSlots.begin(); itr != rightsAndSlots.end(); ++itr)
+ _SetRankBankTabRightsAndSlots(rankId, tabId++, *itr);
- player->GetSession()->SendPacket(&data);
+ HandleQuery(session);
+ HandleRoster(); // Broadcast for tab rights update
}
-
- sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
}
-void Guild::DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots)
+void Guild::HandleBuyBankTab(WorldSession* session, uint8 tabId)
{
- GuildBankTab const* tab = m_TabListMap[TabId];
+ if (tabId != _GetPurchasedTabsSize())
+ return;
- WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
+ uint32 tabCost = _GetGuildBankTabPrice(tabId) * GOLD;
+ if (!tabCost)
+ return;
- data << uint64(GetGuildBankMoney());
- data << uint8(TabId);
+ Player* player = session->GetPlayer();
+ if (!player->HasEnoughMoney(tabCost)) // Should not happen, this is checked by client
+ return;
- size_t rempos = data.wpos();
- data << uint32(0); // item withdraw amount, will be filled later
- data << uint8(0); // Tell client that there's no tab info in this packet
+ if (!_CreateNewBankTab())
+ return;
- data << uint8(slots.size()); // updates count
+ player->ModifyMoney(-int32(tabCost));
+ _SetRankBankMoneyPerDay(player->GetRank(), GUILD_WITHDRAW_MONEY_UNLIMITED);
+ _SetRankBankTabRightsAndSlots(player->GetRank(), tabId, GuildBankRightsAndSlots(GUILD_BANK_RIGHT_FULL, GUILD_WITHDRAW_SLOT_UNLIMITED));
+ HandleRoster(); // Broadcast for tab rights update
+ SendBankTabsInfo(session);
+}
- for (GuildItemPosCountVec::const_iterator itr = slots.begin(); itr != slots.end(); ++itr)
- AppendDisplayGuildBankSlot(data, tab, itr->Slot);
+void Guild::HandleInviteMember(WorldSession* session, const std::string& name)
+{
+ Player* pInvitee = sObjectAccessor.FindPlayerByName(name.c_str());
+ if (!pInvitee)
+ {
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PLAYER_NOT_FOUND_S, name);
+ return;
+ }
- for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
+ Player* player = session->GetPlayer();
+ // Do not show invitations from ignored players
+ if (pInvitee->GetSocial()->HasIgnore(player->GetGUIDLow()))
+ return;
+ if (!sWorld.getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && pInvitee->GetTeam() != player->GetTeam())
{
- Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
- if (!player)
- continue;
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_NOT_ALLIED, name);
+ return;
+ }
+ // Invited player cannot be in another guild
+ if (pInvitee->GetGuildId())
+ {
+ SendCommandResult(session, GUILD_INVITE_S, ERR_ALREADY_IN_GUILD_S, name);
+ return;
+ }
+ // Invited player cannot be invited
+ if (pInvitee->GetGuildIdInvited())
+ {
+ SendCommandResult(session, GUILD_INVITE_S, ERR_ALREADY_INVITED_TO_GUILD_S, name);
+ return;
+ }
+ // Inviting player must have rights to invite
+ if (!_HasRankRight(player, GR_RIGHT_INVITE))
+ {
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ return;
+ }
- if (!IsMemberHaveRights(itr->first,TabId,GUILD_BANK_RIGHT_VIEW_TAB))
- continue;
+ sLog.outDebug("Player %s invited %s to join his Guild", player->GetName(), name.c_str());
- data.put<uint32>(rempos,uint32(GetMemberSlotWithdrawRem(player->GetGUIDLow(), TabId)));
+ pInvitee->SetGuildIdInvited(m_id);
+ _LogEvent(GUILD_EVENT_LOG_INVITE_PLAYER, player->GetGUIDLow(), pInvitee->GetGUIDLow());
- player->GetSession()->SendPacket(&data);
- }
+ WorldPacket data(SMSG_GUILD_INVITE, 8 + 10); // Guess size
+ data << player->GetName();
+ data << m_name;
+ pInvitee->GetSession()->SendPacket(&data);
- sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_INVITE)");
}
-Item* Guild::GetItem(uint8 TabId, uint8 SlotId)
+void Guild::HandleAcceptMember(WorldSession* session)
{
- if (TabId >= GetPurchasedTabs() || SlotId >= GUILD_BANK_MAX_SLOTS)
- return NULL;
- return m_TabListMap[TabId]->Slots[SlotId];
-}
+ Player* player = session->GetPlayer();
+ if (!sWorld.getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) &&
+ player->GetTeam() != sObjectMgr.GetPlayerTeamByGUID(GetLeaderGUID()))
+ return;
-// *************************************************
-// Tab related
+ if (AddMember(player->GetGUID()))
+ {
+ _LogEvent(GUILD_EVENT_LOG_JOIN_GUILD, player->GetGUIDLow());
+ _BroadcastEvent(GE_JOINED, player->GetGUID(), player->GetName());
+ }
+}
-void Guild::DisplayGuildBankTabsInfo(WorldSession *session)
+void Guild::HandleLeaveMember(WorldSession* session)
{
- WorldPacket data(SMSG_GUILD_BANK_LIST, 500);
+ Player* player = session->GetPlayer();
+ // If leader is leaving
+ if (_IsLeader(player))
+ {
+ 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
+ // Guild is disbanded if leader leaves.
+ Disband();
+ }
+ else
+ {
+ DeleteMember(player->GetGUID(), false, false);
- data << uint64(GetGuildBankMoney());
- data << uint8(0); // TabInfo packet must be for TabId 0
- data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), 0));
- data << uint8(1); // Tell client that this packet includes tab info
- data << uint8(GetPurchasedTabs()); // here is the number of tabs
+ _LogEvent(GUILD_EVENT_LOG_LEAVE_GUILD, player->GetGUIDLow());
+ _BroadcastEvent(GE_LEFT, player->GetGUID(), player->GetName());
- for (uint8 i = 0; i < GetPurchasedTabs(); ++i)
- {
- data << m_TabListMap[i]->Name.c_str();
- data << m_TabListMap[i]->Icon.c_str();
+ SendCommandResult(session, GUILD_QUIT_S, ERR_PLAYER_NO_MORE_IN_GUILD, m_name);
}
- data << uint8(0); // Do not send tab content
- session->SendPacket(&data);
+}
- sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+void Guild::HandleRemoveMember(WorldSession* session, const std::string& name)
+{
+ Player* player = session->GetPlayer();
+ // Player must have rights to remove members
+ if (!_HasRankRight(player, GR_RIGHT_REMOVE))
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ // Removed player must be a member of guild
+ else if (Member* pMember = GetMember(session, name))
+ {
+ // Leader cannot be removed
+ if (pMember->IsRank(GR_GUILDMASTER))
+ SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_LEADER_LEAVE);
+ // Do not allow to remove player with the same rank or higher
+ else if (pMember->IsRankNotLower(player->GetRank()))
+ SendCommandResult(session, GUILD_QUIT_S, ERR_GUILD_RANK_TOO_HIGH_S, name);
+ else
+ {
+ const uint64& guid = pMember->GetGUID();
+ // After call to DeleteMember pointer to member becomes invalid
+ DeleteMember(guid, false, true);
+ _LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUIDLow(), GUID_LOPART(guid));
+ _BroadcastEvent(GE_REMOVED, 0, name.c_str(), player->GetName());
+ }
+ }
}
-void Guild::DisplayGuildBankMoneyUpdate(WorldSession *session)
+void Guild::HandleUpdateMemberRank(WorldSession* session, const std::string& name, bool demote)
{
- WorldPacket data(SMSG_GUILD_BANK_LIST, 8+1+4+1+1);
+ Player* player = session->GetPlayer();
+ // Player must have rights to promote
+ if (!_HasRankRight(player, demote ? GR_RIGHT_DEMOTE : GR_RIGHT_PROMOTE))
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ // Promoted player must be a member of guild
+ else if (Member* pMember = GetMember(session, name))
+ {
+ // Player cannot promote himself
+ if (pMember->IsSamePlayer(player->GetGUID()))
+ {
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_NAME_INVALID);
+ return;
+ }
- data << uint64(GetGuildBankMoney());
- data << uint8(0); // TabId, default 0
- data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), 0));
- data << uint8(0); // Tell that there's no tab info in this packet
- data << uint8(0); // not send items
- BroadcastPacket(&data);
+ if (demote)
+ {
+ // Player can demote only lower rank members
+ if (pMember->IsRankNotLower(player->GetRank()))
+ {
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_HIGH_S, name);
+ return;
+ }
+ // Lowest rank cannot be demoted
+ if (pMember->GetRankId() >= _GetLowestRankId())
+ {
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_LOW_S, name);
+ return;
+ }
+ }
+ else
+ {
+ // Allow to promote only to lower rank than member's rank
+ // pMember->GetRank() + 1 is the highest rank that current player can promote to
+ if (pMember->IsRankNotLower(player->GetRank() + 1))
+ {
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_RANK_TOO_HIGH_S, name);
+ return;
+ }
+ }
- sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+ // When promoting player, rank is decreased, when demoting - increased
+ uint32 newRankId = pMember->GetRankId() + (demote ? 1 : -1);
+ pMember->ChangeRank(newRankId);
+ _LogEvent(demote ? GUILD_EVENT_LOG_DEMOTE_PLAYER : GUILD_EVENT_LOG_PROMOTE_PLAYER, player->GetGUIDLow(), GUID_LOPART(pMember->GetGUID()), newRankId);
+ _BroadcastEvent(demote ? GE_DEMOTION : GE_PROMOTION, 0, player->GetName(), name.c_str(), _GetRankName(newRankId).c_str());
+ }
}
-void Guild::CreateNewBankTab()
+void Guild::HandleAddNewRank(WorldSession* session, const std::string& name)
{
- if (GetPurchasedTabs() >= GUILD_BANK_MAX_TABS)
+ if (_GetRanksSize() >= GUILD_RANKS_MAX_COUNT)
return;
- uint32 tabId = GetPurchasedTabs(); // next free id
- m_TabListMap.push_back(new GuildBankTab);
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- trans->PAppend("DELETE FROM guild_bank_tab WHERE guildid='%u' AND TabId='%u'", m_Id, tabId);
- trans->PAppend("INSERT INTO guild_bank_tab (guildid,TabId) VALUES ('%u','%u')", m_Id, tabId);
- CharacterDatabase.CommitTransaction(trans);
+ // Only leader can add new rank
+ if (!_IsLeader(session->GetPlayer()))
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ else
+ {
+ _CreateRank(name, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
+ HandleQuery(session);
+ HandleRoster(); // Broadcast for tab rights update
+ }
}
-void Guild::SetGuildBankTabInfo(uint8 TabId, std::string Name, std::string Icon)
+void Guild::HandleRemoveLowestRank(WorldSession* session)
{
- if (m_TabListMap[TabId]->Name == Name && m_TabListMap[TabId]->Icon == Icon)
+ // Cannot remove rank if total count is minimum allowed by the client
+ if (_GetRanksSize() <= GUILD_RANKS_MIN_COUNT)
return;
- m_TabListMap[TabId]->Name = Name;
- m_TabListMap[TabId]->Icon = Icon;
-
- CharacterDatabase.escape_string(Name);
- CharacterDatabase.escape_string(Icon);
- CharacterDatabase.PExecute("UPDATE guild_bank_tab SET TabName='%s',TabIcon='%s' WHERE guildid='%u' AND TabId='%u'", Name.c_str(), Icon.c_str(), m_Id, uint32(TabId));
+ // Only leader can delete ranks
+ if (!_IsLeader(session->GetPlayer()))
+ SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ else
+ {
+ uint8 rankId = _GetLowestRankId();
+ // Delete bank rights for rank
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHTS_FOR_RANK);
+ stmt->setUInt32(0, m_id);
+ stmt->setUInt8 (1, rankId);
+ CharacterDatabase.Execute(stmt);
+ // Delete rank
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_LOWEST_RANK);
+ stmt->setUInt32(0, m_id);
+ stmt->setUInt8 (1, rankId);
+ CharacterDatabase.Execute(stmt);
+
+ m_ranks.pop_back();
+
+ HandleQuery(session);
+ HandleRoster(); // Broadcast for tab rights update
+ }
}
-uint32 Guild::GetBankRights(uint32 rankId, uint8 TabId) const
+void Guild::HandleMemberDepositMoney(WorldSession* session, uint32 amount)
{
- if (rankId >= m_Ranks.size() || TabId >= GUILD_BANK_MAX_TABS)
- return 0;
+ if (!_GetPurchasedTabsSize())
+ return; // No guild bank tabs - no money in bank
- return m_Ranks[rankId].TabRight[TabId];
-}
+ Player* player = session->GetPlayer();
-// *************************************************
-// Money deposit/withdraw related
+ // Call script after validation and before money transfer.
+ sScriptMgr.OnGuildMemberDepositMoney(this, player, amount);
-void Guild::SendMoneyInfo(WorldSession *session, uint32 LowGuid)
-{
- WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4);
- data << uint32(GetMemberMoneyWithdrawRem(LowGuid));
- session->SendPacket(&data);
- sLog.outDebug("WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN");
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ // Add money to bank
+ _ModifyBankMoney(trans, amount, true);
+ // Remove money from player
+ player->ModifyMoney(-int32(amount));
+ player->SaveGoldToDB(trans);
+ // Log GM action (TODO: move to scripts)
+ if (player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getBoolConfig(CONFIG_GM_LOG_TRADE))
+ {
+ sLog.outCommand(player->GetSession()->GetAccountId(),
+ "GM %s (Account: %u) deposit money (Amount: %u) to pGuild bank (Guild ID %u)",
+ player->GetName(), player->GetSession()->GetAccountId(), amount, m_id);
+ }
+ // Log guild bank event
+ _LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), player->GetGUIDLow(), amount);
+
+ CharacterDatabase.CommitTransaction(trans);
+
+ SendBankTabsInfo(session);
+ _SendBankContent(session, 0);
+ _SendBankMoneyUpdate(session);
}
-bool Guild::MemberMoneyWithdraw(uint32 amount, uint32 LowGuid, SQLTransaction& trans)
+bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint32 amount, bool repair)
{
- uint32 MoneyWithDrawRight = GetMemberMoneyWithdrawRem(LowGuid);
+ if (!_GetPurchasedTabsSize())
+ return false; // No guild bank tabs - no money
+
+ if (m_bankMoney < amount) // Not enough money in bank
+ return false;
- if (MoneyWithDrawRight < amount || GetGuildBankMoney() < amount)
+ Player* player = session->GetPlayer();
+ if (!_HasRankRight(player, repair ? GR_RIGHT_WITHDRAW_REPAIR : GR_RIGHT_WITHDRAW_GOLD))
return false;
- SetBankMoney(GetGuildBankMoney()-amount, trans);
+ uint32 remainingMoney = _GetMemberRemainingMoney(player->GetGUID());
+ if (!remainingMoney)
+ return false;
- if (MoneyWithDrawRight < WITHDRAW_MONEY_UNLIMITED)
+ // Call script after validation and before money transfer.
+ sScriptMgr.OnGuildMemberWitdrawMoney(this, player, amount, repair);
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ // Update remaining money amount
+ if (remainingMoney >= amount && remainingMoney < GUILD_WITHDRAW_MONEY_UNLIMITED)
+ if (Member* pMember = GetMember(player->GetGUID()))
+ pMember->DecreaseBankRemainingValue(trans, GUILD_BANK_MAX_TABS, amount);
+ // Remove money from bank
+ _ModifyBankMoney(trans, amount, false);
+ // Add money to player (if required)
+ if (!repair)
{
- MemberList::iterator itr = members.find(LowGuid);
- if (itr == members.end())
- return false;
- itr->second.BankRemMoney -= amount;
- trans->PAppend("UPDATE guild_member SET BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'",
- itr->second.BankRemMoney, m_Id, LowGuid);
+ player->ModifyMoney(amount);
+ player->SaveGoldToDB(trans);
+ }
+ // Log guild bank event
+ _LogBankEvent(trans, repair ? GUILD_BANK_LOG_REPAIR_MONEY : GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), player->GetGUIDLow(), amount);
+ CharacterDatabase.CommitTransaction(trans);
+
+ SendMoneyInfo(session);
+ if (!repair)
+ {
+ SendBankTabsInfo(session);
+ _SendBankContent(session, 0);
+ _SendBankMoneyUpdate(session);
}
return true;
}
-void Guild::SetBankMoney(int64 money, SQLTransaction& trans)
+void Guild::HandleMemberLogout(WorldSession* session)
{
- if (money < 0) // I don't know how this happens, it does!!
- money = 0;
- m_GuildBankMoney = money;
-
- trans->PAppend("UPDATE guild SET BankMoney='" UI64FMTD "' WHERE guildid='%u'", money, m_Id);
+ Player* player = session->GetPlayer();
+ if (Member* pMember = GetMember(player->GetGUID()))
+ {
+ pMember->SetStats(player);
+ pMember->UpdateLogoutTime();
+ }
+ _BroadcastEvent(GE_SIGNED_OFF, player->GetGUID(), player->GetName());
}
-// *************************************************
-// Item per day and money per day related
-
-bool Guild::MemberItemWithdraw(uint8 TabId, uint32 LowGuid, SQLTransaction& trans)
+void Guild::HandleDisband(WorldSession* session)
{
- uint32 SlotsWithDrawRight = GetMemberSlotWithdrawRem(LowGuid, TabId);
-
- if (SlotsWithDrawRight == 0)
- return false;
-
- if (SlotsWithDrawRight < WITHDRAW_SLOT_UNLIMITED)
+ // Only leader can disband guild
+ if (!_IsLeader(session->GetPlayer()))
+ Guild::SendCommandResult(session, GUILD_INVITE_S, ERR_GUILD_PERMISSIONS);
+ else
{
- MemberList::iterator itr = members.find(LowGuid);
- if (itr == members.end())
- return false;
- --itr->second.BankRemSlotsTab[TabId];
- trans->PAppend("UPDATE guild_member SET BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'",
- uint32(TabId), itr->second.BankRemSlotsTab[TabId], m_Id, LowGuid);
+ Disband();
+ sLog.outDebug("WORLD: Guild Successfully Disbanded");
}
- return true;
}
-bool Guild::IsMemberHaveRights(uint32 LowGuid, uint8 TabId, uint32 rights) const
+///////////////////////////////////////////////////////////////////////////////
+// Send data to client
+void Guild::SendInfo(WorldSession* session) const
{
- MemberList::const_iterator itr = members.find(LowGuid);
- if (itr == members.end())
- return false;
-
- if (itr->second.RankId == GR_GUILDMASTER)
- return true;
+ WorldPacket data(SMSG_GUILD_INFO, m_name.size() + 4 + 4 + 4);
+ data << m_name;
+ data << secsToTimeBitFields(m_createdDate); // 3.x (prev. year + month + day)
+ data << uint32(m_members.size()); // Number of members
+ data << m_accountsNumber; // Number of accounts
- return (GetBankRights(itr->second.RankId,TabId) & rights) == rights;
+ session->SendPacket(&data);
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_INFO)");
}
-uint32 Guild::GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId)
+void Guild::SendEventLog(WorldSession *session) const
{
- MemberList::iterator itr = members.find(LowGuid);
- if (itr == members.end())
- return 0;
-
- if (itr->second.RankId == GR_GUILDMASTER)
- return WITHDRAW_SLOT_UNLIMITED;
-
- if ((GetBankRights(itr->second.RankId,TabId) & GUILD_BANK_RIGHT_VIEW_TAB) != GUILD_BANK_RIGHT_VIEW_TAB)
- return 0;
+ WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 1 + m_eventLog->GetSize() * (1 + 8 + 4));
+ m_eventLog->WritePacket(data);
+ session->SendPacket(&data);
+ sLog.outDebug("WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)");
+}
- uint32 curTime = uint32(time(NULL)/MINUTE);
- if (curTime - itr->second.BankResetTimeTab[TabId] >= 24*HOUR/MINUTE)
+void Guild::SendBankLog(WorldSession *session, uint8 tabId) const
+{
+ // GUILD_BANK_MAX_TABS send by client for money log
+ if (tabId < _GetPurchasedTabsSize() || tabId == GUILD_BANK_MAX_TABS)
{
- itr->second.BankResetTimeTab[TabId] = curTime;
- itr->second.BankRemSlotsTab[TabId] = GetBankSlotPerDay(itr->second.RankId, TabId);
- CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeTab%u='%u', BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'",
- uint32(TabId), itr->second.BankResetTimeTab[TabId], uint32(TabId), itr->second.BankRemSlotsTab[TabId], m_Id, LowGuid);
+ const LogHolder* pLog = m_bankEventLog[tabId];
+ WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, pLog->GetSize() * (4 * 4 + 1) + 1 + 1);
+ data << uint8(tabId);
+ pLog->WritePacket(data);
+ session->SendPacket(&data);
+ sLog.outDebug("WORLD: Sent (MSG_GUILD_BANK_LOG_QUERY)");
}
- return itr->second.BankRemSlotsTab[TabId];
}
-uint32 Guild::GetMemberMoneyWithdrawRem(uint32 LowGuid)
+void Guild::SendBankTabData(WorldSession* session, uint8 tabId) const
{
- MemberList::iterator itr = members.find(LowGuid);
- if (itr == members.end())
- return 0;
-
- if (itr->second.RankId == GR_GUILDMASTER)
- return WITHDRAW_MONEY_UNLIMITED;
-
- uint32 curTime = uint32(time(NULL)/MINUTE); // minutes
- // 24 hours
- if (curTime > itr->second.BankResetTimeMoney + 24*HOUR/MINUTE)
+ if (tabId < _GetPurchasedTabsSize())
{
- itr->second.BankResetTimeMoney = curTime;
- itr->second.BankRemMoney = GetBankMoneyPerDay(itr->second.RankId);
- CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeMoney='%u', BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'",
- itr->second.BankResetTimeMoney, itr->second.BankRemMoney, m_Id, LowGuid);
+ SendMoneyInfo(session);
+ _SendBankContent(session, tabId);
}
- return itr->second.BankRemMoney;
}
-void Guild::SetBankMoneyPerDay(uint32 rankId, uint32 money)
+void Guild::SendBankTabsInfo(WorldSession *session) const
{
- if (rankId >= m_Ranks.size())
- return;
+ WorldPacket data(SMSG_GUILD_BANK_LIST, 500);
- if (rankId == GR_GUILDMASTER)
- money = WITHDRAW_MONEY_UNLIMITED;
+ data << uint64(m_bankMoney);
+ data << uint8(0); // TabInfo packet must be for tabId 0
+ data << uint32(_GetMemberRemainingSlots(session->GetPlayer()->GetGUID(), 0));
+ data << uint8(1); // Tell client that this packet includes tab info
- m_Ranks[rankId].BankMoneyPerDay = money;
+ data << uint8(_GetPurchasedTabsSize()); // Number of tabs
+ for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i)
+ m_bankTabs[i]->WriteInfoPacket(data);
- for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
- if (itr->second.RankId == rankId)
- itr->second.BankResetTimeMoney = 0;
+ data << uint8(0); // Do not send tab content
+ session->SendPacket(&data);
- CharacterDatabase.PExecute("UPDATE guild_rank SET BankMoneyPerDay='%u' WHERE rid='%u' AND guildid='%u'", money, rankId, m_Id);
- CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeMoney='0' WHERE guildid='%u' AND rank='%u'", m_Id, rankId);
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
}
-void Guild::SetBankRightsAndSlots(uint32 rankId, uint8 TabId, uint32 right, uint32 nbSlots, bool db)
+void Guild::SendBankTabText(WorldSession *session, uint8 tabId) const
{
- if (rankId >= m_Ranks.size() || TabId >= GetPurchasedTabs())
- return;
-
- if (rankId == GR_GUILDMASTER)
- {
- nbSlots = WITHDRAW_SLOT_UNLIMITED;
- right = GUILD_BANK_RIGHT_FULL;
- }
+ if (const BankTab* pTab = GetBankTab(tabId))
+ pTab->SendText(this, session);
+}
- m_Ranks[rankId].TabSlotPerDay[TabId] = nbSlots;
- m_Ranks[rankId].TabRight[TabId] = right;
+void Guild::SendPermissions(WorldSession *session) const
+{
+ const uint64& guid = session->GetPlayer()->GetGUID();
+ uint8 rankId = session->GetPlayer()->GetRank();
- if (db)
+ WorldPacket data(MSG_GUILD_PERMISSIONS, 4 * 15 + 1);
+ data << uint32(rankId);
+ data << uint32(_GetRankRights(rankId));
+ data << uint32(_GetMemberRemainingMoney(guid));
+ data << uint8 (_GetPurchasedTabsSize());
+ // Why sending all info when not all tabs are purchased???
+ for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
{
- for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
- if (itr->second.RankId == rankId)
- for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- itr->second.BankResetTimeTab[i] = 0;
-
- CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid='%u' AND TabId='%u' AND rid='%u'", m_Id, uint32(TabId), rankId);
- CharacterDatabase.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid,gbright,SlotPerDay) VALUES "
- "('%u','%u','%u','%u','%u')", m_Id, uint32(TabId), rankId, m_Ranks[rankId].TabRight[TabId], m_Ranks[rankId].TabSlotPerDay[TabId]);
- CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeTab%u='0' WHERE guildid='%u' AND rank='%u'", uint32(TabId), m_Id, rankId);
+ data << uint32(_GetRankBankTabRights(rankId, tabId));
+ data << uint32(_GetMemberRemainingSlots(guid, tabId));
}
+ session->SendPacket(&data);
+ sLog.outDebug("WORLD: Sent (MSG_GUILD_PERMISSIONS)");
}
-uint32 Guild::GetBankMoneyPerDay(uint32 rankId)
+void Guild::SendMoneyInfo(WorldSession *session) const
{
- if (rankId >= m_Ranks.size())
- return 0;
-
- if (rankId == GR_GUILDMASTER)
- return WITHDRAW_MONEY_UNLIMITED;
- return m_Ranks[rankId].BankMoneyPerDay;
+ WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4);
+ data << uint32(_GetMemberRemainingMoney(session->GetPlayer()->GetGUID()));
+ session->SendPacket(&data);
+ sLog.outDebug("WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN");
}
-uint32 Guild::GetBankSlotPerDay(uint32 rankId, uint8 TabId)
+void Guild::SendLoginInfo(WorldSession* session) const
{
- if (rankId >= m_Ranks.size() || TabId >= GUILD_BANK_MAX_TABS)
- return 0;
+ WorldPacket data(SMSG_GUILD_EVENT, 1 + 1 + m_motd.size() + 1);
+ data << uint8(GE_MOTD);
+ data << uint8(1);
+ data << m_motd;
+ session->SendPacket(&data);
+ sLog.outDebug("WORLD: Sent guild MOTD (SMSG_GUILD_EVENT)");
- if (rankId == GR_GUILDMASTER)
- return WITHDRAW_SLOT_UNLIMITED;
- return m_Ranks[rankId].TabSlotPerDay[TabId];
-}
+ SendBankTabsInfo(session);
-// *************************************************
-// Rights per day related
+ _BroadcastEvent(GE_SIGNED_ON, session->GetPlayer()->GetGUID(), session->GetPlayer()->GetName());
+}
-bool Guild::LoadBankRightsFromDB(QueryResult guildBankTabRightsResult)
+///////////////////////////////////////////////////////////////////////////////
+// Loading methods
+bool Guild::LoadFromDB(Field* fields)
{
- if (!guildBankTabRightsResult)
- return true;
+ m_id = fields[0].GetUInt32();
+ m_name = fields[1].GetString();
+ m_leaderGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
+ m_emblemInfo.LoadFromDB(fields);
+ m_info = fields[8].GetString();
+ m_motd = fields[9].GetString();
+ m_createdDate = fields[10].GetUInt64();
+ m_bankMoney = fields[11].GetUInt64();
- do
- {
- Field *fields = guildBankTabRightsResult->Fetch();
- //prevent crash when all rights in result are already processed
- if (!fields)
- break;
- uint32 guildId = fields[0].GetUInt32();
- if (guildId < m_Id)
- {
- //there is in table guild_bank_right record which doesn't have guildid in guild table, report error
- sLog.outErrorDb("Guild %u does not exist but it has a record in guild_bank_right table, deleting it!", guildId);
- CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", guildId);
- continue;
- }
-
- if (guildId > m_Id)
- //we loaded all ranks for this guild bank already, break cycle
- break;
- uint8 TabId = fields[1].GetUInt8();
- uint32 rankId = fields[2].GetUInt32();
- uint16 right = fields[3].GetUInt16();
- uint16 SlotPerDay = fields[4].GetUInt16();
-
- SetBankRightsAndSlots(rankId, TabId, right, SlotPerDay, false);
+ uint8 purchasedTabs = uint8(fields[12].GetUInt32());
+ if (purchasedTabs > GUILD_BANK_MAX_TABS)
+ purchasedTabs = GUILD_BANK_MAX_TABS;
- }while (guildBankTabRightsResult->NextRow());
+ m_bankTabs.resize(purchasedTabs);
+ for (uint8 i = 0; i < purchasedTabs; ++i)
+ m_bankTabs[i] = new BankTab(m_id, i);
+ _CreateLogHolders();
return true;
}
-// *************************************************
-// Bank log related
+bool Guild::LoadRankFromDB(Field* fields)
+{
+ RankInfo rankInfo(m_id);
+ if (!rankInfo.LoadFromDB(fields))
+ return false;
+ m_ranks.push_back(rankInfo);
+ return true;
+}
+bool Guild::LoadMemberFromDB(Field* fields)
+{
+ uint32 lowguid = fields[1].GetUInt32();
+ Member *pMember = new Member(m_id, MAKE_NEW_GUID(lowguid, 0, HIGHGUID_PLAYER), fields[2].GetUInt8());
+ if (!pMember->LoadFromDB(fields))
+ {
+ _DeleteMemberFromDB(lowguid);
+ delete pMember;
+ return false;
+ }
+ m_members[lowguid] = pMember;
+ return true;
+}
-void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
+bool Guild::LoadBankRightFromDB(Field* fields)
{
- if (TabId > GUILD_BANK_MAX_TABS) // tabs starts in 0
- return;
+ // rights slots
+ GuildBankRightsAndSlots rightsAndSlots(fields[3].GetUInt8(), fields[4].GetUInt32());
+ // rankId tabId
+ _SetRankBankTabRightsAndSlots(fields[2].GetUInt8(), fields[1].GetUInt8(), rightsAndSlots, false);
+ return true;
+}
- if (TabId == GUILD_BANK_MAX_TABS)
+bool Guild::LoadEventLogFromDB(Field* fields)
+{
+ if (m_eventLog->CanInsert())
{
- // Here we display money logs
- WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, m_GuildBankEventLog_Money.size()*(4*4+1)+1+1);
- data << uint8(TabId); // Here GUILD_BANK_MAX_TABS
- data << uint8(m_GuildBankEventLog_Money.size()); // number of log entries
- for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Money.begin(); itr != m_GuildBankEventLog_Money.end(); ++itr)
- {
- data << uint8(itr->EventType);
- data << uint64(MAKE_NEW_GUID(itr->PlayerGuid,0,HIGHGUID_PLAYER));
- data << uint32(itr->ItemOrMoney);
- data << uint32(time(NULL) - itr->TimeStamp);
- }
- session->SendPacket(&data);
+ m_eventLog->LoadEvent(new EventLogEntry(
+ m_id, // guild id
+ fields[1].GetUInt32(), // guid
+ fields[6].GetUInt64(), // timestamp
+ GuildEventLogTypes(fields[2].GetUInt8()), // event type
+ fields[3].GetUInt32(), // player guid 1
+ fields[4].GetUInt32(), // player guid 2
+ fields[5].GetUInt8())); // rank
+ return true;
}
- else
+ return false;
+}
+
+bool Guild::LoadBankEventLogFromDB(Field* fields)
+{
+ uint8 dbTabId = fields[1].GetUInt8();
+ bool isMoneyTab = (dbTabId == GUILD_BANK_MONEY_LOGS_TAB);
+ if (dbTabId < _GetPurchasedTabsSize() || isMoneyTab)
{
- // here we display current tab logs
- WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, m_GuildBankEventLog_Item[TabId].size()*(4*4+1+1)+1+1);
- data << uint8(TabId); // Here a real Tab Id
- data << uint8(m_GuildBankEventLog_Item[TabId].size()); // number of log entries
- for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Item[TabId].begin(); itr != m_GuildBankEventLog_Item[TabId].end(); ++itr)
+ uint8 tabId = isMoneyTab ? uint8(GUILD_BANK_MAX_TABS) : dbTabId;
+ LogHolder* pLog = m_bankEventLog[tabId];
+ if (pLog->CanInsert())
{
- data << uint8(itr->EventType);
- data << uint64(MAKE_NEW_GUID(itr->PlayerGuid,0,HIGHGUID_PLAYER));
- data << uint32(itr->ItemOrMoney);
- data << uint32(itr->ItemStackCount);
- if (itr->EventType == GUILD_BANK_LOG_MOVE_ITEM || itr->EventType == GUILD_BANK_LOG_MOVE_ITEM2)
- data << uint8(itr->DestTabId); // moved tab
- data << uint32(time(NULL) - itr->TimeStamp);
+ uint32 guid = fields[2].GetUInt32();
+ GuildBankEventLogTypes eventType = GuildBankEventLogTypes(fields[3].GetUInt8());
+ if (BankEventLogEntry::IsMoneyEvent(eventType))
+ {
+ if (!isMoneyTab)
+ {
+ sLog.outError("GuildBankEventLog ERROR: MoneyEvent(LogGuid: %u, Guild: %u) does not belong to money tab (%u), ignoring...", guid, m_id, dbTabId);
+ return false;
+ }
+ }
+ else if (isMoneyTab)
+ {
+ sLog.outError("GuildBankEventLog ERROR: non-money event (LogGuid: %u, Guild: %u) belongs to money tab, ignoring...", guid, m_id);
+ return false;
+ }
+ pLog->LoadEvent(new BankEventLogEntry(
+ m_id, // guild id
+ guid, // guid
+ fields[8].GetUInt64(), // timestamp
+ dbTabId, // tab id
+ eventType, // event type
+ fields[4].GetUInt32(), // player guid
+ fields[5].GetUInt32(), // item or money
+ fields[6].GetUInt16(), // itam stack count
+ fields[7].GetUInt8())); // dest tab id
}
- session->SendPacket(&data);
}
- sLog.outDebug("WORLD: Sent (MSG_GUILD_BANK_LOG_QUERY)");
+ return true;
}
-void Guild::LogBankEvent(SQLTransaction& trans, uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint16 ItemStackCount, uint8 DestTabId)
+bool Guild::LoadBankTabFromDB(Field* fields)
{
- //create Event
- GuildBankEventLogEntry NewEvent;
- NewEvent.EventType = EventType;
- NewEvent.PlayerGuid = PlayerGuidLow;
- NewEvent.ItemOrMoney = ItemOrMoney;
- NewEvent.ItemStackCount = ItemStackCount;
- NewEvent.DestTabId = DestTabId;
- NewEvent.TimeStamp = uint32(time(NULL));
+ uint32 tabId = fields[1].GetUInt8();
+ if (tabId >= _GetPurchasedTabsSize())
+ {
+ sLog.outError("Invalid tab (tabId: %u) in guild bank, skipped.", tabId);
+ return false;
+ }
+ return m_bankTabs[tabId]->LoadFromDB(fields);
+}
- //add new event to the end of event list
- uint32 currentTabId = TabId;
- uint32 currentLogGuid = 0;
- if (NewEvent.isMoneyEvent())
+bool Guild::LoadBankItemFromDB(Field* fields)
+{
+ uint8 tabId = fields[12].GetUInt8();
+ if (tabId >= _GetPurchasedTabsSize())
{
- m_GuildBankEventLogNextGuid_Money = (m_GuildBankEventLogNextGuid_Money + 1) % sWorld.getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT);
- currentLogGuid = m_GuildBankEventLogNextGuid_Money;
- currentTabId = GUILD_BANK_MONEY_LOGS_TAB;
- if (m_GuildBankEventLog_Money.size() >= GUILD_BANK_MAX_LOGS)
- m_GuildBankEventLog_Money.pop_front();
+ sLog.outError("Invalid tab for item (GUID: %u, id: #%u) in guild bank, skipped.",
+ fields[14].GetUInt32(), fields[15].GetUInt32());
+ return false;
+ }
+ return m_bankTabs[tabId]->LoadItemFromDB(fields);
+}
- m_GuildBankEventLog_Money.push_back(NewEvent);
+// Validates guild data loaded from database. Returns false if guild should be deleted.
+bool Guild::Validate()
+{
+ // Validate ranks data
+ // GUILD RANKS represent a sequence starting from 0 = GUILD_MASTER (ALL PRIVILEGES) to max 9 (lowest privileges).
+ // The lower rank id is considered higher rank - so promotion does rank-- and demotion does rank++
+ // Between ranks in sequence cannot be gaps - so 0,1,2,4 is impossible
+ // Min ranks count is 5 and max is 10.
+ bool broken_ranks = false;
+ if (_GetRanksSize() < GUILD_RANKS_MIN_COUNT || _GetRanksSize() > GUILD_RANKS_MAX_COUNT)
+ {
+ sLog.outError("Guild %u has invalid number of ranks, creating new...", m_id);
+ broken_ranks = true;
}
else
{
- m_GuildBankEventLogNextGuid_Item[TabId] = ((m_GuildBankEventLogNextGuid_Item[TabId]) + 1) % sWorld.getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT);
- currentLogGuid = m_GuildBankEventLogNextGuid_Item[TabId];
- if (m_GuildBankEventLog_Item[TabId].size() >= GUILD_BANK_MAX_LOGS)
- m_GuildBankEventLog_Item[TabId].pop_front();
+ for (uint8 rankId = 0; rankId < _GetRanksSize(); ++rankId)
+ {
+ RankInfo* rankInfo = GetRankInfo(rankId);
+ if (rankInfo->GetId() != rankId)
+ {
+ sLog.outError("Guild %u has broken rank id %u, creating default set of ranks...", m_id, rankId);
+ broken_ranks = true;
+ }
+ }
+ }
+ if (broken_ranks)
+ {
+ m_ranks.clear();
+ _CreateDefaultGuildRanks(DEFAULT_LOCALE);
+ }
+
+ // Validate members' data
+ for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (itr->second->GetRankId() > _GetRanksSize())
+ itr->second->ChangeRank(_GetLowestRankId());
- m_GuildBankEventLog_Item[TabId].push_back(NewEvent);
+ // Repair the structure of the guild.
+ // If the guildmaster doesn't exist or isn't member of the guild
+ // attempt to promote another member.
+ Member* pLeader = GetMember(m_leaderGuid);
+ if (!pLeader)
+ {
+ DeleteMember(m_leaderGuid);
+ // If no more members left, disband guild
+ if (m_members.empty())
+ {
+ Disband();
+ return false;
+ }
}
+ else if (!pLeader->IsRank(GR_GUILDMASTER))
+ _SetLeaderGUID(pLeader);
- //save event to database
- trans->PAppend("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u' AND TabId='%u'", m_Id, currentLogGuid, currentTabId);
+ // Check config if multiple guildmasters are allowed
+ if (!sConfig.GetBoolDefault("Guild.AllowMultipleGuildMaster", 0))
+ for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (itr->second->GetRankId() == GR_GUILDMASTER && !itr->second->IsSamePlayer(m_leaderGuid))
+ itr->second->ChangeRank(GR_OFFICER);
- trans->PAppend("INSERT INTO guild_bank_eventlog (guildid,LogGuid,TabId,EventType,PlayerGuid,ItemOrMoney,ItemStackCount,DestTabId,TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','%u','%u','" UI64FMTD "')",
- m_Id, currentLogGuid, currentTabId, uint32(NewEvent.EventType), NewEvent.PlayerGuid, NewEvent.ItemOrMoney, uint32(NewEvent.ItemStackCount), uint32(NewEvent.DestTabId), NewEvent.TimeStamp);
+ _UpdateAccountsNumber();
+ return true;
}
-bool Guild::AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry, SQLTransaction& trans)
+///////////////////////////////////////////////////////////////////////////////
+// Broadcasts
+void Guild::BroadcastToGuild(WorldSession *session, bool officerOnly, const std::string& msg, uint32 language) const
{
- trans->PAppend("DELETE FROM guild_bank_item WHERE guildid = '%u' AND TabId = '%u'AND SlotId = '%u'", GuildId, BankTab, BankTabSlot);
- trans->PAppend("INSERT INTO guild_bank_item (guildid,TabId,SlotId,item_guid,item_entry) "
- "VALUES ('%u', '%u', '%u', '%u', '%u')", GuildId, BankTab, BankTabSlot, GUIDLow, Entry);
- return true;
+ if (session && session->GetPlayer() && _HasRankRight(session->GetPlayer(), officerOnly ? GR_RIGHT_OFFCHATSPEAK : GR_RIGHT_GCHATSPEAK))
+ {
+ WorldPacket data;
+ ChatHandler::FillMessageData(&data, session, officerOnly ? CHAT_MSG_OFFICER : CHAT_MSG_GUILD, language, NULL, 0, msg.c_str(), NULL);
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (Player *player = itr->second->FindPlayer())
+ if (player->GetSession() && _HasRankRight(player, officerOnly ? GR_RIGHT_OFFCHATLISTEN : GR_RIGHT_GCHATLISTEN) &&
+ !player->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()))
+ player->GetSession()->SendPacket(&data);
+ }
}
-void Guild::AppendDisplayGuildBankSlot(WorldPacket& data, GuildBankTab const *tab, int slot)
+void Guild::BroadcastPacketToRank(WorldPacket *packet, uint8 rankId) const
{
- Item *pItem = tab->Slots[slot];
- uint32 entry = pItem ? pItem->GetEntry() : 0;
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (itr->second->IsRank(rankId))
+ if (Player *player = itr->second->FindPlayer())
+ player->GetSession()->SendPacket(packet);
+}
- data << uint8(slot);
- data << uint32(entry);
- if (entry)
+void Guild::BroadcastPacket(WorldPacket *packet) const
+{
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (Player *player = itr->second->FindPlayer())
+ player->GetSession()->SendPacket(packet);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Members handling
+bool Guild::AddMember(const uint64& guid, uint8 rankId)
+{
+ Player* player = sObjectMgr.GetPlayer(guid);
+ // Player cannot be in guild
+ if (player)
{
- data << uint32(0); // 3.3.0 (0x8000, 0x8020)
- data << uint32(pItem->GetItemRandomPropertyId()); // random item property id + 8
+ if (player->GetGuildId() != 0)
+ return false;
+ }
+ else if (Player::GetGuildIdFromDB(guid) != 0)
+ return false;
- if (pItem->GetItemRandomPropertyId())
- data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor + 4
+ // Remove all player signs from another petitions
+ // This will be prevent attempt to join many guilds and corrupt guild data integrity
+ Player::RemovePetitionsAndSigns(guid, GUILD_CHARTER_TYPE);
- data << uint32(pItem->GetCount()); // +12 ITEM_FIELD_STACK_COUNT
- data << uint32(0); // +16 Unknown value
- data << uint8(abs(pItem->GetSpellCharges())); // spell charges
+ uint32 lowguid = GUID_LOPART(guid);
- uint8 enchCount = 0;
- size_t enchCountPos = data.wpos();
+ // If rank was not passed, assing lowest possible rank
+ if (rankId == GUILD_RANK_NONE)
+ rankId = _GetLowestRankId();
- data << uint8(enchCount); // number of enchantments
- for (uint32 i = PERM_ENCHANTMENT_SLOT; i < MAX_ENCHANTMENT_SLOT; ++i)
+ Member* pMember = new Member(m_id, guid, rankId);
+ if (player)
+ pMember->SetStats(player);
+ else
+ {
+ bool ok = false;
+ // Player must exist
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_CHAR_DATA_FOR_GUILD);
+ stmt->setUInt32(0, lowguid);
+ if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
{
- if (uint32 enchId = pItem->GetEnchantmentId(EnchantmentSlot(i)))
- {
- data << uint8(i);
- data << uint32(enchId);
- ++enchCount;
- }
+ Field *fields = result->Fetch();
+ pMember->SetStats(
+ fields[0].GetString(),
+ fields[1].GetUInt8(),
+ fields[2].GetUInt8(),
+ fields[3].GetUInt32(),
+ fields[4].GetUInt32());
+
+ ok = pMember->CheckStats();
}
- data.put<uint8>(enchCountPos, enchCount);
+ if (!ok)
+ {
+ delete pMember;
+ return false;
+ }
+ }
+ m_members[lowguid] = pMember;
+
+ SQLTransaction trans(NULL);
+ pMember->SaveToDB(trans);
+ // If player not in game data in will be loaded from guild tables, so no need to update it!
+ if (player)
+ {
+ player->SetInGuild(m_id);
+ player->SetRank(rankId);
+ player->SetGuildIdInvited(0);
}
+
+ _UpdateAccountsNumber();
+
+ // Call scripts if member was succesfully added (and stored to database)
+ sScriptMgr.OnGuildAddMember(this, player, rankId);
+
+ return true;
}
-Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pItem, SQLTransaction& trans)
+void Guild::DeleteMember(const uint64& guid, bool isDisbanding, bool isKicked)
{
- if (!pItem)
- return NULL;
-
- Item* lastItem = pItem;
+ uint32 lowguid = GUID_LOPART(guid);
+ Player *player = sObjectMgr.GetPlayer(guid);
- for (GuildItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end();)
+ // Guild master can be deleted when loading guild and guid doesn't exist in characters table
+ // or when he is removed from guild by gm command
+ if (m_leaderGuid == guid && !isDisbanding)
{
- uint8 slot = itr->Slot;
- uint32 count = itr->Count;
+ Member* oldLeader = NULL;
+ Member* newLeader = NULL;
+ for (Guild::Members::iterator i = m_members.begin(); i != m_members.end(); ++i)
+ {
+ if (i->first == lowguid)
+ oldLeader = i->second;
+ else if (!newLeader || newLeader->GetRankId() > i->second->GetRankId())
+ newLeader = i->second;
+ }
+ if (!newLeader)
+ {
+ Disband();
+ return;
+ }
- ++itr;
+ _SetLeaderGUID(newLeader);
- if (itr == dest.end())
+ // 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);
+
+ // If leader does not exist (at guild loading with deleted leader) do not send broadcasts
+ if (oldLeader)
{
- lastItem = _StoreItem(tabId, slot, pItem, count, false, trans);
- break;
+ _BroadcastEvent(GE_LEADER_CHANGED, 0, oldLeader->GetName().c_str(), newLeader->GetName().c_str());
+ _BroadcastEvent(GE_LEFT, guid, oldLeader->GetName().c_str());
}
+ }
+ // Call script on remove before member is acutally removed from guild (and database)
+ sScriptMgr.OnGuildRemoveMember(this, player, isDisbanding, isKicked);
+
+ if (Member* pMember = GetMember(guid))
+ delete pMember;
+ m_members.erase(lowguid);
- lastItem = _StoreItem(tabId, slot, pItem, count, true, trans);
+ // If player not online data in data field will be loaded from guild tabs no need to update it !!
+ if (player)
+ {
+ player->SetInGuild(0);
+ player->SetRank(0);
}
- return lastItem;
+ _DeleteMemberFromDB(lowguid);
+ if (!isDisbanding)
+ _UpdateAccountsNumber();
}
-// Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
-Item* Guild::_StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone, SQLTransaction& trans)
+bool Guild::ChangeMemberRank(const uint64& guid, uint8 newRank)
{
- if (!pItem)
- return NULL;
-
- sLog.outDebug("GUILD STORAGE: StoreItem tab = %u, slot = %u, item = %u, count = %u", tab, slot, pItem->GetEntry(), count);
-
- Item* pItem2 = m_TabListMap[tab]->Slots[slot];
+ if (newRank <= _GetLowestRankId()) // Validate rank (allow only existing ranks)
+ if (Member* pMember = GetMember(guid))
+ {
+ pMember->ChangeRank(newRank);
+ return true;
+ }
+ return false;
+}
- if (!pItem2)
- {
- if (clone)
- pItem = pItem->CloneItem(count);
- else
- pItem->SetCount(count);
+///////////////////////////////////////////////////////////////////////////////
+// Bank (items move)
+void Guild::SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount)
+{
+ if (tabId >= _GetPurchasedTabsSize() || slotId >= GUILD_BANK_MAX_SLOTS ||
+ destTabId >= _GetPurchasedTabsSize() || destSlotId >= GUILD_BANK_MAX_SLOTS)
+ return;
- if (!pItem)
- return NULL;
+ if (tabId == destTabId && slotId == destSlotId)
+ return;
- m_TabListMap[tab]->Slots[slot] = pItem;
+ BankMoveItemData from(this, player, tabId, slotId);
+ BankMoveItemData to(this, player, destTabId, destSlotId);
+ _MoveItems(&from, &to, splitedAmount);
+}
- pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, 0);
- pItem->SetUInt64Value(ITEM_FIELD_OWNER, 0);
- AddGBankItemToDB(GetId(), tab, slot, pItem->GetGUIDLow(), pItem->GetEntry(), trans);
- pItem->FSetState(ITEM_NEW);
- pItem->SaveToDB(trans); // not in inventory and can be save standalone
+void Guild::SwapItemsWithInventory(Player* player, bool toChar, uint8 tabId, uint8 slotId, uint8 playerBag, uint8 playerSlotId, uint32 splitedAmount)
+{
+ if ((slotId >= GUILD_BANK_MAX_SLOTS && slotId != NULL_SLOT) || tabId >= _GetPurchasedTabsSize())
+ return;
- return pItem;
- }
+ BankMoveItemData bankData(this, player, tabId, slotId);
+ PlayerMoveItemData charData(this, player, playerBag, playerSlotId);
+ if (toChar)
+ _MoveItems(&bankData, &charData, splitedAmount);
else
- {
- pItem2->SetCount(pItem2->GetCount() + count);
- pItem2->FSetState(ITEM_CHANGED);
- pItem2->SaveToDB(trans); // not in inventory and can be save standalone
-
- if (!clone)
- {
- pItem->RemoveFromWorld();
- pItem->DeleteFromDB(trans);
- delete pItem;
- }
+ _MoveItems(&charData, &bankData, splitedAmount);
+}
- return pItem2;
+///////////////////////////////////////////////////////////////////////////////
+// Bank tabs
+void Guild::SetBankTabText(uint8 tabId, const std::string& text)
+{
+ if (BankTab* pTab = GetBankTab(tabId))
+ {
+ pTab->SetText(text);
+ pTab->SendText(this, NULL);
}
}
-void Guild::RemoveItem(uint8 tab, uint8 slot, SQLTransaction& trans)
+///////////////////////////////////////////////////////////////////////////////
+// Private methods
+void Guild::_CreateLogHolders()
{
- m_TabListMap[tab]->Slots[slot] = NULL;
- trans->PAppend("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'",
- GetId(), uint32(tab), uint32(slot));
+ m_eventLog = new LogHolder(m_id, sWorld.getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT));
+ for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId)
+ m_bankEventLog[tabId] = new LogHolder(m_id, sWorld.getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT));
}
-uint8 Guild::_CanStoreItem_InSpecificSlot(uint8 tab, uint8 slot, GuildItemPosCountVec &dest, uint32& count, bool swap, Item* pSrcItem) const
+bool Guild::_CreateNewBankTab()
{
- Item* pItem2 = m_TabListMap[tab]->Slots[slot];
+ if (_GetPurchasedTabsSize() >= GUILD_BANK_MAX_TABS)
+ return false;
- // ignore move item (this slot will be empty at move)
- if (pItem2 == pSrcItem)
- pItem2 = NULL;
+ uint8 tabId = _GetPurchasedTabsSize(); // Next free id
+ m_bankTabs.push_back(new BankTab(m_id, tabId));
- uint32 need_space;
+ PreparedStatement* stmt = NULL;
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
- // empty specific slot - check item fit to slot
- if (!pItem2 || swap)
- {
- // non empty stack with space
- need_space = pSrcItem->GetMaxStackCount();
- }
- // non empty slot, check item type
- else
- {
- // check item type
- if (pItem2->GetEntry() != pSrcItem->GetEntry())
- return EQUIP_ERR_ITEM_CANT_STACK;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_TAB);
+ stmt->setUInt32(0, m_id);
+ stmt->setUInt8 (1, tabId);
+ trans->Append(stmt);
- // check free space
- if (pItem2->GetCount() >= pSrcItem->GetMaxStackCount())
- return EQUIP_ERR_ITEM_CANT_STACK;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD_BANK_TAB);
+ stmt->setUInt32(0, m_id);
+ stmt->setUInt8 (1, tabId);
+ trans->Append(stmt);
- need_space = pSrcItem->GetMaxStackCount() - pItem2->GetCount();
- }
+ CharacterDatabase.CommitTransaction(trans);
+ return true;
+}
+
+void Guild::_CreateDefaultGuildRanks(LocaleConstant loc)
+{
+ PreparedStatement* stmt = NULL;
- if (need_space > count)
- need_space = count;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_RANKS);
+ stmt->setUInt32(0, m_id);
+ CharacterDatabase.Execute(stmt);
- GuildItemPosCount newPosition = GuildItemPosCount(slot,need_space);
- if (!newPosition.isContainedIn(dest))
- {
- dest.push_back(newPosition);
- count -= need_space;
- }
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_BANK_RIGHTS);
+ stmt->setUInt32(0, m_id);
+ CharacterDatabase.Execute(stmt);
- return EQUIP_ERR_OK;
+ _CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_MASTER, loc), GR_RIGHT_ALL);
+ _CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_OFFICER, loc), GR_RIGHT_ALL);
+ _CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_VETERAN, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
+ _CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_MEMBER, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
+ _CreateRank(sObjectMgr.GetTrinityString(LANG_GUILD_INITIATE, loc), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
}
-uint8 Guild::_CanStoreItem_InTab(uint8 tab, GuildItemPosCountVec &dest, uint32& count, bool merge, Item* pSrcItem, uint8 skip_slot) const
+void Guild::_CreateRank(const std::string& name, uint32 rights)
{
- ASSERT(pSrcItem);
- for (uint32 j = 0; j < GUILD_BANK_MAX_SLOTS; ++j)
- {
- // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot
- if (j == skip_slot)
- continue;
-
- Item* pItem2 = m_TabListMap[tab]->Slots[j];
+ if (_GetRanksSize() >= GUILD_RANKS_MAX_COUNT)
+ return;
- // ignore move item (this slot will be empty at move)
- if (pItem2 == pSrcItem)
- pItem2 = NULL;
+ // Ranks represent sequence 0,1,2,... where 0 means guildmaster
+ uint8 newRankId = _GetRanksSize();
- // if merge skip empty, if !merge skip non-empty
- if ((pItem2 != NULL) != merge)
- continue;
+ RankInfo info(m_id, newRankId, name, rights, 0);
+ m_ranks.push_back(info);
- if (pItem2)
- {
- if (pItem2->GetEntry() == pSrcItem->GetEntry() && pItem2->GetCount() < pSrcItem->GetMaxStackCount())
- {
- uint32 need_space = pSrcItem->GetMaxStackCount() - pItem2->GetCount();
- if (need_space > count)
- need_space = count;
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ for (uint8 i = 0; i < _GetPurchasedTabsSize(); ++i)
+ {
+ // Create bank rights with default values
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_GUILD_BANK_RIGHT_DEFAULT);
+ stmt->setUInt32(0, m_id);
+ stmt->setUInt8 (1, i);
+ stmt->setUInt8 (2, newRankId);
+ trans->Append(stmt);
+ }
+ info.SaveToDB(trans);
+ CharacterDatabase.CommitTransaction(trans);
+}
- GuildItemPosCount newPosition = GuildItemPosCount(j, need_space);
- if (!newPosition.isContainedIn(dest))
- {
- dest.push_back(newPosition);
- count -= need_space;
+// Updates the number of accounts that are in the guild
+// Player may have many characters in the guild, but with the same account
+void Guild::_UpdateAccountsNumber()
+{
+ // We use a set to be sure each element will be unique
+ std::set<uint32> accountsIdSet;
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ accountsIdSet.insert(itr->second->GetAccountId());
- if (count == 0)
- return EQUIP_ERR_OK;
- }
- }
- }
- else
- {
- uint32 need_space = pSrcItem->GetMaxStackCount();
- if (need_space > count)
- need_space = count;
+ m_accountsNumber = accountsIdSet.size();
+}
- GuildItemPosCount newPosition = GuildItemPosCount(j, need_space);
- if (!newPosition.isContainedIn(dest))
- {
- dest.push_back(newPosition);
- count -= need_space;
+// Detects if player is the guild master.
+// Check both leader guid and player's rank (otherwise multiple feature with
+// multiple guild masters won't work)
+bool Guild::_IsLeader(Player* player) const
+{
+ if (player->GetGUID() == m_leaderGuid)
+ return true;
+ if (const Member* pMember = GetMember(player->GetGUID()))
+ return pMember->IsRank(GR_GUILDMASTER);
+ return false;
+}
- if (count == 0)
- return EQUIP_ERR_OK;
- }
- }
+void Guild::_DeleteBankItems(SQLTransaction& trans, bool removeItemsFromDB)
+{
+ for (uint8 tabId = 0; tabId < _GetPurchasedTabsSize(); ++tabId)
+ {
+ m_bankTabs[tabId]->Delete(trans, removeItemsFromDB);
+ delete m_bankTabs[tabId];
+ m_bankTabs[tabId] = NULL;
}
- return EQUIP_ERR_OK;
+ m_bankTabs.clear();
}
-uint8 Guild::CanStoreItem(uint8 tab, uint8 slot, GuildItemPosCountVec &dest, uint32 count, Item *pItem, bool swap) const
+bool Guild::_ModifyBankMoney(SQLTransaction& trans, const uint64& amount, bool add)
{
- sLog.outDebug("GUILD STORAGE: CanStoreItem tab = %u, slot = %u, item = %u, count = %u", tab, slot, pItem->GetEntry(), count);
+ if (add)
+ m_bankMoney += amount;
+ else
+ {
+ // Check if there is enough money in bank.
+ if (m_bankMoney < amount)
+ return false;
+ m_bankMoney -= amount;
+ }
- if (count > pItem->GetCount())
- return EQUIP_ERR_COULDNT_SPLIT_ITEMS;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_BANK_MONEY);
+ stmt->setUInt64(0, m_bankMoney);
+ stmt->setUInt32(1, m_id);
+ trans->Append(stmt);
+ return true;
+}
- if (pItem->IsSoulBound())
- return EQUIP_ERR_CANT_DROP_SOULBOUND;
+void Guild::_SetLeaderGUID(Member* pLeader)
+{
+ if (!pLeader)
+ return;
- // in specific tab
- if (tab >= m_TabListMap.size() || tab >= GUILD_BANK_MAX_TABS)
- return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG;
+ m_leaderGuid = pLeader->GetGUID();
+ pLeader->ChangeRank(GR_GUILDMASTER);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_LEADER);
+ stmt->setUInt32(0, GUID_LOPART(m_leaderGuid));
+ stmt->setUInt32(1, m_id);
+ CharacterDatabase.Execute(stmt);
+}
- // in specific slot
- if (slot != NULL_SLOT)
+void Guild::_SetRankBankMoneyPerDay(uint8 rankId, uint32 moneyPerDay)
+{
+ if (RankInfo* rankInfo = GetRankInfo(rankId))
{
- uint8 res = _CanStoreItem_InSpecificSlot(tab,slot,dest,count,swap,pItem);
- if (res != EQUIP_ERR_OK)
- return res;
+ for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (itr->second->IsRank(rankId))
+ itr->second->ResetMoneyTime();
- if (count == 0)
- return EQUIP_ERR_OK;
+ rankInfo->SetBankMoneyPerDay(moneyPerDay);
}
+}
- // not specific slot or have space for partly store only in specific slot
+void Guild::_SetRankBankTabRightsAndSlots(uint8 rankId, uint8 tabId, GuildBankRightsAndSlots rightsAndSlots, bool saveToDB)
+{
+ if (tabId >= _GetPurchasedTabsSize())
+ return;
- // search stack in tab for merge to
- if (pItem->GetMaxStackCount() > 1)
+ if (RankInfo* rankInfo = GetRankInfo(rankId))
{
- uint8 res = _CanStoreItem_InTab(tab, dest, count, true, pItem, slot);
- if (res != EQUIP_ERR_OK)
- return res;
+ for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (itr->second->IsRank(rankId))
+ itr->second->ResetTabTimes();
- if (count == 0)
- return EQUIP_ERR_OK;
+ rankInfo->SetBankTabSlotsAndRights(tabId, rightsAndSlots, saveToDB);
}
+}
- // search free slot in bag for place to
- uint8 res = _CanStoreItem_InTab(tab, dest, count, false, pItem, slot);
- if (res != EQUIP_ERR_OK)
- return res;
+inline std::string Guild::_GetRankName(uint8 rankId) const
+{
+ if (const RankInfo* rankInfo = GetRankInfo(rankId))
+ return rankInfo->GetName();
+ return "<unknown>";
+}
- if (count == 0)
- return EQUIP_ERR_OK;
+inline uint32 Guild::_GetRankRights(uint8 rankId) const
+{
+ if (const RankInfo* rankInfo = GetRankInfo(rankId))
+ return rankInfo->GetRights();
+ return 0;
+}
- return EQUIP_ERR_BANK_FULL;
+inline uint32 Guild::_GetRankBankMoneyPerDay(uint8 rankId) const
+{
+ if (const RankInfo* rankInfo = GetRankInfo(rankId))
+ return rankInfo->GetBankMoneyPerDay();
+ return 0;
}
-void Guild::SetGuildBankTabText(uint8 TabId, std::string text)
+inline uint32 Guild::_GetRankBankTabSlotsPerDay(uint8 rankId, uint8 tabId) const
{
- if (TabId >= GetPurchasedTabs())
- return;
+ if (tabId < _GetPurchasedTabsSize())
+ if (const RankInfo* rankInfo = GetRankInfo(rankId))
+ return rankInfo->GetBankTabSlotsPerDay(tabId);
+ return 0;
+}
- if (!m_TabListMap[TabId])
- return;
+inline uint8 Guild::_GetRankBankTabRights(uint8 rankId, uint8 tabId) const
+{
+ if (const RankInfo* rankInfo = GetRankInfo(rankId))
+ return rankInfo->GetBankTabRights(tabId);
+ return 0;
+}
- if (m_TabListMap[TabId]->Text == text)
- return;
+inline uint32 Guild::_GetMemberRemainingSlots(const uint64& guid, uint8 tabId) const
+{
+ if (const Member* pMember = GetMember(guid))
+ return pMember->GetBankRemainingValue(tabId, this);
+ return 0;
+}
- utf8truncate(text, 500); // DB and client size limitation
+inline uint32 Guild::_GetMemberRemainingMoney(const uint64& guid) const
+{
+ if (const Member* pMember = GetMember(guid))
+ return pMember->GetBankRemainingValue(GUILD_BANK_MAX_TABS, this);
+ return 0;
+}
- m_TabListMap[TabId]->Text = text;
+inline void Guild::_DecreaseMemberRemainingSlots(SQLTransaction& trans, const uint64& guid, uint8 tabId)
+{
+ // Remaining slots must be more then 0
+ if (uint32 remainingSlots = _GetMemberRemainingSlots(guid, tabId))
+ // Ignore guild master
+ if (remainingSlots < GUILD_WITHDRAW_SLOT_UNLIMITED)
+ if (Member* pMember = GetMember(guid))
+ pMember->DecreaseBankRemainingValue(trans, tabId, 1);
+}
- CharacterDatabase.escape_string(text);
- CharacterDatabase.PExecute("UPDATE guild_bank_tab SET TabText='%s' WHERE guildid='%u' AND TabId='%u'", text.c_str(), m_Id, uint32(TabId));
+inline bool Guild::_MemberHasTabRights(const uint64& guid, uint8 tabId, uint32 rights) const
+{
+ if (const Member* pMember = GetMember(guid))
+ {
+ // Leader always has full rights
+ if (pMember->IsRank(GR_GUILDMASTER) || m_leaderGuid == guid)
+ return true;
+ return (_GetRankBankTabRights(pMember->GetRankId(), tabId) & rights) == rights;
+ }
+ return false;
+}
- // announce
- SendGuildBankTabText(NULL,TabId);
+// Add new event log record
+inline void Guild::_LogEvent(GuildEventLogTypes eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank)
+{
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ m_eventLog->AddEvent(trans, new EventLogEntry(m_id, m_eventLog->GetNextGUID(), eventType, playerGuid1, playerGuid2, newRank));
+ CharacterDatabase.CommitTransaction(trans);
+
+ sScriptMgr.OnGuildEvent(this, uint8(eventType), playerGuid1, playerGuid2, newRank);
}
-void Guild::SendGuildBankTabText(WorldSession *session, uint8 TabId)
+// Add new bank event log record
+void Guild::_LogBankEvent(SQLTransaction& trans, GuildBankEventLogTypes eventType, uint8 tabId, uint32 lowguid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
{
- GuildBankTab const* tab = m_TabListMap[TabId];
+ if (tabId > GUILD_BANK_MAX_TABS)
+ return;
- WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1+tab->Text.size()+1);
- data << uint8(TabId);
- data << tab->Text;
+ uint8 dbTabId = tabId;
+ if (BankEventLogEntry::IsMoneyEvent(eventType))
+ {
+ tabId = GUILD_BANK_MAX_TABS;
+ dbTabId = GUILD_BANK_MONEY_LOGS_TAB;
+ }
+ LogHolder* pLog = m_bankEventLog[tabId];
+ pLog->AddEvent(trans, new BankEventLogEntry(m_id, pLog->GetNextGUID(), eventType, dbTabId, lowguid, itemOrMoney, itemStackCount, destTabId));
- if (session)
- session->SendPacket(&data);
- else
- BroadcastPacket(&data);
+ sScriptMgr.OnGuildBankEvent(this, uint8(eventType), tabId, lowguid, itemOrMoney, itemStackCount, destTabId);
}
-void Guild::SwapItems(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankTabDst, uint8 BankTabSlotDst, uint32 SplitedAmount)
+inline Item* Guild::_GetItem(uint8 tabId, uint8 slotId) const
{
- // empty operation
- if (BankTab == BankTabDst && BankTabSlot == BankTabSlotDst)
- return;
+ if (const BankTab* tab = GetBankTab(tabId))
+ return tab->GetItem(slotId);
+ return NULL;
+}
- Item *pItemSrc = GetItem(BankTab, BankTabSlot);
- if (!pItemSrc) // may prevent crash
- return;
+inline void Guild::_RemoveItem(SQLTransaction& trans, uint8 tabId, uint8 slotId)
+{
+ if (BankTab* pTab = GetBankTab(tabId))
+ pTab->SetItem(trans, slotId, NULL);
+}
+
+void Guild::_MoveItems(MoveItemData* pSrc, MoveItemData* pDest, uint32 splitedAmount)
+{
+ // 1. Initialize source item
+ if (!pSrc->InitItem())
+ return; // No source item
+ // 2. Check source item
+ if (!pSrc->CheckItem(splitedAmount))
+ return; // Source item or splited amount is invalid
+ /*
if (pItemSrc->GetCount() == 0)
{
sLog.outCrash("Guild::SwapItems: Player %s(GUIDLow: %u) tried to move item %u from tab %u slot %u to tab %u slot %u, but item %u has a stack of zero!",
- pl->GetName(), pl->GetGUIDLow(), pItemSrc->GetEntry(), BankTab, BankTabSlot, BankTabDst, BankTabSlotDst, pItemSrc->GetEntry());
+ player->GetName(), player->GetGUIDLow(), pItemSrc->GetEntry(), tabId, slotId, destTabId, destSlotId, pItemSrc->GetEntry());
//return; // Commented out for now, uncomment when it's verified that this causes a crash!!
}
+ //*/
- if (SplitedAmount >= pItemSrc->GetCount())
- SplitedAmount = 0; // no split
+ // 3. Check destination rights
+ if (!pDest->HasStoreRights(pSrc))
+ return; // Player has no rights to store item in destination
- Item *pItemDst = GetItem(BankTabDst, BankTabSlotDst);
+ // 4. Check source withdraw rights
+ if (!pSrc->HasWithdrawRights(pDest))
+ return; // Player has no rights to withdraw items from source
- if (BankTab != BankTabDst)
+ // 5. Check split
+ if (splitedAmount)
{
- // check dest pos rights (if different tabs)
- if (!IsMemberHaveRights(pl->GetGUIDLow(), BankTabDst, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
- return;
+ // 5.1. Clone source item
+ if (!pSrc->CloneItem(splitedAmount))
+ return; // Item could not be cloned
- // check source pos rights (if different tabs)
- uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
- if (remRight <= 0)
- return;
+ // 5.2. Move splited item to destination
+ _DoItemsMove(pSrc, pDest, true, splitedAmount);
}
-
- if (SplitedAmount)
- { // Bank -> Bank item split (in empty or non empty slot
- GuildItemPosCountVec dest;
- uint8 msg = CanStoreItem(BankTabDst, BankTabSlotDst, dest, SplitedAmount, pItemSrc, false);
- if (msg != EQUIP_ERR_OK)
- {
- pl->SendEquipError(msg, pItemSrc, NULL);
- return;
- }
-
- Item *pNewItem = pItemSrc->CloneItem(SplitedAmount);
- if (!pNewItem)
- {
- pl->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItemSrc, NULL);
- return;
- }
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), SplitedAmount, BankTabDst);
-
- pl->ItemRemovedQuestCheck(pItemSrc->GetEntry(), SplitedAmount);
- pItemSrc->SetCount(pItemSrc->GetCount() - SplitedAmount);
- pItemSrc->FSetState(ITEM_CHANGED);
- pItemSrc->SaveToDB(trans); // not in inventory and can be save standalone
- StoreItem(BankTabDst, dest, pNewItem, trans);
- CharacterDatabase.CommitTransaction(trans);
- }
- else // non split
+ else // 6. No split
{
- GuildItemPosCountVec gDest;
- uint8 msg = CanStoreItem(BankTabDst, BankTabSlotDst, gDest, pItemSrc->GetCount(), pItemSrc, false);
- if (msg == EQUIP_ERR_OK) // merge to
+ // 6.1. Try to merge items in destination (pDest->GetItem() == NULL)
+ if (!_DoItemsMove(pSrc, pDest, false)) // Item could not be merged
{
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst);
-
- RemoveItem(BankTab, BankTabSlot, trans);
- StoreItem(BankTabDst, gDest, pItemSrc, trans);
- CharacterDatabase.CommitTransaction(trans);
- }
- else // swap
- {
- gDest.clear();
- msg = CanStoreItem(BankTabDst, BankTabSlotDst, gDest, pItemSrc->GetCount(), pItemSrc, true);
- if (msg != EQUIP_ERR_OK)
- {
- pl->SendEquipError(msg, pItemSrc, NULL);
- return;
- }
-
- GuildItemPosCountVec gSrc;
- msg = CanStoreItem(BankTab, BankTabSlot, gSrc, pItemDst->GetCount(), pItemDst, true);
- if (msg != EQUIP_ERR_OK)
- {
- pl->SendEquipError(msg, pItemDst, NULL);
+ // 6.2. Try to swap items
+ // 6.2.1. Initialize destination item
+ if (!pDest->InitItem())
return;
- }
- if (BankTab != BankTabDst)
- {
- // check source pos rights (item swapped to src)
- if (!IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
- return;
-
- // check dest pos rights (item swapped to src)
- uint32 remRightDst = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTabDst);
- if (remRightDst <= 0)
- return;
- }
+ // 6.2.2. Check rights to store item in source (opposite direction)
+ if (!pSrc->HasStoreRights(pDest))
+ return; // Player has no rights to store item in source (opposite direction)
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst);
- LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, BankTabDst, pl->GetGUIDLow(), pItemDst->GetEntry(), pItemDst->GetCount(), BankTab);
+ if (!pDest->HasWithdrawRights(pSrc))
+ return; // Player has no rights to withdraw item from destination (opposite direction)
- RemoveItem(BankTab, BankTabSlot, trans);
- RemoveItem(BankTabDst, BankTabSlotDst, trans);
- StoreItem(BankTab, gSrc, pItemDst, trans);
- StoreItem(BankTabDst, gDest, pItemSrc, trans);
- CharacterDatabase.CommitTransaction(trans);
+ // 6.2.3. Swap items (pDest->GetItem() != NULL)
+ _DoItemsMove(pSrc, pDest, true);
}
}
- DisplayGuildBankContentUpdate(BankTab,BankTabSlot,BankTab == BankTabDst ? BankTabSlotDst : -1);
- if (BankTab != BankTabDst)
- DisplayGuildBankContentUpdate(BankTabDst,BankTabSlotDst);
+ // 7. Send changes
+ _SendBankContentUpdate(pSrc, pDest);
}
-void Guild::MoveFromBankToChar(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 PlayerBag, uint8 PlayerSlot, uint32 SplitedAmount)
+bool Guild::_DoItemsMove(MoveItemData* pSrc, MoveItemData* pDest, bool sendError, uint32 splitedAmount)
{
- Item *pItemBank = GetItem(BankTab, BankTabSlot);
- Item *pItemChar = pl->GetItemByPos(PlayerBag, PlayerSlot);
-
- if (!pItemBank) // Problem to get bank item
- return;
+ Item* pDestItem = pDest->GetItem();
+ bool swap = (pDestItem != NULL);
- if (SplitedAmount > pItemBank->GetCount())
- return; // cheating?
- else if (SplitedAmount == pItemBank->GetCount())
- SplitedAmount = 0; // no split
+ Item* pSrcItem = pSrc->GetItem(splitedAmount);
+ // 1. Can store source item in destination
+ if (!pDest->CanStore(pSrcItem, swap, sendError))
+ return false;
- if (SplitedAmount)
- { // Bank -> Char split to slot (patly move)
- Item *pNewItem = pItemBank->CloneItem(SplitedAmount);
- if (!pNewItem)
- {
- pl->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItemBank, NULL);
- return;
- }
+ // 2. Can store destination item in source
+ if (swap)
+ if (!pSrc->CanStore(pDestItem, true, true))
+ return false;
- ItemPosCountVec dest;
- uint8 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, dest, pNewItem, false);
- if (msg != EQUIP_ERR_OK)
- {
- pl->SendEquipError(msg, pNewItem, NULL);
- delete pNewItem;
- return;
- }
+ // GM LOG (TODO: move to scripts)
+ pDest->LogAction(pSrc);
+ if (swap)
+ pSrc->LogAction(pDest);
- // check source pos rights (item moved to inventory)
- uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
- if (remRight <= 0)
- {
- delete pNewItem;
- return;
- }
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ // 3. Log bank events
+ pDest->LogBankEvent(trans, pSrc, pSrcItem->GetCount());
+ if (swap)
+ pSrc->LogBankEvent(trans, pDest, pDestItem->GetCount());
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), SplitedAmount);
+ // 4. Remove item from source
+ pSrc->RemoveItem(trans, pDest, splitedAmount);
- pItemBank->SetCount(pItemBank->GetCount()-SplitedAmount);
- pItemBank->FSetState(ITEM_CHANGED);
- pItemBank->SaveToDB(trans); // not in inventory and can be save standalone
- pl->MoveItemToInventory(dest, pNewItem, true);
- pl->SaveInventoryAndGoldToDB(trans);
+ // 5. Remove item from destination
+ if (swap)
+ pDest->RemoveItem(trans, pSrc);
- MemberItemWithdraw(BankTab, pl->GetGUIDLow(), trans);
- CharacterDatabase.CommitTransaction(trans);
- }
- else // Bank -> Char swap with slot (move)
- {
- ItemPosCountVec dest;
- uint8 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, dest, pItemBank, false);
- if (msg == EQUIP_ERR_OK) // merge case
- {
- // check source pos rights (item moved to inventory)
- uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
- if (remRight <= 0)
- return;
+ // 6. Store item in destination
+ pDest->StoreItem(trans, pSrcItem);
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
+ // 7. Store item in source
+ if (swap)
+ pSrc->StoreItem(trans, pDestItem);
- RemoveItem(BankTab, BankTabSlot, trans);
- pl->MoveItemToInventory(dest, pItemBank, true);
- pl->SaveInventoryAndGoldToDB(trans);
+ CharacterDatabase.CommitTransaction(trans);
+ return true;
+}
- MemberItemWithdraw(BankTab, pl->GetGUIDLow(), trans);
- CharacterDatabase.CommitTransaction(trans);
- }
- else // Bank <-> Char swap items
+void Guild::_SendBankContent(WorldSession *session, uint8 tabId) const
+{
+ const uint64& guid = session->GetPlayer()->GetGUID();
+ if (_MemberHasTabRights(guid, tabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ if (const BankTab* pTab = GetBankTab(tabId))
{
- // check source pos rights (item swapped to bank)
- if (!IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
- return;
-
- if (pItemChar)
- {
- if (!pItemChar->CanBeTraded())
- {
- pl->SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL);
- return;
- }
- }
+ WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
- ItemPosCountVec iDest;
- msg = pl->CanStoreItem(PlayerBag, PlayerSlot, iDest, pItemBank, true);
- if (msg != EQUIP_ERR_OK)
- {
- pl->SendEquipError(msg, pItemBank, NULL);
- return;
- }
+ data << uint64(m_bankMoney);
+ data << uint8(tabId);
+ data << uint32(_GetMemberRemainingSlots(guid, tabId));
+ data << uint8(0); // Tell client that there's no tab info in this packet
- GuildItemPosCountVec gDest;
- if (pItemChar)
- {
- msg = CanStoreItem(BankTab, BankTabSlot, gDest, pItemChar->GetCount(), pItemChar, true);
- if (msg != EQUIP_ERR_OK)
- {
- pl->SendEquipError(msg, pItemChar, NULL);
- return;
- }
- }
+ pTab->WritePacket(data);
- // check source pos rights (item moved to inventory)
- uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
- if (remRight <= 0)
- return;
+ session->SendPacket(&data);
- if (pItemChar)
- {
- // logging item move to bank
- if (pl->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getBoolConfig(CONFIG_GM_LOG_TRADE))
- {
- sLog.outCommand(pl->GetSession()->GetAccountId(), "GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u)",
- pl->GetName(), pl->GetSession()->GetAccountId(),
- pItemChar->GetProto()->Name1, pItemChar->GetEntry(), pItemChar->GetCount(),
- m_Id);
- }
- }
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
- if (pItemChar)
- LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
+ }
+}
- RemoveItem(BankTab, BankTabSlot, trans);
- if (pItemChar)
- {
- pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
- pItemChar->DeleteFromInventoryDB(trans);
- }
+void Guild::_SendBankMoneyUpdate(WorldSession *session) const
+{
+ WorldPacket data(SMSG_GUILD_BANK_LIST, 8 + 1 + 4 + 1 + 1);
- if (pItemChar)
- StoreItem(BankTab, gDest, pItemChar, trans);
- pl->MoveItemToInventory(iDest, pItemBank, true);
- pl->SaveInventoryAndGoldToDB(trans);
+ data << uint64(m_bankMoney);
+ data << uint8(0); // tabId, default 0
+ data << uint32(_GetMemberRemainingSlots(session->GetPlayer()->GetGUID(), 0));
+ data << uint8(0); // Tell that there's no tab info in this packet
+ data << uint8(0); // No items
+ BroadcastPacket(&data);
- MemberItemWithdraw(BankTab, pl->GetGUIDLow(), trans);
- CharacterDatabase.CommitTransaction(trans);
- }
- }
- DisplayGuildBankContentUpdate(BankTab,BankTabSlot);
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
}
-void Guild::MoveFromCharToBank(Player * pl, uint8 PlayerBag, uint8 PlayerSlot, uint8 BankTab, uint8 BankTabSlot, uint32 SplitedAmount)
+void Guild::_SendBankContentUpdate(MoveItemData* pSrc, MoveItemData* pDest) const
{
- Item *pItemBank = GetItem(BankTab, BankTabSlot);
- Item *pItemChar = pl->GetItemByPos(PlayerBag, PlayerSlot);
+ ASSERT(pSrc->IsBank() || pDest->IsBank());
- if (!pItemChar) // Problem to get item from player
- return;
-
- // prevent storing non-empty bags
- if (pItemChar && pItemChar->IsBag() && !((Bag*)pItemChar)->IsEmpty())
+ uint8 tabId;
+ SlotIds slots;
+ if (pSrc->IsBank()) // B ->
{
- pl->SendEquipError(EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS, pItemChar, NULL);
- return;
+ tabId = pSrc->GetContainer();
+ slots.insert(pSrc->GetSlotId());
+ if (pDest->IsBank()) // B -> B
+ {
+ // Same tab - add destination slots to collection
+ if (pDest->GetContainer() == pSrc->GetContainer())
+ pDest->CopySlots(slots);
+ else // Different tabs - send second message
+ {
+ SlotIds destSlots;
+ pDest->CopySlots(destSlots);
+ _SendBankContentUpdate(pDest->GetContainer(), destSlots);
+ }
+ }
}
-
- if (!pItemChar->CanBeTraded())
+ else if (pDest->IsBank()) // C -> B
{
- pl->SendEquipError(EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL);
- return;
+ tabId = pDest->GetContainer();
+ pDest->CopySlots(slots);
}
+ _SendBankContentUpdate(tabId, slots);
+}
- // check source pos rights (item moved to bank)
- if (!IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
- return;
-
- if (SplitedAmount > pItemChar->GetCount())
- return; // cheating?
- else if (SplitedAmount == pItemChar->GetCount())
- SplitedAmount = 0; // no split
-
- if (SplitedAmount)
- { // Char -> Bank split to empty or non-empty slot (partly move)
- GuildItemPosCountVec dest;
- uint8 msg = CanStoreItem(BankTab, BankTabSlot, dest, SplitedAmount, pItemChar, false);
- if (msg != EQUIP_ERR_OK)
- {
- pl->SendEquipError(msg, pItemChar, NULL);
- return;
- }
-
- Item *pNewItem = pItemChar->CloneItem(SplitedAmount);
- if (!pNewItem)
- {
- pl->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItemChar, NULL);
- return;
- }
-
- // logging item move to bank (before items merge
- if (pl->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getBoolConfig(CONFIG_GM_LOG_TRADE))
- {
- sLog.outCommand(pl->GetSession()->GetAccountId(), "GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u)",
- pl->GetName(), pl->GetSession()->GetAccountId(),
- pItemChar->GetProto()->Name1, pItemChar->GetEntry(), SplitedAmount,m_Id);
- }
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), SplitedAmount);
-
- pl->ItemRemovedQuestCheck(pItemChar->GetEntry(), SplitedAmount);
- pItemChar->SetCount(pItemChar->GetCount()-SplitedAmount);
- pItemChar->SetState(ITEM_CHANGED, pl);
- pl->SaveInventoryAndGoldToDB(trans);
- StoreItem(BankTab, dest, pNewItem, trans);
- CharacterDatabase.CommitTransaction(trans);
-
- DisplayGuildBankContentUpdate(BankTab, dest);
- }
- else // Char -> Bank swap with empty or non-empty (move)
+void Guild::_SendBankContentUpdate(uint8 tabId, SlotIds slots) const
+{
+ if (const BankTab* pTab = GetBankTab(tabId))
{
- GuildItemPosCountVec dest;
- uint8 msg = CanStoreItem(BankTab, BankTabSlot, dest, pItemChar->GetCount(), pItemChar, false);
- if (msg == EQUIP_ERR_OK) // merge
- {
- // logging item move to bank
- if (pl->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getBoolConfig(CONFIG_GM_LOG_TRADE))
- {
- sLog.outCommand(pl->GetSession()->GetAccountId(), "GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u)",
- pl->GetName(), pl->GetSession()->GetAccountId(),
- pItemChar->GetProto()->Name1, pItemChar->GetEntry(), pItemChar->GetCount(),
- m_Id);
- }
+ WorldPacket data(SMSG_GUILD_BANK_LIST, 1200);
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
+ data << uint64(m_bankMoney);
+ data << uint8(tabId);
- pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
- pItemChar->DeleteFromInventoryDB(trans);
+ size_t rempos = data.wpos();
+ data << uint32(0); // Item withdraw amount, will be filled later
+ data << uint8(0); // Tell client that there's no tab info in this packet
- StoreItem(BankTab, dest, pItemChar, trans);
- pl->SaveInventoryAndGoldToDB(trans);
- CharacterDatabase.CommitTransaction(trans);
+ data << uint8(slots.size());
+ for (uint8 slotId = 0; slotId < GUILD_BANK_MAX_SLOTS; ++slotId)
+ if (slots.find(slotId) != slots.end())
+ pTab->WriteSlotPacket(data, slotId);
- DisplayGuildBankContentUpdate(BankTab, dest);
- }
- else // Char <-> Bank swap items (posible NULL bank item)
- {
- ItemPosCountVec iDest;
- if (pItemBank)
- {
- msg = pl->CanStoreItem(PlayerBag, PlayerSlot, iDest, pItemBank, true);
- if (msg != EQUIP_ERR_OK)
+ for (Members::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
+ if (_MemberHasTabRights(itr->second->GetGUID(), tabId, GUILD_BANK_RIGHT_VIEW_TAB))
+ if (Player *player = itr->second->FindPlayer())
{
- pl->SendEquipError(msg, pItemBank, NULL);
- return;
+ data.put<uint32>(rempos, uint32(_GetMemberRemainingSlots(player->GetGUID(), tabId)));
+ player->GetSession()->SendPacket(&data);
}
- }
- GuildItemPosCountVec gDest;
- msg = CanStoreItem(BankTab, BankTabSlot, gDest, pItemChar->GetCount(), pItemChar, true);
- if (msg != EQUIP_ERR_OK)
- {
- pl->SendEquipError(msg, pItemChar, NULL);
- return;
- }
-
- if (pItemBank)
- {
- // check bank pos rights (item swapped with inventory)
- uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
- if (remRight <= 0)
- return;
- }
-
- // logging item move to bank
- if (pl->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getBoolConfig(CONFIG_GM_LOG_TRADE))
- {
- sLog.outCommand(pl->GetSession()->GetAccountId(), "GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u)",
- pl->GetName(), pl->GetSession()->GetAccountId(),
- pItemChar->GetProto()->Name1, pItemChar->GetEntry(), pItemChar->GetCount(),
- m_Id);
- }
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- if (pItemBank)
- LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
- LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
-
- pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
- pItemChar->DeleteFromInventoryDB(trans);
- if (pItemBank)
- RemoveItem(BankTab, BankTabSlot, trans);
-
- StoreItem(BankTab,gDest,pItemChar, trans);
- if (pItemBank)
- pl->MoveItemToInventory(iDest, pItemBank, true);
- pl->SaveInventoryAndGoldToDB(trans);
- if (pItemBank)
- MemberItemWithdraw(BankTab, pl->GetGUIDLow(), trans);
- CharacterDatabase.CommitTransaction(trans);
-
- DisplayGuildBankContentUpdate(BankTab, gDest);
- }
+ sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
}
}
-void Guild::BroadcastEvent(GuildEvents event, uint64 guid, uint8 strCount, std::string str1, std::string str2, std::string str3)
+void Guild::_BroadcastEvent(GuildEvents guildEvent, const uint64& guid, const char* param1, const char* param2, const char* param3) const
{
- WorldPacket data(SMSG_GUILD_EVENT, 1+1+(guid ? 8 : 0));
- data << uint8(event);
- data << uint8(strCount);
+ uint8 count = !param3 ? (!param2 ? (!param1 ? 0 : 1) : 2) : 3;
- switch(strCount)
- {
- case 0:
- break;
- case 1:
- data << str1;
- break;
- case 2:
- data << str1 << str2;
- break;
- case 3:
- data << str1 << str2 << str3;
- break;
- default:
- sLog.outError("Guild::BroadcastEvent: incorrect strings count %u!", strCount);
- break;
- }
+ WorldPacket data(SMSG_GUILD_EVENT, 1 + 1 + count + (guid ? 8 : 0));
+ data << uint8(guildEvent);
+ data << uint8(count);
+
+ if (param3)
+ data << param1 << param2 << param3;
+ else if (param2)
+ data << param1 << param2;
+ else if (param1)
+ data << param1;
if (guid)
data << uint64(guid);
@@ -2155,35 +2753,3 @@ void Guild::BroadcastEvent(GuildEvents event, uint64 guid, uint8 strCount, std::
sLog.outDebug("WORLD: Sent SMSG_GUILD_EVENT");
}
-
-void Guild::DeleteGuildBankItems(SQLTransaction& trans, bool alsoInDB /*= false*/)
-{
- for (size_t i = 0; i < m_TabListMap.size(); ++i)
- {
- for (uint8 j = 0; j < GUILD_BANK_MAX_SLOTS; ++j)
- {
- if (Item*& pItem = m_TabListMap[i]->Slots[j])
- {
- pItem->RemoveFromWorld();
-
- if (alsoInDB)
- pItem->DeleteFromDB(trans);
-
- delete pItem;
- pItem = NULL;
- }
- }
- delete m_TabListMap[i];
- m_TabListMap[i] = NULL;
- }
- m_TabListMap.clear();
-}
-
-bool GuildItemPosCount::isContainedIn(GuildItemPosCountVec const &vec) const
-{
- for (GuildItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end(); ++itr)
- if (itr->Slot == this->Slot)
- return true;
-
- return false;
-}
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index 5ebb646cd73..311c0e4bcb8 100755
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -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)
-{
- switch(Index)
- {
- 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
+////////////////////////////////////////////////////////////////////////////////////////////
+// Emblem info
+class EmblemInfo
{
- uint8 EventType;
- uint32 PlayerGuid1;
- uint32 PlayerGuid2;
- uint8 NewRank;
- uint64 TimeStamp;
+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;
};
-struct GuildBankEventLogEntry
+// Structure for storing guild bank rights and remaining slots together.
+struct GuildBankRightsAndSlots
{
- uint8 EventType;
- uint32 PlayerGuid;
- uint32 ItemOrMoney;
- uint16 ItemStackCount;
- uint8 DestTabId;
- uint64 TimeStamp;
-
- bool isMoneyEvent()
+ 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()
{
- return EventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
- EventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
- EventType == GUILD_BANK_LOG_REPAIR_MONEY;
+ rights = GUILD_BANK_RIGHT_FULL;
+ slots = GUILD_WITHDRAW_SLOT_UNLIMITED;
}
+
+ uint8 rights;
+ uint32 slots;
};
+typedef std::vector <GuildBankRightsAndSlots> GuildBankRightsAndSlotsVec;
+
+typedef std::set <uint8> SlotIds;
-struct GuildBankTab
+class Guild
{
- GuildBankTab() { memset(Slots, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*)); }
+private:
+ // Class representing guild member
+ class Member
+ {
+ struct RemainingValue
+ {
+ RemainingValue() : value(0), resetTime(0) { }
- Item* Slots[GUILD_BANK_MAX_SLOTS];
- std::string Name;
- std::string Icon;
- std::string Text;
-};
+ uint32 value;
+ uint32 resetTime;
+ };
-struct GuildItemPosCount
-{
- GuildItemPosCount(uint8 _slot, uint32 _count) : Slot(_slot), Count(_count) {}
+ public:
+ Member(uint32 guildId, const uint64& guid, uint8 rankId) : m_guildId(guildId), m_guid(guid), m_logoutTime(::time(NULL)), m_rankId(rankId) { }
- bool isContainedIn(std::vector<GuildItemPosCount> const& vec) const;
+ void SetStats(Player* player);
+ void SetStats(const std::string& name, uint8 level, uint8 _class, uint32 zoneId, uint32 accountId);
+ bool CheckStats() const;
- uint8 Slot;
- uint32 Count;
-};
-typedef std::vector<GuildItemPosCount> GuildItemPosCountVec;
+ void SetPublicNote(const std::string& publicNote);
+ void SetOfficerNote(const std::string& officerNote);
-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];
-};
+ bool LoadFromDB(Field* fields);
+ void SaveToDB(SQLTransaction& trans) const;
+ void WritePacket(WorldPacket& data) const;
-struct RankInfo
-{
- RankInfo(const std::string& _name, uint32 _rights, uint32 _money) : Name(_name), Rights(_rights), BankMoneyPerDay(_money)
+ 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; }
+
+ void ChangeRank(uint8 newRank);
+
+ 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 DecreaseBankRemainingValue(SQLTransaction& trans, uint8 tabId, uint32 amount);
+ uint32 GetBankRemainingValue(uint8 tabId, const Guild* guild) const;
+
+ void ResetTabTimes();
+ void ResetMoneyTime();
+
+ inline Player* FindPlayer() const { return sObjectMgr.GetPlayer(m_guid); }
+
+ private:
+ 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;
+
+ RemainingValue m_bankRemaining[GUILD_BANK_MAX_TABS + 1];
+ };
+
+ // Base class for event entries
+ class LogEntry
{
- for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- {
- TabRight[i] = 0;
- TabSlotPerDay[i] = 0;
- }
- }
+ 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() { }
- std::string Name;
- uint32 Rights;
- uint32 BankMoneyPerDay;
- uint32 TabRight[GUILD_BANK_MAX_TABS];
- uint32 TabSlotPerDay[GUILD_BANK_MAX_TABS];
-};
+ uint32 GetGUID() const { return m_guid; }
-class Guild
-{
- friend class ObjectMgr;
+ 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:
- Guild();
- ~Guild();
-
- bool Create(Player* leader, std::string gname);
- void CreateDefaultGuildRanks(LocaleConstant locale_idx);
- void Disband();
-
- void DeleteGuildBankItems(SQLTransaction& trans, bool alsoInDB = false);
- typedef std::map<uint32, MemberSlot> MemberList;
- typedef std::vector<RankInfo> RankList;
-
- 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; }
-
- time_t GetCreatedDate() const { return m_CreatedDate; }
-
- 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 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; }
-
- 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);
-
- uint32 GetMemberSize() const { return members.size(); }
- uint32 GetAccountsNumber() const { return m_accountsNumber; }
-
- 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)
+ 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)
{
- 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);
+ return
+ eventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
+ eventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
+ eventType == GUILD_BANK_LOG_REPAIR_MONEY;
}
- 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(); }
+ 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) { }
- void SetRankName(uint32 rankId, std::string name);
- void SetRankRights(uint32 rankId, uint32 rights);
- bool HasRankRight(uint32 rankId, uint32 right)
+ ~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
{
- return ((GetRankRights(rankId) & right) != GR_RIGHT_EMPTY) ? true : false;
+ if (tabId < GUILD_BANK_MAX_TABS)
+ return m_rankId == GR_GUILDMASTER ? GUILD_WITHDRAW_SLOT_UNLIMITED : m_bankTabRightsAndSlots[tabId].slots;
+ return 0;
}
- int32 GetRank(uint32 LowGuid);
- bool IsMember(uint32 LowGuid)
+ 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)
{
- return (members.find(LowGuid) != members.end());
+ memset(m_items, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*));
}
- MemberSlot* GetMemberSlot(const std::string& name, uint64& guid)
+
+ 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
{
- for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
- {
- if (itr->second.Name == name)
- {
- guid = itr->first;
- return &itr->second;
- }
- }
- return NULL;
+ data << m_name;
+ data << m_icon;
}
- 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);
+ void SetInfo(const std::string& name, const std::string& icon);
+ void SetText(const std::string& text);
+ void SendText(const Guild* pGuild, WorldSession* session) const;
- protected:
- void AddRank(const std::string& name,uint32 rights,uint32 money);
+ inline Item* GetItem(uint8 slotId) const { return slotId < GUILD_BANK_MAX_SLOTS ? m_items[slotId] : NULL; }
+ bool SetItem(SQLTransaction& trans, uint8 slotId, Item* pItem);
- uint32 m_Id;
- std::string m_Name;
- uint64 m_LeaderGuid;
- std::string MOTD;
- std::string GINFO;
- time_t m_CreatedDate;
+ private:
+ uint32 m_guildId;
+ uint8 m_tabId;
- uint32 m_EmblemStyle;
- uint32 m_EmblemColor;
- uint32 m_BorderStyle;
- uint32 m_BorderColor;
- uint32 m_BackgroundColor;
- uint32 m_accountsNumber;
+ Item* m_items[GUILD_BANK_MAX_SLOTS];
+ std::string m_name;
+ std::string m_icon;
+ std::string m_text;
+ };
- RankList m_Ranks;
+ // 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);
+ };
- MemberList members;
+ 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;
- typedef std::vector<GuildBankTab*> TabListMap;
- TabListMap m_TabListMap;
+ protected:
+ uint8 _CanStore(Item* pItem, bool swap);
- /** 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];
+ 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);
+ }
- uint32 m_GuildEventLogNextGuid;
- uint32 m_GuildBankEventLogNextGuid_Money;
- uint32 m_GuildBankEventLogNextGuid_Item[GUILD_BANK_MAX_TABS];
+ // 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;
- uint64 m_GuildBankMoney;
+ 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);
+ }
- 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);
-
- // 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);
+ // 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
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 5f49e7e60a7..2f4601c493d 100755
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -2505,14 +2505,8 @@ enum PetDiet
#define CHAIN_SPELL_JUMP_RADIUS 10
-// Max values for Guild & Guild Bank
-#define GUILD_BANK_MAX_TABS 6 // send by client for money log also
-#define GUILD_BANK_MAX_SLOTS 98
-#define GUILD_BANK_MAX_LOGS 25
-#define GUILD_BANK_MONEY_LOGS_TAB 100 // used for money log in DB
+#define GUILD_BANKLOG_MAX_RECORDS 25
#define GUILD_EVENTLOG_MAX_RECORDS 100
-#define GUILD_RANKS_MIN_COUNT 5
-#define GUILD_RANKS_MAX_COUNT 10
enum AiReaction
{
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 562e6aa6f7d..9fcf084ca06 100755
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1076,6 +1076,7 @@ bool ScriptMgr::OnCriteriaCheck(AchievementCriteriaData const* data, Player* sou
return tmpscript->OnCheck(source, target);
}
+// Player
void ScriptMgr::OnPVPKill(Player *killer, Player *killed)
{
FOREACH_SCRIPT(PlayerScript)->OnPVPKill(killer, killed);
@@ -1196,7 +1197,8 @@ void ScriptMgr::OnPlayerDelete(uint64 guid)
FOREACH_SCRIPT(PlayerScript)->OnDelete(guid);
}
-void ScriptMgr::OnGuildAddMember(Guild *guild, Player *player, uint32& plRank)
+// Guild
+void ScriptMgr::OnGuildAddMember(Guild *guild, Player *player, uint8& plRank)
{
FOREACH_SCRIPT(GuildScript)->OnAddMember(guild, player, plRank);
}
@@ -1206,14 +1208,19 @@ void ScriptMgr::OnGuildRemoveMember(Guild *guild, Player *player, bool isDisband
FOREACH_SCRIPT(GuildScript)->OnRemoveMember(guild, player, isDisbanding, isKicked);
}
-void ScriptMgr::OnGuildMOTDChanged(Guild *guild, std::string newMotd)
+void ScriptMgr::OnGuildMOTDChanged(Guild *guild, const std::string& newMotd)
{
FOREACH_SCRIPT(GuildScript)->OnMOTDChanged(guild, newMotd);
}
-void ScriptMgr::OnGuildInfoChanged(Guild *guild, std::string newGInfo)
+void ScriptMgr::OnGuildInfoChanged(Guild *guild, const std::string& newInfo)
{
- FOREACH_SCRIPT(GuildScript)->OnGInfoChanged(guild, newGInfo);
+ FOREACH_SCRIPT(GuildScript)->OnInfoChanged(guild, newInfo);
+}
+
+void ScriptMgr::OnGuildCreate(Guild *guild, Player* leader, const std::string& name)
+{
+ FOREACH_SCRIPT(GuildScript)->OnCreate(guild, leader, name);
}
void ScriptMgr::OnGuildDisband(Guild *guild)
@@ -1221,6 +1228,33 @@ void ScriptMgr::OnGuildDisband(Guild *guild)
FOREACH_SCRIPT(GuildScript)->OnDisband(guild);
}
+void ScriptMgr::OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint32 &amount, bool isRepair)
+{
+ FOREACH_SCRIPT(GuildScript)->OnMemberWitdrawMoney(guild, player, amount, isRepair);
+}
+
+void ScriptMgr::OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount)
+{
+ FOREACH_SCRIPT(GuildScript)->OnMemberDepositMoney(guild, player, amount);
+}
+
+void ScriptMgr::OnGuildItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
+ bool isDestBank, uint8 destContainer, uint8 destSlotId)
+{
+ FOREACH_SCRIPT(GuildScript)->OnItemMove(guild, player, pItem, isSrcBank, srcContainer, srcSlotId, isDestBank, destContainer, destSlotId);
+}
+
+void ScriptMgr::OnGuildEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank)
+{
+ FOREACH_SCRIPT(GuildScript)->OnEvent(guild, eventType, playerGuid1, playerGuid2, newRank);
+}
+
+void ScriptMgr::OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId)
+{
+ FOREACH_SCRIPT(GuildScript)->OnBankEvent(guild, eventType, tabId, playerGuid, itemOrMoney, itemStackCount, destTabId);
+}
+
+// Group
void ScriptMgr::OnGroupAddMember(Group* group, uint64 guid)
{
ASSERT(group);
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 2847e55a687..eb20e28f0cc 100755
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -725,11 +725,18 @@ class GuildScript : public ScriptObject
bool IsDatabaseBound() const { return false; }
- virtual void OnAddMember(Guild* /*guild*/, Player* /*player*/, uint32& /*plRank*/) { }
+ virtual void OnAddMember(Guild* /*guild*/, Player* /*player*/, uint8& /*plRank*/) { }
virtual void OnRemoveMember(Guild* /*guild*/, Player* /*player*/, bool /*isDisbanding*/, bool /*isKicked*/) { }
- virtual void OnMOTDChanged(Guild* /*guild*/, std::string /*newMotd*/) { }
- virtual void OnGInfoChanged(Guild* /*guild*/, std::string /*newGInfo*/) { }
+ virtual void OnMOTDChanged(Guild* /*guild*/, const std::string& /*newMotd*/) { }
+ virtual void OnInfoChanged(Guild* /*guild*/, const std::string& /*newInfo*/) { }
+ virtual void OnCreate(Guild* /*guild*/, Player* /*leader*/, const std::string& /*name*/) { }
virtual void OnDisband(Guild* /*guild*/) { }
+ virtual void OnMemberWitdrawMoney(Guild* /*guild*/, Player* /*player*/, uint32& /*amount*/, bool /*isRepair*/) { }
+ virtual void OnMemberDepositMoney(Guild* /*guild*/, Player* /*player*/, uint32& /*amount*/) { }
+ virtual void OnItemMove(Guild* /*guild*/, Player* /*player*/, Item* /*pItem*/, bool /*isSrcBank*/, uint8 /*srcContainer*/, uint8 /*srcSlotId*/,
+ bool /*isDestBank*/, uint8 /*destContainer*/, uint8 /*destSlotId*/) { }
+ virtual void OnEvent(Guild* /*guild*/, uint8 /*eventType*/, uint32 /*playerGuid1*/, uint32 /*playerGuid2*/, uint8 /*newRank*/) { }
+ virtual void OnBankEvent(Guild* /*guild*/, uint8 /*eventType*/, uint8 /*tabId*/, uint32 /*playerGuid*/, uint32 /*itemOrMoney*/, uint16 /*itemStackCount*/, uint8 /*destTabId*/) { }
};
class GroupScript : public ScriptObject
@@ -943,11 +950,18 @@ class ScriptMgr
void OnPlayerDelete(uint64 guid);
public: /* GuildScript */
- void OnGuildAddMember(Guild *guild, Player *player, uint32& plRank);
+ void OnGuildAddMember(Guild *guild, Player *player, uint8& plRank);
void OnGuildRemoveMember(Guild *guild, Player *player, bool isDisbanding, bool isKicked);
- void OnGuildMOTDChanged(Guild *guild, std::string newMotd);
- void OnGuildInfoChanged(Guild *guild, std::string newGInfo);
+ void OnGuildMOTDChanged(Guild *guild, const std::string& newMotd);
+ void OnGuildInfoChanged(Guild *guild, const std::string& newInfo);
+ void OnGuildCreate(Guild *guild, Player* leader, const std::string& name);
void OnGuildDisband(Guild *guild);
+ void OnGuildMemberWitdrawMoney(Guild* guild, Player* player, uint32 &amount, bool isRepair);
+ void OnGuildMemberDepositMoney(Guild* guild, Player* player, uint32 &amount);
+ void OnGuildItemMove(Guild* guild, Player* player, Item* pItem, bool isSrcBank, uint8 srcContainer, uint8 srcSlotId,
+ bool isDestBank, uint8 destContainer, uint8 destSlotId);
+ void OnGuildEvent(Guild* guild, uint8 eventType, uint32 playerGuid1, uint32 playerGuid2, uint8 newRank);
+ void OnGuildBankEvent(Guild* guild, uint8 eventType, uint8 tabId, uint32 playerGuid, uint32 itemOrMoney, uint16 itemStackCount, uint8 destTabId);
public: /* GroupScript */
void OnGroupAddMember(Group* group, uint64 guid);
diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
index 7593fc96c63..3a3a23cc4ec 100755
--- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp
@@ -751,24 +751,12 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
if (pCurrChar->GetGuildId() != 0)
{
- Guild* guild = sObjectMgr.GetGuildById(pCurrChar->GetGuildId());
- if (guild)
- {
- data.Initialize(SMSG_GUILD_EVENT, (1+1+guild->GetMOTD().size()+1));
- data << uint8(GE_MOTD);
- data << uint8(1);
- data << guild->GetMOTD();
- SendPacket(&data);
- sLog.outStaticDebug("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)");
-
- guild->DisplayGuildBankTabsInfo(this);
-
- guild->BroadcastEvent(GE_SIGNED_ON, pCurrChar->GetGUID(), 1, pCurrChar->GetName(), "", "");
- }
+ if (Guild* pGuild = sObjectMgr.GetGuildById(pCurrChar->GetGuildId()))
+ pGuild->SendLoginInfo(this);
else
{
// remove wrong guild data
- sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId());
+ sLog.outError("Player %s (GUID: %u) marked as member of not existing guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId());
pCurrChar->SetInGuild(0);
}
}
diff --git a/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp b/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp
index d01814dad7e..5caa120ec0c 100755
--- a/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/ChatHandler.cpp
@@ -331,7 +331,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data)
{
sScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, guild);
- guild->BroadcastToGuild(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
+ guild->BroadcastToGuild(this, false, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
}
}
@@ -360,7 +360,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data)
{
sScriptMgr.OnPlayerChat(GetPlayer(), type, lang, msg, guild);
- guild->BroadcastToOfficers(this, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
+ guild->BroadcastToGuild(this, true, msg, lang == LANG_ADDON ? LANG_ADDON : LANG_UNIVERSAL);
}
}
break;
diff --git a/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp b/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp
index e185cccf805..421275c94be 100755
--- a/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp
@@ -27,186 +27,80 @@
#include "GossipDef.h"
#include "SocialMgr.h"
+// Helper for getting guild object of session's player.
+// If guild does not exist, sends error (if necessary).
+inline Guild* _GetPlayerGuild(WorldSession* session, bool sendError = false)
+{
+ if (uint32 guildId = session->GetPlayer()->GetGuildId()) // If guild id = 0, player is not in guild
+ if (Guild* pGuild = sObjectMgr.GetGuildById(guildId)) // Find guild by id
+ return pGuild;
+ if (sendError)
+ Guild::SendCommandResult(session, GUILD_CREATE_S, ERR_GUILD_PLAYER_NOT_IN_GUILD);
+ return NULL;
+}
+
void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_QUERY");
uint32 guildId;
recvPacket >> guildId;
-
- if (Guild *guild = sObjectMgr.GetGuildById(guildId))
- {
- guild->Query(this);
- return;
- }
-
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
+ // Use received guild id to access guild method (not player's guild id)
+ if (Guild* pGuild = sObjectMgr.GetGuildById(guildId))
+ pGuild->HandleQuery(this);
+ else
+ Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_PLAYER_NOT_IN_GUILD);
}
void WorldSession::HandleGuildCreateOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_CREATE");
- std::string gname;
- recvPacket >> gname;
-
- if (GetPlayer()->GetGuildId()) // already in guild
- return;
+ std::string name;
+ recvPacket >> name;
- Guild *guild = new Guild;
- if (!guild->Create(GetPlayer(), gname))
+ if (!GetPlayer()->GetGuildId()) // Player cannot be in guild
{
- delete guild;
- return;
+ Guild* pGuild = new Guild();
+ if (pGuild->Create(GetPlayer(), name))
+ sObjectMgr.AddGuild(pGuild);
+ else
+ delete pGuild;
}
-
- sObjectMgr.AddGuild(guild);
}
void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_INVITE");
- std::string Invitedname, plname;
-
- Player * player = NULL;
- recvPacket >> Invitedname;
-
- if (normalizePlayerName(Invitedname))
- player = sObjectAccessor.FindPlayerByName(Invitedname.c_str());
-
- if (!player)
- {
- SendGuildCommandResult(GUILD_INVITE_S, Invitedname, ERR_GUILD_PLAYER_NOT_FOUND_S);
- return;
- }
-
- Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- // OK result but not send invite
- if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
- return;
+ std::string invitedName;
+ recvPacket >> invitedName;
- // not let enemies sign guild charter
- if (!sWorld.getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != GetPlayer()->GetTeam())
- {
- SendGuildCommandResult(GUILD_INVITE_S, Invitedname, ERR_GUILD_NOT_ALLIED);
- return;
- }
-
- if (player->GetGuildId())
- {
- plname = player->GetName();
- SendGuildCommandResult(GUILD_INVITE_S, plname, ERR_ALREADY_IN_GUILD_S);
- return;
- }
-
- if (player->GetGuildIdInvited())
- {
- plname = player->GetName();
- SendGuildCommandResult(GUILD_INVITE_S, plname, ERR_ALREADY_INVITED_TO_GUILD_S);
- return;
- }
-
- if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_INVITE))
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- sLog.outDebug("Player %s Invited %s to Join his Guild", GetPlayer()->GetName(), Invitedname.c_str());
-
- player->SetGuildIdInvited(GetPlayer()->GetGuildId());
- // Put record into guildlog
- guild->LogGuildEvent(GUILD_EVENT_LOG_INVITE_PLAYER, GetPlayer()->GetGUIDLow(), player->GetGUIDLow(), 0);
-
- WorldPacket data(SMSG_GUILD_INVITE, (8+10)); // guess size
- data << GetPlayer()->GetName();
- data << guild->GetName();
- player->GetSession()->SendPacket(&data);
-
- sLog.outDebug("WORLD: Sent (SMSG_GUILD_INVITE)");
+ if (normalizePlayerName(invitedName))
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleInviteMember(this, invitedName);
}
void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_REMOVE");
- std::string plName;
- recvPacket >> plName;
-
- if (!normalizePlayerName(plName))
- return;
-
- Guild* guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_REMOVE))
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- uint64 plGuid;
- MemberSlot* slot = guild->GetMemberSlot(plName, plGuid);
- if (!slot)
- {
- SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S);
- return;
- }
-
- if (slot->RankId == GR_GUILDMASTER)
- {
- SendGuildCommandResult(GUILD_QUIT_S, "", ERR_GUILD_LEADER_LEAVE);
- return;
- }
-
- //do not allow to kick player with same or higher rights
- if (GetPlayer()->GetRank() >= slot->RankId)
- {
- SendGuildCommandResult(GUILD_QUIT_S, plName, ERR_GUILD_RANK_TOO_HIGH_S);
- return;
- }
-
- guild->DelMember(plGuid, false, true);
- // Put record into guildlog
- guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), 0);
+ std::string playerName;
+ recvPacket >> playerName;
- guild->BroadcastEvent(GE_REMOVED, 0, 2, plName, _player->GetName(), "");
+ if (normalizePlayerName(playerName))
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleRemoveMember(this, playerName);
}
void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/)
{
- Guild *guild;
- Player *player = GetPlayer();
-
sLog.outDebug("WORLD: Received CMSG_GUILD_ACCEPT");
-
- guild = sObjectMgr.GetGuildById(player->GetGuildIdInvited());
- if (!guild || player->GetGuildId())
- return;
-
- // not let enemies sign guild charter
- if (!sWorld.getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != sObjectMgr.GetPlayerTeamByGUID(guild->GetLeader()))
- return;
-
- if (!guild->AddMember(GetPlayer()->GetGUID(),guild->GetLowestRank()))
- return;
- // Put record into guildlog
- guild->LogGuildEvent(GUILD_EVENT_LOG_JOIN_GUILD, GetPlayer()->GetGUIDLow(), 0, 0);
-
- guild->BroadcastEvent(GE_JOINED, player->GetGUID(), 1, player->GetName(), "", "");
-
- sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)");
+ // Player cannot be in guild
+ if (!GetPlayer()->GetGuildId())
+ // Guild where player was invited must exist
+ if (Guild* pGuild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildIdInvited()))
+ pGuild->HandleAcceptMember(this);
}
void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/)
@@ -219,204 +113,58 @@ void WorldSession::HandleGuildDeclineOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::HandleGuildInfoOpcode(WorldPacket& /*recvPacket*/)
{
- Guild *guild;
sLog.outDebug("WORLD: Received CMSG_GUILD_INFO");
- guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- WorldPacket data(SMSG_GUILD_INFO, (guild->GetName().size() + 4 + 4 + 4));
- data << guild->GetName();
- data << secsToTimeBitFields(guild->GetCreatedDate()); // 3.x (prev. year + month + day)
- data << guild->GetMemberSize(); // char amount
- data << guild->GetAccountsNumber(); // amount of accounts
-
- SendPacket(&data);
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->SendInfo(this);
}
void WorldSession::HandleGuildRosterOpcode(WorldPacket& /*recvPacket*/)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_ROSTER");
- if (Guild* guild = sObjectMgr.GetGuildById(_player->GetGuildId()))
- guild->Roster(this);
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->HandleRoster(this);
}
void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_PROMOTE");
- std::string plName;
- recvPacket >> plName;
-
- if (!normalizePlayerName(plName))
- return;
-
- Guild* guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_PROMOTE))
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
+ std::string playerName;
+ recvPacket >> playerName;
- uint64 plGuid;
- MemberSlot* slot = guild->GetMemberSlot(plName, plGuid);
-
- if (!slot)
- {
- SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S);
- return;
- }
-
- if (plGuid == GetPlayer()->GetGUID())
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_NAME_INVALID);
- return;
- }
-
- //allow to promote only to lower rank than member's rank
- //guildmaster's rank = 0
- //GetPlayer()->GetRank() + 1 is highest rank that current player can promote to
- if (GetPlayer()->GetRank() + 1 >= slot->RankId)
- {
- SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_HIGH_S);
- return;
- }
-
- uint32 newRankId = slot->RankId - 1; //when promoting player, rank is decreased
-
- guild->BroadcastEvent(GE_PROMOTION, 0, 3, _player->GetName(), plName, guild->GetRankName(newRankId));
-
- guild->ChangeRank(plGuid, newRankId);
- // Put record into guildlog
- guild->LogGuildEvent(GUILD_EVENT_LOG_PROMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId);
+ if (normalizePlayerName(playerName))
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleUpdateMemberRank(this, playerName, false);
}
void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_DEMOTE");
- std::string plName;
- recvPacket >> plName;
-
- if (!normalizePlayerName(plName))
- return;
-
- Guild* guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
-
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_DEMOTE))
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- uint64 plGuid;
- MemberSlot* slot = guild->GetMemberSlot(plName, plGuid);
-
- if (!slot)
- {
- SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S);
- return;
- }
-
- if (plGuid == GetPlayer()->GetGUID())
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_NAME_INVALID);
- return;
- }
-
- //do not allow to demote same or higher rank
- if (GetPlayer()->GetRank() >= slot->RankId)
- {
- SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_HIGH_S);
- return;
- }
-
- //do not allow to demote lowest rank
- if (slot->RankId >= guild->GetLowestRank())
- {
- SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_RANK_TOO_LOW_S);
- return;
- }
-
- uint32 newRankId = slot->RankId + 1; //when demoting player, rank is increased
+ std::string playerName;
+ recvPacket >> playerName;
- guild->ChangeRank(plGuid, newRankId);
- // Put record into guildlog
- guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId);
-
- guild->BroadcastEvent(GE_DEMOTION, 0, 3, _player->GetName(), plName, guild->GetRankName(slot->RankId));
+ if (normalizePlayerName(playerName))
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleUpdateMemberRank(this, playerName, true);
}
void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_LEAVE");
- Guild *guild = sObjectMgr.GetGuildById(_player->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (_player->GetGUID() == guild->GetLeader() && guild->GetMemberSize() > 1)
- {
- SendGuildCommandResult(GUILD_QUIT_S, "", ERR_GUILD_LEADER_LEAVE);
- return;
- }
-
- if (_player->GetGUID() == guild->GetLeader())
- {
- guild->Disband();
- return;
- }
-
- guild->DelMember(_player->GetGUID(), false, false);
-
- // Put record into guildlog
- guild->LogGuildEvent(GUILD_EVENT_LOG_LEAVE_GUILD, _player->GetGUIDLow(), 0, 0);
-
- guild->BroadcastEvent(GE_LEFT, _player->GetGUID(), 1, _player->GetName(), "", "");
-
- SendGuildCommandResult(GUILD_QUIT_S, guild->GetName(), ERR_PLAYER_NO_MORE_IN_GUILD);
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleLeaveMember(this);
}
void WorldSession::HandleGuildDisbandOpcode(WorldPacket& /*recvPacket*/)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_DISBAND");
- Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (GetPlayer()->GetGUID() != guild->GetLeader())
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- guild->Disband();
-
- sLog.outDebug("WORLD: Guild Successfully Disbanded");
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleDisband(this);
}
void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket)
@@ -426,280 +174,119 @@ void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket)
std::string name;
recvPacket >> name;
- Player *oldLeader = GetPlayer();
-
- if (!normalizePlayerName(name))
- return;
-
- Guild *guild = sObjectMgr.GetGuildById(oldLeader->GetGuildId());
-
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (oldLeader->GetGUID() != guild->GetLeader())
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- uint64 newLeaderGUID;
- MemberSlot* slot = guild->GetMemberSlot(name, newLeaderGUID);
-
- if (!slot)
- {
- SendGuildCommandResult(GUILD_INVITE_S, name, ERR_GUILD_PLAYER_NOT_IN_GUILD_S);
- return;
- }
-
- guild->SetLeader(newLeaderGUID);
- guild->ChangeRank(oldLeader->GetGUID(), GR_OFFICER);
-
- guild->BroadcastEvent(GE_LEADER_CHANGED, 0, 2, oldLeader->GetName(), name, "");
+ if (normalizePlayerName(name))
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleSetLeader(this, name);
}
void WorldSession::HandleGuildMOTDOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_MOTD");
- std::string MOTD;
-
+ std::string motd; // Empty by default
if (!recvPacket.empty())
- recvPacket >> MOTD;
- else
- MOTD = "";
-
- Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
+ recvPacket >> motd;
- if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_SETMOTD))
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- guild->SetMOTD(MOTD);
-
- guild->BroadcastEvent(GE_MOTD, 0, 1, MOTD, "", "");
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleSetMOTD(this, motd);
}
void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_SET_PUBLIC_NOTE");
- std::string name,PNOTE;
- recvPacket >> name;
+ std::string playerName;
+ recvPacket >> playerName;
- if (!normalizePlayerName(name))
- return;
-
- Guild* guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EPNOTE))
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- uint64 plGuid;
- MemberSlot* slot = guild->GetMemberSlot(name, plGuid);
-
- if (!slot)
- {
- SendGuildCommandResult(GUILD_INVITE_S, name, ERR_GUILD_PLAYER_NOT_IN_GUILD_S);
- return;
- }
+ std::string publicNote;
+ recvPacket >> publicNote;
- recvPacket >> PNOTE;
- guild->SetPNOTE(plGuid, PNOTE);
-
- guild->Roster(this);
+ if (normalizePlayerName(playerName))
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleSetMemberNote(this, playerName, publicNote, false);
}
void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_SET_OFFICER_NOTE");
- std::string plName, OFFNOTE;
- recvPacket >> plName;
+ std::string playerName;
+ recvPacket >> playerName;
- if (!normalizePlayerName(plName))
- return;
+ std::string officerNote;
+ recvPacket >> officerNote;
- Guild* guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_EOFFNOTE))
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- uint64 plGuid;
- MemberSlot* slot = guild->GetMemberSlot(plName, plGuid);
-
- if (!slot)
- {
- SendGuildCommandResult(GUILD_INVITE_S, plName, ERR_GUILD_PLAYER_NOT_IN_GUILD_S);
- return;
- }
-
- recvPacket >> OFFNOTE;
- guild->SetOFFNOTE(plGuid, OFFNOTE);
-
- guild->Roster(this);
+ if (normalizePlayerName(playerName))
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleSetMemberNote(this, playerName, officerNote, true);
}
void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket)
{
- std::string rankname;
- uint32 rankId;
- uint32 rights, MoneyPerDay;
-
sLog.outDebug("WORLD: Received CMSG_GUILD_RANK");
- Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
- else if (GetPlayer()->GetGUID() != guild->GetLeader())
+ Guild* pGuild = _GetPlayerGuild(this, true);
+ if (!pGuild)
{
- recvPacket.rpos(recvPacket.wpos()); // set to end to avoid warnings spam
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
+ recvPacket.rpos(recvPacket.wpos());
return;
}
+ uint32 rankId;
recvPacket >> rankId;
- recvPacket >> rights;
- recvPacket >> rankname;
- recvPacket >> MoneyPerDay;
- for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- {
- uint32 BankRights;
- uint32 BankSlotPerDay;
+ uint32 rights;
+ recvPacket >> rights;
- recvPacket >> BankRights;
- recvPacket >> BankSlotPerDay;
- guild->SetBankRightsAndSlots(rankId, uint8(i), uint16(BankRights & 0xFF), uint16(BankSlotPerDay), true);
- }
+ std::string rankName;
+ recvPacket >> rankName;
- sLog.outDebug("WORLD: Changed RankName to %s , Rights to 0x%.4X", rankname.c_str(), rights);
+ uint32 money;
+ recvPacket >> money;
- guild->SetBankMoneyPerDay(rankId, MoneyPerDay);
- guild->SetRankName(rankId, rankname);
+ GuildBankRightsAndSlotsVec rightsAndSlots(GUILD_BANK_MAX_TABS);
+ for (uint8 tabId = 0; tabId < GUILD_BANK_MAX_TABS; ++tabId)
+ {
+ uint32 bankRights;
+ uint32 slots;
- if (rankId == GR_GUILDMASTER) // prevent loss leader rights
- rights = GR_RIGHT_ALL;
+ recvPacket >> bankRights;
+ recvPacket >> slots;
- guild->SetRankRights(rankId, rights);
+ rightsAndSlots[tabId] = GuildBankRightsAndSlots(uint8(bankRights), slots);
+ }
- guild->Query(this);
- guild->Roster(); // broadcast for tab rights update
+ pGuild->HandleSetRankInfo(this, rankId, rankName, rights, money, rightsAndSlots);
}
void WorldSession::HandleGuildAddRankOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_ADD_RANK");
- std::string rankname;
- recvPacket >> rankname;
-
- Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (GetPlayer()->GetGUID() != guild->GetLeader())
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- if (guild->GetRanksSize() >= GUILD_RANKS_MAX_COUNT) // client not let create more 10 than ranks
- return;
-
- guild->CreateRank(rankname, GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
+ std::string rankName;
+ recvPacket >> rankName;
- guild->Query(this);
- guild->Roster(); // broadcast for tab rights update
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleAddNewRank(this, rankName);
}
void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_DEL_RANK");
- Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
- else if (GetPlayer()->GetGUID() != guild->GetLeader())
- {
- SendGuildCommandResult(GUILD_INVITE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- guild->DelRank();
-
- guild->Query(this);
- guild->Roster(); // broadcast for tab rights update
-}
-
-void WorldSession::SendGuildCommandResult(uint32 typecmd, const std::string& str,uint32 cmdresult)
-{
- WorldPacket data(SMSG_GUILD_COMMAND_RESULT, (8+str.size()+1));
- data << typecmd;
- data << str;
- data << cmdresult;
- SendPacket(&data);
-
- sLog.outDebug("WORLD: Sent (SMSG_GUILD_COMMAND_RESULT)");
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleRemoveLowestRank(this);
}
void WorldSession::HandleGuildChangeInfoTextOpcode(WorldPacket& recvPacket)
{
sLog.outDebug("WORLD: Received CMSG_GUILD_INFO_TEXT");
- std::string GINFO;
-
- recvPacket >> GINFO;
+ std::string info;
+ recvPacket >> info;
- Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
- return;
- }
-
- if (!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_MODIFY_GUILD_INFO))
- {
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_PERMISSIONS);
- return;
- }
-
- guild->SetGINFO(GINFO);
+ if (Guild* pGuild = _GetPlayerGuild(this, true))
+ pGuild->HandleSetInfo(this, info);
}
void WorldSession::HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket)
@@ -707,154 +294,92 @@ void WorldSession::HandleSaveGuildEmblemOpcode(WorldPacket& recvPacket)
sLog.outDebug("WORLD: Received MSG_SAVE_GUILD_EMBLEM");
uint64 vendorGuid;
-
- uint32 EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor;
-
recvPacket >> vendorGuid;
- recvPacket >> EmblemStyle >> EmblemColor >> BorderStyle >> BorderColor >> BackgroundColor;
-
- Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid,UNIT_NPC_FLAG_TABARDDESIGNER);
- if (!pCreature)
- {
- //"That's not an emblem vendor!"
- SendSaveGuildEmblem(ERR_GUILDEMBLEM_INVALIDVENDOR);
- sLog.outDebug("WORLD: HandleSaveGuildEmblemOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(vendorGuid));
- return;
- }
- // remove fake death
- if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
+ EmblemInfo emblemInfo;
+ emblemInfo.ReadPacket(recvPacket);
- Guild *guild = sObjectMgr.GetGuildById(GetPlayer()->GetGuildId());
- if (!guild)
+ if (GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_TABARDDESIGNER))
{
- //"You are not part of a guild!";
- SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOGUILD);
- return;
- }
+ // Remove fake death
+ if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- if (guild->GetLeader() != GetPlayer()->GetGUID())
- {
- //"Only guild leaders can create emblems."
- SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOTGUILDMASTER);
- return;
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->HandleSetEmblem(this, emblemInfo);
+ else
+ // "You are not part of a pGuild!";
+ Guild::SendSaveEmblemResult(this, ERR_GUILDEMBLEM_NOGUILD);
}
-
- if (!GetPlayer()->HasEnoughMoney(10 * GOLD))
+ else
{
- //"You can't afford to do that."
- SendSaveGuildEmblem(ERR_GUILDEMBLEM_NOTENOUGHMONEY);
- return;
+ // "That's not an emblem vendor!"
+ Guild::SendSaveEmblemResult(this, ERR_GUILDEMBLEM_INVALIDVENDOR);
+ sLog.outDebug("WORLD: HandleSaveGuildEmblemOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(vendorGuid));
}
-
- GetPlayer()->ModifyMoney(-10*GOLD);
- guild->SetEmblem(EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor);
-
- //"Guild Emblem saved."
- SendSaveGuildEmblem(ERR_GUILDEMBLEM_SUCCESS);
-
- guild->Query(this);
}
void WorldSession::HandleGuildEventLogQueryOpcode(WorldPacket& /* recvPacket */)
{
- // empty
sLog.outDebug("WORLD: Received (MSG_GUILD_EVENT_LOG_QUERY)");
- if (uint32 GuildId = GetPlayer()->GetGuildId())
- if (Guild *pGuild = sObjectMgr.GetGuildById(GuildId))
- pGuild->DisplayGuildEventLog(this);
-}
-/****** GUILD BANK *******/
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->SendEventLog(this);
+}
void WorldSession::HandleGuildBankMoneyWithdrawn(WorldPacket & /* recv_data */)
{
sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_MONEY_WITHDRAWN)");
- if (uint32 GuildId = GetPlayer()->GetGuildId())
- if (Guild *pGuild = sObjectMgr.GetGuildById(GuildId))
- pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow());
+
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->SendMoneyInfo(this);
}
void WorldSession::HandleGuildPermissions(WorldPacket& /* recv_data */)
{
sLog.outDebug("WORLD: Received (MSG_GUILD_PERMISSIONS)");
- if (uint32 GuildId = GetPlayer()->GetGuildId())
- {
- if (Guild *pGuild = sObjectMgr.GetGuildById(GuildId))
- {
- uint32 rankId = GetPlayer()->GetRank();
-
- WorldPacket data(MSG_GUILD_PERMISSIONS, 4*15+1);
- data << uint32(rankId); // guild rank id
- data << uint32(pGuild->GetRankRights(rankId)); // rank rights
- // money per day left
- data << uint32(pGuild->GetMemberMoneyWithdrawRem(GetPlayer()->GetGUIDLow()));
- data << uint8(pGuild->GetPurchasedTabs()); // tabs count
- // why sending all info when not all tabs are purchased???
- for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
- {
- data << uint32(pGuild->GetBankRights(rankId, uint8(i)));
- data << uint32(pGuild->GetMemberSlotWithdrawRem(GetPlayer()->GetGUIDLow(), uint8(i)));
- }
- SendPacket(&data);
- sLog.outDebug("WORLD: Sent (MSG_GUILD_PERMISSIONS)");
- }
- }
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->SendPermissions(this);
}
-/* Called when clicking on Guild bank gameobject */
+// Called when clicking on Guild bank gameobject
void WorldSession::HandleGuildBankerActivate(WorldPacket & recv_data)
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANKER_ACTIVATE)");
uint64 GoGuid;
- uint8 unk;
- recv_data >> GoGuid >> unk;
+ recv_data >> GoGuid;
- if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
- return;
+ uint8 unk;
+ recv_data >> unk;
- if (uint32 GuildId = GetPlayer()->GetGuildId())
+ if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
{
- if (Guild *pGuild = sObjectMgr.GetGuildById(GuildId))
- {
- pGuild->DisplayGuildBankTabsInfo(this); // this also will load guild bank if not yet
- return;
- }
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->SendBankTabsInfo(this);
+ else
+ Guild::SendCommandResult(this, GUILD_UNK1, ERR_GUILD_PLAYER_NOT_IN_GUILD);
}
-
- SendGuildCommandResult(GUILD_UNK1, "", ERR_GUILD_PLAYER_NOT_IN_GUILD);
}
-/* Called when opening guild bank tab only (first one) */
+// Called when opening pGuild bank tab only (first one)
void WorldSession::HandleGuildBankQueryTab(WorldPacket & recv_data)
{
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_QUERY_TAB)");
uint64 GoGuid;
- uint8 TabId, unk1;
- recv_data >> GoGuid >> TabId >> unk1;
-
- if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
- return;
+ recv_data >> GoGuid;
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (!GuildId)
- return;
+ uint8 tabId;
+ recv_data >> tabId;
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
-
- if (TabId >= pGuild->GetPurchasedTabs())
- return;
+ uint8 unk1;
+ recv_data >> unk1;
- // Let's update the amount of gold the player can withdraw before displaying the content
- // This is useful if money withdraw right has changed
- pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow());
- pGuild->DisplayGuildBankContent(this, TabId);
+ if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->SendBankTabData(this, tabId);
}
void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recv_data)
@@ -862,50 +387,15 @@ void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recv_data)
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_DEPOSIT_MONEY)");
uint64 GoGuid;
- uint32 money;
- recv_data >> GoGuid >> money;
-
- if (!money)
- return;
-
- if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
- return;
-
- if (!GetPlayer()->HasEnoughMoney(money))
- return;
-
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (!GuildId)
- return;
-
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
-
- if (!pGuild->GetPurchasedTabs())
- return;
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
-
- pGuild->SetBankMoney(pGuild->GetGuildBankMoney()+money, trans);
- GetPlayer()->ModifyMoney(-int(money));
- GetPlayer()->SaveGoldToDB(trans);
-
- // logging money
- if (_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getBoolConfig(CONFIG_GM_LOG_TRADE))
- {
- sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit money (Amount: %u) to guild bank (Guild ID %u)",
- _player->GetName(),_player->GetSession()->GetAccountId(),money,GuildId);
- }
-
- // log
- pGuild->LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money);
+ recv_data >> GoGuid;
- CharacterDatabase.CommitTransaction(trans);
+ uint32 money;
+ recv_data >> money;
- pGuild->DisplayGuildBankTabsInfo(this);
- pGuild->DisplayGuildBankContent(this, 0);
- pGuild->DisplayGuildBankMoneyUpdate(this);
+ if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
+ if (money && GetPlayer()->HasEnoughMoney(money))
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->HandleMemberDepositMoney(this, money);
}
void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recv_data)
@@ -913,49 +403,15 @@ void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recv_data)
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_WITHDRAW_MONEY)");
uint64 GoGuid;
- uint32 money;
- recv_data >> GoGuid >> money;
-
- if (!money)
- return;
-
- if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
- return;
-
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (GuildId == 0)
- return;
-
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
-
- if (!pGuild->GetPurchasedTabs())
- return;
-
- if (pGuild->GetGuildBankMoney()<money) // not enough money in bank
- return;
-
- if (!pGuild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_WITHDRAW_GOLD))
- return;
-
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
-
- if (!pGuild->MemberMoneyWithdraw(money, GetPlayer()->GetGUIDLow(), trans))
- return;
-
- GetPlayer()->ModifyMoney(money);
- GetPlayer()->SaveGoldToDB(trans);
-
- // Log
- pGuild->LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money);
+ recv_data >> GoGuid;
- CharacterDatabase.CommitTransaction(trans);
+ uint32 money;
+ recv_data >> money;
- pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow());
- pGuild->DisplayGuildBankTabsInfo(this);
- pGuild->DisplayGuildBankContent(this,0);
- pGuild->DisplayGuildBankMoneyUpdate(this);
+ if (money)
+ if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->HandleMemberWithdrawMoney(this, money);
}
void WorldSession::HandleGuildBankSwapItems(WorldPacket & recv_data)
@@ -963,108 +419,81 @@ void WorldSession::HandleGuildBankSwapItems(WorldPacket & recv_data)
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_SWAP_ITEMS)");
uint64 GoGuid;
- uint8 BankToBank;
-
- uint8 BankTab, BankTabSlot, AutoStore;
- uint8 PlayerSlot = NULL_SLOT;
- uint8 PlayerBag = NULL_BAG;
- uint8 BankTabDst = 0, BankTabSlotDst = 0, unk2;
- uint8 ToChar = 1;
- uint32 ItemEntry, unk1;
- uint32 AutoStoreCount = 0;
- uint32 SplitedAmount = 0;
-
- recv_data >> GoGuid >> BankToBank;
+ recv_data >> GoGuid;
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (!GuildId)
+ if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
{
- recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
+ recv_data.rpos(recv_data.wpos()); // Prevent additional spam at rejected packet
return;
}
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
+ Guild* pGuild = _GetPlayerGuild(this);
if (!pGuild)
{
- recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
+ recv_data.rpos(recv_data.wpos()); // Prevent additional spam at rejected packet
return;
}
- if (BankToBank)
+ uint8 bankToBank;
+ recv_data >> bankToBank;
+
+ uint8 tabId;
+ uint8 slotId;
+ uint32 itemEntry;
+ uint32 splitedAmount = 0;
+
+ if (bankToBank)
{
- recv_data >> BankTabDst;
- recv_data >> BankTabSlotDst;
- recv_data >> unk1; // always 0
- recv_data >> BankTab;
- recv_data >> BankTabSlot;
- recv_data >> ItemEntry;
- recv_data >> unk2; // always 0
- recv_data >> SplitedAmount;
-
- if (BankTabSlotDst >= GUILD_BANK_MAX_SLOTS ||
- (BankTabDst == BankTab && BankTabSlotDst == BankTabSlot) ||
- BankTab >= pGuild->GetPurchasedTabs() ||
- BankTabDst >= pGuild->GetPurchasedTabs())
- {
- recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
- return;
- }
+ uint8 destTabId;
+ recv_data >> destTabId;
+
+ uint8 destSlotId;
+ recv_data >> destSlotId;
+ recv_data.read_skip<uint32>(); // Always 0
+
+ recv_data >> tabId;
+ recv_data >> slotId;
+ recv_data >> itemEntry;
+ recv_data.read_skip<uint8>(); // Always 0
+
+ recv_data >> splitedAmount;
+
+ pGuild->SwapItems(GetPlayer(), tabId, slotId, destTabId, destSlotId, splitedAmount);
}
else
{
- recv_data >> BankTab;
- recv_data >> BankTabSlot;
- recv_data >> ItemEntry;
- recv_data >> AutoStore;
- if (AutoStore)
+ uint8 playerBag = NULL_BAG;
+ uint8 playerSlotId = NULL_SLOT;
+ uint8 toChar = 1;
+ uint32 autoStoreCount = 0;
+
+ recv_data >> tabId;
+ recv_data >> slotId;
+ recv_data >> itemEntry;
+
+ uint8 autoStore;
+ recv_data >> autoStore;
+ if (autoStore)
{
- recv_data >> AutoStoreCount;
- recv_data.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in guild->ToChar)
- recv_data.read_skip<uint32>(); // unknown, always 0
+ recv_data >> autoStoreCount;
+ recv_data.read_skip<uint8>(); // ToChar (?), always and expected to be 1 (autostore only triggered in Bank -> Char)
+ recv_data.read_skip<uint32>(); // Always 0
}
else
{
- recv_data >> PlayerBag;
- recv_data >> PlayerSlot;
- recv_data >> ToChar;
- recv_data >> SplitedAmount;
+ recv_data >> playerBag;
+ recv_data >> playerSlotId;
+ recv_data >> toChar;
+ recv_data >> splitedAmount;
}
- if ((BankTabSlot >= GUILD_BANK_MAX_SLOTS && BankTabSlot != 0xFF) ||
- BankTab >= pGuild->GetPurchasedTabs())
- {
- recv_data.rpos(recv_data.wpos()); // prevent additional spam at rejected packet
- return;
- }
- }
-
- if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
- return;
-
- if (BankTab >= pGuild->GetPurchasedTabs())
- return;
-
- // Bank <-> Bank
- if (BankToBank)
- {
- pGuild->SwapItems(_player, BankTab, BankTabSlot, BankTabDst, BankTabSlotDst, SplitedAmount);
- return;
- }
-
- // Player <-> Bank
-
- // allow work with inventory only
- if (!Player::IsInventoryPos(PlayerBag, PlayerSlot) && !(PlayerBag == NULL_BAG && PlayerSlot == NULL_SLOT))
- {
- _player->SendEquipError(EQUIP_ERR_NONE, NULL, NULL);
- return;
+ // Player <-> Bank
+ // Allow to work with inventory only
+ if (!Player::IsInventoryPos(playerBag, playerSlotId) && !(playerBag == NULL_BAG && playerSlotId == NULL_SLOT))
+ GetPlayer()->SendEquipError(EQUIP_ERR_NONE, NULL);
+ else
+ pGuild->SwapItemsWithInventory(GetPlayer(), toChar, tabId, slotId, playerBag, playerSlotId, splitedAmount);
}
-
- // BankToChar swap or char to bank remaining
- if (ToChar) // Bank -> Char cases
- pGuild->MoveFromBankToChar(_player, BankTab, BankTabSlot, PlayerBag, PlayerSlot, SplitedAmount);
- else // Char -> Bank cases
- pGuild->MoveFromCharToBank(_player, PlayerBag, PlayerSlot, BankTab, BankTabSlot, SplitedAmount);
}
void WorldSession::HandleGuildBankBuyTab(WorldPacket & recv_data)
@@ -1072,40 +501,14 @@ void WorldSession::HandleGuildBankBuyTab(WorldPacket & recv_data)
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_BUY_TAB)");
uint64 GoGuid;
- uint8 TabId;
-
recv_data >> GoGuid;
- recv_data >> TabId;
-
- if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
- return;
-
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (!GuildId)
- return;
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
-
- // m_PurchasedTabs = 0 when buying Tab 0, that is why this check can be made
- if (TabId != pGuild->GetPurchasedTabs())
- return;
+ uint8 tabId;
+ recv_data >> tabId;
- uint32 TabCost = GetGuildBankTabPrice(TabId) * GOLD;
- if (!TabCost)
- return;
-
- if (!GetPlayer()->HasEnoughMoney(TabCost)) // Should not happen, this is checked by client
- return;
-
- // Go on with creating tab
- pGuild->CreateNewBankTab();
- GetPlayer()->ModifyMoney(-int(TabCost));
- pGuild->SetBankMoneyPerDay(GetPlayer()->GetRank(), WITHDRAW_MONEY_UNLIMITED);
- pGuild->SetBankRightsAndSlots(GetPlayer()->GetRank(), TabId, GUILD_BANK_RIGHT_FULL, WITHDRAW_SLOT_UNLIMITED, true);
- pGuild->Roster(); // broadcast for tab rights update
- pGuild->DisplayGuildBankTabsInfo(this);
+ if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->HandleBuyBankTab(this, tabId);
}
void WorldSession::HandleGuildBankUpdateTab(WorldPacket & recv_data)
@@ -1113,109 +516,55 @@ void WorldSession::HandleGuildBankUpdateTab(WorldPacket & recv_data)
sLog.outDebug("WORLD: Received (CMSG_GUILD_BANK_UPDATE_TAB)");
uint64 GoGuid;
- uint8 TabId;
- std::string Name;
- std::string IconIndex;
-
recv_data >> GoGuid;
- recv_data >> TabId;
- recv_data >> Name;
- recv_data >> IconIndex;
-
- if (Name.empty())
- return;
- if (IconIndex.empty())
- return;
-
- if (!GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
- return;
-
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (!GuildId)
- return;
+ uint8 tabId;
+ recv_data >> tabId;
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
+ std::string name;
+ recv_data >> name;
- if (TabId >= pGuild->GetPurchasedTabs())
- return;
+ std::string icon;
+ recv_data >> icon;
- pGuild->SetGuildBankTabInfo(TabId, Name, IconIndex);
- pGuild->DisplayGuildBankTabsInfo(this);
- pGuild->DisplayGuildBankContent(this, TabId);
+ if (!name.empty() && !icon.empty())
+ if (GetPlayer()->GetGameObjectIfCanInteractWith(GoGuid, GAMEOBJECT_TYPE_GUILD_BANK))
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->HandleSetBankTabInfo(this, tabId, name, icon);
}
void WorldSession::HandleGuildBankLogQuery(WorldPacket & recv_data)
{
sLog.outDebug("WORLD: Received (MSG_GUILD_BANK_LOG_QUERY)");
- uint8 TabId;
- recv_data >> TabId;
-
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (!GuildId)
- return;
-
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
-
- // GUILD_BANK_MAX_TABS send by client for money log
- if (TabId >= pGuild->GetPurchasedTabs() && TabId != GUILD_BANK_MAX_TABS)
- return;
+ uint8 tabId;
+ recv_data >> tabId;
- pGuild->DisplayGuildBankLogs(this, TabId);
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->SendBankLog(this, tabId);
}
void WorldSession::HandleQueryGuildBankTabText(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: Received MSG_QUERY_GUILD_BANK_TEXT");
- uint8 TabId;
- recv_data >> TabId;
+ uint8 tabId;
+ recv_data >> tabId;
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (!GuildId)
- return;
-
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
-
- if (TabId >= pGuild->GetPurchasedTabs())
- return;
-
- pGuild->SendGuildBankTabText(this, TabId);
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->SendBankTabText(this, tabId);
}
void WorldSession::HandleSetGuildBankTabText(WorldPacket &recv_data)
{
sLog.outDebug("WORLD: Received CMSG_SET_GUILD_BANK_TEXT");
- uint8 TabId;
- std::string Text;
- recv_data >> TabId;
- recv_data >> Text;
+ uint8 tabId;
+ recv_data >> tabId;
- uint32 GuildId = GetPlayer()->GetGuildId();
- if (!GuildId)
- return;
+ std::string text;
+ recv_data >> text;
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
-
- if (TabId >= pGuild->GetPurchasedTabs())
- return;
-
- pGuild->SetGuildBankTabText(TabId, Text);
-}
-
-void WorldSession::SendSaveGuildEmblem(uint32 msg)
-{
- WorldPacket data(MSG_SAVE_GUILD_EMBLEM, 4);
- data << uint32(msg); // not part of guild
- SendPacket(&data);
+ if (Guild* pGuild = _GetPlayerGuild(this))
+ pGuild->SetBankTabText(tabId, text);
}
diff --git a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp
index 2a2f24a82b4..5841d9c48f6 100755
--- a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp
@@ -33,7 +33,6 @@
#include "Pet.h"
#include "BattlegroundMgr.h"
#include "Battleground.h"
-#include "Guild.h"
#include "ScriptMgr.h"
enum StableResultCode
@@ -880,31 +879,13 @@ void WorldSession::HandleRepairItemOpcode(WorldPacket & recv_data)
sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID));
Item* item = _player->GetItemByGuid(itemGUID);
-
if (item)
- TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false);
+ TotalCost = _player->DurabilityRepair(item->GetPos(), true, discountMod, guildBank);
}
else
{
sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID));
-
- TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false);
- }
- if (guildBank)
- {
- uint32 GuildId = _player->GetGuildId();
- if (!GuildId)
- return;
- Guild *pGuild = sObjectMgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
-
- //- TODO: Fix poor function call design
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
- pGuild->LogBankEvent(trans, GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost);
- CharacterDatabase.CommitTransaction(trans);
-
- pGuild->SendMoneyInfo(this, _player->GetGUIDLow());
+ TotalCost = _player->DurabilityRepairAll(true, discountMod, guildBank);
}
}
diff --git a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp
index cc4e6028406..37bb3efe62e 100755
--- a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp
@@ -46,14 +46,6 @@ enum CharterItemIDs
ARENA_TEAM_CHARTER_5v5 = 23562
};
-enum CharterTypes
-{
- GUILD_CHARTER_TYPE = 9,
- ARENA_TEAM_CHARTER_2v2_TYPE = 2,
- ARENA_TEAM_CHARTER_3v3_TYPE = 3,
- ARENA_TEAM_CHARTER_5v5_TYPE = 5
-};
-
enum CharterCosts
{
GUILD_CHARTER_COST = 1000,
@@ -164,12 +156,12 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
{
if (sObjectMgr.GetGuildByName(name))
{
- SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S);
+ Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, name);
return;
}
if (sObjectMgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
{
- SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_INVALID);
+ Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_INVALID, name);
return;
}
}
@@ -414,12 +406,12 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
{
if (sObjectMgr.GetGuildByName(newname))
{
- SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_GUILD_NAME_EXISTS_S);
+ Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, newname);
return;
}
if (sObjectMgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
{
- SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_GUILD_NAME_INVALID);
+ Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_INVALID, newname);
return;
}
}
@@ -484,14 +476,14 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
// not let enemies sign guild charter
if (!sWorld.getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != sObjectMgr.GetPlayerTeamByGUID(ownerguid))
{
- if (type != 9)
+ if (type != GUILD_CHARTER_TYPE)
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
else
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_NOT_ALLIED);
+ Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NOT_ALLIED);
return;
}
- if (type != 9)
+ if (type != GUILD_CHARTER_TYPE)
{
if (_player->getLevel() < sWorld.getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
@@ -519,12 +511,12 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
{
if (_player->GetGuildId())
{
- SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_IN_GUILD_S);
+ Guild::SendCommandResult(this, GUILD_INVITE_S, ERR_ALREADY_IN_GUILD_S, _player->GetName());
return;
}
if (_player->GetGuildIdInvited())
{
- SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S);
+ Guild::SendCommandResult(this, GUILD_INVITE_S, ERR_ALREADY_INVITED_TO_GUILD_S, _player->GetName());
return;
}
}
@@ -628,14 +620,14 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
if (!sWorld.getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam())
{
- if (type != 9)
+ if (type != GUILD_CHARTER_TYPE)
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
else
- SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_NOT_ALLIED);
+ Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NOT_ALLIED);
return;
}
- if (type != 9)
+ if (type != GUILD_CHARTER_TYPE)
{
if (player->getLevel() < sWorld.getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
{
@@ -665,13 +657,13 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
{
if (player->GetGuildId())
{
- SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_IN_GUILD_S);
+ Guild::SendCommandResult(this, GUILD_INVITE_S, ERR_ALREADY_IN_GUILD_S, _player->GetName());
return;
}
if (player->GetGuildIdInvited())
{
- SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S);
+ Guild::SendCommandResult(this, GUILD_INVITE_S, ERR_ALREADY_INVITED_TO_GUILD_S, _player->GetName());
return;
}
}
@@ -787,7 +779,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
{
if (sObjectMgr.GetGuildByName(name))
{
- SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S);
+ Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, name);
return;
}
}
@@ -826,7 +818,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
for (uint8 i = 0; i < signs; ++i)
{
Field* fields = result->Fetch();
- guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank());
+ guild->AddMember(fields[0].GetUInt64());
result->NextRow();
}
}
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index ef1b5c4d339..ab269f58204 100755
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -410,14 +410,8 @@ void WorldSession::LogoutPlayer(bool Save)
HandleMoveWorldportAckOpcode();
///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
- Guild *guild = sObjectMgr.GetGuildById(_player->GetGuildId());
- if (guild)
- {
- guild->SetMemberStats(_player->GetGUID());
- guild->UpdateLogoutTime(_player->GetGUID());
-
- guild->BroadcastEvent(GE_SIGNED_OFF, _player->GetGUID(), 1, _player->GetName(), "", "");
- }
+ if (Guild *pGuild = sObjectMgr.GetGuildById(_player->GetGuildId()))
+ pGuild->HandleMemberLogout(this);
///- Remove pet
_player->RemovePet(NULL,PET_SAVE_AS_CURRENT, true);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 5f5f4d1b335..d92c8c609d7 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -129,6 +129,14 @@ enum ChatRestrictionType
ERR_YELL_RESTRICTED = 3
};
+enum CharterTypes
+{
+ GUILD_CHARTER_TYPE = 9,
+ ARENA_TEAM_CHARTER_2v2_TYPE = 2,
+ ARENA_TEAM_CHARTER_3v3_TYPE = 3,
+ ARENA_TEAM_CHARTER_5v5_TYPE = 5
+};
+
/// Player session in the World
class WorldSession
{
@@ -272,11 +280,9 @@ class WorldSession
void SendDiscoverNewTaxiNode(uint32 nodeid);
// Guild/Arena Team
- void SendGuildCommandResult(uint32 typecmd, const std::string& str, uint32 cmdresult);
void SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id);
void SendNotInArenaTeamPacket(uint8 type);
void SendPetitionShowList(uint64 guid);
- void SendSaveGuildEmblem(uint32 msg);
void BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index f4117fb9671..27fa609ff16 100755
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1052,9 +1052,9 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = sConfig.GetIntDefault("Guild.EventLogRecordsCount", GUILD_EVENTLOG_MAX_RECORDS);
if (m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] < GUILD_EVENTLOG_MAX_RECORDS)
m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = GUILD_EVENTLOG_MAX_RECORDS;
- m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] = sConfig.GetIntDefault("Guild.BankEventLogRecordsCount", GUILD_BANK_MAX_LOGS);
- if (m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] < GUILD_BANK_MAX_LOGS)
- m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] = GUILD_BANK_MAX_LOGS;
+ m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] = sConfig.GetIntDefault("Guild.BankEventLogRecordsCount", GUILD_BANKLOG_MAX_RECORDS);
+ if (m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] < GUILD_BANKLOG_MAX_RECORDS)
+ m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] = GUILD_BANKLOG_MAX_RECORDS;
m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1);
if (m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
@@ -1530,7 +1530,7 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Auctions...");
sAuctionMgr.LoadAuctions();
- sLog.outString("Loading Guilds...");
+ sLog.outString("***** GUILDS *****");
sObjectMgr.LoadGuilds();
sLog.outString("Loading ArenaTeams...");
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 60e29f22f54..4963a0b89f3 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -88,7 +88,6 @@ bool CharacterDatabaseConnection::Open()
PrepareStatement(CHAR_LOAD_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE account = ?");
PrepareStatement(CHAR_LOAD_PLAYER_MAILITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, item_guid, item_template, owner_guid FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id = ?");
PrepareStatement(CHAR_LOAD_AUCTION_ITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, itemguid, item_template FROM auctionhouse JOIN item_instance ON itemguid = guid");
- PrepareStatement(CHAR_LOAD_GUILD_BANK_ITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, TabId, SlotId, item_guid, item_entry, guildid FROM guild_bank_item JOIN item_instance ON item_guid = guid");
PrepareStatement(CHAR_LOAD_ITEM_REFUNDS, "SELECT player_guid, paidMoney, paidExtendedCost FROM item_refund_instance WHERE item_guid = ? AND player_guid = ? LIMIT 1");
PrepareStatement(CHAR_LOAD_ITEM_BOP_TRADE, "SELECT allowedPlayers FROM item_soulbound_trade_data WHERE itemGuid = ? LIMIT 1");
PrepareStatement(CHAR_DEL_ITEM_BOP_TRADE, "DELETE FROM item_soulbound_trade_data WHERE itemGuid = ? LIMIT 1");
@@ -97,5 +96,120 @@ bool CharacterDatabaseConnection::Open()
PrepareStatement(CHAR_DEL_ITEM_INSTANCE, "DELETE FROM item_instance WHERE guid = ?");
PrepareStatement(CHAR_GET_ACCOUNT_BY_NAME, "SELECT account FROM characters WHERE name = ?");
+ // Guild handling
+ // 0: uint32, 1: string, 2: uint32, 3: string, 4: string, 5: uint64, 6-10: uint32, 11: uint64
+ PrepareStatement(CHAR_ADD_GUILD, "INSERT INTO guild (guildid, name, leaderguid, info, motd, createdate, EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, BankMoney) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ PrepareStatement(CHAR_DEL_GUILD, "DELETE FROM guild WHERE guildid = ?"); // 0: uint32
+ // 0: uint32, 1: uint32, 2: uint8, 4: string, 5: string
+ PrepareStatement(CHAR_ADD_GUILD_MEMBER, "INSERT INTO guild_member (guildid, guid, rank, pnote, offnote) VALUES (?, ?, ?, ?, ?)");
+ PrepareStatement(CHAR_DEL_GUILD_MEMBER, "DELETE FROM guild_member WHERE guid = ?"); // 0: uint32
+ PrepareStatement(CHAR_DEL_GUILD_MEMBERS, "DELETE FROM guild_member WHERE guildid = ?"); // 0: uint32
+ // 0: uint32, 1: uint8, 3: string, 4: uint32
+ PrepareStatement(CHAR_ADD_GUILD_RANK, "INSERT INTO guild_rank (guildid, rid, rname, rights) VALUES (?, ?, ?, ?)");
+ PrepareStatement(CHAR_DEL_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildid = ?"); // 0: uint32
+ PrepareStatement(CHAR_DEL_GUILD_LOWEST_RANK, "DELETE FROM guild_rank WHERE guildid = ? AND rid >= ?"); // 0: uint32, 1: uint8
+ PrepareStatement(CHAR_ADD_GUILD_BANK_TAB, "INSERT INTO guild_bank_tab (guildid, TabId) VALUES (?, ?)"); // 0: uint32, 1: uint8
+ PrepareStatement(CHAR_DEL_GUILD_BANK_TAB, "DELETE FROM guild_bank_tab WHERE guildid = ? AND TabId = ?"); // 0: uint32, 1: uint8
+ PrepareStatement(CHAR_DEL_GUILD_BANK_TABS, "DELETE FROM guild_bank_tab WHERE guildid = ?"); // 0: uint32
+ // 0: uint32, 1: uint8, 2: uint8, 3: uint32, 4: uint32
+ PrepareStatement(CHAR_ADD_GUILD_BANK_ITEM, "INSERT INTO guild_bank_item (guildid, TabId, SlotId, item_guid, item_entry) VALUES (?, ?, ?, ?, ?)");
+ PrepareStatement(CHAR_DEL_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?"); // 0: uint32, 1: uint8, 2: uint8
+ PrepareStatement(CHAR_DEL_GUILD_BANK_ITEMS, "DELETE FROM guild_bank_item WHERE guildid = ?"); // 0: uint32
+ PrepareStatement(CHAR_ADD_GUILD_BANK_RIGHT_DEFAULT, "INSERT INTO guild_bank_right (guildid, TabId, rid) VALUES (?, ?, ?)"); // 0: uint32, 1: uint8, 2: uint8
+ // 0: uint32, 1: uint8, 2: uint8, 3: uint8, 4: uint32
+ PrepareStatement(CHAR_ADD_GUILD_BANK_RIGHT, "INSERT INTO guild_bank_right (guildid, TabId, rid, gbright, SlotPerDay) VALUES (?, ?, ?, ?, ?)");
+ PrepareStatement(CHAR_DEL_GUILD_BANK_RIGHT, "DELETE FROM guild_bank_right WHERE guildid = ? AND TabId = ? AND rid = ?"); // 0: uint32, 1: uint8, 2: uint8
+ PrepareStatement(CHAR_DEL_GUILD_BANK_RIGHTS, "DELETE FROM guild_bank_right WHERE guildid = ?"); // 0: uint32
+ PrepareStatement(CHAR_DEL_GUILD_BANK_RIGHTS_FOR_RANK, "DELETE FROM guild_bank_right WHERE guildid = ? AND rid = ?"); // 0: uint32, 1: uint8
+ // 0-1: uint32, 2-3: uint8, 4-5: uint32, 6: uint16, 7: uint8, 8: uint64
+ PrepareStatement(CHAR_ADD_GUILD_BANK_EVENTLOG, "INSERT INTO guild_bank_eventlog (guildid, LogGuid, TabId, EventType, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ PrepareStatement(CHAR_DEL_GUILD_BANK_EVENTLOG, "DELETE FROM guild_bank_eventlog WHERE guildid = ? AND LogGuid = ? AND TabId = ?"); // 0: uint32, 1: uint32, 2: uint8
+ PrepareStatement(CHAR_DEL_GUILD_BANK_EVENTLOGS, "DELETE FROM guild_bank_eventlog WHERE guildid = ?"); // 0: uint32
+ // 0-1: uint32, 2: uint8, 3-4: uint32, 5: uint8, 6: uint64
+ PrepareStatement(CHAR_ADD_GUILD_EVENTLOG, "INSERT INTO guild_eventlog (guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp) VALUES (?, ?, ?, ?, ?, ?, ?)");
+ PrepareStatement(CHAR_DEL_GUILD_EVENTLOG, "DELETE FROM guild_eventlog WHERE guildid = ? AND LogGuid = ?"); // 0: uint32, 1: uint32
+ PrepareStatement(CHAR_DEL_GUILD_EVENTLOGS, "DELETE FROM guild_eventlog WHERE guildid = ?"); // 0: uint32
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_PNOTE, "UPDATE guild_member SET pnote = ? WHERE guid = ?"); // 0: string, 1: uint32
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_OFFNOTE, "UPDATE guild_member SET offnote = ? WHERE guid = ?"); // 0: string, 1: uint32
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_RANK, "UPDATE guild_member SET rank = ? WHERE guid = ?"); // 0: uint8, 1: uint32
+ PrepareStatement(CHAR_SET_GUILD_MOTD, "UPDATE guild SET motd = ? WHERE guildid = ?"); // 0: string, 1: uint32
+ PrepareStatement(CHAR_SET_GUILD_INFO, "UPDATE guild SET info = ? WHERE guildid = ?"); // 0: string, 1: uint32
+ PrepareStatement(CHAR_SET_GUILD_LEADER, "UPDATE guild SET leaderguid = ? WHERE guildid = ?"); // 0: uint32, 1: uint32
+ PrepareStatement(CHAR_SET_GUILD_RANK_NAME, "UPDATE guild_rank SET rname = ? WHERE rid = ? AND guildid = ?"); // 0: string, 1: uint8, 2: uint32
+ PrepareStatement(CHAR_SET_GUILD_RANK_RIGHTS, "UPDATE guild_rank SET rights = ? WHERE rid = ? AND guildid = ?"); // 0: uint32, 1: uint8, 2: uint32
+ // 0-5: uint32
+ PrepareStatement(CHAR_SET_GUILD_EMBLEM_INFO, "UPDATE guild SET EmblemStyle = ?, EmblemColor = ?, BorderStyle = ?, BorderColor = ?, BackgroundColor = ? WHERE guildid = ?");
+ // 0: string, 1: string, 2: uint32, 3: uint8
+ PrepareStatement(CHAR_SET_GUILD_BANK_TAB_INFO, "UPDATE guild_bank_tab SET TabName = ?,TabIcon = ? WHERE guildid = ? AND TabId = ?");
+ PrepareStatement(CHAR_SET_GUILD_BANK_MONEY, "UPDATE guild SET BankMoney = ? WHERE guildid = ?"); // 0: uint64, 1: uint32
+ // 0: uint8, 1: uint32, 2: uint8, 3: uint32
+ PrepareStatement(CHAR_SET_GUILD_BANK_EVENTLOG_TAB, "UPDATE guild_bank_eventlog SET TabId = ? WHERE guildid = ? AND TabId = ? AND LogGuid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_REM_MONEY, "UPDATE guild_member SET BankRemMoney = ? WHERE guildid = ? AND guid = ?"); // 0: uint32, 1: uint32, 2: uint32
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_TIME_MONEY, "UPDATE guild_member SET BankResetTimeMoney = ?, BankRemMoney = ? WHERE guildid = ? AND guid = ?"); // 0: uint32, 1: uint32, 2: uint32, 3: uint32
+ PrepareStatement(CHAR_RESET_GUILD_RANK_BANK_RESET_TIME, "UPDATE guild_member SET BankResetTimeMoney = 0 WHERE guildid = ? AND rank = ?"); // 0: uint32, 1: uint8
+ PrepareStatement(CHAR_SET_GUILD_RANK_BANK_MONEY, "UPDATE guild_rank SET BankMoneyPerDay = ? WHERE rid = ? AND guildid = ?"); // 0: uint32, 1: uint8, 2: uint32
+ PrepareStatement(CHAR_SET_GUILD_BANK_TAB_TEXT, "UPDATE guild_bank_tab SET TabText = ? WHERE guildid = ? AND TabId = ?"); // 0: string, 1: uint32, 2: uint8
+ // 0: uint32, 1: uint32, 2: uint32
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS0, "UPDATE guild_member SET BankRemSlotsTab0 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS1, "UPDATE guild_member SET BankRemSlotsTab1 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS2, "UPDATE guild_member SET BankRemSlotsTab2 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS3, "UPDATE guild_member SET BankRemSlotsTab3 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS4, "UPDATE guild_member SET BankRemSlotsTab4 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS5, "UPDATE guild_member SET BankRemSlotsTab5 = ? WHERE guildid = ? AND guid = ?");
+ // 0: uint32, 1: uint32, 2: uint32, 3: uint32
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS0, "UPDATE guild_member SET BankResetTimeTab0 = ?, BankRemSlotsTab0 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS1, "UPDATE guild_member SET BankResetTimeTab1 = ?, BankRemSlotsTab1 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS2, "UPDATE guild_member SET BankResetTimeTab2 = ?, BankRemSlotsTab2 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS3, "UPDATE guild_member SET BankResetTimeTab3 = ?, BankRemSlotsTab3 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS4, "UPDATE guild_member SET BankResetTimeTab4 = ?, BankRemSlotsTab4 = ? WHERE guildid = ? AND guid = ?");
+ PrepareStatement(CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS5, "UPDATE guild_member SET BankResetTimeTab5 = ?, BankRemSlotsTab5 = ? WHERE guildid = ? AND guid = ?");
+ // 0: uint32, 1: uint8
+ PrepareStatement(CHAR_RESET_GUILD_RANK_BANK_TIME0, "UPDATE guild_member SET BankResetTimeTab0 = 0 WHERE guildid = ? AND rank = ?");
+ PrepareStatement(CHAR_RESET_GUILD_RANK_BANK_TIME1, "UPDATE guild_member SET BankResetTimeTab1 = 0 WHERE guildid = ? AND rank = ?");
+ PrepareStatement(CHAR_RESET_GUILD_RANK_BANK_TIME2, "UPDATE guild_member SET BankResetTimeTab2 = 0 WHERE guildid = ? AND rank = ?");
+ PrepareStatement(CHAR_RESET_GUILD_RANK_BANK_TIME3, "UPDATE guild_member SET BankResetTimeTab3 = 0 WHERE guildid = ? AND rank = ?");
+ PrepareStatement(CHAR_RESET_GUILD_RANK_BANK_TIME4, "UPDATE guild_member SET BankResetTimeTab4 = 0 WHERE guildid = ? AND rank = ?");
+ PrepareStatement(CHAR_RESET_GUILD_RANK_BANK_TIME5, "UPDATE guild_member SET BankResetTimeTab5 = 0 WHERE guildid = ? AND rank = ?");
+ PrepareStatement(CHAR_LOAD_GUILDS,
+ // 0 1 2 3 4 5 6
+ "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) "
+ "FROM guild g LEFT JOIN guild_bank_tab gbt ON g.guildid = gbt.guildid GROUP BY g.guildid ORDER BY g.guildid ASC");
+ // 0 1 2 3 4
+ PrepareStatement(CHAR_LOAD_GUILD_RANKS, "SELECT guildid, rid, rname, rights, BankMoneyPerDay FROM guild_rank ORDER BY guildid ASC, rid ASC");
+ PrepareStatement(CHAR_LOAD_CHAR_DATA_FOR_GUILD, "SELECT name, level, class, zone, account FROM characters WHERE guid = ?");
+ PrepareStatement(CHAR_LOAD_GUILD_MEMBERS,
+ // 0 1 2 3 4 5 6
+ "SELECT guildid, gm.guid, rank, pnote, offnote, BankResetTimeMoney, BankRemMoney,"
+ // 7 8 9 10 11 12
+ "BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2,"
+ // 13 14 15 16 17 18
+ "BankResetTimeTab3, BankRemSlotsTab3, BankResetTimeTab4, BankRemSlotsTab4, BankResetTimeTab5, BankRemSlotsTab5,"
+ // 19 20 21 22 23 24
+ "c.name, c.level, c.class, c.zone, c.account, c.logout_time "
+ "FROM guild_member gm LEFT JOIN characters c ON c.guid = gm.guid ORDER BY guildid ASC");
+ PrepareStatement(CHAR_LOAD_GUILD_BANK_RIGHTS,
+ // 0 1 2 3 4
+ "SELECT guildid, TabId, rid, gbright, SlotPerDay FROM guild_bank_right ORDER BY guildid ASC, TabId ASC");
+ // 0 1 2 3 4
+ PrepareStatement(CHAR_LOAD_GUILD_BANK_TABS, "SELECT guildid, TabId, TabName, TabIcon, TabText FROM guild_bank_tab ORDER BY guildid ASC, TabId ASC");
+ PrepareStatement(CHAR_LOAD_GUILD_EVENTLOGS,
+ // 0 1 2 3 4 5 6
+ "SELECT guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp FROM guild_eventlog ORDER BY TimeStamp DESC, LogGuid DESC");
+ PrepareStatement(CHAR_LOAD_GUILD_BANK_EVENTLOGS,
+ // 0 1 2 3 4 5 6 7 8
+ "SELECT guildid, TabId, LogGuid, EventType, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp FROM guild_bank_eventlog ORDER BY TimeStamp DESC, LogGuid DESC");
+ PrepareStatement(CHAR_LOAD_GUILD_BANK_ITEMS,
+ // 0 1 2 3 4 5 6 7 8 9 10
+ "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, "
+ // 11 12 13 14 15
+ "guildid, TabId, SlotId, item_guid, item_entry FROM guild_bank_item INNER JOIN item_instance ON item_guid = guid");
+
+ PrepareStatement(CHAR_CLEAN_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildId NOT IN (SELECT guildid FROM guild)");
+ PrepareStatement(CHAR_CLEAN_GUILD_MEMBERS, "DELETE FROM guild_member WHERE guildId NOT IN (SELECT guildid FROM guild)");
+ PrepareStatement(CHAR_CLEAN_GUILD_BANK_TABS, "DELETE FROM guild_bank_tab WHERE guildId NOT IN (SELECT guildid FROM guild)");
+ PrepareStatement(CHAR_CLEAN_GUILD_BANK_RIGHTS, "DELETE FROM guild_bank_right WHERE guildId NOT IN (SELECT guildid FROM guild)");
+ PrepareStatement(CHAR_CLEAN_GUILD_BANK_ITEMS, "DELETE FROM guild_bank_item WHERE guildId NOT IN (SELECT guildid FROM guild)");
return true;
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index ae3c730d1a5..041afca2a23 100755
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -102,6 +102,81 @@ enum CharacterDatabaseStatements
CHAR_DEL_INVENTORY_ITEM,
CHAR_DEL_ITEM_INSTANCE,
CHAR_GET_ACCOUNT_BY_NAME,
+
+ CHAR_ADD_GUILD,
+ CHAR_DEL_GUILD,
+ CHAR_ADD_GUILD_MEMBER,
+ CHAR_DEL_GUILD_MEMBER,
+ CHAR_DEL_GUILD_MEMBERS,
+ CHAR_ADD_GUILD_RANK,
+ CHAR_DEL_GUILD_RANKS,
+ CHAR_DEL_GUILD_LOWEST_RANK,
+ CHAR_ADD_GUILD_BANK_TAB,
+ CHAR_DEL_GUILD_BANK_TAB,
+ CHAR_DEL_GUILD_BANK_TABS,
+ CHAR_ADD_GUILD_BANK_ITEM,
+ CHAR_DEL_GUILD_BANK_ITEM,
+ CHAR_DEL_GUILD_BANK_ITEMS,
+ CHAR_ADD_GUILD_BANK_RIGHT_DEFAULT,
+ CHAR_ADD_GUILD_BANK_RIGHT,
+ CHAR_DEL_GUILD_BANK_RIGHT,
+ CHAR_DEL_GUILD_BANK_RIGHTS,
+ CHAR_DEL_GUILD_BANK_RIGHTS_FOR_RANK,
+ CHAR_ADD_GUILD_BANK_EVENTLOG,
+ CHAR_DEL_GUILD_BANK_EVENTLOG,
+ CHAR_DEL_GUILD_BANK_EVENTLOGS,
+ CHAR_ADD_GUILD_EVENTLOG,
+ CHAR_DEL_GUILD_EVENTLOG,
+ CHAR_DEL_GUILD_EVENTLOGS,
+ CHAR_SET_GUILD_MEMBER_PNOTE,
+ CHAR_SET_GUILD_MEMBER_OFFNOTE,
+ CHAR_SET_GUILD_MEMBER_RANK,
+ CHAR_SET_GUILD_MOTD,
+ CHAR_SET_GUILD_INFO,
+ CHAR_SET_GUILD_LEADER,
+ CHAR_SET_GUILD_RANK_NAME,
+ CHAR_SET_GUILD_RANK_RIGHTS,
+ CHAR_SET_GUILD_EMBLEM_INFO,
+ CHAR_SET_GUILD_BANK_TAB_INFO,
+ CHAR_SET_GUILD_BANK_MONEY,
+ CHAR_SET_GUILD_BANK_EVENTLOG_TAB,
+ CHAR_SET_GUILD_MEMBER_BANK_REM_MONEY,
+ CHAR_SET_GUILD_MEMBER_BANK_TIME_MONEY,
+ CHAR_RESET_GUILD_RANK_BANK_RESET_TIME,
+ CHAR_SET_GUILD_RANK_BANK_MONEY,
+ CHAR_SET_GUILD_BANK_TAB_TEXT,
+ CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS0,
+ CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS1,
+ CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS2,
+ CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS3,
+ CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS4,
+ CHAR_SET_GUILD_MEMBER_BANK_TIME_REM_SLOTS5,
+ CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS0,
+ CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS1,
+ CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS2,
+ CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS3,
+ CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS4,
+ CHAR_SET_GUILD_MEMBER_BANK_REM_SLOTS5,
+ CHAR_RESET_GUILD_RANK_BANK_TIME0,
+ CHAR_RESET_GUILD_RANK_BANK_TIME1,
+ CHAR_RESET_GUILD_RANK_BANK_TIME2,
+ CHAR_RESET_GUILD_RANK_BANK_TIME3,
+ CHAR_RESET_GUILD_RANK_BANK_TIME4,
+ CHAR_RESET_GUILD_RANK_BANK_TIME5,
+ CHAR_LOAD_GUILDS,
+ CHAR_LOAD_GUILD_RANKS,
+ CHAR_LOAD_CHAR_DATA_FOR_GUILD,
+ CHAR_LOAD_GUILD_MEMBERS,
+ CHAR_LOAD_GUILD_BANK_RIGHTS,
+ CHAR_LOAD_GUILD_BANK_TABS,
+ CHAR_LOAD_GUILD_EVENTLOGS,
+ CHAR_LOAD_GUILD_BANK_EVENTLOGS,
+ CHAR_CLEAN_GUILD_RANKS,
+ CHAR_CLEAN_GUILD_MEMBERS,
+ CHAR_CLEAN_GUILD_BANK_TABS,
+ CHAR_CLEAN_GUILD_BANK_RIGHTS,
+ CHAR_CLEAN_GUILD_BANK_ITEMS,
+
MAX_CHARACTERDATABASE_STATEMENTS,
};