diff options
Diffstat (limited to 'src/Generating/VillageGen.cpp')
-rw-r--r-- | src/Generating/VillageGen.cpp | 174 |
1 files changed, 82 insertions, 92 deletions
diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp index a3f8caa46..2475565c0 100644 --- a/src/Generating/VillageGen.cpp +++ b/src/Generating/VillageGen.cpp @@ -5,11 +5,6 @@ #include "Globals.h" #include "VillageGen.h" -#include "Prefabs/AlchemistVillagePrefabs.h" -#include "Prefabs/JapaneseVillagePrefabs.h" -#include "Prefabs/PlainsVillagePrefabs.h" -#include "Prefabs/SandVillagePrefabs.h" -#include "Prefabs/SandFlatRoofVillagePrefabs.h" #include "PieceGenerator.h" @@ -52,6 +47,16 @@ public: ) : super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs) { + AddRoadPieces(); + } + + cVillagePiecePool(void) + { + AddRoadPieces(); + } + + void AddRoadPieces(void) + { // Add the road pieces: for (int len = 27; len < 60; len += 12) { @@ -93,7 +98,7 @@ public: return 0; } - return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector); + return static_cast<const cPrefab &>(a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector); } }; @@ -115,10 +120,8 @@ public: int a_MaxRoadDepth, int a_MaxSize, int a_Density, - cPiecePool & a_Prefabs, - cTerrainHeightGenPtr a_HeightGen, - BLOCKTYPE a_RoadBlock, - BLOCKTYPE a_WaterRoadBlock + cVillagePiecePool & a_Prefabs, + cTerrainHeightGenPtr a_HeightGen ) : super(a_GridX, a_GridZ, a_OriginX, a_OriginZ), m_Seed(a_Seed), @@ -127,9 +130,7 @@ public: m_Density(a_Density), m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, cChunkDef::Height - 1, a_OriginZ + a_MaxSize), m_Prefabs(a_Prefabs), - m_HeightGen(a_HeightGen), - m_RoadBlock(a_RoadBlock), - m_WaterRoadBlock(a_WaterRoadBlock) + m_HeightGen(a_HeightGen) { // Generate the pieces for this village; don't care about the Y coord: cBFSPieceGenerator pg(*this, a_Seed); @@ -141,7 +142,7 @@ public: // If the central piece should be moved to ground, move it, and // check all of its dependents and move those that are strictly connector-driven based on its new Y coord: - if (((cPrefab &)m_Pieces[0]->GetPiece()).ShouldMoveToGround()) + if (static_cast<const cPrefab &>(m_Pieces[0]->GetPiece()).ShouldMoveToGround()) { int OrigPosY = m_Pieces[0]->GetCoords().y; PlacePieceOnGround(*m_Pieces[0]); @@ -172,7 +173,7 @@ protected: cCuboid m_Borders; /** Prefabs to use for buildings */ - cPiecePool & m_Prefabs; + cVillagePiecePool & m_Prefabs; /** The underlying height generator, used for placing the structures on top of the terrain. */ cTerrainHeightGenPtr m_HeightGen; @@ -180,12 +181,6 @@ protected: /** The village pieces, placed by the generator. */ cPlacedPieces m_Pieces; - /** The block to use for the roads. */ - BLOCKTYPE m_RoadBlock; - - /** The block used for the roads if the road is on water. */ - BLOCKTYPE m_WaterRoadBlock; - // cGridStructGen::cStructure overrides: virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override @@ -197,7 +192,7 @@ protected: m_HeightGen->GenHeightMap(a_Chunk.GetChunkX(), a_Chunk.GetChunkZ(), HeightMap); for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr) { - cPrefab & Prefab = (cPrefab &)((*itr)->GetPiece()); + const cPrefab & Prefab = static_cast<const cPrefab &>((*itr)->GetPiece()); if ((*itr)->GetPiece().GetSize().y == 1) { // It's a road, special handling (change top terrain blocks to m_RoadBlock) @@ -241,17 +236,21 @@ protected: int MaxX = std::min(RoadCoords.p2.x - a_Chunk.GetChunkX() * cChunkDef::Width, cChunkDef::Width - 1); int MinZ = std::max(RoadCoords.p1.z - a_Chunk.GetChunkZ() * cChunkDef::Width, 0); int MaxZ = std::min(RoadCoords.p2.z - a_Chunk.GetChunkZ() * cChunkDef::Width, cChunkDef::Width - 1); + auto WaterRoadBlockType = m_Prefabs.GetVillageWaterRoadBlockType(); + auto WaterRoadBlockMeta = m_Prefabs.GetVillageWaterRoadBlockMeta(); + auto RoadBlockType = m_Prefabs.GetVillageRoadBlockType(); + auto RoadBlockMeta = m_Prefabs.GetVillageRoadBlockMeta(); for (int z = MinZ; z <= MaxZ; z++) { for (int x = MinX; x <= MaxX; x++) { if (IsBlockWater(a_Chunk.GetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z))) { - a_Chunk.SetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, m_WaterRoadBlock); + a_Chunk.SetBlockTypeMeta(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, WaterRoadBlockType, WaterRoadBlockMeta); } else { - a_Chunk.SetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, m_RoadBlock); + a_Chunk.SetBlockTypeMeta(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, RoadBlockType, RoadBlockMeta); } } } @@ -259,13 +258,13 @@ protected: // cPiecePool overrides: - virtual cPieces GetPiecesWithConnector(int a_ConnectorType) + virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override { return m_Prefabs.GetPiecesWithConnector(a_ConnectorType); } - virtual cPieces GetStartingPieces(void) + virtual cPieces GetStartingPieces(void) override { return m_Prefabs.GetStartingPieces(); } @@ -319,7 +318,7 @@ protected: { if ( (a_PlacedPieces[i]->GetParent() == Pivot) && // It is a direct dependant of the pivot - !((const cPrefab &)a_PlacedPieces[i]->GetPiece()).ShouldMoveToGround() // It attaches strictly by connectors + !(static_cast<const cPrefab &>(a_PlacedPieces[i]->GetPiece())).ShouldMoveToGround() // It attaches strictly by connectors ) { a_PlacedPieces[i]->MoveToGroundBy(a_HeightDifference); @@ -336,30 +335,18 @@ protected: //////////////////////////////////////////////////////////////////////////////// // cVillageGen: -static cVillagePiecePool g_SandVillage(g_SandVillagePrefabs, g_SandVillagePrefabsCount, g_SandVillageStartingPrefabs, g_SandVillageStartingPrefabsCount); -static cVillagePiecePool g_SandFlatRoofVillage(g_SandFlatRoofVillagePrefabs, g_SandFlatRoofVillagePrefabsCount, g_SandFlatRoofVillageStartingPrefabs, g_SandFlatRoofVillageStartingPrefabsCount); -static cVillagePiecePool g_AlchemistVillage(g_AlchemistVillagePrefabs, g_AlchemistVillagePrefabsCount, g_AlchemistVillageStartingPrefabs, g_AlchemistVillageStartingPrefabsCount); -static cVillagePiecePool g_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillagePrefabsCount, g_PlainsVillageStartingPrefabs, g_PlainsVillageStartingPrefabsCount); -static cVillagePiecePool g_JapaneseVillage(g_JapaneseVillagePrefabs, g_JapaneseVillagePrefabsCount, g_JapaneseVillageStartingPrefabs, g_JapaneseVillageStartingPrefabsCount); - -static cVillagePiecePool * g_DesertVillagePools[] = -{ - &g_SandVillage, - &g_SandFlatRoofVillage, - &g_AlchemistVillage, -} ; - -static cVillagePiecePool * g_PlainsVillagePools[] = -{ - &g_PlainsVillage, - &g_JapaneseVillage, -} ; - - - - - -cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxDepth, int a_MaxSize, int a_MinDensity, int a_MaxDensity, cBiomeGenPtr a_BiomeGen, cTerrainHeightGenPtr a_HeightGen) : +cVillageGen::cVillageGen( + int a_Seed, + int a_GridSize, + int a_MaxOffset, + int a_MaxDepth, + int a_MaxSize, + int a_MinDensity, + int a_MaxDensity, + cBiomeGenPtr a_BiomeGen, + cTerrainHeightGenPtr a_HeightGen, + const AStringVector & a_PrefabsToLoad +) : super(a_Seed, a_GridSize, a_GridSize, a_MaxOffset, a_MaxOffset, a_MaxSize, a_MaxSize, 100), m_Noise(a_Seed + 1000), m_MaxDepth(a_MaxDepth), @@ -369,6 +356,21 @@ cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxOffset, int a_MaxD m_BiomeGen(a_BiomeGen), m_HeightGen(a_HeightGen) { + for (const auto & toLoad: a_PrefabsToLoad) + { + auto prefabs = std::make_shared<cVillagePiecePool>(); + auto fileName = Printf("Prefabs%sVillages%s%s.cubeset", cFile::GetPathSeparator().c_str(), cFile::GetPathSeparator().c_str(), toLoad.c_str()); + if (prefabs->LoadFromFile(fileName, true)) + { + if (NoCaseCompare(prefabs->GetIntendedUse(), "village") != 0) + { + LOGWARNING("Village generator: File %s is intended for use in \"%s\", rather than villages. Loading the file, but the generator may behave unexpectedly.", + fileName.c_str(), prefabs->GetIntendedUse().c_str() + ); + } + m_Pools.push_back(std::move(prefabs)); + } + } } @@ -383,60 +385,48 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_GridX, int a_Gr cChunkDef::BiomeMap Biomes; m_BiomeGen->GenBiomes(ChunkX, ChunkZ, Biomes); - // Check if all the biomes are village-friendly: - // If just one is not, no village is created, because it's likely that an unfriendly biome is too close - cVillagePiecePool * VillagePrefabs = nullptr; - BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL; - BLOCKTYPE WaterRoadBlock = E_BLOCK_PLANKS; - int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11; - cVillagePiecePool * PlainsVillage = g_PlainsVillagePools[rnd % ARRAYCOUNT(g_PlainsVillagePools)]; - cVillagePiecePool * DesertVillage = g_DesertVillagePools[rnd % ARRAYCOUNT(g_DesertVillagePools)]; + // Get a list of pools that support each biome within the chunk: + // If just one column's biome is not allowed, the pool is not used because it's likely that an unfriendly biome is too close + auto availablePools = m_Pools; for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++) { - switch (Biomes[i]) - { - case biDesert: - case biDesertM: + auto biome = Biomes[i]; + availablePools.erase(std::remove_if(availablePools.begin(), availablePools.end(), + [biome](SharedPtr<cPrefabPiecePool> a_Pool) { - // These biomes allow sand villages - VillagePrefabs = DesertVillage; - // RoadBlock = E_BLOCK_SANDSTONE; - break; - } - case biPlains: - case biSavanna: - case biSavannaM: - case biSunflowerPlains: - { - // These biomes allow plains-style villages - VillagePrefabs = PlainsVillage; - break; - } - default: - { - // Village-unfriendly biome, bail out with zero structure: - return cStructurePtr(); - } - } // switch (Biomes[i]) - } // for i - Biomes[] + return !a_Pool->IsBiomeAllowed(biome); + }), + availablePools.end() + ); + // Bail out if no compatible pools left: + if (availablePools.empty()) + { + return cStructurePtr(); + } + } + + // Pick one pool from the available pools: + if (availablePools.empty()) + { + return cStructurePtr(); + } + auto rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11; + auto pool = availablePools[static_cast<size_t>(rnd) % availablePools.size()]; + rnd /= 137; // Choose density for the village, random between m_MinDensity and m_MaxDensity: int Density; - if (m_MaxDensity > m_MinDensity) + if (pool->GetMaxDensity() > pool->GetMinDensity()) { - Density = m_MinDensity + rnd % (m_MaxDensity - m_MinDensity); + Density = pool->GetMinDensity() + rnd % (pool->GetMaxDensity() - pool->GetMinDensity()); } else { - Density = m_MinDensity; + Density = pool->GetMinDensity(); } // Create a village based on the chosen prefabs: - if (VillagePrefabs == nullptr) - { - return cStructurePtr(); - } - return cStructurePtr(new cVillage(m_Seed, a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, Density, *VillagePrefabs, m_HeightGen, RoadBlock, WaterRoadBlock)); + return cStructurePtr(new cVillage(m_Seed, a_GridX, a_GridZ, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, Density, *pool.get(), m_HeightGen)); } |