Esempio n. 1
0
    /// <summary>
    /// Checks whether the current job has all the materials in place and if not instructs the working character to get the materials there first.
    /// Only ever returns true if all materials for the job are at the job location and thus signals to the calling code, that it can proceed with job execution.
    /// </summary>
    /// <returns></returns>
    private bool CheckForJobMaterials()
    {
        List <string> fulfillableInventoryRequirements = new List <string>();

        if (MyJob != null && MyJob.IsNeed && MyJob.Critical == false)
        {
            MyJob.tile = jobTile = new Path_AStar(World.Current, CurrTile, null, MyJob.JobObjectType, 0, false, true).EndTile();
        }

        if (MyJob == null || MyJob.MaterialNeedsMet())
        {
            // We can return early.
            return(true);
        }
        else
        {
            fulfillableInventoryRequirements = MyJob.FulfillableInventoryRequirements();

            // If we somehow get here and fulfillableInventoryRequirements is empty then there is a problem!
            if (fulfillableInventoryRequirements == null || fulfillableInventoryRequirements.Count() == 0)
            {
                Debug.ULogChannel("Character", "CheckForJobMaterials: no fulfillable inventory requirements");
                AbandonJob(true);
                return(false);
            }
        }

        // At this point we know that the job still needs materials and these needs are satisfiable.
        // First we check if we carry any materials the job wants by chance.
        if (inventory != null)
        {
            if (MyJob.AmountDesiredOfInventoryType(inventory) > 0)
            {
                // If so, deliver the goods.
                // Walk to the job tile, then drop off the stack into the job.
                if (CurrTile == JobTile)
                {
                    // We are at the job's site, so drop the inventory
                    World.Current.inventoryManager.PlaceInventory(MyJob, inventory);
                    MyJob.DoWork(0); // This will call all cbJobWorked callbacks, because even though
                    // we aren't progressing, it might want to do something with the fact
                    // that the requirements are being met.

                    // at this point we should dump anything in our inventory
                    DumpExcessInventory();
                }
                else
                {
                    // We still need to walk to the job site.
                    DestTile = JobTile;
                    return(false);
                }
            }
            else
            {
                // We are carrying something, but the job doesn't want it!
                // Dump the inventory so we can be ready to carry what the job actually wants.
                DumpExcessInventory();
            }
        }
        else
        {
            // At this point, the job still requires inventory, but we aren't carrying it!
            // Are we standing on a tile with goods that are desired by the job?
            if (CurrTile.Inventory != null &&
                MyJob.AmountDesiredOfInventoryType(CurrTile.Inventory) > 0 && !CurrTile.Inventory.Locked &&
                (MyJob.canTakeFromStockpile || CurrTile.Furniture == null || CurrTile.Furniture.IsStockpile() == false))
            {
                // Pick up the stuff!
                World.Current.inventoryManager.PlaceInventory(
                    this,
                    CurrTile.Inventory,
                    MyJob.AmountDesiredOfInventoryType(CurrTile.Inventory));
            }
            else
            {
                // Walk towards a tile containing the required goods.
                if (CurrTile != nextTile)
                {
                    // We are still moving somewhere, so just bail out.
                    return(false);
                }

                // Any chance we already have a path that leads to the items we want?
                // Check that we have an end tile and that it has content.
                // Check if contains the desired objectType�.
                if (WalkingToUsableInventory() && fulfillableInventoryRequirements.Contains(pathAStar.EndTile().Inventory.ObjectType))
                {
                    // We are already moving towards a tile that contains what we want!
                    // so....do nothing?
                    return(false);
                }
                else
                {
                    Inventory  desired = null;
                    Path_AStar newPath = null;
                    foreach (string itemType in fulfillableInventoryRequirements)
                    {
                        desired = MyJob.inventoryRequirements[itemType];
                        newPath = World.Current.inventoryManager.GetPathToClosestInventoryOfType(
                            desired.ObjectType,
                            CurrTile,
                            desired.MaxStackSize - desired.StackSize,
                            MyJob.canTakeFromStockpile);

                        if (newPath == null || newPath.Length() < 1)
                        {
                            // Try the next requirement
                            Debug.ULogChannel("Character", "No tile contains objects of type '" + desired.ObjectType + "' to satisfy job requirements.");
                            continue;
                        }

                        // else, there is a valid path to an item that will satisfy the job
                        break;
                    }

                    if (newPath == null || newPath.Length() < 1)
                    {
                        // tried all requirements and found no path
                        Debug.ULogChannel("Character", "No reachable tile contains objects able to satisfy job requirements.");
                        AbandonJob(true);
                        return(false);
                    }

                    Debug.ULogChannel("Character", "pathAStar returned with length of: " + newPath.Length());

                    DestTile = newPath.EndTile();

                    // Since we already have a path calculated, let's just save that.
                    pathAStar = newPath;

                    // Ignore first tile, because that's what we're already in.
                    nextTile = newPath.Dequeue();
                }

                // One way or the other, we are now on route to an object of the right type.
                return(false);
            }
        }

        return(false); // We can't continue until all materials are satisfied.
    }