commit
6de45037c7
@ -212,7 +212,7 @@ void cBioGenCache::InitializeBiomeGen(cIniFile & a_IniFile)
|
||||
|
||||
void cBiomeGenList::InitializeBiomes(const AString & a_Biomes)
|
||||
{
|
||||
AStringVector Split = StringSplit(a_Biomes, ",");
|
||||
AStringVector Split = StringSplitAndTrim(a_Biomes, ",");
|
||||
|
||||
// Convert each string in the list into biome:
|
||||
for (AStringVector::const_iterator itr = Split.begin(); itr != Split.end(); ++itr)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "Noise3DGenerator.h"
|
||||
#include "POCPieceGenerator.h"
|
||||
#include "Ravines.h"
|
||||
#include "VillageGen.h"
|
||||
|
||||
|
||||
|
||||
@ -32,6 +33,7 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cTerrainCompositionGen:
|
||||
|
||||
cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed)
|
||||
{
|
||||
AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", "");
|
||||
@ -404,6 +406,15 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
||||
{
|
||||
m_FinishGens.push_back(new cStructGenTrees(Seed, m_BiomeGen, m_HeightGen, m_CompositionGen));
|
||||
}
|
||||
else if (NoCaseCompare(*itr, "Villages") == 0)
|
||||
{
|
||||
int GridSize = a_IniFile.GetValueSetI("Generator", "VillageGridSize", 384);
|
||||
int MaxDepth = a_IniFile.GetValueSetI("Generator", "VillageMaxDepth", 2);
|
||||
int MaxSize = a_IniFile.GetValueSetI("Generator", "VillageMaxSize", 128);
|
||||
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)
|
||||
{
|
||||
int Probability = a_IniFile.GetValueSetI("Generator", "WaterLakesProbability", 25);
|
||||
|
@ -9,6 +9,34 @@
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cEmptyStructure:
|
||||
|
||||
/** A cStructure descendant representing an empty structure.
|
||||
Used when the generator descended from cGridStructGen doesn't return any structure, to keep at least the
|
||||
Origin coords so that the structure isn't queried over and over again. */
|
||||
class cEmptyStructure :
|
||||
public cGridStructGen::cStructure
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
public:
|
||||
cEmptyStructure(int a_OriginX, int a_OriginZ) :
|
||||
super(a_OriginX, a_OriginZ)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cGridStructGen::cGridStructGen(
|
||||
int a_Seed,
|
||||
int a_GridSizeX, int a_GridSizeZ,
|
||||
@ -90,7 +118,12 @@ void cGridStructGen::GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructur
|
||||
} // for itr - a_Structures[]
|
||||
if (!Found)
|
||||
{
|
||||
a_Structures.push_back(CreateStructure(OriginX, OriginZ));
|
||||
cStructurePtr Structure = CreateStructure(OriginX, OriginZ);
|
||||
if (Structure.get() == NULL)
|
||||
{
|
||||
Structure.reset(new cEmptyStructure(OriginX, OriginZ));
|
||||
}
|
||||
a_Structures.push_back(Structure);
|
||||
}
|
||||
} // for z
|
||||
} // for x
|
||||
|
@ -39,14 +39,6 @@ class cGridStructGen :
|
||||
public cFinishGen
|
||||
{
|
||||
public:
|
||||
cGridStructGen(
|
||||
int a_Seed,
|
||||
int a_GridSizeX, int a_GridSizeZ,
|
||||
int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
|
||||
size_t a_MaxCacheSize
|
||||
);
|
||||
|
||||
protected:
|
||||
/** Represents a single structure that occupies the grid point. Knows how to draw itself into a chunk. */
|
||||
class cStructure
|
||||
{
|
||||
@ -75,6 +67,14 @@ protected:
|
||||
typedef std::list<cStructurePtr> cStructurePtrs;
|
||||
|
||||
|
||||
cGridStructGen(
|
||||
int a_Seed,
|
||||
int a_GridSizeX, int a_GridSizeZ,
|
||||
int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
|
||||
size_t a_MaxCacheSize
|
||||
);
|
||||
|
||||
protected:
|
||||
/** Seed for generating the semi-random grid. */
|
||||
int m_Seed;
|
||||
|
||||
|
@ -186,6 +186,11 @@ cPOCPieceGenerator::cPOCPieceGenerator(int a_Seed) :
|
||||
cPOCPieceGenerator::~cPOCPieceGenerator()
|
||||
{
|
||||
cPieceGenerator::FreePieces(m_Pieces);
|
||||
for (cPieces::iterator itr = m_AvailPieces.begin(), end = m_AvailPieces.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
}
|
||||
m_AvailPieces.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -286,7 +286,8 @@ cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece
|
||||
m_Parent(a_Parent),
|
||||
m_Piece(&a_Piece),
|
||||
m_Coords(a_Coords),
|
||||
m_NumCCWRotations(a_NumCCWRotations)
|
||||
m_NumCCWRotations(a_NumCCWRotations),
|
||||
m_HasBeenMovedToGround(false)
|
||||
{
|
||||
m_Depth = (m_Parent == NULL) ? 0 : (m_Parent->GetDepth() + 1);
|
||||
m_HitBox = a_Piece.RotateMoveHitBox(a_NumCCWRotations, a_Coords.x, a_Coords.y, a_Coords.z);
|
||||
@ -297,6 +298,36 @@ cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece
|
||||
|
||||
|
||||
|
||||
cPiece::cConnector cPlacedPiece::GetRotatedConnector(size_t a_Index) const
|
||||
{
|
||||
cPiece::cConnectors Connectors = m_Piece->GetConnectors();
|
||||
ASSERT(Connectors.size() >= a_Index);
|
||||
return m_Piece->RotateMoveConnector(Connectors[a_Index], m_NumCCWRotations, m_Coords.x, m_Coords.y, m_Coords.z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPlacedPiece::MoveToGroundBy(int a_OffsetY)
|
||||
{
|
||||
m_Coords.y += a_OffsetY;
|
||||
m_HasBeenMovedToGround = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cPieceGenerator:
|
||||
|
||||
@ -331,7 +362,31 @@ cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockY, i
|
||||
|
||||
// Choose a random one of the starting pieces:
|
||||
cPieces StartingPieces = m_PiecePool.GetStartingPieces();
|
||||
cPiece * StartingPiece = StartingPieces[rnd % StartingPieces.size()];
|
||||
int Total = 0;
|
||||
for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr)
|
||||
{
|
||||
Total += m_PiecePool.GetStartingPieceWeight(**itr);
|
||||
}
|
||||
cPiece * StartingPiece;
|
||||
if (Total > 0)
|
||||
{
|
||||
int Chosen = rnd % Total;
|
||||
StartingPiece = StartingPieces.front();
|
||||
for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr)
|
||||
{
|
||||
Chosen -= m_PiecePool.GetStartingPieceWeight(**itr);
|
||||
if (Chosen <= 0)
|
||||
{
|
||||
StartingPiece = *itr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// All pieces returned zero weight, but we need one to start. Choose with equal chance:
|
||||
StartingPiece = StartingPieces[rnd % StartingPieces.size()];
|
||||
}
|
||||
rnd = rnd >> 16;
|
||||
|
||||
// Choose a random supported rotation:
|
||||
|
@ -110,6 +110,7 @@ public:
|
||||
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.
|
||||
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.
|
||||
The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will never be chosen.
|
||||
*/
|
||||
@ -119,6 +120,15 @@ public:
|
||||
const cPiece & a_NewPiece
|
||||
) { return 1; }
|
||||
|
||||
/** Returns the relative weight with which the a_NewPiece is to be selected for placing as the first piece.
|
||||
This allows the pool to tweak the piece's chances.
|
||||
The higher the number returned, the higher the chance the piece will be chosen. 0 means the piece will not be chosen.
|
||||
If all pieces return 0, a random piece is chosen, with all equal chances.
|
||||
*/
|
||||
virtual int GetStartingPieceWeight(
|
||||
const cPiece & a_NewPiece
|
||||
) { return 1; }
|
||||
|
||||
/** Called after a piece is placed, to notify the pool that it has been used.
|
||||
The pool may adjust the pieces it will return the next time. */
|
||||
virtual void PiecePlaced(const cPiece & a_Piece) = 0;
|
||||
@ -138,19 +148,41 @@ class cPlacedPiece
|
||||
public:
|
||||
cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece, const Vector3i & a_Coords, int a_NumCCWRotations);
|
||||
|
||||
const cPlacedPiece * GetParent (void) const { return m_Parent; }
|
||||
const cPiece & GetPiece (void) const { return *m_Piece; }
|
||||
const Vector3i & GetCoords (void) const { return m_Coords; }
|
||||
int GetNumCCWRotations(void) const { return m_NumCCWRotations; }
|
||||
int GetNumCCWRotations (void) const { return m_NumCCWRotations; }
|
||||
const cCuboid & GetHitBox (void) const { return m_HitBox; }
|
||||
int GetDepth (void) const { return m_Depth; }
|
||||
bool HasBeenMovedToGround(void) const { return m_HasBeenMovedToGround; }
|
||||
|
||||
/** Returns the coords as a modifiable object. */
|
||||
Vector3i & GetCoords(void) { return m_Coords; }
|
||||
|
||||
/** Returns the connector at the specified index, rotated in the actual placement.
|
||||
Undefined behavior if a_Index is out of range. */
|
||||
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;
|
||||
|
||||
/** Moves the placed piece Y-wise by the specified offset.
|
||||
Sets m_HasBeenMovedToGround to true, too.
|
||||
Used eg. by village houses. */
|
||||
void MoveToGroundBy(int a_OffsetY);
|
||||
|
||||
protected:
|
||||
const cPlacedPiece * m_Parent;
|
||||
const cPiece * m_Piece;
|
||||
Vector3i m_Coords;
|
||||
int m_NumCCWRotations;
|
||||
cCuboid m_HitBox;
|
||||
int m_Depth;
|
||||
cCuboid m_HitBox; // Hitbox of the placed piece, in world coords
|
||||
int m_Depth; // Depth in the generated piece tree
|
||||
|
||||
/** Set to true once the piece has been moved Y-wise.
|
||||
Used eg. by village houses. */
|
||||
bool m_HasBeenMovedToGround;
|
||||
};
|
||||
|
||||
typedef std::vector<cPlacedPiece *> cPlacedPieces;
|
||||
|
@ -108,6 +108,9 @@ static const cPrefab::sDef g_TestPrefabDef =
|
||||
|
||||
// AddWeightIfSame:
|
||||
1000,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
};
|
||||
|
||||
static cPrefab g_TestPrefab(g_TestPrefabDef);
|
||||
@ -127,7 +130,8 @@ cPrefab::cPrefab(const cPrefab::sDef & a_Def) :
|
||||
m_MergeStrategy(a_Def.m_MergeStrategy),
|
||||
m_ShouldExtendFloor(a_Def.m_ShouldExtendFloor),
|
||||
m_DefaultWeight(a_Def.m_DefaultWeight),
|
||||
m_AddWeightIfSame(a_Def.m_AddWeightIfSame)
|
||||
m_AddWeightIfSame(a_Def.m_AddWeightIfSame),
|
||||
m_MoveToGround(a_Def.m_MoveToGround)
|
||||
{
|
||||
m_BlockArea[0].Create(m_Size);
|
||||
CharMap cm;
|
||||
@ -136,6 +140,34 @@ cPrefab::cPrefab(const cPrefab::sDef & a_Def) :
|
||||
ParseConnectors(a_Def.m_Connectors);
|
||||
ParseDepthWeight(a_Def.m_DepthWeight);
|
||||
|
||||
AddRotatedBlockAreas();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPrefab::cPrefab(const cBlockArea & a_Image, int a_AllowedRotations) :
|
||||
m_Size(a_Image.GetSize()),
|
||||
m_AllowedRotations(a_AllowedRotations),
|
||||
m_MergeStrategy(cBlockArea::msOverwrite),
|
||||
m_ShouldExtendFloor(false),
|
||||
m_DefaultWeight(1),
|
||||
m_AddWeightIfSame(0),
|
||||
m_MoveToGround(false)
|
||||
{
|
||||
m_HitBox.p1.Set(0, 0, 0);
|
||||
m_HitBox.p2.Set(m_Size.x - 1, m_Size.y - 1, m_Size.z - 1);
|
||||
m_BlockArea[0].CopyFrom(a_Image);
|
||||
AddRotatedBlockAreas();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefab::AddRotatedBlockAreas(void)
|
||||
{
|
||||
// 1 CCW rotation:
|
||||
if ((m_AllowedRotations & 0x01) != 0)
|
||||
{
|
||||
@ -164,13 +196,21 @@ cPrefab::cPrefab(const cPrefab::sDef & a_Def) :
|
||||
|
||||
|
||||
void cPrefab::Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const
|
||||
{
|
||||
Draw(a_Dest, a_Placement->GetCoords(), a_Placement->GetNumCCWRotations());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefab::Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumRotations) const
|
||||
{
|
||||
// Draw the basic image:
|
||||
Vector3i Placement = a_Placement->GetCoords();
|
||||
Vector3i Placement(a_Placement);
|
||||
int ChunkStartX = a_Dest.GetChunkX() * cChunkDef::Width;
|
||||
int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width;
|
||||
Placement.Move(-ChunkStartX, 0, -ChunkStartZ);
|
||||
const cBlockArea & Image = m_BlockArea[a_Placement->GetNumCCWRotations()];
|
||||
const cBlockArea & Image = m_BlockArea[a_NumRotations];
|
||||
a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy);
|
||||
|
||||
// If requested, draw the floor (from the bottom of the prefab down to the nearest non-air)
|
||||
@ -257,6 +297,24 @@ int cPrefab::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cC
|
||||
|
||||
|
||||
|
||||
void cPrefab::SetDefaultWeight(int a_DefaultWeight)
|
||||
{
|
||||
m_DefaultWeight = a_DefaultWeight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefab::AddConnector(int a_RelX, int a_RelY, int a_RelZ, eBlockFace a_Direction, int a_Type)
|
||||
{
|
||||
m_Connectors.push_back(cConnector(a_RelX, a_RelY, a_RelZ, a_Type, a_Direction));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef)
|
||||
{
|
||||
ASSERT(a_CharMapDef != NULL);
|
||||
|
@ -82,13 +82,25 @@ public:
|
||||
Can be positive or negative.
|
||||
This is used e. g. to make nether bridges prefer spanning multiple segments or to penalize turrets next to each other. */
|
||||
int m_AddWeightIfSame;
|
||||
|
||||
/** If true, the piece will be moved Y-wise so that its first connector is sitting on the terrain.
|
||||
This is used e. g. for village houses. */
|
||||
bool m_MoveToGround;
|
||||
};
|
||||
|
||||
|
||||
/** Creates a prefab from the provided definition. */
|
||||
cPrefab(const sDef & a_Def);
|
||||
|
||||
/** Creates a prefab based on the given BlockArea and allowed rotations. */
|
||||
cPrefab(const cBlockArea & a_Image, int a_AllowedRotations);
|
||||
|
||||
/** Draws the prefab into the specified chunk, according to the placement stored in the PlacedPiece. */
|
||||
void Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const;
|
||||
|
||||
/** Draws the prefab into the specified chunks, according to the specified placement and rotations. */
|
||||
void Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumRotations) const;
|
||||
|
||||
/** Returns true if the prefab has any connector of the specified type. */
|
||||
bool HasConnectorType(int a_ConnectorType) const;
|
||||
|
||||
@ -96,6 +108,22 @@ public:
|
||||
PiecePool implementations can use this for their GetPieceWeight() implementations. */
|
||||
int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector) const;
|
||||
|
||||
/** Sets the (unmodified) DefaultWeight property for this piece. */
|
||||
void SetDefaultWeight(int a_DefaultWeight);
|
||||
|
||||
/** Returns the unmodified DefaultWeight property for the piece. */
|
||||
int GetDefaultWeight(void) const { return m_DefaultWeight; }
|
||||
|
||||
/** Sets the AddWeightIfSame member, that is used to modify the weight when the previous piece is the same prefab */
|
||||
void SetAddWeightIfSame(int a_AddWeightIfSame) { m_AddWeightIfSame = a_AddWeightIfSame; }
|
||||
|
||||
/** Adds the specified connector to the list of connectors this piece supports. */
|
||||
void AddConnector(int a_RelX, int a_RelY, int a_RelZ, eBlockFace a_Direction, int a_Type);
|
||||
|
||||
/** Returns whether the prefab should be moved Y-wise to ground before drawing, rather than staying
|
||||
at the coords governed by the connectors. */
|
||||
bool ShouldMoveToGround(void) const { return m_MoveToGround; }
|
||||
|
||||
protected:
|
||||
/** Packs complete definition of a single block, for per-letter assignment. */
|
||||
struct sBlockTypeDef
|
||||
@ -150,6 +178,10 @@ protected:
|
||||
This is used e. g. to make nether bridges prefer spanning multiple segments or to penalize turrets next to each other. */
|
||||
int m_AddWeightIfSame;
|
||||
|
||||
/** If true, the piece will be moved Y-wise so that its first connector is sitting on the terrain.
|
||||
This is used e. g. for village houses. */
|
||||
bool m_MoveToGround;
|
||||
|
||||
|
||||
// cPiece overrides:
|
||||
virtual cConnectors GetConnectors(void) const override;
|
||||
@ -157,6 +189,10 @@ protected:
|
||||
virtual cCuboid GetHitBox(void) const override;
|
||||
virtual bool CanRotateCCW(int a_NumRotations) const override;
|
||||
|
||||
/** Based on the m_AllowedRotations, adds rotated cBlockAreas to the m_BlockArea array.
|
||||
To be called only from this class's constructor! */
|
||||
void AddRotatedBlockAreas(void);
|
||||
|
||||
/** Parses the CharMap in the definition into a CharMap binary data used for translating the definition into BlockArea. */
|
||||
void ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef);
|
||||
|
||||
|
@ -129,6 +129,15 @@ int cPrefabPiecePool::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const c
|
||||
|
||||
|
||||
|
||||
int cPrefabPiecePool::GetStartingPieceWeight(const cPiece & a_NewPiece)
|
||||
{
|
||||
return ((const cPrefab &)a_NewPiece).GetDefaultWeight();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefabPiecePool::PiecePlaced(const cPiece & a_Piece)
|
||||
{
|
||||
// Do nothing
|
||||
|
@ -75,6 +75,7 @@ protected:
|
||||
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
|
||||
virtual cPieces GetStartingPieces(void) override;
|
||||
virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override;
|
||||
virtual int GetStartingPieceWeight(const cPiece & a_NewPiece) override;
|
||||
virtual void PiecePlaced(const cPiece & a_Piece) override;
|
||||
virtual void Reset(void) override;
|
||||
} ;
|
||||
|
3182
src/Generating/Prefabs/AlchemistVillagePrefabs.cpp
Normal file
3182
src/Generating/Prefabs/AlchemistVillagePrefabs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
15
src/Generating/Prefabs/AlchemistVillagePrefabs.h
Normal file
15
src/Generating/Prefabs/AlchemistVillagePrefabs.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
// AlchemistVillagePrefabs.h
|
||||
|
||||
// Declares the prefabs in the group AlchemistVillage
|
||||
|
||||
#include "../Prefab.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern const cPrefab::sDef g_AlchemistVillagePrefabs[];
|
||||
extern const cPrefab::sDef g_AlchemistVillageStartingPrefabs[];
|
||||
extern const size_t g_AlchemistVillagePrefabsCount;
|
||||
extern const size_t g_AlchemistVillageStartingPrefabsCount;
|
3200
src/Generating/Prefabs/JapaneseVillagePrefabs.cpp
Normal file
3200
src/Generating/Prefabs/JapaneseVillagePrefabs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
15
src/Generating/Prefabs/JapaneseVillagePrefabs.h
Normal file
15
src/Generating/Prefabs/JapaneseVillagePrefabs.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
// JapaneseVillagePrefabs.h
|
||||
|
||||
// Declares the prefabs in the group JapaneseVillage
|
||||
|
||||
#include "../Prefab.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern const cPrefab::sDef g_JapaneseVillagePrefabs[];
|
||||
extern const cPrefab::sDef g_JapaneseVillageStartingPrefabs[];
|
||||
extern const size_t g_JapaneseVillagePrefabsCount;
|
||||
extern const size_t g_JapaneseVillageStartingPrefabsCount;
|
@ -155,6 +155,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BalconyCorridor
|
||||
|
||||
|
||||
@ -315,6 +318,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BalconyTee2
|
||||
|
||||
|
||||
@ -435,6 +441,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BlazePlatform
|
||||
|
||||
|
||||
@ -605,6 +614,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BlazePlatformOverhang
|
||||
|
||||
|
||||
@ -805,6 +817,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
-1000,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeCircleCrossing
|
||||
|
||||
|
||||
@ -1006,6 +1021,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeCrossing
|
||||
|
||||
|
||||
@ -1100,6 +1118,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeCrumble1
|
||||
|
||||
|
||||
@ -1200,6 +1221,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeCrumble2
|
||||
|
||||
|
||||
@ -1379,6 +1403,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
1000,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeDoubleCrumble
|
||||
|
||||
|
||||
@ -1619,6 +1646,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeFunnelDown
|
||||
|
||||
|
||||
@ -1948,6 +1978,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeLevelCrossing
|
||||
|
||||
|
||||
@ -2067,6 +2100,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
1000,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeSegment
|
||||
|
||||
|
||||
@ -2227,6 +2263,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // BridgeTee
|
||||
|
||||
|
||||
@ -2328,6 +2367,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // Corridor11
|
||||
|
||||
|
||||
@ -2429,6 +2471,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // Corridor13
|
||||
|
||||
|
||||
@ -2524,6 +2569,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
500,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // Corridor5
|
||||
|
||||
|
||||
@ -2663,6 +2711,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // CorridorCorner5
|
||||
|
||||
|
||||
@ -2803,6 +2854,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // CorridorCornerChest5
|
||||
|
||||
|
||||
@ -2928,6 +2982,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
-50,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // CorridorCrossing
|
||||
|
||||
|
||||
@ -3080,6 +3137,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // CorridorStairs
|
||||
|
||||
|
||||
@ -3181,6 +3241,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // DarkCorridor
|
||||
|
||||
|
||||
@ -3438,6 +3501,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // LavaStaircase
|
||||
|
||||
|
||||
@ -3769,6 +3835,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
-1000,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // LavaStaircaseBig
|
||||
|
||||
|
||||
@ -4047,6 +4116,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // LavaStairsBridge
|
||||
|
||||
|
||||
@ -4235,6 +4307,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
-1000,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // MidStaircase
|
||||
|
||||
|
||||
@ -4378,6 +4453,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // StairsToOpen1
|
||||
|
||||
|
||||
@ -4521,6 +4599,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // StairsToOpen2
|
||||
|
||||
|
||||
@ -4638,6 +4719,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // Tee2x4
|
||||
|
||||
|
||||
@ -4767,6 +4851,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // Tee4x4
|
||||
|
||||
|
||||
@ -4863,6 +4950,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
-50,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // TinyCorridorCorner
|
||||
|
||||
|
||||
@ -4960,6 +5050,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // TinyCorridorCornerChest
|
||||
|
||||
|
||||
@ -5059,6 +5152,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
-50,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // TinyCorridorCrossing
|
||||
|
||||
|
||||
@ -5174,6 +5270,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
-99,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // Turret
|
||||
}; // g_NetherFortPrefabs
|
||||
|
||||
@ -5378,6 +5477,9 @@ const cPrefab::sDef g_NetherFortStartingPrefabs[] =
|
||||
|
||||
// AddWeightIfSame:
|
||||
0,
|
||||
|
||||
// MoveToGround:
|
||||
false,
|
||||
}, // CentralRoom
|
||||
};
|
||||
|
||||
|
6114
src/Generating/Prefabs/PlainsVillagePrefabs.cpp
Normal file
6114
src/Generating/Prefabs/PlainsVillagePrefabs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
15
src/Generating/Prefabs/PlainsVillagePrefabs.h
Normal file
15
src/Generating/Prefabs/PlainsVillagePrefabs.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
// PlainsVillagePrefabs.h
|
||||
|
||||
// Declares the prefabs in the group PlainsVillage
|
||||
|
||||
#include "../Prefab.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern const cPrefab::sDef g_PlainsVillagePrefabs[];
|
||||
extern const cPrefab::sDef g_PlainsVillageStartingPrefabs[];
|
||||
extern const size_t g_PlainsVillagePrefabsCount;
|
||||
extern const size_t g_PlainsVillageStartingPrefabsCount;
|
1558
src/Generating/Prefabs/SandFlatRoofVillagePrefabs.cpp
Normal file
1558
src/Generating/Prefabs/SandFlatRoofVillagePrefabs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
15
src/Generating/Prefabs/SandFlatRoofVillagePrefabs.h
Normal file
15
src/Generating/Prefabs/SandFlatRoofVillagePrefabs.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
// SandFlatRoofVillagePrefabs.h
|
||||
|
||||
// Declares the prefabs in the group SandFlatRoofVillage
|
||||
|
||||
#include "../Prefab.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern const cPrefab::sDef g_SandFlatRoofVillagePrefabs[];
|
||||
extern const cPrefab::sDef g_SandFlatRoofVillageStartingPrefabs[];
|
||||
extern const size_t g_SandFlatRoofVillagePrefabsCount;
|
||||
extern const size_t g_SandFlatRoofVillageStartingPrefabsCount;
|
2133
src/Generating/Prefabs/SandVillagePrefabs.cpp
Normal file
2133
src/Generating/Prefabs/SandVillagePrefabs.cpp
Normal file
File diff suppressed because it is too large
Load Diff
15
src/Generating/Prefabs/SandVillagePrefabs.h
Normal file
15
src/Generating/Prefabs/SandVillagePrefabs.h
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
// SandVillagePrefabs.h
|
||||
|
||||
// Declares the prefabs in the group SandVillage
|
||||
|
||||
#include "../Prefab.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern const cPrefab::sDef g_SandVillagePrefabs[];
|
||||
extern const cPrefab::sDef g_SandVillageStartingPrefabs[];
|
||||
extern const size_t g_SandVillagePrefabsCount;
|
||||
extern const size_t g_SandVillageStartingPrefabsCount;
|
430
src/Generating/VillageGen.cpp
Normal file
430
src/Generating/VillageGen.cpp
Normal file
@ -0,0 +1,430 @@
|
||||
|
||||
// VillageGen.cpp
|
||||
|
||||
// Implements the cVillageGen class representing the village generator
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
How village generating works:
|
||||
By descending from a cGridStructGen, a semi-random grid is generated. A village may be generated for each of
|
||||
the grid's cells. Each cell checks the biomes in an entire chunk around it, only generating a village if all
|
||||
biomes are village-friendly. If yes, the entire village structure is built for that cell. If not, the cell
|
||||
is left village-less.
|
||||
|
||||
A village is generated using the regular BFS piece generator. The well piece is used as the starting piece,
|
||||
the roads and houses are then used as the following pieces. Only the houses are read from the prefabs,
|
||||
though, the roads are generated by code and their content is ignored. A special subclass of the cPiecePool
|
||||
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. 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 :
|
||||
public cPrefabPiecePool
|
||||
{
|
||||
typedef cPrefabPiecePool super;
|
||||
public:
|
||||
cVillagePiecePool(
|
||||
const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
|
||||
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
|
||||
) :
|
||||
super(a_PieceDefs, a_NumPieceDefs, a_StartingPieceDefs, a_NumStartingPieceDefs)
|
||||
{
|
||||
// Add the road pieces:
|
||||
for (int len = 27; len < 60; len += 12)
|
||||
{
|
||||
cBlockArea BA;
|
||||
BA.Create(len, 1, 3, cBlockArea::baTypes | cBlockArea::baMetas);
|
||||
BA.Fill(cBlockArea::baTypes | cBlockArea::baMetas, E_BLOCK_GRAVEL, 0);
|
||||
cPrefab * RoadPiece = new cPrefab(BA, 1);
|
||||
RoadPiece->AddConnector(0, 0, 1, BLOCK_FACE_XM, -2);
|
||||
RoadPiece->AddConnector(len - 1, 0, 1, BLOCK_FACE_XP, -2);
|
||||
RoadPiece->SetDefaultWeight(100);
|
||||
|
||||
// Add the road connectors:
|
||||
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 = 7; x < len; x += 12)
|
||||
{
|
||||
RoadPiece->AddConnector(x, 0, 0, BLOCK_FACE_ZM, 1);
|
||||
RoadPiece->AddConnector(x, 0, 2, BLOCK_FACE_ZP, 1);
|
||||
}
|
||||
m_AllPieces.push_back(RoadPiece);
|
||||
m_PiecesByConnector[-2].push_back(RoadPiece);
|
||||
m_PiecesByConnector[1].push_back(RoadPiece);
|
||||
m_PiecesByConnector[2].push_back(RoadPiece);
|
||||
} // for len - roads of varying length
|
||||
}
|
||||
|
||||
|
||||
// cPrefabPiecePool overrides:
|
||||
virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override
|
||||
{
|
||||
// Roads cannot branch T-wise (appending -2 connector to a +2 connector on a 1-high piece):
|
||||
if ((a_ExistingConnector.m_Type == 2) && (a_PlacedPiece.GetDepth() > 0) && (a_PlacedPiece.GetPiece().GetSize().y == 1))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cVillageGen::cVillage :
|
||||
public cGridStructGen::cStructure,
|
||||
protected cPiecePool
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
public:
|
||||
cVillage(
|
||||
int a_Seed,
|
||||
int a_OriginX, int a_OriginZ,
|
||||
int a_MaxRoadDepth,
|
||||
int a_MaxSize,
|
||||
int a_Density,
|
||||
cPiecePool & a_Prefabs,
|
||||
cTerrainHeightGen & a_HeightGen,
|
||||
BLOCKTYPE a_RoadBlock
|
||||
) :
|
||||
super(a_OriginX, a_OriginZ),
|
||||
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)
|
||||
{
|
||||
// Generate the pieces for this village; don't care about the Y coord:
|
||||
cBFSPieceGenerator pg(*this, a_Seed);
|
||||
pg.PlacePieces(a_OriginX, 0, a_OriginZ, a_MaxRoadDepth + 1, m_Pieces);
|
||||
if (m_Pieces.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 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())
|
||||
{
|
||||
int OrigPosY = m_Pieces[0]->GetCoords().y;
|
||||
PlacePieceOnGround(*m_Pieces[0]);
|
||||
int NewPosY = m_Pieces[0]->GetCoords().y;
|
||||
MoveAllDescendants(m_Pieces, 0, NewPosY - OrigPosY);
|
||||
}
|
||||
}
|
||||
|
||||
~cVillage()
|
||||
{
|
||||
cPieceGenerator::FreePieces(m_Pieces);
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Seed for the random functions */
|
||||
int m_Seed;
|
||||
|
||||
/** The noise used as a pseudo-random generator */
|
||||
cNoise m_Noise;
|
||||
|
||||
/** 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 */
|
||||
cPiecePool & m_Prefabs;
|
||||
|
||||
/** The underlying height generator, used for placing the structures on top of the terrain. */
|
||||
cTerrainHeightGen & m_HeightGen;
|
||||
|
||||
/** The village pieces, placed by the generator. */
|
||||
cPlacedPieces m_Pieces;
|
||||
|
||||
/** The block to use for the roads. */
|
||||
BLOCKTYPE m_RoadBlock;
|
||||
|
||||
|
||||
// cGridStructGen::cStructure overrides:
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
|
||||
{
|
||||
// Iterate over all items
|
||||
// Each intersecting prefab is placed on ground, then drawn
|
||||
// Each intersecting road is drawn by replacing top soil blocks with gravel / sandstone blocks
|
||||
cChunkDef::HeightMap HeightMap; // Heightmap for this chunk, used by roads
|
||||
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());
|
||||
if ((*itr)->GetPiece().GetSize().y == 1)
|
||||
{
|
||||
// It's a road, special handling (change top terrain blocks to m_RoadBlock)
|
||||
DrawRoad(a_Chunk, **itr, HeightMap);
|
||||
continue;
|
||||
}
|
||||
if (Prefab.ShouldMoveToGround() && !(*itr)->HasBeenMovedToGround())
|
||||
{
|
||||
PlacePieceOnGround(**itr);
|
||||
}
|
||||
Prefab.Draw(a_Chunk, *itr);
|
||||
} // for itr - m_PlacedPieces[]
|
||||
}
|
||||
|
||||
|
||||
/** Adjusts the Y coord of the given piece so that the piece is on the ground.
|
||||
Ground level is assumed to be represented by the first connector in the piece. */
|
||||
void PlacePieceOnGround(cPlacedPiece & a_Piece)
|
||||
{
|
||||
cPiece::cConnector FirstConnector = a_Piece.GetRotatedConnector(0);
|
||||
int ChunkX, ChunkZ;
|
||||
int BlockX = FirstConnector.m_Pos.x;
|
||||
int BlockZ = FirstConnector.m_Pos.z;
|
||||
int BlockY;
|
||||
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
||||
cChunkDef::HeightMap HeightMap;
|
||||
m_HeightGen.GenHeightMap(ChunkX, ChunkZ, HeightMap);
|
||||
int TerrainHeight = cChunkDef::GetHeight(HeightMap, BlockX, BlockZ);
|
||||
a_Piece.MoveToGroundBy(TerrainHeight - FirstConnector.m_Pos.y + 1);
|
||||
}
|
||||
|
||||
|
||||
/** Draws the road into the chunk.
|
||||
The heightmap is not queried from the heightgen, but is given via parameter, so that it may be queried just
|
||||
once for all roads in a chunk. */
|
||||
void DrawRoad(cChunkDesc & a_Chunk, cPlacedPiece & a_Road, cChunkDef::HeightMap & a_HeightMap)
|
||||
{
|
||||
cCuboid RoadCoords = a_Road.GetHitBox();
|
||||
RoadCoords.Sort();
|
||||
int MinX = std::max(RoadCoords.p1.x - a_Chunk.GetChunkX() * cChunkDef::Width, 0);
|
||||
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);
|
||||
for (int z = MinZ; z <= MaxZ; z++)
|
||||
{
|
||||
for (int x = MinX; x <= MaxX; x++)
|
||||
{
|
||||
a_Chunk.SetBlockType(x, cChunkDef::GetHeight(a_HeightMap, x, z), z, m_RoadBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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 int GetStartingPieceWeight(const cPiece & a_NewPiece) override
|
||||
{
|
||||
return m_Prefabs.GetStartingPieceWeight(a_NewPiece);
|
||||
}
|
||||
|
||||
|
||||
virtual void PiecePlaced(const cPiece & a_Piece) override
|
||||
{
|
||||
m_Prefabs.PiecePlaced(a_Piece);
|
||||
}
|
||||
|
||||
|
||||
virtual void Reset(void) override
|
||||
{
|
||||
m_Prefabs.Reset();
|
||||
}
|
||||
|
||||
|
||||
void MoveAllDescendants(cPlacedPieces & a_PlacedPieces, size_t a_Pivot, int a_HeightDifference)
|
||||
{
|
||||
size_t num = a_PlacedPieces.size();
|
||||
cPlacedPiece * Pivot = a_PlacedPieces[a_Pivot];
|
||||
for (size_t i = a_Pivot + 1; i < num; i++)
|
||||
{
|
||||
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
|
||||
)
|
||||
{
|
||||
a_PlacedPieces[i]->MoveToGroundBy(a_HeightDifference);
|
||||
MoveAllDescendants(a_PlacedPieces, i, a_HeightDifference);
|
||||
}
|
||||
} // for i - a_PlacedPieces[]
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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_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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cGridStructGen::cStructurePtr cVillageGen::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||
{
|
||||
// Generate the biomes for the chunk surrounding the origin:
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(a_OriginX, a_OriginZ, ChunkX, ChunkZ);
|
||||
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 = NULL;
|
||||
BLOCKTYPE RoadBlock = E_BLOCK_GRAVEL;
|
||||
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)];
|
||||
for (size_t i = 0; i < ARRAYCOUNT(Biomes); i++)
|
||||
{
|
||||
switch (Biomes[i])
|
||||
{
|
||||
case biDesert:
|
||||
case biDesertM:
|
||||
{
|
||||
// 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[]
|
||||
|
||||
// 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, Density, *VillagePrefabs, m_HeightGen, RoadBlock));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
57
src/Generating/VillageGen.h
Normal file
57
src/Generating/VillageGen.h
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
// VillageGen.h
|
||||
|
||||
// Declares the cVillageGen class representing the village generator
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GridStructGen.h"
|
||||
#include "PrefabPiecePool.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cVillageGen :
|
||||
public cGridStructGen
|
||||
{
|
||||
typedef cGridStructGen super;
|
||||
public:
|
||||
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:
|
||||
class cVillage; // fwd: VillageGen.cpp
|
||||
|
||||
/** The noise used for generating random numbers */
|
||||
cNoise m_Noise;
|
||||
|
||||
/** Maximum depth of the generator tree*/
|
||||
int m_MaxDepth;
|
||||
|
||||
/** Maximum size, in X/Z blocks, of the village (radius from the origin) */
|
||||
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 */
|
||||
cBiomeGen & m_BiomeGen;
|
||||
|
||||
/** The underlying height generator, used to position the prefabs crossing chunk borders */
|
||||
cTerrainHeightGen & m_HeightGen;
|
||||
|
||||
|
||||
// cGridStructGen overrides:
|
||||
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
@ -234,7 +234,8 @@ void cProtocol172::SendChat(const cCompositeChat & a_Message)
|
||||
|
||||
// Compose the complete Json string to send:
|
||||
Json::Value msg;
|
||||
msg["text"] = cClientHandle::FormatMessageType(m_Client->GetPlayer()->GetWorld()->ShouldUseChatPrefixes(), a_Message.GetMessageType(), a_Message.GetAdditionalMessageTypeData()); // The client crashes without this field being present
|
||||
cWorld * World = m_Client->GetPlayer()->GetWorld();
|
||||
msg["text"] = cClientHandle::FormatMessageType((World == NULL) ? false : World->ShouldUseChatPrefixes(), a_Message.GetMessageType(), a_Message.GetAdditionalMessageTypeData()); // The client crashes without this field being present
|
||||
const cCompositeChat::cParts & Parts = a_Message.GetParts();
|
||||
for (cCompositeChat::cParts::const_iterator itr = Parts.begin(), end = Parts.end(); itr != end; ++itr)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user