// ===================== 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; } }
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); }
// ===================== 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); } }
// ===================== 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); } } }
// ===================== 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()); }
/// <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); }
// ===================== 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); }
// ===================== 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); } }
// ===================== 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); } } }
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); }
// ===================== 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()); }
/// <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); }
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)); }