From f28c678c14148b1b69b4f50ae0b6e58df2b883f0 Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Mon, 6 Jun 2022 14:03:24 +0200 Subject: [PATCH] =?UTF-8?q?fix(Core/Spells):=20Hunter=20traps=20should=20n?= =?UTF-8?q?ot=20be=20activated=20by=20targets=20not=E2=80=A6=20(#11971)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Core/Spells): Hunter traps should not be activated by targets not in LoS. Fixes #11432 --- .../game/Entities/GameObject/GameObject.cpp | 4 +- .../game/Grids/Notifiers/GridNotifiers.h | 41 +++++++++++++++++++ src/server/game/Spells/Spell.cpp | 14 +++---- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index ef224798d..fdf514c78 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -701,8 +701,8 @@ void GameObject::Update(uint32 diff) // search unfriendly creature if (owner && goInfo->trap.autoCloseTime != -1) // hunter trap { - Acore::AnyUnfriendlyNoTotemUnitInObjectRangeCheck checker(this, owner, radius); - Acore::UnitSearcher searcher(this, target, checker); + Acore::NearestAttackableNoTotemUnitInObjectRangeCheck checker(this, owner, radius); + Acore::UnitSearcher searcher(this, target, checker); Cell::VisitAllObjects(this, searcher, radius); } else // environmental trap diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 654f0aa27..c8692a224 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -898,6 +898,47 @@ namespace Acore float i_range; }; + class NearestAttackableNoTotemUnitInObjectRangeCheck + { + public: + NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* owner, float range) : i_obj(obj), i_owner(owner), i_range(range) {} + + bool operator()(Unit* u) + { + if (!u->IsAlive()) + { + return false; + } + + if (u->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET) + { + return false; + } + + if (u->GetTypeId() == TYPEID_UNIT && u->ToCreature()->IsTotem()) + { + return false; + } + + if (!u->isTargetableForAttack(false, i_owner)) + { + return false; + } + + if (!i_obj->IsWithinDistInMap(u, i_range) || !i_owner->IsValidAttackTarget(u) || !i_obj->IsWithinLOSInMap(u)) + { + return false; + } + + return true; + } + + private: + WorldObject const* i_obj; + Unit const* i_owner; + float i_range; + }; + class AnyUnfriendlyAttackableVisibleUnitInObjectRangeCheck { public: diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 9758eeebc..44df83ab6 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5892,31 +5892,27 @@ SpellCastResult Spell::CheckCast(bool strict) if ((!m_caster->IsTotem() || !m_spellInfo->IsPositive()) && !m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) && !m_spellInfo->HasAttribute(SPELL_ATTR5_ALWAYS_AOE_LINE_OF_SIGHT)) { - WorldObject* losCenter = nullptr; + bool castedByGameobject = false; uint32 losChecks = LINEOFSIGHT_ALL_CHECKS; if (m_originalCasterGUID.IsGameObject()) { - losCenter = m_caster->GetMap()->GetGameObject(m_originalCasterGUID); + castedByGameobject = m_caster->GetMap()->GetGameObject(m_originalCasterGUID) != nullptr; } else if (m_caster->GetEntry() == WORLD_TRIGGER) { if (TempSummon* tempSummon = m_caster->ToTempSummon()) { - losCenter = tempSummon->GetSummonerGameObject(); + castedByGameobject = tempSummon->GetSummonerGameObject() != nullptr; } } - if (losCenter) + if (castedByGameobject) { // If spell casted by gameobject then ignore M2 models losChecks &= ~LINEOFSIGHT_CHECK_GOBJECT_M2; } - else - { - losCenter = m_caster; - } - if (!losCenter->IsWithinLOS(x, y, z, VMAP::ModelIgnoreFlags::M2, LineOfSightChecks((losChecks)))) + if (!m_caster->IsWithinLOS(x, y, z, VMAP::ModelIgnoreFlags::M2, LineOfSightChecks((losChecks)))) { return SPELL_FAILED_LINE_OF_SIGHT; }