Core/Entities: fix interaction of traps with ffa pvp and sanctuary flags

This commit is contained in:
hondacrx
2018-01-24 12:06:19 -05:00
parent 461dff9b67
commit 659080b5a5
4 changed files with 31 additions and 17 deletions
@@ -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());
+24 -11
View File
@@ -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;
}
+1 -2
View File
@@ -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)
+3 -3
View File
@@ -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);