Merge commit 'mangos/master'
[auctionmangos.git] / src / game / Level2.cpp
blobf22458b26296745dcd5766b1bccace3b50bb175a
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Database/DatabaseEnv.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "World.h"
24 #include "ObjectMgr.h"
25 #include "Player.h"
26 #include "Item.h"
27 #include "GameObject.h"
28 #include "Opcodes.h"
29 #include "Chat.h"
30 #include "ObjectAccessor.h"
31 #include "MapManager.h"
32 #include "Language.h"
33 #include "World.h"
34 #include "GameEvent.h"
35 #include "SpellMgr.h"
36 #include "AccountMgr.h"
37 #include "GMTicketMgr.h"
38 #include "WaypointManager.h"
39 #include "Util.h"
40 #include <cctype>
41 #include <iostream>
42 #include <fstream>
43 #include <map>
44 #include "GlobalEvents.h"
46 #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
48 static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
50 LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL,
51 LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED
54 //mute player for some times
55 bool ChatHandler::HandleMuteCommand(const char* args)
57 if (!*args)
58 return false;
60 char *charname = strtok((char*)args, " ");
61 if (!charname)
62 return false;
64 std::string cname = charname;
66 char *timetonotspeak = strtok(NULL, " ");
67 if(!timetonotspeak)
68 return false;
70 uint32 notspeaktime = (uint32) atoi(timetonotspeak);
72 if(!normalizePlayerName(cname))
74 SendSysMessage(LANG_PLAYER_NOT_FOUND);
75 SetSentErrorMessage(true);
76 return false;
79 uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
80 if(!guid)
82 SendSysMessage(LANG_PLAYER_NOT_FOUND);
83 SetSentErrorMessage(true);
84 return false;
87 Player *chr = objmgr.GetPlayer(guid);
89 // check security
90 uint32 account_id = 0;
91 uint32 security = 0;
93 if (chr)
95 account_id = chr->GetSession()->GetAccountId();
96 security = chr->GetSession()->GetSecurity();
98 else
100 account_id = objmgr.GetPlayerAccountIdByGUID(guid);
101 security = accmgr.GetSecurity(account_id);
104 if(m_session && security >= m_session->GetSecurity())
106 SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
107 SetSentErrorMessage(true);
108 return false;
111 time_t mutetime = time(NULL) + notspeaktime*60;
113 if (chr)
114 chr->GetSession()->m_muteTime = mutetime;
116 loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
118 if(chr)
119 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
121 PSendSysMessage(LANG_YOU_DISABLE_CHAT, cname.c_str(), notspeaktime);
123 return true;
126 //unmute player
127 bool ChatHandler::HandleUnmuteCommand(const char* args)
129 if (!*args)
130 return false;
132 char *charname = strtok((char*)args, " ");
133 if (!charname)
134 return false;
136 std::string cname = charname;
138 if(!normalizePlayerName(cname))
140 SendSysMessage(LANG_PLAYER_NOT_FOUND);
141 SetSentErrorMessage(true);
142 return false;
145 uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
146 if(!guid)
148 SendSysMessage(LANG_PLAYER_NOT_FOUND);
149 SetSentErrorMessage(true);
150 return false;
153 Player *chr = objmgr.GetPlayer(guid);
155 // check security
156 uint32 account_id = 0;
157 uint32 security = 0;
159 if (chr)
161 account_id = chr->GetSession()->GetAccountId();
162 security = chr->GetSession()->GetSecurity();
164 else
166 account_id = objmgr.GetPlayerAccountIdByGUID(guid);
167 security = accmgr.GetSecurity(account_id);
170 if(m_session && security >= m_session->GetSecurity())
172 SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
173 SetSentErrorMessage(true);
174 return false;
177 if (chr)
179 if(chr->CanSpeak())
181 SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
182 SetSentErrorMessage(true);
183 return false;
186 chr->GetSession()->m_muteTime = 0;
189 loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
191 if(chr)
192 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
194 PSendSysMessage(LANG_YOU_ENABLE_CHAT, cname.c_str());
195 return true;
198 bool ChatHandler::HandleTargetObjectCommand(const char* args)
200 Player* pl = m_session->GetPlayer();
201 QueryResult *result;
202 GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
203 if(*args)
205 int32 id = atoi((char*)args);
206 if(id)
207 result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1",
208 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
209 else
211 std::string name = args;
212 WorldDatabase.escape_string(name);
213 result = WorldDatabase.PQuery(
214 "SELECT guid, id, position_x, position_y, position_z, orientation, map, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ "
215 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
216 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
219 else
221 std::ostringstream eventFilter;
222 eventFilter << " AND (event IS NULL ";
223 bool initString = true;
225 for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
227 if (initString)
229 eventFilter << "OR event IN (" <<*itr;
230 initString =false;
232 else
233 eventFilter << "," << *itr;
236 if (!initString)
237 eventFilter << "))";
238 else
239 eventFilter << ")";
241 result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
242 "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
243 "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 1",
244 m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
247 if (!result)
249 SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
250 return true;
253 Field *fields = result->Fetch();
254 uint32 lowguid = fields[0].GetUInt32();
255 uint32 id = fields[1].GetUInt32();
256 float x = fields[2].GetFloat();
257 float y = fields[3].GetFloat();
258 float z = fields[4].GetFloat();
259 float o = fields[5].GetFloat();
260 int mapid = fields[6].GetUInt16();
261 delete result;
263 GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id);
265 if (!goI)
267 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
268 return false;
271 GameObject* target = ObjectAccessor::GetGameObject(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
273 PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
275 if(target)
277 int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
278 if(curRespawnDelay < 0)
279 curRespawnDelay = 0;
281 std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
282 std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
284 PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
286 return true;
289 //teleport to gameobject
290 bool ChatHandler::HandleGoObjectCommand(const char* args)
292 if(!*args)
293 return false;
295 Player* _player = m_session->GetPlayer();
297 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
298 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
299 if(!cId)
300 return false;
302 int32 guid = atoi(cId);
303 if(!guid)
304 return false;
306 float x, y, z, ort;
307 int mapid;
309 // by DB guid
310 if (GameObjectData const* go_data = objmgr.GetGOData(guid))
312 x = go_data->posX;
313 y = go_data->posY;
314 z = go_data->posZ;
315 ort = go_data->orientation;
316 mapid = go_data->mapid;
318 else
320 SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
321 SetSentErrorMessage(true);
322 return false;
325 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
327 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
328 SetSentErrorMessage(true);
329 return false;
332 // stop flight if need
333 if(_player->isInFlight())
335 _player->GetMotionMaster()->MovementExpired();
336 _player->m_taxi.ClearTaxiDestinations();
338 // save only in non-flight case
339 else
340 _player->SaveRecallPosition();
342 _player->TeleportTo(mapid, x, y, z, ort);
343 return true;
346 bool ChatHandler::HandleGoTriggerCommand(const char* args)
348 Player* _player = m_session->GetPlayer();
350 if (!*args)
351 return false;
353 char *atId = strtok((char*)args, " ");
354 if (!atId)
355 return false;
357 int32 i_atId = atoi(atId);
359 if(!i_atId)
360 return false;
362 AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
363 if (!at)
365 PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
366 SetSentErrorMessage(true);
367 return false;
370 if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
372 PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
373 SetSentErrorMessage(true);
374 return false;
377 // stop flight if need
378 if(_player->isInFlight())
380 _player->GetMotionMaster()->MovementExpired();
381 _player->m_taxi.ClearTaxiDestinations();
383 // save only in non-flight case
384 else
385 _player->SaveRecallPosition();
387 _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
388 return true;
391 bool ChatHandler::HandleGoGraveyardCommand(const char* args)
393 Player* _player = m_session->GetPlayer();
395 if (!*args)
396 return false;
398 char *gyId = strtok((char*)args, " ");
399 if (!gyId)
400 return false;
402 int32 i_gyId = atoi(gyId);
404 if(!i_gyId)
405 return false;
407 WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
408 if (!gy)
410 PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
411 SetSentErrorMessage(true);
412 return false;
415 if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
417 PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
418 SetSentErrorMessage(true);
419 return false;
422 // stop flight if need
423 if(_player->isInFlight())
425 _player->GetMotionMaster()->MovementExpired();
426 _player->m_taxi.ClearTaxiDestinations();
428 // save only in non-flight case
429 else
430 _player->SaveRecallPosition();
432 _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
433 return true;
436 /** \brief Teleport the GM to the specified creature
438 * .gocreature <GUID> --> TP using creature.guid
439 * .gocreature azuregos --> TP player to the mob with this name
440 * Warning: If there is more than one mob with this name
441 * you will be teleported to the first one that is found.
442 * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry
443 * Warning: If there is more than one mob with this "id"
444 * you will be teleported to the first one that is found.
446 //teleport to creature
447 bool ChatHandler::HandleGoCreatureCommand(const char* args)
449 if(!*args)
450 return false;
451 Player* _player = m_session->GetPlayer();
453 // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
454 char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
455 if (!pParam1)
456 return false;
458 std::ostringstream whereClause;
460 // User wants to teleport to the NPC's template entry
461 if( strcmp(pParam1, "id") == 0 )
463 //sLog.outError("DEBUG: ID found");
465 // Get the "creature_template.entry"
466 // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
467 char* tail = strtok(NULL,"");
468 if(!tail)
469 return false;
470 char* cId = extractKeyFromLink(tail,"Hcreature_entry");
471 if(!cId)
472 return false;
474 int32 tEntry = atoi(cId);
475 //sLog.outError("DEBUG: ID value: %d", tEntry);
476 if(!tEntry)
477 return false;
479 whereClause << "WHERE id = '" << tEntry << "'";
481 else
483 //sLog.outError("DEBUG: ID *not found*");
485 int32 guid = atoi(pParam1);
487 // Number is invalid - maybe the user specified the mob's name
488 if(!guid)
490 std::string name = pParam1;
491 WorldDatabase.escape_string(name);
492 whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
494 else
496 whereClause << "WHERE guid = '" << guid << "'";
499 //sLog.outError("DEBUG: %s", whereClause.c_str());
501 QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
502 if (!result)
504 SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
505 SetSentErrorMessage(true);
506 return false;
508 if( result->GetRowCount() > 1 )
510 SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
513 Field *fields = result->Fetch();
514 float x = fields[0].GetFloat();
515 float y = fields[1].GetFloat();
516 float z = fields[2].GetFloat();
517 float ort = fields[3].GetFloat();
518 int mapid = fields[4].GetUInt16();
520 delete result;
522 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
524 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
525 SetSentErrorMessage(true);
526 return false;
529 // stop flight if need
530 if(_player->isInFlight())
532 _player->GetMotionMaster()->MovementExpired();
533 _player->m_taxi.ClearTaxiDestinations();
535 // save only in non-flight case
536 else
537 _player->SaveRecallPosition();
539 _player->TeleportTo(mapid, x, y, z, ort);
540 return true;
543 bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
545 uint64 guid = m_session->GetPlayer()->GetSelection();
547 if (guid == 0)
549 SendSysMessage(LANG_NO_SELECTION);
550 SetSentErrorMessage(true);
551 return false;
554 PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
555 return true;
558 bool ChatHandler::HandleLookupFactionCommand(const char* args)
560 if (!*args)
561 return false;
563 // Can be NULL at console call
564 Player *target = getSelectedPlayer ();
566 std::string namepart = args;
567 std::wstring wnamepart;
569 if (!Utf8toWStr (namepart,wnamepart))
570 return false;
572 // converting string that we try to find to lower case
573 wstrToLower (wnamepart);
575 uint32 counter = 0; // Counter for figure out that we found smth.
577 for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
579 FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
580 if (factionEntry)
582 FactionState const* repState = NULL;
583 if(target)
585 FactionStateList::const_iterator repItr = target->m_factions.find (factionEntry->reputationListID);
586 if(repItr != target->m_factions.end())
587 repState = &repItr->second;
591 int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale();
592 std::string name = factionEntry->name[loc];
593 if(name.empty())
594 continue;
596 if (!Utf8FitTo(name, wnamepart))
598 loc = 0;
599 for(; loc < MAX_LOCALE; ++loc)
601 if(m_session && loc==m_session->GetSessionDbcLocale())
602 continue;
604 name = factionEntry->name[loc];
605 if(name.empty())
606 continue;
608 if (Utf8FitTo(name, wnamepart))
609 break;
613 if(loc < MAX_LOCALE)
615 // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
616 // or "id - [faction] [no reputation]" format
617 std::ostringstream ss;
618 if (m_session)
619 ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
620 else
621 ss << id << " - " << name << " " << localeNames[loc];
623 if (repState) // and then target!=NULL also
625 ReputationRank rank = target->GetReputationRank(factionEntry);
626 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
628 ss << " " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
630 if(repState->Flags & FACTION_FLAG_VISIBLE)
631 ss << GetMangosString(LANG_FACTION_VISIBLE);
632 if(repState->Flags & FACTION_FLAG_AT_WAR)
633 ss << GetMangosString(LANG_FACTION_ATWAR);
634 if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
635 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
636 if(repState->Flags & FACTION_FLAG_HIDDEN)
637 ss << GetMangosString(LANG_FACTION_HIDDEN);
638 if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
639 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
640 if(repState->Flags & FACTION_FLAG_INACTIVE)
641 ss << GetMangosString(LANG_FACTION_INACTIVE);
643 else
644 ss << GetMangosString(LANG_FACTION_NOREPUTATION);
646 SendSysMessage(ss.str().c_str());
647 counter++;
652 if (counter == 0) // if counter == 0 then we found nth
653 SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
654 return true;
657 bool ChatHandler::HandleModifyRepCommand(const char * args)
659 if (!*args) return false;
661 Player* target = NULL;
662 target = getSelectedPlayer();
664 if(!target)
666 SendSysMessage(LANG_PLAYER_NOT_FOUND);
667 SetSentErrorMessage(true);
668 return false;
671 char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
672 if(!factionTxt)
673 return false;
675 uint32 factionId = atoi(factionTxt);
677 int32 amount = 0;
678 char *rankTxt = strtok(NULL, " ");
679 if (!factionTxt || !rankTxt)
680 return false;
682 amount = atoi(rankTxt);
683 if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
685 std::string rankStr = rankTxt;
686 std::wstring wrankStr;
687 if(!Utf8toWStr(rankStr,wrankStr))
688 return false;
689 wstrToLower( wrankStr );
691 int r = 0;
692 amount = -42000;
693 for (; r < MAX_REPUTATION_RANK; ++r)
695 std::string rank = GetMangosString(ReputationRankStrIndex[r]);
696 if(rank.empty())
697 continue;
699 std::wstring wrank;
700 if(!Utf8toWStr(rank,wrank))
701 continue;
703 wstrToLower(wrank);
705 if(wrank.substr(0,wrankStr.size())==wrankStr)
707 char *deltaTxt = strtok(NULL, " ");
708 if (deltaTxt)
710 int32 delta = atoi(deltaTxt);
711 if ((delta < 0) || (delta > Player::ReputationRank_Length[r] -1))
713 PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (Player::ReputationRank_Length[r]-1));
714 SetSentErrorMessage(true);
715 return false;
717 amount += delta;
719 break;
721 amount += Player::ReputationRank_Length[r];
723 if (r >= MAX_REPUTATION_RANK)
725 PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
726 SetSentErrorMessage(true);
727 return false;
731 FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
733 if (!factionEntry)
735 PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
736 SetSentErrorMessage(true);
737 return false;
740 if (factionEntry->reputationListID < 0)
742 PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[m_session->GetSessionDbcLocale()], factionId);
743 SetSentErrorMessage(true);
744 return false;
747 target->SetFactionReputation(factionEntry,amount);
748 PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, target->GetName(), target->GetReputation(factionId));
749 return true;
752 bool ChatHandler::HandleNameCommand(const char* /*args*/)
754 /* Temp. disabled
755 if(!*args)
756 return false;
758 if(strlen((char*)args)>75)
760 PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
761 return true;
764 for (uint8 i = 0; i < strlen(args); i++)
766 if(!isalpha(args[i]) && args[i]!=' ')
768 SendSysMessage(LANG_CHARS_ONLY);
769 return false;
773 uint64 guid;
774 guid = m_session->GetPlayer()->GetSelection();
775 if (guid == 0)
777 SendSysMessage(LANG_NO_SELECTION);
778 return true;
781 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
783 if(!pCreature)
785 SendSysMessage(LANG_SELECT_CREATURE);
786 return true;
789 pCreature->SetName(args);
790 uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName());
791 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
793 pCreature->SaveToDB();
796 return true;
799 bool ChatHandler::HandleSubNameCommand(const char* /*args*/)
801 /* Temp. disabled
803 if(!*args)
804 args = "";
806 if(strlen((char*)args)>75)
809 PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
810 return true;
813 for (uint8 i = 0; i < strlen(args); i++)
815 if(!isalpha(args[i]) && args[i]!=' ')
817 SendSysMessage(LANG_CHARS_ONLY);
818 return false;
821 uint64 guid;
822 guid = m_session->GetPlayer()->GetSelection();
823 if (guid == 0)
825 SendSysMessage(LANG_NO_SELECTION);
826 return true;
829 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
831 if(!pCreature)
833 SendSysMessage(LANG_SELECT_CREATURE);
834 return true;
837 uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
838 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
840 pCreature->SaveToDB();
842 return true;
845 //move item to other slot
846 bool ChatHandler::HandleItemMoveCommand(const char* args)
848 if(!*args)
849 return false;
850 uint8 srcslot, dstslot;
852 char* pParam1 = strtok((char*)args, " ");
853 if (!pParam1)
854 return false;
856 char* pParam2 = strtok(NULL, " ");
857 if (!pParam2)
858 return false;
860 srcslot = (uint8)atoi(pParam1);
861 dstslot = (uint8)atoi(pParam2);
863 if(srcslot==dstslot)
864 return true;
866 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot))
867 return false;
869 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot))
870 return false;
872 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
873 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
875 m_session->GetPlayer()->SwapItem( src, dst );
877 return true;
880 //add spawn of creature
881 bool ChatHandler::HandleNpcAddCommand(const char* args)
883 if(!*args)
884 return false;
885 char* charID = strtok((char*)args, " ");
886 if (!charID)
887 return false;
889 char* team = strtok(NULL, " ");
890 int32 teamval = 0;
891 if (team) { teamval = atoi(team); }
892 if (teamval < 0) { teamval = 0; }
894 uint32 id = atoi(charID);
896 Player *chr = m_session->GetPlayer();
897 float x = chr->GetPositionX();
898 float y = chr->GetPositionY();
899 float z = chr->GetPositionZ();
900 float o = chr->GetOrientation();
901 Map *map = chr->GetMap();
903 Creature* pCreature = new Creature;
904 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, (uint32)teamval))
906 delete pCreature;
907 return false;
910 pCreature->Relocate(x,y,z,o);
912 if(!pCreature->IsPositionValid())
914 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());
915 delete pCreature;
916 return false;
919 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
921 uint32 db_guid = pCreature->GetDBTableGUIDLow();
923 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
924 pCreature->LoadFromDB(db_guid, map);
926 map->Add(pCreature);
927 objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid));
928 return true;
931 bool ChatHandler::HandleNpcDeleteCommand(const char* args)
933 Creature* unit = NULL;
935 if(*args)
937 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
938 char* cId = extractKeyFromLink((char*)args,"Hcreature");
939 if(!cId)
940 return false;
942 uint32 lowguid = atoi(cId);
943 if(!lowguid)
944 return false;
946 if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid))
947 unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
949 else
950 unit = getSelectedCreature();
952 if(!unit || unit->isPet() || unit->isTotem())
954 SendSysMessage(LANG_SELECT_CREATURE);
955 SetSentErrorMessage(true);
956 return false;
959 // Delete the creature
960 unit->CombatStop();
961 unit->DeleteFromDB();
962 unit->CleanupsBeforeDelete();
963 unit->AddObjectToRemoveList();
965 SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
967 return true;
970 //delete object by selection or guid
971 bool ChatHandler::HandleDelObjectCommand(const char* args)
973 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
974 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
975 if(!cId)
976 return false;
978 uint32 lowguid = atoi(cId);
979 if(!lowguid)
980 return false;
982 GameObject* obj = NULL;
984 // by DB guid
985 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
986 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
988 if(!obj)
990 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
991 SetSentErrorMessage(true);
992 return false;
995 uint64 owner_guid = obj->GetOwnerGUID();
996 if(owner_guid)
998 Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
999 if(!owner && !IS_PLAYER_GUID(owner_guid))
1001 PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
1002 SetSentErrorMessage(true);
1003 return false;
1006 owner->RemoveGameObject(obj,false);
1009 obj->SetRespawnTime(0); // not save respawn time
1010 obj->Delete();
1011 obj->DeleteFromDB();
1013 PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
1015 return true;
1018 //turn selected object
1019 bool ChatHandler::HandleTurnObjectCommand(const char* args)
1021 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
1022 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1023 if(!cId)
1024 return false;
1026 uint32 lowguid = atoi(cId);
1027 if(!lowguid)
1028 return false;
1030 GameObject* obj = NULL;
1032 // by DB guid
1033 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1034 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1036 if(!obj)
1038 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1039 SetSentErrorMessage(true);
1040 return false;
1043 char* po = strtok(NULL, " ");
1044 float o;
1046 if (po)
1048 o = (float)atof(po);
1050 else
1052 Player *chr = m_session->GetPlayer();
1053 o = chr->GetOrientation();
1056 float rot2 = sin(o/2);
1057 float rot3 = cos(o/2);
1059 Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1060 map->Remove(obj,false);
1062 obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
1064 obj->SetFloatValue(GAMEOBJECT_FACING, o);
1065 obj->SetFloatValue(GAMEOBJECT_ROTATION+2, rot2);
1066 obj->SetFloatValue(GAMEOBJECT_ROTATION+3, rot3);
1068 map->Add(obj);
1070 obj->SaveToDB();
1071 obj->Refresh();
1073 PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o);
1075 return true;
1078 //move selected creature
1079 bool ChatHandler::HandleNpcMoveCommand(const char* args)
1081 uint32 lowguid = 0;
1083 Creature* pCreature = getSelectedCreature();
1085 if(!pCreature)
1087 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1088 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1089 if(!cId)
1090 return false;
1092 uint32 lowguid = atoi(cId);
1094 /* FIXME: impossibel without entry
1095 if(lowguid)
1096 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1099 // Attempting creature load from DB data
1100 if(!pCreature)
1102 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1103 if(!data)
1105 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1106 SetSentErrorMessage(true);
1107 return false;
1110 uint32 map_id = data->mapid;
1112 if(m_session->GetPlayer()->GetMapId()!=map_id)
1114 PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1115 SetSentErrorMessage(true);
1116 return false;
1119 else
1121 lowguid = pCreature->GetDBTableGUIDLow();
1124 else
1126 lowguid = pCreature->GetDBTableGUIDLow();
1129 float x = m_session->GetPlayer()->GetPositionX();
1130 float y = m_session->GetPlayer()->GetPositionY();
1131 float z = m_session->GetPlayer()->GetPositionZ();
1132 float o = m_session->GetPlayer()->GetOrientation();
1134 if (pCreature)
1136 if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1138 const_cast<CreatureData*>(data)->posX = x;
1139 const_cast<CreatureData*>(data)->posY = y;
1140 const_cast<CreatureData*>(data)->posZ = z;
1141 const_cast<CreatureData*>(data)->orientation = o;
1143 MapManager::Instance().GetMap(pCreature->GetMapId(),pCreature)->CreatureRelocation(pCreature,x, y, z,o);
1144 pCreature->GetMotionMaster()->Initialize();
1145 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1147 pCreature->setDeathState(JUST_DIED);
1148 pCreature->Respawn();
1152 WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1153 PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1154 return true;
1157 //move selected object
1158 bool ChatHandler::HandleMoveObjectCommand(const char* args)
1160 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
1161 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1162 if(!cId)
1163 return false;
1165 uint32 lowguid = atoi(cId);
1166 if(!lowguid)
1167 return false;
1169 GameObject* obj = NULL;
1171 // by DB guid
1172 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1173 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1175 if(!obj)
1177 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1178 SetSentErrorMessage(true);
1179 return false;
1182 char* px = strtok(NULL, " ");
1183 char* py = strtok(NULL, " ");
1184 char* pz = strtok(NULL, " ");
1186 if (!px)
1188 Player *chr = m_session->GetPlayer();
1190 Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1191 map->Remove(obj,false);
1193 obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
1194 obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX());
1195 obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY());
1196 obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ());
1198 map->Add(obj);
1200 else
1202 if(!py || !pz)
1203 return false;
1205 float x = (float)atof(px);
1206 float y = (float)atof(py);
1207 float z = (float)atof(pz);
1209 if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
1211 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
1212 SetSentErrorMessage(true);
1213 return false;
1216 Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1217 map->Remove(obj,false);
1219 obj->Relocate(x, y, z, obj->GetOrientation());
1220 obj->SetFloatValue(GAMEOBJECT_POS_X, x);
1221 obj->SetFloatValue(GAMEOBJECT_POS_Y, y);
1222 obj->SetFloatValue(GAMEOBJECT_POS_Z, z);
1224 map->Add(obj);
1227 obj->SaveToDB();
1228 obj->Refresh();
1230 PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow());
1232 return true;
1235 //demorph player or unit
1236 bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
1238 Unit *target = getSelectedUnit();
1239 if(!target)
1240 target = m_session->GetPlayer();
1242 target->DeMorph();
1244 return true;
1247 //add item in vendorlist
1248 bool ChatHandler::HandleAddVendorItemCommand(const char* args)
1250 if (!*args)
1251 return false;
1253 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1254 if (!pitem)
1256 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1257 SetSentErrorMessage(true);
1258 return false;
1261 uint32 itemId = atol(pitem);
1263 char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
1264 uint32 maxcount = 0;
1265 if (fmaxcount)
1266 maxcount = atol(fmaxcount);
1268 char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
1269 uint32 incrtime = 0;
1270 if (fincrtime)
1271 incrtime = atol(fincrtime);
1273 char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
1274 uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1276 Creature* vendor = getSelectedCreature();
1278 uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1280 if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1282 SetSentErrorMessage(true);
1283 return false;
1286 objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1288 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1290 PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1291 return true;
1294 //del item from vendor list
1295 bool ChatHandler::HandleDelVendorItemCommand(const char* args)
1297 if (!*args)
1298 return false;
1300 Creature* vendor = getSelectedCreature();
1301 if (!vendor || !vendor->isVendor())
1303 SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1304 SetSentErrorMessage(true);
1305 return false;
1308 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1309 if (!pitem)
1311 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1312 SetSentErrorMessage(true);
1313 return false;
1315 uint32 itemId = atol(pitem);
1317 if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1319 PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1320 SetSentErrorMessage(true);
1321 return false;
1324 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1326 PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1327 return true;
1330 //add move for creature
1331 bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
1333 if(!*args)
1334 return false;
1336 char* guid_str = strtok((char*)args, " ");
1337 char* wait_str = strtok((char*)NULL, " ");
1339 uint32 lowguid = atoi((char*)guid_str);
1341 Creature* pCreature = NULL;
1343 /* FIXME: impossible without entry
1344 if(lowguid)
1345 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1348 // attempt check creature existence by DB data
1349 if(!pCreature)
1351 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1352 if(!data)
1354 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1355 SetSentErrorMessage(true);
1356 return false;
1359 else
1361 // obtain real GUID for DB operations
1362 lowguid = pCreature->GetDBTableGUIDLow();
1365 int wait = wait_str ? atoi(wait_str) : 0;
1367 if(wait < 0)
1368 wait = 0;
1370 Player* player = m_session->GetPlayer();
1372 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1374 // update movement type
1375 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1376 if(pCreature)
1378 pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1379 pCreature->GetMotionMaster()->Initialize();
1380 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1382 pCreature->setDeathState(JUST_DIED);
1383 pCreature->Respawn();
1385 pCreature->SaveToDB();
1388 SendSysMessage(LANG_WAYPOINT_ADDED);
1390 return true;
1394 * Set the movement type for an NPC.<br/>
1395 * <br/>
1396 * Valid movement types are:
1397 * <ul>
1398 * <li> stay - NPC wont move </li>
1399 * <li> random - NPC will move randomly according to the spawndist </li>
1400 * <li> way - NPC will move with given waypoints set </li>
1401 * </ul>
1402 * additional parameter: NODEL - so no waypoints are deleted, if you
1403 * change the movement type
1405 bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
1407 if(!*args)
1408 return false;
1410 // 3 arguments:
1411 // GUID (optional - you can also select the creature)
1412 // stay|random|way (determines the kind of movement)
1413 // NODEL (optional - tells the system NOT to delete any waypoints)
1414 // this is very handy if you want to do waypoints, that are
1415 // later switched on/off according to special events (like escort
1416 // quests, etc)
1417 char* guid_str = strtok((char*)args, " ");
1418 char* type_str = strtok((char*)NULL, " ");
1419 char* dontdel_str = strtok((char*)NULL, " ");
1421 bool doNotDelete = false;
1423 if(!guid_str)
1424 return false;
1426 uint32 lowguid = 0;
1427 Creature* pCreature = NULL;
1429 if( dontdel_str )
1431 //sLog.outError("DEBUG: All 3 params are set");
1433 // All 3 params are set
1434 // GUID
1435 // type
1436 // doNotDEL
1437 if( stricmp( dontdel_str, "NODEL" ) == 0 )
1439 //sLog.outError("DEBUG: doNotDelete = true;");
1440 doNotDelete = true;
1443 else
1445 // Only 2 params - but maybe NODEL is set
1446 if( type_str )
1448 sLog.outError("DEBUG: Only 2 params ");
1449 if( stricmp( type_str, "NODEL" ) == 0 )
1451 //sLog.outError("DEBUG: type_str, NODEL ");
1452 doNotDelete = true;
1453 type_str = NULL;
1458 if(!type_str) // case .setmovetype $move_type (with selected creature)
1460 type_str = guid_str;
1461 pCreature = getSelectedCreature();
1462 if(!pCreature || pCreature->isPet())
1463 return false;
1464 lowguid = pCreature->GetDBTableGUIDLow();
1466 else // case .setmovetype #creature_guid $move_type (with selected creature)
1468 lowguid = atoi((char*)guid_str);
1470 /* impossible without entry
1471 if(lowguid)
1472 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1475 // attempt check creature existence by DB data
1476 if(!pCreature)
1478 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1479 if(!data)
1481 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1482 SetSentErrorMessage(true);
1483 return false;
1486 else
1488 lowguid = pCreature->GetDBTableGUIDLow();
1492 // now lowguid is low guid really existed creature
1493 // and pCreature point (maybe) to this creature or NULL
1495 MovementGeneratorType move_type;
1497 std::string type = type_str;
1499 if(type == "stay")
1500 move_type = IDLE_MOTION_TYPE;
1501 else if(type == "random")
1502 move_type = RANDOM_MOTION_TYPE;
1503 else if(type == "way")
1504 move_type = WAYPOINT_MOTION_TYPE;
1505 else
1506 return false;
1508 // update movement type
1509 if(doNotDelete == false)
1510 WaypointMgr.DeletePath(lowguid);
1512 if(pCreature)
1514 pCreature->SetDefaultMovementType(move_type);
1515 pCreature->GetMotionMaster()->Initialize();
1516 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1518 pCreature->setDeathState(JUST_DIED);
1519 pCreature->Respawn();
1521 pCreature->SaveToDB();
1523 if( doNotDelete == false )
1525 PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1527 else
1529 PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1532 return true;
1533 } // HandleNpcSetMoveTypeCommand
1535 //change level of creature or pet
1536 bool ChatHandler::HandleChangeLevelCommand(const char* args)
1538 if (!*args)
1539 return false;
1541 uint8 lvl = (uint8) atoi((char*)args);
1542 if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3)
1544 SendSysMessage(LANG_BAD_VALUE);
1545 SetSentErrorMessage(true);
1546 return false;
1549 Creature* pCreature = getSelectedCreature();
1550 if(!pCreature)
1552 SendSysMessage(LANG_SELECT_CREATURE);
1553 SetSentErrorMessage(true);
1554 return false;
1557 if(pCreature->isPet())
1559 ((Pet*)pCreature)->GivePetLevel(lvl);
1561 else
1563 pCreature->SetMaxHealth( 100 + 30*lvl);
1564 pCreature->SetHealth( 100 + 30*lvl);
1565 pCreature->SetLevel( lvl);
1566 pCreature->SaveToDB();
1569 return true;
1572 //set npcflag of creature
1573 bool ChatHandler::HandleNpcFlagCommand(const char* args)
1575 if (!*args)
1576 return false;
1578 uint32 npcFlags = (uint32) atoi((char*)args);
1580 Creature* pCreature = getSelectedCreature();
1582 if(!pCreature)
1584 SendSysMessage(LANG_SELECT_CREATURE);
1585 SetSentErrorMessage(true);
1586 return false;
1589 pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1591 WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1593 SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1595 return true;
1598 //set model of creature
1599 bool ChatHandler::HandleNpcSetModelCommand(const char* args)
1601 if (!*args)
1602 return false;
1604 uint32 displayId = (uint32) atoi((char*)args);
1606 Creature *pCreature = getSelectedCreature();
1608 if(!pCreature || pCreature->isPet())
1610 SendSysMessage(LANG_SELECT_CREATURE);
1611 SetSentErrorMessage(true);
1612 return false;
1615 pCreature->SetDisplayId(displayId);
1616 pCreature->SetNativeDisplayId(displayId);
1618 pCreature->SaveToDB();
1620 return true;
1623 //morph creature or player
1624 bool ChatHandler::HandleMorphCommand(const char* args)
1626 if (!*args)
1627 return false;
1629 uint16 display_id = (uint16)atoi((char*)args);
1631 Unit *target = getSelectedUnit();
1632 if(!target)
1633 target = m_session->GetPlayer();
1635 target->SetDisplayId(display_id);
1637 return true;
1640 //set faction of creature
1641 bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
1643 if (!*args)
1644 return false;
1646 uint32 factionId = (uint32) atoi((char*)args);
1648 if (!sFactionTemplateStore.LookupEntry(factionId))
1650 PSendSysMessage(LANG_WRONG_FACTION, factionId);
1651 SetSentErrorMessage(true);
1652 return false;
1655 Creature* pCreature = getSelectedCreature();
1657 if(!pCreature)
1659 SendSysMessage(LANG_SELECT_CREATURE);
1660 SetSentErrorMessage(true);
1661 return false;
1664 pCreature->setFaction(factionId);
1666 // faction is set in creature_template - not inside creature
1668 // update in memory
1669 if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1671 const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1672 const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1675 // and DB
1676 WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1678 return true;
1681 //kick player
1682 bool ChatHandler::HandleKickPlayerCommand(const char *args)
1684 char* kickName = strtok((char*)args, " ");
1685 if (!kickName)
1687 Player* player = getSelectedPlayer();
1689 if(!player)
1691 SendSysMessage(LANG_NO_CHAR_SELECTED);
1692 SetSentErrorMessage(true);
1693 return false;
1696 if(player==m_session->GetPlayer())
1698 SendSysMessage(LANG_COMMAND_KICKSELF);
1699 SetSentErrorMessage(true);
1700 return false;
1703 player->GetSession()->KickPlayer();
1705 else
1707 std::string name = kickName;
1708 if(!normalizePlayerName(name))
1710 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1711 SetSentErrorMessage(true);
1712 return false;
1715 if(m_session && name==m_session->GetPlayer()->GetName())
1717 SendSysMessage(LANG_COMMAND_KICKSELF);
1718 SetSentErrorMessage(true);
1719 return false;
1722 if(sWorld.KickPlayer(name))
1724 PSendSysMessage(LANG_COMMAND_KICKMESSAGE,name.c_str());
1726 else
1727 PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,name.c_str());
1730 return true;
1733 //show info of player
1734 bool ChatHandler::HandlePInfoCommand(const char* args)
1736 Player* target = NULL;
1737 uint64 targetGUID = 0;
1739 char* px = strtok((char*)args, " ");
1740 char* py = NULL;
1742 std::string name;
1744 if (px)
1746 name = px;
1748 if(name.empty())
1749 return false;
1751 if(!normalizePlayerName(name))
1753 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1754 SetSentErrorMessage(true);
1755 return false;
1758 target = objmgr.GetPlayer(name.c_str());
1759 if (target)
1760 py = strtok(NULL, " ");
1761 else
1763 targetGUID = objmgr.GetPlayerGUIDByName(name);
1764 if(targetGUID)
1765 py = strtok(NULL, " ");
1766 else
1767 py = px;
1771 if(!target && !targetGUID)
1773 target = getSelectedPlayer();
1776 if(!target && !targetGUID)
1778 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1779 SetSentErrorMessage(true);
1780 return false;
1783 uint32 accId = 0;
1784 uint32 money = 0;
1785 uint32 total_player_time = 0;
1786 uint32 level = 0;
1787 uint32 latency = 0;
1789 // get additional information from Player object
1790 if(target)
1792 targetGUID = target->GetGUID();
1793 name = target->GetName(); // re-read for case getSelectedPlayer() target
1794 accId = target->GetSession()->GetAccountId();
1795 money = target->GetMoney();
1796 total_player_time = target->GetTotalPlayedTime();
1797 level = target->getLevel();
1798 latency = target->GetSession()->GetLatency();
1800 // get additional information from DB
1801 else
1803 // 0
1804 QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID));
1805 if (!result)
1807 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1808 SetSentErrorMessage(true);
1809 return false;
1811 Field *fields = result->Fetch();
1812 total_player_time = fields[0].GetUInt32();
1813 delete result;
1815 Tokens data;
1816 if (!Player::LoadValuesArrayFromDB(data,targetGUID))
1818 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1819 SetSentErrorMessage(true);
1820 return false;
1823 money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE);
1824 level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL);
1826 accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
1829 std::string username = GetMangosString(LANG_ERROR);
1830 std::string last_ip = GetMangosString(LANG_ERROR);
1831 uint32 security = 0;
1832 std::string last_login = GetMangosString(LANG_ERROR);
1834 QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
1835 if(result)
1837 Field* fields = result->Fetch();
1838 username = fields[0].GetCppString();
1839 security = fields[1].GetUInt32();
1841 if(!m_session || m_session->GetSecurity() >= security)
1843 last_ip = fields[2].GetCppString();
1844 last_login = fields[3].GetCppString();
1846 else
1848 last_ip = "-";
1849 last_login = "-";
1852 delete result;
1855 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);
1857 std::string timeStr = secsToTimeString(total_player_time,true,true);
1858 uint32 gold = money /GOLD;
1859 uint32 silv = (money % GOLD) / SILVER;
1860 uint32 copp = (money % GOLD) % SILVER;
1861 PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp );
1863 if ( py && strncmp(py, "rep", 3) == 0 )
1865 if(!target)
1867 // rep option not implemented for offline case
1868 SendSysMessage(LANG_PINFO_NO_REP);
1869 SetSentErrorMessage(true);
1870 return false;
1873 char* FactionName;
1874 for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr)
1876 FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
1877 if (factionEntry)
1878 FactionName = factionEntry->name[m_session->GetSessionDbcLocale()];
1879 else
1880 FactionName = "#Not found#";
1881 ReputationRank rank = target->GetReputationRank(factionEntry);
1882 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
1883 std::ostringstream ss;
1884 ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << FactionName << "]|h|r " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
1886 if(itr->second.Flags & FACTION_FLAG_VISIBLE)
1887 ss << GetMangosString(LANG_FACTION_VISIBLE);
1888 if(itr->second.Flags & FACTION_FLAG_AT_WAR)
1889 ss << GetMangosString(LANG_FACTION_ATWAR);
1890 if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
1891 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
1892 if(itr->second.Flags & FACTION_FLAG_HIDDEN)
1893 ss << GetMangosString(LANG_FACTION_HIDDEN);
1894 if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
1895 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
1896 if(itr->second.Flags & FACTION_FLAG_INACTIVE)
1897 ss << GetMangosString(LANG_FACTION_INACTIVE);
1899 SendSysMessage(ss.str().c_str());
1902 return true;
1905 //show tickets
1906 void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
1908 std::string name;
1909 if(!objmgr.GetPlayerNameByGUID(guid,name))
1910 name = GetMangosString(LANG_UNKNOWN);
1912 PSendSysMessage(LANG_COMMAND_TICKETVIEW, name.c_str(),time,text);
1915 //ticket commands
1916 bool ChatHandler::HandleTicketCommand(const char* args)
1918 char* px = strtok((char*)args, " ");
1920 // ticket<end>
1921 if (!px)
1923 if(!m_session)
1925 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1926 SetSentErrorMessage(true);
1927 return false;
1930 size_t count = ticketmgr.GetTicketCount();
1932 bool accept = m_session->GetPlayer()->isAcceptTickets();
1934 PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
1935 return true;
1938 // ticket on
1939 if(strncmp(px,"on",3) == 0)
1941 if(!m_session)
1943 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1944 SetSentErrorMessage(true);
1945 return false;
1948 m_session->GetPlayer()->SetAcceptTicket(true);
1949 SendSysMessage(LANG_COMMAND_TICKETON);
1950 return true;
1953 // ticket off
1954 if(strncmp(px,"off",4) == 0)
1956 if(!m_session)
1958 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1959 SetSentErrorMessage(true);
1960 return false;
1963 m_session->GetPlayer()->SetAcceptTicket(false);
1964 SendSysMessage(LANG_COMMAND_TICKETOFF);
1965 return true;
1968 // ticket #num
1969 int num = atoi(px);
1970 if(num > 0)
1972 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
1974 if(!result)
1976 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
1977 SetSentErrorMessage(true);
1978 return false;
1981 Field* fields = result->Fetch();
1983 uint32 guid = fields[0].GetUInt32();
1984 char const* text = fields[1].GetString();
1985 char const* time = fields[2].GetString();
1987 ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time);
1988 delete result;
1989 return true;
1992 std::string name = px;
1994 if(!normalizePlayerName(name))
1996 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1997 SetSentErrorMessage(true);
1998 return false;
2001 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2003 if(!guid)
2004 return false;
2006 // ticket $char_name
2007 GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(guid));
2008 if(!ticket)
2009 return false;
2011 std::string time = TimeToTimestampStr(ticket->GetLastUpdate());
2013 ShowTicket(guid, ticket->GetText(), time.c_str());
2015 return true;
2018 //dell all tickets
2019 bool ChatHandler::HandleDelTicketCommand(const char *args)
2021 char* px = strtok((char*)args, " ");
2022 if (!px)
2023 return false;
2025 // delticket all
2026 if(strncmp(px,"all",4) == 0)
2028 ticketmgr.DeleteAll();
2029 SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2030 return true;
2033 int num = (uint32)atoi(px);
2035 // delticket #num
2036 if(num > 0)
2038 QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2039 if(!result)
2041 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2042 SetSentErrorMessage(true);
2043 return false;
2045 Field* fields = result->Fetch();
2046 uint32 guid = fields[0].GetUInt32();
2047 delete result;
2049 ticketmgr.Delete(guid);
2051 //notify player
2052 if(Player* pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)))
2054 pl->GetSession()->SendGMTicketGetTicket(0x0A, 0);
2055 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, pl->GetName());
2057 else
2058 PSendSysMessage(LANG_COMMAND_TICKETDEL);
2060 return true;
2063 std::string name = px;
2065 if(!normalizePlayerName(name))
2067 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2068 SetSentErrorMessage(true);
2069 return false;
2072 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2074 if(!guid)
2075 return false;
2077 // delticket $char_name
2078 ticketmgr.Delete(GUID_LOPART(guid));
2080 // notify players about ticket deleting
2081 if(Player* sender = objmgr.GetPlayer(guid))
2082 sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2084 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,px);
2085 return true;
2088 //set spawn dist of creature
2089 bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
2091 if(!*args)
2092 return false;
2094 float option = atof((char*)args);
2095 if (option < 0.0f)
2097 SendSysMessage(LANG_BAD_VALUE);
2098 return false;
2101 MovementGeneratorType mtype = IDLE_MOTION_TYPE;
2102 if (option >0.0f)
2103 mtype = RANDOM_MOTION_TYPE;
2105 Creature *pCreature = getSelectedCreature();
2106 uint32 u_guidlow = 0;
2108 if (pCreature)
2109 u_guidlow = pCreature->GetDBTableGUIDLow();
2110 else
2111 return false;
2113 pCreature->SetRespawnRadius((float)option);
2114 pCreature->SetDefaultMovementType(mtype);
2115 pCreature->GetMotionMaster()->Initialize();
2116 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
2118 pCreature->setDeathState(JUST_DIED);
2119 pCreature->Respawn();
2122 WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
2123 PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
2124 return true;
2127 bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
2129 if(!*args)
2130 return false;
2132 char* stime = strtok((char*)args, " ");
2134 if (!stime)
2135 return false;
2137 int i_stime = atoi((char*)stime);
2139 if (i_stime < 0)
2141 SendSysMessage(LANG_BAD_VALUE);
2142 SetSentErrorMessage(true);
2143 return false;
2146 Creature *pCreature = getSelectedCreature();
2147 uint32 u_guidlow = 0;
2149 if (pCreature)
2150 u_guidlow = pCreature->GetDBTableGUIDLow();
2151 else
2152 return false;
2154 WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
2155 pCreature->SetRespawnDelay((uint32)i_stime);
2156 PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
2158 return true;
2162 * Add a waypoint to a creature.
2164 * The user can either select an npc or provide its GUID.
2166 * The user can even select a visual waypoint - then the new waypoint
2167 * is placed *after* the selected one - this makes insertion of new
2168 * waypoints possible.
2170 * eg:
2171 * .wp add 12345
2172 * -> adds a waypoint to the npc with the GUID 12345
2174 * .wp add
2175 * -> adds a waypoint to the currently selected creature
2178 * @param args if the user did not provide a GUID, it is NULL
2180 * @return true - command did succeed, false - something went wrong
2182 bool ChatHandler::HandleWpAddCommand(const char* args)
2184 sLog.outDebug("DEBUG: HandleWpAddCommand");
2186 // optional
2187 char* guid_str = NULL;
2189 if(*args)
2191 guid_str = strtok((char*)args, " ");
2194 uint32 lowguid = 0;
2195 uint32 point = 0;
2196 Creature* target = getSelectedCreature();
2197 // Did player provide a GUID?
2198 if (!guid_str)
2200 sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2202 // No GUID provided
2203 // -> Player must have selected a creature
2205 if(!target || target->isPet())
2207 SendSysMessage(LANG_SELECT_CREATURE);
2208 SetSentErrorMessage(true);
2209 return false;
2211 if (target->GetEntry() == VISUAL_WAYPOINT )
2213 sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2215 QueryResult *result =
2216 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2217 target->GetGUIDLow() );
2218 if(!result)
2220 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2221 // User selected a visual spawnpoint -> get the NPC
2222 // Select NPC GUID
2223 // Since we compare float values, we have to deal with
2224 // some difficulties.
2225 // Here we search for all waypoints that only differ in one from 1 thousand
2226 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2227 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2228 const char* maxDIFF = "0.01";
2229 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 )",
2230 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2231 if(!result)
2233 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2234 SetSentErrorMessage(true);
2235 return false;
2240 Field *fields = result->Fetch();
2241 lowguid = fields[0].GetUInt32();
2242 point = fields[1].GetUInt32();
2243 }while( result->NextRow() );
2244 delete result;
2246 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2247 if(!data)
2249 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2250 SetSentErrorMessage(true);
2251 return false;
2254 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2255 if(!target)
2257 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2258 SetSentErrorMessage(true);
2259 return false;
2262 else
2264 lowguid = target->GetDBTableGUIDLow();
2267 else
2269 sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2271 // GUID provided
2272 // Warn if player also selected a creature
2273 // -> Creature selection is ignored <-
2274 if(target)
2276 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2278 lowguid = atoi((char*)guid_str);
2280 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2281 if(!data)
2283 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2284 SetSentErrorMessage(true);
2285 return false;
2288 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2289 if(!target || target->isPet())
2291 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2292 SetSentErrorMessage(true);
2293 return false;
2296 // lowguid -> GUID of the NPC
2297 // point -> number of the waypoint (if not 0)
2298 sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2300 sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2302 Player* player = m_session->GetPlayer();
2303 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2305 // update movement type
2306 if(target)
2308 target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2309 target->GetMotionMaster()->Initialize();
2310 if(target->isAlive()) // dead creature will reset movement generator at respawn
2312 target->setDeathState(JUST_DIED);
2313 target->Respawn();
2315 target->SaveToDB();
2317 else
2318 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2320 PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2322 return true;
2323 } // HandleWpAddCommand
2326 * .wp modify emote | spell | text | del | move | add
2328 * add -> add a WP after the selected visual waypoint
2329 * User must select a visual waypoint and then issue ".wp modify add"
2331 * emote <emoteID>
2332 * User has selected a visual waypoint before.
2333 * <emoteID> is added to this waypoint. Everytime the
2334 * NPC comes to this waypoint, the emote is called.
2336 * emote <GUID> <WPNUM> <emoteID>
2337 * User has not selected visual waypoint before.
2338 * For the waypoint <WPNUM> for the NPC with <GUID>
2339 * an emote <emoteID> is added.
2340 * Everytime the NPC comes to this waypoint, the emote is called.
2343 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2345 bool ChatHandler::HandleWpModifyCommand(const char* args)
2347 sLog.outDebug("DEBUG: HandleWpModifyCommand");
2349 if(!*args)
2350 return false;
2352 // first arg: add del text emote spell waittime move
2353 char* show_str = strtok((char*)args, " ");
2354 if (!show_str)
2356 return false;
2359 std::string show = show_str;
2360 // Check
2361 // Remember: "show" must also be the name of a column!
2362 if( (show != "emote") && (show != "spell") && (show != "text1") && (show != "text2")
2363 && (show != "text3") && (show != "text4") && (show != "text5")
2364 && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2365 && (show != "model1") && (show != "model2") && (show != "orientation"))
2367 return false;
2370 // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2372 // Did user provide a GUID
2373 // or did the user select a creature?
2374 // -> variable lowguid is filled with the GUID of the NPC
2375 uint32 lowguid = 0;
2376 uint32 point = 0;
2377 uint32 wpGuid = 0;
2378 Creature* target = getSelectedCreature();
2380 if(target)
2382 sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2384 // Did the user select a visual spawnpoint?
2385 if (target->GetEntry() != VISUAL_WAYPOINT )
2387 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2388 SetSentErrorMessage(true);
2389 return false;
2392 wpGuid = target->GetGUIDLow();
2394 // The visual waypoint
2395 QueryResult *result =
2396 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2397 target->GetGUIDLow() );
2398 if(!result)
2400 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2401 SetSentErrorMessage(true);
2402 return false;
2404 sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2406 Field *fields = result->Fetch();
2407 lowguid = fields[0].GetUInt32();
2408 point = fields[1].GetUInt32();
2410 // Cleanup memory
2411 sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2412 delete result;
2414 else
2416 // User did provide <GUID> <WPNUM>
2418 char* guid_str = strtok((char*)NULL, " ");
2419 if( !guid_str )
2421 SendSysMessage(LANG_WAYPOINT_NOGUID);
2422 return false;
2424 lowguid = atoi((char*)guid_str);
2426 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2427 if(!data)
2429 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2430 SetSentErrorMessage(true);
2431 return false;
2434 PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2436 char* point_str = strtok((char*)NULL, " ");
2437 if( !point_str )
2439 SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2440 return false;
2442 point = atoi((char*)point_str);
2444 PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2446 // Now we need the GUID of the visual waypoint
2447 // -> "del", "move", "add" command
2449 QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2450 if (!result)
2452 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2453 SetSentErrorMessage(true);
2454 return false;
2457 Field *fields = result->Fetch();
2458 wpGuid = fields[0].GetUInt32();
2460 // Free memory
2461 delete result;
2464 char* arg_str = NULL;
2465 // Check for argument
2466 if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2468 // Text is enclosed in "<>", all other arguments not
2469 if( show.find("text") != std::string::npos )
2470 arg_str = strtok((char*)NULL, "<>");
2471 else
2472 arg_str = strtok((char*)NULL, " ");
2474 if( !arg_str)
2476 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2477 return false;
2481 sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2483 // wpGuid -> GUID of the waypoint creature
2484 // lowguid -> GUID of the NPC
2485 // point -> waypoint number
2487 // Special functions:
2488 // add - move - del -> no args commands
2489 // Add a waypoint after the selected visual
2490 if(show == "add" && target)
2492 PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2494 // Get the creature for which we read the waypoint
2495 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2496 if(!data)
2498 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2499 SetSentErrorMessage(true);
2500 return false;
2503 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2505 if( !npcCreature )
2507 PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2508 SetSentErrorMessage(true);
2509 return false;
2512 sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2514 // What to do:
2515 // Add the visual spawnpoint (DB only)
2516 // Adjust the waypoints
2517 // Respawn the owner of the waypoints
2518 sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2520 Player* chr = m_session->GetPlayer();
2521 Map *map = chr->GetMap();
2523 if(npcCreature)
2525 npcCreature->GetMotionMaster()->Initialize();
2526 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2528 npcCreature->setDeathState(JUST_DIED);
2529 npcCreature->Respawn();
2533 // create the waypoint creature
2534 wpGuid = 0;
2535 Creature* wpCreature = new Creature;
2536 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map,VISUAL_WAYPOINT,0))
2538 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2539 delete wpCreature;
2541 else
2543 wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2545 if(!wpCreature->IsPositionValid())
2547 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());
2548 delete wpCreature;
2550 else
2552 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2553 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2554 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2555 map->Add(wpCreature);
2556 wpGuid = wpCreature->GetGUIDLow();
2560 WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2562 if(!wpGuid)
2563 return false;
2565 PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2566 return true;
2567 } // add
2569 if(show == "del" && target)
2571 PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2573 // Get the creature for which we read the waypoint
2574 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2575 if(!data)
2577 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2578 SetSentErrorMessage(true);
2579 return false;
2582 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2584 // wpCreature
2585 Creature* wpCreature = NULL;
2586 if( wpGuid != 0 )
2588 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2589 wpCreature->DeleteFromDB();
2590 wpCreature->CleanupsBeforeDelete();
2591 wpCreature->AddObjectToRemoveList();
2594 // What to do:
2595 // Remove the visual spawnpoint
2596 // Adjust the waypoints
2597 // Respawn the owner of the waypoints
2599 WaypointMgr.DeleteNode(lowguid, point);
2601 if(npcCreature)
2603 // Any waypoints left?
2604 QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2605 if(!result2)
2607 npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2609 else
2611 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2612 delete result2;
2614 npcCreature->GetMotionMaster()->Initialize();
2615 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2617 npcCreature->setDeathState(JUST_DIED);
2618 npcCreature->Respawn();
2620 npcCreature->SaveToDB();
2623 PSendSysMessage(LANG_WAYPOINT_REMOVED);
2624 return true;
2625 } // del
2627 if(show == "move" && target)
2629 PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2631 Player *chr = m_session->GetPlayer();
2632 Map *map = chr->GetMap();
2634 // Get the creature for which we read the waypoint
2635 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2636 if(!data)
2638 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2639 SetSentErrorMessage(true);
2640 return false;
2643 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2645 // wpCreature
2646 Creature* wpCreature = NULL;
2647 // What to do:
2648 // Move the visual spawnpoint
2649 // Respawn the owner of the waypoints
2650 if( wpGuid != 0 )
2652 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2653 wpCreature->DeleteFromDB();
2654 wpCreature->CleanupsBeforeDelete();
2655 wpCreature->AddObjectToRemoveList();
2656 // re-create
2657 Creature* wpCreature2 = new Creature;
2658 if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0))
2660 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2661 delete wpCreature2;
2662 return false;
2665 wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2667 if(!wpCreature2->IsPositionValid())
2669 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());
2670 delete wpCreature2;
2671 return false;
2674 wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2675 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2676 wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2677 map->Add(wpCreature2);
2678 //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2);
2681 WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2683 if(npcCreature)
2685 npcCreature->GetMotionMaster()->Initialize();
2686 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2688 npcCreature->setDeathState(JUST_DIED);
2689 npcCreature->Respawn();
2692 PSendSysMessage(LANG_WAYPOINT_CHANGED);
2694 return true;
2695 } // move
2697 // Create creature - npc that has the waypoint
2698 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2699 if(!data)
2701 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2702 SetSentErrorMessage(true);
2703 return false;
2706 WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2708 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2709 if(npcCreature)
2711 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2712 npcCreature->GetMotionMaster()->Initialize();
2713 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2715 npcCreature->setDeathState(JUST_DIED);
2716 npcCreature->Respawn();
2719 PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2721 return true;
2725 * .wp show info | on | off
2727 * info -> User has selected a visual waypoint before
2729 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2730 * provided the GUID of the NPC and the number of
2731 * the waypoint.
2733 * on -> User has selected an NPC; all visual waypoints for this
2734 * NPC are added to the world
2736 * on <GUID> -> User did not select an NPC - instead the GUID of the
2737 * NPC is provided. All visual waypoints for this NPC
2738 * are added from the world.
2740 * off -> User has selected an NPC; all visual waypoints for this
2741 * NPC are removed from the world.
2743 * on <GUID> -> User did not select an NPC - instead the GUID of the
2744 * NPC is provided. All visual waypoints for this NPC
2745 * are removed from the world.
2749 bool ChatHandler::HandleWpShowCommand(const char* args)
2751 sLog.outDebug("DEBUG: HandleWpShowCommand");
2753 if(!*args)
2754 return false;
2756 // first arg: on, off, first, last
2757 char* show_str = strtok((char*)args, " ");
2758 if (!show_str)
2760 return false;
2762 // second arg: GUID (optional, if a creature is selected)
2763 char* guid_str = strtok((char*)NULL, " ");
2764 sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
2765 //if (!guid_str) {
2766 // return false;
2769 // Did user provide a GUID
2770 // or did the user select a creature?
2771 // -> variable lowguid is filled with the GUID
2772 Creature* target = getSelectedCreature();
2773 // Did player provide a GUID?
2774 if (!guid_str)
2776 sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
2777 // No GUID provided
2778 // -> Player must have selected a creature
2780 if(!target)
2782 SendSysMessage(LANG_SELECT_CREATURE);
2783 SetSentErrorMessage(true);
2784 return false;
2787 else
2789 sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
2790 // GUID provided
2791 // Warn if player also selected a creature
2792 // -> Creature selection is ignored <-
2793 if(target)
2795 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2798 uint32 lowguid = atoi((char*)guid_str);
2800 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2801 if(!data)
2803 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2804 SetSentErrorMessage(true);
2805 return false;
2808 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2810 if(!target)
2812 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2813 SetSentErrorMessage(true);
2814 return false;
2818 uint32 lowguid = target->GetDBTableGUIDLow();
2820 std::string show = show_str;
2821 uint32 Maxpoint;
2823 sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
2825 // Show info for the selected waypoint
2826 if(show == "info")
2828 PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
2830 // Check if the user did specify a visual waypoint
2831 if( target->GetEntry() != VISUAL_WAYPOINT )
2833 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2834 SetSentErrorMessage(true);
2835 return false;
2838 //PSendSysMessage("wp on, GUID: %u", lowguid);
2840 //pCreature->GetPositionX();
2842 QueryResult *result =
2843 WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u",
2844 target->GetGUIDLow() );
2845 if(!result)
2847 // Since we compare float values, we have to deal with
2848 // some difficulties.
2849 // Here we search for all waypoints that only differ in one from 1 thousand
2850 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2851 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2852 const char* maxDIFF = "0.01";
2853 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
2855 result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
2856 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2857 if(!result)
2859 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2860 SetSentErrorMessage(true);
2861 return false;
2866 Field *fields = result->Fetch();
2867 uint32 creGUID = fields[0].GetUInt32();
2868 uint32 point = fields[1].GetUInt32();
2869 int waittime = fields[2].GetUInt32();
2870 uint32 emote = fields[3].GetUInt32();
2871 uint32 spell = fields[4].GetUInt32();
2872 const char * text1 = fields[5].GetString();
2873 const char * text2 = fields[6].GetString();
2874 const char * text3 = fields[7].GetString();
2875 const char * text4 = fields[8].GetString();
2876 const char * text5 = fields[9].GetString();
2877 uint32 model1 = fields[10].GetUInt32();
2878 uint32 model2 = fields[11].GetUInt32();
2880 // Get the creature for which we read the waypoint
2881 Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2883 PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
2884 PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
2885 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
2886 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
2887 PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
2888 PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
2889 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 1, text1);
2890 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 2, text2);
2891 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 3, text3);
2892 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 4, text4);
2893 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 5, text5);
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 //MapManager::Instance().GetMap(wpCreature->GetMapId())->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'");
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, text1, text2, text3, text4, text5, 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, text1, text2, text3, text4, text5 ) 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 const char *tmpChar = fields[10].GetString();
3258 if( !tmpChar )
3260 outfile << "NULL"; // text1
3262 else
3264 outfile << "'";
3265 outfile << tmpChar; // text1
3266 outfile << "'";
3268 outfile << ", ";
3269 tmpChar = fields[11].GetString();
3270 if( !tmpChar )
3272 outfile << "NULL"; // text2
3274 else
3276 outfile << "'";
3277 outfile << tmpChar; // text2
3278 outfile << "'";
3280 outfile << ", ";
3281 tmpChar = fields[12].GetString();
3282 if( !tmpChar )
3284 outfile << "NULL"; // text3
3286 else
3288 outfile << "'";
3289 outfile << tmpChar; // text3
3290 outfile << "'";
3292 outfile << ", ";
3293 tmpChar = fields[13].GetString();
3294 if( !tmpChar )
3296 outfile << "NULL"; // text4
3298 else
3300 outfile << "'";
3301 outfile << tmpChar; // text4
3302 outfile << "'";
3304 outfile << ", ";
3305 tmpChar = fields[14].GetString();
3306 if( !tmpChar )
3308 outfile << "NULL"; // text5
3310 else
3312 outfile << "'";
3313 outfile << tmpChar; // text5
3314 outfile << "'";
3316 outfile << ");\n ";
3318 } while( result->NextRow() );
3319 delete result;
3321 PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3322 outfile.close();
3324 return true;
3327 bool ChatHandler::HandleWpImportCommand(const char *args)
3329 if(!*args)
3330 return false;
3332 char* arg_str = strtok((char*)args, " ");
3333 if (!arg_str)
3334 return false;
3336 std::string line;
3337 std::ifstream infile (arg_str);
3338 if (infile.is_open())
3340 while (! infile.eof() )
3342 getline (infile,line);
3343 //cout << line << endl;
3344 QueryResult *result = WorldDatabase.Query(line.c_str());
3345 delete result;
3347 infile.close();
3349 PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3351 return true;
3354 //rename characters
3355 bool ChatHandler::HandleRenameCommand(const char* args)
3357 Player* target = NULL;
3358 uint64 targetGUID = 0;
3359 std::string oldname;
3361 char* px = strtok((char*)args, " ");
3363 if(px)
3365 oldname = px;
3367 if(!normalizePlayerName(oldname))
3369 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3370 SetSentErrorMessage(true);
3371 return false;
3374 target = objmgr.GetPlayer(oldname.c_str());
3376 if (!target)
3377 targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3380 if(!target && !targetGUID)
3382 target = getSelectedPlayer();
3385 if(!target && !targetGUID)
3387 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3388 SetSentErrorMessage(true);
3389 return false;
3392 if(target)
3394 PSendSysMessage(LANG_RENAME_PLAYER, target->GetName());
3395 target->SetAtLoginFlag(AT_LOGIN_RENAME);
3396 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3398 else
3400 PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
3401 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3404 return true;
3407 //spawn go
3408 bool ChatHandler::HandleGameObjectCommand(const char* args)
3410 if (!*args)
3411 return false;
3413 char* pParam1 = strtok((char*)args, " ");
3414 if (!pParam1)
3415 return false;
3417 uint32 id = atoi((char*)pParam1);
3418 if(!id)
3419 return false;
3421 char* spawntimeSecs = strtok(NULL, " ");
3423 const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id);
3425 if (!goI)
3427 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
3428 SetSentErrorMessage(true);
3429 return false;
3432 Player *chr = m_session->GetPlayer();
3433 float x = float(chr->GetPositionX());
3434 float y = float(chr->GetPositionY());
3435 float z = float(chr->GetPositionZ());
3436 float o = float(chr->GetOrientation());
3437 Map *map = chr->GetMap();
3439 float rot2 = sin(o/2);
3440 float rot3 = cos(o/2);
3442 GameObject* pGameObj = new GameObject;
3443 uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
3445 if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1))
3447 delete pGameObj;
3448 return false;
3451 if( spawntimeSecs )
3453 uint32 value = atoi((char*)spawntimeSecs);
3454 pGameObj->SetRespawnTime(value);
3455 //sLog.outDebug("*** spawntimeSecs: %d", value);
3458 // fill the gameobject data and save to the db
3459 pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3461 // this will generate a new guid if the object is in an instance
3462 if(!pGameObj->LoadFromDB(db_lowGUID, map))
3464 delete pGameObj;
3465 return false;
3468 sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o);
3470 map->Add(pGameObj);
3472 // TODO: is it really necessary to add both the real and DB table guid here ?
3473 objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
3475 PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z);
3476 return true;
3479 //show animation
3480 bool ChatHandler::HandleAnimCommand(const char* args)
3482 if (!*args)
3483 return false;
3485 uint32 anim_id = atoi((char*)args);
3486 m_session->GetPlayer()->HandleEmoteCommand(anim_id);
3487 return true;
3490 //change standstate
3491 bool ChatHandler::HandleStandStateCommand(const char* args)
3493 if (!*args)
3494 return false;
3496 uint32 anim_id = atoi((char*)args);
3497 m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3499 return true;
3502 bool ChatHandler::HandleAddHonorCommand(const char* args)
3504 if (!*args)
3505 return false;
3507 Player *target = getSelectedPlayer();
3508 if(!target)
3510 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3511 SetSentErrorMessage(true);
3512 return false;
3515 uint32 amount = (uint32)atoi(args);
3516 target->RewardHonor(NULL, 1, amount);
3517 return true;
3520 bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3522 Unit *target = getSelectedUnit();
3523 if(!target)
3525 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3526 SetSentErrorMessage(true);
3527 return false;
3530 m_session->GetPlayer()->RewardHonor(target, 1);
3531 return true;
3534 bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/)
3536 Player *target = getSelectedPlayer();
3537 if(!target)
3539 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3540 SetSentErrorMessage(true);
3541 return false;
3544 target->UpdateHonorFields();
3545 return true;
3548 bool ChatHandler::HandleLookupEventCommand(const char* args)
3550 if(!*args)
3551 return false;
3553 std::string namepart = args;
3554 std::wstring wnamepart;
3556 // converting string that we try to find to lower case
3557 if(!Utf8toWStr(namepart,wnamepart))
3558 return false;
3560 wstrToLower(wnamepart);
3562 uint32 counter = 0;
3564 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3565 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3567 for(uint32 id = 0; id < events.size(); ++id )
3569 GameEventData const& eventData = events[id];
3571 std::string descr = eventData.description;
3572 if(descr.empty())
3573 continue;
3575 if (Utf8FitTo(descr, wnamepart))
3577 char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : "";
3579 if(m_session)
3580 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3581 else
3582 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3584 ++counter;
3588 if (counter==0)
3589 SendSysMessage(LANG_NOEVENTFOUND);
3591 return true;
3594 bool ChatHandler::HandleEventActiveListCommand(const char* /*args*/)
3596 uint32 counter = 0;
3598 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3599 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3601 char const* active = GetMangosString(LANG_ACTIVE);
3603 for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
3605 uint32 event_id = *itr;
3606 GameEventData const& eventData = events[event_id];
3608 if(m_session)
3609 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
3610 else
3611 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
3613 ++counter;
3616 if (counter==0)
3617 SendSysMessage(LANG_NOEVENTFOUND);
3619 return true;
3622 bool ChatHandler::HandleEventInfoCommand(const char* args)
3624 if(!*args)
3625 return false;
3627 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3628 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3629 if(!cId)
3630 return false;
3632 uint32 event_id = atoi(cId);
3634 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3636 if(event_id >=events.size())
3638 SendSysMessage(LANG_EVENT_NOT_EXIST);
3639 SetSentErrorMessage(true);
3640 return false;
3643 GameEventData const& eventData = events[event_id];
3644 if(!eventData.isValid())
3646 SendSysMessage(LANG_EVENT_NOT_EXIST);
3647 SetSentErrorMessage(true);
3648 return false;
3651 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3652 bool active = activeEvents.find(event_id) != activeEvents.end();
3653 char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : "";
3655 std::string startTimeStr = TimeToTimestampStr(eventData.start);
3656 std::string endTimeStr = TimeToTimestampStr(eventData.end);
3658 uint32 delay = gameeventmgr.NextCheck(event_id);
3659 time_t nextTime = time(NULL)+delay;
3660 std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3662 std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3663 std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3665 PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3666 startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3667 nextStr.c_str());
3668 return true;
3671 bool ChatHandler::HandleEventStartCommand(const char* args)
3673 if(!*args)
3674 return false;
3676 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3677 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3678 if(!cId)
3679 return false;
3681 int32 event_id = atoi(cId);
3683 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3685 if(event_id < 1 || event_id >=events.size())
3687 SendSysMessage(LANG_EVENT_NOT_EXIST);
3688 SetSentErrorMessage(true);
3689 return false;
3692 GameEventData const& eventData = events[event_id];
3693 if(!eventData.isValid())
3695 SendSysMessage(LANG_EVENT_NOT_EXIST);
3696 SetSentErrorMessage(true);
3697 return false;
3700 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3701 if(activeEvents.find(event_id) != activeEvents.end())
3703 PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3704 SetSentErrorMessage(true);
3705 return false;
3708 gameeventmgr.StartEvent(event_id,true);
3709 return true;
3712 bool ChatHandler::HandleEventStopCommand(const char* args)
3714 if(!*args)
3715 return false;
3717 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3718 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3719 if(!cId)
3720 return false;
3722 int32 event_id = atoi(cId);
3724 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3726 if(event_id < 1 || event_id >=events.size())
3728 SendSysMessage(LANG_EVENT_NOT_EXIST);
3729 SetSentErrorMessage(true);
3730 return false;
3733 GameEventData const& eventData = events[event_id];
3734 if(!eventData.isValid())
3736 SendSysMessage(LANG_EVENT_NOT_EXIST);
3737 SetSentErrorMessage(true);
3738 return false;
3741 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3743 if(activeEvents.find(event_id) == activeEvents.end())
3745 PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3746 SetSentErrorMessage(true);
3747 return false;
3750 gameeventmgr.StopEvent(event_id,true);
3751 return true;
3754 bool ChatHandler::HandleCombatStopCommand(const char* args)
3756 Player *player;
3758 if(*args)
3760 std::string playername = args;
3762 if(!normalizePlayerName(playername))
3764 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3765 SetSentErrorMessage(true);
3766 return false;
3769 player = objmgr.GetPlayer(playername.c_str());
3771 if(!player)
3773 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3774 SetSentErrorMessage(true);
3775 return false;
3778 else
3780 player = getSelectedPlayer();
3782 if (!player)
3783 player = m_session->GetPlayer();
3786 player->CombatStop();
3787 player->getHostilRefManager().deleteReferences();
3788 return true;
3791 bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3793 uint32 classmask = m_session->GetPlayer()->getClassMask();
3795 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3797 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3798 if( !skillInfo )
3799 continue;
3801 if( skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY )
3803 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3805 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3806 if( !skillLine )
3807 continue;
3809 // skip racial skills
3810 if( skillLine->racemask != 0 )
3811 continue;
3813 // skip wrong class skills
3814 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3815 continue;
3817 if( skillLine->skillId != i || skillLine->forward_spellid )
3818 continue;
3820 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3821 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3822 continue;
3824 m_session->GetPlayer()->learnSpell(skillLine->spellId);
3829 SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
3830 return true;
3833 bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
3835 // Learns all recipes of specified profession and sets skill to max
3836 // Example: .learn all_recipes enchanting
3838 Player* target = getSelectedPlayer();
3839 if( !target )
3841 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3842 return false;
3845 if(!*args)
3846 return false;
3848 std::wstring wnamepart;
3850 if(!Utf8toWStr(args,wnamepart))
3851 return false;
3853 // converting string that we try to find to lower case
3854 wstrToLower( wnamepart );
3856 uint32 classmask = m_session->GetPlayer()->getClassMask();
3858 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3860 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3861 if( !skillInfo )
3862 continue;
3864 if( skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
3865 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY )
3866 continue;
3868 int loc = m_session->GetSessionDbcLocale();
3869 std::string name = skillInfo->name[loc];
3871 if(Utf8FitTo(name, wnamepart))
3873 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3875 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3876 if( !skillLine )
3877 continue;
3879 if( skillLine->skillId != i || skillLine->forward_spellid )
3880 continue;
3882 // skip racial skills
3883 if( skillLine->racemask != 0 )
3884 continue;
3886 // skip wrong class skills
3887 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3888 continue;
3890 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3891 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3892 continue;
3894 if( !target->HasSpell(spellInfo->Id) )
3895 m_session->GetPlayer()->learnSpell(skillLine->spellId);
3898 uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
3899 target->SetSkill(skillInfo->id, maxLevel, maxLevel);
3900 PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
3901 return true;
3905 return false;
3908 bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
3911 if (!*args)
3912 return false;
3914 std::string ip = strtok ((char*)args, " ");
3915 char* limit_str = strtok (NULL, " ");
3916 int32 limit = limit_str ? atoi (limit_str) : -1;
3918 loginDatabase.escape_string (ip);
3920 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
3922 return LookupPlayerSearchCommand (result,limit);
3925 bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
3927 if (!*args)
3928 return false;
3930 std::string account = strtok ((char*)args, " ");
3931 char* limit_str = strtok (NULL, " ");
3932 int32 limit = limit_str ? atoi (limit_str) : -1;
3934 if (!AccountMgr::normilizeString (account))
3935 return false;
3937 loginDatabase.escape_string (account);
3939 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
3941 return LookupPlayerSearchCommand (result,limit);
3944 bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
3947 if (!*args)
3948 return false;
3950 std::string email = strtok ((char*)args, " ");
3951 char* limit_str = strtok (NULL, " ");
3952 int32 limit = limit_str ? atoi (limit_str) : -1;
3954 loginDatabase.escape_string (email);
3956 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
3958 return LookupPlayerSearchCommand (result,limit);
3961 bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
3963 if(!result)
3965 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
3966 SetSentErrorMessage(true);
3967 return false;
3970 int i =0;
3973 Field* fields = result->Fetch();
3974 uint32 acc_id = fields[0].GetUInt32();
3975 std::string acc_name = fields[1].GetCppString();
3977 QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
3978 if(chars)
3980 PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
3982 uint64 guid = 0;
3983 std::string name;
3987 Field* charfields = chars->Fetch();
3988 guid = charfields[0].GetUInt64();
3989 name = charfields[1].GetCppString();
3991 PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
3992 ++i;
3994 } while( chars->NextRow() && ( limit == -1 || i < limit ) );
3996 delete chars;
3998 } while(result->NextRow());
4000 delete result;
4002 return true;
4005 /// Triggering corpses expire check in world
4006 bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4008 CorpsesErase();
4009 return true;
4012 bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
4014 Player *target = getSelectedPlayer();
4016 if(!target)
4018 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4019 SetSentErrorMessage(true);
4020 return false;
4023 // Repair items
4024 target->DurabilityRepairAll(false, 0, false);
4026 PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName());
4027 if(needReportToTarget(target))
4028 ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName());
4029 return true;
4032 bool ChatHandler::HandleWaterwalkCommand(const char* args)
4034 if(!*args)
4035 return false;
4037 Player *player = getSelectedPlayer();
4039 if(!player)
4041 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4042 SetSentErrorMessage(true);
4043 return false;
4046 if (strncmp(args, "on", 3) == 0)
4047 player->SetMovement(MOVE_WATER_WALK); // ON
4048 else if (strncmp(args, "off", 4) == 0)
4049 player->SetMovement(MOVE_LAND_WALK); // OFF
4050 else
4052 SendSysMessage(LANG_USE_BOL);
4053 return false;
4056 PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
4057 if(needReportToTarget(player))
4058 ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
4059 return true;
4062 bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
4064 Player *player = m_session->GetPlayer();
4065 Creature *creature = getSelectedCreature();
4067 if(!creature)
4069 PSendSysMessage(LANG_SELECT_CREATURE);
4070 SetSentErrorMessage(true);
4071 return false;
4074 // Follow player - Using pet's default dist and angle
4075 creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
4077 PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
4078 return true;
4081 bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
4083 Player *player = m_session->GetPlayer();
4084 Creature *creature = getSelectedCreature();
4086 if(!creature)
4088 PSendSysMessage(LANG_SELECT_CREATURE);
4089 SetSentErrorMessage(true);
4090 return false;
4093 if (creature->GetMotionMaster()->empty() ||
4094 creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
4096 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4097 SetSentErrorMessage(true);
4098 return false;
4101 TargetedMovementGenerator<Creature> const* mgen
4102 = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
4104 if(mgen->GetTarget()!=player)
4106 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4107 SetSentErrorMessage(true);
4108 return false;
4111 // reset movement
4112 creature->GetMotionMaster()->MovementExpired(true);
4114 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
4115 return true;
4118 bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
4120 Creature *creatureTarget = getSelectedCreature ();
4121 if (!creatureTarget || creatureTarget->isPet ())
4123 PSendSysMessage (LANG_SELECT_CREATURE);
4124 SetSentErrorMessage (true);
4125 return false;
4128 Player *player = m_session->GetPlayer ();
4130 if(player->GetPetGUID ())
4132 SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
4133 SetSentErrorMessage (true);
4134 return false;
4137 CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
4139 if (!cInfo->isTameable ())
4141 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4142 SetSentErrorMessage (true);
4143 return false;
4146 // Everything looks OK, create new pet
4147 Pet* pet = player->CreateTamedPetFrom (creatureTarget);
4148 if (!pet)
4150 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4151 SetSentErrorMessage (true);
4152 return false;
4155 // place pet before player
4156 float x,y,z;
4157 player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
4158 pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
4160 // set pet to defensive mode by default (some classes can't control contolled pets in fact).
4161 pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4163 // prepare visual effect for levelup
4164 pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
4166 // add to world
4167 MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
4169 // visual effect for levelup
4170 pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
4172 // caster have pet now
4173 player->SetPet(pet);
4175 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4176 player->PetSpellInitialize();
4178 return true;