root/trunk/src/game/Level2.cpp @ 139

Revision 132, 121.5 kB (checked in by yumileroy, 17 years ago)

[svn] * Added npc follow, waterwalk, repairitems commands. Patch by dythzer
* Prevent adding more than 5 people to raid - Apoc
* fixed typo from one of our previous commits.
* Fixed two strings in core, thanx to warhead for patch.

Original author: KingPin?
Date: 2008-10-29 17:09:32-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "Common.h"
22#include "Database/DatabaseEnv.h"
23#include "WorldPacket.h"
24#include "WorldSession.h"
25#include "World.h"
26#include "ObjectMgr.h"
27#include "Player.h"
28#include "Item.h"
29#include "GameObject.h"
30#include "Opcodes.h"
31#include "Chat.h"
32#include "ObjectAccessor.h"
33#include "MapManager.h"
34#include "Language.h"
35#include "World.h"
36#include "GameEvent.h"
37#include "SpellMgr.h"
38#include "AccountMgr.h"
39#include "WaypointManager.h"
40#include "Util.h"
41#include <cctype>
42#include <iostream>
43#include <fstream>
44#include <map>
45#include "GlobalEvents.h"
46
47#include "TargetedMovementGenerator.h"                      // for HandleNpcUnFollowCommand
48
49static uint32 ReputationRankStrIndex[MAX_REPUTATION_RANK] =
50{
51    LANG_REP_HATED,    LANG_REP_HOSTILE, LANG_REP_UNFRIENDLY, LANG_REP_NEUTRAL,
52    LANG_REP_FRIENDLY, LANG_REP_HONORED, LANG_REP_REVERED,    LANG_REP_EXALTED
53};
54
55//mute player for some times
56bool ChatHandler::HandleMuteCommand(const char* args)
57{
58    if (!*args)
59        return false;
60
61    char *charname = strtok((char*)args, " ");
62    if (!charname)
63        return false;
64
65    std::string cname = charname;
66
67    char *timetonotspeak = strtok(NULL, " ");
68    if(!timetonotspeak)
69        return false;
70
71    uint32 notspeaktime = (uint32) atoi(timetonotspeak);
72
73    if(!normalizePlayerName(cname))
74    {
75        SendSysMessage(LANG_PLAYER_NOT_FOUND);
76        SetSentErrorMessage(true);
77        return false;
78    }
79
80    uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
81    if(!guid)
82    {
83        SendSysMessage(LANG_PLAYER_NOT_FOUND);
84        SetSentErrorMessage(true);
85        return false;
86    }
87
88    Player *chr = objmgr.GetPlayer(guid);
89
90    // check security
91    uint32 account_id = 0;
92    uint32 security = 0;
93
94    if (chr)
95    {
96        account_id = chr->GetSession()->GetAccountId();
97        security = chr->GetSession()->GetSecurity();
98    }
99    else
100    {
101        account_id = objmgr.GetPlayerAccountIdByGUID(guid);
102        security = accmgr.GetSecurity(account_id);
103    }
104
105    if(m_session && security >= m_session->GetSecurity())
106    {
107        SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
108        SetSentErrorMessage(true);
109        return false;
110    }
111
112    time_t mutetime = time(NULL) + notspeaktime*60;
113
114    if (chr)
115        chr->GetSession()->m_muteTime = mutetime;
116
117    loginDatabase.PExecute("UPDATE account SET mutetime = " I64FMTD " WHERE id = '%u'",uint64(mutetime), account_id );
118
119    if(chr)
120        ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime);
121
122    PSendSysMessage(LANG_YOU_DISABLE_CHAT, cname.c_str(), notspeaktime);
123
124    return true;
125}
126
127//unmute player
128bool ChatHandler::HandleUnmuteCommand(const char* args)
129{
130    if (!*args)
131        return false;
132
133    char *charname = strtok((char*)args, " ");
134    if (!charname)
135        return false;
136
137    std::string cname = charname;
138
139    if(!normalizePlayerName(cname))
140    {
141        SendSysMessage(LANG_PLAYER_NOT_FOUND);
142        SetSentErrorMessage(true);
143        return false;
144    }
145
146    uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str());
147    if(!guid)
148    {
149        SendSysMessage(LANG_PLAYER_NOT_FOUND);
150        SetSentErrorMessage(true);
151        return false;
152    }
153
154    Player *chr = objmgr.GetPlayer(guid);
155
156    // check security
157    uint32 account_id = 0;
158    uint32 security = 0;
159
160    if (chr)
161    {
162        account_id = chr->GetSession()->GetAccountId();
163        security = chr->GetSession()->GetSecurity();
164    }
165    else
166    {
167        account_id = objmgr.GetPlayerAccountIdByGUID(guid);
168        security = accmgr.GetSecurity(account_id);
169    }
170
171    if(m_session && security >= m_session->GetSecurity())
172    {
173        SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
174        SetSentErrorMessage(true);
175        return false;
176    }
177
178    if (chr)
179    {
180        if(chr->CanSpeak())
181        {
182            SendSysMessage(LANG_CHAT_ALREADY_ENABLED);
183            SetSentErrorMessage(true);
184            return false;
185        }
186
187        chr->GetSession()->m_muteTime = 0;
188    }
189
190    loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id );
191
192    if(chr)
193        ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED);
194
195    PSendSysMessage(LANG_YOU_ENABLE_CHAT, cname.c_str());
196    return true;
197}
198
199bool ChatHandler::HandleTargetObjectCommand(const char* args)
200{
201    Player* pl = m_session->GetPlayer();
202    QueryResult *result;
203    GameEvent::ActiveEvents const& activeEventsList = gameeventmgr.GetActiveEventList();
204    if(*args)
205    {
206        int32 id = atoi((char*)args);
207        if(id)
208            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",
209                pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),id);
210        else
211        {
212            std::string name = args;
213            WorldDatabase.escape_string(name);
214            result = WorldDatabase.PQuery(
215                "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_ "
216                "FROM gameobject,gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" ORDER BY order_ ASC LIMIT 1",
217                pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(),name.c_str());
218        }
219    }
220    else
221    {
222        std::ostringstream eventFilter;
223        eventFilter << " AND (event IS NULL ";
224        bool initString = true;
225
226        for (GameEvent::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
227        {
228            if (initString)
229            {
230                eventFilter  <<  "OR event IN (" <<*itr;
231                initString =false;
232            }
233            else
234                eventFilter << "," << *itr;
235        }
236
237        if (!initString)
238            eventFilter << "))";
239        else
240            eventFilter << ")";
241
242        result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, "
243            "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject "
244            "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 1",
245            m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(),eventFilter.str().c_str());
246    }
247
248    if (!result)
249    {
250        SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND);
251        return true;
252    }
253
254    Field *fields = result->Fetch();
255    uint32 lowguid = fields[0].GetUInt32();
256    uint32 id = fields[1].GetUInt32();
257    float x = fields[2].GetFloat();
258    float y = fields[3].GetFloat();
259    float z = fields[4].GetFloat();
260    float o = fields[5].GetFloat();
261    int mapid = fields[6].GetUInt16();
262    delete result;
263
264    GameObjectInfo const* goI = objmgr.GetGameObjectInfo(id);
265
266    if (!goI)
267    {
268        PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
269        return false;
270    }
271
272    GameObject* target = ObjectAccessor::GetGameObject(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,id,HIGHGUID_GAMEOBJECT));
273
274    PSendSysMessage(LANG_GAMEOBJECT_DETAIL, lowguid, goI->name, lowguid, id, x, y, z, mapid, o);
275
276    if(target)
277    {
278        int32 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL);
279        if(curRespawnDelay < 0)
280            curRespawnDelay = 0;
281
282        std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay,true);
283        std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(),true);
284
285        PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(),curRespawnDelayStr.c_str());
286    }
287    return true;
288}
289
290//teleport to gameobject
291bool ChatHandler::HandleGoObjectCommand(const char* args)
292{
293    if(!*args)
294        return false;
295
296    Player* _player = m_session->GetPlayer();
297
298    // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
299    char* cId = extractKeyFromLink((char*)args,"Hgameobject");
300    if(!cId)
301        return false;
302
303    int32 guid = atoi(cId);
304    if(!guid)
305        return false;
306
307    float x, y, z, ort;
308    int mapid;
309
310    // by DB guid
311    if (GameObjectData const* go_data = objmgr.GetGOData(guid))
312    {
313        x = go_data->posX;
314        y = go_data->posY;
315        z = go_data->posZ;
316        ort = go_data->orientation;
317        mapid = go_data->mapid;
318    }
319    else
320    {
321        SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND);
322        SetSentErrorMessage(true);
323        return false;
324    }
325
326    if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
327    {
328        PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
329        SetSentErrorMessage(true);
330        return false;
331    }
332
333    // stop flight if need
334    if(_player->isInFlight())
335    {
336        _player->GetMotionMaster()->MovementExpired();
337        _player->m_taxi.ClearTaxiDestinations();
338    }
339    // save only in non-flight case
340    else
341        _player->SaveRecallPosition();
342
343    _player->TeleportTo(mapid, x, y, z, ort);
344    return true;
345}
346
347bool ChatHandler::HandleGoTriggerCommand(const char* args)
348{
349    Player* _player = m_session->GetPlayer();
350
351    if (!*args)
352        return false;
353
354    char *atId = strtok((char*)args, " ");
355    if (!atId)
356        return false;
357
358    int32 i_atId = atoi(atId);
359
360    if(!i_atId)
361        return false;
362
363    AreaTriggerEntry const* at = sAreaTriggerStore.LookupEntry(i_atId);
364    if (!at)
365    {
366        PSendSysMessage(LANG_COMMAND_GOAREATRNOTFOUND,i_atId);
367        SetSentErrorMessage(true);
368        return false;
369    }
370
371    if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z))
372    {
373        PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->mapid);
374        SetSentErrorMessage(true);
375        return false;
376    }
377
378    // stop flight if need
379    if(_player->isInFlight())
380    {
381        _player->GetMotionMaster()->MovementExpired();
382        _player->m_taxi.ClearTaxiDestinations();
383    }
384    // save only in non-flight case
385    else
386        _player->SaveRecallPosition();
387
388    _player->TeleportTo(at->mapid, at->x, at->y, at->z, _player->GetOrientation());
389    return true;
390}
391
392bool ChatHandler::HandleGoGraveyardCommand(const char* args)
393{
394    Player* _player = m_session->GetPlayer();
395
396    if (!*args)
397        return false;
398
399    char *gyId = strtok((char*)args, " ");
400    if (!gyId)
401        return false;
402
403    int32 i_gyId = atoi(gyId);
404
405    if(!i_gyId)
406        return false;
407
408    WorldSafeLocsEntry const* gy = sWorldSafeLocsStore.LookupEntry(i_gyId);
409    if (!gy)
410    {
411        PSendSysMessage(LANG_COMMAND_GRAVEYARDNOEXIST,i_gyId);
412        SetSentErrorMessage(true);
413        return false;
414    }
415
416    if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z))
417    {
418        PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->map_id);
419        SetSentErrorMessage(true);
420        return false;
421    }
422
423    // stop flight if need
424    if(_player->isInFlight())
425    {
426        _player->GetMotionMaster()->MovementExpired();
427        _player->m_taxi.ClearTaxiDestinations();
428    }
429    // save only in non-flight case
430    else
431        _player->SaveRecallPosition();
432
433    _player->TeleportTo(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation());
434    return true;
435}
436
437/** \brief Teleport the GM to the specified creature
438 *
439 * .gocreature <GUID>      --> TP using creature.guid
440 * .gocreature azuregos    --> TP player to the mob with this name
441 *                             Warning: If there is more than one mob with this name
442 *                                      you will be teleported to the first one that is found.
443 * .gocreature id 6109     --> TP player to the mob, that has this creature_template.entry
444 *                             Warning: If there is more than one mob with this "id"
445 *                                      you will be teleported to the first one that is found.
446 */
447//teleport to creature
448bool ChatHandler::HandleGoCreatureCommand(const char* args)
449{
450    if(!*args)
451        return false;
452    Player* _player = m_session->GetPlayer();
453
454    // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
455    char* pParam1 = extractKeyFromLink((char*)args,"Hcreature");
456    if (!pParam1)
457        return false;
458
459    std::ostringstream whereClause;
460
461    // User wants to teleport to the NPC's template entry
462    if( strcmp(pParam1, "id") == 0 )
463    {
464        //sLog.outError("DEBUG: ID found");
465
466        // Get the "creature_template.entry"
467        // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r
468        char* tail = strtok(NULL,"");
469        if(!tail)
470            return false;
471        char* cId = extractKeyFromLink(tail,"Hcreature_entry");
472        if(!cId)
473            return false;
474
475        int32 tEntry = atoi(cId);
476        //sLog.outError("DEBUG: ID value: %d", tEntry);
477        if(!tEntry)
478            return false;
479
480        whereClause << "WHERE id = '" << tEntry << "'";
481    }
482    else
483    {
484        //sLog.outError("DEBUG: ID *not found*");
485
486        int32 guid = atoi(pParam1);
487
488        // Number is invalid - maybe the user specified the mob's name
489        if(!guid)
490        {
491            std::string name = pParam1;
492            WorldDatabase.escape_string(name);
493            whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'";
494        }
495        else
496        {
497            whereClause <<  "WHERE guid = '" << guid << "'";
498        }
499    }
500    //sLog.outError("DEBUG: %s", whereClause.c_str());
501
502    QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() );
503    if (!result)
504    {
505        SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND);
506        SetSentErrorMessage(true);
507        return false;
508    }
509    if( result->GetRowCount() > 1 )
510    {
511        SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE);
512    }
513
514    Field *fields = result->Fetch();
515    float x = fields[0].GetFloat();
516    float y = fields[1].GetFloat();
517    float z = fields[2].GetFloat();
518    float ort = fields[3].GetFloat();
519    int mapid = fields[4].GetUInt16();
520
521    delete result;
522
523    if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort))
524    {
525        PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
526        SetSentErrorMessage(true);
527        return false;
528    }
529
530    // stop flight if need
531    if(_player->isInFlight())
532    {
533        _player->GetMotionMaster()->MovementExpired();
534        _player->m_taxi.ClearTaxiDestinations();
535    }
536    // save only in non-flight case
537    else
538        _player->SaveRecallPosition();
539
540    _player->TeleportTo(mapid, x, y, z, ort);
541    return true;
542}
543
544bool ChatHandler::HandleGUIDCommand(const char* /*args*/)
545{
546    uint64 guid = m_session->GetPlayer()->GetSelection();
547
548    if (guid == 0)
549    {
550        SendSysMessage(LANG_NO_SELECTION);
551        SetSentErrorMessage(true);
552        return false;
553    }
554
555    PSendSysMessage(LANG_OBJECT_GUID, GUID_LOPART(guid), GUID_HIPART(guid));
556    return true;
557}
558
559bool ChatHandler::HandleLookupFactionCommand(const char* args)
560{
561    if (!*args)
562        return false;
563
564    // Can be NULL at console call
565        Player *target = getSelectedPlayer ();
566
567    std::string namepart = args;
568    std::wstring wnamepart;
569
570    if (!Utf8toWStr (namepart,wnamepart))
571        return false;
572
573    // converting string that we try to find to lower case
574    wstrToLower (wnamepart);
575
576    uint32 counter = 0;                                     // Counter for figure out that we found smth.
577
578    for (uint32 id = 0; id < sFactionStore.GetNumRows(); ++id)
579    {
580        FactionEntry const *factionEntry = sFactionStore.LookupEntry (id);
581        if (factionEntry)
582        {
583            FactionState const* repState = NULL;
584                        if(target)
585                        {
586                                FactionStateList::const_iterator repItr = target->m_factions.find (factionEntry->reputationListID);
587                                if(repItr != target->m_factions.end())
588                                        repState = &repItr->second;
589                        }
590
591            int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale();
592            std::string name = factionEntry->name[loc];
593            if(name.empty())
594                continue;
595
596            if (!Utf8FitTo(name, wnamepart))
597            {
598                loc = 0;
599                for(; loc < MAX_LOCALE; ++loc)
600                {
601                    if(m_session && loc==m_session->GetSessionDbcLocale())
602                        continue;
603
604                    name = factionEntry->name[loc];
605                    if(name.empty())
606                        continue;
607
608                    if (Utf8FitTo(name, wnamepart))
609                        break;
610                }
611            }
612
613            if(loc < MAX_LOCALE)
614            {
615                // send faction in "id - [faction] rank reputation [visible] [at war] [own team] [unknown] [invisible] [inactive]" format
616                // or              "id - [faction] [no reputation]" format
617                std::ostringstream ss;
618                if (m_session)
619                                        ss << id << " - |cffffffff|Hfaction:" << id << "|h[" << name << " " << localeNames[loc] << "]|h|r";
620                                else
621                                        ss << id << " - " << name << " " << localeNames[loc];
622
623                if (repState)                               // and then target!=NULL also
624                {
625                    ReputationRank rank = target->GetReputationRank(factionEntry);
626                    std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]);
627
628                    ss << " " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
629
630                    if(repState->Flags & FACTION_FLAG_VISIBLE)
631                        ss << GetTrinityString(LANG_FACTION_VISIBLE);
632                    if(repState->Flags & FACTION_FLAG_AT_WAR)
633                        ss << GetTrinityString(LANG_FACTION_ATWAR);
634                    if(repState->Flags & FACTION_FLAG_PEACE_FORCED)
635                        ss << GetTrinityString(LANG_FACTION_PEACE_FORCED);
636                    if(repState->Flags & FACTION_FLAG_HIDDEN)
637                        ss << GetTrinityString(LANG_FACTION_HIDDEN);
638                    if(repState->Flags & FACTION_FLAG_INVISIBLE_FORCED)
639                        ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED);
640                    if(repState->Flags & FACTION_FLAG_INACTIVE)
641                        ss << GetTrinityString(LANG_FACTION_INACTIVE);
642                }
643                else
644                    ss << GetTrinityString(LANG_FACTION_NOREPUTATION);
645
646                SendSysMessage(ss.str().c_str());
647                counter++;
648            }
649        }
650    }
651
652    if (counter == 0)                                       // if counter == 0 then we found nth
653        SendSysMessage(LANG_COMMAND_FACTION_NOTFOUND);
654    return true;
655}
656
657bool ChatHandler::HandleModifyRepCommand(const char * args)
658{
659    if (!*args) return false;
660
661    Player* target = NULL;
662    target = getSelectedPlayer();
663
664    if(!target)
665    {
666        SendSysMessage(LANG_PLAYER_NOT_FOUND);
667        SetSentErrorMessage(true);
668        return false;
669    }
670
671    char* factionTxt = extractKeyFromLink((char*)args,"Hfaction");
672    if(!factionTxt)
673        return false;
674
675    uint32 factionId = atoi(factionTxt);
676
677    int32 amount = 0;
678    char *rankTxt = strtok(NULL, " ");
679    if (!factionTxt || !rankTxt)
680        return false;
681
682    amount = atoi(rankTxt);
683    if ((amount == 0) && (rankTxt[0] != '-') && !isdigit(rankTxt[0]))
684    {
685        std::string rankStr = rankTxt;
686        std::wstring wrankStr;
687        if(!Utf8toWStr(rankStr,wrankStr))
688            return false;
689        wstrToLower( wrankStr );
690
691        int r = 0;
692        amount = -42000;
693        for (; r < MAX_REPUTATION_RANK; ++r)
694        {
695            std::string rank = GetTrinityString(ReputationRankStrIndex[r]);
696            if(rank.empty())
697                continue;
698
699            std::wstring wrank;
700            if(!Utf8toWStr(rank,wrank))
701                continue;
702
703            wstrToLower(wrank);
704
705            if(wrank.substr(0,wrankStr.size())==wrankStr)
706            {
707                char *deltaTxt = strtok(NULL, " ");
708                if (deltaTxt)
709                {
710                    int32 delta = atoi(deltaTxt);
711                    if ((delta < 0) || (delta > Player::ReputationRank_Length[r] -1))
712                    {
713                        PSendSysMessage(LANG_COMMAND_FACTION_DELTA, (Player::ReputationRank_Length[r]-1));
714                        SetSentErrorMessage(true);
715                        return false;
716                    }
717                    amount += delta;
718                }
719                break;
720            }
721            amount += Player::ReputationRank_Length[r];
722        }
723        if (r >= MAX_REPUTATION_RANK)
724        {
725            PSendSysMessage(LANG_COMMAND_FACTION_INVPARAM, rankTxt);
726            SetSentErrorMessage(true);
727            return false;
728        }
729    }
730
731    FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId);
732
733    if (!factionEntry)
734    {
735        PSendSysMessage(LANG_COMMAND_FACTION_UNKNOWN, factionId);
736        SetSentErrorMessage(true);
737        return false;
738    }
739
740    if (factionEntry->reputationListID < 0)
741    {
742        PSendSysMessage(LANG_COMMAND_FACTION_NOREP_ERROR, factionEntry->name[m_session->GetSessionDbcLocale()], factionId);
743        SetSentErrorMessage(true);
744        return false;
745    }
746
747    target->SetFactionReputation(factionEntry,amount);
748    PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, target->GetName(), target->GetReputation(factionId));
749    return true;
750}
751
752bool ChatHandler::HandleNameCommand(const char* args)
753{
754    /* Temp. disabled
755        if(!*args)
756            return false;
757
758        if(strlen((char*)args)>75)
759        {
760            PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75);
761            return true;
762        }
763
764        for (uint8 i = 0; i < strlen(args); i++)
765        {
766            if(!isalpha(args[i]) && args[i]!=' ')
767            {
768                SendSysMessage(LANG_CHARS_ONLY);
769                return false;
770            }
771        }
772
773        uint64 guid;
774        guid = m_session->GetPlayer()->GetSelection();
775        if (guid == 0)
776        {
777            SendSysMessage(LANG_NO_SELECTION);
778            return true;
779        }
780
781        Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
782
783        if(!pCreature)
784        {
785            SendSysMessage(LANG_SELECT_CREATURE);
786            return true;
787        }
788
789        pCreature->SetName(args);
790        uint32 idname = objmgr.AddCreatureTemplate(pCreature->GetName());
791        pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
792
793        pCreature->SaveToDB();
794    */
795
796    return true;
797}
798
799bool ChatHandler::HandleSubNameCommand(const char* /*args*/)
800{
801    /* Temp. disabled
802
803    if(!*args)
804        args = "";
805
806    if(strlen((char*)args)>75)
807    {
808
809        PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75);
810        return true;
811    }
812
813    for (uint8 i = 0; i < strlen(args); i++)
814    {
815        if(!isalpha(args[i]) && args[i]!=' ')
816        {
817            SendSysMessage(LANG_CHARS_ONLY);
818            return false;
819        }
820    }
821    uint64 guid;
822    guid = m_session->GetPlayer()->GetSelection();
823    if (guid == 0)
824    {
825        SendSysMessage(LANG_NO_SELECTION);
826        return true;
827    }
828
829    Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
830
831    if(!pCreature)
832    {
833        SendSysMessage(LANG_SELECT_CREATURE);
834        return true;
835    }
836
837    uint32 idname = objmgr.AddCreatureSubName(pCreature->GetName(),args,pCreature->GetUInt32Value(UNIT_FIELD_DISPLAYID));
838    pCreature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname);
839
840    pCreature->SaveToDB();
841    */
842    return true;
843}
844
845//move item to other slot
846bool ChatHandler::HandleItemMoveCommand(const char* args)
847{
848    if(!*args)
849        return false;
850    uint8 srcslot, dstslot;
851
852    char* pParam1 = strtok((char*)args, " ");
853    if (!pParam1)
854        return false;
855
856    char* pParam2 = strtok(NULL, " ");
857    if (!pParam2)
858        return false;
859
860    srcslot = (uint8)atoi(pParam1);
861    dstslot = (uint8)atoi(pParam2);
862
863    uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
864    uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
865
866    if(srcslot==dstslot)
867        return true;
868
869    m_session->GetPlayer()->SwapItem( src, dst );
870
871    return true;
872}
873
874//add spawn of creature
875bool ChatHandler::HandleAddSpwCommand(const char* args)
876{
877    if(!*args)
878        return false;
879    char* charID = strtok((char*)args, " ");
880    if (!charID)
881        return false;
882
883    char* team = strtok(NULL, " ");
884    int32 teamval = 0;
885    if (team) { teamval = atoi(team); }
886    if (teamval < 0) { teamval = 0; }
887
888    uint32 id  = atoi(charID);
889
890    Player *chr = m_session->GetPlayer();
891    float x = chr->GetPositionX();
892    float y = chr->GetPositionY();
893    float z = chr->GetPositionZ();
894    float o = chr->GetOrientation();
895    Map *map = chr->GetMap();
896
897    Creature* pCreature = new Creature;
898    if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, (uint32)teamval))
899    {
900        delete pCreature;
901        return false;
902    }
903
904    pCreature->Relocate(x,y,z,o);
905
906    if(!pCreature->IsPositionValid())
907    {
908        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());
909        delete pCreature;
910        return false;
911    }
912
913    pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
914
915    uint32 db_guid = pCreature->GetDBTableGUIDLow();
916
917    // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
918    pCreature->LoadFromDB(db_guid, map);
919
920    map->Add(pCreature);
921    objmgr.AddCreatureToGrid(db_guid, objmgr.GetCreatureData(db_guid));
922    return true;
923}
924
925bool ChatHandler::HandleDelCreatureCommand(const char* args)
926{
927    Creature* unit = NULL;
928
929    if(*args)
930    {
931        // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
932        char* cId = extractKeyFromLink((char*)args,"Hcreature");
933        if(!cId)
934            return false;
935
936        uint32 lowguid = atoi(cId);
937        if(!lowguid)
938            return false;
939
940        if (CreatureData const* cr_data = objmgr.GetCreatureData(lowguid))
941            unit = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT));
942    }
943    else
944        unit = getSelectedCreature();
945
946    if(!unit || unit->isPet() || unit->isTotem())
947    {
948        SendSysMessage(LANG_SELECT_CREATURE);
949        SetSentErrorMessage(true);
950        return false;
951    }
952
953    // Delete the creature
954    unit->CombatStop();
955    unit->DeleteFromDB();
956    unit->CleanupsBeforeDelete();
957    unit->AddObjectToRemoveList();
958
959    SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
960
961    return true;
962}
963
964//delete object by selection or guid
965bool ChatHandler::HandleDelObjectCommand(const char* args)
966{
967    // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
968    char* cId = extractKeyFromLink((char*)args,"Hgameobject");
969    if(!cId)
970        return false;
971
972    uint32 lowguid = atoi(cId);
973    if(!lowguid)
974        return false;
975
976    GameObject* obj = NULL;
977
978    // by DB guid
979    if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
980        obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
981
982    if(!obj)
983    {
984        PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
985        SetSentErrorMessage(true);
986        return false;
987    }
988
989    uint64 owner_guid = obj->GetOwnerGUID();
990    if(owner_guid)
991    {
992        Unit* owner = ObjectAccessor::GetUnit(*m_session->GetPlayer(),owner_guid);
993        if(!owner && !IS_PLAYER_GUID(owner_guid))
994        {
995            PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, GUID_LOPART(owner_guid), obj->GetGUIDLow());
996            SetSentErrorMessage(true);
997            return false;
998        }
999
1000        owner->RemoveGameObject(obj,false);
1001    }
1002
1003    obj->SetRespawnTime(0);                                 // not save respawn time
1004    obj->Delete();
1005    obj->DeleteFromDB();
1006
1007    PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, obj->GetGUIDLow());
1008
1009    return true;
1010}
1011
1012//turn selected object
1013bool ChatHandler::HandleTurnObjectCommand(const char* args)
1014{
1015    // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r
1016    char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1017    if(!cId)
1018        return false;
1019
1020    uint32 lowguid = atoi(cId);
1021    if(!lowguid)
1022        return false;
1023
1024    GameObject* obj = NULL;
1025
1026    // by DB guid
1027    if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1028        obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1029
1030    if(!obj)
1031    {
1032        PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1033        SetSentErrorMessage(true);
1034        return false;
1035    }
1036
1037    char* po = strtok(NULL, " ");
1038    float o;
1039
1040    if (po)
1041    {
1042        o = (float)atof(po);
1043    }
1044    else
1045    {
1046        Player *chr = m_session->GetPlayer();
1047        o = chr->GetOrientation();
1048    }
1049
1050    float rot2 = sin(o/2);
1051    float rot3 = cos(o/2);
1052
1053    Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1054    map->Remove(obj,false);
1055
1056    obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
1057
1058    obj->SetFloatValue(GAMEOBJECT_FACING, o);
1059    obj->SetFloatValue(GAMEOBJECT_ROTATION+2, rot2);
1060    obj->SetFloatValue(GAMEOBJECT_ROTATION+3, rot3);
1061
1062    map->Add(obj);
1063
1064    obj->SaveToDB();
1065    obj->Refresh();
1066
1067    PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), o);
1068
1069    return true;
1070}
1071
1072//move selected creature
1073bool ChatHandler::HandleMoveCreatureCommand(const char* args)
1074{
1075    uint32 lowguid = 0;
1076
1077    Creature* pCreature = getSelectedCreature();
1078
1079    if(!pCreature)
1080    {
1081        // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r
1082        char* cId = extractKeyFromLink((char*)args,"Hcreature");
1083        if(!cId)
1084            return false;
1085
1086        uint32 lowguid = atoi(cId);
1087
1088        /* FIXME: impossibel without entry
1089        if(lowguid)
1090            pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1091        */
1092
1093        // Attempting creature load from DB data
1094        if(!pCreature)
1095        {
1096            CreatureData const* data = objmgr.GetCreatureData(lowguid);
1097            if(!data)
1098            {
1099                PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1100                SetSentErrorMessage(true);
1101                return false;
1102            }
1103
1104            uint32 map_id = data->mapid;
1105
1106            if(m_session->GetPlayer()->GetMapId()!=map_id)
1107            {
1108                PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
1109                SetSentErrorMessage(true);
1110                return false;
1111            }
1112        }
1113        else
1114        {
1115            lowguid = pCreature->GetDBTableGUIDLow();
1116        }
1117    }
1118    else
1119    {
1120        lowguid = pCreature->GetDBTableGUIDLow();
1121    }
1122
1123    float x = m_session->GetPlayer()->GetPositionX();
1124    float y = m_session->GetPlayer()->GetPositionY();
1125    float z = m_session->GetPlayer()->GetPositionZ();
1126    float o = m_session->GetPlayer()->GetOrientation();
1127
1128    if (pCreature)
1129    {
1130        if(CreatureData const* data = objmgr.GetCreatureData(pCreature->GetDBTableGUIDLow()))
1131        {
1132            const_cast<CreatureData*>(data)->posX = x;
1133            const_cast<CreatureData*>(data)->posY = y;
1134            const_cast<CreatureData*>(data)->posZ = z;
1135            const_cast<CreatureData*>(data)->orientation = o;
1136        }
1137        MapManager::Instance().GetMap(pCreature->GetMapId(),pCreature)->CreatureRelocation(pCreature,x, y, z,o);
1138        pCreature->GetMotionMaster()->Initialize();
1139        if(pCreature->isAlive())                            // dead creature will reset movement generator at respawn
1140        {
1141            pCreature->setDeathState(JUST_DIED);
1142            pCreature->Respawn();
1143        }
1144    }
1145
1146    WorldDatabase.PExecuteLog("UPDATE creature SET position_x = '%f', position_y = '%f', position_z = '%f', orientation = '%f' WHERE guid = '%u'", x, y, z, o, lowguid);
1147    PSendSysMessage(LANG_COMMAND_CREATUREMOVED);
1148    return true;
1149}
1150
1151//move selected object
1152bool ChatHandler::HandleMoveObjectCommand(const char* args)
1153{
1154    // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r
1155    char* cId = extractKeyFromLink((char*)args,"Hgameobject");
1156    if(!cId)
1157        return false;
1158
1159    uint32 lowguid = atoi(cId);
1160    if(!lowguid)
1161        return false;
1162
1163    GameObject* obj = NULL;
1164
1165    // by DB guid
1166    if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
1167        obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
1168
1169    if(!obj)
1170    {
1171        PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
1172        SetSentErrorMessage(true);
1173        return false;
1174    }
1175
1176    char* px = strtok(NULL, " ");
1177    char* py = strtok(NULL, " ");
1178    char* pz = strtok(NULL, " ");
1179
1180    if (!px)
1181    {
1182        Player *chr = m_session->GetPlayer();
1183
1184        Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1185        map->Remove(obj,false);
1186
1187        obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation());
1188        obj->SetFloatValue(GAMEOBJECT_POS_X, chr->GetPositionX());
1189        obj->SetFloatValue(GAMEOBJECT_POS_Y, chr->GetPositionY());
1190        obj->SetFloatValue(GAMEOBJECT_POS_Z, chr->GetPositionZ());
1191
1192        map->Add(obj);
1193    }
1194    else
1195    {
1196        if(!py || !pz)
1197            return false;
1198
1199        float x = (float)atof(px);
1200        float y = (float)atof(py);
1201        float z = (float)atof(pz);
1202
1203        if(!MapManager::IsValidMapCoord(obj->GetMapId(),x,y,z))
1204        {
1205            PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,obj->GetMapId());
1206            SetSentErrorMessage(true);
1207            return false;
1208        }
1209
1210        Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj);
1211        map->Remove(obj,false);
1212
1213        obj->Relocate(x, y, z, obj->GetOrientation());
1214        obj->SetFloatValue(GAMEOBJECT_POS_X, x);
1215        obj->SetFloatValue(GAMEOBJECT_POS_Y, y);
1216        obj->SetFloatValue(GAMEOBJECT_POS_Z, z);
1217
1218        map->Add(obj);
1219    }
1220
1221    obj->SaveToDB();
1222    obj->Refresh();
1223
1224    PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, obj->GetGUIDLow());
1225
1226    return true;
1227}
1228
1229//demorph player or unit
1230bool ChatHandler::HandleDeMorphCommand(const char* /*args*/)
1231{
1232    Unit *target = getSelectedUnit();
1233    if(!target)
1234        target = m_session->GetPlayer();
1235
1236    target->DeMorph();
1237
1238    return true;
1239}
1240
1241//add item in vendorlist
1242bool ChatHandler::HandleAddVendorItemCommand(const char* args)
1243{
1244    if (!*args)
1245        return false;
1246
1247    char* pitem  = extractKeyFromLink((char*)args,"Hitem");
1248    if (!pitem)
1249    {
1250        SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1251        SetSentErrorMessage(true);
1252        return false;
1253    }
1254
1255    uint32 itemId = atol(pitem);
1256
1257    char* fmaxcount = strtok(NULL, " ");                    //add maxcount, default: 0
1258    uint32 maxcount = 0;
1259    if (fmaxcount)
1260        maxcount = atol(fmaxcount);
1261
1262    char* fincrtime = strtok(NULL, " ");                    //add incrtime, default: 0
1263    uint32 incrtime = 0;
1264    if (fincrtime)
1265        incrtime = atol(fincrtime);
1266
1267    char* fextendedcost = strtok(NULL, " ");                //add ExtendedCost, default: 0
1268    uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
1269
1270    Creature* vendor = getSelectedCreature();
1271
1272    uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
1273
1274    if(!objmgr.IsVendorItemValid(vendor_entry,itemId,maxcount,incrtime,extendedcost,m_session->GetPlayer()))
1275    {
1276        SetSentErrorMessage(true);
1277        return false;
1278    }
1279
1280    objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
1281
1282    ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1283
1284    PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
1285    return true;
1286}
1287
1288//del item from vendor list
1289bool ChatHandler::HandleDelVendorItemCommand(const char* args)
1290{
1291    if (!*args)
1292        return false;
1293
1294    Creature* vendor = getSelectedCreature();
1295    if (!vendor || !vendor->isVendor())
1296    {
1297        SendSysMessage(LANG_COMMAND_VENDORSELECTION);
1298        SetSentErrorMessage(true);
1299        return false;
1300    }
1301
1302    char* pitem  = extractKeyFromLink((char*)args,"Hitem");
1303    if (!pitem)
1304    {
1305        SendSysMessage(LANG_COMMAND_NEEDITEMSEND);
1306        SetSentErrorMessage(true);
1307        return false;
1308    }
1309    uint32 itemId = atol(pitem);
1310
1311
1312    if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId))
1313    {
1314        PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId);
1315        SetSentErrorMessage(true);
1316        return false;
1317    }
1318
1319    ItemPrototype const* pProto = objmgr.GetItemPrototype(itemId);
1320
1321    PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST,itemId,pProto->Name1);
1322    return true;
1323}
1324
1325//add move for creature
1326bool ChatHandler::HandleAddMoveCommand(const char* args)
1327{
1328    if(!*args)
1329        return false;
1330
1331    char* guid_str = strtok((char*)args, " ");
1332    char* wait_str = strtok((char*)NULL, " ");
1333
1334    uint32 lowguid = atoi((char*)guid_str);
1335
1336    Creature* pCreature = NULL;
1337
1338    /* FIXME: impossible without entry
1339    if(lowguid)
1340        pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1341    */
1342
1343    // attempt check creature existence by DB data
1344    if(!pCreature)
1345    {
1346        CreatureData const* data = objmgr.GetCreatureData(lowguid);
1347        if(!data)
1348        {
1349            PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1350            SetSentErrorMessage(true);
1351            return false;
1352        }
1353    }
1354    else
1355    {
1356        // obtain real GUID for DB operations
1357        lowguid = pCreature->GetDBTableGUIDLow();
1358    }
1359
1360    int wait = wait_str ? atoi(wait_str) : 0;
1361
1362    if(wait < 0)
1363        wait = 0;
1364
1365    Player* player = m_session->GetPlayer();
1366
1367    WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
1368
1369    // update movement type
1370    WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
1371    if(pCreature)
1372    {
1373        pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
1374        pCreature->GetMotionMaster()->Initialize();
1375        if(pCreature->isAlive())                            // dead creature will reset movement generator at respawn
1376        {
1377            pCreature->setDeathState(JUST_DIED);
1378            pCreature->Respawn();
1379        }
1380        pCreature->SaveToDB();
1381    }
1382
1383    SendSysMessage(LANG_WAYPOINT_ADDED);
1384
1385    return true;
1386}
1387
1388/**
1389 * Set the movement type for an NPC.<br/>
1390 * <br/>
1391 * Valid movement types are:
1392 * <ul>
1393 * <li> stay - NPC wont move </li>
1394 * <li> random - NPC will move randomly according to the spawndist </li>
1395 * <li> way - NPC will move with given waypoints set </li>
1396 * </ul>
1397 * additional parameter: NODEL - so no waypoints are deleted, if you
1398 *                       change the movement type
1399 */
1400bool ChatHandler::HandleSetMoveTypeCommand(const char* args)
1401{
1402    if(!*args)
1403        return false;
1404
1405    // 3 arguments:
1406    // GUID (optional - you can also select the creature)
1407    // stay|random|way (determines the kind of movement)
1408    // NODEL (optional - tells the system NOT to delete any waypoints)
1409    //        this is very handy if you want to do waypoints, that are
1410    //        later switched on/off according to special events (like escort
1411    //        quests, etc)
1412    char* guid_str = strtok((char*)args, " ");
1413    char* type_str = strtok((char*)NULL, " ");
1414    char* dontdel_str = strtok((char*)NULL, " ");
1415
1416    bool doNotDelete = false;
1417
1418    if(!guid_str)
1419        return false;
1420
1421    uint32 lowguid = 0;
1422    Creature* pCreature = NULL;
1423
1424    if( dontdel_str )
1425    {
1426        //sLog.outError("DEBUG: All 3 params are set");
1427
1428        // All 3 params are set
1429        // GUID
1430        // type
1431        // doNotDEL
1432        if( stricmp( dontdel_str, "NODEL" ) == 0 )
1433        {
1434            //sLog.outError("DEBUG: doNotDelete = true;");
1435            doNotDelete = true;
1436        }
1437    }
1438    else
1439    {
1440        // Only 2 params - but maybe NODEL is set
1441        if( type_str )
1442        {
1443            sLog.outError("DEBUG: Only 2 params ");
1444            if( stricmp( type_str, "NODEL" ) == 0 )
1445            {
1446                //sLog.outError("DEBUG: type_str, NODEL ");
1447                doNotDelete = true;
1448                type_str = NULL;
1449            }
1450        }
1451    }
1452
1453    if(!type_str)                                           // case .setmovetype $move_type (with selected creature)
1454    {
1455        type_str = guid_str;
1456        pCreature = getSelectedCreature();
1457        if(!pCreature || pCreature->isPet())
1458            return false;
1459        lowguid = pCreature->GetDBTableGUIDLow();
1460    }
1461    else                                                    // case .setmovetype #creature_guid $move_type (with selected creature)
1462    {
1463        lowguid = atoi((char*)guid_str);
1464
1465        /* impossible without entry
1466        if(lowguid)
1467            pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_GUID(lowguid,HIGHGUID_UNIT));
1468        */
1469
1470        // attempt check creature existence by DB data
1471        if(!pCreature)
1472        {
1473            CreatureData const* data = objmgr.GetCreatureData(lowguid);
1474            if(!data)
1475            {
1476                PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
1477                SetSentErrorMessage(true);
1478                return false;
1479            }
1480        }
1481        else
1482        {
1483            lowguid = pCreature->GetDBTableGUIDLow();
1484        }
1485    }
1486
1487    // now lowguid is low guid really existed creature
1488    // and pCreature point (maybe) to this creature or NULL
1489
1490    MovementGeneratorType move_type;
1491
1492    std::string type = type_str;
1493
1494    if(type == "stay")
1495        move_type = IDLE_MOTION_TYPE;
1496    else if(type == "random")
1497        move_type = RANDOM_MOTION_TYPE;
1498    else if(type == "way")
1499        move_type = WAYPOINT_MOTION_TYPE;
1500    else
1501        return false;
1502
1503    // update movement type
1504    if(doNotDelete == false)
1505        WaypointMgr.DeletePath(lowguid);
1506
1507    if(pCreature)
1508    {
1509        pCreature->SetDefaultMovementType(move_type);
1510        pCreature->GetMotionMaster()->Initialize();
1511        if(pCreature->isAlive())                            // dead creature will reset movement generator at respawn
1512        {
1513            pCreature->setDeathState(JUST_DIED);
1514            pCreature->Respawn();
1515        }
1516        pCreature->SaveToDB();
1517    }
1518    if( doNotDelete == false )
1519    {
1520        PSendSysMessage(LANG_MOVE_TYPE_SET,type_str);
1521    }
1522    else
1523    {
1524        PSendSysMessage(LANG_MOVE_TYPE_SET_NODEL,type_str);
1525    }
1526
1527    return true;
1528}                                                           // HandleSetMoveTypeCommand
1529
1530//change level of creature or pet
1531bool ChatHandler::HandleChangeLevelCommand(const char* args)
1532{
1533    if (!*args)
1534        return false;
1535
1536    uint8 lvl = (uint8) atoi((char*)args);
1537    if ( lvl < 1 || lvl > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) + 3)
1538    {
1539        SendSysMessage(LANG_BAD_VALUE);
1540        SetSentErrorMessage(true);
1541        return false;
1542    }
1543
1544    Creature* pCreature = getSelectedCreature();
1545    if(!pCreature)
1546    {
1547        SendSysMessage(LANG_SELECT_CREATURE);
1548        SetSentErrorMessage(true);
1549        return false;
1550    }
1551
1552    if(pCreature->isPet())
1553    {
1554        ((Pet*)pCreature)->GivePetLevel(lvl);
1555    }
1556    else
1557    {
1558        pCreature->SetMaxHealth( 100 + 30*lvl);
1559        pCreature->SetHealth( 100 + 30*lvl);
1560        pCreature->SetLevel( lvl);
1561        pCreature->SaveToDB();
1562    }
1563
1564    return true;
1565}
1566
1567//set npcflag of creature
1568bool ChatHandler::HandleNPCFlagCommand(const char* args)
1569{
1570    if (!*args)
1571        return false;
1572
1573    uint32 npcFlags = (uint32) atoi((char*)args);
1574
1575    Creature* pCreature = getSelectedCreature();
1576
1577    if(!pCreature)
1578    {
1579        SendSysMessage(LANG_SELECT_CREATURE);
1580        SetSentErrorMessage(true);
1581        return false;
1582    }
1583
1584    pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
1585
1586    WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
1587
1588    SendSysMessage(LANG_VALUE_SAVED_REJOIN);
1589
1590    return true;
1591}
1592
1593//set model of creature
1594bool ChatHandler::HandleSetModelCommand(const char* args)
1595{
1596    if (!*args)
1597        return false;
1598
1599    uint32 displayId = (uint32) atoi((char*)args);
1600
1601    Creature *pCreature = getSelectedCreature();
1602
1603    if(!pCreature || pCreature->isPet())
1604    {
1605        SendSysMessage(LANG_SELECT_CREATURE);
1606        SetSentErrorMessage(true);
1607        return false;
1608    }
1609
1610    pCreature->SetDisplayId(displayId);
1611    pCreature->SetNativeDisplayId(displayId);
1612
1613    pCreature->SaveToDB();
1614
1615    return true;
1616}
1617
1618//morph creature or player
1619bool ChatHandler::HandleMorphCommand(const char* args)
1620{
1621    if (!*args)
1622        return false;
1623
1624    uint16 display_id = (uint16)atoi((char*)args);
1625
1626    Unit *target = getSelectedUnit();
1627    if(!target)
1628        target = m_session->GetPlayer();
1629
1630    target->SetDisplayId(display_id);
1631
1632    return true;
1633}
1634
1635//set faction of creature  or go
1636bool ChatHandler::HandleFactionIdCommand(const char* args)
1637{
1638    if (!*args)
1639        return false;
1640
1641    uint32 factionId = (uint32) atoi((char*)args);
1642
1643    if (!sFactionTemplateStore.LookupEntry(factionId))
1644    {
1645        PSendSysMessage(LANG_WRONG_FACTION, factionId);
1646        SetSentErrorMessage(true);
1647        return false;
1648    }
1649
1650    Creature* pCreature = getSelectedCreature();
1651
1652    if(!pCreature)
1653    {
1654        SendSysMessage(LANG_SELECT_CREATURE);
1655        SetSentErrorMessage(true);
1656        return false;
1657    }
1658
1659    pCreature->setFaction(factionId);
1660
1661    // faction is set in creature_template - not inside creature
1662
1663    // update in memory
1664    if(CreatureInfo const *cinfo = pCreature->GetCreatureInfo())
1665    {
1666        const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
1667        const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
1668    }
1669
1670    // and DB
1671    WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
1672
1673    return true;
1674}
1675
1676//kick player
1677bool ChatHandler::HandleKickPlayerCommand(const char *args)
1678{
1679    char* kickName = strtok((char*)args, " ");
1680    if (!kickName)
1681    {
1682        Player* player = getSelectedPlayer();
1683
1684        if(!player)
1685        {
1686            SendSysMessage(LANG_NO_CHAR_SELECTED);
1687            SetSentErrorMessage(true);
1688            return false;
1689        }
1690
1691        if(player==m_session->GetPlayer())
1692        {
1693            SendSysMessage(LANG_COMMAND_KICKSELF);
1694            SetSentErrorMessage(true);
1695            return false;
1696        }
1697
1698        player->GetSession()->KickPlayer();
1699    }
1700    else
1701    {
1702        std::string name = kickName;
1703        if(!normalizePlayerName(name))
1704        {
1705            SendSysMessage(LANG_PLAYER_NOT_FOUND);
1706            SetSentErrorMessage(true);
1707            return false;
1708        }
1709
1710        if(m_session && name==m_session->GetPlayer()->GetName())
1711        {
1712            SendSysMessage(LANG_COMMAND_KICKSELF);
1713            SetSentErrorMessage(true);
1714            return false;
1715        }
1716
1717        if(sWorld.KickPlayer(name))
1718        {
1719            PSendSysMessage(LANG_COMMAND_KICKMESSAGE,name.c_str());
1720        }
1721        else
1722            PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,name.c_str());
1723    }
1724
1725    return true;
1726}
1727
1728//show info of player
1729bool ChatHandler::HandlePInfoCommand(const char* args)
1730{
1731    Player* target = NULL;
1732    uint64 targetGUID = 0;
1733
1734    char* px = strtok((char*)args, " ");
1735    char* py = NULL;
1736
1737    std::string name;
1738
1739    if (px)
1740    {
1741        name = px;
1742
1743        if(name.empty())
1744            return false;
1745
1746        if(!normalizePlayerName(name))
1747        {
1748            SendSysMessage(LANG_PLAYER_NOT_FOUND);
1749            SetSentErrorMessage(true);
1750            return false;
1751        }
1752
1753        target = objmgr.GetPlayer(name.c_str());
1754        if (target)
1755            py = strtok(NULL, " ");
1756        else
1757        {
1758            targetGUID = objmgr.GetPlayerGUIDByName(name);
1759            if(targetGUID)
1760                py = strtok(NULL, " ");
1761            else
1762                py = px;
1763        }
1764    }
1765
1766    if(!target && !targetGUID)
1767    {
1768        target = getSelectedPlayer();
1769    }
1770
1771    if(!target && !targetGUID)
1772    {
1773        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1774        SetSentErrorMessage(true);
1775        return false;
1776    }
1777
1778    uint32 accId = 0;
1779    uint32 money = 0;
1780    uint32 total_player_time = 0;
1781    uint32 level = 0;
1782    uint32 latency = 0;
1783
1784    // get additional information from Player object
1785    if(target)
1786    {
1787        targetGUID = target->GetGUID();
1788        name = target->GetName();                           // re-read for case getSelectedPlayer() target
1789        accId = target->GetSession()->GetAccountId();
1790        money = target->GetMoney();
1791        total_player_time = target->GetTotalPlayedTime();
1792        level = target->getLevel();
1793        latency = target->GetSession()->GetLatency();
1794    }
1795    // get additional information from DB
1796    else
1797    {
1798        accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
1799        Player plr(m_session);                              // use current session for temporary load
1800        plr.MinimalLoadFromDB(NULL, targetGUID);
1801        money = plr.GetMoney();
1802        total_player_time = plr.GetTotalPlayedTime();
1803        level = plr.getLevel();
1804    }
1805
1806    std::string username = GetTrinityString(LANG_ERROR);
1807    std::string last_ip = GetTrinityString(LANG_ERROR);
1808    uint32 security = 0;
1809    std::string last_login = GetTrinityString(LANG_ERROR);
1810
1811    QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
1812    if(result)
1813    {
1814        Field* fields = result->Fetch();
1815        username = fields[0].GetCppString();
1816        security = fields[1].GetUInt32();
1817       
1818                if(!m_session || m_session->GetSecurity() >= security)
1819        {
1820            last_ip = fields[2].GetCppString();
1821            last_login = fields[3].GetCppString();
1822        }
1823        else
1824        {
1825            last_ip = "-";
1826            last_login = "-";
1827        }
1828
1829        delete result;
1830    }
1831
1832    PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetTrinityString(LANG_OFFLINE)), name.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency);
1833
1834    std::string timeStr = secsToTimeString(total_player_time,true,true);
1835    uint32 gold = money /GOLD;
1836    uint32 silv = (money % GOLD) / SILVER;
1837    uint32 copp = (money % GOLD) % SILVER;
1838    PSendSysMessage(LANG_PINFO_LEVEL,  timeStr.c_str(), level, gold,silv,copp );
1839
1840    if ( py && strncmp(py, "rep", 3) == 0 )
1841    {
1842        if(!target)
1843        {
1844            // rep option not implemented for offline case
1845            SendSysMessage(LANG_PINFO_NO_REP);
1846            SetSentErrorMessage(true);
1847            return false;
1848        }
1849
1850        char* FactionName;
1851        for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr)
1852        {
1853            FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
1854            if (factionEntry)
1855                FactionName = factionEntry->name[m_session->GetSessionDbcLocale()];
1856            else
1857                FactionName = "#Not found#";
1858            ReputationRank rank = target->GetReputationRank(factionEntry);
1859            std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]);
1860            std::ostringstream ss;
1861            ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << FactionName << "]|h|r " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
1862
1863            if(itr->second.Flags & FACTION_FLAG_VISIBLE)
1864                ss << GetTrinityString(LANG_FACTION_VISIBLE);
1865            if(itr->second.Flags & FACTION_FLAG_AT_WAR)
1866                ss << GetTrinityString(LANG_FACTION_ATWAR);
1867            if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
1868                ss << GetTrinityString(LANG_FACTION_PEACE_FORCED);
1869            if(itr->second.Flags & FACTION_FLAG_HIDDEN)
1870                ss << GetTrinityString(LANG_FACTION_HIDDEN);
1871            if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
1872                ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED);
1873            if(itr->second.Flags & FACTION_FLAG_INACTIVE)
1874                ss << GetTrinityString(LANG_FACTION_INACTIVE);
1875
1876            SendSysMessage(ss.str().c_str());
1877        }
1878    }
1879    return true;
1880}
1881
1882//show tickets
1883void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
1884{
1885    std::string name;
1886    if(!objmgr.GetPlayerNameByGUID(guid,name))
1887        name = GetTrinityString(LANG_UNKNOWN);
1888
1889    PSendSysMessage(LANG_COMMAND_TICKETVIEW, name.c_str(),time,text);
1890}
1891
1892//ticket commands
1893bool ChatHandler::HandleTicketCommand(const char* args)
1894{
1895    char* px = strtok((char*)args, " ");
1896
1897    // ticket<end>
1898    if (!px)
1899    {
1900                if(!m_session)
1901                {
1902                        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1903                        SetSentErrorMessage(true);
1904                        return false;
1905                }
1906
1907        size_t count;
1908        QueryResult *result = CharacterDatabase.Query("SELECT COUNT(ticket_id) FROM character_ticket");
1909        if(result)
1910        {
1911            count = (*result)[0].GetUInt32();
1912            delete result;
1913        }
1914        else
1915            count = 0;
1916
1917        bool accept = m_session->GetPlayer()->isAcceptTickets();
1918               
1919                PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ?  GetTrinityString(LANG_ON) : GetTrinityString(LANG_OFF));
1920        return true;
1921    }
1922
1923    // ticket on
1924    if(strncmp(px,"on",3) == 0)
1925    {
1926                if(!m_session)
1927                {
1928                        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1929                        SetSentErrorMessage(true);
1930                        return false;
1931                }
1932
1933        m_session->GetPlayer()->SetAcceptTicket(true);
1934        SendSysMessage(LANG_COMMAND_TICKETON);
1935        return true;
1936    }
1937
1938    // ticket off
1939    if(strncmp(px,"off",4) == 0)
1940    {
1941                if(!m_session)
1942                {
1943                        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1944                        SetSentErrorMessage(true);
1945                        return false;
1946                }
1947
1948        m_session->GetPlayer()->SetAcceptTicket(false);
1949        SendSysMessage(LANG_COMMAND_TICKETOFF);
1950        return true;
1951    }
1952
1953    // ticket #num
1954    int num = atoi(px);
1955    if(num > 0)
1956    {
1957        QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC LIMIT %d,1",num-1);
1958
1959        if(!result)
1960        {
1961            PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
1962            delete result;
1963            SetSentErrorMessage(true);
1964            return false;
1965        }
1966
1967        Field* fields = result->Fetch();
1968
1969        uint64 guid = fields[0].GetUInt64();
1970        char const* text = fields[1].GetString();
1971        char const* time = fields[2].GetString();
1972
1973        ShowTicket(guid,text,time);
1974        delete result;
1975        return true;
1976    }
1977
1978    std::string name = px;
1979
1980    if(!normalizePlayerName(name))
1981    {
1982        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1983        SetSentErrorMessage(true);
1984        return false;
1985    }
1986
1987    uint64 guid = objmgr.GetPlayerGUIDByName(name);
1988
1989    if(!guid)
1990        return false;
1991
1992    // ticket $char_name
1993    QueryResult *result = CharacterDatabase.PQuery("SELECT ticket_text,ticket_lastchange FROM character_ticket WHERE guid = '%u' ORDER BY ticket_id ASC",GUID_LOPART(guid));
1994
1995    if(!result)
1996        return false;
1997
1998    Field* fields = result->Fetch();
1999
2000    char const* text = fields[0].GetString();
2001    char const* time = fields[1].GetString();
2002
2003    ShowTicket(guid,text,time);
2004    delete result;
2005
2006    return true;
2007}
2008
2009uint32 ChatHandler::GetTicketIDByNum(uint32 num)
2010{
2011    QueryResult *result = CharacterDatabase.Query("SELECT ticket_id FROM character_ticket");
2012
2013    if(!result || num > result->GetRowCount())
2014    {
2015        PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2016        delete result;
2017        return 0;
2018    }
2019
2020    for(uint32 i = 1; i < num; ++i)
2021        result->NextRow();
2022
2023    Field* fields = result->Fetch();
2024
2025    uint32 id = fields[0].GetUInt32();
2026    delete result;
2027    return id;
2028}
2029
2030//dell all tickets
2031bool ChatHandler::HandleDelTicketCommand(const char *args)
2032{
2033    char* px = strtok((char*)args, " ");
2034    if (!px)
2035        return false;
2036
2037    // delticket all
2038    if(strncmp(px,"all",4) == 0)
2039    {
2040        QueryResult *result = CharacterDatabase.Query("SELECT guid FROM character_ticket");
2041
2042        if(!result)
2043            return true;
2044
2045        // notify players about ticket deleting
2046        do
2047        {
2048            Field* fields = result->Fetch();
2049
2050            uint64 guid = fields[0].GetUInt64();
2051
2052            if(Player* sender = objmgr.GetPlayer(guid))
2053                sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2054
2055        }while(result->NextRow());
2056
2057        delete result;
2058
2059        CharacterDatabase.PExecute("DELETE FROM character_ticket");
2060        SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2061        return true;
2062    }
2063
2064    int num = (uint32)atoi(px);
2065
2066    // delticket #num
2067    if(num > 0)
2068    {
2069        QueryResult *result = CharacterDatabase.PQuery("SELECT ticket_id,guid FROM character_ticket LIMIT %i",num);
2070
2071        if(!result || uint64(num) > result->GetRowCount())
2072        {
2073            PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2074            delete result;
2075            SetSentErrorMessage(true);
2076            return false;
2077        }
2078
2079        for(int i = 1; i < num; ++i)
2080            result->NextRow();
2081
2082        Field* fields = result->Fetch();
2083
2084        uint32 id   = fields[0].GetUInt32();
2085        uint64 guid = fields[1].GetUInt64();
2086        delete result;
2087
2088        CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE ticket_id = '%u'", id);
2089
2090        // notify players about ticket deleting
2091        if(Player* sender = objmgr.GetPlayer(guid))
2092        {
2093            sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2094            PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,sender->GetName());
2095        }
2096        else
2097            SendSysMessage(LANG_COMMAND_TICKETDEL);
2098
2099        return true;
2100    }
2101
2102    std::string name = px;
2103
2104    if(!normalizePlayerName(name))
2105    {
2106        SendSysMessage(LANG_PLAYER_NOT_FOUND);
2107        SetSentErrorMessage(true);
2108        return false;
2109    }
2110
2111    uint64 guid = objmgr.GetPlayerGUIDByName(name);
2112
2113    if(!guid)
2114        return false;
2115
2116    // delticket $char_name
2117    CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u'",GUID_LOPART(guid));
2118
2119    // notify players about ticket deleting
2120    if(Player* sender = objmgr.GetPlayer(guid))
2121        sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2122
2123    PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,px);
2124    return true;
2125}
2126
2127//set spawn dist of creature
2128bool ChatHandler::HandleSpawnDistCommand(const char* args)
2129{
2130    if(!*args)
2131        return false;
2132
2133    float option = atof((char*)args);
2134    if (option < 0.0f)
2135    {
2136        SendSysMessage(LANG_BAD_VALUE);
2137        return false;
2138    }
2139
2140    MovementGeneratorType mtype = IDLE_MOTION_TYPE;
2141    if (option >0.0f)
2142        mtype = RANDOM_MOTION_TYPE;
2143
2144    Creature *pCreature = getSelectedCreature();
2145    uint32 u_guidlow = 0;
2146
2147    if (pCreature)
2148        u_guidlow = pCreature->GetDBTableGUIDLow();
2149    else
2150        return false;
2151
2152    pCreature->SetRespawnRadius((float)option);
2153    pCreature->SetDefaultMovementType(mtype);
2154    pCreature->GetMotionMaster()->Initialize();
2155    if(pCreature->isAlive())                                // dead creature will reset movement generator at respawn
2156    {
2157        pCreature->setDeathState(JUST_DIED);
2158        pCreature->Respawn();
2159    }
2160
2161    WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
2162    PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
2163    return true;
2164}
2165
2166bool ChatHandler::HandleSpawnTimeCommand(const char* args)
2167{
2168    if(!*args)
2169        return false;
2170
2171    char* stime = strtok((char*)args, " ");
2172
2173    if (!stime)
2174        return false;
2175
2176    int i_stime = atoi((char*)stime);
2177
2178    if (i_stime < 0)
2179    {
2180        SendSysMessage(LANG_BAD_VALUE);
2181        SetSentErrorMessage(true);
2182        return false;
2183    }
2184
2185    Creature *pCreature = getSelectedCreature();
2186    uint32 u_guidlow = 0;
2187
2188    if (pCreature)
2189        u_guidlow = pCreature->GetDBTableGUIDLow();
2190    else
2191        return false;
2192
2193    WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
2194    pCreature->SetRespawnDelay((uint32)i_stime);
2195    PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
2196
2197    return true;
2198}
2199
2200/**
2201 * Add a waypoint to a creature.
2202 *
2203 * The user can either select an npc or provide its GUID.
2204 *
2205 * The user can even select a visual waypoint - then the new waypoint
2206 * is placed *after* the selected one - this makes insertion of new
2207 * waypoints possible.
2208 *
2209 * eg:
2210 * .wp add 12345
2211 * -> adds a waypoint to the npc with the GUID 12345
2212 *
2213 * .wp add
2214 * -> adds a waypoint to the currently selected creature
2215 *
2216 *
2217 * @param args if the user did not provide a GUID, it is NULL
2218 *
2219 * @return true - command did succeed, false - something went wrong
2220 */
2221bool ChatHandler::HandleWpAddCommand(const char* args)
2222{
2223    sLog.outDebug("DEBUG: HandleWpAddCommand");
2224
2225    // optional
2226    char* guid_str = NULL;
2227
2228    if(*args)
2229    {
2230        guid_str = strtok((char*)args, " ");
2231    }
2232
2233    uint32 lowguid = 0;
2234    uint32 point = 0;
2235    Creature* target = getSelectedCreature();
2236    // Did player provide a GUID?
2237    if (!guid_str)
2238    {
2239        sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2240
2241        // No GUID provided
2242        // -> Player must have selected a creature
2243
2244        if(!target || target->isPet())
2245        {
2246            SendSysMessage(LANG_SELECT_CREATURE);
2247            SetSentErrorMessage(true);
2248            return false;
2249        }
2250        if (target->GetEntry() == VISUAL_WAYPOINT )
2251        {
2252            sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2253
2254            QueryResult *result =
2255                WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2256                target->GetGUIDLow() );
2257            if(!result)
2258            {
2259                PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2260                // User selected a visual spawnpoint -> get the NPC
2261                // Select NPC GUID
2262                // Since we compare float values, we have to deal with
2263                // some difficulties.
2264                // Here we search for all waypoints that only differ in one from 1 thousand
2265                // (0.001) - There is no other way to compare C++ floats with mySQL floats
2266                // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2267                const char* maxDIFF = "0.01";
2268                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 )",
2269                    target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2270                if(!result)
2271                {
2272                    PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2273                    SetSentErrorMessage(true);
2274                    return false;
2275                }
2276            }
2277            do
2278            {
2279                Field *fields = result->Fetch();
2280                lowguid = fields[0].GetUInt32();
2281                point   = fields[1].GetUInt32();
2282            }while( result->NextRow() );
2283            delete result;
2284
2285            CreatureData const* data = objmgr.GetCreatureData(lowguid);
2286            if(!data)
2287            {
2288                PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2289                SetSentErrorMessage(true);
2290                return false;
2291            }
2292
2293            target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2294            if(!target)
2295            {
2296                PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2297                SetSentErrorMessage(true);
2298                return false;
2299            }
2300        }
2301        else
2302        {
2303            lowguid = target->GetDBTableGUIDLow();
2304        }
2305    }
2306    else
2307    {
2308        sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2309
2310        // GUID provided
2311        // Warn if player also selected a creature
2312        // -> Creature selection is ignored <-
2313        if(target)
2314        {
2315            SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2316        }
2317        lowguid = atoi((char*)guid_str);
2318
2319        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2320        if(!data)
2321        {
2322            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2323            SetSentErrorMessage(true);
2324            return false;
2325        }
2326
2327        target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2328        if(!target || target->isPet())
2329        {
2330            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2331            SetSentErrorMessage(true);
2332            return false;
2333        }
2334    }
2335    // lowguid -> GUID of the NPC
2336    // point   -> number of the waypoint (if not 0)
2337    sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2338
2339    sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2340
2341    Player* player = m_session->GetPlayer();
2342    WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2343
2344    // update movement type
2345    if(target)
2346    {
2347        target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2348        target->GetMotionMaster()->Initialize();
2349        if(target->isAlive())                               // dead creature will reset movement generator at respawn
2350        {
2351            target->setDeathState(JUST_DIED);
2352            target->Respawn();
2353        }
2354        target->SaveToDB();
2355    }
2356    else
2357        WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2358
2359    PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2360
2361    return true;
2362}                                                           // HandleWpAddCommand
2363
2364/**
2365 * .wp modify emote | spell | text | del | move | add
2366 *
2367 * add -> add a WP after the selected visual waypoint
2368 *        User must select a visual waypoint and then issue ".wp modify add"
2369 *
2370 * emote <emoteID>
2371 *   User has selected a visual waypoint before.
2372 *   <emoteID> is added to this waypoint. Everytime the
2373 *   NPC comes to this waypoint, the emote is called.
2374 *
2375 * emote <GUID> <WPNUM> <emoteID>
2376 *   User has not selected visual waypoint before.
2377 *   For the waypoint <WPNUM> for the NPC with <GUID>
2378 *   an emote <emoteID> is added.
2379 *   Everytime the NPC comes to this waypoint, the emote is called.
2380 *
2381 *
2382 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2383 */
2384bool ChatHandler::HandleWpModifyCommand(const char* args)
2385{
2386    sLog.outDebug("DEBUG: HandleWpModifyCommand");
2387
2388    if(!*args)
2389        return false;
2390
2391    // first arg: add del text emote spell waittime move
2392    char* show_str = strtok((char*)args, " ");
2393    if (!show_str)
2394    {
2395        return false;
2396    }
2397
2398    std::string show = show_str;
2399    // Check
2400    // Remember: "show" must also be the name of a column!
2401    if( (show != "emote") && (show != "spell") && (show != "text1") && (show != "text2")
2402        && (show != "text3") && (show != "text4") && (show != "text5")
2403        && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2404        && (show != "model1") && (show != "model2") && (show != "orientation"))
2405    {
2406        return false;
2407    }
2408
2409    // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2410
2411    // Did user provide a GUID
2412    // or did the user select a creature?
2413    // -> variable lowguid is filled with the GUID of the NPC
2414    uint32 lowguid = 0;
2415    uint32 point = 0;
2416    uint32 wpGuid = 0;
2417    Creature* target = getSelectedCreature();
2418
2419    if(target)
2420    {
2421        sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2422
2423        // Did the user select a visual spawnpoint?
2424        if (target->GetEntry() != VISUAL_WAYPOINT )
2425        {
2426            PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2427            SetSentErrorMessage(true);
2428            return false;
2429        }
2430
2431        wpGuid = target->GetGUIDLow();
2432
2433        // The visual waypoint
2434        QueryResult *result =
2435            WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2436            target->GetGUIDLow() );
2437        if(!result)
2438        {
2439            PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2440            SetSentErrorMessage(true);
2441            return false;
2442        }
2443        sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2444
2445        Field *fields = result->Fetch();
2446        lowguid = fields[0].GetUInt32();
2447        point   = fields[1].GetUInt32();
2448
2449        // Cleanup memory
2450        sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2451        delete result;
2452    }
2453    else
2454    {
2455        // User did provide <GUID> <WPNUM>
2456
2457        char* guid_str = strtok((char*)NULL, " ");
2458        if( !guid_str )
2459        {
2460            SendSysMessage(LANG_WAYPOINT_NOGUID);
2461            return false;
2462        }
2463        lowguid = atoi((char*)guid_str);
2464
2465        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2466        if(!data)
2467        {
2468            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2469            SetSentErrorMessage(true);
2470            return false;
2471        }
2472
2473        PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2474
2475        char* point_str = strtok((char*)NULL, " ");
2476        if( !point_str )
2477        {
2478            SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2479            return false;
2480        }
2481        point    = atoi((char*)point_str);
2482
2483        PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2484
2485        // Now we need the GUID of the visual waypoint
2486        // -> "del", "move", "add" command
2487
2488        QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2489        if (!result)
2490        {
2491            PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2492            SetSentErrorMessage(true);
2493            return false;
2494        }
2495
2496        Field *fields = result->Fetch();
2497        wpGuid  = fields[0].GetUInt32();
2498
2499        // Free memory
2500        delete result;
2501    }
2502
2503    char* arg_str = NULL;
2504    // Check for argument
2505    if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2506    {
2507        // Text is enclosed in "<>", all other arguments not
2508        if( show.find("text") != std::string::npos )
2509            arg_str = strtok((char*)NULL, "<>");
2510        else
2511            arg_str = strtok((char*)NULL, " ");
2512
2513        if( !arg_str)
2514        {
2515            PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2516            return false;
2517        }
2518    }
2519
2520    sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2521
2522    // wpGuid  -> GUID of the waypoint creature
2523    // lowguid -> GUID of the NPC
2524    // point   -> waypoint number
2525
2526    // Special functions:
2527    // add - move - del -> no args commands
2528    // Add a waypoint after the selected visual
2529    if(show == "add" && target)
2530    {
2531        PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2532
2533        // Get the creature for which we read the waypoint
2534        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2535        if(!data)
2536        {
2537            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2538            SetSentErrorMessage(true);
2539            return false;
2540        }
2541
2542        Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2543
2544        if( !npcCreature )
2545        {
2546            PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2547            SetSentErrorMessage(true);
2548            return false;
2549        }
2550
2551        sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2552
2553        // What to do:
2554        // Add the visual spawnpoint (DB only)
2555        // Adjust the waypoints
2556        // Respawn the owner of the waypoints
2557        sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2558
2559        Player* chr = m_session->GetPlayer();
2560        Map *map = chr->GetMap();
2561
2562        if(npcCreature)
2563        {
2564            npcCreature->GetMotionMaster()->Initialize();
2565            if(npcCreature->isAlive())                      // dead creature will reset movement generator at respawn
2566            {
2567                npcCreature->setDeathState(JUST_DIED);
2568                npcCreature->Respawn();
2569            }
2570        }
2571
2572        // create the waypoint creature
2573        wpGuid = 0;
2574        Creature* wpCreature = new Creature;
2575        if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map,VISUAL_WAYPOINT,0))
2576        {
2577            PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2578            delete wpCreature;
2579        }
2580        else
2581        {
2582            wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2583
2584            if(!wpCreature->IsPositionValid())
2585            {
2586                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());
2587                delete wpCreature;
2588            }
2589            else
2590            {
2591                wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2592                // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2593                wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2594                map->Add(wpCreature);
2595                wpGuid = wpCreature->GetGUIDLow();
2596            }
2597        }
2598
2599        WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2600
2601        if(!wpGuid)
2602            return false;
2603
2604        PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2605        return true;
2606    }                                                       // add
2607
2608    if(show == "del" && target)
2609    {
2610        PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2611
2612        // Get the creature for which we read the waypoint
2613        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2614        if(!data)
2615        {
2616            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2617            SetSentErrorMessage(true);
2618            return false;
2619        }
2620
2621        Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2622
2623        // wpCreature
2624        Creature* wpCreature = NULL;
2625        if( wpGuid != 0 )
2626        {
2627            wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2628            wpCreature->DeleteFromDB();
2629            wpCreature->CleanupsBeforeDelete();
2630            wpCreature->AddObjectToRemoveList();
2631        }
2632
2633        // What to do:
2634        // Remove the visual spawnpoint
2635        // Adjust the waypoints
2636        // Respawn the owner of the waypoints
2637
2638        WaypointMgr.DeleteNode(lowguid, point);
2639
2640        if(npcCreature)
2641        {
2642            // Any waypoints left?
2643            QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2644            if(!result2)
2645            {
2646                npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2647            }
2648            else
2649            {
2650                npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2651                delete result2;
2652            }
2653            npcCreature->GetMotionMaster()->Initialize();
2654            if(npcCreature->isAlive())                      // dead creature will reset movement generator at respawn
2655            {
2656                npcCreature->setDeathState(JUST_DIED);
2657                npcCreature->Respawn();
2658            }
2659            npcCreature->SaveToDB();
2660        }
2661
2662        PSendSysMessage(LANG_WAYPOINT_REMOVED);
2663        return true;
2664    }                                                       // del
2665
2666    if(show == "move" && target)
2667    {
2668        PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2669
2670        Player *chr = m_session->GetPlayer();
2671        Map *map = chr->GetMap();
2672        {
2673            // Get the creature for which we read the waypoint
2674            CreatureData const* data = objmgr.GetCreatureData(lowguid);
2675            if(!data)
2676            {
2677                PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2678                SetSentErrorMessage(true);
2679                return false;
2680            }
2681
2682            Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2683
2684            // wpCreature
2685            Creature* wpCreature = NULL;
2686            // What to do:
2687            // Move the visual spawnpoint
2688            // Respawn the owner of the waypoints
2689            if( wpGuid != 0 )
2690            {
2691                wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2692                wpCreature->DeleteFromDB();
2693                wpCreature->CleanupsBeforeDelete();
2694                wpCreature->AddObjectToRemoveList();
2695                // re-create
2696                Creature* wpCreature2 = new Creature;
2697                if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0))
2698                {
2699                    PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2700                    delete wpCreature2;
2701                    return false;
2702                }
2703
2704                wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2705
2706                if(!wpCreature2->IsPositionValid())
2707                {
2708                    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());
2709                    delete wpCreature2;
2710                    return false;
2711                }
2712
2713                wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2714                // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2715                wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2716                map->Add(wpCreature2);
2717                //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2);
2718            }
2719
2720            WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2721
2722            if(npcCreature)
2723            {
2724                npcCreature->GetMotionMaster()->Initialize();
2725                if(npcCreature->isAlive())                  // dead creature will reset movement generator at respawn
2726                {
2727                    npcCreature->setDeathState(JUST_DIED);
2728                    npcCreature->Respawn();
2729                }
2730            }
2731            PSendSysMessage(LANG_WAYPOINT_CHANGED);
2732        }
2733        return true;
2734    }                                                       // move
2735
2736    // Create creature - npc that has the waypoint
2737    CreatureData const* data = objmgr.GetCreatureData(lowguid);
2738    if(!data)
2739    {
2740        PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2741        SetSentErrorMessage(true);
2742        return false;
2743    }
2744
2745    WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2746
2747    Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2748    if(npcCreature)
2749    {
2750        npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2751        npcCreature->GetMotionMaster()->Initialize();
2752        if(npcCreature->isAlive())                          // dead creature will reset movement generator at respawn
2753        {
2754            npcCreature->setDeathState(JUST_DIED);
2755            npcCreature->Respawn();
2756        }
2757    }
2758    PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2759
2760    return true;
2761}
2762
2763/**
2764 * .wp show info | on | off
2765 *
2766 * info -> User has selected a visual waypoint before
2767 *
2768 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2769 *                        provided the GUID of the NPC and the number of
2770 *                        the waypoint.
2771 *
2772 * on -> User has selected an NPC; all visual waypoints for this
2773 *       NPC are added to the world
2774 *
2775 * on <GUID> -> User did not select an NPC - instead the GUID of the
2776 *              NPC is provided. All visual waypoints for this NPC
2777 *              are added from the world.
2778 *
2779 * off -> User has selected an NPC; all visual waypoints for this
2780 *        NPC are removed from the world.
2781 *
2782 * on <GUID> -> User did not select an NPC - instead the GUID of the
2783 *              NPC is provided. All visual waypoints for this NPC
2784 *              are removed from the world.
2785 *
2786 *
2787 */
2788bool ChatHandler::HandleWpShowCommand(const char* args)
2789{
2790    sLog.outDebug("DEBUG: HandleWpShowCommand");
2791
2792    if(!*args)
2793        return false;
2794
2795    // first arg: on, off, first, last
2796    char* show_str = strtok((char*)args, " ");
2797    if (!show_str)
2798    {
2799        return false;
2800    }
2801    // second arg: GUID (optional, if a creature is selected)
2802    char* guid_str = strtok((char*)NULL, " ");
2803    sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
2804    //if (!guid_str) {
2805    //    return false;
2806    //}
2807
2808    // Did user provide a GUID
2809    // or did the user select a creature?
2810    // -> variable lowguid is filled with the GUID
2811    Creature* target = getSelectedCreature();
2812    // Did player provide a GUID?
2813    if (!guid_str)
2814    {
2815        sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
2816        // No GUID provided
2817        // -> Player must have selected a creature
2818
2819        if(!target)
2820        {
2821            SendSysMessage(LANG_SELECT_CREATURE);
2822            SetSentErrorMessage(true);
2823            return false;
2824        }
2825    }
2826    else
2827    {
2828        sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
2829        // GUID provided
2830        // Warn if player also selected a creature
2831        // -> Creature selection is ignored <-
2832        if(target)
2833        {
2834            SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2835        }
2836
2837        uint32 lowguid = atoi((char*)guid_str);
2838
2839        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2840        if(!data)
2841        {
2842            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2843            SetSentErrorMessage(true);
2844            return false;
2845        }
2846
2847        target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2848
2849        if(!target)
2850        {
2851            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2852            SetSentErrorMessage(true);
2853            return false;
2854        }
2855    }
2856
2857    uint32 lowguid = target->GetDBTableGUIDLow();
2858
2859    std::string show = show_str;
2860    uint32 Maxpoint;
2861
2862    sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u", lowguid);
2863
2864    sLog.outDebug("DEBUG: HandleWpShowCommand: Habe creature: %ld", target );
2865
2866    sLog.outDebug("DEBUG: HandleWpShowCommand: wpshow - show: %s", show_str);
2867    //PSendSysMessage("wpshow - show: %s", show);
2868
2869    // Show info for the selected waypoint
2870    if(show == "info")
2871    {
2872        PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
2873
2874        // Check if the user did specify a visual waypoint
2875        if( target->GetEntry() != VISUAL_WAYPOINT )
2876        {
2877            PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2878            SetSentErrorMessage(true);
2879            return false;
2880        }
2881
2882        //PSendSysMessage("wp on, GUID: %u", lowguid);
2883
2884        //pCreature->GetPositionX();
2885
2886        QueryResult *result =
2887            WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u",
2888            target->GetGUID() );
2889        if(!result)
2890        {
2891            // Since we compare float values, we have to deal with
2892            // some difficulties.
2893            // Here we search for all waypoints that only differ in one from 1 thousand
2894            // (0.001) - There is no other way to compare C++ floats with mySQL floats
2895            // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2896            const char* maxDIFF = "0.01";
2897            PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
2898
2899            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 )",
2900                target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2901            if(!result)
2902            {
2903                PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2904                SetSentErrorMessage(true);
2905                return false;
2906            }
2907        }
2908        do
2909        {
2910            Field *fields = result->Fetch();
2911            uint32 creGUID          = fields[0].GetUInt32();
2912            uint32 point            = fields[1].GetUInt32();
2913            int waittime            = fields[2].GetUInt32();
2914            uint32 emote            = fields[3].GetUInt32();
2915            uint32 spell            = fields[4].GetUInt32();
2916            const char * text1      = fields[5].GetString();
2917            const char * text2      = fields[6].GetString();
2918            const char * text3      = fields[7].GetString();
2919            const char * text4      = fields[8].GetString();
2920            const char * text5      = fields[9].GetString();
2921            uint32 model1           = fields[10].GetUInt32();
2922            uint32 model2           = fields[11].GetUInt32();
2923
2924            // Get the creature for which we read the waypoint
2925            Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2926
2927            PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
2928            PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
2929            PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
2930            PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
2931            PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
2932            PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
2933            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 1, text1);
2934            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 2, text2);
2935            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 3, text3);
2936            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 4, text4);
2937            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 5, text5);
2938
2939        }while( result->NextRow() );
2940        // Cleanup memory
2941        delete result;
2942        return true;
2943    }
2944
2945    if(show == "on")
2946    {
2947        PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
2948
2949        QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
2950        if(!result)
2951        {
2952            PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
2953            SetSentErrorMessage(true);
2954            return false;
2955        }
2956        // Delete all visuals for this NPC
2957        QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
2958        if(result2)
2959        {
2960            bool hasError = false;
2961            do
2962            {
2963                Field *fields = result2->Fetch();
2964                uint32 wpguid = fields[0].GetUInt32();
2965                Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2966
2967                if(!pCreature)
2968                {
2969                    PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
2970                    hasError = true;
2971                    WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
2972                }
2973                else
2974                {
2975                    pCreature->DeleteFromDB();
2976                    pCreature->CleanupsBeforeDelete();
2977                    pCreature->AddObjectToRemoveList();
2978                }
2979
2980            }while( result2->NextRow() );
2981            delete result2;
2982            if( hasError )
2983            {
2984                PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
2985                PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
2986                PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
2987            }
2988        }
2989
2990        do
2991        {
2992            Field *fields = result->Fetch();
2993            uint32 point    = fields[0].GetUInt32();
2994            float x         = fields[1].GetFloat();
2995            float y         = fields[2].GetFloat();
2996            float z         = fields[3].GetFloat();
2997
2998            uint32 id = VISUAL_WAYPOINT;
2999
3000            Player *chr = m_session->GetPlayer();
3001            Map *map = chr->GetMap();
3002            float o = chr->GetOrientation();
3003
3004            Creature* wpCreature = new Creature;
3005            if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
3006            {
3007                PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3008                delete wpCreature;
3009                delete result;
3010                return false;
3011            }
3012
3013            wpCreature->Relocate(x, y, z, o);
3014
3015            if(!wpCreature->IsPositionValid())
3016            {
3017                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());
3018                delete wpCreature;
3019                delete result;
3020                return false;
3021            }
3022
3023            wpCreature->SetVisibility(VISIBILITY_OFF);
3024            sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
3025            // set "wpguid" column to the visual waypoint
3026            WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
3027
3028            wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3029            // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
3030            wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
3031            map->Add(wpCreature);
3032            //MapManager::Instance().GetMap(wpCreature->GetMapId())->Add(wpCreature);
3033        }while( result->NextRow() );
3034
3035        // Cleanup memory
3036        delete result;
3037        return true;
3038    }
3039
3040    if(show == "first")
3041    {
3042        PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3043
3044        QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3045        if(!result)
3046        {
3047            PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3048            SetSentErrorMessage(true);
3049            return false;
3050        }
3051
3052        Field *fields = result->Fetch();
3053        float x         = fields[0].GetFloat();
3054        float y         = fields[1].GetFloat();
3055        float z         = fields[2].GetFloat();
3056        uint32 id = VISUAL_WAYPOINT;
3057
3058        Player *chr = m_session->GetPlayer();
3059        float o = chr->GetOrientation();
3060        Map *map = chr->GetMap();
3061
3062        Creature* pCreature = new Creature;
3063        if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, id, 0))
3064        {
3065            PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3066            delete pCreature;
3067            delete result;
3068            return false;
3069        }
3070
3071        pCreature->Relocate(x, y, z, o);
3072
3073        if(!pCreature->IsPositionValid())
3074        {
3075            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());
3076            delete pCreature;
3077            delete result;
3078            return false;
3079        }
3080
3081        pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3082        pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3083        map->Add(pCreature);
3084        //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3085
3086        // Cleanup memory
3087        delete result;
3088        return true;
3089    }
3090
3091    if(show == "last")
3092    {
3093        PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3094
3095        QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3096        if( result )
3097        {
3098            Maxpoint = (*result)[0].GetUInt32();
3099
3100            delete result;
3101        }
3102        else
3103            Maxpoint = 0;
3104
3105        result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3106        if(!result)
3107        {
3108            PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3109            SetSentErrorMessage(true);
3110            return false;
3111        }
3112        Field *fields = result->Fetch();
3113        float x         = fields[0].GetFloat();
3114        float y         = fields[1].GetFloat();
3115        float z         = fields[2].GetFloat();
3116        uint32 id = VISUAL_WAYPOINT;
3117
3118        Player *chr = m_session->GetPlayer();
3119        float o = chr->GetOrientation();
3120        Map *map = chr->GetMap();
3121
3122        Creature* pCreature = new Creature;
3123        if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
3124        {
3125            PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3126            delete pCreature;
3127            delete result;
3128            return false;
3129        }
3130
3131        pCreature->Relocate(x, y, z, o);
3132
3133        if(!pCreature->IsPositionValid())
3134        {
3135            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());
3136            delete pCreature;
3137            delete result;
3138            return false;
3139        }
3140
3141        pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3142        pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3143        map->Add(pCreature);
3144        //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3145        // Cleanup memory
3146        delete result;
3147        return true;
3148    }
3149
3150    if(show == "off")
3151    {
3152        QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3153        if(!result)
3154        {
3155            SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3156            SetSentErrorMessage(true);
3157            return false;
3158        }
3159        bool hasError = false;
3160        do
3161        {
3162            Field *fields = result->Fetch();
3163            uint32 guid = fields[0].GetUInt32();
3164            Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3165
3166            //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
3167
3168            if(!pCreature)
3169            {
3170                PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3171                hasError = true;
3172                WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3173            }
3174            else
3175            {
3176                pCreature->DeleteFromDB();
3177                pCreature->CleanupsBeforeDelete();
3178                pCreature->AddObjectToRemoveList();
3179            }
3180        }while(result->NextRow());
3181        // set "wpguid" column to "empty" - no visual waypoint spawned
3182        WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'");
3183
3184        if( hasError )
3185        {
3186            PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3187            PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3188            PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3189        }
3190
3191        SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3192        // Cleanup memory
3193        delete result;
3194
3195        return true;
3196    }
3197
3198    PSendSysMessage("DEBUG: wpshow - no valid command found");
3199
3200    return true;
3201}                                                           // HandleWpShowCommand
3202
3203bool ChatHandler::HandleWpExportCommand(const char *args)
3204{
3205    if(!*args)
3206        return false;
3207
3208    // Next arg is: <GUID> <ARGUMENT>
3209
3210    // Did user provide a GUID
3211    // or did the user select a creature?
3212    // -> variable lowguid is filled with the GUID of the NPC
3213    uint32 lowguid = 0;
3214    Creature* target = getSelectedCreature();
3215    char* arg_str = NULL;
3216    if (target)
3217    {
3218        if (target->GetEntry() != VISUAL_WAYPOINT)
3219            lowguid = target->GetGUIDLow();
3220        else
3221        {
3222            QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3223            if (!result)
3224            {
3225                PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3226                return true;
3227            }
3228            Field *fields = result->Fetch();
3229            lowguid = fields[0].GetUInt32();;
3230            delete result;
3231        }
3232
3233        arg_str = strtok((char*)args, " ");
3234    }
3235    else
3236    {
3237        // user provided <GUID>
3238        char* guid_str = strtok((char*)args, " ");
3239        if( !guid_str )
3240        {
3241            SendSysMessage(LANG_WAYPOINT_NOGUID);
3242            return false;
3243        }
3244        lowguid = atoi((char*)guid_str);
3245
3246        arg_str = strtok((char*)NULL, " ");
3247    }
3248
3249    if( !arg_str)
3250    {
3251        PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3252        return false;
3253    }
3254
3255    PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3256
3257    QueryResult *result = WorldDatabase.PQuery(
3258    //          0      1           2           3           4            5       6       7         8      9      10     11     12     13     14     15
3259        "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 );
3260
3261    if (!result)
3262    {
3263        PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3264        SetSentErrorMessage(true);
3265        return false;
3266    }
3267
3268    std::ofstream outfile;
3269    outfile.open (arg_str);
3270
3271    do
3272    {
3273        Field *fields = result->Fetch();
3274
3275        outfile << "INSERT INTO creature_movement ";
3276        outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5 ) VALUES ";
3277
3278        outfile << "( ";
3279        outfile << fields[15].GetUInt32();                  // id
3280        outfile << ", ";
3281        outfile << fields[0].GetUInt32();                   // point
3282        outfile << ", ";
3283        outfile << fields[1].GetFloat();                    // position_x
3284        outfile << ", ";
3285        outfile << fields[2].GetFloat();                    // position_y
3286        outfile << ", ";
3287        outfile << fields[3].GetUInt32();                   // position_z
3288        outfile << ", ";
3289        outfile << fields[4].GetUInt32();                   // orientation
3290        outfile << ", ";
3291        outfile << fields[5].GetUInt32();                   // model1
3292        outfile << ", ";
3293        outfile << fields[6].GetUInt32();                   // model2
3294        outfile << ", ";
3295        outfile << fields[7].GetUInt16();                   // waittime
3296        outfile << ", ";
3297        outfile << fields[8].GetUInt32();                   // emote
3298        outfile << ", ";
3299        outfile << fields[9].GetUInt32();                   // spell
3300        outfile << ", ";
3301        const char *tmpChar = fields[10].GetString();
3302        if( !tmpChar )
3303        {
3304            outfile << "NULL";                              // text1
3305        }
3306        else
3307        {
3308            outfile << "'";
3309            outfile << tmpChar;                             // text1
3310            outfile << "'";
3311        }
3312        outfile << ", ";
3313        tmpChar = fields[11].GetString();
3314        if( !tmpChar )
3315        {
3316            outfile << "NULL";                              // text2
3317        }
3318        else
3319        {
3320            outfile << "'";
3321            outfile << tmpChar;                             // text2
3322            outfile << "'";
3323        }
3324        outfile << ", ";
3325        tmpChar = fields[12].GetString();
3326        if( !tmpChar )
3327        {
3328            outfile << "NULL";                              // text3
3329        }
3330        else
3331        {
3332            outfile << "'";
3333            outfile << tmpChar;                             // text3
3334            outfile << "'";
3335        }
3336        outfile << ", ";
3337        tmpChar = fields[13].GetString();
3338        if( !tmpChar )
3339        {
3340            outfile << "NULL";                              // text4
3341        }
3342        else
3343        {
3344            outfile << "'";
3345            outfile << tmpChar;                             // text4
3346            outfile << "'";
3347        }
3348        outfile << ", ";
3349        tmpChar = fields[14].GetString();
3350        if( !tmpChar )
3351        {
3352            outfile << "NULL";                              // text5
3353        }
3354        else
3355        {
3356            outfile << "'";
3357            outfile << tmpChar;                             // text5
3358            outfile << "'";
3359        }
3360        outfile << ");\n ";
3361
3362    } while( result->NextRow() );
3363    delete result;
3364
3365    PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3366    outfile.close();
3367
3368    return true;
3369}
3370
3371bool ChatHandler::HandleWpImportCommand(const char *args)
3372{
3373    if(!*args)
3374        return false;
3375
3376    char* arg_str = strtok((char*)args, " ");
3377    if (!arg_str)
3378        return false;
3379
3380    std::string line;
3381    std::ifstream infile (arg_str);
3382    if (infile.is_open())
3383    {
3384        while (! infile.eof() )
3385        {
3386            getline (infile,line);
3387            //cout << line << endl;
3388            QueryResult *result = WorldDatabase.PQuery(line.c_str());
3389            delete result;
3390        }
3391        infile.close();
3392    }
3393    PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3394
3395    return true;
3396}
3397
3398//rename characters
3399bool ChatHandler::HandleRenameCommand(const char* args)
3400{
3401    Player* target = NULL;
3402    uint64 targetGUID = 0;
3403    std::string oldname;
3404
3405    char* px = strtok((char*)args, " ");
3406
3407    if(px)
3408    {
3409        oldname = px;
3410
3411        if(!normalizePlayerName(oldname))
3412        {
3413            SendSysMessage(LANG_PLAYER_NOT_FOUND);
3414            SetSentErrorMessage(true);
3415            return false;
3416        }
3417
3418        target = objmgr.GetPlayer(oldname.c_str());
3419
3420        if (!target)
3421            targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3422    }
3423
3424    if(!target && !targetGUID)
3425    {
3426        target = getSelectedPlayer();
3427    }
3428
3429    if(!target && !targetGUID)
3430    {
3431        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3432        SetSentErrorMessage(true);
3433        return false;
3434    }
3435
3436    if(target)
3437    {
3438        PSendSysMessage(LANG_RENAME_PLAYER, target->GetName());
3439        target->SetAtLoginFlag(AT_LOGIN_RENAME);
3440        CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3441    }
3442    else
3443    {
3444        PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
3445        CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3446    }
3447
3448    return true;
3449}
3450
3451//spawn go
3452bool ChatHandler::HandleGameObjectCommand(const char* args)
3453{
3454    if (!*args)
3455        return false;
3456
3457    char* pParam1 = strtok((char*)args, " ");
3458    if (!pParam1)
3459        return false;
3460
3461    uint32 id = atoi((char*)pParam1);
3462    if(!id)
3463        return false;
3464
3465    char* spawntimeSecs = strtok(NULL, " ");
3466
3467    const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id);
3468
3469    if (!goI)
3470    {
3471        PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
3472        SetSentErrorMessage(true);
3473        return false;
3474    }
3475
3476    Player *chr = m_session->GetPlayer();
3477    float x = float(chr->GetPositionX());
3478    float y = float(chr->GetPositionY());
3479    float z = float(chr->GetPositionZ());
3480    float o = float(chr->GetOrientation());
3481    Map *map = chr->GetMap();
3482
3483    float rot2 = sin(o/2);
3484    float rot3 = cos(o/2);
3485
3486    GameObject* pGameObj = new GameObject;
3487    uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
3488
3489    if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1))
3490    {
3491        delete pGameObj;
3492        return false;
3493    }
3494
3495    if( spawntimeSecs )
3496    {
3497        uint32 value = atoi((char*)spawntimeSecs);
3498        pGameObj->SetRespawnTime(value);
3499        //sLog.outDebug("*** spawntimeSecs: %d", value);
3500    }
3501
3502    // fill the gameobject data and save to the db
3503    pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3504
3505    // this will generate a new guid if the object is in an instance
3506    if(!pGameObj->LoadFromDB(db_lowGUID, map))
3507    {
3508        delete pGameObj;
3509        return false;
3510    }
3511
3512    sLog.outDebug(GetTrinityString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o);
3513
3514    map->Add(pGameObj);
3515
3516    // TODO: is it really necessary to add both the real and DB table guid here ?
3517    objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
3518
3519    PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z);
3520    return true;
3521}
3522
3523//show animation
3524bool ChatHandler::HandleAnimCommand(const char* args)
3525{
3526    if (!*args)
3527        return false;
3528
3529    uint32 anim_id = atoi((char*)args);
3530    m_session->GetPlayer()->HandleEmoteCommand(anim_id);
3531    return true;
3532}
3533
3534//change standstate
3535bool ChatHandler::HandleStandStateCommand(const char* args)
3536{
3537    if (!*args)
3538        return false;
3539
3540    uint32 anim_id = atoi((char*)args);
3541    m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3542
3543    return true;
3544}
3545
3546bool ChatHandler::HandleAddHonorCommand(const char* args)
3547{
3548    if (!*args)
3549        return false;
3550
3551    Player *target = getSelectedPlayer();
3552    if(!target)
3553    {
3554        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3555        SetSentErrorMessage(true);
3556        return false;
3557    }
3558
3559    uint32 amount = (uint32)atoi(args);
3560    target->RewardHonor(NULL, 1, amount);
3561    return true;
3562}
3563
3564bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3565{
3566    Unit *target = getSelectedUnit();
3567    if(!target)
3568    {
3569        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3570        SetSentErrorMessage(true);
3571        return false;
3572    }
3573
3574    m_session->GetPlayer()->RewardHonor(target, 1);
3575    return true;
3576}
3577
3578bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/)
3579{
3580    Player *target = getSelectedPlayer();
3581    if(!target)
3582    {
3583        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3584        SetSentErrorMessage(true);
3585        return false;
3586    }
3587
3588    target->UpdateHonorFields();
3589    return true;
3590}
3591
3592bool ChatHandler::HandleLookupEventCommand(const char* args)
3593{
3594    if(!*args)
3595        return false;
3596
3597    std::string namepart = args;
3598    std::wstring wnamepart;
3599
3600    // converting string that we try to find to lower case
3601    if(!Utf8toWStr(namepart,wnamepart))
3602        return false;
3603
3604    wstrToLower(wnamepart);
3605
3606    uint32 counter = 0;
3607
3608    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3609    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3610
3611    for(uint32 id = 0; id < events.size(); ++id )
3612    {
3613        GameEventData const& eventData = events[id];
3614
3615        std::string descr = eventData.description;
3616        if(descr.empty())
3617            continue;
3618
3619        if (Utf8FitTo(descr, wnamepart))
3620        {
3621            char const* active = activeEvents.find(id) != activeEvents.end() ? GetTrinityString(LANG_ACTIVE) : "";
3622           
3623                        if(m_session)
3624                                PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3625                        else
3626                                PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3627
3628            ++counter;
3629        }
3630    }
3631
3632    if (counter==0)
3633        SendSysMessage(LANG_NOEVENTFOUND);
3634
3635    return true;
3636}
3637
3638bool ChatHandler::HandleEventActiveListCommand(const char* args)
3639{
3640    uint32 counter = 0;
3641
3642    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3643    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3644
3645    char const* active = GetTrinityString(LANG_ACTIVE);
3646
3647    for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
3648    {
3649        uint32 event_id = *itr;
3650        GameEventData const& eventData = events[event_id];
3651
3652        if(m_session)
3653                        PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
3654                else
3655                        PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
3656
3657        ++counter;
3658    }
3659
3660    if (counter==0)
3661        SendSysMessage(LANG_NOEVENTFOUND);
3662
3663    return true;
3664}
3665
3666bool ChatHandler::HandleEventInfoCommand(const char* args)
3667{
3668    if(!*args)
3669        return false;
3670
3671    // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3672    char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3673    if(!cId)
3674        return false;
3675
3676    uint32 event_id = atoi(cId);
3677
3678    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3679
3680    if(event_id >=events.size())
3681    {
3682        SendSysMessage(LANG_EVENT_NOT_EXIST);
3683        SetSentErrorMessage(true);
3684        return false;
3685    }
3686
3687    GameEventData const& eventData = events[event_id];
3688    if(!eventData.isValid())
3689    {
3690        SendSysMessage(LANG_EVENT_NOT_EXIST);
3691        SetSentErrorMessage(true);
3692        return false;
3693    }
3694
3695    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3696    bool active = activeEvents.find(event_id) != activeEvents.end();
3697    char const* activeStr = active ? GetTrinityString(LANG_ACTIVE) : "";
3698
3699    std::string startTimeStr = TimeToTimestampStr(eventData.start);
3700    std::string endTimeStr = TimeToTimestampStr(eventData.end);
3701
3702    uint32 delay = gameeventmgr.NextCheck(event_id);
3703    time_t nextTime = time(NULL)+delay;
3704    std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3705
3706    std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3707    std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3708
3709    PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3710        startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3711        nextStr.c_str());
3712    return true;
3713}
3714
3715bool ChatHandler::HandleEventStartCommand(const char* args)
3716{
3717    if(!*args)
3718        return false;
3719
3720    // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3721    char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3722    if(!cId)
3723        return false;
3724
3725    int32 event_id = atoi(cId);
3726
3727    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3728
3729    if(event_id < 1 || event_id >=events.size())
3730    {
3731        SendSysMessage(LANG_EVENT_NOT_EXIST);
3732        SetSentErrorMessage(true);
3733        return false;
3734    }
3735
3736    GameEventData const& eventData = events[event_id];
3737    if(!eventData.isValid())
3738    {
3739        SendSysMessage(LANG_EVENT_NOT_EXIST);
3740        SetSentErrorMessage(true);
3741        return false;
3742    }
3743
3744    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3745    if(activeEvents.find(event_id) != activeEvents.end())
3746    {
3747        PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3748        SetSentErrorMessage(true);
3749        return false;
3750    }
3751
3752    gameeventmgr.StartEvent(event_id,true);
3753    return true;
3754}
3755
3756bool ChatHandler::HandleEventStopCommand(const char* args)
3757{
3758    if(!*args)
3759        return false;
3760
3761    // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3762    char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3763    if(!cId)
3764        return false;
3765
3766    int32 event_id = atoi(cId);
3767
3768    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3769
3770    if(event_id < 1 || event_id >=events.size())
3771    {
3772        SendSysMessage(LANG_EVENT_NOT_EXIST);
3773        SetSentErrorMessage(true);
3774        return false;
3775    }
3776
3777    GameEventData const& eventData = events[event_id];
3778    if(!eventData.isValid())
3779    {
3780        SendSysMessage(LANG_EVENT_NOT_EXIST);
3781        SetSentErrorMessage(true);
3782        return false;
3783    }
3784
3785    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3786
3787    if(activeEvents.find(event_id) == activeEvents.end())
3788    {
3789        PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3790        SetSentErrorMessage(true);
3791        return false;
3792    }
3793
3794    gameeventmgr.StopEvent(event_id,true);
3795    return true;
3796}
3797
3798bool ChatHandler::HandleCombatStopCommand(const char* args)
3799{
3800    Player *player;
3801
3802    if(*args)
3803    {
3804        std::string playername = args;
3805
3806        if(!normalizePlayerName(playername))
3807        {
3808            SendSysMessage(LANG_PLAYER_NOT_FOUND);
3809            SetSentErrorMessage(true);
3810            return false;
3811        }
3812
3813        player = objmgr.GetPlayer(playername.c_str());
3814
3815        if(!player)
3816        {
3817            SendSysMessage(LANG_PLAYER_NOT_FOUND);
3818            SetSentErrorMessage(true);
3819            return false;
3820        }
3821    }
3822    else
3823    {
3824        player = getSelectedPlayer();
3825
3826        if (!player)
3827            player = m_session->GetPlayer();
3828    }
3829
3830    player->CombatStop();
3831    player->getHostilRefManager().deleteReferences();
3832    return true;
3833}
3834
3835bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3836{
3837    uint32 classmask = m_session->GetPlayer()->getClassMask();
3838
3839    for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3840    {
3841        SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3842        if( !skillInfo )
3843            continue;
3844
3845        if( skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY )
3846        {
3847            for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3848            {
3849                SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3850                if( !skillLine )
3851                    continue;
3852
3853                // skip racial skills
3854                if( skillLine->racemask != 0 )
3855                    continue;
3856
3857                // skip wrong class skills
3858                if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3859                    continue;
3860
3861                if( skillLine->skillId != i || skillLine->forward_spellid )
3862                    continue;
3863
3864                SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3865                if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3866                    continue;
3867
3868                m_session->GetPlayer()->learnSpell(skillLine->spellId);
3869            }
3870        }
3871    }
3872
3873    SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
3874    return true;
3875}
3876
3877bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
3878{
3879    //  Learns all recipes of specified profession and sets skill to max
3880    //  Example: .learn all_recipes enchanting
3881
3882    Player* target = getSelectedPlayer();
3883    if( !target )
3884    {
3885        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3886        return false;
3887    }
3888
3889    if (!*args)
3890        return false;
3891
3892    std::wstring wnamepart;
3893
3894    if(!Utf8toWStr(args,wnamepart))
3895        return false;
3896
3897    uint32 counter = 0;                                     // Counter for figure out that we found smth.
3898
3899    // converting string that we try to find to lower case
3900    wstrToLower( wnamepart );
3901
3902    uint32 classmask = m_session->GetPlayer()->getClassMask();
3903
3904    for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3905    {
3906        SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3907        if( !skillInfo )
3908            continue;
3909
3910        if( skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
3911            skillInfo->categoryId != SKILL_CATEGORY_SECONDARY )
3912            continue;
3913
3914        int loc = m_session->GetSessionDbcLocale();
3915        std::string name = skillInfo->name[loc];
3916
3917        if(Utf8FitTo(name, wnamepart))
3918        {
3919            for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3920            {
3921                SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3922                if( !skillLine )
3923                    continue;
3924
3925                if( skillLine->skillId != i || skillLine->forward_spellid )
3926                    continue;
3927
3928                // skip racial skills
3929                if( skillLine->racemask != 0 )
3930                    continue;
3931
3932                // skip wrong class skills
3933                if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3934                    continue;
3935
3936                SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3937                if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3938                    continue;
3939
3940                if( !target->HasSpell(spellInfo->Id) )
3941                    m_session->GetPlayer()->learnSpell(skillLine->spellId);
3942            }
3943
3944            uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
3945            target->SetSkill(skillInfo->id, maxLevel, maxLevel);
3946            PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
3947            return true;
3948        }
3949    }
3950
3951    return false;
3952}
3953
3954bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
3955{
3956 
3957    if (!*args)
3958        return false;
3959
3960    std::string ip = strtok ((char*)args, " ");
3961        char* limit_str = strtok (NULL, " ");
3962        int32 limit = limit_str ? atoi (limit_str) : -1;
3963
3964    loginDatabase.escape_string (ip);
3965
3966    QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
3967
3968    return LookupPlayerSearchCommand (result,limit);
3969}
3970
3971bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
3972{
3973    if (!*args)
3974        return false;
3975
3976    std::string account = strtok ((char*)args, " ");
3977        char* limit_str = strtok (NULL, " ");
3978        int32 limit = limit_str ? atoi (limit_str) : -1;
3979
3980    if (!AccountMgr::normilizeString (account))
3981        return false;
3982
3983    loginDatabase.escape_string (account);
3984
3985    QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
3986
3987    return LookupPlayerSearchCommand (result,limit);
3988}
3989
3990bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
3991{
3992 
3993    if (!*args)
3994        return false;
3995
3996    std::string email = strtok ((char*)args, " ");
3997        char* limit_str = strtok (NULL, " ");
3998        int32 limit = limit_str ? atoi (limit_str) : -1;
3999
4000    loginDatabase.escape_string (email);
4001
4002    QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
4003
4004    return LookupPlayerSearchCommand (result,limit);
4005}
4006
4007bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
4008{
4009    if(!result)
4010    {
4011        PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4012        SetSentErrorMessage(true);
4013        return false;
4014    }
4015
4016    int i =0;
4017    do
4018    {
4019        Field* fields = result->Fetch();
4020        uint32 acc_id = fields[0].GetUInt32();
4021        std::string acc_name = fields[1].GetCppString();
4022       
4023        QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
4024        if(chars)
4025        {
4026            PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4027
4028            uint64 guid = 0;
4029            std::string name;
4030
4031            do
4032            {
4033                Field* charfields = chars->Fetch();
4034                guid = charfields[0].GetUInt64();
4035                name = charfields[1].GetCppString();
4036
4037                PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
4038                ++i;
4039
4040            } while( chars->NextRow() && ( limit == -1 || i < limit ) );
4041
4042            delete chars;
4043        }
4044    } while(result->NextRow());
4045
4046    delete result;
4047
4048    return true;
4049}
4050
4051/// Triggering corpses expire check in world
4052bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4053{
4054        CorpsesErase();
4055        return true;
4056}
4057
4058bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
4059{
4060    Player *target = getSelectedPlayer();
4061
4062    if(!target)
4063    {
4064        PSendSysMessage(LANG_NO_CHAR_SELECTED);
4065        SetSentErrorMessage(true);
4066        return false;
4067        }
4068
4069    // Repair items
4070    target->DurabilityRepairAll(false, 0, false);
4071
4072    PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName());
4073    if(needReportToTarget(target))
4074        ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName());
4075    return true;
4076}
4077
4078bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
4079{
4080    Player *player = m_session->GetPlayer();
4081    Creature *creature = getSelectedCreature();
4082
4083    if(!creature)
4084    {
4085        PSendSysMessage(LANG_SELECT_CREATURE);
4086        SetSentErrorMessage(true);
4087        return false;
4088    }
4089
4090    // Follow player - Using pet's default dist and angle
4091    creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
4092
4093    PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
4094    return true;
4095}
4096
4097bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
4098{
4099    Player *player = m_session->GetPlayer();
4100    Creature *creature = getSelectedCreature();
4101
4102    if(!creature)
4103    {
4104        PSendSysMessage(LANG_SELECT_CREATURE);
4105        SetSentErrorMessage(true);
4106        return false;
4107    }
4108
4109    if (creature->GetMotionMaster()->empty() ||
4110        creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
4111    {
4112        PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4113        SetSentErrorMessage(true);
4114        return false;
4115    }
4116
4117    TargetedMovementGenerator<Creature> const* mgen
4118        = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
4119
4120    if(mgen->GetTarget()!=player)
4121    {
4122        PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4123        SetSentErrorMessage(true);
4124        return false;
4125    }
4126
4127    // reset movement
4128    creature->GetMotionMaster()->MovementExpired(true);
4129
4130    PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
4131    return true;
4132}
Note: See TracBrowser for help on using the browser.