Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 4598) +++ src/game/SpellAuras.cpp (working copy) @@ -2303,7 +2303,7 @@ { if(Apply) { - m_target->m_invisibilityvalue = m_modifier.m_amount; + m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); // drop flag at invisible in bg if(Real && m_target->GetTypeId()==TYPEID_PLAYER && ((Player*)m_target)->InBattleGround()) @@ -2325,8 +2325,17 @@ } else { - m_target->m_invisibilityvalue = 0; - //m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_CREEP ); + // recalculate value at modifier remove (current aura already removed) + m_target->m_invisibilityMask &= ~(1 << m_modifier.m_miscvalue); + Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + if((*itr)->GetModifier()->m_miscvalue==m_modifier.m_miscvalue) + { + m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); + break; + } + } // only at real aura remove if(Real) @@ -2346,11 +2355,21 @@ { if(Apply) { - m_target->m_detectInvisibility = m_modifier.m_amount; + m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); } else { - m_target->m_detectInvisibility = 0; + // recalculate value at modifier remove (current aura already removed) + m_target->m_detectInvisibilityMask &= ~(1 << m_modifier.m_miscvalue); + Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); + for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + if((*itr)->GetModifier()->m_miscvalue==m_modifier.m_miscvalue) + { + m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); + break; + } + } } if(Real && m_target->GetTypeId()==TYPEID_PLAYER) Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 4598) +++ src/game/Unit.cpp (working copy) @@ -144,9 +144,9 @@ m_Visibility = VISIBILITY_ON; m_detectStealth = 0; - m_detectInvisibility = 0; + m_detectInvisibilityMask = 0; m_stealthvalue = 0; - m_invisibilityvalue = 0; + m_invisibilityMask = 0; m_transform = 0; m_ShapeShiftForm = 0; m_canModifyStats = false; @@ -5773,18 +5773,62 @@ if (m_Visibility == VISIBILITY_OFF) return false; - // Invisible units, always are visible for units under invisibility or unit that can detect this invisibility - if (m_Visibility == VISIBILITY_GROUP_INVISIBILITY) + // Invisible units, always are visible for units under same invisibility type + if(m_invisibilityMask & u->m_invisibilityMask) + return true; + + // Invisible units, always are visible for unit that can detect this invisibility (have appropriate level for detect) + if(uint32 mask = (m_invisibilityMask & u->m_detectInvisibilityMask)) { - if(u->GetVisibility()== VISIBILITY_GROUP_INVISIBILITY || m_invisibilityvalue <= u->m_detectInvisibility) - return true; + for(uint32 i = 0; i < 10; ++i) + { + if(((1 << i) & mask)==0) + continue; + + // find invisibility level + uint32 invLevel = 0; + Unit::AuraList const& iAuras = GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); + for(Unit::AuraList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr) + if(((*itr)->GetModifier()->m_miscvalue)==i && invLevel < (*itr)->GetModifier()->m_amount) + invLevel = (*itr)->GetModifier()->m_amount; + + // find invisibility detect level + uint32 detectLevel = 0; + Unit::AuraList const& dAuras = u->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); + for(Unit::AuraList::const_iterator itr = dAuras.begin(); itr != dAuras.end(); ++itr) + if(((*itr)->GetModifier()->m_miscvalue)==i && detectLevel < (*itr)->GetModifier()->m_amount) + detectLevel = (*itr)->GetModifier()->m_amount; + + if(invLevel <= detectLevel) + return true; + } } // Units that can detect invisibility always are visible for units that can be detected - if (u->GetVisibility()== VISIBILITY_GROUP_INVISIBILITY) + if(uint32 mask = (m_detectInvisibilityMask & u->m_invisibilityMask)) { - if(m_detectInvisibility >= u->m_invisibilityvalue) - return true; + for(uint32 i = 0; i < 10; ++i) + { + if(((1 << i) & mask)==0) + continue; + + // find invisibility level + uint32 invLevel = 0; + Unit::AuraList const& iAuras = u->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); + for(Unit::AuraList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr) + if(((*itr)->GetModifier()->m_miscvalue)==i && invLevel < (*itr)->GetModifier()->m_amount) + invLevel = (*itr)->GetModifier()->m_amount; + + // find invisibility detect level + uint32 detectLevel = 0; + Unit::AuraList const& dAuras = GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); + for(Unit::AuraList::const_iterator itr = dAuras.begin(); itr != dAuras.end(); ++itr) + if(((*itr)->GetModifier()->m_miscvalue)==i && detectLevel < (*itr)->GetModifier()->m_amount) + detectLevel = (*itr)->GetModifier()->m_amount; + + if(invLevel <= detectLevel) + return true; + } } // Stealth/invisible not hostile units, not visible (except Player-with-Player case) Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 4598) +++ src/game/Unit.h (working copy) @@ -1034,9 +1034,9 @@ uint64 m_TotemSlot[4]; uint64 m_ObjectSlot[4]; uint32 m_detectStealth; - uint32 m_detectInvisibility; + uint32 m_detectInvisibilityMask; uint32 m_stealthvalue; - uint32 m_invisibilityvalue; + uint32 m_invisibilityMask; uint32 m_ShapeShiftForm; uint32 m_form; int32 m_modHitChance;