mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-22 02:04:52 +01:00
Core/Gameobjects: Improve stealth detection (#24417)
* Core/Gameobjects: Improve stealth detection
* fix warning: private field 'i_funit' is not used
* Code cleanup
* add comment
Co-authored-by: jackpoz <giacomopoz@gmail.com>
(cherry picked from commit 862097a633)
This commit is contained in:
@@ -768,7 +768,7 @@ void GameObject::Update(uint32 diff)
|
||||
if (Unit* owner = GetOwner())
|
||||
{
|
||||
// Hunter trap: Search units which are unfriendly to the trap's owner
|
||||
Trinity::NearestAttackableNoTotemUnitInObjectRangeCheck checker(this, owner, radius);
|
||||
Trinity::NearestAttackableNoTotemUnitInObjectRangeCheck checker(this, radius);
|
||||
Trinity::UnitLastSearcher<Trinity::NearestAttackableNoTotemUnitInObjectRangeCheck> searcher(this, target, checker);
|
||||
Cell::VisitAllObjects(this, searcher, radius);
|
||||
}
|
||||
|
||||
@@ -1548,9 +1548,15 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj, bool checkAlert) co
|
||||
if (distance < combatReach)
|
||||
return true;
|
||||
|
||||
if (!HasInArc(float(M_PI), obj))
|
||||
// Only check back for units, it does not make sense for gameobjects
|
||||
if (unit && !HasInArc(float(M_PI), obj))
|
||||
return false;
|
||||
|
||||
// Traps should detect stealth always
|
||||
if (GameObject const* go = ToGameObject())
|
||||
if (go->GetGoType() == GAMEOBJECT_TYPE_TRAP)
|
||||
return true;
|
||||
|
||||
GameObject const* go = obj->ToGameObject();
|
||||
for (uint32 i = 0; i < TOTAL_STEALTH_TYPES; ++i)
|
||||
{
|
||||
@@ -2457,8 +2463,8 @@ ReputationRank WorldObject::GetReactionTo(WorldObject const* target) const
|
||||
return *repRank;
|
||||
}
|
||||
|
||||
Unit const* unit = ToUnit();
|
||||
Unit const* targetUnit = target->ToUnit();
|
||||
Unit const* unit = Coalesce<const Unit>(ToUnit(), selfPlayerOwner);
|
||||
Unit const* targetUnit = Coalesce<const Unit>(target->ToUnit(), targetPlayerOwner);
|
||||
if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
|
||||
{
|
||||
if (targetUnit && targetUnit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
|
||||
@@ -2813,7 +2819,7 @@ bool WorldObject::IsValidAttackTarget(WorldObject const* target, SpellInfo const
|
||||
if (IsFriendlyTo(target) || target->IsFriendlyTo(this))
|
||||
return false;
|
||||
|
||||
Player const* playerAffectingAttacker = unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) ? GetAffectingPlayer() : nullptr;
|
||||
Player const* playerAffectingAttacker = unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) ? GetAffectingPlayer() : ToGameObject() ? GetAffectingPlayer() : nullptr;
|
||||
Player const* playerAffectingTarget = unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) ? target->GetAffectingPlayer() : nullptr;
|
||||
|
||||
// Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
|
||||
@@ -2854,14 +2860,14 @@ bool WorldObject::IsValidAttackTarget(WorldObject const* target, SpellInfo const
|
||||
// additional checks - only PvP case
|
||||
if (playerAffectingAttacker && playerAffectingTarget)
|
||||
{
|
||||
if (unitTarget->IsPvP())
|
||||
if (playerAffectingTarget->IsPvP())
|
||||
return true;
|
||||
|
||||
if (unit->IsFFAPvP() && unitTarget->IsFFAPvP())
|
||||
if (playerAffectingAttacker->IsFFAPvP() && playerAffectingTarget->IsFFAPvP())
|
||||
return true;
|
||||
|
||||
return unit->HasPvpFlag(UNIT_BYTE2_FLAG_UNK1) ||
|
||||
unitTarget->HasPvpFlag(UNIT_BYTE2_FLAG_UNK1);
|
||||
return playerAffectingAttacker->HasPvpFlag(UNIT_BYTE2_FLAG_UNK1) ||
|
||||
playerAffectingTarget->HasPvpFlag(UNIT_BYTE2_FLAG_UNK1);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -945,7 +945,7 @@ namespace Trinity
|
||||
class NearestAttackableNoTotemUnitInObjectRangeCheck
|
||||
{
|
||||
public:
|
||||
NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) { }
|
||||
NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) { }
|
||||
|
||||
bool operator()(Unit* u)
|
||||
{
|
||||
@@ -961,7 +961,7 @@ namespace Trinity
|
||||
if (!u->isTargetableForAttack(false))
|
||||
return false;
|
||||
|
||||
if (!i_obj->IsWithinDistInMap(u, i_range) || !i_funit->IsValidAttackTarget(u))
|
||||
if (!i_obj->IsWithinDistInMap(u, i_range) || !i_obj->IsValidAttackTarget(u))
|
||||
return false;
|
||||
|
||||
i_range = i_obj->GetDistance(*u);
|
||||
@@ -970,7 +970,6 @@ namespace Trinity
|
||||
|
||||
private:
|
||||
WorldObject const* i_obj;
|
||||
Unit const* i_funit;
|
||||
float i_range;
|
||||
};
|
||||
|
||||
|
||||
@@ -5402,7 +5402,9 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32
|
||||
{
|
||||
// Check explicit target for m_originalCaster - todo: get rid of such workarounds
|
||||
WorldObject* caster = m_caster;
|
||||
if (m_originalCaster)
|
||||
// in case of gameobjects like traps, we need the gameobject itself to check target validity
|
||||
// otherwise, if originalCaster is far away and cannot detect the target, the trap would not hit the target
|
||||
if (m_originalCaster && !caster->ToGameObject())
|
||||
caster = m_originalCaster;
|
||||
|
||||
SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(caster, m_targets.GetObjectTarget(), m_targets.GetItemTarget());
|
||||
|
||||
Reference in New Issue
Block a user