2 * Copyright (C) 2005-2010 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;
51 m_GuildEventLogNextGuid
= 0;
52 m_GuildBankEventLogNextGuid_Money
= 0;
53 for (uint8 i
= 0; i
< GUILD_BANK_MAX_TABS
; ++i
)
54 m_GuildBankEventLogNextGuid_Item
[i
] = 0;
62 bool Guild::Create(Player
* leader
, std::string gname
)
64 if (sObjectMgr
.GetGuildByName(gname
))
67 WorldSession
* lSession
= leader
->GetSession();
71 m_LeaderGuid
= leader
->GetGUID();
74 MOTD
= "No message set.";
77 m_Id
= sObjectMgr
.GenerateGuildId();
79 sLog
.outDebug("GUILD: creating guild %s to leader: %u", gname
.c_str(), GUID_LOPART(m_LeaderGuid
));
81 // gname already assigned to Guild::name, use it to encode string for DB
82 CharacterDatabase
.escape_string(gname
);
84 std::string dbGINFO
= GINFO
;
85 std::string dbMOTD
= MOTD
;
86 CharacterDatabase
.escape_string(dbGINFO
);
87 CharacterDatabase
.escape_string(dbMOTD
);
89 CharacterDatabase
.BeginTransaction();
90 // CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid='%u'", Id); - MAX(guildid)+1 not exist
91 CharacterDatabase
.PExecute("DELETE FROM guild_member WHERE guildid='%u'", m_Id
);
92 CharacterDatabase
.PExecute("INSERT INTO guild (guildid,name,leaderguid,info,motd,createdate,EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor,BankMoney) "
93 "VALUES('%u','%s','%u', '%s', '%s', UNIX_TIMESTAMP(NOW()),'%u','%u','%u','%u','%u','" UI64FMTD
"')",
94 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
);
95 CharacterDatabase
.CommitTransaction();
97 CreateDefaultGuildRanks(lSession
->GetSessionDbLocaleIndex());
99 return AddMember(m_LeaderGuid
, (uint32
)GR_GUILDMASTER
);
102 void Guild::CreateDefaultGuildRanks(int locale_idx
)
104 CharacterDatabase
.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", m_Id
);
105 CharacterDatabase
.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", m_Id
);
107 CreateRank(sObjectMgr
.GetMangosString(LANG_GUILD_MASTER
, locale_idx
), GR_RIGHT_ALL
);
108 CreateRank(sObjectMgr
.GetMangosString(LANG_GUILD_OFFICER
, locale_idx
), GR_RIGHT_ALL
);
109 CreateRank(sObjectMgr
.GetMangosString(LANG_GUILD_VETERAN
, locale_idx
), GR_RIGHT_GCHATLISTEN
| GR_RIGHT_GCHATSPEAK
);
110 CreateRank(sObjectMgr
.GetMangosString(LANG_GUILD_MEMBER
, locale_idx
), GR_RIGHT_GCHATLISTEN
| GR_RIGHT_GCHATSPEAK
);
111 CreateRank(sObjectMgr
.GetMangosString(LANG_GUILD_INITIATE
, locale_idx
), GR_RIGHT_GCHATLISTEN
| GR_RIGHT_GCHATSPEAK
);
113 SetBankMoneyPerDay((uint32
)GR_GUILDMASTER
, WITHDRAW_MONEY_UNLIMITED
);
116 bool Guild::AddMember(uint64 plGuid
, uint32 plRank
)
118 Player
* pl
= sObjectMgr
.GetPlayer(plGuid
);
121 if (pl
->GetGuildId() != 0)
126 if (Player::GetGuildIdFromDB(plGuid
) != 0) // player already in guild
130 // remove all player signs from another petitions
131 // this will be prevent attempt joining player to many guilds and corrupt guild data integrity
132 Player::RemovePetitionsAndSigns(plGuid
, 9);
135 MemberSlot newmember
;
139 newmember
.Name
= pl
->GetName();
140 newmember
.Level
= pl
->getLevel();
141 newmember
.Class
= pl
->getClass();
142 newmember
.ZoneId
= pl
->GetZoneId();
147 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT name,level,class,zone FROM characters WHERE guid = '%u'", GUID_LOPART(plGuid
));
149 return false; // player doesn't exist
151 Field
*fields
= result
->Fetch();
152 newmember
.Name
= fields
[0].GetCppString();
153 newmember
.Level
= fields
[1].GetUInt8();
154 newmember
.Class
= fields
[2].GetUInt8();
155 newmember
.ZoneId
= fields
[3].GetUInt32();
157 if (newmember
.Level
< 1 || newmember
.Level
> STRONG_MAX_LEVEL
||
158 newmember
.Class
< CLASS_WARRIOR
|| newmember
.Class
>= MAX_CLASSES
)
160 sLog
.outError("Player (GUID: %u) has a broken data in field `characters` table, cannot add him to guild.",GUID_LOPART(plGuid
));
165 newmember
.RankId
= plRank
;
166 newmember
.OFFnote
= (std::string
)"";
167 newmember
.Pnote
= (std::string
)"";
168 newmember
.LogoutTime
= time(NULL
);
169 newmember
.BankResetTimeMoney
= 0; // this will force update at first query
170 for (int i
= 0; i
< GUILD_BANK_MAX_TABS
; ++i
)
171 newmember
.BankResetTimeTab
[i
] = 0;
172 members
[GUID_LOPART(plGuid
)] = newmember
;
174 std::string dbPnote
= newmember
.Pnote
;
175 std::string dbOFFnote
= newmember
.OFFnote
;
176 CharacterDatabase
.escape_string(dbPnote
);
177 CharacterDatabase
.escape_string(dbOFFnote
);
179 CharacterDatabase
.PExecute("INSERT INTO guild_member (guildid,guid,rank,pnote,offnote) VALUES ('%u', '%u', '%u','%s','%s')",
180 m_Id
, GUID_LOPART(plGuid
), newmember
.RankId
, dbPnote
.c_str(), dbOFFnote
.c_str());
182 // If player not in game data in data field will be loaded from guild tables, no need to update it!!
185 pl
->SetInGuild(m_Id
);
186 pl
->SetRank(newmember
.RankId
);
187 pl
->SetGuildIdInvited(0);
192 void Guild::SetMOTD(std::string motd
)
196 // motd now can be used for encoding to DB
197 CharacterDatabase
.escape_string(motd
);
198 CharacterDatabase
.PExecute("UPDATE guild SET motd='%s' WHERE guildid='%u'", motd
.c_str(), m_Id
);
201 void Guild::SetGINFO(std::string ginfo
)
205 // ginfo now can be used for encoding to DB
206 CharacterDatabase
.escape_string(ginfo
);
207 CharacterDatabase
.PExecute("UPDATE guild SET info='%s' WHERE guildid='%u'", ginfo
.c_str(), m_Id
);
210 bool Guild::LoadGuildFromDB(QueryResult
*guildDataResult
)
212 if (!guildDataResult
)
215 Field
*fields
= guildDataResult
->Fetch();
217 m_Id
= fields
[0].GetUInt32();
218 m_Name
= fields
[1].GetCppString();
219 m_LeaderGuid
= MAKE_NEW_GUID(fields
[2].GetUInt32(), 0, HIGHGUID_PLAYER
);
220 m_EmblemStyle
= fields
[3].GetUInt32();
221 m_EmblemColor
= fields
[4].GetUInt32();
222 m_BorderStyle
= fields
[5].GetUInt32();
223 m_BorderColor
= fields
[6].GetUInt32();
224 m_BackgroundColor
= fields
[7].GetUInt32();
225 GINFO
= fields
[8].GetCppString();
226 MOTD
= fields
[9].GetCppString();
227 time_t time
= fields
[10].GetUInt64();
228 m_GuildBankMoney
= fields
[11].GetUInt64();
229 m_PurchasedTabs
= fields
[12].GetUInt32();
231 if (m_PurchasedTabs
> GUILD_BANK_MAX_TABS
)
232 m_PurchasedTabs
= GUILD_BANK_MAX_TABS
;
236 tm local
= *(localtime(&time
)); // dereference and assign
237 m_CreatedDay
= local
.tm_mday
;
238 m_CreatedMonth
= local
.tm_mon
+ 1;
239 m_CreatedYear
= local
.tm_year
+ 1900;
245 bool Guild::CheckGuildStructure()
247 // Repair the structure of guild
248 // If the guildmaster doesn't exist or isn't the member of guild
249 // attempt to promote another member
250 int32 GM_rights
= GetRank(GUID_LOPART(m_LeaderGuid
));
253 DelMember(m_LeaderGuid
);
254 // check no members case (disbanded)
258 else if (GM_rights
!= GR_GUILDMASTER
)
259 SetLeader(m_LeaderGuid
);
261 // Allow only 1 guildmaster
262 for (MemberList::const_iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
264 if (itr
->second
.RankId
== GR_GUILDMASTER
&& GUID_LOPART(m_LeaderGuid
) != itr
->first
)
265 //set right of member to officer
266 ChangeRank(itr
->first
, GR_OFFICER
);
272 bool Guild::LoadRanksFromDB(QueryResult
*guildRanksResult
)
274 if (!guildRanksResult
)
276 sLog
.outError("Guild %u has broken `guild_rank` data, creating new...",m_Id
);
277 CreateDefaultGuildRanks(0);
282 bool broken_ranks
= false;
284 // GUILD RANKS are sequence starting from 0 = GUILD_MASTER (ALL PRIVILEGES) to max 9 (lowest privileges)
285 // the lower rank id is considered higher rank - so promotion does rank-- and demotion does rank++
286 // between ranks in sequence cannot be gaps - so 0,1,2,4 cannot be
287 // min ranks count is 5 and max is 10.
291 fields
= guildRanksResult
->Fetch();
292 //condition that would be true when all ranks in QueryResult will be processed and guild without ranks is being processed
296 uint32 guildId
= fields
[0].GetUInt32();
299 //there is in table guild_rank record which doesn't have guildid in guild table, report error
300 sLog
.outErrorDb("Guild %u does not exist but it has a record in guild_rank table, deleting it!", guildId
);
301 CharacterDatabase
.PExecute("DELETE FROM guild_rank WHERE guildid = '%u'", guildId
);
305 if (guildId
> m_Id
) //we loaded all ranks for this guild already, break cycle
308 uint32 rankID
= fields
[1].GetUInt32();
309 std::string rankName
= fields
[2].GetCppString();
310 uint32 rankRights
= fields
[3].GetUInt32();
311 uint32 rankMoney
= fields
[4].GetUInt32();
313 if (rankID
!= m_Ranks
.size()) // guild_rank.ids are sequence 0,1,2,3..
316 // first rank is guildmaster, prevent loss leader rights
318 rankRights
|= GR_RIGHT_ALL
;
320 AddRank(rankName
, rankRights
, rankMoney
);
321 } while( guildRanksResult
->NextRow() );
323 if (m_Ranks
.size() < GUILD_RANKS_MIN_COUNT
) // if too few ranks, renew them
326 sLog
.outError("Guild %u has broken `guild_rank` data, creating new...", m_Id
);
327 CreateDefaultGuildRanks(0); // 0 is default locale_idx
328 broken_ranks
= false;
330 // guild_rank have wrong numbered ranks, repair
333 sLog
.outError("Guild %u has broken `guild_rank` data, repairing...", m_Id
);
334 CharacterDatabase
.BeginTransaction();
335 CharacterDatabase
.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", m_Id
);
336 for(size_t i
= 0; i
< m_Ranks
.size(); ++i
)
338 std::string name
= m_Ranks
[i
].Name
;
339 uint32 rights
= m_Ranks
[i
].Rights
;
340 CharacterDatabase
.escape_string(name
);
341 CharacterDatabase
.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id
, uint32(i
), name
.c_str(), rights
);
343 CharacterDatabase
.CommitTransaction();
349 bool Guild::LoadMembersFromDB(QueryResult
*guildMembersResult
)
351 if (!guildMembersResult
)
356 Field
*fields
= guildMembersResult
->Fetch();
357 // this condition will be true when all rows in QueryResult are processed and new guild without members is going to be loaded - prevent crash
360 uint32 guildId
= fields
[0].GetUInt32();
363 // there is in table guild_member record which doesn't have guildid in guild table, report error
364 sLog
.outErrorDb("Guild %u does not exist but it has a record in guild_member table, deleting it!", guildId
);
365 CharacterDatabase
.PExecute("DELETE FROM guild_member WHERE guildid = '%u'", guildId
);
370 // we loaded all members for this guild already, break cycle
373 MemberSlot newmember
;
374 uint64 guid
= MAKE_NEW_GUID(fields
[1].GetUInt32(), 0, HIGHGUID_PLAYER
);
375 newmember
.RankId
= fields
[2].GetUInt32();
376 // don't allow member to have not existing rank!
377 if (newmember
.RankId
>= m_Ranks
.size())
378 newmember
.RankId
= GetLowestRank();
380 newmember
.Pnote
= fields
[3].GetCppString();
381 newmember
.OFFnote
= fields
[4].GetCppString();
382 newmember
.BankResetTimeMoney
= fields
[5].GetUInt32();
383 newmember
.BankRemMoney
= fields
[6].GetUInt32();
384 for (int i
= 0; i
< GUILD_BANK_MAX_TABS
; ++i
)
386 newmember
.BankResetTimeTab
[i
] = fields
[7+(2*i
)].GetUInt32();
387 newmember
.BankRemSlotsTab
[i
] = fields
[8+(2*i
)].GetUInt32();
390 newmember
.Name
= fields
[19].GetCppString();
391 newmember
.Level
= fields
[20].GetUInt8();
392 newmember
.Class
= fields
[21].GetUInt8();
393 newmember
.ZoneId
= fields
[22].GetUInt32();
394 newmember
.LogoutTime
= fields
[23].GetUInt64();
396 // this code will remove not existing character guids from guild
397 if (newmember
.Level
< 1 || newmember
.Level
> STRONG_MAX_LEVEL
) // can be at broken `data` field
399 sLog
.outError("Player (GUID: %u) has a broken data in field `characters`.`data`, deleting him from guild!",GUID_LOPART(guid
));
400 CharacterDatabase
.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid
));
403 if (!newmember
.ZoneId
)
405 sLog
.outError("Player (GUID: %u) has broken zone-data", GUID_LOPART(guid
));
406 // here it will also try the same, to get the zone from characters-table, but additional it tries to find
407 // the zone through xy coords .. this is a bit redundant, but shouldn't be called often
408 newmember
.ZoneId
= Player::GetZoneIdFromDB(guid
);
410 if (newmember
.Class
< CLASS_WARRIOR
|| newmember
.Class
>= MAX_CLASSES
) // can be at broken `class` field
412 sLog
.outError("Player (GUID: %u) has a broken data in field `characters`.`class`, deleting him from guild!",GUID_LOPART(guid
));
413 CharacterDatabase
.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid
));
417 members
[GUID_LOPART(guid
)] = newmember
;
419 } while (guildMembersResult
->NextRow());
427 void Guild::SetMemberStats(uint64 guid
)
429 MemberList::iterator itr
= members
.find(GUID_LOPART(guid
));
430 if (itr
== members
.end() )
433 Player
*pl
= ObjectAccessor::FindPlayer(guid
);
436 itr
->second
.Name
= pl
->GetName();
437 itr
->second
.Level
= pl
->getLevel();
438 itr
->second
.Class
= pl
->getClass();
439 itr
->second
.ZoneId
= pl
->GetZoneId();
442 void Guild::SetLeader(uint64 guid
)
445 ChangeRank(guid
, GR_GUILDMASTER
);
447 CharacterDatabase
.PExecute("UPDATE guild SET leaderguid='%u' WHERE guildid='%u'", GUID_LOPART(guid
), m_Id
);
450 void Guild::DelMember(uint64 guid
, bool isDisbanding
)
452 // guild master can be deleted when loading guild and guid doesn't exist in characters table
453 // or when he is removed from guild by gm command
454 if (m_LeaderGuid
== guid
&& !isDisbanding
)
456 MemberSlot
* oldLeader
= NULL
;
457 MemberSlot
* best
= NULL
;
458 uint64 newLeaderGUID
= 0;
459 for (Guild::MemberList::iterator i
= members
.begin(); i
!= members
.end(); ++i
)
461 if (i
->first
== GUID_LOPART(guid
))
463 oldLeader
= &(i
->second
);
467 if (!best
|| best
->RankId
> i
->second
.RankId
)
470 newLeaderGUID
= i
->first
;
479 SetLeader(newLeaderGUID
);
481 // If player not online data in data field will be loaded from guild tabs no need to update it !!
482 if (Player
*newLeader
= sObjectMgr
.GetPlayer(newLeaderGUID
))
483 newLeader
->SetRank(GR_GUILDMASTER
);
485 // when leader non-exist (at guild load with deleted leader only) not send broadcasts
488 BroadcastEvent(GE_LEADER_CHANGED
, 0, 2, oldLeader
->Name
, best
->Name
, "");
490 BroadcastEvent(GE_LEFT
, guid
, 1, oldLeader
->Name
, "", "");
494 members
.erase(GUID_LOPART(guid
));
496 Player
*player
= sObjectMgr
.GetPlayer(guid
);
497 // If player not online data in data field will be loaded from guild tabs no need to update it !!
500 player
->SetInGuild(0);
504 CharacterDatabase
.PExecute("DELETE FROM guild_member WHERE guid = '%u'", GUID_LOPART(guid
));
507 void Guild::ChangeRank(uint64 guid
, uint32 newRank
)
509 MemberList::iterator itr
= members
.find(GUID_LOPART(guid
));
510 if (itr
!= members
.end())
511 itr
->second
.RankId
= newRank
;
513 Player
*player
= sObjectMgr
.GetPlayer(guid
);
514 // If player not online data in data field will be loaded from guild tabs no need to update it !!
516 player
->SetRank(newRank
);
518 CharacterDatabase
.PExecute( "UPDATE guild_member SET rank='%u' WHERE guid='%u'", newRank
, GUID_LOPART(guid
) );
521 void Guild::SetPNOTE(uint64 guid
,std::string pnote
)
523 MemberList::iterator itr
= members
.find(GUID_LOPART(guid
));
524 if (itr
== members
.end())
527 itr
->second
.Pnote
= pnote
;
529 // pnote now can be used for encoding to DB
530 CharacterDatabase
.escape_string(pnote
);
531 CharacterDatabase
.PExecute("UPDATE guild_member SET pnote = '%s' WHERE guid = '%u'", pnote
.c_str(), itr
->first
);
534 void Guild::SetOFFNOTE(uint64 guid
,std::string offnote
)
536 MemberList::iterator itr
= members
.find(GUID_LOPART(guid
));
537 if (itr
== members
.end())
539 itr
->second
.OFFnote
= offnote
;
540 // offnote now can be used for encoding to DB
541 CharacterDatabase
.escape_string(offnote
);
542 CharacterDatabase
.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote
.c_str(), itr
->first
);
545 void Guild::BroadcastToGuild(WorldSession
*session
, const std::string
& msg
, uint32 language
)
547 if (session
&& session
->GetPlayer() && HasRankRight(session
->GetPlayer()->GetRank(),GR_RIGHT_GCHATSPEAK
))
550 ChatHandler(session
).FillMessageData(&data
, CHAT_MSG_GUILD
, language
, 0, msg
.c_str());
552 for (MemberList::const_iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
554 Player
*pl
= ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER
, itr
->first
));
556 if (pl
&& pl
->GetSession() && HasRankRight(pl
->GetRank(),GR_RIGHT_GCHATLISTEN
) && !pl
->GetSocial()->HasIgnore(session
->GetPlayer()->GetGUIDLow()) )
557 pl
->GetSession()->SendPacket(&data
);
562 void Guild::BroadcastToOfficers(WorldSession
*session
, const std::string
& msg
, uint32 language
)
564 if (session
&& session
->GetPlayer() && HasRankRight(session
->GetPlayer()->GetRank(), GR_RIGHT_OFFCHATSPEAK
))
566 for(MemberList::const_iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
569 ChatHandler::FillMessageData(&data
, session
, CHAT_MSG_OFFICER
, language
, NULL
, 0, msg
.c_str(), NULL
);
571 Player
*pl
= ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER
, itr
->first
));
573 if (pl
&& pl
->GetSession() && HasRankRight(pl
->GetRank(),GR_RIGHT_OFFCHATLISTEN
) && !pl
->GetSocial()->HasIgnore(session
->GetPlayer()->GetGUIDLow()))
574 pl
->GetSession()->SendPacket(&data
);
579 void Guild::BroadcastPacket(WorldPacket
*packet
)
581 for(MemberList::const_iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
583 Player
*player
= ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER
, itr
->first
));
585 player
->GetSession()->SendPacket(packet
);
589 void Guild::BroadcastPacketToRank(WorldPacket
*packet
, uint32 rankId
)
591 for(MemberList::const_iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
593 if (itr
->second
.RankId
== rankId
)
595 Player
*player
= ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER
, itr
->first
));
597 player
->GetSession()->SendPacket(packet
);
602 void Guild::CreateRank(std::string name_
,uint32 rights
)
604 if (m_Ranks
.size() >= GUILD_RANKS_MAX_COUNT
)
607 // ranks are sequence 0,1,2,... where 0 means guildmaster
608 uint32 new_rank_id
= m_Ranks
.size();
610 AddRank(name_
, rights
, 0);
612 // existing records in db should be deleted before calling this procedure and m_PurchasedTabs must be loaded already
614 for (uint32 i
= 0; i
< m_PurchasedTabs
; ++i
)
616 // create bank rights with 0
617 CharacterDatabase
.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid) VALUES ('%u','%u','%u')", m_Id
, i
, new_rank_id
);
619 // name now can be used for encoding to DB
620 CharacterDatabase
.escape_string(name_
);
621 CharacterDatabase
.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id
, new_rank_id
, name_
.c_str(), rights
);
624 void Guild::AddRank(const std::string
& name_
,uint32 rights
, uint32 money
)
626 m_Ranks
.push_back(RankInfo(name_
,rights
,money
));
629 void Guild::DelRank()
631 // client won't allow to have less than GUILD_RANKS_MIN_COUNT ranks in guild
632 if (m_Ranks
.size() <= GUILD_RANKS_MIN_COUNT
)
635 // delete lowest guild_rank
636 uint32 rank
= GetLowestRank();
637 CharacterDatabase
.PExecute("DELETE FROM guild_rank WHERE rid>='%u' AND guildid='%u'", rank
, m_Id
);
638 CharacterDatabase
.PExecute("DELETE FROM guild_bank_right WHERE rid>='%u' AND guildid='%u'", rank
, m_Id
);
643 std::string
Guild::GetRankName(uint32 rankId
)
645 if (rankId
>= m_Ranks
.size())
648 return m_Ranks
[rankId
].Name
;
651 uint32
Guild::GetRankRights(uint32 rankId
)
653 if (rankId
>= m_Ranks
.size())
656 return m_Ranks
[rankId
].Rights
;
659 void Guild::SetRankName(uint32 rankId
, std::string name_
)
661 if (rankId
>= m_Ranks
.size())
664 m_Ranks
[rankId
].Name
= name_
;
666 // name now can be used for encoding to DB
667 CharacterDatabase
.escape_string(name_
);
668 CharacterDatabase
.PExecute("UPDATE guild_rank SET rname='%s' WHERE rid='%u' AND guildid='%u'", name_
.c_str(), rankId
, m_Id
);
671 void Guild::SetRankRights(uint32 rankId
, uint32 rights
)
673 if (rankId
>= m_Ranks
.size())
676 m_Ranks
[rankId
].Rights
= rights
;
678 CharacterDatabase
.PExecute("UPDATE guild_rank SET rights='%u' WHERE rid='%u' AND guildid='%u'", rights
, rankId
, m_Id
);
681 int32
Guild::GetRank(uint32 LowGuid
)
683 MemberList::const_iterator itr
= members
.find(LowGuid
);
684 if (itr
== members
.end())
687 return itr
->second
.RankId
;
690 void Guild::Disband()
692 BroadcastEvent(GE_DISBANDED
, 0, 0, "", "", "");
694 while (!members
.empty())
696 MemberList::const_iterator itr
= members
.begin();
697 DelMember(MAKE_NEW_GUID(itr
->first
, 0, HIGHGUID_PLAYER
), true);
700 CharacterDatabase
.BeginTransaction();
701 CharacterDatabase
.PExecute("DELETE FROM guild WHERE guildid = '%u'", m_Id
);
702 CharacterDatabase
.PExecute("DELETE FROM guild_rank WHERE guildid = '%u'", m_Id
);
703 CharacterDatabase
.PExecute("DELETE FROM guild_bank_tab WHERE guildid = '%u'", m_Id
);
704 // TODO item_instance should be deleted ?
705 CharacterDatabase
.PExecute("DELETE FROM guild_bank_item WHERE guildid = '%u'", m_Id
);
706 CharacterDatabase
.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", m_Id
);
707 CharacterDatabase
.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid = '%u'", m_Id
);
708 CharacterDatabase
.PExecute("DELETE FROM guild_eventlog WHERE guildid = '%u'", m_Id
);
709 CharacterDatabase
.CommitTransaction();
710 sObjectMgr
.RemoveGuild(m_Id
);
713 void Guild::Roster(WorldSession
*session
/*= NULL*/)
715 // we can only guess size
716 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));
717 data
<< uint32(members
.size());
721 data
<< uint32(m_Ranks
.size());
722 for (RankList::const_iterator ritr
= m_Ranks
.begin(); ritr
!= m_Ranks
.end(); ++ritr
)
724 data
<< uint32(ritr
->Rights
);
725 data
<< uint32(ritr
->BankMoneyPerDay
); // count of: withdraw gold(gold/day) Note: in game set gold, in packet set bronze.
726 for (int i
= 0; i
< GUILD_BANK_MAX_TABS
; ++i
)
728 data
<< uint32(ritr
->TabRight
[i
]); // for TAB_i rights: view tabs = 0x01, deposit items =0x02
729 data
<< uint32(ritr
->TabSlotPerDay
[i
]); // for TAB_i count of: withdraw items(stack/day)
732 for (MemberList::const_iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
734 if (Player
*pl
= ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER
, itr
->first
)))
736 data
<< uint64(pl
->GetGUID());
738 data
<< pl
->GetName();
739 data
<< uint32(itr
->second
.RankId
);
740 data
<< uint8(pl
->getLevel());
741 data
<< uint8(pl
->getClass());
742 data
<< uint8(0); // new 2.4.0
743 data
<< uint32(pl
->GetZoneId());
744 data
<< itr
->second
.Pnote
;
745 data
<< itr
->second
.OFFnote
;
749 data
<< ObjectGuid(HIGHGUID_PLAYER
, itr
->first
);
751 data
<< itr
->second
.Name
;
752 data
<< uint32(itr
->second
.RankId
);
753 data
<< uint8(itr
->second
.Level
);
754 data
<< uint8(itr
->second
.Class
);
755 data
<< uint8(0); // new 2.4.0
756 data
<< uint32(itr
->second
.ZoneId
);
757 data
<< float(float(time(NULL
)-itr
->second
.LogoutTime
) / DAY
);
758 data
<< itr
->second
.Pnote
;
759 data
<< itr
->second
.OFFnote
;
763 session
->SendPacket(&data
);
765 BroadcastPacket(&data
);
766 sLog
.outDebug( "WORLD: Sent (SMSG_GUILD_ROSTER)" );
769 void Guild::Query(WorldSession
*session
)
771 WorldPacket
data(SMSG_GUILD_QUERY_RESPONSE
, (8*32+200));// we can only guess size
773 data
<< uint32(m_Id
);
776 for (size_t i
= 0 ; i
< GUILD_RANKS_MAX_COUNT
; ++i
) // show always 10 ranks
778 if (i
< m_Ranks
.size())
779 data
<< m_Ranks
[i
].Name
;
781 data
<< uint8(0); // null string
784 data
<< uint32(m_EmblemStyle
);
785 data
<< uint32(m_EmblemColor
);
786 data
<< uint32(m_BorderStyle
);
787 data
<< uint32(m_BorderColor
);
788 data
<< uint32(m_BackgroundColor
);
789 data
<< uint32(0); // probably real ranks count
791 session
->SendPacket( &data
);
792 sLog
.outDebug( "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)" );
795 void Guild::SetEmblem(uint32 emblemStyle
, uint32 emblemColor
, uint32 borderStyle
, uint32 borderColor
, uint32 backgroundColor
)
797 m_EmblemStyle
= emblemStyle
;
798 m_EmblemColor
= emblemColor
;
799 m_BorderStyle
= borderStyle
;
800 m_BorderColor
= borderColor
;
801 m_BackgroundColor
= backgroundColor
;
803 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
);
806 void Guild::UpdateLogoutTime(uint64 guid
)
808 MemberList::iterator itr
= members
.find(GUID_LOPART(guid
));
809 if (itr
== members
.end() )
812 itr
->second
.LogoutTime
= time(NULL
);
815 // *************************************************
816 // Guild Eventlog part
817 // *************************************************
818 // Display guild eventlog
819 void Guild::DisplayGuildEventLog(WorldSession
*session
)
822 WorldPacket
data(MSG_GUILD_EVENT_LOG_QUERY
, 0);
823 // count, max count == 100
824 data
<< uint8(m_GuildEventLog
.size());
825 for (GuildEventLog::const_iterator itr
= m_GuildEventLog
.begin(); itr
!= m_GuildEventLog
.end(); ++itr
)
828 data
<< uint8(itr
->EventType
);
830 data
<< uint64(itr
->PlayerGuid1
);
831 // Player 2 not for left/join guild events
832 if (itr
->EventType
!= GUILD_EVENT_LOG_JOIN_GUILD
&& itr
->EventType
!= GUILD_EVENT_LOG_LEAVE_GUILD
)
833 data
<< uint64(itr
->PlayerGuid2
);
834 // New Rank - only for promote/demote guild events
835 if (itr
->EventType
== GUILD_EVENT_LOG_PROMOTE_PLAYER
|| itr
->EventType
== GUILD_EVENT_LOG_DEMOTE_PLAYER
)
836 data
<< uint8(itr
->NewRank
);
838 data
<< uint32(time(NULL
)-itr
->TimeStamp
);
840 session
->SendPacket(&data
);
841 sLog
.outDebug("WORLD: Sent (MSG_GUILD_EVENT_LOG_QUERY)");
844 // Load guild eventlog from DB
845 void Guild::LoadGuildEventLogFromDB()
848 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
);
851 bool isNextLogGuidSet
= false;
852 //uint32 configCount = sWorld.getConfig(CONFIG_UINT32_GUILD_EVENT_LOG_COUNT);
853 // First event in list will be the oldest and the latest event is last event in list
856 Field
*fields
= result
->Fetch();
857 if (!isNextLogGuidSet
)
859 m_GuildEventLogNextGuid
= fields
[0].GetUInt32();
860 isNextLogGuidSet
= true;
863 GuildEventLogEntry NewEvent
;
864 NewEvent
.EventType
= fields
[1].GetUInt8();
865 NewEvent
.PlayerGuid1
= fields
[2].GetUInt32();
866 NewEvent
.PlayerGuid2
= fields
[3].GetUInt32();
867 NewEvent
.NewRank
= fields
[4].GetUInt8();
868 NewEvent
.TimeStamp
= fields
[5].GetUInt64();
870 // There can be a problem if more events have same TimeStamp the ORDER can be broken when fields[0].GetUInt32() == configCount, but
871 // events with same timestamp can appear when there is lag, and we naivly suppose that mangos isn't laggy
872 // but if problem appears, player will see set of guild events that have same timestamp in bad order
875 m_GuildEventLog
.push_front(NewEvent
);
877 } while( result
->NextRow() );
881 // Add entry to guild eventlog
882 void Guild::LogGuildEvent(uint8 EventType
, uint32 PlayerGuid1
, uint32 PlayerGuid2
, uint8 NewRank
)
884 GuildEventLogEntry NewEvent
;
886 NewEvent
.EventType
= EventType
;
887 NewEvent
.PlayerGuid1
= PlayerGuid1
;
888 NewEvent
.PlayerGuid2
= PlayerGuid2
;
889 NewEvent
.NewRank
= NewRank
;
890 NewEvent
.TimeStamp
= uint32(time(NULL
));
892 m_GuildEventLogNextGuid
= (m_GuildEventLogNextGuid
+ 1) % sWorld
.getConfig(CONFIG_UINT32_GUILD_EVENT_LOG_COUNT
);
893 // Check max records limit
894 if (m_GuildEventLog
.size() >= GUILD_EVENTLOG_MAX_RECORDS
)
895 m_GuildEventLog
.pop_front();
897 m_GuildEventLog
.push_back(NewEvent
);
899 CharacterDatabase
.PExecute("DELETE FROM guild_eventlog WHERE guildid='%u' AND LogGuid='%u'", m_Id
, m_GuildEventLogNextGuid
);
900 CharacterDatabase
.PExecute("INSERT INTO guild_eventlog (guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','" UI64FMTD
"')",
901 m_Id
, m_GuildEventLogNextGuid
, uint32(NewEvent
.EventType
), NewEvent
.PlayerGuid1
, NewEvent
.PlayerGuid2
, uint32(NewEvent
.NewRank
), NewEvent
.TimeStamp
);
904 // *************************************************
906 // *************************************************
907 // Bank content related
908 void Guild::DisplayGuildBankContent(WorldSession
*session
, uint8 TabId
)
910 GuildBankTab
const* tab
= m_TabListMap
[TabId
];
912 if (!IsMemberHaveRights(session
->GetPlayer()->GetGUIDLow(), TabId
, GUILD_BANK_RIGHT_VIEW_TAB
))
915 WorldPacket
data(SMSG_GUILD_BANK_LIST
, 1200);
917 data
<< uint64(GetGuildBankMoney());
918 data
<< uint8(TabId
);
919 // remaining slots for today
920 data
<< uint32(GetMemberSlotWithdrawRem(session
->GetPlayer()->GetGUIDLow(), TabId
));
921 data
<< uint8(0); // Tell client that there's no tab info in this packet
923 data
<< uint8(GUILD_BANK_MAX_SLOTS
);
925 for (int i
= 0; i
< GUILD_BANK_MAX_SLOTS
; ++i
)
926 AppendDisplayGuildBankSlot(data
, tab
, i
);
928 session
->SendPacket(&data
);
930 sLog
.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
933 void Guild::DisplayGuildBankMoneyUpdate(WorldSession
*session
)
935 WorldPacket
data(SMSG_GUILD_BANK_LIST
, 8+1+4+1+1);
937 data
<< uint64(GetGuildBankMoney());
938 data
<< uint8(0); // TabId, default 0
939 data
<< uint32(GetMemberSlotWithdrawRem(session
->GetPlayer()->GetGUIDLow(), 0));
940 data
<< uint8(0); // Tell that there's no tab info in this packet
941 data
<< uint8(0); // not send items
942 BroadcastPacket(&data
);
944 sLog
.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
947 void Guild::DisplayGuildBankContentUpdate(uint8 TabId
, int32 slot1
, int32 slot2
)
949 GuildBankTab
const* tab
= m_TabListMap
[TabId
];
951 WorldPacket
data(SMSG_GUILD_BANK_LIST
, 1200);
953 data
<< uint64(GetGuildBankMoney());
954 data
<< uint8(TabId
);
956 size_t rempos
= data
.wpos();
957 data
<< uint32(0); // item withdraw amount, will be filled later
958 data
<< uint8(0); // Tell client that there's no tab info in this packet
960 if (slot2
== -1) // single item in slot1
962 data
<< uint8(1); // item count
964 AppendDisplayGuildBankSlot(data
, tab
, slot1
);
966 else // 2 items (in slot1 and slot2)
968 data
<< uint8(2); // item count
971 std::swap(slot1
, slot2
);
973 AppendDisplayGuildBankSlot(data
, tab
, slot1
);
974 AppendDisplayGuildBankSlot(data
, tab
, slot2
);
977 for (MemberList::const_iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
979 Player
*player
= ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER
, itr
->first
));
983 if (!IsMemberHaveRights(itr
->first
,TabId
,GUILD_BANK_RIGHT_VIEW_TAB
))
986 data
.put
<uint32
>(rempos
, uint32(GetMemberSlotWithdrawRem(player
->GetGUIDLow(), TabId
)));
988 player
->GetSession()->SendPacket(&data
);
991 sLog
.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
994 void Guild::DisplayGuildBankContentUpdate(uint8 TabId
, GuildItemPosCountVec
const& slots
)
996 GuildBankTab
const* tab
= m_TabListMap
[TabId
];
998 WorldPacket
data(SMSG_GUILD_BANK_LIST
, 1200);
1000 data
<< uint64(GetGuildBankMoney());
1001 data
<< uint8(TabId
);
1003 size_t rempos
= data
.wpos();
1004 data
<< uint32(0); // item withdraw amount, will be filled later
1005 data
<< uint8(0); // Tell client that there's no tab info in this packet
1007 data
<< uint8(slots
.size()); // updates count
1009 for (GuildItemPosCountVec::const_iterator itr
= slots
.begin(); itr
!= slots
.end(); ++itr
)
1010 AppendDisplayGuildBankSlot(data
, tab
, itr
->Slot
);
1012 for (MemberList::const_iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
1014 Player
*player
= ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER
, itr
->first
));
1018 if (!IsMemberHaveRights(itr
->first
,TabId
,GUILD_BANK_RIGHT_VIEW_TAB
))
1021 data
.put
<uint32
>(rempos
,uint32(GetMemberSlotWithdrawRem(player
->GetGUIDLow(), TabId
)));
1023 player
->GetSession()->SendPacket(&data
);
1026 sLog
.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
1029 Item
* Guild::GetItem(uint8 TabId
, uint8 SlotId
)
1031 if (TabId
>= m_TabListMap
.size() || SlotId
>= GUILD_BANK_MAX_SLOTS
)
1033 return m_TabListMap
[TabId
]->Slots
[SlotId
];
1036 // *************************************************
1039 void Guild::DisplayGuildBankTabsInfo(WorldSession
*session
)
1041 WorldPacket
data(SMSG_GUILD_BANK_LIST
, 500);
1043 data
<< uint64(GetGuildBankMoney());
1044 data
<< uint8(0); // TabInfo packet must be for TabId 0
1045 data
<< uint32(GetMemberSlotWithdrawRem(session
->GetPlayer()->GetGUIDLow(), 0));
1046 data
<< uint8(1); // Tell client that this packet includes tab info
1048 data
<< uint8(m_PurchasedTabs
); // here is the number of tabs
1050 for (uint8 i
= 0; i
< m_PurchasedTabs
; ++i
)
1052 data
<< m_TabListMap
[i
]->Name
.c_str();
1053 data
<< m_TabListMap
[i
]->Icon
.c_str();
1055 data
<< uint8(0); // Do not send tab content
1056 session
->SendPacket(&data
);
1058 sLog
.outDebug("WORLD: Sent (SMSG_GUILD_BANK_LIST)");
1061 void Guild::CreateNewBankTab()
1063 if (m_PurchasedTabs
>= GUILD_BANK_MAX_TABS
)
1068 GuildBankTab
* AnotherTab
= new GuildBankTab
;
1069 memset(AnotherTab
->Slots
, 0, GUILD_BANK_MAX_SLOTS
* sizeof(Item
*));
1070 m_TabListMap
.resize(m_PurchasedTabs
);
1071 m_TabListMap
[m_PurchasedTabs
-1] = AnotherTab
;
1073 CharacterDatabase
.BeginTransaction();
1074 CharacterDatabase
.PExecute("DELETE FROM guild_bank_tab WHERE guildid='%u' AND TabId='%u'", m_Id
, uint32(m_PurchasedTabs
-1));
1075 CharacterDatabase
.PExecute("INSERT INTO guild_bank_tab (guildid,TabId) VALUES ('%u','%u')", m_Id
, uint32(m_PurchasedTabs
-1));
1076 CharacterDatabase
.CommitTransaction();
1079 void Guild::SetGuildBankTabInfo(uint8 TabId
, std::string Name
, std::string Icon
)
1081 if (m_TabListMap
[TabId
]->Name
== Name
&& m_TabListMap
[TabId
]->Icon
== Icon
)
1084 m_TabListMap
[TabId
]->Name
= Name
;
1085 m_TabListMap
[TabId
]->Icon
= Icon
;
1087 CharacterDatabase
.escape_string(Name
);
1088 CharacterDatabase
.escape_string(Icon
);
1089 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
));
1092 uint32
Guild::GetBankRights(uint32 rankId
, uint8 TabId
) const
1094 if (rankId
>= m_Ranks
.size() || TabId
>= GUILD_BANK_MAX_TABS
)
1097 return m_Ranks
[rankId
].TabRight
[TabId
];
1100 // *************************************************
1101 // Guild bank loading related
1103 // This load should be called on startup only
1104 void Guild::LoadGuildBankFromDB()
1107 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT TabId, TabName, TabIcon, TabText FROM guild_bank_tab WHERE guildid='%u' ORDER BY TabId", m_Id
);
1110 m_PurchasedTabs
= 0;
1114 m_TabListMap
.resize(m_PurchasedTabs
);
1117 Field
*fields
= result
->Fetch();
1118 uint8 TabId
= fields
[0].GetUInt8();
1120 GuildBankTab
*NewTab
= new GuildBankTab
;
1121 memset(NewTab
->Slots
, 0, GUILD_BANK_MAX_SLOTS
* sizeof(Item
*));
1123 NewTab
->Name
= fields
[1].GetCppString();
1124 NewTab
->Icon
= fields
[2].GetCppString();
1125 NewTab
->Text
= fields
[3].GetCppString();
1127 m_TabListMap
[TabId
] = NewTab
;
1128 } while (result
->NextRow());
1132 // data needs to be at first place for Item::LoadFromDB
1134 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
);
1140 Field
*fields
= result
->Fetch();
1141 uint8 TabId
= fields
[1].GetUInt8();
1142 uint8 SlotId
= fields
[2].GetUInt8();
1143 uint32 ItemGuid
= fields
[3].GetUInt32();
1144 uint32 ItemEntry
= fields
[4].GetUInt32();
1146 if (TabId
>= m_PurchasedTabs
|| TabId
>= GUILD_BANK_MAX_TABS
)
1148 sLog
.outError( "Guild::LoadGuildBankFromDB: Invalid tab for item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid
,ItemEntry
);
1152 if (SlotId
>= GUILD_BANK_MAX_SLOTS
)
1154 sLog
.outError( "Guild::LoadGuildBankFromDB: Invalid slot for item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid
,ItemEntry
);
1158 ItemPrototype
const *proto
= ObjectMgr::GetItemPrototype(ItemEntry
);
1162 sLog
.outError( "Guild::LoadGuildBankFromDB: Unknown item (GUID: %u id: #%u) in guild bank, skipped.", ItemGuid
,ItemEntry
);
1166 Item
*pItem
= NewItemOrBag(proto
);
1167 if (!pItem
->LoadFromDB(ItemGuid
, 0, result
))
1169 CharacterDatabase
.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", m_Id
, uint32(TabId
), uint32(SlotId
));
1170 sLog
.outError("Item GUID %u not found in item_instance, deleting from Guild Bank!", ItemGuid
);
1175 pItem
->AddToWorld();
1176 m_TabListMap
[TabId
]->Slots
[SlotId
] = pItem
;
1177 } while (result
->NextRow());
1182 // *************************************************
1183 // Money deposit/withdraw related
1185 void Guild::SendMoneyInfo(WorldSession
*session
, uint32 LowGuid
)
1187 WorldPacket
data(MSG_GUILD_BANK_MONEY_WITHDRAWN
, 4);
1188 data
<< uint32(GetMemberMoneyWithdrawRem(LowGuid
));
1189 session
->SendPacket(&data
);
1190 sLog
.outDebug("WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN");
1193 bool Guild::MemberMoneyWithdraw(uint32 amount
, uint32 LowGuid
)
1195 uint32 MoneyWithDrawRight
= GetMemberMoneyWithdrawRem(LowGuid
);
1197 if (MoneyWithDrawRight
< amount
|| GetGuildBankMoney() < amount
)
1200 SetBankMoney(GetGuildBankMoney()-amount
);
1202 if (MoneyWithDrawRight
< WITHDRAW_MONEY_UNLIMITED
)
1204 MemberList::iterator itr
= members
.find(LowGuid
);
1205 if (itr
== members
.end() )
1207 itr
->second
.BankRemMoney
-= amount
;
1208 CharacterDatabase
.PExecute("UPDATE guild_member SET BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'",
1209 itr
->second
.BankRemMoney
, m_Id
, LowGuid
);
1214 void Guild::SetBankMoney(int64 money
)
1216 if (money
< 0) // I don't know how this happens, it does!!
1218 m_GuildBankMoney
= money
;
1220 CharacterDatabase
.PExecute("UPDATE guild SET BankMoney='" UI64FMTD
"' WHERE guildid='%u'", money
, m_Id
);
1223 // *************************************************
1224 // Item per day and money per day related
1226 bool Guild::MemberItemWithdraw(uint8 TabId
, uint32 LowGuid
)
1228 uint32 SlotsWithDrawRight
= GetMemberSlotWithdrawRem(LowGuid
, TabId
);
1230 if (SlotsWithDrawRight
== 0)
1233 if (SlotsWithDrawRight
< WITHDRAW_SLOT_UNLIMITED
)
1235 MemberList::iterator itr
= members
.find(LowGuid
);
1236 if (itr
== members
.end() )
1238 --itr
->second
.BankRemSlotsTab
[TabId
];
1239 CharacterDatabase
.PExecute("UPDATE guild_member SET BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'",
1240 uint32(TabId
), itr
->second
.BankRemSlotsTab
[TabId
], m_Id
, LowGuid
);
1245 bool Guild::IsMemberHaveRights(uint32 LowGuid
, uint8 TabId
, uint32 rights
) const
1247 MemberList::const_iterator itr
= members
.find(LowGuid
);
1248 if (itr
== members
.end() )
1251 if (itr
->second
.RankId
== GR_GUILDMASTER
)
1254 return (GetBankRights(itr
->second
.RankId
, TabId
) & rights
) == rights
;
1257 uint32
Guild::GetMemberSlotWithdrawRem(uint32 LowGuid
, uint8 TabId
)
1259 MemberList::iterator itr
= members
.find(LowGuid
);
1260 if (itr
== members
.end() )
1263 if (itr
->second
.RankId
== GR_GUILDMASTER
)
1264 return WITHDRAW_SLOT_UNLIMITED
;
1266 if ((GetBankRights(itr
->second
.RankId
,TabId
) & GUILD_BANK_RIGHT_VIEW_TAB
) != GUILD_BANK_RIGHT_VIEW_TAB
)
1269 uint32 curTime
= uint32(time(NULL
)/MINUTE
);
1270 if (curTime
- itr
->second
.BankResetTimeTab
[TabId
] >= 24*HOUR
/MINUTE
)
1272 itr
->second
.BankResetTimeTab
[TabId
] = curTime
;
1273 itr
->second
.BankRemSlotsTab
[TabId
] = GetBankSlotPerDay(itr
->second
.RankId
, TabId
);
1274 CharacterDatabase
.PExecute("UPDATE guild_member SET BankResetTimeTab%u='%u', BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'",
1275 uint32(TabId
), itr
->second
.BankResetTimeTab
[TabId
], uint32(TabId
), itr
->second
.BankRemSlotsTab
[TabId
], m_Id
, LowGuid
);
1277 return itr
->second
.BankRemSlotsTab
[TabId
];
1280 uint32
Guild::GetMemberMoneyWithdrawRem(uint32 LowGuid
)
1282 MemberList::iterator itr
= members
.find(LowGuid
);
1283 if (itr
== members
.end() )
1286 if (itr
->second
.RankId
== GR_GUILDMASTER
)
1287 return WITHDRAW_MONEY_UNLIMITED
;
1289 uint32 curTime
= uint32(time(NULL
)/MINUTE
); // minutes
1291 if (curTime
> itr
->second
.BankResetTimeMoney
+ 24*HOUR
/MINUTE
)
1293 itr
->second
.BankResetTimeMoney
= curTime
;
1294 itr
->second
.BankRemMoney
= GetBankMoneyPerDay(itr
->second
.RankId
);
1295 CharacterDatabase
.PExecute("UPDATE guild_member SET BankResetTimeMoney='%u', BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'",
1296 itr
->second
.BankResetTimeMoney
, itr
->second
.BankRemMoney
, m_Id
, LowGuid
);
1298 return itr
->second
.BankRemMoney
;
1301 void Guild::SetBankMoneyPerDay(uint32 rankId
, uint32 money
)
1303 if (rankId
>= m_Ranks
.size())
1306 if (rankId
== GR_GUILDMASTER
)
1307 money
= WITHDRAW_MONEY_UNLIMITED
;
1309 m_Ranks
[rankId
].BankMoneyPerDay
= money
;
1311 for (MemberList::iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
1312 if (itr
->second
.RankId
== rankId
)
1313 itr
->second
.BankResetTimeMoney
= 0;
1315 CharacterDatabase
.PExecute("UPDATE guild_rank SET BankMoneyPerDay='%u' WHERE rid='%u' AND guildid='%u'", money
, rankId
, m_Id
);
1316 CharacterDatabase
.PExecute("UPDATE guild_member SET BankResetTimeMoney='0' WHERE guildid='%u' AND rank='%u'", m_Id
, rankId
);
1319 void Guild::SetBankRightsAndSlots(uint32 rankId
, uint8 TabId
, uint32 right
, uint32 nbSlots
, bool db
)
1321 if (rankId
>= m_Ranks
.size() ||
1322 TabId
>= GUILD_BANK_MAX_TABS
||
1323 TabId
>= m_PurchasedTabs
)
1325 // TODO remove next line, It is there just to repair existing bug in deleting guild rank
1326 CharacterDatabase
.PExecute("DELETE FROM guild_bank_right WHERE guildid='%u' AND rid='%u' AND TabId='%u'", m_Id
, rankId
, TabId
);
1330 if (rankId
== GR_GUILDMASTER
)
1332 nbSlots
= WITHDRAW_SLOT_UNLIMITED
;
1333 right
= GUILD_BANK_RIGHT_FULL
;
1336 m_Ranks
[rankId
].TabSlotPerDay
[TabId
] = nbSlots
;
1337 m_Ranks
[rankId
].TabRight
[TabId
] = right
;
1341 for (MemberList::iterator itr
= members
.begin(); itr
!= members
.end(); ++itr
)
1342 if (itr
->second
.RankId
== rankId
)
1343 for (int i
= 0; i
< GUILD_BANK_MAX_TABS
; ++i
)
1344 itr
->second
.BankResetTimeTab
[i
] = 0;
1346 CharacterDatabase
.PExecute("DELETE FROM guild_bank_right WHERE guildid='%u' AND TabId='%u' AND rid='%u'", m_Id
, uint32(TabId
), rankId
);
1347 CharacterDatabase
.PExecute("INSERT INTO guild_bank_right (guildid,TabId,rid,gbright,SlotPerDay) VALUES "
1348 "('%u','%u','%u','%u','%u')", m_Id
, uint32(TabId
), rankId
, m_Ranks
[rankId
].TabRight
[TabId
], m_Ranks
[rankId
].TabSlotPerDay
[TabId
]);
1349 CharacterDatabase
.PExecute("UPDATE guild_member SET BankResetTimeTab%u='0' WHERE guildid='%u' AND rank='%u'", uint32(TabId
), m_Id
, rankId
);
1353 uint32
Guild::GetBankMoneyPerDay(uint32 rankId
)
1355 if (rankId
>= m_Ranks
.size())
1358 if (rankId
== GR_GUILDMASTER
)
1359 return WITHDRAW_MONEY_UNLIMITED
;
1360 return m_Ranks
[rankId
].BankMoneyPerDay
;
1363 uint32
Guild::GetBankSlotPerDay(uint32 rankId
, uint8 TabId
)
1365 if (rankId
>= m_Ranks
.size() || TabId
>= GUILD_BANK_MAX_TABS
)
1368 if (rankId
== GR_GUILDMASTER
)
1369 return WITHDRAW_SLOT_UNLIMITED
;
1370 return m_Ranks
[rankId
].TabSlotPerDay
[TabId
];
1373 // *************************************************
1374 // Rights per day related
1376 bool Guild::LoadBankRightsFromDB(QueryResult
*guildBankTabRightsResult
)
1378 if (!guildBankTabRightsResult
)
1383 Field
*fields
= guildBankTabRightsResult
->Fetch();
1384 // prevent crash when all rights in result are already processed
1387 uint32 guildId
= fields
[0].GetUInt32();
1390 // there is in table guild_bank_right record which doesn't have guildid in guild table, report error
1391 sLog
.outErrorDb("Guild %u does not exist but it has a record in guild_bank_right table, deleting it!", guildId
);
1392 CharacterDatabase
.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", guildId
);
1397 // we loaded all ranks for this guild bank already, break cycle
1399 uint8 TabId
= fields
[1].GetUInt8();
1400 uint32 rankId
= fields
[2].GetUInt32();
1401 uint16 right
= fields
[3].GetUInt16();
1402 uint16 SlotPerDay
= fields
[4].GetUInt16();
1404 SetBankRightsAndSlots(rankId
, TabId
, right
, SlotPerDay
, false);
1406 } while (guildBankTabRightsResult
->NextRow());
1411 // *************************************************
1414 void Guild::LoadGuildBankEventLogFromDB()
1416 // Money log is in TabId = GUILD_BANK_MONEY_LOGS_TAB
1418 // uint32 configCount = sWorld.getConfig(CONFIG_UINT32_GUILD_BANK_EVENT_LOG_COUNT);
1419 // cycle through all purchased guild bank item tabs
1420 for (uint32 tabId
= 0; tabId
< m_PurchasedTabs
; ++tabId
)
1423 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
);
1427 bool isNextLogGuidSet
= false;
1430 Field
*fields
= result
->Fetch();
1432 GuildBankEventLogEntry NewEvent
;
1433 NewEvent
.EventType
= fields
[1].GetUInt8();
1434 NewEvent
.PlayerGuid
= fields
[2].GetUInt32();
1435 NewEvent
.ItemOrMoney
= fields
[3].GetUInt32();
1436 NewEvent
.ItemStackCount
= fields
[4].GetUInt8();
1437 NewEvent
.DestTabId
= fields
[5].GetUInt8();
1438 NewEvent
.TimeStamp
= fields
[6].GetUInt64();
1440 // if newEvent is moneyEvent, move it to moneyEventTab in DB and report error
1441 if (NewEvent
.isMoneyEvent())
1443 uint32 logGuid
= fields
[0].GetUInt32();
1444 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
);
1445 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
);
1449 // add event to list
1450 // events are ordered from oldest (in beginning) to latest (in the end)
1451 m_GuildBankEventLog_Item
[tabId
].push_front(NewEvent
);
1453 if (!isNextLogGuidSet
)
1455 m_GuildBankEventLogNextGuid_Item
[tabId
] = fields
[0].GetUInt32();
1456 // we don't have to do m_GuildBankEventLogNextGuid_Item[tabId] %= configCount; - it will be done when creating new record
1457 isNextLogGuidSet
= true;
1459 } while (result
->NextRow());
1463 // special handle for guild bank money log
1465 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
);
1469 bool isNextMoneyLogGuidSet
= false;
1472 Field
*fields
= result
->Fetch();
1473 if (!isNextMoneyLogGuidSet
)
1475 m_GuildBankEventLogNextGuid_Money
= fields
[0].GetUInt32();
1476 // we don't have to do m_GuildBankEventLogNextGuid_Money %= configCount; - it will be done when creating new record
1477 isNextMoneyLogGuidSet
= true;
1479 GuildBankEventLogEntry NewEvent
;
1481 NewEvent
.EventType
= fields
[1].GetUInt8();
1482 NewEvent
.PlayerGuid
= fields
[2].GetUInt32();
1483 NewEvent
.ItemOrMoney
= fields
[3].GetUInt32();
1484 NewEvent
.ItemStackCount
= fields
[4].GetUInt8();
1485 NewEvent
.DestTabId
= fields
[5].GetUInt8();
1486 NewEvent
.TimeStamp
= fields
[6].GetUInt64();
1488 // if newEvent is not moneyEvent, then report error
1489 if (!NewEvent
.isMoneyEvent())
1490 sLog
.outError("GuildBankEventLog ERROR: MoneyEvent LogGuid %u for Guild %u is not MoneyEvent - ignoring...", fields
[0].GetUInt32(), m_Id
);
1492 // add event to list
1493 // events are ordered from oldest (in beginning) to latest (in the end)
1494 m_GuildBankEventLog_Money
.push_front(NewEvent
);
1496 } while (result
->NextRow());
1500 void Guild::DisplayGuildBankLogs(WorldSession
*session
, uint8 TabId
)
1502 if (TabId
> GUILD_BANK_MAX_TABS
)
1505 if (TabId
== GUILD_BANK_MAX_TABS
)
1507 // Here we display money logs
1508 WorldPacket
data(MSG_GUILD_BANK_LOG_QUERY
, m_GuildBankEventLog_Money
.size()*(4*4+1)+1+1);
1509 data
<< uint8(TabId
); // Here GUILD_BANK_MAX_TABS
1510 data
<< uint8(m_GuildBankEventLog_Money
.size()); // number of log entries
1511 for (GuildBankEventLog::const_iterator itr
= m_GuildBankEventLog_Money
.begin(); itr
!= m_GuildBankEventLog_Money
.end(); ++itr
)
1513 data
<< uint8(itr
->EventType
);
1514 data
<< uint64(MAKE_NEW_GUID(itr
->PlayerGuid
,0,HIGHGUID_PLAYER
));
1515 if (itr
->EventType
== GUILD_BANK_LOG_DEPOSIT_MONEY
||
1516 itr
->EventType
== GUILD_BANK_LOG_WITHDRAW_MONEY
||
1517 itr
->EventType
== GUILD_BANK_LOG_REPAIR_MONEY
||
1518 itr
->EventType
== GUILD_BANK_LOG_UNK1
||
1519 itr
->EventType
== GUILD_BANK_LOG_UNK2
)
1521 data
<< uint32(itr
->ItemOrMoney
);
1525 data
<< uint32(itr
->ItemOrMoney
);
1526 data
<< uint32(itr
->ItemStackCount
);
1527 if (itr
->EventType
== GUILD_BANK_LOG_MOVE_ITEM
|| itr
->EventType
== GUILD_BANK_LOG_MOVE_ITEM2
)
1528 data
<< uint8(itr
->DestTabId
); // moved tab
1530 data
<< uint32(time(NULL
) - itr
->TimeStamp
);
1532 session
->SendPacket(&data
);
1536 // here we display current tab logs
1537 WorldPacket
data(MSG_GUILD_BANK_LOG_QUERY
, m_GuildBankEventLog_Item
[TabId
].size()*(4*4+1+1)+1+1);
1538 data
<< uint8(TabId
); // Here a real Tab Id
1539 // number of log entries
1540 data
<< uint8(m_GuildBankEventLog_Item
[TabId
].size());
1541 for (GuildBankEventLog::const_iterator itr
= m_GuildBankEventLog_Item
[TabId
].begin(); itr
!= m_GuildBankEventLog_Item
[TabId
].end(); ++itr
)
1543 data
<< uint8(itr
->EventType
);
1544 data
<< uint64(MAKE_NEW_GUID(itr
->PlayerGuid
,0,HIGHGUID_PLAYER
));
1545 if (itr
->EventType
== GUILD_BANK_LOG_DEPOSIT_MONEY
||
1546 itr
->EventType
== GUILD_BANK_LOG_WITHDRAW_MONEY
||
1547 itr
->EventType
== GUILD_BANK_LOG_REPAIR_MONEY
||
1548 itr
->EventType
== GUILD_BANK_LOG_UNK1
||
1549 itr
->EventType
== GUILD_BANK_LOG_UNK2
)
1551 data
<< uint32(itr
->ItemOrMoney
);
1555 data
<< uint32(itr
->ItemOrMoney
);
1556 data
<< uint32(itr
->ItemStackCount
);
1557 if (itr
->EventType
== GUILD_BANK_LOG_MOVE_ITEM
|| itr
->EventType
== GUILD_BANK_LOG_MOVE_ITEM2
)
1558 data
<< uint8(itr
->DestTabId
); // moved tab
1560 data
<< uint32(time(NULL
) - itr
->TimeStamp
);
1562 session
->SendPacket(&data
);
1564 sLog
.outDebug("WORLD: Sent (MSG_GUILD_BANK_LOG_QUERY)");
1567 void Guild::LogBankEvent(uint8 EventType
, uint8 TabId
, uint32 PlayerGuidLow
, uint32 ItemOrMoney
, uint8 ItemStackCount
, uint8 DestTabId
)
1570 GuildBankEventLogEntry NewEvent
;
1571 NewEvent
.EventType
= EventType
;
1572 NewEvent
.PlayerGuid
= PlayerGuidLow
;
1573 NewEvent
.ItemOrMoney
= ItemOrMoney
;
1574 NewEvent
.ItemStackCount
= ItemStackCount
;
1575 NewEvent
.DestTabId
= DestTabId
;
1576 NewEvent
.TimeStamp
= uint32(time(NULL
));
1578 // add new event to the end of event list
1579 uint32 currentTabId
= TabId
;
1580 uint32 currentLogGuid
= 0;
1581 if (NewEvent
.isMoneyEvent())
1583 m_GuildBankEventLogNextGuid_Money
= (m_GuildBankEventLogNextGuid_Money
+ 1) % sWorld
.getConfig(CONFIG_UINT32_GUILD_BANK_EVENT_LOG_COUNT
);
1584 currentLogGuid
= m_GuildBankEventLogNextGuid_Money
;
1585 currentTabId
= GUILD_BANK_MONEY_LOGS_TAB
;
1586 if (m_GuildBankEventLog_Money
.size() >= GUILD_BANK_MAX_LOGS
)
1587 m_GuildBankEventLog_Money
.pop_front();
1589 m_GuildBankEventLog_Money
.push_back(NewEvent
);
1593 m_GuildBankEventLogNextGuid_Item
[TabId
] = ((m_GuildBankEventLogNextGuid_Item
[TabId
]) + 1) % sWorld
.getConfig(CONFIG_UINT32_GUILD_BANK_EVENT_LOG_COUNT
);
1594 currentLogGuid
= m_GuildBankEventLogNextGuid_Item
[TabId
];
1595 if (m_GuildBankEventLog_Item
[TabId
].size() >= GUILD_BANK_MAX_LOGS
)
1596 m_GuildBankEventLog_Item
[TabId
].pop_front();
1598 m_GuildBankEventLog_Item
[TabId
].push_back(NewEvent
);
1601 // save event to database
1602 CharacterDatabase
.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u' AND TabId='%u'", m_Id
, currentLogGuid
, currentTabId
);
1604 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
"')",
1605 m_Id
, currentLogGuid
, currentTabId
, uint32(NewEvent
.EventType
), NewEvent
.PlayerGuid
, NewEvent
.ItemOrMoney
, uint32(NewEvent
.ItemStackCount
), uint32(NewEvent
.DestTabId
), NewEvent
.TimeStamp
);
1608 bool Guild::AddGBankItemToDB(uint32 GuildId
, uint32 BankTab
, uint32 BankTabSlot
, uint32 GUIDLow
, uint32 Entry
)
1610 CharacterDatabase
.PExecute("DELETE FROM guild_bank_item WHERE guildid = '%u' AND TabId = '%u'AND SlotId = '%u'", GuildId
, BankTab
, BankTabSlot
);
1611 CharacterDatabase
.PExecute("INSERT INTO guild_bank_item (guildid,TabId,SlotId,item_guid,item_entry) "
1612 "VALUES ('%u', '%u', '%u', '%u', '%u')", GuildId
, BankTab
, BankTabSlot
, GUIDLow
, Entry
);
1616 void Guild::AppendDisplayGuildBankSlot( WorldPacket
& data
, GuildBankTab
const *tab
, int slot
)
1618 Item
*pItem
= tab
->Slots
[slot
];
1619 uint32 entry
= pItem
? pItem
->GetEntry() : 0;
1621 data
<< uint8(slot
);
1622 data
<< uint32(entry
);
1625 data
<< uint32(0); // 3.3.0 (0x8000, 0x8020)
1626 data
<< uint32(pItem
->GetItemRandomPropertyId()); // random item property id + 8
1628 if (pItem
->GetItemRandomPropertyId())
1629 data
<< uint32(pItem
->GetItemSuffixFactor()); // SuffixFactor + 4
1631 data
<< uint32(pItem
->GetCount()); // +12 ITEM_FIELD_STACK_COUNT
1632 data
<< uint32(0); // +16 Unknown value
1633 data
<< uint8(0); // +20
1635 uint8 enchCount
= 0;
1636 size_t enchCountPos
= data
.wpos();
1638 data
<< uint8(enchCount
); // number of enchantments
1639 for(uint32 i
= PERM_ENCHANTMENT_SLOT
; i
< MAX_ENCHANTMENT_SLOT
; ++i
)
1641 if(uint32 enchId
= pItem
->GetEnchantmentId(EnchantmentSlot(i
)))
1644 data
<< uint32(enchId
);
1648 data
.put
<uint8
>(enchCountPos
, enchCount
);
1652 Item
* Guild::StoreItem(uint8 tabId
, GuildItemPosCountVec
const& dest
, Item
* pItem
)
1657 Item
* lastItem
= pItem
;
1659 for (GuildItemPosCountVec::const_iterator itr
= dest
.begin(); itr
!= dest
.end(); )
1661 uint8 slot
= itr
->Slot
;
1662 uint32 count
= itr
->Count
;
1666 if (itr
== dest
.end())
1668 lastItem
= _StoreItem(tabId
, slot
, pItem
, count
, false);
1672 lastItem
= _StoreItem(tabId
, slot
, pItem
, count
, true);
1678 // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case.
1679 Item
* Guild::_StoreItem( uint8 tab
, uint8 slot
, Item
*pItem
, uint32 count
, bool clone
)
1684 sLog
.outDebug( "GUILD STORAGE: StoreItem tab = %u, slot = %u, item = %u, count = %u", tab
, slot
, pItem
->GetEntry(), count
);
1686 Item
* pItem2
= m_TabListMap
[tab
]->Slots
[slot
];
1691 pItem
= pItem
->CloneItem(count
);
1693 pItem
->SetCount(count
);
1698 m_TabListMap
[tab
]->Slots
[slot
] = pItem
;
1700 pItem
->SetUInt64Value(ITEM_FIELD_CONTAINED
, 0);
1701 pItem
->SetUInt64Value(ITEM_FIELD_OWNER
, 0);
1702 AddGBankItemToDB(GetId(), tab
, slot
, pItem
->GetGUIDLow(), pItem
->GetEntry());
1703 pItem
->FSetState(ITEM_NEW
);
1704 pItem
->SaveToDB(); // not in inventory and can be save standalone
1710 pItem2
->SetCount( pItem2
->GetCount() + count
);
1711 pItem2
->FSetState(ITEM_CHANGED
);
1712 pItem2
->SaveToDB(); // not in inventory and can be save standalone
1716 pItem
->RemoveFromWorld();
1717 pItem
->DeleteFromDB();
1725 void Guild::RemoveItem(uint8 tab
, uint8 slot
)
1727 m_TabListMap
[tab
]->Slots
[slot
] = NULL
;
1728 CharacterDatabase
.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'",
1729 GetId(), uint32(tab
), uint32(slot
));
1732 uint8
Guild::_CanStoreItem_InSpecificSlot( uint8 tab
, uint8 slot
, GuildItemPosCountVec
&dest
, uint32
& count
, bool swap
, Item
* pSrcItem
) const
1734 Item
* pItem2
= m_TabListMap
[tab
]->Slots
[slot
];
1736 // ignore move item (this slot will be empty at move)
1737 if (pItem2
== pSrcItem
)
1742 // empty specific slot - check item fit to slot
1743 if (!pItem2
|| swap
)
1745 // non empty stack with space
1746 need_space
= pSrcItem
->GetMaxStackCount();
1748 // non empty slot, check item type
1752 if (pItem2
->GetEntry() != pSrcItem
->GetEntry())
1753 return EQUIP_ERR_ITEM_CANT_STACK
;
1756 if (pItem2
->GetCount() >= pSrcItem
->GetMaxStackCount())
1757 return EQUIP_ERR_ITEM_CANT_STACK
;
1759 need_space
= pSrcItem
->GetMaxStackCount() - pItem2
->GetCount();
1762 if (need_space
> count
)
1765 GuildItemPosCount newPosition
= GuildItemPosCount(slot
, need_space
);
1766 if (!newPosition
.isContainedIn(dest
))
1768 dest
.push_back(newPosition
);
1769 count
-= need_space
;
1772 return EQUIP_ERR_OK
;
1775 uint8
Guild::_CanStoreItem_InTab( uint8 tab
, GuildItemPosCountVec
&dest
, uint32
& count
, bool merge
, Item
* pSrcItem
, uint8 skip_slot
) const
1777 for (uint32 j
= 0; j
< GUILD_BANK_MAX_SLOTS
; ++j
)
1779 // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot
1783 Item
* pItem2
= m_TabListMap
[tab
]->Slots
[j
];
1785 // ignore move item (this slot will be empty at move)
1786 if (pItem2
== pSrcItem
)
1789 // if merge skip empty, if !merge skip non-empty
1790 if ((pItem2
!= NULL
) != merge
)
1795 if (pItem2
->GetEntry() == pSrcItem
->GetEntry() && pItem2
->GetCount() < pSrcItem
->GetMaxStackCount())
1797 uint32 need_space
= pSrcItem
->GetMaxStackCount() - pItem2
->GetCount();
1798 if (need_space
> count
)
1801 GuildItemPosCount newPosition
= GuildItemPosCount(j
, need_space
);
1802 if (!newPosition
.isContainedIn(dest
))
1804 dest
.push_back(newPosition
);
1805 count
-= need_space
;
1808 return EQUIP_ERR_OK
;
1814 uint32 need_space
= pSrcItem
->GetMaxStackCount();
1815 if (need_space
> count
)
1818 GuildItemPosCount newPosition
= GuildItemPosCount(j
, need_space
);
1819 if (!newPosition
.isContainedIn(dest
))
1821 dest
.push_back(newPosition
);
1822 count
-= need_space
;
1825 return EQUIP_ERR_OK
;
1829 return EQUIP_ERR_OK
;
1832 uint8
Guild::CanStoreItem( uint8 tab
, uint8 slot
, GuildItemPosCountVec
&dest
, uint32 count
, Item
*pItem
, bool swap
) const
1834 sLog
.outDebug( "GUILD STORAGE: CanStoreItem tab = %u, slot = %u, item = %u, count = %u", tab
, slot
, pItem
->GetEntry(), count
);
1836 if (count
> pItem
->GetCount())
1837 return EQUIP_ERR_COULDNT_SPLIT_ITEMS
;
1839 if (pItem
->IsSoulBound())
1840 return EQUIP_ERR_CANT_DROP_SOULBOUND
;
1843 if (slot
!= NULL_SLOT
)
1845 uint8 res
= _CanStoreItem_InSpecificSlot(tab
,slot
,dest
,count
,swap
,pItem
);
1846 if (res
!= EQUIP_ERR_OK
)
1850 return EQUIP_ERR_OK
;
1853 // not specific slot or have space for partly store only in specific slot
1855 // search stack in tab for merge to
1856 if (pItem
->GetMaxStackCount() > 1)
1858 uint8 res
= _CanStoreItem_InTab(tab
, dest
, count
, true, pItem
, slot
);
1859 if (res
!= EQUIP_ERR_OK
)
1863 return EQUIP_ERR_OK
;
1866 // search free slot in bag for place to
1867 uint8 res
= _CanStoreItem_InTab(tab
, dest
, count
, false, pItem
, slot
);
1868 if (res
!= EQUIP_ERR_OK
)
1872 return EQUIP_ERR_OK
;
1874 return EQUIP_ERR_BANK_FULL
;
1877 void Guild::SetGuildBankTabText(uint8 TabId
, std::string text
)
1879 if (TabId
>= GUILD_BANK_MAX_TABS
)
1881 if (TabId
>= m_TabListMap
.size())
1883 if (!m_TabListMap
[TabId
])
1886 if (m_TabListMap
[TabId
]->Text
== text
)
1889 utf8truncate(text
, 500); // DB and client size limitation
1891 m_TabListMap
[TabId
]->Text
= text
;
1893 CharacterDatabase
.escape_string(text
);
1894 CharacterDatabase
.PExecute("UPDATE guild_bank_tab SET TabText='%s' WHERE guildid='%u' AND TabId='%u'", text
.c_str(), m_Id
, uint32(TabId
));
1897 SendGuildBankTabText(NULL
,TabId
);
1900 void Guild::SendGuildBankTabText(WorldSession
*session
, uint8 TabId
)
1902 GuildBankTab
const* tab
= m_TabListMap
[TabId
];
1904 WorldPacket
data(MSG_QUERY_GUILD_BANK_TEXT
, 1+tab
->Text
.size()+1);
1905 data
<< uint8(TabId
);
1909 session
->SendPacket(&data
);
1911 BroadcastPacket(&data
);
1914 void Guild::SwapItems(Player
* pl
, uint8 BankTab
, uint8 BankTabSlot
, uint8 BankTabDst
, uint8 BankTabSlotDst
, uint32 SplitedAmount
)
1917 if (BankTab
== BankTabDst
&& BankTabSlot
== BankTabSlotDst
)
1920 Item
*pItemSrc
= GetItem(BankTab
, BankTabSlot
);
1921 if (!pItemSrc
) // may prevent crash
1924 if (SplitedAmount
> pItemSrc
->GetCount())
1925 return; // cheating?
1926 else if (SplitedAmount
== pItemSrc
->GetCount())
1927 SplitedAmount
= 0; // no split
1929 Item
*pItemDst
= GetItem(BankTabDst
, BankTabSlotDst
);
1931 if (BankTab
!= BankTabDst
)
1933 // check dest pos rights (if different tabs)
1934 if (!IsMemberHaveRights(pl
->GetGUIDLow(), BankTabDst
, GUILD_BANK_RIGHT_DEPOSIT_ITEM
))
1937 // check source pos rights (if different tabs)
1938 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
1944 { // Bank -> Bank item split (in empty or non empty slot
1945 GuildItemPosCountVec dest
;
1946 uint8 msg
= CanStoreItem(BankTabDst
, BankTabSlotDst
, dest
, SplitedAmount
, pItemSrc
, false);
1947 if (msg
!= EQUIP_ERR_OK
)
1949 pl
->SendEquipError( msg
, pItemSrc
, NULL
);
1953 Item
*pNewItem
= pItemSrc
->CloneItem( SplitedAmount
);
1956 pl
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, pItemSrc
, NULL
);
1960 CharacterDatabase
.BeginTransaction();
1961 LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemSrc
->GetEntry(), SplitedAmount
, BankTabDst
);
1963 pl
->ItemRemovedQuestCheck( pItemSrc
->GetEntry(), SplitedAmount
);
1964 pItemSrc
->SetCount( pItemSrc
->GetCount() - SplitedAmount
);
1965 pItemSrc
->FSetState(ITEM_CHANGED
);
1966 pItemSrc
->SaveToDB(); // not in inventory and can be save standalone
1967 StoreItem(BankTabDst
, dest
, pNewItem
);
1968 CharacterDatabase
.CommitTransaction();
1972 GuildItemPosCountVec gDest
;
1973 uint8 msg
= CanStoreItem(BankTabDst
,BankTabSlotDst
,gDest
,pItemSrc
->GetCount(), pItemSrc
, false);
1974 if (msg
== EQUIP_ERR_OK
) // merge to
1976 CharacterDatabase
.BeginTransaction();
1977 LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemSrc
->GetEntry(), pItemSrc
->GetCount(), BankTabDst
);
1979 RemoveItem(BankTab
, BankTabSlot
);
1980 StoreItem(BankTabDst
, gDest
, pItemSrc
);
1981 CharacterDatabase
.CommitTransaction();
1986 msg
= CanStoreItem(BankTabDst
, BankTabSlotDst
, gDest
, pItemSrc
->GetCount(), pItemSrc
, true);
1987 if (msg
!= EQUIP_ERR_OK
)
1989 pl
->SendEquipError( msg
, pItemSrc
, NULL
);
1993 GuildItemPosCountVec gSrc
;
1994 msg
= CanStoreItem(BankTab
, BankTabSlot
, gSrc
, pItemDst
->GetCount(), pItemDst
, true);
1995 if (msg
!= EQUIP_ERR_OK
)
1997 pl
->SendEquipError( msg
, pItemDst
, NULL
);
2001 if (BankTab
!= BankTabDst
)
2003 // check source pos rights (item swapped to src)
2004 if (!IsMemberHaveRights(pl
->GetGUIDLow(), BankTab
, GUILD_BANK_RIGHT_DEPOSIT_ITEM
))
2007 // check dest pos rights (item swapped to src)
2008 uint32 remRightDst
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTabDst
);
2009 if (remRightDst
<= 0)
2013 CharacterDatabase
.BeginTransaction();
2014 LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemSrc
->GetEntry(), pItemSrc
->GetCount(), BankTabDst
);
2015 LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM
, BankTabDst
, pl
->GetGUIDLow(), pItemDst
->GetEntry(), pItemDst
->GetCount(), BankTab
);
2017 RemoveItem(BankTab
, BankTabSlot
);
2018 RemoveItem(BankTabDst
, BankTabSlotDst
);
2019 StoreItem(BankTab
, gSrc
, pItemDst
);
2020 StoreItem(BankTabDst
, gDest
, pItemSrc
);
2021 CharacterDatabase
.CommitTransaction();
2024 DisplayGuildBankContentUpdate(BankTab
, BankTabSlot
, BankTab
== BankTabDst
? BankTabSlotDst
: -1);
2025 if (BankTab
!= BankTabDst
)
2026 DisplayGuildBankContentUpdate(BankTabDst
, BankTabSlotDst
);
2030 void Guild::MoveFromBankToChar( Player
* pl
, uint8 BankTab
, uint8 BankTabSlot
, uint8 PlayerBag
, uint8 PlayerSlot
, uint32 SplitedAmount
)
2032 Item
*pItemBank
= GetItem(BankTab
, BankTabSlot
);
2033 Item
*pItemChar
= pl
->GetItemByPos(PlayerBag
, PlayerSlot
);
2035 if (!pItemBank
) // Problem to get bank item
2038 if (SplitedAmount
> pItemBank
->GetCount())
2039 return; // cheating?
2040 else if (SplitedAmount
== pItemBank
->GetCount())
2041 SplitedAmount
= 0; // no split
2044 { // Bank -> Char split to slot (patly move)
2045 Item
*pNewItem
= pItemBank
->CloneItem( SplitedAmount
);
2048 pl
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, pItemBank
, NULL
);
2052 ItemPosCountVec dest
;
2053 uint8 msg
= pl
->CanStoreItem(PlayerBag
, PlayerSlot
, dest
, pNewItem
, false);
2054 if (msg
!= EQUIP_ERR_OK
)
2056 pl
->SendEquipError( msg
, pNewItem
, NULL
);
2061 // check source pos rights (item moved to inventory)
2062 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
2069 CharacterDatabase
.BeginTransaction();
2070 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemBank
->GetEntry(), SplitedAmount
);
2072 pItemBank
->SetCount(pItemBank
->GetCount()-SplitedAmount
);
2073 pItemBank
->FSetState(ITEM_CHANGED
);
2074 pItemBank
->SaveToDB(); // not in inventory and can be save standalone
2075 pl
->MoveItemToInventory(dest
, pNewItem
, true);
2076 pl
->SaveInventoryAndGoldToDB();
2078 MemberItemWithdraw(BankTab
, pl
->GetGUIDLow());
2079 CharacterDatabase
.CommitTransaction();
2081 else // Bank -> Char swap with slot (move)
2083 ItemPosCountVec dest
;
2084 uint8 msg
= pl
->CanStoreItem(PlayerBag
, PlayerSlot
, dest
, pItemBank
, false);
2085 if (msg
== EQUIP_ERR_OK
) // merge case
2087 // check source pos rights (item moved to inventory)
2088 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
2092 CharacterDatabase
.BeginTransaction();
2093 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemBank
->GetEntry(), pItemBank
->GetCount());
2095 RemoveItem(BankTab
, BankTabSlot
);
2096 pl
->MoveItemToInventory(dest
, pItemBank
, true);
2097 pl
->SaveInventoryAndGoldToDB();
2099 MemberItemWithdraw(BankTab
, pl
->GetGUIDLow());
2100 CharacterDatabase
.CommitTransaction();
2102 else // Bank <-> Char swap items
2104 // check source pos rights (item swapped to bank)
2105 if (!IsMemberHaveRights(pl
->GetGUIDLow(), BankTab
, GUILD_BANK_RIGHT_DEPOSIT_ITEM
))
2110 if (!pItemChar
->CanBeTraded())
2112 pl
->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED
, pItemChar
, NULL
);
2117 ItemPosCountVec iDest
;
2118 msg
= pl
->CanStoreItem(PlayerBag
, PlayerSlot
, iDest
, pItemBank
, true);
2119 if (msg
!= EQUIP_ERR_OK
)
2121 pl
->SendEquipError( msg
, pItemBank
, NULL
);
2125 GuildItemPosCountVec gDest
;
2128 msg
= CanStoreItem(BankTab
,BankTabSlot
,gDest
,pItemChar
->GetCount(),pItemChar
,true);
2129 if (msg
!= EQUIP_ERR_OK
)
2131 pl
->SendEquipError( msg
, pItemChar
, NULL
);
2136 // check source pos rights (item moved to inventory)
2137 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
2143 // logging item move to bank
2144 if (pl
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_BOOL_GM_LOG_TRADE
))
2146 sLog
.outCommand(pl
->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
2147 pl
->GetName(),pl
->GetSession()->GetAccountId(),
2148 pItemChar
->GetProto()->Name1
, pItemChar
->GetEntry(), pItemChar
->GetCount(),
2153 CharacterDatabase
.BeginTransaction();
2154 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemBank
->GetEntry(), pItemBank
->GetCount());
2156 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemChar
->GetEntry(), pItemChar
->GetCount());
2158 RemoveItem(BankTab
, BankTabSlot
);
2161 pl
->MoveItemFromInventory(PlayerBag
, PlayerSlot
, true);
2162 pItemChar
->DeleteFromInventoryDB();
2166 StoreItem(BankTab
, gDest
, pItemChar
);
2167 pl
->MoveItemToInventory(iDest
, pItemBank
, true);
2168 pl
->SaveInventoryAndGoldToDB();
2170 MemberItemWithdraw(BankTab
, pl
->GetGUIDLow());
2171 CharacterDatabase
.CommitTransaction();
2174 DisplayGuildBankContentUpdate(BankTab
, BankTabSlot
);
2178 void Guild::MoveFromCharToBank( Player
* pl
, uint8 PlayerBag
, uint8 PlayerSlot
, uint8 BankTab
, uint8 BankTabSlot
, uint32 SplitedAmount
)
2180 Item
*pItemBank
= GetItem(BankTab
, BankTabSlot
);
2181 Item
*pItemChar
= pl
->GetItemByPos(PlayerBag
, PlayerSlot
);
2183 if (!pItemChar
) // Problem to get item from player
2186 if (!pItemChar
->CanBeTraded())
2188 pl
->SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED
, pItemChar
, NULL
);
2192 // check source pos rights (item moved to bank)
2193 if (!IsMemberHaveRights(pl
->GetGUIDLow(), BankTab
, GUILD_BANK_RIGHT_DEPOSIT_ITEM
))
2196 if (SplitedAmount
> pItemChar
->GetCount())
2197 return; // cheating?
2198 else if (SplitedAmount
== pItemChar
->GetCount())
2199 SplitedAmount
= 0; // no split
2202 { // Char -> Bank split to empty or non-empty slot (partly move)
2203 GuildItemPosCountVec dest
;
2204 uint8 msg
= CanStoreItem(BankTab
, BankTabSlot
, dest
, SplitedAmount
, pItemChar
, false);
2205 if (msg
!= EQUIP_ERR_OK
)
2207 pl
->SendEquipError( msg
, pItemChar
, NULL
);
2211 Item
*pNewItem
= pItemChar
->CloneItem( SplitedAmount
);
2214 pl
->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND
, pItemChar
, NULL
);
2218 // logging item move to bank (before items merge
2219 if (pl
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_BOOL_GM_LOG_TRADE
))
2221 sLog
.outCommand(pl
->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
2222 pl
->GetName(),pl
->GetSession()->GetAccountId(),
2223 pItemChar
->GetProto()->Name1
, pItemChar
->GetEntry(), SplitedAmount
, m_Id
);
2226 CharacterDatabase
.BeginTransaction();
2227 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemChar
->GetEntry(), SplitedAmount
);
2229 pl
->ItemRemovedQuestCheck( pItemChar
->GetEntry(), SplitedAmount
);
2230 pItemChar
->SetCount(pItemChar
->GetCount()-SplitedAmount
);
2231 pItemChar
->SetState(ITEM_CHANGED
);
2232 pl
->SaveInventoryAndGoldToDB();
2233 StoreItem(BankTab
, dest
, pNewItem
);
2234 CharacterDatabase
.CommitTransaction();
2236 DisplayGuildBankContentUpdate(BankTab
, dest
);
2238 else // Char -> Bank swap with empty or non-empty (move)
2240 GuildItemPosCountVec dest
;
2241 uint8 msg
= CanStoreItem(BankTab
, BankTabSlot
, dest
, pItemChar
->GetCount(), pItemChar
, false);
2242 if (msg
== EQUIP_ERR_OK
) // merge
2244 // logging item move to bank
2245 if (pl
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_BOOL_GM_LOG_TRADE
))
2247 sLog
.outCommand(pl
->GetSession()->GetAccountId(),"GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
2248 pl
->GetName(),pl
->GetSession()->GetAccountId(),
2249 pItemChar
->GetProto()->Name1
, pItemChar
->GetEntry(), pItemChar
->GetCount(),
2253 CharacterDatabase
.BeginTransaction();
2254 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemChar
->GetEntry(), pItemChar
->GetCount());
2256 pl
->MoveItemFromInventory(PlayerBag
, PlayerSlot
, true);
2257 pItemChar
->DeleteFromInventoryDB();
2259 StoreItem(BankTab
, dest
, pItemChar
);
2260 pl
->SaveInventoryAndGoldToDB();
2261 CharacterDatabase
.CommitTransaction();
2263 DisplayGuildBankContentUpdate(BankTab
, dest
);
2265 else // Char <-> Bank swap items (posible NULL bank item)
2267 ItemPosCountVec iDest
;
2270 msg
= pl
->CanStoreItem(PlayerBag
, PlayerSlot
, iDest
, pItemBank
, true);
2271 if (msg
!= EQUIP_ERR_OK
)
2273 pl
->SendEquipError( msg
, pItemBank
, NULL
);
2278 GuildItemPosCountVec gDest
;
2279 msg
= CanStoreItem(BankTab
, BankTabSlot
, gDest
, pItemChar
->GetCount(), pItemChar
, true);
2280 if (msg
!= EQUIP_ERR_OK
)
2282 pl
->SendEquipError( msg
, pItemChar
, NULL
);
2288 // check bank pos rights (item swapped with inventory)
2289 uint32 remRight
= GetMemberSlotWithdrawRem(pl
->GetGUIDLow(), BankTab
);
2294 // logging item move to bank
2295 if (pl
->GetSession()->GetSecurity() > SEC_PLAYER
&& sWorld
.getConfig(CONFIG_BOOL_GM_LOG_TRADE
))
2297 sLog
.outCommand(pl
->GetSession()->GetAccountId(), "GM %s (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank (Guild ID: %u )",
2298 pl
->GetName(), pl
->GetSession()->GetAccountId(),
2299 pItemChar
->GetProto()->Name1
, pItemChar
->GetEntry(), pItemChar
->GetCount(),
2303 CharacterDatabase
.BeginTransaction();
2305 LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemBank
->GetEntry(), pItemBank
->GetCount());
2306 LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM
, BankTab
, pl
->GetGUIDLow(), pItemChar
->GetEntry(), pItemChar
->GetCount());
2308 pl
->MoveItemFromInventory(PlayerBag
, PlayerSlot
, true);
2309 pItemChar
->DeleteFromInventoryDB();
2311 RemoveItem(BankTab
, BankTabSlot
);
2313 StoreItem(BankTab
, gDest
, pItemChar
);
2315 pl
->MoveItemToInventory(iDest
, pItemBank
, true);
2316 pl
->SaveInventoryAndGoldToDB();
2318 MemberItemWithdraw(BankTab
, pl
->GetGUIDLow());
2319 CharacterDatabase
.CommitTransaction();
2321 DisplayGuildBankContentUpdate(BankTab
, gDest
);
2326 void Guild::BroadcastEvent(GuildEvents event
, uint64 guid
, uint8 strCount
, std::string str1
, std::string str2
, std::string str3
)
2328 WorldPacket
data(SMSG_GUILD_EVENT
, 1+1+(guid
? 8 : 0));
2329 data
<< uint8(event
);
2330 data
<< uint8(strCount
);
2340 data
<< str1
<< str2
;
2343 data
<< str1
<< str2
<< str3
;
2346 sLog
.outError("Guild::BroadcastEvent: incorrect strings count %u!", strCount
);
2351 data
<< uint64(guid
);
2353 BroadcastPacket(&data
);
2355 sLog
.outDebug("WORLD: Sent SMSG_GUILD_EVENT");
2358 bool GuildItemPosCount::isContainedIn(GuildItemPosCountVec
const &vec
) const
2360 for(GuildItemPosCountVec::const_iterator itr
= vec
.begin(); itr
!= vec
.end(); ++itr
)
2361 if (itr
->Slot
== this->Slot
)