Esempio n. 1
0
 protected override void Add(IMortalTarget target) {
     base.Add(target);
     D.Assert(Owner != null);
     if (Owner.IsEnemyOf(target.Owner) && !target.IsAlive && !EnemyTargets.Contains(target)) {
         AddEnemyTarget(target);
     }
 }
Esempio n. 2
0
 private void AddEnemyTarget(IMortalTarget enemyTarget) {
     D.Log("{0}.{1}({2:0.00}) added Enemy {3} at distance {4}.",
          ParentFullName, _transform.name, Range, enemyTarget.FullName, Vector3.Distance(_transform.position, enemyTarget.Position));
     if (EnemyTargets.Count == 0) {
         OnEnemyInRange(true);   // there are now enemies in range
     }
     EnemyTargets.Add(enemyTarget);
 }
Esempio n. 3
0
 /// <summary>
 /// Plots a course to a Planetoid target and notifies the requester of the
 /// outcome via the onCoursePlotSuccess or Failure events.
 /// </summary>
 /// <param name="planetoid">The planetoid.</param>
 /// <param name="speed">The speed.</param>
 /// <param name="standoffDistance">The distance to standoff from the target. This is added to the radius of the target to
 /// determine how close the ship is allowed to approach the target.</param>
 /// <param name="isFleetMove">>if set to <c>true</c> this navigator will only move when the fleet is ready.</param>
 private void PlotCourse(IMortalTarget planetoid, Speed speed, float standoffDistance, bool isFleetMove) {
     // a formationOffset is required if this is a fleet move
     Vector3 destinationOffset = isFleetMove ? _data.FormationStation.StationOffset : Vector3.zero;
     _targetInfo = new TargetInfo(planetoid, destinationOffset, standoffDistance);
     Speed = speed;
     _isFleetMove = isFleetMove;
     InitializeTargetValues();
     //PlotCourse();
 }
Esempio n. 4
0
 /// <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>
 private void OverrideCurrentOrder(FacilityDirective order, bool retainSuperiorsOrder, IMortalTarget target = null) {
     // if the captain says to, and the current existing order is from his superior, then record it as a standing order
     FacilityOrder 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;
         }
         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;
         }
     }
     FacilityOrder newOrder = new FacilityOrder(order, OrderSource.ElementCaptain, target) {
         StandingOrder = standingOrder
     };
     CurrentOrder = newOrder;
 }
Esempio n. 5
0
 void ExecuteAttackOrder_ExitState() {
     LogEvent();
     _ordersTarget = null;
     _primaryTarget = null;
     _isDestinationUnreachable = false;
 }
Esempio n. 6
0
 protected override void Remove(IMortalTarget target) {
     base.Remove(target);
     RemoveEnemyTarget(target);
 }
Esempio n. 7
0
 void Attacking_ExitState() {
     LogEvent();
     _attackTarget.onTargetDeathOneShot -= OnTargetDeath;
     _attackTarget = null;
 }
Esempio n. 8
0
 void Attacking_EnterState() {
     LogEvent();
     _attackTarget = CurrentOrder.Target as IMortalTarget;
     _attackTarget.onTargetDeathOneShot += OnTargetDeath;
     var elementAttackOrder = new FacilityOrder(FacilityDirective.Attack, OrderSource.UnitCommand, _attackTarget);
     Elements.ForAll(e => (e as FacilityModel).CurrentOrder = elementAttackOrder);
 }
Esempio n. 9
0
 void Attacking_EnterState() {
     LogEvent();
     _attackTarget = CurrentOrder.Target as IMortalTarget;
     _attackTarget.onTargetDeathOneShot += OnTargetDeath;
     var shipAttackOrder = new ShipOrder(ShipDirective.Attack, OrderSource.UnitCommand, _attackTarget);
     Elements.ForAll(e => (e as ShipModel).CurrentOrder = shipAttackOrder);
 }
Esempio n. 10
0
 public TargetInfo(IMortalTarget planetoid, Vector3 fstOffset, float standoffDistance) {
     Target = planetoid;
     Destination = planetoid.Position + fstOffset;
     CloseEnoughDistance = planetoid.Radius + standoffDistance;
     CloseEnoughDistanceSqrd = CloseEnoughDistance * CloseEnoughDistance;
 }
Esempio n. 11
0
 protected virtual void Remove(IMortalTarget target) {
     bool isRemoved = AllTargets.Remove(target);
     if (isRemoved) {
         //D.Log("{0}.{1} no longer tracking target {2} at distance = {3}.", ParentFullName, _transform.name, target.FullName, Vector3.Distance(target.Position, _transform.position));
         target.onTargetDeathOneShot -= OnTargetDeath;
         target.onOwnerChanged -= OnTargetOwnerChanged;
     }
     else {
         D.Warn("{0}.{1} target {2} not present to be removed.", ParentFullName, _transform.name, target.FullName);
     }
 }
Esempio n. 12
0
 protected virtual void Add(IMortalTarget target) {
     if (!AllTargets.Contains(target)) {
         if (!target.IsAlive) {
             //D.Log("{0}.{1} now tracking target {2}.", ParentFullName, _transform.name, target.FullName);
             target.onTargetDeathOneShot += OnTargetDeath;
             target.onOwnerChanged += OnTargetOwnerChanged;
             AllTargets.Add(target);
         }
         else {
             D.Log("{0}.{1} avoided adding target {2} that is already dead but not yet destroyed.", ParentFullName, _transform.name, target.FullName);
         }
     }
     else {
         D.Warn("{0}.{1} attempted to add duplicate Target {2}.", ParentFullName, _transform.name, target.FullName);
     }
 }
Esempio n. 13
0
 void OnTargetDeath(IMortalTarget deadTarget) { RelayToCurrentState(deadTarget); }
Esempio n. 14
0
    /// <summary>
    /// Picks the highest priority target from orders. First selection criteria is inRange.
    /// </summary>
    /// <param name="chosenTarget">The chosen target from orders or null if no targets remain alive.</param>
    /// <returns> <c>true</c> if the target is in range, <c>false</c> otherwise.</returns>
    private bool PickPrimaryTarget(out IMortalTarget chosenTarget) {
        D.Assert(_ordersTarget != null && _ordersTarget.IsAlive, "{0}'s target from orders is null or dead.".Inject(Data.FullName));
        bool isTargetInRange = false;
        var uniqueEnemyTargetsInRange = Enumerable.Empty<IMortalTarget>();
        foreach (var rangeMonitor in _weaponRangeMonitorLookup.Values) {
            uniqueEnemyTargetsInRange = uniqueEnemyTargetsInRange.Union<IMortalTarget>(rangeMonitor.EnemyTargets);  // OPTIMIZE
        }

        ICmdTarget cmdTarget = _ordersTarget as ICmdTarget;
        if (cmdTarget != null) {
            var primaryTargets = cmdTarget.UnitElementTargets.Cast<IMortalTarget>();
            var primaryTargetsInRange = primaryTargets.Intersect(uniqueEnemyTargetsInRange);
            if (!primaryTargetsInRange.IsNullOrEmpty()) {
                chosenTarget = __SelectHighestPriorityTarget(primaryTargetsInRange);
                isTargetInRange = true;
            }
            else {
                D.Assert(!primaryTargets.IsNullOrEmpty(), "{0}'s primaryTargets cannot be empty when _ordersTarget is alive.");
                chosenTarget = __SelectHighestPriorityTarget(primaryTargets);
            }
        }
        else {            // Planetoid
            D.Assert(_ordersTarget is APlanetoidModel);
            if (!uniqueEnemyTargetsInRange.Contains(_ordersTarget)) {
                if (_weaponRangeMonitorLookup.Values.Any(rangeTracker => rangeTracker.AllTargets.Contains(_ordersTarget))) {
                    // the planetoid is not an enemy, but it is in range and therefore fair game
                    isTargetInRange = true;
                }
            }
            else {
                // the planetoid is an enemy and in range
                isTargetInRange = true;
            }
            chosenTarget = _ordersTarget;
        }
        if (chosenTarget != null) {
            // no need for knowing about death event as primaryTarget is continuously checked while under orders to attack
            //D.Log("{0}'s has selected {1} as it's primary target. InRange = {2}.", Data.Name, chosenTarget.Name, isTargetInRange);
        }
        else {
            D.Warn("{0}'s primary target returned as null. InRange = {1}.", Data.Name, isTargetInRange);
        }
        return isTargetInRange;
    }
Esempio n. 15
0
 void Attacking_OnTargetDeath(IMortalTarget deadTarget) {
     // this can occur as a result of TakeHit but since we currently Return() right after TakeHit we shouldn't double up
 }
Esempio n. 16
0
 public TargetInfo(IMortalTarget planetoid, Vector3 fstOffset, float standoffDistance) {
     Target = planetoid;
     //Destination = planetoid.Position + fstOffset;
     _fstOffset = fstOffset;
     CloseEnoughDistance = planetoid.Radius + standoffDistance;      //TODO should account for keepoutRadius
     CloseEnoughDistanceSqrd = CloseEnoughDistance * CloseEnoughDistance;
 }
Esempio n. 17
0
 protected void OnTargetDeath(IMortalTarget deadTarget) {
     //LogEvent();
     RelayToCurrentState(deadTarget);
 }
Esempio n. 18
0
 void Moving_OnTargetDeath(IMortalTarget deadTarget) {
     LogEvent();
     D.Assert(_moveTarget == deadTarget, "{0}.target {1} is not dead target {2}.".Inject(Data.Name, _moveTarget.FullName, deadTarget.FullName));
     Return();
 }
Esempio n. 19
0
 void Attacking_OnTargetDeath(IMortalTarget deadTarget) {
     LogEvent();
     D.Assert(_attackTarget == deadTarget, "{0}.target {1} is not dead target {2}.".Inject(FullName, _attackTarget.FullName, deadTarget.FullName));
     Return();
 }
Esempio n. 20
0
    private IMortalTarget _primaryTarget; // IMPROVE  take this previous target into account when PickPrimaryTarget()

    IEnumerator ExecuteAttackOrder_EnterState() {
        D.Log("{0}.ExecuteAttackOrder_EnterState() called.", FullName);
        _ordersTarget = CurrentOrder.Target;

        while (_ordersTarget.IsAlive) {
            // bool inRange = PickPrimaryTarget(out _primaryTarget);
            // if a primaryTarget is inRange, primary target is not null so OnWeaponReady will attack it
            // if not in range, then primary target will be null, so OnWeaponReady will attack other targets of opportunity, if any
            yield return null;
        }
        CurrentState = FacilityState.Idling;
    }
Esempio n. 21
0
 public bool __TryGetRandomEnemyTarget(out IMortalTarget enemyTarget) {
     bool result = false;
     enemyTarget = null;
     if (EnemyTargets.Count > 0) {
         result = true;
         enemyTarget = RandomExtended<IMortalTarget>.Choice(EnemyTargets);
     }
     return result;
 }
Esempio n. 22
0
 void ExecuteAttackOrder_ExitState() {
     LogEvent();
     _primaryTarget = null;
     _ordersTarget = null;
 }
Esempio n. 23
0
 void Attacking_ExitState() {
     LogEvent();
     _attackTarget = null;
     _attackStrength = TempGameValues.NoCombatStrength;
 }
Esempio n. 24
0
    /// <summary>
    /// Picks the highest priority target from orders. First selection criteria is inRange.
    /// </summary>
    /// <param name="chosenTarget">The chosen target from orders or null if no targets remain.</param>
    /// <returns> <c>true</c>if the target is in range, <c>false</c> otherwise. 
    /// </returns>
    private bool PickPrimaryTarget(out IMortalTarget chosenTarget) {
        D.Assert(_ordersTarget != null && _ordersTarget.IsAlive, "{0}'s target from orders is null or dead.".Inject(FullName));
        bool isTargetInRange = false;
        var uniqueEnemyTargetsInRange = Enumerable.Empty<IMortalTarget>();
        foreach (var rMonitor in _weaponRangeMonitorLookup.Values) {
            uniqueEnemyTargetsInRange = uniqueEnemyTargetsInRange.Union<IMortalTarget>(rMonitor.EnemyTargets);  // OPTIMIZE
        }

        ICmdTarget cmdTarget = _ordersTarget as ICmdTarget;
        if (cmdTarget != null) {
            var primaryTargets = cmdTarget.UnitElementTargets.Cast<IMortalTarget>();
            var primaryTargetsInRange = primaryTargets.Intersect(uniqueEnemyTargetsInRange);
            if (!primaryTargetsInRange.IsNullOrEmpty()) {
                chosenTarget = SelectHighestPriorityTarget(primaryTargetsInRange);
                isTargetInRange = true;
            }
            else {
                D.Assert(!primaryTargets.IsNullOrEmpty(), "{0}'s primaryTargets cannot be empty when _ordersTarget is alive.".Inject(FullName));
                chosenTarget = null;    // no target as all are out of range
            }
        }
        else {
            chosenTarget = _ordersTarget;   // Planetoid
            isTargetInRange = uniqueEnemyTargetsInRange.Contains(_ordersTarget);
        }
        if (chosenTarget != null) {
            // no need for knowing about death event as primaryTarget is continuously checked while under orders to attack
            D.Log("{0}'s has selected {1} as it's primary target. InRange = {2}.", FullName, chosenTarget.FullName, isTargetInRange);
        }
        return isTargetInRange;
    }
Esempio n. 25
0
 private void RemoveEnemyTarget(IMortalTarget enemyTarget) {
     if (EnemyTargets.Remove(enemyTarget)) {
         if (EnemyTargets.Count == 0) {
             OnEnemyInRange(false);  // no longer any Enemies in range
         }
         D.Log("{0}.{1}({2:0.00}) removed Enemy Target {3} at distance {4}.",
             ParentFullName, _transform.name, Range, enemyTarget.FullName, Vector3.Distance(_transform.position, enemyTarget.Position));
     }
 }
Esempio n. 26
0
    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;
    }