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"
24 #include "ObjectMgr.h"
27 #include "SocialMgr.h"
42 m_BackgroundColor
= 0;
48 m_EventLogLoaded
= false;
49 m_GuildBankLoaded
= false;
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;
65 bool Guild::Create(Player
* leader
, std::string gname
)
67 if(objmgr
.GetGuildByName(gname
))
70 WorldSession
* lSession
= leader
->GetSession();
74 m_LeaderGuid
= leader
->GetGUID();
77 MOTD
= "No message set.";
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
);
115 if(pl
->GetGuildId() != 0)
120 if(Player::GetGuildIdFromDB(plGuid
) != 0) // player already in guild
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);
129 MemberSlot newmember
;
131 if(!FillPlayerData(plGuid
, &newmember
)) // problems with player data collection
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!!
154 pl
->SetInGuild(m_Id
);
155 pl
->SetRank(newmember
.RankId
);
156 pl
->SetGuildIdInvited(0);
161 void Guild::SetMOTD(std::string 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
)
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
))
184 if(!LoadMembersFromDB(GuildId
))
187 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT MAX(TabId) FROM guild_bank_tab WHERE guildid='%u'", GuildId
);
190 Field
*fields
= result
->Fetch();
191 m_PurchasedTabs
= fields
[0].GetUInt8()+1; // Because TabId begins at 0
197 LoadBankRightsFromDB(GuildId
); // Must be after LoadRanksFromDB because it populates rank struct
200 result
= CharacterDatabase
.PQuery("SELECT guildid, name, leaderguid, EmblemStyle, EmblemColor, BorderStyle, BorderColor,"
202 "BackgroundColor, info, motd, createdate, BankMoney FROM guild WHERE guildid = '%u'", GuildId
);
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();
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)
240 sLog
.outDebug("Guild %u Creation time Loaded day: %u, month: %u, year: %u", GuildId
, m_CreatedDay
, m_CreatedMonth
, m_CreatedYear
);
245 bool Guild::LoadRanksFromDB(uint32 GuildId
)
248 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT rname,rights,BankMoneyPerDay,rid FROM guild_rank WHERE guildid = '%u' ORDER BY rid ASC", GuildId
);
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
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() );
274 if(m_Ranks
.size()==0) // empty rank table?
276 AddRank("Guild Master",GR_RIGHT_ALL
,0);
280 // guild_rank have wrong numbered ranks, repair
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();
300 bool Guild::LoadMembersFromDB(uint32 GuildId
)
303 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT guild_member.guid,rank, pnote, offnote, BankResetTimeMoney,BankRemMoney,"
305 "BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2,"
307 "BankResetTimeTab3, BankRemSlotsTab3, BankResetTimeTab4, BankRemSlotsTab4, BankResetTimeTab5, BankRemSlotsTab5,"
309 "logout_time FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid WHERE guildid = '%u'", GuildId
);
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
))
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() );
346 bool Guild::FillPlayerData(uint64 guid
, MemberSlot
* memslot
)
353 Player
* pl
= objmgr
.GetPlayer(guid
);
356 plName
= pl
->GetName();
357 plLevel
= pl
->getLevel();
358 plClass
= pl
->getClass();
359 plZone
= pl
->GetZoneId();
363 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT name,level,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid
));
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();
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
));
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
));
397 memslot
->name
= plName
;
398 memslot
->level
= plLevel
;
399 memslot
->Class
= plClass
;
400 memslot
->zoneId
= plZone
;
405 void Guild::LoadPlayerStatsByGuid(uint64 guid
)
407 MemberList::iterator itr
= members
.find(GUID_LOPART(guid
));
408 if (itr
== members
.end() )
411 Player
*pl
= ObjectAccessor::FindPlayer(guid
);
414 itr
->second
.name
= pl
->GetName();
415 itr
->second
.level
= pl
->getLevel();
416 itr
->second
.Class
= pl
->getClass();
419 void Guild::SetLeader(uint64 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
);
442 if(!best
|| best
->RankId
> i
->second
.RankId
)
445 newLeaderGUID
= i
->first
;
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
463 WorldPacket
data(SMSG_GUILD_EVENT
, (1+1+(oldLeader
->name
).size()+1+(best
->name
).size()+1));
464 data
<< (uint8
)GE_LEADER_CHANGED
;
466 data
<< oldLeader
->name
;
468 BroadcastPacket(&data
);
470 data
.Initialize(SMSG_GUILD_EVENT
, (1+1+(oldLeader
->name
).size()+1));
471 data
<< (uint8
)GE_LEFT
;
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 !!
486 player
->SetInGuild(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 !!
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() )
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() )
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
))
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
)
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
));
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
));
583 player
->GetSession()->SendPacket(packet
);
588 void Guild::CreateRank(std::string name_
,uint32 rights
)
590 if(m_Ranks
.size() >= GUILD_MAX_RANKS
)
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()
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
);
624 std::string
Guild::GetRankName(uint32 rankId
)
626 if(rankId
>= m_Ranks
.size())
629 return m_Ranks
[rankId
].name
;
632 uint32
Guild::GetRankRights(uint32 rankId
)
634 if(rankId
>= m_Ranks
.size())
637 return m_Ranks
[rankId
].rights
;
640 void Guild::SetRankName(uint32 rankId
, std::string name_
)
642 if(rankId
>= m_Ranks
.size())
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())
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())
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();
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());
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
;
731 data
<< uint64(MAKE_NEW_GUID(itr
->first
, 0, HIGHGUID_PLAYER
));
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
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
;
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() )
791 itr
->second
.logout_time
= time(NULL
);
793 if (m_OnlineMembers
> 0)
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();
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
)
819 data
<< uint8(itr
->EventType
);
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
);
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
)
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
);
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;
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
870 m_GuildEventLog
.push_front(NewEvent
);
872 } while( result
->NextRow() );
875 m_EventLogLoaded
= true;
878 // Unload guild eventlog
879 void Guild::UnloadGuildEventLog()
881 if (!m_EventLogLoaded
)
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
;
893 NewEvent
.EventType
= EventType
;
894 NewEvent
.PlayerGuid1
= PlayerGuid1
;
895 NewEvent
.PlayerGuid2
= PlayerGuid2
;
896 NewEvent
.NewRank
= NewRank
;
897 NewEvent
.TimeStamp
= uint32(time(NULL
));
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();
904 m_GuildEventLog
.push_back(NewEvent
);
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 // *************************************************
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
);
923 if(!IsMemberHaveRights(session
->GetPlayer()->GetGUIDLow(),TabId
,GUILD_BANK_RIGHT_VIEW_TAB
))
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
);
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
976 AppendDisplayGuildBankSlot(data
, tab
, slot1
);
978 else // 2 items (in slot1 and 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
));
995 if(!IsMemberHaveRights(itr
->first
,TabId
,GUILD_BANK_RIGHT_VIEW_TAB
))
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
);
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
));
1033 if(!IsMemberHaveRights(itr
->first
,TabId
,GUILD_BANK_RIGHT_VIEW_TAB
))
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
)
1048 return m_TabListMap
[TabId
]->Slots
[SlotId
];
1051 // *************************************************
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
)
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
)
1102 if (TabId
>= m_TabListMap
.size())
1105 if (!m_TabListMap
[TabId
])
1108 if(m_TabListMap
[TabId
]->Name
== Name
&& m_TabListMap
[TabId
]->Icon
== Icon
)
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
)
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
)
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
)
1150 m_GuildBankLoaded
= true;
1151 LoadGuildBankEventLogFromDB();
1154 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT TabId, TabName, TabIcon, TabText FROM guild_bank_tab WHERE guildid='%u' ORDER BY TabId", m_Id
);
1157 m_PurchasedTabs
= 0;
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() );
1179 // data needs to be at first place for Item::LoadFromDB
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
);
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
);
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
);
1205 ItemPrototype
const *proto
= objmgr
.GetItemPrototype(ItemEntry
);
1209 sLog
.outError( "Guild::LoadGuildBankFromDB: Unknown item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid
,ItemEntry
);
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
);
1222 pItem
->AddToWorld();
1223 m_TabListMap
[TabId
]->Slots
[SlotId
] = pItem
;
1224 }while( result
->NextRow() );
1229 // This unload should be called when the last member of the guild gets offline
1230 void Guild::UnloadGuildBank()
1232 if (!m_GuildBankLoaded
)
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
)
1270 SetBankMoney(GetGuildBankMoney()-amount
);
1272 if (MoneyWithDrawRight
< WITHDRAW_MONEY_UNLIMITED
)
1274 MemberList::iterator itr
= members
.find(LowGuid
);
1275 if (itr
== members
.end() )
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
);
1284 void Guild::SetBankMoney(int64 money
)
1286 if (money
< 0) // I don't know how this happens, it does!!
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)
1303 if (SlotsWithDrawRight
< WITHDRAW_SLOT_UNLIMITED
)
1305 MemberList::iterator itr
= members
.find(LowGuid
);
1306 if (itr
== members
.end() )
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
);
1315 bool Guild::IsMemberHaveRights(uint32 LowGuid
, uint8 TabId
, uint32 rights
) const
1317 MemberList::const_iterator itr
= members
.find(LowGuid
);
1318 if (itr
== members
.end() )
1321 if (itr
->second
.RankId
== GR_GUILDMASTER
)
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() )
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
)
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() )
1356 if (itr
->second
.RankId
== GR_GUILDMASTER
)
1357 return WITHDRAW_MONEY_UNLIMITED
;
1359 uint32 curTime
= uint32(time(NULL
)/MINUTE
); // minutes
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())
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
)
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
;
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())
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
)
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
)
1445 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT TabId, rid, gbright, SlotPerDay FROM guild_bank_right WHERE guildid = '%u' ORDER BY TabId", GuildId
);
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() );
1466 // *************************************************
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
++)
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
);
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
);
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() );
1518 //special handle for guild bank money log
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
);
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
);
1548 //events are ordered from oldest (in beginning) to latest (in the end)
1549 m_GuildBankEventLog_Money
.push_front(NewEvent
);
1551 } while( result
->NextRow() );
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
)
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
);
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
);
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
);
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
)
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
);
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
);
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
);
1688 // random item property id +8
1689 data
<< (uint32
) pItem
->GetItemRandomPropertyId();
1690 if (pItem
->GetItemRandomPropertyId())
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
1704 data
<< uint8(0); // no enchantments (0)
1708 Item
* Guild::StoreItem(uint8 tabId
, GuildItemPosCountVec
const& dest
, Item
* pItem
)
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
;
1722 if(itr
== dest
.end())
1724 lastItem
= _StoreItem(tabId
,slot
,pItem
,count
,false);
1728 lastItem
= _StoreItem(tabId
,slot
,pItem
,count
,true);
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
)
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
];
1747 pItem
= pItem
->CloneItem(count
);
1749 pItem
->SetCount(count
);
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
1766 pItem2
->SetCount( pItem2
->GetCount() + count
);
1767 pItem2
->FSetState(ITEM_CHANGED
);
1768 pItem2
->SaveToDB(); // not in onventory and can be save standalone
1772 pItem
->RemoveFromWorld();
1773 pItem
->DeleteFromDB();
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
)
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
1808 if(pItem2
->GetEntry() != pSrcItem
->GetEntry())
1809 return EQUIP_ERR_ITEM_CANT_STACK
;
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
)
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
1839 Item
* pItem2
= m_TabListMap
[tab
]->Slots
[j
];
1841 // ignore move item (this slot will be empty at move)
1842 if(pItem2
==pSrcItem
)
1845 // if merge skip empty, if !merge skip non-empty
1846 if((pItem2
!=NULL
)!=merge
)
1851 if(pItem2
->GetEntry() == pSrcItem
->GetEntry() && pItem2
->GetCount() < pSrcItem
->GetMaxStackCount() )
1853 uint32 need_space
= pSrcItem
->GetMaxStackCount() - pItem2
->GetCount();
1854 if(need_space
> count
)
1857 GuildItemPosCount newPosition
= GuildItemPosCount(j
,need_space
);
1858 if(!newPosition
.isContainedIn(dest
))
1860 dest
.push_back(newPosition
);
1861 count
-= need_space
;
1864 return EQUIP_ERR_OK
;
1870 uint32 need_space
= pSrcItem
->GetMaxStackCount();
1871 if(need_space
> count
)
1874 GuildItemPosCount newPosition
= GuildItemPosCount(j
,need_space
);
1875 if(!newPosition
.isContainedIn(dest
))
1877 dest
.push_back(newPosition
);
1878 count
-= need_space
;
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
;
1899 if( slot
!= NULL_SLOT
)
1901 uint8 res
= _CanStoreItem_InSpecificSlot(tab
,slot
,dest
,count
,swap
,pItem
);
1902 if(res
!=EQUIP_ERR_OK
)
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
)
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
)
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
)
1937 if (TabId
>= m_TabListMap
.size())
1939 if (!m_TabListMap
[TabId
])
1942 if(m_TabListMap
[TabId
]->Text
==text
)
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
));
1953 SendGuildBankTabText(NULL
,TabId
);
1956 void Guild::SendGuildBankTabText(WorldSession
*session
, uint8 TabId
)
1958 if (TabId
> GUILD_BANK_MAX_TABS
)
1961 GuildBankTab
const *tab
= GetBankTab(TabId
);
1965 WorldPacket
data(MSG_QUERY_GUILD_BANK_TEXT
, 1+tab
->Text
.size()+1);
1966 data
<< uint8(TabId
);
1970 session
->SendPacket(&data
);
1972 BroadcastPacket(&data
);
1976 void Guild::SwapItems(Player
* pl
, uint8 BankTab
, uint8 BankTabSlot
, uint8 BankTabDst
, uint8 BankTabSlotDst
, uint32 SplitedAmount
)
1979 if(BankTab
==BankTabDst
&& BankTabSlot
==BankTabSlotDst
)
1982 Item
*pItemSrc
= GetItem(BankTab
, BankTabSlot
);
1983 if (!pItemSrc
) // may prevent crash
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
))
1999 // check source pos rights (if different tabs)
2000 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
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
);
2015 Item
*pNewItem
= pItemSrc
->CloneItem( SplitedAmount
);
2018 pl
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, pItemSrc
, NULL
);
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();
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();
2048 msg
= CanStoreItem(BankTabDst
,BankTabSlotDst
,gDest
,pItemSrc
->GetCount(),pItemSrc
,true);
2049 if( msg
!= EQUIP_ERR_OK
)
2051 pl
->SendEquipError( msg
, pItemSrc
, NULL
);
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
);
2063 if(BankTab
!=BankTabDst
)
2065 // check source pos rights (item swapped to src)
2066 if(!IsMemberHaveRights(pl
->GetGUIDLow(), BankTab
, GUILD_BANK_RIGHT_DEPOSIT_ITEM
))
2069 // check dest pos rights (item swapped to src)
2070 uint32 remRightDst
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTabDst
);
2071 if(remRightDst
<= 0)
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
2100 if(SplitedAmount
> pItemBank
->GetCount())
2101 return; // cheating?
2102 else if(SplitedAmount
== pItemBank
->GetCount())
2103 SplitedAmount
= 0; // no split
2106 { // Bank -> Char split to slot (patly move)
2107 Item
*pNewItem
= pItemBank
->CloneItem( SplitedAmount
);
2110 pl
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, pItemBank
, NULL
);
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
);
2123 // check source pos rights (item moved to inventory)
2124 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
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
);
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
))
2172 if(!pItemChar
->CanBeTraded())
2174 pl
->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED
, pItemChar
, NULL
);
2179 ItemPosCountVec iDest
;
2180 msg
= pl
->CanStoreItem(PlayerBag
, PlayerSlot
, iDest
, pItemBank
, true);
2181 if( msg
!= EQUIP_ERR_OK
)
2183 pl
->SendEquipError( msg
, pItemBank
, NULL
);
2187 GuildItemPosCountVec gDest
;
2190 msg
= CanStoreItem(BankTab
,BankTabSlot
,gDest
,pItemChar
->GetCount(),pItemChar
,true);
2191 if( msg
!= EQUIP_ERR_OK
)
2193 pl
->SendEquipError( msg
, pItemChar
, NULL
);
2198 // check source pos rights (item moved to inventory)
2199 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
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(),
2215 CharacterDatabase
.BeginTransaction();
2216 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemBank
->GetEntry(), pItemBank
->GetCount());
2218 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemChar
->GetEntry(), pItemChar
->GetCount());
2220 RemoveItem(BankTab
, BankTabSlot
);
2223 pl
->MoveItemFromInventory(PlayerBag
, PlayerSlot
, true);
2224 pItemChar
->DeleteFromInventoryDB();
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
2248 if(!pItemChar
->CanBeTraded())
2250 pl
->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED
, pItemChar
, NULL
);
2254 // check source pos rights (item moved to bank)
2255 if(!IsMemberHaveRights(pl
->GetGUIDLow(), BankTab
, GUILD_BANK_RIGHT_DEPOSIT_ITEM
))
2258 if(SplitedAmount
> pItemChar
->GetCount())
2259 return; // cheating?
2260 else if(SplitedAmount
== pItemChar
->GetCount())
2261 SplitedAmount
= 0; // no split
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
);
2273 Item
*pNewItem
= pItemChar
->CloneItem( SplitedAmount
);
2276 pl
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, pItemChar
, NULL
);
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(),
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
;
2332 msg
= pl
->CanStoreItem(PlayerBag
, PlayerSlot
, iDest
, pItemBank
, true);
2333 if( msg
!= EQUIP_ERR_OK
)
2335 pl
->SendEquipError( msg
, pItemBank
, NULL
);
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
);
2350 // check bank pos rights (item swapped with inventory)
2351 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
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(),
2365 CharacterDatabase
.BeginTransaction();
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();
2373 RemoveItem(BankTab
, BankTabSlot
);
2375 StoreItem(BankTab
,gDest
,pItemChar
);
2377 pl
->MoveItemToInventory(iDest
,pItemBank
,true);
2378 pl
->SaveInventoryAndGoldToDB();
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
)