コード例 #1
0
 /// <summary>
 /// Plots a course and notifies the requester of the outcome via the onCoursePlotCompleted event if set.
 /// </summary>
 /// <param name="target">The target.</param>
 /// <param name="speed">The speed.</param>
 public void PlotCourse(INavigableTarget target, Speed speed) {
     Target = target;
     Speed = speed;
     D.Assert(speed != Speed.Stop, "{0} designated speed to new target {1} is 0!".Inject(_fleet.FullName, target.FullName));
     InitializeTargetValues();
     InitializeReplotValues();
     GenerateCourse();
 }
コード例 #2
0
ファイル: ANavigator2.cs プロジェクト: Maxii/CodeEnv.Master
        /// <summary>
        /// Checks for an obstacle enroute to the designated <c>navTarget</c>. Returns true if one
        /// is found and provides the detour around it.
        /// </summary>
        /// <param name="destination">The current destination.</param>
        /// <param name="destinationCastingKeepoutRadius">The distance around the destination to avoid casting into.</param>
        /// <param name="detour">The obstacle detour.</param>
        /// <param name="obstacleHitDistance">The obstacle hit distance.</param>
        /// <returns>
        ///   <c>true</c> if an obstacle was found, false if the way is clear.
        /// </returns>
        protected bool TryCheckForObstacleEnrouteTo(INavigableTarget destination, float destinationCastingKeepoutRadius, out INavigableTarget detour, out float obstacleHitDistance) {
            detour = null;
            obstacleHitDistance = Mathf.Infinity;
            Vector3 vectorToDestination = destination.Position - Position;
            float destinationDistance = vectorToDestination.magnitude;
            if (destinationDistance <= destinationCastingKeepoutRadius) {
                return false;
            }
            Vector3 destinationBearing = vectorToDestination.normalized;
            float rayLength = destinationDistance - destinationCastingKeepoutRadius;
            Ray entryRay = new Ray(Position, destinationBearing);

            RaycastHit entryHit;
            if (Physics.Raycast(entryRay, out entryHit, rayLength, _keepoutOnlyLayerMask.value)) {
                // there is a keepout zone obstacle in the way 
                var obstacle = entryHit.transform;
                string obstacleName = obstacle.parent.name + "." + obstacle.name;
                obstacleHitDistance = entryHit.distance;
                D.Log("{0} encountered obstacle {1} centered at {2} when checking approach to {3}. \nRay length = {4:0.#}, DistanceToHit = {5:0.#}.",
                Name, obstacleName, obstacle.position, destination.FullName, rayLength, obstacleHitDistance);
                detour = GenerateDetourAroundObstacle(entryRay, entryHit);

                INavigableTarget newDetour;
                float newObstacleHitDistance;
                if (TryCheckForObstacleEnrouteTo(detour, 0F, out newDetour, out newObstacleHitDistance)) {
                    D.Warn("{0} found another obstacle on the way to detour {1}.", Name, detour.FullName);
                    detour = newDetour;
                    obstacleHitDistance = newObstacleHitDistance;
                }
                return true;
            }
            return false;
        }
コード例 #3
0
ファイル: ANavigator2.cs プロジェクト: Maxii/CodeEnv.Master
 /// <summary>
 /// Refreshes the course.
 /// </summary>
 /// <param name="mode">The mode.</param>
 /// <param name="waypoint">The waypoint.</param>
 protected abstract void RefreshCourse(CourseRefreshMode mode, INavigableTarget waypoint = null);
コード例 #4
0
ファイル: FleetCmdModel.cs プロジェクト: Maxii/CodeEnv.Master
 void Moving_ExitState() {
     LogEvent();
     var mortalMoveTarget = _moveTarget as IMortalTarget;
     if (mortalMoveTarget != null) {
         mortalMoveTarget.onTargetDeathOneShot -= OnTargetDeath;
     }
     _moveTarget = null;
     _navigator.DisengageAutoPilot();
 }
コード例 #5
0
ファイル: ANavigator2.cs プロジェクト: Maxii/CodeEnv.Master
 /// <summary>
 /// Plots the course to the target and notifies the requester of the outcome via the onCoursePlotSuccess or Failure events.
 /// </summary>
 /// <param name="target">The target.</param>
 /// <param name="travelSpeed">The speed to travel at.</param>
 public virtual void PlotCourse(INavigableTarget target, Speed travelSpeed, OrderSource orderSource) {
     D.Assert(travelSpeed != default(Speed) && travelSpeed != Speed.Stop && travelSpeed != Speed.EmergencyStop, "{0} speed of {1} is illegal.".Inject(Name, travelSpeed.GetValueName()));
     Target = target;
     TravelSpeed = travelSpeed;
     _orderSource = orderSource;
 }
コード例 #6
0
ファイル: FleetCmdModel.cs プロジェクト: Maxii/CodeEnv.Master
        /// <summary>
        /// Checks to see if any System entry or exit points need to be set. If it is determined an entry or exit
        /// point is needed, the appropriate point will be set to minimize the amount of InSystem travel time req'd to reach the
        /// target and the method will return true. These points will then be inserted into the course that is plotted by GenerateCourse();
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="fleetSystemExitPt">The fleet system exit pt.</param>
        /// <param name="targetSystemEntryPt">The target system entry pt.</param>
        /// <returns></returns>
        private bool TryCheckForSystemAccessPoints(INavigableTarget target, out Vector3 fleetSystemExitPt, out Vector3 targetSystemEntryPt) {
            targetSystemEntryPt = Vector3.zero;
            fleetSystemExitPt = Vector3.zero;

            SystemModel fleetSystem = null;
            SystemModel targetSystem = null;

            //D.Log("{0}.Topography = {1}.", _fleet.FullName, _fleet.Topography);
            if (_fleet.Topography == Topography.System) {
                var fleetSectorIndex = SectorGrid.GetSectorIndex(_fleet.Position);
                D.Assert(SystemCreator.TryGetSystem(fleetSectorIndex, out fleetSystem));  // error if a system isn't found
                D.Assert(Vector3.SqrMagnitude(fleetSystem.Position - _fleet.Position) <= fleetSystem.Radius * fleetSystem.Radius);
                D.Log("{0} is plotting a course from within System {1}.", _fleet.FullName, fleetSystem.FullName);
            }

            //D.Log("{0}.Topography = {1}.", target.FullName, target.Topography);
            if (target.Topography == Topography.System) {
                var targetSectorIndex = SectorGrid.GetSectorIndex(target.Position);
                D.Assert(SystemCreator.TryGetSystem(targetSectorIndex, out targetSystem));  // error if a system isn't found
                D.Assert(Vector3.SqrMagnitude(targetSystem.Position - target.Position) <= targetSystem.Radius * targetSystem.Radius);
                D.Log("{0}'s target {1} is contained within System {2}.", _fleet.FullName, target.FullName, targetSystem.FullName);
            }

            var result = false;
            if (fleetSystem != null) {
                if (fleetSystem == targetSystem) {
                    // the target and fleet are in the same system so exit and entry points aren't needed
                    D.Log("{0} start and destination {1} is contained within System {2}.", _fleet.FullName, target.FullName, fleetSystem.FullName);
                    return result;
                }
                fleetSystemExitPt = UnityUtility.FindClosestPointOnSphereTo(_fleet.Position, fleetSystem.Position, fleetSystem.Radius);
                result = true;
            }

            if (targetSystem != null) {
                targetSystemEntryPt = UnityUtility.FindClosestPointOnSphereTo(target.Position, targetSystem.Position, targetSystem.Radius);
                result = true;
            }
            return result;
        }
コード例 #7
0
ファイル: FleetCmdModel.cs プロジェクト: Maxii/CodeEnv.Master
 public void __IssueShipMovementOrders(INavigableTarget target, Speed speed) {
     var shipMoveToOrder = new ShipOrder(ShipDirective.Move, OrderSource.UnitCommand, target, speed);
     Elements.ForAll(e => (e as ShipModel).CurrentOrder = shipMoveToOrder);
 }
コード例 #8
0
ファイル: FleetCmdModel.cs プロジェクト: Maxii/CodeEnv.Master
    IEnumerator ExecuteJoinFleetOrder_EnterState() {
        D.Log("{0}.ExecuteJoinFleetOrder_EnterState called.", FullName);
        _moveTarget = CurrentOrder.Target;
        D.Assert(CurrentOrder.Speed == Speed.None,
            "{0}.JoinFleetOrder has speed set to {1}.".Inject(FullName, CurrentOrder.Speed.GetValueName()));
        _moveSpeed = Speed.FleetStandard;
        Call(FleetState.Moving);
        yield return null;  // required immediately after Call() to avoid FSM bug
        if (_isDestinationUnreachable) {
            CurrentState = FleetState.Idling;
            yield break;
        }

        // we've arrived so transfer the ship to the fleet we are joining
        var fleetToJoin = CurrentOrder.Target as FleetCmdModel;
        var ship = Elements[0] as ShipModel;   // IMPROVE more than one ship?
        TransferShip(ship, fleetToJoin);
        // removing the only ship will immediately call FleetState.Dead
    }
コード例 #9
0
ファイル: FleetCmdModel.cs プロジェクト: Maxii/CodeEnv.Master
        /// <summary>
        /// Plots the course to the target and notifies the requester of the outcome via the onCoursePlotSuccess or Failure events.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="speed">The speed.</param>
        public void PlotCourse(INavigableTarget target, Speed speed) {
            D.Assert(speed != default(Speed) && speed != Speed.Stop, "{0} speed of {1} is illegal.".Inject(_fleet.FullName, speed.GetValueName()));

            TryCheckForSystemAccessPoints(target, out _fleetSystemExitPoint, out _targetSystemEntryPoint);

            Target = target;
            FleetSpeed = speed;
            AssessFrequencyOfCourseProgressChecks();
            InitializeReplotValues();
            GenerateCourse();
        }
コード例 #10
0
ファイル: ShipNavigator.cs プロジェクト: Maxii/CodeEnv.Master
 /// <summary>
 /// Plots the course to the target and notifies the requester of the 
 /// outcome via the onCoursePlotCompleted event.
 /// </summary>
 /// <param name="target">The target.</param>
 /// <param name="speed">The speed.</param>
 /// <param name="standoffDistance">The distance to standoff from the target. When appropriate, this is added to the radius of the target to
 /// determine how close the ship is allowed to approach.</param>
 /// <param name="isFleetMove">if set to <c>true</c> the ship will only move when the fleet is ready.</param>
 public void PlotCourse(INavigableTarget target, Speed speed, float standoffDistance, bool isFleetMove) {
     if (target is IFormationStation) {
         PlotCourse(target as IFormationStation, speed);
     }
     else if (target is StationaryLocation) {
         PlotCourse(target as StationaryLocation, speed, isFleetMove);
     }
     else if (target is ICmdTarget) {
         PlotCourse(target as ICmdTarget, speed, standoffDistance);
     }
     else if (target is IElementAttackableTarget) {
         PlotCourse(target as IElementAttackableTarget, speed, standoffDistance);
     }
     else if (target is IMortalTarget) {
         D.Assert(target is IPlanetoidModel);
         PlotCourse(target as IMortalTarget, speed, standoffDistance, isFleetMove);
     }
     else {
         D.Error("{0} of Type {1} not anticipated.", target.FullName, target.GetType().Name);
     }
 }
コード例 #11
0
ファイル: FleetCmdModel.cs プロジェクト: Maxii/CodeEnv.Master
    IEnumerator ExecuteAttackOrder_EnterState() {
        D.Log("{0}.ExecuteAttackOrder_EnterState called. Target = {1}.", FullName, CurrentOrder.Target.FullName);
        _moveTarget = CurrentOrder.Target;
        _moveSpeed = Speed.FleetFull;
        Call(FleetState.Moving);
        yield return null;  // required immediately after Call() to avoid FSM bug
        if (_isDestinationUnreachable) {
            CurrentState = FleetState.Idling;
            yield break;
        }
        if (!(CurrentOrder.Target as IMortalTarget).IsAlive) {
            // Moving Return()s if the target dies
            CurrentState = FleetState.Idling;
            yield break;
        }

        Call(FleetState.Attacking);
        yield return null;  // required immediately after Call() to avoid FSM bug
        CurrentState = FleetState.Idling;
    }
コード例 #12
0
ファイル: ShipModel.cs プロジェクト: Maxii/CodeEnv.Master
        /// <summary>
        /// Plots the course to the target and notifies the requester of the outcome via the onCoursePlotSuccess or Failure events.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="speed">The speed.</param>
        /// <param name="orderSource">The source of this move order.</param>
        public void PlotCourse(INavigableTarget target, Speed speed, OrderSource orderSource) {
            D.Assert(speed != default(Speed) && speed != Speed.Stop, "{0} speed of {1} is illegal.".Inject(_ship.FullName, speed.GetValueName()));

            // NOTE: I know of no way to check whether a target is unreachable at this stage since many targets move, 
            // and most have a closeEnoughDistance that makes them reachable even when enclosed in a keepoutZone

            if (target is IFormationStation) {
                D.Assert(orderSource == OrderSource.ElementCaptain);
                DestinationInfo = new ShipDestinationInfo(target as IFormationStation);
            }
            else if (target is SectorModel) {
                Vector3 destinationOffset = orderSource == OrderSource.UnitCommand ? _ship.Data.FormationStation.StationOffset : Vector3.zero;
                DestinationInfo = new ShipDestinationInfo(target as SectorModel, destinationOffset);
            }
            else if (target is StationaryLocation) {
                Vector3 destinationOffset = orderSource == OrderSource.UnitCommand ? _ship.Data.FormationStation.StationOffset : Vector3.zero;
                var autoPilotSpeedReference = new Reference<float>(() => _autoPilotSpeedInUnitsPerHour);
                DestinationInfo = new ShipDestinationInfo((StationaryLocation)target, destinationOffset, autoPilotSpeedReference);
            }
            else if (target is FleetCmdModel) {
                D.Assert(orderSource == OrderSource.UnitCommand);
                var fleetTarget = target as FleetCmdModel;
                bool isEnemy = _ship.Owner.IsEnemyOf(fleetTarget.Owner);
                DestinationInfo = new ShipDestinationInfo(fleetTarget, _ship.Data.FormationStation.StationOffset, isEnemy);
            }
            else if (target is AUnitBaseCmdModel) {
                D.Assert(orderSource == OrderSource.UnitCommand);
                var baseTarget = target as AUnitBaseCmdModel;
                bool isEnemy = _ship.Owner.IsEnemyOf(baseTarget.Owner);
                DestinationInfo = new ShipDestinationInfo(baseTarget, _ship.Data.FormationStation.StationOffset, isEnemy);
            }
            else if (target is FacilityModel) {
                D.Assert(orderSource == OrderSource.ElementCaptain);
                var facilityTarget = target as FacilityModel;
                bool isEnemy = _ship.Owner.IsEnemyOf(facilityTarget.Owner);
                DestinationInfo = new ShipDestinationInfo(facilityTarget, isEnemy);
            }
            else if (target is ShipModel) {
                D.Assert(orderSource == OrderSource.ElementCaptain);
                var shipTarget = target as ShipModel;
                bool isEnemy = _ship.Owner.IsEnemyOf(shipTarget.Owner);
                DestinationInfo = new ShipDestinationInfo(shipTarget, isEnemy);
            }
            else if (target is APlanetoidModel) {
                Vector3 destinationOffset = orderSource == OrderSource.UnitCommand ? _ship.Data.FormationStation.StationOffset : Vector3.zero;
                DestinationInfo = new ShipDestinationInfo(target as APlanetoidModel, destinationOffset);
            }
            else if (target is SystemModel) {
                Vector3 destinationOffset = orderSource == OrderSource.UnitCommand ? _ship.Data.FormationStation.StationOffset : Vector3.zero;
                DestinationInfo = new ShipDestinationInfo(target as SystemModel, destinationOffset);
            }
            else if (target is StarModel) {
                Vector3 destinationOffset = orderSource == OrderSource.UnitCommand ? _ship.Data.FormationStation.StationOffset : Vector3.zero;
                DestinationInfo = new ShipDestinationInfo(target as StarModel, destinationOffset);
            }
            else if (target is UniverseCenterModel) {
                Vector3 destinationOffset = orderSource == OrderSource.UnitCommand ? _ship.Data.FormationStation.StationOffset : Vector3.zero;
                DestinationInfo = new ShipDestinationInfo(target as UniverseCenterModel, destinationOffset);
            }
            else {
                D.Error("{0} of Type {1} not anticipated.", target.FullName, target.GetType().Name);
                return;
            }

            OrderSource = orderSource;
            AutoPilotSpeed = speed;
            RefreshNavigationalValues();
            OnCoursePlotSuccess();
        }
コード例 #13
0
ファイル: ShipModel.cs プロジェクト: Maxii/CodeEnv.Master
    IEnumerator ExecuteRepairOrder_EnterState() {
        D.Log("{0}.ExecuteRepairOrder_EnterState called.", FullName);

        TryBreakOrbit();

        _moveSpeed = Speed.Full;
        _moveTarget = CurrentOrder.Target;
        _orderSource = OrderSource.ElementCaptain;  // UNCLEAR what if the fleet issued the fleet-wide repair order?
        Call(ShipState.Moving);
        yield return null;  // required immediately after Call() to avoid FSM bug
        // Return()s here
        if (_isDestinationUnreachable) {
            //TODO how to handle move errors?
            CurrentState = ShipState.Idling;
            yield break;
        }

        if (AssessWhetherToAssumeOrbit()) {
            Call(ShipState.AssumingOrbit);
            yield return null;  // required immediately after Call() to avoid FSM bug
            // Return()s here
        }

        Call(ShipState.Repairing);
        yield return null;  // required immediately after Call() to avoid FSM bug
        CurrentState = ShipState.Idling;
    }
コード例 #14
0
ファイル: ShipModel.cs プロジェクト: Maxii/CodeEnv.Master
    private IMortalTarget _primaryTarget; // IMPROVE  take this previous target into account when PickPrimaryTarget()

    IEnumerator ExecuteAttackOrder_EnterState() {
        D.Log("{0}.ExecuteAttackOrder_EnterState() called.", FullName);

        TryBreakOrbit();

        _ordersTarget = CurrentOrder.Target as IMortalTarget;
        while (_ordersTarget.IsAlive) {
            // once picked, _primaryTarget cannot be null when _ordersTarget is alive
            bool inRange = PickPrimaryTarget(out _primaryTarget);
            if (inRange) {
                D.Assert(_primaryTarget != null);
                // while this inRange state exists, we wait for OnWeaponReady() to be called
            }
            else {
                _moveTarget = _primaryTarget;
                _moveSpeed = Speed.Full;
                _orderSource = OrderSource.ElementCaptain;
                Call(ShipState.Moving);
                yield return null;  // required immediately after Call() to avoid FSM bug
                if (_isDestinationUnreachable) {
                    __HandleDestinationUnreachable();
                    yield break;
                }
                _helm.AllStop();  // stop and shoot after completing move
            }
            yield return null;
        }
        CurrentState = ShipState.Idling;
    }
コード例 #15
0
ファイル: ShipModel.cs プロジェクト: Maxii/CodeEnv.Master
 void Moving_ExitState() {
     LogEvent();
     var mortalMoveTarget = _moveTarget as IMortalTarget;
     if (mortalMoveTarget != null) {
         mortalMoveTarget.onTargetDeathOneShot -= OnTargetDeath;
     }
     _moveTarget = null;
     _moveSpeed = Speed.None;
     _orderSource = OrderSource.None;
     _helm.DisengageAutoPilot();
     // the ship retains its existing speed and heading upon exit
 }
コード例 #16
0
ファイル: ShipModel.cs プロジェクト: Maxii/CodeEnv.Master
 /// <summary>
 /// The Captain uses this method to issue orders.
 /// </summary>
 /// <param name="order">The order.</param>
 /// <param name="retainSuperiorsOrder">if set to <c>true</c> [retain superiors order].</param>
 /// <param name="target">The target.</param>
 /// <param name="speed">The speed.</param>
 private void OverrideCurrentOrder(ShipDirective order, bool retainSuperiorsOrder, INavigableTarget target = null, Speed speed = Speed.None) {
     // if the captain says to, and the current existing order is from his superior, then record it as a standing order
     ShipOrder standingOrder = null;
     if (retainSuperiorsOrder && CurrentOrder != null) {
         if (CurrentOrder.Source != OrderSource.ElementCaptain) {
             // the current order is from the Captain's superior so retain it
             standingOrder = CurrentOrder;
             if (IsHQElement) {
                 // the captain is overriding his superior on the flagship so declare an emergency   // HACK
                 Command.__OnHQElementEmergency();
             }
         }
         else if (CurrentOrder.StandingOrder != null) {
             // the current order is from the Captain, but there is a standing order in it so retain it
             standingOrder = CurrentOrder.StandingOrder;
         }
     }
     ShipOrder newOrder = new ShipOrder(order, OrderSource.ElementCaptain, target, speed) {
         StandingOrder = standingOrder
     };
     CurrentOrder = newOrder;
 }