/// <summary> /// Try to get a valid cell to spawn a new cluster away from plant. /// </summary> public static void TryGetRandomSpawnCellAwayFromCluster(Cluster cluster, int newDesiredClusterSize, out IntVec3 spawnCell) { spawnCell = IntVec3.Invalid; float newClusterExclusivityRadius = Cluster.GetExclusivityRadius(cluster.plantDef, newDesiredClusterSize); //Log.Message("newCluster size/ExclusivityRadius = " + newClusterSize + "/" + newClusterExclusivityRadius); // Current cluster and new cluster zones are exclusive and should not overlap. float newClusterMinDistance = cluster.exclusivityRadius + newClusterExclusivityRadius; float newClusterMaxDistance = 2f * newClusterMinDistance; //Log.Message("newClusterMinDistance/newClusterMaxDistance = " + newClusterMinDistance + "/" + newClusterMaxDistance); Predicate<IntVec3> validator = delegate(IntVec3 cell) { // Check cell is not too close from current cluster. if (cell.InHorDistOf(cluster.Position, newClusterMinDistance)) { return false; } //Log.Message("not too close"); // Check cell is not too distant from current cluster. if (cell.InHorDistOf(cluster.Position, newClusterMaxDistance) == false) { return false; } //Log.Message("not too distant"); // Check cell is in the same room. if (cell.GetRoom() != cluster.GetRoom()) { return false; } // Check a plant can be spawned here. if (IsValidPositionToGrowPlant(cluster.plantDef, cell) == false) { return false; } //Log.Message("IsValidPositionToSpawnPlant OK"); // Check there is no third cluster nearby. if (IsClusterAreaClear(cluster.plantDef, newDesiredClusterSize, cell) == false) { return false; } return true; }; bool validCellIsFound = CellFinder.TryFindRandomCellNear(cluster.Position, (int)newClusterMaxDistance, validator, out spawnCell); if (validCellIsFound == false) { // Note that TryFindRandomCellNear set result to root if no valid cell is found! spawnCell = IntVec3.Invalid; } }
public static ClusterPlant TryToSpawnNewSymbiosisCluster(Cluster cluster) { // Check there is not already a symbiosis cluster. if (cluster.symbiosisCluster == null) { foreach (IntVec3 cell in GenRadial.RadialCellsAround(cluster.Position, cluster.plantDef.clusterSpawnRadius, false).InRandomOrder()) { if (cell.InBounds() == false) { continue; } ClusterPlant plant = cell.GetFirstThing(cluster.plantDef) as ClusterPlant; if (plant != null) { plant.Destroy(); ClusterPlant symbiosisPlant = Cluster.SpawnNewClusterAt(cell, cluster.plantDef.symbiosisPlantDefEvolution, cluster.plantDef.symbiosisPlantDefEvolution.clusterSizeRange.RandomInRange); cluster.NotifySymbiosisClusterAdded(symbiosisPlant.cluster); return symbiosisPlant; } } } return null; }
/// <summary> /// Try to spawn a new cluster away from plant. /// </summary> public static ClusterPlant TrySpawnNewClusterAwayFrom(Cluster cluster) { //Log.Message("TrySpawnNewClusterAwayFrom"); IntVec3 spawnCell = IntVec3.Invalid; int newDesiredClusterSize = cluster.plantDef.clusterSizeRange.RandomInRange; TryGetRandomSpawnCellAwayFromCluster(cluster, newDesiredClusterSize, out spawnCell); if (spawnCell.IsValid) { return Cluster.SpawnNewClusterAt(spawnCell, cluster.plantDef, newDesiredClusterSize); } else { return null; } }
/// <summary> /// Get a valid cell in this cluster to spawn another cave plant. /// </summary> public static void TryGetRandomSpawnCellNearCluster(Cluster cluster, out IntVec3 spawnCell) { spawnCell = IntVec3.Invalid; float maxSpawnDistance = GenRadial.RadiusOfNumCells(cluster.actualSize + 1); // Min radius to hold cluster's plants + new plant. //Log.Message("Cluster at " + clusterCenter.ToString() + ": actualClusterSize/desiredClusterSize => maxSpawnDistance " + actualClusterSize + "/" + desiredClusterSize + " => " + maxSpawnDistance); maxSpawnDistance += 2f; // Add a margin so the cluster does not have a perfect circle shape. /* = plantDef.clusterSpawnRadius; if (plantDef.clusterSizeRange.max > plantDef.clusterSizeRange.min) { maxSpawnDistance *= clusterMaturity; maxSpawnDistance = Math.Max(2f, maxSpawnDistance); } Log.Message("maxSpawnDistance at " + clusterCenter.ToString() + ": maturity/maxSpawnDistance => " + clusterMaturity + "/" + maxSpawnDistance);*/ Predicate<IntVec3> validator = delegate(IntVec3 cell) { // Check cell is not too far away from current cluster. if (cell.InHorDistOf(cluster.Position, maxSpawnDistance) == false) { return false; } // Check cell is in the same room. if (cell.GetRoom() != cluster.GetRoom()) { return false; } return IsValidPositionToGrowPlant(cluster.plantDef, cell); }; bool validCellIsFound = CellFinder.TryFindRandomCellNear(cluster.Position, (int)maxSpawnDistance, validator, out spawnCell); if (validCellIsFound == false) { // Note that TryFindRandomCellNear set result to root if no valid cell is found! spawnCell = IntVec3.Invalid; } }
/// <summary> /// Get the center of a cluster and its actual size. /// </summary> /*public static void GetClusterCenterAndActualSize(ClusterPlant plant, out IntVec3 clusterCenter, out int actualClusterSize) { // Default values. clusterCenter = plant.Position; actualClusterSize = 1; if (plant.desiredClusterSize == 1) { return; } else { clusterCenter = IntVec3.Zero; actualClusterSize = 0; Room plantRoom = plant.Position.GetRoom(); // We only check with clusterSpawnRadius (+ a small offset). No need to check entire cluster exclusivity area. IEnumerable<IntVec3> cellsInCluster = GenRadial.RadialCellsAround(plant.Position, plant.clusterPlantProps.clusterSpawnRadius + 3f, true); foreach (IntVec3 cell in cellsInCluster) { if ((cell.GetRoom() == plantRoom) && (Find.ThingGrid.ThingAt(cell, plant.def) != null)) { actualClusterSize++; clusterCenter += cell; } } clusterCenter.x = (int)Mathf.Round(clusterCenter.x / (float)actualClusterSize); clusterCenter.z = (int)Mathf.Round(clusterCenter.z / (float)actualClusterSize); if (clusterCenter.x < 0) { clusterCenter.x = 0; } else if (clusterCenter.x > Find.Map.Size.x) { clusterCenter.x = Find.Map.Size.x; } if (clusterCenter.z < 0) { clusterCenter.z = 0; } else if (clusterCenter.z > Find.Map.Size.z) { clusterCenter.z = Find.Map.Size.z; } //Log.Message("GetClusterActualSizeAndCenter: " + plant.Position.ToString() + "/" + clusterActualSize + "/" + clusterCenter); } }*/ /// <summary> /// Try to spawn another plant in this cluster. /// </summary> public static ClusterPlant TryGrowCluster(Cluster cluster) { IntVec3 spawnCell = IntVec3.Invalid; TryGetRandomSpawnCellNearCluster(cluster, out spawnCell); if (spawnCell.IsValid) { ClusterPlant newPlant = ThingMaker.MakeThing(cluster.plantDef) as ClusterPlant; GenSpawn.Spawn(newPlant, spawnCell); newPlant.cluster = cluster; cluster.NotifyPlantAdded(); if (cluster.plantDef.isSymbiosisPlant) { // Destroy source symbiosis plant. Thing sourceSymbiosisPlant = spawnCell.GetFirstThing(cluster.plantDef.symbiosisPlantDefSource); if (sourceSymbiosisPlant != null) { sourceSymbiosisPlant.Destroy(); } } return newPlant; } else { return null; } }
public void NotifySymbiosisClusterRemoved(Cluster symbiosisCluster) { this.symbiosisCluster = null; symbiosisCluster.symbiosisCluster = null; }
public void NotifySymbiosisClusterAdded(Cluster symbiosisCluster) { this.symbiosisCluster = symbiosisCluster; symbiosisCluster.symbiosisCluster = this; }