public static List <CustomVector> PlaceAt(CustomVector point, StructureLayoutDef building, CustomVector[][] grid)
        {
            RectUtils.HeightWidthFromLayout(building, out int height, out int width);
            List <CustomVector> doors         = GetDoorsInLayout(building);
            List <CustomVector> doorsAdjusted = new List <CustomVector>();

            for (int i = (int)point.X; i < width + point.X; i++)
            {
                for (int j = (int)point.Y; j < height + point.Y; j++)
                {
                    CellType type = doors.FindAll(d => i == d.X + point.X && j == d.Y + point.Y).Any() ? CellType.DOOR : CellType.BUILDING;
                    if (type == CellType.DOOR)
                    {
                        doorsAdjusted.Add(new CustomVector(i, j));
                    }

                    if (grid[i][j] != null)
                    {
                        grid[i][j].Type = type;
                    }
                    else
                    {
                        grid[i][j] = new CustomVector(i, j, type: type);
                    }
                }
            }

            return(doorsAdjusted);
        }
        public static bool CanPlaceAt(CustomVector point, StructureLayoutDef building, CustomVector[][] grid)
        {
            bool result = true;

            RectUtils.HeightWidthFromLayout(building, out int height, out int width);

            for (int i = (int)point.X - 1; i < width + point.X + 1 && result; i++)
            {
                for (int j = (int)(point.Y - 1); j < height + point.Y + 1 && result; j++)
                {
                    if (IsInBound(i, j, grid.Length, grid[0].Length))
                    {
                        if (grid[i][j] != null && grid[i][j].Type != CellType.NONE)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            return(result);
        }
Example #3
0
        public override bool CanUseWith(IncidentParms parms, PawnGroupKindDef groupKind)
        {
            CGO.fallingStructure = this.def.GetModExtension <FallingStructure>();

            if (CGO.fallingStructure.needToHaveSettlements && !Find.World.worldObjects.Settlements.FindAll(s => s.Faction == parms.faction).Any())
            {
                return(false);
            }

            if (CGO.fallingStructure.canBeUsedBy.Contains(parms.faction.def))
            {
                CGO.fallingStructureChoosen = LayoutUtils.ChooseWeightedStruct(CGO.fallingStructure.WeightedStructs, parms).structureLayoutDef;

                if (CGO.fallingStructureChoosen != null)
                {
                    RectUtils.HeightWidthFromLayout(CGO.fallingStructureChoosen, out int h, out int w);
                    return(parms.points >= this.MinimumPoints(parms.faction, groupKind) && this.FindRect((Map)parms.target, h, w) != IntVec3.Invalid);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                return(false);
            }
        }
Example #4
0
        private static void QuickspawnStructure()
        {
            if (DefDatabase <StructureLayoutDef> .AllDefs.Count() > 0)
            {
                List <DebugMenuOption> list = new List <DebugMenuOption>();
                foreach (StructureLayoutDef localDef2 in DefDatabase <StructureLayoutDef> .AllDefs)
                {
                    StructureLayoutDef localDef = localDef2;
                    list.Add(new DebugMenuOption(localDef.defName, DebugMenuOptionMode.Tool, delegate()
                    {
                        if (UI.MouseCell().InBounds(Find.CurrentMap))
                        {
                            RectUtils.HeightWidthFromLayout(localDef, out int h, out int w);
                            CellRect cellRect = CellRect.CenteredOn(UI.MouseCell(), w, h);

                            foreach (List <string> item in localDef.layouts)
                            {
                                GenUtils.GenerateRoomFromLayout(item, cellRect, Find.CurrentMap, localDef);
                            }
                        }
                    }));
                }
                Find.WindowStack.Add(new Dialog_DebugOptionListLister(list));
            }
        }
Example #5
0
        public override bool TryResolveRaidSpawnCenter(IncidentParms parms)
        {
            RectUtils.HeightWidthFromLayout(CGO.fallingStructureChoosen, out int h, out int w);

            Map map = (Map)parms.target;

            parms.spawnCenter   = this.FindRect(map, h, w);
            parms.spawnRotation = Rot4.Random;
            return(true);
        }
Example #6
0
        public override void Generate(Map map, GenStepParams parms)
        {
            StructureLayoutDef structureLayoutDef = structureLayoutDefs.RandomElement();

            RectUtils.HeightWidthFromLayout(structureLayoutDef, out int h, out int w);
            CellRect cellRect = CellRect.CenteredOn(map.Center, w, h);

            GenUtils.PreClean(map, cellRect, structureLayoutDef.roofGrid, fullClear);

            foreach (List <string> item in structureLayoutDef.layouts)
            {
                GenUtils.GenerateRoomFromLayout(item, cellRect, map, structureLayoutDef);
            }

            if (shouldRuin)
            {
                CGO.factionSettlement = new CustomGenOption
                {
                    filthTypes    = filthTypes,
                    scatterThings = scatterThings,
                    scatterChance = scatterChance
                };

                ResolveParams rp = new ResolveParams
                {
                    faction = map.ParentFaction,
                    rect    = cellRect
                };
                foreach (string resolver in ruinSymbolResolvers)
                {
                    if (!(ruinSymbolResolvers.Contains("kcsg_randomroofremoval") && resolver == "kcsg_scatterstuffaround"))
                    {
                        BaseGen.symbolStack.Push(resolver, rp, null);
                    }
                }
            }

            // Flood refog
            if (map.mapPawns.FreeColonistsSpawned.Count > 0)
            {
                FloodFillerFog.DebugRefogMap(map);
            }
        }
        public override void Resolve(ResolveParams rp)
        {
            CGO.currentGenStep = "Generating structures";

            foreach (KeyValuePair <CustomVector, StructureLayoutDef> keyValue in CGO.vectStruct)
            {
                CGO.currentGenStepMoreInfo = "Generating " + keyValue.Value.defName;

                RectUtils.HeightWidthFromLayout(keyValue.Value, out int height, out int width);
                IntVec3 limitMin = new IntVec3
                {
                    x = CGO.offset.x + (int)keyValue.Key.X,
                    z = CGO.offset.z - (int)keyValue.Key.Y - height + 1
                };
                CellRect rect = new CellRect(limitMin.x, limitMin.z, width, height);

                foreach (List <string> item in keyValue.Value.layouts)
                {
                    GenUtils.GenerateRoomFromLayout(item, rect, BaseGen.globalSettings.map, keyValue.Value);
                }

                if (keyValue.Value.isStorage)
                {
                    ResolveParams rstock = rp;
                    rstock.rect = new CellRect(limitMin.x, limitMin.z, width, height);
                    BaseGen.symbolStack.Push("kcsg_storagezone", rstock, null);
                }
            }

            if (CGO.settlementLayoutDef.addLandingPad && ModLister.RoyaltyInstalled)
            {
                if (rp.rect.TryFindRandomInnerRect(new IntVec2(9, 9), out CellRect rect, null))
                {
                    CGO.currentGenStepMoreInfo = "Generating landing pad";
                    ResolveParams resolveParams = rp;
                    resolveParams.rect = rect;
                    BaseGen.symbolStack.Push("landingPad", resolveParams, null);
                    BaseGen.globalSettings.basePart_landingPadsResolved++;
                }
            }

            BaseGen.symbolStack.Push("kcsg_gridsecondpass", rp, null);
        }
        /// <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);
        }
Example #9
0
        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);
            }
        }
Example #11
0
        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);
        }