aboutsummaryrefslogtreecommitdiff
path: root/src/game/Unit.cpp
diff options
context:
space:
mode:
authormegamage <none@none>2008-11-06 10:27:58 -0600
committermegamage <none@none>2008-11-06 10:27:58 -0600
commit43910434c5eb2240dc4b4585ccbb5f95fa399d53 (patch)
tree3dd9f0bc0c9bdc5d6d3ab84585d9c2dea50cd2ef /src/game/Unit.cpp
parent5746d0e98d8a5c4af96102835d501c47ed370def (diff)
[svn] Rewrite canSeeOrDetect function.
Minor change on trigger creatures. Remove some unused hacks in scripts. --HG-- branch : trunk
Diffstat (limited to 'src/game/Unit.cpp')
-rw-r--r--src/game/Unit.cpp306
1 files changed, 53 insertions, 253 deletions
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 0c94c095c3e..00cd8694b35 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -8506,9 +8506,6 @@ bool Unit::isTargetableForAttack() const
if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
return false;
- if(GetTypeId()==TYPEID_UNIT && (((Creature *)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER))
- return false;
-
return isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;
}
@@ -8580,240 +8577,79 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList)
{
if(!u)
return false;
+ return u->canSeeOrDetect(this, detect, inVisibleList);
+}
- // Always can see self
- if (u==this)
- return true;
-
- // player visible for other player if not logout and at same transport
- // including case when player is out of world
- bool at_same_transport =
- GetTypeId() == TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER &&
- !((Player*)this)->GetSession()->PlayerLogout() && !((Player*)u)->GetSession()->PlayerLogout() &&
- !((Player*)this)->GetSession()->PlayerLoading() && !((Player*)u)->GetSession()->PlayerLoading() &&
- ((Player*)this)->GetTransport() && ((Player*)this)->GetTransport() == ((Player*)u)->GetTransport();
-
- // not in world
- if(!at_same_transport && (!IsInWorld() || !u->IsInWorld()))
- return false;
-
- // forbidden to seen (at GM respawn command)
- if(m_Visibility==VISIBILITY_RESPAWN)
- return false;
+bool Unit::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const
+{
+ return true;
+}
- // always seen by owner
- if(GetCharmerOrOwnerGUID()==u->GetGUID())
+bool Unit::canDetectInvisibilityOf(Unit const* u) const
+{
+ if(m_invisibilityMask & u->m_invisibilityMask) // same group
return true;
+ AuraList const& auras = GetAurasByType(SPELL_AURA_MOD_STALKED); // Hunter mark
+ for(AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
+ if((*iter)->GetCasterGUID()==u->GetGUID())
+ return true;
- // Grid dead/alive checks
- if( u->GetTypeId()==TYPEID_PLAYER)
- {
- // non visible at grid for any stealth state
- if(!IsVisibleInGridForPlayer((Player *)u))
- return false;
-
- // if player is dead then he can't detect anyone in anycases
- if(!u->isAlive())
- detect = false;
- }
- else
- {
- // all dead creatures/players not visible for any creatures
- if(!u->isAlive() || !isAlive())
- return false;
- }
-
- // If the player is currently possessing, update visibility from the possessed unit's location
- const Unit* target = u->GetTypeId() == TYPEID_PLAYER && u->isPossessing() ? u->GetCharm() : u;
-
- // different visible distance checks
- if(u->isInFlight()) // what see player in flight
- {
- // use object grey distance for all (only see objects any way)
- if (!IsWithinDistInMap(target,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)))
- return false;
- }
- else if(!isAlive()) // distance for show body
- {
- if (!IsWithinDistInMap(target,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)))
- return false;
- }
- else if(GetTypeId()==TYPEID_PLAYER) // distance for show player
+ if(uint32 mask = (m_detectInvisibilityMask & u->m_invisibilityMask))
{
- if(u->GetTypeId()==TYPEID_PLAYER)
- {
- // Players far than max visible distance for player or not in our map are not visible too
- if (!at_same_transport && !IsWithinDistInMap(target,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
- return false;
- }
- else
+ for(uint32 i = 0; i < 10; ++i)
{
- // Units far than max visible distance for creature or not in our map are not visible too
- // Active unit should always be visibile
- if (!IsWithinDistInMap(target, target->isActive()
- ? (MAX_VISIBILITY_DISTANCE - (inVisibleList ? 0.0f : World::GetVisibleUnitGreyDistance()))
- : (World::GetMaxVisibleDistanceForCreature() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))))
- return false;
- }
- }
- else if(GetCharmerOrOwnerGUID()) // distance for show pet/charmed
- {
- // Pet/charmed far than max visible distance for player or not in our map are not visible too
- if (!IsWithinDistInMap(target,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
- return false;
- }
- else // distance for show creature
- {
- // Units far than max visible distance for creature or not in our map are not visible too
- if (!IsWithinDistInMap(target,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
- return false;
- }
-
- // Visible units, always are visible for all units, except for units under invisibility
- if (m_Visibility == VISIBILITY_ON && u->m_invisibilityMask==0)
- return true;
-
- // GMs see any players, not higher GMs and all units
- if (u->GetTypeId() == TYPEID_PLAYER && ((Player *)u)->isGameMaster())
- {
- if(GetTypeId() == TYPEID_PLAYER)
- return ((Player *)this)->GetSession()->GetSecurity() <= ((Player *)u)->GetSession()->GetSecurity();
- else
- return true;
- }
-
- // non faction visibility non-breakable for non-GMs
- if (m_Visibility == VISIBILITY_OFF)
- return false;
-
- // raw invisibility
- bool invisible = (m_invisibilityMask != 0 || u->m_invisibilityMask !=0);
+ if(((1 << i) & mask)==0)
+ continue;
- // detectable invisibility case
- if( invisible && (
- // Invisible units, always are visible for units under same invisibility type
- (m_invisibilityMask & u->m_invisibilityMask)!=0 ||
- // Invisible units, always are visible for unit that can detect this invisibility (have appropriate level for detect)
- u->canDetectInvisibilityOf(this) ||
- // Units that can detect invisibility always are visible for units that can be detected
- canDetectInvisibilityOf(u) ))
- {
- invisible = false;
- }
+ // 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;
- // special cases for always overwrite invisibility/stealth
- if(invisible || m_Visibility == VISIBILITY_GROUP_STEALTH)
- {
- // non-hostile case
- if (!u->IsHostileTo(this))
- {
- // player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting)
- if(GetTypeId()==TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER)
+ // find invisibility detect level
+ uint32 detectLevel = 0;
+ if(i==6 && GetTypeId()==TYPEID_PLAYER) // special drunk detection case
{
- if(((Player*)this)->IsGroupVisibleFor(((Player*)u)))
- return true;
-
- // else apply same rules as for hostile case (detecting check for stealth)
+ detectLevel = ((Player*)this)->GetDrunkValue();
+ }
+ else
+ {
+ 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;
}
- }
- // hostile case
- else
- {
- // Hunter mark functionality
- AuraList const& auras = GetAurasByType(SPELL_AURA_MOD_STALKED);
- for(AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
- if((*iter)->GetCasterGUID()==u->GetGUID())
- return true;
- // else apply detecting check for stealth
+ if(invLevel <= detectLevel)
+ return true;
}
-
- // none other cases for detect invisibility, so invisible
- if(invisible)
- return false;
-
- // else apply stealth detecting check
}
- // unit got in stealth in this moment and must ignore old detected state
- if (m_Visibility == VISIBILITY_GROUP_NO_DETECT)
- return false;
-
- // GM invisibility checks early, invisibility if any detectable, so if not stealth then visible
- if (m_Visibility != VISIBILITY_GROUP_STEALTH)
- return true;
-
- // NOW ONLY STEALTH CASE
-
- // stealth and detected and visible for some seconds
- if (u->GetTypeId() == TYPEID_PLAYER && ((Player*)u)->m_DetectInvTimer > 300 && ((Player*)u)->HaveAtClient(this))
- return true;
+ return false;
+}
- //if in non-detect mode then invisible for unit
- if (!detect)
+bool Unit::canDetectStealthOf(Unit const* target, float distance) const
+{
+ if(hasUnitState(UNIT_STAT_STUNNED))
return false;
-
- // Special cases
-
- // If is attacked then stealth is lost, some creature can use stealth too
- if( !getAttackers().empty() )
- return true;
-
- // If there is collision rogue is seen regardless of level difference
- // TODO: check sizes in DB
- float distance = GetDistance(u);
- if (distance < 0.24f)
+ if(distance < 0.24f) //collision
return true;
-
- //If a mob or player is stunned he will not be able to detect stealth
- if (u->hasUnitState(UNIT_STAT_STUNNED) && (u != this))
+ if(!HasInArc(M_PI, target)) //behind
return false;
+ if(HasAuraType(SPELL_AURA_DETECT_STEALTH))
+ return true;
- // Creature can detect target only in aggro radius
- if(u->GetTypeId() != TYPEID_PLAYER)
- {
- //Always invisible from back and out of aggro range
- bool isInFront = u->isInFront(this,((Creature const*)u)->GetAttackDistance(this));
- if(!isInFront)
- return false;
- }
- else
- {
- //Always invisible from back
- bool isInFront = u->isInFront(this,(GetTypeId()==TYPEID_PLAYER || GetCharmerOrOwnerGUID()) ? World::GetMaxVisibleDistanceForPlayer() : World::GetMaxVisibleDistanceForCreature());
- if(!isInFront)
- return false;
- }
-
- // if doesn't have stealth detection (Shadow Sight), then check how stealthy the unit is, otherwise just check los
- if(!u->HasAuraType(SPELL_AURA_DETECT_STEALTH))
- {
- //Calculation if target is in front
-
- //Visible distance based on stealth value (stealth rank 4 300MOD, 10.5 - 3 = 7.5)
- float visibleDistance = 10.5f - (GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH)/100.0f);
-
- //Visible distance is modified by
- //-Level Diff (every level diff = 1.0f in visible distance)
- visibleDistance += int32(u->getLevelForTarget(this)) - int32(this->getLevelForTarget(u));
-
- //This allows to check talent tree and will add addition stealth dependent on used points)
- int32 stealthMod = GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH_LEVEL);
- if(stealthMod < 0)
- stealthMod = 0;
-
- //-Stealth Mod(positive like Master of Deception) and Stealth Detection(negative like paranoia)
- //based on wowwiki every 5 mod we have 1 more level diff in calculation
- visibleDistance += (int32(u->GetTotalAuraModifier(SPELL_AURA_MOD_DETECT)) - stealthMod)/5.0f;
-
- if(distance > visibleDistance)
- return false;
- }
+ //Visible distance based on stealth value (stealth rank 4 300MOD, 10.5 - 3 = 7.5)
+ float visibleDistance = 10.5f - target->GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH) / 100.0f;
+ //Visible distance is modified by -Level Diff (every level diff = 1.0f in visible distance)
+ visibleDistance += int32(getLevelForTarget(target)) - int32(target->getLevelForTarget(this));
+ //-Stealth Mod(positive like Master of Deception) and Stealth Detection(negative like paranoia)
+ //based on wowwiki every 5 mod we have 1 more level diff in calculation
+ visibleDistance += (float)(GetTotalAuraModifier(SPELL_AURA_MOD_DETECT) - target->GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH_LEVEL)) / 5.0f;
- // Now check is target visible with LoS
- float ox,oy,oz;
- u->GetPosition(ox,oy,oz);
- return IsWithinLOS(ox,oy,oz);
+ return distance < visibleDistance;
}
void Unit::SetVisibility(UnitVisibility x)
@@ -8831,42 +8667,6 @@ void Unit::SetVisibility(UnitVisibility x)
}
}
-bool Unit::canDetectInvisibilityOf(Unit const* u) const
-{
- if(uint32 mask = (m_detectInvisibilityMask & u->m_invisibilityMask))
- {
- 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(i==6 && GetTypeId()==TYPEID_PLAYER) // special drunk detection case
- {
- detectLevel = ((Player*)this)->GetDrunkValue();
- }
-
- if(invLevel <= detectLevel)
- return true;
- }
- }
-
- return false;
-}
-
void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
{
int32 main_speed_mod = 0;