Villages have min and max density setting.
Also made roads use 3+9 scheme, instead of 3+5, for the house connectors. Fixes #1020.
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user