/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* 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 3 of the License, or
* 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, see .
*
*/
#include "StdAfx.h"
extern std::string LogFileName;
extern bool bLogChat;
void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data, 9);
WorldPacket *data;
if(!_player->IsInWorld())
return;
uint32 type;
int32 lang;
const char * pMisc = 0;
const char * pMsg = 0;
recv_data >> type;
recv_data >> lang;
if(GetPlayer()->IsBanned())
{
GetPlayer()->BroadcastMessage("You cannot do that when banned.");
return;
}
if(lang != -1 && !GetPermissionCount() && sWorld.flood_lines)
{
/* flood detection, wheeee! */
if(World::UNIXTIME >= floodTime)
{
floodLines = 0;
floodTime = World::UNIXTIME + sWorld.flood_seconds;
}
if((++floodLines) > sWorld.flood_lines)
{
if(sWorld.flood_message)
_player->BroadcastMessage("Your message has triggered serverside flood protection. You can speak again in %u seconds.", floodTime - World::UNIXTIME);
return;
}
}
std::stringstream irctext;
irctext.rdbuf()->str("");
std::string msg;
msg.reserve(256);
//arghhh STFU. I'm not giving you gold or items NOOB
switch(type)
{
case CHAT_MSG_EMOTE:
case CHAT_MSG_SAY:
case CHAT_MSG_YELL:
case CHAT_MSG_WHISPER:
case CHAT_MSG_CHANNEL:
{
if(_player->HasMuteOnPlayer())
{
std::stringstream Reply;
Reply << "Your voice has been taken away for "<< (_player->HasMuteOnPlayer()/1000/60) << " minutes by a GM.";
data = sChatHandler.FillMessageData( CHAT_MSG_WHISPER, LANG_UNIVERSAL, Reply.str().c_str(), _player->GetGUID(), 3);
}
}
}
switch(type)
{
case CHAT_MSG_EMOTE:
{
recv_data >> msg;
if(sWorld.getReqGmClient() == false)
if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
break;
if(GetPlayer()->m_modlanguage >=0)
data = sChatHandler.FillMessageData( CHAT_MSG_EMOTE, GetPlayer()->m_modlanguage, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
else
data = sChatHandler.FillMessageData( CHAT_MSG_EMOTE, CanUseCommand('c') ? LANG_UNIVERSAL : lang, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
GetPlayer()->SendMessageToSet( data, true ,true );
sLog.outString("[emote] %s: %s", _player->GetName(), msg.c_str());
delete data;
pMsg=msg.c_str();
pMisc=0;
}break;
case CHAT_MSG_SAY:
{
recv_data >> msg;
if(sWorld.getReqGmClient() == false)
if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
break;
if(GetPlayer()->m_modlanguage >=0)
data = sChatHandler.FillMessageData( CHAT_MSG_SAY, GetPlayer()->m_modlanguage, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
else
data = sChatHandler.FillMessageData( CHAT_MSG_SAY, (CanUseCommand('c') && lang != -1) ? LANG_UNIVERSAL : lang, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
GetPlayer()->SendMessageToSet( data, true );
sLog.outString("[say] %s: %s", _player->GetName(), msg.c_str());
delete data;
pMsg=msg.c_str();
pMisc=0;
} break;
case CHAT_MSG_PARTY:
case CHAT_MSG_RAID:
case CHAT_MSG_RAIDLEADER:
case CHAT_MSG_RAIDWARNING:
{
recv_data >> msg;
if(sWorld.getReqGmClient() == false)
if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
break;
Group *pGroup = _player->GetGroup();
if(pGroup == NULL) break;
if(GetPlayer()->m_modlanguage >=0)
data=sChatHandler.FillMessageData( type, GetPlayer()->m_modlanguage, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
else
data=sChatHandler.FillMessageData( type, (CanUseCommand('c') && lang != -1) ? LANG_UNIVERSAL : lang, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0);
if(type == CHAT_MSG_PARTY && pGroup->GetGroupType() == GROUP_TYPE_RAID)
{
// only send to that subgroup
SubGroup * sgr = _player->GetGroup() ?
_player->GetGroup()->GetSubGroup(_player->GetSubGroup()) : 0;
if(sgr)
{
_player->GetGroup()->Lock();
for(GroupMembersSet::iterator itr = sgr->GetGroupMembersBegin(); itr != sgr->GetGroupMembersEnd(); ++itr)
{
if(itr->player)
itr->player->GetSession()->SendPacket(data);
}
_player->GetGroup()->Unlock();
}
}
else
{
pGroup->SendPacketToAll(data);
}
//sLog.outString("[party] %s: %s", _player->GetName(), msg.c_str());
delete data;
pMsg=msg.c_str();
pMisc=0;
} break;
case CHAT_MSG_GUILD:
{
recv_data >> msg;
if(sWorld.getReqGmClient() == false)
if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
{
break;
}
if (GetPlayer()->IsInGuild())
{
Guild *pGuild = objmgr.GetGuild( GetPlayer()->GetGuildId() );
if(pGuild)
{
if(pGuild->HasRankRight(GetPlayer()->GetGuildRank(), GR_RIGHT_GCHATSPEAK))
pGuild->BroadCastToGuild(this, msg);
else
{
WorldPacket data2(SMSG_GUILD_COMMAND_RESULT, 8 + pGuild->GetGuildName().size() + 1);
data2 << uint32(GUILD_MEMBER_S);
data2 << pGuild->GetGuildName();
data2 << uint32(C_R_DONT_HAVE_PERMISSION);
SendPacket(&data2);
}
}
}
pMsg=msg.c_str();
pMisc=0;
} break;
case CHAT_MSG_OFFICER:
{
recv_data >> msg;
if(sWorld.getReqGmClient() == false)
if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
break;
if (GetPlayer()->IsInGuild())
{
Guild *pGuild = objmgr.GetGuild( GetPlayer()->GetGuildId() );
if(pGuild)
{
if(pGuild->HasRankRight(GetPlayer()->GetGuildRank(), GR_RIGHT_OFFCHATSPEAK))
pGuild->OfficerChannelChat(this, msg);
else
{
WorldPacket data2(SMSG_GUILD_COMMAND_RESULT, 8 + pGuild->GetGuildName().size() + 1);
data2 << uint32(GUILD_MEMBER_S);
data2 << pGuild->GetGuildName();
data2 << uint32(C_R_DONT_HAVE_PERMISSION);
SendPacket(&data2);
}
}
}
pMsg=msg.c_str();
pMisc=0;
} break;
case CHAT_MSG_YELL:
{
recv_data >> msg;
if(sWorld.getReqGmClient() == false)
if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
break;
if(GetPlayer()->m_modlanguage >=0)
data = sChatHandler.FillMessageData( CHAT_MSG_YELL, GetPlayer()->m_modlanguage, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
else
data = sChatHandler.FillMessageData( CHAT_MSG_YELL, (CanUseCommand('c') && lang != -1) ? LANG_UNIVERSAL : lang, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
SendPacket(data);
sWorld.SendZoneMessage(data, GetPlayer()->GetZoneId(), this);
delete data;
sLog.outString("[yell] %s: %s", _player->GetName(), msg.c_str());
pMsg=msg.c_str();
pMisc=0;
} break;
case CHAT_MSG_WHISPER:
{
std::string to = "",tmp;
recv_data >> to >> msg;
Player *player = objmgr.GetPlayer(to.c_str(), false);
if(!player)
{
/*tmp = "Player \"";
tmp += to.c_str();
tmp += "\" is not online.";
data = sChatHandler.FillSystemMessageData( tmp.c_str() );
SendPacket(data);
delete data;*/
data = new WorldPacket(SMSG_CHAT_PLAYER_NOT_FOUND, to.length() + 1);
*data << to;
SendPacket(data);
delete data;
break;
}
// Check that the player isn't a gm with his status on
if(!_player->GetSession()->GetPermissionCount() && player->bGMTagOn && player->gmTargets.count(_player) == 0)
{
// Build automated reply
string Reply = "This Game Master does not currently have an open ticket from you and did not receive your whisper. Please submit a new GM Ticket request if you need to speak to a GM. This is an automatic message.";
data = sChatHandler.FillMessageData( CHAT_MSG_WHISPER, LANG_UNIVERSAL, Reply.c_str(), player->GetGUID(), 3);
SendPacket(data);
delete data;
break;
}
if( sSocialMgr.HasIgnore(player, GetPlayer()) )
return;
if(GetPlayer()->m_modlanguage >=0)
data = sChatHandler.FillMessageData( CHAT_MSG_WHISPER, GetPlayer()->m_modlanguage, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
else
data = sChatHandler.FillMessageData( CHAT_MSG_WHISPER, (CanUseCommand('c') && lang != -1) ? LANG_UNIVERSAL : lang, msg.c_str(), _player->GetGUID(), _player->bGMTagOn ? 4 : 0 );
player->GetSession()->SendPacket(data);
delete data;
//Sent the to Users id as the channel, this should be fine as it's not used for wisper
data = sChatHandler.FillMessageData(CHAT_MSG_WHISPER_INFORM, LANG_UNIVERSAL,msg.c_str(), player->GetGUID(), player->bGMTagOn ? 4 : 0 );
SendPacket(data);
delete data;
if(player->HasFlag(PLAYER_FLAGS, 0x02))
{
// Has AFK flag, autorespond.
data = sChatHandler.FillMessageData(CHAT_MSG_AFK, LANG_UNIVERSAL, player->m_afk_reason.c_str(),player->GetGUID(), _player->bGMTagOn ? 4 : 0);
SendPacket(data);
delete data;
}
else if(player->HasFlag(PLAYER_FLAGS, 0x04))
{
// Has AFK flag, autorespond.
data = sChatHandler.FillMessageData(CHAT_MSG_DND, LANG_UNIVERSAL, player->m_afk_reason.c_str(),player->GetGUID(), _player->bGMTagOn ? 4 : 0);
SendPacket(data);
delete data;
}
sLog.outString("[whisper] %s to %s: %s", _player->GetName(), to.c_str(), msg.c_str());
pMsg=msg.c_str();
pMisc=to.c_str();
} break;
case CHAT_MSG_CHANNEL:
{
std::string channel = "";
recv_data >> channel;
recv_data >> msg;
if(strcmp(channel.c_str(), sWorld.getGmClientChannel().c_str()) == 0)
if (sChatHandler.ParseCommands(msg.c_str(), this) > 0)
break;
Channel *chn = channelmgr.GetChannel(channel.c_str(),GetPlayer());
if(chn)
chn->Say(GetPlayer(),msg.c_str());
//sLog.outString("[%s] %s: %s", channel.c_str(), _player->GetName(), msg.c_str());
pMsg=msg.c_str();
pMisc=channel.c_str();
} break;
case CHAT_MSG_AFK:
{
std::string reason;
recv_data >> reason;
GetPlayer()->SetAFKReason(reason);
/* WorldPacket *data, WorldSession* session, uint32 type, uint32 language, const char *channelName, const char *message*/
if(GetPlayer()->HasFlag(PLAYER_FLAGS, 0x02))
{
GetPlayer()->RemoveFlag(PLAYER_FLAGS, 0x02);
if(sWorld.GetKickAFKPlayerTime())
sEventMgr.RemoveEvents(GetPlayer(),EVENT_PLAYER_SOFT_DISCONNECT);
}
else
{
GetPlayer()->SetFlag(PLAYER_FLAGS, 0x02);
if(sWorld.GetKickAFKPlayerTime())
sEventMgr.AddEvent(GetPlayer(),&Player::SoftDisconnect,EVENT_PLAYER_SOFT_DISCONNECT,sWorld.GetKickAFKPlayerTime(),1,0);
}
} break;
case CHAT_MSG_DND:
{
std::string reason;
recv_data >> reason;
GetPlayer()->SetAFKReason(reason);
if(GetPlayer()->HasFlag(PLAYER_FLAGS, 0x04))
GetPlayer()->RemoveFlag(PLAYER_FLAGS, 0x04);
else
{
GetPlayer()->SetFlag(PLAYER_FLAGS, 0x04);
}
} break;
default:
sLog.outError("CHAT: unknown msg type %u, lang: %u", type, lang);
}
if(pMsg)
sHookInterface.OnChat(_player, type, lang, pMsg, pMisc);
}
void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data, 16);
if(!_player->IsInWorld())
return;
uint64 guid;
uint32
text_emote,
unk,
namelen =1;
const char* name =" ";
recv_data >> text_emote;
recv_data >> unk;
recv_data >> guid;
Unit * pUnit = _player->GetMapMgr()->GetUnit(guid);
if(pUnit)
{
if(pUnit->IsPlayer())
{
name = static_cast(pUnit)->GetName();
namelen = strlen(name) + 1;
}
else if(pUnit->GetTypeId() == TYPEID_UNIT)
{
Creature * p = static_cast(pUnit);
if(p->GetCreatureName())
{
name = p->GetCreatureName()->Name;
namelen = strlen(name) + 1;
}
else
{
name = 0;
namelen = 0;
}
}
}
emoteentry *em = sEmoteStore.LookupEntry(text_emote);
if(em)
{
WorldPacket data(SMSG_EMOTE, 28 + namelen);
sHookInterface.OnEmote(_player, (EmoteType)em->textid);
switch(em->textid)
{
case EMOTE_STATE_SLEEP:
case EMOTE_STATE_SIT:
case EMOTE_STATE_KNEEL:
break;
default:
data << (uint32)em->textid;
data << (uint64)GetPlayer()->GetGUID();
GetPlayer()->SendMessageToSet(&data, true); //If player receives his own emote, his animation stops.
break;
}
data.Initialize(SMSG_TEXT_EMOTE);
data << (uint64)GetPlayer()->GetGUID();
data << (uint32)text_emote;
data << unk;
data << (uint32)namelen;
if( namelen > 1 ) data.append(name, namelen);
else data << (uint8)0x00;
GetPlayer()->SendMessageToSet(&data, true);
}
}
void WorldSession::HandleReportSpamOpcode(WorldPacket & recvPacket)
{
CHECK_PACKET_SIZE(recvPacket, 29);
// the 0 in the out packet is unknown
GetPlayer()->GetSession()->OutPacket(SMSG_REPORT_SPAM_RESPONSE, 1, 0 );
/* This whole thing is guess-work */
uint8 unk1;
uint64 reportedGuid;
uint32 unk2;
uint32 messagetype;
uint32 unk3;
uint32 unk4;
std::string message;
recvPacket >> unk1 >> reportedGuid >> unk2 >> messagetype >> unk3 >> unk4 >> message;
Player * rPlayer = objmgr.GetPlayer(reportedGuid);
if(!rPlayer)
return;
sSocialMgr.AddIgnore(GetPlayer(), rPlayer->GetName());
}