Example #1
0
        public void Transfer(CoverageMap coverageMap)
        {
            //Planting blueprint
            float totalCost           = 0;
            int   transferredTerrains = 0;
            int   transferredTiles    = 0;
            int   totalTerrains       = 0;
            int   totalItems          = 0;

            //update rect to actual placement rect using width and height
            rp.rect = new CellRect(mapOriginX, mapOriginZ, blueprint.width, blueprint.height);

            Debug.Extra(Debug.BlueprintTransfer, "Clearing map...");

            for (int z = 0; z < blueprint.height; z++)
            {
                for (int x = 0; x < blueprint.width; x++)
                {
                    try {
                        IntVec3 mapLocation = new IntVec3(x + mapOriginX, 0, z + mapOriginZ);
                        //Check if thepoint is in allowed bounds of the map
                        if (!mapLocation.InBounds(map) || mapLocation.InNoBuildEdgeArea(map))
                        {
                            continue; //ignore invalid cells
                        }

                        if (options.overwritesEverything || Rand.Chance(0.6f))
                        {
                            if (blueprint.terrainMap[x, z] != null ||
                                blueprint.itemsMap[x, z].Count > 0 ||
                                blueprint.wallMap[x, z] > 1)
                            {
                                ClearCell(mapLocation, map, true);
                            }
                        }
                    } catch (Exception e) {
                        Debug.Warning(Debug.BlueprintTransfer, "Failed to clean cell at {0}, {1} because of {2}", x, z, e);
                    }
                }
            }

            Debug.Extra(Debug.BlueprintTransfer, "Transferring map objects");
            for (int z = 0; z < blueprint.height; z++)
            {
                for (int x = 0; x < blueprint.width; x++)
                {
                    IntVec3 mapLocation = new IntVec3(x + mapOriginX, 0, z + mapOriginZ);
                    if (coverageMap != null)
                    {
                        if (coverageMap.isMarked(mapLocation.x, mapLocation.z) == true) //cell was used earlier
                        {
                            continue;                                                   //skip already covered tiles
                        }
                        else
                        {
                            if (blueprint.wallMap[x, z] > 1 || blueprint.wallMap[x, z] == -1)
                            {
                                coverageMap.Mark(mapLocation.x, mapLocation.z);                                                               //mark cell as used
                            }
                        }
                    }


                    //Check if thepoint is in allowed bounds of the map
                    if (!mapLocation.InBounds(map) || mapLocation.InNoBuildEdgeArea(map))
                    {
                        continue; //ignore invalid cells
                    }

                    try {
                        //Construct terrain if some specific terrain stored in the blueprint
                        if (blueprint.terrainMap[x, z] != null)
                        {
                            totalTerrains++;
                            TerrainDef blueprintTerrain = TerrainDef.Named(blueprint.terrainMap[x, z].defName);
                            if (!map.terrainGrid.TerrainAt(mapLocation).IsWater)
                            {
                                map.terrainGrid.SetTerrain(mapLocation, blueprintTerrain);
                                totalCost += blueprint.terrainMap[x, z].cost;
                                transferredTerrains++;
                            }
                        }


                        //construct roof evetywhere if we doing complete transfer (ignoring outside: room with index 1).
                        if (blueprint.roofMap[x, z] == true && options.overwritesEverything && blueprint.wallMap[x, z] != 1)
                        {
                            map.roofGrid.SetRoof(mapLocation, RoofDefOf.RoofConstructed);
                        }


                        Debug.Extra(Debug.BlueprintTransfer, "Transferred terrain and roof at cell ({0}, {1})", x, z);
                    } catch (Exception e) {
                        Debug.Warning(Debug.BlueprintTransfer, "Failed to transfer terrain {0} at {1}, {2} because of {3}", blueprint.terrainMap[x, z].defName, x, z, e);
                    }

                    //Add items
                    if (blueprint.itemsMap[x, z] != null && blueprint.itemsMap[x, z].Count > 0 /* && cellUsed[mapLocation.x, mapLocation.z] == false*/)
                    {
                        totalItems += blueprint.itemsMap[x, z].Count;


                        foreach (ItemTile itemTile in blueprint.itemsMap[x, z])
                        {
                            Debug.Extra(Debug.BlueprintTransfer, "Creating thing {2} at cell ({0}, {1})", x, z, itemTile.defName);
                            Thing thing = MakeThingFromItemTile(itemTile);
                            if (thing != null)
                            {
                                try {
                                    Rot4 rotation = new Rot4(itemTile.rot);
                                    //check if there is anything we have to despawn in order to spawn our new item
                                    //we have to do this, because many dubs bad hygiene items enter endless cycle when removed during mapgen.
                                    foreach (IntVec3 occupiedCell in GenAdj.CellsOccupiedBy(mapLocation, rotation, thing.def.Size))
                                    {
                                        foreach (Thing existingItem in map.thingGrid.ThingsAt(occupiedCell).ToList())
                                        {
                                            if (GenSpawn.SpawningWipes(thing.def, existingItem.def))
                                            {
                                                if (thing.def.thingClass.ToString().Contains("DubsBadHygiene"))
                                                {
                                                    throw new Exception("Can't spawn item because it will destroy Dubs Bad Hygiene Item and it will lead to app freeze.");
                                                }
                                                existingItem.Destroy(DestroyMode.Vanish);
                                            }
                                        }
                                    }



                                    GenSpawn.Spawn(thing, mapLocation, map, rotation);
                                    Debug.Extra(Debug.BlueprintTransfer, "Spawned");
                                    try {
                                        switch (thing.def.tickerType)
                                        {
                                        case TickerType.Never:
                                            break;

                                        case TickerType.Normal:
                                            thing.Tick();
                                            break;

                                        case TickerType.Long:
                                            thing.TickLong();
                                            break;

                                        case TickerType.Rare:
                                            thing.TickRare();
                                            break;
                                        }
                                        //Debug.Message("Ticked");
                                    } catch (Exception e) {
                                        Debug.Log(Debug.BlueprintTransfer, "Exception while tried to perform tick for {0} of cost {1}, retrhrowing...", thing.def.defName, itemTile.cost);
                                        thing.Destroy();
                                        throw e;
                                    }

                                    //Debug.Message("Setting up props");
                                    //Breakdown breakdownables: it't yet impossible to silently breakdown an item which is not spawned.
                                    CompBreakdownable b = thing.TryGetComp <CompBreakdownable>();
                                    if (b != null && options.enableDeterioration)
                                    {
                                        if (Rand.Chance(0.8f))
                                        {
                                            b.DoBreakdown();
                                        }
                                    }

                                    //reduce HP for haulable things in water
                                    if (thing.def.EverHaulable)
                                    {
                                        TerrainDef t = map.terrainGrid.TerrainAt(mapLocation);
                                        if (t != null && t.IsWater)
                                        {
                                            thing.HitPoints = (thing.HitPoints - 10) / Rand.Range(5, 20) + Rand.Range(1, 10); //things in marsh or river are really in bad condition
                                        }
                                    }
                                    Debug.Extra(Debug.BlueprintTransfer, "Item completed");

                                    transferredTiles++;
                                    totalCost += itemTile.cost;
                                } catch (Exception e) {
                                    Debug.Warning(Debug.BlueprintTransfer, "Failed to spawn item {0} of cost {1} because of exception {2}", thing, itemTile.cost, e.Message);
                                    //ignore
                                }
                            }
                        }
                    }
                }
            }

            Debug.Log(Debug.BlueprintTransfer, "Finished transferring");
            if (options.shouldKeepDefencesAndPower)
            {
                RestoreDefencesAndPower();
            }
            options.uncoveredCost = totalCost;
            Debug.Log(Debug.BlueprintTransfer, "Transferred blueprint of size {0}x{1}, age {2}, total cost of approximately {3}. Items: {4}/{5}, terrains: {6}/{7}", blueprint.width, blueprint.height, -blueprint.dateShift, totalCost, transferredTiles, totalItems, transferredTerrains, totalTerrains);
        }
        public void Transfer()
        {
            //Planting blueprint
            float totalCost           = 0;
            int   transferredTerrains = 0;
            int   transferredTiles    = 0;
            int   totalTerrains       = 0;
            int   totalItems          = 0;

            //update rect to actual placement rect using width and height
            rp.rect = new CellRect(mapOriginX, mapOriginZ, blueprint.width, blueprint.height);
            CoverageMap coverageMap = null;

            rp.TryGetCustom <CoverageMap>(Constants.CoverageMap, out coverageMap);

            for (int z = 0; z < blueprint.height; z++)
            {
                for (int x = 0; x < blueprint.width; x++)
                {
                    IntVec3 mapLocation = new IntVec3(x + mapOriginX, 0, z + mapOriginZ);
                    //Check if thepoint is in allowed bounds of the map
                    if (!mapLocation.InBounds(map) || mapLocation.InNoBuildEdgeArea(map))
                    {
                        continue; //ignore invalid cells
                    }

                    if (options.overwritesEverything || Rand.Chance(0.6f))
                    {
                        if (blueprint.terrainMap[x, z] != null ||
                            blueprint.itemsMap[x, z].Count > 0 ||
                            blueprint.wallMap[x, z] > 1)
                        {
                            ClearCell(mapLocation, map, true);
                        }
                    }
                }
            }


            for (int z = 0; z < blueprint.height; z++)
            {
                for (int x = 0; x < blueprint.width; x++)
                {
                    IntVec3 mapLocation = new IntVec3(x + mapOriginX, 0, z + mapOriginZ);
                    if (coverageMap != null)
                    {
                        if (coverageMap.isMarked(mapLocation.x, mapLocation.z) == true) //cell was used earlier
                        {
                            continue;                                                   //skip already covered tiles
                        }
                        else
                        {
                            if (blueprint.wallMap[x, z] > 1 || blueprint.wallMap[x, z] == -1)
                            {
                                coverageMap.Mark(mapLocation.x, mapLocation.z);                                                               //mark cell as used
                            }
                        }
                    }

                    //Check if thepoint is in allowed bounds of the map
                    if (!mapLocation.InBounds(map) || mapLocation.InNoBuildEdgeArea(map))
                    {
                        continue; //ignore invalid cells
                    }

                    //Construct terrain if some specific terrain stored in the blueprint
                    if (blueprint.terrainMap[x, z] != null)
                    {
                        totalTerrains++;
                        TerrainDef blueprintTerrain = TerrainDef.Named(blueprint.terrainMap[x, z].defName);
                        if (!map.terrainGrid.TerrainAt(mapLocation).IsWater)
                        {
                            map.terrainGrid.SetTerrain(mapLocation, blueprintTerrain);
                            totalCost += blueprint.terrainMap[x, z].cost;
                            transferredTerrains++;
                        }
                    }

                    //construct roof evetywhere if we doing complete transfer (ignoring outside: room with index 1).
                    if (blueprint.roofMap[x, z] == true && options.overwritesEverything && blueprint.wallMap[x, z] != 1)
                    {
                        map.roofGrid.SetRoof(mapLocation, RoofDefOf.RoofConstructed);
                    }


                    //Add items
                    if (blueprint.itemsMap[x, z] != null && blueprint.itemsMap[x, z].Count > 0 /* && cellUsed[mapLocation.x, mapLocation.z] == false*/)
                    {
                        totalItems += blueprint.itemsMap[x, z].Count;

                        bool cellIsAlreadyCleared = false;
                        foreach (ItemTile itemTile in blueprint.itemsMap[x, z])
                        {
                            if (!cellIsAlreadyCleared)   //first item to be spawned should also clear place for itself. we can't do it beforehand because we don't know if it will be able and get a chance to be spawned.
                            {
                                bool forceCleaning = (blueprint.wallMap[x, z] > 1) && Rand.Chance(0.9f);

                                if (!ClearCell(mapLocation, map, forceCleaning))
                                {
                                    break; //if cell was not cleared successfully -> break things placement cycle and move on to the next item
                                }
                                else
                                {
                                    cellIsAlreadyCleared = true;
                                }
                            }

                            Thing thing = MakeThingFromItemTile(itemTile);
                            if (thing != null)
                            {
                                try {
                                    GenSpawn.Spawn(thing, mapLocation, map, new Rot4(itemTile.rot));
                                    try {
                                        switch (thing.def.tickerType)
                                        {
                                        case TickerType.Never:
                                            break;

                                        case TickerType.Normal:
                                            thing.Tick();
                                            break;

                                        case TickerType.Long:
                                            thing.TickLong();
                                            break;

                                        case TickerType.Rare:
                                            thing.TickRare();
                                            break;
                                        }
                                        //Debug.Message("Ticked");
                                    } catch (Exception e) {
                                        //Debug.Message("Exception while tried to perform tick for {0} of cost {1}", thing.def.defName, itemTile.cost);
                                        thing.Destroy();
                                        throw e;
                                    }

                                    //Debug.Message("Setting up props");
                                    //Breakdown breakdownables: it't yet impossible to silently breakdown an item which is not spawned.
                                    CompBreakdownable b = thing.TryGetComp <CompBreakdownable>();
                                    if (b != null && options.enableDeterioration)
                                    {
                                        if (Rand.Chance(0.8f))
                                        {
                                            b.DoBreakdown();
                                        }
                                    }

                                    //reduce HP for haulable things in water
                                    if (thing.def.EverHaulable)
                                    {
                                        TerrainDef t = map.terrainGrid.TerrainAt(mapLocation);
                                        if (t != null && t.IsWater)
                                        {
                                            thing.HitPoints = (thing.HitPoints - 10) / Rand.Range(5, 20) + Rand.Range(1, 10); //things in marsh or river are really in bad condition
                                        }
                                    }
                                    transferredTiles++;
                                    totalCost += itemTile.cost;
                                } catch (Exception e) {
                                    //Debug.Message("Failed to spawn item {0} of cost {1} because of exception", thing, itemTile.cost);
                                    //ignore
                                }
                            }
                        }
                    }
                }

                if (options.shouldKeepDefencesAndPower)
                {
                    RestoreDefencesAndPower();
                }
                options.uncoveredCost = totalCost;
            }
            Debug.Log(Debug.BlueprintTransfer, "Transferred blueprint of size {0}x{1}, age {2}, total cost of approximately {3}. Items: {4}/{5}, terrains: {6}/{7}", blueprint.width, blueprint.height, -blueprint.dateShift, totalCost, transferredTiles, totalItems, transferredTerrains, totalTerrains);
        }