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

Revision 112, 119.4 kB (checked in by yumileroy, 17 years ago)

[svn] * Merge CLI Commands with regular commands and give them level4 access. sec_console. Source mangos - thanks to ogeraisi for the amalgamated patch.
* Redid/Fixed/Added some lang strings.
* As usual remember this is a trunk rev so stability only guaranteed on northern countries of Mars and western parts of Pluto. No warranties outside the solar system, sorry :( . Check with your local government or dictator on regulations regarding export.

Original author: KingPin?
Date: 2008-10-26 13:32:42-05:00

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