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

Revision 177, 126.4 kB (checked in by yumileroy, 17 years ago)

[svn] * Avoid access to bag item prototype for getting bag size, use related item
update field instead as more fast source. source mangos.
* Further reduce of DB access in guild handlers.
* Multi-locale DBC extracting - source Foks

*** Devs not responsible if all your player items drop to the ground and get eaten by ants or rabbits.. or some kind of wierd ant-rabbits..

Original author: KingPin?
Date: 2008-11-06 08:20:26-06: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    if(srcslot==dstslot)
864        return true;
865       
866    uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
867    uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
868
869    m_session->GetPlayer()->SwapItem( src, dst );
870
871    return true;
872}
873
874//add spawn of creature
875bool ChatHandler::HandleNpcAddCommand(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::HandleNpcDeleteCommand(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::HandleNpcMoveCommand(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::HandleNpcAddMoveCommand(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::HandleNpcSetMoveTypeCommand(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}                                                           // HandleNpcSetMoveTypeCommand
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::HandleNpcSetModelCommand(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
1636bool ChatHandler::HandleNpcFactionIdCommand(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        QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", targetGUID);
1799        if (!result)
1800        {
1801            SendSysMessage(LANG_PLAYER_NOT_FOUND);
1802            SetSentErrorMessage(true);
1803            return false;
1804        }
1805        Field *fields = result->Fetch();
1806        total_player_time = fields[0].GetUInt32();
1807        delete result;
1808       
1809        Tokens data;
1810        if (!Player::LoadValuesArrayFromDB(data,targetGUID))
1811        {
1812            SendSysMessage(LANG_PLAYER_NOT_FOUND);
1813            SetSentErrorMessage(true);
1814            return false;
1815        }
1816       
1817        money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE);
1818        level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL);
1819        accId = objmgr.GetPlayerAccountIdByGUID(targetGUID);
1820    }
1821
1822    std::string username = GetTrinityString(LANG_ERROR);
1823    std::string last_ip = GetTrinityString(LANG_ERROR);
1824    uint32 security = 0;
1825    std::string last_login = GetTrinityString(LANG_ERROR);
1826
1827    QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,last_ip,last_login FROM account WHERE id = '%u'",accId);
1828    if(result)
1829    {
1830        Field* fields = result->Fetch();
1831        username = fields[0].GetCppString();
1832        security = fields[1].GetUInt32();
1833       
1834                if(!m_session || m_session->GetSecurity() >= security)
1835        {
1836            last_ip = fields[2].GetCppString();
1837            last_login = fields[3].GetCppString();
1838        }
1839        else
1840        {
1841            last_ip = "-";
1842            last_login = "-";
1843        }
1844
1845        delete result;
1846    }
1847
1848    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);
1849
1850    std::string timeStr = secsToTimeString(total_player_time,true,true);
1851    uint32 gold = money /GOLD;
1852    uint32 silv = (money % GOLD) / SILVER;
1853    uint32 copp = (money % GOLD) % SILVER;
1854    PSendSysMessage(LANG_PINFO_LEVEL,  timeStr.c_str(), level, gold,silv,copp );
1855
1856    if ( py && strncmp(py, "rep", 3) == 0 )
1857    {
1858        if(!target)
1859        {
1860            // rep option not implemented for offline case
1861            SendSysMessage(LANG_PINFO_NO_REP);
1862            SetSentErrorMessage(true);
1863            return false;
1864        }
1865
1866        char* FactionName;
1867        for(FactionStateList::const_iterator itr = target->m_factions.begin(); itr != target->m_factions.end(); ++itr)
1868        {
1869            FactionEntry const *factionEntry = sFactionStore.LookupEntry(itr->second.ID);
1870            if (factionEntry)
1871                FactionName = factionEntry->name[m_session->GetSessionDbcLocale()];
1872            else
1873                FactionName = "#Not found#";
1874            ReputationRank rank = target->GetReputationRank(factionEntry);
1875            std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]);
1876            std::ostringstream ss;
1877            ss << itr->second.ID << ": |cffffffff|Hfaction:" << itr->second.ID << "|h[" << FactionName << "]|h|r " << rankName << "|h|r (" << target->GetReputation(factionEntry) << ")";
1878
1879            if(itr->second.Flags & FACTION_FLAG_VISIBLE)
1880                ss << GetTrinityString(LANG_FACTION_VISIBLE);
1881            if(itr->second.Flags & FACTION_FLAG_AT_WAR)
1882                ss << GetTrinityString(LANG_FACTION_ATWAR);
1883            if(itr->second.Flags & FACTION_FLAG_PEACE_FORCED)
1884                ss << GetTrinityString(LANG_FACTION_PEACE_FORCED);
1885            if(itr->second.Flags & FACTION_FLAG_HIDDEN)
1886                ss << GetTrinityString(LANG_FACTION_HIDDEN);
1887            if(itr->second.Flags & FACTION_FLAG_INVISIBLE_FORCED)
1888                ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED);
1889            if(itr->second.Flags & FACTION_FLAG_INACTIVE)
1890                ss << GetTrinityString(LANG_FACTION_INACTIVE);
1891
1892            SendSysMessage(ss.str().c_str());
1893        }
1894    }
1895    return true;
1896}
1897
1898//show tickets
1899void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time)
1900{
1901    std::string name;
1902    if(!objmgr.GetPlayerNameByGUID(guid,name))
1903        name = GetTrinityString(LANG_UNKNOWN);
1904
1905    PSendSysMessage(LANG_COMMAND_TICKETVIEW, name.c_str(),time,text);
1906}
1907
1908//ticket commands
1909bool ChatHandler::HandleTicketCommand(const char* args)
1910{
1911    char* px = strtok((char*)args, " ");
1912
1913    // ticket<end>
1914    if (!px)
1915    {
1916                if(!m_session)
1917                {
1918                        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1919                        SetSentErrorMessage(true);
1920                        return false;
1921                }
1922
1923        size_t count;
1924        QueryResult *result = CharacterDatabase.Query("SELECT COUNT(ticket_id) FROM character_ticket");
1925        if(result)
1926        {
1927            count = (*result)[0].GetUInt32();
1928            delete result;
1929        }
1930        else
1931            count = 0;
1932
1933        bool accept = m_session->GetPlayer()->isAcceptTickets();
1934               
1935                PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ?  GetTrinityString(LANG_ON) : GetTrinityString(LANG_OFF));
1936        return true;
1937    }
1938
1939    // ticket on
1940    if(strncmp(px,"on",3) == 0)
1941    {
1942                if(!m_session)
1943                {
1944                        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1945                        SetSentErrorMessage(true);
1946                        return false;
1947                }
1948
1949        m_session->GetPlayer()->SetAcceptTicket(true);
1950        SendSysMessage(LANG_COMMAND_TICKETON);
1951        return true;
1952    }
1953
1954    // ticket off
1955    if(strncmp(px,"off",4) == 0)
1956    {
1957                if(!m_session)
1958                {
1959                        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1960                        SetSentErrorMessage(true);
1961                        return false;
1962                }
1963
1964        m_session->GetPlayer()->SetAcceptTicket(false);
1965        SendSysMessage(LANG_COMMAND_TICKETOFF);
1966        return true;
1967    }
1968
1969    // ticket #num
1970    int num = atoi(px);
1971    if(num > 0)
1972    {
1973        QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1);
1974
1975        if(!result)
1976        {
1977            PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
1978            delete result;
1979            SetSentErrorMessage(true);
1980            return false;
1981        }
1982
1983        Field* fields = result->Fetch();
1984
1985        uint64 guid = fields[0].GetUInt64();
1986        char const* text = fields[1].GetString();
1987        char const* time = fields[2].GetString();
1988
1989        ShowTicket(guid,text,time);
1990        delete result;
1991        return true;
1992    }
1993
1994    std::string name = px;
1995
1996    if(!normalizePlayerName(name))
1997    {
1998        SendSysMessage(LANG_PLAYER_NOT_FOUND);
1999        SetSentErrorMessage(true);
2000        return false;
2001    }
2002
2003    uint64 guid = objmgr.GetPlayerGUIDByName(name);
2004
2005    if(!guid)
2006        return false;
2007
2008    // ticket $char_name
2009    QueryResult *result = CharacterDatabase.PQuery("SELECT ticket_text,ticket_lastchange FROM character_ticket WHERE guid = '%u' ORDER BY ticket_id ASC",GUID_LOPART(guid));
2010
2011    if(!result)
2012        return false;
2013
2014    Field* fields = result->Fetch();
2015
2016    char const* text = fields[0].GetString();
2017    char const* time = fields[1].GetString();
2018
2019    ShowTicket(guid,text,time);
2020    delete result;
2021
2022    return true;
2023}
2024
2025uint32 ChatHandler::GetTicketIDByNum(uint32 num)
2026{
2027    QueryResult *result = CharacterDatabase.Query("SELECT ticket_id FROM character_ticket");
2028
2029    if(!result || num > result->GetRowCount())
2030    {
2031        PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2032        delete result;
2033        return 0;
2034    }
2035
2036    for(uint32 i = 1; i < num; ++i)
2037        result->NextRow();
2038
2039    Field* fields = result->Fetch();
2040
2041    uint32 id = fields[0].GetUInt32();
2042    delete result;
2043    return id;
2044}
2045
2046//dell all tickets
2047bool ChatHandler::HandleDelTicketCommand(const char *args)
2048{
2049    char* px = strtok((char*)args, " ");
2050    if (!px)
2051        return false;
2052
2053    // delticket all
2054    if(strncmp(px,"all",4) == 0)
2055    {
2056        QueryResult *result = CharacterDatabase.Query("SELECT guid FROM character_ticket");
2057
2058        if(!result)
2059            return true;
2060
2061        // notify players about ticket deleting
2062        do
2063        {
2064            Field* fields = result->Fetch();
2065
2066            uint64 guid = fields[0].GetUInt64();
2067
2068            if(Player* sender = objmgr.GetPlayer(guid))
2069                sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2070
2071        }while(result->NextRow());
2072
2073        delete result;
2074
2075        CharacterDatabase.PExecute("DELETE FROM character_ticket");
2076        SendSysMessage(LANG_COMMAND_ALLTICKETDELETED);
2077        return true;
2078    }
2079
2080    int num = (uint32)atoi(px);
2081
2082    // delticket #num
2083    if(num > 0)
2084    {
2085        QueryResult *result = CharacterDatabase.PQuery("SELECT ticket_id,guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1);
2086
2087        if(!result)
2088        {
2089            PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num);
2090            delete result;
2091            SetSentErrorMessage(true);
2092            return false;
2093        }
2094
2095        Field* fields = result->Fetch();
2096
2097        uint32 id   = fields[0].GetUInt32();
2098        uint64 guid = fields[1].GetUInt64();
2099        delete result;
2100
2101        CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE ticket_id = '%u'", id);
2102
2103        // notify players about ticket deleting
2104        if(Player* sender = objmgr.GetPlayer(guid))
2105        {
2106            sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2107            PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,sender->GetName());
2108        }
2109        else
2110            SendSysMessage(LANG_COMMAND_TICKETDEL);
2111
2112        return true;
2113    }
2114
2115    std::string name = px;
2116
2117    if(!normalizePlayerName(name))
2118    {
2119        SendSysMessage(LANG_PLAYER_NOT_FOUND);
2120        SetSentErrorMessage(true);
2121        return false;
2122    }
2123
2124    uint64 guid = objmgr.GetPlayerGUIDByName(name);
2125
2126    if(!guid)
2127        return false;
2128
2129    // delticket $char_name
2130    CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE guid = '%u'",GUID_LOPART(guid));
2131
2132    // notify players about ticket deleting
2133    if(Player* sender = objmgr.GetPlayer(guid))
2134        sender->GetSession()->SendGMTicketGetTicket(0x0A,0);
2135
2136    PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,px);
2137    return true;
2138}
2139
2140//set spawn dist of creature
2141bool ChatHandler::HandleNpcSpawnDistCommand(const char* args)
2142{
2143    if(!*args)
2144        return false;
2145
2146    float option = atof((char*)args);
2147    if (option < 0.0f)
2148    {
2149        SendSysMessage(LANG_BAD_VALUE);
2150        return false;
2151    }
2152
2153    MovementGeneratorType mtype = IDLE_MOTION_TYPE;
2154    if (option >0.0f)
2155        mtype = RANDOM_MOTION_TYPE;
2156
2157    Creature *pCreature = getSelectedCreature();
2158    uint32 u_guidlow = 0;
2159
2160    if (pCreature)
2161        u_guidlow = pCreature->GetDBTableGUIDLow();
2162    else
2163        return false;
2164
2165    pCreature->SetRespawnRadius((float)option);
2166    pCreature->SetDefaultMovementType(mtype);
2167    pCreature->GetMotionMaster()->Initialize();
2168    if(pCreature->isAlive())                                // dead creature will reset movement generator at respawn
2169    {
2170        pCreature->setDeathState(JUST_DIED);
2171        pCreature->Respawn();
2172    }
2173
2174    WorldDatabase.PExecuteLog("UPDATE creature SET spawndist=%f, MovementType=%i WHERE guid=%u",option,mtype,u_guidlow);
2175    PSendSysMessage(LANG_COMMAND_SPAWNDIST,option);
2176    return true;
2177}
2178
2179bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
2180{
2181    if(!*args)
2182        return false;
2183
2184    char* stime = strtok((char*)args, " ");
2185
2186    if (!stime)
2187        return false;
2188
2189    int i_stime = atoi((char*)stime);
2190
2191    if (i_stime < 0)
2192    {
2193        SendSysMessage(LANG_BAD_VALUE);
2194        SetSentErrorMessage(true);
2195        return false;
2196    }
2197
2198    Creature *pCreature = getSelectedCreature();
2199    uint32 u_guidlow = 0;
2200
2201    if (pCreature)
2202        u_guidlow = pCreature->GetDBTableGUIDLow();
2203    else
2204        return false;
2205
2206    WorldDatabase.PExecuteLog("UPDATE creature SET spawntimesecs=%i WHERE guid=%u",i_stime,u_guidlow);
2207    pCreature->SetRespawnDelay((uint32)i_stime);
2208    PSendSysMessage(LANG_COMMAND_SPAWNTIME,i_stime);
2209
2210    return true;
2211}
2212
2213/**
2214 * Add a waypoint to a creature.
2215 *
2216 * The user can either select an npc or provide its GUID.
2217 *
2218 * The user can even select a visual waypoint - then the new waypoint
2219 * is placed *after* the selected one - this makes insertion of new
2220 * waypoints possible.
2221 *
2222 * eg:
2223 * .wp add 12345
2224 * -> adds a waypoint to the npc with the GUID 12345
2225 *
2226 * .wp add
2227 * -> adds a waypoint to the currently selected creature
2228 *
2229 *
2230 * @param args if the user did not provide a GUID, it is NULL
2231 *
2232 * @return true - command did succeed, false - something went wrong
2233 */
2234bool ChatHandler::HandleWpAddCommand(const char* args)
2235{
2236    sLog.outDebug("DEBUG: HandleWpAddCommand");
2237
2238    // optional
2239    char* guid_str = NULL;
2240
2241    if(*args)
2242    {
2243        guid_str = strtok((char*)args, " ");
2244    }
2245
2246    uint32 lowguid = 0;
2247    uint32 point = 0;
2248    Creature* target = getSelectedCreature();
2249    // Did player provide a GUID?
2250    if (!guid_str)
2251    {
2252        sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
2253
2254        // No GUID provided
2255        // -> Player must have selected a creature
2256
2257        if(!target || target->isPet())
2258        {
2259            SendSysMessage(LANG_SELECT_CREATURE);
2260            SetSentErrorMessage(true);
2261            return false;
2262        }
2263        if (target->GetEntry() == VISUAL_WAYPOINT )
2264        {
2265            sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
2266
2267            QueryResult *result =
2268                WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
2269                target->GetGUIDLow() );
2270            if(!result)
2271            {
2272                PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
2273                // User selected a visual spawnpoint -> get the NPC
2274                // Select NPC GUID
2275                // Since we compare float values, we have to deal with
2276                // some difficulties.
2277                // Here we search for all waypoints that only differ in one from 1 thousand
2278                // (0.001) - There is no other way to compare C++ floats with mySQL floats
2279                // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2280                const char* maxDIFF = "0.01";
2281                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 )",
2282                    target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2283                if(!result)
2284                {
2285                    PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
2286                    SetSentErrorMessage(true);
2287                    return false;
2288                }
2289            }
2290            do
2291            {
2292                Field *fields = result->Fetch();
2293                lowguid = fields[0].GetUInt32();
2294                point   = fields[1].GetUInt32();
2295            }while( result->NextRow() );
2296            delete result;
2297
2298            CreatureData const* data = objmgr.GetCreatureData(lowguid);
2299            if(!data)
2300            {
2301                PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2302                SetSentErrorMessage(true);
2303                return false;
2304            }
2305
2306            target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2307            if(!target)
2308            {
2309                PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2310                SetSentErrorMessage(true);
2311                return false;
2312            }
2313        }
2314        else
2315        {
2316            lowguid = target->GetDBTableGUIDLow();
2317        }
2318    }
2319    else
2320    {
2321        sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
2322
2323        // GUID provided
2324        // Warn if player also selected a creature
2325        // -> Creature selection is ignored <-
2326        if(target)
2327        {
2328            SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2329        }
2330        lowguid = atoi((char*)guid_str);
2331
2332        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2333        if(!data)
2334        {
2335            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2336            SetSentErrorMessage(true);
2337            return false;
2338        }
2339
2340        target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2341        if(!target || target->isPet())
2342        {
2343            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2344            SetSentErrorMessage(true);
2345            return false;
2346        }
2347    }
2348    // lowguid -> GUID of the NPC
2349    // point   -> number of the waypoint (if not 0)
2350    sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
2351
2352    sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
2353
2354    Player* player = m_session->GetPlayer();
2355    WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
2356
2357    // update movement type
2358    if(target)
2359    {
2360        target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2361        target->GetMotionMaster()->Initialize();
2362        if(target->isAlive())                               // dead creature will reset movement generator at respawn
2363        {
2364            target->setDeathState(JUST_DIED);
2365            target->Respawn();
2366        }
2367        target->SaveToDB();
2368    }
2369    else
2370        WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
2371
2372    PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
2373
2374    return true;
2375}                                                           // HandleWpAddCommand
2376
2377/**
2378 * .wp modify emote | spell | text | del | move | add
2379 *
2380 * add -> add a WP after the selected visual waypoint
2381 *        User must select a visual waypoint and then issue ".wp modify add"
2382 *
2383 * emote <emoteID>
2384 *   User has selected a visual waypoint before.
2385 *   <emoteID> is added to this waypoint. Everytime the
2386 *   NPC comes to this waypoint, the emote is called.
2387 *
2388 * emote <GUID> <WPNUM> <emoteID>
2389 *   User has not selected visual waypoint before.
2390 *   For the waypoint <WPNUM> for the NPC with <GUID>
2391 *   an emote <emoteID> is added.
2392 *   Everytime the NPC comes to this waypoint, the emote is called.
2393 *
2394 *
2395 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2396 */
2397bool ChatHandler::HandleWpModifyCommand(const char* args)
2398{
2399    sLog.outDebug("DEBUG: HandleWpModifyCommand");
2400
2401    if(!*args)
2402        return false;
2403
2404    // first arg: add del text emote spell waittime move
2405    char* show_str = strtok((char*)args, " ");
2406    if (!show_str)
2407    {
2408        return false;
2409    }
2410
2411    std::string show = show_str;
2412    // Check
2413    // Remember: "show" must also be the name of a column!
2414    if( (show != "emote") && (show != "spell") && (show != "text1") && (show != "text2")
2415        && (show != "text3") && (show != "text4") && (show != "text5")
2416        && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
2417        && (show != "model1") && (show != "model2") && (show != "orientation"))
2418    {
2419        return false;
2420    }
2421
2422    // Next arg is: <GUID> <WPNUM> <ARGUMENT>
2423
2424    // Did user provide a GUID
2425    // or did the user select a creature?
2426    // -> variable lowguid is filled with the GUID of the NPC
2427    uint32 lowguid = 0;
2428    uint32 point = 0;
2429    uint32 wpGuid = 0;
2430    Creature* target = getSelectedCreature();
2431
2432    if(target)
2433    {
2434        sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
2435
2436        // Did the user select a visual spawnpoint?
2437        if (target->GetEntry() != VISUAL_WAYPOINT )
2438        {
2439            PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2440            SetSentErrorMessage(true);
2441            return false;
2442        }
2443
2444        wpGuid = target->GetGUIDLow();
2445
2446        // The visual waypoint
2447        QueryResult *result =
2448            WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
2449            target->GetGUIDLow() );
2450        if(!result)
2451        {
2452            PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
2453            SetSentErrorMessage(true);
2454            return false;
2455        }
2456        sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
2457
2458        Field *fields = result->Fetch();
2459        lowguid = fields[0].GetUInt32();
2460        point   = fields[1].GetUInt32();
2461
2462        // Cleanup memory
2463        sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
2464        delete result;
2465    }
2466    else
2467    {
2468        // User did provide <GUID> <WPNUM>
2469
2470        char* guid_str = strtok((char*)NULL, " ");
2471        if( !guid_str )
2472        {
2473            SendSysMessage(LANG_WAYPOINT_NOGUID);
2474            return false;
2475        }
2476        lowguid = atoi((char*)guid_str);
2477
2478        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2479        if(!data)
2480        {
2481            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2482            SetSentErrorMessage(true);
2483            return false;
2484        }
2485
2486        PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
2487
2488        char* point_str = strtok((char*)NULL, " ");
2489        if( !point_str )
2490        {
2491            SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
2492            return false;
2493        }
2494        point    = atoi((char*)point_str);
2495
2496        PSendSysMessage("DEBUG: wpNumber provided: %d", point);
2497
2498        // Now we need the GUID of the visual waypoint
2499        // -> "del", "move", "add" command
2500
2501        QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
2502        if (!result)
2503        {
2504            PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
2505            SetSentErrorMessage(true);
2506            return false;
2507        }
2508
2509        Field *fields = result->Fetch();
2510        wpGuid  = fields[0].GetUInt32();
2511
2512        // Free memory
2513        delete result;
2514    }
2515
2516    char* arg_str = NULL;
2517    // Check for argument
2518    if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
2519    {
2520        // Text is enclosed in "<>", all other arguments not
2521        if( show.find("text") != std::string::npos )
2522            arg_str = strtok((char*)NULL, "<>");
2523        else
2524            arg_str = strtok((char*)NULL, " ");
2525
2526        if( !arg_str)
2527        {
2528            PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
2529            return false;
2530        }
2531    }
2532
2533    sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
2534
2535    // wpGuid  -> GUID of the waypoint creature
2536    // lowguid -> GUID of the NPC
2537    // point   -> waypoint number
2538
2539    // Special functions:
2540    // add - move - del -> no args commands
2541    // Add a waypoint after the selected visual
2542    if(show == "add" && target)
2543    {
2544        PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
2545
2546        // Get the creature for which we read the waypoint
2547        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2548        if(!data)
2549        {
2550            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2551            SetSentErrorMessage(true);
2552            return false;
2553        }
2554
2555        Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2556
2557        if( !npcCreature )
2558        {
2559            PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
2560            SetSentErrorMessage(true);
2561            return false;
2562        }
2563
2564        sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
2565
2566        // What to do:
2567        // Add the visual spawnpoint (DB only)
2568        // Adjust the waypoints
2569        // Respawn the owner of the waypoints
2570        sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
2571
2572        Player* chr = m_session->GetPlayer();
2573        Map *map = chr->GetMap();
2574
2575        if(npcCreature)
2576        {
2577            npcCreature->GetMotionMaster()->Initialize();
2578            if(npcCreature->isAlive())                      // dead creature will reset movement generator at respawn
2579            {
2580                npcCreature->setDeathState(JUST_DIED);
2581                npcCreature->Respawn();
2582            }
2583        }
2584
2585        // create the waypoint creature
2586        wpGuid = 0;
2587        Creature* wpCreature = new Creature;
2588        if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map,VISUAL_WAYPOINT,0))
2589        {
2590            PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2591            delete wpCreature;
2592        }
2593        else
2594        {
2595            wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2596
2597            if(!wpCreature->IsPositionValid())
2598            {
2599                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());
2600                delete wpCreature;
2601            }
2602            else
2603            {
2604                wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2605                // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2606                wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
2607                map->Add(wpCreature);
2608                wpGuid = wpCreature->GetGUIDLow();
2609            }
2610        }
2611
2612        WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
2613
2614        if(!wpGuid)
2615            return false;
2616
2617        PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
2618        return true;
2619    }                                                       // add
2620
2621    if(show == "del" && target)
2622    {
2623        PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
2624
2625        // Get the creature for which we read the waypoint
2626        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2627        if(!data)
2628        {
2629            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2630            SetSentErrorMessage(true);
2631            return false;
2632        }
2633
2634        Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2635
2636        // wpCreature
2637        Creature* wpCreature = NULL;
2638        if( wpGuid != 0 )
2639        {
2640            wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2641            wpCreature->DeleteFromDB();
2642            wpCreature->CleanupsBeforeDelete();
2643            wpCreature->AddObjectToRemoveList();
2644        }
2645
2646        // What to do:
2647        // Remove the visual spawnpoint
2648        // Adjust the waypoints
2649        // Respawn the owner of the waypoints
2650
2651        WaypointMgr.DeleteNode(lowguid, point);
2652
2653        if(npcCreature)
2654        {
2655            // Any waypoints left?
2656            QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
2657            if(!result2)
2658            {
2659                npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
2660            }
2661            else
2662            {
2663                npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2664                delete result2;
2665            }
2666            npcCreature->GetMotionMaster()->Initialize();
2667            if(npcCreature->isAlive())                      // dead creature will reset movement generator at respawn
2668            {
2669                npcCreature->setDeathState(JUST_DIED);
2670                npcCreature->Respawn();
2671            }
2672            npcCreature->SaveToDB();
2673        }
2674
2675        PSendSysMessage(LANG_WAYPOINT_REMOVED);
2676        return true;
2677    }                                                       // del
2678
2679    if(show == "move" && target)
2680    {
2681        PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
2682
2683        Player *chr = m_session->GetPlayer();
2684        Map *map = chr->GetMap();
2685        {
2686            // Get the creature for which we read the waypoint
2687            CreatureData const* data = objmgr.GetCreatureData(lowguid);
2688            if(!data)
2689            {
2690                PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2691                SetSentErrorMessage(true);
2692                return false;
2693            }
2694
2695            Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2696
2697            // wpCreature
2698            Creature* wpCreature = NULL;
2699            // What to do:
2700            // Move the visual spawnpoint
2701            // Respawn the owner of the waypoints
2702            if( wpGuid != 0 )
2703            {
2704                wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
2705                wpCreature->DeleteFromDB();
2706                wpCreature->CleanupsBeforeDelete();
2707                wpCreature->AddObjectToRemoveList();
2708                // re-create
2709                Creature* wpCreature2 = new Creature;
2710                if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0))
2711                {
2712                    PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
2713                    delete wpCreature2;
2714                    return false;
2715                }
2716
2717                wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
2718
2719                if(!wpCreature2->IsPositionValid())
2720                {
2721                    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());
2722                    delete wpCreature2;
2723                    return false;
2724                }
2725
2726                wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
2727                // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
2728                wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map);
2729                map->Add(wpCreature2);
2730                //MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2);
2731            }
2732
2733            WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
2734
2735            if(npcCreature)
2736            {
2737                npcCreature->GetMotionMaster()->Initialize();
2738                if(npcCreature->isAlive())                  // dead creature will reset movement generator at respawn
2739                {
2740                    npcCreature->setDeathState(JUST_DIED);
2741                    npcCreature->Respawn();
2742                }
2743            }
2744            PSendSysMessage(LANG_WAYPOINT_CHANGED);
2745        }
2746        return true;
2747    }                                                       // move
2748
2749    // Create creature - npc that has the waypoint
2750    CreatureData const* data = objmgr.GetCreatureData(lowguid);
2751    if(!data)
2752    {
2753        PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2754        SetSentErrorMessage(true);
2755        return false;
2756    }
2757
2758    WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
2759
2760    Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
2761    if(npcCreature)
2762    {
2763        npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
2764        npcCreature->GetMotionMaster()->Initialize();
2765        if(npcCreature->isAlive())                          // dead creature will reset movement generator at respawn
2766        {
2767            npcCreature->setDeathState(JUST_DIED);
2768            npcCreature->Respawn();
2769        }
2770    }
2771    PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
2772
2773    return true;
2774}
2775
2776/**
2777 * .wp show info | on | off
2778 *
2779 * info -> User has selected a visual waypoint before
2780 *
2781 * info <GUID> <WPNUM> -> User did not select a visual waypoint and
2782 *                        provided the GUID of the NPC and the number of
2783 *                        the waypoint.
2784 *
2785 * on -> User has selected an NPC; all visual waypoints for this
2786 *       NPC are added to the world
2787 *
2788 * on <GUID> -> User did not select an NPC - instead the GUID of the
2789 *              NPC is provided. All visual waypoints for this NPC
2790 *              are added from the world.
2791 *
2792 * off -> User has selected an NPC; all visual waypoints for this
2793 *        NPC are removed from the world.
2794 *
2795 * on <GUID> -> User did not select an NPC - instead the GUID of the
2796 *              NPC is provided. All visual waypoints for this NPC
2797 *              are removed from the world.
2798 *
2799 *
2800 */
2801bool ChatHandler::HandleWpShowCommand(const char* args)
2802{
2803    sLog.outDebug("DEBUG: HandleWpShowCommand");
2804
2805    if(!*args)
2806        return false;
2807
2808    // first arg: on, off, first, last
2809    char* show_str = strtok((char*)args, " ");
2810    if (!show_str)
2811    {
2812        return false;
2813    }
2814    // second arg: GUID (optional, if a creature is selected)
2815    char* guid_str = strtok((char*)NULL, " ");
2816    sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
2817    //if (!guid_str) {
2818    //    return false;
2819    //}
2820
2821    // Did user provide a GUID
2822    // or did the user select a creature?
2823    // -> variable lowguid is filled with the GUID
2824    Creature* target = getSelectedCreature();
2825    // Did player provide a GUID?
2826    if (!guid_str)
2827    {
2828        sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
2829        // No GUID provided
2830        // -> Player must have selected a creature
2831
2832        if(!target)
2833        {
2834            SendSysMessage(LANG_SELECT_CREATURE);
2835            SetSentErrorMessage(true);
2836            return false;
2837        }
2838    }
2839    else
2840    {
2841        sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
2842        // GUID provided
2843        // Warn if player also selected a creature
2844        // -> Creature selection is ignored <-
2845        if(target)
2846        {
2847            SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
2848        }
2849
2850        uint32 lowguid = atoi((char*)guid_str);
2851
2852        CreatureData const* data = objmgr.GetCreatureData(lowguid);
2853        if(!data)
2854        {
2855            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2856            SetSentErrorMessage(true);
2857            return false;
2858        }
2859
2860        target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
2861
2862        if(!target)
2863        {
2864            PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
2865            SetSentErrorMessage(true);
2866            return false;
2867        }
2868    }
2869
2870    uint32 lowguid = target->GetDBTableGUIDLow();
2871
2872    std::string show = show_str;
2873    uint32 Maxpoint;
2874
2875    sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u", lowguid);
2876
2877    sLog.outDebug("DEBUG: HandleWpShowCommand: Habe creature: %ld", target );
2878
2879    sLog.outDebug("DEBUG: HandleWpShowCommand: wpshow - show: %s", show_str);
2880    //PSendSysMessage("wpshow - show: %s", show);
2881
2882    // Show info for the selected waypoint
2883    if(show == "info")
2884    {
2885        PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
2886
2887        // Check if the user did specify a visual waypoint
2888        if( target->GetEntry() != VISUAL_WAYPOINT )
2889        {
2890            PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
2891            SetSentErrorMessage(true);
2892            return false;
2893        }
2894
2895        //PSendSysMessage("wp on, GUID: %u", lowguid);
2896
2897        //pCreature->GetPositionX();
2898
2899        QueryResult *result =
2900            WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u",
2901            target->GetGUID() );
2902        if(!result)
2903        {
2904            // Since we compare float values, we have to deal with
2905            // some difficulties.
2906            // Here we search for all waypoints that only differ in one from 1 thousand
2907            // (0.001) - There is no other way to compare C++ floats with mySQL floats
2908            // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
2909            const char* maxDIFF = "0.01";
2910            PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
2911
2912            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 )",
2913                target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
2914            if(!result)
2915            {
2916                PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
2917                SetSentErrorMessage(true);
2918                return false;
2919            }
2920        }
2921        do
2922        {
2923            Field *fields = result->Fetch();
2924            uint32 creGUID          = fields[0].GetUInt32();
2925            uint32 point            = fields[1].GetUInt32();
2926            int waittime            = fields[2].GetUInt32();
2927            uint32 emote            = fields[3].GetUInt32();
2928            uint32 spell            = fields[4].GetUInt32();
2929            const char * text1      = fields[5].GetString();
2930            const char * text2      = fields[6].GetString();
2931            const char * text3      = fields[7].GetString();
2932            const char * text4      = fields[8].GetString();
2933            const char * text5      = fields[9].GetString();
2934            uint32 model1           = fields[10].GetUInt32();
2935            uint32 model2           = fields[11].GetUInt32();
2936
2937            // Get the creature for which we read the waypoint
2938            Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2939
2940            PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
2941            PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
2942            PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
2943            PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
2944            PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
2945            PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
2946            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 1, text1);
2947            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 2, text2);
2948            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 3, text3);
2949            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 4, text4);
2950            PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, 5, text5);
2951
2952        }while( result->NextRow() );
2953        // Cleanup memory
2954        delete result;
2955        return true;
2956    }
2957
2958    if(show == "on")
2959    {
2960        PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
2961
2962        QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
2963        if(!result)
2964        {
2965            PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
2966            SetSentErrorMessage(true);
2967            return false;
2968        }
2969        // Delete all visuals for this NPC
2970        QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
2971        if(result2)
2972        {
2973            bool hasError = false;
2974            do
2975            {
2976                Field *fields = result2->Fetch();
2977                uint32 wpguid = fields[0].GetUInt32();
2978                Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpguid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
2979
2980                if(!pCreature)
2981                {
2982                    PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid);
2983                    hasError = true;
2984                    WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", wpguid);
2985                }
2986                else
2987                {
2988                    pCreature->DeleteFromDB();
2989                    pCreature->CleanupsBeforeDelete();
2990                    pCreature->AddObjectToRemoveList();
2991                }
2992
2993            }while( result2->NextRow() );
2994            delete result2;
2995            if( hasError )
2996            {
2997                PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
2998                PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
2999                PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3000            }
3001        }
3002
3003        do
3004        {
3005            Field *fields = result->Fetch();
3006            uint32 point    = fields[0].GetUInt32();
3007            float x         = fields[1].GetFloat();
3008            float y         = fields[2].GetFloat();
3009            float z         = fields[3].GetFloat();
3010
3011            uint32 id = VISUAL_WAYPOINT;
3012
3013            Player *chr = m_session->GetPlayer();
3014            Map *map = chr->GetMap();
3015            float o = chr->GetOrientation();
3016
3017            Creature* wpCreature = new Creature;
3018            if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
3019            {
3020                PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3021                delete wpCreature;
3022                delete result;
3023                return false;
3024            }
3025
3026            wpCreature->Relocate(x, y, z, o);
3027
3028            if(!wpCreature->IsPositionValid())
3029            {
3030                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());
3031                delete wpCreature;
3032                delete result;
3033                return false;
3034            }
3035
3036            wpCreature->SetVisibility(VISIBILITY_OFF);
3037            sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
3038            // set "wpguid" column to the visual waypoint
3039            WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
3040
3041            wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3042            // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
3043            wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
3044            map->Add(wpCreature);
3045            //MapManager::Instance().GetMap(wpCreature->GetMapId())->Add(wpCreature);
3046        }while( result->NextRow() );
3047
3048        // Cleanup memory
3049        delete result;
3050        return true;
3051    }
3052
3053    if(show == "first")
3054    {
3055        PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
3056
3057        QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
3058        if(!result)
3059        {
3060            PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
3061            SetSentErrorMessage(true);
3062            return false;
3063        }
3064
3065        Field *fields = result->Fetch();
3066        float x         = fields[0].GetFloat();
3067        float y         = fields[1].GetFloat();
3068        float z         = fields[2].GetFloat();
3069        uint32 id = VISUAL_WAYPOINT;
3070
3071        Player *chr = m_session->GetPlayer();
3072        float o = chr->GetOrientation();
3073        Map *map = chr->GetMap();
3074
3075        Creature* pCreature = new Creature;
3076        if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, id, 0))
3077        {
3078            PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id);
3079            delete pCreature;
3080            delete result;
3081            return false;
3082        }
3083
3084        pCreature->Relocate(x, y, z, o);
3085
3086        if(!pCreature->IsPositionValid())
3087        {
3088            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());
3089            delete pCreature;
3090            delete result;
3091            return false;
3092        }
3093
3094        pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3095        pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3096        map->Add(pCreature);
3097        //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
3098
3099        // Cleanup memory
3100        delete result;
3101        return true;
3102    }
3103
3104    if(show == "last")
3105    {
3106        PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
3107
3108        QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
3109        if( result )
3110        {
3111            Maxpoint = (*result)[0].GetUInt32();
3112
3113            delete result;
3114        }
3115        else
3116            Maxpoint = 0;
3117
3118        result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
3119        if(!result)
3120        {
3121            PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
3122            SetSentErrorMessage(true);
3123            return false;
3124        }
3125        Field *fields = result->Fetch();
3126        float x         = fields[0].GetFloat();
3127        float y         = fields[1].GetFloat();
3128        float z         = fields[2].GetFloat();
3129        uint32 id = VISUAL_WAYPOINT;
3130
3131        Player *chr = m_session->GetPlayer();
3132        float o = chr->GetOrientation();
3133        Map *map = chr->GetMap();
3134
3135        Creature* pCreature = new Creature;
3136        if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0))
3137        {
3138            PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id);
3139            delete pCreature;
3140            delete result;
3141            return false;
3142        }
3143
3144        pCreature->Relocate(x, y, z, o);
3145
3146        if(!pCreature->IsPositionValid())
3147        {
3148            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());
3149            delete pCreature;
3150            delete result;
3151            return false;
3152        }
3153
3154        pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3155        pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
3156        map->Add(pCreature);
3157        //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
3158        // Cleanup memory
3159        delete result;
3160        return true;
3161    }
3162
3163    if(show == "off")
3164    {
3165        QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
3166        if(!result)
3167        {
3168            SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
3169            SetSentErrorMessage(true);
3170            return false;
3171        }
3172        bool hasError = false;
3173        do
3174        {
3175            Field *fields = result->Fetch();
3176            uint32 guid = fields[0].GetUInt32();
3177            Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
3178
3179            //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
3180
3181            if(!pCreature)
3182            {
3183                PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
3184                hasError = true;
3185                WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid = '%u'", guid);
3186            }
3187            else
3188            {
3189                pCreature->DeleteFromDB();
3190                pCreature->CleanupsBeforeDelete();
3191                pCreature->AddObjectToRemoveList();
3192            }
3193        }while(result->NextRow());
3194        // set "wpguid" column to "empty" - no visual waypoint spawned
3195        WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'");
3196
3197        if( hasError )
3198        {
3199            PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
3200            PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
3201            PSendSysMessage(LANG_WAYPOINT_TOOFAR3);
3202        }
3203
3204        SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED);
3205        // Cleanup memory
3206        delete result;
3207
3208        return true;
3209    }
3210
3211    PSendSysMessage("DEBUG: wpshow - no valid command found");
3212
3213    return true;
3214}                                                           // HandleWpShowCommand
3215
3216bool ChatHandler::HandleWpExportCommand(const char *args)
3217{
3218    if(!*args)
3219        return false;
3220
3221    // Next arg is: <GUID> <ARGUMENT>
3222
3223    // Did user provide a GUID
3224    // or did the user select a creature?
3225    // -> variable lowguid is filled with the GUID of the NPC
3226    uint32 lowguid = 0;
3227    Creature* target = getSelectedCreature();
3228    char* arg_str = NULL;
3229    if (target)
3230    {
3231        if (target->GetEntry() != VISUAL_WAYPOINT)
3232            lowguid = target->GetGUIDLow();
3233        else
3234        {
3235            QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
3236            if (!result)
3237            {
3238                PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
3239                return true;
3240            }
3241            Field *fields = result->Fetch();
3242            lowguid = fields[0].GetUInt32();;
3243            delete result;
3244        }
3245
3246        arg_str = strtok((char*)args, " ");
3247    }
3248    else
3249    {
3250        // user provided <GUID>
3251        char* guid_str = strtok((char*)args, " ");
3252        if( !guid_str )
3253        {
3254            SendSysMessage(LANG_WAYPOINT_NOGUID);
3255            return false;
3256        }
3257        lowguid = atoi((char*)guid_str);
3258
3259        arg_str = strtok((char*)NULL, " ");
3260    }
3261
3262    if( !arg_str)
3263    {
3264        PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
3265        return false;
3266    }
3267
3268    PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
3269
3270    QueryResult *result = WorldDatabase.PQuery(
3271    //          0      1           2           3           4            5       6       7         8      9      10     11     12     13     14     15
3272        "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 );
3273
3274    if (!result)
3275    {
3276        PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
3277        SetSentErrorMessage(true);
3278        return false;
3279    }
3280
3281    std::ofstream outfile;
3282    outfile.open (arg_str);
3283
3284    do
3285    {
3286        Field *fields = result->Fetch();
3287
3288        outfile << "INSERT INTO creature_movement ";
3289        outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, text1, text2, text3, text4, text5 ) VALUES ";
3290
3291        outfile << "( ";
3292        outfile << fields[15].GetUInt32();                  // id
3293        outfile << ", ";
3294        outfile << fields[0].GetUInt32();                   // point
3295        outfile << ", ";
3296        outfile << fields[1].GetFloat();                    // position_x
3297        outfile << ", ";
3298        outfile << fields[2].GetFloat();                    // position_y
3299        outfile << ", ";
3300        outfile << fields[3].GetUInt32();                   // position_z
3301        outfile << ", ";
3302        outfile << fields[4].GetUInt32();                   // orientation
3303        outfile << ", ";
3304        outfile << fields[5].GetUInt32();                   // model1
3305        outfile << ", ";
3306        outfile << fields[6].GetUInt32();                   // model2
3307        outfile << ", ";
3308        outfile << fields[7].GetUInt16();                   // waittime
3309        outfile << ", ";
3310        outfile << fields[8].GetUInt32();                   // emote
3311        outfile << ", ";
3312        outfile << fields[9].GetUInt32();                   // spell
3313        outfile << ", ";
3314        const char *tmpChar = fields[10].GetString();
3315        if( !tmpChar )
3316        {
3317            outfile << "NULL";                              // text1
3318        }
3319        else
3320        {
3321            outfile << "'";
3322            outfile << tmpChar;                             // text1
3323            outfile << "'";
3324        }
3325        outfile << ", ";
3326        tmpChar = fields[11].GetString();
3327        if( !tmpChar )
3328        {
3329            outfile << "NULL";                              // text2
3330        }
3331        else
3332        {
3333            outfile << "'";
3334            outfile << tmpChar;                             // text2
3335            outfile << "'";
3336        }
3337        outfile << ", ";
3338        tmpChar = fields[12].GetString();
3339        if( !tmpChar )
3340        {
3341            outfile << "NULL";                              // text3
3342        }
3343        else
3344        {
3345            outfile << "'";
3346            outfile << tmpChar;                             // text3
3347            outfile << "'";
3348        }
3349        outfile << ", ";
3350        tmpChar = fields[13].GetString();
3351        if( !tmpChar )
3352        {
3353            outfile << "NULL";                              // text4
3354        }
3355        else
3356        {
3357            outfile << "'";
3358            outfile << tmpChar;                             // text4
3359            outfile << "'";
3360        }
3361        outfile << ", ";
3362        tmpChar = fields[14].GetString();
3363        if( !tmpChar )
3364        {
3365            outfile << "NULL";                              // text5
3366        }
3367        else
3368        {
3369            outfile << "'";
3370            outfile << tmpChar;                             // text5
3371            outfile << "'";
3372        }
3373        outfile << ");\n ";
3374
3375    } while( result->NextRow() );
3376    delete result;
3377
3378    PSendSysMessage(LANG_WAYPOINT_EXPORTED);
3379    outfile.close();
3380
3381    return true;
3382}
3383
3384bool ChatHandler::HandleWpImportCommand(const char *args)
3385{
3386    if(!*args)
3387        return false;
3388
3389    char* arg_str = strtok((char*)args, " ");
3390    if (!arg_str)
3391        return false;
3392
3393    std::string line;
3394    std::ifstream infile (arg_str);
3395    if (infile.is_open())
3396    {
3397        while (! infile.eof() )
3398        {
3399            getline (infile,line);
3400            //cout << line << endl;
3401            QueryResult *result = WorldDatabase.Query(line.c_str());
3402            delete result;
3403        }
3404        infile.close();
3405    }
3406    PSendSysMessage(LANG_WAYPOINT_IMPORTED);
3407
3408    return true;
3409}
3410
3411//rename characters
3412bool ChatHandler::HandleRenameCommand(const char* args)
3413{
3414    Player* target = NULL;
3415    uint64 targetGUID = 0;
3416    std::string oldname;
3417
3418    char* px = strtok((char*)args, " ");
3419
3420    if(px)
3421    {
3422        oldname = px;
3423
3424        if(!normalizePlayerName(oldname))
3425        {
3426            SendSysMessage(LANG_PLAYER_NOT_FOUND);
3427            SetSentErrorMessage(true);
3428            return false;
3429        }
3430
3431        target = objmgr.GetPlayer(oldname.c_str());
3432
3433        if (!target)
3434            targetGUID = objmgr.GetPlayerGUIDByName(oldname);
3435    }
3436
3437    if(!target && !targetGUID)
3438    {
3439        target = getSelectedPlayer();
3440    }
3441
3442    if(!target && !targetGUID)
3443    {
3444        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3445        SetSentErrorMessage(true);
3446        return false;
3447    }
3448
3449    if(target)
3450    {
3451        PSendSysMessage(LANG_RENAME_PLAYER, target->GetName());
3452        target->SetAtLoginFlag(AT_LOGIN_RENAME);
3453        CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow());
3454    }
3455    else
3456    {
3457        PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
3458        CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID));
3459    }
3460
3461    return true;
3462}
3463
3464//spawn go
3465bool ChatHandler::HandleGameObjectCommand(const char* args)
3466{
3467    if (!*args)
3468        return false;
3469
3470    char* pParam1 = strtok((char*)args, " ");
3471    if (!pParam1)
3472        return false;
3473
3474    uint32 id = atoi((char*)pParam1);
3475    if(!id)
3476        return false;
3477
3478    char* spawntimeSecs = strtok(NULL, " ");
3479
3480    const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id);
3481
3482    if (!goI)
3483    {
3484        PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
3485        SetSentErrorMessage(true);
3486        return false;
3487    }
3488
3489    Player *chr = m_session->GetPlayer();
3490    float x = float(chr->GetPositionX());
3491    float y = float(chr->GetPositionY());
3492    float z = float(chr->GetPositionZ());
3493    float o = float(chr->GetOrientation());
3494    Map *map = chr->GetMap();
3495
3496    float rot2 = sin(o/2);
3497    float rot3 = cos(o/2);
3498
3499    GameObject* pGameObj = new GameObject;
3500    uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
3501
3502    if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1))
3503    {
3504        delete pGameObj;
3505        return false;
3506    }
3507
3508    if( spawntimeSecs )
3509    {
3510        uint32 value = atoi((char*)spawntimeSecs);
3511        pGameObj->SetRespawnTime(value);
3512        //sLog.outDebug("*** spawntimeSecs: %d", value);
3513    }
3514
3515    // fill the gameobject data and save to the db
3516    pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
3517
3518    // this will generate a new guid if the object is in an instance
3519    if(!pGameObj->LoadFromDB(db_lowGUID, map))
3520    {
3521        delete pGameObj;
3522        return false;
3523    }
3524
3525    sLog.outDebug(GetTrinityString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o);
3526
3527    map->Add(pGameObj);
3528
3529    // TODO: is it really necessary to add both the real and DB table guid here ?
3530    objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
3531
3532    PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z);
3533    return true;
3534}
3535
3536//show animation
3537bool ChatHandler::HandleAnimCommand(const char* args)
3538{
3539    if (!*args)
3540        return false;
3541
3542    uint32 anim_id = atoi((char*)args);
3543    m_session->GetPlayer()->HandleEmoteCommand(anim_id);
3544    return true;
3545}
3546
3547//change standstate
3548bool ChatHandler::HandleStandStateCommand(const char* args)
3549{
3550    if (!*args)
3551        return false;
3552
3553    uint32 anim_id = atoi((char*)args);
3554    m_session->GetPlayer( )->SetUInt32Value( UNIT_NPC_EMOTESTATE , anim_id );
3555
3556    return true;
3557}
3558
3559bool ChatHandler::HandleAddHonorCommand(const char* args)
3560{
3561    if (!*args)
3562        return false;
3563
3564    Player *target = getSelectedPlayer();
3565    if(!target)
3566    {
3567        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3568        SetSentErrorMessage(true);
3569        return false;
3570    }
3571
3572    uint32 amount = (uint32)atoi(args);
3573    target->RewardHonor(NULL, 1, amount);
3574    return true;
3575}
3576
3577bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/)
3578{
3579    Unit *target = getSelectedUnit();
3580    if(!target)
3581    {
3582        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3583        SetSentErrorMessage(true);
3584        return false;
3585    }
3586
3587    m_session->GetPlayer()->RewardHonor(target, 1);
3588    return true;
3589}
3590
3591bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/)
3592{
3593    Player *target = getSelectedPlayer();
3594    if(!target)
3595    {
3596        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3597        SetSentErrorMessage(true);
3598        return false;
3599    }
3600
3601    target->UpdateHonorFields();
3602    return true;
3603}
3604
3605bool ChatHandler::HandleLookupEventCommand(const char* args)
3606{
3607    if(!*args)
3608        return false;
3609
3610    std::string namepart = args;
3611    std::wstring wnamepart;
3612
3613    // converting string that we try to find to lower case
3614    if(!Utf8toWStr(namepart,wnamepart))
3615        return false;
3616
3617    wstrToLower(wnamepart);
3618
3619    uint32 counter = 0;
3620
3621    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3622    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3623
3624    for(uint32 id = 0; id < events.size(); ++id )
3625    {
3626        GameEventData const& eventData = events[id];
3627
3628        std::string descr = eventData.description;
3629        if(descr.empty())
3630            continue;
3631
3632        if (Utf8FitTo(descr, wnamepart))
3633        {
3634            char const* active = activeEvents.find(id) != activeEvents.end() ? GetTrinityString(LANG_ACTIVE) : "";
3635           
3636                        if(m_session)
3637                                PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,id,id,eventData.description.c_str(),active );
3638                        else
3639                                PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,id,eventData.description.c_str(),active );
3640
3641            ++counter;
3642        }
3643    }
3644
3645    if (counter==0)
3646        SendSysMessage(LANG_NOEVENTFOUND);
3647
3648    return true;
3649}
3650
3651bool ChatHandler::HandleEventActiveListCommand(const char* args)
3652{
3653    uint32 counter = 0;
3654
3655    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3656    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3657
3658    char const* active = GetTrinityString(LANG_ACTIVE);
3659
3660    for(GameEvent::ActiveEvents::const_iterator itr = activeEvents.begin(); itr != activeEvents.end(); ++itr )
3661    {
3662        uint32 event_id = *itr;
3663        GameEventData const& eventData = events[event_id];
3664
3665        if(m_session)
3666                        PSendSysMessage(LANG_EVENT_ENTRY_LIST_CHAT,event_id,event_id,eventData.description.c_str(),active );
3667                else
3668                        PSendSysMessage(LANG_EVENT_ENTRY_LIST_CONSOLE,event_id,eventData.description.c_str(),active );
3669
3670        ++counter;
3671    }
3672
3673    if (counter==0)
3674        SendSysMessage(LANG_NOEVENTFOUND);
3675
3676    return true;
3677}
3678
3679bool ChatHandler::HandleEventInfoCommand(const char* args)
3680{
3681    if(!*args)
3682        return false;
3683
3684    // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3685    char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3686    if(!cId)
3687        return false;
3688
3689    uint32 event_id = atoi(cId);
3690
3691    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3692
3693    if(event_id >=events.size())
3694    {
3695        SendSysMessage(LANG_EVENT_NOT_EXIST);
3696        SetSentErrorMessage(true);
3697        return false;
3698    }
3699
3700    GameEventData const& eventData = events[event_id];
3701    if(!eventData.isValid())
3702    {
3703        SendSysMessage(LANG_EVENT_NOT_EXIST);
3704        SetSentErrorMessage(true);
3705        return false;
3706    }
3707
3708    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3709    bool active = activeEvents.find(event_id) != activeEvents.end();
3710    char const* activeStr = active ? GetTrinityString(LANG_ACTIVE) : "";
3711
3712    std::string startTimeStr = TimeToTimestampStr(eventData.start);
3713    std::string endTimeStr = TimeToTimestampStr(eventData.end);
3714
3715    uint32 delay = gameeventmgr.NextCheck(event_id);
3716    time_t nextTime = time(NULL)+delay;
3717    std::string nextStr = nextTime >= eventData.start && nextTime < eventData.end ? TimeToTimestampStr(time(NULL)+delay) : "-";
3718
3719    std::string occurenceStr = secsToTimeString(eventData.occurence * MINUTE);
3720    std::string lengthStr = secsToTimeString(eventData.length * MINUTE);
3721
3722    PSendSysMessage(LANG_EVENT_INFO,event_id,eventData.description.c_str(),activeStr,
3723        startTimeStr.c_str(),endTimeStr.c_str(),occurenceStr.c_str(),lengthStr.c_str(),
3724        nextStr.c_str());
3725    return true;
3726}
3727
3728bool ChatHandler::HandleEventStartCommand(const char* args)
3729{
3730    if(!*args)
3731        return false;
3732
3733    // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3734    char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3735    if(!cId)
3736        return false;
3737
3738    int32 event_id = atoi(cId);
3739
3740    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3741
3742    if(event_id < 1 || event_id >=events.size())
3743    {
3744        SendSysMessage(LANG_EVENT_NOT_EXIST);
3745        SetSentErrorMessage(true);
3746        return false;
3747    }
3748
3749    GameEventData const& eventData = events[event_id];
3750    if(!eventData.isValid())
3751    {
3752        SendSysMessage(LANG_EVENT_NOT_EXIST);
3753        SetSentErrorMessage(true);
3754        return false;
3755    }
3756
3757    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3758    if(activeEvents.find(event_id) != activeEvents.end())
3759    {
3760        PSendSysMessage(LANG_EVENT_ALREADY_ACTIVE,event_id);
3761        SetSentErrorMessage(true);
3762        return false;
3763    }
3764
3765    gameeventmgr.StartEvent(event_id,true);
3766    return true;
3767}
3768
3769bool ChatHandler::HandleEventStopCommand(const char* args)
3770{
3771    if(!*args)
3772        return false;
3773
3774    // id or [name] Shift-click form |color|Hgameevent:id|h[name]|h|r
3775    char* cId = extractKeyFromLink((char*)args,"Hgameevent");
3776    if(!cId)
3777        return false;
3778
3779    int32 event_id = atoi(cId);
3780
3781    GameEvent::GameEventDataMap const& events = gameeventmgr.GetEventMap();
3782
3783    if(event_id < 1 || event_id >=events.size())
3784    {
3785        SendSysMessage(LANG_EVENT_NOT_EXIST);
3786        SetSentErrorMessage(true);
3787        return false;
3788    }
3789
3790    GameEventData const& eventData = events[event_id];
3791    if(!eventData.isValid())
3792    {
3793        SendSysMessage(LANG_EVENT_NOT_EXIST);
3794        SetSentErrorMessage(true);
3795        return false;
3796    }
3797
3798    GameEvent::ActiveEvents const& activeEvents = gameeventmgr.GetActiveEventList();
3799
3800    if(activeEvents.find(event_id) == activeEvents.end())
3801    {
3802        PSendSysMessage(LANG_EVENT_NOT_ACTIVE,event_id);
3803        SetSentErrorMessage(true);
3804        return false;
3805    }
3806
3807    gameeventmgr.StopEvent(event_id,true);
3808    return true;
3809}
3810
3811bool ChatHandler::HandleCombatStopCommand(const char* args)
3812{
3813    Player *player;
3814
3815    if(*args)
3816    {
3817        std::string playername = args;
3818
3819        if(!normalizePlayerName(playername))
3820        {
3821            SendSysMessage(LANG_PLAYER_NOT_FOUND);
3822            SetSentErrorMessage(true);
3823            return false;
3824        }
3825
3826        player = objmgr.GetPlayer(playername.c_str());
3827
3828        if(!player)
3829        {
3830            SendSysMessage(LANG_PLAYER_NOT_FOUND);
3831            SetSentErrorMessage(true);
3832            return false;
3833        }
3834    }
3835    else
3836    {
3837        player = getSelectedPlayer();
3838
3839        if (!player)
3840            player = m_session->GetPlayer();
3841    }
3842
3843    player->CombatStop();
3844    player->getHostilRefManager().deleteReferences();
3845    return true;
3846}
3847
3848bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/)
3849{
3850    uint32 classmask = m_session->GetPlayer()->getClassMask();
3851
3852    for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3853    {
3854        SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3855        if( !skillInfo )
3856            continue;
3857
3858        if( skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY )
3859        {
3860            for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3861            {
3862                SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3863                if( !skillLine )
3864                    continue;
3865
3866                // skip racial skills
3867                if( skillLine->racemask != 0 )
3868                    continue;
3869
3870                // skip wrong class skills
3871                if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3872                    continue;
3873
3874                if( skillLine->skillId != i || skillLine->forward_spellid )
3875                    continue;
3876
3877                SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3878                if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3879                    continue;
3880
3881                m_session->GetPlayer()->learnSpell(skillLine->spellId);
3882            }
3883        }
3884    }
3885
3886    SendSysMessage(LANG_COMMAND_LEARN_ALL_CRAFT);
3887    return true;
3888}
3889
3890bool ChatHandler::HandleLearnAllRecipesCommand(const char* args)
3891{
3892    //  Learns all recipes of specified profession and sets skill to max
3893    //  Example: .learn all_recipes enchanting
3894
3895    Player* target = getSelectedPlayer();
3896    if( !target )
3897    {
3898        SendSysMessage(LANG_PLAYER_NOT_FOUND);
3899        return false;
3900    }
3901
3902    if (!*args)
3903        return false;
3904
3905    std::wstring wnamepart;
3906
3907    if(!Utf8toWStr(args,wnamepart))
3908        return false;
3909
3910    uint32 counter = 0;                                     // Counter for figure out that we found smth.
3911
3912    // converting string that we try to find to lower case
3913    wstrToLower( wnamepart );
3914
3915    uint32 classmask = m_session->GetPlayer()->getClassMask();
3916
3917    for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i)
3918    {
3919        SkillLineEntry const *skillInfo = sSkillLineStore.LookupEntry(i);
3920        if( !skillInfo )
3921            continue;
3922
3923        if( skillInfo->categoryId != SKILL_CATEGORY_PROFESSION &&
3924            skillInfo->categoryId != SKILL_CATEGORY_SECONDARY )
3925            continue;
3926
3927        int loc = m_session->GetSessionDbcLocale();
3928        std::string name = skillInfo->name[loc];
3929
3930        if(Utf8FitTo(name, wnamepart))
3931        {
3932            for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
3933            {
3934                SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
3935                if( !skillLine )
3936                    continue;
3937
3938                if( skillLine->skillId != i || skillLine->forward_spellid )
3939                    continue;
3940
3941                // skip racial skills
3942                if( skillLine->racemask != 0 )
3943                    continue;
3944
3945                // skip wrong class skills
3946                if( skillLine->classmask && (skillLine->classmask & classmask) == 0)
3947                    continue;
3948
3949                SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
3950                if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false))
3951                    continue;
3952
3953                if( !target->HasSpell(spellInfo->Id) )
3954                    m_session->GetPlayer()->learnSpell(skillLine->spellId);
3955            }
3956
3957            uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id);
3958            target->SetSkill(skillInfo->id, maxLevel, maxLevel);
3959            PSendSysMessage(LANG_COMMAND_LEARN_ALL_RECIPES, name.c_str());
3960            return true;
3961        }
3962    }
3963
3964    return false;
3965}
3966
3967bool ChatHandler::HandleLookupPlayerIpCommand(const char* args)
3968{
3969 
3970    if (!*args)
3971        return false;
3972
3973    std::string ip = strtok ((char*)args, " ");
3974        char* limit_str = strtok (NULL, " ");
3975        int32 limit = limit_str ? atoi (limit_str) : -1;
3976
3977    loginDatabase.escape_string (ip);
3978
3979    QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ());
3980
3981    return LookupPlayerSearchCommand (result,limit);
3982}
3983
3984bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args)
3985{
3986    if (!*args)
3987        return false;
3988
3989    std::string account = strtok ((char*)args, " ");
3990        char* limit_str = strtok (NULL, " ");
3991        int32 limit = limit_str ? atoi (limit_str) : -1;
3992
3993    if (!AccountMgr::normilizeString (account))
3994        return false;
3995
3996    loginDatabase.escape_string (account);
3997
3998    QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ());
3999
4000    return LookupPlayerSearchCommand (result,limit);
4001}
4002
4003bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args)
4004{
4005 
4006    if (!*args)
4007        return false;
4008
4009    std::string email = strtok ((char*)args, " ");
4010        char* limit_str = strtok (NULL, " ");
4011        int32 limit = limit_str ? atoi (limit_str) : -1;
4012
4013    loginDatabase.escape_string (email);
4014
4015    QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ());
4016
4017    return LookupPlayerSearchCommand (result,limit);
4018}
4019
4020bool ChatHandler::LookupPlayerSearchCommand(QueryResult* result, int32 limit)
4021{
4022    if(!result)
4023    {
4024        PSendSysMessage(LANG_NO_PLAYERS_FOUND);
4025        SetSentErrorMessage(true);
4026        return false;
4027    }
4028
4029    int i =0;
4030    do
4031    {
4032        Field* fields = result->Fetch();
4033        uint32 acc_id = fields[0].GetUInt32();
4034        std::string acc_name = fields[1].GetCppString();
4035       
4036        QueryResult* chars = CharacterDatabase.PQuery("SELECT guid,name FROM characters WHERE account = '%u'", acc_id);
4037        if(chars)
4038        {
4039            PSendSysMessage(LANG_LOOKUP_PLAYER_ACCOUNT,acc_name.c_str(),acc_id);
4040
4041            uint64 guid = 0;
4042            std::string name;
4043
4044            do
4045            {
4046                Field* charfields = chars->Fetch();
4047                guid = charfields[0].GetUInt64();
4048                name = charfields[1].GetCppString();
4049
4050                PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER,name.c_str(),guid);
4051                ++i;
4052
4053            } while( chars->NextRow() && ( limit == -1 || i < limit ) );
4054
4055            delete chars;
4056        }
4057    } while(result->NextRow());
4058
4059    delete result;
4060
4061    return true;
4062}
4063
4064/// Triggering corpses expire check in world
4065bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/)
4066{
4067        CorpsesErase();
4068        return true;
4069}
4070
4071bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
4072{
4073    Player *target = getSelectedPlayer();
4074
4075    if(!target)
4076    {
4077        PSendSysMessage(LANG_NO_CHAR_SELECTED);
4078        SetSentErrorMessage(true);
4079        return false;
4080        }
4081
4082    // Repair items
4083    target->DurabilityRepairAll(false, 0, false);
4084
4085    PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName());
4086    if(needReportToTarget(target))
4087        ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName());
4088    return true;
4089}
4090
4091bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
4092{
4093    Player *player = m_session->GetPlayer();
4094    Creature *creature = getSelectedCreature();
4095
4096    if(!creature)
4097    {
4098        PSendSysMessage(LANG_SELECT_CREATURE);
4099        SetSentErrorMessage(true);
4100        return false;
4101    }
4102
4103    // Follow player - Using pet's default dist and angle
4104    creature->GetMotionMaster()->MoveFollow(player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
4105
4106    PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName());
4107    return true;
4108}
4109
4110bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
4111{
4112    Player *player = m_session->GetPlayer();
4113    Creature *creature = getSelectedCreature();
4114
4115    if(!creature)
4116    {
4117        PSendSysMessage(LANG_SELECT_CREATURE);
4118        SetSentErrorMessage(true);
4119        return false;
4120    }
4121
4122    if (creature->GetMotionMaster()->empty() ||
4123        creature->GetMotionMaster()->GetCurrentMovementGeneratorType ()!=TARGETED_MOTION_TYPE)
4124    {
4125        PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4126        SetSentErrorMessage(true);
4127        return false;
4128    }
4129
4130    TargetedMovementGenerator<Creature> const* mgen
4131        = static_cast<TargetedMovementGenerator<Creature> const*>((creature->GetMotionMaster()->top()));
4132
4133    if(mgen->GetTarget()!=player)
4134    {
4135        PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU);
4136        SetSentErrorMessage(true);
4137        return false;
4138    }
4139
4140    // reset movement
4141    creature->GetMotionMaster()->MovementExpired(true);
4142
4143    PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName());
4144    return true;
4145}
4146
4147bool ChatHandler::HandleCreatePetCommand(const char* args)
4148{
4149        Player *player = m_session->GetPlayer();
4150        Creature *creatureTarget = getSelectedCreature();
4151   
4152        if(!creatureTarget || creatureTarget->isPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER)
4153        {
4154                PSendSysMessage(LANG_SELECT_CREATURE);
4155                SetSentErrorMessage(true);
4156                return false;
4157        }
4158
4159        CreatureInfo const* cInfo = objmgr.GetCreatureTemplate(creatureTarget->GetEntry());
4160        // Creatures with family 0 crashes the server
4161        if(cInfo->family == 0)
4162        {
4163                PSendSysMessage("This creature cannot be tamed. (family id: 0).");
4164                SetSentErrorMessage(true);
4165                return false;
4166        }
4167
4168        if(player->GetPetGUID())
4169        {
4170                PSendSysMessage("You already have a pet");
4171                SetSentErrorMessage(true);
4172                return false;
4173        }
4174
4175        // Everything looks OK, create new pet
4176        Pet* pet = new Pet(HUNTER_PET);
4177
4178        if(!pet->CreateBaseAtCreature(creatureTarget))
4179        {
4180                delete pet;
4181                PSendSysMessage("Error 1");
4182                return false;
4183        }
4184
4185        creatureTarget->setDeathState(JUST_DIED);
4186        creatureTarget->RemoveCorpse();
4187        creatureTarget->SetHealth(0); // just for nice GM-mode view
4188
4189        pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, player->GetGUID());
4190        pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID());
4191        pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction());
4192
4193        if(!pet->InitStatsForLevel(creatureTarget->getLevel()))
4194        {
4195                sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted.");
4196                PSendSysMessage("Error 2");
4197                return false;
4198        }
4199
4200        // prepare visual effect for levelup
4201        pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
4202
4203         pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true);
4204         // this enables pet details window (Shift+P)
4205         pet->AIM_Initialize();
4206         pet->InitPetCreateSpells();
4207         pet->SetHealth(pet->GetMaxHealth());
4208
4209         MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
4210
4211         // visual effect for levelup
4212         pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
4213
4214         player->SetPet(pet);
4215         pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4216         player->PetSpellInitialize();
4217
4218        return true;
4219}
4220
4221bool ChatHandler::HandlePetLearnCommand(const char* args)
4222{
4223        if(!*args)
4224                return false;
4225
4226        Player *plr = m_session->GetPlayer();
4227        Pet *pet = plr->GetPet();
4228
4229        if(!pet)
4230        {
4231                PSendSysMessage("You have no pet");
4232                SetSentErrorMessage(true);
4233                return false;
4234        }
4235
4236        uint32 spellId = extractSpellIdFromLink((char*)args);
4237
4238        if(!spellId || !sSpellStore.LookupEntry(spellId))
4239        return false;
4240
4241        // Check if pet already has it
4242        if(pet->HasSpell(spellId))
4243        {
4244                PSendSysMessage("Pet already has spell: %u", spellId);
4245                SetSentErrorMessage(true);
4246        return false;
4247        }
4248
4249        // Check if spell is valid
4250        SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
4251        if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo))
4252    {
4253        PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spellId);
4254        SetSentErrorMessage(true);
4255        return false;
4256    }
4257
4258        pet->learnSpell(spellId);
4259
4260        PSendSysMessage("Pet has learned spell %u", spellId);
4261        return true;
4262}
4263
4264bool ChatHandler::HandlePetUnlearnCommand(const char *args)
4265{
4266        if(!*args)
4267                return false;
4268
4269        Player *plr = m_session->GetPlayer();
4270        Pet *pet = plr->GetPet();
4271
4272        if(!pet)
4273        {
4274                PSendSysMessage("You have no pet");
4275                SetSentErrorMessage(true);
4276                return false;
4277        }
4278
4279        uint32 spellId = extractSpellIdFromLink((char*)args);
4280
4281        if(pet->HasSpell(spellId))
4282                pet->removeSpell(spellId);
4283        else
4284                PSendSysMessage("Pet doesn't have that spell");
4285
4286        return true;
4287}
4288
4289bool ChatHandler::HandlePetTpCommand(const char *args)
4290{
4291        if(!*args)
4292                return false;
4293
4294        Player *plr = m_session->GetPlayer();
4295        Pet *pet = plr->GetPet();
4296
4297        if(!pet)
4298        {
4299                PSendSysMessage("You have no pet");
4300                SetSentErrorMessage(true);
4301                return false;
4302        }
4303
4304        uint32 tp = atol(args);
4305
4306        pet->SetTP(tp);
4307
4308        PSendSysMessage("Pet's tp changed to %u", tp);
4309        return true;
4310}
4311
4312bool ChatHandler::HandleActivateObjectCommand(const char *args)
4313{
4314        if(!*args)
4315                return false;
4316
4317        char* cId = extractKeyFromLink((char*)args,"Hgameobject");
4318    if(!cId)
4319        return false;
4320
4321    uint32 lowguid = atoi(cId);
4322    if(!lowguid)
4323        return false;
4324
4325    GameObject* obj = NULL;
4326
4327    // by DB guid
4328    if (GameObjectData const* go_data = objmgr.GetGOData(lowguid))
4329        obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id);
4330
4331    if(!obj)
4332    {
4333        PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid);
4334        SetSentErrorMessage(true);
4335        return false;
4336    }
4337
4338        // Activate
4339        obj->SetLootState(GO_READY);
4340        obj->UseDoorOrButton(10000);
4341
4342        PSendSysMessage("Object activated!");
4343
4344        return true;
4345}
Note: See TracBrowser for help on using the browser.