[7290] Command .npc setdeathstate on/off.
[getmangos.git] / src / game / Level2.cpp
blob24d30cc929f37712767260cf38e9e7f15c010ba5
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 "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "World.h"
24 #include "ObjectMgr.h"
25 #include "Player.h"
26 #include "Item.h"
27 #include "GameObject.h"
28 #include "Opcodes.h"
29 #include "Chat.h"
30 #include "ObjectAccessor.h"
31 #include "MapManager.h"
32 #include "Language.h"
33 #include "World.h"
34 #include "GameEvent.h"
35 #include "SpellMgr.h"
36 #include "AccountMgr.h"
37 #include "GMTicketMgr.h"
38 #include "WaypointManager.h"
39 #include "Util.h"
40 #include <cctype>
41 #include <iostream>
42 #include <fstream>
43 #include <map>
44 #include "GlobalEvents.h"
46 #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
48 static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
50 LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL,
51 LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED
54 //mute player for some times
55 bool ChatHandler::HandleMuteCommand(const char* args)
57 if (!*args)
58 return false;
60 std::string name = extractPlayerNameFromLink((char*)args);
61 if(name.empty())
63 SendSysMessage(LANG_PLAYER_NOT_FOUND);
64 SetSentErrorMessage(true);
65 return false;
68 char *timetonotspeak = strtok(NULL, " ");
69 if(!timetonotspeak)
70 return false;
72 uint32 notspeaktime = (uint32) atoi(timetonotspeak);
74 uint64 guid = objmgr.GetPlayerGUIDByName(name);
75 if(!guid)
77 SendSysMessage(LANG_PLAYER_NOT_FOUND);
78 SetSentErrorMessage(true);
79 return false;
82 Player *chr = objmgr.GetPlayer(guid);
84 // must have strong lesser security level
85 if(HasLowerSecurity (chr,guid,true))
86 return false;
88 uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid);
90 time_t mutetime = time(NULL) + notspeaktime*60;
92 if (chr)
93 chr->GetSession()->m_muteTime = mutetime;
95 loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
97 if(chr)
98 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
100 std::string nameLink = playerLink(name);
102 PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime);
104 return true;
107 //unmute player
108 bool ChatHandler::HandleUnmuteCommand(const char* args)
110 if (!*args)
111 return false;
113 std::string name = extractPlayerNameFromLink((char*)args);
114 if(name.empty())
116 SendSysMessage(LANG_PLAYER_NOT_FOUND);
117 SetSentErrorMessage(true);
118 return false;
121 uint64 guid = objmgr.GetPlayerGUIDByName(name);
122 if(!guid)
124 SendSysMessage(LANG_PLAYER_NOT_FOUND);
125 SetSentErrorMessage(true);
126 return false;
129 Player *chr = objmgr.GetPlayer(guid);
131 // must have strong lesser security level
132 if(HasLowerSecurity (chr,guid,true))
133 return false;
135 uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid);
137 if (chr)
139 if(chr->CanSpeak())
141 SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
142 SetSentErrorMessage(true);
143 return false;
146 chr->GetSession()->m_muteTime = 0;
149 loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
151 if(chr)
152 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
154 std::string nameLink = playerLink(name);
156 PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str());
157 return true;
160 bool ChatHandler::HandleTargetObjectCommand(const char* args)
162 Player* pl = m_session->GetPlayer();
163 QueryResult *result;
164 GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
165 if(*args)
167 int32 id = atoi((char*)args);
168 if(id)
169 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",
170 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
171 else
173 std::string name = args;
174 WorldDatabase.escape_string(name);
175 result = WorldDatabase.PQuery(
176 "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_ "
177 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
178 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
181 else
183 std::ostringstream eventFilter;
184 eventFilter << " AND (event IS NULL ";
185 bool initString = true;
187 for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
189 if (initString)
191 eventFilter << "OR event IN (" <<*itr;
192 initString =false;
194 else
195 eventFilter << "," << *itr;
198 if (!initString)
199 eventFilter << "))";
200 else
201 eventFilter << ")";
203 result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
204 "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
205 "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 1",
206 m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
209 if (!result)
211 SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
212 return true;
215 Field *fields = result->Fetch();
216 uint32 lowguid = fields[0].GetUInt32();
217 uint32 id = fields[1].GetUInt32();
218 float x = fields[2].GetFloat();
219 float y = fields[3].GetFloat();
220 float z = fields[4].GetFloat();
221 float o = fields[5].GetFloat();
222 int mapid = fields[6].GetUInt16();
223 delete result;
225 GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id);
227 if (!goI)
229 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
230 return false;
233 GameObject* target = ObjectAccessor::GetGameObject(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
235 PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
237 if(target)
239 int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
240 if(curRespawnDelay < 0)
241 curRespawnDelay = 0;
243 std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
244 std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
246 PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
248 return true;
251 //teleport to gameobject
252 bool ChatHandler::HandleGoObjectCommand(const char* args)
254 if(!*args)
255 return false;
257 Player* _player = m_session->GetPlayer();
259 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
260 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
261 if(!cId)
262 return false;
264 int32 guid = atoi(cId);
265 if(!guid)
266 return false;
268 float x, y, z, ort;
269 int mapid;
271 // by DB guid
272 if (GameObjectData const* go_data = objmgr.GetGOData(guid))
274 x = go_data->posX;
275 y = go_data->posY;
276 z = go_data->posZ;
277 ort = go_data->orientation;
278 mapid = go_data->mapid;
280 else
282 SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
283 SetSentErrorMessage(true);
284 return false;
287 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
289 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
290 SetSentErrorMessage(true);
291 return false;
294 // stop flight if need
295 if(_player->isInFlight())
297 _player->GetMotionMaster()->MovementExpired();
298 _player->m_taxi.ClearTaxiDestinations();
300 // save only in non-flight case
301 else
302 _player->SaveRecallPosition();
304 _player->TeleportTo(mapid, x, y, z, ort);
305 return true;
308 bool ChatHandler::HandleGoTriggerCommand(const char* args)
310 Player* _player = m_session->GetPlayer();
312 if (!*args)
313 return false;
315 char *atId = strtok((char*)args, " ");
316 if (!atId)
317 return false;
319 int32 i_atId = atoi(atId);
321 if(!i_atId)
322 return false;
324 AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
325 if (!at)
327 PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
328 SetSentErrorMessage(true);
329 return false;
332 if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
334 PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
335 SetSentErrorMessage(true);
336 return false;
339 // stop flight if need
340 if(_player->isInFlight())
342 _player->GetMotionMaster()->MovementExpired();
343 _player->m_taxi.ClearTaxiDestinations();
345 // save only in non-flight case
346 else
347 _player->SaveRecallPosition();
349 _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
350 return true;
353 bool ChatHandler::HandleGoGraveyardCommand(const char* args)
355 Player* _player = m_session->GetPlayer();
357 if (!*args)
358 return false;
360 char *gyId = strtok((char*)args, " ");
361 if (!gyId)
362 return false;
364 int32 i_gyId = atoi(gyId);
366 if(!i_gyId)
367 return false;
369 WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
370 if (!gy)
372 PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
373 SetSentErrorMessage(true);
374 return false;
377 if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
379 PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
380 SetSentErrorMessage(true);
381 return false;
384 // stop flight if need
385 if(_player->isInFlight())
387 _player->GetMotionMaster()->MovementExpired();
388 _player->m_taxi.ClearTaxiDestinations();
390 // save only in non-flight case
391 else
392 _player->SaveRecallPosition();
394 _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
395 return true;
398 /** \brief Teleport the GM to the specified creature
400 * .gocreature <GUID> --> TP using creature.guid
401 * .gocreature azuregos --> TP player to the mob with this name
402 * Warning: If there is more than one mob with this name
403 * you will be teleported to the first one that is found.
404 * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry
405 * Warning: If there is more than one mob with this "id"
406 * you will be teleported to the first one that is found.
408 //teleport to creature
409 bool ChatHandler::HandleGoCreatureCommand(const char* args)
411 if(!*args)
412 return false;
413 Player* _player = m_session->GetPlayer();
415 // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
416 char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
417 if (!pParam1)
418 return false;
420 std::ostringstream whereClause;
422 // User wants to teleport to the NPC's template entry
423 if( strcmp(pParam1, "id") == 0 )
425 //sLog.outError("DEBUG: ID found");
427 // Get the "creature_template.entry"
428 // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
429 char* tail = strtok(NULL,"");
430 if(!tail)
431 return false;
432 char* cId = extractKeyFromLink(tail,"Hcreature_entry");
433 if(!cId)
434 return false;
436 int32 tEntry = atoi(cId);
437 //sLog.outError("DEBUG: ID value: %d", tEntry);
438 if(!tEntry)
439 return false;
441 whereClause << "WHERE id = '" << tEntry << "'";
443 else
445 //sLog.outError("DEBUG: ID *not found*");
447 int32 guid = atoi(pParam1);
449 // Number is invalid - maybe the user specified the mob's name
450 if(!guid)
452 std::string name = pParam1;
453 WorldDatabase.escape_string(name);
454 whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
456 else
458 whereClause << "WHERE guid = '" << guid << "'";
461 //sLog.outError("DEBUG: %s", whereClause.c_str());
463 QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
464 if (!result)
466 SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
467 SetSentErrorMessage(true);
468 return false;
470 if( result->GetRowCount() > 1 )
472 SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
475 Field *fields = result->Fetch();
476 float x = fields[0].GetFloat();
477 float y = fields[1].GetFloat();
478 float z = fields[2].GetFloat();
479 float ort = fields[3].GetFloat();
480 int mapid = fields[4].GetUInt16();
482 delete result;
484 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
486 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
487 SetSentErrorMessage(true);
488 return false;
491 // stop flight if need
492 if(_player->isInFlight())
494 _player->GetMotionMaster()->MovementExpired();
495 _player->m_taxi.ClearTaxiDestinations();
497 // save only in non-flight case
498 else
499 _player->SaveRecallPosition();
501 _player->TeleportTo(mapid, x, y, z, ort);
502 return true;
505 bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
507 uint64 guid = m_session->GetPlayer()->GetSelection();
509 if (guid == 0)
511 SendSysMessage(LANG_NO_SELECTION);
512 SetSentErrorMessage(true);
513 return false;
516 PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
517 return true;
520 bool ChatHandler::HandleLookupFactionCommand(const char* args)
522 if (!*args)
523 return false;
525 // Can be NULL at console call
526 Player *target = getSelectedPlayer ();
528 std::string namepart = args;
529 std::wstring wnamepart;
531 if (!Utf8toWStr (namepart,wnamepart))
532 return false;
534 // converting string that we try to find to lower case
535 wstrToLower (wnamepart);
537 uint32 counter = 0; // Counter for figure out that we found smth.
539 for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
541 FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
542 if (factionEntry)
544 FactionState const* repState = NULL;
545 if(target)
547 FactionStateList::const_iterator repItr = target->m_factions.find (factionEntry->reputationListID);
548 if(repItr != target->m_factions.end())
549 repState = &repItr->second;
553 int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale();
554 std::string name = factionEntry->name[loc];
555 if(name.empty())
556 continue;
558 if (!Utf8FitTo(name, wnamepart))
560 loc = 0;
561 for(; loc < MAX_LOCALE; ++loc)
563 if(m_session && loc==m_session->GetSessionDbcLocale())
564 continue;
566 name = factionEntry->name[loc];
567 if(name.empty())
568 continue;
570 if (Utf8FitTo(name, wnamepart))
571 break;
575 if(loc < MAX_LOCALE)
577 // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
578 // or "id - [faction] [no reputation]" format
579 std::ostringstream ss;
580 if (m_session)
581 ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
582 else
583 ss << id << " - " << name << " " << localeNames[loc];
585 if (repState) // and then target!=NULL also
587 ReputationRank rank = target->GetReputationRank(factionEntry);
588 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
590 ss << " " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
592 if(repState->Flags & FACTION_FLAG_VISIBLE)
593 ss << GetMangosString(LANG_FACTION_VISIBLE);
594 if(repState->Flags & FACTION_FLAG_AT_WAR)
595 ss << GetMangosString(LANG_FACTION_ATWAR);
596 if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
597 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
598 if(repState->Flags & FACTION_FLAG_HIDDEN)
599 ss << GetMangosString(LANG_FACTION_HIDDEN);
600 if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
601 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
602 if(repState->Flags & FACTION_FLAG_INACTIVE)
603 ss << GetMangosString(LANG_FACTION_INACTIVE);
605 else
606 ss << GetMangosString(LANG_FACTION_NOREPUTATION);
608 SendSysMessage(ss.str().c_str());
609 counter++;
614 if (counter == 0) // if counter == 0 then we found nth
615 SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
616 return true;
619 bool ChatHandler::HandleModifyRepCommand(const char * args)
621 if (!*args) return false;
623 Player* target = NULL;
624 target = getSelectedPlayer();
626 if(!target)
628 SendSysMessage(LANG_PLAYER_NOT_FOUND);
629 SetSentErrorMessage(true);
630 return false;
633 // check online security
634 if (HasLowerSecurity(target, 0))
635 return false;
637 char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
638 if(!factionTxt)
639 return false;
641 uint32 factionId = atoi(factionTxt);
643 int32 amount = 0;
644 char *rankTxt = strtok(NULL, " ");
645 if (!factionTxt || !rankTxt)
646 return false;
648 amount = atoi(rankTxt);
649 if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
651 std::string rankStr = rankTxt;
652 std::wstring wrankStr;
653 if(!Utf8toWStr(rankStr,wrankStr))
654 return false;
655 wstrToLower( wrankStr );
657 int r = 0;
658 amount = -42000;
659 for (; r < MAX_REPUTATION_RANK; ++r)
661 std::string rank = GetMangosString(ReputationRankStrIndex[r]);
662 if(rank.empty())
663 continue;
665 std::wstring wrank;
666 if(!Utf8toWStr(rank,wrank))
667 continue;
669 wstrToLower(wrank);
671 if(wrank.substr(0,wrankStr.size())==wrankStr)
673 char *deltaTxt = strtok(NULL, " ");
674 if (deltaTxt)
676 int32 delta = atoi(deltaTxt);
677 if ((delta < 0) || (delta > Player::ReputationRank_Length[r] -1))
679 PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (Player::ReputationRank_Length[r]-1));
680 SetSentErrorMessage(true);
681 return false;
683 amount += delta;
685 break;
687 amount += Player::ReputationRank_Length[r];
689 if (r >= MAX_REPUTATION_RANK)
691 PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
692 SetSentErrorMessage(true);
693 return false;
697 FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
699 if (!factionEntry)
701 PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
702 SetSentErrorMessage(true);
703 return false;
706 if (factionEntry->reputationListID < 0)
708 PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[m_session->GetSessionDbcLocale()], factionId);
709 SetSentErrorMessage(true);
710 return false;
713 target->SetFactionReputation(factionEntry,amount);
714 PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, GetNameLink(target).c_str(), target->GetReputation(factionId));
715 return true;
718 bool ChatHandler::HandleNameCommand(const char* /*args*/)
720 /* Temp. disabled
721 if(!*args)
722 return false;
724 if(strlen((char*)args)>75)
726 PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
727 return true;
730 for (uint8 i = 0; i < strlen(args); i++)
732 if(!isalpha(args[i]) && args[i]!=' ')
734 SendSysMessage(LANG_CHARS_ONLY);
735 return false;
739 uint64 guid;
740 guid = m_session->GetPlayer()->GetSelection();
741 if (guid == 0)
743 SendSysMessage(LANG_NO_SELECTION);
744 return true;
747 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
749 if(!pCreature)
751 SendSysMessage(LANG_SELECT_CREATURE);
752 return true;
755 pCreature->SetName(args);
756 uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName());
757 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
759 pCreature->SaveToDB();
762 return true;
765 bool ChatHandler::HandleSubNameCommand(const char* /*args*/)
767 /* Temp. disabled
769 if(!*args)
770 args = "";
772 if(strlen((char*)args)>75)
775 PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
776 return true;
779 for (uint8 i = 0; i < strlen(args); i++)
781 if(!isalpha(args[i]) && args[i]!=' ')
783 SendSysMessage(LANG_CHARS_ONLY);
784 return false;
787 uint64 guid;
788 guid = m_session->GetPlayer()->GetSelection();
789 if (guid == 0)
791 SendSysMessage(LANG_NO_SELECTION);
792 return true;
795 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
797 if(!pCreature)
799 SendSysMessage(LANG_SELECT_CREATURE);
800 return true;
803 uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
804 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
806 pCreature->SaveToDB();
808 return true;
811 //move item to other slot
812 bool ChatHandler::HandleItemMoveCommand(const char* args)
814 if(!*args)
815 return false;
816 uint8 srcslot, dstslot;
818 char* pParam1 = strtok((char*)args, " ");
819 if (!pParam1)
820 return false;
822 char* pParam2 = strtok(NULL, " ");
823 if (!pParam2)
824 return false;
826 srcslot = (uint8)atoi(pParam1);
827 dstslot = (uint8)atoi(pParam2);
829 if(srcslot==dstslot)
830 return true;
832 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot))
833 return false;
835 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot))
836 return false;
838 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
839 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
841 m_session->GetPlayer()->SwapItem( src, dst );
843 return true;
846 //add spawn of creature
847 bool ChatHandler::HandleNpcAddCommand(const char* args)
849 if(!*args)
850 return false;
851 char* charID = extractKeyFromLink((char*)args,"Hcreature_entry");
852 if(!charID)
853 return false;
855 char* team = strtok(NULL, " ");
856 int32 teamval = 0;
857 if (team) { teamval = atoi(team); }
858 if (teamval < 0) { teamval = 0; }
860 uint32 id = atoi(charID);
862 Player *chr = m_session->GetPlayer();
863 float x = chr->GetPositionX();
864 float y = chr->GetPositionY();
865 float z = chr->GetPositionZ();
866 float o = chr->GetOrientation();
867 Map *map = chr->GetMap();
869 Creature* pCreature = new Creature;
870 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, (uint32)teamval))
872 delete pCreature;
873 return false;
876 pCreature->Relocate(x,y,z,o);
878 if(!pCreature->IsPositionValid())
880 sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
881 delete pCreature;
882 return false;
885 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
887 uint32 db_guid = pCreature->GetDBTableGUIDLow();
889 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
890 pCreature->LoadFromDB(db_guid, map);
892 map->Add(pCreature);
893 objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid));
894 return true;
897 bool ChatHandler::HandleNpcDeleteCommand(const char* args)
899 Creature* unit = NULL;
901 if(*args)
903 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
904 char* cId = extractKeyFromLink((char*)args,"Hcreature");
905 if(!cId)
906 return false;
908 uint32 lowguid = atoi(cId);
909 if(!lowguid)
910 return false;
912 if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid))
913 unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
915 else
916 unit = getSelectedCreature();
918 if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle())
920 SendSysMessage(LANG_SELECT_CREATURE);
921 SetSentErrorMessage(true);
922 return false;
925 // Delete the creature
926 unit->CombatStop();
927 unit->DeleteFromDB();
928 unit->CleanupsBeforeDelete();
929 unit->AddObjectToRemoveList();
931 SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
933 return true;
936 //delete object by selection or guid
937 bool ChatHandler::HandleDelObjectCommand(const char* args)
939 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
940 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
941 if(!cId)
942 return false;
944 uint32 lowguid = atoi(cId);
945 if(!lowguid)
946 return false;
948 GameObject* obj = NULL;
950 // by DB guid
951 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
952 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
954 if(!obj)
956 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
957 SetSentErrorMessage(true);
958 return false;
961 uint64 owner_guid = obj->GetOwnerGUID();
962 if(owner_guid)
964 Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
965 if(!owner && !IS_PLAYER_GUID(owner_guid))
967 PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
968 SetSentErrorMessage(true);
969 return false;
972 owner->RemoveGameObject(obj,false);
975 obj->SetRespawnTime(0); // not save respawn time
976 obj->Delete();
977 obj->DeleteFromDB();
979 PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
981 return true;
984 //turn selected object
985 bool ChatHandler::HandleTurnObjectCommand(const char* args)
987 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
988 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
989 if(!cId)
990 return false;
992 uint32 lowguid = atoi(cId);
993 if(!lowguid)
994 return false;
996 GameObject* obj = NULL;
998 // by DB guid
999 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1000 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1002 if(!obj)
1004 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1005 SetSentErrorMessage(true);
1006 return false;
1009 char* po = strtok(NULL, " ");
1010 float o;
1012 if (po)
1014 o = (float)atof(po);
1016 else
1018 Player *chr = m_session->GetPlayer();
1019 o = chr->GetOrientation();
1022 float rot2 = sin(o/2);
1023 float rot3 = cos(o/2);
1025 Map* map = obj->GetMap();
1026 map->Remove(obj,false);
1028 obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
1030 obj->SetFloatValue(GAMEOBJECT_FACING, o);
1031 obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2);
1032 obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3);
1034 map->Add(obj);
1036 obj->SaveToDB();
1037 obj->Refresh();
1039 PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o);
1041 return true;
1044 //move selected creature
1045 bool ChatHandler::HandleNpcMoveCommand(const char* args)
1047 uint32 lowguid = 0;
1049 Creature* pCreature = getSelectedCreature();
1051 if(!pCreature)
1053 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1054 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1055 if(!cId)
1056 return false;
1058 uint32 lowguid = atoi(cId);
1060 /* FIXME: impossibel without entry
1061 if(lowguid)
1062 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1065 // Attempting creature load from DB data
1066 if(!pCreature)
1068 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1069 if(!data)
1071 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1072 SetSentErrorMessage(true);
1073 return false;
1076 uint32 map_id = data->mapid;
1078 if(m_session->GetPlayer()->GetMapId()!=map_id)
1080 PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1081 SetSentErrorMessage(true);
1082 return false;
1085 else
1087 lowguid = pCreature->GetDBTableGUIDLow();
1090 else
1092 lowguid = pCreature->GetDBTableGUIDLow();
1095 float x = m_session->GetPlayer()->GetPositionX();
1096 float y = m_session->GetPlayer()->GetPositionY();
1097 float z = m_session->GetPlayer()->GetPositionZ();
1098 float o = m_session->GetPlayer()->GetOrientation();
1100 if (pCreature)
1102 if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1104 const_cast<CreatureData*>(data)->posX = x;
1105 const_cast<CreatureData*>(data)->posY = y;
1106 const_cast<CreatureData*>(data)->posZ = z;
1107 const_cast<CreatureData*>(data)->orientation = o;
1109 pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
1110 pCreature->GetMotionMaster()->Initialize();
1111 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1113 pCreature->setDeathState(JUST_DIED);
1114 pCreature->Respawn();
1118 WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1119 PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1120 return true;
1123 //move selected object
1124 bool ChatHandler::HandleMoveObjectCommand(const char* args)
1126 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
1127 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1128 if(!cId)
1129 return false;
1131 uint32 lowguid = atoi(cId);
1132 if(!lowguid)
1133 return false;
1135 GameObject* obj = NULL;
1137 // by DB guid
1138 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1139 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1141 if(!obj)
1143 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1144 SetSentErrorMessage(true);
1145 return false;
1148 char* px = strtok(NULL, " ");
1149 char* py = strtok(NULL, " ");
1150 char* pz = strtok(NULL, " ");
1152 if (!px)
1154 Player *chr = m_session->GetPlayer();
1156 Map* map = obj->GetMap();
1157 map->Remove(obj,false);
1159 obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
1160 obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX());
1161 obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY());
1162 obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ());
1164 map->Add(obj);
1166 else
1168 if(!py || !pz)
1169 return false;
1171 float x = (float)atof(px);
1172 float y = (float)atof(py);
1173 float z = (float)atof(pz);
1175 if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
1177 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
1178 SetSentErrorMessage(true);
1179 return false;
1182 Map* map = obj->GetMap();
1183 map->Remove(obj,false);
1185 obj->Relocate(x, y, z, obj->GetOrientation());
1186 obj->SetFloatValue(GAMEOBJECT_POS_X, x);
1187 obj->SetFloatValue(GAMEOBJECT_POS_Y, y);
1188 obj->SetFloatValue(GAMEOBJECT_POS_Z, z);
1190 map->Add(obj);
1193 obj->SaveToDB();
1194 obj->Refresh();
1196 PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow());
1198 return true;
1201 //demorph player or unit
1202 bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
1204 Unit *target = getSelectedUnit();
1205 if(!target)
1206 target = m_session->GetPlayer();
1209 // check online security
1210 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
1211 return false;
1213 target->DeMorph();
1215 return true;
1218 //add item in vendorlist
1219 bool ChatHandler::HandleAddVendorItemCommand(const char* args)
1221 if (!*args)
1222 return false;
1224 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1225 if (!pitem)
1227 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1228 SetSentErrorMessage(true);
1229 return false;
1232 uint32 itemId = atol(pitem);
1234 char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
1235 uint32 maxcount = 0;
1236 if (fmaxcount)
1237 maxcount = atol(fmaxcount);
1239 char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
1240 uint32 incrtime = 0;
1241 if (fincrtime)
1242 incrtime = atol(fincrtime);
1244 char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
1245 uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1247 Creature* vendor = getSelectedCreature();
1249 uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1251 if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1253 SetSentErrorMessage(true);
1254 return false;
1257 objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1259 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1261 PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1262 return true;
1265 //del item from vendor list
1266 bool ChatHandler::HandleDelVendorItemCommand(const char* args)
1268 if (!*args)
1269 return false;
1271 Creature* vendor = getSelectedCreature();
1272 if (!vendor || !vendor->isVendor())
1274 SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1275 SetSentErrorMessage(true);
1276 return false;
1279 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1280 if (!pitem)
1282 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1283 SetSentErrorMessage(true);
1284 return false;
1286 uint32 itemId = atol(pitem);
1288 if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1290 PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1291 SetSentErrorMessage(true);
1292 return false;
1295 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1297 PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1298 return true;
1301 //add move for creature
1302 bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
1304 if(!*args)
1305 return false;
1307 char* guid_str = strtok((char*)args, " ");
1308 char* wait_str = strtok((char*)NULL, " ");
1310 uint32 lowguid = atoi((char*)guid_str);
1312 Creature* pCreature = NULL;
1314 /* FIXME: impossible without entry
1315 if(lowguid)
1316 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1319 // attempt check creature existence by DB data
1320 if(!pCreature)
1322 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1323 if(!data)
1325 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1326 SetSentErrorMessage(true);
1327 return false;
1330 else
1332 // obtain real GUID for DB operations
1333 lowguid = pCreature->GetDBTableGUIDLow();
1336 int wait = wait_str ? atoi(wait_str) : 0;
1338 if(wait < 0)
1339 wait = 0;
1341 Player* player = m_session->GetPlayer();
1343 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1345 // update movement type
1346 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1347 if(pCreature)
1349 pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1350 pCreature->GetMotionMaster()->Initialize();
1351 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1353 pCreature->setDeathState(JUST_DIED);
1354 pCreature->Respawn();
1356 pCreature->SaveToDB();
1359 SendSysMessage(LANG_WAYPOINT_ADDED);
1361 return true;
1365 * Set the movement type for an NPC.<br/>
1366 * <br/>
1367 * Valid movement types are:
1368 * <ul>
1369 * <li> stay - NPC wont move </li>
1370 * <li> random - NPC will move randomly according to the spawndist </li>
1371 * <li> way - NPC will move with given waypoints set </li>
1372 * </ul>
1373 * additional parameter: NODEL - so no waypoints are deleted, if you
1374 * change the movement type
1376 bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
1378 if(!*args)
1379 return false;
1381 // 3 arguments:
1382 // GUID (optional - you can also select the creature)
1383 // stay|random|way (determines the kind of movement)
1384 // NODEL (optional - tells the system NOT to delete any waypoints)
1385 // this is very handy if you want to do waypoints, that are
1386 // later switched on/off according to special events (like escort
1387 // quests, etc)
1388 char* guid_str = strtok((char*)args, " ");
1389 char* type_str = strtok((char*)NULL, " ");
1390 char* dontdel_str = strtok((char*)NULL, " ");
1392 bool doNotDelete = false;
1394 if(!guid_str)
1395 return false;
1397 uint32 lowguid = 0;
1398 Creature* pCreature = NULL;
1400 if( dontdel_str )
1402 //sLog.outError("DEBUG: All 3 params are set");
1404 // All 3 params are set
1405 // GUID
1406 // type
1407 // doNotDEL
1408 if( stricmp( dontdel_str, "NODEL" ) == 0 )
1410 //sLog.outError("DEBUG: doNotDelete = true;");
1411 doNotDelete = true;
1414 else
1416 // Only 2 params - but maybe NODEL is set
1417 if( type_str )
1419 sLog.outError("DEBUG: Only 2 params ");
1420 if( stricmp( type_str, "NODEL" ) == 0 )
1422 //sLog.outError("DEBUG: type_str, NODEL ");
1423 doNotDelete = true;
1424 type_str = NULL;
1429 if(!type_str) // case .setmovetype $move_type (with selected creature)
1431 type_str = guid_str;
1432 pCreature = getSelectedCreature();
1433 if(!pCreature || pCreature->isPet())
1434 return false;
1435 lowguid = pCreature->GetDBTableGUIDLow();
1437 else // case .setmovetype #creature_guid $move_type (with selected creature)
1439 lowguid = atoi((char*)guid_str);
1441 /* impossible without entry
1442 if(lowguid)
1443 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1446 // attempt check creature existence by DB data
1447 if(!pCreature)
1449 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1450 if(!data)
1452 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1453 SetSentErrorMessage(true);
1454 return false;
1457 else
1459 lowguid = pCreature->GetDBTableGUIDLow();
1463 // now lowguid is low guid really existed creature
1464 // and pCreature point (maybe) to this creature or NULL
1466 MovementGeneratorType move_type;
1468 std::string type = type_str;
1470 if(type == "stay")
1471 move_type = IDLE_MOTION_TYPE;
1472 else if(type == "random")
1473 move_type = RANDOM_MOTION_TYPE;
1474 else if(type == "way")
1475 move_type = WAYPOINT_MOTION_TYPE;
1476 else
1477 return false;
1479 // update movement type
1480 if(doNotDelete == false)
1481 WaypointMgr.DeletePath(lowguid);
1483 if(pCreature)
1485 pCreature->SetDefaultMovementType(move_type);
1486 pCreature->GetMotionMaster()->Initialize();
1487 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1489 pCreature->setDeathState(JUST_DIED);
1490 pCreature->Respawn();
1492 pCreature->SaveToDB();
1494 if( doNotDelete == false )
1496 PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1498 else
1500 PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1503 return true;
1504 } // HandleNpcSetMoveTypeCommand
1506 //change level of creature or pet
1507 bool ChatHandler::HandleChangeLevelCommand(const char* args)
1509 if (!*args)
1510 return false;
1512 uint8 lvl = (uint8) atoi((char*)args);
1513 if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3)
1515 SendSysMessage(LANG_BAD_VALUE);
1516 SetSentErrorMessage(true);
1517 return false;
1520 Creature* pCreature = getSelectedCreature();
1521 if(!pCreature)
1523 SendSysMessage(LANG_SELECT_CREATURE);
1524 SetSentErrorMessage(true);
1525 return false;
1528 if(pCreature->isPet())
1530 ((Pet*)pCreature)->GivePetLevel(lvl);
1532 else
1534 pCreature->SetMaxHealth( 100 + 30*lvl);
1535 pCreature->SetHealth( 100 + 30*lvl);
1536 pCreature->SetLevel( lvl);
1537 pCreature->SaveToDB();
1540 return true;
1543 //set npcflag of creature
1544 bool ChatHandler::HandleNpcFlagCommand(const char* args)
1546 if (!*args)
1547 return false;
1549 uint32 npcFlags = (uint32) atoi((char*)args);
1551 Creature* pCreature = getSelectedCreature();
1553 if(!pCreature)
1555 SendSysMessage(LANG_SELECT_CREATURE);
1556 SetSentErrorMessage(true);
1557 return false;
1560 pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1562 WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1564 SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1566 return true;
1569 //set model of creature
1570 bool ChatHandler::HandleNpcSetModelCommand(const char* args)
1572 if (!*args)
1573 return false;
1575 uint32 displayId = (uint32) atoi((char*)args);
1577 Creature *pCreature = getSelectedCreature();
1579 if(!pCreature || pCreature->isPet())
1581 SendSysMessage(LANG_SELECT_CREATURE);
1582 SetSentErrorMessage(true);
1583 return false;
1586 pCreature->SetDisplayId(displayId);
1587 pCreature->SetNativeDisplayId(displayId);
1589 pCreature->SaveToDB();
1591 return true;
1594 //morph creature or player
1595 bool ChatHandler::HandleMorphCommand(const char* args)
1597 if (!*args)
1598 return false;
1600 uint16 display_id = (uint16)atoi((char*)args);
1602 Unit *target = getSelectedUnit();
1603 if(!target)
1604 target = m_session->GetPlayer();
1606 // check online security
1607 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
1608 return false;
1610 target->SetDisplayId(display_id);
1612 return true;
1615 //set faction of creature
1616 bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
1618 if (!*args)
1619 return false;
1621 uint32 factionId = (uint32) atoi((char*)args);
1623 if (!sFactionTemplateStore.LookupEntry(factionId))
1625 PSendSysMessage(LANG_WRONG_FACTION, factionId);
1626 SetSentErrorMessage(true);
1627 return false;
1630 Creature* pCreature = getSelectedCreature();
1632 if(!pCreature)
1634 SendSysMessage(LANG_SELECT_CREATURE);
1635 SetSentErrorMessage(true);
1636 return false;
1639 pCreature->setFaction(factionId);
1641 // faction is set in creature_template - not inside creature
1643 // update in memory
1644 if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1646 const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1647 const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1650 // and DB
1651 WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1653 return true;
1656 //kick player
1657 bool ChatHandler::HandleKickPlayerCommand(const char *args)
1659 if (!args)
1661 Player* player = getSelectedPlayer();
1663 if(!player)
1665 SendSysMessage(LANG_NO_CHAR_SELECTED);
1666 SetSentErrorMessage(true);
1667 return false;
1670 if(player==m_session->GetPlayer())
1672 SendSysMessage(LANG_COMMAND_KICKSELF);
1673 SetSentErrorMessage(true);
1674 return false;
1677 // check online security
1678 if (HasLowerSecurity(player, 0))
1679 return false;
1681 player->GetSession()->KickPlayer();
1683 else
1685 std::string name = extractPlayerNameFromLink((char*)args);
1686 if(name.empty())
1688 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1689 SetSentErrorMessage(true);
1690 return false;
1693 if(m_session && name==m_session->GetPlayer()->GetName())
1695 SendSysMessage(LANG_COMMAND_KICKSELF);
1696 SetSentErrorMessage(true);
1697 return false;
1700 // check online security
1701 Player* player = ObjectAccessor::Instance().FindPlayerByName(name.c_str());
1702 if (player && HasLowerSecurity(player, 0))
1703 return false;
1705 std::string nameLink = playerLink(name);
1707 if(sWorld.KickPlayer(name))
1709 PSendSysMessage(LANG_COMMAND_KICKMESSAGE,nameLink.c_str());
1711 else
1712 PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,nameLink.c_str());
1715 return true;
1718 //set temporary phase mask for player
1719 bool ChatHandler::HandleModifyPhaseCommand(const char* args)
1721 if (!*args)
1722 return false;
1724 uint32 phasemask = (uint32)atoi((char*)args);
1726 Unit *target = getSelectedUnit();
1727 if(!target)
1728 target = m_session->GetPlayer();
1730 // check online security
1731 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
1732 return false;
1734 target->SetPhaseMask(phasemask,true);
1736 return true;
1739 //show info of player
1740 bool ChatHandler::HandlePInfoCommand(const char* args)
1742 Player* target = NULL;
1743 uint64 targetGUID = 0;
1745 char* px = strtok((char*)args, " ");
1746 char* py = NULL;
1748 std::string name;
1750 if (px)
1752 name = extractPlayerNameFromLink(px);
1753 if(name.empty())
1755 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1756 SetSentErrorMessage(true);
1757 return false;
1760 target = objmgr.GetPlayer(name.c_str());
1761 if (target)
1762 py = strtok(NULL, " ");
1763 else
1765 targetGUID = objmgr.GetPlayerGUIDByName(name);
1766 if(targetGUID)
1767 py = strtok(NULL, " ");
1768 else
1769 py = px;
1773 if(!target && !targetGUID)
1775 target = getSelectedPlayer();
1778 if(!target && !targetGUID)
1780 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1781 SetSentErrorMessage(true);
1782 return false;
1785 uint32 accId = 0;
1786 uint32 money = 0;
1787 uint32 total_player_time = 0;
1788 uint32 level = 0;
1789 uint32 latency = 0;
1791 // get additional information from Player object
1792 if(target)
1794 // check online security
1795 if (HasLowerSecurity(target, 0))
1796 return false;
1798 targetGUID = target->GetGUID();
1799 name = target->GetName(); // re-read for case getSelectedPlayer() target
1800 accId = target->GetSession()->GetAccountId();
1801 money = target->GetMoney();
1802 total_player_time = target->GetTotalPlayedTime();
1803 level = target->getLevel();
1804 latency = target->GetSession()->GetLatency();
1806 // get additional information from DB
1807 else
1809 // check offline security
1810 if (HasLowerSecurity(NULL, targetGUID))
1811 return false;
1813 // 0
1814 QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID));
1815 if (!result)
1817 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1818 SetSentErrorMessage(true);
1819 return false;
1821 Field *fields = result->Fetch();
1822 total_player_time = fields[0].GetUInt32();
1823 delete result;
1825 Tokens data;
1826 if (!Player::LoadValuesArrayFromDB(data,targetGUID))
1828 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1829 SetSentErrorMessage(true);
1830 return false;
1833 money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE);
1834 level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL);
1836 accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
1839 std::string username = GetMangosString(LANG_ERROR);
1840 std::string last_ip = GetMangosString(LANG_ERROR);
1841 uint32 security = 0;
1842 std::string last_login = GetMangosString(LANG_ERROR);
1844 QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
1845 if(result)
1847 Field* fields = result->Fetch();
1848 username = fields[0].GetCppString();
1849 security = fields[1].GetUInt32();
1851 if(!m_session || m_session->GetSecurity() >= security)
1853 last_ip = fields[2].GetCppString();
1854 last_login = fields[3].GetCppString();
1856 else
1858 last_ip = "-";
1859 last_login = "-";
1862 delete result;
1865 std::string nameLink = playerLink(name);
1867 PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetMangosString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency);
1869 std::string timeStr = secsToTimeString(total_player_time,true,true);
1870 uint32 gold = money /GOLD;
1871 uint32 silv = (money % GOLD) / SILVER;
1872 uint32 copp = (money % GOLD) % SILVER;
1873 PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp );
1875 if ( py && strncmp(py, "rep", 3) == 0 )
1877 if(!target)
1879 // rep option not implemented for offline case
1880 SendSysMessage(LANG_PINFO_NO_REP);
1881 SetSentErrorMessage(true);
1882 return false;
1885 char* FactionName;
1886 for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr)
1888 FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
1889 if (factionEntry)
1890 FactionName = factionEntry->name[m_session->GetSessionDbcLocale()];
1891 else
1892 FactionName = "#Not found#";
1893 ReputationRank rank = target->GetReputationRank(factionEntry);
1894 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
1895 std::ostringstream ss;
1896 ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << FactionName << "]|h|r " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
1898 if(itr->second.Flags & FACTION_FLAG_VISIBLE)
1899 ss << GetMangosString(LANG_FACTION_VISIBLE);
1900 if(itr->second.Flags & FACTION_FLAG_AT_WAR)
1901 ss << GetMangosString(LANG_FACTION_ATWAR);
1902 if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
1903 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
1904 if(itr->second.Flags & FACTION_FLAG_HIDDEN)
1905 ss << GetMangosString(LANG_FACTION_HIDDEN);
1906 if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
1907 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
1908 if(itr->second.Flags & FACTION_FLAG_INACTIVE)
1909 ss << GetMangosString(LANG_FACTION_INACTIVE);
1911 SendSysMessage(ss.str().c_str());
1914 return true;
1917 //show tickets
1918 void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
1920 std::string name;
1921 if(!objmgr.GetPlayerNameByGUID(guid,name))
1922 name = GetMangosString(LANG_UNKNOWN);
1924 std::string nameLink = playerLink(name);
1926 PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(),time,text);
1929 //ticket commands
1930 bool ChatHandler::HandleTicketCommand(const char* args)
1932 char* px = strtok((char*)args, " ");
1934 // ticket<end>
1935 if (!px)
1937 if(!m_session)
1939 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1940 SetSentErrorMessage(true);
1941 return false;
1944 size_t count = ticketmgr.GetTicketCount();
1946 bool accept = m_session->GetPlayer()->isAcceptTickets();
1948 PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
1949 return true;
1952 // ticket on
1953 if(strncmp(px,"on",3) == 0)
1955 if(!m_session)
1957 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1958 SetSentErrorMessage(true);
1959 return false;
1962 m_session->GetPlayer()->SetAcceptTicket(true);
1963 SendSysMessage(LANG_COMMAND_TICKETON);
1964 return true;
1967 // ticket off
1968 if(strncmp(px,"off",4) == 0)
1970 if(!m_session)
1972 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1973 SetSentErrorMessage(true);
1974 return false;
1977 m_session->GetPlayer()->SetAcceptTicket(false);
1978 SendSysMessage(LANG_COMMAND_TICKETOFF);
1979 return true;
1982 // ticket #num
1983 int num = atoi(px);
1984 if(num > 0)
1986 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
1988 if(!result)
1990 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
1991 SetSentErrorMessage(true);
1992 return false;
1995 Field* fields = result->Fetch();
1997 uint32 guid = fields[0].GetUInt32();
1998 char const* text = fields[1].GetString();
1999 char const* time = fields[2].GetString();
2001 ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
2002 delete result;
2003 return true;
2006 std::string name = extractPlayerNameFromLink(px);
2007 if(name.empty())
2009 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2010 SetSentErrorMessage(true);
2011 return false;
2014 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2016 if(!guid)
2017 return false;
2019 // ticket $char_name
2020 GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(guid));
2021 if(!ticket)
2022 return false;
2024 std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
2026 ShowTicket(guid, ticket->GetText(), time.c_str());
2028 return true;
2031 //dell all tickets
2032 bool ChatHandler::HandleDelTicketCommand(const char *args)
2034 char* px = strtok((char*)args, " ");
2035 if (!px)
2036 return false;
2038 // delticket all
2039 if(strncmp(px,"all",4) == 0)
2041 ticketmgr.DeleteAll();
2042 SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2043 return true;
2046 int num = (uint32)atoi(px);
2048 // delticket #num
2049 if(num > 0)
2051 QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2052 if(!result)
2054 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2055 SetSentErrorMessage(true);
2056 return false;
2058 Field* fields = result->Fetch();
2059 uint32 guid = fields[0].GetUInt32();
2060 delete result;
2062 ticketmgr.Delete(guid);
2064 //notify player
2065 if(Player* pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)))
2067 pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
2068 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str());
2070 else
2071 PSendSysMessage(LANG_COMMAND_TICKETDEL);
2073 return true;
2076 std::string name = extractPlayerNameFromLink(px);
2077 if(name.empty())
2079 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2080 SetSentErrorMessage(true);
2081 return false;
2084 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2086 if(!guid)
2087 return false;
2089 // delticket $char_name
2090 ticketmgr.Delete(GUID_LOPART(guid));
2092 // notify players about ticket deleting
2093 if(Player* sender = objmgr.GetPlayer(guid))
2094 sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2096 std::string nameLink = playerLink(name);
2098 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,nameLink.c_str());
2099 return true;
2102 //set spawn dist of creature
2103 bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
2105 if(!*args)
2106 return false;
2108 float option = atof((char*)args);
2109 if (option < 0.0f)
2111 SendSysMessage(LANG_BAD_VALUE);
2112 return false;
2115 MovementGeneratorType mtype = IDLE_MOTION_TYPE;
2116 if (option >0.0f)
2117 mtype = RANDOM_MOTION_TYPE;
2119 Creature *pCreature = getSelectedCreature();
2120 uint32 u_guidlow = 0;
2122 if (pCreature)
2123 u_guidlow = pCreature->GetDBTableGUIDLow();
2124 else
2125 return false;
2127 pCreature->SetRespawnRadius((float)option);
2128 pCreature->SetDefaultMovementType(mtype);
2129 pCreature->GetMotionMaster()->Initialize();
2130 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
2132 pCreature->setDeathState(JUST_DIED);
2133 pCreature->Respawn();
2136 WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
2137 PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
2138 return true;
2141 bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
2143 if(!*args)
2144 return false;
2146 char* stime = strtok((char*)args, " ");
2148 if (!stime)
2149 return false;
2151 int i_stime = atoi((char*)stime);
2153 if (i_stime < 0)
2155 SendSysMessage(LANG_BAD_VALUE);
2156 SetSentErrorMessage(true);
2157 return false;
2160 Creature *pCreature = getSelectedCreature();
2161 uint32 u_guidlow = 0;
2163 if (pCreature)
2164 u_guidlow = pCreature->GetDBTableGUIDLow();
2165 else
2166 return false;
2168 WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
2169 pCreature->SetRespawnDelay((uint32)i_stime);
2170 PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
2172 return true;
2176 * Add a waypoint to a creature.
2178 * The user can either select an npc or provide its GUID.
2180 * The user can even select a visual waypoint - then the new waypoint
2181 * is placed *after* the selected one - this makes insertion of new
2182 * waypoints possible.
2184 * eg:
2185 * .wp add 12345
2186 * -> adds a waypoint to the npc with the GUID 12345
2188 * .wp add
2189 * -> adds a waypoint to the currently selected creature
2192 * @param args if the user did not provide a GUID, it is NULL
2194 * @return true - command did succeed, false - something went wrong
2196 bool ChatHandler::HandleWpAddCommand(const char* args)
2198 sLog.outDebug("DEBUG: HandleWpAddCommand");
2200 // optional
2201 char* guid_str = NULL;
2203 if(*args)
2205 guid_str = strtok((char*)args, " ");
2208 uint32 lowguid = 0;
2209 uint32 point = 0;
2210 Creature* target = getSelectedCreature();
2211 // Did player provide a GUID?
2212 if (!guid_str)
2214 sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2216 // No GUID provided
2217 // -> Player must have selected a creature
2219 if(!target || target->isPet())
2221 SendSysMessage(LANG_SELECT_CREATURE);
2222 SetSentErrorMessage(true);
2223 return false;
2225 if (target->GetEntry() == VISUAL_WAYPOINT )
2227 sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2229 QueryResult *result =
2230 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2231 target->GetGUIDLow() );
2232 if(!result)
2234 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2235 // User selected a visual spawnpoint -> get the NPC
2236 // Select NPC GUID
2237 // Since we compare float values, we have to deal with
2238 // some difficulties.
2239 // Here we search for all waypoints that only differ in one from 1 thousand
2240 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2241 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2242 const char* maxDIFF = "0.01";
2243 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 )",
2244 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2245 if(!result)
2247 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2248 SetSentErrorMessage(true);
2249 return false;
2254 Field *fields = result->Fetch();
2255 lowguid = fields[0].GetUInt32();
2256 point = fields[1].GetUInt32();
2257 }while( result->NextRow() );
2258 delete result;
2260 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2261 if(!data)
2263 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2264 SetSentErrorMessage(true);
2265 return false;
2268 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2269 if(!target)
2271 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2272 SetSentErrorMessage(true);
2273 return false;
2276 else
2278 lowguid = target->GetDBTableGUIDLow();
2281 else
2283 sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2285 // GUID provided
2286 // Warn if player also selected a creature
2287 // -> Creature selection is ignored <-
2288 if(target)
2290 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2292 lowguid = atoi((char*)guid_str);
2294 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2295 if(!data)
2297 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2298 SetSentErrorMessage(true);
2299 return false;
2302 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2303 if(!target || target->isPet())
2305 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2306 SetSentErrorMessage(true);
2307 return false;
2310 // lowguid -> GUID of the NPC
2311 // point -> number of the waypoint (if not 0)
2312 sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2314 sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2316 Player* player = m_session->GetPlayer();
2317 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2319 // update movement type
2320 if(target)
2322 target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2323 target->GetMotionMaster()->Initialize();
2324 if(target->isAlive()) // dead creature will reset movement generator at respawn
2326 target->setDeathState(JUST_DIED);
2327 target->Respawn();
2329 target->SaveToDB();
2331 else
2332 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2334 PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2336 return true;
2337 } // HandleWpAddCommand
2340 * .wp modify emote | spell | text | del | move | add
2342 * add -> add a WP after the selected visual waypoint
2343 * User must select a visual waypoint and then issue ".wp modify add"
2345 * emote <emoteID>
2346 * User has selected a visual waypoint before.
2347 * <emoteID> is added to this waypoint. Everytime the
2348 * NPC comes to this waypoint, the emote is called.
2350 * emote <GUID> <WPNUM> <emoteID>
2351 * User has not selected visual waypoint before.
2352 * For the waypoint <WPNUM> for the NPC with <GUID>
2353 * an emote <emoteID> is added.
2354 * Everytime the NPC comes to this waypoint, the emote is called.
2357 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2359 bool ChatHandler::HandleWpModifyCommand(const char* args)
2361 sLog.outDebug("DEBUG: HandleWpModifyCommand");
2363 if(!*args)
2364 return false;
2366 // first arg: add del text emote spell waittime move
2367 char* show_str = strtok((char*)args, " ");
2368 if (!show_str)
2370 return false;
2373 std::string show = show_str;
2374 // Check
2375 // Remember: "show" must also be the name of a column!
2376 if( (show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2")
2377 && (show != "textid3") && (show != "textid4") && (show != "textid5")
2378 && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2379 && (show != "model1") && (show != "model2") && (show != "orientation"))
2381 return false;
2384 // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2386 // Did user provide a GUID
2387 // or did the user select a creature?
2388 // -> variable lowguid is filled with the GUID of the NPC
2389 uint32 lowguid = 0;
2390 uint32 point = 0;
2391 uint32 wpGuid = 0;
2392 Creature* target = getSelectedCreature();
2394 if(target)
2396 sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2398 // Did the user select a visual spawnpoint?
2399 if (target->GetEntry() != VISUAL_WAYPOINT )
2401 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2402 SetSentErrorMessage(true);
2403 return false;
2406 wpGuid = target->GetGUIDLow();
2408 // The visual waypoint
2409 QueryResult *result =
2410 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2411 target->GetGUIDLow() );
2412 if(!result)
2414 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2415 SetSentErrorMessage(true);
2416 return false;
2418 sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2420 Field *fields = result->Fetch();
2421 lowguid = fields[0].GetUInt32();
2422 point = fields[1].GetUInt32();
2424 // Cleanup memory
2425 sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2426 delete result;
2428 else
2430 // User did provide <GUID> <WPNUM>
2432 char* guid_str = strtok((char*)NULL, " ");
2433 if( !guid_str )
2435 SendSysMessage(LANG_WAYPOINT_NOGUID);
2436 return false;
2438 lowguid = atoi((char*)guid_str);
2440 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2441 if(!data)
2443 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2444 SetSentErrorMessage(true);
2445 return false;
2448 PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2450 char* point_str = strtok((char*)NULL, " ");
2451 if( !point_str )
2453 SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2454 return false;
2456 point = atoi((char*)point_str);
2458 PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2460 // Now we need the GUID of the visual waypoint
2461 // -> "del", "move", "add" command
2463 QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2464 if (!result)
2466 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2467 SetSentErrorMessage(true);
2468 return false;
2471 Field *fields = result->Fetch();
2472 wpGuid = fields[0].GetUInt32();
2474 // Free memory
2475 delete result;
2478 char* arg_str = NULL;
2479 // Check for argument
2480 if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2482 // Text is enclosed in "<>", all other arguments not
2483 if( show.find("text") != std::string::npos )
2484 arg_str = strtok((char*)NULL, "<>");
2485 else
2486 arg_str = strtok((char*)NULL, " ");
2488 if( !arg_str)
2490 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2491 return false;
2495 sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2497 // wpGuid -> GUID of the waypoint creature
2498 // lowguid -> GUID of the NPC
2499 // point -> waypoint number
2501 // Special functions:
2502 // add - move - del -> no args commands
2503 // Add a waypoint after the selected visual
2504 if(show == "add" && target)
2506 PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2508 // Get the creature for which we read the waypoint
2509 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2510 if(!data)
2512 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2513 SetSentErrorMessage(true);
2514 return false;
2517 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2519 if( !npcCreature )
2521 PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2522 SetSentErrorMessage(true);
2523 return false;
2526 sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2528 // What to do:
2529 // Add the visual spawnpoint (DB only)
2530 // Adjust the waypoints
2531 // Respawn the owner of the waypoints
2532 sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2534 Player* chr = m_session->GetPlayer();
2535 Map *map = chr->GetMap();
2537 if(npcCreature)
2539 npcCreature->GetMotionMaster()->Initialize();
2540 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2542 npcCreature->setDeathState(JUST_DIED);
2543 npcCreature->Respawn();
2547 // create the waypoint creature
2548 wpGuid = 0;
2549 Creature* wpCreature = new Creature;
2550 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT,0))
2552 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2553 delete wpCreature;
2555 else
2557 wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2559 if(!wpCreature->IsPositionValid())
2561 sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY());
2562 delete wpCreature;
2564 else
2566 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
2567 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2568 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2569 map->Add(wpCreature);
2570 wpGuid = wpCreature->GetGUIDLow();
2574 WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2576 if(!wpGuid)
2577 return false;
2579 PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2580 return true;
2581 } // add
2583 if(show == "del" && target)
2585 PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2587 // Get the creature for which we read the waypoint
2588 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2589 if(!data)
2591 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2592 SetSentErrorMessage(true);
2593 return false;
2596 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2598 // wpCreature
2599 Creature* wpCreature = NULL;
2600 if( wpGuid != 0 )
2602 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2603 wpCreature->DeleteFromDB();
2604 wpCreature->CleanupsBeforeDelete();
2605 wpCreature->AddObjectToRemoveList();
2608 // What to do:
2609 // Remove the visual spawnpoint
2610 // Adjust the waypoints
2611 // Respawn the owner of the waypoints
2613 WaypointMgr.DeleteNode(lowguid, point);
2615 if(npcCreature)
2617 // Any waypoints left?
2618 QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2619 if(!result2)
2621 npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2623 else
2625 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2626 delete result2;
2628 npcCreature->GetMotionMaster()->Initialize();
2629 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2631 npcCreature->setDeathState(JUST_DIED);
2632 npcCreature->Respawn();
2634 npcCreature->SaveToDB();
2637 PSendSysMessage(LANG_WAYPOINT_REMOVED);
2638 return true;
2639 } // del
2641 if(show == "move" && target)
2643 PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2645 Player *chr = m_session->GetPlayer();
2646 Map *map = chr->GetMap();
2648 // Get the creature for which we read the waypoint
2649 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2650 if(!data)
2652 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2653 SetSentErrorMessage(true);
2654 return false;
2657 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2659 // wpCreature
2660 Creature* wpCreature = NULL;
2661 // What to do:
2662 // Move the visual spawnpoint
2663 // Respawn the owner of the waypoints
2664 if( wpGuid != 0 )
2666 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2667 wpCreature->DeleteFromDB();
2668 wpCreature->CleanupsBeforeDelete();
2669 wpCreature->AddObjectToRemoveList();
2670 // re-create
2671 Creature* wpCreature2 = new Creature;
2672 if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0))
2674 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2675 delete wpCreature2;
2676 return false;
2679 wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2681 if(!wpCreature2->IsPositionValid())
2683 sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature2->GetGUIDLow(),wpCreature2->GetEntry(),wpCreature2->GetPositionX(),wpCreature2->GetPositionY());
2684 delete wpCreature2;
2685 return false;
2688 wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
2689 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2690 wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2691 map->Add(wpCreature2);
2692 //npcCreature->GetMap()->Add(wpCreature2);
2695 WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2697 if(npcCreature)
2699 npcCreature->GetMotionMaster()->Initialize();
2700 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2702 npcCreature->setDeathState(JUST_DIED);
2703 npcCreature->Respawn();
2706 PSendSysMessage(LANG_WAYPOINT_CHANGED);
2708 return true;
2709 } // move
2711 // Create creature - npc that has the waypoint
2712 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2713 if(!data)
2715 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2716 SetSentErrorMessage(true);
2717 return false;
2720 // set in game textids not supported
2721 if( show == "textid1" || show == "textid2" || show == "textid3" ||
2722 show == "textid4" || show == "textid5" )
2724 return false;
2727 WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2729 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2730 if(npcCreature)
2732 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2733 npcCreature->GetMotionMaster()->Initialize();
2734 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2736 npcCreature->setDeathState(JUST_DIED);
2737 npcCreature->Respawn();
2740 PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2742 return true;
2746 * .wp show info | on | off
2748 * info -> User has selected a visual waypoint before
2750 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2751 * provided the GUID of the NPC and the number of
2752 * the waypoint.
2754 * on -> User has selected an NPC; all visual waypoints for this
2755 * NPC are added to the world
2757 * on <GUID> -> User did not select an NPC - instead the GUID of the
2758 * NPC is provided. All visual waypoints for this NPC
2759 * are added from the world.
2761 * off -> User has selected an NPC; all visual waypoints for this
2762 * NPC are removed from the world.
2764 * on <GUID> -> User did not select an NPC - instead the GUID of the
2765 * NPC is provided. All visual waypoints for this NPC
2766 * are removed from the world.
2770 bool ChatHandler::HandleWpShowCommand(const char* args)
2772 sLog.outDebug("DEBUG: HandleWpShowCommand");
2774 if(!*args)
2775 return false;
2777 // first arg: on, off, first, last
2778 char* show_str = strtok((char*)args, " ");
2779 if (!show_str)
2781 return false;
2783 // second arg: GUID (optional, if a creature is selected)
2784 char* guid_str = strtok((char*)NULL, " ");
2785 sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
2786 //if (!guid_str) {
2787 // return false;
2790 // Did user provide a GUID
2791 // or did the user select a creature?
2792 // -> variable lowguid is filled with the GUID
2793 Creature* target = getSelectedCreature();
2794 // Did player provide a GUID?
2795 if (!guid_str)
2797 sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
2798 // No GUID provided
2799 // -> Player must have selected a creature
2801 if(!target)
2803 SendSysMessage(LANG_SELECT_CREATURE);
2804 SetSentErrorMessage(true);
2805 return false;
2808 else
2810 sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
2811 // GUID provided
2812 // Warn if player also selected a creature
2813 // -> Creature selection is ignored <-
2814 if(target)
2816 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2819 uint32 lowguid = atoi((char*)guid_str);
2821 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2822 if(!data)
2824 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2825 SetSentErrorMessage(true);
2826 return false;
2829 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2831 if(!target)
2833 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2834 SetSentErrorMessage(true);
2835 return false;
2839 uint32 lowguid = target->GetDBTableGUIDLow();
2841 std::string show = show_str;
2842 uint32 Maxpoint;
2844 sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
2846 // Show info for the selected waypoint
2847 if(show == "info")
2849 PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
2851 // Check if the user did specify a visual waypoint
2852 if( target->GetEntry() != VISUAL_WAYPOINT )
2854 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2855 SetSentErrorMessage(true);
2856 return false;
2859 //PSendSysMessage("wp on, GUID: %u", lowguid);
2861 //pCreature->GetPositionX();
2863 QueryResult *result =
2864 WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u",
2865 target->GetGUIDLow() );
2866 if(!result)
2868 // Since we compare float values, we have to deal with
2869 // some difficulties.
2870 // Here we search for all waypoints that only differ in one from 1 thousand
2871 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2872 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2873 const char* maxDIFF = "0.01";
2874 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
2876 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 )",
2877 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2878 if(!result)
2880 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2881 SetSentErrorMessage(true);
2882 return false;
2887 Field *fields = result->Fetch();
2888 uint32 creGUID = fields[0].GetUInt32();
2889 uint32 point = fields[1].GetUInt32();
2890 int waittime = fields[2].GetUInt32();
2891 uint32 emote = fields[3].GetUInt32();
2892 uint32 spell = fields[4].GetUInt32();
2893 uint32 textid[MAX_WAYPOINT_TEXT];
2894 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
2895 textid[i] = fields[5+i].GetUInt32();
2896 uint32 model1 = fields[10].GetUInt32();
2897 uint32 model2 = fields[11].GetUInt32();
2899 // Get the creature for which we read the waypoint
2900 Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2902 PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
2903 PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
2904 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
2905 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
2906 PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
2907 PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
2908 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
2909 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i+1, textid[i], (textid[i] ? GetMangosString(textid[i]) : ""));
2911 }while( result->NextRow() );
2912 // Cleanup memory
2913 delete result;
2914 return true;
2917 if(show == "on")
2919 PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
2921 QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
2922 if(!result)
2924 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
2925 SetSentErrorMessage(true);
2926 return false;
2928 // Delete all visuals for this NPC
2929 QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
2930 if(result2)
2932 bool hasError = false;
2935 Field *fields = result2->Fetch();
2936 uint32 wpguid = fields[0].GetUInt32();
2937 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2939 if(!pCreature)
2941 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
2942 hasError = true;
2943 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
2945 else
2947 pCreature->DeleteFromDB();
2948 pCreature->CleanupsBeforeDelete();
2949 pCreature->AddObjectToRemoveList();
2952 }while( result2->NextRow() );
2953 delete result2;
2954 if( hasError )
2956 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
2957 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
2958 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
2964 Field *fields = result->Fetch();
2965 uint32 point = fields[0].GetUInt32();
2966 float x = fields[1].GetFloat();
2967 float y = fields[2].GetFloat();
2968 float z = fields[3].GetFloat();
2970 uint32 id = VISUAL_WAYPOINT;
2972 Player *chr = m_session->GetPlayer();
2973 Map *map = chr->GetMap();
2974 float o = chr->GetOrientation();
2976 Creature* wpCreature = new Creature;
2977 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
2979 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
2980 delete wpCreature;
2981 delete result;
2982 return false;
2985 wpCreature->Relocate(x, y, z, o);
2987 if(!wpCreature->IsPositionValid())
2989 sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY());
2990 delete wpCreature;
2991 delete result;
2992 return false;
2995 wpCreature->SetVisibility(VISIBILITY_OFF);
2996 sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
2997 // set "wpguid" column to the visual waypoint
2998 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
3000 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3001 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
3002 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
3003 map->Add(wpCreature);
3004 //wpCreature->GetMap()->Add(wpCreature);
3005 }while( result->NextRow() );
3007 // Cleanup memory
3008 delete result;
3009 return true;
3012 if(show == "first")
3014 PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3016 QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3017 if(!result)
3019 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3020 SetSentErrorMessage(true);
3021 return false;
3024 Field *fields = result->Fetch();
3025 float x = fields[0].GetFloat();
3026 float y = fields[1].GetFloat();
3027 float z = fields[2].GetFloat();
3028 uint32 id = VISUAL_WAYPOINT;
3030 Player *chr = m_session->GetPlayer();
3031 float o = chr->GetOrientation();
3032 Map *map = chr->GetMap();
3034 Creature* pCreature = new Creature;
3035 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0))
3037 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3038 delete pCreature;
3039 delete result;
3040 return false;
3043 pCreature->Relocate(x, y, z, o);
3045 if(!pCreature->IsPositionValid())
3047 sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
3048 delete pCreature;
3049 delete result;
3050 return false;
3053 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3054 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3055 map->Add(pCreature);
3056 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3058 // Cleanup memory
3059 delete result;
3060 return true;
3063 if(show == "last")
3065 PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3067 QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3068 if( result )
3070 Maxpoint = (*result)[0].GetUInt32();
3072 delete result;
3074 else
3075 Maxpoint = 0;
3077 result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3078 if(!result)
3080 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3081 SetSentErrorMessage(true);
3082 return false;
3084 Field *fields = result->Fetch();
3085 float x = fields[0].GetFloat();
3086 float y = fields[1].GetFloat();
3087 float z = fields[2].GetFloat();
3088 uint32 id = VISUAL_WAYPOINT;
3090 Player *chr = m_session->GetPlayer();
3091 float o = chr->GetOrientation();
3092 Map *map = chr->GetMap();
3094 Creature* pCreature = new Creature;
3095 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0))
3097 PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3098 delete pCreature;
3099 delete result;
3100 return false;
3103 pCreature->Relocate(x, y, z, o);
3105 if(!pCreature->IsPositionValid())
3107 sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
3108 delete pCreature;
3109 delete result;
3110 return false;
3113 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
3114 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3115 map->Add(pCreature);
3116 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3117 // Cleanup memory
3118 delete result;
3119 return true;
3122 if(show == "off")
3124 QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3125 if(!result)
3127 SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3128 SetSentErrorMessage(true);
3129 return false;
3131 bool hasError = false;
3134 Field *fields = result->Fetch();
3135 uint32 guid = fields[0].GetUInt32();
3136 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3138 //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
3140 if(!pCreature)
3142 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3143 hasError = true;
3144 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3146 else
3148 pCreature->DeleteFromDB();
3149 pCreature->CleanupsBeforeDelete();
3150 pCreature->AddObjectToRemoveList();
3152 }while(result->NextRow());
3153 // set "wpguid" column to "empty" - no visual waypoint spawned
3154 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
3156 if( hasError )
3158 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3159 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3160 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3163 SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3164 // Cleanup memory
3165 delete result;
3167 return true;
3170 PSendSysMessage("DEBUG: wpshow - no valid command found");
3172 return true;
3173 } // HandleWpShowCommand
3175 bool ChatHandler::HandleWpExportCommand(const char *args)
3177 if(!*args)
3178 return false;
3180 // Next arg is: <GUID> <ARGUMENT>
3182 // Did user provide a GUID
3183 // or did the user select a creature?
3184 // -> variable lowguid is filled with the GUID of the NPC
3185 uint32 lowguid = 0;
3186 Creature* target = getSelectedCreature();
3187 char* arg_str = NULL;
3188 if (target)
3190 if (target->GetEntry() != VISUAL_WAYPOINT)
3191 lowguid = target->GetGUIDLow();
3192 else
3194 QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3195 if (!result)
3197 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3198 return true;
3200 Field *fields = result->Fetch();
3201 lowguid = fields[0].GetUInt32();;
3202 delete result;
3205 arg_str = strtok((char*)args, " ");
3207 else
3209 // user provided <GUID>
3210 char* guid_str = strtok((char*)args, " ");
3211 if( !guid_str )
3213 SendSysMessage(LANG_WAYPOINT_NOGUID);
3214 return false;
3216 lowguid = atoi((char*)guid_str);
3218 arg_str = strtok((char*)NULL, " ");
3221 if( !arg_str)
3223 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3224 return false;
3227 PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3229 QueryResult *result = WorldDatabase.PQuery(
3230 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3231 "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 );
3233 if (!result)
3235 PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3236 SetSentErrorMessage(true);
3237 return false;
3240 std::ofstream outfile;
3241 outfile.open (arg_str);
3245 Field *fields = result->Fetch();
3247 outfile << "INSERT INTO creature_movement ";
3248 outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5 ) VALUES ";
3250 outfile << "( ";
3251 outfile << fields[15].GetUInt32(); // id
3252 outfile << ", ";
3253 outfile << fields[0].GetUInt32(); // point
3254 outfile << ", ";
3255 outfile << fields[1].GetFloat(); // position_x
3256 outfile << ", ";
3257 outfile << fields[2].GetFloat(); // position_y
3258 outfile << ", ";
3259 outfile << fields[3].GetUInt32(); // position_z
3260 outfile << ", ";
3261 outfile << fields[4].GetUInt32(); // orientation
3262 outfile << ", ";
3263 outfile << fields[5].GetUInt32(); // model1
3264 outfile << ", ";
3265 outfile << fields[6].GetUInt32(); // model2
3266 outfile << ", ";
3267 outfile << fields[7].GetUInt16(); // waittime
3268 outfile << ", ";
3269 outfile << fields[8].GetUInt32(); // emote
3270 outfile << ", ";
3271 outfile << fields[9].GetUInt32(); // spell
3272 outfile << ", ";
3273 outfile << fields[10].GetUInt32(); // textid1
3274 outfile << ", ";
3275 outfile << fields[11].GetUInt32(); // textid2
3276 outfile << ", ";
3277 outfile << fields[12].GetUInt32(); // textid3
3278 outfile << ", ";
3279 outfile << fields[13].GetUInt32(); // textid4
3280 outfile << ", ";
3281 outfile << fields[14].GetUInt32(); // textid5
3282 outfile << ");\n ";
3284 } while( result->NextRow() );
3285 delete result;
3287 PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3288 outfile.close();
3290 return true;
3293 bool ChatHandler::HandleWpImportCommand(const char *args)
3295 if(!*args)
3296 return false;
3298 char* arg_str = strtok((char*)args, " ");
3299 if (!arg_str)
3300 return false;
3302 std::string line;
3303 std::ifstream infile (arg_str);
3304 if (infile.is_open())
3306 while (! infile.eof() )
3308 getline (infile,line);
3309 //cout << line << endl;
3310 QueryResult *result = WorldDatabase.Query(line.c_str());
3311 delete result;
3313 infile.close();
3315 PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3317 return true;
3320 //rename characters
3321 bool ChatHandler::HandleRenameCommand(const char* args)
3323 Player* target = NULL;
3324 uint64 targetGUID = 0;
3325 std::string oldname;
3327 char* px = strtok((char*)args, " ");
3329 if(px)
3331 oldname = extractPlayerNameFromLink(px);
3332 if(oldname.empty())
3334 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3335 SetSentErrorMessage(true);
3336 return false;
3339 target = objmgr.GetPlayer(oldname.c_str());
3341 if (!target)
3342 targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3345 if(!target && !targetGUID)
3347 target = getSelectedPlayer();
3350 if(!target && !targetGUID)
3352 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3353 SetSentErrorMessage(true);
3354 return false;
3357 if(target)
3359 // check online security
3360 if (HasLowerSecurity(target, 0))
3361 return false;
3363 PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str());
3364 target->SetAtLoginFlag(AT_LOGIN_RENAME);
3365 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3367 else
3369 // check offline security
3370 if (HasLowerSecurity(NULL, targetGUID))
3371 return false;
3373 std::string oldNameLink = playerLink(oldname);
3375 PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGUID));
3376 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3379 return true;
3382 // customize characters
3383 bool ChatHandler::HandleCustomizeCommand(const char* args)
3385 Player* target = NULL;
3386 uint64 targetGUID = 0;
3387 std::string oldname;
3389 char* px = strtok((char*)args, " ");
3391 if(px)
3393 oldname = extractPlayerNameFromLink(px);
3394 if(oldname.empty())
3396 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3397 SetSentErrorMessage(true);
3398 return false;
3401 target = objmgr.GetPlayer(oldname.c_str());
3403 if (!target)
3404 targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3407 if(!target && !targetGUID)
3409 target = getSelectedPlayer();
3412 if(!target && !targetGUID)
3414 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3415 SetSentErrorMessage(true);
3416 return false;
3419 if(target)
3421 PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str());
3422 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
3423 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow());
3425 else
3427 std::string oldNameLink = playerLink(oldname);
3429 PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGUID));
3430 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3433 return true;
3436 //spawn go
3437 bool ChatHandler::HandleGameObjectCommand(const char* args)
3439 if (!*args)
3440 return false;
3442 char* pParam1 = strtok((char*)args, " ");
3443 if (!pParam1)
3444 return false;
3446 uint32 id = atoi((char*)pParam1);
3447 if(!id)
3448 return false;
3450 char* spawntimeSecs = strtok(NULL, " ");
3452 const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id);
3454 if (!goI)
3456 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
3457 SetSentErrorMessage(true);
3458 return false;
3461 Player *chr = m_session->GetPlayer();
3462 float x = float(chr->GetPositionX());
3463 float y = float(chr->GetPositionY());
3464 float z = float(chr->GetPositionZ());
3465 float o = float(chr->GetOrientation());
3466 Map *map = chr->GetMap();
3468 float rot2 = sin(o/2);
3469 float rot3 = cos(o/2);
3471 GameObject* pGameObj = new GameObject;
3472 uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
3474 if(!pGameObj->Create(db_lowGUID, goI->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0, 0, rot2, rot3, 0, 1))
3476 delete pGameObj;
3477 return false;
3480 if( spawntimeSecs )
3482 uint32 value = atoi((char*)spawntimeSecs);
3483 pGameObj->SetRespawnTime(value);
3484 //sLog.outDebug("*** spawntimeSecs: %d", value);
3487 // fill the gameobject data and save to the db
3488 pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn());
3490 // this will generate a new guid if the object is in an instance
3491 if(!pGameObj->LoadFromDB(db_lowGUID, map))
3493 delete pGameObj;
3494 return false;
3497 sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o);
3499 map->Add(pGameObj);
3501 // TODO: is it really necessary to add both the real and DB table guid here ?
3502 objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
3504 PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z);
3505 return true;
3508 //show animation
3509 bool ChatHandler::HandleAnimCommand(const char* args)
3511 if (!*args)
3512 return false;
3514 uint32 anim_id = atoi((char*)args);
3515 m_session->GetPlayer()->HandleEmoteCommand(anim_id);
3516 return true;
3519 //change standstate
3520 bool ChatHandler::HandleStandStateCommand(const char* args)
3522 if (!*args)
3523 return false;
3525 uint32 anim_id = atoi((char*)args);
3526 m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3528 return true;
3531 bool ChatHandler::HandleAddHonorCommand(const char* args)
3533 if (!*args)
3534 return false;
3536 Player *target = getSelectedPlayer();
3537 if(!target)
3539 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3540 SetSentErrorMessage(true);
3541 return false;
3544 // check online security
3545 if (HasLowerSecurity(target, 0))
3546 return false;
3548 uint32 amount = (uint32)atoi(args);
3549 target->RewardHonor(NULL, 1, amount);
3550 return true;
3553 bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3555 Unit *target = getSelectedUnit();
3556 if(!target)
3558 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3559 SetSentErrorMessage(true);
3560 return false;
3563 // check online security
3564 if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
3565 return false;
3567 m_session->GetPlayer()->RewardHonor(target, 1);
3568 return true;
3571 bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/)
3573 Player *target = getSelectedPlayer();
3574 if(!target)
3576 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3577 SetSentErrorMessage(true);
3578 return false;
3581 // check online security
3582 if (HasLowerSecurity(target, 0))
3583 return false;
3585 target->UpdateHonorFields();
3586 return true;
3589 bool ChatHandler::HandleLookupEventCommand(const char* args)
3591 if(!*args)
3592 return false;
3594 std::string namepart = args;
3595 std::wstring wnamepart;
3597 // converting string that we try to find to lower case
3598 if(!Utf8toWStr(namepart,wnamepart))
3599 return false;
3601 wstrToLower(wnamepart);
3603 uint32 counter = 0;
3605 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3606 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3608 for(uint32 id = 0; id < events.size(); ++id )
3610 GameEventData const& eventData = events[id];
3612 std::string descr = eventData.description;
3613 if(descr.empty())
3614 continue;
3616 if (Utf8FitTo(descr, wnamepart))
3618 char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : "";
3620 if(m_session)
3621 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3622 else
3623 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3625 ++counter;
3629 if (counter==0)
3630 SendSysMessage(LANG_NOEVENTFOUND);
3632 return true;
3635 bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/)
3637 uint32 counter = 0;
3639 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3640 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3642 char const* active = GetMangosString(LANG_ACTIVE);
3644 for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
3646 uint32 event_id = *itr;
3647 GameEventData const& eventData = events[event_id];
3649 if(m_session)
3650 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
3651 else
3652 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
3654 ++counter;
3657 if (counter==0)
3658 SendSysMessage(LANG_NOEVENTFOUND);
3660 return true;
3663 bool ChatHandler::HandleEventInfoCommand(const char* args)
3665 if(!*args)
3666 return false;
3668 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3669 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3670 if(!cId)
3671 return false;
3673 uint32 event_id = atoi(cId);
3675 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3677 if(event_id >=events.size())
3679 SendSysMessage(LANG_EVENT_NOT_EXIST);
3680 SetSentErrorMessage(true);
3681 return false;
3684 GameEventData const& eventData = events[event_id];
3685 if(!eventData.isValid())
3687 SendSysMessage(LANG_EVENT_NOT_EXIST);
3688 SetSentErrorMessage(true);
3689 return false;
3692 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3693 bool active = activeEvents.find(event_id) != activeEvents.end();
3694 char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : "";
3696 std::string startTimeStr = TimeToTimestampStr(eventData.start);
3697 std::string endTimeStr = TimeToTimestampStr(eventData.end);
3699 uint32 delay = gameeventmgr.NextCheck(event_id);
3700 time_t nextTime = time(NULL)+delay;
3701 std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3703 std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3704 std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3706 PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3707 startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3708 nextStr.c_str());
3709 return true;
3712 bool ChatHandler::HandleEventStartCommand(const char* args)
3714 if(!*args)
3715 return false;
3717 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3718 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3719 if(!cId)
3720 return false;
3722 int32 event_id = atoi(cId);
3724 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3726 if(event_id < 1 || event_id >=events.size())
3728 SendSysMessage(LANG_EVENT_NOT_EXIST);
3729 SetSentErrorMessage(true);
3730 return false;
3733 GameEventData const& eventData = events[event_id];
3734 if(!eventData.isValid())
3736 SendSysMessage(LANG_EVENT_NOT_EXIST);
3737 SetSentErrorMessage(true);
3738 return false;
3741 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3742 if(activeEvents.find(event_id) != activeEvents.end())
3744 PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3745 SetSentErrorMessage(true);
3746 return false;
3749 gameeventmgr.StartEvent(event_id,true);
3750 return true;
3753 bool ChatHandler::HandleEventStopCommand(const char* args)
3755 if(!*args)
3756 return false;
3758 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3759 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3760 if(!cId)
3761 return false;
3763 int32 event_id = atoi(cId);
3765 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3767 if(event_id < 1 || event_id >=events.size())
3769 SendSysMessage(LANG_EVENT_NOT_EXIST);
3770 SetSentErrorMessage(true);
3771 return false;
3774 GameEventData const& eventData = events[event_id];
3775 if(!eventData.isValid())
3777 SendSysMessage(LANG_EVENT_NOT_EXIST);
3778 SetSentErrorMessage(true);
3779 return false;
3782 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3784 if(activeEvents.find(event_id) == activeEvents.end())
3786 PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3787 SetSentErrorMessage(true);
3788 return false;
3791 gameeventmgr.StopEvent(event_id,true);
3792 return true;
3795 bool ChatHandler::HandleCombatStopCommand(const char* args)
3797 Player *player;
3799 if(*args)
3801 std::string playername = extractPlayerNameFromLink((char*)args);
3802 if(playername.empty())
3804 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3805 SetSentErrorMessage(true);
3806 return false;
3809 player = objmgr.GetPlayer(playername.c_str());
3811 if(!player)
3813 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3814 SetSentErrorMessage(true);
3815 return false;
3818 else
3820 player = getSelectedPlayer();
3822 if (!player)
3823 player = m_session->GetPlayer();
3826 // check online security
3827 if (HasLowerSecurity(player, 0))
3828 return false;
3830 player->CombatStop();
3831 player->getHostilRefManager().deleteReferences();
3832 return true;
3835 bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3837 uint32 classmask = m_session->GetPlayer()->getClassMask();
3839 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3841 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3842 if( !skillInfo )
3843 continue;
3845 if( skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY )
3847 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3849 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3850 if( !skillLine )
3851 continue;
3853 // skip racial skills
3854 if( skillLine->racemask != 0 )
3855 continue;
3857 // skip wrong class skills
3858 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3859 continue;
3861 if( skillLine->skillId != i || skillLine->forward_spellid )
3862 continue;
3864 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3865 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3866 continue;
3868 m_session->GetPlayer()->learnSpell(skillLine->spellId,false);
3873 SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
3874 return true;
3877 bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
3879 // Learns all recipes of specified profession and sets skill to max
3880 // Example: .learn all_recipes enchanting
3882 Player* target = getSelectedPlayer();
3883 if( !target )
3885 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3886 return false;
3889 if(!*args)
3890 return false;
3892 std::wstring wnamepart;
3894 if(!Utf8toWStr(args,wnamepart))
3895 return false;
3897 // converting string that we try to find to lower case
3898 wstrToLower( wnamepart );
3900 uint32 classmask = m_session->GetPlayer()->getClassMask();
3902 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3904 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3905 if( !skillInfo )
3906 continue;
3908 if( skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
3909 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY )
3910 continue;
3912 int loc = m_session->GetSessionDbcLocale();
3913 std::string name = skillInfo->name[loc];
3915 if(Utf8FitTo(name, wnamepart))
3917 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3919 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3920 if( !skillLine )
3921 continue;
3923 if( skillLine->skillId != i || skillLine->forward_spellid )
3924 continue;
3926 // skip racial skills
3927 if( skillLine->racemask != 0 )
3928 continue;
3930 // skip wrong class skills
3931 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3932 continue;
3934 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3935 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3936 continue;
3938 if( !target->HasSpell(spellInfo->Id) )
3939 m_session->GetPlayer()->learnSpell(skillLine->spellId,false);
3942 uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
3943 target->SetSkill(skillInfo->id, maxLevel, maxLevel);
3944 PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
3945 return true;
3949 return false;
3952 bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
3955 if (!*args)
3956 return false;
3958 std::string ip = strtok ((char*)args, " ");
3959 char* limit_str = strtok (NULL, " ");
3960 int32 limit = limit_str ? atoi (limit_str) : -1;
3962 loginDatabase.escape_string (ip);
3964 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
3966 return LookupPlayerSearchCommand (result,limit);
3969 bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
3971 if (!*args)
3972 return false;
3974 std::string account = strtok ((char*)args, " ");
3975 char* limit_str = strtok (NULL, " ");
3976 int32 limit = limit_str ? atoi (limit_str) : -1;
3978 if (!AccountMgr::normilizeString (account))
3979 return false;
3981 loginDatabase.escape_string (account);
3983 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
3985 return LookupPlayerSearchCommand (result,limit);
3988 bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
3991 if (!*args)
3992 return false;
3994 std::string email = strtok ((char*)args, " ");
3995 char* limit_str = strtok (NULL, " ");
3996 int32 limit = limit_str ? atoi (limit_str) : -1;
3998 loginDatabase.escape_string (email);
4000 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
4002 return LookupPlayerSearchCommand (result,limit);
4005 bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
4007 if(!result)
4009 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4010 SetSentErrorMessage(true);
4011 return false;
4014 int i =0;
4017 Field* fields = result->Fetch();
4018 uint32 acc_id = fields[0].GetUInt32();
4019 std::string acc_name = fields[1].GetCppString();
4021 QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
4022 if(chars)
4024 PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4026 uint64 guid = 0;
4027 std::string name;
4031 Field* charfields = chars->Fetch();
4032 guid = charfields[0].GetUInt64();
4033 name = charfields[1].GetCppString();
4035 PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
4036 ++i;
4038 } while( chars->NextRow() && ( limit == -1 || i < limit ) );
4040 delete chars;
4042 } while(result->NextRow());
4044 delete result;
4046 return true;
4049 /// Triggering corpses expire check in world
4050 bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4052 CorpsesErase();
4053 return true;
4056 bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
4058 Player *target = getSelectedPlayer();
4060 if(!target)
4062 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4063 SetSentErrorMessage(true);
4064 return false;
4067 // check online security
4068 if (HasLowerSecurity(target, 0))
4069 return false;
4071 // Repair items
4072 target->DurabilityRepairAll(false, 0, false);
4074 PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str());
4075 if(needReportToTarget(target))
4076 ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str());
4077 return true;
4080 bool ChatHandler::HandleWaterwalkCommand(const char* args)
4082 if(!*args)
4083 return false;
4085 Player *player = getSelectedPlayer();
4087 if(!player)
4089 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4090 SetSentErrorMessage(true);
4091 return false;
4094 // check online security
4095 if (HasLowerSecurity(player, 0))
4096 return false;
4098 if (strncmp(args, "on", 3) == 0)
4099 player->SetMovement(MOVE_WATER_WALK); // ON
4100 else if (strncmp(args, "off", 4) == 0)
4101 player->SetMovement(MOVE_LAND_WALK); // OFF
4102 else
4104 SendSysMessage(LANG_USE_BOL);
4105 return false;
4108 PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str());
4109 if(needReportToTarget(player))
4110 ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str());
4111 return true;
4114 bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
4116 Player *player = m_session->GetPlayer();
4117 Creature *creature = getSelectedCreature();
4119 if(!creature)
4121 PSendSysMessage(LANG_SELECT_CREATURE);
4122 SetSentErrorMessage(true);
4123 return false;
4126 // Follow player - Using pet's default dist and angle
4127 creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
4129 PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
4130 return true;
4133 bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
4135 Player *player = m_session->GetPlayer();
4136 Creature *creature = getSelectedCreature();
4138 if(!creature)
4140 PSendSysMessage(LANG_SELECT_CREATURE);
4141 SetSentErrorMessage(true);
4142 return false;
4145 if (creature->GetMotionMaster()->empty() ||
4146 creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
4148 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4149 SetSentErrorMessage(true);
4150 return false;
4153 TargetedMovementGenerator<Creature> const* mgen
4154 = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
4156 if(mgen->GetTarget()!=player)
4158 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4159 SetSentErrorMessage(true);
4160 return false;
4163 // reset movement
4164 creature->GetMotionMaster()->MovementExpired(true);
4166 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
4167 return true;
4170 bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
4172 Creature *creatureTarget = getSelectedCreature ();
4173 if (!creatureTarget || creatureTarget->isPet ())
4175 PSendSysMessage (LANG_SELECT_CREATURE);
4176 SetSentErrorMessage (true);
4177 return false;
4180 Player *player = m_session->GetPlayer ();
4182 if(player->GetPetGUID ())
4184 SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
4185 SetSentErrorMessage (true);
4186 return false;
4189 CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
4191 if (!cInfo->isTameable ())
4193 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4194 SetSentErrorMessage (true);
4195 return false;
4198 // Everything looks OK, create new pet
4199 Pet* pet = player->CreateTamedPetFrom (creatureTarget);
4200 if (!pet)
4202 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4203 SetSentErrorMessage (true);
4204 return false;
4207 // place pet before player
4208 float x,y,z;
4209 player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
4210 pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
4212 // set pet to defensive mode by default (some classes can't control controlled pets in fact).
4213 pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4215 // calculate proper level
4216 uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
4218 // prepare visual effect for levelup
4219 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4221 // add to world
4222 pet->GetMap()->Add((Creature*)pet);
4224 // visual effect for levelup
4225 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4227 // caster have pet now
4228 player->SetPet(pet);
4230 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4231 player->PetSpellInitialize();
4233 return true;
4236 //change phasemask of creature or pet
4237 bool ChatHandler::HandleNpcSetPhaseCommand(const char* args)
4239 if (!*args)
4240 return false;
4242 uint32 phasemask = (uint32) atoi((char*)args);
4243 if ( phasemask == 0 )
4245 SendSysMessage(LANG_BAD_VALUE);
4246 SetSentErrorMessage(true);
4247 return false;
4250 Creature* pCreature = getSelectedCreature();
4251 if(!pCreature)
4253 SendSysMessage(LANG_SELECT_CREATURE);
4254 SetSentErrorMessage(true);
4255 return false;
4258 pCreature->SetPhaseMask(phasemask,true);
4260 if(!pCreature->isPet())
4261 pCreature->SaveToDB();
4263 return true;
4266 //set pahsemask for selected object
4267 bool ChatHandler::HandleGOPhaseCommand(const char* args)
4269 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
4270 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
4271 if(!cId)
4272 return false;
4274 uint32 lowguid = atoi(cId);
4275 if(!lowguid)
4276 return false;
4278 GameObject* obj = NULL;
4280 // by DB guid
4281 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
4282 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
4284 if(!obj)
4286 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
4287 SetSentErrorMessage(true);
4288 return false;
4291 char* phaseStr = strtok (NULL, " ");
4292 uint32 phasemask = phaseStr? atoi(phaseStr) : 0;
4293 if ( phasemask == 0 )
4295 SendSysMessage(LANG_BAD_VALUE);
4296 SetSentErrorMessage(true);
4297 return false;
4300 obj->SetPhaseMask(phasemask,true);
4301 obj->SaveToDB();
4302 return true;
4305 bool ChatHandler::HandleNpcSetDeathStateCommand(const char* args)
4307 if (!*args)
4308 return false;
4310 Creature* pCreature = getSelectedCreature();
4311 if(!pCreature || pCreature->isPet())
4313 SendSysMessage(LANG_SELECT_CREATURE);
4314 SetSentErrorMessage(true);
4315 return false;
4318 if (strncmp(args, "on", 3) == 0)
4319 pCreature->SetDeadByDefault(true);
4320 else if (strncmp(args, "off", 4) == 0)
4321 pCreature->SetDeadByDefault(false);
4322 else
4324 SendSysMessage(LANG_USE_BOL);
4325 SetSentErrorMessage(true);
4326 return false;
4329 pCreature->SaveToDB();
4330 pCreature->Respawn();
4332 return true;