summaryrefslogtreecommitdiffstats
path: root/src/Generating/DungeonRoomsFinisher.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Generating/DungeonRoomsFinisher.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp
new file mode 100644
index 000000000..37409d486
--- /dev/null
+++ b/src/Generating/DungeonRoomsFinisher.cpp
@@ -0,0 +1,232 @@
+
+// DungeonRoomsFinisher.cpp
+
+// Declares the cDungeonRoomsFinisher class representing the finisher that generates dungeon rooms
+
+#include "Globals.h"
+#include "DungeonRoomsFinisher.h"
+
+
+
+
+
+/** Height, in blocks, of the internal dungeon room open space. This many air blocks Y-wise. */
+static const int ROOM_HEIGHT = 4;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cDungeonRoom:
+
+class cDungeonRoom :
+ public cGridStructGen::cStructure
+{
+ typedef cGridStructGen::cStructure super;
+
+public:
+
+ cDungeonRoom(
+ int a_GridX, int a_GridZ,
+ int a_OriginX, int a_OriginZ,
+ int a_HalfSizeX, int a_HalfSizeZ,
+ int a_FloorHeight,
+ cNoise & a_Noise
+ ) :
+ super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
+ m_StartX(a_OriginX - a_HalfSizeX),
+ m_EndX(a_OriginX + a_HalfSizeX),
+ m_StartZ(a_OriginZ - a_HalfSizeZ),
+ m_EndZ(a_OriginZ + a_HalfSizeZ),
+ m_FloorHeight(a_FloorHeight),
+ m_Chest1(SelectChestCoords(a_Noise, a_OriginX + 1, a_OriginZ)),
+ m_Chest2(SelectChestCoords(a_Noise, a_OriginX + 2, a_OriginZ))
+ {
+ }
+
+protected:
+
+ // The X range of the room, start inclusive, end exclusive:
+ int m_StartX, m_EndX;
+
+ // The Z range of the room, start inclusive, end exclusive:
+ int m_StartZ, m_EndZ;
+
+ /** The Y coord of the floor of the room */
+ int m_FloorHeight;
+
+ /** The (absolute) coords of the first chest. The Y coord represents the chest's Meta value (facing). */
+ Vector3i m_Chest1;
+
+ /** The (absolute) coords of the second chest. The Y coord represents the chest's Meta value (facing). */
+ Vector3i m_Chest2;
+
+
+
+ /** Selects the coords for the chest, using the noise and coords provided.
+ Assumes that the room XZ ranges are already assigned. */
+ Vector3i SelectChestCoords(cNoise & a_Noise, int a_X, int a_Z)
+ {
+ // Pick a coord next to the wall:
+ int rnd = a_Noise.IntNoise2DInt(a_X, a_Z) / 7;
+ int SizeX = m_EndX - m_StartX - 1;
+ int SizeZ = m_EndZ - m_StartZ - 1;
+ rnd = rnd % (2 * SizeX + 2 * SizeZ);
+
+ if (rnd < SizeX)
+ {
+ // Return a coord on the ZM side of the room:
+ return Vector3i(m_StartX + rnd + 1, E_META_CHEST_FACING_ZP, m_StartZ + 1);
+ }
+ rnd -= SizeX;
+ if (rnd < SizeZ)
+ {
+ // Return a coord on the XP side of the room:
+ return Vector3i(m_EndX - 1, E_META_CHEST_FACING_XM, m_StartZ + rnd + 1);
+ }
+ rnd -= SizeZ;
+ if (rnd < SizeX)
+ {
+ // Return a coord on the ZP side of the room:
+ return Vector3i(m_StartX + rnd + 1, E_META_CHEST_FACING_ZM, m_StartZ + 1);
+ }
+ rnd -= SizeX;
+ // Return a coord on the XM side of the room:
+ return Vector3i(m_StartX + 1, E_META_CHEST_FACING_XP, m_StartZ + rnd + 1);
+ }
+
+
+
+ /** Fills the specified area of blocks in the chunk with the specified blocktype if they are one of the overwritten block types.
+ The coords are absolute, start coords are inclusive, end coords are exclusive. */
+ void ReplaceCuboid(cChunkDesc & a_ChunkDesc, int a_StartX, int a_StartY, int a_StartZ, int a_EndX, int a_EndY, int a_EndZ, BLOCKTYPE a_DstBlockType)
+ {
+ int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width - 1);
+ int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width - 1);
+ int RelEndX = Clamp(a_EndX - BlockX, 0, cChunkDef::Width);
+ int RelEndZ = Clamp(a_EndZ - BlockZ, 0, cChunkDef::Width);
+ for (int y = a_StartY; y < a_EndY; y++)
+ {
+ for (int z = RelStartZ; z < RelEndZ; z++)
+ {
+ for (int x = RelStartX; x < RelEndX; x++)
+ {
+ switch (a_ChunkDesc.GetBlockType(x, y, z))
+ {
+ case E_BLOCK_STONE:
+ case E_BLOCK_DIRT:
+ case E_BLOCK_GRASS:
+ case E_BLOCK_GRAVEL:
+ case E_BLOCK_SAND:
+ {
+ a_ChunkDesc.SetBlockType(x, y, z, a_DstBlockType);
+ break;
+ }
+ } // switch (GetBlockType)
+ } // for x
+ } // for z
+ } // for z
+ }
+
+
+
+ /** Tries to place a chest at the specified (absolute) coords.
+ Does nothing if the coords are outside the chunk. */
+ void TryPlaceChest(cChunkDesc & a_ChunkDesc, const Vector3i & a_Chest)
+ {
+ int RelX = a_Chest.x - a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int RelZ = a_Chest.z - a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ if (
+ (RelX < 0) || (RelX >= cChunkDef::Width) || // The X coord is not in this chunk
+ (RelZ < 0) || (RelZ >= cChunkDef::Width) // The Z coord is not in this chunk
+ )
+ {
+ return;
+ }
+ a_ChunkDesc.SetBlockTypeMeta(RelX, m_FloorHeight + 1, RelZ, E_BLOCK_CHEST, (NIBBLETYPE)a_Chest.y);
+
+ // TODO: Fill the chest with random loot
+ }
+
+
+
+ // cGridStructGen::cStructure override:
+ virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override
+ {
+ if (
+ (m_EndX <= a_ChunkDesc.GetChunkX() * cChunkDef::Width) ||
+ (m_StartX >= a_ChunkDesc.GetChunkX() * cChunkDef::Width + cChunkDef::Width) ||
+ (m_EndZ <= a_ChunkDesc.GetChunkZ() * cChunkDef::Width) ||
+ (m_StartZ >= a_ChunkDesc.GetChunkZ() * cChunkDef::Width + cChunkDef::Width)
+ )
+ {
+ // The chunk is not intersecting the room at all, bail out
+ return;
+ }
+ int b = m_FloorHeight + 1; // Bottom
+ int t = m_FloorHeight + 1 + ROOM_HEIGHT; // Top
+ ReplaceCuboid(a_ChunkDesc, m_StartX, m_FloorHeight, m_StartZ, m_EndX + 1, b, m_EndZ + 1, E_BLOCK_MOSSY_COBBLESTONE); // Floor
+ ReplaceCuboid(a_ChunkDesc, m_StartX + 1, b, m_StartZ + 1, m_EndX, t, m_EndZ, E_BLOCK_AIR); // Insides
+ ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_StartZ, m_StartX + 1, t, m_EndZ, E_BLOCK_COBBLESTONE); // XM wall
+ ReplaceCuboid(a_ChunkDesc, m_EndX, b, m_StartZ, m_EndX + 1, t, m_EndZ, E_BLOCK_COBBLESTONE); // XP wall
+ ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_StartZ, m_EndX + 1, t, m_StartZ + 1, E_BLOCK_COBBLESTONE); // ZM wall
+ ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_EndZ, m_EndX + 1, t, m_EndZ + 1, E_BLOCK_COBBLESTONE); // ZP wall
+ TryPlaceChest(a_ChunkDesc, m_Chest1);
+ TryPlaceChest(a_ChunkDesc, m_Chest2);
+ }
+} ;
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cDungeonRoomsFinisher:
+
+cDungeonRoomsFinisher::cDungeonRoomsFinisher(cTerrainHeightGen & a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize) :
+ super(a_Seed + 100, a_GridSize, a_GridSize, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 1024),
+ m_HeightGen(a_HeightGen),
+ m_MaxHalfSize((a_MaxSize + 1) / 2),
+ m_MinHalfSize((a_MinSize + 1) / 2)
+{
+ // Normalize the min and max size:
+ if (m_MinHalfSize > m_MaxHalfSize)
+ {
+ std::swap(m_MinHalfSize, m_MaxHalfSize);
+ }
+}
+
+
+
+
+
+
+cDungeonRoomsFinisher::cStructurePtr cDungeonRoomsFinisher::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
+{
+ // Select a random room size in each direction:
+ int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7;
+ int HalfSizeX = m_MinHalfSize + (rnd % (m_MaxHalfSize - m_MinHalfSize + 1));
+ rnd = rnd / 32;
+ int HalfSizeZ = m_MinHalfSize + (rnd % (m_MaxHalfSize - m_MinHalfSize + 1));
+ rnd = rnd / 32;
+
+ // Select a random floor height for the room, based on the height generator:
+ int ChunkX, ChunkZ;
+ int RelX = a_OriginX, RelY = 0, RelZ = a_OriginZ;
+ cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ);
+ cChunkDef::HeightMap HeightMap;
+ m_HeightGen.GenHeightMap(ChunkX, ChunkZ, HeightMap);
+ int Height = cChunkDef::GetHeight(HeightMap, RelX, RelZ); // Max room height at {a_OriginX, a_OriginZ}
+ Height = 10 + (rnd % std::max(1, (Height - 14)));
+
+ // Create the dungeon room descriptor:
+ return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, Height, m_Noise));
+}
+
+
+
+