Пример #1
0
        public void UnblockRefinery(Actor self)
        {
            // Check that we're not in a critical location and being useless (refinery drop-off):
            var lastproc = LastLinkedProc ?? LinkedProc;
            if (lastproc != null && !lastproc.Destroyed)
            {
                var deliveryLoc = lastproc.Location + lastproc.Trait<IAcceptResources>().DeliveryOffset;
                if (self.Location == deliveryLoc)
                {
                    // Get out of the way:
                    var mobile = self.Trait<Mobile>();
                    var harv = self.Trait<Harvester>();

                    var moveTo = harv.LastHarvestedCell ?? (deliveryLoc + new CVec(0, 4));
                    self.QueueActivity(mobile.MoveTo(moveTo, 1));
                    self.SetTargetLine(Target.FromCell(self.World, moveTo), Color.Gray, false);

                    var territory = self.World.WorldActor.TraitOrDefault<ResourceClaimLayer>();
                    if (territory != null) territory.ClaimResource(self, moveTo);

                    var notify = self.TraitsImplementing<INotifyHarvesterAction>();
                    var next = new FindResources();
                    foreach (var n in notify)
                        n.MovingToResources(self, moveTo, next);

                    self.QueueActivity(new FindResources());
                    return;
                }
            }
        }
Пример #2
0
        public override Activity Tick(Actor self)
        {
            if (IsCanceled || NextActivity != null)
            {
                return(NextActivity);
            }

            var harv = self.Trait <Harvester>();

            if (harv.IsFull)
            {
                return(Util.SequenceActivities(new DeliverResources(), NextActivity));
            }

            var harvInfo   = self.Info.Traits.Get <HarvesterInfo>();
            var mobile     = self.Trait <Mobile>();
            var mobileInfo = self.Info.Traits.Get <MobileInfo>();
            var resLayer   = self.World.WorldActor.Trait <ResourceLayer>();
            var territory  = self.World.WorldActor.TraitOrDefault <ResourceClaimLayer>();

            // Determine where to search from and how far to search:
            var searchFromLoc       = harv.LastOrderLocation ?? (harv.LastLinkedProc ?? harv.LinkedProc ?? self).Location;
            var searchRadius        = harv.LastOrderLocation.HasValue ? harvInfo.SearchFromOrderRadius : harvInfo.SearchFromProcRadius;
            var searchRadiusSquared = searchRadius * searchRadius;

            // Find harvestable resources nearby:
            var path = self.World.WorldActor.Trait <IPathFinder>().FindPath(
                PathSearch.Search(self.World, mobileInfo, self, true)
                .WithHeuristic(loc =>
            {
                // Avoid this cell:
                if (avoidCell.HasValue && loc == avoidCell.Value)
                {
                    return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost);
                }

                // Don't harvest out of range:
                var distSquared = (loc - searchFromLoc).LengthSquared;
                if (distSquared > searchRadiusSquared)
                {
                    return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost * 2);
                }

                // Get the resource at this location:
                var resType = resLayer.GetResource(loc);
                if (resType == null)
                {
                    return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost);
                }

                // Can the harvester collect this kind of resource?
                if (!harvInfo.Resources.Contains(resType.Info.Name))
                {
                    return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost);
                }

                if (territory != null)
                {
                    // Another harvester has claimed this resource:
                    ResourceClaim claim;
                    if (territory.IsClaimedByAnyoneElse(self, loc, out claim))
                    {
                        return(EstimateDistance(loc, searchFromLoc) + Constants.CellCost);
                    }
                }

                return(0);
            })
                .FromPoint(self.Location));

            if (path.Count == 0)
            {
                if (!harv.IsEmpty)
                {
                    return(new DeliverResources());
                }
                else
                {
                    // Get out of the way if we are:
                    harv.UnblockRefinery(self);
                    var randFrames = 125 + self.World.SharedRandom.Next(-35, 35);
                    if (NextActivity != null)
                    {
                        return(Util.SequenceActivities(NextActivity, new Wait(randFrames), new FindResources()));
                    }
                    else
                    {
                        return(Util.SequenceActivities(new Wait(randFrames), new FindResources()));
                    }
                }
            }

            // Attempt to claim a resource as ours:
            if (territory != null)
            {
                if (!territory.ClaimResource(self, path[0]))
                {
                    return(Util.SequenceActivities(new Wait(25), new FindResources()));
                }
            }

            // If not given a direct order, assume ordered to the first resource location we find:
            if (harv.LastOrderLocation == null)
            {
                harv.LastOrderLocation = path[0];
            }

            self.SetTargetLine(Target.FromCell(self.World, path[0]), Color.Red, false);

            var notify = self.TraitsImplementing <INotifyHarvesterAction>();
            var next   = new FindResources();

            foreach (var n in notify)
            {
                n.MovingToResources(self, path[0], next);
            }

            return(Util.SequenceActivities(mobile.MoveTo(path[0], 1), new HarvestResource(), new FindResources()));
        }
Пример #3
0
        public void ResolveOrder(Actor self, Order order)
        {
            if (order.OrderString == "Harvest")
            {
                // NOTE: An explicit harvest order allows the harvester to decide which refinery to deliver to.
                LinkProc(self, OwnerLinkedProc = null);
                idleSmart = true;

                self.CancelActivity();

                var mobile = self.Trait<Mobile>();
                if (order.TargetLocation != CPos.Zero)
                {
                    var loc = order.TargetLocation;
                    var territory = self.World.WorldActor.TraitOrDefault<ResourceClaimLayer>();

                    if (territory != null)
                    {
                        // Find the nearest claimable cell to the order location (useful for group-select harvest):
                        loc = mobile.NearestCell(loc, p => mobile.CanEnterCell(p) && territory.ClaimResource(self, p), 1, 6);
                    }
                    else
                    {
                        // Find the nearest cell to the order location (useful for group-select harvest):
                        var taken = new HashSet<CPos>();
                        loc = mobile.NearestCell(loc, p => mobile.CanEnterCell(p) && taken.Add(p), 1, 6);
                    }

                    self.QueueActivity(mobile.MoveTo(loc, 0));
                    self.SetTargetLine(Target.FromCell(self.World, loc), Color.Red);

                    var notify = self.TraitsImplementing<INotifyHarvesterAction>();
                    var next = new FindResources();
                    foreach (var n in notify)
                        n.MovingToResources(self, loc, next);

                    LastOrderLocation = loc;
                }
                else
                {
                    // A bot order gives us a CPos.Zero TargetLocation, so find some good resources for him:
                    var loc = FindNextResourceForBot(self);

                    // No more resources? Oh well.
                    if (!loc.HasValue)
                        return;

                    self.QueueActivity(mobile.MoveTo(loc.Value, 0));
                    self.SetTargetLine(Target.FromCell(self.World, loc.Value), Color.Red);

                    LastOrderLocation = loc;
                }

                // This prevents harvesters returning to an empty patch when the player orders them to a new patch:
                LastHarvestedCell = LastOrderLocation;
                self.QueueActivity(new FindResources());
            }
            else if (order.OrderString == "Deliver")
            {
                // NOTE: An explicit deliver order forces the harvester to always deliver to this refinery.
                var iao = order.TargetActor.TraitOrDefault<IAcceptResources>();
                if (iao == null || !iao.AllowDocking || !IsAcceptableProcType(order.TargetActor))
                    return;

                if (order.TargetActor != OwnerLinkedProc)
                    LinkProc(self, OwnerLinkedProc = order.TargetActor);

                if (IsEmpty)
                    return;

                idleSmart = true;

                self.SetTargetLine(Target.FromOrder(self.World, order), Color.Green);

                self.CancelActivity();
                self.QueueActivity(new DeliverResources());

                var notify = self.TraitsImplementing<INotifyHarvesterAction>();
                var next = new DeliverResources();
                foreach (var n in notify)
                    n.MovingToRefinery(self, order.TargetLocation, next);
            }
            else if (order.OrderString == "Stop" || order.OrderString == "Move")
            {
                var notify = self.TraitsImplementing<INotifyHarvesterAction>();
                foreach (var n in notify)
                    n.MovementCancelled(self);

                // Turn off idle smarts to obey the stop/move:
                idleSmart = false;
            }
        }