protected override IEnumerable <Toil> MakeNewToils() { List <Toil> toilsList = new List <Toil>(); Building_Pyre pyre = this.TargetThingA as Building_Pyre; bool beerIsAvailable = false; if (this.pawn.Position.InHorDistOf(pyre.Position, Building_Pyre.partyAreaRadius) == false) { // Go around pyre. toilsList.Add(base.ToilGetWanderCell(pyre.Position)); Find.PawnDestinationManager.ReserveDestinationFor(this.pawn, this.CurJob.targetB.Cell); toilsList.Add(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.OnCell)); // Release cell (the pawn will either go grab a beer or move on the next job). toilsList.Add(base.ToilReleaseCell()); } // Look for an available beer. List <Thing> list = Find.ListerThings.ThingsOfDef(ThingDefOf.Beer); if (list.Count > 0) { Predicate <Thing> validator = (Thing t) => pawn.CanReserve(t, 1) && !t.IsForbidden(pawn); Thing beer = GenClosest.ClosestThing_Global_Reachable(pyre.Position, list, PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), Building_Pyre.beerSearchAreaRadius, validator, null); if (beer != null) { beerIsAvailable = true; this.CurJob.SetTarget(TargetIndex.A, beer); //this.CurJob.targetA = beer; this.CurJob.maxNumToCarry = 1; toilsList.Add(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A)); toilsList.Add(Toils_Ingest.PickupIngestible(TargetIndex.A, this.pawn)); // TargetIndex.A becomes the carried beer. toilsList.Add(Toils_Ingest.CarryIngestibleToChewSpot(this.pawn)); toilsList.Add(Toils_Ingest.FindAdjacentEatSurface(TargetIndex.B, TargetIndex.A)); // float durationMultiplier = 1f / this.pawn.GetStatValue(StatDefOf.EatingSpeed, true); // Don't use it so the job duration is nearly the same for all pawns. float durationMultiplier = 1f; toilsList.Add(Toils_Ingest.ChewIngestible(this.pawn, durationMultiplier, TargetIndex.A, TargetIndex.B).FailOn((Toil x) => !this.Food.Spawned && (this.pawn.carrier == null || this.pawn.carrier.CarriedThing != this.Food))); toilsList.Add(Toils_Ingest.FinalizeIngest(this.pawn, TargetIndex.A)); } } // Draw a mote. ThingDef moteDef = null; if (beerIsAvailable) { moteDef = Util_CampfireParty.Mote_BeerAvailable; } else { moteDef = Util_CampfireParty.Mote_BeerUnavailable; } MoteAttached moteAttached = (MoteAttached)ThingMaker.MakeThing(moteDef); moteAttached.AttachTo(this.pawn); GenSpawn.Spawn(moteAttached, this.pawn.Position); return(toilsList); }
internal static IEnumerable <Toil> _MakeNewToils(this JobDriver_FoodFeedPatient obj) { var foodThing = obj.TargetThing(FoodInd); var deliveree = (Pawn)obj.TargetThing(DelivereeInd); obj.FailOnDespawnedNullOrForbidden(DelivereeInd); obj.FailOn(() => { return(!FoodUtility.ShouldBeFedBySomeone(deliveree)); }); yield return(Toils_Reserve.Reserve(DelivereeInd, 1)); if (foodThing is Building) { yield return(Toils_Reserve.Reserve(FoodInd, 1)); yield return(Toils_Goto.GotoThing(FoodInd, PathEndMode.InteractionCell).FailOnForbidden(FoodInd)); if (foodThing is Building_NutrientPasteDispenser) { yield return(Toils_Ingest.TakeMealFromDispenser(FoodInd, obj.pawn)); } else if (foodThing is Building_AutomatedFactory) { yield return(Toils_FoodSynthesizer.TakeMealFromSynthesizer(FoodInd, obj.pawn)); } else // Unknown building { throw new Exception("Food target for JobDriver_FoodDeliver is a building but not Building_NutrientPasteDispenser or Building_AutomatedFactory!"); } } else if ( (obj.pawn.inventory != null) && (obj.pawn.inventory.Contains(foodThing)) ) { yield return(Toils_Misc.TakeItemFromInventoryToCarrier(obj.pawn, FoodInd)); } else { yield return(Toils_Reserve.Reserve(FoodInd, 1)); yield return(Toils_Goto.GotoThing(FoodInd, PathEndMode.ClosestTouch).FailOnForbidden(FoodInd)); yield return(Toils_Ingest.PickupIngestible(FoodInd, deliveree)); } yield return(Toils_Goto.GotoThing(DelivereeInd, PathEndMode.Touch)); yield return(Toils_Ingest.ChewIngestible(deliveree, FeedDurationMultiplier, FoodInd)); yield return(Toils_Ingest.FinalizeIngest(deliveree, FoodInd)); }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOn(() => !IngestibleSource.Destroyed && !IngestibleSource.IngestibleNow); Toil chew = Toils_Ingest.ChewIngestible(pawn, ChewDurationMultiplier, TargetIndex.A, TargetIndex.None).FailOn((Toil x) => !IngestibleSource.Spawned && (pawn.carryTracker == null || pawn.carryTracker.CarriedThing != IngestibleSource)).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); foreach (Toil toil in PrepareToIngestToils()) { yield return(toil); } yield return(chew); yield return(Toils_Ingest.FinalizeIngest(pawn, TargetIndex.A)); }
private IEnumerable <Toil> Nibble() { Toil gotoCorpse = Toils_Goto.GotoThing(CorpseInd, PathEndMode.Touch); yield return(gotoCorpse); float durationMultiplier = 1f / this.pawn.GetStatValue(StatDefOf.EatingSpeed, true); yield return(Toils_Ingest.ChewIngestible(this.pawn, durationMultiplier, CorpseInd, TargetIndex.None).FailOnDespawnedOrNull(CorpseInd).FailOnCannotTouch(CorpseInd, PathEndMode.Touch)); yield return(Toils_Ingest.FinalizeIngest(this.pawn, CorpseInd)); yield return(Toils_Jump.JumpIf(gotoCorpse, () => this.pawn.needs.food.CurLevelPercentage < 0.9f)); }
protected override IEnumerable <Toil> MakeNewToils() { if (this.pawn.inventory != null && this.pawn.inventory.Contains(base.TargetThingA)) { yield return(Toils_Misc.TakeItemFromInventoryToCarrier(this.pawn, TargetIndex.A)); } else { yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnForbidden(TargetIndex.A)); yield return(Toils_Ingest.PickupIngestible(TargetIndex.A, this.pawn)); } yield return(Toils_Ingest.ChewIngestible(this.pawn, 1f, TargetIndex.A)); yield return(Toils_DrugIngest.FinalizeIngest(this.pawn, TargetIndex.A)); yield break; }
protected override IEnumerable <Toil> MakeNewToils() { if (!usingNutrientPasteDispenser) { this.FailOn(() => !IngestibleSource.Destroyed && !IngestibleSource.IngestibleNow); } Toil chew = Toils_Ingest.ChewIngestible(pawn, ChewDurationMultiplier, TargetIndex.A, TargetIndex.B).FailOn((Toil x) => (!IngestibleSource.Spawned && (pawn.carryTracker != null)) || pawn.mindState.anyCloseHostilesRecently).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); foreach (Toil item in PrepareToIngestToils(chew)) { yield return(item); } yield return(chew); yield return(Toils_Ingest.FinalizeIngest(pawn, TargetIndex.A)); yield return(Toils_Jump.JumpIf(chew, () => job.GetTarget(TargetIndex.A).Thing is Corpse && pawn.needs.food.CurLevelPercentage < 0.9f)); }
protected override IEnumerable <Toil> MakeNewToils() { // Declare these early - jumping points var waitForWaiter = Toils_Dining.WaitForWaiter(SpotIndex, WaiterIndex).FailOnRestaurantClosed().FailOnDangerous(); var waitForMeal = Toils_Dining.WaitForMeal(MealIndex).FailOnDangerous(); this.FailOn(() => DiningSpot.Destroyed); yield return(Toils_Dining.GoToDineSpot(pawn, SpotIndex).FailOnRestaurantClosed()); yield return(Toils_Dining.TurnToEatSurface(SpotIndex)); // Order broken? Jump straight to waiter yield return(Toils_Jump.JumpIf(waitForWaiter, () => !pawn.GetRestaurant().Orders.CheckOrderOfWaitingPawn(pawn))); // Already has ordered? Jump to waiting for meal yield return(Toils_Jump.JumpIf(waitForMeal, () => pawn.GetRestaurant().Orders.GetOrderFor(pawn) != null)); yield return(waitForWaiter); yield return(waitForMeal); yield return(Toils_Misc.TakeItemFromInventoryToCarrier(pawn, MealIndex)); yield return(Toils_Reserve.Reserve(MealIndex, 1, 1)); yield return(Toils_Dining.TurnToEatSurface(SpotIndex, MealIndex)); yield return(Toils_Dining.WaitDuringDinner(SpotIndex, 100, 250)); yield return(Toils_Ingest.ChewIngestible(pawn, ChewDurationMultiplier, MealIndex, SpotIndex)); yield return(Toils_Ingest.FinalizeIngest(pawn, MealIndex)); yield return(Toils_Dining.OnCompletedMeal(pawn)); yield return(Toils_Dining.MakeTableMessy(SpotIndex, () => pawn.Position)); yield return(Toils_Jump.JumpIf(waitForWaiter, () => pawn.needs.food.CurLevelPercentage < 0.9f)); yield return(Toils_Dining.WaitDuringDinner(SpotIndex, 100, 250)); yield return(Toils_Dining.PayDebt(pawn)); }
internal static IEnumerable <Toil> _MakeNewToils(this JobDriver_FoodFeedPatient obj) { Pawn deliveree = (Pawn)obj.pawn.CurJob.targetB.Thing; obj.FailOnDespawnedNullOrForbidden(TargetIndex.B); obj.FailOn(() => { return(!FoodUtility.ShouldBeFedBySomeone(deliveree)); }); yield return(Toils_Reserve.Reserve(TargetIndex.B, 1)); var targetThingA = obj.TargetThingA(); if (targetThingA is Building) { yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnForbidden(TargetIndex.A)); if (targetThingA is Building_NutrientPasteDispenser) { yield return(Toils_Ingest.TakeMealFromDispenser(TargetIndex.A, obj.pawn)); } if (targetThingA is Building_AutomatedFactory) { yield return(Toils_FoodSynthesizer.TakeMealFromSynthesizer(TargetIndex.A, obj.pawn)); } } else { yield return(Toils_Reserve.Reserve(TargetIndex.A, 1)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnForbidden(TargetIndex.A)); yield return(Toils_Ingest.PickupIngestible(TargetIndex.A, deliveree)); } yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch)); yield return(Toils_Ingest.ChewIngestible(deliveree, 1.5f, TargetIndex.A)); yield return(Toils_Ingest.FinalizeIngest(deliveree, TargetIndex.A)); }
protected override IEnumerable <Toil> MakeNewToils() { if (!usingNutrientPasteDispenser) { this.FailOn(() => !IngestibleSource.Destroyed && !IngestibleSource.IngestibleNow); } Toil chew = Toils_Ingest.ChewIngestible(pawn, ChewDurationMultiplier, TargetIndex.A, TargetIndex.B) .FailOn((Toil x) => !IngestibleSource.Spawned && (pawn.carryTracker == null || pawn.carryTracker.CarriedThing != IngestibleSource)) .FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); foreach (Toil toil in PrepareToIngestToils(chew)) { yield return(toil); } yield return(chew); yield return(FinalizeIngest(pawn, TargetIndex.A)); yield return(Toils_Jump.JumpIf(chew, () => pawn?.BloodNeed()?.CurLevelPercentage < 1f)); }
public override IEnumerable <Toil> MakeNewToils() { base.AddFinishAction(delegate { this.Map.attackTargetsCache.UpdateTarget(this.pawn); }); Toil prepareToEatCorpse = new Toil(); prepareToEatCorpse.initAction = delegate() { Pawn actor = prepareToEatCorpse.actor; Corpse corpse = this.Corpse; if (corpse == null) { Pawn prey = this.Prey; if (prey == null) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true, true); return; } corpse = prey.Corpse; if (corpse == null || !corpse.Spawned) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true, true); return; } } if (actor.Faction == Faction.OfPlayer) { corpse.SetForbidden(false, false); } else { corpse.SetForbidden(true, false); } actor.CurJob.SetTarget(TargetIndex.A, corpse); }; yield return(Toils_General.DoAtomic(delegate { this.Map.attackTargetsCache.UpdateTarget(this.pawn); })); Action hitAction = delegate() { Pawn prey = this.Prey; bool surpriseAttack = this.firstHit && !prey.IsColonist; if (this.pawn.meleeVerbs.TryMeleeAttack(prey, this.job.verbToUse, surpriseAttack)) { if (!this.notifiedPlayerAttacked && PawnUtility.ShouldSendNotificationAbout(prey)) { this.notifiedPlayerAttacked = true; Messages.Message("MessageAttackedByPredator".Translate(prey.LabelShort, this.pawn.LabelIndefinite(), prey.Named("PREY"), this.pawn.Named("PREDATOR")).CapitalizeFirst(), prey, MessageTypeDefOf.ThreatSmall, true); } this.Map.attackTargetsCache.UpdateTarget(this.pawn); this.firstHit = false; } }; Toil toil = Toils_Combat.FollowAndMeleeAttack(TargetIndex.A, hitAction).JumpIfDespawnedOrNull(TargetIndex.A, prepareToEatCorpse).JumpIf(() => this.Corpse != null, prepareToEatCorpse).FailOn(() => Find.TickManager.TicksGame > this.startTick + 5000 && (float)(this.job.GetTarget(TargetIndex.A).Cell - this.pawn.Position).LengthHorizontalSquared > 4f); toil.AddPreTickAction(new Action(this.CheckWarnPlayer)); yield return(toil); yield return(prepareToEatCorpse); Toil gotoCorpse = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch); yield return(gotoCorpse); float durationMultiplier = 1f / this.pawn.GetStatValue(StatDefOf.EatingSpeed, true); yield return(Toils_Ingest.ChewIngestible(this.pawn, durationMultiplier, TargetIndex.A, TargetIndex.None).FailOnDespawnedOrNull(TargetIndex.A).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch)); yield return(Toils_Ingest.FinalizeIngest(this.pawn, TargetIndex.A)); yield return(Toils_Jump.JumpIf(gotoCorpse, () => this.pawn.needs.food.CurLevelPercentage < 0.9f)); yield break; }
internal static IEnumerable <Toil> _MakeNewToils(this JobDriver_Ingest obj) { if (obj.IsDispenser()) { yield return(Toils_Goto.GotoThing(FoodOrDispenserInd, PathEndMode.InteractionCell).FailOnDespawnedNullOrForbidden(FoodOrDispenserInd)); if (obj.Alcohol() == null) { // Meals if (obj.Dispenser() is Building_NutrientPasteDispenser) { yield return(Toils_Ingest.TakeMealFromDispenser(FoodOrDispenserInd, obj.pawn)); } if (obj.Dispenser() is Building_AutomatedFactory) { yield return(Toils_FoodSynthesizer.TakeMealFromSynthesizer(FoodOrDispenserInd, obj.pawn)); } } else { // Alcohol if (obj.Dispenser() is Building_AutomatedFactory) { yield return(Toils_FoodSynthesizer.TakeAlcoholFromSynthesizer(FoodOrDispenserInd, obj.pawn)); } } yield return(Toils_Ingest.CarryIngestibleToChewSpot(obj.pawn).FailOnDestroyedNullOrForbidden(FoodOrDispenserInd)); yield return(Toils_Ingest.FindAdjacentEatSurface(TableCellInd, FoodOrDispenserInd)); } else if (obj.pawn.RaceProps.ToolUser) { if (obj.pawn.CurJob.eatFromInventory) { var dropIfNeeded = new Toil(); dropIfNeeded.initAction = new Action(() => { Pawn pawn = obj.pawn; Thing resultingThing = obj.Food(); Thing thing = resultingThing; if ( (pawn.inventory == null) || (!pawn.inventory.container.Contains(resultingThing)) ) { return; } int count = Mathf.Min(resultingThing.stackCount, pawn.CurJob.maxNumToCarry); if (!pawn.inventory.container.TryDrop(resultingThing, pawn.Position, ThingPlaceMode.Near, count, out resultingThing)) { Verse.Log.Error(pawn + " could not drop their food to eat it."); obj.EndJobWith(JobCondition.Errored); } else { if (resultingThing == thing) { return; } pawn.CurJob.SetTarget(FoodOrDispenserInd, (TargetInfo)resultingThing); } }); yield return(dropIfNeeded); } yield return(obj.ReserveFoodIfWillEatWholeStack()); yield return(Toils_Goto.GotoThing(FoodOrDispenserInd, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(FoodOrDispenserInd)); yield return(Toils_Ingest.PickupIngestible(FoodOrDispenserInd, obj.pawn)); yield return(Toils_Ingest.CarryIngestibleToChewSpot(obj.pawn).FailOnDestroyedNullOrForbidden(FoodOrDispenserInd)); yield return(Toils_Ingest.FindAdjacentEatSurface(TableCellInd, FoodOrDispenserInd)); } else // Non-Tool User { yield return(obj.ReserveFoodIfWillEatWholeStack()); yield return(Toils_Goto.GotoThing(FoodOrDispenserInd, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(FoodOrDispenserInd)); } var durationMultiplier = 1f / obj.pawn.GetStatValue(StatDefOf.EatingSpeed, true); var chew = Toils_Ingest.ChewIngestible(obj.pawn, durationMultiplier, FoodOrDispenserInd, TableCellInd).FailOn(() => { if (!obj.Food().Spawned) { return((obj.pawn.carrier == null ? 0 : (obj.pawn.carrier.CarriedThing == obj.Food() ? 1 : 0)) == 0); } return(false); }); yield return(chew); yield return(Toils_Ingest.FinalizeIngest(obj.pawn, FoodOrDispenserInd)); yield return(Toils_Jump.JumpIf(chew, () => { if (obj.Food() is Corpse) { return (double)obj.pawn.needs.food.CurLevelPercentage < JobDriver_Ingest.EatCorpseBodyPartsUntilFoodLevelPct; } return false; })); }