Esempio n. 1
0
        private void DestroyTarget()
        {
            if (this.targetWillBeHit)
            {
                foreach (Thing thing in this.target.contents.containedThings)
                {
                    if (thing is Pawn)
                    {
                        // Spawn a dead copy of the pawn as the original one will be destroyed with the incoming drop pod.
                        Pawn pawn     = thing as Pawn;
                        Pawn pawnCopy = PawnGenerator.GeneratePawn(pawn.kindDef, pawn.Faction);
                        GenPlace.TryPlaceThing(pawnCopy, this.target.Position, ThingPlaceMode.Near);
                        if (pawnCopy.equipment.Primary != null)
                        {
                            pawnCopy.equipment.Primary.HitPoints = (int)(Rand.Range(0.05f, 0.30f) * pawnCopy.equipment.Primary.MaxHitPoints);
                        }
                        HealthUtility.GiveInjuriesToKill(pawnCopy);
                        // TODO: add tale. Destroyed drop pod.

                        /*TaleRecorder.RecordTale(TaleDef.Named("LandedInPod"), new object[]
                         * {
                         *  pawnCopy
                         * });*/
                        break;
                    }
                }
                for (int slagIndex = 0; slagIndex < 3; slagIndex++)
                {
                    GenPlace.TryPlaceThing(ThingMaker.MakeThing(ThingDefOf.ChunkSlagSteel), this.target.Position + new IntVec3(Rand.Range(-3, 3), 0, Rand.Range(-3, 3)), ThingPlaceMode.Near);
                }
                FireUtility.TryStartFireIn(this.target.Position + new IntVec3(Rand.Range(-3, 3), 0, Rand.Range(-3, 3)), 0.3f);
                this.target.Destroy(DestroyMode.Vanish);
            }
        }
 public static void KillAndRotPawn(Pawn pawn, float rotProgressInTicks)
 {
     HealthUtility.GiveInjuriesToKill(pawn);
     foreach (Thing thing in pawn.Position.GetThingList(pawn.MapHeld))
     {
         if (thing.def.defName.Contains("Corpse"))
         {
             CompRottable rotComp = thing.TryGetComp <CompRottable>();
             if (rotComp != null)
             {
                 rotComp.RotProgress = rotProgressInTicks;
             }
         }
     }
 }
        public void GenerateWarfield(int battleZoneAbs, int battleZoneOrd, OG_OutpostData outpostData)
        {
            // Get a random hostile faction.
            int        securityForcesCorpseNumber = Rand.Range(2, 4);
            int        hostilesCorpseNumber       = 0;
            FactionDef hostileFactionDef          = null;
            Faction    hostileFaction             = null;
            float      hostileFactionSelector     = Rand.Value;

            if (hostileFactionSelector < 0.25f)
            {
                hostileFactionDef    = FactionDefOf.Tribe;
                hostileFaction       = Find.FactionManager.FirstFactionOfDef(hostileFactionDef);
                hostilesCorpseNumber = Rand.Range(6, 8);
            }
            else if (hostileFactionSelector < 0.5f)
            {
                hostileFactionDef    = FactionDefOf.Pirate;
                hostileFaction       = Find.FactionManager.FirstFactionOfDef(hostileFactionDef);
                hostilesCorpseNumber = Rand.Range(3, 5);
            }
            else if (hostileFactionSelector < 0.75f)
            {
                hostileFactionDef    = FactionDefOf.SpacerHostile;
                hostileFaction       = Find.FactionManager.FirstFactionOfDef(hostileFactionDef);
                hostilesCorpseNumber = Rand.Range(3, 5);
            }
            else
            {
                hostileFactionDef    = FactionDefOf.Mechanoid;
                hostileFaction       = Find.FactionManager.FirstFactionOfDef(hostileFactionDef);
                hostilesCorpseNumber = Rand.Range(1, 3);
            }
            // Spawn corpses.
            IntVec3 zoneOrigin = Zone.GetZoneOrigin(outpostData.areaSouthWestOrigin, battleZoneAbs, battleZoneOrd);

            for (int corpseIndex = 0; corpseIndex < securityForcesCorpseNumber + hostilesCorpseNumber; corpseIndex++)
            {
                int     tries = 3; // Max 3 tries per corpse.
                bool    validPositionIsFound = false;
                IntVec3 corpsePosition       = new IntVec3();
                for (int tryIndex = 0; tryIndex < tries; tryIndex++)
                {
                    corpsePosition = zoneOrigin + new IntVec3(Rand.Range(1, Genstep_GenerateOutpost.zoneSideSize - 1), 0, Rand.Range(1, Genstep_GenerateOutpost.zoneSideSize - 1));
                    if (corpsePosition.GetEdifice() == null)
                    {
                        validPositionIsFound = true;
                        break;
                    }
                }
                if (validPositionIsFound == false)
                {
                    continue;
                }
                // Generate the corpse according to the faction.
                Pawn corpse = null;
                if (corpseIndex < securityForcesCorpseNumber)
                {
                    corpse = PawnGenerator.GeneratePawn(OG_Util.OutpostScoutDef, OG_Util.FactionOfMAndCo);
                }
                else
                {
                    float       pawnKindSelector = Rand.Value;
                    PawnKindDef corpseKindDef    = null;
                    if (hostileFactionDef == FactionDefOf.Tribe)
                    {
                        if (pawnKindSelector < 0.4f)
                        {
                            corpseKindDef = PawnKindDef.Named("TribalWarrior");
                        }
                        else if (pawnKindSelector < 0.8f)
                        {
                            corpseKindDef = PawnKindDef.Named("TribalArcher");
                        }
                        else
                        {
                            corpseKindDef = PawnKindDef.Named("TribalChief");
                        }
                    }
                    else if (hostileFactionDef == FactionDefOf.Pirate)
                    {
                        if (pawnKindSelector < 0.25f)
                        {
                            corpseKindDef = PawnKindDef.Named("Drifter");
                        }
                        else if (pawnKindSelector < 0.50f)
                        {
                            corpseKindDef = PawnKindDef.Named("Scavenger");
                        }
                        else if (pawnKindSelector < 0.75f)
                        {
                            corpseKindDef = PawnKindDef.Named("Thrasher");
                        }
                        else
                        {
                            corpseKindDef = PawnKindDef.Named("Pirate");
                        }
                    }
                    else if (hostileFactionDef == FactionDefOf.SpacerHostile)
                    {
                        if (pawnKindSelector < 0.25f)
                        {
                            corpseKindDef = PawnKindDef.Named("SpaceSoldier");
                        }
                        else if (pawnKindSelector < 0.50f)
                        {
                            corpseKindDef = PawnKindDef.Named("MercenaryGunner");
                        }
                        else if (pawnKindSelector < 0.75f)
                        {
                            corpseKindDef = PawnKindDef.Named("GrenadierDestructive");
                        }
                        else
                        {
                            corpseKindDef = PawnKindDef.Named("MercenaryElite");
                        }
                    }
                    else if (hostileFactionDef == FactionDefOf.Mechanoid)
                    {
                        if (pawnKindSelector < 0.6f)
                        {
                            corpseKindDef = PawnKindDef.Named("Scyther");
                        }
                        else
                        {
                            corpseKindDef = PawnKindDef.Named("Centipede");
                        }
                    }
                    corpse = PawnGenerator.GeneratePawn(corpseKindDef, hostileFaction);
                }
                GenSpawn.Spawn(corpse, corpsePosition);
                // Damage the weapon so the warfield effect is not too exploitable (otherwise, player can get good guns at game start).
                if (corpse.equipment.Primary != null)
                {
                    corpse.equipment.Primary.HitPoints = (int)(Rand.Range(0.05f, 0.30f) * corpse.equipment.Primary.MaxHitPoints);
                }
                // "Kill the corpse".
                HealthUtility.GiveInjuriesToKill(corpse);
                // Make it rotten if outpost is abandonned.
                if (this.outpostData.isInhabited == false)
                {
                    List <Thing> thingsList = corpsePosition.GetThingList();
                    foreach (Thing thing in thingsList)
                    {
                        if (thing.def.defName.Contains("Corpse"))
                        {
                            CompRottable rotComp = thing.TryGetComp <CompRottable>();
                            if (rotComp != null)
                            {
                                rotComp.rotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated.
                            }
                        }
                    }
                }
            }

            // Destroy some sandbags in the zone.
            List <Thing> sandbagsList = Find.ListerThings.ThingsOfDef(ThingDefOf.Sandbags);

            for (int sandbagIndex = sandbagsList.Count - 1; sandbagIndex >= 0; sandbagIndex--)
            {
                Thing sandbag = sandbagsList[sandbagIndex];
                if (sandbag.Position.InHorDistOf(this.Position, Genstep_GenerateOutpost.zoneSideSize / 2f) &&
                    (Rand.Value < 0.1f))
                {
                    // Manually spawn sandbag rubble and use Vanish instead of Kill to avoid spawning ugly metal remains.
                    GenSpawn.Spawn(ThingDef.Named("SandbagRubble"), sandbag.Position);
                    sandbag.Destroy(DestroyMode.Vanish);
                }
            }
        }
        private void AddPsionicShock(Pawn pawn)
        {
            System.Random rand = new System.Random();

            int  psychicSensitivity    = 0;
            bool?shouldGiveHeartAttack = null;
            bool?shouldSedate          = null;

            if (pawn.story?.traits != null && pawn.story.traits.HasTrait(TraitDef.Named("PsychicSensitivity")))
            {
                Trait psychicSensitivityTrait = pawn.story.traits.GetTrait(TraitDef.Named("PsychicSensitivity"));
                psychicSensitivity = psychicSensitivityTrait.Degree;
            }

            // If they're Psychically Deaf, do nothing:
            if (psychicSensitivity == -2)
            {
                return;
            }
            // If they're Psychically Dull, don't give them a heart attack.
            else if (psychicSensitivity == -1)
            {
                shouldGiveHeartAttack = false;
            }
            // If they're Psychically Sensitive, make sure they're passed out for a few hours.
            else if (psychicSensitivity == 1)
            {
                shouldSedate = true;
            }
            // If they're Psychically Hypersensitive, unfortunately, it will mean instant death :-(
            else if (psychicSensitivity >= 2)
            {
                Messages.Message(pawn.NameStringShort + " was psychically supersensitive and died because of the psionic blast.", MessageSound.SeriousAlert);
                HealthUtility.GiveInjuriesToKill(pawn);
            }

            Hediff shock = HediffMaker.MakeHediff(HediffDefOf.PsychicShock, pawn, null);

            pawn.health.AddHediff(shock, null, null);

            if (shouldGiveHeartAttack == null)
            {
                shouldGiveHeartAttack = rand.Next(1, 11) >= 3;
            }

            if (shouldGiveHeartAttack == true)
            {
                this.CauseHeartAttack(pawn);
            }

            if (shouldSedate == null)
            {
                int likelihood = rand.Next(1, 11);
                Log.Message(pawn.NameStringShort + " should sedate? " + likelihood);
                shouldSedate = likelihood >= 6;
            }

            if (shouldSedate == true)
            {
                this.CauseSedation(pawn);
            }

            DamageInfo psionicIntensity = new DamageInfo(DamageDefOf.Stun, 50);

            pawn.TakeDamage(psionicIntensity);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            QualityCategory      fishingEquipmentQuality = QualityCategory.Normal;
            float                catchSomethingThreshold = 0f;
            Building_FishingPier fishingPier             = this.TargetThingA as Building_FishingPier;
            Passion              passion = Passion.None;
            int         fishingDuration  = 1000;
            const float skillGainPerTick = 0.15f;
            float       skillGainFactor  = 0f;

            this.AddEndCondition(() =>
            {
                var targ = this.pawn.jobs.curJob.GetTarget(fishingPierIndex).Thing;
                if (targ is Building && !targ.Spawned)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });

            this.FailOnBurningImmobile(fishingPierIndex); // Bill giver or product burning in carry phase.

            yield return(Toils_Reserve.Reserve(fishingPierIndex));

            float statValue = this.pawn.GetStatValue(Util_FishIndustry.FishingSpeedDef, true);

            fishingDuration = (int)Math.Round((double)(800f / statValue));

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

            Toil verifyFisherHasFishingEquipmentToil = new Toil()
            {
                initAction = () =>
                {
                    if ((this.pawn.equipment.Primary != null) &&
                        (this.pawn.equipment.Primary.def == Util_FishIndustry.HarpoonDef))
                    {
                        this.fishingEquipment = FishingEquipment.Harpoon;
                        this.pawn.equipment.Primary.TryGetQuality(out fishingEquipmentQuality);
                    }
                    foreach (Apparel apparel in this.pawn.apparel.WornApparel)
                    {
                        if (apparel.def == Util_FishIndustry.FishingRodDef)
                        {
                            this.fishingEquipment = FishingEquipment.FishingRod;
                            apparel.TryGetQuality(out fishingEquipmentQuality);
                            break;
                        }
                    }
                    if (this.fishingEquipment == FishingEquipment.NoEquipment)
                    {
                        this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                    }
                }
            };

            yield return(verifyFisherHasFishingEquipmentToil);

            Toil fishToil = new Toil()
            {
                initAction = () =>
                {
                    ThingDef moteDef = null;
                    if (fishingEquipment == FishingEquipment.FishingRod)
                    {
                        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;
                        }
                    }
                    if (moteDef != null)
                    {
                        this.fishingRodMote = (Mote)ThingMaker.MakeThing(moteDef, null);
                        this.fishingRodMote.exactPosition = fishingPier.fishingSpotCell.ToVector3Shifted();
                        this.fishingRodMote.Scale         = 1f;
                        GenSpawn.Spawn(this.fishingRodMote, fishingPier.fishingSpotCell);
                    }
                    WorkTypeDef fishingWorkDef = DefDatabase <WorkTypeDef> .GetNamed("Fishing");

                    passion = this.pawn.skills.MaxPassionOfRelevantSkillsFor(fishingWorkDef);
                    if (passion == Passion.None)
                    {
                        skillGainFactor = 0.3f;
                    }
                    else if (passion == Passion.Minor)
                    {
                        skillGainFactor = 1f;
                    }
                    else
                    {
                        skillGainFactor = 1.5f;
                    }
                },
                tickAction = () =>
                {
                    if (fishingEquipment == FishingEquipment.Harpoon)
                    {
                        if (Find.TickManager.TicksGame % GenTicks.TickRareInterval == 0)
                        {
                            Bullet     thrownHarpoon = GenSpawn.Spawn(Util_FishIndustry.HarpoonDef.Verbs.First().projectileDef, this.pawn.Position) as Bullet;
                            TargetInfo targetCell    = new TargetInfo(fishingPier.fishingSpotCell + new IntVec3(Rand.RangeInclusive(-1, 1), 0, Rand.RangeInclusive(0, 2)).RotatedBy(fishingPier.Rotation));
                            thrownHarpoon.Launch(this.pawn, targetCell);
                        }
                    }
                    this.pawn.Drawer.rotator.FaceCell(fishingPier.fishingSpotCell);

                    if (passion == Passion.Minor)
                    {
                        this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMinor, JoyKindDefOf.Work);
                    }
                    else if (passion == Passion.Major)
                    {
                        this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMajor, JoyKindDefOf.Work);
                    }
                    SkillDef fishingSkillDef = DefDatabase <SkillDef> .GetNamed("Fishing");

                    this.pawn.skills.Learn(fishingSkillDef, skillGainPerTick * skillGainFactor);

                    if (this.ticksLeftThisToil == 1)
                    {
                        if (this.fishingRodMote != null)
                        {
                            Log.Message("destroy mote");
                            this.fishingRodMote.Destroy();
                        }
                    }
                },
                defaultDuration     = fishingDuration,
                defaultCompleteMode = ToilCompleteMode.Delay
            };

            yield return(fishToil.WithProgressBarToilDelay(fishingPierIndex));

            yield return(verifyFisherHasFishingEquipmentToil); // Could be dropped during fishToil.

            Toil computeChanceToCatchToil = new Toil()
            {
                initAction = () =>
                {
                    float       fishingSkillLevel = 0f;
                    WorkTypeDef fishingWorkDef    = DefDatabase <WorkTypeDef> .GetNamed("Fishing");

                    fishingSkillLevel = this.pawn.skills.AverageOfRelevantSkillsFor(fishingWorkDef);
                    float fishingEquipmentQualityFactor = (float)fishingEquipmentQuality / (float)QualityCategory.Legendary;
                    float fishingSkillFactor            = fishingSkillLevel / 20f;
                    float snowFactor             = 1 - Find.SnowGrid.GetDepth(fishingPier.fishingSpotCell);
                    float fishingEquipmentOffset = 0f;
                    switch (this.fishingEquipment)
                    {
                    case FishingEquipment.Harpoon:
                        fishingEquipmentOffset = 0.2f;
                        break;

                    case FishingEquipment.FishingRod:
                        fishingEquipmentOffset = 0.5f;
                        break;
                    }
                    catchSomethingThreshold = ((fishingEquipmentOffset * fishingEquipmentQualityFactor) + 0.4f * fishingSkillFactor) * (0.25f + 0.75f * snowFactor);
                    // Reframe min and max chance (min 5%, max 75 % chance of success).
                    catchSomethingThreshold = catchSomethingThreshold * 0.75f;
                    catchSomethingThreshold = Math.Max(catchSomethingThreshold, 0.05f);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            yield return(computeChanceToCatchToil);

            Toil catchFishToil = new Toil()
            {
                initAction = () =>
                {
                    Job   curJob       = this.pawn.jobs.curJob;
                    Thing fishingCatch = null;

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

                    float catchSelectorValue = Rand.Value;
                    if (catchSelectorValue > 0.04f)
                    {
                        // Catch a fish.
                        bool fishSpotIsMarshy = (Find.TerrainGrid.TerrainAt(fishingPier.fishingSpotCell) == TerrainDef.Named("Marsh"));
                        bool isDaytime        = (SkyManager.CurSkyGlow >= 0.4f);

                        ThingDef caugthFishDef = Util_FishIndustry.TailteethDef;
                        if (fishSpotIsMarshy && isDaytime)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList()
                                             where fishSpecies.livesInMarsh
                                             where fishSpecies.catchableDuringDay
                                             select fishSpecies).RandomElementByWeight((ThingDef_FishSpecies def) => def.commonality);
                        }
                        else if (fishSpotIsMarshy && !isDaytime)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList()
                                             where fishSpecies.livesInMarsh
                                             where fishSpecies.catchableDuringNight
                                             select fishSpecies).RandomElementByWeight((ThingDef_FishSpecies def) => def.commonality);
                        }
                        else if (!fishSpotIsMarshy && isDaytime)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList()
                                             where fishSpecies.livesInSea
                                             where fishSpecies.catchableDuringDay
                                             select fishSpecies).RandomElementByWeight((ThingDef_FishSpecies def) => def.commonality);
                        }
                        else
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList()
                                             where fishSpecies.livesInSea
                                             where fishSpecies.catchableDuringNight
                                             select fishSpecies).RandomElementByWeight((ThingDef_FishSpecies def) => def.commonality);
                        }

                        /*TerrainDef fishSpotType = Find.TerrainGrid.TerrainAt(fishingPier.fishingSpotCell);
                         * List<ThingDef> fishSpeciesList = null;
                         * ThingDef_FishSpecies.AquaticEnvironment aquaticEnvironment;
                         * ThingDef_FishSpecies.LivingTime livingTime;
                         * float fishSpeciesTotalCommonality = 0f;
                         * float fishSpeciesCommonalitySum = 0f;
                         *
                         * // Aquatic environment.
                         * if (fishSpotType == TerrainDef.Named("Marsh"))
                         * {
                         *  aquaticEnvironment = ThingDef_FishSpecies.AquaticEnvironment.Marsh;
                         * }
                         * else
                         * {
                         *  aquaticEnvironment = ThingDef_FishSpecies.AquaticEnvironment.Sea;
                         * }
                         * // Day time.
                         * if (SkyManager.CurSkyGlow >= 0.4f)
                         * {
                         *  livingTime = ThingDef_FishSpecies.LivingTime.Day;
                         * }
                         * else
                         * {
                         *  livingTime = ThingDef_FishSpecies.LivingTime.Night;
                         * }
                         *
                         * fishSpeciesList = Util_FishIndustry.GetFishSpeciesList(aquaticEnvironment, livingTime);
                         * fishSpeciesTotalCommonality = Util_FishIndustry.GetFishSpeciesTotalCommonality(aquaticEnvironment, livingTime);
                         *
                         * float randomSelector = Rand.Range(0f, fishSpeciesTotalCommonality);
                         * ThingDef selectedFishSpecies = null;
                         * for (int fishSpeciesIndex = 0; fishSpeciesIndex < fishSpeciesList.Count; fishSpeciesIndex++)
                         * {
                         *  ThingDef_FishSpecies currentFishSpecies = fishSpeciesList[fishSpeciesIndex] as ThingDef_FishSpecies;
                         *  fishSpeciesCommonalitySum += currentFishSpecies.commonality;
                         *
                         *  if (randomSelector <= fishSpeciesCommonalitySum)
                         *  {
                         *      selectedFishSpecies = currentFishSpecies;
                         *      break;
                         *  }
                         * }*/
                        fishingCatch            = GenSpawn.Spawn(caugthFishDef, this.pawn.Position);
                        fishingCatch.stackCount = (caugthFishDef as ThingDef_FishSpecies).catchQuantity;
                        fishingPier.fishStock--;
                    }
                    else if (catchSelectorValue > 0.02)
                    {
                        fishingCatch            = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position);
                        fishingCatch.stackCount = Rand.RangeInclusive(5, 27);
                    }
                    else
                    {
                        float bonusCatchValue = Rand.Value;
                        if (bonusCatchValue < 0.01f)
                        {
                            // Really small chance to find a sunken treasure!!!
                            fishingCatch            = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position);
                            fishingCatch.stackCount = Rand.RangeInclusive(58, 289);
                            Thing treasureSilver = GenSpawn.Spawn(ThingDefOf.Silver, fishingPier.middleCell);
                            treasureSilver.stackCount = Rand.RangeInclusive(237, 2154);
                            string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has found a sunken treasure while fishing! What a good catch!\n";
                            Find.LetterStack.ReceiveLetter("Sunken treasure!", eventText, LetterType.Good, this.pawn.Position);
                        }
                        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);
                            fishingCatch = powerArmor; // Used to carry the power armor.
                            Thing powerArmorHelmet = GenSpawn.Spawn(ThingDef.Named("Apparel_PowerArmorHelmet"), this.pawn.Position);
                            Thing rifle            = null;
                            if (Rand.Value < 0.5f)
                            {
                                rifle = GenSpawn.Spawn(ThingDef.Named("Gun_ChargeRifle"), this.pawn.Position);
                            }
                            else
                            {
                                rifle = GenSpawn.Spawn(ThingDef.Named("Gun_SniperRifle"), this.pawn.Position);
                            }
                            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.SpacerHostile);
                            Pawn    deadMarine = PawnGenerator.GeneratePawn(PawnKindDefOf.SpaceSoldier, faction);
                            GenSpawn.Spawn(deadMarine, fishingPier.bankCell);
                            HealthUtility.GiveInjuriesToKill(deadMarine);
                            List <Thing> thingsList = deadMarine.Position.GetThingList();
                            foreach (Thing thing in thingsList)
                            {
                                if (thing.def.defName.Contains("Corpse"))
                                {
                                    CompRottable rotComp = thing.TryGetComp <CompRottable>();
                                    if (rotComp != null)
                                    {
                                        rotComp.RotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated.
                                    }
                                }
                            }
                            string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has cought a dead body while fishing!\n\n'This is really disgusting but look at his gear! This guy was probably a Mining & Co. security member. I wonder what happend to him...'\n";
                            Find.LetterStack.ReceiveLetter("Dead marine", eventText, LetterType.Good, this.pawn.Position);
                        }
                        else
                        {
                            // Find a small amount of gold.
                            fishingCatch            = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position);
                            fishingCatch.stackCount = Rand.RangeInclusive(1, 7);
                        }
                        // TODO: add chance to get hurt by a tailteeth (missing finger or even hand!).
                    }
                    IntVec3 storageCell;
                    if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true))
                    {
                        this.pawn.carrier.TryStartCarry(fishingCatch);
                        curJob.targetB       = storageCell;
                        curJob.targetC       = fishingCatch;
                        curJob.maxNumToCarry = 99999;
                    }
                    else
                    {
                        this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
                    }
                }
            };

            yield return(catchFishToil);

            // Reserve the product and storage cell.
            yield return(Toils_Reserve.Reserve(TargetIndex.B));

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

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

            yield return(carryToCell);

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

            yield return(Toils_Reserve.Release(fishingPierIndex));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            const float baseFishingDuration = 2000f;

            int   fishingDuration            = (int)baseFishingDuration;
            float catchSomethingThreshold    = 0f;
            Building_FishingPier fishingPier = this.TargetThingA as Building_FishingPier;
            Passion     passion          = Passion.None;
            const float skillGainPerTick = 0.15f;
            float       skillGainFactor  = 0f;

            this.AddEndCondition(() =>
            {
                var targ = this.pawn.jobs.curJob.GetTarget(fishingPierIndex).Thing;
                if (targ is Building && !targ.Spawned)
                {
                    return(JobCondition.Incompletable);
                }
                return(JobCondition.Ongoing);
            });

            this.FailOnBurningImmobile(fishingPierIndex); // Bill giver or product burning in carry phase.

            this.rotateToFace = TargetIndex.B;

            yield return(Toils_Reserve.Reserve(fishingPierIndex));

            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).FailOnDespawnedOrNull(fishingPierIndex));

            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);
                    WorkTypeDef fishingWorkDef = WorkTypeDefOf.Hunting;
                    passion = this.pawn.skills.MaxPassionOfRelevantSkillsFor(fishingWorkDef);
                    if (passion == Passion.None)
                    {
                        skillGainFactor = 0.3f;
                    }
                    else if (passion == Passion.Minor)
                    {
                        skillGainFactor = 1f;
                    }
                    else
                    {
                        skillGainFactor = 1.5f;
                    }
                },
                tickAction = () =>
                {
                    if (passion == Passion.Minor)
                    {
                        this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMinor, JoyKindDefOf.Work);
                    }
                    else if (passion == Passion.Major)
                    {
                        this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMajor, JoyKindDefOf.Work);
                    }
                    this.pawn.skills.Learn(SkillDefOf.Shooting, skillGainPerTick * skillGainFactor);

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

            yield return(fishToil.WithProgressBarToilDelay(fishingPierIndex));

            Toil computeChanceToCatchToil = new Toil()
            {
                initAction = () =>
                {
                    catchSomethingThreshold = fishingSkillLevel / 20f;
                    // Reframe min and max chance (min 5%, max 75 % chance of success).
                    Mathf.Clamp(catchSomethingThreshold, 0.05f, 0.75f);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            yield return(computeChanceToCatchToil);

            Toil catchFishToil = new Toil()
            {
                initAction = () =>
                {
                    Job   curJob       = this.pawn.jobs.curJob;
                    Thing fishingCatch = null;

                    // 90% chance to successfully catch something.
                    bool catchIsSuccessful = (Rand.Value >= 0.1f);
                    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.04f)
                    {
                        // Catch a fish.
                        bool fishSpotIsMarshy = (this.Map.terrainGrid.TerrainAt(fishingPier.fishingSpotCell) == TerrainDef.Named("Marsh"));
                        bool isDaytime        = (this.Map.skyManager.CurSkyGlow >= 0.4f);

                        PawnKindDef caugthFishDef = null;
                        if (fishSpotIsMarshy && isDaytime)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList()
                                             where fishSpecies.livesInMarsh
                                             where fishSpecies.catchableDuringDay
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else if (fishSpotIsMarshy && !isDaytime)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList()
                                             where fishSpecies.livesInMarsh
                                             where fishSpecies.catchableDuringNight
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else if (!fishSpotIsMarshy && isDaytime)
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList()
                                             where fishSpecies.livesInSea
                                             where fishSpecies.catchableDuringDay
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        else
                        {
                            caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList()
                                             where fishSpecies.livesInSea
                                             where fishSpecies.catchableDuringNight
                                             select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality);
                        }
                        Pawn caughtFish = PawnGenerator.GeneratePawn(caugthFishDef);
                        GenSpawn.Spawn(caughtFish, this.pawn.Position, this.Map);
                        HealthUtility.GiveInjuriesToKill(caughtFish);
                        foreach (Thing thing in this.pawn.Position.GetThingList(this.Map))
                        {
                            Corpse fishCorpse = thing as Corpse;
                            if (fishCorpse != null)
                            {
                                fishingCatch = fishCorpse;
                            }
                        }
                        if (caughtFish.BodySize >= 0.1f)
                        {
                            fishingPier.fishStock--;
                            fishingPier.UpdateMaxFishStock();
                        }
                    }
                    else if (catchSelectorValue > 0.02)
                    {
                        fishingCatch            = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position, this.Map);
                        fishingCatch.stackCount = Rand.RangeInclusive(5, 27);
                    }
                    else
                    {
                        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);
                            string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has found a sunken treasure while fishing! What a good catch!\n";
                            Find.LetterStack.ReceiveLetter("Sunken treasure!", eventText, LetterType.Good, 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.SpacerHostile);
                            Pawn    deadMarine = PawnGenerator.GeneratePawn(PawnKindDefOf.SpaceSoldier, faction);
                            GenSpawn.Spawn(deadMarine, fishingPier.bankCell, this.Map);
                            HealthUtility.GiveInjuriesToKill(deadMarine);
                            List <Thing> thingsList = deadMarine.Position.GetThingList(this.Map);
                            foreach (Thing thing in thingsList)
                            {
                                if (thing.def.defName.Contains("Corpse"))
                                {
                                    CompRottable rotComp = thing.TryGetComp <CompRottable>();
                                    if (rotComp != null)
                                    {
                                        rotComp.RotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated.
                                    }
                                }
                            }
                            string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has cought a dead body while fishing!\n\n'This is really disgusting but look at his gear! This guy was probably a MiningCo. security member. I wonder what happend to him...'\n";
                            Find.LetterStack.ReceiveLetter("Dead marine", eventText, LetterType.Good, 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);
                        }
                        // TODO: add chance to get hurt by a tailteeth (missing finger or even hand!).
                    }
                    IntVec3 storageCell;
                    if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, this.Map, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true))
                    {
                        this.pawn.carryTracker.TryStartCarry(fishingCatch);
                        curJob.targetB = storageCell;
                        curJob.targetC = fishingCatch;
                        curJob.count   = 99999;
                    }
                    else
                    {
                        this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
                    }
                }
            };

            yield return(catchFishToil);

            // Reserve the product and storage cell.
            yield return(Toils_Reserve.Reserve(TargetIndex.B));

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

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

            yield return(carryToCell);

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

            yield return(Toils_Reserve.Release(fishingPierIndex));
        }
        public override bool TryExecute(IncidentParms parms)
        {
            Map     map = (Map)parms.target;
            IntVec3 spawnSpot;

            if (!CellFinder.TryFindRandomEdgeCellWith(c => map.reachability.CanReachColony(c), map, out spawnSpot))
            {
                return(false);
            }

            #region CHANGED

            Func <Pawn, bool> selector = other => other.RaceProps.Humanlike && other.Faction != null && other.Faction.HostileTo(Faction.OfPlayer) && HasGroupMakers(other.Faction);

            Pawn refugee = GenericUtility.GetAnyRelatedWorldPawn(selector, 100);
            if (refugee == null)
            {
                // Just ANYONE
                Find.WorldPawns.AllPawnsAlive.Where(selector).TryRandomElement(out refugee);
            }
            if (refugee == null)
            {
                return(false);
            }

            refugee.relations.everSeenByPlayer = true;
            Faction enemyFac = refugee.Faction;

            string text = "RefugeeChasedInitial".Translate(new object[]
            {
                refugee.Name.ToStringFull,
                refugee.GetTitle().ToLower(),
                enemyFac.def.pawnsPlural, enemyFac.Name,
                refugee.ageTracker.AgeBiologicalYears
            });

            text = text.AdjustedFor(refugee);
            PawnRelationUtility.TryAppendRelationsWithColonistsInfo(ref text, refugee);
            DiaNode   diaNode   = new DiaNode(text);
            DiaOption diaOption = new DiaOption("RefugeeChasedInitial_Accept".Translate());
            diaOption.action = delegate
            {
                if (refugee == enemyFac.leader)
                {
                    enemyFac.GenerateNewLeader();
                }

                Find.WorldPawns.RemovePawn(refugee);
                var canDrop = enemyFac.def.techLevel >= TechLevel.Spacer;

                if (canDrop)
                {
                    spawnSpot = DropCellFinder.TradeDropSpot(map);
                    TradeUtility.SpawnDropPod(spawnSpot, map, refugee);
                }
                else
                {
                    GenSpawn.Spawn(refugee, spawnSpot, map);
                }

                refugee.SetFaction(Faction.OfPlayer);
                Find.CameraDriver.JumpTo(spawnSpot);
                IncidentParms incidentParms = StorytellerUtility.DefaultParmsNow(Find.Storyteller.def, IncidentCategory.ThreatBig, map);
                incidentParms.forced          = true;
                incidentParms.faction         = enemyFac;
                incidentParms.raidStrategy    = RaidStrategyDefOf.ImmediateAttack;
                incidentParms.raidArrivalMode = canDrop ? PawnsArriveMode.CenterDrop : PawnsArriveMode.EdgeWalkIn;
                incidentParms.spawnCenter     = spawnSpot;
                incidentParms.points         *= RaidPointsFactor;
                QueuedIncident qi = new QueuedIncident(new FiringIncident(IncidentDefOf.RaidEnemy, null, incidentParms), Find.TickManager.TicksGame + RaidDelay.RandomInRange);
                Find.Storyteller.incidentQueue.Add(qi);
            };
            diaOption.resolveTree = true;
            diaNode.options.Add(diaOption);
            string text2 = "RefugeeChasedRejected".Translate(new object[]
            {
                refugee.NameStringShort
            });
            DiaNode   diaNode2   = new DiaNode(text2);
            DiaOption diaOption2 = new DiaOption("OK".Translate());
            diaOption2.resolveTree = true;
            diaNode2.options.Add(diaOption2);
            DiaOption diaOption3 = new DiaOption("RefugeeChasedInitial_Reject".Translate());
            diaOption3.action = delegate
            {
                HealthUtility.GiveInjuriesToKill(refugee);
                //Log.Message(refugee.Name + " dead? " + refugee.Dead);
                //Find.WorldPawns.PassToWorld(refugee,PawnDiscardDecideMode.Discard);
            };
            #endregion
            diaOption3.link = diaNode2;
            diaNode.options.Add(diaOption3);
            Find.WindowStack.Add(new Dialog_NodeTree(diaNode, true, true));
            return(true);
        }