private void GenerateRooms(SettlementLayoutDef sld, Map map, ResolveParams rp) { List <StructureLayoutDef> authorizedLayouts = DefDatabase <StructureLayoutDef> .AllDefsListForReading.FindAll(s => s.tags.Any(t => sld.allowedTags.Contains(t))); Log.Message(authorizedLayouts.Count + " auhtorized layouts."); map.terrainGrid.SetTerrain(rp.rect.Last(), TerrainDefOf.Bridge); }
private void GenerateRooms(SettlementLayoutDef sld, Map map, ResolveParams rp) { int seed = new Random().Next(0, 100000); CGO.offset = rp.rect.Corners.ElementAt(2); CGO.grid = GridUtils.GenerateGrid(seed, sld, map); BaseGen.symbolStack.Push("kcsg_roomgenfromlist", rp, null); }
public override void Resolve(ResolveParams rp) { Map map = BaseGen.globalSettings.map; SettlementLayoutDef lDef = FactionSettlement.temp; List <CellRect> gridRects = FactionSettlement.tempRectList; if (VFECore.VFEGlobal.settings.enableLog) { Log.Message("KCSG_RoomGen generating " + lDef.defName.ToString()); } int count = 0; foreach (string str in lDef.roomLayout) { if (str != ".") { StructureLayoutDef rld = DefDatabase <StructureLayoutDef> .GetNamed(str); KCSG_Utilities.FillCellThingsList(gridRects[count].Cells.ToList(), map, pairsCellThingList); foreach (List <String> item in rld.layouts) { KCSG_Utilities.GenerateRoomFromLayout(item, gridRects[count], map, rld); } if (rld.isStockpile) { KCSG_Utilities.FillStockpileRoom(rld, gridRects[count], map); } } count++; } ThingDef conduit; if (LoadedModManager.RunningMods.ToList().FindAll(m => m.Name == "Subsurface Conduit").Count > 0) { conduit = DefDatabase <ThingDef> .AllDefsListForReading.FindAll(d => d.defName == "MUR_SubsurfaceConduit").First(); } else { conduit = ThingDefOf.PowerConduit; } KCSG_Utilities.EnsureBatteriesConnectedAndMakeSense(map, tmpThings, tmpPowerNetPredicateResults, tmpCells, conduit); KCSG_Utilities.EnsurePowerUsersConnected(map, tmpThings, tmpPowerNetPredicateResults, tmpCells, conduit); KCSG_Utilities.EnsureGeneratorsConnectedAndMakeSense(map, tmpThings, tmpPowerNetPredicateResults, tmpCells, conduit); }
public override void Resolve(ResolveParams rp) { Map map = BaseGen.globalSettings.map; Faction faction = rp.faction ?? Find.FactionManager.RandomEnemyFaction(false, false, true, TechLevel.Undefined); if (FactionSettlement.tempUseStructureLayout) { this.AddHostilePawnGroup(faction, map, rp); ResolveParams usl_rp = rp; usl_rp.faction = faction; BaseGen.symbolStack.Push("kcsg_roomsgenfromstructure", usl_rp, null); this.PreClean(map, false, rp); } else { SettlementLayoutDef sld = DefDatabase <SettlementLayoutDef> .GetNamed(FactionSettlement.temp); this.PreClean(map, true, rp); if (sld.pathThing != null) { ResolveParams sld_rp_1 = rp; sld_rp_1.floorDef = sld.pathThing; sld_rp_1.allowBridgeOnAnyImpassableTerrain = true; BaseGen.symbolStack.Push("floor", sld_rp_1, null); } this.GenerateRooms(sld, map, rp); if (sld.vanillaLikeDefense) { int dWidth = (Rand.Bool ? 2 : 4); ResolveParams rp3 = rp; rp3.rect = new CellRect(rp.rect.minX - dWidth, rp.rect.minZ - dWidth, rp.rect.Width + (dWidth * 2), rp.rect.Height + (dWidth * 2)); rp3.faction = faction; rp3.edgeDefenseWidth = dWidth; rp3.edgeThingMustReachMapEdge = new bool?(rp.edgeThingMustReachMapEdge ?? true); BaseGen.symbolStack.Push("edgeDefense", rp3, null); } this.AddHostilePawnGroup(faction, map, rp); } }
public static List <CustomVector> Run(SettlementLayoutDef sld, CustomVector[][] grid, int maxTries) { CGO.vectStruct = new Dictionary <CustomVector, StructureLayoutDef>(); Dictionary <string, int> structCount = new Dictionary <string, int>(); List <CustomVector> doors = new List <CustomVector>(); foreach (CustomVector vector in CGO.vectors.ListFullCopy()) { for (int i = 0; i < maxTries; i++) { sld.allowedStructuresConverted.TryRandomElementByWeight(p => GetWeight(p, structCount), out StructOption option); List <StructureLayoutDef> all = DefDatabase <StructureLayoutDef> .AllDefsListForReading.FindAll(s => s.tags.Contains(option.structureLayoutTag)); StructureLayoutDef b = LayoutUtils.ChooseLayoutFrom(all); if (CanPlaceAt(vector, b, grid)) { CGO.vectStruct.Add(vector, b); doors.AddRange(PlaceAt(vector, b, grid)); if (structCount.ContainsKey(option.structureLayoutTag)) { structCount[option.structureLayoutTag]++; } else { structCount.Add(option.structureLayoutTag, 1); } CGO.vectors.Remove(vector); break; } } } return(doors); }
/// <summary> /// Generate a grid, add the preexisting vanilla road if needed. Add main roads. Fill the potential point list, add buildings on grid and fill the origin/layout dictionnary /// </summary> /// <param name="seed">Seed for Random</param> /// <param name="sld">SettlementLayoutDef to get all StructureLayoutDef authorized</param> /// <param name="map">The map</param> /// <returns></returns> public static CustomVector[][] GenerateGrid(int seed, SettlementLayoutDef sld, Map map) { CGO.currentGenStepMoreInfo = "Generating grid and main road"; int mapWidth = Math.Min(map.Size.x, sld.settlementSize.x), mapHeight = Math.Min(map.Size.z, sld.settlementSize.z); // Search for the smallest sized allowed structure. It will be the radius between potential building spawn points CGO.radius = 9999; for (int i = 0; i < sld.allowedStructures.Count; i++) { foreach (StructureLayoutDef item in DefDatabase <StructureLayoutDef> .AllDefsListForReading.FindAll(s => s.tags.Contains(sld.allowedStructuresConverted[i].structureLayoutTag))) { RectUtils.HeightWidthFromLayout(item, out int height, out int width); if (height < CGO.radius) { CGO.radius = height; } if (width < CGO.radius) { CGO.radius = width; } } } CGO.radius += 2; // Add to radius to ensure no building touch one another // Initialize the grid used for generation Random r = new Random(seed); CustomVector[][] grid = new CustomVector[mapWidth][]; for (int i = 0; i < mapWidth; i++) { grid[i] = new CustomVector[mapHeight]; for (int j = 0; j < mapHeight; j++) { grid[i][j] = new CustomVector(i, j); } } // Exclude non bridgeable cells for (int i = 0; i < mapWidth; i++) { for (int j = 0; j < mapHeight; j++) { TerrainDef t = map.terrainGrid.TerrainAt(new IntVec3(CGO.offset.x + i, 0, CGO.offset.y + j)); if (t.HasTag("Water") && (t.affordances == null || !t.affordances.Contains(TerrainAffordanceDefOf.Bridgeable))) { grid[i][j].Type = CellType.WATER; } } } // Main roads CGO.usePathCostReduction = false; // No path cost reduction for main road, for them to be distinct DrawXMainRoad(grid, mapWidth, mapHeight, 15, r); DrawYMainRoad(grid, mapWidth, mapHeight, 15, r); // If bigger sized settlement, add more main roads for (int i = 0; i < mapWidth / 100; i++) { if (i == 0) { DrawXMainRoad(grid, mapWidth, mapHeight, mapWidth / 2, r); DrawYMainRoad(grid, mapWidth, mapHeight, mapHeight / 2, r); } else { DrawXMainRoad(grid, mapWidth, mapHeight, 50, r); DrawYMainRoad(grid, mapWidth, mapHeight, 50, r); } } // Get vanilla world road type and use it if present if (CGO.preRoadTypes?.Count > 0) { for (int i = 0; i < mapWidth; i++) { for (int j = 0; j < mapHeight; j++) { TerrainDef t = map.terrainGrid.TerrainAt(new IntVec3(CGO.offset.x + i, 0, CGO.offset.y + j)); if (CGO.preRoadTypes.Contains(t)) { grid[i][j].Type = CellType.MAINROAD; // Add vanilla generated road to the grid } } } } CGO.usePathCostReduction = true; // Renable path cost reduction CGO.vectors = PoissonDiskSampling.Run(50, mapWidth, mapHeight, r, grid); // Get all possible points with radius CGO.doors = BuildingPlacement.Run(sld, grid, 50); // Place buildings on grid and add them/their origin into vectStruct return(grid); }
public static void Generate(Map map, IntVec3 c, FactionSettlement sf, string symbolResolver = "kcsg_settlement") { FactionSettlement.tempUseStructureLayout = sf.useStructureLayout; string sld; if (!sf.useStructureLayout) { sld = sf.chooseFromSettlements.RandomElement().defName; } else { if (ModLister.RoyaltyInstalled) { sld = sf.chooseFromlayouts.RandomElement().defName; } else { sld = sf.chooseFromlayouts.ToList().FindAll(sfl => !sfl.requireRoyalty).RandomElement().defName; } } FactionSettlement.temp = sld; // Get faction Faction faction; if (map.ParentFaction == null || map.ParentFaction == Faction.OfPlayer) { faction = Find.FactionManager.RandomEnemyFaction(false, false, true, TechLevel.Undefined); } else { faction = map.ParentFaction; } // Get settlement size int width; int height; if (sf.useStructureLayout) { KCSG_Utilities.HeightWidthFromLayout(DefDatabase <StructureLayoutDef> .GetNamed(sld), out height, out width); } else { SettlementLayoutDef temp = DefDatabase <SettlementLayoutDef> .GetNamed(sld); height = temp.settlementSize.x; width = temp.settlementSize.z; } CellRect rect = new CellRect(c.x - width / 2, c.z - height / 2, width, height); rect.ClipInsideMap(map); ResolveParams rp = default(ResolveParams); rp.faction = faction; rp.rect = rect; BaseGen.globalSettings.map = map; BaseGen.symbolStack.Push(symbolResolver, rp, null); BaseGen.Generate(); }
public override void Resolve(ResolveParams rp) { Map map = BaseGen.globalSettings.map; Faction faction = rp.faction ?? Find.FactionManager.RandomEnemyFaction(false, false, true, TechLevel.Undefined); SettlementLayoutDef lDef = FactionSettlement.temp; List <CellRect> gridRects = KCSG_Utilities.GetRects(rp.rect, lDef, map, out rp.rect); FactionSettlement.tempRectList = gridRects; if (VFECore.VFEGlobal.settings.enableLog) { Log.Message("Hostile pawns generation - PASS"); } // Add pawn to the base Lord singlePawnLord = rp.singlePawnLord ?? LordMaker.MakeNewLord(faction, new LordJob_DefendBase(faction, rp.rect.CenterCell), map, null); TraverseParms traverseParms = TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false); ResolveParams resolveParams = rp; resolveParams.rect = rp.rect; resolveParams.faction = faction; resolveParams.singlePawnLord = singlePawnLord; resolveParams.pawnGroupKindDef = (rp.pawnGroupKindDef ?? PawnGroupKindDefOf.Settlement); resolveParams.singlePawnSpawnCellExtraPredicate = (rp.singlePawnSpawnCellExtraPredicate ?? ((IntVec3 x) => map.reachability.CanReachMapEdge(x, traverseParms))); if (resolveParams.pawnGroupMakerParams == null && faction.def.pawnGroupMakers.Any(pgm => pgm.kindDef == PawnGroupKindDefOf.Settlement)) { resolveParams.pawnGroupMakerParams = new PawnGroupMakerParms(); resolveParams.pawnGroupMakerParams.tile = map.Tile; resolveParams.pawnGroupMakerParams.faction = faction; resolveParams.pawnGroupMakerParams.points = (rp.settlementPawnGroupPoints ?? SymbolResolver_Settlement.DefaultPawnsPoints.RandomInRange); resolveParams.pawnGroupMakerParams.inhabitants = true; resolveParams.pawnGroupMakerParams.seed = rp.settlementPawnGroupSeed; } if (faction.def.pawnGroupMakers.Any(pgm => pgm.kindDef == PawnGroupKindDefOf.Settlement)) { BaseGen.symbolStack.Push("pawnGroup", resolveParams, null); } // Add defense if (lDef.vanillaLikeDefense) { int dWidth = (Rand.Bool ? 2 : 4); ResolveParams rp3 = rp; rp3.rect = new CellRect(rp.rect.minX - dWidth, rp.rect.minZ - dWidth, rp.rect.Width + (dWidth * 2), rp.rect.Height + (dWidth * 2)); rp3.faction = faction; rp3.edgeDefenseWidth = dWidth; rp3.edgeThingMustReachMapEdge = new bool?(rp.edgeThingMustReachMapEdge ?? true); BaseGen.symbolStack.Push("edgeDefense", rp3, null); } if (VFECore.VFEGlobal.settings.enableLog) { Log.Message("Structures generation - PASS"); } // Create the rooms ResolveParams rp2 = rp; rp2.faction = faction; BaseGen.symbolStack.Push("kcsg_roomsgen", rp2, null); // Add path if (VFECore.VFEGlobal.settings.enableLog) { Log.Message("Adding paths - PASS"); } if (lDef.path) { ResolveParams rp1 = rp; rp1.floorDef = lDef.pathType ?? TerrainDefOf.Gravel; rp1.allowBridgeOnAnyImpassableTerrain = true; BaseGen.symbolStack.Push("floor", rp1, null); } // Destroy all things before spawning the base if (VFECore.VFEGlobal.settings.enableLog) { Log.Message("Clearing ground - PASS"); } if (lDef.clearEverything) { foreach (IntVec3 c in rp.rect) { c.GetThingList(map).ToList().ForEach((t) => t.DeSpawn()); // Remove all things map.roofGrid.SetRoof(c, null); // Remove roof } map.roofGrid.RoofGridUpdate(); // Update roof grid } else { foreach (IntVec3 c in rp.rect) { c.GetThingList(map).ToList().FindAll(t1 => t1.def.category == ThingCategory.Filth || t1.def.category == ThingCategory.Item).ForEach((t) => t.DeSpawn()); } } }
public static void Generate(Map map, IntVec3 c, CustomGenOption sf, string symbolResolver = "kcsg_settlement") { CGO.useStructureLayout = sf.useStructureLayout; if (sf.useStructureLayout) { CGO.structureLayoutDef = LayoutUtils.ChooseLayoutFrom(sf.chooseFromlayouts); } else { CGO.settlementLayoutDef = sf.chooseFromSettlements.RandomElement(); } // Get faction Faction faction; if (map.ParentFaction == null || map.ParentFaction == Faction.OfPlayer) { faction = Find.FactionManager.RandomEnemyFaction(false, false, true, TechLevel.Undefined); } else { faction = map.ParentFaction; } // Get settlement size int width; int height; if (sf.useStructureLayout) { RectUtils.HeightWidthFromLayout(CGO.structureLayoutDef, out height, out width); } else { SettlementLayoutDef temp = CGO.settlementLayoutDef; height = temp.settlementSize.x; width = temp.settlementSize.z; } IntVec3 intVec3 = c; if (CGO.factionSettlement.tryFindFreeArea) { bool success = RCellFinder.TryFindRandomCellNearTheCenterOfTheMapWith(cell => new CellRect(cell.x - width / 2, cell.z - height / 2, width, height).Cells.All(pC => pC.Walkable(map) && !pC.GetTerrain(map).affordances.Contains(TerrainAffordanceDefOf.Bridgeable)), map, out intVec3); KLog.Message($"Trying to find free spawn area success: {success}"); } CellRect rect = new CellRect(intVec3.x - width / 2, intVec3.z - height / 2, width, height); rect.ClipInsideMap(map); ResolveParams rp = default; rp.faction = faction; rp.rect = rect; BaseGen.globalSettings.map = map; BaseGen.symbolStack.Push(symbolResolver, rp, null); BaseGen.Generate(); }