Core/Entities: fix interaction of traps with ffa pvp and sanctuary flags
This commit is contained in:
1 parent
6aac0c2073
commit
938f43302c
3 files changed
+37
-22
No files matched your search
@@ -564,8 +564,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
|
||||
@@ -1880,6 +1880,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, UNIT_BYTES_2_OFFSET_PVP_FLAG, owner->GetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG));
|
||||
// needed for GO casts for proper target validation checks
|
||||
trigger->SetOwnerGUID(owner->GetGUID());
|
||||
trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, owner->GetGUID());
|
||||
|
||||
@@ -5459,8 +5459,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)
|
||||
@@ -8434,10 +8433,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())
|
||||
@@ -8472,7 +8487,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;
|
||||
|
||||
@@ -8480,10 +8495,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;
|
||||
@@ -8517,15 +8530,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, UNIT_BYTES_2_OFFSET_PVP_FLAG) & 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, UNIT_BYTES_2_OFFSET_PVP_FLAG) & 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, UNIT_BYTES_2_OFFSET_PVP_FLAG) & UNIT_BYTE2_FLAG_UNK1);
|
||||
return HasByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_UNK1)
|
||||
|| target->HasByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG, UNIT_BYTE2_FLAG_UNK1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -893,10 +893,11 @@ 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)
|
||||
{
|
||||
if (!u->IsAlive())
|
||||
@@ -905,13 +906,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);
|
||||
|
||||
Reference in new issue
Block a user