aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2016-11-19 15:43:22 -0300
committerjoschiwald <joschiwald.trinity@gmail.com>2018-01-21 14:51:49 +0100
commit2c022a5aa8123d12cfdc681000eeb62be039aff1 (patch)
treefb175272c335e108d80aed3c73d074f4438862e4
parent771ec0b2256e0f88b365e47af5b8d837a3cae445 (diff)
Core/Entities: fix interaction of traps with ffa pvp and sanctuary flags
- Traps should select ATTACKABLE not UNFRIENDLY targets (it shouldn't attack unfriendly targets on sanctuary zones for example) - Made more readable the nasty oneliner in Unit::_IsValidAttackTarget Closes #6464 Closes #18271 (cherry picked from commit ef227d7e64a3dc62fbf0cba0209202310b1af00b)
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp6
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp44
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h8
3 files changed, 36 insertions, 22 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 7e6a557c499..e33d099b2ac 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -608,8 +608,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);
Cell::VisitAllObjects(this, searcher, radius);
}
else
@@ -1980,6 +1980,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());
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index c4c47317f25..f80966aeaf1 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -5319,8 +5319,7 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const
}
// check FFA_PVP
- if (GetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PVP_FLAG) & 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 REP_HOSTILE;
if (selfPlayerOwner)
@@ -7911,10 +7910,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(GetMap()->GetDifficultyID())) : !CanSeeOrDetect(target, (bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficultyID())) || (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(GetMap()->GetDifficultyID())))
+ 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(GetMap()->GetDifficultyID())) ||
+ (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())
@@ -7949,7 +7964,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;
@@ -7957,10 +7972,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;
@@ -7994,15 +8007,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, UNIT_BYTES_2_OFFSET_PVP_FLAG) & 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, UNIT_BYTES_2_OFFSET_PVP_FLAG) & 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;
}
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 9c678db944e..f2611edab14 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -862,10 +862,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)
{
@@ -875,13 +875,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);