[1130] Database Query Audit is now at 90 percent with this commit.
[mangos-git.git] / src / game / CharacterHandler.cpp
blob3204b95b4028b982edcc724c50fb2c411ad76753
1 /*
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
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "Opcodes.h"
24 #include "Log.h"
25 #include "World.h"
26 #include "ObjectMgr.h"
27 #include "Player.h"
28 #include "UpdateMask.h"
29 #include "Chat.h"
30 #include "Auth/md5.h"
31 #include "MapManager.h"
32 #include "ObjectAccessor.h"
34 void WorldSession::HandleCharEnumOpcode( WorldPacket & recv_data )
36 WorldPacket data;
38 /*// uknown opcode ?
39 WorldPacket packet;
40 packet.Initialize(SMSG_AUTH_RESPONSE2_UNKNOWN180);
41 packet << uint8(10);
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());
50 uint8 num = 0;
52 data << num;
54 if( result )
56 Player *plr;
59 plr = new Player(this);
60 ASSERT(plr);
62 sLog.outError("Loading char guid %d from account %d.",(*result)[0].GetUInt32(),GetAccountId());
64 plr->LoadFromDB( (*result)[0].GetUInt32() );
66 plr->BuildEnumData( &data );
68 delete plr;
70 num++;
72 while( result->NextRow() );
74 delete result;
77 data.put<uint8>(0, num);
79 SendPacket( &data );
82 void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
84 std::string name;
85 WorldPacket data;
87 recv_data >> name;
88 recv_data.rpos(0);
90 QueryResult *result = sDatabase.PQuery("SELECT `guid` FROM `character` WHERE `name` = '%s';", name.c_str());
92 if ( result )
94 delete result;
96 data.Initialize(SMSG_CHAR_CREATE);
97 data << (uint8)0x31;
98 SendPacket( &data );
100 return;
103 result = sDatabase.PQuery("SELECT `guid` FROM `character` WHERE `account` = '%lu';", (unsigned long)GetAccountId());
105 if ( result )
107 if (result->GetRowCount() >= 10)
109 data.Initialize(SMSG_CHAR_CREATE);
110 data << (uint8)0x2F;
111 SendPacket( &data );
112 delete result;
113 return;
115 delete result;
118 Player * pNewChar = new Player(this);
120 if(pNewChar->Create( objmgr.GenerateLowGuid(HIGHGUID_PLAYER), recv_data ))
122 // Player create
123 pNewChar->SaveToDB();
125 delete pNewChar;
127 else
129 // Player not create (race/class problem?)
130 delete pNewChar;
132 data.Initialize(SMSG_CHAR_CREATE);
133 data << (uint8)0x2F;
134 SendPacket( &data );
136 return;
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 );
148 data << (uint8)0x2E;
149 SendPacket( &data );
153 void WorldSession::HandleCharDeleteOpcode( WorldPacket & recv_data )
155 WorldPacket data;
157 uint64 guid;
158 recv_data >> guid;
160 Player* plr = new Player(this);
161 ASSERT(plr);
163 plr->LoadFromDB( GUID_LOPART(guid) );
164 plr->DeleteFromDB();
166 delete plr;
168 data.Initialize(SMSG_CHAR_CREATE);
169 data << (uint8)0x34;
170 SendPacket( &data );
173 void WorldSession::HandlePlayerLoginOpcode( WorldPacket & recv_data )
175 WorldPacket data;
176 uint64 playerGuid = 0;
178 DEBUG_LOG( "WORLD: Recvd Player Logon Message" );
180 recv_data >> playerGuid;
182 Player* plr = new Player(this);
183 ASSERT(plr);
185 plr->SetSession(this);
186 plr->LoadFromDB(GUID_LOPART(playerGuid));
187 plr->_RemoveAllItemMods();
189 SetPlayer(plr);
191 data.Initialize( SMSG_ACCOUNT_DATA_MD5 );
193 for(int i = 0; i < 80; i++)
194 data << uint8(0);
196 SendPacket(&data);
198 sChatHandler.FillSystemMessageData(&data, this, sWorld.GetMotd());
199 SendPacket( &data );
201 DEBUG_LOG( "WORLD: Sent motd (SMSG_MESSAGECHAT)" );
203 // home bind stuff
204 Field *fields;
205 QueryResult *result7 = sDatabase.PQuery("SELECT COUNT(*) FROM `character_homebind` WHERE `guid` = '%d';", playerGuid);
206 if (result7)
208 int cnt;
209 fields = result7->Fetch();
210 cnt = fields[0].GetUInt32();
212 if ( cnt > 0 )
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();
220 SendPacket (&data);
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());
222 delete result4;
224 else
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();
236 SendPacket (&data);
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());
238 delete result5;
240 delete result7;
243 // set proficiency
244 switch (GetPlayer()->getClass())
246 case CLASS_MAGE:
247 SendProficiency (0x04, 0x02);
248 SendProficiency (0x02, 0x00, 0x04);
249 SendProficiency (0x02, 0x00, 0x44);
250 SendProficiency (0x04, 0x03);
251 SendProficiency (0x02, 0x00, 0x44, 0x08);
252 break;
253 case CLASS_ROGUE:
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);
260 break;
261 case CLASS_WARRIOR:
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);
271 break;
272 case CLASS_PALADIN:
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);
281 break;
282 case CLASS_WARLOCK:
283 SendProficiency (0x04, 0x02);
284 SendProficiency (0x02, 0x00, 0x80);
285 SendProficiency (0x02, 0x00, 0xC0);
286 SendProficiency (0x04, 0x03);
287 SendProficiency (0x02, 0x00, 0xC0, 0x08);
288 break;
289 case CLASS_PRIEST:
290 SendProficiency (0x04, 0x02);
291 SendProficiency (0x02, 0x10);
292 SendProficiency (0x02, 0x10, 0x40);
293 SendProficiency (0x04, 0x03);
294 SendProficiency (0x02, 0x10, 0x40, 0x08);
295 break;
296 case CLASS_DRUID:
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);
303 break;
304 case CLASS_HUNTER:
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);
311 break;
312 case CLASS_SHAMAN:
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);
320 break;
323 data.Initialize( SMSG_TUTORIAL_FLAGS );
325 for (int i = 0; i < 8; i++)
326 data << uint32( GetPlayer()->GetTutorialInt(i) );
328 SendPacket(&data);
329 sLog.outDebug( "WORLD: Sent tutorial flags." );
331 // Proficiency more to come
332 switch (GetPlayer()->getClass())
334 case CLASS_MAGE:
335 SendProficiency (0x02, 0x00, 0x44, 0x08);
336 SendProficiency (0x04, 0x03);
337 break;
338 case CLASS_ROGUE:
339 SendProficiency (0x02, 0x00, 0xC0, 0x01);
340 SendProficiency (0x04, 0x07);
341 break;
342 case CLASS_WARRIOR:
343 SendProficiency (0x02, 0x91, 0x40);
344 SendProficiency (0x04, 0x4F);
345 break;
346 case CLASS_PALADIN:
347 SendProficiency (0x02, 0x30, 0x40);
348 SendProficiency (0x04, 0x4F);
349 break;
350 case CLASS_WARLOCK:
351 SendProficiency (0x02, 0x00, 0xC0, 0x08);
352 SendProficiency (0x04, 0x03);
353 break;
354 case CLASS_PRIEST:
355 SendProficiency (0x02, 0x10, 0x40, 0x08);
356 SendProficiency (0x04, 0x03);
357 break;
358 case CLASS_DRUID:
359 SendProficiency (0x02, 0x00, 0xC4);
360 SendProficiency (0x04, 0x07);
361 break;
362 case CLASS_HUNTER:
363 SendProficiency (0x02, 0x05, 0x40);
364 SendProficiency (0x04, 0x07);
365 break;
366 case CLASS_SHAMAN:
367 SendProficiency (0x02, 0x10, 0x44);
368 SendProficiency (0x04, 0x47);
369 break;
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);
389 break;
393 else
395 data << uint8 (0x00);
396 data << uint32 (0x00000000);
399 SendPacket(&data);
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;
409 SendPacket( &data );
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();
419 switch (race)
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);
431 SendPacket( &data );
434 Player *pCurrChar = GetPlayer();
436 QueryResult *result = sDatabase.PQuery("SELECT * FROM `guild_member` WHERE `guid` = '%d';",pCurrChar->GetGUID());
438 if(result)
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);
465 else
467 pCurrChar->SetPlayerSpeed(MOVE_RUN, (float)10.625, true);
468 pCurrChar->SetPlayerSpeed(MOVE_SWIM, (float)7.375, true);
472 delete result;
476 void WorldSession::HandleSetFactionAtWar( WorldPacket & recv_data )
478 sLog.outDebug("WORLD SESSION: HandleSetFactionAtWar");
480 uint32 FactionID;
481 uint8 Flag;
483 recv_data >> FactionID;
484 recv_data >> Flag;
486 std::list<struct Factions>::iterator itr;
488 for(itr = GetPlayer()->factions.begin(); itr != GetPlayer()->factions.end(); ++itr)
490 if(itr->ReputationListID == FactionID)
492 if( Flag )
493 itr->Flags = (itr->Flags | 2);
494 else
495 if( itr->Flags >= 2) itr->Flags -= 2;
496 break;
501 void WorldSession::HandleSetFactionCheat( WorldPacket & recv_data )
503 sLog.outDebug("WORLD SESSION: HandleSetFactionCheat");
505 uint32 FactionID;
506 uint32 Standing;
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);
519 break;
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 )
533 uint32 iFlag;
534 recv_data >> iFlag;
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 );