[9581] Fixed apply damage reduction to melee/ranged damage.
[getmangos.git] / src / game / LFGHandler.cpp
blobddfdd0a6acf266e53da90fbd9c91a85162b22c24
1 /*
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 "WorldSession.h"
20 #include "Log.h"
21 #include "Database/DatabaseEnv.h"
22 #include "Player.h"
23 #include "WorldPacket.h"
24 #include "ObjectMgr.h"
25 #include "World.h"
27 static void AttemptJoin(Player* _player)
29 // skip not can autojoin cases and player group case
30 if(!_player->m_lookingForGroup.canAutoJoin() || _player->GetGroup())
31 return;
33 //TODO: Guard Player Map
34 HashMapHolder<Player>::MapType const& players = sObjectAccessor.GetPlayers();
35 for(HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
37 Player *plr = iter->second;
39 // skip enemies and self
40 if(!plr || plr==_player || plr->GetTeam() != _player->GetTeam())
41 continue;
43 //skip players not in world
44 if(!plr->IsInWorld())
45 continue;
47 // skip not auto add, not group leader cases
48 if (!plr->GetSession()->LookingForGroup_auto_add || (plr->GetGroup() && plr->GetGroup()->GetLeaderGUID()!=plr->GetGUID()))
49 continue;
51 // skip non auto-join or empty slots, or non compatible slots
52 if(!plr->m_lookingForGroup.more.canAutoJoin() || !_player->m_lookingForGroup.HaveInSlot(plr->m_lookingForGroup.more))
53 continue;
55 // attempt create group, or skip
56 if(!plr->GetGroup())
58 Group* group = new Group;
59 if(!group->Create(plr->GetGUID(), plr->GetName()))
61 delete group;
62 continue;
65 sObjectMgr.AddGroup(group);
68 // stop at success join
69 if(plr->GetGroup()->AddMember(_player->GetGUID(), _player->GetName()))
71 if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER )
72 _player->LeaveLFGChannel();
73 break;
75 // full
76 else
78 if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER )
79 plr->LeaveLFGChannel();
84 static void AttemptAddMore(Player* _player)
86 // skip not group leader case
87 if(_player->GetGroup() && _player->GetGroup()->GetLeaderGUID()!=_player->GetGUID())
88 return;
90 if(!_player->m_lookingForGroup.more.canAutoJoin())
91 return;
93 //TODO: Guard Player map
94 HashMapHolder<Player>::MapType const& players = sObjectAccessor.GetPlayers();
95 for(HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
97 Player *plr = iter->second;
99 // skip enemies and self
100 if(!plr || plr==_player || plr->GetTeam() != _player->GetTeam())
101 continue;
103 if(!plr->IsInWorld())
104 continue;
106 // skip not auto join or in group
107 if(!plr->GetSession()->LookingForGroup_auto_join || plr->GetGroup() )
108 continue;
110 if(!plr->m_lookingForGroup.HaveInSlot(_player->m_lookingForGroup.more))
111 continue;
113 // attempt create group if need, or stop attempts
114 if(!_player->GetGroup())
116 Group* group = new Group;
117 if(!group->Create(_player->GetGUID(), _player->GetName()))
119 delete group;
120 return; // can't create group (??)
123 sObjectMgr.AddGroup(group);
126 // stop at join fail (full)
127 if(!_player->GetGroup()->AddMember(plr->GetGUID(), plr->GetName()) )
129 if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER )
130 _player->LeaveLFGChannel();
132 break;
135 // joined
136 if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && plr->GetSession()->GetSecurity() == SEC_PLAYER )
137 plr->LeaveLFGChannel();
139 // and group full
140 if(_player->GetGroup()->IsFull() )
142 if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER )
143 _player->LeaveLFGChannel();
145 break;
150 void WorldSession::HandleLfgJoinOpcode( WorldPacket & recv_data )
152 sLog.outDebug("CMSG_LFG_JOIN");
153 LookingForGroup_auto_join = true;
155 uint8 counter1, counter2;
156 std::string comment;
158 recv_data >> Unused<uint32>(); // lfg roles
159 recv_data >> Unused<uint8>(); // unk1 (unused?)
160 recv_data >> Unused<uint8>(); // unk2 (unused?)
162 recv_data >> counter1;
163 for (uint8 i = 0; i < counter1; i++)
164 recv_data >> Unused<uint32>(); // queue block? (type/zone?)
166 recv_data >> counter2;
167 for (uint8 i = 0; i < counter2; i++)
168 recv_data >> Unused<uint8>(); // unk (unused?)
170 recv_data >> comment; // lfg comment
172 if(!_player) // needed because STATUS_AUTHED
173 return;
175 AttemptJoin(_player);
178 void WorldSession::HandleLfgLeaveOpcode( WorldPacket & /*recv_data*/ )
180 sLog.outDebug("CMSG_LFG_LEAVE");
181 LookingForGroup_auto_join = false;
184 void WorldSession::HandleSearchLfgJoinOpcode( WorldPacket & recv_data )
186 sLog.outDebug("CMSG_SEARCH_LFG_JOIN");
187 LookingForGroup_auto_add = true;
189 recv_data >> Unused<uint32>(); // join id?
191 if(!_player) // needed because STATUS_AUTHED
192 return;
194 AttemptAddMore(_player);
197 void WorldSession::HandleSearchLfgLeaveOpcode( WorldPacket & recv_data )
199 sLog.outDebug("CMSG_SEARCH_LFG_LEAVE");
200 LookingForGroup_auto_add = false;
202 recv_data >> Unused<uint32>(); // join id?
205 void WorldSession::HandleLfgClearOpcode( WorldPacket & /*recv_data */ )
207 // empty packet
208 sLog.outDebug("CMSG_CLEAR_LOOKING_FOR_GROUP");
210 for(int i = 0; i < MAX_LOOKING_FOR_GROUP_SLOT; ++i)
211 _player->m_lookingForGroup.slots[i].Clear();
213 if( sWorld.getConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL) && _player->GetSession()->GetSecurity() == SEC_PLAYER )
214 _player->LeaveLFGChannel();
216 SendLfgUpdate(0, 0, 0);
219 void WorldSession::HandleLfmClearOpcode( WorldPacket & /*recv_data */)
221 // empty packet
222 sLog.outDebug("CMSG_CLEAR_LOOKING_FOR_MORE");
224 _player->m_lookingForGroup.more.Clear();
227 void WorldSession::HandleSetLfmOpcode( WorldPacket & recv_data )
229 sLog.outDebug("CMSG_SET_LOOKING_FOR_MORE");
230 //recv_data.hexlike();
231 uint32 temp, entry, type;
232 uint8 unk1;
233 uint8 unk2[3];
235 recv_data >> temp >> unk1 >> unk2[0] >> unk2[1] >> unk2[2];
237 entry = ( temp & 0x00FFFFFF);
238 type = ( (temp >> 24) & 0x000000FF);
240 _player->m_lookingForGroup.more.Set(entry,type);
241 sLog.outDebug("LFM set: temp %u, zone %u, type %u", temp, entry, type);
243 if(LookingForGroup_auto_add)
244 AttemptAddMore(_player);
246 SendLfgResult(type, entry, 1);
249 void WorldSession::HandleSetLfgCommentOpcode( WorldPacket & recv_data )
251 sLog.outDebug("CMSG_SET_LFG_COMMENT");
252 //recv_data.hexlike();
254 std::string comment;
255 recv_data >> comment;
256 sLog.outDebug("LFG comment %s", comment.c_str());
258 _player->m_lookingForGroup.comment = comment;
261 void WorldSession::HandleLookingForGroup(WorldPacket& recv_data)
263 sLog.outDebug("MSG_LOOKING_FOR_GROUP");
264 //recv_data.hexlike();
265 uint32 type, entry, unk;
267 recv_data >> type >> entry >> unk;
268 sLog.outDebug("MSG_LOOKING_FOR_GROUP: type %u, entry %u, unk %u", type, entry, unk);
270 if(LookingForGroup_auto_add)
271 AttemptAddMore(_player);
273 if(LookingForGroup_auto_join)
274 AttemptJoin(_player);
276 SendLfgResult(type, entry, 0);
277 SendLfgUpdate(0, 1, 0);
280 void WorldSession::SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type)
282 /*uint32 number = 0;
284 WorldPacket data(MSG_LOOKING_FOR_GROUP);
285 data << uint32(type); // type
286 data << uint32(entry); // entry from LFGDungeons.dbc
288 data << uint8(0);
289 if(uint8)
291 uint32 count1;
292 for(count1)
294 uint64; // player guid
298 data << uint32(0); // count2
299 data << uint32(0);
300 for(count2)
302 uint64 // not player guid
303 uint32 flags;
304 if(flags & 0x2)
306 data << uint8(0); // string
308 if(flags & 0x10)
310 data << uint8(0);
312 if(flags & 0x20)
314 for(int i = 0; i < 3; ++i)
316 data << uint8(0);
321 size_t count3_pos = data.wpos();
322 data << uint32(0); // count3
323 data << uint32(0); // unk
325 //TODO: Guard Player map
326 HashMapHolder<Player>::MapType const& players = sObjectAccessor.GetPlayers();
327 for(HashMapHolder<Player>::MapType::const_iterator iter = players.begin(); iter != players.end(); ++iter)
329 Player *plr = iter->second;
331 if(!plr || plr->GetTeam() != _player->GetTeam())
332 continue;
334 if(!plr->IsInWorld())
335 continue;
337 if(!plr->m_lookingForGroup.HaveInSlot(entry, type))
338 continue;
340 ++number;
342 data << uint64(plr->GetGUID()); // guid
344 uint32 flags = 0x1FF;
345 data << uint32(flags); // flags
347 if(flags & 0x1)
349 data << uint8(plr->getLevel());
350 data << uint8(plr->getClass());
351 data << uint8(plr->getRace());
353 for(int i = 0; i < 3; ++i)
354 data << uint8(0); // spent talents count in specific tab
356 data << uint32(0); // resistances1
357 data << uint32(0); // spd/heal
358 data << uint32(0); // spd/heal
359 data << uint32(0); // combat_rating9
360 data << uint32(0); // combat_rating10
361 data << uint32(0); // combat_rating11
362 data << float(0); // mp5
363 data << float(0); // unk
364 data << uint32(0); // attack power
365 data << uint32(0); // stat1
366 data << uint32(0); // maxhealth
367 data << uint32(0); // maxpower1
368 data << uint32(0); // unk
369 data << float(0); // unk
370 data << uint32(0); // unk
371 data << uint32(0); // unk
372 data << uint32(0); // unk
373 data << uint32(0); // unk
374 data << uint32(0); // combat_rating20
375 data << uint32(0); // unk
378 if(flags & 0x2)
379 data << plr->m_lookingForGroup.comment; // comment
381 if(flags & 0x4)
382 data << uint8(0); // unk
384 if(flags & 0x8)
385 data << uint64(0); // guid from count2 block, not player guid
387 if(flags & 0x10)
388 data << uint8(0); // unk
390 if(flags & 0x20)
391 data << uint8(plr->m_lookingForGroup.roles); // roles
393 if(flags & 0x40)
394 data << uint32(plr->GetZoneId()); // areaid
396 if(flags & 0x100)
397 data << uint8(0); // LFG/LFM flag?
399 if(flags & 0x80)
401 for(uint8 j = 0; j < MAX_LOOKING_FOR_GROUP_SLOT; ++j)
403 data << uint32(plr->m_lookingForGroup.slots[j].entry | (plr->m_lookingForGroup.slots[j].type << 24));
408 data.put<uint32>(count3_pos, number); // fill count placeholder
410 SendPacket(&data);*/
413 void WorldSession::HandleSetLfgOpcode( WorldPacket & recv_data )
415 sLog.outDebug("CMSG_SET_LOOKING_FOR_GROUP");
416 recv_data.hexlike();
417 uint32 slot, temp, entry, type;
418 uint8 roles, unk1;
420 recv_data >> slot >> temp >> roles >> unk1;
422 entry = ( temp & 0x00FFFFFF);
423 type = ( (temp >> 24) & 0x000000FF);
425 if(slot >= MAX_LOOKING_FOR_GROUP_SLOT)
426 return;
428 _player->m_lookingForGroup.slots[slot].Set(entry, type);
429 _player->m_lookingForGroup.roles = roles;
430 sLog.outDebug("LFG set: looknumber %u, temp %X, type %u, entry %u", slot, temp, type, entry);
432 if(LookingForGroup_auto_join)
433 AttemptJoin(_player);
435 //SendLfgResult(type, entry, 0);
436 SendLfgUpdate(0, 1, 0);
439 void WorldSession::HandleLfgSetRoles(WorldPacket &recv_data)
441 sLog.outDebug("CMSG_LFG_SET_ROLES");
443 uint8 roles;
444 recv_data >> roles;
446 _player->m_lookingForGroup.roles = roles;
449 void WorldSession::SendLfgUpdate(uint8 /*unk1*/, uint8 /*unk2*/, uint8 /*unk3*/)
451 // disabled
452 /*WorldPacket data(SMSG_LFG_UPDATE, 3);
453 data << uint8(unk1);
454 data << uint8(unk2);
455 data << uint8(unk3);
456 SendPacket(&data);*/