summaryrefslogtreecommitdiffstats
path: root/src/Generating/VillageGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Generating/VillageGen.cpp')
-rw-r--r--src/Generating/VillageGen.cpp174
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));
}