[8407] Extract from guild bank handler functions for 3 cases and move code to Guild...
[getmangos.git] / src / game / Guild.cpp
blob64be25aa964b398c80bcd9662f530c3928258b0b
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Database/DatabaseEnv.h"
20 #include "WorldPacket.h"
21 #include "WorldSession.h"
22 #include "Player.h"
23 #include "Opcodes.h"
24 #include "ObjectMgr.h"
25 #include "Guild.h"
26 #include "Chat.h"
27 #include "SocialMgr.h"
28 #include "Util.h"
29 #include "Language.h"
30 #include "World.h"
32 Guild::Guild()
34 m_Id = 0;
35 m_Name = "";
36 m_LeaderGuid = 0;
37 GINFO = MOTD = "";
38 m_EmblemStyle = 0;
39 m_EmblemColor = 0;
40 m_BorderStyle = 0;
41 m_BorderColor = 0;
42 m_BackgroundColor = 0;
44 m_CreatedYear = 0;
45 m_CreatedMonth = 0;
46 m_CreatedDay = 0;
48 m_EventLogLoaded = false;
49 m_GuildBankLoaded = false;
50 m_OnlineMembers = 0;
51 m_GuildBankMoney = 0;
52 m_PurchasedTabs = 0;
54 m_GuildEventLogNextGuid = 0;
55 m_GuildBankEventLogNextGuid_Money = 0;
56 for (uint8 i = 0; i < GUILD_BANK_MAX_TABS; i++)
57 m_GuildBankEventLogNextGuid_Item[i] = 0;
60 Guild::~Guild()
65 bool Guild::Create(Player* leader, std::string gname)
67 if(objmgr.GetGuildByName(gname))
68 return false;
70 WorldSession* lSession = leader->GetSession();
71 if(!lSession)
72 return false;
74 m_LeaderGuid = leader->GetGUID();
75 m_Name = gname;
76 GINFO = "";
77 MOTD = "No message set.";
78 m_GuildBankMoney = 0;
79 m_PurchasedTabs = 0;
80 m_Id = objmgr.GenerateGuildId();
82 sLog.outDebug("GUILD: creating guild %s to leader: %u", gname.c_str(), GUID_LOPART(m_LeaderGuid));
84 // gname already assigned to Guild::name, use it to encode string for DB
85 CharacterDatabase.escape_string(gname);
87 std::string dbGINFO = GINFO;
88 std::string dbMOTD = MOTD;
89 CharacterDatabase.escape_string(dbGINFO);
90 CharacterDatabase.escape_string(dbMOTD);
92 CharacterDatabase.BeginTransaction();
93 // CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid='%u'", Id); - MAX(guildid)+1 not exist
94 CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", m_Id);
95 CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guildid='%u'", m_Id);
96 CharacterDatabase.PExecute("INSERT INTO guild (guildid,name,leaderguid,info,motd,createdate,EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor,BankMoney) "
97 "VALUES('%u','%s','%u', '%s', '%s', NOW(),'%u','%u','%u','%u','%u','" UI64FMTD "')",
98 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);
99 CharacterDatabase.CommitTransaction();
101 CreateRank(lSession->GetMangosString(LANG_GUILD_MASTER), GR_RIGHT_ALL);
102 CreateRank(lSession->GetMangosString(LANG_GUILD_OFFICER), GR_RIGHT_ALL);
103 CreateRank(lSession->GetMangosString(LANG_GUILD_VETERAN), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
104 CreateRank(lSession->GetMangosString(LANG_GUILD_MEMBER), GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
105 CreateRank(lSession->GetMangosString(LANG_GUILD_INITIATE),GR_RIGHT_GCHATLISTEN | GR_RIGHT_GCHATSPEAK);
107 return AddMember(m_LeaderGuid, (uint32)GR_GUILDMASTER);
110 bool Guild::AddMember(uint64 plGuid, uint32 plRank)
112 Player* pl = objmgr.GetPlayer(plGuid);
113 if(pl)
115 if(pl->GetGuildId() != 0)
116 return false;
118 else
120 if(Player::GetGuildIdFromDB(plGuid) != 0) // player already in guild
121 return false;
124 // remove all player signs from another petitions
125 // this will be prevent attempt joining player to many guilds and corrupt guild data integrity
126 Player::RemovePetitionsAndSigns(plGuid, 9);
128 // fill player data
129 MemberSlot newmember;
131 if(!FillPlayerData(plGuid, &newmember)) // problems with player data collection
132 return false;
134 newmember.RankId = plRank;
135 newmember.OFFnote = (std::string)"";
136 newmember.Pnote = (std::string)"";
137 newmember.logout_time = time(NULL);
138 newmember.BankResetTimeMoney = 0; // this will force update at first query
139 for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
140 newmember.BankResetTimeTab[i] = 0;
141 members[GUID_LOPART(plGuid)] = newmember;
143 std::string dbPnote = newmember.Pnote;
144 std::string dbOFFnote = newmember.OFFnote;
145 CharacterDatabase.escape_string(dbPnote);
146 CharacterDatabase.escape_string(dbOFFnote);
148 CharacterDatabase.PExecute("INSERT INTO guild_member (guildid,guid,rank,pnote,offnote) VALUES ('%u', '%u', '%u','%s','%s')",
149 m_Id, GUID_LOPART(plGuid), newmember.RankId, dbPnote.c_str(), dbOFFnote.c_str());
151 // If player not in game data in data field will be loaded from guild tables, no need to update it!!
152 if(pl)
154 pl->SetInGuild(m_Id);
155 pl->SetRank(newmember.RankId);
156 pl->SetGuildIdInvited(0);
158 return true;
161 void Guild::SetMOTD(std::string motd)
163 MOTD = motd;
165 // motd now can be used for encoding to DB
166 CharacterDatabase.escape_string(motd);
167 CharacterDatabase.PExecute("UPDATE guild SET motd='%s' WHERE guildid='%u'", motd.c_str(), m_Id);
170 void Guild::SetGINFO(std::string ginfo)
172 GINFO = ginfo;
174 // ginfo now can be used for encoding to DB
175 CharacterDatabase.escape_string(ginfo);
176 CharacterDatabase.PExecute("UPDATE guild SET info='%s' WHERE guildid='%u'", ginfo.c_str(), m_Id);
179 bool Guild::LoadGuildFromDB(uint32 GuildId)
181 if(!LoadRanksFromDB(GuildId))
182 return false;
184 if(!LoadMembersFromDB(GuildId))
185 return false;
187 QueryResult *result = CharacterDatabase.PQuery("SELECT MAX(TabId) FROM guild_bank_tab WHERE guildid='%u'", GuildId);
188 if(result)
190 Field *fields = result->Fetch();
191 m_PurchasedTabs = fields[0].GetUInt8()+1; // Because TabId begins at 0
192 delete result;
194 else
195 m_PurchasedTabs = 0;
197 LoadBankRightsFromDB(GuildId); // Must be after LoadRanksFromDB because it populates rank struct
199 // 0 1 2 3 4 5 6
200 result = CharacterDatabase.PQuery("SELECT guildid, name, leaderguid, EmblemStyle, EmblemColor, BorderStyle, BorderColor,"
201 // 7 8 9 10 11
202 "BackgroundColor, info, motd, createdate, BankMoney FROM guild WHERE guildid = '%u'", GuildId);
204 if(!result)
205 return false;
207 Field *fields = result->Fetch();
209 m_Id = fields[0].GetUInt32();
210 m_Name = fields[1].GetCppString();
211 m_LeaderGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
213 m_EmblemStyle = fields[3].GetUInt32();
214 m_EmblemColor = fields[4].GetUInt32();
215 m_BorderStyle = fields[5].GetUInt32();
216 m_BorderColor = fields[6].GetUInt32();
217 m_BackgroundColor = fields[7].GetUInt32();
218 GINFO = fields[8].GetCppString();
219 MOTD = fields[9].GetCppString();
220 uint64 time = fields[10].GetUInt64(); //datetime is uint64 type ... YYYYmmdd:hh:mm:ss
221 m_GuildBankMoney = fields[11].GetUInt64();
223 delete result;
225 uint64 dTime = time /1000000;
226 m_CreatedDay = dTime%100;
227 m_CreatedMonth = (dTime/100)%100;
228 m_CreatedYear = (dTime/10000)%10000;
230 // If the leader does not exist attempt to promote another member
231 if(!objmgr.GetPlayerAccountIdByGUID(m_LeaderGuid ))
233 DelMember(m_LeaderGuid);
235 // check no members case (disbanded)
236 if(members.empty())
237 return false;
240 sLog.outDebug("Guild %u Creation time Loaded day: %u, month: %u, year: %u", GuildId, m_CreatedDay, m_CreatedMonth, m_CreatedYear);
242 return true;
245 bool Guild::LoadRanksFromDB(uint32 GuildId)
247 Field *fields;
248 QueryResult *result = CharacterDatabase.PQuery("SELECT rname,rights,BankMoneyPerDay,rid FROM guild_rank WHERE guildid = '%u' ORDER BY rid ASC", GuildId);
250 if(!result)
251 return false;
253 bool broken_ranks = false;
257 fields = result->Fetch();
259 std::string rankName = fields[0].GetCppString();
260 uint32 rankRights = fields[1].GetUInt32();
261 uint32 rankMoney = fields[2].GetUInt32();
262 uint32 rankRID = fields[3].GetUInt32();
264 if(rankRID != m_Ranks.size()+1) // guild_rank.rid always store rank+1
265 broken_ranks = true;
267 if(m_Ranks.size() == GR_GUILDMASTER) // prevent loss leader rights
268 rankRights |= GR_RIGHT_ALL;
270 AddRank(rankName,rankRights,rankMoney);
271 }while( result->NextRow() );
272 delete result;
274 if(m_Ranks.size()==0) // empty rank table?
276 AddRank("Guild Master",GR_RIGHT_ALL,0);
277 broken_ranks = true;
280 // guild_rank have wrong numbered ranks, repair
281 if(broken_ranks)
283 sLog.outError("Guild %u have broken `guild_rank` data, repairing...",GuildId);
284 CharacterDatabase.BeginTransaction();
285 CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", GuildId);
286 for(size_t i =0; i < m_Ranks.size(); ++i)
288 // guild_rank.rid always store rank+1
289 std::string name = m_Ranks[i].name;
290 uint32 rights = m_Ranks[i].rights;
291 CharacterDatabase.escape_string(name);
292 CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", GuildId, uint32(i+1), name.c_str(), rights);
294 CharacterDatabase.CommitTransaction();
297 return true;
300 bool Guild::LoadMembersFromDB(uint32 GuildId)
302 // 0 1 2 3 4 5
303 QueryResult *result = CharacterDatabase.PQuery("SELECT guild_member.guid,rank, pnote, offnote, BankResetTimeMoney,BankRemMoney,"
304 // 6 7 8 9 10 11
305 "BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2,"
306 // 12 13 14 15 16 17
307 "BankResetTimeTab3, BankRemSlotsTab3, BankResetTimeTab4, BankRemSlotsTab4, BankResetTimeTab5, BankRemSlotsTab5,"
308 // 18
309 "logout_time FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid WHERE guildid = '%u'", GuildId);
311 if(!result)
312 return false;
316 Field *fields = result->Fetch();
317 MemberSlot newmember;
318 newmember.RankId = fields[1].GetUInt32();
319 uint64 guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
321 // Player does not exist
322 if(!FillPlayerData(guid, &newmember))
323 continue;
325 newmember.Pnote = fields[2].GetCppString();
326 newmember.OFFnote = fields[3].GetCppString();
327 newmember.BankResetTimeMoney = fields[4].GetUInt32();
328 newmember.BankRemMoney = fields[5].GetUInt32();
329 for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
331 newmember.BankResetTimeTab[i] = fields[6+(2*i)].GetUInt32();
332 newmember.BankRemSlotsTab[i] = fields[7+(2*i)].GetUInt32();
334 newmember.logout_time = fields[18].GetUInt64();
335 members[GUID_LOPART(guid)] = newmember;
337 }while( result->NextRow() );
338 delete result;
340 if(members.empty())
341 return false;
343 return true;
346 bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot)
348 std::string plName;
349 uint32 plLevel;
350 uint32 plClass;
351 uint32 plZone;
353 Player* pl = objmgr.GetPlayer(guid);
354 if(pl)
356 plName = pl->GetName();
357 plLevel = pl->getLevel();
358 plClass = pl->getClass();
359 plZone = pl->GetZoneId();
361 else
363 QueryResult *result = CharacterDatabase.PQuery("SELECT name,level,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid));
364 if(!result)
365 return false; // player doesn't exist
367 Field *fields = result->Fetch();
369 plName = fields[0].GetCppString();
370 plLevel = fields[1].GetUInt32();
371 plZone = fields[2].GetUInt32();
372 plClass = fields[3].GetUInt32();
373 delete result;
375 if(plLevel<1||plLevel>STRONG_MAX_LEVEL) // can be at broken `data` field
377 sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid));
378 return false;
381 if(!plZone)
383 sLog.outError("Player (GUID: %u) has broken zone-data",GUID_LOPART(guid));
384 //here it will also try the same, to get the zone from characters-table, but additional it tries to find
385 plZone = Player::GetZoneIdFromDB(guid);
386 //the zone through xy coords.. this is a bit redundant, but
387 //shouldn't be called often
390 if(plClass<CLASS_WARRIOR||plClass>=MAX_CLASSES) // can be at broken `class` field
392 sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid));
393 return false;
397 memslot->name = plName;
398 memslot->level = plLevel;
399 memslot->Class = plClass;
400 memslot->zoneId = plZone;
402 return(true);
405 void Guild::LoadPlayerStatsByGuid(uint64 guid)
407 MemberList::iterator itr = members.find(GUID_LOPART(guid));
408 if (itr == members.end() )
409 return;
411 Player *pl = ObjectAccessor::FindPlayer(guid);
412 if(!pl)
413 return;
414 itr->second.name = pl->GetName();
415 itr->second.level = pl->getLevel();
416 itr->second.Class = pl->getClass();
419 void Guild::SetLeader(uint64 guid)
421 m_LeaderGuid = guid;
422 ChangeRank(guid, GR_GUILDMASTER);
424 CharacterDatabase.PExecute("UPDATE guild SET leaderguid='%u' WHERE guildid='%u'", GUID_LOPART(guid), m_Id);
427 void Guild::DelMember(uint64 guid, bool isDisbanding)
429 if(m_LeaderGuid == guid && !isDisbanding)
431 MemberSlot* oldLeader = NULL;
432 MemberSlot* best = NULL;
433 uint64 newLeaderGUID = 0;
434 for(Guild::MemberList::iterator i = members.begin(); i != members.end(); ++i)
436 if(i->first == GUID_LOPART(guid))
438 oldLeader = &(i->second);
439 continue;
442 if(!best || best->RankId > i->second.RankId)
444 best = &(i->second);
445 newLeaderGUID = i->first;
448 if(!best)
450 Disband();
451 return;
454 SetLeader(newLeaderGUID);
456 // If player not online data in data field will be loaded from guild tabs no need to update it !!
457 if(Player *newLeader = objmgr.GetPlayer(newLeaderGUID))
458 newLeader->SetRank(GR_GUILDMASTER);
460 // when leader non-exist (at guild load with deleted leader only) not send broadcasts
461 if(oldLeader)
463 WorldPacket data(SMSG_GUILD_EVENT, (1+1+(oldLeader->name).size()+1+(best->name).size()+1));
464 data << (uint8)GE_LEADER_CHANGED;
465 data << (uint8)2;
466 data << oldLeader->name;
467 data << best->name;
468 BroadcastPacket(&data);
470 data.Initialize(SMSG_GUILD_EVENT, (1+1+(oldLeader->name).size()+1));
471 data << (uint8)GE_LEFT;
472 data << (uint8)1;
473 data << oldLeader->name;
474 BroadcastPacket(&data);
477 sLog.outDebug( "WORLD: Sent (SMSG_GUILD_EVENT)" );
480 members.erase(GUID_LOPART(guid));
482 Player *player = objmgr.GetPlayer(guid);
483 // If player not online data in data field will be loaded from guild tabs no need to update it !!
484 if(player)
486 player->SetInGuild(0);
487 player->SetRank(0);
490 CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid));
493 void Guild::ChangeRank(uint64 guid, uint32 newRank)
495 MemberList::iterator itr = members.find(GUID_LOPART(guid));
496 if( itr != members.end() )
497 itr->second.RankId = newRank;
499 Player *player = objmgr.GetPlayer(guid);
500 // If player not online data in data field will be loaded from guild tabs no need to update it !!
501 if(player)
502 player->SetRank(newRank);
504 CharacterDatabase.PExecute( "UPDATE guild_member SET rank='%u' WHERE guid='%u'", newRank, GUID_LOPART(guid) );
507 void Guild::SetPNOTE(uint64 guid,std::string pnote)
509 MemberList::iterator itr = members.find(GUID_LOPART(guid));
510 if( itr == members.end() )
511 return;
513 itr->second.Pnote = pnote;
515 // pnote now can be used for encoding to DB
516 CharacterDatabase.escape_string(pnote);
517 CharacterDatabase.PExecute("UPDATE guild_member SET pnote = '%s' WHERE guid = '%u'", pnote.c_str(), itr->first);
520 void Guild::SetOFFNOTE(uint64 guid,std::string offnote)
522 MemberList::iterator itr = members.find(GUID_LOPART(guid));
523 if( itr == members.end() )
524 return;
525 itr->second.OFFnote = offnote;
526 // offnote now can be used for encoding to DB
527 CharacterDatabase.escape_string(offnote);
528 CharacterDatabase.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote.c_str(), itr->first);
531 void Guild::BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language)
533 if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_GCHATSPEAK))
535 WorldPacket data;
536 ChatHandler(session).FillMessageData(&data, CHAT_MSG_GUILD, language, 0, msg.c_str());
538 for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
540 Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
542 if (pl && pl->GetSession() && HasRankRight(pl->GetRank(),GR_RIGHT_GCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()) )
543 pl->GetSession()->SendPacket(&data);
548 void Guild::BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language)
550 if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_OFFCHATSPEAK))
552 for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
554 WorldPacket data;
555 ChatHandler::FillMessageData(&data, session, CHAT_MSG_OFFICER, language, NULL, 0, msg.c_str(),NULL);
557 Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
559 if (pl && pl->GetSession() && HasRankRight(pl->GetRank(),GR_RIGHT_OFFCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetGUIDLow()))
560 pl->GetSession()->SendPacket(&data);
565 void Guild::BroadcastPacket(WorldPacket *packet)
567 for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
569 Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
570 if(player)
571 player->GetSession()->SendPacket(packet);
575 void Guild::BroadcastPacketToRank(WorldPacket *packet, uint32 rankId)
577 for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
579 if (itr->second.RankId == rankId)
581 Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
582 if(player)
583 player->GetSession()->SendPacket(packet);
588 void Guild::CreateRank(std::string name_,uint32 rights)
590 if(m_Ranks.size() >= GUILD_MAX_RANKS)
591 return;
593 AddRank(name_,rights,0);
595 for (int i = 0; i < m_PurchasedTabs; ++i)
597 CreateBankRightForTab(m_Ranks.size()-1, uint8(i));
600 // guild_rank.rid always store rank+1 value
602 // name now can be used for encoding to DB
603 CharacterDatabase.escape_string(name_);
604 CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id, (unsigned int)m_Ranks.size(), name_.c_str(), rights );
607 void Guild::AddRank(const std::string& name_,uint32 rights, uint32 money)
609 m_Ranks.push_back(RankInfo(name_,rights,money));
612 void Guild::DelRank()
614 if(m_Ranks.empty())
615 return;
617 // guild_rank.rid always store rank+1 value
618 uint32 rank = m_Ranks.size()-1;
619 CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE rid>='%u' AND guildid='%u'", (rank+1), m_Id);
621 m_Ranks.pop_back();
624 std::string Guild::GetRankName(uint32 rankId)
626 if(rankId >= m_Ranks.size())
627 return "<unknown>";
629 return m_Ranks[rankId].name;
632 uint32 Guild::GetRankRights(uint32 rankId)
634 if(rankId >= m_Ranks.size())
635 return 0;
637 return m_Ranks[rankId].rights;
640 void Guild::SetRankName(uint32 rankId, std::string name_)
642 if(rankId >= m_Ranks.size())
643 return;
645 m_Ranks[rankId].name = name_;
647 // name now can be used for encoding to DB
648 CharacterDatabase.escape_string(name_);
649 CharacterDatabase.PExecute("UPDATE guild_rank SET rname='%s' WHERE rid='%u' AND guildid='%u'", name_.c_str(), (rankId+1), m_Id);
652 void Guild::SetRankRights(uint32 rankId, uint32 rights)
654 if(rankId >= m_Ranks.size())
655 return;
657 m_Ranks[rankId].rights = rights;
659 CharacterDatabase.PExecute("UPDATE guild_rank SET rights='%u' WHERE rid='%u' AND guildid='%u'", rights, (rankId+1), m_Id);
662 int32 Guild::GetRank(uint32 LowGuid)
664 MemberList::const_iterator itr = members.find(LowGuid);
665 if (itr==members.end())
666 return -1;
668 return itr->second.RankId;
671 void Guild::Disband()
673 WorldPacket data(SMSG_GUILD_EVENT, 1);
674 data << (uint8)GE_DISBANDED;
675 BroadcastPacket(&data);
677 while (!members.empty())
679 MemberList::const_iterator itr = members.begin();
680 DelMember(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER), true);
683 CharacterDatabase.BeginTransaction();
684 CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid = '%u'", m_Id);
685 CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid = '%u'", m_Id);
686 CharacterDatabase.PExecute("DELETE FROM guild_bank_tab WHERE guildid = '%u'", m_Id);
687 CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid = '%u'", m_Id);
688 CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", m_Id);
689 CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid = '%u'", m_Id);
690 CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid = '%u'", m_Id);
691 CharacterDatabase.CommitTransaction();
692 objmgr.RemoveGuild(m_Id);
695 void Guild::Roster(WorldSession *session)
697 // we can only guess size
698 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));
699 data << (uint32)members.size();
700 data << MOTD;
701 data << GINFO;
703 data << (uint32)m_Ranks.size();
704 for (RankList::const_iterator ritr = m_Ranks.begin(); ritr != m_Ranks.end(); ++ritr)
706 data << uint32(ritr->rights);
707 data << uint32(ritr->BankMoneyPerDay); // count of: withdraw gold(gold/day) Note: in game set gold, in packet set bronze.
708 for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
710 data << uint32(ritr->TabRight[i]); // for TAB_i rights: view tabs = 0x01, deposit items =0x02
711 data << uint32(ritr->TabSlotPerDay[i]); // for TAB_i count of: withdraw items(stack/day)
714 for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
716 if (Player *pl = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)))
718 data << uint64(pl->GetGUID());
719 data << uint8(1);
720 data << pl->GetName();
721 data << uint32(itr->second.RankId);
722 data << uint8(pl->getLevel());
723 data << uint8(pl->getClass());
724 data << uint8(0); // new 2.4.0
725 data << uint32(pl->GetZoneId());
726 data << itr->second.Pnote;
727 data << itr->second.OFFnote;
729 else
731 data << uint64(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
732 data << uint8(0);
733 data << itr->second.name;
734 data << uint32(itr->second.RankId);
735 data << uint8(itr->second.level);
736 data << uint8(itr->second.Class);
737 data << uint8(0); // new 2.4.0
738 data << uint32(itr->second.zoneId);
739 data << float(float(time(NULL)-itr->second.logout_time) / DAY);
740 data << itr->second.Pnote;
741 data << itr->second.OFFnote;
744 session->SendPacket(&data);;
745 sLog.outDebug( "WORLD: Sent (SMSG_GUILD_ROSTER)" );
748 void Guild::Query(WorldSession *session)
750 WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, (8*32+200));// we can only guess size
752 data << m_Id;
753 data << m_Name;
755 for (size_t i = 0 ; i < 10; ++i) // show always 10 ranks
757 if(i < m_Ranks.size())
758 data << m_Ranks[i].name;
759 else
760 data << (uint8)0; // null string
763 data << uint32(m_EmblemStyle);
764 data << uint32(m_EmblemColor);
765 data << uint32(m_BorderStyle);
766 data << uint32(m_BorderColor);
767 data << uint32(m_BackgroundColor);
768 data << uint32(0); // something new in WotLK
770 session->SendPacket( &data );
771 sLog.outDebug( "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)" );
774 void Guild::SetEmblem(uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor, uint32 backgroundColor)
776 m_EmblemStyle = emblemStyle;
777 m_EmblemColor = emblemColor;
778 m_BorderStyle = borderStyle;
779 m_BorderColor = borderColor;
780 m_BackgroundColor = backgroundColor;
782 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);
785 void Guild::UpdateLogoutTime(uint64 guid)
787 MemberList::iterator itr = members.find(GUID_LOPART(guid));
788 if (itr == members.end() )
789 return;
791 itr->second.logout_time = time(NULL);
793 if (m_OnlineMembers > 0)
794 --m_OnlineMembers;
795 else
797 UnloadGuildBank();
798 UnloadGuildEventLog();
802 // *************************************************
803 // Guild Eventlog part
804 // *************************************************
805 // Display guild eventlog
806 void Guild::DisplayGuildEventLog(WorldSession *session)
808 // Load guild eventlog, if not already done
809 if (!m_EventLogLoaded)
810 LoadGuildEventLogFromDB();
812 // Sending result
813 WorldPacket data(MSG_GUILD_EVENT_LOG_QUERY, 0);
814 // count, max count == 100
815 data << uint8(m_GuildEventLog.size());
816 for (GuildEventLog::const_iterator itr = m_GuildEventLog.begin(); itr != m_GuildEventLog.end(); ++itr)
818 // Event type
819 data << uint8(itr->EventType);
820 // Player 1
821 data << uint64(itr->PlayerGuid1);
822 // Player 2 not for left/join guild events
823 if (itr->EventType != GUILD_EVENT_LOG_JOIN_GUILD && itr->EventType != GUILD_EVENT_LOG_LEAVE_GUILD)
824 data << uint64(itr->PlayerGuid2);
825 // New Rank - only for promote/demote guild events
826 if (itr->EventType == GUILD_EVENT_LOG_PROMOTE_PLAYER || itr->EventType == GUILD_EVENT_LOG_DEMOTE_PLAYER)
827 data << uint8(itr->NewRank);
828 // Event timestamp
829 data << uint32(time(NULL)-itr->TimeStamp);
831 session->SendPacket(&data);
832 sLog.outDebug("WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)");
835 // Load guild eventlog from DB
836 void Guild::LoadGuildEventLogFromDB()
838 // Return if already loaded
839 if (m_EventLogLoaded)
840 return;
842 // 0 1 2 3 4 5
843 QueryResult *result = CharacterDatabase.PQuery("SELECT LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp FROM guild_eventlog WHERE guildid=%u ORDER BY TimeStamp DESC,LogGuid DESC LIMIT %u", m_Id, GUILD_EVENTLOG_MAX_RECORDS);
844 if(!result)
845 return;
846 bool isNextLogGuidSet = false;
847 //uint32 configCount = sWorld.getConfig(CONFIG_GUILD_EVENT_LOG_COUNT);
848 // First event in list will be the oldest and the latest event is last event in list
851 Field *fields = result->Fetch();
852 if (!isNextLogGuidSet)
854 m_GuildEventLogNextGuid = fields[0].GetUInt32();
855 isNextLogGuidSet = true;
857 // Fill entry
858 GuildEventLogEntry NewEvent;
859 NewEvent.EventType = fields[1].GetUInt8();
860 NewEvent.PlayerGuid1 = fields[2].GetUInt32();
861 NewEvent.PlayerGuid2 = fields[3].GetUInt32();
862 NewEvent.NewRank = fields[4].GetUInt8();
863 NewEvent.TimeStamp = fields[5].GetUInt64();
865 // There can be a problem if more events have same TimeStamp the ORDER can be broken when fields[0].GetUInt32() == configCount, but
866 // events with same timestamp can appear when there is lag, and we naivly suppose that mangos isn't laggy
867 // but if problem appears, player will see set of guild events that have same timestamp in bad order
869 // Add entry to list
870 m_GuildEventLog.push_front(NewEvent);
872 } while( result->NextRow() );
873 delete result;
875 m_EventLogLoaded = true;
878 // Unload guild eventlog
879 void Guild::UnloadGuildEventLog()
881 if (!m_EventLogLoaded)
882 return;
884 m_GuildEventLog.clear();
885 m_EventLogLoaded = false;
888 // Add entry to guild eventlog
889 void Guild::LogGuildEvent(uint8 EventType, uint32 PlayerGuid1, uint32 PlayerGuid2, uint8 NewRank)
891 GuildEventLogEntry NewEvent;
892 // Create event
893 NewEvent.EventType = EventType;
894 NewEvent.PlayerGuid1 = PlayerGuid1;
895 NewEvent.PlayerGuid2 = PlayerGuid2;
896 NewEvent.NewRank = NewRank;
897 NewEvent.TimeStamp = uint32(time(NULL));
898 // Count new LogGuid
899 m_GuildEventLogNextGuid = (m_GuildEventLogNextGuid + 1) % sWorld.getConfig(CONFIG_GUILD_EVENT_LOG_COUNT);
900 // Check max records limit
901 if (m_GuildEventLog.size() >= GUILD_EVENTLOG_MAX_RECORDS)
902 m_GuildEventLog.pop_front();
903 // Add event to list
904 m_GuildEventLog.push_back(NewEvent);
905 // Save event to DB
906 CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid='%u' AND LogGuid='%u'", m_Id, m_GuildEventLogNextGuid);
907 CharacterDatabase.PExecute("INSERT INTO guild_eventlog (guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','" UI64FMTD "')",
908 m_Id, m_GuildEventLogNextGuid, uint32(NewEvent.EventType), NewEvent.PlayerGuid1, NewEvent.PlayerGuid2, uint32(NewEvent.NewRank), NewEvent.TimeStamp);
911 // *************************************************
912 // Guild Bank part
913 // *************************************************
914 // Bank content related
915 void Guild::DisplayGuildBankContent(WorldSession *session, uint8 TabId)
917 WorldPacket data(SMSG_GUILD_BANK_LIST,1200);
919 GuildBankTab const* tab = GetBankTab(TabId);
920 if (!tab)
921 return;
923 if(!IsMemberHaveRights(session->GetPlayer()->GetGUIDLow(),TabId,GUILD_BANK_RIGHT_VIEW_TAB))
924 return;
926 data << uint64(GetGuildBankMoney());
927 data << uint8(TabId);
928 // remaining slots for today
929 data << uint32(GetMemberSlotWithdrawRem(session->GetPlayer()->GetGUIDLow(), TabId));
930 data << uint8(0); // Tell client this is a tab content packet
932 data << uint8(GUILD_BANK_MAX_SLOTS);
934 for (int i=0; i<GUILD_BANK_MAX_SLOTS; ++i)
935 AppendDisplayGuildBankSlot(data, tab, i);
937 session->SendPacket(&data);
939 sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
942 void Guild::DisplayGuildBankMoneyUpdate()
944 WorldPacket data(SMSG_GUILD_BANK_LIST, 8+1+4+1+1);
946 data << uint64(GetGuildBankMoney());
947 data << uint8(0); // TabId, default 0
948 data << uint32(0); // slot withdrow, default 0
949 data << uint8(0); // Tell client this is a tab content packet
950 data << uint8(0); // not send items
951 BroadcastPacket(&data);
953 sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
956 void Guild::DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2)
958 GuildBankTab const* tab = GetBankTab(TabId);
959 if (!tab)
960 return;
962 WorldPacket data(SMSG_GUILD_BANK_LIST,1200);
964 data << uint64(GetGuildBankMoney());
965 data << uint8(TabId);
966 // remaining slots for today
968 size_t rempos = data.wpos();
969 data << uint32(0); // will be filled later
970 data << uint8(0); // Tell client this is a tab content packet
972 if(slot2==-1) // single item in slot1
974 data << uint8(1);
976 AppendDisplayGuildBankSlot(data, tab, slot1);
978 else // 2 items (in slot1 and slot2)
980 data << uint8(2);
982 if(slot1 > slot2)
983 std::swap(slot1,slot2);
985 AppendDisplayGuildBankSlot(data, tab, slot1);
986 AppendDisplayGuildBankSlot(data, tab, slot2);
989 for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
991 Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
992 if(!player)
993 continue;
995 if(!IsMemberHaveRights(itr->first,TabId,GUILD_BANK_RIGHT_VIEW_TAB))
996 continue;
998 data.put<uint32>(rempos,uint32(GetMemberSlotWithdrawRem(player->GetGUIDLow(), TabId)));
1000 player->GetSession()->SendPacket(&data);
1003 sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
1006 void Guild::DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots)
1008 GuildBankTab const* tab = GetBankTab(TabId);
1009 if (!tab)
1010 return;
1012 WorldPacket data(SMSG_GUILD_BANK_LIST,1200);
1014 data << uint64(GetGuildBankMoney());
1015 data << uint8(TabId);
1016 // remaining slots for today
1018 size_t rempos = data.wpos();
1019 data << uint32(0); // will be filled later
1020 data << uint8(0); // Tell client this is a tab content packet
1022 data << uint8(slots.size()); // updates count
1024 for(GuildItemPosCountVec::const_iterator itr = slots.begin(); itr != slots.end(); ++itr)
1025 AppendDisplayGuildBankSlot(data, tab, itr->slot);
1027 for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
1029 Player *player = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
1030 if(!player)
1031 continue;
1033 if(!IsMemberHaveRights(itr->first,TabId,GUILD_BANK_RIGHT_VIEW_TAB))
1034 continue;
1036 data.put<uint32>(rempos,uint32(GetMemberSlotWithdrawRem(player->GetGUIDLow(), TabId)));
1038 player->GetSession()->SendPacket(&data);
1041 sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
1044 Item* Guild::GetItem(uint8 TabId, uint8 SlotId)
1046 if (TabId >= m_TabListMap.size() || SlotId >= GUILD_BANK_MAX_SLOTS)
1047 return NULL;
1048 return m_TabListMap[TabId]->Slots[SlotId];
1051 // *************************************************
1052 // Tab related
1054 void Guild::DisplayGuildBankTabsInfo(WorldSession *session)
1056 // Time to load bank if not already done
1057 if (!m_GuildBankLoaded)
1058 LoadGuildBankFromDB();
1060 WorldPacket data(SMSG_GUILD_BANK_LIST, 500);
1062 data << uint64(GetGuildBankMoney());
1063 data << uint8(0); // TabInfo packet must be for TabId 0
1064 data << uint32(0xFFFFFFFF); // bit 9 must be set for this packet to work
1065 data << uint8(1); // Tell Client this is a TabInfo packet
1067 data << uint8(m_PurchasedTabs); // here is the number of tabs
1069 for(int i = 0; i < m_PurchasedTabs; ++i)
1071 data << m_TabListMap[i]->Name.c_str();
1072 data << m_TabListMap[i]->Icon.c_str();
1074 data << uint8(0); // Do not send tab content
1075 session->SendPacket(&data);
1077 sLog.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
1080 void Guild::CreateNewBankTab()
1082 if (m_PurchasedTabs >= GUILD_BANK_MAX_TABS)
1083 return;
1085 ++m_PurchasedTabs;
1087 GuildBankTab* AnotherTab = new GuildBankTab;
1088 memset(AnotherTab->Slots, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*));
1089 m_TabListMap.resize(m_PurchasedTabs);
1090 m_TabListMap[m_PurchasedTabs-1] = AnotherTab;
1092 CharacterDatabase.BeginTransaction();
1093 CharacterDatabase.PExecute("DELETE FROM guild_bank_tab WHERE guildid='%u' AND TabId='%u'", m_Id, uint32(m_PurchasedTabs-1));
1094 CharacterDatabase.PExecute("INSERT INTO guild_bank_tab (guildid,TabId) VALUES ('%u','%u')", m_Id, uint32(m_PurchasedTabs-1));
1095 CharacterDatabase.CommitTransaction();
1098 void Guild::SetGuildBankTabInfo(uint8 TabId, std::string Name, std::string Icon)
1100 if (TabId >= GUILD_BANK_MAX_TABS)
1101 return;
1102 if (TabId >= m_TabListMap.size())
1103 return;
1105 if (!m_TabListMap[TabId])
1106 return;
1108 if(m_TabListMap[TabId]->Name == Name && m_TabListMap[TabId]->Icon == Icon)
1109 return;
1111 m_TabListMap[TabId]->Name = Name;
1112 m_TabListMap[TabId]->Icon = Icon;
1114 CharacterDatabase.escape_string(Name);
1115 CharacterDatabase.escape_string(Icon);
1116 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));
1119 void Guild::CreateBankRightForTab(uint32 rankId, uint8 TabId)
1121 sLog.outDebug("CreateBankRightForTab. rank: %u, TabId: %u", rankId, uint32(TabId));
1122 if (rankId >= m_Ranks.size() || TabId >= GUILD_BANK_MAX_TABS)
1123 return;
1125 m_Ranks[rankId].TabRight[TabId]=0;
1126 m_Ranks[rankId].TabSlotPerDay[TabId]=0;
1127 CharacterDatabase.BeginTransaction();
1128 CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u' AND TabId = '%u' AND rid = '%u'", m_Id, uint32(TabId), rankId);
1129 CharacterDatabase.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid) VALUES ('%u','%u','%u')", m_Id, uint32(TabId), rankId);
1130 CharacterDatabase.CommitTransaction();
1133 uint32 Guild::GetBankRights(uint32 rankId, uint8 TabId) const
1135 if(rankId >= m_Ranks.size() || TabId >= GUILD_BANK_MAX_TABS)
1136 return 0;
1138 return m_Ranks[rankId].TabRight[TabId];
1141 // *************************************************
1142 // Guild bank loading/unloading related
1144 // This load should be called when the bank is first accessed by a guild member
1145 void Guild::LoadGuildBankFromDB()
1147 if (m_GuildBankLoaded)
1148 return;
1150 m_GuildBankLoaded = true;
1151 LoadGuildBankEventLogFromDB();
1153 // 0 1 2 3
1154 QueryResult *result = CharacterDatabase.PQuery("SELECT TabId, TabName, TabIcon, TabText FROM guild_bank_tab WHERE guildid='%u' ORDER BY TabId", m_Id);
1155 if(!result)
1157 m_PurchasedTabs = 0;
1158 return;
1161 m_TabListMap.resize(m_PurchasedTabs);
1164 Field *fields = result->Fetch();
1165 uint8 TabId = fields[0].GetUInt8();
1167 GuildBankTab *NewTab = new GuildBankTab;
1168 memset(NewTab->Slots, 0, GUILD_BANK_MAX_SLOTS * sizeof(Item*));
1170 NewTab->Name = fields[1].GetCppString();
1171 NewTab->Icon = fields[2].GetCppString();
1172 NewTab->Text = fields[3].GetCppString();
1174 m_TabListMap[TabId] = NewTab;
1175 }while( result->NextRow() );
1177 delete result;
1179 // data needs to be at first place for Item::LoadFromDB
1180 // 0 1 2 3 4
1181 result = CharacterDatabase.PQuery("SELECT data, TabId, SlotId, item_guid, item_entry FROM guild_bank_item JOIN item_instance ON item_guid = guid WHERE guildid='%u' ORDER BY TabId", m_Id);
1182 if(!result)
1183 return;
1187 Field *fields = result->Fetch();
1188 uint8 TabId = fields[1].GetUInt8();
1189 uint8 SlotId = fields[2].GetUInt8();
1190 uint32 ItemGuid = fields[3].GetUInt32();
1191 uint32 ItemEntry = fields[4].GetUInt32();
1193 if (TabId >= m_PurchasedTabs || TabId >= GUILD_BANK_MAX_TABS)
1195 sLog.outError( "Guild::LoadGuildBankFromDB: Invalid tab for item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid,ItemEntry);
1196 continue;
1199 if (SlotId >= GUILD_BANK_MAX_SLOTS)
1201 sLog.outError( "Guild::LoadGuildBankFromDB: Invalid slot for item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid,ItemEntry);
1202 continue;
1205 ItemPrototype const *proto = objmgr.GetItemPrototype(ItemEntry);
1207 if(!proto)
1209 sLog.outError( "Guild::LoadGuildBankFromDB: Unknown item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid,ItemEntry);
1210 continue;
1213 Item *pItem = NewItemOrBag(proto);
1214 if(!pItem->LoadFromDB(ItemGuid, 0, result))
1216 CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", m_Id, uint32(TabId), uint32(SlotId));
1217 sLog.outError("Item GUID %u not found in item_instance, deleting from Guild Bank!", ItemGuid);
1218 delete pItem;
1219 continue;
1222 pItem->AddToWorld();
1223 m_TabListMap[TabId]->Slots[SlotId] = pItem;
1224 }while( result->NextRow() );
1226 delete result;
1229 // This unload should be called when the last member of the guild gets offline
1230 void Guild::UnloadGuildBank()
1232 if (!m_GuildBankLoaded)
1233 return;
1234 for (uint8 i = 0 ; i < m_PurchasedTabs ; ++i )
1236 for (uint8 j = 0 ; j < GUILD_BANK_MAX_SLOTS ; ++j)
1238 if (m_TabListMap[i]->Slots[j])
1240 m_TabListMap[i]->Slots[j]->RemoveFromWorld();
1241 delete m_TabListMap[i]->Slots[j];
1244 delete m_TabListMap[i];
1246 m_TabListMap.clear();
1248 UnloadGuildBankEventLog();
1249 m_GuildBankLoaded = false;
1252 // *************************************************
1253 // Money deposit/withdraw related
1255 void Guild::SendMoneyInfo(WorldSession *session, uint32 LowGuid)
1257 WorldPacket data(MSG_GUILD_BANK_MONEY_WITHDRAWN, 4);
1258 data << uint32(GetMemberMoneyWithdrawRem(LowGuid));
1259 session->SendPacket(&data);
1260 sLog.outDebug("WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN");
1263 bool Guild::MemberMoneyWithdraw(uint32 amount, uint32 LowGuid)
1265 uint32 MoneyWithDrawRight = GetMemberMoneyWithdrawRem(LowGuid);
1267 if (MoneyWithDrawRight < amount || GetGuildBankMoney() < amount)
1268 return false;
1270 SetBankMoney(GetGuildBankMoney()-amount);
1272 if (MoneyWithDrawRight < WITHDRAW_MONEY_UNLIMITED)
1274 MemberList::iterator itr = members.find(LowGuid);
1275 if (itr == members.end() )
1276 return false;
1277 itr->second.BankRemMoney -= amount;
1278 CharacterDatabase.PExecute("UPDATE guild_member SET BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'",
1279 itr->second.BankRemMoney, m_Id, LowGuid);
1281 return true;
1284 void Guild::SetBankMoney(int64 money)
1286 if (money < 0) // I don't know how this happens, it does!!
1287 money = 0;
1288 m_GuildBankMoney = money;
1290 CharacterDatabase.PExecute("UPDATE guild SET BankMoney='" UI64FMTD "' WHERE guildid='%u'", money, m_Id);
1293 // *************************************************
1294 // Item per day and money per day related
1296 bool Guild::MemberItemWithdraw(uint8 TabId, uint32 LowGuid)
1298 uint32 SlotsWithDrawRight = GetMemberSlotWithdrawRem(LowGuid, TabId);
1300 if (SlotsWithDrawRight == 0)
1301 return false;
1303 if (SlotsWithDrawRight < WITHDRAW_SLOT_UNLIMITED)
1305 MemberList::iterator itr = members.find(LowGuid);
1306 if (itr == members.end() )
1307 return false;
1308 --itr->second.BankRemSlotsTab[TabId];
1309 CharacterDatabase.PExecute("UPDATE guild_member SET BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'",
1310 uint32(TabId), itr->second.BankRemSlotsTab[TabId], m_Id, LowGuid);
1312 return true;
1315 bool Guild::IsMemberHaveRights(uint32 LowGuid, uint8 TabId, uint32 rights) const
1317 MemberList::const_iterator itr = members.find(LowGuid);
1318 if (itr == members.end() )
1319 return false;
1321 if (itr->second.RankId == GR_GUILDMASTER)
1322 return true;
1324 return (GetBankRights(itr->second.RankId,TabId) & rights)==rights;
1327 uint32 Guild::GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId)
1329 MemberList::iterator itr = members.find(LowGuid);
1330 if (itr == members.end() )
1331 return 0;
1333 if (itr->second.RankId == GR_GUILDMASTER)
1334 return WITHDRAW_SLOT_UNLIMITED;
1336 if((GetBankRights(itr->second.RankId,TabId) & GUILD_BANK_RIGHT_VIEW_TAB)!=GUILD_BANK_RIGHT_VIEW_TAB)
1337 return 0;
1339 uint32 curTime = uint32(time(NULL)/MINUTE);
1340 if (curTime - itr->second.BankResetTimeTab[TabId] >= 24*HOUR/MINUTE)
1342 itr->second.BankResetTimeTab[TabId] = curTime;
1343 itr->second.BankRemSlotsTab[TabId] = GetBankSlotPerDay(itr->second.RankId, TabId);
1344 CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeTab%u='%u',BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'",
1345 uint32(TabId), itr->second.BankResetTimeTab[TabId], uint32(TabId), itr->second.BankRemSlotsTab[TabId], m_Id, LowGuid);
1347 return itr->second.BankRemSlotsTab[TabId];
1350 uint32 Guild::GetMemberMoneyWithdrawRem(uint32 LowGuid)
1352 MemberList::iterator itr = members.find(LowGuid);
1353 if (itr == members.end() )
1354 return 0;
1356 if (itr->second.RankId == GR_GUILDMASTER)
1357 return WITHDRAW_MONEY_UNLIMITED;
1359 uint32 curTime = uint32(time(NULL)/MINUTE); // minutes
1360 // 24 hours
1361 if (curTime > itr->second.BankResetTimeMoney + 24*HOUR/MINUTE)
1363 itr->second.BankResetTimeMoney = curTime;
1364 itr->second.BankRemMoney = GetBankMoneyPerDay(itr->second.RankId);
1365 CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeMoney='%u',BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'",
1366 itr->second.BankResetTimeMoney, itr->second.BankRemMoney, m_Id, LowGuid);
1368 return itr->second.BankRemMoney;
1371 void Guild::SetBankMoneyPerDay(uint32 rankId, uint32 money)
1373 if (rankId >= m_Ranks.size())
1374 return;
1376 if (rankId == GR_GUILDMASTER)
1377 money = WITHDRAW_MONEY_UNLIMITED;
1379 m_Ranks[rankId].BankMoneyPerDay = money;
1381 for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
1382 if (itr->second.RankId == rankId)
1383 itr->second.BankResetTimeMoney = 0;
1385 CharacterDatabase.PExecute("UPDATE guild_rank SET BankMoneyPerDay='%u' WHERE rid='%u' AND guildid='%u'", money, (rankId+1), m_Id);
1386 CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeMoney='0' WHERE guildid='%u' AND rank='%u'", m_Id, rankId);
1389 void Guild::SetBankRightsAndSlots(uint32 rankId, uint8 TabId, uint32 right, uint32 nbSlots, bool db)
1391 if(rankId >= m_Ranks.size() ||
1392 TabId >= GUILD_BANK_MAX_TABS ||
1393 TabId >= m_PurchasedTabs)
1394 return;
1396 if (rankId == GR_GUILDMASTER)
1398 nbSlots = WITHDRAW_SLOT_UNLIMITED;
1399 right = GUILD_BANK_RIGHT_FULL;
1402 m_Ranks[rankId].TabSlotPerDay[TabId]=nbSlots;
1403 m_Ranks[rankId].TabRight[TabId]=right;
1405 if (db)
1407 for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
1408 if (itr->second.RankId == rankId)
1409 for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
1410 itr->second.BankResetTimeTab[i] = 0;
1412 CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid='%u' AND TabId='%u' AND rid='%u'", m_Id, uint32(TabId), rankId);
1413 CharacterDatabase.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid,gbright,SlotPerDay) VALUES "
1414 "('%u','%u','%u','%u','%u')", m_Id, uint32(TabId), rankId, m_Ranks[rankId].TabRight[TabId], m_Ranks[rankId].TabSlotPerDay[TabId]);
1415 CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeTab%u='0' WHERE guildid='%u' AND rank='%u'", uint32(TabId), m_Id, rankId);
1419 uint32 Guild::GetBankMoneyPerDay(uint32 rankId)
1421 if(rankId >= m_Ranks.size())
1422 return 0;
1424 if (rankId == GR_GUILDMASTER)
1425 return WITHDRAW_MONEY_UNLIMITED;
1426 return m_Ranks[rankId].BankMoneyPerDay;
1429 uint32 Guild::GetBankSlotPerDay(uint32 rankId, uint8 TabId)
1431 if(rankId >= m_Ranks.size() || TabId >= GUILD_BANK_MAX_TABS)
1432 return 0;
1434 if (rankId == GR_GUILDMASTER)
1435 return WITHDRAW_SLOT_UNLIMITED;
1436 return m_Ranks[rankId].TabSlotPerDay[TabId];
1439 // *************************************************
1440 // Rights per day related
1442 void Guild::LoadBankRightsFromDB(uint32 GuildId)
1444 // 0 1 2 3
1445 QueryResult *result = CharacterDatabase.PQuery("SELECT TabId, rid, gbright, SlotPerDay FROM guild_bank_right WHERE guildid = '%u' ORDER BY TabId", GuildId);
1447 if(!result)
1448 return;
1452 Field *fields = result->Fetch();
1453 uint8 TabId = fields[0].GetUInt8();
1454 uint32 rankId = fields[1].GetUInt32();
1455 uint16 right = fields[2].GetUInt16();
1456 uint16 SlotPerDay = fields[3].GetUInt16();
1458 SetBankRightsAndSlots(rankId, TabId, right, SlotPerDay, false);
1460 }while( result->NextRow() );
1461 delete result;
1463 return;
1466 // *************************************************
1467 // Bank log related
1469 void Guild::LoadGuildBankEventLogFromDB()
1471 // Money log is in TabId = GUILD_BANK_MONEY_LOGS_TAB
1473 //uint32 configCount = sWorld.getConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT);
1474 //cycle through all purchased guild bank item tabs
1475 for (uint32 tabId = 0; tabId < m_PurchasedTabs; tabId++)
1477 // 0 1 2 3 4 5 6
1478 QueryResult *result = CharacterDatabase.PQuery("SELECT LogGuid, EventType, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp FROM guild_bank_eventlog WHERE guildid='%u' AND TabId='%u' ORDER BY TimeStamp DESC,LogGuid DESC LIMIT %u", m_Id, tabId, GUILD_BANK_MAX_LOGS);
1479 if(!result)
1480 continue;
1482 bool isNextLogGuidSet = false;
1485 Field *fields = result->Fetch();
1487 GuildBankEventLogEntry NewEvent;
1488 NewEvent.EventType = fields[1].GetUInt8();
1489 NewEvent.PlayerGuid = fields[2].GetUInt32();
1490 NewEvent.ItemOrMoney = fields[3].GetUInt32();
1491 NewEvent.ItemStackCount = fields[4].GetUInt8();
1492 NewEvent.DestTabId = fields[5].GetUInt8();
1493 NewEvent.TimeStamp = fields[6].GetUInt64();
1495 //if newEvent is moneyEvent, move it to moneyEventTab in DB and report error
1496 if (NewEvent.isMoneyEvent())
1498 uint32 logGuid = fields[0].GetUInt32();
1499 CharacterDatabase.PExecute("UPDATE guild_bank_eventlog SET TabId='%u' WHERE guildid='%u' AND TabId='%u' AND LogGuid='%u'", GUILD_BANK_MONEY_LOGS_TAB, m_Id, tabId, logGuid);
1500 sLog.outError("GuildBankEventLog ERROR: MoneyEvent LogGuid %u for Guild %u had incorrectly set its TabId to %u, correcting it to %u TabId", logGuid, m_Id, tabId, GUILD_BANK_MONEY_LOGS_TAB);
1501 continue;
1503 else
1504 //add event to list
1505 //events are ordered from oldest (in beginning) to latest (in the end)
1506 m_GuildBankEventLog_Item[tabId].push_front(NewEvent);
1508 if (!isNextLogGuidSet)
1510 m_GuildBankEventLogNextGuid_Item[tabId] = fields[0].GetUInt32();
1511 //we don't have to do m_GuildBankEventLogNextGuid_Item[tabId] %= configCount; - it will be done when creating new record
1512 isNextLogGuidSet = true;
1514 } while( result->NextRow() );
1515 delete result;
1518 //special handle for guild bank money log
1519 // 0 1 2 3 4 5 6
1520 QueryResult *result = CharacterDatabase.PQuery("SELECT LogGuid, EventType, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp FROM guild_bank_eventlog WHERE guildid='%u' AND TabId='%u' ORDER BY TimeStamp DESC,LogGuid DESC LIMIT %u", m_Id, GUILD_BANK_MONEY_LOGS_TAB, GUILD_BANK_MAX_LOGS);
1521 if(!result)
1522 return;
1524 bool isNextMoneyLogGuidSet = false;
1527 Field *fields = result->Fetch();
1528 if (!isNextMoneyLogGuidSet)
1530 m_GuildBankEventLogNextGuid_Money = fields[0].GetUInt32();
1531 //we don't have to do m_GuildBankEventLogNextGuid_Money %= configCount; - it will be done when creating new record
1532 isNextMoneyLogGuidSet = true;
1534 GuildBankEventLogEntry NewEvent;
1536 NewEvent.EventType = fields[1].GetUInt8();
1537 NewEvent.PlayerGuid = fields[2].GetUInt32();
1538 NewEvent.ItemOrMoney = fields[3].GetUInt32();
1539 NewEvent.ItemStackCount = fields[4].GetUInt8();
1540 NewEvent.DestTabId = fields[5].GetUInt8();
1541 NewEvent.TimeStamp = fields[6].GetUInt64();
1543 //if newEvent is not moneyEvent, then report error
1544 if (!NewEvent.isMoneyEvent())
1545 sLog.outError("GuildBankEventLog ERROR: MoneyEvent LogGuid %u for Guild %u is not MoneyEvent - ignoring...", fields[0].GetUInt32(), m_Id);
1546 else
1547 //add event to list
1548 //events are ordered from oldest (in beginning) to latest (in the end)
1549 m_GuildBankEventLog_Money.push_front(NewEvent);
1551 } while( result->NextRow() );
1552 delete result;
1555 void Guild::UnloadGuildBankEventLog()
1557 m_GuildBankEventLog_Money.clear();
1559 for (int i = 0; i < GUILD_BANK_MAX_TABS; ++i)
1560 m_GuildBankEventLog_Item[i].clear();
1563 void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
1565 if (TabId > GUILD_BANK_MAX_TABS)
1566 return;
1568 if (TabId == GUILD_BANK_MAX_TABS)
1570 // Here we display money logs
1571 WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, m_GuildBankEventLog_Money.size()*(4*4+1)+1+1);
1572 data << uint8(TabId); // Here GUILD_BANK_MAX_TABS
1573 data << uint8(m_GuildBankEventLog_Money.size()); // number of log entries
1574 for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Money.begin(); itr != m_GuildBankEventLog_Money.end(); ++itr)
1576 data << uint8(itr->EventType);
1577 data << uint64(MAKE_NEW_GUID(itr->PlayerGuid,0,HIGHGUID_PLAYER));
1578 if (itr->EventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
1579 itr->EventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
1580 itr->EventType == GUILD_BANK_LOG_REPAIR_MONEY ||
1581 itr->EventType == GUILD_BANK_LOG_UNK1 ||
1582 itr->EventType == GUILD_BANK_LOG_UNK2)
1584 data << uint32(itr->ItemOrMoney);
1586 else
1588 data << uint32(itr->ItemOrMoney);
1589 data << uint32(itr->ItemStackCount);
1590 if (itr->EventType == GUILD_BANK_LOG_MOVE_ITEM || itr->EventType == GUILD_BANK_LOG_MOVE_ITEM2)
1591 data << uint8(itr->DestTabId); // moved tab
1593 data << uint32(time(NULL) - itr->TimeStamp);
1595 session->SendPacket(&data);
1597 else
1599 // here we display current tab logs
1600 WorldPacket data(MSG_GUILD_BANK_LOG_QUERY, m_GuildBankEventLog_Item[TabId].size()*(4*4+1+1)+1+1);
1601 data << uint8(TabId); // Here a real Tab Id
1602 // number of log entries
1603 data << uint8(m_GuildBankEventLog_Item[TabId].size());
1604 for (GuildBankEventLog::const_iterator itr = m_GuildBankEventLog_Item[TabId].begin(); itr != m_GuildBankEventLog_Item[TabId].end(); ++itr)
1606 data << uint8(itr->EventType);
1607 data << uint64(MAKE_NEW_GUID(itr->PlayerGuid,0,HIGHGUID_PLAYER));
1608 if (itr->EventType == GUILD_BANK_LOG_DEPOSIT_MONEY ||
1609 itr->EventType == GUILD_BANK_LOG_WITHDRAW_MONEY ||
1610 itr->EventType == GUILD_BANK_LOG_REPAIR_MONEY ||
1611 itr->EventType == GUILD_BANK_LOG_UNK1 ||
1612 itr->EventType == GUILD_BANK_LOG_UNK2)
1614 data << uint32(itr->ItemOrMoney);
1616 else
1618 data << uint32(itr->ItemOrMoney);
1619 data << uint32(itr->ItemStackCount);
1620 if (itr->EventType == GUILD_BANK_LOG_MOVE_ITEM || itr->EventType == GUILD_BANK_LOG_MOVE_ITEM2)
1621 data << uint8(itr->DestTabId); // moved tab
1623 data << uint32(time(NULL) - itr->TimeStamp);
1625 session->SendPacket(&data);
1627 sLog.outDebug("WORLD: Sent (MSG_GUILD_BANK_LOG_QUERY)");
1630 void Guild::LogBankEvent(uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount, uint8 DestTabId)
1632 //create Event
1633 GuildBankEventLogEntry NewEvent;
1634 NewEvent.EventType = EventType;
1635 NewEvent.PlayerGuid = PlayerGuidLow;
1636 NewEvent.ItemOrMoney = ItemOrMoney;
1637 NewEvent.ItemStackCount = ItemStackCount;
1638 NewEvent.DestTabId = DestTabId;
1639 NewEvent.TimeStamp = uint32(time(NULL));
1641 //add new event to the end of event list
1642 uint32 currentTabId = TabId;
1643 uint32 currentLogGuid = 0;
1644 if (NewEvent.isMoneyEvent())
1646 m_GuildBankEventLogNextGuid_Money = (m_GuildBankEventLogNextGuid_Money + 1) % sWorld.getConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT);
1647 currentLogGuid = m_GuildBankEventLogNextGuid_Money;
1648 currentTabId = GUILD_BANK_MONEY_LOGS_TAB;
1649 if (m_GuildBankEventLog_Money.size() >= GUILD_BANK_MAX_LOGS)
1650 m_GuildBankEventLog_Money.pop_front();
1652 m_GuildBankEventLog_Money.push_back(NewEvent);
1654 else
1656 m_GuildBankEventLogNextGuid_Item[TabId] = ((m_GuildBankEventLogNextGuid_Item[TabId]) + 1) % sWorld.getConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT);
1657 currentLogGuid = m_GuildBankEventLogNextGuid_Item[TabId];
1658 if (m_GuildBankEventLog_Item[TabId].size() >= GUILD_BANK_MAX_LOGS)
1659 m_GuildBankEventLog_Item[TabId].pop_front();
1661 m_GuildBankEventLog_Item[TabId].push_back(NewEvent);
1664 //save event to database
1665 CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u' AND TabId='%u'", m_Id, currentLogGuid, currentTabId);
1667 CharacterDatabase.PExecute("INSERT INTO guild_bank_eventlog (guildid,LogGuid,TabId,EventType,PlayerGuid,ItemOrMoney,ItemStackCount,DestTabId,TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','%u','%u','" UI64FMTD "')",
1668 m_Id, currentLogGuid, currentTabId, uint32(NewEvent.EventType), NewEvent.PlayerGuid, NewEvent.ItemOrMoney, uint32(NewEvent.ItemStackCount), uint32(NewEvent.DestTabId), NewEvent.TimeStamp);
1671 bool Guild::AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry )
1673 CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid = '%u' AND TabId = '%u'AND SlotId = '%u'", GuildId, BankTab, BankTabSlot);
1674 CharacterDatabase.PExecute("INSERT INTO guild_bank_item (guildid,TabId,SlotId,item_guid,item_entry) "
1675 "VALUES ('%u', '%u', '%u', '%u', '%u')", GuildId, BankTab, BankTabSlot, GUIDLow, Entry);
1676 return true;
1679 void Guild::AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *tab, int slot )
1681 Item *pItem = tab->Slots[slot];
1682 uint32 entry = pItem ? pItem->GetEntry() : 0;
1684 data << uint8(slot);
1685 data << uint32(entry);
1686 if (entry)
1688 // random item property id +8
1689 data << (uint32) pItem->GetItemRandomPropertyId();
1690 if (pItem->GetItemRandomPropertyId())
1691 // SuffixFactor +4
1692 data << (uint32) pItem->GetItemSuffixFactor();
1693 // +12 // ITEM_FIELD_STACK_COUNT
1694 data << uint32(pItem->GetCount());
1695 data << uint32(0); // +16 // Unknown value
1696 data << uint8(0); // unknown 2.4.2
1697 if (uint32 Enchant0 = pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT))
1699 data << uint8(1); // number of enchantments (max 3) why max 3?
1700 data << uint8(PERM_ENCHANTMENT_SLOT); // enchantment slot (range: 0:2)
1701 data << uint32(Enchant0); // enchantment id
1703 else
1704 data << uint8(0); // no enchantments (0)
1708 Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pItem )
1710 if( !pItem )
1711 return NULL;
1713 Item* lastItem = pItem;
1715 for(GuildItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end(); )
1717 uint8 slot = itr->slot;
1718 uint32 count = itr->count;
1720 ++itr;
1722 if(itr == dest.end())
1724 lastItem = _StoreItem(tabId,slot,pItem,count,false);
1725 break;
1728 lastItem = _StoreItem(tabId,slot,pItem,count,true);
1731 return lastItem;
1734 // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
1735 Item* Guild::_StoreItem( uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone )
1737 if( !pItem )
1738 return NULL;
1740 sLog.outDebug( "GUILD STORAGE: StoreItem tab = %u, slot = %u, item = %u, count = %u", tab, slot, pItem->GetEntry(), count);
1742 Item* pItem2 = m_TabListMap[tab]->Slots[slot];
1744 if( !pItem2 )
1746 if(clone)
1747 pItem = pItem->CloneItem(count);
1748 else
1749 pItem->SetCount(count);
1751 if(!pItem)
1752 return NULL;
1754 m_TabListMap[tab]->Slots[slot] = pItem;
1756 pItem->SetUInt64Value(ITEM_FIELD_CONTAINED, 0);
1757 pItem->SetUInt64Value(ITEM_FIELD_OWNER, 0);
1758 AddGBankItemToDB(GetId(), tab, slot, pItem->GetGUIDLow(), pItem->GetEntry());
1759 pItem->FSetState(ITEM_NEW);
1760 pItem->SaveToDB(); // not in onventory and can be save standalone
1762 return pItem;
1764 else
1766 pItem2->SetCount( pItem2->GetCount() + count );
1767 pItem2->FSetState(ITEM_CHANGED);
1768 pItem2->SaveToDB(); // not in onventory and can be save standalone
1770 if(!clone)
1772 pItem->RemoveFromWorld();
1773 pItem->DeleteFromDB();
1774 delete pItem;
1777 return pItem2;
1781 void Guild::RemoveItem(uint8 tab, uint8 slot )
1783 m_TabListMap[tab]->Slots[slot] = NULL;
1784 CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'",
1785 GetId(), uint32(tab), uint32(slot));
1788 uint8 Guild::_CanStoreItem_InSpecificSlot( uint8 tab, uint8 slot, GuildItemPosCountVec &dest, uint32& count, bool swap, Item* pSrcItem ) const
1790 Item* pItem2 = m_TabListMap[tab]->Slots[slot];
1792 // ignore move item (this slot will be empty at move)
1793 if(pItem2==pSrcItem)
1794 pItem2 = NULL;
1796 uint32 need_space;
1798 // empty specific slot - check item fit to slot
1799 if( !pItem2 || swap )
1801 // non empty stack with space
1802 need_space = pSrcItem->GetMaxStackCount();
1804 // non empty slot, check item type
1805 else
1807 // check item type
1808 if(pItem2->GetEntry() != pSrcItem->GetEntry())
1809 return EQUIP_ERR_ITEM_CANT_STACK;
1811 // check free space
1812 if(pItem2->GetCount() >= pSrcItem->GetMaxStackCount())
1813 return EQUIP_ERR_ITEM_CANT_STACK;
1815 need_space = pSrcItem->GetMaxStackCount() - pItem2->GetCount();
1818 if(need_space > count)
1819 need_space = count;
1821 GuildItemPosCount newPosition = GuildItemPosCount(slot,need_space);
1822 if(!newPosition.isContainedIn(dest))
1824 dest.push_back(newPosition);
1825 count -= need_space;
1828 return EQUIP_ERR_OK;
1831 uint8 Guild::_CanStoreItem_InTab( uint8 tab, GuildItemPosCountVec &dest, uint32& count, bool merge, Item* pSrcItem, uint8 skip_slot ) const
1833 for(uint32 j = 0; j < GUILD_BANK_MAX_SLOTS; j++)
1835 // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot
1836 if(j==skip_slot)
1837 continue;
1839 Item* pItem2 = m_TabListMap[tab]->Slots[j];
1841 // ignore move item (this slot will be empty at move)
1842 if(pItem2==pSrcItem)
1843 pItem2 = NULL;
1845 // if merge skip empty, if !merge skip non-empty
1846 if((pItem2!=NULL)!=merge)
1847 continue;
1849 if( pItem2 )
1851 if(pItem2->GetEntry() == pSrcItem->GetEntry() && pItem2->GetCount() < pSrcItem->GetMaxStackCount() )
1853 uint32 need_space = pSrcItem->GetMaxStackCount() - pItem2->GetCount();
1854 if(need_space > count)
1855 need_space = count;
1857 GuildItemPosCount newPosition = GuildItemPosCount(j,need_space);
1858 if(!newPosition.isContainedIn(dest))
1860 dest.push_back(newPosition);
1861 count -= need_space;
1863 if(count==0)
1864 return EQUIP_ERR_OK;
1868 else
1870 uint32 need_space = pSrcItem->GetMaxStackCount();
1871 if(need_space > count)
1872 need_space = count;
1874 GuildItemPosCount newPosition = GuildItemPosCount(j,need_space);
1875 if(!newPosition.isContainedIn(dest))
1877 dest.push_back(newPosition);
1878 count -= need_space;
1880 if(count==0)
1881 return EQUIP_ERR_OK;
1885 return EQUIP_ERR_OK;
1888 uint8 Guild::CanStoreItem( uint8 tab, uint8 slot, GuildItemPosCountVec &dest, uint32 count, Item *pItem, bool swap ) const
1890 sLog.outDebug( "GUILD STORAGE: CanStoreItem tab = %u, slot = %u, item = %u, count = %u", tab, slot, pItem->GetEntry(), count);
1892 if(count > pItem->GetCount())
1893 return EQUIP_ERR_COULDNT_SPLIT_ITEMS;
1895 if(pItem->IsSoulBound())
1896 return EQUIP_ERR_CANT_DROP_SOULBOUND;
1898 // in specific slot
1899 if( slot != NULL_SLOT )
1901 uint8 res = _CanStoreItem_InSpecificSlot(tab,slot,dest,count,swap,pItem);
1902 if(res!=EQUIP_ERR_OK)
1903 return res;
1905 if(count==0)
1906 return EQUIP_ERR_OK;
1909 // not specific slot or have spece for partly store only in specific slot
1911 // search stack in tab for merge to
1912 if( pItem->GetMaxStackCount() > 1 )
1914 uint8 res = _CanStoreItem_InTab(tab,dest,count,true,pItem,slot);
1915 if(res!=EQUIP_ERR_OK)
1916 return res;
1918 if(count==0)
1919 return EQUIP_ERR_OK;
1922 // search free slot in bag for place to
1923 uint8 res = _CanStoreItem_InTab(tab,dest,count,false,pItem,slot);
1924 if(res!=EQUIP_ERR_OK)
1925 return res;
1927 if(count==0)
1928 return EQUIP_ERR_OK;
1930 return EQUIP_ERR_BANK_FULL;
1933 void Guild::SetGuildBankTabText(uint8 TabId, std::string text)
1935 if (TabId >= GUILD_BANK_MAX_TABS)
1936 return;
1937 if (TabId >= m_TabListMap.size())
1938 return;
1939 if (!m_TabListMap[TabId])
1940 return;
1942 if(m_TabListMap[TabId]->Text==text)
1943 return;
1945 utf8truncate(text,500); // DB and client size limitation
1947 m_TabListMap[TabId]->Text = text;
1949 CharacterDatabase.escape_string(text);
1950 CharacterDatabase.PExecute("UPDATE guild_bank_tab SET TabText='%s' WHERE guildid='%u' AND TabId='%u'", text.c_str(), m_Id, uint32(TabId));
1952 // announce
1953 SendGuildBankTabText(NULL,TabId);
1956 void Guild::SendGuildBankTabText(WorldSession *session, uint8 TabId)
1958 if (TabId > GUILD_BANK_MAX_TABS)
1959 return;
1961 GuildBankTab const *tab = GetBankTab(TabId);
1962 if (!tab)
1963 return;
1965 WorldPacket data(MSG_QUERY_GUILD_BANK_TEXT, 1+tab->Text.size()+1);
1966 data << uint8(TabId);
1967 data << tab->Text;
1969 if(session)
1970 session->SendPacket(&data);
1971 else
1972 BroadcastPacket(&data);
1976 void Guild::SwapItems(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankTabDst, uint8 BankTabSlotDst, uint32 SplitedAmount )
1978 // empty operation
1979 if(BankTab==BankTabDst && BankTabSlot==BankTabSlotDst)
1980 return;
1982 Item *pItemSrc = GetItem(BankTab, BankTabSlot);
1983 if (!pItemSrc) // may prevent crash
1984 return;
1986 if(SplitedAmount > pItemSrc->GetCount())
1987 return; // cheating?
1988 else if(SplitedAmount == pItemSrc->GetCount())
1989 SplitedAmount = 0; // no split
1991 Item *pItemDst = GetItem(BankTabDst, BankTabSlotDst);
1993 if(BankTab!=BankTabDst)
1995 // check dest pos rights (if different tabs)
1996 if(!IsMemberHaveRights(pl->GetGUIDLow(), BankTabDst, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
1997 return;
1999 // check source pos rights (if different tabs)
2000 uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
2001 if(remRight <= 0)
2002 return;
2005 if (SplitedAmount)
2006 { // Bank -> Bank item split (in empty or non empty slot
2007 GuildItemPosCountVec dest;
2008 uint8 msg = CanStoreItem(BankTabDst,BankTabSlotDst,dest,SplitedAmount,pItemSrc,false);
2009 if( msg != EQUIP_ERR_OK )
2011 pl->SendEquipError( msg, pItemSrc, NULL );
2012 return;
2015 Item *pNewItem = pItemSrc->CloneItem( SplitedAmount );
2016 if( !pNewItem )
2018 pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemSrc, NULL );
2019 return;
2022 CharacterDatabase.BeginTransaction();
2023 LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), SplitedAmount, BankTabDst);
2025 pl->ItemRemovedQuestCheck( pItemSrc->GetEntry(), SplitedAmount );
2026 pItemSrc->SetCount( pItemSrc->GetCount() - SplitedAmount );
2027 pItemSrc->FSetState(ITEM_CHANGED);
2028 pItemSrc->SaveToDB(); // not in inventory and can be save standalone
2029 StoreItem(BankTabDst,dest,pNewItem);
2030 CharacterDatabase.CommitTransaction();
2032 else // non split
2034 GuildItemPosCountVec gDest;
2035 uint8 msg = CanStoreItem(BankTabDst,BankTabSlotDst,gDest,pItemSrc->GetCount(),pItemSrc,false);
2036 if( msg == EQUIP_ERR_OK ) // merge to
2038 CharacterDatabase.BeginTransaction();
2039 LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst);
2041 RemoveItem(BankTab, BankTabSlot);
2042 StoreItem(BankTabDst, gDest, pItemSrc);
2043 CharacterDatabase.CommitTransaction();
2045 else // swap
2047 gDest.clear();
2048 msg = CanStoreItem(BankTabDst,BankTabSlotDst,gDest,pItemSrc->GetCount(),pItemSrc,true);
2049 if( msg != EQUIP_ERR_OK )
2051 pl->SendEquipError( msg, pItemSrc, NULL );
2052 return;
2055 GuildItemPosCountVec gSrc;
2056 msg = CanStoreItem(BankTab,BankTabSlot,gSrc,pItemDst->GetCount(),pItemDst,true);
2057 if( msg != EQUIP_ERR_OK )
2059 pl->SendEquipError( msg, pItemDst, NULL );
2060 return;
2063 if(BankTab!=BankTabDst)
2065 // check source pos rights (item swapped to src)
2066 if(!IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
2067 return;
2069 // check dest pos rights (item swapped to src)
2070 uint32 remRightDst = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTabDst);
2071 if(remRightDst <= 0)
2072 return;
2075 CharacterDatabase.BeginTransaction();
2076 LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst);
2077 LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTabDst, pl->GetGUIDLow(), pItemDst->GetEntry(), pItemDst->GetCount(), BankTab);
2079 RemoveItem(BankTab, BankTabSlot);
2080 RemoveItem(BankTabDst, BankTabSlotDst);
2081 StoreItem(BankTab, gSrc, pItemDst);
2082 StoreItem(BankTabDst, gDest, pItemSrc);
2083 CharacterDatabase.CommitTransaction();
2086 DisplayGuildBankContentUpdate(BankTab,BankTabSlot,BankTab==BankTabDst ? BankTabSlotDst : -1);
2087 if(BankTab!=BankTabDst)
2088 DisplayGuildBankContentUpdate(BankTabDst,BankTabSlotDst);
2092 void Guild::MoveFromBankToChar( Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 PlayerBag, uint8 PlayerSlot, uint32 SplitedAmount)
2094 Item *pItemBank = GetItem(BankTab, BankTabSlot);
2095 Item *pItemChar = pl->GetItemByPos(PlayerBag, PlayerSlot);
2097 if (!pItemBank) // Problem to get bank item
2098 return;
2100 if(SplitedAmount > pItemBank->GetCount())
2101 return; // cheating?
2102 else if(SplitedAmount == pItemBank->GetCount())
2103 SplitedAmount = 0; // no split
2105 if (SplitedAmount)
2106 { // Bank -> Char split to slot (patly move)
2107 Item *pNewItem = pItemBank->CloneItem( SplitedAmount );
2108 if( !pNewItem )
2110 pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemBank, NULL );
2111 return;
2114 ItemPosCountVec dest;
2115 uint8 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, dest, pNewItem, false);
2116 if( msg != EQUIP_ERR_OK )
2118 pl->SendEquipError( msg, pNewItem, NULL );
2119 delete pNewItem;
2120 return;
2123 // check source pos rights (item moved to inventory)
2124 uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
2125 if(remRight <= 0)
2127 delete pNewItem;
2128 return;
2131 CharacterDatabase.BeginTransaction();
2132 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), SplitedAmount);
2134 pItemBank->SetCount(pItemBank->GetCount()-SplitedAmount);
2135 pItemBank->FSetState(ITEM_CHANGED);
2136 pItemBank->SaveToDB(); // not in inventory and can be save standalone
2137 pl->MoveItemToInventory(dest,pNewItem,true);
2138 pl->SaveInventoryAndGoldToDB();
2140 MemberItemWithdraw(BankTab, pl->GetGUIDLow());
2141 CharacterDatabase.CommitTransaction();
2143 else // Bank -> Char swap with slot (move)
2145 ItemPosCountVec dest;
2146 uint8 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, dest, pItemBank, false);
2147 if( msg == EQUIP_ERR_OK ) // merge case
2149 // check source pos rights (item moved to inventory)
2150 uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
2151 if(remRight <= 0)
2152 return;
2154 CharacterDatabase.BeginTransaction();
2155 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
2157 RemoveItem(BankTab, BankTabSlot);
2158 pl->MoveItemToInventory(dest,pItemBank,true);
2159 pl->SaveInventoryAndGoldToDB();
2161 MemberItemWithdraw(BankTab, pl->GetGUIDLow());
2162 CharacterDatabase.CommitTransaction();
2164 else // Bank <-> Char swap items
2166 // check source pos rights (item swapped to bank)
2167 if(!IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
2168 return;
2170 if(pItemChar)
2172 if(!pItemChar->CanBeTraded())
2174 pl->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL );
2175 return;
2179 ItemPosCountVec iDest;
2180 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, iDest, pItemBank, true);
2181 if( msg != EQUIP_ERR_OK )
2183 pl->SendEquipError( msg, pItemBank, NULL );
2184 return;
2187 GuildItemPosCountVec gDest;
2188 if(pItemChar)
2190 msg = CanStoreItem(BankTab,BankTabSlot,gDest,pItemChar->GetCount(),pItemChar,true);
2191 if( msg != EQUIP_ERR_OK )
2193 pl->SendEquipError( msg, pItemChar, NULL );
2194 return;
2198 // check source pos rights (item moved to inventory)
2199 uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
2200 if(remRight <= 0)
2201 return;
2203 if(pItemChar)
2205 // logging item move to bank
2206 if(pl->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
2208 sLog.outCommand(pl->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
2209 pl->GetName(),pl->GetSession()->GetAccountId(),
2210 pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(),
2211 m_Id);
2215 CharacterDatabase.BeginTransaction();
2216 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
2217 if(pItemChar)
2218 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
2220 RemoveItem(BankTab, BankTabSlot);
2221 if(pItemChar)
2223 pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
2224 pItemChar->DeleteFromInventoryDB();
2227 if(pItemChar)
2228 StoreItem(BankTab, gDest, pItemChar);
2229 pl->MoveItemToInventory(iDest,pItemBank,true);
2230 pl->SaveInventoryAndGoldToDB();
2232 MemberItemWithdraw(BankTab, pl->GetGUIDLow());
2233 CharacterDatabase.CommitTransaction();
2236 DisplayGuildBankContentUpdate(BankTab,BankTabSlot);
2240 void Guild::MoveFromCharToBank( Player * pl, uint8 PlayerBag, uint8 PlayerSlot, uint8 BankTab, uint8 BankTabSlot, uint32 SplitedAmount )
2242 Item *pItemBank = GetItem(BankTab, BankTabSlot);
2243 Item *pItemChar = pl->GetItemByPos(PlayerBag, PlayerSlot);
2245 if (!pItemChar) // Problem to get item from player
2246 return;
2248 if(!pItemChar->CanBeTraded())
2250 pl->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pItemChar, NULL );
2251 return;
2254 // check source pos rights (item moved to bank)
2255 if(!IsMemberHaveRights(pl->GetGUIDLow(), BankTab, GUILD_BANK_RIGHT_DEPOSIT_ITEM))
2256 return;
2258 if(SplitedAmount > pItemChar->GetCount())
2259 return; // cheating?
2260 else if(SplitedAmount == pItemChar->GetCount())
2261 SplitedAmount = 0; // no split
2263 if (SplitedAmount)
2264 { // Char -> Bank split to empty or non-empty slot (partly move)
2265 GuildItemPosCountVec dest;
2266 uint8 msg = CanStoreItem(BankTab,BankTabSlot,dest,SplitedAmount,pItemChar,false);
2267 if( msg != EQUIP_ERR_OK )
2269 pl->SendEquipError( msg, pItemChar, NULL );
2270 return;
2273 Item *pNewItem = pItemChar->CloneItem( SplitedAmount );
2274 if( !pNewItem )
2276 pl->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, pItemChar, NULL );
2277 return;
2280 // logging item move to bank (before items merge
2281 if(pl->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
2283 sLog.outCommand(pl->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
2284 pl->GetName(),pl->GetSession()->GetAccountId(),
2285 pItemChar->GetProto()->Name1,pItemChar->GetEntry(),SplitedAmount,m_Id);
2288 CharacterDatabase.BeginTransaction();
2289 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), SplitedAmount);
2291 pl->ItemRemovedQuestCheck( pItemChar->GetEntry(), SplitedAmount );
2292 pItemChar->SetCount(pItemChar->GetCount()-SplitedAmount);
2293 pItemChar->SetState(ITEM_CHANGED);
2294 pl->SaveInventoryAndGoldToDB();
2295 StoreItem(BankTab, dest, pNewItem);
2296 CharacterDatabase.CommitTransaction();
2298 DisplayGuildBankContentUpdate(BankTab,dest);
2300 else // Char -> Bank swap with empty or non-empty (move)
2302 GuildItemPosCountVec dest;
2303 uint8 msg = CanStoreItem(BankTab,BankTabSlot,dest,pItemChar->GetCount(),pItemChar,false);
2304 if( msg == EQUIP_ERR_OK ) // merge
2306 // logging item move to bank
2307 if(pl->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
2309 sLog.outCommand(pl->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
2310 pl->GetName(),pl->GetSession()->GetAccountId(),
2311 pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(),
2312 m_Id);
2315 CharacterDatabase.BeginTransaction();
2316 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
2318 pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
2319 pItemChar->DeleteFromInventoryDB();
2321 StoreItem(BankTab,dest,pItemChar);
2322 pl->SaveInventoryAndGoldToDB();
2323 CharacterDatabase.CommitTransaction();
2325 DisplayGuildBankContentUpdate(BankTab,dest);
2327 else // Char <-> Bank swap items (posible NULL bank item)
2329 ItemPosCountVec iDest;
2330 if(pItemBank)
2332 msg = pl->CanStoreItem(PlayerBag, PlayerSlot, iDest, pItemBank, true);
2333 if( msg != EQUIP_ERR_OK )
2335 pl->SendEquipError( msg, pItemBank, NULL );
2336 return;
2340 GuildItemPosCountVec gDest;
2341 msg = CanStoreItem(BankTab,BankTabSlot,gDest,pItemChar->GetCount(),pItemChar,true);
2342 if( msg != EQUIP_ERR_OK )
2344 pl->SendEquipError( msg, pItemChar, NULL );
2345 return;
2348 if(pItemBank)
2350 // check bank pos rights (item swapped with inventory)
2351 uint32 remRight = GetMemberSlotWithdrawRem(pl->GetGUIDLow(), BankTab);
2352 if(remRight <= 0)
2353 return;
2356 // logging item move to bank
2357 if(pl->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
2359 sLog.outCommand(pl->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
2360 pl->GetName(),pl->GetSession()->GetAccountId(),
2361 pItemChar->GetProto()->Name1,pItemChar->GetEntry(),pItemChar->GetCount(),
2362 m_Id);
2365 CharacterDatabase.BeginTransaction();
2366 if(pItemBank)
2367 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount());
2368 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount());
2370 pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true);
2371 pItemChar->DeleteFromInventoryDB();
2372 if(pItemBank)
2373 RemoveItem(BankTab, BankTabSlot);
2375 StoreItem(BankTab,gDest,pItemChar);
2376 if(pItemBank)
2377 pl->MoveItemToInventory(iDest,pItemBank,true);
2378 pl->SaveInventoryAndGoldToDB();
2379 if(pItemBank)
2380 MemberItemWithdraw(BankTab, pl->GetGUIDLow());
2381 CharacterDatabase.CommitTransaction();
2383 DisplayGuildBankContentUpdate(BankTab,gDest);
2388 bool GuildItemPosCount::isContainedIn(GuildItemPosCountVec const &vec) const
2390 for(GuildItemPosCountVec::const_iterator itr = vec.begin(); itr != vec.end();++itr)
2391 if(itr->slot == slot)
2392 return true;
2394 return false;