public static void RebuffDemandAndSmiteThePlayer(TravelingIncidentCaravan caravan, Pawn pawn)
 {
     if (!(caravan.incident is InterceptedIncident_HumanCrowd_RaidEnemy incident))
     {
         return;
     }
     caravan.Communicable = false;
     if (incident.raidGoalType == RaidGoalType.Rescue)
     {
         RaidingGoal_Rescue goal = incident.goal as RaidingGoal_Rescue;
         foreach (var p in goal.Prisoners)
         {
             p.guilt.lastGuiltyTick = Find.TickManager.TicksGame;
             ExecutionUtility.DoExecutionByCut(pawn, p);
         }
     }
     incident.goal = new RaidingGoal_Smite();
     if (pawn.skills.GetSkill(SkillDefOf.Social).Level < 5)
     {
         incident.CombatMoral = -1;
     }
     else if (pawn.skills.GetSkill(SkillDefOf.Social).Level < 10)
     {
         incident.CombatMoral = 0;
     }
     else
     {
         incident.CombatMoral = 1;
     }
 }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            yield return(Toils_Goto.Goto(TargetIndex.A, PathEndMode.Touch).FailOn(() => !Victim.Downed));

            Toil execute = new Toil();

            execute.initAction = delegate
            {
                ExecutionUtility.DoExecutionByCut(execute.actor, Victim);
            };
            execute.defaultCompleteMode = ToilCompleteMode.Instant;
            execute.activeSkill         = (() => SkillDefOf.Melee);
            yield return(execute);
        }
Example #3
0
        // Token: 0x06002BEA RID: 11242 RVA: 0x000FF850 File Offset: 0x000FDA50
        public override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnAggroMentalState(TargetIndex.A);
            this.FailOnThingMissingDesignation(TargetIndex.A, DesignationDefOf.Slaughter);
            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch));

            yield return(Toils_General.WaitWith(TargetIndex.A, 180, true, false));

            yield return(Toils_General.Do(delegate
            {
                ExecutionUtility.DoExecutionByCut(this.pawn, this.Victim);
                this.pawn.records.Increment(RecordDefOf.AnimalsSlaughtered);
                if (this.pawn.InMentalState)
                {
                    this.pawn.MentalState.Notify_SlaughteredAnimal();
                }
            }));

            yield break;
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnAggroMentalState(TargetIndex.A);
            yield return(Toils_Interpersonal.GotoPrisoner(pawn, Victim, PrisonerInteractionModeDefOf.Execution).FailOn(() => !Victim.IsPrisonerOfColony || !Victim.guest.PrisonerIsSecure));

            Toil execute = new Toil();

            execute.initAction = delegate
            {
                ExecutionUtility.DoExecutionByCut(execute.actor, Victim);
                ThoughtUtility.GiveThoughtsForPawnExecuted(Victim, PawnExecutionKind.GenericBrutal);
                TaleRecorder.RecordTale(TaleDefOf.ExecutedPrisoner, new object[]
                {
                    pawn,
                    Victim
                });
            };
            execute.defaultCompleteMode = ToilCompleteMode.Instant;
            yield return(execute);
        }
Example #5
0
 private Toil Sacrifce(TargetIndex sacrificable)
 {
     return(new Toil()
     {
         initAction = delegate
         {
             Thing sacrificableThing = pawn.CurJob.GetTarget(sacrificable).Thing;
             if (sacrificableThing != null)
             {
                 Pawn sacrificablePawn = sacrificableThing as Pawn;
                 if (sacrificablePawn != null)
                 {
                     ExecutionUtility.DoExecutionByCut(pawn, sacrificablePawn);
                     pawn.Reserve(sacrificablePawn.Corpse, this.job);
                 }
                 else
                 {
                     sacrificableThing.Destroy(DestroyMode.Vanish);
                 }
             }
         }
     });
 }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOn(delegate
            {
                if (!job.ignoreDesignations)
                {
                    Pawn victim = Victim;
                    if (victim != null && !victim.Dead && Map.designationManager.DesignationOn(victim, DesignationDefOf.Hunt) == null)
                    {
                        return(true);
                    }
                }
                return(false);
            });

            yield return(Toils_Reserve.Reserve(VictimInd, 1));

            var init = new Toil();

            init.initAction = delegate
            {
                jobStartTick = Find.TickManager.TicksGame;
            };
            yield return(init);

            yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A));

            var comp = (pawn.equipment != null && pawn.equipment.Primary != null) ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : null;
            var startCollectCorpse = StartCollectCorpseToil();
            var gotoCastPos        = GotoCastPosition(VictimInd, true).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse).FailOn(() => Find.TickManager.TicksGame > jobStartTick + MaxHuntTicks);

            yield return(gotoCastPos);

            //var moveIfCannotHit = Toils_Jump.JumpIfTargetNotHittable(VictimInd, gotoCastPos);
            var moveIfCannotHit = Toils_Jump.JumpIf(gotoCastPos, delegate
            {
                var verb         = pawn.CurJob.verbToUse;
                var optimalRange = HuntRangePerBodysize(Victim.RaceProps.baseBodySize, Victim.RaceProps.executionRange, verb.verbProps.range);
                if (pawn.Position.DistanceTo(Victim.Position) > optimalRange)
                {
                    return(true);
                }
                return(!verb.CanHitTarget(Victim));
            });

            yield return(moveIfCannotHit);

            yield return(Toils_Jump.JumpIfTargetDespawnedOrNull(VictimInd, startCollectCorpse));

            var startExecuteDowned = Toils_Goto.GotoThing(VictimInd, PathEndMode.Touch).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse);

            yield return(Toils_Jump.JumpIf(startExecuteDowned, () => Victim.Downed && Victim.RaceProps.executionRange <= 2));

            yield return(Toils_Jump.JumpIfTargetDowned(VictimInd, gotoCastPos));

            yield return(Toils_Combat.CastVerb(VictimInd, false).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse)
                         .FailOn(() =>
            {
                if (Find.TickManager.TicksGame <= jobStartTick + MaxHuntTicks)
                {
                    if (comp == null || comp.HasAndUsesAmmoOrMagazine)
                    {
                        return false;
                    }
                }
                return true;
            }));

            yield return(Toils_Jump.Jump(moveIfCannotHit));

            // Execute downed animal - adapted from JobDriver_Slaughter
            yield return(startExecuteDowned);

            yield return(Toils_General.WaitWith(VictimInd, 180, true).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse));

            yield return(new Toil
            {
                initAction = delegate
                {
                    ExecutionUtility.DoExecutionByCut(pawn, Victim);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });

            // Haul corpse to stockpile
            yield return(startCollectCorpse);

            yield return(Toils_Goto.GotoCell(VictimInd, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(VictimInd).FailOnSomeonePhysicallyInteracting(VictimInd));

            yield return(Toils_Haul.StartCarryThing(VictimInd));

            var carryToCell = Toils_Haul.CarryHauledThingToCell(StoreCellInd);

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(StoreCellInd, carryToCell, true));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOn(delegate
            {
                if (!job.ignoreDesignations)
                {
                    Pawn victim2 = Victim;
                    if (victim2 != null && !victim2.Dead && base.Map.designationManager.DesignationOn(victim2, DesignationDefOf.Hunt) == null)
                    {
                        return(true);
                    }
                }
                return(false);
            });
            Toil toil = new Toil();

            toil.initAction = delegate
            {
                jobStartTick = Find.TickManager.TicksGame;
            };
            yield return(toil);

            yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A));

            Toil startCollectCorpseLabel = Toils_General.Label();
            Toil slaughterLabel          = Toils_General.Label();
            Toil gotoCastPos             = Toils_Combat.GotoCastPosition(TargetIndex.A, TargetIndex.None, closeIfDowned: true, 0.95f).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000);

            yield return(gotoCastPos);

            Toil slaughterIfPossible = Toils_Jump.JumpIf(slaughterLabel, delegate
            {
                Pawn victim = Victim;
                if (victim.RaceProps.DeathActionWorker != null && victim.RaceProps.DeathActionWorker.DangerousInMelee)
                {
                    return(false);
                }
                return(victim.Downed ? true : false);
            });

            yield return(slaughterIfPossible);

            yield return(Toils_Jump.JumpIfTargetNotHittable(TargetIndex.A, gotoCastPos));

            yield return(Toils_Combat.CastVerb(TargetIndex.A, canHitNonTargetPawns: false).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000));

            yield return(Toils_Jump.JumpIfTargetDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel));

            yield return(Toils_Jump.Jump(slaughterIfPossible));

            yield return(slaughterLabel);

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

            yield return(Toils_General.WaitWith(TargetIndex.A, 180, useProgressBar: true).FailOnMobile(TargetIndex.A));

            yield return(Toils_General.Do(delegate
            {
                if (!Victim.Dead)
                {
                    ExecutionUtility.DoHuntingExecution(pawn, Victim);
                    pawn.records.Increment(RecordDefOf.AnimalsSlaughtered);
                    if (pawn.InMentalState)
                    {
                        pawn.MentalState.Notify_SlaughteredAnimal();
                    }
                }
            }));

            yield return(Toils_Jump.Jump(startCollectCorpseLabel));

            yield return(startCollectCorpseLabel);

            yield return(StartCollectCorpseToil());

            yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnSomeonePhysicallyInteracting(TargetIndex.A));

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

            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B);

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, storageMode: true));
        }
        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;
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            const float baseFishingDuration    = 1600f;
            const float catchSuccessRateOnPier = 0.90f;
            const float skillGainPerTick       = 0.15f;

            int fishingDuration = (int)baseFishingDuration;
            Building_FishingPier fishingPier = this.TargetThingA as Building_FishingPier;
            int thrownCornCount   = 0;
            int nextCornThrowTick = 0;

            this.FailOnBurningImmobile(fishingPierIndex);

            // Drawing.
            this.rotateToFace = TargetIndex.B;
            this.pawn.CurJob.SetTarget(TargetIndex.C, fishingPier.riverCell);
            TargetIndex riverCellIndex = TargetIndex.C;

            // Compute fishing duration.
            float fishingSkillLevel = 0f;

            fishingSkillLevel = this.pawn.skills.AverageOfRelevantSkillsFor(WorkTypeDefOf.Hunting);
            float fishingSkillDurationFactor = fishingSkillLevel / 20f;

            fishingDuration = (int)(baseFishingDuration * (1.5f - fishingSkillDurationFactor));

            yield return(Toils_Goto.GotoThing(fishingPierIndex, fishingPier.riverCell).FailOn(FishingForbiddenOrPierDestroyedOrNoFish));

            Toil attractfishesToil = new Toil()
            {
                tickAction = () =>
                {
                    if (fishingPier.allowUsingGrain == false)
                    {
                        this.ReadyForNextToil();
                        return;
                    }
                    if (Find.TickManager.TicksGame >= nextCornThrowTick)
                    {
                        nextCornThrowTick = Find.TickManager.TicksGame + 3 * GenTicks.TicksPerRealSecond;
                        // Look for corn in inventory.
                        Thing corn = null;
                        foreach (Thing thing in this.pawn.inventory.innerContainer)
                        {
                            if (thing.def == Util_FishIndustry.RawCornDef)
                            {
                                corn = thing;
                                break;
                            }
                        }
                        if ((corn == null) ||
                            (thrownCornCount >= grainCountToAttractFishes))
                        {
                            fishingDuration -= Mathf.CeilToInt((float)fishingDuration * 0.75f * ((float)thrownCornCount / (float)grainCountToAttractFishes));
                            this.ReadyForNextToil();
                            return;
                        }
                        // Throw corn grains.
                        thrownCornCount++;
                        this.pawn.inventory.innerContainer.Take(corn, 1);
                        for (int cornGrainIndex = 0; cornGrainIndex < 5; cornGrainIndex++)
                        {
                            if (!this.pawn.Position.ShouldSpawnMotesAt(this.pawn.Map) || this.pawn.Map.moteCounter.Saturated)
                            {
                                break;
                            }
                            float   speed          = Rand.Range(1.5f, 3f);
                            Vector3 targetPosition = this.pawn.Position.ToVector3Shifted() + new Vector3(0f, 0f, 2f).RotatedBy(fishingPier.Rotation.AsAngle) + Vector3Utility.RandomHorizontalOffset(1.5f);
                            targetPosition.y = this.pawn.DrawPos.y;
                            MoteThrown moteThrown = (MoteThrown)ThingMaker.MakeThing(ThingDefOf.Mote_Stone, null);
                            moteThrown.Scale         = 0.2f;
                            moteThrown.rotationRate  = (float)Rand.Range(-300, 300);
                            moteThrown.exactPosition = this.pawn.DrawPos;
                            moteThrown.SetVelocity((targetPosition - moteThrown.exactPosition).AngleFlat(), speed);
                            moteThrown.airTimeLeft = (float)Mathf.RoundToInt((moteThrown.exactPosition - targetPosition).MagnitudeHorizontal() / speed);
                            GenSpawn.Spawn(moteThrown, this.pawn.Position, this.pawn.Map);
                            MoteMaker.MakeWaterSplash(targetPosition, this.pawn.Map, 1.8f, 0.5f);
                        }
                    }
                },
                defaultDuration     = fishingDuration,
                defaultCompleteMode = ToilCompleteMode.Delay
            };

            yield return(attractfishesToil.FailOn(FishingForbiddenOrPierDestroyedOrNoFish));

            Toil fishToil = new Toil()
            {
                initAction = () =>
                {
                    ThingDef moteDef = null;
                    if (fishingPier.Rotation == Rot4.North)
                    {
                        moteDef = Util_FishIndustry.MoteFishingRodNorthDef;
                    }
                    else if (fishingPier.Rotation == Rot4.East)
                    {
                        moteDef = Util_FishIndustry.MoteFishingRodEastDef;
                    }
                    else if (fishingPier.Rotation == Rot4.South)
                    {
                        moteDef = Util_FishIndustry.MoteFishingRodSouthDef;
                    }
                    else
                    {
                        moteDef = Util_FishIndustry.MoteFishingRodWestDef;
                    }
                    this.fishingRodMote = (Mote)ThingMaker.MakeThing(moteDef, null);
                    this.fishingRodMote.exactPosition = fishingPier.fishingSpotCell.ToVector3Shifted();
                    this.fishingRodMote.Scale         = 1f;
                    GenSpawn.Spawn(this.fishingRodMote, fishingPier.fishingSpotCell, this.Map);
                },
                tickAction = () =>
                {
                    this.pawn.skills.Learn(SkillDefOf.Shooting, skillGainPerTick);

                    if (this.fishingRodMote != null)
                    {
                        this.fishingRodMote.Maintain();
                    }
                },
                defaultDuration     = fishingDuration,
                defaultCompleteMode = ToilCompleteMode.Delay
            };

            yield return(fishToil.WithProgressBarToilDelay(riverCellIndex).FailOn(FishingForbiddenOrPierDestroyedOrNoFish));

            Toil catchFishToil = new Toil()
            {
                initAction = () =>
                {
                    Thing fishingCatch = null;

                    bool catchIsSuccessful = (Rand.Value <= catchSuccessRateOnPier);
                    if (catchIsSuccessful == false)
                    {
                        MoteMaker.ThrowMetaIcon(this.pawn.Position, this.Map, ThingDefOf.Mote_IncapIcon);
                        this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                        return;
                    }

                    float catchSelectorValue = Rand.Value;

                    if (catchSelectorValue < 0.02)
                    {
                        float bonusCatchValue = Rand.Value;
                        if (bonusCatchValue < 0.01f)
                        {
                            // Really small chance to find a sunken treasure!!!
                            fishingCatch            = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position, this.Map);
                            fishingCatch.stackCount = Rand.RangeInclusive(58, 289);
                            Thing treasureSilver = GenSpawn.Spawn(ThingDefOf.Silver, fishingPier.middleCell, this.Map);
                            treasureSilver.stackCount = Rand.RangeInclusive(237, 2154);
                            Find.LetterStack.ReceiveLetter("FishIndustry.LetterLabelSunkenTreasure".Translate(), "FishIndustry.SunkenTreasure".Translate(this.pawn.Name.ToStringShort.CapitalizeFirst()),
                                                           LetterDefOf.PositiveEvent, this.pawn);
                        }
                        else if (bonusCatchValue < 0.02f)
                        {
                            // Really small chance to find a complete power armor set + sniper or charge rifle.
                            Thing powerArmor = GenSpawn.Spawn(ThingDef.Named("Apparel_PowerArmor"), this.pawn.Position, this.Map);
                            fishingCatch = powerArmor; // Used to carry the power armor.
                            Thing powerArmorHelmet = GenSpawn.Spawn(ThingDef.Named("Apparel_PowerArmorHelmet"), this.pawn.Position, this.Map);
                            Thing rifle            = null;
                            if (Rand.Value < 0.5f)
                            {
                                rifle = GenSpawn.Spawn(ThingDef.Named("Gun_ChargeRifle"), this.pawn.Position, this.Map);
                            }
                            else
                            {
                                rifle = GenSpawn.Spawn(ThingDef.Named("Gun_SniperRifle"), this.pawn.Position, this.Map);
                            }
                            CompQuality qualityComp = powerArmor.TryGetComp <CompQuality>();
                            if (qualityComp != null)
                            {
                                qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider);
                            }
                            qualityComp = powerArmorHelmet.TryGetComp <CompQuality>();
                            if (qualityComp != null)
                            {
                                qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider);
                            }
                            qualityComp = rifle.TryGetComp <CompQuality>();
                            if (qualityComp != null)
                            {
                                qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider);
                            }

                            Faction faction    = Find.FactionManager.FirstFactionOfDef(FactionDefOf.AncientsHostile);
                            Pawn    deadMarine = PawnGenerator.GeneratePawn(PawnKindDefOf.AncientSoldier, faction);
                            HealthUtility.DamageUntilDead(deadMarine);
                            Corpse       corpse  = deadMarine.ParentHolder as Corpse;
                            CompRottable rotComp = corpse.TryGetComp <CompRottable>();
                            if (rotComp != null)
                            {
                                rotComp.RotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated.
                            }
                            GenSpawn.Spawn(corpse, fishingPier.bankCell, this.Map);
                            string eventText = "FishIndustry.LetterDescDeadMarine".Translate(this.pawn.Name.ToStringShort.CapitalizeFirst());
                            Find.LetterStack.ReceiveLetter("FishIndustry.LetterLabelDeadMarine".Translate(), eventText, LetterDefOf.PositiveEvent, this.pawn);
                        }
                        else
                        {
                            // Find a small amount of gold.
                            fishingCatch            = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position, this.Map);
                            fishingCatch.stackCount = Rand.RangeInclusive(1, 7);
                        }
                    }
                    else if (catchSelectorValue < 0.04)
                    {
                        // Find oysters.
                        fishingCatch            = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position, this.Map);
                        fishingCatch.stackCount = Rand.RangeInclusive(2, 9);
                    }
                    else
                    {
                        // Catch a fish.
                        IntVec3 fishSpot        = fishingPier.aquaticCells.RandomElement();
                        bool    fishSpotIsOcean = (this.Map.terrainGrid.TerrainAt(fishSpot) == TerrainDefOf.WaterOceanShallow) ||
                                                  (this.Map.terrainGrid.TerrainAt(fishSpot) == TerrainDefOf.WaterOceanDeep);
                        bool fishSpotIsMarshy = (this.Map.terrainGrid.TerrainAt(fishSpot) == TerrainDef.Named("Marsh"));

                        PawnKindDef caugthFishDef = null;
                        if (fishSpotIsOcean)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInOcean
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else if (fishSpotIsMarshy)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInMarsh
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInRiver
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        Pawn caughtFish = PawnGenerator.GeneratePawn(caugthFishDef);
                        ExecutionUtility.DoExecutionByCut(this.pawn, caughtFish);
                        Corpse corpse = caughtFish.ParentHolder as Corpse;
                        GenSpawn.Spawn(corpse, this.pawn.Position, this.Map);
                        fishingCatch = corpse;
                        fishingCatch.SetForbidden(false);
                        if (caughtFish.BodySize >= 0.1f)
                        {
                            fishingPier.fishStock--;
                        }
                    }
                    IntVec3 storageCell;
                    if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, this.Map, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true))
                    {
                        this.pawn.Reserve(fishingCatch, this.job);
                        this.pawn.Reserve(storageCell, this.job);
                        this.pawn.CurJob.SetTarget(TargetIndex.B, storageCell);
                        this.pawn.CurJob.SetTarget(TargetIndex.A, fishingCatch);
                        this.pawn.CurJob.count    = 9999;
                        this.pawn.CurJob.haulMode = HaulMode.ToCellStorage;
                    }
                    else
                    {
                        this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
                    }
                }
            };

            yield return(catchFishToil);

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

            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B);

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Toil startJobToil = new Toil();

            startJobToil.initAction = delegate
            {
                jobStartTick = Find.TickManager.TicksGame;
            };
            yield return(startJobToil);

            yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A));

            Toil startCollectCorpseLabel = Toils_General.Label();
            Toil slaughterLabel          = Toils_General.Label();
            Toil meleeLabel = Toils_General.Label();

            Toil checkTargetToil = new Toil();

            checkTargetToil.initAction = delegate
            {
                targetCheckTick = Find.TickManager.TicksGame;

                //if (pawn.equipment.Primary == null || pawn.equipment.Primary.def.IsMeleeWeapon)
                //    pawn.jobs.curDriver.JumpToToil(meleeLabel);
            };
            yield return(checkTargetToil);

            //Toil gotoCastPos = Toils_Combat.GotoCastPosition(TargetIndex.A, true, 0.95f).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000);
            Toil gotoCastPos = Toils_Combat.GotoCastPosition(TargetIndex.A, true, 4.0f)
                               .JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel)
                               .JumpIf(() => Find.TickManager.TicksGame > targetCheckTick + targetCheckInterval, checkTargetToil);

            yield return(gotoCastPos);

            Toil selectAttack = new Toil();

            selectAttack.initAction = delegate
            {
                if (pawn.CanReachImmediate(TargetA, PathEndMode.Touch))
                {
                    pawn.jobs.curDriver.JumpToToil(meleeLabel);
                }
                else if (Victim.Downed)
                {
                    if (Victim.AnimalOrWildMan())
                    {
                        pawn.jobs.curDriver.JumpToToil(slaughterLabel);
                    }
                    else
                    {
                        pawn.jobs.curDriver.JumpToToil(meleeLabel);
                    }
                }
            };
            yield return(selectAttack);

            // Ranged attack
            yield return(Toils_Jump.JumpIfTargetNotHittable(TargetIndex.A, checkTargetToil));

            yield return(Toils_Combat.CastVerb(TargetIndex.A, canHitNonTargetPawns: false).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000));

            yield return(Toils_Jump.JumpIfTargetDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel));

            yield return(Toils_Jump.Jump(selectAttack));

            // Melee
            yield return(meleeLabel);

            yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIf(() => Find.TickManager.TicksGame > targetCheckTick + targetCheckInterval, checkTargetToil));

            //yield return Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.OnCell).JumpIf(() => Find.TickManager.TicksGame > targetCheckTick + targetCheckInterval, checkTargetToil);
            Toil meleeAttack = new Toil();

            meleeAttack.tickAction = delegate
            {
                if (Victim == null || !Victim.Spawned || Victim.IsForbidden(pawn) || !pawn.CanReachImmediate(TargetA, PathEndMode.Touch))
                {
                    pawn.jobs.curDriver.JumpToToil(checkTargetToil);
                }
                else if (Victim.Downed && Victim.AnimalOrWildMan())
                {
                    pawn.jobs.curDriver.JumpToToil(slaughterLabel);
                }

                pawn.pather.StopDead();
                pawn.meleeVerbs.TryMeleeAttack(Victim);
            };
            meleeAttack.activeSkill         = () => SkillDefOf.Melee;
            meleeAttack.defaultCompleteMode = ToilCompleteMode.Never;
            yield return(meleeAttack);

            yield return(Toils_Jump.JumpIfCannotTouch(TargetIndex.A, PathEndMode.Touch, checkTargetToil));

            // Slaughter target
            yield return(slaughterLabel);

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

            yield return(Toils_General.WaitWith(TargetIndex.A, 180, useProgressBar: true).FailOnMobile(TargetIndex.A));

            yield return(Toils_General.Do(delegate
            {
                if (!Victim.Dead)
                {
                    ExecutionUtility.DoExecutionByCut(pawn, Victim);
                    pawn.records.Increment(RecordDefOf.AnimalsSlaughtered);
                    if (pawn.InMentalState)
                    {
                        pawn.MentalState.Notify_SlaughteredAnimal();
                    }
                }
            }));

            yield return(Toils_Jump.Jump(startCollectCorpseLabel));

            yield return(startCollectCorpseLabel);

            //yield return Toils_Misc.ThrowColonistAttackingMote(TargetIndex.A);
            //yield return Toils_Combat.FollowAndMeleeAttack(TargetIndex.A, delegate
            //{
            //    Thing thing = job.GetTarget(TargetIndex.A).Thing;
            //    Pawn p;
            //    if (job.reactingToMeleeThreat && (p = thing as Pawn) != null && !p.Awake())
            //    {
            //        EndJobWith(JobCondition.InterruptForced);
            //    }
            //    else if (pawn.meleeVerbs.TryMeleeAttack(thing, job.verbToUse) && pawn.CurJob != null && pawn.jobs.curDriver == this)
            //    {
            //        numMeleeAttacksMade++;
            //        if (numMeleeAttacksMade >= job.maxNumMeleeAttacks)
            //        {
            //            EndJobWith(JobCondition.Succeeded);
            //        }
            //    }
            //}).FailOnDespawnedOrNull(TargetIndex.A);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            const float baseFishingDuration    = 2400f;
            const float skillGainPerTick       = 0.15f;
            const float catchSuccessRateInZone = 0.70f;

            int fishingDuration = (int)baseFishingDuration;

            // Compute fishing duration.
            float fishingSkillLevel = 0f;

            fishingSkillLevel = this.pawn.skills.AverageOfRelevantSkillsFor(WorkTypeDefOf.Hunting);
            float fishingSkillDurationFactor = fishingSkillLevel / 20f;

            fishingDuration = (int)(baseFishingDuration * (1.5f - fishingSkillDurationFactor));

            Toil faceWaterToil = new Toil()
            {
                initAction = () =>
                {
                    // Compute pawn rotation during fishing.
                    foreach (IntVec3 offset in GenAdj.CardinalDirections.InRandomOrder())
                    {
                        IntVec3      adjacentCell = this.TargetLocA + offset;
                        Zone_Fishing fishingZone  = adjacentCell.GetZone(this.Map) as Zone_Fishing;
                        if ((fishingZone != null) &&
                            fishingZone.fishingSpots.Contains(this.TargetLocA))
                        {
                            this.cardinalDir = offset;
                            this.pawn.CurJob.SetTarget(TargetIndex.B, adjacentCell);
                            this.rotateToFace = TargetIndex.B;
                            break;
                        }
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            yield return(faceWaterToil);

            yield return(Toils_Goto.GotoCell(this.TargetLocA, this.pathEndMode).FailOn(FishingForbiddenOrInvalidSpot));

            Toil fishToil = new Toil()
            {
                tickAction = () =>
                {
                    this.pawn.skills.Learn(SkillDefOf.Shooting, skillGainPerTick);

                    // Spawn mote or maintain it.
                    if (this.fishingRodMote.DestroyedOrNull())
                    {
                        IntVec3  motePosition = this.TargetB.Cell;
                        ThingDef moteDef      = null;
                        if (cardinalDir == IntVec3.North)
                        {
                            moteDef = Util_FishIndustry.MoteFishingRodNorthDef;
                        }
                        else if (cardinalDir == IntVec3.East)
                        {
                            moteDef = Util_FishIndustry.MoteFishingRodEastDef;
                        }
                        else if (cardinalDir == IntVec3.South)
                        {
                            moteDef = Util_FishIndustry.MoteFishingRodSouthDef;
                        }
                        else
                        {
                            moteDef = Util_FishIndustry.MoteFishingRodWestDef;
                        }
                        this.fishingRodMote = (Mote)ThingMaker.MakeThing(moteDef, null);
                        this.fishingRodMote.exactPosition = motePosition.ToVector3Shifted();
                        this.fishingRodMote.Scale         = 1f;
                        GenSpawn.Spawn(this.fishingRodMote, motePosition, this.Map);
                    }
                    else
                    {
                        this.fishingRodMote.Maintain();
                    }
                },
                defaultDuration     = fishingDuration,
                defaultCompleteMode = ToilCompleteMode.Delay
            };

            yield return(fishToil.WithProgressBarToilDelay(this.fishPositionIndex, true).FailOn(FishingForbiddenOrInvalidSpot));

            Toil catchFishToil = new Toil()
            {
                initAction = () =>
                {
                    Thing fishingCatch = null;

                    bool catchIsSuccessful = (Rand.Value <= catchSuccessRateInZone);
                    if (catchIsSuccessful == false)
                    {
                        MoteMaker.ThrowMetaIcon(this.pawn.Position, this.Map, ThingDefOf.Mote_IncapIcon);
                        this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                        return;
                    }

                    float catchSelectorValue = Rand.Value;

                    if ((catchSelectorValue < 0.02) &&
                        Util_FishIndustry.GetFishSpeciesList(this.Map.Biome).Contains(Util_FishIndustry.TailteethPawnKindDef as PawnKindDef_FishSpecies))
                    {
                        // Get hurt by a tailteeth.
                        this.pawn.TakeDamage(new DamageInfo(DamageDefOf.Bite, Rand.Range(5, 12)));
                        Messages.Message(this.pawn.Name.ToStringShort + "FishIndustry.FisherBitten".Translate(), this.pawn, MessageTypeDefOf.NegativeHealthEvent);
                        this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                        return;
                    }
                    else if (catchSelectorValue < 0.04)
                    {
                        // Find oysters.
                        fishingCatch            = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position, this.Map);
                        fishingCatch.stackCount = Rand.RangeInclusive(5, 27);
                    }
                    else
                    {
                        // Catch a fish.
                        bool fishSpotIsOcean = (this.Map.terrainGrid.TerrainAt(this.TargetLocA) == TerrainDefOf.WaterOceanShallow) ||
                                               (this.Map.terrainGrid.TerrainAt(this.TargetLocA) == TerrainDefOf.WaterOceanDeep);
                        bool fishSpotIsMarshy = (this.Map.terrainGrid.TerrainAt(this.TargetLocA) == TerrainDef.Named("Marsh"));

                        PawnKindDef caugthFishDef = null;
                        if (fishSpotIsOcean)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInOcean
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else if (fishSpotIsMarshy)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInMarsh
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome)
                                             where fishSpecies.livesInRiver
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        Pawn caughtFish = PawnGenerator.GeneratePawn(caugthFishDef);
                        ExecutionUtility.DoExecutionByCut(this.pawn, caughtFish);
                        Corpse corpse = caughtFish.ParentHolder as Corpse;
                        GenSpawn.Spawn(corpse, this.pawn.Position, this.Map);
                        fishingCatch = corpse;
                        fishingCatch.SetForbidden(false);
                        if (caughtFish.BodySize >= 0.1f)
                        {
                            Zone_Fishing fishingZone = this.TargetB.Cell.GetZone(this.Map) as Zone_Fishing;
                            if ((fishingZone != null) &&
                                fishingZone.fishingSpots.Contains(this.TargetLocA))
                            {
                                fishingZone.fishingSpots.Remove(this.TargetLocA);
                            }
                        }
                    }

                    IntVec3 storageCell;
                    if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, this.Map, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true))
                    {
                        this.pawn.Reserve(fishingCatch, this.job);
                        this.pawn.Reserve(storageCell, this.job);
                        this.pawn.CurJob.SetTarget(TargetIndex.B, storageCell);
                        this.pawn.CurJob.SetTarget(TargetIndex.A, fishingCatch);
                        this.pawn.CurJob.count    = 9999;
                        this.pawn.CurJob.haulMode = HaulMode.ToCellStorage;
                    }
                    else
                    {
                        this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
                    }
                }
            };

            yield return(catchFishToil);

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

            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B);

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true));
        }