[9957] Alow sell item for money and extanded coset without momey in same time.
[getmangos.git] / src / game / Level2.cpp
blobbba39a064478aebb150ddb79e09f56d760acbc80
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>
45 #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
47 static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
49 LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL,
50 LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED
53 //mute player for some times
54 bool ChatHandler::HandleMuteCommand(const char* args)
56 char* nameStr;
57 char* delayStr;
58 extractOptFirstArg((char*)args,&nameStr,&delayStr);
59 if(!delayStr)
60 return false;
62 Player* target;
63 uint64 target_guid;
64 std::string target_name;
65 if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name))
66 return false;
68 uint32 account_id = target ? target->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(target_guid);
70 // find only player from same account if any
71 if(!target)
73 if(WorldSession* session = sWorld.FindSession(account_id))
74 target = session->GetPlayer();
77 uint32 notspeaktime = (uint32) atoi(delayStr);
79 // must have strong lesser security level
80 if(HasLowerSecurity (target,target_guid,true))
81 return false;
83 time_t mutetime = time(NULL) + notspeaktime*60;
85 if (target)
86 target->GetSession()->m_muteTime = mutetime;
88 loginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
90 if(target)
91 ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
93 std::string nameLink = playerLink(target_name);
95 PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime);
96 return true;
99 //unmute player
100 bool ChatHandler::HandleUnmuteCommand(const char* args)
102 Player* target;
103 uint64 target_guid;
104 std::string target_name;
105 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
106 return false;
108 uint32 account_id = target ? target->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(target_guid);
110 // find only player from same account if any
111 if(!target)
113 if(WorldSession* session = sWorld.FindSession(account_id))
114 target = session->GetPlayer();
117 // must have strong lesser security level
118 if(HasLowerSecurity (target,target_guid,true))
119 return false;
121 if (target)
123 if(target->CanSpeak())
125 SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
126 SetSentErrorMessage(true);
127 return false;
130 target->GetSession()->m_muteTime = 0;
133 loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
135 if(target)
136 ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
138 std::string nameLink = playerLink(target_name);
140 PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str());
141 return true;
144 bool ChatHandler::HandleGoTriggerCommand(const char* args)
146 Player* _player = m_session->GetPlayer();
148 if (!*args)
149 return false;
151 char *atId = strtok((char*)args, " ");
152 if (!atId)
153 return false;
155 int32 i_atId = atoi(atId);
157 if(!i_atId)
158 return false;
160 AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
161 if (!at)
163 PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
164 SetSentErrorMessage(true);
165 return false;
168 if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
170 PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
171 SetSentErrorMessage(true);
172 return false;
175 // stop flight if need
176 if(_player->isInFlight())
178 _player->GetMotionMaster()->MovementExpired();
179 _player->m_taxi.ClearTaxiDestinations();
181 // save only in non-flight case
182 else
183 _player->SaveRecallPosition();
185 _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
186 return true;
189 bool ChatHandler::HandleGoGraveyardCommand(const char* args)
191 Player* _player = m_session->GetPlayer();
193 if (!*args)
194 return false;
196 char *gyId = strtok((char*)args, " ");
197 if (!gyId)
198 return false;
200 int32 i_gyId = atoi(gyId);
202 if(!i_gyId)
203 return false;
205 WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
206 if (!gy)
208 PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
209 SetSentErrorMessage(true);
210 return false;
213 if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
215 PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
216 SetSentErrorMessage(true);
217 return false;
220 // stop flight if need
221 if(_player->isInFlight())
223 _player->GetMotionMaster()->MovementExpired();
224 _player->m_taxi.ClearTaxiDestinations();
226 // save only in non-flight case
227 else
228 _player->SaveRecallPosition();
230 _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
231 return true;
234 /** \brief Teleport the GM to the specified creature
236 * .gocreature <GUID> --> TP using creature.guid
237 * .gocreature azuregos --> TP player to the mob with this name
238 * Warning: If there is more than one mob with this name
239 * you will be teleported to the first one that is found.
240 * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry
241 * Warning: If there is more than one mob with this "id"
242 * you will be teleported to the first one that is found.
244 //teleport to creature
245 bool ChatHandler::HandleGoCreatureCommand(const char* args)
247 if(!*args)
248 return false;
249 Player* _player = m_session->GetPlayer();
251 // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
252 char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
253 if (!pParam1)
254 return false;
256 std::ostringstream whereClause;
258 // User wants to teleport to the NPC's template entry
259 if( strcmp(pParam1, "id") == 0 )
261 //sLog.outError("DEBUG: ID found");
263 // Get the "creature_template.entry"
264 // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
265 char* tail = strtok(NULL,"");
266 if(!tail)
267 return false;
268 char* cId = extractKeyFromLink(tail,"Hcreature_entry");
269 if(!cId)
270 return false;
272 int32 tEntry = atoi(cId);
273 //sLog.outError("DEBUG: ID value: %d", tEntry);
274 if(!tEntry)
275 return false;
277 whereClause << "WHERE id = '" << tEntry << "'";
279 else
281 //sLog.outError("DEBUG: ID *not found*");
283 int32 guid = atoi(pParam1);
285 // Number is invalid - maybe the user specified the mob's name
286 if(!guid)
288 std::string name = pParam1;
289 WorldDatabase.escape_string(name);
290 whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
292 else
294 whereClause << "WHERE guid = '" << guid << "'";
297 //sLog.outError("DEBUG: %s", whereClause.c_str());
299 QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
300 if (!result)
302 SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
303 SetSentErrorMessage(true);
304 return false;
306 if( result->GetRowCount() > 1 )
308 SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
311 Field *fields = result->Fetch();
312 float x = fields[0].GetFloat();
313 float y = fields[1].GetFloat();
314 float z = fields[2].GetFloat();
315 float ort = fields[3].GetFloat();
316 int mapid = fields[4].GetUInt16();
318 delete result;
320 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
322 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
323 SetSentErrorMessage(true);
324 return false;
327 // stop flight if need
328 if(_player->isInFlight())
330 _player->GetMotionMaster()->MovementExpired();
331 _player->m_taxi.ClearTaxiDestinations();
333 // save only in non-flight case
334 else
335 _player->SaveRecallPosition();
337 _player->TeleportTo(mapid, x, y, z, ort);
338 return true;
341 //teleport to gameobject
342 bool ChatHandler::HandleGoObjectCommand(const char* args)
344 if(!*args)
345 return false;
347 Player* _player = m_session->GetPlayer();
349 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
350 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
351 if(!cId)
352 return false;
354 int32 guid = atoi(cId);
355 if(!guid)
356 return false;
358 float x, y, z, ort;
359 int mapid;
361 // by DB guid
362 if (GameObjectData const* go_data = sObjectMgr.GetGOData(guid))
364 x = go_data->posX;
365 y = go_data->posY;
366 z = go_data->posZ;
367 ort = go_data->orientation;
368 mapid = go_data->mapid;
370 else
372 SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
373 SetSentErrorMessage(true);
374 return false;
377 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
379 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
380 SetSentErrorMessage(true);
381 return false;
384 // stop flight if need
385 if(_player->isInFlight())
387 _player->GetMotionMaster()->MovementExpired();
388 _player->m_taxi.ClearTaxiDestinations();
390 // save only in non-flight case
391 else
392 _player->SaveRecallPosition();
394 _player->TeleportTo(mapid, x, y, z, ort);
395 return true;
398 bool ChatHandler::HandleGameObjectTargetCommand(const char* args)
400 Player* pl = m_session->GetPlayer();
401 QueryResult *result;
402 GameEventMgr::ActiveEvents const& activeEventsList = sGameEventMgr.GetActiveEventList();
403 if(*args)
405 // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r
406 char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry");
407 if(!cId)
408 return false;
410 uint32 id = atol(cId);
412 if(id)
413 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",
414 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
415 else
417 std::string name = cId;
418 WorldDatabase.escape_string(name);
419 result = WorldDatabase.PQuery(
420 "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_ "
421 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
422 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
425 else
427 std::ostringstream eventFilter;
428 eventFilter << " AND (event IS NULL ";
429 bool initString = true;
431 for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
433 if (initString)
435 eventFilter << "OR event IN (" <<*itr;
436 initString =false;
438 else
439 eventFilter << "," << *itr;
442 if (!initString)
443 eventFilter << "))";
444 else
445 eventFilter << ")";
447 result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
448 "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
449 "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10",
450 m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
453 if (!result)
455 SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
456 return true;
459 bool found = false;
460 float x, y, z, o;
461 uint32 lowguid, id;
462 uint16 mapid, pool_id;
466 Field *fields = result->Fetch();
467 lowguid = fields[0].GetUInt32();
468 id = fields[1].GetUInt32();
469 x = fields[2].GetFloat();
470 y = fields[3].GetFloat();
471 z = fields[4].GetFloat();
472 o = fields[5].GetFloat();
473 mapid = fields[6].GetUInt16();
474 pool_id = sPoolMgr.IsPartOfAPool<GameObject>(lowguid);
475 if (!pool_id || sPoolMgr.IsSpawnedObject<GameObject>(lowguid))
476 found = true;
477 } while( result->NextRow() && (!found) );
479 delete result;
481 if (!found)
483 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
484 return false;
487 GameObjectInfo const* goI = ObjectMgr::GetGameObjectInfo(id);
489 if (!goI)
491 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
492 return false;
495 GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
497 PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
499 if(target)
501 time_t curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
502 if(curRespawnDelay < 0)
503 curRespawnDelay = 0;
505 std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
506 std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
508 PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
510 return true;
513 //delete object by selection or guid
514 bool ChatHandler::HandleGameObjectDeleteCommand(const char* args)
516 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
517 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
518 if(!cId)
519 return false;
521 uint32 lowguid = atoi(cId);
522 if(!lowguid)
523 return false;
525 GameObject* obj = NULL;
527 // by DB guid
528 if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid))
529 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
531 if(!obj)
533 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
534 SetSentErrorMessage(true);
535 return false;
538 uint64 owner_guid = obj->GetOwnerGUID();
539 if(owner_guid)
541 Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
542 if(!owner || !IS_PLAYER_GUID(owner_guid))
544 PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
545 SetSentErrorMessage(true);
546 return false;
549 owner->RemoveGameObject(obj,false);
552 obj->SetRespawnTime(0); // not save respawn time
553 obj->Delete();
554 obj->DeleteFromDB();
556 PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
558 return true;
561 //turn selected object
562 bool ChatHandler::HandleGameObjectTurnCommand(const char* args)
564 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
565 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
566 if(!cId)
567 return false;
569 uint32 lowguid = atoi(cId);
570 if(!lowguid)
571 return false;
573 GameObject* obj = NULL;
575 // by DB guid
576 if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid))
577 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
579 if(!obj)
581 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
582 SetSentErrorMessage(true);
583 return false;
586 char* po = strtok(NULL, " ");
587 float o;
589 if (po)
591 o = (float)atof(po);
593 else
595 Player *chr = m_session->GetPlayer();
596 o = chr->GetOrientation();
599 Map* map = obj->GetMap();
600 map->Remove(obj,false);
602 obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
603 obj->UpdateRotationFields();
605 map->Add(obj);
607 obj->SaveToDB();
608 obj->Refresh();
610 PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow());
612 return true;
615 //move selected object
616 bool ChatHandler::HandleGameObjectMoveCommand(const char* args)
618 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
619 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
620 if(!cId)
621 return false;
623 uint32 lowguid = atoi(cId);
624 if(!lowguid)
625 return false;
627 GameObject* obj = NULL;
629 // by DB guid
630 if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid))
631 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
633 if(!obj)
635 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
636 SetSentErrorMessage(true);
637 return false;
640 char* px = strtok(NULL, " ");
641 char* py = strtok(NULL, " ");
642 char* pz = strtok(NULL, " ");
644 if (!px)
646 Player *chr = m_session->GetPlayer();
648 Map* map = obj->GetMap();
649 map->Remove(obj,false);
651 obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
653 map->Add(obj);
655 else
657 if(!py || !pz)
658 return false;
660 float x = (float)atof(px);
661 float y = (float)atof(py);
662 float z = (float)atof(pz);
664 if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
666 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
667 SetSentErrorMessage(true);
668 return false;
671 Map* map = obj->GetMap();
672 map->Remove(obj,false);
674 obj->Relocate(x, y, z, obj->GetOrientation());
676 map->Add(obj);
679 obj->SaveToDB();
680 obj->Refresh();
682 PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow());
684 return true;
687 //spawn go
688 bool ChatHandler::HandleGameObjectAddCommand(const char* args)
690 if (!*args)
691 return false;
693 // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r
694 char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry");
695 if(!cId)
696 return false;
698 uint32 id = atol(cId);
699 if(!id)
700 return false;
702 char* spawntimeSecs = strtok(NULL, " ");
704 const GameObjectInfo *gInfo = ObjectMgr::GetGameObjectInfo(id);
706 if (!gInfo)
708 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
709 SetSentErrorMessage(true);
710 return false;
713 if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId))
715 // report to DB errors log as in loading case
716 sLog.outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.",id, gInfo->type, gInfo->displayId);
717 PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA,id);
718 SetSentErrorMessage(true);
719 return false;
722 Player *chr = m_session->GetPlayer();
723 float x = float(chr->GetPositionX());
724 float y = float(chr->GetPositionY());
725 float z = float(chr->GetPositionZ());
726 float o = float(chr->GetOrientation());
727 Map *map = chr->GetMap();
729 GameObject* pGameObj = new GameObject;
730 uint32 db_lowGUID = sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
732 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))
734 delete pGameObj;
735 return false;
738 if( spawntimeSecs )
740 uint32 value = atoi((char*)spawntimeSecs);
741 pGameObj->SetRespawnTime(value);
742 //DEBUG_LOG("*** spawntimeSecs: %d", value);
745 // fill the gameobject data and save to the db
746 pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn());
748 // this will generate a new guid if the object is in an instance
749 if(!pGameObj->LoadFromDB(db_lowGUID, map))
751 delete pGameObj;
752 return false;
755 DEBUG_LOG(GetMangosString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o);
757 map->Add(pGameObj);
759 // TODO: is it really necessary to add both the real and DB table guid here ?
760 sObjectMgr.AddGameobjectToGrid(db_lowGUID, sObjectMgr.GetGOData(db_lowGUID));
762 PSendSysMessage(LANG_GAMEOBJECT_ADD,id,gInfo->name,db_lowGUID,x,y,z);
763 return true;
766 //set pahsemask for selected object
767 bool ChatHandler::HandleGameObjectPhaseCommand(const char* args)
769 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
770 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
771 if(!cId)
772 return false;
774 uint32 lowguid = atoi(cId);
775 if(!lowguid)
776 return false;
778 GameObject* obj = NULL;
780 // by DB guid
781 if (GameObjectData const* go_data = sObjectMgr.GetGOData(lowguid))
782 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
784 if(!obj)
786 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
787 SetSentErrorMessage(true);
788 return false;
791 char* phaseStr = strtok (NULL, " ");
792 uint32 phasemask = phaseStr? atoi(phaseStr) : 0;
793 if ( phasemask == 0 )
795 SendSysMessage(LANG_BAD_VALUE);
796 SetSentErrorMessage(true);
797 return false;
800 obj->SetPhaseMask(phasemask,true);
801 obj->SaveToDB();
802 return true;
805 bool ChatHandler::HandleGameObjectNearCommand(const char* args)
807 float distance = (!*args) ? 10.0f : (float)atof(args);
808 uint32 count = 0;
810 Player* pl = m_session->GetPlayer();
811 QueryResult *result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, map, "
812 "(POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ "
813 "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_",
814 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),
815 pl->GetMapId(),pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),distance*distance);
817 if (result)
821 Field *fields = result->Fetch();
822 uint32 guid = fields[0].GetUInt32();
823 uint32 entry = fields[1].GetUInt32();
824 float x = fields[2].GetFloat();
825 float y = fields[3].GetFloat();
826 float z = fields[4].GetFloat();
827 int mapid = fields[5].GetUInt16();
829 GameObjectInfo const * gInfo = ObjectMgr::GetGameObjectInfo(entry);
831 if(!gInfo)
832 continue;
834 PSendSysMessage(LANG_GO_MIXED_LIST_CHAT, guid, entry, guid, gInfo->name, x, y, z, mapid);
836 ++count;
837 } while (result->NextRow());
839 delete result;
842 PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE,distance,count);
843 return true;
846 bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
848 uint64 guid = m_session->GetPlayer()->GetSelection();
850 if (guid == 0)
852 SendSysMessage(LANG_NO_SELECTION);
853 SetSentErrorMessage(true);
854 return false;
857 PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
858 return true;
861 bool ChatHandler::HandleLookupFactionCommand(const char* args)
863 if (!*args)
864 return false;
866 // Can be NULL at console call
867 Player *target = getSelectedPlayer ();
869 std::string namepart = args;
870 std::wstring wnamepart;
872 if (!Utf8toWStr (namepart,wnamepart))
873 return false;
875 // converting string that we try to find to lower case
876 wstrToLower (wnamepart);
878 uint32 counter = 0; // Counter for figure out that we found smth.
880 for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
882 FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
883 if (factionEntry)
885 FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL;
887 int loc = GetSessionDbcLocale();
888 std::string name = factionEntry->name[loc];
889 if(name.empty())
890 continue;
892 if (!Utf8FitTo(name, wnamepart))
894 loc = 0;
895 for(; loc < MAX_LOCALE; ++loc)
897 if(loc==GetSessionDbcLocale())
898 continue;
900 name = factionEntry->name[loc];
901 if(name.empty())
902 continue;
904 if (Utf8FitTo(name, wnamepart))
905 break;
909 if(loc < MAX_LOCALE)
911 // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
912 // or "id - [faction] [no reputation]" format
913 std::ostringstream ss;
914 if (m_session)
915 ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
916 else
917 ss << id << " - " << name << " " << localeNames[loc];
919 if (repState) // and then target!=NULL also
921 ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
922 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
924 ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")";
926 if(repState->Flags & FACTION_FLAG_VISIBLE)
927 ss << GetMangosString(LANG_FACTION_VISIBLE);
928 if(repState->Flags & FACTION_FLAG_AT_WAR)
929 ss << GetMangosString(LANG_FACTION_ATWAR);
930 if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
931 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
932 if(repState->Flags & FACTION_FLAG_HIDDEN)
933 ss << GetMangosString(LANG_FACTION_HIDDEN);
934 if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
935 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
936 if(repState->Flags & FACTION_FLAG_INACTIVE)
937 ss << GetMangosString(LANG_FACTION_INACTIVE);
939 else
940 ss << GetMangosString(LANG_FACTION_NOREPUTATION);
942 SendSysMessage(ss.str().c_str());
943 counter++;
948 if (counter == 0) // if counter == 0 then we found nth
949 SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
950 return true;
953 bool ChatHandler::HandleModifyRepCommand(const char * args)
955 if (!*args) return false;
957 Player* target = NULL;
958 target = getSelectedPlayer();
960 if(!target)
962 SendSysMessage(LANG_PLAYER_NOT_FOUND);
963 SetSentErrorMessage(true);
964 return false;
967 // check online security
968 if (HasLowerSecurity(target, 0))
969 return false;
971 char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
972 if(!factionTxt)
973 return false;
975 uint32 factionId = atoi(factionTxt);
977 int32 amount = 0;
978 char *rankTxt = strtok(NULL, " ");
979 if (!factionTxt || !rankTxt)
980 return false;
982 amount = atoi(rankTxt);
983 if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
985 std::string rankStr = rankTxt;
986 std::wstring wrankStr;
987 if(!Utf8toWStr(rankStr,wrankStr))
988 return false;
989 wstrToLower( wrankStr );
991 int r = 0;
992 amount = -42000;
993 for (; r < MAX_REPUTATION_RANK; ++r)
995 std::string rank = GetMangosString(ReputationRankStrIndex[r]);
996 if(rank.empty())
997 continue;
999 std::wstring wrank;
1000 if(!Utf8toWStr(rank,wrank))
1001 continue;
1003 wstrToLower(wrank);
1005 if(wrank.substr(0,wrankStr.size())==wrankStr)
1007 char *deltaTxt = strtok(NULL, " ");
1008 if (deltaTxt)
1010 int32 delta = atoi(deltaTxt);
1011 if ((delta < 0) || (delta > ReputationMgr::PointsInRank[r] -1))
1013 PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (ReputationMgr::PointsInRank[r]-1));
1014 SetSentErrorMessage(true);
1015 return false;
1017 amount += delta;
1019 break;
1021 amount += ReputationMgr::PointsInRank[r];
1023 if (r >= MAX_REPUTATION_RANK)
1025 PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
1026 SetSentErrorMessage(true);
1027 return false;
1031 FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
1033 if (!factionEntry)
1035 PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
1036 SetSentErrorMessage(true);
1037 return false;
1040 if (factionEntry->reputationListID < 0)
1042 PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[GetSessionDbcLocale()], factionId);
1043 SetSentErrorMessage(true);
1044 return false;
1047 target->GetReputationMgr().SetReputation(factionEntry,amount);
1048 PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[GetSessionDbcLocale()], factionId,
1049 GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry));
1050 return true;
1053 //-----------------------Npc Commands-----------------------
1054 //add spawn of creature
1055 bool ChatHandler::HandleNpcAddCommand(const char* args)
1057 if(!*args)
1058 return false;
1059 char* charID = extractKeyFromLink((char*)args,"Hcreature_entry");
1060 if(!charID)
1061 return false;
1063 char* team = strtok(NULL, " ");
1064 int32 teamval = 0;
1065 if (team) { teamval = atoi(team); }
1066 if (teamval < 0) { teamval = 0; }
1068 uint32 id = atoi(charID);
1070 Player *chr = m_session->GetPlayer();
1071 float x = chr->GetPositionX();
1072 float y = chr->GetPositionY();
1073 float z = chr->GetPositionZ();
1074 float o = chr->GetOrientation();
1075 Map *map = chr->GetMap();
1077 Creature* pCreature = new Creature;
1078 if (!pCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, (uint32)teamval))
1080 delete pCreature;
1081 return false;
1084 pCreature->Relocate(x,y,z,o);
1086 if(!pCreature->IsPositionValid())
1088 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());
1089 delete pCreature;
1090 return false;
1093 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
1095 uint32 db_guid = pCreature->GetDBTableGUIDLow();
1097 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
1098 pCreature->LoadFromDB(db_guid, map);
1100 map->Add(pCreature);
1101 sObjectMgr.AddCreatureToGrid(db_guid, sObjectMgr.GetCreatureData(db_guid));
1102 return true;
1105 //add item in vendorlist
1106 bool ChatHandler::HandleNpcAddVendorItemCommand(const char* args)
1108 if (!*args)
1109 return false;
1111 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1112 if (!pitem)
1114 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1115 SetSentErrorMessage(true);
1116 return false;
1119 uint32 itemId = atol(pitem);
1121 char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
1122 uint32 maxcount = 0;
1123 if (fmaxcount)
1124 maxcount = atol(fmaxcount);
1126 char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
1127 uint32 incrtime = 0;
1128 if (fincrtime)
1129 incrtime = atol(fincrtime);
1131 char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
1132 int32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1134 Creature* vendor = getSelectedCreature();
1136 uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1138 if(!sObjectMgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1140 SetSentErrorMessage(true);
1141 return false;
1144 sObjectMgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1146 ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId);
1148 PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1149 return true;
1152 //del item from vendor list
1153 bool ChatHandler::HandleNpcDelVendorItemCommand(const char* args)
1155 if (!*args)
1156 return false;
1158 Creature* vendor = getSelectedCreature();
1159 if (!vendor || !vendor->isVendor())
1161 SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1162 SetSentErrorMessage(true);
1163 return false;
1166 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1167 if (!pitem)
1169 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1170 SetSentErrorMessage(true);
1171 return false;
1173 uint32 itemId = atol(pitem);
1175 if(!sObjectMgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1177 PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1178 SetSentErrorMessage(true);
1179 return false;
1182 ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(itemId);
1184 PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1185 return true;
1188 //add move for creature
1189 bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
1191 if(!*args)
1192 return false;
1194 char* guid_str = strtok((char*)args, " ");
1195 char* wait_str = strtok((char*)NULL, " ");
1197 uint32 lowguid = atoi((char*)guid_str);
1199 Creature* pCreature = NULL;
1201 /* FIXME: impossible without entry
1202 if(lowguid)
1203 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1206 // attempt check creature existence by DB data
1207 if(!pCreature)
1209 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
1210 if(!data)
1212 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1213 SetSentErrorMessage(true);
1214 return false;
1217 else
1219 // obtain real GUID for DB operations
1220 lowguid = pCreature->GetDBTableGUIDLow();
1223 int wait = wait_str ? atoi(wait_str) : 0;
1225 if(wait < 0)
1226 wait = 0;
1228 Player* player = m_session->GetPlayer();
1230 sWaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1232 // update movement type
1233 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1234 if(pCreature)
1236 pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1237 pCreature->GetMotionMaster()->Initialize();
1238 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1240 pCreature->setDeathState(JUST_DIED);
1241 pCreature->Respawn();
1243 pCreature->SaveToDB();
1246 SendSysMessage(LANG_WAYPOINT_ADDED);
1248 return true;
1251 //change level of creature or pet
1252 bool ChatHandler::HandleNpcChangeLevelCommand(const char* args)
1254 if (!*args)
1255 return false;
1257 uint8 lvl = (uint8) atoi((char*)args);
1258 if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL) + 3)
1260 SendSysMessage(LANG_BAD_VALUE);
1261 SetSentErrorMessage(true);
1262 return false;
1265 Creature* pCreature = getSelectedCreature();
1266 if(!pCreature)
1268 SendSysMessage(LANG_SELECT_CREATURE);
1269 SetSentErrorMessage(true);
1270 return false;
1273 if(pCreature->isPet())
1275 if(((Pet*)pCreature)->getPetType()==HUNTER_PET)
1277 pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr.GetXPForPetLevel(lvl));
1278 pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
1280 ((Pet*)pCreature)->GivePetLevel(lvl);
1282 else
1284 pCreature->SetMaxHealth( 100 + 30*lvl);
1285 pCreature->SetHealth( 100 + 30*lvl);
1286 pCreature->SetLevel( lvl);
1287 pCreature->SaveToDB();
1290 return true;
1293 //set npcflag of creature
1294 bool ChatHandler::HandleNpcFlagCommand(const char* args)
1296 if (!*args)
1297 return false;
1299 uint32 npcFlags = (uint32) atoi((char*)args);
1301 Creature* pCreature = getSelectedCreature();
1303 if(!pCreature)
1305 SendSysMessage(LANG_SELECT_CREATURE);
1306 SetSentErrorMessage(true);
1307 return false;
1310 pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1312 WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1314 SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1316 return true;
1319 bool ChatHandler::HandleNpcDeleteCommand(const char* args)
1321 Creature* unit = NULL;
1323 if(*args)
1325 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1326 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1327 if(!cId)
1328 return false;
1330 uint32 lowguid = atoi(cId);
1331 if(!lowguid)
1332 return false;
1334 if (CreatureData const* cr_data = sObjectMgr.GetCreatureData(lowguid))
1335 unit = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
1337 else
1338 unit = getSelectedCreature();
1340 if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle())
1342 SendSysMessage(LANG_SELECT_CREATURE);
1343 SetSentErrorMessage(true);
1344 return false;
1347 // Delete the creature
1348 unit->CombatStop();
1349 unit->DeleteFromDB();
1350 unit->AddObjectToRemoveList();
1352 SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
1354 return true;
1357 //move selected creature
1358 bool ChatHandler::HandleNpcMoveCommand(const char* args)
1360 uint32 lowguid = 0;
1362 Creature* pCreature = getSelectedCreature();
1364 if(!pCreature)
1366 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1367 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1368 if(!cId)
1369 return false;
1371 lowguid = atoi(cId);
1373 /* FIXME: impossibel without entry
1374 if(lowguid)
1375 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1378 // Attempting creature load from DB data
1379 if(!pCreature)
1381 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
1382 if(!data)
1384 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1385 SetSentErrorMessage(true);
1386 return false;
1389 uint32 map_id = data->mapid;
1391 if(m_session->GetPlayer()->GetMapId()!=map_id)
1393 PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1394 SetSentErrorMessage(true);
1395 return false;
1398 else
1400 lowguid = pCreature->GetDBTableGUIDLow();
1403 else
1405 lowguid = pCreature->GetDBTableGUIDLow();
1408 float x = m_session->GetPlayer()->GetPositionX();
1409 float y = m_session->GetPlayer()->GetPositionY();
1410 float z = m_session->GetPlayer()->GetPositionZ();
1411 float o = m_session->GetPlayer()->GetOrientation();
1413 if (pCreature)
1415 if(CreatureData const* data = sObjectMgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1417 const_cast<CreatureData*>(data)->posX = x;
1418 const_cast<CreatureData*>(data)->posY = y;
1419 const_cast<CreatureData*>(data)->posZ = z;
1420 const_cast<CreatureData*>(data)->orientation = o;
1422 pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
1423 pCreature->GetMotionMaster()->Initialize();
1424 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1426 pCreature->setDeathState(JUST_DIED);
1427 pCreature->Respawn();
1431 WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1432 PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1433 return true;
1436 /**HandleNpcSetMoveTypeCommand
1437 * Set the movement type for an NPC.<br/>
1438 * <br/>
1439 * Valid movement types are:
1440 * <ul>
1441 * <li> stay - NPC wont move </li>
1442 * <li> random - NPC will move randomly according to the spawndist </li>
1443 * <li> way - NPC will move with given waypoints set </li>
1444 * </ul>
1445 * additional parameter: NODEL - so no waypoints are deleted, if you
1446 * change the movement type
1448 bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
1450 if(!*args)
1451 return false;
1453 // 3 arguments:
1454 // GUID (optional - you can also select the creature)
1455 // stay|random|way (determines the kind of movement)
1456 // NODEL (optional - tells the system NOT to delete any waypoints)
1457 // this is very handy if you want to do waypoints, that are
1458 // later switched on/off according to special events (like escort
1459 // quests, etc)
1460 char* guid_str = strtok((char*)args, " ");
1461 char* type_str = strtok((char*)NULL, " ");
1462 char* dontdel_str = strtok((char*)NULL, " ");
1464 bool doNotDelete = false;
1466 if(!guid_str)
1467 return false;
1469 uint32 lowguid = 0;
1470 Creature* pCreature = NULL;
1472 if( dontdel_str )
1474 //sLog.outError("DEBUG: All 3 params are set");
1476 // All 3 params are set
1477 // GUID
1478 // type
1479 // doNotDEL
1480 if( stricmp( dontdel_str, "NODEL" ) == 0 )
1482 //sLog.outError("DEBUG: doNotDelete = true;");
1483 doNotDelete = true;
1486 else
1488 // Only 2 params - but maybe NODEL is set
1489 if( type_str )
1491 sLog.outError("DEBUG: Only 2 params ");
1492 if( stricmp( type_str, "NODEL" ) == 0 )
1494 //sLog.outError("DEBUG: type_str, NODEL ");
1495 doNotDelete = true;
1496 type_str = NULL;
1501 if(!type_str) // case .setmovetype $move_type (with selected creature)
1503 type_str = guid_str;
1504 pCreature = getSelectedCreature();
1505 if(!pCreature || pCreature->isPet())
1506 return false;
1507 lowguid = pCreature->GetDBTableGUIDLow();
1509 else // case .setmovetype #creature_guid $move_type (with selected creature)
1511 lowguid = atoi((char*)guid_str);
1513 /* impossible without entry
1514 if(lowguid)
1515 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1518 // attempt check creature existence by DB data
1519 if(!pCreature)
1521 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
1522 if(!data)
1524 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1525 SetSentErrorMessage(true);
1526 return false;
1529 else
1531 lowguid = pCreature->GetDBTableGUIDLow();
1535 // now lowguid is low guid really existed creature
1536 // and pCreature point (maybe) to this creature or NULL
1538 MovementGeneratorType move_type;
1540 std::string type = type_str;
1542 if(type == "stay")
1543 move_type = IDLE_MOTION_TYPE;
1544 else if(type == "random")
1545 move_type = RANDOM_MOTION_TYPE;
1546 else if(type == "way")
1547 move_type = WAYPOINT_MOTION_TYPE;
1548 else
1549 return false;
1551 // update movement type
1552 if(doNotDelete == false)
1553 sWaypointMgr.DeletePath(lowguid);
1555 if(pCreature)
1557 pCreature->SetDefaultMovementType(move_type);
1558 pCreature->GetMotionMaster()->Initialize();
1559 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1561 pCreature->setDeathState(JUST_DIED);
1562 pCreature->Respawn();
1564 pCreature->SaveToDB();
1566 if( doNotDelete == false )
1568 PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1570 else
1572 PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1575 return true;
1578 //set model of creature
1579 bool ChatHandler::HandleNpcSetModelCommand(const char* args)
1581 if (!*args)
1582 return false;
1584 uint32 displayId = (uint32) atoi((char*)args);
1586 Creature *pCreature = getSelectedCreature();
1588 if(!pCreature || pCreature->isPet())
1590 SendSysMessage(LANG_SELECT_CREATURE);
1591 SetSentErrorMessage(true);
1592 return false;
1595 pCreature->SetDisplayId(displayId);
1596 pCreature->SetNativeDisplayId(displayId);
1598 pCreature->SaveToDB();
1600 return true;
1602 //set faction of creature
1603 bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
1605 if (!*args)
1606 return false;
1608 uint32 factionId = (uint32) atoi((char*)args);
1610 if (!sFactionTemplateStore.LookupEntry(factionId))
1612 PSendSysMessage(LANG_WRONG_FACTION, factionId);
1613 SetSentErrorMessage(true);
1614 return false;
1617 Creature* pCreature = getSelectedCreature();
1619 if(!pCreature)
1621 SendSysMessage(LANG_SELECT_CREATURE);
1622 SetSentErrorMessage(true);
1623 return false;
1626 pCreature->setFaction(factionId);
1628 // faction is set in creature_template - not inside creature
1630 // update in memory
1631 if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1633 const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1634 const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1637 // and DB
1638 WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1640 return true;
1642 //set spawn dist of creature
1643 bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
1645 if(!*args)
1646 return false;
1648 float option = (float)atof((char*)args);
1649 if (option < 0.0f)
1651 SendSysMessage(LANG_BAD_VALUE);
1652 return false;
1655 MovementGeneratorType mtype = IDLE_MOTION_TYPE;
1656 if (option >0.0f)
1657 mtype = RANDOM_MOTION_TYPE;
1659 Creature *pCreature = getSelectedCreature();
1660 uint32 u_guidlow = 0;
1662 if (pCreature)
1663 u_guidlow = pCreature->GetDBTableGUIDLow();
1664 else
1665 return false;
1667 pCreature->SetRespawnRadius((float)option);
1668 pCreature->SetDefaultMovementType(mtype);
1669 pCreature->GetMotionMaster()->Initialize();
1670 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1672 pCreature->setDeathState(JUST_DIED);
1673 pCreature->Respawn();
1676 WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
1677 PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
1678 return true;
1680 //spawn time handling
1681 bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
1683 if(!*args)
1684 return false;
1686 char* stime = strtok((char*)args, " ");
1688 if (!stime)
1689 return false;
1691 int i_stime = atoi((char*)stime);
1693 if (i_stime < 0)
1695 SendSysMessage(LANG_BAD_VALUE);
1696 SetSentErrorMessage(true);
1697 return false;
1700 Creature *pCreature = getSelectedCreature();
1701 uint32 u_guidlow = 0;
1703 if (pCreature)
1704 u_guidlow = pCreature->GetDBTableGUIDLow();
1705 else
1706 return false;
1708 WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
1709 pCreature->SetRespawnDelay((uint32)i_stime);
1710 PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
1712 return true;
1714 //npc follow handling
1715 bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
1717 Player *player = m_session->GetPlayer();
1718 Creature *creature = getSelectedCreature();
1720 if(!creature)
1722 PSendSysMessage(LANG_SELECT_CREATURE);
1723 SetSentErrorMessage(true);
1724 return false;
1727 // Follow player - Using pet's default dist and angle
1728 creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
1730 PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
1731 return true;
1733 //npc unfollow handling
1734 bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
1736 Player *player = m_session->GetPlayer();
1737 Creature *creature = getSelectedCreature();
1739 if(!creature)
1741 PSendSysMessage(LANG_SELECT_CREATURE);
1742 SetSentErrorMessage(true);
1743 return false;
1746 if (creature->GetMotionMaster()->empty() ||
1747 creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=FOLLOW_MOTION_TYPE)
1749 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
1750 SetSentErrorMessage(true);
1751 return false;
1754 FollowMovementGenerator<Creature> const* mgen
1755 = static_cast<FollowMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
1757 if(mgen->GetTarget()!=player)
1759 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
1760 SetSentErrorMessage(true);
1761 return false;
1764 // reset movement
1765 creature->GetMotionMaster()->MovementExpired(true);
1767 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
1768 return true;
1770 //npc tame handling
1771 bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
1773 Creature *creatureTarget = getSelectedCreature ();
1774 if (!creatureTarget || creatureTarget->isPet ())
1776 PSendSysMessage (LANG_SELECT_CREATURE);
1777 SetSentErrorMessage (true);
1778 return false;
1781 Player *player = m_session->GetPlayer ();
1783 if(player->GetPetGUID ())
1785 SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
1786 SetSentErrorMessage (true);
1787 return false;
1790 CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
1792 if (!cInfo->isTameable (player->CanTameExoticPets()))
1794 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
1795 SetSentErrorMessage (true);
1796 return false;
1799 // Everything looks OK, create new pet
1800 Pet* pet = player->CreateTamedPetFrom (creatureTarget);
1801 if (!pet)
1803 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
1804 SetSentErrorMessage (true);
1805 return false;
1808 // place pet before player
1809 float x,y,z;
1810 player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
1811 pet->Relocate (x,y,z,M_PI_F-player->GetOrientation ());
1813 // set pet to defensive mode by default (some classes can't control controlled pets in fact).
1814 pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
1816 // calculate proper level
1817 uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
1819 // prepare visual effect for levelup
1820 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
1822 // add to world
1823 pet->GetMap()->Add((Creature*)pet);
1825 // visual effect for levelup
1826 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
1828 // caster have pet now
1829 player->SetPet(pet);
1831 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
1832 player->PetSpellInitialize();
1834 return true;
1836 //npc phasemask handling
1837 //change phasemask of creature or pet
1838 bool ChatHandler::HandleNpcSetPhaseCommand(const char* args)
1840 if (!*args)
1841 return false;
1843 uint32 phasemask = (uint32) atoi((char*)args);
1844 if ( phasemask == 0 )
1846 SendSysMessage(LANG_BAD_VALUE);
1847 SetSentErrorMessage(true);
1848 return false;
1851 Creature* pCreature = getSelectedCreature();
1852 if(!pCreature)
1854 SendSysMessage(LANG_SELECT_CREATURE);
1855 SetSentErrorMessage(true);
1856 return false;
1859 pCreature->SetPhaseMask(phasemask,true);
1861 if(!pCreature->isPet())
1862 pCreature->SaveToDB();
1864 return true;
1866 //npc deathstate handling
1867 bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args)
1869 if (!*args)
1870 return false;
1872 Creature* pCreature = getSelectedCreature();
1873 if(!pCreature || pCreature->isPet())
1875 SendSysMessage(LANG_SELECT_CREATURE);
1876 SetSentErrorMessage(true);
1877 return false;
1880 if (strncmp(args, "on", 3) == 0)
1881 pCreature->SetDeadByDefault(true);
1882 else if (strncmp(args, "off", 4) == 0)
1883 pCreature->SetDeadByDefault(false);
1884 else
1886 SendSysMessage(LANG_USE_BOL);
1887 SetSentErrorMessage(true);
1888 return false;
1891 pCreature->SaveToDB();
1892 pCreature->Respawn();
1894 return true;
1897 //TODO: NpcCommands that need to be fixed :
1899 bool ChatHandler::HandleNpcNameCommand(const char* /*args*/)
1901 /* Temp. disabled
1902 if(!*args)
1903 return false;
1905 if(strlen((char*)args)>75)
1907 PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
1908 return true;
1911 for (uint8 i = 0; i < strlen(args); ++i)
1913 if(!isalpha(args[i]) && args[i]!=' ')
1915 SendSysMessage(LANG_CHARS_ONLY);
1916 return false;
1920 uint64 guid;
1921 guid = m_session->GetPlayer()->GetSelection();
1922 if (guid == 0)
1924 SendSysMessage(LANG_NO_SELECTION);
1925 return true;
1928 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
1930 if(!pCreature)
1932 SendSysMessage(LANG_SELECT_CREATURE);
1933 return true;
1936 pCreature->SetName(args);
1937 uint32 idname = sObjectMgr.AddCreatureTemplate(pCreature->GetName());
1938 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
1940 pCreature->SaveToDB();
1943 return true;
1946 bool ChatHandler::HandleNpcSubNameCommand(const char* /*args*/)
1948 /* Temp. disabled
1950 if(!*args)
1951 args = "";
1953 if(strlen((char*)args)>75)
1956 PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
1957 return true;
1960 for (uint8 i = 0; i < strlen(args); i++)
1962 if(!isalpha(args[i]) && args[i]!=' ')
1964 SendSysMessage(LANG_CHARS_ONLY);
1965 return false;
1968 uint64 guid;
1969 guid = m_session->GetPlayer()->GetSelection();
1970 if (guid == 0)
1972 SendSysMessage(LANG_NO_SELECTION);
1973 return true;
1976 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
1978 if(!pCreature)
1980 SendSysMessage(LANG_SELECT_CREATURE);
1981 return true;
1984 uint32 idname = sObjectMgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
1985 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
1987 pCreature->SaveToDB();
1989 return true;
1992 //move item to other slot
1993 bool ChatHandler::HandleItemMoveCommand(const char* args)
1995 if(!*args)
1996 return false;
1997 uint8 srcslot, dstslot;
1999 char* pParam1 = strtok((char*)args, " ");
2000 if (!pParam1)
2001 return false;
2003 char* pParam2 = strtok(NULL, " ");
2004 if (!pParam2)
2005 return false;
2007 srcslot = (uint8)atoi(pParam1);
2008 dstslot = (uint8)atoi(pParam2);
2010 if(srcslot==dstslot)
2011 return true;
2013 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true))
2014 return false;
2016 // can be autostore pos
2017 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot, false))
2018 return false;
2020 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
2021 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
2023 m_session->GetPlayer()->SwapItem( src, dst );
2025 return true;
2028 //demorph player or unit
2029 bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
2031 Unit *target = getSelectedUnit();
2032 if(!target)
2033 target = m_session->GetPlayer();
2036 // check online security
2037 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2038 return false;
2040 target->DeMorph();
2042 return true;
2045 //morph creature or player
2046 bool ChatHandler::HandleModifyMorphCommand(const char* args)
2048 if (!*args)
2049 return false;
2051 uint16 display_id = (uint16)atoi((char*)args);
2053 Unit *target = getSelectedUnit();
2054 if(!target)
2055 target = m_session->GetPlayer();
2057 // check online security
2058 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2059 return false;
2061 target->SetDisplayId(display_id);
2063 return true;
2066 //kick player
2067 bool ChatHandler::HandleKickPlayerCommand(const char *args)
2069 Player* target;
2070 if(!extractPlayerTarget((char*)args,&target))
2071 return false;
2073 if (m_session && target==m_session->GetPlayer())
2075 SendSysMessage(LANG_COMMAND_KICKSELF);
2076 SetSentErrorMessage(true);
2077 return false;
2080 // check online security
2081 if (HasLowerSecurity(target, 0))
2082 return false;
2084 // send before target pointer invalidate
2085 PSendSysMessage(LANG_COMMAND_KICKMESSAGE,GetNameLink(target).c_str());
2086 target->GetSession()->KickPlayer();
2087 return true;
2090 //set temporary phase mask for player
2091 bool ChatHandler::HandleModifyPhaseCommand(const char* args)
2093 if (!*args)
2094 return false;
2096 uint32 phasemask = (uint32)atoi((char*)args);
2098 Unit *target = getSelectedUnit();
2099 if(!target)
2100 target = m_session->GetPlayer();
2102 // check online security
2103 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2104 return false;
2106 target->SetPhaseMask(phasemask,true);
2108 return true;
2111 //show info of player
2112 bool ChatHandler::HandlePInfoCommand(const char* args)
2114 Player* target;
2115 uint64 target_guid;
2116 std::string target_name;
2117 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
2118 return false;
2120 uint32 accId = 0;
2121 uint32 money = 0;
2122 uint32 total_player_time = 0;
2123 uint32 level = 0;
2124 uint32 latency = 0;
2126 // get additional information from Player object
2127 if(target)
2129 // check online security
2130 if (HasLowerSecurity(target, 0))
2131 return false;
2133 accId = target->GetSession()->GetAccountId();
2134 money = target->GetMoney();
2135 total_player_time = target->GetTotalPlayedTime();
2136 level = target->getLevel();
2137 latency = target->GetSession()->GetLatency();
2139 // get additional information from DB
2140 else
2142 // check offline security
2143 if (HasLowerSecurity(NULL, target_guid))
2144 return false;
2146 // 0 1 2 3
2147 QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime, level, money, account FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid));
2148 if (!result)
2149 return false;
2151 Field *fields = result->Fetch();
2152 total_player_time = fields[0].GetUInt32();
2153 level = fields[1].GetUInt32();
2154 money = fields[2].GetUInt32();
2155 accId = fields[3].GetUInt32();
2156 delete result;
2159 std::string username = GetMangosString(LANG_ERROR);
2160 std::string last_ip = GetMangosString(LANG_ERROR);
2161 AccountTypes security = SEC_PLAYER;
2162 std::string last_login = GetMangosString(LANG_ERROR);
2164 QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
2165 if(result)
2167 Field* fields = result->Fetch();
2168 username = fields[0].GetCppString();
2169 security = (AccountTypes)fields[1].GetUInt32();
2171 if(GetAccessLevel() >= security)
2173 last_ip = fields[2].GetCppString();
2174 last_login = fields[3].GetCppString();
2176 else
2178 last_ip = "-";
2179 last_login = "-";
2182 delete result;
2185 std::string nameLink = playerLink(target_name);
2187 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);
2189 std::string timeStr = secsToTimeString(total_player_time,true,true);
2190 uint32 gold = money /GOLD;
2191 uint32 silv = (money % GOLD) / SILVER;
2192 uint32 copp = (money % GOLD) % SILVER;
2193 PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp );
2195 return true;
2198 //show tickets
2199 void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
2201 std::string name;
2202 if(!sObjectMgr.GetPlayerNameByGUID(guid,name))
2203 name = GetMangosString(LANG_UNKNOWN);
2205 std::string nameLink = playerLink(name);
2207 PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(),time,text);
2210 //ticket commands
2211 bool ChatHandler::HandleTicketCommand(const char* args)
2213 char* px = strtok((char*)args, " ");
2215 // ticket<end>
2216 if (!px)
2218 if(!m_session)
2220 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2221 SetSentErrorMessage(true);
2222 return false;
2225 size_t count = sTicketMgr.GetTicketCount();
2227 bool accept = m_session->GetPlayer()->isAcceptTickets();
2229 PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
2230 return true;
2233 // ticket on
2234 if(strncmp(px,"on",3) == 0)
2236 if(!m_session)
2238 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2239 SetSentErrorMessage(true);
2240 return false;
2243 m_session->GetPlayer()->SetAcceptTicket(true);
2244 SendSysMessage(LANG_COMMAND_TICKETON);
2245 return true;
2248 // ticket off
2249 if(strncmp(px,"off",4) == 0)
2251 if(!m_session)
2253 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2254 SetSentErrorMessage(true);
2255 return false;
2258 m_session->GetPlayer()->SetAcceptTicket(false);
2259 SendSysMessage(LANG_COMMAND_TICKETOFF);
2260 return true;
2263 // ticket respond
2264 if(strncmp(px,"respond",8) == 0)
2266 char *name = strtok(NULL, " ");
2268 if(!name)
2270 SendSysMessage(LANG_CMD_SYNTAX);
2271 SetSentErrorMessage(true);
2272 return false;
2275 std::string plName = name;
2276 uint64 guid = sObjectMgr.GetPlayerGUIDByName(plName);
2278 if(!guid)
2280 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2281 SetSentErrorMessage(true);
2282 return false;
2285 GMTicket* ticket = sTicketMgr.GetGMTicket(GUID_LOPART(guid));
2287 if(!ticket)
2289 PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, GUID_LOPART(guid));
2290 SetSentErrorMessage(true);
2291 return false;
2294 char* response = strtok(NULL, "");
2296 if(!response)
2298 SendSysMessage(LANG_CMD_SYNTAX);
2299 SetSentErrorMessage(true);
2300 return false;
2303 ticket->SetResponseText(response);
2305 if(Player* pl = sObjectMgr.GetPlayer(guid))
2306 pl->GetSession()->SendGMResponse(ticket);
2308 return true;
2311 // ticket #num
2312 int num = atoi(px);
2313 if(num > 0)
2315 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
2317 if(!result)
2319 PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num);
2320 SetSentErrorMessage(true);
2321 return false;
2324 Field* fields = result->Fetch();
2326 uint32 guid = fields[0].GetUInt32();
2327 char const* text = fields[1].GetString();
2328 char const* time = fields[2].GetString();
2330 ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
2331 delete result;
2332 return true;
2335 uint64 target_guid;
2336 if(!extractPlayerTarget(px,NULL,&target_guid))
2337 return false;
2339 // ticket $char_name
2340 GMTicket* ticket = sTicketMgr.GetGMTicket(GUID_LOPART(target_guid));
2341 if(!ticket)
2342 return false;
2344 std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
2346 ShowTicket(target_guid, ticket->GetText(), time.c_str());
2348 return true;
2351 //dell all tickets
2352 bool ChatHandler::HandleDelTicketCommand(const char *args)
2354 char* px = strtok((char*)args, " ");
2355 if (!px)
2356 return false;
2358 // delticket all
2359 if(strncmp(px,"all",4) == 0)
2361 sTicketMgr.DeleteAll();
2362 SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2363 return true;
2366 int num = (uint32)atoi(px);
2368 // delticket #num
2369 if(num > 0)
2371 QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2372 if(!result)
2374 PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num);
2375 SetSentErrorMessage(true);
2376 return false;
2378 Field* fields = result->Fetch();
2379 uint32 guid = fields[0].GetUInt32();
2380 delete result;
2382 sTicketMgr.Delete(guid);
2384 //notify player
2385 if(Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, guid)))
2387 pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
2388 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str());
2390 else
2391 PSendSysMessage(LANG_COMMAND_TICKETDEL);
2393 return true;
2396 Player* target;
2397 uint64 target_guid;
2398 std::string target_name;
2399 if(!extractPlayerTarget(px,&target,&target_guid,&target_name))
2400 return false;
2402 // delticket $char_name
2403 sTicketMgr.Delete(GUID_LOPART(target_guid));
2405 // notify players about ticket deleting
2406 if(target)
2407 target->GetSession()->SendGMTicketGetTicket(0x0A,0);
2409 std::string nameLink = playerLink(target_name);
2411 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,nameLink.c_str());
2412 return true;
2416 * Add a waypoint to a creature.
2418 * The user can either select an npc or provide its GUID.
2420 * The user can even select a visual waypoint - then the new waypoint
2421 * is placed *after* the selected one - this makes insertion of new
2422 * waypoints possible.
2424 * eg:
2425 * .wp add 12345
2426 * -> adds a waypoint to the npc with the GUID 12345
2428 * .wp add
2429 * -> adds a waypoint to the currently selected creature
2432 * @param args if the user did not provide a GUID, it is NULL
2434 * @return true - command did succeed, false - something went wrong
2436 bool ChatHandler::HandleWpAddCommand(const char* args)
2438 DEBUG_LOG("DEBUG: HandleWpAddCommand");
2440 // optional
2441 char* guid_str = NULL;
2443 if(*args)
2445 guid_str = strtok((char*)args, " ");
2448 uint32 lowguid = 0;
2449 uint32 point = 0;
2450 Creature* target = getSelectedCreature();
2451 // Did player provide a GUID?
2452 if (!guid_str)
2454 DEBUG_LOG("DEBUG: HandleWpAddCommand - No GUID provided");
2456 // No GUID provided
2457 // -> Player must have selected a creature
2459 if(!target || target->isPet())
2461 SendSysMessage(LANG_SELECT_CREATURE);
2462 SetSentErrorMessage(true);
2463 return false;
2465 if (target->GetEntry() == VISUAL_WAYPOINT )
2467 DEBUG_LOG("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2469 QueryResult *result =
2470 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2471 target->GetGUIDLow() );
2472 if(!result)
2474 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2475 // User selected a visual spawnpoint -> get the NPC
2476 // Select NPC GUID
2477 // Since we compare float values, we have to deal with
2478 // some difficulties.
2479 // Here we search for all waypoints that only differ in one from 1 thousand
2480 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2481 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2482 const char* maxDIFF = "0.01";
2483 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 )",
2484 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2485 if(!result)
2487 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2488 SetSentErrorMessage(true);
2489 return false;
2494 Field *fields = result->Fetch();
2495 lowguid = fields[0].GetUInt32();
2496 point = fields[1].GetUInt32();
2497 }while( result->NextRow() );
2498 delete result;
2500 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2501 if(!data)
2503 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2504 SetSentErrorMessage(true);
2505 return false;
2508 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2509 if(!target)
2511 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2512 SetSentErrorMessage(true);
2513 return false;
2516 else
2518 lowguid = target->GetDBTableGUIDLow();
2521 else
2523 DEBUG_LOG("DEBUG: HandleWpAddCommand - GUID provided");
2525 // GUID provided
2526 // Warn if player also selected a creature
2527 // -> Creature selection is ignored <-
2528 if(target)
2530 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2532 lowguid = atoi((char*)guid_str);
2534 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2535 if(!data)
2537 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2538 SetSentErrorMessage(true);
2539 return false;
2542 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2543 if(!target || target->isPet())
2545 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2546 SetSentErrorMessage(true);
2547 return false;
2550 // lowguid -> GUID of the NPC
2551 // point -> number of the waypoint (if not 0)
2552 DEBUG_LOG("DEBUG: HandleWpAddCommand - danach");
2554 DEBUG_LOG("DEBUG: HandleWpAddCommand - point == 0");
2556 Player* player = m_session->GetPlayer();
2557 sWaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2559 // update movement type
2560 if(target)
2562 target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2563 target->GetMotionMaster()->Initialize();
2564 if(target->isAlive()) // dead creature will reset movement generator at respawn
2566 target->setDeathState(JUST_DIED);
2567 target->Respawn();
2569 target->SaveToDB();
2571 else
2572 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2574 PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2576 return true;
2577 } // HandleWpAddCommand
2580 * .wp modify emote | spell | text | del | move | add
2582 * add -> add a WP after the selected visual waypoint
2583 * User must select a visual waypoint and then issue ".wp modify add"
2585 * emote <emoteID>
2586 * User has selected a visual waypoint before.
2587 * <emoteID> is added to this waypoint. Everytime the
2588 * NPC comes to this waypoint, the emote is called.
2590 * emote <GUID> <WPNUM> <emoteID>
2591 * User has not selected visual waypoint before.
2592 * For the waypoint <WPNUM> for the NPC with <GUID>
2593 * an emote <emoteID> is added.
2594 * Everytime the NPC comes to this waypoint, the emote is called.
2597 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2599 bool ChatHandler::HandleWpModifyCommand(const char* args)
2601 DEBUG_LOG("DEBUG: HandleWpModifyCommand");
2603 if(!*args)
2604 return false;
2606 // first arg: add del text emote spell waittime move
2607 char* show_str = strtok((char*)args, " ");
2608 if (!show_str)
2610 return false;
2613 std::string show = show_str;
2614 // Check
2615 // Remember: "show" must also be the name of a column!
2616 if( (show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2")
2617 && (show != "textid3") && (show != "textid4") && (show != "textid5")
2618 && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2619 && (show != "model1") && (show != "model2") && (show != "orientation"))
2621 return false;
2624 // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2626 // Did user provide a GUID
2627 // or did the user select a creature?
2628 // -> variable lowguid is filled with the GUID of the NPC
2629 uint32 lowguid = 0;
2630 uint32 point = 0;
2631 uint32 wpGuid = 0;
2632 Creature* target = getSelectedCreature();
2634 if(target)
2636 DEBUG_LOG("DEBUG: HandleWpModifyCommand - User did select an NPC");
2638 // Did the user select a visual spawnpoint?
2639 if (target->GetEntry() != VISUAL_WAYPOINT )
2641 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2642 SetSentErrorMessage(true);
2643 return false;
2646 wpGuid = target->GetGUIDLow();
2648 // The visual waypoint
2649 QueryResult *result =
2650 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2651 target->GetGUIDLow() );
2652 if(!result)
2654 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2655 SetSentErrorMessage(true);
2656 return false;
2658 DEBUG_LOG("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2660 Field *fields = result->Fetch();
2661 lowguid = fields[0].GetUInt32();
2662 point = fields[1].GetUInt32();
2664 // Cleanup memory
2665 DEBUG_LOG("DEBUG: HandleWpModifyCommand - Cleanup memory");
2666 delete result;
2668 else
2670 // User did provide <GUID> <WPNUM>
2672 char* guid_str = strtok((char*)NULL, " ");
2673 if( !guid_str )
2675 SendSysMessage(LANG_WAYPOINT_NOGUID);
2676 return false;
2678 lowguid = atoi((char*)guid_str);
2680 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2681 if(!data)
2683 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2684 SetSentErrorMessage(true);
2685 return false;
2688 PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2690 char* point_str = strtok((char*)NULL, " ");
2691 if( !point_str )
2693 SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2694 return false;
2696 point = atoi((char*)point_str);
2698 PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2700 // Now we need the GUID of the visual waypoint
2701 // -> "del", "move", "add" command
2703 QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2704 if (!result)
2706 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2707 SetSentErrorMessage(true);
2708 return false;
2711 Field *fields = result->Fetch();
2712 wpGuid = fields[0].GetUInt32();
2714 // Free memory
2715 delete result;
2718 char* arg_str = NULL;
2719 // Check for argument
2720 if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2722 // Text is enclosed in "<>", all other arguments not
2723 if( show.find("text") != std::string::npos )
2724 arg_str = strtok((char*)NULL, "<>");
2725 else
2726 arg_str = strtok((char*)NULL, " ");
2728 if( !arg_str)
2730 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2731 return false;
2735 DEBUG_LOG("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2737 // wpGuid -> GUID of the waypoint creature
2738 // lowguid -> GUID of the NPC
2739 // point -> waypoint number
2741 // Special functions:
2742 // add - move - del -> no args commands
2743 // Add a waypoint after the selected visual
2744 if(show == "add" && target)
2746 PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2748 // Get the creature for which we read the waypoint
2749 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2750 if(!data)
2752 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2753 SetSentErrorMessage(true);
2754 return false;
2757 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2759 if( !npcCreature )
2761 PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2762 SetSentErrorMessage(true);
2763 return false;
2766 DEBUG_LOG("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2768 // What to do:
2769 // Add the visual spawnpoint (DB only)
2770 // Adjust the waypoints
2771 // Respawn the owner of the waypoints
2772 DEBUG_LOG("DEBUG: HandleWpModifyCommand - add");
2774 Player* chr = m_session->GetPlayer();
2775 Map *map = chr->GetMap();
2777 if(npcCreature)
2779 npcCreature->GetMotionMaster()->Initialize();
2780 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2782 npcCreature->setDeathState(JUST_DIED);
2783 npcCreature->Respawn();
2787 // create the waypoint creature
2788 wpGuid = 0;
2789 Creature* wpCreature = new Creature;
2790 if (!wpCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT,0))
2792 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2793 delete wpCreature;
2795 else
2797 wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2799 if(!wpCreature->IsPositionValid())
2801 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());
2802 delete wpCreature;
2804 else
2806 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
2807 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2808 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2809 map->Add(wpCreature);
2810 wpGuid = wpCreature->GetGUIDLow();
2814 sWaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2816 if(!wpGuid)
2817 return false;
2819 PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2820 return true;
2821 } // add
2823 if(show == "del" && target)
2825 PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2827 // Get the creature for which we read the waypoint
2828 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2829 if(!data)
2831 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2832 SetSentErrorMessage(true);
2833 return false;
2836 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2838 // wpCreature
2839 Creature* wpCreature = NULL;
2840 if( wpGuid != 0 )
2842 wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2843 wpCreature->DeleteFromDB();
2844 wpCreature->AddObjectToRemoveList();
2847 // What to do:
2848 // Remove the visual spawnpoint
2849 // Adjust the waypoints
2850 // Respawn the owner of the waypoints
2852 sWaypointMgr.DeleteNode(lowguid, point);
2854 if(npcCreature)
2856 // Any waypoints left?
2857 QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2858 if(!result2)
2860 npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2862 else
2864 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2865 delete result2;
2867 npcCreature->GetMotionMaster()->Initialize();
2868 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2870 npcCreature->setDeathState(JUST_DIED);
2871 npcCreature->Respawn();
2873 npcCreature->SaveToDB();
2876 PSendSysMessage(LANG_WAYPOINT_REMOVED);
2877 return true;
2878 } // del
2880 if(show == "move" && target)
2882 PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2884 Player *chr = m_session->GetPlayer();
2885 Map *map = chr->GetMap();
2887 // Get the creature for which we read the waypoint
2888 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2889 if(!data)
2891 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2892 SetSentErrorMessage(true);
2893 return false;
2896 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2898 // wpCreature
2899 Creature* wpCreature = NULL;
2900 // What to do:
2901 // Move the visual spawnpoint
2902 // Respawn the owner of the waypoints
2903 if( wpGuid != 0 )
2905 wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2906 wpCreature->DeleteFromDB();
2907 wpCreature->AddObjectToRemoveList();
2908 // re-create
2909 Creature* wpCreature2 = new Creature;
2910 if (!wpCreature2->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0))
2912 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2913 delete wpCreature2;
2914 return false;
2917 wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2919 if(!wpCreature2->IsPositionValid())
2921 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());
2922 delete wpCreature2;
2923 return false;
2926 wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
2927 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2928 wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2929 map->Add(wpCreature2);
2930 //npcCreature->GetMap()->Add(wpCreature2);
2933 sWaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2935 if(npcCreature)
2937 npcCreature->GetMotionMaster()->Initialize();
2938 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2940 npcCreature->setDeathState(JUST_DIED);
2941 npcCreature->Respawn();
2944 PSendSysMessage(LANG_WAYPOINT_CHANGED);
2946 return true;
2947 } // move
2949 // Create creature - npc that has the waypoint
2950 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
2951 if(!data)
2953 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2954 SetSentErrorMessage(true);
2955 return false;
2958 // set in game textids not supported
2959 if( show == "textid1" || show == "textid2" || show == "textid3" ||
2960 show == "textid4" || show == "textid5" )
2962 return false;
2965 sWaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2967 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2968 if(npcCreature)
2970 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2971 npcCreature->GetMotionMaster()->Initialize();
2972 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2974 npcCreature->setDeathState(JUST_DIED);
2975 npcCreature->Respawn();
2978 PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2980 return true;
2984 * .wp show info | on | off
2986 * info -> User has selected a visual waypoint before
2988 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2989 * provided the GUID of the NPC and the number of
2990 * the waypoint.
2992 * on -> User has selected an NPC; all visual waypoints for this
2993 * NPC are added to the world
2995 * on <GUID> -> User did not select an NPC - instead the GUID of the
2996 * NPC is provided. All visual waypoints for this NPC
2997 * are added from the world.
2999 * off -> User has selected an NPC; all visual waypoints for this
3000 * NPC are removed from the world.
3002 * on <GUID> -> User did not select an NPC - instead the GUID of the
3003 * NPC is provided. All visual waypoints for this NPC
3004 * are removed from the world.
3008 bool ChatHandler::HandleWpShowCommand(const char* args)
3010 DEBUG_LOG("DEBUG: HandleWpShowCommand");
3012 if(!*args)
3013 return false;
3015 // first arg: on, off, first, last
3016 char* show_str = strtok((char*)args, " ");
3017 if (!show_str)
3019 return false;
3021 // second arg: GUID (optional, if a creature is selected)
3022 char* guid_str = strtok((char*)NULL, " ");
3023 DEBUG_LOG("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
3024 //if (!guid_str) {
3025 // return false;
3028 // Did user provide a GUID
3029 // or did the user select a creature?
3030 // -> variable lowguid is filled with the GUID
3031 Creature* target = getSelectedCreature();
3032 // Did player provide a GUID?
3033 if (!guid_str)
3035 DEBUG_LOG("DEBUG: HandleWpShowCommand: !guid_str");
3036 // No GUID provided
3037 // -> Player must have selected a creature
3039 if(!target)
3041 SendSysMessage(LANG_SELECT_CREATURE);
3042 SetSentErrorMessage(true);
3043 return false;
3046 else
3048 DEBUG_LOG("DEBUG: HandleWpShowCommand: GUID provided");
3049 // GUID provided
3050 // Warn if player also selected a creature
3051 // -> Creature selection is ignored <-
3052 if(target)
3054 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
3057 uint32 lowguid = atoi((char*)guid_str);
3059 CreatureData const* data = sObjectMgr.GetCreatureData(lowguid);
3060 if(!data)
3062 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
3063 SetSentErrorMessage(true);
3064 return false;
3067 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
3069 if(!target)
3071 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
3072 SetSentErrorMessage(true);
3073 return false;
3077 uint32 lowguid = target->GetDBTableGUIDLow();
3079 std::string show = show_str;
3080 uint32 Maxpoint;
3082 DEBUG_LOG("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
3084 // Show info for the selected waypoint
3085 if(show == "info")
3087 PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
3089 // Check if the user did specify a visual waypoint
3090 if( target->GetEntry() != VISUAL_WAYPOINT )
3092 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
3093 SetSentErrorMessage(true);
3094 return false;
3097 //PSendSysMessage("wp on, GUID: %u", lowguid);
3099 //pCreature->GetPositionX();
3101 QueryResult *result =
3102 WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u",
3103 target->GetGUIDLow() );
3104 if(!result)
3106 // Since we compare float values, we have to deal with
3107 // some difficulties.
3108 // Here we search for all waypoints that only differ in one from 1 thousand
3109 // (0.001) - There is no other way to compare C++ floats with mySQL floats
3110 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
3111 const char* maxDIFF = "0.01";
3112 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
3114 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 )",
3115 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
3116 if(!result)
3118 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
3119 SetSentErrorMessage(true);
3120 return false;
3125 Field *fields = result->Fetch();
3126 uint32 creGUID = fields[0].GetUInt32();
3127 uint32 point = fields[1].GetUInt32();
3128 int waittime = fields[2].GetUInt32();
3129 uint32 emote = fields[3].GetUInt32();
3130 uint32 spell = fields[4].GetUInt32();
3131 uint32 textid[MAX_WAYPOINT_TEXT];
3132 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
3133 textid[i] = fields[5+i].GetUInt32();
3134 uint32 model1 = fields[10].GetUInt32();
3135 uint32 model2 = fields[11].GetUInt32();
3137 // Get the creature for which we read the waypoint
3138 Creature* wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3140 PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
3141 PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
3142 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
3143 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
3144 PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
3145 PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
3146 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
3147 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i+1, textid[i], (textid[i] ? GetMangosString(textid[i]) : ""));
3149 }while( result->NextRow() );
3150 // Cleanup memory
3151 delete result;
3152 return true;
3155 if(show == "on")
3157 PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
3159 QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
3160 if(!result)
3162 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3163 SetSentErrorMessage(true);
3164 return false;
3166 // Delete all visuals for this NPC
3167 QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
3168 if(result2)
3170 bool hasError = false;
3173 Field *fields = result2->Fetch();
3174 uint32 wpguid = fields[0].GetUInt32();
3175 Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3177 if(!pCreature)
3179 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
3180 hasError = true;
3181 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
3183 else
3185 pCreature->DeleteFromDB();
3186 pCreature->AddObjectToRemoveList();
3189 }while( result2->NextRow() );
3190 delete result2;
3191 if( hasError )
3193 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3194 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3195 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3201 Field *fields = result->Fetch();
3202 uint32 point = fields[0].GetUInt32();
3203 float x = fields[1].GetFloat();
3204 float y = fields[2].GetFloat();
3205 float z = fields[3].GetFloat();
3207 uint32 id = VISUAL_WAYPOINT;
3209 Player *chr = m_session->GetPlayer();
3210 Map *map = chr->GetMap();
3211 float o = chr->GetOrientation();
3213 Creature* wpCreature = new Creature;
3214 if (!wpCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
3216 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3217 delete wpCreature;
3218 delete result;
3219 return false;
3222 wpCreature->Relocate(x, y, z, o);
3224 if(!wpCreature->IsPositionValid())
3226 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());
3227 delete wpCreature;
3228 delete result;
3229 return false;
3232 wpCreature->SetVisibility(VISIBILITY_OFF);
3233 DEBUG_LOG("DEBUG: UPDATE creature_movement SET wpguid = '%u", wpCreature->GetGUIDLow());
3234 // set "wpguid" column to the visual waypoint
3235 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
3237 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3238 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
3239 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
3240 map->Add(wpCreature);
3241 //wpCreature->GetMap()->Add(wpCreature);
3242 }while( result->NextRow() );
3244 // Cleanup memory
3245 delete result;
3246 return true;
3249 if(show == "first")
3251 PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3253 QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3254 if(!result)
3256 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3257 SetSentErrorMessage(true);
3258 return false;
3261 Field *fields = result->Fetch();
3262 float x = fields[0].GetFloat();
3263 float y = fields[1].GetFloat();
3264 float z = fields[2].GetFloat();
3265 uint32 id = VISUAL_WAYPOINT;
3267 Player *chr = m_session->GetPlayer();
3268 float o = chr->GetOrientation();
3269 Map *map = chr->GetMap();
3271 Creature* pCreature = new Creature;
3272 if (!pCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0))
3274 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3275 delete pCreature;
3276 delete result;
3277 return false;
3280 pCreature->Relocate(x, y, z, o);
3282 if(!pCreature->IsPositionValid())
3284 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());
3285 delete pCreature;
3286 delete result;
3287 return false;
3290 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3291 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3292 map->Add(pCreature);
3293 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3295 // Cleanup memory
3296 delete result;
3297 return true;
3300 if(show == "last")
3302 PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3304 QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3305 if( result )
3307 Maxpoint = (*result)[0].GetUInt32();
3309 delete result;
3311 else
3312 Maxpoint = 0;
3314 result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3315 if(!result)
3317 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3318 SetSentErrorMessage(true);
3319 return false;
3321 Field *fields = result->Fetch();
3322 float x = fields[0].GetFloat();
3323 float y = fields[1].GetFloat();
3324 float z = fields[2].GetFloat();
3325 uint32 id = VISUAL_WAYPOINT;
3327 Player *chr = m_session->GetPlayer();
3328 float o = chr->GetOrientation();
3329 Map *map = chr->GetMap();
3331 Creature* pCreature = new Creature;
3332 if (!pCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
3334 PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3335 delete pCreature;
3336 delete result;
3337 return false;
3340 pCreature->Relocate(x, y, z, o);
3342 if(!pCreature->IsPositionValid())
3344 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());
3345 delete pCreature;
3346 delete result;
3347 return false;
3350 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3351 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3352 map->Add(pCreature);
3353 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3354 // Cleanup memory
3355 delete result;
3356 return true;
3359 if(show == "off")
3361 QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3362 if(!result)
3364 SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3365 SetSentErrorMessage(true);
3366 return false;
3368 bool hasError = false;
3371 Field *fields = result->Fetch();
3372 uint32 guid = fields[0].GetUInt32();
3373 Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3374 if(!pCreature)
3376 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3377 hasError = true;
3378 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3380 else
3382 pCreature->DeleteFromDB();
3383 pCreature->AddObjectToRemoveList();
3385 }while(result->NextRow());
3386 // set "wpguid" column to "empty" - no visual waypoint spawned
3387 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
3389 if( hasError )
3391 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3392 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3393 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3396 SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3397 // Cleanup memory
3398 delete result;
3400 return true;
3403 PSendSysMessage("DEBUG: wpshow - no valid command found");
3405 return true;
3406 } // HandleWpShowCommand
3408 bool ChatHandler::HandleWpExportCommand(const char *args)
3410 if(!*args)
3411 return false;
3413 // Next arg is: <GUID> <ARGUMENT>
3415 // Did user provide a GUID
3416 // or did the user select a creature?
3417 // -> variable lowguid is filled with the GUID of the NPC
3418 uint32 lowguid = 0;
3419 Creature* target = getSelectedCreature();
3420 char* arg_str = NULL;
3421 if (target)
3423 if (target->GetEntry() != VISUAL_WAYPOINT)
3424 lowguid = target->GetGUIDLow();
3425 else
3427 QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3428 if (!result)
3430 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3431 return true;
3433 Field *fields = result->Fetch();
3434 lowguid = fields[0].GetUInt32();;
3435 delete result;
3438 arg_str = strtok((char*)args, " ");
3440 else
3442 // user provided <GUID>
3443 char* guid_str = strtok((char*)args, " ");
3444 if( !guid_str )
3446 SendSysMessage(LANG_WAYPOINT_NOGUID);
3447 return false;
3449 lowguid = atoi((char*)guid_str);
3451 arg_str = strtok((char*)NULL, " ");
3454 if( !arg_str)
3456 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3457 return false;
3460 PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3462 QueryResult *result = WorldDatabase.PQuery(
3463 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3464 "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 );
3466 if (!result)
3468 PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3469 SetSentErrorMessage(true);
3470 return false;
3473 std::ofstream outfile;
3474 outfile.open (arg_str);
3478 Field *fields = result->Fetch();
3480 outfile << "INSERT INTO creature_movement ";
3481 outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5 ) VALUES ";
3483 outfile << "( ";
3484 outfile << fields[15].GetUInt32(); // id
3485 outfile << ", ";
3486 outfile << fields[0].GetUInt32(); // point
3487 outfile << ", ";
3488 outfile << fields[1].GetFloat(); // position_x
3489 outfile << ", ";
3490 outfile << fields[2].GetFloat(); // position_y
3491 outfile << ", ";
3492 outfile << fields[3].GetUInt32(); // position_z
3493 outfile << ", ";
3494 outfile << fields[4].GetUInt32(); // orientation
3495 outfile << ", ";
3496 outfile << fields[5].GetUInt32(); // model1
3497 outfile << ", ";
3498 outfile << fields[6].GetUInt32(); // model2
3499 outfile << ", ";
3500 outfile << fields[7].GetUInt16(); // waittime
3501 outfile << ", ";
3502 outfile << fields[8].GetUInt32(); // emote
3503 outfile << ", ";
3504 outfile << fields[9].GetUInt32(); // spell
3505 outfile << ", ";
3506 outfile << fields[10].GetUInt32(); // textid1
3507 outfile << ", ";
3508 outfile << fields[11].GetUInt32(); // textid2
3509 outfile << ", ";
3510 outfile << fields[12].GetUInt32(); // textid3
3511 outfile << ", ";
3512 outfile << fields[13].GetUInt32(); // textid4
3513 outfile << ", ";
3514 outfile << fields[14].GetUInt32(); // textid5
3515 outfile << ");\n ";
3517 } while( result->NextRow() );
3518 delete result;
3520 PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3521 outfile.close();
3523 return true;
3526 bool ChatHandler::HandleWpImportCommand(const char *args)
3528 if(!*args)
3529 return false;
3531 char* arg_str = strtok((char*)args, " ");
3532 if (!arg_str)
3533 return false;
3535 std::string line;
3536 std::ifstream infile (arg_str);
3537 if (infile.is_open())
3539 while (! infile.eof() )
3541 getline (infile,line);
3542 //cout << line << endl;
3543 QueryResult *result = WorldDatabase.Query(line.c_str());
3544 delete result;
3546 infile.close();
3548 PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3550 return true;
3553 //rename characters
3554 bool ChatHandler::HandleCharacterRenameCommand(const char* args)
3556 Player* target;
3557 uint64 target_guid;
3558 std::string target_name;
3559 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
3560 return false;
3562 if(target)
3564 // check online security
3565 if (HasLowerSecurity(target, 0))
3566 return false;
3568 PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str());
3569 target->SetAtLoginFlag(AT_LOGIN_RENAME);
3570 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3572 else
3574 // check offline security
3575 if (HasLowerSecurity(NULL, target_guid))
3576 return false;
3578 std::string oldNameLink = playerLink(target_name);
3580 PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid));
3581 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(target_guid));
3584 return true;
3587 // customize characters
3588 bool ChatHandler::HandleCharacterCustomizeCommand(const char* args)
3590 Player* target;
3591 uint64 target_guid;
3592 std::string target_name;
3593 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
3594 return false;
3596 if(target)
3598 PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str());
3599 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
3600 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow());
3602 else
3604 std::string oldNameLink = playerLink(target_name);
3606 PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid));
3607 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(target_guid));
3610 return true;
3613 bool ChatHandler::HandleCharacterReputationCommand(const char* args)
3615 Player* target;
3616 if(!extractPlayerTarget((char*)args,&target))
3617 return false;
3619 LocaleConstant loc = GetSessionDbcLocale();
3621 FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList();
3622 for(FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr)
3624 FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
3625 char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#";
3626 ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
3627 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
3628 std::ostringstream ss;
3629 if (m_session)
3630 ss << itr->second.ID << " - |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << " " << localeNames[loc] << "]|h|r";
3631 else
3632 ss << itr->second.ID << " - " << factionName << " " << localeNames[loc];
3634 ss << " " << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ")";
3636 if(itr->second.Flags & FACTION_FLAG_VISIBLE)
3637 ss << GetMangosString(LANG_FACTION_VISIBLE);
3638 if(itr->second.Flags & FACTION_FLAG_AT_WAR)
3639 ss << GetMangosString(LANG_FACTION_ATWAR);
3640 if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
3641 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
3642 if(itr->second.Flags & FACTION_FLAG_HIDDEN)
3643 ss << GetMangosString(LANG_FACTION_HIDDEN);
3644 if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
3645 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
3646 if(itr->second.Flags & FACTION_FLAG_INACTIVE)
3647 ss << GetMangosString(LANG_FACTION_INACTIVE);
3649 SendSysMessage(ss.str().c_str());
3651 return true;
3654 //change standstate
3655 bool ChatHandler::HandleModifyStandStateCommand(const char* args)
3657 if (!*args)
3658 return false;
3660 uint32 anim_id = atoi((char*)args);
3662 if (!sEmotesStore.LookupEntry(anim_id))
3663 return false;
3665 m_session->GetPlayer()->HandleEmoteState(anim_id);
3667 return true;
3670 bool ChatHandler::HandleHonorAddCommand(const char* args)
3672 if (!*args)
3673 return false;
3675 Player *target = getSelectedPlayer();
3676 if(!target)
3678 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3679 SetSentErrorMessage(true);
3680 return false;
3683 // check online security
3684 if (HasLowerSecurity(target, 0))
3685 return false;
3687 float amount = (float)atof(args);
3688 target->RewardHonor(NULL, 1, amount);
3689 return true;
3692 bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3694 Unit *target = getSelectedUnit();
3695 if(!target)
3697 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3698 SetSentErrorMessage(true);
3699 return false;
3702 // check online security
3703 if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
3704 return false;
3706 m_session->GetPlayer()->RewardHonor(target, 1);
3707 return true;
3710 bool ChatHandler::HandleHonorUpdateCommand(const char* /*args*/)
3712 Player *target = getSelectedPlayer();
3713 if(!target)
3715 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3716 SetSentErrorMessage(true);
3717 return false;
3720 // check online security
3721 if (HasLowerSecurity(target, 0))
3722 return false;
3724 target->UpdateHonorFields();
3725 return true;
3728 bool ChatHandler::HandleLookupEventCommand(const char* args)
3730 if(!*args)
3731 return false;
3733 std::string namepart = args;
3734 std::wstring wnamepart;
3736 // converting string that we try to find to lower case
3737 if(!Utf8toWStr(namepart,wnamepart))
3738 return false;
3740 wstrToLower(wnamepart);
3742 uint32 counter = 0;
3744 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3745 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3747 for(uint32 id = 0; id < events.size(); ++id )
3749 GameEventData const& eventData = events[id];
3751 std::string descr = eventData.description;
3752 if(descr.empty())
3753 continue;
3755 if (Utf8FitTo(descr, wnamepart))
3757 char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : "";
3759 if(m_session)
3760 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3761 else
3762 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3764 ++counter;
3768 if (counter==0)
3769 SendSysMessage(LANG_NOEVENTFOUND);
3771 return true;
3774 bool ChatHandler::HandleEventListCommand(const char* args)
3776 uint32 counter = 0;
3777 bool all = false;
3778 std::string arg = args;
3779 if (arg == "all")
3780 all = true;
3782 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3783 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3785 char const* active = GetMangosString(LANG_ACTIVE);
3786 char const* inactive = GetMangosString(LANG_FACTION_INACTIVE);
3787 char const* state = "";
3789 for (uint32 event_id = 0; event_id < events.size(); ++event_id)
3791 if (activeEvents.find(event_id) == activeEvents.end())
3793 if (!all)
3794 continue;
3795 state = inactive;
3797 else
3798 state = active;
3800 GameEventData const& eventData = events[event_id];
3802 if(m_session)
3803 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT, event_id, event_id, eventData.description.c_str(), state);
3804 else
3805 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE, event_id, eventData.description.c_str(), state);
3807 ++counter;
3810 if (counter==0)
3811 SendSysMessage(LANG_NOEVENTFOUND);
3813 return true;
3816 bool ChatHandler::HandleEventInfoCommand(const char* args)
3818 if(!*args)
3819 return false;
3821 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3822 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3823 if(!cId)
3824 return false;
3826 uint32 event_id = atoi(cId);
3828 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3830 if(event_id >=events.size())
3832 SendSysMessage(LANG_EVENT_NOT_EXIST);
3833 SetSentErrorMessage(true);
3834 return false;
3837 GameEventData const& eventData = events[event_id];
3838 if(!eventData.isValid())
3840 SendSysMessage(LANG_EVENT_NOT_EXIST);
3841 SetSentErrorMessage(true);
3842 return false;
3845 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3846 bool active = activeEvents.find(event_id) != activeEvents.end();
3847 char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : "";
3849 std::string startTimeStr = TimeToTimestampStr(eventData.start);
3850 std::string endTimeStr = TimeToTimestampStr(eventData.end);
3852 uint32 delay = sGameEventMgr.NextCheck(event_id);
3853 time_t nextTime = time(NULL)+delay;
3854 std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3856 std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3857 std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3859 PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3860 startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3861 nextStr.c_str());
3862 return true;
3865 bool ChatHandler::HandleEventStartCommand(const char* args)
3867 if(!*args)
3868 return false;
3870 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3871 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3872 if(!cId)
3873 return false;
3875 int32 event_id = atoi(cId);
3877 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3879 if(event_id < 1 || event_id >=(int32)events.size())
3881 SendSysMessage(LANG_EVENT_NOT_EXIST);
3882 SetSentErrorMessage(true);
3883 return false;
3886 GameEventData const& eventData = events[event_id];
3887 if(!eventData.isValid())
3889 SendSysMessage(LANG_EVENT_NOT_EXIST);
3890 SetSentErrorMessage(true);
3891 return false;
3894 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3895 if(activeEvents.find(event_id) != activeEvents.end())
3897 PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3898 SetSentErrorMessage(true);
3899 return false;
3902 PSendSysMessage(LANG_EVENT_STARTED, event_id, eventData.description.c_str());
3903 sGameEventMgr.StartEvent(event_id,true);
3904 return true;
3907 bool ChatHandler::HandleEventStopCommand(const char* args)
3909 if(!*args)
3910 return false;
3912 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3913 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3914 if(!cId)
3915 return false;
3917 int32 event_id = atoi(cId);
3919 GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
3921 if(event_id < 1 || event_id >=(int32)events.size())
3923 SendSysMessage(LANG_EVENT_NOT_EXIST);
3924 SetSentErrorMessage(true);
3925 return false;
3928 GameEventData const& eventData = events[event_id];
3929 if(!eventData.isValid())
3931 SendSysMessage(LANG_EVENT_NOT_EXIST);
3932 SetSentErrorMessage(true);
3933 return false;
3936 GameEventMgr::ActiveEvents const& activeEvents = sGameEventMgr.GetActiveEventList();
3938 if(activeEvents.find(event_id) == activeEvents.end())
3940 PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3941 SetSentErrorMessage(true);
3942 return false;
3945 PSendSysMessage(LANG_EVENT_STOPPED, event_id, eventData.description.c_str());
3946 sGameEventMgr.StopEvent(event_id,true);
3947 return true;
3950 bool ChatHandler::HandleCombatStopCommand(const char* args)
3952 Player* target;
3953 if(!extractPlayerTarget((char*)args,&target))
3954 return false;
3956 // check online security
3957 if (HasLowerSecurity(target, 0))
3958 return false;
3960 target->CombatStop();
3961 target->getHostileRefManager().deleteReferences();
3962 return true;
3965 void ChatHandler::HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id)
3967 uint32 classmask = player->getClassMask();
3969 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3971 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3972 if (!skillLine)
3973 continue;
3975 // wrong skill
3976 if( skillLine->skillId != skill_id)
3977 continue;
3979 // not high rank
3980 if(skillLine->forward_spellid )
3981 continue;
3983 // skip racial skills
3984 if (skillLine->racemask != 0)
3985 continue;
3987 // skip wrong class skills
3988 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3989 continue;
3991 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3992 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,player,false))
3993 continue;
3995 player->learnSpell(skillLine->spellId, false);
3999 bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
4001 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
4003 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
4004 if( !skillInfo )
4005 continue;
4007 if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) &&
4008 skillInfo->canLink) // only prof. with recipes have
4010 HandleLearnSkillRecipesHelper(m_session->GetPlayer(),skillInfo->id);
4014 SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
4015 return true;
4018 bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
4020 // Learns all recipes of specified profession and sets skill to max
4021 // Example: .learn all_recipes enchanting
4023 Player* target = getSelectedPlayer();
4024 if( !target )
4026 SendSysMessage(LANG_PLAYER_NOT_FOUND);
4027 return false;
4030 if(!*args)
4031 return false;
4033 std::wstring wnamepart;
4035 if(!Utf8toWStr(args,wnamepart))
4036 return false;
4038 // converting string that we try to find to lower case
4039 wstrToLower( wnamepart );
4041 std::string name;
4043 SkillLineEntry const *targetSkillInfo = NULL;
4044 for (uint32 i = 1; i < sSkillLineStore.GetNumRows(); ++i)
4046 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
4047 if (!skillInfo)
4048 continue;
4050 if ((skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
4051 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY) ||
4052 !skillInfo->canLink) // only prof with recipes have set
4053 continue;
4055 int loc = GetSessionDbcLocale();
4056 name = skillInfo->name[loc];
4057 if(name.empty())
4058 continue;
4060 if (!Utf8FitTo(name, wnamepart))
4062 loc = 0;
4063 for(; loc < MAX_LOCALE; ++loc)
4065 if(loc==GetSessionDbcLocale())
4066 continue;
4068 name = skillInfo->name[loc];
4069 if(name.empty())
4070 continue;
4072 if (Utf8FitTo(name, wnamepart))
4073 break;
4077 if(loc < MAX_LOCALE)
4079 targetSkillInfo = skillInfo;
4080 break;
4084 if(!targetSkillInfo)
4085 return false;
4087 HandleLearnSkillRecipesHelper(target,targetSkillInfo->id);
4089 uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id);
4090 target->SetSkill(targetSkillInfo->id, maxLevel, maxLevel);
4091 PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
4092 return true;
4095 bool ChatHandler::HandleLookupAccountEmailCommand(const char* args)
4098 if (!*args)
4099 return false;
4101 std::string email = strtok ((char*)args, " ");
4102 char* limit_str = strtok (NULL, " ");
4103 uint32 limit = limit_str ? atoi (limit_str) : 100;
4105 loginDatabase.escape_string (email);
4106 // 0 1 2 3 4
4107 QueryResult *result = loginDatabase.PQuery("SELECT id, username, last_ip, gmlevel, expansion FROM account WHERE email "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"), email.c_str ());
4109 return ShowAccountListHelper(result,&limit);
4112 bool ChatHandler::HandleLookupAccountIpCommand(const char* args)
4115 if (!*args)
4116 return false;
4118 std::string ip = strtok ((char*)args, " ");
4119 char* limit_str = strtok (NULL, " ");
4120 uint32 limit = limit_str ? atoi (limit_str) : 100;
4122 loginDatabase.escape_string (ip);
4124 // 0 1 2 3 4
4125 QueryResult *result = loginDatabase.PQuery("SELECT id, username, last_ip, gmlevel, expansion FROM account WHERE last_ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"), ip.c_str ());
4127 return ShowAccountListHelper(result,&limit);
4130 bool ChatHandler::HandleLookupAccountNameCommand(const char* args)
4132 if (!*args)
4133 return false;
4135 std::string account = strtok ((char*)args, " ");
4136 char* limit_str = strtok (NULL, " ");
4137 uint32 limit = limit_str ? atoi (limit_str) : 100;
4139 if (!AccountMgr::normalizeString (account))
4140 return false;
4142 loginDatabase.escape_string (account);
4143 // 0 1 2 3 4
4144 QueryResult *result = loginDatabase.PQuery("SELECT id, username, last_ip, gmlevel, expansion FROM account WHERE username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"), account.c_str ());
4146 return ShowAccountListHelper(result,&limit);
4149 bool ChatHandler::ShowAccountListHelper(QueryResult* result, uint32* limit, bool title, bool error)
4151 if (!result)
4153 if (error)
4154 SendSysMessage(LANG_ACCOUNT_LIST_EMPTY);
4155 return true;
4158 ///- Display the list of account/characters online
4159 if (!m_session && title) // not output header for online case
4161 SendSysMessage(LANG_ACCOUNT_LIST_BAR);
4162 SendSysMessage(LANG_ACCOUNT_LIST_HEADER);
4163 SendSysMessage(LANG_ACCOUNT_LIST_BAR);
4166 ///- Circle through accounts
4169 // check limit
4170 if (limit)
4172 if(*limit == 0)
4173 break;
4174 --*limit;
4177 Field *fields = result->Fetch();
4178 uint32 account = fields[0].GetUInt32();
4180 WorldSession* session = sWorld.FindSession(account);
4181 Player* player = session ? session->GetPlayer() : NULL;
4182 char const* char_name = player ? player->GetName() : " - ";
4184 if(m_session)
4185 PSendSysMessage(LANG_ACCOUNT_LIST_LINE_CHAT,
4186 account,fields[1].GetString(),char_name,fields[2].GetString(),fields[3].GetUInt32(),fields[4].GetUInt32());
4187 else
4188 PSendSysMessage(LANG_ACCOUNT_LIST_LINE_CONSOLE,
4189 account,fields[1].GetString(),char_name,fields[2].GetString(),fields[3].GetUInt32(),fields[4].GetUInt32());
4191 }while(result->NextRow());
4193 delete result;
4195 if (!m_session) // not output header for online case
4196 SendSysMessage(LANG_ACCOUNT_LIST_BAR);
4198 return true;
4201 bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
4204 if (!*args)
4205 return false;
4207 std::string ip = strtok ((char*)args, " ");
4208 char* limit_str = strtok (NULL, " ");
4209 uint32 limit = limit_str ? atoi (limit_str) : 100;
4211 loginDatabase.escape_string (ip);
4213 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"), ip.c_str ());
4215 return LookupPlayerSearchCommand (result,&limit);
4218 bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
4220 if (!*args)
4221 return false;
4223 std::string account = strtok ((char*)args, " ");
4224 char* limit_str = strtok (NULL, " ");
4225 uint32 limit = limit_str ? atoi (limit_str) : 100;
4227 if (!AccountMgr::normalizeString (account))
4228 return false;
4230 loginDatabase.escape_string (account);
4232 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"), account.c_str ());
4234 return LookupPlayerSearchCommand (result,&limit);
4237 bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
4240 if (!*args)
4241 return false;
4243 std::string email = strtok ((char*)args, " ");
4244 char* limit_str = strtok (NULL, " ");
4245 uint32 limit = limit_str ? atoi (limit_str) : 100;
4247 loginDatabase.escape_string (email);
4249 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"), email.c_str ());
4251 return LookupPlayerSearchCommand (result,&limit);
4254 bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, uint32* limit)
4256 if (!result)
4258 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4259 SetSentErrorMessage(true);
4260 return false;
4263 uint32 limit_original = limit ? *limit : 100;
4265 uint32 limit_local = limit_original;
4267 if (!limit)
4268 limit = &limit_local;
4272 if (limit && *limit == 0)
4273 break;
4275 Field* fields = result->Fetch();
4276 uint32 acc_id = fields[0].GetUInt32();
4277 std::string acc_name = fields[1].GetCppString();
4279 ///- Get the characters for account id
4280 QueryResult *chars = CharacterDatabase.PQuery( "SELECT guid, name, race, class, level FROM characters WHERE account = %u", acc_id);
4281 if (chars)
4283 if (chars->GetRowCount())
4285 PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4286 ShowPlayerListHelper(chars,limit,true,false);
4288 else
4289 delete chars;
4291 } while(result->NextRow());
4293 delete result;
4295 if (*limit==limit_original) // empty accounts only
4297 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4298 SetSentErrorMessage(true);
4299 return false;
4302 return true;
4305 /// Triggering corpses expire check in world
4306 bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4308 sObjectAccessor.RemoveOldCorpses();
4309 return true;
4312 bool ChatHandler::HandleRepairitemsCommand(const char* args)
4314 Player* target;
4315 if(!extractPlayerTarget((char*)args,&target))
4316 return false;
4318 // check online security
4319 if (HasLowerSecurity(target, 0))
4320 return false;
4322 // Repair items
4323 target->DurabilityRepairAll(false, 0, false);
4325 PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str());
4326 if(needReportToTarget(target))
4327 ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str());
4328 return true;
4331 bool ChatHandler::HandleWaterwalkCommand(const char* args)
4333 if(!*args)
4334 return false;
4336 Player *player = getSelectedPlayer();
4338 if(!player)
4340 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4341 SetSentErrorMessage(true);
4342 return false;
4345 // check online security
4346 if (HasLowerSecurity(player, 0))
4347 return false;
4349 if (strncmp(args, "on", 3) == 0)
4350 player->SetMovement(MOVE_WATER_WALK); // ON
4351 else if (strncmp(args, "off", 4) == 0)
4352 player->SetMovement(MOVE_LAND_WALK); // OFF
4353 else
4355 SendSysMessage(LANG_USE_BOL);
4356 return false;
4359 PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str());
4360 if(needReportToTarget(player))
4361 ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str());
4362 return true;
4365 bool ChatHandler::HandleLookupTitleCommand(const char* args)
4367 if(!*args)
4368 return false;
4370 // can be NULL in console call
4371 Player* target = getSelectedPlayer();
4373 // title name have single string arg for player name
4374 char const* targetName = target ? target->GetName() : "NAME";
4376 std::string namepart = args;
4377 std::wstring wnamepart;
4379 if(!Utf8toWStr(namepart,wnamepart))
4380 return false;
4382 // converting string that we try to find to lower case
4383 wstrToLower( wnamepart );
4385 uint32 counter = 0; // Counter for figure out that we found smth.
4387 // Search in CharTitles.dbc
4388 for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
4390 CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id);
4391 if(titleInfo)
4393 int loc = GetSessionDbcLocale();
4394 std::string name = titleInfo->name[loc];
4395 if(name.empty())
4396 continue;
4398 if (!Utf8FitTo(name, wnamepart))
4400 loc = 0;
4401 for(; loc < MAX_LOCALE; ++loc)
4403 if(loc==GetSessionDbcLocale())
4404 continue;
4406 name = titleInfo->name[loc];
4407 if(name.empty())
4408 continue;
4410 if (Utf8FitTo(name, wnamepart))
4411 break;
4415 if(loc < MAX_LOCALE)
4417 char const* knownStr = target && target->HasTitle(titleInfo) ? GetMangosString(LANG_KNOWN) : "";
4419 char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE)==titleInfo->bit_index
4420 ? GetMangosString(LANG_ACTIVE)
4421 : "";
4423 char titleNameStr[80];
4424 snprintf(titleNameStr,80,name.c_str(),targetName);
4426 // send title in "id (idx:idx) - [namedlink locale]" format
4427 if (m_session)
4428 PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr);
4429 else
4430 PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,titleNameStr,localeNames[loc],knownStr,activeStr);
4432 ++counter;
4436 if (counter == 0) // if counter == 0 then we found nth
4437 SendSysMessage(LANG_COMMAND_NOTITLEFOUND);
4438 return true;
4441 bool ChatHandler::HandleTitlesAddCommand(const char* args)
4443 // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r
4444 char* id_p = extractKeyFromLink((char*)args,"Htitle");
4445 if(!id_p)
4446 return false;
4448 int32 id = atoi(id_p);
4449 if (id <= 0)
4451 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4452 SetSentErrorMessage(true);
4453 return false;
4456 Player * target = getSelectedPlayer();
4457 if(!target)
4459 SendSysMessage(LANG_NO_CHAR_SELECTED);
4460 SetSentErrorMessage(true);
4461 return false;
4464 // check online security
4465 if (HasLowerSecurity(target, 0))
4466 return false;
4468 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
4469 if(!titleInfo)
4471 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4472 SetSentErrorMessage(true);
4473 return false;
4476 std::string tNameLink = GetNameLink(target);
4478 char const* targetName = target->GetName();
4479 char titleNameStr[80];
4480 snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName);
4482 target->SetTitle(titleInfo);
4483 PSendSysMessage(LANG_TITLE_ADD_RES, id, titleNameStr, tNameLink.c_str());
4485 return true;
4488 bool ChatHandler::HandleTitlesRemoveCommand(const char* args)
4490 // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r
4491 char* id_p = extractKeyFromLink((char*)args,"Htitle");
4492 if(!id_p)
4493 return false;
4495 int32 id = atoi(id_p);
4496 if (id <= 0)
4498 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4499 SetSentErrorMessage(true);
4500 return false;
4503 Player * target = getSelectedPlayer();
4504 if(!target)
4506 SendSysMessage(LANG_NO_CHAR_SELECTED);
4507 SetSentErrorMessage(true);
4508 return false;
4511 // check online security
4512 if (HasLowerSecurity(target, 0))
4513 return false;
4515 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
4516 if(!titleInfo)
4518 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4519 SetSentErrorMessage(true);
4520 return false;
4523 target->SetTitle(titleInfo,true);
4525 std::string tNameLink = GetNameLink(target);
4527 char const* targetName = target->GetName();
4528 char titleNameStr[80];
4529 snprintf(titleNameStr,80,titleInfo->name[GetSessionDbcLocale()],targetName);
4531 PSendSysMessage(LANG_TITLE_REMOVE_RES, id, titleNameStr, tNameLink.c_str());
4533 if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE)))
4535 target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0);
4536 PSendSysMessage(LANG_CURRENT_TITLE_RESET, tNameLink.c_str());
4539 return true;
4542 //Edit Player KnownTitles
4543 bool ChatHandler::HandleTitlesSetMaskCommand(const char* args)
4545 if(!*args)
4546 return false;
4548 uint64 titles = 0;
4550 sscanf((char*)args, UI64FMTD, &titles);
4552 Player *target = getSelectedPlayer();
4553 if (!target)
4555 SendSysMessage(LANG_NO_CHAR_SELECTED);
4556 SetSentErrorMessage(true);
4557 return false;
4560 // check online security
4561 if (HasLowerSecurity(target, 0))
4562 return false;
4564 uint64 titles2 = titles;
4566 for(uint32 i = 1; i < sCharTitlesStore.GetNumRows(); ++i)
4567 if(CharTitlesEntry const* tEntry = sCharTitlesStore.LookupEntry(i))
4568 titles2 &= ~(uint64(1) << tEntry->bit_index);
4570 titles &= ~titles2; // remove not existed titles
4572 target->SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES, titles);
4573 SendSysMessage(LANG_DONE);
4575 if (!target->HasTitle(target->GetInt32Value(PLAYER_CHOSEN_TITLE)))
4577 target->SetUInt32Value(PLAYER_CHOSEN_TITLE,0);
4578 PSendSysMessage(LANG_CURRENT_TITLE_RESET,GetNameLink(target).c_str());
4581 return true;
4584 bool ChatHandler::HandleCharacterTitlesCommand(const char* args)
4586 Player* target;
4587 if(!extractPlayerTarget((char*)args,&target))
4588 return false;
4590 LocaleConstant loc = GetSessionDbcLocale();
4591 char const* targetName = target->GetName();
4592 char const* knownStr = GetMangosString(LANG_KNOWN);
4594 // Search in CharTitles.dbc
4595 for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++)
4597 CharTitlesEntry const *titleInfo = sCharTitlesStore.LookupEntry(id);
4598 if (titleInfo && target->HasTitle(titleInfo))
4600 std::string name = titleInfo->name[loc];
4601 if(name.empty())
4602 continue;
4604 char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE)==titleInfo->bit_index
4605 ? GetMangosString(LANG_ACTIVE)
4606 : "";
4608 char titleNameStr[80];
4609 snprintf(titleNameStr,80,name.c_str(),targetName);
4611 // send title in "id (idx:idx) - [namedlink locale]" format
4612 if (m_session)
4613 PSendSysMessage(LANG_TITLE_LIST_CHAT,id,titleInfo->bit_index,id,titleNameStr,localeNames[loc],knownStr,activeStr);
4614 else
4615 PSendSysMessage(LANG_TITLE_LIST_CONSOLE,id,titleInfo->bit_index,name.c_str(),localeNames[loc],knownStr,activeStr);
4618 return true;
4621 bool ChatHandler::HandleTitlesCurrentCommand(const char* args)
4623 // number or [name] Shift-click form |color|Htitle:title_id|h[name]|h|r
4624 char* id_p = extractKeyFromLink((char*)args,"Htitle");
4625 if(!id_p)
4626 return false;
4628 int32 id = atoi(id_p);
4629 if (id <= 0)
4631 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4632 SetSentErrorMessage(true);
4633 return false;
4636 Player * target = getSelectedPlayer();
4637 if(!target)
4639 SendSysMessage(LANG_NO_CHAR_SELECTED);
4640 SetSentErrorMessage(true);
4641 return false;
4644 // check online security
4645 if (HasLowerSecurity(target, 0))
4646 return false;
4648 CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
4649 if(!titleInfo)
4651 PSendSysMessage(LANG_INVALID_TITLE_ID, id);
4652 SetSentErrorMessage(true);
4653 return false;
4656 std::string tNameLink = GetNameLink(target);
4658 target->SetTitle(titleInfo); // to be sure that title now known
4659 target->SetUInt32Value(PLAYER_CHOSEN_TITLE,titleInfo->bit_index);
4661 PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name[GetSessionDbcLocale()], tNameLink.c_str());
4663 return true;