protected override IEnumerable <Toil> MakeNewToils()
        {
            if (!ModLister.RoyaltyInstalled)
            {
                Log.ErrorOnce("Bestowing cermonies are a Royalty-specific game system. If you want to use this code please check ModLister.RoyaltyInstalled before calling it. See rules on the Ludeon forum for more info.", 5464564);
                yield break;
            }
            AddFailCondition(() => Bestower.GetLord() == null || Bestower.GetLord().CurLordToil == null || !(Bestower.GetLord().CurLordToil is LordToil_BestowingCeremony_Wait));
            yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.OnCell));

            Toil waitToil = Toils_General.Wait(471);

            waitToil.AddPreInitAction(delegate
            {
                Messages.Message("MessageBestowingCeremonyStarted".Translate(pawn.Named("PAWN")), Bestower, MessageTypeDefOf.PositiveEvent);
            });
            waitToil.AddPreInitAction(delegate
            {
                if (!AnalyzeThroneRoom(Bestower, pawn))
                {
                    Messages.Message("BestowingCeremonyThroneroomRequirementsNotSatisfied".Translate(pawn.Named("PAWN"), pawn.royalty.GetTitleAwardedWhenUpdating(Bestower.Faction, pawn.royalty.GetFavor(Bestower.Faction)).label.Named("TITLE")), pawn, MessageTypeDefOf.NegativeEvent);
                    ((LordJob_BestowingCeremony)Bestower.GetLord().LordJob).MakeCeremonyFail();
                }
            });
            waitToil.AddPreInitAction(delegate
            {
                SoundDefOf.Bestowing_Start.PlayOneShot(pawn);
            });
            waitToil.tickAction = delegate
            {
                pawn.rotationTracker.FaceTarget(Bestower);
                if (mote == null || mote.Destroyed)
                {
                    Vector3 loc = (pawn.TrueCenter() + Bestower.TrueCenter()) / 2f;
                    mote = MoteMaker.MakeStaticMote(loc, pawn.Map, ThingDefOf.Mote_Bestow);
                }
                mote.Maintain();
                if ((sound == null || sound.Ended) && waitToil.actor.jobs.curDriver.ticksLeftThisToil <= 307)
                {
                    sound = SoundDefOf.Bestowing_Warmup.TrySpawnSustainer(SoundInfo.InMap(new TargetInfo(pawn.Position, pawn.Map), MaintenanceType.PerTick));
                }
                if (sound != null)
                {
                    sound.Maintain();
                }
            };
            waitToil.handlingFacing = false;
            waitToil.socialMode     = RandomSocialMode.Off;
            waitToil.WithProgressBarToilDelay(TargetIndex.A);
            yield return(waitToil);

            yield return(Toils_General.Do(delegate
            {
                CeremonyJob.FinishCeremony(pawn);
                MoteMaker.MakeStaticMote((pawn.TrueCenter() + Bestower.TrueCenter()) / 2f, pawn.Map, ThingDefOf.Mote_PsycastAreaEffect, 2f);
                SoundDefOf.Bestowing_Finished.PlayOneShot(pawn);
            }));
        }
예제 #2
0
        public static void _ctor(Toil __instance)
        {
            if (SimpleSidearms.ToolAutoSwitch == true)
            {
                Toil toil = __instance;
                toil.AddPreInitAction(delegate
                {
                    if (toil.activeSkill != null && toil.activeSkill() != null && toil.GetActor() != null)
                    {
                        //Log.Message("Pawn " + toil.GetActor().Label + " initializing toil that uses skill " + toil.activeSkill().label);
                        bool usingAppropriateTool = WeaponAssingment.equipBestWeaponFromInventoryByStatModifiers(toil.GetActor(), SkillStatMap.Map[toil.activeSkill()]);
                        if (usingAppropriateTool)
                        {
                            GoldfishModule pawnMemory = GoldfishModule.GetGoldfishForPawn(toil.GetActor());
                            if (pawnMemory != null)
                            {
                                pawnMemory.autotoolToil = toil;
                            }
                        }
                    }
                });
                toil.AddFinishAction(delegate
                {
                    GoldfishModule pawnMemory = GoldfishModule.GetGoldfishForPawn(toil.GetActor());
                    if (pawnMemory != null && pawnMemory.autotoolToil == toil)
                    {
                        pawnMemory.delayIdleSwitchTimestamp = Find.TickManager.TicksGame;
                    }

                    pawnMemory.autotoolToil = null;
                });
            }
        }
예제 #3
0
            public static void Postfix(Toil __instance)
            {
                if (__instance == null)
                {
                    return;
                }

                __instance.AddPreInitAction(delegate
                {
                    Pawn pawn = __instance.GetActor();

                    if (pawn == null || pawn.Dead || pawn.equipment == null || pawn.inventory == null || !pawn.RaceProps.Humanlike)
                    {
                        return;
                    }

                    if (pawn.Drafted)
                    {
                        GrabYourToolMod.Instance.ClearMemory(pawn);
                        return;
                    }

                    SkillDef activeSkill = pawn.CurJob?.RecipeDef?.workSkill;
                    if (__instance.activeSkill != null && __instance.activeSkill() != null)
                    {
                        activeSkill = __instance.activeSkill();
                    }

                    if (activeSkill != null)
                    {
                        ToolMemory memory = GrabYourToolMod.Instance.GetMemory(pawn);

                        if (!memory.UpdateSkill(activeSkill))
                        {
                            return;
                        }

                        // Don't do it if this job uses weapons (i.e. hunting)
                        if (activeSkill == SkillDefOf.Shooting || activeSkill == SkillDefOf.Melee)
                        {
                            memory.UpdateUsingTool(null, false);
                        }
                        // Check currently equipped item
                        else if (pawn.equipment.Primary != null && ToolMemoryTracker.HasReleventStatModifiers(pawn.equipment.Primary, activeSkill))
                        {
                            memory.UpdateUsingTool(null, true);
                        }
                        // Try and find something else in inventory
                        else
                        {
                            memory.UpdateUsingTool(pawn.equipment.Primary, ToolMemoryTracker.EquipAppropriateWeapon(pawn, activeSkill));
                        }
                    }
                    else
                    {
                        GrabYourToolMod.Instance.ClearMemory(pawn);
                    }
                });
            }
 protected override void ModifyPlayToil(Toil toil)
 {
     base.ModifyPlayToil(toil);
     toil.AddPreInitAction(delegate
     {
         MusicalInstrument.StartPlaying(pawn);
     });
     toil.AddFinishAction(delegate
     {
         MusicalInstrument.StopPlaying();
     });
 }
예제 #5
0
        public static Toil PlaceBookInShelf(TargetIndex book, TargetIndex shelf, Pawn pawn)
        {
            ReadableBooks bookint   = (ReadableBooks)pawn.jobs.curJob.GetTarget(book).Thing;
            Bookshelf     bookshelf = (Bookshelf)pawn.jobs.curJob.GetTarget(shelf).Thing;

            Log.Message("Trying to place book");
            Toil toil = new Toil();

            toil.defaultCompleteMode = ToilCompleteMode.Instant;
            toil.AddPreInitAction(delegate
            {
                bookint.Destroy(DestroyMode.Vanish);
                bookshelf.AddBookToLibrary(bookint.Tdef);
            });
            return(toil);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOn(() => Find.World.GetComponent <WorldComponent_Uvhash>().CurrentBloodMage != null);
            this.EndOnDespawnedOrNull(InvestigateeIndex, JobCondition.Incompletable);
            //this.EndOnDespawnedOrNull(Build, JobCondition.Incompletable);
            yield return(Toils_Reserve.Reserve(InvestigateeIndex, this.job.def.joyMaxParticipants));

            var gotoInvestigatee = Toils_Goto.GotoThing(InvestigateeIndex, PathEndMode.ClosestTouch);

            yield return(gotoInvestigatee);

            yield return(Toils_Goto.GotoCell(Investigatee.InteractionCell, PathEndMode.OnCell));

            var watchToil = new Toil
            {
                defaultCompleteMode = ToilCompleteMode.Delay,
                defaultDuration     = this.job.def.joyDuration
            };

            watchToil.AddPreInitAction(() =>
            {
                ticksLeft = this.job.def.joyDuration;
            });
            watchToil.WithProgressBar(TargetIndex.A,
                                      () => 1f - (float)watchToil.actor.jobs.curDriver.ticksLeftThisToil /
                                      Mathf.Round((float)watchToil.actor.CurJob.def.joyDuration));
            watchToil.AddPreTickAction(() =>
            {
                ticksLeft--;
                this.pawn.rotationTracker.FaceCell(this.TargetA.Cell);
                this.pawn.GainComfortFromCellIfPossible();
            });
            watchToil.AddFinishAction(() =>
            {
                Find.World.GetComponent <WorldComponent_Uvhash>().Notify_BloodBond(this.pawn);
            });
            yield return(watchToil);
        }
        /// <summary>
        /// 行为过程
        /// </summary>
        /// <returns></returns>
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedOrNull(TargetIndex.A);
            this.FailOnDestroyedOrNull(TargetIndex.B);
            this.FailOnAggroMentalStateAndHostile(TargetIndex.B);                                                //B精神不正常
            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch));                         //走到囚犯身边

            yield return(Toils_Haul.StartCarryThing(TargetIndex.B, false, false, false));                        //搬运囚犯

            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).FailOnForbidden(TargetIndex.A)); //走到dark家具旁边

            Pawn prisoner = (Pawn)Target;
            Building_ElectricChair chair = (Building_ElectricChair)Thing;

            if (!prisoner.Dead)
            {
                Toil toilWaitWith = Toils_General.WaitWith(TargetIndex.A, 180, true, true); //交互3秒
                var  cpt          = chair.GetComp <CompPowerTrader>() ?? throw new Exception("cant find comp:CompPowerTrader");
                toilWaitWith.AddPreInitAction(() => { chair.OnOrOff(true); });              //启动电椅 提高电力负载
                toilWaitWith.AddFinishAction(() => { chair.OnOrOff(false); });              //恢复电力负载
                toilWaitWith.tickAction = delegate() {
                    if (!cpt.PowerOn)
                    {
                        ////Power interruption leads to { 0 } electrocution failure
                        Messages.Message("SR_ElectrocutionFailure".Translate(prisoner.Label), MessageTypeDefOf.NeutralEvent);
                        pawn.jobs.EndCurrentJob(JobCondition.Incompletable, true, true);
                    }
                };
                yield return(toilWaitWith); //交互

                yield return(new Toil
                {
                    initAction = delegate()
                    {
                        this.pawn.carryTracker.TryDropCarriedThing(this.Thing.Position, ThingPlaceMode.Direct, out Verse.Thing thing, null);//把囚犯扔下去
                    },
                    defaultCompleteMode = ToilCompleteMode.Instant
                });
예제 #8
0
        public static void Postfix(Toil __result, TargetIndex cellInd)
        {
            // make the "initAction" a final action:
            //TODO::::  Make a wrapper around old initAction that doesn't put
            //  stuff down if failure happens?

//            __result.preInitActions.Add(delegate () { __result.actor.jobs.debugLog = true; });
//            __result.AddFinishAction(__result.initAction);
            // replace it with a test for Deep Storage
            //   and if it IS deep storage, set up wait:
            Action placeStuff = __result.initAction;

            __result.AddPreInitAction(delegate() {
                __result.tickAction = null;
                Pawn actor          = __result.actor;
                Job curJob          = actor.jobs.curJob;
                IntVec3 cell        = curJob.GetTarget(cellInd).Cell;
                if (actor.carryTracker.CarriedThing == null)
                {
                    Log.Error(actor + " tried to place hauled thing in cell but is not hauling anything?", false);
                    return;
                }
                SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell);
                ThingComp comp;
                if (slotGroup == null || !(slotGroup?.parent is ThingWithComps) ||
                    (comp = ((ThingWithComps)slotGroup.parent).TryGetComp <CompDeepStorage>()) == null)
                {
                    __result.initAction = placeStuff;
                    return;
                }
                int timeStoringTakes = ((LWM.DeepStorage.Properties)comp.props).timeStoringTakes;
                if (timeStoringTakes <= 0)   // just like vanilla
                {
                    __result.initAction = placeStuff;
                    return;
                }

                __result.initAction = null;
                __result.tickAction = delegate() {
                    if (actor.jobs.curDriver.ticksLeftThisToil == 1) // last tick is 1, not 0
                    {
                        placeStuff();
                    }
                };

                actor.jobs.curDriver.ticksLeftThisToil = timeStoringTakes;

                __result.WithProgressBar(TargetIndex.B, () => 1f -
                                         (float)__result.actor.jobs.curDriver.ticksLeftThisToil / timeStoringTakes, true);
                Thing t = actor.CurJob.GetTarget(TargetIndex.A).Thing;

                // Add some end conditions:
                if (t != null)
                {
                    __result.FailOn(() => !slotGroup.parent.Accepts(t));
                }
            }); // added pre-init action!

            // HMM...let's get rid of stuff:
            __result.initAction          = null;
            __result.atomicWithPrevious  = false;
            __result.defaultCompleteMode = ToilCompleteMode.Delay;
            __result.defaultDuration     = 0; // changed by initAction, if needed
            __result.FailOnBurningImmobile(TargetIndex.B);

            // TODO: FailOn&c, EndOn&c
            //  Other fails.....
            //    No longer allowed in that area?
            //    No longer accepts what we're puttin there?
            //    Um?
        } // end Postfix
        public static void Postfix(Toil __result, TargetIndex cellInd)
        {
            Utils.Err(PlaceHauledThingInCell, "Starting new haul job, toils created");
            //TODO?  Make a wrapper around old initAction that doesn't put
            //  stuff down if failure happens?

            SlotGroup groupAt = __result?.actor?.Map?.haulDestinationManager?.SlotGroupAt(__result.actor?.CurJob?.GetTarget(cellInd).Cell ?? IntVec3.Invalid);

            if ((groupAt?.parent as ThingWithComps)?.GetComp <CompDeepStorage>() == null)
            {
                Utils.Err(PlaceHauledThingInCell, "Not going into Deep Storage, exiting ASAP without modifying anything.");
                return;
            }

            Action placeStuff = __result.initAction;

            // NOTE: none of this PreInitAtion happens if the game is being loaded while storing is going on:
            //   This means, among other things, that pawns don't get progress bars on reload
            //   I could make it happen if it ever gets to be important...
            __result.AddPreInitAction(delegate()
            {
                Pawn actor   = __result.actor;
                Job curJob   = actor.jobs.curJob;
                IntVec3 cell = curJob.GetTarget(cellInd).Cell;
                Utils.Err(PlaceHauledThingInCell, "PreInitAction called for " + actor + "'s haul job " + curJob.def.driverClass + " to " + cell);
                //                Log.Error("Place Hauled Thing in Cell:  Toil preInit!  Putting in "+cell.ToString());
                //                actor.jobs.debugLog = true;
                if (actor.carryTracker.CarriedThing == null)
                { // error as per original toil code
                    Log.Error(actor + " tried to place hauled thing in cell but is not hauling anything?", false);
                    return;
                }
                SlotGroup slotGroup = actor.Map.haulDestinationManager.SlotGroupAt(cell);
                CompDeepStorage cds;
                if (!(slotGroup?.parent is ThingWithComps) ||
                    (cds = (((ThingWithComps)slotGroup?.parent)?.GetComp <CompDeepStorage>())) == null)
                {
                    Utils.Warn(PlaceHauledThingInCell, "not going into Deep Storage");
                    return; // initAction still around, will handle
                }
                int timeStoringTakes = cds.timeStoringTakes(cell);
                if (timeStoringTakes <= 0)
                { // just like vanilla
                    Utils.Warn(PlaceHauledThingInCell, "Instantaneous storing time");
                    return;
                }
                // Remove the initAction so it doesn't happen before waiting starts:
                __result.initAction = null;
                if (actor.jobs.curDriver.ticksLeftThisToil < 1) // test is probably superfluous
                {
                    actor.jobs.curDriver.ticksLeftThisToil = timeStoringTakes;
                }
                // It'd be nice to have a progress bar for deep storage
                __result.WithProgressBar(TargetIndex.B, () => 1f -
                                         (float)__result.actor.jobs.curDriver.ticksLeftThisToil / timeStoringTakes, true);

                /***** Add some end conditions: *****/

                Thing t = actor.CurJob.GetTarget(TargetIndex.A).Thing;
                if (t != null)
                {
                    __result.FailOn(() => !slotGroup.parent.Accepts(t));
                }

                // TODO: any other end conditions?  Fail conditions?
                // TODO: Any reservations?
            }); // added pre-init action!

            // The tickAction is only called if we are going into Deep Storage,
            //   otherwise the toil is over after initAction and no ticks happen.
            // This will still get called even on load/save, because ticks count down.
            __result.tickAction = delegate()
            {
                Pawn pawn = __result.actor;
                Utils.Warn(PlaceHauledThingInCell,
                           "  " + pawn + "'s ticks left: " + __result.actor.jobs.curDriver.ticksLeftThisToil);
                if (pawn.jobs.curDriver.ticksLeftThisToil <= 1) // last tick is 1, not 0
                {
                    Utils.Err(PlaceHauledThingInCell, "Hit 0 ticks");
                    placeStuff();
                }
            };

            // ToilCompleteMode.Delay is acceptable in vanilla case, as duration is 0:
            __result.defaultCompleteMode = ToilCompleteMode.Delay;
            __result.defaultDuration     = 0; // changed by PreInitAction, if needed
            __result.FailOnBurningImmobile(TargetIndex.B);

            // todo reservations (possibly?)
            // also todo, undo reservations (possibly?) (as another final action?)

            // TODO: FailOn&c, EndOn&c
            //  Other fails.....
            //    No longer allowed in that area?  <--- Very definitely TODO
            //    Um?
        } // end Postfix
예제 #10
0
        public static void _ctor(Toil __instance)
        {
            if (SimpleSidearms.ToolAutoSwitch == true)
            {
                Toil toil = __instance;
                if (toil == null)
                {
                    return;
                }

                toil.AddPreInitAction(delegate
                {
                    Pawn pawn = toil.GetActor();
                    if (pawn == null || !pawn.IsValidSidearmsCarrier())
                    {
                        return;
                    }

                    CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                    if (pawnMemory == null)
                    {
                        return;
                    }
                    pawnMemory.CheckIfStillOnAutotoolJob();

                    StatDef activeStat = pawn.CurJob?.RecipeDef?.workSpeedStat;

                    SkillDef activeSkill = null;
                    if (toil.activeSkill != null && toil.activeSkill() != null)
                    {
                        activeSkill = toil.activeSkill();
                    }
                    else
                    {
                        activeSkill = pawn.CurJob?.RecipeDef?.workSkill;
                    }

                    List <StatDef> possiblyActiveStats = new List <StatDef>();
                    if (activeStat != null)
                    {
                        possiblyActiveStats.Add(activeStat);
                    }
                    else if (activeSkill != null && SkillStatMap.Map.ContainsKey(activeSkill))
                    {
                        possiblyActiveStats.AddRange(SkillStatMap.Map[activeSkill]);
                    }

                    bool usingAppropriateTool = WeaponAssingment.equipBestWeaponFromInventoryByStatModifiers(toil.GetActor(), possiblyActiveStats);
                    if (usingAppropriateTool)
                    {
                        if (pawnMemory != null)
                        {
                            pawnMemory.autotoolToil = toil;
                            pawnMemory.autotoolJob  = pawn.CurJobDef;
                        }
                    }
                });
                toil.AddFinishAction(delegate
                {
                    Pawn pawn = toil.GetActor();
                    if (!pawn.IsValidSidearmsCarrier())
                    {
                        return;
                    }
                    CompSidearmMemory pawnMemory = CompSidearmMemory.GetMemoryCompForPawn(pawn);
                    if (pawnMemory != null)
                    {
                        if (pawnMemory.autotoolToil == toil)
                        {
                            pawnMemory.delayIdleSwitchTimestamp = Find.TickManager.TicksGame;
                        }
                        else
                        {
                            pawnMemory.autotoolToil = null;
                        }
                    }
                });
            }
        }
예제 #11
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.EndOnDespawnedOrNull(Executioner, JobCondition.Incompletable);
            if (CultUtility.AreOccultGrimoiresAvailable(pawn.Map))
            {
                pawn.Map.GetComponent <MapComponent_LocalCultTracker>().CurrentSeedState = CultSeedState.NeedTable;
            }
            else
            {
                IntVec3 destination = IntVec3.Invalid;

                //First, let's try and find a typewriter.
                //If we find one, let's go to it and start typing.
                Thing Typewriter = null;
                if (Cthulhu.Utility.IsIndustrialAgeLoaded())
                {
                    Cthulhu.Utility.DebugReport("Industrial age check");
                    if (this.pawn.Map != null)
                    {
                        if (this.pawn.Map.listerBuildings != null)
                        {
                            foreach (Building thing in this.pawn.Map.listerBuildings.allBuildingsColonist)
                            {
                                if (thing.def.defName == "Estate_TableTypewriter")
                                {
                                    Typewriter = thing;
                                    Cthulhu.Utility.DebugReport("Found typewriter");
                                    Toil gotoDestination = Toils_Goto.GotoCell(Typewriter.InteractionCell, PathEndMode.OnCell);
                                    atTypeWriter = true;
                                    yield return(gotoDestination);

                                    goto SkipRoom;
                                }
                            }
                        }
                    }
                }

                //If we don't have a typewriter, then let's go to our personal room or near our bed.
                Room     destinationRoom = this.pawn.ownership.OwnedRoom;
                Building destinationBed  = this.pawn.ownership.OwnedBed;
                if (destinationRoom != null)
                {
                    if (destinationRoom.Cells.TryRandomElement <IntVec3>(out destination))
                    {
                        IntVec3 cellInsideRoom = IntVec3.Invalid;
                        if (Cthulhu.Utility.IsRandomWalkable8WayAdjacentOf(destination, Map, out cellInsideRoom))
                        {
                            Toil gotoRoom;
                            gotoRoom = Toils_Goto.GotoCell(cellInsideRoom, PathEndMode.OnCell);
                            yield return(gotoRoom);

                            goto SkipRoom;
                        }
                    }
                }
                else if (destinationBed != null)
                {
                    IntVec3 cellNearBed = IntVec3.Invalid;
                    if (Cthulhu.Utility.IsRandomWalkable8WayAdjacentOf(destinationBed.Position, Map, out cellNearBed))
                    {
                        Toil gotoBedArea;
                        gotoBedArea = Toils_Goto.GotoCell(cellNearBed, PathEndMode.OnCell);
                    }
                }

SkipRoom:

                Toil altarToil = new Toil();
                altarToil.defaultCompleteMode = ToilCompleteMode.Delay;
                if (atTypeWriter)
                {
                    altarToil.PlaySustainerOrSound(SoundDef.Named("Estate_SoundManualTypewriter"));
                }
                else
                {
                    altarToil.PlaySustainerOrSound(SoundDef.Named("PencilWriting"));
                }
                altarToil.WithProgressBarToilDelay(TargetIndex.A);
                altarToil.defaultDuration = this.job.def.joyDuration;
                altarToil.AddPreTickAction(() =>
                {
                    if (Typewriter != null)
                    {
                        this.pawn.rotationTracker.FaceCell(Typewriter.Position);
                        this.pawn.GainComfortFromCellIfPossible();
                    }
                });
                altarToil.AddPreInitAction(() =>
                {
                    Messages.Message(this.pawn.LabelCap + "WritingStrangeSymbols".Translate(), MessageTypeDefOf.NeutralEvent);
                });
                yield return(altarToil);

                Toil finishedAction = new Toil();
                finishedAction.defaultCompleteMode = ToilCompleteMode.Instant;
                finishedAction.initAction          = delegate
                {
                    Map.GetComponent <MapComponent_LocalCultTracker>().CurrentSeedState = CultSeedState.FinishedWriting;
                };
                yield return(finishedAction);

                this.AddFinishAction(() =>
                {
                    if (Map.GetComponent <MapComponent_LocalCultTracker>().CurrentSeedState == CultSeedState.FinishedWriting)
                    {
                        CultUtility.FinishedTheBook(this.pawn);
                    }
                });
            }
        }
예제 #12
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);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            /*
             *
             *  Toil Configurations
             *
             */
            Toil prepareToSpin = new Toil();

            prepareToSpin.initAction = delegate
            {
                if (Prey == null && Corpse == null)
                {
                    this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                    return;
                }
                if (Prey.Dead)
                {
                    this.pawn.CurJob.SetTarget(TargetIndex.A, Prey.Corpse);
                }
            };

            Toil gotoBody = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch);

            gotoBody.AddPreInitAction(new Action(delegate
            {
                this.pawn.ClearAllReservations();
                this.pawn.Reserve(TargetA, this.job);
                //this.Map.physicalInteractionReservationManager.ReleaseAllForTarget(TargetA);
                //this.Map.physicalInteractionReservationManager.Reserve(this.GetActor(), TargetA);
                currentActivity = "Spinning Cocoon";
            }));

            Toil spinDelay = new Toil
            {
                defaultCompleteMode = ToilCompleteMode.Delay,
                defaultDuration     = 500,
                initAction          = delegate
                {
                    currentActivity = "Spinning Cocoon";
                }
            };

            spinDelay.WithProgressBarToilDelay(TargetIndex.B);
            Toil spinBody = new Toil
            {
                initAction = delegate
                {
                    //Log.Message("5");
                    var spinner = this.GetActor() as Spider;
                    if (spinner != null)
                    {
                        Building_Cocoon newCocoon;
                        Thing           toLoad;
                        IntVec3         newPosition;
                        if (Prey.Dead)
                        {
                            toLoad      = Prey.Corpse;
                            newPosition = Prey.Corpse.Position;
                        }
                        else
                        {
                            toLoad      = Prey;
                            newPosition = Prey.Position;
                        }
                        if (!toLoad.Spawned)
                        {
                            this.EndJobWith(JobCondition.Incompletable); return;
                        }

                        toLoad.DeSpawn();
                        toLoad.holdingOwner = null;
                        if (!GenConstruct.CanPlaceBlueprintAt(CocoonDef, newPosition, Rot4.North, this.pawn.Map).Accepted)
                        {
                            var cells = GenAdj.CellsAdjacent8Way(new TargetInfo(newPosition, this.pawn.Map));
                            foreach (IntVec3 cell in cells)
                            {
                                if (GenConstruct.CanPlaceBlueprintAt(CocoonDef, cell, Rot4.North, this.Map).Accepted)
                                {
                                    newPosition = cell;
                                    break;
                                }
                            }
                        }

                        newCocoon = (Building_Cocoon)GenSpawn.Spawn(CocoonDef, newPosition, spinner.Map);
                        //Log.Message("New Spinner: " + newCocoon.Spinner.Label);
                        newCocoon.TryGetInnerInteractableThingOwner().TryAdd(toLoad);
                        this.pawn?.CurJob?.SetTarget(TargetIndex.B, newCocoon);
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            Toil pickupCocoon = Toils_Haul.StartCarryThing(TargetIndex.B);

            pickupCocoon.AddPreInitAction(new Action(delegate
            {
                //this.TargetB.Thing.DeSpawn();
                this.pawn.CurJob.SetTarget(TargetIndex.C, TargetB.Thing);
                this.pawn.Reserve(TargetC, this.job);
                //this.pawn.Map.physicalInteractionReservationManager.Reserve(this.pawn, TargetC);
            }));
            Toil relocateCocoon = Toils_Haul.CarryHauledThingToCell(TargetIndex.C);
            Toil dropCocoon     = Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, relocateCocoon, false).FailOn(() => !GenConstruct.CanPlaceBlueprintAt(CocoonDef, TargetC.Cell, Rot4.North, this.Map).Accepted);

            this.AddFinishAction(new Action(delegate
            {
                this.pawn.Map.physicalInteractionReservationManager.ReleaseAllClaimedBy(this.pawn);
            }));


            /*
             *
             *  Toil Execution
             *
             */
            yield return(new Toil
            {
                initAction = delegate
                {
                    this.Map.attackTargetsCache.UpdateTarget(this.pawn);
                },
                atomicWithPrevious = true,
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            Action onHitAction = delegate
            {
                Pawn prey           = this.Prey;
                bool surpriseAttack = this.firstHit && !prey.IsColonist;
                if (this.pawn.meleeVerbs.TryMeleeAttack(prey, this.job.verbToUse, surpriseAttack))
                {
                    if (!this.notifiedPlayer && PawnUtility.ShouldSendNotificationAbout(prey))
                    {
                        this.notifiedPlayer = true;
                        Messages.Message("MessageAttackedByPredator".Translate(new object[]
                        {
                            prey.LabelShort,
                            this.pawn.LabelIndefinite()
                        }).CapitalizeFirst(), prey, MessageTypeDefOf.ThreatBig);// MessageSound.SeriousAlert);
                    }
                    this.Map.attackTargetsCache.UpdateTarget(this.pawn);
                }
                this.firstHit = false;
            };

            //yield return Toils_Combat.FollowAndMeleeAttack(TargetIndex.A, onHitAction).JumpIf(() => Prey.Downed || Prey.Dead, prepareToSpin).FailOn(() => Find.TickManager.TicksGame > this.startTick + 5000 && (float)(this.job.GetTarget(TargetIndex.A).Cell - this.pawn.Position).LengthHorizontalSquared > 4f);
            yield return(prepareToSpin.FailOn(() => Prey == null));

            yield return(gotoBody.FailOn(() => Prey == null));

            yield return(spinDelay.FailOn(() => Prey == null));

            yield return(spinBody.FailOn(() => Prey == null));
            //yield return pickupCocoon;
            //yield return relocateCocoon;
            //yield return dropCocoon;

            //float durationMultiplier = 1f / this.pawn.GetStatValue(StatDefOf.EatingSpeed, true);
            //yield return Toils_Ingest.ChewIngestible(this.pawn, durationMultiplier, TargetIndex.A, TargetIndex.None).FailOnDespawnedOrNull(TargetIndex.A).FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch);
            //yield return Toils_Ingest.FinalizeIngest(this.pawn, TargetIndex.A);
            //yield return Toils_Jump.JumpIf(gotoCorpse, () => this.pawn.needs.food.CurLevelPercentage < 0.9f);
        }
예제 #14
0
        public override IEnumerable <Toil> MakeNewToils()
        {
            AddEndCondition(delegate
            {
                Thing thing = GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing;
                if (thing is Building && !thing.Spawned)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });
            this.FailOnBurningImmobile(TargetIndex.A);
            this.FailOn(delegate()
            {
                IBillGiver billGiver = job.GetTarget(TargetIndex.A).Thing as IBillGiver;
                if (billGiver != null)
                {
                    if (job.bill.DeletedOrDereferenced)
                    {
                        return(true);
                    }
                    if (!billGiver.CurrentlyUsableForBills())
                    {
                        return(true);
                    }
                }
                if (inShelf && !bookOut && !shelf.innerContainer.Contains(book))
                {
                    return(true);
                }
                return(false);
            });
            AddFinishAction(delegate
            {
                if (inShelf && bookOut)
                {
                    shelf.CheckBookOut(book, true);
                }
            });
            Toil gotoBillGiver = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell);

            yield return(Toils_Jump.JumpIf(gotoBillGiver, () => job.GetTargetQueue(TargetIndex.B).NullOrEmpty <LocalTargetInfo>()));

            Toil extract = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, true);

            yield return(extract);

            Toil getToHaulTarget = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B);

            yield return(getToHaulTarget);

            yield return(inShelf ? TakeFromShelf(TargetIndex.B) : Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true));

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

            Toil findPlaceTarget = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C);

            yield return(findPlaceTarget);

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

            extract         = null;
            getToHaulTarget = null;
            findPlaceTarget = null;
            yield return(gotoBillGiver);

            yield return(Toils_Recipe.DoRecipeWork().FailOnDespawnedNullOrForbiddenPlacedThings().FailOnCannotTouch(TargetIndex.A, PathEndMode.InteractionCell));

            Toil upload = new Toil();

            upload.initAction = delegate()
            {
                Pawn             actor            = upload.actor;
                Job              curJob           = actor.jobs.curJob;
                JobDriver_DoBill jobDriver_DoBill = (JobDriver_DoBill)actor.jobs.curDriver;
                if (curJob.RecipeDef.workSkill != null)
                {
                    float xp = (float)jobDriver_DoBill.ticksSpentDoingRecipeWork * 0.1f * curJob.RecipeDef.workSkillLearnFactor;
                    actor.skills.GetSkill(curJob.RecipeDef.workSkill).Learn(xp, false);
                }
                project.Unlock(TargetThingA, false);
                Thing scanned = TargetB.Thing;
                if (scanned.def == TechDefOf.TechDrive)
                {
                    Toils_Recipe_Patch.ConsumeIngredients(new List <Thing> {
                        scanned
                    }, curJob.RecipeDef, actor.Map);
                }
                curJob.bill.Notify_IterationCompleted(actor, new List <Thing>());
            };
            yield return(upload);

            //Put it back!
            if (inShelf)
            {
                yield return(Toils_Haul.StartCarryThing(TargetIndex.B, true, false, true));

                yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, true));

                yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch).FailOnDestroyedOrNull(TargetIndex.B));

                Toil handOver = Toils_Haul.DepositHauledThingInContainer(TargetIndex.B, TargetIndex.A);
                handOver.AddPreInitAction(delegate
                {
                    bookOut = false;
                });
                yield return(handOver);
            }
            yield return(new Toil()
            {
                initAction = delegate()
                {
                    pawn.jobs.EndCurrentJob(JobCondition.Succeeded, true, true);
                }
            });

            yield break;
        }
        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);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedOrNull(TargetIndex.A);
            this.FailOnDestroyedOrNull(TargetIndex.B);
            this.FailOnAggroMentalStateAndHostile(TargetIndex.A);
            this.FailOn(delegate()
            {
                if (this.job.def.makeTargetPrisoner)
                {
                    if (!this.DropBed.ForPrisoners)
                    {
                        return(true);
                    }
                }
                else if (this.DropBed.ForPrisoners != this.Takee.IsPrisoner)
                {
                    return(true);
                }
                return(false);
            });
            yield return(Toils_Bed.ClaimBedIfNonMedical(TargetIndex.B, TargetIndex.A));

            base.AddFinishAction(delegate
            {
                if (this.job.def.makeTargetPrisoner && this.Takee.ownership.OwnedBed == this.DropBed && this.Takee.Position != RestUtility.GetBedSleepingSlotPosFor(this.Takee, this.DropBed))
                {
                    this.Takee.ownership.UnclaimBed();
                }
            });
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOn(() => this.job.def == JobDefOf.Arrest && !this.Takee.CanBeArrestedBy(this.pawn)).FailOn(() => !this.pawn.CanReach(this.DropBed, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn)).FailOn(() => this.job.def == JobDefOf.Rescue && !this.Takee.Downed).FailOnSomeonePhysicallyInteracting(TargetIndex.A));

            yield return(new Toil
            {
                initAction = delegate()
                {
                    if (this.job.def.makeTargetPrisoner)
                    {
                        Pawn pawn = (Pawn)this.job.targetA.Thing;
                        Lord lord = pawn.GetLord();
                        if (lord != null)
                        {
                            lord.Notify_PawnAttemptArrested(pawn);
                        }
                        GenClamor.DoClamor(pawn, 10f, ClamorDefOf.Harm);
                        if (this.job.def == JobDefOf.Arrest && !pawn.CheckAcceptArrest(this.pawn))
                        {
                            this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                        }
                    }
                }
            });

            Toil startCarrying = Toils_Haul.StartCarryThing(TargetIndex.A, false, false, false).FailOnNonMedicalBedNotOwned(TargetIndex.B, TargetIndex.A);

            startCarrying.AddPreInitAction(new Action(this.CheckMakeTakeeGuest));
            yield return(startCarrying);

            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch));

            yield return(new Toil
            {
                initAction = delegate()
                {
                    this.CheckMakeTakeePrisoner();
                    if (this.Takee.playerSettings == null)
                    {
                        this.Takee.playerSettings = new Pawn_PlayerSettings(this.Takee);
                    }
                }
            });

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

            yield return(new Toil
            {
                initAction = delegate()
                {
                    IntVec3 position = this.DropBed.Position;
                    Thing thing;
                    this.pawn.carryTracker.TryDropCarriedThing(position, ThingPlaceMode.Direct, out thing, null);
                    if (!this.DropBed.Destroyed && (this.DropBed.owners.Contains(this.Takee) || (this.DropBed.Medical && this.DropBed.AnyUnoccupiedSleepingSlot) || this.Takee.ownership == null))
                    {
                        this.Takee.jobs.Notify_TuckedIntoBed(this.DropBed);
                        if (this.Takee.RaceProps.Humanlike && this.job.def != JobDefOf.Arrest && !this.Takee.IsPrisonerOfColony)
                        {
                            this.Takee.relations.Notify_RescuedBy(this.pawn);
                        }
                        this.Takee.mindState.Notify_TuckedIntoBed();
                    }
                    if (this.Takee.IsPrisonerOfColony)
                    {
                        LessonAutoActivator.TeachOpportunity(ConceptDefOf.PrisonerTab, this.Takee, OpportunityType.GoodToKnow);
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            yield break;
        }
예제 #17
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedOrNull(TargetIndex.A);
            this.FailOnDestroyedOrNull(TargetIndex.B);
            this.FailOnAggroMentalStateAndHostile(TargetIndex.A);
            this.FailOn(delegate
            {
                if (job.def.makeTargetPrisoner)
                {
                    if (!DropBed.ForPrisoners)
                    {
                        return(true);
                    }
                }
                else if (DropBed.ForPrisoners != Takee.IsPrisoner)
                {
                    return(true);
                }
                return(false);
            });
            yield return(Toils_Bed.ClaimBedIfNonMedical(TargetIndex.B, TargetIndex.A));

            AddFinishAction(delegate
            {
                if (job.def.makeTargetPrisoner && Takee.ownership.OwnedBed == DropBed && Takee.Position != RestUtility.GetBedSleepingSlotPosFor(Takee, DropBed))
                {
                    Takee.ownership.UnclaimBed();
                }
            });
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.B)
                         .FailOn(() => job.def == JobDefOf.Arrest && !Takee.CanBeArrestedBy(pawn))
                         .FailOn(() => !pawn.CanReach(DropBed, PathEndMode.OnCell, Danger.Deadly))
                         .FailOn(() => (job.def == JobDefOf.Rescue || job.def == JobDefOf.Capture) && !Takee.Downed)
                         .FailOnSomeonePhysicallyInteracting(TargetIndex.A));

            Toil toil = new Toil();

            toil.initAction = delegate
            {
                if (job.def.makeTargetPrisoner)
                {
                    Pawn pawn = (Pawn)job.targetA.Thing;
                    pawn.GetLord()?.Notify_PawnAttemptArrested(pawn);
                    GenClamor.DoClamor(pawn, 10f, ClamorDefOf.Harm);
                    if (job.def == JobDefOf.Arrest && !pawn.CheckAcceptArrest(base.pawn))
                    {
                        base.pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                    }
                    if (!pawn.IsPrisoner)
                    {
                        QuestUtility.SendQuestTargetSignals(pawn.questTags, "Arrested", pawn.Named("SUBJECT"));
                    }
                }
            };
            yield return(toil);

            Toil toil2 = Toils_Haul.StartCarryThing(TargetIndex.A).FailOnNonMedicalBedNotOwned(TargetIndex.B, TargetIndex.A);

            toil2.AddPreInitAction(CheckMakeTakeeGuest);
            yield return(toil2);

            yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.Touch));

            Toil toil3 = new Toil();

            toil3.initAction = delegate
            {
                CheckMakeTakeePrisoner();
                if (Takee.playerSettings == null)
                {
                    Takee.playerSettings = new Pawn_PlayerSettings(Takee);
                }
            };
            yield return(toil3);

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

            Toil toil4 = new Toil();

            toil4.initAction = delegate
            {
                IntVec3 position = DropBed.Position;
                pawn.carryTracker.TryDropCarriedThing(position, ThingPlaceMode.Direct, out Thing _);
                if (!DropBed.Destroyed && (DropBed.OwnersForReading.Contains(Takee) || (DropBed.Medical && DropBed.AnyUnoccupiedSleepingSlot) || Takee.ownership == null))
                {
                    Takee.jobs.Notify_TuckedIntoBed(DropBed);
                    if (Takee.RaceProps.Humanlike && job.def != JobDefOf.Arrest && !Takee.IsPrisonerOfColony)
                    {
                        Takee.relations.Notify_RescuedBy(pawn);
                    }
                    Takee.mindState.Notify_TuckedIntoBed();
                }
                if (Takee.IsPrisonerOfColony)
                {
                    LessonAutoActivator.TeachOpportunity(ConceptDefOf.PrisonerTab, Takee, OpportunityType.GoodToKnow);
                }
            };
            toil4.defaultCompleteMode = ToilCompleteMode.Instant;
            yield return(toil4);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            var checkIncaseJobWasCancelledPreviously = new Toil
            {
                initAction = () =>
                {
                    var curMap     = this.GetActor().MapHeld;
                    var lastCorpse = curMap.listerThings.AllThings.FirstOrDefault(x =>
                                                                                  x is Corpse c && c.InnerPawn.health.hediffSet.HasHediff(UvhashDefOf.Uvhash_TattooParalysis));
                    if (lastCorpse != null)
                    {
                        this.job.SetTarget(TargetIndex.A, lastCorpse);
                    }
                }
            };

            var prepareToTransformCorpse = new Toil();

            prepareToTransformCorpse.initAction = delegate
            {
                Pawn   actor  = prepareToTransformCorpse.actor;
                Corpse corpse = this.Corpse;
                if (corpse == null)
                {
                    Pawn prey = this.Prey;
                    if (prey == null)
                    {
                        actor.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                        return;
                    }
                    corpse = prey.Corpse;
                    if (corpse == null || !corpse.Spawned)
                    {
                        actor.jobs.EndCurrentJob(JobCondition.Incompletable, true);
                        return;
                    }
                }
                corpse.SetForbidden(actor.Faction != Faction.OfPlayer, false);
                actor.CurJob.SetTarget(TargetIndex.A, corpse);
            };
            var goToCorpse      = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch);
            var goToPreyPos     = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch);
            var gotoCastPos     = Toils_Combat.GotoCastPosition(TargetIndex.A, true).JumpIfDespawnedOrNull(TargetIndex.A, prepareToTransformCorpse).FailOn(() => Find.TickManager.TicksGame > this.jobStartTick + 5000);
            var moveIfCannotHit = Toils_Jump.JumpIfTargetNotHittable(TargetIndex.A, goToPreyPos);
            var castSpell       = new Toil {
                defaultCompleteMode = ToilCompleteMode.Delay
            };

            castSpell.WithProgressBarToilDelay(TargetIndex.A);
            castSpell.defaultDuration = 1200;
            castSpell.AddPreInitAction(() =>
            {
                curReport  = "BloodMage_CastingOn".Translate(TargetA.Thing.Label);
                moteThrown = UvhashUtility.ThrowMagicMote(1f, this.GetActor());
                moteThrown.LifeSpanOffset += 99999f;
                moteTarget.LifeSpanOffset += 99999f;
                moteTarget = UvhashUtility.ThrowMagicMote(TargetA.Thing.def.race.baseBodySize, TargetA.Thing);
            });
            castSpell.tickAction = () =>
            {
                if (moteThrown != null)
                {
                    moteThrown.exactPosition = this.GetActor().DrawPos;
                }
                if (moteTarget != null)
                {
                    moteTarget.exactPosition = TargetA.Thing.DrawPos;
                }
                if (Find.TickManager.TicksGame % 15 == 0)
                {
                    MoteMaker.ThrowText(this.GetActor().DrawPos + new Vector3(new FloatRange(-1, 1).RandomInRange, 0, new FloatRange(-1, 1).RandomInRange), this.GetActor().MapHeld, cultMadText.RandomElement(), Color.red);
                    //MoteMaker.ThrowText(this.TargetA.Thing.DrawPos + new Vector3(new FloatRange(-1, 1).RandomInRange, 0, new FloatRange(-1, 1).RandomInRange), this.GetActor().MapHeld, cultMadText.RandomElement(), Color.red);
                }
            };
            castSpell.PlaySustainerOrSound(UvhashDefOf.Uvhash_BloodMagicCastingSustainer);
            castSpell.AddFinishAction(() =>
            {
                if (!Prey.Downed)
                {
                    HealthUtility.AdjustSeverity(Prey, UvhashDefOf.Uvhash_TattooParalysis, 1.0f);
                }
                curReport = "";
                if (moteThrown != null)
                {
                    moteThrown.LifeSpanOffset -= 999999f;
                }
                if (moteTarget != null)
                {
                    moteTarget.LifeSpanOffset -= 999999f;
                }
            });
            var executeTarget = new Toil {
                defaultCompleteMode = ToilCompleteMode.Delay
            };

            executeTarget.WithProgressBarToilDelay(TargetIndex.B);
            executeTarget.defaultDuration = 200;
            executeTarget.AddFinishAction(() =>
            {
                ExecutionUtility.DoExecutionByCut(this.GetActor(), Prey);
            });
            Toil transformCorpse = new Toil();

            transformCorpse.defaultCompleteMode = ToilCompleteMode.Delay;
            transformCorpse.WithEffect(() => EffecterDef.Named("ButcherFlesh"), TargetIndex.A);
            transformCorpse.WithProgressBarToilDelay(TargetIndex.A);
            transformCorpse.defaultDuration = 800;
            transformCorpse.AddPreInitAction(() =>
            {
                Messages.Message("BloodBookCreation_Message".Translate(new object[] { this.pawn.LabelCap, this.Prey.Label }), MessageTypeDefOf.NeutralEvent);
            });
            var destroyCorpseAndSpawnBook = new Toil();

            destroyCorpseAndSpawnBook.initAction = () =>
            {
                var corpsePos = Corpse.PositionHeld;
                var corpseMap = Corpse.MapHeld;
                Corpse.Destroy();
                FilthMaker.MakeFilth(corpsePos, corpseMap, ThingDefOf.FilthBlood, Rand.Range(1, 2));
                for (int i = 0; i < 10; i++)
                {
                    FilthMaker.MakeFilth(corpsePos.RandomAdjacentCell8Way(), corpseMap, ThingDefOf.FilthBlood, Rand.Range(1, 2));
                    this.GetActor().filth.GainFilth(ThingDefOf.FilthBlood);
                }
                var book = (ThingWithComps_LiberCruoris)ThingMaker.MakeThing(UvhashDefOf.Uvhash_LiberCruoris);
                GenPlace.TryPlaceThing(book, corpsePos, corpseMap, ThingPlaceMode.Near);

                Find.World.GetComponent <WorldComponent_Uvhash>().CurrentCrystalStage = CrystalStage.BookCreated;
                this.GetActor().MentalState.RecoverFromState();
                this.GetActor().TryGetComp <CompBloodMage>().BloodMageLevel = 1;
                UvhashUtility.ShowMessageBox("BloodBookCreatedDesc".Translate(this.GetActor()).AdjustedFor(this.GetActor()), "BloodBookCreated".Translate());
            };

            yield return(new Toil
            {
                initAction = delegate
                {
                    this.jobStartTick = Find.TickManager.TicksGame;
                }
            });

            yield return(checkIncaseJobWasCancelledPreviously);

            yield return(Toils_Jump.JumpIf(goToCorpse, () => Prey.Dead));

            yield return(Toils_Jump.JumpIf(goToPreyPos, () => Prey.Downed));

            yield return(Toils_Combat.TrySetJobToUseAttackVerb());

            yield return(gotoCastPos.FailOn(() => this.GetActor().IsFighting()));

            yield return(castSpell);

            yield return(goToPreyPos);

            yield return(executeTarget);

            yield return(prepareToTransformCorpse);

            yield return(goToCorpse);

            yield return(transformCorpse);

            yield return(destroyCorpseAndSpawnBook);

            this.AddFinishAction(() =>
            {
                if (moteThrown != null)
                {
                    moteThrown.LifeSpanOffset -= 999999f;
                }
                if (moteTarget != null)
                {
                    moteTarget.LifeSpanOffset -= 999999f;
                }
            });
            yield break;
        }