[svn] Rewrite canSeeOrDetect function.
Minor change on trigger creatures. Remove some unused hacks in scripts. --HG-- branch : trunk
This commit is contained in:
+46
-1
@@ -319,6 +319,10 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
|
||||
m_spells[2] = GetCreatureInfo()->spell3;
|
||||
m_spells[3] = GetCreatureInfo()->spell4;
|
||||
|
||||
// HACK: trigger creature is always not selectable
|
||||
if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1487,6 +1491,47 @@ void Creature::DeleteFromDB()
|
||||
WorldDatabase.CommitTransaction();
|
||||
}
|
||||
|
||||
bool Creature::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const
|
||||
{
|
||||
// not in world
|
||||
if(!IsInWorld() || !u->IsInWorld())
|
||||
return false;
|
||||
|
||||
// all dead creatures/players not visible for any creatures
|
||||
if(!u->isAlive() || !isAlive())
|
||||
return false;
|
||||
|
||||
// Always can see self
|
||||
if (u == this)
|
||||
return true;
|
||||
|
||||
// always seen by owner
|
||||
if(GetGUID() == u->GetCharmerOrOwnerGUID())
|
||||
return true;
|
||||
|
||||
if(u->GetVisibility() == VISIBILITY_OFF) //GM
|
||||
return false;
|
||||
|
||||
// invisible aura
|
||||
if((m_invisibilityMask || u->m_invisibilityMask) && !canDetectInvisibilityOf(u))
|
||||
return false;
|
||||
|
||||
// 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(u->GetVisibility() == VISIBILITY_GROUP_STEALTH)
|
||||
{
|
||||
//do not know what is the use of this detect
|
||||
if(!detect || !canDetectStealthOf(u, GetDistance(u)))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now check is target visible with LoS
|
||||
return u->IsWithinLOS(GetPositionX(),GetPositionY(),GetPositionZ());
|
||||
}
|
||||
|
||||
float Creature::GetAttackDistance(Unit const* pl) const
|
||||
{
|
||||
float aggroRate = sWorld.getRate(RATE_CREATURE_AGGRO);
|
||||
@@ -1698,7 +1743,7 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Creature::IsVisibleInGridForPlayer(Player* pl) const
|
||||
bool Creature::IsVisibleInGridForPlayer(Player const* pl) const
|
||||
{
|
||||
// gamemaster in GM mode see all, including ghosts
|
||||
if(pl->isGameMaster())
|
||||
|
||||
+2
-1
@@ -547,6 +547,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
|
||||
CreatureSpellCooldowns m_CreatureCategoryCooldowns;
|
||||
uint32 m_GlobalCooldown;
|
||||
|
||||
bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const;
|
||||
float GetAttackDistance(Unit const* pl) const;
|
||||
|
||||
void CallAssistence();
|
||||
@@ -560,7 +561,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
|
||||
Cell const& GetCurrentCell() const { return m_currentCell; }
|
||||
void SetCurrentCell(Cell const& cell) { m_currentCell = cell; }
|
||||
|
||||
bool IsVisibleInGridForPlayer(Player* pl) const;
|
||||
bool IsVisibleInGridForPlayer(Player const* pl) const;
|
||||
|
||||
void RemoveCorpse();
|
||||
|
||||
|
||||
+1
-1
@@ -1486,7 +1486,7 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa
|
||||
{
|
||||
if(GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER)
|
||||
pCreature->setFaction(((Unit*)this)->getFaction());
|
||||
pCreature->CastSpell(pCreature, pCreature->m_spells[0], true, 0, 0, GetGUID());
|
||||
pCreature->CastSpell(pCreature, pCreature->m_spells[0], false, 0, 0, GetGUID());
|
||||
}
|
||||
|
||||
//return the creature therewith the summoner has access to it
|
||||
|
||||
@@ -50,13 +50,13 @@ bool OutdoorPvPObjectiveAI::IsVisible(Unit *pl) const
|
||||
|
||||
void OutdoorPvPObjectiveAI::AttackStart(Unit *)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
//EnterEvadeMode();
|
||||
}
|
||||
|
||||
void OutdoorPvPObjectiveAI::EnterEvadeMode()
|
||||
{
|
||||
i_creature.DeleteThreatList();
|
||||
i_creature.CombatStop();
|
||||
// i_creature.DeleteThreatList();
|
||||
// i_creature.CombatStop();
|
||||
}
|
||||
|
||||
void OutdoorPvPObjectiveAI::UpdateAI(const uint32 diff)
|
||||
|
||||
+104
-4
@@ -2000,8 +2000,8 @@ void Player::SetGMVisible(bool on)
|
||||
// Reapply stealth/invisibility if active or show if not any
|
||||
if(HasAuraType(SPELL_AURA_MOD_STEALTH))
|
||||
SetVisibility(VISIBILITY_GROUP_STEALTH);
|
||||
else if(HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
|
||||
SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
|
||||
//else if(HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
|
||||
// SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
|
||||
else
|
||||
SetVisibility(VISIBILITY_ON);
|
||||
}
|
||||
@@ -16395,7 +16395,6 @@ void Player::HandleStealthedUnitsDetection()
|
||||
|
||||
if ((*i)->isVisibleForOrDetect(this,true))
|
||||
{
|
||||
|
||||
(*i)->SendUpdateToPlayer(this);
|
||||
m_clientGUIDs.insert((*i)->GetGUID());
|
||||
|
||||
@@ -17188,7 +17187,108 @@ void Player::ReportedAfkBy(Player* reporter)
|
||||
}
|
||||
}
|
||||
|
||||
bool Player::IsVisibleInGridForPlayer( Player* pl ) const
|
||||
bool Player::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const
|
||||
{
|
||||
// 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 =
|
||||
GetTransport() && u->GetTypeId() == TYPEID_PLAYER
|
||||
&& !GetSession()->PlayerLogout() && !((Player*)u)->GetSession()->PlayerLogout()
|
||||
&& !GetSession()->PlayerLoading() && !((Player*)u)->GetSession()->PlayerLoading()
|
||||
&& GetTransport() == ((Player*)u)->GetTransport();
|
||||
|
||||
// not in world
|
||||
if(!at_same_transport && (!IsInWorld() || !u->IsInWorld()))
|
||||
return false;
|
||||
|
||||
// forbidden to seen (at GM respawn command)
|
||||
if(u->GetVisibility() == VISIBILITY_RESPAWN)
|
||||
return false;
|
||||
|
||||
// always seen by owner
|
||||
if(GetGUID() == u->GetCharmerOrOwnerGUID())
|
||||
return true;
|
||||
|
||||
// Grid dead/alive checks
|
||||
// non visible at grid for any stealth state
|
||||
if(!u->IsVisibleInGridForPlayer(this))
|
||||
return false;
|
||||
|
||||
// If the player is currently possessing, update visibility from the possessed unit's location
|
||||
const Unit* target = isPossessing() ? GetCharm() : this;
|
||||
|
||||
// different visible distance checks
|
||||
if(isInFlight()) // what see player in flight
|
||||
{
|
||||
if (!target->IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)))
|
||||
return false;
|
||||
}
|
||||
else if(!u->isAlive()) // distance for show body
|
||||
{
|
||||
if (!target->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)))
|
||||
return false;
|
||||
}
|
||||
else if(u->GetTypeId()==TYPEID_PLAYER) // distance for show player
|
||||
{
|
||||
// Players far than max visible distance for player or not in our map are not visible too
|
||||
if (!at_same_transport && !target->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
|
||||
return false;
|
||||
}
|
||||
else if(u->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 (!target->IsWithinDistInMap(u,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 (!target->IsWithinDistInMap(u, target->isActive()
|
||||
? (MAX_VISIBILITY_DISTANCE - (inVisibleList ? 0.0f : World::GetVisibleUnitGreyDistance()))
|
||||
: (World::GetMaxVisibleDistanceForCreature() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))))
|
||||
return false;
|
||||
}
|
||||
|
||||
// GMs see any players, not higher GMs and all units
|
||||
if(isGameMaster())
|
||||
{
|
||||
if(u->GetTypeId() == TYPEID_PLAYER)
|
||||
return ((Player *)u)->GetSession()->GetSecurity() <= GetSession()->GetSecurity();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
if(u->GetVisibility() == VISIBILITY_OFF)
|
||||
return false;
|
||||
|
||||
// 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((m_invisibilityMask || u->m_invisibilityMask) && !canDetectInvisibilityOf(u))
|
||||
if(!(u->GetTypeId()==TYPEID_PLAYER && !IsHostileTo(u) && IsGroupVisibleFor(((Player*)u))))
|
||||
return false;
|
||||
|
||||
// GM invisibility checks early, invisibility if any detectable, so if not stealth then visible
|
||||
if(u->GetVisibility() == VISIBILITY_GROUP_STEALTH)
|
||||
{
|
||||
// if player is dead then he can't detect anyone in anycases
|
||||
//do not know what is the use of this detect
|
||||
// stealth and detected and visible for some seconds
|
||||
if(!isAlive())
|
||||
detect = false;
|
||||
if(m_DetectInvTimer < 300 || !HaveAtClient(u))
|
||||
if(!(u->GetTypeId()==TYPEID_PLAYER && !IsHostileTo(u) && IsGroupVisibleFor(((Player*)u))))
|
||||
if(!detect || !canDetectStealthOf(u, GetDistance(u)))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now check is target visible with LoS
|
||||
return u->IsWithinLOS(GetPositionX(),GetPositionY(),GetPositionZ());
|
||||
}
|
||||
|
||||
bool Player::IsVisibleInGridForPlayer( Player const * pl ) const
|
||||
{
|
||||
// gamemaster in GM mode see all, including ghosts
|
||||
if(pl->isGameMaster() && GetSession()->GetSecurity() <= pl->GetSession()->GetSecurity())
|
||||
|
||||
+3
-2
@@ -1992,9 +1992,10 @@ class TRINITY_DLL_SPEC Player : public Unit
|
||||
typedef std::set<uint64> ClientGUIDs;
|
||||
ClientGUIDs m_clientGUIDs;
|
||||
|
||||
bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }
|
||||
bool HaveAtClient(WorldObject const* u) const { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }
|
||||
|
||||
bool IsVisibleInGridForPlayer(Player* pl) const;
|
||||
bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const;
|
||||
bool IsVisibleInGridForPlayer(Player const* pl) const;
|
||||
bool IsVisibleGloballyFor(Player* pl) const;
|
||||
|
||||
void UpdateVisibilityOf(WorldObject* target);
|
||||
|
||||
@@ -3230,7 +3230,8 @@ void Aura::HandleModStealth(bool apply, bool Real)
|
||||
// apply only if not in GM invisibility (and overwrite invisibility state)
|
||||
if(m_target->GetVisibility()!=VISIBILITY_OFF)
|
||||
{
|
||||
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
|
||||
//m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
|
||||
m_target->SetVisibility(VISIBILITY_OFF);
|
||||
m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
|
||||
}
|
||||
|
||||
@@ -3258,8 +3259,9 @@ void Aura::HandleModStealth(bool apply, bool Real)
|
||||
// restore invisibility if any
|
||||
if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
|
||||
{
|
||||
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
|
||||
m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
|
||||
//m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
|
||||
//m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
|
||||
m_target->SetVisibility(VISIBILITY_ON);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3314,8 +3316,9 @@ void Aura::HandleInvisibility(bool apply, bool Real)
|
||||
if(m_target->GetVisibility()==VISIBILITY_ON)
|
||||
{
|
||||
// Aura not added yet but visibility code expect temporary add aura
|
||||
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
|
||||
m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
|
||||
//m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
|
||||
//m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
|
||||
m_target->SetVisibility(VISIBILITY_ON);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -3576,6 +3576,13 @@ void Spell::EffectSummonGuardian(uint32 i)
|
||||
return;
|
||||
}
|
||||
|
||||
// trigger
|
||||
if(m_spellInfo->Id == 40276)
|
||||
{
|
||||
EffectSummonWild(i);
|
||||
return;
|
||||
}
|
||||
|
||||
// set timer for unsummon
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
|
||||
|
||||
+54
-254
@@ -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,259 +8577,23 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList)
|
||||
{
|
||||
if(!u)
|
||||
return false;
|
||||
|
||||
// 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;
|
||||
|
||||
// always seen by owner
|
||||
if(GetCharmerOrOwnerGUID()==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(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
|
||||
{
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if(((Player*)this)->IsGroupVisibleFor(((Player*)u)))
|
||||
return true;
|
||||
|
||||
// else apply same rules as for hostile case (detecting check for stealth)
|
||||
}
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
//if in non-detect mode then invisible for unit
|
||||
if (!detect)
|
||||
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)
|
||||
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))
|
||||
return false;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Now check is target visible with LoS
|
||||
float ox,oy,oz;
|
||||
u->GetPosition(ox,oy,oz);
|
||||
return IsWithinLOS(ox,oy,oz);
|
||||
return u->canSeeOrDetect(this, detect, inVisibleList);
|
||||
}
|
||||
|
||||
void Unit::SetVisibility(UnitVisibility x)
|
||||
bool Unit::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const
|
||||
{
|
||||
m_Visibility = x;
|
||||
|
||||
if(IsInWorld())
|
||||
{
|
||||
Map *m = MapManager::Instance().GetMap(GetMapId(), this);
|
||||
|
||||
if(GetTypeId()==TYPEID_PLAYER)
|
||||
m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
|
||||
else
|
||||
m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if(uint32 mask = (m_detectInvisibilityMask & u->m_invisibilityMask))
|
||||
{
|
||||
for(uint32 i = 0; i < 10; ++i)
|
||||
@@ -8849,15 +8610,17 @@ bool Unit::canDetectInvisibilityOf(Unit const* u) const
|
||||
|
||||
// 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();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if(invLevel <= detectLevel)
|
||||
return true;
|
||||
@@ -8867,6 +8630,43 @@ bool Unit::canDetectInvisibilityOf(Unit const* u) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Unit::canDetectStealthOf(Unit const* target, float distance) const
|
||||
{
|
||||
if(hasUnitState(UNIT_STAT_STUNNED))
|
||||
return false;
|
||||
if(distance < 0.24f) //collision
|
||||
return true;
|
||||
if(!HasInArc(M_PI, target)) //behind
|
||||
return false;
|
||||
if(HasAuraType(SPELL_AURA_DETECT_STEALTH))
|
||||
return true;
|
||||
|
||||
//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;
|
||||
|
||||
return distance < visibleDistance;
|
||||
}
|
||||
|
||||
void Unit::SetVisibility(UnitVisibility x)
|
||||
{
|
||||
m_Visibility = x;
|
||||
|
||||
if(IsInWorld())
|
||||
{
|
||||
Map *m = MapManager::Instance().GetMap(GetMapId(), this);
|
||||
|
||||
if(GetTypeId()==TYPEID_PLAYER)
|
||||
m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
|
||||
else
|
||||
m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
|
||||
{
|
||||
int32 main_speed_mod = 0;
|
||||
|
||||
+5
-3
@@ -437,8 +437,8 @@ enum UnitVisibility
|
||||
VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other
|
||||
VISIBILITY_ON = 1,
|
||||
VISIBILITY_GROUP_STEALTH = 2, // detect chance, seen and can see group members
|
||||
VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit, set only if not stealthed, and in checks not used (mask used instead)
|
||||
VISIBILITY_GROUP_NO_DETECT = 4, // state just at stealth apply for update Grid state. Don't remove, otherwise stealth spells will break
|
||||
//VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit, set only if not stealthed, and in checks not used (mask used instead)
|
||||
//VISIBILITY_GROUP_NO_DETECT = 4, // state just at stealth apply for update Grid state. Don't remove, otherwise stealth spells will break
|
||||
VISIBILITY_RESPAWN = 5 // special totally not detectable visibility for force delete object at respawn command
|
||||
};
|
||||
|
||||
@@ -1135,13 +1135,15 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
||||
void SetVisibility(UnitVisibility x);
|
||||
|
||||
// common function for visibility checks for player/creatures with detection code
|
||||
virtual bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const;
|
||||
bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false) const;
|
||||
bool canDetectInvisibilityOf(Unit const* u) const;
|
||||
bool canDetectStealthOf(Unit const* u, float distance) const;
|
||||
|
||||
// virtual functions for all world objects types
|
||||
bool isVisibleForInState(Player const* u, bool inVisibleList) const;
|
||||
// function for low level grid visibility checks in player/creature cases
|
||||
virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0;
|
||||
virtual bool IsVisibleInGridForPlayer(Player const* pl) const = 0;
|
||||
|
||||
bool waterbreath;
|
||||
AuraList & GetSingleCastAuras() { return m_scAuras; }
|
||||
|
||||
Reference in New Issue
Block a user