예제 #1
0
        // ===================== Main Work Function =====================
        /// <summary>
        /// Periodically resplenishes the fish stock if possible.
        /// </summary>
        public override void TickRare()
        {
            base.TickRare();

            // Update zone properties.
            UpdateCells();
            Util_Zone_Fishing.UpdateZoneProperties(this.Map, this.aquaticCells, ref this.oceanCellsCount, ref this.riverCellsCount, ref this.marshCellsCount,
                                                   ref this.isAffectedByBiome, ref this.isAffectedByToxicFallout, ref this.isAffectedByBadTemperature, ref this.maxFishStock);
            this.cachedSpeciesInZone = Util_Zone_Fishing.GetSpeciesInZoneText(this.Map.Biome, this.oceanCellsCount, this.riverCellsCount, this.marshCellsCount);

            // Udpdate fish stock.
            if ((this.fishStock < this.maxFishStock) &&
                viableCellsCount > 0)
            {
                float fishSpawnRateFactor = 0f;
                Util_Zone_Fishing.ComputeFishSpawnRateFactor(this.Map, this.oceanCellsCount, this.riverCellsCount, this.marshCellsCount,
                                                             this.isAffectedByToxicFallout, this.isAffectedByBadTemperature, out fishSpawnRateFactor);
                cachedFishSpawnMtb = baseFishSpawnMtbPier * fishSpawnRateFactor;
                int missingFishesCount = this.maxFishStock - this.fishStock;
                for (int missingFishIndex = 0; missingFishIndex < missingFishesCount; missingFishIndex++)
                {
                    bool fishShouldBeSpawned = Rand.MTBEventOccurs(cachedFishSpawnMtb, 1, MapComponent_FishingZone.updatePeriodInTicks);
                    if (fishShouldBeSpawned)
                    {
                        this.fishStock++;
                    }
                }
            }
            else if (this.fishStock > this.maxFishStock)
            {
                int surplusFishesCount = this.fishStock - this.maxFishStock;
                this.fishStock -= surplusFishesCount;
            }
        }
예제 #2
0
        public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
        {
            if ((t is Building_FishingPier) == false)
            {
                return(false);
            }
            Building_FishingPier fishingPier = t as Building_FishingPier;

            if (fishingPier.IsBurning() ||
                (fishingPier.allowFishing == false))
            {
                return(false);
            }
            if (Util_Zone_Fishing.IsAquaticTerrain(fishingPier.Map, fishingPier.fishingSpotCell) == false)
            {
                return(false);
            }
            if (pawn.CanReserveAndReach(fishingPier, this.PathEndMode, Danger.Some) == false)
            {
                return(false);
            }
            if (fishingPier.fishStock <= 0)
            {
                return(false);
            }
            return(true);
        }
예제 #3
0
        // ===================== Other Functions =====================
        /// <summary>
        /// Remove cells and fishing spots that are no more valid.
        /// </summary>
        public void UpdateCellsAndFishingSpots()
        {
            // Remove cells that are no more valid (case of moisture pump near marsh).
            List <IntVec3> cellsToRemove = new List <IntVec3>();

            foreach (IntVec3 cell in this.Cells)
            {
                if ((Util_Zone_Fishing.IsAquaticTerrain(this.Map, cell) == false) ||
                    (cell.Walkable(this.Map) == false))
                {
                    cellsToRemove.Add(cell);
                }
            }
            foreach (IntVec3 cell in cellsToRemove)
            {
                this.RemoveCell(cell);
            }

            // Remove fishing spots that are no more valid (case of destroyed bridge).
            cellsToRemove.Clear();
            foreach (IntVec3 cell in this.fishingSpots)
            {
                if (IsNearFishingZone(cell) == false)
                {
                    cellsToRemove.Add(cell);
                }
            }
            foreach (IntVec3 cell in cellsToRemove)
            {
                this.fishingSpots.Remove(cell);
            }
        }
예제 #4
0
        // ===================== Other functions =====================
        public void UpdateZone()
        {
            // Check current zone cells are valid. Remove invalid ones (terrain may have changed with moisture pump or mods).
            UpdateCellsAndFishingSpots();

            // Update zone properties.
            Util_Zone_Fishing.UpdateZoneProperties(this.Map, this.Cells, ref this.oceanCellsCount, ref this.riverCellsCount, ref this.marshCellsCount,
                                                   ref this.isAffectedByBiome, ref this.isAffectedByToxicFallout, ref this.isAffectedByBadTemperature, ref this.maxFishStock);
            this.cachedSpeciesInZone = Util_Zone_Fishing.GetSpeciesInZoneText(this.Map.Biome, this.oceanCellsCount, this.riverCellsCount, this.marshCellsCount);

            // Udpdate fish stock.
            if ((this.fishingSpots.Count < this.maxFishStock) &&
                this.viableCellsCount > 0)
            {
                float fishSpawnRateFactor = 0f;
                Util_Zone_Fishing.ComputeFishSpawnRateFactor(this.Map, this.oceanCellsCount, this.riverCellsCount, this.marshCellsCount,
                                                             this.isAffectedByToxicFallout, this.isAffectedByBadTemperature, out fishSpawnRateFactor);
                cachedFishSpawnMtb = baseFishSpawnMtbZone * fishSpawnRateFactor;

                // Check if fishes should be spawned.
                int missingFishesCount = this.maxFishStock - this.fishingSpots.Count;
                int fishesToSpawnCount = 0;
                for (int missingFishIndex = 0; missingFishIndex < missingFishesCount; missingFishIndex++)
                {
                    bool fishShouldBeSpawned = Rand.MTBEventOccurs(cachedFishSpawnMtb, 1, MapComponent_FishingZone.updatePeriodInTicks);
                    if (fishShouldBeSpawned)
                    {
                        fishesToSpawnCount++;
                    }
                }

                if (fishesToSpawnCount > 0)
                {
                    // Update bank and bridge cells.
                    List <IntVec3> bankCells   = new List <IntVec3>();
                    List <IntVec3> bridgeCells = new List <IntVec3>();
                    GetFreeBankAndBridgeCells(missingFishesCount, ref bankCells, ref bridgeCells);
                    // Actually try to spawn fishes.
                    for (int newFishIndex = 0; newFishIndex < fishesToSpawnCount; newFishIndex++)
                    {
                        if ((bankCells.Count == 0) &&
                            (bridgeCells.Count == 0))
                        {
                            break;
                        }
                        TrySpawnNewFish(ref bankCells, ref bridgeCells);
                    }
                }
            }
            else if (this.fishingSpots.Count > maxFishStock)
            {
                int surplusFishesCount = this.fishingSpots.Count - maxFishStock;
                for (int surplusFishIndex = 0; surplusFishIndex < surplusFishesCount; surplusFishIndex++)
                {
                    IntVec3 position = fishingSpots.RandomElement();
                    this.fishingSpots.Remove(position);
                }
            }
        }
예제 #5
0
        // ===================== Inspection pannel functions =====================
        /// <summary>
        /// Get the string displayed in the inspection panel.
        /// </summary>
        public override string GetInspectString()
        {
            StringBuilder stringBuilder = new StringBuilder();

            if (Util_FishIndustry.GetFishSpeciesList(this.Map.Biome).NullOrEmpty())
            {
                stringBuilder.Append("FishIndustry.FishingPier_InvalidBiome".Translate());
                return(stringBuilder.ToString());
            }

            if (this.maxFishStock < 0)
            {
                // Update after a savegame loading for example.
                UpdateAquaticCellsAround();
                Util_Zone_Fishing.UpdateZoneProperties(this.Map, this.Cells, ref this.oceanCellsCount, ref this.riverCellsCount, ref this.marshCellsCount,
                                                       ref this.isAffectedByBiome, ref this.isAffectedByToxicFallout, ref this.isAffectedByBadTemperature, ref this.maxFishStock);
            }
            // Fish stock.
            stringBuilder.Append("FishIndustry.FishStock".Translate(this.fishesPosition.Count));
            // Status.
            stringBuilder.AppendLine();
            if (this.viableCellsCount < Util_Zone_Fishing.minCellsToSpawnFish)
            {
                stringBuilder.Append("FishIndustry.NotViableNow".Translate());
            }
            else
            {
                stringBuilder.Append("FishIndustry.SpeciesInZone".Translate() + Util_Zone_Fishing.GetSpeciesInZoneText(this.Map, this.oceanCellsCount, this.riverCellsCount, this.marshCellsCount));
            }
            // Affections.
            if (this.Cells.Count < Util_Zone_Fishing.minCellsToSpawnFish)
            {
                stringBuilder.AppendLine();
                stringBuilder.Append("FishIndustry.TooSmallZone".Translate());
            }
            if (this.isAffectedByBiome ||
                this.isAffectedByToxicFallout ||
                this.isAffectedByBadTemperature)
            {
                stringBuilder.AppendLine();
                stringBuilder.Append("FishIndustry.AffectedBy".Translate());
                StringBuilder effects = new StringBuilder();
                if (this.isAffectedByBiome)
                {
                    effects.Append("FishIndustry.AffectedByBiome".Translate());
                }
                if (this.isAffectedByToxicFallout)
                {
                    effects.AppendWithSeparator("FishIndustry.AffectedByToxicFallout".Translate(), "FishIndustry.AffectedBySeparator".Translate());
                }
                if (this.isAffectedByBadTemperature)
                {
                    effects.AppendWithSeparator("FishIndustry.AffectedByBadTemperature".Translate(), "FishIndustry.AffectedBySeparator".Translate());
                }
                stringBuilder.Append(effects);
            }
            return(stringBuilder.ToString());
        }
예제 #6
0
 /// <summary>
 /// Check if a cell is a bank cell.
 /// </summary>
 public bool IsBankCell(IntVec3 cell)
 {
     if (cell.Standable(this.Map) &&
         (Util_Zone_Fishing.IsAquaticTerrain(this.Map, cell) == false))
     {
         return(true);
     }
     return(false);
 }
예제 #7
0
 // ===================== Other Functions =====================
 /// <summary>
 /// Update valid aquatic cells around the fishing pier.
 /// </summary>
 public void UpdateCells()
 {
     this.aquaticCells.Clear();
     foreach (IntVec3 cell in GenRadial.RadialCellsAround(this.fishingSpotCell, aquaticAreaRadius, false))
     {
         // Same room cannot be checked for deep water.
         if (cell.InBounds(this.Map) == false)
         {
             continue;
         }
         if (Util_Zone_Fishing.IsAquaticTerrain(this.Map, cell))
         {
             this.aquaticCells.Add(cell);
         }
     }
 }
 public override AcceptanceReport CanDesignateCell(IntVec3 c)
 {
     if (!base.CanDesignateCell(c).Accepted)
     {
         return(false);
     }
     if (Util_PlaceWorker.IsNearFishingPier(this.Map, c, Util_PlaceWorker.minDistanceBetweenTwoFishingSpots))
     {
         return(false);
     }
     if (Util_Zone_Fishing.IsAquaticTerrain(this.Map, c) &&
         c.Walkable(this.Map))
     {
         return(true);
     }
     return(false);
 }
예제 #9
0
        // ===================== Other Functions =====================
        public void UpdateAquaticCellsAround()
        {
            List <IntVec3> cellsToRemove = new List <IntVec3>();

            foreach (IntVec3 cell in this.Cells)
            {
                if ((Util_Zone_Fishing.IsAquaticTerrain(this.Map, cell) == false) ||
                    (cell.Walkable(this.Map) == false))
                {
                    cellsToRemove.Add(cell);
                }
            }
            foreach (IntVec3 cell in cellsToRemove)
            {
                this.RemoveCell(cell);
            }
        }
예제 #10
0
        // ===================== Other functions =====================
        public void UpdateZone()
        {
            // Check current zone cells are valid. Remove invalid ones (terrain may have changed with moisture pump or mods).
            UpdateAquaticCellsAround();
            // Update zone properties.
            Util_Zone_Fishing.UpdateZoneProperties(this.Map, this.Cells, ref this.oceanCellsCount, ref this.riverCellsCount, ref this.marshCellsCount,
                                                   ref this.isAffectedByBiome, ref this.isAffectedByToxicFallout, ref this.isAffectedByBadTemperature, ref this.maxFishStock);

            // Udpdate fish stock.
            if ((this.fishesPosition.Count < this.maxFishStock) &&
                viableCellsCount > 0)
            {
                float fishSpawnRateFactor = 1f;
                Util_Zone_Fishing.UpdateFishSpawnRateFactor(this.Map, this.oceanCellsCount, this.riverCellsCount, this.marshCellsCount,
                                                            this.isAffectedByToxicFallout, this.isAffectedByBadTemperature, ref fishSpawnRateFactor);
                float fishSpawnMtb       = baseFishSpawnMtbZone * fishSpawnRateFactor;
                int   missingFishesCount = this.maxFishStock - this.fishesPosition.Count;
                for (int missingFishIndex = 0; missingFishIndex < missingFishesCount; missingFishIndex++)
                {
                    bool fishShouldBeSpawned = Rand.MTBEventOccurs(fishSpawnMtb, 1, MapComponent_FishingZone.updatePeriodInTicks);
                    if (fishShouldBeSpawned)
                    {
                        // Try to spawn a new fish.
                        for (int tryIndex = 0; tryIndex < 5; tryIndex++)
                        {
                            IntVec3 spawnCell = this.Cells.RandomElement();
                            if (this.fishesPosition.Contains(spawnCell) == false)
                            {
                                this.fishesPosition.Add(spawnCell);
                                break;
                            }
                        }
                    }
                }
            }
            else if (this.fishesPosition.Count > maxFishStock)
            {
                int surplusFishesCount = this.fishesPosition.Count - maxFishStock;
                for (int surplusFishIndex = 0; surplusFishIndex < surplusFishesCount; surplusFishIndex++)
                {
                    IntVec3 fishPos = fishesPosition.RandomElement();
                    this.fishesPosition.Remove(fishPos);
                }
            }
        }
예제 #11
0
        public static int GetAquaticCellsInRadius(Map map, IntVec3 position, float radius)
        {
            int aquaticCellsNumber = 0;

            if (radius <= 0)
            {
                return(0);
            }
            foreach (IntVec3 cell in GenRadial.RadialCellsAround(position, radius, true))
            {
                if (cell.InBounds(map) == false)
                {
                    continue;
                }
                if (Util_Zone_Fishing.IsAquaticTerrain(map, cell))
                {
                    aquaticCellsNumber++;
                }
            }
            return(aquaticCellsNumber);
        }
예제 #12
0
        // ===================== Inspection pannel functions =====================
        /// <summary>
        /// Get the inspection string.
        /// </summary>
        ///
        public override string GetInspectString()
        {
            StringBuilder stringBuilder = new StringBuilder();

            if (Util_FishIndustry.GetFishSpeciesList(this.Map.Biome).NullOrEmpty())
            {
                stringBuilder.Append("FishIndustry.FishingPier_InvalidBiome".Translate());
                return(stringBuilder.ToString());
            }

            if (this.maxFishStock < 0)
            {
                // Update after a savegame loading for example.
                UpdateCells();
                Util_Zone_Fishing.UpdateZoneProperties(this.Map, this.aquaticCells, ref this.oceanCellsCount, ref this.riverCellsCount, ref this.marshCellsCount,
                                                       ref this.isAffectedByBiome, ref this.isAffectedByToxicFallout, ref this.isAffectedByBadTemperature, ref this.maxFishStock);
                this.cachedSpeciesInZone = Util_Zone_Fishing.GetSpeciesInZoneText(this.Map.Biome, this.oceanCellsCount, this.riverCellsCount, this.marshCellsCount);
            }
            // Fish stock.
            stringBuilder.Append("FishIndustry.FishStock".Translate(this.fishStock));
            if (Prefs.DevMode)
            {
                stringBuilder.Append("/" + this.maxFishStock);
            }
            // Status.
            stringBuilder.AppendLine();
            if (this.viableCellsCount < Util_Zone_Fishing.minCellsToSpawnFish)
            {
                stringBuilder.Append("FishIndustry.NotEnoughViableSpace".Translate());
            }
            else
            {
                stringBuilder.Append("FishIndustry.SpeciesInZone".Translate() + this.cachedSpeciesInZone);
            }
            // Affections.
            if (this.isAffectedByBiome ||
                this.isAffectedByToxicFallout ||
                this.isAffectedByBadTemperature)
            {
                stringBuilder.AppendLine();
                stringBuilder.Append("FishIndustry.AffectedBy".Translate());
                StringBuilder effects = new StringBuilder();
                if (this.isAffectedByBiome)
                {
                    effects.AppendWithComma("FishIndustry.AffectedByBiome".Translate());
                }
                if (this.isAffectedByToxicFallout)
                {
                    effects.AppendWithComma("FishIndustry.AffectedByToxicFallout".Translate());
                }
                if (this.isAffectedByBadTemperature)
                {
                    effects.AppendWithComma("FishIndustry.AffectedByBadTemperature".Translate());
                }
                stringBuilder.Append(effects);
            }
            // Debug.
            if (Prefs.DevMode)
            {
                stringBuilder.AppendLine();
                stringBuilder.Append("Spawn mean time: " + GenDate.ToStringTicksToPeriod((int)cachedFishSpawnMtb));
            }
            return(stringBuilder.ToString());
        }
예제 #13
0
        /// <summary>
        /// Check if a new fishing pier can be built at this location.
        /// - the fishing pier bank cell must be on a bank.
        /// - the rest of the fishing pier and the fishing spot must be on water.
        /// - must not be too near another fishing pier.
        /// </summary>
        public override AcceptanceReport AllowsPlacing(BuildableDef checkingDef, IntVec3 loc, Rot4 rot, Map map, Thing thingToIgnore = null, Thing thing = null)
        {
            // Remove old fish stock respawn rate text mote.
            if (lastMotePosition.IsValid &&
                (loc != lastMotePosition))
            {
                RemoveLastRespawnRateMote(map);
            }

            // Check this biome contains some fishes.
            if (Util_FishIndustry.GetFishSpeciesList(map.Biome).NullOrEmpty())
            {
                return(new AcceptanceReport("FishIndustry.FishingPier_InvalidBiome".Translate()));
            }

            // Check if another fishing pier is not too close.
            if (Util_PlaceWorker.IsNearFishingPier(map, loc, Util_PlaceWorker.minDistanceBetweenTwoFishingSpots))
            {
                return(new AcceptanceReport("FishIndustry.TooCloseFishingPier".Translate()));
            }

            // Check if a fishing zone is not too close.
            if (Util_PlaceWorker.IsNearFishingZone(map, loc, Util_PlaceWorker.minDistanceBetweenTwoFishingSpots))
            {
                return(new AcceptanceReport("FishIndustry.TooCloseFishingZone".Translate()));
            }

            // Check fishing pier is on water.
            if ((Util_Zone_Fishing.IsAquaticTerrain(map, loc + new IntVec3(0, 0, -1).RotatedBy(rot)) == false) ||
                (Util_Zone_Fishing.IsAquaticTerrain(map, loc + new IntVec3(0, 0, 0).RotatedBy(rot)) == false) ||
                (Util_Zone_Fishing.IsAquaticTerrain(map, loc + new IntVec3(0, 0, 1).RotatedBy(rot)) == false))
            {
                return(new AcceptanceReport("FishIndustry.FishingPier_PierMustBeOnWater".Translate()));
            }

            // Check fishing zone is on water.
            for (int xOffset = -1; xOffset <= 1; xOffset++)
            {
                for (int yOffset = 2; yOffset <= 4; yOffset++)
                {
                    if (Util_Zone_Fishing.IsAquaticTerrain(map, loc + new IntVec3(xOffset, 0, yOffset).RotatedBy(rot)) == false)
                    {
                        return(new AcceptanceReport("FishIndustry.FishingPier_ZoneMustBeOnWater".Translate()));
                    }
                }
            }

            // Display fish stock respawn rate.
            if ((lastMotePosition.IsValid == false) ||
                (Find.TickManager.Paused &&
                 (DateTime.Now.Second != lastMoteUpdateSecond)) ||
                ((Find.TickManager.Paused == false) &&
                 (Find.TickManager.TicksGame >= lastMoteUpdateTick + GenTicks.TicksPerRealSecond)))
            {
                lastMoteUpdateSecond = DateTime.Now.Second;
                lastMoteUpdateTick   = Find.TickManager.TicksGame;
                RemoveLastRespawnRateMote(map);
                DisplayMaxFishStockMoteAt(map, loc, rot);
            }

            return(true);
        }
예제 #14
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            const float baseFishingDuration    = 2400f;
            const float skillGainPerTick       = 0.15f;
            const float catchSuccessRateInZone = 0.70f;

            int     fishingDuration = (int)baseFishingDuration;
            Passion passion         = Passion.None;

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

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

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

            // Compute pawn rotation.
            if (cardinalDir == IntVec3.Invalid)
            {
                cardinalDir = GenAdj.CardinalDirections.RandomElement();
                foreach (IntVec3 direction in GenAdj.CardinalDirections.InRandomOrder())
                {
                    if (Util_Zone_Fishing.IsAquaticTerrain(this.Map, this.TargetLocA + direction))
                    {
                        cardinalDir = direction;
                        break;
                    }
                }
                this.pawn.CurJob.SetTarget(TargetIndex.B, this.TargetLocA + cardinalDir);
                this.rotateToFace = TargetIndex.B;
            }

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

            Toil fishToil = new Toil()
            {
                initAction = () =>
                {
                },
                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);

                    // Spawn mote or maintain it.
                    if (this.fishingRodMote.DestroyedOrNull())
                    {
                        IntVec3  motePosition = this.TargetLocA + cardinalDir;
                        ThingDef moteDef      = null;
                        if (cardinalDir == new IntVec3(0, 0, 1))
                        {
                            moteDef = Util_FishIndustry.MoteFishingRodNorthDef;
                        }
                        else if (cardinalDir == new IntVec3(1, 0, 0))
                        {
                            moteDef = Util_FishIndustry.MoteFishingRodEastDef;
                        }
                        else if (cardinalDir == new IntVec3(0, 0, -1))
                        {
                            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.fishingSpotIndex).FailOn(FishingForbiddenOrNoFishAtTargetLocA));;

            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.NameStringShort + "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.Map.zoneManager.ZoneAt(this.TargetLocA) as Zone_Fishing;
                            if ((fishingZone != null) &&
                                fishingZone.fishesPosition.Contains(this.TargetLocA))
                            {
                                fishingZone.fishesPosition.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));
        }