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); }
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() { this.FailOnDespawnedNullOrForbidden(TargetIndex.A); this.FailOnDestroyedOrNull(TargetIndex.A); yield return(Toils_Reserve.Reserve(TargetIndex.A)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell)); yield return(Toils_General.WaitWith(TargetIndex.A, 200, true)); yield return(new Toil() { initAction = delegate() { Building_GrowerBase grower = TargetThingA as Building_GrowerBase; if (grower != null) { Pawn actor = GetActor(); Thing product = grower.ExtractProduct(actor); if (!product.Spawned) { GenPlace.TryPlaceThing(product, grower.InteractionCell, grower.Map, ThingPlaceMode.Near); } if (product is Pawn) { EndJobWith(JobCondition.Succeeded); } else { //job.SetTarget(TargetIndex.B, product); IntVec3 storeCell; IHaulDestination haulDestination; if (StoreUtility.TryFindBestBetterStorageFor(product, actor, product.Map, StoragePriority.Unstored, actor.Faction, out storeCell, out haulDestination, false)) { if (storeCell.IsValid || haulDestination != null) { actor.jobs.StartJob(HaulAIUtility.HaulToStorageJob(actor, product), JobCondition.Succeeded); } } } } } }); }
/// <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 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); }
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 _)); }
// 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); }