예제 #1
0
            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);
        }
예제 #3
0
 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));
     }
 }
예제 #4
0
        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);
        }
예제 #5
0
 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;
        }
예제 #8
0
 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]);
 }
예제 #9
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;
            }
        }
예제 #11
0
 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);
 }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
        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);
 }
예제 #18
0
        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));
        }
예제 #19
0
 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);
 }
예제 #20
0
        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);
        }
예제 #21
0
        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);
        }