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

Revision 279, 123.7 kB (checked in by yumileroy, 17 years ago)

Merged commit 269 (5f0e38da128a).

Original author: gvcoman
Date: 2008-11-21 14:34:05-05:00

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