2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
25 #include "ObjectMgr.h"
27 #include "Database/DatabaseEnv.h"
28 #include "ChannelMgr.h"
31 #include "MapManager.h"
32 #include "ObjectAccessor.h"
33 #include "ScriptCalls.h"
35 #include "SpellAuras.h"
39 void WorldSession::HandleMessagechatOpcode( WorldPacket
& recv_data
)
41 CHECK_PACKET_SIZE(recv_data
,4+4+1);
49 if(type
>= MAX_CHAT_MSG_TYPE
)
51 sLog
.outError("CHAT: Wrong message type received: %u", type
);
55 //sLog.outDebug("CHAT: packet received. type %u, lang %u", type, lang );
57 // prevent talking at unknown language (cheating)
58 LanguageDesc
const* langDesc
= GetLanguageDescByID(lang
);
61 SendNotification(LANG_UNKNOWN_LANGUAGE
);
64 if(langDesc
->skill_id
!= 0 && !_player
->HasSkill(langDesc
->skill_id
))
66 // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language)
67 Unit::AuraList
const& langAuras
= _player
->GetAurasByType(SPELL_AURA_COMPREHEND_LANGUAGE
);
68 bool foundAura
= false;
69 for(Unit::AuraList::const_iterator i
= langAuras
.begin();i
!= langAuras
.end(); ++i
)
71 if((*i
)->GetModifier()->m_miscvalue
== lang
)
79 SendNotification(LANG_NOT_LEARNED_LANGUAGE
);
84 if(lang
== LANG_ADDON
)
86 // Disabled addon channel?
87 if(!sWorld
.getConfig(CONFIG_ADDON_CHANNEL
))
90 // LANG_ADDON should not be changed nor be affected by flood control
93 // send in universal language if player in .gmon mode (ignore spell effects)
94 if (_player
->isGameMaster())
95 lang
= LANG_UNIVERSAL
;
98 // send in universal language in two side iteration allowed mode
99 if (sWorld
.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT
))
100 lang
= LANG_UNIVERSAL
;
107 case CHAT_MSG_RAID_LEADER
:
108 case CHAT_MSG_RAID_WARNING
:
109 // allow two side chat at group channel if two side group allowed
110 if(sWorld
.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP
))
111 lang
= LANG_UNIVERSAL
;
114 case CHAT_MSG_OFFICER
:
115 // allow two side chat at guild channel if two side guild allowed
116 if(sWorld
.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD
))
117 lang
= LANG_UNIVERSAL
;
122 // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used)
123 Unit::AuraList
const& ModLangAuras
= _player
->GetAurasByType(SPELL_AURA_MOD_LANGUAGE
);
124 if(!ModLangAuras
.empty())
125 lang
= ModLangAuras
.front()->GetModifier()->m_miscvalue
;
128 if (!_player
->CanSpeak())
130 std::string timeStr
= secsToTimeString(m_muteTime
- time(NULL
));
131 SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING
),timeStr
.c_str());
135 if (type
!= CHAT_MSG_AFK
&& type
!= CHAT_MSG_DND
)
136 GetPlayer()->UpdateSpeakTime();
145 std::string msg
= "";
151 if (ChatHandler(this).ParseCommands(msg
.c_str()) > 0)
154 // strip invisible characters for non-addon messages
155 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
156 stripLineInvisibleChars(msg
);
161 if(type
== CHAT_MSG_SAY
)
162 GetPlayer()->Say(msg
, lang
);
163 else if(type
== CHAT_MSG_EMOTE
)
164 GetPlayer()->TextEmote(msg
);
165 else if(type
== CHAT_MSG_YELL
)
166 GetPlayer()->Yell(msg
, lang
);
169 case CHAT_MSG_WHISPER
:
173 CHECK_PACKET_SIZE(recv_data
,4+4+(to
.size()+1)+1);
176 // strip invisible characters for non-addon messages
177 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
178 stripLineInvisibleChars(msg
);
183 if(!normalizePlayerName(to
))
185 WorldPacket
data(SMSG_CHAT_PLAYER_NOT_FOUND
, (to
.size()+1));
191 Player
*player
= objmgr
.GetPlayer(to
.c_str());
192 uint32 tSecurity
= GetSecurity();
193 uint32 pSecurity
= player
? player
->GetSession()->GetSecurity() : 0;
194 if(!player
|| tSecurity
== SEC_PLAYER
&& pSecurity
> SEC_PLAYER
&& !player
->isAcceptWhispers())
196 WorldPacket
data(SMSG_CHAT_PLAYER_NOT_FOUND
, (to
.size()+1));
202 if (!sWorld
.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT
) && tSecurity
== SEC_PLAYER
&& pSecurity
== SEC_PLAYER
)
204 uint32 sidea
= GetPlayer()->GetTeam();
205 uint32 sideb
= player
->GetTeam();
208 WorldPacket
data(SMSG_CHAT_PLAYER_NOT_FOUND
, (to
.size()+1));
215 GetPlayer()->Whisper(msg
, lang
,player
->GetGUID());
220 std::string msg
= "";
226 if (ChatHandler(this).ParseCommands(msg
.c_str()) > 0)
229 // strip invisible characters for non-addon messages
230 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
231 stripLineInvisibleChars(msg
);
236 Group
*group
= GetPlayer()->GetGroup();
241 ChatHandler::FillMessageData(&data
, this, CHAT_MSG_PARTY
, lang
, NULL
, 0, msg
.c_str(),NULL
);
242 group
->BroadcastPacket(&data
, group
->GetMemberGroup(GetPlayer()->GetGUID()));
247 std::string msg
= "";
253 if (ChatHandler(this).ParseCommands(msg
.c_str()) > 0)
256 // strip invisible characters for non-addon messages
257 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
258 stripLineInvisibleChars(msg
);
263 if (GetPlayer()->GetGuildId())
265 Guild
*guild
= objmgr
.GetGuildById(GetPlayer()->GetGuildId());
267 guild
->BroadcastToGuild(this, msg
, lang
== LANG_ADDON
? LANG_ADDON
: LANG_UNIVERSAL
);
272 case CHAT_MSG_OFFICER
:
274 std::string msg
= "";
280 if (ChatHandler(this).ParseCommands(msg
.c_str()) > 0)
283 // strip invisible characters for non-addon messages
284 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
285 stripLineInvisibleChars(msg
);
290 if (GetPlayer()->GetGuildId())
292 Guild
*guild
= objmgr
.GetGuildById(GetPlayer()->GetGuildId());
294 guild
->BroadcastToOfficers(this, msg
, lang
== LANG_ADDON
? LANG_ADDON
: LANG_UNIVERSAL
);
306 if (ChatHandler(this).ParseCommands(msg
.c_str()) > 0)
309 // strip invisible characters for non-addon messages
310 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
311 stripLineInvisibleChars(msg
);
316 Group
*group
= GetPlayer()->GetGroup();
317 if(!group
|| !group
->isRaidGroup())
321 ChatHandler::FillMessageData(&data
, this, CHAT_MSG_RAID
, lang
, "", 0, msg
.c_str(),NULL
);
322 group
->BroadcastPacket(&data
);
324 case CHAT_MSG_RAID_LEADER
:
332 if (ChatHandler(this).ParseCommands(msg
.c_str()) > 0)
335 // strip invisible characters for non-addon messages
336 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
337 stripLineInvisibleChars(msg
);
342 Group
*group
= GetPlayer()->GetGroup();
343 if(!group
|| !group
->isRaidGroup() || !group
->IsLeader(GetPlayer()->GetGUID()))
347 ChatHandler::FillMessageData(&data
, this, CHAT_MSG_RAID_LEADER
, lang
, "", 0, msg
.c_str(),NULL
);
348 group
->BroadcastPacket(&data
);
350 case CHAT_MSG_RAID_WARNING
:
355 // strip invisible characters for non-addon messages
356 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
357 stripLineInvisibleChars(msg
);
362 Group
*group
= GetPlayer()->GetGroup();
363 if(!group
|| !group
->isRaidGroup() || !(group
->IsLeader(GetPlayer()->GetGUID()) || group
->IsAssistant(GetPlayer()->GetGUID())))
367 ChatHandler::FillMessageData(&data
, this, CHAT_MSG_RAID_WARNING
, lang
, "", 0, msg
.c_str(),NULL
);
368 group
->BroadcastPacket(&data
);
371 case CHAT_MSG_BATTLEGROUND
:
376 // strip invisible characters for non-addon messages
377 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
378 stripLineInvisibleChars(msg
);
383 Group
*group
= GetPlayer()->GetGroup();
384 if(!group
|| !group
->isRaidGroup())
388 ChatHandler::FillMessageData(&data
, this, CHAT_MSG_BATTLEGROUND
, lang
, "", 0, msg
.c_str(),NULL
);
389 group
->BroadcastPacket(&data
);
392 case CHAT_MSG_BATTLEGROUND_LEADER
:
397 // strip invisible characters for non-addon messages
398 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
399 stripLineInvisibleChars(msg
);
404 Group
*group
= GetPlayer()->GetGroup();
405 if(!group
|| !group
->isRaidGroup() || !group
->IsLeader(GetPlayer()->GetGUID()))
409 ChatHandler::FillMessageData(&data
, this, CHAT_MSG_BATTLEGROUND_LEADER
, lang
, "", 0, msg
.c_str(),NULL
);
410 group
->BroadcastPacket(&data
);
413 case CHAT_MSG_CHANNEL
:
415 std::string channel
= "", msg
= "";
416 recv_data
>> channel
;
419 CHECK_PACKET_SIZE(recv_data
,4+4+(channel
.size()+1)+1);
423 // strip invisible characters for non-addon messages
424 if (lang
!= LANG_ADDON
&& sWorld
.getConfig(CONFIG_CHAT_FAKE_MESSAGE_PREVENTING
))
425 stripLineInvisibleChars(msg
);
430 if(ChannelMgr
* cMgr
= channelMgr(_player
->GetTeam()))
432 if(Channel
*chn
= cMgr
->GetChannel(channel
,_player
))
433 chn
->Say(_player
->GetGUID(),msg
.c_str(),lang
);
442 if((msg
.empty() || !_player
->isAFK()) && !_player
->isInCombat() )
444 if(!_player
->isAFK())
447 msg
= GetMangosString(LANG_PLAYER_AFK_DEFAULT
);
448 _player
->afkMsg
= msg
;
450 _player
->ToggleAFK();
451 if(_player
->isAFK() && _player
->isDND())
452 _player
->ToggleDND();
461 if(msg
.empty() || !_player
->isDND())
463 if(!_player
->isDND())
466 msg
= GetMangosString(LANG_PLAYER_DND_DEFAULT
);
467 _player
->dndMsg
= msg
;
469 _player
->ToggleDND();
470 if(_player
->isDND() && _player
->isAFK())
471 _player
->ToggleAFK();
476 sLog
.outError("CHAT: unknown message type %u, lang: %u", type
, lang
);
481 void WorldSession::HandleEmoteOpcode( WorldPacket
& recv_data
)
483 if(!GetPlayer()->isAlive())
485 CHECK_PACKET_SIZE(recv_data
,4);
489 GetPlayer()->HandleEmoteCommand(emote
);
492 void WorldSession::HandleTextEmoteOpcode( WorldPacket
& recv_data
)
494 if(!GetPlayer()->isAlive())
497 if (!GetPlayer()->CanSpeak())
499 std::string timeStr
= secsToTimeString(m_muteTime
- time(NULL
));
500 SendNotification(GetMangosString(LANG_WAIT_BEFORE_SPEAKING
),timeStr
.c_str());
504 CHECK_PACKET_SIZE(recv_data
,4+4+8);
506 uint32 text_emote
, emoteNum
;
509 recv_data
>> text_emote
;
510 recv_data
>> emoteNum
;
516 Unit
* unit
= ObjectAccessor::GetUnit(*_player
, guid
);
517 Creature
*pCreature
= dynamic_cast<Creature
*>(unit
);
520 nam
= unit
->GetName();
521 namlen
= (nam
? strlen(nam
) : 0) + 1;
524 EmotesTextEntry
const *em
= sEmotesTextStore
.LookupEntry(text_emote
);
527 uint32 emote_anim
= em
->textid
;
533 case EMOTE_STATE_SLEEP
:
534 case EMOTE_STATE_SIT
:
535 case EMOTE_STATE_KNEEL
:
536 case EMOTE_ONESHOT_NONE
:
539 GetPlayer()->HandleEmoteCommand(emote_anim
);
543 data
.Initialize(SMSG_TEXT_EMOTE
, (20+namlen
));
544 data
<< GetPlayer()->GetGUID();
545 data
<< (uint32
)text_emote
;
547 data
<< (uint32
)namlen
;
550 data
.append(nam
, namlen
);
557 GetPlayer()->SendMessageToSetInRange(&data
,sWorld
.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE
),true);
559 //Send scripted event call
560 if (pCreature
&& Script
)
561 Script
->ReceiveEmote(GetPlayer(),pCreature
,text_emote
);
565 void WorldSession::HandleChatIgnoredOpcode(WorldPacket
& recv_data
)
567 CHECK_PACKET_SIZE(recv_data
, 8+1);
571 //sLog.outDebug("WORLD: Received CMSG_CHAT_IGNORED");
574 recv_data
>> unk
; // probably related to spam reporting
576 Player
*player
= objmgr
.GetPlayer(iguid
);
577 if(!player
|| !player
->GetSession())
581 ChatHandler::FillMessageData(&data
, this, CHAT_MSG_IGNORED
, LANG_UNIVERSAL
, NULL
, GetPlayer()->GetGUID(), GetPlayer()->GetName(),NULL
);
582 player
->GetSession()->SendPacket(&data
);