Custom World Event Map Spawns All Fog

Started by SickBoyWi, November 06, 2019, 08:32:01 AM

Previous topic - Next topic

SickBoyWi

I have an issue, and after a ton of digging haven't found a solution.

I have a custom world event, that generates it's own map. Very similar to a bandit camp; in fact that's the code I started with.

The issue is that once in a while the map for the custom event will spawn all fog. The pawns will be there, but you won't see them, like they're on a different layer. Sometimes this happens because they spawn in ocean tiles, and sometimes they spawn in a spot that is just fine, but for whatever reason it's like they're on a Z layer that doesn't show them. And, again, the map is all fog. Everything looks fine with the map if you turn off fog in Dev Mode.

Note that this happens rarely, not every time.

I'll post the genstep code below. If config would help, I can post that too, just let me know.

Any ideas would be greatly appreciated!



using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using RimWorld;
using RimWorld.BaseGen;
using UnityEngine;
using Verse;
using Verse.AI.Group;
using Verse.AI;

namespace TheEndTimes
{
    public class GenStep_ChaosPortalSmall : GenStep
    {
        public override void Generate(Map map, GenStepParams parms)
        {
            Faction faction = Find.FactionManager.FirstFactionOfDef(TheEndTimesDefOf.RH_TET_ChaosMonsterFaction);
           
            CellRect rectToDefend;
            if (!MapGenerator.TryGetVar<CellRect>("RectOfInterest", out rectToDefend))
            {
                rectToDefend = CellRect.SingleCell(map.Center);
            }
           
            // Add portal && flooring for it.
            Thing portal = GenSpawn.Spawn(ThingMaker.MakeThing(ThingDef.Named("RH_TET_ChaosPortal_Small"), null), map.Center, map, WipeMode.Vanish);
            portal.SetFaction(faction);
            map.attackTargetsCache.TargetsHostileToFaction(Find.FactionManager.OfPlayer).Add((IAttackTarget)portal);

            IEnumerable<IntVec3> portalAreaCells = portal.CellsAdjacent8WayAndInside();

            int minx = 1000;
            int minz = 1000;

            foreach (IntVec3 intvec3 in portalAreaCells)
            {
                if (intvec3.x < minx)
                {
                    minx = intvec3.x;
                }
                if (intvec3.z < minz)
                {
                    minz = intvec3.z;
                }
            }

            CellRect portalArea = new CellRect(minx - 4, minz - 4, 13, 15);

            // Clear map center, add floors around portal.
            TerrainDef floorDef = TerrainDef.Named("FlagstoneGranite");
            ResolveParams areaAroundPortal = default(ResolveParams);
            areaAroundPortal.rect = portalArea;
            areaAroundPortal.clearEdificeOnly = true;
            areaAroundPortal.faction = faction;
            areaAroundPortal.floorDef = floorDef;
            areaAroundPortal.pathwayFloorDef = floorDef;
            areaAroundPortal.edgeDefenseWidth = new int?(0);
            areaAroundPortal.edgeDefenseTurretsCount = new int?(0);
            areaAroundPortal.edgeDefenseMortarsCount = new int?(0);
            areaAroundPortal.settlementPawnGroupPoints = new float?(0f);
            areaAroundPortal.chanceToSkipWallBlock = 0f;
            BaseGen.symbolStack.Push("floor", areaAroundPortal);

            BaseGen.globalSettings.map = map;

            BaseGen.Generate();
           
            // Create Base.
            ResolveParams resolveParams = default(ResolveParams);

            resolveParams.rect = this.GetOutpostRect(rectToDefend, map);
            resolveParams.faction = faction;
            resolveParams.edgeDefenseWidth = new int?(2);
            resolveParams.edgeDefenseTurretsCount = new int?(0);
            resolveParams.edgeDefenseMortarsCount = new int?(0);
            if (parms.siteCoreOrPart != null)
            {
                resolveParams.settlementPawnGroupPoints = new float?(250);
                resolveParams.settlementPawnGroupSeed = new int?(OutpostSitePartUtility.GetPawnGroupMakerSeed(parms.siteCoreOrPart.parms));
            }
            else
            {
                resolveParams.settlementPawnGroupPoints = new float?(this.defaultPawnGroupPointsRange.RandomInRange);
            }
            BaseGen.globalSettings.map = map;
            BaseGen.globalSettings.minBuildings = 1;
            BaseGen.globalSettings.minBarracks = 1;
            BaseGen.globalSettings.basePart_breweriesCoverage = 0;
            BaseGen.globalSettings.basePart_farmsCoverage = 0;
            BaseGen.symbolStack.Push("settlement", resolveParams);
            BaseGen.Generate();
        }

        private CellRect GetOutpostRect(CellRect rectToDefend, Map map)
        {
            GenStep_ChaosPortalSmall.possibleRects.Add(new CellRect(rectToDefend.minX - 1 - Size, rectToDefend.CenterCell.z - Size, Size, Size));
            GenStep_ChaosPortalSmall.possibleRects.Add(new CellRect(rectToDefend.maxX + 1, rectToDefend.CenterCell.z - Size, Size, Size));
            GenStep_ChaosPortalSmall.possibleRects.Add(new CellRect(rectToDefend.CenterCell.x - Size, rectToDefend.minZ - 1 - Size, Size, Size));
            GenStep_ChaosPortalSmall.possibleRects.Add(new CellRect(rectToDefend.CenterCell.x - Size, rectToDefend.maxZ + 1, Size, Size));
            CellRect mapRect = new CellRect(0, 0, map.Size.x, map.Size.z);
            GenStep_ChaosPortalSmall.possibleRects.RemoveAll((CellRect x) => !x.FullyContainedWithin(mapRect));
            if (GenStep_ChaosPortalSmall.possibleRects.Any<CellRect>())
            {
                return GenStep_ChaosPortalSmall.possibleRects.RandomElement<CellRect>();
            }
            return rectToDefend;
        }

        private CellRect GetPortalRect(CellRect rectToDefend, Map map)
        {
            GenStep_ChaosPortalSmall.portalRects.Add(new CellRect(rectToDefend.minX - 1 - PortalSize, rectToDefend.CenterCell.z - PortalSize / 2, PortalSize, PortalSize));
            GenStep_ChaosPortalSmall.portalRects.Add(new CellRect(rectToDefend.maxX + 1, rectToDefend.CenterCell.z - PortalSize / 2, PortalSize, PortalSize));
            GenStep_ChaosPortalSmall.portalRects.Add(new CellRect(rectToDefend.CenterCell.x - PortalSize / 2, rectToDefend.minZ - 1 - PortalSize, PortalSize, PortalSize));
            GenStep_ChaosPortalSmall.portalRects.Add(new CellRect(rectToDefend.CenterCell.x - PortalSize / 2, rectToDefend.maxZ + 1, PortalSize, PortalSize));
            CellRect mapRect = new CellRect(0, 0, map.Size.x, map.Size.z);
            GenStep_ChaosPortalSmall.portalRects.RemoveAll((Predicate<CellRect>)(x => !x.FullyContainedWithin(mapRect)));
            if (GenStep_ChaosPortalSmall.portalRects.Any<CellRect>())
                return GenStep_ChaosPortalSmall.portalRects.RandomElement<CellRect>();
            return rectToDefend;
        }

        private const int Size = 22;
        private const int PortalSize = 8;
        private static List<CellRect> possibleRects = new List<CellRect>();
        private static List<CellRect> portalRects = new List<CellRect>();
        public override int SeedPart { get; }
        public FloatRange defaultPawnGroupPointsRange = SymbolResolver_Settlement.DefaultPawnsPoints;
    }
}


SickBoyWi

Perhaps I could provide additional info that would make it more likely that someone would have an idea here? If so, just let me know, and I will do so.

SickBoyWi

Just in case any one else ever has this issue, I'm still tracking it.

The actual warning message that shows up in the log when it happens is:
Could not find any valid edge cell.
Verse.Log:Warning(String, Boolean)
RimWorld.Planet.CaravanEnterMapUtility:FindNearEdgeCell(Map, Predicate`1)
RimWorld.Planet.CaravanEnterMapUtility:GetEnterCell(Caravan, Map, CaravanEnterMode, Predicate`1)
RimWorld.Planet.CaravanEnterMapUtility:Enter(Caravan, Map, CaravanEnterMode, CaravanDropInventoryMode, Boolean, Predicate`1)
RimWorld.SiteCoreWorker:DoEnter(Caravan, Site)
RimWorld.<Enter>c__AnonStorey2:<>m__0()
Verse.LongEventHandler:UpdateCurrentSynchronousEvent(Boolean&)
Verse.LongEventHandler:LongEventsUpdate(Boolean&)
Verse.Root:Update_Patch1(Object)
Verse.Root_Play:Update()


I will continue looking into this until I correct the issue.

SickBoyWi

Just a little more info, for any one tracking this (and myself, so it's all in one spot).

The core FindNearEdgeCell function is:
   
private static IntVec3 FindNearEdgeCell(Map map, Predicate<IntVec3> extraCellValidator)
    {
      Predicate<IntVec3> baseValidator = (Predicate<IntVec3>) (x =>
      {
        if (x.Standable(map))
          return !x.Fogged(map);
        return false;
      });
      Faction hostFaction = map.ParentFaction;
      IntVec3 result;
      if (CellFinder.TryFindRandomEdgeCellWith((Predicate<IntVec3>) (x =>
      {
        if (!baseValidator(x) || extraCellValidator != null && !extraCellValidator(x))
          return false;
        if (hostFaction != null && map.reachability.CanReachFactionBase(x, hostFaction))
          return true;
        if (hostFaction == null)
          return map.reachability.CanReachBiggestMapEdgeRoom(x);
        return false;
      }), map, CellFinder.EdgeRoadChance_Neutral, out result))
        return CellFinder.RandomClosewalkCellNear(result, map, 5, (Predicate<IntVec3>) null);
      if (extraCellValidator != null && CellFinder.TryFindRandomEdgeCellWith((Predicate<IntVec3>) (x =>
      {
        if (baseValidator(x))
          return extraCellValidator(x);
        return false;
      }), map, CellFinder.EdgeRoadChance_Neutral, out result))
        return CellFinder.RandomClosewalkCellNear(result, map, 5, (Predicate<IntVec3>) null);
      if (CellFinder.TryFindRandomEdgeCellWith(baseValidator, map, CellFinder.EdgeRoadChance_Neutral, out result))
        return CellFinder.RandomClosewalkCellNear(result, map, 5, (Predicate<IntVec3>) null);
      Log.Warning("Could not find any valid edge cell.", false);
      return CellFinder.RandomCell(map);
    }


I tracked it back, and it looks like the extraCellValidator parameter is always going to be null for my case here.

I haven't dug through the function in detail yet, but it looks like it ends in a fail safe condition to return a random cell if all else failed. The issue is that it doesn't unfog the map in that case. I'm going to try and simply unfog the map on my side as a next step. That'll be just to see if it works, and to keep poking at this and learning stuff so that I can hopefully find a legit fix.