[9581] Fixed apply damage reduction to melee/ranged damage.
[getmangos.git] / src / game / Level2.cpp
blob87fdfe4688f0e2089225a6d38ca4367b4d8557cc
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 "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "DBCStores.h"
22 #include "ObjectMgr.h"
23 #include "ObjectGuid.h"
24 #include "Player.h"
25 #include "Item.h"
26 #include "GameObject.h"
27 #include "Opcodes.h"
28 #include "Chat.h"
29 #include "ObjectAccessor.h"
30 #include "MapManager.h"
31 #include "Language.h"
32 #include "World.h"
33 #include "GameEventMgr.h"
34 #include "SpellMgr.h"
35 #include "PoolManager.h"
36 #include "AccountMgr.h"
37 #include "GMTicketMgr.h"
38 #include "WaypointManager.h"
39 #include "Util.h"
40 #include <cctype>
41 #include <iostream>
42 #include <fstream>
43 #include <map>
44 #include "GlobalEvents.h"
46 #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
48 static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
50 LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL,
51 LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED
54 //mute player for some times
55 bool ChatHandler::HandleMuteCommand(const char* args)
57 char* nameStr;
58 char* delayStr;
59 extractOptFirstArg((char*)args,&nameStr,&delayStr);
60 if(!delayStr)
61 return false;
63 Player* target;
64 uint64 target_guid;
65 std::string target_name;
66 if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name))
67 return false;
69 uint32 account_id = target ? target->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(target_guid);
71 // find only player from same account if any
72 if(!target)
74 if(WorldSession* session = sWorld.FindSession(account_id))
75 target = session->GetPlayer();
78 uint32 notspeaktime = (uint32) atoi(delayStr);
80 // must have strong lesser security level
81 if(HasLowerSecurity (target,target_guid,true))
82 return false;
84 time_t mutetime = time(NULL) + notspeaktime*60;
86 if (target)
87 target->GetSession()->m_muteTime = mutetime;
89 loginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
91 if(target)
92 ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
94 std::string nameLink = playerLink(target_name);
96 PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime);
97 return true;
100 //unmute player
101 bool ChatHandler::HandleUnmuteCommand(const char* args)
103 Player* target;
104 uint64 target_guid;
105 std::string target_name;
106 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
107 return false;
109 uint32 account_id = target ? target->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(target_guid);
111 // find only player from same account if any
112 if(!target)
114 if(WorldSession* session = sWorld.FindSession(account_id))
115 target = session->GetPlayer();
118 // must have strong lesser security level
119 if(HasLowerSecurity (target,target_guid,true))
120 return false;
122 if (target)
124 if(target->CanSpeak())
126 SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
127 SetSentErrorMessage(true);
128 return false;
131 target->GetSession()->m_muteTime = 0;
134 loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
136 if(target)
137 ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
139 std::string nameLink = playerLink(target_name);
141 PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str());
142 return true;
145 bool ChatHandler::HandleGoTriggerCommand(const char* args)
147 Player* _player = m_session->GetPlayer();
149 if (!*args)
150 return false;
152 char *atId = strtok((char*)args, " ");
153 if (!atId)
154 return false;
156 int32 i_atId = atoi(atId);
158 if(!i_atId)
159 return false;
161 AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
162 if (!at)
164 PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
165 SetSentErrorMessage(true);
166 return false;
169 if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
171 PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
172 SetSentErrorMessage(true);
173 return false;
176 // stop flight if need
177 if(_player->isInFlight())
179 _player->GetMotionMaster()->MovementExpired();
180 _player->m_taxi.ClearTaxiDestinations();
182 // save only in non-flight case
183 else
184 _player->SaveRecallPosition();
186 _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
187 return true;
190 bool ChatHandler::HandleGoGraveyardCommand(const char* args)
192 Player* _player = m_session->GetPlayer();
194 if (!*args)
195 return false;
197 char *gyId = strtok((char*)args, " ");
198 if (!gyId)
199 return false;
201 int32 i_gyId = atoi(gyId);
203 if(!i_gyId)
204 return false;
206 WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
207 if (!gy)
209 PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
210 SetSentErrorMessage(true);
211 return false;
214 if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
216 PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
217 SetSentErrorMessage(true);
218 return false;
221 // stop flight if need
222 if(_player->isInFlight())
224 _player->GetMotionMaster()->MovementExpired();
225 _player->m_taxi.ClearTaxiDestinations();
227 // save only in non-flight case
228 else
229 _player->SaveRecallPosition();
231 _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
232 return true;
235 /** \brief Teleport the GM to the specified creature
237 * .gocreature <GUID> --> TP using creature.guid
238 * .gocreature azuregos --> TP player to the mob with this name
239 * Warning: If there is more than one mob with this name
240 * you will be teleported to the first one that is found.
241 * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry
242 * Warning: If there is more than one mob with this "id"
243 * you will be teleported to the first one that is found.
245 //teleport to creature
246 bool ChatHandler::HandleGoCreatureCommand(const char* args)
248 if(!*args)
249 return false;
250 Player* _player = m_session->GetPlayer();
252 // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
253 char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
254 if (!pParam1)
255 return false;
257 std::ostringstream whereClause;
259 // User wants to teleport to the NPC's template entry
260 if( strcmp(pParam1, "id") == 0 )
262 //sLog.outError("DEBUG: ID found");
264 // Get the "creature_template.entry"
265 // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
266 char* tail = strtok(NULL,"");
267 if(!tail)
268 return false;
269 char* cId = extractKeyFromLink(tail,"Hcreature_entry");
270 if(!cId)
271 return false;
273 int32 tEntry = atoi(cId);
274 //sLog.outError("DEBUG: ID value: %d", tEntry);
275 if(!tEntry)
276 return false;
278 whereClause << "WHERE id = '" << tEntry << "'";
280 else
282 //sLog.outError("DEBUG: ID *not found*");
284 int32 guid = atoi(pParam1);
286 // Number is invalid - maybe the user specified the mob's name
287 if(!guid)
289 std::string name = pParam1;
290 WorldDatabase.escape_string(name);
291 whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
293 else
295 whereClause << "WHERE guid = '" << guid << "'";
298 //sLog.outError("DEBUG: %s", whereClause.c_str());
300 QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
301 if (!result)
303 SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
304 SetSentErrorMessage(true);
305 return false;
307 if( result->GetRowCount() > 1 )
309 SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
312 Field *fields = result->Fetch();
313 float x = fields[0].GetFloat();
314 float y = fields[1].GetFloat();
315 float z = fields[2].GetFloat();
316 float ort = fields[3].GetFloat();
317 int mapid = fields[4].GetUInt16();
319 delete result;
321 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
323 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
324 SetSentErrorMessage(true);
325 return false;
328 // stop flight if need
329 if(_player->isInFlight())
331 _player->GetMotionMaster()->MovementExpired();
332 _player->m_taxi.ClearTaxiDestinations();
334 // save only in non-flight case
335 else
336 _player->SaveRecallPosition();
338 _player->TeleportTo(mapid, x, y, z, ort);
339 return true;
342 //teleport to gameobject
343 bool ChatHandler::HandleGoObjectCommand(const char* args)
345 if(!*args)
346 return false;
348 Player* _player = m_session->GetPlayer();
350 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
351 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
352 if(!cId)
353 return false;
355 int32 guid = atoi(cId);
356 if(!guid)
357 return false;
359 float x, y, z, ort;
360 int mapid;
362 // by DB guid
363 if (GameObjectData const* go_data = sObjectMgr.GetGOData(guid))
365 x = go_data->posX;
366 y = go_data->posY;
367 z = go_data->posZ;
368 ort = go_data->orientation;
369 mapid = go_data->mapid;
371 else
373 SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
374 SetSentErrorMessage(true);
375 return false;
378 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
380 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
381 SetSentErrorMessage(true);
382 return false;
385 // stop flight if need
386 if(_player->isInFlight())
388 _player->GetMotionMaster()->MovementExpired();
389 _player->m_taxi.ClearTaxiDestinations();
391 // save only in non-flight case
392 else
393 _player->SaveRecallPosition();
395 _player->TeleportTo(mapid, x, y, z, ort);
396 return true;
399 bool ChatHandler::HandleGameObjectTargetCommand(const char* args)
401 Player* pl = m_session->GetPlayer();
402 QueryResult *result;
403 GameEventMgr::ActiveEvents const& activeEventsList = sGameEventMgr.GetActiveEventList();
404 if(*args)
406 // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r
407 char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry");
408 if(!cId)
409 return false;
411 uint32 id = atol(cId);
413 if(id)
414 result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1",
415 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
416 else
418 std::string name = cId;
419 WorldDatabase.escape_string(name);
420 result = WorldDatabase.PQuery(
421 "SELECT guid, id, position_x, position_y, position_z, orientation, map, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ "
422 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
423 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
426 else
428 std::ostringstream eventFilter;
429 eventFilter << " AND (event IS NULL ";
430 bool initString = true;
432 for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
434 if (initString)
436 eventFilter << "OR event IN (" <<*itr;
437 initString =false;
439 else
440 eventFilter << "," << *itr;
443 if (!initString)
444 eventFilter << "))";
445 else
446 eventFilter << ")";
448 result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
449 "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
450 "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10",
451 m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
454 if (!result)
456 SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
457 return true;
460 bool found = false;
461 float x, y, z, o;
462 uint32 lowguid, id;
463 uint16 mapid, pool_id;
467 Field *fields = result->Fetch();
468 lowguid = fields[0].GetUInt32();
469 id = fields[1].GetUInt32();
470 x = fields[2].GetFloat();
471 y = fields[3].GetFloat();
472 z = fields[4].GetFloat();
473 o = fields[5].GetFloat();
474 mapid = fields[6].GetUInt16();
475 pool_id = sPoolMgr.IsPartOfAPool<GameObject>(lowguid);
476 if (!pool_id || sPoolMgr.IsSpawnedObject<GameObject>(lowguid))
477 found = true;
478 } while( result->NextRow() && (!found) );
480 delete result;
482 if (!found)
484 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
485 return false;
488 GameObjectInfo const* goI = ObjectMgr::GetGameObjectInfo(id);
490 if (!goI)
492 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
493 return false;
496 GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
498 PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
500 if(target)
502 time_t curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
503 if(curRespawnDelay < 0)
504 curRespawnDelay = 0;
506 std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
507 std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
509 PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
511 return true;
514 //delete object by selection or guid
515 bool ChatHandler::HandleGameObjectDeleteCommand(const char* args)
517 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
518 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
519 if(!cId)
520 return false;
522 uint32 lowguid = atoi(cId);
523 if(!lowguid)
524 return false;
526 GameObject* obj = NULL;
528 // by DB guid
529 if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid))
530 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
532 if(!obj)
534 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
535 SetSentErrorMessage(true);
536 return false;
539 uint64 owner_guid = obj->GetOwnerGUID();
540 if(owner_guid)
542 Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
543 if(!owner || !IS_PLAYER_GUID(owner_guid))
545 PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
546 SetSentErrorMessage(true);
547 return false;
550 owner->RemoveGameObject(obj,false);
553 obj->SetRespawnTime(0); // not save respawn time
554 obj->Delete();
555 obj->DeleteFromDB();
557 PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
559 return true;
562 //turn selected object
563 bool ChatHandler::HandleGameObjectTurnCommand(const char* args)
565 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
566 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
567 if(!cId)
568 return false;
570 uint32 lowguid = atoi(cId);
571 if(!lowguid)
572 return false;
574 GameObject* obj = NULL;
576 // by DB guid
577 if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid))
578 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
580 if(!obj)
582 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
583 SetSentErrorMessage(true);
584 return false;
587 char* po = strtok(NULL, " ");
588 float o;
590 if (po)
592 o = (float)atof(po);
594 else
596 Player *chr = m_session->GetPlayer();
597 o = chr->GetOrientation();
600 Map* map = obj->GetMap();
601 map->Remove(obj,false);
603 obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
604 obj->UpdateRotationFields();
606 map->Add(obj);
608 obj->SaveToDB();
609 obj->Refresh();
611 PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow(), o);
613 return true;
616 //move selected object
617 bool ChatHandler::HandleGameObjectMoveCommand(const char* args)
619 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
620 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
621 if(!cId)
622 return false;
624 uint32 lowguid = atoi(cId);
625 if(!lowguid)
626 return false;
628 GameObject* obj = NULL;
630 // by DB guid
631 if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid))
632 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
634 if(!obj)
636 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
637 SetSentErrorMessage(true);
638 return false;
641 char* px = strtok(NULL, " ");
642 char* py = strtok(NULL, " ");
643 char* pz = strtok(NULL, " ");
645 if (!px)
647 Player *chr = m_session->GetPlayer();
649 Map* map = obj->GetMap();
650 map->Remove(obj,false);
652 obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
654 map->Add(obj);
656 else
658 if(!py || !pz)
659 return false;
661 float x = (float)atof(px);
662 float y = (float)atof(py);
663 float z = (float)atof(pz);
665 if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
667 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
668 SetSentErrorMessage(true);
669 return false;
672 Map* map = obj->GetMap();
673 map->Remove(obj,false);
675 obj->Relocate(x, y, z, obj->GetOrientation());
677 map->Add(obj);
680 obj->SaveToDB();
681 obj->Refresh();
683 PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow());
685 return true;
688 //spawn go
689 bool ChatHandler::HandleGameObjectAddCommand(const char* args)
691 if (!*args)
692 return false;
694 // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r
695 char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry");
696 if(!cId)
697 return false;
699 uint32 id = atol(cId);
700 if(!id)
701 return false;
703 char* spawntimeSecs = strtok(NULL, " ");
705 const GameObjectInfo *gInfo = ObjectMgr::GetGameObjectInfo(id);
707 if (!gInfo)
709 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
710 SetSentErrorMessage(true);
711 return false;
714 if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId))
716 // report to DB errors log as in loading case
717 sLog.outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.",id, gInfo->type, gInfo->displayId);
718 PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA,id);
719 SetSentErrorMessage(true);
720 return false;
723 Player *chr = m_session->GetPlayer();
724 float x = float(chr->GetPositionX());
725 float y = float(chr->GetPositionY());
726 float z = float(chr->GetPositionZ());
727 float o = float(chr->GetOrientation());
728 Map *map = chr->GetMap();
730 GameObject* pGameObj = new GameObject;
731 uint32 db_lowGUID = sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
733 if(!pGameObj->Create(db_lowGUID, gInfo->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
735 delete pGameObj;
736 return false;
739 if( spawntimeSecs )
741 uint32 value = atoi((char*)spawntimeSecs);
742 pGameObj->SetRespawnTime(value);
743 //sLog.outDebug("*** spawntimeSecs: %d", value);
746 // fill the gameobject data and save to the db
747 pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn());
749 // this will generate a new guid if the object is in an instance
750 if(!pGameObj->LoadFromDB(db_lowGUID, map))
752 delete pGameObj;
753 return false;
756 sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o);
758 map->Add(pGameObj);
760 // TODO: is it really necessary to add both the real and DB table guid here ?
761 sObjectMgr.AddGameobjectToGrid(db_lowGUID, sObjectMgr.GetGOData(db_lowGUID));
763 PSendSysMessage(LANG_GAMEOBJECT_ADD,id,gInfo->name,db_lowGUID,x,y,z);
764 return true;
767 //set pahsemask for selected object
768 bool ChatHandler::HandleGameObjectPhaseCommand(const char* args)
770 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
771 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
772 if(!cId)
773 return false;
775 uint32 lowguid = atoi(cId);
776 if(!lowguid)
777 return false;
779 GameObject* obj = NULL;
781 // by DB guid
782 if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid))
783 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
785 if(!obj)
787 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
788 SetSentErrorMessage(true);
789 return false;
792 char* phaseStr = strtok (NULL, " ");
793 uint32 phasemask = phaseStr? atoi(phaseStr) : 0;
794 if ( phasemask == 0 )
796 SendSysMessage(LANG_BAD_VALUE);
797 SetSentErrorMessage(true);
798 return false;
801 obj->SetPhaseMask(phasemask,true);
802 obj->SaveToDB();
803 return true;
806 bool ChatHandler::HandleGameObjectNearCommand(const char* args)
808 float distance = (!*args) ? 10.0f : (float)atof(args);
809 uint32 count = 0;
811 Player* pl = m_session->GetPlayer();
812 QueryResult *result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, map, "
813 "(POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ "
814 "FROM gameobject WHERE map='%u' AND (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) <= '%f' ORDER BY order_",
815 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),
816 pl->GetMapId(),pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),distance*distance);
818 if (result)
822 Field *fields = result->Fetch();
823 uint32 guid = fields[0].GetUInt32();
824 uint32 entry = fields[1].GetUInt32();
825 float x = fields[2].GetFloat();
826 float y = fields[3].GetFloat();
827 float z = fields[4].GetFloat();
828 int mapid = fields[5].GetUInt16();
830 GameObjectInfo const * gInfo = ObjectMgr::GetGameObjectInfo(entry);
832 if(!gInfo)
833 continue;
835 PSendSysMessage(LANG_GO_LIST_CHAT, guid, guid, gInfo->name, x, y, z, mapid);
837 ++count;
838 } while (result->NextRow());
840 delete result;
843 PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE,distance,count);
844 return true;
847 bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
849 uint64 guid = m_session->GetPlayer()->GetSelection();
851 if (guid == 0)
853 SendSysMessage(LANG_NO_SELECTION);
854 SetSentErrorMessage(true);
855 return false;
858 PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
859 return true;
862 bool ChatHandler::HandleLookupFactionCommand(const char* args)
864 if (!*args)
865 return false;
867 // Can be NULL at console call
868 Player *target = getSelectedPlayer ();
870 std::string namepart = args;
871 std::wstring wnamepart;
873 if (!Utf8toWStr (namepart,wnamepart))
874 return false;
876 // converting string that we try to find to lower case
877 wstrToLower (wnamepart);
879 uint32 counter = 0; // Counter for figure out that we found smth.
881 for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
883 FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
884 if (factionEntry)
886 FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL;
888 int loc = GetSessionDbcLocale();
889 std::string name = factionEntry->name[loc];
890 if(name.empty())
891 continue;
893 if (!Utf8FitTo(name, wnamepart))
895 loc = 0;
896 for(; loc < MAX_LOCALE; ++loc)
898 if(loc==GetSessionDbcLocale())
899 continue;
901 name = factionEntry->name[loc];
902 if(name.empty())
903 continue;
905 if (Utf8FitTo(name, wnamepart))
906 break;
910 if(loc < MAX_LOCALE)
912 // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
913 // or "id - [faction] [no reputation]" format
914 std::ostringstream ss;
915 if (m_session)
916 ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
917 else
918 ss << id << " - " << name << " " << localeNames[loc];
920 if (repState) // and then target!=NULL also
922 ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
923 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
925 ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")";
927 if(repState->Flags & FACTION_FLAG_VISIBLE)
928 ss << GetMangosString(LANG_FACTION_VISIBLE);
929 if(repState->Flags & FACTION_FLAG_AT_WAR)
930 ss << GetMangosString(LANG_FACTION_ATWAR);
931 if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
932 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
933 if(repState->Flags & FACTION_FLAG_HIDDEN)
934 ss << GetMangosString(LANG_FACTION_HIDDEN);
935 if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
936 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
937 if(repState->Flags & FACTION_FLAG_INACTIVE)
938 ss << GetMangosString(LANG_FACTION_INACTIVE);
940 else
941 ss << GetMangosString(LANG_FACTION_NOREPUTATION);
943 SendSysMessage(ss.str().c_str());
944 counter++;
949 if (counter == 0) // if counter == 0 then we found nth
950 SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
951 return true;
954 bool ChatHandler::HandleModifyRepCommand(const char * args)
956 if (!*args) return false;
958 Player* target = NULL;
959 target = getSelectedPlayer();
961 if(!target)
963 SendSysMessage(LANG_PLAYER_NOT_FOUND);
964 SetSentErrorMessage(true);
965 return false;
968 // check online security
969 if (HasLowerSecurity(target, 0))
970 return false;
972 char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
973 if(!factionTxt)
974 return false;
976 uint32 factionId = atoi(factionTxt);
978 int32 amount = 0;
979 char *rankTxt = strtok(NULL, " ");
980 if (!factionTxt || !rankTxt)
981 return false;
983 amount = atoi(rankTxt);
984 if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
986 std::string rankStr = rankTxt;
987 std::wstring wrankStr;
988 if(!Utf8toWStr(rankStr,wrankStr))
989 return false;
990 wstrToLower( wrankStr );
992 int r = 0;
993 amount = -42000;
994 for (; r < MAX_REPUTATION_RANK; ++r)
996 std::string rank = GetMangosString(ReputationRankStrIndex[r]);
997 if(rank.empty())
998 continue;
1000 std::wstring wrank;
1001 if(!Utf8toWStr(rank,wrank))
1002 continue;
1004 wstrToLower(wrank);
1006 if(wrank.substr(0,wrankStr.size())==wrankStr)
1008 char *deltaTxt = strtok(NULL, " ");
1009 if (deltaTxt)
1011 int32 delta = atoi(deltaTxt);
1012 if ((delta < 0) || (delta > ReputationMgr::PointsInRank[r] -1))
1014 PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (ReputationMgr::PointsInRank[r]-1));
1015 SetSentErrorMessage(true);
1016 return false;
1018 amount += delta;
1020 break;
1022 amount += ReputationMgr::PointsInRank[r];
1024 if (r >= MAX_REPUTATION_RANK)
1026 PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
1027 SetSentErrorMessage(true);
1028 return false;
1032 FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
1034 if (!factionEntry)
1036 PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
1037 SetSentErrorMessage(true);
1038 return false;
1041 if (factionEntry->reputationListID < 0)
1043 PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[GetSessionDbcLocale()], factionId);
1044 SetSentErrorMessage(true);
1045 return false;
1048 target->GetReputationMgr().SetReputation(factionEntry,amount);
1049 PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[GetSessionDbcLocale()], factionId,
1050 GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry));
1051 return true;
1054 //-----------------------Npc Commands-----------------------
1055 //add spawn of creature
1056 bool ChatHandler::HandleNpcAddCommand(const char* args)
1058 if(!*args)
1059 return false;
1060 char* charID = extractKeyFromLink((char*)args,"Hcreature_entry");
1061 if(!charID)
1062 return false;
1064 char* team = strtok(NULL, " ");
1065 int32 teamval = 0;
1066 if (team) { teamval = atoi(team); }
1067 if (teamval < 0) { teamval = 0; }
1069 uint32 id = atoi(charID);
1071 Player *chr = m_session->GetPlayer();
1072 float x = chr->GetPositionX();
1073 float y = chr->GetPositionY();
1074 float z = chr->GetPositionZ();
1075 float o = chr->GetOrientation();
1076 Map *map = chr->GetMap();
1078 Creature* pCreature = new Creature;
1079 if (!pCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, (uint32)teamval))
1081 delete pCreature;
1082 return false;
1085 pCreature->Relocate(x,y,z,o);
1087 if(!pCreature->IsPositionValid())
1089 sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
1090 delete pCreature;
1091 return false;
1094 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
1096 uint32 db_guid = pCreature->GetDBTableGUIDLow();
1098 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
1099 pCreature->LoadFromDB(db_guid, map);
1101 map->Add(pCreature);
1102 sObjectMgr.AddCreatureToGrid(db_guid, sObjectMgr.GetCreatureData(db_guid));
1103 return true;
1106 //add item in vendorlist
1107 bool ChatHandler::HandleNpcAddVendorItemCommand(const char* args)
1109 if (!*args)
1110 return false;
1112 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1113 if (!pitem)
1115 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1116 SetSentErrorMessage(true);
1117 return false;
1120 uint32 itemId = atol(pitem);
1122 char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
1123 uint32 maxcount = 0;
1124 if (fmaxcount)
1125 maxcount = atol(fmaxcount);
1127 char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
1128 uint32 incrtime = 0;
1129 if (fincrtime)
1130 incrtime = atol(fincrtime);
1132 char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
1133 uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1135 Creature* vendor = getSelectedCreature();
1137 uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1139 if(!sObjectMgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1141 SetSentErrorMessage(true);
1142 return false;
1145 sObjectMgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1147 ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId);
1149 PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1150 return true;
1153 //del item from vendor list
1154 bool ChatHandler::HandleNpcDelVendorItemCommand(const char* args)
1156 if (!*args)
1157 return false;
1159 Creature* vendor = getSelectedCreature();
1160 if (!vendor || !vendor->isVendor())
1162 SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1163 SetSentErrorMessage(true);
1164 return false;
1167 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1168 if (!pitem)
1170 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1171 SetSentErrorMessage(true);
1172 return false;
1174 uint32 itemId = atol(pitem);
1176 if(!sObjectMgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1178 PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1179 SetSentErrorMessage(true);
1180 return false;
1183 ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId);
1185 PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1186 return true;
1189 //add move for creature
1190 bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
1192 if(!*args)
1193 return false;
1195 char* guid_str = strtok((char*)args, " ");
1196 char* wait_str = strtok((char*)NULL, " ");
1198 uint32 lowguid = atoi((char*)guid_str);
1200 Creature* pCreature = NULL;
1202 /* FIXME: impossible without entry
1203 if(lowguid)
1204 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1207 // attempt check creature existence by DB data
1208 if(!pCreature)
1210 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
1211 if(!data)
1213 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1214 SetSentErrorMessage(true);
1215 return false;
1218 else
1220 // obtain real GUID for DB operations
1221 lowguid = pCreature->GetDBTableGUIDLow();
1224 int wait = wait_str ? atoi(wait_str) : 0;
1226 if(wait < 0)
1227 wait = 0;
1229 Player* player = m_session->GetPlayer();
1231 sWaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1233 // update movement type
1234 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1235 if(pCreature)
1237 pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1238 pCreature->GetMotionMaster()->Initialize();
1239 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1241 pCreature->setDeathState(JUST_DIED);
1242 pCreature->Respawn();
1244 pCreature->SaveToDB();
1247 SendSysMessage(LANG_WAYPOINT_ADDED);
1249 return true;
1252 //change level of creature or pet
1253 bool ChatHandler::HandleNpcChangeLevelCommand(const char* args)
1255 if (!*args)
1256 return false;
1258 uint8 lvl = (uint8) atoi((char*)args);
1259 if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL) + 3)
1261 SendSysMessage(LANG_BAD_VALUE);
1262 SetSentErrorMessage(true);
1263 return false;
1266 Creature* pCreature = getSelectedCreature();
1267 if(!pCreature)
1269 SendSysMessage(LANG_SELECT_CREATURE);
1270 SetSentErrorMessage(true);
1271 return false;
1274 if(pCreature->isPet())
1276 if(((Pet*)pCreature)->getPetType()==HUNTER_PET)
1278 pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr.GetXPForPetLevel(lvl));
1279 pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
1281 ((Pet*)pCreature)->GivePetLevel(lvl);
1283 else
1285 pCreature->SetMaxHealth( 100 + 30*lvl);
1286 pCreature->SetHealth( 100 + 30*lvl);
1287 pCreature->SetLevel( lvl);
1288 pCreature->SaveToDB();
1291 return true;
1294 //set npcflag of creature
1295 bool ChatHandler::HandleNpcFlagCommand(const char* args)
1297 if (!*args)
1298 return false;
1300 uint32 npcFlags = (uint32) atoi((char*)args);
1302 Creature* pCreature = getSelectedCreature();
1304 if(!pCreature)
1306 SendSysMessage(LANG_SELECT_CREATURE);
1307 SetSentErrorMessage(true);
1308 return false;
1311 pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1313 WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1315 SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1317 return true;
1320 bool ChatHandler::HandleNpcDeleteCommand(const char* args)
1322 Creature* unit = NULL;
1324 if(*args)
1326 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1327 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1328 if(!cId)
1329 return false;
1331 uint32 lowguid = atoi(cId);
1332 if(!lowguid)
1333 return false;
1335 if (CreatureData const* cr_data = sObjectMgr.GetCreatureData(lowguid))
1336 unit = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
1338 else
1339 unit = getSelectedCreature();
1341 if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle())
1343 SendSysMessage(LANG_SELECT_CREATURE);
1344 SetSentErrorMessage(true);
1345 return false;
1348 // Delete the creature
1349 unit->CombatStop();
1350 unit->DeleteFromDB();
1351 unit->AddObjectToRemoveList();
1353 SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
1355 return true;
1358 //move selected creature
1359 bool ChatHandler::HandleNpcMoveCommand(const char* args)
1361 uint32 lowguid = 0;
1363 Creature* pCreature = getSelectedCreature();
1365 if(!pCreature)
1367 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1368 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1369 if(!cId)
1370 return false;
1372 lowguid = atoi(cId);
1374 /* FIXME: impossibel without entry
1375 if(lowguid)
1376 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1379 // Attempting creature load from DB data
1380 if(!pCreature)
1382 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
1383 if(!data)
1385 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1386 SetSentErrorMessage(true);
1387 return false;
1390 uint32 map_id = data->mapid;
1392 if(m_session->GetPlayer()->GetMapId()!=map_id)
1394 PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1395 SetSentErrorMessage(true);
1396 return false;
1399 else
1401 lowguid = pCreature->GetDBTableGUIDLow();
1404 else
1406 lowguid = pCreature->GetDBTableGUIDLow();
1409 float x = m_session->GetPlayer()->GetPositionX();
1410 float y = m_session->GetPlayer()->GetPositionY();
1411 float z = m_session->GetPlayer()->GetPositionZ();
1412 float o = m_session->GetPlayer()->GetOrientation();
1414 if (pCreature)
1416 if(CreatureData const* data = sObjectMgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1418 const_cast<CreatureData*>(data)->posX = x;
1419 const_cast<CreatureData*>(data)->posY = y;
1420 const_cast<CreatureData*>(data)->posZ = z;
1421 const_cast<CreatureData*>(data)->orientation = o;
1423 pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
1424 pCreature->GetMotionMaster()->Initialize();
1425 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1427 pCreature->setDeathState(JUST_DIED);
1428 pCreature->Respawn();
1432 WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1433 PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1434 return true;
1437 /**HandleNpcSetMoveTypeCommand
1438 * Set the movement type for an NPC.<br/>
1439 * <br/>
1440 * Valid movement types are:
1441 * <ul>
1442 * <li> stay - NPC wont move </li>
1443 * <li> random - NPC will move randomly according to the spawndist </li>
1444 * <li> way - NPC will move with given waypoints set </li>
1445 * </ul>
1446 * additional parameter: NODEL - so no waypoints are deleted, if you
1447 * change the movement type
1449 bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
1451 if(!*args)
1452 return false;
1454 // 3 arguments:
1455 // GUID (optional - you can also select the creature)
1456 // stay|random|way (determines the kind of movement)
1457 // NODEL (optional - tells the system NOT to delete any waypoints)
1458 // this is very handy if you want to do waypoints, that are
1459 // later switched on/off according to special events (like escort
1460 // quests, etc)
1461 char* guid_str = strtok((char*)args, " ");
1462 char* type_str = strtok((char*)NULL, " ");
1463 char* dontdel_str = strtok((char*)NULL, " ");
1465 bool doNotDelete = false;
1467 if(!guid_str)
1468 return false;
1470 uint32 lowguid = 0;
1471 Creature* pCreature = NULL;
1473 if( dontdel_str )
1475 //sLog.outError("DEBUG: All 3 params are set");
1477 // All 3 params are set
1478 // GUID
1479 // type
1480 // doNotDEL
1481 if( stricmp( dontdel_str, "NODEL" ) == 0 )
1483 //sLog.outError("DEBUG: doNotDelete = true;");
1484 doNotDelete = true;
1487 else
1489 // Only 2 params - but maybe NODEL is set
1490 if( type_str )
1492 sLog.outError("DEBUG: Only 2 params ");
1493 if( stricmp( type_str, "NODEL" ) == 0 )
1495 //sLog.outError("DEBUG: type_str, NODEL ");
1496 doNotDelete = true;
1497 type_str = NULL;
1502 if(!type_str) // case .setmovetype $move_type (with selected creature)
1504 type_str = guid_str;
1505 pCreature = getSelectedCreature();
1506 if(!pCreature || pCreature->isPet())
1507 return false;
1508 lowguid = pCreature->GetDBTableGUIDLow();
1510 else // case .setmovetype #creature_guid $move_type (with selected creature)
1512 lowguid = atoi((char*)guid_str);
1514 /* impossible without entry
1515 if(lowguid)
1516 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1519 // attempt check creature existence by DB data
1520 if(!pCreature)
1522 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
1523 if(!data)
1525 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1526 SetSentErrorMessage(true);
1527 return false;
1530 else
1532 lowguid = pCreature->GetDBTableGUIDLow();
1536 // now lowguid is low guid really existed creature
1537 // and pCreature point (maybe) to this creature or NULL
1539 MovementGeneratorType move_type;
1541 std::string type = type_str;
1543 if(type == "stay")
1544 move_type = IDLE_MOTION_TYPE;
1545 else if(type == "random")
1546 move_type = RANDOM_MOTION_TYPE;
1547 else if(type == "way")
1548 move_type = WAYPOINT_MOTION_TYPE;
1549 else
1550 return false;
1552 // update movement type
1553 if(doNotDelete == false)
1554 sWaypointMgr.DeletePath(lowguid);
1556 if(pCreature)
1558 pCreature->SetDefaultMovementType(move_type);
1559 pCreature->GetMotionMaster()->Initialize();
1560 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1562 pCreature->setDeathState(JUST_DIED);
1563 pCreature->Respawn();
1565 pCreature->SaveToDB();
1567 if( doNotDelete == false )
1569 PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1571 else
1573 PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1576 return true;
1579 //set model of creature
1580 bool ChatHandler::HandleNpcSetModelCommand(const char* args)
1582 if (!*args)
1583 return false;
1585 uint32 displayId = (uint32) atoi((char*)args);
1587 Creature *pCreature = getSelectedCreature();
1589 if(!pCreature || pCreature->isPet())
1591 SendSysMessage(LANG_SELECT_CREATURE);
1592 SetSentErrorMessage(true);
1593 return false;
1596 pCreature->SetDisplayId(displayId);
1597 pCreature->SetNativeDisplayId(displayId);
1599 pCreature->SaveToDB();
1601 return true;
1603 //set faction of creature
1604 bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
1606 if (!*args)
1607 return false;
1609 uint32 factionId = (uint32) atoi((char*)args);
1611 if (!sFactionTemplateStore.LookupEntry(factionId))
1613 PSendSysMessage(LANG_WRONG_FACTION, factionId);
1614 SetSentErrorMessage(true);
1615 return false;
1618 Creature* pCreature = getSelectedCreature();
1620 if(!pCreature)
1622 SendSysMessage(LANG_SELECT_CREATURE);
1623 SetSentErrorMessage(true);
1624 return false;
1627 pCreature->setFaction(factionId);
1629 // faction is set in creature_template - not inside creature
1631 // update in memory
1632 if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1634 const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1635 const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1638 // and DB
1639 WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1641 return true;
1643 //set spawn dist of creature
1644 bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
1646 if(!*args)
1647 return false;
1649 float option = (float)atof((char*)args);
1650 if (option < 0.0f)
1652 SendSysMessage(LANG_BAD_VALUE);
1653 return false;
1656 MovementGeneratorType mtype = IDLE_MOTION_TYPE;
1657 if (option >0.0f)
1658 mtype = RANDOM_MOTION_TYPE;
1660 Creature *pCreature = getSelectedCreature();
1661 uint32 u_guidlow = 0;
1663 if (pCreature)
1664 u_guidlow = pCreature->GetDBTableGUIDLow();
1665 else
1666 return false;
1668 pCreature->SetRespawnRadius((float)option);
1669 pCreature->SetDefaultMovementType(mtype);
1670 pCreature->GetMotionMaster()->Initialize();
1671 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1673 pCreature->setDeathState(JUST_DIED);
1674 pCreature->Respawn();
1677 WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
1678 PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
1679 return true;
1681 //spawn time handling
1682 bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
1684 if(!*args)
1685 return false;
1687 char* stime = strtok((char*)args, " ");
1689 if (!stime)
1690 return false;
1692 int i_stime = atoi((char*)stime);
1694 if (i_stime < 0)
1696 SendSysMessage(LANG_BAD_VALUE);
1697 SetSentErrorMessage(true);
1698 return false;
1701 Creature *pCreature = getSelectedCreature();
1702 uint32 u_guidlow = 0;
1704 if (pCreature)
1705 u_guidlow = pCreature->GetDBTableGUIDLow();
1706 else
1707 return false;
1709 WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
1710 pCreature->SetRespawnDelay((uint32)i_stime);
1711 PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
1713 return true;
1715 //npc follow handling
1716 bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
1718 Player *player = m_session->GetPlayer();
1719 Creature *creature = getSelectedCreature();
1721 if(!creature)
1723 PSendSysMessage(LANG_SELECT_CREATURE);
1724 SetSentErrorMessage(true);
1725 return false;
1728 // Follow player - Using pet's default dist and angle
1729 creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
1731 PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
1732 return true;
1734 //npc unfollow handling
1735 bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
1737 Player *player = m_session->GetPlayer();
1738 Creature *creature = getSelectedCreature();
1740 if(!creature)
1742 PSendSysMessage(LANG_SELECT_CREATURE);
1743 SetSentErrorMessage(true);
1744 return false;
1747 if (creature->GetMotionMaster()->empty() ||
1748 creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=FOLLOW_MOTION_TYPE)
1750 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
1751 SetSentErrorMessage(true);
1752 return false;
1755 FollowMovementGenerator<Creature> const* mgen
1756 = static_cast<FollowMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
1758 if(mgen->GetTarget()!=player)
1760 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
1761 SetSentErrorMessage(true);
1762 return false;
1765 // reset movement
1766 creature->GetMotionMaster()->MovementExpired(true);
1768 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
1769 return true;
1771 //npc tame handling
1772 bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
1774 Creature *creatureTarget = getSelectedCreature ();
1775 if (!creatureTarget || creatureTarget->isPet ())
1777 PSendSysMessage (LANG_SELECT_CREATURE);
1778 SetSentErrorMessage (true);
1779 return false;
1782 Player *player = m_session->GetPlayer ();
1784 if(player->GetPetGUID ())
1786 SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
1787 SetSentErrorMessage (true);
1788 return false;
1791 CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
1793 if (!cInfo->isTameable (player->CanTameExoticPets()))
1795 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
1796 SetSentErrorMessage (true);
1797 return false;
1800 // Everything looks OK, create new pet
1801 Pet* pet = player->CreateTamedPetFrom (creatureTarget);
1802 if (!pet)
1804 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
1805 SetSentErrorMessage (true);
1806 return false;
1809 // place pet before player
1810 float x,y,z;
1811 player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
1812 pet->Relocate (x,y,z,M_PI_F-player->GetOrientation ());
1814 // set pet to defensive mode by default (some classes can't control controlled pets in fact).
1815 pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
1817 // calculate proper level
1818 uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
1820 // prepare visual effect for levelup
1821 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
1823 // add to world
1824 pet->GetMap()->Add((Creature*)pet);
1826 // visual effect for levelup
1827 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
1829 // caster have pet now
1830 player->SetPet(pet);
1832 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
1833 player->PetSpellInitialize();
1835 return true;
1837 //npc phasemask handling
1838 //change phasemask of creature or pet
1839 bool ChatHandler::HandleNpcSetPhaseCommand(const char* args)
1841 if (!*args)
1842 return false;
1844 uint32 phasemask = (uint32) atoi((char*)args);
1845 if ( phasemask == 0 )
1847 SendSysMessage(LANG_BAD_VALUE);
1848 SetSentErrorMessage(true);
1849 return false;
1852 Creature* pCreature = getSelectedCreature();
1853 if(!pCreature)
1855 SendSysMessage(LANG_SELECT_CREATURE);
1856 SetSentErrorMessage(true);
1857 return false;
1860 pCreature->SetPhaseMask(phasemask,true);
1862 if(!pCreature->isPet())
1863 pCreature->SaveToDB();
1865 return true;
1867 //npc deathstate handling
1868 bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args)
1870 if (!*args)
1871 return false;
1873 Creature* pCreature = getSelectedCreature();
1874 if(!pCreature || pCreature->isPet())
1876 SendSysMessage(LANG_SELECT_CREATURE);
1877 SetSentErrorMessage(true);
1878 return false;
1881 if (strncmp(args, "on", 3) == 0)
1882 pCreature->SetDeadByDefault(true);
1883 else if (strncmp(args, "off", 4) == 0)
1884 pCreature->SetDeadByDefault(false);
1885 else
1887 SendSysMessage(LANG_USE_BOL);
1888 SetSentErrorMessage(true);
1889 return false;
1892 pCreature->SaveToDB();
1893 pCreature->Respawn();
1895 return true;
1898 //TODO: NpcCommands that need to be fixed :
1900 bool ChatHandler::HandleNpcNameCommand(const char* /*args*/)
1902 /* Temp. disabled
1903 if(!*args)
1904 return false;
1906 if(strlen((char*)args)>75)
1908 PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
1909 return true;
1912 for (uint8 i = 0; i < strlen(args); ++i)
1914 if(!isalpha(args[i]) && args[i]!=' ')
1916 SendSysMessage(LANG_CHARS_ONLY);
1917 return false;
1921 uint64 guid;
1922 guid = m_session->GetPlayer()->GetSelection();
1923 if (guid == 0)
1925 SendSysMessage(LANG_NO_SELECTION);
1926 return true;
1929 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
1931 if(!pCreature)
1933 SendSysMessage(LANG_SELECT_CREATURE);
1934 return true;
1937 pCreature->SetName(args);
1938 uint32 idname = sObjectMgr.AddCreatureTemplate(pCreature->GetName());
1939 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
1941 pCreature->SaveToDB();
1944 return true;
1947 bool ChatHandler::HandleNpcSubNameCommand(const char* /*args*/)
1949 /* Temp. disabled
1951 if(!*args)
1952 args = "";
1954 if(strlen((char*)args)>75)
1957 PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
1958 return true;
1961 for (uint8 i = 0; i < strlen(args); i++)
1963 if(!isalpha(args[i]) && args[i]!=' ')
1965 SendSysMessage(LANG_CHARS_ONLY);
1966 return false;
1969 uint64 guid;
1970 guid = m_session->GetPlayer()->GetSelection();
1971 if (guid == 0)
1973 SendSysMessage(LANG_NO_SELECTION);
1974 return true;
1977 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
1979 if(!pCreature)
1981 SendSysMessage(LANG_SELECT_CREATURE);
1982 return true;
1985 uint32 idname = sObjectMgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
1986 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
1988 pCreature->SaveToDB();
1990 return true;
1993 //move item to other slot
1994 bool ChatHandler::HandleItemMoveCommand(const char* args)
1996 if(!*args)
1997 return false;
1998 uint8 srcslot, dstslot;
2000 char* pParam1 = strtok((char*)args, " ");
2001 if (!pParam1)
2002 return false;
2004 char* pParam2 = strtok(NULL, " ");
2005 if (!pParam2)
2006 return false;
2008 srcslot = (uint8)atoi(pParam1);
2009 dstslot = (uint8)atoi(pParam2);
2011 if(srcslot==dstslot)
2012 return true;
2014 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true))
2015 return false;
2017 // can be autostore pos
2018 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot, false))
2019 return false;
2021 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
2022 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
2024 m_session->GetPlayer()->SwapItem( src, dst );
2026 return true;
2029 //demorph player or unit
2030 bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
2032 Unit *target = getSelectedUnit();
2033 if(!target)
2034 target = m_session->GetPlayer();
2037 // check online security
2038 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2039 return false;
2041 target->DeMorph();
2043 return true;
2046 //morph creature or player
2047 bool ChatHandler::HandleModifyMorphCommand(const char* args)
2049 if (!*args)
2050 return false;
2052 uint16 display_id = (uint16)atoi((char*)args);
2054 Unit *target = getSelectedUnit();
2055 if(!target)
2056 target = m_session->GetPlayer();
2058 // check online security
2059 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2060 return false;
2062 target->SetDisplayId(display_id);
2064 return true;
2067 //kick player
2068 bool ChatHandler::HandleKickPlayerCommand(const char *args)
2070 Player* target;
2071 if(!extractPlayerTarget((char*)args,&target))
2072 return false;
2074 if (m_session && target==m_session->GetPlayer())
2076 SendSysMessage(LANG_COMMAND_KICKSELF);
2077 SetSentErrorMessage(true);
2078 return false;
2081 // check online security
2082 if (HasLowerSecurity(target, 0))
2083 return false;
2085 // send before target pointer invalidate
2086 PSendSysMessage(LANG_COMMAND_KICKMESSAGE,GetNameLink(target).c_str());
2087 target->GetSession()->KickPlayer();
2088 return true;
2091 //set temporary phase mask for player
2092 bool ChatHandler::HandleModifyPhaseCommand(const char* args)
2094 if (!*args)
2095 return false;
2097 uint32 phasemask = (uint32)atoi((char*)args);
2099 Unit *target = getSelectedUnit();
2100 if(!target)
2101 target = m_session->GetPlayer();
2103 // check online security
2104 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2105 return false;
2107 target->SetPhaseMask(phasemask,true);
2109 return true;
2112 //show info of player
2113 bool ChatHandler::HandlePInfoCommand(const char* args)
2115 Player* target;
2116 uint64 target_guid;
2117 std::string target_name;
2118 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
2119 return false;
2121 uint32 accId = 0;
2122 uint32 money = 0;
2123 uint32 total_player_time = 0;
2124 uint32 level = 0;
2125 uint32 latency = 0;
2127 // get additional information from Player object
2128 if(target)
2130 // check online security
2131 if (HasLowerSecurity(target, 0))
2132 return false;
2134 accId = target->GetSession()->GetAccountId();
2135 money = target->GetMoney();
2136 total_player_time = target->GetTotalPlayedTime();
2137 level = target->getLevel();
2138 latency = target->GetSession()->GetLatency();
2140 // get additional information from DB
2141 else
2143 // check offline security
2144 if (HasLowerSecurity(NULL, target_guid))
2145 return false;
2147 // 0 1 2 3
2148 QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime, level, money, account FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid));
2149 if (!result)
2150 return false;
2152 Field *fields = result->Fetch();
2153 total_player_time = fields[0].GetUInt32();
2154 level = fields[1].GetUInt32();
2155 money = fields[2].GetUInt32();
2156 accId = fields[3].GetUInt32();
2157 delete result;
2160 std::string username = GetMangosString(LANG_ERROR);
2161 std::string last_ip = GetMangosString(LANG_ERROR);
2162 AccountTypes security = SEC_PLAYER;
2163 std::string last_login = GetMangosString(LANG_ERROR);
2165 QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
2166 if(result)
2168 Field* fields = result->Fetch();
2169 username = fields[0].GetCppString();
2170 security = (AccountTypes)fields[1].GetUInt32();
2172 if(GetAccessLevel() >= security)
2174 last_ip = fields[2].GetCppString();
2175 last_login = fields[3].GetCppString();
2177 else
2179 last_ip = "-";
2180 last_login = "-";
2183 delete result;
2186 std::string nameLink = playerLink(target_name);
2188 PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetMangosString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(target_guid), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency);
2190 std::string timeStr = secsToTimeString(total_player_time,true,true);
2191 uint32 gold = money /GOLD;
2192 uint32 silv = (money % GOLD) / SILVER;
2193 uint32 copp = (money % GOLD) % SILVER;
2194 PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp );
2196 return true;
2199 //show tickets
2200 void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
2202 std::string name;
2203 if(!sObjectMgr.GetPlayerNameByGUID(guid,name))
2204 name = GetMangosString(LANG_UNKNOWN);
2206 std::string nameLink = playerLink(name);
2208 PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(),time,text);
2211 //ticket commands
2212 bool ChatHandler::HandleTicketCommand(const char* args)
2214 char* px = strtok((char*)args, " ");
2216 // ticket<end>
2217 if (!px)
2219 if(!m_session)
2221 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2222 SetSentErrorMessage(true);
2223 return false;
2226 size_t count = sTicketMgr.GetTicketCount();
2228 bool accept = m_session->GetPlayer()->isAcceptTickets();
2230 PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
2231 return true;
2234 // ticket on
2235 if(strncmp(px,"on",3) == 0)
2237 if(!m_session)
2239 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2240 SetSentErrorMessage(true);
2241 return false;
2244 m_session->GetPlayer()->SetAcceptTicket(true);
2245 SendSysMessage(LANG_COMMAND_TICKETON);
2246 return true;
2249 // ticket off
2250 if(strncmp(px,"off",4) == 0)
2252 if(!m_session)
2254 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2255 SetSentErrorMessage(true);
2256 return false;
2259 m_session->GetPlayer()->SetAcceptTicket(false);
2260 SendSysMessage(LANG_COMMAND_TICKETOFF);
2261 return true;
2264 // ticket respond
2265 if(strncmp(px,"respond",8) == 0)
2267 char *name = strtok(NULL, " ");
2269 if(!name)
2271 SendSysMessage(LANG_CMD_SYNTAX);
2272 SetSentErrorMessage(true);
2273 return false;
2276 std::string plName = name;
2277 uint64 guid = sObjectMgr.GetPlayerGUIDByName(plName);
2279 if(!guid)
2281 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2282 SetSentErrorMessage(true);
2283 return false;
2286 GMTicket* ticket = sTicketMgr.GetGMTicket(GUID_LOPART(guid));
2288 if(!ticket)
2290 PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, GUID_LOPART(guid));
2291 SetSentErrorMessage(true);
2292 return false;
2295 char* response = strtok(NULL, "");
2297 if(!response)
2299 SendSysMessage(LANG_CMD_SYNTAX);
2300 SetSentErrorMessage(true);
2301 return false;
2304 ticket->SetResponseText(response);
2306 if(Player* pl = sObjectMgr.GetPlayer(guid))
2307 pl->GetSession()->SendGMResponse(ticket);
2309 return true;
2312 // ticket #num
2313 int num = atoi(px);
2314 if(num > 0)
2316 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
2318 if(!result)
2320 PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num);
2321 SetSentErrorMessage(true);
2322 return false;
2325 Field* fields = result->Fetch();
2327 uint32 guid = fields[0].GetUInt32();
2328 char const* text = fields[1].GetString();
2329 char const* time = fields[2].GetString();
2331 ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
2332 delete result;
2333 return true;
2336 uint64 target_guid;
2337 if(!extractPlayerTarget(px,NULL,&target_guid))
2338 return false;
2340 // ticket $char_name
2341 GMTicket* ticket = sTicketMgr.GetGMTicket(GUID_LOPART(target_guid));
2342 if(!ticket)
2343 return false;
2345 std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
2347 ShowTicket(target_guid, ticket->GetText(), time.c_str());
2349 return true;
2352 //dell all tickets
2353 bool ChatHandler::HandleDelTicketCommand(const char *args)
2355 char* px = strtok((char*)args, " ");
2356 if (!px)
2357 return false;
2359 // delticket all
2360 if(strncmp(px,"all",4) == 0)
2362 sTicketMgr.DeleteAll();
2363 SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2364 return true;
2367 int num = (uint32)atoi(px);
2369 // delticket #num
2370 if(num > 0)
2372 QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2373 if(!result)
2375 PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num);
2376 SetSentErrorMessage(true);
2377 return false;
2379 Field* fields = result->Fetch();
2380 uint32 guid = fields[0].GetUInt32();
2381 delete result;
2383 sTicketMgr.Delete(guid);
2385 //notify player
2386 if(Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, guid)))
2388 pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
2389 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str());
2391 else
2392 PSendSysMessage(LANG_COMMAND_TICKETDEL);
2394 return true;
2397 Player* target;
2398 uint64 target_guid;
2399 std::string target_name;
2400 if(!extractPlayerTarget(px,&target,&target_guid,&target_name))
2401 return false;
2403 // delticket $char_name
2404 sTicketMgr.Delete(GUID_LOPART(target_guid));
2406 // notify players about ticket deleting
2407 if(target)
2408 target->GetSession()->SendGMTicketGetTicket(0x0A,0);
2410 std::string nameLink = playerLink(target_name);
2412 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,nameLink.c_str());
2413 return true;
2417 * Add a waypoint to a creature.
2419 * The user can either select an npc or provide its GUID.
2421 * The user can even select a visual waypoint - then the new waypoint
2422 * is placed *after* the selected one - this makes insertion of new
2423 * waypoints possible.
2425 * eg:
2426 * .wp add 12345
2427 * -> adds a waypoint to the npc with the GUID 12345
2429 * .wp add
2430 * -> adds a waypoint to the currently selected creature
2433 * @param args if the user did not provide a GUID, it is NULL
2435 * @return true - command did succeed, false - something went wrong
2437 bool ChatHandler::HandleWpAddCommand(const char* args)
2439 sLog.outDebug("DEBUG: HandleWpAddCommand");
2441 // optional
2442 char* guid_str = NULL;
2444 if(*args)
2446 guid_str = strtok((char*)args, " ");
2449 uint32 lowguid = 0;
2450 uint32 point = 0;
2451 Creature* target = getSelectedCreature();
2452 // Did player provide a GUID?
2453 if (!guid_str)
2455 sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2457 // No GUID provided
2458 // -> Player must have selected a creature
2460 if(!target || target->isPet())
2462 SendSysMessage(LANG_SELECT_CREATURE);
2463 SetSentErrorMessage(true);
2464 return false;
2466 if (target->GetEntry() == VISUAL_WAYPOINT )
2468 sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2470 QueryResult *result =
2471 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2472 target->GetGUIDLow() );
2473 if(!result)
2475 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2476 // User selected a visual spawnpoint -> get the NPC
2477 // Select NPC GUID
2478 // Since we compare float values, we have to deal with
2479 // some difficulties.
2480 // Here we search for all waypoints that only differ in one from 1 thousand
2481 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2482 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2483 const char* maxDIFF = "0.01";
2484 result = WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
2485 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2486 if(!result)
2488 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2489 SetSentErrorMessage(true);
2490 return false;
2495 Field *fields = result->Fetch();
2496 lowguid = fields[0].GetUInt32();
2497 point = fields[1].GetUInt32();
2498 }while( result->NextRow() );
2499 delete result;
2501 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2502 if(!data)
2504 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2505 SetSentErrorMessage(true);
2506 return false;
2509 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2510 if(!target)
2512 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2513 SetSentErrorMessage(true);
2514 return false;
2517 else
2519 lowguid = target->GetDBTableGUIDLow();
2522 else
2524 sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2526 // GUID provided
2527 // Warn if player also selected a creature
2528 // -> Creature selection is ignored <-
2529 if(target)
2531 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2533 lowguid = atoi((char*)guid_str);
2535 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2536 if(!data)
2538 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2539 SetSentErrorMessage(true);
2540 return false;
2543 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2544 if(!target || target->isPet())
2546 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2547 SetSentErrorMessage(true);
2548 return false;
2551 // lowguid -> GUID of the NPC
2552 // point -> number of the waypoint (if not 0)
2553 sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2555 sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2557 Player* player = m_session->GetPlayer();
2558 sWaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2560 // update movement type
2561 if(target)
2563 target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2564 target->GetMotionMaster()->Initialize();
2565 if(target->isAlive()) // dead creature will reset movement generator at respawn
2567 target->setDeathState(JUST_DIED);
2568 target->Respawn();
2570 target->SaveToDB();
2572 else
2573 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2575 PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2577 return true;
2578 } // HandleWpAddCommand
2581 * .wp modify emote | spell | text | del | move | add
2583 * add -> add a WP after the selected visual waypoint
2584 * User must select a visual waypoint and then issue ".wp modify add"
2586 * emote <emoteID>
2587 * User has selected a visual waypoint before.
2588 * <emoteID> is added to this waypoint. Everytime the
2589 * NPC comes to this waypoint, the emote is called.
2591 * emote <GUID> <WPNUM> <emoteID>
2592 * User has not selected visual waypoint before.
2593 * For the waypoint <WPNUM> for the NPC with <GUID>
2594 * an emote <emoteID> is added.
2595 * Everytime the NPC comes to this waypoint, the emote is called.
2598 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2600 bool ChatHandler::HandleWpModifyCommand(const char* args)
2602 sLog.outDebug("DEBUG: HandleWpModifyCommand");
2604 if(!*args)
2605 return false;
2607 // first arg: add del text emote spell waittime move
2608 char* show_str = strtok((char*)args, " ");
2609 if (!show_str)
2611 return false;
2614 std::string show = show_str;
2615 // Check
2616 // Remember: "show" must also be the name of a column!
2617 if( (show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2")
2618 && (show != "textid3") && (show != "textid4") && (show != "textid5")
2619 && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2620 && (show != "model1") && (show != "model2") && (show != "orientation"))
2622 return false;
2625 // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2627 // Did user provide a GUID
2628 // or did the user select a creature?
2629 // -> variable lowguid is filled with the GUID of the NPC
2630 uint32 lowguid = 0;
2631 uint32 point = 0;
2632 uint32 wpGuid = 0;
2633 Creature* target = getSelectedCreature();
2635 if(target)
2637 sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2639 // Did the user select a visual spawnpoint?
2640 if (target->GetEntry() != VISUAL_WAYPOINT )
2642 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2643 SetSentErrorMessage(true);
2644 return false;
2647 wpGuid = target->GetGUIDLow();
2649 // The visual waypoint
2650 QueryResult *result =
2651 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2652 target->GetGUIDLow() );
2653 if(!result)
2655 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2656 SetSentErrorMessage(true);
2657 return false;
2659 sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2661 Field *fields = result->Fetch();
2662 lowguid = fields[0].GetUInt32();
2663 point = fields[1].GetUInt32();
2665 // Cleanup memory
2666 sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2667 delete result;
2669 else
2671 // User did provide <GUID> <WPNUM>
2673 char* guid_str = strtok((char*)NULL, " ");
2674 if( !guid_str )
2676 SendSysMessage(LANG_WAYPOINT_NOGUID);
2677 return false;
2679 lowguid = atoi((char*)guid_str);
2681 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2682 if(!data)
2684 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2685 SetSentErrorMessage(true);
2686 return false;
2689 PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2691 char* point_str = strtok((char*)NULL, " ");
2692 if( !point_str )
2694 SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2695 return false;
2697 point = atoi((char*)point_str);
2699 PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2701 // Now we need the GUID of the visual waypoint
2702 // -> "del", "move", "add" command
2704 QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2705 if (!result)
2707 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2708 SetSentErrorMessage(true);
2709 return false;
2712 Field *fields = result->Fetch();
2713 wpGuid = fields[0].GetUInt32();
2715 // Free memory
2716 delete result;
2719 char* arg_str = NULL;
2720 // Check for argument
2721 if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2723 // Text is enclosed in "<>", all other arguments not
2724 if( show.find("text") != std::string::npos )
2725 arg_str = strtok((char*)NULL, "<>");
2726 else
2727 arg_str = strtok((char*)NULL, " ");
2729 if( !arg_str)
2731 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2732 return false;
2736 sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2738 // wpGuid -> GUID of the waypoint creature
2739 // lowguid -> GUID of the NPC
2740 // point -> waypoint number
2742 // Special functions:
2743 // add - move - del -> no args commands
2744 // Add a waypoint after the selected visual
2745 if(show == "add" && target)
2747 PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2749 // Get the creature for which we read the waypoint
2750 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2751 if(!data)
2753 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2754 SetSentErrorMessage(true);
2755 return false;
2758 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2760 if( !npcCreature )
2762 PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2763 SetSentErrorMessage(true);
2764 return false;
2767 sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2769 // What to do:
2770 // Add the visual spawnpoint (DB only)
2771 // Adjust the waypoints
2772 // Respawn the owner of the waypoints
2773 sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2775 Player* chr = m_session->GetPlayer();
2776 Map *map = chr->GetMap();
2778 if(npcCreature)
2780 npcCreature->GetMotionMaster()->Initialize();
2781 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2783 npcCreature->setDeathState(JUST_DIED);
2784 npcCreature->Respawn();
2788 // create the waypoint creature
2789 wpGuid = 0;
2790 Creature* wpCreature = new Creature;
2791 if (!wpCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT,0))
2793 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2794 delete wpCreature;
2796 else
2798 wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2800 if(!wpCreature->IsPositionValid())
2802 sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY());
2803 delete wpCreature;
2805 else
2807 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
2808 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2809 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2810 map->Add(wpCreature);
2811 wpGuid = wpCreature->GetGUIDLow();
2815 sWaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2817 if(!wpGuid)
2818 return false;
2820 PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2821 return true;
2822 } // add
2824 if(show == "del" && target)
2826 PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2828 // Get the creature for which we read the waypoint
2829 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2830 if(!data)
2832 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2833 SetSentErrorMessage(true);
2834 return false;
2837 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2839 // wpCreature
2840 Creature* wpCreature = NULL;
2841 if( wpGuid != 0 )
2843 wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2844 wpCreature->DeleteFromDB();
2845 wpCreature->AddObjectToRemoveList();
2848 // What to do:
2849 // Remove the visual spawnpoint
2850 // Adjust the waypoints
2851 // Respawn the owner of the waypoints
2853 sWaypointMgr.DeleteNode(lowguid, point);
2855 if(npcCreature)
2857 // Any waypoints left?
2858 QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2859 if(!result2)
2861 npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2863 else
2865 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2866 delete result2;
2868 npcCreature->GetMotionMaster()->Initialize();
2869 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2871 npcCreature->setDeathState(JUST_DIED);
2872 npcCreature->Respawn();
2874 npcCreature->SaveToDB();
2877 PSendSysMessage(LANG_WAYPOINT_REMOVED);
2878 return true;
2879 } // del
2881 if(show == "move" && target)
2883 PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2885 Player *chr = m_session->GetPlayer();
2886 Map *map = chr->GetMap();
2888 // Get the creature for which we read the waypoint
2889 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2890 if(!data)
2892 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2893 SetSentErrorMessage(true);
2894 return false;
2897 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2899 // wpCreature
2900 Creature* wpCreature = NULL;
2901 // What to do:
2902 // Move the visual spawnpoint
2903 // Respawn the owner of the waypoints
2904 if( wpGuid != 0 )
2906 wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2907 wpCreature->DeleteFromDB();
2908 wpCreature->AddObjectToRemoveList();
2909 // re-create
2910 Creature* wpCreature2 = new Creature;
2911 if (!wpCreature2->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0))
2913 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2914 delete wpCreature2;
2915 return false;
2918 wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2920 if(!wpCreature2->IsPositionValid())
2922 sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature2->GetGUIDLow(),wpCreature2->GetEntry(),wpCreature2->GetPositionX(),wpCreature2->GetPositionY());
2923 delete wpCreature2;
2924 return false;
2927 wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
2928 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2929 wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2930 map->Add(wpCreature2);
2931 //npcCreature->GetMap()->Add(wpCreature2);
2934 sWaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2936 if(npcCreature)
2938 npcCreature->GetMotionMaster()->Initialize();
2939 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2941 npcCreature->setDeathState(JUST_DIED);
2942 npcCreature->Respawn();
2945 PSendSysMessage(LANG_WAYPOINT_CHANGED);
2947 return true;
2948 } // move
2950 // Create creature - npc that has the waypoint
2951 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2952 if(!data)
2954 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2955 SetSentErrorMessage(true);
2956 return false;
2959 // set in game textids not supported
2960 if( show == "textid1" || show == "textid2" || show == "textid3" ||
2961 show == "textid4" || show == "textid5" )
2963 return false;
2966 sWaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2968 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2969 if(npcCreature)
2971 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2972 npcCreature->GetMotionMaster()->Initialize();
2973 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2975 npcCreature->setDeathState(JUST_DIED);
2976 npcCreature->Respawn();
2979 PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2981 return true;
2985 * .wp show info | on | off
2987 * info -> User has selected a visual waypoint before
2989 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2990 * provided the GUID of the NPC and the number of
2991 * the waypoint.
2993 * on -> User has selected an NPC; all visual waypoints for this
2994 * NPC are added to the world
2996 * on <GUID> -> User did not select an NPC - instead the GUID of the
2997 * NPC is provided. All visual waypoints for this NPC
2998 * are added from the world.
3000 * off -> User has selected an NPC; all visual waypoints for this
3001 * NPC are removed from the world.
3003 * on <GUID> -> User did not select an NPC - instead the GUID of the
3004 * NPC is provided. All visual waypoints for this NPC
3005 * are removed from the world.
3009 bool ChatHandler::HandleWpShowCommand(const char* args)
3011 sLog.outDebug("DEBUG: HandleWpShowCommand");
3013 if(!*args)
3014 return false;
3016 // first arg: on, off, first, last
3017 char* show_str = strtok((char*)args, " ");
3018 if (!show_str)
3020 return false;
3022 // second arg: GUID (optional, if a creature is selected)
3023 char* guid_str = strtok((char*)NULL, " ");
3024 sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
3025 //if (!guid_str) {
3026 // return false;
3029 // Did user provide a GUID
3030 // or did the user select a creature?
3031 // -> variable lowguid is filled with the GUID
3032 Creature* target = getSelectedCreature();
3033 // Did player provide a GUID?
3034 if (!guid_str)
3036 sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
3037 // No GUID provided
3038 // -> Player must have selected a creature
3040 if(!target)
3042 SendSysMessage(LANG_SELECT_CREATURE);
3043 SetSentErrorMessage(true);
3044 return false;
3047 else
3049 sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
3050 // GUID provided
3051 // Warn if player also selected a creature
3052 // -> Creature selection is ignored <-
3053 if(target)
3055 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
3058 uint32 lowguid = atoi((char*)guid_str);
3060 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
3061 if(!data)
3063 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
3064 SetSentErrorMessage(true);
3065 return false;
3068 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
3070 if(!target)
3072 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
3073 SetSentErrorMessage(true);
3074 return false;
3078 uint32 lowguid = target->GetDBTableGUIDLow();
3080 std::string show = show_str;
3081 uint32 Maxpoint;
3083 sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
3085 // Show info for the selected waypoint
3086 if(show == "info")
3088 PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
3090 // Check if the user did specify a visual waypoint
3091 if( target->GetEntry() != VISUAL_WAYPOINT )
3093 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
3094 SetSentErrorMessage(true);
3095 return false;
3098 //PSendSysMessage("wp on, GUID: %u", lowguid);
3100 //pCreature->GetPositionX();
3102 QueryResult *result =
3103 WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u",
3104 target->GetGUIDLow() );
3105 if(!result)
3107 // Since we compare float values, we have to deal with
3108 // some difficulties.
3109 // Here we search for all waypoints that only differ in one from 1 thousand
3110 // (0.001) - There is no other way to compare C++ floats with mySQL floats
3111 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
3112 const char* maxDIFF = "0.01";
3113 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
3115 result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
3116 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
3117 if(!result)
3119 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
3120 SetSentErrorMessage(true);
3121 return false;
3126 Field *fields = result->Fetch();
3127 uint32 creGUID = fields[0].GetUInt32();
3128 uint32 point = fields[1].GetUInt32();
3129 int waittime = fields[2].GetUInt32();
3130 uint32 emote = fields[3].GetUInt32();
3131 uint32 spell = fields[4].GetUInt32();
3132 uint32 textid[MAX_WAYPOINT_TEXT];
3133 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
3134 textid[i] = fields[5+i].GetUInt32();
3135 uint32 model1 = fields[10].GetUInt32();
3136 uint32 model2 = fields[11].GetUInt32();
3138 // Get the creature for which we read the waypoint
3139 Creature* wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3141 PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
3142 PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
3143 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
3144 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
3145 PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
3146 PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
3147 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
3148 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i+1, textid[i], (textid[i] ? GetMangosString(textid[i]) : ""));
3150 }while( result->NextRow() );
3151 // Cleanup memory
3152 delete result;
3153 return true;
3156 if(show == "on")
3158 PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
3160 QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
3161 if(!result)
3163 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3164 SetSentErrorMessage(true);
3165 return false;
3167 // Delete all visuals for this NPC
3168 QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
3169 if(result2)
3171 bool hasError = false;
3174 Field *fields = result2->Fetch();
3175 uint32 wpguid = fields[0].GetUInt32();
3176 Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3178 if(!pCreature)
3180 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
3181 hasError = true;
3182 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
3184 else
3186 pCreature->DeleteFromDB();
3187 pCreature->AddObjectToRemoveList();
3190 }while( result2->NextRow() );
3191 delete result2;
3192 if( hasError )
3194 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3195 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3196 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3202 Field *fields = result->Fetch();
3203 uint32 point = fields[0].GetUInt32();
3204 float x = fields[1].GetFloat();
3205 float y = fields[2].GetFloat();
3206 float z = fields[3].GetFloat();
3208 uint32 id = VISUAL_WAYPOINT;
3210 Player *chr = m_session->GetPlayer();
3211 Map *map = chr->GetMap();
3212 float o = chr->GetOrientation();
3214 Creature* wpCreature = new Creature;
3215 if (!wpCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
3217 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3218 delete wpCreature;
3219 delete result;
3220 return false;
3223 wpCreature->Relocate(x, y, z, o);
3225 if(!wpCreature->IsPositionValid())
3227 sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY());
3228 delete wpCreature;
3229 delete result;
3230 return false;
3233 wpCreature->SetVisibility(VISIBILITY_OFF);
3234 sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u", wpCreature->GetGUIDLow());
3235 // set "wpguid" column to the visual waypoint
3236 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
3238 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3239 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
3240 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
3241 map->Add(wpCreature);
3242 //wpCreature->GetMap()->Add(wpCreature);
3243 }while( result->NextRow() );
3245 // Cleanup memory
3246 delete result;
3247 return true;
3250 if(show == "first")
3252 PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3254 QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3255 if(!result)
3257 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3258 SetSentErrorMessage(true);
3259 return false;
3262 Field *fields = result->Fetch();
3263 float x = fields[0].GetFloat();
3264 float y = fields[1].GetFloat();
3265 float z = fields[2].GetFloat();
3266 uint32 id = VISUAL_WAYPOINT;
3268 Player *chr = m_session->GetPlayer();
3269 float o = chr->GetOrientation();
3270 Map *map = chr->GetMap();
3272 Creature* pCreature = new Creature;
3273 if (!pCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0))
3275 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3276 delete pCreature;
3277 delete result;
3278 return false;
3281 pCreature->Relocate(x, y, z, o);
3283 if(!pCreature->IsPositionValid())
3285 sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
3286 delete pCreature;
3287 delete result;
3288 return false;
3291 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3292 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3293 map->Add(pCreature);
3294 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3296 // Cleanup memory
3297 delete result;
3298 return true;
3301 if(show == "last")
3303 PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3305 QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3306 if( result )
3308 Maxpoint = (*result)[0].GetUInt32();
3310 delete result;
3312 else
3313 Maxpoint = 0;
3315 result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3316 if(!result)
3318 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3319 SetSentErrorMessage(true);
3320 return false;
3322 Field *fields = result->Fetch();
3323 float x = fields[0].GetFloat();
3324 float y = fields[1].GetFloat();
3325 float z = fields[2].GetFloat();
3326 uint32 id = VISUAL_WAYPOINT;
3328 Player *chr = m_session->GetPlayer();
3329 float o = chr->GetOrientation();
3330 Map *map = chr->GetMap();
3332 Creature* pCreature = new Creature;
3333 if (!pCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
3335 PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3336 delete pCreature;
3337 delete result;
3338 return false;
3341 pCreature->Relocate(x, y, z, o);
3343 if(!pCreature->IsPositionValid())
3345 sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
3346 delete pCreature;
3347 delete result;
3348 return false;
3351 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3352 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3353 map->Add(pCreature);
3354 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3355 // Cleanup memory
3356 delete result;
3357 return true;
3360 if(show == "off")
3362 QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3363 if(!result)
3365 SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3366 SetSentErrorMessage(true);
3367 return false;
3369 bool hasError = false;
3372 Field *fields = result->Fetch();
3373 uint32 guid = fields[0].GetUInt32();
3374 Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3375 if(!pCreature)
3377 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3378 hasError = true;
3379 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3381 else
3383 pCreature->DeleteFromDB();
3384 pCreature->AddObjectToRemoveList();
3386 }while(result->NextRow());
3387 // set "wpguid" column to "empty" - no visual waypoint spawned
3388 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
3390 if( hasError )
3392 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3393 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3394 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3397 SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3398 // Cleanup memory
3399 delete result;
3401 return true;
3404 PSendSysMessage("DEBUG: wpshow - no valid command found");
3406 return true;
3407 } // HandleWpShowCommand
3409 bool ChatHandler::HandleWpExportCommand(const char *args)
3411 if(!*args)
3412 return false;
3414 // Next arg is: <GUID> <ARGUMENT>
3416 // Did user provide a GUID
3417 // or did the user select a creature?
3418 // -> variable lowguid is filled with the GUID of the NPC
3419 uint32 lowguid = 0;
3420 Creature* target = getSelectedCreature();
3421 char* arg_str = NULL;
3422 if (target)
3424 if (target->GetEntry() != VISUAL_WAYPOINT)
3425 lowguid = target->GetGUIDLow();
3426 else
3428 QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3429 if (!result)
3431 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3432 return true;
3434 Field *fields = result->Fetch();
3435 lowguid = fields[0].GetUInt32();;
3436 delete result;
3439 arg_str = strtok((char*)args, " ");
3441 else
3443 // user provided <GUID>
3444 char* guid_str = strtok((char*)args, " ");
3445 if( !guid_str )
3447 SendSysMessage(LANG_WAYPOINT_NOGUID);
3448 return false;
3450 lowguid = atoi((char*)guid_str);
3452 arg_str = strtok((char*)NULL, " ");
3455 if( !arg_str)
3457 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3458 return false;
3461 PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3463 QueryResult *result = WorldDatabase.PQuery(
3464 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3465 "SELECT point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, id FROM creature_movement WHERE id = '%u' ORDER BY point", lowguid );
3467 if (!result)
3469 PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3470 SetSentErrorMessage(true);
3471 return false;
3474 std::ofstream outfile;
3475 outfile.open (arg_str);
3479 Field *fields = result->Fetch();
3481 outfile << "INSERT INTO creature_movement ";
3482 outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5 ) VALUES ";
3484 outfile << "( ";
3485 outfile << fields[15].GetUInt32(); // id
3486 outfile << ", ";
3487 outfile << fields[0].GetUInt32(); // point
3488 outfile << ", ";
3489 outfile << fields[1].GetFloat(); // position_x
3490 outfile << ", ";
3491 outfile << fields[2].GetFloat(); // position_y
3492 outfile << ", ";
3493 outfile << fields[3].GetUInt32(); // position_z
3494 outfile << ", ";
3495 outfile << fields[4].GetUInt32(); // orientation
3496 outfile << ", ";
3497 outfile << fields[5].GetUInt32(); // model1
3498 outfile << ", ";
3499 outfile << fields[6].GetUInt32(); // model2
3500 outfile << ", ";
3501 outfile << fields[7].GetUInt16(); // waittime
3502 outfile << ", ";
3503 outfile << fields[8].GetUInt32(); // emote
3504 outfile << ", ";
3505 outfile << fields[9].GetUInt32(); // spell
3506 outfile << ", ";
3507 outfile << fields[10].GetUInt32(); // textid1
3508 outfile << ", ";
3509 outfile << fields[11].GetUInt32(); // textid2
3510 outfile << ", ";
3511 outfile << fields[12].GetUInt32(); // textid3
3512 outfile << ", ";
3513 outfile << fields[13].GetUInt32(); // textid4
3514 outfile << ", ";
3515 outfile << fields[14].GetUInt32(); // textid5
3516 outfile << ");\n ";
3518 } while( result->NextRow() );
3519 delete result;
3521 PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3522 outfile.close();
3524 return true;
3527 bool ChatHandler::HandleWpImportCommand(const char *args)
3529 if(!*args)
3530 return false;
3532 char* arg_str = strtok((char*)args, " ");
3533 if (!arg_str)
3534 return false;
3536 std::string line;
3537 std::ifstream infile (arg_str);
3538 if (infile.is_open())
3540 while (! infile.eof() )
3542 getline (infile,line);
3543 //cout << line << endl;
3544 QueryResult *result = WorldDatabase.Query(line.c_str());
3545 delete result;
3547 infile.close();
3549 PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3551 return true;
3554 //rename characters
3555 bool ChatHandler::HandleCharacterRenameCommand(const char* args)
3557 Player* target;
3558 uint64 target_guid;
3559 std::string target_name;
3560 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
3561 return false;
3563 if(target)
3565 // check online security
3566 if (HasLowerSecurity(target, 0))
3567 return false;
3569 PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str());
3570 target->SetAtLoginFlag(AT_LOGIN_RENAME);
3571 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3573 else
3575 // check offline security
3576 if (HasLowerSecurity(NULL, target_guid))
3577 return false;
3579 std::string oldNameLink = playerLink(target_name);
3581 PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid));
3582 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(target_guid));
3585 return true;
3588 // customize characters
3589 bool ChatHandler::HandleCharacterCustomizeCommand(const char* args)
3591 Player* target;
3592 uint64 target_guid;
3593 std::string target_name;
3594 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
3595 return false;
3597 if(target)
3599 PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str());
3600 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
3601 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow());
3603 else
3605 std::string oldNameLink = playerLink(target_name);
3607 PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid));
3608 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(target_guid));
3611 return true;
3614 bool ChatHandler::HandleCharacterReputationCommand(const char* args)
3616 Player* target;
3617 if(!extractPlayerTarget((char*)args,&target))
3618 return false;
3620 LocaleConstant loc = GetSessionDbcLocale();
3622 FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList();
3623 for(FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr)
3625 FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
3626 char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#";
3627 ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
3628 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
3629 std::ostringstream ss;
3630 if (m_session)
3631 ss << itr->second.ID << " - |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << " " << localeNames[loc] << "]|h|r";
3632 else
3633 ss << itr->second.ID << " - " << factionName << " " << localeNames[loc];
3635 ss << " " << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ")";
3637 if(itr->second.Flags & FACTION_FLAG_VISIBLE)
3638 ss << GetMangosString(LANG_FACTION_VISIBLE);
3639 if(itr->second.Flags & FACTION_FLAG_AT_WAR)
3640 ss << GetMangosString(LANG_FACTION_ATWAR);
3641 if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
3642 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
3643 if(itr->second.Flags & FACTION_FLAG_HIDDEN)
3644 ss << GetMangosString(LANG_FACTION_HIDDEN);
3645 if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
3646 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
3647 if(itr->second.Flags & FACTION_FLAG_INACTIVE)
3648 ss << GetMangosString(LANG_FACTION_INACTIVE);
3650 SendSysMessage(ss.str().c_str());
3652 return true;
3655 //change standstate
3656 bool ChatHandler::HandleModifyStandStateCommand(const char* args)
3658 if (!*args)
3659 return false;
3661 uint32 anim_id = atoi((char*)args);
3662 m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3664 return true;
3667 bool ChatHandler::HandleHonorAddCommand(const char* args)
3669 if (!*args)
3670 return false;
3672 Player *target = getSelectedPlayer();
3673 if(!target)
3675 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3676 SetSentErrorMessage(true);
3677 return false;
3680 // check online security
3681 if (HasLowerSecurity(target, 0))
3682 return false;
3684 float amount = (float)atof(args);
3685 target->RewardHonor(NULL, 1, amount);
3686 return true;
3689 bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3691 Unit *target = getSelectedUnit();
3692 if(!target)
3694 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3695 SetSentErrorMessage(true);
3696 return false;
3699 // check online security
3700 if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
3701 return false;
3703 m_session->GetPlayer()->RewardHonor(target, 1);
3704 return true;
3707 bool ChatHandler::HandleHonorUpdateCommand(const char* /*args*/)
3709 Player *target = getSelectedPlayer();
3710 if(!target)
3712 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3713 SetSentErrorMessage(true);
3714 return false;
3717 // check online security
3718 if (HasLowerSecurity(target, 0))
3719 return false;
3721 target->UpdateHonorFields();
3722 return true;
3725 bool ChatHandler::HandleLookupEventCommand(const char* args)
3727 if(!*args)
3728 return false;
3730 std::string namepart = args;
3731 std::wstring wnamepart;
3733 // converting string that we try to find to lower case
3734 if(!Utf8toWStr(namepart,wnamepart))
3735 return false;
3737 wstrToLower(wnamepart);
3739 uint32 counter = 0;
3741 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3742 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3744 for(uint32 id = 0; id < events.size(); ++id )
3746 GameEventData const& eventData = events[id];
3748 std::string descr = eventData.description;
3749 if(descr.empty())
3750 continue;
3752 if (Utf8FitTo(descr, wnamepart))
3754 char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : "";
3756 if(m_session)
3757 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3758 else
3759 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3761 ++counter;
3765 if (counter==0)
3766 SendSysMessage(LANG_NOEVENTFOUND);
3768 return true;
3771 bool ChatHandler::HandleEventListCommand(const char* args)
3773 uint32 counter = 0;
3774 bool all = false;
3775 std::string arg = args;
3776 if (arg == "all")
3777 all = true;
3779 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3780 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3782 char const* active = GetMangosString(LANG_ACTIVE);
3783 char const* inactive = GetMangosString(LANG_FACTION_INACTIVE);
3784 char const* state = "";
3786 for (uint32 event_id = 0; event_id < events.size(); ++event_id)
3788 if (activeEvents.find(event_id) == activeEvents.end())
3790 if (!all)
3791 continue;
3792 state = inactive;
3794 else
3795 state = active;
3797 GameEventData const& eventData = events[event_id];
3799 if(m_session)
3800 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, event_id, event_id, eventData.description.c_str(), state);
3801 else
3802 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, event_id, eventData.description.c_str(), state);
3804 ++counter;
3807 if (counter==0)
3808 SendSysMessage(LANG_NOEVENTFOUND);
3810 return true;
3813 bool ChatHandler::HandleEventInfoCommand(const char* args)
3815 if(!*args)
3816 return false;
3818 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3819 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3820 if(!cId)
3821 return false;
3823 uint32 event_id = atoi(cId);
3825 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3827 if(event_id >=events.size())
3829 SendSysMessage(LANG_EVENT_NOT_EXIST);
3830 SetSentErrorMessage(true);
3831 return false;
3834 GameEventData const& eventData = events[event_id];
3835 if(!eventData.isValid())
3837 SendSysMessage(LANG_EVENT_NOT_EXIST);
3838 SetSentErrorMessage(true);
3839 return false;
3842 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3843 bool active = activeEvents.find(event_id) != activeEvents.end();
3844 char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : "";
3846 std::string startTimeStr = TimeToTimestampStr(eventData.start);
3847 std::string endTimeStr = TimeToTimestampStr(eventData.end);
3849 uint32 delay = sGameEventMgr.NextCheck(event_id);
3850 time_t nextTime = time(NULL)+delay;
3851 std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3853 std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3854 std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3856 PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3857 startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3858 nextStr.c_str());
3859 return true;
3862 bool ChatHandler::HandleEventStartCommand(const char* args)
3864 if(!*args)
3865 return false;
3867 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3868 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3869 if(!cId)
3870 return false;
3872 int32 event_id = atoi(cId);
3874 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3876 if(event_id < 1 || event_id >=(int32)events.size())
3878 SendSysMessage(LANG_EVENT_NOT_EXIST);
3879 SetSentErrorMessage(true);
3880 return false;
3883 GameEventData const& eventData = events[event_id];
3884 if(!eventData.isValid())
3886 SendSysMessage(LANG_EVENT_NOT_EXIST);
3887 SetSentErrorMessage(true);
3888 return false;
3891 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3892 if(activeEvents.find(event_id) != activeEvents.end())
3894 PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3895 SetSentErrorMessage(true);
3896 return false;
3899 PSendSysMessage(LANG_EVENT_STARTED, event_id, eventData.description.c_str());
3900 sGameEventMgr.StartEvent(event_id,true);
3901 return true;
3904 bool ChatHandler::HandleEventStopCommand(const char* args)
3906 if(!*args)
3907 return false;
3909 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3910 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3911 if(!cId)
3912 return false;
3914 int32 event_id = atoi(cId);
3916 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3918 if(event_id < 1 || event_id >=(int32)events.size())
3920 SendSysMessage(LANG_EVENT_NOT_EXIST);
3921 SetSentErrorMessage(true);
3922 return false;
3925 GameEventData const& eventData = events[event_id];
3926 if(!eventData.isValid())
3928 SendSysMessage(LANG_EVENT_NOT_EXIST);
3929 SetSentErrorMessage(true);
3930 return false;
3933 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3935 if(activeEvents.find(event_id) == activeEvents.end())
3937 PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3938 SetSentErrorMessage(true);
3939 return false;
3942 PSendSysMessage(LANG_EVENT_STOPPED, event_id, eventData.description.c_str());
3943 sGameEventMgr.StopEvent(event_id,true);
3944 return true;
3947 bool ChatHandler::HandleCombatStopCommand(const char* args)
3949 Player* target;
3950 if(!extractPlayerTarget((char*)args,&target))
3951 return false;
3953 // check online security
3954 if (HasLowerSecurity(target, 0))
3955 return false;
3957 target->CombatStop();
3958 target->getHostileRefManager().deleteReferences();
3959 return true;
3962 void ChatHandler::HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id)
3964 uint32 classmask = player->getClassMask();
3966 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3968 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3969 if (!skillLine)
3970 continue;
3972 // wrong skill
3973 if( skillLine->skillId != skill_id)
3974 continue;
3976 // not high rank
3977 if(skillLine->forward_spellid )
3978 continue;
3980 // skip racial skills
3981 if (skillLine->racemask != 0)
3982 continue;
3984 // skip wrong class skills
3985 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3986 continue;
3988 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3989 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,player,false))
3990 continue;
3992 player->learnSpell(skillLine->spellId,false);
3996 bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3998 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
4000 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
4001 if( !skillInfo )
4002 continue;
4004 if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) &&
4005 skillInfo->canLink) // only prof. with recipes have
4007 HandleLearnSkillRecipesHelper(m_session->GetPlayer(),skillInfo->id);
4011 SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
4012 return true;
4015 bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
4017 // Learns all recipes of specified profession and sets skill to max
4018 // Example: .learn all_recipes enchanting
4020 Player* target = getSelectedPlayer();
4021 if( !target )
4023 SendSysMessage(LANG_PLAYER_NOT_FOUND);
4024 return false;
4027 if(!*args)
4028 return false;
4030 std::wstring wnamepart;
4032 if(!Utf8toWStr(args,wnamepart))
4033 return false;
4035 // converting string that we try to find to lower case
4036 wstrToLower( wnamepart );
4038 std::string name;
4040 SkillLineEntry const *targetSkillInfo = NULL;
4041 for (uint32 i = 1; i < sSkillLineStore.GetNumRows(); ++i)
4043 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
4044 if (!skillInfo)
4045 continue;
4047 if ((skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
4048 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY) ||
4049 !skillInfo->canLink) // only prof with recipes have set
4050 continue;
4052 int loc = GetSessionDbcLocale();
4053 name = skillInfo->name[loc];
4054 if(name.empty())
4055 continue;
4057 if (!Utf8FitTo(name, wnamepart))
4059 loc = 0;
4060 for(; loc < MAX_LOCALE; ++loc)
4062 if(loc==GetSessionDbcLocale())
4063 continue;
4065 name = skillInfo->name[loc];
4066 if(name.empty())
4067 continue;
4069 if (Utf8FitTo(name, wnamepart))
4070 break;
4074 if(loc < MAX_LOCALE)
4076 targetSkillInfo = skillInfo;
4077 break;
4081 if(!targetSkillInfo)
4082 return false;
4084 HandleLearnSkillRecipesHelper(target,targetSkillInfo->id);
4086 uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id);
4087 target->SetSkill(targetSkillInfo->id, maxLevel, maxLevel);
4088 PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
4089 return true;
4092 bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
4095 if (!*args)
4096 return false;
4098 std::string ip = strtok ((char*)args, " ");
4099 char* limit_str = strtok (NULL, " ");
4100 int32 limit = limit_str ? atoi (limit_str) : -1;
4102 loginDatabase.escape_string (ip);
4104 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
4106 return LookupPlayerSearchCommand (result,limit);
4109 bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
4111 if (!*args)
4112 return false;
4114 std::string account = strtok ((char*)args, " ");
4115 char* limit_str = strtok (NULL, " ");
4116 int32 limit = limit_str ? atoi (limit_str) : -1;
4118 if (!AccountMgr::normalizeString (account))
4119 return false;
4121 loginDatabase.escape_string (account);
4123 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
4125 return LookupPlayerSearchCommand (result,limit);
4128 bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
4131 if (!*args)
4132 return false;
4134 std::string email = strtok ((char*)args, " ");
4135 char* limit_str = strtok (NULL, " ");
4136 int32 limit = limit_str ? atoi (limit_str) : -1;
4138 loginDatabase.escape_string (email);
4140 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
4142 return LookupPlayerSearchCommand (result,limit);
4145 bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
4147 if(!result)
4149 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4150 SetSentErrorMessage(true);
4151 return false;
4154 int i =0;
4157 Field* fields = result->Fetch();
4158 uint32 acc_id = fields[0].GetUInt32();
4159 std::string acc_name = fields[1].GetCppString();
4161 QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
4162 if(chars)
4164 PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4166 uint64 guid = 0;
4167 std::string name;
4171 Field* charfields = chars->Fetch();
4172 guid = charfields[0].GetUInt64();
4173 name = charfields[1].GetCppString();
4175 PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
4176 ++i;
4178 } while( chars->NextRow() && ( limit == -1 || i < limit ) );
4180 delete chars;
4182 } while(result->NextRow());
4184 delete result;
4186 if(i==0) // empty accounts only
4188 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4189 SetSentErrorMessage(true);
4190 return false;
4193 return true;
4196 /// Triggering corpses expire check in world
4197 bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4199 CorpsesErase();
4200 return true;
4203 bool ChatHandler::HandleRepairitemsCommand(const char* args)
4205 Player* target;
4206 if(!extractPlayerTarget((char*)args,&target))
4207 return false;
4209 // check online security
4210 if (HasLowerSecurity(target, 0))
4211 return false;
4213 // Repair items
4214 target->DurabilityRepairAll(false, 0, false);
4216 PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str());
4217 if(needReportToTarget(target))
4218 ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str());
4219 return true;
4222 bool ChatHandler::HandleWaterwalkCommand(const char* args)
4224 if(!*args)
4225 return false;
4227 Player *player = getSelectedPlayer();
4229 if(!player)
4231 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4232 SetSentErrorMessage(true);
4233 return false;
4236 // check online security
4237 if (HasLowerSecurity(player, 0))
4238 return false;
4240 if (strncmp(args, "on", 3) == 0)
4241 player->SetMovement(MOVE_WATER_WALK); // ON
4242 else if (strncmp(args, "off", 4) == 0)
4243 player->SetMovement(MOVE_LAND_WALK); // OFF
4244 else
4246 SendSysMessage(LANG_USE_BOL);
4247 return false;
4250 PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str());
4251 if(needReportToTarget(player))
4252 ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str());
4253 return true;
4256 bool ChatHandler::HandleLookupTitleCommand(const char* args)
4258 if(!*args)
4259 return false;
4261 // can be NULL in console call
4262 Player* target = getSelectedPlayer();
4264 // title name have single string arg for player name
4265 char const* targetName = target ? target->GetName() : "NAME";
4267 std::string namepart = args;
4268 std::wstring wnamepart;
4270 if(!Utf8toWStr(namepart,wnamepart))
4271 return false;
4273 // converting string that we try to find to lower case
4274 wstrToLower( wnamepart );
4276 uint32 counter = 0; // Counter for figure out that we found smth.
4278 // Search in CharTitles.dbc
4279 for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
4281 CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id);
4282 if(titleInfo)
4284 int loc = GetSessionDbcLocale();
4285 std::string name = titleInfo->name[loc];
4286 if(name.empty())
4287 continue;
4289 if (!Utf8FitTo(name, wnamepart))
4291 loc = 0;
4292 for(; loc < MAX_LOCALE; ++loc)
4294 if(loc==GetSessionDbcLocale())
4295 continue;
4297 name = titleInfo->name[loc];
4298 if(name.empty())
4299 continue;
4301 if (Utf8FitTo(name, wnamepart))
4302 break;
4306 if(loc < MAX_LOCALE)
4308 char const* knownStr = target && target->HasTitle(titleInfo) ? GetMangosString(LANG_KNOWN) : "";
4310 char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE)==titleInfo->bit_index
4311 ? GetMangosString(LANG_ACTIVE)
4312 : "";
4314 char titleNameStr[80];
4315 snprintf(titleNameStr,80,name.c_str(),targetName);
4317 // send title in "id (idx:idx) - [namedlink locale]" format
4318 if (m_session)
4319 PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr);
4320 else
4321 PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,titleNameStr,localeNames[loc],knownStr,activeStr);
4323 ++counter;
4327 if (counter == 0) // if counter == 0 then we found nth
4328 SendSysMessage(LANG_COMMAND_NOTITLEFOUND);
4329 return true;
4332 bool ChatHandler::HandleTitlesAddCommand(const char* args)
4334 // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r
4335 char* id_p = extractKeyFromLink((char*)args,"Htitle");
4336 if(!id_p)
4337 return false;
4339 int32 id = atoi(id_p);
4340 if (id <= 0)
4342 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4343 SetSentErrorMessage(true);
4344 return false;
4347 Player * target = getSelectedPlayer();
4348 if(!target)
4350 SendSysMessage(LANG_NO_CHAR_SELECTED);
4351 SetSentErrorMessage(true);
4352 return false;
4355 // check online security
4356 if (HasLowerSecurity(target, 0))
4357 return false;
4359 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
4360 if(!titleInfo)
4362 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4363 SetSentErrorMessage(true);
4364 return false;
4367 std::string tNameLink = GetNameLink(target);
4369 char const* targetName = target->GetName();
4370 char titleNameStr[80];
4371 snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName);
4373 target->SetTitle(titleInfo);
4374 PSendSysMessage(LANG_TITLE_ADD_RES, id, titleNameStr, tNameLink.c_str());
4376 return true;
4379 bool ChatHandler::HandleTitlesRemoveCommand(const char* args)
4381 // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r
4382 char* id_p = extractKeyFromLink((char*)args,"Htitle");
4383 if(!id_p)
4384 return false;
4386 int32 id = atoi(id_p);
4387 if (id <= 0)
4389 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4390 SetSentErrorMessage(true);
4391 return false;
4394 Player * target = getSelectedPlayer();
4395 if(!target)
4397 SendSysMessage(LANG_NO_CHAR_SELECTED);
4398 SetSentErrorMessage(true);
4399 return false;
4402 // check online security
4403 if (HasLowerSecurity(target, 0))
4404 return false;
4406 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
4407 if(!titleInfo)
4409 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4410 SetSentErrorMessage(true);
4411 return false;
4414 target->SetTitle(titleInfo,true);
4416 std::string tNameLink = GetNameLink(target);
4418 char const* targetName = target->GetName();
4419 char titleNameStr[80];
4420 snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName);
4422 PSendSysMessage(LANG_TITLE_REMOVE_RES, id, titleNameStr, tNameLink.c_str());
4424 if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE)))
4426 target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0);
4427 PSendSysMessage(LANG_CURRENT_TITLE_RESET, tNameLink.c_str());
4430 return true;
4433 //Edit Player KnownTitles
4434 bool ChatHandler::HandleTitlesSetMaskCommand(const char* args)
4436 if(!*args)
4437 return false;
4439 uint64 titles = 0;
4441 sscanf((char*)args, UI64FMTD, &titles);
4443 Player *target = getSelectedPlayer();
4444 if (!target)
4446 SendSysMessage(LANG_NO_CHAR_SELECTED);
4447 SetSentErrorMessage(true);
4448 return false;
4451 // check online security
4452 if (HasLowerSecurity(target, 0))
4453 return false;
4455 uint64 titles2 = titles;
4457 for(uint32 i = 1; i < sCharTitlesStore.GetNumRows(); ++i)
4458 if(CharTitlesEntry const* tEntry = sCharTitlesStore.LookupEntry(i))
4459 titles2 &= ~(uint64(1) << tEntry->bit_index);
4461 titles &= ~titles2; // remove not existed titles
4463 target->SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES, titles);
4464 SendSysMessage(LANG_DONE);
4466 if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE)))
4468 target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0);
4469 PSendSysMessage(LANG_CURRENT_TITLE_RESET,GetNameLink(target).c_str());
4472 return true;
4475 bool ChatHandler::HandleCharacterTitlesCommand(const char* args)
4477 Player* target;
4478 if(!extractPlayerTarget((char*)args,&target))
4479 return false;
4481 LocaleConstant loc = GetSessionDbcLocale();
4482 char const* targetName = target->GetName();
4483 char const* knownStr = GetMangosString(LANG_KNOWN);
4485 // Search in CharTitles.dbc
4486 for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
4488 CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id);
4489 if (titleInfo && target->HasTitle(titleInfo))
4491 std::string name = titleInfo->name[loc];
4492 if(name.empty())
4493 continue;
4495 char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE)==titleInfo->bit_index
4496 ? GetMangosString(LANG_ACTIVE)
4497 : "";
4499 char titleNameStr[80];
4500 snprintf(titleNameStr,80,name.c_str(),targetName);
4502 // send title in "id (idx:idx) - [namedlink locale]" format
4503 if (m_session)
4504 PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr);
4505 else
4506 PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,name.c_str(),localeNames[loc],knownStr,activeStr);
4509 return true;
4512 bool ChatHandler::HandleTitlesCurrentCommand(const char* args)
4514 // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r
4515 char* id_p = extractKeyFromLink((char*)args,"Htitle");
4516 if(!id_p)
4517 return false;
4519 int32 id = atoi(id_p);
4520 if (id <= 0)
4522 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4523 SetSentErrorMessage(true);
4524 return false;
4527 Player * target = getSelectedPlayer();
4528 if(!target)
4530 SendSysMessage(LANG_NO_CHAR_SELECTED);
4531 SetSentErrorMessage(true);
4532 return false;
4535 // check online security
4536 if (HasLowerSecurity(target, 0))
4537 return false;
4539 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
4540 if(!titleInfo)
4542 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4543 SetSentErrorMessage(true);
4544 return false;
4547 std::string tNameLink = GetNameLink(target);
4549 target->SetTitle(titleInfo); // to be sure that title now known
4550 target->SetUInt32Value(PLAYER_CHOSEN_TITLE,titleInfo->bit_index);
4552 PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name[GetSessionDbcLocale()], tNameLink.c_str());
4554 return true;