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) if (owner)
{ {
// Hunter trap: Search units which are unfriendly to the trap's 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); var searcher = new UnitLastSearcher(this, checker);
Cell.VisitAllObjects(this, searcher, radius); Cell.VisitAllObjects(this, searcher, radius);
target = searcher.GetTarget(); target = searcher.GetTarget();
@@ -1944,6 +1944,8 @@ namespace Game.Entities
trigger.SetFaction(owner.getFaction()); trigger.SetFaction(owner.getFaction());
if (owner.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable)) if (owner.HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable))
trigger.SetFlag(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 // needed for GO casts for proper target validation checks
trigger.SetOwnerGUID(owner.GetGUID()); trigger.SetOwnerGUID(owner.GetGUID());
trigger.CastSpell(target != null ? target : trigger, spellInfo, triggered, null, null, 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())) || (target.IsTypeId(TypeId.Player) && target.ToPlayer().IsGameMaster()))
return false; 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 // visibility checks
// skip visibility check for GO casts, needs removal when go cast is implemented // skip visibility check for GO casts, needs removal when go cast is implemented. Also ignore for gameobject and dynauras
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))))) if (GetEntry() != SharedConst.WorldTrigger && (!obj || !obj.isTypeMask(TypeMask.GameObject | TypeMask.DynamicObject)))
return false; {
// 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 // can't attack dead
if ((bySpell == null || !bySpell.IsAllowingDeadTarget()) && !target.IsAlive()) if ((bySpell == null || !bySpell.IsAllowingDeadTarget()) && !target.IsAlive())
@@ -2942,8 +2958,7 @@ namespace Game.Entities
// PvP, PvC, CvP case // PvP, PvC, CvP case
// can't attack friendly targets // can't attack friendly targets
if (GetReactionTo(target) > ReputationRank.Neutral if (GetReactionTo(target) > ReputationRank.Neutral || target.GetReactionTo(this) > ReputationRank.Neutral)
|| target.GetReactionTo(this) > ReputationRank.Neutral)
return false; return false;
Player playerAffectingAttacker = HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) ? GetAffectingPlayer() : null; Player playerAffectingAttacker = HasFlag(UnitFields.Flags, UnitFlags.PvpAttackable) ? GetAffectingPlayer() : null;
@@ -2996,15 +3011,13 @@ namespace Game.Entities
// additional checks - only PvP case // additional checks - only PvP case
if (playerAffectingAttacker != null && playerAffectingTarget != null) if (playerAffectingAttacker != null && playerAffectingTarget != null)
{ {
if (Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.PvP)) if (target.IsPvP())
return true; return true;
if (Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp) if (IsFFAPvP() && target.IsFFAPvP())
&& Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp))
return true; return true;
return (Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Unk1) return HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Unk1) || target.HasByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, UnitBytes2Flags.Unk1);
|| Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.Unk1));
} }
return true; return true;
} }
+1 -2
View File
@@ -2508,8 +2508,7 @@ namespace Game.Entities
} }
// check FFA_PVP // check FFA_PVP
if (Convert.ToBoolean(GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp) if (IsFFAPvP() && target.IsFFAPvP())
&& Convert.ToBoolean(target.GetByteValue(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag) & (byte)UnitBytes2Flags.FFAPvp))
return ReputationRank.Hostile; return ReputationRank.Hostile;
if (selfPlayerOwner != null) if (selfPlayerOwner != null)
+3 -3
View File
@@ -1458,9 +1458,9 @@ namespace Game.Maps
float i_range; 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_obj = obj;
i_funit = funit; i_funit = funit;
@@ -1481,7 +1481,7 @@ namespace Game.Maps
if (!u.isTargetableForAttack(false)) if (!u.isTargetableForAttack(false))
return 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; return false;
i_range = i_obj.GetDistance(u); i_range = i_obj.GetDistance(u);