/// <summary> /// Initializes a new instance of the <see cref="FacilityOrder" /> 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 facility will notify its Cmd of the outcome.</param> /// <param name="target">The target of this order. Default is null.</param> public FacilityOrder(FacilityDirective directive, OrderSource source, bool toNotifyCmd = false, IUnitAttackable target = null) { if (directive.EqualsAnyOf(DirectivesWithNullTarget)) { D.AssertNull(target, ToString()); } Directive = directive; Source = source; ToNotifyCmd = toNotifyCmd; Target = target; }
/// <summary> /// Initializes a new instance of the <see cref="BaseOrder" /> class. /// </summary> /// <param name="directive">The order directive.</param> /// <param name="source">The source of this order.</param> /// <param name="target">The target of this order. Default is null.</param> public BaseOrder(BaseDirective directive, OrderSource source, IUnitAttackable target = null) { D.AssertNotEqual(OrderSource.Captain, source); Directive = directive; Source = source; Target = target; }
private void __ValidateKnowledgeOfOrderTarget(IUnitAttackable target, FacilityDirective directive) { if (directive == FacilityDirective.Disband || directive == FacilityDirective.Refit || directive == FacilityDirective.StopAttack) { // directives aren't yet implemented return; } if (directive == FacilityDirective.Scuttle || directive == FacilityDirective.Repair) { D.AssertNull(target); return; } 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); } }
protected void ExecuteAttackOrder_ExitState() { LogEvent(); bool isUnsubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.TargetDeath, _fsmTgt, toSubscribe: false); D.Assert(isUnsubscribed); isUnsubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.InfoAccessChg, _fsmTgt, toSubscribe: false); D.Assert(isUnsubscribed); isUnsubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.OwnerChg, _fsmTgt, toSubscribe: false); D.Assert(isUnsubscribed); _orderFailureCause = UnitItemOrderFailureCause.None; _fsmTgt = null; }
private IUnitAttackable _fsmTgt; // UNCLEAR is there an _fsmTgt for other states? protected void ExecuteAttackOrder_UponPreconfigureState() { LogEvent(); if (_fsmTgt != null) { D.Error("{0} _fsmMoveTgt {1} should not already be assigned.", DebugName, _fsmTgt.DebugName); } D.AssertDefault((int)_orderFailureCause, _orderFailureCause.GetValueName()); IUnitAttackable attackTgt = CurrentOrder.Target; _fsmTgt = attackTgt; bool isSubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.TargetDeath, _fsmTgt, toSubscribe: true); D.Assert(isSubscribed); isSubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.InfoAccessChg, _fsmTgt, toSubscribe: true); D.Assert(isSubscribed); isSubscribed = __AttemptFsmTgtSubscriptionChg(FsmTgtEventSubscriptionMode.OwnerChg, _fsmTgt, toSubscribe: true); D.Assert(isSubscribed); }
// 4.22.16: Currently Order is issued only by user or fleet. Once HQ has arrived at the IUnitAttackable target, // individual ships can still be a long way off trying to get there. In addition, the element a ship picks as its // primary target could also be a long way off so we need to rely on the AutoPilot to manage speed. #region ExecuteAttackOrder Support Members /// <summary> /// Tries to pick a primary target for the ship derived from the provided UnitTarget. Returns <c>true</c> if an acceptable /// target belonging to unitAttackTgt is found within SensorRange and the ship decides to attack, <c>false</c> otherwise. /// A ship can decide not to attack even if it finds an acceptable target - e.g. it has no currently operational weapons. /// </summary> /// <param name="unitAttackTgt">The unit target to Attack.</param> /// <param name="allowLogging">if set to <c>true</c> [allow logging].</param> /// <param name="shipPrimaryAttackTgt">The ship's primary attack target. Will be null when returning false.</param> /// <returns></returns> private bool TryPickPrimaryAttackTgt(IUnitAttackable unitAttackTgt, bool allowLogging, out IShipAttackable shipPrimaryAttackTgt) { D.AssertNotNull(unitAttackTgt); if (!unitAttackTgt.IsOperational) { D.Error("{0}'s unit attack target {1} is dead.", DebugName, unitAttackTgt.DebugName); } D.AssertNotEqual(ShipCombatStance.Defensive, Data.CombatStance); D.AssertNotEqual(ShipCombatStance.Disengage, Data.CombatStance); if (Data.WeaponsRange.Max == Constants.ZeroF) { if (ShowDebugLog && allowLogging) { D.Log("{0} is declining to engage with target {1} as it has no operational weapons.", DebugName, unitAttackTgt.DebugName); } shipPrimaryAttackTgt = null; return false; } var uniqueEnemyTargetsInSensorRange = Enumerable.Empty<IShipAttackable>(); Command.SensorRangeMonitors.ForAll(srm => { var attackableEnemyTgtsDetected = srm.EnemyTargetsDetected.Cast<IShipAttackable>(); uniqueEnemyTargetsInSensorRange = uniqueEnemyTargetsInSensorRange.Union(attackableEnemyTgtsDetected); }); IShipAttackable primaryTgt = null; var cmdTarget = unitAttackTgt as AUnitCmdItem; if (cmdTarget != null) { var primaryTargets = cmdTarget.Elements.Cast<IShipAttackable>(); var primaryTargetsInSensorRange = primaryTargets.Intersect(uniqueEnemyTargetsInSensorRange); if (primaryTargetsInSensorRange.Any()) { primaryTgt = __SelectHighestPriorityAttackTgt(primaryTargetsInSensorRange); } } else { // Planetoid var planetoidTarget = unitAttackTgt as APlanetoidItem; D.AssertNotNull(planetoidTarget); if (uniqueEnemyTargetsInSensorRange.Contains(planetoidTarget)) { primaryTgt = planetoidTarget; } } if (primaryTgt == null) { if (allowLogging) { D.Warn("{0} found no target within sensor range to attack!", DebugName); // UNCLEAR how this could happen. Sensors damaged? } shipPrimaryAttackTgt = null; return false; } shipPrimaryAttackTgt = primaryTgt; return true; }