public static bool PawnCanAutomaticallyHaulFast(Pawn p, Thing t, bool forced) { UnfinishedThing unfinishedThing = t as UnfinishedThing; Building building; if (unfinishedThing != null && unfinishedThing.BoundBill != null && ((building = unfinishedThing.BoundBill.billStack.billGiver as Building) == null || (building.Spawned && building.OccupiedRect().ExpandedBy(1).Contains(unfinishedThing.Position)))) { return(false); } if (!p.CanReach(t, PathEndMode.ClosestTouch, p.NormalMaxDanger())) { return(false); } if (!p.CanReserve(t, 1, -1, null, forced)) { return(false); } if (!p.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation)) { return(false); } if (t.def.IsNutritionGivingIngestible && t.def.ingestible.HumanEdible && !t.IsSociallyProper(p, forPrisoner: false, animalsCare: true)) { JobFailReason.Is(ReservedForPrisonersTrans); return(false); } if (t.IsBurning()) { JobFailReason.Is(BurningLowerTrans); return(false); } return(true); }
public static bool PawnCanAutomaticallyHaulFast(Pawn p, Thing t, bool forced) { UnfinishedThing unfinishedThing = t as UnfinishedThing; if (unfinishedThing != null && unfinishedThing.BoundBill != null) { return(false); } if (!p.CanReach(t, PathEndMode.ClosestTouch, p.NormalMaxDanger(), false, TraverseMode.ByPawn)) { return(false); } LocalTargetInfo target = t; if (!p.CanReserve(target, 1, -1, null, forced)) { return(false); } if (t.def.IsNutritionGivingIngestible && t.def.ingestible.HumanEdible && !t.IsSociallyProper(p, false, true)) { JobFailReason.Is(HaulAIUtility.ReservedForPrisonersTrans, null); return(false); } if (t.IsBurning()) { JobFailReason.Is(HaulAIUtility.BurningLowerTrans, null); return(false); } return(true); }
private static Job FinishUftJob(Pawn pawn, UnfinishedThing uft, Bill_ProductionWithUft bill) { if (uft.Creator != pawn) { Log.Error(string.Concat(new object[] { "Tried to get FinishUftJob for ", pawn, " finishing ", uft, " but its creator is ", uft.Creator }), false); return(null); } Job job = WorkGiverUtility.HaulStuffOffBillGiverJob(pawn, bill.billStack.billGiver, uft); if (job != null && job.targetA.Thing != uft) { return(job); } return(new Job(JobDefOf.DoBill, (Thing)bill.billStack.billGiver) { bill = bill, targetQueueB = new List <LocalTargetInfo> { uft }, countQueue = new List <int> { 1 }, haulMode = HaulMode.ToCellNonStorage }); }
private static List <Thing> CalculateIngredients(Job job, Pawn actor) { UnfinishedThing unfinishedThing = job.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (unfinishedThing != null) { List <Thing> ingredients = unfinishedThing.ingredients; job.RecipeDef.Worker.ConsumeIngredient(unfinishedThing, job.RecipeDef, actor.Map); job.placedThings = null; return(ingredients); } List <Thing> list = new List <Thing>(); if (job.placedThings != null) { for (int i = 0; i < job.placedThings.Count; i++) { if (job.placedThings[i].Count <= 0) { Log.Error(string.Concat(new object[] { "PlacedThing ", job.placedThings[i], " with count ", job.placedThings[i].Count, " for job ", job })); } else { Thing thing; if (job.placedThings[i].Count < job.placedThings[i].thing.stackCount) { thing = job.placedThings[i].thing.SplitOff(job.placedThings[i].Count); } else { thing = job.placedThings[i].thing; } job.placedThings[i].Count = 0; if (list.Contains(thing)) { Log.Error("Tried to add ingredient from job placed targets twice: " + thing); } else { list.Add(thing); IStrippable strippable = thing as IStrippable; if (strippable != null) { strippable.Strip(); } } } } } job.placedThings = null; return(list); }
static Pawn Postfix(Pawn __result, Bill_ProductionWithUft __instance, UnfinishedThing __state) { if (__result == null && __state != null) { Pawn creator = __state.Creator; if (creator == null || creator.Downed || creator.Destroyed || !creator.Spawned) { return(__result); } Thing thing = __instance.billStack.billGiver as Thing; if (thing != null) { WorkTypeDef workTypeDef = null; List <WorkGiverDef> allDefsListForReading = DefDatabase <WorkGiverDef> .AllDefsListForReading; for (int i = 0; i < allDefsListForReading.Count; i++) { if (allDefsListForReading[i].fixedBillGiverDefs != null && allDefsListForReading[i].fixedBillGiverDefs.Contains(thing.def)) { workTypeDef = allDefsListForReading[i].workType; break; } } if (workTypeDef != null && !creator.workSettings.WorkIsActive(workTypeDef)) { return(__result); } } Traverse.Create(__instance).Field("boundUftInt").SetValue(__state); DebugLogger.debug($"Returning creator {creator.LabelShort}, value override"); return(creator); } return(__result); }
public static bool PawnCanAutomaticallyHaulFast(Pawn p, Thing t, bool forced) { UnfinishedThing unfinishedThing = t as UnfinishedThing; if (unfinishedThing != null && unfinishedThing.BoundBill != null) { return(false); } if (!p.CanReach(t, PathEndMode.ClosestTouch, p.NormalMaxDanger())) { return(false); } LocalTargetInfo target = t; bool ignoreOtherReservations = forced; if (!p.CanReserve(target, 1, -1, null, ignoreOtherReservations)) { return(false); } if (t.def.IsNutritionGivingIngestible && t.def.ingestible.HumanEdible && !t.IsSociallyProper(p, forPrisoner: false, animalsCare: true)) { JobFailReason.Is(ReservedForPrisonersTrans); return(false); } if (t.IsBurning()) { JobFailReason.Is(BurningLowerTrans); return(false); } return(true); }
private static Thing CalculateDominantIngredient(Job job, List <Thing> ingredients) { UnfinishedThing uft = job.GetTarget(TargetIndex.B).Thing as UnfinishedThing; Thing result; if (uft != null && uft.def.MadeFromStuff) { result = uft.ingredients.First((Thing ing) => ing.def == uft.Stuff); } else if (!ingredients.NullOrEmpty <Thing>()) { if (job.RecipeDef.productHasIngredientStuff) { result = ingredients[0]; } else if (job.RecipeDef.products.Any((ThingDefCountClass x) => x.thingDef.MadeFromStuff)) { result = (from x in ingredients where x.def.IsStuff select x).RandomElementByWeight((Thing x) => (float)x.stackCount); } else { result = ingredients.RandomElementByWeight((Thing x) => (float)x.stackCount); } } else { result = null; } return(result); }
private static Job FinishUftJob(Pawn pawn, UnfinishedThing uft, Bill_ProductionWithUft bill) { if (uft.Creator != pawn) { Log.Error("Tried to get FinishUftJob for " + pawn + " finishing " + uft + " but its creator is " + uft.Creator); return(null); } Job job = WorkGiverUtility.HaulStuffOffBillGiverJob(pawn, bill.billStack.billGiver, uft); if (job != null && job.targetA.Thing != uft) { return(job); } Job job2 = JobMaker.MakeJob(JobDefOf.DoBill, (Thing)bill.billStack.billGiver); job2.bill = bill; job2.targetQueueB = new List <LocalTargetInfo> { uft }; job2.countQueue = new List <int> { 1 }; job2.haulMode = HaulMode.ToCellNonStorage; return(job2); }
/// <summary> /// Gets the dominant ingredient that determines the stuff, color, and possibly other properties of recipe products. /// </summary> private static Thing CalculateDominantIngredient(Job job, List <Thing> ingredients) { UnfinishedThing uft = job.GetTarget(JobDriver_DoBill.IngredientInd).Thing as UnfinishedThing; if (uft != null && uft.def.MadeFromStuff) { return(uft.ingredients.First(ing => ing.def == uft.Stuff)); } if (!ingredients.NullOrEmpty()) { // if the recipe uses stuff ingredient (from recipe maker), then the first ingredient is the dominant one (stuff) if (job.RecipeDef.productHasIngredientStuff) { return(ingredients[0]); } if (job.RecipeDef.products.Any(x => x.thingDef.MadeFromStuff)) { return(ingredients.Where(x => x.def.IsStuff).RandomElementByWeight(x => x.stackCount)); } else { return(ingredients.RandomElementByWeight(x => x.stackCount)); } } return(null); }
public static void Creator(UnfinishedThing __instance) { if (__instance.def.HasModExtension <ModExtension_NoJobAuthor>()) { _creatorName(__instance) = "Everyone"; } }
private Toil MakeUnfinishedThingIfNeeded() { Toil toil = new Toil(); toil.initAction = delegate() { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; if (!curJob.RecipeDef.UsesUnfinishedThing) { return; } if (curJob.GetTarget(TargetIndex.B).Thing != null && curJob.GetTarget(TargetIndex.B).Thing is UnfinishedThing) { return; } UnfinishedThing unfinishedThing = (UnfinishedThing)ThingMaker.MakeThing(curJob.RecipeDef.unfinishedThingDef, techStuff); unfinishedThing.Creator = actor; unfinishedThing.BoundBill = (Bill_ProductionWithUft)curJob.bill; // <- when pawn is a prisoner, the recipe doesn't seem to register this. unfinishedThing.ingredients = new List <Thing> { new Thing() { def = unfinishedThing.Stuff, stackCount = 0 } }; GenSpawn.Spawn(unfinishedThing, curJob.GetTarget(TargetIndex.A).Cell, actor.Map, WipeMode.Vanish); curJob.SetTarget(TargetIndex.B, unfinishedThing); actor.Reserve(unfinishedThing, curJob, 1, -1, null, true); }; return(toil); }
private Job StartOrResumeBillJob(Pawn pawn, IBillGiver giver) { for (int i = 0; i < giver.BillStack.Count; i++) { Bill bill = giver.BillStack[i]; if ((bill.recipe.requiredGiverWorkType != null && bill.recipe.requiredGiverWorkType != def.workType) || (Find.TickManager.TicksGame < bill.lastIngredientSearchFailTicks + ReCheckFailedBillTicksRange.RandomInRange && FloatMenuMakerMap.makingFor != pawn)) { continue; } bill.lastIngredientSearchFailTicks = 0; if (!bill.ShouldDoNow() || !bill.PawnAllowedToStartAnew(pawn)) { continue; } SkillRequirement skillRequirement = bill.recipe.FirstSkillRequirementPawnDoesntSatisfy(pawn); if (skillRequirement != null) { JobFailReason.Is("UnderRequiredSkill".Translate(skillRequirement.minLevel), bill.Label); continue; } Bill_ProductionWithUft bill_ProductionWithUft = bill as Bill_ProductionWithUft; if (bill_ProductionWithUft != null) { if (bill_ProductionWithUft.BoundUft != null) { if (bill_ProductionWithUft.BoundWorker == pawn && pawn.CanReserveAndReach(bill_ProductionWithUft.BoundUft, PathEndMode.Touch, Danger.Deadly) && !bill_ProductionWithUft.BoundUft.IsForbidden(pawn)) { return(FinishUftJob(pawn, bill_ProductionWithUft.BoundUft, bill_ProductionWithUft)); } continue; } UnfinishedThing unfinishedThing = ClosestUnfinishedThingForBill(pawn, bill_ProductionWithUft); if (unfinishedThing != null) { return(FinishUftJob(pawn, unfinishedThing, bill_ProductionWithUft)); } } if (!TryFindBestBillIngredients(bill, pawn, (Thing)giver, chosenIngThings)) { if (FloatMenuMakerMap.makingFor != pawn) { bill.lastIngredientSearchFailTicks = Find.TickManager.TicksGame; } else { JobFailReason.Is(MissingMaterialsTranslated, bill.Label); } chosenIngThings.Clear(); continue; } Job haulOffJob; Job result = TryStartNewDoBillJob(pawn, bill, giver, chosenIngThings, out haulOffJob); chosenIngThings.Clear(); return(result); } chosenIngThings.Clear(); return(null); }
public static bool Creator(UnfinishedThing __instance, ref Pawn __result) { if (__instance.def.HasModExtension <ModExtension_NoJobAuthor>()) { __result = null; return(false); } return(true); }
private Job StartOrResumeBillJob(Pawn pawn, IBillGiver giver, LocalTargetInfo target) { for (int i = 0; i < giver.BillStack.Count; i++) { Bill bill = giver.BillStack[i]; if ((bill.recipe == TechDefOf.DocumentTech || bill.recipe == TechDefOf.DocumentTechDigital) && bill.ShouldDoNow() && bill.PawnAllowedToStartAnew(pawn)) { SkillRequirement skillRequirement = bill.recipe.FirstSkillRequirementPawnDoesntSatisfy(pawn); if (skillRequirement != null) { JobFailReason.Is("UnderRequiredSkill".Translate(skillRequirement.minLevel), bill.Label); } else { if (bill.recipe.UsesUnfinishedThing) { Bill_ProductionWithUft bill_ProductionWithUft = bill as Bill_ProductionWithUft; if (bill_ProductionWithUft != null) { if (bill_ProductionWithUft.BoundUft != null) { if (bill_ProductionWithUft.BoundWorker == pawn && pawn.CanReserveAndReach(bill_ProductionWithUft.BoundUft, PathEndMode.Touch, Danger.Deadly, 1, -1, null, false) && !bill_ProductionWithUft.BoundUft.IsForbidden(pawn)) { return(FinishUftJob(pawn, bill_ProductionWithUft.BoundUft, bill_ProductionWithUft)); } return(null); } else { MethodInfo ClosestUftInfo = AccessTools.Method(typeof(WorkGiver_DoBill), "ClosestUnfinishedThingForBill"); UnfinishedThing unfinishedThing = (UnfinishedThing)ClosestUftInfo.Invoke(this, new object[] { pawn, bill_ProductionWithUft }); if (unfinishedThing != null) { return(FinishUftJob(pawn, unfinishedThing, bill_ProductionWithUft)); } } } return(new Job(TechJobDefOf.DocumentTech, target) { bill = bill }); } else { return(new Job(TechJobDefOf.DocumentTechDigital, target) { bill = bill }); } } } } return(null); }
// prefix // - wants instance, result and count // - wants to change count // - returns a boolean that controls if original is executed (true) or not (false) public static Boolean CalculateIngredientsPrefix(Job job, Pawn actor, ref List <Thing> __result) { UnfinishedThing unfinishedThing = job.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (unfinishedThing != null) { List <Thing> ingredients = unfinishedThing.ingredients; job.RecipeDef.Worker.ConsumeIngredient(unfinishedThing, job.RecipeDef, actor.Map); job.placedThings = null; //return ingredients; __result = ingredients; return(false); } List <Thing> list = new List <Thing>(); if (job.placedThings != null) { for (int i = 0; i < job.placedThings.Count; i++) { if (job.placedThings[i].Count <= 0) { Log.Error("PlacedThing " + job.placedThings[i] + " with count " + job.placedThings[i].Count + " for job " + job); } else { Thing thing = (job.placedThings[i].Count >= job.placedThings[i].thing.stackCount) ? job.placedThings[i].thing : job.placedThings[i].thing.SplitOff(job.placedThings[i].Count); job.placedThings[i].Count = 0; if (list.Contains(thing)) { Log.Error("Tried to add ingredient from job placed targets twice: " + thing); } else { list.Add(thing); //Check if the Name of the Recipe is "CremateCorpse", if so do not strip. if (!string.Equals(job.RecipeDef.defName, "CremateCorpse")) { IStrippable strippable = thing as IStrippable; if (strippable != null) { strippable.Strip(); } } } } } } job.placedThings = null; // return list; __result = list; return(false); }
public new object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { Bill_ProductionWithUft _obj = (Bill_ProductionWithUft)base.SetObjectData(obj, info, context, selector); UnfinishedThing uft = (UnfinishedThing)info.GetValue("uft", typeof(UnfinishedThing)); if (_obj != null) { _obj.SetBoundUft(uft, true); } return _obj; }
// Token: 0x0600002D RID: 45 RVA: 0x0000384C File Offset: 0x00001A4C public static Toil MakeUnfinishedThingIfNeeded() { Toil toil = new Toil(); toil.initAction = delegate() { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; bool flag = !curJob.RecipeDef.UsesUnfinishedThing; if (!flag) { bool flag2 = curJob.GetTarget(TargetIndex.B).Thing is UnfinishedThing; if (!flag2) { List <Thing> list = Toils_WPRecipe.CalculateIngredients(curJob, actor); string str = "ingredient list in toil_wprecipe"; List <Thing> list2 = list; Log.Message(str + ((list2 != null) ? list2.ToString() : null), false); Thing thing = Toils_WPRecipe.CalculateDominantIngredient(curJob, list); for (int i = 0; i < list.Count; i++) { Thing thing2 = list[i]; string str2 = "ingredient in toil_wprecipe"; Thing thing3 = list[i]; Log.Message(str2 + ((thing3 != null) ? thing3.ToString() : null), false); actor.Map.designationManager.RemoveAllDesignationsOn(thing2, false); bool spawned = thing2.Spawned; if (spawned) { thing2.DeSpawn(DestroyMode.Vanish); } } ThingDef stuff = (!curJob.RecipeDef.unfinishedThingDef.MadeFromStuff) ? null : thing.def; UnfinishedThing unfinishedThing = (UnfinishedThing)ThingMaker.MakeThing(curJob.RecipeDef.unfinishedThingDef, stuff); unfinishedThing.Creator = actor; unfinishedThing.BoundBill = (Bill_ProductionWithUft)curJob.bill; unfinishedThing.ingredients = list; CompColorable compColorable = unfinishedThing.TryGetComp <CompColorable>(); bool flag3 = compColorable != null; if (flag3) { compColorable.Color = thing.DrawColor; } GenSpawn.Spawn(unfinishedThing, curJob.GetTarget(TargetIndex.A).Cell, actor.Map, WipeMode.Vanish); curJob.SetTarget(TargetIndex.B, unfinishedThing); actor.Reserve(unfinishedThing, curJob, 1, -1, null, true); } } }; return(toil); }
static void Prefix(Bill_ProductionWithUft __instance, out UnfinishedThing __state) { UnfinishedThing unfinishedThing = Traverse.Create(__instance).Field("boundUftInt").GetValue <UnfinishedThing>(); if (unfinishedThing != null && unfinishedThing.Creator != null && unfinishedThing.Creator.IsPrisonerOfColony) { DebugLogger.debug($"[PL] Saving unfinished thing to state pawn: {unfinishedThing.Creator.LabelShort}, bill: {unfinishedThing.LabelShort}"); __state = unfinishedThing; } else { __state = null; } }
public static bool ClosestUnfinishedThingForBill(ref UnfinishedThing __result, Pawn pawn, Bill_ProductionWithUft bill) { bool Validator(Thing t) => !t.IsForbidden(pawn) && ((UnfinishedThing)t).Recipe == bill.recipe && ((UnfinishedThing)t).ingredients.TrueForAll(x => bill.IsFixedOrAllowedIngredient(x.def)) && pawn.CanReserve(t); ThingRequest thingReq = ThingRequest.ForDef(bill.recipe.unfinishedThingDef); TraverseParms traverseParams = TraverseParms.For(pawn, pawn.NormalMaxDanger()); __result = (UnfinishedThing)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, thingReq, PathEndMode.InteractionCell, traverseParams, validator: Validator); //Log.Message("This is closest unfinished thing for bill", false); return(false); }
private Job StartOrResumeBillJob(Pawn pawn, IBillGiver giver) { for (int i = 0; i < giver.BillStack.Count; i++) { Bill bill = giver.BillStack[i]; if ((bill.recipe.requiredGiverWorkType == null || bill.recipe.requiredGiverWorkType == base.def.workType) && (Find.TickManager.TicksGame >= bill.lastIngredientSearchFailTicks + WorkGiver_DoBill.ReCheckFailedBillTicksRange.RandomInRange || FloatMenuMakerMap.makingFor == pawn)) { bill.lastIngredientSearchFailTicks = 0; if (bill.ShouldDoNow() && bill.PawnAllowedToStartAnew(pawn)) { if (bill.recipe.PawnSatisfiesSkillRequirements(pawn)) { Bill_ProductionWithUft bill_ProductionWithUft = bill as Bill_ProductionWithUft; if (bill_ProductionWithUft != null) { if (bill_ProductionWithUft.BoundUft != null) { if (bill_ProductionWithUft.BoundWorker == pawn && pawn.CanReserveAndReach(bill_ProductionWithUft.BoundUft, PathEndMode.Touch, Danger.Deadly, 1, -1, null, false) && !bill_ProductionWithUft.BoundUft.IsForbidden(pawn)) { return(WorkGiver_DoBill.FinishUftJob(pawn, bill_ProductionWithUft.BoundUft, bill_ProductionWithUft)); } continue; } UnfinishedThing unfinishedThing = WorkGiver_DoBill.ClosestUnfinishedThingForBill(pawn, bill_ProductionWithUft); if (unfinishedThing != null) { return(WorkGiver_DoBill.FinishUftJob(pawn, unfinishedThing, bill_ProductionWithUft)); } } if (!WorkGiver_DoBill.TryFindBestBillIngredients(bill, pawn, (Thing)giver, this.chosenIngThings)) { if (FloatMenuMakerMap.makingFor != pawn) { bill.lastIngredientSearchFailTicks = Find.TickManager.TicksGame; } else { JobFailReason.Is(WorkGiver_DoBill.MissingMaterialsTranslated); } continue; } return(this.TryStartNewDoBillJob(pawn, bill, giver)); } JobFailReason.Is(WorkGiver_DoBill.MissingSkillTranslated); } } } return(null); }
protected override IEnumerable <Toil> MakeNewToils() { AddEndCondition(delegate { Thing thing = ((_003CMakeNewToils_003Ec__Iterator0) /*Error near IL_006b: stateMachine*/)._0024this.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; if (thing is Building && !thing.Spawned) { return(JobCondition.Incompletable); } return(JobCondition.Ongoing); }); this.FailOnBurningImmobile(TargetIndex.A); this.FailOn(delegate { IBillGiver billGiver = ((_003CMakeNewToils_003Ec__Iterator0) /*Error near IL_008f: stateMachine*/)._0024this.job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (((_003CMakeNewToils_003Ec__Iterator0) /*Error near IL_008f: stateMachine*/)._0024this.job.bill.DeletedOrDereferenced) { return(true); } if (!billGiver.CurrentlyUsableForBills()) { return(true); } } return(false); }); Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); yield return(new Toil { initAction = delegate { if (((_003CMakeNewToils_003Ec__Iterator0) /*Error near IL_00bf: stateMachine*/)._0024this.job.targetQueueB != null && ((_003CMakeNewToils_003Ec__Iterator0) /*Error near IL_00bf: stateMachine*/)._0024this.job.targetQueueB.Count == 1) { UnfinishedThing unfinishedThing = ((_003CMakeNewToils_003Ec__Iterator0) /*Error near IL_00bf: stateMachine*/)._0024this.job.targetQueueB[0].Thing as UnfinishedThing; if (unfinishedThing != null) { unfinishedThing.BoundBill = (Bill_ProductionWithUft)((_003CMakeNewToils_003Ec__Iterator0) /*Error near IL_00bf: stateMachine*/)._0024this.job.bill; } } } }); /*Error: Unable to find new state assignment for yield return*/; }
private bool TryGetValue(StatRequest req, out float value) { UnfinishedThing unfinishedThing = req.Thing as UnfinishedThing; if (unfinishedThing == null) { value = 0f; return(false); } float num = 0f; for (int i = 0; i < unfinishedThing.ingredients.Count; i++) { num += unfinishedThing.ingredients[i].GetStatValue(StatDefOf.Mass, true) * (float)unfinishedThing.ingredients[i].stackCount; } value = num; return(true); }
public static Toil MakeUnfinishedThingIfNeeded() { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; if (!curJob.RecipeDef.UsesUnfinishedThing) { return; } if (curJob.GetTarget(TargetIndex.B).Thing is UnfinishedThing) { return; } List <Thing> list = Toils_Recipe.CalculateIngredients(curJob, actor); Thing thing = Toils_Recipe.CalculateDominantIngredient(curJob, list); for (int i = 0; i < list.Count; i++) { Thing thing2 = list[i]; actor.Map.designationManager.RemoveAllDesignationsOn(thing2, false); if (thing2.Spawned) { thing2.DeSpawn(DestroyMode.Vanish); } } ThingDef stuff = (!curJob.RecipeDef.unfinishedThingDef.MadeFromStuff) ? null : thing.def; UnfinishedThing unfinishedThing = (UnfinishedThing)ThingMaker.MakeThing(curJob.RecipeDef.unfinishedThingDef, stuff); unfinishedThing.Creator = actor; unfinishedThing.BoundBill = (Bill_ProductionWithUft)curJob.bill; unfinishedThing.ingredients = list; CompColorable compColorable = unfinishedThing.TryGetComp <CompColorable>(); if (compColorable != null) { compColorable.Color = thing.DrawColor; } GenSpawn.Spawn(unfinishedThing, curJob.GetTarget(TargetIndex.A).Cell, actor.Map, WipeMode.Vanish); curJob.SetTarget(TargetIndex.B, unfinishedThing); actor.Reserve(unfinishedThing, curJob, 1, -1, null, true); }; return(toil); }
private static List <Thing> CalculateIngredients(Job job, Pawn actor) { UnfinishedThing unfinishedThing = job.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (unfinishedThing != null) { List <Thing> ingredients = unfinishedThing.ingredients; job.RecipeDef.Worker.ConsumeIngredient(unfinishedThing, job.RecipeDef, actor.Map); job.placedThings = null; return(ingredients); } List <Thing> list = new List <Thing>(); if (job.placedThings != null) { for (int i = 0; i < job.placedThings.Count; i++) { if (job.placedThings[i].Count <= 0) { Log.Error("PlacedThing " + job.placedThings[i] + " with count " + job.placedThings[i].Count + " for job " + job); } else { Thing thing = (job.placedThings[i].Count >= job.placedThings[i].thing.stackCount) ? job.placedThings[i].thing : job.placedThings[i].thing.SplitOff(job.placedThings[i].Count); job.placedThings[i].Count = 0; if (list.Contains(thing)) { Log.Error("Tried to add ingredient from job placed targets twice: " + thing); } else { list.Add(thing); if (job.RecipeDef.autoStripCorpses) { (thing as IStrippable)?.Strip(); } } } } } job.placedThings = null; return(list); }
public static bool CanGetThing(Pawn pawn, Thing t, bool forced) { //tests based on AI.HaulAIUtility.PawnCanAutomaticallyHaulFast UnfinishedThing unfinishedThing = t as UnfinishedThing; if ((unfinishedThing != null && unfinishedThing.BoundBill != null) || !pawn.CanReach(t, PathEndMode.ClosestTouch, pawn.NormalMaxDanger(), mode: TraverseMode.ByPawn) || !pawn.CanReserve(t, 1, -1, null, forced)) { return(false); } if (t.IsBurning()) { JobFailReason.Is("BurningLower".Translate(), null); return(false); } return(true); }
public void SetBoundUft(UnfinishedThing value, bool setOtherLink = true) { if (value != this.boundUftInt) { UnfinishedThing unfinishedThing = this.boundUftInt; this.boundUftInt = value; if (setOtherLink) { if (unfinishedThing != null && unfinishedThing.BoundBill == this) { unfinishedThing.BoundBill = null; } if (value != null && value.BoundBill != this) { this.boundUftInt.BoundBill = this; } } } }
private static Thing CalculateDominantIngredient(Job job, List <Thing> ingredients) { UnfinishedThing uft = job.GetTarget(TargetIndex.B).Thing as UnfinishedThing; if (uft != null && uft.def.MadeFromStuff) { return(uft.ingredients.First((Thing ing) => ing.def == uft.Stuff)); } if (!ingredients.NullOrEmpty()) { if (job.RecipeDef.productHasIngredientStuff) { return(ingredients[0]); } if (job.RecipeDef.products.Any((ThingDefCountClass x) => x.thingDef.MadeFromStuff)) { return(ingredients.Where((Thing x) => x.def.IsStuff).RandomElementByWeight((Thing x) => x.stackCount)); } return(ingredients.RandomElementByWeight((Thing x) => x.stackCount)); } return(null); }
public new static Job FinishUftJob(Pawn pawn, UnfinishedThing uft, Bill_ProductionWithUft bill) { if (pawn.TryGetComp <CompKnowledge>().expertise.Where(x => !x.Key.IsFinished && x.Value >= 1f && x.Key.LabelCap == uft.Stuff.stuffProps.stuffAdjective).Any() == false) { return(null); } Job job = WorkGiverUtility.HaulStuffOffBillGiverJob(pawn, bill.billStack.billGiver, uft); if (job != null && job.targetA.Thing != uft) { return(job); } Job job2 = JobMaker.MakeJob(TechJobDefOf.DocumentTech, (Thing)bill.billStack.billGiver); job2.bill = bill; job2.targetQueueB = new List <LocalTargetInfo> { uft }; job2.countQueue = new List <int> { 1 }; job2.haulMode = HaulMode.ToCellNonStorage; return(job2); }
static IEnumerable <Toil> DoMakeToils(JobDriver_DoBill_Access __instance) { //normal scenario __instance.AddEndCondition(delegate { Thing thing = __instance.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; if (thing is Building && !thing.Spawned) { return(JobCondition.Incompletable); } return(JobCondition.Ongoing); }); __instance.FailOnBurningImmobile(TargetIndex.A); __instance.FailOn(delegate() { if (__instance.job.GetTarget(TargetIndex.A).Thing is Filth) { return(false); } IBillGiver billGiver = __instance.job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (__instance.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 (__instance.job.targetQueueB != null && __instance.job.targetQueueB.Count == 1) { UnfinishedThing unfinishedThing = __instance.job.targetQueueB[0].Thing as UnfinishedThing; if (unfinishedThing != null) { unfinishedThing.BoundBill = (Bill_ProductionWithUft)__instance.job.bill; } } } }); yield return(Toils_Jump.JumpIf(gotoBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.B).NullOrEmpty())); //hauling patch if (Settings.adv_haul_all_ings && __instance.pawn.Faction == Faction.OfPlayer) { Toil checklist = new Toil(); checklist.initAction = delegate() { Pawn actor = checklist.actor; Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B); if (targetQueue.NullOrEmpty()) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } else { foreach (var target in (targetQueue)) { if (target == null || target.Thing.DestroyedOrNull()) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); break; } } } }; yield return(checklist); Toil extract = new Toil(); extract.initAction = delegate() { Pawn actor = extract.actor; Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B); if (!curJob.countQueue.NullOrEmpty()) { if (curJob.countQueue[0] > targetQueue[0].Thing.stackCount) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } else { curJob.SetTarget(TargetIndex.B, targetQueue[0]); targetQueue.RemoveAt(0); curJob.count = curJob.countQueue[0]; curJob.countQueue.RemoveAt(0); } } }; Toil PickUpThing; List <LocalTargetInfo> L = __instance.job.GetTargetQueue(TargetIndex.B); if (L.Count < 2 && (L.Count == 0 || L[0].Thing.def.stackLimit < 2)) { PickUpThing = Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true); } else { PickUpThing = new Toil(); PickUpThing.initAction = delegate() { Pawn actor = PickUpThing.actor; Job curJob = actor.jobs.curJob; Thing thing = curJob.GetTarget(TargetIndex.B).Thing; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B); bool InventorySpawned = thing.ParentHolder == actor.inventory; if (InventorySpawned || !Toils_Haul.ErrorCheckForCarry(actor, thing)) { if (thing.stackCount < curJob.count) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } else { Thing splitThing = thing.SplitOff(curJob.count); if (splitThing.ParentHolder != actor.inventory && !actor.inventory.GetDirectlyHeldThings().TryAdd(splitThing, false)) { actor.jobs.curDriver.EndJobWith(JobCondition.Incompletable); } if (!splitThing.Destroyed && splitThing.stackCount != 0) { targetQueue.Add(splitThing); if (!InventorySpawned) { CompUnloadChecker CUC = splitThing.TryGetComp <CompUnloadChecker>(); if (CUC != null) { CUC.ShouldUnload = true; } } } if (splitThing != thing && actor.Map.reservationManager.ReservedBy(thing, actor, curJob)) { actor.Map.reservationManager.Release(thing, actor, curJob); } } } }; } Toil TakeToHands = new Toil(); TakeToHands.initAction = delegate() { Pawn actor = TakeToHands.actor; Job curJob = actor.jobs.curJob; List <LocalTargetInfo> targetQueue = curJob.GetTargetQueue(TargetIndex.B); if (!targetQueue.NullOrEmpty() && targetQueue[0].Thing.ParentHolder != actor.carryTracker) { actor.inventory.innerContainer.TryTransferToContainer(targetQueue[0].Thing, actor.carryTracker.innerContainer); actor.Reserve(targetQueue[0], curJob); curJob.SetTarget(TargetIndex.B, targetQueue[0]); targetQueue.RemoveAt(0); } }; yield return(extract); Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); yield return(Toils_Jump.JumpIf(PickUpThing, () => __instance.job.GetTarget(TargetIndex.B).Thing.ParentHolder == __instance.pawn.inventory)); yield return(getToHaulTarget); yield return(PickUpThing); yield return(Toils_Jump.JumpIf(extract, () => !__instance.job.countQueue.NullOrEmpty())); yield return(TakeToHands); 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, TakeToHands)); } else { 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_Access.JumpToCollectNextIntoHandsForBillCrutch(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); //one line from normal scenario //cleaning patch if (Settings.adv_cleaning && !Utility.IncapableOfCleaning(__instance.pawn)) { Toil returnToBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); Toil FilthList = new Toil(); FilthList.initAction = delegate() { Job curJob = FilthList.actor.jobs.curJob; if (curJob.GetTargetQueue(TargetIndex.A).NullOrEmpty()) { LocalTargetInfo A = curJob.GetTarget(TargetIndex.A); DoCleanComp comp; if (!Settings.clean_gizmo || (comp = A.Thing?.TryGetComp <DoCleanComp>()) == null || comp.Active) { IEnumerable <Filth> l = Utility.SelectAllFilth(FilthList.actor, A, Settings.adv_clean_num); Utility.AddFilthToQueue(curJob, TargetIndex.A, l, FilthList.actor); FilthList.actor.ReserveAsManyAsPossible(curJob.GetTargetQueue(TargetIndex.A), curJob); } curJob.targetQueueA.Add(A); } }; yield return(FilthList); yield return(Toils_Jump.JumpIf(returnToBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.A).NullOrEmpty())); Toil CleanFilthList = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A, null); yield return(CleanFilthList); yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.A, true)); yield return(Toils_Jump.JumpIf(returnToBillGiver, () => __instance.job.GetTargetQueue(TargetIndex.A).NullOrEmpty())); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, CleanFilthList).JumpIfOutsideHomeArea(TargetIndex.A, CleanFilthList)); Toil clean = new Toil(); clean.initAction = delegate() { Filth filth = clean.actor.jobs.curJob.GetTarget(TargetIndex.A).Thing as Filth; __instance.billStartTick = 0; __instance.ticksSpentDoingRecipeWork = 0; __instance.workLeft = filth.def.filth.cleaningWorkToReduceThickness * filth.thickness; }; clean.tickAction = delegate() { Filth filth = clean.actor.jobs.curJob.GetTarget(TargetIndex.A).Thing as Filth; __instance.billStartTick += 1; __instance.ticksSpentDoingRecipeWork += 1; if (__instance.billStartTick > filth.def.filth.cleaningWorkToReduceThickness) { filth.ThinFilth(); __instance.billStartTick = 0; if (filth.Destroyed) { clean.actor.records.Increment(RecordDefOf.MessesCleaned); __instance.ReadyForNextToil(); return; } } }; clean.defaultCompleteMode = ToilCompleteMode.Never; clean.WithEffect(EffecterDefOf.Clean, TargetIndex.A); clean.WithProgressBar(TargetIndex.A, () => __instance.ticksSpentDoingRecipeWork / __instance.workLeft, true, -0.5f); clean.PlaySustainerOrSound(() => SoundDefOf.Interact_CleanFilth); clean.JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, CleanFilthList); clean.JumpIfOutsideHomeArea(TargetIndex.A, CleanFilthList); yield return(clean); yield return(Toils_Jump.Jump(CleanFilthList)); yield return(returnToBillGiver); } //continuation of normal scenario yield return(Toils_Recipe.MakeUnfinishedThingIfNeeded()); yield return(Toils_Recipe.DoRecipeWork().FailOnDespawnedNullOrForbiddenPlacedThings().FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell)); yield return(Toils_Recipe.FinishRecipeAndStartStoringProduct()); if (!__instance.job.RecipeDef.products.NullOrEmpty() || !__instance.job.RecipeDef.specialProducts.NullOrEmpty()) { 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) { __instance.MapCrutch().resourceCounter.UpdateResourceCounts(); } }; yield return(recount); } yield break; }
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.Learn(curJob.RecipeDef.workSkill, 0.1f * curJob.RecipeDef.workSkillLearnFactor, false); } float num = (curJob.RecipeDef.workSpeedStat != null) ? actor.GetStatValue(curJob.RecipeDef.workSpeedStat, true) : 1f; if (curJob.RecipeDef.workTableSpeedStat != null) { Building_WorkTable building_WorkTable = jobDriver_DoBill.BillGiver as Building_WorkTable; if (building_WorkTable != null) { num *= building_WorkTable.GetStatValue(curJob.RecipeDef.workTableSpeedStat, 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); toil.activeSkill = (() => toil.actor.CurJob.bill.recipe.workSkill); return(toil); }