[8449] Deprecate healing/damage item mods and merge internal data in to spell power.
[getmangos.git] / src / game / Level2.cpp
bloba188f65c59025941e440e63e88c386bb379f6ae5
1 /*
2 * Copyright (C) 2005-2009 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 "ObjectMgr.h"
22 #include "Player.h"
23 #include "Item.h"
24 #include "GameObject.h"
25 #include "Opcodes.h"
26 #include "Chat.h"
27 #include "ObjectAccessor.h"
28 #include "MapManager.h"
29 #include "Language.h"
30 #include "World.h"
31 #include "GameEventMgr.h"
32 #include "SpellMgr.h"
33 #include "PoolHandler.h"
34 #include "AccountMgr.h"
35 #include "GMTicketMgr.h"
36 #include "WaypointManager.h"
37 #include "Util.h"
38 #include <cctype>
39 #include <iostream>
40 #include <fstream>
41 #include <map>
42 #include "GlobalEvents.h"
44 #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
46 static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
48 LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL,
49 LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED
52 //mute player for some times
53 bool ChatHandler::HandleMuteCommand(const char* args)
55 char* nameStr;
56 char* delayStr;
57 extractOptFirstArg((char*)args,&nameStr,&delayStr);
58 if(!delayStr)
59 return false;
61 Player* target;
62 uint64 target_guid;
63 std::string target_name;
64 if(!extractPlayerTarget(nameStr,&target,&target_guid,&target_name))
65 return false;
67 uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid);
69 // find only player from same account if any
70 if(!target)
72 if(WorldSession* session = sWorld.FindSession(account_id))
73 target = session->GetPlayer();
76 uint32 notspeaktime = (uint32) atoi(delayStr);
78 // must have strong lesser security level
79 if(HasLowerSecurity (target,target_guid,true))
80 return false;
82 time_t mutetime = time(NULL) + notspeaktime*60;
84 if (target)
85 target->GetSession()->m_muteTime = mutetime;
87 loginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
89 if(target)
90 ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
92 std::string nameLink = playerLink(target_name);
94 PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime);
95 return true;
98 //unmute player
99 bool ChatHandler::HandleUnmuteCommand(const char* args)
101 Player* target;
102 uint64 target_guid;
103 std::string target_name;
104 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
105 return false;
107 uint32 account_id = target ? target->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(target_guid);
109 // find only player from same account if any
110 if(!target)
112 if(WorldSession* session = sWorld.FindSession(account_id))
113 target = session->GetPlayer();
116 // must have strong lesser security level
117 if(HasLowerSecurity (target,target_guid,true))
118 return false;
120 if (target)
122 if(target->CanSpeak())
124 SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
125 SetSentErrorMessage(true);
126 return false;
129 target->GetSession()->m_muteTime = 0;
132 loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
134 if(target)
135 ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
137 std::string nameLink = playerLink(target_name);
139 PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str());
140 return true;
143 bool ChatHandler::HandleGoTriggerCommand(const char* args)
145 Player* _player = m_session->GetPlayer();
147 if (!*args)
148 return false;
150 char *atId = strtok((char*)args, " ");
151 if (!atId)
152 return false;
154 int32 i_atId = atoi(atId);
156 if(!i_atId)
157 return false;
159 AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
160 if (!at)
162 PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
163 SetSentErrorMessage(true);
164 return false;
167 if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
169 PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
170 SetSentErrorMessage(true);
171 return false;
174 // stop flight if need
175 if(_player->isInFlight())
177 _player->GetMotionMaster()->MovementExpired();
178 _player->m_taxi.ClearTaxiDestinations();
180 // save only in non-flight case
181 else
182 _player->SaveRecallPosition();
184 _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
185 return true;
188 bool ChatHandler::HandleGoGraveyardCommand(const char* args)
190 Player* _player = m_session->GetPlayer();
192 if (!*args)
193 return false;
195 char *gyId = strtok((char*)args, " ");
196 if (!gyId)
197 return false;
199 int32 i_gyId = atoi(gyId);
201 if(!i_gyId)
202 return false;
204 WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
205 if (!gy)
207 PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
208 SetSentErrorMessage(true);
209 return false;
212 if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
214 PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
215 SetSentErrorMessage(true);
216 return false;
219 // stop flight if need
220 if(_player->isInFlight())
222 _player->GetMotionMaster()->MovementExpired();
223 _player->m_taxi.ClearTaxiDestinations();
225 // save only in non-flight case
226 else
227 _player->SaveRecallPosition();
229 _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
230 return true;
233 /** \brief Teleport the GM to the specified creature
235 * .gocreature <GUID> --> TP using creature.guid
236 * .gocreature azuregos --> TP player to the mob with this name
237 * Warning: If there is more than one mob with this name
238 * you will be teleported to the first one that is found.
239 * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry
240 * Warning: If there is more than one mob with this "id"
241 * you will be teleported to the first one that is found.
243 //teleport to creature
244 bool ChatHandler::HandleGoCreatureCommand(const char* args)
246 if(!*args)
247 return false;
248 Player* _player = m_session->GetPlayer();
250 // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
251 char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
252 if (!pParam1)
253 return false;
255 std::ostringstream whereClause;
257 // User wants to teleport to the NPC's template entry
258 if( strcmp(pParam1, "id") == 0 )
260 //sLog.outError("DEBUG: ID found");
262 // Get the "creature_template.entry"
263 // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
264 char* tail = strtok(NULL,"");
265 if(!tail)
266 return false;
267 char* cId = extractKeyFromLink(tail,"Hcreature_entry");
268 if(!cId)
269 return false;
271 int32 tEntry = atoi(cId);
272 //sLog.outError("DEBUG: ID value: %d", tEntry);
273 if(!tEntry)
274 return false;
276 whereClause << "WHERE id = '" << tEntry << "'";
278 else
280 //sLog.outError("DEBUG: ID *not found*");
282 int32 guid = atoi(pParam1);
284 // Number is invalid - maybe the user specified the mob's name
285 if(!guid)
287 std::string name = pParam1;
288 WorldDatabase.escape_string(name);
289 whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
291 else
293 whereClause << "WHERE guid = '" << guid << "'";
296 //sLog.outError("DEBUG: %s", whereClause.c_str());
298 QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
299 if (!result)
301 SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
302 SetSentErrorMessage(true);
303 return false;
305 if( result->GetRowCount() > 1 )
307 SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
310 Field *fields = result->Fetch();
311 float x = fields[0].GetFloat();
312 float y = fields[1].GetFloat();
313 float z = fields[2].GetFloat();
314 float ort = fields[3].GetFloat();
315 int mapid = fields[4].GetUInt16();
317 delete result;
319 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
321 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
322 SetSentErrorMessage(true);
323 return false;
326 // stop flight if need
327 if(_player->isInFlight())
329 _player->GetMotionMaster()->MovementExpired();
330 _player->m_taxi.ClearTaxiDestinations();
332 // save only in non-flight case
333 else
334 _player->SaveRecallPosition();
336 _player->TeleportTo(mapid, x, y, z, ort);
337 return true;
340 //teleport to gameobject
341 bool ChatHandler::HandleGoObjectCommand(const char* args)
343 if(!*args)
344 return false;
346 Player* _player = m_session->GetPlayer();
348 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
349 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
350 if(!cId)
351 return false;
353 int32 guid = atoi(cId);
354 if(!guid)
355 return false;
357 float x, y, z, ort;
358 int mapid;
360 // by DB guid
361 if (GameObjectData const* go_data = objmgr.GetGOData(guid))
363 x = go_data->posX;
364 y = go_data->posY;
365 z = go_data->posZ;
366 ort = go_data->orientation;
367 mapid = go_data->mapid;
369 else
371 SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
372 SetSentErrorMessage(true);
373 return false;
376 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
378 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
379 SetSentErrorMessage(true);
380 return false;
383 // stop flight if need
384 if(_player->isInFlight())
386 _player->GetMotionMaster()->MovementExpired();
387 _player->m_taxi.ClearTaxiDestinations();
389 // save only in non-flight case
390 else
391 _player->SaveRecallPosition();
393 _player->TeleportTo(mapid, x, y, z, ort);
394 return true;
397 bool ChatHandler::HandleGameObjectTargetCommand(const char* args)
399 Player* pl = m_session->GetPlayer();
400 QueryResult *result;
401 GameEventMgr::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
402 if(*args)
404 // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r
405 char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry");
406 if(!cId)
407 return false;
409 uint32 id = atol(cId);
411 if(id)
412 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",
413 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
414 else
416 std::string name = cId;
417 WorldDatabase.escape_string(name);
418 result = WorldDatabase.PQuery(
419 "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_ "
420 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
421 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
424 else
426 std::ostringstream eventFilter;
427 eventFilter << " AND (event IS NULL ";
428 bool initString = true;
430 for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
432 if (initString)
434 eventFilter << "OR event IN (" <<*itr;
435 initString =false;
437 else
438 eventFilter << "," << *itr;
441 if (!initString)
442 eventFilter << "))";
443 else
444 eventFilter << ")";
446 result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
447 "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
448 "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10",
449 m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
452 if (!result)
454 SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
455 return true;
458 bool found = false;
459 float x, y, z, o;
460 uint32 lowguid, id;
461 uint16 mapid, pool_id;
465 Field *fields = result->Fetch();
466 lowguid = fields[0].GetUInt32();
467 id = fields[1].GetUInt32();
468 x = fields[2].GetFloat();
469 y = fields[3].GetFloat();
470 z = fields[4].GetFloat();
471 o = fields[5].GetFloat();
472 mapid = fields[6].GetUInt16();
473 pool_id = poolhandler.IsPartOfAPool(lowguid, TYPEID_GAMEOBJECT);
474 if (!pool_id || (pool_id && poolhandler.IsSpawnedObject(pool_id, lowguid, TYPEID_GAMEOBJECT)))
475 found = true;
476 } while( result->NextRow() && (!found) );
478 delete result;
480 if (!found)
482 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
483 return false;
486 GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id);
488 if (!goI)
490 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
491 return false;
494 GameObject* target = m_session->GetPlayer()->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
496 PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
498 if(target)
500 int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
501 if(curRespawnDelay < 0)
502 curRespawnDelay = 0;
504 std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
505 std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
507 PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
509 return true;
512 //delete object by selection or guid
513 bool ChatHandler::HandleGameObjectDeleteCommand(const char* args)
515 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
516 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
517 if(!cId)
518 return false;
520 uint32 lowguid = atoi(cId);
521 if(!lowguid)
522 return false;
524 GameObject* obj = NULL;
526 // by DB guid
527 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
528 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
530 if(!obj)
532 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
533 SetSentErrorMessage(true);
534 return false;
537 uint64 owner_guid = obj->GetOwnerGUID();
538 if(owner_guid)
540 Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
541 if(!owner || !IS_PLAYER_GUID(owner_guid))
543 PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
544 SetSentErrorMessage(true);
545 return false;
548 owner->RemoveGameObject(obj,false);
551 obj->SetRespawnTime(0); // not save respawn time
552 obj->Delete();
553 obj->DeleteFromDB();
555 PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
557 return true;
560 //turn selected object
561 bool ChatHandler::HandleGameObjectTurnCommand(const char* args)
563 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
564 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
565 if(!cId)
566 return false;
568 uint32 lowguid = atoi(cId);
569 if(!lowguid)
570 return false;
572 GameObject* obj = NULL;
574 // by DB guid
575 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
576 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
578 if(!obj)
580 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
581 SetSentErrorMessage(true);
582 return false;
585 char* po = strtok(NULL, " ");
586 float o;
588 if (po)
590 o = (float)atof(po);
592 else
594 Player *chr = m_session->GetPlayer();
595 o = chr->GetOrientation();
598 Map* map = obj->GetMap();
599 map->Remove(obj,false);
601 obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
602 obj->UpdateRotationFields();
604 map->Add(obj);
606 obj->SaveToDB();
607 obj->Refresh();
609 PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow(), o);
611 return true;
614 //move selected object
615 bool ChatHandler::HandleGameObjectMoveCommand(const char* args)
617 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
618 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
619 if(!cId)
620 return false;
622 uint32 lowguid = atoi(cId);
623 if(!lowguid)
624 return false;
626 GameObject* obj = NULL;
628 // by DB guid
629 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
630 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
632 if(!obj)
634 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
635 SetSentErrorMessage(true);
636 return false;
639 char* px = strtok(NULL, " ");
640 char* py = strtok(NULL, " ");
641 char* pz = strtok(NULL, " ");
643 if (!px)
645 Player *chr = m_session->GetPlayer();
647 Map* map = obj->GetMap();
648 map->Remove(obj,false);
650 obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
652 map->Add(obj);
654 else
656 if(!py || !pz)
657 return false;
659 float x = (float)atof(px);
660 float y = (float)atof(py);
661 float z = (float)atof(pz);
663 if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
665 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
666 SetSentErrorMessage(true);
667 return false;
670 Map* map = obj->GetMap();
671 map->Remove(obj,false);
673 obj->Relocate(x, y, z, obj->GetOrientation());
675 map->Add(obj);
678 obj->SaveToDB();
679 obj->Refresh();
681 PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow());
683 return true;
686 //spawn go
687 bool ChatHandler::HandleGameObjectAddCommand(const char* args)
689 if (!*args)
690 return false;
692 // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r
693 char* cId = extractKeyFromLink((char*)args,"Hgameobject_entry");
694 if(!cId)
695 return false;
697 uint32 id = atol(cId);
698 if(!id)
699 return false;
701 char* spawntimeSecs = strtok(NULL, " ");
703 const GameObjectInfo *gInfo = objmgr.GetGameObjectInfo(id);
705 if (!gInfo)
707 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
708 SetSentErrorMessage(true);
709 return false;
712 if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId))
714 // report to DB errors log as in loading case
715 sLog.outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.",id, gInfo->type, gInfo->displayId);
716 PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA,id);
717 SetSentErrorMessage(true);
718 return false;
721 Player *chr = m_session->GetPlayer();
722 float x = float(chr->GetPositionX());
723 float y = float(chr->GetPositionY());
724 float z = float(chr->GetPositionZ());
725 float o = float(chr->GetOrientation());
726 Map *map = chr->GetMap();
728 GameObject* pGameObj = new GameObject;
729 uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
731 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))
733 delete pGameObj;
734 return false;
737 if( spawntimeSecs )
739 uint32 value = atoi((char*)spawntimeSecs);
740 pGameObj->SetRespawnTime(value);
741 //sLog.outDebug("*** spawntimeSecs: %d", value);
744 // fill the gameobject data and save to the db
745 pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn());
747 // this will generate a new guid if the object is in an instance
748 if(!pGameObj->LoadFromDB(db_lowGUID, map))
750 delete pGameObj;
751 return false;
754 sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o);
756 map->Add(pGameObj);
758 // TODO: is it really necessary to add both the real and DB table guid here ?
759 objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
761 PSendSysMessage(LANG_GAMEOBJECT_ADD,id,gInfo->name,db_lowGUID,x,y,z);
762 return true;
765 //set pahsemask for selected object
766 bool ChatHandler::HandleGameObjectPhaseCommand(const char* args)
768 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
769 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
770 if(!cId)
771 return false;
773 uint32 lowguid = atoi(cId);
774 if(!lowguid)
775 return false;
777 GameObject* obj = NULL;
779 // by DB guid
780 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
781 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
783 if(!obj)
785 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
786 SetSentErrorMessage(true);
787 return false;
790 char* phaseStr = strtok (NULL, " ");
791 uint32 phasemask = phaseStr? atoi(phaseStr) : 0;
792 if ( phasemask == 0 )
794 SendSysMessage(LANG_BAD_VALUE);
795 SetSentErrorMessage(true);
796 return false;
799 obj->SetPhaseMask(phasemask,true);
800 obj->SaveToDB();
801 return true;
804 bool ChatHandler::HandleGameObjectNearCommand(const char* args)
806 float distance = (!*args) ? 10 : atol(args);
807 uint32 count = 0;
809 Player* pl = m_session->GetPlayer();
810 QueryResult *result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, map, "
811 "(POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ "
812 "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_",
813 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),
814 pl->GetMapId(),pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(),distance*distance);
816 if (result)
820 Field *fields = result->Fetch();
821 uint32 guid = fields[0].GetUInt32();
822 uint32 entry = fields[1].GetUInt32();
823 float x = fields[2].GetFloat();
824 float y = fields[3].GetFloat();
825 float z = fields[4].GetFloat();
826 int mapid = fields[5].GetUInt16();
828 GameObjectInfo const * gInfo = objmgr.GetGameObjectInfo(entry);
830 if(!gInfo)
831 continue;
833 PSendSysMessage(LANG_GO_LIST_CHAT, guid, guid, gInfo->name, x, y, z, mapid);
835 ++count;
836 } while (result->NextRow());
838 delete result;
841 PSendSysMessage(LANG_COMMAND_NEAROBJMESSAGE,distance,count);
842 return true;
845 bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
847 uint64 guid = m_session->GetPlayer()->GetSelection();
849 if (guid == 0)
851 SendSysMessage(LANG_NO_SELECTION);
852 SetSentErrorMessage(true);
853 return false;
856 PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
857 return true;
860 bool ChatHandler::HandleLookupFactionCommand(const char* args)
862 if (!*args)
863 return false;
865 // Can be NULL at console call
866 Player *target = getSelectedPlayer ();
868 std::string namepart = args;
869 std::wstring wnamepart;
871 if (!Utf8toWStr (namepart,wnamepart))
872 return false;
874 // converting string that we try to find to lower case
875 wstrToLower (wnamepart);
877 uint32 counter = 0; // Counter for figure out that we found smth.
879 for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
881 FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
882 if (factionEntry)
884 FactionState const* repState = target ? target->GetReputationMgr().GetState(factionEntry) : NULL;
886 int loc = GetSessionDbcLocale();
887 std::string name = factionEntry->name[loc];
888 if(name.empty())
889 continue;
891 if (!Utf8FitTo(name, wnamepart))
893 loc = 0;
894 for(; loc < MAX_LOCALE; ++loc)
896 if(loc==GetSessionDbcLocale())
897 continue;
899 name = factionEntry->name[loc];
900 if(name.empty())
901 continue;
903 if (Utf8FitTo(name, wnamepart))
904 break;
908 if(loc < MAX_LOCALE)
910 // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
911 // or "id - [faction] [no reputation]" format
912 std::ostringstream ss;
913 if (m_session)
914 ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
915 else
916 ss << id << " - " << name << " " << localeNames[loc];
918 if (repState) // and then target!=NULL also
920 ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
921 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
923 ss << " " << rankName << "|h|r (" << target->GetReputationMgr().GetReputation(factionEntry) << ")";
925 if(repState->Flags & FACTION_FLAG_VISIBLE)
926 ss << GetMangosString(LANG_FACTION_VISIBLE);
927 if(repState->Flags & FACTION_FLAG_AT_WAR)
928 ss << GetMangosString(LANG_FACTION_ATWAR);
929 if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
930 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
931 if(repState->Flags & FACTION_FLAG_HIDDEN)
932 ss << GetMangosString(LANG_FACTION_HIDDEN);
933 if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
934 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
935 if(repState->Flags & FACTION_FLAG_INACTIVE)
936 ss << GetMangosString(LANG_FACTION_INACTIVE);
938 else
939 ss << GetMangosString(LANG_FACTION_NOREPUTATION);
941 SendSysMessage(ss.str().c_str());
942 counter++;
947 if (counter == 0) // if counter == 0 then we found nth
948 SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
949 return true;
952 bool ChatHandler::HandleModifyRepCommand(const char * args)
954 if (!*args) return false;
956 Player* target = NULL;
957 target = getSelectedPlayer();
959 if(!target)
961 SendSysMessage(LANG_PLAYER_NOT_FOUND);
962 SetSentErrorMessage(true);
963 return false;
966 // check online security
967 if (HasLowerSecurity(target, 0))
968 return false;
970 char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
971 if(!factionTxt)
972 return false;
974 uint32 factionId = atoi(factionTxt);
976 int32 amount = 0;
977 char *rankTxt = strtok(NULL, " ");
978 if (!factionTxt || !rankTxt)
979 return false;
981 amount = atoi(rankTxt);
982 if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
984 std::string rankStr = rankTxt;
985 std::wstring wrankStr;
986 if(!Utf8toWStr(rankStr,wrankStr))
987 return false;
988 wstrToLower( wrankStr );
990 int r = 0;
991 amount = -42000;
992 for (; r < MAX_REPUTATION_RANK; ++r)
994 std::string rank = GetMangosString(ReputationRankStrIndex[r]);
995 if(rank.empty())
996 continue;
998 std::wstring wrank;
999 if(!Utf8toWStr(rank,wrank))
1000 continue;
1002 wstrToLower(wrank);
1004 if(wrank.substr(0,wrankStr.size())==wrankStr)
1006 char *deltaTxt = strtok(NULL, " ");
1007 if (deltaTxt)
1009 int32 delta = atoi(deltaTxt);
1010 if ((delta < 0) || (delta > ReputationMgr::PointsInRank[r] -1))
1012 PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (ReputationMgr::PointsInRank[r]-1));
1013 SetSentErrorMessage(true);
1014 return false;
1016 amount += delta;
1018 break;
1020 amount += ReputationMgr::PointsInRank[r];
1022 if (r >= MAX_REPUTATION_RANK)
1024 PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
1025 SetSentErrorMessage(true);
1026 return false;
1030 FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
1032 if (!factionEntry)
1034 PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
1035 SetSentErrorMessage(true);
1036 return false;
1039 if (factionEntry->reputationListID < 0)
1041 PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[GetSessionDbcLocale()], factionId);
1042 SetSentErrorMessage(true);
1043 return false;
1046 target->GetReputationMgr().SetReputation(factionEntry,amount);
1047 PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[GetSessionDbcLocale()], factionId,
1048 GetNameLink(target).c_str(), target->GetReputationMgr().GetReputation(factionEntry));
1049 return true;
1052 //-----------------------Npc Commands-----------------------
1053 //add spawn of creature
1054 bool ChatHandler::HandleNpcAddCommand(const char* args)
1056 if(!*args)
1057 return false;
1058 char* charID = extractKeyFromLink((char*)args,"Hcreature_entry");
1059 if(!charID)
1060 return false;
1062 char* team = strtok(NULL, " ");
1063 int32 teamval = 0;
1064 if (team) { teamval = atoi(team); }
1065 if (teamval < 0) { teamval = 0; }
1067 uint32 id = atoi(charID);
1069 Player *chr = m_session->GetPlayer();
1070 float x = chr->GetPositionX();
1071 float y = chr->GetPositionY();
1072 float z = chr->GetPositionZ();
1073 float o = chr->GetOrientation();
1074 Map *map = chr->GetMap();
1076 Creature* pCreature = new Creature;
1077 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, (uint32)teamval))
1079 delete pCreature;
1080 return false;
1083 pCreature->Relocate(x,y,z,o);
1085 if(!pCreature->IsPositionValid())
1087 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());
1088 delete pCreature;
1089 return false;
1092 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
1094 uint32 db_guid = pCreature->GetDBTableGUIDLow();
1096 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
1097 pCreature->LoadFromDB(db_guid, map);
1099 map->Add(pCreature);
1100 objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid));
1101 return true;
1104 //add item in vendorlist
1105 bool ChatHandler::HandleNpcAddVendorItemCommand(const char* args)
1107 if (!*args)
1108 return false;
1110 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1111 if (!pitem)
1113 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1114 SetSentErrorMessage(true);
1115 return false;
1118 uint32 itemId = atol(pitem);
1120 char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
1121 uint32 maxcount = 0;
1122 if (fmaxcount)
1123 maxcount = atol(fmaxcount);
1125 char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
1126 uint32 incrtime = 0;
1127 if (fincrtime)
1128 incrtime = atol(fincrtime);
1130 char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
1131 uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1133 Creature* vendor = getSelectedCreature();
1135 uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1137 if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1139 SetSentErrorMessage(true);
1140 return false;
1143 objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1145 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1147 PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1148 return true;
1151 //del item from vendor list
1152 bool ChatHandler::HandleNpcDelVendorItemCommand(const char* args)
1154 if (!*args)
1155 return false;
1157 Creature* vendor = getSelectedCreature();
1158 if (!vendor || !vendor->isVendor())
1160 SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1161 SetSentErrorMessage(true);
1162 return false;
1165 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1166 if (!pitem)
1168 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1169 SetSentErrorMessage(true);
1170 return false;
1172 uint32 itemId = atol(pitem);
1174 if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1176 PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1177 SetSentErrorMessage(true);
1178 return false;
1181 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1183 PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1184 return true;
1187 //add move for creature
1188 bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
1190 if(!*args)
1191 return false;
1193 char* guid_str = strtok((char*)args, " ");
1194 char* wait_str = strtok((char*)NULL, " ");
1196 uint32 lowguid = atoi((char*)guid_str);
1198 Creature* pCreature = NULL;
1200 /* FIXME: impossible without entry
1201 if(lowguid)
1202 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1205 // attempt check creature existence by DB data
1206 if(!pCreature)
1208 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1209 if(!data)
1211 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1212 SetSentErrorMessage(true);
1213 return false;
1216 else
1218 // obtain real GUID for DB operations
1219 lowguid = pCreature->GetDBTableGUIDLow();
1222 int wait = wait_str ? atoi(wait_str) : 0;
1224 if(wait < 0)
1225 wait = 0;
1227 Player* player = m_session->GetPlayer();
1229 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1231 // update movement type
1232 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1233 if(pCreature)
1235 pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1236 pCreature->GetMotionMaster()->Initialize();
1237 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1239 pCreature->setDeathState(JUST_DIED);
1240 pCreature->Respawn();
1242 pCreature->SaveToDB();
1245 SendSysMessage(LANG_WAYPOINT_ADDED);
1247 return true;
1250 //change level of creature or pet
1251 bool ChatHandler::HandleNpcChangeLevelCommand(const char* args)
1253 if (!*args)
1254 return false;
1256 uint8 lvl = (uint8) atoi((char*)args);
1257 if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3)
1259 SendSysMessage(LANG_BAD_VALUE);
1260 SetSentErrorMessage(true);
1261 return false;
1264 Creature* pCreature = getSelectedCreature();
1265 if(!pCreature)
1267 SendSysMessage(LANG_SELECT_CREATURE);
1268 SetSentErrorMessage(true);
1269 return false;
1272 if(pCreature->isPet())
1274 if(((Pet*)pCreature)->getPetType()==HUNTER_PET)
1276 pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(lvl)/4);
1277 pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
1279 ((Pet*)pCreature)->GivePetLevel(lvl);
1281 else
1283 pCreature->SetMaxHealth( 100 + 30*lvl);
1284 pCreature->SetHealth( 100 + 30*lvl);
1285 pCreature->SetLevel( lvl);
1286 pCreature->SaveToDB();
1289 return true;
1292 //set npcflag of creature
1293 bool ChatHandler::HandleNpcFlagCommand(const char* args)
1295 if (!*args)
1296 return false;
1298 uint32 npcFlags = (uint32) atoi((char*)args);
1300 Creature* pCreature = getSelectedCreature();
1302 if(!pCreature)
1304 SendSysMessage(LANG_SELECT_CREATURE);
1305 SetSentErrorMessage(true);
1306 return false;
1309 pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1311 WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1313 SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1315 return true;
1318 bool ChatHandler::HandleNpcDeleteCommand(const char* args)
1320 Creature* unit = NULL;
1322 if(*args)
1324 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1325 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1326 if(!cId)
1327 return false;
1329 uint32 lowguid = atoi(cId);
1330 if(!lowguid)
1331 return false;
1333 if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid))
1334 unit = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
1336 else
1337 unit = getSelectedCreature();
1339 if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle())
1341 SendSysMessage(LANG_SELECT_CREATURE);
1342 SetSentErrorMessage(true);
1343 return false;
1346 // Delete the creature
1347 unit->CombatStop();
1348 unit->DeleteFromDB();
1349 unit->AddObjectToRemoveList();
1351 SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
1353 return true;
1356 //move selected creature
1357 bool ChatHandler::HandleNpcMoveCommand(const char* args)
1359 uint32 lowguid = 0;
1361 Creature* pCreature = getSelectedCreature();
1363 if(!pCreature)
1365 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1366 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1367 if(!cId)
1368 return false;
1370 lowguid = atoi(cId);
1372 /* FIXME: impossibel without entry
1373 if(lowguid)
1374 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1377 // Attempting creature load from DB data
1378 if(!pCreature)
1380 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1381 if(!data)
1383 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1384 SetSentErrorMessage(true);
1385 return false;
1388 uint32 map_id = data->mapid;
1390 if(m_session->GetPlayer()->GetMapId()!=map_id)
1392 PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1393 SetSentErrorMessage(true);
1394 return false;
1397 else
1399 lowguid = pCreature->GetDBTableGUIDLow();
1402 else
1404 lowguid = pCreature->GetDBTableGUIDLow();
1407 float x = m_session->GetPlayer()->GetPositionX();
1408 float y = m_session->GetPlayer()->GetPositionY();
1409 float z = m_session->GetPlayer()->GetPositionZ();
1410 float o = m_session->GetPlayer()->GetOrientation();
1412 if (pCreature)
1414 if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1416 const_cast<CreatureData*>(data)->posX = x;
1417 const_cast<CreatureData*>(data)->posY = y;
1418 const_cast<CreatureData*>(data)->posZ = z;
1419 const_cast<CreatureData*>(data)->orientation = o;
1421 pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
1422 pCreature->GetMotionMaster()->Initialize();
1423 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1425 pCreature->setDeathState(JUST_DIED);
1426 pCreature->Respawn();
1430 WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1431 PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1432 return true;
1435 /**HandleNpcSetMoveTypeCommand
1436 * Set the movement type for an NPC.<br/>
1437 * <br/>
1438 * Valid movement types are:
1439 * <ul>
1440 * <li> stay - NPC wont move </li>
1441 * <li> random - NPC will move randomly according to the spawndist </li>
1442 * <li> way - NPC will move with given waypoints set </li>
1443 * </ul>
1444 * additional parameter: NODEL - so no waypoints are deleted, if you
1445 * change the movement type
1447 bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
1449 if(!*args)
1450 return false;
1452 // 3 arguments:
1453 // GUID (optional - you can also select the creature)
1454 // stay|random|way (determines the kind of movement)
1455 // NODEL (optional - tells the system NOT to delete any waypoints)
1456 // this is very handy if you want to do waypoints, that are
1457 // later switched on/off according to special events (like escort
1458 // quests, etc)
1459 char* guid_str = strtok((char*)args, " ");
1460 char* type_str = strtok((char*)NULL, " ");
1461 char* dontdel_str = strtok((char*)NULL, " ");
1463 bool doNotDelete = false;
1465 if(!guid_str)
1466 return false;
1468 uint32 lowguid = 0;
1469 Creature* pCreature = NULL;
1471 if( dontdel_str )
1473 //sLog.outError("DEBUG: All 3 params are set");
1475 // All 3 params are set
1476 // GUID
1477 // type
1478 // doNotDEL
1479 if( stricmp( dontdel_str, "NODEL" ) == 0 )
1481 //sLog.outError("DEBUG: doNotDelete = true;");
1482 doNotDelete = true;
1485 else
1487 // Only 2 params - but maybe NODEL is set
1488 if( type_str )
1490 sLog.outError("DEBUG: Only 2 params ");
1491 if( stricmp( type_str, "NODEL" ) == 0 )
1493 //sLog.outError("DEBUG: type_str, NODEL ");
1494 doNotDelete = true;
1495 type_str = NULL;
1500 if(!type_str) // case .setmovetype $move_type (with selected creature)
1502 type_str = guid_str;
1503 pCreature = getSelectedCreature();
1504 if(!pCreature || pCreature->isPet())
1505 return false;
1506 lowguid = pCreature->GetDBTableGUIDLow();
1508 else // case .setmovetype #creature_guid $move_type (with selected creature)
1510 lowguid = atoi((char*)guid_str);
1512 /* impossible without entry
1513 if(lowguid)
1514 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1517 // attempt check creature existence by DB data
1518 if(!pCreature)
1520 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1521 if(!data)
1523 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1524 SetSentErrorMessage(true);
1525 return false;
1528 else
1530 lowguid = pCreature->GetDBTableGUIDLow();
1534 // now lowguid is low guid really existed creature
1535 // and pCreature point (maybe) to this creature or NULL
1537 MovementGeneratorType move_type;
1539 std::string type = type_str;
1541 if(type == "stay")
1542 move_type = IDLE_MOTION_TYPE;
1543 else if(type == "random")
1544 move_type = RANDOM_MOTION_TYPE;
1545 else if(type == "way")
1546 move_type = WAYPOINT_MOTION_TYPE;
1547 else
1548 return false;
1550 // update movement type
1551 if(doNotDelete == false)
1552 WaypointMgr.DeletePath(lowguid);
1554 if(pCreature)
1556 pCreature->SetDefaultMovementType(move_type);
1557 pCreature->GetMotionMaster()->Initialize();
1558 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1560 pCreature->setDeathState(JUST_DIED);
1561 pCreature->Respawn();
1563 pCreature->SaveToDB();
1565 if( doNotDelete == false )
1567 PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1569 else
1571 PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1574 return true;
1577 //set model of creature
1578 bool ChatHandler::HandleNpcSetModelCommand(const char* args)
1580 if (!*args)
1581 return false;
1583 uint32 displayId = (uint32) atoi((char*)args);
1585 Creature *pCreature = getSelectedCreature();
1587 if(!pCreature || pCreature->isPet())
1589 SendSysMessage(LANG_SELECT_CREATURE);
1590 SetSentErrorMessage(true);
1591 return false;
1594 pCreature->SetDisplayId(displayId);
1595 pCreature->SetNativeDisplayId(displayId);
1597 pCreature->SaveToDB();
1599 return true;
1601 //set faction of creature
1602 bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
1604 if (!*args)
1605 return false;
1607 uint32 factionId = (uint32) atoi((char*)args);
1609 if (!sFactionTemplateStore.LookupEntry(factionId))
1611 PSendSysMessage(LANG_WRONG_FACTION, factionId);
1612 SetSentErrorMessage(true);
1613 return false;
1616 Creature* pCreature = getSelectedCreature();
1618 if(!pCreature)
1620 SendSysMessage(LANG_SELECT_CREATURE);
1621 SetSentErrorMessage(true);
1622 return false;
1625 pCreature->setFaction(factionId);
1627 // faction is set in creature_template - not inside creature
1629 // update in memory
1630 if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1632 const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1633 const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1636 // and DB
1637 WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1639 return true;
1641 //set spawn dist of creature
1642 bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
1644 if(!*args)
1645 return false;
1647 float option = atof((char*)args);
1648 if (option < 0.0f)
1650 SendSysMessage(LANG_BAD_VALUE);
1651 return false;
1654 MovementGeneratorType mtype = IDLE_MOTION_TYPE;
1655 if (option >0.0f)
1656 mtype = RANDOM_MOTION_TYPE;
1658 Creature *pCreature = getSelectedCreature();
1659 uint32 u_guidlow = 0;
1661 if (pCreature)
1662 u_guidlow = pCreature->GetDBTableGUIDLow();
1663 else
1664 return false;
1666 pCreature->SetRespawnRadius((float)option);
1667 pCreature->SetDefaultMovementType(mtype);
1668 pCreature->GetMotionMaster()->Initialize();
1669 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1671 pCreature->setDeathState(JUST_DIED);
1672 pCreature->Respawn();
1675 WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
1676 PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
1677 return true;
1679 //spawn time handling
1680 bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
1682 if(!*args)
1683 return false;
1685 char* stime = strtok((char*)args, " ");
1687 if (!stime)
1688 return false;
1690 int i_stime = atoi((char*)stime);
1692 if (i_stime < 0)
1694 SendSysMessage(LANG_BAD_VALUE);
1695 SetSentErrorMessage(true);
1696 return false;
1699 Creature *pCreature = getSelectedCreature();
1700 uint32 u_guidlow = 0;
1702 if (pCreature)
1703 u_guidlow = pCreature->GetDBTableGUIDLow();
1704 else
1705 return false;
1707 WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
1708 pCreature->SetRespawnDelay((uint32)i_stime);
1709 PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
1711 return true;
1713 //npc follow handling
1714 bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
1716 Player *player = m_session->GetPlayer();
1717 Creature *creature = getSelectedCreature();
1719 if(!creature)
1721 PSendSysMessage(LANG_SELECT_CREATURE);
1722 SetSentErrorMessage(true);
1723 return false;
1726 // Follow player - Using pet's default dist and angle
1727 creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
1729 PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
1730 return true;
1732 //npc unfollow handling
1733 bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
1735 Player *player = m_session->GetPlayer();
1736 Creature *creature = getSelectedCreature();
1738 if(!creature)
1740 PSendSysMessage(LANG_SELECT_CREATURE);
1741 SetSentErrorMessage(true);
1742 return false;
1745 if (creature->GetMotionMaster()->empty() ||
1746 creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
1748 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
1749 SetSentErrorMessage(true);
1750 return false;
1753 TargetedMovementGenerator<Creature> const* mgen
1754 = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
1756 if(mgen->GetTarget()!=player)
1758 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
1759 SetSentErrorMessage(true);
1760 return false;
1763 // reset movement
1764 creature->GetMotionMaster()->MovementExpired(true);
1766 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
1767 return true;
1769 //npc tame handling
1770 bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
1772 Creature *creatureTarget = getSelectedCreature ();
1773 if (!creatureTarget || creatureTarget->isPet ())
1775 PSendSysMessage (LANG_SELECT_CREATURE);
1776 SetSentErrorMessage (true);
1777 return false;
1780 Player *player = m_session->GetPlayer ();
1782 if(player->GetPetGUID ())
1784 SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
1785 SetSentErrorMessage (true);
1786 return false;
1789 CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
1791 if (!cInfo->isTameable (player->CanTameExoticPets()))
1793 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
1794 SetSentErrorMessage (true);
1795 return false;
1798 // Everything looks OK, create new pet
1799 Pet* pet = player->CreateTamedPetFrom (creatureTarget);
1800 if (!pet)
1802 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
1803 SetSentErrorMessage (true);
1804 return false;
1807 // place pet before player
1808 float x,y,z;
1809 player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
1810 pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
1812 // set pet to defensive mode by default (some classes can't control controlled pets in fact).
1813 pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
1815 // calculate proper level
1816 uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
1818 // prepare visual effect for levelup
1819 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
1821 // add to world
1822 pet->GetMap()->Add((Creature*)pet);
1824 // visual effect for levelup
1825 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
1827 // caster have pet now
1828 player->SetPet(pet);
1830 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
1831 player->PetSpellInitialize();
1833 return true;
1835 //npc phasemask handling
1836 //change phasemask of creature or pet
1837 bool ChatHandler::HandleNpcSetPhaseCommand(const char* args)
1839 if (!*args)
1840 return false;
1842 uint32 phasemask = (uint32) atoi((char*)args);
1843 if ( phasemask == 0 )
1845 SendSysMessage(LANG_BAD_VALUE);
1846 SetSentErrorMessage(true);
1847 return false;
1850 Creature* pCreature = getSelectedCreature();
1851 if(!pCreature)
1853 SendSysMessage(LANG_SELECT_CREATURE);
1854 SetSentErrorMessage(true);
1855 return false;
1858 pCreature->SetPhaseMask(phasemask,true);
1860 if(!pCreature->isPet())
1861 pCreature->SaveToDB();
1863 return true;
1865 //npc deathstate handling
1866 bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args)
1868 if (!*args)
1869 return false;
1871 Creature* pCreature = getSelectedCreature();
1872 if(!pCreature || pCreature->isPet())
1874 SendSysMessage(LANG_SELECT_CREATURE);
1875 SetSentErrorMessage(true);
1876 return false;
1879 if (strncmp(args, "on", 3) == 0)
1880 pCreature->SetDeadByDefault(true);
1881 else if (strncmp(args, "off", 4) == 0)
1882 pCreature->SetDeadByDefault(false);
1883 else
1885 SendSysMessage(LANG_USE_BOL);
1886 SetSentErrorMessage(true);
1887 return false;
1890 pCreature->SaveToDB();
1891 pCreature->Respawn();
1893 return true;
1896 //TODO: NpcCommands that need to be fixed :
1898 bool ChatHandler::HandleNpcNameCommand(const char* /*args*/)
1900 /* Temp. disabled
1901 if(!*args)
1902 return false;
1904 if(strlen((char*)args)>75)
1906 PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
1907 return true;
1910 for (uint8 i = 0; i < strlen(args); ++i)
1912 if(!isalpha(args[i]) && args[i]!=' ')
1914 SendSysMessage(LANG_CHARS_ONLY);
1915 return false;
1919 uint64 guid;
1920 guid = m_session->GetPlayer()->GetSelection();
1921 if (guid == 0)
1923 SendSysMessage(LANG_NO_SELECTION);
1924 return true;
1927 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
1929 if(!pCreature)
1931 SendSysMessage(LANG_SELECT_CREATURE);
1932 return true;
1935 pCreature->SetName(args);
1936 uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName());
1937 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
1939 pCreature->SaveToDB();
1942 return true;
1945 bool ChatHandler::HandleNpcSubNameCommand(const char* /*args*/)
1947 /* Temp. disabled
1949 if(!*args)
1950 args = "";
1952 if(strlen((char*)args)>75)
1955 PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
1956 return true;
1959 for (uint8 i = 0; i < strlen(args); i++)
1961 if(!isalpha(args[i]) && args[i]!=' ')
1963 SendSysMessage(LANG_CHARS_ONLY);
1964 return false;
1967 uint64 guid;
1968 guid = m_session->GetPlayer()->GetSelection();
1969 if (guid == 0)
1971 SendSysMessage(LANG_NO_SELECTION);
1972 return true;
1975 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
1977 if(!pCreature)
1979 SendSysMessage(LANG_SELECT_CREATURE);
1980 return true;
1983 uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
1984 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
1986 pCreature->SaveToDB();
1988 return true;
1991 //move item to other slot
1992 bool ChatHandler::HandleItemMoveCommand(const char* args)
1994 if(!*args)
1995 return false;
1996 uint8 srcslot, dstslot;
1998 char* pParam1 = strtok((char*)args, " ");
1999 if (!pParam1)
2000 return false;
2002 char* pParam2 = strtok(NULL, " ");
2003 if (!pParam2)
2004 return false;
2006 srcslot = (uint8)atoi(pParam1);
2007 dstslot = (uint8)atoi(pParam2);
2009 if(srcslot==dstslot)
2010 return true;
2012 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot))
2013 return false;
2015 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot))
2016 return false;
2018 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
2019 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
2021 m_session->GetPlayer()->SwapItem( src, dst );
2023 return true;
2026 //demorph player or unit
2027 bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
2029 Unit *target = getSelectedUnit();
2030 if(!target)
2031 target = m_session->GetPlayer();
2034 // check online security
2035 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2036 return false;
2038 target->DeMorph();
2040 return true;
2043 //morph creature or player
2044 bool ChatHandler::HandleModifyMorphCommand(const char* args)
2046 if (!*args)
2047 return false;
2049 uint16 display_id = (uint16)atoi((char*)args);
2051 Unit *target = getSelectedUnit();
2052 if(!target)
2053 target = m_session->GetPlayer();
2055 // check online security
2056 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2057 return false;
2059 target->SetDisplayId(display_id);
2061 return true;
2064 //kick player
2065 bool ChatHandler::HandleKickPlayerCommand(const char *args)
2067 Player* target;
2068 if(!extractPlayerTarget((char*)args,&target))
2069 return false;
2071 if (m_session && target==m_session->GetPlayer())
2073 SendSysMessage(LANG_COMMAND_KICKSELF);
2074 SetSentErrorMessage(true);
2075 return false;
2078 // check online security
2079 if (HasLowerSecurity(target, 0))
2080 return false;
2082 // send before target pointer invalidate
2083 PSendSysMessage(LANG_COMMAND_KICKMESSAGE,GetNameLink(target).c_str());
2084 target->GetSession()->KickPlayer();
2085 return true;
2088 //set temporary phase mask for player
2089 bool ChatHandler::HandleModifyPhaseCommand(const char* args)
2091 if (!*args)
2092 return false;
2094 uint32 phasemask = (uint32)atoi((char*)args);
2096 Unit *target = getSelectedUnit();
2097 if(!target)
2098 target = m_session->GetPlayer();
2100 // check online security
2101 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
2102 return false;
2104 target->SetPhaseMask(phasemask,true);
2106 return true;
2109 //show info of player
2110 bool ChatHandler::HandlePInfoCommand(const char* args)
2112 Player* target;
2113 uint64 target_guid;
2114 std::string target_name;
2115 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
2116 return false;
2118 uint32 accId = 0;
2119 uint32 money = 0;
2120 uint32 total_player_time = 0;
2121 uint32 level = 0;
2122 uint32 latency = 0;
2124 // get additional information from Player object
2125 if(target)
2127 // check online security
2128 if (HasLowerSecurity(target, 0))
2129 return false;
2131 accId = target->GetSession()->GetAccountId();
2132 money = target->GetMoney();
2133 total_player_time = target->GetTotalPlayedTime();
2134 level = target->getLevel();
2135 latency = target->GetSession()->GetLatency();
2137 // get additional information from DB
2138 else
2140 // check offline security
2141 if (HasLowerSecurity(NULL, target_guid))
2142 return false;
2144 // 0 1 2 3
2145 QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime, level, money, account FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid));
2146 if (!result)
2147 return false;
2149 Field *fields = result->Fetch();
2150 total_player_time = fields[0].GetUInt32();
2151 level = fields[1].GetUInt32();
2152 money = fields[2].GetUInt32();
2153 accId = fields[3].GetUInt32();
2154 delete result;
2157 std::string username = GetMangosString(LANG_ERROR);
2158 std::string last_ip = GetMangosString(LANG_ERROR);
2159 uint32 security = 0;
2160 std::string last_login = GetMangosString(LANG_ERROR);
2162 QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
2163 if(result)
2165 Field* fields = result->Fetch();
2166 username = fields[0].GetCppString();
2167 security = fields[1].GetUInt32();
2169 if(!m_session || m_session->GetSecurity() >= security)
2171 last_ip = fields[2].GetCppString();
2172 last_login = fields[3].GetCppString();
2174 else
2176 last_ip = "-";
2177 last_login = "-";
2180 delete result;
2183 std::string nameLink = playerLink(target_name);
2185 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);
2187 std::string timeStr = secsToTimeString(total_player_time,true,true);
2188 uint32 gold = money /GOLD;
2189 uint32 silv = (money % GOLD) / SILVER;
2190 uint32 copp = (money % GOLD) % SILVER;
2191 PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp );
2193 return true;
2196 //show tickets
2197 void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
2199 std::string name;
2200 if(!objmgr.GetPlayerNameByGUID(guid,name))
2201 name = GetMangosString(LANG_UNKNOWN);
2203 std::string nameLink = playerLink(name);
2205 PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(),time,text);
2208 //ticket commands
2209 bool ChatHandler::HandleTicketCommand(const char* args)
2211 char* px = strtok((char*)args, " ");
2213 // ticket<end>
2214 if (!px)
2216 if(!m_session)
2218 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2219 SetSentErrorMessage(true);
2220 return false;
2223 size_t count = ticketmgr.GetTicketCount();
2225 bool accept = m_session->GetPlayer()->isAcceptTickets();
2227 PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
2228 return true;
2231 // ticket on
2232 if(strncmp(px,"on",3) == 0)
2234 if(!m_session)
2236 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2237 SetSentErrorMessage(true);
2238 return false;
2241 m_session->GetPlayer()->SetAcceptTicket(true);
2242 SendSysMessage(LANG_COMMAND_TICKETON);
2243 return true;
2246 // ticket off
2247 if(strncmp(px,"off",4) == 0)
2249 if(!m_session)
2251 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2252 SetSentErrorMessage(true);
2253 return false;
2256 m_session->GetPlayer()->SetAcceptTicket(false);
2257 SendSysMessage(LANG_COMMAND_TICKETOFF);
2258 return true;
2261 // ticket #num
2262 int num = atoi(px);
2263 if(num > 0)
2265 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
2267 if(!result)
2269 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2270 SetSentErrorMessage(true);
2271 return false;
2274 Field* fields = result->Fetch();
2276 uint32 guid = fields[0].GetUInt32();
2277 char const* text = fields[1].GetString();
2278 char const* time = fields[2].GetString();
2280 ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
2281 delete result;
2282 return true;
2285 uint64 target_guid;
2286 if(!extractPlayerTarget(px,NULL,&target_guid))
2287 return false;
2289 // ticket $char_name
2290 GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(target_guid));
2291 if(!ticket)
2292 return false;
2294 std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
2296 ShowTicket(target_guid, ticket->GetText(), time.c_str());
2298 return true;
2301 //dell all tickets
2302 bool ChatHandler::HandleDelTicketCommand(const char *args)
2304 char* px = strtok((char*)args, " ");
2305 if (!px)
2306 return false;
2308 // delticket all
2309 if(strncmp(px,"all",4) == 0)
2311 ticketmgr.DeleteAll();
2312 SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2313 return true;
2316 int num = (uint32)atoi(px);
2318 // delticket #num
2319 if(num > 0)
2321 QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2322 if(!result)
2324 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2325 SetSentErrorMessage(true);
2326 return false;
2328 Field* fields = result->Fetch();
2329 uint32 guid = fields[0].GetUInt32();
2330 delete result;
2332 ticketmgr.Delete(guid);
2334 //notify player
2335 if(Player* pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)))
2337 pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
2338 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str());
2340 else
2341 PSendSysMessage(LANG_COMMAND_TICKETDEL);
2343 return true;
2346 Player* target;
2347 uint64 target_guid;
2348 std::string target_name;
2349 if(!extractPlayerTarget(px,&target,&target_guid,&target_name))
2350 return false;
2352 // delticket $char_name
2353 ticketmgr.Delete(GUID_LOPART(target_guid));
2355 // notify players about ticket deleting
2356 if(target)
2357 target->GetSession()->SendGMTicketGetTicket(0x0A,0);
2359 std::string nameLink = playerLink(target_name);
2361 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,nameLink.c_str());
2362 return true;
2366 * Add a waypoint to a creature.
2368 * The user can either select an npc or provide its GUID.
2370 * The user can even select a visual waypoint - then the new waypoint
2371 * is placed *after* the selected one - this makes insertion of new
2372 * waypoints possible.
2374 * eg:
2375 * .wp add 12345
2376 * -> adds a waypoint to the npc with the GUID 12345
2378 * .wp add
2379 * -> adds a waypoint to the currently selected creature
2382 * @param args if the user did not provide a GUID, it is NULL
2384 * @return true - command did succeed, false - something went wrong
2386 bool ChatHandler::HandleWpAddCommand(const char* args)
2388 sLog.outDebug("DEBUG: HandleWpAddCommand");
2390 // optional
2391 char* guid_str = NULL;
2393 if(*args)
2395 guid_str = strtok((char*)args, " ");
2398 uint32 lowguid = 0;
2399 uint32 point = 0;
2400 Creature* target = getSelectedCreature();
2401 // Did player provide a GUID?
2402 if (!guid_str)
2404 sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2406 // No GUID provided
2407 // -> Player must have selected a creature
2409 if(!target || target->isPet())
2411 SendSysMessage(LANG_SELECT_CREATURE);
2412 SetSentErrorMessage(true);
2413 return false;
2415 if (target->GetEntry() == VISUAL_WAYPOINT )
2417 sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2419 QueryResult *result =
2420 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2421 target->GetGUIDLow() );
2422 if(!result)
2424 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2425 // User selected a visual spawnpoint -> get the NPC
2426 // Select NPC GUID
2427 // Since we compare float values, we have to deal with
2428 // some difficulties.
2429 // Here we search for all waypoints that only differ in one from 1 thousand
2430 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2431 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2432 const char* maxDIFF = "0.01";
2433 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 )",
2434 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2435 if(!result)
2437 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2438 SetSentErrorMessage(true);
2439 return false;
2444 Field *fields = result->Fetch();
2445 lowguid = fields[0].GetUInt32();
2446 point = fields[1].GetUInt32();
2447 }while( result->NextRow() );
2448 delete result;
2450 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2451 if(!data)
2453 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2454 SetSentErrorMessage(true);
2455 return false;
2458 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2459 if(!target)
2461 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2462 SetSentErrorMessage(true);
2463 return false;
2466 else
2468 lowguid = target->GetDBTableGUIDLow();
2471 else
2473 sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2475 // GUID provided
2476 // Warn if player also selected a creature
2477 // -> Creature selection is ignored <-
2478 if(target)
2480 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2482 lowguid = atoi((char*)guid_str);
2484 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2485 if(!data)
2487 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2488 SetSentErrorMessage(true);
2489 return false;
2492 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2493 if(!target || target->isPet())
2495 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2496 SetSentErrorMessage(true);
2497 return false;
2500 // lowguid -> GUID of the NPC
2501 // point -> number of the waypoint (if not 0)
2502 sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2504 sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2506 Player* player = m_session->GetPlayer();
2507 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2509 // update movement type
2510 if(target)
2512 target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2513 target->GetMotionMaster()->Initialize();
2514 if(target->isAlive()) // dead creature will reset movement generator at respawn
2516 target->setDeathState(JUST_DIED);
2517 target->Respawn();
2519 target->SaveToDB();
2521 else
2522 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2524 PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2526 return true;
2527 } // HandleWpAddCommand
2530 * .wp modify emote | spell | text | del | move | add
2532 * add -> add a WP after the selected visual waypoint
2533 * User must select a visual waypoint and then issue ".wp modify add"
2535 * emote <emoteID>
2536 * User has selected a visual waypoint before.
2537 * <emoteID> is added to this waypoint. Everytime the
2538 * NPC comes to this waypoint, the emote is called.
2540 * emote <GUID> <WPNUM> <emoteID>
2541 * User has not selected visual waypoint before.
2542 * For the waypoint <WPNUM> for the NPC with <GUID>
2543 * an emote <emoteID> is added.
2544 * Everytime the NPC comes to this waypoint, the emote is called.
2547 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2549 bool ChatHandler::HandleWpModifyCommand(const char* args)
2551 sLog.outDebug("DEBUG: HandleWpModifyCommand");
2553 if(!*args)
2554 return false;
2556 // first arg: add del text emote spell waittime move
2557 char* show_str = strtok((char*)args, " ");
2558 if (!show_str)
2560 return false;
2563 std::string show = show_str;
2564 // Check
2565 // Remember: "show" must also be the name of a column!
2566 if( (show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2")
2567 && (show != "textid3") && (show != "textid4") && (show != "textid5")
2568 && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2569 && (show != "model1") && (show != "model2") && (show != "orientation"))
2571 return false;
2574 // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2576 // Did user provide a GUID
2577 // or did the user select a creature?
2578 // -> variable lowguid is filled with the GUID of the NPC
2579 uint32 lowguid = 0;
2580 uint32 point = 0;
2581 uint32 wpGuid = 0;
2582 Creature* target = getSelectedCreature();
2584 if(target)
2586 sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2588 // Did the user select a visual spawnpoint?
2589 if (target->GetEntry() != VISUAL_WAYPOINT )
2591 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2592 SetSentErrorMessage(true);
2593 return false;
2596 wpGuid = target->GetGUIDLow();
2598 // The visual waypoint
2599 QueryResult *result =
2600 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2601 target->GetGUIDLow() );
2602 if(!result)
2604 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2605 SetSentErrorMessage(true);
2606 return false;
2608 sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2610 Field *fields = result->Fetch();
2611 lowguid = fields[0].GetUInt32();
2612 point = fields[1].GetUInt32();
2614 // Cleanup memory
2615 sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2616 delete result;
2618 else
2620 // User did provide <GUID> <WPNUM>
2622 char* guid_str = strtok((char*)NULL, " ");
2623 if( !guid_str )
2625 SendSysMessage(LANG_WAYPOINT_NOGUID);
2626 return false;
2628 lowguid = atoi((char*)guid_str);
2630 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2631 if(!data)
2633 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2634 SetSentErrorMessage(true);
2635 return false;
2638 PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2640 char* point_str = strtok((char*)NULL, " ");
2641 if( !point_str )
2643 SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2644 return false;
2646 point = atoi((char*)point_str);
2648 PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2650 // Now we need the GUID of the visual waypoint
2651 // -> "del", "move", "add" command
2653 QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2654 if (!result)
2656 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2657 SetSentErrorMessage(true);
2658 return false;
2661 Field *fields = result->Fetch();
2662 wpGuid = fields[0].GetUInt32();
2664 // Free memory
2665 delete result;
2668 char* arg_str = NULL;
2669 // Check for argument
2670 if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2672 // Text is enclosed in "<>", all other arguments not
2673 if( show.find("text") != std::string::npos )
2674 arg_str = strtok((char*)NULL, "<>");
2675 else
2676 arg_str = strtok((char*)NULL, " ");
2678 if( !arg_str)
2680 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2681 return false;
2685 sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2687 // wpGuid -> GUID of the waypoint creature
2688 // lowguid -> GUID of the NPC
2689 // point -> waypoint number
2691 // Special functions:
2692 // add - move - del -> no args commands
2693 // Add a waypoint after the selected visual
2694 if(show == "add" && target)
2696 PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2698 // Get the creature for which we read the waypoint
2699 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2700 if(!data)
2702 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2703 SetSentErrorMessage(true);
2704 return false;
2707 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2709 if( !npcCreature )
2711 PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2712 SetSentErrorMessage(true);
2713 return false;
2716 sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2718 // What to do:
2719 // Add the visual spawnpoint (DB only)
2720 // Adjust the waypoints
2721 // Respawn the owner of the waypoints
2722 sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2724 Player* chr = m_session->GetPlayer();
2725 Map *map = chr->GetMap();
2727 if(npcCreature)
2729 npcCreature->GetMotionMaster()->Initialize();
2730 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2732 npcCreature->setDeathState(JUST_DIED);
2733 npcCreature->Respawn();
2737 // create the waypoint creature
2738 wpGuid = 0;
2739 Creature* wpCreature = new Creature;
2740 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT,0))
2742 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2743 delete wpCreature;
2745 else
2747 wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2749 if(!wpCreature->IsPositionValid())
2751 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());
2752 delete wpCreature;
2754 else
2756 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
2757 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2758 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2759 map->Add(wpCreature);
2760 wpGuid = wpCreature->GetGUIDLow();
2764 WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2766 if(!wpGuid)
2767 return false;
2769 PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2770 return true;
2771 } // add
2773 if(show == "del" && target)
2775 PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2777 // Get the creature for which we read the waypoint
2778 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2779 if(!data)
2781 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2782 SetSentErrorMessage(true);
2783 return false;
2786 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2788 // wpCreature
2789 Creature* wpCreature = NULL;
2790 if( wpGuid != 0 )
2792 wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2793 wpCreature->DeleteFromDB();
2794 wpCreature->AddObjectToRemoveList();
2797 // What to do:
2798 // Remove the visual spawnpoint
2799 // Adjust the waypoints
2800 // Respawn the owner of the waypoints
2802 WaypointMgr.DeleteNode(lowguid, point);
2804 if(npcCreature)
2806 // Any waypoints left?
2807 QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2808 if(!result2)
2810 npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2812 else
2814 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2815 delete result2;
2817 npcCreature->GetMotionMaster()->Initialize();
2818 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2820 npcCreature->setDeathState(JUST_DIED);
2821 npcCreature->Respawn();
2823 npcCreature->SaveToDB();
2826 PSendSysMessage(LANG_WAYPOINT_REMOVED);
2827 return true;
2828 } // del
2830 if(show == "move" && target)
2832 PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2834 Player *chr = m_session->GetPlayer();
2835 Map *map = chr->GetMap();
2837 // Get the creature for which we read the waypoint
2838 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2839 if(!data)
2841 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2842 SetSentErrorMessage(true);
2843 return false;
2846 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2848 // wpCreature
2849 Creature* wpCreature = NULL;
2850 // What to do:
2851 // Move the visual spawnpoint
2852 // Respawn the owner of the waypoints
2853 if( wpGuid != 0 )
2855 wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2856 wpCreature->DeleteFromDB();
2857 wpCreature->AddObjectToRemoveList();
2858 // re-create
2859 Creature* wpCreature2 = new Creature;
2860 if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0))
2862 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2863 delete wpCreature2;
2864 return false;
2867 wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2869 if(!wpCreature2->IsPositionValid())
2871 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());
2872 delete wpCreature2;
2873 return false;
2876 wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
2877 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2878 wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2879 map->Add(wpCreature2);
2880 //npcCreature->GetMap()->Add(wpCreature2);
2883 WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2885 if(npcCreature)
2887 npcCreature->GetMotionMaster()->Initialize();
2888 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2890 npcCreature->setDeathState(JUST_DIED);
2891 npcCreature->Respawn();
2894 PSendSysMessage(LANG_WAYPOINT_CHANGED);
2896 return true;
2897 } // move
2899 // Create creature - npc that has the waypoint
2900 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2901 if(!data)
2903 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2904 SetSentErrorMessage(true);
2905 return false;
2908 // set in game textids not supported
2909 if( show == "textid1" || show == "textid2" || show == "textid3" ||
2910 show == "textid4" || show == "textid5" )
2912 return false;
2915 WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2917 Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2918 if(npcCreature)
2920 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2921 npcCreature->GetMotionMaster()->Initialize();
2922 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2924 npcCreature->setDeathState(JUST_DIED);
2925 npcCreature->Respawn();
2928 PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2930 return true;
2934 * .wp show info | on | off
2936 * info -> User has selected a visual waypoint before
2938 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2939 * provided the GUID of the NPC and the number of
2940 * the waypoint.
2942 * on -> User has selected an NPC; all visual waypoints for this
2943 * NPC are added to the world
2945 * on <GUID> -> User did not select an NPC - instead the GUID of the
2946 * NPC is provided. All visual waypoints for this NPC
2947 * are added from the world.
2949 * off -> User has selected an NPC; all visual waypoints for this
2950 * NPC are removed from the world.
2952 * on <GUID> -> User did not select an NPC - instead the GUID of the
2953 * NPC is provided. All visual waypoints for this NPC
2954 * are removed from the world.
2958 bool ChatHandler::HandleWpShowCommand(const char* args)
2960 sLog.outDebug("DEBUG: HandleWpShowCommand");
2962 if(!*args)
2963 return false;
2965 // first arg: on, off, first, last
2966 char* show_str = strtok((char*)args, " ");
2967 if (!show_str)
2969 return false;
2971 // second arg: GUID (optional, if a creature is selected)
2972 char* guid_str = strtok((char*)NULL, " ");
2973 sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
2974 //if (!guid_str) {
2975 // return false;
2978 // Did user provide a GUID
2979 // or did the user select a creature?
2980 // -> variable lowguid is filled with the GUID
2981 Creature* target = getSelectedCreature();
2982 // Did player provide a GUID?
2983 if (!guid_str)
2985 sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
2986 // No GUID provided
2987 // -> Player must have selected a creature
2989 if(!target)
2991 SendSysMessage(LANG_SELECT_CREATURE);
2992 SetSentErrorMessage(true);
2993 return false;
2996 else
2998 sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
2999 // GUID provided
3000 // Warn if player also selected a creature
3001 // -> Creature selection is ignored <-
3002 if(target)
3004 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
3007 uint32 lowguid = atoi((char*)guid_str);
3009 CreatureData const* data = objmgr.GetCreatureData(lowguid);
3010 if(!data)
3012 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
3013 SetSentErrorMessage(true);
3014 return false;
3017 target = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
3019 if(!target)
3021 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
3022 SetSentErrorMessage(true);
3023 return false;
3027 uint32 lowguid = target->GetDBTableGUIDLow();
3029 std::string show = show_str;
3030 uint32 Maxpoint;
3032 sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
3034 // Show info for the selected waypoint
3035 if(show == "info")
3037 PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
3039 // Check if the user did specify a visual waypoint
3040 if( target->GetEntry() != VISUAL_WAYPOINT )
3042 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
3043 SetSentErrorMessage(true);
3044 return false;
3047 //PSendSysMessage("wp on, GUID: %u", lowguid);
3049 //pCreature->GetPositionX();
3051 QueryResult *result =
3052 WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u",
3053 target->GetGUIDLow() );
3054 if(!result)
3056 // Since we compare float values, we have to deal with
3057 // some difficulties.
3058 // Here we search for all waypoints that only differ in one from 1 thousand
3059 // (0.001) - There is no other way to compare C++ floats with mySQL floats
3060 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
3061 const char* maxDIFF = "0.01";
3062 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
3064 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 )",
3065 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
3066 if(!result)
3068 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
3069 SetSentErrorMessage(true);
3070 return false;
3075 Field *fields = result->Fetch();
3076 uint32 creGUID = fields[0].GetUInt32();
3077 uint32 point = fields[1].GetUInt32();
3078 int waittime = fields[2].GetUInt32();
3079 uint32 emote = fields[3].GetUInt32();
3080 uint32 spell = fields[4].GetUInt32();
3081 uint32 textid[MAX_WAYPOINT_TEXT];
3082 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
3083 textid[i] = fields[5+i].GetUInt32();
3084 uint32 model1 = fields[10].GetUInt32();
3085 uint32 model2 = fields[11].GetUInt32();
3087 // Get the creature for which we read the waypoint
3088 Creature* wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3090 PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
3091 PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
3092 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
3093 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
3094 PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
3095 PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
3096 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
3097 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i+1, textid[i], (textid[i] ? GetMangosString(textid[i]) : ""));
3099 }while( result->NextRow() );
3100 // Cleanup memory
3101 delete result;
3102 return true;
3105 if(show == "on")
3107 PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
3109 QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
3110 if(!result)
3112 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3113 SetSentErrorMessage(true);
3114 return false;
3116 // Delete all visuals for this NPC
3117 QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
3118 if(result2)
3120 bool hasError = false;
3123 Field *fields = result2->Fetch();
3124 uint32 wpguid = fields[0].GetUInt32();
3125 Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3127 if(!pCreature)
3129 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
3130 hasError = true;
3131 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
3133 else
3135 pCreature->DeleteFromDB();
3136 pCreature->AddObjectToRemoveList();
3139 }while( result2->NextRow() );
3140 delete result2;
3141 if( hasError )
3143 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3144 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3145 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3151 Field *fields = result->Fetch();
3152 uint32 point = fields[0].GetUInt32();
3153 float x = fields[1].GetFloat();
3154 float y = fields[2].GetFloat();
3155 float z = fields[3].GetFloat();
3157 uint32 id = VISUAL_WAYPOINT;
3159 Player *chr = m_session->GetPlayer();
3160 Map *map = chr->GetMap();
3161 float o = chr->GetOrientation();
3163 Creature* wpCreature = new Creature;
3164 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
3166 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3167 delete wpCreature;
3168 delete result;
3169 return false;
3172 wpCreature->Relocate(x, y, z, o);
3174 if(!wpCreature->IsPositionValid())
3176 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());
3177 delete wpCreature;
3178 delete result;
3179 return false;
3182 wpCreature->SetVisibility(VISIBILITY_OFF);
3183 sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
3184 // set "wpguid" column to the visual waypoint
3185 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
3187 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3188 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
3189 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
3190 map->Add(wpCreature);
3191 //wpCreature->GetMap()->Add(wpCreature);
3192 }while( result->NextRow() );
3194 // Cleanup memory
3195 delete result;
3196 return true;
3199 if(show == "first")
3201 PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3203 QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3204 if(!result)
3206 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3207 SetSentErrorMessage(true);
3208 return false;
3211 Field *fields = result->Fetch();
3212 float x = fields[0].GetFloat();
3213 float y = fields[1].GetFloat();
3214 float z = fields[2].GetFloat();
3215 uint32 id = VISUAL_WAYPOINT;
3217 Player *chr = m_session->GetPlayer();
3218 float o = chr->GetOrientation();
3219 Map *map = chr->GetMap();
3221 Creature* pCreature = new Creature;
3222 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0))
3224 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3225 delete pCreature;
3226 delete result;
3227 return false;
3230 pCreature->Relocate(x, y, z, o);
3232 if(!pCreature->IsPositionValid())
3234 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());
3235 delete pCreature;
3236 delete result;
3237 return false;
3240 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3241 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3242 map->Add(pCreature);
3243 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3245 // Cleanup memory
3246 delete result;
3247 return true;
3250 if(show == "last")
3252 PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3254 QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3255 if( result )
3257 Maxpoint = (*result)[0].GetUInt32();
3259 delete result;
3261 else
3262 Maxpoint = 0;
3264 result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3265 if(!result)
3267 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3268 SetSentErrorMessage(true);
3269 return false;
3271 Field *fields = result->Fetch();
3272 float x = fields[0].GetFloat();
3273 float y = fields[1].GetFloat();
3274 float z = fields[2].GetFloat();
3275 uint32 id = VISUAL_WAYPOINT;
3277 Player *chr = m_session->GetPlayer();
3278 float o = chr->GetOrientation();
3279 Map *map = chr->GetMap();
3281 Creature* pCreature = new Creature;
3282 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
3284 PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3285 delete pCreature;
3286 delete result;
3287 return false;
3290 pCreature->Relocate(x, y, z, o);
3292 if(!pCreature->IsPositionValid())
3294 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());
3295 delete pCreature;
3296 delete result;
3297 return false;
3300 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3301 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3302 map->Add(pCreature);
3303 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3304 // Cleanup memory
3305 delete result;
3306 return true;
3309 if(show == "off")
3311 QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3312 if(!result)
3314 SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3315 SetSentErrorMessage(true);
3316 return false;
3318 bool hasError = false;
3321 Field *fields = result->Fetch();
3322 uint32 guid = fields[0].GetUInt32();
3323 Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3324 if(!pCreature)
3326 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3327 hasError = true;
3328 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3330 else
3332 pCreature->DeleteFromDB();
3333 pCreature->AddObjectToRemoveList();
3335 }while(result->NextRow());
3336 // set "wpguid" column to "empty" - no visual waypoint spawned
3337 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
3339 if( hasError )
3341 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3342 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3343 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3346 SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3347 // Cleanup memory
3348 delete result;
3350 return true;
3353 PSendSysMessage("DEBUG: wpshow - no valid command found");
3355 return true;
3356 } // HandleWpShowCommand
3358 bool ChatHandler::HandleWpExportCommand(const char *args)
3360 if(!*args)
3361 return false;
3363 // Next arg is: <GUID> <ARGUMENT>
3365 // Did user provide a GUID
3366 // or did the user select a creature?
3367 // -> variable lowguid is filled with the GUID of the NPC
3368 uint32 lowguid = 0;
3369 Creature* target = getSelectedCreature();
3370 char* arg_str = NULL;
3371 if (target)
3373 if (target->GetEntry() != VISUAL_WAYPOINT)
3374 lowguid = target->GetGUIDLow();
3375 else
3377 QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3378 if (!result)
3380 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3381 return true;
3383 Field *fields = result->Fetch();
3384 lowguid = fields[0].GetUInt32();;
3385 delete result;
3388 arg_str = strtok((char*)args, " ");
3390 else
3392 // user provided <GUID>
3393 char* guid_str = strtok((char*)args, " ");
3394 if( !guid_str )
3396 SendSysMessage(LANG_WAYPOINT_NOGUID);
3397 return false;
3399 lowguid = atoi((char*)guid_str);
3401 arg_str = strtok((char*)NULL, " ");
3404 if( !arg_str)
3406 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3407 return false;
3410 PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3412 QueryResult *result = WorldDatabase.PQuery(
3413 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3414 "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 );
3416 if (!result)
3418 PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3419 SetSentErrorMessage(true);
3420 return false;
3423 std::ofstream outfile;
3424 outfile.open (arg_str);
3428 Field *fields = result->Fetch();
3430 outfile << "INSERT INTO creature_movement ";
3431 outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5 ) VALUES ";
3433 outfile << "( ";
3434 outfile << fields[15].GetUInt32(); // id
3435 outfile << ", ";
3436 outfile << fields[0].GetUInt32(); // point
3437 outfile << ", ";
3438 outfile << fields[1].GetFloat(); // position_x
3439 outfile << ", ";
3440 outfile << fields[2].GetFloat(); // position_y
3441 outfile << ", ";
3442 outfile << fields[3].GetUInt32(); // position_z
3443 outfile << ", ";
3444 outfile << fields[4].GetUInt32(); // orientation
3445 outfile << ", ";
3446 outfile << fields[5].GetUInt32(); // model1
3447 outfile << ", ";
3448 outfile << fields[6].GetUInt32(); // model2
3449 outfile << ", ";
3450 outfile << fields[7].GetUInt16(); // waittime
3451 outfile << ", ";
3452 outfile << fields[8].GetUInt32(); // emote
3453 outfile << ", ";
3454 outfile << fields[9].GetUInt32(); // spell
3455 outfile << ", ";
3456 outfile << fields[10].GetUInt32(); // textid1
3457 outfile << ", ";
3458 outfile << fields[11].GetUInt32(); // textid2
3459 outfile << ", ";
3460 outfile << fields[12].GetUInt32(); // textid3
3461 outfile << ", ";
3462 outfile << fields[13].GetUInt32(); // textid4
3463 outfile << ", ";
3464 outfile << fields[14].GetUInt32(); // textid5
3465 outfile << ");\n ";
3467 } while( result->NextRow() );
3468 delete result;
3470 PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3471 outfile.close();
3473 return true;
3476 bool ChatHandler::HandleWpImportCommand(const char *args)
3478 if(!*args)
3479 return false;
3481 char* arg_str = strtok((char*)args, " ");
3482 if (!arg_str)
3483 return false;
3485 std::string line;
3486 std::ifstream infile (arg_str);
3487 if (infile.is_open())
3489 while (! infile.eof() )
3491 getline (infile,line);
3492 //cout << line << endl;
3493 QueryResult *result = WorldDatabase.Query(line.c_str());
3494 delete result;
3496 infile.close();
3498 PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3500 return true;
3503 //rename characters
3504 bool ChatHandler::HandleCharacterRenameCommand(const char* args)
3506 Player* target;
3507 uint64 target_guid;
3508 std::string target_name;
3509 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
3510 return false;
3512 if(target)
3514 // check online security
3515 if (HasLowerSecurity(target, 0))
3516 return false;
3518 PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str());
3519 target->SetAtLoginFlag(AT_LOGIN_RENAME);
3520 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3522 else
3524 // check offline security
3525 if (HasLowerSecurity(NULL, target_guid))
3526 return false;
3528 std::string oldNameLink = playerLink(target_name);
3530 PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid));
3531 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(target_guid));
3534 return true;
3537 // customize characters
3538 bool ChatHandler::HandleCharacterCustomizeCommand(const char* args)
3540 Player* target;
3541 uint64 target_guid;
3542 std::string target_name;
3543 if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
3544 return false;
3546 if(target)
3548 PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str());
3549 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
3550 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow());
3552 else
3554 std::string oldNameLink = playerLink(target_name);
3556 PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid));
3557 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(target_guid));
3560 return true;
3563 bool ChatHandler::HandleCharacterReputationCommand(const char* args)
3565 Player* target;
3566 if(!extractPlayerTarget((char*)args,&target))
3567 return false;
3569 LocaleConstant loc = GetSessionDbcLocale();
3571 FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList();
3572 for(FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr)
3574 FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
3575 char const* factionName = factionEntry ? factionEntry->name[loc] : "#Not found#";
3576 ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry);
3577 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
3578 std::ostringstream ss;
3579 if (m_session)
3580 ss << itr->second.ID << " - |cffffffff|Hfaction:" << itr->second.ID << "|h[" << factionName << " " << localeNames[loc] << "]|h|r";
3581 else
3582 ss << itr->second.ID << " - " << factionName << " " << localeNames[loc];
3584 ss << " " << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ")";
3586 if(itr->second.Flags & FACTION_FLAG_VISIBLE)
3587 ss << GetMangosString(LANG_FACTION_VISIBLE);
3588 if(itr->second.Flags & FACTION_FLAG_AT_WAR)
3589 ss << GetMangosString(LANG_FACTION_ATWAR);
3590 if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
3591 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
3592 if(itr->second.Flags & FACTION_FLAG_HIDDEN)
3593 ss << GetMangosString(LANG_FACTION_HIDDEN);
3594 if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
3595 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
3596 if(itr->second.Flags & FACTION_FLAG_INACTIVE)
3597 ss << GetMangosString(LANG_FACTION_INACTIVE);
3599 SendSysMessage(ss.str().c_str());
3601 return true;
3604 //change standstate
3605 bool ChatHandler::HandleModifyStandStateCommand(const char* args)
3607 if (!*args)
3608 return false;
3610 uint32 anim_id = atoi((char*)args);
3611 m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3613 return true;
3616 bool ChatHandler::HandleHonorAddCommand(const char* args)
3618 if (!*args)
3619 return false;
3621 Player *target = getSelectedPlayer();
3622 if(!target)
3624 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3625 SetSentErrorMessage(true);
3626 return false;
3629 // check online security
3630 if (HasLowerSecurity(target, 0))
3631 return false;
3633 uint32 amount = (uint32)atoi(args);
3634 target->RewardHonor(NULL, 1, amount);
3635 return true;
3638 bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3640 Unit *target = getSelectedUnit();
3641 if(!target)
3643 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3644 SetSentErrorMessage(true);
3645 return false;
3648 // check online security
3649 if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
3650 return false;
3652 m_session->GetPlayer()->RewardHonor(target, 1);
3653 return true;
3656 bool ChatHandler::HandleHonorUpdateCommand(const char* /*args*/)
3658 Player *target = getSelectedPlayer();
3659 if(!target)
3661 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3662 SetSentErrorMessage(true);
3663 return false;
3666 // check online security
3667 if (HasLowerSecurity(target, 0))
3668 return false;
3670 target->UpdateHonorFields();
3671 return true;
3674 bool ChatHandler::HandleLookupEventCommand(const char* args)
3676 if(!*args)
3677 return false;
3679 std::string namepart = args;
3680 std::wstring wnamepart;
3682 // converting string that we try to find to lower case
3683 if(!Utf8toWStr(namepart,wnamepart))
3684 return false;
3686 wstrToLower(wnamepart);
3688 uint32 counter = 0;
3690 GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3691 GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3693 for(uint32 id = 0; id < events.size(); ++id )
3695 GameEventData const& eventData = events[id];
3697 std::string descr = eventData.description;
3698 if(descr.empty())
3699 continue;
3701 if (Utf8FitTo(descr, wnamepart))
3703 char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : "";
3705 if(m_session)
3706 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3707 else
3708 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3710 ++counter;
3714 if (counter==0)
3715 SendSysMessage(LANG_NOEVENTFOUND);
3717 return true;
3720 bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/)
3722 uint32 counter = 0;
3724 GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3725 GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3727 char const* active = GetMangosString(LANG_ACTIVE);
3729 for(GameEventMgr::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
3731 uint32 event_id = *itr;
3732 GameEventData const& eventData = events[event_id];
3734 if(m_session)
3735 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
3736 else
3737 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
3739 ++counter;
3742 if (counter==0)
3743 SendSysMessage(LANG_NOEVENTFOUND);
3745 return true;
3748 bool ChatHandler::HandleEventInfoCommand(const char* args)
3750 if(!*args)
3751 return false;
3753 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3754 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3755 if(!cId)
3756 return false;
3758 uint32 event_id = atoi(cId);
3760 GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3762 if(event_id >=events.size())
3764 SendSysMessage(LANG_EVENT_NOT_EXIST);
3765 SetSentErrorMessage(true);
3766 return false;
3769 GameEventData const& eventData = events[event_id];
3770 if(!eventData.isValid())
3772 SendSysMessage(LANG_EVENT_NOT_EXIST);
3773 SetSentErrorMessage(true);
3774 return false;
3777 GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3778 bool active = activeEvents.find(event_id) != activeEvents.end();
3779 char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : "";
3781 std::string startTimeStr = TimeToTimestampStr(eventData.start);
3782 std::string endTimeStr = TimeToTimestampStr(eventData.end);
3784 uint32 delay = gameeventmgr.NextCheck(event_id);
3785 time_t nextTime = time(NULL)+delay;
3786 std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3788 std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3789 std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3791 PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3792 startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3793 nextStr.c_str());
3794 return true;
3797 bool ChatHandler::HandleEventStartCommand(const char* args)
3799 if(!*args)
3800 return false;
3802 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3803 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3804 if(!cId)
3805 return false;
3807 int32 event_id = atoi(cId);
3809 GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3811 if(event_id < 1 || event_id >=events.size())
3813 SendSysMessage(LANG_EVENT_NOT_EXIST);
3814 SetSentErrorMessage(true);
3815 return false;
3818 GameEventData const& eventData = events[event_id];
3819 if(!eventData.isValid())
3821 SendSysMessage(LANG_EVENT_NOT_EXIST);
3822 SetSentErrorMessage(true);
3823 return false;
3826 GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3827 if(activeEvents.find(event_id) != activeEvents.end())
3829 PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3830 SetSentErrorMessage(true);
3831 return false;
3834 gameeventmgr.StartEvent(event_id,true);
3835 return true;
3838 bool ChatHandler::HandleEventStopCommand(const char* args)
3840 if(!*args)
3841 return false;
3843 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3844 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3845 if(!cId)
3846 return false;
3848 int32 event_id = atoi(cId);
3850 GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3852 if(event_id < 1 || event_id >=events.size())
3854 SendSysMessage(LANG_EVENT_NOT_EXIST);
3855 SetSentErrorMessage(true);
3856 return false;
3859 GameEventData const& eventData = events[event_id];
3860 if(!eventData.isValid())
3862 SendSysMessage(LANG_EVENT_NOT_EXIST);
3863 SetSentErrorMessage(true);
3864 return false;
3867 GameEventMgr::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3869 if(activeEvents.find(event_id) == activeEvents.end())
3871 PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3872 SetSentErrorMessage(true);
3873 return false;
3876 gameeventmgr.StopEvent(event_id,true);
3877 return true;
3880 bool ChatHandler::HandleCombatStopCommand(const char* args)
3882 Player* target;
3883 if(!extractPlayerTarget((char*)args,&target))
3884 return false;
3886 // check online security
3887 if (HasLowerSecurity(target, 0))
3888 return false;
3890 target->CombatStop();
3891 target->getHostilRefManager().deleteReferences();
3892 return true;
3895 void ChatHandler::HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id)
3897 uint32 classmask = player->getClassMask();
3899 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3901 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3902 if (!skillLine)
3903 continue;
3905 // wrong skill
3906 if( skillLine->skillId != skill_id)
3907 continue;
3909 // not high rank
3910 if(skillLine->forward_spellid )
3911 continue;
3913 // skip racial skills
3914 if (skillLine->racemask != 0)
3915 continue;
3917 // skip wrong class skills
3918 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3919 continue;
3921 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3922 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,player,false))
3923 continue;
3925 player->learnSpell(skillLine->spellId,false);
3929 bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3931 uint32 classmask = m_session->GetPlayer()->getClassMask();
3933 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3935 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3936 if( !skillInfo )
3937 continue;
3939 if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) &&
3940 skillInfo->canLink) // only prof. with recipes have
3942 HandleLearnSkillRecipesHelper(m_session->GetPlayer(),skillInfo->id);
3946 SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
3947 return true;
3950 bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
3952 // Learns all recipes of specified profession and sets skill to max
3953 // Example: .learn all_recipes enchanting
3955 Player* target = getSelectedPlayer();
3956 if( !target )
3958 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3959 return false;
3962 if(!*args)
3963 return false;
3965 std::wstring wnamepart;
3967 if(!Utf8toWStr(args,wnamepart))
3968 return false;
3970 // converting string that we try to find to lower case
3971 wstrToLower( wnamepart );
3973 uint32 classmask = m_session->GetPlayer()->getClassMask();
3975 std::string name;
3977 SkillLineEntry const *targetSkillInfo = NULL;
3978 for (uint32 i = 1; i < sSkillLineStore.GetNumRows(); ++i)
3980 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3981 if (!skillInfo)
3982 continue;
3984 if ((skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
3985 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY) ||
3986 !skillInfo->canLink) // only prof with recipes have set
3987 continue;
3989 int loc = GetSessionDbcLocale();
3990 name = skillInfo->name[loc];
3991 if(name.empty())
3992 continue;
3994 if (!Utf8FitTo(name, wnamepart))
3996 loc = 0;
3997 for(; loc < MAX_LOCALE; ++loc)
3999 if(loc==GetSessionDbcLocale())
4000 continue;
4002 name = skillInfo->name[loc];
4003 if(name.empty())
4004 continue;
4006 if (Utf8FitTo(name, wnamepart))
4007 break;
4011 if(loc < MAX_LOCALE)
4013 targetSkillInfo = skillInfo;
4014 break;
4018 if(!targetSkillInfo)
4019 return false;
4021 HandleLearnSkillRecipesHelper(target,targetSkillInfo->id);
4023 uint16 maxLevel = target->GetPureMaxSkillValue(targetSkillInfo->id);
4024 target->SetSkill(targetSkillInfo->id, maxLevel, maxLevel);
4025 PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
4026 return true;
4029 bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
4032 if (!*args)
4033 return false;
4035 std::string ip = strtok ((char*)args, " ");
4036 char* limit_str = strtok (NULL, " ");
4037 int32 limit = limit_str ? atoi (limit_str) : -1;
4039 loginDatabase.escape_string (ip);
4041 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
4043 return LookupPlayerSearchCommand (result,limit);
4046 bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
4048 if (!*args)
4049 return false;
4051 std::string account = strtok ((char*)args, " ");
4052 char* limit_str = strtok (NULL, " ");
4053 int32 limit = limit_str ? atoi (limit_str) : -1;
4055 if (!AccountMgr::normalizeString (account))
4056 return false;
4058 loginDatabase.escape_string (account);
4060 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
4062 return LookupPlayerSearchCommand (result,limit);
4065 bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
4068 if (!*args)
4069 return false;
4071 std::string email = strtok ((char*)args, " ");
4072 char* limit_str = strtok (NULL, " ");
4073 int32 limit = limit_str ? atoi (limit_str) : -1;
4075 loginDatabase.escape_string (email);
4077 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
4079 return LookupPlayerSearchCommand (result,limit);
4082 bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
4084 if(!result)
4086 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4087 SetSentErrorMessage(true);
4088 return false;
4091 int i =0;
4094 Field* fields = result->Fetch();
4095 uint32 acc_id = fields[0].GetUInt32();
4096 std::string acc_name = fields[1].GetCppString();
4098 QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
4099 if(chars)
4101 PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4103 uint64 guid = 0;
4104 std::string name;
4108 Field* charfields = chars->Fetch();
4109 guid = charfields[0].GetUInt64();
4110 name = charfields[1].GetCppString();
4112 PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
4113 ++i;
4115 } while( chars->NextRow() && ( limit == -1 || i < limit ) );
4117 delete chars;
4119 } while(result->NextRow());
4121 delete result;
4123 if(i==0) // empty accounts only
4125 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4126 SetSentErrorMessage(true);
4127 return false;
4130 return true;
4133 /// Triggering corpses expire check in world
4134 bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4136 CorpsesErase();
4137 return true;
4140 bool ChatHandler::HandleRepairitemsCommand(const char* args)
4142 Player* target;
4143 if(!extractPlayerTarget((char*)args,&target))
4144 return false;
4146 // check online security
4147 if (HasLowerSecurity(target, 0))
4148 return false;
4150 // Repair items
4151 target->DurabilityRepairAll(false, 0, false);
4153 PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str());
4154 if(needReportToTarget(target))
4155 ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str());
4156 return true;
4159 bool ChatHandler::HandleWaterwalkCommand(const char* args)
4161 if(!*args)
4162 return false;
4164 Player *player = getSelectedPlayer();
4166 if(!player)
4168 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4169 SetSentErrorMessage(true);
4170 return false;
4173 // check online security
4174 if (HasLowerSecurity(player, 0))
4175 return false;
4177 if (strncmp(args, "on", 3) == 0)
4178 player->SetMovement(MOVE_WATER_WALK); // ON
4179 else if (strncmp(args, "off", 4) == 0)
4180 player->SetMovement(MOVE_LAND_WALK); // OFF
4181 else
4183 SendSysMessage(LANG_USE_BOL);
4184 return false;
4187 PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str());
4188 if(needReportToTarget(player))
4189 ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str());
4190 return true;