diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 4ab10b561..2607d905d 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1912,10 +1912,7 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update) m_phaseMask = newPhaseMask; if(update && IsInWorld()) - { - UpdateObjectVisibility(); - GetViewPoint().Event_ViewPointVisibilityChanged(); - } + UpdateVisibilityAndView(); } 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 ); } +void WorldObject::UpdateVisibilityAndView() +{ + GetViewPoint().Call_UpdateVisibilityForOwner(); + UpdateObjectVisibility(); + GetViewPoint().Event_ViewPointVisibilityChanged(); +} + void WorldObject::UpdateObjectVisibility() { CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()); diff --git a/src/game/Object.h b/src/game/Object.h index 9aa64e55f..d77032dda 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -551,6 +551,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object void AddObjectToRemoveList(); 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) bool isVisibleFor(Player const* u, WorldObject const* viewPoint) const { return isVisibleForInState(u,viewPoint,false); } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index b68add48a..9d00d5677 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -8101,9 +8101,7 @@ void Aura::HandlePhase(bool apply, bool Real) else 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) - if(target->GetVisibility() != VISIBILITY_OFF) - target->SetVisibility(target->GetVisibility()); + target->UpdateVisibilityAndView(); } void Aura::HandleAuraSafeFall( bool Apply, bool Real ) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 46a15e529..62ea6050f 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -8057,45 +8057,44 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo 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) { m_Visibility = x; if(IsInWorld()) - { - // 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(); - } + UpdateVisibilityAndView(); } bool Unit::canDetectInvisibilityOf(Unit const* u) const @@ -10373,14 +10372,14 @@ void Unit::SetContestedPvP(Player *attackedPlayer) player->addUnitState(UNIT_STAT_ATTACK_PLAYER); player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP); // call MoveInLineOfSight for nearby contested guards - SetVisibility(GetVisibility()); + UpdateVisibilityAndView(); } if (!hasUnitState(UNIT_STAT_ATTACK_PLAYER)) { addUnitState(UNIT_STAT_ATTACK_PLAYER); // 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) { - if(newPhaseMask==GetPhaseMask()) + if (newPhaseMask==GetPhaseMask()) 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 - WorldObject::SetPhaseMask(newPhaseMask,update); + // all controlled except not owned charmed units + CallForAllControlledUnits(SetPhaseMaskHelper(newPhaseMask), CONTROLLED_PET|CONTROLLED_GUARDIANS|CONTROLLED_MINIPET|CONTROLLED_TOTEMS); + } - if(IsInWorld()) - if(Pet* pet = GetPet()) - pet->SetPhaseMask(newPhaseMask,true); + WorldObject::SetPhaseMask(newPhaseMask, update); } void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ ) diff --git a/src/game/Unit.h b/src/game/Unit.h index ffaed0a09..a0b14adcc 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1710,6 +1710,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject // Visibility system UnitVisibility GetVisibility() const { return m_Visibility; } void SetVisibility(UnitVisibility x); + void UpdateVisibilityAndView(); // overwrite WorldObject::UpdateVisibilityAndView() // 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; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3b2c8be06..257738e43 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11205" + #define REVISION_NR "11206" #endif // __REVISION_NR_H__