From 7f053ea099e08f7da72a5491041ea0577874f5fe Mon Sep 17 00:00:00 2001 From: hondacrx Date: Tue, 4 Jan 2022 20:09:33 -0500 Subject: [PATCH] Core/Movement: Fix LoS issue of NPCs chasing targets Port From (https://github.com/TrinityCore/TrinityCore/commit/f012d4b7fcf0376de75f09c2b59509247fd133cb) --- Source/Game/Entities/Object/WorldObject.cs | 4 ++-- .../Movement/Generators/ChaseMovementGenerator.cs | 6 +++++- Source/Game/Movement/Generators/PathGenerator.cs | 13 +++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 18718da5d..f2a707a87 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -3023,7 +3023,7 @@ namespace Game.Entities return GetMap().IsInLineOfSight(GetPhaseShift(), x, y, z, ox, oy, oz, checks, ignoreFlags); } - Position GetHitSpherePointFor(Position dest) + public Position GetHitSpherePointFor(Position dest) { Vector3 vThis = new(GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight()); Vector3 vObj = new(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()); @@ -3032,7 +3032,7 @@ namespace Game.Entities return new Position(contactPoint.X, contactPoint.Y, contactPoint.Z, GetAbsoluteAngle(contactPoint.X, contactPoint.Y)); } - void GetHitSpherePointFor(Position dest, out float x, out float y, out float z) + public void GetHitSpherePointFor(Position dest, out float x, out float y, out float z) { Position pos = GetHitSpherePointFor(dest); x = pos.GetPositionX(); diff --git a/Source/Game/Movement/Generators/ChaseMovementGenerator.cs b/Source/Game/Movement/Generators/ChaseMovementGenerator.cs index 7a7b47168..b7cf6c335 100644 --- a/Source/Game/Movement/Generators/ChaseMovementGenerator.cs +++ b/Source/Game/Movement/Generators/ChaseMovementGenerator.cs @@ -259,7 +259,11 @@ namespace Game.Movement return false; if (maxDistance.HasValue && distSq > MathF.Sqrt(maxDistance.Value)) return false; - return !angle.HasValue || angle.Value.IsAngleOkay(target.GetRelativeAngle(owner)); + if (angle.HasValue && !angle.Value.IsAngleOkay(target.GetRelativeAngle(owner))) + return false; + if (!owner.IsWithinLOSInMap(target)) + return false; + return true; } static void DoMovementInform(Unit owner, Unit target) diff --git a/Source/Game/Movement/Generators/PathGenerator.cs b/Source/Game/Movement/Generators/PathGenerator.cs index d846a8d78..66cc0e0f5 100644 --- a/Source/Game/Movement/Generators/PathGenerator.cs +++ b/Source/Game/Movement/Generators/PathGenerator.cs @@ -892,6 +892,10 @@ namespace Game.Movement return; int i = _pathPoints.Length - 1; + float x; + float y; + float z; + float collisionHeight = _sourceUnit.GetCollisionHeight(); // find the first i s.t.: // - _pathPoints[i] is still too close // - _pathPoints[i-1] is too far away @@ -902,6 +906,15 @@ namespace Game.Movement if ((_pathPoints[i - 1] - target).LengthSquared() >= distSq) break; // bingo! + // check if the shortened path is still in LoS with the target + _sourceUnit.GetHitSpherePointFor(new Position(_pathPoints[i - 1].X, _pathPoints[i - 1].Y, _pathPoints[i - 1].Z + collisionHeight), out x, out y, out z); + if (!_sourceUnit.GetMap().IsInLineOfSight(_sourceUnit.GetPhaseShift(), x, y, z, _pathPoints[i - 1].X, _pathPoints[i - 1].Y, _pathPoints[i - 1].Z + collisionHeight, LineOfSightChecks.All, ModelIgnoreFlags.Nothing)) + { + // whenver we find a point that is not in LoS anymore, simply use last valid path + Array.Resize(ref _pathPoints, i + 1); + return; + } + if (--i == 0) { // no point found that fulfills the condition