public ManagerJobProduction(RecipeDef recipe) { Bill = recipe.UsesUnfinishedThing ? new Bill_ProductionWithUft(recipe) : new Bill_Production(recipe); MainProduct = new MainProductTracker(Bill.recipe); Trigger = new TriggerThreshold(this); BillGivers = new BillGiverTracker(this); }
public ManagerJob_Production( RecipeDef recipe ) { Bill = recipe.UsesUnfinishedThing ? new Bill_ProductionWithUft( recipe ) : new Bill_Production( recipe ); _hasMeaningfulIngredientChoices = Dialog_CreateJobsForIngredients.HasPrerequisiteChoices( recipe ); MainProduct = new MainProductTracker( Bill.recipe ); Trigger = new Trigger_Threshold( this ); BillGivers = new BillGiverTracker( this ); History = new History( new[] { Trigger.ThresholdFilter.Summary } ); }
public override string ProductsDescription(Bill_Production bill) { return(ThingCategoryDefOf.ResourcesRaw.label); }
protected override IEnumerable <Toil> MakeNewToils() { base.AddEndCondition(delegate { Thing thing = this.$this.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 = this.$this.job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (this.$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.$this.job.targetQueueB != null && this.$this.job.targetQueueB.Count == 1) { UnfinishedThing unfinishedThing = this.$this.job.targetQueueB[0].Thing as UnfinishedThing; if (unfinishedThing != null) { unfinishedThing.BoundBill = (Bill_ProductionWithUft)this.$this.job.bill; } } } }); yield return(Toils_Jump.JumpIf(gotoBillGiver, () => this.$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.$this.Map.resourceCounter.UpdateResourceCounts(); } }; yield return(recount); } }
public void MirrorBills(Bill_Production sourceBill, Bill_Production destinationBill, bool preserveTargetProduct) { if (!preserveTargetProduct || DoFiltersMatch(sourceBill, destinationBill)) { if (sourceBill.ingredientFilter != null) { destinationBill.ingredientFilter?.CopyAllowancesFrom(sourceBill.ingredientFilter); } } destinationBill.ingredientSearchRadius = sourceBill.ingredientSearchRadius; destinationBill.allowedSkillRange = sourceBill.allowedSkillRange; destinationBill.SetStoreMode(sourceBill.GetStoreMode(), sourceBill.GetStoreZone()); destinationBill.paused = sourceBill.paused; destinationBill.pawnRestriction = sourceBill.pawnRestriction; if (Main.Instance.ShouldMirrorSuspendedStatus()) { destinationBill.suspended = sourceBill.suspended; } var outputCanBeFiltered = CanOutputBeFiltered(destinationBill) || destinationBill.recipe?.WorkerCounter is RecipeWorkerCounter_MakeStoneBlocks; if (sourceBill.repeatMode != BillRepeatModeDefOf.TargetCount || outputCanBeFiltered) { destinationBill.repeatMode = sourceBill.repeatMode; } if (outputCanBeFiltered) { destinationBill.repeatCount = sourceBill.repeatCount; destinationBill.targetCount = sourceBill.targetCount; destinationBill.pauseWhenSatisfied = sourceBill.pauseWhenSatisfied; destinationBill.unpauseWhenYouHave = sourceBill.unpauseWhenYouHave; destinationBill.includeFromZone = sourceBill.includeFromZone; destinationBill.hpRange = sourceBill.hpRange; var sourceThingDef = sourceBill.recipe.ProducedThingDef; var producedThingDef = destinationBill.recipe.ProducedThingDef; if (sourceThingDef != null && producedThingDef != null) { if ((sourceThingDef.IsWeapon || sourceThingDef.IsApparel) && (producedThingDef.IsWeapon || producedThingDef.IsApparel)) { destinationBill.includeEquipped = sourceBill.includeEquipped; } if (sourceThingDef.IsApparel && sourceThingDef.apparel.careIfWornByCorpse && producedThingDef.IsApparel && producedThingDef.apparel.careIfWornByCorpse) { destinationBill.includeTainted = sourceBill.includeTainted; } if (sourceThingDef.HasComp(typeof(CompQuality)) && producedThingDef.HasComp(typeof(CompQuality))) { destinationBill.qualityRange = sourceBill.qualityRange; } if (sourceThingDef.MadeFromStuff && producedThingDef.MadeFromStuff) { destinationBill.limitToAllowedStuff = sourceBill.limitToAllowedStuff; } } } var sourceExtendedData = GetOrCreateExtendedDataFor(sourceBill); if (sourceExtendedData == null) { return; } var destinationExtendedData = GetOrCreateExtendedDataFor(destinationBill); destinationExtendedData?.CloneFrom(sourceExtendedData, !preserveTargetProduct); }
// Delete extended data when bill is deleted public void DeleteExtendedDataFor(Bill_Production bill) { RemoveBillFromLinkSets(bill); _store.Remove(bill); }
public bool UpdateAvailIngredientsCache() { anyBillIngredientsAvailable = false; ingredientsAvailableNow.Clear(); if (AnyPendingRequests == false) { return(false); } //Thing giver = (observedThingHolder as Thing); //QEEMod.TryLog("Updating available ingredients cache for " + giver.ThingID); List <Bill> bills = new List <Bill>(); if (_activeBill != null) { bills.Add(_activeBill); } else { bills = (observedThingHolder as IBillGiver)?.BillStack.Bills; } Dictionary <string, Thing> ingsFoundOnMap = new Dictionary <string, Thing>(); int checkIntervalTicks = QEESettings.instance.ingredientCheckIntervalSeconds * 60; for (int i = 0; i < bills.Count; i++) { Bill_Production curBill = bills[i] as Bill_Production; if (Find.TickManager.TicksGame < curBill.lastIngredientSearchFailTicks + checkIntervalTicks) { QEEMod.TryLog("checked " + curBill.GetUniqueLoadID() + " for avail. ingredients recently, skipping"); continue; } curBill.lastIngredientSearchFailTicks = 0; if (curBill.ShouldDoNow()) { //loop through ingredients foreach (IngredientCount curIng in curBill.recipe.ingredients) { Thing ing; //if same ingredient was found on map in previous loop iteration, don't search map again ingsFoundOnMap.TryGetValue(curIng.FixedIngredient.defName, out ing); if (ing != null) { ingredientsAvailableNow[curBill.GetUniqueLoadID()] = ing; //QEEMod.TryLog("Already found " + ing.Label + " on previous iteration. Skipping"); break; } //check if this ingredient is on the map ing = IngredientUtility.FindClosestIngToBillGiver(curBill, curIng); if (ing != null) { QEEMod.TryLog("Found " + ing.Label + " on map, adding to ingredient cache"); ingsFoundOnMap[curIng.FixedIngredient.defName] = ing; ingredientsAvailableNow[curBill.GetUniqueLoadID()] = ing; anyBillIngredientsAvailable = true; break; } else { //QEEMod.TryLog("no ingredients available"); } } Thing dummy; if (!ingredientsAvailableNow.TryGetValue(curBill.GetUniqueLoadID(), out dummy)) { curBill.lastIngredientSearchFailTicks = Find.TickManager.TicksGame; } } } return(anyBillIngredientsAvailable); }
public bool CanPasteInto(Bill_Production targetBill) { return(_copiedBills.Count == 1 && _copiedBills.First() != targetBill); }
private void Update(Bill_Production thatBill, ref bool actionTaken) { if (thatBill.storeMode != Bill.storeMode) { thatBill.storeMode = Bill.storeMode; actionTaken = true; } if (thatBill.ingredientFilter != Bill.ingredientFilter) { thatBill.ingredientFilter = Bill.ingredientFilter; actionTaken = true; } if (Math.Abs(thatBill.ingredientSearchRadius - Bill.ingredientSearchRadius) > 1) { thatBill.ingredientSearchRadius = Bill.ingredientSearchRadius; actionTaken = true; } if (thatBill.minSkillLevel != Bill.minSkillLevel) { thatBill.minSkillLevel = Bill.minSkillLevel; actionTaken = true; } }
protected override IEnumerable <Toil> MakeNewToils() { Building_FishingSpot fishingSpot = this.job.GetTarget(FishingSpotIndex).Thing as Building_FishingSpot; int fishingDuration = (int)(baseFishingDuration * Rand.Range(0.2f, 1.8f) * fishingSpot.MapFishTracker.DifficultyMultiplier / (ModController.Settings.FishingEfficiency)); Thing thingCaught = null; yield return(Toils_Goto.GotoThing(FishingSpotIndex, fishingSpot.InteractionCell) .FailOnDespawnedNullOrForbidden(FishingSpotIndex)); Toil fishToil = new Toil() { initAction = () => { if (Find.TickManager.TicksGame > fishingSpot.lastFishingStartTick + 60000 * fishingSpot.FishingFrequency) { fishingSpot.lastFishingStartTick = Find.TickManager.TicksGame; } }, tickAction = () => { this.pawn.skills.Learn(job.def.joySkill, job.def.joyXpPerTick); if (pawn.CurJob.GetTarget(FishingSpotIndex).IsValid) { pawn.rotationTracker.FaceCell(pawn.CurJob.GetTarget(FishingSpotIndex).Cell); } }, handlingFacing = true, defaultDuration = fishingDuration, defaultCompleteMode = ToilCompleteMode.Delay }; yield return(fishToil.FailOnDespawnedNullOrForbidden(FishingSpotIndex)); Toil catchFishToil = new Toil() { initAction = () => { string eventText; if (Rand.Value < pawn.GetStatValue(ResourceBank.StatDefOf.FishingChance)) { if (fishingSpot.FishStock > 0 && fishingSpot.FishByWeight.Count > 0) { FishDef fishDefToCatch = fishingSpot.FishByWeight.RandomElementByWeight(item => item.Item1).Item2; if (fishDefToCatch.fishProperties.CanBite && Rand.Value < pawn.GetStatValue(ResourceBank.StatDefOf.FishBiteChance)) { float damage = Rand.Range(fishDefToCatch.fishProperties.BiteDamageRange.min, fishDefToCatch.fishProperties.BiteDamageRange.max); eventText = string.Format(ResourceBank.Strings.FishingTradegyText.Translate(), this.pawn.Name.ToStringShort.CapitalizeFirst(), fishDefToCatch.label); Find.LetterStack.ReceiveLetter(ResourceBank.Strings.FishingTradegyTitle.Translate(), eventText, LetterDefOf.NegativeEvent, this.pawn); this.pawn.TakeDamage(new DamageInfo(fishDefToCatch.fishProperties.BiteDamageDef, damage, 0f, -1f, this.pawn, null, null, DamageInfo.SourceCategory.ThingOrUnknown, this.pawn)); return; } fishingSpot.FishCaught(); bool roeFish = false; if (fishDefToCatch.fishProperties.HasRoe && fishDefToCatch.fishProperties.RoeDef != null && fishDefToCatch.fishProperties.SpawningYearRange != null) { int day = GenDate.DayOfYear(Find.TickManager.TicksAbs, Find.WorldGrid.LongLatOf(this.Map.Tile).x); if (fishDefToCatch.fishProperties.SpawningYearRange.min <= day && day <= fishDefToCatch.fishProperties.SpawningYearRange.max) { if (Rand.Value < ModController.Settings.roeChance) { roeFish = true; } } } if (roeFish) { thingCaught = ThingMaker.MakeThing(fishDefToCatch.fishProperties.RoeDef, null); } else { thingCaught = ThingMaker.MakeThing(fishDefToCatch, null); } thingCaught.stackCount = 1; eventText = ResourceBank.Strings.FishingSuccess.Translate(this.pawn.Name.ToStringShort.CapitalizeFirst(), fishDefToCatch.label); NotifyFishingSuccess(eventText); } else if (Rand.Value < ModController.Settings.junkChance) { //catch non-fish float treasureChance = ModController.Settings.treasureChanceStandart; if (fishingSpot.DeepTerrain) { treasureChance *= treasureDeepAdditionalChance; } ThingSetMakerParams parms = default(ThingSetMakerParams); parms.countRange = new IntRange(1, 1); if (Rand.Value <= treasureChance) { parms.maxTotalMass = ModController.Settings.MaxTreasureMass; parms.totalMarketValueRange = new FloatRange(100.0f, ModController.Settings.treasureMaxValue); parms.qualityGenerator = QualityGenerator.Reward; List <Thing> list = ThingSetMakerDefOf.Reward_ItemsStandard.root.Generate(parms); thingCaught = list.RandomElement(); eventText = ResourceBank.Strings.FishingCaughtTreasureText.Translate(this.pawn.Name.ToStringShort.CapitalizeFirst(), thingCaught.def.label); NotifyCaughtTreasure(eventText); } else { parms.maxTotalMass = ModController.Settings.MaxJunkMass; parms.qualityGenerator = QualityGenerator.BaseGen; List <Thing> list = ResourceBank.ThingSetMakerDefOf.Fishing_ItemJunk.root.Generate(parms); thingCaught = list.RandomElement(); eventText = ResourceBank.Strings.FishingCaughtJunkText.Translate(this.pawn.Name.ToStringShort.CapitalizeFirst(), thingCaught.def.label); NotifyCaughtJunk(eventText); } } } else { eventText = ResourceBank.Strings.FishingCaughtNothingText.Translate(this.pawn.Name.ToStringShort.CapitalizeFirst()); MoteMaker.ThrowMetaIcon(this.pawn.Position, this.Map, ThingDefOf.Mote_IncapIcon); NotifyCaughtNothing(eventText); this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); return; } } }; yield return(catchFishToil); //yield return FinishAndStartHaul(fishingCatch); Toil toilFinishAndStartHaul = new Toil(); toilFinishAndStartHaul.initAction = delegate { Pawn actor = toilFinishAndStartHaul.actor; Job curJob = actor.jobs.curJob; Bill bill = curJob.bill; Log.Message(bill.recipe.defName); Log.Message(thingCaught.def.defName); if (curJob.bill.GetStoreMode() == BillStoreModeDefOf.DropOnFloor) { if (!GenPlace.TryPlaceThing(thingCaught, actor.Position, actor.Map, ThingPlaceMode.Near)) { Log.Error(actor + " could not drop recipe product " + thingCaught + " near " + actor.Position); } actor.jobs.EndCurrentJob(JobCondition.Succeeded); } else { IntVec3 foundCell = IntVec3.Invalid; if (curJob.bill.GetStoreMode() == BillStoreModeDefOf.BestStockpile) { StoreUtility.TryFindBestBetterStoreCellFor(thingCaught, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out foundCell); } else if (curJob.bill.GetStoreMode() == BillStoreModeDefOf.SpecificStockpile) { if (curJob.bill.GetStoreZone().Accepts(thingCaught)) { StoreUtility.TryFindBestBetterStoreCellForIn(thingCaught, actor, actor.Map, StoragePriority.Unstored, actor.Faction, curJob.bill.GetStoreZone().slotGroup, out foundCell); } else { if (!GenPlace.TryPlaceThing(thingCaught, actor.Position, actor.Map, ThingPlaceMode.Near)) { Log.Error(actor + " could not drop recipe product " + thingCaught + " near " + actor.Position); } actor.jobs.EndCurrentJob(JobCondition.Succeeded); } } else { Log.ErrorOnce("Unknown store mode", 9158246); } if (foundCell.IsValid) { actor.carryTracker.TryStartCarry(thingCaught); curJob.SetTarget(HaulableInd, thingCaught); curJob.SetTarget(StoreCellInd, foundCell); curJob.count = 99999; } else { if (!GenPlace.TryPlaceThing(thingCaught, actor.Position, actor.Map, ThingPlaceMode.Near)) { Log.Error("Bill doer could not drop product " + thingCaught + " near " + actor.Position); } actor.jobs.EndCurrentJob(JobCondition.Succeeded); } } }; yield return(toilFinishAndStartHaul); yield return(Toils_Reserve.Reserve(StoreCellInd)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(StoreCellInd); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(StoreCellInd, carryToCell, storageMode: true, tryStoreInSameStorageIfSpotCantHoldWholeStack: 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) { Map.resourceCounter.UpdateResourceCounts(); } }; yield return(recount); }
public override string ProductsDescription(Bill_Production bill) { return(Base.DefOf.DTechshards.label); }
public override int CountProducts(Bill_Production bill) { return(bill.Map.resourceCounter.GetCountIn(Base.DefOf.DTechshards)); }
//public int CountValidThings(List<Thing> things, Bill_Production bill, ThingDef def) public static bool Prefix(ref int __result, RecipeWorkerCounter __instance, List <Thing> things, Bill_Production bill, ThingDef def) { //Vital fix being stackCount, not just # of things. __result = things.Where(t => __instance.CountValidThing(t, bill, def)).Sum(t => t.stackCount); return(false); }
public void OnBillDeleted(Bill_Production bill) { _extendedBillDataStorage?.DeleteExtendedDataFor(bill); BillCopyPasteHandler.RemoveBill(bill); }
public override Job JobOnThing(Pawn pawn, Thing researchBench) { var billGiver = researchBench as IBillGiver; Bill bill; // check if can generate bills if (billGiver == null) { return null; } // require no power or power available if (!billGiver.CurrentlyUsable()) { return null; } if (!pawn.CanReserve(researchBench) || !pawn.CanReach(researchBench.InteractionCell, PathEndMode.OnCell, Danger.Some) || researchBench.IsBurning() || researchBench.IsForbidden(pawn)) { return null; } // researchBench has added bills if (billGiver.BillStack.Count == 1) { // clear bill stack if research is finished or changed if (billGiver.BillStack[0].recipe.defName != Find.ResearchManager.currentProj.defName || ResearchProjectDef.Named(billGiver.BillStack[0].recipe.defName).IsFinished) { billGiver.BillStack.Clear(); } } // Add research bill if it's not added already if (billGiver.BillStack.Count == 0) { bill = new Bill_Production(DefDatabase<RecipeDef>.GetNamed(Find.ResearchManager.currentProj.defName)) { suspended = true }; // NOTE: why suspended??? billGiver.BillStack.AddBill(bill); } else { bill = billGiver.BillStack[0]; } if (!TryFindBestBillIngredients(bill, pawn, researchBench, chosenIngridiens)) { if (FloatMenuMakerMap.making) { JobFailReason.Is(MissingMaterialsTranslated); } return null; } bill.suspended = false; // clear the work table var haulAside = WorkGiverUtility.HaulStuffOffBillGiverJob(pawn, billGiver, null); if (haulAside != null) { return haulAside; } // gather ingridients and do bill var doBill = new Job(JobDefOf.Research, researchBench) { targetQueueB = new List<TargetInfo>(chosenIngridiens.Count), numToBringList = new List<int>(chosenIngridiens.Count) }; foreach (var ingridient in chosenIngridiens) { doBill.targetQueueB.Add(ingridient.thing); doBill.numToBringList.Add(ingridient.count); } doBill.haulMode = HaulMode.ToCellNonStorage; doBill.bill = bill; return doBill; }
/// <summary> /// update bill settings /// </summary> /// <param name="thatBill">Managed bill</param> /// <param name="actionTaken">Any changes made?</param> private void Update( Bill_Production thatBill, ref bool actionTaken ) { if ( thatBill.storeMode != Bill.storeMode ) { #if DEBUG_JOBS debug.AppendLine( "Updating Bill.storeMode" ); #endif thatBill.storeMode = Bill.storeMode; actionTaken = true; } if ( thatBill.ingredientFilter != Bill.ingredientFilter ) { #if DEBUG_JOBS debug.AppendLine( "Updating Bill.ingredientFilter" ); #endif thatBill.ingredientFilter = Bill.ingredientFilter; actionTaken = true; } if ( Math.Abs( thatBill.ingredientSearchRadius - Bill.ingredientSearchRadius ) > 1 ) { #if DEBUG_JOBS debug.AppendLine( "Updating Bill.ingredientSearchRadius" ); #endif thatBill.ingredientSearchRadius = Bill.ingredientSearchRadius; actionTaken = true; } if ( thatBill.allowedSkillRange != Bill.allowedSkillRange ) { #if DEBUG_JOBS debug.AppendLine( "Updating Bill.minSkillLevel" ); #endif thatBill.allowedSkillRange = Bill.allowedSkillRange; actionTaken = true; } }
protected override IEnumerable <Toil> MakeNewToils() { AddEndCondition(delegate { Thing thing = GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; return((!(thing is Building) || thing.Spawned) ? JobCondition.Ongoing : JobCondition.Incompletable); }); this.FailOnBurningImmobile(TargetIndex.A); this.FailOn(delegate { IBillGiver billGiver = job.GetTarget(TargetIndex.A).Thing as IBillGiver; if (billGiver != null) { if (job.bill.DeletedOrDereferenced) { return(true); } if (!billGiver.CurrentlyUsableForBills()) { return(true); } } return(false); }); Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); Toil toil = new Toil(); toil.initAction = delegate { if (job.targetQueueB != null && job.targetQueueB.Count == 1) { UnfinishedThing unfinishedThing = job.targetQueueB[0].Thing as UnfinishedThing; if (unfinishedThing != null) { unfinishedThing.BoundBill = (Bill_ProductionWithUft)job.bill; } } }; yield return(toil); yield return(Toils_Jump.JumpIf(gotoBillGiver, () => job.GetTargetQueue(TargetIndex.B).NullOrEmpty())); Toil extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B); 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, putRemainderInQueue: true, subtractNumTakenFromJobCount: false, failIfStackCountLessThanJobCount: true)); yield return(JumpToCollectNextIntoHandsForBill(getToHaulTarget, TargetIndex.B)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnDestroyedOrNull(TargetIndex.B)); Toil findPlaceTarget2 = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C); yield return(findPlaceTarget2); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, findPlaceTarget2, storageMode: 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 (!job.RecipeDef.products.NullOrEmpty() || !job.RecipeDef.specialProducts.NullOrEmpty()) { yield return(Toils_Reserve.Reserve(TargetIndex.B)); findPlaceTarget2 = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(findPlaceTarget2); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, findPlaceTarget2, storageMode: true, tryStoreInSameStorageIfSpotCantHoldWholeStack: 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) { base.Map.resourceCounter.UpdateResourceCounts(); } }; yield return(recount); } }
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 virtual bool CanPossiblyStoreInStockpile(Bill_Production bill, Zone_Stockpile stockpile) { return(!this.CanCountProducts(bill) || stockpile.GetStoreSettings().AllowedToAccept(this.recipe.products[0].thingDef)); }
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 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 = new Toil(); PickUpThing.initAction = delegate() { Pawn actor = extract.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; } } } } } }; 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()) { 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) { 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); IEnumerable <Filth> l = Utility.SelectAllFilth(FilthList.actor, A); 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 = __instance.job.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 = __instance.job.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, FilthList); clean.JumpIfOutsideHomeArea(TargetIndex.A, FilthList); yield return(clean); yield return(Toils_Jump.Jump(FilthList)); 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 virtual bool CanCountProducts(Bill_Production bill) { return(this.recipe.specialProducts == null && this.recipe.products != null && this.recipe.products.Count == 1); }
// Specific storage stockpile private static void ShowCustomTakeToStockpileMenu(Bill_Production billRaw, Rect inRect) { var extendedBillDataStorage = Main.Instance.GetExtendedBillDataStorage(); var extendedBillData = extendedBillDataStorage.GetExtendedDataFor(billRaw); if (extendedBillData == null) { return; } const float columnWidth = 180f; const float middleColumn = columnWidth + 34f; const float buttonHeight = 30f; var storeRect = new Rect(middleColumn + 3f, inRect.yMin + 114f, columnWidth, buttonHeight); var allStockpiles = Find.VisibleMap.zoneManager.AllZones.OfType <Zone_Stockpile>(); if (Widgets.ButtonText(storeRect, "null")) { var storeOptionList = new List <FloatMenuOption>(); var builtInStoremodesQry = from bsm in DefDatabase <BillStoreModeDef> .AllDefs orderby bsm.listOrder select bsm; foreach (var storeModeDef in builtInStoremodesQry) { var smLocal = storeModeDef; var smLabel = storeModeDef.LabelCap; storeOptionList.Add( new FloatMenuOption( smLabel, delegate { billRaw.storeMode = smLocal; extendedBillData.RemoveTakeToStockpile(); } ) ); } foreach (Zone_Stockpile stockpile in allStockpiles) { var label = "IW.TakeToLabel".Translate() + " " + stockpile.label; var option = new FloatMenuOption( label, delegate { extendedBillData.SetTakeToStockpile(stockpile); billRaw.storeMode = BillStoreModeDefOf.BestStockpile; } ); storeOptionList.Add(option); } Find.WindowStack.Add(new FloatMenu(storeOptionList)); } }
static IEnumerable <Widgets.DropdownMenuElement <Pawn> > Postfix(IEnumerable <Widgets.DropdownMenuElement <Pawn> > values, Dialog_BillConfig __instance) { foreach (Widgets.DropdownMenuElement <Pawn> value in values) { yield return(value); } Bill_Production bill = Traverse.Create(__instance).Field("bill").GetValue <Bill_Production>(); WorkGiverDef workGiver = bill.billStack.billGiver.GetWorkgiver(); List <Pawn> allPrisonersOfColony = PawnsFinder.AllMaps_PrisonersOfColony; Widgets.DropdownMenuElement <Pawn> dropdownMenuElement; foreach (Pawn pawn in allPrisonersOfColony) { if (PrisonLaborUtility.LaborEnabled(pawn)) { if (pawn.WorkTypeIsDisabled(workGiver.workType)) { dropdownMenuElement = new Widgets.DropdownMenuElement <Pawn> { option = new FloatMenuOption(string.Format("{0} ({1})", pawn.LabelShortCap, "WillNever".Translate(workGiver.verb)), null), payload = pawn }; yield return(dropdownMenuElement); } else if (bill.recipe.workSkill != null && !pawn.workSettings.WorkIsActive(workGiver.workType)) { dropdownMenuElement = new Widgets.DropdownMenuElement <Pawn> { option = new FloatMenuOption(string.Format("{0} ({1} {2}, {3})", pawn.LabelShortCap, pawn.skills.GetSkill(bill.recipe.workSkill).Level, bill.recipe.workSkill.label, "NotAssigned".Translate()), delegate { bill.pawnRestriction = pawn; }), payload = pawn }; yield return(dropdownMenuElement); } else if (!pawn.workSettings.WorkIsActive(workGiver.workType)) { dropdownMenuElement = new Widgets.DropdownMenuElement <Pawn> { option = new FloatMenuOption(string.Format("{0} ({1})", pawn.LabelShortCap, "NotAssigned".Translate()), delegate { bill.pawnRestriction = pawn; }), payload = pawn }; yield return(dropdownMenuElement); } else if (bill.recipe.workSkill != null) { dropdownMenuElement = new Widgets.DropdownMenuElement <Pawn> { option = new FloatMenuOption($"{pawn.LabelShortCap} ({pawn.skills.GetSkill(bill.recipe.workSkill).Level} {bill.recipe.workSkill.label})", delegate { bill.pawnRestriction = pawn; }), payload = pawn }; yield return(dropdownMenuElement); } else { dropdownMenuElement = new Widgets.DropdownMenuElement <Pawn> { option = new FloatMenuOption($"{pawn.LabelShortCap}", delegate { bill.pawnRestriction = pawn; }), payload = pawn }; yield return(dropdownMenuElement); } } } }
public bool IsLinkedBill(Bill_Production bill) { return(GetBillSetContaining(bill) != null); }
public static void Postfix(Bill_Production __instance) { var storage = HugsLib.Utils.UtilityWorldObjectManager.GetUtilityWorldObject <ExtendedBillDataStorage>(); storage.GetOrCreateExtendedDataFor(__instance).ExposeData(); }
// Return the associate extended data for a given bill, if found. public ExtendedBillData GetExtendedDataFor(Bill_Production bill) { return(_store.TryGetValue(bill, out ExtendedBillData data) ? data : null); }
public virtual string ProductsDescription(Bill_Production bill) { return(null); }
public override bool CanCountProducts(Bill_Production bill) { return(true); }
public virtual int CountProducts(Bill_Production bill) { ThingDefCountClass thingDefCountClass = recipe.products[0]; ThingDef thingDef = thingDefCountClass.thingDef; if (thingDefCountClass.thingDef.CountAsResource && !bill.includeEquipped && (bill.includeTainted || !thingDefCountClass.thingDef.IsApparel || !thingDefCountClass.thingDef.apparel.careIfWornByCorpse) && bill.includeFromZone == null && bill.hpRange.min == 0f && bill.hpRange.max == 1f && bill.qualityRange.min == QualityCategory.Awful && bill.qualityRange.max == QualityCategory.Legendary && !bill.limitToAllowedStuff) { return(bill.Map.resourceCounter.GetCount(thingDefCountClass.thingDef) + GetCarriedCount(bill, thingDef)); } int num = 0; if (bill.includeFromZone == null) { num = CountValidThings(bill.Map.listerThings.ThingsOfDef(thingDefCountClass.thingDef), bill, thingDef); if (thingDefCountClass.thingDef.Minifiable) { List <Thing> list = bill.Map.listerThings.ThingsInGroup(ThingRequestGroup.MinifiedThing); for (int i = 0; i < list.Count; i++) { MinifiedThing minifiedThing = (MinifiedThing)list[i]; if (CountValidThing(minifiedThing.InnerThing, bill, thingDef)) { num += minifiedThing.stackCount * minifiedThing.InnerThing.stackCount; } } } num += GetCarriedCount(bill, thingDef); } else { foreach (Thing allContainedThing in bill.includeFromZone.AllContainedThings) { Thing innerIfMinified = allContainedThing.GetInnerIfMinified(); if (CountValidThing(innerIfMinified, bill, thingDef)) { num += innerIfMinified.stackCount; } } } if (bill.includeEquipped) { foreach (Pawn item in bill.Map.mapPawns.FreeColonistsSpawned) { List <ThingWithComps> allEquipmentListForReading = item.equipment.AllEquipmentListForReading; for (int j = 0; j < allEquipmentListForReading.Count; j++) { if (CountValidThing(allEquipmentListForReading[j], bill, thingDef)) { num += allEquipmentListForReading[j].stackCount; } } List <Apparel> wornApparel = item.apparel.WornApparel; for (int k = 0; k < wornApparel.Count; k++) { if (CountValidThing(wornApparel[k], bill, thingDef)) { num += wornApparel[k].stackCount; } } ThingOwner directlyHeldThings = item.inventory.GetDirectlyHeldThings(); for (int l = 0; l < directlyHeldThings.Count; l++) { if (CountValidThing(directlyHeldThings[l], bill, thingDef)) { num += directlyHeldThings[l].stackCount; } } } return(num); } return(num); }
public override string ProductsDescription(Bill_Production bill) { return(ThingCategoryDefOf.StoneBlocks.label); }
/// <summary> /// Checks if Bill specifies to drop product on ground, and if so, creates the product and drops it. /// The current grower's active Bill is retrieved programmatically via grower members. /// Heavily modified version of the Toils_Recipe.FinishRecipeAndStartStoringProduct() toil in vanilla. /// </summary> /// <returns></returns> public static Toil TryDropProductOnFloor(Building_GrowerBase_WorkTable vat) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Bill_Production activeBill = vat.billProc.ActiveBill; if (vat?.activeRecipe?.products[0]?.thingDef == null) { if (vat?.activeRecipe?.label != null) { QEEMod.TryLog("No product found in recipe " + vat.activeRecipe.label + ".Ending extract Job."); } else { QEEMod.TryLog("No product found in recipe. Ending extract Job."); } //decrement billstack count if (activeBill.repeatMode == BillRepeatModeDefOf.RepeatCount) { if (activeBill.repeatCount > 0) { activeBill.repeatCount--; } } actor.jobs.EndCurrentJob(JobCondition.Succeeded); } else if (activeBill == null || activeBill.GetStoreMode() == BillStoreModeDefOf.DropOnFloor) { //true if no output stockpile specified in bill options Thing product = ThingMaker.MakeThing(vat.activeRecipe.products[0].thingDef); product.stackCount = vat.activeRecipe.products[0].count; if (activeBill?.GetUniqueLoadID() != null) { QEEMod.TryLog("activeBill: " + activeBill?.GetUniqueLoadID() + " specifies dropping " + product.Label + " on floor."); } else { QEEMod.TryLog("activeBill is null, dropping " + product.Label + " on floor."); } //put the product on the ground on the same cell as the pawn if (GenPlace.TryPlaceThing(product, actor.Position, actor.Map, ThingPlaceMode.Near)) { vat.Notify_ProductExtracted(actor); } else { QEEMod.TryLog(actor + " could not drop recipe product " + product + " near " + actor.Position + ". Ending extract job."); } //decrement billstack count if (activeBill.repeatMode == BillRepeatModeDefOf.RepeatCount) { if (activeBill.repeatCount > 0) { activeBill.repeatCount--; } } actor.jobs.EndCurrentJob(JobCondition.Succeeded); } }; return(toil); } // end TryDropProductOnFloor
public void SetNewRecipe( RecipeDef newRecipe ) { // clear currently assigned bills. CleanUp(); // set the bill on this job Bill = newRecipe.UsesUnfinishedThing ? new Bill_ProductionWithUft( newRecipe ) : new Bill_Production( newRecipe ); _hasMeaningfulIngredientChoices = Dialog_CreateJobsForIngredients.HasPrerequisiteChoices( manager, newRecipe ); // mainproduct and trigger do not change. BillGivers = new BillGiverTracker( this ); // set the last cache time so it gets updated. ForceRecacheOtherRecipe(); // null targets cache so it gets updated _targets = null; }
} // end TryDropProductOnFloor /// <summary> /// Generates the recipe product, then looks for a valid cell in the Bill's output stockpile. /// If a valid cell is found, puts the product into the pawn's arms for transport in a future Toil. /// Uses code from the Toils_Recipe.FinishRecipeAndStartStoringProduct() toil in vanilla. /// </summary> /// <param name="vat"></param> /// <returns></returns> public static Toil StartCarryProductToStockpile(Building_GrowerBase_WorkTable vat) { Toil toil = new Toil(); toil.initAction = delegate { Pawn actor = toil.actor; Job curJob = actor.jobs.curJob; //Skip null checking, as it was done in previous toil Thing product = ThingMaker.MakeThing(vat.activeRecipe.products[0].thingDef); product.stackCount = vat.activeRecipe.products[0].count; Bill_Production activeBill = vat.billProc.ActiveBill; //decrement billstack count if (activeBill.repeatMode == BillRepeatModeDefOf.RepeatCount) { if (activeBill.repeatCount > 0) { activeBill.repeatCount--; } } IntVec3 foundCell = IntVec3.Invalid; //find the best cell to put the product in if (activeBill.GetStoreMode() == BillStoreModeDefOf.BestStockpile) { StoreUtility.TryFindBestBetterStoreCellFor(product, actor, actor.Map, StoragePriority.Unstored, actor.Faction, out foundCell); } else if (activeBill.GetStoreMode() == BillStoreModeDefOf.SpecificStockpile) { StoreUtility.TryFindBestBetterStoreCellForIn(product, actor, actor.Map, StoragePriority.Unstored, actor.Faction, activeBill.GetStoreZone().slotGroup, out foundCell); } else { Log.ErrorOnce("Unknown bill store mode", 9158246); } //if a cell was found in a stockpile, start a hauling job to move the product from the ground to that cell if (foundCell.IsValid) { bool tryCarrySuccess = actor.carryTracker.TryStartCarry(product); QEEMod.TryLog("Valid stockpile found - haul product to cell " + foundCell + ". TryStartCarry() result for " + actor.LabelShort + ": " + tryCarrySuccess); curJob.targetB = foundCell; curJob.targetA = product; curJob.count = 99999; vat.Notify_ProductExtracted(actor); //the next toil in the JobDriver will now haul the carried object to the stockpile } else { QEEMod.TryLog("No stockpile found to haul " + product.Label + " to. Dropping product on ground."); if (GenPlace.TryPlaceThing(product, actor.Position, actor.Map, ThingPlaceMode.Near)) { vat.Notify_ProductExtracted(actor); } else { QEEMod.TryLog(actor + " could not drop recipe product " + product + " near " + actor.Position + ". Ending extract job."); } actor.jobs.EndCurrentJob(JobCondition.Succeeded); } }; return(toil); } // end StartCarryProductToStockpile
public BillTablePriority( Bill_Production bill, Building_WorkTable table, int priority ) { this.bill = bill; this.table = table; this.priority = priority; }
public void RemoveBill(Bill_Production bill) { _copiedBills.Remove(bill); }
public void DoCopy(Bill_Production bill) { _copiedBills.Clear(); _copiedBills.Add(bill); }
public static bool SaveCraftingSettings(BillStack bills, FileInfo fi) { try { // Write Data using (FileStream fileStream = File.Open(fi.FullName, FileMode.Create, FileAccess.Write)) { using (StreamWriter sw = new StreamWriter(fileStream)) { WriteField(sw, "Version", "2"); foreach (Bill b in bills) { if (b is Bill_Production) { Bill_Production p = b as Bill_Production; BillStoreModeDef storeMode = p.GetStoreMode(); Zone_Stockpile storeZone = p.GetStoreZone(); Zone_Stockpile includeFromZone = p.includeFromZone; WriteField(sw, "bill", p.recipe.defName); if (b is Bill_ProductionWithUft) { WriteField(sw, "recipeDefNameUft", p.recipe.defName); } else { WriteField(sw, "recipeDefName", p.recipe.defName); } WriteField(sw, "skillRange", p.allowedSkillRange.ToString()); WriteField(sw, "suspended", p.suspended.ToString()); WriteField(sw, "ingSearchRadius", p.ingredientSearchRadius.ToString()); WriteField(sw, "storeMode", storeMode == BillStoreModeDefOf.SpecificStockpile ? string.Join("/", storeMode.defName, storeZone.GetUniqueLoadID()) : storeMode.defName ); WriteField(sw, "repeatMode", p.repeatMode.defName); WriteField(sw, "repeatCount", p.repeatCount.ToString()); WriteField(sw, "targetCount", p.targetCount.ToString()); WriteField(sw, "includeEquipped", p.includeEquipped.ToString()); WriteField(sw, "includeTainted", p.includeTainted.ToString()); if (includeFromZone != null) { WriteField(sw, "includeFromZone", includeFromZone.GetUniqueLoadID()); } WriteField(sw, "limitToAllowedStuff", p.limitToAllowedStuff.ToString()); WriteField(sw, "pauseWhenSatisfied", p.pauseWhenSatisfied.ToString()); WriteField(sw, "unpauseWhenYouHave", p.unpauseWhenYouHave.ToString()); WriteField(sw, "hpRange", p.hpRange.ToString()); WriteField(sw, "qualityRange", p.qualityRange.ToString()); WriteField(sw, "ingredientFilter", ""); WriteFiltersToFile(p.ingredientFilter, sw); } WriteField(sw, BREAK, BREAK); } } } } catch (Exception e) { LogException("Problem saving crafting bills file '" + fi.Name + "'.", e); return(false); } return(true); }