Exemplo n.º 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ShipMoveOrder" /> class.
 /// </summary>
 /// <param name="source">The source of the order.</param>
 /// <param name="target">The move target.</param>
 /// <param name="speed">The move speed.</param>
 /// <param name="isFleetwide">if set to <c>true</c> the move should be coordinated as a fleet.</param>
 /// <param name="targetStandoffDistance">When the ship arrives at the target, this is the distance
 /// from the target it should strive to achieve.</param>
 public ShipMoveOrder(OrderSource source, IShipNavigable target, Speed speed, bool isFleetwide, float targetStandoffDistance)
     : base(ShipDirective.Move, source, false, target) {
     Utility.ValidateNotNull(target);
     D.AssertNotDefault((int)speed);
     Utility.ValidateNotNegative(targetStandoffDistance);
     Speed = speed;
     IsFleetwide = isFleetwide;
     TargetStandoffDistance = targetStandoffDistance;
 }
 public AutoPilotDestinationProxy(IShipNavigable destination, Vector3 destOffset, float innerRadius, float outerRadius) {
     Utility.ValidateNotNull(destination);
     Utility.ValidateNotNegative(innerRadius);
     Utility.ValidateForRange(outerRadius, innerRadius, Mathf.Infinity); // HACK
     Destination = destination;
     _destOffset = destOffset;
     InnerRadius = innerRadius;
     _innerRadiusSqrd = innerRadius * innerRadius;
     OuterRadius = outerRadius;
     _outerRadiusSqrd = outerRadius * outerRadius;
     ArrivalWindowDepth = outerRadius - innerRadius;
 }
Exemplo n.º 3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ShipOrder" /> class.
 /// </summary>
 /// <param name="directive">The order directive.</param>
 /// <param name="source">The source of this order.</param>
 /// <param name="toNotifyCmd">if set to <c>true</c> the ship will notify its Command of the outcome.</param>
 /// <param name="target">The target of this order. No need for FormationStation. Default is null.</param>
 public ShipOrder(ShipDirective directive, OrderSource source, bool toNotifyCmd = false, IShipNavigable target = null) {
     if (directive == ShipDirective.Move) {
         D.AssertEqual(typeof(ShipMoveOrder), GetType());
         D.Assert(!toNotifyCmd);
     }
     if (directive.EqualsAnyOf(DirectivesWithNullTarget)) {
         D.AssertNull(target, ToString());
     }
     Directive = directive;
     Source = source;
     ToNotifyCmd = toNotifyCmd;
     Target = target;
 }
Exemplo n.º 4
0
    // 4.22.16: Currently Order is issued only by user or fleet as Captain doesn't know whether ship's formationStation 
    // is inside some local obstacle zone. Once HQ has arrived at the LocalAssyStation (if any), individual ships can 
    // still be a long way off trying to get there, so we need to rely on the AutoPilot to manage speed.

    void ExecuteAssumeStationOrder_UponPreconfigureState() {
        LogEvent();

        if (_fsmTgt != null) {
            D.Error("{0} _fsmTgt {1} should not already be assigned.", DebugName, _fsmTgt.DebugName);
        }
        D.AssertDefault((int)_orderFailureCause, _orderFailureCause.GetValueName());

        _fsmTgt = FormationStation;
    }
Exemplo n.º 5
0
 void ExecuteAssumeStationOrder_ExitState() {
     LogEvent();
     _orderFailureCause = UnitItemOrderFailureCause.None;
     _fsmTgt = null;
 }
Exemplo n.º 6
0
    void ExecuteMoveOrder_UponPreconfigureState() {
        LogEvent();

        if (_fsmTgt != null) {
            D.Error("{0} _fsmTgt {1} should not already be assigned.", DebugName, _fsmTgt.DebugName);
        }
        D.AssertDefault((int)_orderFailureCause, _orderFailureCause.GetValueName());
        D.Assert(!CurrentOrder.ToNotifyCmd);

        var currentShipMoveOrder = CurrentOrder as ShipMoveOrder;
        D.Assert(currentShipMoveOrder != null);

        _fsmTgt = currentShipMoveOrder.Target;

        __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.TargetDeath, _fsmTgt, toSubscribe: true);
        __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.InfoAccessChg, _fsmTgt, toSubscribe: true);
        __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.OwnerChg, _fsmTgt, toSubscribe: true);
    }
Exemplo n.º 7
0
 void ExecuteMoveOrder_ExitState() {
     LogEvent();
     __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.TargetDeath, _fsmTgt, toSubscribe: false);
     __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.InfoAccessChg, _fsmTgt, toSubscribe: false);
     __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.OwnerChg, _fsmTgt, toSubscribe: false);
     _fsmTgt = null;
     _orderFailureCause = UnitItemOrderFailureCause.None;
 }
Exemplo n.º 8
0
    /// <summary>
    /// Calculates and returns the world space offset reqd by the AutoPilotDestinationProxy wrapping _fsmTgt. 
    /// When combined with the target's position, the result represents the actual location in world space this ship
    /// is trying to reach. The ship will 'arrive' when it gets within the arrival window of the AutoPilotDestinationProxy.
    /// <remarks>Figures out what the HQ/Cmd ship's approach vector to the target would be if it headed
    /// directly for the target when called, and uses that rotation to calculate the desired offset to the
    /// target for this ship, based off the ship's formation station offset. The result returned can be subsequently
    /// changed to Vector3.zero using AutoPilotDestinationProxy.ResetOffset() if the ship finds it can't reach this initial 
    /// 'arrival point' due to the target itself being in the way.
    /// </remarks>
    /// </summary>
    /// <returns></returns>
    private Vector3 CalcFleetwideMoveTargetOffset(IShipNavigable moveTarget) {
        ShipItem hqShip = Command.HQElement;
        Quaternion hqShipCurrentRotation = hqShip.transform.rotation;
        Vector3 hqShipToTargetDirection = (moveTarget.Position - hqShip.Position).normalized;
        Quaternion hqShipRotationChgReqdToFaceTarget = Quaternion.FromToRotation(hqShip.CurrentHeading, hqShipToTargetDirection);
        Quaternion hqShipRotationThatFacesTarget = Math3D.AddRotation(hqShipCurrentRotation, hqShipRotationChgReqdToFaceTarget);

        Vector3 shipLocalFormationOffset = FormationStation.LocalOffset;
        if (moveTarget is AUnitBaseCmdItem || moveTarget is APlanetoidItem || moveTarget is StarItem || moveTarget is UniverseCenterItem) {
            // destination is a base, planetoid, star or UCenter so its something we could run into
            if (shipLocalFormationOffset.z > Constants.ZeroF) {
                // this ship's formation station is in front of Cmd so the ship will run into destination unless it stops short
                shipLocalFormationOffset = shipLocalFormationOffset.SetZ(Constants.ZeroF);
            }
        }
        Vector3 shipTargetOffset = Math3D.TransformDirectionMath(hqShipRotationThatFacesTarget, shipLocalFormationOffset);
        //D.Log(ShowDebugLog, "{0}.CalcFleetModeTargetOffset() called. Target: {1}, LocalOffsetUsed: {2}, WorldSpaceOffsetResult: {3}.",
        //    DebugName, moveTarget.DebugName, shipLocalFormationOffset, shipTargetOffset);
        return shipTargetOffset;
    }
Exemplo n.º 9
0
 private bool __TryValidateRightToAssumeHighOrbit(IShipNavigable moveTgt, out IShipOrbitable highOrbitTgt) {
     highOrbitTgt = moveTgt as IShipOrbitable;
     if (highOrbitTgt != null && highOrbitTgt.IsHighOrbitAllowedBy(Owner)) {
         return true;
     }
     return false;
 }
Exemplo n.º 10
0
 /// <summary>
 /// Handles the results of the ship's attempt to execute the provided directive.
 /// </summary>
 /// <param name="directive">The directive.</param>
 /// <param name="ship">The ship.</param>
 /// <param name="isSuccess">if set to <c>true</c> the directive was successfully completed. May still be ongoing.</param>
 /// <param name="target">The target. Can be null.</param>
 /// <param name="failCause">The failure cause if not successful.</param>
 internal void HandleOrderOutcome(ShipDirective directive, ShipItem ship, bool isSuccess, IShipNavigable target = null, UnitItemOrderFailureCause failCause = UnitItemOrderFailureCause.None) {
     UponOrderOutcome(directive, ship, isSuccess, target, failCause);
 }
Exemplo n.º 11
0
    void AssumingFormation_UponOrderOutcome(ShipDirective directive, ShipItem ship, bool isSuccess, IShipNavigable target, UnitItemOrderFailureCause failCause) {
        LogEvent();
        if (directive != ShipDirective.AssumeStation) {
            D.Warn("{0} State {1} erroneously received OrderOutcome callback with {2} {3}.", DebugName, CurrentState.GetValueName(), typeof(ShipDirective).Name, directive.GetValueName());
            return;
        }

        D.AssertNull(target);
        if (isSuccess) {
            _fsmShipWaitForOnStationCount--;
        }
        else {
            switch (failCause) {
                case UnitItemOrderFailureCause.UnitItemNeedsRepair:
                    // Ship will get repaired, but even if it goes to its formationStation to do so
                    // it won't communicate its success back to Cmd since Captain ordered it, not Cmd
                    _fsmShipWaitForOnStationCount--;
                    break;
                case UnitItemOrderFailureCause.UnitItemDeath:
                    _fsmShipWaitForOnStationCount--;
                    break;
                case UnitItemOrderFailureCause.TgtDeath:
                case UnitItemOrderFailureCause.TgtRelationship:
                case UnitItemOrderFailureCause.TgtUncatchable:
                case UnitItemOrderFailureCause.TgtUnreachable:
                case UnitItemOrderFailureCause.None:
                default:
                    throw new NotImplementedException(ErrorMessages.UnanticipatedSwitchValue.Inject(failCause));
            }
        }
        if (_fsmShipWaitForOnStationCount == Constants.Zero) {
            Return();
        }
    }
Exemplo n.º 12
0
    IEnumerator ExecuteAttackOrder_EnterState() {
        LogEvent();

        TryBreakOrbit();

        IUnitAttackable unitAttackTgt = CurrentOrder.Target as IUnitAttackable;
        string unitAttackTgtName = unitAttackTgt.DebugName;
        if (!unitAttackTgt.IsOperational) {
            // if this occurs, it happened in the yield return null delay before EnterState execution
            D.Warn("{0} was killed before {1} could begin attack. Canceling Attack Order.", unitAttackTgtName, DebugName);
            CurrentState = ShipState.Idling;
            yield return null;
        }
        // Other unitAttackTgt condition changes (owner, relationship, infoAccess) handled by FleetCmd

        ShipCombatStance stance = Data.CombatStance;
        if (stance == ShipCombatStance.Disengage) {
            if (IsHQ) {
                D.Warn("{0} as HQ cannot have {1} of {2}. Changing to {3}.", DebugName, typeof(ShipCombatStance).Name,
                    ShipCombatStance.Disengage.GetValueName(), ShipCombatStance.Defensive.GetValueName());
                Data.CombatStance = ShipCombatStance.Defensive;
            }
            else {
                if (IsThereNeedForAFormationStationChangeTo(WithdrawPurpose.Disengage)) {
                    D.AssertDefault((int)_fsmDisengagePurpose);
                    _fsmDisengagePurpose = WithdrawPurpose.Disengage;
                    ShipOrder disengageOrder = new ShipOrder(ShipDirective.Disengage, OrderSource.Captain);
                    OverrideCurrentOrder(disengageOrder, retainSuperiorsOrder: false);
                }
                else {
                    D.Log(ShowDebugLog, "{0} is already {1}d as the current FormationStation meets that need. Canceling Attack Order.",
                        DebugName, ShipDirective.Disengage.GetValueName());
                    CurrentState = ShipState.Idling;
                }
                yield return null;
            }
        }

        if (stance == ShipCombatStance.Defensive) {
            D.Log(ShowDebugLog, "{0}'s {1} is {2}. Changing Attack order to AssumeStationAndEntrench.",
                DebugName, typeof(ShipCombatStance).Name, ShipCombatStance.Defensive.GetValueName());
            ShipOrder assumeStationAndEntrenchOrder = new ShipOrder(ShipDirective.AssumeStation, OrderSource.Captain) {
                FollowonOrder = new ShipOrder(ShipDirective.Entrench, OrderSource.Captain)
            };
            OverrideCurrentOrder(assumeStationAndEntrenchOrder, retainSuperiorsOrder: false);
            yield return null;
        }

        if (unitAttackTgt.IsColdWarAttackByAllowed(Owner)) {
            // we are not at war with the owner of this Unit as Owner must be accessible
            WeaponRangeMonitors.ForAll(wrm => wrm.ToEngageColdWarEnemies = true);
            // IMPROVE weapons will shoot at ANY ColdWar or War enemy in range, even innocent ColdWar bystanders
        }

        bool allowLogging = true;
        IShipAttackable primaryAttackTgt;
        while (unitAttackTgt.IsOperational) {
            if (TryPickPrimaryAttackTgt(unitAttackTgt, allowLogging, out primaryAttackTgt)) {
                D.Log(ShowDebugLog, "{0} picked {1} as primary attack target.", DebugName, primaryAttackTgt.DebugName);
                // target found within sensor range that it can and wants to attack
                _fsmTgt = primaryAttackTgt as IShipNavigable;

                Call(ShipState.Attacking);
                yield return null;  // reqd so Return()s here

                if (_orderFailureCause != UnitItemOrderFailureCause.None) {
                    Command.HandleOrderOutcome(CurrentOrder.Directive, this, isSuccess: false, target: primaryAttackTgt, failCause: _orderFailureCause);
                    switch (_orderFailureCause) {
                        case UnitItemOrderFailureCause.TgtUncatchable:
                            continue;   // pick another primary attack target
                        case UnitItemOrderFailureCause.UnitItemNeedsRepair:
                            InitiateRepair(retainSuperiorsOrderOnRepairCompletion: false);
                            break;
                        case UnitItemOrderFailureCause.UnitItemDeath:
                            // No Cmd notification reqd in this state. Dead state will follow
                            break;
                        case UnitItemOrderFailureCause.TgtDeath:
                        // Should not happen as Attacking does not generate a failure cause when target dies
                        case UnitItemOrderFailureCause.TgtRelationship:
                        case UnitItemOrderFailureCause.TgtUnreachable:
                        default:
                            throw new NotImplementedException(ErrorMessages.UnanticipatedSwitchValue.Inject(_orderFailureCause));
                    }
                    yield return null;
                }
                else {
                    D.Assert(!primaryAttackTgt.IsOperational);
                    Command.HandleOrderOutcome(CurrentOrder.Directive, this, isSuccess: true, target: primaryAttackTgt);
                }

                _fsmTgt = null;
                allowLogging = true;
            }
            else {
                // declined to pick first or subsequent primary target
                if (allowLogging) {
                    D.LogBold(ShowDebugLog, "{0} is staying put as it found no target it chooses to attack associated with UnitTarget {1}.",
                        DebugName, unitAttackTgt.DebugName);  // either no operational weapons or no targets in sensor range
                    allowLogging = false;
                }
            }
            yield return null;
        }
        if (IsInOrbit) {
            D.Error("{0} is in orbit around {1} after killing {2}.", DebugName, _itemBeingOrbited.DebugName, unitAttackTgtName);
        }
        CurrentState = ShipState.Idling;
    }
Exemplo n.º 13
0
 void ExecuteAttackOrder_ExitState() {
     LogEvent();
     WeaponRangeMonitors.ForAll(wrm => wrm.ToEngageColdWarEnemies = false);
     _fsmTgt = null;
     _orderFailureCause = UnitItemOrderFailureCause.None;
 }
Exemplo n.º 14
0
    void ExecuteAssumeCloseOrbitOrder_ExitState() {
        LogEvent();

        __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.TargetDeath, _fsmTgt, toSubscribe: false);
        bool isUnsubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.InfoAccessChg, _fsmTgt, toSubscribe: false);
        D.Assert(isUnsubscribed);
        isUnsubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.OwnerChg, _fsmTgt, toSubscribe: false);
        D.Assert(isUnsubscribed);

        _fsmTgt = null;
        _orderFailureCause = UnitItemOrderFailureCause.None;
    }
Exemplo n.º 15
0
    // 4.22.16: Currently Order is issued only by user or fleet. Once HQ has arrived at the IShipCloseOrbitable target, 
    // individual ships can still be a long way off trying to get there, so we need to rely on the AutoPilot to manage speed.

    void ExecuteAssumeCloseOrbitOrder_UponPreconfigureState() {
        LogEvent();

        if (_fsmTgt != null) {
            D.Error("{0} _fsmTgt {1} should not already be assigned.", DebugName, _fsmTgt.DebugName);
        }
        D.AssertDefault((int)_orderFailureCause, _orderFailureCause.GetValueName());
        D.Assert(!CurrentOrder.ToNotifyCmd);

        var orbitTgt = CurrentOrder.Target as IShipCloseOrbitable;
        D.Assert(orbitTgt != null);
        _fsmTgt = orbitTgt;

        __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.TargetDeath, _fsmTgt, toSubscribe: true);
        bool isSubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.InfoAccessChg, _fsmTgt, toSubscribe: true);
        D.Assert(isSubscribed);
        isSubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.OwnerChg, _fsmTgt, toSubscribe: true);
        D.Assert(isSubscribed);
    }
Exemplo n.º 16
0
 /// <summary>
 /// Attempts subscribing or unsubscribing to <c>fsmTgt</c> in the mode provided.
 /// Returns <c>true</c> if the indicated subscribe action was taken, <c>false</c> if not.
 /// <remarks>Issues a warning if attempting to create a duplicate subscription.</remarks>
 /// </summary>
 /// <param name="subscriptionMode">The subscription mode.</param>
 /// <param name="fsmTgt">The target used by the State Machine.</param>
 /// <param name="toSubscribe">if set to <c>true</c> subscribe, otherwise unsubscribe.</param>
 /// <returns></returns>
 /// <exception cref="NotImplementedException"></exception>
 protected bool __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode subscriptionMode, IShipNavigable fsmTgt, bool toSubscribe) {
     Utility.ValidateNotNull(fsmTgt);
     bool isSubscribeActionTaken = false;
     bool isDuplicateSubscriptionAttempted = false;
     IItem_Ltd itemFsmTgt = null;
     bool isSubscribed = __subscriptionStatusLookup[subscriptionMode];
     switch (subscriptionMode) {
         case FsmTgtEventSubscriptionMode.TargetDeath:
             var mortalFsmTgt = fsmTgt as IMortalItem_Ltd;
             if (mortalFsmTgt != null) {
                 if (!toSubscribe) {
                     mortalFsmTgt.deathOneShot -= FsmTgtDeathEventHandler;
                     isSubscribeActionTaken = true;
                 }
                 else if (!isSubscribed) {
                     mortalFsmTgt.deathOneShot += FsmTgtDeathEventHandler;
                     isSubscribeActionTaken = true;
                 }
                 else {
                     isDuplicateSubscriptionAttempted = true;
                 }
             }
             break;
         case FsmTgtEventSubscriptionMode.InfoAccessChg:
             itemFsmTgt = fsmTgt as IItem_Ltd;
             if (itemFsmTgt != null) {    // fsmTgt can be a StationaryLocation
                 if (!toSubscribe) {
                     itemFsmTgt.infoAccessChgd -= FsmTgtInfoAccessChgdEventHandler;
                     isSubscribeActionTaken = true;
                 }
                 else if (!isSubscribed) {
                     itemFsmTgt.infoAccessChgd += FsmTgtInfoAccessChgdEventHandler;
                     isSubscribeActionTaken = true;
                 }
                 else {
                     isDuplicateSubscriptionAttempted = true;
                 }
             }
             break;
         case FsmTgtEventSubscriptionMode.OwnerChg:
             itemFsmTgt = fsmTgt as IItem_Ltd;
             if (itemFsmTgt != null) {    // fsmTgt can be a StationaryLocation
                 if (!toSubscribe) {
                     itemFsmTgt.ownerChanged -= FsmTgtOwnerChgdEventHandler;
                     isSubscribeActionTaken = true;
                 }
                 else if (!isSubscribed) {
                     itemFsmTgt.ownerChanged += FsmTgtOwnerChgdEventHandler;
                     isSubscribeActionTaken = true;
                 }
                 else {
                     isDuplicateSubscriptionAttempted = true;
                 }
             }
             break;
         case FsmTgtEventSubscriptionMode.None:
         default:
             throw new NotImplementedException(ErrorMessages.UnanticipatedSwitchValue.Inject(subscriptionMode));
     }
     if (isDuplicateSubscriptionAttempted) {
         D.Warn("{0}: Attempting to subscribe to {1}'s {2} when already subscribed.", DebugName, fsmTgt.DebugName, subscriptionMode.GetValueName());
     }
     if (isSubscribeActionTaken) {
         __subscriptionStatusLookup[subscriptionMode] = toSubscribe;
     }
     return isSubscribeActionTaken;
 }
Exemplo n.º 17
0
    void ExecuteExploreOrder_UponPreconfigureState() {
        LogEvent();

        if (_fsmTgt != null) {
            D.Error("{0} _fsmTgt {1} should not already be assigned.", DebugName, _fsmTgt.DebugName);
        }
        D.AssertDefault((int)_orderFailureCause, _orderFailureCause.GetValueName());
        D.Assert(CurrentOrder.ToNotifyCmd);

        var exploreTgt = CurrentOrder.Target as IShipExplorable;
        D.Assert(exploreTgt != null);   // individual ships only explore Planets, Stars and UCenter
        D.Assert(exploreTgt.IsExploringAllowedBy(Owner));
        D.Assert(!exploreTgt.IsFullyExploredBy(Owner));
        D.Assert(exploreTgt.IsCloseOrbitAllowedBy(Owner));

        _fsmTgt = exploreTgt;

        __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.TargetDeath, _fsmTgt, toSubscribe: true);
        bool isSubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.InfoAccessChg, _fsmTgt, toSubscribe: true);
        D.Assert(isSubscribed);
        isSubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.OwnerChg, _fsmTgt, toSubscribe: true);
        D.Assert(isSubscribed);
    }
Exemplo n.º 18
0
 void ExecuteAttackOrder_UponOrderOutcome(ShipDirective directive, ShipItem ship, bool isSuccess, IShipNavigable target, UnitItemOrderFailureCause failCause) {
     LogEvent();
     if (directive != ShipDirective.Attack) {
         D.Warn("{0} State {1} erroneously received OrderOutcome callback with {2} {3}.", DebugName, CurrentState.GetValueName(), typeof(ShipDirective).Name, directive.GetValueName());
         return;
     }
     // TODO keep track of results to make better resulting decisions about what to do as battle rages
     // IShipAttackable attackedTgt = target as IShipAttackable;    // target can be null if ship failed and didn't have a target: Disengaged...
 }
Exemplo n.º 19
0
    /// <summary>
    /// Assesses whether this ship should attempt to assume close orbit around the provided target.
    /// </summary>
    /// <param name="target">The target to assess close orbiting.</param>
    /// <returns>
    ///   <c>true</c> if the ship should initiate assuming close orbit.
    /// </returns>
    private bool AssessWhetherToAssumeCloseOrbitAround(IShipNavigable target) {
        Utility.ValidateNotNull(target);
        D.Assert(!IsInCloseOrbit);
        D.Assert(!_helm.IsPilotEngaged);
        var closeOrbitableTarget = target as IShipCloseOrbitable;
        if (closeOrbitableTarget != null) {
            if (!(closeOrbitableTarget is StarItem) && !(closeOrbitableTarget is SystemItem) && !(closeOrbitableTarget is UniverseCenterItem)) {
                // filter out objectToOrbit items that generate unnecessary knowledge check warnings    // OPTIMIZE
                D.Assert(OwnerAIMgr.HasKnowledgeOf(closeOrbitableTarget as IItem_Ltd));  // ship very close so should know. UNCLEAR Dead sensors?, sensors w/FleetCmd
            }

            if (closeOrbitableTarget.IsCloseOrbitAllowedBy(Owner)) {
                return true;
            }
        }
        return false;
    }
Exemplo n.º 20
0
 private void UponOrderOutcome(ShipDirective directive, ShipItem ship, bool isSuccess, IShipNavigable target = null, UnitItemOrderFailureCause failCause = UnitItemOrderFailureCause.None) {
     RelayToCurrentState(directive, ship, isSuccess, target, failCause);
 }
Exemplo n.º 21
0
 private void __ValidateKnowledgeOfOrderTarget(IShipNavigable target, ShipDirective directive) {
     if (directive == ShipDirective.Retreat || directive == ShipDirective.Disband || directive == ShipDirective.Refit
         || directive == ShipDirective.StopAttack) {
         // directives aren't yet implemented
         return;
     }
     if (target is StarItem || target is SystemItem || target is UniverseCenterItem) {
         // unnecessary check as all players have knowledge of these targets
         return;
     }
     if (directive == ShipDirective.AssumeStation || directive == ShipDirective.Scuttle
         || directive == ShipDirective.Repair || directive == ShipDirective.Entrench || directive == ShipDirective.Disengage) {
         D.AssertNull(target);
         return;
     }
     if (directive == ShipDirective.Move) {
         if (target is StationaryLocation || target is MobileLocation) {
             return;
         }
         if (target is ISector) {
             return; // IMPROVE currently PlayerKnowledge does not keep track of Sectors
         }
     }
     if (!OwnerAIMgr.HasKnowledgeOf(target as IItem_Ltd)) {
         D.Error("{0} received {1} order with Target {2} that {3} has no knowledge of.", DebugName, directive.GetValueName(), target.DebugName, Owner.LeaderName);
     }
 }
Exemplo n.º 22
0
    void ExecuteExploreOrder_UponOrderOutcome(ShipDirective directive, ShipItem ship, bool isSuccess, IShipNavigable target,
        UnitItemOrderFailureCause failCause) {
        LogEvent();
        if (directive != ShipDirective.Explore) {
            D.Warn("{0} State {1} erroneously received OrderOutcome callback with {2} {3}.", DebugName, CurrentState.GetValueName(), typeof(ShipDirective).Name, directive.GetValueName());
            return;
        }

        IShipExplorable shipExploreTgt = target as IShipExplorable;
        D.AssertNotNull(shipExploreTgt);

        bool issueFleetRecall = false;
        if (IsShipExploreTargetPartOfSystem(shipExploreTgt)) {
            // exploreTgt is a planet or star
            D.Assert(_shipSystemExploreTgtAssignments.ContainsKey(shipExploreTgt));
            if (isSuccess) {
                HandleSystemTargetExploredOrDead(ship, shipExploreTgt);
            }
            else {
                bool isNewShipAssigned;
                bool testForAdditionalExploringShips = false;
                switch (failCause) {
                    case UnitItemOrderFailureCause.TgtRelationship:
                        // exploration failed so recall all ships
                        issueFleetRecall = true;
                        break;
                    case UnitItemOrderFailureCause.TgtDeath:
                        HandleSystemTargetExploredOrDead(ship, shipExploreTgt);
                        // This is effectively counted as a success and will show up during the _EnterState's
                        // continuous test System.IsFullyExplored. As not really a failure, no reason to issue a fleet recall.
                        break;
                    case UnitItemOrderFailureCause.UnitItemNeedsRepair:
                        isNewShipAssigned = HandleShipNoLongerAvailableToExplore(ship, shipExploreTgt);
                        if (!isNewShipAssigned) {
                            if (Elements.Count > 1) {
                                // This is not the last ship in the fleet, but the others aren't available. Since it usually takes 
                                // more than one ship to explore a System, the other ships might currently be exploring
                                testForAdditionalExploringShips = true;
                            }
                            else {
                                D.AssertEqual(Constants.One, Elements.Count);
                                // Damaged ship is only one left in fleet and it can't explore so exploration failed
                                issueFleetRecall = true;
                            }
                        }
                        break;
                    case UnitItemOrderFailureCause.UnitItemDeath:
                        isNewShipAssigned = HandleShipNoLongerAvailableToExplore(ship, shipExploreTgt);
                        if (!isNewShipAssigned) {
                            if (Elements.Count > 1) {    // >1 as dead ship has not yet been removed from fleet
                                                         // This is not the last ship in the fleet, but the others aren't available. Since it usually takes 
                                                         // more than one ship to explore a System, the other ships might currently be exploring
                                testForAdditionalExploringShips = true;
                            }
                            else {
                                D.AssertEqual(Constants.One, Elements.Count);  // dead ship has not yet been removed from fleet
                                // Do nothing as Unit is about to die
                            }
                        }
                        break;
                    case UnitItemOrderFailureCause.TgtUncatchable:
                    case UnitItemOrderFailureCause.TgtUnreachable:
                    case UnitItemOrderFailureCause.None:
                    default:
                        throw new NotImplementedException(ErrorMessages.UnanticipatedSwitchValue.Inject(failCause));
                }

                if (testForAdditionalExploringShips) {
                    var otherShipsCurrentlyExploring = Elements.Cast<ShipItem>().Except(ship).Where(s => s.IsCurrentOrderDirectiveAnyOf(ShipDirective.Explore));
                    if (otherShipsCurrentlyExploring.Any()) {
                        // Do nothing as there are other ships currently exploring so exploreTarget will eventually be assigned a ship
                    }
                    else {
                        // There are no remaining ships out exploring -> the exploration attempt has failed so issue recall
                        issueFleetRecall = true;
                    }
                }
            }
        }
        else {
            // exploreTgt is UCenter
            D.Assert(shipExploreTgt is UniverseCenterItem);
            if (isSuccess) {
                // exploration of UCenter has successfully completed so issue fleet recall
                issueFleetRecall = true;
            }
            else {
                bool isNewShipAssigned;
                switch (failCause) {
                    case UnitItemOrderFailureCause.UnitItemNeedsRepair:
                        isNewShipAssigned = HandleShipNoLongerAvailableToExplore(ship, shipExploreTgt);
                        if (!isNewShipAssigned) {
                            // No more ships are available to finish UCenter explore. Since it only takes one ship
                            // to explore UCenter, the other ships, if any, can't currently be exploring, so no reason to wait for them
                            // to complete their exploration. -> the exploration attempt has failed so issue recall
                            issueFleetRecall = true;
                        }
                        break;
                    case UnitItemOrderFailureCause.UnitItemDeath:
                        isNewShipAssigned = HandleShipNoLongerAvailableToExplore(ship, shipExploreTgt);
                        if (!isNewShipAssigned) {
                            if (Elements.Count > 1) {    // >1 as dead ship has not yet been removed from fleet
                                                         // This is not the last ship in the fleet, but the others aren't available. Since it only takes one ship
                                                         // to explore UCenter, the other ships can't currently be exploring, so no reason to wait for them
                                                         // to complete their exploration. -> the exploration attempt has failed so issue recall
                                issueFleetRecall = true;
                            }
                            else {
                                D.AssertEqual(Constants.One, Elements.Count);  // dead ship has not yet been removed from fleet
                                // Do nothing as Unit is about to die
                            }
                        }
                        break;
                    case UnitItemOrderFailureCause.TgtDeath:
                    case UnitItemOrderFailureCause.TgtRelationship:
                    case UnitItemOrderFailureCause.TgtUncatchable:
                    case UnitItemOrderFailureCause.TgtUnreachable:
                    case UnitItemOrderFailureCause.None:
                    default:
                        throw new NotImplementedException(ErrorMessages.UnanticipatedSwitchValue.Inject(failCause));
                }
            }
        }
        if (issueFleetRecall) {
            IFleetExplorable fleetExploreTgt = CurrentOrder.Target as IFleetExplorable;
            var closestLocalAssyStation = GameUtility.GetClosest(Position, fleetExploreTgt.LocalAssemblyStations);
            CurrentOrder = new FleetOrder(FleetDirective.AssumeFormation, OrderSource.CmdStaff, closestLocalAssyStation);
        }
    }