[11206] Move visibility self/around to new function and use it.

* Fixed wrong visibility changes in some cases at .mod phase uses.
* Apply phase change to any owned units (not only pets as before).
  It also will applied in more safe way for avoid unexpected lost owner at update.
* Check view point setting auras targets accessability not only at visibility change
  but also at phase change.
* Replace SetVisibility(GetVisibility()) hack like calls.
This commit is contained in:
VladimirMangos 2011-02-27 19:16:31 +03:00
parent bef47ce126
commit f1899e3b27
6 changed files with 64 additions and 50 deletions

View file

@ -1912,10 +1912,7 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
m_phaseMask = newPhaseMask; m_phaseMask = newPhaseMask;
if(update && IsInWorld()) if(update && IsInWorld())
{ UpdateVisibilityAndView();
UpdateObjectVisibility();
GetViewPoint().Event_ViewPointVisibilityChanged();
}
} }
void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ ) void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ )
@ -1939,6 +1936,13 @@ void WorldObject::PlayDirectSound( uint32 sound_id, Player* target /*= NULL*/ )
SendMessageToSet( &data, true ); SendMessageToSet( &data, true );
} }
void WorldObject::UpdateVisibilityAndView()
{
GetViewPoint().Call_UpdateVisibilityForOwner();
UpdateObjectVisibility();
GetViewPoint().Event_ViewPointVisibilityChanged();
}
void WorldObject::UpdateObjectVisibility() void WorldObject::UpdateObjectVisibility()
{ {
CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()); CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY());

View file

@ -551,6 +551,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void AddObjectToRemoveList(); void AddObjectToRemoveList();
void UpdateObjectVisibility(); void UpdateObjectVisibility();
virtual void UpdateVisibilityAndView(); // update visibility for object and object for all around
// main visibility check function in normal case (ignore grey zone distance check) // main visibility check function in normal case (ignore grey zone distance check)
bool isVisibleFor(Player const* u, WorldObject const* viewPoint) const { return isVisibleForInState(u,viewPoint,false); } bool isVisibleFor(Player const* u, WorldObject const* viewPoint) const { return isVisibleForInState(u,viewPoint,false); }

View file

@ -8101,9 +8101,7 @@ void Aura::HandlePhase(bool apply, bool Real)
else else
target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL, false); target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL, false);
// need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases) target->UpdateVisibilityAndView();
if(target->GetVisibility() != VISIBILITY_OFF)
target->SetVisibility(target->GetVisibility());
} }
void Aura::HandleAuraSafeFall( bool Apply, bool Real ) void Aura::HandleAuraSafeFall( bool Apply, bool Real )

View file

@ -8057,45 +8057,44 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
return IsWithinLOS(ox,oy,oz); return IsWithinLOS(ox,oy,oz);
} }
void Unit::UpdateVisibilityAndView()
{
static const AuraType auratypes[] = {SPELL_AURA_BIND_SIGHT, SPELL_AURA_FAR_SIGHT, SPELL_AURA_NONE};
for (AuraType const* type = &auratypes[0]; *type != SPELL_AURA_NONE; ++type)
{
AuraList& alist = m_modAuras[*type];
if(alist.empty())
continue;
for (AuraList::iterator it = alist.begin(); it != alist.end();)
{
Aura* aura = (*it);
Unit* owner = aura->GetCaster();
if (!owner || !isVisibleForOrDetect(owner,this,false))
{
alist.erase(it);
RemoveAura(aura);
it = alist.begin();
}
else
++it;
}
}
GetViewPoint().Call_UpdateVisibilityForOwner();
UpdateObjectVisibility();
ScheduleAINotify(0);
GetViewPoint().Event_ViewPointVisibilityChanged();
}
void Unit::SetVisibility(UnitVisibility x) void Unit::SetVisibility(UnitVisibility x)
{ {
m_Visibility = x; m_Visibility = x;
if(IsInWorld()) if(IsInWorld())
{ UpdateVisibilityAndView();
// some auras requires visible target
if(m_Visibility == VISIBILITY_GROUP_NO_DETECT || m_Visibility == VISIBILITY_OFF)
{
static const AuraType auratypes[] = {SPELL_AURA_BIND_SIGHT, SPELL_AURA_FAR_SIGHT, SPELL_AURA_NONE};
for (AuraType const* type = &auratypes[0]; *type != SPELL_AURA_NONE; ++type)
{
AuraList& alist = m_modAuras[*type];
if(alist.empty())
continue;
for (AuraList::iterator it = alist.begin(); it != alist.end();)
{
Aura* aura = (*it);
Unit* owner = aura->GetCaster();
if (!owner || !isVisibleForOrDetect(owner,this,false))
{
alist.erase(it);
RemoveAura(aura);
it = alist.begin();
}
else
++it;
}
}
}
GetViewPoint().Call_UpdateVisibilityForOwner();
UpdateObjectVisibility();
ScheduleAINotify(0);
GetViewPoint().Event_ViewPointVisibilityChanged();
}
} }
bool Unit::canDetectInvisibilityOf(Unit const* u) const bool Unit::canDetectInvisibilityOf(Unit const* u) const
@ -10373,14 +10372,14 @@ void Unit::SetContestedPvP(Player *attackedPlayer)
player->addUnitState(UNIT_STAT_ATTACK_PLAYER); player->addUnitState(UNIT_STAT_ATTACK_PLAYER);
player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP); player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP);
// call MoveInLineOfSight for nearby contested guards // call MoveInLineOfSight for nearby contested guards
SetVisibility(GetVisibility()); UpdateVisibilityAndView();
} }
if (!hasUnitState(UNIT_STAT_ATTACK_PLAYER)) if (!hasUnitState(UNIT_STAT_ATTACK_PLAYER))
{ {
addUnitState(UNIT_STAT_ATTACK_PLAYER); addUnitState(UNIT_STAT_ATTACK_PLAYER);
// call MoveInLineOfSight for nearby contested guards // call MoveInLineOfSight for nearby contested guards
SetVisibility(GetVisibility()); UpdateVisibilityAndView();
} }
} }
@ -10469,19 +10468,30 @@ void Unit::RemoveAurasAtMechanicImmunity(uint32 mechMask, uint32 exceptSpellId,
} }
} }
struct SetPhaseMaskHelper
{
explicit SetPhaseMaskHelper(uint32 _phaseMask) : phaseMask(_phaseMask) {}
void operator()(Unit* unit) const { unit->SetPhaseMask(phaseMask, true); }
uint32 phaseMask;
};
void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
{ {
if(newPhaseMask==GetPhaseMask()) if (newPhaseMask==GetPhaseMask())
return; return;
if(IsInWorld()) // first move to both phase for proper update controlled units
WorldObject::SetPhaseMask(GetPhaseMask() | newPhaseMask, false);
if (IsInWorld())
{
RemoveNotOwnSingleTargetAuras(newPhaseMask); // we can lost access to caster or target RemoveNotOwnSingleTargetAuras(newPhaseMask); // we can lost access to caster or target
WorldObject::SetPhaseMask(newPhaseMask,update); // all controlled except not owned charmed units
CallForAllControlledUnits(SetPhaseMaskHelper(newPhaseMask), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_MINIPET|CONTROLLED_TOTEMS);
}
if(IsInWorld()) WorldObject::SetPhaseMask(newPhaseMask, update);
if(Pet* pet = GetPet())
pet->SetPhaseMask(newPhaseMask,true);
} }
void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ ) void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ )

View file

@ -1710,6 +1710,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
// Visibility system // Visibility system
UnitVisibility GetVisibility() const { return m_Visibility; } UnitVisibility GetVisibility() const { return m_Visibility; }
void SetVisibility(UnitVisibility x); void SetVisibility(UnitVisibility x);
void UpdateVisibilityAndView(); // overwrite WorldObject::UpdateVisibilityAndView()
// common function for visibility checks for player/creatures with detection code // common function for visibility checks for player/creatures with detection code
bool isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, bool detect, bool inVisibleList = false, bool is3dDistance = true) const; bool isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, bool detect, bool inVisibleList = false, bool is3dDistance = true) const;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11205" #define REVISION_NR "11206"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__