private static bool AllowToolHaulUrgentlyJobOnThing_PreFix(ref Job __result, Pawn pawn, Thing t, bool forced = false) { if (ModCompatibilityCheck.AllowToolIsActive) { //allowTool HaulUrgently CompHauledToInventory takenToInventory = pawn.TryGetComp <CompHauledToInventory>(); if (pawn.RaceProps.Humanlike && pawn.Faction == Faction.OfPlayer && t is Corpse == false && takenToInventory != null && !(t.def.defName.Contains("Chunk")) //most of the time we don't have space for it ) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(t); if (!StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true)) { JobFailReason.Is("NoEmptyPlaceLower".Translate()); return(false); } WorkGiver_HaulToInventory haulWG = (WorkGiver_HaulToInventory)pawn.workSettings.WorkGiversInOrderNormal.Find(wg => wg is WorkGiver_HaulToInventory); Job haul = haulWG.JobOnThing(pawn, t, forced); __result = haul; return(false); } } return(true); }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDespawnedNullOrForbidden(TargetIndex.A); this.FailOnBurningImmobile(TargetIndex.A); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch)); yield return(Toils_General.Wait(200, TargetIndex.None).FailOnDestroyedNullOrForbidden(TargetIndex.A).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch).FailOn(() => !this.OniWineBarrel.Fermented).WithProgressBarToilDelay(TargetIndex.A, false, -0.5f)); yield return(new Toil { initAction = delegate() { Thing thing = this.OniWineBarrel.TakeOutAOniWine(); GenPlace.TryPlaceThing(thing, this.pawn.Position, base.Map, ThingPlaceMode.Near, null, null, default); StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (StoreUtility.TryFindBestBetterStoreCellFor(thing, this.pawn, base.Map, currentPriority, this.pawn.Faction, out IntVec3 c, true)) { this.job.SetTarget(TargetIndex.C, c); this.job.SetTarget(TargetIndex.B, thing); this.job.count = thing.stackCount; return; } base.EndJobWith(JobCondition.Incompletable); }, defaultCompleteMode = ToilCompleteMode.Instant });
public static bool Prefix(Pawn pawn, Thing thing, WorkGiver_HaulToInventory __instance, bool forced, ref bool __result) { #region PickUpAndHaul code //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(false); } if (!WorkGiver_HaulToInventory.GoodThingToHaul(thing, pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(false); } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); bool foundCell = StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true); #endregion if (!foundCell) { __result = false; } else { SlotGroup slotGroup = pawn.Map.haulDestinationManager.SlotGroupAt(storeCell); __result = !(slotGroup != null && Limits.HasLimit(slotGroup.Settings) && Limits.GetLimit(slotGroup.Settings) >= slotGroup.TotalPrecalculatedItemsStack()); } return(false); }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDespawnedNullOrForbidden(BuildingInd); this.FailOnBurningImmobile(BuildingInd); yield return(Toils_Goto.GotoThing(BuildingInd, PathEndMode.Touch)); yield return(Toils_General.Wait(Duration).FailOnDestroyedNullOrForbidden(BuildingInd).FailOnCannotTouch(BuildingInd, PathEndMode.Touch).FailOn(() => !Building.Completed).WithProgressBarToilDelay(BuildingInd)); yield return(new Toil { initAction = delegate { Thing product = Building.TakeOutProduct(); GenPlace.TryPlaceThing(product, pawn.Position, Map, ThingPlaceMode.Near); StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(product); if (StoreUtility.TryFindBestBetterStoreCellFor(product, pawn, Map, currentPriority, pawn.Faction, out IntVec3 cell)) { job.SetTarget(StorageCellInd, cell); job.SetTarget(ProductInd, product); job.count = product.stackCount; } else { EndJobWith(JobCondition.Incompletable); } },
public override bool TryMakePreToilReservations(bool errorOnFailed) { Pawn pawn = base.pawn; LocalTargetInfo target = base.job.GetTarget(TargetIndex.B); Job job = base.job; bool errorOnFailed2 = errorOnFailed; bool result = false; if (!target.Cell.IsValidStorageFor(pawn.Map, pawn.carryTracker.CarriedThing)) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(TargetThingA); if (!StoreUtility.TryFindBestBetterStorageFor(TargetThingA, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 foundCell, out IHaulDestination haulDestination)) { return(false); } } if (pawn.Reserve(target, job, 1, -1, null, errorOnFailed2)) { pawn = base.pawn; target = base.job.GetTarget(TargetIndex.A); job = base.job; errorOnFailed2 = errorOnFailed; result = pawn.Reserve(target, job, 1, -1, null, errorOnFailed2); } Log.Message("Make Reservation result: " + result); return(result); }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDespawnedNullOrForbidden(BarrelInd); this.FailOnBurningImmobile(BarrelInd); yield return(Toils_Goto.GotoThing(BarrelInd, PathEndMode.Touch)); yield return(Toils_General.Wait(Duration).FailOnDestroyedNullOrForbidden(BarrelInd) .FailOnCannotTouch(BarrelInd, PathEndMode.Touch).FailOn(() => !MeadBarrel.Fermented) .WithProgressBarToilDelay(BarrelInd)); yield return(new Toil { initAction = delegate { var thing = MeadBarrel.TakeOutMead(); GenPlace.TryPlaceThing(thing, pawn.Position, Map, ThingPlaceMode.Near); var currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, Map, currentPriority, pawn.Faction, out var c)) { job.SetTarget(TargetIndex.C, c); job.SetTarget(TargetIndex.B, thing); job.count = thing.stackCount; } else { EndJobWith(JobCondition.Incompletable); } },
public static Job HaulToStorageJob(Pawn p, Thing t) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(t); IntVec3 storeCell; IHaulDestination haulDestination; Job result; if (!StoreUtility.TryFindBestBetterStorageFor(t, p, p.Map, currentPriority, p.Faction, out storeCell, out haulDestination, true)) { JobFailReason.Is(HaulAIUtility.NoEmptyPlaceLowerTrans, null); result = null; } else if (haulDestination is ISlotGroupParent) { result = HaulAIUtility.HaulToCellStorageJob(p, t, storeCell, false); } else { Thing thing = haulDestination as Thing; if (thing != null && thing.TryGetInnerInteractableThingOwner() != null) { result = HaulAIUtility.HaulToContainerJob(p, t, thing); } else { Log.Error("Don't know how to handle HaulToStorageJob for storage " + haulDestination.ToStringSafe <IHaulDestination>() + ". thing=" + t.ToStringSafe <Thing>(), false); result = null; } } return(result); }
protected override IEnumerable <Toil> MakeNewToils() { //Log.Message("I am inside the job now, with "+pawn.ToString(), false); Building_ItemProcessor building_processor = (Building_ItemProcessor)this.job.GetTarget(TargetIndex.A).Thing; this.FailOnDespawnedNullOrForbidden(TargetIndex.A); this.FailOnBurningImmobile(TargetIndex.A); yield return(Toils_General.DoAtomic(delegate { this.job.count = 1; })); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch)); yield return(Toils_General.Wait(240).FailOnDestroyedNullOrForbidden(TargetIndex.A).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch).WithProgressBarToilDelay(TargetIndex.A, false, -0.5f)); yield return(new Toil { initAction = delegate { Thing newProduct; if (building_processor.productsToTurnInto != null && building_processor.productsToTurnInto.Count > 0) { newProduct = ThingMaker.MakeThing(ThingDef.Named(building_processor.productsToTurnInto[(int)building_processor.qualityNow])); } else { newProduct = ThingMaker.MakeThing(ThingDef.Named(building_processor.productToTurnInto)); } newProduct.stackCount = building_processor.amount; if ((newProduct.TryGetComp <CompIngredients>() is CompIngredients ingredientComp) && !building_processor.compItemProcessor.Props.ignoresIngredientLists) { ingredientComp.ingredients = building_processor.ingredients; } if (building_processor.usingQualityIncreasing && newProduct.TryGetComp <CompQuality>() is CompQuality qualityComp) { qualityComp.SetQuality(building_processor.qualityNow, ArtGenerationContext.Colony); } GenSpawn.Spawn(newProduct, building_processor.InteractionCell, building_processor.Map); building_processor.processorStage = ProcessorStage.ProductRemoved; building_processor.ResetEverything(); building_processor.DestroyIngredients(); StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(newProduct); IntVec3 c; if (StoreUtility.TryFindBestBetterStoreCellFor(newProduct, this.pawn, this.Map, currentPriority, this.pawn.Faction, out c, true)) { this.job.SetTarget(TargetIndex.C, c); this.job.SetTarget(TargetIndex.B, newProduct); this.job.count = newProduct.stackCount; } else { this.EndJobWith(JobCondition.Incompletable); } },
public static void DeregisterHaulableItem(Thing haulableThing) { Map map = haulableThing.Map; if (map != null) { int storagePriority = (int)StoreUtility.CurrentStoragePriorityOf(haulableThing); getWaitingForZoneBetterThan(map)[storagePriority].Remove(haulableThing); RemoveThingFromAwaitingHaulingHashSets(haulableThing); } }
//pick up stuff until you can't anymore, //while you're up and about, pick up something and haul it //before you go out, empty your pockets public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) { //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(null); } DesignationDef haulUrgentlyDesignation = DefDatabase <DesignationDef> .GetNamed("HaulUrgentlyDesignation", false); // Misc. Robots compatibility // See https://github.com/catgirlfighter/RimWorld_CommonSense/blob/master/Source/CommonSense11/CommonSense/OpportunisticTasks.cs#L129-L140 if (pawn.TryGetComp <CompHauledToInventory>() == null) { return(null); } //This WorkGiver gets hijacked by AllowTool and expects us to urgently haul corpses. if (ModCompatibilityCheck.AllowToolIsActive && thing is Corpse && pawn.Map.designationManager.DesignationOn(thing)?.def == haulUrgentlyDesignation && HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } if (!GoodThingToHaul(thing, pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(null); } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true)) { //since we've gone through all the effort of getting the loc, might as well use it. //Don't multi-haul food to hoppers. if (thing.def.IsNutritionGivingIngestible) { if (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty) { List <Thing> thingList = storeCell.GetThingList(thing.Map); foreach (Thing t in thingList) { if (t.def == ThingDefOf.Hopper) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } } } } }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDespawnedNullOrForbidden(TargetIndex.A); this.FailOnBurningImmobile(TargetIndex.A); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch)); yield return(Toils_General.Wait(240).FailOnDestroyedNullOrForbidden(TargetIndex.A).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch).WithProgressBarToilDelay(TargetIndex.A, false, -0.5f)); yield return(new Toil { initAction = delegate { Building_Beehouse buildingbeehouse = (Building_Beehouse)this.job.GetTarget(TargetIndex.A).Thing; buildingbeehouse.BeehouseIsFull = false; Thing newComb = ThingMaker.MakeThing(DecideRandomComb()); GenSpawn.Spawn(newComb, buildingbeehouse.Position - GenAdj.CardinalDirections[0], buildingbeehouse.Map); StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(newComb); IntVec3 c; if (StoreUtility.TryFindBestBetterStoreCellFor(newComb, this.pawn, this.Map, currentPriority, this.pawn.Faction, out c, true)) { this.job.SetTarget(TargetIndex.C, c); this.job.SetTarget(TargetIndex.B, newComb); this.job.count = newComb.stackCount; buildingbeehouse.tickCounter = 0; } else { this.EndJobWith(JobCondition.Incompletable); buildingbeehouse.BeehouseIsFull = false; buildingbeehouse.tickCounter = 0; } }, defaultCompleteMode = ToilCompleteMode.Instant }); yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null)); yield return(Toils_Reserve.Reserve(TargetIndex.C, 1, -1, null)); yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch)); yield return(Toils_Haul.StartCarryThing(TargetIndex.B, false, false, false)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.C); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, carryToCell, true)); }
// Token: 0x0600002E RID: 46 RVA: 0x000035B0 File Offset: 0x000025B0 protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDespawnedNullOrForbidden(TargetIndex.A); this.FailOnBurningImmobile(TargetIndex.A); yield return(Toils_Reserve.Reserve(TargetIndex.A, 1, -1, null)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch)); yield return(Toils_General.Wait(200, TargetIndex.None).FailOnDestroyedNullOrForbidden(TargetIndex.A).FailOn(() => !this.Barrel.Distilled).WithProgressBarToilDelay(TargetIndex.A, false, -0.5f)); yield return(new Toil { initAction = delegate() { Thing thing = this.Barrel.TakeOutrawlucibatch(); GenPlace.TryPlaceThing(thing, this.pawn.Position, base.Map, ThingPlaceMode.Near, null, null); StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); IntVec3 c; if (StoreUtility.TryFindBestBetterStoreCellFor(thing, this.pawn, base.Map, currentPriority, this.pawn.Faction, out c, true)) { this.job.SetTarget(TargetIndex.C, c); this.job.SetTarget(TargetIndex.B, thing); this.job.count = thing.stackCount; } else { base.EndJobWith(JobCondition.Incompletable); } }, defaultCompleteMode = ToilCompleteMode.Instant }); yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null)); yield return(Toils_Reserve.Reserve(TargetIndex.C, 1, -1, null)); yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch)); yield return(Toils_Haul.StartCarryThing(TargetIndex.B, false, false, false)); Toil toil = Toils_Haul.CarryHauledThingToCell(TargetIndex.C); yield return(toil); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, toil, true)); yield break; }
// Token: 0x06000030 RID: 48 RVA: 0x00002C83 File Offset: 0x00000E83 protected override IEnumerable <Toil> MakeNewToils() { CompUniversalFermenter comp = ThingCompUtility.TryGetComp <CompUniversalFermenter>(this.Fermenter); ToilFailConditions.FailOn <JobDriver_TakeProductOutOfUniversalFermenter>(this, () => !comp.Fermented); ToilFailConditions.FailOnDestroyedNullOrForbidden <JobDriver_TakeProductOutOfUniversalFermenter>(this, (TargetIndex)1); yield return(Toils_Reserve.Reserve((TargetIndex)1, 1, -1, null)); yield return(Toils_Goto.GotoThing((TargetIndex)1, (PathEndMode)3)); yield return(ToilEffects.WithProgressBarToilDelay(ToilFailConditions.FailOnDestroyedNullOrForbidden <Toil>(Toils_General.Wait(200, 0), (TargetIndex)1), (TargetIndex)1, false, -0.5f)); yield return(new Toil { initAction = delegate() { Thing thing = comp.TakeOutProduct(); GenPlace.TryPlaceThing(thing, this.pawn.Position, this.Map, (ThingPlaceMode)1, null, null); StoragePriority storagePriority = StoreUtility.CurrentStoragePriorityOf(thing); IntVec3 intVec; if (StoreUtility.TryFindBestBetterStoreCellFor(thing, this.pawn, this.Map, storagePriority, this.pawn.Faction, out intVec, true)) { this.job.SetTarget((TargetIndex)2, thing); this.job.count = thing.stackCount; this.job.SetTarget((TargetIndex)3, intVec); return; } this.EndJobWith((JobCondition)3); }, defaultCompleteMode = (ToilCompleteMode)1 }); yield return(Toils_Reserve.Reserve((TargetIndex)2, 1, -1, null)); yield return(Toils_Reserve.Reserve((TargetIndex)3, 1, -1, null)); yield return(Toils_Goto.GotoThing((TargetIndex)2, (PathEndMode)3)); yield return(Toils_Haul.StartCarryThing((TargetIndex)2, false, false, false)); Toil carry = Toils_Haul.CarryHauledThingToCell((TargetIndex)3); yield return(carry); yield return(Toils_Haul.PlaceHauledThingInCell((TargetIndex)3, carry, true)); yield break; }
public static bool Prefix(Pawn pawn, Thing thing, ref Job __result) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true)) { SlotGroup slotGroup = StoreUtility.GetSlotGroup(storeCell, thing.Map); if (Limits.HasLimit(slotGroup.Settings)) { __result = HaulAIUtility.HaulToStorageJob(pawn, thing); return(false); } } return(true); }
public override bool HasJobOnThing(Pawn pawn, Thing thing, bool forced = false) { //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(false); } if (!GoodThingToHaul(thing, pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(false); } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); return(StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 _)); }
//pick up stuff until you can't anymore, //while you're up and about, pick up something and haul it //before you go out, empty your pockets public override Job JobOnThing(Pawn pawn, Thing thing, bool forced = false) { //bulky gear (power armor + minigun) so don't bother. if (MassUtility.GearMass(pawn) / MassUtility.Capacity(pawn) >= 0.8f) { return(null); } DesignationDef HaulUrgentlyDesignation = DefDatabase <DesignationDef> .GetNamed("HaulUrgentlyDesignation", false); //This WorkGiver gets hijacked by AllowTool and expects us to urgently haul corpses. if (ModCompatibilityCheck.AllowToolIsActive && thing is Corpse && pawn.Map.designationManager.DesignationOn(thing)?.def == HaulUrgentlyDesignation && HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } if (!GoodThingToHaul(thing, pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced)) { return(null); } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 storeCell, true)) { //since we've gone through all the effort of getting the loc, might as well use it. //Don't multi-haul food to hoppers. if (thing.def.IsNutritionGivingIngestible) { if (thing.def.ingestible.preferability == FoodPreferability.RawBad || thing.def.ingestible.preferability == FoodPreferability.RawTasty) { List <Thing> thingList = storeCell.GetThingList(thing.Map); for (int i = 0; i < thingList.Count; i++) { if (thingList[i].def == ThingDefOf.Hopper) { return(HaulAIUtility.HaulToStorageJob(pawn, thing)); } } } } }
// "Optimize hauling" public static Job HaulBeforeCarry(Pawn pawn, IntVec3 destCell, Thing thing) { if (thing.ParentHolder is Pawn_InventoryTracker) { return(null); } if (!JooStoreUtility.TryFindBestBetterStoreCellFor_ClosestToDestCell( thing, destCell, pawn, pawn.Map, StoreUtility.CurrentStoragePriorityOf(thing), pawn.Faction, out var storeCell, true)) { return(null); } var supplyFromHereDist = thing.Position.DistanceTo(destCell); var supplyFromStoreDist = storeCell.DistanceTo(destCell); // Debug.WriteLine($"Carry from here: {supplyFromHereDist}; carry from store: {supplyFromStoreDist}"); // [KV] Infinite Storage https://steamcommunity.com/sharedfiles/filedetails/?id=1233893175 // infinite storage has an interaction spot 1 tile away from itself if (supplyFromStoreDist + 1 < supplyFromHereDist) { // Debug.WriteLine( // $"'{pawn}' prefixed job with haul for '{thing.Label}' because '{storeCell.GetSlotGroup(pawn.Map)}' is closer to original destination '{destCell}'."); #if RELEASE if (DebugViewSettings.drawOpportunisticJobs) { #endif pawn.Map.debugDrawer.FlashLine(pawn.Position, thing.Position, 600, SimpleColor.White); // unchanged pawn.Map.debugDrawer.FlashLine(thing.Position, destCell, 600, SimpleColor.Magenta); pawn.Map.debugDrawer.FlashLine(thing.Position, storeCell, 600, SimpleColor.Cyan); pawn.Map.debugDrawer.FlashLine(storeCell, destCell, 600, SimpleColor.Cyan); #if RELEASE } #endif var haulTracker = HaulTracker.CreateAndAdd(SpecialHaulType.HaulBeforeCarry, pawn, destCell); return(PuahJob(haulTracker, pawn, thing, storeCell) ?? HaulAIUtility.HaulToCellStorageJob(pawn, thing, storeCell, false)); } return(null); }
public static Job HaulToStorageJob(Pawn p, Thing t) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(t); if (!StoreUtility.TryFindBestBetterStorageFor(t, p, p.Map, currentPriority, p.Faction, out IntVec3 foundCell, out IHaulDestination haulDestination)) { JobFailReason.Is(NoEmptyPlaceLowerTrans); return(null); } if (haulDestination is ISlotGroupParent) { return(HaulToCellStorageJob(p, t, foundCell, fitInStoreCell: false)); } Thing thing = haulDestination as Thing; if (thing != null && thing.TryGetInnerInteractableThingOwner() != null) { return(HaulToContainerJob(p, t, thing)); } Log.Error("Don't know how to handle HaulToStorageJob for storage " + haulDestination.ToStringSafe() + ". thing=" + t.ToStringSafe()); return(null); }
/// <summary> /// Make reservation for job targets before doing the job. /// </summary> /// <param name="errorOnFailed"> If true, log result as error if failed to make a reservation. </param> /// <returns> Returns true if a reservation is made. </returns> public override bool TryMakePreToilReservations(bool errorOnFailed) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(TargetThingA); if (!StoreUtility.TryFindBestBetterStorageFor(TargetThingA, pawn, pawn.Map, currentPriority, pawn.Faction, out IntVec3 foundCell, out IHaulDestination haulDestination)) { JobFailReason.Is(UIText.NoEmptyPlaceLower); Messages.Message( UIText.NoEmptyPlaceLower.TranslateSimple() , new TargetInfo(this.pawn.PositionHeld, this.pawn.MapHeld), MessageTypeDefOf.NeutralEvent); return(false); } this.Init(foundCell, haulDestination); if (pawn.Reserve(TargetB, this.job, 1, -1, null, errorOnFailed)) { return(pawn.Reserve(TargetA, this.job, 1, -1, null, errorOnFailed)); } return(false); }
public static bool TryGiveJob(ref Job __result, Pawn pawn) { int validationChecks = 0; int validatorFalses1 = 0; int validatorFalses2 = 0; int validatorFalses3 = 0; int validatorFalses4 = 0; Predicate <Thing> validator = delegate(Thing t) { validationChecks++; if (t.IsForbidden(pawn)) { validatorFalses1++; return(false); } if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t, forced: false)) { validatorFalses2++; return(false); } if (pawn.carryTracker.MaxStackSpaceEver(t.def) <= 0) { validatorFalses3++; return(false); } IntVec3 foundCell; bool tryFindBestBetterStoreCellFor = StoreUtility.TryFindBestBetterStoreCellFor(t, pawn, pawn.Map, StoreUtility.CurrentStoragePriorityOf(t), pawn.Faction, out foundCell) ? true : false; if (!tryFindBestBetterStoreCellFor) { validatorFalses4++; } return(tryFindBestBetterStoreCellFor); }; //Log.Error(pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling().Count.ToString()); Thing thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling(), PathEndMode.OnCell, TraverseParms.For(pawn), 9999f, validator); if (validationChecks > 10) { Log.Error("Validator Checks: " + validationChecks.ToString() + " " + validatorFalses1.ToString() + " " + validatorFalses2.ToString() + " " + validatorFalses3.ToString() + " " + validatorFalses4.ToString() + " "); } if (thing != null) { __result = HaulAIUtility.HaulToStorageJob(pawn, thing); return(false); } __result = null; return(false); }
// This is a janky mess and a half, but works! protected override Job TryGiveJob(Pawn pawn) { Pawn_SurvivalToolAssignmentTracker assignmentTracker = pawn.TryGetComp <Pawn_SurvivalToolAssignmentTracker>(); // Pawn can't use tools, lacks a tool assignment tracker or it isn't yet time to re-optimise tools if (!pawn.CanUseSurvivalTools() || assignmentTracker == null || Find.TickManager.TicksGame < assignmentTracker.nextSurvivalToolOptimizeTick) { return(null); } if (SurvivalToolsSettings.toolAutoDropExcess) { assignmentTracker.CheckToolsInUse(); // Check if current tool assignment allows for each tool, auto-removing those that aren't allowed. SurvivalToolAssignment curAssignment = assignmentTracker.CurrentSurvivalToolAssignment; List <SurvivalTool> heldTools = pawn.GetHeldSurvivalTools(); foreach (SurvivalTool tool in heldTools) { if ((!curAssignment.filter.Allows(tool) || !pawn.NeedsSurvivalTool(tool) || !tool.InUse) && !tool.Forced && StoreUtility.TryFindBestBetterStoreCellFor(tool, pawn, pawn.Map, StoreUtility.CurrentStoragePriorityOf(tool), pawn.Faction, out IntVec3 c)) { return(pawn.DequipAndTryStoreSurvivalTool(tool, true, c)); } } } if (SurvivalToolsSettings.toolOptimization) { SurvivalToolAssignment curAssignment = assignmentTracker.CurrentSurvivalToolAssignment; List <StatDef> workRelevantStats = pawn.AssignedToolRelevantWorkGiversStatDefs(); List <Thing> mapTools = pawn.MapHeld.listerThings.AllThings.Where(t => t is SurvivalTool).ToList(); SurvivalTool curTool = null; SurvivalTool newTool = null; float optimality = 0f; foreach (StatDef stat in workRelevantStats) { curTool = pawn.GetBestSurvivalTool(stat); optimality = SurvivalToolScore(curTool, workRelevantStats); foreach (SurvivalTool potentialTool in mapTools) { if (StatUtility.StatListContains(potentialTool.WorkStatFactors.ToList(), stat) && curAssignment.filter.Allows(potentialTool) && potentialTool.BetterThanWorkingToollessFor(stat) && pawn.CanUseSurvivalTool(potentialTool.def) && potentialTool.IsInAnyStorage() && !potentialTool.IsForbidden(pawn) && !potentialTool.IsBurning()) { float potentialOptimality = SurvivalToolScore(potentialTool, workRelevantStats); float delta = potentialOptimality - optimality; if (delta > 0f && pawn.CanReserveAndReach(potentialTool, PathEndMode.OnCell, pawn.NormalMaxDanger())) { newTool = potentialTool; optimality = potentialOptimality; } } } if (newTool != null) { break; } } // Return a job based on whether or not a better tool was located // Failure if (newTool == null) { SetNextOptimizeTick(pawn); return(null); } // Success int heldToolOffset = 0; if (curTool != null && !curTool.Forced) { pawn.jobs.jobQueue.EnqueueFirst(pawn.DequipAndTryStoreSurvivalTool(curTool, false)); heldToolOffset = -1; } if (pawn.CanCarryAnyMoreSurvivalTools(heldToolOffset)) { Job pickupJob = new Job(JobDefOf.TakeInventory, newTool) { count = 1 }; return(pickupJob); } } // Final failure state SetNextOptimizeTick(pawn); return(null); }
public static void RegisterHaulableItem(Thing haulableThing) { Map map = haulableThing.Map; if (map == null) { return; } if (haulableThing.IsForbidden(Faction.OfPlayer)) { return; } //---SHOULD HELP WITH NOT HAULING ROCK CHUNKS--- if (!haulableThing.def.EverHaulable) { return; } if (!haulableThing.def.alwaysHaulable && (map.designationManager.DesignationOn(haulableThing, DesignationDefOf.Haul) == null)) { return; } //---SHOULD HELP WITH NOT HAULING ROCK CHUNKS--- int num = haulableThing.stackCount; int maxPawns = 1; if (map.physicalInteractionReservationManager.IsReserved(haulableThing)) { //Log.Warning("IsReserved"); return; } List <Reservation> reservations = ReservationManager_Patch.getReservationTargetList(map.reservationManager, haulableThing); if (reservations != null && reservations.Count > 0) { return; } int num3 = 0; int num4 = 0; List <Reservation> reservationTargetList = ReservationManager_Patch.getReservationTargetList(map.reservationManager, haulableThing); foreach (Reservation reservation in reservationTargetList) { if (reservation.Layer == null) { if (reservation.Claimant != null && (reservation.StackCount == -1 || reservation.StackCount >= num)) { break; } if (reservation.Claimant != null) { if (reservation.MaxPawns != maxPawns) { //Log.Warning("maxPawns"); return; } num3++; num4 = (reservation.StackCount != -1) ? (num4 + reservation.StackCount) : (num4 + num); if (num3 >= maxPawns || num + num4 > num) { //Log.Warning(reservation.Claimant.ToString() + " StackCount"); return; } } } } int storagePriority = (int)StoreUtility.CurrentStoragePriorityOf(haulableThing); if (TryFindBestBetterStoreCellFor(haulableThing, null, map, StoreUtility.CurrentStoragePriorityOf(haulableThing), null, out _, false) && //fast check HaulToStorageJobTest(haulableThing)) //slower check { AddThingToAwaitingHaulingHashSets(haulableThing); } else { HashSet <Thing> things = getWaitingForZoneBetterThan(map)[storagePriority]; lock (things) { things.Add(haulableThing); } } }
static ProximityStage CanHaul(ProximityStage proximityStage, Pawn pawn, Thing thing, IntVec3 jobCell, ProximityCheck proximityCheck, out IntVec3 storeCell) { storeCell = IntVec3.Invalid; var pawnToJob = pawn.Position.DistanceTo(jobCell); var pawnToThing = pawn.Position.DistanceTo(thing.Position); if (proximityStage < ProximityStage.StoreToJob) { var atMax = maxStartToThing.Value > 0 && pawnToThing > maxStartToThing.Value; var atMaxPct = maxStartToThingPctOrigTrip.Value > 0 && pawnToThing > pawnToJob * maxStartToThingPctOrigTrip.Value; var pawnToThingFail = atMax || atMaxPct; switch (proximityCheck) { case ProximityCheck.Both when pawnToThingFail: return(ProximityStage.PawnToThing); } var thingToJob = thing.Position.DistanceTo(jobCell); // if this one exceeds the maximum the next maxTotalTripPctOrigTrip check certainly will if (maxTotalTripPctOrigTrip.Value > 0 && pawnToThing + thingToJob > pawnToJob * maxTotalTripPctOrigTrip.Value) { return(ProximityStage.Fail); } if (pawn.Map.reservationManager.FirstRespectedReserver(thing, pawn) != null) { return(ProximityStage.Fail); } if (thing.IsForbidden(pawn)) { return(ProximityStage.Fail); } if (!HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, false)) { return(ProximityStage.Fail); } } // we need storeCell everywhere, so cache it if (!cachedStoreCell.TryGetValue(thing, out storeCell)) { var currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); if (!StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out storeCell)) { return(ProximityStage.Fail); } } cachedStoreCell.SetOrAdd(thing, storeCell); var storeToJob = storeCell.DistanceTo(jobCell); if (proximityStage < ProximityStage.PawnToThingRegion) { var atMax2 = maxStoreToJob.Value > 0 && storeToJob > maxStoreToJob.Value; var atMaxPct2 = maxStoreToJobPctOrigTrip.Value > 0 && storeToJob > pawnToJob * maxStoreToJobPctOrigTrip.Value; var storeToJobFail = atMax2 || atMaxPct2; switch (proximityCheck) { case ProximityCheck.Both when storeToJobFail: return(ProximityStage.StoreToJob); case ProximityCheck.Either when proximityStage == ProximityStage.PawnToThing && storeToJobFail: return(ProximityStage.StoreToJob); } var thingToStore = thing.Position.DistanceTo(storeCell); if (maxTotalTripPctOrigTrip.Value > 0 && pawnToThing + thingToStore + storeToJob > pawnToJob * maxTotalTripPctOrigTrip.Value) { return(ProximityStage.Fail); } if (maxNewLegsPctOrigTrip.Value > 0 && pawnToThing + storeToJob > pawnToJob * maxNewLegsPctOrigTrip.Value) { return(ProximityStage.Fail); } } bool PawnToThingRegionFail() { return(maxStartToThingRegionLookCount.Value > 0 && !pawn.Position.WithinRegions(thing.Position, pawn.Map, maxStartToThingRegionLookCount.Value, TraverseParms.For(pawn))); } bool StoreToJobRegionFail(IntVec3 _storeCell) { return(maxStoreToJobRegionLookCount.Value > 0 && !_storeCell.WithinRegions(jobCell, pawn.Map, maxStoreToJobRegionLookCount.Value, TraverseParms.For(pawn))); } switch (proximityCheck) { case ProximityCheck.Both when PawnToThingRegionFail(): return(ProximityStage.PawnToThingRegion); case ProximityCheck.Both when StoreToJobRegionFail(storeCell): return(ProximityStage.Fail); case ProximityCheck.Either when proximityStage == ProximityStage.PawnToThingRegion && StoreToJobRegionFail(storeCell): return(ProximityStage.Fail); } return(ProximityStage.Success); }
/// <inheritdoc/> public override ThinkResult TryIssueJobPackage(Pawn pawn, JobIssueParams jobParams) { if (pawn?.inventory?.innerContainer == null) { return(ThinkResult.NoJob); } if (!pawn.UseLoadout(out CompAwesomeInventoryLoadout comp)) { return(ThinkResult.NoJob); } foreach (Thing thing in pawn.inventory.innerContainer) { if (thing is Apparel apparel) { bool extra = true; CompAwesomeInventoryLoadout.ThingGroupSelectorPool pool = comp.FindPotentialThingGroupSelectors(thing, comp.Loadout); if (pool.OrderedSelectorTuples.Any()) { foreach (var tuple in pool.OrderedSelectorTuples) { if (!(comp.InventoryMargins[tuple.Item2] > 0)) { extra = false; break; } } } if (extra) { if (StoreUtility.TryFindBestBetterStorageFor(apparel, pawn, pawn.Map, StoreUtility.CurrentStoragePriorityOf(apparel), pawn.Faction, out _, out _)) { UnloadApparelJob job = new UnloadApparelJob(thing); return(new ThinkResult(job, this, JobTag.UnloadingOwnInventory)); } } } } return(ThinkResult.NoJob); }
public Job TryOpportunisticJob(Job job) { Job result; if (this.pawn.def.race.intelligence < Intelligence.Humanlike) { result = null; } else if (this.pawn.Faction != Faction.OfPlayer) { result = null; } else if (this.pawn.Drafted) { result = null; } else if (job.playerForced) { result = null; } else if (this.pawn.RaceProps.intelligence < Intelligence.Humanlike) { result = null; } else if (!job.def.allowOpportunisticPrefix) { result = null; } else if (this.pawn.story.WorkTagIsDisabled(WorkTags.ManualDumb | WorkTags.Hauling)) { result = null; } else if (this.pawn.InMentalState) { result = null; } else { IntVec3 cell = job.targetA.Cell; if (!cell.IsValid) { result = null; } else { float num = this.pawn.Position.DistanceTo(cell); if (num < AITuning.OpportunisticJobMinDistPawnToDest) { result = null; } else { List <Thing> list = this.pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling(); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; if (this.pawn.Map.reservationManager.FirstRespectedReserver(thing, this.pawn) == null) { float num2 = this.pawn.Position.DistanceTo(thing.Position); if (num2 <= AITuning.OpportunisticJobMaxDistPawnToItem) { if (num2 <= num * AITuning.OpportunisticJobMaxPickupDistanceFactor) { if (num2 + thing.Position.DistanceTo(cell) <= num * AITuning.OpportunisticJobMaxRatioOppHaulDistanceToDestDistance) { if (HaulAIUtility.PawnCanAutomaticallyHaulFast(this.pawn, thing, false)) { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); IntVec3 invalid = IntVec3.Invalid; if (StoreUtility.TryFindBestBetterStoreCellFor(thing, this.pawn, this.pawn.Map, currentPriority, this.pawn.Faction, out invalid, true)) { float num3 = invalid.DistanceTo(cell); if (num3 <= AITuning.OpportunisticJobMaxDistDestToDropoff) { if (num3 <= num * AITuning.OpportunisticJobMaxDistDestToDropoffFactor) { if (num2 + thing.Position.DistanceTo(invalid) + num3 <= num * AITuning.OpportunisticJobMaxRatioOppHaulDistanceToDestDistance) { if (num2 + num3 <= num) { if (this.pawn.Position.WithinRegions(thing.Position, this.pawn.Map, AITuning.OpportunisticJobMaxPickupRegions, TraverseParms.For(this.pawn, Danger.Deadly, TraverseMode.ByPawn, false), RegionType.Set_Passable)) { if (invalid.WithinRegions(cell, this.pawn.Map, AITuning.OpportunisticJobMaxDropoffRegions, TraverseParms.For(this.pawn, Danger.Deadly, TraverseMode.ByPawn, false), RegionType.Set_Passable)) { if (DebugViewSettings.drawOpportunisticJobs) { Log.Message("Opportunistic job spawned", false); this.pawn.Map.debugDrawer.FlashLine(this.pawn.Position, thing.Position, 600, SimpleColor.Red); this.pawn.Map.debugDrawer.FlashLine(thing.Position, invalid, 600, SimpleColor.Green); this.pawn.Map.debugDrawer.FlashLine(invalid, cell, 600, SimpleColor.Blue); } return(HaulAIUtility.HaulToCellStorageJob(this.pawn, thing, invalid, false)); } } } } } } } } } } } } } result = null; } } } return(result); }
// Token: 0x0600005B RID: 91 RVA: 0x00004104 File Offset: 0x00002304 protected override IEnumerable <Toil> MakeNewToils() { var toilSwapback = new Toil(); var toilReturnStock = new Toil(); var toilDrop = new Toil(); var toilDropHome = new Toil(); Thing resultingThing = null; var FETakeBack = (ThingWithComps)job.GetTarget(TargetIndex.A).Thing; var FETBSwapType = (FETakeBack as FireWardenData)?.FWSwapType; var DebugMsg = ""; toilSwapback.initAction = delegate { if (!FWHasFE(pawn) || resultingThing == null) { return; } if (FWDebug) { DebugMsg = pawn.Label + " in toil Swapback"; Messages.Message(DebugMsg, pawn, MessageTypeDefOf.NeutralEvent, false); } if (job.GetTarget(TargetIndex.B) != null) { var RemoveThing = job.GetTarget(TargetIndex.B).Thing; var invGearToEquip = (ThingWithComps)RemoveThing; if (pawn.inventory.innerContainer.Contains(RemoveThing) && pawn.equipment.Primary != invGearToEquip) { pawn.inventory.innerContainer.Remove(RemoveThing); pawn.equipment.MakeRoomFor(invGearToEquip); pawn.equipment.AddEquipment(invGearToEquip); } } FETakeBack = (ThingWithComps)job.GetTarget(TargetIndex.A).Thing; FEResetVars(FETakeBack); FETBSwapType = (FETakeBack as FireWardenData)?.FWSwapType; pawn.jobs.EndCurrentJob(JobCondition.Succeeded); }; toilSwapback.AddFailCondition(() => FETBSwapType != "ER"); toilSwapback.FailOnDespawnedOrNull(TargetIndex.A); toilSwapback.FailOnDespawnedOrNull(TargetIndex.B); toilSwapback.defaultCompleteMode = ToilCompleteMode.Delay; yield return(toilSwapback); if (pawn.equipment.Primary == null || pawn.equipment.Primary.def.defName != FEDefName || (pawn.equipment.Primary as FireWardenData)?.FWSwapType != "ER" || ((FireWardenData)pawn.equipment.Primary).FWPawnID != pawn.thingIDNumber) { yield break; } var currentPriority = StoreUtility.CurrentStoragePriorityOf(job.GetTarget(TargetIndex.A).Thing); var dumpAtHome = false; if (Controller.Settings.ReturnToSpot) { dumpAtHome = true; } else { if (pawn.equipment.Primary == (ThingWithComps)job.GetTarget(TargetIndex.A).Thing) { pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out _, pawn.Position, false); pawn.carryTracker.TryStartCarry(job.GetTarget(TargetIndex.A).Thing, 1); } if (!StoreUtility.TryFindBestBetterStorageFor(job.GetTarget(TargetIndex.A).Thing, pawn, pawn.Map, currentPriority, pawn.Faction, out _, out var haulDestination)) { dumpAtHome = true; } else { toilReturnStock.initAction = delegate { if (FWDebug) { DebugMsg = pawn.Label + " in toil ReturnStock"; Messages.Message(DebugMsg, pawn, MessageTypeDefOf.NeutralEvent, false); } if (pawn.carryTracker.CarriedThing != job.GetTarget(TargetIndex.A).Thing) { return; } var destCell = haulDestination.Position; pawn.Map.pawnDestinationReservationManager.Reserve(pawn, job, destCell); pawn.pather.StartPath(destCell, PathEndMode.ClosestTouch); }; toilReturnStock.AddFailCondition(() => FETBSwapType != "ER"); toilReturnStock.FailOnDespawnedOrNull(TargetIndex.A); toilReturnStock.defaultCompleteMode = ToilCompleteMode.PatherArrival; yield return(toilReturnStock); toilDrop.initAction = delegate { if (!((haulDestination.Position - pawn.Position).LengthHorizontal <= 2f)) { return; } if (pawn.carryTracker.CarriedThing == job.GetTarget(TargetIndex.A).Thing) { if (!pawn.carryTracker.TryDropCarriedThing(pawn.Position, ThingPlaceMode.Near, out resultingThing)) { return; } dumpAtHome = false; if (job.GetTarget(TargetIndex.B) != null) { return; } FETakeBack = (ThingWithComps)job.GetTarget(TargetIndex.A).Thing; FEResetVars(FETakeBack); FETBSwapType = (FETakeBack as FireWardenData)?.FWSwapType; pawn.jobs.EndCurrentJob(JobCondition.Succeeded); } else { dumpAtHome = true; } }; toilSwapback.AddFailCondition(() => FETBSwapType != "ER"); toilDrop.FailOnDespawnedOrNull(TargetIndex.A); toilDrop.defaultCompleteMode = ToilCompleteMode.FinishedBusy; yield return(toilDrop); } } if (!dumpAtHome) { yield break; } var ReturnCell = pawn.Position; // if (false) // { // /* // { // toilReturnHome.initAction = delegate // { // if (FWDebug) // { // DebugMsg = pawn.Label + " in toil ReturnHome"; // Messages.Message(DebugMsg, pawn, MessageTypeDefOf.NeutralEvent, false); // } // if (pawn.equipment.Primary == (ThingWithComps)job.GetTarget(TargetIndex.A).Thing) // { // pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out _, pawn.Position, false); // pawn.carryTracker.TryStartCarry(job.GetTarget(TargetIndex.A).Thing, 1); // } // // if (pawn.carryTracker.CarriedThing != job.GetTarget(TargetIndex.A).Thing) // { // return; // } // // pawn.Map.pawnDestinationReservationManager.Reserve(pawn, job, ReturnCell); // pawn.pather.StartPath(ReturnCell, PathEndMode.ClosestTouch); // }; // toilReturnHome.AddFailCondition(() => FETBSwapType != "ER"); // toilReturnHome.FailOnDespawnedOrNull(TargetIndex.A); // toilReturnHome.defaultCompleteMode = ToilCompleteMode.PatherArrival; // yield return toilReturnHome; // } // */ // } if (pawn.equipment.Primary == (ThingWithComps)job.GetTarget(TargetIndex.A).Thing) { pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out _, pawn.Position, false); pawn.carryTracker.TryStartCarry(job.GetTarget(TargetIndex.A).Thing, 1); } toilDropHome.initAction = delegate { if (!((ReturnCell - pawn.Position).LengthHorizontal <= 2f) || pawn.carryTracker.CarriedThing != job.GetTarget(TargetIndex.A).Thing || !pawn.carryTracker.TryDropCarriedThing(pawn.Position, ThingPlaceMode.Near, out resultingThing) || job.GetTarget(TargetIndex.B) != null) { return; } FETakeBack = (ThingWithComps)job.GetTarget(TargetIndex.A).Thing; FEResetVars(FETakeBack); FETBSwapType = (FETakeBack as FireWardenData)?.FWSwapType; pawn.jobs.EndCurrentJob(JobCondition.Succeeded); }; toilDropHome.AddFailCondition(() => FETBSwapType != "ER"); toilDropHome.FailOnDespawnedOrNull(TargetIndex.A); toilDropHome.defaultCompleteMode = ToilCompleteMode.FinishedBusy; yield return(toilDropHome); }
public Job TryOpportunisticJob(Job job) { if ((int)pawn.def.race.intelligence < 2) { return(null); } if (pawn.Faction != Faction.OfPlayer) { return(null); } if (pawn.Drafted) { return(null); } if (job.playerForced) { return(null); } if ((int)pawn.RaceProps.intelligence < 2) { return(null); } if (!job.def.allowOpportunisticPrefix) { return(null); } if (pawn.WorkTagIsDisabled(WorkTags.ManualDumb | WorkTags.Hauling)) { return(null); } if (pawn.InMentalState || pawn.IsBurning()) { return(null); } IntVec3 cell = job.targetA.Cell; if (!cell.IsValid || cell.IsForbidden(pawn)) { return(null); } float num = pawn.Position.DistanceTo(cell); if (num < 3f) { return(null); } List <Thing> list = pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling(); for (int i = 0; i < list.Count; i++) { Thing thing = list[i]; float num2 = pawn.Position.DistanceTo(thing.Position); if (num2 > 30f || num2 > num * 0.5f || num2 + thing.Position.DistanceTo(cell) > num * 1.7f || pawn.Map.reservationManager.FirstRespectedReserver(thing, pawn) != null || thing.IsForbidden(pawn) || !HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, thing, forced: false)) { continue; } StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(thing); IntVec3 foundCell = IntVec3.Invalid; if (!StoreUtility.TryFindBestBetterStoreCellFor(thing, pawn, pawn.Map, currentPriority, pawn.Faction, out foundCell)) { continue; } float num3 = foundCell.DistanceTo(cell); if (!(num3 > 50f) && !(num3 > num * 0.6f) && !(num2 + thing.Position.DistanceTo(foundCell) + num3 > num * 1.7f) && !(num2 + num3 > num) && pawn.Position.WithinRegions(thing.Position, pawn.Map, 25, TraverseParms.For(pawn)) && foundCell.WithinRegions(cell, pawn.Map, 25, TraverseParms.For(pawn))) { if (DebugViewSettings.drawOpportunisticJobs) { Log.Message("Opportunistic job spawned"); pawn.Map.debugDrawer.FlashLine(pawn.Position, thing.Position, 600, SimpleColor.Red); pawn.Map.debugDrawer.FlashLine(thing.Position, foundCell, 600, SimpleColor.Green); pawn.Map.debugDrawer.FlashLine(foundCell, cell, 600, SimpleColor.Blue); } return(HaulAIUtility.HaulToCellStorageJob(pawn, thing, foundCell, fitInStoreCell: false)); } } return(null); }
private Toil Collect() { return(new Toil() { initAction = delegate { // Increment the record for how many cells this pawn has mined since this counts as mining // TODO: B19 - change to quarry m3 pawn.records.Increment(RecordDefOf.CellsMined); // Start with None to act as a fallback. Rubble will be returned with this parameter ResourceRequest req = ResourceRequest.None; // Use the mineModeToggle to determine the request req = (ResourceRequest)(((int)Quarry.mineModeToggle) + 1); MoteType mote = MoteType.None; int stackCount = 1; // Get the resource from the quarry ThingDef def = Quarry.GiveResources(req, out mote, out bool singleSpawn, out bool eventTriggered); // If something went wrong, bail out if (def == null || def.thingClass == null) { Log.Warning("Quarry:: Tried to quarry mineable ore, but the ore given was null."); mote = MoteType.None; singleSpawn = true; // This shouldn't happen at all, but if it does let's add a little reward instead of just giving rubble def = ThingDefOf.ChunkSlagSteel; } Thing haulableResult = ThingMaker.MakeThing(def); if (!singleSpawn && def != ThingDefOf.ComponentIndustrial) { int sub = (int)(def.BaseMarketValue / 2f); sub = Mathf.Clamp(sub, 0, 10); stackCount += Mathf.Min(Rand.RangeInclusive(15 - sub, 40 - (sub * 2)), def.stackLimit - 1); } if (def == ThingDefOf.ComponentIndustrial) { stackCount += Random.Range(0, 1); } haulableResult.stackCount = stackCount; if (stackCount >= 30) { mote = MoteType.LargeVein; } bool usesQuality = false; // Adjust quality for items that use it if (haulableResult.TryGetComp <CompQuality>() != null) { usesQuality = true; haulableResult.TryGetComp <CompQuality>().SetQuality(QualityUtility.GenerateQualityTraderItem(), ArtGenerationContext.Outsider); } // Adjust hitpoints, this was just mined from under the ground after all if (def.useHitPoints && !def.thingCategories.Contains(QuarryDefOf.StoneChunks) && def != ThingDefOf.ComponentIndustrial) { float minHpThresh = 0.25f; if (usesQuality) { minHpThresh = Mathf.Clamp((float)haulableResult.TryGetComp <CompQuality>().Quality / 10f, 0.1f, 0.7f); } int hp = Mathf.RoundToInt(Rand.Range(minHpThresh, 1f) * haulableResult.MaxHitPoints); hp = Mathf.Max(1, hp); haulableResult.HitPoints = hp; } // Place the resource near the pawn GenPlace.TryPlaceThing(haulableResult, pawn.Position, Map, ThingPlaceMode.Near); // If the resource had a mote, throw it if (mote == MoteType.LargeVein) { MoteMaker.ThrowText(haulableResult.DrawPos, Map, Static.TextMote_LargeVein, Color.green, 3f); } else if (mote == MoteType.Failure) { MoteMaker.ThrowText(haulableResult.DrawPos, Map, Static.TextMote_MiningFailed, Color.red, 3f); } // If the sinkhole event was triggered, damage the pawn and end this job // Even if the sinkhole doesn't incapacitate the pawn, they will probably want to seek medical attention if (eventTriggered) { NamedArgument pawnName = new NamedArgument(0, pawn.NameShortColored); Messages.Message("QRY_MessageSinkhole".Translate(pawnName), pawn, MessageTypeDefOf.NegativeEvent); DamageInfo dInfo = new DamageInfo(DamageDefOf.Crush, 9, category: DamageInfo.SourceCategory.Collapse); dInfo.SetBodyRegion(BodyPartHeight.Bottom, BodyPartDepth.Inside); pawn.TakeDamage(dInfo); EndJobWith(JobCondition.Succeeded); } else { // Prevent the colonists from trying to haul rubble, which just makes them visit the platform if (def == ThingDefOf.Filth_RubbleRock) { EndJobWith(JobCondition.Succeeded); } else { // If this is a chunk or slag, mark it as haulable if allowed to if (def.designateHaulable && Quarry.autoHaul) { Map.designationManager.AddDesignation(new Designation(haulableResult, DesignationDefOf.Haul)); } // Try to find a suitable storage spot for the resource, removing it from the quarry // If there are no platforms with free space, or if the resource is a chunk, try to haul it to a storage area if (Quarry.autoHaul) { if (!def.thingCategories.Contains(QuarryDefOf.StoneChunks) && Quarry.HasConnectedPlatform && Quarry.TryFindBestPlatformCell(haulableResult, pawn, Map, pawn.Faction, out IntVec3 c)) { job.SetTarget(TargetIndex.B, haulableResult); job.count = haulableResult.stackCount; job.SetTarget(TargetIndex.C, c); } else { StoragePriority currentPriority = StoreUtility.CurrentStoragePriorityOf(haulableResult); Job result; if (!StoreUtility.TryFindBestBetterStorageFor(haulableResult, pawn, Map, currentPriority, pawn.Faction, out c, out IHaulDestination haulDestination, true)) { JobFailReason.Is("NoEmptyPlaceLower".Translate(), null); } else if (haulDestination is ISlotGroupParent) { result = HaulAIUtility.HaulToCellStorageJob(pawn, haulableResult, c, false); } else { job.SetTarget(TargetIndex.B, haulableResult); job.count = haulableResult.stackCount; job.SetTarget(TargetIndex.C, c); } } }
private bool HasNoHaulDestination(Thing t) { return(!StoreUtility.TryFindBestBetterStorageFor(t, null, t.Map, StoreUtility.CurrentStoragePriorityOf(t), Faction.OfPlayer, out IntVec3 _, out IHaulDestination _)); }
protected override IEnumerable <Toil> MakeNewToils() { CompUniversalFermenter comp = Fermenter.TryGetComp <CompUniversalFermenter>(); // Verify fermenter validity this.FailOn(() => !comp.Fermented); this.FailOnDestroyedNullOrForbidden(FermenterInd); // Reserve fermenter yield return(Toils_Reserve.Reserve(FermenterInd)); // Go to the fermenter yield return(Toils_Goto.GotoThing(FermenterInd, PathEndMode.ClosestTouch)); // Add delay for collecting product from fermenter, if it is ready yield return(Toils_General.Wait(Duration).FailOnDestroyedNullOrForbidden(FermenterInd).WithProgressBarToilDelay(FermenterInd)); // Collect product Toil collect = new Toil(); collect.initAction = () => { Thing product = comp.TakeOutProduct(); GenPlace.TryPlaceThing(product, pawn.Position, Map, ThingPlaceMode.Near); StoragePriority storagePriority = StoreUtility.CurrentStoragePriorityOf(product); IntVec3 c; // Try to find a suitable storage spot for the product if (StoreUtility.TryFindBestBetterStoreCellFor(product, pawn, Map, storagePriority, pawn.Faction, out c)) { this.job.SetTarget(TargetIndex.B, product); this.job.count = product.stackCount; this.job.SetTarget(TargetIndex.C, c); } // If there is no spot to store the product, end this job else { EndJobWith(JobCondition.Incompletable); } }; collect.defaultCompleteMode = ToilCompleteMode.Instant; yield return(collect); // Reserve the product yield return(Toils_Reserve.Reserve(ProductToHaulInd)); // Reserve the storage cell yield return(Toils_Reserve.Reserve(StorageCellInd)); // Go to the product yield return(Toils_Goto.GotoThing(ProductToHaulInd, PathEndMode.ClosestTouch)); // Pick up the product yield return(Toils_Haul.StartCarryThing(ProductToHaulInd)); // Carry the product to the storage cell, then place it down Toil carry = Toils_Haul.CarryHauledThingToCell(StorageCellInd); yield return(carry); yield return(Toils_Haul.PlaceHauledThingInCell(StorageCellInd, carry, true)); // End the current job yield break; }