diff options
author | Jeremy <Golrag@users.noreply.github.com> | 2023-06-28 19:01:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-28 19:01:14 +0200 |
commit | 815e158a3ec5f5e173376ff4273913990e9bce10 (patch) | |
tree | c9e2837e673232e3d84b969cefed1100e5862a15 /src | |
parent | be81ff713333225ffa6f1d4c2b608db8a8fffe26 (diff) |
Core/Creatures: Implement CREATURE_STATIC_FLAG_4_IGNORE_LOS_WHEN_CASTING_ON_ME (#29029)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 53 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 4 |
3 files changed, 43 insertions, 15 deletions
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 3220fb38c8c..46aa837a386 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -187,6 +187,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); } bool CanMelee() const { return !_staticFlags.HasFlag(CREATURE_STATIC_FLAG_NO_MELEE); } void SetCanMelee(bool canMelee) { _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_NO_MELEE, !canMelee); } + bool CanIgnoreLineOfSightWhenCastingOnMe() const { return _staticFlags.HasFlag(CREATURE_STATIC_FLAG_4_IGNORE_LOS_WHEN_CASTING_ON_ME); } bool HasSpell(uint32 spellID) const override; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 8a55827d6d6..0b5c23de9f0 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2251,7 +2251,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar if (Unit* unit = (*itr)->ToUnit()) { uint32 deficit = unit->GetMaxHealth() - unit->GetHealth(); - if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && chainSource->IsWithinDist(unit, jumpRadius) && chainSource->IsWithinLOSInMap(unit, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && chainSource->IsWithinDist(unit, jumpRadius) && IsWithinLOS(chainSource, unit, false, VMAP::ModelIgnoreFlags::M2)) { foundItr = itr; maxHPDeficit = deficit; @@ -2266,10 +2266,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar { if (foundItr == tempTargets.end()) { - if (chainSource->IsWithinDist(*itr, jumpRadius) && chainSource->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if (chainSource->IsWithinDist(*itr, jumpRadius) && IsWithinLOS(chainSource, *itr, false, VMAP::ModelIgnoreFlags::M2)) foundItr = itr; } - else if (chainSource->GetDistanceOrder(*itr, *foundItr) && chainSource->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + else if (chainSource->GetDistanceOrder(*itr, *foundItr) && IsWithinLOS(chainSource, *itr, false, VMAP::ModelIgnoreFlags::M2)) foundItr = itr; } } @@ -5774,7 +5774,7 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32 if (DynamicObject* dynObj = m_caster->ToUnit()->GetDynObject(m_triggeredByAuraSpell->Id)) losTarget = dynObj; - if (!m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, nullptr, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if (!IsWithinLOS(losTarget, target, true, VMAP::ModelIgnoreFlags::M2)) return SPELL_FAILED_LINE_OF_SIGHT; } } @@ -5782,13 +5782,8 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32 // Check for line of sight for spells with dest if (m_targets.HasDst()) - { - float x, y, z; - m_targets.GetDstPos()->GetPosition(x, y, z); - - if (!m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, nullptr, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if (!IsWithinLOS(m_caster, *m_targets.GetDstPos(), VMAP::ModelIgnoreFlags::M2)) return SPELL_FAILED_LINE_OF_SIGHT; - } // check pet presence if (Unit* unitCaster = m_caster->ToUnit()) @@ -6070,7 +6065,7 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32 return SPELL_FAILED_DONT_REPORT; // first we must check to see if the target is in LoS. A path can usually be built but LoS matters for charge spells - if (!target->IsWithinLOSInMap(unitCaster)) //Do full LoS/Path check. Don't exclude m2 + if (!IsWithinLOS(unitCaster, target, true, VMAP::ModelIgnoreFlags::Nothing)) //Do full LoS/Path check. Don't exclude m2 return SPELL_FAILED_LINE_OF_SIGHT; float objSize = target->GetCombatReach(); @@ -7992,7 +7987,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEf { if (!m_targets.GetCorpseTargetGUID()) { - if (target->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2) && target->HasUnitFlag(UNIT_FLAG_SKINNABLE)) + if (IsWithinLOS(m_caster, target, true, VMAP::ModelIgnoreFlags::M2) && target->HasUnitFlag(UNIT_FLAG_SKINNABLE)) return true; return false; @@ -8008,7 +8003,7 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEf if (!corpse->HasDynamicFlag(CORPSE_DYNFLAG_LOOTABLE)) return false; - if (!corpse->IsWithinLOSInMap(m_caster, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if (!IsWithinLOS(m_caster, corpse, true, VMAP::ModelIgnoreFlags::M2)) return false; break; @@ -8023,12 +8018,13 @@ bool Spell::CheckEffectTarget(Unit const* target, SpellEffectInfo const& spellEf caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID); if (!caster) caster = m_caster; - if (target != m_caster && !target->IsWithinLOSInMap(caster, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + + if (target != m_caster && !IsWithinLOS(caster, target, true, VMAP::ModelIgnoreFlags::M2)) return false; } if (losPosition) - if (!target->IsWithinLOS(losPosition->GetPositionX(), losPosition->GetPositionY(), losPosition->GetPositionZ(), LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if (!IsWithinLOS(target, *losPosition, VMAP::ModelIgnoreFlags::M2)) return false; } } @@ -8900,6 +8896,33 @@ void Spell::CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageIn } } +bool Spell::IsWithinLOS(WorldObject const* source, WorldObject const* target, bool targetAsSourceLocation, VMAP::ModelIgnoreFlags ignoreFlags) const +{ + if (m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT)) + return true; + + if (DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, nullptr, SPELL_DISABLE_LOS)) + return true; + + if (target->IsCreature() && target->ToCreature()->CanIgnoreLineOfSightWhenCastingOnMe()) + return true; + + WorldObject const* src = targetAsSourceLocation ? target : source; + WorldObject const* dst = targetAsSourceLocation ? source : target; + return src->IsWithinLOSInMap(dst, LINEOFSIGHT_ALL_CHECKS, ignoreFlags); +} + +bool Spell::IsWithinLOS(WorldObject const* source, Position const& target, VMAP::ModelIgnoreFlags ignoreFlags) const +{ + if (m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT)) + return true; + + if (DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, nullptr, SPELL_DISABLE_LOS)) + return true; + + return source->IsWithinLOS(target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), LINEOFSIGHT_ALL_CHECKS, ignoreFlags); +} + namespace Trinity { diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 38071b7c097..267976119e2 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -20,6 +20,7 @@ #include "ConditionMgr.h" #include "DBCEnums.h" +#include "ModelIgnoreFlags.h" #include "ObjectGuid.h" #include "Optional.h" #include "Position.h" @@ -652,6 +653,9 @@ class TC_GAME_API Spell std::string GetDebugInfo() const; void CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount); + bool IsWithinLOS(WorldObject const* source, WorldObject const* target, bool targetAsSourceLocation, VMAP::ModelIgnoreFlags ignoreFlags) const; + bool IsWithinLOS(WorldObject const* source, Position const& target, VMAP::ModelIgnoreFlags ignoreFlags) const; + protected: bool HasGlobalCooldown() const; void TriggerGlobalCooldown(); |