protected override bool AllowResourceAt(string resourceType, CPos cell) { if (!Map.Contains(cell)) { return(false); } // Resources are allowed on flat terrain and cardinal slopes if (Map.Ramp[cell] > 4) { return(false); } if (!info.ResourceTypes.TryGetValue(resourceType, out var resourceInfo)) { return(false); } if (!resourceInfo.AllowedTerrainTypes.Contains(Map.GetTerrainInfo(cell).Type)) { return(false); } // Ensure there is space for the vein border tiles (not needed on ramps) var check = resourceType == info.VeinType ? (Func <CPos, CPos, bool>)IsValidVeinNeighbour : IsValidResourceNeighbour; var blockedByNeighbours = Map.Ramp[cell] == 0 && !Common.Util.ExpandFootprint(cell, false).All(c => check(cell, c)); return(!blockedByNeighbours && (resourceType == info.VeinType || !BuildingInfluence.AnyBuildingAt(cell))); }
CPos?ChooseBuildLocation(string actorType, bool distanceToBaseIsImportant, BuildingType type) { var actorInfo = world.Map.Rules.Actors[actorType]; var buildingInfo = actorInfo.TraitInfoOrDefault <BuildingInfo>(); if (buildingInfo == null) { return(null); } // Find the buildable cell that is closest to pos and centered around center Func <CPos, CPos, int, int, CPos?> findPos = (center, target, minRange, maxRange) => { var cells = world.Map.FindTilesInAnnulus(center, minRange, maxRange); // Sort by distance to target if we have one if (center != target) { cells = cells.OrderBy(c => (c - target).LengthSquared); } else { cells = cells.Shuffle(world.LocalRandom); } foreach (var cell in cells) { if (!world.CanPlaceBuilding(cell, actorInfo, buildingInfo, null)) { continue; } foreach (var adjacent in CVec.Directions) { var adjacentCell = cell + adjacent; // Don't clutter the base if (buildingInfluence.AnyBuildingAt(adjacentCell)) { continue; } // Don't block of resources if (resourceLayer.GetResource(adjacentCell).Density > 0) { continue; } } if (distanceToBaseIsImportant && !buildingInfo.IsCloseEnoughToBase(world, player, actorInfo, cell)) { continue; } return(cell); } return(null); }; var baseCenter = baseBuilder.GetRandomBaseCenter(); switch (type) { case BuildingType.Defense: // Build near the closest enemy structure var closestEnemy = world.ActorsHavingTrait <Building>().Where(a => !a.Disposed && player.RelationshipWith(a.Owner) == PlayerRelationship.Enemy) .ClosestTo(world.Map.CenterOfCell(baseBuilder.DefenseCenter)); var targetCell = closestEnemy != null ? closestEnemy.Location : baseCenter; return(findPos(baseBuilder.DefenseCenter, targetCell, baseBuilder.Info.MinimumDefenseRadius, baseBuilder.Info.MaximumDefenseRadius)); case BuildingType.Refinery: case BuildingType.Building: return(findPos(baseCenter, baseCenter, baseBuilder.Info.MinBaseRadius, distanceToBaseIsImportant ? baseBuilder.Info.MaxBaseRadius : world.Map.Grid.MaximumTileSearchRange)); } // Can't find a build location return(null); }