public override Job TryGiveJob(Pawn pawn) { int plantSkill = pawn.skills.GetSkill(SkillDefOf.Plants).Level; Zone growZone = null; if (!pawn.Map.zoneManager.AllZones.Where((Zone x) => { Zone_Growing zone = x as Zone_Growing; if (zone == null) { return(false); } if (zone.cells.Count == 0) { return(false); } if (zone.GetPlantDefToGrow() == null || zone.GetPlantDefToGrow().plant == null) { return(false); } if (plantSkill < Mathf.RoundToInt(zone.GetPlantDefToGrow().plant.sowMinSkill * 0.75f)) { return(false); } return(true); }).TryRandomElement(out growZone)) { return(null); } IntVec3 position = AIUtility.FindRandomSpotInZone(pawn, growZone, true, true); if (position != IntVec3.Invalid) { return(new Job(IdleJobDefOf.IdleJob_Gardening, position) { locomotionUrgency = modSettings.wanderMovePolicy }); } else { return(null); } }
private static void Postfix(Zone_Growing __instance, ref string __result) { var data = __instance.GetFarmingHysteresisData(); var(harvestedThingDef, harvestedThingCount) = __instance.PlantHarvestInfo(); if (data.Enabled) { if (harvestedThingDef == null) { data.DisableDueToMissingHarvestedThingDef(__instance); return; } var plant = __instance.GetPlantDefToGrow(); __result += "\n" + "FarmingHysteresis.UseGlobalBounds".Translate(harvestedThingDef.label, data.useGlobalValues ? "Yes".Translate() : "No".Translate()); __result += "\n" + "FarmingHysteresis.LowerBound".Translate(plant.label, data.LowerBound, harvestedThingDef.label); __result += "\n" + "FarmingHysteresis.UpperBound".Translate(plant.label, data.UpperBound, harvestedThingDef.label); __result += "\n" + "FarmingHysteresis.InStorage".Translate(harvestedThingDef.label, harvestedThingCount); __result += "\n" + "FarmingHysteresis.LatchModeDesc".Translate(("FarmingHysteresis.LatchModeDesc." + data.latchMode.ToString()).Translate()); } else if (harvestedThingDef == null) { __result += "\n" + "FarmingHysteresis.DisabledDueToMissingHarvestedThingDef".Translate(); } }
public static void Postfix(ref Zone_Growing __instance, ref string __result) { var plantDef = __instance.GetPlantDefToGrow(); var thePlant = plantDef.plant; int totalYield = 0, maxYield = 0, num = 0, numGrowing = 0; float totalGrowthRemaining = 0f; foreach (Thing thing in __instance.AllContainedThings) { if (thing.def == plantDef && thing is Plant plant) { ++num; totalYield += plant.YieldNow(); if (plant.Growth < 0.95f && !plant.YIResting() && plant.GrowthRateFactor_Light > .001f) { ++numGrowing; totalGrowthRemaining += plant.YIActualGrowthTime(); } } } maxYield = (int)thePlant.harvestYield; float efficiency = maxYield / thePlant.growDays; __result += "\n" + "YI.InspectYields".Translate(new object[] { totalYield.ToString(), (maxYield * num).ToString() }); __result += "\n" + "YI.Efficiency".Translate(efficiency.ToString("0.##")); // If is resting period, we dont show the line. if (GenLocalDate.DayPercent(__instance.Map) < 0.25f || GenLocalDate.DayPercent(__instance.Map) > 0.8f) { __result += "\n" + "YI.GrowthRemaining".Translate((totalGrowthRemaining / numGrowing).ToString("0.##")); } }
internal static (ThingDef, int) PlantHarvestInfo(this Zone_Growing zone) { var harvestedThingDef = zone.GetPlantDefToGrow().plant.harvestedThingDef; if (harvestedThingDef != null) { return(harvestedThingDef, zone.Map.resourceCounter.GetCount(harvestedThingDef)); } else { return(null, 0); } }
public static int GrownCount(Zone_Growing zone) { Map map = zone.Map; int ret = 0; ThingDef plantDef = zone.GetPlantDefToGrow(); foreach (IntVec3 cell in zone.cells) { if (map.thingGrid.ThingsAt(cell).FirstOrDefault(t => t is Plant) is Plant p && p.def == plantDef && p.Growth == 1) { ret++; } } return(ret); }
public static bool Patch_Zone_Growing_GetInspectString(ref Zone_Growing __instance, ref string __result) { ThingDef plantDefToGrow = __instance.GetPlantDefToGrow(); if (plantDefToGrow.thingClass != typeof(FrostPlant)) { return(true); } string text = ""; if (!__instance.cells.NullOrEmpty()) { IntVec3 val = __instance.cells.First(); if (GridsUtility.UsesOutdoorTemperature(val, __instance.Map)) { string text2 = text; text = text2 + Translator.Translate("OutdoorGrowingPeriod") + ": " + Zone_Growing.GrowingQuadrumsDescription(__instance.Map.Tile) + " (" + Translator.Translate("OrassansColdImmunePlants") + ")\n"; } text = (__result = (!GrowthSeasonNowFrostPlant(val, __instance.Map) ? text + Translator.Translate("CannotGrowBadSeasonTemperature") : text + Translator.Translate("GrowSeasonHereNow"))); } return(false); }
private void GatherSingleZoneData(Zone_Growing zone, out SingleZoneGrowingData data) { data = new SingleZoneGrowingData(); data.zone = zone; Plant plant; int growthRate; float harvestMinGrowth = zone.GetPlantDefToGrow().plant.harvestMinGrowth * 100; //analyze growth values foreach (Thing t in zone.AllContainedThings) { if (t.def == zone.GetPlantDefToGrow()) { plant = t as Plant; if (plant != null) { growthRate = (int)(plant.Growth * 100); data.growRatesAbsolute[growthRate]++; data.totalPlantedCount++; if (growthRate >= 100) { data.fullyGrownPlants.Add(t); } if (growthRate >= harvestMinGrowth) { data.harvestablePlants.Add(t); } } } } //add curve points growthValueDrawInfo.curve = new SimpleCurve(); float maxYValue = 0; if (data.totalPlantedCount > 0) { for (int i = 0; i < data.growRatesAbsolute.Length; i++) { growthValueDrawInfo.curve.Add(new CurvePoint((float)i, 100 * data.growRatesAbsolute[i] / data.totalPlantedCount), false); } maxYValue = 100 * data.growthRateMaxCount / data.totalPlantedCount + 5; } else { growthValueDrawInfo.curve.Add(new CurvePoint(0f, 0f), false); growthValueDrawInfo.curve.Add(new CurvePoint(100f, 0f), false); maxYValue = 5; } //draw vertical marker harvestableMarkerDrawInfo.color = Color.white; harvestableMarkerDrawInfo.curve = new SimpleCurve(); harvestableMarkerDrawInfo.curve.Add(-5, -5f, false); harvestableMarkerDrawInfo.curve.Add(harvestMinGrowth, -5f, false); harvestableMarkerDrawInfo.curve.Add(harvestMinGrowth, Math.Min(100, maxYValue), false); harvestableMarkerDrawInfo.curve.Add(harvestMinGrowth, -5f, false); curves.Add(growthValueDrawInfo); curves.Add(harvestableMarkerDrawInfo); }
public override void MapComponentTick() { // TickLong if (Find.TickManager.TicksGame % 2000 != 0) { return; } List <Zone> allZones = map.zoneManager.AllZones; foreach (Zone z in allZones) { // Skip wrong or useless cases if (z.GetType() != typeof(Zone_Growing)) { continue; } Zone_Growing zg = (Zone_Growing)z; /*if (!z2.allowGrowthSync) * { * continue; * }*/ /*var extVals = z2.GetPlantDefToGrow().GetModExtension<ModExtension_Plant>() ?? ModExtension_Plant.defaultValues; * if (!extVals.syncGrowthIfCrop) { * continue; * }*/ float growthSyncStep = SyncRatePerFullGrowth / (zg.GetPlantDefToGrow().plant.growDays * 30); IEnumerable <Thing> allThings = zg.AllContainedThings; // Sum up all plant growth List <Plant> plantsInZone = new List <Plant>(); float avg = 0; foreach (Thing thing in allThings) { if (thing.GetType() == typeof(Plant)) { Plant plant = (Plant)thing; // Is plant wanted in this zone (isCrop) and growing? if (plant.IsCrop && plant.LifeStage == PlantLifeStage.Growing) { avg += plant.Growth; plantsInZone.Add(plant); } } } // Calculate average avg = avg / plantsInZone.Count; // Get ups and downs and process/clean near avg plants int ups = 0; int downs = 0; for (int i = plantsInZone.Count - 1; i >= 0; i--) { if (Math.Abs(avg - plantsInZone[i].Growth) <= growthSyncStep) { plantsInZone[i].Growth = avg; plantsInZone.RemoveAt(i); continue; } if (plantsInZone[i].Growth < avg) { ups++; } if (plantsInZone[i].Growth > avg) { downs++; } } // Calculate step balance factor float upBalance = 1f; float downBalance = 1f; if (ups > 0 && downs > 0) { if (ups > downs) { upBalance = (float)downs / ups; } else { downBalance = (float)ups / downs; } } // Use on plants foreach (Plant plant in plantsInZone) { if (plant.Growth < avg) { plant.Growth += growthSyncStep * upBalance; } if (plant.Growth > avg) { plant.Growth -= growthSyncStep * downBalance; } } } }
public static int ToDoCount(Zone_Growing zone) { Map map = zone.Map; return(zone.cells.FindAll(c => !map.thingGrid.ThingsAt(c).Any(t => t.def == zone.GetPlantDefToGrow())).Count); }
public static float FertilityCount(Zone_Growing zone) { return(zone.GetPlantDefToGrow().plant.fertilitySensitivity *zone.cells.Sum(cell => zone.Map.fertilityGrid.FertilityAt(cell) - 1.0f)); }
public Job JobOnCell(Pawn pawn, IntVec3 c) { if (c.IsForbidden(pawn)) { return(null); } if (!GenPlant.GrowthSeasonNow(c)) { return(null); } if (wantedPlantDef == null) { DetermineWantedPlantDef(c); if (wantedPlantDef == null) { return(null); } } Plant plant = c.GetPlant(); if (plant != null) { if (plant.def == wantedPlantDef) { return(null); } if (plant.def.plant.blockAdjacentSow) { if (!pawn.CanReserve(plant, 1) || plant.IsForbidden(pawn)) { return(null); } return(new Job(JobDefOf.CutPlant, plant)); } } Thing thing = GenPlant.AdjacentSowBlocker(wantedPlantDef, c); if (thing != null) { Plant plant2 = thing as Plant; if (plant2 != null && pawn.CanReserve(plant2, 1) && !plant2.IsForbidden(pawn)) { Zone_Growing zone_Growing = Find.ZoneManager.ZoneAt(plant2.Position) as Zone_Growing; if (zone_Growing == null || zone_Growing.GetPlantDefToGrow() != plant2.def) { return(new Job(JobDefOf.CutPlant, plant2)); } } return(null); } List <Thing> list = Find.ThingGrid.ThingsListAt(c); int i = 0; while (i < list.Count) { Thing thing2 = list[i]; if (thing2.def == wantedPlantDef) { return(null); } if (thing2.def.BlockPlanting) { if (!pawn.CanReserve(thing2, 1)) { return(null); } if (thing2.def.category == ThingCategory.Plant) { if (!thing2.IsForbidden(pawn)) { return(new Job(JobDefOf.CutPlant, thing2)); } return(null); } else { if (thing2.def.EverHaulable) { return(HaulAIUtility.HaulAsideJobFor(pawn, thing2)); } return(null); } } else { i++; } } if (!wantedPlantDef.CanEverPlantAt(c) || !GenPlant.GrowthSeasonNow(c) || !pawn.CanReserve(c, 1)) { return(null); } return(new Job(JobDefOf.Sow, c) { plantDefToSow = wantedPlantDef }); }
private static void Postfix(Zone_Growing __instance, ref IEnumerable <Gizmo> __result) { if (Find.Selector.NumSelected != 1) { return; } var data = __instance.GetFarmingHysteresisData(); var harvestedThingDef = __instance.GetPlantDefToGrow().plant.harvestedThingDef; var harvestHysteresisCommand = new Command_Toggle { defaultLabel = "FarmingHysteresis.EnableFarmingHysteresis".Translate(), defaultDesc = "FarmingHysteresis.EnableFarmingHysteresisisDesc".Translate(), icon = TexCommand.ForbidOff, isActive = () => data.Enabled, toggleAction = () => { if (data.Enabled) { data.Disable(__instance); } else { data.Enable(__instance); } } }; var result = new List <Gizmo>(__result); if (harvestedThingDef != null) { result.Add(harvestHysteresisCommand); } if (data.Enabled) { if (harvestedThingDef == null) { data.DisableDueToMissingHarvestedThingDef(__instance); return; } // If hysteresis is enabled, disable the manual sowing enabled button var sowingGizmo = result.Find(g => g is Command_Toggle t && t.defaultLabel == "CommandAllowSow".Translate()); result.Remove(sowingGizmo); var useGlobalValuesCommand = new Command_Toggle { defaultLabel = "FarmingHysteresis.UseGlobalValues".Translate(), defaultDesc = "FarmingHysteresis.UseGlobalValuesDesc".Translate(), icon = TexCommand.ForbidOff, isActive = () => data.useGlobalValues, toggleAction = () => { if (data.useGlobalValues || FarmingHysteresisMapComponent.For(Find.CurrentMap).HasBoundsFor(harvestedThingDef)) { // We were already using global values OR such global values already exist for this harvest type. // So just flip the value. data.useGlobalValues = !data.useGlobalValues; } else { // This is the first time this harvest type is switching to global values. // Copy the initial global values over from the local values for a better user experience. var currentLowerBound = data.LowerBound; var currentUpperBound = data.UpperBound; data.useGlobalValues = true; data.LowerBound = currentLowerBound; data.UpperBound = currentUpperBound; } } }; result.Add(useGlobalValuesCommand); Texture2D uiIcon = harvestedThingDef.uiIcon; var decrementLowerHysteresisCommand = new Command_Decrement { defaultLabel = "FarmingHysteresis.DecrementLowerHysteresis".Translate(GenUI.CurrentAdjustmentMultiplier()), defaultDesc = "FarmingHysteresis.DecrementLowerHysteresisDesc".Translate( GenUI.CurrentAdjustmentMultiplier(), KeyBindingDefOf.ModifierIncrement_10x.MainKeyLabel, KeyBindingDefOf.ModifierIncrement_100x.MainKeyLabel ), icon = uiIcon, action = () => data.LowerBound -= GenUI.CurrentAdjustmentMultiplier() }; result.Add(decrementLowerHysteresisCommand); var incrementLowerHysteresisCommand = new Command_Increment { defaultLabel = "FarmingHysteresis.IncrementLowerHysteresis".Translate(GenUI.CurrentAdjustmentMultiplier()), defaultDesc = "FarmingHysteresis.IncrementLowerHysteresisDesc".Translate( GenUI.CurrentAdjustmentMultiplier(), KeyBindingDefOf.ModifierIncrement_10x.MainKeyLabel, KeyBindingDefOf.ModifierIncrement_100x.MainKeyLabel ), icon = uiIcon, action = () => data.LowerBound += GenUI.CurrentAdjustmentMultiplier() }; result.Add(incrementLowerHysteresisCommand); var decrementUpperHysteresisCommand = new Command_Decrement { defaultLabel = "FarmingHysteresis.DecrementUpperHysteresis".Translate(GenUI.CurrentAdjustmentMultiplier()), defaultDesc = "FarmingHysteresis.DecrementUpperHysteresisDesc".Translate( GenUI.CurrentAdjustmentMultiplier(), KeyBindingDefOf.ModifierIncrement_10x.MainKeyLabel, KeyBindingDefOf.ModifierIncrement_100x.MainKeyLabel ), icon = uiIcon, action = () => data.UpperBound -= GenUI.CurrentAdjustmentMultiplier() }; result.Add(decrementUpperHysteresisCommand); var incrementUpperHysteresisCommand = new Command_Increment { defaultLabel = "FarmingHysteresis.IncrementUpperHysteresis".Translate(GenUI.CurrentAdjustmentMultiplier()), defaultDesc = "FarmingHysteresis.IncrementUpperHysteresisDesc".Translate( GenUI.CurrentAdjustmentMultiplier(), KeyBindingDefOf.ModifierIncrement_10x.MainKeyLabel, KeyBindingDefOf.ModifierIncrement_100x.MainKeyLabel ), icon = uiIcon, action = () => data.UpperBound += GenUI.CurrentAdjustmentMultiplier() }; result.Add(incrementUpperHysteresisCommand); } __result = result; }
public override void MapComponentTick() { if (tickMan.TicksGame % PGSModSettings.TimeBetweenChecks != 0) // 60 ticks = 1 second { return; } foreach (Zone allZone in map.zoneManager.AllZones) { if (allZone.GetType() == typeof(Zone_Growing)) { Zone_Growing zoneGrowing = (Zone_Growing)allZone; float growRate = (float)(PGSModSettings.SyncRatePerFullGrowth / (zoneGrowing.GetPlantDefToGrow().plant.growDays * 30.0)); IEnumerable <Thing> allContainedThings = zoneGrowing.AllContainedThings; List <Plant> plantList = new List <Plant>(); float totalPlantGrowth = 0.0f; foreach (Thing thing in allContainedThings) { if (thing.GetType() == typeof(Plant)) { Plant plant = (Plant)thing; if (plant.IsCrop && plant.LifeStage == PlantLifeStage.Growing) { totalPlantGrowth += plant.Growth; plantList.Add(plant); } } } float averagePlantGrowth = totalPlantGrowth / plantList.Count; int underAveragePlants = 0; int overAveragePlants = 0; for (int index = plantList.Count - 1; index >= 0; --index) { if (Math.Abs(averagePlantGrowth - plantList[index].Growth) <= (double)growRate) { plantList[index].Growth = averagePlantGrowth; plantList.RemoveAt(index); } else { if (plantList[index].Growth < averagePlantGrowth) { ++underAveragePlants; } if (plantList[index].Growth > averagePlantGrowth) { ++overAveragePlants; } } } float moreUnderThanOver = 1f; float moreOverThanUnder = 1f; if (underAveragePlants > 0 && overAveragePlants > 0) { if (underAveragePlants > overAveragePlants) { moreUnderThanOver = overAveragePlants / underAveragePlants; } else { moreOverThanUnder = underAveragePlants / overAveragePlants; } } foreach (Plant plant in plantList) { if (plant.Growth < averagePlantGrowth) { plant.Growth += growRate * moreUnderThanOver; } if (plant.Growth > averagePlantGrowth) { plant.Growth -= growRate * moreOverThanUnder; } } } } }