Core/Entities: fix interaction of traps with ffa pvp and sanctuary flags
This commit is contained in:
@@ -565,7 +565,7 @@ namespace Game.Entities
|
||||
if (owner)
|
||||
{
|
||||
// Hunter trap: Search units which are unfriendly to the trap's owner
|
||||
var checker = new NearestUnfriendlyNoTotemUnitInObjectRangeCheck(this, owner, radius);
|
||||
var checker = new NearestAttackableNoTotemUnitInObjectRangeCheck(this, owner, radius);
|
||||
var searcher = new UnitLastSearcher(this, checker);
|
||||
Cell.VisitAllObjects(this, searcher, radius);
|
||||
target = searcher.GetTarget();
|
||||
@@ -1944,6 +1944,8 @@ namespace Game.Entities
|
||||
trigger.SetFaction(owner.getFaction());
|
||||
if (owner.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
|
||||
trigger.SetFlag(UnitFields.Flags, UnitFlags.PvpAttackable);
|
||||
// copy pvp state flags from owner
|
||||
trigger.SetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, owner.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag));
|
||||
// needed for GO casts for proper target validation checks
|
||||
trigger.SetOwnerGUID(owner.GetGUID());
|
||||
trigger.CastSpell(target != null ? target : trigger, spellInfo, triggered, null, null, owner.GetGUID());
|
||||
|
||||
@@ -2903,10 +2903,26 @@ namespace Game.Entities
|
||||
|| (target.IsTypeId(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() != SharedConst.WorldTrigger && (bySpell == null || !bySpell.HasAttribute(SpellAttr6.CanTargetInvisible)) && (obj ? !obj.CanSeeOrDetect(target, bySpell != null && bySpell.IsAffectingArea(GetMap().GetDifficultyID())) : !CanSeeOrDetect(target, (bySpell != null && 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() != SharedConst.WorldTrigger && (!obj || !obj.isTypeMask(TypeMask.GameObject | TypeMask.DynamicObject)))
|
||||
{
|
||||
// can't attack invisible
|
||||
if (bySpell == null || !bySpell.HasAttribute(SpellAttr6.CanTargetInvisible))
|
||||
{
|
||||
if (obj && !obj.CanSeeOrDetect(target, bySpell != null && 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 ignoreStealthCheck = (bySpell != null && 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 == null || !bySpell.IsAllowingDeadTarget()) && !target.IsAlive())
|
||||
@@ -2942,8 +2958,7 @@ namespace Game.Entities
|
||||
|
||||
// PvP, PvC, CvP case
|
||||
// can't attack friendly targets
|
||||
if (GetReactionTo(target) > ReputationRank.Neutral
|
||||
|| target.GetReactionTo(this) > ReputationRank.Neutral)
|
||||
if (GetReactionTo(target) > ReputationRank.Neutral || target.GetReactionTo(this) > ReputationRank.Neutral)
|
||||
return false;
|
||||
|
||||
Player playerAffectingAttacker = HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) ? GetAffectingPlayer() : null;
|
||||
@@ -2996,15 +3011,13 @@ namespace Game.Entities
|
||||
// additional checks - only PvP case
|
||||
if (playerAffectingAttacker != null && playerAffectingTarget != null)
|
||||
{
|
||||
if (Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.PvP))
|
||||
if (target.IsPvP())
|
||||
return true;
|
||||
|
||||
if (Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp)
|
||||
&& Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp))
|
||||
if (IsFFAPvP() && target.IsFFAPvP())
|
||||
return true;
|
||||
|
||||
return (Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Unk1)
|
||||
|| Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Unk1));
|
||||
return HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Unk1) || target.HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Unk1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2508,8 +2508,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// check FFA_PVP
|
||||
if (Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp)
|
||||
&& Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp))
|
||||
if (IsFFAPvP() && target.IsFFAPvP())
|
||||
return ReputationRank.Hostile;
|
||||
|
||||
if (selfPlayerOwner != null)
|
||||
|
||||
@@ -1458,9 +1458,9 @@ namespace Game.Maps
|
||||
float i_range;
|
||||
}
|
||||
|
||||
public class NearestUnfriendlyNoTotemUnitInObjectRangeCheck : ICheck<Unit>
|
||||
public class NearestAttackableNoTotemUnitInObjectRangeCheck : ICheck<Unit>
|
||||
{
|
||||
public NearestUnfriendlyNoTotemUnitInObjectRangeCheck(WorldObject obj, Unit funit, float range)
|
||||
public NearestAttackableNoTotemUnitInObjectRangeCheck(WorldObject obj, Unit funit, float range)
|
||||
{
|
||||
i_obj = obj;
|
||||
i_funit = funit;
|
||||
@@ -1481,7 +1481,7 @@ namespace Game.Maps
|
||||
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, null, i_obj))
|
||||
return false;
|
||||
|
||||
i_range = i_obj.GetDistance(u);
|
||||
|
||||
Reference in New Issue
Block a user