// 3rd step: Get the ThingDef of the position from the Non-BuildingData of the blueprint. private static ThingDef TryGetThingDefFromNonBuildingData(MapGeneratorBaseBlueprintDef blueprint, int itemPos) { if (blueprint.nonbuildingData == null || blueprint.nonbuildingData.Count() - 1 < itemPos || blueprint.nonbuildingLegend == null) { return(null); } char keyChar = blueprint.nonbuildingData.ElementAt(itemPos); string key = keyChar.ToString(); if (!blueprint.nonbuildingLegend.ContainsKey(key)) { return(null); } return(DefDatabase <ThingDef> .GetNamedSilentFail(blueprint.nonbuildingLegend[key])); }
// 5th step: Get the PawnKindDef of the position from the PawnData of the blueprint. private static PawnKindDef TryGetPawnKindDefFromPawnData(MapGeneratorBaseBlueprintDef blueprint, int itemPos) { if (blueprint.pawnData == null || blueprint.pawnData.Count() - 1 < itemPos || blueprint.pawnLegend == null) { return(null); } char keyChar = blueprint.pawnData.ElementAt(itemPos); string key = keyChar.ToString(); if (!blueprint.pawnLegend.ContainsKey(key)) { return(null); } return(blueprint.pawnLegend[key]); }
// 2nd step (b): Get the Rotation of the position from the BuildingData of the blueprint. private static Rot4 TryGetRotationFromBuildingData(MapGeneratorBaseBlueprintDef blueprint, int itemPos) { // Using buildingData and rotationLegend here.. if (blueprint.buildingData == null || blueprint.buildingData.Count() - 1 < itemPos || blueprint.rotationLegend == null) { return(Rot4.Invalid); } char keyChar = blueprint.buildingData.ElementAt(itemPos); string key = keyChar.ToString(); if (!blueprint.rotationLegend.ContainsKey(key)) { return(Rot4.Invalid); } return(blueprint.rotationLegend[key]); }
// Fill the cell with Pawn private static void TrySetCell_5_SetPawn(IntVec3 c, Map map, Faction faction, PawnKindDef pawnKindDef = null, MapGeneratorBaseBlueprintDef blueprint = null) { //Note: Here is no functionality to clear the cell by design, because it is possible to place items that are larger than 1x1 // The following needs blueprint data to work if (blueprint == null) { return; } // 5th step - work with the Pawn if (pawnKindDef != null && blueprint.pawnSpawnChance / 100 > Rand.Value) { if (blueprint.factionDef != null) { faction = Find.FactionManager.FirstFactionOfDef(blueprint.factionDef); } // null - find a valid faction. if (faction == null) { if ((from fac in Find.FactionManager.AllFactions where fac.HostileTo(Faction.OfPlayer) select fac).TryRandomElementByWeight((Faction fac) => 101 - fac.def.RaidCommonalityFromPoints(map.IncidentPointsRandomFactorRange.RandomInRange), out faction) == false) { faction = Faction.OfMechanoids; } } Pawn pawn = PawnGenerator.GeneratePawn(pawnKindDef, faction); //pawn.mindState.Active = true; pawn = GenSpawn.Spawn(pawn, c, map) as Pawn; if (pawn != null) { if (allSpawnedPawns == null) { allSpawnedPawns = new List <Pawn>(); } allSpawnedPawns.Add(pawn); } } }
// Fill the cell with Item private static void TrySetCell_4_SetItem(IntVec3 c, Map map, ThingDef itemDef = null, MapGeneratorBaseBlueprintDef blueprint = null) { //Note: Here is no functionality to clear the cell by design, because it is possible to place items that are larger than 1x1 // The following needs blueprint data to work if (blueprint == null) { return; } // 4th step - work with the Item //if (itemDef != null) // && blueprint.itemSpawnChance / 100 > Rand.Value) if (itemDef != null && blueprint.itemSpawnChance / 100 > Rand.Value) { ThingDef stuffDef2; if (itemDef.IsApparel) { if (!DefDatabase <ThingDef> .AllDefs.Where <ThingDef>(t => t.IsStuff && t.stuffProps != null && t.stuffProps.categories != null && t.stuffProps.categories.Contains(StuffCategoryDefOf.Fabric)) .TryRandomElement(out stuffDef2)) { stuffDef2 = DefDatabase <ThingDef> .GetNamedSilentFail("Synthread"); } } else { List <string> stuffPossibles = new List <string>() { "Steel", "Steel", "Steel", "Steel", "Silver", "Gold", "Jade", "Plasteel" }; stuffDef2 = DefDatabase <ThingDef> .GetNamedSilentFail(stuffPossibles.RandomElement()); } if (!itemDef.MadeFromStuff) { stuffDef2 = null; } Thing newItem = TryGetTreasure(itemDef, stuffDef2); newItem = GenSpawn.Spawn(newItem, c, map); // Don't forget to set the items to forbidden! if (newItem.TryGetComp <CompForbiddable>() != null) { newItem.SetForbidden(true, false); } // If it is a hive, it needs to be deactivated Hive newHive = newItem as Hive; //if (newHive != null) //{ // newHive.active = false; //} } }
public static void CreateBlueprintAt(IntVec3 c, Map map, MapGeneratorBaseBlueprintDef blueprint, Faction faction, ref ThingDef wallStuff, ref List <IntVec3> usedSpots) { if (working) { Log.Error("Called BlueprintHandler.CreateBlueprintAt(..) while it's still working. This is not allowed!"); return; } if (map == null) { Log.Error("Called BlueprintHandler.CreateBlueprintAt(..) with null map."); return; } working = true; allSpawnedPawns = new List <Pawn>(); pawnLord = null; rooms = new HashSet <Room>(); try { CellRect mapRect = new CellRect(c.x, c.z, blueprint.size.x, blueprint.size.z); mapRect.ClipInsideMap(map); // if mapRect was clipped -> the blueprint doesn't fit inside the map... if (mapRect.Width != blueprint.size.x || mapRect.Height != blueprint.size.z) { return; } //// Don't do anything, if there is an cryosleep casket at the building site //foreach (IntVec3 current in mapRect.Cells) //{ // List<Thing> list = map.thingGrid.ThingsListAt(current); // for (int i = 0; i < list.Count; i++) // { // if (list[i].def == ThingDefOf.AncientCryptosleepCasket) // return; // } // if (usedSpots != null) // usedSpots.Add(current); // prevent the base scatterer to use this spot again //} // If a building material is defined, use this if (blueprint.buildingMaterial != null && blueprint.buildingMaterial != "") { wallStuff = DefDatabase <ThingDef> .GetNamedSilentFail(blueprint.buildingMaterial); } // Make all buildings from the same random stuff if (wallStuff == null) { wallStuff = BaseGenUtility.RandomCheapWallStuff(faction, false); } MakeBlueprintObject(map, faction, mapRect, blueprint, wallStuff); if (blueprint.createTrigger) { int nextSignalTagID = Find.UniqueIDsManager.GetNextSignalTagID(); string signalTag = "unfogBaseAreaTriggerSignal-" + nextSignalTagID; SignalAction_Letter signalAction_Letter = ThingMaker.MakeThing(ThingDefOf.SignalAction_Letter, null) as SignalAction_Letter; if (signalAction_Letter != null) { signalAction_Letter.signalTag = signalTag; if (blueprint.TriggerLetterMessageText != null) { if (blueprint.TriggerLetterDef == null) { blueprint.TriggerLetterDef = LetterDefOf.ThreatSmall; } if (blueprint.TriggerLetterLabel != null) { signalAction_Letter.letter = LetterMaker.MakeLetter(blueprint.TriggerLetterLabel.Translate(), blueprint.TriggerLetterMessageText.Translate(), blueprint.TriggerLetterDef, new GlobalTargetInfo(mapRect.CenterCell, map, false)); } else { signalAction_Letter.letter = LetterMaker.MakeLetter("", blueprint.TriggerLetterMessageText.Translate(), blueprint.TriggerLetterDef, new GlobalTargetInfo(mapRect.CenterCell, map)); } GenSpawn.Spawn(signalAction_Letter, mapRect.CenterCell, map); } } RectTrigger_UnfogBaseArea rectTrigger = ThingMaker.MakeThing(ThingDef.Named("RectTrigger_UnfogBaseArea"), null) as RectTrigger_UnfogBaseArea; if (rectTrigger != null) { rectTrigger.signalTag = signalTag; rectTrigger.destroyIfUnfogged = true; rectTrigger.Rect = mapRect; GenSpawn.Spawn(rectTrigger, mapRect.CenterCell, map); } } map.regionAndRoomUpdater.RebuildAllRegionsAndRooms(); HashSet <Room> rooms = new HashSet <Room>(); foreach (IntVec3 current in mapRect.Cells) { // Find all created rooms Room room = current.GetRoom(map, RegionType.Set_All); if (room != null && !room.TouchesMapEdge) { rooms.Add(room); } } // Add rooms to unfog area AddRoomCentersToRootsToUnfog(rooms.ToList()); // Create roof foreach (Room room in rooms) { BuildRoofToRoom(room, false); } map.roofGrid.RoofGridUpdate(); } catch (Exception ex) { string errBP = ""; if (blueprint != null) { errBP = blueprint.defName; } Log.Error("Error in BlueprintHandler.CreateBlueprintAt(..) '" + errBP + "': " + ex); } finally { // Whatever happends, when its done, reset the working state. working = false; // Clear all data holder allSpawnedPawns = null; pawnLord = null; rooms = null; } }
private static void MakeBlueprintObject(Map map, Faction faction, CellRect mapRect, MapGeneratorBaseBlueprintDef blueprint, ThingDef stuffDef) { blueprint.buildingData = GetCleanedBlueprintData(blueprint.buildingData); blueprint.nonbuildingData = GetCleanedBlueprintData(blueprint.nonbuildingData); blueprint.floorData = GetCleanedBlueprintData(blueprint.floorData); blueprint.pawnData = GetCleanedBlueprintData(blueprint.pawnData); blueprint.itemData = GetCleanedBlueprintData(blueprint.itemData); if (blueprint.buildingData == null && blueprint.nonbuildingData == null && blueprint.floorData == null) { Log.ErrorOnce(string.Format("After cleaning the BlueprintData and FloorData of blueprint {0} -> both are null, nothing will be done!", blueprint.defName), 313001); return; } IntVec3 spawnBaseCell = new IntVec3(mapRect.BottomLeft.x, mapRect.TopRight.y, mapRect.TopRight.z); IntVec3 spawnCell; //// Check all cells and abort if there is something indestructible found -> disabled //foreach (IntVec3 cell in mapRect) //{ // if (!CheckCell(cell, map)) // return; //} allSpawnedPawns = null; // Disable automatic room updating map.regionAndRoomUpdater.Enabled = false; int step = 1; while (step <= 5) { //Log.Warning("Current step: " + step); // Work through blueprint - Note: top-left to bottom-right // Work step by step: 1st all floors, 2nd all things, 3rd all items, 4th all pawns for (int zn = 0; zn < blueprint.size.z; zn++) { for (int x = 0; x < blueprint.size.x; x++) { //// map can be clipped, don't work with the clipped parts //if (x > mapRect.Width - 1 || zn > mapRect.Height - 1) // continue; if (blueprint.canHaveHoles && Rand.Value < 0.08f) { continue; } spawnCell = spawnBaseCell + new IntVec3(x, 0, -zn); if (!TrySetCell_prepare_CheckCell(spawnCell, map)) { continue; } int itemPos = x + blueprint.size.x * zn; try { ThingDef thingDef = TryGetThingDefFromBuildingData(blueprint, itemPos); Rot4 thingRot = TryGetRotationFromBuildingData(blueprint, itemPos); ThingDef nonthingDef = TryGetThingDefFromNonBuildingData(blueprint, itemPos); TerrainDef terrainDef = TryGetTerrainDefFromFloorData(blueprint, itemPos); PawnKindDef pawnKindDef = TryGetPawnKindDefFromPawnData(blueprint, itemPos); ThingDef itemDef = TryGetItemDefFromItemData(blueprint, itemPos); //List<Thing> list = map.thingGrid.ThingsListAt(spawnCell); //for (int i = 0; i < list.Count; i++) //{ // if (list[i].def == thingDef) // continue; //} //Only clear the space, if something will be made here // Do only in step 1: if (step == 1) { if (thingDef != null || terrainDef != null || pawnKindDef != null || itemDef != null) { ClearCell(spawnCell, map); } } switch (step) { case 1: // Terrain TrySetCell_1_SetFloor(spawnCell, map, terrainDef, thingDef, stuffDef); break; case 2: // non-Building TrySetCell_3_SetNonThing(spawnCell, map, nonthingDef); break; case 3: // Building TrySetCell_2_SetThing(spawnCell, map, faction, thingDef, thingRot, stuffDef); break; case 4: // Item TrySetCell_4_SetItem(spawnCell, map, itemDef, blueprint); break; case 5: // Pawn TrySetCell_5_SetPawn(spawnCell, map, faction, pawnKindDef, blueprint); break; default: return; } } catch (Exception ex) { Log.Warning("MapGeneratorFactionBase - Error while creating the blueprint (" + blueprint.defName + ")\n" + ex.Message + "\n" + ex.StackTrace); } } } step++; } // Update the powernets map.powerNetManager.UpdatePowerNetsAndConnections_First(); // Enable automatic room updating and rebuild all rooms map.regionAndRoomUpdater.Enabled = true; map.regionAndRoomUpdater.RebuildAllRegionsAndRooms(); HashSet <Room> rooms = new HashSet <Room>(); foreach (IntVec3 current in mapRect.Cells) { // Find all created rooms Room room = current.GetRoom(map); if (room != null && !room.TouchesMapEdge) { rooms.Add(room); } } // Add rooms to unfog area AddRoomCentersToRootsToUnfog(rooms.ToList()); // make the appropriate Lord pawnLord = LordMaker.MakeNewLord(faction, new LordJob_DefendBase(faction, mapRect.CenterCell), map, null); // Get points used by current pawns float pointsUsed = 0f; if (allSpawnedPawns != null && allSpawnedPawns.Count > 0) { foreach (Pawn pawnSpawned in allSpawnedPawns) { pointsUsed += pawnSpawned.kindDef.combatPower; } } // Make additional pawns if these are not enough! if (allSpawnedPawns == null || allSpawnedPawns.Count == 0 || pointsUsed < (faction.def.techLevel == TechLevel.Neolithic ? NeolithicPawnsPoints.min : NonNeolithicPawnsPoints.min)) { //Log.Warning("Info: Creating base pawns.."); PrepareBaseGen_PawnGroup(map, mapRect, faction, rooms.ToList(), pawnLord, pointsUsed); } PrepareBaseGen_CampFires(map, mapRect, faction); BaseGen.Generate(); if (allSpawnedPawns != null) { foreach (Pawn pawn in allSpawnedPawns) { pawnLord.AddPawn(pawn); } } allSpawnedPawns = null; }
protected override void ScatterAt(IntVec3 c, Map map, int stackCount = 1) { if (testActive) { Log.Warning("Genstep_CreateBlueprintBase - Test-Mode is active!"); } Faction faction; if (map.info.parent == null || map.info.parent.Faction == null || map.info.parent.Faction == Faction.OfPlayer) { faction = Find.FactionManager.RandomEnemyFaction(false, false, false); } else { faction = map.info.parent.Faction; } int worldTile = -1; if (map != null) { worldTile = map.Tile; } TechLevel techlevel = faction.def.techLevel; // Select only blueprints with a techlevel corresponding to the faction techlevel IEnumerable <MapGeneratorBaseBlueprintDef> blueprint1stSelection = DefDatabase <MapGeneratorBaseBlueprintDef> .AllDefsListForReading .Where((MapGeneratorBaseBlueprintDef b) => b.techLevelRequired <= techlevel && (b.techLevelMax == TechLevel.Undefined || b.techLevelMax >= techlevel)); float createVanillaLimit = 0.95f; if (blueprint1stSelection != null && blueprint1stSelection.Count() > 0) { if (blueprint1stSelection.Count() <= 3) { createVanillaLimit = 0.85f; } else if (blueprint1stSelection.Count() <= 5) { createVanillaLimit = 0.80f; } else if (blueprint1stSelection.Count() <= 7) { createVanillaLimit = 0.70f; } else if (blueprint1stSelection.Count() <= 10) { createVanillaLimit = 0.65f; } else if (blueprint1stSelection.Count() <= 15) { createVanillaLimit = 0.50f; } else if (blueprint1stSelection.Count() <= 20) { createVanillaLimit = 0.45f; } else { createVanillaLimit = 0.35f; } } if (blueprint1stSelection == null || blueprint1stSelection.Count() == 0) { Log.Warning("Genstep_CreateBlueprintBase - no usable blueprint found. Using vanilla base generation.."); } if (blueprint1stSelection == null || blueprint1stSelection.Count() == 0 || (!testActive && randomlyUseVanilla && Rand.Value < createVanillaLimit && (mapWorldCoord2Blueprint == null || !mapWorldCoord2Blueprint.ContainsKey(worldTile)) )) { // No blueprint for this faction techlevel found? // Use basic base builder code instead! Core_ScatterAt(c, map, stackCount); return; } MapGeneratorBaseBlueprintDef blueprint = blueprint1stSelection.RandomElementByWeight((MapGeneratorBaseBlueprintDef b) => b.chance); // Check if this position was already used -> re-use old blueprint if (mapWorldCoord2Blueprint == null) { mapWorldCoord2Blueprint = new Dictionary <int, string>(); } if (mapWorldCoord2Blueprint.ContainsKey(worldTile)) { MapGeneratorBaseBlueprintDef newBlueprint = DefDatabase <MapGeneratorBaseBlueprintDef> .GetNamedSilentFail(mapWorldCoord2Blueprint[worldTile]); if (newBlueprint != null && newBlueprint.techLevelRequired <= faction.def.techLevel && newBlueprint.techLevelMax >= faction.def.techLevel) { blueprint = newBlueprint; } } else if (worldTile != -1) { mapWorldCoord2Blueprint.Add(worldTile, blueprint.defName); } // place the blueprint BlueprintHandler.CreateBlueprintAt(c, map, blueprint, faction, ref selectedWallStuff, ref usedSpots); // reset selectedWallStuff = null; // Add a message to honor the creator if (!blueprint.createdBy.NullOrEmpty()) { string label = "MapGenerator_FactionBase_Header_ProvidedBy".Translate(); string text = "MapGenerator_FactionBase_Body_ProvidedBy".Translate(new object[] { blueprint.createdBy }); Find.LetterStack.ReceiveLetter(label, text, LetterDefOf.PositiveEvent, new GlobalTargetInfo(c, map)); } }