Use configuration values for arena directly instead of values cached in local variabl...
[getmangos.git] / src / game / Level2.cpp
blob1e6172b7413e25cb50e4a66b64036e836673252b
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "World.h"
24 #include "ObjectMgr.h"
25 #include "Player.h"
26 #include "Item.h"
27 #include "GameObject.h"
28 #include "Opcodes.h"
29 #include "Chat.h"
30 #include "ObjectAccessor.h"
31 #include "MapManager.h"
32 #include "Language.h"
33 #include "World.h"
34 #include "GameEvent.h"
35 #include "SpellMgr.h"
36 #include "AccountMgr.h"
37 #include "GMTicketMgr.h"
38 #include "WaypointManager.h"
39 #include "Util.h"
40 #include <cctype>
41 #include <iostream>
42 #include <fstream>
43 #include <map>
44 #include "GlobalEvents.h"
46 #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
48 static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
50 LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL,
51 LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED
54 //mute player for some times
55 bool ChatHandler::HandleMuteCommand(const char* args)
57 if (!*args)
58 return false;
60 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 // must have strong lesser security level
90 if(HasLowerSecurity (chr,guid,true))
91 return false;
93 uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid);
95 time_t mutetime = time(NULL) + notspeaktime*60;
97 if (chr)
98 chr->GetSession()->m_muteTime = mutetime;
100 loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
102 if(chr)
103 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
105 PSendSysMessage(LANG_YOU_DISABLE_CHAT, cname.c_str(), notspeaktime);
107 return true;
110 //unmute player
111 bool ChatHandler::HandleUnmuteCommand(const char* args)
113 if (!*args)
114 return false;
116 char *charname = strtok((char*)args, " ");
117 if (!charname)
118 return false;
120 std::string cname = charname;
122 if(!normalizePlayerName(cname))
124 SendSysMessage(LANG_PLAYER_NOT_FOUND);
125 SetSentErrorMessage(true);
126 return false;
129 uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
130 if(!guid)
132 SendSysMessage(LANG_PLAYER_NOT_FOUND);
133 SetSentErrorMessage(true);
134 return false;
137 Player *chr = objmgr.GetPlayer(guid);
139 // must have strong lesser security level
140 if(HasLowerSecurity (chr,guid,true))
141 return false;
143 uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid);
145 if (chr)
147 if(chr->CanSpeak())
149 SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
150 SetSentErrorMessage(true);
151 return false;
154 chr->GetSession()->m_muteTime = 0;
157 loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
159 if(chr)
160 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
162 PSendSysMessage(LANG_YOU_ENABLE_CHAT, cname.c_str());
163 return true;
166 bool ChatHandler::HandleTargetObjectCommand(const char* args)
168 Player* pl = m_session->GetPlayer();
169 QueryResult *result;
170 GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
171 if(*args)
173 int32 id = atoi((char*)args);
174 if(id)
175 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",
176 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
177 else
179 std::string name = args;
180 WorldDatabase.escape_string(name);
181 result = WorldDatabase.PQuery(
182 "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_ "
183 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
184 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
187 else
189 std::ostringstream eventFilter;
190 eventFilter << " AND (event IS NULL ";
191 bool initString = true;
193 for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
195 if (initString)
197 eventFilter << "OR event IN (" <<*itr;
198 initString =false;
200 else
201 eventFilter << "," << *itr;
204 if (!initString)
205 eventFilter << "))";
206 else
207 eventFilter << ")";
209 result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
210 "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
211 "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 1",
212 m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
215 if (!result)
217 SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
218 return true;
221 Field *fields = result->Fetch();
222 uint32 lowguid = fields[0].GetUInt32();
223 uint32 id = fields[1].GetUInt32();
224 float x = fields[2].GetFloat();
225 float y = fields[3].GetFloat();
226 float z = fields[4].GetFloat();
227 float o = fields[5].GetFloat();
228 int mapid = fields[6].GetUInt16();
229 delete result;
231 GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id);
233 if (!goI)
235 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
236 return false;
239 GameObject* target = ObjectAccessor::GetGameObject(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
241 PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
243 if(target)
245 int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
246 if(curRespawnDelay < 0)
247 curRespawnDelay = 0;
249 std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
250 std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
252 PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
254 return true;
257 //teleport to gameobject
258 bool ChatHandler::HandleGoObjectCommand(const char* args)
260 if(!*args)
261 return false;
263 Player* _player = m_session->GetPlayer();
265 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
266 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
267 if(!cId)
268 return false;
270 int32 guid = atoi(cId);
271 if(!guid)
272 return false;
274 float x, y, z, ort;
275 int mapid;
277 // by DB guid
278 if (GameObjectData const* go_data = objmgr.GetGOData(guid))
280 x = go_data->posX;
281 y = go_data->posY;
282 z = go_data->posZ;
283 ort = go_data->orientation;
284 mapid = go_data->mapid;
286 else
288 SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
289 SetSentErrorMessage(true);
290 return false;
293 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
295 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
296 SetSentErrorMessage(true);
297 return false;
300 // stop flight if need
301 if(_player->isInFlight())
303 _player->GetMotionMaster()->MovementExpired();
304 _player->m_taxi.ClearTaxiDestinations();
306 // save only in non-flight case
307 else
308 _player->SaveRecallPosition();
310 _player->TeleportTo(mapid, x, y, z, ort);
311 return true;
314 bool ChatHandler::HandleGoTriggerCommand(const char* args)
316 Player* _player = m_session->GetPlayer();
318 if (!*args)
319 return false;
321 char *atId = strtok((char*)args, " ");
322 if (!atId)
323 return false;
325 int32 i_atId = atoi(atId);
327 if(!i_atId)
328 return false;
330 AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
331 if (!at)
333 PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
334 SetSentErrorMessage(true);
335 return false;
338 if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
340 PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
341 SetSentErrorMessage(true);
342 return false;
345 // stop flight if need
346 if(_player->isInFlight())
348 _player->GetMotionMaster()->MovementExpired();
349 _player->m_taxi.ClearTaxiDestinations();
351 // save only in non-flight case
352 else
353 _player->SaveRecallPosition();
355 _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
356 return true;
359 bool ChatHandler::HandleGoGraveyardCommand(const char* args)
361 Player* _player = m_session->GetPlayer();
363 if (!*args)
364 return false;
366 char *gyId = strtok((char*)args, " ");
367 if (!gyId)
368 return false;
370 int32 i_gyId = atoi(gyId);
372 if(!i_gyId)
373 return false;
375 WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
376 if (!gy)
378 PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
379 SetSentErrorMessage(true);
380 return false;
383 if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
385 PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
386 SetSentErrorMessage(true);
387 return false;
390 // stop flight if need
391 if(_player->isInFlight())
393 _player->GetMotionMaster()->MovementExpired();
394 _player->m_taxi.ClearTaxiDestinations();
396 // save only in non-flight case
397 else
398 _player->SaveRecallPosition();
400 _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
401 return true;
404 /** \brief Teleport the GM to the specified creature
406 * .gocreature <GUID> --> TP using creature.guid
407 * .gocreature azuregos --> TP player to the mob with this name
408 * Warning: If there is more than one mob with this name
409 * you will be teleported to the first one that is found.
410 * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry
411 * Warning: If there is more than one mob with this "id"
412 * you will be teleported to the first one that is found.
414 //teleport to creature
415 bool ChatHandler::HandleGoCreatureCommand(const char* args)
417 if(!*args)
418 return false;
419 Player* _player = m_session->GetPlayer();
421 // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
422 char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
423 if (!pParam1)
424 return false;
426 std::ostringstream whereClause;
428 // User wants to teleport to the NPC's template entry
429 if( strcmp(pParam1, "id") == 0 )
431 //sLog.outError("DEBUG: ID found");
433 // Get the "creature_template.entry"
434 // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
435 char* tail = strtok(NULL,"");
436 if(!tail)
437 return false;
438 char* cId = extractKeyFromLink(tail,"Hcreature_entry");
439 if(!cId)
440 return false;
442 int32 tEntry = atoi(cId);
443 //sLog.outError("DEBUG: ID value: %d", tEntry);
444 if(!tEntry)
445 return false;
447 whereClause << "WHERE id = '" << tEntry << "'";
449 else
451 //sLog.outError("DEBUG: ID *not found*");
453 int32 guid = atoi(pParam1);
455 // Number is invalid - maybe the user specified the mob's name
456 if(!guid)
458 std::string name = pParam1;
459 WorldDatabase.escape_string(name);
460 whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
462 else
464 whereClause << "WHERE guid = '" << guid << "'";
467 //sLog.outError("DEBUG: %s", whereClause.c_str());
469 QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
470 if (!result)
472 SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
473 SetSentErrorMessage(true);
474 return false;
476 if( result->GetRowCount() > 1 )
478 SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
481 Field *fields = result->Fetch();
482 float x = fields[0].GetFloat();
483 float y = fields[1].GetFloat();
484 float z = fields[2].GetFloat();
485 float ort = fields[3].GetFloat();
486 int mapid = fields[4].GetUInt16();
488 delete result;
490 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
492 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
493 SetSentErrorMessage(true);
494 return false;
497 // stop flight if need
498 if(_player->isInFlight())
500 _player->GetMotionMaster()->MovementExpired();
501 _player->m_taxi.ClearTaxiDestinations();
503 // save only in non-flight case
504 else
505 _player->SaveRecallPosition();
507 _player->TeleportTo(mapid, x, y, z, ort);
508 return true;
511 bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
513 uint64 guid = m_session->GetPlayer()->GetSelection();
515 if (guid == 0)
517 SendSysMessage(LANG_NO_SELECTION);
518 SetSentErrorMessage(true);
519 return false;
522 PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
523 return true;
526 bool ChatHandler::HandleLookupFactionCommand(const char* args)
528 if (!*args)
529 return false;
531 // Can be NULL at console call
532 Player *target = getSelectedPlayer ();
534 std::string namepart = args;
535 std::wstring wnamepart;
537 if (!Utf8toWStr (namepart,wnamepart))
538 return false;
540 // converting string that we try to find to lower case
541 wstrToLower (wnamepart);
543 uint32 counter = 0; // Counter for figure out that we found smth.
545 for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
547 FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
548 if (factionEntry)
550 FactionState const* repState = NULL;
551 if(target)
553 FactionStateList::const_iterator repItr = target->m_factions.find (factionEntry->reputationListID);
554 if(repItr != target->m_factions.end())
555 repState = &repItr->second;
559 int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale();
560 std::string name = factionEntry->name[loc];
561 if(name.empty())
562 continue;
564 if (!Utf8FitTo(name, wnamepart))
566 loc = 0;
567 for(; loc < MAX_LOCALE; ++loc)
569 if(m_session && loc==m_session->GetSessionDbcLocale())
570 continue;
572 name = factionEntry->name[loc];
573 if(name.empty())
574 continue;
576 if (Utf8FitTo(name, wnamepart))
577 break;
581 if(loc < MAX_LOCALE)
583 // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
584 // or "id - [faction] [no reputation]" format
585 std::ostringstream ss;
586 if (m_session)
587 ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
588 else
589 ss << id << " - " << name << " " << localeNames[loc];
591 if (repState) // and then target!=NULL also
593 ReputationRank rank = target->GetReputationRank(factionEntry);
594 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
596 ss << " " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
598 if(repState->Flags & FACTION_FLAG_VISIBLE)
599 ss << GetMangosString(LANG_FACTION_VISIBLE);
600 if(repState->Flags & FACTION_FLAG_AT_WAR)
601 ss << GetMangosString(LANG_FACTION_ATWAR);
602 if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
603 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
604 if(repState->Flags & FACTION_FLAG_HIDDEN)
605 ss << GetMangosString(LANG_FACTION_HIDDEN);
606 if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
607 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
608 if(repState->Flags & FACTION_FLAG_INACTIVE)
609 ss << GetMangosString(LANG_FACTION_INACTIVE);
611 else
612 ss << GetMangosString(LANG_FACTION_NOREPUTATION);
614 SendSysMessage(ss.str().c_str());
615 counter++;
620 if (counter == 0) // if counter == 0 then we found nth
621 SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
622 return true;
625 bool ChatHandler::HandleModifyRepCommand(const char * args)
627 if (!*args) return false;
629 Player* target = NULL;
630 target = getSelectedPlayer();
632 if(!target)
634 SendSysMessage(LANG_PLAYER_NOT_FOUND);
635 SetSentErrorMessage(true);
636 return false;
639 // check online security
640 if (HasLowerSecurity(target, 0))
641 return false;
643 char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
644 if(!factionTxt)
645 return false;
647 uint32 factionId = atoi(factionTxt);
649 int32 amount = 0;
650 char *rankTxt = strtok(NULL, " ");
651 if (!factionTxt || !rankTxt)
652 return false;
654 amount = atoi(rankTxt);
655 if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
657 std::string rankStr = rankTxt;
658 std::wstring wrankStr;
659 if(!Utf8toWStr(rankStr,wrankStr))
660 return false;
661 wstrToLower( wrankStr );
663 int r = 0;
664 amount = -42000;
665 for (; r < MAX_REPUTATION_RANK; ++r)
667 std::string rank = GetMangosString(ReputationRankStrIndex[r]);
668 if(rank.empty())
669 continue;
671 std::wstring wrank;
672 if(!Utf8toWStr(rank,wrank))
673 continue;
675 wstrToLower(wrank);
677 if(wrank.substr(0,wrankStr.size())==wrankStr)
679 char *deltaTxt = strtok(NULL, " ");
680 if (deltaTxt)
682 int32 delta = atoi(deltaTxt);
683 if ((delta < 0) || (delta > Player::ReputationRank_Length[r] -1))
685 PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (Player::ReputationRank_Length[r]-1));
686 SetSentErrorMessage(true);
687 return false;
689 amount += delta;
691 break;
693 amount += Player::ReputationRank_Length[r];
695 if (r >= MAX_REPUTATION_RANK)
697 PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
698 SetSentErrorMessage(true);
699 return false;
703 FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
705 if (!factionEntry)
707 PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
708 SetSentErrorMessage(true);
709 return false;
712 if (factionEntry->reputationListID < 0)
714 PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[m_session->GetSessionDbcLocale()], factionId);
715 SetSentErrorMessage(true);
716 return false;
719 target->SetFactionReputation(factionEntry,amount);
720 PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, target->GetName(), target->GetReputation(factionId));
721 return true;
724 bool ChatHandler::HandleNameCommand(const char* /*args*/)
726 /* Temp. disabled
727 if(!*args)
728 return false;
730 if(strlen((char*)args)>75)
732 PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
733 return true;
736 for (uint8 i = 0; i < strlen(args); i++)
738 if(!isalpha(args[i]) && args[i]!=' ')
740 SendSysMessage(LANG_CHARS_ONLY);
741 return false;
745 uint64 guid;
746 guid = m_session->GetPlayer()->GetSelection();
747 if (guid == 0)
749 SendSysMessage(LANG_NO_SELECTION);
750 return true;
753 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
755 if(!pCreature)
757 SendSysMessage(LANG_SELECT_CREATURE);
758 return true;
761 pCreature->SetName(args);
762 uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName());
763 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
765 pCreature->SaveToDB();
768 return true;
771 bool ChatHandler::HandleSubNameCommand(const char* /*args*/)
773 /* Temp. disabled
775 if(!*args)
776 args = "";
778 if(strlen((char*)args)>75)
781 PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
782 return true;
785 for (uint8 i = 0; i < strlen(args); i++)
787 if(!isalpha(args[i]) && args[i]!=' ')
789 SendSysMessage(LANG_CHARS_ONLY);
790 return false;
793 uint64 guid;
794 guid = m_session->GetPlayer()->GetSelection();
795 if (guid == 0)
797 SendSysMessage(LANG_NO_SELECTION);
798 return true;
801 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
803 if(!pCreature)
805 SendSysMessage(LANG_SELECT_CREATURE);
806 return true;
809 uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
810 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
812 pCreature->SaveToDB();
814 return true;
817 //move item to other slot
818 bool ChatHandler::HandleItemMoveCommand(const char* args)
820 if(!*args)
821 return false;
822 uint8 srcslot, dstslot;
824 char* pParam1 = strtok((char*)args, " ");
825 if (!pParam1)
826 return false;
828 char* pParam2 = strtok(NULL, " ");
829 if (!pParam2)
830 return false;
832 srcslot = (uint8)atoi(pParam1);
833 dstslot = (uint8)atoi(pParam2);
835 if(srcslot==dstslot)
836 return true;
838 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot))
839 return false;
841 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot))
842 return false;
844 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
845 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
847 m_session->GetPlayer()->SwapItem( src, dst );
849 return true;
852 //add spawn of creature
853 bool ChatHandler::HandleNpcAddCommand(const char* args)
855 if(!*args)
856 return false;
857 char* charID = extractKeyFromLink((char*)args,"Hcreature_entry");
858 if(!charID)
859 return false;
861 char* team = strtok(NULL, " ");
862 int32 teamval = 0;
863 if (team) { teamval = atoi(team); }
864 if (teamval < 0) { teamval = 0; }
866 uint32 id = atoi(charID);
868 Player *chr = m_session->GetPlayer();
869 float x = chr->GetPositionX();
870 float y = chr->GetPositionY();
871 float z = chr->GetPositionZ();
872 float o = chr->GetOrientation();
873 Map *map = chr->GetMap();
875 Creature* pCreature = new Creature;
876 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, (uint32)teamval))
878 delete pCreature;
879 return false;
882 pCreature->Relocate(x,y,z,o);
884 if(!pCreature->IsPositionValid())
886 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());
887 delete pCreature;
888 return false;
891 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
893 uint32 db_guid = pCreature->GetDBTableGUIDLow();
895 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
896 pCreature->LoadFromDB(db_guid, map);
898 map->Add(pCreature);
899 objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid));
900 return true;
903 bool ChatHandler::HandleNpcDeleteCommand(const char* args)
905 Creature* unit = NULL;
907 if(*args)
909 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
910 char* cId = extractKeyFromLink((char*)args,"Hcreature");
911 if(!cId)
912 return false;
914 uint32 lowguid = atoi(cId);
915 if(!lowguid)
916 return false;
918 if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid))
919 unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
921 else
922 unit = getSelectedCreature();
924 if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle())
926 SendSysMessage(LANG_SELECT_CREATURE);
927 SetSentErrorMessage(true);
928 return false;
931 // Delete the creature
932 unit->CombatStop();
933 unit->DeleteFromDB();
934 unit->CleanupsBeforeDelete();
935 unit->AddObjectToRemoveList();
937 SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
939 return true;
942 //delete object by selection or guid
943 bool ChatHandler::HandleDelObjectCommand(const char* args)
945 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
946 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
947 if(!cId)
948 return false;
950 uint32 lowguid = atoi(cId);
951 if(!lowguid)
952 return false;
954 GameObject* obj = NULL;
956 // by DB guid
957 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
958 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
960 if(!obj)
962 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
963 SetSentErrorMessage(true);
964 return false;
967 uint64 owner_guid = obj->GetOwnerGUID();
968 if(owner_guid)
970 Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
971 if(!owner && !IS_PLAYER_GUID(owner_guid))
973 PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
974 SetSentErrorMessage(true);
975 return false;
978 owner->RemoveGameObject(obj,false);
981 obj->SetRespawnTime(0); // not save respawn time
982 obj->Delete();
983 obj->DeleteFromDB();
985 PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
987 return true;
990 //turn selected object
991 bool ChatHandler::HandleTurnObjectCommand(const char* args)
993 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
994 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
995 if(!cId)
996 return false;
998 uint32 lowguid = atoi(cId);
999 if(!lowguid)
1000 return false;
1002 GameObject* obj = NULL;
1004 // by DB guid
1005 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1006 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1008 if(!obj)
1010 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1011 SetSentErrorMessage(true);
1012 return false;
1015 char* po = strtok(NULL, " ");
1016 float o;
1018 if (po)
1020 o = (float)atof(po);
1022 else
1024 Player *chr = m_session->GetPlayer();
1025 o = chr->GetOrientation();
1028 float rot2 = sin(o/2);
1029 float rot3 = cos(o/2);
1031 Map* map = obj->GetMap();
1032 map->Remove(obj,false);
1034 obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
1036 obj->SetFloatValue(GAMEOBJECT_FACING, o);
1037 obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2);
1038 obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3);
1040 map->Add(obj);
1042 obj->SaveToDB();
1043 obj->Refresh();
1045 PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o);
1047 return true;
1050 //move selected creature
1051 bool ChatHandler::HandleNpcMoveCommand(const char* args)
1053 uint32 lowguid = 0;
1055 Creature* pCreature = getSelectedCreature();
1057 if(!pCreature)
1059 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1060 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1061 if(!cId)
1062 return false;
1064 uint32 lowguid = atoi(cId);
1066 /* FIXME: impossibel without entry
1067 if(lowguid)
1068 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1071 // Attempting creature load from DB data
1072 if(!pCreature)
1074 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1075 if(!data)
1077 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1078 SetSentErrorMessage(true);
1079 return false;
1082 uint32 map_id = data->mapid;
1084 if(m_session->GetPlayer()->GetMapId()!=map_id)
1086 PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1087 SetSentErrorMessage(true);
1088 return false;
1091 else
1093 lowguid = pCreature->GetDBTableGUIDLow();
1096 else
1098 lowguid = pCreature->GetDBTableGUIDLow();
1101 float x = m_session->GetPlayer()->GetPositionX();
1102 float y = m_session->GetPlayer()->GetPositionY();
1103 float z = m_session->GetPlayer()->GetPositionZ();
1104 float o = m_session->GetPlayer()->GetOrientation();
1106 if (pCreature)
1108 if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1110 const_cast<CreatureData*>(data)->posX = x;
1111 const_cast<CreatureData*>(data)->posY = y;
1112 const_cast<CreatureData*>(data)->posZ = z;
1113 const_cast<CreatureData*>(data)->orientation = o;
1115 pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o);
1116 pCreature->GetMotionMaster()->Initialize();
1117 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1119 pCreature->setDeathState(JUST_DIED);
1120 pCreature->Respawn();
1124 WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1125 PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1126 return true;
1129 //move selected object
1130 bool ChatHandler::HandleMoveObjectCommand(const char* args)
1132 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
1133 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1134 if(!cId)
1135 return false;
1137 uint32 lowguid = atoi(cId);
1138 if(!lowguid)
1139 return false;
1141 GameObject* obj = NULL;
1143 // by DB guid
1144 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1145 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1147 if(!obj)
1149 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1150 SetSentErrorMessage(true);
1151 return false;
1154 char* px = strtok(NULL, " ");
1155 char* py = strtok(NULL, " ");
1156 char* pz = strtok(NULL, " ");
1158 if (!px)
1160 Player *chr = m_session->GetPlayer();
1162 Map* map = obj->GetMap();
1163 map->Remove(obj,false);
1165 obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
1166 obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX());
1167 obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY());
1168 obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ());
1170 map->Add(obj);
1172 else
1174 if(!py || !pz)
1175 return false;
1177 float x = (float)atof(px);
1178 float y = (float)atof(py);
1179 float z = (float)atof(pz);
1181 if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
1183 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
1184 SetSentErrorMessage(true);
1185 return false;
1188 Map* map = obj->GetMap();
1189 map->Remove(obj,false);
1191 obj->Relocate(x, y, z, obj->GetOrientation());
1192 obj->SetFloatValue(GAMEOBJECT_POS_X, x);
1193 obj->SetFloatValue(GAMEOBJECT_POS_Y, y);
1194 obj->SetFloatValue(GAMEOBJECT_POS_Z, z);
1196 map->Add(obj);
1199 obj->SaveToDB();
1200 obj->Refresh();
1202 PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow());
1204 return true;
1207 //demorph player or unit
1208 bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
1210 Unit *target = getSelectedUnit();
1211 if(!target)
1212 target = m_session->GetPlayer();
1215 // check online security
1216 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
1217 return false;
1219 target->DeMorph();
1221 return true;
1224 //add item in vendorlist
1225 bool ChatHandler::HandleAddVendorItemCommand(const char* args)
1227 if (!*args)
1228 return false;
1230 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1231 if (!pitem)
1233 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1234 SetSentErrorMessage(true);
1235 return false;
1238 uint32 itemId = atol(pitem);
1240 char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
1241 uint32 maxcount = 0;
1242 if (fmaxcount)
1243 maxcount = atol(fmaxcount);
1245 char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
1246 uint32 incrtime = 0;
1247 if (fincrtime)
1248 incrtime = atol(fincrtime);
1250 char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
1251 uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1253 Creature* vendor = getSelectedCreature();
1255 uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1257 if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1259 SetSentErrorMessage(true);
1260 return false;
1263 objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1265 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1267 PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1268 return true;
1271 //del item from vendor list
1272 bool ChatHandler::HandleDelVendorItemCommand(const char* args)
1274 if (!*args)
1275 return false;
1277 Creature* vendor = getSelectedCreature();
1278 if (!vendor || !vendor->isVendor())
1280 SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1281 SetSentErrorMessage(true);
1282 return false;
1285 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1286 if (!pitem)
1288 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1289 SetSentErrorMessage(true);
1290 return false;
1292 uint32 itemId = atol(pitem);
1294 if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1296 PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1297 SetSentErrorMessage(true);
1298 return false;
1301 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1303 PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1304 return true;
1307 //add move for creature
1308 bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
1310 if(!*args)
1311 return false;
1313 char* guid_str = strtok((char*)args, " ");
1314 char* wait_str = strtok((char*)NULL, " ");
1316 uint32 lowguid = atoi((char*)guid_str);
1318 Creature* pCreature = NULL;
1320 /* FIXME: impossible without entry
1321 if(lowguid)
1322 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1325 // attempt check creature existence by DB data
1326 if(!pCreature)
1328 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1329 if(!data)
1331 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1332 SetSentErrorMessage(true);
1333 return false;
1336 else
1338 // obtain real GUID for DB operations
1339 lowguid = pCreature->GetDBTableGUIDLow();
1342 int wait = wait_str ? atoi(wait_str) : 0;
1344 if(wait < 0)
1345 wait = 0;
1347 Player* player = m_session->GetPlayer();
1349 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1351 // update movement type
1352 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1353 if(pCreature)
1355 pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1356 pCreature->GetMotionMaster()->Initialize();
1357 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1359 pCreature->setDeathState(JUST_DIED);
1360 pCreature->Respawn();
1362 pCreature->SaveToDB();
1365 SendSysMessage(LANG_WAYPOINT_ADDED);
1367 return true;
1371 * Set the movement type for an NPC.<br/>
1372 * <br/>
1373 * Valid movement types are:
1374 * <ul>
1375 * <li> stay - NPC wont move </li>
1376 * <li> random - NPC will move randomly according to the spawndist </li>
1377 * <li> way - NPC will move with given waypoints set </li>
1378 * </ul>
1379 * additional parameter: NODEL - so no waypoints are deleted, if you
1380 * change the movement type
1382 bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
1384 if(!*args)
1385 return false;
1387 // 3 arguments:
1388 // GUID (optional - you can also select the creature)
1389 // stay|random|way (determines the kind of movement)
1390 // NODEL (optional - tells the system NOT to delete any waypoints)
1391 // this is very handy if you want to do waypoints, that are
1392 // later switched on/off according to special events (like escort
1393 // quests, etc)
1394 char* guid_str = strtok((char*)args, " ");
1395 char* type_str = strtok((char*)NULL, " ");
1396 char* dontdel_str = strtok((char*)NULL, " ");
1398 bool doNotDelete = false;
1400 if(!guid_str)
1401 return false;
1403 uint32 lowguid = 0;
1404 Creature* pCreature = NULL;
1406 if( dontdel_str )
1408 //sLog.outError("DEBUG: All 3 params are set");
1410 // All 3 params are set
1411 // GUID
1412 // type
1413 // doNotDEL
1414 if( stricmp( dontdel_str, "NODEL" ) == 0 )
1416 //sLog.outError("DEBUG: doNotDelete = true;");
1417 doNotDelete = true;
1420 else
1422 // Only 2 params - but maybe NODEL is set
1423 if( type_str )
1425 sLog.outError("DEBUG: Only 2 params ");
1426 if( stricmp( type_str, "NODEL" ) == 0 )
1428 //sLog.outError("DEBUG: type_str, NODEL ");
1429 doNotDelete = true;
1430 type_str = NULL;
1435 if(!type_str) // case .setmovetype $move_type (with selected creature)
1437 type_str = guid_str;
1438 pCreature = getSelectedCreature();
1439 if(!pCreature || pCreature->isPet())
1440 return false;
1441 lowguid = pCreature->GetDBTableGUIDLow();
1443 else // case .setmovetype #creature_guid $move_type (with selected creature)
1445 lowguid = atoi((char*)guid_str);
1447 /* impossible without entry
1448 if(lowguid)
1449 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1452 // attempt check creature existence by DB data
1453 if(!pCreature)
1455 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1456 if(!data)
1458 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1459 SetSentErrorMessage(true);
1460 return false;
1463 else
1465 lowguid = pCreature->GetDBTableGUIDLow();
1469 // now lowguid is low guid really existed creature
1470 // and pCreature point (maybe) to this creature or NULL
1472 MovementGeneratorType move_type;
1474 std::string type = type_str;
1476 if(type == "stay")
1477 move_type = IDLE_MOTION_TYPE;
1478 else if(type == "random")
1479 move_type = RANDOM_MOTION_TYPE;
1480 else if(type == "way")
1481 move_type = WAYPOINT_MOTION_TYPE;
1482 else
1483 return false;
1485 // update movement type
1486 if(doNotDelete == false)
1487 WaypointMgr.DeletePath(lowguid);
1489 if(pCreature)
1491 pCreature->SetDefaultMovementType(move_type);
1492 pCreature->GetMotionMaster()->Initialize();
1493 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1495 pCreature->setDeathState(JUST_DIED);
1496 pCreature->Respawn();
1498 pCreature->SaveToDB();
1500 if( doNotDelete == false )
1502 PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1504 else
1506 PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1509 return true;
1510 } // HandleNpcSetMoveTypeCommand
1512 //change level of creature or pet
1513 bool ChatHandler::HandleChangeLevelCommand(const char* args)
1515 if (!*args)
1516 return false;
1518 uint8 lvl = (uint8) atoi((char*)args);
1519 if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3)
1521 SendSysMessage(LANG_BAD_VALUE);
1522 SetSentErrorMessage(true);
1523 return false;
1526 Creature* pCreature = getSelectedCreature();
1527 if(!pCreature)
1529 SendSysMessage(LANG_SELECT_CREATURE);
1530 SetSentErrorMessage(true);
1531 return false;
1534 if(pCreature->isPet())
1536 ((Pet*)pCreature)->GivePetLevel(lvl);
1538 else
1540 pCreature->SetMaxHealth( 100 + 30*lvl);
1541 pCreature->SetHealth( 100 + 30*lvl);
1542 pCreature->SetLevel( lvl);
1543 pCreature->SaveToDB();
1546 return true;
1549 //set npcflag of creature
1550 bool ChatHandler::HandleNpcFlagCommand(const char* args)
1552 if (!*args)
1553 return false;
1555 uint32 npcFlags = (uint32) atoi((char*)args);
1557 Creature* pCreature = getSelectedCreature();
1559 if(!pCreature)
1561 SendSysMessage(LANG_SELECT_CREATURE);
1562 SetSentErrorMessage(true);
1563 return false;
1566 pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1568 WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1570 SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1572 return true;
1575 //set model of creature
1576 bool ChatHandler::HandleNpcSetModelCommand(const char* args)
1578 if (!*args)
1579 return false;
1581 uint32 displayId = (uint32) atoi((char*)args);
1583 Creature *pCreature = getSelectedCreature();
1585 if(!pCreature || pCreature->isPet())
1587 SendSysMessage(LANG_SELECT_CREATURE);
1588 SetSentErrorMessage(true);
1589 return false;
1592 pCreature->SetDisplayId(displayId);
1593 pCreature->SetNativeDisplayId(displayId);
1595 pCreature->SaveToDB();
1597 return true;
1600 //morph creature or player
1601 bool ChatHandler::HandleMorphCommand(const char* args)
1603 if (!*args)
1604 return false;
1606 uint16 display_id = (uint16)atoi((char*)args);
1608 Unit *target = getSelectedUnit();
1609 if(!target)
1610 target = m_session->GetPlayer();
1612 // check online security
1613 else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
1614 return false;
1616 target->SetDisplayId(display_id);
1618 return true;
1621 //set faction of creature
1622 bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
1624 if (!*args)
1625 return false;
1627 uint32 factionId = (uint32) atoi((char*)args);
1629 if (!sFactionTemplateStore.LookupEntry(factionId))
1631 PSendSysMessage(LANG_WRONG_FACTION, factionId);
1632 SetSentErrorMessage(true);
1633 return false;
1636 Creature* pCreature = getSelectedCreature();
1638 if(!pCreature)
1640 SendSysMessage(LANG_SELECT_CREATURE);
1641 SetSentErrorMessage(true);
1642 return false;
1645 pCreature->setFaction(factionId);
1647 // faction is set in creature_template - not inside creature
1649 // update in memory
1650 if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1652 const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1653 const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1656 // and DB
1657 WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1659 return true;
1662 //kick player
1663 bool ChatHandler::HandleKickPlayerCommand(const char *args)
1665 char* kickName = strtok((char*)args, " ");
1666 if (!kickName)
1668 Player* player = getSelectedPlayer();
1670 if(!player)
1672 SendSysMessage(LANG_NO_CHAR_SELECTED);
1673 SetSentErrorMessage(true);
1674 return false;
1677 if(player==m_session->GetPlayer())
1679 SendSysMessage(LANG_COMMAND_KICKSELF);
1680 SetSentErrorMessage(true);
1681 return false;
1684 // check online security
1685 if (HasLowerSecurity(player, 0))
1686 return false;
1688 player->GetSession()->KickPlayer();
1690 else
1692 std::string name = kickName;
1693 if(!normalizePlayerName(name))
1695 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1696 SetSentErrorMessage(true);
1697 return false;
1700 if(m_session && name==m_session->GetPlayer()->GetName())
1702 SendSysMessage(LANG_COMMAND_KICKSELF);
1703 SetSentErrorMessage(true);
1704 return false;
1707 // check online security
1708 Player* player = ObjectAccessor::Instance().FindPlayerByName(name.c_str());
1709 if (player && HasLowerSecurity(player, 0))
1710 return false;
1712 if(sWorld.KickPlayer(name))
1714 PSendSysMessage(LANG_COMMAND_KICKMESSAGE,name.c_str());
1716 else
1717 PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,name.c_str());
1720 return true;
1723 //show info of player
1724 bool ChatHandler::HandlePInfoCommand(const char* args)
1726 Player* target = NULL;
1727 uint64 targetGUID = 0;
1729 char* px = strtok((char*)args, " ");
1730 char* py = NULL;
1732 std::string name;
1734 if (px)
1736 name = px;
1738 if(name.empty())
1739 return false;
1741 if(!normalizePlayerName(name))
1743 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1744 SetSentErrorMessage(true);
1745 return false;
1748 target = objmgr.GetPlayer(name.c_str());
1749 if (target)
1750 py = strtok(NULL, " ");
1751 else
1753 targetGUID = objmgr.GetPlayerGUIDByName(name);
1754 if(targetGUID)
1755 py = strtok(NULL, " ");
1756 else
1757 py = px;
1761 if(!target && !targetGUID)
1763 target = getSelectedPlayer();
1766 if(!target && !targetGUID)
1768 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1769 SetSentErrorMessage(true);
1770 return false;
1773 uint32 accId = 0;
1774 uint32 money = 0;
1775 uint32 total_player_time = 0;
1776 uint32 level = 0;
1777 uint32 latency = 0;
1779 // get additional information from Player object
1780 if(target)
1782 // check online security
1783 if (HasLowerSecurity(target, 0))
1784 return false;
1786 targetGUID = target->GetGUID();
1787 name = target->GetName(); // re-read for case getSelectedPlayer() target
1788 accId = target->GetSession()->GetAccountId();
1789 money = target->GetMoney();
1790 total_player_time = target->GetTotalPlayedTime();
1791 level = target->getLevel();
1792 latency = target->GetSession()->GetLatency();
1794 // get additional information from DB
1795 else
1797 // check offline security
1798 if (HasLowerSecurity(NULL, targetGUID))
1799 return false;
1801 // 0
1802 QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID));
1803 if (!result)
1805 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1806 SetSentErrorMessage(true);
1807 return false;
1809 Field *fields = result->Fetch();
1810 total_player_time = fields[0].GetUInt32();
1811 delete result;
1813 Tokens data;
1814 if (!Player::LoadValuesArrayFromDB(data,targetGUID))
1816 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1817 SetSentErrorMessage(true);
1818 return false;
1821 money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE);
1822 level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL);
1824 accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
1827 std::string username = GetMangosString(LANG_ERROR);
1828 std::string last_ip = GetMangosString(LANG_ERROR);
1829 uint32 security = 0;
1830 std::string last_login = GetMangosString(LANG_ERROR);
1832 QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
1833 if(result)
1835 Field* fields = result->Fetch();
1836 username = fields[0].GetCppString();
1837 security = fields[1].GetUInt32();
1839 if(!m_session || m_session->GetSecurity() >= security)
1841 last_ip = fields[2].GetCppString();
1842 last_login = fields[3].GetCppString();
1844 else
1846 last_ip = "-";
1847 last_login = "-";
1850 delete result;
1853 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);
1855 std::string timeStr = secsToTimeString(total_player_time,true,true);
1856 uint32 gold = money /GOLD;
1857 uint32 silv = (money % GOLD) / SILVER;
1858 uint32 copp = (money % GOLD) % SILVER;
1859 PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp );
1861 if ( py && strncmp(py, "rep", 3) == 0 )
1863 if(!target)
1865 // rep option not implemented for offline case
1866 SendSysMessage(LANG_PINFO_NO_REP);
1867 SetSentErrorMessage(true);
1868 return false;
1871 char* FactionName;
1872 for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr)
1874 FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
1875 if (factionEntry)
1876 FactionName = factionEntry->name[m_session->GetSessionDbcLocale()];
1877 else
1878 FactionName = "#Not found#";
1879 ReputationRank rank = target->GetReputationRank(factionEntry);
1880 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
1881 std::ostringstream ss;
1882 ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << FactionName << "]|h|r " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
1884 if(itr->second.Flags & FACTION_FLAG_VISIBLE)
1885 ss << GetMangosString(LANG_FACTION_VISIBLE);
1886 if(itr->second.Flags & FACTION_FLAG_AT_WAR)
1887 ss << GetMangosString(LANG_FACTION_ATWAR);
1888 if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
1889 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
1890 if(itr->second.Flags & FACTION_FLAG_HIDDEN)
1891 ss << GetMangosString(LANG_FACTION_HIDDEN);
1892 if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
1893 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
1894 if(itr->second.Flags & FACTION_FLAG_INACTIVE)
1895 ss << GetMangosString(LANG_FACTION_INACTIVE);
1897 SendSysMessage(ss.str().c_str());
1900 return true;
1903 //show tickets
1904 void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
1906 std::string name;
1907 if(!objmgr.GetPlayerNameByGUID(guid,name))
1908 name = GetMangosString(LANG_UNKNOWN);
1910 PSendSysMessage(LANG_COMMAND_TICKETVIEW, name.c_str(),time,text);
1913 //ticket commands
1914 bool ChatHandler::HandleTicketCommand(const char* args)
1916 char* px = strtok((char*)args, " ");
1918 // ticket<end>
1919 if (!px)
1921 if(!m_session)
1923 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1924 SetSentErrorMessage(true);
1925 return false;
1928 size_t count = ticketmgr.GetTicketCount();
1930 bool accept = m_session->GetPlayer()->isAcceptTickets();
1932 PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
1933 return true;
1936 // ticket on
1937 if(strncmp(px,"on",3) == 0)
1939 if(!m_session)
1941 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1942 SetSentErrorMessage(true);
1943 return false;
1946 m_session->GetPlayer()->SetAcceptTicket(true);
1947 SendSysMessage(LANG_COMMAND_TICKETON);
1948 return true;
1951 // ticket off
1952 if(strncmp(px,"off",4) == 0)
1954 if(!m_session)
1956 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1957 SetSentErrorMessage(true);
1958 return false;
1961 m_session->GetPlayer()->SetAcceptTicket(false);
1962 SendSysMessage(LANG_COMMAND_TICKETOFF);
1963 return true;
1966 // ticket #num
1967 int num = atoi(px);
1968 if(num > 0)
1970 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
1972 if(!result)
1974 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
1975 SetSentErrorMessage(true);
1976 return false;
1979 Field* fields = result->Fetch();
1981 uint32 guid = fields[0].GetUInt32();
1982 char const* text = fields[1].GetString();
1983 char const* time = fields[2].GetString();
1985 ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
1986 delete result;
1987 return true;
1990 std::string name = px;
1992 if(!normalizePlayerName(name))
1994 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1995 SetSentErrorMessage(true);
1996 return false;
1999 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2001 if(!guid)
2002 return false;
2004 // ticket $char_name
2005 GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(guid));
2006 if(!ticket)
2007 return false;
2009 std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
2011 ShowTicket(guid, ticket->GetText(), time.c_str());
2013 return true;
2016 //dell all tickets
2017 bool ChatHandler::HandleDelTicketCommand(const char *args)
2019 char* px = strtok((char*)args, " ");
2020 if (!px)
2021 return false;
2023 // delticket all
2024 if(strncmp(px,"all",4) == 0)
2026 ticketmgr.DeleteAll();
2027 SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2028 return true;
2031 int num = (uint32)atoi(px);
2033 // delticket #num
2034 if(num > 0)
2036 QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2037 if(!result)
2039 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2040 SetSentErrorMessage(true);
2041 return false;
2043 Field* fields = result->Fetch();
2044 uint32 guid = fields[0].GetUInt32();
2045 delete result;
2047 ticketmgr.Delete(guid);
2049 //notify player
2050 if(Player* pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)))
2052 pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
2053 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, pl->GetName());
2055 else
2056 PSendSysMessage(LANG_COMMAND_TICKETDEL);
2058 return true;
2061 std::string name = px;
2063 if(!normalizePlayerName(name))
2065 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2066 SetSentErrorMessage(true);
2067 return false;
2070 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2072 if(!guid)
2073 return false;
2075 // delticket $char_name
2076 ticketmgr.Delete(GUID_LOPART(guid));
2078 // notify players about ticket deleting
2079 if(Player* sender = objmgr.GetPlayer(guid))
2080 sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2082 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,px);
2083 return true;
2086 //set spawn dist of creature
2087 bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
2089 if(!*args)
2090 return false;
2092 float option = atof((char*)args);
2093 if (option < 0.0f)
2095 SendSysMessage(LANG_BAD_VALUE);
2096 return false;
2099 MovementGeneratorType mtype = IDLE_MOTION_TYPE;
2100 if (option >0.0f)
2101 mtype = RANDOM_MOTION_TYPE;
2103 Creature *pCreature = getSelectedCreature();
2104 uint32 u_guidlow = 0;
2106 if (pCreature)
2107 u_guidlow = pCreature->GetDBTableGUIDLow();
2108 else
2109 return false;
2111 pCreature->SetRespawnRadius((float)option);
2112 pCreature->SetDefaultMovementType(mtype);
2113 pCreature->GetMotionMaster()->Initialize();
2114 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
2116 pCreature->setDeathState(JUST_DIED);
2117 pCreature->Respawn();
2120 WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
2121 PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
2122 return true;
2125 bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
2127 if(!*args)
2128 return false;
2130 char* stime = strtok((char*)args, " ");
2132 if (!stime)
2133 return false;
2135 int i_stime = atoi((char*)stime);
2137 if (i_stime < 0)
2139 SendSysMessage(LANG_BAD_VALUE);
2140 SetSentErrorMessage(true);
2141 return false;
2144 Creature *pCreature = getSelectedCreature();
2145 uint32 u_guidlow = 0;
2147 if (pCreature)
2148 u_guidlow = pCreature->GetDBTableGUIDLow();
2149 else
2150 return false;
2152 WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
2153 pCreature->SetRespawnDelay((uint32)i_stime);
2154 PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
2156 return true;
2160 * Add a waypoint to a creature.
2162 * The user can either select an npc or provide its GUID.
2164 * The user can even select a visual waypoint - then the new waypoint
2165 * is placed *after* the selected one - this makes insertion of new
2166 * waypoints possible.
2168 * eg:
2169 * .wp add 12345
2170 * -> adds a waypoint to the npc with the GUID 12345
2172 * .wp add
2173 * -> adds a waypoint to the currently selected creature
2176 * @param args if the user did not provide a GUID, it is NULL
2178 * @return true - command did succeed, false - something went wrong
2180 bool ChatHandler::HandleWpAddCommand(const char* args)
2182 sLog.outDebug("DEBUG: HandleWpAddCommand");
2184 // optional
2185 char* guid_str = NULL;
2187 if(*args)
2189 guid_str = strtok((char*)args, " ");
2192 uint32 lowguid = 0;
2193 uint32 point = 0;
2194 Creature* target = getSelectedCreature();
2195 // Did player provide a GUID?
2196 if (!guid_str)
2198 sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2200 // No GUID provided
2201 // -> Player must have selected a creature
2203 if(!target || target->isPet())
2205 SendSysMessage(LANG_SELECT_CREATURE);
2206 SetSentErrorMessage(true);
2207 return false;
2209 if (target->GetEntry() == VISUAL_WAYPOINT )
2211 sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2213 QueryResult *result =
2214 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2215 target->GetGUIDLow() );
2216 if(!result)
2218 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2219 // User selected a visual spawnpoint -> get the NPC
2220 // Select NPC GUID
2221 // Since we compare float values, we have to deal with
2222 // some difficulties.
2223 // Here we search for all waypoints that only differ in one from 1 thousand
2224 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2225 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2226 const char* maxDIFF = "0.01";
2227 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 )",
2228 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2229 if(!result)
2231 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2232 SetSentErrorMessage(true);
2233 return false;
2238 Field *fields = result->Fetch();
2239 lowguid = fields[0].GetUInt32();
2240 point = fields[1].GetUInt32();
2241 }while( result->NextRow() );
2242 delete result;
2244 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2245 if(!data)
2247 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2248 SetSentErrorMessage(true);
2249 return false;
2252 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2253 if(!target)
2255 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2256 SetSentErrorMessage(true);
2257 return false;
2260 else
2262 lowguid = target->GetDBTableGUIDLow();
2265 else
2267 sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2269 // GUID provided
2270 // Warn if player also selected a creature
2271 // -> Creature selection is ignored <-
2272 if(target)
2274 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2276 lowguid = atoi((char*)guid_str);
2278 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2279 if(!data)
2281 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2282 SetSentErrorMessage(true);
2283 return false;
2286 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2287 if(!target || target->isPet())
2289 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2290 SetSentErrorMessage(true);
2291 return false;
2294 // lowguid -> GUID of the NPC
2295 // point -> number of the waypoint (if not 0)
2296 sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2298 sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2300 Player* player = m_session->GetPlayer();
2301 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2303 // update movement type
2304 if(target)
2306 target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2307 target->GetMotionMaster()->Initialize();
2308 if(target->isAlive()) // dead creature will reset movement generator at respawn
2310 target->setDeathState(JUST_DIED);
2311 target->Respawn();
2313 target->SaveToDB();
2315 else
2316 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2318 PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2320 return true;
2321 } // HandleWpAddCommand
2324 * .wp modify emote | spell | text | del | move | add
2326 * add -> add a WP after the selected visual waypoint
2327 * User must select a visual waypoint and then issue ".wp modify add"
2329 * emote <emoteID>
2330 * User has selected a visual waypoint before.
2331 * <emoteID> is added to this waypoint. Everytime the
2332 * NPC comes to this waypoint, the emote is called.
2334 * emote <GUID> <WPNUM> <emoteID>
2335 * User has not selected visual waypoint before.
2336 * For the waypoint <WPNUM> for the NPC with <GUID>
2337 * an emote <emoteID> is added.
2338 * Everytime the NPC comes to this waypoint, the emote is called.
2341 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2343 bool ChatHandler::HandleWpModifyCommand(const char* args)
2345 sLog.outDebug("DEBUG: HandleWpModifyCommand");
2347 if(!*args)
2348 return false;
2350 // first arg: add del text emote spell waittime move
2351 char* show_str = strtok((char*)args, " ");
2352 if (!show_str)
2354 return false;
2357 std::string show = show_str;
2358 // Check
2359 // Remember: "show" must also be the name of a column!
2360 if( (show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2")
2361 && (show != "textid3") && (show != "textid4") && (show != "textid5")
2362 && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2363 && (show != "model1") && (show != "model2") && (show != "orientation"))
2365 return false;
2368 // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2370 // Did user provide a GUID
2371 // or did the user select a creature?
2372 // -> variable lowguid is filled with the GUID of the NPC
2373 uint32 lowguid = 0;
2374 uint32 point = 0;
2375 uint32 wpGuid = 0;
2376 Creature* target = getSelectedCreature();
2378 if(target)
2380 sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2382 // Did the user select a visual spawnpoint?
2383 if (target->GetEntry() != VISUAL_WAYPOINT )
2385 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2386 SetSentErrorMessage(true);
2387 return false;
2390 wpGuid = target->GetGUIDLow();
2392 // The visual waypoint
2393 QueryResult *result =
2394 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2395 target->GetGUIDLow() );
2396 if(!result)
2398 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2399 SetSentErrorMessage(true);
2400 return false;
2402 sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2404 Field *fields = result->Fetch();
2405 lowguid = fields[0].GetUInt32();
2406 point = fields[1].GetUInt32();
2408 // Cleanup memory
2409 sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2410 delete result;
2412 else
2414 // User did provide <GUID> <WPNUM>
2416 char* guid_str = strtok((char*)NULL, " ");
2417 if( !guid_str )
2419 SendSysMessage(LANG_WAYPOINT_NOGUID);
2420 return false;
2422 lowguid = atoi((char*)guid_str);
2424 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2425 if(!data)
2427 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2428 SetSentErrorMessage(true);
2429 return false;
2432 PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2434 char* point_str = strtok((char*)NULL, " ");
2435 if( !point_str )
2437 SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2438 return false;
2440 point = atoi((char*)point_str);
2442 PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2444 // Now we need the GUID of the visual waypoint
2445 // -> "del", "move", "add" command
2447 QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2448 if (!result)
2450 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2451 SetSentErrorMessage(true);
2452 return false;
2455 Field *fields = result->Fetch();
2456 wpGuid = fields[0].GetUInt32();
2458 // Free memory
2459 delete result;
2462 char* arg_str = NULL;
2463 // Check for argument
2464 if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2466 // Text is enclosed in "<>", all other arguments not
2467 if( show.find("text") != std::string::npos )
2468 arg_str = strtok((char*)NULL, "<>");
2469 else
2470 arg_str = strtok((char*)NULL, " ");
2472 if( !arg_str)
2474 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2475 return false;
2479 sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2481 // wpGuid -> GUID of the waypoint creature
2482 // lowguid -> GUID of the NPC
2483 // point -> waypoint number
2485 // Special functions:
2486 // add - move - del -> no args commands
2487 // Add a waypoint after the selected visual
2488 if(show == "add" && target)
2490 PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2492 // Get the creature for which we read the waypoint
2493 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2494 if(!data)
2496 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2497 SetSentErrorMessage(true);
2498 return false;
2501 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2503 if( !npcCreature )
2505 PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2506 SetSentErrorMessage(true);
2507 return false;
2510 sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2512 // What to do:
2513 // Add the visual spawnpoint (DB only)
2514 // Adjust the waypoints
2515 // Respawn the owner of the waypoints
2516 sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2518 Player* chr = m_session->GetPlayer();
2519 Map *map = chr->GetMap();
2521 if(npcCreature)
2523 npcCreature->GetMotionMaster()->Initialize();
2524 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2526 npcCreature->setDeathState(JUST_DIED);
2527 npcCreature->Respawn();
2531 // create the waypoint creature
2532 wpGuid = 0;
2533 Creature* wpCreature = new Creature;
2534 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map,VISUAL_WAYPOINT,0))
2536 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2537 delete wpCreature;
2539 else
2541 wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2543 if(!wpCreature->IsPositionValid())
2545 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());
2546 delete wpCreature;
2548 else
2550 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2551 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2552 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2553 map->Add(wpCreature);
2554 wpGuid = wpCreature->GetGUIDLow();
2558 WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2560 if(!wpGuid)
2561 return false;
2563 PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2564 return true;
2565 } // add
2567 if(show == "del" && target)
2569 PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2571 // Get the creature for which we read the waypoint
2572 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2573 if(!data)
2575 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2576 SetSentErrorMessage(true);
2577 return false;
2580 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2582 // wpCreature
2583 Creature* wpCreature = NULL;
2584 if( wpGuid != 0 )
2586 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2587 wpCreature->DeleteFromDB();
2588 wpCreature->CleanupsBeforeDelete();
2589 wpCreature->AddObjectToRemoveList();
2592 // What to do:
2593 // Remove the visual spawnpoint
2594 // Adjust the waypoints
2595 // Respawn the owner of the waypoints
2597 WaypointMgr.DeleteNode(lowguid, point);
2599 if(npcCreature)
2601 // Any waypoints left?
2602 QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2603 if(!result2)
2605 npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2607 else
2609 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2610 delete result2;
2612 npcCreature->GetMotionMaster()->Initialize();
2613 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2615 npcCreature->setDeathState(JUST_DIED);
2616 npcCreature->Respawn();
2618 npcCreature->SaveToDB();
2621 PSendSysMessage(LANG_WAYPOINT_REMOVED);
2622 return true;
2623 } // del
2625 if(show == "move" && target)
2627 PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2629 Player *chr = m_session->GetPlayer();
2630 Map *map = chr->GetMap();
2632 // Get the creature for which we read the waypoint
2633 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2634 if(!data)
2636 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2637 SetSentErrorMessage(true);
2638 return false;
2641 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2643 // wpCreature
2644 Creature* wpCreature = NULL;
2645 // What to do:
2646 // Move the visual spawnpoint
2647 // Respawn the owner of the waypoints
2648 if( wpGuid != 0 )
2650 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2651 wpCreature->DeleteFromDB();
2652 wpCreature->CleanupsBeforeDelete();
2653 wpCreature->AddObjectToRemoveList();
2654 // re-create
2655 Creature* wpCreature2 = new Creature;
2656 if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0))
2658 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2659 delete wpCreature2;
2660 return false;
2663 wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2665 if(!wpCreature2->IsPositionValid())
2667 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());
2668 delete wpCreature2;
2669 return false;
2672 wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2673 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2674 wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2675 map->Add(wpCreature2);
2676 //npcCreature->GetMap()->Add(wpCreature2);
2679 WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2681 if(npcCreature)
2683 npcCreature->GetMotionMaster()->Initialize();
2684 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2686 npcCreature->setDeathState(JUST_DIED);
2687 npcCreature->Respawn();
2690 PSendSysMessage(LANG_WAYPOINT_CHANGED);
2692 return true;
2693 } // move
2695 // Create creature - npc that has the waypoint
2696 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2697 if(!data)
2699 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2700 SetSentErrorMessage(true);
2701 return false;
2704 // set in game textids not supported
2705 if( show == "textid1" || show == "textid2" || show == "textid3" ||
2706 show == "textid4" || show == "textid5" )
2708 return false;
2711 WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2713 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2714 if(npcCreature)
2716 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2717 npcCreature->GetMotionMaster()->Initialize();
2718 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2720 npcCreature->setDeathState(JUST_DIED);
2721 npcCreature->Respawn();
2724 PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2726 return true;
2730 * .wp show info | on | off
2732 * info -> User has selected a visual waypoint before
2734 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2735 * provided the GUID of the NPC and the number of
2736 * the waypoint.
2738 * on -> User has selected an NPC; all visual waypoints for this
2739 * NPC are added to the world
2741 * on <GUID> -> User did not select an NPC - instead the GUID of the
2742 * NPC is provided. All visual waypoints for this NPC
2743 * are added from the world.
2745 * off -> User has selected an NPC; all visual waypoints for this
2746 * NPC are removed from the world.
2748 * on <GUID> -> User did not select an NPC - instead the GUID of the
2749 * NPC is provided. All visual waypoints for this NPC
2750 * are removed from the world.
2754 bool ChatHandler::HandleWpShowCommand(const char* args)
2756 sLog.outDebug("DEBUG: HandleWpShowCommand");
2758 if(!*args)
2759 return false;
2761 // first arg: on, off, first, last
2762 char* show_str = strtok((char*)args, " ");
2763 if (!show_str)
2765 return false;
2767 // second arg: GUID (optional, if a creature is selected)
2768 char* guid_str = strtok((char*)NULL, " ");
2769 sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
2770 //if (!guid_str) {
2771 // return false;
2774 // Did user provide a GUID
2775 // or did the user select a creature?
2776 // -> variable lowguid is filled with the GUID
2777 Creature* target = getSelectedCreature();
2778 // Did player provide a GUID?
2779 if (!guid_str)
2781 sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
2782 // No GUID provided
2783 // -> Player must have selected a creature
2785 if(!target)
2787 SendSysMessage(LANG_SELECT_CREATURE);
2788 SetSentErrorMessage(true);
2789 return false;
2792 else
2794 sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
2795 // GUID provided
2796 // Warn if player also selected a creature
2797 // -> Creature selection is ignored <-
2798 if(target)
2800 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2803 uint32 lowguid = atoi((char*)guid_str);
2805 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2806 if(!data)
2808 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2809 SetSentErrorMessage(true);
2810 return false;
2813 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2815 if(!target)
2817 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2818 SetSentErrorMessage(true);
2819 return false;
2823 uint32 lowguid = target->GetDBTableGUIDLow();
2825 std::string show = show_str;
2826 uint32 Maxpoint;
2828 sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
2830 // Show info for the selected waypoint
2831 if(show == "info")
2833 PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
2835 // Check if the user did specify a visual waypoint
2836 if( target->GetEntry() != VISUAL_WAYPOINT )
2838 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2839 SetSentErrorMessage(true);
2840 return false;
2843 //PSendSysMessage("wp on, GUID: %u", lowguid);
2845 //pCreature->GetPositionX();
2847 QueryResult *result =
2848 WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u",
2849 target->GetGUIDLow() );
2850 if(!result)
2852 // Since we compare float values, we have to deal with
2853 // some difficulties.
2854 // Here we search for all waypoints that only differ in one from 1 thousand
2855 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2856 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2857 const char* maxDIFF = "0.01";
2858 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
2860 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 )",
2861 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2862 if(!result)
2864 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2865 SetSentErrorMessage(true);
2866 return false;
2871 Field *fields = result->Fetch();
2872 uint32 creGUID = fields[0].GetUInt32();
2873 uint32 point = fields[1].GetUInt32();
2874 int waittime = fields[2].GetUInt32();
2875 uint32 emote = fields[3].GetUInt32();
2876 uint32 spell = fields[4].GetUInt32();
2877 uint32 textid[MAX_WAYPOINT_TEXT];
2878 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
2879 textid[i] = fields[5+i].GetUInt32();
2880 uint32 model1 = fields[10].GetUInt32();
2881 uint32 model2 = fields[11].GetUInt32();
2883 // Get the creature for which we read the waypoint
2884 Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2886 PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
2887 PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
2888 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
2889 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
2890 PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
2891 PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
2892 for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
2893 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i+1, textid[i], (textid[i] ? GetMangosString(textid[i]) : ""));
2895 }while( result->NextRow() );
2896 // Cleanup memory
2897 delete result;
2898 return true;
2901 if(show == "on")
2903 PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
2905 QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
2906 if(!result)
2908 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
2909 SetSentErrorMessage(true);
2910 return false;
2912 // Delete all visuals for this NPC
2913 QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
2914 if(result2)
2916 bool hasError = false;
2919 Field *fields = result2->Fetch();
2920 uint32 wpguid = fields[0].GetUInt32();
2921 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2923 if(!pCreature)
2925 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
2926 hasError = true;
2927 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
2929 else
2931 pCreature->DeleteFromDB();
2932 pCreature->CleanupsBeforeDelete();
2933 pCreature->AddObjectToRemoveList();
2936 }while( result2->NextRow() );
2937 delete result2;
2938 if( hasError )
2940 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
2941 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
2942 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
2948 Field *fields = result->Fetch();
2949 uint32 point = fields[0].GetUInt32();
2950 float x = fields[1].GetFloat();
2951 float y = fields[2].GetFloat();
2952 float z = fields[3].GetFloat();
2954 uint32 id = VISUAL_WAYPOINT;
2956 Player *chr = m_session->GetPlayer();
2957 Map *map = chr->GetMap();
2958 float o = chr->GetOrientation();
2960 Creature* wpCreature = new Creature;
2961 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
2963 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
2964 delete wpCreature;
2965 delete result;
2966 return false;
2969 wpCreature->Relocate(x, y, z, o);
2971 if(!wpCreature->IsPositionValid())
2973 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());
2974 delete wpCreature;
2975 delete result;
2976 return false;
2979 wpCreature->SetVisibility(VISIBILITY_OFF);
2980 sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
2981 // set "wpguid" column to the visual waypoint
2982 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
2984 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2985 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2986 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
2987 map->Add(wpCreature);
2988 //wpCreature->GetMap()->Add(wpCreature);
2989 }while( result->NextRow() );
2991 // Cleanup memory
2992 delete result;
2993 return true;
2996 if(show == "first")
2998 PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3000 QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3001 if(!result)
3003 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3004 SetSentErrorMessage(true);
3005 return false;
3008 Field *fields = result->Fetch();
3009 float x = fields[0].GetFloat();
3010 float y = fields[1].GetFloat();
3011 float z = fields[2].GetFloat();
3012 uint32 id = VISUAL_WAYPOINT;
3014 Player *chr = m_session->GetPlayer();
3015 float o = chr->GetOrientation();
3016 Map *map = chr->GetMap();
3018 Creature* pCreature = new Creature;
3019 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, id, 0))
3021 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3022 delete pCreature;
3023 delete result;
3024 return false;
3027 pCreature->Relocate(x, y, z, o);
3029 if(!pCreature->IsPositionValid())
3031 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());
3032 delete pCreature;
3033 delete result;
3034 return false;
3037 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3038 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3039 map->Add(pCreature);
3040 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3042 // Cleanup memory
3043 delete result;
3044 return true;
3047 if(show == "last")
3049 PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3051 QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3052 if( result )
3054 Maxpoint = (*result)[0].GetUInt32();
3056 delete result;
3058 else
3059 Maxpoint = 0;
3061 result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3062 if(!result)
3064 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3065 SetSentErrorMessage(true);
3066 return false;
3068 Field *fields = result->Fetch();
3069 float x = fields[0].GetFloat();
3070 float y = fields[1].GetFloat();
3071 float z = fields[2].GetFloat();
3072 uint32 id = VISUAL_WAYPOINT;
3074 Player *chr = m_session->GetPlayer();
3075 float o = chr->GetOrientation();
3076 Map *map = chr->GetMap();
3078 Creature* pCreature = new Creature;
3079 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
3081 PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3082 delete pCreature;
3083 delete result;
3084 return false;
3087 pCreature->Relocate(x, y, z, o);
3089 if(!pCreature->IsPositionValid())
3091 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());
3092 delete pCreature;
3093 delete result;
3094 return false;
3097 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3098 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3099 map->Add(pCreature);
3100 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3101 // Cleanup memory
3102 delete result;
3103 return true;
3106 if(show == "off")
3108 QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3109 if(!result)
3111 SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3112 SetSentErrorMessage(true);
3113 return false;
3115 bool hasError = false;
3118 Field *fields = result->Fetch();
3119 uint32 guid = fields[0].GetUInt32();
3120 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3122 //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
3124 if(!pCreature)
3126 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3127 hasError = true;
3128 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3130 else
3132 pCreature->DeleteFromDB();
3133 pCreature->CleanupsBeforeDelete();
3134 pCreature->AddObjectToRemoveList();
3136 }while(result->NextRow());
3137 // set "wpguid" column to "empty" - no visual waypoint spawned
3138 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
3140 if( hasError )
3142 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3143 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3144 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3147 SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3148 // Cleanup memory
3149 delete result;
3151 return true;
3154 PSendSysMessage("DEBUG: wpshow - no valid command found");
3156 return true;
3157 } // HandleWpShowCommand
3159 bool ChatHandler::HandleWpExportCommand(const char *args)
3161 if(!*args)
3162 return false;
3164 // Next arg is: <GUID> <ARGUMENT>
3166 // Did user provide a GUID
3167 // or did the user select a creature?
3168 // -> variable lowguid is filled with the GUID of the NPC
3169 uint32 lowguid = 0;
3170 Creature* target = getSelectedCreature();
3171 char* arg_str = NULL;
3172 if (target)
3174 if (target->GetEntry() != VISUAL_WAYPOINT)
3175 lowguid = target->GetGUIDLow();
3176 else
3178 QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3179 if (!result)
3181 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3182 return true;
3184 Field *fields = result->Fetch();
3185 lowguid = fields[0].GetUInt32();;
3186 delete result;
3189 arg_str = strtok((char*)args, " ");
3191 else
3193 // user provided <GUID>
3194 char* guid_str = strtok((char*)args, " ");
3195 if( !guid_str )
3197 SendSysMessage(LANG_WAYPOINT_NOGUID);
3198 return false;
3200 lowguid = atoi((char*)guid_str);
3202 arg_str = strtok((char*)NULL, " ");
3205 if( !arg_str)
3207 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3208 return false;
3211 PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3213 QueryResult *result = WorldDatabase.PQuery(
3214 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3215 "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 );
3217 if (!result)
3219 PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3220 SetSentErrorMessage(true);
3221 return false;
3224 std::ofstream outfile;
3225 outfile.open (arg_str);
3229 Field *fields = result->Fetch();
3231 outfile << "INSERT INTO creature_movement ";
3232 outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5 ) VALUES ";
3234 outfile << "( ";
3235 outfile << fields[15].GetUInt32(); // id
3236 outfile << ", ";
3237 outfile << fields[0].GetUInt32(); // point
3238 outfile << ", ";
3239 outfile << fields[1].GetFloat(); // position_x
3240 outfile << ", ";
3241 outfile << fields[2].GetFloat(); // position_y
3242 outfile << ", ";
3243 outfile << fields[3].GetUInt32(); // position_z
3244 outfile << ", ";
3245 outfile << fields[4].GetUInt32(); // orientation
3246 outfile << ", ";
3247 outfile << fields[5].GetUInt32(); // model1
3248 outfile << ", ";
3249 outfile << fields[6].GetUInt32(); // model2
3250 outfile << ", ";
3251 outfile << fields[7].GetUInt16(); // waittime
3252 outfile << ", ";
3253 outfile << fields[8].GetUInt32(); // emote
3254 outfile << ", ";
3255 outfile << fields[9].GetUInt32(); // spell
3256 outfile << ", ";
3257 outfile << fields[10].GetUInt32(); // textid1
3258 outfile << ", ";
3259 outfile << fields[11].GetUInt32(); // textid2
3260 outfile << ", ";
3261 outfile << fields[12].GetUInt32(); // textid3
3262 outfile << ", ";
3263 outfile << fields[13].GetUInt32(); // textid4
3264 outfile << ", ";
3265 outfile << fields[14].GetUInt32(); // textid5
3266 outfile << ");\n ";
3268 } while( result->NextRow() );
3269 delete result;
3271 PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3272 outfile.close();
3274 return true;
3277 bool ChatHandler::HandleWpImportCommand(const char *args)
3279 if(!*args)
3280 return false;
3282 char* arg_str = strtok((char*)args, " ");
3283 if (!arg_str)
3284 return false;
3286 std::string line;
3287 std::ifstream infile (arg_str);
3288 if (infile.is_open())
3290 while (! infile.eof() )
3292 getline (infile,line);
3293 //cout << line << endl;
3294 QueryResult *result = WorldDatabase.Query(line.c_str());
3295 delete result;
3297 infile.close();
3299 PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3301 return true;
3304 //rename characters
3305 bool ChatHandler::HandleRenameCommand(const char* args)
3307 Player* target = NULL;
3308 uint64 targetGUID = 0;
3309 std::string oldname;
3311 char* px = strtok((char*)args, " ");
3313 if(px)
3315 oldname = px;
3317 if(!normalizePlayerName(oldname))
3319 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3320 SetSentErrorMessage(true);
3321 return false;
3324 target = objmgr.GetPlayer(oldname.c_str());
3326 if (!target)
3327 targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3330 if(!target && !targetGUID)
3332 target = getSelectedPlayer();
3335 if(!target && !targetGUID)
3337 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3338 SetSentErrorMessage(true);
3339 return false;
3342 if(target)
3344 // check online security
3345 if (HasLowerSecurity(target, 0))
3346 return false;
3348 PSendSysMessage(LANG_RENAME_PLAYER, target->GetName());
3349 target->SetAtLoginFlag(AT_LOGIN_RENAME);
3350 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3352 else
3354 // check offline security
3355 if (HasLowerSecurity(NULL, targetGUID))
3356 return false;
3358 PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
3359 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3362 return true;
3365 // customize characters
3366 bool ChatHandler::HandleCustomizeCommand(const char* args)
3368 Player* target = NULL;
3369 uint64 targetGUID = 0;
3370 std::string oldname;
3372 char* px = strtok((char*)args, " ");
3374 if(px)
3376 oldname = px;
3378 if(!normalizePlayerName(oldname))
3380 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3381 SetSentErrorMessage(true);
3382 return false;
3385 target = objmgr.GetPlayer(oldname.c_str());
3387 if (!target)
3388 targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3391 if(!target && !targetGUID)
3393 target = getSelectedPlayer();
3396 if(!target && !targetGUID)
3398 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3399 SetSentErrorMessage(true);
3400 return false;
3403 if(target)
3405 PSendSysMessage(LANG_CUSTOMIZE_PLAYER, target->GetName());
3406 target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
3407 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow());
3409 else
3411 PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
3412 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3415 return true;
3418 //spawn go
3419 bool ChatHandler::HandleGameObjectCommand(const char* args)
3421 if (!*args)
3422 return false;
3424 char* pParam1 = strtok((char*)args, " ");
3425 if (!pParam1)
3426 return false;
3428 uint32 id = atoi((char*)pParam1);
3429 if(!id)
3430 return false;
3432 char* spawntimeSecs = strtok(NULL, " ");
3434 const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id);
3436 if (!goI)
3438 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
3439 SetSentErrorMessage(true);
3440 return false;
3443 Player *chr = m_session->GetPlayer();
3444 float x = float(chr->GetPositionX());
3445 float y = float(chr->GetPositionY());
3446 float z = float(chr->GetPositionZ());
3447 float o = float(chr->GetOrientation());
3448 Map *map = chr->GetMap();
3450 float rot2 = sin(o/2);
3451 float rot3 = cos(o/2);
3453 GameObject* pGameObj = new GameObject;
3454 uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
3456 if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1))
3458 delete pGameObj;
3459 return false;
3462 if( spawntimeSecs )
3464 uint32 value = atoi((char*)spawntimeSecs);
3465 pGameObj->SetRespawnTime(value);
3466 //sLog.outDebug("*** spawntimeSecs: %d", value);
3469 // fill the gameobject data and save to the db
3470 pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3472 // this will generate a new guid if the object is in an instance
3473 if(!pGameObj->LoadFromDB(db_lowGUID, map))
3475 delete pGameObj;
3476 return false;
3479 sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o);
3481 map->Add(pGameObj);
3483 // TODO: is it really necessary to add both the real and DB table guid here ?
3484 objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
3486 PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z);
3487 return true;
3490 //show animation
3491 bool ChatHandler::HandleAnimCommand(const char* args)
3493 if (!*args)
3494 return false;
3496 uint32 anim_id = atoi((char*)args);
3497 m_session->GetPlayer()->HandleEmoteCommand(anim_id);
3498 return true;
3501 //change standstate
3502 bool ChatHandler::HandleStandStateCommand(const char* args)
3504 if (!*args)
3505 return false;
3507 uint32 anim_id = atoi((char*)args);
3508 m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3510 return true;
3513 bool ChatHandler::HandleAddHonorCommand(const char* args)
3515 if (!*args)
3516 return false;
3518 Player *target = getSelectedPlayer();
3519 if(!target)
3521 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3522 SetSentErrorMessage(true);
3523 return false;
3526 // check online security
3527 if (HasLowerSecurity(target, 0))
3528 return false;
3530 uint32 amount = (uint32)atoi(args);
3531 target->RewardHonor(NULL, 1, amount);
3532 return true;
3535 bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3537 Unit *target = getSelectedUnit();
3538 if(!target)
3540 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3541 SetSentErrorMessage(true);
3542 return false;
3545 // check online security
3546 if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0))
3547 return false;
3549 m_session->GetPlayer()->RewardHonor(target, 1);
3550 return true;
3553 bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/)
3555 Player *target = getSelectedPlayer();
3556 if(!target)
3558 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3559 SetSentErrorMessage(true);
3560 return false;
3563 // check online security
3564 if (HasLowerSecurity(target, 0))
3565 return false;
3567 target->UpdateHonorFields();
3568 return true;
3571 bool ChatHandler::HandleLookupEventCommand(const char* args)
3573 if(!*args)
3574 return false;
3576 std::string namepart = args;
3577 std::wstring wnamepart;
3579 // converting string that we try to find to lower case
3580 if(!Utf8toWStr(namepart,wnamepart))
3581 return false;
3583 wstrToLower(wnamepart);
3585 uint32 counter = 0;
3587 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3588 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3590 for(uint32 id = 0; id < events.size(); ++id )
3592 GameEventData const& eventData = events[id];
3594 std::string descr = eventData.description;
3595 if(descr.empty())
3596 continue;
3598 if (Utf8FitTo(descr, wnamepart))
3600 char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : "";
3602 if(m_session)
3603 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3604 else
3605 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3607 ++counter;
3611 if (counter==0)
3612 SendSysMessage(LANG_NOEVENTFOUND);
3614 return true;
3617 bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/)
3619 uint32 counter = 0;
3621 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3622 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3624 char const* active = GetMangosString(LANG_ACTIVE);
3626 for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
3628 uint32 event_id = *itr;
3629 GameEventData const& eventData = events[event_id];
3631 if(m_session)
3632 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
3633 else
3634 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
3636 ++counter;
3639 if (counter==0)
3640 SendSysMessage(LANG_NOEVENTFOUND);
3642 return true;
3645 bool ChatHandler::HandleEventInfoCommand(const char* args)
3647 if(!*args)
3648 return false;
3650 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3651 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3652 if(!cId)
3653 return false;
3655 uint32 event_id = atoi(cId);
3657 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3659 if(event_id >=events.size())
3661 SendSysMessage(LANG_EVENT_NOT_EXIST);
3662 SetSentErrorMessage(true);
3663 return false;
3666 GameEventData const& eventData = events[event_id];
3667 if(!eventData.isValid())
3669 SendSysMessage(LANG_EVENT_NOT_EXIST);
3670 SetSentErrorMessage(true);
3671 return false;
3674 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3675 bool active = activeEvents.find(event_id) != activeEvents.end();
3676 char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : "";
3678 std::string startTimeStr = TimeToTimestampStr(eventData.start);
3679 std::string endTimeStr = TimeToTimestampStr(eventData.end);
3681 uint32 delay = gameeventmgr.NextCheck(event_id);
3682 time_t nextTime = time(NULL)+delay;
3683 std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3685 std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3686 std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3688 PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3689 startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3690 nextStr.c_str());
3691 return true;
3694 bool ChatHandler::HandleEventStartCommand(const char* args)
3696 if(!*args)
3697 return false;
3699 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3700 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3701 if(!cId)
3702 return false;
3704 int32 event_id = atoi(cId);
3706 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3708 if(event_id < 1 || event_id >=events.size())
3710 SendSysMessage(LANG_EVENT_NOT_EXIST);
3711 SetSentErrorMessage(true);
3712 return false;
3715 GameEventData const& eventData = events[event_id];
3716 if(!eventData.isValid())
3718 SendSysMessage(LANG_EVENT_NOT_EXIST);
3719 SetSentErrorMessage(true);
3720 return false;
3723 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3724 if(activeEvents.find(event_id) != activeEvents.end())
3726 PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3727 SetSentErrorMessage(true);
3728 return false;
3731 gameeventmgr.StartEvent(event_id,true);
3732 return true;
3735 bool ChatHandler::HandleEventStopCommand(const char* args)
3737 if(!*args)
3738 return false;
3740 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3741 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3742 if(!cId)
3743 return false;
3745 int32 event_id = atoi(cId);
3747 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3749 if(event_id < 1 || event_id >=events.size())
3751 SendSysMessage(LANG_EVENT_NOT_EXIST);
3752 SetSentErrorMessage(true);
3753 return false;
3756 GameEventData const& eventData = events[event_id];
3757 if(!eventData.isValid())
3759 SendSysMessage(LANG_EVENT_NOT_EXIST);
3760 SetSentErrorMessage(true);
3761 return false;
3764 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3766 if(activeEvents.find(event_id) == activeEvents.end())
3768 PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3769 SetSentErrorMessage(true);
3770 return false;
3773 gameeventmgr.StopEvent(event_id,true);
3774 return true;
3777 bool ChatHandler::HandleCombatStopCommand(const char* args)
3779 Player *player;
3781 if(*args)
3783 std::string playername = args;
3785 if(!normalizePlayerName(playername))
3787 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3788 SetSentErrorMessage(true);
3789 return false;
3792 player = objmgr.GetPlayer(playername.c_str());
3794 if(!player)
3796 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3797 SetSentErrorMessage(true);
3798 return false;
3801 else
3803 player = getSelectedPlayer();
3805 if (!player)
3806 player = m_session->GetPlayer();
3809 // check online security
3810 if (HasLowerSecurity(player, 0))
3811 return false;
3813 player->CombatStop();
3814 player->getHostilRefManager().deleteReferences();
3815 return true;
3818 bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3820 uint32 classmask = m_session->GetPlayer()->getClassMask();
3822 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3824 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3825 if( !skillInfo )
3826 continue;
3828 if( skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY )
3830 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3832 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3833 if( !skillLine )
3834 continue;
3836 // skip racial skills
3837 if( skillLine->racemask != 0 )
3838 continue;
3840 // skip wrong class skills
3841 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3842 continue;
3844 if( skillLine->skillId != i || skillLine->forward_spellid )
3845 continue;
3847 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3848 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3849 continue;
3851 m_session->GetPlayer()->learnSpell(skillLine->spellId);
3856 SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
3857 return true;
3860 bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
3862 // Learns all recipes of specified profession and sets skill to max
3863 // Example: .learn all_recipes enchanting
3865 Player* target = getSelectedPlayer();
3866 if( !target )
3868 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3869 return false;
3872 if(!*args)
3873 return false;
3875 std::wstring wnamepart;
3877 if(!Utf8toWStr(args,wnamepart))
3878 return false;
3880 // converting string that we try to find to lower case
3881 wstrToLower( wnamepart );
3883 uint32 classmask = m_session->GetPlayer()->getClassMask();
3885 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3887 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3888 if( !skillInfo )
3889 continue;
3891 if( skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
3892 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY )
3893 continue;
3895 int loc = m_session->GetSessionDbcLocale();
3896 std::string name = skillInfo->name[loc];
3898 if(Utf8FitTo(name, wnamepart))
3900 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3902 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3903 if( !skillLine )
3904 continue;
3906 if( skillLine->skillId != i || skillLine->forward_spellid )
3907 continue;
3909 // skip racial skills
3910 if( skillLine->racemask != 0 )
3911 continue;
3913 // skip wrong class skills
3914 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3915 continue;
3917 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3918 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3919 continue;
3921 if( !target->HasSpell(spellInfo->Id) )
3922 m_session->GetPlayer()->learnSpell(skillLine->spellId);
3925 uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
3926 target->SetSkill(skillInfo->id, maxLevel, maxLevel);
3927 PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
3928 return true;
3932 return false;
3935 bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
3938 if (!*args)
3939 return false;
3941 std::string ip = strtok ((char*)args, " ");
3942 char* limit_str = strtok (NULL, " ");
3943 int32 limit = limit_str ? atoi (limit_str) : -1;
3945 loginDatabase.escape_string (ip);
3947 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
3949 return LookupPlayerSearchCommand (result,limit);
3952 bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
3954 if (!*args)
3955 return false;
3957 std::string account = strtok ((char*)args, " ");
3958 char* limit_str = strtok (NULL, " ");
3959 int32 limit = limit_str ? atoi (limit_str) : -1;
3961 if (!AccountMgr::normilizeString (account))
3962 return false;
3964 loginDatabase.escape_string (account);
3966 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
3968 return LookupPlayerSearchCommand (result,limit);
3971 bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
3974 if (!*args)
3975 return false;
3977 std::string email = strtok ((char*)args, " ");
3978 char* limit_str = strtok (NULL, " ");
3979 int32 limit = limit_str ? atoi (limit_str) : -1;
3981 loginDatabase.escape_string (email);
3983 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
3985 return LookupPlayerSearchCommand (result,limit);
3988 bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
3990 if(!result)
3992 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
3993 SetSentErrorMessage(true);
3994 return false;
3997 int i =0;
4000 Field* fields = result->Fetch();
4001 uint32 acc_id = fields[0].GetUInt32();
4002 std::string acc_name = fields[1].GetCppString();
4004 QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
4005 if(chars)
4007 PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4009 uint64 guid = 0;
4010 std::string name;
4014 Field* charfields = chars->Fetch();
4015 guid = charfields[0].GetUInt64();
4016 name = charfields[1].GetCppString();
4018 PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
4019 ++i;
4021 } while( chars->NextRow() && ( limit == -1 || i < limit ) );
4023 delete chars;
4025 } while(result->NextRow());
4027 delete result;
4029 return true;
4032 /// Triggering corpses expire check in world
4033 bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4035 CorpsesErase();
4036 return true;
4039 bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
4041 Player *target = getSelectedPlayer();
4043 if(!target)
4045 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4046 SetSentErrorMessage(true);
4047 return false;
4050 // check online security
4051 if (HasLowerSecurity(target, 0))
4052 return false;
4054 // Repair items
4055 target->DurabilityRepairAll(false, 0, false);
4057 PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName());
4058 if(needReportToTarget(target))
4059 ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName());
4060 return true;
4063 bool ChatHandler::HandleWaterwalkCommand(const char* args)
4065 if(!*args)
4066 return false;
4068 Player *player = getSelectedPlayer();
4070 if(!player)
4072 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4073 SetSentErrorMessage(true);
4074 return false;
4077 // check online security
4078 if (HasLowerSecurity(player, 0))
4079 return false;
4081 if (strncmp(args, "on", 3) == 0)
4082 player->SetMovement(MOVE_WATER_WALK); // ON
4083 else if (strncmp(args, "off", 4) == 0)
4084 player->SetMovement(MOVE_LAND_WALK); // OFF
4085 else
4087 SendSysMessage(LANG_USE_BOL);
4088 return false;
4091 PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
4092 if(needReportToTarget(player))
4093 ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
4094 return true;
4097 bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
4099 Player *player = m_session->GetPlayer();
4100 Creature *creature = getSelectedCreature();
4102 if(!creature)
4104 PSendSysMessage(LANG_SELECT_CREATURE);
4105 SetSentErrorMessage(true);
4106 return false;
4109 // Follow player - Using pet's default dist and angle
4110 creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
4112 PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
4113 return true;
4116 bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
4118 Player *player = m_session->GetPlayer();
4119 Creature *creature = getSelectedCreature();
4121 if(!creature)
4123 PSendSysMessage(LANG_SELECT_CREATURE);
4124 SetSentErrorMessage(true);
4125 return false;
4128 if (creature->GetMotionMaster()->empty() ||
4129 creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
4131 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4132 SetSentErrorMessage(true);
4133 return false;
4136 TargetedMovementGenerator<Creature> const* mgen
4137 = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
4139 if(mgen->GetTarget()!=player)
4141 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4142 SetSentErrorMessage(true);
4143 return false;
4146 // reset movement
4147 creature->GetMotionMaster()->MovementExpired(true);
4149 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
4150 return true;
4153 bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
4155 Creature *creatureTarget = getSelectedCreature ();
4156 if (!creatureTarget || creatureTarget->isPet ())
4158 PSendSysMessage (LANG_SELECT_CREATURE);
4159 SetSentErrorMessage (true);
4160 return false;
4163 Player *player = m_session->GetPlayer ();
4165 if(player->GetPetGUID ())
4167 SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
4168 SetSentErrorMessage (true);
4169 return false;
4172 CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
4174 if (!cInfo->isTameable ())
4176 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4177 SetSentErrorMessage (true);
4178 return false;
4181 // Everything looks OK, create new pet
4182 Pet* pet = player->CreateTamedPetFrom (creatureTarget);
4183 if (!pet)
4185 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4186 SetSentErrorMessage (true);
4187 return false;
4190 // place pet before player
4191 float x,y,z;
4192 player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
4193 pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
4195 // set pet to defensive mode by default (some classes can't control controlled pets in fact).
4196 pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4198 // calculate proper level
4199 uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
4201 // prepare visual effect for levelup
4202 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
4204 // add to world
4205 pet->GetMap()->Add((Creature*)pet);
4207 // visual effect for levelup
4208 pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
4210 // caster have pet now
4211 player->SetPet(pet);
4213 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4214 player->PetSpellInitialize();
4216 return true;