/// <summary> /// Generates a detour around the provided obstacle. /// </summary> /// <param name="obstacle">The obstacle.</param> /// <param name="hitInfo">The hit information.</param> /// <param name="fleetRadius">The fleet radius.</param> /// <returns></returns> private AutoPilotDestinationProxy GenerateDetourAroundObstacle(IAvoidableObstacle obstacle, RaycastHit hitInfo, float fleetRadius) { Vector3 detourPosition = obstacle.GetDetour(Position, hitInfo, fleetRadius); StationaryLocation detour = new StationaryLocation(detourPosition); Vector3 detourOffset = CalcDetourOffset(detour); float tgtStandoffDistance = _ship.CollisionDetectionZoneRadius; return detour.GetApMoveTgtProxy(detourOffset, tgtStandoffDistance, Position); }
private void HandleObstacleFoundIsTarget(IAvoidableObstacle obstacle) { if (_ship.IsHQ) { // should never happen as HQ approach is always direct D.Warn("HQ {0} encountered obstacle {1} which is target.", DebugName, obstacle.DebugName); } ApTargetProxy.ResetOffset(); // go directly to target if (_apNavJob != null) { // if no _apNavJob HandleObstacleFoundIsTarget() call originated from EngagePilot D.AssertNotNull(_apObstacleCheckJob); ResumeDirectCourseToTarget(); } }
/// <summary> /// Tries to generate a detour around the provided obstacle. Returns <c>true</c> if a detour /// was generated, <c>false</c> otherwise. /// <remarks>A detour can always be generated around an obstacle. However, this algorithm considers other factors /// before initiating a heading change to redirect to a detour. E.g. moving obstacles that are far away /// and/or require only a small change in heading may not necessitate a diversion to a detour yet. /// </remarks> /// </summary> /// <param name="obstacle">The obstacle.</param> /// <param name="zoneHitInfo">The zone hit information.</param> /// <param name="detourProxy">The resulting detour.</param> /// <returns></returns> private bool TryGenerateDetourAroundObstacle(IAvoidableObstacle obstacle, RaycastHit zoneHitInfo, out AutoPilotDestinationProxy detourProxy) { detourProxy = GenerateDetourAroundObstacle(obstacle, zoneHitInfo, _ship.Command.UnitMaxFormationRadius); bool useDetour = true; Vector3 detourBearing = (detourProxy.Position - Position).normalized; float reqdTurnAngleToDetour = Vector3.Angle(_ship.CurrentHeading, detourBearing); if (obstacle.IsMobile) { if (reqdTurnAngleToDetour < DetourTurnAngleThreshold) { useDetour = false; // angle is still shallow but short remaining distance might require use of a detour float maxDistanceTraveledBeforeNextObstacleCheck = _engineRoom.IntendedCurrentSpeedValue * _apObstacleCheckPeriod.TotalInHours; float obstacleDistanceThresholdRequiringDetour = maxDistanceTraveledBeforeNextObstacleCheck * 2F; // HACK float distanceToObstacleZone = zoneHitInfo.distance; if (distanceToObstacleZone <= obstacleDistanceThresholdRequiringDetour) { useDetour = true; } } } if (useDetour) { D.Log(ShowDebugLog, "{0} has generated detour {1} to get by obstacle {2}. Reqd Turn = {3:0.#} degrees.", DebugName, detourProxy.DebugName, obstacle.DebugName, reqdTurnAngleToDetour); } else { D.Log(ShowDebugLog, "{0} has declined to generate a detour to get by mobile obstacle {1}. Reqd Turn = {2:0.#} degrees.", DebugName, obstacle.DebugName, reqdTurnAngleToDetour); } return useDetour; }
/// <summary> /// Hook for derived classes to take action when an obstacle has been found that is also the destination. /// </summary> /// <param name="obstacle">The obstacle.</param> protected virtual void HandleObstacleFoundIsTarget(IAvoidableObstacle obstacle) { //D.Assert(GetType() == typeof(ShipItem.ShipHelm)); }
/// <summary> /// Tries to generate a detour around the provided obstacle. Returns <c>true</c> if a detour was generated, <c>false</c> otherwise. /// </summary> /// <param name="obstacle">The obstacle.</param> /// <param name="zoneHitInfo">The zone hit information.</param> /// <param name="detour">The detour.</param> /// <returns></returns> protected abstract bool TryGenerateDetourAroundObstacle(IAvoidableObstacle obstacle, RaycastHit zoneHitInfo, out INavigable detour);
/// <summary> /// Generates a detour around the provided obstacle. /// </summary> /// <param name="obstacle">The obstacle.</param> /// <param name="hitInfo">The hit information.</param> /// <param name="fleetRadius">The fleet radius.</param> /// <returns></returns> protected INavigable GenerateDetourAroundObstacle(IAvoidableObstacle obstacle, RaycastHit hitInfo, float fleetRadius) { Vector3 detourPosition = obstacle.GetDetour(Position, hitInfo, fleetRadius); return new StationaryLocation(detourPosition); }
private bool TryGenerateDetourAroundObstacle(IAvoidableObstacle obstacle, RaycastHit zoneHitInfo, out IFleetNavigable detour) { detour = GenerateDetourAroundObstacle(obstacle, zoneHitInfo, _fleet.UnitMaxFormationRadius); if (obstacle.IsMobile) { Vector3 detourBearing = (detour.Position - Position).normalized; float reqdTurnAngleToDetour = Vector3.Angle(_fleetData.CurrentFlagshipFacing, detourBearing); if (reqdTurnAngleToDetour < DetourTurnAngleThreshold) { // Note: can't use a distance check here as Fleets don't check for obstacles based on time. // They only check when embarking on a new course leg //D.Log(ShowDebugLog, "{0} has declined to generate a detour around mobile obstacle {1}. Reqd Turn = {2:0.#} degrees.", DebugName, obstacle.DebugName, reqdTurnAngleToDetour); return false; } } return true; }