diff options
author | jackpoz <giacomopoz@gmail.com> | 2014-04-07 22:16:31 +0200 |
---|---|---|
committer | jackpoz <giacomopoz@gmail.com> | 2014-04-07 22:16:31 +0200 |
commit | 8927a042536d4671e94ad901e9209efcf78ffa2c (patch) | |
tree | ac19bf156e54509552118852a921997bb711c8bc | |
parent | b717ce0edaf2fec82eeac1f73d6817098c420385 (diff) |
Core/Movement: Fix LoS issue of NPCs chasing targets
Add Line of Sight checks to WorldObject::GetNearPoint(), fixing to TargetedMovementGenerator not reaching a point with valid LoS to the target and MotionMaster::MoveKnockbackFrom() knocking creatures inside walls.
Remove unused code.
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 117 | ||||
-rw-r--r-- | src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp | 5 |
2 files changed, 19 insertions, 103 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 69f7073ce1b..c0a54060298 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2489,125 +2489,36 @@ void WorldObject::GetNearPoint(WorldObject const* /*searcher*/, float &x, float { GetNearPoint2D(x, y, distance2d+searcher_size, absAngle); z = GetPositionZ(); + // Should "searcher" be used instead of "this" when updating z coordinate ? UpdateAllowedPositionZ(x, y, z); - /* // if detection disabled, return first point - if (!sWorld->getIntConfig(CONFIG_DETECT_POS_COLLISION)) - { - UpdateGroundPositionZ(x, y, z); // update to LOS height if available + if (!sWorld->getBoolConfig(CONFIG_DETECT_POS_COLLISION)) return; - } - // or remember first point - float first_x = x; - float first_y = y; - bool first_los_conflict = false; // first point LOS problems - - // prepare selector for work - ObjectPosSelector selector(GetPositionX(), GetPositionY(), GetObjectSize(), distance2d+searcher_size); - - // adding used positions around object - { - CellCoord p(Trinity::ComputeCellCoord(GetPositionX(), GetPositionY())); - Cell cell(p); - cell.SetNoCreate(); - - Trinity::NearUsedPosDo u_do(*this, searcher, absAngle, selector); - Trinity::WorldObjectWorker<Trinity::NearUsedPosDo> worker(this, u_do); - - TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::NearUsedPosDo>, GridTypeMapContainer > grid_obj_worker(worker); - TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::NearUsedPosDo>, WorldTypeMapContainer > world_obj_worker(worker); - - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap(), *this, distance2d); - cell_lock->Visit(cell_lock, world_obj_worker, *GetMap(), *this, distance2d); - } - - // maybe can just place in primary position - if (selector.CheckOriginal()) - { - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - - if (IsWithinLOS(x, y, z)) - return; - - first_los_conflict = true; // first point have LOS problems - } - - float angle; // candidate of angle for free pos - - // special case when one from list empty and then empty side preferred - if (selector.FirstAngle(angle)) - { - GetNearPoint2D(x, y, distance2d, absAngle+angle); - z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - - if (IsWithinLOS(x, y, z)) - return; - } - - // set first used pos in lists - selector.InitializeAngle(); - - // select in positions after current nodes (selection one by one) - while (selector.NextAngle(angle)) // angle for free pos - { - GetNearPoint2D(x, y, distance2d, absAngle+angle); - z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - - if (IsWithinLOS(x, y, z)) - return; - } - - // BAD NEWS: not free pos (or used or have LOS problems) - // Attempt find _used_ pos without LOS problem - - if (!first_los_conflict) - { - x = first_x; - y = first_y; - - UpdateGroundPositionZ(x, y, z); // update to LOS height if available + // return if the point is already in LoS + if (IsWithinLOS(x, y, z)) return; - } - - // special case when one from list empty and then empty side preferred - if (selector.IsNonBalanced()) - { - if (!selector.FirstAngle(angle)) // _used_ pos - { - GetNearPoint2D(x, y, distance2d, absAngle+angle); - z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - - if (IsWithinLOS(x, y, z)) - return; - } - } - // set first used pos in lists - selector.InitializeAngle(); + // remember first point + float first_x = x; + float first_y = y; + float first_z = z; - // select in positions after current nodes (selection one by one) - while (selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem + // loop in a circle to look for a point in LoS using small steps + for (float angle = M_PI / 8; angle < M_PI * 2; angle += M_PI / 8) { - GetNearPoint2D(x, y, distance2d, absAngle+angle); + GetNearPoint2D(x, y, distance2d + searcher_size, absAngle + angle); z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - + UpdateAllowedPositionZ(x, y, z); if (IsWithinLOS(x, y, z)) return; } - // BAD BAD NEWS: all found pos (free and used) have LOS problem :( + // still not in LoS, give up and return first position found x = first_x; y = first_y; - - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - */ + z = first_z; } void WorldObject::GetClosePoint(float &x, float &y, float &z, float size, float distance2d /*= 0*/, float angle /*= 0*/) const diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 28e58c87323..c59762066ae 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -159,10 +159,15 @@ bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff) if (TransportBase* transport = owner->GetDirectTransport()) transport->CalculatePassengerPosition(dest.x, dest.y, dest.z); + // First check distance if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->CanFly()) targetMoved = !i_target->IsWithinDist3d(dest.x, dest.y, dest.z, allowed_dist); else targetMoved = !i_target->IsWithinDist2d(dest.x, dest.y, allowed_dist); + + // then, if the target is in range, check also Line of Sight. + if (!targetMoved) + targetMoved = !i_target->IsWithinLOSInMap(owner); } if (i_recalculateTravel || targetMoved) |