Пример #1
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Toil wait = new Toil();

            wait.tickAction = delegate
            {
                Pawn actor = wait.actor;
                this.gatherProgress += actor.GetStatValue(StatDefOf.AnimalGatherSpeed, true);
                if (this.gatherProgress >= this.WorkTotal)
                {
                    Pawn milkedPawn = actor;
                    milkedPawn.TryGetComp <CompMilkableHumanoid>().GatherMilkSelf();
                    actor.jobs.EndCurrentJob(JobCondition.Succeeded, true);
                }
            };

            wait.AddEndCondition(delegate
            {
                Pawn milkedPawn = wait.actor;
                if (!milkedPawn.TryGetComp <CompMilkableHumanoid>().ActiveAndCanBeMilked)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => this.gatherProgress / this.WorkTotal, false, -0.5f);
            yield return(wait);
        }
Пример #2
0
        private IEnumerable <Toil> ChargeToils(IChargeSource charger, PathEndMode pathMode, Action initAction, Action tickAction)
        {
            this.FailOnDestroyedOrNull(PowerSourceIndex);
            this.FailOn(() => !charger.Available);
            this.FailOn(() =>
                        EnergyNeed == null ||
                        !EnergyNeed.CanBeSatisfied ||
                        EnergyNeed.Satisfied ||
                        charger == null ||
                        !charger.Available ||
                        !pawn.CanReach(PowerSource, pathMode, Danger.Deadly));

            yield return(Toils_Goto
                         .GotoThing(PowerSourceIndex, pathMode)
                         .FailOnDestroyedNullOrForbidden(PowerSourceIndex));

            var charge = new Toil()
                         .WithProgressBar(PowerSourceIndex, () => EnergyNeed.CurLevelPercentage, true);

            charge.defaultCompleteMode = ToilCompleteMode.Never;
            charge.AddEndCondition(() =>
                                   EnergyNeed.Satisfied
                    ? JobCondition.Succeeded
                    : JobCondition.Ongoing);
            if (initAction != null)
            {
                charge.initAction = initAction;
            }
            if (tickAction != null)
            {
                charge.tickAction = tickAction;
            }
            yield return(charge);
        }
Пример #3
0
 protected override IEnumerable<Toil> MakeNewToils()
 {
     Building_DroidChargePad charger = (Building_DroidChargePad)TargetThingA;
     Toil goToPad = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.OnCell);
     goToPad.AddFailCondition(() => { return !charger.IsAvailable(pawn); });
     yield return goToPad;
     Droid droid = (Droid)this.pawn;
     Toil charge = new Toil();
     charge.initAction = () =>
         {
             if (charger.Position != droid.Position)
             {
                 pawn.jobs.EndCurrentJob(JobCondition.Errored);
             }
         };
     charge.defaultCompleteMode = ToilCompleteMode.Never;
     charge.AddFailCondition(() =>
         { return !charger.IsAvailable(pawn); });
     charge.AddEndCondition(() =>
         {
             if (!droid.DesiresCharge())
             {
                 return JobCondition.Succeeded;
             }
             return JobCondition.Ongoing;
         });
     yield return charge;
 }
        protected override IEnumerable<Toil> MakeNewToils()
        {
            //Set what will cause the job to fail:
            this.FailOnDestroyedOrForbidden(CorpseIndex);
            this.FailOnBurningImmobile(CorpseIndex);
            this.FailOn(() => !(pawn is Droid));

            //Reserve the corpse
            yield return Toils_Reserve.Reserve(CorpseIndex);
            //Go to the corpse
            yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch);
            Toil toil = new Toil();
            toil.initAction = () =>
                {
                    //Check if the pawn is set to strip bodies, if yes then strip it, otherwise skip this step
                    Droid droid = (Droid)pawn;
                    CremationWorker worker = droid.work.specialist.GetWorker<CremationWorker>();
                    if (worker.StripBodies)
                    {
                        Corpse corpse = (Corpse)TargetThingA;
                        if (corpse.AnythingToStrip())
                            corpse.Strip();
                    }
                };
            toil.defaultCompleteMode = ToilCompleteMode.Delay;
            toil.defaultDuration = 300;
            toil.WithEffect(() => DefDatabase<EffecterDef>.GetNamed("Cremate"), CorpseIndex);
            toil.WithSustainer(() => DefDatabase<SoundDef>.GetNamed("Recipe_Cremate"));
            toil.AddFinishAction(() => TargetA.Thing.Destroy());
            toil.FailOnBurningImmobile(CorpseIndex);
            toil.FailOnDestroyedOrForbidden(CorpseIndex);
            toil.AddEndCondition(() => this.ticksLeftThisToil <= 0 ? JobCondition.Succeeded : JobCondition.Ongoing);
            yield return toil;
        }
Пример #5
0
        public static IEnumerable <Toil> MakePartnerWoohoo(Pawn pawn, Pawn mate, Building_Bed bed)
        {
            int tick = 400;

            void NewFunction()
            {
                if (PawnHelper.IsNotWoohooing(mate))
                {
                    /* Log.Message("Asking for love job"); */
                    Job newJob = new Job(Constants.JobWooHooRecieve, pawn, bed)
                    {
                        playerForced = true //its important
                    };
                    mate.jobs.StartJob(newJob, JobCondition.InterruptForced);

                    /* Log.Message("Make Lover Go To Bed"); */
                    //mate.jobs.StartJob(, JobCondition.InterruptForced);
                }
                else
                {
                    /* Log.Message("Partner already doin it"); */
                }
            }

            Toil t = new Toil()
            {
                socialMode = RandomSocialMode.Off,
                tickAction = NewFunction,
                initAction = NewFunction
            };

            t.AddEndCondition(() => PawnHelper.IsNotWoohooing(mate) && (tick--) > 0 ? JobCondition.Ongoing : JobCondition.Succeeded);

            yield return(t);
        }
        // Token: 0x06000010 RID: 16 RVA: 0x00002787 File Offset: 0x00000987
        protected override IEnumerable <Toil> MakeNewToils()
        {
            var wait = new Toil();

            wait.tickAction = delegate
            {
                var actor = wait.actor;
                gatherProgress += actor.GetStatValue(StatDefOf.AnimalGatherSpeed);
                if (!(gatherProgress >= WorkTotal))
                {
                    return;
                }

                actor.TryGetComp <CompWidowMilkableHumanoid>().GatherMilkSelf();
                actor.jobs.EndCurrentJob(JobCondition.Succeeded);
            };
            wait.AddEndCondition(delegate
            {
                var actor  = wait.actor;
                var result = !actor.TryGetComp <CompWidowMilkableHumanoid>().ActiveAndCanBeMilked
                    ? JobCondition.Incompletable
                    : JobCondition.Ongoing;

                return(result);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => gatherProgress / WorkTotal);
            yield return(wait);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            Toil wait = new Toil();

            wait.initAction = delegate()
            {
                Pawn actor = wait.actor;
                actor.pather.StopDead();
            };
            wait.tickAction = delegate()
            {
                Pawn       actor = wait.actor;
                Plant_Nest nest  = (Plant_Nest)this.job.targetA.Thing;
                this.gatherProgress += actor.GetStatValue(StatDefOf.PlantWorkSpeed, true);
                if (this.gatherProgress >= this.WorkTotal)
                {
                    actor.jobs.EndCurrentJob(JobCondition.Succeeded, true, true);
                    if (!Rand.Chance(actor.GetStatValue(StatDefOf.PlantHarvestYield, true)))
                    {
                        nest.nectarAmount /= 2;
                        MoteMaker.ThrowText((actor.DrawPos + nest.DrawPos) / 2f, actor.Map, "TextMote_ProductWasted".Translate(), 3.65f);
                    }
                    else
                    {
                        int i = GenMath.RoundRandom((float)1 * (float)nest.nectarAmount);
                        int totalExtracted = 0;
                        while (i > 0)
                        {
                            int num = Mathf.Clamp(i, 1, PurpleIvyDefOf.PI_Nectar.stackLimit);
                            i -= num;
                            totalExtracted += num;
                            Thing thing = ThingMaker.MakeThing(PurpleIvyDefOf.PI_Nectar, null);
                            thing.stackCount = num;
                            GenPlace.TryPlaceThing(thing, actor.Position, actor.Map, ThingPlaceMode.Near, null, null, default(Rot4));
                        }
                        nest.nectarAmount -= totalExtracted;
                        if (nest.nectarAmount < 0)
                        {
                            nest.nectarAmount = 0;
                        }
                    }
                }
            };
            wait.FailOnDespawnedOrNull(TargetIndex.A);
            wait.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            wait.AddEndCondition(delegate
            {
                return(JobCondition.Ongoing);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => this.gatherProgress / this.WorkTotal, false, -0.5f);
            wait.activeSkill = (() => SkillDefOf.Plants);
            yield return(wait);

            yield break;
        }
        // Token: 0x06000046 RID: 70 RVA: 0x000040B9 File Offset: 0x000022B9
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            this.FailOnDowned(TargetIndex.A);
            this.FailOnNotCasualInterruptible(TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            Toil wait = new Toil();

            wait.initAction = delegate()
            {
                Pawn actor = wait.actor;
                Pawn pawn  = (Pawn)wait.actor.CurJob.GetTarget(TargetIndex.A).Thing;
                actor.pather.StopDead();
                PawnUtility.ForceWait(pawn, 15000, null, true);
            };
            wait.tickAction = delegate()
            {
                Pawn actor = wait.actor;
                this.gatherProgress += actor.GetStatValue(StatDefOf.AnimalGatherSpeed, true);
                bool flag = this.gatherProgress >= this.WorkTotal;
                if (flag)
                {
                    this.GetComp((Pawn)((Thing)this.job.GetTarget(TargetIndex.A))).Gathered(this.pawn);
                    actor.jobs.EndCurrentJob(JobCondition.Succeeded, true, true);
                }
            };
            wait.AddFinishAction(delegate
            {
                Pawn pawn = (Pawn)wait.actor.CurJob.GetTarget(TargetIndex.A).Thing;
                bool flag = pawn.jobs.curJob.def == JobDefOf.Wait_MaintainPosture;
                if (flag)
                {
                    pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, true, true);
                }
            });
            wait.FailOnDespawnedOrNull(TargetIndex.A);
            wait.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            wait.AddEndCondition(delegate
            {
                bool flag = !this.GetComp((Pawn)((Thing)this.job.GetTarget(TargetIndex.A))).ActiveAndFull;
                JobCondition result;
                if (flag)
                {
                    result = JobCondition.Incompletable;
                }
                else
                {
                    result = JobCondition.Ongoing;
                }
                return(result);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => this.gatherProgress / this.WorkTotal, false, -0.5f);
            yield return(wait);

            yield break;
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            this.FailOnDowned(TargetIndex.A);
            this.FailOnNotCasualInterruptible(TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            Toil wait = new Toil();

            wait.initAction = delegate()
            {
                Pawn actor = wait.actor;
                Pawn pawn  = (Pawn)this.job.GetTarget(TargetIndex.A).Thing;
                actor.pather.StopDead();
                PawnUtility.ForceWait(pawn, 15000, null, true);
            };
            wait.tickAction = delegate()
            {
                Pawn actor = wait.actor;
                actor.skills.Learn(SkillDefOf.Animals, 0.13f, false);
                this.gatherProgress += actor.GetStatValue(StatDefOf.AnimalGatherSpeed, true);
                if (this.gatherProgress >= this.WorkTotal)
                {
                    this.GetSpecificComp((Pawn)((Thing)this.job.GetTarget(TargetIndex.A))).InformGathered(this.pawn);
                    actor.jobs.EndCurrentJob(JobCondition.Succeeded, true, true);
                    if (ModLister.HasActiveModWithName("Alpha Animals"))
                    {
                        actor.health.AddHediff(HediffDef.Named("AA_GatheredResource"));
                    }
                }
            };
            wait.AddFinishAction(delegate
            {
                Pawn pawn = (Pawn)this.job.GetTarget(TargetIndex.A).Thing;
                if (pawn != null && pawn.CurJobDef == JobDefOf.Wait_MaintainPosture)
                {
                    pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, true, true);
                }
            });
            wait.FailOnDespawnedOrNull(TargetIndex.A);
            wait.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            wait.AddEndCondition(delegate
            {
                if (!this.GetComp((Pawn)((Thing)this.job.GetTarget(TargetIndex.A))).ActiveAndFull)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => this.gatherProgress / this.WorkTotal, false, -0.5f);
            wait.activeSkill = (() => SkillDefOf.Animals);

            yield return(wait);

            yield break;
        }
Пример #10
0
        protected IEnumerable <Toil> MakeNewToils(HediffDef hediffDef)
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            //this.FailOnDowned(TargetIndex.A);
            this.FailOnAggroMentalState(TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            Toil wait = new Toil();

            wait.initAction = delegate
            {
                Pawn actor2 = wait.actor;
                Pawn pawn2  = (Pawn)job.GetTarget(TargetIndex.A).Thing;
                actor2.pather.StopDead();
                PawnUtility.ForceWait(pawn2, 15000, null, maintainPosture: true);
            };
            wait.tickAction = delegate
            {
                ticks++;
            };
            wait.AddFinishAction(delegate
            {
                Pawn pawn = (Pawn)job.GetTarget(TargetIndex.A).Thing;
                if (pawn != null)
                {
                    Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(hediffDef, false);
                    if (hediff == null)
                    {
                        hediff = HediffMaker.MakeHediff(hediffDef, pawn, null);
                        pawn.health.AddHediff(hediff, null, null);
                    }
                    else
                    {
                        pawn.health.hediffSet.hediffs.Remove(hediff);
                    }
                    if (pawn.CurJobDef == JobDefOf.Wait_MaintainPosture)
                    {
                        pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                    }
                }
            });
            wait.FailOnDespawnedOrNull(TargetIndex.A);
            wait.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            wait.AddEndCondition(() =>
            {
                if (ticks >= BGP.Unchain_Ticks)
                {
                    return(JobCondition.Succeeded);
                }
                return(JobCondition.Ongoing);
            }
                                 );
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => ticks / BGP.Unchain_Ticks);
            yield return(wait);
        }
Пример #11
0
        // Token: 0x06000014 RID: 20 RVA: 0x000027CB File Offset: 0x000009CB
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            this.FailOnDowned(TargetIndex.A);
            this.FailOnNotCasualInterruptible(TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            var wait = new Toil();

            wait.initAction = delegate
            {
                var actor = wait.actor;
                var thing = (Pawn)wait.actor.CurJob.GetTarget(TargetIndex.A).Thing;
                actor.pather.StopDead();
                PawnUtility.ForceWait(thing, 15000, null, true);
            };
            wait.tickAction = delegate
            {
                var actor = wait.actor;
                actor.skills.Learn(SkillDefOf.Social, 0.142999992f);
                gatherProgress += actor.GetStatValue(StatDefOf.AnimalGatherSpeed);
                if (!(gatherProgress >= WorkTotal))
                {
                    return;
                }

                var thing = (Pawn)(Thing)job.GetTarget(TargetIndex.A);
                thing.TryGetComp <CompWidowMilkableHumanoid>().GatherMilk(pawn);
                actor.jobs.EndCurrentJob(JobCondition.Succeeded);
            };
            wait.AddFinishAction(delegate
            {
                var thing = (Pawn)wait.actor.CurJob.GetTarget(TargetIndex.A).Thing;
                if (thing.jobs.curJob.def == JobDefOf.Wait_MaintainPosture)
                {
                    thing.jobs.EndCurrentJob(JobCondition.InterruptForced);
                }
            });
            wait.FailOnDespawnedOrNull(TargetIndex.A);
            wait.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            wait.AddEndCondition(delegate
            {
                var thing  = (Pawn)(Thing)job.GetTarget(TargetIndex.A);
                var result = !thing.TryGetComp <CompWidowMilkableHumanoid>().ActiveAndCanBeMilked
                    ? JobCondition.Incompletable
                    : JobCondition.Ongoing;

                return(result);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => gatherProgress / WorkTotal);
            yield return(wait);
        }
Пример #12
0
        /*
         * //maybe change?
         * protected abstract int GatherResourcesIntervalDays
         * {
         *      get;
         * }
         *
         * //add breastsize modifier?
         * protected abstract int ResourceAmount
         * {
         *      get;
         * }
         * //add more  milks?
         * protected abstract ThingDef ResourceDef
         * {
         *      get;
         * }
         */

        protected override IEnumerable <Toil> MakeNewToils()
        {
            ToilFailConditions.FailOnDespawnedNullOrForbidden <JobDriver_GatherHumanBodyResources>(this, TargetIndex.A);
            ToilFailConditions.FailOnNotCasualInterruptible <JobDriver_GatherHumanBodyResources>(this, TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            Toil wait = new Toil();

            wait.initAction = delegate
            {
                Pawn            milker  = base.pawn;
                LocalTargetInfo target  = base.job.GetTarget(TargetIndex.A);
                Pawn            target2 = (Pawn)target.Thing;
                milker.pather.StopDead();
                PawnUtility.ForceWait(target2, 15000, null, true);
            };
            wait.tickAction = delegate
            {
                Pawn milker = base.pawn;
                milker.skills.Learn(SkillDefOf.Animals, 0.13f, false);
                gatherProgress += StatExtension.GetStatValue(milker, StatDefOf.AnimalGatherSpeed, true);
                if (gatherProgress >= WorkTotal)
                {
                    GetComp((Pawn)base.job.GetTarget(TargetIndex.A)).Gathered(base.pawn);
                    milker.jobs.EndCurrentJob(JobCondition.Succeeded, true);
                }
            };
            wait.AddFinishAction((Action) delegate
            {
                Pawn milker            = base.pawn;
                LocalTargetInfo target = base.job.GetTarget(TargetIndex.A);
                Pawn target2           = (Pawn)target.Thing;
                if (target2 != null && target2.CurJobDef == JobDefOf.Wait_MaintainPosture)
                {
                    milker.jobs.EndCurrentJob(JobCondition.InterruptForced, true);
                }
            });
            ToilFailConditions.FailOnDespawnedOrNull <Toil>(wait, TargetIndex.A);
            ToilFailConditions.FailOnCannotTouch <Toil>(wait, TargetIndex.A, PathEndMode.Touch);
            wait.AddEndCondition((Func <JobCondition>) delegate
            {
                if (GetComp((Pawn)base.job.GetTarget(TargetIndex.A)).ActiveAndFull)
                {
                    return(JobCondition.Ongoing);
                }
                return(JobCondition.Incompletable);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            ToilEffects.WithProgressBar(wait, TargetIndex.A, (Func <float>)(() => gatherProgress / WorkTotal), false, -0.5f);
            wait.activeSkill = (() => SkillDefOf.Animals);
            yield return(wait);
        }
Пример #13
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            ToilFailConditions.FailOnDespawnedNullOrForbidden(this, TargetIndex.A);
            ToilFailConditions.FailOnNotCasualInterruptible(this, TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            Toil wait = new Toil();

            wait.initAction = delegate()
            {
                Pawn actor = wait.actor;
                Pawn pawn  = (Pawn)job.GetTarget(TargetIndex.A).Thing;
                actor.pather.StopDead();
                PawnUtility.ForceWait(pawn, 15000, null, true);
            };
            wait.tickAction = delegate()
            {
                Pawn actor = wait.actor;
                actor.skills.Learn(SkillDefOf.Animals, 0.13f, false);
                gatherProgress += StatExtension.GetStatValue(actor, StatDefOf.AnimalGatherSpeed, true);
                if (gatherProgress >= WorkTotal)
                {
                    GetComp((Pawn)((Thing)job.GetTarget(TargetIndex.A))).Gathered(this.pawn);
                    actor.jobs.EndCurrentJob(JobCondition.Succeeded, true);
                }
            };
            wait.AddFinishAction(delegate()
            {
                Pawn pawn = (Pawn)job.GetTarget(TargetIndex.A).Thing;
                if (pawn != null && pawn.CurJobDef == JobDefOf.Wait_MaintainPosture)
                {
                    pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, true);
                }
            });
            ToilFailConditions.FailOnDespawnedOrNull <Toil>(wait, TargetIndex.A);
            ToilFailConditions.FailOnCannotTouch <Toil>(wait, TargetIndex.A, PathEndMode.Touch);
            wait.AddEndCondition(delegate()
            {
                if (!GetComp((Pawn)((Thing)this.job.GetTarget(TargetIndex.A))).ActiveAndFull)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            ToilEffects.WithProgressBar(wait, TargetIndex.A, () => this.gatherProgress / this.WorkTotal, false, -0.5f);
            wait.activeSkill = (() => SkillDefOf.Animals);
            yield return(wait);

            yield break;
        }
Пример #14
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Set what will cause the job to fail
            this.FailOnBurningImmobile(RepairStationIndex);
            this.FailOnDestroyedOrForbidden(RepairStationIndex);
            this.FailOn(delegate
            {
                return(Repairee == null || !Repairee.ShouldGetRepairs);
            });

            //Reserve the repair station
            yield return(Toils_Reserve.Reserve(RepairStationIndex));

            //Go to the repair station interaction cell
            yield return(Toils_Goto.GotoThing(RepairStationIndex, PathEndMode.InteractionCell));

            //Make a new toil that sets the droid to repair mode, then wait until fully repaired
            Toil toil = new Toil();

            toil.FailOnDestroyedOrForbidden(RepairStationIndex);
            toil.FailOn(() =>
            {
                return(Repairee == null || RPS == null || Repairee.Pawn.Position != TargetThingA.InteractionCell || !RPS.IsAvailable(Repairee));
            });

            toil.initAction = () =>
            {
                //Log.Message("initAction");
                Repairee.BeingRepaired = true;
                RPS.RegisterRepairee(Repairee);
            };
            toil.defaultCompleteMode = ToilCompleteMode.Never;
            toil.AddFinishAction(delegate
            {
                //Log.Message("Finish action");
                RPS.DeregisterRepairee(Repairee);
                Repairee.BeingRepaired = false;
            });
            toil.AddEndCondition(() =>
            {
                if (Repairee.ShouldGetRepairs)
                {
                    return(JobCondition.Ongoing);
                }
                return(JobCondition.Succeeded);
            });
            toil.WithEffect(DefDatabase <EffecterDef> .GetNamed("Repair"), TargetIndex.A);
            toil.WithSustainer(() => { return(DefDatabase <SoundDef> .GetNamed("Interact_Repair")); });
            yield return(toil);
        }
        public Toil PractiseCombat(TargetIndex targetInd)
        {
            var toil = new Toil();

            var lastMeleeExperienceValue = pawn.skills.GetSkill(SkillDefOf.Melee).XpTotalEarned + pawn.skills.GetSkill(SkillDefOf.Melee).xpSinceLastLevel;
            var lastShootingExperienceValue = pawn.skills.GetSkill(SkillDefOf.Shooting).XpTotalEarned + pawn.skills.GetSkill(SkillDefOf.Shooting).xpSinceLastLevel;

            toil.tickAction = () =>
            {
                // try execute attack on dummy
                pawn.equipment.TryStartAttack(CurJob.GetTarget(targetInd));

                // if zoom is close enough and dummy is selected
                if (Find.CameraDriver.CurrentZoom == CameraZoomRange.Closest && (Find.Selector.IsSelected(CurJob.GetTarget(targetInd).Thing) || Find.Selector.IsSelected(pawn)))
                {
                    var currentMeleeExperienceValue = pawn.skills.GetSkill(SkillDefOf.Melee).XpTotalEarned + pawn.skills.GetSkill(SkillDefOf.Melee).xpSinceLastLevel;
                    var currentShootingExperienceValue = pawn.skills.GetSkill(SkillDefOf.Shooting).XpTotalEarned + pawn.skills.GetSkill(SkillDefOf.Shooting).xpSinceLastLevel;

                    // throws text mote of gained melee experience
                    if (currentMeleeExperienceValue - lastMeleeExperienceValue >= 1f)
                    {
                        var expGained = currentMeleeExperienceValue - lastMeleeExperienceValue;
                        MoteMaker.ThrowText(new Vector3(pawn.Position.x + 0.5f, pawn.Position.y, pawn.Position.z + 1f), expGained.ToString("F0") + " XP", Color.green, GenDate.SecondsToTicks(1));
                        lastMeleeExperienceValue = currentMeleeExperienceValue;
                    }

                    // throws text mote of gained shooting experience
                    if (currentShootingExperienceValue - lastShootingExperienceValue >= 1f)
                    {
                        var expGained = currentShootingExperienceValue - lastShootingExperienceValue;
                        MoteMaker.ThrowText(new Vector3(pawn.Position.x + 0.5f, pawn.Position.y, pawn.Position.z + 1f), expGained.ToString("F0") + " XP", Color.green, GenDate.SecondsToTicks(1));
                        lastShootingExperienceValue = currentShootingExperienceValue;
                    }
                }
            };

            toil.AddEndCondition(() =>
            {
                // fail if pawn has life needs or can't hit target
                var dummy = CurJob.GetTarget(targetInd).Thing as Dummy;
                if (dummy != null && (dummy.PawnHasNeeds(pawn) || !pawn.equipment.PrimaryEq.PrimaryVerb.CanHitTarget(CurJob.GetTarget(targetInd))))
                {
                    return JobCondition.InterruptForced;
                }
                return JobCondition.Ongoing;
            });
            toil.defaultCompleteMode = ToilCompleteMode.Never;
            return toil;
        }
Пример #16
0
        private IEnumerable <Toil> MechToils()
        {
            Toil toil = Toils_General.Wait(6000);

            toil.socialMode = RandomSocialMode.Off;
            toil.initAction = delegate()
            {
                this.ticksLeftThisToil = 6000;
                Building firstBuilding = base.GetActor().Position.GetFirstBuilding(base.GetActor().Map);
                if (firstBuilding is Building_Bed)
                {
                    //TODO: check if it works
                    JobMaker.MakeJob(JobDefOf.LayDown, firstBuilding);

                    //base.GetActor().jobs.curDriver.layingDown = 2;
                }
            };
            toil.tickAction = delegate()
            {
                if (Rand.Chance(0.0004f))
                {
                    IEnumerable <Hediff_Injury> injuriesTendable = base.GetActor().health.hediffSet.GetInjuriesTendable();
                    if (injuriesTendable.Count <Hediff_Injury>() > 0)
                    {
                        Hediff_Injury hediff_Injury = injuriesTendable.RandomElement <Hediff_Injury>();
                        hediff_Injury.Heal((float)Rand.RangeInclusive(1, 3));
                    }
                }
            };
            toil.AddEndCondition(delegate
            {
                JobCondition result;
                if (base.GetActor().health.hediffSet.GetInjuriesTendable().Count <Hediff_Injury>() == 0)
                {
                    result = JobCondition.Succeeded;
                }
                else
                {
                    result = JobCondition.Ongoing;
                }
                return(result);
            });
            yield return(toil);

            yield break;
        }
Пример #17
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedNullOrForbidden(TargetIndex.A);
            ICharge          chargee = (ICharge)pawn;
            CompDroidCharger charger = job.GetTarget(TargetIndex.A).Thing.TryGetComp <CompDroidCharger>();

            yield return(Toils_Reserve.Reserve(TargetIndex.A));

            Toil goToPad = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell);

            goToPad.AddFailCondition(() => { return(!charger.IsAvailable(chargee)); });
            yield return(goToPad);

            Toil charge = new Toil();

            charge.initAction = () =>
            {
                if (charger.parent.InteractionCell != chargee.Parent.Position)
                {
                    pawn.jobs.EndCurrentJob(JobCondition.Errored);
                }
                else
                {
                    charger.BeginCharge(chargee);
                    chargee.ShouldUsePower = false;
                }
            };
            charge.defaultCompleteMode = ToilCompleteMode.Never;
            charge.AddFailCondition(() =>
                                    { return(!charger.IsAvailable(chargee)); });
            charge.AddEndCondition(() =>
            {
                if (!chargee.DesiresCharge)
                {
                    return(JobCondition.Succeeded);
                }
                return(JobCondition.Ongoing);
            });
            charge.AddFinishAction(() =>
            {
                charger.EndCharge();
                chargee.ShouldUsePower = true;
            });
            yield return(charge);
        }
        protected override IEnumerable<Toil> MakeNewToils()
        {
            //Set what will cause the job to fail
            this.FailOnBurningImmobile(RepairStationIndex);
            this.FailOnDestroyedOrForbidden(RepairStationIndex);
            this.FailOn(delegate
            {
                return Repairee == null || !Repairee.ShouldGetRepairs;
            });

            //Reserve the repair station
            yield return Toils_Reserve.Reserve(RepairStationIndex);
            //Go to the repair station interaction cell
            yield return Toils_Goto.GotoThing(RepairStationIndex, PathEndMode.InteractionCell);
            //Make a new toil that sets the droid to repair mode, then wait until fully repaired
            Toil toil = new Toil();
            toil.FailOnDestroyedOrForbidden(RepairStationIndex);
            toil.FailOn(() =>
                {
                    return Repairee == null || RPS == null || Repairee.Pawn.Position != TargetThingA.InteractionCell || !RPS.IsAvailable(Repairee);
                });

            toil.initAction = () =>
                {
                    //Log.Message("initAction");
                    Repairee.BeingRepaired = true;
                    RPS.RegisterRepairee(Repairee);
                };
            toil.defaultCompleteMode = ToilCompleteMode.Never;
            toil.AddFinishAction(delegate
            {
                //Log.Message("Finish action");
                RPS.DeregisterRepairee(Repairee);
                Repairee.BeingRepaired = false;
            });
            toil.AddEndCondition(() =>
            {
                if (Repairee.ShouldGetRepairs)
                    return JobCondition.Ongoing;
                return JobCondition.Succeeded;
            });
            toil.WithEffect(DefDatabase<EffecterDef>.GetNamed("Repair"), TargetIndex.A);
            toil.WithSustainer(() => { return DefDatabase<SoundDef>.GetNamed("Interact_Repair"); });
            yield return toil;
        }
Пример #19
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDespawnedNullOrForbidden(TargetIndex.A);
            this.FailOnDowned(TargetIndex.A);
            this.FailOnNotCasualInterruptible(TargetIndex.A);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            Toil wait = new Toil();

            wait.initAction = delegate
            {
                Pawn actor2 = wait.actor;
                Pawn pawn2  = (Pawn)job.GetTarget(TargetIndex.A).Thing;
                actor2.pather.StopDead();
                PawnUtility.ForceWait(pawn2, 15000, null, maintainPosture: true);
            };
            wait.tickAction = delegate
            {
                Pawn actor = wait.actor;
                actor.skills.Learn(SkillDefOf.Animals, 0.13f);
                gatherProgress += actor.GetStatValue(StatDefOf.AnimalGatherSpeed);
                if (gatherProgress >= WorkTotal)
                {
                    GetComp((Pawn)(Thing)job.GetTarget(TargetIndex.A)).Gathered(pawn);
                    actor.jobs.EndCurrentJob(JobCondition.Succeeded);
                }
            };
            wait.AddFinishAction(delegate
            {
                Pawn pawn = (Pawn)job.GetTarget(TargetIndex.A).Thing;
                if (pawn != null && pawn.CurJobDef == JobDefOf.Wait_MaintainPosture)
                {
                    pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
                }
            });
            wait.FailOnDespawnedOrNull(TargetIndex.A);
            wait.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            wait.AddEndCondition(() => GetComp((Pawn)(Thing)job.GetTarget(TargetIndex.A)).ActiveAndFull ? JobCondition.Ongoing : JobCondition.Incompletable);
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => gatherProgress / WorkTotal);
            wait.activeSkill = (() => SkillDefOf.Animals);
            yield return(wait);
        }
        private static Toil TakeFromSynthesier(TargetIndex ind, Pawn eater, Func <ThingDef, bool> validator, Func <ThingDef, ThingDef, int> sorter)
        {
            var synthesizer         = (Building_AutomatedFactory)eater.jobs.curJob.GetTarget(ind).Thing;
            var bestDef             = synthesizer.BestProduct(validator, sorter);
            var takeFromSynthesizer = new Toil();

            //Log.Message( string.Format( "{0}.TakeMealFromSynthesizier( {1}, {2} )", eater == null ? "null" : eater.NameStringShort, synthesizer == null ? "null" : synthesizer.ThingID, bestDef == null ? "null" : bestDef.defName ) );
            if (bestDef == null)
            {
                takeFromSynthesizer.defaultCompleteMode = ToilCompleteMode.Delay;
                takeFromSynthesizer.AddEndCondition(() =>
                {
                    Find.Reservations.Release(synthesizer, eater);
                    return(JobCondition.Incompletable);
                }
                                                    );
                takeFromSynthesizer.defaultDuration = 999;
            }
            else
            {
                takeFromSynthesizer.defaultCompleteMode = ToilCompleteMode.Delay;
                takeFromSynthesizer.AddFinishAction(() =>
                {
                    var meal = synthesizer.TryProduceThingDef(bestDef);
                    Find.Reservations.Release(synthesizer, eater);
                    if (meal == null)
                    {       // This should never happen, why is it?
                        Log.Error(eater.Label + " unable to take " + bestDef.label + " from " + synthesizer.ThingID);
                        eater.jobs.curDriver.EndJobWith(JobCondition.Incompletable);
                    }
                    else
                    {
                        eater.carrier.TryStartCarry(meal);
                        eater.jobs.curJob.targetA = (TargetInfo)eater.carrier.CarriedThing;
                    }
                }
                                                    );
                takeFromSynthesizer.defaultDuration = synthesizer.ProductionTicks(bestDef);
            }
            return(takeFromSynthesizer);
        }
 protected override IEnumerable<Toil> MakeNewToils()
 {
     ICharge chargee = (ICharge)this.pawn;
     CompDroidCharger charger =TargetThingA.TryGetComp<CompDroidCharger>();
     yield return Toils_Reserve.Reserve(TargetIndex.A);
     Toil goToPad = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell);
     goToPad.AddFailCondition(() => { return !charger.IsAvailable(chargee); });
     yield return goToPad;
     Toil charge = new Toil();
     charge.initAction = () =>
         {
             if (charger.parent.InteractionCell != chargee.Parent.Position)
             {
                 pawn.jobs.EndCurrentJob(JobCondition.Errored);
             }
             else
             {
                 charger.BeginCharge(chargee);
                 chargee.ShouldUsePower = false;
             }
         };
     charge.defaultCompleteMode = ToilCompleteMode.Never;
     charge.AddFailCondition(() =>
         { return !charger.IsAvailable(chargee); });
     charge.AddEndCondition(() =>
         {
             if (!chargee.DesiresCharge)
             {
                 return JobCondition.Succeeded;
             }
             return JobCondition.Ongoing;
         });
     charge.AddFinishAction(() =>
         {
             charger.EndCharge();
             chargee.ShouldUsePower = true;
         });
     yield return charge;
 }
        // Token: 0x06000010 RID: 16 RVA: 0x00002787 File Offset: 0x00000987
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Toil wait = new Toil();

            wait.tickAction = delegate()
            {
                Pawn actor = wait.actor;
                this.gatherProgress += actor.GetStatValue(StatDefOf.AnimalGatherSpeed, true);
                bool flag  = this.gatherProgress >= this.WorkTotal;
                bool flag2 = flag;
                if (flag2)
                {
                    Pawn thing = actor;
                    thing.TryGetComp <CompWidowMilkableHumanoid>().GatherMilkSelf();
                    actor.jobs.EndCurrentJob(JobCondition.Succeeded, true, true);
                }
            };
            wait.AddEndCondition(delegate
            {
                Pawn actor = wait.actor;
                bool flag  = !actor.TryGetComp <CompWidowMilkableHumanoid>().ActiveAndCanBeMilked;
                bool flag2 = flag;
                JobCondition result;
                if (flag2)
                {
                    result = JobCondition.Incompletable;
                }
                else
                {
                    result = JobCondition.Ongoing;
                }
                return(result);
            });
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => this.gatherProgress / this.WorkTotal, false, -0.5f);
            yield return(wait);

            yield break;
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Set what will cause the job to fail:
            this.FailOnDestroyedOrForbidden(CorpseIndex);
            this.FailOnBurningImmobile(CorpseIndex);
            this.FailOn(() => !(pawn is Droid));

            //Reserve the corpse
            yield return(Toils_Reserve.Reserve(CorpseIndex));

            //Go to the corpse
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch));

            Toil toil = new Toil();

            toil.initAction = () =>
            {
                //Check if the pawn is set to strip bodies, if yes then strip it, otherwise skip this step
                Droid           droid  = (Droid)pawn;
                CremationWorker worker = droid.work.specialist.GetWorker <CremationWorker>();
                if (worker.StripBodies)
                {
                    Corpse corpse = (Corpse)TargetThingA;
                    if (corpse.AnythingToStrip())
                    {
                        corpse.Strip();
                    }
                }
            };
            toil.defaultCompleteMode = ToilCompleteMode.Delay;
            toil.defaultDuration     = 300;
            toil.WithEffect(() => DefDatabase <EffecterDef> .GetNamed("Cremate"), CorpseIndex);
            toil.WithSustainer(() => DefDatabase <SoundDef> .GetNamed("Recipe_Cremate"));
            toil.AddFinishAction(() => TargetA.Thing.Destroy());
            toil.FailOnBurningImmobile(CorpseIndex);
            toil.FailOnDestroyedOrForbidden(CorpseIndex);
            toil.AddEndCondition(() => this.ticksLeftThisToil <= 0 ? JobCondition.Succeeded : JobCondition.Ongoing);
            yield return(toil);
        }
 private static Toil TakeFromSynthesier( TargetIndex ind, Pawn eater, Func<ThingDef,bool> validator, Func<ThingDef,ThingDef,int> sorter )
 {
     var synthesizer = (Building_AutomatedFactory) eater.jobs.curJob.GetTarget( ind ).Thing;
     var bestDef = synthesizer.BestProduct( validator, sorter );
     var takeFromSynthesizer = new Toil();
     //Log.Message( string.Format( "{0}.TakeMealFromSynthesizier( {1}, {2} )", eater == null ? "null" : eater.NameStringShort, synthesizer == null ? "null" : synthesizer.ThingID, bestDef == null ? "null" : bestDef.defName ) );
     if( bestDef == null )
     {
         takeFromSynthesizer.defaultCompleteMode = ToilCompleteMode.Delay;
         takeFromSynthesizer.AddEndCondition( () =>
             {
                 return JobCondition.Incompletable;
             }
         );
         takeFromSynthesizer.defaultDuration = 999;
     }
     else
     {
         takeFromSynthesizer.defaultCompleteMode = ToilCompleteMode.Delay;
         takeFromSynthesizer.AddFinishAction( () =>
             {
                 Thing thing = synthesizer.TryProduceThingDef( bestDef );
                 if( thing == null )
                 {
                     Log.Error( eater.Label + " unable to take " + bestDef.label + " from " + synthesizer.ThingID );
                     eater.jobs.curDriver.EndJobWith( JobCondition.Incompletable );
                 }
                 else
                 {
                     eater.carrier.TryStartCarry( thing );
                     eater.jobs.curJob.targetA = (TargetInfo) eater.carrier.CarriedThing;
                 }
             }
         );
         takeFromSynthesizer.defaultDuration = synthesizer.ProductionTicks( bestDef );
     }
     return takeFromSynthesizer;
 }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Building_DroidCharger building = (Building_DroidCharger)TargetThingA;

            // Go to the charging pad, but stop trying if it isn't on or is taken.
            Toil gotoToil = Toils_Goto.GotoThing(TargetIndex.A, PathMode.OnSquare);

            gotoToil.AddFailCondition(() => {
                return(!building.IsOnAndAvailable(pawn));
            });
            yield return(gotoToil);

            // Charge until at least 99% full, or the charger is off or taken.
            DroidPawn droid      = (DroidPawn)this.pawn;
            Toil      chargeToil = new Toil();

            chargeToil.initAction = () => {
                if (building.Position != pawn.Position)
                {
                    pawn.jobs.EndCurrentJob(JobCondition.Errored);
                }
            };
            chargeToil.defaultCompleteMode = ToilCompleteMode.Never;
            chargeToil.AddFailCondition(() => {
                return(!building.IsOnAndAvailable(pawn));
            });
            chargeToil.AddEndCondition(() => {
                if (droid.storedEnergy >= 0.99 * DroidPawn.storedEnergyMax)
                {
                    return(JobCondition.Succeeded);
                }
                return(JobCondition.Ongoing);
            });

            yield return(chargeToil);
        }
Пример #26
0
        public static Toil LayDown(TargetIndex bedOrRestSpotIndex, bool hasBed, bool lookForOtherJobs, bool canSleep = true, bool gainRestAndHealth = true)
        {
            Toil layDown = new Toil();

            layDown.initAction = delegate()
            {
                Pawn actor = layDown.actor;
                actor.pather.StopDead();
                JobDriver curDriver = actor.jobs.curDriver;
                if (hasBed)
                {
                    if (!((Building_Bed)actor.CurJob.GetTarget(bedOrRestSpotIndex).Thing).OccupiedRect().Contains(actor.Position))
                    {
                        Log.Error("Can't start LayDown toil because pawn is not in the bed. pawn=" + actor, false);
                        actor.jobs.EndCurrentJob(JobCondition.Errored, true, true);
                        return;
                    }
                    actor.jobs.posture = PawnPosture.LayingInBed;
                }
                else
                {
                    actor.jobs.posture = PawnPosture.LayingOnGroundNormal;
                }
                curDriver.asleep = false;
                if (actor.mindState.applyBedThoughtsTick == 0)
                {
                    actor.mindState.applyBedThoughtsTick    = Find.TickManager.TicksGame + Rand.Range(2500, 10000);
                    actor.mindState.applyBedThoughtsOnLeave = false;
                }
                if (actor.ownership != null && actor.CurrentBed() != actor.ownership.OwnedBed)
                {
                    ThoughtUtility.RemovePositiveBedroomThoughts(actor);
                }
                CompCanBeDormant comp = actor.GetComp <CompCanBeDormant>();
                if (comp != null)
                {
                    comp.ToSleep();
                }
            };
            layDown.tickAction = delegate()
            {
                Pawn         actor        = layDown.actor;
                Job          curJob       = actor.CurJob;
                JobDriver    curDriver    = actor.jobs.curDriver;
                Building_Bed building_Bed = (Building_Bed)curJob.GetTarget(bedOrRestSpotIndex).Thing;
                actor.GainComfortFromCellIfPossible(false);
                if (!curDriver.asleep)
                {
                    if (canSleep && ((actor.needs.rest != null && actor.needs.rest.CurLevel < RestUtility.FallAsleepMaxLevel(actor)) || curJob.forceSleep))
                    {
                        curDriver.asleep = true;
                    }
                }
                else if (!canSleep)
                {
                    curDriver.asleep = false;
                }
                else if ((actor.needs.rest == null || actor.needs.rest.CurLevel >= RestUtility.WakeThreshold(actor)) && !curJob.forceSleep)
                {
                    curDriver.asleep = false;
                }
                if (curDriver.asleep && gainRestAndHealth && actor.needs.rest != null)
                {
                    float restEffectiveness;
                    if (building_Bed != null && building_Bed.def.statBases.StatListContains(StatDefOf.BedRestEffectiveness))
                    {
                        restEffectiveness = building_Bed.GetStatValue(StatDefOf.BedRestEffectiveness, true);
                    }
                    else
                    {
                        restEffectiveness = StatDefOf.BedRestEffectiveness.valueIfMissing;
                    }
                    actor.needs.rest.TickResting(restEffectiveness);
                }
                if (actor.IsHashIntervalTick(100) && !actor.Position.Fogged(actor.Map))
                {
                    if (curDriver.asleep)
                    {
                        MoteMaker.ThrowMetaIcon(actor.Position, actor.Map, ThingDefOf.Mote_SleepZ);
                    }
                    if (gainRestAndHealth && actor.health.hediffSet.GetNaturallyHealingInjuredParts().Any <BodyPartRecord>())
                    {
                        MoteMaker.ThrowMetaIcon(actor.Position, actor.Map, ThingDefOf.Mote_HealingCross);
                    }
                }
                if (actor.ownership != null && building_Bed != null && !building_Bed.Medical && !building_Bed.OwnersForReading.Contains(actor))
                {
                    if (actor.Downed)
                    {
                        actor.Position = CellFinder.RandomClosewalkCellNear(actor.Position, actor.Map, 1, null);
                    }
                    actor.jobs.EndCurrentJob(JobCondition.Incompletable, true, true);
                    return;
                }
                if (lookForOtherJobs && actor.IsHashIntervalTick(211))
                {
                    actor.jobs.CheckForJobOverride();
                    return;
                }
            };
            layDown.AddEndCondition(delegate()
            {
                Pawn actor = layDown.actor;
                if (!actor.health.hediffSet.HasHediff(HediffDefOf.Hypothermia))
                {
                    return(JobCondition.Succeeded);
                }
                else
                {
                    return(JobCondition.Ongoing);
                }
            });
            layDown.defaultCompleteMode = ToilCompleteMode.Never;
            if (hasBed)
            {
                layDown.FailOnBedNoLongerUsable(bedOrRestSpotIndex);
            }
            layDown.AddFinishAction(delegate
            {
                Pawn actor          = layDown.actor;
                JobDriver curDriver = actor.jobs.curDriver;

                curDriver.asleep = false;
            });
            return(layDown);
        }
Пример #27
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.AddFinishAction(delegate()
            {
                if (Patient.CurrentBed() == Bed && Patient.CurJobDef == JobDefOf.LayDown)
                {
                    Patient.jobs.EndCurrentJob(JobCondition.Succeeded);
                }
            });
            this.FailOnDestroyedNullOrForbidden(TargetIndex.A);
            this.FailOnDestroyedNullOrForbidden(TargetIndex.B);
            this.FailOnDestroyedNullOrForbidden(TargetIndex.C);
            yield return(Toils_Reserve.Reserve(TargetIndex.A));

            yield return(Toils_Reserve.Reserve(TargetIndex.B));

            yield return(Toils_Reserve.Reserve(TargetIndex.C));

            //Go and get the thing to carry.
            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.OnCell));

            yield return(Toils_Haul.StartCarryThing(TargetIndex.B));

            yield return(Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.ClosestTouch));

            yield return(Toils_Haul.PlaceCarriedThingInCellFacing(TargetIndex.C));

            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell));

            yield return(Toils_Haul.StartCarryThing(TargetIndex.A));

            yield return(Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.ClosestTouch));

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, null, false));

            yield return(Toils_Reserve.Release(TargetIndex.C));

            Toil applyBrainTemplateToil = new Toil()
            {
                defaultCompleteMode = ToilCompleteMode.Never,
                initAction          = delegate()
                {
                    Patient.pather.StopDead();
                    Patient.jobs.StartJob(new Job(JobDefOf.LayDown, TargetC)
                    {
                        forceSleep = true
                    });
                },
                tickAction = delegate()
                {
                    ticksWork -= 1f * pawn.GetStatValue(StatDefOf.ResearchSpeed);

                    if (ticksWork <= 0)
                    {
                        BrainManipUtility.ApplyBrainScanTemplateOnPawn(Patient, BrainTemplate);
                        Patient.jobs.EndCurrentJob(JobCondition.Succeeded);

                        //Give headache
                        Patient.health.AddHediff(QEHediffDefOf.QE_Headache, Patient.health.hediffSet.GetBrain());
                    }
                }
            }.WithProgressBar(TargetIndex.A, () => (workRequired - ticksWork) / workRequired).WithEffect(EffecterDefOf.Research, TargetIndex.A);

            applyBrainTemplateToil.AddPreInitAction(delegate()
            {
                ticksWork   = workRequired;
                workStarted = true;
                //Log.Message("preInitAction: ticksWork = " + ticksWork);
            });
            applyBrainTemplateToil.AddEndCondition(delegate()
            {
                if (workStarted && ticksWork <= 0)
                {
                    //Log.Message("Succeeded: ticksWork = " + ticksWork);
                    return(JobCondition.Succeeded);
                }

                //Log.Message("Ongoing: ticksWork = " + ticksWork);
                return(JobCondition.Ongoing);
            });
            applyBrainTemplateToil.AddFailCondition(() => workStarted && Patient.CurJobDef != JobDefOf.LayDown);

            yield return(applyBrainTemplateToil);
        }
Пример #28
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedNullOrForbidden(PowerDestIndex);
            AddFailCondition(() => energyNeed == null);

            yield return(Toils_Reserve.Reserve(PowerDestIndex));

            if (!TargetB.IsValid)
            {
                yield return(Toils_Goto.GotoThing(PowerDestIndex, PathEndMode.ClosestTouch));
            }
            else
            {
                yield return(Toils_Reserve.Reserve(AlternateDestIndex));

                yield return(Toils_Goto.GotoThing(AlternateDestIndex, PathEndMode.OnCell));
            }

            Toil rechargeToil = new Toil();

            rechargeToil.tickAction = delegate
            {
                //Drain the powernet.
                CompPowerBattery compBattery = powerBuilding.PowerComp?.PowerNet?.batteryComps?.FirstOrDefault(battery => battery.StoredEnergy > PowerNetEnergyDrainedPerTick);

                if (compBattery != null)
                {
                    compBattery.DrawPower(PowerNetEnergyDrainedPerTick);

                    //Add to our energy.
                    energyNeed.CurLevel += energyNeed.MaxLevel / MaxTicksSpentCharging;
                }

                ticksSpentCharging++;
            };
            rechargeToil.AddEndCondition(delegate
            {
                if (powerBuilding == null || powerBuilding.PowerComp == null /*|| temporaryTrader == null*/)
                {
                    return(JobCondition.Incompletable);
                }

                if (powerBuilding.PowerComp?.PowerNet.CurrentStoredEnergy() < PowerNetEnergyDrainedPerTick)
                {
                    return(JobCondition.Incompletable);
                }

                if (energyNeed.CurLevelPercentage >= 0.99f)
                {
                    return(JobCondition.Succeeded);
                }

                if (ticksSpentCharging > MaxTicksSpentCharging)
                {
                    return(JobCondition.Incompletable);
                }

                return(JobCondition.Ongoing);
            });

            if (!TargetB.IsValid)
            {
                rechargeToil.FailOnCannotTouch(PowerDestIndex, PathEndMode.ClosestTouch);
            }
            else
            {
                rechargeToil.FailOnCannotTouch(AlternateDestIndex, PathEndMode.OnCell);
            }

            rechargeToil.WithProgressBar(TargetIndex.A, () => energyNeed.CurLevelPercentage, false);
            rechargeToil.defaultCompleteMode = ToilCompleteMode.Never;
            yield return(rechargeToil);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            setup_ticks();
            parteners.Add(Partner);            // add job starter, so this wont fail, before Initiator starts his job
            float partner_ability = xxx.get_sex_ability(Partner);

            // More/less hearts based on partner ability.
            if (partner_ability < 0.8f)
            {
                ticks_between_thrusts += 120;
            }
            else if (partner_ability > 2.0f)
            {
                ticks_between_thrusts -= 30;
            }

            // More/less hearts based on opinion.
            if (pawn.relations.OpinionOf(Partner) < 0)
            {
                ticks_between_hearts += 50;
            }
            else if (pawn.relations.OpinionOf(Partner) > 60)
            {
                ticks_between_hearts -= 25;
            }

            this.FailOnDespawnedOrNull(iTarget);
            this.FailOn(() => !Partner.health.capacities.CanBeAwake);

            yield return(Toils_Reserve.Reserve(iTarget, 1, 0));

            Toil get_loved = new Toil();

            get_loved.defaultCompleteMode = ToilCompleteMode.Never;
            get_loved.socialMode          = RandomSocialMode.Off;
            get_loved.initAction          = delegate
            {
                pawn.pather.StopDead();
                pawn.jobs.curDriver.asleep = false;
            };
            get_loved.AddPreTickAction(delegate
            {
                if (pawn.IsHashIntervalTick(ticks_between_hearts))
                {
                    ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                }
            });
            get_loved.AddEndCondition(new Func <JobCondition>(() =>
            {
                if ((ticks_remaining <= 0) || (parteners.Count <= 0))
                {
                    return(JobCondition.Succeeded);
                }
                return(JobCondition.Ongoing);
            }));
            get_loved.AddFinishAction(delegate
            {
                if (xxx.is_human(pawn))
                {
                    pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
                }
            });
            yield return(get_loved);
        }
Пример #30
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Log.Message("Toil start:" + pawn + " is trying to learn " + project + ", globalFailConditions count:" + globalFailConditions.Count);
            Dictionary <ResearchProjectDef, float> expertise = pawn.TryGetComp <CompKnowledge>().expertise;

            AddEndCondition(delegate
            {
                if (!desk.Spawned)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });
            this.FailOnBurningImmobile(TargetIndex.A);
            this.FailOn(delegate()
            {
                IBillGiver billGiver = desk as IBillGiver;
                if (billGiver != null)
                {
                    if (job.bill.DeletedOrDereferenced)
                    {
                        return(true);
                    }
                    if (!billGiver.CurrentlyUsableForBills())
                    {
                        return(true);
                    }
                    if (project == null)
                    {
                        Log.Warning("[HumanResources] " + pawn + " tried to learn a null project.");
                        TryMakePreToilReservations(true);
                        return(true);
                    }
                    bool flag = IsResearch ? project.IsKnownBy(pawn) : !techComp.homework.Contains(project);
                    if (flag)
                    {
                        return(true);
                    }
                }
                return(false);
            });
            Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell);

            yield return(gotoBillGiver);

            Toil acquireKnowledge = new Toil();

            acquireKnowledge.initAction = delegate()
            {
                Pawn actor = acquireKnowledge.actor;
                if (!expertise.ContainsKey(project))
                {
                    expertise.Add(project, 0f);
                }
            };
            acquireKnowledge.AddEndCondition(delegate
            {
                Pawn actor = acquireKnowledge.actor;
                if (expertise.ContainsKey(project) && expertise[project] > 1f)
                {
                    expertise[project] = 1f;
                    if (!IsResearch)
                    {
                        Notify_IterationCompleted(actor, job.bill as Bill_Production);
                        techComp.homework.Remove(project);
                    }
                    techComp.LearnCrops(project);
                    Messages.Message("MessageStudyComplete".Translate(actor, project.LabelCap), desk, MessageTypeDefOf.TaskCompletion, true);
                    project = null;
                    return(JobCondition.Succeeded);
                }
                return(JobCondition.Ongoing);
            });
            acquireKnowledge.tickAction = delegate()
            {
                Pawn  actor = acquireKnowledge.actor;
                float num   = actor.GetStatValue(StatDefOf.ResearchSpeed, true);
                num *= TargetThingA.GetStatValue(StatDefOf.ResearchSpeedFactor, true);
                float workAmount = IsResearch ? 1f : job.bill.recipe.workAmount;
                project.Learned(num, workAmount, actor, job.bill == null);
                actor.skills.Learn(SkillDefOf.Intellectual, 0.1f, false);
                actor.GainComfortFromCellIfPossible(true);
            };
            acquireKnowledge.AddFinishAction(delegate
            {
                Pawn actor = acquireKnowledge.actor;
                if (job.bill != null && job.RecipeDef.workSkill != null)
                {
                    float xp = ticksSpentDoingRecipeWork * 0.1f * job.RecipeDef.workSkillLearnFactor;
                    actor.skills.GetSkill(job.RecipeDef.workSkill).Learn(xp, false);
                }
            });
            acquireKnowledge.FailOn(() => project == null);
            //research.FailOn(() => !this.Project.CanBeResearchedAt(this.ResearchBench, false)); //need rework
            acquireKnowledge.FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell);
            acquireKnowledge.FailOnDespawnedOrNull(TargetIndex.A);
            acquireKnowledge.WithEffect(EffecterDefOf.Research, TargetIndex.A);
            acquireKnowledge.WithProgressBar(TargetIndex.A, delegate
            {
                if (project == null)
                {
                    return(0f);
                }
                return(expertise[project]);
            }, false, -0.5f);
            acquireKnowledge.defaultCompleteMode = ToilCompleteMode.Delay;
            acquireKnowledge.defaultDuration     = 4000;
            acquireKnowledge.activeSkill         = () => SkillDefOf.Intellectual;
            yield return(acquireKnowledge);

            yield return(Toils_General.Wait(2, TargetIndex.None));

            yield break;
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            setup_ticks();
            parteners.Add(Partner);            // add job starter, so this wont fail, before Initiator starts his job
            //--Log.Message("[RJW]JobDriver_GettinLoved::MakeNewToils is called");

            float partner_ability = xxx.get_sex_ability(Partner);

            // More/less hearts based on partner ability.
            if (partner_ability < 0.8f)
            {
                ticks_between_thrusts += 120;
            }
            else if (partner_ability > 2.0f)
            {
                ticks_between_thrusts -= 30;
            }

            // More/less hearts based on opinion.
            if (pawn.relations.OpinionOf(Partner) < 0)
            {
                ticks_between_hearts += 50;
            }
            else if (pawn.relations.OpinionOf(Partner) > 60)
            {
                ticks_between_hearts -= 25;
            }

            this.FailOnDespawnedOrNull(iTarget);
            this.FailOn(() => !Partner.health.capacities.CanBeAwake);

            if (Partner.CurJob.def == xxx.casual_sex)
            {
                this.FailOn(() => pawn.Drafted);
                this.KeepLyingDown(iBed);
                yield return(Toils_Reserve.Reserve(iTarget, 1, 0));

                yield return(Toils_Reserve.Reserve(iBed, Bed.SleepingSlotsCount, 0));

                Toil get_loved = Toils_LayDown.LayDown(iBed, true, false, false, false);
                get_loved.FailOn(() => Partner.CurJob.def != xxx.casual_sex);
                get_loved.defaultCompleteMode = ToilCompleteMode.Never;
                get_loved.socialMode          = RandomSocialMode.Off;
                get_loved.handlingFacing      = true;
                get_loved.tickAction          = delegate
                {
                    if (pawn.IsHashIntervalTick(ticks_between_hearts))
                    {
                        ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                    }
                };
                get_loved.AddFinishAction(delegate
                {
                    if (xxx.is_human(pawn))
                    {
                        pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
                    }
                });
                yield return(get_loved);
            }
            else if (Partner.CurJob.def == xxx.whore_is_serving_visitors)
            {
                this.FailOn(() => Partner.CurJob == null);
                yield return(Toils_Goto.GotoThing(iTarget, PathEndMode.OnCell));

                yield return(Toils_Reserve.Reserve(iTarget, 1, 0));

                Toil get_loved = new Toil();
                get_loved.FailOn(() => (Partner.CurJob.def != xxx.whore_is_serving_visitors));
                get_loved.defaultCompleteMode = ToilCompleteMode.Never;
                get_loved.socialMode          = RandomSocialMode.Off;
                get_loved.handlingFacing      = true;
                get_loved.tickAction          = delegate
                {
                    --ticks_remaining;
                    if (pawn.IsHashIntervalTick(ticks_between_hearts))
                    {
                        ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                    }
                };
                get_loved.AddEndCondition(new Func <JobCondition>(() =>
                {
                    if ((ticks_remaining <= 0) || (parteners.Count <= 0))
                    {
                        return(JobCondition.Succeeded);
                    }
                    return(JobCondition.Ongoing);
                }));
                get_loved.AddFinishAction(delegate
                {
                    if (xxx.is_human(pawn))
                    {
                        pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
                    }
                });
                yield return(get_loved);
            }
            else if (Partner.CurJob.def == xxx.bestialityForFemale)
            {
                this.FailOn(() => Partner.CurJob == null);
                yield return(Toils_Goto.GotoThing(iTarget, PathEndMode.OnCell));

                yield return(Toils_Reserve.Reserve(iTarget, 1, 0));

                Toil get_loved = new Toil();
                get_loved.FailOn(() => (Partner.CurJob.def != xxx.bestialityForFemale));
                get_loved.defaultCompleteMode = ToilCompleteMode.Never;
                get_loved.socialMode          = RandomSocialMode.Off;
                get_loved.handlingFacing      = true;
                get_loved.tickAction          = delegate
                {
                    --ticks_remaining;
                    if (pawn.IsHashIntervalTick(ticks_between_hearts))
                    {
                        ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                    }
                };
                get_loved.AddEndCondition(new Func <JobCondition>(() =>
                {
                    if ((ticks_remaining <= 0) || (parteners.Count <= 0))
                    {
                        return(JobCondition.Succeeded);
                    }
                    return(JobCondition.Ongoing);
                }));
                get_loved.AddFinishAction(delegate
                {
                    if (xxx.is_human(pawn))
                    {
                        pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
                    }
                });
                get_loved.socialMode = RandomSocialMode.Off;
                yield return(get_loved);
            }
        }
Пример #32
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            ticks_between_hearts = Rand.RangeInclusive(70, 130);
            was_laying_down      = (pawn.jobs.curDriver != null) && pawn.jobs.curDriver.layingDown != Verse.AI.LayingDownState.NotLaying;

            var get_raped = new Toil();

            get_raped.defaultCompleteMode = ToilCompleteMode.Never;
            get_raped.initAction          = delegate
            {
                pawn.pather.StopDead();
                pawn.jobs.curDriver.layingDown = Verse.AI.LayingDownState.NotLaying;
                pawn.jobs.curDriver.asleep     = false;
                //pawn.mindState.awokeVoluntarily = false;
                // Added by nizhuan-jjr: human pawns get raped will put on clothes again.
                if (!xxx.is_animal(pawn))
                {
                    dummy_container = new RJW_DummyContainer();
                    foreach (Apparel apparel in pawn.apparel.GetDirectlyHeldThings().OfType <Apparel>().ToList <Apparel>())
                    {
                        if (!(apparel is rjw.bondage_gear))
                        {
                            pawn.apparel.GetDirectlyHeldThings().TryTransferToContainer(apparel, dummy_container.GetDirectlyHeldThings(), true);
                            if ((pawn.outfits != null) && pawn.outfits.forcedHandler.IsForced(apparel))
                            {
                                dummy_container.forcedApparel.Add(apparel);
                            }
                        }
                    }
                }
                Messages.Message(pawn.NameStringShort + " is getting raped.", pawn, MessageTypeDefOf.NegativeEvent);
                //Messages.Message("GetinRapedNow".Translate(new object[] { pawn.LabelIndefinite() }).CapitalizeFirst(), pawn, MessageTypeDefOf.NegativeEvent);
            };
            get_raped.tickAction = delegate
            {
                --ticks_remaining;

                /*
                 * if ((ticks_remaining <= 0) || (rapist_count <= 0))
                 * ReadyForNextToil();
                 */
                if ((rapist_count > 0) && (pawn.IsHashIntervalTick(ticks_between_hearts / rapist_count)))
                {
                    MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, xxx.mote_noheart);
                }
            };
            get_raped.AddEndCondition(new Func <JobCondition>(() =>
            {
                if ((ticks_remaining <= 0) || (rapist_count <= 0))
                {
                    return(JobCondition.Succeeded);
                }
                return(JobCondition.Ongoing);
            }));
            get_raped.AddFinishAction(delegate
            {
                pawn.jobs.curDriver.layingDown = was_laying_down ? Verse.AI.LayingDownState.NotLaying : Verse.AI.LayingDownState.LayingInBed;

                // Added by nizhuan-jjr: human pawns get raped will put on clothes again.
                if (!xxx.is_animal(pawn))
                {
                    if (dummy_container != null)
                    {
                        foreach (Apparel apparel in dummy_container.GetDirectlyHeldThings().OfType <Apparel>().ToList <Apparel>())
                        {
                            if (!(apparel is rjw.bondage_gear))
                            {
                                dummy_container.GetDirectlyHeldThings().TryTransferToContainer(apparel, pawn.apparel.GetDirectlyHeldThings(), true);
                                if (dummy_container.forcedApparel.Contains(apparel) && (pawn.outfits != null))
                                {
                                    pawn.outfits.forcedHandler.SetForced(apparel, true);
                                }
                            }
                        }
                    }
                }
            });
            get_raped.socialMode = RandomSocialMode.Off;
            yield return(get_raped);

            /*
             * var after_rape = new Toil();
             * after_rape.defaultCompleteMode = ToilCompleteMode.Delay;
             * after_rape.defaultDuration = 150;
             * after_rape.socialMode = RandomSocialMode.Off;
             * after_rape.AddFinishAction(delegate {
             * pawn.jobs.curDriver.layingDown = was_laying_down ? Verse.AI.LayingDownState.NotLaying : Verse.AI.LayingDownState.LayingInBed;
             *
             * // Added by nizhuan-jjr: human pawns get raped will put on clothes again.
             * if (!xxx.is_animal(pawn))
             * {
             * if (dummy_container != null)
             * {
             * foreach (Apparel apparel in dummy_container.GetDirectlyHeldThings().OfType<Apparel>().ToList<Apparel>())
             * {
             *  if (!(apparel is rjw.bondage_gear))
             *  {
             *      dummy_container.GetDirectlyHeldThings().TryTransferToContainer(apparel, pawn.apparel.GetDirectlyHeldThings(), true);
             *      if (dummy_container.forcedApparel.Contains(apparel) && (pawn.outfits != null))
             *      {
             *          pawn.outfits.forcedHandler.SetForced(apparel, true);
             *      }
             *  }
             * }
             * }
             * }
             * });
             * yield return after_rape;
             */
        }
Пример #33
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            setup_ticks();
            parteners.Add(Partner);            // add job starter, so this wont fail, before Initiator starts his job

            var get_raped = new Toil();

            get_raped.defaultCompleteMode = ToilCompleteMode.Never;
            get_raped.handlingFacing      = true;
            get_raped.initAction          = delegate
            {
                pawn.pather.StopDead();
                pawn.jobs.curDriver.asleep = false;

                SexUtility.BeeingRapedAlert(Partner, pawn);
            };
            get_raped.tickAction = delegate
            {
                --ticks_remaining;
                if ((parteners.Count > 0) && (pawn.IsHashIntervalTick(ticks_between_hearts / parteners.Count)))
                {
                    if (pawn.IsHashIntervalTick(ticks_between_hearts))
                    {
                        if (xxx.is_masochist(pawn))
                        {
                            ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                        }
                        else
                        {
                            ThrowMetaIcon(pawn.Position, pawn.Map, xxx.mote_noheart);
                        }
                    }
                }
            };
            get_raped.AddEndCondition(new Func <JobCondition>(() =>
            {
                if ((ticks_remaining <= 0) || (parteners.Count <= 0))
                {
                    return(JobCondition.Succeeded);
                }
                return(JobCondition.Ongoing);
            }));
            get_raped.AddFinishAction(delegate
            {
                if (xxx.is_human(pawn))
                {
                    pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
                }

                if (Bed != null && pawn.Downed)
                {
                    Job tobed   = JobMaker.MakeJob(JobDefOf.Rescue, pawn, Bed);
                    tobed.count = 1;
                    Partner.jobs.jobQueue.EnqueueFirst(tobed);
                    //Log.Message(xxx.get_pawnname(Initiator) + ": job tobed:" + tobed);
                }
                else if (pawn.HostileTo(Partner))
                {
                    pawn.health.AddHediff(HediffDef.Named("Hediff_Submitting"));
                }
                else
                {
                    pawn.stances.stunner.StunFor(600, pawn);
                }
            });
            get_raped.socialMode = RandomSocialMode.Off;
            yield return(get_raped);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            ticks_between_hearts = Rand.RangeInclusive(70, 130);
            //was_laying_down = pawn.GetPosture() != PawnPosture.Standing;
            //Log.Message(xxx.get_pawnname(Initiator) + ": was_laying_down:" + was_laying_down + " LayingInBed:" + Initiator.GetPosture());
            //Log.Message(xxx.get_pawnname(Receiver) + ": was_laying_down:" + was_laying_down + " LayingInBed:" + Receiver.GetPosture());
            //was_laying_down = (pawn.jobs.curDriver != null) && pawn.GetPosture() != PawnPosture.Standing;
            //Log.Message(xxx.get_pawnname(pawn) + ": bed:" + Bed);

            var get_raped = new Toil();

            get_raped.defaultCompleteMode = ToilCompleteMode.Never;
            get_raped.initAction          = delegate
            {
                pawn.pather.StopDead();
                //pawn.jobs.posture = PawnPosture.Standing;
                pawn.jobs.curDriver.asleep = false;

                switch (RJWPreferenceSettings.rape_alert_sound)
                {
                case RJWPreferenceSettings.RapeAlert.Enabled:
                    RapeAlert();
                    break;

                case RJWPreferenceSettings.RapeAlert.Humanlikes:
                    if (xxx.is_human(Receiver))
                    {
                        RapeAlert();
                    }
                    else
                    {
                        RapeAlert(true);
                    }
                    break;

                case RJWPreferenceSettings.RapeAlert.Colonists:
                    if (Receiver.Faction == Faction.OfPlayer)
                    {
                        RapeAlert();
                    }
                    else
                    {
                        RapeAlert(true);
                    }
                    break;

                default:
                    RapeAlert(true);
                    break;
                }

                //Messages.Message("GetinRapedNow".Translate(new object[] { pawn.LabelIndefinite() }).CapitalizeFirst(), pawn, MessageTypeDefOf.NegativeEvent);

                if (Initiator == null || Receiver == null)
                {
                    return;
                }
                bool partnerHasHands = Receiver.health.hediffSet.GetNotMissingParts().Any(part => part.IsInGroup(BodyPartGroupDefOf.RightHand) || part.IsInGroup(BodyPartGroupDefOf.LeftHand));

                // Hand check is for monstergirls and other bipedal 'animals'.
                if ((!xxx.is_animal(Initiator) && partnerHasHands) || Rand.Chance(0.3f)) // 30% chance of face-to-face regardless, for variety.
                {                                                                        // Face-to-face
                    Initiator.rotationTracker.Face(Receiver.DrawPos);
                    Receiver.rotationTracker.Face(Initiator.DrawPos);
                }
                else
                {                 // From behind / animal stuff should mostly use this
                    Initiator.rotationTracker.Face(Receiver.DrawPos);
                    Receiver.Rotation = Initiator.Rotation;
                }
                // TODO: The above works, but something is forcing the partners to face each other during sex. Need to figure it out.

                //prevent Receiver standing up and interrupting rape, probably
                if (Receiver.health.hediffSet.HasHediff(HediffDef.Named("Hediff_Submitting")))
                {
                    Receiver.health.AddHediff(HediffDef.Named("Hediff_Submitting"));
                }
            };
            get_raped.tickAction = delegate
            {
                --ticks_remaining;

                /*
                 * if ((ticks_remaining <= 0) || (rapist_count <= 0))
                 *      ReadyForNextToil();
                 */
                if ((rapist_count > 0) && (pawn.IsHashIntervalTick(ticks_between_hearts / rapist_count)))
                {
                    MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, xxx.mote_noheart);
                }
            };
            get_raped.AddEndCondition(new Func <JobCondition>(() =>
            {
                if ((ticks_remaining <= 0) || (rapist_count <= 0))
                {
                    return(JobCondition.Succeeded);
                }
                return(JobCondition.Ongoing);
            }));
            get_raped.AddFinishAction(delegate
            {
                if (Bed != null && pawn.Downed)
                {
                    Job tobed   = new Job(JobDefOf.Rescue, pawn, Bed);
                    tobed.count = 1;
                    Initiator.jobs.jobQueue.EnqueueFirst(tobed);
                    //Log.Message(xxx.get_pawnname(Initiator) + ": job tobed:" + tobed);
                }
            });
            get_raped.socialMode = RandomSocialMode.Off;
            yield return(get_raped);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //A - Sleeper   B - Brain template   C - Bed

            this.FailOnDestroyedNullOrForbidden(TargetIndex.A);
            this.FailOnDestroyedNullOrForbidden(TargetIndex.B);
            this.FailOnDestroyedNullOrForbidden(TargetIndex.C);

            yield return(Toils_Reserve.Reserve(TargetIndex.B));

            if (Patient.CurJobDef != JobDefOf.LayDown || Patient.CurrentBed() != Bed)
            {
                QEEMod.TryLog("Patient not in bed, carrying them to bed");
                //get the patient and carry them to the bed
                yield return(Toils_Reserve.Reserve(TargetIndex.A));

                yield return(Toils_Reserve.Reserve(TargetIndex.C));

                yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell));

                yield return(Toils_Haul.StartCarryThing(TargetIndex.A));

                yield return(Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.InteractionCell));

                yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, null, false));

                yield return(Toils_Reserve.Release(TargetIndex.C));
            }

            //anesthetize the patient
            Toil anesthetizePatient = new Toil()
            {
                initAction = delegate()
                {
                    Toils_Reserve.Reserve(TargetIndex.A);

                    Patient.health.AddHediff(HediffDefOf.Anesthetic);

                    if (Patient.CurJobDef != JobDefOf.LayDown)
                    {
                        Patient.pather.StopDead();
                        Patient.jobs.StartJob(new Job(JobDefOf.LayDown, TargetC)
                        {
                            forceSleep = true
                        });
                    }
                },
            };

            yield return(anesthetizePatient);

            //Surgeon gets the brain template, carries it, then travel to bed
            QEEMod.TryLog("Carrying brain template to bed");
            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.OnCell));

            yield return(Toils_Haul.StartCarryThing(TargetIndex.B));

            yield return(Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.ClosestTouch));

            Toil applyBrainTemplateToil = new Toil()
            {
                defaultCompleteMode = ToilCompleteMode.Never,
                tickAction          = delegate()
                {
                    ticksWork -= StatDefOf.ResearchSpeed.Worker.IsDisabledFor(pawn) ? 1f : 1f * pawn.GetStatValue(StatDefOf.ResearchSpeed);

                    if (ticksWork <= 0)
                    {
                        BrainManipUtility.ApplyBrainScanTemplateOnPawn(Patient, BrainTemplate);

                        //Give headache
                        Patient.health.AddHediff(QEHediffDefOf.QE_Headache, Patient.health.hediffSet.GetBrain());
                    }
                }
            }.WithProgressBar(TargetIndex.A, () => (workRequired - ticksWork) / workRequired).WithEffect(EffecterDefOf.Research, TargetIndex.A);

            applyBrainTemplateToil.AddPreInitAction(delegate()
            {
                ticksWork   = workRequired;
                workStarted = true;
                //Log.Message("preInitAction: ticksWork = " + ticksWork);
            });
            applyBrainTemplateToil.AddEndCondition(delegate()
            {
                if (workStarted && ticksWork <= 0)
                {
                    //Log.Message("Succeeded: ticksWork = " + ticksWork);
                    return(JobCondition.Succeeded);
                }

                //Log.Message("Ongoing: ticksWork = " + ticksWork);
                return(JobCondition.Ongoing);
            });
            applyBrainTemplateToil.AddFailCondition(() => workStarted && Patient.CurJobDef != JobDefOf.LayDown);

            yield return(applyBrainTemplateToil);
        }