[11575] Add support for simulating Yells to Map.

Including case when related creature not loaded.
For proper animation yell from loaded creature for near players
better use correct lowguid/guid if creature.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
Schmoozerd 2011-05-31 05:12:33 +04:00 committed by VladimirMangos
parent 7995a36c69
commit 2d82b4bccc
5 changed files with 127 additions and 11 deletions

View file

@ -3087,3 +3087,111 @@ uint32 Map::GenerateLocalLowGuid(HighGuid guidhigh)
MANGOS_ASSERT(0); MANGOS_ASSERT(0);
return 0; return 0;
} }
/**
* Helper structure for building static chat information
*
*/
class StaticMonsterChatBuilder
{
public:
StaticMonsterChatBuilder(CreatureInfo const* cInfo, ChatMsg msgtype, int32 textId, uint32 language, Unit* target, uint32 senderLowGuid = 0)
: i_cInfo(cInfo), i_msgtype(msgtype), i_textId(textId), i_language(language), i_target(target)
{
// 0 lowguid not used in core, but accepted fine in this case by client
i_senderGuid = i_cInfo->GetObjectGuid(senderLowGuid);
}
void operator()(WorldPacket& data, int32 loc_idx)
{
char const* text = sObjectMgr.GetMangosString(i_textId,loc_idx);
std::string nameForLocale = "";
if (loc_idx >= 0)
{
CreatureLocale const *cl = sObjectMgr.GetCreatureLocale(i_cInfo->Entry);
if (cl)
{
if (cl->Name.size() > (size_t)loc_idx && !cl->Name[loc_idx].empty())
nameForLocale = cl->Name[loc_idx];
}
}
if (nameForLocale.empty())
nameForLocale = i_cInfo->Name;
WorldObject::BuildMonsterChat(&data, i_senderGuid, i_msgtype, text, i_language, nameForLocale.c_str(), i_target ? i_target->GetObjectGuid() : ObjectGuid(), i_target ? i_target->GetNameForLocaleIdx(loc_idx) : "");
}
private:
ObjectGuid i_senderGuid;
CreatureInfo const* i_cInfo;
ChatMsg i_msgtype;
int32 i_textId;
uint32 i_language;
Unit* i_target;
};
/**
* Function simulates yell of creature
*
* @param guid must be creature guid of whom to Simulate the yell, non-creature guids not supported at this moment
* @param textId Id of the simulated text
* @param language language of the text
* @param target, can be NULL
*/
void Map::MonsterYellToMap(ObjectGuid guid, int32 textId, uint32 language, Unit* target)
{
if (guid.IsAnyTypeCreature())
{
CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(guid.GetEntry());
if (!cInfo)
{
sLog.outError("Map::MonsterYellToMap: Called for nonexistent creature entry in guid: %s", guid.GetString().c_str());
return;
}
MonsterYellToMap(cInfo, textId, language, target, guid.GetCounter());
}
else
{
sLog.outError("Map::MonsterYellToMap: Called for non creature guid: %s", guid.GetString().c_str());
return;
}
}
/**
* Function simulates yell of creature
*
* @param cinfo must be entry of Creature of whom to Simulate the yell
* @param textId Id of the simulated text
* @param language language of the text
* @param target, can be NULL
* @param senderLowGuid provide way proper show yell for near spawned creature with known lowguid,
* 0 accepted by client else if this not important
*/
void Map::MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, uint32 language, Unit* target, uint32 senderLowGuid /*= 0*/)
{
StaticMonsterChatBuilder say_build(cinfo, CHAT_MSG_MONSTER_YELL, textId, language, target, senderLowGuid);
MaNGOS::LocalizedPacketDo<StaticMonsterChatBuilder> say_do(say_build);
Map::PlayerList const& pList = GetPlayers();
for (PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
say_do(itr->getSource());
}
/**
* Function to play sound to all players in map
*
* @param soundId Played Sound
*/
void Map::PlayDirectSoundToMap(uint32 soundId)
{
WorldPacket data(SMSG_PLAY_SOUND, 4);
data << uint32(soundId);
Map::PlayerList const& pList = GetPlayers();
for (PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
itr->getSource()->SendDirectMessage(&data);
}

View file

@ -40,6 +40,7 @@
#include <bitset> #include <bitset>
#include <list> #include <list>
struct CreatureInfo;
class Creature; class Creature;
class Unit; class Unit;
class WorldPacket; class WorldPacket;
@ -94,6 +95,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
friend class MapReference; friend class MapReference;
friend class ObjectGridLoader; friend class ObjectGridLoader;
friend class ObjectWorldLoader; friend class ObjectWorldLoader;
protected: protected:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
@ -252,6 +254,11 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
void CreateInstanceData(bool load); void CreateInstanceData(bool load);
InstanceData* GetInstanceData() { return i_data; } InstanceData* GetInstanceData() { return i_data; }
uint32 GetScriptId() const { return i_script_id; } uint32 GetScriptId() const { return i_script_id; }
void MonsterYellToMap(ObjectGuid guid, int32 textId, uint32 language, Unit* target);
void MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, uint32 language, Unit* target, uint32 senderLowGuid = 0);
void PlayDirectSoundToMap(uint32 soundId);
private: private:
void LoadMapAndVMap(int gx, int gy); void LoadMapAndVMap(int gx, int gy);
@ -289,8 +296,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
void SendObjectUpdates(); void SendObjectUpdates();
std::set<Object *> i_objectsToClientUpdate; std::set<Object *> i_objectsToClientUpdate;
protected:
protected:
MapEntry const* i_mapEntry; MapEntry const* i_mapEntry;
uint8 i_spawnMode; uint8 i_spawnMode;
uint32 i_id; uint32 i_id;
@ -306,6 +313,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>
ActiveNonPlayers m_activeNonPlayers; ActiveNonPlayers m_activeNonPlayers;
ActiveNonPlayers::iterator m_activeNonPlayersIter; ActiveNonPlayers::iterator m_activeNonPlayersIter;
MapStoredObjectTypesContainer m_objectsStore; MapStoredObjectTypesContainer m_objectsStore;
private: private:
time_t i_gridExpiry; time_t i_gridExpiry;

View file

@ -1471,21 +1471,21 @@ bool WorldObject::IsPositionValid() const
void WorldObject::MonsterSay(const char* text, uint32 language, Unit* target) void WorldObject::MonsterSay(const char* text, uint32 language, Unit* target)
{ {
WorldPacket data(SMSG_MESSAGECHAT, 200); WorldPacket data(SMSG_MESSAGECHAT, 200);
BuildMonsterChat(&data, CHAT_MSG_MONSTER_SAY, text, language, GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : ""); BuildMonsterChat(&data, GetObjectGuid(), CHAT_MSG_MONSTER_SAY, text, language, GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),true); SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),true);
} }
void WorldObject::MonsterYell(const char* text, uint32 language, Unit* target) void WorldObject::MonsterYell(const char* text, uint32 language, Unit* target)
{ {
WorldPacket data(SMSG_MESSAGECHAT, 200); WorldPacket data(SMSG_MESSAGECHAT, 200);
BuildMonsterChat(&data, CHAT_MSG_MONSTER_YELL, text, language, GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : ""); BuildMonsterChat(&data, GetObjectGuid(), CHAT_MSG_MONSTER_YELL, text, language, GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL),true); SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL),true);
} }
void WorldObject::MonsterTextEmote(const char* text, Unit* target, bool IsBossEmote) void WorldObject::MonsterTextEmote(const char* text, Unit* target, bool IsBossEmote)
{ {
WorldPacket data(SMSG_MESSAGECHAT, 200); WorldPacket data(SMSG_MESSAGECHAT, 200);
BuildMonsterChat(&data, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, text, LANG_UNIVERSAL, BuildMonsterChat(&data, GetObjectGuid(), IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, text, LANG_UNIVERSAL,
GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : ""); GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
SendMessageToSetInRange(&data, sWorld.getConfig(IsBossEmote ? CONFIG_FLOAT_LISTEN_RANGE_YELL : CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE), true); SendMessageToSetInRange(&data, sWorld.getConfig(IsBossEmote ? CONFIG_FLOAT_LISTEN_RANGE_YELL : CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE), true);
} }
@ -1496,7 +1496,7 @@ void WorldObject::MonsterWhisper(const char* text, Unit* target, bool IsBossWhis
return; return;
WorldPacket data(SMSG_MESSAGECHAT, 200); WorldPacket data(SMSG_MESSAGECHAT, 200);
BuildMonsterChat(&data, IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL, BuildMonsterChat(&data, GetObjectGuid(), IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL,
GetName(), target->GetObjectGuid(), target->GetName()); GetName(), target->GetObjectGuid(), target->GetName());
((Player*)target)->GetSession()->SendPacket(&data); ((Player*)target)->GetSession()->SendPacket(&data);
} }
@ -1512,7 +1512,7 @@ namespace MaNGOS
{ {
char const* text = sObjectMgr.GetMangosString(i_textId,loc_idx); char const* text = sObjectMgr.GetMangosString(i_textId,loc_idx);
i_object.BuildMonsterChat(&data, i_msgtype, text, i_language, i_object.GetNameForLocaleIdx(loc_idx), i_target ? i_target->GetObjectGuid() : ObjectGuid(), i_target ? i_target->GetNameForLocaleIdx(loc_idx) : ""); WorldObject::BuildMonsterChat(&data, i_object.GetObjectGuid(), i_msgtype, text, i_language, i_object.GetNameForLocaleIdx(loc_idx), i_target ? i_target->GetObjectGuid() : ObjectGuid(), i_target ? i_target->GetNameForLocaleIdx(loc_idx) : "");
} }
private: private:
@ -1574,17 +1574,17 @@ void WorldObject::MonsterWhisper(int32 textId, Unit* target, bool IsBossWhisper)
char const* text = sObjectMgr.GetMangosString(textId, loc_idx); char const* text = sObjectMgr.GetMangosString(textId, loc_idx);
WorldPacket data(SMSG_MESSAGECHAT, 200); WorldPacket data(SMSG_MESSAGECHAT, 200);
BuildMonsterChat(&data, IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL, BuildMonsterChat(&data, GetObjectGuid(), IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL,
GetNameForLocaleIdx(loc_idx), target->GetObjectGuid(), ""); GetNameForLocaleIdx(loc_idx), target->GetObjectGuid(), "");
((Player*)target)->GetSession()->SendPacket(&data); ((Player*)target)->GetSession()->SendPacket(&data);
} }
void WorldObject::BuildMonsterChat(WorldPacket *data, uint8 msgtype, char const* text, uint32 language, char const* name, ObjectGuid targetGuid, char const* targetName) const void WorldObject::BuildMonsterChat(WorldPacket *data, ObjectGuid senderGuid, uint8 msgtype, char const* text, uint32 language, char const* name, ObjectGuid targetGuid, char const* targetName)
{ {
*data << uint8(msgtype); *data << uint8(msgtype);
*data << uint32(language); *data << uint32(language);
*data << ObjectGuid(GetObjectGuid()); *data << ObjectGuid(senderGuid);
*data << uint32(0); // 2.1.0 *data << uint32(0); // 2.1.0
*data << uint32(strlen(name)+1); *data << uint32(strlen(name)+1);
*data << name; *data << name;

View file

@ -542,7 +542,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void MonsterTextEmote(int32 textId, Unit* target, bool IsBossEmote = false); void MonsterTextEmote(int32 textId, Unit* target, bool IsBossEmote = false);
void MonsterWhisper(int32 textId, Unit* receiver, bool IsBossWhisper = false); void MonsterWhisper(int32 textId, Unit* receiver, bool IsBossWhisper = false);
void MonsterYellToZone(int32 textId, uint32 language, Unit* target); void MonsterYellToZone(int32 textId, uint32 language, Unit* target);
void BuildMonsterChat(WorldPacket *data, uint8 msgtype, char const* text, uint32 language, char const* name, ObjectGuid targetGuid, char const* targetName) const; static void BuildMonsterChat(WorldPacket *data, ObjectGuid senderGuid, uint8 msgtype, char const* text, uint32 language, char const* name, ObjectGuid targetGuid, char const* targetName);
void PlayDistanceSound(uint32 sound_id, Player* target = NULL); void PlayDistanceSound(uint32 sound_id, Player* target = NULL);
void PlayDirectSound(uint32 sound_id, Player* target = NULL); void PlayDirectSound(uint32 sound_id, Player* target = NULL);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11574" #define REVISION_NR "11575"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__