public static void SetWindExposureColors(Color32[] colors, Plant plant) { colors[1].a = (colors[2].a = GenPlant.GetWindExposure(plant)); colors[0].a = (colors[3].a = 0); }
private static void CacheAccessibleThings(int nearTile) { if (nearTile != cachedAccessibleThingsForTile || RealTime.frameCount != cachedAccessibleThingsForFrame) { cachedAccessibleThings.Clear(); cachedPossiblyAccessibleThings.Clear(); cachedMakeableItemDefs.Clear(); WorldGrid worldGrid = Find.WorldGrid; List <Map> maps = Find.Maps; for (int i = 0; i < maps.Count; i++) { float num = worldGrid.ApproxDistanceInTiles(nearTile, maps[i].Tile); if (!(num > 5f)) { ThingOwnerUtility.GetAllThingsRecursively(maps[i], tmpThings, allowUnreal: false); cachedAccessibleThings.AddRange(tmpThings); } } List <Caravan> caravans = Find.WorldObjects.Caravans; for (int j = 0; j < caravans.Count; j++) { if (caravans[j].IsPlayerControlled) { float num2 = worldGrid.ApproxDistanceInTiles(nearTile, caravans[j].Tile); if (!(num2 > 5f)) { ThingOwnerUtility.GetAllThingsRecursively(caravans[j], tmpThings, allowUnreal: false); cachedAccessibleThings.AddRange(tmpThings); } } } for (int k = 0; k < cachedAccessibleThings.Count; k++) { Thing thing = cachedAccessibleThings[k]; cachedPossiblyAccessibleThings.Add(new ThingDefCount(thing.def, thing.stackCount)); if (GenLeaving.CanBuildingLeaveResources(thing, DestroyMode.Deconstruct)) { List <ThingDefCountClass> list = thing.CostListAdjusted(); for (int l = 0; l < list.Count; l++) { int num3 = Mathf.RoundToInt((float)list[l].count * thing.def.resourcesFractionWhenDeconstructed); if (num3 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(list[l].thingDef, num3)); cachedMakeableItemDefs.Add(list[l].thingDef); } } } Plant plant = thing as Plant; if (plant != null && (plant.HarvestableNow || plant.HarvestableSoon)) { int num4 = Mathf.RoundToInt(plant.def.plant.harvestYield * Find.Storyteller.difficulty.cropYieldFactor); if (num4 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(plant.def.plant.harvestedThingDef, num4)); cachedMakeableItemDefs.Add(plant.def.plant.harvestedThingDef); } } if (!thing.def.butcherProducts.NullOrEmpty()) { for (int m = 0; m < thing.def.butcherProducts.Count; m++) { cachedPossiblyAccessibleThings.Add(thing.def.butcherProducts[m]); cachedMakeableItemDefs.Add(thing.def.butcherProducts[m].thingDef); } } Pawn pawn = thing as Pawn; if (pawn != null) { if (pawn.RaceProps.meatDef != null) { int num5 = Mathf.RoundToInt(pawn.GetStatValue(StatDefOf.MeatAmount)); if (num5 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(pawn.RaceProps.meatDef, num5)); cachedMakeableItemDefs.Add(pawn.RaceProps.meatDef); } } if (pawn.RaceProps.leatherDef != null) { int num6 = GenMath.RoundRandom(pawn.GetStatValue(StatDefOf.LeatherAmount)); if (num6 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(pawn.RaceProps.leatherDef, num6)); cachedMakeableItemDefs.Add(pawn.RaceProps.leatherDef); } } if (!pawn.RaceProps.Humanlike) { PawnKindLifeStage curKindLifeStage = pawn.ageTracker.CurKindLifeStage; if (curKindLifeStage.butcherBodyPart != null) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(curKindLifeStage.butcherBodyPart.thing, 1)); cachedMakeableItemDefs.Add(curKindLifeStage.butcherBodyPart.thing); } } } if (thing.def.smeltable) { List <ThingDefCountClass> list2 = thing.CostListAdjusted(); for (int n = 0; n < list2.Count; n++) { if (!list2[n].thingDef.intricate) { int num7 = Mathf.RoundToInt((float)list2[n].count * 0.25f); if (num7 > 0) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(list2[n].thingDef, num7)); cachedMakeableItemDefs.Add(list2[n].thingDef); } } } } if (thing.def.smeltable && !thing.def.smeltProducts.NullOrEmpty()) { for (int num8 = 0; num8 < thing.def.smeltProducts.Count; num8++) { cachedPossiblyAccessibleThings.Add(thing.def.smeltProducts[num8]); cachedMakeableItemDefs.Add(thing.def.smeltProducts[num8].thingDef); } } } int num9 = 0; for (int num10 = 0; num10 < cachedAccessibleThings.Count; num10++) { Pawn pawn2 = cachedAccessibleThings[num10] as Pawn; if (pawn2 != null && pawn2.IsFreeColonist && !pawn2.Dead && !pawn2.Downed && pawn2.workSettings.WorkIsActive(WorkTypeDefOf.Crafting)) { num9++; } } if (num9 > 0) { tmpWorkTables.Clear(); for (int num11 = 0; num11 < cachedAccessibleThings.Count; num11++) { Building_WorkTable building_WorkTable = cachedAccessibleThings[num11] as Building_WorkTable; if (building_WorkTable != null && building_WorkTable.Spawned && tmpWorkTables.Add(building_WorkTable.def)) { List <RecipeDef> allRecipes = building_WorkTable.def.AllRecipes; for (int num12 = 0; num12 < allRecipes.Count; num12++) { if (allRecipes[num12].AvailableNow && allRecipes[num12].products.Any() && !allRecipes[num12].PotentiallyMissingIngredients(null, building_WorkTable.Map).Any()) { ThingDef stuffDef = (!allRecipes[num12].products[0].thingDef.MadeFromStuff) ? null : GenStuff.DefaultStuffFor(allRecipes[num12].products[0].thingDef); float num13 = allRecipes[num12].WorkAmountTotal(stuffDef); if (!(num13 <= 0f)) { int num14 = Mathf.FloorToInt((float)(num9 * 60000 * 5) * 0.09f / num13); if (num14 > 0) { for (int num15 = 0; num15 < allRecipes[num12].products.Count; num15++) { cachedPossiblyAccessibleThings.Add(new ThingDefCount(allRecipes[num12].products[num15].thingDef, allRecipes[num12].products[num15].count * num14)); cachedMakeableItemDefs.Add(allRecipes[num12].products[num15].thingDef); } } } } } } } } cachedAccessibleThingsForTile = nearTile; cachedAccessibleThingsForFrame = RealTime.frameCount; } }
public static bool TryFindReproductionDestination(IntVec3 source, ThingDef plantDef, SeedTargFindMode mode, Map map, out IntVec3 foundCell) { float radius = -1f; switch (mode) { case SeedTargFindMode.Reproduce: radius = plantDef.plant.reproduceRadius; break; case SeedTargFindMode.MapGenCluster: radius = plantDef.plant.WildClusterRadiusActual; break; case SeedTargFindMode.MapEdge: radius = 40f; break; case SeedTargFindMode.Cave: radius = plantDef.plant.WildClusterRadiusActual; break; } int num = 0; int num2 = 0; float num3 = 0f; CellRect cellRect = CellRect.CenteredOn(source, Mathf.RoundToInt(radius)); cellRect.ClipInsideMap(map); for (int i = cellRect.minZ; i <= cellRect.maxZ; i++) { for (int j = cellRect.minX; j <= cellRect.maxX; j++) { IntVec3 c2 = new IntVec3(j, 0, i); Plant plant = c2.GetPlant(map); if (plant != null && (mode != SeedTargFindMode.Cave || plant.def.plant.cavePlant)) { num++; if (plant.def == plantDef) { num2++; } } num3 += c2.GetTerrain(map).fertility; } } float num4 = (float)((mode != SeedTargFindMode.Cave) ? map.Biome.plantDensity : 0.5); float num5 = num3 * num4; bool flag = (float)num > num5; if ((float)num > num5 * 1.25) { foundCell = IntVec3.Invalid; return(false); } if (mode != 0 && mode != SeedTargFindMode.Cave) { BiomeDef curBiome = map.Biome; float num6 = curBiome.AllWildPlants.Sum((ThingDef pd) => curBiome.CommonalityOfPlant(pd)); float num7 = curBiome.CommonalityOfPlant(plantDef) / num6; float num8 = curBiome.CommonalityOfPlant(plantDef) * plantDef.plant.wildCommonalityMaxFraction / num6; float num9 = num5 * num8; if ((float)num2 > num9) { foundCell = IntVec3.Invalid; return(false); } float num10 = num5 * num7; bool flag2 = (float)num2 < num10 * 0.5; if (flag && !flag2) { foundCell = IntVec3.Invalid; return(false); } } Predicate <IntVec3> validator = delegate(IntVec3 c) { if (!plantDef.CanEverPlantAt(c, map)) { return(false); } if (plantDef.plant.cavePlant && !GenPlantReproduction.GoodRoofForCavePlantReproduction(c, map)) { return(false); } if (!GenPlant.SnowAllowsPlanting(c, map)) { return(false); } if (!source.InHorDistOf(c, radius)) { return(false); } if (!GenSight.LineOfSight(source, c, map, true, null, 0, 0)) { return(false); } return(true); }; return(CellFinder.TryFindRandomCellNear(source, map, Mathf.CeilToInt(radius), validator, out foundCell)); }
public static byte GetWindExposure(Plant plant) { return((byte)Mathf.Min(255f * plant.def.plant.topWindExposure, 255f)); }
public override bool HasJobOnCell(Pawn pawn, IntVec3 c) { Plant plant = c.GetPlant(pawn.Map); return(plant != null && !plant.IsForbidden(pawn) && plant.HarvestableNow && plant.LifeStage == PlantLifeStage.Mature && plant.YieldNow() > 0 && pawn.CanReserve(plant, 1, -1, null, false)); }
protected override IEnumerable <Toil> MakeNewToils() { Toil meditate = new Toil { socialMode = RandomSocialMode.Off }; if (FromBed) { this.KeepLyingDown(TargetIndex.B); meditate = Toils_LayDown.LayDown(TargetIndex.B, job.GetTarget(TargetIndex.B).Thing is Building_Bed, lookForOtherJobs: false, canSleep: false); } else { yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.OnCell)); meditate.initAction = delegate { LocalTargetInfo target = job.GetTarget(TargetIndex.C); if (target.IsValid) { faceDir = target.Cell - pawn.Position; } else { faceDir = (job.def.faceDir.IsValid ? job.def.faceDir : Rot4.Random).FacingCell; } }; if (Focus != null) { meditate.FailOnDespawnedNullOrForbidden(TargetIndex.C); if (pawn.HasPsylink && Focus.Thing != null) { meditate.FailOn(() => Focus.Thing.GetStatValueForPawn(StatDefOf.MeditationFocusStrength, pawn) < float.Epsilon); } } meditate.handlingFacing = true; } meditate.defaultCompleteMode = ToilCompleteMode.Delay; meditate.defaultDuration = job.def.joyDuration; meditate.FailOn(() => !MeditationUtility.CanMeditateNow(pawn) || !MeditationUtility.SafeEnvironmentalConditions(pawn, base.TargetLocA, base.Map)); meditate.AddPreTickAction(delegate { bool flag = pawn.GetTimeAssignment() == TimeAssignmentDefOf.Meditate; if (job.ignoreJoyTimeAssignment) { Pawn_PsychicEntropyTracker psychicEntropy = pawn.psychicEntropy; if (!flag && psychicEntropy.TargetPsyfocus < psychicEntropy.CurrentPsyfocus && (psychicEntropy.TargetPsyfocus < job.psyfocusTargetLast || job.wasOnMeditationTimeAssignment)) { EndJobWith(JobCondition.InterruptForced); return; } job.psyfocusTargetLast = psychicEntropy.TargetPsyfocus; job.wasOnMeditationTimeAssignment = flag; } if (faceDir.IsValid && !FromBed) { pawn.rotationTracker.FaceCell(pawn.Position + faceDir); } MeditationTick(); if (ModLister.RoyaltyInstalled && MeditationFocusDefOf.Natural.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 == ThingDefOf.Plant_TreeAnima) { plant.TryGetComp <CompSpawnSubplant>()?.AddProgress_NewTmp(AnimaTreeSubplantProgressPerTick); } } } } }); yield return(meditate); }
protected override IEnumerable <Toil> MakeNewToils() { Init(); yield return(Toils_JobTransforms.MoveCurrentTargetIntoQueue(TargetIndex.A)); Toil initExtractTargetFromQueue = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A, (RequiredDesignation != null) ? ((Func <Thing, bool>)((Thing t) => base.Map.designationManager.DesignationOn(t, RequiredDesignation) != null)) : null); yield return(initExtractTargetFromQueue); yield return(Toils_JobTransforms.SucceedOnNoTargetInQueue(TargetIndex.A)); yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.A)); Toil toil = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, initExtractTargetFromQueue); if (RequiredDesignation != null) { toil.FailOnThingMissingDesignation(TargetIndex.A, RequiredDesignation); } yield return(toil); Toil cut = new Toil(); cut.tickAction = delegate { Pawn actor = cut.actor; if (actor.skills != null) { actor.skills.Learn(SkillDefOf.Plants, xpPerTick); } float statValue = actor.GetStatValue(StatDefOf.PlantWorkSpeed); Plant plant = Plant; statValue *= Mathf.Lerp(3.3f, 1f, plant.Growth); workDone += statValue; if (workDone >= plant.def.plant.harvestWork) { if (plant.def.plant.harvestedThingDef != null) { if (actor.RaceProps.Humanlike && plant.def.plant.harvestFailable && !plant.Blighted && Rand.Value > actor.GetStatValue(StatDefOf.PlantHarvestYield)) { MoteMaker.ThrowText((pawn.DrawPos + plant.DrawPos) / 2f, base.Map, "TextMote_HarvestFailed".Translate(), 3.65f); } else { int num = plant.YieldNow(); if (num > 0) { Thing thing = ThingMaker.MakeThing(plant.def.plant.harvestedThingDef); thing.stackCount = num; if (actor.Faction != Faction.OfPlayer) { thing.SetForbidden(value: true); } Find.QuestManager.Notify_PlantHarvested(actor, thing); GenPlace.TryPlaceThing(thing, actor.Position, base.Map, ThingPlaceMode.Near); actor.records.Increment(RecordDefOf.PlantsHarvested); } } } plant.def.plant.soundHarvestFinish.PlayOneShot(actor); plant.PlantCollected(); workDone = 0f; ReadyForNextToil(); } }; cut.FailOnDespawnedNullOrForbidden(TargetIndex.A); if (RequiredDesignation != null) { cut.FailOnThingMissingDesignation(TargetIndex.A, RequiredDesignation); } cut.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); cut.defaultCompleteMode = ToilCompleteMode.Never; cut.WithEffect(EffecterDefOf.Harvest, TargetIndex.A); cut.WithProgressBar(TargetIndex.A, () => workDone / Plant.def.plant.harvestWork, interpolateBetweenActorAndTarget: true); cut.PlaySustainerOrSound(() => Plant.def.plant.soundHarvesting); cut.activeSkill = () => SkillDefOf.Plants; yield return(cut); Toil toil2 = PlantWorkDoneToil(); if (toil2 != null) { yield return(toil2); } yield return(Toils_Jump.Jump(initExtractTargetFromQueue)); }
private static bool IsSafeDropSpot(IntVec3 cell, Map map, Faction faction, IntVec2?size = null, int distToEdge = 25, int distToHostiles = 35, int distToFires = 15) { Faction factionBaseFaction = map.ParentFaction ?? Faction.OfPlayer; if (size.HasValue) { foreach (IntVec3 item in GenAdj.OccupiedRect(cell, Rot4.North, size.Value)) { if (!IsGoodDropSpot(item, map, allowFogged: false, canRoofPunch: false, allowIndoors: false)) { return(false); } } } else if (!IsGoodDropSpot(cell, map, allowFogged: false, canRoofPunch: false, allowIndoors: false)) { return(false); } if (distToEdge > 0 && cell.CloseToEdge(map, distToEdge)) { return(false); } if (faction != null) { foreach (IAttackTarget item2 in map.attackTargetsCache.TargetsHostileToFaction(faction)) { if (!item2.ThreatDisabled(null) && item2.Thing.Position.InHorDistOf(cell, distToHostiles)) { return(false); } } } if (!map.reachability.CanReachFactionBase(cell, factionBaseFaction)) { return(false); } if (size.HasValue) { foreach (IntVec3 cell2 in CellRect.CenteredOn(cell, size.Value.x, size.Value.z).Cells) { if (CellHasCrops(cell2)) { return(false); } } } else if (CellHasCrops(cell)) { return(false); } float minDistToFiresSq = distToFires * distToFires; float closestDistSq = float.MaxValue; int firesCount = 0; RegionTraverser.BreadthFirstTraverse(cell, map, (Region from, Region to) => true, delegate(Region x) { List <Thing> list = x.ListerThings.ThingsInGroup(ThingRequestGroup.Fire); for (int i = 0; i < list.Count; i++) { float num = cell.DistanceToSquared(list[i].Position); if (!(num > minDistToFiresSq)) { if (num < closestDistSq) { closestDistSq = num; } firesCount++; } } return(closestDistSq <= minDistToFiresSq && firesCount >= 5); }, 15); if (closestDistSq <= minDistToFiresSq && firesCount >= 5) { return(false); } return(true); bool CellHasCrops(IntVec3 c) { Plant plant = c.GetPlant(map); if (plant != null && plant.sown) { return(map.zoneManager.ZoneAt(c) is Zone_Growing); } return(false); } }
public override Job JobOnCell(Pawn pawn, IntVec3 c) { Map map = pawn.Map; if (c.IsForbidden(pawn)) { return(null); } if (!GenPlant.GrowthSeasonNow(c, map)) { return(null); } if (WorkGiver_Grower.wantedPlantDef == null) { WorkGiver_Grower.wantedPlantDef = WorkGiver_Grower.CalculateWantedPlantDef(c, map); if (WorkGiver_Grower.wantedPlantDef == null) { return(null); } } List <Thing> thingList = c.GetThingList(map); bool flag = false; for (int i = 0; i < thingList.Count; i++) { Thing thing = thingList[i]; if (thing.def == WorkGiver_Grower.wantedPlantDef) { return(null); } if ((thing is Blueprint || thing is Frame) && thing.Faction == pawn.Faction) { flag = true; } } if (flag) { Thing edifice = c.GetEdifice(map); if (edifice != null && !(edifice.def.fertility < 0.0)) { goto IL_00dc; } return(null); } goto IL_00dc; IL_00dc: if (WorkGiver_Grower.wantedPlantDef.plant.cavePlant) { if (!c.Roofed(map)) { JobFailReason.Is(WorkGiver_GrowerSow.CantSowCavePlantBecauseUnroofedTrans); return(null); } if (map.glowGrid.GameGlowAt(c, true) > 0.0) { JobFailReason.Is(WorkGiver_GrowerSow.CantSowCavePlantBecauseOfLightTrans); return(null); } } Plant plant = c.GetPlant(map); if (plant != null && plant.def.plant.blockAdjacentSow) { if (pawn.CanReserve(plant, 1, -1, null, false) && !plant.IsForbidden(pawn)) { return(new Job(JobDefOf.CutPlant, plant)); } return(null); } Thing thing2 = GenPlant.AdjacentSowBlocker(WorkGiver_Grower.wantedPlantDef, c, map); if (thing2 != null) { Plant plant2 = thing2 as Plant; if (plant2 != null && pawn.CanReserve(plant2, 1, -1, null, false) && !plant2.IsForbidden(pawn)) { IPlantToGrowSettable plantToGrowSettable = plant2.Position.GetPlantToGrowSettable(plant2.Map); if (plantToGrowSettable != null && plantToGrowSettable.GetPlantDefToGrow() == plant2.def) { goto IL_0211; } return(new Job(JobDefOf.CutPlant, plant2)); } goto IL_0211; } if (WorkGiver_Grower.wantedPlantDef.plant.sowMinSkill > 0 && pawn.skills != null && pawn.skills.GetSkill(SkillDefOf.Growing).Level < WorkGiver_Grower.wantedPlantDef.plant.sowMinSkill) { return(null); } for (int j = 0; j < thingList.Count; j++) { Thing thing3 = thingList[j]; if (thing3.def.BlockPlanting) { if (!pawn.CanReserve(thing3, 1, -1, null, false)) { return(null); } if (thing3.def.category == ThingCategory.Plant) { if (!thing3.IsForbidden(pawn)) { return(new Job(JobDefOf.CutPlant, thing3)); } return(null); } if (thing3.def.EverHaulable) { return(HaulAIUtility.HaulAsideJobFor(pawn, thing3)); } return(null); } } if (WorkGiver_Grower.wantedPlantDef.CanEverPlantAt(c, map) && GenPlant.GrowthSeasonNow(c, map) && pawn.CanReserve(c, 1, -1, null, false)) { Job job = new Job(JobDefOf.Sow, c); job.plantDefToSow = WorkGiver_Grower.wantedPlantDef; return(job); } return(null); IL_0211: return(null); }
protected override IEnumerable <Toil> MakeNewToils() { this.Init(); yield return(Toils_JobTransforms.MoveCurrentTargetIntoQueue(TargetIndex.A)); Toil initExtractTargetFromQueue = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A, (this.RequiredDesignation == null) ? null : new Func <Thing, bool>((Thing t) => this.$this.Map.designationManager.DesignationOn(t, this.$this.RequiredDesignation) != null)); yield return(initExtractTargetFromQueue); yield return(Toils_JobTransforms.SucceedOnNoTargetInQueue(TargetIndex.A)); yield return(Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.A, true)); Toil gotoThing = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIfDespawnedOrNullOrForbidden(TargetIndex.A, initExtractTargetFromQueue); if (this.RequiredDesignation != null) { gotoThing.FailOnThingMissingDesignation(TargetIndex.A, this.RequiredDesignation); } yield return(gotoThing); Toil cut = new Toil(); cut.tickAction = delegate { Pawn actor = cut.actor; if (actor.skills != null) { actor.skills.Learn(SkillDefOf.Plants, this.$this.xpPerTick, false); } float statValue = actor.GetStatValue(StatDefOf.PlantWorkSpeed, true); float num = statValue; Plant plant = this.$this.Plant; num *= Mathf.Lerp(3.3f, 1f, plant.Growth); this.$this.workDone += num; if (this.$this.workDone >= plant.def.plant.harvestWork) { if (plant.def.plant.harvestedThingDef != null) { if (actor.RaceProps.Humanlike && plant.def.plant.harvestFailable && Rand.Value > actor.GetStatValue(StatDefOf.PlantHarvestYield, true)) { Vector3 loc = (this.$this.pawn.DrawPos + plant.DrawPos) / 2f; MoteMaker.ThrowText(loc, this.$this.Map, "TextMote_HarvestFailed".Translate(), 3.65f); } else { int num2 = plant.YieldNow(); if (num2 > 0) { Thing thing = ThingMaker.MakeThing(plant.def.plant.harvestedThingDef, null); thing.stackCount = num2; if (actor.Faction != Faction.OfPlayer) { thing.SetForbidden(true, true); } GenPlace.TryPlaceThing(thing, actor.Position, this.$this.Map, ThingPlaceMode.Near, null, null); actor.records.Increment(RecordDefOf.PlantsHarvested); } } } plant.def.plant.soundHarvestFinish.PlayOneShot(actor); plant.PlantCollected(); this.$this.workDone = 0f; this.$this.ReadyForNextToil(); return; } }; cut.FailOnDespawnedNullOrForbidden(TargetIndex.A); if (this.RequiredDesignation != null) { cut.FailOnThingMissingDesignation(TargetIndex.A, this.RequiredDesignation); } cut.FailOnCannotTouch(TargetIndex.A, PathEndMode.Touch); cut.defaultCompleteMode = ToilCompleteMode.Never; cut.WithEffect(EffecterDefOf.Harvest, TargetIndex.A); cut.WithProgressBar(TargetIndex.A, () => this.$this.workDone / this.$this.Plant.def.plant.harvestWork, true, -0.5f); cut.PlaySustainerOrSound(() => this.$this.Plant.def.plant.soundHarvesting); cut.activeSkill = (() => SkillDefOf.Plants); yield return(cut); Toil plantWorkDoneToil = this.PlantWorkDoneToil(); if (plantWorkDoneToil != null) { yield return(plantWorkDoneToil); } yield return(Toils_Jump.Jump(initExtractTargetFromQueue)); }
protected override IEnumerable <Toil> MakeNewToils() { Toil meditate = new Toil { socialMode = RandomSocialMode.Off }; if (FromBed) { this.KeepLyingDown(TargetIndex.B); meditate = Toils_LayDown.LayDown(TargetIndex.B, job.GetTarget(TargetIndex.B).Thing is Building_Bed, lookForOtherJobs: false, canSleep: false); } else { yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.OnCell)); meditate.initAction = delegate { LocalTargetInfo target = job.GetTarget(TargetIndex.C); if (target.IsValid) { faceDir = target.Cell - pawn.Position; } else { faceDir = (job.def.faceDir.IsValid ? job.def.faceDir : Rot4.Random).FacingCell; } }; if (Focus != null) { meditate.FailOnDespawnedNullOrForbidden(TargetIndex.C); } meditate.handlingFacing = true; } meditate.defaultCompleteMode = ToilCompleteMode.Delay; meditate.defaultDuration = job.def.joyDuration; meditate.FailOn(() => !MeditationUtility.CanMeditateNow(pawn) || !MeditationUtility.SafeEnvironmentalConditions(pawn, base.TargetLocA, base.Map)); meditate.AddPreTickAction(delegate { if (faceDir.IsValid && !FromBed) { pawn.rotationTracker.FaceCell(pawn.Position + faceDir); } pawn.GainComfortFromCellIfPossible(); MeditationTick(); if (ModLister.RoyaltyInstalled && MeditationFocusDefOf.Natural.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 == ThingDefOf.Plant_TreeAnima) { plant.TryGetComp <CompSpawnSubplant>()?.AddProgress(AnimaTreeSubplantProgressPerTick); } } } } }); meditate.AddFinishAction(delegate { if (sustainer != null) { sustainer.End(); } }); yield return(meditate); }
public override void TickRare() { base.TickRare(); this.SpreadTick--; if (this.growthPercent >= 1) { //check things in cell and react CheckThings(Position); } if (this.SpreadTick == 0) { //Pick a random direction cell IntVec3 dir = new IntVec3(); dir = GenAdj.RandomAdjSquareCardinal(Position); //If in bounds if (dir.InBounds()) { //If we find a tasty floor lets eat it nomnomnom TerrainDef terrain = dir.GetTerrain(); if (terrain != null) { //Only eat floor if not natural if (terrain.defName != "Sand" && terrain.defName != "Soil" && terrain.defName != "MarshyTerrain" && terrain.defName != "SoilRich" && terrain.defName != "Mud" && terrain.defName != "Marsh" && terrain.defName != "Gravel" && terrain.defName != "RoughStone" && terrain.defName != "WaterDeep" && terrain.defName != "WaterShallow" && terrain.defName != "RoughHewnRock") { //And by eat i mean replace - TODO can you damage floors over time? //Replace with soil - TODO for now, maybe change to regen tile later if possible Find.TerrainGrid.SetTerrain(dir, TerrainDef.Named("Soil")); //if theres no ivy here if (!IvyInCell(dir)) { if (dir.GetPlant() == null) { //no plant, move on } else { //Found plant, Kill it Plant plant = dir.GetPlant(); plant.Destroy(); } //Spawn more Ivy SpawnIvy(dir); } } //Its natural floor else if (terrain.defName != "WaterDeep" && terrain.defName != "WaterShallow" && terrain.defName != "MarshyTerrain") { //if theres no ivy here if (!IvyInCell(dir)) { if (dir.GetPlant() == null) { //no plant, move on } else { //Found plant, Kill it Plant plant = dir.GetPlant(); plant.Destroy(); } //Spawn more Ivy SpawnIvy(dir); } } //its water or something I dont know of else { } } } SpreadTick = OrigSpreadTick; } if (this.MutateTry == true) { Random random = new Random(); int MutateRate = random.Next(1, 200); if (MutateRate == 3 || MutateRate == 23) { Building_GasPump GasPump = (Building_GasPump)ThingMaker.MakeThing(ThingDef.Named("GasPump")); GasPump.SetFactionDirect(factionDirect); if (hasNoBuildings(Position)) { GenSpawn.Spawn(GasPump, Position); } this.MutateTry = false; //Find.History.AddGameEvent("Gas here", GameEventType.BadNonUrgent, true, Position, string.Empty); } else if (MutateRate == 4 || MutateRate == 24) { Building_EggSac EggSac = (Building_EggSac)ThingMaker.MakeThing(ThingDef.Named("EggSac")); EggSac.SetFactionDirect(factionDirect); if (hasNoBuildings(Position)) { GenSpawn.Spawn(EggSac, Position); } this.MutateTry = false; //Find.History.AddGameEvent("Egg here", GameEventType.BadNonUrgent, true, Position, string.Empty); } else if (MutateRate == 5) { Building_Turret GenMortar = (Building_Turret)ThingMaker.MakeThing(ThingDef.Named("Turret_GenMortarSeed")); GenMortar.SetFactionDirect(factionDirect); if (hasNoBuildings(Position)) { GenSpawn.Spawn(GenMortar, Position); } this.MutateTry = false; //Find.History.AddGameEvent("Mortar here", GameEventType.BadNonUrgent, true, Position, string.Empty); } else if (MutateRate == 6) { Building_Turret GenTurret = (Building_Turret)ThingMaker.MakeThing(ThingDef.Named("GenTurretBase")); GenTurret.SetFactionDirect(factionDirect); if (hasNoBuildings(Position)) { GenSpawn.Spawn(GenTurret, Position); } this.MutateTry = false; //Find.History.AddGameEvent("Turret here", GameEventType.BadNonUrgent, true, Position, string.Empty); } else { this.MutateTry = false; } } if (stuckPawn != null) { int damageAmountBase = 1; DamageInfo damageInfo = new DamageInfo(this.dmgdef, damageAmountBase, this, null, null); stuckPawn.TakeDamage(damageInfo); stuckPawn = null; } if (stuckCorpse != null) { stuckCorpse.Destroy(); stuckCorpse = null; } }
public static Thing BestFoodSourceOnMap(Pawn getter, Pawn eater, bool desperate, out ThingDef foodDef, FoodPreferability maxPref = FoodPreferability.MealLavish, bool allowPlant = true, bool allowDrug = true, bool allowCorpse = true, bool allowDispenserFull = true, bool allowDispenserEmpty = true, bool allowForbidden = false, bool allowSociallyImproper = false, bool allowHarvest = false, bool forceScanWholeMap = false) { foodDef = null; bool getterCanManipulate = getter.RaceProps.ToolUser && getter.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation); if (!getterCanManipulate && getter != eater) { Log.Error(getter + " tried to find food to bring to " + eater + " but " + getter + " is incapable of Manipulation."); return(null); } FoodPreferability minPref; if (eater.NonHumanlikeOrWildMan()) { minPref = FoodPreferability.NeverForNutrition; } else if (desperate) { minPref = FoodPreferability.DesperateOnly; } else { minPref = (((int)eater.needs.food.CurCategory < 2) ? FoodPreferability.MealAwful : FoodPreferability.RawBad); } Predicate <Thing> foodValidator = delegate(Thing t) { Building_NutrientPasteDispenser building_NutrientPasteDispenser = t as Building_NutrientPasteDispenser; if (building_NutrientPasteDispenser != null) { if (!allowDispenserFull || !getterCanManipulate || (int)ThingDefOf.MealNutrientPaste.ingestible.preferability < (int)minPref || (int)ThingDefOf.MealNutrientPaste.ingestible.preferability > (int)maxPref || !eater.WillEat(ThingDefOf.MealNutrientPaste, getter) || (t.Faction != getter.Faction && t.Faction != getter.HostFaction) || (!allowForbidden && t.IsForbidden(getter)) || !building_NutrientPasteDispenser.powerComp.PowerOn || (!allowDispenserEmpty && !building_NutrientPasteDispenser.HasEnoughFeedstockInHoppers()) || !t.InteractionCell.Standable(t.Map) || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || getter.IsWildMan() || !getter.Map.reachability.CanReachNonLocal(getter.Position, new TargetInfo(t.InteractionCell, t.Map), PathEndMode.OnCell, TraverseParms.For(getter, Danger.Some))) { return(false); } } else if ((int)t.def.ingestible.preferability < (int)minPref || (int)t.def.ingestible.preferability > (int)maxPref || !eater.WillEat(t, getter) || !t.def.IsNutritionGivingIngestible || !t.IngestibleNow || (!allowCorpse && t is Corpse) || (!allowDrug && t.def.IsDrug) || (!allowForbidden && t.IsForbidden(getter)) || (!desperate && t.IsNotFresh()) || t.IsDessicated() || !IsFoodSourceOnMapSociallyProper(t, getter, eater, allowSociallyImproper) || (!getter.AnimalAwareOf(t) && !forceScanWholeMap) || !getter.CanReserve(t)) { return(false); } return(true); }; ThingRequest thingRequest = ((eater.RaceProps.foodType & (FoodTypeFlags.Plant | FoodTypeFlags.Tree)) == FoodTypeFlags.None || !allowPlant) ? ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree) : ThingRequest.ForGroup(ThingRequestGroup.FoodSource); Thing bestThing; if (getter.RaceProps.Humanlike) { Pawn eater2 = eater; IntVec3 position = getter.Position; List <Thing> searchSet = getter.Map.listerThings.ThingsMatching(thingRequest); PathEndMode peMode = PathEndMode.ClosestTouch; TraverseParms traverseParams = TraverseParms.For(getter); Predicate <Thing> validator = foodValidator; bestThing = SpawnedFoodSearchInnerScan(eater2, position, searchSet, peMode, traverseParams, 9999f, validator); if (allowHarvest && getterCanManipulate) { Thing thing = GenClosest.ClosestThingReachable(searchRegionsMax : (!forceScanWholeMap || bestThing != null) ? 30 : (-1), root : getter.Position, map : getter.Map, thingReq : ThingRequest.ForGroup(ThingRequestGroup.HarvestablePlant), peMode : PathEndMode.Touch, traverseParams : TraverseParms.For(getter), maxDistance : 9999f, validator : delegate(Thing x) { Plant plant = (Plant)x; if (!plant.HarvestableNow) { return(false); } ThingDef harvestedThingDef = plant.def.plant.harvestedThingDef; if (!harvestedThingDef.IsNutritionGivingIngestible) { return(false); } if (!eater.WillEat(harvestedThingDef, getter)) { return(false); } if (!getter.CanReserve(plant)) { return(false); } if (!allowForbidden && plant.IsForbidden(getter)) { return(false); } if (bestThing != null && (int)GetFinalIngestibleDef(bestThing).ingestible.preferability >= (int)harvestedThingDef.ingestible.preferability) { return(false); } return(true); }); if (thing != null) { bestThing = thing; foodDef = GetFinalIngestibleDef(thing, harvest: true); } } if (foodDef == null && bestThing != null) { foodDef = GetFinalIngestibleDef(bestThing); } } else { int maxRegionsToScan = GetMaxRegionsToScan(getter, forceScanWholeMap); filtered.Clear(); foreach (Thing item in GenRadial.RadialDistinctThingsAround(getter.Position, getter.Map, 2f, useCenter: true)) { Pawn pawn = item as Pawn; if (pawn != null && pawn != getter && pawn.RaceProps.Animal && pawn.CurJob != null && pawn.CurJob.def == JobDefOf.Ingest && pawn.CurJob.GetTarget(TargetIndex.A).HasThing) { filtered.Add(pawn.CurJob.GetTarget(TargetIndex.A).Thing); } } bool flag = !allowForbidden && ForbidUtility.CaresAboutForbidden(getter, cellTarget: true) && getter.playerSettings != null && getter.playerSettings.EffectiveAreaRestrictionInPawnCurrentMap != null; Predicate <Thing> predicate = delegate(Thing t) { if (!foodValidator(t)) { return(false); } if (filtered.Contains(t)) { return(false); } if (!(t is Building_NutrientPasteDispenser) && (int)t.def.ingestible.preferability <= 2) { return(false); } if (t.IsNotFresh()) { return(false); } return(true); }; IntVec3 position = getter.Position; Map map = getter.Map; ThingRequest thingReq = thingRequest; PathEndMode peMode = PathEndMode.ClosestTouch; TraverseParms traverseParams = TraverseParms.For(getter); Predicate <Thing> validator = predicate; bool ignoreEntirelyForbiddenRegions = flag; bestThing = GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, 9999f, validator, null, 0, maxRegionsToScan, forceGlobalSearch: false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); filtered.Clear(); if (bestThing == null) { desperate = true; position = getter.Position; map = getter.Map; thingReq = thingRequest; peMode = PathEndMode.ClosestTouch; traverseParams = TraverseParms.For(getter); validator = foodValidator; ignoreEntirelyForbiddenRegions = flag; bestThing = GenClosest.ClosestThingReachable(position, map, thingReq, peMode, traverseParams, 9999f, validator, null, 0, maxRegionsToScan, forceGlobalSearch: false, RegionType.Set_Passable, ignoreEntirelyForbiddenRegions); } if (bestThing != null) { foodDef = GetFinalIngestibleDef(bestThing); } } return(bestThing); }