protected override IEnumerable <Toil> MakeNewToils() { /// //Set fail conditions /// this.FailOnDestroyed(HaulableInd); this.FailOnDestroyed(CarrierInd); //Note we only fail on forbidden if the target doesn't start that way //This helps haul-aside jobs on forbidden items if (!TargetThingA.IsForbidden(pawn.Faction)) { this.FailOnForbidden(HaulableInd); } /// //Define Toil /// Toil toilGoto = null; toilGoto = Toils_Goto.GotoThing(HaulableInd, PathMode.ClosestTouch) .FailOn(() => { Vehicle_Cargo vc = CurJob.GetTarget(CarrierInd).Thing as Vehicle_Cargo; if (!vc.storage.CanAcceptAnyOf(CurJob.GetTarget(HaulableInd).Thing)) { return(true); } return(false); }); /// //Toils Start /// //Reserve thing to be stored and storage cell yield return(Toils_Reserve.Reserve(HaulableInd)); //Collect Target yield return(toilGoto); yield return(ToolsForHaul.Toils_Collect.CollectThing(HaulableInd, CarrierInd)); }
protected override Job TryGiveTerminalJob(Pawn pawn) { Thing closestHaulable; Job jobCollectThing = new Job(DefDatabase <JobDef> .GetNamed("CollectThing")); Job jobDropInCell = new Job(DefDatabase <JobDef> .GetNamed("DropInCell")); Job jobDismountInBase = new Job(DefDatabase <JobDef> .GetNamed("DismountInBase")); jobCollectThing.maxNumToCarry = 99999; jobCollectThing.haulMode = HaulMode.ToCellStorage; //Find Available Carrier Vehicle_Cargo carrier = Find.ListerThings.AllThings.Find((Thing t) => (t.TryGetComp <CompMountable>() != null && t.TryGetComp <CompMountable>().Driver == pawn)) as Vehicle_Cargo; //No Carrier if (carrier == null) { //Log.Message("No Carrier"); return(null); } jobCollectThing.targetC = carrier; jobDropInCell.targetC = carrier; jobDismountInBase.targetA = carrier; //collectThing Predicate Predicate <Thing> predicate = (Thing t) => (!t.IsForbidden(pawn.Faction) && !t.IsInAnyStorage() && pawn.CanReserve(t) && carrier.storage.CanAcceptAnyOf(t)); //Log.Message("flagInProgressDrop" + flagInProgressDrop); if (carrier.storage.TotalStackCount < carrier.GetMaxStackCount && carrier.storage.Contents.Count() < carrier.maxItem && !ListerHaulables.ThingsPotentiallyNeedingHauling().NullOrEmpty() && flagInProgressDrop == false) { //Log.Message("Finding Haulable"); closestHaulable = GenClosest.ClosestThing_Global_Reachable(pawn.Position, ListerHaulables.ThingsPotentiallyNeedingHauling(), PathMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, false), 9999, predicate); if (closestHaulable == null) { //Log.Message("No Haulable"); return(null); } jobCollectThing.targetA = closestHaulable; return(jobCollectThing); } else { //Log.Message("flagInProgressDrop" + flagInProgressDrop); flagInProgressDrop = true; if (carrier.storage.Contents.Count() <= 0) { flagInProgressDrop = false; //Log.Message("End Progress Drop"); if (ListerHaulables.ThingsPotentiallyNeedingHauling().NullOrEmpty()) { return(jobDismountInBase); } return(null); } foreach (Zone zone in Find.ZoneManager.AllZones) { if (zone is Zone_Stockpile) { foreach (var zoneCell in zone.cells) { Thing dropThing = carrier.storage.Contents.Last(); if (zoneCell.IsValidStorageFor(dropThing) && pawn.CanReserve(zoneCell)) { jobDropInCell.targetA = dropThing; jobDropInCell.targetB = zoneCell; return(jobDropInCell); } } } } //No zone for stock //Log.Message("No Zone"); return(null); } }
public override Job JobOnThing(Pawn pawn, Thing t) { if (!(t is Vehicle_Cargo)) { return(null); } Vehicle_Cargo carrier = t as Vehicle_Cargo; List <Thing> haulables = ListerHaulables.ThingsPotentiallyNeedingHauling(); IEnumerable <Thing> remainingItems = carrier.storage.Contents; //bool IsMountedVehicle = ((carrier.GetComp<CompMountable>().Driver == pawn)? true: false); int reservedStackCount = carrier.storage.TotalStackCount; int reservedMaxItem = carrier.storage.Contents.Count(); Job jobDismountInBase = new Job(DefDatabase <JobDef> .GetNamed("DismountInBase")); Job jobCollect = new Job(DefDatabase <JobDef> .GetNamed("Collect")); jobCollect.maxNumToCarry = 99999; jobCollect.haulMode = HaulMode.ToCellStorage; jobCollect.targetQueueA = new List <TargetInfo>(); jobCollect.targetQueueB = new List <TargetInfo>(); //Set carrier jobDismountInBase.targetA = carrier; jobCollect.targetC = carrier; ReservationUtility.Reserve(pawn, t); //If IgnoreForbidden is true, add forbidden if (carrier.ignoreForbidden) { List <Thing> forbiddens = Find.ListerThings.AllThings.FindAll((Thing thing) => (thing.TryGetComp <CompForbiddable>() != null && thing.TryGetComp <CompForbiddable>().Forbidden == true)); haulables = forbiddens.Concat(haulables).ToList(); /*string logStr = ""; * foreach (var forbidden in forbiddens) * logStr += forbidden.ThingID; * Log.Message("Haulable: " + logStr);*/ } //Drop remaining item foreach (var remainingItem in remainingItems) { IntVec3 storageCell = new IntVec3(-1000, -1000, -1000); foreach (Zone zone in Find.ZoneManager.AllZones) { if (storageCell.IsValid) { break; } if (zone is Zone_Stockpile) { foreach (var zoneCell in zone.cells) { if (!jobCollect.targetQueueB.Contains(zoneCell) && zoneCell.IsValidStorageFor(remainingItem) && pawn.CanReserve(zoneCell)) { storageCell = zoneCell; break; } } } } if (!storageCell.IsValid) { break; } //Just drop, not collect. It was already collected //jobCollect.targetQueueA.Add(remainingItem); //ReservationUtility.Reserve(pawn, remainingItem, ReservationType.Total); jobCollect.targetQueueB.Add(storageCell); ReservationUtility.Reserve(pawn, storageCell); } if (!jobCollect.targetQueueB.NullOrEmpty()) { return(jobCollect); } //collectThing Predicate Predicate <Thing> predicate = (Thing item) => ((carrier.ignoreForbidden || !item.IsForbidden(pawn.Faction)) && !item.IsInValidStorage() && pawn.CanReserve(item) && carrier.storage.CanAcceptAnyOf(item)); //Collect and drop item while (!haulables.NullOrEmpty() && reservedStackCount < carrier.GetMaxStackCount && reservedMaxItem < carrier.maxItem) { IntVec3 storageCell = new IntVec3(-1000, -1000, -1000); Thing closestHaulable = null; //Log.Message("reservedStackCount, reservedMaxItem :" + reservedStackCount + ',' + reservedMaxItem); closestHaulable = GenClosest.ClosestThing_Global_Reachable(pawn.Position, haulables, PathMode.ClosestTouch, TraverseParms.For(pawn, Danger.Deadly, false), 9999, predicate); if (closestHaulable == null) { break; } if (!jobCollect.targetQueueB.NullOrEmpty()) { foreach (TargetInfo target in jobCollect.targetQueueB) { if (storageCell.IsValid) { break; } foreach (var adjCell in GenAdjFast.AdjacentCells8Way(target)) { if (!jobCollect.targetQueueB.Contains(adjCell) && adjCell.IsValidStorageFor(closestHaulable) && pawn.CanReserve(adjCell)) { storageCell = adjCell; break; } } } } foreach (Zone zone in Find.ZoneManager.AllZones) { if (storageCell.IsValid) { break; } if (zone is Zone_Stockpile) { foreach (var zoneCell in zone.cells) { if (!jobCollect.targetQueueB.Contains(zoneCell) && zoneCell.IsValidStorageFor(closestHaulable) && pawn.CanReserve(zoneCell)) { storageCell = zoneCell; //Log.Message("storageCell: " + storageCell); break; } } } } //No Storage if (!storageCell.IsValid) { break; } jobCollect.targetQueueA.Add(closestHaulable); ReservationUtility.Reserve(pawn, closestHaulable); haulables.Remove(closestHaulable); jobCollect.targetQueueB.Add(storageCell); ReservationUtility.Reserve(pawn, storageCell); reservedMaxItem++; reservedStackCount += closestHaulable.stackCount; } //No haulables or zone if (jobCollect.targetQueueA.NullOrEmpty() || jobCollect.targetQueueB.NullOrEmpty()) { foreach (Zone zone in Find.ZoneManager.AllZones) { if (jobDismountInBase.targetB != null) { break; } if (zone is Zone_Stockpile) { foreach (var zoneCell in zone.cells) { Thing dropThing = carrier; if (zoneCell.IsValidStorageFor(dropThing) && pawn.CanReserve(zoneCell)) { ReservationUtility.Reserve(pawn, zoneCell); jobDismountInBase.targetB = zoneCell; break; } } } } //Move cargo in Base if (!carrier.IsInValidStorage() && jobDismountInBase.targetB != null) { return(jobDismountInBase); } //No job, no move to cargo if (Find.Reservations.IsReserved(carrier, pawn.Faction)) { Find.Reservations.Release(carrier, pawn); } return(null); } return(jobCollect); }