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);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //this.FailOnDestroyedOrNull(TargetIndex.A);
            //this.FailOnDowned(TargetIndex.A);
            //this.FailOnCannotTouch(TargetIndex.A, PathEndMode.OnCell);

            circle = TargetB.Thing as Building_TMMagicCircleBase;
            Toil gotoPortal = new Toil()
            {
                initAction = () =>
                {
                    pawn.pather.StartPath(TargetA.Cell, PathEndMode.OnCell);
                },
                defaultCompleteMode = ToilCompleteMode.PatherArrival
            };

            yield return(gotoPortal);

            Toil waitFor = new Toil()
            {
                initAction = () =>
                {
                    if (circle != null)
                    {
                        this.pawn.rotationTracker.FaceTarget(circle.GetCircleCenter);
                    }
                    if (this.age > this.durationTicks)
                    {
                        this.EndJobWith(JobCondition.InterruptForced);
                    }
                },
                tickAction = () =>
                {
                    if (this.circle != null)
                    {
                        this.pawn.rotationTracker.FaceTarget(circle.GetCircleCenter);
                    }
                    else
                    {
                        if (TargetB.Thing != null && TargetB.Thing is Building_TMMagicCircleBase)
                        {
                            circle = TargetB.Thing as Building_TMMagicCircleBase;
                        }
                    }
                    if (age > durationTicks)
                    {
                        if (circle != null)
                        {
                            if (circle.IsPending)
                            {
                                this.totalWaitDuration += age;
                                if (totalWaitDuration >= (15 * this.durationTicks))
                                {
                                    this.EndJobWith(JobCondition.Incompletable);
                                }
                                age = 0;
                            }
                            else
                            {
                                this.EndJobWith(JobCondition.InterruptForced);
                            }
                        }
                        else
                        {
                            this.EndJobWith(JobCondition.Succeeded);
                        }
                    }
                    age++;
                },
                defaultCompleteMode = ToilCompleteMode.Never
            };

            waitFor.defaultDuration = this.durationTicks;
            waitFor.WithProgressBar(TargetIndex.A, delegate
            {
                if (this.pawn.DestroyedOrNull() || this.pawn.Dead || this.pawn.Downed)
                {
                    return(1f);
                }
                return((float)((float)age / (float)this.durationTicks));
            }, false, 0f);
            yield return(waitFor);
        }