Fixed some format arg type/value pairs. Other warnings.
[getmangos.git] / src / game / Level2.cpp
blobfb07a793fdccd3770b09deda9bc6a9ba98f19202
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 "WaypointManager.h"
38 #include "Util.h"
39 #include <cctype>
40 #include <iostream>
41 #include <fstream>
42 #include <map>
43 #include "GlobalEvents.h"
45 #include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
47 static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
49 LANG_REP_HATED, LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL,
50 LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED, LANG_REP_EXALTED
53 //mute player for some times
54 bool ChatHandler::HandleMuteCommand(const char* args)
56 if (!*args)
57 return false;
59 char *charname = strtok((char*)args, " ");
60 if (!charname)
61 return false;
63 std::string cname = charname;
65 char *timetonotspeak = strtok(NULL, " ");
66 if(!timetonotspeak)
67 return false;
69 uint32 notspeaktime = (uint32) atoi(timetonotspeak);
71 if(!normalizePlayerName(cname))
73 SendSysMessage(LANG_PLAYER_NOT_FOUND);
74 SetSentErrorMessage(true);
75 return false;
78 uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
79 if(!guid)
81 SendSysMessage(LANG_PLAYER_NOT_FOUND);
82 SetSentErrorMessage(true);
83 return false;
86 Player *chr = objmgr.GetPlayer(guid);
88 // check security
89 uint32 account_id = 0;
90 uint32 security = 0;
92 if (chr)
94 account_id = chr->GetSession()->GetAccountId();
95 security = chr->GetSession()->GetSecurity();
97 else
99 account_id = objmgr.GetPlayerAccountIdByGUID(guid);
100 security = accmgr.GetSecurity(account_id);
103 if(m_session && security >= m_session->GetSecurity())
105 SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
106 SetSentErrorMessage(true);
107 return false;
110 time_t mutetime = time(NULL) + notspeaktime*60;
112 if (chr)
113 chr->GetSession()->m_muteTime = mutetime;
115 loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
117 if(chr)
118 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
120 PSendSysMessage(LANG_YOU_DISABLE_CHAT, cname.c_str(), notspeaktime);
122 return true;
125 //unmute player
126 bool ChatHandler::HandleUnmuteCommand(const char* args)
128 if (!*args)
129 return false;
131 char *charname = strtok((char*)args, " ");
132 if (!charname)
133 return false;
135 std::string cname = charname;
137 if(!normalizePlayerName(cname))
139 SendSysMessage(LANG_PLAYER_NOT_FOUND);
140 SetSentErrorMessage(true);
141 return false;
144 uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
145 if(!guid)
147 SendSysMessage(LANG_PLAYER_NOT_FOUND);
148 SetSentErrorMessage(true);
149 return false;
152 Player *chr = objmgr.GetPlayer(guid);
154 // check security
155 uint32 account_id = 0;
156 uint32 security = 0;
158 if (chr)
160 account_id = chr->GetSession()->GetAccountId();
161 security = chr->GetSession()->GetSecurity();
163 else
165 account_id = objmgr.GetPlayerAccountIdByGUID(guid);
166 security = accmgr.GetSecurity(account_id);
169 if(m_session && security >= m_session->GetSecurity())
171 SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
172 SetSentErrorMessage(true);
173 return false;
176 if (chr)
178 if(chr->CanSpeak())
180 SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
181 SetSentErrorMessage(true);
182 return false;
185 chr->GetSession()->m_muteTime = 0;
188 loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
190 if(chr)
191 ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
193 PSendSysMessage(LANG_YOU_ENABLE_CHAT, cname.c_str());
194 return true;
197 bool ChatHandler::HandleTargetObjectCommand(const char* args)
199 Player* pl = m_session->GetPlayer();
200 QueryResult *result;
201 GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
202 if(*args)
204 int32 id = atoi((char*)args);
205 if(id)
206 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",
207 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
208 else
210 std::string name = args;
211 WorldDatabase.escape_string(name);
212 result = WorldDatabase.PQuery(
213 "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_ "
214 "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
215 pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
218 else
220 std::ostringstream eventFilter;
221 eventFilter << " AND (event IS NULL ";
222 bool initString = true;
224 for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
226 if (initString)
228 eventFilter << "OR event IN (" <<*itr;
229 initString =false;
231 else
232 eventFilter << "," << *itr;
235 if (!initString)
236 eventFilter << "))";
237 else
238 eventFilter << ")";
240 result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
241 "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
242 "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 1",
243 m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
246 if (!result)
248 SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
249 return true;
252 Field *fields = result->Fetch();
253 uint32 lowguid = fields[0].GetUInt32();
254 uint32 id = fields[1].GetUInt32();
255 float x = fields[2].GetFloat();
256 float y = fields[3].GetFloat();
257 float z = fields[4].GetFloat();
258 float o = fields[5].GetFloat();
259 int mapid = fields[6].GetUInt16();
260 delete result;
262 GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id);
264 if (!goI)
266 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
267 return false;
270 GameObject* target = ObjectAccessor::GetGameObject(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
272 PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
274 if(target)
276 int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
277 if(curRespawnDelay < 0)
278 curRespawnDelay = 0;
280 std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
281 std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
283 PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
285 return true;
288 //teleport to gameobject
289 bool ChatHandler::HandleGoObjectCommand(const char* args)
291 if(!*args)
292 return false;
294 Player* _player = m_session->GetPlayer();
296 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
297 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
298 if(!cId)
299 return false;
301 int32 guid = atoi(cId);
302 if(!guid)
303 return false;
305 float x, y, z, ort;
306 int mapid;
308 // by DB guid
309 if (GameObjectData const* go_data = objmgr.GetGOData(guid))
311 x = go_data->posX;
312 y = go_data->posY;
313 z = go_data->posZ;
314 ort = go_data->orientation;
315 mapid = go_data->mapid;
317 else
319 SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
320 SetSentErrorMessage(true);
321 return false;
324 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
326 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
327 SetSentErrorMessage(true);
328 return false;
331 // stop flight if need
332 if(_player->isInFlight())
334 _player->GetMotionMaster()->MovementExpired();
335 _player->m_taxi.ClearTaxiDestinations();
337 // save only in non-flight case
338 else
339 _player->SaveRecallPosition();
341 _player->TeleportTo(mapid, x, y, z, ort);
342 return true;
345 bool ChatHandler::HandleGoTriggerCommand(const char* args)
347 Player* _player = m_session->GetPlayer();
349 if (!*args)
350 return false;
352 char *atId = strtok((char*)args, " ");
353 if (!atId)
354 return false;
356 int32 i_atId = atoi(atId);
358 if(!i_atId)
359 return false;
361 AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
362 if (!at)
364 PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
365 SetSentErrorMessage(true);
366 return false;
369 if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
371 PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
372 SetSentErrorMessage(true);
373 return false;
376 // stop flight if need
377 if(_player->isInFlight())
379 _player->GetMotionMaster()->MovementExpired();
380 _player->m_taxi.ClearTaxiDestinations();
382 // save only in non-flight case
383 else
384 _player->SaveRecallPosition();
386 _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
387 return true;
390 bool ChatHandler::HandleGoGraveyardCommand(const char* args)
392 Player* _player = m_session->GetPlayer();
394 if (!*args)
395 return false;
397 char *gyId = strtok((char*)args, " ");
398 if (!gyId)
399 return false;
401 int32 i_gyId = atoi(gyId);
403 if(!i_gyId)
404 return false;
406 WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
407 if (!gy)
409 PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
410 SetSentErrorMessage(true);
411 return false;
414 if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
416 PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
417 SetSentErrorMessage(true);
418 return false;
421 // stop flight if need
422 if(_player->isInFlight())
424 _player->GetMotionMaster()->MovementExpired();
425 _player->m_taxi.ClearTaxiDestinations();
427 // save only in non-flight case
428 else
429 _player->SaveRecallPosition();
431 _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
432 return true;
435 /** \brief Teleport the GM to the specified creature
437 * .gocreature <GUID> --> TP using creature.guid
438 * .gocreature azuregos --> TP player to the mob with this name
439 * Warning: If there is more than one mob with this name
440 * you will be teleported to the first one that is found.
441 * .gocreature id 6109 --> TP player to the mob, that has this creature_template.entry
442 * Warning: If there is more than one mob with this "id"
443 * you will be teleported to the first one that is found.
445 //teleport to creature
446 bool ChatHandler::HandleGoCreatureCommand(const char* args)
448 if(!*args)
449 return false;
450 Player* _player = m_session->GetPlayer();
452 // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
453 char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
454 if (!pParam1)
455 return false;
457 std::ostringstream whereClause;
459 // User wants to teleport to the NPC's template entry
460 if( strcmp(pParam1, "id") == 0 )
462 //sLog.outError("DEBUG: ID found");
464 // Get the "creature_template.entry"
465 // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
466 char* tail = strtok(NULL,"");
467 if(!tail)
468 return false;
469 char* cId = extractKeyFromLink(tail,"Hcreature_entry");
470 if(!cId)
471 return false;
473 int32 tEntry = atoi(cId);
474 //sLog.outError("DEBUG: ID value: %d", tEntry);
475 if(!tEntry)
476 return false;
478 whereClause << "WHERE id = '" << tEntry << "'";
480 else
482 //sLog.outError("DEBUG: ID *not found*");
484 int32 guid = atoi(pParam1);
486 // Number is invalid - maybe the user specified the mob's name
487 if(!guid)
489 std::string name = pParam1;
490 WorldDatabase.escape_string(name);
491 whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
493 else
495 whereClause << "WHERE guid = '" << guid << "'";
498 //sLog.outError("DEBUG: %s", whereClause.c_str());
500 QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
501 if (!result)
503 SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
504 SetSentErrorMessage(true);
505 return false;
507 if( result->GetRowCount() > 1 )
509 SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
512 Field *fields = result->Fetch();
513 float x = fields[0].GetFloat();
514 float y = fields[1].GetFloat();
515 float z = fields[2].GetFloat();
516 float ort = fields[3].GetFloat();
517 int mapid = fields[4].GetUInt16();
519 delete result;
521 if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
523 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
524 SetSentErrorMessage(true);
525 return false;
528 // stop flight if need
529 if(_player->isInFlight())
531 _player->GetMotionMaster()->MovementExpired();
532 _player->m_taxi.ClearTaxiDestinations();
534 // save only in non-flight case
535 else
536 _player->SaveRecallPosition();
538 _player->TeleportTo(mapid, x, y, z, ort);
539 return true;
542 bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
544 uint64 guid = m_session->GetPlayer()->GetSelection();
546 if (guid == 0)
548 SendSysMessage(LANG_NO_SELECTION);
549 SetSentErrorMessage(true);
550 return false;
553 PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
554 return true;
557 bool ChatHandler::HandleLookupFactionCommand(const char* args)
559 if (!*args)
560 return false;
562 // Can be NULL at console call
563 Player *target = getSelectedPlayer ();
565 std::string namepart = args;
566 std::wstring wnamepart;
568 if (!Utf8toWStr (namepart,wnamepart))
569 return false;
571 // converting string that we try to find to lower case
572 wstrToLower (wnamepart);
574 uint32 counter = 0; // Counter for figure out that we found smth.
576 for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
578 FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
579 if (factionEntry)
581 FactionState const* repState = NULL;
582 if(target)
584 FactionStateList::const_iterator repItr = target->m_factions.find (factionEntry->reputationListID);
585 if(repItr != target->m_factions.end())
586 repState = &repItr->second;
590 int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale();
591 std::string name = factionEntry->name[loc];
592 if(name.empty())
593 continue;
595 if (!Utf8FitTo(name, wnamepart))
597 loc = 0;
598 for(; loc < MAX_LOCALE; ++loc)
600 if(m_session && loc==m_session->GetSessionDbcLocale())
601 continue;
603 name = factionEntry->name[loc];
604 if(name.empty())
605 continue;
607 if (Utf8FitTo(name, wnamepart))
608 break;
612 if(loc < MAX_LOCALE)
614 // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
615 // or "id - [faction] [no reputation]" format
616 std::ostringstream ss;
617 if (m_session)
618 ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
619 else
620 ss << id << " - " << name << " " << localeNames[loc];
622 if (repState) // and then target!=NULL also
624 ReputationRank rank = target->GetReputationRank(factionEntry);
625 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
627 ss << " " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
629 if(repState->Flags & FACTION_FLAG_VISIBLE)
630 ss << GetMangosString(LANG_FACTION_VISIBLE);
631 if(repState->Flags & FACTION_FLAG_AT_WAR)
632 ss << GetMangosString(LANG_FACTION_ATWAR);
633 if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
634 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
635 if(repState->Flags & FACTION_FLAG_HIDDEN)
636 ss << GetMangosString(LANG_FACTION_HIDDEN);
637 if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
638 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
639 if(repState->Flags & FACTION_FLAG_INACTIVE)
640 ss << GetMangosString(LANG_FACTION_INACTIVE);
642 else
643 ss << GetMangosString(LANG_FACTION_NOREPUTATION);
645 SendSysMessage(ss.str().c_str());
646 counter++;
651 if (counter == 0) // if counter == 0 then we found nth
652 SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
653 return true;
656 bool ChatHandler::HandleModifyRepCommand(const char * args)
658 if (!*args) return false;
660 Player* target = NULL;
661 target = getSelectedPlayer();
663 if(!target)
665 SendSysMessage(LANG_PLAYER_NOT_FOUND);
666 SetSentErrorMessage(true);
667 return false;
670 char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
671 if(!factionTxt)
672 return false;
674 uint32 factionId = atoi(factionTxt);
676 int32 amount = 0;
677 char *rankTxt = strtok(NULL, " ");
678 if (!factionTxt || !rankTxt)
679 return false;
681 amount = atoi(rankTxt);
682 if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
684 std::string rankStr = rankTxt;
685 std::wstring wrankStr;
686 if(!Utf8toWStr(rankStr,wrankStr))
687 return false;
688 wstrToLower( wrankStr );
690 int r = 0;
691 amount = -42000;
692 for (; r < MAX_REPUTATION_RANK; ++r)
694 std::string rank = GetMangosString(ReputationRankStrIndex[r]);
695 if(rank.empty())
696 continue;
698 std::wstring wrank;
699 if(!Utf8toWStr(rank,wrank))
700 continue;
702 wstrToLower(wrank);
704 if(wrank.substr(0,wrankStr.size())==wrankStr)
706 char *deltaTxt = strtok(NULL, " ");
707 if (deltaTxt)
709 int32 delta = atoi(deltaTxt);
710 if ((delta < 0) || (delta > Player::ReputationRank_Length[r] -1))
712 PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (Player::ReputationRank_Length[r]-1));
713 SetSentErrorMessage(true);
714 return false;
716 amount += delta;
718 break;
720 amount += Player::ReputationRank_Length[r];
722 if (r >= MAX_REPUTATION_RANK)
724 PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
725 SetSentErrorMessage(true);
726 return false;
730 FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
732 if (!factionEntry)
734 PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
735 SetSentErrorMessage(true);
736 return false;
739 if (factionEntry->reputationListID < 0)
741 PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[m_session->GetSessionDbcLocale()], factionId);
742 SetSentErrorMessage(true);
743 return false;
746 target->SetFactionReputation(factionEntry,amount);
747 PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, target->GetName(), target->GetReputation(factionId));
748 return true;
751 bool ChatHandler::HandleNameCommand(const char* args)
753 /* Temp. disabled
754 if(!*args)
755 return false;
757 if(strlen((char*)args)>75)
759 PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
760 return true;
763 for (uint8 i = 0; i < strlen(args); i++)
765 if(!isalpha(args[i]) && args[i]!=' ')
767 SendSysMessage(LANG_CHARS_ONLY);
768 return false;
772 uint64 guid;
773 guid = m_session->GetPlayer()->GetSelection();
774 if (guid == 0)
776 SendSysMessage(LANG_NO_SELECTION);
777 return true;
780 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
782 if(!pCreature)
784 SendSysMessage(LANG_SELECT_CREATURE);
785 return true;
788 pCreature->SetName(args);
789 uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName());
790 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
792 pCreature->SaveToDB();
795 return true;
798 bool ChatHandler::HandleSubNameCommand(const char* /*args*/)
800 /* Temp. disabled
802 if(!*args)
803 args = "";
805 if(strlen((char*)args)>75)
808 PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
809 return true;
812 for (uint8 i = 0; i < strlen(args); i++)
814 if(!isalpha(args[i]) && args[i]!=' ')
816 SendSysMessage(LANG_CHARS_ONLY);
817 return false;
820 uint64 guid;
821 guid = m_session->GetPlayer()->GetSelection();
822 if (guid == 0)
824 SendSysMessage(LANG_NO_SELECTION);
825 return true;
828 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
830 if(!pCreature)
832 SendSysMessage(LANG_SELECT_CREATURE);
833 return true;
836 uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
837 pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
839 pCreature->SaveToDB();
841 return true;
844 //move item to other slot
845 bool ChatHandler::HandleItemMoveCommand(const char* args)
847 if(!*args)
848 return false;
849 uint8 srcslot, dstslot;
851 char* pParam1 = strtok((char*)args, " ");
852 if (!pParam1)
853 return false;
855 char* pParam2 = strtok(NULL, " ");
856 if (!pParam2)
857 return false;
859 srcslot = (uint8)atoi(pParam1);
860 dstslot = (uint8)atoi(pParam2);
862 if(srcslot==dstslot)
863 return true;
865 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot))
866 return false;
868 if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot))
869 return false;
871 uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
872 uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
874 m_session->GetPlayer()->SwapItem( src, dst );
876 return true;
879 //add spawn of creature
880 bool ChatHandler::HandleNpcAddCommand(const char* args)
882 if(!*args)
883 return false;
884 char* charID = strtok((char*)args, " ");
885 if (!charID)
886 return false;
888 char* team = strtok(NULL, " ");
889 int32 teamval = 0;
890 if (team) { teamval = atoi(team); }
891 if (teamval < 0) { teamval = 0; }
893 uint32 id = atoi(charID);
895 Player *chr = m_session->GetPlayer();
896 float x = chr->GetPositionX();
897 float y = chr->GetPositionY();
898 float z = chr->GetPositionZ();
899 float o = chr->GetOrientation();
900 Map *map = chr->GetMap();
902 Creature* pCreature = new Creature;
903 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, (uint32)teamval))
905 delete pCreature;
906 return false;
909 pCreature->Relocate(x,y,z,o);
911 if(!pCreature->IsPositionValid())
913 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());
914 delete pCreature;
915 return false;
918 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
920 uint32 db_guid = pCreature->GetDBTableGUIDLow();
922 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
923 pCreature->LoadFromDB(db_guid, map);
925 map->Add(pCreature);
926 objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid));
927 return true;
930 bool ChatHandler::HandleNpcDeleteCommand(const char* args)
932 Creature* unit = NULL;
934 if(*args)
936 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
937 char* cId = extractKeyFromLink((char*)args,"Hcreature");
938 if(!cId)
939 return false;
941 uint32 lowguid = atoi(cId);
942 if(!lowguid)
943 return false;
945 if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid))
946 unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
948 else
949 unit = getSelectedCreature();
951 if(!unit || unit->isPet() || unit->isTotem())
953 SendSysMessage(LANG_SELECT_CREATURE);
954 SetSentErrorMessage(true);
955 return false;
958 // Delete the creature
959 unit->CombatStop();
960 unit->DeleteFromDB();
961 unit->CleanupsBeforeDelete();
962 unit->AddObjectToRemoveList();
964 SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
966 return true;
969 //delete object by selection or guid
970 bool ChatHandler::HandleDelObjectCommand(const char* args)
972 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
973 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
974 if(!cId)
975 return false;
977 uint32 lowguid = atoi(cId);
978 if(!lowguid)
979 return false;
981 GameObject* obj = NULL;
983 // by DB guid
984 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
985 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
987 if(!obj)
989 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
990 SetSentErrorMessage(true);
991 return false;
994 uint64 owner_guid = obj->GetOwnerGUID();
995 if(owner_guid)
997 Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
998 if(!owner && !IS_PLAYER_GUID(owner_guid))
1000 PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
1001 SetSentErrorMessage(true);
1002 return false;
1005 owner->RemoveGameObject(obj,false);
1008 obj->SetRespawnTime(0); // not save respawn time
1009 obj->Delete();
1010 obj->DeleteFromDB();
1012 PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
1014 return true;
1017 //turn selected object
1018 bool ChatHandler::HandleTurnObjectCommand(const char* args)
1020 // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
1021 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1022 if(!cId)
1023 return false;
1025 uint32 lowguid = atoi(cId);
1026 if(!lowguid)
1027 return false;
1029 GameObject* obj = NULL;
1031 // by DB guid
1032 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1033 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1035 if(!obj)
1037 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1038 SetSentErrorMessage(true);
1039 return false;
1042 char* po = strtok(NULL, " ");
1043 float o;
1045 if (po)
1047 o = (float)atof(po);
1049 else
1051 Player *chr = m_session->GetPlayer();
1052 o = chr->GetOrientation();
1055 float rot2 = sin(o/2);
1056 float rot3 = cos(o/2);
1058 Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1059 map->Remove(obj,false);
1061 obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
1063 obj->SetFloatValue(GAMEOBJECT_FACING, o);
1064 obj->SetFloatValue(GAMEOBJECT_ROTATION+2, rot2);
1065 obj->SetFloatValue(GAMEOBJECT_ROTATION+3, rot3);
1067 map->Add(obj);
1069 obj->SaveToDB();
1070 obj->Refresh();
1072 PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o);
1074 return true;
1077 //move selected creature
1078 bool ChatHandler::HandleNpcMoveCommand(const char* args)
1080 uint32 lowguid = 0;
1082 Creature* pCreature = getSelectedCreature();
1084 if(!pCreature)
1086 // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1087 char* cId = extractKeyFromLink((char*)args,"Hcreature");
1088 if(!cId)
1089 return false;
1091 uint32 lowguid = atoi(cId);
1093 /* FIXME: impossibel without entry
1094 if(lowguid)
1095 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1098 // Attempting creature load from DB data
1099 if(!pCreature)
1101 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1102 if(!data)
1104 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1105 SetSentErrorMessage(true);
1106 return false;
1109 uint32 map_id = data->mapid;
1111 if(m_session->GetPlayer()->GetMapId()!=map_id)
1113 PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1114 SetSentErrorMessage(true);
1115 return false;
1118 else
1120 lowguid = pCreature->GetDBTableGUIDLow();
1123 else
1125 lowguid = pCreature->GetDBTableGUIDLow();
1128 float x = m_session->GetPlayer()->GetPositionX();
1129 float y = m_session->GetPlayer()->GetPositionY();
1130 float z = m_session->GetPlayer()->GetPositionZ();
1131 float o = m_session->GetPlayer()->GetOrientation();
1133 if (pCreature)
1135 if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1137 const_cast<CreatureData*>(data)->posX = x;
1138 const_cast<CreatureData*>(data)->posY = y;
1139 const_cast<CreatureData*>(data)->posZ = z;
1140 const_cast<CreatureData*>(data)->orientation = o;
1142 MapManager::Instance().GetMap(pCreature->GetMapId(),pCreature)->CreatureRelocation(pCreature,x, y, z,o);
1143 pCreature->GetMotionMaster()->Initialize();
1144 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1146 pCreature->setDeathState(JUST_DIED);
1147 pCreature->Respawn();
1151 WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1152 PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1153 return true;
1156 //move selected object
1157 bool ChatHandler::HandleMoveObjectCommand(const char* args)
1159 // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
1160 char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1161 if(!cId)
1162 return false;
1164 uint32 lowguid = atoi(cId);
1165 if(!lowguid)
1166 return false;
1168 GameObject* obj = NULL;
1170 // by DB guid
1171 if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1172 obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1174 if(!obj)
1176 PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1177 SetSentErrorMessage(true);
1178 return false;
1181 char* px = strtok(NULL, " ");
1182 char* py = strtok(NULL, " ");
1183 char* pz = strtok(NULL, " ");
1185 if (!px)
1187 Player *chr = m_session->GetPlayer();
1189 Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1190 map->Remove(obj,false);
1192 obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
1193 obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX());
1194 obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY());
1195 obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ());
1197 map->Add(obj);
1199 else
1201 if(!py || !pz)
1202 return false;
1204 float x = (float)atof(px);
1205 float y = (float)atof(py);
1206 float z = (float)atof(pz);
1208 if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
1210 PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
1211 SetSentErrorMessage(true);
1212 return false;
1215 Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1216 map->Remove(obj,false);
1218 obj->Relocate(x, y, z, obj->GetOrientation());
1219 obj->SetFloatValue(GAMEOBJECT_POS_X, x);
1220 obj->SetFloatValue(GAMEOBJECT_POS_Y, y);
1221 obj->SetFloatValue(GAMEOBJECT_POS_Z, z);
1223 map->Add(obj);
1226 obj->SaveToDB();
1227 obj->Refresh();
1229 PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow());
1231 return true;
1234 //demorph player or unit
1235 bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
1237 Unit *target = getSelectedUnit();
1238 if(!target)
1239 target = m_session->GetPlayer();
1241 target->DeMorph();
1243 return true;
1246 //add item in vendorlist
1247 bool ChatHandler::HandleAddVendorItemCommand(const char* args)
1249 if (!*args)
1250 return false;
1252 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1253 if (!pitem)
1255 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1256 SetSentErrorMessage(true);
1257 return false;
1260 uint32 itemId = atol(pitem);
1262 char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0
1263 uint32 maxcount = 0;
1264 if (fmaxcount)
1265 maxcount = atol(fmaxcount);
1267 char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0
1268 uint32 incrtime = 0;
1269 if (fincrtime)
1270 incrtime = atol(fincrtime);
1272 char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0
1273 uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1275 Creature* vendor = getSelectedCreature();
1277 uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1279 if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1281 SetSentErrorMessage(true);
1282 return false;
1285 objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1287 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1289 PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1290 return true;
1293 //del item from vendor list
1294 bool ChatHandler::HandleDelVendorItemCommand(const char* args)
1296 if (!*args)
1297 return false;
1299 Creature* vendor = getSelectedCreature();
1300 if (!vendor || !vendor->isVendor())
1302 SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1303 SetSentErrorMessage(true);
1304 return false;
1307 char* pitem = extractKeyFromLink((char*)args,"Hitem");
1308 if (!pitem)
1310 SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1311 SetSentErrorMessage(true);
1312 return false;
1314 uint32 itemId = atol(pitem);
1316 if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1318 PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1319 SetSentErrorMessage(true);
1320 return false;
1323 ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1325 PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1326 return true;
1329 //add move for creature
1330 bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
1332 if(!*args)
1333 return false;
1335 char* guid_str = strtok((char*)args, " ");
1336 char* wait_str = strtok((char*)NULL, " ");
1338 uint32 lowguid = atoi((char*)guid_str);
1340 Creature* pCreature = NULL;
1342 /* FIXME: impossible without entry
1343 if(lowguid)
1344 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1347 // attempt check creature existence by DB data
1348 if(!pCreature)
1350 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1351 if(!data)
1353 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1354 SetSentErrorMessage(true);
1355 return false;
1358 else
1360 // obtain real GUID for DB operations
1361 lowguid = pCreature->GetDBTableGUIDLow();
1364 int wait = wait_str ? atoi(wait_str) : 0;
1366 if(wait < 0)
1367 wait = 0;
1369 Player* player = m_session->GetPlayer();
1371 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1373 // update movement type
1374 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1375 if(pCreature)
1377 pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1378 pCreature->GetMotionMaster()->Initialize();
1379 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1381 pCreature->setDeathState(JUST_DIED);
1382 pCreature->Respawn();
1384 pCreature->SaveToDB();
1387 SendSysMessage(LANG_WAYPOINT_ADDED);
1389 return true;
1393 * Set the movement type for an NPC.<br/>
1394 * <br/>
1395 * Valid movement types are:
1396 * <ul>
1397 * <li> stay - NPC wont move </li>
1398 * <li> random - NPC will move randomly according to the spawndist </li>
1399 * <li> way - NPC will move with given waypoints set </li>
1400 * </ul>
1401 * additional parameter: NODEL - so no waypoints are deleted, if you
1402 * change the movement type
1404 bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
1406 if(!*args)
1407 return false;
1409 // 3 arguments:
1410 // GUID (optional - you can also select the creature)
1411 // stay|random|way (determines the kind of movement)
1412 // NODEL (optional - tells the system NOT to delete any waypoints)
1413 // this is very handy if you want to do waypoints, that are
1414 // later switched on/off according to special events (like escort
1415 // quests, etc)
1416 char* guid_str = strtok((char*)args, " ");
1417 char* type_str = strtok((char*)NULL, " ");
1418 char* dontdel_str = strtok((char*)NULL, " ");
1420 bool doNotDelete = false;
1422 if(!guid_str)
1423 return false;
1425 uint32 lowguid = 0;
1426 Creature* pCreature = NULL;
1428 if( dontdel_str )
1430 //sLog.outError("DEBUG: All 3 params are set");
1432 // All 3 params are set
1433 // GUID
1434 // type
1435 // doNotDEL
1436 if( stricmp( dontdel_str, "NODEL" ) == 0 )
1438 //sLog.outError("DEBUG: doNotDelete = true;");
1439 doNotDelete = true;
1442 else
1444 // Only 2 params - but maybe NODEL is set
1445 if( type_str )
1447 sLog.outError("DEBUG: Only 2 params ");
1448 if( stricmp( type_str, "NODEL" ) == 0 )
1450 //sLog.outError("DEBUG: type_str, NODEL ");
1451 doNotDelete = true;
1452 type_str = NULL;
1457 if(!type_str) // case .setmovetype $move_type (with selected creature)
1459 type_str = guid_str;
1460 pCreature = getSelectedCreature();
1461 if(!pCreature || pCreature->isPet())
1462 return false;
1463 lowguid = pCreature->GetDBTableGUIDLow();
1465 else // case .setmovetype #creature_guid $move_type (with selected creature)
1467 lowguid = atoi((char*)guid_str);
1469 /* impossible without entry
1470 if(lowguid)
1471 pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1474 // attempt check creature existence by DB data
1475 if(!pCreature)
1477 CreatureData const* data = objmgr.GetCreatureData(lowguid);
1478 if(!data)
1480 PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1481 SetSentErrorMessage(true);
1482 return false;
1485 else
1487 lowguid = pCreature->GetDBTableGUIDLow();
1491 // now lowguid is low guid really existed creature
1492 // and pCreature point (maybe) to this creature or NULL
1494 MovementGeneratorType move_type;
1496 std::string type = type_str;
1498 if(type == "stay")
1499 move_type = IDLE_MOTION_TYPE;
1500 else if(type == "random")
1501 move_type = RANDOM_MOTION_TYPE;
1502 else if(type == "way")
1503 move_type = WAYPOINT_MOTION_TYPE;
1504 else
1505 return false;
1507 // update movement type
1508 if(doNotDelete == false)
1509 WaypointMgr.DeletePath(lowguid);
1511 if(pCreature)
1513 pCreature->SetDefaultMovementType(move_type);
1514 pCreature->GetMotionMaster()->Initialize();
1515 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
1517 pCreature->setDeathState(JUST_DIED);
1518 pCreature->Respawn();
1520 pCreature->SaveToDB();
1522 if( doNotDelete == false )
1524 PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1526 else
1528 PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1531 return true;
1532 } // HandleNpcSetMoveTypeCommand
1534 //change level of creature or pet
1535 bool ChatHandler::HandleChangeLevelCommand(const char* args)
1537 if (!*args)
1538 return false;
1540 uint8 lvl = (uint8) atoi((char*)args);
1541 if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3)
1543 SendSysMessage(LANG_BAD_VALUE);
1544 SetSentErrorMessage(true);
1545 return false;
1548 Creature* pCreature = getSelectedCreature();
1549 if(!pCreature)
1551 SendSysMessage(LANG_SELECT_CREATURE);
1552 SetSentErrorMessage(true);
1553 return false;
1556 if(pCreature->isPet())
1558 ((Pet*)pCreature)->GivePetLevel(lvl);
1560 else
1562 pCreature->SetMaxHealth( 100 + 30*lvl);
1563 pCreature->SetHealth( 100 + 30*lvl);
1564 pCreature->SetLevel( lvl);
1565 pCreature->SaveToDB();
1568 return true;
1571 //set npcflag of creature
1572 bool ChatHandler::HandleNpcFlagCommand(const char* args)
1574 if (!*args)
1575 return false;
1577 uint32 npcFlags = (uint32) atoi((char*)args);
1579 Creature* pCreature = getSelectedCreature();
1581 if(!pCreature)
1583 SendSysMessage(LANG_SELECT_CREATURE);
1584 SetSentErrorMessage(true);
1585 return false;
1588 pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1590 WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1592 SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1594 return true;
1597 //set model of creature
1598 bool ChatHandler::HandleNpcSetModelCommand(const char* args)
1600 if (!*args)
1601 return false;
1603 uint32 displayId = (uint32) atoi((char*)args);
1605 Creature *pCreature = getSelectedCreature();
1607 if(!pCreature || pCreature->isPet())
1609 SendSysMessage(LANG_SELECT_CREATURE);
1610 SetSentErrorMessage(true);
1611 return false;
1614 pCreature->SetDisplayId(displayId);
1615 pCreature->SetNativeDisplayId(displayId);
1617 pCreature->SaveToDB();
1619 return true;
1622 //morph creature or player
1623 bool ChatHandler::HandleMorphCommand(const char* args)
1625 if (!*args)
1626 return false;
1628 uint16 display_id = (uint16)atoi((char*)args);
1630 Unit *target = getSelectedUnit();
1631 if(!target)
1632 target = m_session->GetPlayer();
1634 target->SetDisplayId(display_id);
1636 return true;
1639 //set faction of creature
1640 bool ChatHandler::HandleNpcFactionIdCommand(const char* args)
1642 if (!*args)
1643 return false;
1645 uint32 factionId = (uint32) atoi((char*)args);
1647 if (!sFactionTemplateStore.LookupEntry(factionId))
1649 PSendSysMessage(LANG_WRONG_FACTION, factionId);
1650 SetSentErrorMessage(true);
1651 return false;
1654 Creature* pCreature = getSelectedCreature();
1656 if(!pCreature)
1658 SendSysMessage(LANG_SELECT_CREATURE);
1659 SetSentErrorMessage(true);
1660 return false;
1663 pCreature->setFaction(factionId);
1665 // faction is set in creature_template - not inside creature
1667 // update in memory
1668 if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1670 const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1671 const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1674 // and DB
1675 WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1677 return true;
1680 //kick player
1681 bool ChatHandler::HandleKickPlayerCommand(const char *args)
1683 char* kickName = strtok((char*)args, " ");
1684 if (!kickName)
1686 Player* player = getSelectedPlayer();
1688 if(!player)
1690 SendSysMessage(LANG_NO_CHAR_SELECTED);
1691 SetSentErrorMessage(true);
1692 return false;
1695 if(player==m_session->GetPlayer())
1697 SendSysMessage(LANG_COMMAND_KICKSELF);
1698 SetSentErrorMessage(true);
1699 return false;
1702 player->GetSession()->KickPlayer();
1704 else
1706 std::string name = kickName;
1707 if(!normalizePlayerName(name))
1709 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1710 SetSentErrorMessage(true);
1711 return false;
1714 if(m_session && name==m_session->GetPlayer()->GetName())
1716 SendSysMessage(LANG_COMMAND_KICKSELF);
1717 SetSentErrorMessage(true);
1718 return false;
1721 if(sWorld.KickPlayer(name))
1723 PSendSysMessage(LANG_COMMAND_KICKMESSAGE,name.c_str());
1725 else
1726 PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,name.c_str());
1729 return true;
1732 //show info of player
1733 bool ChatHandler::HandlePInfoCommand(const char* args)
1735 Player* target = NULL;
1736 uint64 targetGUID = 0;
1738 char* px = strtok((char*)args, " ");
1739 char* py = NULL;
1741 std::string name;
1743 if (px)
1745 name = px;
1747 if(name.empty())
1748 return false;
1750 if(!normalizePlayerName(name))
1752 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1753 SetSentErrorMessage(true);
1754 return false;
1757 target = objmgr.GetPlayer(name.c_str());
1758 if (target)
1759 py = strtok(NULL, " ");
1760 else
1762 targetGUID = objmgr.GetPlayerGUIDByName(name);
1763 if(targetGUID)
1764 py = strtok(NULL, " ");
1765 else
1766 py = px;
1770 if(!target && !targetGUID)
1772 target = getSelectedPlayer();
1775 if(!target && !targetGUID)
1777 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1778 SetSentErrorMessage(true);
1779 return false;
1782 uint32 accId = 0;
1783 uint32 money = 0;
1784 uint32 total_player_time = 0;
1785 uint32 level = 0;
1786 uint32 latency = 0;
1788 // get additional information from Player object
1789 if(target)
1791 targetGUID = target->GetGUID();
1792 name = target->GetName(); // re-read for case getSelectedPlayer() target
1793 accId = target->GetSession()->GetAccountId();
1794 money = target->GetMoney();
1795 total_player_time = target->GetTotalPlayedTime();
1796 level = target->getLevel();
1797 latency = target->GetSession()->GetLatency();
1799 // get additional information from DB
1800 else
1802 accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
1803 WorldSession session(0,NULL,SEC_PLAYER,0,0,LOCALE_enUS);
1804 Player plr(&session); // use fake session for temporary load
1805 plr.MinimalLoadFromDB(NULL, targetGUID);
1806 money = plr.GetMoney();
1807 total_player_time = plr.GetTotalPlayedTime();
1808 level = plr.getLevel();
1811 std::string username = GetMangosString(LANG_ERROR);
1812 std::string last_ip = GetMangosString(LANG_ERROR);
1813 uint32 security = 0;
1814 std::string last_login = GetMangosString(LANG_ERROR);
1816 QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
1817 if(result)
1819 Field* fields = result->Fetch();
1820 username = fields[0].GetCppString();
1821 security = fields[1].GetUInt32();
1823 if(!m_session || m_session->GetSecurity() >= security)
1825 last_ip = fields[2].GetCppString();
1826 last_login = fields[3].GetCppString();
1828 else
1830 last_ip = "-";
1831 last_login = "-";
1834 delete result;
1837 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);
1839 std::string timeStr = secsToTimeString(total_player_time,true,true);
1840 uint32 gold = money /GOLD;
1841 uint32 silv = (money % GOLD) / SILVER;
1842 uint32 copp = (money % GOLD) % SILVER;
1843 PSendSysMessage(LANG_PINFO_LEVEL, timeStr.c_str(), level, gold,silv,copp );
1845 if ( py && strncmp(py, "rep", 3) == 0 )
1847 if(!target)
1849 // rep option not implemented for offline case
1850 SendSysMessage(LANG_PINFO_NO_REP);
1851 SetSentErrorMessage(true);
1852 return false;
1855 char* FactionName;
1856 for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr)
1858 FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
1859 if (factionEntry)
1860 FactionName = factionEntry->name[m_session->GetSessionDbcLocale()];
1861 else
1862 FactionName = "#Not found#";
1863 ReputationRank rank = target->GetReputationRank(factionEntry);
1864 std::string rankName = GetMangosString(ReputationRankStrIndex[rank]);
1865 std::ostringstream ss;
1866 ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << FactionName << "]|h|r " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
1868 if(itr->second.Flags & FACTION_FLAG_VISIBLE)
1869 ss << GetMangosString(LANG_FACTION_VISIBLE);
1870 if(itr->second.Flags & FACTION_FLAG_AT_WAR)
1871 ss << GetMangosString(LANG_FACTION_ATWAR);
1872 if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
1873 ss << GetMangosString(LANG_FACTION_PEACE_FORCED);
1874 if(itr->second.Flags & FACTION_FLAG_HIDDEN)
1875 ss << GetMangosString(LANG_FACTION_HIDDEN);
1876 if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
1877 ss << GetMangosString(LANG_FACTION_INVISIBLE_FORCED);
1878 if(itr->second.Flags & FACTION_FLAG_INACTIVE)
1879 ss << GetMangosString(LANG_FACTION_INACTIVE);
1881 SendSysMessage(ss.str().c_str());
1884 return true;
1887 //show tickets
1888 void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
1890 std::string name;
1891 if(!objmgr.GetPlayerNameByGUID(guid,name))
1892 name = GetMangosString(LANG_UNKNOWN);
1894 PSendSysMessage(LANG_COMMAND_TICKETVIEW, name.c_str(),time,text);
1897 //ticket commands
1898 bool ChatHandler::HandleTicketCommand(const char* args)
1900 char* px = strtok((char*)args, " ");
1902 // ticket<end>
1903 if (!px)
1905 if(!m_session)
1907 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1908 SetSentErrorMessage(true);
1909 return false;
1912 size_t count;
1913 QueryResult *result = CharacterDatabase.Query("SELECT COUNT(ticket_id) FROM character_ticket");
1914 if(result)
1916 count = (*result)[0].GetUInt32();
1917 delete result;
1919 else
1920 count = 0;
1922 bool accept = m_session->GetPlayer()->isAcceptTickets();
1924 PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF));
1925 return true;
1928 // ticket on
1929 if(strncmp(px,"on",3) == 0)
1931 if(!m_session)
1933 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1934 SetSentErrorMessage(true);
1935 return false;
1938 m_session->GetPlayer()->SetAcceptTicket(true);
1939 SendSysMessage(LANG_COMMAND_TICKETON);
1940 return true;
1943 // ticket off
1944 if(strncmp(px,"off",4) == 0)
1946 if(!m_session)
1948 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1949 SetSentErrorMessage(true);
1950 return false;
1953 m_session->GetPlayer()->SetAcceptTicket(false);
1954 SendSysMessage(LANG_COMMAND_TICKETOFF);
1955 return true;
1958 // ticket #num
1959 int num = atoi(px);
1960 if(num > 0)
1962 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
1964 if(!result)
1966 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
1967 delete result;
1968 SetSentErrorMessage(true);
1969 return false;
1972 Field* fields = result->Fetch();
1974 uint64 guid = fields[0].GetUInt64();
1975 char const* text = fields[1].GetString();
1976 char const* time = fields[2].GetString();
1978 ShowTicket(guid,text,time);
1979 delete result;
1980 return true;
1983 std::string name = px;
1985 if(!normalizePlayerName(name))
1987 SendSysMessage(LANG_PLAYER_NOT_FOUND);
1988 SetSentErrorMessage(true);
1989 return false;
1992 uint64 guid = objmgr.GetPlayerGUIDByName(name);
1994 if(!guid)
1995 return false;
1997 // ticket $char_name
1998 QueryResult *result = CharacterDatabase.PQuery("SELECT ticket_text,ticket_lastchange FROM character_ticket WHERE guid = '%u' ORDER BY ticket_id ASC",GUID_LOPART(guid));
2000 if(!result)
2001 return false;
2003 Field* fields = result->Fetch();
2005 char const* text = fields[0].GetString();
2006 char const* time = fields[1].GetString();
2008 ShowTicket(guid,text,time);
2009 delete result;
2011 return true;
2014 uint32 ChatHandler::GetTicketIDByNum(uint32 num)
2016 QueryResult *result = CharacterDatabase.Query("SELECT ticket_id FROM character_ticket");
2018 if(!result || num > result->GetRowCount())
2020 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2021 delete result;
2022 return 0;
2025 for(uint32 i = 1; i < num; ++i)
2026 result->NextRow();
2028 Field* fields = result->Fetch();
2030 uint32 id = fields[0].GetUInt32();
2031 delete result;
2032 return id;
2035 //dell all tickets
2036 bool ChatHandler::HandleDelTicketCommand(const char *args)
2038 char* px = strtok((char*)args, " ");
2039 if (!px)
2040 return false;
2042 // delticket all
2043 if(strncmp(px,"all",4) == 0)
2045 QueryResult *result = CharacterDatabase.Query("SELECT guid FROM character_ticket");
2047 if(!result)
2048 return true;
2050 // notify players about ticket deleting
2053 Field* fields = result->Fetch();
2055 uint64 guid = fields[0].GetUInt64();
2057 if(Player* sender = objmgr.GetPlayer(guid))
2058 sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2060 }while(result->NextRow());
2062 delete result;
2064 CharacterDatabase.PExecute("DELETE FROM character_ticket");
2065 SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2066 return true;
2069 int num = (uint32)atoi(px);
2071 // delticket #num
2072 if(num > 0)
2074 QueryResult *result = CharacterDatabase.PQuery("SELECT ticket_id,guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2076 if(!result)
2078 PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2079 delete result;
2080 SetSentErrorMessage(true);
2081 return false;
2084 Field* fields = result->Fetch();
2086 uint32 id = fields[0].GetUInt32();
2087 uint64 guid = fields[1].GetUInt64();
2088 delete result;
2090 CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE ticket_id = '%u'", id);
2092 // notify players about ticket deleting
2093 if(Player* sender = objmgr.GetPlayer(guid))
2095 sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2096 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,sender->GetName());
2098 else
2099 SendSysMessage(LANG_COMMAND_TICKETDEL);
2101 return true;
2104 std::string name = px;
2106 if(!normalizePlayerName(name))
2108 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2109 SetSentErrorMessage(true);
2110 return false;
2113 uint64 guid = objmgr.GetPlayerGUIDByName(name);
2115 if(!guid)
2116 return false;
2118 // delticket $char_name
2119 CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u'",GUID_LOPART(guid));
2121 // notify players about ticket deleting
2122 if(Player* sender = objmgr.GetPlayer(guid))
2123 sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2125 PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,px);
2126 return true;
2129 //set spawn dist of creature
2130 bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
2132 if(!*args)
2133 return false;
2135 float option = atof((char*)args);
2136 if (option < 0.0f)
2138 SendSysMessage(LANG_BAD_VALUE);
2139 return false;
2142 MovementGeneratorType mtype = IDLE_MOTION_TYPE;
2143 if (option >0.0f)
2144 mtype = RANDOM_MOTION_TYPE;
2146 Creature *pCreature = getSelectedCreature();
2147 uint32 u_guidlow = 0;
2149 if (pCreature)
2150 u_guidlow = pCreature->GetDBTableGUIDLow();
2151 else
2152 return false;
2154 pCreature->SetRespawnRadius((float)option);
2155 pCreature->SetDefaultMovementType(mtype);
2156 pCreature->GetMotionMaster()->Initialize();
2157 if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
2159 pCreature->setDeathState(JUST_DIED);
2160 pCreature->Respawn();
2163 WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
2164 PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
2165 return true;
2168 bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
2170 if(!*args)
2171 return false;
2173 char* stime = strtok((char*)args, " ");
2175 if (!stime)
2176 return false;
2178 int i_stime = atoi((char*)stime);
2180 if (i_stime < 0)
2182 SendSysMessage(LANG_BAD_VALUE);
2183 SetSentErrorMessage(true);
2184 return false;
2187 Creature *pCreature = getSelectedCreature();
2188 uint32 u_guidlow = 0;
2190 if (pCreature)
2191 u_guidlow = pCreature->GetDBTableGUIDLow();
2192 else
2193 return false;
2195 WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
2196 pCreature->SetRespawnDelay((uint32)i_stime);
2197 PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
2199 return true;
2203 * Add a waypoint to a creature.
2205 * The user can either select an npc or provide its GUID.
2207 * The user can even select a visual waypoint - then the new waypoint
2208 * is placed *after* the selected one - this makes insertion of new
2209 * waypoints possible.
2211 * eg:
2212 * .wp add 12345
2213 * -> adds a waypoint to the npc with the GUID 12345
2215 * .wp add
2216 * -> adds a waypoint to the currently selected creature
2219 * @param args if the user did not provide a GUID, it is NULL
2221 * @return true - command did succeed, false - something went wrong
2223 bool ChatHandler::HandleWpAddCommand(const char* args)
2225 sLog.outDebug("DEBUG: HandleWpAddCommand");
2227 // optional
2228 char* guid_str = NULL;
2230 if(*args)
2232 guid_str = strtok((char*)args, " ");
2235 uint32 lowguid = 0;
2236 uint32 point = 0;
2237 Creature* target = getSelectedCreature();
2238 // Did player provide a GUID?
2239 if (!guid_str)
2241 sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2243 // No GUID provided
2244 // -> Player must have selected a creature
2246 if(!target || target->isPet())
2248 SendSysMessage(LANG_SELECT_CREATURE);
2249 SetSentErrorMessage(true);
2250 return false;
2252 if (target->GetEntry() == VISUAL_WAYPOINT )
2254 sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2256 QueryResult *result =
2257 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2258 target->GetGUIDLow() );
2259 if(!result)
2261 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2262 // User selected a visual spawnpoint -> get the NPC
2263 // Select NPC GUID
2264 // Since we compare float values, we have to deal with
2265 // some difficulties.
2266 // Here we search for all waypoints that only differ in one from 1 thousand
2267 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2268 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2269 const char* maxDIFF = "0.01";
2270 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 )",
2271 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2272 if(!result)
2274 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2275 SetSentErrorMessage(true);
2276 return false;
2281 Field *fields = result->Fetch();
2282 lowguid = fields[0].GetUInt32();
2283 point = fields[1].GetUInt32();
2284 }while( result->NextRow() );
2285 delete result;
2287 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2288 if(!data)
2290 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2291 SetSentErrorMessage(true);
2292 return false;
2295 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2296 if(!target)
2298 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2299 SetSentErrorMessage(true);
2300 return false;
2303 else
2305 lowguid = target->GetDBTableGUIDLow();
2308 else
2310 sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2312 // GUID provided
2313 // Warn if player also selected a creature
2314 // -> Creature selection is ignored <-
2315 if(target)
2317 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2319 lowguid = atoi((char*)guid_str);
2321 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2322 if(!data)
2324 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2325 SetSentErrorMessage(true);
2326 return false;
2329 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2330 if(!target || target->isPet())
2332 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2333 SetSentErrorMessage(true);
2334 return false;
2337 // lowguid -> GUID of the NPC
2338 // point -> number of the waypoint (if not 0)
2339 sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2341 sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2343 Player* player = m_session->GetPlayer();
2344 WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2346 // update movement type
2347 if(target)
2349 target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2350 target->GetMotionMaster()->Initialize();
2351 if(target->isAlive()) // dead creature will reset movement generator at respawn
2353 target->setDeathState(JUST_DIED);
2354 target->Respawn();
2356 target->SaveToDB();
2358 else
2359 WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2361 PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2363 return true;
2364 } // HandleWpAddCommand
2367 * .wp modify emote | spell | text | del | move | add
2369 * add -> add a WP after the selected visual waypoint
2370 * User must select a visual waypoint and then issue ".wp modify add"
2372 * emote <emoteID>
2373 * User has selected a visual waypoint before.
2374 * <emoteID> is added to this waypoint. Everytime the
2375 * NPC comes to this waypoint, the emote is called.
2377 * emote <GUID> <WPNUM> <emoteID>
2378 * User has not selected visual waypoint before.
2379 * For the waypoint <WPNUM> for the NPC with <GUID>
2380 * an emote <emoteID> is added.
2381 * Everytime the NPC comes to this waypoint, the emote is called.
2384 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2386 bool ChatHandler::HandleWpModifyCommand(const char* args)
2388 sLog.outDebug("DEBUG: HandleWpModifyCommand");
2390 if(!*args)
2391 return false;
2393 // first arg: add del text emote spell waittime move
2394 char* show_str = strtok((char*)args, " ");
2395 if (!show_str)
2397 return false;
2400 std::string show = show_str;
2401 // Check
2402 // Remember: "show" must also be the name of a column!
2403 if( (show != "emote") && (show != "spell") && (show != "text1") && (show != "text2")
2404 && (show != "text3") && (show != "text4") && (show != "text5")
2405 && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2406 && (show != "model1") && (show != "model2") && (show != "orientation"))
2408 return false;
2411 // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2413 // Did user provide a GUID
2414 // or did the user select a creature?
2415 // -> variable lowguid is filled with the GUID of the NPC
2416 uint32 lowguid = 0;
2417 uint32 point = 0;
2418 uint32 wpGuid = 0;
2419 Creature* target = getSelectedCreature();
2421 if(target)
2423 sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2425 // Did the user select a visual spawnpoint?
2426 if (target->GetEntry() != VISUAL_WAYPOINT )
2428 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2429 SetSentErrorMessage(true);
2430 return false;
2433 wpGuid = target->GetGUIDLow();
2435 // The visual waypoint
2436 QueryResult *result =
2437 WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2438 target->GetGUIDLow() );
2439 if(!result)
2441 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2442 SetSentErrorMessage(true);
2443 return false;
2445 sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2447 Field *fields = result->Fetch();
2448 lowguid = fields[0].GetUInt32();
2449 point = fields[1].GetUInt32();
2451 // Cleanup memory
2452 sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2453 delete result;
2455 else
2457 // User did provide <GUID> <WPNUM>
2459 char* guid_str = strtok((char*)NULL, " ");
2460 if( !guid_str )
2462 SendSysMessage(LANG_WAYPOINT_NOGUID);
2463 return false;
2465 lowguid = atoi((char*)guid_str);
2467 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2468 if(!data)
2470 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2471 SetSentErrorMessage(true);
2472 return false;
2475 PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2477 char* point_str = strtok((char*)NULL, " ");
2478 if( !point_str )
2480 SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2481 return false;
2483 point = atoi((char*)point_str);
2485 PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2487 // Now we need the GUID of the visual waypoint
2488 // -> "del", "move", "add" command
2490 QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2491 if (!result)
2493 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2494 SetSentErrorMessage(true);
2495 return false;
2498 Field *fields = result->Fetch();
2499 wpGuid = fields[0].GetUInt32();
2501 // Free memory
2502 delete result;
2505 char* arg_str = NULL;
2506 // Check for argument
2507 if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2509 // Text is enclosed in "<>", all other arguments not
2510 if( show.find("text") != std::string::npos )
2511 arg_str = strtok((char*)NULL, "<>");
2512 else
2513 arg_str = strtok((char*)NULL, " ");
2515 if( !arg_str)
2517 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2518 return false;
2522 sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2524 // wpGuid -> GUID of the waypoint creature
2525 // lowguid -> GUID of the NPC
2526 // point -> waypoint number
2528 // Special functions:
2529 // add - move - del -> no args commands
2530 // Add a waypoint after the selected visual
2531 if(show == "add" && target)
2533 PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2535 // Get the creature for which we read the waypoint
2536 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2537 if(!data)
2539 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2540 SetSentErrorMessage(true);
2541 return false;
2544 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2546 if( !npcCreature )
2548 PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2549 SetSentErrorMessage(true);
2550 return false;
2553 sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2555 // What to do:
2556 // Add the visual spawnpoint (DB only)
2557 // Adjust the waypoints
2558 // Respawn the owner of the waypoints
2559 sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2561 Player* chr = m_session->GetPlayer();
2562 Map *map = chr->GetMap();
2564 if(npcCreature)
2566 npcCreature->GetMotionMaster()->Initialize();
2567 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2569 npcCreature->setDeathState(JUST_DIED);
2570 npcCreature->Respawn();
2574 // create the waypoint creature
2575 wpGuid = 0;
2576 Creature* wpCreature = new Creature;
2577 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map,VISUAL_WAYPOINT,0))
2579 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2580 delete wpCreature;
2582 else
2584 wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2586 if(!wpCreature->IsPositionValid())
2588 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());
2589 delete wpCreature;
2591 else
2593 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2594 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2595 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2596 map->Add(wpCreature);
2597 wpGuid = wpCreature->GetGUIDLow();
2601 WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2603 if(!wpGuid)
2604 return false;
2606 PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2607 return true;
2608 } // add
2610 if(show == "del" && target)
2612 PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2614 // Get the creature for which we read the waypoint
2615 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2616 if(!data)
2618 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2619 SetSentErrorMessage(true);
2620 return false;
2623 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2625 // wpCreature
2626 Creature* wpCreature = NULL;
2627 if( wpGuid != 0 )
2629 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2630 wpCreature->DeleteFromDB();
2631 wpCreature->CleanupsBeforeDelete();
2632 wpCreature->AddObjectToRemoveList();
2635 // What to do:
2636 // Remove the visual spawnpoint
2637 // Adjust the waypoints
2638 // Respawn the owner of the waypoints
2640 WaypointMgr.DeleteNode(lowguid, point);
2642 if(npcCreature)
2644 // Any waypoints left?
2645 QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2646 if(!result2)
2648 npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2650 else
2652 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2653 delete result2;
2655 npcCreature->GetMotionMaster()->Initialize();
2656 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2658 npcCreature->setDeathState(JUST_DIED);
2659 npcCreature->Respawn();
2661 npcCreature->SaveToDB();
2664 PSendSysMessage(LANG_WAYPOINT_REMOVED);
2665 return true;
2666 } // del
2668 if(show == "move" && target)
2670 PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2672 Player *chr = m_session->GetPlayer();
2673 Map *map = chr->GetMap();
2675 // Get the creature for which we read the waypoint
2676 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2677 if(!data)
2679 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2680 SetSentErrorMessage(true);
2681 return false;
2684 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2686 // wpCreature
2687 Creature* wpCreature = NULL;
2688 // What to do:
2689 // Move the visual spawnpoint
2690 // Respawn the owner of the waypoints
2691 if( wpGuid != 0 )
2693 wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2694 wpCreature->DeleteFromDB();
2695 wpCreature->CleanupsBeforeDelete();
2696 wpCreature->AddObjectToRemoveList();
2697 // re-create
2698 Creature* wpCreature2 = new Creature;
2699 if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0))
2701 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2702 delete wpCreature2;
2703 return false;
2706 wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2708 if(!wpCreature2->IsPositionValid())
2710 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());
2711 delete wpCreature2;
2712 return false;
2715 wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2716 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2717 wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2718 map->Add(wpCreature2);
2719 //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2);
2722 WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2724 if(npcCreature)
2726 npcCreature->GetMotionMaster()->Initialize();
2727 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2729 npcCreature->setDeathState(JUST_DIED);
2730 npcCreature->Respawn();
2733 PSendSysMessage(LANG_WAYPOINT_CHANGED);
2735 return true;
2736 } // move
2738 // Create creature - npc that has the waypoint
2739 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2740 if(!data)
2742 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2743 SetSentErrorMessage(true);
2744 return false;
2747 WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2749 Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2750 if(npcCreature)
2752 npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2753 npcCreature->GetMotionMaster()->Initialize();
2754 if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
2756 npcCreature->setDeathState(JUST_DIED);
2757 npcCreature->Respawn();
2760 PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2762 return true;
2766 * .wp show info | on | off
2768 * info -> User has selected a visual waypoint before
2770 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2771 * provided the GUID of the NPC and the number of
2772 * the waypoint.
2774 * on -> User has selected an NPC; all visual waypoints for this
2775 * NPC are added to the world
2777 * on <GUID> -> User did not select an NPC - instead the GUID of the
2778 * NPC is provided. All visual waypoints for this NPC
2779 * are added from the world.
2781 * off -> User has selected an NPC; all visual waypoints for this
2782 * NPC are removed from the world.
2784 * on <GUID> -> User did not select an NPC - instead the GUID of the
2785 * NPC is provided. All visual waypoints for this NPC
2786 * are removed from the world.
2790 bool ChatHandler::HandleWpShowCommand(const char* args)
2792 sLog.outDebug("DEBUG: HandleWpShowCommand");
2794 if(!*args)
2795 return false;
2797 // first arg: on, off, first, last
2798 char* show_str = strtok((char*)args, " ");
2799 if (!show_str)
2801 return false;
2803 // second arg: GUID (optional, if a creature is selected)
2804 char* guid_str = strtok((char*)NULL, " ");
2805 sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
2806 //if (!guid_str) {
2807 // return false;
2810 // Did user provide a GUID
2811 // or did the user select a creature?
2812 // -> variable lowguid is filled with the GUID
2813 Creature* target = getSelectedCreature();
2814 // Did player provide a GUID?
2815 if (!guid_str)
2817 sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
2818 // No GUID provided
2819 // -> Player must have selected a creature
2821 if(!target)
2823 SendSysMessage(LANG_SELECT_CREATURE);
2824 SetSentErrorMessage(true);
2825 return false;
2828 else
2830 sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
2831 // GUID provided
2832 // Warn if player also selected a creature
2833 // -> Creature selection is ignored <-
2834 if(target)
2836 SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2839 uint32 lowguid = atoi((char*)guid_str);
2841 CreatureData const* data = objmgr.GetCreatureData(lowguid);
2842 if(!data)
2844 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2845 SetSentErrorMessage(true);
2846 return false;
2849 target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2851 if(!target)
2853 PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2854 SetSentErrorMessage(true);
2855 return false;
2859 uint32 lowguid = target->GetDBTableGUIDLow();
2861 std::string show = show_str;
2862 uint32 Maxpoint;
2864 sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
2866 // Show info for the selected waypoint
2867 if(show == "info")
2869 PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
2871 // Check if the user did specify a visual waypoint
2872 if( target->GetEntry() != VISUAL_WAYPOINT )
2874 PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2875 SetSentErrorMessage(true);
2876 return false;
2879 //PSendSysMessage("wp on, GUID: %u", lowguid);
2881 //pCreature->GetPositionX();
2883 QueryResult *result =
2884 WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u",
2885 target->GetGUIDLow() );
2886 if(!result)
2888 // Since we compare float values, we have to deal with
2889 // some difficulties.
2890 // Here we search for all waypoints that only differ in one from 1 thousand
2891 // (0.001) - There is no other way to compare C++ floats with mySQL floats
2892 // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2893 const char* maxDIFF = "0.01";
2894 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
2896 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 )",
2897 target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2898 if(!result)
2900 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2901 SetSentErrorMessage(true);
2902 return false;
2907 Field *fields = result->Fetch();
2908 uint32 creGUID = fields[0].GetUInt32();
2909 uint32 point = fields[1].GetUInt32();
2910 int waittime = fields[2].GetUInt32();
2911 uint32 emote = fields[3].GetUInt32();
2912 uint32 spell = fields[4].GetUInt32();
2913 const char * text1 = fields[5].GetString();
2914 const char * text2 = fields[6].GetString();
2915 const char * text3 = fields[7].GetString();
2916 const char * text4 = fields[8].GetString();
2917 const char * text5 = fields[9].GetString();
2918 uint32 model1 = fields[10].GetUInt32();
2919 uint32 model2 = fields[11].GetUInt32();
2921 // Get the creature for which we read the waypoint
2922 Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2924 PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
2925 PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
2926 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
2927 PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
2928 PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
2929 PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
2930 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 1, text1);
2931 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 2, text2);
2932 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 3, text3);
2933 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 4, text4);
2934 PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 5, text5);
2936 }while( result->NextRow() );
2937 // Cleanup memory
2938 delete result;
2939 return true;
2942 if(show == "on")
2944 PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
2946 QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
2947 if(!result)
2949 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
2950 SetSentErrorMessage(true);
2951 return false;
2953 // Delete all visuals for this NPC
2954 QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
2955 if(result2)
2957 bool hasError = false;
2960 Field *fields = result2->Fetch();
2961 uint32 wpguid = fields[0].GetUInt32();
2962 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2964 if(!pCreature)
2966 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
2967 hasError = true;
2968 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
2970 else
2972 pCreature->DeleteFromDB();
2973 pCreature->CleanupsBeforeDelete();
2974 pCreature->AddObjectToRemoveList();
2977 }while( result2->NextRow() );
2978 delete result2;
2979 if( hasError )
2981 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
2982 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
2983 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
2989 Field *fields = result->Fetch();
2990 uint32 point = fields[0].GetUInt32();
2991 float x = fields[1].GetFloat();
2992 float y = fields[2].GetFloat();
2993 float z = fields[3].GetFloat();
2995 uint32 id = VISUAL_WAYPOINT;
2997 Player *chr = m_session->GetPlayer();
2998 Map *map = chr->GetMap();
2999 float o = chr->GetOrientation();
3001 Creature* wpCreature = new Creature;
3002 if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
3004 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3005 delete wpCreature;
3006 delete result;
3007 return false;
3010 wpCreature->Relocate(x, y, z, o);
3012 if(!wpCreature->IsPositionValid())
3014 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());
3015 delete wpCreature;
3016 delete result;
3017 return false;
3020 wpCreature->SetVisibility(VISIBILITY_OFF);
3021 sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
3022 // set "wpguid" column to the visual waypoint
3023 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
3025 wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3026 // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
3027 wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
3028 map->Add(wpCreature);
3029 //MapManager::Instance().GetMap(wpCreature->GetMapId())->Add(wpCreature);
3030 }while( result->NextRow() );
3032 // Cleanup memory
3033 delete result;
3034 return true;
3037 if(show == "first")
3039 PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3041 QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3042 if(!result)
3044 PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3045 SetSentErrorMessage(true);
3046 return false;
3049 Field *fields = result->Fetch();
3050 float x = fields[0].GetFloat();
3051 float y = fields[1].GetFloat();
3052 float z = fields[2].GetFloat();
3053 uint32 id = VISUAL_WAYPOINT;
3055 Player *chr = m_session->GetPlayer();
3056 float o = chr->GetOrientation();
3057 Map *map = chr->GetMap();
3059 Creature* pCreature = new Creature;
3060 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, id, 0))
3062 PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3063 delete pCreature;
3064 delete result;
3065 return false;
3068 pCreature->Relocate(x, y, z, o);
3070 if(!pCreature->IsPositionValid())
3072 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());
3073 delete pCreature;
3074 delete result;
3075 return false;
3078 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3079 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3080 map->Add(pCreature);
3081 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3083 // Cleanup memory
3084 delete result;
3085 return true;
3088 if(show == "last")
3090 PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3092 QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3093 if( result )
3095 Maxpoint = (*result)[0].GetUInt32();
3097 delete result;
3099 else
3100 Maxpoint = 0;
3102 result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3103 if(!result)
3105 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3106 SetSentErrorMessage(true);
3107 return false;
3109 Field *fields = result->Fetch();
3110 float x = fields[0].GetFloat();
3111 float y = fields[1].GetFloat();
3112 float z = fields[2].GetFloat();
3113 uint32 id = VISUAL_WAYPOINT;
3115 Player *chr = m_session->GetPlayer();
3116 float o = chr->GetOrientation();
3117 Map *map = chr->GetMap();
3119 Creature* pCreature = new Creature;
3120 if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
3122 PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3123 delete pCreature;
3124 delete result;
3125 return false;
3128 pCreature->Relocate(x, y, z, o);
3130 if(!pCreature->IsPositionValid())
3132 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());
3133 delete pCreature;
3134 delete result;
3135 return false;
3138 pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3139 pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3140 map->Add(pCreature);
3141 //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3142 // Cleanup memory
3143 delete result;
3144 return true;
3147 if(show == "off")
3149 QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3150 if(!result)
3152 SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3153 SetSentErrorMessage(true);
3154 return false;
3156 bool hasError = false;
3159 Field *fields = result->Fetch();
3160 uint32 guid = fields[0].GetUInt32();
3161 Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3163 //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
3165 if(!pCreature)
3167 PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3168 hasError = true;
3169 WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3171 else
3173 pCreature->DeleteFromDB();
3174 pCreature->CleanupsBeforeDelete();
3175 pCreature->AddObjectToRemoveList();
3177 }while(result->NextRow());
3178 // set "wpguid" column to "empty" - no visual waypoint spawned
3179 WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'");
3181 if( hasError )
3183 PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3184 PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3185 PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3188 SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3189 // Cleanup memory
3190 delete result;
3192 return true;
3195 PSendSysMessage("DEBUG: wpshow - no valid command found");
3197 return true;
3198 } // HandleWpShowCommand
3200 bool ChatHandler::HandleWpExportCommand(const char *args)
3202 if(!*args)
3203 return false;
3205 // Next arg is: <GUID> <ARGUMENT>
3207 // Did user provide a GUID
3208 // or did the user select a creature?
3209 // -> variable lowguid is filled with the GUID of the NPC
3210 uint32 lowguid = 0;
3211 Creature* target = getSelectedCreature();
3212 char* arg_str = NULL;
3213 if (target)
3215 if (target->GetEntry() != VISUAL_WAYPOINT)
3216 lowguid = target->GetGUIDLow();
3217 else
3219 QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3220 if (!result)
3222 PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3223 return true;
3225 Field *fields = result->Fetch();
3226 lowguid = fields[0].GetUInt32();;
3227 delete result;
3230 arg_str = strtok((char*)args, " ");
3232 else
3234 // user provided <GUID>
3235 char* guid_str = strtok((char*)args, " ");
3236 if( !guid_str )
3238 SendSysMessage(LANG_WAYPOINT_NOGUID);
3239 return false;
3241 lowguid = atoi((char*)guid_str);
3243 arg_str = strtok((char*)NULL, " ");
3246 if( !arg_str)
3248 PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3249 return false;
3252 PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3254 QueryResult *result = WorldDatabase.PQuery(
3255 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3256 "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 );
3258 if (!result)
3260 PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3261 SetSentErrorMessage(true);
3262 return false;
3265 std::ofstream outfile;
3266 outfile.open (arg_str);
3270 Field *fields = result->Fetch();
3272 outfile << "INSERT INTO creature_movement ";
3273 outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5 ) VALUES ";
3275 outfile << "( ";
3276 outfile << fields[15].GetUInt32(); // id
3277 outfile << ", ";
3278 outfile << fields[0].GetUInt32(); // point
3279 outfile << ", ";
3280 outfile << fields[1].GetFloat(); // position_x
3281 outfile << ", ";
3282 outfile << fields[2].GetFloat(); // position_y
3283 outfile << ", ";
3284 outfile << fields[3].GetUInt32(); // position_z
3285 outfile << ", ";
3286 outfile << fields[4].GetUInt32(); // orientation
3287 outfile << ", ";
3288 outfile << fields[5].GetUInt32(); // model1
3289 outfile << ", ";
3290 outfile << fields[6].GetUInt32(); // model2
3291 outfile << ", ";
3292 outfile << fields[7].GetUInt16(); // waittime
3293 outfile << ", ";
3294 outfile << fields[8].GetUInt32(); // emote
3295 outfile << ", ";
3296 outfile << fields[9].GetUInt32(); // spell
3297 outfile << ", ";
3298 const char *tmpChar = fields[10].GetString();
3299 if( !tmpChar )
3301 outfile << "NULL"; // text1
3303 else
3305 outfile << "'";
3306 outfile << tmpChar; // text1
3307 outfile << "'";
3309 outfile << ", ";
3310 tmpChar = fields[11].GetString();
3311 if( !tmpChar )
3313 outfile << "NULL"; // text2
3315 else
3317 outfile << "'";
3318 outfile << tmpChar; // text2
3319 outfile << "'";
3321 outfile << ", ";
3322 tmpChar = fields[12].GetString();
3323 if( !tmpChar )
3325 outfile << "NULL"; // text3
3327 else
3329 outfile << "'";
3330 outfile << tmpChar; // text3
3331 outfile << "'";
3333 outfile << ", ";
3334 tmpChar = fields[13].GetString();
3335 if( !tmpChar )
3337 outfile << "NULL"; // text4
3339 else
3341 outfile << "'";
3342 outfile << tmpChar; // text4
3343 outfile << "'";
3345 outfile << ", ";
3346 tmpChar = fields[14].GetString();
3347 if( !tmpChar )
3349 outfile << "NULL"; // text5
3351 else
3353 outfile << "'";
3354 outfile << tmpChar; // text5
3355 outfile << "'";
3357 outfile << ");\n ";
3359 } while( result->NextRow() );
3360 delete result;
3362 PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3363 outfile.close();
3365 return true;
3368 bool ChatHandler::HandleWpImportCommand(const char *args)
3370 if(!*args)
3371 return false;
3373 char* arg_str = strtok((char*)args, " ");
3374 if (!arg_str)
3375 return false;
3377 std::string line;
3378 std::ifstream infile (arg_str);
3379 if (infile.is_open())
3381 while (! infile.eof() )
3383 getline (infile,line);
3384 //cout << line << endl;
3385 QueryResult *result = WorldDatabase.PQuery(line.c_str());
3386 delete result;
3388 infile.close();
3390 PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3392 return true;
3395 //rename characters
3396 bool ChatHandler::HandleRenameCommand(const char* args)
3398 Player* target = NULL;
3399 uint64 targetGUID = 0;
3400 std::string oldname;
3402 char* px = strtok((char*)args, " ");
3404 if(px)
3406 oldname = px;
3408 if(!normalizePlayerName(oldname))
3410 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3411 SetSentErrorMessage(true);
3412 return false;
3415 target = objmgr.GetPlayer(oldname.c_str());
3417 if (!target)
3418 targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3421 if(!target && !targetGUID)
3423 target = getSelectedPlayer();
3426 if(!target && !targetGUID)
3428 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3429 SetSentErrorMessage(true);
3430 return false;
3433 if(target)
3435 PSendSysMessage(LANG_RENAME_PLAYER, target->GetName());
3436 target->SetAtLoginFlag(AT_LOGIN_RENAME);
3437 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3439 else
3441 PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
3442 CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3445 return true;
3448 //spawn go
3449 bool ChatHandler::HandleGameObjectCommand(const char* args)
3451 if (!*args)
3452 return false;
3454 char* pParam1 = strtok((char*)args, " ");
3455 if (!pParam1)
3456 return false;
3458 uint32 id = atoi((char*)pParam1);
3459 if(!id)
3460 return false;
3462 char* spawntimeSecs = strtok(NULL, " ");
3464 const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id);
3466 if (!goI)
3468 PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
3469 SetSentErrorMessage(true);
3470 return false;
3473 Player *chr = m_session->GetPlayer();
3474 float x = float(chr->GetPositionX());
3475 float y = float(chr->GetPositionY());
3476 float z = float(chr->GetPositionZ());
3477 float o = float(chr->GetOrientation());
3478 Map *map = chr->GetMap();
3480 float rot2 = sin(o/2);
3481 float rot3 = cos(o/2);
3483 GameObject* pGameObj = new GameObject;
3484 uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
3486 if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1))
3488 delete pGameObj;
3489 return false;
3492 if( spawntimeSecs )
3494 uint32 value = atoi((char*)spawntimeSecs);
3495 pGameObj->SetRespawnTime(value);
3496 //sLog.outDebug("*** spawntimeSecs: %d", value);
3499 // fill the gameobject data and save to the db
3500 pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3502 // this will generate a new guid if the object is in an instance
3503 if(!pGameObj->LoadFromDB(db_lowGUID, map))
3505 delete pGameObj;
3506 return false;
3509 sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o);
3511 map->Add(pGameObj);
3513 // TODO: is it really necessary to add both the real and DB table guid here ?
3514 objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
3516 PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z);
3517 return true;
3520 //show animation
3521 bool ChatHandler::HandleAnimCommand(const char* args)
3523 if (!*args)
3524 return false;
3526 uint32 anim_id = atoi((char*)args);
3527 m_session->GetPlayer()->HandleEmoteCommand(anim_id);
3528 return true;
3531 //change standstate
3532 bool ChatHandler::HandleStandStateCommand(const char* args)
3534 if (!*args)
3535 return false;
3537 uint32 anim_id = atoi((char*)args);
3538 m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3540 return true;
3543 bool ChatHandler::HandleAddHonorCommand(const char* args)
3545 if (!*args)
3546 return false;
3548 Player *target = getSelectedPlayer();
3549 if(!target)
3551 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3552 SetSentErrorMessage(true);
3553 return false;
3556 uint32 amount = (uint32)atoi(args);
3557 target->RewardHonor(NULL, 1, amount);
3558 return true;
3561 bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3563 Unit *target = getSelectedUnit();
3564 if(!target)
3566 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3567 SetSentErrorMessage(true);
3568 return false;
3571 m_session->GetPlayer()->RewardHonor(target, 1);
3572 return true;
3575 bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/)
3577 Player *target = getSelectedPlayer();
3578 if(!target)
3580 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3581 SetSentErrorMessage(true);
3582 return false;
3585 target->UpdateHonorFields();
3586 return true;
3589 bool ChatHandler::HandleLookupEventCommand(const char* args)
3591 if(!*args)
3592 return false;
3594 std::string namepart = args;
3595 std::wstring wnamepart;
3597 // converting string that we try to find to lower case
3598 if(!Utf8toWStr(namepart,wnamepart))
3599 return false;
3601 wstrToLower(wnamepart);
3603 uint32 counter = 0;
3605 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3606 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3608 for(uint32 id = 0; id < events.size(); ++id )
3610 GameEventData const& eventData = events[id];
3612 std::string descr = eventData.description;
3613 if(descr.empty())
3614 continue;
3616 if (Utf8FitTo(descr, wnamepart))
3618 char const* active = activeEvents.find(id) != activeEvents.end() ? GetMangosString(LANG_ACTIVE) : "";
3620 if(m_session)
3621 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3622 else
3623 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3625 ++counter;
3629 if (counter==0)
3630 SendSysMessage(LANG_NOEVENTFOUND);
3632 return true;
3635 bool ChatHandler::HandleEventActiveListCommand(const char* args)
3637 uint32 counter = 0;
3639 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3640 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3642 char const* active = GetMangosString(LANG_ACTIVE);
3644 for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
3646 uint32 event_id = *itr;
3647 GameEventData const& eventData = events[event_id];
3649 if(m_session)
3650 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
3651 else
3652 PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
3654 ++counter;
3657 if (counter==0)
3658 SendSysMessage(LANG_NOEVENTFOUND);
3660 return true;
3663 bool ChatHandler::HandleEventInfoCommand(const char* args)
3665 if(!*args)
3666 return false;
3668 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3669 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3670 if(!cId)
3671 return false;
3673 uint32 event_id = atoi(cId);
3675 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3677 if(event_id >=events.size())
3679 SendSysMessage(LANG_EVENT_NOT_EXIST);
3680 SetSentErrorMessage(true);
3681 return false;
3684 GameEventData const& eventData = events[event_id];
3685 if(!eventData.isValid())
3687 SendSysMessage(LANG_EVENT_NOT_EXIST);
3688 SetSentErrorMessage(true);
3689 return false;
3692 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3693 bool active = activeEvents.find(event_id) != activeEvents.end();
3694 char const* activeStr = active ? GetMangosString(LANG_ACTIVE) : "";
3696 std::string startTimeStr = TimeToTimestampStr(eventData.start);
3697 std::string endTimeStr = TimeToTimestampStr(eventData.end);
3699 uint32 delay = gameeventmgr.NextCheck(event_id);
3700 time_t nextTime = time(NULL)+delay;
3701 std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3703 std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3704 std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3706 PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3707 startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3708 nextStr.c_str());
3709 return true;
3712 bool ChatHandler::HandleEventStartCommand(const char* args)
3714 if(!*args)
3715 return false;
3717 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3718 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3719 if(!cId)
3720 return false;
3722 int32 event_id = atoi(cId);
3724 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3726 if(event_id < 1 || event_id >=events.size())
3728 SendSysMessage(LANG_EVENT_NOT_EXIST);
3729 SetSentErrorMessage(true);
3730 return false;
3733 GameEventData const& eventData = events[event_id];
3734 if(!eventData.isValid())
3736 SendSysMessage(LANG_EVENT_NOT_EXIST);
3737 SetSentErrorMessage(true);
3738 return false;
3741 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3742 if(activeEvents.find(event_id) != activeEvents.end())
3744 PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3745 SetSentErrorMessage(true);
3746 return false;
3749 gameeventmgr.StartEvent(event_id,true);
3750 return true;
3753 bool ChatHandler::HandleEventStopCommand(const char* args)
3755 if(!*args)
3756 return false;
3758 // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3759 char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3760 if(!cId)
3761 return false;
3763 int32 event_id = atoi(cId);
3765 GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3767 if(event_id < 1 || event_id >=events.size())
3769 SendSysMessage(LANG_EVENT_NOT_EXIST);
3770 SetSentErrorMessage(true);
3771 return false;
3774 GameEventData const& eventData = events[event_id];
3775 if(!eventData.isValid())
3777 SendSysMessage(LANG_EVENT_NOT_EXIST);
3778 SetSentErrorMessage(true);
3779 return false;
3782 GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3784 if(activeEvents.find(event_id) == activeEvents.end())
3786 PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3787 SetSentErrorMessage(true);
3788 return false;
3791 gameeventmgr.StopEvent(event_id,true);
3792 return true;
3795 bool ChatHandler::HandleCombatStopCommand(const char* args)
3797 Player *player;
3799 if(*args)
3801 std::string playername = args;
3803 if(!normalizePlayerName(playername))
3805 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3806 SetSentErrorMessage(true);
3807 return false;
3810 player = objmgr.GetPlayer(playername.c_str());
3812 if(!player)
3814 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3815 SetSentErrorMessage(true);
3816 return false;
3819 else
3821 player = getSelectedPlayer();
3823 if (!player)
3824 player = m_session->GetPlayer();
3827 player->CombatStop();
3828 player->getHostilRefManager().deleteReferences();
3829 return true;
3832 bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3834 uint32 classmask = m_session->GetPlayer()->getClassMask();
3836 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3838 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3839 if( !skillInfo )
3840 continue;
3842 if( skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY )
3844 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3846 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3847 if( !skillLine )
3848 continue;
3850 // skip racial skills
3851 if( skillLine->racemask != 0 )
3852 continue;
3854 // skip wrong class skills
3855 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3856 continue;
3858 if( skillLine->skillId != i || skillLine->forward_spellid )
3859 continue;
3861 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3862 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3863 continue;
3865 m_session->GetPlayer()->learnSpell(skillLine->spellId);
3870 SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
3871 return true;
3874 bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
3876 // Learns all recipes of specified profession and sets skill to max
3877 // Example: .learn all_recipes enchanting
3879 Player* target = getSelectedPlayer();
3880 if( !target )
3882 SendSysMessage(LANG_PLAYER_NOT_FOUND);
3883 return false;
3886 if(!*args)
3887 return false;
3889 std::wstring wnamepart;
3891 if(!Utf8toWStr(args,wnamepart))
3892 return false;
3894 uint32 counter = 0; // Counter for figure out that we found smth.
3896 // converting string that we try to find to lower case
3897 wstrToLower( wnamepart );
3899 uint32 classmask = m_session->GetPlayer()->getClassMask();
3901 for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3903 SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3904 if( !skillInfo )
3905 continue;
3907 if( skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
3908 skillInfo->categoryId != SKILL_CATEGORY_SECONDARY )
3909 continue;
3911 int loc = m_session->GetSessionDbcLocale();
3912 std::string name = skillInfo->name[loc];
3914 if(Utf8FitTo(name, wnamepart))
3916 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3918 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3919 if( !skillLine )
3920 continue;
3922 if( skillLine->skillId != i || skillLine->forward_spellid )
3923 continue;
3925 // skip racial skills
3926 if( skillLine->racemask != 0 )
3927 continue;
3929 // skip wrong class skills
3930 if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3931 continue;
3933 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3934 if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3935 continue;
3937 if( !target->HasSpell(spellInfo->Id) )
3938 m_session->GetPlayer()->learnSpell(skillLine->spellId);
3941 uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
3942 target->SetSkill(skillInfo->id, maxLevel, maxLevel);
3943 PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
3944 return true;
3948 return false;
3951 bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
3954 if (!*args)
3955 return false;
3957 std::string ip = strtok ((char*)args, " ");
3958 char* limit_str = strtok (NULL, " ");
3959 int32 limit = limit_str ? atoi (limit_str) : -1;
3961 loginDatabase.escape_string (ip);
3963 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
3965 return LookupPlayerSearchCommand (result,limit);
3968 bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
3970 if (!*args)
3971 return false;
3973 std::string account = strtok ((char*)args, " ");
3974 char* limit_str = strtok (NULL, " ");
3975 int32 limit = limit_str ? atoi (limit_str) : -1;
3977 if (!AccountMgr::normilizeString (account))
3978 return false;
3980 loginDatabase.escape_string (account);
3982 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
3984 return LookupPlayerSearchCommand (result,limit);
3987 bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
3990 if (!*args)
3991 return false;
3993 std::string email = strtok ((char*)args, " ");
3994 char* limit_str = strtok (NULL, " ");
3995 int32 limit = limit_str ? atoi (limit_str) : -1;
3997 loginDatabase.escape_string (email);
3999 QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
4001 return LookupPlayerSearchCommand (result,limit);
4004 bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
4006 if(!result)
4008 PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4009 SetSentErrorMessage(true);
4010 return false;
4013 int i =0;
4016 Field* fields = result->Fetch();
4017 uint32 acc_id = fields[0].GetUInt32();
4018 std::string acc_name = fields[1].GetCppString();
4020 QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
4021 if(chars)
4023 PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4025 uint64 guid = 0;
4026 std::string name;
4030 Field* charfields = chars->Fetch();
4031 guid = charfields[0].GetUInt64();
4032 name = charfields[1].GetCppString();
4034 PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
4035 ++i;
4037 } while( chars->NextRow() && ( limit == -1 || i < limit ) );
4039 delete chars;
4041 } while(result->NextRow());
4043 delete result;
4045 return true;
4048 /// Triggering corpses expire check in world
4049 bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4051 CorpsesErase();
4052 return true;
4055 bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
4057 Player *target = getSelectedPlayer();
4059 if(!target)
4061 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4062 SetSentErrorMessage(true);
4063 return false;
4066 // Repair items
4067 target->DurabilityRepairAll(false, 0, false);
4069 PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName());
4070 if(needReportToTarget(target))
4071 ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName());
4072 return true;
4075 bool ChatHandler::HandleWaterwalkCommand(const char* args)
4077 if(!*args)
4078 return false;
4080 Player *player = getSelectedPlayer();
4082 if(!player)
4084 PSendSysMessage(LANG_NO_CHAR_SELECTED);
4085 SetSentErrorMessage(true);
4086 return false;
4089 if (strncmp(args, "on", 3) == 0)
4090 player->SetMovement(MOVE_WATER_WALK); // ON
4091 else if (strncmp(args, "off", 4) == 0)
4092 player->SetMovement(MOVE_LAND_WALK); // OFF
4093 else
4095 SendSysMessage(LANG_USE_BOL);
4096 return false;
4099 PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
4100 if(needReportToTarget(player))
4101 ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
4102 return true;
4105 bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
4107 Player *player = m_session->GetPlayer();
4108 Creature *creature = getSelectedCreature();
4110 if(!creature)
4112 PSendSysMessage(LANG_SELECT_CREATURE);
4113 SetSentErrorMessage(true);
4114 return false;
4117 // Follow player - Using pet's default dist and angle
4118 creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
4120 PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
4121 return true;
4124 bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
4126 Player *player = m_session->GetPlayer();
4127 Creature *creature = getSelectedCreature();
4129 if(!creature)
4131 PSendSysMessage(LANG_SELECT_CREATURE);
4132 SetSentErrorMessage(true);
4133 return false;
4136 if (creature->GetMotionMaster()->empty() ||
4137 creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
4139 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4140 SetSentErrorMessage(true);
4141 return false;
4144 TargetedMovementGenerator<Creature> const* mgen
4145 = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
4147 if(mgen->GetTarget()!=player)
4149 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4150 SetSentErrorMessage(true);
4151 return false;
4154 // reset movement
4155 creature->GetMotionMaster()->MovementExpired(true);
4157 PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
4158 return true;
4161 bool ChatHandler::HandleNpcTameCommand(const char* args)
4163 Creature *creatureTarget = getSelectedCreature ();
4164 if (!creatureTarget || creatureTarget->isPet ())
4166 PSendSysMessage (LANG_SELECT_CREATURE);
4167 SetSentErrorMessage (true);
4168 return false;
4171 Player *player = m_session->GetPlayer ();
4173 if(player->GetPetGUID ())
4175 SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
4176 SetSentErrorMessage (true);
4177 return false;
4180 CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
4182 if (!cInfo->isTameable ())
4184 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4185 SetSentErrorMessage (true);
4186 return false;
4189 // Everything looks OK, create new pet
4190 Pet* pet = player->CreateTamedPetFrom (creatureTarget);
4191 if (!pet)
4193 PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
4194 SetSentErrorMessage (true);
4195 return false;
4198 // place pet before player
4199 float x,y,z;
4200 player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
4201 pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
4203 // set pet to defensive mode by default (some classes can't control contolled pets in fact).
4204 pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4206 // prepare visual effect for levelup
4207 pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
4209 // add to world
4210 MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
4212 // visual effect for levelup
4213 pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
4215 // caster have pet now
4216 player->SetPet(pet);
4218 pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4219 player->PetSpellInitialize();
4221 return true;