diff options
Diffstat (limited to 'src/server/game')
| -rw-r--r-- | src/server/game/Entities/AreaTrigger/AreaTrigger.cpp | 3 | ||||
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 13 | ||||
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.h | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 40 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.h | 8 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 34 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 8 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 18 |
12 files changed, 77 insertions, 63 deletions
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp index 234a03aa9d0..14812acb868 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp @@ -235,7 +235,10 @@ bool AreaTrigger::Create(AreaTriggerCreatePropertiesId areaTriggerCreateProperti } if (target && HasAreaTriggerFlag(AreaTriggerFieldFlags::Attached)) + { m_movementInfo.transport.guid = target->GetGUID(); + m_updateFlag.MovementTransport = true; + } if (!IsStaticSpawn()) UpdatePositionData(); diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index d0f8fb33695..a5742dc17eb 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -430,9 +430,9 @@ public: return 1; } - std::vector<uint32> const* GetPauseTimes() const + std::span<uint32 const> GetPauseTimes() const { - return &_stopFrames; + return _stopFrames; } ObjectGuid GetTransportGUID() const override { return _owner.GetGUID(); } @@ -4136,12 +4136,13 @@ void GameObject::ClearUpdateMask(bool remove) Object::ClearUpdateMask(remove); } -std::vector<uint32> const* GameObject::GetPauseTimes() const +std::span<uint32 const> GameObject::GetPauseTimes() const { + std::span<uint32 const> result; if (GameObjectType::Transport const* transport = dynamic_cast<GameObjectType::Transport const*>(m_goTypeImpl.get())) - return transport->GetPauseTimes(); + result = transport->GetPauseTimes(); - return nullptr; + return result; } void GameObject::SetPathProgressForClient(float progress) @@ -4253,6 +4254,8 @@ void GameObject::SetAnimKitId(uint16 animKitId, bool oneshot) else _animKitId = 0; + m_updateFlag.AnimKit = _animKitId != 0; + WorldPackets::GameObject::GameObjectActivateAnimKit activateAnimKit; activateAnimKit.ObjectGUID = GetGUID(); activateAnimKit.AnimKitID = animKitId; diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 800ef83a09e..5b1ed3b0b0b 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -290,7 +290,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject> void SetGoAnimProgress(uint8 animprogress) { SetUpdateFieldValue(m_values.ModifyValue(&GameObject::m_gameObjectData).ModifyValue(&UF::GameObjectData::PercentHealth), animprogress); } static void SetGoArtKit(uint32 artkit, GameObject* go, ObjectGuid::LowType lowguid = UI64LIT(0)); - std::vector<uint32> const* GetPauseTimes() const; + std::span<uint32 const> GetPauseTimes() const; Optional<float> GetPathProgressForClient() const { return m_transportPathProgress; } void SetPathProgressForClient(float progress); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index ac2219ed5cf..3f68036a278 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -152,24 +152,10 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c if (IsWorldObject()) { WorldObject const* worldObject = static_cast<WorldObject const*>(this); - if (!flags.MovementUpdate && !worldObject->m_movementInfo.transport.guid.IsEmpty()) - flags.MovementTransport = true; - - if (worldObject->GetAIAnimKitId() || worldObject->GetMovementAnimKitId() || worldObject->GetMeleeAnimKitId()) - flags.AnimKit = true; - if (worldObject->GetSmoothPhasing() && worldObject->GetSmoothPhasing()->GetInfoForSeer(target->GetGUID())) flags.SmoothPhasing = true; } - if (Unit const* unit = ToUnit()) - { - flags.PlayHoverAnim = unit->IsPlayingHoverAnim(); - - if (unit->GetVictim()) - flags.CombatVictim = true; - } - ByteBuffer& buf = data->GetBuffer(); buf << uint8(updateType); buf << GetGUID(); @@ -274,7 +260,7 @@ ByteBuffer& Object::PrepareValuesUpdateBuffer(UpdateData* data) const return buffer; } -void Object::DestroyForPlayer(Player* target) const +void Object::DestroyForPlayer(Player const* target) const { ASSERT(target); @@ -285,7 +271,7 @@ void Object::DestroyForPlayer(Player* target) const target->SendDirectMessage(&packet); } -void Object::SendOutOfRangeForPlayer(Player* target) const +void Object::SendOutOfRangeForPlayer(Player const* target) const { ASSERT(target); @@ -298,9 +284,9 @@ void Object::SendOutOfRangeForPlayer(Player* target) const void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Player const* target) const { - std::vector<uint32> const* PauseTimes = nullptr; - if (GameObject const* go = ToGameObject()) - PauseTimes = go->GetPauseTimes(); + std::span<uint32 const> PauseTimes; + if (IsGameObject()) + PauseTimes = static_cast<GameObject const*>(this)->GetPauseTimes(); data->WriteBit(IsWorldObject()); // HasPositionFragment data->WriteBit(flags.NoBirthAnim); @@ -459,7 +445,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe WorldPackets::Movement::CommonMovement::WriteCreateObjectSplineDataBlock(*unit->movespline, *data); } - *data << uint32(PauseTimes ? PauseTimes->size() : 0); + *data << uint32(PauseTimes.size()); if (flags.Stationary) { @@ -512,8 +498,8 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe // *data << uint8(AttachmentFlags); //} - if (PauseTimes && !PauseTimes->empty()) - data->append(PauseTimes->data(), PauseTimes->size()); + if (!PauseTimes.empty()) + data->append(PauseTimes.data(), PauseTimes.size()); if (flags.MovementTransport) { @@ -2591,10 +2577,10 @@ SpellMissInfo WorldObject::MagicSpellHitResult(Unit* victim, SpellInfo const* sp // Parry // For spells // Resist -SpellMissInfo WorldObject::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect /*= false*/) const +SpellMissInfo WorldObject::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect, bool canImmune) const { // Check for immune - if (victim->IsImmunedToSpell(spellInfo, this)) + if (canImmune && victim->IsImmunedToSpell(spellInfo, MAX_EFFECT_MASK, this)) return SPELL_MISS_IMMUNE; // Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply @@ -3747,6 +3733,12 @@ ObjectGuid WorldObject::GetTransGUID() const return ObjectGuid::Empty; } +void WorldObject::SetTransport(TransportBase* t) +{ + m_transport = t; + m_updateFlag.MovementTransport = !m_updateFlag.MovementUpdate && t != nullptr; +} + float WorldObject::GetFloorZ() const { if (!IsInWorld()) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 72b3a5dd448..6f484f765c4 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -228,8 +228,8 @@ class TC_GAME_API Object void BuildOutOfRangeUpdateBlock(UpdateData* data) const; ByteBuffer& PrepareValuesUpdateBuffer(UpdateData* data) const; - virtual void DestroyForPlayer(Player* target) const; - void SendOutOfRangeForPlayer(Player* target) const; + virtual void DestroyForPlayer(Player const* target) const; + void SendOutOfRangeForPlayer(Player const* target) const; virtual void ClearUpdateMask(bool remove); @@ -837,7 +837,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation virtual float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, SpellInfo const* spellInfo) const; virtual SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo) const; SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo) const; - SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect = false) const; + SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect, bool canImmune) const; void SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo); virtual uint32 GetFaction() const = 0; @@ -921,7 +921,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation uint32 GetTransTime() const { return m_movementInfo.transport.time; } int8 GetTransSeat() const { return m_movementInfo.transport.seat; } virtual ObjectGuid GetTransGUID() const; - void SetTransport(TransportBase* t) { m_transport = t; } + void SetTransport(TransportBase* t); MovementInfo m_movementInfo; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ecddafd9c28..c579bca7400 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3706,7 +3706,7 @@ void Player::ValuesUpdateForPlayerWithMaskSender::operator()(Player const* playe player->SendDirectMessage(&packet); } -void Player::DestroyForPlayer(Player* target) const +void Player::DestroyForPlayer(Player const* target) const { Unit::DestroyForPlayer(target); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 62b5e410559..93ccffcce1b 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2233,7 +2233,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player> void operator()(Player const* player) const; }; - void DestroyForPlayer(Player* target) const override; + void DestroyForPlayer(Player const* target) const override; // notifiers void SendAttackSwingCancelAttack() const; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 6e888db12d1..f51da1de0f8 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -53,6 +53,7 @@ #include "Loot.h" #include "LootMgr.h" #include "LootPackets.h" +#include "MapUtils.h" #include "MiscPackets.h" #include "MotionMaster.h" #include "MovementGenerator.h" @@ -312,7 +313,7 @@ Unit::Unit(bool isWorldObject) : m_unitMovedByMe(nullptr), m_playerMovingMe(nullptr), m_charmer(nullptr), m_charmed(nullptr), i_motionMaster(std::make_unique<MotionMaster>(this)), m_regenTimer(0), m_vehicle(nullptr), m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(), m_combatManager(this), - m_threatManager(this), m_aiLocked(false), _playHoverAnim(false), _aiAnimKitId(0), _movementAnimKitId(0), _meleeAnimKitId(0), + m_threatManager(this), m_aiLocked(false), _aiAnimKitId(0), _movementAnimKitId(0), _meleeAnimKitId(0), _spellHistory(std::make_unique<SpellHistory>(this)) { m_objectTypeId = TYPEID_UNIT; @@ -1597,7 +1598,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Damage shield can be resisted... - SpellMissInfo missInfo = victim->SpellHitResult(this, spellInfo, false); + SpellMissInfo missInfo = victim->SpellHitResult(this, spellInfo, false, true); if (missInfo != SPELL_MISS_NONE) { victim->SendSpellMiss(this, spellInfo->Id, missInfo); @@ -5901,6 +5902,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack) m_attacking = victim; m_attacking->_addAttacker(this); + m_updateFlag.CombatVictim = true; // Set our target SetTarget(victim->GetGUID()); @@ -5951,6 +5953,7 @@ bool Unit::AttackStop() Unit* victim = m_attacking; + m_updateFlag.CombatVictim = false; m_attacking->_removeAttacker(this); m_attacking = nullptr; @@ -7743,7 +7746,7 @@ int32 Unit::SpellAbsorbBonusTaken(Unit* caster, SpellInfo const* spellProto, int return static_cast<int32>(std::round(absorb)); } -bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute /*= false*/) const +bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute /*= false*/) const { if (!spellInfo) return false; @@ -7754,14 +7757,14 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste if (!requireImmunityPurgesEffectAttribute) return range.begin() != range.end(); - return std::any_of(range.begin(), range.end(), [](SpellImmuneContainer::value_type const& entry) + return std::ranges::any_of(range, [](uint32 immunitySpellId) { - if (SpellInfo const* immunitySourceSpell = sSpellMgr->GetSpellInfo(entry.second, DIFFICULTY_NONE)) + if (SpellInfo const* immunitySourceSpell = sSpellMgr->GetSpellInfo(immunitySpellId, DIFFICULTY_NONE)) if (immunitySourceSpell->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT)) return true; return false; - }); + }, Trinity::Containers::MapValue); }; // Single spell immunity. @@ -7792,7 +7795,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste { // State/effect immunities applied by aura expect full spell immunity // Ignore effects with mechanic, they are supposed to be checked separately - if (!spellEffectInfo.IsEffect()) + if (!spellEffectInfo.IsEffect() || !(effectMask & (1 << spellEffectInfo.EffectIndex))) continue; if (!IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster, requireImmunityPurgesEffectAttribute)) { @@ -7820,7 +7823,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste if (!immuneSpellInfo || !immuneSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT)) continue; - if (spellInfo->IsPositive() && !(immuneSpellInfo && immuneSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS))) + if (!(spellInfo->NegativeEffects.to_ulong() & effectMask) && !(immuneSpellInfo && immuneSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS))) continue; if (spellInfo->CanPierceImmuneAura(immuneSpellInfo)) @@ -7955,14 +7958,14 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo co if (!requireImmunityPurgesEffectAttribute) return range.begin() != range.end(); - return std::any_of(range.begin(), range.end(), [](SpellImmuneContainer::value_type const& entry) + return std::ranges::any_of(range, [](uint32 immunitySpellId) { - if (SpellInfo const* immunitySourceSpell = sSpellMgr->GetSpellInfo(entry.second, DIFFICULTY_NONE)) + if (SpellInfo const* immunitySourceSpell = sSpellMgr->GetSpellInfo(immunitySpellId, DIFFICULTY_NONE)) if (immunitySourceSpell->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT)) return true; return false; - }); + }, Trinity::Containers::MapValue); }; // If m_immuneToEffect type contain this effect type, IMMUNE effect. @@ -11200,6 +11203,7 @@ void Unit::SetAIAnimKitId(uint16 animKitId) return; _aiAnimKitId = animKitId; + m_updateFlag.AnimKit = _aiAnimKitId != 0 || _movementAnimKitId != 0 || _meleeAnimKitId != 0; WorldPackets::Misc::SetAIAnimKit data; data.Unit = GetGUID(); @@ -11216,6 +11220,7 @@ void Unit::SetMovementAnimKitId(uint16 animKitId) return; _movementAnimKitId = animKitId; + m_updateFlag.AnimKit = _aiAnimKitId != 0 || _movementAnimKitId != 0 || _meleeAnimKitId != 0; WorldPackets::Misc::SetMovementAnimKit data; data.Unit = GetGUID(); @@ -11232,6 +11237,7 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId) return; _meleeAnimKitId = animKitId; + m_updateFlag.AnimKit = _aiAnimKitId != 0 || _movementAnimKitId != 0 || _meleeAnimKitId != 0; WorldPackets::Misc::SetMeleeAnimKit data; data.Unit = GetGUID(); @@ -12283,7 +12289,7 @@ Aura* Unit::AddAura(SpellInfo const* spellInfo, uint32 effMask, Unit* target) if (!target->IsAlive() && !spellInfo->IsPassive() && !spellInfo->HasAttribute(SPELL_ATTR2_ALLOW_DEAD_TARGET)) return nullptr; - if (target->IsImmunedToSpell(spellInfo, this)) + if (target->IsImmunedToSpell(spellInfo, effMask, this)) return nullptr; for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) @@ -14073,7 +14079,7 @@ void Unit::SetPlayHoverAnim(bool enable, bool sendUpdate /*= true*/) if (IsPlayingHoverAnim() == enable) return; - _playHoverAnim = enable; + m_updateFlag.PlayHoverAnim = enable; if (!sendUpdate) return; @@ -14122,7 +14128,7 @@ UF::UpdateFieldFlag Unit::GetUpdateFieldFlagsFor(Player const* target) const return flags; } -void Unit::DestroyForPlayer(Player* target) const +void Unit::DestroyForPlayer(Player const* target) const { if (Battleground* bg = target->GetBattleground()) { diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 881aee786cb..ed291549b04 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1138,7 +1138,7 @@ class TC_GAME_API Unit : public WorldObject void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false); - bool IsPlayingHoverAnim() const { return _playHoverAnim; } + bool IsPlayingHoverAnim() const { return m_updateFlag.PlayHoverAnim; } void SetPlayHoverAnim(bool enable, bool sendUpdate = true); void CalculateHoverHeight(); void SetHoverHeight(float hoverHeight) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::HoverHeight), hoverHeight); } @@ -1677,7 +1677,7 @@ class TC_GAME_API Unit : public WorldObject static uint32 SpellCriticalHealingBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim); void ApplySpellImmune(uint32 spellId, SpellImmunity op, uint32 type, bool apply); - bool IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const; + bool IsImmunedToSpell(SpellInfo const* spellInfo, uint32 effectMask, WorldObject const* caster, bool requireImmunityPurgesEffectAttribute = false) const; uint32 GetSchoolImmunityMask() const; uint32 GetDamageImmunityMask() const; uint64 GetMechanicImmunityMask() const; @@ -1878,7 +1878,7 @@ class TC_GAME_API Unit : public WorldObject UF::UpdateFieldFlag GetUpdateFieldFlagsFor(Player const* target) const override; - void DestroyForPlayer(Player* target) const override; + void DestroyForPlayer(Player const* target) const override; void ClearUpdateMask(bool remove) override; void _UpdateSpells(uint32 time); @@ -2030,8 +2030,6 @@ class TC_GAME_API Unit : public WorldObject uint32 _oldFactionId; ///< faction before charm bool _isWalkingBeforeCharm; ///< Are we walking before we were charmed? - bool _playHoverAnim; - uint16 _aiAnimKitId; uint16 _movementAnimKitId; uint16 _meleeAnimKitId; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 25397d69d62..73fcbe1cefe 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5629,7 +5629,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const // Consecrate ticks can miss and will not show up in the combat log // dynobj auras must always have a caster if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && - ASSERT_NOTNULL(caster)->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) + ASSERT_NOTNULL(caster)->SpellHitResult(target, GetSpellInfo(), false, true) != SPELL_MISS_NONE) return; CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); @@ -5763,7 +5763,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c // dynobj auras must always have a caster if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && - ASSERT_NOTNULL(caster)->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) + ASSERT_NOTNULL(caster)->SpellHitResult(target, GetSpellInfo(), false, true) != SPELL_MISS_NONE) return; CleanDamage cleanDamage = CleanDamage(0, 0, GetSpellInfo()->GetAttackType(), MELEE_HIT_NORMAL); @@ -5953,7 +5953,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con } if (GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && - caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) + caster->SpellHitResult(target, GetSpellInfo(), false, true) != SPELL_MISS_NONE) return; // ignore negative values (can be result apply spellmods to aura damage diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 7a4722f9cef..3a68549f238 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -684,7 +684,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) { // needs readding - remove now, will be applied in next update cycle // (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed) - if (itr->first->IsImmunedToSpell(GetSpellInfo(), caster, true) || !CanBeAppliedOn(itr->first)) + if (itr->first->IsImmunedToSpell(GetSpellInfo(), itr->second, caster, true) || !CanBeAppliedOn(itr->first)) { targetsToRemove.push_back(applicationPair.second->GetTarget()); continue; @@ -717,7 +717,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), spellEffectInfo, caster)) itr->second &= ~(1 << spellEffectInfo.EffectIndex); - if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(itr->first)) + if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo(), itr->second, caster) || !CanBeAppliedOn(itr->first)) addUnit = false; } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 50db01b3fec..8cc94e2f59d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2434,7 +2434,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= // Calculate hit result WorldObject* caster = m_originalCaster ? m_originalCaster : m_caster; - targetInfo.MissCondition = caster->SpellHitResult(target, m_spellInfo, m_canReflect && !(IsPositive() && m_caster->IsFriendlyTo(target))); + targetInfo.MissCondition = caster->SpellHitResult(target, m_spellInfo, + m_canReflect && !(IsPositive() && m_caster->IsFriendlyTo(target)), + false /*immunity will be checked after complete EffectMask is known*/); // Spell have speed - need calculate incoming time // Incoming time is zero for self casts. At least I think so. @@ -2479,7 +2481,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= { // Calculate reflected spell result on caster (shouldn't be able to reflect gameobject spells) Unit* unitCaster = ASSERT_NOTNULL(m_caster->ToUnit()); - targetInfo.ReflectResult = unitCaster->SpellHitResult(unitCaster, m_spellInfo, false); // can't reflect twice + targetInfo.ReflectResult = unitCaster->SpellHitResult(unitCaster, m_spellInfo, + false /*can't reflect twice*/, + false /*immunity will be checked after complete EffectMask is known*/); // Proc spell reflect aura when missile hits the original target target->m_Events.AddEvent(new ProcReflectDelayed(target, m_originalCasterGUID), target->m_Events.CalculateTime(Milliseconds(targetInfo.TimeDelay))); @@ -3099,7 +3103,7 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo) return SPELL_MISS_EVADE; // For delayed spells immunity may be applied between missile launch and hit - check immunity for that case - if (hitInfo.TimeDelay && unit->IsImmunedToSpell(m_spellInfo, m_caster)) + if (hitInfo.TimeDelay && unit->IsImmunedToSpell(m_spellInfo, hitInfo.EffectMask, m_caster)) return SPELL_MISS_IMMUNE; CallScriptBeforeHitHandlers(hitInfo.MissCondition); @@ -8612,6 +8616,10 @@ void Spell::PreprocessSpellLaunch(TargetInfo& targetInfo) if (!targetUnit) return; + // Check immunity now that EffectMask is known + if (targetUnit->IsImmunedToSpell(GetSpellInfo(), targetInfo.EffectMask, m_caster)) + targetInfo.MissCondition = SPELL_MISS_IMMUNE; + // This will only cause combat - the target will engage once the projectile hits (in Spell::TargetInfo::PreprocessTarget) if (m_originalCaster && targetInfo.MissCondition != SPELL_MISS_EVADE && !m_originalCaster->IsFriendlyTo(targetUnit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) && (m_spellInfo->HasInitialAggro() || targetUnit->IsEngaged())) m_originalCaster->SetInCombatWith(targetUnit, true); @@ -8622,7 +8630,11 @@ void Spell::PreprocessSpellLaunch(TargetInfo& targetInfo) unit = targetUnit; // In case spell reflect from target, do all effect on caster (if hit) else if (targetInfo.MissCondition == SPELL_MISS_REFLECT && targetInfo.ReflectResult == SPELL_MISS_NONE) + { unit = m_caster->ToUnit(); + if (unit && unit->IsImmunedToSpell(GetSpellInfo(), targetInfo.EffectMask, unit)) + targetInfo.ReflectResult = SPELL_MISS_IMMUNE; + } if (!unit) return; |
