diff options
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 43 |
3 files changed, 45 insertions, 4 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f5a0412d7f1..2dbef6af0dd 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -7977,8 +7977,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo // PvP case - can't attack when attacker or target are in sanctuary // however, 13850 client doesn't allow to attack when one of the unit's has sanctuary flag and is pvp - if (target->HasUnitFlag(UNIT_FLAG_PVP_ATTACKABLE) && HasUnitFlag(UNIT_FLAG_PVP_ATTACKABLE) - && ((target->HasPvpFlag(UNIT_BYTE2_FLAG_SANCTUARY)) || (HasPvpFlag(UNIT_BYTE2_FLAG_SANCTUARY)))) + if (target->HasUnitFlag(UNIT_FLAG_PVP_ATTACKABLE) && HasUnitFlag(UNIT_FLAG_PVP_ATTACKABLE) && (target->IsInSanctuary() || IsInSanctuary())) return false; // additional checks - only PvP case @@ -8076,7 +8075,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co return false; // can't assist player out of sanctuary from sanctuary if has pvp enabled if (target->HasPvpFlag(UNIT_BYTE2_FLAG_PVP)) - if (HasPvpFlag(UNIT_BYTE2_FLAG_SANCTUARY) && !target->HasPvpFlag(UNIT_BYTE2_FLAG_SANCTUARY)) + if (IsInSanctuary() && !target->IsInSanctuary()) return false; } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e56dc09df42..a1af7666b50 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1153,6 +1153,7 @@ class TC_GAME_API Unit : public WorldObject void AddPvpFlag(UnitPVPStateFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::PvpFlags), flags); } void RemovePvpFlag(UnitPVPStateFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::PvpFlags), flags); } void SetPvpFlags(UnitPVPStateFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::PvpFlags), flags); } + bool IsInSanctuary() const { return HasPvpFlag(UNIT_BYTE2_FLAG_SANCTUARY); } bool IsPvP() const { return HasPvpFlag(UNIT_BYTE2_FLAG_PVP); } bool IsFFAPvP() const { return HasPvpFlag(UNIT_BYTE2_FLAG_FFA_PVP); } virtual void SetPvP(bool state); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 76c45ce96f4..43c2f1c29a5 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4970,6 +4970,18 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (Unit* target = m_targets.GetUnitTarget()) { + // do not allow to cast on hostile targets in sanctuary + if (!m_caster->IsFriendlyTo(target)) + { + if (m_caster->IsInSanctuary() || target->IsInSanctuary()) + { + // fix for duels + Player* player = m_caster->ToPlayer(); + if (!player || !player->duel || target != player->duel->opponent) + return SPELL_FAILED_NOTHING_TO_DISPEL; + } + } + SpellCastResult castResult = m_spellInfo->CheckTarget(m_caster, target, m_caster->GetEntry() == WORLD_TRIGGER); // skip stealth checks for GO casts if (castResult != SPELL_CAST_OK) return castResult; @@ -5532,8 +5544,30 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } case SPELL_EFFECT_STEAL_BENEFICIAL_BUFF: { - if (m_targets.GetUnitTarget() == m_caster) + if (!m_targets.GetUnitTarget() || m_targets.GetUnitTarget() == m_caster) return SPELL_FAILED_BAD_TARGETS; + + uint32 dispelMask = m_spellInfo->GetDispelMask(DispelType(effect->MiscValue)); + bool hasStealableAura = false; + for (AuraApplication* visibleAura : m_targets.GetUnitTarget()->GetVisibleAuras()) + { + if (!visibleAura->IsPositive()) + continue; + + Aura const* aura = visibleAura->GetBase(); + if (!(aura->GetSpellInfo()->GetDispelMask() & dispelMask)) + continue; + + if (aura->IsPassive() || aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_NOT_STEALABLE)) + continue; + + hasStealableAura = true; + break; + } + + if (!hasStealableAura) + return SPELL_FAILED_NOTHING_TO_STEAL; + break; } case SPELL_EFFECT_LEAP_BACK: @@ -5547,6 +5581,13 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint } break; } + case SPELL_EFFECT_JUMP: + case SPELL_EFFECT_JUMP_DEST: + { + if (m_caster->HasUnitState(UNIT_STATE_ROOT)) + return SPELL_FAILED_ROOTED; + break; + } case SPELL_EFFECT_TALENT_SPEC_SELECT: { ChrSpecializationEntry const* spec = sChrSpecializationStore.LookupEntry(m_misc.SpecializationId); |