Beispiel #1
0
        public override Activity Tick(Actor self)
        {
            // Refuse to take off if it would land immediately again.
            if (aircraft.ForceLanding)
            {
                Cancel(self);
                return(NextActivity);
            }

            if (!target.IsValidFor(self))
            {
                return(NextActivity);
            }

            // If all valid weapons have depleted their ammo and Rearmable trait exists, return to RearmActor to reload and then resume the activity
            if (rearmable != null && attackAircraft.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
            {
                return(ActivityUtils.SequenceActivities(new ReturnToBase(self, aircraft.Info.AbortOnResupply), this));
            }

            attackAircraft.DoAttack(self, target);

            if (ChildActivity == null)
            {
                if (IsCanceled)
                {
                    return(NextActivity);
                }

                // TODO: This should fire each weapon at its maximum range
                if (attackAircraft != null && target.IsInRange(self.CenterPosition, attackAircraft.Armaments.Where(Exts.IsTraitEnabled).Select(a => a.Weapon.MinRange).Min()))
                {
                    ChildActivity = ActivityUtils.SequenceActivities(new FlyTimed(ticksUntilTurn, self), new Fly(self, target), new FlyTimed(ticksUntilTurn, self));
                }
                else
                {
                    ChildActivity = ActivityUtils.SequenceActivities(new Fly(self, target), new FlyTimed(ticksUntilTurn, self));
                }

                // HACK: This needs to be done in this round-about way because TakeOff doesn't behave as expected when it doesn't have a NextActivity.
                if (self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length < aircraft.Info.MinAirborneAltitude)
                {
                    ChildActivity = ActivityUtils.SequenceActivities(new TakeOff(self), ChildActivity);
                }
            }

            ActivityUtils.RunActivity(self, ChildActivity);

            return(this);
        }
Beispiel #2
0
        public override Activity Tick(Actor self)
        {
            // Refuse to take off if it would land immediately again.
            if (aircraft.ForceLanding)
            {
                Cancel(self);
                return(NextActivity);
            }

            if (IsCanceled || !target.IsValidFor(self))
            {
                return(NextActivity);
            }

            var pos       = self.CenterPosition;
            var targetPos = attackAircraft.GetTargetPosition(pos, target);

            if (attackOnlyVisibleTargets && target.Type == TargetType.Actor && canHideUnderFog &&
                !target.Actor.CanBeViewedByPlayer(self.Owner))
            {
                var newTarget = Target.FromCell(self.World, self.World.Map.CellContaining(targetPos));

                Cancel(self);
                self.SetTargetLine(newTarget, Color.Green);
                return(new HeliFly(self, newTarget));
            }

            // If all valid weapons have depleted their ammo and Rearmable trait exists, return to RearmActor to reload and then resume the activity
            if (rearmable != null && attackAircraft.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
            {
                return(ActivityUtils.SequenceActivities(new HeliReturnToBase(self, aircraft.Info.AbortOnResupply), this));
            }

            var dist = targetPos - pos;

            // Can rotate facing while ascending
            var desiredFacing = dist.HorizontalLengthSquared != 0 ? dist.Yaw.Facing : aircraft.Facing;

            aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.TurnSpeed);

            if (HeliFly.AdjustAltitude(self, aircraft, aircraft.Info.CruiseAltitude))
            {
                return(this);
            }

            // Fly towards the target
            if (!target.IsInRange(pos, attackAircraft.GetMaximumRangeVersusTarget(target)))
            {
                aircraft.SetPosition(self, aircraft.CenterPosition + aircraft.FlyStep(desiredFacing));
            }

            // Fly backwards from the target
            if (target.IsInRange(pos, attackAircraft.GetMinimumRangeVersusTarget(target)))
            {
                // Facing 0 doesn't work with the following position change
                var facing = 1;
                if (desiredFacing != 0)
                {
                    facing = desiredFacing;
                }
                else if (aircraft.Facing != 0)
                {
                    facing = aircraft.Facing;
                }
                aircraft.SetPosition(self, aircraft.CenterPosition + aircraft.FlyStep(-facing));
            }

            attackAircraft.DoAttack(self, target);

            return(this);
        }