/// <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. }