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.cpp92
1 files changed, 80 insertions, 12 deletions
diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp
index a899d5837..bcce62af5 100644
--- a/src/Generating/VillageGen.cpp
+++ b/src/Generating/VillageGen.cpp
@@ -27,11 +27,16 @@ though, the roads are generated by code and their content is ignored. A special
class is used, so that the roads connect to each other and to the well only in predefined manners.
The well has connectors of type "2". The houses have connectors of type "-1". The roads have connectors of
-both types' opposites, type "-2" at the far ends and type "1" on the long edges.
+both types' opposites, type "-2" at the far ends and type "1" on the long edges. Additionally, there are
+type "2" connectors along the long edges of the roads as well, so that the roads create T junctions.
When the village is about to be drawn into a chunk, it queries the heights for each piece intersecting the
chunk. The pieces are shifted so that their pivot points lie on the surface, and the roads are drawn
directly by turning the surface blocks into gravel / sandstone.
+
+The village prefabs are stored in global piecepools (one pool per village type). In order to support
+per-village density setting, the cVillage class itself implements the cPiecePool interface, relaying the
+calls to the underlying cVillagePiecePool, after processing the density check.
*/
class cVillagePiecePool :
@@ -46,7 +51,7 @@ public:
super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs)
{
// Add the road pieces:
- for (int len = 19; len < 60; len += 8)
+ for (int len = 27; len < 60; len += 12)
{
cBlockArea BA;
BA.Create(len, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas);
@@ -56,14 +61,14 @@ public:
RoadPiece->AddConnector(len - 1, 0, 1, BLOCK_FACE_XP, -2);
// Add the road connectors:
- for (int x = 1; x < len; x += 8)
+ for (int x = 1; x < len; x += 12)
{
RoadPiece->AddConnector(x, 0, 0, BLOCK_FACE_ZM, 2);
RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 2);
}
// Add the buildings connectors:
- for (int x = 5; x < len; x += 8)
+ for (int x = 7; x < len; x += 12)
{
RoadPiece->AddConnector(x, 0, 0, BLOCK_FACE_ZM, 1);
RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 1);
@@ -94,7 +99,8 @@ public:
class cVillageGen::cVillage :
- public cGridStructGen::cStructure
+ public cGridStructGen::cStructure,
+ protected cPiecePool
{
typedef cGridStructGen::cStructure super;
@@ -104,7 +110,8 @@ public:
int a_OriginX, int a_OriginZ,
int a_MaxRoadDepth,
int a_MaxSize,
- cPrefabPiecePool & a_Prefabs,
+ int a_Density,
+ cPiecePool & a_Prefabs,
cTerrainHeightGen & a_HeightGen,
BLOCKTYPE a_RoadBlock
) :
@@ -112,12 +119,13 @@ public:
m_Seed(a_Seed),
m_Noise(a_Seed),
m_MaxSize(a_MaxSize),
+ m_Density(a_Density),
m_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize),
m_Prefabs(a_Prefabs),
m_HeightGen(a_HeightGen),
m_RoadBlock(a_RoadBlock)
{
- cBFSPieceGenerator pg(m_Prefabs, a_Seed);
+ cBFSPieceGenerator pg(*this, a_Seed);
// Generate the pieces at very negative Y coords, so that we can later test
// Piece has negative Y coord -> hasn't been height-adjusted yet
pg.PlacePieces(a_OriginX, -1000, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces);
@@ -133,11 +141,14 @@ protected:
/** Maximum size, in X/Z blocks, of the village (radius from the origin) */
int m_MaxSize;
+ /** The density for this village. Used to refrain from populating all house connectors. Range [0, 100] */
+ int m_Density;
+
/** Borders of the vilalge - no item may reach out of this cuboid. */
cCuboid m_Borders;
/** Prefabs to use for buildings */
- cPrefabPiecePool & m_Prefabs;
+ cPiecePool & m_Prefabs;
/** The underlying height generator, used for placing the structures on top of the terrain. */
cTerrainHeightGen & m_HeightGen;
@@ -149,7 +160,7 @@ protected:
BLOCKTYPE m_RoadBlock;
- // cGrdStructGen::cStructure overrides:
+ // cGridStructGen::cStructure overrides:
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
{
// Iterate over all items
@@ -211,6 +222,49 @@ protected:
}
}
}
+
+
+ // cPiecePool overrides:
+ virtual cPieces GetPiecesWithConnector(int a_ConnectorType)
+ {
+ return m_Prefabs.GetPiecesWithConnector(a_ConnectorType);
+ }
+
+ virtual cPieces GetStartingPieces(void)
+ {
+ return m_Prefabs.GetStartingPieces();
+ }
+
+ virtual int GetPieceWeight(
+ const cPlacedPiece & a_PlacedPiece,
+ const cPiece::cConnector & a_ExistingConnector,
+ const cPiece & a_NewPiece
+ ) override
+ {
+ // Check against the density:
+ if (a_ExistingConnector.m_Type == 1)
+ {
+ const Vector3i & Coords = a_PlacedPiece.GetRotatedConnector(a_ExistingConnector).m_Pos;
+ int rnd = (m_Noise.IntNoise3DInt(Coords.x, Coords.y, Coords.z) / 7) % 100;
+ if (rnd > m_Density)
+ {
+ return 0;
+ }
+ }
+
+ // Density check passed, relay to m_Prefabs:
+ return m_Prefabs.GetPieceWeight(a_PlacedPiece, a_ExistingConnector, a_NewPiece);
+ }
+
+ virtual void PiecePlaced(const cPiece & a_Piece) override
+ {
+ m_Prefabs.PiecePlaced(a_Piece);
+ }
+
+ virtual void Reset(void) override
+ {
+ m_Prefabs.Reset();
+ }
} ;
@@ -233,10 +287,13 @@ static cVillagePiecePool g_PlainsVillage(g_PlainsVillagePrefabs, g_PlainsVillage
-cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxDepth, int a_MaxSize, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) :
+cVillageGen::cVillageGen(int a_Seed, int a_GridSize, int a_MaxDepth, int a_MaxSize, int a_MinDensity, int a_MaxDensity, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen) :
super(a_Seed, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 100),
+ m_Noise(a_Seed + 1000),
m_MaxDepth(a_MaxDepth),
m_MaxSize(a_MaxSize),
+ m_MinDensity(a_MinDensity),
+ m_MaxDensity(a_MaxDensity),
m_BiomeGen(a_BiomeGen),
m_HeightGen(a_HeightGen)
{
@@ -258,7 +315,7 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_
// If just one is not, no village is created, because it's likely that an unfriendly biome is too close
cVillagePiecePool * VillagePrefabs = NULL;
BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL;
- int rnd = (a_OriginX + 21 * a_OriginZ + 985) / 11;
+ int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 11;
for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++)
{
switch (Biomes[i])
@@ -288,12 +345,23 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_
} // switch (Biomes[i])
} // for i - Biomes[]
+ // Choose density for the village, random between m_MinDensity and m_MaxDensity:
+ int Density;
+ if (m_MaxDensity > m_MinDensity)
+ {
+ Density = m_MinDensity + rnd % (m_MaxDensity - m_MinDensity);
+ }
+ else
+ {
+ Density = m_MinDensity;
+ }
+
// Create a village based on the chosen prefabs:
if (VillagePrefabs == NULL)
{
return cStructurePtr();
}
- return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, *VillagePrefabs, m_HeightGen, RoadBlock));
+ return cStructurePtr(new cVillage(m_Seed, a_OriginX, a_OriginZ, m_MaxDepth, m_MaxSize, Density, *VillagePrefabs, m_HeightGen, RoadBlock));
}