Example #1
0
        public override void Generate(Map map, GenStepParams parms)
        {
            //add standard ruins along with real.
            if (RealRuins_ModSettings.preserveStandardRuins)
            {
                GenStep scatterOriginalRuins = new GenStep_ScatterRuinsSimple();
                scatterOriginalRuins.Generate(map, parms);
            }
            //skip generation due to low blueprints count
            if (SnapshotStoreManager.Instance.StoredSnapshotsCount() < 10)
            {
                Debug.Error(Debug.Scatter, "Skipping ruins gerenation due to low blueprints count.");
                return;
            }

            //Skip generation for starting tile if corresponding settings flag is set
            if (RealRuins_ModSettings.startWithoutRuins)
            {
                int homes   = 0;
                var allMaps = Find.Maps;
                for (int i = 0; i < allMaps.Count; i++)
                {
                    Map someMap = allMaps[i];
                    if (someMap.IsPlayerHome)
                    {
                        homes++;
                    }
                }

                if (homes == 1 && Find.TickManager.TicksGame < 10)
                {
                    return;                                                //single home => we're generating that single home => that's starting map => no ruins here if this option is selected.
                }
            }

            //Skip generation on other ruins world objects
            foreach (WorldObject wo in Find.World.worldObjects.ObjectsAt(map.Tile))
            {
                if (wo is RealRuinsPOIWorldObject || wo is AbandonedBaseWorldObject)
                {
                    return;
                }
            }

            if (!map.TileInfo.WaterCovered)
            {
                float densityMultiplier    = 1.0f;
                float scaleMultiplier      = 1.0f;
                float distanceToSettlement = 0.0f;
                float totalDensity         = RealRuins_ModSettings.defaultScatterOptions.densityMultiplier;
                currentOptions = RealRuins_ModSettings.defaultScatterOptions.Copy(); //store as instance variable to keep accessible on subsequent ScatterAt calls

                if (RealRuins_ModSettings.defaultScatterOptions.enableProximity)
                {
                    distanceToSettlement = CalculateDistanceToNearestSettlement(map);
                    if (distanceToSettlement >= 16 && Rand.Chance(0.5f))
                    {
                        totalDensity = 0;
                    }

                    if (totalDensity > 0)
                    {
                        densityMultiplier = (float)(Math.Exp(1.0 / (distanceToSettlement / 10.0 + 0.3)) - 0.7);
                        scaleMultiplier   = (float)(Math.Exp(1 / (distanceToSettlement / 5 + 0.5)) - 0.3);
                    }
                    else
                    {
                        densityMultiplier = 0.0f;
                    }

                    currentOptions.densityMultiplier       *= densityMultiplier;
                    currentOptions.minRadius                = Math.Min(60, Math.Max(6, (int)(currentOptions.minRadius * scaleMultiplier))); //keep between 6 and 60
                    currentOptions.maxRadius                = Math.Min(60, Math.Max(6, (int)(currentOptions.maxRadius * scaleMultiplier))); //keep between 6 and 60
                    currentOptions.scavengingMultiplier    *= scaleMultiplier * densityMultiplier;
                    currentOptions.deteriorationMultiplier += Math.Min(0.2f, (1.0f / (scaleMultiplier * densityMultiplier * 3)));


                    if (densityMultiplier > 20.0f)
                    {
                        densityMultiplier = 20.0f;
                    }
                    while (densityMultiplier * currentOptions.maxRadius > 800)
                    {
                        densityMultiplier *= 0.9f; //WHAT? Why not 800/radius?
                    }
                }

                //number of ruins based on density settings
                var num = (int)((float)map.Area / 10000.0f) * Rand.Range(1 * totalDensity, 2 * totalDensity);

                Debug.Log(Debug.Scatter, "dist {0}, dens {1} (x{2}), scale x{3} ({4}-{5}), scav {6}, deter {7}", distanceToSettlement, currentOptions.densityMultiplier, densityMultiplier, scaleMultiplier, currentOptions.minRadius, currentOptions.maxRadius, currentOptions.scavengingMultiplier, currentOptions.deteriorationMultiplier);
                Debug.Log(Debug.Scatter, "Spawning {0} ruin chunks", num);
                BaseGen.globalSettings.map = map;

                bool shouldUnpause = false;
                Find.TickManager.Pause();
                if (!Find.TickManager.Paused)
                {
                    Find.TickManager.TogglePaused();
                    shouldUnpause = true;
                }

                CoverageMap coverageMap = CoverageMap.EmptyCoverageMap(map);

                for (int i = 0; i < num; i++)
                {
                    try {
                        //We use copy of scatteroptions because each scatteroptions represents separate chunk with separate location, size, maps, etc.
                        //should use struct instead? is it compatible with IExposable?
                        ResolveParams rp = default(ResolveParams);

                        List <AbstractDefenderForcesGenerator> generators = new List <AbstractDefenderForcesGenerator>();
                        if (Rand.Chance(currentOptions.hostileChance))
                        {
                            if (Rand.Chance(0.8f))
                            {
                                generators = new List <AbstractDefenderForcesGenerator> {
                                    new AnimalInhabitantsForcesGenerator()
                                };
                            }
                            else
                            {
                                generators = new List <AbstractDefenderForcesGenerator> {
                                    new MechanoidsForcesGenerator(0)
                                };
                            }
                        }
                        rp.faction = Find.FactionManager.OfAncientsHostile;
                        var center = CellFinder.RandomNotEdgeCell(10, map);
                        rp.rect = new CellRect(center.x, center.z, 1, 1); //after generation will be extended to a real size
                        RuinsScatterer.Scatter(rp, currentOptions.Copy(), coverageMap, generators);
                    } catch {
                        Debug.Warning(Debug.Scatter, "Could not scatter a single ruins chunk.");
                    }
                }

                if (shouldUnpause)
                {
                    //Debug.Message("Finished spawning, unpausing");
                    Find.TickManager.TogglePaused();
                }
            }
        }
Example #2
0
        public override void Generate(Map map, GenStepParams parms)
        {
            Find.TickManager.Pause();
            //Debug.Message("Overridden LARGE generate");

            RealRuinsPOIComp poiComp  = map.Parent.GetComponent <RealRuinsPOIComp>();
            string           filename = SnapshotStoreManager.Instance.SnapshotNameFor(poiComp.blueprintName, poiComp.gameName);


            Debug.Log("Spawning POI: Preselected file name is {0}", filename);
            Debug.Log("Location is {0} {1}", poiComp.originX, poiComp.originZ);

            currentOptions = RealRuins_ModSettings.defaultScatterOptions.Copy(); //store as instance variable to keep accessible on subsequent ScatterAt calls

            currentOptions.minRadius               = 400;
            currentOptions.maxRadius               = 400;
            currentOptions.scavengingMultiplier    = 0.0f;
            currentOptions.deteriorationMultiplier = 0.0f;
            currentOptions.hostileChance           = 0.0f;


            currentOptions.blueprintFileName          = filename;
            currentOptions.costCap                    = -1;
            currentOptions.startingPartyPoints        = -1;
            currentOptions.minimumCostRequired        = 0;
            currentOptions.minimumDensityRequired     = 0.0f;
            currentOptions.minimumAreaRequired        = 0;
            currentOptions.deleteLowQuality           = false;
            currentOptions.shouldKeepDefencesAndPower = true;
            currentOptions.shouldLoadPartOnly         = false;
            currentOptions.shouldAddRaidTriggers      = false;
            currentOptions.claimableBlocks            = false;


            if (poiComp.poiType == (int)POIType.Ruins || map.ParentFaction == null)
            {
                /*if (Rand.Chance(0.1f)) {
                 *  currentOptions.wallsDoorsOnly = true;
                 * } else {
                 *  currentOptions.deteriorationMultiplier = Math.Abs(Rand.Gaussian(0, 0.15f));
                 * }*/
                currentOptions.shouldAddFilth       = true;
                currentOptions.forceFullHitPoints   = false;
                currentOptions.enableDeterioration  = true;
                currentOptions.overwritesEverything = false;
                currentOptions.costCap       = (int)Math.Abs(Rand.Gaussian(0, 10000));
                currentOptions.itemCostLimit = Rand.Range(50, 300);
            }
            else
            {
                currentOptions.shouldAddFilth       = false;
                currentOptions.forceFullHitPoints   = true;
                currentOptions.enableDeterioration  = false;
                currentOptions.overwritesEverything = true;
            }

            currentOptions.overridePosition      = new IntVec3(poiComp.originX, 0, poiComp.originZ);
            currentOptions.centerIfExceedsBounds = true;

            var bp = BlueprintLoader.LoadWholeBlueprintAtPath(filename);

            //FOR DEBUG LOGGING
            //var a = new BlueprintAnalyzer(bp, currentOptions);
            //a.Analyze();

            Debug.Log(Debug.BlueprintTransfer, "Trying to place POI map at tile {0}, at {1},{2} to {3},{4} ({5}x{6})",
                      map.Parent.Tile,
                      poiComp.originX, poiComp.originZ,
                      poiComp.originX + bp.width, poiComp.originZ + bp.height,
                      bp.width, bp.height);

            var generators = GeneratorsForBlueprint(bp, poiComp, map.Parent.Faction);

            ResolveParams resolveParams = default(ResolveParams);

            BaseGen.globalSettings.map = map;
            resolveParams.faction      = map.ParentFaction;
            resolveParams.rect         = new CellRect(currentOptions.overridePosition.x, currentOptions.overridePosition.z, map.Size.x - currentOptions.overridePosition.x, map.Size.z - currentOptions.overridePosition.z);


            BaseGen.globalSettings.mainRect = resolveParams.rect;

            float uncoveredCost = currentOptions.uncoveredCost;

            if (resolveParams.faction != null)
            {
                //Debug.Log("Mannable count: {0}", poiComp.mannableCount);
                ManTurrets((int)(poiComp.mannableCount * 1.25f + 1), resolveParams, map);
            }


            RuinsScatterer.Scatter(resolveParams, currentOptions, null, generators);

            //ok, but why LIFO? Queue looks more suitable for map generation.
            //Looks like it was done for nested symbols resolving, but looks strange anyway.

            BaseGen.symbolStack.Push("chargeBatteries", resolveParams);
            BaseGen.symbolStack.Push("ensureCanHoldRoof", resolveParams);
            BaseGen.symbolStack.Push("refuel", resolveParams);

            BaseGen.Generate();

            if (generators != null)
            {
                foreach (AbstractDefenderForcesGenerator generator in generators)
                {
                    generator.GenerateStartingParty(map, resolveParams, currentOptions);
                }
            }
        }
Example #3
0
        public override void Generate(Map map, GenStepParams parms)
        {
            Find.TickManager.Pause();
            //Debug.Message("Overridden LARGE generate");

            string filename = map.Parent.GetComponent <RuinedBaseComp>()?.blueprintFileName;

            Debug.Log(Debug.Scatter, "Large Ruins - Preselected file name is {0}", filename);

            currentOptions = RealRuins_ModSettings.defaultScatterOptions.Copy(); //store as instance variable to keep accessible on subsequent ScatterAt calls

            currentOptions.minRadius               = 200;
            currentOptions.maxRadius               = 200;
            currentOptions.scavengingMultiplier    = 0.1f;
            currentOptions.deteriorationMultiplier = 0.0f;
            currentOptions.hostileChance           = 1.0f;


            currentOptions.blueprintFileName          = filename;
            currentOptions.costCap                    = map.Parent.GetComponent <RuinedBaseComp>()?.currentCapCost ?? -1;
            currentOptions.startingPartyPoints        = (int)(map.Parent.GetComponent <RuinedBaseComp>()?.raidersActivity ?? -1);
            currentOptions.minimumCostRequired        = (int)Math.Min(100000.0f, RealRuins_ModSettings.ruinsCostCap);
            currentOptions.minimumDensityRequired     = 0.015f;
            currentOptions.minimumAreaRequired        = 6400;
            currentOptions.deleteLowQuality           = false; //do not delete since we have much higher requirements for base ruins
            currentOptions.shouldKeepDefencesAndPower = true;
            currentOptions.shouldLoadPartOnly         = false;
            currentOptions.shouldAddRaidTriggers      = Find.Storyteller.difficulty.allowBigThreats;
            currentOptions.claimableBlocks            = false;
            currentOptions.enableDeterioration        = false;


            ResolveParams resolveParams = default(ResolveParams);

            BaseGen.globalSettings.map = map;
            resolveParams.faction      = Find.FactionManager.OfAncientsHostile;
            resolveParams.rect         = new CellRect(0, 0, map.Size.x, map.Size.z);
            List <AbstractDefenderForcesGenerator> generators = new List <AbstractDefenderForcesGenerator> {
                new BattleRoyaleForcesGenerator()
            };


            BaseGen.globalSettings.mainRect = resolveParams.rect;

            float uncoveredCost = currentOptions.uncoveredCost;

            if (uncoveredCost < 0)
            {
                if (Rand.Chance(0.5f))
                {
                    uncoveredCost = -uncoveredCost; //adding really small party
                }
            }


            RuinsScatterer.Scatter(resolveParams, currentOptions, null, generators);
            BaseGen.symbolStack.Push("chargeBatteries", resolveParams);
            BaseGen.symbolStack.Push("refuel", resolveParams);
            BaseGen.Generate();



            //adding starting party
            //don't doing it via basegen because of uh oh i don't remember, something with pawn location control
            if (generators != null)
            {
                foreach (AbstractDefenderForcesGenerator generator in generators)
                {
                    generator.GenerateStartingParty(map, resolveParams, currentOptions);
                }
            }
        }