diff options
| author | Gildor <gildor55@gmail.com> | 2020-04-12 15:28:01 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-12 15:28:01 +0200 |
| commit | 862097a63351e957fd4aa6cb82fe7d9edf4d3926 (patch) | |
| tree | c557ea317bd244ca7ff5f6d688d5a812cf122b41 | |
| parent | c3037c35639a547fca6be02ad1a0a2ed4c1c5fe9 (diff) | |
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>
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 26 | ||||
| -rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.h | 5 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 4 |
4 files changed, 22 insertions, 15 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 32567a37e63..f3b86001aed 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -649,7 +649,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); } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 17376cd2da8..a0de5074ad9 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1691,9 +1691,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) { @@ -2625,8 +2631,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->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) { if (targetUnit && targetUnit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) @@ -2878,7 +2884,7 @@ bool WorldObject::IsValidAttackTarget(WorldObject const* target, SpellInfo const } // CvC case - can attack each other only when one of them is hostile - if (ToUnit() && !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED) && target->ToUnit() && !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) + if (unit && !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED) && target->ToUnit() && !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED)) return IsHostileTo(target) || target->IsHostileTo(this); // PvP, PvC, CvP case @@ -2886,7 +2892,7 @@ bool WorldObject::IsValidAttackTarget(WorldObject const* target, SpellInfo const if (IsFriendlyTo(target) || target->IsFriendlyTo(this)) return false; - Player const* playerAffectingAttacker = ToUnit() && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED) ? GetAffectingPlayer() : nullptr; + Player const* playerAffectingAttacker = unit && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED) ? GetAffectingPlayer() : ToGameObject() ? GetAffectingPlayer() : nullptr; Player const* playerAffectingTarget = target->ToUnit() && target->HasFlag(UNIT_FIELD_FLAGS, 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) @@ -2894,7 +2900,7 @@ bool WorldObject::IsValidAttackTarget(WorldObject const* target, SpellInfo const { Player const* player = playerAffectingAttacker ? playerAffectingAttacker : playerAffectingTarget; - if (Unit const* creature = playerAffectingAttacker ? target->ToUnit() : ToUnit()) + if (Unit const* creature = playerAffectingAttacker ? target->ToUnit() : unit) { if (creature->IsContestedGuard() && player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) return true; @@ -2927,14 +2933,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->HasByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_UNK1) || - unitTarget->HasByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_UNK1); + return playerAffectingAttacker->HasByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_UNK1) || + playerAffectingTarget->HasByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_UNK1); } return true; diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 71f420482a5..637e1ef2fe6 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -887,7 +887,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) { @@ -903,7 +903,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); @@ -912,7 +912,6 @@ namespace Trinity private: WorldObject const* i_obj; - Unit const* i_funit; float i_range; }; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 3e6de8b9baf..ff52652452f 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5186,7 +5186,9 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint { // 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()); |
