Merge branch 'master' into 4.3.4
Conflicts: src/server/game/Entities/Object/Object.cpp src/server/game/Entities/Object/Object.h src/server/game/Entities/Pet/Pet.cpp src/server/game/Entities/Player/Player.cpp src/server/game/Entities/Player/Player.h src/server/game/Events/GameEventMgr.cpp src/server/game/Loot/LootMgr.cpp src/server/shared/Packets/ByteBuffer.h
This commit is contained in:
commit
c97c381ea0
54 files changed
+924
-465
No files matched your search
@@ -16,13 +16,13 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Object.h"
|
||||
#include "Common.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Log.h"
|
||||
#include "World.h"
|
||||
#include "Object.h"
|
||||
#include "Creature.h"
|
||||
#include "Player.h"
|
||||
#include "Vehicle.h"
|
||||
@@ -200,8 +200,9 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
|
||||
updateType = UPDATETYPE_CREATE_OBJECT2;
|
||||
break;
|
||||
case HIGHGUID_UNIT:
|
||||
if (ToUnit()->ToTempSummon() && IS_PLAYER_GUID(ToUnit()->ToTempSummon()->GetSummonerGUID()))
|
||||
updateType = UPDATETYPE_CREATE_OBJECT2;
|
||||
if (TempSummon const* summon = ToUnit()->ToTempSummon())
|
||||
if (IS_PLAYER_GUID(summon->GetSummonerGUID()))
|
||||
updateType = UPDATETYPE_CREATE_OBJECT2;
|
||||
break;
|
||||
case HIGHGUID_GAMEOBJECT:
|
||||
if (IS_PLAYER_GUID(ToGameObject()->GetOwnerGUID()))
|
||||
@@ -214,7 +215,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
|
||||
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
|
||||
if (isType(TYPEMASK_GAMEOBJECT))
|
||||
{
|
||||
switch (((GameObject*)this)->GetGoType())
|
||||
switch (ToGameObject()->GetGoType())
|
||||
{
|
||||
case GAMEOBJECT_TYPE_TRAP:
|
||||
case GAMEOBJECT_TYPE_DUEL_ARBITER:
|
||||
@@ -231,8 +232,10 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
|
||||
}
|
||||
}
|
||||
|
||||
if (ToUnit() && ToUnit()->getVictim())
|
||||
flags |= UPDATEFLAG_HAS_TARGET;
|
||||
if (Unit const* unit = ToUnit())
|
||||
if (unit->getVictim())
|
||||
flags |= UPDATEFLAG_HAS_TARGET;
|
||||
|
||||
|
||||
ByteBuffer buf(500);
|
||||
buf << uint8(updateType);
|
||||
@@ -349,6 +352,17 @@ uint16 Object::GetUInt16Value(uint16 index, uint8 offset) const
|
||||
|
||||
void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
{
|
||||
Unit const* self = NULL;
|
||||
ObjectGuid guid = GetGUID();
|
||||
uint32 movementFlags = 0;
|
||||
uint16 movementFlagsExtra = 0;
|
||||
|
||||
bool hasFallDirection = false;
|
||||
bool hasFallData = false;
|
||||
bool hasPitch = false;
|
||||
bool hasSpline = false;
|
||||
bool hasSplineElevation = false;
|
||||
|
||||
uint32 unkLoopCounter = 0;
|
||||
// Bit content
|
||||
data->WriteBit(0);
|
||||
@@ -369,10 +383,16 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
|
||||
if (flags & UPDATEFLAG_LIVING)
|
||||
{
|
||||
Unit const* self = ToUnit();
|
||||
ObjectGuid guid = GetGUID();
|
||||
uint32 movementFlags = self->m_movementInfo.GetMovementFlags();
|
||||
uint16 movementFlagsExtra = self->m_movementInfo.GetExtraMovementFlags();
|
||||
self = ToUnit();
|
||||
movementFlags = self->m_movementInfo.GetMovementFlags();
|
||||
movementFlagsExtra = self->m_movementInfo.GetExtraMovementFlags();
|
||||
hasPitch = ((movementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) ||
|
||||
(movementFlagsExtra & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING));
|
||||
hasSpline = self->IsSplineEnabled();
|
||||
hasSplineElevation = movementFlags & MOVEMENTFLAG_SPLINE_ELEVATION;
|
||||
hasFallData = movementFlagsExtra & MOVEMENTFLAG2_INTERPOLATED_TURNING;
|
||||
hasFallDirection = movementFlags & MOVEMENTFLAG_FALLING;
|
||||
|
||||
if (GetTypeId() == TYPEID_UNIT)
|
||||
movementFlags &= MOVEMENTFLAG_MASK_CREATURE_ALLOWED;
|
||||
|
||||
@@ -385,14 +405,14 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
data->WriteBits(movementFlags, 30);
|
||||
|
||||
data->WriteBit(0);
|
||||
data->WriteBit(!((movementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) ||
|
||||
(movementFlagsExtra & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))); // Has pitch
|
||||
data->WriteBit(self->IsSplineEnabled()); // Has spline data
|
||||
data->WriteBit(movementFlagsExtra & MOVEMENTFLAG2_INTERPOLATED_TURNING);// Has fall data
|
||||
data->WriteBit(!(movementFlags & MOVEMENTFLAG_SPLINE_ELEVATION)); // Has spline elevation
|
||||
data->WriteBit(!hasPitch); // Has pitch
|
||||
data->WriteBit(hasSpline); // Has spline data
|
||||
data->WriteBit(hasFallData); // Has fall data
|
||||
data->WriteBit(!hasSplineElevation); // Has spline elevation
|
||||
data->WriteBit(guid[5]);
|
||||
data->WriteBit(self->m_movementInfo.t_guid); // Has transport data
|
||||
data->WriteBit(0); // Is missing time
|
||||
|
||||
if (self->m_movementInfo.t_guid)
|
||||
{
|
||||
ObjectGuid transGuid = self->m_movementInfo.t_guid;
|
||||
@@ -410,12 +430,13 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
}
|
||||
|
||||
data->WriteBit(guid[4]);
|
||||
if (self->IsSplineEnabled())
|
||||
|
||||
if (hasSpline)
|
||||
Movement::PacketBuilder::WriteCreateBits(*self->movespline, *data);
|
||||
|
||||
data->WriteBit(guid[6]);
|
||||
if (movementFlagsExtra & MOVEMENTFLAG2_INTERPOLATED_TURNING)
|
||||
data->WriteBit(movementFlags & MOVEMENTFLAG_FALLING);
|
||||
if (hasFallData)
|
||||
data->WriteBit(hasFallDirection);
|
||||
|
||||
data->WriteBit(guid[0]);
|
||||
data->WriteBit(guid[1]);
|
||||
@@ -443,7 +464,7 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
|
||||
if (flags & UPDATEFLAG_HAS_TARGET)
|
||||
{
|
||||
ObjectGuid victimGuid = ToUnit()->getVictim()->GetGUID(); // checked in BuildCreateUpdateBlockForPlayer
|
||||
ObjectGuid victimGuid = self->getVictim()->GetGUID(); // checked in BuildCreateUpdateBlockForPlayer
|
||||
data->WriteBit(victimGuid[2]);
|
||||
data->WriteBit(victimGuid[7]);
|
||||
data->WriteBit(victimGuid[0]);
|
||||
@@ -469,18 +490,12 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
|
||||
if (flags & UPDATEFLAG_LIVING)
|
||||
{
|
||||
Unit const* self = ToUnit();
|
||||
ObjectGuid guid = GetGUID();
|
||||
uint32 movementFlags = self->m_movementInfo.GetMovementFlags();
|
||||
uint16 movementFlagsExtra = self->m_movementInfo.GetExtraMovementFlags();
|
||||
if (GetTypeId() == TYPEID_UNIT)
|
||||
movementFlags &= MOVEMENTFLAG_MASK_CREATURE_ALLOWED;
|
||||
|
||||
data->WriteByteSeq(guid[4]);
|
||||
*data << self->GetSpeed(MOVE_RUN_BACK);
|
||||
if (movementFlagsExtra & MOVEMENTFLAG2_INTERPOLATED_TURNING)
|
||||
|
||||
if (hasFallData)
|
||||
{
|
||||
if (movementFlags & MOVEMENTFLAG_FALLING)
|
||||
if (hasFallDirection)
|
||||
{
|
||||
*data << float(self->m_movementInfo.j_cosAngle);
|
||||
*data << float(self->m_movementInfo.j_xyspeed);
|
||||
@@ -492,14 +507,15 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
}
|
||||
|
||||
*data << self->GetSpeed(MOVE_SWIM_BACK);
|
||||
if (movementFlags & MOVEMENTFLAG_SPLINE_ELEVATION)
|
||||
if (hasSplineElevation)
|
||||
*data << float(self->m_movementInfo.splineElevation);
|
||||
|
||||
if (self->IsSplineEnabled())
|
||||
if (hasSpline)
|
||||
Movement::PacketBuilder::WriteCreateData(*self->movespline, *data);
|
||||
|
||||
*data << float(self->GetPositionZMinusOffset());
|
||||
data->WriteByteSeq(guid[5]);
|
||||
|
||||
if (self->m_movementInfo.t_guid)
|
||||
{
|
||||
ObjectGuid transGuid = self->m_movementInfo.t_guid;
|
||||
@@ -547,8 +563,7 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
*data << float(self->GetOrientation());
|
||||
|
||||
*data << self->GetSpeed(MOVE_RUN);
|
||||
if ((movementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) ||
|
||||
(movementFlagsExtra & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))
|
||||
if (hasPitch)
|
||||
*data << float(self->m_movementInfo.pitch);
|
||||
|
||||
*data << self->GetSpeed(MOVE_FLIGHT);
|
||||
@@ -556,7 +571,6 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
|
||||
if (flags & UPDATEFLAG_VEHICLE)
|
||||
{
|
||||
Unit const* self = ToUnit();
|
||||
*data << float(self->GetOrientation());
|
||||
*data << uint32(self->GetVehicleKit()->GetVehicleInfo()->m_ID);
|
||||
}
|
||||
@@ -625,7 +639,7 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
|
||||
if (flags & UPDATEFLAG_HAS_TARGET)
|
||||
{
|
||||
ObjectGuid victimGuid = ToUnit()->getVictim()->GetGUID(); // checked in BuildCreateUpdateBlockForPlayer
|
||||
ObjectGuid victimGuid = self->getVictim()->GetGUID(); // checked in BuildCreateUpdateBlockForPlayer
|
||||
data->WriteByteSeq(victimGuid[4]);
|
||||
data->WriteByteSeq(victimGuid[0]);
|
||||
data->WriteByteSeq(victimGuid[3]);
|
||||
@@ -650,45 +664,50 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
|
||||
*data << uint32(getMSTime()); // Unknown - getMSTime is wrong.
|
||||
}
|
||||
|
||||
void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* updateMask, Player* target) const
|
||||
void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask* updateMask, Player* target) const
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
bool IsActivateToQuest = false;
|
||||
if (updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2)
|
||||
{
|
||||
if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsDynTransport())
|
||||
{
|
||||
if (((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
|
||||
IsActivateToQuest = true;
|
||||
|
||||
if (((GameObject*)this)->GetGoArtKit())
|
||||
updateMask->SetBit(GAMEOBJECT_BYTES_1);
|
||||
}
|
||||
else if (isType(TYPEMASK_UNIT))
|
||||
{
|
||||
if (((Unit*)this)->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK))
|
||||
updateMask->SetBit(UNIT_FIELD_AURASTATE);
|
||||
}
|
||||
// Before trying to convert to each type there is a check, so safe
|
||||
Unit const* unit = ToUnit();
|
||||
GameObject const* go = ToGameObject();
|
||||
|
||||
if (unit)
|
||||
{
|
||||
if (unit->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK))
|
||||
updateMask->SetBit(UNIT_FIELD_AURASTATE);
|
||||
}
|
||||
else // case UPDATETYPE_VALUES
|
||||
else if (go)
|
||||
{
|
||||
if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
|
||||
if (updateType == UPDATETYPE_CREATE_OBJECT || updateType == UPDATETYPE_CREATE_OBJECT2)
|
||||
{
|
||||
if (((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
|
||||
IsActivateToQuest = true;
|
||||
if (!go->IsDynTransport())
|
||||
{
|
||||
if (go->ActivateToQuest(target) || target->isGameMaster())
|
||||
IsActivateToQuest = true;
|
||||
|
||||
updateMask->SetBit(GAMEOBJECT_BYTES_1);
|
||||
|
||||
if (ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_CHEST && ToGameObject()->GetGOInfo()->chest.groupLootRules &&
|
||||
ToGameObject()->HasLootRecipient())
|
||||
updateMask->SetBit(GAMEOBJECT_FLAGS);
|
||||
if (go->GetGoArtKit())
|
||||
updateMask->SetBit(GAMEOBJECT_BYTES_1);
|
||||
}
|
||||
}
|
||||
else if (isType(TYPEMASK_UNIT))
|
||||
else
|
||||
{
|
||||
if (((Unit*)this)->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK))
|
||||
updateMask->SetBit(UNIT_FIELD_AURASTATE);
|
||||
if (!go->IsTransport())
|
||||
{
|
||||
if (go->ActivateToQuest(target) || target->isGameMaster())
|
||||
IsActivateToQuest = true;
|
||||
|
||||
updateMask->SetBit(GAMEOBJECT_BYTES_1);
|
||||
|
||||
if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules &&
|
||||
go->HasLootRecipient())
|
||||
{
|
||||
updateMask->SetBit(GAMEOBJECT_FLAGS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,14 +715,15 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
if (GetTypeId() == TYPEID_PLAYER && target != this)
|
||||
valCount = PLAYER_END_NOT_SELF;
|
||||
|
||||
WPAssert(updateMask && updateMask->GetCount() == valCount);
|
||||
ASSERT(updateMask && updateMask->GetCount() == valCount);
|
||||
|
||||
*data << (uint8)updateMask->GetBlockCount();
|
||||
*data << uint8(updateMask->GetBlockCount());
|
||||
updateMask->AppendToPacket(data);
|
||||
|
||||
// 2 specialized loops for speed optimization in non-unit case
|
||||
if (isType(TYPEMASK_UNIT)) // unit (creature/player) case
|
||||
if (unit) // unit (creature/player) case
|
||||
{
|
||||
Creature const* creature = ToCreature();
|
||||
for (uint16 index = 0; index < valCount; ++index)
|
||||
{
|
||||
if (updateMask->GetBit(index))
|
||||
@@ -720,7 +740,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
|
||||
if (appendValue & UNIT_NPC_FLAG_TRAINER)
|
||||
{
|
||||
if (!this->ToCreature()->isCanTrainingOf(target, false))
|
||||
if (!creature->isCanTrainingOf(target, false))
|
||||
appendValue &= ~(UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS | UNIT_NPC_FLAG_TRAINER_PROFESSION);
|
||||
}
|
||||
}
|
||||
@@ -729,8 +749,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
}
|
||||
else if (index == UNIT_FIELD_AURASTATE)
|
||||
{
|
||||
// Check per caster aura states to not enable using a pell in client if specified aura is not by target
|
||||
*data << ((Unit*)this)->BuildAuraStateUpdateForTarget(target);
|
||||
// Check per caster aura states to not enable using a spell in client if specified aura is not by target
|
||||
*data << unit->BuildAuraStateUpdateForTarget(target);
|
||||
}
|
||||
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
|
||||
else if (index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
|
||||
@@ -759,7 +779,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
{
|
||||
if (GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
|
||||
CreatureTemplate const* cinfo = creature->GetCreatureTemplate();
|
||||
|
||||
// this also applies for transform auras
|
||||
if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(ToUnit()->getTransForm()))
|
||||
@@ -799,7 +819,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
{
|
||||
uint32 dynamicFlags = m_uint32Values[index];
|
||||
|
||||
if (Creature const* creature = ToCreature())
|
||||
if (creature)
|
||||
{
|
||||
if (creature->hasLootRecipient())
|
||||
{
|
||||
@@ -824,16 +844,14 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
}
|
||||
|
||||
// unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
|
||||
if (Unit const* unit = ToUnit())
|
||||
if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT)
|
||||
if (!unit->HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID()))
|
||||
dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT;
|
||||
if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT)
|
||||
if (!unit->HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID()))
|
||||
dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT;
|
||||
*data << dynamicFlags;
|
||||
}
|
||||
// FG: pretend that OTHER players in own group are friendly ("blue")
|
||||
else if (index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE)
|
||||
{
|
||||
Unit const* unit = ToUnit();
|
||||
if (unit->IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && unit->IsInRaidWith(target))
|
||||
{
|
||||
FactionTemplateEntry const* ft1 = unit->getFactionTemplateEntry();
|
||||
@@ -866,7 +884,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isType(TYPEMASK_GAMEOBJECT)) // gameobject case
|
||||
else if (go) // gameobject case
|
||||
{
|
||||
for (uint16 index = 0; index < valCount; ++index)
|
||||
{
|
||||
@@ -877,7 +895,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
{
|
||||
if (IsActivateToQuest)
|
||||
{
|
||||
switch (ToGameObject()->GetGoType())
|
||||
switch (go->GetGoType())
|
||||
{
|
||||
case GAMEOBJECT_TYPE_CHEST:
|
||||
if (target->isGameMaster())
|
||||
@@ -910,8 +928,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask*
|
||||
else if (index == GAMEOBJECT_FLAGS)
|
||||
{
|
||||
uint32 flags = m_uint32Values[index];
|
||||
if (ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_CHEST)
|
||||
if (ToGameObject()->GetGOInfo()->chest.groupLootRules && !ToGameObject()->IsLootAllowedFor(target))
|
||||
if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST)
|
||||
if (go->GetGOInfo()->chest.groupLootRules && !go->IsLootAllowedFor(target))
|
||||
flags |= GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE;
|
||||
|
||||
*data << flags;
|
||||
@@ -1444,6 +1462,14 @@ bool Object::PrintIndexError(uint32 index, bool set) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Position::operator==(Position const &a)
|
||||
{
|
||||
return (G3D::fuzzyEq(a.m_positionX, m_positionX) &&
|
||||
G3D::fuzzyEq(a.m_positionY, m_positionY) &&
|
||||
G3D::fuzzyEq(a.m_positionZ, m_positionZ) &&
|
||||
G3D::fuzzyEq(a.m_orientation, m_orientation));
|
||||
}
|
||||
|
||||
bool Position::HasInLine(WorldObject const* target, float width) const
|
||||
{
|
||||
if (!HasInArc(M_PI, target))
|
||||
@@ -2187,7 +2213,7 @@ bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth) const
|
||||
const WorldObject* seer = this;
|
||||
|
||||
// Pets don't have detection, they use the detection of their masters
|
||||
if (const Unit* thisUnit = ToUnit())
|
||||
if (Unit const* thisUnit = ToUnit())
|
||||
if (Unit* controller = thisUnit->GetCharmerOrOwner())
|
||||
seer = controller;
|
||||
|
||||
@@ -2239,8 +2265,9 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const
|
||||
float distance = GetExactDist(obj);
|
||||
float combatReach = 0.0f;
|
||||
|
||||
if (isType(TYPEMASK_UNIT))
|
||||
combatReach = ((Unit*)this)->GetCombatReach();
|
||||
Unit const* unit = ToUnit();
|
||||
if (unit)
|
||||
combatReach = unit->GetCombatReach();
|
||||
|
||||
if (distance < combatReach)
|
||||
return true;
|
||||
@@ -2248,14 +2275,14 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const
|
||||
if (!HasInArc(M_PI, obj))
|
||||
return false;
|
||||
|
||||
GameObject const* go = ToGameObject();
|
||||
for (uint32 i = 0; i < TOTAL_STEALTH_TYPES; ++i)
|
||||
{
|
||||
if (!(obj->m_stealth.GetFlags() & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (isType(TYPEMASK_UNIT))
|
||||
if (((Unit*)this)->HasAuraTypeWithMiscvalue(SPELL_AURA_DETECT_STEALTH, i))
|
||||
return true;
|
||||
if (unit && unit->HasAuraTypeWithMiscvalue(SPELL_AURA_DETECT_STEALTH, i))
|
||||
return true;
|
||||
|
||||
// Starting points
|
||||
int32 detectionValue = 30;
|
||||
@@ -2267,8 +2294,8 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const
|
||||
|
||||
// Apply modifiers
|
||||
detectionValue += m_stealthDetect.GetValue(StealthType(i));
|
||||
if (obj->isType(TYPEMASK_GAMEOBJECT))
|
||||
if (Unit* owner = ((GameObject*)obj)->GetOwner())
|
||||
if (go)
|
||||
if (Unit* owner = go->GetOwner())
|
||||
detectionValue -= int32(owner->getLevelForTarget(this) - 1) * 5;
|
||||
|
||||
detectionValue -= obj->m_stealth.GetValue(StealthType(i));
|
||||
|
||||
Reference in new issue
Block a user