Example #1
0
        public override Activity Tick(Actor self)
        {
            if (IsCanceled)
            {
                return(NextActivity);
            }

            if (dest == null || dest.IsDead || Reservable.IsReserved(dest))
            {
                dest = ChooseHelipad(self, true);
            }

            var initialFacing = heli.Info.InitialFacing;

            if (dest == null || dest.IsDead)
            {
                var nearestHpad = ChooseHelipad(self, false);

                if (nearestHpad == null)
                {
                    return(ActivityUtils.SequenceActivities(new Turn(self, initialFacing), new HeliLand(self, true), NextActivity));
                }
                else
                {
                    var distanceFromHelipad = (nearestHpad.CenterPosition - self.CenterPosition).HorizontalLength;
                    var distanceLength      = heli.Info.WaitDistanceFromResupplyBase.Length;

                    // If no pad is available, move near one and wait
                    if (distanceFromHelipad > distanceLength)
                    {
                        var randomPosition = WVec.FromPDF(self.World.SharedRandom, 2) * distanceLength / 1024;

                        var target = Target.FromPos(nearestHpad.CenterPosition + randomPosition);

                        return(ActivityUtils.SequenceActivities(new HeliFly(self, target, WDist.Zero, heli.Info.WaitDistanceFromResupplyBase), this));
                    }

                    return(this);
                }
            }

            var exit   = dest.Info.TraitInfos <ExitInfo>().FirstOrDefault();
            var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero;

            if (ShouldLandAtBuilding(self, dest))
            {
                heli.MakeReservation(dest);

                return(ActivityUtils.SequenceActivities(
                           new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)),
                           new Turn(self, initialFacing),
                           new HeliLand(self, false),
                           new ResupplyAircraft(self),
                           !abortOnResupply ? NextActivity : null));
            }

            return(ActivityUtils.SequenceActivities(
                       new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)),
                       NextActivity));
        }
Example #2
0
        public void ResolveOrder(Actor self, Order order)
        {
            if (order.OrderString == "Repair")
            {
                // Repair orders are only valid for own/allied actors,
                // which are guaranteed to never be frozen.
                if (order.Target.Type != TargetType.Actor)
                {
                    return;
                }

                if (!CanRepairAt(order.Target.Actor) || (!CanRepair() && !CanRearm()))
                {
                    return;
                }

                if (!order.Queued)
                {
                    self.CancelActivity();
                }

                self.SetTargetLine(order.Target, Color.Green);
                self.QueueActivity(new WaitForTransport(self, ActivityUtils.SequenceActivities(new MoveAdjacentTo(self, order.Target),
                                                                                               new CallFunc(() => AfterReachActivities(self, order, movement)))));

                TryCallTransport(self, order.Target, new CallFunc(() => AfterReachActivities(self, order, movement)));
            }
        }
Example #3
0
        public override Activity Tick(Actor self)
        {
            if (move == null || refuels == null || fueltank == null)
            {
                return(NextActivity);
            }

            self.SetTargetLine(target, Color.Green);

            var act = ActivityUtils.SequenceActivities(
                new MoveAdjacentTo(self, target),
                move.MoveTo(host.Location + refuels.Info.RefuelOffset, 0),
                new CallFunc(() => refuels.RefuelUnit(host, self)),
                new WaitFor(() => fueltank.IsFull, true));

            var rp = host.TraitOrDefault <RallyPoint>();

            if (rp != null)
            {
                act.Queue(new CallFunc(() =>
                {
                    self.SetTargetLine(Target.FromCell(self.World, rp.Location), Color.Green);
                    self.QueueActivity(move.MoveTo(rp.Location, host));
                }));
            }

            return(ActivityUtils.SequenceActivities(act, NextActivity));
        }
Example #4
0
        public override Activity Tick(Actor self)
        {
            if (cargo.IsDead || !carryall.IsBusy)
            {
                carryall.UnreserveCarryable();
                return(NextActivity);
            }

            switch (state)
            {
            case State.Intercept:
                state = State.LockCarryable;
                return(ActivityUtils.SequenceActivities(movement.MoveWithinRange(Target.FromActor(cargo), WDist.FromCells(4)), this));

            case State.LockCarryable:
                // Last check
                if (carryable.StandbyForPickup(self))
                {
                    state = State.MoveToCarryable;
                    return(this);
                }

                // We got cancelled
                carryall.UnreserveCarryable();
                return(NextActivity);

            case State.MoveToCarryable:                     // We arrived, move on top
                if (self.Location == cargo.Location)
                {
                    state = State.Turn;
                    return(this);
                }

                return(ActivityUtils.SequenceActivities(movement.MoveTo(cargo.Location, 0), this));

            case State.Turn:                     // Align facing and Land
                if (selfFacing.Facing != cargoFacing.Facing)
                {
                    return(ActivityUtils.SequenceActivities(new Turn(self, cargoFacing.Facing), this));
                }
                state = State.Pickup;
                return(ActivityUtils.SequenceActivities(new HeliLand(self, false), new Wait(10), this));

            case State.Pickup:
                // Remove our carryable from world
                self.World.AddFrameEndTask(w => cargo.World.Remove(cargo));
                carryall.AttachCarryable(cargo);
                state = State.TakeOff;
                return(this);

            case State.TakeOff:
                if (HeliFly.AdjustAltitude(self, aircraft, aircraft.Info.CruiseAltitude))
                {
                    return(this);
                }
                return(NextActivity);
            }

            return(NextActivity);
        }
Example #5
0
        protected override void OnFirstRun(Actor self)
        {
            var aircraft = self.Trait <Aircraft>();
            var host     = aircraft.GetActorBelow();

            if (host == null)
            {
                return;
            }

            if (aircraft.IsPlane)
            {
                ChildActivity = ActivityUtils.SequenceActivities(
                    aircraft.GetResupplyActivities(host)
                    .Append(new AllowYieldingReservation(self))
                    .Append(new WaitFor(() => NextInQueue != null || aircraft.ReservedActor == null))
                    .ToArray());
            }
            else
            {
                // Helicopters should take off from their helipad immediately after resupplying.
                // HACK: Append NextInQueue to TakeOff to avoid moving to the Rallypoint (if NextInQueue is non-null).
                ChildActivity = ActivityUtils.SequenceActivities(
                    aircraft.GetResupplyActivities(host)
                    .Append(new AllowYieldingReservation(self))
                    .Append(new TakeOff(self)).Append(NextInQueue).ToArray());
            }
        }
Example #6
0
        public override Activity Tick(Actor self)
        {
            // Refuse to take off if it would land immediately again.
            if (plane.ForceLanding)
            {
                Cancel(self);
                return(NextActivity);
            }

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

            if (target.IsInRange(self.CenterPosition, minRange))
            {
                var directVector = target.CenterPosition - self.CenterPosition;
                Fly.FlyToward(self, plane, (directVector.Yaw + WAngle.FromDegrees(180)).Facing, plane.Info.CruiseAltitude);
                return(this);
            }

            if (target.IsInRange(self.CenterPosition, maxRange))
            {
                Fly.FlyToward(self, plane, plane.Facing, plane.Info.CruiseAltitude);
                return(this);
            }

            return(ActivityUtils.SequenceActivities(new Fly(self, target, minRange, maxRange), this));
        }
Example #7
0
 public Activity VisualMove(Actor self, WPos fromPos, WPos toPos)
 {
     // TODO: Ignore repulsion when moving
     return(ActivityUtils.SequenceActivities(self,
                                             new CallFunc(() => SetVisualPosition(self, fromPos)),
                                             new Fly(self, Target.FromPos(toPos))));
 }
Example #8
0
        public static Activity GenericApproachDockActivities(Actor host, Actor client, Dock dock,
                                                             Activity requester, bool goThroughHost = false)
        {
            var air = client.TraitOrDefault <Aircraft>();

            if (air != null)
            {
                if (air.IsPlane)
                {
                    // Let's reload. The assumption here is that for aircrafts, there are no waiting docks.
                    System.Diagnostics.Debug.Assert(requester is ReturnToBase, "Wrong parameter for landing");
                    var rtb = requester as ReturnToBase;
                }

                var angle = dock.Info.DockAngle;
                if (angle < 0)
                {
                    angle = client.Info.TraitInfo <AircraftInfo>().InitialFacing;
                }

                return(ActivityUtils.SequenceActivities(
                           new HeliFly(client, Target.FromPos(dock.CenterPosition)),
                           new Turn(client, angle),
                           new HeliLand(client, false)));
            }

            if (goThroughHost)
            {
                return(client.Trait <IMove>().MoveTo(dock.Location, host));
            }
            else
            {
                return(client.Trait <IMove>().MoveTo(dock.Location, 0));
            }
        }
Example #9
0
        public override Activity Tick(Actor self)
        {
            if (plane.ForceLanding)
            {
                return(NextActivity);
            }

            if (IsCanceled || self.IsDead)
            {
                return(NextActivity);
            }

            if (!isCalculated)
            {
                Calculate(self);
            }

            if (dest == null || dest.IsDead)
            {
                var nearestAfld = ChooseAirfield(self, false);

                if (nearestAfld != null)
                {
                    return(ActivityUtils.SequenceActivities(
                               new Fly(self, Target.FromActor(nearestAfld), WDist.Zero, plane.Info.WaitDistanceFromResupplyBase),
                               new FlyCircle(self, plane.Info.NumberOfTicksToVerifyAvailableAirport), this));
                }
                else
                {
                    //Prevent a infinite loop in case we'd return to the activity that called ReturnToBase in the first place.Go idle instead
                    Cancel(self);
                    return(NextActivity);
                }
            }


            List <Activity> landingProcedures = new List <Activity>();

            var turnRadius = CalculateTurnRadius(planeInfo.Speed);

            landingProcedures.Add(new Fly(self, Target.FromPos(w1), WDist.Zero, new WDist(turnRadius * 3)));
            landingProcedures.Add(new Fly(self, Target.FromPos(w2)));

            landingProcedures.Add(new Fly(self, Target.FromPos(w3), WDist.Zero, new WDist(turnRadius / 2)));

            if (ShouldLandAtBuilding(self, dest))
            {
                plane.MakeReservation(dest);

                landingProcedures.Add(new Land(self, Target.FromActor(dest)));
                landingProcedures.Add(new ResupplyAircraft(self));
            }

            if (!abortOnResupply)
            {
                landingProcedures.Add(NextActivity);
            }

            return(ActivityUtils.SequenceActivities(landingProcedures.ToArray()));
        }
Example #10
0
        public override Activity Tick(Actor self)
        {
            cargo.Unloading = false;
            if (IsCanceled || cargo.IsEmpty(self))
            {
                return(NextActivity);
            }

            foreach (var inu in notifiers)
            {
                inu.Unloading(self);
            }

            var actor = cargo.Peek(self);
            var spawn = self.CenterPosition;

            var exitSubCell = ChooseExitSubCell(actor);

            if (exitSubCell == null)
            {
                self.NotifyBlocker(BlockedExitCells(actor));

                return(ActivityUtils.SequenceActivities(new Wait(10), this));
            }

            cargo.Unload(self);
            self.World.AddFrameEndTask(w =>
            {
                if (actor.Disposed)
                {
                    return;
                }

                var move = actor.Trait <IMove>();
                var pos  = actor.Trait <IPositionable>();

                var bunkerPassenger = actor.TraitOrDefault <BunkerPassenger>();
                bunkerPassenger.RevokeCondition();//Disable the condition

                actor.CancelActivity();
                pos.SetVisualPosition(actor, spawn);
                actor.QueueActivity(move.MoveIntoWorld(actor, exitSubCell.Value.First, exitSubCell.Value.Second));
                actor.SetTargetLine(Target.FromCell(w, exitSubCell.Value.First, exitSubCell.Value.Second), Color.Green, false);

                if (cargo.Info.WillDisappear)
                {
                    w.Add(actor);
                }
            });

            if (!unloadAll || cargo.IsEmpty(self))
            {
                return(NextActivity);
            }

            cargo.Unloading = true;

            return(this);
        }
Example #11
0
        public override Activity Tick(Actor self)
        {
            if (NextActivity != null)
            {
                return(NextActivity);
            }

            // Find the nearest best refinery if not explicitly ordered to a specific refinery:
            if (harv.OwnerLinkedProc == null || !harv.OwnerLinkedProc.IsInWorld)
            {
                // Maybe we lost the owner-linked refinery:
                harv.OwnerLinkedProc = null;
                if (self.World.WorldTick - chosenTicks > NextChooseTime)
                {
                    harv.ChooseNewProc(self, null);
                    chosenTicks = self.World.WorldTick;
                }
            }
            else
            {
                harv.LinkProc(self, harv.OwnerLinkedProc);
            }

            if (harv.LinkedProc == null || !harv.LinkedProc.IsInWorld)
            {
                harv.ChooseNewProc(self, null);
            }

            // No refineries exist; check again after delay defined in Harvester.
            if (harv.LinkedProc == null)
            {
                return(ActivityUtils.SequenceActivities(new Wait(harv.Info.SearchForDeliveryBuildingDelay), this));
            }

            var proc = harv.LinkedProc;
            var iao  = proc.Trait <IAcceptResources>();

            self.SetTargetLine(Target.FromActor(proc), Color.Green, false);
            if (self.Location != proc.Location + iao.DeliveryOffset)
            {
                var notify = self.TraitsImplementing <INotifyHarvesterAction>();
                var next   = new DeliverResources(self);
                foreach (var n in notify)
                {
                    n.MovingToRefinery(self, proc.Location + iao.DeliveryOffset, next);
                }

                return(ActivityUtils.SequenceActivities(movement.MoveTo(proc.Location + iao.DeliveryOffset, 0), this));
            }

            if (!isDocking)
            {
                isDocking = true;
                iao.OnDock(self, this);
            }

            return(ActivityUtils.SequenceActivities(new Wait(10), this));
        }
Example #12
0
        public Activity MoveToTarget(Actor self, Target target)
        {
            if (!Info.CanHover)
            {
                return(new Fly(self, target, WDist.FromCells(3), WDist.FromCells(5)));
            }

            return(ActivityUtils.SequenceActivities(new HeliFly(self, target), new Turn(self, Info.InitialFacing)));
        }
Example #13
0
        public Activity VisualMove(Actor self, WPos fromPos, WPos toPos, CPos cell)
        {
            var speed  = MovementSpeedForCell(self, cell);
            var length = speed > 0 ? (toPos - fromPos).Length / speed : 0;

            var delta  = toPos - fromPos;
            var facing = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : Facing;

            return(ActivityUtils.SequenceActivities(new Turn(self, facing), new Drag(self, fromPos, toPos, length)));
        }
Example #14
0
        public override Activity Tick(Actor self)
        {
            cargo.Unloading = false;
            if (IsCanceled || cargo.IsEmpty(self))
            {
                return(NextActivity);
            }

            foreach (var cloak in cloaks)
            {
                if (cloak.Info.UncloakOn.HasFlag(UncloakType.Unload))
                {
                    cloak.Uncloak();
                }
            }

            var actor = cargo.Peek(self);
            var spawn = self.CenterPosition;

            var exitSubCell = ChooseExitSubCell(actor);

            if (exitSubCell == null)
            {
                self.NotifyBlocker(BlockedExitCells(actor));

                return(ActivityUtils.SequenceActivities(new Wait(10), this));
            }

            cargo.Unload(self);
            self.World.AddFrameEndTask(w =>
            {
                if (actor.Disposed)
                {
                    return;
                }

                var move = actor.Trait <IMove>();
                var pos  = actor.Trait <IPositionable>();

                actor.CancelActivity();
                pos.SetVisualPosition(actor, spawn);
                actor.QueueActivity(move.MoveIntoWorld(actor, exitSubCell.Value.First, exitSubCell.Value.Second));
                actor.SetTargetLine(Target.FromCell(w, exitSubCell.Value.First, exitSubCell.Value.Second), Color.Green, false);
                w.Add(actor);
            });

            if (!unloadAll || cargo.IsEmpty(self))
            {
                return(NextActivity);
            }

            cargo.Unloading = true;
            return(this);
        }
Example #15
0
        public override Activity Tick(Actor self)
        {
            switch (dockingState)
            {
            case DockingState.Wait:
                return(this);

            case DockingState.Turn:
                dockingState = DockingState.Dock;
                if (IsDragRequired)
                {
                    return(ActivityUtils.SequenceActivities(new Turn(self, DockAngle), new Drag(self, StartDrag, EndDrag, DragLength), this));
                }
                return(ActivityUtils.SequenceActivities(new Turn(self, DockAngle), this));

            case DockingState.Dock:
                if (Refinery.IsInWorld && !Refinery.IsDead)
                {
                    foreach (var nd in Refinery.TraitsImplementing <INotifyDocking>())
                    {
                        nd.Docked(Refinery, self);
                    }
                }
                return(OnStateDock(self));

            case DockingState.Loop:
                if (!Refinery.IsInWorld || Refinery.IsDead || Harv.TickUnload(self, Refinery))
                {
                    dockingState = DockingState.Undock;
                }
                return(this);

            case DockingState.Undock:
                return(OnStateUndock(self));

            case DockingState.Complete:
                if (Refinery.IsInWorld && !Refinery.IsDead)
                {
                    foreach (var nd in Refinery.TraitsImplementing <INotifyDocking>())
                    {
                        nd.Undocked(Refinery, self);
                    }
                }
                Harv.LastLinkedProc = Harv.LinkedProc;
                Harv.LinkProc(self, null);
                if (IsDragRequired)
                {
                    return(ActivityUtils.SequenceActivities(new Drag(self, EndDrag, StartDrag, DragLength), NextActivity));
                }
                return(NextActivity);
            }

            throw new InvalidOperationException("Invalid harvester dock state.");
        }
Example #16
0
        public override Activity Tick(Actor self)
        {
            if (move == null || refuelsNear == null)
            {
                return(NextActivity);
            }

            self.SetTargetLine(target, Color.Green);

            return(ActivityUtils.SequenceActivities(move.MoveWithinRange(target, refuelsNear.Info.Range), NextActivity));
        }
Example #17
0
            public override Activity Tick(Actor self)
            {
                if (IsCanceled || !target.IsValidFor(self))
                {
                    return(NextActivity);
                }

                if (self.IsDisabled())
                {
                    return(this);
                }

                var weapon = attack.ChooseArmamentsForTarget(target, forceAttack).FirstOrDefault();

                if (weapon != null)
                {
                    var targetIsMobile = (target.Type == TargetType.Actor && target.Actor.Info.HasTraitInfo <IMoveInfo>()) ||
                                         (target.Type == TargetType.FrozenActor && target.FrozenActor.Info.HasTraitInfo <IMoveInfo>());

                    // Try and sit at least one cell closer than the max range to give some leeway if the target starts moving.
                    var modifiedRange = weapon.MaxRange();
                    var maxRange      = targetIsMobile ? new WDist(Math.Max(weapon.Weapon.MinRange.Length, modifiedRange.Length - 1024))
                                                : modifiedRange;

                    // Check that AttackFollow hasn't cancelled the target by modifying attack.Target
                    // Having both this and AttackFollow modify that field is a horrible hack.
                    if (hasTicked && attack.Target.Type == TargetType.Invalid)
                    {
                        return(NextActivity);
                    }

                    attack.Target = target;
                    hasTicked     = true;

                    if (move != null)
                    {
                        return(ActivityUtils.SequenceActivities(move.MoveFollow(self, target, weapon.Weapon.MinRange, maxRange), this));
                    }
                    if (!onRailsHack &&
                        target.IsInRange(self.CenterPosition, weapon.MaxRange()) &&
                        !target.IsInRange(self.CenterPosition, weapon.Weapon.MinRange))
                    {
                        return(this);
                    }
                }

                if (!onRailsHack)
                {
                    attack.Target = Target.Invalid;
                }

                return(NextActivity);
            }
Example #18
0
        public override Activity Tick(Actor self)
        {
            if (IsCanceled)
            {
                if (territory != null)
                {
                    territory.UnclaimByActor(self);
                }
                return(NextActivity);
            }

            harv.LastHarvestedCell = self.Location;

            if (harv.IsFull)
            {
                if (territory != null)
                {
                    territory.UnclaimByActor(self);
                }
                return(NextActivity);
            }

            // Turn to one of the harvestable facings
            if (harvInfo.HarvestFacings != 0)
            {
                var current = facing.Facing;
                var desired = body.QuantizeFacing(current, harvInfo.HarvestFacings);
                if (desired != current)
                {
                    return(ActivityUtils.SequenceActivities(new Turn(self, desired), this));
                }
            }

            var resource = resLayer.Harvest(self.Location);

            if (resource == null)
            {
                if (territory != null)
                {
                    territory.UnclaimByActor(self);
                }
                return(NextActivity);
            }

            harv.AcceptResource(resource);

            foreach (var t in self.TraitsImplementing <INotifyHarvesterAction>())
            {
                t.Harvested(self, resource);
            }

            return(ActivityUtils.SequenceActivities(new Wait(harvInfo.BaleLoadDelay), this));
        }
Example #19
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 RearmBuilding is defined, return to RearmBuilding to reload and then resume the activity
            if (!autoReloads && aircraft.Info.RearmBuildings.Any() && attackPlane.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
            {
                return(ActivityUtils.SequenceActivities(new ReturnToBase(self, aircraft.Info.AbortOnResupply), this));
            }

            if (attackPlane != null)
            {
                attackPlane.DoAttack(self, target);
            }

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

                // TODO: This should fire each weapon at its maximum range
                if (attackPlane != null && target.IsInRange(self.CenterPosition, attackPlane.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);
        }
Example #20
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);
            }

            // TODO: This should check whether there is ammo left that is actually suitable for the target
            if (ammoPools.All(x => !x.Info.SelfReloads && !x.HasAmmo()))
            {
                return(ActivityUtils.SequenceActivities(new ReturnToBase(self, aircraft.Info.AbortOnResupply), this));
            }

            if (attackPlane != null)
            {
                attackPlane.DoAttack(self, target);
            }

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

                // TODO: This should fire each weapon at its maximum range
                if (attackPlane != null && target.IsInRange(self.CenterPosition, attackPlane.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);
        }
Example #21
0
        public override Activity Tick(Actor self)
        {
            var host = aircraft.GetActorBelow();

            if (host == null)
            {
                return(NextActivity);
            }

            return(ActivityUtils.SequenceActivities(
                       aircraft.GetResupplyActivities(host).Append(NextActivity).ToArray()));
        }
Example #22
0
        public override Activity Tick(Actor self)
        {
            if (IsCanceled)
            {
                return(NextActivity);
            }

            var dest          = ChooseHelipad(self);
            var initialFacing = heli.Info.InitialFacing;

            if (dest == null)
            {
                var rearmBuildings = heli.Info.RearmBuildings;
                var nearestHpad    = self.World.ActorsHavingTrait <Reservable>()
                                     .Where(a => a.Owner == self.Owner && rearmBuildings.Contains(a.Info.Name))
                                     .ClosestTo(self);

                if (nearestHpad == null)
                {
                    return(ActivityUtils.SequenceActivities(new Turn(self, initialFacing), new HeliLand(self, true), NextActivity));
                }
                else
                {
                    var distanceFromHelipad = (nearestHpad.CenterPosition - self.CenterPosition).HorizontalLength;
                    var distanceLength      = heli.Info.WaitDistanceFromResupplyBase.Length;

                    // If no pad is available, move near one and wait
                    if (distanceFromHelipad > distanceLength)
                    {
                        var randomPosition = WVec.FromPDF(self.World.SharedRandom, 2) * distanceLength / 1024;

                        var target = Target.FromPos(nearestHpad.CenterPosition + randomPosition);

                        return(ActivityUtils.SequenceActivities(new HeliFly(self, target, WDist.Zero, heli.Info.WaitDistanceFromResupplyBase), this));
                    }

                    return(this);
                }
            }

            heli.MakeReservation(dest);

            var exit   = dest.Info.TraitInfos <ExitInfo>().FirstOrDefault();
            var offset = (exit != null) ? exit.SpawnOffset : WVec.Zero;

            return(ActivityUtils.SequenceActivities(
                       new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)),
                       new Turn(self, initialFacing),
                       new HeliLand(self, false),
                       new ResupplyAircraft(self),
                       NextActivity));
        }
Example #23
0
        public Activity MoveToTarget(Actor self, Target target,
                                     WPos?initialTargetPosition = null, Color?targetLineColor = null)
        {
            if (!Info.CanHover)
            {
                return(new Fly(self, target, WDist.FromCells(3), WDist.FromCells(5),
                               initialTargetPosition, targetLineColor));
            }

            return(ActivityUtils.SequenceActivities(self,
                                                    new HeliFly(self, target, initialTargetPosition, targetLineColor),
                                                    new Turn(self, Info.InitialFacing)));
        }
Example #24
0
        public override Activity Tick(Actor self)
        {
            if (!target.IsValidFor(self))
            {
                return(NextActivity);
            }

            // TODO: This should check whether there is ammo left that is actually suitable for the target
            if (ammoPools.All(x => !x.Info.SelfReloads && !x.HasAmmo()))
            {
                //var master = self.Trait<Spawned>().Master;
                //var tgt = Target.FromActor(master);
                //// We let the spawned to move closer then Enter.
                //// If we just let it enter, it "slides on the ground", targetable by ground units.
                //return ActivityUtils.SequenceActivities(new Fly(self, tgt, new WDist(1024*3), new WDist(1024*5)), new EnterSpawner(self, master, EnterBehaviour.Exit));
                self.Trait <Spawned>().EnterSpawner(self);
            }

            if (attackPlane != null)
            {
                attackPlane.DoAttack(self, target);
            }

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

                // TODO: This should fire each weapon at its maximum range
                if (attackPlane != null && target.IsInRange(self.CenterPosition, attackPlane.Armaments.Select(a => a.Weapon.MinRange).Min()))
                {
                    inner = ActivityUtils.SequenceActivities(new FlyTimed(ticksUntilTurn, self), new Fly(self, target), new FlyTimed(ticksUntilTurn, self));
                }
                else
                {
                    inner = 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)
                {
                    inner = ActivityUtils.SequenceActivities(new SpawnedTakeOff(self), inner);
                }
            }

            inner = ActivityUtils.RunActivity(self, inner);

            return(this);
        }
Example #25
0
        public override Activity Tick(Actor self)
        {
            if (aircraft.ForceLanding)
            {
                Cancel(self);
                return(NextActivity);
            }

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


            if (!autoReloads && aircraft.Info.RearmBuildings.Any() &&
                attackPlane.Armaments.All(x => x.IsTraitPaused || !x.Weapon.IsValidAgainst(target, self.World, self)))
            {
                return(ActivityUtils.SequenceActivities(new ReturnToBase(self, aircraft.Info.AbortOnResupply), this));
            }

            if (attackPlane != null)
            {
                attackPlane.DoAttack(self, target);
            }

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

                if (attackPlane != null && target.IsInRange(self.CenterPosition, attackPlane.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));
                }

                if (self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length < aircraft.Info.MinAirborneAltitude)
                {
                    ChildActivity = ActivityUtils.SequenceActivities(new TakeOff(self), ChildActivity);
                }
            }

            ActivityUtils.RunActivity(self, ChildActivity);

            return(this);
        }
Example #26
0
        public override Activity Tick(Actor self)
        {
            if (IsCanceled)
            {
                return(NextActivity);
            }

            if (ammoPools != null && ammoPools.Any(p => p.Info.Name == info.AmmoPoolName && !p.HasAmmo()))
            {
                // Rearm (and possibly repair) at rearm building, then back out here to refill the minefield some more
                var rearmTarget = self.World.Actors.Where(a => self.Owner.Stances[a.Owner] == Stance.Ally &&
                                                          rearmBuildings.Contains(a.Info.Name))
                                  .ClosestTo(self);

                if (rearmTarget == null)
                {
                    return(new Wait(20));
                }

                // Add a CloseEnough range of 512 to the Repair activity in order to ensure that we're at the host actor
                return(ActivityUtils.SequenceActivities(
                           new MoveAdjacentTo(self, Target.FromActor(rearmTarget)),
                           movement.MoveTo(self.World.Map.CellContaining(rearmTarget.CenterPosition), rearmTarget),
                           new Rearm(self),
                           new Repair(self, rearmTarget, new WDist(512)),
                           this));
            }

            if (minelayer.Minefield.Contains(self.Location) && ShouldLayMine(self, self.Location))
            {
                LayMine(self);
                return(ActivityUtils.SequenceActivities(new Wait(20), this));                // A little wait after placing each mine, for show
            }

            if (minelayer.Minefield.Length > 0)
            {
                // Don't get stuck forever here
                for (var n = 0; n < 20; n++)
                {
                    var p = minelayer.Minefield.Random(self.World.SharedRandom);
                    if (ShouldLayMine(self, p))
                    {
                        return(ActivityUtils.SequenceActivities(movement.MoveTo(p, 0), this));
                    }
                }
            }

            // TODO: Return somewhere likely to be safe (near rearm building) so we're not sitting out in the minefield.
            return(new Wait(20));               // nothing to do here
        }
Example #27
0
        public override Activity Tick(Actor self)
        {
            if (NextInQueue != null)
            {
                return(NextInQueue);
            }

            if (harv.OwnerLinkedProc == null || !harv.OwnerLinkedProc.IsInWorld)
            {
                harv.OwnerLinkedProc = null;
                if (self.World.WorldTick - chosenTicks > NextChooseTime)
                {
                    harv.ChooseNewProc(self, null);
                    chosenTicks = self.World.WorldTick;
                }
            }
            else
            {
                harv.LinkProc(self, harv.OwnerLinkedProc);
            }


            if (harv.LinkedProc == null || !harv.LinkedProc.IsInWorld)
            {
                harv.ChooseNewProc(self, null);
            }

            if (harv.LinkedProc == null)
            {
                return(ActivityUtils.SequenceActivities(new Wait(harv.Info.SearchForDeliveryBuildingDelay), this));
            }

            var proc = harv.LinkedProc;
            var iao  = proc.Trait <IAcceptResources>();

            self.SetTargetLine(Target.FromActor(proc), Color.Green, false);

            if (self.Location != proc.Location + iao.DeliveryOffset)
            {
                return(ActivityUtils.SequenceActivities(movement.MoveTo(proc.Location + iao.DeliveryOffset, 0), this));
            }

            if (!isDocking)
            {
                isDocking = true;
                iao.OnDock(self, this);
            }

            return(ActivityUtils.SequenceActivities(new Wait(10), this));
        }
Example #28
0
        public override Activity Tick(Actor self)
        {
            if (IsCanceled || !target.IsValidFor(self))
            {
                return(NextActivity);
            }

            if (target.IsInRange(self.CenterPosition, maxRange) && !target.IsInRange(self.CenterPosition, minRange))
            {
                Fly.FlyToward(self, plane, plane.Facing, plane.Info.CruiseAltitude);
                return(this);
            }

            return(ActivityUtils.SequenceActivities(new Fly(self, target, minRange, maxRange), this));
        }
Example #29
0
            public override Activity Tick(Actor self)
            {
                if (IsCanceled || !attack.CanAttack(self, target))
                {
                    return(NextActivity);
                }

                if (attack.charges == 0)
                {
                    return(NextActivity);
                }

                attack.DoAttack(self, target);

                return(ActivityUtils.SequenceActivities(new Wait(attack.info.ChargeDelay), this));
            }
Example #30
0
            public override Activity Tick(Actor self)
            {
                if (IsCanceled || !target.IsValidFor(self))
                {
                    return(NextActivity);
                }

                if (attack.IsTraitPaused)
                {
                    return(this);
                }

                var weapon = attack.ChooseArmamentsForTarget(target, forceAttack).FirstEnabledTraitOrDefault();

                if (weapon != null)
                {
                    var targetIsMobile = (target.Type == TargetT.Actor && target.Actor.Info.HasTraitInfo <IMoveInfo>()) ||
                                         (target.Type == TargetT.FrozenActor && target.FrozenActor.Info.HasTraitInfo <IMoveInfo>());

                    var modifiedRange = weapon.MaxRange();
                    var maxRange      = targetIsMobile ? new WDist(Math.Max(weapon.Weapon.MinRange.Length, modifiedRange.Length - 1024)) : modifiedRange;

                    if (hasTicked && attack.Target.Type == TargetT.Invalid)
                    {
                        return(NextActivity);
                    }

                    attack.Target = target;
                    hasTicked     = true;

                    if (move != null)
                    {
                        return(ActivityUtils.SequenceActivities(move.MoveFollow(self, target, weapon.Weapon.MinRange, maxRange), this));
                    }

                    if (target.IsInRange(self.CenterPosition, weapon.MaxRange()) && !target.IsInRange(self.CenterPosition, weapon.Weapon.MinRange))
                    {
                        return(this);
                    }
                }

                attack.Target = Target.Invalid;

                return(NextActivity);
            }