Core/Misc: Added new CanSeeOrDetectExtraArgs to CanSeeOrDetect
Port From (https://github.com/TrinityCore/TrinityCore/commit/260fab23786917619ad3453677ed7d983a431cc4)
This commit is contained in:
@@ -2035,7 +2035,7 @@ namespace Framework.Constants
|
|||||||
OnlyTargetOwnSummons = 0x10000, // Only Target Own Summons
|
OnlyTargetOwnSummons = 0x10000, // Only Target Own Summons
|
||||||
HasteAffectsDuration = 0x20000, // Haste Affects Duration
|
HasteAffectsDuration = 0x20000, // Haste Affects Duration
|
||||||
IgnoreSpellcastOverrideCost = 0x40000, // Ttile Ignore Spellcast Override Cost
|
IgnoreSpellcastOverrideCost = 0x40000, // Ttile Ignore Spellcast Override Cost
|
||||||
AllowTargetsHiddenBySpawnTracking = 0x80000, /*Nyi - No Spawn Tracking Implementation*/ // Allow Targets Hidden By Spawn Tracking
|
AllowTargetsHiddenBySpawnTracking = 0x80000, // Allow Targets Hidden By Spawn Tracking
|
||||||
RequiresEquippedInvTypes = 0x100000, // Requires Equipped Inv Types
|
RequiresEquippedInvTypes = 0x100000, // Requires Equipped Inv Types
|
||||||
NoSummonDestFromClientTargetingPathingRequirement = 0x200000, /*Nyi - Vald Path To A Spell Dest Is Not Required Currently If The Dest Comes From Client*/ // No 'Summon + Dest From Client' Targeting Pathing Requirement
|
NoSummonDestFromClientTargetingPathingRequirement = 0x200000, /*Nyi - Vald Path To A Spell Dest Is Not Required Currently If The Dest Comes From Client*/ // No 'Summon + Dest From Client' Targeting Pathing Requirement
|
||||||
MeleeHasteAffectsPeriodic = 0x400000, // Melee Haste Affects Periodic
|
MeleeHasteAffectsPeriodic = 0x400000, // Melee Haste Affects Periodic
|
||||||
@@ -2320,7 +2320,8 @@ namespace Framework.Constants
|
|||||||
SchoolmaskNormalWithMagic = 0x200000,
|
SchoolmaskNormalWithMagic = 0x200000,
|
||||||
DeprecatedLiquidAura = 0x400000,
|
DeprecatedLiquidAura = 0x400000,
|
||||||
IsTalent = 0x800000,
|
IsTalent = 0x800000,
|
||||||
AuraCannotBeSaved = 0x1000000
|
AuraCannotBeSaved = 0x1000000,
|
||||||
|
CanTargetAnyPrivateObject = 0x2000000,
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,12 @@ namespace Game.AI
|
|||||||
Unit victim = !_victimGuid.IsEmpty() ? Global.ObjAccessor.GetUnit(me, _victimGuid) : null;
|
Unit victim = !_victimGuid.IsEmpty() ? Global.ObjAccessor.GetUnit(me, _victimGuid) : null;
|
||||||
|
|
||||||
// Search victim if no, not attackable, or out of range, or friendly (possible in case duel end)
|
// Search victim if no, not attackable, or out of range, or friendly (possible in case duel end)
|
||||||
if (victim == null || !victim.IsTargetableForAttack() || !me.IsWithinDistInMap(victim, max_range) || me.IsFriendlyTo(victim) || !me.CanSeeOrDetect(victim))
|
CanSeeOrDetectExtraArgs canSeeOrDetectExtraArgs = new CanSeeOrDetectExtraArgs() {
|
||||||
|
IgnorePhaseShift = spellInfo.HasAttribute(SpellAttr6.IgnorePhaseShift),
|
||||||
|
IncludeHiddenBySpawnTracking = spellInfo.HasAttribute(SpellAttr8.AllowTargetsHiddenBySpawnTracking),
|
||||||
|
IncludeAnyPrivateObject = spellInfo.HasAttribute(SpellCustomAttributes.CanTargetAnyPrivateObject)
|
||||||
|
};
|
||||||
|
if (victim == null || !victim.IsTargetableForAttack() || !me.IsWithinDistInMap(victim, max_range) || me.IsFriendlyTo(victim) || !me.CanSeeOrDetect(victim, canSeeOrDetectExtraArgs))
|
||||||
{
|
{
|
||||||
float extraSearchRadius = max_range > 0.0f ? SharedConst.ExtraCellSearchRadius : 0.0f;
|
float extraSearchRadius = max_range > 0.0f ? SharedConst.ExtraCellSearchRadius : 0.0f;
|
||||||
var u_check = new NearestAttackableUnitInObjectRangeCheck(me, me.GetCharmerOrOwnerOrSelf(), max_range);
|
var u_check = new NearestAttackableUnitInObjectRangeCheck(me, me.GetCharmerOrOwnerOrSelf(), max_range);
|
||||||
|
|||||||
@@ -1271,18 +1271,18 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public SmoothPhasing GetSmoothPhasing() { return _smoothPhasing; }
|
public SmoothPhasing GetSmoothPhasing() { return _smoothPhasing; }
|
||||||
|
|
||||||
public bool CanSeeOrDetect(WorldObject obj, bool implicitDetect = false, bool distanceCheck = false, bool checkAlert = false)
|
public bool CanSeeOrDetect(WorldObject obj, CanSeeOrDetectExtraArgs args = default)
|
||||||
{
|
{
|
||||||
if (this == obj)
|
if (this == obj)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (obj.IsNeverVisibleFor(this, implicitDetect) || CanNeverSee(obj))
|
if (obj.IsNeverVisibleFor(this, args.ImplicitDetection) || CanNeverSee(obj, args.IgnorePhaseShift))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (obj.IsAlwaysVisibleFor(this) || CanAlwaysSee(obj))
|
if (obj.IsAlwaysVisibleFor(this) || CanAlwaysSee(obj))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!obj.CheckPrivateObjectOwnerVisibility(this))
|
if (!args.IncludeAnyPrivateObject && !obj.CheckPrivateObjectOwnerVisibility(this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SmoothPhasing smoothPhasing = obj.GetSmoothPhasing();
|
SmoothPhasing smoothPhasing = obj.GetSmoothPhasing();
|
||||||
@@ -1292,17 +1292,21 @@ namespace Game.Entities
|
|||||||
if (!obj.IsPrivateObject() && !Global.ConditionMgr.IsObjectMeetingVisibilityByObjectIdConditions(obj, this))
|
if (!obj.IsPrivateObject() && !Global.ConditionMgr.IsObjectMeetingVisibilityByObjectIdConditions(obj, this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Spawn tracking
|
|
||||||
Player player = ToPlayer();
|
Player player = ToPlayer();
|
||||||
if (player != null)
|
|
||||||
|
// Spawn tracking
|
||||||
|
if (!args.IncludeHiddenBySpawnTracking)
|
||||||
{
|
{
|
||||||
SpawnTrackingStateData spawnTrackingStateData = obj.GetSpawnTrackingStateDataForPlayer(player);
|
if (player != null)
|
||||||
if (spawnTrackingStateData != null && !spawnTrackingStateData.Visible)
|
{
|
||||||
return false;
|
SpawnTrackingStateData spawnTrackingStateData = obj.GetSpawnTrackingStateDataForPlayer(player);
|
||||||
|
if (spawnTrackingStateData != null && !spawnTrackingStateData.Visible)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool corpseVisibility = false;
|
bool corpseVisibility = false;
|
||||||
if (distanceCheck)
|
if (args.DistanceCheck)
|
||||||
{
|
{
|
||||||
bool corpseCheck = false;
|
bool corpseCheck = false;
|
||||||
Player thisPlayer = ToPlayer();
|
Player thisPlayer = ToPlayer();
|
||||||
@@ -1376,15 +1380,15 @@ namespace Game.Entities
|
|||||||
if (obj.IsInvisibleDueToDespawn(this))
|
if (obj.IsInvisibleDueToDespawn(this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CanDetect(obj, implicitDetect, checkAlert))
|
if (!CanDetect(obj, args.ImplicitDetection, args.AlertCheck))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool CanNeverSee(WorldObject obj)
|
public virtual bool CanNeverSee(WorldObject obj, bool ignorePhaseShift = false)
|
||||||
{
|
{
|
||||||
return GetMap() != obj.GetMap() || !InSamePhase(obj);
|
return GetMap() != obj.GetMap() || (!ignorePhaseShift && !InSamePhase(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool CanAlwaysSee(WorldObject obj) { return false; }
|
public virtual bool CanAlwaysSee(WorldObject obj) { return false; }
|
||||||
@@ -2679,11 +2683,16 @@ namespace Game.Entities
|
|||||||
if (unit != null)
|
if (unit != null)
|
||||||
{
|
{
|
||||||
// can't attack invisible
|
// can't attack invisible
|
||||||
if (bySpell == null || !bySpell.HasAttribute(SpellAttr6.IgnorePhaseShift))
|
CanSeeOrDetectExtraArgs canSeeOrDetectExtraArgs = new();
|
||||||
|
if (bySpell != null)
|
||||||
{
|
{
|
||||||
if (!unit.CanSeeOrDetect(target, bySpell != null && bySpell.IsAffectingArea()))
|
canSeeOrDetectExtraArgs.ImplicitDetection = bySpell.IsAffectingArea();
|
||||||
return false;
|
canSeeOrDetectExtraArgs.IgnorePhaseShift = bySpell.HasAttribute(SpellAttr6.IgnorePhaseShift);
|
||||||
|
canSeeOrDetectExtraArgs.IncludeHiddenBySpawnTracking = bySpell.HasAttribute(SpellAttr8.AllowTargetsHiddenBySpawnTracking);
|
||||||
|
canSeeOrDetectExtraArgs.IncludeAnyPrivateObject = bySpell.HasAttribute(SpellCustomAttributes.CanTargetAnyPrivateObject);
|
||||||
}
|
}
|
||||||
|
if (!unit.CanSeeOrDetect(target, canSeeOrDetectExtraArgs))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// can't attack dead
|
// can't attack dead
|
||||||
@@ -2845,7 +2854,15 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
// can't assist invisible
|
// can't assist invisible
|
||||||
if ((bySpell == null || !bySpell.HasAttribute(SpellAttr6.IgnorePhaseShift)) && !CanSeeOrDetect(target, bySpell != null && bySpell.IsAffectingArea()))
|
CanSeeOrDetectExtraArgs canSeeOrDetectExtraArgs = new();
|
||||||
|
if (bySpell != null)
|
||||||
|
{
|
||||||
|
canSeeOrDetectExtraArgs.ImplicitDetection = bySpell.IsAffectingArea();
|
||||||
|
canSeeOrDetectExtraArgs.IgnorePhaseShift = bySpell.HasAttribute(SpellAttr6.IgnorePhaseShift);
|
||||||
|
canSeeOrDetectExtraArgs.IncludeHiddenBySpawnTracking = bySpell.HasAttribute(SpellAttr8.AllowTargetsHiddenBySpawnTracking);
|
||||||
|
canSeeOrDetectExtraArgs.IncludeAnyPrivateObject = bySpell.HasAttribute(SpellCustomAttributes.CanTargetAnyPrivateObject);
|
||||||
|
}
|
||||||
|
if (!CanSeeOrDetect(target, canSeeOrDetectExtraArgs))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// can't assist dead
|
// can't assist dead
|
||||||
@@ -4332,4 +4349,15 @@ namespace Game.Entities
|
|||||||
return _changesMask[(int)index];
|
return _changesMask[(int)index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct CanSeeOrDetectExtraArgs
|
||||||
|
{
|
||||||
|
public bool ImplicitDetection;
|
||||||
|
public bool IgnorePhaseShift;
|
||||||
|
public bool IncludeHiddenBySpawnTracking;
|
||||||
|
public bool IncludeAnyPrivateObject;
|
||||||
|
|
||||||
|
public bool DistanceCheck;
|
||||||
|
public bool AlertCheck;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3959,11 +3959,11 @@ namespace Game.Entities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanNeverSee(WorldObject obj)
|
public override bool CanNeverSee(WorldObject obj, bool ignorePhaseShift = false)
|
||||||
{
|
{
|
||||||
// the intent is to delay sending visible objects until client is ready for them
|
// the intent is to delay sending visible objects until client is ready for them
|
||||||
// some gameobjects dont function correctly if they are sent before TransportServerTime is correctly set (after CMSG_MOVE_INIT_ACTIVE_MOVER_COMPLETE)
|
// some gameobjects dont function correctly if they are sent before TransportServerTime is correctly set (after CMSG_MOVE_INIT_ACTIVE_MOVER_COMPLETE)
|
||||||
return !HasPlayerLocalFlag(PlayerLocalFlags.OverrideTransportServerTime) || base.CanNeverSee(obj);
|
return !HasPlayerLocalFlag(PlayerLocalFlags.OverrideTransportServerTime) || base.CanNeverSee(obj, ignorePhaseShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanAlwaysSee(WorldObject obj)
|
public override bool CanAlwaysSee(WorldObject obj)
|
||||||
@@ -6229,7 +6229,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
if (HaveAtClient(target))
|
if (HaveAtClient(target))
|
||||||
{
|
{
|
||||||
if (!CanSeeOrDetect(target, false, true))
|
if (!CanSeeOrDetect(target, new CanSeeOrDetectExtraArgs() { DistanceCheck = true }))
|
||||||
{
|
{
|
||||||
BeforeVisibilityDestroy(target, this);
|
BeforeVisibilityDestroy(target, this);
|
||||||
|
|
||||||
@@ -6243,7 +6243,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (CanSeeOrDetect(target, false, true))
|
if (CanSeeOrDetect(target, new CanSeeOrDetectExtraArgs() { DistanceCheck = true }))
|
||||||
{
|
{
|
||||||
target.SendUpdateToPlayer(this);
|
target.SendUpdateToPlayer(this);
|
||||||
m_clientGUIDs.Add(target.GetGUID());
|
m_clientGUIDs.Add(target.GetGUID());
|
||||||
@@ -6259,7 +6259,7 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
if (HaveAtClient(target))
|
if (HaveAtClient(target))
|
||||||
{
|
{
|
||||||
if (!CanSeeOrDetect(target, false, true))
|
if (!CanSeeOrDetect(target, new CanSeeOrDetectExtraArgs() { DistanceCheck = true }))
|
||||||
{
|
{
|
||||||
BeforeVisibilityDestroy(target, this);
|
BeforeVisibilityDestroy(target, this);
|
||||||
|
|
||||||
@@ -6273,7 +6273,7 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (CanSeeOrDetect(target, false, true))
|
if (CanSeeOrDetect(target, new CanSeeOrDetectExtraArgs() { DistanceCheck = true }))
|
||||||
{
|
{
|
||||||
target.BuildCreateUpdateBlockForPlayer(data, this);
|
target.BuildCreateUpdateBlockForPlayer(data, this);
|
||||||
m_clientGUIDs.Add(target.GetGUID());
|
m_clientGUIDs.Add(target.GetGUID());
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ namespace Game.Maps
|
|||||||
|
|
||||||
if (!c.HasUnitState(UnitState.Sightless))
|
if (!c.HasUnitState(UnitState.Sightless))
|
||||||
{
|
{
|
||||||
if (c.IsAIEnabled() && c.CanSeeOrDetect(u, false, true))
|
if (c.IsAIEnabled() && c.CanSeeOrDetect(u, new CanSeeOrDetectExtraArgs() { DistanceCheck = true }))
|
||||||
c.GetAI().MoveInLineOfSight_Safe(u);
|
c.GetAI().MoveInLineOfSight_Safe(u);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (u.IsTypeId(TypeId.Player) && u.HasStealthAura() && c.IsAIEnabled() && c.CanSeeOrDetect(u, false, true, true))
|
if (u.IsTypeId(TypeId.Player) && u.HasStealthAura() && c.IsAIEnabled() && c.CanSeeOrDetect(u, new CanSeeOrDetectExtraArgs() { DistanceCheck = true, AlertCheck = true }))
|
||||||
c.GetAI().TriggerAlert(u);
|
c.GetAI().TriggerAlert(u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -995,8 +995,15 @@ namespace Game.Spells
|
|||||||
if (HasAttribute(SpellAttr1.ExcludeCaster) && caster == target)
|
if (HasAttribute(SpellAttr1.ExcludeCaster) && caster == target)
|
||||||
return SpellCastResult.BadTargets;
|
return SpellCastResult.BadTargets;
|
||||||
|
|
||||||
// check visibility - ignore invisibility/stealth for implicit (area) targets
|
// check visibility - Ignore invisibility/stealth for implicit (area) targets
|
||||||
if (!HasAttribute(SpellAttr6.IgnorePhaseShift) && !caster.CanSeeOrDetect(target, Implicit))
|
CanSeeOrDetectExtraArgs canSeeOrDetectExtraArgs = new CanSeeOrDetectExtraArgs
|
||||||
|
{
|
||||||
|
ImplicitDetection = Implicit,
|
||||||
|
IgnorePhaseShift = HasAttribute(SpellAttr6.IgnorePhaseShift),
|
||||||
|
IncludeHiddenBySpawnTracking = HasAttribute(SpellAttr8.AllowTargetsHiddenBySpawnTracking),
|
||||||
|
IncludeAnyPrivateObject = HasAttribute(SpellCustomAttributes.CanTargetAnyPrivateObject)
|
||||||
|
};
|
||||||
|
if (!caster.CanSeeOrDetect(target, canSeeOrDetectExtraArgs))
|
||||||
return SpellCastResult.BadTargets;
|
return SpellCastResult.BadTargets;
|
||||||
|
|
||||||
Unit unitTarget = target.ToUnit();
|
Unit unitTarget = target.ToUnit();
|
||||||
|
|||||||
Reference in New Issue
Block a user