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

Revision 2, 117.0 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

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