mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
50 plus cmangos updates implemented (to c12832)
Implemented over 50 updates from the cmangos Cata repo, up to and including c12832 Improve random movement The core will now work with the creature_template update that was applied to the database yesterday.
This commit is contained in:
parent
12f8fbf37d
commit
e4d1bdfc74
80 changed files with 3164 additions and 2965 deletions
1129
doc/EventAI.md
1129
doc/EventAI.md
File diff suppressed because it is too large
Load diff
|
|
@ -53,6 +53,9 @@ namespace MaNGOS
|
|||
{
|
||||
char const* text = sObjectMgr.GetMangosString(i_textId, loc_idx);
|
||||
|
||||
ObjectGuid sourceGuid = i_source ? i_source->GetObjectGuid() : ObjectGuid();
|
||||
std::string sourceName = i_source ? i_source->GetName() : "";
|
||||
|
||||
if (i_args)
|
||||
{
|
||||
// we need copy va_list before use or original va_list will corrupted
|
||||
|
|
@ -63,26 +66,12 @@ namespace MaNGOS
|
|||
vsnprintf(str, 2048, text, ap);
|
||||
va_end(ap);
|
||||
|
||||
do_helper(data, &str[0]);
|
||||
ChatHandler::BuildChatPacket(data, i_msgtype, &str[0], LANG_UNIVERSAL, CHAT_TAG_NONE, sourceGuid, sourceName.c_str());
|
||||
}
|
||||
else
|
||||
do_helper(data, text);
|
||||
ChatHandler::BuildChatPacket(data, i_msgtype, text, LANG_UNIVERSAL, CHAT_TAG_NONE, sourceGuid, sourceName.c_str(), sourceGuid, sourceName.c_str());
|
||||
}
|
||||
private:
|
||||
void do_helper(WorldPacket& data, char const* text)
|
||||
{
|
||||
ObjectGuid targetGuid = i_source ? i_source ->GetObjectGuid() : ObjectGuid();
|
||||
|
||||
data << uint8(i_msgtype);
|
||||
data << uint32(LANG_UNIVERSAL);
|
||||
data << ObjectGuid(targetGuid); // there 0 for BG messages
|
||||
data << uint32(0); // can be chat msg group or something
|
||||
data << ObjectGuid(targetGuid);
|
||||
data << uint32(strlen(text) + 1);
|
||||
data << text;
|
||||
data << uint8(i_source ? i_source->GetChatTag() : uint8(CHAT_TAG_NONE));
|
||||
}
|
||||
|
||||
ChatMsg i_msgtype;
|
||||
int32 i_textId;
|
||||
Player const* i_source;
|
||||
|
|
@ -91,8 +80,8 @@ namespace MaNGOS
|
|||
|
||||
class BattleGroundYellBuilder
|
||||
{
|
||||
public:
|
||||
BattleGroundYellBuilder(uint32 language, int32 textId, Creature const* source, va_list* args = NULL)
|
||||
public:
|
||||
BattleGroundYellBuilder(Language language, int32 textId, Creature const* source, va_list* args = nullptr)
|
||||
: i_language(language), i_textId(textId), i_source(source), i_args(args) {}
|
||||
void operator()(WorldPacket& data, int32 loc_idx)
|
||||
{
|
||||
|
|
@ -108,28 +97,13 @@ namespace MaNGOS
|
|||
vsnprintf(str, 2048, text, ap);
|
||||
va_end(ap);
|
||||
|
||||
do_helper(data, &str[0]);
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_MONSTER_YELL, &str[0], i_language, CHAT_TAG_NONE, i_source->GetObjectGuid(), i_source->GetName());
|
||||
}
|
||||
else
|
||||
do_helper(data, text);
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_MONSTER_YELL, text, i_language, CHAT_TAG_NONE, i_source->GetObjectGuid(), i_source->GetName());
|
||||
}
|
||||
private:
|
||||
void do_helper(WorldPacket& data, char const* text)
|
||||
{
|
||||
// copyied from BuildMonsterChat
|
||||
data << uint8(CHAT_MSG_MONSTER_YELL);
|
||||
data << uint32(i_language);
|
||||
data << ObjectGuid(i_source->GetObjectGuid());
|
||||
data << uint32(0); // 2.1.0
|
||||
data << uint32(strlen(i_source->GetName()) + 1);
|
||||
data << i_source->GetName();
|
||||
data << ObjectGuid(); // Unit Target - isn't important for bgs
|
||||
data << uint32(strlen(text) + 1);
|
||||
data << text;
|
||||
data << uint8(0); // ChatTag - for bgs allways 0?
|
||||
}
|
||||
|
||||
uint32 i_language;
|
||||
Language i_language;
|
||||
int32 i_textId;
|
||||
Creature const* i_source;
|
||||
va_list* i_args;
|
||||
|
|
@ -150,19 +124,16 @@ namespace MaNGOS
|
|||
char str [2048];
|
||||
snprintf(str, 2048, text, arg1str, arg2str);
|
||||
|
||||
ObjectGuid targetGuid = i_source ? i_source ->GetObjectGuid() : ObjectGuid();
|
||||
|
||||
data << uint8(i_msgtype);
|
||||
data << uint32(LANG_UNIVERSAL);
|
||||
data << ObjectGuid(targetGuid); // there 0 for BG messages
|
||||
data << uint32(0); // can be chat msg group or something
|
||||
data << ObjectGuid(targetGuid);
|
||||
data << uint32(strlen(str) + 1);
|
||||
data << str;
|
||||
data << uint8(i_source ? i_source->GetChatTag() : uint8(CHAT_TAG_NONE));
|
||||
ObjectGuid guid;
|
||||
char const* pName = nullptr;
|
||||
if (i_source)
|
||||
{
|
||||
guid = i_source->GetObjectGuid();
|
||||
pName = i_source->GetName();
|
||||
}
|
||||
ChatHandler::BuildChatPacket(data, i_msgtype, str, LANG_UNIVERSAL, CHAT_TAG_NONE, ObjectGuid(), nullptr, guid, pName);
|
||||
}
|
||||
private:
|
||||
|
||||
ChatMsg i_msgtype;
|
||||
int32 i_textId;
|
||||
Player const* i_source;
|
||||
|
|
@ -1589,7 +1560,7 @@ void BattleGround::SendYellToAll(int32 entry, uint32 language, ObjectGuid guid)
|
|||
Creature* source = GetBgMap()->GetCreature(guid);
|
||||
if (!source)
|
||||
return;
|
||||
MaNGOS::BattleGroundYellBuilder bg_builder(language, entry, source);
|
||||
MaNGOS::BattleGroundYellBuilder bg_builder(Language(language), entry, source);
|
||||
MaNGOS::LocalizedPacketDo<MaNGOS::BattleGroundYellBuilder> bg_do(bg_builder);
|
||||
BroadcastWorker(bg_do);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,19 +178,19 @@ void BattleGroundEY::HandleGameObjectCreate(GameObject* go)
|
|||
{
|
||||
case GO_CAPTURE_POINT_BLOOD_ELF_TOWER:
|
||||
m_towers[NODE_BLOOD_ELF_TOWER] = go->GetObjectGuid();
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE);
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE, false);
|
||||
break;
|
||||
case GO_CAPTURE_POINT_FEL_REAVER_RUINS:
|
||||
m_towers[NODE_FEL_REAVER_RUINS] = go->GetObjectGuid();
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE);
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE, false);
|
||||
break;
|
||||
case GO_CAPTURE_POINT_MAGE_TOWER:
|
||||
m_towers[NODE_MAGE_TOWER] = go->GetObjectGuid();
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE);
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE, false);
|
||||
break;
|
||||
case GO_CAPTURE_POINT_DRAENEI_RUINS:
|
||||
m_towers[NODE_DRAENEI_RUINS] = go->GetObjectGuid();
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE);
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ bool ChatHandler::HandleNpcSayCommand(char* args)
|
|||
return false;
|
||||
}
|
||||
|
||||
pCreature->MonsterSay(args, LANG_UNIVERSAL);
|
||||
pCreature->MonsterSay(args, LANG_UNIVERSAL, m_session->GetPlayer());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ bool ChatHandler::HandleNpcYellCommand(char* args)
|
|||
return false;
|
||||
}
|
||||
|
||||
pCreature->MonsterYell(args, LANG_UNIVERSAL);
|
||||
pCreature->MonsterYell(args, LANG_UNIVERSAL, m_session->GetPlayer());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ bool ChatHandler::HandleNpcTextEmoteCommand(char* args)
|
|||
return false;
|
||||
}
|
||||
|
||||
pCreature->MonsterTextEmote(args, NULL);
|
||||
pCreature->MonsterTextEmote(args, m_session->GetPlayer());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -909,9 +909,9 @@ bool ChatHandler::HandleModifyFactionCommand(char* args)
|
|||
{
|
||||
uint32 factionid = chr->getFaction();
|
||||
uint32 flag = chr->GetUInt32Value(UNIT_FIELD_FLAGS);
|
||||
uint32 npcflag = chr->GetUInt32Value(UNIT_NPC_FLAGS);
|
||||
uint32 NpcFlags = chr->GetUInt32Value(UNIT_NPC_FLAGS);
|
||||
uint32 dyflag = chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS);
|
||||
PSendSysMessage(LANG_CURRENT_FACTION, chr->GetGUIDLow(), factionid, flag, npcflag, dyflag);
|
||||
PSendSysMessage(LANG_CURRENT_FACTION, chr->GetGUIDLow(), factionid, flag, NpcFlags, dyflag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -938,19 +938,19 @@ bool ChatHandler::HandleModifyFactionCommand(char* args)
|
|||
if (!ExtractOptUInt32(&args, flag, chr->GetUInt32Value(UNIT_FIELD_FLAGS)))
|
||||
return false;
|
||||
|
||||
uint32 npcflag;
|
||||
if (!ExtractOptUInt32(&args, npcflag, chr->GetUInt32Value(UNIT_NPC_FLAGS)))
|
||||
uint32 NpcFlags;
|
||||
if (!ExtractOptUInt32(&args, NpcFlags, chr->GetUInt32Value(UNIT_NPC_FLAGS)))
|
||||
return false;
|
||||
|
||||
uint32 dyflag;
|
||||
if (!ExtractOptUInt32(&args, dyflag, chr->GetUInt32Value(UNIT_DYNAMIC_FLAGS)))
|
||||
return false;
|
||||
|
||||
PSendSysMessage(LANG_YOU_CHANGE_FACTION, chr->GetGUIDLow(), factionid, flag, npcflag, dyflag);
|
||||
PSendSysMessage(LANG_YOU_CHANGE_FACTION, chr->GetGUIDLow(), factionid, flag, NpcFlags, dyflag);
|
||||
|
||||
chr->setFaction(factionid);
|
||||
chr->SetUInt32Value(UNIT_FIELD_FLAGS, flag);
|
||||
chr->SetUInt32Value(UNIT_NPC_FLAGS, npcflag);
|
||||
chr->SetUInt32Value(UNIT_NPC_FLAGS, NpcFlags);
|
||||
chr->SetUInt32Value(UNIT_DYNAMIC_FLAGS, dyflag);
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1878,7 +1878,7 @@ bool ChatHandler::HandleNpcChangeLevelCommand(char* args)
|
|||
return true;
|
||||
}
|
||||
|
||||
// set npcflag of creature
|
||||
// set NpcFlags of creature
|
||||
bool ChatHandler::HandleNpcFlagCommand(char* args)
|
||||
{
|
||||
if (!*args)
|
||||
|
|
@ -1897,7 +1897,7 @@ bool ChatHandler::HandleNpcFlagCommand(char* args)
|
|||
|
||||
pCreature->SetUInt32Value(UNIT_NPC_FLAGS, npcFlags);
|
||||
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_template SET npcflag = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_template SET NpcFlags = '%u' WHERE entry = '%u'", npcFlags, pCreature->GetEntry());
|
||||
|
||||
SendSysMessage(LANG_VALUE_SAVED_REJOIN);
|
||||
|
||||
|
|
|
|||
|
|
@ -1137,6 +1137,14 @@ bool ChatHandler::HandleReloadMailLevelRewardCommand(char* /*args*/)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleReloadCreaturesStatsCommand(char* /*args*/)
|
||||
{
|
||||
sLog.outString("Re-Loading stats data...");
|
||||
sObjectMgr.LoadCreatureClassLvlStats();
|
||||
SendGlobalSysMessage("DB table `creature_template_classlevelstats` reloaded.");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleLoadScriptsCommand(char* args)
|
||||
{
|
||||
if (!*args)
|
||||
|
|
@ -2472,7 +2480,7 @@ bool ChatHandler::HandleLearnAllMyPetTalentsCommand(char* /*args*/)
|
|||
return false;
|
||||
}
|
||||
|
||||
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
|
||||
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->Family);
|
||||
if (!pet_family)
|
||||
{
|
||||
SendSysMessage(LANG_WRONG_PET_TYPE);
|
||||
|
|
@ -4338,7 +4346,7 @@ bool ChatHandler::HandleNpcInfoCommand(char* /*args*/)
|
|||
}
|
||||
|
||||
uint32 faction = target->getFaction();
|
||||
uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS);
|
||||
uint32 NpcFlagss = target->GetUInt32Value(UNIT_NPC_FLAGS);
|
||||
uint32 displayid = target->GetDisplayId();
|
||||
uint32 nativeid = target->GetNativeDisplayId();
|
||||
uint32 Entry = target->GetEntry();
|
||||
|
|
@ -4358,25 +4366,25 @@ bool ChatHandler::HandleNpcInfoCommand(char* /*args*/)
|
|||
break;
|
||||
|
||||
if (diff < MAX_DIFFICULTY)
|
||||
PSendSysMessage(LANG_NPCINFO_CHAR_DIFFICULTY, target->GetGuidStr().c_str(), faction, npcflags,
|
||||
PSendSysMessage(LANG_NPCINFO_CHAR_DIFFICULTY, target->GetGuidStr().c_str(), faction, NpcFlagss,
|
||||
Entry, target->GetCreatureInfo()->Entry, diff,
|
||||
displayid, nativeid);
|
||||
else
|
||||
PSendSysMessage(LANG_NPCINFO_CHAR, target->GetGuidStr().c_str(), faction, npcflags, Entry, displayid, nativeid);
|
||||
PSendSysMessage(LANG_NPCINFO_CHAR, target->GetGuidStr().c_str(), faction, NpcFlagss, Entry, displayid, nativeid);
|
||||
|
||||
PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel());
|
||||
PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth());
|
||||
PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction());
|
||||
PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(), curRespawnDelayStr.c_str());
|
||||
PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->lootid, cInfo->pickpocketLootId, cInfo->SkinLootId);
|
||||
PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->LootId, cInfo->PickpocketLootId, cInfo->SkinningLootId);
|
||||
PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId());
|
||||
PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ()));
|
||||
|
||||
if ((npcflags & UNIT_NPC_FLAG_VENDOR))
|
||||
if ((NpcFlagss & UNIT_NPC_FLAG_VENDOR))
|
||||
{
|
||||
SendSysMessage(LANG_NPCINFO_VENDOR);
|
||||
}
|
||||
if ((npcflags & UNIT_NPC_FLAG_TRAINER))
|
||||
if ((NpcFlagss & UNIT_NPC_FLAG_TRAINER))
|
||||
{
|
||||
SendSysMessage(LANG_NPCINFO_TRAINER);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ bool ChatHandler::HandleDebugSendChatMsgCommand(char* args)
|
|||
return false;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, m_session, type, 0, "chan", m_session->GetPlayer()->GetObjectGuid(), msg, m_session->GetPlayer());
|
||||
ChatHandler::BuildChatPacket(data, ChatMsg(type), msg, LANG_UNIVERSAL, CHAT_TAG_NONE, m_session->GetPlayer()->GetObjectGuid(), m_session->GetPlayerName());
|
||||
m_session->SendPacket(&data);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,13 +46,42 @@ RandomMovementGenerator<Creature>::RandomMovementGenerator(const Creature& creat
|
|||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
|
||||
{
|
||||
float destX = i_x;
|
||||
float destY = i_y;
|
||||
float destZ = i_z;
|
||||
|
||||
creature.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||
|
||||
// check if new random position is assigned, GetReachableRandomPosition may fail
|
||||
if (creature.GetMap()->GetReachableRandomPosition(&creature, destX, destY, destZ, i_radius))
|
||||
{
|
||||
Movement::MoveSplineInit init(creature);
|
||||
init.MoveTo(destX, destY, destZ, true);
|
||||
init.SetWalk(true);
|
||||
init.Launch();
|
||||
if (roll_chance_i(MOVEMENT_RANDOM_MMGEN_CHANCE_NO_BREAK))
|
||||
i_nextMoveTime.Reset(50);
|
||||
else
|
||||
i_nextMoveTime.Reset(urand(3000, 10000)); // Keep a short wait time
|
||||
}
|
||||
else
|
||||
i_nextMoveTime.Reset(50); // Retry later
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
|
||||
{
|
||||
const float angle = rand_norm_f() * (M_PI_F * 2.0f);
|
||||
const float range = rand_norm_f() * i_radius;
|
||||
|
||||
float destX = i_x + range * cos(angle);
|
||||
float destY = i_y + range * sin(angle);
|
||||
float destZ = i_z + frand(-1, 1) * i_verticalZ;
|
||||
float destX = i_x;
|
||||
float destY = i_y;
|
||||
float destZ = i_z;
|
||||
// float destX = i_x + range * cos(angle);
|
||||
// float destY = i_y + range * sin(angle);
|
||||
// float destZ = i_z + frand(-1, 1) * i_verticalZ;
|
||||
creature.UpdateAllowedPositionZ(destX, destY, destZ);
|
||||
|
||||
creature.addUnitState(UNIT_STAT_ROAMING_MOVE);
|
||||
|
|
@ -67,6 +96,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature& creature)
|
|||
else
|
||||
i_nextMoveTime.Reset(urand(500, 10000));
|
||||
}
|
||||
*/
|
||||
|
||||
template<>
|
||||
void RandomMovementGenerator<Creature>::Initialize(Creature& creature)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
#include "MovementGenerator.h"
|
||||
|
||||
// define chance for creature to not stop after reaching a waypoint
|
||||
#define MOVEMENT_RANDOM_MMGEN_CHANCE_NO_BREAK 30
|
||||
|
||||
template<class T>
|
||||
class RandomMovementGenerator
|
||||
: public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
|
|||
|
||||
if (behavior->textid[0])
|
||||
{
|
||||
int32 textId = behavior->textid[0];
|
||||
// Not only one text is set
|
||||
if (behavior->textid[1])
|
||||
{
|
||||
|
|
@ -153,10 +154,13 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature& creature)
|
|||
break;
|
||||
}
|
||||
|
||||
creature.MonsterSay(behavior->textid[rand() % i], LANG_UNIVERSAL);
|
||||
textId = behavior->textid[urand(0, i - 1)];
|
||||
}
|
||||
|
||||
if (MangosStringLocale const* textData = sObjectMgr.GetMangosStringLocale(textId))
|
||||
creature.MonsterText(textData, nullptr);
|
||||
else
|
||||
creature.MonsterSay(behavior->textid[0], LANG_UNIVERSAL);
|
||||
sLog.outErrorDb("%s reached waypoint %u, attempted to do text %i, but required text-data could not be found", creature.GetGuidStr().c_str(), i_currentNode, textId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -846,8 +846,24 @@ void WorldSession::BuildListAuctionItems(std::vector<AuctionEntry*> const& aucti
|
|||
if (levelmin != 0x00 && (proto->RequiredLevel < levelmin || (levelmax != 0x00 && proto->RequiredLevel > levelmax)))
|
||||
continue;
|
||||
|
||||
if (usable != 0x00 && _player->CanUseItem(item) != EQUIP_ERR_OK)
|
||||
continue;
|
||||
if (usable != 0x00)
|
||||
{
|
||||
if (_player->CanUseItem(item) != EQUIP_ERR_OK)
|
||||
continue;
|
||||
|
||||
if (proto->Class == ITEM_CLASS_RECIPE)
|
||||
{
|
||||
if (SpellEntry const* spell = sSpellStore.LookupEntry(proto->Spells[0].SpellId))
|
||||
{
|
||||
SpellEffectEntry const* spellEff = spell->GetSpellEffect(EFFECT_INDEX_0);
|
||||
if (!spellEff)
|
||||
continue;
|
||||
|
||||
if (_player->HasSpell(spellEff->EffectTriggerSpell))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name = proto->Name1;
|
||||
sObjectMgr.GetItemLocaleStrings(proto->ItemId, loc_idx, &name);
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ Creature::Creature(CreatureSubtype subtype) : Unit(),
|
|||
lootForPickPocketed(false), lootForBody(false), lootForSkin(false),
|
||||
m_groupLootTimer(0), m_groupLootId(0),
|
||||
m_lootMoney(0), m_lootGroupRecipientId(0),
|
||||
m_corpseDecayTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(5.0f),
|
||||
m_corpseDecayTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_aggroDelay(0), m_respawnradius(5.0f),
|
||||
m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
|
||||
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
|
||||
m_regenHealth(true), m_AI_locked(false), m_IsDeadByDefault(false),
|
||||
|
|
@ -310,7 +310,7 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
|
|||
SetByteValue(UNIT_FIELD_BYTES_0, 0, 0);
|
||||
|
||||
// known valid are: CLASS_WARRIOR,CLASS_PALADIN,CLASS_ROGUE,CLASS_MAGE
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class));
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->UnitClass));
|
||||
|
||||
uint32 display_id = ChooseDisplayId(GetCreatureInfo(), data, eventData);
|
||||
if (!display_id) // Cancel load if no display id
|
||||
|
|
@ -374,28 +374,26 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData* data /*=
|
|||
if (!InitEntry(Entry, data, eventData))
|
||||
return false;
|
||||
|
||||
m_regenHealth = GetCreatureInfo()->RegenHealth;
|
||||
|
||||
// creatures always have melee weapon ready if any
|
||||
SetSheath(SHEATH_STATE_MELEE);
|
||||
|
||||
SelectLevel(GetCreatureInfo(), preserveHPAndPower ? GetHealthPercent() : 100.0f, 100.0f);
|
||||
SelectLevel(GetCreatureInfo(), preserveHPAndPower ? GetHealthPercent() : 100.0f);
|
||||
|
||||
if (team == HORDE)
|
||||
setFaction(GetCreatureInfo()->FactionHorde);
|
||||
else
|
||||
setFaction(GetCreatureInfo()->FactionAlliance);
|
||||
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, GetCreatureInfo()->npcflag);
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, GetCreatureInfo()->NpcFlags);
|
||||
|
||||
uint32 attackTimer = GetCreatureInfo()->baseattacktime;
|
||||
uint32 attackTimer = GetCreatureInfo()->MeleeBaseAttackTime;
|
||||
|
||||
SetAttackTime(BASE_ATTACK, attackTimer);
|
||||
SetAttackTime(OFF_ATTACK, attackTimer - attackTimer / 4);
|
||||
SetAttackTime(RANGED_ATTACK, GetCreatureInfo()->rangeattacktime);
|
||||
SetAttackTime(RANGED_ATTACK, GetCreatureInfo()->RangedBaseAttackTime);
|
||||
|
||||
uint32 unitFlags = GetCreatureInfo()->unit_flags;
|
||||
uint32 unitFlags2 = GetCreatureInfo()->unit_flags2;
|
||||
uint32 unitFlags = GetCreatureInfo()->UnitFlags;
|
||||
uint32 unitFlags2 = GetCreatureInfo()->UnitFlags2;
|
||||
|
||||
// we may need to append or remove additional flags
|
||||
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT))
|
||||
|
|
@ -406,15 +404,15 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData* data /*=
|
|||
|
||||
// preserve all current dynamic flags if exist
|
||||
uint32 dynFlags = GetUInt32Value(UNIT_DYNAMIC_FLAGS);
|
||||
SetUInt32Value(UNIT_DYNAMIC_FLAGS, dynFlags ? dynFlags : GetCreatureInfo()->dynamicflags);
|
||||
SetUInt32Value(UNIT_DYNAMIC_FLAGS, dynFlags ? dynFlags : GetCreatureInfo()->DynamicFlags);
|
||||
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetCreatureInfo()->armor));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(GetCreatureInfo()->resistance1));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(GetCreatureInfo()->resistance2));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(GetCreatureInfo()->resistance3));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(GetCreatureInfo()->resistance4));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(GetCreatureInfo()->resistance5));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(GetCreatureInfo()->resistance6));
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetCreatureInfo()->Armor));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(GetCreatureInfo()->ResistanceHoly));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(GetCreatureInfo()->ResistanceFire));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(GetCreatureInfo()->ResistanceNature));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(GetCreatureInfo()->ResistanceFrost));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(GetCreatureInfo()->ResistanceShadow));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(GetCreatureInfo()->ResistanceArcane));
|
||||
|
||||
SetCanModifyStats(true);
|
||||
UpdateAllStats();
|
||||
|
|
@ -518,6 +516,7 @@ void Creature::Update(uint32 update_diff, uint32 diff)
|
|||
{
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Respawning...");
|
||||
m_respawnTime = 0;
|
||||
m_aggroDelay = sWorld.getConfig(CONFIG_UINT32_CREATURE_RESPAWN_AGGRO_DELAY);
|
||||
lootForPickPocketed = false;
|
||||
lootForBody = false;
|
||||
lootForSkin = false;
|
||||
|
|
@ -535,6 +534,7 @@ void Creature::Update(uint32 update_diff, uint32 diff)
|
|||
CreatureInfo const* cinfo = GetCreatureInfo();
|
||||
|
||||
SelectLevel(cinfo);
|
||||
UpdateAllStats(); // to be sure stats is correct regarding level of the creature
|
||||
SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
|
||||
if (m_IsDeadByDefault)
|
||||
{
|
||||
|
|
@ -584,6 +584,11 @@ void Creature::Update(uint32 update_diff, uint32 diff)
|
|||
}
|
||||
case ALIVE:
|
||||
{
|
||||
if (m_aggroDelay <= update_diff)
|
||||
m_aggroDelay = 0;
|
||||
else
|
||||
m_aggroDelay -= update_diff;
|
||||
|
||||
if (m_IsDeadByDefault)
|
||||
{
|
||||
if (m_corpseDecayTimer <= update_diff)
|
||||
|
|
@ -819,7 +824,7 @@ bool Creature::IsTrainerOf(Player* pPlayer, bool msg) const
|
|||
return false;
|
||||
|
||||
// pet trainers not have spells in fact now
|
||||
if (GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS)
|
||||
if (GetCreatureInfo()->TrainerType != TRAINER_TYPE_PETS)
|
||||
{
|
||||
TrainerSpellData const* cSpells = GetTrainerSpells();
|
||||
TrainerSpellData const* tSpells = GetTrainerTemplateSpells();
|
||||
|
|
@ -833,15 +838,15 @@ bool Creature::IsTrainerOf(Player* pPlayer, bool msg) const
|
|||
}
|
||||
}
|
||||
|
||||
switch (GetCreatureInfo()->trainer_type)
|
||||
switch (GetCreatureInfo()->TrainerType)
|
||||
{
|
||||
case TRAINER_TYPE_CLASS:
|
||||
if (pPlayer->getClass() != GetCreatureInfo()->trainer_class)
|
||||
if (pPlayer->getClass() != GetCreatureInfo()->TrainerClass)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
switch (GetCreatureInfo()->trainer_class)
|
||||
switch (GetCreatureInfo()->TrainerClass)
|
||||
{
|
||||
case CLASS_DRUID: pPlayer->PlayerTalkClass->SendGossipMenu(4913, GetObjectGuid()); break;
|
||||
case CLASS_HUNTER: pPlayer->PlayerTalkClass->SendGossipMenu(10090, GetObjectGuid()); break;
|
||||
|
|
@ -869,7 +874,7 @@ bool Creature::IsTrainerOf(Player* pPlayer, bool msg) const
|
|||
}
|
||||
break;
|
||||
case TRAINER_TYPE_MOUNTS:
|
||||
if (GetCreatureInfo()->trainer_race && pPlayer->getRace() != GetCreatureInfo()->trainer_race)
|
||||
if (GetCreatureInfo()->TrainerRace && pPlayer->getRace() != GetCreatureInfo()->TrainerRace)
|
||||
{
|
||||
// Allowed to train if exalted
|
||||
if (FactionTemplateEntry const* faction_template = getFactionTemplateEntry())
|
||||
|
|
@ -881,7 +886,7 @@ bool Creature::IsTrainerOf(Player* pPlayer, bool msg) const
|
|||
if (msg)
|
||||
{
|
||||
pPlayer->PlayerTalkClass->ClearMenus();
|
||||
switch (GetCreatureInfo()->trainer_class)
|
||||
switch (GetCreatureInfo()->TrainerClass)
|
||||
{
|
||||
case RACE_DWARF: pPlayer->PlayerTalkClass->SendGossipMenu(5865, GetObjectGuid()); break;
|
||||
case RACE_GNOME: pPlayer->PlayerTalkClass->SendGossipMenu(4881, GetObjectGuid()); break;
|
||||
|
|
@ -899,7 +904,7 @@ bool Creature::IsTrainerOf(Player* pPlayer, bool msg) const
|
|||
}
|
||||
break;
|
||||
case TRAINER_TYPE_TRADESKILLS:
|
||||
if (GetCreatureInfo()->trainer_spell && !pPlayer->HasSpell(GetCreatureInfo()->trainer_spell))
|
||||
if (GetCreatureInfo()->TrainerSpell && !pPlayer->HasSpell(GetCreatureInfo()->TrainerSpell))
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
|
|
@ -953,8 +958,8 @@ bool Creature::CanInteractWithBattleMaster(Player* pPlayer, bool msg) const
|
|||
bool Creature::CanTrainAndResetTalentsOf(Player* pPlayer) const
|
||||
{
|
||||
return pPlayer->getLevel() >= 10
|
||||
&& GetCreatureInfo()->trainer_type == TRAINER_TYPE_CLASS
|
||||
&& pPlayer->getClass() == GetCreatureInfo()->trainer_class;
|
||||
&& GetCreatureInfo()->TrainerType == TRAINER_TYPE_CLASS
|
||||
&& pPlayer->getClass() == GetCreatureInfo()->TrainerType;
|
||||
}
|
||||
|
||||
void Creature::PrepareBodyLootState()
|
||||
|
|
@ -965,9 +970,9 @@ void Creature::PrepareBodyLootState()
|
|||
if (!lootForBody)
|
||||
{
|
||||
// have normal loot
|
||||
if (GetCreatureInfo()->maxgold > 0 || GetCreatureInfo()->lootid ||
|
||||
if (GetCreatureInfo()->MaxLootGold > 0 || GetCreatureInfo()->LootId ||
|
||||
// ... or can have skinning after
|
||||
(GetCreatureInfo()->SkinLootId && sWorld.getConfig(CONFIG_BOOL_CORPSE_EMPTY_LOOT_SHOW)))
|
||||
(GetCreatureInfo()->SkinningLootId && sWorld.getConfig(CONFIG_BOOL_CORPSE_EMPTY_LOOT_SHOW)))
|
||||
{
|
||||
SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||
return;
|
||||
|
|
@ -977,7 +982,7 @@ void Creature::PrepareBodyLootState()
|
|||
lootForBody = true; // pass this loot mode
|
||||
|
||||
// if not have normal loot allow skinning if need
|
||||
if (!lootForSkin && GetCreatureInfo()->SkinLootId)
|
||||
if (!lootForSkin && GetCreatureInfo()->SkinningLootId)
|
||||
{
|
||||
RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
|
||||
|
|
@ -1162,25 +1167,59 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
|||
WorldDatabase.CommitTransaction();
|
||||
}
|
||||
|
||||
void Creature::SelectLevel(const CreatureInfo* cinfo, float percentHealth, float percentMana)
|
||||
|
||||
void Creature::SelectLevel(const CreatureInfo* cinfo, float percentHealth /*= 100.0f*/)
|
||||
{
|
||||
uint32 rank = IsPet() ? 0 : cinfo->Rank;
|
||||
uint32 rank = IsPet() ? 0 : cinfo->Rank; // TODO :: IsPet probably not needed here
|
||||
|
||||
// level
|
||||
uint32 minlevel = std::min(cinfo->maxlevel, cinfo->minlevel);
|
||||
uint32 maxlevel = std::max(cinfo->maxlevel, cinfo->minlevel);
|
||||
uint32 const minlevel = cinfo->MinLevel;
|
||||
uint32 const maxlevel = cinfo->MaxLevel;
|
||||
uint32 level = minlevel == maxlevel ? minlevel : urand(minlevel, maxlevel);
|
||||
SetLevel(level);
|
||||
|
||||
float rellevel = maxlevel == minlevel ? 0 : (float(level - minlevel)) / (maxlevel - minlevel);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Calculate level dependend stats
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint32 health;
|
||||
uint32 mana;
|
||||
|
||||
if (CreatureClassLvlStats const* cCLS = sObjectMgr.GetCreatureClassLvlStats(level, cinfo->UnitClass, cinfo->Expansion))
|
||||
{
|
||||
// Use Creature Stats to calculate stat values
|
||||
|
||||
// health
|
||||
health = cCLS->BaseHealth * cinfo->HealthMultiplier;
|
||||
|
||||
// mana
|
||||
mana = cCLS->BaseMana * cinfo->PowerMultiplier;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use old style to calculate stat values
|
||||
float rellevel = maxlevel == minlevel ? 0 : (float(level - minlevel)) / (maxlevel - minlevel);
|
||||
|
||||
// health
|
||||
uint32 minhealth = std::min(cinfo->MaxLevelHealth, cinfo->MinLevelHealth);
|
||||
uint32 maxhealth = std::max(cinfo->MaxLevelHealth, cinfo->MinLevelHealth);
|
||||
health = uint32(minhealth + uint32(rellevel * (maxhealth - minhealth)));
|
||||
|
||||
// mana
|
||||
uint32 minmana = std::min(cinfo->MaxLevelMana, cinfo->MinLevelMana);
|
||||
uint32 maxmana = std::max(cinfo->MaxLevelMana, cinfo->MinLevelMana);
|
||||
mana = minmana + uint32(rellevel * (maxmana - minmana));
|
||||
}
|
||||
|
||||
health *= _GetHealthMod(rank); // Apply custom config settting
|
||||
if (health < 1)
|
||||
health = 1;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Set values
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// health
|
||||
float healthmod = _GetHealthMod(rank);
|
||||
|
||||
uint32 minhealth = std::min(cinfo->maxhealth, cinfo->minhealth);
|
||||
uint32 maxhealth = std::max(cinfo->maxhealth, cinfo->minhealth);
|
||||
uint32 health = uint32(healthmod * (minhealth + uint32(rellevel * (maxhealth - minhealth))));
|
||||
|
||||
SetCreateHealth(health);
|
||||
SetMaxHealth(health);
|
||||
|
||||
|
|
@ -1189,33 +1228,51 @@ void Creature::SelectLevel(const CreatureInfo* cinfo, float percentHealth, float
|
|||
else
|
||||
SetHealthPercent(percentHealth);
|
||||
|
||||
// mana
|
||||
uint32 minmana = std::min(cinfo->maxmana, cinfo->minmana);
|
||||
uint32 maxmana = std::max(cinfo->maxmana, cinfo->minmana);
|
||||
uint32 mana = minmana + uint32(rellevel * (maxmana - minmana));
|
||||
|
||||
SetCreateMana(mana);
|
||||
SetMaxPower(POWER_MANA, mana); // MAX Mana
|
||||
SetPower(POWER_MANA, mana);
|
||||
|
||||
// TODO: set UNIT_FIELD_POWER*, for some creature class case (energy, etc)
|
||||
|
||||
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, float(health));
|
||||
SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, float(mana));
|
||||
|
||||
// all power types
|
||||
for (int i = POWER_MANA; i <= POWER_RUNIC_POWER; ++i)
|
||||
{
|
||||
uint32 maxValue = 0;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case POWER_MANA: maxValue = mana; break;
|
||||
case POWER_RAGE: maxValue = 0; break;
|
||||
case POWER_FOCUS: maxValue = POWER_FOCUS_DEFAULT; break;
|
||||
case POWER_ENERGY: maxValue = POWER_ENERGY_DEFAULT * cinfo->PowerMultiplier; break;
|
||||
case POWER_RUNE: maxValue = 0; break;
|
||||
case POWER_RUNIC_POWER: maxValue = 0; break;
|
||||
}
|
||||
|
||||
uint32 value = maxValue;
|
||||
|
||||
// For non regenerating powers set 0
|
||||
if ((i == POWER_ENERGY || i == POWER_MANA) && !IsRegeneratingPower())
|
||||
value = 0;
|
||||
|
||||
// Mana requires an extra field to be set
|
||||
if (i == POWER_MANA)
|
||||
SetCreateMana(value);
|
||||
|
||||
SetMaxPower(Powers(i), maxValue);
|
||||
SetPower(Powers(i), value);
|
||||
SetModifierValue(UnitMods(UNIT_MOD_POWER_START + i), BASE_VALUE, float(value));
|
||||
}
|
||||
|
||||
// damage
|
||||
float damagemod = _GetDamageMod(rank);
|
||||
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg * damagemod);
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg * damagemod);
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->MinMeleeDmg * damagemod);
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->MaxMeleeDmg * damagemod);
|
||||
|
||||
SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg * damagemod);
|
||||
SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg * damagemod);
|
||||
SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->MinMeleeDmg * damagemod);
|
||||
SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->MaxMeleeDmg * damagemod);
|
||||
|
||||
SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, cinfo->minrangedmg * damagemod);
|
||||
SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, cinfo->maxrangedmg * damagemod);
|
||||
SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, cinfo->MinRangedDmg * damagemod);
|
||||
SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, cinfo->MaxRangedDmg * damagemod);
|
||||
|
||||
SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod);
|
||||
SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->MeleeAttackPower * damagemod);
|
||||
}
|
||||
|
||||
float Creature::_GetHealthMod(int32 Rank)
|
||||
|
|
@ -1370,7 +1427,7 @@ bool Creature::LoadFromDB(uint32 guidlow, Map* map)
|
|||
SetHealth(m_deathState == ALIVE ? curhealth : 0);
|
||||
SetPower(POWER_MANA, data->curmana);
|
||||
|
||||
SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->dmgschool));
|
||||
SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->DamageSchool));
|
||||
|
||||
// checked at creature_template loading
|
||||
m_defaultMovementType = MovementGeneratorType(data->movementType);
|
||||
|
|
@ -1561,7 +1618,7 @@ void Creature::SetDeathState(DeathState s)
|
|||
if (GetTemporaryFactionFlags() & TEMPFACTION_RESTORE_RESPAWN)
|
||||
ClearTemporaryFaction();
|
||||
|
||||
SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->dmgschool));
|
||||
SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->DamageSchool));
|
||||
|
||||
// Dynamic flags may be adjusted by spells. Clear them
|
||||
// first and let spell from *addon apply where needed.
|
||||
|
|
@ -1570,7 +1627,7 @@ void Creature::SetDeathState(DeathState s)
|
|||
|
||||
// Flags after LoadCreatureAddon. Any spell in *addon
|
||||
// will not be able to adjust these.
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, GetCreatureInfo()->npcflag);
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, GetCreatureInfo()->NpcFlags);
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
|
||||
|
||||
SetWalk(true, true);
|
||||
|
|
@ -1634,7 +1691,7 @@ bool Creature::IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectInd
|
|||
return true;
|
||||
|
||||
// Taunt immunity special flag check
|
||||
if (GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NOT_TAUNTABLE)
|
||||
if (GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NOT_TAUNTABLE)
|
||||
{
|
||||
// Taunt aura apply check
|
||||
if (spellEffect->Effect == SPELL_EFFECT_APPLY_AURA)
|
||||
|
|
@ -1775,7 +1832,7 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const
|
|||
if (pl->isGameMaster())
|
||||
return true;
|
||||
|
||||
if (GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_INVISIBLE)
|
||||
if (GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_INVISIBLE)
|
||||
return false;
|
||||
|
||||
// Live player (or with not release body see live creatures or death creatures with corpse disappearing time > 0
|
||||
|
|
@ -1822,6 +1879,10 @@ void Creature::CallAssistance()
|
|||
if (!m_AlreadyCallAssistance && getVictim() && !IsCharmed())
|
||||
{
|
||||
SetNoCallAssistance(true);
|
||||
|
||||
if (GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_CALL_ASSIST)
|
||||
return;
|
||||
|
||||
AI()->SendAIEventAround(AI_EVENT_CALL_ASSISTANCE, getVictim(), sWorld.getConfig(CONFIG_UINT32_CREATURE_FAMILY_ASSISTANCE_DELAY), sWorld.getConfig(CONFIG_FLOAT_CREATURE_FAMILY_ASSISTANCE_RADIUS));
|
||||
}
|
||||
}
|
||||
|
|
@ -1888,6 +1949,12 @@ bool Creature::CanInitiateAttack()
|
|||
if (isPassiveToHostile())
|
||||
return false;
|
||||
|
||||
if (m_aggroDelay != 0)
|
||||
return false;
|
||||
|
||||
if (!CanAttackByItself())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2350,8 +2417,8 @@ VendorItemData const* Creature::GetVendorItems() const
|
|||
|
||||
VendorItemData const* Creature::GetVendorTemplateItems() const
|
||||
{
|
||||
uint32 vendorId = GetCreatureInfo()->vendorId;
|
||||
return vendorId ? sObjectMgr.GetNpcVendorTemplateItemList(vendorId) : NULL;
|
||||
uint32 VendorTemplateId = GetCreatureInfo()->VendorTemplateId;
|
||||
return VendorTemplateId ? sObjectMgr.GetNpcVendorTemplateItemList(VendorTemplateId) : NULL;
|
||||
}
|
||||
|
||||
uint32 Creature::GetVendorItemCurrentCount(VendorItem const* vItem)
|
||||
|
|
@ -2428,8 +2495,8 @@ uint32 Creature::UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 us
|
|||
|
||||
TrainerSpellData const* Creature::GetTrainerTemplateSpells() const
|
||||
{
|
||||
uint32 trainerId = GetCreatureInfo()->trainerId;
|
||||
return trainerId ? sObjectMgr.GetNpcTrainerTemplateSpells(trainerId) : NULL;
|
||||
uint32 TrainerTemplateId = GetCreatureInfo()->TrainerTemplateId;
|
||||
return TrainerTemplateId ? sObjectMgr.GetNpcTrainerTemplateSpells(TrainerTemplateId) : NULL;
|
||||
}
|
||||
|
||||
TrainerSpellData const* Creature::GetTrainerSpells() const
|
||||
|
|
@ -2469,11 +2536,11 @@ void Creature::ClearTemporaryFaction()
|
|||
// Reset to original faction
|
||||
setFaction(GetCreatureInfo()->FactionAlliance);
|
||||
// Reset UNIT_FLAG_NON_ATTACKABLE, UNIT_FLAG_OOC_NOT_ATTACKABLE or UNIT_FLAG_PASSIVE flags
|
||||
if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_NON_ATTACKABLE && GetCreatureInfo()->unit_flags & UNIT_FLAG_NON_ATTACKABLE)
|
||||
if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_NON_ATTACKABLE && GetCreatureInfo()->UnitFlags & UNIT_FLAG_NON_ATTACKABLE)
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_OOC_NOT_ATTACK && GetCreatureInfo()->unit_flags & UNIT_FLAG_OOC_NOT_ATTACKABLE && !IsInCombat())
|
||||
if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_OOC_NOT_ATTACK && GetCreatureInfo()->UnitFlags & UNIT_FLAG_OOC_NOT_ATTACKABLE && !IsInCombat())
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
|
||||
if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_PASSIVE && GetCreatureInfo()->unit_flags & UNIT_FLAG_PASSIVE)
|
||||
if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_PASSIVE && GetCreatureInfo()->UnitFlags & UNIT_FLAG_PASSIVE)
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
|
||||
|
||||
m_temporaryFactionFlags = TEMPFACTION_NONE;
|
||||
|
|
|
|||
|
|
@ -49,17 +49,23 @@ struct GameEventCreatureData;
|
|||
|
||||
enum CreatureFlagsExtra
|
||||
{
|
||||
CREATURE_FLAG_EXTRA_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
|
||||
CREATURE_FLAG_EXTRA_CIVILIAN = 0x00000002, // not aggro (ignore faction/reputation hostility)
|
||||
CREATURE_FLAG_EXTRA_NO_PARRY = 0x00000004, // creature can't parry
|
||||
CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN = 0x00000008, // creature can't counter-attack at parry
|
||||
CREATURE_FLAG_EXTRA_NO_BLOCK = 0x00000010, // creature can't block
|
||||
CREATURE_FLAG_EXTRA_NO_CRUSH = 0x00000020, // creature can't do crush attacks
|
||||
CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP
|
||||
CREATURE_FLAG_EXTRA_INVISIBLE = 0x00000080, // creature is always invisible for player (mostly trigger creatures)
|
||||
CREATURE_FLAG_EXTRA_NOT_TAUNTABLE = 0x00000100, // creature is immune to taunt auras and effect attack me
|
||||
CREATURE_FLAG_EXTRA_AGGRO_ZONE = 0x00000200, // creature sets itself in combat with zone on aggro
|
||||
CREATURE_FLAG_EXTRA_GUARD = 0x00000400, // creature is a guard
|
||||
CREATURE_EXTRA_FLAG_INSTANCE_BIND = 0x00000001, // creature kill bind instance with killer and killer's group
|
||||
CREATURE_EXTRA_FLAG_CIVILIAN = 0x00000002, // not aggro (ignore faction/reputation hostility)
|
||||
CREATURE_EXTRA_FLAG_NO_PARRY = 0x00000004, // creature can't parry
|
||||
CREATURE_EXTRA_FLAG_NO_PARRY_HASTEN = 0x00000008, // creature can't counter-attack at parry
|
||||
CREATURE_EXTRA_FLAG_NO_BLOCK = 0x00000010, // creature can't block
|
||||
CREATURE_EXTRA_FLAG_NO_CRUSH = 0x00000020, // creature can't do crush attacks
|
||||
CREATURE_EXTRA_FLAG_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP
|
||||
CREATURE_EXTRA_FLAG_INVISIBLE = 0x00000080, // creature is always invisible for player (mostly trigger creatures)
|
||||
CREATURE_EXTRA_FLAG_NOT_TAUNTABLE = 0x00000100, // creature is immune to taunt auras and effect attack me
|
||||
CREATURE_EXTRA_FLAG_AGGRO_ZONE = 0x00000200, // creature sets itself in combat with zone on aggro
|
||||
CREATURE_EXTRA_FLAG_GUARD = 0x00000400, // creature is a guard
|
||||
CREATURE_EXTRA_FLAG_NO_CALL_ASSIST = 0x00000800, // creature shouldn't call for assistance on aggro
|
||||
CREATURE_EXTRA_FLAG_ACTIVE = 0x00001000, // creature is active object. Grid of this creature will be loaded and creature set as active
|
||||
CREATURE_EXTRA_FLAG_MMAP_FORCE_ENABLE = 0x00002000, // creature is forced to use MMaps
|
||||
CREATURE_EXTRA_FLAG_MMAP_FORCE_DISABLE = 0x00004000, // creature is forced to NOT use MMaps
|
||||
CREATURE_EXTRA_FLAG_WALK_IN_WATER = 0x00008000, // creature is forced to walk in water even it can swim
|
||||
CREATURE_EXTRA_FLAG_HAVE_NO_SWIM_ANIMATION = 0x00010000, // we have to not set "swim" animation or creature will have "no animation"
|
||||
};
|
||||
|
||||
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
|
||||
|
|
@ -72,8 +78,124 @@ enum CreatureFlagsExtra
|
|||
#define MAX_KILL_CREDIT 2
|
||||
#define MAX_CREATURE_MODEL 4
|
||||
|
||||
|
||||
// from `creature_template` table
|
||||
struct CreatureInfo
|
||||
{
|
||||
uint32 Entry;
|
||||
char* Name;
|
||||
char* SubName;
|
||||
char* IconName;
|
||||
uint32 MinLevel;
|
||||
uint32 MaxLevel;
|
||||
uint32 DifficultyEntry[MAX_DIFFICULTY - 1];
|
||||
uint32 ModelId[MAX_CREATURE_MODEL];
|
||||
uint32 FactionAlliance;
|
||||
uint32 FactionHorde;
|
||||
float Scale;
|
||||
uint32 Family; // enum CreatureFamily values (optional)
|
||||
uint32 CreatureType; // enum CreatureType values
|
||||
uint32 InhabitType;
|
||||
uint32 RegenerateStats;
|
||||
bool RacialLeader;
|
||||
uint32 NpcFlags;
|
||||
uint32 UnitFlags; // enum UnitFlags mask values
|
||||
uint32 UnitFlags2; // enum UnitFlags2 mask values
|
||||
uint32 DynamicFlags;
|
||||
uint32 ExtraFlags;
|
||||
uint32 CreatureTypeFlags; // enum CreatureTypeFlags mask values
|
||||
float SpeedWalk;
|
||||
float SpeedRun;
|
||||
uint32 UnitClass; // enum Classes. Note only 4 classes are known for creatures.
|
||||
uint32 Rank;
|
||||
int32 Expansion; // creature expansion, important for stats, CAN BE -1 as marker for some invalid cases.
|
||||
float HealthMultiplier;
|
||||
float PowerMultiplier;
|
||||
float DamageMultiplier;
|
||||
float DamageVariance;
|
||||
float ArmorMultiplier;
|
||||
float ExperienceMultiplier;
|
||||
uint32 MinLevelHealth;
|
||||
uint32 MaxLevelHealth;
|
||||
uint32 MinLevelMana;
|
||||
uint32 MaxLevelMana;
|
||||
float MinMeleeDmg;
|
||||
float MaxMeleeDmg;
|
||||
float MinRangedDmg;
|
||||
float MaxRangedDmg;
|
||||
uint32 Armor;
|
||||
uint32 MeleeAttackPower;
|
||||
uint32 RangedAttackPower;
|
||||
uint32 MeleeBaseAttackTime;
|
||||
uint32 RangedBaseAttackTime;
|
||||
uint32 DamageSchool;
|
||||
uint32 MinLootGold;
|
||||
uint32 MaxLootGold;
|
||||
uint32 LootId;
|
||||
uint32 PickpocketLootId;
|
||||
uint32 SkinningLootId;
|
||||
uint32 KillCredit[MAX_KILL_CREDIT];
|
||||
uint32 QuestItems[6];
|
||||
uint32 MechanicImmuneMask;
|
||||
int32 ResistanceHoly;
|
||||
int32 ResistanceFire;
|
||||
int32 ResistanceNature;
|
||||
int32 ResistanceFrost;
|
||||
int32 ResistanceShadow;
|
||||
int32 ResistanceArcane;
|
||||
uint32 PetSpellDataId;
|
||||
uint32 MovementType;
|
||||
uint32 MovementTemplateId;
|
||||
uint32 TrainerType;
|
||||
uint32 TrainerSpell;
|
||||
uint32 TrainerClass;
|
||||
uint32 TrainerRace;
|
||||
uint32 TrainerTemplateId;
|
||||
uint32 VendorTemplateId;
|
||||
uint32 EquipmentTemplateId;
|
||||
uint32 VehicleTemplateId;
|
||||
uint32 GossipMenuId;
|
||||
char const* AIName;
|
||||
|
||||
// helpers
|
||||
HighGuid GetHighGuid() const
|
||||
{
|
||||
return VehicleTemplateId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT;
|
||||
}
|
||||
|
||||
ObjectGuid GetObjectGuid(uint32 lowguid) const { return ObjectGuid(GetHighGuid(), Entry, lowguid); }
|
||||
|
||||
SkillType GetRequiredLootSkill() const
|
||||
{
|
||||
if (CreatureTypeFlags & CREATURE_TYPEFLAGS_HERBLOOT)
|
||||
return SKILL_HERBALISM;
|
||||
else if (CreatureTypeFlags & CREATURE_TYPEFLAGS_MININGLOOT)
|
||||
return SKILL_MINING;
|
||||
else if (CreatureTypeFlags & CREATURE_TYPEFLAGS_ENGINEERLOOT)
|
||||
return SKILL_ENGINEERING;
|
||||
else
|
||||
return SKILL_SKINNING; // normal case
|
||||
}
|
||||
|
||||
bool IsExotic() const
|
||||
{
|
||||
return (CreatureTypeFlags & CREATURE_TYPEFLAGS_EXOTIC);
|
||||
}
|
||||
|
||||
bool isTameable(bool exotic) const
|
||||
{
|
||||
if (CreatureType != CREATURE_TYPE_BEAST || Family == 0 || (CreatureTypeFlags & CREATURE_TYPEFLAGS_TAMEABLE) == 0)
|
||||
return false;
|
||||
|
||||
// if can tame exotic then can tame any temable
|
||||
return exotic || !IsExotic();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// from `creature_template` table
|
||||
/*
|
||||
struct CreatureInfo
|
||||
{
|
||||
uint32 Entry;
|
||||
uint32 DifficultyEntry[MAX_DIFFICULTY - 1];
|
||||
|
|
@ -83,16 +205,16 @@ struct CreatureInfo
|
|||
char* SubName;
|
||||
char* IconName;
|
||||
uint32 GossipMenuId;
|
||||
uint32 minlevel;
|
||||
uint32 maxlevel;
|
||||
uint32 minhealth;
|
||||
uint32 MinLevel;
|
||||
uint32 MaxLevel;
|
||||
uint32 MinLevelHealth;
|
||||
uint32 maxhealth;
|
||||
uint32 minmana;
|
||||
uint32 MinLevelMana;
|
||||
uint32 maxmana;
|
||||
uint32 armor;
|
||||
uint32 FactionAlliance;
|
||||
uint32 FactionHorde;
|
||||
uint32 npcflag;
|
||||
uint32 NpcFlags;
|
||||
float speed_walk;
|
||||
float speed_run;
|
||||
float Scale;
|
||||
|
|
@ -102,25 +224,25 @@ struct CreatureInfo
|
|||
uint32 dmgschool;
|
||||
uint32 attackpower;
|
||||
float dmg_multiplier;
|
||||
uint32 baseattacktime;
|
||||
uint32 rangeattacktime;
|
||||
uint32 unit_class; // enum Classes. Note only 4 classes are known for creatures.
|
||||
uint32 unit_flags; // enum UnitFlags mask values
|
||||
uint32 unit_flags2; // enum UnitFlags2 mask values
|
||||
uint32 MeleeAttackPower;
|
||||
uint32 RangedAttackPower;
|
||||
uint32 UnitClass; // enum Classes. Note only 4 classes are known for creatures.
|
||||
uint32 UnitFlags; // enum UnitFlags mask values
|
||||
uint32 UnitFlags2; // enum UnitFlags2 mask values
|
||||
uint32 dynamicflags;
|
||||
uint32 family; // enum CreatureFamily values (optional)
|
||||
uint32 trainer_type;
|
||||
uint32 TrainerType;
|
||||
uint32 trainer_spell;
|
||||
uint32 trainer_class;
|
||||
uint32 TrainerClass;
|
||||
uint32 trainer_race;
|
||||
float minrangedmg;
|
||||
float maxrangedmg;
|
||||
uint32 rangedattackpower;
|
||||
uint32 type; // enum CreatureType values
|
||||
uint32 CreatureTypeFlags; // enum CreatureTypeFlags mask values
|
||||
uint32 lootid;
|
||||
uint32 Lootid;
|
||||
uint32 pickpocketLootId;
|
||||
uint32 SkinLootId;
|
||||
uint32 SkinningLootId;
|
||||
int32 resistance1;
|
||||
int32 resistance2;
|
||||
int32 resistance3;
|
||||
|
|
@ -128,7 +250,7 @@ struct CreatureInfo
|
|||
int32 resistance5;
|
||||
int32 resistance6;
|
||||
uint32 PetSpellDataId;
|
||||
uint32 mingold;
|
||||
uint32 MinLootGold;
|
||||
uint32 maxgold;
|
||||
char const* AIName;
|
||||
uint32 MovementType;
|
||||
|
|
@ -141,8 +263,8 @@ struct CreatureInfo
|
|||
bool RegenHealth;
|
||||
uint32 VehicleTemplateId;
|
||||
uint32 EquipmentTemplateId;
|
||||
uint32 trainerId;
|
||||
uint32 vendorId;
|
||||
uint32 TrainerTemplateId;
|
||||
uint32 VendorTemplateId;
|
||||
uint32 MechanicImmuneMask;
|
||||
uint32 ExtraFlags;
|
||||
|
||||
|
|
@ -179,7 +301,7 @@ struct CreatureInfo
|
|||
// if can tame exotic then can tame any temable
|
||||
return exotic || !IsExotic();
|
||||
}
|
||||
};
|
||||
}; */
|
||||
|
||||
struct CreatureTemplateSpells
|
||||
{
|
||||
|
|
@ -330,6 +452,12 @@ enum SelectFlags
|
|||
SELECT_FLAG_NOT_IN_MELEE_RANGE = 0x080,
|
||||
};
|
||||
|
||||
enum RegenStatsFlags
|
||||
{
|
||||
REGEN_FLAG_HEALTH = 0x001,
|
||||
REGEN_FLAG_POWER = 0x002,
|
||||
};
|
||||
|
||||
// Vendors
|
||||
|
||||
enum
|
||||
|
|
@ -501,7 +629,7 @@ class Creature : public Unit
|
|||
|
||||
bool Create(uint32 guidlow, CreatureCreatePos& cPos, CreatureInfo const* cinfo, Team team = TEAM_NONE, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL);
|
||||
bool LoadCreatureAddon(bool reload);
|
||||
void SelectLevel(const CreatureInfo* cinfo, float percentHealth = 100.0f, float percentMana = 100.0f);
|
||||
void SelectLevel(const CreatureInfo* cinfo, float percentHealth = 100.0f);
|
||||
void LoadEquipment(uint32 equip_entry, bool force = false);
|
||||
|
||||
bool HasStaticDBSpawnData() const; // listed in `creature` table and have fixed in DB guid
|
||||
|
|
@ -523,12 +651,14 @@ class Creature : public Unit
|
|||
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
|
||||
uint32 GetCorpseDelay() const { return m_corpseDelay; }
|
||||
bool IsRacialLeader() const { return GetCreatureInfo()->RacialLeader; }
|
||||
bool IsCivilian() const { return GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_CIVILIAN; }
|
||||
bool IsGuard() const { return GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_GUARD; }
|
||||
bool IsCivilian() const { return GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_CIVILIAN; }
|
||||
bool IsGuard() const { return GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_GUARD; }
|
||||
|
||||
bool CanWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; }
|
||||
virtual bool CanSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; }
|
||||
bool CanFly() const { return (GetCreatureInfo()->InhabitType & INHABIT_AIR) || (GetByteValue(UNIT_FIELD_BYTES_1, 3) & UNIT_BYTE1_FLAG_FLY_ANIM) || HasAuraType(SPELL_AURA_FLY); }
|
||||
bool CanSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; }
|
||||
bool IsSwimming() const { return (m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_SWIMMING))); }
|
||||
bool CanFly() const { return (GetCreatureInfo()->InhabitType & INHABIT_AIR) || (GetByteValue(UNIT_FIELD_BYTES_1, 3) & UNIT_BYTE1_FLAG_FLY_ANIM) || m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_LEVITATING | MOVEFLAG_CAN_FLY)); }
|
||||
bool IsFlying() const { return (m_movementInfo.HasMovementFlag((MovementFlags)(MOVEFLAG_FLYING | MOVEFLAG_LEVITATING))); }
|
||||
|
||||
bool IsTrainerOf(Player* player, bool msg) const;
|
||||
bool CanInteractWithBattleMaster(Player* player, bool msg) const;
|
||||
|
|
@ -745,7 +875,8 @@ class Creature : public Unit
|
|||
bool HasInvolvedQuest(uint32 quest_id) const override;
|
||||
|
||||
GridReference<Creature>& GetGridRef() { return m_gridRef; }
|
||||
bool IsRegeneratingHealth() { return m_regenHealth; }
|
||||
bool IsRegeneratingHealth() { return GetCreatureInfo()->RegenerateStats & REGEN_FLAG_HEALTH; }
|
||||
bool IsRegeneratingPower() { return GetCreatureInfo()->RegenerateStats & REGEN_FLAG_POWER; }
|
||||
virtual uint8 GetPetAutoSpellSize() const { return CREATURE_MAX_SPELLS; }
|
||||
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
|
||||
{
|
||||
|
|
@ -802,6 +933,7 @@ class Creature : public Unit
|
|||
time_t m_respawnTime; // (secs) time of next respawn
|
||||
uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning
|
||||
uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance
|
||||
uint32 m_aggroDelay; // (msecs)delay between respawn and aggro due to movement
|
||||
float m_respawnradius;
|
||||
|
||||
CreatureSubtype m_subtype; // set in Creatures subclasses for fast it detect without dynamic_cast use
|
||||
|
|
|
|||
|
|
@ -732,7 +732,7 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
|
|||
break;
|
||||
case ACTION_T_COMBAT_MOVEMENT:
|
||||
// ignore no affect case
|
||||
if (m_isCombatMovement == (action.combat_movement.state != 0))
|
||||
if (m_isCombatMovement == (action.combat_movement.state != 0) || m_creature->IsNonMeleeSpellCasted(false))
|
||||
return;
|
||||
|
||||
SetCombatMovement(action.combat_movement.state != 0, true);
|
||||
|
|
@ -966,63 +966,38 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
|
|||
m_throwAIEventMask = action.setThrowMask.eventTypeMask;
|
||||
break;
|
||||
}
|
||||
case ACTION_T_SUMMON_UNIQUE:
|
||||
case ACTION_T_SET_STAND_STATE:
|
||||
{
|
||||
Creature* pCreature = NULL;
|
||||
MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_creature, action.summon_unique.creatureId, true, false, 100, true);
|
||||
MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(pCreature, u_check);
|
||||
Cell::VisitGridObjects(m_creature, searcher, 100);
|
||||
WorldObject* pSpawn = NULL;
|
||||
pSpawn = pCreature;
|
||||
|
||||
if (!pSpawn)
|
||||
{
|
||||
Unit* target = GetTargetByType(action.summon_unique.target, pActionInvoker, pAIEventSender, reportTargetError);
|
||||
|
||||
if (!target && reportTargetError)
|
||||
sLog.outErrorEventAI("Event %u - NULL target for ACTION_T_SUMMON_UNIQUE(%u), target-type %u", EventId, action.type, action.summon_unique.target);
|
||||
|
||||
CreatureEventAI_Summon_Map::const_iterator i = sEventAIMgr.GetCreatureEventAISummonMap().find(action.summon_unique.spawnId);
|
||||
if (i == sEventAIMgr.GetCreatureEventAISummonMap().end())
|
||||
{
|
||||
sLog.outErrorEventAI("Failed to spawn creature %u. Summon map index %u does not exist. EventID %d. CreatureID %d", action.summon_unique.creatureId, action.summon_unique.spawnId, EventId, m_creature->GetEntry());
|
||||
return;
|
||||
}
|
||||
|
||||
Creature* pCreature = NULL;
|
||||
if ((*i).second.SpawnTimeSecs)
|
||||
pCreature = m_creature->SummonCreature(action.summon_unique.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN, (*i).second.SpawnTimeSecs);
|
||||
else
|
||||
pCreature = m_creature->SummonCreature(action.summon_unique.creatureId, (*i).second.position_x, (*i).second.position_y, (*i).second.position_z, (*i).second.orientation, TEMPSUMMON_TIMED_OOC_DESPAWN, 0);
|
||||
|
||||
if (!pCreature)
|
||||
sLog.outErrorEventAI("Failed to spawn creature %u. EventId %d.Creature %d", action.summon_unique.creatureId, EventId, m_creature->GetEntry());
|
||||
else if (action.summon_unique.target != TARGET_T_SELF && target)
|
||||
pCreature->AI()->AttackStart(target);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (pSpawn)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_creature->SetStandState(action.setStandState.standState);
|
||||
break;
|
||||
}
|
||||
case ACTION_T_EMOTE_TARGET:
|
||||
case ACTION_T_CHANGE_MOVEMENT:
|
||||
{
|
||||
Unit* pCreature = m_creature->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, action.emoteTarget.targetGuid));
|
||||
if (!pCreature)
|
||||
switch (action.changeMovement.movementType)
|
||||
{
|
||||
sLog.outErrorEventAI("Event %d. Cannot find creature by guid %d", EventId, action.emoteTarget.targetGuid);
|
||||
return;
|
||||
case IDLE_MOTION_TYPE:
|
||||
m_creature->GetMotionMaster()->MoveIdle();
|
||||
break;
|
||||
case RANDOM_MOTION_TYPE:
|
||||
m_creature->GetMotionMaster()->MoveRandomAroundPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), float(action.changeMovement.wanderDistance));
|
||||
break;
|
||||
case WAYPOINT_MOTION_TYPE:
|
||||
m_creature->GetMotionMaster()->MoveWaypoint();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_T_DYNAMIC_MOVEMENT:
|
||||
{
|
||||
if (action.dynamicMovement.state && m_DynamicMovement || !action.dynamicMovement.state && !m_DynamicMovement)
|
||||
break;
|
||||
|
||||
|
||||
m_creature->SetFacingToObject(pCreature);
|
||||
m_creature->HandleEmote(action.emoteTarget.emoteId);
|
||||
m_DynamicMovement = action.dynamicMovement.state;
|
||||
SetCombatMovement(!m_DynamicMovement, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sLog.outError("CreatureEventAi::ProcessAction(): action(%u) not implemented", static_cast<uint32>(action.type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,10 +121,12 @@ enum EventAI_ActionType
|
|||
ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue, format(0-flat,1-percent from max health)
|
||||
ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to unmount)
|
||||
ACTION_T_CHANCED_TEXT = 44, // Chance to display the text, TextId1, optionally TextId2. If more than just -TextId1 is defined, randomize. Negative values.
|
||||
ACTION_T_THROW_AI_EVENT = 45, // EventType, Radius, unused
|
||||
ACTION_T_THROW_AI_EVENT = 45, // EventType, Radius, unused
|
||||
ACTION_T_SET_THROW_MASK = 46, // EventTypeMask, unused, unused
|
||||
ACTION_T_SUMMON_UNIQUE = 47, // CreatureId, Target, SpawnId
|
||||
ACTION_T_EMOTE_TARGET = 48, // EmoteId, TargetGuid
|
||||
ACTION_T_SET_STAND_STATE = 47, // StandState, unused, unused
|
||||
ACTION_T_CHANGE_MOVEMENT = 48, // MovementType, WanderDistance, unused
|
||||
ACTION_T_DYNAMIC_MOVEMENT = 49, // EnableDynamicMovement (1 = on; 0 = off)
|
||||
|
||||
ACTION_T_END,
|
||||
};
|
||||
|
||||
|
|
@ -173,7 +175,7 @@ enum SpawnedEventMode
|
|||
|
||||
struct CreatureEventAI_Action
|
||||
{
|
||||
EventAI_ActionType type: 16;
|
||||
EventAI_ActionType type : 16;
|
||||
union
|
||||
{
|
||||
// ACTION_T_TEXT = 1
|
||||
|
|
@ -384,7 +386,6 @@ struct CreatureEventAI_Action
|
|||
uint32 creatureId; // set one from fields (or 0 for both to dismount)
|
||||
uint32 modelId;
|
||||
} mount;
|
||||
|
||||
// ACTION_T_CHANCED_TEXT = 44
|
||||
struct
|
||||
{
|
||||
|
|
@ -405,19 +406,27 @@ struct CreatureEventAI_Action
|
|||
uint32 unused1;
|
||||
uint32 unused2;
|
||||
} setThrowMask;
|
||||
// ACTION_T_SUMMON_UNIQUE = 47
|
||||
// ACTION_T_SET_STAND_STATE = 47
|
||||
struct
|
||||
{
|
||||
uint32 creatureId;
|
||||
uint32 target;
|
||||
uint32 spawnId;
|
||||
} summon_unique;
|
||||
// ACTION_T_EMOTE_TARGET = 48
|
||||
uint32 standState;
|
||||
uint32 unused1;
|
||||
uint32 unused2;
|
||||
} setStandState;
|
||||
// ACTION_T_CHANGE_MOVEMENT = 48
|
||||
struct
|
||||
{
|
||||
uint32 emoteId;
|
||||
uint32 targetGuid;
|
||||
} emoteTarget;
|
||||
uint32 movementType;
|
||||
uint32 wanderDistance;
|
||||
uint32 unused1;
|
||||
} changeMovement;
|
||||
// ACTION_T_DYNAMIC_MOVEMENT = 49
|
||||
struct
|
||||
{
|
||||
uint32 state; // bool: 1 = on; 0 = off
|
||||
uint32 unused1;
|
||||
uint32 unused2;
|
||||
} dynamicMovement;
|
||||
// RAW
|
||||
struct
|
||||
{
|
||||
|
|
@ -672,6 +681,8 @@ class CreatureEventAI : public CreatureAI
|
|||
|
||||
uint8 m_Phase; // Current phase, max 32 phases
|
||||
bool m_MeleeEnabled; // If we allow melee auto attack
|
||||
bool m_DynamicMovement; // Core will control creatures movement if this is enabled
|
||||
bool m_HasOOCLoSEvent; // Cache if a OOC-LoS Event exists
|
||||
uint32 m_InvinceabilityHpLevel; // Minimal health level allowed at damage apply
|
||||
|
||||
uint32 m_throwAIEventMask; // Automatically throw AIEvents that are encoded into this mask
|
||||
|
|
|
|||
|
|
@ -873,6 +873,21 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
|
|||
continue;
|
||||
}
|
||||
break;
|
||||
case ACTION_T_SET_STAND_STATE:
|
||||
if (action.setStandState.standState >= MAX_UNIT_STAND_STATE)
|
||||
{
|
||||
sLog.outErrorEventAI("Event %u Action %u uses invalid unit stand state %u (must be smaller than %u)", i, j + 1, action.setStandState.standState, MAX_UNIT_STAND_STATE);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case ACTION_T_CHANGE_MOVEMENT:
|
||||
if (action.changeMovement.movementType >= MAX_DB_MOTION_TYPE)
|
||||
{
|
||||
sLog.outErrorEventAI("Event %u Action %u uses invalid movement type %u (must be smaller than %u)", i, j + 1, action.changeMovement.movementType, MAX_DB_MOTION_TYPE);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sLog.outErrorEventAI("Event %u Action %u have currently not checked at load action type (%u). Need check code update?", i, j + 1, temp.action[j].type);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ namespace MaNGOS
|
|||
{
|
||||
if (u->GetTypeId() == TYPEID_UNIT && (
|
||||
((Creature*)u)->IsTotem() || ((Creature*)u)->IsPet() ||
|
||||
(((Creature*)u)->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)))
|
||||
(((Creature*)u)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_XP_AT_KILL)))
|
||||
return 0;
|
||||
|
||||
uint32 xp_gain = BaseGain(pl->getLevel(), u->getLevel(), GetContentLevelsForMapAndZone(pl->GetMapId(), pl->GetZoneId()));
|
||||
|
|
|
|||
|
|
@ -2048,30 +2048,27 @@ bool GameObject::HasStaticDBSpawnData() const
|
|||
return sObjectMgr.GetGOData(GetGUIDLow()) != NULL;
|
||||
}
|
||||
|
||||
void GameObject::SetCapturePointSlider(float value)
|
||||
void GameObject::SetCapturePointSlider(float value, bool isLocked)
|
||||
{
|
||||
GameObjectInfo const* info = GetGOInfo();
|
||||
|
||||
m_captureSlider = value;
|
||||
|
||||
// only activate non-locked capture point
|
||||
if (value >= 0)
|
||||
{
|
||||
m_captureSlider = value;
|
||||
{ SetLootState(GO_ACTIVATED); }
|
||||
}
|
||||
else
|
||||
m_captureSlider = -value;
|
||||
if (!isLocked)
|
||||
SetLootState(GO_ACTIVATED);
|
||||
|
||||
// set the state of the capture point based on the slider value
|
||||
if ((int)m_captureSlider == CAPTURE_SLIDER_ALLIANCE)
|
||||
{ m_captureState = CAPTURE_STATE_WIN_ALLIANCE; }
|
||||
m_captureState = CAPTURE_STATE_WIN_ALLIANCE;
|
||||
else if ((int)m_captureSlider == CAPTURE_SLIDER_HORDE)
|
||||
{ m_captureState = CAPTURE_STATE_WIN_HORDE; }
|
||||
m_captureState = CAPTURE_STATE_WIN_HORDE;
|
||||
else if (m_captureSlider > CAPTURE_SLIDER_MIDDLE + info->capturePoint.neutralPercent * 0.5f)
|
||||
{ m_captureState = CAPTURE_STATE_PROGRESS_ALLIANCE; }
|
||||
m_captureState = CAPTURE_STATE_PROGRESS_ALLIANCE;
|
||||
else if (m_captureSlider < CAPTURE_SLIDER_MIDDLE - info->capturePoint.neutralPercent * 0.5f)
|
||||
{ m_captureState = CAPTURE_STATE_PROGRESS_HORDE; }
|
||||
m_captureState = CAPTURE_STATE_PROGRESS_HORDE;
|
||||
else
|
||||
{ m_captureState = CAPTURE_STATE_NEUTRAL; }
|
||||
m_captureState = CAPTURE_STATE_NEUTRAL;
|
||||
}
|
||||
|
||||
void GameObject::TickCapturePoint()
|
||||
|
|
|
|||
|
|
@ -622,11 +622,11 @@ enum CapturePointState
|
|||
CAPTURE_STATE_WIN_HORDE
|
||||
};
|
||||
|
||||
enum CapturePointSlider
|
||||
enum CapturePointSliderValue
|
||||
{
|
||||
CAPTURE_SLIDER_ALLIANCE = 100, // full alliance
|
||||
CAPTURE_SLIDER_HORDE = 0, // full horde
|
||||
CAPTURE_SLIDER_MIDDLE = 50 // middle
|
||||
CAPTURE_SLIDER_ALLIANCE = 100, // full alliance
|
||||
CAPTURE_SLIDER_HORDE = 0, // full horde
|
||||
CAPTURE_SLIDER_MIDDLE = 50 // middle
|
||||
};
|
||||
|
||||
class Unit;
|
||||
|
|
@ -796,8 +796,10 @@ class GameObject : public WorldObject
|
|||
|
||||
GameObject* LookupFishingHoleAround(float range);
|
||||
|
||||
void SetCapturePointSlider(float value);
|
||||
float GetCapturePointSlider() const { return m_captureSlider; }
|
||||
void SetCapturePointSlider(float value, bool isLocked);
|
||||
float GetCapturePointSliderValue() const { return m_captureSlider; }
|
||||
|
||||
float GetInteractionDistance();
|
||||
|
||||
uint32 GetScriptId();
|
||||
|
||||
|
|
|
|||
|
|
@ -583,7 +583,7 @@ void Guild::BroadcastToGuild(WorldSession* session, const std::string& msg, uint
|
|||
if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(), GR_RIGHT_GCHATSPEAK))
|
||||
{
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, session, CHAT_MSG_GUILD, language, msg.c_str());
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_GUILD, msg.c_str(), Language(language), session->GetPlayer()->GetChatTag(), session->GetPlayer()->GetObjectGuid(), session->GetPlayer()->GetName());
|
||||
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
|
|
@ -600,7 +600,7 @@ void Guild::BroadcastAddonToGuild(WorldSession* session, const std::string& msg,
|
|||
if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(), GR_RIGHT_GCHATSPEAK))
|
||||
{
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, session,CHAT_MSG_GUILD, CHAT_MSG_ADDON, NULL, ObjectGuid(), msg.c_str(), NULL, prefix.c_str());
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_GUILD, msg.c_str(), LANG_ADDON, CHAT_TAG_NONE, ObjectGuid(), NULL, ObjectGuid(), NULL, NULL, 0, prefix.c_str());
|
||||
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
|
|
@ -614,18 +614,22 @@ void Guild::BroadcastAddonToGuild(WorldSession* session, const std::string& msg,
|
|||
|
||||
void Guild::BroadcastToOfficers(WorldSession* session, const std::string& msg, uint32 language)
|
||||
{
|
||||
if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(), GR_RIGHT_OFFCHATSPEAK))
|
||||
if (!session)
|
||||
return;
|
||||
|
||||
Player* player = session->GetPlayer();
|
||||
if (!player || !HasRankRight(player->GetRank(), GR_RIGHT_OFFCHATSPEAK))
|
||||
return;
|
||||
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, session, CHAT_MSG_OFFICER, language, msg.c_str());
|
||||
WorldPacket data;
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_OFFICER, msg.c_str(), Language(language), player->GetChatTag(), player->GetObjectGuid(), player->GetName());
|
||||
|
||||
Player* pl = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first));
|
||||
Player* pl = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first));
|
||||
|
||||
if (pl && pl->GetSession() && HasRankRight(pl->GetRank(), GR_RIGHT_OFFCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetObjectGuid()))
|
||||
pl->GetSession()->SendPacket(&data);
|
||||
}
|
||||
if (pl && pl->GetSession() && HasRankRight(pl->GetRank(), GR_RIGHT_OFFCHATLISTEN) && !pl->GetSocial()->HasIgnore(player->GetObjectGuid()))
|
||||
pl->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -636,7 +640,7 @@ void Guild::BroadcastAddonToOfficers(WorldSession* session, const std::string& m
|
|||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, session, CHAT_MSG_OFFICER, CHAT_MSG_ADDON, NULL, ObjectGuid(), msg.c_str(), NULL, prefix.c_str());
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_OFFICER, msg.c_str(), LANG_ADDON, CHAT_TAG_NONE, ObjectGuid(), NULL, ObjectGuid(), NULL, NULL, 0, prefix.c_str());
|
||||
|
||||
Player* pl = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first));
|
||||
|
||||
|
|
|
|||
|
|
@ -47,11 +47,11 @@ static eConfigFloatValues const qualityToRate[MAX_ITEM_QUALITY] =
|
|||
LootStore LootTemplates_Creature("creature_loot_template", "creature entry", true);
|
||||
LootStore LootTemplates_Disenchant("disenchant_loot_template", "item disenchant id", true);
|
||||
LootStore LootTemplates_Fishing("fishing_loot_template", "area id", true);
|
||||
LootStore LootTemplates_Gameobject("gameobject_loot_template", "gameobject lootid", true);
|
||||
LootStore LootTemplates_Gameobject("gameobject_loot_template", "gameobject Lootid", true);
|
||||
LootStore LootTemplates_Item("item_loot_template", "item entry with ITEM_FLAG_LOOTABLE", true);
|
||||
LootStore LootTemplates_Mail("mail_loot_template", "mail template id", false);
|
||||
LootStore LootTemplates_Milling("milling_loot_template", "item entry (herb)", true);
|
||||
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template", "creature pickpocket lootid", true);
|
||||
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template", "creature pickpocket Lootid", true);
|
||||
LootStore LootTemplates_Prospecting("prospecting_loot_template", "item entry (ore)", true);
|
||||
LootStore LootTemplates_Reference("reference_loot_template", "reference id", false);
|
||||
LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true);
|
||||
|
|
@ -1271,12 +1271,12 @@ void LoadLootTemplates_Creature()
|
|||
{
|
||||
if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
|
||||
{
|
||||
if (uint32 lootid = cInfo->lootid)
|
||||
if (uint32 Lootid = cInfo->LootId)
|
||||
{
|
||||
if (ids_set.find(lootid) == ids_set.end())
|
||||
LootTemplates_Creature.ReportNotExistedId(lootid);
|
||||
if (ids_set.find(Lootid) == ids_set.end())
|
||||
LootTemplates_Creature.ReportNotExistedId(Lootid);
|
||||
else
|
||||
ids_setUsed.insert(lootid);
|
||||
ids_setUsed.insert(Lootid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1301,12 +1301,12 @@ void LoadLootTemplates_Disenchant()
|
|||
{
|
||||
if (ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i))
|
||||
{
|
||||
if (uint32 lootid = proto->DisenchantID)
|
||||
if (uint32 Lootid = proto->DisenchantID)
|
||||
{
|
||||
if (ids_set.find(lootid) == ids_set.end())
|
||||
LootTemplates_Disenchant.ReportNotExistedId(lootid);
|
||||
if (ids_set.find(Lootid) == ids_set.end())
|
||||
LootTemplates_Disenchant.ReportNotExistedId(Lootid);
|
||||
else
|
||||
ids_setUsed.insert(lootid);
|
||||
ids_setUsed.insert(Lootid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1344,12 +1344,12 @@ void LoadLootTemplates_Gameobject()
|
|||
// remove real entries and check existence loot
|
||||
for (SQLStorageBase::SQLSIterator<GameObjectInfo> itr = sGOStorage.getDataBegin<GameObjectInfo>(); itr < sGOStorage.getDataEnd<GameObjectInfo>(); ++itr)
|
||||
{
|
||||
if (uint32 lootid = itr->GetLootId())
|
||||
if (uint32 Lootid = itr->GetLootId())
|
||||
{
|
||||
if (ids_set.find(lootid) == ids_set.end())
|
||||
LootTemplates_Gameobject.ReportNotExistedId(lootid);
|
||||
if (ids_set.find(Lootid) == ids_set.end())
|
||||
LootTemplates_Gameobject.ReportNotExistedId(Lootid);
|
||||
else
|
||||
ids_setUsed.insert(lootid);
|
||||
ids_setUsed.insert(Lootid);
|
||||
}
|
||||
}
|
||||
for (LootIdSet::const_iterator itr = ids_setUsed.begin(); itr != ids_setUsed.end(); ++itr)
|
||||
|
|
@ -1419,12 +1419,12 @@ void LoadLootTemplates_Pickpocketing()
|
|||
{
|
||||
if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
|
||||
{
|
||||
if (uint32 lootid = cInfo->pickpocketLootId)
|
||||
if (uint32 Lootid = cInfo->PickpocketLootId)
|
||||
{
|
||||
if (ids_set.find(lootid) == ids_set.end())
|
||||
LootTemplates_Pickpocketing.ReportNotExistedId(lootid);
|
||||
if (ids_set.find(Lootid) == ids_set.end())
|
||||
LootTemplates_Pickpocketing.ReportNotExistedId(Lootid);
|
||||
else
|
||||
ids_setUsed.insert(lootid);
|
||||
ids_setUsed.insert(Lootid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1485,12 +1485,12 @@ void LoadLootTemplates_Skinning()
|
|||
{
|
||||
if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
|
||||
{
|
||||
if (uint32 lootid = cInfo->SkinLootId)
|
||||
if (uint32 Lootid = cInfo->SkinningLootId)
|
||||
{
|
||||
if (ids_set.find(lootid) == ids_set.end())
|
||||
LootTemplates_Skinning.ReportNotExistedId(lootid);
|
||||
if (ids_set.find(Lootid) == ids_set.end())
|
||||
LootTemplates_Skinning.ReportNotExistedId(Lootid);
|
||||
else
|
||||
ids_setUsed.insert(lootid);
|
||||
ids_setUsed.insert(Lootid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "TemporarySummon.h"
|
||||
#include "movement/packet_builder.h"
|
||||
#include "CreatureLinkingMgr.h"
|
||||
#include "Chat.h"
|
||||
#ifdef ENABLE_ELUNA
|
||||
#include "LuaEngine.h"
|
||||
#include "ElunaEventMgr.h"
|
||||
|
|
@ -1550,22 +1551,24 @@ bool WorldObject::IsPositionValid() const
|
|||
void WorldObject::MonsterSay(const char* text, uint32 language, Unit const* target) const
|
||||
{
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildMonsterChat(&data, GetObjectGuid(), CHAT_MSG_MONSTER_SAY, text, language, GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_MONSTER_SAY, text, LANG_UNIVERSAL, CHAT_TAG_NONE, GetObjectGuid(), GetName(),
|
||||
target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
|
||||
SendMessageToSetInRange(&data, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY), true);
|
||||
}
|
||||
|
||||
void WorldObject::MonsterYell(const char* text, uint32 language, Unit const* target) const
|
||||
{
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildMonsterChat(&data, GetObjectGuid(), CHAT_MSG_MONSTER_YELL, text, language, GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_MONSTER_YELL, text, LANG_UNIVERSAL, CHAT_TAG_NONE, GetObjectGuid(), GetName(),
|
||||
target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
|
||||
SendMessageToSetInRange(&data, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL), true);
|
||||
}
|
||||
|
||||
void WorldObject::MonsterTextEmote(const char* text, Unit const* target, bool IsBossEmote) const
|
||||
{
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildMonsterChat(&data, GetObjectGuid(), IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, text, LANG_UNIVERSAL,
|
||||
GetName(), target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
|
||||
ChatHandler::BuildChatPacket(data, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, text, LANG_UNIVERSAL, CHAT_TAG_NONE, GetObjectGuid(), GetName(),
|
||||
target ? target->GetObjectGuid() : ObjectGuid(), target ? target->GetName() : "");
|
||||
SendMessageToSetInRange(&data, sWorld.getConfig(IsBossEmote ? CONFIG_FLOAT_LISTEN_RANGE_YELL : CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE), true);
|
||||
}
|
||||
|
||||
|
|
@ -1575,8 +1578,8 @@ void WorldObject::MonsterWhisper(const char* text, Unit const* target, bool IsBo
|
|||
{ return; }
|
||||
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildMonsterChat(&data, GetObjectGuid(), IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL,
|
||||
GetName(), target->GetObjectGuid(), target->GetName());
|
||||
ChatHandler::BuildChatPacket(data, IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL, CHAT_TAG_NONE, GetObjectGuid(), GetName(),
|
||||
target->GetObjectGuid(), target->GetName());
|
||||
((Player*)target)->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
@ -1584,102 +1587,87 @@ namespace MaNGOS
|
|||
{
|
||||
class MonsterChatBuilder
|
||||
{
|
||||
public:
|
||||
MonsterChatBuilder(WorldObject const& obj, ChatMsg msgtype, int32 textId, uint32 language, Unit const* target)
|
||||
: i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language), i_target(target) {}
|
||||
public:
|
||||
MonsterChatBuilder(WorldObject const& obj, ChatMsg msgtype, MangosStringLocale const* textData, Language language, Unit const* target)
|
||||
: i_object(obj), i_msgtype(msgtype), i_textData(textData), i_language(language), i_target(target) {}
|
||||
void operator()(WorldPacket& data, int32 loc_idx)
|
||||
{
|
||||
char const* text = sObjectMgr.GetMangosString(i_textId, loc_idx);
|
||||
char const* text = nullptr;
|
||||
if ((int32)i_textData->Content.size() > loc_idx + 1 && !i_textData->Content[loc_idx + 1].empty())
|
||||
text = i_textData->Content[loc_idx + 1].c_str();
|
||||
else
|
||||
text = i_textData->Content[0].c_str();
|
||||
|
||||
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) : "");
|
||||
ChatHandler::BuildChatPacket(data, i_msgtype, text, i_language, CHAT_TAG_NONE, i_object.GetObjectGuid(), i_object.GetNameForLocaleIdx(loc_idx),
|
||||
i_target ? i_target->GetObjectGuid() : ObjectGuid(), i_target ? i_target->GetNameForLocaleIdx(loc_idx) : "");
|
||||
}
|
||||
|
||||
private:
|
||||
WorldObject const& i_object;
|
||||
ChatMsg i_msgtype;
|
||||
int32 i_textId;
|
||||
uint32 i_language;
|
||||
MangosStringLocale const* i_textData;
|
||||
Language i_language;
|
||||
Unit const* i_target;
|
||||
};
|
||||
} // namespace MaNGOS
|
||||
|
||||
void WorldObject::MonsterSay(int32 textId, uint32 language, Unit const* target) const
|
||||
/// Helper function to create localized around a source
|
||||
void _DoLocalizedTextAround(WorldObject const* source, MangosStringLocale const* textData, ChatMsg msgtype, Language language, Unit const* target, float range)
|
||||
{
|
||||
float range = sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY);
|
||||
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_SAY, textId, language, target);
|
||||
MaNGOS::MonsterChatBuilder say_build(*source, msgtype, textData, language, target);
|
||||
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
|
||||
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this, range, say_do);
|
||||
Cell::VisitWorldObjects(this, say_worker, range);
|
||||
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(source, range, say_do);
|
||||
Cell::VisitWorldObjects(source, say_worker, range);
|
||||
}
|
||||
|
||||
void WorldObject::MonsterYell(int32 textId, uint32 language, Unit const* target) const
|
||||
/// Function that sends a text associated to a MangosString
|
||||
void WorldObject::MonsterText(MangosStringLocale const* textData, Unit const* target) const
|
||||
{
|
||||
float range = sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL);
|
||||
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId, language, target);
|
||||
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
|
||||
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this, range, say_do);
|
||||
Cell::VisitWorldObjects(this, say_worker, range);
|
||||
}
|
||||
MANGOS_ASSERT(textData);
|
||||
|
||||
void WorldObject::MonsterYellToZone(int32 textId, uint32 language, Unit const* target) const
|
||||
{
|
||||
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId, language, target);
|
||||
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
|
||||
|
||||
uint32 zoneid = GetZoneId();
|
||||
|
||||
Map::PlayerList const& pList = GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
|
||||
if (itr->getSource()->GetZoneId() == zoneid)
|
||||
say_do(itr->getSource());
|
||||
}
|
||||
|
||||
void WorldObject::MonsterTextEmote(int32 textId, Unit const* target, bool IsBossEmote) const
|
||||
{
|
||||
float range = sWorld.getConfig(IsBossEmote ? CONFIG_FLOAT_LISTEN_RANGE_YELL : CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE);
|
||||
|
||||
MaNGOS::MonsterChatBuilder say_build(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId, LANG_UNIVERSAL, target);
|
||||
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
|
||||
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this, range, say_do);
|
||||
Cell::VisitWorldObjects(this, say_worker, range);
|
||||
}
|
||||
|
||||
void WorldObject::MonsterWhisper(int32 textId, Unit const* target, bool IsBossWhisper) const
|
||||
{
|
||||
if (!target || target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
uint32 loc_idx = ((Player*)target)->GetSession()->GetSessionDbLocaleIndex();
|
||||
char const* text = sObjectMgr.GetMangosString(textId, loc_idx);
|
||||
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildMonsterChat(&data, GetObjectGuid(), IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL,
|
||||
GetNameForLocaleIdx(loc_idx), target->GetObjectGuid(), "");
|
||||
|
||||
((Player*)target)->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
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 << uint32(language);
|
||||
*data << ObjectGuid(senderGuid);
|
||||
*data << uint32(0); // 2.1.0
|
||||
*data << uint32(strlen(name) + 1);
|
||||
*data << name;
|
||||
*data << ObjectGuid(targetGuid); // Unit Target
|
||||
if (targetGuid && !targetGuid.IsPlayer())
|
||||
switch (textData->Type)
|
||||
{
|
||||
*data << uint32(strlen(targetName) + 1); // target name length
|
||||
*data << targetName; // target name
|
||||
}
|
||||
*data << uint32(strlen(text) + 1);
|
||||
*data << text;
|
||||
*data << uint8(0); // ChatTag
|
||||
if (msgtype == CHAT_MSG_RAID_BOSS_EMOTE || msgtype == CHAT_MSG_RAID_BOSS_WHISPER)
|
||||
{
|
||||
*data << float(0.0f);
|
||||
*data << uint8(0);
|
||||
case CHAT_TYPE_SAY:
|
||||
_DoLocalizedTextAround(this, textData, CHAT_MSG_MONSTER_SAY, textData->LanguageId, target, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY));
|
||||
break;
|
||||
case CHAT_TYPE_YELL:
|
||||
_DoLocalizedTextAround(this, textData, CHAT_MSG_MONSTER_YELL, textData->LanguageId, target, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL));
|
||||
break;
|
||||
case CHAT_TYPE_TEXT_EMOTE:
|
||||
_DoLocalizedTextAround(this, textData, CHAT_MSG_MONSTER_EMOTE, LANG_UNIVERSAL, target, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE));
|
||||
break;
|
||||
case CHAT_TYPE_BOSS_EMOTE:
|
||||
_DoLocalizedTextAround(this, textData, CHAT_MSG_RAID_BOSS_EMOTE, LANG_UNIVERSAL, target, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL));
|
||||
break;
|
||||
case CHAT_TYPE_WHISPER:
|
||||
{
|
||||
if (!target || target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_WHISPER, textData, LANG_UNIVERSAL, target);
|
||||
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
|
||||
say_do((Player*)target);
|
||||
break;
|
||||
}
|
||||
case CHAT_TYPE_BOSS_WHISPER:
|
||||
{
|
||||
if (!target || target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_RAID_BOSS_WHISPER, textData, LANG_UNIVERSAL, target);
|
||||
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
|
||||
say_do((Player*)target);
|
||||
break;
|
||||
}
|
||||
case CHAT_TYPE_ZONE_YELL:
|
||||
{
|
||||
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textData, textData->LanguageId, target);
|
||||
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
|
||||
uint32 zoneid = GetZoneId();
|
||||
Map::PlayerList const& pList = GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
|
||||
if (itr->getSource()->GetZoneId() == zoneid)
|
||||
say_do(itr->getSource());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -601,16 +601,13 @@ class WorldObject : public Object
|
|||
virtual void SendMessageToSetInRange(WorldPacket* data, float dist, bool self) const;
|
||||
void SendMessageToSetExcept(WorldPacket* data, Player const* skipped_receiver) const;
|
||||
|
||||
void MonsterSay(const char* text, uint32 language, Unit const* target = NULL) const;
|
||||
void MonsterYell(const char* text, uint32 language, Unit const* target = NULL) const;
|
||||
void MonsterSay(const char* text, uint32 language, Unit const* target = nullptr) const;
|
||||
void MonsterYell(const char* text, uint32 language, Unit const* target = nullptr) const;
|
||||
void MonsterTextEmote(const char* text, Unit const* target, bool IsBossEmote = false) const;
|
||||
void MonsterWhisper(const char* text, Unit const* target, bool IsBossWhisper = false) const;
|
||||
void MonsterSay(int32 textId, uint32 language, Unit const* target = NULL) const;
|
||||
void MonsterYell(int32 textId, uint32 language, Unit const* target = NULL) const;
|
||||
void MonsterTextEmote(int32 textId, Unit const* target, bool IsBossEmote = false) const;
|
||||
void MonsterWhisper(int32 textId, Unit const* receiver, bool IsBossWhisper = false) const;
|
||||
void MonsterText(MangosStringLocale const* textData, Unit const* target) const;
|
||||
|
||||
void MonsterYellToZone(int32 textId, uint32 language, Unit const* target) 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 const* target = NULL) const;
|
||||
void PlayDirectSound(uint32 sound_id, Player const* target = NULL) const;
|
||||
|
|
|
|||
|
|
@ -527,38 +527,38 @@ void ObjectMgr::LoadCreatureTemplates()
|
|||
if (!ok2)
|
||||
continue;
|
||||
|
||||
if (cInfo->unit_class != difficultyInfo->unit_class)
|
||||
if (cInfo->UnitClass != difficultyInfo->UnitFlags)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u, class %u) has different `unit_class` in difficulty %u mode (Entry: %u, class %u).",
|
||||
i, cInfo->unit_class, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->unit_class);
|
||||
sLog.outErrorDb("Creature (Entry: %u, class %u) has different `UnitClass` in difficulty %u mode (Entry: %u, class %u).",
|
||||
i, cInfo->UnitClass, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->UnitClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cInfo->npcflag != difficultyInfo->npcflag)
|
||||
if (cInfo->NpcFlags != difficultyInfo->NpcFlags)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has different `npcflag` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
|
||||
sLog.outErrorDb("Creature (Entry: %u) has different `NpcFlags` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cInfo->trainer_class != difficultyInfo->trainer_class)
|
||||
if (cInfo->TrainerClass != difficultyInfo->TrainerClass)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has different `trainer_class` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
|
||||
sLog.outErrorDb("Creature (Entry: %u) has different `TrainerClass` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cInfo->trainer_race != difficultyInfo->trainer_race)
|
||||
if (cInfo->TrainerRace != difficultyInfo->TrainerRace)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has different `trainer_race` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cInfo->trainer_type != difficultyInfo->trainer_type)
|
||||
if (cInfo->TrainerType != difficultyInfo->TrainerType)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has different `trainer_type` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
|
||||
sLog.outErrorDb("Creature (Entry: %u) has different `TrainerType` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cInfo->trainer_spell != difficultyInfo->trainer_spell)
|
||||
if (cInfo->TrainerSpell != difficultyInfo->TrainerSpell)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has different `trainer_spell` in difficulty %u mode (Entry: %u).", i, diff + 1, cInfo->DifficultyEntry[diff]);
|
||||
continue;
|
||||
|
|
@ -630,56 +630,89 @@ void ObjectMgr::LoadCreatureTemplates()
|
|||
if (!displayScaleEntry)
|
||||
sLog.outErrorDb("Creature (Entry: %u) has nonexistent modelid in modelid_1/modelid_2/modelid_3/modelid_4", cInfo->Entry);
|
||||
|
||||
if (!cInfo->minlevel)
|
||||
if (!cInfo->MinLevel)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid minlevel, set to 1", cInfo->Entry);
|
||||
const_cast<CreatureInfo*>(cInfo)->minlevel = 1;
|
||||
const_cast<CreatureInfo*>(cInfo)->MinLevel = 1;
|
||||
}
|
||||
|
||||
if (cInfo->minlevel > cInfo->maxlevel)
|
||||
if (cInfo->MinLevel > cInfo->MaxLevel)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid maxlevel, set to minlevel", cInfo->Entry);
|
||||
const_cast<CreatureInfo*>(cInfo)->maxlevel = cInfo->minlevel;
|
||||
const_cast<CreatureInfo*>(cInfo)->MaxLevel = cInfo->MinLevel;
|
||||
}
|
||||
|
||||
// use below code for 0-checks for unit_class
|
||||
if (!cInfo->unit_class)
|
||||
ERROR_DB_STRICT_LOG("Creature (Entry: %u) not has proper unit_class(%u) for creature_template", cInfo->Entry, cInfo->unit_class);
|
||||
else if (((1 << (cInfo->unit_class - 1)) & CLASSMASK_ALL_CREATURES) == 0)
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid unit_class(%u) for creature_template", cInfo->Entry, cInfo->unit_class);
|
||||
|
||||
if (cInfo->dmgschool >= MAX_SPELL_SCHOOL)
|
||||
if (cInfo->MinLevel > DEFAULT_MAX_CREATURE_LEVEL)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid spell school value (%u) in `dmgschool`", cInfo->Entry, cInfo->dmgschool);
|
||||
const_cast<CreatureInfo*>(cInfo)->dmgschool = SPELL_SCHOOL_NORMAL;
|
||||
sLog.outErrorDb("Creature (Entry: %u) `MinLevel` exceeds maximum allowed value of '%u'", cInfo->Entry, uint32(DEFAULT_MAX_CREATURE_LEVEL));
|
||||
const_cast<CreatureInfo*>(cInfo)->MinLevel = uint32(DEFAULT_MAX_CREATURE_LEVEL);
|
||||
}
|
||||
|
||||
if (cInfo->baseattacktime == 0)
|
||||
const_cast<CreatureInfo*>(cInfo)->baseattacktime = BASE_ATTACK_TIME;
|
||||
if (cInfo->MaxLevel > DEFAULT_MAX_CREATURE_LEVEL)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) `MaxLevel` exceeds maximum allowed value of '%u'", cInfo->Entry, uint32(DEFAULT_MAX_CREATURE_LEVEL));
|
||||
const_cast<CreatureInfo*>(cInfo)->MaxLevel = uint32(DEFAULT_MAX_CREATURE_LEVEL);
|
||||
}
|
||||
|
||||
if (cInfo->rangeattacktime == 0)
|
||||
const_cast<CreatureInfo*>(cInfo)->rangeattacktime = BASE_ATTACK_TIME;
|
||||
if (cInfo->Expansion > MAX_EXPANSION)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) `Expansion(%u)` is not correct", cInfo->Entry, uint32(MAX_EXPANSION));
|
||||
const_cast<CreatureInfo*>(cInfo)->Expansion = -1;
|
||||
}
|
||||
|
||||
if (cInfo->npcflag & UNIT_NPC_FLAG_SPELLCLICK)
|
||||
if (!cInfo->UnitClass || (((1 << (cInfo->UnitClass - 1)) & CLASSMASK_ALL_CREATURES) == 0))
|
||||
{
|
||||
ERROR_DB_STRICT_LOG("Creature (Entry: %u) does not have proper `UnitClass` (%u) in creature_template", cInfo->Entry, cInfo->UnitClass);
|
||||
// Mark NPC as having improper data by his expansion
|
||||
const_cast<CreatureInfo*>(cInfo)->Expansion = -1;
|
||||
}
|
||||
|
||||
if (!sLog.HasLogFilter(LOG_FILTER_DB_STRICTED_CHECK) && cInfo->Expansion >= 0) // TODO - Remove the DB_STRICTED_CHECK after a while
|
||||
{
|
||||
// check if ClassLevel data are available for all possible level of that creature
|
||||
for (uint32 level = cInfo->MinLevel; level <= cInfo->MaxLevel; ++level)
|
||||
{
|
||||
if (!GetCreatureClassLvlStats(level, cInfo->UnitClass, cInfo->Expansion))
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u), level(%u) has no data in `creature_template_classlevelstats`", cInfo->Entry, level);
|
||||
// Deactivate using ClassLevelStats for this NPC
|
||||
const_cast<CreatureInfo*>(cInfo)->Expansion = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cInfo->DamageSchool >= MAX_SPELL_SCHOOL)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid spell school value (%u) in `DamageSchool`", cInfo->Entry, cInfo->DamageSchool);
|
||||
const_cast<CreatureInfo*>(cInfo)->DamageSchool = SPELL_SCHOOL_NORMAL;
|
||||
}
|
||||
|
||||
if (cInfo->MeleeAttackPower == 0)
|
||||
const_cast<CreatureInfo*>(cInfo)->MeleeAttackPower = BASE_ATTACK_TIME;
|
||||
|
||||
if (cInfo->RangedAttackPower == 0)
|
||||
const_cast<CreatureInfo*>(cInfo)->RangedAttackPower = BASE_ATTACK_TIME;
|
||||
|
||||
if (cInfo->NpcFlags & UNIT_NPC_FLAG_SPELLCLICK)
|
||||
{
|
||||
sLog.outDebug("Creature (Entry: %u) has dynamic flag UNIT_NPC_FLAG_SPELLCLICK (%u) set, but it is expected to be set in run-time based at `npc_spellclick_spells` contents.", cInfo->Entry, UNIT_NPC_FLAG_SPELLCLICK);
|
||||
const_cast<CreatureInfo*>(cInfo)->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK;
|
||||
const_cast<CreatureInfo*>(cInfo)->NpcFlags &= ~UNIT_NPC_FLAG_SPELLCLICK;
|
||||
}
|
||||
|
||||
if ((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE)
|
||||
sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u", cInfo->Entry, cInfo->trainer_type);
|
||||
if ((cInfo->NpcFlags & UNIT_NPC_FLAG_TRAINER) && cInfo->TrainerType >= MAX_TRAINER_TYPE)
|
||||
sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u", cInfo->Entry, cInfo->TrainerType);
|
||||
|
||||
if (cInfo->type && !sCreatureTypeStore.LookupEntry(cInfo->type))
|
||||
if (cInfo->CreatureType && !sCreatureTypeStore.LookupEntry(cInfo->CreatureType))
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid creature type (%u) in `type`", cInfo->Entry, cInfo->type);
|
||||
const_cast<CreatureInfo*>(cInfo)->type = CREATURE_TYPE_HUMANOID;
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid creature type (%u) in `type`", cInfo->Entry, cInfo->CreatureType);
|
||||
const_cast<CreatureInfo*>(cInfo)->CreatureType = CREATURE_TYPE_HUMANOID;
|
||||
}
|
||||
|
||||
// must exist or used hidden but used in data horse case
|
||||
if (cInfo->family && !sCreatureFamilyStore.LookupEntry(cInfo->family) && cInfo->family != CREATURE_FAMILY_HORSE_CUSTOM)
|
||||
if (cInfo->Family && !sCreatureFamilyStore.LookupEntry(cInfo->Family) && cInfo->Family != CREATURE_FAMILY_HORSE_CUSTOM)
|
||||
{
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid creature family (%u) in `family`", cInfo->Entry, cInfo->family);
|
||||
const_cast<CreatureInfo*>(cInfo)->family = 0;
|
||||
sLog.outErrorDb("Creature (Entry: %u) has invalid creature family (%u) in `Family`", cInfo->Entry, cInfo->Family);
|
||||
const_cast<CreatureInfo*>(cInfo)->Family = 0;
|
||||
}
|
||||
|
||||
if (cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE)
|
||||
|
|
@ -716,10 +749,10 @@ void ObjectMgr::LoadCreatureTemplates()
|
|||
}
|
||||
}
|
||||
|
||||
if (cInfo->vendorId > 0)
|
||||
if (cInfo->VendorTemplateId > 0)
|
||||
{
|
||||
if (!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR))
|
||||
sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with vendor_id %u but not have flag UNIT_NPC_FLAG_VENDOR (%u), vendor items will ignored.", cInfo->Entry, cInfo->vendorId, UNIT_NPC_FLAG_VENDOR);
|
||||
if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_VENDOR))
|
||||
sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with vendor_id %u but not have flag UNIT_NPC_FLAG_VENDOR (%u), vendor items will ignored.", cInfo->Entry, cInfo->VendorTemplateId, UNIT_NPC_FLAG_VENDOR);
|
||||
}
|
||||
|
||||
/// if not set custom creature Scale then load Scale from CreatureDisplayInfo.dbc
|
||||
|
|
@ -948,6 +981,19 @@ void ObjectMgr::LoadCreatureClassLvlStats()
|
|||
sLog.outString(">> Loaded %u creature class level stats definitions.", DataCount);
|
||||
}
|
||||
|
||||
CreatureClassLvlStats const* ObjectMgr::GetCreatureClassLvlStats(uint32 level, uint32 unitClass, int32 expansion) const
|
||||
{
|
||||
if (expansion < 0)
|
||||
return nullptr;
|
||||
|
||||
CreatureClassLvlStats const* cCLS = &m_creatureClassLvlStats[level][classToIndex[unitClass]][expansion];
|
||||
|
||||
if (cCLS->BaseHealth != 0 && cCLS->BaseDamage > 0.1f)
|
||||
return cCLS;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadEquipmentTemplates()
|
||||
{
|
||||
sEquipmentStorage.Load();
|
||||
|
|
@ -1401,30 +1447,30 @@ void ObjectMgr::LoadCreatures()
|
|||
}
|
||||
}
|
||||
|
||||
if (cInfo->RegenHealth && data.curhealth < cInfo->minhealth)
|
||||
if (cInfo->RegenerateStats & REGEN_FLAG_HEALTH && data.curhealth < cInfo->MinLevelHealth)
|
||||
{
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`RegenHealth`=1 and low current health (%u), `creature_template`.`minhealth`=%u.", guid, data.id, data.curhealth, cInfo->minhealth);
|
||||
data.curhealth = cInfo->minhealth;
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`RegenHealth`=1 and low current health (%u), `creature_template`.`MinLevelHealth`=%u.", guid, data.id, data.curhealth, cInfo->MinLevelHealth);
|
||||
data.curhealth = cInfo->MinLevelHealth;
|
||||
}
|
||||
|
||||
if (cInfo->ExtraFlags & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
|
||||
if (cInfo->ExtraFlags & CREATURE_EXTRA_FLAG_INSTANCE_BIND)
|
||||
{
|
||||
if (!mapEntry || !mapEntry->IsDungeon())
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`ExtraFlags` including CREATURE_FLAG_EXTRA_INSTANCE_BIND (%u) but creature are not in instance.",
|
||||
guid, data.id, CREATURE_FLAG_EXTRA_INSTANCE_BIND);
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`ExtraFlags` including CREATURE_EXTRA_FLAG_INSTANCE_BIND (%u) but creature are not in instance.",
|
||||
guid, data.id, CREATURE_EXTRA_FLAG_INSTANCE_BIND);
|
||||
}
|
||||
|
||||
if (cInfo->ExtraFlags & CREATURE_FLAG_EXTRA_AGGRO_ZONE)
|
||||
if (cInfo->ExtraFlags & CREATURE_EXTRA_FLAG_AGGRO_ZONE)
|
||||
{
|
||||
if (!mapEntry || !mapEntry->IsDungeon())
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`ExtraFlags` including CREATURE_FLAG_EXTRA_AGGRO_ZONE (%u) but creature are not in instance.",
|
||||
guid, data.id, CREATURE_FLAG_EXTRA_AGGRO_ZONE);
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`ExtraFlags` including CREATURE_EXTRA_FLAG_AGGRO_ZONE (%u) but creature are not in instance.",
|
||||
guid, data.id, CREATURE_EXTRA_FLAG_AGGRO_ZONE);
|
||||
}
|
||||
|
||||
if (data.curmana < cInfo->minmana)
|
||||
if (data.curmana < cInfo->MinLevelMana)
|
||||
{
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with low current mana (%u), `creature_template`.`minmana`=%u.", guid, data.id, data.curmana, cInfo->minmana);
|
||||
data.curmana = cInfo->minmana;
|
||||
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with low current mana (%u), `creature_template`.`MinLevelMana`=%u.", guid, data.id, data.curmana, cInfo->MinLevelMana);
|
||||
data.curmana = cInfo->MinLevelMana;
|
||||
}
|
||||
|
||||
if (data.spawndist < 0.0f)
|
||||
|
|
@ -6601,7 +6647,7 @@ std::string ObjectMgr::GeneratePetName(uint32 entry)
|
|||
if (list0.empty() || list1.empty())
|
||||
{
|
||||
CreatureInfo const* cinfo = GetCreatureTemplate(entry);
|
||||
char const* petname = GetPetName(cinfo->family, sWorld.GetDefaultDbcLocale());
|
||||
char const* petname = GetPetName(cinfo->Family, sWorld.GetDefaultDbcLocale());
|
||||
if (!petname)
|
||||
petname = cinfo->Name;
|
||||
return std::string(petname);
|
||||
|
|
@ -7340,7 +7386,7 @@ void ObjectMgr::LoadNPCSpellClickSpells()
|
|||
mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info));
|
||||
|
||||
// mark creature template as spell clickable
|
||||
const_cast<CreatureInfo*>(cInfo)->npcflag |= UNIT_NPC_FLAG_SPELLCLICK;
|
||||
const_cast<CreatureInfo*>(cInfo)->NpcFlags |= UNIT_NPC_FLAG_SPELLCLICK;
|
||||
|
||||
++count;
|
||||
}
|
||||
|
|
@ -7544,8 +7590,8 @@ void ObjectMgr::LoadCreatureQuestRelations()
|
|||
CreatureInfo const* cInfo = GetCreatureTemplate(itr->first);
|
||||
if (!cInfo)
|
||||
sLog.outErrorDb("Table `creature_questrelation` have data for nonexistent creature entry (%u) and existing quest %u", itr->first, itr->second);
|
||||
else if (!(cInfo->npcflag & UNIT_NPC_FLAG_QUESTGIVER))
|
||||
sLog.outErrorDb("Table `creature_questrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second);
|
||||
else if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_QUESTGIVER))
|
||||
sLog.outErrorDb("Table `creature_questrelation` has creature entry (%u) for quest %u, but NpcFlags does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7558,8 +7604,8 @@ void ObjectMgr::LoadCreatureInvolvedRelations()
|
|||
CreatureInfo const* cInfo = GetCreatureTemplate(itr->first);
|
||||
if (!cInfo)
|
||||
sLog.outErrorDb("Table `creature_involvedrelation` have data for nonexistent creature entry (%u) and existing quest %u", itr->first, itr->second);
|
||||
else if (!(cInfo->npcflag & UNIT_NPC_FLAG_QUESTGIVER))
|
||||
sLog.outErrorDb("Table `creature_involvedrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second);
|
||||
else if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_QUESTGIVER))
|
||||
sLog.outErrorDb("Table `creature_involvedrelation` has creature entry (%u) for quest %u, but NpcFlags does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7997,10 +8043,10 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min
|
|||
// Load additional string content if necessary
|
||||
if (extra_content)
|
||||
{
|
||||
data.SoundId = fields[10].GetUInt32();
|
||||
data.Type = fields[11].GetUInt32();
|
||||
data.LanguageId = (Language)fields[12].GetUInt32();
|
||||
data.Emote = fields[13].GetUInt32();
|
||||
data.SoundId = fields[10].GetUInt32();
|
||||
data.Type = fields[11].GetUInt32();
|
||||
data.LanguageId = Language(fields[12].GetUInt32());
|
||||
data.Emote = fields[13].GetUInt32();
|
||||
|
||||
if (data.SoundId && !sSoundEntriesStore.LookupEntry(data.SoundId))
|
||||
{
|
||||
|
|
@ -8010,7 +8056,7 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min
|
|||
|
||||
if (!GetLanguageDescByID(data.LanguageId))
|
||||
{
|
||||
_DoStringError(entry, "Entry %i in table `%s` using Language %u but Language does not exist.", entry, table, data.LanguageId);
|
||||
_DoStringError(entry, "Entry %i in table `%s` using Language %u but Language does not exist.", entry, table, uint32(data.LanguageId));
|
||||
data.LanguageId = LANG_UNIVERSAL;
|
||||
}
|
||||
|
||||
|
|
@ -9237,7 +9283,7 @@ void ObjectMgr::LoadTrainers(char const* tableName, bool isTemplates)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!(cInfo->npcflag & UNIT_NPC_FLAG_TRAINER))
|
||||
if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_TRAINER))
|
||||
{
|
||||
if (skip_trainers.find(entry) == skip_trainers.end())
|
||||
{
|
||||
|
|
@ -9247,11 +9293,11 @@ void ObjectMgr::LoadTrainers(char const* tableName, bool isTemplates)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (TrainerSpellData const* tSpells = cInfo->trainerId ? GetNpcTrainerTemplateSpells(cInfo->trainerId) : NULL)
|
||||
if (TrainerSpellData const* tSpells = cInfo->TrainerTemplateId ? GetNpcTrainerTemplateSpells(cInfo->TrainerTemplateId) : NULL)
|
||||
{
|
||||
if (tSpells->spellList.find(spell) != tSpells->spellList.end())
|
||||
{
|
||||
sLog.outErrorDb("Table `%s` (Entry: %u) has spell %u listed in trainer template %u, ignore", tableName, entry, spell, cInfo->trainerId);
|
||||
sLog.outErrorDb("Table `%s` (Entry: %u) has spell %u listed in trainer template %u, ignore", tableName, entry, spell, cInfo->TrainerTemplateId);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -9349,12 +9395,12 @@ void ObjectMgr::LoadTrainerTemplates()
|
|||
{
|
||||
if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
|
||||
{
|
||||
if (cInfo->trainerId)
|
||||
if (cInfo->TrainerTemplateId)
|
||||
{
|
||||
if (m_mCacheTrainerTemplateSpellMap.find(cInfo->trainerId) != m_mCacheTrainerTemplateSpellMap.end())
|
||||
trainer_ids.erase(cInfo->trainerId);
|
||||
if (m_mCacheTrainerTemplateSpellMap.find(cInfo->TrainerTemplateId) != m_mCacheTrainerTemplateSpellMap.end())
|
||||
trainer_ids.erase(cInfo->TrainerTemplateId);
|
||||
else
|
||||
sLog.outErrorDb("Creature (Entry: %u) has trainer_id = %u for nonexistent trainer template", cInfo->Entry, cInfo->trainerId);
|
||||
sLog.outErrorDb("Creature (Entry: %u) has trainer_id = %u for nonexistent trainer template", cInfo->Entry, cInfo->TrainerTemplateId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9433,12 +9479,12 @@ void ObjectMgr::LoadVendorTemplates()
|
|||
{
|
||||
if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
|
||||
{
|
||||
if (cInfo->vendorId)
|
||||
if (cInfo->VendorTemplateId)
|
||||
{
|
||||
if (m_mCacheVendorTemplateItemMap.find(cInfo->vendorId) != m_mCacheVendorTemplateItemMap.end())
|
||||
vendor_ids.erase(cInfo->vendorId);
|
||||
if (m_mCacheVendorTemplateItemMap.find(cInfo->VendorTemplateId) != m_mCacheVendorTemplateItemMap.end())
|
||||
vendor_ids.erase(cInfo->VendorTemplateId);
|
||||
else
|
||||
sLog.outErrorDb("Creature (Entry: %u) has vendor_id = %u for nonexistent vendor template", cInfo->Entry, cInfo->vendorId);
|
||||
sLog.outErrorDb("Creature (Entry: %u) has vendor_id = %u for nonexistent vendor template", cInfo->Entry, cInfo->VendorTemplateId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9593,7 +9639,7 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
m_mGossipMenuItemsMap.clear();
|
||||
|
||||
QueryResult* result = WorldDatabase.Query(
|
||||
"SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, "
|
||||
"SELECT menu_id, id, option_icon, option_text, option_id, npc_option_NpcFlags, "
|
||||
"action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text, "
|
||||
"condition_id "
|
||||
"FROM gossip_menu_option ORDER BY menu_id, id");
|
||||
|
|
@ -9654,7 +9700,7 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
gMenuItem.option_icon = fields[2].GetUInt8();
|
||||
gMenuItem.option_text = fields[3].GetCppString();
|
||||
gMenuItem.option_id = fields[4].GetUInt32();
|
||||
gMenuItem.npc_option_npcflag = fields[5].GetUInt32();
|
||||
gMenuItem.npc_option_NpcFlags = fields[5].GetUInt32();
|
||||
gMenuItem.action_menu_id = fields[6].GetInt32();
|
||||
gMenuItem.action_poi_id = fields[7].GetUInt32();
|
||||
gMenuItem.action_script_id = fields[8].GetUInt32();
|
||||
|
|
@ -9693,7 +9739,7 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
if (gMenuItem.option_id >= GOSSIP_OPTION_MAX)
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown option id %u. Option will not be used", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_id);
|
||||
|
||||
if (gMenuItem.menu_id && gMenuItem.npc_option_npcflag)
|
||||
if (gMenuItem.menu_id && gMenuItem.npc_option_NpcFlags)
|
||||
{
|
||||
bool found_menu_uses = false;
|
||||
bool found_flags_uses = false;
|
||||
|
|
@ -9706,12 +9752,12 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
found_menu_uses = true;
|
||||
|
||||
// some from creatures with gossip menu can use gossip option base at npc_flags
|
||||
if (gMenuItem.npc_option_npcflag & cInfo->npcflag)
|
||||
if (gMenuItem.npc_option_NpcFlags & cInfo->NpcFlags)
|
||||
found_flags_uses = true;
|
||||
}
|
||||
|
||||
if (found_menu_uses && !found_flags_uses)
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has `npc_option_npcflag` = %u but creatures using this menu does not have corresponding`npcflag`. Option will not accessible in game.", gMenuItem.menu_id, gMenuItem.id, gMenuItem.npc_option_npcflag);
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has `npc_option_NpcFlags` = %u but creatures using this menu does not have corresponding`NpcFlags`. Option will not accessible in game.", gMenuItem.menu_id, gMenuItem.id, gMenuItem.npc_option_NpcFlags);
|
||||
}
|
||||
|
||||
if (gMenuItem.action_poi_id && !GetPointOfInterest(gMenuItem.action_poi_id))
|
||||
|
|
@ -9820,7 +9866,7 @@ bool ObjectMgr::IsVendorItemValid(bool isTemplate, char const* tableName, uint32
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR))
|
||||
if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_VENDOR))
|
||||
{
|
||||
if (!skip_vendors || skip_vendors->count(vendor_entry) == 0)
|
||||
{
|
||||
|
|
@ -9923,12 +9969,12 @@ bool ObjectMgr::IsVendorItemValid(bool isTemplate, char const* tableName, uint32
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!cInfo->vendorId)
|
||||
if (!cInfo->VendorTemplateId)
|
||||
sLog.outErrorDb("Table `%s` has duplicate items %u for %s %u, ignoring",
|
||||
tableName, item_id, idStr, vendor_entry);
|
||||
else
|
||||
sLog.outErrorDb("Table `%s` has duplicate items %u for %s %u (or possible in vendor template %u), ignoring",
|
||||
tableName, item_id, idStr, vendor_entry, cInfo->vendorId);
|
||||
tableName, item_id, idStr, vendor_entry, cInfo->VendorTemplateId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -9974,7 +10020,7 @@ bool ObjectMgr::IsVendorItemValid(bool isTemplate, char const* tableName, uint32
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR))
|
||||
if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_VENDOR))
|
||||
{
|
||||
if (!skip_vendors || skip_vendors->count(vendor_entry) == 0)
|
||||
{
|
||||
|
|
@ -10111,12 +10157,12 @@ bool ObjectMgr::IsVendorItemValid(bool isTemplate, char const* tableName, uint32
|
|||
ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, type == VENDOR_ITEM_TYPE_CURRENCY, ExtendedCost);
|
||||
else
|
||||
{
|
||||
if (!cInfo->vendorId)
|
||||
if (!cInfo->VendorTemplateId)
|
||||
sLog.outErrorDb("Table `%s` has duplicate %s %u (with extended cost %u) for %s %u, ignoring",
|
||||
tableName, nameStr, item_id, ExtendedCost, idStr, vendor_entry);
|
||||
else
|
||||
sLog.outErrorDb("Table `%s` has duplicate %s %u (with extended cost %u) for %s %u (or possible in vendor template %u), ignoring",
|
||||
tableName, nameStr, item_id, ExtendedCost, idStr, vendor_entry, cInfo->vendorId);
|
||||
tableName, nameStr, item_id, ExtendedCost, idStr, vendor_entry, cInfo->VendorTemplateId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -10366,47 +10412,13 @@ bool DoDisplayText(WorldObject* source, int32 entry, Unit const* target /*=NULL*
|
|||
}
|
||||
}
|
||||
|
||||
switch (data->Type)
|
||||
if ((data->Type == CHAT_TYPE_WHISPER || data->Type == CHAT_TYPE_BOSS_WHISPER) && (!target || target->GetTypeId() != TYPEID_PLAYER))
|
||||
{
|
||||
case CHAT_TYPE_SAY:
|
||||
source->MonsterSay(entry, data->LanguageId, target);
|
||||
break;
|
||||
case CHAT_TYPE_YELL:
|
||||
source->MonsterYell(entry, data->LanguageId, target);
|
||||
break;
|
||||
case CHAT_TYPE_TEXT_EMOTE:
|
||||
source->MonsterTextEmote(entry, target);
|
||||
break;
|
||||
case CHAT_TYPE_BOSS_EMOTE:
|
||||
source->MonsterTextEmote(entry, target, true);
|
||||
break;
|
||||
case CHAT_TYPE_WHISPER:
|
||||
{
|
||||
if (target && target->GetTypeId() == TYPEID_PLAYER)
|
||||
source->MonsterWhisper(entry, target);
|
||||
else
|
||||
{
|
||||
_DoStringError(entry, "DoDisplayText entry %i cannot whisper without target unit (TYPEID_PLAYER).", entry);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHAT_TYPE_BOSS_WHISPER:
|
||||
{
|
||||
if (target && target->GetTypeId() == TYPEID_PLAYER)
|
||||
source->MonsterWhisper(entry, target, true);
|
||||
else
|
||||
{
|
||||
_DoStringError(entry, "DoDisplayText entry %i cannot whisper without target unit (TYPEID_PLAYER).", entry);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHAT_TYPE_ZONE_YELL:
|
||||
source->MonsterYellToZone(entry, data->LanguageId, target);
|
||||
break;
|
||||
_DoStringError(entry, "DoDisplayText entry %i cannot whisper without target unit (TYPEID_PLAYER).", entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
source->MonsterText(data, target);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ typedef UNORDERED_MAP < uint32/*(mapid,spawnMode) pair*/, CellObjectGuidsMap > M
|
|||
#define MIN_MANGOS_STRING_ID 1 // 'mangos_string'
|
||||
#define MAX_MANGOS_STRING_ID 2000000000
|
||||
#define MIN_DB_SCRIPT_STRING_ID MAX_MANGOS_STRING_ID // 'db_script_string'
|
||||
#define MAX_DB_SCRIPT_STRING_ID 2000010000
|
||||
#define MAX_DB_SCRIPT_STRING_ID 2001000000
|
||||
#define MIN_CREATURE_AI_TEXT_STRING_ID (-1) // 'creature_ai_texts'
|
||||
#define MAX_CREATURE_AI_TEXT_STRING_ID (-1000000)
|
||||
// Anything below MAX_CREATURE_AI_TEXT_STRING_ID is handled by the external script lib
|
||||
|
|
@ -283,7 +283,7 @@ struct GossipMenuItems
|
|||
uint8 option_icon;
|
||||
std::string option_text;
|
||||
uint32 option_id;
|
||||
uint32 npc_option_npcflag;
|
||||
uint32 npc_option_NpcFlags;
|
||||
int32 action_menu_id;
|
||||
uint32 action_poi_id;
|
||||
uint32 action_script_id;
|
||||
|
|
@ -1191,6 +1191,19 @@ class ObjectMgr
|
|||
QuestRelationsMap& GetCreatureQuestRelationsMap() { return m_CreatureQuestRelations; }
|
||||
|
||||
uint32 GetModelForRace(uint32 sourceModelId, uint32 racemask);
|
||||
/**
|
||||
* \brief: Data returned is used to compute health, mana, armor, damage of creatures. May be nullptr.
|
||||
* \param uint32 level creature level
|
||||
* \param uint32 unitClass creature class, related to CLASSMASK_ALL_CREATURES
|
||||
* \param uint32 expansion creature expansion (we could have creature exp = 0 for wotlk as well as exp = 1 or exp = 2)
|
||||
* \return: CreatureClassLvlStats const* or nullptr
|
||||
*
|
||||
* Description: GetCreatureClassLvlStats give fast access to creature stats data.
|
||||
* FullName: ObjectMgr::GetCreatureClassLvlStats
|
||||
* Access: public
|
||||
* Qualifier: const
|
||||
**/
|
||||
CreatureClassLvlStats const* GetCreatureClassLvlStats(uint32 level, uint32 unitClass, int32 expansion) const;
|
||||
|
||||
void LoadHotfixData();
|
||||
HotfixData const& GetHotfixData() const { return m_hotfixData; }
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c
|
|||
|
||||
// reget for sure use real creature info selected for Pet at load/creating
|
||||
CreatureInfo const* cinfo = GetCreatureInfo();
|
||||
if (cinfo->type == CREATURE_TYPE_CRITTER)
|
||||
if (cinfo->CreatureType == CREATURE_TYPE_CRITTER)
|
||||
{
|
||||
AIM_Initialize();
|
||||
pos.GetMap()->Add((Creature*)this);
|
||||
|
|
@ -817,7 +817,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (cinfo->type == CREATURE_TYPE_CRITTER)
|
||||
if (cinfo->CreatureType == CREATURE_TYPE_CRITTER)
|
||||
{
|
||||
setPetType(MINI_PET);
|
||||
return true;
|
||||
|
|
@ -830,12 +830,12 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
|
|||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr.GetXPForPetLevel(creature->getLevel()));
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||
|
||||
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family))
|
||||
if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->Family))
|
||||
SetName(cFamily->Name[sWorld.GetDefaultDbcLocale()]);
|
||||
else
|
||||
SetName(creature->GetNameForLocaleIdx(sObjectMgr.GetDBCLocaleIndex()));
|
||||
|
||||
if (cinfo->type == CREATURE_TYPE_BEAST)
|
||||
if (cinfo->CreatureType == CREATURE_TYPE_BEAST)
|
||||
{
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 1, CLASS_WARRIOR);
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 2, GENDER_NONE);
|
||||
|
|
@ -889,7 +889,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
|
|||
|
||||
SetLevel(petlevel);
|
||||
|
||||
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
|
||||
SetMeleeDamageSchool(SpellSchools(cinfo->DamageSchool));
|
||||
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
|
||||
|
||||
|
|
@ -899,7 +899,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
|
|||
|
||||
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0);
|
||||
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family);
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->Family);
|
||||
if (cFamily && cFamily->minScale > 0.0f && getPetType() == HUNTER_PET)
|
||||
{
|
||||
float Scale;
|
||||
|
|
@ -919,12 +919,12 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
|
|||
|
||||
if (getPetType() != HUNTER_PET)
|
||||
{
|
||||
createResistance[SPELL_SCHOOL_HOLY] = cinfo->resistance1;
|
||||
createResistance[SPELL_SCHOOL_FIRE] = cinfo->resistance2;
|
||||
createResistance[SPELL_SCHOOL_NATURE] = cinfo->resistance3;
|
||||
createResistance[SPELL_SCHOOL_FROST] = cinfo->resistance4;
|
||||
createResistance[SPELL_SCHOOL_SHADOW] = cinfo->resistance5;
|
||||
createResistance[SPELL_SCHOOL_ARCANE] = cinfo->resistance6;
|
||||
createResistance[SPELL_SCHOOL_HOLY] = cinfo->ResistanceHoly;
|
||||
createResistance[SPELL_SCHOOL_FIRE] = cinfo->ResistanceFire;
|
||||
createResistance[SPELL_SCHOOL_NATURE] = cinfo->ResistanceNature;
|
||||
createResistance[SPELL_SCHOOL_FROST] = cinfo->ResistanceFrost;
|
||||
createResistance[SPELL_SCHOOL_SHADOW] = cinfo->ResistanceShadow;
|
||||
createResistance[SPELL_SCHOOL_ARCANE] = cinfo->ResistanceArcane;
|
||||
}
|
||||
|
||||
switch (getPetType())
|
||||
|
|
@ -985,8 +985,8 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
|
|||
sLog.outErrorDb("Summoned pet (Entry: %u) not have pet stats data in DB", cinfo->Entry);
|
||||
|
||||
// remove elite bonuses included in DB values
|
||||
SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
SetCreateMana(uint32(((float(cinfo->maxmana) / cinfo->maxlevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
SetCreateHealth(uint32(((float(cinfo->MaxLevelHealth) / cinfo->MaxLevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
SetCreateMana(uint32(((float(cinfo->MaxLevelMana) / cinfo->MaxLevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
|
||||
SetCreateStat(STAT_STRENGTH, 22);
|
||||
SetCreateStat(STAT_AGILITY, 22);
|
||||
|
|
@ -1024,7 +1024,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
|
|||
sLog.outErrorDb("Hunter pet levelstats missing in DB");
|
||||
|
||||
// remove elite bonuses included in DB values
|
||||
SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
SetCreateHealth(uint32(((float(cinfo->MaxLevelHealth) / cinfo->MaxLevel) / (1 + 2 * cinfo->Rank)) * petlevel));
|
||||
|
||||
SetCreateStat(STAT_STRENGTH, 22);
|
||||
SetCreateStat(STAT_AGILITY, 22);
|
||||
|
|
@ -1074,7 +1074,7 @@ bool Pet::HaveInDiet(ItemPrototype const* item) const
|
|||
if (!cInfo)
|
||||
return false;
|
||||
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family);
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->Family);
|
||||
if (!cFamily)
|
||||
return false;
|
||||
|
||||
|
|
@ -1563,7 +1563,7 @@ void Pet::InitLevelupSpellsForLevel()
|
|||
{
|
||||
uint32 level = getLevel();
|
||||
|
||||
if (PetLevelupSpellSet const* levelupSpells = GetCreatureInfo()->family ? sSpellMgr.GetPetLevelupSpellList(GetCreatureInfo()->family) : NULL)
|
||||
if (PetLevelupSpellSet const* levelupSpells = GetCreatureInfo()->Family ? sSpellMgr.GetPetLevelupSpellList(GetCreatureInfo()->Family) : NULL)
|
||||
{
|
||||
// PetLevelupSpellSet ordered by levels, process in reversed order
|
||||
for (PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr)
|
||||
|
|
@ -1702,7 +1702,7 @@ bool Pet::resetTalents(bool no_cost)
|
|||
if (!ci)
|
||||
return false;
|
||||
// Check pet talent type
|
||||
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
|
||||
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->Family);
|
||||
if (!pet_family || pet_family->petTalentType < 0)
|
||||
return false;
|
||||
|
||||
|
|
@ -1961,9 +1961,9 @@ bool Pet::IsPermanentPetFor(Player* owner)
|
|||
// oddly enough, Mage's Water Elemental is still treated as temporary pet with Glyph of Eternal Water
|
||||
// i.e. does not unsummon at mounting, gets dismissed at teleport etc.
|
||||
case CLASS_WARLOCK:
|
||||
return GetCreatureInfo()->type == CREATURE_TYPE_DEMON;
|
||||
return GetCreatureInfo()->CreatureType == CREATURE_TYPE_DEMON;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
return GetCreatureInfo()->type == CREATURE_TYPE_UNDEAD;
|
||||
return GetCreatureInfo()->CreatureType == CREATURE_TYPE_UNDEAD;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2012,7 +2012,7 @@ void Pet::LearnPetPassives()
|
|||
if (!cInfo)
|
||||
return;
|
||||
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->family);
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cInfo->Family);
|
||||
if (!cFamily)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ class Pet : public Creature
|
|||
return m_autospells[pos];
|
||||
}
|
||||
|
||||
bool CanSwim() const override
|
||||
bool CanSwim() const
|
||||
{
|
||||
Unit const* owner = GetOwner();
|
||||
if (owner)
|
||||
|
|
|
|||
|
|
@ -1526,7 +1526,7 @@ bool Player::BuildEnumData(QueryResult* result, ByteBuffer* data, ByteBuffer* bu
|
|||
{
|
||||
petDisplayId = fields[17].GetUInt32();
|
||||
petLevel = fields[18].GetUInt32();
|
||||
petFamily = cInfo->family;
|
||||
petFamily = cInfo->Family;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1644,9 +1644,9 @@ void Player::ToggleDND()
|
|||
ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_DND);
|
||||
}
|
||||
|
||||
uint8 Player::GetChatTag() const
|
||||
ChatTagFlags Player::GetChatTag() const
|
||||
{
|
||||
uint8 tag = CHAT_TAG_NONE;
|
||||
ChatTagFlags tag = CHAT_TAG_NONE;
|
||||
|
||||
if (isAFK())
|
||||
tag |= CHAT_TAG_AFK;
|
||||
|
|
@ -2291,7 +2291,7 @@ void Player::RegenerateHealth(uint32 diff)
|
|||
ModifyHealth(int32(addvalue));
|
||||
}
|
||||
|
||||
Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
|
||||
Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 NpcFlagsmask)
|
||||
{
|
||||
// some basic checks
|
||||
if (!guid || !IsInWorld() || IsTaxiFlying())
|
||||
|
|
@ -2307,10 +2307,10 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
|
|||
return NULL;
|
||||
|
||||
// appropriate npc type
|
||||
if (npcflagmask && !unit->HasFlag(UNIT_NPC_FLAGS, npcflagmask))
|
||||
if (NpcFlagsmask && !unit->HasFlag(UNIT_NPC_FLAGS, NpcFlagsmask))
|
||||
return NULL;
|
||||
|
||||
if (npcflagmask == UNIT_NPC_FLAG_STABLEMASTER)
|
||||
if (NpcFlagsmask == UNIT_NPC_FLAG_STABLEMASTER)
|
||||
{
|
||||
if (getClass() != CLASS_HUNTER)
|
||||
return NULL;
|
||||
|
|
@ -5047,7 +5047,7 @@ void Player::CleanupChannels()
|
|||
{
|
||||
Channel* ch = *m_channels.begin();
|
||||
m_channels.erase(m_channels.begin()); // remove from player's channel list
|
||||
ch->Leave(GetObjectGuid(), false); // not send to client, not remove from player's channel list
|
||||
ch->Leave(this, false); // not send to client, not remove from player's channel list
|
||||
if (ChannelMgr* cMgr = channelMgr(GetTeam()))
|
||||
cMgr->LeftChannel(ch->GetName()); // deleted channel if empty
|
||||
}
|
||||
|
|
@ -5091,13 +5091,13 @@ void Player::UpdateLocalChannels(uint32 newZone)
|
|||
|
||||
if ((*i) != new_channel)
|
||||
{
|
||||
new_channel->Join(GetObjectGuid(), ""); // will output Changed Channel: N. Name
|
||||
new_channel->Join(this, ""); // will output Changed Channel: N. Name
|
||||
|
||||
// leave old channel
|
||||
(*i)->Leave(GetObjectGuid(), false); // not send leave channel, it already replaced at client
|
||||
(*i)->Leave(this, false); // not send leave channel, it already replaced at client
|
||||
std::string name = (*i)->GetName(); // store name, (*i)erase in LeftChannel
|
||||
LeftChannel(*i); // remove from player's channel list
|
||||
cMgr->LeftChannel(name); // delete if empty
|
||||
cMgr->LeftChannel(name); // delete if empty // delete if empty
|
||||
}
|
||||
}
|
||||
DEBUG_LOG("Player: channels cleaned up!");
|
||||
|
|
@ -5109,7 +5109,7 @@ void Player::LeaveLFGChannel()
|
|||
{
|
||||
if ((*i)->IsLFG())
|
||||
{
|
||||
(*i)->Leave(GetObjectGuid());
|
||||
(*i)->Leave(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -8120,7 +8120,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
|||
// generate loot only if ready for open and spawned in world
|
||||
if (go->getLootState() == GO_READY && go->isSpawned())
|
||||
{
|
||||
uint32 lootid = go->GetGOInfo()->GetLootId();
|
||||
uint32 Lootid = go->GetGOInfo()->GetLootId();
|
||||
if ((go->GetEntry() == BG_AV_OBJECTID_MINE_N || go->GetEntry() == BG_AV_OBJECTID_MINE_S))
|
||||
{
|
||||
if (BattleGround* bg = GetBattleGround())
|
||||
|
|
@ -8149,11 +8149,11 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
|||
loot->FillLoot(zone, LootTemplates_Fishing, this, true);
|
||||
break;
|
||||
default:
|
||||
if (!lootid)
|
||||
if (!Lootid)
|
||||
break;
|
||||
DEBUG_LOG(" send normal GO loot");
|
||||
|
||||
loot->FillLoot(lootid, LootTemplates_Gameobject, this, false);
|
||||
loot->FillLoot(Lootid, LootTemplates_Gameobject, this, false);
|
||||
loot->generateMoneyLoot(go->GetGOInfo()->MinMoneyLoot, go->GetGOInfo()->MaxMoneyLoot);
|
||||
|
||||
if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules)
|
||||
|
|
@ -8313,8 +8313,8 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
|||
creature->lootForPickPocketed = true;
|
||||
loot->clear();
|
||||
|
||||
if (uint32 lootid = creature->GetCreatureInfo()->pickpocketLootId)
|
||||
loot->FillLoot(lootid, LootTemplates_Pickpocketing, this, false);
|
||||
if (uint32 Lootid = creature->GetCreatureInfo()->PickpocketLootId)
|
||||
loot->FillLoot(Lootid, LootTemplates_Pickpocketing, this, false);
|
||||
|
||||
// Generate extra money for pick pocket loot
|
||||
const uint32 a = urand(0, creature->getLevel() / 2);
|
||||
|
|
@ -8344,10 +8344,10 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
|||
creature->lootForBody = true;
|
||||
loot->clear();
|
||||
|
||||
if (uint32 lootid = creature->GetCreatureInfo()->lootid)
|
||||
loot->FillLoot(lootid, LootTemplates_Creature, recipient, false);
|
||||
if (uint32 Lootid = creature->GetCreatureInfo()->LootId)
|
||||
loot->FillLoot(Lootid, LootTemplates_Creature, recipient, false);
|
||||
|
||||
loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold, creature->GetCreatureInfo()->maxgold);
|
||||
loot->generateMoneyLoot(creature->GetCreatureInfo()->MinLootGold, creature->GetCreatureInfo()->MaxLootGold);
|
||||
|
||||
if (Group* group = creature->GetGroupLootRecipient())
|
||||
{
|
||||
|
|
@ -8378,7 +8378,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
|||
{
|
||||
creature->lootForSkin = true;
|
||||
loot->clear();
|
||||
loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, this, false);
|
||||
loot->FillLoot(creature->GetCreatureInfo()->SkinningLootId, LootTemplates_Skinning, this, false);
|
||||
|
||||
// let reopen skinning loot if will closed.
|
||||
if (!loot->empty())
|
||||
|
|
@ -8474,302 +8474,6 @@ void Player::SendUpdateWorldState(uint32 Field, uint32 Value)
|
|||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
static WorldStatePair AV_world_states[] =
|
||||
{
|
||||
{ 0x7ae, 0x1 }, // 1966 7 snowfall n
|
||||
{ 0x532, 0x1 }, // 1330 8 frostwolfhut hc
|
||||
{ 0x531, 0x0 }, // 1329 9 frostwolfhut ac
|
||||
{ 0x52e, 0x0 }, // 1326 10 stormpike firstaid a_a
|
||||
{ 0x571, 0x0 }, // 1393 11 east frostwolf tower horde assaulted -unused
|
||||
{ 0x570, 0x0 }, // 1392 12 west frostwolf tower horde assaulted - unused
|
||||
{ 0x567, 0x1 }, // 1383 13 frostwolfe c
|
||||
{ 0x566, 0x1 }, // 1382 14 frostwolfw c
|
||||
{ 0x550, 0x1 }, // 1360 15 irondeep (N) ally
|
||||
{ 0x544, 0x0 }, // 1348 16 ice grave a_a
|
||||
{ 0x536, 0x0 }, // 1334 17 stormpike grave h_c
|
||||
{ 0x535, 0x1 }, // 1333 18 stormpike grave a_c
|
||||
{ 0x518, 0x0 }, // 1304 19 stoneheart grave a_a
|
||||
{ 0x517, 0x0 }, // 1303 20 stoneheart grave h_a
|
||||
{ 0x574, 0x0 }, // 1396 21 unk
|
||||
{ 0x573, 0x0 }, // 1395 22 iceblood tower horde assaulted -unused
|
||||
{ 0x572, 0x0 }, // 1394 23 towerpoint horde assaulted - unused
|
||||
{ 0x56f, 0x0 }, // 1391 24 unk
|
||||
{ 0x56e, 0x0 }, // 1390 25 iceblood a
|
||||
{ 0x56d, 0x0 }, // 1389 26 towerp a
|
||||
{ 0x56c, 0x0 }, // 1388 27 frostwolfe a
|
||||
{ 0x56b, 0x0 }, // 1387 28 froswolfw a
|
||||
{ 0x56a, 0x1 }, // 1386 29 unk
|
||||
{ 0x569, 0x1 }, // 1385 30 iceblood c
|
||||
{ 0x568, 0x1 }, // 1384 31 towerp c
|
||||
{ 0x565, 0x0 }, // 1381 32 stoneh tower a
|
||||
{ 0x564, 0x0 }, // 1380 33 icewing tower a
|
||||
{ 0x563, 0x0 }, // 1379 34 dunn a
|
||||
{ 0x562, 0x0 }, // 1378 35 duns a
|
||||
{ 0x561, 0x0 }, // 1377 36 stoneheart bunker alliance assaulted - unused
|
||||
{ 0x560, 0x0 }, // 1376 37 icewing bunker alliance assaulted - unused
|
||||
{ 0x55f, 0x0 }, // 1375 38 dunbaldar south alliance assaulted - unused
|
||||
{ 0x55e, 0x0 }, // 1374 39 dunbaldar north alliance assaulted - unused
|
||||
{ 0x55d, 0x0 }, // 1373 40 stone tower d
|
||||
{ 0x3c6, 0x0 }, // 966 41 unk
|
||||
{ 0x3c4, 0x0 }, // 964 42 unk
|
||||
{ 0x3c2, 0x0 }, // 962 43 unk
|
||||
{ 0x516, 0x1 }, // 1302 44 stoneheart grave a_c
|
||||
{ 0x515, 0x0 }, // 1301 45 stonheart grave h_c
|
||||
{ 0x3b6, 0x0 }, // 950 46 unk
|
||||
{ 0x55c, 0x0 }, // 1372 47 icewing tower d
|
||||
{ 0x55b, 0x0 }, // 1371 48 dunn d
|
||||
{ 0x55a, 0x0 }, // 1370 49 duns d
|
||||
{ 0x559, 0x0 }, // 1369 50 unk
|
||||
{ 0x558, 0x0 }, // 1368 51 iceblood d
|
||||
{ 0x557, 0x0 }, // 1367 52 towerp d
|
||||
{ 0x556, 0x0 }, // 1366 53 frostwolfe d
|
||||
{ 0x555, 0x0 }, // 1365 54 frostwolfw d
|
||||
{ 0x554, 0x1 }, // 1364 55 stoneh tower c
|
||||
{ 0x553, 0x1 }, // 1363 56 icewing tower c
|
||||
{ 0x552, 0x1 }, // 1362 57 dunn c
|
||||
{ 0x551, 0x1 }, // 1361 58 duns c
|
||||
{ 0x54f, 0x0 }, // 1359 59 irondeep (N) horde
|
||||
{ 0x54e, 0x0 }, // 1358 60 irondeep (N) ally
|
||||
{ 0x54d, 0x1 }, // 1357 61 mine (S) neutral
|
||||
{ 0x54c, 0x0 }, // 1356 62 mine (S) horde
|
||||
{ 0x54b, 0x0 }, // 1355 63 mine (S) ally
|
||||
{ 0x545, 0x0 }, // 1349 64 iceblood h_a
|
||||
{ 0x543, 0x1 }, // 1347 65 iceblod h_c
|
||||
{ 0x542, 0x0 }, // 1346 66 iceblood a_c
|
||||
{ 0x540, 0x0 }, // 1344 67 snowfall h_a
|
||||
{ 0x53f, 0x0 }, // 1343 68 snowfall a_a
|
||||
{ 0x53e, 0x0 }, // 1342 69 snowfall h_c
|
||||
{ 0x53d, 0x0 }, // 1341 70 snowfall a_c
|
||||
{ 0x53c, 0x0 }, // 1340 71 frostwolf g h_a
|
||||
{ 0x53b, 0x0 }, // 1339 72 frostwolf g a_a
|
||||
{ 0x53a, 0x1 }, // 1338 73 frostwolf g h_c
|
||||
{ 0x539, 0x0 }, // l33t 74 frostwolf g a_c
|
||||
{ 0x538, 0x0 }, // 1336 75 stormpike grave h_a
|
||||
{ 0x537, 0x0 }, // 1335 76 stormpike grave a_a
|
||||
{ 0x534, 0x0 }, // 1332 77 frostwolf hut h_a
|
||||
{ 0x533, 0x0 }, // 1331 78 frostwolf hut a_a
|
||||
{ 0x530, 0x0 }, // 1328 79 stormpike first aid h_a
|
||||
{ 0x52f, 0x0 }, // 1327 80 stormpike first aid h_c
|
||||
{ 0x52d, 0x1 }, // 1325 81 stormpike first aid a_c
|
||||
{ 0x0, 0x0 }
|
||||
};
|
||||
|
||||
static WorldStatePair WS_world_states[] =
|
||||
{
|
||||
{ 0x62d, 0x0 }, // 1581 7 alliance flag captures
|
||||
{ 0x62e, 0x0 }, // 1582 8 horde flag captures
|
||||
{ 0x609, 0x0 }, // 1545 9 unk, set to 1 on alliance flag pickup...
|
||||
{ 0x60a, 0x0 }, // 1546 10 unk, set to 1 on horde flag pickup, after drop it's -1
|
||||
{ 0x60b, 0x2 }, // 1547 11 unk
|
||||
{ 0x641, 0x3 }, // 1601 12 unk (max flag captures?)
|
||||
{ 0x922, 0x1 }, // 2338 13 horde (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing)
|
||||
{ 0x923, 0x1 }, // 2339 14 alliance (0 - hide, 1 - flag ok, 2 - flag picked up (flashing), 3 - flag picked up (not flashing)
|
||||
{ 0x1097, 0x1 }, // 4247 15 show time limit?
|
||||
{ 0x1098, 0x19 }, // 4248 16 time remaining in minutes
|
||||
{ 0x0, 0x0 }
|
||||
};
|
||||
|
||||
static WorldStatePair AB_world_states[] =
|
||||
{
|
||||
{ 0x6e7, 0x0 }, // 1767 7 stables alliance
|
||||
{ 0x6e8, 0x0 }, // 1768 8 stables horde
|
||||
{ 0x6e9, 0x0 }, // 1769 9 unk, ST?
|
||||
{ 0x6ea, 0x0 }, // 1770 10 stables (show/hide)
|
||||
{ 0x6ec, 0x0 }, // 1772 11 farm (0 - horde controlled, 1 - alliance controlled)
|
||||
{ 0x6ed, 0x0 }, // 1773 12 farm (show/hide)
|
||||
{ 0x6ee, 0x0 }, // 1774 13 farm color
|
||||
{ 0x6ef, 0x0 }, // 1775 14 gold mine color, may be FM?
|
||||
{ 0x6f0, 0x0 }, // 1776 15 alliance resources
|
||||
{ 0x6f1, 0x0 }, // 1777 16 horde resources
|
||||
{ 0x6f2, 0x0 }, // 1778 17 horde bases
|
||||
{ 0x6f3, 0x0 }, // 1779 18 alliance bases
|
||||
{ 0x6f4, 0x7d0 }, // 1780 19 max resources (2000)
|
||||
{ 0x6f6, 0x0 }, // 1782 20 blacksmith color
|
||||
{ 0x6f7, 0x0 }, // 1783 21 blacksmith (show/hide)
|
||||
{ 0x6f8, 0x0 }, // 1784 22 unk, bs?
|
||||
{ 0x6f9, 0x0 }, // 1785 23 unk, bs?
|
||||
{ 0x6fb, 0x0 }, // 1787 24 gold mine (0 - horde contr, 1 - alliance contr)
|
||||
{ 0x6fc, 0x0 }, // 1788 25 gold mine (0 - conflict, 1 - horde)
|
||||
{ 0x6fd, 0x0 }, // 1789 26 gold mine (1 - show/0 - hide)
|
||||
{ 0x6fe, 0x0 }, // 1790 27 gold mine color
|
||||
{ 0x700, 0x0 }, // 1792 28 gold mine color, wtf?, may be LM?
|
||||
{ 0x701, 0x0 }, // 1793 29 lumber mill color (0 - conflict, 1 - horde contr)
|
||||
{ 0x702, 0x0 }, // 1794 30 lumber mill (show/hide)
|
||||
{ 0x703, 0x0 }, // 1795 31 lumber mill color color
|
||||
{ 0x732, 0x1 }, // 1842 32 stables (1 - uncontrolled)
|
||||
{ 0x733, 0x1 }, // 1843 33 gold mine (1 - uncontrolled)
|
||||
{ 0x734, 0x1 }, // 1844 34 lumber mill (1 - uncontrolled)
|
||||
{ 0x735, 0x1 }, // 1845 35 farm (1 - uncontrolled)
|
||||
{ 0x736, 0x1 }, // 1846 36 blacksmith (1 - uncontrolled)
|
||||
{ 0x745, 0x2 }, // 1861 37 unk
|
||||
{ 0x7a3, 0x708 }, // 1955 38 warning limit (1800)
|
||||
{ 0x0, 0x0 }
|
||||
};
|
||||
|
||||
static WorldStatePair EY_world_states[] =
|
||||
{
|
||||
{ 2753, 0 }, // WORLD_STATE_EY_TOWER_COUNT_HORDE
|
||||
{ 2752, 0 }, // WORLD_STATE_EY_TOWER_COUNT_ALLIANCE
|
||||
{ 2733, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_DRAENEI_RUINS_HORDE
|
||||
{ 2732, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_DRAENEI_RUINS_ALLIANCE
|
||||
{ 2731, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_DRAENEI_RUINS_NEUTRAL
|
||||
{ 2730, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_MAGE_TOWER_ALLIANCE
|
||||
{ 2729, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_MAGE_TOWER_HORDE
|
||||
{ 2728, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_MAGE_TOWER_NEUTRAL
|
||||
{ 2727, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_FEL_REAVER_HORDE
|
||||
{ 2726, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_FEL_REAVER_ALLIANCE
|
||||
{ 2725, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_FEL_REAVER_NEUTRAL
|
||||
{ 2724, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_BLOOD_ELF_HORDE
|
||||
{ 2723, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_BLOOD_ELF_ALLIANCE
|
||||
{ 2722, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_BLOOD_ELF_NEUTRAL
|
||||
{ 2757, WORLD_STATE_REMOVE }, // WORLD_STATE_EY_NETHERSTORM_FLAG_READY
|
||||
{ 2770, 1 }, // WORLD_STATE_EY_NETHERSTORM_FLAG_STATE_HORDE
|
||||
{ 2769, 1 }, // WORLD_STATE_EY_NETHERSTORM_FLAG_STATE_ALLIANCE
|
||||
{ 2750, 0 }, // WORLD_STATE_EY_RESOURCES_HORDE
|
||||
{ 2749, 0 }, // WORLD_STATE_EY_RESOURCES_ALLIANCE
|
||||
{ 2565, 0x8e }, // global unk -- TODO: move to global world state
|
||||
{ 3085, 0x17b } // global unk -- TODO: move to global world state
|
||||
};
|
||||
|
||||
static WorldStatePair SI_world_states[] = // Silithus
|
||||
{
|
||||
{ 2313, 0 }, // WORLD_STATE_SI_GATHERED_A
|
||||
{ 2314, 0 }, // WORLD_STATE_SI_GATHERED_H
|
||||
{ 2317, 0 } // WORLD_STATE_SI_SILITHYST_MAX
|
||||
};
|
||||
|
||||
static WorldStatePair EP_world_states[] = // Eastern Plaguelands
|
||||
{
|
||||
{ 2327, 0 }, // WORLD_STATE_EP_TOWER_COUNT_ALLIANCE
|
||||
{ 2328, 0 }, // WORLD_STATE_EP_TOWER_COUNT_HORDE
|
||||
{ 2355, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_CROWNGUARD_NEUTRAL
|
||||
{ 2374, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_CROWNGUARD_CONTEST_ALLIANCE
|
||||
{ 2375, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_CROWNGUARD_CONTEST_HORDE
|
||||
{ 2376, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_CROWNGUARD_PROGRESS_ALLIANCE
|
||||
{ 2377, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_CROWNGUARD_PROGRESS_HORDE
|
||||
{ 2378, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_CROWNGUARD_ALLIANCE
|
||||
{ 2379, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_CROWNGUARD_HORDE
|
||||
{ 2354, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_EASTWALL_ALLIANCE
|
||||
{ 2356, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_EASTWALL_HORDE
|
||||
{ 2357, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_EASTWALL_PROGRESS_ALLIANCE
|
||||
{ 2358, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_EASTWALL_PROGRESS_HORDE
|
||||
{ 2359, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_EASTWALL_CONTEST_ALLIANCE
|
||||
{ 2360, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_EASTWALL_CONTEST_HORDE
|
||||
{ 2361, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_EASTWALL_NEUTRAL
|
||||
{ 2352, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_NORTHPASS_NEUTRAL
|
||||
{ 2362, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_NORTHPASS_CONTEST_ALLIANCE
|
||||
{ 2363, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_NORTHPASS_CONTEST_HORDE
|
||||
{ 2364, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_NORTHPASS_PROGRESS_ALLIANCE
|
||||
{ 2365, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_NORTHPASS_PROGRESS_HORDE
|
||||
{ 2372, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_NORTHPASS_ALLIANCE
|
||||
{ 2373, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_NORTHPASS_HORDE
|
||||
{ 2353, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_PLAGUEWOOD_NEUTRAL
|
||||
{ 2366, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_PLAGUEWOOD_CONTEST_ALLIANCE
|
||||
{ 2367, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_PLAGUEWOOD_CONTEST_HORDE - not in dbc! sent for consistency's sake, and to match field count
|
||||
{ 2368, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_PLAGUEWOOD_PROGRESS_ALLIANCE
|
||||
{ 2369, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_PLAGUEWOOD_PROGRESS_HORDE
|
||||
{ 2370, WORLD_STATE_REMOVE }, // WORLD_STATE_EP_PLAGUEWOOD_ALLIANCE
|
||||
{ 2371, WORLD_STATE_REMOVE } // WORLD_STATE_EP_PLAGUEWOOD_HORDE
|
||||
};
|
||||
|
||||
static WorldStatePair HP_world_states[] = // Hellfire Peninsula
|
||||
{
|
||||
{ 2490, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_TOWER_DISPLAY_A
|
||||
{ 2489, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_TOWER_DISPLAY_H
|
||||
{ 2485, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_BROKEN_HILL_NEUTRAL
|
||||
{ 2484, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_BROKEN_HILL_HORDE
|
||||
{ 2483, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_BROKEN_HILL_ALLIANCE
|
||||
{ 2482, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_OVERLOOK_NEUTRAL
|
||||
{ 2481, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_OVERLOOK_HORDE
|
||||
{ 2480, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_OVERLOOK_ALLIANCE
|
||||
{ 2478, 0 }, // WORLD_STATE_HP_TOWER_COUNT_HORDE
|
||||
{ 2476, 0 }, // WORLD_STATE_HP_TOWER_COUNT_ALLIANCE
|
||||
{ 2472, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_STADIUM_NEUTRAL
|
||||
{ 2471, WORLD_STATE_REMOVE }, // WORLD_STATE_HP_STADIUM_ALLIANCE
|
||||
{ 2470, WORLD_STATE_REMOVE } // WORLD_STATE_HP_STADIUM_HORDE
|
||||
};
|
||||
|
||||
static WorldStatePair TF_world_states[] = // Terokkar Forest
|
||||
{
|
||||
{ 2622, 0 }, // WORLD_STATE_TF_TOWER_COUNT_H
|
||||
{ 2621, 0 }, // WORLD_STATE_TF_TOWER_COUNT_A
|
||||
{ 2620, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_TOWERS_CONTROLLED
|
||||
{ 2695, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_SOUTH_EAST_TOWER_HORDE
|
||||
{ 2694, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_SOUTH_EAST_TOWER_ALLIANCE
|
||||
{ 2693, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_SOUTH_TOWER_NEUTRAL
|
||||
{ 2692, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_SOUTH_TOWER_HORDE
|
||||
{ 2691, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_SOUTH_TOWER_ALLIANCE
|
||||
{ 2690, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_EAST_TOWER_NEUTRAL
|
||||
{ 2689, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_EAST_TOWER_HORDE
|
||||
{ 2688, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_EAST_TOWER_ALLIANCE
|
||||
{ 2686, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_NORTH_TOWER_NEUTRAL
|
||||
{ 2685, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_NORTH_TOWER_HORDE
|
||||
{ 2684, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_NORTH_TOWER_ALLIANCE
|
||||
{ 2683, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_WEST_TOWER_ALLIANCE
|
||||
{ 2682, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_WEST_TOWER_HORDE
|
||||
{ 2681, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_WEST_TOWER_NEUTRAL
|
||||
{ 2512, 0 }, // WORLD_STATE_TF_TIME_MIN_FIRST_DIGIT
|
||||
{ 2510, 0 }, // WORLD_STATE_TF_TIME_MIN_SECOND_DIGIT
|
||||
{ 2509, 0 }, // WORLD_STATE_TF_TIME_HOURS
|
||||
{ 2508, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_LOCKED_NEUTRAL
|
||||
{ 2696, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_SOUTH_EAST_TOWER_NEUTRAL
|
||||
{ 2768, WORLD_STATE_REMOVE }, // WORLD_STATE_TF_LOCKED_HORDE
|
||||
{ 2767, WORLD_STATE_REMOVE } // WORLD_STATE_TF_LOCKED_ALLIANCE
|
||||
};
|
||||
|
||||
static WorldStatePair ZM_world_states[] = // Zangarmarsh
|
||||
{
|
||||
{ 2653, 0x1 }, // WORLD_STATE_ZM_UNK
|
||||
{ 2652, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_EAST_NEUTRAL
|
||||
{ 2651, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_EAST_HORDE
|
||||
{ 2650, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_EAST_ALLIANCE
|
||||
{ 2649, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_GRAVEYARD_HORDE
|
||||
{ 2648, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_GRAVEYARD_ALLIANCE
|
||||
{ 2647, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_GRAVEYARD_NEUTRAL
|
||||
{ 2646, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_WEST_NEUTRAL
|
||||
{ 2645, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_WEST_HORDE
|
||||
{ 2644, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_WEST_ALLIANCE
|
||||
{ 2560, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_EAST_UI_NEUTRAL
|
||||
{ 2559, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_EAST_UI_HORDE
|
||||
{ 2558, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_EAST_UI_ALLIANCE
|
||||
{ 2557, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_WEST_UI_NEUTRAL
|
||||
{ 2556, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_WEST_UI_HORDE
|
||||
{ 2555, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_BEACON_WEST_UI_ALLIANCE
|
||||
{ 2658, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_FLAG_READY_HORDE
|
||||
{ 2657, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_FLAG_NOT_READY_HORDE
|
||||
{ 2656, WORLD_STATE_REMOVE }, // WORLD_STATE_ZM_FLAG_NOT_READY_ALLIANCE
|
||||
{ 2655, WORLD_STATE_REMOVE } // WORLD_STATE_ZM_FLAG_READY_ALLIANCE
|
||||
};
|
||||
|
||||
static WorldStatePair NA_world_states[] =
|
||||
{
|
||||
{ 2503, 0 }, // WORLD_STATE_NA_GUARDS_HORDE
|
||||
{ 2502, 0 }, // WORLD_STATE_NA_GUARDS_ALLIANCE
|
||||
{ 2493, 0 }, // WORLD_STATE_NA_GUARDS_MAX
|
||||
{ 2491, 0 }, // WORLD_STATE_NA_GUARDS_LEFT
|
||||
{ 2762, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_NORTH_NEUTRAL_H
|
||||
{ 2662, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_NORTH_NEUTRAL_A
|
||||
{ 2663, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_NORTH_H
|
||||
{ 2664, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_NORTH_A
|
||||
{ 2760, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_SOUTH_NEUTRAL_H
|
||||
{ 2670, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_SOUTH_NEUTRAL_A
|
||||
{ 2668, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_SOUTH_H
|
||||
{ 2669, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_SOUTH_A
|
||||
{ 2761, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_WEST_NEUTRAL_H
|
||||
{ 2667, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_WEST_NEUTRAL_A
|
||||
{ 2665, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_WEST_H
|
||||
{ 2666, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_WEST_A
|
||||
{ 2763, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_EAST_NEUTRAL_H
|
||||
{ 2659, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_EAST_NEUTRAL_A
|
||||
{ 2660, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_EAST_H
|
||||
{ 2661, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_WYVERN_EAST_A
|
||||
{ 2671, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_HALAA_NEUTRAL
|
||||
{ 2676, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_HALAA_NEUTRAL_A
|
||||
{ 2677, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_HALAA_NEUTRAL_H
|
||||
{ 2672, WORLD_STATE_REMOVE }, // WORLD_STATE_NA_HALAA_HORDE
|
||||
{ 2673, WORLD_STATE_REMOVE } // WORLD_STATE_NA_HALAA_ALLIANCE
|
||||
};
|
||||
|
||||
void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
|
||||
{
|
||||
// data depends on zoneid/mapid...
|
||||
|
|
@ -8787,136 +8491,53 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
|
|||
size_t count_pos = data.wpos();
|
||||
data << uint16(0); // count of uint64 blocks, placeholder
|
||||
|
||||
// common fields
|
||||
FillInitialWorldState(data, count, 0x8d8, 0x0); // 2264 1
|
||||
FillInitialWorldState(data, count, 0x8d7, 0x0); // 2263 2
|
||||
FillInitialWorldState(data, count, 0x8d6, 0x0); // 2262 3
|
||||
FillInitialWorldState(data, count, 0x8d5, 0x0); // 2261 4
|
||||
FillInitialWorldState(data, count, 0x8d4, 0x0); // 2260 5
|
||||
FillInitialWorldState(data, count, 0x8d3, 0x0); // 2259 6
|
||||
// 3191 7 Current arena season
|
||||
// Current arena season
|
||||
FillInitialWorldState(data, count, 0xC77, sWorld.getConfig(CONFIG_UINT32_ARENA_SEASON_ID));
|
||||
// 3901 8 Previous arena season
|
||||
// Previous arena season
|
||||
FillInitialWorldState(data, count, 0xF3D, sWorld.getConfig(CONFIG_UINT32_ARENA_SEASON_PREVIOUS_ID));
|
||||
FillInitialWorldState(data, count, 0xED9, 1); // 3801 9 0 - Battle for Wintergrasp in progress, 1 - otherwise
|
||||
// 4354 10 Time when next Battle for Wintergrasp starts
|
||||
FillInitialWorldState(data, count, 0x1102, uint32(time(NULL) + 9000));
|
||||
|
||||
if (mapid == 530) // Outland
|
||||
{
|
||||
FillInitialWorldState(data, count, 0x9bf, 0x0); // 2495
|
||||
FillInitialWorldState(data, count, 0x9bd, 0xF); // 2493
|
||||
FillInitialWorldState(data, count, 0x9bb, 0xF); // 2491
|
||||
}
|
||||
// 0 - Battle for Wintergrasp in progress, 1 - otherwise
|
||||
FillInitialWorldState(data, count, 0xED9, 1);
|
||||
// Time when next Battle for Wintergrasp starts
|
||||
FillInitialWorldState(data, count, 0x1102, uint32(time(nullptr) + 9000));
|
||||
|
||||
switch (zoneid)
|
||||
{
|
||||
case 1: // Dun Morogh
|
||||
case 11: // Wetlands
|
||||
case 12: // Elwynn Forest
|
||||
case 38: // Loch Modan
|
||||
case 40: // Westfall
|
||||
case 51: // Searing Gorge
|
||||
case 1519: // Stormwind City
|
||||
case 1537: // Ironforge
|
||||
case 2257: // Deeprun Tram
|
||||
case 3703: // Shattrath City
|
||||
break;
|
||||
case 139: // Eastern Plaguelands
|
||||
if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(zoneid))
|
||||
outdoorPvP->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, EP_world_states);
|
||||
break;
|
||||
case 1377: // Silithus
|
||||
case 3483: // Hellfire Peninsula
|
||||
case 3518: // Nagrand
|
||||
case 3519: // Terokkar Forest
|
||||
case 3521: // Zangarmarsh
|
||||
if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(zoneid))
|
||||
outdoorPvP->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, SI_world_states);
|
||||
break;
|
||||
case 2597: // AV
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_AV)
|
||||
bg->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, AV_world_states);
|
||||
break;
|
||||
case 3277: // WS
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_WS)
|
||||
bg->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, WS_world_states);
|
||||
break;
|
||||
case 3358: // AB
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_AB)
|
||||
bg->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, AB_world_states);
|
||||
break;
|
||||
case 3820: // EY
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_EY)
|
||||
bg->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, EY_world_states);
|
||||
break;
|
||||
case 3483: // Hellfire Peninsula
|
||||
if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(zoneid))
|
||||
outdoorPvP->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, HP_world_states);
|
||||
break;
|
||||
case 3518: // Nagrand
|
||||
if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(zoneid))
|
||||
outdoorPvP->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, NA_world_states);
|
||||
break;
|
||||
case 3519: // Terokkar Forest
|
||||
if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(zoneid))
|
||||
outdoorPvP->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, TF_world_states);
|
||||
break;
|
||||
case 3521: // Zangarmarsh
|
||||
if (OutdoorPvP* outdoorPvP = sOutdoorPvPMgr.GetScript(zoneid))
|
||||
outdoorPvP->FillInitialWorldStates(data, count);
|
||||
else
|
||||
FillInitialWorldState(data, count, ZM_world_states);
|
||||
break;
|
||||
case 3698: // Nagrand Arena
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_NA)
|
||||
bg->FillInitialWorldStates(data, count);
|
||||
else
|
||||
{
|
||||
FillInitialWorldState(data, count, 0xa0f, 0x0); // 2575 7
|
||||
FillInitialWorldState(data, count, 0xa10, 0x0); // 2576 8
|
||||
FillInitialWorldState(data, count, 0xa11, 0x0); // 2577 9 show
|
||||
}
|
||||
break;
|
||||
case 3702: // Blade's Edge Arena
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_BE)
|
||||
bg->FillInitialWorldStates(data, count);
|
||||
else
|
||||
{
|
||||
FillInitialWorldState(data, count, 0x9f0, 0x0); // 2544 7 gold
|
||||
FillInitialWorldState(data, count, 0x9f1, 0x0); // 2545 8 green
|
||||
FillInitialWorldState(data, count, 0x9f3, 0x0); // 2547 9 show
|
||||
}
|
||||
break;
|
||||
case 3968: // Ruins of Lordaeron
|
||||
if (bg && bg->GetTypeID() == BATTLEGROUND_RL)
|
||||
bg->FillInitialWorldStates(data, count);
|
||||
else
|
||||
{
|
||||
FillInitialWorldState(data, count, 0xbb8, 0x0); // 3000 7 gold
|
||||
FillInitialWorldState(data, count, 0xbb9, 0x0); // 3001 8 green
|
||||
FillInitialWorldState(data, count, 0xbba, 0x0); // 3002 9 show
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FillInitialWorldState(data, count, 0x914, 0x0); // 2324 7
|
||||
FillInitialWorldState(data, count, 0x913, 0x0); // 2323 8
|
||||
FillInitialWorldState(data, count, 0x912, 0x0); // 2322 9
|
||||
FillInitialWorldState(data, count, 0x915, 0x0); // 2325 10
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -13093,9 +12714,9 @@ void Player::PrepareGossipMenu(WorldObject* pSource, uint32 menuId)
|
|||
{
|
||||
Creature* pCreature = (Creature*)pSource;
|
||||
|
||||
uint32 npcflags = pCreature->GetUInt32Value(UNIT_NPC_FLAGS);
|
||||
uint32 NpcFlagss = pCreature->GetUInt32Value(UNIT_NPC_FLAGS);
|
||||
|
||||
if (!(itr->second.npc_option_npcflag & npcflags))
|
||||
if (!(itr->second.npc_option_NpcFlags & NpcFlagss))
|
||||
continue;
|
||||
|
||||
switch (itr->second.option_id)
|
||||
|
|
@ -13126,7 +12747,7 @@ void Player::PrepareGossipMenu(WorldObject* pSource, uint32 menuId)
|
|||
case GOSSIP_OPTION_TRAINER:
|
||||
// pet trainers not have spells in fact now
|
||||
/* FIXME: gossip menu with single unlearn pet talents option not show by some reason
|
||||
if (pCreature->GetCreatureInfo()->trainer_type == TRAINER_TYPE_PETS)
|
||||
if (pCreature->GetCreatureInfo()->TrainerType == TRAINER_TYPE_PETS)
|
||||
hasMenuItem = false;
|
||||
else */
|
||||
if (!pCreature->IsTrainerOf(this, false))
|
||||
|
|
@ -13137,7 +12758,7 @@ void Player::PrepareGossipMenu(WorldObject* pSource, uint32 menuId)
|
|||
hasMenuItem = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_UNLEARNPETSKILLS:
|
||||
if (pCreature->GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS || pCreature->GetCreatureInfo()->trainer_class != CLASS_HUNTER)
|
||||
if (pCreature->GetCreatureInfo()->TrainerType != TRAINER_TYPE_PETS || pCreature->GetCreatureInfo()->TrainerClass != CLASS_HUNTER)
|
||||
hasMenuItem = false;
|
||||
else if (Pet* pet = GetPet())
|
||||
{
|
||||
|
|
@ -18660,39 +18281,24 @@ void Player::RemovePet(PetSaveMode mode)
|
|||
pet->Unsummon(mode, this);
|
||||
}
|
||||
|
||||
void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix) const
|
||||
{
|
||||
*data << uint8(msgtype);
|
||||
*data << uint32(language);
|
||||
*data << GetObjectGuid();
|
||||
*data << uint32(0); // constant unknown time 4.3.4
|
||||
if (addonPrefix)
|
||||
*data << addonPrefix;
|
||||
else
|
||||
*data << GetObjectGuid();
|
||||
*data << uint32(text.length() + 1);
|
||||
*data << text;
|
||||
*data << uint8(GetChatTag());
|
||||
}
|
||||
|
||||
void Player::Say(const std::string& text, const uint32 language)
|
||||
{
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildPlayerChat(&data, CHAT_MSG_SAY, text, language);
|
||||
WorldPacket data;
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_SAY, text.c_str(), Language(language), GetChatTag(), GetObjectGuid(), GetName());
|
||||
SendMessageToSetInRange(&data, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY), true);
|
||||
}
|
||||
|
||||
void Player::Yell(const std::string& text, const uint32 language)
|
||||
{
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildPlayerChat(&data, CHAT_MSG_YELL, text, language);
|
||||
WorldPacket data;
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_YELL, text.c_str(), Language(language), GetChatTag(), GetObjectGuid(), GetName());
|
||||
SendMessageToSetInRange(&data, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL), true);
|
||||
}
|
||||
|
||||
void Player::TextEmote(const std::string& text)
|
||||
{
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildPlayerChat(&data, CHAT_MSG_EMOTE, text, LANG_UNIVERSAL);
|
||||
WorldPacket data;
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, text.c_str(), LANG_UNIVERSAL, GetChatTag(), GetObjectGuid(), GetName());
|
||||
SendMessageToSetInRange(&data, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE), true, !sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT));
|
||||
}
|
||||
|
||||
|
|
@ -18700,12 +18306,12 @@ void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiv
|
|||
{
|
||||
Player* rPlayer = sObjectMgr.GetPlayer(receiver);
|
||||
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildPlayerChat(&data, CHAT_MSG_WHISPER, text, language);
|
||||
WorldPacket data;
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, text.c_str(), Language(language), GetChatTag(), GetObjectGuid(), GetName());
|
||||
rPlayer->GetSession()->SendPacket(&data);
|
||||
|
||||
data.Initialize(SMSG_MESSAGECHAT, 200);
|
||||
rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, text, language);
|
||||
data.clear();
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER_INFORM, text.c_str(), Language(language), CHAT_TAG_NONE, rPlayer->GetObjectGuid());
|
||||
GetSession()->SendPacket(&data);
|
||||
|
||||
if (!isAcceptWhispers())
|
||||
|
|
@ -18721,17 +18327,6 @@ void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiv
|
|||
ChatHandler(this).PSendSysMessage(LANG_PLAYER_DND, rPlayer->GetName(), rPlayer->autoReplyMsg.c_str());
|
||||
}
|
||||
|
||||
void Player::WhisperAddon(const std::string& text, const std::string& prefix, ObjectGuid receiver)
|
||||
{
|
||||
Player* rPlayer = sObjectMgr.GetPlayer(receiver);
|
||||
|
||||
std::string _text(text);
|
||||
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
BuildPlayerChat(&data, CHAT_MSG_WHISPER, _text, LANG_UNIVERSAL, prefix.c_str());
|
||||
rPlayer->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void Player::PetSpellInitialize()
|
||||
{
|
||||
Pet* pet = GetPet();
|
||||
|
|
@ -18745,7 +18340,7 @@ void Player::PetSpellInitialize()
|
|||
|
||||
WorldPacket data(SMSG_PET_SPELLS, 8 + 2 + 4 + 4 + 4 * MAX_UNIT_ACTION_BAR_INDEX + 1 + 1);
|
||||
data << pet->GetObjectGuid();
|
||||
data << uint16(pet->GetCreatureInfo()->family); // creature family (required for pet talents)
|
||||
data << uint16(pet->GetCreatureInfo()->Family); // creature family (required for pet talents)
|
||||
data << uint32(0);
|
||||
data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0);
|
||||
|
||||
|
|
@ -18862,7 +18457,7 @@ void Player::CharmSpellInitialize()
|
|||
{
|
||||
CreatureInfo const* cinfo = ((Creature*)charm)->GetCreatureInfo();
|
||||
|
||||
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK)
|
||||
if (cinfo && cinfo->CreatureType == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK)
|
||||
{
|
||||
for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
|
||||
{
|
||||
|
|
@ -21486,7 +21081,7 @@ bool Player::isHonorOrXPTarget(Unit* pVictim) const
|
|||
{
|
||||
if (((Creature*)pVictim)->IsTotem() ||
|
||||
((Creature*)pVictim)->IsPet() ||
|
||||
((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
|
||||
((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_XP_AT_KILL)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -22808,7 +22403,7 @@ void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRa
|
|||
if (!ci)
|
||||
return;
|
||||
|
||||
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
|
||||
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->Family);
|
||||
|
||||
if (!pet_family)
|
||||
return;
|
||||
|
|
@ -23033,7 +22628,7 @@ void Player::BuildPetTalentsInfoData(WorldPacket* data)
|
|||
if (!ci)
|
||||
return;
|
||||
|
||||
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
|
||||
CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->Family);
|
||||
if (!pet_family || pet_family->petTalentType < 0)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "ReputationMgr.h"
|
||||
#include "BattleGround.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "Chat.h"
|
||||
|
||||
#include<string>
|
||||
#include<vector>
|
||||
|
|
@ -1111,20 +1112,15 @@ class Player : public Unit
|
|||
void SendInitialPacketsAfterAddToMap();
|
||||
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
|
||||
|
||||
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
|
||||
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 NpcFlagsmask);
|
||||
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const;
|
||||
|
||||
void ToggleAFK();
|
||||
void ToggleDND();
|
||||
bool isAFK() const
|
||||
{
|
||||
return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK);
|
||||
}
|
||||
bool isDND() const
|
||||
{
|
||||
return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_DND);
|
||||
}
|
||||
uint8 GetChatTag() const;
|
||||
bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); }
|
||||
bool isDND() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_DND); }
|
||||
ChatTagFlags GetChatTag() const;
|
||||
|
||||
std::string autoReplyMsg;
|
||||
|
||||
uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, uint32 newskintone);
|
||||
|
|
@ -1219,8 +1215,6 @@ class Player : public Unit
|
|||
void Yell(const std::string& text, const uint32 language);
|
||||
void TextEmote(const std::string& text);
|
||||
void Whisper(const std::string& text, const uint32 language, ObjectGuid receiver);
|
||||
void WhisperAddon(const std::string& text, const std::string& prefix, ObjectGuid receiver);
|
||||
void BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix = NULL) const;
|
||||
|
||||
/*********************************************************/
|
||||
/*** STORAGE SYSTEM ***/
|
||||
|
|
|
|||
|
|
@ -757,10 +757,16 @@ bool IsPositiveEffect(SpellEntry const* spellproto, SpellEffectIndex effIndex)
|
|||
case 18153: // Kodo Kombobulator
|
||||
case 32312: // Move 1
|
||||
case 37388: // Move 2
|
||||
case 45863: // Cosmetic - Incinerate to Random Target
|
||||
case 49634: // Sergeant's Flare
|
||||
case 54530: // Opening
|
||||
case 56099: // Throw Ice
|
||||
case 56099: // Throw Ice
|
||||
case 58533: // Return to Stormwind
|
||||
case 58552: // Return to Orgrimmar
|
||||
case 62105: // To'kini's Blowgun
|
||||
case 63745: // Sara's Blessing
|
||||
case 63747: // Sara's Fervor
|
||||
case 64402: // Rocket Strike
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -2220,6 +2226,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
|
|||
if ((spellInfo_1->Id == 62169 && spellInfo_2->Id == 64417) ||
|
||||
(spellInfo_2->Id == 62169 && spellInfo_1->Id == 64417))
|
||||
return false;
|
||||
|
||||
// Auto Grow and Healthy Spore Visual
|
||||
if ((spellInfo_1->Id == 62559 && spellInfo_2->Id == 62538) ||
|
||||
(spellInfo_2->Id == 62559 && spellInfo_1->Id == 62538))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_MAGE:
|
||||
|
|
@ -3523,9 +3534,9 @@ void SpellMgr::LoadSpellScriptTarget()
|
|||
}
|
||||
if (const CreatureInfo* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(itr->targetEntry))
|
||||
{
|
||||
if (itr->spellId == 30427 && !cInfo->SkinLootId)
|
||||
if (itr->spellId == 30427 && !cInfo->SkinningLootId)
|
||||
{
|
||||
sLog.outErrorDb("Table `spell_script_target` has creature %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!", cInfo->Entry);
|
||||
sLog.outErrorDb("Table `spell_script_target` has creature %u as a target of spellid 30427, but this creature has no skinLootid. Gas extraction will not work!", cInfo->Entry);
|
||||
sSpellScriptTargetStorage.EraseEntry(itr->spellId);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -3710,7 +3721,7 @@ bool SpellMgr::LoadPetDefaultSpells_helper(CreatureInfo const* cInfo, PetDefault
|
|||
return false;
|
||||
|
||||
// remove duplicates with levelupSpells if any
|
||||
if (PetLevelupSpellSet const* levelupSpells = cInfo->family ? GetPetLevelupSpellList(cInfo->family) : NULL)
|
||||
if (PetLevelupSpellSet const* levelupSpells = cInfo->Family ? GetPetLevelupSpellList(cInfo->Family) : NULL)
|
||||
{
|
||||
for (int j = 0; j < MAX_CREATURE_SPELL_DATA_SLOT; ++j)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -883,12 +883,12 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType)
|
|||
UnitMods unitMod = (attType == BASE_ATTACK ? UNIT_MOD_DAMAGE_MAINHAND : UNIT_MOD_DAMAGE_OFFHAND);
|
||||
|
||||
/* difference in AP between current attack power and base value from DB */
|
||||
float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureInfo()->attackpower;
|
||||
float att_pwr_change = GetTotalAttackPowerValue(attType) - GetCreatureInfo()->MeleeAttackPower;
|
||||
float base_value = GetModifierValue(unitMod, BASE_VALUE) + (att_pwr_change * GetAPMultiplier(attType, false) / 14.0f);
|
||||
float base_pct = GetModifierValue(unitMod, BASE_PCT);
|
||||
float total_value = GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
float total_pct = GetModifierValue(unitMod, TOTAL_PCT);
|
||||
float dmg_multiplier = GetCreatureInfo()->dmg_multiplier;
|
||||
float dmg_multiplier = GetCreatureInfo()->DamageMultiplier;
|
||||
|
||||
float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE);
|
||||
float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE);
|
||||
|
|
|
|||
|
|
@ -902,48 +902,11 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
return 0;
|
||||
}
|
||||
|
||||
// no xp,health if type 8 /critters/
|
||||
if (pVictim->GetTypeId() == TYPEID_UNIT && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
|
||||
{
|
||||
// TODO: fix this part
|
||||
// Critter may not die of damage taken, instead expect it to run away (no fighting back)
|
||||
// If (this) is TYPEID_PLAYER, (this) will enter combat w/victim, but after some time, automatically leave combat.
|
||||
// It is unclear how it should work for other cases.
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "DealDamage critter, critter dies");
|
||||
|
||||
((Creature*)pVictim)->SetLootRecipient(this);
|
||||
|
||||
JustKilledCreature((Creature*)pVictim, NULL);
|
||||
pVictim->SetHealth(0);
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "DealDamageStart");
|
||||
|
||||
uint32 health = pVictim->GetHealth();
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "deal dmg:%d to health:%d ", damage, health);
|
||||
|
||||
// duel ends when player has 1 or less hp
|
||||
bool duel_hasEnded = false;
|
||||
if (pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->duel && damage >= (health - 1))
|
||||
{
|
||||
// prevent kill only if killed in duel and killed by opponent or opponent controlled creature
|
||||
if (((Player*)pVictim)->duel->opponent == this || ((Player*)pVictim)->duel->opponent->GetObjectGuid() == GetOwnerGuid())
|
||||
damage = health - 1;
|
||||
|
||||
duel_hasEnded = true;
|
||||
}
|
||||
// Get in CombatState
|
||||
if (pVictim != this && damagetype != DOT)
|
||||
{
|
||||
SetInCombatWith(pVictim);
|
||||
pVictim->SetInCombatWith(this);
|
||||
|
||||
if (Player* attackedPlayer = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
SetContestedPvP(attackedPlayer);
|
||||
}
|
||||
|
||||
// Rage from Damage made (only from direct weapon damage)
|
||||
if (cleanDamage && damagetype == DIRECT_DAMAGE && this != pVictim && GetTypeId() == TYPEID_PLAYER && (GetPowerType() == POWER_RAGE))
|
||||
{
|
||||
|
|
@ -978,6 +941,70 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
}
|
||||
}
|
||||
|
||||
// no xp,health if type 8 /critters/
|
||||
if (pVictim->GetTypeId() == TYPEID_UNIT && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
|
||||
{
|
||||
// TODO: fix this part
|
||||
// Critter may not die of damage taken, instead expect it to run away (no fighting back)
|
||||
// If (this) is TYPEID_PLAYER, (this) will enter combat w/victim, but after some time, automatically leave combat.
|
||||
// It is unclear how it should work for other cases.
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_DAMAGE, "DealDamage critter, critter dies");
|
||||
|
||||
((Creature*)pVictim)->SetLootRecipient(this);
|
||||
|
||||
JustKilledCreature((Creature*)pVictim, nullptr);
|
||||
pVictim->SetHealth(0);
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
// share damage by auras
|
||||
AuraList const& vShareDamageAuras = pVictim->GetAurasByType(SPELL_AURA_SHARE_DAMAGE_PCT);
|
||||
for (AuraList::const_iterator itr = vShareDamageAuras.begin(); itr != vShareDamageAuras.end(); ++itr)
|
||||
{
|
||||
if (!spellProto)
|
||||
break;
|
||||
|
||||
SpellEffectEntry const* spellEffect = spellProto->GetSpellEffect(EFFECT_INDEX_0);
|
||||
|
||||
// if damage is done by another shared aura, then skip to avoid circular reference (aura 300 is only applied on effect_idx_0
|
||||
if (spellEffect && spellEffect->Effect == SPELL_EFFECT_APPLY_AURA &&
|
||||
spellEffect->EffectApplyAuraName == SPELL_AURA_SHARE_DAMAGE_PCT)
|
||||
break;
|
||||
|
||||
if (Unit* shareTarget = (*itr)->GetCaster())
|
||||
{
|
||||
if (shareTarget != pVictim && ((*itr)->GetMiscValue() & damageSchoolMask))
|
||||
{
|
||||
SpellEntry const* shareSpell = (*itr)->GetSpellProto();
|
||||
uint32 shareDamage = uint32(damage*(*itr)->GetModifier()->m_amount / 100.0f);
|
||||
DealDamageMods(shareTarget, shareDamage, nullptr);
|
||||
DealDamage(shareTarget, shareDamage, 0, damagetype, GetSpellSchoolMask(shareSpell), shareSpell, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// duel ends when player has 1 or less hp
|
||||
bool duel_hasEnded = false;
|
||||
if (pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->duel && damage >= (health - 1))
|
||||
{
|
||||
// prevent kill only if killed in duel and killed by opponent or opponent controlled creature
|
||||
if (((Player*)pVictim)->duel->opponent == this || ((Player*)pVictim)->duel->opponent->GetObjectGuid() == GetOwnerGuid())
|
||||
damage = health - 1;
|
||||
|
||||
duel_hasEnded = true;
|
||||
}
|
||||
|
||||
// Get in CombatState
|
||||
if (pVictim != this && damagetype != DOT)
|
||||
{
|
||||
SetInCombatWith(pVictim);
|
||||
pVictim->SetInCombatWith(this);
|
||||
|
||||
if (Player* attackedPlayer = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
SetContestedPvP(attackedPlayer);
|
||||
}
|
||||
|
||||
if (GetTypeId() == TYPEID_PLAYER && this != pVictim)
|
||||
{
|
||||
Player* killer = ((Player*)this);
|
||||
|
|
@ -1208,11 +1235,6 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
pVictim->AttackedBy(this);
|
||||
}
|
||||
|
||||
if (damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE)
|
||||
{
|
||||
if (!spellProto || !(spellProto->GetAuraInterruptFlags() & AURA_INTERRUPT_FLAG_DIRECT_DAMAGE))
|
||||
pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE);
|
||||
}
|
||||
if (pVictim->GetTypeId() != TYPEID_PLAYER)
|
||||
{
|
||||
float threat = damage * sSpellMgr.GetSpellThreatMultiplier(spellProto);
|
||||
|
|
@ -1245,21 +1267,6 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Store auras by interrupt flag to speed this up.
|
||||
SpellAuraHolderMap& vAuras = pVictim->GetSpellAuraHolderMap();
|
||||
for (SpellAuraHolderMap::const_iterator i = vAuras.begin(), next; i != vAuras.end(); i = next)
|
||||
{
|
||||
const SpellEntry* se = i->second->GetSpellProto();
|
||||
next = i; ++next;
|
||||
if (spellProto && spellProto->Id == se->Id) // Not drop auras added by self
|
||||
continue;
|
||||
if (!se->GetProcFlags() && (se->GetAuraInterruptFlags() & AURA_INTERRUPT_FLAG_DAMAGE))
|
||||
{
|
||||
pVictim->RemoveAurasDueToSpell(i->second->GetId());
|
||||
next = vAuras.begin();
|
||||
}
|
||||
}
|
||||
|
||||
if (damagetype != NODAMAGE && damage && pVictim->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (damagetype != DOT)
|
||||
|
|
@ -1426,7 +1433,7 @@ void Unit::JustKilledCreature(Creature* victim, Player* responsiblePlayer)
|
|||
{
|
||||
if (m->IsRaidOrHeroicDungeon())
|
||||
{
|
||||
if (victim->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
|
||||
if (victim->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_INSTANCE_BIND)
|
||||
{ ((DungeonMap*)m)->PermBindAllPlayers(creditedPlayer); }
|
||||
}
|
||||
else
|
||||
|
|
@ -1779,7 +1786,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
|
|||
}
|
||||
|
||||
// TODO for melee need create structure as in
|
||||
void Unit::CalculateMeleeDamage(Unit* pVictim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType)
|
||||
void Unit::CalculateMeleeDamage(Unit* pVictim, CalcDamageInfo* damageInfo, WeaponAttackType attackType /*= BASE_ATTACK*/)
|
||||
{
|
||||
damageInfo->attacker = this;
|
||||
damageInfo->target = pVictim;
|
||||
|
|
@ -1836,7 +1843,7 @@ void Unit::CalculateMeleeDamage(Unit* pVictim, uint32 damage, CalcDamageInfo* da
|
|||
damageInfo->cleanDamage = 0;
|
||||
return;
|
||||
}
|
||||
damage += CalculateDamage(damageInfo->attackType, false);
|
||||
uint32 damage = CalculateDamage(damageInfo->attackType, false);
|
||||
// Add melee damage bonus
|
||||
damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType);
|
||||
damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType);
|
||||
|
|
@ -2909,7 +2916,7 @@ void Unit::AttackerStateUpdate(Unit* pVictim, WeaponAttackType attType, bool ext
|
|||
pVictim = SelectMagnetTarget(pVictim);
|
||||
|
||||
CalcDamageInfo damageInfo;
|
||||
CalculateMeleeDamage(pVictim, 0, &damageInfo, attType);
|
||||
CalculateMeleeDamage(pVictim, &damageInfo, attType);
|
||||
// Send log damage message to client
|
||||
DealDamageMods(pVictim, damageInfo.damage, &damageInfo.absorb);
|
||||
SendAttackStateUpdate(&damageInfo);
|
||||
|
|
@ -3028,7 +3035,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* pVictim, WeaponAttackT
|
|||
else
|
||||
parry_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
|
||||
|
||||
if (parry_chance > 0 && (pVictim->GetTypeId() == TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NO_PARRY)))
|
||||
if (parry_chance > 0 && (pVictim->GetTypeId() == TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_PARRY)))
|
||||
{
|
||||
parry_chance -= skillBonus;
|
||||
|
||||
|
|
@ -3066,7 +3073,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* pVictim, WeaponAttackT
|
|||
// check if attack comes from behind, nobody can parry or block if attacker is behind
|
||||
if (!from_behind)
|
||||
{
|
||||
if (pVictim->GetTypeId() == TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NO_BLOCK))
|
||||
if (pVictim->GetTypeId() == TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_BLOCK))
|
||||
{
|
||||
tmp = block_chance;
|
||||
if ((tmp > 0) // check if unit _can_ block
|
||||
|
|
@ -3092,7 +3099,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* pVictim, WeaponAttackT
|
|||
if (GetLevelForTarget(pVictim) >= pVictim->GetLevelForTarget(this) + 4 &&
|
||||
// can be from by creature (if can) or from controlled player that considered as creature
|
||||
((GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->IsPet() &&
|
||||
!(((Creature*)this)->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NO_CRUSH)) ||
|
||||
!(((Creature*)this)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_CRUSH)) ||
|
||||
GetTypeId() == TYPEID_PLAYER && GetCharmerOrOwnerGuid()))
|
||||
{
|
||||
// when their weapon skill is 15 or more above victim's defense skill
|
||||
|
|
@ -3226,7 +3233,7 @@ bool Unit::IsSpellBlocked(Unit* pCaster, SpellEntry const* spellEntry, WeaponAtt
|
|||
// Check creatures ExtraFlags for disable block
|
||||
if (GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (((Creature*)this)->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NO_BLOCK)
|
||||
if (((Creature*)this)->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_BLOCK)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -3363,7 +3370,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* pVictim, SpellEntry const* spell)
|
|||
if (pVictim->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
uint32 flagEx = ((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags;
|
||||
if (flagEx & CREATURE_FLAG_EXTRA_NO_PARRY)
|
||||
if (flagEx & CREATURE_EXTRA_FLAG_NO_PARRY)
|
||||
canParry = false;
|
||||
}
|
||||
// Ignore combat result aura
|
||||
|
|
@ -6225,6 +6232,26 @@ bool Unit::isAttackingPlayer() const
|
|||
return CheckAllControlledUnits(IsAttackingPlayerHelper(), CONTROLLED_PET | CONTROLLED_TOTEMS | CONTROLLED_GUARDIANS | CONTROLLED_CHARM);
|
||||
}
|
||||
|
||||
bool Unit::CanAttackByItself() const
|
||||
{
|
||||
if (!IsVehicle())
|
||||
return true;
|
||||
|
||||
for (uint8 i = 0; i < MAX_VEHICLE_SEAT; ++i)
|
||||
{
|
||||
if (uint32 seatId = m_vehicleInfo->GetVehicleEntry()->m_seatID[i])
|
||||
{
|
||||
if (VehicleSeatEntry const* seatEntry = sVehicleSeatStore.LookupEntry(seatId))
|
||||
{
|
||||
if (seatEntry->m_flags & SEAT_FLAG_CAN_CONTROL)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Unit::RemoveAllAttackers()
|
||||
{
|
||||
while (!m_attackers.empty())
|
||||
|
|
@ -8431,7 +8458,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
|
|||
{ pCreature->AI()->EnterCombat(enemy); }
|
||||
|
||||
// Some bosses are set into combat with zone
|
||||
if (GetMap()->IsDungeon() && (pCreature->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_AGGRO_ZONE) && enemy && enemy->IsControlledByPlayer())
|
||||
if (GetMap()->IsDungeon() && (pCreature->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_AGGRO_ZONE) && enemy && enemy->IsControlledByPlayer())
|
||||
{ pCreature->SetInCombatWithZone(); }
|
||||
|
||||
if (InstanceData* mapInstance = GetInstanceData())
|
||||
|
|
@ -8466,7 +8493,7 @@ void Unit::ClearInCombat()
|
|||
if (GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
Creature* cThis = static_cast<Creature*>(this);
|
||||
if (cThis->GetCreatureInfo()->unit_flags & UNIT_FLAG_OOC_NOT_ATTACKABLE && !(cThis->GetTemporaryFactionFlags() & TEMPFACTION_TOGGLE_OOC_NOT_ATTACK))
|
||||
if (cThis->GetCreatureInfo()->UnitFlags & UNIT_FLAG_OOC_NOT_ATTACKABLE && !(cThis->GetTemporaryFactionFlags() & TEMPFACTION_TOGGLE_OOC_NOT_ATTACK))
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
|
||||
|
||||
clearUnitState(UNIT_STAT_ATTACK_PLAYER);
|
||||
|
|
@ -8968,10 +8995,10 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced, float ratio, bool ignore
|
|||
switch (mtype)
|
||||
{
|
||||
case MOVE_RUN:
|
||||
speed *= ((Creature*)this)->GetCreatureInfo()->speed_run;
|
||||
speed *= ((Creature*)this)->GetCreatureInfo()->SpeedRun;
|
||||
break;
|
||||
case MOVE_WALK:
|
||||
speed *= ((Creature*)this)->GetCreatureInfo()->speed_walk;
|
||||
speed *= ((Creature*)this)->GetCreatureInfo()->SpeedWalk;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -9900,7 +9927,7 @@ uint32 Unit::GetCreatureType() const
|
|||
return CREATURE_TYPE_HUMANOID;
|
||||
}
|
||||
else
|
||||
return ((Creature*)this)->GetCreatureInfo()->type;
|
||||
return ((Creature*)this)->GetCreatureInfo()->CreatureType;
|
||||
}
|
||||
|
||||
/*#######################################
|
||||
|
|
@ -10816,76 +10843,91 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* pTarget, uint32 procFlag,
|
|||
if (itr->second->IsDeleted())
|
||||
continue;
|
||||
|
||||
SpellProcEventEntry const* spellProcEvent = NULL;
|
||||
SpellProcEventEntry const* spellProcEvent = nullptr;
|
||||
// check if that aura is triggered by proc event (then it will be managed by proc handler)
|
||||
if (!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, spellProcEvent))
|
||||
{
|
||||
// spell seem not managed by proc system, although some case need to be handled
|
||||
|
||||
// only process damage case on victim
|
||||
if (!isVictim || !(procFlag & PROC_FLAG_TAKEN_ANY_DAMAGE))
|
||||
continue;
|
||||
|
||||
const SpellEntry* se = itr->second->GetSpellProto();
|
||||
|
||||
// check if the aura is interruptible by damage and if its not just added by this spell (spell who is responsible for this damage is procSpell)
|
||||
if (se->GetAuraInterruptFlags() & AURA_INTERRUPT_FLAG_DAMAGE && (!procSpell || procSpell->Id != se->Id))
|
||||
{
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "ProcDamageAndSpell: Added Spell %u to 'remove aura due to spell' list! Reason: Damage received.", se->Id);
|
||||
removedSpells.push_back(se->Id);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
itr->second->SetInUse(true); // prevent holder deletion
|
||||
procTriggered.push_back(ProcTriggeredData(spellProcEvent, itr->second));
|
||||
}
|
||||
|
||||
// Nothing found
|
||||
if (procTriggered.empty())
|
||||
return;
|
||||
|
||||
// Handle effects proceed this time
|
||||
for (ProcTriggeredList::const_iterator itr = procTriggered.begin(); itr != procTriggered.end(); ++itr)
|
||||
if (!procTriggered.empty())
|
||||
{
|
||||
// Some auras can be deleted in function called in this loop (except first, ofc)
|
||||
SpellAuraHolder* triggeredByHolder = itr->triggeredByHolder;
|
||||
if (triggeredByHolder->IsDeleted())
|
||||
continue;
|
||||
|
||||
SpellProcEventEntry const* spellProcEvent = itr->spellProcEvent;
|
||||
bool useCharges = triggeredByHolder->GetAuraCharges() > 0;
|
||||
bool procSuccess = true;
|
||||
bool anyAuraProc = false;
|
||||
|
||||
// For players set spell cooldown if need
|
||||
uint32 cooldown = 0;
|
||||
if (GetTypeId() == TYPEID_PLAYER && spellProcEvent && spellProcEvent->cooldown)
|
||||
cooldown = spellProcEvent->cooldown;
|
||||
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
// Handle effects proceed this time
|
||||
for (ProcTriggeredList::const_iterator itr = procTriggered.begin(); itr != procTriggered.end(); ++itr)
|
||||
{
|
||||
Aura* triggeredByAura = triggeredByHolder->GetAuraByEffectIndex(SpellEffectIndex(i));
|
||||
if (!triggeredByAura)
|
||||
// Some auras can be deleted in function called in this loop (except first, ofc)
|
||||
SpellAuraHolder* triggeredByHolder = itr->triggeredByHolder;
|
||||
if (triggeredByHolder->IsDeleted())
|
||||
continue;
|
||||
|
||||
SpellEffectEntry const* spellEffect = triggeredByHolder->GetSpellProto()->GetSpellEffect(SpellEffectIndex(i));
|
||||
if (!spellEffect)
|
||||
continue;
|
||||
SpellProcEventEntry const* spellProcEvent = itr->spellProcEvent;
|
||||
bool useCharges = triggeredByHolder->GetAuraCharges() > 0;
|
||||
bool procSuccess = true;
|
||||
bool anyAuraProc = false;
|
||||
|
||||
if (procSpell)
|
||||
// For players set spell cooldown if need
|
||||
uint32 cooldown = 0;
|
||||
if (GetTypeId() == TYPEID_PLAYER && spellProcEvent && spellProcEvent->cooldown)
|
||||
cooldown = spellProcEvent->cooldown;
|
||||
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
{
|
||||
if (spellProcEvent)
|
||||
{
|
||||
if (spellProcEvent->spellFamilyMask[i])
|
||||
{
|
||||
if (!procSpell->IsFitToFamilyMask(spellProcEvent->spellFamilyMask[i]))
|
||||
continue;
|
||||
Aura* triggeredByAura = triggeredByHolder->GetAuraByEffectIndex(SpellEffectIndex(i));
|
||||
if (!triggeredByAura)
|
||||
continue;
|
||||
|
||||
// don't allow proc from cast end for non modifier spells
|
||||
// unless they have proc ex defined for that
|
||||
if (IsCastEndProcModifierAura(triggeredByHolder->GetSpellProto(), SpellEffectIndex(i), procSpell))
|
||||
SpellEffectEntry const* spellEffect = triggeredByHolder->GetSpellProto()->GetSpellEffect(SpellEffectIndex(i));
|
||||
if (!spellEffect)
|
||||
continue;
|
||||
|
||||
if (procSpell)
|
||||
{
|
||||
if (spellProcEvent)
|
||||
{
|
||||
if (spellProcEvent->spellFamilyMask[i])
|
||||
{
|
||||
if (useCharges && procExtra != PROC_EX_CAST_END && spellProcEvent->procEx == PROC_EX_NONE)
|
||||
if (!procSpell->IsFitToFamilyMask(spellProcEvent->spellFamilyMask[i]))
|
||||
continue;
|
||||
|
||||
// don't allow proc from cast end for non modifier spells
|
||||
// unless they have proc ex defined for that
|
||||
if (IsCastEndProcModifierAura(triggeredByHolder->GetSpellProto(), SpellEffectIndex(i), procSpell))
|
||||
{
|
||||
if (useCharges && procExtra != PROC_EX_CAST_END && spellProcEvent->procEx == PROC_EX_NONE)
|
||||
continue;
|
||||
}
|
||||
else if (spellProcEvent->procEx == PROC_EX_NONE && procExtra == PROC_EX_CAST_END)
|
||||
continue;
|
||||
}
|
||||
else if (spellProcEvent->procEx == PROC_EX_NONE && procExtra == PROC_EX_CAST_END)
|
||||
// don't check dbc FamilyFlags if schoolMask exists
|
||||
else if (!triggeredByAura->CanProcFrom(procSpell, procFlag, spellProcEvent->procEx, procExtra, damage != 0, !spellProcEvent->schoolMask))
|
||||
continue;
|
||||
}
|
||||
// don't check dbc FamilyFlags if schoolMask exists
|
||||
else if (!triggeredByAura->CanProcFrom(procSpell, procFlag, spellProcEvent->procEx, procExtra, damage != 0, !spellProcEvent->schoolMask))
|
||||
else if (!triggeredByAura->CanProcFrom(procSpell, procFlag, PROC_EX_NONE, procExtra, damage != 0, true))
|
||||
continue;
|
||||
}
|
||||
else if (!triggeredByAura->CanProcFrom(procSpell, procFlag, PROC_EX_NONE, procExtra, damage != 0, true))
|
||||
continue;
|
||||
}
|
||||
|
||||
SpellAuraProcResult procResult = (*this.*AuraProcHandler[spellEffect->EffectApplyAuraName])(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown);
|
||||
switch (procResult)
|
||||
{
|
||||
SpellAuraProcResult procResult = (*this.*AuraProcHandler[spellEffect->EffectApplyAuraName])(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown);
|
||||
switch (procResult)
|
||||
{
|
||||
case SPELL_AURA_PROC_CANT_TRIGGER:
|
||||
continue;
|
||||
case SPELL_AURA_PROC_FAILED:
|
||||
|
|
@ -10893,20 +10935,21 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* pTarget, uint32 procFlag,
|
|||
break;
|
||||
case SPELL_AURA_PROC_OK:
|
||||
break;
|
||||
}
|
||||
|
||||
anyAuraProc = true;
|
||||
}
|
||||
|
||||
anyAuraProc = true;
|
||||
}
|
||||
// Remove charge (aura can be removed by triggers)
|
||||
if (useCharges && procSuccess && anyAuraProc && !triggeredByHolder->IsDeleted())
|
||||
{
|
||||
// If last charge dropped add spell to remove list
|
||||
if (triggeredByHolder->DropAuraCharge())
|
||||
removedSpells.push_back(triggeredByHolder->GetId());
|
||||
}
|
||||
|
||||
// Remove charge (aura can be removed by triggers)
|
||||
if (useCharges && procSuccess && anyAuraProc && !triggeredByHolder->IsDeleted())
|
||||
{
|
||||
// If last charge dropped add spell to remove list
|
||||
if (triggeredByHolder->DropAuraCharge())
|
||||
removedSpells.push_back(triggeredByHolder->GetId());
|
||||
triggeredByHolder->SetInUse(false);
|
||||
}
|
||||
|
||||
triggeredByHolder->SetInUse(false);
|
||||
}
|
||||
|
||||
if (!removedSpells.empty())
|
||||
|
|
|
|||
|
|
@ -1253,6 +1253,18 @@ enum IgnoreUnitState
|
|||
#define REGEN_TIME_PRECISE 500 // Used in Spell::CheckPower for precise regeneration in spell cast time
|
||||
#define REGEN_TIME_HOLY_POWER 10000 // This determines how often holy power regen is processed
|
||||
|
||||
// Power type values defines
|
||||
enum PowerDefaults
|
||||
{
|
||||
POWER_RAGE_DEFAULT = 1000,
|
||||
POWER_FOCUS_DEFAULT = 100,
|
||||
POWER_ENERGY_DEFAULT = 100,
|
||||
POWER_RUNE_DEFAULT = 8,
|
||||
POWER_RUNIC_POWER_DEFAULT = 1000,
|
||||
POWER_HOLY_POWER_DEFAULT = 3,
|
||||
POWER_SOUL_SHARDS_DEFAULT = 3,
|
||||
};
|
||||
|
||||
struct SpellProcEventEntry; // used only privately
|
||||
|
||||
#define MAX_OBJECT_SLOT 5
|
||||
|
|
@ -1492,6 +1504,11 @@ class Unit : public WorldObject
|
|||
* @return true if you and/or your pets/minions etc are attacking a player.
|
||||
*/
|
||||
bool isAttackingPlayer() const;
|
||||
/**
|
||||
* Checks if wa vehicle is allowed to attack other units by itself.
|
||||
* @return true if vehicle can attack itself.
|
||||
*/
|
||||
bool CanAttackByItself() const;
|
||||
/**
|
||||
* @return The victim that you are currently attacking
|
||||
*/
|
||||
|
|
@ -2120,7 +2137,7 @@ class Unit : public WorldObject
|
|||
* @param damageInfo this is filled with data about what kind of damage that was done
|
||||
* @param attackType type of attack, base/off/ranged
|
||||
*/
|
||||
void CalculateMeleeDamage(Unit* pVictim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK);
|
||||
void CalculateMeleeDamage(Unit* pVictim, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK);
|
||||
/**
|
||||
* Deals melee damage, if the attack was parried we reduce the victims time until next hit
|
||||
* instead of the weapons normal time by 20 or 60%.
|
||||
|
|
|
|||
|
|
@ -79,14 +79,24 @@ void OutdoorPvP::HandleGameObjectCreate(GameObject* go)
|
|||
{
|
||||
// set initial data and activate capture points
|
||||
if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_CAPTURE_POINT)
|
||||
go->SetCapturePointSlider(sOutdoorPvPMgr.GetCapturePointSliderValue(go->GetEntry(), CAPTURE_SLIDER_MIDDLE));
|
||||
{
|
||||
CapturePointSliderMap const* capturePoints = sOutdoorPvPMgr.GetCapturePointSliderMap();
|
||||
CapturePointSliderMap::const_iterator itr = capturePoints->find(go->GetEntry());
|
||||
if (itr != capturePoints->end())
|
||||
go->SetCapturePointSlider(itr->second.Value, itr->second.IsLocked);
|
||||
else
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE, false);
|
||||
}
|
||||
}
|
||||
|
||||
void OutdoorPvP::HandleGameObjectRemove(GameObject* go)
|
||||
{
|
||||
// save capture point slider value (negative value if locked)
|
||||
if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_CAPTURE_POINT)
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(go->GetEntry(), go->getLootState() == GO_ACTIVATED ? go->GetCapturePointSlider() : -go->GetCapturePointSlider());
|
||||
{
|
||||
CapturePointSlider value(go->GetCapturePointSliderValue(), go->getLootState() != GO_ACTIVATED);
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(go->GetEntry(), value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ enum CapturePointAnimations
|
|||
CAPTURE_ANIM_NEUTRAL = 2
|
||||
};
|
||||
|
||||
typedef std::map < ObjectGuid /*playerGuid*/, bool /*isMainZone*/ > GuidZoneMap;
|
||||
typedef std::map<ObjectGuid /*playerGuid*/, bool /*isMainZone*/> GuidZoneMap;
|
||||
|
||||
class OutdoorPvP
|
||||
{
|
||||
|
|
@ -65,7 +65,7 @@ class OutdoorPvP
|
|||
virtual bool HandleEvent(uint32 /*eventId*/, GameObject* /*go*/) { return false; }
|
||||
|
||||
// handle capture objective complete
|
||||
virtual void HandleObjectiveComplete(uint32 /*eventId*/, std::list<Player*> /*players*/, Team /*team*/) {}
|
||||
virtual void HandleObjectiveComplete(uint32 /*eventId*/, const std::list<Player*>& /*players*/, Team /*team*/) {}
|
||||
|
||||
// Called when a creature is created
|
||||
virtual void HandleCreatureCreate(Creature* /*creature*/) {}
|
||||
|
|
|
|||
|
|
@ -148,38 +148,38 @@ void OutdoorPvPEP::HandleGameObjectCreate(GameObject* go)
|
|||
}
|
||||
}
|
||||
|
||||
void OutdoorPvPEP::HandleObjectiveComplete(uint32 eventId, std::list<Player*> players, Team team)
|
||||
void OutdoorPvPEP::HandleObjectiveComplete(uint32 eventId, const std::list<Player*>& players, Team team)
|
||||
{
|
||||
uint32 credit = 0;
|
||||
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_CROWNGUARD_PROGRESS_ALLIANCE:
|
||||
case EVENT_CROWNGUARD_PROGRESS_HORDE:
|
||||
credit = NPC_CROWNGUARD_TOWER_QUEST_DOODAD;
|
||||
break;
|
||||
case EVENT_EASTWALL_PROGRESS_ALLIANCE:
|
||||
case EVENT_EASTWALL_PROGRESS_HORDE:
|
||||
credit = NPC_EASTWALL_TOWER_QUEST_DOODAD;
|
||||
break;
|
||||
case EVENT_NORTHPASS_PROGRESS_ALLIANCE:
|
||||
case EVENT_NORTHPASS_PROGRESS_HORDE:
|
||||
credit = NPC_NORTHPASS_TOWER_QUEST_DOODAD;
|
||||
break;
|
||||
case EVENT_PLAGUEWOOD_PROGRESS_ALLIANCE:
|
||||
case EVENT_PLAGUEWOOD_PROGRESS_HORDE:
|
||||
credit = NPC_PLAGUEWOOD_TOWER_QUEST_DOODAD;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
case EVENT_CROWNGUARD_PROGRESS_ALLIANCE:
|
||||
case EVENT_CROWNGUARD_PROGRESS_HORDE:
|
||||
credit = NPC_CROWNGUARD_TOWER_QUEST_DOODAD;
|
||||
break;
|
||||
case EVENT_EASTWALL_PROGRESS_ALLIANCE:
|
||||
case EVENT_EASTWALL_PROGRESS_HORDE:
|
||||
credit = NPC_EASTWALL_TOWER_QUEST_DOODAD;
|
||||
break;
|
||||
case EVENT_NORTHPASS_PROGRESS_ALLIANCE:
|
||||
case EVENT_NORTHPASS_PROGRESS_HORDE:
|
||||
credit = NPC_NORTHPASS_TOWER_QUEST_DOODAD;
|
||||
break;
|
||||
case EVENT_PLAGUEWOOD_PROGRESS_ALLIANCE:
|
||||
case EVENT_PLAGUEWOOD_PROGRESS_HORDE:
|
||||
credit = NPC_PLAGUEWOOD_TOWER_QUEST_DOODAD;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
for (std::list<Player*>::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
{
|
||||
if ((*itr) && (*itr)->GetTeam() == team)
|
||||
{
|
||||
(*itr)->KilledMonsterCredit(credit);
|
||||
(*itr)->RewardHonor(NULL, 1, HONOR_REWARD_PLAGUELANDS);
|
||||
(*itr)->RewardHonor(nullptr, 1, HONOR_REWARD_PLAGUELANDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ class OutdoorPvPEP : public OutdoorPvP
|
|||
void SendRemoveWorldStates(Player* player) override;
|
||||
|
||||
bool HandleEvent(uint32 eventId, GameObject* go) override;
|
||||
void HandleObjectiveComplete(uint32 eventId, std::list<Player*> players, Team team) override;
|
||||
void HandleObjectiveComplete(uint32 eventId, const std::list<Player*>& players, Team team) override;
|
||||
|
||||
void HandleCreatureCreate(Creature* creature) override;
|
||||
void HandleGameObjectCreate(GameObject* go) override;
|
||||
|
|
|
|||
|
|
@ -143,16 +143,22 @@ void OutdoorPvPGH::LockLighthouse(const WorldObject* objRef)
|
|||
if (GameObject* go = objRef->GetMap()->GetGameObject(m_capturePoint))
|
||||
go->SetLootState(GO_JUST_DEACTIVATED);
|
||||
else
|
||||
{
|
||||
// if grid is unloaded, changing the saved slider value is enough
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(GO_VENTURE_BAY_LIGHTHOUSE, m_zoneOwner == ALLIANCE ? -CAPTURE_SLIDER_ALLIANCE : -CAPTURE_SLIDER_HORDE);
|
||||
CapturePointSlider value(m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE, true);
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(GO_VENTURE_BAY_LIGHTHOUSE, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Lighthouse unlock when the commander is killed
|
||||
void OutdoorPvPGH::UnlockLighthouse(const WorldObject* objRef)
|
||||
{
|
||||
if (GameObject* go = objRef->GetMap()->GetGameObject(m_capturePoint))
|
||||
go->SetCapturePointSlider(m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE);
|
||||
go->SetLootState(GO_ACTIVATED);
|
||||
else
|
||||
// if grid is unloaded, resetting the saved slider value is enough
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(GO_VENTURE_BAY_LIGHTHOUSE, m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE);
|
||||
{
|
||||
// if grid is unloaded, changing the saved slider value is enough
|
||||
CapturePointSlider value(m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE, false);
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(GO_VENTURE_BAY_LIGHTHOUSE, value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ void OutdoorPvPHP::HandleGameObjectCreate(GameObject* go)
|
|||
}
|
||||
}
|
||||
|
||||
void OutdoorPvPHP::HandleObjectiveComplete(uint32 eventId, std::list<Player*> players, Team team)
|
||||
void OutdoorPvPHP::HandleObjectiveComplete(uint32 eventId, const std::list<Player*>& players, Team team)
|
||||
{
|
||||
uint32 credit = 0;
|
||||
|
||||
|
|
@ -136,12 +136,12 @@ void OutdoorPvPHP::HandleObjectiveComplete(uint32 eventId, std::list<Player*> pl
|
|||
return;
|
||||
}
|
||||
|
||||
for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
for (std::list<Player*>::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
{
|
||||
if ((*itr) && (*itr)->GetTeam() == team)
|
||||
{
|
||||
(*itr)->KilledMonsterCredit(credit);
|
||||
(*itr)->RewardHonor(NULL, 1, HONOR_REWARD_HELLFIRE);
|
||||
(*itr)->RewardHonor(nullptr, 1, HONOR_REWARD_HELLFIRE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ class OutdoorPvPHP : public OutdoorPvP
|
|||
void SendRemoveWorldStates(Player* player) override;
|
||||
|
||||
bool HandleEvent(uint32 eventId, GameObject* go) override;
|
||||
void HandleObjectiveComplete(uint32 eventId, std::list<Player*> players, Team team) override;
|
||||
void HandleObjectiveComplete(uint32 eventId, const std::list<Player*>& players, Team team) override;
|
||||
|
||||
void HandleGameObjectCreate(GameObject* go) override;
|
||||
void HandlePlayerKillInsideArea(Player* player) override;
|
||||
|
|
|
|||
|
|
@ -167,19 +167,3 @@ void OutdoorPvPMgr::Update(uint32 diff)
|
|||
|
||||
m_updateTimer.Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
Function that gets the capture point slider value
|
||||
|
||||
@param capture point entry
|
||||
@param default value being returned if no saved value for the capture point was found
|
||||
*/
|
||||
float OutdoorPvPMgr::GetCapturePointSliderValue(uint32 entry, float defaultValue)
|
||||
{
|
||||
CapturePointSliderMap::const_iterator itr = m_capturePointSlider.find(entry);
|
||||
if (itr != m_capturePointSlider.end())
|
||||
return itr->second;
|
||||
|
||||
// return default value if we can't find any
|
||||
return defaultValue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,11 +79,22 @@ enum OutdoorPvPZones
|
|||
ZONE_ID_GRIZZLY_HILLS = 394
|
||||
};
|
||||
|
||||
struct CapturePointSlider
|
||||
{
|
||||
CapturePointSlider() : Value(0.0f), IsLocked(false) {}
|
||||
CapturePointSlider(float value, bool isLocked) : Value(value), IsLocked(isLocked) {}
|
||||
|
||||
float Value;
|
||||
bool IsLocked;
|
||||
};
|
||||
|
||||
class Player;
|
||||
class GameObject;
|
||||
class Creature;
|
||||
class OutdoorPvP;
|
||||
|
||||
typedef std::map<uint32 /*capture point entry*/, CapturePointSlider /*slider value and lock state*/> CapturePointSliderMap;
|
||||
|
||||
class OutdoorPvPMgr
|
||||
{
|
||||
public:
|
||||
|
|
@ -104,23 +115,21 @@ class OutdoorPvPMgr
|
|||
|
||||
void Update(uint32 diff);
|
||||
|
||||
// Save and load capture point slider values
|
||||
float GetCapturePointSliderValue(uint32 entry, float defaultValue);
|
||||
void SetCapturePointSlider(uint32 entry, float value) { m_capturePointSlider[entry] = value; }
|
||||
// Save and load capture point slider
|
||||
CapturePointSliderMap const* GetCapturePointSliderMap() const { return &m_capturePointSlider; }
|
||||
void SetCapturePointSlider(uint32 entry, CapturePointSlider value) { m_capturePointSlider[entry] = value; }
|
||||
|
||||
private:
|
||||
// return assigned outdoor pvp script
|
||||
OutdoorPvP* GetScriptOfAffectedZone(uint32 zoneId);
|
||||
private:
|
||||
// return assigned outdoor pvp script
|
||||
OutdoorPvP* GetScriptOfAffectedZone(uint32 zoneId);
|
||||
|
||||
// contains all outdoor pvp scripts
|
||||
OutdoorPvP* m_scripts[MAX_OPVP_ID];
|
||||
// contains all outdoor pvp scripts
|
||||
OutdoorPvP* m_scripts[MAX_OPVP_ID];
|
||||
|
||||
typedef std::map<uint32 /*capture point entry*/, float /*slider value*/> CapturePointSliderMap;
|
||||
CapturePointSliderMap m_capturePointSlider;
|
||||
|
||||
CapturePointSliderMap m_capturePointSlider;
|
||||
|
||||
// update interval
|
||||
ShortIntervalTimer m_updateTimer;
|
||||
// update interval
|
||||
ShortIntervalTimer m_updateTimer;
|
||||
};
|
||||
|
||||
#define sOutdoorPvPMgr MaNGOS::Singleton<OutdoorPvPMgr>::Instance()
|
||||
|
|
|
|||
|
|
@ -85,11 +85,11 @@ void OutdoorPvPNA::HandlePlayerLeaveZone(Player* player, bool isMainZone)
|
|||
OutdoorPvP::HandlePlayerLeaveZone(player, isMainZone);
|
||||
}
|
||||
|
||||
void OutdoorPvPNA::HandleObjectiveComplete(uint32 eventId, std::list<Player*> players, Team team)
|
||||
void OutdoorPvPNA::HandleObjectiveComplete(uint32 eventId, const std::list<Player*>& players, Team team)
|
||||
{
|
||||
if (eventId == EVENT_HALAA_BANNER_WIN_ALLIANCE || eventId == EVENT_HALAA_BANNER_WIN_HORDE)
|
||||
{
|
||||
for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
for (std::list<Player*>::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
{
|
||||
if ((*itr) && (*itr)->GetTeam() == team)
|
||||
(*itr)->KilledMonsterCredit(NPC_HALAA_COMBATANT);
|
||||
|
|
@ -550,16 +550,22 @@ void OutdoorPvPNA::LockHalaa(const WorldObject* objRef)
|
|||
if (GameObject* go = objRef->GetMap()->GetGameObject(m_capturePoint))
|
||||
go->SetLootState(GO_JUST_DEACTIVATED);
|
||||
else
|
||||
{
|
||||
// if grid is unloaded, changing the saved slider value is enough
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(GO_HALAA_BANNER, m_zoneOwner == ALLIANCE ? -CAPTURE_SLIDER_ALLIANCE : -CAPTURE_SLIDER_HORDE);
|
||||
CapturePointSlider value(m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE, true);
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(GO_HALAA_BANNER, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock Halaa when all the soldiers are killed
|
||||
void OutdoorPvPNA::UnlockHalaa(const WorldObject* objRef)
|
||||
{
|
||||
if (GameObject* go = objRef->GetMap()->GetGameObject(m_capturePoint))
|
||||
go->SetCapturePointSlider(m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE);
|
||||
go->SetLootState(GO_ACTIVATED);
|
||||
else
|
||||
// if grid is unloaded, resetting the saved slider value is enough
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(GO_HALAA_BANNER, m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE);
|
||||
{
|
||||
// if grid is unloaded, changing the saved slider value is enough
|
||||
CapturePointSlider value(m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE, false);
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(GO_HALAA_BANNER, value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ class OutdoorPvPNA : public OutdoorPvP
|
|||
void SendRemoveWorldStates(Player* player) override;
|
||||
|
||||
bool HandleEvent(uint32 eventId, GameObject* go) override;
|
||||
void HandleObjectiveComplete(uint32 eventId, std::list<Player*> players, Team team) override;
|
||||
void HandleObjectiveComplete(uint32 eventId, const std::list<Player*>& players, Team team) override;
|
||||
|
||||
void HandleCreatureCreate(Creature* creature) override;
|
||||
void HandleGameObjectCreate(GameObject* go) override;
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ void OutdoorPvPTF::HandleGameObjectCreate(GameObject* go)
|
|||
}
|
||||
}
|
||||
|
||||
void OutdoorPvPTF::HandleObjectiveComplete(uint32 eventId, std::list<Player*> players, Team team)
|
||||
void OutdoorPvPTF::HandleObjectiveComplete(uint32 eventId, const std::list<Player*>& players, Team team)
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_TF_TOWERS; ++i)
|
||||
{
|
||||
|
|
@ -126,7 +126,7 @@ void OutdoorPvPTF::HandleObjectiveComplete(uint32 eventId, std::list<Player*> pl
|
|||
{
|
||||
if (terokkarTowerEvents[i][j].eventEntry == eventId)
|
||||
{
|
||||
for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
for (std::list<Player*>::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
{
|
||||
if ((*itr) && (*itr)->GetTeam() == team)
|
||||
(*itr)->AreaExploredOrEventHappens(team == ALLIANCE ? QUEST_SPIRITS_OF_AUCHINDOUM_ALLIANCE : QUEST_SPIRITS_OF_AUCHINDOUM_HORDE);
|
||||
|
|
@ -351,8 +351,11 @@ void OutdoorPvPTF::LockTowers(const WorldObject* objRef)
|
|||
if (GameObject* go = objRef->GetMap()->GetGameObject(m_towerBanners[i]))
|
||||
go->SetLootState(GO_JUST_DEACTIVATED);
|
||||
else
|
||||
{
|
||||
// if grid is unloaded, changing the saved slider value is enough
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(terokkarTowers[i], m_zoneOwner == ALLIANCE ? -CAPTURE_SLIDER_ALLIANCE : -CAPTURE_SLIDER_HORDE);
|
||||
CapturePointSlider value(m_zoneOwner == ALLIANCE ? CAPTURE_SLIDER_ALLIANCE : CAPTURE_SLIDER_HORDE, true);
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(terokkarTowers[i], value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -363,12 +366,15 @@ void OutdoorPvPTF::ResetTowers(const WorldObject* objRef)
|
|||
{
|
||||
if (GameObject* go = objRef->GetMap()->GetGameObject(m_towerBanners[i]))
|
||||
{
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE);
|
||||
go->SetCapturePointSlider(CAPTURE_SLIDER_MIDDLE, false);
|
||||
// visual update needed because banner still has artkit from previous owner
|
||||
SetBannerVisual(go, CAPTURE_ARTKIT_NEUTRAL, CAPTURE_ANIM_NEUTRAL);
|
||||
}
|
||||
else
|
||||
// if grid is unloaded, resetting the saved slider value is enough
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(terokkarTowers[i], CAPTURE_SLIDER_MIDDLE);
|
||||
{
|
||||
// if grid is unloaded, changing the saved slider value is enough
|
||||
CapturePointSlider value(CAPTURE_SLIDER_MIDDLE, false);
|
||||
sOutdoorPvPMgr.SetCapturePointSlider(terokkarTowers[i], value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ class OutdoorPvPTF : public OutdoorPvP
|
|||
void SendRemoveWorldStates(Player* player) override;
|
||||
|
||||
bool HandleEvent(uint32 eventId, GameObject* go) override;
|
||||
void HandleObjectiveComplete(uint32 eventId, std::list<Player*> players, Team team) override;
|
||||
void HandleObjectiveComplete(uint32 eventId, const std::list<Player*>& players, Team team) override;
|
||||
|
||||
void HandleGameObjectCreate(GameObject* go) override;
|
||||
void Update(uint32 diff) override;
|
||||
|
|
|
|||
|
|
@ -3779,7 +3779,7 @@ enum MaxLevel
|
|||
static const MaxLevel maxLevelForExpansion[MAX_EXPANSION + 1] = { MAX_LEVEL_CLASSIC, MAX_LEVEL_TBC, MAX_LEVEL_WOTLK, MAX_LEVEL_CATACLYSM };
|
||||
|
||||
// Max creature level (included some bosses and elite)
|
||||
#define DEFAULT_MAX_CREATURE_LEVEL 85
|
||||
#define DEFAULT_MAX_CREATURE_LEVEL 90
|
||||
|
||||
// This spell is used for general boarding serverside
|
||||
#define SPELL_RIDE_VEHICLE_HARDCODED 46598
|
||||
|
|
|
|||
|
|
@ -1042,7 +1042,7 @@ enum MangosStrings
|
|||
// Use for custom patches 11000-11999
|
||||
|
||||
// NOT RESERVED IDS 12000-1999999999
|
||||
// `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID)
|
||||
// For other tables maybe 2000010000-2147483647 (max index)
|
||||
// `db_script_string` table index 2000000000-2000999999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID)
|
||||
// For other tables maybe 2001000000-2147483647 (max index)
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -246,12 +246,13 @@ bool AccountMgr::CheckPassword(uint32 accid, std::string passwd)
|
|||
bool AccountMgr::normalizeString(std::string& utf8str)
|
||||
{
|
||||
wchar_t wstr_buf[MAX_ACCOUNT_STR + 1];
|
||||
|
||||
size_t wstr_len = MAX_ACCOUNT_STR;
|
||||
|
||||
if (!Utf8toWStr(utf8str, wstr_buf, wstr_len))
|
||||
return false;
|
||||
|
||||
std::transform(&wstr_buf[0], wstr_buf + wstr_len, &wstr_buf[0], wcharToUpperOnlyLatin);
|
||||
for (uint32 i = 0; i <= wstr_len; ++i)
|
||||
wstr_buf[i] = wcharToUpperOnlyLatin(wstr_buf[i]);
|
||||
|
||||
return WStrToUtf8(wstr_buf, wstr_len, utf8str);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "Map.h"
|
||||
#include "InstanceData.h"
|
||||
#include "DBCStructure.h"
|
||||
#include "Chat.h"
|
||||
|
||||
#include "Policies/Singleton.h"
|
||||
|
||||
|
|
@ -63,15 +64,8 @@ namespace MaNGOS
|
|||
{
|
||||
char const* text = sObjectMgr.GetMangosString(i_textId, loc_idx);
|
||||
|
||||
data << uint8(i_msgtype);
|
||||
data << uint32(LANG_UNIVERSAL);
|
||||
data << i_player.GetObjectGuid();
|
||||
data << uint32(5);
|
||||
data << i_player.GetObjectGuid();
|
||||
data << uint32(strlen(text) + 1);
|
||||
data << text;
|
||||
data << uint8(0);
|
||||
data << uint32(i_achievementId);
|
||||
ChatHandler::BuildChatPacket(data, i_msgtype, text, LANG_UNIVERSAL, i_player.GetChatTag(), i_player.GetObjectGuid(), nullptr, i_player.GetObjectGuid(), nullptr, nullptr,
|
||||
i_achievementId);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -39,9 +39,9 @@ enum ChatNotify
|
|||
{
|
||||
CHAT_JOINED_NOTICE = 0x00, //+ "%s joined channel.";
|
||||
CHAT_LEFT_NOTICE = 0x01, //+ "%s left channel.";
|
||||
// CHAT_SUSPENDED_NOTICE = 0x01, // "%s left channel.";
|
||||
// CHAT_SUSPENDED_NOTICE = 0x01, // "%s left channel.";
|
||||
CHAT_YOU_JOINED_NOTICE = 0x02, //+ "Joined Channel: [%s]"; -- You joined
|
||||
// CHAT_YOU_CHANGED_NOTICE = 0x02, // "Changed Channel: [%s]";
|
||||
// CHAT_YOU_CHANGED_NOTICE = 0x02, // "Changed Channel: [%s]";
|
||||
CHAT_YOU_LEFT_NOTICE = 0x03, //+ "Left Channel: [%s]"; -- You left
|
||||
CHAT_WRONG_PASSWORD_NOTICE = 0x04, //+ "Wrong password for %s.";
|
||||
CHAT_NOT_MEMBER_NOTICE = 0x05, //+ "Not on channel %s.";
|
||||
|
|
@ -63,7 +63,7 @@ enum ChatNotify
|
|||
CHAT_PLAYER_UNBANNED_NOTICE = 0x15, //? "[%s] Player %s unbanned by %s.";
|
||||
CHAT_PLAYER_NOT_BANNED_NOTICE = 0x16, //+ "[%s] Player %s is not banned.";
|
||||
CHAT_PLAYER_ALREADY_MEMBER_NOTICE = 0x17, //+ "[%s] Player %s is already on the channel.";
|
||||
CHAT_INVITE_NOTICE = 0x18, //+ "%2$s has invited you to join the channel '%1$s'.";
|
||||
CHAT_INVITE_NOTICE = 0x18, //+ "%2$s has invited you to join the channel '%1$s'.";
|
||||
CHAT_INVITE_WRONG_FACTION_NOTICE = 0x19, //+ "Target is in the wrong alliance for %s.";
|
||||
CHAT_WRONG_FACTION_NOTICE = 0x1A, //+ "Wrong alliance for %s.";
|
||||
CHAT_INVALID_NAME_NOTICE = 0x1B, //+ "Invalid channel name";
|
||||
|
|
@ -75,215 +75,215 @@ enum ChatNotify
|
|||
CHAT_NOT_IN_LFG_NOTICE = 0x21, //+ "[%s] You must be queued in looking for group before joining this channel."; -- The user must be in the looking for group system to join LFG chat channels.
|
||||
CHAT_VOICE_ON_NOTICE = 0x22, //+ "[%s] Channel voice enabled by %s.";
|
||||
CHAT_VOICE_OFF_NOTICE = 0x23 //+ "[%s] Channel voice disabled by %s.";
|
||||
// 0x24 enable voice?
|
||||
// 0x24 enable voice?
|
||||
};
|
||||
|
||||
class Channel
|
||||
{
|
||||
enum ChannelFlags
|
||||
{
|
||||
CHANNEL_FLAG_NONE = 0x00,
|
||||
CHANNEL_FLAG_CUSTOM = 0x01,
|
||||
// 0x02
|
||||
CHANNEL_FLAG_TRADE = 0x04,
|
||||
CHANNEL_FLAG_NOT_LFG = 0x08,
|
||||
CHANNEL_FLAG_GENERAL = 0x10,
|
||||
CHANNEL_FLAG_CITY = 0x20,
|
||||
CHANNEL_FLAG_LFG = 0x40,
|
||||
CHANNEL_FLAG_VOICE = 0x80
|
||||
// General 0x18 = 0x10 | 0x08
|
||||
// Trade 0x3C = 0x20 | 0x10 | 0x08 | 0x04
|
||||
// LocalDefence 0x18 = 0x10 | 0x08
|
||||
// GuildRecruitment 0x38 = 0x20 | 0x10 | 0x08
|
||||
// LookingForGroup 0x50 = 0x40 | 0x10
|
||||
};
|
||||
enum ChannelFlags
|
||||
{
|
||||
CHANNEL_FLAG_NONE = 0x00,
|
||||
CHANNEL_FLAG_CUSTOM = 0x01,
|
||||
// 0x02
|
||||
CHANNEL_FLAG_TRADE = 0x04,
|
||||
CHANNEL_FLAG_NOT_LFG = 0x08,
|
||||
CHANNEL_FLAG_GENERAL = 0x10,
|
||||
CHANNEL_FLAG_CITY = 0x20,
|
||||
CHANNEL_FLAG_LFG = 0x40,
|
||||
CHANNEL_FLAG_VOICE = 0x80
|
||||
// General 0x18 = 0x10 | 0x08
|
||||
// Trade 0x3C = 0x20 | 0x10 | 0x08 | 0x04
|
||||
// LocalDefence 0x18 = 0x10 | 0x08
|
||||
// GuildRecruitment 0x38 = 0x20 | 0x10 | 0x08
|
||||
// LookingForGroup 0x50 = 0x40 | 0x10
|
||||
};
|
||||
|
||||
enum ChannelDBCFlags
|
||||
{
|
||||
CHANNEL_DBC_FLAG_NONE = 0x00000,
|
||||
CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG
|
||||
CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment
|
||||
CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense
|
||||
CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade
|
||||
CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment
|
||||
CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment
|
||||
CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense
|
||||
CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment
|
||||
CHANNEL_DBC_FLAG_LFG = 0x40000 // LookingForGroup
|
||||
};
|
||||
enum ChannelDBCFlags
|
||||
{
|
||||
CHANNEL_DBC_FLAG_NONE = 0x00000,
|
||||
CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG
|
||||
CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment
|
||||
CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense
|
||||
CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade
|
||||
CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment
|
||||
CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment
|
||||
CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense
|
||||
CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment
|
||||
CHANNEL_DBC_FLAG_LFG = 0x40000 // LookingForGroup
|
||||
};
|
||||
|
||||
enum ChannelMemberFlags
|
||||
{
|
||||
MEMBER_FLAG_NONE = 0x00,
|
||||
MEMBER_FLAG_OWNER = 0x01,
|
||||
MEMBER_FLAG_MODERATOR = 0x02,
|
||||
MEMBER_FLAG_VOICED = 0x04,
|
||||
MEMBER_FLAG_MUTED = 0x08,
|
||||
MEMBER_FLAG_CUSTOM = 0x10,
|
||||
MEMBER_FLAG_MIC_MUTED = 0x20,
|
||||
// 0x40
|
||||
// 0x80
|
||||
};
|
||||
enum ChannelMemberFlags
|
||||
{
|
||||
MEMBER_FLAG_NONE = 0x00,
|
||||
MEMBER_FLAG_OWNER = 0x01,
|
||||
MEMBER_FLAG_MODERATOR = 0x02,
|
||||
MEMBER_FLAG_VOICED = 0x04,
|
||||
MEMBER_FLAG_MUTED = 0x08,
|
||||
MEMBER_FLAG_CUSTOM = 0x10,
|
||||
MEMBER_FLAG_MIC_MUTED = 0x20,
|
||||
// 0x40
|
||||
// 0x80
|
||||
};
|
||||
|
||||
struct PlayerInfo
|
||||
{
|
||||
ObjectGuid player;
|
||||
uint8 flags;
|
||||
struct PlayerInfo
|
||||
{
|
||||
ObjectGuid player;
|
||||
uint8 flags;
|
||||
|
||||
bool HasFlag(uint8 flag) { return flags & flag; }
|
||||
void SetFlag(uint8 flag) { if (!HasFlag(flag)) flags |= flag; }
|
||||
bool IsOwner() { return flags & MEMBER_FLAG_OWNER; }
|
||||
void SetOwner(bool state)
|
||||
{
|
||||
if (state) flags |= MEMBER_FLAG_OWNER;
|
||||
else flags &= ~MEMBER_FLAG_OWNER;
|
||||
}
|
||||
bool IsModerator() { return flags & MEMBER_FLAG_MODERATOR; }
|
||||
void SetModerator(bool state)
|
||||
{
|
||||
if (state) flags |= MEMBER_FLAG_MODERATOR;
|
||||
else flags &= ~MEMBER_FLAG_MODERATOR;
|
||||
}
|
||||
bool IsMuted() { return flags & MEMBER_FLAG_MUTED; }
|
||||
void SetMuted(bool state)
|
||||
{
|
||||
if (state) flags |= MEMBER_FLAG_MUTED;
|
||||
else flags &= ~MEMBER_FLAG_MUTED;
|
||||
}
|
||||
};
|
||||
bool HasFlag(uint8 flag) { return flags & flag; }
|
||||
void SetFlag(uint8 flag) { if (!HasFlag(flag)) flags |= flag; }
|
||||
bool IsOwner() { return flags & MEMBER_FLAG_OWNER; }
|
||||
void SetOwner(bool state)
|
||||
{
|
||||
if (state) flags |= MEMBER_FLAG_OWNER;
|
||||
else flags &= ~MEMBER_FLAG_OWNER;
|
||||
}
|
||||
bool IsModerator() { return flags & MEMBER_FLAG_MODERATOR; }
|
||||
void SetModerator(bool state)
|
||||
{
|
||||
if (state) flags |= MEMBER_FLAG_MODERATOR;
|
||||
else flags &= ~MEMBER_FLAG_MODERATOR;
|
||||
}
|
||||
bool IsMuted() { return flags & MEMBER_FLAG_MUTED; }
|
||||
void SetMuted(bool state)
|
||||
{
|
||||
if (state) flags |= MEMBER_FLAG_MUTED;
|
||||
else flags &= ~MEMBER_FLAG_MUTED;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
Channel(const std::string& name, uint32 channel_id);
|
||||
std::string GetName() const { return m_name; }
|
||||
uint32 GetChannelId() const { return m_channelId; }
|
||||
bool IsConstant() const { return m_channelId != 0; }
|
||||
bool IsAnnounce() const { return m_announce; }
|
||||
bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; }
|
||||
std::string GetPassword() const { return m_password; }
|
||||
void SetPassword(const std::string& npassword) { m_password = npassword; }
|
||||
void SetAnnounce(bool nannounce) { m_announce = nannounce; }
|
||||
uint32 GetNumPlayers() const { return m_players.size(); }
|
||||
uint8 GetFlags() const { return m_flags; }
|
||||
bool HasFlag(uint8 flag) { return m_flags & flag; }
|
||||
public:
|
||||
Channel(const std::string& name, uint32 channel_id);
|
||||
std::string GetName() const { return m_name; }
|
||||
uint32 GetChannelId() const { return m_channelId; }
|
||||
bool IsConstant() const { return m_channelId != 0; }
|
||||
bool IsAnnounce() const { return m_announce; }
|
||||
bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; }
|
||||
std::string GetPassword() const { return m_password; }
|
||||
void SetPassword(const std::string& npassword) { m_password = npassword; }
|
||||
void SetAnnounce(bool nannounce) { m_announce = nannounce; }
|
||||
uint32 GetNumPlayers() const { return m_players.size(); }
|
||||
uint8 GetFlags() const { return m_flags; }
|
||||
bool HasFlag(uint8 flag) { return m_flags & flag; }
|
||||
|
||||
void Join(ObjectGuid p, const char* pass);
|
||||
void Leave(ObjectGuid p, bool send = true);
|
||||
void KickOrBan(ObjectGuid good, const char* badname, bool ban);
|
||||
void Kick(ObjectGuid good, const char* badname) { KickOrBan(good, badname, false); }
|
||||
void Ban(ObjectGuid good, const char* badname) { KickOrBan(good, badname, true); }
|
||||
void UnBan(ObjectGuid good, const char* badname);
|
||||
void Password(ObjectGuid p, const char* pass);
|
||||
void SetMode(ObjectGuid p, const char* p2n, bool mod, bool set);
|
||||
void SetOwner(ObjectGuid p, bool exclaim = true);
|
||||
void SetOwner(ObjectGuid p, const char* newname);
|
||||
void SendWhoOwner(ObjectGuid p);
|
||||
void SetModerator(ObjectGuid p, const char* newname) { SetMode(p, newname, true, true); }
|
||||
void UnsetModerator(ObjectGuid p, const char* newname) { SetMode(p, newname, true, false); }
|
||||
void SetMute(ObjectGuid p, const char* newname) { SetMode(p, newname, false, true); }
|
||||
void UnsetMute(ObjectGuid p, const char* newname) { SetMode(p, newname, false, false); }
|
||||
void List(Player* p);
|
||||
void Announce(ObjectGuid p);
|
||||
void Moderate(ObjectGuid p);
|
||||
void Say(ObjectGuid p, const char* what, uint32 lang);
|
||||
void Invite(ObjectGuid p, const char* newp);
|
||||
void Voice(ObjectGuid guid1, ObjectGuid guid2);
|
||||
void DeVoice(ObjectGuid guid1, ObjectGuid guid2);
|
||||
void JoinNotify(ObjectGuid guid); // invisible notify
|
||||
void LeaveNotify(ObjectGuid guid); // invisible notify
|
||||
void Join(Player* player, const char* password);
|
||||
void Leave(Player* player, bool send = true);
|
||||
void KickOrBan(Player* player, const char* targetName, bool ban);
|
||||
void Kick(Player* player, const char* targetName) { KickOrBan(player, targetName, false); }
|
||||
void Ban(Player* player, const char* targetName) { KickOrBan(player, targetName, true); }
|
||||
void UnBan(Player* player, const char* targetName);
|
||||
void Password(Player* player, const char* password);
|
||||
void SetMode(Player* player, const char* targetName, bool moderator, bool set);
|
||||
void SetOwner(ObjectGuid guid, bool exclaim = true);
|
||||
void SetOwner(Player* player, const char* targetName);
|
||||
void SendWhoOwner(Player* player);
|
||||
void SetModerator(Player* player, const char* targetName) { SetMode(player, targetName, true, true); }
|
||||
void UnsetModerator(Player* player, const char* targetName) { SetMode(player, targetName, true, false); }
|
||||
void SetMute(Player* player, const char* targetName) { SetMode(player, targetName, false, true); }
|
||||
void UnsetMute(Player* player, const char* targetName) { SetMode(player, targetName, false, false); }
|
||||
void List(Player* player);
|
||||
void Announce(Player* player);
|
||||
void Moderate(Player* player);
|
||||
void Say(Player* player, const char* text, uint32 lang);
|
||||
void Invite(Player* player, const char* targetName);
|
||||
void Voice(ObjectGuid guid1, ObjectGuid guid2);
|
||||
void DeVoice(ObjectGuid guid1, ObjectGuid guid2);
|
||||
void JoinNotify(ObjectGuid guid); // invisible notify
|
||||
void LeaveNotify(ObjectGuid guid); // invisible notify
|
||||
|
||||
private:
|
||||
// initial packet data (notify type and channel name)
|
||||
void MakeNotifyPacket(WorldPacket* data, uint8 notify_type);
|
||||
// type specific packet data
|
||||
void MakeJoined(WorldPacket* data, ObjectGuid guid); //+ 0x00
|
||||
void MakeLeft(WorldPacket* data, ObjectGuid guid); //+ 0x01
|
||||
void MakeYouJoined(WorldPacket* data); //+ 0x02
|
||||
void MakeYouLeft(WorldPacket* data); //+ 0x03
|
||||
void MakeWrongPassword(WorldPacket* data); //? 0x04
|
||||
void MakeNotMember(WorldPacket* data); //? 0x05
|
||||
void MakeNotModerator(WorldPacket* data); //? 0x06
|
||||
void MakePasswordChanged(WorldPacket* data, ObjectGuid guid); //+ 0x07
|
||||
void MakeOwnerChanged(WorldPacket* data, ObjectGuid guid); //? 0x08
|
||||
void MakePlayerNotFound(WorldPacket* data, const std::string& name); //+ 0x09
|
||||
void MakeNotOwner(WorldPacket* data); //? 0x0A
|
||||
void MakeChannelOwner(WorldPacket* data); //? 0x0B
|
||||
void MakeModeChange(WorldPacket* data, ObjectGuid guid, uint8 oldflags);//+ 0x0C
|
||||
void MakeAnnouncementsOn(WorldPacket* data, ObjectGuid guid); //+ 0x0D
|
||||
void MakeAnnouncementsOff(WorldPacket* data, ObjectGuid guid); //+ 0x0E
|
||||
void MakeModerationOn(WorldPacket* data, ObjectGuid guid); //+ 0x0F
|
||||
void MakeModerationOff(WorldPacket* data, ObjectGuid guid); //+ 0x10
|
||||
void MakeMuted(WorldPacket* data); //? 0x11
|
||||
void MakePlayerKicked(WorldPacket* data, ObjectGuid bad, ObjectGuid good);//? 0x12
|
||||
void MakeBanned(WorldPacket* data); //? 0x13
|
||||
void MakePlayerBanned(WorldPacket* data, ObjectGuid bad, ObjectGuid good);//? 0x14
|
||||
void MakePlayerUnbanned(WorldPacket* data, ObjectGuid bad, ObjectGuid good);//? 0x15
|
||||
void MakePlayerNotBanned(WorldPacket* data, ObjectGuid guid); //? 0x16
|
||||
void MakePlayerAlreadyMember(WorldPacket* data, ObjectGuid guid); //+ 0x17
|
||||
void MakeInvite(WorldPacket* data, ObjectGuid guid); //? 0x18
|
||||
void MakeInviteWrongFaction(WorldPacket* data); //? 0x19
|
||||
void MakeWrongFaction(WorldPacket* data); //? 0x1A
|
||||
void MakeInvalidName(WorldPacket* data); //? 0x1B
|
||||
void MakeNotModerated(WorldPacket* data); //? 0x1C
|
||||
void MakePlayerInvited(WorldPacket* data, const std::string& name); //+ 0x1D
|
||||
void MakePlayerInviteBanned(WorldPacket* data, ObjectGuid guid); //? 0x1E
|
||||
void MakeThrottled(WorldPacket* data); //? 0x1F
|
||||
void MakeNotInArea(WorldPacket* data); //? 0x20
|
||||
void MakeNotInLfg(WorldPacket* data); //? 0x21
|
||||
void MakeVoiceOn(WorldPacket* data, ObjectGuid guid); //+ 0x22
|
||||
void MakeVoiceOff(WorldPacket* data, ObjectGuid guid); //+ 0x23
|
||||
private:
|
||||
// initial packet data (notify type and channel name)
|
||||
void MakeNotifyPacket(WorldPacket* data, uint8 notify_type);
|
||||
// type specific packet data
|
||||
void MakeJoined(WorldPacket* data, ObjectGuid guid); //+ 0x00
|
||||
void MakeLeft(WorldPacket* data, ObjectGuid guid); //+ 0x01
|
||||
void MakeYouJoined(WorldPacket* data); //+ 0x02
|
||||
void MakeYouLeft(WorldPacket* data); //+ 0x03
|
||||
void MakeWrongPassword(WorldPacket* data); //? 0x04
|
||||
void MakeNotMember(WorldPacket* data); //? 0x05
|
||||
void MakeNotModerator(WorldPacket* data); //? 0x06
|
||||
void MakePasswordChanged(WorldPacket* data, ObjectGuid guid); //+ 0x07
|
||||
void MakeOwnerChanged(WorldPacket* data, ObjectGuid guid); //? 0x08
|
||||
void MakePlayerNotFound(WorldPacket* data, const std::string& name); //+ 0x09
|
||||
void MakeNotOwner(WorldPacket* data); //? 0x0A
|
||||
void MakeChannelOwner(WorldPacket* data); //? 0x0B
|
||||
void MakeModeChange(WorldPacket* data, ObjectGuid guid, uint8 oldflags);//+ 0x0C
|
||||
void MakeAnnouncementsOn(WorldPacket* data, ObjectGuid guid); //+ 0x0D
|
||||
void MakeAnnouncementsOff(WorldPacket* data, ObjectGuid guid); //+ 0x0E
|
||||
void MakeModerationOn(WorldPacket* data, ObjectGuid guid); //+ 0x0F
|
||||
void MakeModerationOff(WorldPacket* data, ObjectGuid guid); //+ 0x10
|
||||
void MakeMuted(WorldPacket* data); //? 0x11
|
||||
void MakePlayerKicked(WorldPacket* data, ObjectGuid target, ObjectGuid source);//? 0x12
|
||||
void MakeBanned(WorldPacket* data); //? 0x13
|
||||
void MakePlayerBanned(WorldPacket* data, ObjectGuid target, ObjectGuid source);//? 0x14
|
||||
void MakePlayerUnbanned(WorldPacket* data, ObjectGuid target, ObjectGuid source);//? 0x15
|
||||
void MakePlayerNotBanned(WorldPacket* data, const std::string& name); //? 0x16
|
||||
void MakePlayerAlreadyMember(WorldPacket* data, ObjectGuid guid); //+ 0x17
|
||||
void MakeInvite(WorldPacket* data, ObjectGuid guid); //? 0x18
|
||||
void MakeInviteWrongFaction(WorldPacket* data); //? 0x19
|
||||
void MakeWrongFaction(WorldPacket* data); //? 0x1A
|
||||
void MakeInvalidName(WorldPacket* data); //? 0x1B
|
||||
void MakeNotModerated(WorldPacket* data); //? 0x1C
|
||||
void MakePlayerInvited(WorldPacket* data, const std::string& name); //+ 0x1D
|
||||
void MakePlayerInviteBanned(WorldPacket* data, const std::string& name);//? 0x1E
|
||||
void MakeThrottled(WorldPacket* data); //? 0x1F
|
||||
void MakeNotInArea(WorldPacket* data); //? 0x20
|
||||
void MakeNotInLfg(WorldPacket* data); //? 0x21
|
||||
void MakeVoiceOn(WorldPacket* data, ObjectGuid guid); //+ 0x22
|
||||
void MakeVoiceOff(WorldPacket* data, ObjectGuid guid); //+ 0x23
|
||||
|
||||
void SendToAll(WorldPacket* data, ObjectGuid p = ObjectGuid());
|
||||
void SendToOne(WorldPacket* data, ObjectGuid who);
|
||||
void SendToAll(WorldPacket* data, ObjectGuid guid = ObjectGuid());
|
||||
void SendToOne(WorldPacket* data, ObjectGuid who);
|
||||
|
||||
bool IsOn(ObjectGuid who) const { return m_players.find(who) != m_players.end(); }
|
||||
bool IsBanned(ObjectGuid guid) const { return m_banned.find(guid) != m_banned.end(); }
|
||||
bool IsOn(ObjectGuid who) const { return m_players.find(who) != m_players.end(); }
|
||||
bool IsBanned(ObjectGuid guid) const { return m_banned.find(guid) != m_banned.end(); }
|
||||
|
||||
uint8 GetPlayerFlags(ObjectGuid p) const
|
||||
{
|
||||
PlayerList::const_iterator p_itr = m_players.find(p);
|
||||
if (p_itr == m_players.end())
|
||||
return 0;
|
||||
uint8 GetPlayerFlags(ObjectGuid guid) const
|
||||
{
|
||||
PlayerList::const_iterator p_itr = m_players.find(guid);
|
||||
if (p_itr == m_players.end())
|
||||
return 0;
|
||||
|
||||
return p_itr->second.flags;
|
||||
}
|
||||
return p_itr->second.flags;
|
||||
}
|
||||
|
||||
void SetModerator(ObjectGuid p, bool set)
|
||||
{
|
||||
if (m_players[p].IsModerator() != set)
|
||||
{
|
||||
uint8 oldFlag = GetPlayerFlags(p);
|
||||
m_players[p].SetModerator(set);
|
||||
void SetModerator(ObjectGuid guid, bool set)
|
||||
{
|
||||
if (m_players[guid].IsModerator() != set)
|
||||
{
|
||||
uint8 oldFlag = GetPlayerFlags(guid);
|
||||
m_players[guid].SetModerator(set);
|
||||
|
||||
WorldPacket data;
|
||||
MakeModeChange(&data, p, oldFlag);
|
||||
SendToAll(&data);
|
||||
}
|
||||
}
|
||||
WorldPacket data;
|
||||
MakeModeChange(&data, guid, oldFlag);
|
||||
SendToAll(&data);
|
||||
}
|
||||
}
|
||||
|
||||
void SetMute(ObjectGuid p, bool set)
|
||||
{
|
||||
if (m_players[p].IsMuted() != set)
|
||||
{
|
||||
uint8 oldFlag = GetPlayerFlags(p);
|
||||
m_players[p].SetMuted(set);
|
||||
void SetMute(ObjectGuid guid, bool set)
|
||||
{
|
||||
if (m_players[guid].IsMuted() != set)
|
||||
{
|
||||
uint8 oldFlag = GetPlayerFlags(guid);
|
||||
m_players[guid].SetMuted(set);
|
||||
|
||||
WorldPacket data;
|
||||
MakeModeChange(&data, p, oldFlag);
|
||||
SendToAll(&data);
|
||||
}
|
||||
}
|
||||
WorldPacket data;
|
||||
MakeModeChange(&data, guid, oldFlag);
|
||||
SendToAll(&data);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_announce;
|
||||
bool m_moderate;
|
||||
std::string m_name;
|
||||
std::string m_password;
|
||||
uint8 m_flags;
|
||||
uint32 m_channelId;
|
||||
ObjectGuid m_ownerGuid;
|
||||
private:
|
||||
bool m_announce;
|
||||
bool m_moderate;
|
||||
std::string m_name;
|
||||
std::string m_password;
|
||||
uint8 m_flags;
|
||||
uint32 m_channelId;
|
||||
ObjectGuid m_ownerGuid;
|
||||
|
||||
typedef std::map<ObjectGuid, PlayerInfo> PlayerList;
|
||||
PlayerList m_players;
|
||||
GuidSet m_banned;
|
||||
typedef std::map<ObjectGuid, PlayerInfo> PlayerList;
|
||||
PlayerList m_players;
|
||||
GuidSet m_banned;
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -45,14 +45,15 @@ void WorldSession::HandleJoinChannelOpcode(WorldPacket& recvPacket)
|
|||
return;
|
||||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetJoinChannel(channelname, channel_id)) // channel id seems to be useless but must be checked for LFG
|
||||
chn->Join(_player->GetObjectGuid(), pass.c_str());
|
||||
if (Channel* chn = cMgr->GetJoinChannel(channelname, channel_id))
|
||||
chn->Join(_player, pass.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleLeaveChannelOpcode(WorldPacket& recvPacket)
|
||||
{
|
||||
DEBUG_LOG("WORLD: Received opcode %s (%u, 0x%X)", recvPacket.GetOpcodeName(), recvPacket.GetOpcode(), recvPacket.GetOpcode());
|
||||
// recvPacket.hexlike();
|
||||
|
||||
uint32 unk;
|
||||
std::string channelname;
|
||||
recvPacket >> unk; // channel id?
|
||||
|
|
@ -64,7 +65,7 @@ void WorldSession::HandleLeaveChannelOpcode(WorldPacket& recvPacket)
|
|||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
{
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->Leave(_player->GetObjectGuid(), true);
|
||||
chn->Leave(_player, true);
|
||||
cMgr->LeftChannel(channelname);
|
||||
}
|
||||
}
|
||||
|
|
@ -94,7 +95,7 @@ void WorldSession::HandleChannelPasswordOpcode(WorldPacket& recvPacket)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->Password(_player->GetObjectGuid(), pass.c_str());
|
||||
chn->Password(_player, pass.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelSetOwnerOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -126,7 +127,7 @@ void WorldSession::HandleChannelOwnerOpcode(WorldPacket& recvPacket)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->SendWhoOwner(_player->GetObjectGuid());
|
||||
chn->SendWhoOwner(_player);
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelModeratorOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -146,7 +147,7 @@ void WorldSession::HandleChannelModeratorOpcode(WorldPacket& recvPacket)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->SetModerator(_player->GetObjectGuid(), otp.c_str());
|
||||
chn->SetModerator(_player, otp.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelUnmoderatorOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -156,17 +157,17 @@ void WorldSession::HandleChannelUnmoderatorOpcode(WorldPacket& recvPacket)
|
|||
uint32 channelLen, nameLen;
|
||||
std::string channelname, otp;
|
||||
|
||||
nameLen = recvPacket.ReadBits(7);
|
||||
channelLen = recvPacket.ReadBits(8);
|
||||
channelname = recvPacket.ReadString(channelLen);
|
||||
nameLen = recvPacket.ReadBits(7);
|
||||
otp = recvPacket.ReadString(nameLen);
|
||||
channelname = recvPacket.ReadString(channelLen);
|
||||
|
||||
if (!normalizePlayerName(otp))
|
||||
return;
|
||||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->UnsetModerator(_player->GetObjectGuid(), otp.c_str());
|
||||
chn->UnsetMute(_player, otp.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelMuteOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -176,17 +177,17 @@ void WorldSession::HandleChannelMuteOpcode(WorldPacket& recvPacket)
|
|||
uint32 channelLen, nameLen;
|
||||
std::string channelname, otp;
|
||||
|
||||
channelLen = recvPacket.ReadBits(8);
|
||||
nameLen = recvPacket.ReadBits(7);
|
||||
channelname = recvPacket.ReadString(channelLen);
|
||||
channelLen = recvPacket.ReadBits(8);
|
||||
otp = recvPacket.ReadString(nameLen);
|
||||
channelname = recvPacket.ReadString(channelLen);
|
||||
|
||||
if (!normalizePlayerName(otp))
|
||||
return;
|
||||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->SetMute(_player->GetObjectGuid(), otp.c_str());
|
||||
chn->Invite(_player, otp.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelUnmuteOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -206,7 +207,7 @@ void WorldSession::HandleChannelUnmuteOpcode(WorldPacket& recvPacket)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->UnsetMute(_player->GetObjectGuid(), otp.c_str());
|
||||
chn->UnsetMute(_player, otp.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelInviteOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -226,7 +227,7 @@ void WorldSession::HandleChannelInviteOpcode(WorldPacket& recvPacket)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->Invite(_player->GetObjectGuid(), otp.c_str());
|
||||
chn->Invite(_player, otp.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelKickOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -246,7 +247,7 @@ void WorldSession::HandleChannelKickOpcode(WorldPacket& recvPacket)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->Kick(_player->GetObjectGuid(), otp.c_str());
|
||||
chn->Kick(_player, otp.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelBanOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -266,7 +267,7 @@ void WorldSession::HandleChannelBanOpcode(WorldPacket& recvPacket)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->Ban(_player->GetObjectGuid(), otp.c_str());
|
||||
chn->Ban(_player, otp.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelUnbanOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -286,7 +287,7 @@ void WorldSession::HandleChannelUnbanOpcode(WorldPacket& recvPacket)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->UnBan(_player->GetObjectGuid(), otp.c_str());
|
||||
chn->UnBan(_player, otp.c_str());
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelAnnouncementsOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -296,7 +297,7 @@ void WorldSession::HandleChannelAnnouncementsOpcode(WorldPacket& recvPacket)
|
|||
std::string channelname = recvPacket.ReadString(recvPacket.ReadBits(8));
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->Announce(_player->GetObjectGuid());
|
||||
chn->Announce(_player);
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelModerateOpcode(WorldPacket& recvPacket)
|
||||
|
|
@ -307,7 +308,7 @@ void WorldSession::HandleChannelModerateOpcode(WorldPacket& recvPacket)
|
|||
recvPacket >> channelname;
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channelname, _player))
|
||||
chn->Moderate(_player->GetObjectGuid());
|
||||
chn->Moderate(_player);
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelDisplayListQueryOpcode(WorldPacket& recvPacket)
|
||||
|
|
|
|||
|
|
@ -536,7 +536,8 @@ ChatCommand* ChatHandler::getCommandTable()
|
|||
{ "creature_ai_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAIScriptsCommand, "", NULL },
|
||||
{ "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL },
|
||||
{ "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL },
|
||||
{ "creature_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL },
|
||||
{ "creature_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL },
|
||||
{ "creature_template_classlevelstats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreaturesStatsCommand, "", nullptr },
|
||||
{ "creature_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand, "", NULL },
|
||||
{ "creature_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL },
|
||||
{ "creature_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL },
|
||||
|
|
@ -985,7 +986,7 @@ void ChatHandler::SendSysMessage(const char* str)
|
|||
|
||||
while (char* line = LineFromMessage(pos))
|
||||
{
|
||||
FillSystemMessageData(&data, line);
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, line, LANG_UNIVERSAL, CHAT_TAG_NONE, m_session->GetPlayer()->GetObjectGuid());
|
||||
m_session->SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
@ -1000,10 +1001,11 @@ void ChatHandler::SendGlobalSysMessage(const char* str)
|
|||
// need copy to prevent corruption by strtok call in LineFromMessage original string
|
||||
char* buf = mangos_strdup(str);
|
||||
char* pos = buf;
|
||||
ObjectGuid guid = m_session ? m_session->GetPlayer()->GetObjectGuid() : ObjectGuid();
|
||||
|
||||
while (char* line = LineFromMessage(pos))
|
||||
{
|
||||
FillSystemMessageData(&data, line);
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, line, LANG_UNIVERSAL, CHAT_TAG_NONE, guid);
|
||||
sWorld.SendGlobalMessage(&data);
|
||||
}
|
||||
|
||||
|
|
@ -2095,99 +2097,6 @@ bool ChatHandler::isValidChatMessage(const char* message)
|
|||
return validSequence == validSequenceIterator;
|
||||
}
|
||||
|
||||
// Note: target_guid used only in CHAT_MSG_WHISPER_INFORM mode (in this case channelName ignored)
|
||||
void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char* channelName, ObjectGuid targetGuid, const char* message, Unit* speaker, const char* addonPrefix /*= NULL*/)
|
||||
{
|
||||
uint32 messageLength = (message ? strlen(message) : 0) + 1;
|
||||
|
||||
data->Initialize(SMSG_MESSAGECHAT, 100); // guess size
|
||||
*data << uint8(type);
|
||||
if ((type != CHAT_MSG_CHANNEL && type != CHAT_MSG_WHISPER) || language == LANG_ADDON)
|
||||
*data << uint32(language);
|
||||
else
|
||||
*data << uint32(LANG_UNIVERSAL);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CHAT_MSG_SAY:
|
||||
case CHAT_MSG_PARTY:
|
||||
case CHAT_MSG_PARTY_LEADER:
|
||||
case CHAT_MSG_RAID:
|
||||
case CHAT_MSG_GUILD:
|
||||
case CHAT_MSG_OFFICER:
|
||||
case CHAT_MSG_YELL:
|
||||
case CHAT_MSG_WHISPER:
|
||||
case CHAT_MSG_CHANNEL:
|
||||
case CHAT_MSG_RAID_LEADER:
|
||||
case CHAT_MSG_RAID_WARNING:
|
||||
case CHAT_MSG_BG_SYSTEM_NEUTRAL:
|
||||
case CHAT_MSG_BG_SYSTEM_ALLIANCE:
|
||||
case CHAT_MSG_BG_SYSTEM_HORDE:
|
||||
case CHAT_MSG_BATTLEGROUND:
|
||||
case CHAT_MSG_BATTLEGROUND_LEADER:
|
||||
targetGuid = session ? session->GetPlayer()->GetObjectGuid() : ObjectGuid();
|
||||
break;
|
||||
case CHAT_MSG_MONSTER_SAY:
|
||||
case CHAT_MSG_MONSTER_PARTY:
|
||||
case CHAT_MSG_MONSTER_YELL:
|
||||
case CHAT_MSG_MONSTER_WHISPER:
|
||||
case CHAT_MSG_MONSTER_EMOTE:
|
||||
case CHAT_MSG_RAID_BOSS_WHISPER:
|
||||
case CHAT_MSG_RAID_BOSS_EMOTE:
|
||||
case CHAT_MSG_BATTLENET:
|
||||
{
|
||||
*data << ObjectGuid(speaker->GetObjectGuid());
|
||||
*data << uint32(0); // 2.1.0
|
||||
*data << uint32(strlen(speaker->GetName()) + 1);
|
||||
*data << speaker->GetName();
|
||||
ObjectGuid listener_guid;
|
||||
*data << listener_guid;
|
||||
if (listener_guid && !listener_guid.IsPlayer())
|
||||
{
|
||||
*data << uint32(1); // string listener_name_length
|
||||
*data << uint8(0); // string listener_name
|
||||
}
|
||||
*data << uint32(messageLength);
|
||||
*data << message;
|
||||
*data << uint8(0);
|
||||
|
||||
if (type == CHAT_MSG_RAID_BOSS_WHISPER || type == CHAT_MSG_RAID_BOSS_EMOTE)
|
||||
{
|
||||
*data << float(0.0f); // Added in 4.2.0, unk
|
||||
*data << uint8(0); // Added in 4.2.0, unk
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
if (type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_IGNORED && type != CHAT_MSG_DND && type != CHAT_MSG_AFK)
|
||||
targetGuid.Clear(); // only for CHAT_MSG_WHISPER_INFORM used original value target_guid
|
||||
break;
|
||||
}
|
||||
|
||||
*data << ObjectGuid(targetGuid); // there 0 for BG messages
|
||||
*data << uint32(0); // can be chat msg group or something
|
||||
|
||||
if (type == CHAT_MSG_CHANNEL)
|
||||
{
|
||||
MANGOS_ASSERT(channelName);
|
||||
*data << channelName;
|
||||
*data << ObjectGuid(targetGuid);
|
||||
}
|
||||
else if (type == CHAT_MSG_ADDON)
|
||||
{
|
||||
MANGOS_ASSERT(addonPrefix);
|
||||
*data << addonPrefix;
|
||||
}
|
||||
else
|
||||
*data << ObjectGuid(targetGuid);
|
||||
*data << uint32(messageLength);
|
||||
*data << message;
|
||||
if (session != 0 && type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_DND && type != CHAT_MSG_AFK)
|
||||
*data << uint8(session->GetPlayer()->GetChatTag());
|
||||
else
|
||||
*data << uint8(0);
|
||||
}
|
||||
|
||||
Player* ChatHandler::getSelectedPlayer()
|
||||
{
|
||||
if (!m_session)
|
||||
|
|
@ -3717,11 +3626,12 @@ void ChatHandler::LogCommand(char const* fullcmd)
|
|||
}
|
||||
|
||||
void ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg msgtype, char const* message, Language language /*= LANG_UNIVERSAL*/, ChatTagFlags chatTag /*= CHAT_TAG_NONE*/,
|
||||
ObjectGuid const& senderGuid /*= ObjectGuid()*/, char const* senderName /*= NULL*/,
|
||||
ObjectGuid const& targetGuid /*= ObjectGuid()*/, char const* targetName /*= NULL*/,
|
||||
char const* channelName /*= NULL*/)
|
||||
ObjectGuid const& senderGuid /*= ObjectGuid()*/, char const* senderName /*= nullptr*/,
|
||||
ObjectGuid const& targetGuid /*= ObjectGuid()*/, char const* targetName /*= nullptr*/,
|
||||
char const* channelName /*= nullptr*/, uint32 achievementId /*= 0*/, const char* addonPrefix /*= nullptr*/)
|
||||
{
|
||||
bool isGM = chatTag & CHAT_TAG_GM;
|
||||
bool isAchievement = false;
|
||||
|
||||
data.Initialize(isGM ? SMSG_GM_MESSAGECHAT : SMSG_MESSAGECHAT);
|
||||
data << uint8(msgtype);
|
||||
|
|
@ -3731,60 +3641,76 @@ void ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg msgtype, char const
|
|||
|
||||
switch (msgtype)
|
||||
{
|
||||
case CHAT_MSG_MONSTER_SAY:
|
||||
case CHAT_MSG_MONSTER_PARTY:
|
||||
case CHAT_MSG_MONSTER_YELL:
|
||||
case CHAT_MSG_MONSTER_WHISPER:
|
||||
case CHAT_MSG_RAID_BOSS_WHISPER:
|
||||
case CHAT_MSG_RAID_BOSS_EMOTE:
|
||||
case CHAT_MSG_MONSTER_EMOTE:
|
||||
MANGOS_ASSERT(senderName);
|
||||
data << uint32(strlen(senderName) + 1);
|
||||
data << senderName;
|
||||
data << ObjectGuid(targetGuid); // Unit Target
|
||||
if (targetGuid && !targetGuid.IsPlayer() && !targetGuid.IsPet())
|
||||
{
|
||||
data << uint32(strlen(targetName) + 1); // target name length
|
||||
data << targetName; // target name
|
||||
}
|
||||
MANGOS_ASSERT(message);
|
||||
data << uint32(strlen(message) + 1);
|
||||
data << message;
|
||||
data << uint8(chatTag);
|
||||
break;
|
||||
case CHAT_MSG_BG_SYSTEM_NEUTRAL:
|
||||
case CHAT_MSG_BG_SYSTEM_ALLIANCE:
|
||||
case CHAT_MSG_BG_SYSTEM_HORDE:
|
||||
data << ObjectGuid(targetGuid); // Unit Target
|
||||
if (targetGuid && !targetGuid.IsPlayer())
|
||||
{
|
||||
MANGOS_ASSERT(targetName);
|
||||
data << uint32(strlen(targetName) + 1); // target name length
|
||||
data << targetName; // target name
|
||||
}
|
||||
MANGOS_ASSERT(message);
|
||||
data << uint32(strlen(message) + 1);
|
||||
data << message;
|
||||
data << uint8(chatTag);
|
||||
break;
|
||||
default:
|
||||
if (msgtype == CHAT_MSG_CHANNEL)
|
||||
{
|
||||
MANGOS_ASSERT(channelName);
|
||||
data << channelName;
|
||||
}
|
||||
data << ObjectGuid(targetGuid);
|
||||
MANGOS_ASSERT(message);
|
||||
data << uint32(strlen(message) + 1);
|
||||
data << message;
|
||||
data << uint8(chatTag);
|
||||
if (isGM)
|
||||
{
|
||||
case CHAT_MSG_MONSTER_SAY:
|
||||
case CHAT_MSG_MONSTER_PARTY:
|
||||
case CHAT_MSG_MONSTER_YELL:
|
||||
case CHAT_MSG_MONSTER_WHISPER:
|
||||
case CHAT_MSG_MONSTER_EMOTE:
|
||||
case CHAT_MSG_RAID_BOSS_WHISPER:
|
||||
case CHAT_MSG_RAID_BOSS_EMOTE:
|
||||
case CHAT_MSG_BATTLENET:
|
||||
case CHAT_MSG_WHISPER_FOREIGN:
|
||||
MANGOS_ASSERT(senderName);
|
||||
data << uint32(strlen(senderName) + 1);
|
||||
data << senderName;
|
||||
}
|
||||
break;
|
||||
data << ObjectGuid(targetGuid); // Unit Target
|
||||
if (targetGuid && !targetGuid.IsPlayer() && !targetGuid.IsPet() && (msgtype != CHAT_MSG_WHISPER_FOREIGN))
|
||||
{
|
||||
data << uint32(strlen(targetName) + 1); // target name length
|
||||
data << targetName; // target name
|
||||
}
|
||||
break;
|
||||
case CHAT_MSG_BG_SYSTEM_NEUTRAL:
|
||||
case CHAT_MSG_BG_SYSTEM_ALLIANCE:
|
||||
case CHAT_MSG_BG_SYSTEM_HORDE:
|
||||
data << ObjectGuid(targetGuid); // Unit Target
|
||||
if (targetGuid && !targetGuid.IsPlayer())
|
||||
{
|
||||
MANGOS_ASSERT(targetName);
|
||||
data << uint32(strlen(targetName) + 1); // target name length
|
||||
data << targetName; // target name
|
||||
}
|
||||
break;
|
||||
case CHAT_MSG_ACHIEVEMENT:
|
||||
case CHAT_MSG_GUILD_ACHIEVEMENT:
|
||||
data << ObjectGuid(targetGuid); // Unit Target
|
||||
isAchievement = true;
|
||||
break;
|
||||
default:
|
||||
if (isGM)
|
||||
{
|
||||
MANGOS_ASSERT(senderName);
|
||||
data << uint32(strlen(senderName) + 1);
|
||||
data << senderName;
|
||||
}
|
||||
|
||||
if (msgtype == CHAT_MSG_CHANNEL)
|
||||
{
|
||||
MANGOS_ASSERT(channelName);
|
||||
data << channelName;
|
||||
data << ObjectGuid(targetGuid);
|
||||
}
|
||||
else if (msgtype == CHAT_MSG_ADDON)
|
||||
{
|
||||
MANGOS_ASSERT(addonPrefix);
|
||||
data << addonPrefix;
|
||||
}
|
||||
else
|
||||
data << ObjectGuid(targetGuid);
|
||||
break;
|
||||
}
|
||||
MANGOS_ASSERT(message);
|
||||
data << uint32(strlen(message) + 1);
|
||||
data << message;
|
||||
data << uint8(chatTag);
|
||||
|
||||
if (isAchievement)
|
||||
data << uint32(achievementId);
|
||||
|
||||
if (msgtype == CHAT_MSG_RAID_BOSS_WHISPER || msgtype == CHAT_MSG_RAID_BOSS_EMOTE)
|
||||
{
|
||||
data << float(0.0f); // Added in 4.2.0, unk
|
||||
data << uint8(0); // Added in 4.2.0, unk
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,12 +71,12 @@ enum ChatCommandSearchResult
|
|||
|
||||
enum PlayerChatTag
|
||||
{
|
||||
CHAT_TAG_NONE = 0,
|
||||
CHAT_TAG_AFK = 1,
|
||||
CHAT_TAG_DND = 2,
|
||||
CHAT_TAG_GM = 3,
|
||||
CHAT_TAG_COM = 4, // Commentator
|
||||
CHAT_TAG_DEV = 5, // Developer
|
||||
CHAT_TAG_NONE = 0x00,
|
||||
CHAT_TAG_AFK = 0x01,
|
||||
CHAT_TAG_DND = 0x02,
|
||||
CHAT_TAG_GM = 0x04,
|
||||
CHAT_TAG_COM = 0x08, // Commentator
|
||||
CHAT_TAG_DEV = 0x10, // Developer
|
||||
};
|
||||
typedef uint32 ChatTagFlags;
|
||||
|
||||
|
|
@ -87,23 +87,6 @@ class ChatHandler
|
|||
explicit ChatHandler(Player* player);
|
||||
~ChatHandler();
|
||||
|
||||
static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char* channelName, ObjectGuid targetGuid, const char* message, Unit* speaker, const char* addonPrefix = NULL);
|
||||
|
||||
static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, ObjectGuid targetGuid, const char* message)
|
||||
{
|
||||
FillMessageData(data, session, type, language, NULL, targetGuid, message, NULL);
|
||||
}
|
||||
|
||||
static void FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char* message)
|
||||
{
|
||||
FillMessageData(data, session, type, language, NULL, ObjectGuid(), message, NULL);
|
||||
}
|
||||
|
||||
void FillSystemMessageData(WorldPacket* data, const char* message)
|
||||
{
|
||||
FillMessageData(data, m_session, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, ObjectGuid(), message);
|
||||
}
|
||||
|
||||
static char* LineFromMessage(char*& pos) { char* start = strtok(pos, "\n"); pos = NULL; return start; }
|
||||
|
||||
// function with different implementation for chat/console
|
||||
|
|
@ -140,12 +123,13 @@ class ChatHandler
|
|||
* \param ObjectGuid const& targetGuid : Often null, but needed for type *MONSTER* or *BATTLENET or *BATTLEGROUND* or *ACHIEVEMENT
|
||||
* \param char const* targetName : Often null, but needed for type *MONSTER* or *BATTLENET or *BATTLEGROUND*
|
||||
* \param char const* channelName : Required only for CHAT_MSG_CHANNEL
|
||||
* \param uint32 achievementId : Required only for *ACHIEVEMENT
|
||||
* \param const char* addonPrefix : Required only for *CHAT_MSG_ADDON
|
||||
**/
|
||||
static void BuildChatPacket(
|
||||
WorldPacket& data, ChatMsg msgtype, char const* message, Language language = LANG_UNIVERSAL, ChatTagFlags chatTag = CHAT_TAG_NONE,
|
||||
static void ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg msgtype, char const* message, Language language = LANG_UNIVERSAL, ChatTagFlags chatTag = CHAT_TAG_NONE,
|
||||
ObjectGuid const& senderGuid = ObjectGuid(), char const* senderName = NULL,
|
||||
ObjectGuid const& targetGuid = ObjectGuid(), char const* targetName = NULL,
|
||||
char const* channelName = NULL);
|
||||
char const* channelName = NULL, uint32 achievementId = 0, const char* addonPrefix = NULL);
|
||||
|
||||
protected:
|
||||
explicit ChatHandler() : m_session(NULL) {} // for CLI subclass
|
||||
|
|
@ -450,6 +434,7 @@ class ChatHandler
|
|||
bool HandleReloadAreaTriggerTavernCommand(char* args);
|
||||
bool HandleReloadAreaTriggerTeleportCommand(char* args);
|
||||
bool HandleReloadBattleEventCommand(char* args);
|
||||
bool HandleReloadCreaturesStatsCommand(char* args);
|
||||
bool HandleReloadCommandCommand(char* args);
|
||||
bool HandleReloadConditionsCommand(char* args);
|
||||
bool HandleReloadCreatureQuestRelationsCommand(char* args);
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
return;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, type, lang, msg.c_str());
|
||||
ChatHandler::BuildChatPacket(data, ChatMsg(type), msg.c_str(), Language(lang), _player->GetChatTag(), _player->GetObjectGuid(), _player->GetName());
|
||||
group->BroadcastPacket(&data, false, group->GetMemberGroup(GetPlayer()->GetObjectGuid()));
|
||||
|
||||
break;
|
||||
|
|
@ -364,7 +364,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
}
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID, lang, msg.c_str());
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID, msg.c_str(), Language(lang), _player->GetChatTag(), _player->GetObjectGuid(), _player->GetName());
|
||||
group->BroadcastPacket(&data, false);
|
||||
} break;
|
||||
case CHAT_MSG_RAID_LEADER:
|
||||
|
|
@ -394,7 +394,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
}
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_LEADER, lang, msg.c_str());
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_LEADER, msg.c_str(), Language(lang), _player->GetChatTag(), _player->GetObjectGuid(), _player->GetName());
|
||||
group->BroadcastPacket(&data, false);
|
||||
} break;
|
||||
|
||||
|
|
@ -416,7 +416,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
|
||||
WorldPacket data;
|
||||
// in battleground, raid warning is sent only to players in battleground - code is ok
|
||||
ChatHandler::FillMessageData(&data, this, CHAT_MSG_RAID_WARNING, lang, msg.c_str());
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_RAID_WARNING, msg.c_str(), Language(lang), _player->GetChatTag(), _player->GetObjectGuid(), _player->GetName());
|
||||
group->BroadcastPacket(&data, false);
|
||||
} break;
|
||||
|
||||
|
|
@ -437,7 +437,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
return;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND, lang, msg.c_str());
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND, msg.c_str(), Language(lang), _player->GetChatTag(), _player->GetObjectGuid(), _player->GetName());
|
||||
group->BroadcastPacket(&data, false);
|
||||
} break;
|
||||
|
||||
|
|
@ -458,7 +458,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
return;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, CHAT_MSG_BATTLEGROUND_LEADER, lang, msg.c_str());
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_BATTLEGROUND_LEADER, msg.c_str(), Language(lang), _player->GetChatTag(), _player->GetObjectGuid(), _player->GetName());
|
||||
group->BroadcastPacket(&data, false);
|
||||
} break;
|
||||
|
||||
|
|
@ -478,7 +478,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
|
||||
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
|
||||
if (Channel* chn = cMgr->GetChannel(channel, _player))
|
||||
chn->Say(_player->GetObjectGuid(), msg.c_str(), lang);
|
||||
chn->Say(_player, msg.c_str(), lang);
|
||||
} break;
|
||||
|
||||
case CHAT_MSG_AFK:
|
||||
|
|
@ -539,7 +539,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recv_data)
|
|||
|
||||
void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
uint32 type;
|
||||
ChatMsg type;
|
||||
|
||||
switch (recv_data.GetOpcode())
|
||||
{
|
||||
|
|
@ -573,7 +573,7 @@ void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recv_data)
|
|||
return;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, type, LANG_ADDON, "", ObjectGuid(), msg.c_str(), NULL);
|
||||
ChatHandler::BuildChatPacket(data, type, msg.c_str(), LANG_ADDON);
|
||||
group->BroadcastPacket(&data, false);
|
||||
break;
|
||||
}
|
||||
|
|
@ -618,7 +618,9 @@ void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recv_data)
|
|||
if (!receiver)
|
||||
break;
|
||||
|
||||
_player->WhisperAddon(msg, prefix, receiver->GetObjectGuid());
|
||||
WorldPacket data;
|
||||
ChatHandler::BuildChatPacket(data, type, msg.c_str(), LANG_UNIVERSAL, CHAT_TAG_NONE, ObjectGuid(), NULL, receiver->GetObjectGuid(), targetName.c_str(), NULL, 0, prefix.c_str());
|
||||
_player->GetSession()->SendPacket(&data);
|
||||
break;
|
||||
}
|
||||
// Messages sent to "RAID" while in a party will get delivered to "PARTY"
|
||||
|
|
@ -635,7 +637,7 @@ void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recv_data)
|
|||
break;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, type, LANG_ADDON, "", ObjectGuid(), msg.c_str(), NULL, prefix.c_str());
|
||||
ChatHandler::BuildChatPacket(data, type, msg.c_str(), LANG_ADDON, CHAT_TAG_NONE, ObjectGuid(), NULL, ObjectGuid(), NULL, NULL, 0, prefix.c_str());
|
||||
group->BroadcastPacket(&data, false, group->GetMemberGroup(_player->GetObjectGuid()));
|
||||
break;
|
||||
}
|
||||
|
|
@ -768,7 +770,7 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data)
|
|||
return;
|
||||
|
||||
WorldPacket data;
|
||||
ChatHandler::FillMessageData(&data, this, CHAT_MSG_IGNORED, LANG_UNIVERSAL, NULL, GetPlayer()->GetObjectGuid(), GetPlayer()->GetName(), NULL);
|
||||
ChatHandler::BuildChatPacket(data, CHAT_MSG_IGNORED, _player->GetName(), LANG_UNIVERSAL, CHAT_TAG_NONE, _player->GetObjectGuid());
|
||||
player->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@
|
|||
|
||||
class WorldSession;
|
||||
|
||||
#define GOSSIP_MAX_MENU_ITEMS 64 // client supported items unknown, but provided number must be enough
|
||||
#define DEFAULT_GOSSIP_MESSAGE 0xffffff
|
||||
#define GOSSIP_MAX_MENU_ITEMS 32 // client supports showing max 32 items
|
||||
#define DEFAULT_GOSSIP_MESSAGE 0xffffff
|
||||
|
||||
enum Gossip_Option
|
||||
{
|
||||
|
|
|
|||
|
|
@ -657,7 +657,7 @@ void MaNGOS::LocalizedPacketDo<Builder>::operator()(Player* p)
|
|||
if (i_data_cache.size() < cache_idx + 1)
|
||||
i_data_cache.resize(cache_idx + 1);
|
||||
|
||||
data = new WorldPacket(SMSG_MESSAGECHAT, 200);
|
||||
data = new WorldPacket();
|
||||
|
||||
i_builder(*data, loc_idx);
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "BattleGround/BattleGroundMgr.h"
|
||||
#include "Weather.h"
|
||||
#include "Calendar.h"
|
||||
#include "Chat.h"
|
||||
#ifdef ENABLE_ELUNA
|
||||
#include "LuaEngine.h"
|
||||
#endif /* ENABLE_ELUNA */
|
||||
|
|
@ -1970,8 +1971,8 @@ uint32 Map::GenerateLocalLowGuid(HighGuid guidhigh)
|
|||
*/
|
||||
class StaticMonsterChatBuilder
|
||||
{
|
||||
public:
|
||||
StaticMonsterChatBuilder(CreatureInfo const* cInfo, ChatMsg msgtype, int32 textId, uint32 language, Unit const* target, uint32 senderLowGuid = 0)
|
||||
public:
|
||||
StaticMonsterChatBuilder(CreatureInfo const* cInfo, ChatMsg msgtype, int32 textId, Language language, Unit const* 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
|
||||
|
|
@ -1984,7 +1985,8 @@ class StaticMonsterChatBuilder
|
|||
char const* nameForLocale = i_cInfo->Name;
|
||||
sObjectMgr.GetCreatureLocaleStrings(i_cInfo->Entry, loc_idx, &nameForLocale);
|
||||
|
||||
WorldObject::BuildMonsterChat(&data, i_senderGuid, i_msgtype, text, i_language, nameForLocale, i_target ? i_target->GetObjectGuid() : ObjectGuid(), i_target ? i_target->GetNameForLocaleIdx(loc_idx) : "");
|
||||
ChatHandler::BuildChatPacket(data, i_msgtype, text, i_language, CHAT_TAG_NONE, i_senderGuid, nameForLocale, i_target ? i_target->GetObjectGuid() : ObjectGuid(),
|
||||
i_target ? i_target->GetNameForLocaleIdx(loc_idx) : "");
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -1992,7 +1994,7 @@ class StaticMonsterChatBuilder
|
|||
CreatureInfo const* i_cInfo;
|
||||
ChatMsg i_msgtype;
|
||||
int32 i_textId;
|
||||
uint32 i_language;
|
||||
Language i_language;
|
||||
Unit const* i_target;
|
||||
};
|
||||
|
||||
|
|
@ -2126,3 +2128,178 @@ bool Map::ContainsGameObjectModel(const GameObjectModel& mdl) const
|
|||
{
|
||||
return m_dyn_tree.contains(mdl);
|
||||
}
|
||||
// This will generate a random point to all directions in water for the provided point in radius range.
|
||||
bool Map::GetRandomPointUnderWater(uint32 phaseMask, float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status)
|
||||
{
|
||||
const float angle = rand_norm_f() * (M_PI_F * 2.0f);
|
||||
const float range = rand_norm_f() * radius;
|
||||
|
||||
float i_x = x + range * cos(angle);
|
||||
float i_y = y + range * sin(angle);
|
||||
|
||||
// get real ground of new point
|
||||
// the code consider cylinder instead of sphere for possible z
|
||||
float ground = GetHeight(phaseMask, i_x, i_y, z);
|
||||
if (ground > INVALID_HEIGHT) // GetHeight can fail
|
||||
{
|
||||
float min_z = z - 0.7f * radius; // 0.7 to have a bit a "flat" cylinder, TODO which value looks nicest
|
||||
if (min_z < ground)
|
||||
min_z = ground + 0.5f; // Get some space to prevent under map
|
||||
|
||||
float liquidLevel = liquid_status.level - 2.0f; // just to make the generated point is in water and not on surface or a bit above
|
||||
|
||||
// if not enough space to fit the creature better is to return from here
|
||||
if (min_z > liquidLevel)
|
||||
return false;
|
||||
|
||||
float max_z = std::max(z + 0.7f * radius, min_z);
|
||||
max_z = std::min(max_z, liquidLevel);
|
||||
x = i_x;
|
||||
y = i_y;
|
||||
z = min_z + rand_norm_f() * (max_z - min_z);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This will generate a random point to all directions in air for the provided point in radius range.
|
||||
bool Map::GetRandomPointInTheAir(uint32 phaseMask, float& x, float& y, float& z, float radius)
|
||||
{
|
||||
const float angle = rand_norm_f() * (M_PI_F * 2.0f);
|
||||
const float range = rand_norm_f() * radius;
|
||||
|
||||
float i_x = x + range * cos(angle);
|
||||
float i_y = y + range * sin(angle);
|
||||
|
||||
// get real ground of new point
|
||||
// the code consider cylinder instead of sphere for possible z
|
||||
float ground = GetHeight(phaseMask, i_x, i_y, z);
|
||||
if (ground > INVALID_HEIGHT) // GetHeight can fail
|
||||
{
|
||||
float min_z = z - 0.7f * radius; // 0.7 to have a bit a "flat" cylinder, TODO which value looks nicest
|
||||
if (min_z < ground)
|
||||
min_z = ground + 2.5f; // Get some space to prevent landing
|
||||
float max_z = std::max(z + 0.7f * radius, min_z);
|
||||
x = i_x;
|
||||
y = i_y;
|
||||
z = min_z + rand_norm_f() * (max_z - min_z);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// supposed to be used for not big radius, usually less than 20.0f
|
||||
bool Map::GetReachableRandomPointOnGround(uint32 phaseMask, float& x, float& y, float& z, float radius)
|
||||
{
|
||||
// Generate a random range and direction for the new point
|
||||
const float angle = rand_norm_f() * (M_PI_F * 2.0f);
|
||||
const float range = rand_norm_f() * radius;
|
||||
|
||||
float i_x = x + range * cos(angle);
|
||||
float i_y = y + range * sin(angle);
|
||||
float i_z = z + 1.0f;
|
||||
|
||||
GetHitPosition(x, y, z + 1.0f, i_x, i_y, i_z, phaseMask, -0.5f);
|
||||
i_z = z; // reset i_z to z value to avoid too much difference from original point before GetHeightInRange
|
||||
// commented out, as this function has not been defined anywhere (previous cores or other repos)
|
||||
// if (!GetHeightInRange(phaseMask, i_x, i_y, i_z)) // GetHeight can fail
|
||||
// return false;
|
||||
|
||||
// here we have a valid position but the point can have a big Z in some case
|
||||
// next code will check angle from 2 points
|
||||
// c
|
||||
// /|
|
||||
// / |
|
||||
// b/__|a
|
||||
|
||||
// project vector to get only positive value
|
||||
float ab = fabs(x - i_x);
|
||||
float ac = fabs(z - i_z);
|
||||
|
||||
// slope represented by c angle (in radian)
|
||||
float slope = 0;
|
||||
const float MAX_SLOPE_IN_RADIAN = 50.0f / 180.0f * M_PI_F; // 50(degree) max seem best value for walkable slope
|
||||
|
||||
// check ab vector to avoid divide by 0
|
||||
if (ab > 0.0f)
|
||||
{
|
||||
// compute c angle and convert it from radian to degree
|
||||
slope = atan(ac / ab);
|
||||
if (slope < MAX_SLOPE_IN_RADIAN)
|
||||
{
|
||||
x = i_x;
|
||||
y = i_y;
|
||||
z = i_z;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get random point by handling different situation depending of if the unit is flying/swimming/walking
|
||||
bool Map::GetReachableRandomPosition(Unit* unit, float& x, float& y, float& z, float radius)
|
||||
{
|
||||
|
||||
float i_x = x;
|
||||
float i_y = y;
|
||||
float i_z = z;
|
||||
|
||||
bool newDestAssigned = false; // used to check if new random destination is found
|
||||
|
||||
bool isFlying = false;
|
||||
bool isSwimming = true;
|
||||
switch (unit->GetTypeId())
|
||||
{
|
||||
case TYPEID_PLAYER:
|
||||
isFlying = static_cast<Player*>(unit)->IsFlying();
|
||||
break;
|
||||
case TYPEID_UNIT:
|
||||
isFlying = static_cast<Creature*>(unit)->IsFlying();
|
||||
isSwimming = static_cast<Creature*>(unit)->IsSwimming();
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Map::GetReachableRandomPosition> Unsupported unit type is passed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (radius < 0.1f)
|
||||
{
|
||||
sLog.outError("Map::GetReachableRandomPosition> Unsupported unit type is passed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isFlying)
|
||||
{
|
||||
newDestAssigned = GetRandomPointInTheAir(unit->GetPhaseMask(), i_x, i_y, i_z, radius);
|
||||
/*if (newDestAssigned)
|
||||
sLog.outString("Generating air random point for %s", GetGuidStr().c_str());*/
|
||||
}
|
||||
else
|
||||
{
|
||||
GridMapLiquidData liquid_status;
|
||||
GridMapLiquidStatus res = m_TerrainData->getLiquidStatus(i_x, i_y, i_z, MAP_ALL_LIQUIDS, &liquid_status);
|
||||
if (isSwimming && (res & (LIQUID_MAP_UNDER_WATER | LIQUID_MAP_IN_WATER)))
|
||||
{
|
||||
newDestAssigned = GetRandomPointUnderWater(unit->GetPhaseMask(), i_x, i_y, i_z, radius, liquid_status);
|
||||
/*if (newDestAssigned)
|
||||
sLog.outString("Generating swim random point for %s", GetGuidStr().c_str());*/
|
||||
}
|
||||
else
|
||||
{
|
||||
newDestAssigned = GetReachableRandomPointOnGround(unit->GetPhaseMask(), i_x, i_y, i_z, radius);
|
||||
/*if (newDestAssigned)
|
||||
sLog.outString("Generating ground random point for %s", GetGuidStr().c_str());*/
|
||||
}
|
||||
}
|
||||
|
||||
if (newDestAssigned)
|
||||
{
|
||||
x = i_x;
|
||||
y = i_y;
|
||||
z = i_z;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -309,9 +309,9 @@ class Map : public GridRefManager<NGridType>
|
|||
|
||||
// Random on map generation
|
||||
bool GetReachableRandomPosition(Unit* unit, float& x, float& y, float& z, float radius);
|
||||
bool GetReachableRandomPointOnGround(float& x, float& y, float& z, float radius);
|
||||
bool GetRandomPointInTheAir(float& x, float& y, float& z, float radius);
|
||||
bool GetRandomPointUnderWater(float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status);
|
||||
bool GetReachableRandomPointOnGround(uint32 phaseMask, float& x, float& y, float& z, float radius);
|
||||
bool GetRandomPointInTheAir(uint32 phaseMask, float& x, float& y, float& z, float radius);
|
||||
bool GetRandomPointUnderWater(uint32 phaseMask, float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status);
|
||||
|
||||
private:
|
||||
void LoadMapAndVMap(int gx, int gy);
|
||||
|
|
|
|||
|
|
@ -1565,7 +1565,7 @@ void WorldSession::HandleRequestHotfix(WorldPacket& recv_data)
|
|||
count = recv_data.ReadBits(23);
|
||||
|
||||
std::vector<ObjectGuid> guids;
|
||||
guids.reserve(count);
|
||||
guids.resize(count);
|
||||
|
||||
for (uint32 i = 0; i < count; ++i)
|
||||
recv_data.ReadGuidMask<0, 4, 7, 2, 5, 3, 6, 1>(guids[i]);
|
||||
|
|
|
|||
|
|
@ -178,12 +178,12 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
|
|||
}
|
||||
|
||||
uint32 maxcount = (cSpells ? cSpells->spellList.size() : 0) + (tSpells ? tSpells->spellList.size() : 0);
|
||||
uint32 trainer_type = cSpells && cSpells->trainerType ? cSpells->trainerType : (tSpells ? tSpells->trainerType : 0);
|
||||
uint32 TrainerType = cSpells && cSpells->trainerType ? cSpells->trainerType : (tSpells ? tSpells->trainerType : 0);
|
||||
|
||||
WorldPacket data(SMSG_TRAINER_LIST, 8 + 4 + 4 + maxcount * 38 + strTitle.size() + 1);
|
||||
data << ObjectGuid(guid);
|
||||
data << uint32(trainer_type);
|
||||
data << uint32(ci->trainerId);
|
||||
data << uint32(TrainerType);
|
||||
data << uint32(ci->TrainerTemplateId);
|
||||
|
||||
size_t count_pos = data.wpos();
|
||||
data << uint32(maxcount);
|
||||
|
|
@ -243,9 +243,9 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
|
|||
void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
ObjectGuid guid;
|
||||
uint32 spellId = 0, trainerId = 0;
|
||||
uint32 spellId = 0, TrainerTemplateId = 0;
|
||||
|
||||
recv_data >> guid >> trainerId >> spellId;
|
||||
recv_data >> guid >> TrainerTemplateId >> spellId;
|
||||
DEBUG_LOG("WORLD: Received opcode CMSG_TRAINER_BUY_SPELL Trainer: %s, learn spell id is: %u", guid.GetString().c_str(), spellId);
|
||||
|
||||
Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER);
|
||||
|
|
|
|||
|
|
@ -182,8 +182,8 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recv_data)
|
|||
data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
|
||||
data << uint32(ci->CreatureTypeFlags); // flags
|
||||
data << uint32(0); // unk
|
||||
data << uint32(ci->type); // CreatureType.dbc
|
||||
data << uint32(ci->family); // CreatureFamily.dbc
|
||||
data << uint32(ci->CreatureType); // CreatureType.dbc
|
||||
data << uint32(ci->Family); // CreatureFamily.dbc
|
||||
data << uint32(ci->Rank); // Creature Rank (elite, boss, etc)
|
||||
data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit
|
||||
data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit
|
||||
|
|
@ -191,12 +191,12 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recv_data)
|
|||
for (int i = 0; i < MAX_CREATURE_MODEL; ++i)
|
||||
data << uint32(ci->ModelId[i]);
|
||||
|
||||
data << float(ci->healthModifier); // health modifier
|
||||
data << float(ci->powerModifier); // power modifier
|
||||
data << float(ci->HealthMultiplier); // health modifier
|
||||
data << float(ci->PowerMultiplier); // power modifier
|
||||
data << uint8(ci->RacialLeader);
|
||||
for (uint32 i = 0; i < 6; ++i)
|
||||
data << uint32(ci->questItems[i]); // itemId[6], quest drop
|
||||
data << uint32(ci->movementId); // CreatureMovementInfo.dbc
|
||||
data << uint32(ci->QuestItems[i]); // itemId[6], quest drop
|
||||
data << uint32(ci->MovementTemplateId); // CreatureMovementInfo.dbc
|
||||
data << uint32(0); //unk
|
||||
SendPacket(&data);
|
||||
DEBUG_LOG("WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
|
||||
|
|
|
|||
|
|
@ -1226,7 +1226,7 @@ bool ScriptAction::HandleScriptStep()
|
|||
for (int i = 0; i < MAX_TEXT_ID; ++i)
|
||||
{
|
||||
if (!m_script->textId[i])
|
||||
{ break; }
|
||||
break;
|
||||
emotes.push_back(uint32(m_script->textId[i]));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3384,7 +3384,7 @@ void Spell::cast(bool skipCheck)
|
|||
// Hand of Reckoning
|
||||
else if (m_spellInfo->Id == 62124)
|
||||
{
|
||||
if (m_targets.getUnitTarget() && m_targets.getUnitTarget()->getVictim() != m_caster)
|
||||
if (!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTargetGuid() != m_caster->GetObjectGuid())
|
||||
AddPrecastSpell(67485); // Hand of Rekoning (no typos in name ;) )
|
||||
}
|
||||
// Divine Shield, Divine Protection or Hand of Protection
|
||||
|
|
@ -7972,6 +7972,7 @@ void Spell::GetSpellRangeAndRadius(SpellEffectEntry const* spellEffect, float& r
|
|||
case 44869: // Spectral Blast (SWP, Kalecgos)
|
||||
case 45391: // Summon Demonic Vapor (SWP, Felmyst)
|
||||
case 45785: // Sinister Reflection Clone (SWP, Kil'jaeden)
|
||||
case 45863: // Cosmetic - Incinerate to Random Target (Borean Tundra)
|
||||
case 45892: // Sinister Reflection (SWP, Kil'jaeden)
|
||||
case 45976: // Open Portal (SWP, M'uru)
|
||||
case 46372: // Ice Spear Target Picker (Slave Pens, Ahune)
|
||||
|
|
@ -8000,15 +8001,15 @@ void Spell::GetSpellRangeAndRadius(SpellEffectEntry const* spellEffect, float& r
|
|||
case 62797: // Storm Cloud (Ulduar, Hodir)
|
||||
case 63018: // Searing Light (Ulduar, XT-002)
|
||||
case 63024: // Gravity Bomb (Ulduar, XT-002)
|
||||
case 63387: // Rapid Burst
|
||||
case 63545: // Icicle (Ulduar, Hodir)
|
||||
case 63795: // Psychosis (Ulduar, Yogg-Saron)
|
||||
case 63820: // Summon Scrap Bot Trigger (Ulduar, Mimiron) use for Scrap Bots, hits npc 33856
|
||||
case 64218: // Overcharge (VoA, Emalon)
|
||||
case 64234: // Gravity Bomb (h) (Ulduar, XT-002)
|
||||
case 64402: // Rocket Strike (Ulduar, Mimiron)
|
||||
case 64425: // Summon Scrap Bot Trigger (Ulduar, Mimiron) use for Assault Bots, hits npc 33856
|
||||
case 64531: // Rapid Burst (h)
|
||||
case 64543: // Melt Ice (Ulduar, Hodir)
|
||||
case 64623: // Frost Bomb (Ulduar, Mimiron)
|
||||
case 65121: // Searing Light (h) (Ulduar, XT-002)
|
||||
case 65301: // Psychosis (Ulduar, Yogg-Saron)
|
||||
case 65872: // Pursuing Spikes (ToCrusader, Anub'arak)
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ enum AuraType
|
|||
SPELL_AURA_297 = 297,
|
||||
SPELL_AURA_298 = 298,
|
||||
SPELL_AURA_299 = 299,
|
||||
SPELL_AURA_300 = 300,
|
||||
SPELL_AURA_SHARE_DAMAGE_PCT = 300,
|
||||
SPELL_AURA_HEAL_ABSORB = 301,
|
||||
SPELL_AURA_302 = 302,
|
||||
SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE = 303,
|
||||
|
|
|
|||
|
|
@ -1457,15 +1457,15 @@ void Aura::TriggerSpell()
|
|||
// move loot to player inventory and despawn target
|
||||
if (caster->GetTypeId() == TYPEID_PLAYER &&
|
||||
triggerTarget->GetTypeId() == TYPEID_UNIT &&
|
||||
((Creature*)triggerTarget)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
|
||||
((Creature*)triggerTarget)->GetCreatureInfo()->CreatureType == CREATURE_TYPE_GAS_CLOUD)
|
||||
{
|
||||
Player* player = (Player*)caster;
|
||||
Creature* creature = (Creature*)triggerTarget;
|
||||
// missing lootid has been reported on startup - just return
|
||||
if (!creature->GetCreatureInfo()->SkinLootId)
|
||||
// missing Lootid has been reported on startup - just return
|
||||
if (!creature->GetCreatureInfo()->SkinningLootId)
|
||||
return;
|
||||
|
||||
player->AutoStoreLoot(creature, creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, true);
|
||||
player->AutoStoreLoot(creature, creature->GetCreatureInfo()->SkinningLootId, LootTemplates_Skinning, true);
|
||||
|
||||
creature->ForcedDespawn();
|
||||
}
|
||||
|
|
@ -2378,9 +2378,14 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
|||
case 54729: // Winged Steed of the Ebon Blade
|
||||
Spell::SelectMountByAreaAndSkill(target, GetSpellProto(), 0, 0, 54726, 54727, 0);
|
||||
return;
|
||||
case 58600: // Restricted Flight Area
|
||||
target->MonsterWhisper(LANG_NO_FLY_ZONE, target, true);
|
||||
case 58600: // Restricted Flight Area
|
||||
{
|
||||
if (!target || target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
const char* text = sObjectMgr.GetMangosString(LANG_NO_FLY_ZONE, ((Player*)target)->GetSession()->GetSessionDbLocaleIndex());
|
||||
target->MonsterWhisper(text, target, true);
|
||||
return;
|
||||
}
|
||||
case 61187: // Twilight Shift (single target)
|
||||
case 61190: // Twilight Shift (many targets)
|
||||
target->RemoveAurasDueToSpell(57620);
|
||||
|
|
@ -2936,18 +2941,18 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
|||
|
||||
return;
|
||||
}
|
||||
case 64398: // Summon Scrap Bot (Ulduar, Mimiron) - for Scrap Bots
|
||||
case 64426: // Summon Scrap Bot (Ulduar, Mimiron) - for Assault Bots
|
||||
case 64621: // Summon Fire Bot (Ulduar, Mimiron)
|
||||
case 62483: // Stonebark's Essence Channel
|
||||
case 62484: // Ironbranch's Essence Channel
|
||||
case 62485: // Brightleaf's Essence Channel
|
||||
case 65587: // Brightleaf's Essence Channel (h)
|
||||
case 65588: // Ironbranch's Essence Channel (h)
|
||||
case 65589: // Stonebark's Essence Channel (h)
|
||||
{
|
||||
uint32 triggerSpell = 0;
|
||||
switch (GetId())
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
case 64398: triggerSpell = 63819; break;
|
||||
case 64426: triggerSpell = 64427; break;
|
||||
case 64621: triggerSpell = 64622; break;
|
||||
if (m_removeMode == AURA_REMOVE_BY_EXPIRE)
|
||||
caster->CastSpell(caster, 62467, true);
|
||||
}
|
||||
target->CastSpell(target, triggerSpell, false);
|
||||
return;
|
||||
}
|
||||
case 68839: // Corrupt Soul
|
||||
|
|
@ -4487,15 +4492,15 @@ void Aura::HandleModCharm(bool apply, bool Real)
|
|||
if (caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
|
||||
{
|
||||
CreatureInfo const* cinfo = ((Creature*)target)->GetCreatureInfo();
|
||||
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
||||
if (cinfo && cinfo->CreatureType == CREATURE_TYPE_DEMON)
|
||||
{
|
||||
// creature with pet number expected have class set
|
||||
if (target->GetByteValue(UNIT_FIELD_BYTES_0, 1) == 0)
|
||||
{
|
||||
if (cinfo->unit_class == 0)
|
||||
sLog.outErrorDb("Creature (Entry: %u) have unit_class = 0 but used in charmed spell, that will be result client crash.", cinfo->Entry);
|
||||
if (cinfo->UnitClass == 0)
|
||||
sLog.outErrorDb("Creature (Entry: %u) have UnitClass = 0 but used in charmed spell, that will be result client crash.", cinfo->Entry);
|
||||
else
|
||||
sLog.outError("Creature (Entry: %u) have unit_class = %u but at charming have class 0!!! that will be result client crash.", cinfo->Entry, cinfo->unit_class);
|
||||
sLog.outError("Creature (Entry: %u) have UnitClass = %u but at charming have class 0!!! that will be result client crash.", cinfo->Entry, cinfo->UnitClass);
|
||||
|
||||
target->SetByteValue(UNIT_FIELD_BYTES_0, 1, CLASS_MAGE);
|
||||
}
|
||||
|
|
@ -4533,10 +4538,10 @@ void Aura::HandleModCharm(bool apply, bool Real)
|
|||
target->setFaction(cinfo->FactionAlliance);
|
||||
|
||||
// restore UNIT_FIELD_BYTES_0
|
||||
if (cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
|
||||
if (cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->CreatureType == CREATURE_TYPE_DEMON)
|
||||
{
|
||||
// DB must have proper class set in field at loading, not req. restore, including workaround case at apply
|
||||
// m_target->SetByteValue(UNIT_FIELD_BYTES_0, 1, cinfo->unit_class);
|
||||
// m_target->SetByteValue(UNIT_FIELD_BYTES_0, 1, cinfo->UnitClass);
|
||||
|
||||
if (target->GetCharmInfo())
|
||||
{ target->GetCharmInfo()->SetPetNumber(0, true); }
|
||||
|
|
@ -4947,13 +4952,8 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
|
|||
if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_FROST)
|
||||
{ target->ModifyAuraState(AURA_STATE_FROZEN, apply); }
|
||||
|
||||
target->addUnitState(UNIT_STAT_ROOT);
|
||||
target->SetTargetGuid(ObjectGuid());
|
||||
|
||||
// Save last orientation
|
||||
if (target->getVictim())
|
||||
target->SetOrientation(target->GetAngle(target->getVictim()));
|
||||
|
||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
target->SetRoot(true);
|
||||
|
|
@ -4991,18 +4991,14 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
|
|||
|
||||
// Real remove called after current aura remove from lists, check if other similar auras active
|
||||
if (target->HasAuraType(SPELL_AURA_MOD_ROOT))
|
||||
{ return; }
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
target->clearUnitState(UNIT_STAT_ROOT);
|
||||
|
||||
if (!target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
|
||||
{
|
||||
if (target->getVictim() && target->IsAlive())
|
||||
target->SetTargetGuid(target->getVictim()->GetObjectGuid());
|
||||
|
||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||
target->SetRoot(false);
|
||||
}
|
||||
if (!target->hasUnitState(UNIT_STAT_STUNNED) && (target->GetTypeId() == TYPEID_PLAYER)) // prevent allow move if have also stun effect
|
||||
target->SetRoot(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7027,7 +7023,7 @@ void Aura::HandleAuraEmpathy(bool apply, bool /*Real*/)
|
|||
return;
|
||||
|
||||
CreatureInfo const* ci = ObjectMgr::GetCreatureTemplate(GetTarget()->GetEntry());
|
||||
if (ci && ci->type == CREATURE_TYPE_BEAST)
|
||||
if (ci && ci->CreatureType == CREATURE_TYPE_BEAST)
|
||||
GetTarget()->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
|
||||
}
|
||||
|
||||
|
|
@ -8346,6 +8342,14 @@ void Aura::PeriodicDummyTick()
|
|||
target->CastSpell(target, 63536, true, NULL, this);
|
||||
return;
|
||||
}
|
||||
case 63382: // Rapid Burst
|
||||
{
|
||||
if (GetAuraTicks() % 2)
|
||||
target->CastSpell(target, target->GetMap()->IsRegularDifficulty() ? 64019 : 64532, true);
|
||||
else
|
||||
target->CastSpell(target, target->GetMap()->IsRegularDifficulty() ? 63387 : 64531, true);
|
||||
return;
|
||||
}
|
||||
case 64217: // Overcharged
|
||||
{
|
||||
if (GetHolder()->GetStackAmount() >= 10)
|
||||
|
|
@ -8826,7 +8830,7 @@ void Aura::HandleAuraMirrorImage(bool apply, bool Real)
|
|||
const CreatureModelInfo* minfo = sObjectMgr.GetCreatureModelInfo(pCreature->GetNativeDisplayId());
|
||||
|
||||
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 0, 0);
|
||||
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 1, cinfo->unit_class);
|
||||
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 1, cinfo->UnitClass);
|
||||
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
|
||||
pCreature->SetByteValue(UNIT_FIELD_BYTES_0, 3, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1542,6 +1542,14 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
unitTarget->CastSpell(unitTarget, spell_id, true);
|
||||
return;
|
||||
}
|
||||
case 41283: // Abyssal Toss
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
m_caster->SummonCreature(23416, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
|
||||
return;
|
||||
}
|
||||
case 41333: // Empyreal Equivalency
|
||||
{
|
||||
if (!unitTarget)
|
||||
|
|
@ -2738,6 +2746,31 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
unitTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
|
||||
return;
|
||||
}
|
||||
case 62217: // Unstable Energy
|
||||
case 62922: // Unstable Energy (h)
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue());
|
||||
return;
|
||||
}
|
||||
case 62262: // Brightleaf Flux
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
if (unitTarget->HasAura(62239))
|
||||
unitTarget->RemoveAurasDueToSpell(62239);
|
||||
else
|
||||
{
|
||||
uint32 stackAmount = urand(1, GetSpellStore()->LookupEntry(62239)->GetStackAmount());
|
||||
|
||||
for (uint8 i = 0; i < stackAmount; ++i)
|
||||
unitTarget->CastSpell(unitTarget, 62239, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 62278: // Lightning Orb Charger
|
||||
{
|
||||
if (!unitTarget)
|
||||
|
|
@ -2747,6 +2780,14 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
unitTarget->CastSpell(unitTarget, 62279, true);
|
||||
return;
|
||||
}
|
||||
case 62652: // Tidal Wave
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
m_caster->CastSpell(unitTarget, m_caster->GetMap()->IsRegularDifficulty() ? 62653 : 62935, true);
|
||||
return;
|
||||
}
|
||||
case 62797: // Storm Cloud
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
|
|
@ -2764,6 +2805,15 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true);
|
||||
return;
|
||||
}
|
||||
case 63027: // Proximity Mines
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
for (uint8 i = 0; i < 15; ++i)
|
||||
unitTarget->CastSpell(unitTarget, 65347, true);
|
||||
return;
|
||||
}
|
||||
case 63499: // Dispel Magic
|
||||
{
|
||||
if (!unitTarget)
|
||||
|
|
@ -2779,6 +2829,22 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
|
||||
m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true);
|
||||
}
|
||||
case 63667: // Napalm Shell
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
m_caster->CastSpell(unitTarget, m_caster->GetMap()->IsRegularDifficulty() ? 63666 : 65026, true);
|
||||
return;
|
||||
}
|
||||
case 63681: // Rocket Strike
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
m_caster->CastSpell(unitTarget, 63036, true);
|
||||
return;
|
||||
}
|
||||
case 63820: // Summon Scrap Bot Trigger (Ulduar - Mimiron) for Scrap Bots
|
||||
case 64425: // Summon Scrap Bot Trigger (Ulduar - Mimiron) for Assault Bots
|
||||
case 64620: // Summon Fire Bot Trigger (Ulduar - Mimiron) for Fire Bots
|
||||
|
|
@ -2801,6 +2867,14 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
m_caster->SetFacingTo(frand(0, M_PI_F * 2));
|
||||
return;
|
||||
}
|
||||
case 64402: // Rocket Strike
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
unitTarget->CastSpell(unitTarget, 63681, true);
|
||||
return;
|
||||
}
|
||||
case 64489: // Feral Rush
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
|
|
@ -2818,6 +2892,14 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
m_caster->CastSpell(m_caster, 64540, true);
|
||||
return;
|
||||
}
|
||||
case 64623: // Frost Bomb
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
m_caster->CastSpell(unitTarget, 64627, true);
|
||||
return;
|
||||
}
|
||||
case 64673: // Feral Rush (h)
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
|
|
@ -2826,6 +2908,14 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
m_caster->CastSpell(unitTarget, 64674, true);
|
||||
return;
|
||||
}
|
||||
case 64841: // Rapid Burst
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
unitTarget->CastSpell(m_caster, 63382, false);
|
||||
return;
|
||||
}
|
||||
case 64981: // Summon Random Vanquished Tentacle
|
||||
{
|
||||
uint32 spell_id = 0;
|
||||
|
|
@ -2840,6 +2930,16 @@ void Spell::EffectDummy(SpellEffectEntry const* effect)
|
|||
m_caster->CastSpell(m_caster, spell_id, true);
|
||||
return;
|
||||
}
|
||||
case 65346: // Proximity Mine
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
m_caster->CastSpell(m_caster, m_caster->GetMap()->IsRegularDifficulty() ? 66351 : 63009, true);
|
||||
m_caster->RemoveAurasDueToSpell(65345);
|
||||
m_caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
return;
|
||||
}
|
||||
case 66390: // Read Last Rites
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
|
|
@ -5279,7 +5379,7 @@ void Spell::EffectSummonType(SpellEffectEntry const* effect)
|
|||
return;
|
||||
|
||||
// FIXME: not all totems and similar cases selected by this check...
|
||||
if (cInfo->type == CREATURE_TYPE_TOTEM)
|
||||
if (cInfo->CreatureType == CREATURE_TYPE_TOTEM)
|
||||
summonResult = DoSummonTotem(effect);
|
||||
else
|
||||
summonResult = DoSummonGuardian(summonPositions, summon_prop, effect, level);
|
||||
|
|
@ -5468,7 +5568,7 @@ bool Spell::DoSummonCritter(CreatureSummonPositions& list, SummonPropertiesEntry
|
|||
critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
|
||||
// critter->InitLevelupSpellsForLevel(); // none?
|
||||
critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
|
||||
critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
|
||||
critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->NpcFlags);
|
||||
// some mini-pets have quests
|
||||
// set timer for unsummon
|
||||
if (m_duration > 0)
|
||||
|
|
@ -5538,7 +5638,7 @@ bool Spell::DoSummonGuardian(CreatureSummonPositions& list, SummonPropertiesEntr
|
|||
// spawnCreature->SetName(""); // generated by client
|
||||
spawnCreature->SetOwnerGuid(m_caster->GetObjectGuid());
|
||||
spawnCreature->SetPowerType(POWER_MANA);
|
||||
spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->npcflag);
|
||||
spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, spawnCreature->GetCreatureInfo()->NpcFlags);
|
||||
|
||||
spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0);
|
||||
spawnCreature->SetCreatorGuid(m_caster->GetObjectGuid());
|
||||
|
|
@ -7597,6 +7697,23 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect)
|
|||
unitTarget->CastSpell(unitTarget, triggeredSpell[urand(0, 3)], true);
|
||||
return;
|
||||
}
|
||||
case 44323: // Hawk Hunting
|
||||
case 44407: // Hawk Hunting
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
|
||||
// check target entry specific to each spell
|
||||
if (m_spellInfo->Id == 44323 && unitTarget->GetEntry() != 24746)
|
||||
return;
|
||||
if (m_spellInfo->Id == 44407 && unitTarget->GetEntry() != 24747)
|
||||
return;
|
||||
|
||||
unitTarget->CastSpell(m_caster, effect->CalculateSimpleValue(), true);
|
||||
// despawn delay depends on the distance between caster and target
|
||||
((Creature*)unitTarget)->ForcedDespawn(100 * unitTarget->GetDistance2d(m_caster));
|
||||
return;
|
||||
}
|
||||
case 44364: // Rock Falcon Primer
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
|
||||
|
|
@ -7771,6 +7888,14 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect)
|
|||
unitTarget->CastSpell(unitTarget, 45259, true);
|
||||
return;
|
||||
}
|
||||
case 45625: // Arcane Chains: Character Force Cast
|
||||
{
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
unitTarget->CastSpell(unitTarget, effect->CalculateSimpleValue(), true);
|
||||
return;
|
||||
}
|
||||
case 45668: // Ultra-Advanced Proto-Typical Shortening Blaster
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
|
||||
|
|
@ -7855,7 +7980,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_caster->SetUInt32Value(UNIT_NPC_FLAGS, cTemplate->npcflag);
|
||||
m_caster->SetUInt32Value(UNIT_NPC_FLAGS, cTemplate->NpcFlags);
|
||||
((Creature*)m_caster)->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, 0);
|
||||
((Creature*)m_caster)->SetVirtualItem(VIRTUAL_ITEM_SLOT_1, 0);
|
||||
|
||||
|
|
@ -8643,6 +8768,28 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect)
|
|||
unitTarget->CastSpell(m_caster, 64909, true);
|
||||
return;
|
||||
}
|
||||
case 62282: // Iron Roots
|
||||
case 62440: // Strengthened Iron Roots
|
||||
case 63598: // Iron Roots (h)
|
||||
case 63601: // Strengthened Iron Roots (h)
|
||||
{
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || !((Creature*)unitTarget)->IsTemporarySummon())
|
||||
return;
|
||||
|
||||
uint32 ownerAura = 0;
|
||||
|
||||
switch (m_spellInfo->Id)
|
||||
{
|
||||
case 62282: ownerAura = 62283; break;
|
||||
case 62440: ownerAura = 62438; break;
|
||||
case 63598: ownerAura = 62930; break;
|
||||
case 63601: ownerAura = 62861; break;
|
||||
};
|
||||
|
||||
if (Unit* summoner = unitTarget->GetMap()->GetUnit(((TemporarySummon*)unitTarget)->GetSummonerGuid()))
|
||||
summoner->RemoveAurasDueToSpell(ownerAura);
|
||||
return;
|
||||
}
|
||||
case 62381: // Chill
|
||||
{
|
||||
if (!unitTarget)
|
||||
|
|
@ -8685,18 +8832,6 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect)
|
|||
unitTarget->RemoveAuraHolderFromStack(spellId, numStacks);
|
||||
return;
|
||||
}
|
||||
case 62678: // Summon Allies of Nature
|
||||
{
|
||||
const uint32 randSpells[] =
|
||||
{
|
||||
62685, // Summon Wave - 1 Mob
|
||||
62686, // Summon Wave - 3 Mob
|
||||
62688, // Summon Wave - 10 Mob
|
||||
};
|
||||
|
||||
m_caster->CastSpell(m_caster, randSpells[urand(0, countof(randSpells) - 1)], true);
|
||||
return;
|
||||
}
|
||||
case 62688: // Summon Wave - 10 Mob
|
||||
{
|
||||
uint32 spellId = effect->CalculateSimpleValue();
|
||||
|
|
|
|||
|
|
@ -1214,6 +1214,13 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura
|
|||
basepoints[0] = damage * 15 / 100;
|
||||
break;
|
||||
}
|
||||
// Fingers of Frost
|
||||
case 74396:
|
||||
{
|
||||
// Remove only single aura from stack and remove holder if its last stack
|
||||
RemoveAuraHolderFromStack(74396);
|
||||
return SPELL_AURA_PROC_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -3111,6 +3118,12 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d
|
|||
(((Creature*)pVictim)->GetCreatureInfo()->MechanicImmuneMask & (1 << (MECHANIC_STUN - 1))) == 0)
|
||||
return SPELL_AURA_PROC_FAILED;
|
||||
}
|
||||
else if (auraSpellInfo->SpellIconID == 2947) // Fingers of Frost
|
||||
{
|
||||
// proc chance for spells in basepoints
|
||||
if (!roll_chance_i(triggerAmount))
|
||||
return SPELL_AURA_PROC_FAILED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_WARRIOR:
|
||||
|
|
|
|||
|
|
@ -779,6 +779,7 @@ void World::LoadConfigSettings(bool reload)
|
|||
setConfigMinMax(CONFIG_FLOAT_GHOST_RUN_SPEED_BG, "Death.Ghost.RunSpeed.Battleground", 1.0f, 0.1f, 10.0f);
|
||||
|
||||
setConfig(CONFIG_FLOAT_THREAT_RADIUS, "ThreatRadius", 100.0f);
|
||||
setConfigMin(CONFIG_UINT32_CREATURE_RESPAWN_AGGRO_DELAY, "CreatureRespawnAggroDelay", 5000, 0);
|
||||
|
||||
// always use declined names in the russian client
|
||||
if (getConfig(CONFIG_UINT32_REALM_ZONE) == REALM_ZONE_RUSSIAN)
|
||||
|
|
@ -812,7 +813,7 @@ void World::LoadConfigSettings(bool reload)
|
|||
|
||||
setConfig(CONFIG_BOOL_KICK_PLAYER_ON_BAD_PACKET, "Network.KickOnBadPacket", false);
|
||||
|
||||
setConfig(CONFIG_BOOL_PLAYER_COMMANDS, "PlayerCommands", false);
|
||||
setConfig(CONFIG_BOOL_PLAYER_COMMANDS, "PlayerCommands", true);
|
||||
|
||||
if (int clientCacheId = sConfig.GetIntDefault("ClientCacheVersion", 0))
|
||||
{
|
||||
|
|
@ -1782,19 +1783,7 @@ namespace MaNGOS
|
|||
while (char* line = lineFromMessage(pos))
|
||||
{
|
||||
WorldPacket* data = new WorldPacket();
|
||||
|
||||
uint32 lineLength = (line ? strlen(line) : 0) + 1;
|
||||
|
||||
data->Initialize(SMSG_MESSAGECHAT, 100);// guess size
|
||||
*data << uint8(CHAT_MSG_SYSTEM);
|
||||
*data << uint32(LANG_UNIVERSAL);
|
||||
*data << uint64(0);
|
||||
*data << uint32(0); // can be chat msg group or something
|
||||
*data << uint64(0);
|
||||
*data << uint32(lineLength);
|
||||
*data << line;
|
||||
*data << uint8(0);
|
||||
|
||||
ChatHandler::BuildChatPacket(*data, CHAT_MSG_SYSTEM, line);
|
||||
data_list.push_back(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ enum eConfigUInt32Values
|
|||
CONFIG_UINT32_GUID_RESERVE_SIZE_CREATURE,
|
||||
CONFIG_UINT32_GUID_RESERVE_SIZE_GAMEOBJECT,
|
||||
CONFIG_UINT32_MIN_LEVEL_FOR_RAID,
|
||||
CONFIG_UINT32_CREATURE_RESPAWN_AGGRO_DELAY,
|
||||
CONFIG_UINT32_RANDOM_BG_RESET_HOUR,
|
||||
// Warden
|
||||
CONFIG_UINT32_WARDEN_CLIENT_RESPONSE_DELAY,
|
||||
|
|
|
|||
|
|
@ -785,6 +785,11 @@ SD2ErrorLogFile = "scriptdev2-errors.log"
|
|||
# You can bypass this setting by typing "/script SetAllowLowLevelRaid(true/false)" command in chat
|
||||
# Default: 10
|
||||
#
|
||||
# PlayerCommands
|
||||
# Should player chat be parsed for GM commands.
|
||||
# Default: 1 (parse commands)
|
||||
# 0 (ignore commands)
|
||||
#
|
||||
################################################################################
|
||||
|
||||
GameType = 1
|
||||
|
|
@ -856,6 +861,7 @@ WaitAtStartupError = 10
|
|||
PlayerCommands = 0
|
||||
Motd = "Welcome to Mangos Three."
|
||||
Raid.MinLevel = 10
|
||||
PlayerCommands = 1
|
||||
|
||||
################################################################################
|
||||
# PLAYER INTERACTION
|
||||
|
|
@ -1008,6 +1014,7 @@ TalentsInspecting = 1
|
|||
|
||||
ThreatRadius = 100
|
||||
Rate.Creature.Aggro = 1
|
||||
CreatureRespawnAggroDelay = 5000
|
||||
CreatureFamilyFleeAssistanceRadius = 30
|
||||
CreatureFamilyAssistanceRadius = 10
|
||||
CreatureFamilyAssistanceDelay = 1500
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ bool npc_escortAI::AssistPlayerInCombat(Unit* pWho)
|
|||
return false;
|
||||
}
|
||||
|
||||
// unit state prevents (similar check is done in CanInitiateAttack which also include checking unit_flags. We skip those here)
|
||||
// unit state prevents (similar check is done in CanInitiateAttack which also include checking UnitFlags. We skip those here)
|
||||
if (m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -629,7 +629,7 @@ void npc_escortAI::Start(bool bRun, const Player* pPlayer, const Quest* pQuest,
|
|||
debug_log("SD3: EscortAI start with WAYPOINT_MOTION_TYPE, changed to MoveIdle.");
|
||||
}
|
||||
|
||||
// disable npcflags
|
||||
// disable NpcFlagss
|
||||
m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
|
||||
|
||||
debug_log("SD3: EscortAI started with " SIZEFMTD " waypoints. Run = %d, PlayerGuid = %s", WaypointList.size(), m_bIsRunning, m_playerGuid.GetString().c_str());
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ bool FollowerAI::AssistPlayerInCombat(Unit* pWho)
|
|||
return false;
|
||||
}
|
||||
|
||||
// unit state prevents (similar check is done in CanInitiateAttack which also include checking unit_flags. We skip those here)
|
||||
// unit state prevents (similar check is done in CanInitiateAttack which also include checking UnitFlags. We skip those here)
|
||||
if (m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED))
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ struct npc_kitten : public CreatureScript
|
|||
|
||||
void MoveInLineOfSight(Unit* pWho) override
|
||||
{
|
||||
// should not have npcflag by default, so set when expected
|
||||
// should not have NpcFlags by default, so set when expected
|
||||
if (!m_creature->getVictim() && !m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP) && HasFollowState(STATE_FOLLOW_INPROGRESS) && pWho->GetEntry() == NPC_WINNA)
|
||||
{
|
||||
if (m_creature->IsWithinDistInMap(pWho, INTERACTION_DISTANCE))
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ struct boss_moam : public CreatureScript
|
|||
m_creature->SetMaxPower(POWER_MANA, m_creature->GetCreatureInfo()->MaxLevelMana);
|
||||
#endif
|
||||
#if defined (CATA)
|
||||
m_creature->SetMaxPower(POWER_MANA, m_creature->GetCreatureInfo()->maxmana);// TODO MaxLevelHealth);
|
||||
m_creature->SetMaxPower(POWER_MANA, m_creature->GetCreatureInfo()->MaxLevelMana);// TODO MaxLevelHealth);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ struct mob_lump : public CreatureScript
|
|||
m_creature->DeleteThreatList();
|
||||
m_creature->CombatStop(true);
|
||||
|
||||
// should get unit_flags UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE at faction change, but unclear why/for what reason, skipped (no flags expected as default)
|
||||
// should get UnitFlags UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE at faction change, but unclear why/for what reason, skipped (no flags expected as default)
|
||||
m_creature->SetFactionTemporary(FACTION_FRIENDLY, TEMPFACTION_RESTORE_REACH_HOME);
|
||||
|
||||
m_creature->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
|
|
|
|||
|
|
@ -1213,9 +1213,9 @@ struct npc_guardian : public CreatureScript
|
|||
# npc_innkeeper
|
||||
#########*/
|
||||
|
||||
// Script applied to all innkeepers by npcflag.
|
||||
// Script applied to all innkeepers by NpcFlags.
|
||||
// Are there any known innkeepers that does not hape the options in the below?
|
||||
// (remember gossipHello is not called unless npcflag|1 is present)
|
||||
// (remember gossipHello is not called unless NpcFlags|1 is present)
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,18 +41,6 @@ BarGoLink::BarGoLink(int row_count)
|
|||
init(row_count);
|
||||
}
|
||||
|
||||
BarGoLink::BarGoLink(uint32 row_count)
|
||||
{
|
||||
MANGOS_ASSERT(row_count < (uint32)ACE_INT32_MAX);
|
||||
init((int)row_count);
|
||||
}
|
||||
|
||||
BarGoLink::BarGoLink(uint64 row_count)
|
||||
{
|
||||
MANGOS_ASSERT(row_count < (uint64)ACE_INT32_MAX);
|
||||
init((int)row_count);
|
||||
}
|
||||
|
||||
BarGoLink::~BarGoLink()
|
||||
{
|
||||
if (!m_showOutput)
|
||||
|
|
|
|||
|
|
@ -40,8 +40,6 @@ class BarGoLink
|
|||
* @param row_count
|
||||
*/
|
||||
explicit BarGoLink(int row_count);
|
||||
explicit BarGoLink(uint32 row_count); // row_count < ACE_INT32_MAX
|
||||
explicit BarGoLink(uint64 row_count); // row_count < ACE_INT64_MAX
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue