diff options
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 44 | ||||
| -rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.h | 8 | 
4 files changed, 37 insertions, 23 deletions
| diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index dd67d99c366..f1365ac3150 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -527,8 +527,8 @@ void GameObject::Update(uint32 diff)                      if (Unit* owner = GetOwner())                      {                          // Hunter trap: Search units which are unfriendly to the trap's owner -                        Trinity::NearestUnfriendlyNoTotemUnitInObjectRangeCheck checker(this, owner, radius); -                        Trinity::UnitLastSearcher<Trinity::NearestUnfriendlyNoTotemUnitInObjectRangeCheck> searcher(this, target, checker); +                        Trinity::NearestAttackableNoTotemUnitInObjectRangeCheck checker(this, owner, radius); +                        Trinity::UnitLastSearcher<Trinity::NearestAttackableNoTotemUnitInObjectRangeCheck> searcher(this, target, checker);                          VisitNearbyObject(radius, searcher);                      }                      else @@ -1837,6 +1837,8 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge          trigger->setFaction(owner->getFaction());          if (owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))              trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); +        // copy pvp state flags from owner +        trigger->SetByteValue(UNIT_FIELD_BYTES_2, 1, owner->GetByteValue(UNIT_FIELD_BYTES_2, 1));          // needed for GO casts for proper target validation checks          trigger->SetOwnerGUID(owner->GetGUID());          trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, owner->GetGUID()); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index f7d4fb38cee..a5f5aa18b1d 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -173,7 +173,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c      if (flags & UPDATEFLAG_STATIONARY_POSITION)      {          // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses... -        if (isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER)) +        if (isType(TYPEMASK_DYNAMICOBJECT | TYPEMASK_CORPSE | TYPEMASK_PLAYER))              updateType = UPDATETYPE_CREATE_OBJECT2;          // UPDATETYPE_CREATE_OBJECT2 for pets... diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 3891dad310b..c4e879c08d9 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -5535,8 +5535,7 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const              }              // check FFA_PVP -            if (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP -                && target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP) +            if (IsFFAPvP() && target->IsFFAPvP())                  return REP_HOSTILE;              if (selfPlayerOwner) @@ -8665,10 +8664,26 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo          || (target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->IsGameMaster()))          return false; -    // can't attack invisible (ignore stealth for aoe spells) also if the area being looked at is from a spell use the dynamic object created instead of the casting unit. Ignore stealth if target is player and unit in combat with same player -    // skip visibility check for GO casts, needs removal when go cast is implemented -    if (GetEntry() != WORLD_TRIGGER && (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !CanSeeOrDetect(target, (bySpell && bySpell->IsAffectingArea()) || (target->GetTypeId() == TYPEID_PLAYER && target->HasStealthAura() && target->IsInCombat() && IsInCombatWith(target))))) -        return false; +    // visibility checks +    // skip visibility check for GO casts, needs removal when go cast is implemented. Also ignore for gameobject and dynauras +    if (GetEntry() != WORLD_TRIGGER && (!obj || !obj->isType(TYPEMASK_GAMEOBJECT | TYPEMASK_DYNAMICOBJECT))) +    { +        // can't attack invisible +        if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) +        { +            if (obj && !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea())) +                return false; +            else if (!obj) +            { +                // ignore stealth for aoe spells. Ignore stealth if target is player and unit in combat with same player +                bool const ignoreStealthCheck = (bySpell && bySpell->IsAffectingArea()) || +                    (target->GetTypeId() == TYPEID_PLAYER && target->HasStealthAura() && target->IsInCombat() && IsInCombatWith(target)); + +                if (!CanSeeOrDetect(target, ignoreStealthCheck)) +                    return false; +            } +        } +    }      // can't attack dead      if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && !target->IsAlive()) @@ -8699,7 +8714,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo      // PvP, PvC, CvP case      // can't attack friendly targets -    if ( GetReactionTo(target) > REP_NEUTRAL +    if (GetReactionTo(target) > REP_NEUTRAL          || target->GetReactionTo(this) > REP_NEUTRAL)          return false; @@ -8707,10 +8722,8 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo      Player const* playerAffectingTarget = target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? target->GetAffectingPlayer() : nullptr;      // Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar) -    if  ( -        (playerAffectingAttacker && !playerAffectingTarget) || -        (!playerAffectingAttacker && playerAffectingTarget) -    ) +    if ((playerAffectingAttacker && !playerAffectingTarget) || +        (!playerAffectingAttacker && playerAffectingTarget))      {          Player const* player = playerAffectingAttacker ? playerAffectingAttacker : playerAffectingTarget;          Unit const* creature = playerAffectingAttacker ? target : this; @@ -8744,15 +8757,14 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo      // additional checks - only PvP case      if (playerAffectingAttacker && playerAffectingTarget)      { -        if (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP) +        if (target->IsPvP())              return true; -        if (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP -            && target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_FFA_PVP) +        if (IsFFAPvP() && target->IsFFAPvP())              return true; -        return (GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1) -            || (target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_UNK1); +        return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK1) +            || target->HasByteFlag(UNIT_FIELD_BYTES_2, 1, 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 263ba355865..ac153f31b8e 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -842,10 +842,10 @@ namespace Trinity              float i_range;      }; -    class NearestUnfriendlyNoTotemUnitInObjectRangeCheck +    class NearestAttackableNoTotemUnitInObjectRangeCheck      {          public: -            NearestUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) { } +            NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) { }              bool operator()(Unit* u)              { @@ -855,13 +855,13 @@ namespace Trinity                  if (u->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)                      return false; -                if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->IsTotem()) +                if (u->GetTypeId() == TYPEID_UNIT && u->ToCreature()->IsTotem())                      return false;                  if (!u->isTargetableForAttack(false))                      return false; -                if (!i_obj->IsWithinDistInMap(u, i_range) || i_funit->IsFriendlyTo(u)) +                if (!i_obj->IsWithinDistInMap(u, i_range) || !i_funit->_IsValidAttackTarget(u, nullptr, i_obj))                      return false;                  i_range = i_obj->GetDistance(*u); | 
