2 * Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
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
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
26 #include "ObjectMgr.h"
27 #include "WorldSession.h"
28 #include "Auth/BigNumber.h"
29 #include "Auth/Sha1.h"
30 #include "UpdateData.h"
33 #include "ScriptCalls.h"
34 #include <zlib/zlib.h>
35 #include "MapManager.h"
36 #include "ObjectAccessor.h"
38 #include "BattleGround.h"
39 #include "SpellAuras.h"
41 void WorldSession::HandleRepopRequestOpcode( WorldPacket
& recv_data
)
43 sLog
.outDebug( "WORLD: Recvd CMSG_REPOP_REQUEST Message" );
45 if(GetPlayer()->isAlive()||GetPlayer()->HasFlag(PLAYER_FLAGS
, PLAYER_FLAGS_GHOST
))
48 GetPlayer()->BuildPlayerRepop();
49 GetPlayer()->RepopAtGraveyard();
52 void WorldSession::HandleWhoOpcode( WorldPacket
& recv_data
)
54 uint32 clientcount
= 0;
57 sLog
.outDebug( "WORLD: Recvd CMSG_WHO Message" );
59 uint32 team
= _player
->GetTeam();
60 uint32 security
= GetSecurity();
61 bool allowTwoSideWhoList
= sWorld
.getConfig(CONFIG_ALLOW_TWO_SIDE_WHO_LIST
);
63 data
.Initialize( SMSG_WHO
);
64 data
<< uint32( 0 ); // clientcount place holder
65 data
<< uint32( 0 ); // clientcount place holder
67 ObjectAccessor::PlayersMapType
&m(ObjectAccessor::Instance().GetPlayers());
68 for(ObjectAccessor::PlayersMapType::iterator itr
= m
.begin(); itr
!= m
.end(); ++itr
)
70 // PLAYER see his team only and PLAYER can't see MODERATOR, GAME MASTER, ADMINISTRATOR characters
71 // MODERATOR, GAME MASTER, ADMINISTRATOR can see all
72 if ( itr
->second
->GetName() && ( security
> 0 || ( itr
->second
->GetTeam() == team
|| allowTwoSideWhoList
) && itr
->second
->GetSession()->GetSecurity() == 0 ) )
76 data
.append(itr
->second
->GetName() , strlen(itr
->second
->GetName()) + 1);
77 if(itr
->second
->GetGuildId()) // in fact just could use objmgr.GetGuildNameById(itr->second->GetGuildId()) cause getguildid() returns 0 with no guild and getguildnamebyid "" which equals uint8(0)
78 data
<< objmgr
.GetGuildNameById(itr
->second
->GetGuildId());
81 data
<< uint32( itr
->second
->getLevel() );
82 data
<< uint32( itr
->second
->getClass() );
83 data
<< uint32( itr
->second
->getRace() );
84 data
<< uint32( itr
->second
->GetZoneId() );
88 data
.put( 0, clientcount
); //insert right count
89 data
.put( sizeof(uint32
), clientcount
); //insert right count
92 sLog
.outDebug( "WORLD: Send SMSG_WHO Message" );
95 void WorldSession::HandleLogoutRequestOpcode( WorldPacket
& recv_data
)
98 Player
* Target
= GetPlayer();
100 uint32 security
= Target
->GetSession()->GetSecurity();
102 sLog
.outDebug( "WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", security
);
104 //instant logout for admins, gm's, mod's
112 //Can not logout if...
113 if( Target
->isInCombat() || //...is in combat
114 Target
->isInDuel() || //...is in Duel
115 //...is jumping ...is falling
116 Target
->HasMovementFlags( MOVEMENT_JUMPING
| MOVEMENT_FALLING
))
118 data
.Initialize( SMSG_LOGOUT_RESPONSE
);
127 //instant logout in taverns/cities
128 if(Target
->HasFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
))
135 // not set flags if flight - must continue move until exit, not saved anyway.
136 if(!GetPlayer()->isInFlight())
138 Target
->SetFlag(UNIT_FIELD_BYTES_1
,PLAYER_STATE_SIT
);
140 data
.Initialize( SMSG_FORCE_MOVE_ROOT
);
141 data
<< (uint8
)0xFF << Target
->GetGUID() << (uint32
)2;
143 Target
->SetFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_DISABLE_ROTATE
);
146 data
.Initialize( SMSG_LOGOUT_RESPONSE
);
150 LogoutRequest(time(NULL
));
154 void WorldSession::HandlePlayerLogoutOpcode( WorldPacket
& recv_data
)
156 sLog
.outDebug( "WORLD: Recvd CMSG_PLAYER_LOGOUT Message" );
159 void WorldSession::HandleLogoutCancelOpcode( WorldPacket
& recv_data
)
163 sLog
.outDebug( "WORLD: Recvd CMSG_LOGOUT_CANCEL Message" );
167 data
.Initialize( SMSG_LOGOUT_CANCEL_ACK
);
170 // not remove flags if flight - its not setted in Logout request code.
171 if(!GetPlayer()->isInFlight())
174 data
.Initialize( SMSG_FORCE_MOVE_UNROOT
);
175 data
<< (uint8
)0xFF << GetPlayer()->GetGUID();
179 //! Removes the flag so player stands
180 GetPlayer()->RemoveFlag(UNIT_FIELD_BYTES_1
,PLAYER_STATE_SIT
);
183 GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS
, UNIT_FLAG_DISABLE_ROTATE
);
186 sLog
.outDebug( "WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message" );
189 void WorldSession::SendGMTicketGetTicket(uint32 status
, char const* text
)
191 int len
= text
? strlen(text
) : 0;
193 data
.Initialize( SMSG_GMTICKET_GETTICKET
);
196 data
.append((uint8
*)text
,len
+1);
202 void WorldSession::HandleGMTicketGetTicketOpcode( WorldPacket
& recv_data
)
205 data
.Initialize( SMSG_QUERY_TIME_RESPONSE
);
206 // data << (uint32)20;
207 data
<< (uint32
)getMSTime();
212 guid
= GetPlayer()->GetGUID();
214 QueryResult
*result
= sDatabase
.PQuery("SELECT COUNT(`ticket_id`) FROM `character_ticket` WHERE `guid` = '%u'", GUID_LOPART(guid
));
219 fields
= result
->Fetch();
220 cnt
= fields
[0].GetUInt32();
225 QueryResult
*result2
= sDatabase
.PQuery("SELECT `ticket_text` FROM `character_ticket` WHERE `guid` = '%u'", GUID_LOPART(guid
));
227 Field
*fields2
= result2
->Fetch();
229 SendGMTicketGetTicket(6,fields2
[0].GetString());
233 SendGMTicketGetTicket(1,0);
237 void WorldSession::HandleGMTicketUpdateTextOpcode( WorldPacket
& recv_data
)
240 uint32 guid
= GetPlayer()->GetGUIDLow();
241 std::string ticketText
= "";
243 memcpy( buf
, recv_data
.contents(), sizeof buf
<recv_data
.size() ? sizeof buf
: recv_data
.size() );
245 ticketText
= (char *)buf
+ 1;
246 sDatabase
.escape_string(ticketText
);
247 sDatabase
.PExecute("UPDATE `character_ticket` SET `ticket_text` = '%s' WHERE `guid` = '%u'", ticketText
.c_str(), guid
);
251 void WorldSession::HandleGMTicketDeleteOpcode( WorldPacket
& recv_data
)
254 uint32 guid
= GetPlayer()->GetGUIDLow();
256 sDatabase
.PExecute("DELETE FROM `character_ticket` WHERE `guid` = '%u' LIMIT 1",guid
);
258 data
.Initialize( SMSG_GMTICKET_DELETETICKET
);
263 SendGMTicketGetTicket(1,0);
266 void WorldSession::HandleGMTicketCreateOpcode( WorldPacket
& recv_data
)
271 guid
= GetPlayer()->GetGUIDLow();
272 std::string ticketText
= "";
275 uint32 cat
[] = { 0,5,1,2,0,6,4,7,0,8,3 };
276 memcpy( buf
, recv_data
.contents(), sizeof buf
< recv_data
.size() ? sizeof buf
: recv_data
.size() );
279 ticketText
= (char *)buf
+ 17;
280 sDatabase
.escape_string(ticketText
);
282 QueryResult
*result
= sDatabase
.PQuery("SELECT COUNT(*) FROM `character_ticket` WHERE `guid` = '%u'",guid
);
287 fields
= result
->Fetch();
288 cnt
= fields
[0].GetUInt32();
293 data
.Initialize( SMSG_GMTICKET_CREATE
);
300 sDatabase
.PExecute("INSERT INTO `character_ticket` (`guid`,`ticket_text`,`ticket_category`) VALUES ('%u', '%s', '%u')", guid
, ticketText
.c_str(), cat
[buf
[0]]);
302 data
.Initialize( SMSG_QUERY_TIME_RESPONSE
);
303 //data << (uint32)20;
304 data
<< (uint32
)getMSTime();
307 data
.Initialize( SMSG_GMTICKET_CREATE
);
310 DEBUG_LOG("update the ticket\n");
312 ObjectAccessor::PlayersMapType
&m
= ObjectAccessor::Instance().GetPlayers();
313 for(ObjectAccessor::PlayersMapType::iterator itr
= m
.begin(); itr
!= m
.end(); ++itr
)
315 if(itr
->second
->GetSession()->GetSecurity() >= 2 && itr
->second
->isAcceptTickets())
316 ChatHandler::PSendSysMessage(itr
->second
->GetSession(),"New ticket from %s",GetPlayer()->GetName());
322 void WorldSession::HandleGMTicketSystemStatusOpcode( WorldPacket
& recv_data
)
326 data
.Initialize( SMSG_GMTICKET_SYSTEMSTATUS
);
332 void WorldSession::HandleEnablePvP(WorldPacket
& recvPacket
)
335 if ( (!GetPlayer()->isAlive()) || GetPlayer()->isInCombat() || GetPlayer()->isInDuel() )
338 data
.Initialize(SMSG_CAST_RESULT
);
346 if( !GetPlayer()->GetPvP() || GetPlayer()->m_pvp_counting
)
348 //sChatHandler.SendSysMessage(GetPlayer()->GetSession(), "You are now flagged PvP combat and will remain so until toggled off.");
349 GetPlayer()->SetFlag(PLAYER_FLAGS
, PLAYER_FLAGS_IN_PVP
);
350 GetPlayer()->SetPvP (true);
354 //sChatHandler.SendSysMessage(GetPlayer()->GetSession(), "You will be unflagged for PvP combat after five minutes of non-PvP action in friendly territory.");
356 GetPlayer()->RemoveFlag(PLAYER_FLAGS
, PLAYER_FLAGS_IN_PVP
);
357 GetPlayer()->SetPVPCount(time(NULL
));
361 void WorldSession::HandleZoneUpdateOpcode( WorldPacket
& recv_data
)
364 WPAssert(GetPlayer());
366 // if player is resting stop resting
367 if(GetPlayer()->HasFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
))
369 if(GetPlayer()->GetRestType()==2) //rest in city
371 //speed collect rest bonus (section/in hour)
372 float bubble
=1; //0% Blizzlike
373 GetPlayer()->SetRestBonus( GetPlayer()->GetRestBonus()+ (time(NULL
)-GetPlayer()->GetTimeInnEter())*0.0142108*bubble
);
374 if(GetPlayer()->GetRestBonus()>1534)GetPlayer()->SetRestBonus(1534);
375 GetPlayer()->RemoveFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
);
379 recv_data
>> newZone
;
380 sLog
.outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone
);
382 AreaTableEntry
* area
= GetAreaEntryByAreaID(newZone
);
384 if(area
&& area
->zone_type
== 312) // city
386 GetPlayer()->SetFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
);
387 GetPlayer()->SetRestType(2);
388 GetPlayer()->InnEnter(time(NULL
),0,0,0);
392 void WorldSession::HandleSetTargetOpcode( WorldPacket
& recv_data
)
399 _player
->SetTarget(guid
);
403 void WorldSession::HandleSetSelectionOpcode( WorldPacket
& recv_data
)
409 _player
->SetSelection(guid
);
411 if(_player
->GetUInt64Value(PLAYER_FIELD_COMBO_TARGET
) != guid
)
413 _player
->SetUInt64Value(PLAYER_FIELD_COMBO_TARGET
,0);
414 _player
->SetUInt32Value(PLAYER_FIELD_BYTES
,((_player
->GetUInt32Value(PLAYER_FIELD_BYTES
) & ~(0xFF << 8)) | (0x00 << 8)));
418 void WorldSession::HandleStandStateChangeOpcode( WorldPacket
& recv_data
)
420 sLog
.outDebug( "WORLD: Received CMSG_STAND_STATE_CHANGE" );
421 if( GetPlayer() != 0 )
424 recv_data
>> animstate
;
427 data
.Initialize(SMSG_STANDSTATE_CHANGE_ACK
);
431 uint32 bytes1
= _player
->GetUInt32Value( UNIT_FIELD_BYTES_1
);
434 _player
->SetUInt32Value(UNIT_FIELD_BYTES_1
, bytes1
);
436 if (animstate
!= PLAYER_STATE_SIT_CHAIR
&& animstate
!= PLAYER_STATE_SIT_LOW_CHAIR
&& animstate
!= PLAYER_STATE_SIT_MEDIUM_CHAIR
&&
437 animstate
!= PLAYER_STATE_SIT_HIGH_CHAIR
&& animstate
!= PLAYER_STATE_SIT
&& animstate
!= PLAYER_STATE_SLEEP
&&
438 animstate
!= PLAYER_STATE_KNEEL
)
440 // cancel drinking / eating
441 Unit::AuraMap
& p_auras
= _player
->GetAuras();
442 for (Unit::AuraMap::iterator itr
= p_auras
.begin(); itr
!= p_auras
.end();)
444 if (itr
->second
&& (itr
->second
->GetSpellProto()->AuraInterruptFlags
& (1<<18)) != 0)
445 _player
->RemoveAura(itr
);
453 void WorldSession::HandleFriendListOpcode( WorldPacket
& recv_data
)
455 sLog
.outDebug( "WORLD: Received CMSG_FRIEND_LIST" );
457 GetPlayer()->SendFriendlist();
459 GetPlayer()->SendIgnorelist();
462 void WorldSession::HandleAddFriendOpcode( WorldPacket
& recv_data
)
464 sLog
.outDebug( "WORLD: Received CMSG_ADD_FRIEND" );
466 std::string friendName
= "UNKNOWN";
467 unsigned char friendResult
= FRIEND_NOT_FOUND
;
468 Player
*pfriend
=NULL
;
469 uint64 friendGuid
= 0;
470 uint32 friendArea
= 0, friendLevel
= 0, friendClass
= 0;
473 recv_data
>> friendName
;
475 normalizePlayerName(friendName
);
476 sDatabase
.escape_string(friendName
); // prevent SQL injection - normal name don't must changed by this call
478 sLog
.outDetail( "WORLD: %s asked to add friend : '%s'",
479 GetPlayer()->GetName(), friendName
.c_str() );
481 friendGuid
= objmgr
.GetPlayerGUIDByName(friendName
.c_str());
485 pfriend
= ObjectAccessor::Instance().FindPlayer(friendGuid
);
486 if(pfriend
==GetPlayer())
487 friendResult
= FRIEND_SELF
;
488 else if(GetPlayer()->GetTeam()!=objmgr
.GetPlayerTeamByGUID(friendGuid
))
489 friendResult
= FRIEND_ENEMY
;
492 QueryResult
*result
= sDatabase
.PQuery("SELECT `guid` FROM `character_social` WHERE `guid` = '%u' AND `flags` = 'FRIEND' AND `friend` = '%u'", GetPlayer()->GetGUIDLow(), GUID_LOPART(friendGuid
));
495 friendResult
= FRIEND_ALREADY
;
502 data
.Initialize( SMSG_FRIEND_STATUS
);
504 if (friendGuid
&& friendResult
==FRIEND_NOT_FOUND
)
506 if( pfriend
&& pfriend
->IsInWorld() && pfriend
->isGMVisibleFor(GetPlayer()))
508 friendResult
= FRIEND_ADDED_ONLINE
;
509 friendArea
= pfriend
->GetZoneId();
510 friendLevel
= pfriend
->getLevel();
511 friendClass
= pfriend
->getClass();
515 friendResult
= FRIEND_ADDED_OFFLINE
;
517 sDatabase
.PExecute("INSERT INTO `character_social` (`guid`,`name`,`friend`,`flags`) VALUES ('%u', '%s', '%u', 'FRIEND')",
518 GetPlayer()->GetGUIDLow(), friendName
.c_str(), GUID_LOPART(friendGuid
));
520 sLog
.outDetail( "WORLD: %s Guid found '%u' area:%u Level:%u Class:%u. ",
521 friendName
.c_str(), GUID_LOPART(friendGuid
), friendArea
, friendLevel
, friendClass
);
524 else if(friendResult
==FRIEND_ALREADY
)
526 sLog
.outDetail( "WORLD: %s Guid Already a Friend. ", friendName
.c_str() );
528 else if(friendResult
==FRIEND_SELF
)
530 sLog
.outDetail( "WORLD: %s Guid can't add himself. ", friendName
.c_str() );
534 sLog
.outDetail( "WORLD: %s Guid not found. ", friendName
.c_str() );
537 data
<< (uint8
)friendResult
<< (uint64
)friendGuid
<< (uint8
)0;
538 if(friendResult
== FRIEND_ADDED_ONLINE
)
539 data
<< (uint32
)friendArea
<< (uint32
)friendLevel
<< (uint32
)friendClass
;
543 sLog
.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" );
546 void WorldSession::HandleDelFriendOpcode( WorldPacket
& recv_data
)
551 sLog
.outDebug( "WORLD: Received CMSG_DEL_FRIEND" );
552 recv_data
>> FriendGUID
;
554 uint8 FriendResult
= FRIEND_REMOVED
;
556 data
.Initialize( SMSG_FRIEND_STATUS
);
558 data
<< (uint8
)FriendResult
<< (uint64
)FriendGUID
;
560 uint32 guidlow
= GetPlayer()->GetGUIDLow();
562 sDatabase
.PExecute("DELETE FROM `character_social` WHERE `flags` = 'FRIEND' AND `guid` = '%u' AND `friend` = '%u'",guidlow
, GUID_LOPART(FriendGUID
));
566 sLog
.outDebug( "WORLD: Sent motd (SMSG_FRIEND_STATUS)" );
569 void WorldSession::HandleAddIgnoreOpcode( WorldPacket
& recv_data
)
571 sLog
.outDebug( "WORLD: Received CMSG_ADD_IGNORE" );
573 std::string IgnoreName
= "UNKNOWN";
574 unsigned char ignoreResult
= FRIEND_IGNORE_NOT_FOUND
;
575 uint64 IgnoreGuid
= 0;
579 recv_data
>> IgnoreName
;
581 normalizePlayerName(IgnoreName
);
582 sDatabase
.escape_string(IgnoreName
); // prevent SQL injection - normal name don't must changed by this call
584 sLog
.outDetail( "WORLD: %s asked to Ignore: '%s'",
585 GetPlayer()->GetName(), IgnoreName
.c_str() );
587 IgnoreGuid
= objmgr
.GetPlayerGUIDByName(IgnoreName
.c_str());
591 if(IgnoreGuid
==GetPlayer()->GetGUID())
592 ignoreResult
= FRIEND_IGNORE_SELF
;
595 QueryResult
*result
= sDatabase
.PQuery("SELECT `guid`,`name`,`friend`,`flags` FROM `character_social` WHERE `guid` = '%u' AND `flags` = 'IGNORE' AND `friend` = '%u'", GetPlayer()->GetGUIDLow(), GUID_LOPART(IgnoreGuid
));
598 ignoreResult
= FRIEND_IGNORE_ALREADY
;
604 data
.Initialize( SMSG_FRIEND_STATUS
);
606 if (IgnoreGuid
&& ignoreResult
== FRIEND_IGNORE_NOT_FOUND
)
608 ignoreResult
= FRIEND_IGNORE_ADDED
;
610 sDatabase
.PExecute("INSERT INTO `character_social` (`guid`,`name`,`friend`,`flags`) VALUES ('%u', '%s', '%u', 'IGNORE')",
611 GetPlayer()->GetGUIDLow(), IgnoreName
.c_str(), GUID_LOPART(IgnoreGuid
));
613 else if(ignoreResult
==FRIEND_IGNORE_ALREADY
)
615 sLog
.outDetail( "WORLD: %s Guid Already Ignored. ", IgnoreName
.c_str() );
617 else if(ignoreResult
==FRIEND_IGNORE_SELF
)
619 sLog
.outDetail( "WORLD: %s Guid can't add himself. ", IgnoreName
.c_str() );
623 sLog
.outDetail( "WORLD: %s Guid not found. ", IgnoreName
.c_str() );
626 data
<< (uint8
)ignoreResult
<< (uint64
)IgnoreGuid
;
629 sLog
.outDebug( "WORLD: Sent (SMSG_FRIEND_STATUS)" );
632 void WorldSession::HandleDelIgnoreOpcode( WorldPacket
& recv_data
)
637 sLog
.outDebug( "WORLD: Received CMSG_DEL_IGNORE" );
638 recv_data
>> IgnoreGUID
;
640 unsigned char IgnoreResult
= FRIEND_IGNORE_REMOVED
;
642 data
.Initialize( SMSG_FRIEND_STATUS
);
644 data
<< (uint8
)IgnoreResult
<< (uint64
)IgnoreGUID
;
646 uint32 guidlow
= GetPlayer()->GetGUIDLow();
648 sDatabase
.PExecute("DELETE FROM `character_social` WHERE `flags` = 'IGNORE' AND `guid` = '%u' AND `friend` = '%u'",guidlow
, GUID_LOPART(IgnoreGUID
));
652 sLog
.outDebug( "WORLD: Sent motd (SMSG_FRIEND_STATUS)" );
656 void WorldSession::HandleBugOpcode( WorldPacket
& recv_data
)
658 uint32 suggestion
, contentlen
;
663 recv_data
>> suggestion
>> contentlen
>> content
>> typelen
>> type
;
665 if( suggestion
== 0 )
666 sLog
.outDebug( "WORLD: Received CMSG_BUG [Bug Report]" );
668 sLog
.outDebug( "WORLD: Received CMSG_BUG [Suggestion]" );
670 sLog
.outDebug( type
.c_str( ) );
671 sLog
.outDebug( content
.c_str( ) );
673 sDatabase
.escape_string(type
);
674 sDatabase
.escape_string(content
);
675 sDatabase
.PExecute ("INSERT INTO `bugreport` (`type`,`content`) VALUES('%s', '%s')", type
.c_str( ), content
.c_str( ));
679 void WorldSession::HandleCorpseReclaimOpcode(WorldPacket
&recv_data
)
681 sLog
.outDetail("WORLD: Received CMSG_RECLAIM_CORPSE");
682 if (GetPlayer()->isAlive())
685 // body not released yet
686 if(!GetPlayer()->HasFlag(PLAYER_FLAGS
, PLAYER_FLAGS_GHOST
))
689 Corpse
* corpse
= GetPlayer()->GetCorpse();
694 // prevent resurrect before 30-sec delay after body release not finished
695 if(corpse
->GetGhostTime() + CORPSE_RECLAIM_DELAY
> time(NULL
))
698 float dist
= corpse
->GetDistance2dSq(GetPlayer());
699 sLog
.outDebug("Corpse 2D Distance: \t%f",dist
);
700 if (dist
> CORPSE_RECLAIM_RADIUS
*CORPSE_RECLAIM_RADIUS
)
707 GetPlayer()->ResurrectPlayer();
710 GetPlayer()->SpawnCorpseBones();
713 GetPlayer()->ApplyStats(false);
714 GetPlayer()->SetHealth(GetPlayer()->GetMaxHealth()/2);
715 GetPlayer()->SetPower(POWER_MANA
,GetPlayer()->GetMaxPower(POWER_MANA
)/2);
716 GetPlayer()->ApplyStats(true);
718 // update world right away
719 MapManager::Instance().GetMap(GetPlayer()->GetMapId())->Add(GetPlayer());
722 void WorldSession::HandleResurrectResponseOpcode(WorldPacket
& recv_data
)
724 sLog
.outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE");
726 if(GetPlayer()->isAlive())
738 if(GetPlayer()->m_resurrectGUID
== 0)
741 GetPlayer()->ResurrectPlayer();
743 if(GetPlayer()->GetMaxHealth() > GetPlayer()->m_resurrectHealth
)
744 GetPlayer()->SetHealth( GetPlayer()->m_resurrectHealth
);
746 GetPlayer()->SetHealth( GetPlayer()->GetMaxHealth() );
748 if(GetPlayer()->GetMaxPower(POWER_MANA
) > GetPlayer()->m_resurrectMana
)
749 GetPlayer()->SetPower(POWER_MANA
, GetPlayer()->m_resurrectMana
);
751 GetPlayer()->SetPower(POWER_MANA
, GetPlayer()->GetMaxPower(POWER_MANA
) );
753 GetPlayer()->SetPower(POWER_RAGE
, 0 );
755 GetPlayer()->SetPower(POWER_ENERGY
, GetPlayer()->GetMaxPower(POWER_ENERGY
) );
757 GetPlayer()->SpawnCorpseBones();
759 GetPlayer()->BuildTeleportAckMsg(&data
, GetPlayer()->m_resurrectX
, GetPlayer()->m_resurrectY
, GetPlayer()->m_resurrectZ
, GetPlayer()->GetOrientation());
760 GetPlayer()->GetSession()->SendPacket(&data
);
762 GetPlayer()->SetPosition(GetPlayer()->m_resurrectX
,GetPlayer()->m_resurrectY
,GetPlayer()->m_resurrectZ
,GetPlayer()->GetOrientation());
764 GetPlayer()->m_resurrectGUID
= 0;
765 GetPlayer()->m_resurrectHealth
= GetPlayer()->m_resurrectMana
= 0;
766 GetPlayer()->m_resurrectX
= GetPlayer()->m_resurrectY
= GetPlayer()->m_resurrectZ
= 0;
769 void WorldSession::HandleAreaTriggerOpcode(WorldPacket
& recv_data
)
771 sLog
.outDebug("WORLD: Received CMSG_AREATRIGGER");
776 recv_data
>> Trigger_ID
;
777 sLog
.outDebug("Trigger ID:%u",Trigger_ID
);
779 if(GetPlayer()->isInFlight())
781 sLog
.outDebug("Player '%s' in flight, ignore Area Trigger ID:%u",GetPlayer()->GetName(),Trigger_ID
);
785 AreaTriggerPoint
*pArea
= objmgr
.GetAreaTriggerQuestPoint( Trigger_ID
);
788 uint32 quest_id
= pArea
->Quest_ID
;
789 Quest
* pQuest
= GetPlayer()->GetActiveQuest(quest_id
);
792 if( !Script
->scriptAreaTrigger( GetPlayer(), pQuest
, Trigger_ID
) )
794 if(GetPlayer()->GetQuestStatus(quest_id
) == QUEST_STATUS_INCOMPLETE
)
795 GetPlayer()->AreaExplored( quest_id
);
800 QueryResult
*result
= sDatabase
.PQuery("SELECT `name` FROM `areatrigger_tavern` WHERE `id` = '%u'", Trigger_ID
);
803 GetPlayer()->SetFlag(PLAYER_FLAGS
, PLAYER_FLAGS_RESTING
);
804 result
= sDatabase
.PQuery("SELECT `trigger_map`,`trigger_position_x`,`trigger_position_y`,`trigger_position_z` FROM `areatrigger_template` WHERE `id` = '%u'", Trigger_ID
);
807 Field
*fields
= result
->Fetch();
808 GetPlayer()->InnEnter(time(NULL
),fields
[1].GetFloat(),fields
[2].GetFloat(),fields
[3].GetFloat());
809 GetPlayer()->SetRestType(1);
813 else if(AreaTrigger
* at
= objmgr
.GetAreaTrigger(Trigger_ID
))
815 if(at
->mapId
== GetPlayer()->GetMapId() && !GetPlayer()->m_bgInBattleGround
)
817 WorldPacket movedata
;
818 _player
->BuildTeleportAckMsg(&movedata
, at
->X
, at
->Y
, at
->Z
, at
->Orientation
);
819 _player
->SendMessageToSet(&movedata
,true);
820 //_player->SetPosition( at->X, at->Y, at->Z, _player->GetOrientation());
821 //_player->BuildHeartBeatMsg(&data);
822 //_player->SendMessageToSet(&data, true);
824 else if (GetPlayer()->m_bgInBattleGround
) //if player is playing in a BattleGround
826 //! AreaTrigger BattleGround
828 //Get current BattleGround the player is in
829 BattleGround
* TempBattlegrounds
= sBattleGroundMgr
.GetBattleGround(GetPlayer()->GetBattleGroundId());
830 //Run the areatrigger code
831 if(TempBattlegrounds
)
832 TempBattlegrounds
->HandleAreaTrigger(GetPlayer(),Trigger_ID
);
836 GetPlayer()->TeleportTo(at
->mapId
,at
->X
,at
->Y
,at
->Z
,at
->Orientation
);
841 // set resting flag we are in the inn
844 void WorldSession::HandleUpdateAccountData(WorldPacket
&recv_data
)
848 void WorldSession::HandleRequestAccountData(WorldPacket
& recv_data
)
850 sLog
.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA");
853 void WorldSession::HandleSetActionButtonOpcode(WorldPacket
& recv_data
)
855 sLog
.outDetail( "WORLD: Received CMSG_SET_ACTION_BUTTON" );
856 uint8 button
, misc
, type
;
858 recv_data
>> button
>> action
>> misc
>> type
;
859 sLog
.outDetail( "BUTTON: %u ACTION: %u TYPE: %u MISC: %u", button
, action
, type
, misc
);
862 sLog
.outDetail( "MISC: Remove action from button %u", button
);
864 GetPlayer()->removeAction(button
);
868 if(type
==ACTION_BUTTON_MACRO
)
870 sLog
.outDetail( "MISC: Added Macro %u into button %u", action
, button
);
871 GetPlayer()->addAction(button
,action
,type
,misc
);
873 else if(type
==ACTION_BUTTON_SPELL
)
875 sLog
.outDetail( "MISC: Added Action %u into button %u", action
, button
);
876 GetPlayer()->addAction(button
,action
,type
,misc
);
878 else if(type
==ACTION_BUTTON_ITEM
)
880 sLog
.outDetail( "MISC: Added Item %u into button %u", action
, button
);
881 GetPlayer()->addAction(button
,action
,type
,misc
);
884 sLog
.outError( "MISC: Unknown action button type %u for action %u into button %u", type
, action
, button
);
888 void WorldSession::HandleCompleteCinema( WorldPacket
& recv_data
)
890 DEBUG_LOG( "WORLD: Player is watching cinema" );
893 void WorldSession::HandleNextCinematicCamera( WorldPacket
& recv_data
)
895 DEBUG_LOG( "WORLD: Which movie to play" );
898 void WorldSession::HandleRequestRaidInfoOpcode( WorldPacket
& recv_data
)
900 sLog
.outDebug("Received opcode CMSG_REQUEST_RAID_INFO");
902 data
.Initialize(SMSG_RAID_INSTANCE_INFO
);
904 _player
->GetSession()->SendPacket(&data
);
907 void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket
& recv_data
)
910 DEBUG_LOG( "WORLD: Battleground status - not yet" );
913 void WorldSession::HandleMoveTimeSkippedOpcode( WorldPacket
& recv_data
)
916 WorldSession::Update( getMSTime() );
917 DEBUG_LOG( "WORLD: Time Lag/Synchronization Resent/Update" );
921 void WorldSession::HandleMoveUnRootAck(WorldPacket
& recv_data
)
924 sLog
.outDebug( "WORLD: CMSG_FORCE_MOVE_UNROOT_ACK" );
935 recv_data
>> unknown1
;
936 recv_data
>> unknown2
;
937 recv_data
>> PositionX
;
938 recv_data
>> PositionY
;
939 recv_data
>> PositionZ
;
940 recv_data
>> Orientation
;
942 // TODO for later may be we can use for anticheat
943 // DEBUG_LOG("Guid " I64FMTD,guid);
944 // DEBUG_LOG("unknown1 " I64FMTD,unknown1);
945 // DEBUG_LOG("unknown2 %u",unknown2);
946 // DEBUG_LOG("X %f",PositionX);
947 // DEBUG_LOG("Y %f",PositionY);
948 // DEBUG_LOG("Z %f",PositionZ);
949 // DEBUG_LOG("O %f",Orientation);
952 void WorldSession::HandleLookingForGroup(WorldPacket
& recv_data
)
954 // TODO send groups need data
955 sLog
.outDebug( "WORLD: MSG_LOOKING_FOR_GROUP" );
958 void WorldSession::HandleMoveRootAck(WorldPacket
& recv_data
)
961 sLog
.outDebug( "WORLD: CMSG_FORCE_MOVE_ROOT_ACK" );
972 recv_data
>> unknown1
;
973 recv_data
>> unknown2
;
974 recv_data
>> PositionX
;
975 recv_data
>> PositionY
;
976 recv_data
>> PositionZ
;
977 recv_data
>> Orientation
;
979 // for later may be we can use for anticheat
980 // DEBUG_LOG("Guid " I64FMTD,guid);
981 // DEBUG_LOG("unknown1 " I64FMTD,unknown1);
982 // DEBUG_LOG("unknown1 %u",unknown2);
983 // DEBUG_LOG("X %f",PositionX);
984 // DEBUG_LOG("Y %f",PositionY);
985 // DEBUG_LOG("Z %f",PositionZ);
986 // DEBUG_LOG("O %f",Orientation);
989 void WorldSession::HandleMoveTeleportAck(WorldPacket
& recv_data
)
997 recv_data
>> value1
; // ms time ?
998 DEBUG_LOG("Guid " I64FMTD
,guid
);
999 DEBUG_LOG("Value 1 %u",value1
);
1002 void WorldSession::HandleForceRunSpeedChangeAck(WorldPacket
& recv_data
)
1004 //check for speed stuff
1005 recv_data
.hexlike();
1007 uint32 Flags
,unk1
, unk0
;
1013 recv_data
>> unk0
>> Flags
;
1014 if ( (Flags
& 0x2000) || (Flags
& 0x6000) ) //0x2000 == jumping 0x6000 == Falling
1016 uint32 unk2
, unk3
, unk4
, unk5
;
1019 recv_data
>> d_time
;
1020 recv_data
>> X
>> Y
>> Z
>> O
;
1021 recv_data
>> unk2
>> unk3
; //no idea, maybe unk2 = flags2
1022 recv_data
>> unk4
>> unk5
; //no idea
1023 recv_data
>> OldSpeed
>> NewSpeed
;
1027 recv_data
>> d_time
;
1028 recv_data
>> X
>> Y
>> Z
>> O
;
1029 recv_data
>> unk1
>> NewSpeed
;
1031 if (GetPlayer()->GetSpeed(MOVE_RUN
) != NewSpeed
)
1032 //now kick player???
1033 sLog
.outError("SpeedChange player is NOT correct, its set to: %f", NewSpeed
);
1036 void WorldSession::HandleForceSwimSpeedChangeAck(WorldPacket
& recv_data
)
1038 // set swim speed ? received data is more
1039 sLog
.outDebug("CMSG_FORCE_SWIM_SPEED_CHANGE_ACK");
1043 void WorldSession::HandleSetActionBar(WorldPacket
& recv_data
)
1048 recv_data
>> ActionBar
;
1050 temp
= ((GetPlayer()->GetUInt32Value( PLAYER_FIELD_BYTES
)) & 0xFFF0FFFF) + (ActionBar
<< 16);
1051 GetPlayer()->SetUInt32Value( PLAYER_FIELD_BYTES
, temp
);
1054 void WorldSession::HandleMoveWaterWalkAck(WorldPacket
& recv_data
)
1057 // we receive guid,x,y,z
1060 void WorldSession::HandleChangePlayerNameOpcode(WorldPacket
& recv_data
)
1063 // need to be written
1066 void WorldSession::HandleWardenDataOpcode(WorldPacket
& recv_data
)
1070 sLog
.outDebug("Received opcode CMSG_WARDEN_DATA, not resolve.uint8 = %u",tmp
);
1073 void WorldSession::HandlePlayedTime(WorldPacket
& recv_data
)
1076 uint32 TotalTimePlayed
= GetPlayer()->GetTotalPlayedTime();
1077 uint32 LevelPlayedTime
= GetPlayer()->GetLevelPlayedTime();
1079 data
.Initialize(SMSG_PLAYED_TIME
);
1080 data
<< TotalTimePlayed
;
1081 data
<< LevelPlayedTime
;
1085 void WorldSession::HandleInspectOpcode(WorldPacket
& recv_data
)
1091 DEBUG_LOG("Inspected guid is " I64FMTD
,guid
);
1095 _player
->SetSelection(guid
);
1098 if(_player
->GetUInt64Value(PLAYER_FIELD_COMBO_TARGET
) != guid
)
1100 _player
->SetUInt64Value(PLAYER_FIELD_COMBO_TARGET
,0);
1101 _player
->SetUInt32Value(PLAYER_FIELD_BYTES
,((_player
->GetUInt32Value(PLAYER_FIELD_BYTES
) & ~(0xFF << 8)) | (0x00 << 8)));
1104 data
.Initialize( SMSG_INSPECT
);
1110 void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket
& recv_data
)
1116 DEBUG_LOG("Party Stats guid is " I64FMTD
,guid
);
1118 pl
= objmgr
.GetPlayer(guid
);
1121 data
.Initialize( MSG_INSPECT_HONOR_STATS
);
1122 data
<< guid
; // player guid
1123 // Rank, filling bar, PLAYER_BYTES_3, ??
1124 data
<< (uint8
)pl
->GetUInt32Value(PLAYER_FIELD_HONOR_BAR
);
1125 // Today Honorable and Dishonorable Kills
1126 data
<< pl
->GetUInt32Value(PLAYER_FIELD_SESSION_KILLS
);
1127 // Yesterday Honorable Kills
1128 data
<< pl
->GetUInt32Value(PLAYER_FIELD_YESTERDAY_KILLS
);
1129 // Last Week Honorable Kills
1130 data
<< pl
->GetUInt32Value(PLAYER_FIELD_LAST_WEEK_KILLS
);
1131 // This Week Honorable kills
1132 data
<< pl
->GetUInt32Value(PLAYER_FIELD_THIS_WEEK_KILLS
);
1133 // Lifetime Honorable Kills
1134 data
<< pl
->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS
);
1135 // Lifetime Dishonorable Kills
1136 data
<< pl
->GetUInt32Value(PLAYER_FIELD_LIFETIME_DISHONORABLE_KILLS
);
1138 data
<< pl
->GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION
);
1140 data
<< pl
->GetUInt32Value(PLAYER_FIELD_LAST_WEEK_CONTRIBUTION
);
1142 data
<< pl
->GetUInt32Value(PLAYER_FIELD_THIS_WEEK_CONTRIBUTION
);
1143 // Last Week Standing
1144 data
<< pl
->GetUInt32Value(PLAYER_FIELD_LAST_WEEK_RANK
);
1145 data
<< (uint8
)pl
->GetHonorHighestRank(); // Highest Rank, ??
1149 sLog
.outDebug("Player %u not found!", guid
);
1152 void WorldSession::HandleWorldTeleportOpcode(WorldPacket
& recv_data
)
1154 // write in client console: worldport 469 452 6454 2536 180 or /console worldport 469 452 6454 2536 180
1155 // Received opcode CMSG_WORLD_TELEPORT
1156 // Time is ***, map=469, x=452.000000, y=6454.000000, z=2536.000000, orient=3.141593
1158 sLog
.outDebug("Received opcode CMSG_WORLD_TELEPORT");
1160 if(GetPlayer()->isInFlight())
1162 sLog
.outDebug("Player '%s' in flight, ignore worldport command.",GetPlayer()->GetName());
1174 recv_data
>> time
; // time in m.sec.
1176 recv_data
>> PositionX
;
1177 recv_data
>> PositionY
;
1178 recv_data
>> PositionZ
;
1179 recv_data
>> Orientation
; // o (3.141593 = 180 degrees)
1180 DEBUG_LOG("Time %u sec, map=%u, x=%f, y=%f, z=%f, orient=%f", time
/1000, mapid
, PositionX
, PositionY
, PositionZ
, Orientation
);
1182 if (GetSecurity() >= 3)
1183 GetPlayer()->TeleportTo(mapid
,PositionX
,PositionY
,PositionZ
,Orientation
);
1185 SendNotification("You do not have permission to perform that function");
1186 sLog
.outDebug("Received worldport command from player %s", GetPlayer()->GetName());
1189 void WorldSession::SendNotification(char* msg
)
1194 data
.Initialize(SMSG_NOTIFICATION
);