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:
parent
ebb1ef237a
commit
6aa7df367f
@ -408,10 +408,12 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
|||||||
}
|
}
|
||||||
else if (NoCaseCompare(*itr, "Villages") == 0)
|
else if (NoCaseCompare(*itr, "Villages") == 0)
|
||||||
{
|
{
|
||||||
int GridSize = a_IniFile.GetValueSetI("Generator", "VillageGridSize", 384);
|
int GridSize = a_IniFile.GetValueSetI("Generator", "VillageGridSize", 384);
|
||||||
int MaxDepth = a_IniFile.GetValueSetI("Generator", "VillageMaxDepth", 3);
|
int MaxDepth = a_IniFile.GetValueSetI("Generator", "VillageMaxDepth", 2);
|
||||||
int MaxSize = a_IniFile.GetValueSetI("Generator", "VillageMaxSize", 128);
|
int MaxSize = a_IniFile.GetValueSetI("Generator", "VillageMaxSize", 128);
|
||||||
m_FinishGens.push_back(new cVillageGen(Seed, GridSize, MaxDepth, MaxSize, *m_BiomeGen, *m_HeightGen));
|
int MinDensity = a_IniFile.GetValueSetI("Generator", "VillageMinDensity", 50);
|
||||||
|
int MaxDensity = a_IniFile.GetValueSetI("Generator", "VillageMaxDensity", 80);
|
||||||
|
m_FinishGens.push_back(new cVillageGen(Seed, GridSize, MaxDepth, MaxSize, MinDensity, MaxDensity, *m_BiomeGen, *m_HeightGen));
|
||||||
}
|
}
|
||||||
else if (NoCaseCompare(*itr, "WaterLakes") == 0)
|
else if (NoCaseCompare(*itr, "WaterLakes") == 0)
|
||||||
{
|
{
|
||||||
|
@ -308,6 +308,15 @@ cPiece::cConnector cPlacedPiece::GetRotatedConnector(size_t a_Index) const
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cPiece::cConnector cPlacedPiece::GetRotatedConnector(const cPiece::cConnector & a_Connector) const
|
||||||
|
{
|
||||||
|
return m_Piece->RotateMoveConnector(a_Connector, m_NumCCWRotations, m_Coords.x, m_Coords.y, m_Coords.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cPieceGenerator:
|
// cPieceGenerator:
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ public:
|
|||||||
virtual cPieces GetStartingPieces(void) = 0;
|
virtual cPieces GetStartingPieces(void) = 0;
|
||||||
|
|
||||||
/** Returns the relative weight with which the a_NewPiece is to be selected for placing under a_PlacedPiece through a_ExistingConnector.
|
/** Returns the relative weight with which the a_NewPiece is to be selected for placing under a_PlacedPiece through a_ExistingConnector.
|
||||||
|
a_ExistingConnector is the original connector, before any movement or rotation is applied to it.
|
||||||
This allows the pool to tweak the piece's chances, based on the previous pieces in the tree and the connector used.
|
This allows the pool to tweak the piece's chances, based on the previous pieces in the tree and the connector used.
|
||||||
The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will never be chosen.
|
The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will never be chosen.
|
||||||
*/
|
*/
|
||||||
@ -151,6 +152,10 @@ public:
|
|||||||
Undefined behavior if a_Index is out of range. */
|
Undefined behavior if a_Index is out of range. */
|
||||||
cPiece::cConnector GetRotatedConnector(size_t a_Index) const;
|
cPiece::cConnector GetRotatedConnector(size_t a_Index) const;
|
||||||
|
|
||||||
|
/** Returns a copy of the specified connector, modified to account for the translation and rotation for
|
||||||
|
this placement. */
|
||||||
|
cPiece::cConnector GetRotatedConnector(const cPiece::cConnector & a_Connector) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const cPlacedPiece * m_Parent;
|
const cPlacedPiece * m_Parent;
|
||||||
const cPiece * m_Piece;
|
const cPiece * m_Piece;
|
||||||
|
@ -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.
|
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
|
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
|
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
|
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.
|
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 :
|
class cVillagePiecePool :
|
||||||
@ -46,7 +51,7 @@ public:
|
|||||||
super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs)
|
super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs)
|
||||||
{
|
{
|
||||||
// Add the road pieces:
|
// Add the road pieces:
|
||||||
for (int len = 19; len < 60; len += 8)
|
for (int len = 27; len < 60; len += 12)
|
||||||
{
|
{
|
||||||
cBlockArea BA;
|
cBlockArea BA;
|
||||||
BA.Create(len, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas);
|
BA.Create(len, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas);
|
||||||
@ -56,14 +61,14 @@ public:
|
|||||||
RoadPiece->AddConnector(len - 1, 0, 1, BLOCK_FACE_XP, -2);
|
RoadPiece->AddConnector(len - 1, 0, 1, BLOCK_FACE_XP, -2);
|
||||||
|
|
||||||
// Add the road connectors:
|
// 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, 0, BLOCK_FACE_ZM, 2);
|
||||||
RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 2);
|
RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the buildings connectors:
|
// 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, 0, BLOCK_FACE_ZM, 1);
|
||||||
RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 1);
|
RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 1);
|
||||||
@ -94,7 +99,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
class cVillageGen::cVillage :
|
class cVillageGen::cVillage :
|
||||||
public cGridStructGen::cStructure
|
public cGridStructGen::cStructure,
|
||||||
|
protected cPiecePool
|
||||||
{
|
{
|
||||||
typedef cGridStructGen::cStructure super;
|
typedef cGridStructGen::cStructure super;
|
||||||
|
|
||||||
@ -104,7 +110,8 @@ public:
|
|||||||
int a_OriginX, int a_OriginZ,
|
int a_OriginX, int a_OriginZ,
|
||||||
int a_MaxRoadDepth,
|
int a_MaxRoadDepth,
|
||||||
int a_MaxSize,
|
int a_MaxSize,
|
||||||
cPrefabPiecePool & a_Prefabs,
|
int a_Density,
|
||||||
|
cPiecePool & a_Prefabs,
|
||||||
cTerrainHeightGen & a_HeightGen,
|
cTerrainHeightGen & a_HeightGen,
|
||||||
BLOCKTYPE a_RoadBlock
|
BLOCKTYPE a_RoadBlock
|
||||||
) :
|
) :
|
||||||
@ -112,12 +119,13 @@ public:
|
|||||||
m_Seed(a_Seed),
|
m_Seed(a_Seed),
|
||||||
m_Noise(a_Seed),
|
m_Noise(a_Seed),
|
||||||
m_MaxSize(a_MaxSize),
|
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_Borders(a_OriginX - a_MaxSize, 0, a_OriginZ - a_MaxSize, a_OriginX + a_MaxSize, 255, a_OriginZ + a_MaxSize),
|
||||||
m_Prefabs(a_Prefabs),
|
m_Prefabs(a_Prefabs),
|
||||||
m_HeightGen(a_HeightGen),
|
m_HeightGen(a_HeightGen),
|
||||||
m_RoadBlock(a_RoadBlock)
|
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
|
// 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
|
// Piece has negative Y coord -> hasn't been height-adjusted yet
|
||||||
pg.PlacePieces(a_OriginX, -1000, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces);
|
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) */
|
/** Maximum size, in X/Z blocks, of the village (radius from the origin) */
|
||||||
int m_MaxSize;
|
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. */
|
/** Borders of the vilalge - no item may reach out of this cuboid. */
|
||||||
cCuboid m_Borders;
|
cCuboid m_Borders;
|
||||||
|
|
||||||
/** Prefabs to use for buildings */
|
/** 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. */
|
/** The underlying height generator, used for placing the structures on top of the terrain. */
|
||||||
cTerrainHeightGen & m_HeightGen;
|
cTerrainHeightGen & m_HeightGen;
|
||||||
@ -149,7 +160,7 @@ protected:
|
|||||||
BLOCKTYPE m_RoadBlock;
|
BLOCKTYPE m_RoadBlock;
|
||||||
|
|
||||||
|
|
||||||
// cGrdStructGen::cStructure overrides:
|
// cGridStructGen::cStructure overrides:
|
||||||
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
|
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
|
||||||
{
|
{
|
||||||
// Iterate over all items
|
// 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),
|
super(a_Seed, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 100),
|
||||||
|
m_Noise(a_Seed + 1000),
|
||||||
m_MaxDepth(a_MaxDepth),
|
m_MaxDepth(a_MaxDepth),
|
||||||
m_MaxSize(a_MaxSize),
|
m_MaxSize(a_MaxSize),
|
||||||
|
m_MinDensity(a_MinDensity),
|
||||||
|
m_MaxDensity(a_MaxDensity),
|
||||||
m_BiomeGen(a_BiomeGen),
|
m_BiomeGen(a_BiomeGen),
|
||||||
m_HeightGen(a_HeightGen)
|
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
|
// If just one is not, no village is created, because it's likely that an unfriendly biome is too close
|
||||||
cVillagePiecePool * VillagePrefabs = NULL;
|
cVillagePiecePool * VillagePrefabs = NULL;
|
||||||
BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL;
|
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++)
|
for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++)
|
||||||
{
|
{
|
||||||
switch (Biomes[i])
|
switch (Biomes[i])
|
||||||
@ -288,12 +345,23 @@ cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_
|
|||||||
} // switch (Biomes[i])
|
} // switch (Biomes[i])
|
||||||
} // for i - Biomes[]
|
} // 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:
|
// Create a village based on the chosen prefabs:
|
||||||
if (VillagePrefabs == NULL)
|
if (VillagePrefabs == NULL)
|
||||||
{
|
{
|
||||||
return cStructurePtr();
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,16 +21,25 @@ class cVillageGen :
|
|||||||
{
|
{
|
||||||
typedef cGridStructGen super;
|
typedef cGridStructGen super;
|
||||||
public:
|
public:
|
||||||
cVillageGen(int a_Seed, int a_GridSize, int a_MaxDepth, int a_MaxSize, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen);
|
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);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class cVillage; // fwd: VillageGen.cpp
|
class cVillage; // fwd: VillageGen.cpp
|
||||||
|
|
||||||
|
/** The noise used for generating random numbers */
|
||||||
|
cNoise m_Noise;
|
||||||
|
|
||||||
/** Maximum depth of the generator tree*/
|
/** Maximum depth of the generator tree*/
|
||||||
int m_MaxDepth;
|
int m_MaxDepth;
|
||||||
|
|
||||||
/** Maximum size, in X/Z blocks, of the village (radius from the origin) */
|
/** Maximum size, in X/Z blocks, of the village (radius from the origin) */
|
||||||
int m_MaxSize;
|
int m_MaxSize;
|
||||||
|
|
||||||
|
/** Minimum density - percentage of allowed house connections. Range [0, 100] */
|
||||||
|
int m_MinDensity;
|
||||||
|
|
||||||
|
/** Maximum density - percentage of allowed house connections. Range [0, 100] */
|
||||||
|
int m_MaxDensity;
|
||||||
|
|
||||||
/** The underlying biome generator that defines whether the village is created or not */
|
/** The underlying biome generator that defines whether the village is created or not */
|
||||||
cBiomeGen & m_BiomeGen;
|
cBiomeGen & m_BiomeGen;
|
||||||
|
Loading…
Reference in New Issue
Block a user