[6982] Implemented gmlevel-based command security
[getmangos.git] / src / game / Level2.cpp
blobd713001117644c91ca94a63829bf0f56e85134dc
1 /*
2 * Copyright (C) 2005-2008 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 char *charname = strtok((char*)args, " ");
61 if (!charname)
62 return false;
64 std::string cname = charname;
66 char *timetonotspeak = strtok(NULL, " ");
67 if(!timetonotspeak)
68 return false;
70 uint32 notspeaktime = (uint32) atoi(timetonotspeak);
72 if(!normalizePlayerName(cname))
74 SendSysMessage(LANG_PLAYER_NOT_FOUND);
75 SetSentErrorMessage(true);
76 return false;
79 uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
80 if(!guid)
82 SendSysMessage(LANG_PLAYER_NOT_FOUND);
83 SetSentErrorMessage(true);
84 return false;
87 Player *chr = objmgr.GetPlayer(guid);
89 // check security
90 uint32 account_id = 0;
91 uint32 security = 0;
93 if (chr)
95 account_id = chr->GetSession()->GetAccountId();
96 security = chr->GetSession()->GetSecurity();
98 else
100 account_id = objmgr.GetPlayerAccountIdByGUID(guid);
101 security = accmgr.GetSecurity(account_id);
104 if(m_session && security >= m_session->GetSecurity())
106 SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
107 SetSentErrorMessage(true);
108 return false;
111 time_t mutetime = time(NULL) + notspeaktime*60;
113 if (chr)
114 chr->GetSession()->m_muteTime = mutetime;
116 loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
118 if(chr)
119 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
121 PSendSysMessage(LANG_YOU_DISABLE_CHAT, cname.c_str(), notspeaktime);
123 return true;
126 //unmute player
127 bool ChatHandler::HandleUnmuteCommand(const char* args)
129 if (!*args)
130 return false;
132 char *charname = strtok((char*)args, " ");
133 if (!charname)
134 return false;
136 std::string cname = charname;
138 if(!normalizePlayerName(cname))
140 SendSysMessage(LANG_PLAYER_NOT_FOUND);
141 SetSentErrorMessage(true);
142 return false;
145 uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
146 if(!guid)
148 SendSysMessage(LANG_PLAYER_NOT_FOUND);
149 SetSentErrorMessage(true);
150 return false;
153 Player *chr = objmgr.GetPlayer(guid);
155 // check security
156 uint32 account_id = 0;
157 uint32 security = 0;
159 if (chr)
161 account_id = chr->GetSession()->GetAccountId();
162 security = chr->GetSession()->GetSecurity();
164 else
166 account_id = objmgr.GetPlayerAccountIdByGUID(guid);
167 security = accmgr.GetSecurity(account_id);
170 if(m_session && security >= m_session->GetSecurity())
172 SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
173 SetSentErrorMessage(true);
174 return false;
177 if (chr)
179 if(chr->CanSpeak())
181 SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
182 SetSentErrorMessage(true);
183 return false;
186 chr->GetSession()->m_muteTime = 0;
189 loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
191 if(chr)
192 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
194 PSendSysMessage(LANG_YOU_ENABLE_CHAT, cname.c_str());
195 return true;
198 bool ChatHandler::HandleTargetObjectCommand(const char* args)
200 Player* pl = m_session->GetPlayer();
201 QueryResult *result;
202 GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
203 if(*args)
205 int32 id = atoi((char*)args);
206 if(id)
207 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",
208 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
209 else
211 std::string name = args;
212 WorldDatabase.escape_string(name);
213 result = WorldDatabase.PQuery(
214 "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_ "
215 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
216 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
219 else
221 std::ostringstream eventFilter;
222 eventFilter << " AND (event IS NULL ";
223 bool initString = true;
225 for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
227 if (initString)
229 eventFilter << "OR event IN (" <<*itr;
230 initString =false;
232 else
233 eventFilter << "," << *itr;
236 if (!initString)
237 eventFilter << "))";
238 else
239 eventFilter << ")";
241 result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
242 "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
243 "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 1",
244 m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
247 if (!result)
249 SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
250 return true;
253 Field *fields = result->Fetch();
254 uint32 lowguid = fields[0].GetUInt32();
255 uint32 id = fields[1].GetUInt32();
256 float x = fields[2].GetFloat();
257 float y = fields[3].GetFloat();
258 float z = fields[4].GetFloat();
259 float o = fields[5].GetFloat();
260 int mapid = fields[6].GetUInt16();
261 delete result;
263 GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id);
265 if (!goI)
267 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
268 return false;
271 GameObject* target = ObjectAccessor::GetGameObject(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
273 PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
275 if(target)
277 int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
278 if(curRespawnDelay < 0)
279 curRespawnDelay = 0;
281 std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
282 std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
284 PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
286 return true;
289 //teleport to gameobject
290 bool ChatHandler::HandleGoObjectCommand(const char* args)
292 if(!*args)
293 return false;
295 Player* _player = m_session->GetPlayer();
297 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
298 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
299 if(!cId)
300 return false;
302 int32 guid = atoi(cId);
303 if(!guid)
304 return false;
306 float x, y, z, ort;
307 int mapid;
309 // by DB guid
310 if (GameObjectData const* go_data = objmgr.GetGOData(guid))
312 x = go_data->posX;
313 y = go_data->posY;
314 z = go_data->posZ;
315 ort = go_data->orientation;
316 mapid = go_data->mapid;
318 else
320 SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
321 SetSentErrorMessage(true);
322 return false;
325 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
327 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
328 SetSentErrorMessage(true);
329 return false;
332 // stop flight if need
333 if(_player->isInFlight())
335 _player->GetMotionMaster()->MovementExpired();
336 _player->m_taxi.ClearTaxiDestinations();
338 // save only in non-flight case
339 else
340 _player->SaveRecallPosition();
342 _player->TeleportTo(mapid, x, y, z, ort);
343 return true;
346 bool ChatHandler::HandleGoTriggerCommand(const char* args)
348 Player* _player = m_session->GetPlayer();
350 if (!*args)
351 return false;
353 char *atId = strtok((char*)args, " ");
354 if (!atId)
355 return false;
357 int32 i_atId = atoi(atId);
359 if(!i_atId)
360 return false;
362 AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
363 if (!at)
365 PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
366 SetSentErrorMessage(true);
367 return false;
370 if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
372 PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
373 SetSentErrorMessage(true);
374 return false;
377 // stop flight if need
378 if(_player->isInFlight())
380 _player->GetMotionMaster()->MovementExpired();
381 _player->m_taxi.ClearTaxiDestinations();
383 // save only in non-flight case
384 else
385 _player->SaveRecallPosition();
387 _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
388 return true;
391 bool ChatHandler::HandleGoGraveyardCommand(const char* args)
393 Player* _player = m_session->GetPlayer();
395 if (!*args)
396 return false;
398 char *gyId = strtok((char*)args, " ");
399 if (!gyId)
400 return false;
402 int32 i_gyId = atoi(gyId);
404 if(!i_gyId)
405 return false;
407 WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
408 if (!gy)
410 PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
411 SetSentErrorMessage(true);
412 return false;
415 if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
417 PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
418 SetSentErrorMessage(true);
419 return false;
422 // stop flight if need
423 if(_player->isInFlight())
425 _player->GetMotionMaster()->MovementExpired();
426 _player->m_taxi.ClearTaxiDestinations();
428 // save only in non-flight case
429 else
430 _player->SaveRecallPosition();
432 _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
433 return true;
436 /** \brief Teleport the GM to the specified creature
438 * .gocreature <GUID> --> TP using creature.guid
439 * .gocreature azuregos --> TP player to the mob with this name
440 * Warning: If there is more than one mob with this name
441 * you will be teleported to the first one that is found.
442 * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry
443 * Warning: If there is more than one mob with this "id"
444 * you will be teleported to the first one that is found.
446 //teleport to creature
447 bool ChatHandler::HandleGoCreatureCommand(const char* args)
449 if(!*args)
450 return false;
451 Player* _player = m_session->GetPlayer();
453 // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
454 char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
455 if (!pParam1)
456 return false;
458 std::ostringstream whereClause;
460 // User wants to teleport to the NPC's template entry
461 if( strcmp(pParam1, "id") == 0 )
463 //sLog.outError("DEBUG: ID found");
465 // Get the "creature_template.entry"
466 // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
467 char* tail = strtok(NULL,"");
468 if(!tail)
469 return false;
470 char* cId = extractKeyFromLink(tail,"Hcreature_entry");
471 if(!cId)
472 return false;
474 int32 tEntry = atoi(cId);
475 //sLog.outError("DEBUG: ID value: %d", tEntry);
476 if(!tEntry)
477 return false;
479 whereClause << "WHERE id = '" << tEntry << "'";
481 else
483 //sLog.outError("DEBUG: ID *not found*");
485 int32 guid = atoi(pParam1);
487 // Number is invalid - maybe the user specified the mob's name
488 if(!guid)
490 std::string name = pParam1;
491 WorldDatabase.escape_string(name);
492 whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
494 else
496 whereClause << "WHERE guid = '" << guid << "'";
499 //sLog.outError("DEBUG: %s", whereClause.c_str());
501 QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
502 if (!result)
504 SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
505 SetSentErrorMessage(true);
506 return false;
508 if( result->GetRowCount() > 1 )
510 SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
513 Field *fields = result->Fetch();
514 float x = fields[0].GetFloat();
515 float y = fields[1].GetFloat();
516 float z = fields[2].GetFloat();
517 float ort = fields[3].GetFloat();
518 int mapid = fields[4].GetUInt16();
520 delete result;
522 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
524 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
525 SetSentErrorMessage(true);
526 return false;
529 // stop flight if need
530 if(_player->isInFlight())
532 _player->GetMotionMaster()->MovementExpired();
533 _player->m_taxi.ClearTaxiDestinations();
535 // save only in non-flight case
536 else
537 _player->SaveRecallPosition();
539 _player->TeleportTo(mapid, x, y, z, ort);
540 return true;
543 bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
545 uint64 guid = m_session->GetPlayer()->GetSelection();
547 if (guid == 0)
549 SendSysMessage(LANG_NO_SELECTION);
550 SetSentErrorMessage(true);
551 return false;
554 PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
555 return true;
558 bool ChatHandler::HandleLookupFactionCommand(const char* args)
560 if (!*args)
561 return false;
563 // Can be NULL at console call
564 Player *target = getSelectedPlayer ();
566 std::string namepart = args;
567 std::wstring wnamepart;
569 if (!Utf8toWStr (namepart,wnamepart))
570 return false;
572 // converting string that we try to find to lower case
573 wstrToLower (wnamepart);
575 uint32 counter = 0; // Counter for figure out that we found smth.
577 for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
579 FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
580 if (factionEntry)
582 FactionState const* repState = NULL;
583 if(target)
585 FactionStateList::const_iterator repItr = target->m_factions.find (factionEntry->reputationListID);
586 if(repItr != target->m_factions.end())
587 repState = &repItr->second;
591 int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale();
592 std::string name = factionEntry->name[loc];
593 if(name.empty())
594 continue;
596 if (!Utf8FitTo(name, wnamepart))
598 loc = 0;
599 for(; loc < MAX_LOCALE; ++loc)
601 if(m_session && loc==m_session->GetSessionDbcLocale())
602 continue;
604 name = factionEntry->name[loc];
605 if(name.empty())
606 continue;
608 if (Utf8FitTo(name, wnamepart))
609 break;
613 if(loc < MAX_LOCALE)
615 // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
616 // or "id - [faction] [no reputation]" format
617 std::ostringstream ss;
618 if (m_session)
619 ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
620 else
621 ss << id << " - " << name << " " << localeNames[loc];
623 if (repState) // and then target!=NULL also
625 ReputationRank rank = target->GetReputationRank(factionEntry);
626 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
628 ss << " " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
630 if(repState->Flags & FACTION_FLAG_VISIBLE)
631 ss << GetMangosString(LANG_FACTION_VISIBLE);
632 if(repState->Flags & FACTION_FLAG_AT_WAR)
633 ss << GetMangosString(LANG_FACTION_ATWAR);
634 if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
635 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
636 if(repState->Flags & FACTION_FLAG_HIDDEN)
637 ss << GetMangosString(LANG_FACTION_HIDDEN);
638 if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
639 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
640 if(repState->Flags & FACTION_FLAG_INACTIVE)
641 ss << GetMangosString(LANG_FACTION_INACTIVE);
643 else
644 ss << GetMangosString(LANG_FACTION_NOREPUTATION);
646 SendSysMessage(ss.str().c_str());
647 counter++;
652 if (counter == 0) // if counter == 0 then we found nth
653 SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
654 return true;
657 bool ChatHandler::HandleModifyRepCommand(const char * args)
659 if (!*args) return false;
661 Player* target = NULL;
662 target = getSelectedPlayer();
664 if(!target)
666 SendSysMessage(LANG_PLAYER_NOT_FOUND);
667 SetSentErrorMessage(true);
668 return false;
671 // check online security
672 if (HasLowerSecurity(target, 0))
673 return false;
675 char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
676 if(!factionTxt)
677 return false;
679 uint32 factionId = atoi(factionTxt);
681 int32 amount = 0;
682 char *rankTxt = strtok(NULL, " ");
683 if (!factionTxt || !rankTxt)
684 return false;
686 amount = atoi(rankTxt);
687 if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
689 std::string rankStr = rankTxt;
690 std::wstring wrankStr;
691 if(!Utf8toWStr(rankStr,wrankStr))
692 return false;
693 wstrToLower( wrankStr );
695 int r = 0;
696 amount = -42000;
697 for (; r < MAX_REPUTATION_RANK; ++r)
699 std::string rank = GetMangosString(ReputationRankStrIndex[r]);
700 if(rank.empty())
701 continue;
703 std::wstring wrank;
704 if(!Utf8toWStr(rank,wrank))
705 continue;
707 wstrToLower(wrank);
709 if(wrank.substr(0,wrankStr.size())==wrankStr)
711 char *deltaTxt = strtok(NULL, " ");
712 if (deltaTxt)
714 int32 delta = atoi(deltaTxt);
715 if ((delta < 0) || (delta > Player::ReputationRank_Length[r] -1))
717 PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (Player::ReputationRank_Length[r]-1));
718 SetSentErrorMessage(true);
719 return false;
721 amount += delta;
723 break;
725 amount += Player::ReputationRank_Length[r];
727 if (r >= MAX_REPUTATION_RANK)
729 PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
730 SetSentErrorMessage(true);
731 return false;
735 FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
737 if (!factionEntry)
739 PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
740 SetSentErrorMessage(true);
741 return false;
744 if (factionEntry->reputationListID < 0)
746 PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[m_session->GetSessionDbcLocale()], factionId);
747 SetSentErrorMessage(true);
748 return false;
751 target->SetFactionReputation(factionEntry,amount);
752 PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, target->GetName(), target->GetReputation(factionId));
753 return true;
756 bool ChatHandler::HandleNameCommand(const char* /*args*/)
758 /* Temp. disabled
759 if(!*args)
760 return false;
762 if(strlen((char*)args)>75)
764 PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
765 return true;
768 for (uint8 i = 0; i < strlen(args); i++)
770 if(!isalpha(args[i]) && args[i]!=' ')
772 SendSysMessage(LANG_CHARS_ONLY);
773 return false;
777 uint64 guid;
778 guid = m_session->GetPlayer()->GetSelection();
779 if (guid == 0)
781 SendSysMessage(LANG_NO_SELECTION);
782 return true;
785 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
787 if(!pCreature)
789 SendSysMessage(LANG_SELECT_CREATURE);
790 return true;
793 pCreature->SetName(args);
794 uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName());
795 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
797 pCreature->SaveToDB();
800 return true;
803 bool ChatHandler::HandleSubNameCommand(const char* /*args*/)
805 /* Temp. disabled
807 if(!*args)
808 args = "";
810 if(strlen((char*)args)>75)
813 PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
814 return true;
817 for (uint8 i = 0; i < strlen(args); i++)
819 if(!isalpha(args[i]) && args[i]!=' ')
821 SendSysMessage(LANG_CHARS_ONLY);
822 return false;
825 uint64 guid;
826 guid = m_session->GetPlayer()->GetSelection();
827 if (guid == 0)
829 SendSysMessage(LANG_NO_SELECTION);
830 return true;
833 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
835 if(!pCreature)
837 SendSysMessage(LANG_SELECT_CREATURE);
838 return true;
841 uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
842 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
844 pCreature->SaveToDB();
846 return true;
849 //move item to other slot
850 bool ChatHandler::HandleItemMoveCommand(const char* args)
852 if(!*args)
853 return false;
854 uint8 srcslot, dstslot;
856 char* pParam1 = strtok((char*)args, " ");
857 if (!pParam1)
858 return false;
860 char* pParam2 = strtok(NULL, " ");
861 if (!pParam2)
862 return false;
864 srcslot = (uint8)atoi(pParam1);
865 dstslot = (uint8)atoi(pParam2);
867 if(srcslot==dstslot)
868 return true;
870 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot))
871 return false;
873 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot))
874 return false;
876 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
877 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
879 m_session->GetPlayer()->SwapItem( src, dst );
881 return true;
884 //add spawn of creature
885 bool ChatHandler::HandleNpcAddCommand(const char* args)
887 if(!*args)
888 return false;
889 char* charID = strtok((char*)args, " ");
890 if (!charID)
891 return false;
893 char* team = strtok(NULL, " ");
894 int32 teamval = 0;
895 if (team) { teamval = atoi(team); }
896 if (teamval < 0) { teamval = 0; }
898 uint32 id = atoi(charID);
900 Player *chr = m_session->GetPlayer();
901 float x = chr->GetPositionX();
902 float y = chr->GetPositionY();
903 float z = chr->GetPositionZ();
904 float o = chr->GetOrientation();
905 Map *map = chr->GetMap();
907 Creature* pCreature = new Creature;
908 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, (uint32)teamval))
910 delete pCreature;
911 return false;
914 pCreature->Relocate(x,y,z,o);
916 if(!pCreature->IsPositionValid())
918 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());
919 delete pCreature;
920 return false;
923 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
925 uint32 db_guid = pCreature->GetDBTableGUIDLow();
927 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
928 pCreature->LoadFromDB(db_guid, map);
930 map->Add(pCreature);
931 objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid));
932 return true;
935 bool ChatHandler::HandleNpcDeleteCommand(const char* args)
937 Creature* unit = NULL;
939 if(*args)
941 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
942 char* cId = extractKeyFromLink((char*)args,"Hcreature");
943 if(!cId)
944 return false;
946 uint32 lowguid = atoi(cId);
947 if(!lowguid)
948 return false;
950 if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid))
951 unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
953 else
954 unit = getSelectedCreature();
956 if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle())
958 SendSysMessage(LANG_SELECT_CREATURE);
959 SetSentErrorMessage(true);
960 return false;
963 // Delete the creature
964 unit->CombatStop();
965 unit->DeleteFromDB();
966 unit->CleanupsBeforeDelete();
967 unit->AddObjectToRemoveList();
969 SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
971 return true;
974 //delete object by selection or guid
975 bool ChatHandler::HandleDelObjectCommand(const char* args)
977 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
978 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
979 if(!cId)
980 return false;
982 uint32 lowguid = atoi(cId);
983 if(!lowguid)
984 return false;
986 GameObject* obj = NULL;
988 // by DB guid
989 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
990 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
992 if(!obj)
994 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
995 SetSentErrorMessage(true);
996 return false;
999 uint64 owner_guid = obj->GetOwnerGUID();
1000 if(owner_guid)
1002 Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
1003 if(!owner && !IS_PLAYER_GUID(owner_guid))
1005 PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
1006 SetSentErrorMessage(true);
1007 return false;
1010 owner->RemoveGameObject(obj,false);
1013 obj->SetRespawnTime(0); // not save respawn time
1014 obj->Delete();
1015 obj->DeleteFromDB();
1017 PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
1019 return true;
1022 //turn selected object
1023 bool ChatHandler::HandleTurnObjectCommand(const char* args)
1025 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
1026 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1027 if(!cId)
1028 return false;
1030 uint32 lowguid = atoi(cId);
1031 if(!lowguid)
1032 return false;
1034 GameObject* obj = NULL;
1036 // by DB guid
1037 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1038 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1040 if(!obj)
1042 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1043 SetSentErrorMessage(true);
1044 return false;
1047 char* po = strtok(NULL, " ");
1048 float o;
1050 if (po)
1052 o = (float)atof(po);
1054 else
1056 Player *chr = m_session->GetPlayer();
1057 o = chr->GetOrientation();
1060 float rot2 = sin(o/2);
1061 float rot3 = cos(o/2);
1063 Map* map = obj->GetMap();
1064 map->Remove(obj,false);
1066 obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
1068 obj->SetFloatValue(GAMEOBJECT_FACING, o);
1069 obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2);
1070 obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3);
1072 map->Add(obj);
1074 obj->SaveToDB();
1075 obj->Refresh();
1077 PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o);
1079 return true;
1082 //move selected creature
1083 bool ChatHandler::HandleNpcMoveCommand(const char* args)
1085 uint32 lowguid = 0;
1087 Creature* pCreature = getSelectedCreature();
1089 if(!pCreature)
1091 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1092 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1093 if(!cId)
1094 return false;
1096 uint32 lowguid = atoi(cId);
1098 /* FIXME: impossibel without entry
1099 if(lowguid)
1100 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1103 // Attempting creature load from DB data
1104 if(!pCreature)
1106 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1107 if(!data)
1109 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1110 SetSentErrorMessage(true);
1111 return false;
1114 uint32 map_id = data->mapid;
1116 if(m_session->GetPlayer()->GetMapId()!=map_id)
1118 PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1119 SetSentErrorMessage(true);
1120 return false;
1123 else
1125 lowguid = pCreature->GetDBTableGUIDLow();
1128 else
1130 lowguid = pCreature->GetDBTableGUIDLow();
1133 float x = m_session->GetPlayer()->GetPositionX();
1134 float y = m_session->GetPlayer()->GetPositionY();
1135 float z = m_session->GetPlayer()->GetPositionZ();
1136 float o = m_session->GetPlayer()->GetOrientation();
1138 if (pCreature)
1140 if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1142 const_cast<CreatureData*>(data)->posX = x;
1143 const_cast<CreatureData*>(data)->posY = y;
1144 const_cast<CreatureData*>(data)->posZ = z;
1145 const_cast<CreatureData*>(data)->orientation = o;
1147 pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
1148 pCreature->GetMotionMaster()->Initialize();
1149 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1151 pCreature->setDeathState(JUST_DIED);
1152 pCreature->Respawn();
1156 WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1157 PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1158 return true;
1161 //move selected object
1162 bool ChatHandler::HandleMoveObjectCommand(const char* args)
1164 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
1165 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1166 if(!cId)
1167 return false;
1169 uint32 lowguid = atoi(cId);
1170 if(!lowguid)
1171 return false;
1173 GameObject* obj = NULL;
1175 // by DB guid
1176 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1177 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1179 if(!obj)
1181 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1182 SetSentErrorMessage(true);
1183 return false;
1186 char* px = strtok(NULL, " ");
1187 char* py = strtok(NULL, " ");
1188 char* pz = strtok(NULL, " ");
1190 if (!px)
1192 Player *chr = m_session->GetPlayer();
1194 Map* map = obj->GetMap();
1195 map->Remove(obj,false);
1197 obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
1198 obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX());
1199 obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY());
1200 obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ());
1202 map->Add(obj);
1204 else
1206 if(!py || !pz)
1207 return false;
1209 float x = (float)atof(px);
1210 float y = (float)atof(py);
1211 float z = (float)atof(pz);
1213 if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
1215 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
1216 SetSentErrorMessage(true);
1217 return false;
1220 Map* map = obj->GetMap();
1221 map->Remove(obj,false);
1223 obj->Relocate(x, y, z, obj->GetOrientation());
1224 obj->SetFloatValue(GAMEOBJECT_POS_X, x);
1225 obj->SetFloatValue(GAMEOBJECT_POS_Y, y);
1226 obj->SetFloatValue(GAMEOBJECT_POS_Z, z);
1228 map->Add(obj);
1231 obj->SaveToDB();
1232 obj->Refresh();
1234 PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow());
1236 return true;
1239 //demorph player or unit
1240 bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
1242 Unit *target = getSelectedUnit();
1243 if(!target)
1244 target = m_session->GetPlayer();
1247 // check online security
1248 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
1249 return false;
1251 target->DeMorph();
1253 return true;
1256 //add item in vendorlist
1257 bool ChatHandler::HandleAddVendorItemCommand(const char* args)
1259 if (!*args)
1260 return false;
1262 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1263 if (!pitem)
1265 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1266 SetSentErrorMessage(true);
1267 return false;
1270 uint32 itemId = atol(pitem);
1272 char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
1273 uint32 maxcount = 0;
1274 if (fmaxcount)
1275 maxcount = atol(fmaxcount);
1277 char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
1278 uint32 incrtime = 0;
1279 if (fincrtime)
1280 incrtime = atol(fincrtime);
1282 char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
1283 uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1285 Creature* vendor = getSelectedCreature();
1287 uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1289 if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1291 SetSentErrorMessage(true);
1292 return false;
1295 objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1297 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1299 PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1300 return true;
1303 //del item from vendor list
1304 bool ChatHandler::HandleDelVendorItemCommand(const char* args)
1306 if (!*args)
1307 return false;
1309 Creature* vendor = getSelectedCreature();
1310 if (!vendor || !vendor->isVendor())
1312 SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1313 SetSentErrorMessage(true);
1314 return false;
1317 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1318 if (!pitem)
1320 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1321 SetSentErrorMessage(true);
1322 return false;
1324 uint32 itemId = atol(pitem);
1326 if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1328 PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1329 SetSentErrorMessage(true);
1330 return false;
1333 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1335 PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1336 return true;
1339 //add move for creature
1340 bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
1342 if(!*args)
1343 return false;
1345 char* guid_str = strtok((char*)args, " ");
1346 char* wait_str = strtok((char*)NULL, " ");
1348 uint32 lowguid = atoi((char*)guid_str);
1350 Creature* pCreature = NULL;
1352 /* FIXME: impossible without entry
1353 if(lowguid)
1354 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1357 // attempt check creature existence by DB data
1358 if(!pCreature)
1360 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1361 if(!data)
1363 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1364 SetSentErrorMessage(true);
1365 return false;
1368 else
1370 // obtain real GUID for DB operations
1371 lowguid = pCreature->GetDBTableGUIDLow();
1374 int wait = wait_str ? atoi(wait_str) : 0;
1376 if(wait < 0)
1377 wait = 0;
1379 Player* player = m_session->GetPlayer();
1381 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1383 // update movement type
1384 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1385 if(pCreature)
1387 pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1388 pCreature->GetMotionMaster()->Initialize();
1389 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1391 pCreature->setDeathState(JUST_DIED);
1392 pCreature->Respawn();
1394 pCreature->SaveToDB();
1397 SendSysMessage(LANG_WAYPOINT_ADDED);
1399 return true;
1403 * Set the movement type for an NPC.<br/>
1404 * <br/>
1405 * Valid movement types are:
1406 * <ul>
1407 * <li> stay - NPC wont move </li>
1408 * <li> random - NPC will move randomly according to the spawndist </li>
1409 * <li> way - NPC will move with given waypoints set </li>
1410 * </ul>
1411 * additional parameter: NODEL - so no waypoints are deleted, if you
1412 * change the movement type
1414 bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
1416 if(!*args)
1417 return false;
1419 // 3 arguments:
1420 // GUID (optional - you can also select the creature)
1421 // stay|random|way (determines the kind of movement)
1422 // NODEL (optional - tells the system NOT to delete any waypoints)
1423 // this is very handy if you want to do waypoints, that are
1424 // later switched on/off according to special events (like escort
1425 // quests, etc)
1426 char* guid_str = strtok((char*)args, " ");
1427 char* type_str = strtok((char*)NULL, " ");
1428 char* dontdel_str = strtok((char*)NULL, " ");
1430 bool doNotDelete = false;
1432 if(!guid_str)
1433 return false;
1435 uint32 lowguid = 0;
1436 Creature* pCreature = NULL;
1438 if( dontdel_str )
1440 //sLog.outError("DEBUG: All 3 params are set");
1442 // All 3 params are set
1443 // GUID
1444 // type
1445 // doNotDEL
1446 if( stricmp( dontdel_str, "NODEL" ) == 0 )
1448 //sLog.outError("DEBUG: doNotDelete = true;");
1449 doNotDelete = true;
1452 else
1454 // Only 2 params - but maybe NODEL is set
1455 if( type_str )
1457 sLog.outError("DEBUG: Only 2 params ");
1458 if( stricmp( type_str, "NODEL" ) == 0 )
1460 //sLog.outError("DEBUG: type_str, NODEL ");
1461 doNotDelete = true;
1462 type_str = NULL;
1467 if(!type_str) // case .setmovetype $move_type (with selected creature)
1469 type_str = guid_str;
1470 pCreature = getSelectedCreature();
1471 if(!pCreature || pCreature->isPet())
1472 return false;
1473 lowguid = pCreature->GetDBTableGUIDLow();
1475 else // case .setmovetype #creature_guid $move_type (with selected creature)
1477 lowguid = atoi((char*)guid_str);
1479 /* impossible without entry
1480 if(lowguid)
1481 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1484 // attempt check creature existence by DB data
1485 if(!pCreature)
1487 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1488 if(!data)
1490 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1491 SetSentErrorMessage(true);
1492 return false;
1495 else
1497 lowguid = pCreature->GetDBTableGUIDLow();
1501 // now lowguid is low guid really existed creature
1502 // and pCreature point (maybe) to this creature or NULL
1504 MovementGeneratorType move_type;
1506 std::string type = type_str;
1508 if(type == "stay")
1509 move_type = IDLE_MOTION_TYPE;
1510 else if(type == "random")
1511 move_type = RANDOM_MOTION_TYPE;
1512 else if(type == "way")
1513 move_type = WAYPOINT_MOTION_TYPE;
1514 else
1515 return false;
1517 // update movement type
1518 if(doNotDelete == false)
1519 WaypointMgr.DeletePath(lowguid);
1521 if(pCreature)
1523 pCreature->SetDefaultMovementType(move_type);
1524 pCreature->GetMotionMaster()->Initialize();
1525 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1527 pCreature->setDeathState(JUST_DIED);
1528 pCreature->Respawn();
1530 pCreature->SaveToDB();
1532 if( doNotDelete == false )
1534 PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1536 else
1538 PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1541 return true;
1542 } // HandleNpcSetMoveTypeCommand
1544 //change level of creature or pet
1545 bool ChatHandler::HandleChangeLevelCommand(const char* args)
1547 if (!*args)
1548 return false;
1550 uint8 lvl = (uint8) atoi((char*)args);
1551 if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3)
1553 SendSysMessage(LANG_BAD_VALUE);
1554 SetSentErrorMessage(true);
1555 return false;
1558 Creature* pCreature = getSelectedCreature();
1559 if(!pCreature)
1561 SendSysMessage(LANG_SELECT_CREATURE);
1562 SetSentErrorMessage(true);
1563 return false;
1566 if(pCreature->isPet())
1568 ((Pet*)pCreature)->GivePetLevel(lvl);
1570 else
1572 pCreature->SetMaxHealth( 100 + 30*lvl);
1573 pCreature->SetHealth( 100 + 30*lvl);
1574 pCreature->SetLevel( lvl);
1575 pCreature->SaveToDB();
1578 return true;
1581 //set npcflag of creature
1582 bool ChatHandler::HandleNpcFlagCommand(const char* args)
1584 if (!*args)
1585 return false;
1587 uint32 npcFlags = (uint32) atoi((char*)args);
1589 Creature* pCreature = getSelectedCreature();
1591 if(!pCreature)
1593 SendSysMessage(LANG_SELECT_CREATURE);
1594 SetSentErrorMessage(true);
1595 return false;
1598 pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1600 WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1602 SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1604 return true;
1607 //set model of creature
1608 bool ChatHandler::HandleNpcSetModelCommand(const char* args)
1610 if (!*args)
1611 return false;
1613 uint32 displayId = (uint32) atoi((char*)args);
1615 Creature *pCreature = getSelectedCreature();
1617 if(!pCreature || pCreature->isPet())
1619 SendSysMessage(LANG_SELECT_CREATURE);
1620 SetSentErrorMessage(true);
1621 return false;
1624 pCreature->SetDisplayId(displayId);
1625 pCreature->SetNativeDisplayId(displayId);
1627 pCreature->SaveToDB();
1629 return true;
1632 //morph creature or player
1633 bool ChatHandler::HandleMorphCommand(const char* args)
1635 if (!*args)
1636 return false;
1638 uint16 display_id = (uint16)atoi((char*)args);
1640 Unit *target = getSelectedUnit();
1641 if(!target)
1642 target = m_session->GetPlayer();
1644 // check online security
1645 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
1646 return false;
1648 target->SetDisplayId(display_id);
1650 return true;
1653 //set faction of creature
1654 bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
1656 if (!*args)
1657 return false;
1659 uint32 factionId = (uint32) atoi((char*)args);
1661 if (!sFactionTemplateStore.LookupEntry(factionId))
1663 PSendSysMessage(LANG_WRONG_FACTION, factionId);
1664 SetSentErrorMessage(true);
1665 return false;
1668 Creature* pCreature = getSelectedCreature();
1670 if(!pCreature)
1672 SendSysMessage(LANG_SELECT_CREATURE);
1673 SetSentErrorMessage(true);
1674 return false;
1677 pCreature->setFaction(factionId);
1679 // faction is set in creature_template - not inside creature
1681 // update in memory
1682 if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1684 const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1685 const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1688 // and DB
1689 WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1691 return true;
1694 //kick player
1695 bool ChatHandler::HandleKickPlayerCommand(const char *args)
1697 char* kickName = strtok((char*)args, " ");
1698 if (!kickName)
1700 Player* player = getSelectedPlayer();
1702 if(!player)
1704 SendSysMessage(LANG_NO_CHAR_SELECTED);
1705 SetSentErrorMessage(true);
1706 return false;
1709 if(player==m_session->GetPlayer())
1711 SendSysMessage(LANG_COMMAND_KICKSELF);
1712 SetSentErrorMessage(true);
1713 return false;
1716 // check online security
1717 if (HasLowerSecurity(player, 0))
1718 return false;
1720 player->GetSession()->KickPlayer();
1722 else
1724 std::string name = kickName;
1725 if(!normalizePlayerName(name))
1727 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1728 SetSentErrorMessage(true);
1729 return false;
1732 if(m_session && name==m_session->GetPlayer()->GetName())
1734 SendSysMessage(LANG_COMMAND_KICKSELF);
1735 SetSentErrorMessage(true);
1736 return false;
1739 // check online security
1740 Player* player = ObjectAccessor::Instance().FindPlayerByName(name.c_str());
1741 if (player && HasLowerSecurity(player, 0))
1742 return false;
1744 if(sWorld.KickPlayer(name))
1746 PSendSysMessage(LANG_COMMAND_KICKMESSAGE,name.c_str());
1748 else
1749 PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,name.c_str());
1752 return true;
1755 //show info of player
1756 bool ChatHandler::HandlePInfoCommand(const char* args)
1758 Player* target = NULL;
1759 uint64 targetGUID = 0;
1761 char* px = strtok((char*)args, " ");
1762 char* py = NULL;
1764 std::string name;
1766 if (px)
1768 name = px;
1770 if(name.empty())
1771 return false;
1773 if(!normalizePlayerName(name))
1775 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1776 SetSentErrorMessage(true);
1777 return false;
1780 target = objmgr.GetPlayer(name.c_str());
1781 if (target)
1782 py = strtok(NULL, " ");
1783 else
1785 targetGUID = objmgr.GetPlayerGUIDByName(name);
1786 if(targetGUID)
1787 py = strtok(NULL, " ");
1788 else
1789 py = px;
1793 if(!target && !targetGUID)
1795 target = getSelectedPlayer();
1798 if(!target && !targetGUID)
1800 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1801 SetSentErrorMessage(true);
1802 return false;
1805 uint32 accId = 0;
1806 uint32 money = 0;
1807 uint32 total_player_time = 0;
1808 uint32 level = 0;
1809 uint32 latency = 0;
1811 // get additional information from Player object
1812 if(target)
1814 // check online security
1815 if (HasLowerSecurity(target, 0))
1816 return false;
1818 targetGUID = target->GetGUID();
1819 name = target->GetName(); // re-read for case getSelectedPlayer() target
1820 accId = target->GetSession()->GetAccountId();
1821 money = target->GetMoney();
1822 total_player_time = target->GetTotalPlayedTime();
1823 level = target->getLevel();
1824 latency = target->GetSession()->GetLatency();
1826 // get additional information from DB
1827 else
1829 // check offline security
1830 if (HasLowerSecurity(NULL, targetGUID))
1831 return false;
1833 // 0
1834 QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID));
1835 if (!result)
1837 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1838 SetSentErrorMessage(true);
1839 return false;
1841 Field *fields = result->Fetch();
1842 total_player_time = fields[0].GetUInt32();
1843 delete result;
1845 Tokens data;
1846 if (!Player::LoadValuesArrayFromDB(data,targetGUID))
1848 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1849 SetSentErrorMessage(true);
1850 return false;
1853 money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE);
1854 level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL);
1856 accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
1859 std::string username = GetMangosString(LANG_ERROR);
1860 std::string last_ip = GetMangosString(LANG_ERROR);
1861 uint32 security = 0;
1862 std::string last_login = GetMangosString(LANG_ERROR);
1864 QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
1865 if(result)
1867 Field* fields = result->Fetch();
1868 username = fields[0].GetCppString();
1869 security = fields[1].GetUInt32();
1871 if(!m_session || m_session->GetSecurity() >= security)
1873 last_ip = fields[2].GetCppString();
1874 last_login = fields[3].GetCppString();
1876 else
1878 last_ip = "-";
1879 last_login = "-";
1882 delete result;
1885 PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetMangosString(LANG_OFFLINE)), name.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency);
1887 std::string timeStr = secsToTimeString(total_player_time,true,true);
1888 uint32 gold = money /GOLD;
1889 uint32 silv = (money % GOLD) / SILVER;
1890 uint32 copp = (money % GOLD) % SILVER;
1891 PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp );
1893 if ( py && strncmp(py, "rep", 3) == 0 )
1895 if(!target)
1897 // rep option not implemented for offline case
1898 SendSysMessage(LANG_PINFO_NO_REP);
1899 SetSentErrorMessage(true);
1900 return false;
1903 char* FactionName;
1904 for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr)
1906 FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
1907 if (factionEntry)
1908 FactionName = factionEntry->name[m_session->GetSessionDbcLocale()];
1909 else
1910 FactionName = "#Not found#";
1911 ReputationRank rank = target->GetReputationRank(factionEntry);
1912 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
1913 std::ostringstream ss;
1914 ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << FactionName << "]|h|r " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
1916 if(itr->second.Flags & FACTION_FLAG_VISIBLE)
1917 ss << GetMangosString(LANG_FACTION_VISIBLE);
1918 if(itr->second.Flags & FACTION_FLAG_AT_WAR)
1919 ss << GetMangosString(LANG_FACTION_ATWAR);
1920 if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
1921 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
1922 if(itr->second.Flags & FACTION_FLAG_HIDDEN)
1923 ss << GetMangosString(LANG_FACTION_HIDDEN);
1924 if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
1925 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
1926 if(itr->second.Flags & FACTION_FLAG_INACTIVE)
1927 ss << GetMangosString(LANG_FACTION_INACTIVE);
1929 SendSysMessage(ss.str().c_str());
1932 return true;
1935 //show tickets
1936 void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
1938 std::string name;
1939 if(!objmgr.GetPlayerNameByGUID(guid,name))
1940 name = GetMangosString(LANG_UNKNOWN);
1942 PSendSysMessage(LANG_COMMAND_TICKETVIEW, name.c_str(),time,text);
1945 //ticket commands
1946 bool ChatHandler::HandleTicketCommand(const char* args)
1948 char* px = strtok((char*)args, " ");
1950 // ticket<end>
1951 if (!px)
1953 if(!m_session)
1955 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1956 SetSentErrorMessage(true);
1957 return false;
1960 size_t count = ticketmgr.GetTicketCount();
1962 bool accept = m_session->GetPlayer()->isAcceptTickets();
1964 PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
1965 return true;
1968 // ticket on
1969 if(strncmp(px,"on",3) == 0)
1971 if(!m_session)
1973 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1974 SetSentErrorMessage(true);
1975 return false;
1978 m_session->GetPlayer()->SetAcceptTicket(true);
1979 SendSysMessage(LANG_COMMAND_TICKETON);
1980 return true;
1983 // ticket off
1984 if(strncmp(px,"off",4) == 0)
1986 if(!m_session)
1988 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1989 SetSentErrorMessage(true);
1990 return false;
1993 m_session->GetPlayer()->SetAcceptTicket(false);
1994 SendSysMessage(LANG_COMMAND_TICKETOFF);
1995 return true;
1998 // ticket #num
1999 int num = atoi(px);
2000 if(num > 0)
2002 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
2004 if(!result)
2006 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2007 SetSentErrorMessage(true);
2008 return false;
2011 Field* fields = result->Fetch();
2013 uint32 guid = fields[0].GetUInt32();
2014 char const* text = fields[1].GetString();
2015 char const* time = fields[2].GetString();
2017 ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
2018 delete result;
2019 return true;
2022 std::string name = px;
2024 if(!normalizePlayerName(name))
2026 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2027 SetSentErrorMessage(true);
2028 return false;
2031 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2033 if(!guid)
2034 return false;
2036 // ticket $char_name
2037 GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(guid));
2038 if(!ticket)
2039 return false;
2041 std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
2043 ShowTicket(guid, ticket->GetText(), time.c_str());
2045 return true;
2048 //dell all tickets
2049 bool ChatHandler::HandleDelTicketCommand(const char *args)
2051 char* px = strtok((char*)args, " ");
2052 if (!px)
2053 return false;
2055 // delticket all
2056 if(strncmp(px,"all",4) == 0)
2058 ticketmgr.DeleteAll();
2059 SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2060 return true;
2063 int num = (uint32)atoi(px);
2065 // delticket #num
2066 if(num > 0)
2068 QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2069 if(!result)
2071 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2072 SetSentErrorMessage(true);
2073 return false;
2075 Field* fields = result->Fetch();
2076 uint32 guid = fields[0].GetUInt32();
2077 delete result;
2079 ticketmgr.Delete(guid);
2081 //notify player
2082 if(Player* pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)))
2084 pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
2085 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, pl->GetName());
2087 else
2088 PSendSysMessage(LANG_COMMAND_TICKETDEL);
2090 return true;
2093 std::string name = px;
2095 if(!normalizePlayerName(name))
2097 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2098 SetSentErrorMessage(true);
2099 return false;
2102 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2104 if(!guid)
2105 return false;
2107 // delticket $char_name
2108 ticketmgr.Delete(GUID_LOPART(guid));
2110 // notify players about ticket deleting
2111 if(Player* sender = objmgr.GetPlayer(guid))
2112 sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2114 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,px);
2115 return true;
2118 //set spawn dist of creature
2119 bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
2121 if(!*args)
2122 return false;
2124 float option = atof((char*)args);
2125 if (option < 0.0f)
2127 SendSysMessage(LANG_BAD_VALUE);
2128 return false;
2131 MovementGeneratorType mtype = IDLE_MOTION_TYPE;
2132 if (option >0.0f)
2133 mtype = RANDOM_MOTION_TYPE;
2135 Creature *pCreature = getSelectedCreature();
2136 uint32 u_guidlow = 0;
2138 if (pCreature)
2139 u_guidlow = pCreature->GetDBTableGUIDLow();
2140 else
2141 return false;
2143 pCreature->SetRespawnRadius((float)option);
2144 pCreature->SetDefaultMovementType(mtype);
2145 pCreature->GetMotionMaster()->Initialize();
2146 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
2148 pCreature->setDeathState(JUST_DIED);
2149 pCreature->Respawn();
2152 WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
2153 PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
2154 return true;
2157 bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
2159 if(!*args)
2160 return false;
2162 char* stime = strtok((char*)args, " ");
2164 if (!stime)
2165 return false;
2167 int i_stime = atoi((char*)stime);
2169 if (i_stime < 0)
2171 SendSysMessage(LANG_BAD_VALUE);
2172 SetSentErrorMessage(true);
2173 return false;
2176 Creature *pCreature = getSelectedCreature();
2177 uint32 u_guidlow = 0;
2179 if (pCreature)
2180 u_guidlow = pCreature->GetDBTableGUIDLow();
2181 else
2182 return false;
2184 WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
2185 pCreature->SetRespawnDelay((uint32)i_stime);
2186 PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
2188 return true;
2192 * Add a waypoint to a creature.
2194 * The user can either select an npc or provide its GUID.
2196 * The user can even select a visual waypoint - then the new waypoint
2197 * is placed *after* the selected one - this makes insertion of new
2198 * waypoints possible.
2200 * eg:
2201 * .wp add 12345
2202 * -> adds a waypoint to the npc with the GUID 12345
2204 * .wp add
2205 * -> adds a waypoint to the currently selected creature
2208 * @param args if the user did not provide a GUID, it is NULL
2210 * @return true - command did succeed, false - something went wrong
2212 bool ChatHandler::HandleWpAddCommand(const char* args)
2214 sLog.outDebug("DEBUG: HandleWpAddCommand");
2216 // optional
2217 char* guid_str = NULL;
2219 if(*args)
2221 guid_str = strtok((char*)args, " ");
2224 uint32 lowguid = 0;
2225 uint32 point = 0;
2226 Creature* target = getSelectedCreature();
2227 // Did player provide a GUID?
2228 if (!guid_str)
2230 sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2232 // No GUID provided
2233 // -> Player must have selected a creature
2235 if(!target || target->isPet())
2237 SendSysMessage(LANG_SELECT_CREATURE);
2238 SetSentErrorMessage(true);
2239 return false;
2241 if (target->GetEntry() == VISUAL_WAYPOINT )
2243 sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2245 QueryResult *result =
2246 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2247 target->GetGUIDLow() );
2248 if(!result)
2250 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2251 // User selected a visual spawnpoint -> get the NPC
2252 // Select NPC GUID
2253 // Since we compare float values, we have to deal with
2254 // some difficulties.
2255 // Here we search for all waypoints that only differ in one from 1 thousand
2256 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2257 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2258 const char* maxDIFF = "0.01";
2259 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 )",
2260 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2261 if(!result)
2263 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2264 SetSentErrorMessage(true);
2265 return false;
2270 Field *fields = result->Fetch();
2271 lowguid = fields[0].GetUInt32();
2272 point = fields[1].GetUInt32();
2273 }while( result->NextRow() );
2274 delete result;
2276 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2277 if(!data)
2279 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2280 SetSentErrorMessage(true);
2281 return false;
2284 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2285 if(!target)
2287 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2288 SetSentErrorMessage(true);
2289 return false;
2292 else
2294 lowguid = target->GetDBTableGUIDLow();
2297 else
2299 sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2301 // GUID provided
2302 // Warn if player also selected a creature
2303 // -> Creature selection is ignored <-
2304 if(target)
2306 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2308 lowguid = atoi((char*)guid_str);
2310 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2311 if(!data)
2313 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2314 SetSentErrorMessage(true);
2315 return false;
2318 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2319 if(!target || target->isPet())
2321 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2322 SetSentErrorMessage(true);
2323 return false;
2326 // lowguid -> GUID of the NPC
2327 // point -> number of the waypoint (if not 0)
2328 sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2330 sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2332 Player* player = m_session->GetPlayer();
2333 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2335 // update movement type
2336 if(target)
2338 target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2339 target->GetMotionMaster()->Initialize();
2340 if(target->isAlive()) // dead creature will reset movement generator at respawn
2342 target->setDeathState(JUST_DIED);
2343 target->Respawn();
2345 target->SaveToDB();
2347 else
2348 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2350 PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2352 return true;
2353 } // HandleWpAddCommand
2356 * .wp modify emote | spell | text | del | move | add
2358 * add -> add a WP after the selected visual waypoint
2359 * User must select a visual waypoint and then issue ".wp modify add"
2361 * emote <emoteID>
2362 * User has selected a visual waypoint before.
2363 * <emoteID> is added to this waypoint. Everytime the
2364 * NPC comes to this waypoint, the emote is called.
2366 * emote <GUID> <WPNUM> <emoteID>
2367 * User has not selected visual waypoint before.
2368 * For the waypoint <WPNUM> for the NPC with <GUID>
2369 * an emote <emoteID> is added.
2370 * Everytime the NPC comes to this waypoint, the emote is called.
2373 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2375 bool ChatHandler::HandleWpModifyCommand(const char* args)
2377 sLog.outDebug("DEBUG: HandleWpModifyCommand");
2379 if(!*args)
2380 return false;
2382 // first arg: add del text emote spell waittime move
2383 char* show_str = strtok((char*)args, " ");
2384 if (!show_str)
2386 return false;
2389 std::string show = show_str;
2390 // Check
2391 // Remember: "show" must also be the name of a column!
2392 if( (show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2")
2393 && (show != "textid3") && (show != "textid4") && (show != "textid5")
2394 && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2395 && (show != "model1") && (show != "model2") && (show != "orientation"))
2397 return false;
2400 // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2402 // Did user provide a GUID
2403 // or did the user select a creature?
2404 // -> variable lowguid is filled with the GUID of the NPC
2405 uint32 lowguid = 0;
2406 uint32 point = 0;
2407 uint32 wpGuid = 0;
2408 Creature* target = getSelectedCreature();
2410 if(target)
2412 sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2414 // Did the user select a visual spawnpoint?
2415 if (target->GetEntry() != VISUAL_WAYPOINT )
2417 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2418 SetSentErrorMessage(true);
2419 return false;
2422 wpGuid = target->GetGUIDLow();
2424 // The visual waypoint
2425 QueryResult *result =
2426 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2427 target->GetGUIDLow() );
2428 if(!result)
2430 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2431 SetSentErrorMessage(true);
2432 return false;
2434 sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2436 Field *fields = result->Fetch();
2437 lowguid = fields[0].GetUInt32();
2438 point = fields[1].GetUInt32();
2440 // Cleanup memory
2441 sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2442 delete result;
2444 else
2446 // User did provide <GUID> <WPNUM>
2448 char* guid_str = strtok((char*)NULL, " ");
2449 if( !guid_str )
2451 SendSysMessage(LANG_WAYPOINT_NOGUID);
2452 return false;
2454 lowguid = atoi((char*)guid_str);
2456 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2457 if(!data)
2459 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2460 SetSentErrorMessage(true);
2461 return false;
2464 PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2466 char* point_str = strtok((char*)NULL, " ");
2467 if( !point_str )
2469 SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2470 return false;
2472 point = atoi((char*)point_str);
2474 PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2476 // Now we need the GUID of the visual waypoint
2477 // -> "del", "move", "add" command
2479 QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2480 if (!result)
2482 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2483 SetSentErrorMessage(true);
2484 return false;
2487 Field *fields = result->Fetch();
2488 wpGuid = fields[0].GetUInt32();
2490 // Free memory
2491 delete result;
2494 char* arg_str = NULL;
2495 // Check for argument
2496 if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2498 // Text is enclosed in "<>", all other arguments not
2499 if( show.find("text") != std::string::npos )
2500 arg_str = strtok((char*)NULL, "<>");
2501 else
2502 arg_str = strtok((char*)NULL, " ");
2504 if( !arg_str)
2506 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2507 return false;
2511 sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2513 // wpGuid -> GUID of the waypoint creature
2514 // lowguid -> GUID of the NPC
2515 // point -> waypoint number
2517 // Special functions:
2518 // add - move - del -> no args commands
2519 // Add a waypoint after the selected visual
2520 if(show == "add" && target)
2522 PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2524 // Get the creature for which we read the waypoint
2525 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2526 if(!data)
2528 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2529 SetSentErrorMessage(true);
2530 return false;
2533 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2535 if( !npcCreature )
2537 PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2538 SetSentErrorMessage(true);
2539 return false;
2542 sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2544 // What to do:
2545 // Add the visual spawnpoint (DB only)
2546 // Adjust the waypoints
2547 // Respawn the owner of the waypoints
2548 sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2550 Player* chr = m_session->GetPlayer();
2551 Map *map = chr->GetMap();
2553 if(npcCreature)
2555 npcCreature->GetMotionMaster()->Initialize();
2556 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2558 npcCreature->setDeathState(JUST_DIED);
2559 npcCreature->Respawn();
2563 // create the waypoint creature
2564 wpGuid = 0;
2565 Creature* wpCreature = new Creature;
2566 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map,VISUAL_WAYPOINT,0))
2568 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2569 delete wpCreature;
2571 else
2573 wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2575 if(!wpCreature->IsPositionValid())
2577 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());
2578 delete wpCreature;
2580 else
2582 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2583 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2584 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2585 map->Add(wpCreature);
2586 wpGuid = wpCreature->GetGUIDLow();
2590 WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2592 if(!wpGuid)
2593 return false;
2595 PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2596 return true;
2597 } // add
2599 if(show == "del" && target)
2601 PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2603 // Get the creature for which we read the waypoint
2604 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2605 if(!data)
2607 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2608 SetSentErrorMessage(true);
2609 return false;
2612 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2614 // wpCreature
2615 Creature* wpCreature = NULL;
2616 if( wpGuid != 0 )
2618 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2619 wpCreature->DeleteFromDB();
2620 wpCreature->CleanupsBeforeDelete();
2621 wpCreature->AddObjectToRemoveList();
2624 // What to do:
2625 // Remove the visual spawnpoint
2626 // Adjust the waypoints
2627 // Respawn the owner of the waypoints
2629 WaypointMgr.DeleteNode(lowguid, point);
2631 if(npcCreature)
2633 // Any waypoints left?
2634 QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2635 if(!result2)
2637 npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2639 else
2641 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2642 delete result2;
2644 npcCreature->GetMotionMaster()->Initialize();
2645 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2647 npcCreature->setDeathState(JUST_DIED);
2648 npcCreature->Respawn();
2650 npcCreature->SaveToDB();
2653 PSendSysMessage(LANG_WAYPOINT_REMOVED);
2654 return true;
2655 } // del
2657 if(show == "move" && target)
2659 PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2661 Player *chr = m_session->GetPlayer();
2662 Map *map = chr->GetMap();
2664 // Get the creature for which we read the waypoint
2665 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2666 if(!data)
2668 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2669 SetSentErrorMessage(true);
2670 return false;
2673 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2675 // wpCreature
2676 Creature* wpCreature = NULL;
2677 // What to do:
2678 // Move the visual spawnpoint
2679 // Respawn the owner of the waypoints
2680 if( wpGuid != 0 )
2682 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2683 wpCreature->DeleteFromDB();
2684 wpCreature->CleanupsBeforeDelete();
2685 wpCreature->AddObjectToRemoveList();
2686 // re-create
2687 Creature* wpCreature2 = new Creature;
2688 if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0))
2690 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2691 delete wpCreature2;
2692 return false;
2695 wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2697 if(!wpCreature2->IsPositionValid())
2699 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());
2700 delete wpCreature2;
2701 return false;
2704 wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2705 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2706 wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2707 map->Add(wpCreature2);
2708 //npcCreature->GetMap()->Add(wpCreature2);
2711 WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2713 if(npcCreature)
2715 npcCreature->GetMotionMaster()->Initialize();
2716 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2718 npcCreature->setDeathState(JUST_DIED);
2719 npcCreature->Respawn();
2722 PSendSysMessage(LANG_WAYPOINT_CHANGED);
2724 return true;
2725 } // move
2727 // Create creature - npc that has the waypoint
2728 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2729 if(!data)
2731 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2732 SetSentErrorMessage(true);
2733 return false;
2736 // set in game textids not supported
2737 if( show == "textid1" || show == "textid2" || show == "textid3" ||
2738 show == "textid4" || show == "textid5" )
2740 return false;
2743 WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2745 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2746 if(npcCreature)
2748 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2749 npcCreature->GetMotionMaster()->Initialize();
2750 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2752 npcCreature->setDeathState(JUST_DIED);
2753 npcCreature->Respawn();
2756 PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2758 return true;
2762 * .wp show info | on | off
2764 * info -> User has selected a visual waypoint before
2766 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2767 * provided the GUID of the NPC and the number of
2768 * the waypoint.
2770 * on -> User has selected an NPC; all visual waypoints for this
2771 * NPC are added to the world
2773 * on <GUID> -> User did not select an NPC - instead the GUID of the
2774 * NPC is provided. All visual waypoints for this NPC
2775 * are added from the world.
2777 * off -> User has selected an NPC; all visual waypoints for this
2778 * NPC are removed from the world.
2780 * on <GUID> -> User did not select an NPC - instead the GUID of the
2781 * NPC is provided. All visual waypoints for this NPC
2782 * are removed from the world.
2786 bool ChatHandler::HandleWpShowCommand(const char* args)
2788 sLog.outDebug("DEBUG: HandleWpShowCommand");
2790 if(!*args)
2791 return false;
2793 // first arg: on, off, first, last
2794 char* show_str = strtok((char*)args, " ");
2795 if (!show_str)
2797 return false;
2799 // second arg: GUID (optional, if a creature is selected)
2800 char* guid_str = strtok((char*)NULL, " ");
2801 sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
2802 //if (!guid_str) {
2803 // return false;
2806 // Did user provide a GUID
2807 // or did the user select a creature?
2808 // -> variable lowguid is filled with the GUID
2809 Creature* target = getSelectedCreature();
2810 // Did player provide a GUID?
2811 if (!guid_str)
2813 sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
2814 // No GUID provided
2815 // -> Player must have selected a creature
2817 if(!target)
2819 SendSysMessage(LANG_SELECT_CREATURE);
2820 SetSentErrorMessage(true);
2821 return false;
2824 else
2826 sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
2827 // GUID provided
2828 // Warn if player also selected a creature
2829 // -> Creature selection is ignored <-
2830 if(target)
2832 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2835 uint32 lowguid = atoi((char*)guid_str);
2837 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2838 if(!data)
2840 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2841 SetSentErrorMessage(true);
2842 return false;
2845 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2847 if(!target)
2849 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2850 SetSentErrorMessage(true);
2851 return false;
2855 uint32 lowguid = target->GetDBTableGUIDLow();
2857 std::string show = show_str;
2858 uint32 Maxpoint;
2860 sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
2862 // Show info for the selected waypoint
2863 if(show == "info")
2865 PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
2867 // Check if the user did specify a visual waypoint
2868 if( target->GetEntry() != VISUAL_WAYPOINT )
2870 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2871 SetSentErrorMessage(true);
2872 return false;
2875 //PSendSysMessage("wp on, GUID: %u", lowguid);
2877 //pCreature->GetPositionX();
2879 QueryResult *result =
2880 WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u",
2881 target->GetGUIDLow() );
2882 if(!result)
2884 // Since we compare float values, we have to deal with
2885 // some difficulties.
2886 // Here we search for all waypoints that only differ in one from 1 thousand
2887 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2888 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2889 const char* maxDIFF = "0.01";
2890 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
2892 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 )",
2893 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2894 if(!result)
2896 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2897 SetSentErrorMessage(true);
2898 return false;
2903 Field *fields = result->Fetch();
2904 uint32 creGUID = fields[0].GetUInt32();
2905 uint32 point = fields[1].GetUInt32();
2906 int waittime = fields[2].GetUInt32();
2907 uint32 emote = fields[3].GetUInt32();
2908 uint32 spell = fields[4].GetUInt32();
2909 uint32 textid[MAX_WAYPOINT_TEXT];
2910 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
2911 textid[i] = fields[5+i].GetUInt32();
2912 uint32 model1 = fields[10].GetUInt32();
2913 uint32 model2 = fields[11].GetUInt32();
2915 // Get the creature for which we read the waypoint
2916 Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2918 PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
2919 PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
2920 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
2921 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
2922 PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
2923 PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
2924 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
2925 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i+1, textid[i], (textid[i] ? GetMangosString(textid[i]) : ""));
2927 }while( result->NextRow() );
2928 // Cleanup memory
2929 delete result;
2930 return true;
2933 if(show == "on")
2935 PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
2937 QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
2938 if(!result)
2940 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
2941 SetSentErrorMessage(true);
2942 return false;
2944 // Delete all visuals for this NPC
2945 QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
2946 if(result2)
2948 bool hasError = false;
2951 Field *fields = result2->Fetch();
2952 uint32 wpguid = fields[0].GetUInt32();
2953 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2955 if(!pCreature)
2957 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
2958 hasError = true;
2959 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
2961 else
2963 pCreature->DeleteFromDB();
2964 pCreature->CleanupsBeforeDelete();
2965 pCreature->AddObjectToRemoveList();
2968 }while( result2->NextRow() );
2969 delete result2;
2970 if( hasError )
2972 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
2973 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
2974 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
2980 Field *fields = result->Fetch();
2981 uint32 point = fields[0].GetUInt32();
2982 float x = fields[1].GetFloat();
2983 float y = fields[2].GetFloat();
2984 float z = fields[3].GetFloat();
2986 uint32 id = VISUAL_WAYPOINT;
2988 Player *chr = m_session->GetPlayer();
2989 Map *map = chr->GetMap();
2990 float o = chr->GetOrientation();
2992 Creature* wpCreature = new Creature;
2993 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
2995 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
2996 delete wpCreature;
2997 delete result;
2998 return false;
3001 wpCreature->Relocate(x, y, z, o);
3003 if(!wpCreature->IsPositionValid())
3005 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());
3006 delete wpCreature;
3007 delete result;
3008 return false;
3011 wpCreature->SetVisibility(VISIBILITY_OFF);
3012 sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
3013 // set "wpguid" column to the visual waypoint
3014 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
3016 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3017 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
3018 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
3019 map->Add(wpCreature);
3020 //wpCreature->GetMap()->Add(wpCreature);
3021 }while( result->NextRow() );
3023 // Cleanup memory
3024 delete result;
3025 return true;
3028 if(show == "first")
3030 PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3032 QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3033 if(!result)
3035 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3036 SetSentErrorMessage(true);
3037 return false;
3040 Field *fields = result->Fetch();
3041 float x = fields[0].GetFloat();
3042 float y = fields[1].GetFloat();
3043 float z = fields[2].GetFloat();
3044 uint32 id = VISUAL_WAYPOINT;
3046 Player *chr = m_session->GetPlayer();
3047 float o = chr->GetOrientation();
3048 Map *map = chr->GetMap();
3050 Creature* pCreature = new Creature;
3051 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, id, 0))
3053 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3054 delete pCreature;
3055 delete result;
3056 return false;
3059 pCreature->Relocate(x, y, z, o);
3061 if(!pCreature->IsPositionValid())
3063 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());
3064 delete pCreature;
3065 delete result;
3066 return false;
3069 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3070 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3071 map->Add(pCreature);
3072 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3074 // Cleanup memory
3075 delete result;
3076 return true;
3079 if(show == "last")
3081 PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3083 QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3084 if( result )
3086 Maxpoint = (*result)[0].GetUInt32();
3088 delete result;
3090 else
3091 Maxpoint = 0;
3093 result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3094 if(!result)
3096 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3097 SetSentErrorMessage(true);
3098 return false;
3100 Field *fields = result->Fetch();
3101 float x = fields[0].GetFloat();
3102 float y = fields[1].GetFloat();
3103 float z = fields[2].GetFloat();
3104 uint32 id = VISUAL_WAYPOINT;
3106 Player *chr = m_session->GetPlayer();
3107 float o = chr->GetOrientation();
3108 Map *map = chr->GetMap();
3110 Creature* pCreature = new Creature;
3111 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
3113 PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3114 delete pCreature;
3115 delete result;
3116 return false;
3119 pCreature->Relocate(x, y, z, o);
3121 if(!pCreature->IsPositionValid())
3123 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());
3124 delete pCreature;
3125 delete result;
3126 return false;
3129 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3130 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3131 map->Add(pCreature);
3132 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3133 // Cleanup memory
3134 delete result;
3135 return true;
3138 if(show == "off")
3140 QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3141 if(!result)
3143 SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3144 SetSentErrorMessage(true);
3145 return false;
3147 bool hasError = false;
3150 Field *fields = result->Fetch();
3151 uint32 guid = fields[0].GetUInt32();
3152 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3154 //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
3156 if(!pCreature)
3158 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3159 hasError = true;
3160 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3162 else
3164 pCreature->DeleteFromDB();
3165 pCreature->CleanupsBeforeDelete();
3166 pCreature->AddObjectToRemoveList();
3168 }while(result->NextRow());
3169 // set "wpguid" column to "empty" - no visual waypoint spawned
3170 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
3172 if( hasError )
3174 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3175 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3176 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3179 SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3180 // Cleanup memory
3181 delete result;
3183 return true;
3186 PSendSysMessage("DEBUG: wpshow - no valid command found");
3188 return true;
3189 } // HandleWpShowCommand
3191 bool ChatHandler::HandleWpExportCommand(const char *args)
3193 if(!*args)
3194 return false;
3196 // Next arg is: <GUID> <ARGUMENT>
3198 // Did user provide a GUID
3199 // or did the user select a creature?
3200 // -> variable lowguid is filled with the GUID of the NPC
3201 uint32 lowguid = 0;
3202 Creature* target = getSelectedCreature();
3203 char* arg_str = NULL;
3204 if (target)
3206 if (target->GetEntry() != VISUAL_WAYPOINT)
3207 lowguid = target->GetGUIDLow();
3208 else
3210 QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3211 if (!result)
3213 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3214 return true;
3216 Field *fields = result->Fetch();
3217 lowguid = fields[0].GetUInt32();;
3218 delete result;
3221 arg_str = strtok((char*)args, " ");
3223 else
3225 // user provided <GUID>
3226 char* guid_str = strtok((char*)args, " ");
3227 if( !guid_str )
3229 SendSysMessage(LANG_WAYPOINT_NOGUID);
3230 return false;
3232 lowguid = atoi((char*)guid_str);
3234 arg_str = strtok((char*)NULL, " ");
3237 if( !arg_str)
3239 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3240 return false;
3243 PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3245 QueryResult *result = WorldDatabase.PQuery(
3246 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3247 "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 );
3249 if (!result)
3251 PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3252 SetSentErrorMessage(true);
3253 return false;
3256 std::ofstream outfile;
3257 outfile.open (arg_str);
3261 Field *fields = result->Fetch();
3263 outfile << "INSERT INTO creature_movement ";
3264 outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5 ) VALUES ";
3266 outfile << "( ";
3267 outfile << fields[15].GetUInt32(); // id
3268 outfile << ", ";
3269 outfile << fields[0].GetUInt32(); // point
3270 outfile << ", ";
3271 outfile << fields[1].GetFloat(); // position_x
3272 outfile << ", ";
3273 outfile << fields[2].GetFloat(); // position_y
3274 outfile << ", ";
3275 outfile << fields[3].GetUInt32(); // position_z
3276 outfile << ", ";
3277 outfile << fields[4].GetUInt32(); // orientation
3278 outfile << ", ";
3279 outfile << fields[5].GetUInt32(); // model1
3280 outfile << ", ";
3281 outfile << fields[6].GetUInt32(); // model2
3282 outfile << ", ";
3283 outfile << fields[7].GetUInt16(); // waittime
3284 outfile << ", ";
3285 outfile << fields[8].GetUInt32(); // emote
3286 outfile << ", ";
3287 outfile << fields[9].GetUInt32(); // spell
3288 outfile << ", ";
3289 outfile << fields[10].GetUInt32(); // textid1
3290 outfile << ", ";
3291 outfile << fields[11].GetUInt32(); // textid2
3292 outfile << ", ";
3293 outfile << fields[12].GetUInt32(); // textid3
3294 outfile << ", ";
3295 outfile << fields[13].GetUInt32(); // textid4
3296 outfile << ", ";
3297 outfile << fields[14].GetUInt32(); // textid5
3298 outfile << ");\n ";
3300 } while( result->NextRow() );
3301 delete result;
3303 PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3304 outfile.close();
3306 return true;
3309 bool ChatHandler::HandleWpImportCommand(const char *args)
3311 if(!*args)
3312 return false;
3314 char* arg_str = strtok((char*)args, " ");
3315 if (!arg_str)
3316 return false;
3318 std::string line;
3319 std::ifstream infile (arg_str);
3320 if (infile.is_open())
3322 while (! infile.eof() )
3324 getline (infile,line);
3325 //cout << line << endl;
3326 QueryResult *result = WorldDatabase.Query(line.c_str());
3327 delete result;
3329 infile.close();
3331 PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3333 return true;
3336 //rename characters
3337 bool ChatHandler::HandleRenameCommand(const char* args)
3339 Player* target = NULL;
3340 uint64 targetGUID = 0;
3341 std::string oldname;
3343 char* px = strtok((char*)args, " ");
3345 if(px)
3347 oldname = px;
3349 if(!normalizePlayerName(oldname))
3351 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3352 SetSentErrorMessage(true);
3353 return false;
3356 target = objmgr.GetPlayer(oldname.c_str());
3358 if (!target)
3359 targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3362 if(!target && !targetGUID)
3364 target = getSelectedPlayer();
3367 if(!target && !targetGUID)
3369 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3370 SetSentErrorMessage(true);
3371 return false;
3374 if(target)
3376 // check online security
3377 if (HasLowerSecurity(target, 0))
3378 return false;
3380 PSendSysMessage(LANG_RENAME_PLAYER, target->GetName());
3381 target->SetAtLoginFlag(AT_LOGIN_RENAME);
3382 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3384 else
3386 // check offline security
3387 if (HasLowerSecurity(NULL, targetGUID))
3388 return false;
3390 PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
3391 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3394 return true;
3397 // customize characters
3398 bool ChatHandler::HandleCustomizeCommand(const char* args)
3400 Player* target = NULL;
3401 uint64 targetGUID = 0;
3402 std::string oldname;
3404 char* px = strtok((char*)args, " ");
3406 if(px)
3408 oldname = px;
3410 if(!normalizePlayerName(oldname))
3412 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3413 SetSentErrorMessage(true);
3414 return false;
3417 target = objmgr.GetPlayer(oldname.c_str());
3419 if (!target)
3420 targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3423 if(!target && !targetGUID)
3425 target = getSelectedPlayer();
3428 if(!target && !targetGUID)
3430 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3431 SetSentErrorMessage(true);
3432 return false;
3435 if(target)
3437 PSendSysMessage(LANG_CUSTOMIZE_PLAYER, target->GetName());
3438 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
3439 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow());
3441 else
3443 PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
3444 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3447 return true;
3450 //spawn go
3451 bool ChatHandler::HandleGameObjectCommand(const char* args)
3453 if (!*args)
3454 return false;
3456 char* pParam1 = strtok((char*)args, " ");
3457 if (!pParam1)
3458 return false;
3460 uint32 id = atoi((char*)pParam1);
3461 if(!id)
3462 return false;
3464 char* spawntimeSecs = strtok(NULL, " ");
3466 const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id);
3468 if (!goI)
3470 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
3471 SetSentErrorMessage(true);
3472 return false;
3475 Player *chr = m_session->GetPlayer();
3476 float x = float(chr->GetPositionX());
3477 float y = float(chr->GetPositionY());
3478 float z = float(chr->GetPositionZ());
3479 float o = float(chr->GetOrientation());
3480 Map *map = chr->GetMap();
3482 float rot2 = sin(o/2);
3483 float rot3 = cos(o/2);
3485 GameObject* pGameObj = new GameObject;
3486 uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
3488 if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1))
3490 delete pGameObj;
3491 return false;
3494 if( spawntimeSecs )
3496 uint32 value = atoi((char*)spawntimeSecs);
3497 pGameObj->SetRespawnTime(value);
3498 //sLog.outDebug("*** spawntimeSecs: %d", value);
3501 // fill the gameobject data and save to the db
3502 pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3504 // this will generate a new guid if the object is in an instance
3505 if(!pGameObj->LoadFromDB(db_lowGUID, map))
3507 delete pGameObj;
3508 return false;
3511 sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o);
3513 map->Add(pGameObj);
3515 // TODO: is it really necessary to add both the real and DB table guid here ?
3516 objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
3518 PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z);
3519 return true;
3522 //show animation
3523 bool ChatHandler::HandleAnimCommand(const char* args)
3525 if (!*args)
3526 return false;
3528 uint32 anim_id = atoi((char*)args);
3529 m_session->GetPlayer()->HandleEmoteCommand(anim_id);
3530 return true;
3533 //change standstate
3534 bool ChatHandler::HandleStandStateCommand(const char* args)
3536 if (!*args)
3537 return false;
3539 uint32 anim_id = atoi((char*)args);
3540 m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3542 return true;
3545 bool ChatHandler::HandleAddHonorCommand(const char* args)
3547 if (!*args)
3548 return false;
3550 Player *target = getSelectedPlayer();
3551 if(!target)
3553 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3554 SetSentErrorMessage(true);
3555 return false;
3558 // check online security
3559 if (HasLowerSecurity(target, 0))
3560 return false;
3562 uint32 amount = (uint32)atoi(args);
3563 target->RewardHonor(NULL, 1, amount);
3564 return true;
3567 bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3569 Unit *target = getSelectedUnit();
3570 if(!target)
3572 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3573 SetSentErrorMessage(true);
3574 return false;
3577 // check online security
3578 if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
3579 return false;
3581 m_session->GetPlayer()->RewardHonor(target, 1);
3582 return true;
3585 bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/)
3587 Player *target = getSelectedPlayer();
3588 if(!target)
3590 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3591 SetSentErrorMessage(true);
3592 return false;
3595 // check online security
3596 if (HasLowerSecurity(target, 0))
3597 return false;
3599 target->UpdateHonorFields();
3600 return true;
3603 bool ChatHandler::HandleLookupEventCommand(const char* args)
3605 if(!*args)
3606 return false;
3608 std::string namepart = args;
3609 std::wstring wnamepart;
3611 // converting string that we try to find to lower case
3612 if(!Utf8toWStr(namepart,wnamepart))
3613 return false;
3615 wstrToLower(wnamepart);
3617 uint32 counter = 0;
3619 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3620 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3622 for(uint32 id = 0; id < events.size(); ++id )
3624 GameEventData const& eventData = events[id];
3626 std::string descr = eventData.description;
3627 if(descr.empty())
3628 continue;
3630 if (Utf8FitTo(descr, wnamepart))
3632 char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : "";
3634 if(m_session)
3635 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3636 else
3637 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3639 ++counter;
3643 if (counter==0)
3644 SendSysMessage(LANG_NOEVENTFOUND);
3646 return true;
3649 bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/)
3651 uint32 counter = 0;
3653 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3654 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3656 char const* active = GetMangosString(LANG_ACTIVE);
3658 for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
3660 uint32 event_id = *itr;
3661 GameEventData const& eventData = events[event_id];
3663 if(m_session)
3664 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
3665 else
3666 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
3668 ++counter;
3671 if (counter==0)
3672 SendSysMessage(LANG_NOEVENTFOUND);
3674 return true;
3677 bool ChatHandler::HandleEventInfoCommand(const char* args)
3679 if(!*args)
3680 return false;
3682 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3683 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3684 if(!cId)
3685 return false;
3687 uint32 event_id = atoi(cId);
3689 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3691 if(event_id >=events.size())
3693 SendSysMessage(LANG_EVENT_NOT_EXIST);
3694 SetSentErrorMessage(true);
3695 return false;
3698 GameEventData const& eventData = events[event_id];
3699 if(!eventData.isValid())
3701 SendSysMessage(LANG_EVENT_NOT_EXIST);
3702 SetSentErrorMessage(true);
3703 return false;
3706 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3707 bool active = activeEvents.find(event_id) != activeEvents.end();
3708 char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : "";
3710 std::string startTimeStr = TimeToTimestampStr(eventData.start);
3711 std::string endTimeStr = TimeToTimestampStr(eventData.end);
3713 uint32 delay = gameeventmgr.NextCheck(event_id);
3714 time_t nextTime = time(NULL)+delay;
3715 std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3717 std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3718 std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3720 PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3721 startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3722 nextStr.c_str());
3723 return true;
3726 bool ChatHandler::HandleEventStartCommand(const char* args)
3728 if(!*args)
3729 return false;
3731 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3732 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3733 if(!cId)
3734 return false;
3736 int32 event_id = atoi(cId);
3738 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3740 if(event_id < 1 || event_id >=events.size())
3742 SendSysMessage(LANG_EVENT_NOT_EXIST);
3743 SetSentErrorMessage(true);
3744 return false;
3747 GameEventData const& eventData = events[event_id];
3748 if(!eventData.isValid())
3750 SendSysMessage(LANG_EVENT_NOT_EXIST);
3751 SetSentErrorMessage(true);
3752 return false;
3755 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3756 if(activeEvents.find(event_id) != activeEvents.end())
3758 PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3759 SetSentErrorMessage(true);
3760 return false;
3763 gameeventmgr.StartEvent(event_id,true);
3764 return true;
3767 bool ChatHandler::HandleEventStopCommand(const char* args)
3769 if(!*args)
3770 return false;
3772 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3773 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3774 if(!cId)
3775 return false;
3777 int32 event_id = atoi(cId);
3779 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3781 if(event_id < 1 || event_id >=events.size())
3783 SendSysMessage(LANG_EVENT_NOT_EXIST);
3784 SetSentErrorMessage(true);
3785 return false;
3788 GameEventData const& eventData = events[event_id];
3789 if(!eventData.isValid())
3791 SendSysMessage(LANG_EVENT_NOT_EXIST);
3792 SetSentErrorMessage(true);
3793 return false;
3796 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3798 if(activeEvents.find(event_id) == activeEvents.end())
3800 PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3801 SetSentErrorMessage(true);
3802 return false;
3805 gameeventmgr.StopEvent(event_id,true);
3806 return true;
3809 bool ChatHandler::HandleCombatStopCommand(const char* args)
3811 Player *player;
3813 if(*args)
3815 std::string playername = args;
3817 if(!normalizePlayerName(playername))
3819 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3820 SetSentErrorMessage(true);
3821 return false;
3824 player = objmgr.GetPlayer(playername.c_str());
3826 if(!player)
3828 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3829 SetSentErrorMessage(true);
3830 return false;
3833 else
3835 player = getSelectedPlayer();
3837 if (!player)
3838 player = m_session->GetPlayer();
3841 // check online security
3842 if (HasLowerSecurity(player, 0))
3843 return false;
3845 player->CombatStop();
3846 player->getHostilRefManager().deleteReferences();
3847 return true;
3850 bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3852 uint32 classmask = m_session->GetPlayer()->getClassMask();
3854 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3856 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3857 if( !skillInfo )
3858 continue;
3860 if( skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY )
3862 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3864 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3865 if( !skillLine )
3866 continue;
3868 // skip racial skills
3869 if( skillLine->racemask != 0 )
3870 continue;
3872 // skip wrong class skills
3873 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3874 continue;
3876 if( skillLine->skillId != i || skillLine->forward_spellid )
3877 continue;
3879 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3880 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3881 continue;
3883 m_session->GetPlayer()->learnSpell(skillLine->spellId);
3888 SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
3889 return true;
3892 bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
3894 // Learns all recipes of specified profession and sets skill to max
3895 // Example: .learn all_recipes enchanting
3897 Player* target = getSelectedPlayer();
3898 if( !target )
3900 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3901 return false;
3904 if(!*args)
3905 return false;
3907 std::wstring wnamepart;
3909 if(!Utf8toWStr(args,wnamepart))
3910 return false;
3912 // converting string that we try to find to lower case
3913 wstrToLower( wnamepart );
3915 uint32 classmask = m_session->GetPlayer()->getClassMask();
3917 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3919 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3920 if( !skillInfo )
3921 continue;
3923 if( skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
3924 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY )
3925 continue;
3927 int loc = m_session->GetSessionDbcLocale();
3928 std::string name = skillInfo->name[loc];
3930 if(Utf8FitTo(name, wnamepart))
3932 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3934 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3935 if( !skillLine )
3936 continue;
3938 if( skillLine->skillId != i || skillLine->forward_spellid )
3939 continue;
3941 // skip racial skills
3942 if( skillLine->racemask != 0 )
3943 continue;
3945 // skip wrong class skills
3946 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3947 continue;
3949 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3950 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3951 continue;
3953 if( !target->HasSpell(spellInfo->Id) )
3954 m_session->GetPlayer()->learnSpell(skillLine->spellId);
3957 uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
3958 target->SetSkill(skillInfo->id, maxLevel, maxLevel);
3959 PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
3960 return true;
3964 return false;
3967 bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
3970 if (!*args)
3971 return false;
3973 std::string ip = strtok ((char*)args, " ");
3974 char* limit_str = strtok (NULL, " ");
3975 int32 limit = limit_str ? atoi (limit_str) : -1;
3977 loginDatabase.escape_string (ip);
3979 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
3981 return LookupPlayerSearchCommand (result,limit);
3984 bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
3986 if (!*args)
3987 return false;
3989 std::string account = strtok ((char*)args, " ");
3990 char* limit_str = strtok (NULL, " ");
3991 int32 limit = limit_str ? atoi (limit_str) : -1;
3993 if (!AccountMgr::normilizeString (account))
3994 return false;
3996 loginDatabase.escape_string (account);
3998 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
4000 return LookupPlayerSearchCommand (result,limit);
4003 bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
4006 if (!*args)
4007 return false;
4009 std::string email = strtok ((char*)args, " ");
4010 char* limit_str = strtok (NULL, " ");
4011 int32 limit = limit_str ? atoi (limit_str) : -1;
4013 loginDatabase.escape_string (email);
4015 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
4017 return LookupPlayerSearchCommand (result,limit);
4020 bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
4022 if(!result)
4024 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4025 SetSentErrorMessage(true);
4026 return false;
4029 int i =0;
4032 Field* fields = result->Fetch();
4033 uint32 acc_id = fields[0].GetUInt32();
4034 std::string acc_name = fields[1].GetCppString();
4036 QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
4037 if(chars)
4039 PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4041 uint64 guid = 0;
4042 std::string name;
4046 Field* charfields = chars->Fetch();
4047 guid = charfields[0].GetUInt64();
4048 name = charfields[1].GetCppString();
4050 PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
4051 ++i;
4053 } while( chars->NextRow() && ( limit == -1 || i < limit ) );
4055 delete chars;
4057 } while(result->NextRow());
4059 delete result;
4061 return true;
4064 /// Triggering corpses expire check in world
4065 bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4067 CorpsesErase();
4068 return true;
4071 bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
4073 Player *target = getSelectedPlayer();
4075 if(!target)
4077 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4078 SetSentErrorMessage(true);
4079 return false;
4082 // check online security
4083 if (HasLowerSecurity(target, 0))
4084 return false;
4086 // Repair items
4087 target->DurabilityRepairAll(false, 0, false);
4089 PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName());
4090 if(needReportToTarget(target))
4091 ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName());
4092 return true;
4095 bool ChatHandler::HandleWaterwalkCommand(const char* args)
4097 if(!*args)
4098 return false;
4100 Player *player = getSelectedPlayer();
4102 if(!player)
4104 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4105 SetSentErrorMessage(true);
4106 return false;
4109 // check online security
4110 if (HasLowerSecurity(player, 0))
4111 return false;
4113 if (strncmp(args, "on", 3) == 0)
4114 player->SetMovement(MOVE_WATER_WALK); // ON
4115 else if (strncmp(args, "off", 4) == 0)
4116 player->SetMovement(MOVE_LAND_WALK); // OFF
4117 else
4119 SendSysMessage(LANG_USE_BOL);
4120 return false;
4123 PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
4124 if(needReportToTarget(player))
4125 ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
4126 return true;
4129 bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
4131 Player *player = m_session->GetPlayer();
4132 Creature *creature = getSelectedCreature();
4134 if(!creature)
4136 PSendSysMessage(LANG_SELECT_CREATURE);
4137 SetSentErrorMessage(true);
4138 return false;
4141 // Follow player - Using pet's default dist and angle
4142 creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
4144 PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
4145 return true;
4148 bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
4150 Player *player = m_session->GetPlayer();
4151 Creature *creature = getSelectedCreature();
4153 if(!creature)
4155 PSendSysMessage(LANG_SELECT_CREATURE);
4156 SetSentErrorMessage(true);
4157 return false;
4160 if (creature->GetMotionMaster()->empty() ||
4161 creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
4163 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4164 SetSentErrorMessage(true);
4165 return false;
4168 TargetedMovementGenerator<Creature> const* mgen
4169 = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
4171 if(mgen->GetTarget()!=player)
4173 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4174 SetSentErrorMessage(true);
4175 return false;
4178 // reset movement
4179 creature->GetMotionMaster()->MovementExpired(true);
4181 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
4182 return true;
4185 bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
4187 Creature *creatureTarget = getSelectedCreature ();
4188 if (!creatureTarget || creatureTarget->isPet ())
4190 PSendSysMessage (LANG_SELECT_CREATURE);
4191 SetSentErrorMessage (true);
4192 return false;
4195 Player *player = m_session->GetPlayer ();
4197 if(player->GetPetGUID ())
4199 SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
4200 SetSentErrorMessage (true);
4201 return false;
4204 CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
4206 if (!cInfo->isTameable ())
4208 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4209 SetSentErrorMessage (true);
4210 return false;
4213 // Everything looks OK, create new pet
4214 Pet* pet = player->CreateTamedPetFrom (creatureTarget);
4215 if (!pet)
4217 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4218 SetSentErrorMessage (true);
4219 return false;
4222 // place pet before player
4223 float x,y,z;
4224 player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
4225 pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
4227 // set pet to defensive mode by default (some classes can't control controlled pets in fact).
4228 pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4230 // calculate proper level
4231 uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
4233 // prepare visual effect for levelup
4234 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4236 // add to world
4237 pet->GetMap()->Add((Creature*)pet);
4239 // visual effect for levelup
4240 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4242 // caster have pet now
4243 player->SetPet(pet);
4245 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4246 player->PetSpellInitialize();
4248 return true;