public static Toil DoRecipeWork() { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver; UnfinishedThing unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (unfinishedThing != null && unfinishedThing.Initialized) { jobDriver_DoBill.workLeft = unfinishedThing.workLeft; } else { jobDriver_DoBill.workLeft = curJob.bill.recipe.WorkAmountTotal((unfinishedThing == null) ? null : unfinishedThing.Stuff); if (unfinishedThing != null) { unfinishedThing.workLeft = jobDriver_DoBill.workLeft; } } jobDriver_DoBill.billStartTick = Find.TickManager.TicksGame; jobDriver_DoBill.ticksSpentDoingRecipeWork = 0; curJob.bill.Notify_DoBillStarted(actor); }; toil.tickAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver; UnfinishedThing unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (unfinishedThing != null && unfinishedThing.Destroyed) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true); return; } jobDriver_DoBill.ticksSpentDoingRecipeWork++; curJob.bill.Notify_PawnDidWork(actor); IBillGiverWithTickAction billGiverWithTickAction = toil.actor.CurJob.GetTarget(TargetIndex.A).Thing as IBillGiverWithTickAction; if (billGiverWithTickAction != null) { billGiverWithTickAction.UsedThisTick(); } if (curJob.RecipeDef.workSkill != null && curJob.RecipeDef.UsesUnfinishedThing) { actor.skills.GetSkill(curJob.RecipeDef.workSkill).Learn(0.11f * curJob.RecipeDef.workSkillLearnFactor, false); } float num = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat, true) : 1f; Building_WorkTable building_WorkTable = jobDriver_DoBill.BillGiver as Building_WorkTable; if (building_WorkTable != null) { num *= building_WorkTable.GetStatValue(StatDefOf.WorkTableWorkSpeedFactor, true); } if (DebugSettings.fastCrafting) { num *= 30f; } jobDriver_DoBill.workLeft -= num; if (unfinishedThing != null) { unfinishedThing.workLeft = jobDriver_DoBill.workLeft; } actor.GainComfortFromCellIfPossible(); if (jobDriver_DoBill.workLeft <= 0f) { jobDriver_DoBill.ReadyForNextToil(); } if (curJob.bill.recipe.UsesUnfinishedThing) { int num2 = Find.TickManager.TicksGame - jobDriver_DoBill.billStartTick; if (num2 >= 3000 && num2 % 1000 == 0) { actor.jobs.CheckForJobOverride(); } } }; toil.defaultCompleteMode = ToilCompleteMode.Never; toil.WithEffect(() => toil.actor.CurJob.bill.recipe.effectWorking, TargetIndex.A); toil.PlaySustainerOrSound(() => toil.actor.CurJob.bill.recipe.soundWorking); toil.WithProgressBar(TargetIndex.A, delegate { Pawn actor = toil.actor; Job curJob = actor.CurJob; UnfinishedThing unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; return(1f - ((JobDriver_DoBill)actor.jobs.curDriver).workLeft / curJob.bill.recipe.WorkAmountTotal((unfinishedThing == null) ? null : unfinishedThing.Stuff)); }, false, -0.5f); toil.FailOn(() => toil.actor.CurJob.bill.suspended); return(toil); }
public static bool __Prefix(Pawn pawn, TargetIndex ingestibleInd, ref Toil __result) { if (!TableDiner.settings.useExtraFeatures) { return(true); } Toil toil = new Verse.AI.Toil(); toil.initAction = delegate { Pawn actor = toil.actor; IntVec3 intVec = IntVec3.Invalid; Thing thing = null; Thing thing2 = actor.CurJob.GetTarget(ingestibleInd).Thing; Predicate <Thing> baseChairValidator = delegate(Thing t) { bool result; if (t.def.building == null || !t.def.building.isSittable) { result = false; } else if (t.IsForbidden(pawn)) { result = false; } else if (!actor.CanReserve(t, 1, -1, null, false)) { result = false; } else if (!t.IsSociallyProper(actor)) { result = false; } else if (t.IsBurning()) { result = false; } else if (t.HostileTo(pawn)) { result = false; } else { bool flag = false; for (int i = 0; i < 4; i++) { IntVec3 c = t.Position + GenAdj.CardinalDirections[i]; Building edifice = c.GetEdifice(t.Map); if (edifice != null && edifice.def.surfaceType == SurfaceType.Eat) { float tr = TableDinerGlobal.GetTableRadius(edifice.ThingID); float pr = TableDinerGlobal.GetTableRadius(actor.ThingID); if (tr >= 1 || pr >= 1) { float r2 = (edifice.TrueCenter() - actor.TrueCenter()).sqrMagnitude; if (tr < 1) { if (r2 <= Mathf.Pow(pr, 2)) { flag = true; break; } } else if (pr < 1) { if (r2 <= Mathf.Pow(tr, 2)) { flag = true; break; } } else { if (r2 <= Mathf.Pow(Mathf.Min(tr, pr), 2)) { flag = true; break; } } } else { flag = true; break; } } } result = flag; } return(result); }; if (thing2.def.ingestible.chairSearchRadius > 0f) { thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) == Danger.None, null, 0, -1, false, RegionType.Set_Passable, false); } if (thing == null) { intVec = RCellFinder.SpotToChewStandingNear(actor, actor.CurJob.GetTarget(ingestibleInd).Thing); Danger chewSpotDanger = intVec.GetDangerFor(pawn, actor.Map); if (chewSpotDanger != Danger.None) { thing = GenClosest.ClosestThingReachable(actor.Position, actor.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.OnCell, TraverseParms.For(actor, Danger.Deadly, TraverseMode.ByPawn, false), thing2.def.ingestible.chairSearchRadius, (Thing t) => baseChairValidator(t) && t.Position.GetDangerFor(pawn, t.Map) <= chewSpotDanger, null, 0, -1, false, RegionType.Set_Passable, false); } } if (thing != null) { intVec = thing.Position; actor.Reserve(thing, actor.CurJob, 1, -1, null); } actor.Map.pawnDestinationReservationManager.Reserve(actor, actor.CurJob, intVec); actor.pather.StartPath(intVec, PathEndMode.OnCell); }; toil.defaultCompleteMode = ToilCompleteMode.PatherArrival; __result = toil; return(false); }
protected override IEnumerable <Toil> MakeNewToils() { base.AddEndCondition(delegate { Thing thing = base.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; JobCondition result; if (thing is Building && !thing.Spawned) { result = JobCondition.Incompletable; } else { result = JobCondition.Ongoing; } return(result); }); this.FailOnBurningImmobile(TargetIndex.A); this.FailOn(delegate() { IBillGiver billGiver = this.job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (this.job.bill.DeletedOrDereferenced) { return(true); } if (!billGiver.CurrentlyUsableForBills()) { return(true); } } return(false); }); Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); yield return(new Toil { initAction = delegate() { if (this.job.targetQueueB != null && this.job.targetQueueB.Count == 1) { UnfinishedThing unfinishedThing = this.job.targetQueueB[0].Thing as UnfinishedThing; if (unfinishedThing != null) { unfinishedThing.BoundBill = (Bill_ProductionWithUft)this.job.bill; } } } }); yield return(Toils_Jump.JumpIf(gotoBillGiver, () => this.job.GetTargetQueue(TargetIndex.B).NullOrEmpty <LocalTargetInfo>())); Toil extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, true); yield return(extract); Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); yield return(getToHaulTarget); yield return(Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true)); yield return(JobDriver_DoBill.JumpToCollectNextIntoHandsForBill(getToHaulTarget, TargetIndex.B)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnDestroyedOrNull(TargetIndex.B)); Toil findPlaceTarget = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C); yield return(findPlaceTarget); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, findPlaceTarget, false)); yield return(Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, extract)); yield return(gotoBillGiver); yield return(Toils_Recipe.MakeUnfinishedThingIfNeeded()); yield return(Toils_Recipe.DoRecipeWork().FailOnDespawnedNullOrForbiddenPlacedThings().FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell)); yield return(Toils_Recipe.FinishRecipeAndStartStoringProduct()); if (!this.job.RecipeDef.products.NullOrEmpty <ThingDefCountClass>() || !this.job.RecipeDef.specialProducts.NullOrEmpty <SpecialProductType>()) { yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true)); Toil recount = new Toil(); recount.initAction = delegate() { Bill_Production bill_Production = recount.actor.jobs.curJob.bill as Bill_Production; if (bill_Production != null && bill_Production.repeatMode == BillRepeatModeDefOf.TargetCount) { this.Map.resourceCounter.UpdateResourceCounts(); } }; yield return(recount); } yield break; }
public static Toil FinishRecipeAndStartStoringProduct() { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver; if (curJob.RecipeDef.workSkill != null && !curJob.RecipeDef.UsesUnfinishedThing) { float xp = (float)jobDriver_DoBill.ticksSpentDoingRecipeWork * 0.11f * curJob.RecipeDef.workSkillLearnFactor; actor.skills.GetSkill(curJob.RecipeDef.workSkill).Learn(xp, false); } List <Thing> ingredients = Toils_Recipe.CalculateIngredients(curJob, actor); Thing dominantIngredient = Toils_Recipe.CalculateDominantIngredient(curJob, ingredients); List <Thing> list = GenRecipe.MakeRecipeProducts(curJob.RecipeDef, actor, ingredients, dominantIngredient).ToList <Thing>(); Toils_Recipe.ConsumeIngredients(ingredients, curJob.RecipeDef, actor.Map); curJob.bill.Notify_IterationCompleted(actor, ingredients); RecordsUtility.Notify_BillDone(actor, list); UnfinishedThing unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (curJob.bill.recipe.WorkAmountTotal((unfinishedThing == null) ? null : unfinishedThing.Stuff) >= 20000f && list.Count > 0) { TaleRecorder.RecordTale(TaleDefOf.CompletedLongCraftingProject, new object[] { actor, list[0].def }); } if (list.Count == 0) { actor.jobs.EndCurrentJob(JobCondition.Succeeded, true); return; } if (curJob.bill.GetStoreMode() == BillStoreModeDefOf.DropOnFloor) { for (int i = 0; i < list.Count; i++) { if (!GenPlace.TryPlaceThing(list[i], actor.Position, actor.Map, ThingPlaceMode.Near, null)) { Log.Error(string.Concat(new object[] { actor, " could not drop recipe product ", list[i], " near ", actor.Position })); } } actor.jobs.EndCurrentJob(JobCondition.Succeeded, true); return; } if (list.Count > 1) { for (int j = 1; j < list.Count; j++) { if (!GenPlace.TryPlaceThing(list[j], actor.Position, actor.Map, ThingPlaceMode.Near, null)) { Log.Error(string.Concat(new object[] { actor, " could not drop recipe product ", list[j], " near ", actor.Position })); } } } list[0].SetPositionDirect(actor.Position); IntVec3 c; if (StoreUtility.TryFindBestBetterStoreCellFor(list[0], actor, actor.Map, StoragePriority.Unstored, actor.Faction, out c, true)) { actor.carryTracker.TryStartCarry(list[0]); curJob.targetB = c; curJob.targetA = list[0]; curJob.count = 99999; return; } if (!GenPlace.TryPlaceThing(list[0], actor.Position, actor.Map, ThingPlaceMode.Near, null)) { Log.Error(string.Concat(new object[] { "Bill doer could not drop product ", list[0], " near ", actor.Position })); } actor.jobs.EndCurrentJob(JobCondition.Succeeded, true); }; return(toil); }
public bool MoveNext() { uint num = (uint)this.$PC; this.$PC = -1; switch (num) { case 0u: { base.AddEndCondition(delegate { Thing thing = base.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; JobCondition result; if (thing is Building && !thing.Spawned) { result = JobCondition.Incompletable; } else { result = JobCondition.Ongoing; } return(result); }); this.FailOnBurningImmobile(TargetIndex.A); this.FailOn(delegate() { IBillGiver billGiver = this.job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (this.job.bill.DeletedOrDereferenced) { return(true); } if (!billGiver.CurrentlyUsableForBills()) { return(true); } } return(false); }); gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); Toil bind = new Toil(); bind.initAction = delegate() { if (this.job.targetQueueB != null && this.job.targetQueueB.Count == 1) { UnfinishedThing unfinishedThing = this.job.targetQueueB[0].Thing as UnfinishedThing; if (unfinishedThing != null) { unfinishedThing.BoundBill = (Bill_ProductionWithUft)this.job.bill; } } }; this.$current = bind; if (!this.$disposing) { this.$PC = 1; } return(true); } case 1u: this.$current = Toils_Jump.JumpIf(gotoBillGiver, () => this.job.GetTargetQueue(TargetIndex.B).NullOrEmpty <LocalTargetInfo>()); if (!this.$disposing) { this.$PC = 2; } return(true); case 2u: extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, true); this.$current = extract; if (!this.$disposing) { this.$PC = 3; } return(true); case 3u: getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); this.$current = getToHaulTarget; if (!this.$disposing) { this.$PC = 4; } return(true); case 4u: this.$current = Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true); if (!this.$disposing) { this.$PC = 5; } return(true); case 5u: this.$current = JobDriver_DoBill.JumpToCollectNextIntoHandsForBill(getToHaulTarget, TargetIndex.B); if (!this.$disposing) { this.$PC = 6; } return(true); case 6u: this.$current = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnDestroyedOrNull(TargetIndex.B); if (!this.$disposing) { this.$PC = 7; } return(true); case 7u: findPlaceTarget = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C); this.$current = findPlaceTarget; if (!this.$disposing) { this.$PC = 8; } return(true); case 8u: this.$current = Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, findPlaceTarget, false); if (!this.$disposing) { this.$PC = 9; } return(true); case 9u: this.$current = Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, extract); if (!this.$disposing) { this.$PC = 10; } return(true); case 10u: this.$current = gotoBillGiver; if (!this.$disposing) { this.$PC = 11; } return(true); case 11u: this.$current = Toils_Recipe.MakeUnfinishedThingIfNeeded(); if (!this.$disposing) { this.$PC = 12; } return(true); case 12u: this.$current = Toils_Recipe.DoRecipeWork().FailOnDespawnedNullOrForbiddenPlacedThings().FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell); if (!this.$disposing) { this.$PC = 13; } return(true); case 13u: this.$current = Toils_Recipe.FinishRecipeAndStartStoringProduct(); if (!this.$disposing) { this.$PC = 14; } return(true); case 14u: if (!this.job.RecipeDef.products.NullOrEmpty <ThingDefCountClass>() || !this.job.RecipeDef.specialProducts.NullOrEmpty <SpecialProductType>()) { this.$current = Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null); if (!this.$disposing) { this.$PC = 15; } return(true); } break; case 15u: carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); this.$current = carryToCell; if (!this.$disposing) { this.$PC = 16; } return(true); case 16u: this.$current = Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true); if (!this.$disposing) { this.$PC = 17; } return(true); case 17u: < MakeNewToils > c__AnonStorey.recount = new Toil(); < MakeNewToils > c__AnonStorey.recount.initAction = delegate() { Bill_Production bill_Production = < MakeNewToils > c__AnonStorey.recount.actor.jobs.curJob.bill as Bill_Production; if (bill_Production != null && bill_Production.repeatMode == BillRepeatModeDefOf.TargetCount) { < MakeNewToils > c__AnonStorey.< > f__ref$0.$this.Map.resourceCounter.UpdateResourceCounts(); }
public virtual void DecorateWaitToil(Toil wait) { }
public static Toil StartCarryThing(TargetIndex haulableInd, bool putRemainderInQueue = false, bool subtractNumTakenFromJobCount = false, bool failIfStackCountLessThanJobCount = false) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; Thing thing = curJob.GetTarget(haulableInd).Thing; if (!ErrorCheckForCarry(actor, thing)) { if (curJob.count == 0) { throw new Exception("StartCarryThing job had count = " + curJob.count + ". Job: " + curJob); } int num = actor.carryTracker.AvailableStackSpace(thing.def); if (num == 0) { throw new Exception("StartCarryThing got availableStackSpace " + num + " for haulTarg " + thing + ". Job: " + curJob); } if (failIfStackCountLessThanJobCount && thing.stackCount < curJob.count) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } else { int num2 = Mathf.Min(curJob.count, num, thing.stackCount); if (num2 <= 0) { throw new Exception("StartCarryThing desiredNumToTake = " + num2); } int stackCount = thing.stackCount; int num3 = actor.carryTracker.TryStartCarry(thing, num2); if (num3 == 0) { actor.jobs.EndCurrentJob(JobCondition.Incompletable); } if (num3 < stackCount) { int num4 = curJob.count - num3; if (putRemainderInQueue && num4 > 0) { curJob.GetTargetQueue(haulableInd).Insert(0, thing); if (curJob.countQueue == null) { curJob.countQueue = new List <int>(); } curJob.countQueue.Insert(0, num4); } else if (actor.Map.reservationManager.ReservedBy(thing, actor, curJob)) { actor.Map.reservationManager.Release(thing, actor, curJob); } } if (subtractNumTakenFromJobCount) { curJob.count -= num3; } curJob.SetTarget(haulableInd, actor.carryTracker.CarriedThing); actor.records.Increment(RecordDefOf.ThingsHauled); } } }; return(toil); }
public static Toil PlaceHauledThingInCell(TargetIndex cellInd, Toil nextToilOnPlaceFailOrIncomplete, bool storageMode) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; IntVec3 cell = curJob.GetTarget(cellInd).Cell; if (actor.carryTracker.CarriedThing == null) { Log.Error(actor + " tried to place hauled thing in cell but is not hauling anything."); } else { SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell); if (slotGroup != null && slotGroup.Settings.AllowedToAccept(actor.carryTracker.CarriedThing)) { actor.Map.designationManager.TryRemoveDesignationOn(actor.carryTracker.CarriedThing, DesignationDefOf.Haul); } Action <Thing, int> placedAction = null; if (curJob.def == JobDefOf.DoBill || curJob.def == JobDefOf.RefuelAtomic || curJob.def == JobDefOf.RearmTurretAtomic) { placedAction = delegate(Thing th, int added) { if (curJob.placedThings == null) { curJob.placedThings = new List <ThingCountClass>(); } ThingCountClass thingCountClass = curJob.placedThings.Find((ThingCountClass x) => x.thing == th); if (thingCountClass != null) { thingCountClass.Count += added; } else { curJob.placedThings.Add(new ThingCountClass(th, added)); } }; } if (!actor.carryTracker.TryDropCarriedThing(cell, ThingPlaceMode.Direct, out Thing _, placedAction)) { if (storageMode) { if (nextToilOnPlaceFailOrIncomplete != null && StoreUtility.TryFindBestBetterStoreCellFor(actor.carryTracker.CarriedThing, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out IntVec3 foundCell)) { if (actor.CanReserve(foundCell)) { actor.Reserve(foundCell, actor.CurJob); } actor.CurJob.SetTarget(cellInd, foundCell); actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } else { Job job = HaulAIUtility.HaulAsideJobFor(actor, actor.carryTracker.CarriedThing); if (job != null) { curJob.targetA = job.targetA; curJob.targetB = job.targetB; curJob.targetC = job.targetC; curJob.count = job.count; curJob.haulOpportunisticDuplicates = job.haulOpportunisticDuplicates; curJob.haulMode = job.haulMode; actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } else { Log.Error("Incomplete haul for " + actor + ": Could not find anywhere to put " + actor.carryTracker.CarriedThing + " near " + actor.Position + ". Destroying. This should never happen!"); actor.carryTracker.CarriedThing.Destroy(); } } } else if (nextToilOnPlaceFailOrIncomplete != null) { actor.jobs.curDriver.JumpToToil(nextToilOnPlaceFailOrIncomplete); } } } }; return(toil); }
public static Toil FinishRecipeAndStartStoringProduct() { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver; if (curJob.RecipeDef.workSkill != null && !curJob.RecipeDef.UsesUnfinishedThing) { float xp = (float)jobDriver_DoBill.ticksSpentDoingRecipeWork * 0.1f * curJob.RecipeDef.workSkillLearnFactor; actor.skills.GetSkill(curJob.RecipeDef.workSkill).Learn(xp); } List <Thing> ingredients = CalculateIngredients(curJob, actor); Thing dominantIngredient = CalculateDominantIngredient(curJob, ingredients); List <Thing> list = GenRecipe.MakeRecipeProducts(curJob.RecipeDef, actor, ingredients, dominantIngredient, jobDriver_DoBill.BillGiver).ToList(); ConsumeIngredients(ingredients, curJob.RecipeDef, actor.Map); curJob.bill.Notify_IterationCompleted(actor, ingredients); RecordsUtility.Notify_BillDone(actor, list); UnfinishedThing unfinishedThing = curJob.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (curJob.bill.recipe.WorkAmountTotal(unfinishedThing?.Stuff) >= 10000f && list.Count > 0) { TaleRecorder.RecordTale(TaleDefOf.CompletedLongCraftingProject, actor, list[0].GetInnerIfMinified().def); } if (list.Count == 0) { actor.jobs.EndCurrentJob(JobCondition.Succeeded); } else if (curJob.bill.GetStoreMode() == BillStoreModeDefOf.DropOnFloor) { for (int i = 0; i < list.Count; i++) { if (!GenPlace.TryPlaceThing(list[i], actor.Position, actor.Map, ThingPlaceMode.Near)) { Log.Error(actor + " could not drop recipe product " + list[i] + " near " + actor.Position); } } actor.jobs.EndCurrentJob(JobCondition.Succeeded); } else { if (list.Count > 1) { for (int j = 1; j < list.Count; j++) { if (!GenPlace.TryPlaceThing(list[j], actor.Position, actor.Map, ThingPlaceMode.Near)) { Log.Error(actor + " could not drop recipe product " + list[j] + " near " + actor.Position); } } } IntVec3 foundCell = IntVec3.Invalid; if (curJob.bill.GetStoreMode() == BillStoreModeDefOf.BestStockpile) { StoreUtility.TryFindBestBetterStoreCellFor(list[0], actor, actor.Map, StoragePriority.Unstored, actor.Faction, out foundCell); } else if (curJob.bill.GetStoreMode() == BillStoreModeDefOf.SpecificStockpile) { StoreUtility.TryFindBestBetterStoreCellForIn(list[0], actor, actor.Map, StoragePriority.Unstored, actor.Faction, curJob.bill.GetStoreZone().slotGroup, out foundCell); } else { Log.ErrorOnce("Unknown store mode", 9158246); } if (foundCell.IsValid) { actor.carryTracker.TryStartCarry(list[0]); curJob.targetB = foundCell; curJob.targetA = list[0]; curJob.count = 99999; } else { if (!GenPlace.TryPlaceThing(list[0], actor.Position, actor.Map, ThingPlaceMode.Near)) { Log.Error("Bill doer could not drop product " + list[0] + " near " + actor.Position); } actor.jobs.EndCurrentJob(JobCondition.Succeeded); } } }; return(toil); }