public static XElement CreateTerrainlayout(List <IntVec3> cellExport, Area area, Map map, bool exportNatural, out bool add) { XElement liMain = new XElement("li", null); RectUtils.EdgeFromList(cellExport, out int height, out int width); add = false; IntVec3 first = cellExport.First(); for (int i = 0; i < height; i++) { XElement li = new XElement("li", null); string temp = ""; for (int i2 = 0; i2 < width; i2++) { if (area != null && !area.ActiveCells.Contains(first)) { if (i2 + 1 == width) { temp += "."; } else { temp += ".,"; } } else if (map.terrainGrid.TerrainAt(first) is TerrainDef d && !d.BuildableByPlayer && !d.HasTag("Road") && !exportNatural) { if (i2 + 1 == width) { temp += "."; } else { temp += ".,"; } }
/// <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, 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(); }
public override void PostMapGenerate(Map map) { if (Find.TickManager.TicksGame > 5f || chooseFrom.Count <= 0 || PrepareCarefully_Util.pcScenariosSave.Count <= 0) { return; } StructureLayoutDef structureLayoutDef; if (ModLister.GetActiveModWithIdentifier("EdB.PrepareCarefully") != null) { structureLayoutDef = PrepareCarefully_Util.pcScenariosSave.First().Key; nearMapCenter = PrepareCarefully_Util.pcScenariosSave.First().Value; } else { structureLayoutDef = chooseFrom.RandomElement(); } RectUtils.HeightWidthFromLayout(structureLayoutDef, out int h, out int w); CellRect cellRect = this.CreateCellRect(map, h, w); if (preGenClear) { GenUtils.PreClean(map, cellRect, structureLayoutDef.roofGrid, fullClear); } foreach (List <string> item in structureLayoutDef.layouts) { GenUtils.GenerateRoomFromLayout(item, cellRect, map, structureLayoutDef, spawnConduits); } if (spawnTheStartingPawn && Find.GameInitData != null) { List <List <Thing> > thingsGroups = new List <List <Thing> >(); foreach (Pawn startingAndOptionalPawn in Find.GameInitData.startingAndOptionalPawns) { thingsGroups.Add(new List <Thing>() { startingAndOptionalPawn }); } List <Thing> thingList = new List <Thing>(); foreach (ScenPart allPart in Find.Scenario.AllParts) { thingList.AddRange(allPart.PlayerStartingThings()); } int index = 0; foreach (Thing thing in thingList) { if (thing.def.CanHaveFaction) { thing.SetFactionDirect(Faction.OfPlayer); } thingsGroups[index].Add(thing); ++index; if (index >= thingsGroups.Count) { index = 0; } } IntVec3 center = map.Center; Pos offset = structureLayoutDef.spawnAtPos.RandomElement(); center.x += offset.x; center.y += offset.y; KLog.Message($"Spawning pawns and stuff at {center}"); this.DropThingGroupsAt(center, map, thingsGroups, instaDrop: (Find.GameInitData.QuickStarted || this.method != PlayerPawnsArriveMethod.DropPods), leaveSlag: true, allowFogged: false); } if (map.mapPawns.FreeColonistsSpawned.Count > 0) { FloodFillerFog.DebugRefogMap(map); } }
public override List <Pawn> SpawnThreats(IncidentParms parms) { RectUtils.HeightWidthFromLayout(CGO.fallingStructureChoosen, out int h, out int w); CellRect cellRect = CellRect.CenteredOn(parms.spawnCenter, w, h); List <string> allSymbList = new List <string>(); Map map = (Map)parms.target; foreach (string str in CGO.fallingStructureChoosen.layouts[0]) { List <string> symbSplitFromLine = str.Split(',').ToList(); symbSplitFromLine.ForEach((s) => allSymbList.Add(s)); } List <TTIR> fallers = new List <TTIR>(); Dictionary <ActiveDropPodInfo, IntVec3> pods = new Dictionary <ActiveDropPodInfo, IntVec3>(); int l = 0; foreach (IntVec3 cell in cellRect.Cells) { if (l < allSymbList.Count && allSymbList[l] != ".") { SymbolDef temp = DefDatabase <SymbolDef> .GetNamed(allSymbList[l], false); Thing thing; if (temp.thingDef != null && !CGO.fallingStructure.thingsToSpawnInDropPod.Contains(temp.thingDef)) { TTIR ttir = new TTIR(); thing = ThingMaker.MakeThing(temp.thingDef, temp.stuffDef); thing.SetFactionDirect(parms.faction); if (!CGO.fallingStructure.spawnDormantWhenPossible && thing.TryGetComp <CompCanBeDormant>() is CompCanBeDormant ccbd && ccbd != null) { ccbd.wakeUpOnTick = Find.TickManager.TicksGame + 150; } if (thing.def.rotatable && thing.def.category == ThingCategory.Building) { ttir.rot = new Rot4(temp.rotation.AsInt); } ThingDef faller = new ThingDef { thingClass = CGO.fallingStructure.skyfaller, category = ThingCategory.Ethereal, useHitPoints = false, drawOffscreen = true, tickerType = TickerType.Normal, altitudeLayer = AltitudeLayer.Skyfaller, drawerType = DrawerType.RealtimeOnly, defName = temp.thingDef.defName, label = temp.thingDef.label + " (incoming)", size = new IntVec2(thing.def.size.x, thing.def.size.z) }; faller.skyfaller = new SkyfallerProperties() { shadowSize = new UnityEngine.Vector2(thing.def.size.x + 1, thing.def.size.z + 1), ticksToImpactRange = new IntRange(150, 150), movementType = SkyfallerMovementType.Decelerate }; ttir.faller = faller; ttir.toSpawn = thing; ttir.cell = cell; fallers.Add(ttir); } else if (temp.thingDef != null) { thing = ThingMaker.MakeThing(temp.thingDef, temp.stuffDef); thing.SetFactionDirect(parms.faction); ActiveDropPodInfo activeDropPodInfo = new ActiveDropPodInfo(); activeDropPodInfo.innerContainer.TryAdd(thing); activeDropPodInfo.openDelay = 40; activeDropPodInfo.leaveSlag = false; pods.Add(activeDropPodInfo, cell); } } l++; } // ARRIVAL fallers.ForEach(ttir => this.SpawnSkyfaller(ttir.faller, ttir.toSpawn, ttir.cell, map, ttir.rot)); for (int i = 0; i < pods.Count; i++) { DropPodUtility.MakeDropPodAt(pods.ElementAt(i).Value, map, pods.ElementAt(i).Key); } IncidentParms parms1 = parms; RCellFinder.TryFindRandomCellNearWith(parms.spawnCenter, i => i.Walkable(map), map, out parms1.spawnCenter, 33, 40); base.SpawnThreats(parms1); CGO.ClearFalling(); return(null); }
public static XElement CreateThinglayout(List <IntVec3> cellExport, int index, Area area, Dictionary <IntVec3, List <Thing> > pairsCellThingList, bool exportFilth) { XElement liMain = new XElement("li", null); RectUtils.EdgeFromList(cellExport, out int height, out int width); List <Thing> aAdded = new List <Thing>(); IntVec3 first = cellExport.First(); for (int i = 0; i < height; i++) { XElement li = new XElement("li", null); string temp = ""; for (int i2 = 0; i2 < width; i2++) { List <Thing> things = pairsCellThingList.TryGetValue(first).FindAll(t => t.def.category != ThingCategory.Pawn && t.def.category != ThingCategory.Item); if (!exportFilth) { things.RemoveAll(t => t.def.category == ThingCategory.Filth); } Thing thing; if (things.Count < index + 1 || (area != null && !area.ActiveCells.Contains(first))) { if (i2 + 1 == width) { temp += "."; } else { temp += ".,"; } } else { thing = things[index]; if (!aAdded.Contains(thing) && thing.Position == first) { SymbolDef symbolDef; if (thing.Stuff != null) { if (thing.def.rotatable) { symbolDef = DefDatabase <SymbolDef> .AllDefsListForReading.Find(s => s.thingDef == thing.def && s.stuffDef == thing.Stuff && s.rotation == thing.Rotation); } else { symbolDef = DefDatabase <SymbolDef> .AllDefsListForReading.Find(s => s.thingDef == thing.def && s.stuffDef == thing.Stuff); } } else { if (thing.def.rotatable) { symbolDef = DefDatabase <SymbolDef> .AllDefsListForReading.Find(s => s.thingDef == thing.def && s.rotation == thing.Rotation); } else { symbolDef = DefDatabase <SymbolDef> .AllDefsListForReading.Find(s => s.thingDef == thing.def); } } if (symbolDef == null) { string symbolString = thing.def.defName; if (thing.Stuff != null) { symbolString += "_" + thing.Stuff.defName; } if (thing.def.rotatable && thing.def.category != ThingCategory.Plant) { symbolString += "_" + thing.Rotation.ToStringHuman(); } if (i2 + 1 == width) { temp += symbolString; } else { temp += symbolString + ","; } } else { if (i2 + 1 == width) { temp += symbolDef.defName; } else { temp += symbolDef.defName + ","; } } aAdded.Add(thing); } else { if (i2 + 1 == width) { temp += "."; } else { temp += ".,"; } } } first.x++; } first.x -= width; li.Add(temp); liMain.Add(li); first.z++; } return(liMain); }