protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDestroyedOrNull(TargetIndex.A); this.FailOnBurningImmobile(TargetIndex.B); //this.FailOnForbidden(TargetIndex.A); Toil gotoThing = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch); gotoThing.FailOnSomeonePhysicallyInteracting(TargetIndex.A); gotoThing.FailOn(delegate(Toil toil) { Job job = toil.actor.CurJob; Thing thing = job.GetTarget(TargetIndex.A).Thing; IntVec3 cell = job.GetTarget(TargetIndex.B).Cell; List <Thing> items_in_cell = HaulExplicitlyPosting.GetItemsIfValidItemSpot( toil.actor.Map, cell); if (items_in_cell == null) { return(true); } if (items_in_cell.Count == 0) { return(false); } if (items_in_cell.Count == 1 && thing.CanStackWith(items_in_cell.First())) { return(false); } return(true); }); yield return(gotoThing); yield return(Toils_HaulExplicitly.PickUpThing(TargetIndex.A, gotoThing)); Toil carryToDest = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToDest); yield return(Toils_HaulExplicitly.PlaceHauledThingAtDest(TargetIndex.B, carryToDest)); }
private DeliverableDestinations(Thing item, Pawn carrier, HaulExplicitlyPosting posting, Func <IntVec3, float> grader) { this.grader = grader; this.posting = posting; record = posting.RecordWithItem(item); Map map = posting.map; thing = item; IntVec3 item_pos = (!item.SpawnedOrAnyParentSpawned) ? carrier.PositionHeld : item.PositionHeld; var traverseparms = TraverseParms.For(carrier, Danger.Deadly, TraverseMode.ByPawn, false); foreach (IntVec3 cell in posting.destinations) { List <Thing> items_in_cell = HaulExplicitlyPosting.GetItemsIfValidItemSpot(map, cell); bool valid_destination = items_in_cell != null; //see if this cell already has, or will have, an item of our item's stack type // (tests items in the cell, as well as reservations on the cell) bool cell_is_same_stack_type = false; if (valid_destination) { foreach (Thing i in items_in_cell) { if (record.CanMixWith(i)) { cell_is_same_stack_type = true; } } } Pawn claimant = map.reservationManager.FirstRespectedReserver(cell, carrier); if (claimant != null) { List <Job> jobs = new List <Job>(claimant.jobs.jobQueue.Select(x => x.job)); jobs.Add(claimant.jobs.curJob); foreach (Job job in jobs) { if (job.def.driverClass == typeof(JobDriver_HaulExplicitly) && (job.targetB == cell || job.targetQueueB.Contains(cell)) && (record.CanMixWith(job.targetA.Thing))) { cell_is_same_stack_type = true; break; } } } //finally, increment our counter of cells with our item's stack type if (cell_is_same_stack_type) { dests_with_this_stack_type++; } //check if cell is valid, reachable from item, unreserved, and pawn is allowed to go there bool reachable = map.reachability.CanReach(item_pos, cell, PathEndMode.ClosestTouch, traverseparms); if (!valid_destination || !reachable || claimant != null || cell.IsForbidden(carrier)) { continue; } // oh, just item things if (items_in_cell.Count == 0) { free_cells.Add(cell); } try { Thing item_in_cell = items_in_cell.Single(); int space_avail = item_in_cell.def.stackLimit - item_in_cell.stackCount; if (cell_is_same_stack_type && space_avail > 0) { partial_cells.Add(cell); partialCellSpaceAvailable.Add(space_avail); } } catch { } } }