Esempio n. 1
0
        public override IEnumerable <TargetLineNode> TargetLineNodes(Actor self)
        {
            if (returnToBase)
            {
                yield return(new TargetLineNode(Target.FromActor(rearmTarget), moveInfo.GetTargetLineColor()));
            }

            if (minefield == null || minefield.Count == 0)
            {
                yield break;
            }

            var nextCell = NextValidCell(self);

            if (nextCell != null)
            {
                yield return(new TargetLineNode(Target.FromCell(self.World, nextCell.Value), minelayer.Info.TargetLineColor));
            }

            foreach (var c in minefield)
            {
                yield return(new TargetLineNode(Target.FromCell(self.World, c), minelayer.Info.TargetLineColor, tile: minelayer.Tile));
            }
        }
Esempio n. 2
0
        public override bool Tick(Actor self)
        {
            // Wait for the cooldown to expire before releasing the unit if this was cancelled
            if (IsCanceling && remainingTicks > 0)
            {
                remainingTicks--;
                return(false);
            }

            var isHostInvalid = host.Type != TargetType.Actor || !host.Actor.IsInWorld;
            var isCloseEnough = false;

            if (!isHostInvalid)
            {
                // Negative means there's no distance limit.
                // If RepairableNear, use TargetablePositions instead of CenterPosition
                // to ensure the actor moves close enough to the host.
                // Otherwise check against host CenterPosition.
                if (closeEnough < WDist.Zero)
                {
                    isCloseEnough = true;
                }
                else if (repairableNear != null)
                {
                    isCloseEnough = host.IsInRange(self.CenterPosition, closeEnough);
                }
                else
                {
                    isCloseEnough = (host.CenterPosition - self.CenterPosition).HorizontalLengthSquared <= closeEnough.LengthSquared;
                }
            }

            // This ensures transports are also cancelled when the host becomes invalid
            if (!IsCanceling && isHostInvalid)
            {
                Cancel(self, true);
            }

            if (IsCanceling || isHostInvalid)
            {
                // Only tick host INotifyResupply traits one last time if host is still alive
                if (!isHostInvalid)
                {
                    foreach (var notifyResupply in notifyResupplies)
                    {
                        notifyResupply.ResupplyTick(host.Actor, self, ResupplyType.None);
                    }
                }

                // HACK: If the activity is cancelled while we're on the host resupplying (or about to start resupplying),
                // move actor outside the resupplier footprint to prevent it from blocking other actors.
                // Additionally, if the host is no longer valid, make aircaft take off.
                if (isCloseEnough || isHostInvalid)
                {
                    OnResupplyEnding(self, isHostInvalid);
                }

                return(true);
            }
            else if (activeResupplyTypes != 0 && aircraft == null && !isCloseEnough)
            {
                var targetCell = self.World.Map.CellContaining(host.Actor.CenterPosition);
                QueueChild(move.MoveWithinRange(host, closeEnough, targetLineColor: moveInfo.GetTargetLineColor()));

                // HACK: Repairable needs the actor to move to host center.
                // TODO: Get rid of this or at least replace it with something less hacky.
                if (repairableNear == null)
                {
                    QueueChild(move.MoveTo(targetCell, targetLineColor: moveInfo.GetTargetLineColor()));
                }

                var delta = (self.CenterPosition - host.CenterPosition).LengthSquared;
                transportCallers.FirstOrDefault(t => t.MinimumDistance.LengthSquared < delta)?.RequestTransport(self, targetCell);

                return(false);
            }

            // We don't want to trigger this until we've reached the resupplier and can start resupplying
            if (!actualResupplyStarted && activeResupplyTypes > 0)
            {
                actualResupplyStarted = true;
                foreach (var notifyResupply in notifyResupplies)
                {
                    notifyResupply.BeforeResupply(host.Actor, self, activeResupplyTypes);
                }

                foreach (var br in notifyBeingResupplied)
                {
                    br.StartingResupply(self, host.Actor);
                }
            }

            if (activeResupplyTypes.HasFlag(ResupplyType.Repair))
            {
                RepairTick(self);
            }

            if (activeResupplyTypes.HasFlag(ResupplyType.Rearm))
            {
                RearmTick(self);
            }

            foreach (var notifyResupply in notifyResupplies)
            {
                notifyResupply.ResupplyTick(host.Actor, self, activeResupplyTypes);
            }

            if (activeResupplyTypes == 0)
            {
                OnResupplyEnding(self);
                return(true);
            }

            return(false);
        }