private static void UpdateBill(Bill_Production bill, bool decrement = true) { if (bill.repeatMode == BillRepeatModeDefOf.RepeatCount) { if (decrement && bill.repeatCount > 0) { bill.repeatCount--; } if (bill.repeatCount == 0) { bill.deleted = true; } } else if (bill.repeatMode == BillRepeatModeDefOf.TargetCount) { int productCount = bill.recipe.WorkerCounter.CountProducts(bill); if (productCount >= bill.targetCount) { bill.deleted = true; } } if (decrement) { Bill_ProductionWithUft billWithUft = bill as Bill_ProductionWithUft; if (billWithUft != null) { billWithUft.ClearBoundUft(); } } }
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); }
private static UnfinishedThing ClosestUnfinishedThingForBill(Pawn pawn, Bill_ProductionWithUft bill) { if (ModCheck.Validate.NoJobAuthors.IsInitialized()) { Predicate <Thing> predicate = (Thing t) => !t.IsForbidden(pawn) && ((UnfinishedThing)t).Recipe == bill.recipe && ((UnfinishedThing)t).ingredients.TrueForAll((Thing x) => bill.IsFixedOrAllowedIngredient(x.def)); IntVec3 position = pawn.Position; Map map = pawn.Map; ThingRequest thingReq = ThingRequest.ForDef(bill.recipe.unfinishedThingDef); PathEndMode peMode = PathEndMode.InteractionCell; TraverseParms traverseParams = TraverseParms.For(pawn, pawn.NormalMaxDanger()); Predicate <Thing> validator = predicate; return((UnfinishedThing)GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, 9999f, validator)); } else { Predicate <Thing> predicate = (Thing t) => !t.IsForbidden(pawn) && ((UnfinishedThing)t).Recipe == bill.recipe && ((UnfinishedThing)t).Creator == pawn && ((UnfinishedThing)t).ingredients.TrueForAll((Thing x) => bill.IsFixedOrAllowedIngredient(x.def)) && pawn.CanReserve(t); IntVec3 position = pawn.Position; Map map = pawn.Map; ThingRequest thingReq = ThingRequest.ForDef(bill.recipe.unfinishedThingDef); PathEndMode peMode = PathEndMode.InteractionCell; TraverseParms traverseParams = TraverseParms.For(pawn, pawn.NormalMaxDanger()); Predicate <Thing> validator = predicate; return((UnfinishedThing)GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, 9999f, validator)); } }
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 = new Job(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); }
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); }
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); }
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; }
public override void ExposeData() { base.ExposeData(); if (Scribe.mode == LoadSaveMode.Saving && this.boundBillInt != null && this.boundBillInt.DeletedOrDereferenced) { this.boundBillInt = null; } Scribe_References.Look <Pawn>(ref this.creatorInt, "creator", false); Scribe_Values.Look <string>(ref this.creatorName, "creatorName", null, false); Scribe_References.Look <Bill_ProductionWithUft>(ref this.boundBillInt, "bill", false); Scribe_Defs.Look <RecipeDef>(ref this.recipeInt, "recipe"); Scribe_Values.Look <float>(ref this.workLeft, "workLeft", 0f, false); Scribe_Collections.Look <Thing>(ref this.ingredients, "ingredients", LookMode.Deep, new object[0]); }
public override void ExposeData() { base.ExposeData(); if (Scribe.mode == LoadSaveMode.Saving && boundBillInt != null && boundBillInt.DeletedOrDereferenced) { boundBillInt = null; } Scribe_References.Look(ref creatorInt, "creator"); Scribe_Values.Look(ref creatorName, "creatorName"); Scribe_References.Look(ref boundBillInt, "bill"); Scribe_Defs.Look(ref recipeInt, "recipe"); Scribe_Values.Look(ref workLeft, "workLeft", 0f); Scribe_Collections.Look(ref ingredients, "ingredients", LookMode.Deep); }
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 Bill_ProductionWithUft BillOnTableForMe(Thing workTable) { if (Recipe.AllRecipeUsers.Contains(workTable.def)) { IBillGiver billGiver = (IBillGiver)workTable; for (int i = 0; i < billGiver.BillStack.Count; i++) { Bill_ProductionWithUft bill_ProductionWithUft = billGiver.BillStack[i] as Bill_ProductionWithUft; if (bill_ProductionWithUft != null && bill_ProductionWithUft.ShouldDoNow() && bill_ProductionWithUft != null && bill_ProductionWithUft.recipe == Recipe) { return(bill_ProductionWithUft); } } } 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); }
private static bool CanStartOrResumeBillJob(WorkGiver_DoBill __instance, 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 != __instance.def.workType) || (Find.TickManager.TicksGame < bill.lastIngredientSearchFailTicks + WorkGiver_DoBill.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; } if (bill is Bill_Medical && ((Bill_Medical)bill).IsSurgeryViolationOnExtraFactionMember(pawn)) { JobFailReason.Is("SurgeryViolationFellowFactionMember".Translate()); 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(true); } continue; } if (AnyUnfinishedThingForBill(__instance, pawn, bill_ProductionWithUft)) { return(true); } } List <ThingCount> chosenIngThings = new List <ThingCount>(); if (!TryFindAnyBillIngredients(__instance, bill, pawn, (Thing)giver, chosenIngThings)) { if (FloatMenuMakerMap.makingFor != pawn) { bill.lastIngredientSearchFailTicks = Find.TickManager.TicksGame; } continue; } return(true); } return(false); }
private Job GetProductionBillJob(Pawn meeseeks, CompMeeseeksMemory memory, SavedJob savedJob, SavedTargetInfo jobTarget, ref JobAvailability jobAvailabilty) { Bill_Production bill = jobTarget.bill as Bill_Production; Job job = null; Logger.MessageFormat(this, "Checking for production bill job..."); if (bill.repeatMode == BillRepeatModeDefOf.RepeatCount && bill.repeatCount < 1) { bill.deleted = true; jobAvailabilty = JobAvailability.Complete; return(null); } else if (bill.repeatMode == BillRepeatModeDefOf.TargetCount) { // Might be here without a billgiver (after a save?) so try to set the current target if (jobTarget.Thing != null) { bill.billStack.billGiver = jobTarget.Thing as IBillGiver; } // Otherwise count them later I guess :P if (bill.Map != null) { int productCount = bill.recipe.WorkerCounter.CountProducts(bill); if (productCount >= bill.targetCount) { bill.deleted = true; jobAvailabilty = JobAvailability.Complete; return(null); } } } Logger.MessageFormat(this, "Checking workstations..."); bool workStationValid = (jobTarget.HasThing && !jobTarget.ThingDestroyed && meeseeks.CanReserve(jobTarget.Thing, 1, -1, null, false) && ((jobTarget.Thing as IBillGiver).CurrentlyUsableForBills() || (jobTarget.Thing as IBillGiver).UsableForBillsAfterFueling())); if (!workStationValid) { Logger.MessageFormat(this, "We think the workstation is invalid looking for new one"); List <Building> buildings = meeseeks.MapHeld.listerBuildings.allBuildingsColonist.Where(building => building is IBillGiver && savedJob.workGiverDef.fixedBillGiverDefs.Contains(building.def) && meeseeks.CanReserve(building, 1, -1, null, false) && ((building as IBillGiver).CurrentlyUsableForBills() || (building as IBillGiver).UsableForBillsAfterFueling())).ToList(); if (buildings.Count > 0) { Logger.MessageFormat(this, "Found new one"); buildings.Sort((a, b) => (int)(meeseeks.PositionHeld.DistanceTo(a.Position) - meeseeks.PositionHeld.DistanceTo(b.Position))); jobTarget.target = buildings[0]; workStationValid = true; } else { Logger.MessageFormat(this, "Found no alternate workstations..."); } } else { Logger.MessageFormat(this, "We think the workstation is valid..."); } if (workStationValid) { IBillGiver billGiver = jobTarget.Thing as IBillGiver; bill.billStack.billGiver = billGiver; Bill_ProductionWithUft bill_ProductionWithUft = bill as Bill_ProductionWithUft; if (bill_ProductionWithUft != null) { if (bill_ProductionWithUft.BoundUft != null) { if (bill_ProductionWithUft.BoundUft.Creator.kindDef == MeeseeksDefOf.MeeseeksKind && meeseeks.CanReserveAndReach(bill_ProductionWithUft.BoundUft, PathEndMode.Touch, Danger.Deadly)) { job = FinishUftJob(meeseeks, bill_ProductionWithUft.BoundUft, bill_ProductionWithUft, billGiver); } } else { Predicate <Thing> validator = (Thing t) => ((UnfinishedThing)t).Recipe == bill.recipe && ((UnfinishedThing)t).Creator.kindDef == MeeseeksDefOf.MeeseeksKind && ((UnfinishedThing)t).ingredients.TrueForAll((Thing x) => bill.IsFixedOrAllowedIngredient(x.def)) && meeseeks.CanReserve(t); UnfinishedThing unfinishedThing = (UnfinishedThing)GenClosest.ClosestThingReachable(meeseeks.Position, meeseeks.Map, ThingRequest.ForDef(bill.recipe.unfinishedThingDef), PathEndMode.InteractionCell, TraverseParms.For(meeseeks), 9999f, validator); if (unfinishedThing != null) { job = FinishUftJob(meeseeks, unfinishedThing, bill_ProductionWithUft, billGiver); } } } if (job == null) { List <ThingCount> chosenIngredients = new List <ThingCount>(); // Screw you I need this function bool result = (bool)typeof(WorkGiver_DoBill).GetMethod("TryFindBestBillIngredients", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { bill, meeseeks, jobTarget.Thing, chosenIngredients }); if (result) { Job haulOffJob = null; job = WorkGiver_DoBill.TryStartNewDoBillJob(meeseeks, bill, billGiver, chosenIngredients, out haulOffJob); } } } if (job == null) { jobAvailabilty = JobAvailability.Delayed; } else { jobAvailabilty = JobAvailability.Available; } return(job); }
private static bool TryCreateBill(StreamReader sr, out Bill_Production bill) { bill = null; string[] kv = null; try { while (!sr.EndOfStream) { if (ReadField(sr, out kv)) { RecipeDef def; switch (kv[0]) { case BREAK: return(true); case "recipeDefName": def = DefDatabase <RecipeDef> .GetNamed(kv[1]); if (def == null) { string msg = "SaveStorageSettings.UnableToLoadRecipeDef".Translate().Replace("%s", kv[1]); Messages.Message(msg, MessageTypeDefOf.SilentInput); Log.Warning(msg); return(false); } if (def.researchPrerequisite != null && !def.researchPrerequisite.IsFinished) { string msg = "SaveStorageSettings.ResearchNotDoneForRecipeDef".Translate().Replace("%s", def.label); Messages.Message(msg, MessageTypeDefOf.SilentInput); Log.Warning(msg); return(false); } bill = new Bill_Production(def); break; case "recipeDefNameUft": def = DefDatabase <RecipeDef> .GetNamed(kv[1]); if (def == null) { string msg = "SaveStorageSettings.UnableToLoadRecipeDef".Translate().Replace("%s", kv[1]); Messages.Message(msg, MessageTypeDefOf.SilentInput); Log.Warning(msg); return(false); } if (def.researchPrerequisite != null && !def.researchPrerequisite.IsFinished) { string msg = "SaveStorageSettings.ResearchNotDoneForRecipeDef".Translate().Replace("%s", def.label); Messages.Message(msg, MessageTypeDefOf.SilentInput); Log.Warning(msg); return(false); } bill = new Bill_ProductionWithUft(def); break; case "skillRange": kv = kv[1].Split('~'); bill.allowedSkillRange = new IntRange(int.Parse(kv[0]), int.Parse(kv[1])); break; case "suspended": bill.suspended = bool.Parse(kv[1]); break; case "ingSearchRadius": bill.ingredientSearchRadius = float.Parse(kv[1]); break; case "repeatMode": bill.repeatMode = null; if (BillRepeatModeDefOf.Forever.defName.Equals(kv[1])) { bill.repeatMode = BillRepeatModeDefOf.Forever; } else if (BillRepeatModeDefOf.RepeatCount.defName.Equals(kv[1])) { bill.repeatMode = BillRepeatModeDefOf.RepeatCount; } else if (BillRepeatModeDefOf.TargetCount.defName.Equals(kv[1])) { bill.repeatMode = BillRepeatModeDefOf.TargetCount; } else if ("TD_ColonistCount".Equals(kv[1])) { EverybodyGetsOneUtil.TryGetRepeatModeDef("TD_ColonistCount", out bill.repeatMode); } else if ("TD_XPerColonist".Equals(kv[1])) { EverybodyGetsOneUtil.TryGetRepeatModeDef("TD_XPerColonist", out bill.repeatMode); } else if ("TD_WithSurplusIng".Equals(kv[1])) { EverybodyGetsOneUtil.TryGetRepeatModeDef("TD_WithSurplusIng", out bill.repeatMode); } if (bill.repeatMode == null) { Log.Warning("Unknown repeatMode of [" + kv[1] + "] for bill " + bill.recipe.defName); bill = null; return(false); } break; case "repeatCount": bill.repeatCount = int.Parse(kv[1]); break; case "storeMode": string[] storeSplit = kv[1].Split('/'); BillStoreModeDef storeMode = DefDatabase <BillStoreModeDef> .GetNamedSilentFail(storeSplit[0]); if (storeMode == null) { Log.Message("Bill [" + bill.recipe.defName + "] storeMode [" + kv[1] + "] cannot be found. Defaulting to [" + BillStoreModeDefOf.BestStockpile.ToString() + "]."); storeMode = BillStoreModeDefOf.BestStockpile; } Zone_Stockpile storeZone = null; if (storeMode == BillStoreModeDefOf.SpecificStockpile) { if (storeSplit.Length > 1) { storeZone = (Zone_Stockpile)Find.CurrentMap?.zoneManager.AllZones.FirstOrFallback(z => z.GetUniqueLoadID() == storeSplit[1]); } if (storeZone == null) { Log.Message("Bill [" + bill.recipe.defName + "] storeZone [" + kv[1] + "] cannot be found. Defaulting to storeMode [" + BillStoreModeDefOf.BestStockpile.ToString() + "]."); storeMode = BillStoreModeDefOf.BestStockpile; } } bill.SetStoreMode(storeMode, storeZone); break; case "targetCount": bill.targetCount = int.Parse(kv[1]); break; case "includeEquipped": bill.includeEquipped = bool.Parse(kv[1]); break; case "includeTainted": bill.includeTainted = bool.Parse(kv[1]); break; case "includeFromZone": Zone_Stockpile zone = (Zone_Stockpile)Find.CurrentMap?.zoneManager.AllZones.FirstOrFallback(z => z.GetUniqueLoadID() == kv[1]); if (zone == null) { Log.Message("Bill [" + bill.recipe.defName + "] includeFromZone [" + kv[1] + "] cannot be found. Defaulting to Everywhere (null)."); } bill.includeFromZone = zone; break; case "limitToAllowedStuff": bill.limitToAllowedStuff = bool.Parse(kv[1]); break; case "pauseWhenSatisfied": bill.pauseWhenSatisfied = bool.Parse(kv[1]); break; case "unpauseWhenYouHave": bill.unpauseWhenYouHave = int.Parse(kv[1]); break; case "hpRange": kv = kv[1].Split('~'); bill.hpRange = new FloatRange(float.Parse(kv[0]), float.Parse(kv[1])); break; case "qualityRange": bill.qualityRange = QualityRange.FromString(kv[1]); break; case "ingredientFilter": ReadFiltersFromFile(bill.ingredientFilter, sr); return(true); } } } } catch { string error = ""; if (bill != null && bill.recipe != null) { error = "Unable to load bill [" + bill.recipe.defName + "]."; } else { error = "Unable to load a bill."; } if (kv == null || kv.Length < 2) { error += " Current line: [" + kv[0] + ":" + kv[1] + "]"; } Log.Warning(error); bill = null; return(false); } return(true); }
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); return(false); }
public new void GetObjectData(object obj, SerializationInfo info, StreamingContext context) { Bill_ProductionWithUft bpwu = (Bill_ProductionWithUft)obj; base.GetObjectData(obj, info, context); info.AddValue("uft", bpwu.BoundUft); }
private static UnfinishedThing ClosestUnfinishedThingForBill(Pawn pawn, Bill_ProductionWithUft bill) { Predicate <Thing> validator = (Thing t) => !t.IsForbidden(pawn) && ((UnfinishedThing)t).Recipe == bill.recipe && ((UnfinishedThing)t).Creator == pawn && ((UnfinishedThing)t).ingredients.TrueForAll((Thing x) => bill.IsFixedOrAllowedIngredient(x.def)) && pawn.CanReserve(t); return((UnfinishedThing)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(bill.recipe.unfinishedThingDef), PathEndMode.InteractionCell, TraverseParms.For(pawn, pawn.NormalMaxDanger()), 9999f, validator)); }
private Job StartOrResumeBillJob(Pawn pawn, IBillGiver giver) { for (int i = 0; i < giver.BillStack.Count; i++) { Bill bill = giver.BillStack[i]; //Log.Message("Processing: " + bill.recipe.defName); 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(); if (giver is Building_СontainmentBreach building_WorkTable) { JobDef jobDef = null; if (bill.recipe != null && ReservationUtility.CanReserveAndReach (pawn, building_WorkTable, PathEndMode.ClosestTouch, DangerUtility.NormalMaxDanger(pawn) , 1, -1, null, false) && building_WorkTable.HasJobOnRecipe(result, out jobDef) && (result.targetB.Thing == null || building_WorkTable.innerContainer.Contains(result.targetB.Thing) || ReservationUtility.CanReserveAndReach (pawn, result.targetB.Thing, PathEndMode.ClosestTouch, DangerUtility.NormalMaxDanger(pawn) , 1, -1, null, false)) && jobDef != null) { try { Log.Message(pawn + " - SUCCESS - " + result.bill.recipe.defName, true); } catch { } result = new Job(jobDef, result.targetA, result.targetB) { targetQueueB = result.targetQueueB, countQueue = result.countQueue, haulMode = result.haulMode, bill = result.bill }; return(result); } else { if (result?.bill.recipe != null) { try { //Log.Message("FAIL: " + result.bill.recipe.defName, true); //Log.Message("TARGET A: " + result.targetA.Thing, true); //Log.Message("TARGET B: " + result.targetB.Thing, true); //Log.Message("1" + (result?.RecipeDef != null).ToString()); //Log.Message("3" + (ReservationUtility.CanReserveAndReach //(pawn, building_WorkTable, PathEndMode.ClosestTouch, DangerUtility.NormalMaxDanger(pawn) //, 1, -1, null, false)).ToString()); //Log.Message("4" + building_WorkTable.HasJobOnRecipe(result, out jobDef).ToString()); //Log.Message("5" + (building_WorkTable.innerContainer.Contains(result.targetB.Thing) || ReservationUtility.CanReserveAndReach //(pawn, result.targetB.Thing, PathEndMode.ClosestTouch, DangerUtility.NormalMaxDanger(pawn) //, 1, -1, null, false)).ToString()); //Log.Message("6" + (jobDef != null).ToString()); } catch { } //Log.Message("----------------", true); } continue; } } return(result); } chosenIngThings.Clear(); return(null); }
private Job StartOrResumeBillJob(Pawn pawn, IBillGiver giver, Thing thing) { 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)) { bill.lastIngredientSearchFailTicks = 0; if (bill.ShouldDoNow() && bill.PawnAllowedToStartAnew(pawn)) { bool issueBill = true; this.magicCircle = thing as Building_TMMagicCircleBase; List <Pawn> billPawns = new List <Pawn>(); billPawns.Clear(); if (bill.recipe is MagicRecipeDef) { MagicRecipeDef magicRecipe = bill.recipe as MagicRecipeDef; CompAbilityUserMagic compMagic = pawn.TryGetComp <CompAbilityUserMagic>(); if (magicCircle.IsActive) { issueBill = false; } if (!magicCircle.CanEverDoBill(bill, out billPawns, magicRecipe)) { issueBill = false; } if (!billPawns.Contains(pawn)) { issueBill = false; } } if (issueBill) { SkillRequirement skillRequirement = bill.recipe.FirstSkillRequirementPawnDoesntSatisfy(pawn); if (skillRequirement != null) { JobFailReason.Is("UnderRequiredSkill".Translate(skillRequirement.minLevel), bill.Label); } else { 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)) { this.magicCircle = thing as Building_TMMagicCircle; if (this.magicCircle != null && bill.recipe is MagicRecipeDef) { this.magicCircle.magicRecipeDef = bill.recipe as MagicRecipeDef; this.magicCircle.MageList.Clear(); magicCircle.MageList.Add(pawn); //Log.Message("assigning magic bill to " + pawn.LabelShort); if (bill.recipe is MagicRecipeDef && billPawns.Count > 1) { for (int j = 0; j < billPawns.Count; j++) { if (billPawns[j] != pawn) { magicCircle.MageList.Add(billPawns[j]); magicCircle.IssueAssistJob(billPawns[j]); //Log.Message("assisting magic bill to " + billPawns[j].LabelShort); } } } this.magicCircle.IsPending = true; } Job result = TryStartNewDoBillJob(pawn, bill, giver); chosenIngThings.Clear(); return(result); } if (FloatMenuMakerMap.makingFor != pawn) { bill.lastIngredientSearchFailTicks = Find.TickManager.TicksGame; } else { JobFailReason.Is(MissingMaterialsTranslated, bill.Label); } chosenIngThings.Clear(); } } } } } chosenIngThings.Clear(); return(null); }
private bool TryCreateBill(Dictionary <string, string> fields, out Bill_Production bill) { bill = null; RecipeDef def; ThingFilter filter = null; ThingFilterReflection reflection = null; bool changed = false; foreach (var field in fields) { string key = field.Key; string value = field.Value; switch (key) { case BREAK: return(true); case "recipeDefName": case "recipeDefNameUft": def = DefDatabase <RecipeDef> .GetNamed(value); if (def == null) { string msg = "SaveStorageSettings.UnableToLoadRecipeDef".Translate().Replace("%s", value); Messages.Message(msg, MessageTypeDefOf.SilentInput); Log.Warning(msg); return(false); } if (def.researchPrerequisite != null && !def.researchPrerequisite.IsFinished) { string msg = "SaveStorageSettings.ResearchNotDoneForRecipeDef".Translate().Replace("%s", def.label); Messages.Message(msg, MessageTypeDefOf.SilentInput); Log.Warning(msg); return(false); } if (key == "recipeDefName") { bill = new Bill_Production(def); } else { bill = new Bill_ProductionWithUft(def); } filter = bill.ingredientFilter; reflection = new ThingFilterReflection(filter); break; case "suspended": bill.suspended = bool.Parse(value); break; case "countEquipped": bill.includeEquipped = bool.Parse(value); break; case "countTainted": bill.includeTainted = bool.Parse(value); break; case "skillRange": string[] skillRange = value.Split('~'); bill.allowedSkillRange = new IntRange(int.Parse(skillRange[0]), int.Parse(skillRange[1])); break; case "ingSearchRadius": bill.ingredientSearchRadius = float.Parse(value); break; case "repeatMode": bill.repeatMode = null; if (BillRepeatModeDefOf.Forever.defName.Equals(value)) { bill.repeatMode = BillRepeatModeDefOf.Forever; } else if (BillRepeatModeDefOf.RepeatCount.defName.Equals(value)) { bill.repeatMode = BillRepeatModeDefOf.RepeatCount; } else if (BillRepeatModeDefOf.TargetCount.defName.Equals(value)) { bill.repeatMode = BillRepeatModeDefOf.TargetCount; } else if ("TD_ColonistCount".Equals(value)) { EverybodyGetsOneUtil.TryGetRepeatModeDef("TD_ColonistCount", out bill.repeatMode); } else if ("TD_XPerColonist".Equals(value)) { EverybodyGetsOneUtil.TryGetRepeatModeDef("TD_XPerColonist", out bill.repeatMode); } else if ("TD_WithSurplusIng".Equals(value)) { EverybodyGetsOneUtil.TryGetRepeatModeDef("TD_WithSurplusIng", out bill.repeatMode); } if (bill.repeatMode == null) { Log.Warning("Unknown repeatMode of [" + value + "] for bill " + bill.recipe.defName); bill = null; return(false); } break; case "repeatCount": bill.repeatCount = int.Parse(value); break; case "targetCount": bill.targetCount = int.Parse(value); break; case "pauseWhenSatisfied": bill.pauseWhenSatisfied = bool.Parse(value); break; case "unpauseWhenYouHave": bill.unpauseWhenYouHave = int.Parse(value); break; case "hpRange": string[] hpRange = value.Split('~'); bill.hpRange = new FloatRange(float.Parse(hpRange[0]), float.Parse(hpRange[1])); break; case "qualityRange": if (!string.IsNullOrEmpty(value) && value.IndexOf('~') != -1) { string[] qualityRange = value.Split('~'); bill.qualityRange = new QualityRange( (QualityCategory)Enum.Parse(typeof(QualityCategory), qualityRange[0], true), (QualityCategory)Enum.Parse(typeof(QualityCategory), qualityRange[1], true)); } break; case "onlyAllowedIngredients": bill.limitToAllowedStuff = bool.Parse(value); break; case "storeMode": BillStoreModeDef storeMode = DefDatabase <BillStoreModeDef> .GetNamedSilentFail(value); if (storeMode == null || value == BillStoreModeDefOf.SpecificStockpile.ToString()) { storeMode = BillStoreModeDefOf.BestStockpile; } bill.SetStoreMode(storeMode); break; case "storeZone": var destinationZone = (Zone_Stockpile)Current.Game.CurrentMap.zoneManager.AllZones.Find(z => z.label == value); if (destinationZone != null) { bill.SetStoreMode(BillStoreModeDefOf.SpecificStockpile, destinationZone); } else { bill.SetStoreMode(BillStoreModeDefOf.BestStockpile); } break; case "lookIn": var ingredientZone = (Zone_Stockpile)Current.Game.CurrentMap.zoneManager.AllZones.Find(z => z.label == value); bill.includeFromZone = ingredientZone; break; case "allowedDefs": reflection.AllowedDefs.Clear(); if (value != null) { HashSet <string> expected = new HashSet <string>(value.Split('/')); IEnumerable <ThingDef> all = reflection.AllStorableThingDefs; var expectedContained = from thing in all where expected.Contains(thing.defName) select thing; reflection.AllowedDefs.AddRange(expectedContained.ToList()); } changed = true; break; case "allowedHitPointsPercents": if (!string.IsNullOrEmpty(value) && value.IndexOf(':') != -1) { string[] values = value.Split(':'); float min = float.Parse(values[0]); float max = float.Parse(values[1]); filter.AllowedHitPointsPercents = new FloatRange(min, max); changed = true; } break; case "allowedQualities": if (!string.IsNullOrEmpty(value) && value.IndexOf(':') != -1) { string[] values = value.Split(':'); filter.AllowedQualityLevels = new QualityRange( (QualityCategory)Enum.Parse(typeof(QualityCategory), values[0], true), (QualityCategory)Enum.Parse(typeof(QualityCategory), values[1], true)); changed = true; } break; case "disallowedSpecialFilters": reflection.DisallowedSpecialFilters.Clear(); if (!string.IsNullOrEmpty(value)) { HashSet <string> expected = new HashSet <string>(value.Split('/')); List <SpecialThingFilterDef> l = new List <SpecialThingFilterDef>(); foreach (SpecialThingFilterDef specialDef in DefDatabase <SpecialThingFilterDef> .AllDefs) { if (specialDef != null && specialDef.configurable && expected.Contains(specialDef.defName)) { l.Add(specialDef); } } reflection.DisallowedSpecialFilters = l; } changed = true; break; } } if (changed) { reflection.SettingsChangedCallback(); } return(false); }