www.pudn.com > wow.rar > ChatHandler.cpp


// Copyright (C) 2004 Team Python
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include "ChatHandler.h"
#include "NetworkInterface.h"
#include "GameClient.h"
#include "Opcodes.h"
#include "Log.h"
#include "WorldServer.h"
#include "Character.h"
#include "UpdateMask.h"
#include "Database.h"

#define world WorldServer::getSingleton()
 
ChatCommand * ChatHandler::LoadHelp(bool load) 
{ 
	static bool first_call = true; 
 
	static ChatCommand adminCommandTable[8]; 
	static ChatCommand npcCommandTable[20]; 
	static ChatCommand moveCommandTable[9]; 
	static ChatCommand gmCommandTable[7]; 
	static ChatCommand usrCommandTable[12]; 
	static ChatCommand commandTable[16]; 
 
	if(first_call) 
	{ 
		first_call = false; 
		//ADMIN 
		adminCommandTable[0].setValues("ban",         3, &ChatHandler::HandleBanCommand,           "",   NULL);//LINA FEATURE 
		adminCommandTable[1].setValues("unban",       3, &ChatHandler::HandleUnBanCommand,         "",   NULL);//LINA FEATURE 
		adminCommandTable[2].setValues("lvl",         3, &ChatHandler::HandleSecurityCommand,      "",   NULL);//LINA FEATUR 
		adminCommandTable[3].setValues("addspirit",   3, &ChatHandler::HandleAddSpiritCommand,     "",   NULL); 
		adminCommandTable[4].setValues("die",         3, &ChatHandler::HandleDieCommand,           "",   NULL); 
		adminCommandTable[5].setValues("revive",      3, &ChatHandler::HandleReviveCommand,        "",   NULL); 
		adminCommandTable[6].setValues("update",      3, &ChatHandler::HandleUpdateCommand,        "",   NULL); 
		adminCommandTable[7].setValues(NULL,          0, NULL,                                     "",   NULL); 
 
/*		//CREATOR 
		npcCommandTable[0].setValues("info",        2, &ChatHandler::HandleGUIDCommand,          "",   NULL); 
		npcCommandTable[1].setValues("mobs",        2, &ChatHandler::HandleSpawnCommand,         "",   NULL); 
		npcCommandTable[2].setValues("taxi",        2, &ChatHandler::HandleSpawnTaxiCommand,     "",   NULL); 
		npcCommandTable[3].setValues("spell",       2, &ChatHandler::HandleSpellCommand,         "",   NULL); 
		npcCommandTable[4].setValues("rmvspell",    2, &ChatHandler::HandleRemoveSpellCommand,   "",   NULL); 
		npcCommandTable[5].setValues("item",        2, &ChatHandler::HandleItemCommand,          "",   NULL); 
		npcCommandTable[6].setValues("rmvitem",     2, &ChatHandler::HandleRemoveItemCommand,    "",   NULL); 
		npcCommandTable[7].setValues("itemmove",    2, &ChatHandler::HandleItemMoveCommand,      "",   NULL); 
		npcCommandTable[8].setValues("delete",      2, &ChatHandler::HandleDeleteCommand,        "",   NULL); 
		npcCommandTable[9].setValues("level",       2, &ChatHandler::HandleChangeLevelCommand,   "",   NULL);//LINA FEATURE 
		npcCommandTable[10].setValues("skin",       2, &ChatHandler::HandleDisplayIdCommand,     "",   NULL); 
		npcCommandTable[11].setValues("faction",     2, &ChatHandler::HandleFactionIdCommand,     "",   NULL); 
		npcCommandTable[12].setValues("name",        2, &ChatHandler::HandleNameCommand,          "",   NULL);//LINA FEATURE 
		npcCommandTable[13].setValues("flag",        2, &ChatHandler::HandleNPCFlagCommand,       "",   NULL); 
		npcCommandTable[14].setValues("animfreq",    3, &ChatHandler::HandleAnimFreqCommand,      "",   NULL); 
		npcCommandTable[15].setValues("random",      2, &ChatHandler::HandleRandomCommand,        "",   NULL); 
		npcCommandTable[16].setValues("addmove",     2, &ChatHandler::HandleAddMoveCommand,       "",   NULL); 
		npcCommandTable[17].setValues("run",         2, &ChatHandler::HandleRunCommand,           "",   NULL); 
		npcCommandTable[18].setValues("state",       2, &ChatHandler::HandleAggressiveCommand,    "",   NULL); 
		npcCommandTable[19].setValues(NULL,          0, NULL,                                     "",   NULL); */ 
		 
		//CREATOR  
       npcCommandTable[0].setValues("info",        2, &ChatHandler::HandleGUIDCommand,          "",   NULL);  
       npcCommandTable[1].setValues("mobs",        2, &ChatHandler::HandleSpawnCommand,         "",   NULL);  
       npcCommandTable[2].setValues("taxi",        2, &ChatHandler::HandleSpawnTaxiCommand,     "",   NULL);  
       npcCommandTable[3].setValues("spell",       2, &ChatHandler::HandleSpellCommand,         "",   NULL);  
       npcCommandTable[4].setValues("rmvspell",    2, &ChatHandler::HandleRemoveSpellCommand,   "",   NULL);  
       npcCommandTable[5].setValues("item",        2, &ChatHandler::HandleItemCommand,          "",   NULL);  
       npcCommandTable[6].setValues("rmvitem",     2, &ChatHandler::HandleRemoveItemCommand,    "",   NULL);  
       npcCommandTable[7].setValues("itemmove",    2, &ChatHandler::HandleItemMoveCommand,      "",   NULL);  
       npcCommandTable[8].setValues("delete",      2, &ChatHandler::HandleDeleteCommand,        "",   NULL);  
       npcCommandTable[9].setValues("level",       2, &ChatHandler::HandleChangeLevelCommand,   "",   NULL);//LINA FEATURE  
       npcCommandTable[10].setValues("skin",       2, &ChatHandler::HandleDisplayIdCommand,     "",   NULL);  
       npcCommandTable[11].setValues("faction",     2, &ChatHandler::HandleFactionIdCommand,     "",   NULL);  
       npcCommandTable[12].setValues("name",        2, &ChatHandler::HandleNameCommand,          "",   NULL);//LINA FEATURE  
       npcCommandTable[13].setValues("flag",        2, &ChatHandler::HandleNPCFlagCommand,       "",   NULL);  
       npcCommandTable[14].setValues("animfreq",    3, &ChatHandler::HandleAnimFreqCommand,      "",   NULL);  
       npcCommandTable[15].setValues("random",      2, &ChatHandler::HandleRandomCommand,        "",   NULL);  
       npcCommandTable[16].setValues("addmove",     2, &ChatHandler::HandleAddMoveCommand,       "",   NULL);  
       npcCommandTable[17].setValues("run",         2, &ChatHandler::HandleRunCommand,           "",   NULL);  
       npcCommandTable[18].setValues("state",       2, &ChatHandler::HandleAggressiveCommand,    "",   NULL);  
       npcCommandTable[19].setValues("scale",      2, &ChatHandler::HandleNPCScaleCommand,       "",   NULL);//THE_WIZARD  
       npcCommandTable[20].setValues("hpmin",      2, &ChatHandler::HandleNPChpminCommand,       "",   NULL);//THE_WIZARD  
       npcCommandTable[21].setValues("hpmax",      2, &ChatHandler::HandleNPChpmaxCommand,       "",   NULL);//THE_WIZARD        
       npcCommandTable[22].setValues(NULL,          0, NULL,                                     "",   NULL); 
 
 
		//MOVE		 
		moveCommandTable[0].setValues("where",       1, &ChatHandler::HandleGPSCommand,           "",   NULL); 
		moveCommandTable[1].setValues("there",       1, &ChatHandler::HandleAppearCommand,        "",   NULL); 
		moveCommandTable[2].setValues("here",        1, &ChatHandler::HandleSummonCommand,        "",   NULL); 
		moveCommandTable[3].setValues("fast",        2, &ChatHandler::HandleMoveCommand,          "",   NULL); 
		moveCommandTable[4].setValues("world",       3, &ChatHandler::HandleWorldPortCommand,     "",   NULL); 
		moveCommandTable[5].setValues("town",        1, &ChatHandler::HandleRecallCommand,        "",   NULL); 
		moveCommandTable[6].setValues("prog",        2, &ChatHandler::HandleProgCommand,          "",   NULL); 
		moveCommandTable[7].setValues("isle",        1, &ChatHandler::HandleIsleCommand,          "",   NULL); 
		moveCommandTable[8].setValues(NULL,          0, NULL,                                     "",   NULL); 
     
		//GM	 
		gmCommandTable[0].setValues("pass",        1, &ChatHandler::HandleGMPassCommand,        "",   NULL);//LINA FEATURE 
		gmCommandTable[1].setValues("off",         1, &ChatHandler::HandleGMOffCommand,         "",   NULL); 
		gmCommandTable[2].setValues("on",          1, &ChatHandler::HandleGMOnCommand,          "",   NULL); 
		gmCommandTable[3].setValues("kick",        1, &ChatHandler::HandleKickCommand,          "",   NULL);//LINA FEATURE 
		gmCommandTable[4].setValues("save",        1, &ChatHandler::HandleSaveAllCommand,       "",   NULL);//LINA FEATURE 
		gmCommandTable[5].setValues("announce",    1, &ChatHandler::HandleAnnounceCommand,      "",   NULL); 
		gmCommandTable[6].setValues(NULL,          0, NULL,                                     "",   NULL); 
			 
		//CHANGE	 
		usrCommandTable[0].setValues("hp",          1, &ChatHandler::HandleModifyHPCommand,			"",   NULL); 
		usrCommandTable[1].setValues("mana",        1, &ChatHandler::HandleModifyManaCommand,		"",   NULL); 
		usrCommandTable[2].setValues("gold",        1, &ChatHandler::HandleModifyGoldCommand,		"",   NULL); 
		usrCommandTable[3].setValues("lvl",         1, &ChatHandler::HandleModifyLevelCommand,		"",   NULL); 
		usrCommandTable[4].setValues("speed",       1, &ChatHandler::HandleModifySpeedCommand,		"",   NULL); 
		usrCommandTable[5].setValues("wspeed",      1, &ChatHandler::HandleModifyWaterSpeedCommand,	"",   NULL);//LINA FEATURE 
		usrCommandTable[6].setValues("scale",       1, &ChatHandler::HandleModifyScaleCommand,		"",   NULL);//LINA FEATURE 
		usrCommandTable[7].setValues("mount",       1, &ChatHandler::HandleModifyMountCommand,		"",   NULL); 
		usrCommandTable[8].setValues("aura",        3, &ChatHandler::HandleAuraCommand,				"",   NULL); 
		usrCommandTable[9].setValues("spell",       3, &ChatHandler::HandleLearnCommand,			"",   NULL); 
		usrCommandTable[10].setValues("skin",       3, &ChatHandler::HandleMorphCommand,			"",   NULL); 
		usrCommandTable[11].setValues(NULL,         0, NULL,										"",   NULL); 
		usrCommandTable[12].setValues("talentxp",   2, &ChatHandler::HandleTalantPointsCommand,     "",   NULL);//THE_WIZARD  
	 
 
		//MAIN 
//		commandTable[0].setValues("help",        0, &ChatHandler::HandleHelpCommand,          "",   NULL); 
		commandTable[0].setValues("help",        0, &ChatHandler::HandleCommandsCommand,      "",   NULL); 
		commandTable[1].setValues("commands",    0, &ChatHandler::HandleCommandsCommand,      "",   NULL); 
		commandTable[2].setValues("info",        0, &ChatHandler::HandleInfoCommand,          "",   NULL); 
		commandTable[3].setValues("dismount",    0, &ChatHandler::HandleDismountCommand,      "",   NULL); 
		commandTable[4].setValues("mount",       0, &ChatHandler::HandleMountCommand,         "",   NULL); 
		commandTable[5].setValues("save",        0, &ChatHandler::HandleSaveCommand,          "",   NULL);//LINA FEATURE 
		commandTable[6].setValues("start",       0, &ChatHandler::HandleStartCommand,         "",   NULL); 
		commandTable[7].setValues("list",        0, &ChatHandler::HandleGMListCommand,        "",   NULL); 
		commandTable[8].setValues("acct",        0, &ChatHandler::HandleAcctCommand,          "",   NULL); 
		commandTable[9].setValues("login",       0, &ChatHandler::HandleGMLoginCommand,       "",   NULL); 
		commandTable[10].setValues("usr",        1, NULL,                                     "",   usrCommandTable); 
		commandTable[11].setValues("gm",         1, NULL,                                     "",   gmCommandTable); 
		commandTable[12].setValues("move",		 1, NULL,                                     "",   moveCommandTable); 
		commandTable[13].setValues("npc",        2, NULL,                                     "",   npcCommandTable); 
		commandTable[14].setValues("admin",      3, NULL,                                     "",   adminCommandTable); 
		commandTable[15].setValues(NULL,         0, NULL,                                     "",   NULL); 
	} 
 
	if(load) 
	{ 
		DatabaseInterface *dbi = Database::getSingleton().createDatabaseInterface( ); 
 
		for(uint32 i = 0; commandTable[i].Name != NULL; i++) 
		{ 
			dbi->loadChatCommand(commandTable[i].Name, &commandTable[i]); 
 
			if(commandTable[i].ChildCommands != NULL) 
			{ 
				ChatCommand *ptable = commandTable[i].ChildCommands; 
				for(uint32 j = 0; ptable[j].Name != NULL; j++) 
				{ 
					std::string str = commandTable[i].Name; 
					str += " "; 
					str += ptable[j].Name; 
					dbi->loadChatCommand(str.c_str(), &ptable[j]); 
				} 
			} 
		} 
 
		Database::getSingleton( ).removeDatabaseInterface(dbi); 
	} 
	return commandTable; 
} 

bool ChatHandler::hasStringAbbr(const char* s1, const char* s2)
{
    for(;;)
    {
        if( !*s2 )
            return true;
        else if( !*s1 )
            return false;
        else if( tolower( *s1 ) != tolower( *s2 ) )
            return false;
        s1++; s2++;
    }
}


void ChatHandler::SendMultilineMessage(const char *str)
{
    char buf[256];
    wowWData data;

    const char* line = str;
    const char* pos = line;
    while((pos = strchr(line, '\n')) != NULL)
    {
        strncpy(buf, line, pos-line);
        buf[pos-line]=0;

        FillMessageData(&data, 0x09, m_pClient, (uint8*)buf);
        m_pClient->SendMsg(&data);

        line = pos+1;
    }

    FillMessageData(&data, 0x09, m_pClient, (uint8*)line);
    m_pClient->SendMsg(&data);
}

bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, uint8* text)
{
    char *cmd = (char*)text; 
	uint32 AcctLvl = m_pClient->getAccountLvl();

    while (*text != ' ' && *text != '\0') text++; // skip command
    if(*text != '\0')
    {
        *text = '\0';
        text++;
    }

    while (*text == ' ') text++; // skip whitespace

    if(*cmd == '\0')
        return false;

    for(uint32 i = 0; table[i].Name != NULL; i++)
    {
        if(!hasStringAbbr(table[i].Name, cmd))
            continue;

        if(AcctLvl < table[i].SecurityLevel)
            continue;

		if(table[i].ChildCommands != NULL) 
        { 
            if(!ExecuteCommandInTable(table[i].ChildCommands, text)) 
            { 
                if(table[i].Help != "") 
                    SendMultilineMessage(table[i].Help.c_str()); 
                else 
                { 
                    wowWData data; 
                    FillMessageData(&data, 0x09, m_pClient, (uint8*)"There is no such subcommand."); 
                    m_pClient->SendMsg(&data); 
                } 
            } 
            return true; 
        } 
 
		if(!(this->*(table[i].Handler))(text)) 
        { 
            if(table[i].Help != "") 
                SendMultilineMessage(table[i].Help.c_str()); 
            else 
            { 
                wowWData data; 
                FillMessageData(&data, 0x09, m_pClient, (uint8*)"Incorrect syntax."); 
                m_pClient->SendMsg(&data); 
            } 
        }
        return true;
    }
    return false;
}

int ChatHandler::ParseCommands(uint8* text, uint16 text_length)
{
    assert(text);
   // assert(*text); fixed by ScreaM

    if(text[0] != '!' && text[0] != '.') // let's not confuse users
        return 0;
    text++;

    if(!ExecuteCommandInTable(LoadHelp(false), text))
    {
        wowWData data;
        FillMessageData(&data, 0x09, m_pClient, (uint8*)"There is no such command.");
        m_pClient->SendMsg(&data);
    }

    return 1;
}

void ChatHandler::HandleMsg( wowWData & recv_data, GameClient *pClient )
{
    wowWData data;
    char f[256];
    sprintf(f, "WORLD: Chat Opcode 0x%.4X", recv_data.opcode);
    Log::getSingleton( ).outString( f );
    switch (recv_data.opcode)
    {
	case CHAT_MSG_YELL:
	case CHAT_MSG_PARTY:
	case CHAT_MSG_GUILD:
	case CHAT_MSG_OFFICER:
    case CMSG_MESSAGECHAT:
		{
            uint16 text_length = strlen((char*)recv_data.data+8)+1;

			m_pClient = pClient;
            if (ParseCommands(recv_data.data+8, text_length) > 0)
                return;

			uint8 text_mode = recv_data.data[0];
            FillMessageData( &data, text_mode, pClient, recv_data.data+8 );

			if (text_mode == CHAT_MSG_PARTY) {
				if (((Character*)pClient->getCurrentChar())->IsInGroup()) {
					Group *pGroup = world.GetGroupByLeader(((Character*)pClient->getCurrentChar())->GetGroupLeader());
	                for (uint32 c=0; c < pGroup->count; c++){
						Character *pGroupGuy = world.mCharacters[pGroup->members[c].guid];
						world.SendMessageToPlayer(&data, pGroupGuy->getGUID());
					}
				}
			}
			else if (text_mode == CHAT_MSG_YELL) {
				world.SendZoneMessage(&data, pClient, 1);
			}
			else if (text_mode == CHAT_MSG_GUILD) return;
			else if (text_mode == CHAT_MSG_OFFICER) return;
            else if (text_mode != CHAT_MSG_WHISPER) { // whisper message send in FillMessageData
				world.SendAreaMessage(&data, pClient, 1);
            }
        } break;
    case CMSG_TEXT_EMOTE:
        {
			if (pClient->getCurrentChar()->isDead()) return;
            uint32 text_emote, guid1, guid2;
            recv_data.readData(text_emote);
            recv_data >> guid1 >> guid2;

            char *nam=0; uint16 namlen=0;
            WorldServer::CharacterMap::iterator chariter;
            WorldServer::CreatureMap::iterator npciter;

            if( (( npciter = world.mCreatures.find( guid1 ) ) != world.mCreatures.end( ) ) && (guid2==0xF0001000) ) {
                nam = npciter->second->getCreatureName( );
                namlen = strlen( nam ) + 1;
            } else if( ( chariter = world.mCharacters.find( guid1 ) ) != world.mCharacters.end( ) ) {
                nam = chariter->second->getName( );
                namlen = strlen( nam ) + 1;
            }

            data.clear();
            data.Initialise(12, SMSG_EMOTE);

            uint8 emote_anim = world.mEmotes[uint8(text_emote&0xff)];

            data << (uint8)emote_anim;
            data << (uint8)0x00;
            data << (uint8)0x00;
            data << (uint8)0x00;

            uint32 guid = pClient->getCurrentChar()->getGUID();
            data << (uint32)guid << (uint8)0x00 << (uint8)0x00 << (uint8)0x00 << (uint8)0x00;
//            world.SendGlobalMessage(&data);
			world.SendAreaMessage(&data, pClient, 1);

            data.clear();
            data.setLength(12 + namlen);
            data.opcode = SMSG_TEXT_EMOTE;


            memcpy(data.data, &guid, 4);
            data.data[4] = 0x00;
            data.data[5] = 0x00;
            data.data[6] = 0x00;
            data.data[7] = 0x00;

            memcpy(data.data+8,recv_data.data,4);

            if( namlen > 0 )
                memcpy( data.data + 12, nam, namlen );

//            pClient->SendMsg( &data );
//            world.SendGlobalMessage(&data, pClient);
			world.SendAreaMessage(&data, pClient, 1);
        } break;
    }
}

void ChatHandler::FillMessageData( wowWData *data, uint8 type, GameClient* pClient, uint8 *text )
{

    // !!!! Be careful using strlen to determine the size of the chat message.
    // A CHAT_MSG_WHISPER sends TWO null terminated  strings(first the name of
    // the whisper target, then the message) and doing strlen only finds the
    // length of the first string.  -- DeathCheese

    const uint8 msgchat_header_size=13;
    uint8 msgchat_header[msgchat_header_size] = {type,
        0x00, 0x00, 0x00, 0x00}; //no idea what are those bytes for

    // add guid to message header
    uint32 guid=0;
    if(pClient)
        guid = pClient->getCurrentChar()->getGUID();
    memcpy(msgchat_header+5, &guid, 4);
    msgchat_header[9] = 0x00;
    msgchat_header[10] = 0x00;
    msgchat_header[11] = 0x00;
    msgchat_header[12] = 0x00;

    data->clear();

    std::string logoutput = "CHAT: ";
    if( pClient ) {
        logoutput += pClient->getCurrentChar( )->getName( );
        logoutput += ": ";
    }

    uint16 length = strlen((char*)text) + 1;
    if (type == CHAT_MSG_WHISPER){
        // Whisper Chat:  Server receives two strings.  First is the target of whisper, second is the message.
        uint16 msg_length = strlen((char*)text+length) + 1;

        data->setLength(msgchat_header_size + msg_length + 1);
        data->opcode = SMSG_MESSAGECHAT;
        memcpy(data->data, msgchat_header, msgchat_header_size);
        memcpy(data->data+msgchat_header_size, text+length, msg_length);
        data->data[msgchat_header_size+msg_length] = 0; //NULL terminated string
        logoutput += "->";
        logoutput += (char *)text;
        logoutput += "<- ";
        logoutput += (char *)(text + length);
    }
    else{
        data->setLength(msgchat_header_size + length + 1);
        data->opcode = SMSG_MESSAGECHAT;

        memcpy(data->data,msgchat_header,msgchat_header_size);
        memcpy(data->data+msgchat_header_size, text, length);
        data->data[msgchat_header_size+length] = 0; //NULL terminated string
        logoutput += (char *)text;
    }

    Log::getSingleton( ).outChat( logoutput.c_str( ) );

    // The last byte is most likely a flag, 0 or 1, denoting on or off
    uint8 byte = 0x00;
    if(type == CHAT_MSG_AFK && pClient!=0) { // toggle AFK
        byte = pClient->getCurrentChar()->ToggleAFK();
    }

    data->data[data->length-1] = byte;

    if (type == CHAT_MSG_WHISPER){
        char name[22];
        memcpy(name, text, length);
		if (world.GetClientByName((char*)name))
		{
			world.SendMessageToPlayer(data, (char*)name);
			data->clear();
			uint8 buf[256];
			sprintf((char*)buf,"To %s: %s", (char*)name, (char *)(text + length));
			FillMessageData(data, 0x09, pClient, buf);
			pClient->SendMsg( data );
		}
		else
		{
			data->clear();
			uint8 buf[256];
			sprintf((char*)buf,"No player named '%s' is currently playing", (char*)name);
			FillMessageData(data, 0x09, pClient, buf);
			pClient->SendMsg( data );
		}						
    }
}

void ChatHandler::SpawnCreature(GameClient *pClient, char* pName, uint32 display_id, uint32 npcFlags, uint32 faction_id, uint32 level)
{
    wowWData data;

    // Create the requested monster
    Character *chr = pClient->getCurrentChar();
    float x = chr->getPositionX();
    float y = chr->getPositionY();
    float z = chr->getPositionZ();
    float o = chr->getOrientation();

    Unit* pUnit = new Unit();
    UpdateMask unitMask;
    WorldServer::getSingletonPtr()->mObjectMgr.SetCreateUnitBits(unitMask);

    pUnit->Create(world.m_hiCreatureGuid++, (uint8*)pName, x, y, z, o);
    pUnit->setMapId(chr->getMapId());
    pUnit->setZone(chr->getZone());
    data.clear();
    pUnit->setUpdateValue(OBJECT_FIELD_ENTRY, world.addCreatureName((uint8*)pUnit->getCreatureName()));
    pUnit->setUpdateFloatValue(OBJECT_FIELD_SCALE_X, 1.0f);
    pUnit->setUpdateValue(UNIT_FIELD_DISPLAYID, display_id);
    pUnit->setUpdateValue(UNIT_NPC_FLAGS , npcFlags);
    pUnit->setUpdateValue(UNIT_FIELD_FACTIONTEMPLATE , faction_id);
    pUnit->setUpdateValue(UNIT_FIELD_HEALTH, 100 + 30*level);
    pUnit->setUpdateValue(UNIT_FIELD_MAXHEALTH, 100 + 30*level);
    pUnit->setUpdateValue(UNIT_FIELD_LEVEL , level);

    pUnit->setUpdateFloatValue(UNIT_FIELD_COMBATREACH , 1.5f);
    pUnit->setUpdateFloatValue(UNIT_FIELD_MAXDAMAGE ,  5.0f);
    pUnit->setUpdateFloatValue(UNIT_FIELD_MINDAMAGE , 8.0f);
    pUnit->setUpdateValue(UNIT_FIELD_BASEATTACKTIME, 1900);
    pUnit->setUpdateValue(UNIT_FIELD_BASEATTACKTIME+1, 2000);
    pUnit->setUpdateFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 2.0f);

    pUnit->CreateObject(&unitMask, &data, 0);

    // add to the world list of creatures
    WPAssert( pUnit->getGUID() != 0 );
    world.mCreatures[pUnit->getGUID()] = pUnit;

    // send create message to everyone
//    world.SendGlobalMessage(&data);
	world.SendUnitAreaMessage(&data, pUnit);

    DatabaseInterface *dbi = Database::getSingleton( ).createDatabaseInterface( );
    dbi->saveCreature(pUnit);
    Database::getSingleton( ).removeDatabaseInterface(dbi);
}

void ChatHandler::smsg_NewWorld(GameClient *pClient, uint16 c, float x, float y, float z)
{
	pClient->getCurrentChar()->setWorldPort(true);
	
    wowWData data;
    WorldServer::CreatureMap creatures = world.getCreatureMap();
    WorldServer::CharacterMap characters = world.getCharacterMap();

    data.Initialise(4, SMSG_TRANSFER_PENDING);
    data << uint32(0);

    pClient->SendMsg(&data);

    // Build a NEW WORLD packet
    data.Initialise(20, SMSG_NEW_WORLD);
    data << (uint32)c << (float)x << (float)y << (float)z << (float)0.0f;
    pClient->SendMsg( &data );

    /*
    // Destroy this client's player from all clients (including self)
    uint32 guid = pClient->getCurrentChar()->getGUID();
    data.Initialise(SMSG_DESTROY_OBJECT);
    data << (uint32)guid << (uint8)0x00 << (uint8)0x00 << (uint8)0x00 << (uint8)0x00;
    WPAssert(data.getLength() == 8);
    pClient->SendMsg(&data);

    for( WorldServer::CreatureMap::iterator i = creatures.begin( ); i != creatures.end( ); ++ i )
    {
        uint32 guid = i->second->getGUID();
        data.Initialise(SMSG_DESTROY_OBJECT);
        data << (uint32)guid << i->second->getGUIDHigh();
        WPAssert(data.getLength() == 8);
        pClient->SendMsg(&data);
    }
    */

    // Destroy ourselves from other clients
    uint32 guid = pClient->getCurrentChar()->getGUID();
    data.Initialise(8, SMSG_DESTROY_OBJECT );
    data << (uint32)guid << (uint8)0x00 << (uint8)0x00 << (uint8)0x00 << (uint8)0x00;
//    pClient->getCurrentChar()->SendMessageToSet(&data, true);
	world.SendAreaMessage(&data, pClient, 1);

    // Remove ourselves from inrange lists
    for( WorldServer::CharacterMap::iterator iter = characters.begin( ); iter != characters.end( ); ++ iter )
        iter->second->RemoveInRangeObject( pClient->getCurrentChar() );

    for( WorldServer::CreatureMap::iterator iter = creatures.begin( ); iter != creatures.end( ); ++ iter )
        iter->second->RemoveInRangeObject( pClient->getCurrentChar() );

    pClient->getCurrentChar()->ClearInRangeSet();

    pClient->getCurrentChar()->setMapId(c);

    pClient->getCurrentChar()->setNewPosition(x,y,z);
//    pClient->getCurrentChar()->setPosition(8000,8000,0,0,true);
    pClient->getCurrentChar()->setPosition(x,y,z,0,true);
    //wowWData movedata;
//	pClient->getCurrentChar( )->TeleportAck(&data, x, y, z);
//	world.SendAreaMessage(&data, pClient, 1);
}

void ChatHandler::MovePlayer(GameClient *pClient, float x, float y, float z)
{
    wowWData data;

    //Output new position to the console
    uint8 txtBuffer[512];
    sprintf((char*)txtBuffer,"WORLD: Moved player to (%f, %f, %f)",x,y,z );
    Log::getSingleton( ).outString( (char*)txtBuffer );

    sprintf((char*)txtBuffer,"You have been moved to (%f, %f, %f)",x,y,z );
    FillMessageData(&data, 0x09, pClient, txtBuffer);
    pClient->SendMsg( &data );

    ////////////////////////////////////////
    //Set the new position of the character
    Character *chr = pClient->getCurrentChar();

    //Send new position to client via MSG_MOVE_TELEPORT_ACK
    chr->TeleportAck(&data, x,y,z);
    //pClient->SendMsg(&data);

    //////////////////////////////////
    //Now send new position of this player to all clients using MSG_MOVE_HEARTBEAT
    chr->BuildHeartBeat(&data);
//    world.SendGlobalMessage(&data, pClient);
	world.SendAreaMessage(&data, pClient, 1);
}

//START OF LINA COMMAND BY NAME FONCTION PATCH 
Character * ChatHandler::getCurrentCharByName(uint8 * pName) 
{ 
	WorldServer::ClientSet::iterator itr; 
	for (itr = world.mClients.begin(); itr != world.mClients.end(); itr++) 
	{ 
		if( strcmp(((GameClient*)(*itr))->getCharacterName(), (char*)pName) == 0 ) 
		{ 
			return ((GameClient*)(*itr))->getCurrentChar(); 
		} 
	} 
	wowWData data; 
	uint8 buf[256]; 
	sprintf((char*)buf,"Character (%s) does not exist or is not logged in.", (char*)pName); 
	FillMessageData(&data, 0x09, m_pClient, buf); 
	m_pClient->SendMsg( &data ); 
	return NULL; 
} 
//END OF LINA COMMAND BY NAME FONCTION PATCH 
 
//START OF LINA COMMAND BY PTR FONCTION PATCH 1.3 
Character * ChatHandler::getSelectedChar() 
{ 
	const uint32 *guid; 
	wowWData data; 
	Character *chr=NULL; 
				 
	guid = m_pClient->getCurrentChar()->getSelectionPtr(); 
	if (guid[0] != 0) 
	{ 
		if(guid[1]==0) chr= WorldServer::getSingleton().GetCharacter(guid[0]); 
		else 
		{			 
			FillMessageData(&data, 0x09, m_pClient,(uint8*) "Please select a User."); 
			m_pClient->SendMsg( &data ); 
		} 
	} 
	else 
	{ 
		chr=m_pClient->getCurrentChar(); 
//		FillMessageData(&data, 0x09, m_pClient,(uint8*) "AutoSelection."); 
//		m_pClient->SendMsg( &data ); 
	} 
	return chr; 
} 
 
//UINT32 
int32 ChatHandler::TestValue(const float Value, const float max, const float min) 
{ 
	if(Valuemax) 
	{ 
		wowWData data; 
		FillMessageData(&data, 0x09, m_pClient,(uint8*)"Invalid Value."); 
		m_pClient->SendMsg( &data ); 
		return 0; 
	} 
	return 1; 
} 
 
//FLOAT 
int32 ChatHandler::TestValue(const uint32 Value, const uint32 max, const uint32 min) 
{ 
	if(Valuemax) 
	{ 
		wowWData data; 
		FillMessageData(&data, 0x09, m_pClient,(uint8*)"Invalid Value."); 
		m_pClient->SendMsg( &data ); 
		return 0; 
	} 
	return 1; 
} 
//FLOAT 
void ChatHandler::ChangeSelectedCharMsg(const uint16 &index, const float Value, const float max, const float min, char * nom) 
{ 
	wowWData data; 
 
	if(!TestValue(Value, max, min)) return; 
 
	Character * pChar = getSelectedChar(); 
	if(pChar!=NULL) 
	{ 
		data.Initialise( 12, index ); 
		data << pChar->getUpdateValue( OBJECT_FIELD_GUID ); 
		data << pChar->getUpdateValue( OBJECT_FIELD_GUID + 1 ); 
		data << Value; 
		pChar->SendMessageToSet( &data, true ); 
		Message(pChar, nom, Value); 
	} 
	return; 
} 
//UINT32 
void ChatHandler::ChangeSelectedCharMsg(const uint16 &index, const uint32 Value, const uint32 max, const uint32 min, char * nom) 
{ 
	wowWData data; 
 
	if(!TestValue(Value, max, min)) return; 
 
	Character * pChar = getSelectedChar(); 
	if(pChar!=NULL) 
	{ 
		data.Initialise( 12, index ); 
		data << pChar->getUpdateValue( OBJECT_FIELD_GUID ); 
		data << pChar->getUpdateValue( OBJECT_FIELD_GUID + 1 ); 
		data << Value; 
		pChar->SendMessageToSet( &data, true ); 
		Message(pChar, nom, Value); 
	} 
	return; 
} 
//FLOAT 
void ChatHandler::ChangeSelectedChar(const uint16 &index, const float Value, const float max, const float min, char * nom) 
{ 
	if(!TestValue(Value, max, min)) return; 
 
	Character * pChar = getSelectedChar(); 
	if(pChar!=NULL) 
	{ 
		pChar->setUpdateFloatValue(index , Value); 
		Message(pChar, nom, Value); 
	} 
	return; 
} 
//UINT32 
void ChatHandler::ChangeSelectedChar(const uint16 &index, const uint32 Value, const uint32 max, const uint32 min, char * nom) 
{ 
	if(!TestValue(Value, max, min)) return; 
 
	Character * pChar = getSelectedChar(); 
	if(pChar!=NULL) 
	{ 
		pChar->setUpdateValue(index , Value);		 
		Message(pChar, nom, Value);	 
	} 
	return; 
} 
 
//FLOAT 
void ChatHandler::Message(Character * pChar, char * nom, const float Value) 
{ 
	wowWData data; 
	uint8 buf[256]; 
 
	if(strcmp(pChar->getName(),m_pClient->getCurrentChar()->getName())!=0) 
	{ 
		// send message to user 
		sprintf((char*)buf,"You change the %s to %2.2f of %s.", nom, Value, pChar->getName()); 
		FillMessageData(&data, 0x09, m_pClient, buf); 
		m_pClient->SendMsg( &data ); 
 
		// send message to player 
		sprintf((char*)buf,"%s changed your %s to %2.2f.", m_pClient->getCurrentChar()->getName(), nom, Value); 
		FillMessageData(&data, 0x09, pChar->pClient, buf); 
		pChar->pClient->SendMsg( &data ); 
 
		// log gm command 
		FILE *pFile;
		pFile = fopen("gmcommands.log", "a");
		fprintf(pFile, "%s change %s %s to %2.2f.\n", m_pClient->getCurrentChar()->getName(), pChar->getName(), nom, Value);
		fclose(pFile);
	} 
	else 
	{ 
		// send message to user 
		sprintf((char*)buf,"You change your %s to %2.2f.", nom, Value, pChar->getName()); 
		FillMessageData(&data, 0x09, m_pClient, buf); 
		m_pClient->SendMsg( &data ); 
	} 
} 
 
//UINT32 
void ChatHandler::Message(Character * pChar, char * nom, const uint32 Value) 
{ 
	wowWData data; 
	uint8 buf[256]; 
 
	if(strcmp(pChar->getName(),m_pClient->getCurrentChar()->getName())!=0) 
	{ 
		// send message to user 
		sprintf((char*)buf,"You change the %s to %i of %s.", nom, Value, pChar->getName()); 
		FillMessageData(&data, 0x09, m_pClient, buf); 
		m_pClient->SendMsg( &data ); 
 
		// send message to player 
		sprintf((char*)buf,"%s changed your %s to %i.", m_pClient->getCurrentChar()->getName(), nom, Value); 
		FillMessageData(&data, 0x09, pChar->pClient, buf); 
		pChar->pClient->SendMsg( &data ); 
 
		// log gm command 
		FILE *pFile;
		pFile = fopen("gmcommands.log", "a");
		fprintf(pFile, "%s change %s %s to %i.\n", m_pClient->getCurrentChar()->getName(), pChar->getName(), nom, Value);
		fclose(pFile);
	} 
	else 
	{ 
		// send message to user 
		sprintf((char*)buf,"You change your %s to %i.", nom, Value, pChar->getName()); 
		FillMessageData(&data, 0x09, m_pClient, buf); 
		m_pClient->SendMsg( &data ); 
	} 
} 
void ChatHandler::Message(Character * pChar, char * nom) 
{ 
	wowWData data; 
	uint8 buf[256]; 
 
	if(strcmp(pChar->getName(),m_pClient->getCurrentChar()->getName())!=0) 
	{ 
		// send message to user 
		sprintf((char*)buf,"You %s %s.", nom, pChar->getName()); 
		FillMessageData(&data, 0x09, m_pClient, buf); 
		m_pClient->SendMsg( &data ); 
 
		// send message to player 
		sprintf((char*)buf,"%s %s you.", m_pClient->getCurrentChar()->getName(), nom); 
		FillMessageData(&data, 0x09, pChar->pClient, buf); 
		pChar->pClient->SendMsg( &data ); 
	} 
	else 
	{ 
		// send message to user 
		sprintf((char*)buf,"You %s to you.", nom); 
		FillMessageData(&data, 0x09, m_pClient, buf); 
		m_pClient->SendMsg( &data ); 
	} 
} 
 
Unit * ChatHandler::getSelectedNPC() 
{ 
	const uint32 *guid; 
				 
	guid = m_pClient->getCurrentChar()->getSelectionPtr(); 
	if (guid[0] != 0) 
	{ 
		if(guid[1]==0xF0001000) return WorldServer::getSingleton().GetCreature(guid[0]); 
	} 
 
	wowWData data; 
	FillMessageData(&data, 0x09, m_pClient,(uint8*) "Please select a NPC"); 
	m_pClient->SendMsg( &data ); 
 
	return NULL; 
} 
void ChatHandler::ChangeSelectedNPC(const uint16 &index, const uint32 Value, const uint32 max, const uint32 min) 
{ 
	wowWData data; 
 
	if(!TestValue(Value, max, min)) return; 
 
	Unit * pUnit = getSelectedNPC(); 
	if(pUnit!=NULL) 
	{ 
		pUnit->setUpdateValue(index , Value); 
				 
		DatabaseInterface *dbi = Database::getSingleton().createDatabaseInterface( ); 
		/* 
		sprintf((char*)buf, "DELETE FROM creatures WHERE id=%u", pUnit->getGUID()); 
		dbi->doQuery((char*)buf); 
		dbi->saveCreature(pUnit); 
		*/ 
		dbi->updateCreature(pUnit); 
		Database::getSingleton( ).removeDatabaseInterface(dbi); 
		pUnit->UpdateObject(); 
 
		FillMessageData(&data, 0x09, m_pClient,(uint8*)"NPC updated."); 
		m_pClient->SendMsg( &data ); 
	} 
	return; 
} 
//END OF LINA COMMAND BY PTR FONCTION PATCH 1.3

// ELECTRIX ADD START {

void ChatHandler::GenCreature(GameClient *pClient, uint32 StartId, uint32 EndId ,uint32 StepId )
{
    char* pName= "Def Name ";
    uint32 CurrentId=1;
    uint16 ModuloId=0;
    uint32 npcFlags=0;
    uint32 faction_id=0;
    uint32 level=10;
    wowWData data;

    // Create the requested monster

    Character *chr = pClient->getCurrentChar();
    float x = chr->getPositionX();
    float y = chr->getPositionY();
    float z = chr->getPositionZ();
    float o = chr->getOrientation();

    for (CurrentId=StartId;CurrentId<=EndId;CurrentId++)
    {
        x+= (float) 5.0f;
        ModuloId++;
        if ( ModuloId>=StepId)
        {
            x-= (float) 5.0f *(float) ModuloId;
            ModuloId=0;
            y+= (float) 10.0f;
        }

        sprintf(pName,"Id:%i",CurrentId);

        Unit* pUnit = new Unit();
        UpdateMask unitMask;
        WorldServer::getSingletonPtr()->mObjectMgr.SetCreateUnitBits(unitMask);

        pUnit->Create(world.m_hiCreatureGuid++, (uint8*)pName, x, y, z, o);
        pUnit->setMapId(chr->getMapId());
        pUnit->setZone(chr->getZone());
        data.clear();
        pUnit->setUpdateValue(OBJECT_FIELD_ENTRY, world.addCreatureName((uint8*)pUnit->getCreatureName()));
        pUnit->setUpdateFloatValue(OBJECT_FIELD_SCALE_X, 1.0f);
        pUnit->setUpdateValue(UNIT_FIELD_DISPLAYID, CurrentId);
        pUnit->setUpdateValue(UNIT_NPC_FLAGS , npcFlags);
        pUnit->setUpdateValue(UNIT_FIELD_FACTIONTEMPLATE , faction_id);
        pUnit->setUpdateValue(UNIT_FIELD_HEALTH, 100 + 30*level);
        pUnit->setUpdateValue(UNIT_FIELD_MAXHEALTH, 100 + 30*level);
        pUnit->setUpdateValue(UNIT_FIELD_LEVEL , level);

        pUnit->setUpdateFloatValue(UNIT_FIELD_COMBATREACH , 1.5f);
        pUnit->setUpdateFloatValue(UNIT_FIELD_MAXDAMAGE ,  5.0f);
        pUnit->setUpdateFloatValue(UNIT_FIELD_MINDAMAGE , 8.0f);
        pUnit->setUpdateValue(UNIT_FIELD_BASEATTACKTIME, 1900);
        pUnit->setUpdateValue(UNIT_FIELD_BASEATTACKTIME+1, 2000);
        pUnit->setUpdateFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 2.0f);

        pUnit->CreateObject(&unitMask, &data, 0);

        //  add to the world list of creatures
        WPAssert( pUnit->getGUID() != 0 );
        world.mCreatures[pUnit->getGUID()] = pUnit;

        // send create message to everyone
//        world.SendGlobalMessage(&data);
		world.SendUnitAreaMessage(&data, pUnit);

        DatabaseInterface *dbi = Database::getSingleton( ).createDatabaseInterface( );
        char sql[512];
        sprintf(sql, "insert into skin set id_skin='%i',name='%s',type='0',race='0', gender='0'", CurrentId,pName);
        dbi->doQuery(sql);
        //dbi->saveCreature(pUnit);
        Database::getSingleton( ).removeDatabaseInterface(dbi);
    }
}

// }ELECTRIX ADD END