public override Job JobOnCell(Pawn pawn, IntVec3 c) { Job job = new Job(ZenDefOf.ZEN_PlantsHarvestSecondary); Map map = pawn.Map; Room room = c.GetRoom(map, RegionType.Set_Passable); float num = 0f; for (int i = 0; i < 40; i++) { IntVec3 c2 = c + GenRadial.RadialPattern[i]; if (c.GetRoom(map, RegionType.Set_Passable) == room) { if (HasJobOnCell(pawn, c2)) { Plant plant = c2.GetPlant(map); num += 250; if (num > 2400f) { break; } job.AddQueuedTarget(TargetIndex.A, plant); } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 3) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
public static void MeditationTick_PostFix(JobDriver_Meditate __instance) { var pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>(); if (ModsConfig.RoyaltyActive && DefDatabase <MeditationFocusDef> .GetNamed("Morbid").CanPawnUse(pawn)) { int num = GenRadial.NumCellsInRadius(MeditationUtility.FocusObjectSearchRadius); for (int i = 0; i < num; i++) { IntVec3 c = pawn.Position + GenRadial.RadialPattern[i]; if (c.InBounds(pawn.Map)) { Plant plant = c.GetPlant(pawn.Map); if (plant != null && plant.def == ThingDef.Named("Cults_PlantTreeNightmare")) { CompSpawnSubplant compSpawnSubplant = plant.TryGetComp <CompSpawnSubplant>(); if (compSpawnSubplant != null) { compSpawnSubplant.AddProgress(JobDriver_Meditate.AnimaTreeSubplantProgressPerTick, false); } } } } } }
static bool Prefix(WorkGiver_GrowerHarvest __instance, Pawn pawn, IntVec3 c, ref bool __result) { Plant plant = c.GetPlant(pawn.Map); // If this plant has a secondary resource and is in an orchard zone, don't chop it down unless it's designated if ((plant is PlantWithSecondary) && pawn.Map.zoneManager.ZoneAt(c) is Zone_Orchard) { if (pawn.Map.designationManager.DesignationAt(c, DesignationDefOf.CutPlant) == null) { __result = false; } } else { __result = ( plant != null && !plant.IsForbidden(pawn) && plant.def.plant.Harvestable && plant.LifeStage == PlantLifeStage.Mature && pawn.CanReserve(plant, 1, -1, null, false) ); } return(__result); }
private bool CanSpawnAt(IntVec3 c, Map map) { bool result; if (!c.Standable(map) || c.Fogged(map) || map.fertilityGrid.FertilityAt(c) < ThingDefOf.Plant_Ambrosia.plant.fertilityMin || !c.GetRoom(map, RegionType.Set_Passable).PsychologicallyOutdoors || c.GetEdifice(map) != null || !GenPlant.GrowthSeasonNow(c, map, false)) { result = false; } else { Plant plant = c.GetPlant(map); if (plant != null && plant.def.plant.growDays > 10f) { result = false; } else { List <Thing> thingList = c.GetThingList(map); for (int i = 0; i < thingList.Count; i++) { if (thingList[i].def == ThingDefOf.Plant_Ambrosia) { return(false); } } result = true; } } return(result); }
public override Job JobOnCell(Pawn pawn, IntVec3 c, bool forced = false) { Job job = new Job(JobDefOf.Harvest); Map map = pawn.Map; Room room = c.GetRoom(map, RegionType.Set_Passable); float num = 0f; for (int i = 0; i < 40; i++) { IntVec3 intVec = c + GenRadial.RadialPattern[i]; if (intVec.GetRoom(map, RegionType.Set_Passable) == room) { if (this.HasJobOnCell(pawn, intVec, false)) { Plant plant = intVec.GetPlant(map); if (!(intVec != c) || plant.def == WorkGiver_Grower.CalculateWantedPlantDef(intVec, map)) { num += plant.def.plant.harvestWork; if (intVec != c && num > 2400f) { break; } job.AddQueuedTarget(TargetIndex.A, plant); } } } } if (job.targetQueueA != null && job.targetQueueA.Count >= 3) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
private void HarmPlant() { if (this.PlantHarmRange < 0.0001f) { return; } float angle = Rand.Range(0f, 360f); float num = Rand.Range(0f, this.PlantHarmRange); num = Mathf.Sqrt(num / this.PlantHarmRange) * this.PlantHarmRange; Quaternion rotation = Quaternion.AngleAxis(angle, Vector3.up); Vector3 point = Vector3.forward * num; Vector3 v = rotation * point; IntVec3 b = IntVec3.FromVector3(v); IntVec3 c = base.Position + b; if (c.InBounds(base.Map)) { Plant plant = c.GetPlant(base.Map); if (plant != null) { if (Rand.Value < 0.2f) { plant.Destroy(DestroyMode.Kill); } else { plant.MakeLeafless(); } } } this.ticksToPlantHarm = this.PlantHarmInterval; }
public override bool HasJobOnCell(Pawn pawn, IntVec3 c, bool forced = false) { Plant plant = c.GetPlant(pawn.Map); if (plant == null) { return(false); } if (plant.IsForbidden(pawn)) { return(false); } if (!plant.HarvestableNow || plant.LifeStage != PlantLifeStage.Mature) { return(false); } if (!plant.CanYieldNow()) { return(false); } if (!pawn.CanReserve(plant, 1, -1, null, forced)) { return(false); } return(true); }
public override Job JobOnCell(Pawn pawn, IntVec3 c) { Job job = new Job(JobDefOf.Harvest); Map map = pawn.Map; Room room = c.GetRoom(map, RegionType.Set_Passable); float num = 0f; for (int i = 0; i < 40; i++) { IntVec3 c2 = c + GenRadial.RadialPattern[i]; if (c.GetRoom(map, RegionType.Set_Passable) == room && this.HasJobOnCell(pawn, c2)) { Plant plant = c2.GetPlant(map); num += plant.def.plant.harvestWork; if (!(num > 2400.0)) { job.AddQueuedTarget(TargetIndex.A, plant); continue; } break; } } if (job.targetQueueA != null && job.targetQueueA.Count >= 3) { job.targetQueueA.SortBy((LocalTargetInfo targ) => targ.Cell.DistanceToSquared(pawn.Position)); } return(job); }
// Token: 0x0600295A RID: 10586 RVA: 0x00139AB0 File Offset: 0x00137EB0 private void HarmRandomPlantInRadius(float radius) { IntVec3 c = this.Position + (Rand.InsideUnitCircleVec3 * radius).ToIntVec3(); if (!c.InBounds(this.Map)) { return; } Plant plant = c.GetPlant(this.Map); bool flag = c.GetThingList(this.Map).Any(x => x.def == XenomorphDefOf.RRY_Plant_Neomorph_Fungus_Hidden || x.def == XenomorphDefOf.RRY_Plant_Neomorph_Fungus); if (plant != null && !flag) { // Log.Message(string.Format("this.CanSee(plant): {0}", this.CanSee(plant))); if (Rand.Value < this.LeaflessPlantKillChance && this.CanSee(plant)) { Thing thing2; if (!PlayerKnowledgeDatabase.IsComplete(XenomorphConceptDefOf.RRY_Concept_Fungus)) { thing2 = ThingMaker.MakeThing(XenomorphDefOf.RRY_Plant_Neomorph_Fungus_Hidden); } else { thing2 = ThingMaker.MakeThing(XenomorphDefOf.RRY_Plant_Neomorph_Fungus); } IntVec3 vec3 = plant.Position; GenSpawn.Spawn(thing2, vec3, plant.Map, WipeMode.Vanish); // plant.Destroy(); // GenSpawn.Spawn(ThingMaker.MakeThing(this.def), vec3, this.Map); } } }
private void HarmRandomPlantInRadius(float radius) { IntVec3 c = this.parent.Position + (Rand.PointOnDisc * radius).ToIntVec3(); if (!c.InBounds(this.parent.Map)) { return; } Plant plant = c.GetPlant(this.parent.Map); if (plant != null) { if (plant.LeaflessNow) { if (Rand.Value < 0.2f) { plant.Kill(null, null); } } else { plant.MakeLeafless(Plant.LeaflessCause.Poison); } } }
public static bool CanSpawnAt(IntVec3 c, Map map, int minProximityToArtificialStructures = 40, int minProximityToCenter = 0, int minFertileUnroofedCells = 22, int maxFertileUnroofedCellRadius = 10) { if (!c.Standable(map) || c.Fogged(map) || !c.GetRoom(map).PsychologicallyOutdoors) { return(false); } Plant plant = c.GetPlant(map); if (plant != null && plant.def.plant.growDays > 10f) { return(false); } List <Thing> thingList = c.GetThingList(map); for (int i = 0; i < thingList.Count; i++) { if (thingList[i].def == ThingDefOf.Plant_TreeAnima) { return(false); } } if (minProximityToCenter > 0 && map.Center.InHorDistOf(c, minProximityToCenter)) { return(false); } if (!map.reachability.CanReachFactionBase(c, map.ParentFaction)) { return(false); } TerrainDef terrain = c.GetTerrain(map); if (terrain.avoidWander || terrain.fertility <= 0f) { return(false); } if (c.Roofed(map)) { return(false); } if (minProximityToArtificialStructures != 0 && GenRadial.RadialDistinctThingsAround(c, map, minProximityToArtificialStructures, useCenter: false).Any(MeditationUtility.CountsAsArtificialBuilding)) { return(false); } int num = GenRadial.NumCellsInRadius(maxFertileUnroofedCellRadius); int num2 = 0; for (int j = 0; j < num; j++) { IntVec3 c2 = c + GenRadial.RadialPattern[j]; if (!c2.Roofed(map) && c2.GetTerrain(map).fertility > 0f) { num2++; } if (num2 >= minFertileUnroofedCells) { return(true); } } return(false); }
protected override bool TryExecuteWorker(IncidentParms parms) { Map map = (Map)parms.target; IntVec3 root = default(IntVec3); if (!this.TryFindRootCell(map, out root)) { return(false); } Thing thing = null; int randomInRange = IncidentWorker_AmbrosiaSprout.CountRange.RandomInRange; int num = 0; IntVec3 intVec = default(IntVec3); while (num < randomInRange && CellFinder.TryRandomClosewalkCellNear(root, map, 6, out intVec, (Predicate <IntVec3>)((IntVec3 x) => this.CanSpawnAt(x, map)))) { Plant plant = intVec.GetPlant(map); if (plant != null) { plant.Destroy(DestroyMode.Vanish); } Thing thing2 = GenSpawn.Spawn(ThingDefOf.PlantAmbrosia, intVec, map); if (thing == null) { thing = thing2; } num++; } if (thing == null) { return(false); } base.SendStandardLetter(thing); return(true); }
public Job JobOnCell(Pawn pawn, IntVec3 c) { if (wantedPlantDef == null) { DetermineWantedPlantDef(c); if (wantedPlantDef == null) { return(null); } } Plant plant = c.GetPlant(); if (plant == null) { return(null); } if (plant.def != wantedPlantDef) { return(null); } if (!plant.def.plant.Harvestable || plant.LifeStage != PlantLifeStage.Mature) { return(null); } if (!pawn.CanReserve(plant, 1)) { return(null); } return(new Job(JobDefOf.Harvest, plant)); }
public override bool HasJobOnCell(Pawn pawn, IntVec3 c) { Plant plant = c.GetPlant(pawn.Map); if (plant == null) { return(false); } if (plant.IsForbidden(pawn)) { return(false); } if (plant.HarvestableNow && plant.LifeStage == PlantLifeStage.Mature) { if (plant.YieldNow() <= 0) { return(false); } if (!pawn.CanReserve(plant, 1, -1, null, false)) { return(false); } return(true); } return(false); }
public override AcceptanceReport CanDesignateCell(IntVec3 c) { AcceptanceReport result; if (!c.InBounds(base.Map) || c.Fogged(base.Map)) { result = false; } else { Plant plant = c.GetPlant(base.Map); if (plant == null) { result = "MessageMustDesignatePlants".Translate(); } else { AcceptanceReport acceptanceReport = this.CanDesignateThing(plant); if (!acceptanceReport.Accepted) { result = acceptanceReport; } else { result = true; } } } return(result); }
public override bool HasJobOnCell(Pawn pawn, IntVec3 c, bool forced = false) { Plant plant = c.GetPlant(pawn.Map); if (plant == null) { return(false); } if (plant.IsForbidden(pawn)) { return(false); } if (!plant.HarvestableNow || plant.LifeStage != PlantLifeStage.Mature) { return(false); } if (!plant.CanYieldNow()) { return(false); } LocalTargetInfo target = plant; bool ignoreOtherReservations = forced; if (!pawn.CanReserve(target, 1, -1, null, ignoreOtherReservations)) { return(false); } return(true); }
private void HarmRandomPlantInRadius(float radius) { IntVec3 c = this.parent.Position + (Rand.InsideUnitCircleVec3 * radius).ToIntVec3(); if (!c.InBounds(this.parent.Map)) { return; } Plant plant = c.GetPlant(this.parent.Map); if (plant != null) { if (plant.LeaflessNow) { if (Rand.Value < this.PropsPlantHarmRadius.leaflessPlantKillChance) { plant.Kill(null, null); return; } } else { plant.MakeLeafless(Plant.LeaflessCause.Poison); } } }
static bool IsCellOpenForSowingPlantOfType(IntVec3 cell, Map map, ThingDef plantDef) { var playerSetPlantForCell = GetPlayerSetPlantForCell(cell, map); if (playerSetPlantForCell == null || !playerSetPlantForCell.CanAcceptSowNow()) { return(false); } var plantDefToGrow = playerSetPlantForCell.GetPlantDefToGrow(); if (plantDefToGrow == null || plantDefToGrow != plantDef) { return(false); } if (cell.GetPlant(map) != null) { return(false); } if (PlantUtility.AdjacentSowBlocker(plantDefToGrow, cell, map) != null) { return(false); } foreach (Thing current in map.thingGrid.ThingsListAt(cell)) { if (current.def.BlockPlanting) { return(false); } } return(plantDefToGrow.CanEverPlantAt(cell, map) && PlantUtility.GrowthSeasonNow(cell, map)); }
// Token: 0x06000005 RID: 5 RVA: 0x00002178 File Offset: 0x00000378 private bool CanSpawnAt(IntVec3 c, Map map) { Log.Message("Trying to spawn on " + c.GetTerrain(map).ToString(), false); if (!c.Standable(map) || (c.GetTerrain(map) != TerrainDefOf.Sand && !c.GetTerrain(map).ToString().Contains("SoftSand"))) { Log.Message("Failed spawn on " + c.GetTerrain(map).ToString(), false); return(false); } Plant plant = c.GetPlant(map); if (plant != null && plant.def.plant.growDays > 10f) { return(false); } List <Thing> thingList = c.GetThingList(map); for (int i = 0; i < thingList.Count; i++) { if (thingList[i].def == ThingDefOf.Plant_Ambrosia) { return(false); } } return(true); }
public override bool HasJobOnCell(Pawn pawn, IntVec3 c, bool forced = false) { Plant plant = c.GetPlant(pawn.Map); bool result; if (plant == null) { result = false; } else if (plant.IsForbidden(pawn)) { result = false; } else if (!plant.HarvestableNow || plant.LifeStage != PlantLifeStage.Mature) { result = false; } else if (!plant.CanYieldNow()) { result = false; } else { LocalTargetInfo target = plant; result = pawn.CanReserve(target, 1, -1, null, forced); } return(result); }
public static bool TrySpawnAt(IntVec3 cell, Map map, float growth, out Thing plant) { cell.GetPlant(map)?.Destroy(); plant = GenSpawn.Spawn(ThingDefOf.Plant_TreeAnima, cell, map); ((Plant)plant).Growth = growth; return(plant != null); }
public static bool IsCellOpenForSowingPlantOfType(IntVec3 cell, ThingDef plantDef) { IPlantToGrowSettable plantToGrowSettable = GetPlayerSetPlantForCell(cell); if (plantToGrowSettable == null || !plantToGrowSettable.CanAcceptSowNow()) return false; ThingDef plantDefToGrow = plantToGrowSettable.GetPlantDefToGrow(); if (plantDefToGrow == null || plantDefToGrow != plantDef) return false; // check if there's already a plant occupying the cell if (cell.GetPlant() != null) return false; // check if there are nearby cells which block growth if (GenPlant.AdjacentSowBlocker(plantDefToGrow, cell) != null) return false; // check through all the things in the cell which might block growth foreach (Thing tempThing in Find.ThingGrid.ThingsListAt(cell)) if (tempThing.def.BlockPlanting) return false; if (!plantDefToGrow.CanEverPlantAt(cell) || !GenPlant.GrowthSeasonNow(cell)) return false; return true; }
public override IEnumerable <IntVec3> PotentialWorkCellsGlobal(Pawn pawn) { if (!ResearchProjectDefOf.AC_Tilling.IsFinished) { yield break; } Danger maxDanger = pawn.NormalMaxDanger(); List <Zone> zonesList = pawn.Map.zoneManager.AllZones; ReservationLayerDef layer = ReservationLayerDefOf.Floor; for (int j = 0; j < zonesList.Count; j++) { Zone_Growing growZone = zonesList[j] as Zone_Growing; if (growZone != null && TillToggle.IsAllowed(growZone)) { if (growZone.cells.Count == 0) { Log.ErrorOnce("Grow zone has 0 cells: " + growZone, -563487, false); } else if (!growZone.ContainsStaticFire && pawn.CanReach(growZone.Cells[0], PathEndMode.OnCell, maxDanger)) { for (int k = 0; k < growZone.cells.Count; k++) { IntVec3 c = growZone.cells[k]; if (pawn.Map.terrainGrid.TerrainAt(c).GetModExtension <TerrainExtension>() != null && pawn.Map.terrainGrid.TerrainAt(c).GetModExtension <TerrainExtension>().tillsTo != null && pawn.CanReach(growZone.Cells[0], PathEndMode.OnCell, maxDanger) && pawn.CanReserve(c, 1, -1, layer, false)) { if (c.GetPlant(pawn.Map) != null) { if (!c.GetPlant(pawn.Map).sown) { yield return(growZone.cells[k]); } } else { yield return(growZone.cells[k]); } } } } } } yield break; }
private static void Postfix(Pawn pawn, IntVec3 c, ref bool __result) { if (__result) { ThingDef plant = c.GetPlant(map: pawn.Map).def; __result = RaceAddonTools.CheckPlant(pawn.def, plant); } }
public static bool CheckSpawnWildPlantAt(WildPlantSpawner __instance, ref bool __result, IntVec3 c, float plantDensity, float wholeMapNumDesiredPlants, bool setRandomGrowth = false) { Map map2 = map(__instance); if (plantDensity <= 0f || c.GetPlant(map2) != null || c.GetCover(map2) != null || c.GetEdifice(map2) != null || map2.fertilityGrid.FertilityAt(c) <= 0f || !PlantUtility.SnowAllowsPlanting(c, map2)) { __result = false; return(false); } bool cavePlants = GoodRoofForCavePlant2(map2, c); if (SaturatedAt2(map2, c, plantDensity, cavePlants, wholeMapNumDesiredPlants)) { __result = false; return(false); } List <ThingDef> tmpPossiblePlants = new List <ThingDef>(); CalculatePlantsWhichCanGrowAt2(__instance, c, tmpPossiblePlants, cavePlants, plantDensity); if (!tmpPossiblePlants.Any()) { __result = false; return(false); } Dictionary <ThingDef, float> distanceSqToNearbyClusters = CalculateDistancesToNearbyClusters2(__instance, c); List <KeyValuePair <ThingDef, float> > tmpPossiblePlantsWithWeight = new List <KeyValuePair <ThingDef, float> >(); tmpPossiblePlantsWithWeight.Clear(); for (int i = 0; i < tmpPossiblePlants.Count; i++) { float value = PlantChoiceWeight2(__instance, tmpPossiblePlants[i], c, distanceSqToNearbyClusters, wholeMapNumDesiredPlants, plantDensity); tmpPossiblePlantsWithWeight.Add(new KeyValuePair <ThingDef, float>(tmpPossiblePlants[i], value)); } if (!tmpPossiblePlantsWithWeight.TryRandomElementByWeight((KeyValuePair <ThingDef, float> x) => x.Value, out KeyValuePair <ThingDef, float> result)) { __result = false; return(false); } Plant plant = (Plant)ThingMaker.MakeThing(result.Key); if (setRandomGrowth) { plant.Growth = Rand.Range(0.07f, 1f); if (plant.def.plant.LimitedLifespan) { plant.Age = Rand.Range(0, Mathf.Max(plant.def.plant.LifespanTicks - 50, 0)); } } GenSpawn.Spawn(plant, c, map2); __result = true; return(false); }
public static Plant GetFirstBlightableNowPlant(IntVec3 c, Map map) { Plant plant = c.GetPlant(map); if (plant != null && plant.BlightableNow) { return(plant); } return(null); }
public override bool HasJobOnCell(Pawn pawn, IntVec3 c, bool forced = false) { Plant plant = c.GetPlant(pawn.Map); if (plant == null || plant.def.plant.IsTree) { return(false); } return(base.HasJobOnCell(pawn, c, forced)); }
public override void DesignateSingleCell(IntVec3 c) { Plant plant = c.GetPlant(Map); AcceptanceReport result = CanDesignateThing(plant); if (plant != null && result.Accepted) { DesignateThing(plant); } }
public bool CheckSpawnWildPlantAt(IntVec3 c, float plantDensity, float wholeMapNumDesiredPlants, bool setRandomGrowth = false) { bool result; if (plantDensity <= 0f || c.GetPlant(this.map) != null || c.GetCover(this.map) != null || c.GetEdifice(this.map) != null || this.map.fertilityGrid.FertilityAt(c) <= 0f || !GenPlant.SnowAllowsPlanting(c, this.map)) { result = false; } else { bool cavePlants = this.GoodRoofForCavePlant(c); if (this.SaturatedAt(c, plantDensity, cavePlants, wholeMapNumDesiredPlants)) { result = false; } else { this.CalculatePlantsWhichCanGrowAt(c, WildPlantSpawner.tmpPossiblePlants, cavePlants, plantDensity); if (!WildPlantSpawner.tmpPossiblePlants.Any <ThingDef>()) { result = false; } else { this.CalculateDistancesToNearbyClusters(c); WildPlantSpawner.tmpPossiblePlantsWithWeight.Clear(); for (int i = 0; i < WildPlantSpawner.tmpPossiblePlants.Count; i++) { float value = this.PlantChoiceWeight(WildPlantSpawner.tmpPossiblePlants[i], c, WildPlantSpawner.distanceSqToNearbyClusters, wholeMapNumDesiredPlants, plantDensity); WildPlantSpawner.tmpPossiblePlantsWithWeight.Add(new KeyValuePair <ThingDef, float>(WildPlantSpawner.tmpPossiblePlants[i], value)); } KeyValuePair <ThingDef, float> keyValuePair; if (!WildPlantSpawner.tmpPossiblePlantsWithWeight.TryRandomElementByWeight((KeyValuePair <ThingDef, float> x) => x.Value, out keyValuePair)) { result = false; } else { Plant plant = (Plant)ThingMaker.MakeThing(keyValuePair.Key, null); if (setRandomGrowth) { plant.Growth = Rand.Range(0.07f, 1f); if (plant.def.plant.LimitedLifespan) { plant.Age = Rand.Range(0, Mathf.Max(plant.def.plant.LifespanTicks - 50, 0)); } } GenSpawn.Spawn(plant, c, this.map, WipeMode.Vanish); result = true; } } } } return(result); }
// Do not automatically harvest Party Trees. Player can still designate it explicitly if they wish. public static void HasJobOnCell_PostFix(WorkGiver_GrowerHarvest __instance, Pawn pawn, IntVec3 c, bool forced, ref bool __result) { if (__result == false) { return; } if (c.GetPlant(pawn.Map) is Plant_PartyTree) { __result = false; } }
public override bool DoIterationWork(IntVec3 c) { var plant = c.GetPlant(Map); if (plant != null && !Map.reservationManager.IsReservedByAnyoneOf(plant, Faction)) { var rate = GetGrowthRatePerTickFor(plant); plant.Growth += rate * this.GrowRate;//Growth sped up by 1hr } return(true); }
public override Job JobOnCell(Pawn pawn, IntVec3 cell) { if (WorkGiver_Grower.wantedPlantDef == null) { base.DetermineWantedPlantDef(cell); if (WorkGiver_Grower.wantedPlantDef == null) { return null; } } Plant plant = cell.GetPlant() as Plant; if (plant == null) { return null; } if (plant.def != WorkGiver_Grower.wantedPlantDef) { return null; } if (!plant.def.plant.Harvestable || plant.LifeStage != PlantLifeStage.Growing || !plant.NeedsWatering) { return null; } if (!pawn.CanReserve(plant, 1)) { return null; } // Got a plant we want to water. Do we have a watering tool? Thing tool = WaterUtility.HaulingToolInInventory(pawn); if (tool == null) { tool = WaterUtility.NearestHaulingTool(pawn); if (tool == null) { ConceptDecider.TeachOpportunity(DefDatabase<ConceptDef>.GetNamedSilentFail("Dehydration_HaulWaterTool"), OpportunityType.Important); JobFailReason.Is("nothing to haul with"); return null; } } var toolWc = tool.TryGetComp<CompWaterContainer>(); // If we already have enough water in the tool, can just haul it now. // TODO: use water-per-plant from JobDriver if (toolWc.StoredLitres >= JobDriver_WaterPlant.waterPerPlant) { return MakeWaterPlantJob(TargetInfo.NullThing, plant, tool); } // Otherwise we need to find more. else { float collectLitres = toolWc.FreeSpaceLitres; IntVec3 waterNear = pawn.Position; // Wells, water carriers on the ground, etc. Predicate<Thing> validator = (Thing candidate) => { var candidateWc = candidate.TryGetComp<CompWaterContainer>(); if (candidateWc == null) { return false; } // Don't haul if the source has too little water. return candidateWc.StoredLitres >= JobDriver_WaterPlant.waterPerPlant; }; var thingWater = WaterUtility.BestWaterSpawnedFor(pawn, collectLitres, validator, waterNear); // Rivers, lakes, other terrain-based water sources. var terrainWaterVec = WaterUtility.BestTerrainWaterFor(pawn, waterNear); // Pick the nearest of the water sources. if (thingWater != null && terrainWaterVec != null) { float thingDist = (pawn.Position - thingWater.Position).LengthHorizontalSquared; float terrainDist = (pawn.Position - terrainWaterVec.Value).LengthHorizontalSquared; if (thingDist <= terrainDist) { terrainWaterVec = null; } else { thingWater = null; } } if (thingWater != null) { return MakeWaterPlantJob(thingWater, plant, tool); } else if (terrainWaterVec != null) { return MakeWaterPlantJob(terrainWaterVec.Value, plant, tool); } else { JobFailReason.Is("no water nearby"); return null; } } }