[8449] Deprecate healing/damage item mods and merge internal data in to spell power.
[getmangos.git] / src / game / SocialMgr.cpp
blob65dc730c792d127671b9bbae2456b6b880f500d7
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "SocialMgr.h"
20 #include "Policies/SingletonImp.h"
21 #include "Database/DatabaseEnv.h"
22 #include "Opcodes.h"
23 #include "WorldPacket.h"
24 #include "Player.h"
25 #include "ObjectMgr.h"
26 #include "World.h"
27 #include "Util.h"
29 INSTANTIATE_SINGLETON_1( SocialMgr );
31 PlayerSocial::PlayerSocial()
33 m_playerGUID = 0;
36 PlayerSocial::~PlayerSocial()
38 m_playerSocialMap.clear();
41 uint32 PlayerSocial::GetNumberOfSocialsWithFlag(SocialFlag flag)
43 uint32 counter = 0;
44 for(PlayerSocialMap::const_iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr)
46 if(itr->second.Flags & flag)
47 ++counter;
49 return counter;
52 bool PlayerSocial::AddToSocialList(uint32 friend_guid, bool ignore)
54 // check client limits
55 if(ignore)
57 if(GetNumberOfSocialsWithFlag(SOCIAL_FLAG_IGNORED) >= SOCIALMGR_IGNORE_LIMIT)
58 return false;
60 else
62 if(GetNumberOfSocialsWithFlag(SOCIAL_FLAG_FRIEND) >= SOCIALMGR_FRIEND_LIMIT)
63 return false;
66 uint32 flag = SOCIAL_FLAG_FRIEND;
67 if(ignore)
68 flag = SOCIAL_FLAG_IGNORED;
70 PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(friend_guid);
71 if(itr != m_playerSocialMap.end())
73 CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags | %u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
74 m_playerSocialMap[friend_guid].Flags |= flag;
76 else
78 CharacterDatabase.PExecute("INSERT INTO character_social (guid, friend, flags) VALUES ('%u', '%u', '%u')", GetPlayerGUID(), friend_guid, flag);
79 FriendInfo fi;
80 fi.Flags |= flag;
81 m_playerSocialMap[friend_guid] = fi;
83 return true;
86 void PlayerSocial::RemoveFromSocialList(uint32 friend_guid, bool ignore)
88 PlayerSocialMap::iterator itr = m_playerSocialMap.find(friend_guid);
89 if(itr == m_playerSocialMap.end()) // not exist
90 return;
92 uint32 flag = SOCIAL_FLAG_FRIEND;
93 if(ignore)
94 flag = SOCIAL_FLAG_IGNORED;
96 itr->second.Flags &= ~flag;
97 if(itr->second.Flags == 0)
99 CharacterDatabase.PExecute("DELETE FROM character_social WHERE guid = '%u' AND friend = '%u'", GetPlayerGUID(), friend_guid);
100 m_playerSocialMap.erase(itr);
102 else
104 CharacterDatabase.PExecute("UPDATE character_social SET flags = (flags & ~%u) WHERE guid = '%u' AND friend = '%u'", flag, GetPlayerGUID(), friend_guid);
108 void PlayerSocial::SetFriendNote(uint32 friend_guid, std::string note)
110 PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(friend_guid);
111 if(itr == m_playerSocialMap.end()) // not exist
112 return;
114 utf8truncate(note,48); // DB and client size limitation
116 CharacterDatabase.escape_string(note);
117 CharacterDatabase.PExecute("UPDATE character_social SET note = '%s' WHERE guid = '%u' AND friend = '%u'", note.c_str(), GetPlayerGUID(), friend_guid);
118 m_playerSocialMap[friend_guid].Note = note;
121 void PlayerSocial::SendSocialList()
123 Player *plr = objmgr.GetPlayer(GetPlayerGUID());
124 if(!plr)
125 return;
127 uint32 size = m_playerSocialMap.size();
129 WorldPacket data(SMSG_CONTACT_LIST, (4+4+size*25)); // just can guess size
130 data << uint32(7); // unk flag (0x1, 0x2, 0x4), 0x7 if it include ignore list
131 data << uint32(size); // friends count
133 for(PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr)
135 sSocialMgr.GetFriendInfo(plr, itr->first, itr->second);
137 data << uint64(itr->first); // player guid
138 data << uint32(itr->second.Flags); // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?)
139 data << itr->second.Note; // string note
140 if(itr->second.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend()
142 data << uint8(itr->second.Status); // online/offline/etc?
143 if(itr->second.Status) // if online
145 data << uint32(itr->second.Area); // player area
146 data << uint32(itr->second.Level); // player level
147 data << uint32(itr->second.Class); // player class
152 plr->GetSession()->SendPacket(&data);
153 sLog.outDebug("WORLD: Sent SMSG_CONTACT_LIST");
156 bool PlayerSocial::HasFriend(uint32 friend_guid)
158 PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(friend_guid);
159 if(itr != m_playerSocialMap.end())
160 return itr->second.Flags & SOCIAL_FLAG_FRIEND;
161 return false;
164 bool PlayerSocial::HasIgnore(uint32 ignore_guid)
166 PlayerSocialMap::const_iterator itr = m_playerSocialMap.find(ignore_guid);
167 if(itr != m_playerSocialMap.end())
168 return itr->second.Flags & SOCIAL_FLAG_IGNORED;
169 return false;
172 SocialMgr::SocialMgr()
177 SocialMgr::~SocialMgr()
182 void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo)
184 if(!player)
185 return;
187 Player *pFriend = ObjectAccessor::FindPlayer(friendGUID);
189 uint32 team = player->GetTeam();
190 AccountTypes security = player->GetSession()->GetSecurity();
191 bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
192 AccountTypes gmLevelInWhoList = AccountTypes (sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST));
194 PlayerSocialMap::iterator itr = player->GetSocial()->m_playerSocialMap.find(friendGUID);
195 if(itr != player->GetSocial()->m_playerSocialMap.end())
196 friendInfo.Note = itr->second.Note;
198 // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
199 // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
200 if (pFriend && pFriend->GetName() &&
201 (security > SEC_PLAYER ||
202 (pFriend->GetTeam() == team || allowTwoSideWhoList) && (pFriend->GetSession()->GetSecurity() <= gmLevelInWhoList)) &&
203 pFriend->IsVisibleGloballyFor(player))
205 friendInfo.Status = FRIEND_STATUS_ONLINE;
206 if(pFriend->isAFK())
207 friendInfo.Status = FRIEND_STATUS_AFK;
208 if(pFriend->isDND())
209 friendInfo.Status = FRIEND_STATUS_DND;
210 friendInfo.Area = pFriend->GetZoneId();
211 friendInfo.Level = pFriend->getLevel();
212 friendInfo.Class = pFriend->getClass();
214 else
216 friendInfo.Status = FRIEND_STATUS_OFFLINE;
217 friendInfo.Area = 0;
218 friendInfo.Level = 0;
219 friendInfo.Class = 0;
223 void SocialMgr::MakeFriendStatusPacket(FriendsResult result, uint32 guid, WorldPacket *data)
225 data->Initialize(SMSG_FRIEND_STATUS, 5);
226 *data << uint8(result);
227 *data << uint64(guid);
230 void SocialMgr::SendFriendStatus(Player *player, FriendsResult result, uint32 friend_guid, bool broadcast)
232 FriendInfo fi;
234 WorldPacket data;
235 MakeFriendStatusPacket(result, friend_guid, &data);
236 GetFriendInfo(player, friend_guid, fi);
237 switch(result)
239 case FRIEND_ADDED_OFFLINE:
240 case FRIEND_ADDED_ONLINE:
241 data << fi.Note;
242 break;
243 default:
244 break;
247 switch(result)
249 case FRIEND_ADDED_ONLINE:
250 case FRIEND_ONLINE:
251 data << uint8(fi.Status);
252 data << uint32(fi.Area);
253 data << uint32(fi.Level);
254 data << uint32(fi.Class);
255 break;
256 default:
257 break;
260 if(broadcast)
261 BroadcastToFriendListers(player, &data);
262 else
263 player->GetSession()->SendPacket(&data);
266 void SocialMgr::BroadcastToFriendListers(Player *player, WorldPacket *packet)
268 if(!player)
269 return;
271 uint32 team = player->GetTeam();
272 AccountTypes security = player->GetSession()->GetSecurity();
273 uint32 guid = player->GetGUIDLow();
274 AccountTypes gmLevelInWhoList = AccountTypes(sWorld.getConfig(CONFIG_GM_LEVEL_IN_WHO_LIST));
275 bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST);
277 for(SocialMap::const_iterator itr = m_socialMap.begin(); itr != m_socialMap.end(); ++itr)
279 PlayerSocialMap::const_iterator itr2 = itr->second.m_playerSocialMap.find(guid);
280 if(itr2 != itr->second.m_playerSocialMap.end() && (itr2->second.Flags & SOCIAL_FLAG_FRIEND))
282 Player *pFriend = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER));
284 // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
285 // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
286 if (pFriend && pFriend->IsInWorld() &&
287 (pFriend->GetSession()->GetSecurity() > SEC_PLAYER ||
288 (pFriend->GetTeam() == team || allowTwoSideWhoList) && security <= gmLevelInWhoList) &&
289 player->IsVisibleGloballyFor(pFriend))
291 pFriend->GetSession()->SendPacket(packet);
297 PlayerSocial *SocialMgr::LoadFromDB(QueryResult *result, uint32 guid)
299 PlayerSocial *social = &m_socialMap[guid];
300 social->SetPlayerGUID(guid);
302 if(!result)
303 return social;
305 uint32 friend_guid = 0;
306 uint32 flags = 0;
307 std::string note = "";
309 // used to speed up check below. Using GetNumberOfSocialsWithFlag will cause unneeded iteration
310 uint32 friendCounter=0, ignoreCounter=0;
314 Field *fields = result->Fetch();
316 friend_guid = fields[0].GetUInt32();
317 flags = fields[1].GetUInt32();
318 note = fields[2].GetCppString();
320 if((flags & SOCIAL_FLAG_IGNORED) && ignoreCounter >= SOCIALMGR_IGNORE_LIMIT)
321 continue;
322 if((flags & SOCIAL_FLAG_FRIEND) && friendCounter >= SOCIALMGR_FRIEND_LIMIT)
323 continue;
325 social->m_playerSocialMap[friend_guid] = FriendInfo(flags, note);
327 if(flags & SOCIAL_FLAG_IGNORED)
328 ignoreCounter++;
329 else
330 friendCounter++;
332 while( result->NextRow() );
333 delete result;
334 return social;