public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) { if (!CanGetThing(pawn, t, forced)) { return(null); } //plan count and dests HaulExplicitlyPosting posting = HaulExplicitly.GetManager(t.Map).PostingWithItem(t); if (posting == null) { return(null); } int space_request = AmountPawnWantsToPickUp(pawn, t, posting); var destInfo = DeliverableDestinations.For(t, pawn, posting); List <IntVec3> dests = destInfo.RequestSpaceForItemAmount(space_request); int dest_space_available = destInfo.FreeSpaceInCells(dests); var count = Math.Min(space_request, dest_space_available); if (count < 1) { return(null); } //make job JobDef JobDefOfHaulExplicitly = (JobDef)(GenDefDatabase.GetDef(typeof(JobDef), "HaulExplicitlyHaul")); Job job = new Job(JobDefOfHaulExplicitly, t, dests.First()); //((JobDriver_HaulExplicitly)job.GetCachedDriver(pawn)).init(); job.count = count; job.targetQueueA = new List <LocalTargetInfo>( new LocalTargetInfo[] { new IntVec3(posting.id, dest_space_available, 0) }); job.targetQueueB = new List <LocalTargetInfo>(dests.Skip(1).Take(dests.Count - 1) .Select(c => new LocalTargetInfo(c))); job.haulOpportunisticDuplicates = true; return(job); }
public static Toil PickUpThing(TargetIndex haulxItemInd, Toil nextToilIfBeingOpportunistic) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job job = actor.CurJob; Thing target = job.GetTarget(haulxItemInd).Thing; if (Toils_Haul.ErrorCheckForCarry(actor, target)) { return; } Thing carriedItem = actor.carryTracker.CarriedThing; int targetInitialStackcount = target.stackCount; int countToPickUp = Mathf.Min( job.count - (carriedItem?.stackCount ?? 0), actor.carryTracker.AvailableStackSpace(target.def), targetInitialStackcount); if (countToPickUp <= 0) { throw new Exception("PickUpThing countToPickUp = " + countToPickUp); } //pick up int countPickedUp = actor.carryTracker.TryStartCarry(target, countToPickUp); if (countPickedUp < targetInitialStackcount) { actor.Map.reservationManager.Release(target, actor, job); } carriedItem = actor.carryTracker.CarriedThing; job.SetTarget(haulxItemInd, carriedItem); actor.records.Increment(RecordDefOf.ThingsHauled); //register the carried item (into the HaulExplicitly job) if (carriedItem.IsAHaulableSetToHaulable()) { carriedItem.ToggleHaulDesignation(); } var driver = (JobDriver_HaulExplicitly)actor.jobs.curDriver; driver.posting.TryAddItemSplinter(carriedItem); //pick up next available item in job? if (actor.CurJob.haulOpportunisticDuplicates) { Thing prospect = null; int best_dist = 999; foreach (Thing item in driver.record.items.Where( i => i.Spawned && WorkGiver_HaulExplicitly.CanGetThing(actor, i, false))) { IntVec3 offset = item.Position - actor.Position; int dist = Math.Abs(offset.x) + Math.Abs(offset.z); if (dist < best_dist && dist < 7) { prospect = item; best_dist = dist; } } if (prospect == null) { return; } int space_request = WorkGiver_HaulExplicitly .AmountPawnWantsToPickUp(actor, prospect, driver.posting); if (space_request == 0) { return; } var destInfo = DeliverableDestinations.For(prospect, actor, driver.posting); List <IntVec3> dests = destInfo.RequestSpaceForItemAmount( Math.Max(0, space_request - driver.dest_space_available)); int new_dest_space = destInfo.FreeSpaceInCells(dests); var count = Math.Min(space_request, driver.dest_space_available + new_dest_space); if (count < 1) { return; } //commit to it actor.Reserve(prospect, job); job.SetTarget(haulxItemInd, prospect); job.SetTarget(TargetIndex.C, prospect.Position); foreach (var dest in dests) { actor.Reserve(dest, job); job.targetQueueB.Add(dest); } job.count += count; driver.JumpToToil(nextToilIfBeingOpportunistic); } }; return(toil); }