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"
22 #include "WorldSession.h"
26 #include "ObjectMgr.h"
28 #include "UpdateMask.h"
31 #include "MapManager.h"
32 #include "ObjectAccessor.h"
34 void WorldSession::HandleCharEnumOpcode( WorldPacket
& recv_data
)
40 packet.Initialize(SMSG_AUTH_RESPONSE2_UNKNOWN180);
42 for (int i=0; i<10; i++)
43 packet << uint8(0x02) << uint8(0x01) << uint16(0) << uint32(0);
44 SendPacket(&packet);*/
46 data
.Initialize(SMSG_CHAR_ENUM
);
48 QueryResult
*result
= sDatabase
.PQuery("SELECT `guid` FROM `character` WHERE `account` = '%lu';", (unsigned long)GetAccountId());
59 plr
= new Player(this);
62 sLog
.outError("Loading char guid %d from account %d.",(*result
)[0].GetUInt32(),GetAccountId());
64 plr
->LoadFromDB( (*result
)[0].GetUInt32() );
66 plr
->BuildEnumData( &data
);
72 while( result
->NextRow() );
77 data
.put
<uint8
>(0, num
);
82 void WorldSession::HandleCharCreateOpcode( WorldPacket
& recv_data
)
90 QueryResult
*result
= sDatabase
.PQuery("SELECT `guid` FROM `character` WHERE `name` = '%s';", name
.c_str());
96 data
.Initialize(SMSG_CHAR_CREATE
);
103 result
= sDatabase
.PQuery("SELECT `guid` FROM `character` WHERE `account` = '%lu';", (unsigned long)GetAccountId());
107 if (result
->GetRowCount() >= 10)
109 data
.Initialize(SMSG_CHAR_CREATE
);
118 Player
* pNewChar
= new Player(this);
120 if(pNewChar
->Create( objmgr
.GenerateLowGuid(HIGHGUID_PLAYER
), recv_data
))
123 pNewChar
->SaveToDB();
129 // Player not create (race/class problem?)
132 data
.Initialize(SMSG_CHAR_CREATE
);
139 // we have successfull creation
140 // note all error codes moved + 1
141 // 0x2E - Character created
142 // 0x30 - Char create failed
143 // 0x31 - Char name is in use
144 // 0x35 - Char delete Okay
145 // 0x36 - Char delete failed
147 data
.Initialize( SMSG_CHAR_CREATE
);
153 void WorldSession::HandleCharDeleteOpcode( WorldPacket
& recv_data
)
160 Player
* plr
= new Player(this);
163 plr
->LoadFromDB( GUID_LOPART(guid
) );
168 data
.Initialize(SMSG_CHAR_CREATE
);
173 void WorldSession::HandlePlayerLoginOpcode( WorldPacket
& recv_data
)
176 uint64 playerGuid
= 0;
178 DEBUG_LOG( "WORLD: Recvd Player Logon Message" );
180 recv_data
>> playerGuid
;
182 Player
* plr
= new Player(this);
185 plr
->SetSession(this);
186 plr
->LoadFromDB(GUID_LOPART(playerGuid
));
187 plr
->_RemoveAllItemMods();
191 data
.Initialize( SMSG_ACCOUNT_DATA_MD5
);
193 for(int i
= 0; i
< 80; i
++)
198 sChatHandler
.FillSystemMessageData(&data
, this, sWorld
.GetMotd());
201 DEBUG_LOG( "WORLD: Sent motd (SMSG_MESSAGECHAT)" );
205 QueryResult
*result7
= sDatabase
.PQuery("SELECT COUNT(*) FROM `character_homebind` WHERE `guid` = '%d';", playerGuid
);
209 fields
= result7
->Fetch();
210 cnt
= fields
[0].GetUInt32();
214 QueryResult
*result4
= sDatabase
.PQuery("SELECT `map`,`zone`,`position_x`,`position_y`,`position_z` FROM `character_homebind` WHERE `guid` = '%d';", playerGuid
);
215 fields
= result4
->Fetch();
216 data
.Initialize (SMSG_BINDPOINTUPDATE
);
217 data
<< fields
[2].GetFloat() << fields
[3].GetFloat() << fields
[4].GetFloat();
218 data
<< fields
[0].GetUInt32();
219 data
<< fields
[1].GetUInt32();
221 DEBUG_LOG("Setting player home position: mapid is: %d, zoneid is %d, X is %f, Y is %f, Z is %f\n",fields
[0].GetUInt32(),fields
[1].GetUInt32(),fields
[2].GetFloat(), fields
[3].GetFloat(), fields
[4].GetFloat());
226 int plrace
= GetPlayer()->getRace();
227 int plclass
= GetPlayer()->getClass();
228 QueryResult
*result5
= sDatabase
.PQuery("SELECT `map`,`zone`,`position_x`,`position_y`,`position_z` FROM `playercreateinfo` WHERE `race` = '%u' AND `class` = '%u';", plrace
, plclass
);
229 fields
= result5
->Fetch();
230 // store and send homebind for player
231 sDatabase
.PExecute("INSERT INTO `character_homebind` (`guid`,`map`,`zone`,`position_x`,`position_y`,`position_z`) VALUES ('%lu', '%d', '%d', '%f', '%f', '%f');", (unsigned long)playerGuid
, fields
[0].GetUInt32(), fields
[1].GetUInt32(), fields
[2].GetFloat(), fields
[3].GetFloat(), fields
[4].GetFloat());
232 data
.Initialize (SMSG_BINDPOINTUPDATE
);
233 data
<< fields
[2].GetFloat() << fields
[3].GetFloat() << fields
[4].GetFloat();
234 data
<< fields
[0].GetUInt32();
235 data
<< fields
[1].GetUInt32();
237 DEBUG_LOG("Setting player home position: mapid is: %d, zoneid is %d, X is %f, Y is %f, Z is %f\n",fields
[0].GetUInt32(),fields
[1].GetUInt32(),fields
[2].GetFloat(), fields
[3].GetFloat(), fields
[4].GetFloat());
244 switch (GetPlayer()->getClass())
247 SendProficiency (0x04, 0x02);
248 SendProficiency (0x02, 0x00, 0x04);
249 SendProficiency (0x02, 0x00, 0x44);
250 SendProficiency (0x04, 0x03);
251 SendProficiency (0x02, 0x00, 0x44, 0x08);
254 SendProficiency (0x04, 0x02);
255 SendProficiency (0x02, 0x00, 0x00, 0x01);
256 SendProficiency (0x04, 0x06);
257 SendProficiency (0x02, 0x00, 0x80, 0x01);
258 SendProficiency (0x02, 0x00, 0xC0, 0x01);
259 SendProficiency (0x04, 0x07);
262 SendProficiency (0x04, 0x02);
263 SendProficiency (0x02, 0x01);
264 SendProficiency (0x02, 0x11);
265 SendProficiency (0x04, 0x42);
266 SendProficiency (0x04, 0x4A);
267 SendProficiency (0x04, 0x4E);
268 SendProficiency (0x02, 0x11, 0x40);
269 SendProficiency (0x04, 0x4F);
270 SendProficiency (0x02, 0x91, 0x40);
273 SendProficiency (0x04, 0x02);
274 SendProficiency (0x02, 0x10);
275 SendProficiency (0x04, 0x42);
276 SendProficiency (0x02, 0x30);
277 SendProficiency (0x04, 0x4A);
278 SendProficiency (0x04, 0x4E);
279 SendProficiency (0x02, 0x30, 0x40);
280 SendProficiency (0x04, 0x4F);
283 SendProficiency (0x04, 0x02);
284 SendProficiency (0x02, 0x00, 0x80);
285 SendProficiency (0x02, 0x00, 0xC0);
286 SendProficiency (0x04, 0x03);
287 SendProficiency (0x02, 0x00, 0xC0, 0x08);
290 SendProficiency (0x04, 0x02);
291 SendProficiency (0x02, 0x10);
292 SendProficiency (0x02, 0x10, 0x40);
293 SendProficiency (0x04, 0x03);
294 SendProficiency (0x02, 0x10, 0x40, 0x08);
297 SendProficiency (0x04, 0x02);
298 SendProficiency (0x02, 0x00, 0x04);
299 SendProficiency (0x04, 0x06);
300 SendProficiency (0x02, 0x00, 0x84);
301 SendProficiency (0x02, 0x00, 0xC4);
302 SendProficiency (0x04, 0x07);
305 SendProficiency (0x04, 0x02);
306 SendProficiency (0x02, 0x01);
307 SendProficiency (0x04, 0x06);
308 SendProficiency (0x02, 0x05);
309 SendProficiency (0x02, 0x05, 0x40);
310 SendProficiency (0x04, 0x07);
313 SendProficiency (0x04, 0x02);
314 SendProficiency (0x02, 0x00, 0x04);
315 SendProficiency (0x02, 0x10, 0x04);
316 SendProficiency (0x04, 0x42);
317 SendProficiency (0x04, 0x46);
318 SendProficiency (0x02, 0x10, 0x44);
319 SendProficiency (0x04, 0x47);
323 data
.Initialize( SMSG_TUTORIAL_FLAGS
);
325 for (int i
= 0; i
< 8; i
++)
326 data
<< uint32( GetPlayer()->GetTutorialInt(i
) );
329 sLog
.outDebug( "WORLD: Sent tutorial flags." );
331 // Proficiency more to come
332 switch (GetPlayer()->getClass())
335 SendProficiency (0x02, 0x00, 0x44, 0x08);
336 SendProficiency (0x04, 0x03);
339 SendProficiency (0x02, 0x00, 0xC0, 0x01);
340 SendProficiency (0x04, 0x07);
343 SendProficiency (0x02, 0x91, 0x40);
344 SendProficiency (0x04, 0x4F);
347 SendProficiency (0x02, 0x30, 0x40);
348 SendProficiency (0x04, 0x4F);
351 SendProficiency (0x02, 0x00, 0xC0, 0x08);
352 SendProficiency (0x04, 0x03);
355 SendProficiency (0x02, 0x10, 0x40, 0x08);
356 SendProficiency (0x04, 0x03);
359 SendProficiency (0x02, 0x00, 0xC4);
360 SendProficiency (0x04, 0x07);
363 SendProficiency (0x02, 0x05, 0x40);
364 SendProficiency (0x04, 0x07);
367 SendProficiency (0x02, 0x10, 0x44);
368 SendProficiency (0x04, 0x47);
372 GetPlayer()->smsg_InitialSpells();
374 GetPlayer()->smsg_InitialActions();
376 data
.Initialize(SMSG_INITIALIZE_FACTIONS
);
377 data
<< uint32 (0x00000040);
378 for(int a
=0; a
<64; a
++)
380 if(GetPlayer()->FactionIsInTheList(a
))
382 std::list
<struct Factions
>::iterator itr
;
383 for(itr
= GetPlayer()->factions
.begin(); itr
!= GetPlayer()->factions
.end(); ++itr
)
385 if(itr
->ReputationListID
== a
)
387 data
<< uint8 (itr
->Flags
);
388 data
<< uint32 (itr
->Standing
);
395 data
<< uint8 (0x00);
396 data
<< uint32 (0x00000000);
401 GetPlayer()->UpdateHonor();
403 data
.Initialize(SMSG_LOGIN_SETTIMESPEED
);
404 time_t minutes
= sWorld
.GetGameTime( ) / 60;
405 time_t hours
= minutes
/ 60; minutes
%= 60;
406 time_t gameTime
= minutes
+ ( hours
<< 6 );
407 data
<< (uint32
)gameTime
;
408 data
<< (float)0.017f
;
411 //Show cinematic at the first time that player login
412 if( !GetPlayer()->getCinematic() )
414 GetPlayer()->setCinematic(1);
416 data
.Initialize( SMSG_TRIGGER_CINEMATIC
);
418 uint8 race
= GetPlayer()->getRace();
421 case HUMAN
: data
<< uint32(81); break;
422 case ORC
: data
<< uint32(21); break;
423 case DWARF
: data
<< uint32(41); break;
424 case NIGHTELF
: data
<< uint32(61); break;
425 case UNDEAD_PLAYER
: data
<< uint32(2); break;
426 case TAUREN
: data
<< uint32(141); break;
427 case GNOME
: data
<< uint32(101); break;
428 case TROLL
: data
<< uint32(121); break;
429 default: data
<< uint32(0);
434 Player
*pCurrChar
= GetPlayer();
436 QueryResult
*result
= sDatabase
.PQuery("SELECT * FROM `guild_member` WHERE `guid` = '%d';",pCurrChar
->GetGUID());
440 Field
*fields
= result
->Fetch();
441 pCurrChar
->SetInGuild(fields
[0].GetUInt32());
442 pCurrChar
->SetRank(fields
[2].GetUInt32());
445 sLog
.outError("AddObject at CharacterHandler.cpp");
446 MapManager::Instance().GetMap(pCurrChar
->GetMapId())->Add(pCurrChar
);
447 ObjectAccessor::Instance().InsertPlayer(pCurrChar
);
449 sDatabase
.PExecute("UPDATE `character` SET `online` = 1 WHERE `guid` = '%u';", pCurrChar
->GetGUID());
451 std::string outstring
= pCurrChar
->GetName();
452 outstring
.append( " has come online." );
453 pCurrChar
->BroadcastToFriends(outstring
);
455 // setting new speed if dead
456 if ( pCurrChar
->m_deathState
== DEAD
)
458 GetPlayer()->SetMovement(MOVE_WATER_WALK
);
460 if (GetPlayer()->getRace() == RACE_NIGHT_ELF
)
462 pCurrChar
->SetPlayerSpeed(MOVE_RUN
, (float)12.75, true);
463 pCurrChar
->SetPlayerSpeed(MOVE_SWIM
, (float)8.85, true);
467 pCurrChar
->SetPlayerSpeed(MOVE_RUN
, (float)10.625, true);
468 pCurrChar
->SetPlayerSpeed(MOVE_SWIM
, (float)7.375, true);
476 void WorldSession::HandleSetFactionAtWar( WorldPacket
& recv_data
)
478 sLog
.outDebug("WORLD SESSION: HandleSetFactionAtWar");
483 recv_data
>> FactionID
;
486 std::list
<struct Factions
>::iterator itr
;
488 for(itr
= GetPlayer()->factions
.begin(); itr
!= GetPlayer()->factions
.end(); ++itr
)
490 if(itr
->ReputationListID
== FactionID
)
493 itr
->Flags
= (itr
->Flags
| 2);
495 if( itr
->Flags
>= 2) itr
->Flags
-= 2;
501 void WorldSession::HandleSetFactionCheat( WorldPacket
& recv_data
)
503 sLog
.outDebug("WORLD SESSION: HandleSetFactionCheat");
508 recv_data
>> FactionID
;
509 recv_data
>> Standing
;
511 std::list
<struct Factions
>::iterator itr
;
513 for(itr
= GetPlayer()->factions
.begin(); itr
!= GetPlayer()->factions
.end(); ++itr
)
515 if(itr
->ReputationListID
== FactionID
)
517 itr
->Standing
+= Standing
;
518 itr
->Flags
= (itr
->Flags
| 1);
523 GetPlayer()->UpdateReputation();
526 void WorldSession::HandleMeetingStoneInfo( WorldPacket
& recv_data
)
528 DEBUG_LOG( "WORLD: Received CMSG_MEETING_STONE_INFO" );
531 void WorldSession::HandleTutorialFlag( WorldPacket
& recv_data
)
536 uint32 wInt
= (iFlag
/ 32);
537 uint32 rInt
= (iFlag
% 32);
539 uint32 tutflag
= GetPlayer()->GetTutorialInt( wInt
);
540 tutflag
|= (1 << rInt
);
541 GetPlayer()->SetTutorialInt( wInt
, tutflag
);
543 sLog
.outDebug("Received Tutorial Flag Set {%u}.", iFlag
);
546 void WorldSession::HandleTutorialClear( WorldPacket
& recv_data
)
548 for ( uint32 iI
= 0; iI
< 8; iI
++)
549 GetPlayer()->SetTutorialInt( iI
, 0xFFFFFFFF );
552 void WorldSession::HandleTutorialReset( WorldPacket
& recv_data
)
554 for ( uint32 iI
= 0; iI
< 8; iI
++)
555 GetPlayer()->SetTutorialInt( iI
, 0x00000000 );