Beispiel #1
0
    IEnumerator ExecuteAssumeStationOrder_EnterState() {
        LogEvent();

        TryBreakOrbit();
        _helm.ChangeSpeed(Speed.Stop);

        if (IsHQ) {
            D.Assert(FormationStation.IsOnStation);
            if (CurrentOrder.ToNotifyCmd) {
                Command.HandleOrderOutcome(CurrentOrder.Directive, this, isSuccess: true);
            }
            CurrentState = ShipState.Idling;
            yield return null;
        }

        _apMoveSpeed = Speed.Standard;

        if (ShowDebugLog) {
            string speedMsg = "{0}({1:0.##}) units/hr".Inject(_apMoveSpeed.GetValueName(), _apMoveSpeed.GetUnitsPerHour(Data));
            D.Log("{0} is initiating repositioning to FormationStation at speed {1}. DistanceToStation: {2:0.##}.",
                DebugName, speedMsg, FormationStation.DistanceToStation);
        }

        Call(ShipState.Moving);
        yield return null;  // required so Return()s here

        if (_orderFailureCause != UnitItemOrderFailureCause.None) {
            if (CurrentOrder.ToNotifyCmd) {
                Command.HandleOrderOutcome(CurrentOrder.Directive, this, isSuccess: false, failCause: _orderFailureCause);
            }
            switch (_orderFailureCause) {
                case UnitItemOrderFailureCause.UnitItemNeedsRepair:
                    InitiateRepair(retainSuperiorsOrderOnRepairCompletion: false);
                    break;
                case UnitItemOrderFailureCause.UnitItemDeath:
                    // Dead state will follow
                    break;
                case UnitItemOrderFailureCause.TgtUncatchable:
                case UnitItemOrderFailureCause.TgtDeath:
                case UnitItemOrderFailureCause.TgtRelationship:
                case UnitItemOrderFailureCause.TgtUnreachable:
                default:
                    throw new NotImplementedException(ErrorMessages.UnanticipatedSwitchValue.Inject(_orderFailureCause));
            }
            yield return null;
        }
        if (FormationStation.IsOnStation) {
            D.Log(ShowDebugLog, "{0} has reached its formation station.", DebugName);
        }
        else {
            D.Warn("{0} has exited 'Moving' to its formation station without being on station.", DebugName);
        }

        // If there was a failure generated by Moving, resulting new Orders or Dead state should keep this point from being reached
        D.AssertDefault((int)_orderFailureCause, _orderFailureCause.GetValueName());

        // No need to wait for HQ to stop turning as we are aligning with its intended facing
        Vector3 hqIntendedHeading = Command.HQElement.Data.IntendedHeading;
        _helm.ChangeHeading(hqIntendedHeading, headingConfirmed: () => {
            Speed hqSpeed = Command.HQElement.CurrentSpeedSetting;
            _helm.ChangeSpeed(hqSpeed);  // UNCLEAR always align speed with HQ?
                                         //D.Log(ShowDebugLog, "{0} has aligned heading and speed {1} with HQ {2}.", DebugName, hqSpeed.GetValueName(), Command.HQElement.DebugName);
            if (CurrentOrder.ToNotifyCmd) {
                Command.HandleOrderOutcome(CurrentOrder.Directive, this, isSuccess: true);
            }
            CurrentState = ShipState.Idling;
        });
    }
Beispiel #2
0
 /// <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;
 }
Beispiel #3
0
 /// <summary>
 /// Primary exposed control that changes the speed of the ship and disengages the pilot.
 /// For use when managing the speed of the ship without relying on  the Autopilot.
 /// </summary>
 /// <param name="newSpeed">The new speed.</param>
 internal void ChangeSpeed(Speed newSpeed) {
     D.Assert(__ValidExternalChangeSpeeds.Contains(newSpeed), newSpeed.GetValueName());
     //D.Log(ShowDebugLog, "{0} is about to disengage pilot and change speed to {1}.", DebugName, newSpeed.GetValueName());
     DisengagePilot();
     ChangeSpeed_Internal(newSpeed, isFleetSpeed: false);
 }
Beispiel #4
0
            /// <summary>
            /// Exposed method allowing the ShipHelm to change speed. Returns <c>true</c> if the
            /// intendedNewSpeedValue was different than IntendedCurrentSpeedValue, false otherwise.
            /// </summary>
            /// <param name="newSpeed">The new speed.</param>
            /// <param name="intendedNewSpeedValue">The new speed value in units per hour.</param>
            /// <returns></returns>
            internal void ChangeSpeed(Speed newSpeed, float intendedNewSpeedValue) {
                //D.Log(ShowDebugLog, "{0}'s actual speed = {1:0.##} at EngineRoom.ChangeSpeed({2}, {3:0.##}).",
                //Name, ActualSpeedValue, newSpeed.GetValueName(), intendedNewSpeedValue);

                __PreviousIntendedCurrentSpeedValue = IntendedCurrentSpeedValue;
                CurrentSpeedSetting = newSpeed;
                IntendedCurrentSpeedValue = intendedNewSpeedValue;

                if (newSpeed == Speed.HardStop) {
                    //D.Log(ShowDebugLog, "{0} received ChangeSpeed to {1}!", DebugName, newSpeed.GetValueName());
                    DisengageForwardPropulsion();
                    DisengageReversePropulsion();
                    DisengageDriftCorrection();
                    // Can't terminate CollisionAvoidance as expect to find obstacle in Job lookup when collision averted
                    _shipRigidbody.velocity = Vector3.zero;
                    return;
                }

                if (Mathfx.Approx(intendedNewSpeedValue, __PreviousIntendedCurrentSpeedValue, .01F)) {
                    if (newSpeed != Speed.Stop) {    // can't be HardStop
                        if (!IsPropulsionEngaged) {
                            D.Error("{0} received ChangeSpeed({1}, {2:0.00}) without propulsion engaged to execute it.", DebugName, newSpeed.GetValueName(), intendedNewSpeedValue);
                        }
                    }
                    //D.Log(ShowDebugLog, "{0} is ignoring speed request of {1}({2:0.##}) as it is a duplicate.", DebugName, newSpeed.GetValueName(), intendedNewSpeedValue);
                    return;
                }

                if (IsCollisionAvoidanceEngaged) {
                    //D.Log(ShowDebugLog, "{0} is deferring engaging propulsion at Speed {1} until all collisions are averted.", 
                    //    DebugName, newSpeed.GetValueName());
                    return; // once collision is averted, ResumePropulsionAtRequestedSpeed() will be called
                }
                EngageOrContinuePropulsion();
            }
Beispiel #5
0
 /// <summary>
 /// Engages the pilot to move to the target using the provided proxy. It will notify the ship
 /// when it arrives via Ship.HandleTargetReached.
 /// </summary>
 /// <param name="apTgtProxy">The proxy for the target this Pilot is being engaged to reach.</param>
 /// <param name="speed">The initial speed the pilot should travel at.</param>
 /// <param name="isFleetwideMove">if set to <c>true</c> [is fleetwide move].</param>
 internal void EngagePilotToMoveTo(AutoPilotDestinationProxy apTgtProxy, Speed speed, bool isFleetwideMove) {
     Utility.ValidateNotNull(apTgtProxy);
     D.Assert(!InvalidApSpeeds.Contains(speed), speed.GetValueName());
     ApTargetProxy = apTgtProxy;
     ApSpeed = speed;
     _isApFleetwideMove = isFleetwideMove;
     _isApCurrentSpeedFleetwide = isFleetwideMove;
     _isApInPursuit = false;
     RefreshCourse(CourseRefreshMode.NewCourse);
     EngagePilot();
 }
Beispiel #6
0
 /// <summary>
 /// Records the AutoPilot values needed to plot a course.
 /// </summary>
 /// <param name="autoPilotTgt">The target this AutoPilot is being engaged to reach.</param>
 /// <param name="autoPilotSpeed">The speed the autopilot should travel at.</param>
 protected void RecordAutoPilotCourseValues(INavigable autoPilotTgt, Speed autoPilotSpeed) {
     Utility.ValidateNotNull(autoPilotTgt);
     D.Assert(!_inValidAutoPilotSpeeds.Contains(autoPilotSpeed), "{0} speed of {1} for autopilot is invalid.".Inject(Name, autoPilotSpeed.GetValueName()));
     AutoPilotTarget = autoPilotTgt;
     AutoPilotSpeed = autoPilotSpeed;
 }
Beispiel #7
0
        /// <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();
        }
Beispiel #8
0
        /// <summary>
        /// Plots the course to the target and notifies the requester of the outcome via the onCoursePlotSuccess or Failure events.
        /// </summary>
        /// <param name="apTgt">The target this AutoPilot is being engaged to reach.</param>
        /// <param name="apSpeed">The speed the autopilot should travel at.</param>
        /// <param name="apTgtStandoffDistance">The target standoff distance.</param>
        internal void PlotPilotCourse(IFleetNavigable apTgt, Speed apSpeed, float apTgtStandoffDistance) {
            Utility.ValidateNotNull(apTgt);
            D.Assert(!InvalidApSpeeds.Contains(apSpeed), apSpeed.GetValueName());
            ApTarget = apTgt;
            ApSpeedSetting = apSpeed;
            _apTgtStandoffDistance = apTgtStandoffDistance;

            IList<Vector3> directCourse;
            if (TryDirectCourse(out directCourse)) {
                // use this direct course
                //D.Log(ShowDebugLog, "{0} will use a direct course to {1}.", DebugName, ApTarget.DebugName);
                _isApCourseFromPath = false;
                ConstructApCourse(directCourse);
                HandleApCoursePlotSuccess();
            }
            else {
                _isApCourseFromPath = true;
                ResetPathReplotValues();
                PlotPath();
            }
        }
Beispiel #9
0
        /// <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();
        }